feat(engine,sdk-rust): rename telemetry harness → origin_actor#184
Conversation
Replaces the CLI-centric telemetry `harness` with `origin_actor`, a UA-style
path `{app}/{type}[/{name}]` (e.g. agent-relay-cli/agent/claude-code,
pear/user/send-message-box). Per cloud/plans/origin-actor.md.
- engine: `X-Relaycast-Harness`/`?harness=` -> `X-Relaycast-Origin-Actor`/
`?origin_actor=`; `extractHarness`->`extractOriginActor`; the `harness`
request-context var + emitted `harness` telemetry property + the realtime
`UpgradeRequest` field -> `origin_actor`/`originActor`. Max length 120->128
for the longer path form. The regex already permits `/`.
- sdk-rust: `harness.rs`->`origin_actor.rs`; `with_harness`->`with_origin_actor`;
header + WS query renamed; field/getter renamed.
The DOMAIN harness (harness-emitted session events: `harness.${type}`,
`POST /v1/agents/:name/events`, the session_events table) is untouched — only
the telemetry/origin-attribution harness is renamed.
No back-compat aliases (telemetry data intentionally breaks). origin_surface
removal + the JS/python SDK + cloud/relay producer-consumer wiring follow in
separate PRs.
Engine: tsc clean, origin (15) + lib (20) tests pass.
sdk-rust: 77 tests pass, clippy + fmt clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
Warning Review limit reached
More reviews will be available in 53 minutes and 37 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughReplace the "harness" request origin identifier with "origin actor" across engine and Rust SDK: new extraction/validation, propagate originActor through middleware/context/telemetry and WS upgrade, update Rust HTTP/WS clients and RelayCast options, refresh parity tests, and convert persisted workspace state keys to camelCase. ChangesOrigin Actor Identifier Refactoring
🎯 3 (Moderate) | ⏱️ ~25 minutes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 293dd0ba3c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const raw = | ||
| request.headers.get(HARNESS_HEADER) ?? | ||
| new URL(request.url).searchParams.get("harness"); | ||
| if (!raw) return UNKNOWN_HARNESS; | ||
| request.headers.get(ORIGIN_ACTOR_HEADER) ?? | ||
| new URL(request.url).searchParams.get(ORIGIN_ACTOR_QUERY); |
There was a problem hiding this comment.
Accept the current SDK header until clients migrate
When this engine change is released before the TypeScript SDK/docs follow-up, requests created by the in-repo SDK still send X-Relaycast-Harness and WS harness (checked packages/sdk-typescript/src/origin.ts and client.ts), and openapi.yaml still tells clients to use those names. Because extraction now only reads X-Relaycast-Origin-Actor/origin_actor, those clients’ attribution is silently recorded as unknown; either update the SDK/schema in the same release or keep a temporary alias for the still-published contract.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/engine/src/lib/origin.ts (1)
22-23: ⚡ Quick winUse a zod schema for origin-actor validation instead of ad-hoc checks.
This logic currently duplicates trim/empty/regex/max/lowercase manually; using a single schema keeps the contract centralized and aligned with repo standards.
As per coding guidelines, "Prefer zod schemas for validation instead of ad-hoc manual checks."
♻️ Suggested refactor
+import { z } from "zod"; + const ORIGIN_ACTOR_MAX_LENGTH = 128; const ORIGIN_ACTOR_ALLOWED = /^[a-z0-9 ._\-/():=;,+]+$/i; + +const originActorSchema = z + .string() + .trim() + .min(1) + .max(ORIGIN_ACTOR_MAX_LENGTH) + .regex(ORIGIN_ACTOR_ALLOWED) + .transform((value) => value.toLowerCase()); export function extractOriginActor(request: Request): string { const raw = request.headers.get(ORIGIN_ACTOR_HEADER) ?? new URL(request.url).searchParams.get(ORIGIN_ACTOR_QUERY); - if (!raw) return UNKNOWN_ORIGIN_ACTOR; - - const trimmed = raw.trim(); - if (!trimmed) return UNKNOWN_ORIGIN_ACTOR; - if (!ORIGIN_ACTOR_ALLOWED.test(trimmed)) return UNKNOWN_ORIGIN_ACTOR; - - return trimmed.slice(0, ORIGIN_ACTOR_MAX_LENGTH).toLowerCase(); + if (!raw) return UNKNOWN_ORIGIN_ACTOR; + const parsed = originActorSchema.safeParse(raw); + return parsed.success ? parsed.data : UNKNOWN_ORIGIN_ACTOR; }Also applies to: 32-33, 49-59
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/engine/src/lib/origin.ts` around lines 22 - 23, Replace the ad-hoc origin-actor validation logic with a single zod schema (e.g., export const originActorSchema = z.string().trim().min(1).max(ORIGIN_ACTOR_MAX_LENGTH).regex(/.../).transform(s => s.toLowerCase())) in this module and use originActorSchema.safeParse/parse wherever the current manual checks occur (the blocks around ORIGIN_ACTOR_MAX_LENGTH and the checks at the ranges you noted). Ensure the schema preserves the existing rules (trim, non-empty, regex, max length, lowercase) and update the functions that perform validation to call originActorSchema.safeParse and return/throw the same error shape as before.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/engine/src/lib/origin.ts`:
- Around line 22-23: Replace the ad-hoc origin-actor validation logic with a
single zod schema (e.g., export const originActorSchema =
z.string().trim().min(1).max(ORIGIN_ACTOR_MAX_LENGTH).regex(/.../).transform(s
=> s.toLowerCase())) in this module and use originActorSchema.safeParse/parse
wherever the current manual checks occur (the blocks around
ORIGIN_ACTOR_MAX_LENGTH and the checks at the ranges you noted). Ensure the
schema preserves the existing rules (trim, non-empty, regex, max length,
lowercase) and update the functions that perform validation to call
originActorSchema.safeParse and return/throw the same error shape as before.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: fd4046fa-7169-4508-aa84-af4d9613bda5
📒 Files selected for processing (15)
memory/workspace/.relay/state.jsonpackages/engine/src/engine.tspackages/engine/src/env.tspackages/engine/src/lib/__tests__/origin.test.tspackages/engine/src/lib/origin.tspackages/engine/src/lib/serverTelemetry.tspackages/engine/src/middleware/logger.tspackages/engine/src/ports/realtime.tspackages/sdk-rust/src/agent.rspackages/sdk-rust/src/client.rspackages/sdk-rust/src/lib.rspackages/sdk-rust/src/origin_actor.rspackages/sdk-rust/src/relay.rspackages/sdk-rust/src/ws.rspackages/sdk-rust/tests/parity.rs
The name segment optionally carries harness version + model as
{harness}@{version}-{model} (e.g. claude-code@2.3.1-opus4.8) so cloud can
derive origin_actor_name/_version/_model. Add '@' to the allowed charset
(engine regex + sdk-rust is_allowed) and update the test fixtures from the
stale pre-path UA values (claude-code/2.3 …) to real path examples.
See cloud/plans/origin-actor.md (name sub-format).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The broker writes memory/workspace/.relay/state.json on every run, which churned on PR branches (e.g. the "pr-reviewer fixes for #184" noise commits). Ignore **/.relay/ and untrack the committed state file. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PR 1 of the
origin_actorrollout — plan:cloud/plans/origin-actor.md(cloud#2062).Replaces the CLI-centric telemetry
harnesswithorigin_actor— a UA-style path{app}/{type}[/{name}]:Changes
X-Relaycast-Harness/?harness=→X-Relaycast-Origin-Actor/?origin_actor=;extractHarness→extractOriginActor; the request-context var, the emittedharnesstelemetry property, and the realtimeUpgradeRequestfield →origin_actor/originActor. Max length 120→128 for the longer path; the validation regex already permits/.harness.rs→origin_actor.rs;with_harness→with_origin_actor; header + WS query renamed; field/getter renamed.Guardrail: only the telemetry harness renames
harnesswas overloaded. The domain harness — harness-emitted session events (harness.${type},POST /v1/agents/:name/events, thesession_eventstable, migration0010_actions_and_harness.sql) — is untouched. Only the telemetry/origin-attribution harness is renamed.Breaking
No back-compat aliases — telemetry data intentionally breaks (per plan).
Verification
tscclean;origin.test.ts(15) + lib tests (20) pass.cargo test77 pass; clippy +fmt --checkclean.Follow-ups (separate PRs)
UpgradeRequest.originActorport rename → the cloud adapter that implements it (lands with cloud#… when it bumps the engine).origin_surface(types + sdk-rust/sdk-js/sdk-python + mcp).origin_actor→ PostHogorigin_app/origin_actor_type/origin_actor_name.🤖 Generated with Claude Code