diff --git a/app/e2e/integration/workflow-integration.spec.ts b/app/e2e/integration/workflow-integration.spec.ts index fad9fcaf3..1351c4841 100644 --- a/app/e2e/integration/workflow-integration.spec.ts +++ b/app/e2e/integration/workflow-integration.spec.ts @@ -193,7 +193,7 @@ test.describe("Sidecar Integration — Dashboard Create Skill", { tag: "@integra checks: [ { code: "node_runtime", name: "Node.js", ok: true, detail: "v20.11.0 (system)" }, { code: "agent_sidecar_bundle", name: "Agent sidecar", ok: true, detail: "sidecar/dist/agent-runner.js" }, - { code: "claude_sdk_cli", name: "Claude SDK", ok: true, detail: "sidecar/dist/sdk/cli.js" }, + { code: "claude_sdk_cli", name: "Claude SDK", ok: true, detail: "sidecar/dist/sdk/claude" }, { code: "git_binary", name: "Git", ok: true, detail: "git version 2.50.1" }, ], }, diff --git a/app/sidecar/build.js b/app/sidecar/build.js index a3d41f099..555364fad 100644 --- a/app/sidecar/build.js +++ b/app/sidecar/build.js @@ -34,37 +34,39 @@ console.log("Wrote dist/package.json (ESM marker)"); cpSync(resolve(__dirname, "bootstrap.js"), resolve(__dirname, "dist/bootstrap.js")); console.log("Copied dist/bootstrap.js"); -// Copy SDK runtime files needed by cli.js at runtime. -// The SDK's query() spawns cli.js as a child process, and cli.js -// needs its sibling wasm files and vendor/ directory. -const sdkDir = resolve(__dirname, "node_modules/@anthropic-ai/claude-agent-sdk"); +// Copy the SDK's native `claude` binary to dist/sdk/. +// As of @anthropic-ai/claude-agent-sdk 0.2.116+, the runtime ships as a +// platform-specific native executable in a sibling optional dependency +// (e.g. @anthropic-ai/claude-agent-sdk-darwin-arm64), not as cli.js. +// We pass the copied path to the SDK via `pathToClaudeCodeExecutable`. const outSdk = resolve(__dirname, "dist/sdk"); - -if (existsSync(sdkDir)) { +const sdkBinary = locateSdkBinary(); +if (sdkBinary) { mkdirSync(outSdk, { recursive: true }); + const destName = process.platform === "win32" ? "claude.exe" : "claude"; + cpSync(sdkBinary, resolve(outSdk, destName)); + console.log(`Copied SDK binary to dist/sdk/${destName}`); +} else { + console.warn("SDK native binary not found — skipping"); +} - // Copy cli.js (the actual Claude Code runtime) - cpSync(resolve(sdkDir, "cli.js"), resolve(outSdk, "cli.js")); - - // Copy wasm files (tree-sitter, resvg) - for (const f of ["resvg.wasm", "tree-sitter-bash.wasm", "tree-sitter.wasm"]) { - const src = resolve(sdkDir, f); - if (existsSync(src)) cpSync(src, resolve(outSdk, f)); - } - - // Copy vendor directory (contains ripgrep binaries) - const vendorSrc = resolve(sdkDir, "vendor"); - if (existsSync(vendorSrc)) { - cpSync(vendorSrc, resolve(outSdk, "vendor"), { recursive: true }); +function locateSdkBinary() { + const platform = process.platform; + const arch = process.arch; + const ext = platform === "win32" ? ".exe" : ""; + // On Linux, npm may install either the glibc or musl variant depending on host. + const candidates = + platform === "linux" + ? [ + `@anthropic-ai/claude-agent-sdk-linux-${arch}-musl`, + `@anthropic-ai/claude-agent-sdk-linux-${arch}`, + ] + : [`@anthropic-ai/claude-agent-sdk-${platform}-${arch}`]; + for (const pkg of candidates) { + const candidate = resolve(__dirname, "node_modules", pkg, `claude${ext}`); + if (existsSync(candidate)) return candidate; } - - // Copy manifest.json (SDK metadata) - const manifestSrc = resolve(sdkDir, "manifest.json"); - if (existsSync(manifestSrc)) cpSync(manifestSrc, resolve(outSdk, "manifest.json")); - - console.log("Copied SDK runtime files to dist/sdk/"); -} else { - console.warn("SDK not found — skipping runtime file copy"); + return null; } // Copy mock-templates directory for MOCK_AGENTS mode. diff --git a/app/sidecar/options.ts b/app/sidecar/options.ts index 76429b602..aaf142558 100644 --- a/app/sidecar/options.ts +++ b/app/sidecar/options.ts @@ -103,7 +103,7 @@ export function buildQueryOptions( | "plan", abortController, // Use the same Node binary that's running this sidecar process, - // so the SDK spawns cli.js with a compatible Node version. + // so any SDK-spawned Node tooling (e.g. MCP servers) uses a compatible runtime. executable: process.execPath as 'node', ...(config.pathToClaudeCodeExecutable ? { pathToClaudeCodeExecutable: config.pathToClaudeCodeExecutable } diff --git a/app/sidecar/package-lock.json b/app/sidecar/package-lock.json index 14efc13de..8b1832292 100644 --- a/app/sidecar/package-lock.json +++ b/app/sidecar/package-lock.json @@ -8,7 +8,7 @@ "name": "skill-builder-sidecar", "version": "0.1.0", "dependencies": { - "@anthropic-ai/claude-agent-sdk": "^0.2.109" + "@anthropic-ai/claude-agent-sdk": "^0.2.121" }, "devDependencies": { "@types/node": "^22", @@ -18,9 +18,9 @@ } }, "node_modules/@anthropic-ai/claude-agent-sdk": { - "version": "0.2.109", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.2.109.tgz", - "integrity": "sha512-u7qGFBB2gGcHgiqa2Vn9uF+2Vbr6u6XlGE0SDTfvc49GXwbTfuJ7bmacUoIN2EMXLm7PjkVJC4M8WjccT2MpHQ==", + "version": "0.2.121", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.2.121.tgz", + "integrity": "sha512-hwZNYTkGLKVixd/V/OCJwfH/SdfxZXGV0m6wvy5EBq6qfB+lvJTRz/MSOSa7dHqo4/F7zJY68crEEca68Wrxpw==", "license": "SEE LICENSE IN README.md", "dependencies": { "@anthropic-ai/sdk": "^0.81.0", @@ -30,20 +30,135 @@ "node": ">=18.0.0" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "^0.34.2", - "@img/sharp-darwin-x64": "^0.34.2", - "@img/sharp-linux-arm": "^0.34.2", - "@img/sharp-linux-arm64": "^0.34.2", - "@img/sharp-linux-x64": "^0.34.2", - "@img/sharp-linuxmusl-arm64": "^0.34.2", - "@img/sharp-linuxmusl-x64": "^0.34.2", - "@img/sharp-win32-arm64": "^0.34.2", - "@img/sharp-win32-x64": "^0.34.2" + "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.2.121", + "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.2.121", + "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.2.121", + "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.2.121", + "@anthropic-ai/claude-agent-sdk-linux-x64": "0.2.121", + "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.2.121", + "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.2.121", + "@anthropic-ai/claude-agent-sdk-win32-x64": "0.2.121" }, "peerDependencies": { "zod": "^4.0.0" } }, + "node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64": { + "version": "0.2.121", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.2.121.tgz", + "integrity": "sha512-zVHcXvx6Hl/glDcOCH+EyNx4KPE9cMGLk42eEBSZe014tAN5W8bwM/By08iM6dxijnpH0NQRNNEAW+BryWzuDg==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-darwin-x64": { + "version": "0.2.121", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.2.121.tgz", + "integrity": "sha512-lIXdqKj+bpfDxCk/eU1F1TXNqsIsLTRrkUG/wx19WIGZ8gLUmmVSveUKGlNegTs7S6evMvuezprJzDJT4TcvPA==", + "cpu": [ + "x64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64": { + "version": "0.2.121", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.2.121.tgz", + "integrity": "sha512-AQSnJzaiFvQpUPfO1tWLvsHgb6KNar4QYEQ/5/sk1itfgr3Fx9gxTreq43wX7AXSvkBX1QlDaP1aR1sfM/g/lQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64-musl": { + "version": "0.2.121", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.2.121.tgz", + "integrity": "sha512-4XaGK+dRBYy7krln7BrDG0WsdE6ejUSgHjWHlUGXoubFfZUvls4GSahLcYjJBArLi4dLnxKw8zEuiQguPAIbrw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64": { + "version": "0.2.121", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.2.121.tgz", + "integrity": "sha512-DJUgpm7au086WaQV/S7BGOt2M8D90spGZRizT3twYsacf1BxzK1qsXqB/Pw1lUjPy6pI107pml/TaPzWuS/Vzg==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64-musl": { + "version": "0.2.121", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.2.121.tgz", + "integrity": "sha512-sQoGIgzLlBRrwizxsCV/lbaEuxXom/cfOwlDtQ2HnS1IzDDSjSf5d5pugpWItkOyXBWcHzMUu731WTTutvd/BQ==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-win32-arm64": { + "version": "0.2.121", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.2.121.tgz", + "integrity": "sha512-6n/NHkHxs0/lCJX3XPADjo1EFzXBf0IwYz/nyzJGBCDJjGKmgTe0i8eYBr/hviwt1/OPeK7dmVzVSVl6EL9Azg==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-win32-x64": { + "version": "0.2.121", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.2.121.tgz", + "integrity": "sha512-v2/R918/t94cCwc6rmbxk+UYeQPtF2oBLtQAk+cT0M60hvqmCZO2noyZx5uTp8TQncOlG4MkINIeNY2yfmWSoQ==", + "cpu": [ + "x64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@anthropic-ai/sdk": { "version": "0.81.0", "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.81.0.tgz", @@ -527,310 +642,6 @@ "hono": "^4" } }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", - "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.4" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", - "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.4" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", - "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", - "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", - "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", - "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", - "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", - "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", - "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", - "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", - "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", - "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.4" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", - "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", - "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.4" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", - "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", - "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", diff --git a/app/sidecar/package.json b/app/sidecar/package.json index a03d6c98c..b6177a58c 100644 --- a/app/sidecar/package.json +++ b/app/sidecar/package.json @@ -9,7 +9,7 @@ "test": "vitest run" }, "dependencies": { - "@anthropic-ai/claude-agent-sdk": "^0.2.109" + "@anthropic-ai/claude-agent-sdk": "^0.2.121" }, "devDependencies": { "@types/node": "^22", diff --git a/app/src-tauri/Cargo.lock b/app/src-tauri/Cargo.lock index 8aa196ff0..a0b4a594b 100644 --- a/app/src-tauri/Cargo.lock +++ b/app/src-tauri/Cargo.lock @@ -4085,9 +4085,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.10" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "aws-lc-rs", "ring", diff --git a/app/src-tauri/src/agents/sidecar.rs b/app/src-tauri/src/agents/sidecar.rs index 9c5c52ccb..ed2e9dc9d 100644 --- a/app/src-tauri/src/agents/sidecar.rs +++ b/app/src-tauri/src/agents/sidecar.rs @@ -115,7 +115,7 @@ pub async fn spawn_sidecar( skill_name: String, transcript_log_dir: Option, ) -> Result<(), String> { - // Resolve the SDK cli.js path so the bundled SDK can find it + // Resolve the SDK native binary path so the bundled SDK can spawn it if config.path_to_claude_code_executable.is_none() { if let Ok(cli_path) = resolve_sdk_cli_path(&app_handle) { config.path_to_claude_code_executable = Some(cli_path); @@ -139,35 +139,43 @@ pub fn resolve_sdk_cli_path_public(app_handle: &tauri::AppHandle) -> Result Result { use tauri::Manager; + let exe_name = if cfg!(windows) { + "claude.exe" + } else { + "claude" + }; + // Try resource directory first (production) if let Ok(resource_dir) = app_handle.path().resource_dir() { let cli = resource_dir .join("sidecar") .join("dist") .join("sdk") - .join("cli.js"); + .join(exe_name); if cli.exists() { return cli .to_str() .map(|s| s.strip_prefix("\\\\?\\").unwrap_or(s).replace('\\', "/")) - .ok_or_else(|| "Invalid SDK cli.js path".to_string()); + .ok_or_else(|| "Invalid SDK binary path".to_string()); } } // Fallback: next to the binary if let Ok(exe_dir) = std::env::current_exe() { if let Some(dir) = exe_dir.parent() { - let cli = dir.join("sidecar").join("dist").join("sdk").join("cli.js"); + let cli = dir.join("sidecar").join("dist").join("sdk").join(exe_name); if cli.exists() { return cli .to_str() .map(|s| s.strip_prefix("\\\\?\\").unwrap_or(s).replace('\\', "/")) - .ok_or_else(|| "Invalid SDK cli.js path".to_string()); + .ok_or_else(|| "Invalid SDK binary path".to_string()); } } } @@ -175,17 +183,19 @@ fn resolve_sdk_cli_path(app_handle: &tauri::AppHandle) -> Result // Dev mode fallback let dev_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) .parent() - .map(|p| p.join("sidecar").join("dist").join("sdk").join("cli.js")); + .map(|p| p.join("sidecar").join("dist").join("sdk").join(exe_name)); if let Some(path) = dev_path { if path.exists() { return path .to_str() .map(|s| s.strip_prefix("\\\\?\\").unwrap_or(s).replace('\\', "/")) - .ok_or_else(|| "Invalid SDK cli.js path".to_string()); + .ok_or_else(|| "Invalid SDK binary path".to_string()); } } - Err("Could not find SDK cli.js — run 'npm run build' in app/sidecar/ first".to_string()) + Err(format!( + "Could not find SDK binary ({exe_name}) — run 'npm run build' in app/sidecar/ first" + )) } #[cfg(test)] diff --git a/app/src-tauri/src/commands/evals.rs b/app/src-tauri/src/commands/evals.rs index 73db04862..7612ff1e6 100644 --- a/app/src-tauri/src/commands/evals.rs +++ b/app/src-tauri/src/commands/evals.rs @@ -345,7 +345,7 @@ pub fn list_iterations( .collect(); // Sort descending by iteration number - iterations.sort_by(|a, b| b.iteration.cmp(&a.iteration)); + iterations.sort_by_key(|i| std::cmp::Reverse(i.iteration)); log::debug!("[list_iterations] found {} iterations", iterations.len()); Ok(iterations) diff --git a/app/src-tauri/src/commands/node.rs b/app/src-tauri/src/commands/node.rs index a3ff97150..027533310 100644 --- a/app/src-tauri/src/commands/node.rs +++ b/app/src-tauri/src/commands/node.rs @@ -110,7 +110,7 @@ pub async fn check_startup_deps(app: tauri::AppHandle) -> Result dep_ok("claude_sdk_cli", "Claude SDK", path), Err(e) => dep_fail( diff --git a/app/src-tauri/src/git.rs b/app/src-tauri/src/git.rs index f2b8ef5d4..e35829a03 100644 --- a/app/src-tauri/src/git.rs +++ b/app/src-tauri/src/git.rs @@ -599,7 +599,7 @@ pub fn prior_skill_tag(path: &Path, plugin_slug: &str, skill_name: &str) -> Opti } } - versions.sort_by(|a, b| (b.0, b.1, b.2).cmp(&(a.0, a.1, a.2))); + versions.sort_by_key(|v| std::cmp::Reverse((v.0, v.1, v.2))); if versions.len() >= 2 { Some(versions[1].3.clone()) } else { diff --git a/app/src/test/mocks/tauri-e2e.ts b/app/src/test/mocks/tauri-e2e.ts index c761dbd07..343f23c58 100644 --- a/app/src/test/mocks/tauri-e2e.ts +++ b/app/src/test/mocks/tauri-e2e.ts @@ -42,7 +42,7 @@ const mockResponses: Record = { checks: [ { code: "node_runtime", name: "Node.js", ok: true, detail: "v20.11.0 (system)" }, { code: "agent_sidecar_bundle", name: "Agent sidecar", ok: true, detail: "sidecar/dist/agent-runner.js" }, - { code: "claude_sdk_cli", name: "Claude SDK", ok: true, detail: "sidecar/dist/sdk/cli.js" }, + { code: "claude_sdk_cli", name: "Claude SDK", ok: true, detail: "sidecar/dist/sdk/claude" }, { code: "git_binary", name: "Git", ok: true, detail: "git version 2.50.1" }, ], },