From e6483f1060403408a47b93a986b077de5452775e Mon Sep 17 00:00:00 2001 From: Raymond Weitekamp Date: Tue, 5 May 2026 11:42:56 -0400 Subject: [PATCH 1/5] feat(cli): pin explicit Claude/Codex model + add live API smoke MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Layer 0 + Layer 1 of the harness robustness plan: stop inheriting SDK defaults, and catch upstream drift before users hit it. * claude-sdk + codex-sdk now pass explicit model and (Claude only) thinking via tools/cli/src/harnesses/defaults.ts, the single audit point. Override per run via ANTHROPIC_MODEL / OPENAI_MODEL / CODEX_MODEL env vars. * Pin @anthropic-ai/claude-agent-sdk to exact 0.2.126. The previous ^0.2.90 resolved to 0.2.90, which hardcoded thinking.type: "enabled" — Opus 4.6+ / Sonnet 4.6+ now reject that with HTTP 400. * Add tools/cli/tests/live/smoke.live.test.ts and a `test:live` script using a dedicated vitest.live.config.ts. Tests auto-skip per harness when API keys are absent, so contributors without keys aren't blocked. * Add .github/workflows/cli-live-smoke.yml — runs the live smoke on every PR touching tools/cli/** plus workflow_dispatch. Uses org ANTHROPIC_API_KEY and OPENAI_API_KEY secrets. Complements the existing cli-real-harness-smoke.yml (binary-spawn end-to-end) with a faster harness-unit-level check. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/cli-live-smoke.yml | 52 +++ tools/cli/package-lock.json | 443 ++++++-------------- tools/cli/package.json | 3 +- tools/cli/src/harnesses/claude-sdk.ts | 3 + tools/cli/src/harnesses/codex-sdk.ts | 10 +- tools/cli/src/harnesses/defaults.ts | 16 + tools/cli/tests/harnesses/harnesses.test.ts | 40 +- tools/cli/tests/live/smoke.live.test.ts | 77 ++++ tools/cli/vitest.config.ts | 3 +- tools/cli/vitest.live.config.ts | 10 + 10 files changed, 327 insertions(+), 330 deletions(-) create mode 100644 .github/workflows/cli-live-smoke.yml create mode 100644 tools/cli/src/harnesses/defaults.ts create mode 100644 tools/cli/tests/live/smoke.live.test.ts create mode 100644 tools/cli/vitest.live.config.ts diff --git a/.github/workflows/cli-live-smoke.yml b/.github/workflows/cli-live-smoke.yml new file mode 100644 index 00000000..a36ceb1d --- /dev/null +++ b/.github/workflows/cli-live-smoke.yml @@ -0,0 +1,52 @@ +name: CLI Live Smoke + +on: + pull_request: + paths: + - "tools/cli/**" + - ".github/workflows/cli-live-smoke.yml" + push: + branches: + - main + paths: + - "tools/cli/**" + - ".github/workflows/cli-live-smoke.yml" + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: cli-live-smoke-${{ github.ref }} + cancel-in-progress: true + +jobs: + live-smoke: + name: Harness live smoke (vitest) + runs-on: ubuntu-latest + timeout-minutes: 10 + defaults: + run: + working-directory: tools/cli + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + cache-dependency-path: tools/cli/package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Build CLI + run: npm run build + + - name: Run harness live smoke + run: npm run test:live diff --git a/tools/cli/package-lock.json b/tools/cli/package-lock.json index 4aefaf6a..d811c7d7 100644 --- a/tools/cli/package-lock.json +++ b/tools/cli/package-lock.json @@ -9,7 +9,7 @@ "version": "0.2.5", "license": "MIT", "dependencies": { - "@anthropic-ai/claude-agent-sdk": "^0.2.90", + "@anthropic-ai/claude-agent-sdk": "0.2.126", "@hono/node-server": "^1.19.14", "@oclif/core": "^4.10.6", "@openai/codex-sdk": "^0.125.0", @@ -29,36 +29,139 @@ } }, "node_modules/@anthropic-ai/claude-agent-sdk": { - "version": "0.2.90", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.2.90.tgz", - "integrity": "sha512-up5bK0pUbthKIZtNE18WDrIYi0KNpZUhdgjGbkfH/mFQJxI6W/uE3mTiLrCX3UF0SqNl0fMtojBTZPJr2b3O4g==", + "version": "0.2.126", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.2.126.tgz", + "integrity": "sha512-4ZrVu0XUEwNG6wxvsLgppRAmSfAf3oeEMEUPhgazb0AXUUe/7W8MxwZKJWOffqSLWaNYzOt3ZCIL7NJY6toqWw==", "license": "SEE LICENSE IN README.md", "dependencies": { - "@anthropic-ai/sdk": "^0.74.0", - "@modelcontextprotocol/sdk": "^1.27.1" + "@anthropic-ai/sdk": "^0.81.0", + "@modelcontextprotocol/sdk": "^1.29.0" }, "engines": { "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.126", + "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.2.126", + "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.2.126", + "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.2.126", + "@anthropic-ai/claude-agent-sdk-linux-x64": "0.2.126", + "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.2.126", + "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.2.126", + "@anthropic-ai/claude-agent-sdk-win32-x64": "0.2.126" }, "peerDependencies": { "zod": "^4.0.0" } }, + "node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64": { + "version": "0.2.126", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.2.126.tgz", + "integrity": "sha512-JFlJBbeAlx7Ic5s4lGUN9SppobryXk/lIqPCvhp6KrJTQIerh3MIBzxsVIJ0MaDut7jVni/oYgsvDni7NIyqHA==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-darwin-x64": { + "version": "0.2.126", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.2.126.tgz", + "integrity": "sha512-J8BpMj16NK9FUaG3HnHSivyp4Xww9DKWHiC8QSHT9oiT8pH5IG7nl0jxyjIq/lY79evlTY+ubgDVWlMUhUAN/g==", + "cpu": [ + "x64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64": { + "version": "0.2.126", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.2.126.tgz", + "integrity": "sha512-LM+mnfQsgI+1i5mYZwIPDDf14NGBu5wbhzm5U8P11dCa2p8sXmKoWpkbO16BFM2NxeW44I/RXCxE5qFsbz4zcg==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64-musl": { + "version": "0.2.126", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.2.126.tgz", + "integrity": "sha512-GO0BnIUw3LQ3XAy+nipAabkN0GwQGPhHB6ITI4XLoR99fLHB3TA6WfyvTf0fnpxd25A+c/+UsAoxz4zBQaHlhA==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64": { + "version": "0.2.126", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.2.126.tgz", + "integrity": "sha512-yaOTDcYCdscxC0LKg9w8IwSa5g+993WggFZJBTZpqvflA2+WMQeTarDnKlsFTCw9XUZkL8XZeBALYJGx0HutuA==", + "cpu": [ + "x64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64-musl": { + "version": "0.2.126", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.2.126.tgz", + "integrity": "sha512-ByJGO0+mu7EplxSFSCIHd7QWsXdrF3qgtzQ177o/j+oSppLoqR1ot5ktf8aw5oR3CC5lFHg4tqd6TnneQpEoIg==", + "cpu": [ + "x64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-win32-arm64": { + "version": "0.2.126", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.2.126.tgz", + "integrity": "sha512-gv3MOsOBkCx3LajOOIjD7AKsOtz/qNHsS2oshGt2GVoy7JA3XbCDeCetDjM6SorV4SE+7F/IH0UJdXe5ejI/Zg==", + "cpu": [ + "arm64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@anthropic-ai/claude-agent-sdk-win32-x64": { + "version": "0.2.126", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.2.126.tgz", + "integrity": "sha512-oRV75HwyoOd1/t5+kipAM2g62CaElpKGvSBx3Ys4lCwCiFUyOnmet/O+hRXENsY6ShDeQZEcJL2UWljr2d5NQw==", + "cpu": [ + "x64" + ], + "license": "SEE LICENSE IN LICENSE.md", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@anthropic-ai/sdk": { - "version": "0.74.0", - "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.74.0.tgz", - "integrity": "sha512-srbJV7JKsc5cQ6eVuFzjZO7UR3xEPJqPamHFIe29bs38Ij2IripoAhC0S5NslNbaFUYqBKypmmpzMTpqfHEUDw==", + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.81.0.tgz", + "integrity": "sha512-D4K5PvEV6wPiRtVlVsJHIUhHAmOZ6IT/I9rKlTf84gR7GyyAurPJK7z9BOf/AZqC5d1DhYQGJNKRmV+q8dGhgw==", "license": "MIT", "dependencies": { "json-schema-to-ts": "^3.1.1" @@ -538,310 +641,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/tools/cli/package.json b/tools/cli/package.json index 86b13a58..9a32366b 100644 --- a/tools/cli/package.json +++ b/tools/cli/package.json @@ -51,6 +51,7 @@ "build": "npm run clean && tsc -p tsconfig.build.json", "typecheck": "tsc -p tsconfig.json --noEmit", "test": "vitest --run", + "test:live": "vitest --run --config vitest.live.config.ts", "smoke:harness": "node scripts/smoke-harness.mjs", "dev": "tsx src/index.ts", "clean": "rm -rf dist", @@ -68,7 +69,7 @@ "node": ">=18.14.1" }, "dependencies": { - "@anthropic-ai/claude-agent-sdk": "^0.2.90", + "@anthropic-ai/claude-agent-sdk": "0.2.126", "@hono/node-server": "^1.19.14", "@oclif/core": "^4.10.6", "@openai/codex-sdk": "^0.125.0", diff --git a/tools/cli/src/harnesses/claude-sdk.ts b/tools/cli/src/harnesses/claude-sdk.ts index dcd2d8e9..589c78cd 100644 --- a/tools/cli/src/harnesses/claude-sdk.ts +++ b/tools/cli/src/harnesses/claude-sdk.ts @@ -1,3 +1,4 @@ +import { CLAUDE_SDK_DEFAULTS, resolveClaudeModel } from "./defaults.js"; import { writeLine } from "./streams.js"; import type { Harness, HarnessRunOptions } from "./types.js"; @@ -27,6 +28,8 @@ export function createClaudeSdkHarness(options: ClaudeSdkHarnessOptions = {}): H prompt, options: { abortController, + model: resolveClaudeModel(runOptions.env), + thinking: CLAUDE_SDK_DEFAULTS.thinking, ...(runOptions.additionalDirectories === undefined ? {} : { additionalDirectories: runOptions.additionalDirectories }), diff --git a/tools/cli/src/harnesses/codex-sdk.ts b/tools/cli/src/harnesses/codex-sdk.ts index 129064a8..9512ed80 100644 --- a/tools/cli/src/harnesses/codex-sdk.ts +++ b/tools/cli/src/harnesses/codex-sdk.ts @@ -1,4 +1,5 @@ import { codexClientConfig, codexThreadRuntimeOptions } from "./codex-options.js"; +import { resolveCodexModel } from "./defaults.js"; import { writeLine } from "./streams.js"; import type { CodexSdkClientOptions, CodexSdkFactory, CodexThreadEvent, CodexThreadItem, Harness } from "./types.js"; @@ -19,9 +20,10 @@ export function createCodexSdkHarness(options: CodexSdkHarnessOptions = {}): Har async run(prompt, runOptions) { try { const env = definedEnv(runOptions.env); + const model = resolveCodexModel(runOptions.env); const codex = await factory(codexClientOptions(env, runOptions.systemPromptAppend)); const thread = codex.startThread( - codexThreadOptions(runOptions.cwd, env, runOptions.additionalDirectories), + codexThreadOptions(runOptions.cwd, env, runOptions.additionalDirectories, model), ); const { events } = await thread.runStreamed( prompt, @@ -48,14 +50,14 @@ function codexThreadOptions( cwd: string | undefined, env: Record | undefined, additionalDirectories: readonly string[] | undefined, + model: string, ) { const runtimeOptions = codexThreadRuntimeOptions(env, additionalDirectories); - const options = { + return { + model, ...(cwd === undefined ? {} : { workingDirectory: cwd }), ...runtimeOptions, }; - - return Object.keys(options).length === 0 ? undefined : options; } function codexClientOptions(env: Record | undefined, systemPromptAppend: string | undefined) { diff --git a/tools/cli/src/harnesses/defaults.ts b/tools/cli/src/harnesses/defaults.ts new file mode 100644 index 00000000..971610a3 --- /dev/null +++ b/tools/cli/src/harnesses/defaults.ts @@ -0,0 +1,16 @@ +export const CLAUDE_SDK_DEFAULTS = { + model: "claude-sonnet-4-6", + thinking: { type: "adaptive" as const }, +} as const; + +export const CODEX_SDK_DEFAULTS = { + model: "gpt-5-codex", +} as const; + +export function resolveClaudeModel(env: Record | undefined): string { + return env?.ANTHROPIC_MODEL ?? process.env.ANTHROPIC_MODEL ?? CLAUDE_SDK_DEFAULTS.model; +} + +export function resolveCodexModel(env: Record | undefined): string { + return env?.OPENAI_MODEL ?? env?.CODEX_MODEL ?? process.env.OPENAI_MODEL ?? process.env.CODEX_MODEL ?? CODEX_SDK_DEFAULTS.model; +} diff --git a/tools/cli/tests/harnesses/harnesses.test.ts b/tools/cli/tests/harnesses/harnesses.test.ts index 5d562dbc..254c3f82 100644 --- a/tools/cli/tests/harnesses/harnesses.test.ts +++ b/tools/cli/tests/harnesses/harnesses.test.ts @@ -92,7 +92,7 @@ describe("codex-sdk harness", () => { expect(exitCode).toBe(0); expect(io.stdout).toBe("sdk output\n"); - expect(starts).toEqual([{ skipGitRepoCheck: true, workingDirectory: "/repo" }]); + expect(starts).toEqual([{ model: "gpt-5-codex", skipGitRepoCheck: true, workingDirectory: "/repo" }]); expect(factoryOptions).toEqual([{ apiKey: "test", env: { OPENAI_API_KEY: "test" } }]); }); @@ -127,6 +127,7 @@ describe("codex-sdk harness", () => { expect(starts).toEqual([ { additionalDirectories: ["/skills/open-prose"], + model: "gpt-5-codex", skipGitRepoCheck: true, }, ]); @@ -166,7 +167,9 @@ describe("codex-sdk harness", () => { }); expect(exitCode).toBe(0); - expect(starts).toEqual([{ approvalPolicy: "never", sandboxMode: "danger-full-access", skipGitRepoCheck: true }]); + expect(starts).toEqual([ + { approvalPolicy: "never", model: "gpt-5-codex", sandboxMode: "danger-full-access", skipGitRepoCheck: true }, + ]); }); test("maps failed turns to stderr and nonzero exit", async () => { @@ -219,6 +222,8 @@ describe("claude-sdk harness", () => { additionalDirectories: ["/skills/open-prose"], cwd: "/repo", env: { A: "B" }, + model: "claude-sonnet-4-6", + thinking: { type: "adaptive" }, systemPrompt: { type: "preset", preset: "claude_code", @@ -229,6 +234,37 @@ describe("claude-sdk harness", () => { ]); }); + test("honors ANTHROPIC_MODEL override from runOptions.env", async () => { + const io = memoryStreams(); + const calls: unknown[] = []; + const harness = createClaudeSdkHarness({ + query: async (args) => { + calls.push(args); + return { + async *[Symbol.asyncIterator]() { + yield { type: "result", subtype: "success", result: "ok", is_error: false }; + }, + close() {}, + } as never; + }, + }); + + await harness.run("prose status", { + ...io.options, + env: { ANTHROPIC_MODEL: "claude-opus-4-7" }, + }); + + expect(calls).toEqual([ + { + prompt: "prose status", + options: expect.objectContaining({ + model: "claude-opus-4-7", + thinking: { type: "adaptive" }, + }), + }, + ]); + }); + test("streams text deltas without duplicating final result", async () => { const io = memoryStreams(); const abortControllers: AbortController[] = []; diff --git a/tools/cli/tests/live/smoke.live.test.ts b/tools/cli/tests/live/smoke.live.test.ts new file mode 100644 index 00000000..c13cf95f --- /dev/null +++ b/tools/cli/tests/live/smoke.live.test.ts @@ -0,0 +1,77 @@ +import { describe, expect, test } from "vitest"; + +import { createClaudeSdkHarness, createCodexSdkHarness } from "../../src/harnesses/index.js"; + +const MARKER = "PROSE_LIVE_SMOKE_OK"; +const PROMPT = `Reply with exactly the literal string ${MARKER} and nothing else. Do not use any tools.`; +const TIMEOUT_MS = 90_000; + +function memoryStreams() { + let stdout = ""; + let stderr = ""; + return { + options: { + stdout: { write: (chunk: string) => void (stdout += chunk) }, + stderr: { write: (chunk: string) => void (stderr += chunk) }, + }, + get stdout() { + return stdout; + }, + get stderr() { + return stderr; + }, + }; +} + +const claudeKey = process.env.ANTHROPIC_API_KEY; +const codexKey = process.env.CODEX_API_KEY ?? process.env.OPENAI_API_KEY; + +describe("live smoke", () => { + test.runIf(claudeKey !== undefined)( + "claude-sdk reaches Anthropic and produces text", + async () => { + const io = memoryStreams(); + const exitCode = await createClaudeSdkHarness().run(PROMPT, { + ...io.options, + env: { ANTHROPIC_API_KEY: claudeKey, ...processEnvWhitelist(["HOME", "PATH"]) }, + }); + expect(exitCode).toBe(0); + expect(io.stderr).not.toMatch(/API Error|invalid_request_error/); + expect(io.stdout).toContain(MARKER); + }, + TIMEOUT_MS, + ); + + test.runIf(codexKey !== undefined)( + "codex-sdk reaches OpenAI and produces text", + async () => { + const io = memoryStreams(); + const exitCode = await createCodexSdkHarness().run(PROMPT, { + ...io.options, + env: { OPENAI_API_KEY: codexKey, ...processEnvWhitelist(["HOME", "PATH"]) }, + }); + expect(exitCode).toBe(0); + expect(io.stderr).not.toMatch(/error|failed/i); + expect(io.stdout).toContain(MARKER); + }, + TIMEOUT_MS, + ); + + test.skipIf(claudeKey !== undefined || codexKey !== undefined)( + "skipped: no live keys present", + () => { + expect(true).toBe(true); + }, + ); +}); + +function processEnvWhitelist(keys: readonly string[]): Record { + const out: Record = {}; + for (const key of keys) { + const value = process.env[key]; + if (value !== undefined) { + out[key] = value; + } + } + return out; +} diff --git a/tools/cli/vitest.config.ts b/tools/cli/vitest.config.ts index 651c9797..57f8426d 100644 --- a/tools/cli/vitest.config.ts +++ b/tools/cli/vitest.config.ts @@ -3,6 +3,7 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { environment: "node", - include: ["tests/**/*.test.ts"] + include: ["tests/**/*.test.ts"], + exclude: ["**/node_modules/**", "**/dist/**", "tests/live/**"] } }); diff --git a/tools/cli/vitest.live.config.ts b/tools/cli/vitest.live.config.ts new file mode 100644 index 00000000..7b437fc8 --- /dev/null +++ b/tools/cli/vitest.live.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + environment: "node", + include: ["tests/live/**/*.test.ts"], + exclude: ["**/node_modules/**", "**/dist/**"], + testTimeout: 120_000 + } +}); From 86d588bba178d5ffef647ca010342dae041eeb61 Mon Sep 17 00:00:00 2001 From: Raymond Weitekamp Date: Tue, 5 May 2026 12:17:18 -0400 Subject: [PATCH 2/5] ci(cli-live-smoke): temporarily fire on feat branch push Workflow_dispatch is blocked for new workflow files until they exist on the default branch. Adding the feature branch to the push trigger so the live smoke runs without opening a PR. To revert before merge. --- .github/workflows/cli-live-smoke.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cli-live-smoke.yml b/.github/workflows/cli-live-smoke.yml index a36ceb1d..e445be8e 100644 --- a/.github/workflows/cli-live-smoke.yml +++ b/.github/workflows/cli-live-smoke.yml @@ -8,6 +8,7 @@ on: push: branches: - main + - feat/cli-robust-explicit-defaults paths: - "tools/cli/**" - ".github/workflows/cli-live-smoke.yml" From 597ffd8d56dec25620010aa11948ecac5c9449d8 Mon Sep 17 00:00:00 2001 From: Raymond Weitekamp Date: Tue, 5 May 2026 12:30:37 -0400 Subject: [PATCH 3/5] =?UTF-8?q?fix(cli):=20pin=20claude-agent-sdk=20to=200?= =?UTF-8?q?.2.107=20=E2=80=94=20last=20bundled-cli=20release?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0.2.126 introduced platform-specific native binary packaging via 8 optional-deps, but the linux-x64 and linux-x64-musl variants share identical {os, cpu} constraints with no libc discriminator. npm install on glibc Linux runners is non-deterministic, and the SDK's runtime binary lookup can fail (CI run 25388337686 confirmed this). 0.2.107 is the last 0.2.x release with a bundled cli.js — no native binary lookup, no platform-package mess. It already supports adaptive thinking and modern model names like claude-sonnet-4-6, so it satisfies the original Layer 0 requirement. Worth ~3 weeks of SDK improvements to keep CI deterministic. Layer 1 live smoke caught this drift exactly as designed. --- tools/cli/package-lock.json | 439 ++++++++++++++++++++++++++---------- tools/cli/package.json | 2 +- 2 files changed, 324 insertions(+), 117 deletions(-) diff --git a/tools/cli/package-lock.json b/tools/cli/package-lock.json index d811c7d7..842a6859 100644 --- a/tools/cli/package-lock.json +++ b/tools/cli/package-lock.json @@ -9,7 +9,7 @@ "version": "0.2.5", "license": "MIT", "dependencies": { - "@anthropic-ai/claude-agent-sdk": "0.2.126", + "@anthropic-ai/claude-agent-sdk": "0.2.107", "@hono/node-server": "^1.19.14", "@oclif/core": "^4.10.6", "@openai/codex-sdk": "^0.125.0", @@ -29,9 +29,9 @@ } }, "node_modules/@anthropic-ai/claude-agent-sdk": { - "version": "0.2.126", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.2.126.tgz", - "integrity": "sha512-4ZrVu0XUEwNG6wxvsLgppRAmSfAf3oeEMEUPhgazb0AXUUe/7W8MxwZKJWOffqSLWaNYzOt3ZCIL7NJY6toqWw==", + "version": "0.2.107", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.2.107.tgz", + "integrity": "sha512-zH5CCjvFn4A+RN0LLaqKJYEcGEg2O/Bm+tDpkBGcEKaRZOqwXkKJ2d9JmboALGSxsCAN5K0+uQxPgzk9LhiQzg==", "license": "SEE LICENSE IN README.md", "dependencies": { "@anthropic-ai/sdk": "^0.81.0", @@ -41,123 +41,20 @@ "node": ">=18.0.0" }, "optionalDependencies": { - "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.2.126", - "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.2.126", - "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.2.126", - "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.2.126", - "@anthropic-ai/claude-agent-sdk-linux-x64": "0.2.126", - "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.2.126", - "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.2.126", - "@anthropic-ai/claude-agent-sdk-win32-x64": "0.2.126" + "@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" }, "peerDependencies": { "zod": "^4.0.0" } }, - "node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64": { - "version": "0.2.126", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.2.126.tgz", - "integrity": "sha512-JFlJBbeAlx7Ic5s4lGUN9SppobryXk/lIqPCvhp6KrJTQIerh3MIBzxsVIJ0MaDut7jVni/oYgsvDni7NIyqHA==", - "cpu": [ - "arm64" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@anthropic-ai/claude-agent-sdk-darwin-x64": { - "version": "0.2.126", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.2.126.tgz", - "integrity": "sha512-J8BpMj16NK9FUaG3HnHSivyp4Xww9DKWHiC8QSHT9oiT8pH5IG7nl0jxyjIq/lY79evlTY+ubgDVWlMUhUAN/g==", - "cpu": [ - "x64" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64": { - "version": "0.2.126", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.2.126.tgz", - "integrity": "sha512-LM+mnfQsgI+1i5mYZwIPDDf14NGBu5wbhzm5U8P11dCa2p8sXmKoWpkbO16BFM2NxeW44I/RXCxE5qFsbz4zcg==", - "cpu": [ - "arm64" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64-musl": { - "version": "0.2.126", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.2.126.tgz", - "integrity": "sha512-GO0BnIUw3LQ3XAy+nipAabkN0GwQGPhHB6ITI4XLoR99fLHB3TA6WfyvTf0fnpxd25A+c/+UsAoxz4zBQaHlhA==", - "cpu": [ - "arm64" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64": { - "version": "0.2.126", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.2.126.tgz", - "integrity": "sha512-yaOTDcYCdscxC0LKg9w8IwSa5g+993WggFZJBTZpqvflA2+WMQeTarDnKlsFTCw9XUZkL8XZeBALYJGx0HutuA==", - "cpu": [ - "x64" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64-musl": { - "version": "0.2.126", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.2.126.tgz", - "integrity": "sha512-ByJGO0+mu7EplxSFSCIHd7QWsXdrF3qgtzQ177o/j+oSppLoqR1ot5ktf8aw5oR3CC5lFHg4tqd6TnneQpEoIg==", - "cpu": [ - "x64" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@anthropic-ai/claude-agent-sdk-win32-arm64": { - "version": "0.2.126", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.2.126.tgz", - "integrity": "sha512-gv3MOsOBkCx3LajOOIjD7AKsOtz/qNHsS2oshGt2GVoy7JA3XbCDeCetDjM6SorV4SE+7F/IH0UJdXe5ejI/Zg==", - "cpu": [ - "arm64" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@anthropic-ai/claude-agent-sdk-win32-x64": { - "version": "0.2.126", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.2.126.tgz", - "integrity": "sha512-oRV75HwyoOd1/t5+kipAM2g62CaElpKGvSBx3Ys4lCwCiFUyOnmet/O+hRXENsY6ShDeQZEcJL2UWljr2d5NQw==", - "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", @@ -641,6 +538,310 @@ "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", @@ -1232,6 +1433,7 @@ "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -1908,6 +2110,7 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "license": "MIT", + "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", @@ -2211,6 +2414,7 @@ "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.16.tgz", "integrity": "sha512-jN0ZewiNAWSe5khM3EyCmBb250+b40wWbwNILNfEvq84VREWwOIkuUsFONk/3i3nqkz7Oe1PcpM2mwQEK2L9Kg==", "license": "MIT", + "peer": true, "engines": { "node": ">=16.9.0" } @@ -3135,6 +3339,7 @@ "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" @@ -3418,6 +3623,7 @@ "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -3565,6 +3771,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.1.tgz", "integrity": "sha512-a6ENMBBGZBsnlSebQ/eKCguSBeGKSf4O7BPnqVPmYGtpBYI7VSqoVqw+QcB7kPRjbqPwhYTpFbVj/RqNz/CT0Q==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/tools/cli/package.json b/tools/cli/package.json index 9a32366b..15c1952c 100644 --- a/tools/cli/package.json +++ b/tools/cli/package.json @@ -69,7 +69,7 @@ "node": ">=18.14.1" }, "dependencies": { - "@anthropic-ai/claude-agent-sdk": "0.2.126", + "@anthropic-ai/claude-agent-sdk": "0.2.107", "@hono/node-server": "^1.19.14", "@oclif/core": "^4.10.6", "@openai/codex-sdk": "^0.125.0", From 75a1a85ba10ce9a11c3ef3377f6abcd55866fe63 Mon Sep 17 00:00:00 2001 From: Raymond Weitekamp Date: Tue, 5 May 2026 13:03:13 -0400 Subject: [PATCH 4/5] ci(cli-live-smoke): drop temp feat-branch push trigger Workflow has now landed on this branch and was proven (run 25388993268 green for both harnesses). Revert the feature-branch entry so the trigger surface goes back to its intended scope: PRs touching tools/cli/**, push to main, and workflow_dispatch. --- .github/workflows/cli-live-smoke.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/cli-live-smoke.yml b/.github/workflows/cli-live-smoke.yml index e445be8e..a36ceb1d 100644 --- a/.github/workflows/cli-live-smoke.yml +++ b/.github/workflows/cli-live-smoke.yml @@ -8,7 +8,6 @@ on: push: branches: - main - - feat/cli-robust-explicit-defaults paths: - "tools/cli/**" - ".github/workflows/cli-live-smoke.yml" From df2fcddc84494ab9982d8466011dbed35d65e285 Mon Sep 17 00:00:00 2001 From: Raymond Weitekamp Date: Tue, 5 May 2026 13:24:03 -0400 Subject: [PATCH 5/5] =?UTF-8?q?fix(cli):=20override=20transitive=20@anthro?= =?UTF-8?q?pic-ai/sdk=20to=20=E2=89=A50.92.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit claude-agent-sdk@0.2.107 declares ^0.81.0 on @anthropic-ai/sdk, which resolves to versions in the GHSA-p7fg-763f-g4gf range (insecure default file permissions in Local Filesystem Memory Tool, moderate severity). Adding an npm override to bump the transitive dep to ^0.92.0 (the patched line). The override is invisible to claude-agent-sdk's own caret constraint but ensures the lockfile resolves to a non-vulnerable version. 0.92.0 was published 2026-04-30, passes the 72h cooldown. Verified: npm audit --omit=dev clean, 159/159 unit tests pass, live smoke against Anthropic still green. Layer 1's CI sibling (cli-release-check.yml's audit job) caught this. --- tools/cli/package-lock.json | 6 +++--- tools/cli/package.json | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/cli/package-lock.json b/tools/cli/package-lock.json index 842a6859..21ff838d 100644 --- a/tools/cli/package-lock.json +++ b/tools/cli/package-lock.json @@ -56,9 +56,9 @@ } }, "node_modules/@anthropic-ai/sdk": { - "version": "0.81.0", - "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.81.0.tgz", - "integrity": "sha512-D4K5PvEV6wPiRtVlVsJHIUhHAmOZ6IT/I9rKlTf84gR7GyyAurPJK7z9BOf/AZqC5d1DhYQGJNKRmV+q8dGhgw==", + "version": "0.92.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.92.0.tgz", + "integrity": "sha512-l653JFC83wCglH8H83t1xpgDurCyPyslYW1maPRdCsfuNuGbLvQjQ81sWd3Go3LWRm0jNspzAhuqAYV8r9joSw==", "license": "MIT", "dependencies": { "json-schema-to-ts": "^3.1.1" diff --git a/tools/cli/package.json b/tools/cli/package.json index 15c1952c..91f188d2 100644 --- a/tools/cli/package.json +++ b/tools/cli/package.json @@ -80,5 +80,8 @@ "tsx": "^4.19.2", "typescript": "^5.7.3", "vitest": "^3.2.4" + }, + "overrides": { + "@anthropic-ai/sdk": "^0.92.0" } }