From b38a16f5f69509c57ceb4b6289e4682c5e17ef70 Mon Sep 17 00:00:00 2001 From: Arul Sharma <31745423+arul28@users.noreply.github.com> Date: Wed, 2 Sep 2026 03:25:15 -0400 Subject: [PATCH] feat(chat): pin Claude Agent SDK 0.3.258 and record new result fields Public ADE currently ships CLI 2.1.220 while advertising Fable 5.1, which needs CLI >= 2.1.257. Pin 0.3.258 (CLI 2.1.258) and persist the additive SDK fields without changing usage totals or UI. Co-authored-by: Cursor --- apps/ade-cli/package-lock.json | 142 ++++++++--------- apps/ade-cli/package.json | 2 +- apps/ade-cli/src/bootstrap.ts | 6 + .../tools/toolsManifest.generated.json | 30 ++-- apps/desktop/package-lock.json | 81 +++++----- apps/desktop/package.json | 2 +- apps/desktop/src/main/main.ts | 6 + .../analytics/agentTurnProductAnalytics.ts | 28 ++++ .../analytics/productAnalyticsPolicy.ts | 1 + .../analytics/productAnalyticsService.test.ts | 76 +++++++++ .../services/chat/agentChatService.test.ts | 149 +++++++++++++++++- .../main/services/chat/agentChatService.ts | 133 +++++++++++++++- apps/desktop/src/shared/types/chat.ts | 15 ++ docs/features/chat/README.md | 8 +- .../agent-tools-cache.md | 2 +- 15 files changed, 531 insertions(+), 150 deletions(-) diff --git a/apps/ade-cli/package-lock.json b/apps/ade-cli/package-lock.json index 20184d6b7..71ead3631 100644 --- a/apps/ade-cli/package-lock.json +++ b/apps/ade-cli/package-lock.json @@ -8,7 +8,7 @@ "name": "ade-cli", "version": "0.0.0", "dependencies": { - "@anthropic-ai/claude-agent-sdk": "0.3.220", + "@anthropic-ai/claude-agent-sdk": "0.3.258", "@cursor/sdk": "1.0.27", "@factory/droid-sdk": "0.2.0", "@linear/sdk": "^84.0.0", @@ -94,22 +94,22 @@ } }, "node_modules/@anthropic-ai/claude-agent-sdk": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.220.tgz", - "integrity": "sha512-glc7SdwPkOkLw8oxwLo9PKTdLJGqW/PIR4urWXFoRtX9YllwozsEVc5Tc1+EvLSkfrsxPJqQWqOgpjUOQXf1oA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.258.tgz", + "integrity": "sha512-RxJ5fSPCGCxX5qO/b4IPXhldvtLHeYBAzTUJ4eOzO+gTrepZQSDmwSlQD6nnoEquKGJzOMHCjhdEtBfDjbDWUg==", "license": "SEE LICENSE IN README.md", "engines": { "node": ">=18.0.0" }, "optionalDependencies": { - "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.220", - "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.220", - "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.220" + "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.258", + "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.258", + "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.258" }, "peerDependencies": { "@anthropic-ai/sdk": ">=0.93.0", @@ -118,9 +118,9 @@ } }, "node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.220.tgz", - "integrity": "sha512-7VxlbEosK7DODiOnsjoVd0DSJzbnaPrM2jelMHI0y8zx1UnLS3WC6EFUXbvy74F2sXqEznh2tzn7EKWInaRN6Q==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.258.tgz", + "integrity": "sha512-Hrhzc9WVGSid+DghdTcpVr/8fyXnTD6KeSlDpKx6Wru47J/Nq7RTYiZJt+cex+O2ehaHMEcuYEgoqJ3K/X9NlA==", "cpu": [ "arm64" ], @@ -131,9 +131,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-darwin-x64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.220.tgz", - "integrity": "sha512-X9RwDsSmbF6ultKZroaip+DL8WRgC64gHbrAwrRlAFSPNZV7zmJyP2ur8rW7KrxqmtuehdMMkw8+SAC/6hD2PA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.258.tgz", + "integrity": "sha512-AVqxGX4988J5cS+TMqIzH85+sbsLhJu5Ou9TIALcO/v2Z9ze8GK4vX2ydAYvU/SRnjTvEaiITX+Xcm5afP1IbQ==", "cpu": [ "x64" ], @@ -144,9 +144,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.220.tgz", - "integrity": "sha512-WkROPwWskqhKR9XgnmseHQ6rLi9zM9qt57IWoToIjL/eXOqDWipp7JXZ1L5ud+LrA42dunHPZfBwD/vXZ+A7LA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.258.tgz", + "integrity": "sha512-Jj3K1Ip7WpyMouZCjd7kgV3KswUBF62WAnyG0iaYvKZJvXgYKbIAkjcQ2F2Rx5ZuRUNWAVncE9LeHmdIdx78VQ==", "cpu": [ "arm64" ], @@ -157,9 +157,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64-musl": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.220.tgz", - "integrity": "sha512-OHoZOZ8Cf2TBr6oXIXPwyvUxj9jrq2w8E4poA8dMpacXszcPSPiCQCMuuOh4aWJzfeJE1+TtWxhKMVb2csXyZQ==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.258.tgz", + "integrity": "sha512-I/BLt2vdvqK2B2px526U1lw7Rv+SI+Ld22+wLwu8gLRQk5SYhSW9dmMYEO+GCeF7vQzfzJvMQ4IzbbY+aSGACg==", "cpu": [ "arm64" ], @@ -170,9 +170,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.220.tgz", - "integrity": "sha512-tkTJFnpR9VifvWX2fmkCAPkT6+8Wk/gVu8B5jsVekKZPiZoWRHmMXO30BnZn+f0TZhgYP+82PSX3S8crH1kn+w==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.258.tgz", + "integrity": "sha512-2MJeFVJM/3xwZASP3yn2OuQ9RHIoS30DC/B7oG1XPYcbToPLH4QIfCPLWbSQfqCdp+NEBupLMM9BWpDz4s8Q0g==", "cpu": [ "x64" ], @@ -183,9 +183,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64-musl": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.220.tgz", - "integrity": "sha512-K+FWj+LcGhC1Z7wqeWoLxm1iemcba5xKpLLFVwYm4V6HyMx3ruYd/2r2TiQtjT+JWeNFWIys0ScHiItR6vWAiA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.258.tgz", + "integrity": "sha512-sM7GzRyrOpFhwMn2Ng8nLiWK6cc04uCEu3Zh9mrJS2r3iQu1TryHKoPTjc2Ip0N75sHmwhNodgoRs8NtG1Gkkw==", "cpu": [ "x64" ], @@ -196,9 +196,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-win32-arm64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.220.tgz", - "integrity": "sha512-rIwgq0UwQExWl6KrHUyC4w5KwpL9l6nd95aUTx6RitexaAuEw//xtfTVLnuE4hDDQZFkzEwpdKc3nxDWoGcUbA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.258.tgz", + "integrity": "sha512-n/Vf6oXAo9EZVSSM5+9d+8dFrUrX9cbgSHK/1njkvykWAN5xsfBbikJYqwhbW84GCYkpXYM+gGNZe23h0fHldw==", "cpu": [ "arm64" ], @@ -209,9 +209,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-win32-x64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.220.tgz", - "integrity": "sha512-MuOuXhbr66HlGaWXD2f3w0k2PsvmnbkwcUZ0dAe2poFLdl72GC2dapwwOBefxm9QmoNqk9+jmv/dSKGOVWyvLw==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.258.tgz", + "integrity": "sha512-UDbXE6n37ZMUogVVYEWX901NNmbyXUv1VvGYN/vfOiIWKUJXCAypam71dBlYFhlAhVX28qCd64w+pTZDYQfYQA==", "cpu": [ "x64" ], @@ -5352,66 +5352,66 @@ } }, "@anthropic-ai/claude-agent-sdk": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.220.tgz", - "integrity": "sha512-glc7SdwPkOkLw8oxwLo9PKTdLJGqW/PIR4urWXFoRtX9YllwozsEVc5Tc1+EvLSkfrsxPJqQWqOgpjUOQXf1oA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.258.tgz", + "integrity": "sha512-RxJ5fSPCGCxX5qO/b4IPXhldvtLHeYBAzTUJ4eOzO+gTrepZQSDmwSlQD6nnoEquKGJzOMHCjhdEtBfDjbDWUg==", "requires": { - "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.220", - "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.220", - "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.220" + "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.258", + "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.258", + "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.258" } }, "@anthropic-ai/claude-agent-sdk-darwin-arm64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.220.tgz", - "integrity": "sha512-7VxlbEosK7DODiOnsjoVd0DSJzbnaPrM2jelMHI0y8zx1UnLS3WC6EFUXbvy74F2sXqEznh2tzn7EKWInaRN6Q==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.258.tgz", + "integrity": "sha512-Hrhzc9WVGSid+DghdTcpVr/8fyXnTD6KeSlDpKx6Wru47J/Nq7RTYiZJt+cex+O2ehaHMEcuYEgoqJ3K/X9NlA==", "optional": true }, "@anthropic-ai/claude-agent-sdk-darwin-x64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.220.tgz", - "integrity": "sha512-X9RwDsSmbF6ultKZroaip+DL8WRgC64gHbrAwrRlAFSPNZV7zmJyP2ur8rW7KrxqmtuehdMMkw8+SAC/6hD2PA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.258.tgz", + "integrity": "sha512-AVqxGX4988J5cS+TMqIzH85+sbsLhJu5Ou9TIALcO/v2Z9ze8GK4vX2ydAYvU/SRnjTvEaiITX+Xcm5afP1IbQ==", "optional": true }, "@anthropic-ai/claude-agent-sdk-linux-arm64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.220.tgz", - "integrity": "sha512-WkROPwWskqhKR9XgnmseHQ6rLi9zM9qt57IWoToIjL/eXOqDWipp7JXZ1L5ud+LrA42dunHPZfBwD/vXZ+A7LA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.258.tgz", + "integrity": "sha512-Jj3K1Ip7WpyMouZCjd7kgV3KswUBF62WAnyG0iaYvKZJvXgYKbIAkjcQ2F2Rx5ZuRUNWAVncE9LeHmdIdx78VQ==", "optional": true }, "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.220.tgz", - "integrity": "sha512-OHoZOZ8Cf2TBr6oXIXPwyvUxj9jrq2w8E4poA8dMpacXszcPSPiCQCMuuOh4aWJzfeJE1+TtWxhKMVb2csXyZQ==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.258.tgz", + "integrity": "sha512-I/BLt2vdvqK2B2px526U1lw7Rv+SI+Ld22+wLwu8gLRQk5SYhSW9dmMYEO+GCeF7vQzfzJvMQ4IzbbY+aSGACg==", "optional": true }, "@anthropic-ai/claude-agent-sdk-linux-x64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.220.tgz", - "integrity": "sha512-tkTJFnpR9VifvWX2fmkCAPkT6+8Wk/gVu8B5jsVekKZPiZoWRHmMXO30BnZn+f0TZhgYP+82PSX3S8crH1kn+w==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.258.tgz", + "integrity": "sha512-2MJeFVJM/3xwZASP3yn2OuQ9RHIoS30DC/B7oG1XPYcbToPLH4QIfCPLWbSQfqCdp+NEBupLMM9BWpDz4s8Q0g==", "optional": true }, "@anthropic-ai/claude-agent-sdk-linux-x64-musl": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.220.tgz", - "integrity": "sha512-K+FWj+LcGhC1Z7wqeWoLxm1iemcba5xKpLLFVwYm4V6HyMx3ruYd/2r2TiQtjT+JWeNFWIys0ScHiItR6vWAiA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.258.tgz", + "integrity": "sha512-sM7GzRyrOpFhwMn2Ng8nLiWK6cc04uCEu3Zh9mrJS2r3iQu1TryHKoPTjc2Ip0N75sHmwhNodgoRs8NtG1Gkkw==", "optional": true }, "@anthropic-ai/claude-agent-sdk-win32-arm64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.220.tgz", - "integrity": "sha512-rIwgq0UwQExWl6KrHUyC4w5KwpL9l6nd95aUTx6RitexaAuEw//xtfTVLnuE4hDDQZFkzEwpdKc3nxDWoGcUbA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.258.tgz", + "integrity": "sha512-n/Vf6oXAo9EZVSSM5+9d+8dFrUrX9cbgSHK/1njkvykWAN5xsfBbikJYqwhbW84GCYkpXYM+gGNZe23h0fHldw==", "optional": true }, "@anthropic-ai/claude-agent-sdk-win32-x64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.220.tgz", - "integrity": "sha512-MuOuXhbr66HlGaWXD2f3w0k2PsvmnbkwcUZ0dAe2poFLdl72GC2dapwwOBefxm9QmoNqk9+jmv/dSKGOVWyvLw==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.258.tgz", + "integrity": "sha512-UDbXE6n37ZMUogVVYEWX901NNmbyXUv1VvGYN/vfOiIWKUJXCAypam71dBlYFhlAhVX28qCd64w+pTZDYQfYQA==", "optional": true }, "@anthropic-ai/sdk": { diff --git a/apps/ade-cli/package.json b/apps/ade-cli/package.json index 946927aed..72cf656d6 100644 --- a/apps/ade-cli/package.json +++ b/apps/ade-cli/package.json @@ -26,7 +26,7 @@ "test": "vitest run" }, "dependencies": { - "@anthropic-ai/claude-agent-sdk": "0.3.220", + "@anthropic-ai/claude-agent-sdk": "0.3.258", "@cursor/sdk": "1.0.27", "@factory/droid-sdk": "0.2.0", "@linear/sdk": "^84.0.0", diff --git a/apps/ade-cli/src/bootstrap.ts b/apps/ade-cli/src/bootstrap.ts index ad25c9693..ce66574d3 100644 --- a/apps/ade-cli/src/bootstrap.ts +++ b/apps/ade-cli/src/bootstrap.ts @@ -137,6 +137,7 @@ import { captureAgentTurnSettledAnalytics, captureChatAutoResumeAnalytics, captureChatMentionsExpandedAnalytics, + captureClaudeHooksIgnoredAnalytics, captureSessionMetadataRegeneratedAnalytics, } from "../../desktop/src/main/services/analytics/agentTurnProductAnalytics"; import { createSessionDeltaService } from "../../desktop/src/main/services/sessions/sessionDeltaService"; @@ -1442,6 +1443,11 @@ export async function createAdeRuntime(args: { projectId, event, }), + onClaudeHooksIgnored: (event) => captureClaudeHooksIgnoredAnalytics({ + analytics: productAnalyticsService, + projectId, + event, + }), onChatMentionsExpanded: (event) => captureChatMentionsExpandedAnalytics({ analytics: productAnalyticsService, projectId, diff --git a/apps/ade-cli/src/services/tools/toolsManifest.generated.json b/apps/ade-cli/src/services/tools/toolsManifest.generated.json index 9ac3a4fe8..de22781b8 100644 --- a/apps/ade-cli/src/services/tools/toolsManifest.generated.json +++ b/apps/ade-cli/src/services/tools/toolsManifest.generated.json @@ -54,33 +54,33 @@ "targets": { "darwin-arm64": { "package": "@anthropic-ai/claude-agent-sdk-darwin-arm64", - "version": "0.3.220", - "tarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.220.tgz", - "integrity": "sha512-7VxlbEosK7DODiOnsjoVd0DSJzbnaPrM2jelMHI0y8zx1UnLS3WC6EFUXbvy74F2sXqEznh2tzn7EKWInaRN6Q==" + "version": "0.3.258", + "tarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.258.tgz", + "integrity": "sha512-Hrhzc9WVGSid+DghdTcpVr/8fyXnTD6KeSlDpKx6Wru47J/Nq7RTYiZJt+cex+O2ehaHMEcuYEgoqJ3K/X9NlA==" }, "darwin-x64": { "package": "@anthropic-ai/claude-agent-sdk-darwin-x64", - "version": "0.3.220", - "tarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.220.tgz", - "integrity": "sha512-X9RwDsSmbF6ultKZroaip+DL8WRgC64gHbrAwrRlAFSPNZV7zmJyP2ur8rW7KrxqmtuehdMMkw8+SAC/6hD2PA==" + "version": "0.3.258", + "tarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.258.tgz", + "integrity": "sha512-AVqxGX4988J5cS+TMqIzH85+sbsLhJu5Ou9TIALcO/v2Z9ze8GK4vX2ydAYvU/SRnjTvEaiITX+Xcm5afP1IbQ==" }, "linux-arm64": { "package": "@anthropic-ai/claude-agent-sdk-linux-arm64", - "version": "0.3.220", - "tarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.220.tgz", - "integrity": "sha512-WkROPwWskqhKR9XgnmseHQ6rLi9zM9qt57IWoToIjL/eXOqDWipp7JXZ1L5ud+LrA42dunHPZfBwD/vXZ+A7LA==" + "version": "0.3.258", + "tarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.258.tgz", + "integrity": "sha512-Jj3K1Ip7WpyMouZCjd7kgV3KswUBF62WAnyG0iaYvKZJvXgYKbIAkjcQ2F2Rx5ZuRUNWAVncE9LeHmdIdx78VQ==" }, "linux-x64": { "package": "@anthropic-ai/claude-agent-sdk-linux-x64", - "version": "0.3.220", - "tarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.220.tgz", - "integrity": "sha512-tkTJFnpR9VifvWX2fmkCAPkT6+8Wk/gVu8B5jsVekKZPiZoWRHmMXO30BnZn+f0TZhgYP+82PSX3S8crH1kn+w==" + "version": "0.3.258", + "tarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.258.tgz", + "integrity": "sha512-2MJeFVJM/3xwZASP3yn2OuQ9RHIoS30DC/B7oG1XPYcbToPLH4QIfCPLWbSQfqCdp+NEBupLMM9BWpDz4s8Q0g==" }, "win32-x64": { "package": "@anthropic-ai/claude-agent-sdk-win32-x64", - "version": "0.3.220", - "tarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.220.tgz", - "integrity": "sha512-MuOuXhbr66HlGaWXD2f3w0k2PsvmnbkwcUZ0dAe2poFLdl72GC2dapwwOBefxm9QmoNqk9+jmv/dSKGOVWyvLw==" + "version": "0.3.258", + "tarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.258.tgz", + "integrity": "sha512-UDbXE6n37ZMUogVVYEWX901NNmbyXUv1VvGYN/vfOiIWKUJXCAypam71dBlYFhlAhVX28qCd64w+pTZDYQfYQA==" } } }, diff --git a/apps/desktop/package-lock.json b/apps/desktop/package-lock.json index 8f569e99a..e144f982a 100644 --- a/apps/desktop/package-lock.json +++ b/apps/desktop/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0-beta.1", "license": "AGPL-3.0", "dependencies": { - "@anthropic-ai/claude-agent-sdk": "0.3.220", + "@anthropic-ai/claude-agent-sdk": "0.3.258", "@cursor/sdk": "1.0.27", "@factory/droid-sdk": "0.2.0", "@linear/sdk": "^84.0.0", @@ -247,22 +247,22 @@ } }, "node_modules/@anthropic-ai/claude-agent-sdk": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.220.tgz", - "integrity": "sha512-glc7SdwPkOkLw8oxwLo9PKTdLJGqW/PIR4urWXFoRtX9YllwozsEVc5Tc1+EvLSkfrsxPJqQWqOgpjUOQXf1oA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.258.tgz", + "integrity": "sha512-RxJ5fSPCGCxX5qO/b4IPXhldvtLHeYBAzTUJ4eOzO+gTrepZQSDmwSlQD6nnoEquKGJzOMHCjhdEtBfDjbDWUg==", "license": "SEE LICENSE IN README.md", "engines": { "node": ">=18.0.0" }, "optionalDependencies": { - "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.220", - "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.220", - "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.220", - "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.220" + "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.258", + "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.258", + "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.258", + "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.258" }, "peerDependencies": { "@anthropic-ai/sdk": ">=0.93.0", @@ -271,9 +271,9 @@ } }, "node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.220.tgz", - "integrity": "sha512-7VxlbEosK7DODiOnsjoVd0DSJzbnaPrM2jelMHI0y8zx1UnLS3WC6EFUXbvy74F2sXqEznh2tzn7EKWInaRN6Q==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.258.tgz", + "integrity": "sha512-Hrhzc9WVGSid+DghdTcpVr/8fyXnTD6KeSlDpKx6Wru47J/Nq7RTYiZJt+cex+O2ehaHMEcuYEgoqJ3K/X9NlA==", "cpu": [ "arm64" ], @@ -284,9 +284,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-darwin-x64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.220.tgz", - "integrity": "sha512-X9RwDsSmbF6ultKZroaip+DL8WRgC64gHbrAwrRlAFSPNZV7zmJyP2ur8rW7KrxqmtuehdMMkw8+SAC/6hD2PA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.258.tgz", + "integrity": "sha512-AVqxGX4988J5cS+TMqIzH85+sbsLhJu5Ou9TIALcO/v2Z9ze8GK4vX2ydAYvU/SRnjTvEaiITX+Xcm5afP1IbQ==", "cpu": [ "x64" ], @@ -297,9 +297,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.220.tgz", - "integrity": "sha512-WkROPwWskqhKR9XgnmseHQ6rLi9zM9qt57IWoToIjL/eXOqDWipp7JXZ1L5ud+LrA42dunHPZfBwD/vXZ+A7LA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.258.tgz", + "integrity": "sha512-Jj3K1Ip7WpyMouZCjd7kgV3KswUBF62WAnyG0iaYvKZJvXgYKbIAkjcQ2F2Rx5ZuRUNWAVncE9LeHmdIdx78VQ==", "cpu": [ "arm64" ], @@ -310,9 +310,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64-musl": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.220.tgz", - "integrity": "sha512-OHoZOZ8Cf2TBr6oXIXPwyvUxj9jrq2w8E4poA8dMpacXszcPSPiCQCMuuOh4aWJzfeJE1+TtWxhKMVb2csXyZQ==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.258.tgz", + "integrity": "sha512-I/BLt2vdvqK2B2px526U1lw7Rv+SI+Ld22+wLwu8gLRQk5SYhSW9dmMYEO+GCeF7vQzfzJvMQ4IzbbY+aSGACg==", "cpu": [ "arm64" ], @@ -323,9 +323,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.220.tgz", - "integrity": "sha512-tkTJFnpR9VifvWX2fmkCAPkT6+8Wk/gVu8B5jsVekKZPiZoWRHmMXO30BnZn+f0TZhgYP+82PSX3S8crH1kn+w==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.258.tgz", + "integrity": "sha512-2MJeFVJM/3xwZASP3yn2OuQ9RHIoS30DC/B7oG1XPYcbToPLH4QIfCPLWbSQfqCdp+NEBupLMM9BWpDz4s8Q0g==", "cpu": [ "x64" ], @@ -336,9 +336,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64-musl": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.220.tgz", - "integrity": "sha512-K+FWj+LcGhC1Z7wqeWoLxm1iemcba5xKpLLFVwYm4V6HyMx3ruYd/2r2TiQtjT+JWeNFWIys0ScHiItR6vWAiA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.258.tgz", + "integrity": "sha512-sM7GzRyrOpFhwMn2Ng8nLiWK6cc04uCEu3Zh9mrJS2r3iQu1TryHKoPTjc2Ip0N75sHmwhNodgoRs8NtG1Gkkw==", "cpu": [ "x64" ], @@ -349,9 +349,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-win32-arm64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.220.tgz", - "integrity": "sha512-rIwgq0UwQExWl6KrHUyC4w5KwpL9l6nd95aUTx6RitexaAuEw//xtfTVLnuE4hDDQZFkzEwpdKc3nxDWoGcUbA==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.258.tgz", + "integrity": "sha512-n/Vf6oXAo9EZVSSM5+9d+8dFrUrX9cbgSHK/1njkvykWAN5xsfBbikJYqwhbW84GCYkpXYM+gGNZe23h0fHldw==", "cpu": [ "arm64" ], @@ -362,9 +362,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-win32-x64": { - "version": "0.3.220", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.220.tgz", - "integrity": "sha512-MuOuXhbr66HlGaWXD2f3w0k2PsvmnbkwcUZ0dAe2poFLdl72GC2dapwwOBefxm9QmoNqk9+jmv/dSKGOVWyvLw==", + "version": "0.3.258", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.258.tgz", + "integrity": "sha512-UDbXE6n37ZMUogVVYEWX901NNmbyXUv1VvGYN/vfOiIWKUJXCAypam71dBlYFhlAhVX28qCd64w+pTZDYQfYQA==", "cpu": [ "x64" ], @@ -16845,9 +16845,6 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], "optional": true, "os": [ "linux" @@ -16884,9 +16881,6 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], "optional": true, "os": [ "linux" @@ -16899,9 +16893,6 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], "optional": true, "os": [ "linux" diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 82a7ba262..1182e2cab 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -72,7 +72,7 @@ }, "//dependencies": "Only packages the PACKAGED runtime resolves from node_modules belong here: electron-builder ships every production dependency into app.asar. main/preload are bundled by tsup (dependencies stay external, so a bare require() in dist/main or dist/preload means the package must ship), the packaged ade-cli resolves its own externals through NODE_PATH into app.asar[.unpacked]/node_modules (see src/main/services/runtime/packagedNodePath.ts), and a few binaries are located by path. Everything the renderer uses is inlined into dist/renderer by Vite and belongs in devDependencies.", "dependencies": { - "@anthropic-ai/claude-agent-sdk": "0.3.220", + "@anthropic-ai/claude-agent-sdk": "0.3.258", "@cursor/sdk": "1.0.27", "@factory/droid-sdk": "0.2.0", "@linear/sdk": "^84.0.0", diff --git a/apps/desktop/src/main/main.ts b/apps/desktop/src/main/main.ts index 4c3aa1ab1..e14f3fca2 100644 --- a/apps/desktop/src/main/main.ts +++ b/apps/desktop/src/main/main.ts @@ -79,6 +79,7 @@ import { captureAgentTurnSettledAnalytics, captureChatAutoResumeAnalytics, captureChatMentionsExpandedAnalytics, + captureClaudeHooksIgnoredAnalytics, captureSessionMetadataRegeneratedAnalytics, } from "./services/analytics/agentTurnProductAnalytics"; import { initPerfRunFromEnv } from "./services/perf/perfLog"; @@ -3890,6 +3891,11 @@ app.whenReady().then(async () => { projectId, event, }), + onClaudeHooksIgnored: (event) => captureClaudeHooksIgnoredAnalytics({ + analytics: productAnalyticsService, + projectId, + event, + }), onChatMentionsExpanded: (event) => captureChatMentionsExpandedAnalytics({ analytics: productAnalyticsService, projectId, diff --git a/apps/desktop/src/main/services/analytics/agentTurnProductAnalytics.ts b/apps/desktop/src/main/services/analytics/agentTurnProductAnalytics.ts index d8d3d3888..4b2d3eca9 100644 --- a/apps/desktop/src/main/services/analytics/agentTurnProductAnalytics.ts +++ b/apps/desktop/src/main/services/analytics/agentTurnProductAnalytics.ts @@ -73,6 +73,34 @@ export function captureChatAutoResumeAnalytics(args: { }); } +/** + * One coarse fact when this client's Claude hooks were ignored because + * another client already configured the joined session. Identity only — + * no hook names, payloads, or transcripts. Dedupe per session with a + * one-hour minimum interval. + */ +export function captureClaudeHooksIgnoredAnalytics(args: { + analytics: AgentTurnAnalytics; + projectId: string; + event: { sessionId: string }; +}): void { + args.analytics.captureInternal({ + event: "ade_feature_used", + surface: "api", + projectId: args.projectId, + sessionId: args.event.sessionId, + dedupeKey: `chat_hooks_ignored:${args.event.sessionId}`, + minimumIntervalMs: 60 * 60_000, + properties: { + feature: "chat", + action: "hooks_ignored", + outcome: "failed", + provider: "claude", + source: "runtime", + }, + }); +} + export function captureAgentTurnSettledAnalytics(args: { analytics: AgentTurnAnalytics; projectId: string; diff --git a/apps/desktop/src/main/services/analytics/productAnalyticsPolicy.ts b/apps/desktop/src/main/services/analytics/productAnalyticsPolicy.ts index 47d35db22..e4bbf3da1 100644 --- a/apps/desktop/src/main/services/analytics/productAnalyticsPolicy.ts +++ b/apps/desktop/src/main/services/analytics/productAnalyticsPolicy.ts @@ -130,6 +130,7 @@ const ANALYTICS_ONLY_ACTIONS = new Set([ "brain_repair", "machine_reconnect", "mention_expanded", + "hooks_ignored", "metadata_regenerated", "transaction_failed", "scope_selected", diff --git a/apps/desktop/src/main/services/analytics/productAnalyticsService.test.ts b/apps/desktop/src/main/services/analytics/productAnalyticsService.test.ts index d78c4f571..38f74a7b7 100644 --- a/apps/desktop/src/main/services/analytics/productAnalyticsService.test.ts +++ b/apps/desktop/src/main/services/analytics/productAnalyticsService.test.ts @@ -13,6 +13,7 @@ import { } from "../../../shared/types/productAnalytics"; import { captureAgentTurnSettledAnalytics, + captureClaudeHooksIgnoredAnalytics, captureSessionMetadataRegeneratedAnalytics, } from "./agentTurnProductAnalytics"; import { sanitizeProductAnalyticsProperties } from "./productAnalyticsPolicy"; @@ -320,6 +321,81 @@ describe("productAnalyticsService", () => { fs.rmSync(harness.root, { recursive: true, force: true }); }); + it("accepts the chat hooks_ignored fact and bounds repeats by session dedupe", () => { + const captures: ProductAnalyticsCapture[] = []; + const analytics = settledAnalytics(captures); + + captureClaudeHooksIgnoredAnalytics({ + analytics, + projectId: "project-1", + event: { sessionId: "session-1" }, + }); + + expect(captures).toEqual([{ + event: "ade_feature_used", + surface: "api", + projectId: "project-1", + sessionId: "session-1", + dedupeKey: "chat_hooks_ignored:session-1", + minimumIntervalMs: 60 * 60_000, + properties: { + feature: "chat", + action: "hooks_ignored", + outcome: "failed", + provider: "claude", + source: "runtime", + }, + }]); + + expect(sanitizeProductAnalyticsProperties("ade_feature_used", { + feature: "chat", + action: "hooks_ignored", + outcome: "failed", + provider: "claude", + source: "runtime", + hook_name: "PreToolUse", + })).toEqual({ + feature: "chat", + action: "hooks_ignored", + outcome: "failed", + provider: "claude", + source: "runtime", + }); + + const harness = makeHarness(); + expect(harness.service.captureInternal({ + event: "ade_feature_used", + surface: "api", + projectId: "project-1", + sessionId: "session-1", + properties: { + feature: "chat", + action: "hooks_ignored", + outcome: "failed", + provider: "claude", + source: "runtime", + }, + dedupeKey: "chat_hooks_ignored:session-1", + minimumIntervalMs: 60 * 60_000, + })).toEqual({ accepted: true, reason: "accepted" }); + expect(harness.service.captureInternal({ + event: "ade_feature_used", + surface: "api", + projectId: "project-1", + sessionId: "session-1", + properties: { + feature: "chat", + action: "hooks_ignored", + outcome: "failed", + provider: "claude", + source: "runtime", + }, + dedupeKey: "chat_hooks_ignored:session-1", + minimumIntervalMs: 60 * 60_000, + })).toEqual({ accepted: false, reason: "duplicate" }); + fs.rmSync(harness.root, { recursive: true, force: true }); + }); + it("records metadata regeneration as a coarse chat fact", () => { const captures: ProductAnalyticsCapture[] = []; const analytics = settledAnalytics(captures); diff --git a/apps/desktop/src/main/services/chat/agentChatService.test.ts b/apps/desktop/src/main/services/chat/agentChatService.test.ts index 3f1cb6467..2a8f5eb91 100644 --- a/apps/desktop/src/main/services/chat/agentChatService.test.ts +++ b/apps/desktop/src/main/services/chat/agentChatService.test.ts @@ -4,7 +4,7 @@ import { EventEmitter } from "node:events"; import os from "node:os"; import path from "node:path"; import zlib, { gzipSync } from "node:zlib"; -import { getSessionInfo, getSessionMessages, getSubagentMessages, query, renameSession, startup, tagSession } from "@anthropic-ai/claude-agent-sdk"; +import { getSessionInfo, getSessionMessages, getSubagentMessages, query, renameSession, startup, tagSession, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk"; import { resolveClaudeCodeExecutable } from "../ai/claudeCodeExecutable"; import { codexComputerUseClientCandidates } from "../../utils/codexComputerUse"; import { @@ -1243,12 +1243,12 @@ function bridgeClaudeSessionToQuery(sessionHandle: any, prompt: unknown) { } return []; }), - getContextUsage: vi.fn(async () => { + getContextUsage: vi.fn(async (options?: unknown) => { if (typeof session.getContextUsage === "function") { - return session.getContextUsage(); + return session.getContextUsage(options); } if (typeof session.query?.getContextUsage === "function") { - return session.query.getContextUsage(); + return session.query.getContextUsage(options); } return { categories: [], @@ -1260,6 +1260,15 @@ function bridgeClaudeSessionToQuery(sessionHandle: any, prompt: unknown) { model: "", }; }), + initializationResult: vi.fn(async () => { + if (typeof session.initializationResult === "function") { + return session.initializationResult(); + } + if (typeof session.query?.initializationResult === "function") { + return session.query.initializationResult(); + } + return {}; + }), rewindFiles: vi.fn(async (userMessageId: string, options?: { dryRun?: boolean }) => { if (typeof session.rewindFiles === "function") { return session.rewindFiles(userMessageId, options); @@ -2052,7 +2061,8 @@ async function waitForFakeTimerPromise( async function createClaudeStreamFixture(args: { sdkSessionId: string; messages: Array>; - getContextUsage?: () => Promise; + getContextUsage?: (options?: unknown) => Promise; + initializationResult?: () => Promise; }) { const events: AgentChatEventEnvelope[] = []; const setPermissionMode = vi.fn().mockResolvedValue(undefined); @@ -2083,6 +2093,7 @@ async function createClaudeStreamFixture(args: { sessionId: args.sdkSessionId, setPermissionMode, ...(args.getContextUsage ? { getContextUsage: args.getContextUsage } : {}), + ...(args.initializationResult ? { initializationResult: args.initializationResult } : {}), } as any); const harness = createService({ @@ -4506,6 +4517,10 @@ describe("createAgentChatService", () => { const opts = vi.mocked(claudeSdkCreateSessionCompat).mock.calls.at(-1)?.[0] as any; const server = opts?.mcpServers?.["ade-cto"]; expect(server?.type).toBe("sdk"); + expect(createSdkMcpServer).toHaveBeenCalledWith(expect.objectContaining({ + name: "ade-cto", + timeout: 120_000, + })); const toolNames = Object.keys(server?.instance?._registeredTools ?? {}); expect(toolNames).toContain("spawnChat"); @@ -41964,7 +41979,7 @@ it("fails a cleanly ended OpenCode event stream and clears active child sessions await turn; await vi.waitFor(() => { - expect(getContextUsage).toHaveBeenCalled(); + expect(getContextUsage).toHaveBeenCalledWith({ detail: "summary" }); expect(events.map((entry) => entry.event)) .toEqual(expect.arrayContaining([ expect.objectContaining({ @@ -41982,6 +41997,128 @@ it("fails a cleanly ended OpenCode event stream and clears active child sessions } }); + it("requests a full Claude context snapshot after compact and a summary after settle", async () => { + const getContextUsage = vi.fn().mockResolvedValue({ + categories: [{ name: "Messages", tokens: 40_000 }], + totalTokens: 40_000, + maxTokens: 200_000, + rawMaxTokens: 200_000, + percentage: 20, + gridRows: [], + model: "claude-sonnet-5", + }); + await createClaudeStreamFixture({ + sdkSessionId: "sdk-context-detail", + getContextUsage, + messages: [ + { + type: "system", + subtype: "compact_boundary", + compact_metadata: { trigger: "auto", pre_tokens: 90_000, post_tokens: 40_000 }, + }, + { type: "result", subtype: "success", is_error: false, usage: { input_tokens: 1, output_tokens: 1 } }, + ], + }); + expect(getContextUsage).toHaveBeenCalledWith({ detail: "full" }); + expect(getContextUsage).toHaveBeenCalledWith({ detail: "summary" }); + }); + + it("records Claude modelUsage extras on done without changing outputTokens", async () => { + const events = await runClaudeStreamFixture({ + sdkSessionId: "sdk-model-usage-extras", + messages: [ + { + type: "result", + subtype: "success", + is_error: false, + usage: { input_tokens: 10, output_tokens: 20 }, + total_cost_usd: 0.01, + queued_turn_count: 0, + user_message_uuid: "user-msg-result", + modelUsage: { + "claude-sonnet-5": { + inputTokens: 10, + outputTokens: 20, + thinkingTokens: 7, + costUSD: 0.01, + costBasis: "list", + cacheReadInputTokens: 0, + cacheCreationInputTokens: 0, + webSearchRequests: 0, + contextWindow: 200_000, + maxOutputTokens: 16_000, + }, + }, + }, + ], + }); + const done = events + .map((entry) => entry.event) + .find((event): event is Extract => event.type === "done"); + expect(done).toMatchObject({ + type: "done", + usage: { + inputTokens: 10, + outputTokens: 20, + thinkingTokens: 7, + }, + costUsd: 0.01, + costBasis: "list", + queuedTurnCount: 0, + userMessageUuid: "user-msg-result", + }); + }); + + it("stamps user_message_uuid from the first assistant frame onto done", async () => { + const events = await runClaudeStreamFixture({ + sdkSessionId: "sdk-early-user-message-uuid", + messages: [ + { + type: "assistant", + user_message_uuid: "user-msg-early", + message: { + content: [{ type: "text", text: "hello" }], + usage: { input_tokens: 1, output_tokens: 1 }, + }, + }, + { + type: "result", + subtype: "success", + is_error: false, + usage: { input_tokens: 1, output_tokens: 1 }, + }, + ], + }); + const done = events + .map((entry) => entry.event) + .find((event): event is Extract => event.type === "done"); + expect(done?.userMessageUuid).toBe("user-msg-early"); + }); + + it("warns when Claude reports this client's hooks were ignored", async () => { + const initializationResult = vi.fn().mockResolvedValue({ hooks_applied: false }); + const onClaudeHooksIgnored = vi.fn(); + vi.mocked(claudeSdkCreateSessionCompat).mockReturnValue({ + ...makeDefaultClaudeSession(), + initializationResult, + }); + const { service, logger } = createService({ onClaudeHooksIgnored }); + const session = await service.createSession({ + laneId: "lane-1", + provider: "claude", + model: "claude-sonnet-5", + modelId: "anthropic/claude-sonnet-5", + }); + await service.sendMessage({ sessionId: session.id, text: "hello" }); + await vi.waitFor(() => { + expect(onClaudeHooksIgnored).toHaveBeenCalledWith({ sessionId: session.id }); + }); + expect(logger.warn).toHaveBeenCalledWith( + "agent_chat.claude_hooks_ignored", + expect.objectContaining({ sessionId: session.id }), + ); + }); + it("lets natural compaction suppress the 97% fallback", async () => { const harness = await createClaudeStreamFixture({ sdkSessionId: "sdk-natural-compact", diff --git a/apps/desktop/src/main/services/chat/agentChatService.ts b/apps/desktop/src/main/services/chat/agentChatService.ts index 7e300440b..f311ca197 100644 --- a/apps/desktop/src/main/services/chat/agentChatService.ts +++ b/apps/desktop/src/main/services/chat/agentChatService.ts @@ -845,12 +845,14 @@ function resolveClaudeAgentSdkVersion(): string { } catch { // The package metadata can be unavailable in partial development installs. } - return "0.3.220"; + return "0.3.258"; } const CLAUDE_AGENT_SDK_VERSION = resolveClaudeAgentSdkVersion(); const CLAUDE_AGENT_SDK_API = "v1_query"; const CLAUDE_POST_RESULT_DRAIN_TIMEOUT_MS = 1_000; +/** Hung SDK MCP tool calls currently freeze the chat with no error. 120s is generous enough for slow tools. */ +const CLAUDE_SDK_MCP_TOOL_TIMEOUT_MS = 120_000; const CLAUDE_INTERNAL_EDE_DIAGNOSTIC_PREFIX = "[ede_diagnostic]"; const CLAUDE_AGENT_SDK_TELEMETRY_TAGS = { "claude_sdk.version": CLAUDE_AGENT_SDK_VERSION, @@ -5878,6 +5880,50 @@ function extractReportedModelUsageProvenance(value: unknown): { }; } +const CLAUDE_MODEL_USAGE_COST_BASES = ["list", "managed", "unknown"] as const; +type ClaudeModelUsageCostBasis = (typeof CLAUDE_MODEL_USAGE_COST_BASES)[number]; + +function isClaudeModelUsageCostBasis(value: unknown): value is ClaudeModelUsageCostBasis { + return typeof value === "string" + && (CLAUDE_MODEL_USAGE_COST_BASES as readonly string[]).includes(value); +} + +/** + * Display-only extras from SDK ModelUsage. thinkingTokens is already counted + * inside outputTokens — never add it to a total, sum, or cost. It is also + * partial for sessions resumed from older CLI versions, so it must not be used + * for reconciliation. When more than one model reports a value, skip the + * turn-level field rather than combining them. + */ +function extractClaudeModelUsageExtras(value: unknown): { + thinkingTokens?: number; + costBasis?: ClaudeModelUsageCostBasis; +} { + if (!value || typeof value !== "object") return {}; + const rows = Object.values(value as Record) + .map(asRecord) + .filter((row): row is Record => row !== null); + const thinkingValues = new Set( + rows + .map((row) => numberOrNull(row.thinkingTokens ?? row.thinking_tokens)) + .filter((tokens): tokens is number => tokens != null), + ); + const costBases = new Set( + rows + .map((row) => row.costBasis ?? row.cost_basis) + .filter(isClaudeModelUsageCostBasis), + ); + return { + ...(thinkingValues.size === 1 ? { thinkingTokens: [...thinkingValues][0] } : {}), + ...(costBases.size === 1 ? { costBasis: [...costBases][0] } : {}), + }; +} + +function readClaudeUserMessageUuid(value: unknown): string | null { + const record = asRecord(value); + return normalizeReportedModelName(record?.user_message_uuid); +} + type ClaudeResultMetadata = { canonicalModel?: string; modelProvider?: string; @@ -5885,11 +5931,16 @@ type ClaudeResultMetadata = { fastModeDisabledReason?: string; userMessageUuid?: string; requestSentWallMs?: number; + queuedTurnCount?: number; + thinkingTokens?: number; + costBasis?: ClaudeModelUsageCostBasis; }; function extractClaudeResultMetadata(result: Record): ClaudeResultMetadata { const provenance = extractReportedModelUsageProvenance(result.modelUsage); + const usageExtras = extractClaudeModelUsageExtras(result.modelUsage); const userMessageUuid = normalizeReportedModelName(result.user_message_uuid); + const queuedTurnCount = numberOrNull(result.queued_turn_count); const fastModeDisabledReason = typeof result.fast_mode_disabled_reason === "string" ? result.fast_mode_disabled_reason : result.fast_mode_disabled_reason @@ -5897,10 +5948,12 @@ function extractClaudeResultMetadata(result: Record): ClaudeRes : undefined; return { ...provenance, + ...usageExtras, ...(typeof result.api_error_status === "number" ? { apiErrorStatus: result.api_error_status } : {}), ...(fastModeDisabledReason ? { fastModeDisabledReason } : {}), ...(userMessageUuid ? { userMessageUuid } : {}), ...(typeof result.request_sent_wall_ms === "number" ? { requestSentWallMs: result.request_sent_wall_ms } : {}), + ...(queuedTurnCount != null ? { queuedTurnCount } : {}), }; } @@ -8101,6 +8154,11 @@ export function createAgentChatService(args: { onEvent?: (event: AgentChatEventEnvelope) => void; /** Low-frequency, content-free hook emitted once when a persisted turn reaches a terminal state. */ onTurnSettled?: (event: AgentChatTurnSettledEvent) => void; + /** + * Content-free hook fired when this client's Claude hooks were ignored + * because another client already configured the joined session. + */ + onClaudeHooksIgnored?: (event: { sessionId: string }) => void; /** Content-free hook fired when a send's composer @-mentions were expanded into pointer blocks. */ onChatMentionsExpanded?: (event: { sessionId: string | null }) => void; /** Content-free hook fired after an explicit session-metadata generation request. */ @@ -8180,6 +8238,7 @@ export function createAgentChatService(args: { createScheduledWorkScheduler = createChatScheduledWorkScheduler, onEvent, onTurnSettled, + onClaudeHooksIgnored, onChatMentionsExpanded, onSessionMetadataRegenerated, onAutoResumeOutcome, @@ -9700,7 +9759,7 @@ export function createAgentChatService(args: { applyFlagSettings?: ClaudeQuery["applyFlagSettings"]; reloadPlugins?: ClaudeQuery["reloadPlugins"]; supportedCommands?: () => Promise>; - getContextUsage?: () => Promise; + getContextUsage?: (opts?: { detail?: "summary" | "full" }) => Promise; rewindFiles?: (userMessageId: string, options?: { dryRun?: boolean }) => Promise; interrupt?: ClaudeQuery["interrupt"]; interruptWithOptions?: (options: { cancelQueued: boolean }) => Promise; @@ -15654,7 +15713,7 @@ export function createAgentChatService(args: { const usage = normalizeClaudeContextUsage(await awaitClaudeControlCall( "Claude context usage", CLAUDE_INTERRUPT_REQUEST_TIMEOUT_MS, - () => control.getContextUsage!(), + () => control.getContextUsage!({ detail: origin === "compact" ? "full" : "summary" }), )); if ( managed.runtime !== runtime @@ -18205,6 +18264,7 @@ export function createAgentChatService(args: { version: appVersion, tools: sdkTools, alwaysLoad: true, + timeout: CLAUDE_SDK_MCP_TOOL_TIMEOUT_MS, }); }; @@ -20060,14 +20120,17 @@ export function createAgentChatService(args: { outputTokens?: number | null; cacheReadTokens?: number | null; cacheCreationTokens?: number | null; + thinkingTokens?: number | null; }; costUsd: number | null; + costBasis?: ClaudeModelUsageCostBasis; canonicalModel?: string; modelProvider?: string; apiErrorStatus?: number; fastModeDisabledReason?: string; userMessageUuid?: string; requestSentWallMs?: number; + queuedTurnCount?: number; emittedToolIds: Set; openToolUses: Map; structuredActivity: ClaudeStructuredActivityState; @@ -20230,12 +20293,14 @@ export function createAgentChatService(args: { ...resolveClaudeTurnModelPayload(managed.session, []), ...(state.usage ? { usage: state.usage } : {}), ...(state.costUsd != null ? { costUsd: state.costUsd } : {}), + ...(state.costBasis ? { costBasis: state.costBasis } : {}), ...(state.canonicalModel ? { canonicalModel: state.canonicalModel } : {}), ...(state.modelProvider ? { modelProvider: state.modelProvider } : {}), ...(state.apiErrorStatus != null ? { apiErrorStatus: state.apiErrorStatus } : {}), ...(state.fastModeDisabledReason ? { fastModeDisabledReason: state.fastModeDisabledReason } : {}), ...(state.userMessageUuid ? { userMessageUuid: state.userMessageUuid } : {}), ...(state.requestSentWallMs != null ? { requestSentWallMs: state.requestSentWallMs } : {}), + ...(state.queuedTurnCount != null ? { queuedTurnCount: state.queuedTurnCount } : {}), ...(terminalReason ? { terminalReason, terminalReasonSource: "sdk" as const } : {}), }); if (state.assistantText.trim().length > 0) { @@ -20912,6 +20977,10 @@ export function createAgentChatService(args: { if (msg.type === "assistant") { const assistantMsg = record; + const earlyUserMessageUuid = readClaudeUserMessageUuid(assistantMsg); + if (earlyUserMessageUuid && !state.userMessageUuid) { + state.userMessageUuid = earlyUserMessageUuid; + } const betaMessage = asRecord(assistantMsg.message); const assistantWireUuid = compactString(assistantMsg.uuid); const assistantMessageId = compactString(betaMessage?.id); @@ -21038,6 +21107,10 @@ export function createAgentChatService(args: { if (msg.type === "stream_event") { const streamMsg = record; + const earlyUserMessageUuid = readClaudeUserMessageUuid(streamMsg); + if (earlyUserMessageUuid && !state.userMessageUuid) { + state.userMessageUuid = earlyUserMessageUuid; + } const event = asRecord(streamMsg.event); if (!event) return; const turnId = startClaudeIdleTurn(managed, runtime, state); @@ -21222,8 +21295,13 @@ export function createAgentChatService(args: { state.modelProvider = metadata.modelProvider; state.apiErrorStatus = metadata.apiErrorStatus; state.fastModeDisabledReason = metadata.fastModeDisabledReason; - state.userMessageUuid = metadata.userMessageUuid; + if (metadata.userMessageUuid) state.userMessageUuid = metadata.userMessageUuid; state.requestSentWallMs = metadata.requestSentWallMs; + if (metadata.queuedTurnCount != null) state.queuedTurnCount = metadata.queuedTurnCount; + if (metadata.costBasis) state.costBasis = metadata.costBasis; + if (metadata.thinkingTokens != null) { + state.usage = { ...state.usage, thinkingTokens: metadata.thinkingTokens }; + } if (resultIsError && turnId) { for (const error of resultErrors.userFacing) { emitChatEvent(managed, { type: "error", message: error, turnId }); @@ -21546,7 +21624,7 @@ export function createAgentChatService(args: { }); let assistantText = ""; - let usage: { inputTokens?: number | null; outputTokens?: number | null; cacheReadTokens?: number | null; cacheCreationTokens?: number | null } | undefined; + let usage: { inputTokens?: number | null; outputTokens?: number | null; cacheReadTokens?: number | null; cacheCreationTokens?: number | null; thinkingTokens?: number | null } | undefined; let costUsd: number | null = null; let resultTerminalStatus: ClaudeTerminalStatus = "completed"; let quotaTrippedThisTurn = false; @@ -21557,6 +21635,8 @@ export function createAgentChatService(args: { let resultFastModeDisabledReason: string | undefined; let resultUserMessageUuid: string | undefined; let resultRequestSentWallMs: number | undefined; + let resultQueuedTurnCount: number | undefined; + let resultCostBasis: ClaudeModelUsageCostBasis | undefined; let recoverFromContextOverflow = false; let reportedAssistantModel: string | null = null; let reportedInitModel: string | null = null; @@ -22967,6 +23047,10 @@ export function createAgentChatService(args: { // assistant message — process content blocks if (msg.type === "assistant") { const assistantMsg = msg as any; + const earlyUserMessageUuid = readClaudeUserMessageUuid(assistantMsg); + if (earlyUserMessageUuid && !resultUserMessageUuid) { + resultUserMessageUuid = earlyUserMessageUuid; + } // The SDK reports a logged-out turn as an assistant message carrying // error="authentication_failed" (its text otherwise renders as a plain // bubble with no recovery affordance). Fast-fail into the re-login card. @@ -23144,6 +23228,10 @@ export function createAgentChatService(args: { // stream_event — partial streaming deltas if (msg.type === "stream_event") { const streamMsg = msg as any; + const earlyUserMessageUuid = readClaudeUserMessageUuid(streamMsg); + if (earlyUserMessageUuid && !resultUserMessageUuid) { + resultUserMessageUuid = earlyUserMessageUuid; + } const event = streamMsg.event; if (!event) continue; markBackendDispatched(); @@ -23410,8 +23498,10 @@ export function createAgentChatService(args: { resultModelProvider = metadata.modelProvider; resultApiErrorStatus = metadata.apiErrorStatus; resultFastModeDisabledReason = metadata.fastModeDisabledReason; - resultUserMessageUuid = metadata.userMessageUuid; + if (metadata.userMessageUuid) resultUserMessageUuid = metadata.userMessageUuid; resultRequestSentWallMs = metadata.requestSentWallMs; + if (metadata.queuedTurnCount != null) resultQueuedTurnCount = metadata.queuedTurnCount; + if (metadata.costBasis) resultCostBasis = metadata.costBasis; if (resultMsg.usage) { usage = { inputTokens: resultMsg.usage.input_tokens ?? null, @@ -23420,6 +23510,9 @@ export function createAgentChatService(args: { cacheCreationTokens: resultMsg.usage.cache_creation_input_tokens ?? null, }; } + if (metadata.thinkingTokens != null) { + usage = { ...usage, thinkingTokens: metadata.thinkingTokens }; + } if (typeof resultMsg.total_cost_usd === "number") { costUsd = resultMsg.total_cost_usd; } @@ -23618,12 +23711,14 @@ export function createAgentChatService(args: { ...doneModel, ...(usage ? { usage } : {}), ...(costUsd != null ? { costUsd } : {}), + ...(resultCostBasis ? { costBasis: resultCostBasis } : {}), ...(resultCanonicalModel ? { canonicalModel: resultCanonicalModel } : {}), ...(resultModelProvider ? { modelProvider: resultModelProvider } : {}), ...(resultApiErrorStatus != null ? { apiErrorStatus: resultApiErrorStatus } : {}), ...(resultFastModeDisabledReason ? { fastModeDisabledReason: resultFastModeDisabledReason } : {}), ...(resultUserMessageUuid ? { userMessageUuid: resultUserMessageUuid } : {}), ...(resultRequestSentWallMs != null ? { requestSentWallMs: resultRequestSentWallMs } : {}), + ...(resultQueuedTurnCount != null ? { queuedTurnCount: resultQueuedTurnCount } : {}), ...(resultTerminalReason ? { terminalReason: resultTerminalReason, terminalReasonSource: "sdk" as const } : {}), @@ -32149,6 +32244,31 @@ export function createAgentChatService(args: { } }; + const observeClaudeInitializationHooks = ( + managed: ManagedChatSession, + sessionQuery: ClaudeQuery, + ): void => { + const initializationResult = typeof sessionQuery.initializationResult === "function" + ? sessionQuery.initializationResult.bind(sessionQuery) + : null; + if (!initializationResult) return; + const sessionId = managed.session.id; + void initializationResult().then((response) => { + if (response?.hooks_applied !== false) return; + logger.warn("agent_chat.claude_hooks_ignored", { + sessionId, + ...CLAUDE_AGENT_SDK_TELEMETRY_TAGS, + }); + onClaudeHooksIgnored?.({ sessionId }); + }).catch((error) => { + logger.debug("agent_chat.claude_initialization_result_failed", { + sessionId, + ...CLAUDE_AGENT_SDK_TELEMETRY_TAGS, + error: String(error), + }); + }); + }; + const startClaudeQuery = async (managed: ManagedChatSession, runtime: ClaudeRuntime): Promise => { const startGeneration = runtime.queryGeneration; // background_tasks_changed is per CLI process and emits no startup value. @@ -32223,6 +32343,7 @@ export function createAgentChatService(args: { runtime.query = sessionQuery; runtime.inputPump = pump; runtime.warmQuery = null; + observeClaudeInitializationHooks(managed, sessionQuery); if (runtime.forkFromSdkSessionId) { runtime.forkFromSdkSessionId = null; persistChatState(managed); diff --git a/apps/desktop/src/shared/types/chat.ts b/apps/desktop/src/shared/types/chat.ts index 2b9367ff6..12fddc9af 100644 --- a/apps/desktop/src/shared/types/chat.ts +++ b/apps/desktop/src/shared/types/chat.ts @@ -944,10 +944,20 @@ export type AgentChatEvent = cacheCreationTokens?: number | null; /** Reasoning/thinking output tokens (Codex/Droid/OpenCode/Claude). */ reasoningTokens?: number | null; + /** + * Claude ModelUsage.thinkingTokens. Already counted inside outputTokens — + * display-only; never add to a total, sum, or cost. + */ + thinkingTokens?: number | null; /** Effective context window for the model that produced this turn, when the runtime reports one. */ contextWindow?: number | null; }; costUsd?: number | null; + /** + * Which price table priced this Claude turn: list, managed-settings, or + * unknown (costUsd is then a guess). Recorded only; not used for billing. + */ + costBasis?: "list" | "managed" | "unknown"; /** HTTP status attached to an SDK terminal API error (notably 429/529). */ apiErrorStatus?: number | null; /** Why fast mode was disabled for this result, when reported by Claude. */ @@ -956,6 +966,11 @@ export type AgentChatEvent = userMessageUuid?: string; /** Wall-clock timestamp at which the provider request was sent. */ requestSentWallMs?: number; + /** + * User-initiated sends still waiting in Claude's command queue when this + * result was produced. 0 means none pending. Absent on older CLIs. + */ + queuedTurnCount?: number; // Set only at render time when multiple done events from one cancellation // (parent + subagents) are consolidated into a single row. subagentStoppedCount?: number; diff --git a/docs/features/chat/README.md b/docs/features/chat/README.md index ca2839add..0b61559cf 100644 --- a/docs/features/chat/README.md +++ b/docs/features/chat/README.md @@ -487,7 +487,7 @@ Three rules are specific to it: ## Key concepts - **Claude Agent SDK pipeline.** The Claude adapter is built on the - stable `query()` API and exactly pins SDK `0.3.220` in both the desktop + stable `query()` API and exactly pins SDK `0.3.258` in both the desktop and ADE CLI packages so the bundled Claude Code runtime and protocol surface are reproducible: every chat owns a `ClaudeQuery`, fed by a `ClaudeInputPump` (`claudeInputPump.ts`) async iterable that @@ -503,9 +503,9 @@ Three rules are specific to it: path is passed through `pathToClaudeCodeExecutable`. Context usage, rewindFiles, forkSession, and output-style selection all run through the SDK control channel surfaced on the active `Query` handle. The `claude_sdk.version` telemetry tag is derived from the - resolved runtime package metadata (with `0.3.220` only as the partial-install + resolved runtime package metadata (with `0.3.258` only as the partial-install fallback), so packaged telemetry reports the SDK that actually shipped. -- **Claude SDK 0.3.220 event surfaces.** ADE enables SDK hook events, +- **Claude SDK 0.3.258 event surfaces.** ADE enables SDK hook events, agent progress summaries, prompt suggestions, defensive filtering of tagged child frames, file checkpointing, and all skills for full Claude chats. The adapter translates SDK retry/refusal/notification/memory/mirror/permission events @@ -2000,7 +2000,7 @@ Provider connection management lives on the `ade.ai.*` surface (handled in `regi - **Dispatched steer cancellation.** Every priority message receives a fresh client-side SDK UUID. ADE keeps a bounded UUID-to-`steerId` attribution map, returns those attributed messages in interrupt receipts, and capability-probes - the runtime `cancelAsyncMessage(uuid)` control. SDK `0.3.220` additionally + the runtime `cancelAsyncMessage(uuid)` control. SDK `0.3.258` additionally supports queue cancellation on the raw interrupt request; ADE uses it only when the session advertises `interrupt_cancel_queued_v1`, otherwise it preserves the per-message fallback. Successful cancellation diff --git a/docs/features/onboarding-and-settings/agent-tools-cache.md b/docs/features/onboarding-and-settings/agent-tools-cache.md index 1fe90b48f..3baff4fce 100644 --- a/docs/features/onboarding-and-settings/agent-tools-cache.md +++ b/docs/features/onboarding-and-settings/agent-tools-cache.md @@ -128,7 +128,7 @@ profile — 650 MB must never roam. @openai/codex-darwin-arm64/0.144.5-darwin-arm64/ vendor/aarch64-apple-darwin/bin/codex .install-complete - @anthropic-ai/claude-agent-sdk-darwin-arm64/0.3.220/ + @anthropic-ai/claude-agent-sdk-darwin-arm64/0.3.258/ opencode-darwin-arm64/1.18.14/ .staging/ .locks/