diff --git a/packages/agent-runtime/src/claude-code/adapter.test.ts b/packages/agent-runtime/src/claude-code/adapter.test.ts index 9fef6c6c7e..cc31e368b4 100644 --- a/packages/agent-runtime/src/claude-code/adapter.test.ts +++ b/packages/agent-runtime/src/claude-code/adapter.test.ts @@ -5632,4 +5632,24 @@ describe("claude-code provider adapter", () => { const events = adapter.translateEvent(loadFixture("system-init.json")); expect(events).toMatchObject([]); }); + + it("ignores Claude command lifecycle events", () => { + const adapter = createClaudeCodeProviderAdapter(); + const events = adapter.translateEvent({ + jsonrpc: "2.0", + method: "sdk/message", + params: { + threadId: "thread-1", + message: { + type: "command_lifecycle", + command_uuid: "command-1", + state: "started", + uuid: "message-1", + session_id: "session-1", + }, + }, + }); + + expect(events).toEqual([]); + }); }); diff --git a/packages/agent-runtime/src/claude-code/visibility.ts b/packages/agent-runtime/src/claude-code/visibility.ts index d6301cf2cc..0a9a37eb84 100644 --- a/packages/agent-runtime/src/claude-code/visibility.ts +++ b/packages/agent-runtime/src/claude-code/visibility.ts @@ -94,6 +94,10 @@ interface ClaudeUnknownSdkRawEvent { sdkType?: string; } +interface ClaudeCommandLifecycleRawEvent { + kind: "sdk/command_lifecycle"; +} + interface ClaudeAssistantRawEvent { contentTypes: ClaudeMessageContentType[]; kind: "sdk/assistant"; @@ -151,6 +155,7 @@ interface ClaudeSimpleStreamRawEvent { type ClaudeRawEvent = | ClaudeAssistantRawEvent + | ClaudeCommandLifecycleRawEvent | ClaudeErrorRawEvent | ClaudeNonSdkRawEvent | ClaudeRateLimitRawEvent @@ -298,6 +303,9 @@ function parseClaudeRawEvent(event: JsonRpcMessage): ClaudeRawEvent { ), }; + case "command_lifecycle": + return { kind: "sdk/command_lifecycle" }; + case "rate_limit_event": return { kind: "sdk/rate_limit_event" }; @@ -423,6 +431,11 @@ function describeParsedClaudeRawEvent( return { kind, coverage: "unknown" }; } + // Internal command queue telemetry used by remote Claude surfaces for + // lifecycle acknowledgements. It has no transcript or turn semantics. + case "sdk/command_lifecycle": + return { kind: "sdk/command_lifecycle", coverage: "noise" }; + case "sdk/user": { const kind = toClaudeMessageKind("sdk/user", event.contentTypes); if (kind === "sdk/user:text") { diff --git a/packages/agent-runtime/src/provider-visibility.test.ts b/packages/agent-runtime/src/provider-visibility.test.ts index 8f1c8d32df..2908889d93 100644 --- a/packages/agent-runtime/src/provider-visibility.test.ts +++ b/packages/agent-runtime/src/provider-visibility.test.ts @@ -93,6 +93,28 @@ describe("provider visibility raw events", () => { }); }); + it("classifies Claude command lifecycle events as noise", () => { + expect( + claudeCodeVisibilityMetadata.describeRawEvent({ + jsonrpc: "2.0", + method: "sdk/message", + params: { + threadId: "thread-1", + message: { + type: "command_lifecycle", + command_uuid: "command-1", + state: "started", + uuid: "message-1", + session_id: "session-1", + }, + }, + } satisfies JsonRpcMessage), + ).toEqual({ + kind: "sdk/command_lifecycle", + coverage: "noise", + }); + }); + it("classifies Claude thinking token system events as noise", () => { expect( claudeCodeVisibilityMetadata.describeRawEvent({