mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-11-08 10:21:53 +00:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5e1b7fa72 | ||
|
|
960f62d765 | ||
|
|
508453c288 | ||
|
|
8dc8c86426 | ||
|
|
b4b7f561e2 | ||
|
|
41cde99fd7 | ||
|
|
5729c471f9 | ||
|
|
a759e64ef6 | ||
|
|
15fdf26fc7 | ||
|
|
9f38cb67df | ||
|
|
744b2d4112 | ||
|
|
2554c7bf98 | ||
|
|
1c80bf8e56 | ||
|
|
ad3b5fe745 | ||
|
|
794aa84684 | ||
|
|
12d34e64e5 | ||
|
|
59a098c2b5 | ||
|
|
c27e6aec90 | ||
|
|
4f273a20d8 | ||
|
|
b3640599ae | ||
|
|
58549ffe6a | ||
|
|
116f06eab1 | ||
|
|
db6eaaf714 | ||
|
|
d58004a348 | ||
|
|
0525e6dacb | ||
|
|
cc2885f6a9 | ||
|
|
1be5ca57ee | ||
|
|
7de5e4bcca | ||
|
|
85a45b2895 | ||
|
|
d8af943a1e | ||
|
|
7a701623df |
@@ -1,3 +1,3 @@
|
||||
{
|
||||
".": "0.43.0"
|
||||
".": "0.49.0"
|
||||
}
|
||||
|
||||
84
CHANGELOG.md
84
CHANGELOG.md
@@ -1,5 +1,89 @@
|
||||
# Changelog
|
||||
|
||||
## [0.49.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.48.0...v0.49.0) (2026-06-22)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Update to claude-agent-sdk 0.3.185 ([#798](https://github.com/agentclientprotocol/claude-agent-acp/issues/798)) ([8dc8c86](https://github.com/agentclientprotocol/claude-agent-acp/commit/8dc8c864263fa50d03bec7ebff7aee776604cb3d))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Deduplicate streamed assistant blocks by content ([#800](https://github.com/agentclientprotocol/claude-agent-acp/issues/800)) ([960f62d](https://github.com/agentclientprotocol/claude-agent-acp/commit/960f62d76582ae5c9c5575ab66974809049ce1d0))
|
||||
* Infer 1M context from model descriptions ([#799](https://github.com/agentclientprotocol/claude-agent-acp/issues/799)) ([508453c](https://github.com/agentclientprotocol/claude-agent-acp/commit/508453c288b4a12701abd507199e7fa0ab172171))
|
||||
|
||||
## [0.48.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.47.0...v0.48.0) (2026-06-19)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Agent selection dropdown in config options ([#794](https://github.com/agentclientprotocol/claude-agent-acp/issues/794)) ([5729c47](https://github.com/agentclientprotocol/claude-agent-acp/commit/5729c471f92e1d2a191eb2a6d18c2be47821e9ec))
|
||||
* **deps:** bump the minor group with 11 updates ([#787](https://github.com/agentclientprotocol/claude-agent-acp/issues/787)) ([ad3b5fe](https://github.com/agentclientprotocol/claude-agent-acp/commit/ad3b5fe74527f83964695a1e8056d010b981fc79))
|
||||
* Update to claude-agent-sdk 0.3.183 ([#791](https://github.com/agentclientprotocol/claude-agent-acp/issues/791)) ([744b2d4](https://github.com/agentclientprotocol/claude-agent-acp/commit/744b2d41128f67091d4136283594c0db11ea4db5))
|
||||
* Update to new ACP SDK patterns ([#790](https://github.com/agentclientprotocol/claude-agent-acp/issues/790)) ([2554c7b](https://github.com/agentclientprotocol/claude-agent-acp/commit/2554c7bf980472760a6e7810b826f030d2c3af25))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* duplicate assistant text when turn activates mid-message ([#789](https://github.com/agentclientprotocol/claude-agent-acp/issues/789)) ([1c80bf8](https://github.com/agentclientprotocol/claude-agent-acp/commit/1c80bf8e56a9279dc799e7bbdcae87241e99c18b))
|
||||
* Skip empty thinking chunks ([#793](https://github.com/agentclientprotocol/claude-agent-acp/issues/793)) ([15fdf26](https://github.com/agentclientprotocol/claude-agent-acp/commit/15fdf26fc7d3a6c51e89d3e56fc91dd00cb3d7ae))
|
||||
* surface Bash tool image output instead of dropping it ([#617](https://github.com/agentclientprotocol/claude-agent-acp/issues/617)) ([a759e64](https://github.com/agentclientprotocol/claude-agent-acp/commit/a759e64ef6d9b7c5bfe9a6e6b182db835f8ed3b6))
|
||||
|
||||
## [0.47.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.46.0...v0.47.0) (2026-06-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Update to claude-agent-sdk 0.3.179 ([#783](https://github.com/agentclientprotocol/claude-agent-acp/issues/783)) ([59a098c](https://github.com/agentclientprotocol/claude-agent-acp/commit/59a098c2b530bbae034e9a2dfbd31f8b4ef2a4d0))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Duplicate assistant messages in feed ([#785](https://github.com/agentclientprotocol/claude-agent-acp/issues/785)) ([12d34e6](https://github.com/agentclientprotocol/claude-agent-acp/commit/12d34e64e53564602ac1c38a30127e234c5c25ff))
|
||||
|
||||
## [0.46.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.45.1...v0.46.0) (2026-06-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Update to claude-agent-sdk 0.3.178 ([#777](https://github.com/agentclientprotocol/claude-agent-acp/issues/777)) ([58549ff](https://github.com/agentclientprotocol/claude-agent-acp/commit/58549ffe6a8b02ce59894e567407bd4299c11428))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Better handle out of turn events ([#780](https://github.com/agentclientprotocol/claude-agent-acp/issues/780)) ([4f273a2](https://github.com/agentclientprotocol/claude-agent-acp/commit/4f273a20d870c9c69f71556b8e0519f1de30f285))
|
||||
* Forward option details in elicitation meta ([#779](https://github.com/agentclientprotocol/claude-agent-acp/issues/779)) ([b364059](https://github.com/agentclientprotocol/claude-agent-acp/commit/b3640599ae685beecacd93e012d5bbc9dac716f7)), closes [#764](https://github.com/agentclientprotocol/claude-agent-acp/issues/764)
|
||||
|
||||
## [0.45.1](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.45.0...v0.45.1) (2026-06-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix terminal error printing as text instead of terminal output ([#776](https://github.com/agentclientprotocol/claude-agent-acp/issues/776)) ([db6eaaf](https://github.com/agentclientprotocol/claude-agent-acp/commit/db6eaaf71484a321e47093ad65bcf8994943cb31))
|
||||
* Scope custom answers per question ([#774](https://github.com/agentclientprotocol/claude-agent-acp/issues/774)) ([d58004a](https://github.com/agentclientprotocol/claude-agent-acp/commit/d58004a34880e0a76833697319eb2a9efa6a43c7))
|
||||
|
||||
## [0.45.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.44.0...v0.45.0) (2026-06-15)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **deps-dev:** bump the minor group with 3 updates ([#763](https://github.com/agentclientprotocol/claude-agent-acp/issues/763)) ([7de5e4b](https://github.com/agentclientprotocol/claude-agent-acp/commit/7de5e4bcca9bfea70593092060f82bc8abe33e0e))
|
||||
* **deps:** bump @anthropic-ai/claude-agent-sdk to 0.3.177 ([#771](https://github.com/agentclientprotocol/claude-agent-acp/issues/771)) ([1be5ca5](https://github.com/agentclientprotocol/claude-agent-acp/commit/1be5ca57ee772fe90e41126365dc4186a18ad257))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* preserve ANTHROPIC_CUSTOM_MODEL_OPTION when availableModels is set ([#768](https://github.com/agentclientprotocol/claude-agent-acp/issues/768)) ([cc2885f](https://github.com/agentclientprotocol/claude-agent-acp/commit/cc2885f6a9993cf61e759c3c770015f94c218627))
|
||||
|
||||
## [0.44.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.43.0...v0.44.0) (2026-06-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **deps:** bump the minor group with 14 updates ([#758](https://github.com/agentclientprotocol/claude-agent-acp/issues/758)) ([7a70162](https://github.com/agentclientprotocol/claude-agent-acp/commit/7a701623df2e05aec8e552bdfd1cf573413c3471))
|
||||
* **deps:** update to @anthropic-ai/claude-agent-sdk 0.3.170 ([#761](https://github.com/agentclientprotocol/claude-agent-acp/issues/761)) ([d8af943](https://github.com/agentclientprotocol/claude-agent-acp/commit/d8af943a1efef9be27d771cec089d2f1cb56c523))
|
||||
|
||||
## [0.43.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.42.0...v0.43.0) (2026-06-09)
|
||||
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ export default [
|
||||
"default-case": "error",
|
||||
"prefer-const": "error",
|
||||
"no-var": "error",
|
||||
eqeqeq: ["error", "always"],
|
||||
eqeqeq: ["error", "smart"],
|
||||
curly: ["error", "all"],
|
||||
},
|
||||
},
|
||||
|
||||
439
package-lock.json
generated
439
package-lock.json
generated
@@ -1,62 +1,62 @@
|
||||
{
|
||||
"name": "@agentclientprotocol/claude-agent-acp",
|
||||
"version": "0.43.0",
|
||||
"version": "0.49.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@agentclientprotocol/claude-agent-acp",
|
||||
"version": "0.43.0",
|
||||
"version": "0.49.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "0.25.0",
|
||||
"@anthropic-ai/claude-agent-sdk": "0.3.169",
|
||||
"@agentclientprotocol/sdk": "0.28.1",
|
||||
"@anthropic-ai/claude-agent-sdk": "0.3.185",
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"claude-agent-acp": "dist/index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@anthropic-ai/sdk": "0.102.0",
|
||||
"@anthropic-ai/sdk": "0.105.0",
|
||||
"@eslint/js": "10.0.1",
|
||||
"@types/node": "25.9.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.60.1",
|
||||
"@typescript-eslint/parser": "8.60.1",
|
||||
"eslint": "10.4.1",
|
||||
"@types/node": "26.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.61.1",
|
||||
"@typescript-eslint/parser": "8.61.1",
|
||||
"eslint": "10.5.0",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"globals": "17.6.0",
|
||||
"prettier": "3.8.3",
|
||||
"prettier": "3.8.4",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "6.0.3",
|
||||
"vitest": "4.1.8"
|
||||
"vitest": "4.1.9"
|
||||
}
|
||||
},
|
||||
"node_modules/@agentclientprotocol/sdk": {
|
||||
"version": "0.25.0",
|
||||
"resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-0.25.0.tgz",
|
||||
"integrity": "sha512-wU1VgXNtMvdVotX49txc3WJUDV+/QbLpsgjMvFhlRmp37osdLbI7L7y+iwAlQATwfjLxcv1r1p3ZxZBcXlGhcQ==",
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-0.28.1.tgz",
|
||||
"integrity": "sha512-Z2Frs6YtPhnZZ+XwFXyQkRDXY0fn8FjCalEs0W4yUhQnY4TztmNq0/RnfzWdFN3vqT3h0jTz5klzYbZHGxCDyQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk": {
|
||||
"version": "0.3.169",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.169.tgz",
|
||||
"integrity": "sha512-pzsd0BBnlfHwAUfKouSNwDLcCxGDq+lbPZTsIdiNSLw+AQw7mjxPxqnFwd4YH7qw+E3XhlotuihCm01XzcybPQ==",
|
||||
"version": "0.3.185",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.185.tgz",
|
||||
"integrity": "sha512-UDDd0cInvOufmR88btR/Ursnh71sb5scoutNlRS2L0LBdkt7JEqYJ0jt7DnOYHEVhMx8AAcg0eYgvXztcWUnFA==",
|
||||
"license": "SEE LICENSE IN README.md",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.169",
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.169",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.169",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.169",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.169",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.169",
|
||||
"@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.169",
|
||||
"@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.169"
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.185",
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.185",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.185",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.185",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.185",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.185",
|
||||
"@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.185",
|
||||
"@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.185"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@anthropic-ai/sdk": ">=0.93.0",
|
||||
@@ -65,9 +65,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64": {
|
||||
"version": "0.3.169",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.169.tgz",
|
||||
"integrity": "sha512-5PJU3wqfvJUrgUF3H7iroxAGDyliKmq5q8kK+glERf8YZgmPeDMvQL4mGSB0Vf9RgBWS01dCen93TIsN0O8NPQ==",
|
||||
"version": "0.3.185",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.185.tgz",
|
||||
"integrity": "sha512-P2Svxx1IFrS9aw4ylJBtcoJrc/OAOVnDs+o05x4TV7HoHUQUcKZ9XhWOGnadyVT0KLyoktgjyjnaK7Zdtc0Ldg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -78,9 +78,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-darwin-x64": {
|
||||
"version": "0.3.169",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.169.tgz",
|
||||
"integrity": "sha512-1Hzt0QYG7N/ExfPbN/C92YRc3BoDnyQMJpuWLVyI/r0NmKV/se/cZbIygbvQXs2ywoXOB/EyNj/hkVHaC1G22g==",
|
||||
"version": "0.3.185",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.185.tgz",
|
||||
"integrity": "sha512-H69m2hIJawzSkCDNO/CPLQCYvDGdlbZdzGTgGF8/IQuB4O81sv8WSAh6TBXwtFXOgEi4HtrUYlxiFDmTHt7hMA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -91,9 +91,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64": {
|
||||
"version": "0.3.169",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.169.tgz",
|
||||
"integrity": "sha512-J0tyM4t5qxc2/xilsfHqcJv+fyEDhX66Nv+CMXq4mRbquZmMHhbZbh8ryb+BnKYXUeqKX3uoU/J+7K6/fjcY4g==",
|
||||
"version": "0.3.185",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.185.tgz",
|
||||
"integrity": "sha512-KtXMCoprGYTSPb/A0/kjrO+PpDJAFbHhDd8rjqA4izU51OYjTDkahsGCcSTFM2jA8krOhPqzx/SNVuAVWmexwA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -107,9 +107,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64-musl": {
|
||||
"version": "0.3.169",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.169.tgz",
|
||||
"integrity": "sha512-xkmyNdU6f7HXXzgR6IZym7x41bjL3rjGrXf5PAmx9PjdThy476+TrpO1evKUza1zlVmUj4tj/jYKQsV4ER7QFw==",
|
||||
"version": "0.3.185",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.185.tgz",
|
||||
"integrity": "sha512-1GRpKYrg5foomW+qLrxm/k2R/5PEU7RAuEdX65HV6lFMJR3HsGj8qfBq4KCJHTS3r4YdVrFLvPQ/mUqbY6klIA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -123,9 +123,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-linux-x64": {
|
||||
"version": "0.3.169",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.169.tgz",
|
||||
"integrity": "sha512-ktEPBwzXZagt0cntfRLlvNL0sAplt2HOCbR5iBvq2IV5dLvbEOiBjZQArIcSAN7CTQUFqkZs9HzQMdKe5QPwuQ==",
|
||||
"version": "0.3.185",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.185.tgz",
|
||||
"integrity": "sha512-8U5wu6dNcyzRkwoae0Gu5ZHs6lRSu8CXqd9yrilX3fHR9kKICrm76bLu5q2auuSc/8dx6VL5ZXqSzFKIMp//zw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -139,9 +139,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-linux-x64-musl": {
|
||||
"version": "0.3.169",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.169.tgz",
|
||||
"integrity": "sha512-Me8VW91pCKgkct/y1isjKNVt+ZPMPhHk3C7O078UO1bakHD6kuPiMtugcCsg4jmmmuuywXQIQUESRbcf0GluUg==",
|
||||
"version": "0.3.185",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.185.tgz",
|
||||
"integrity": "sha512-YAky0Oez+YYrlcas/xDiaCm9AUX0z1YwM+pnk+CFxEr/ICmc7MbiFsnEIXFLPHaox9bE5iOzw4LS4b/c1tIJRg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -155,9 +155,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-win32-arm64": {
|
||||
"version": "0.3.169",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.169.tgz",
|
||||
"integrity": "sha512-HL9ecP82A/H8aC896Q7ETyl+nLFkMzBHfO0yvK7Lhxbi98CEpqXn3BADTAc5pEgzkO+r18+CDmZdgjTFMvGoTw==",
|
||||
"version": "0.3.185",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.185.tgz",
|
||||
"integrity": "sha512-pJEOaCLQQQWSyBeseR/GAn4eEp4WtMDP/o5yPMuuAsNWeoJXM7cY4j/N3KBE6GZofgnYdWEXILF2uw3SjbtINA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -168,9 +168,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-win32-x64": {
|
||||
"version": "0.3.169",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.169.tgz",
|
||||
"integrity": "sha512-34pBbiKe7FNsY8LHuuTmKujmYko/cBOrKJpk9H+MOot+dSfB/FmIHq9USL17otNal5Droq9lqpezAWPBPv3lAQ==",
|
||||
"version": "0.3.185",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.185.tgz",
|
||||
"integrity": "sha512-/Kf9XneSuIkSHNwrxOVY0XT7RovAEcx5nDASKzku4994cZz54otU5mT2jT6dwevDLEStfgts5x/A4z0AePwVTQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -181,9 +181,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/sdk": {
|
||||
"version": "0.102.0",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.102.0.tgz",
|
||||
"integrity": "sha512-cThh3KcPW3lzkFyTz1cjyhJvOVw45NkLMoowO2ZJ/76CBz44ADUon+NsjEc/PypAkARs72Xu8qxTnx6PAOTQUQ==",
|
||||
"version": "0.105.0",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.105.0.tgz",
|
||||
"integrity": "sha512-sDyu+aM9cE6uZE+HgRjjHRb+qqb87GHZOx+8bE0YlWetdL1YcVLxn8h9ltxGOflyChTe6PMEo50kMQV4cw0hfg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"json-schema-to-ts": "^3.1.1",
|
||||
@@ -521,14 +521,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/wasm-runtime": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz",
|
||||
"integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==",
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.5.tgz",
|
||||
"integrity": "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@tybys/wasm-util": "^0.10.1"
|
||||
"@tybys/wasm-util": "^0.10.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
@@ -642,6 +642,9 @@
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -659,6 +662,9 @@
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -676,6 +682,9 @@
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -693,6 +702,9 @@
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -710,6 +722,9 @@
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -727,6 +742,9 @@
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -905,27 +923,27 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "25.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.2.tgz",
|
||||
"integrity": "sha512-G05zqtJhcDLb8uslf5EjCxXg9G1KQxiV8OS0R26IC//Eoyitzqe8z37I7cqvnZlrlSfgocQRfSn/AHBZJJFyGw==",
|
||||
"version": "26.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.0.tgz",
|
||||
"integrity": "sha512-vf2YFi1iY9lHGwNJMs01biZFbKJkrZR1T6/MlzjhJLPdntOHLhTrDSnSVcdtvjihi4VQNlrFRIxLsDBlQpAipA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": ">=7.24.0 <7.24.7"
|
||||
"undici-types": "~8.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.1.tgz",
|
||||
"integrity": "sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==",
|
||||
"version": "8.61.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.1.tgz",
|
||||
"integrity": "sha512-ZPlVl3PB3et/59Ne0fv/sci6ZXz4T4Hp4nTJ56i/Y0gR89ARb+KphojTq6j+56E5PIezmOIOOWyY+aWQFd+IkQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.12.2",
|
||||
"@typescript-eslint/scope-manager": "8.60.1",
|
||||
"@typescript-eslint/type-utils": "8.60.1",
|
||||
"@typescript-eslint/utils": "8.60.1",
|
||||
"@typescript-eslint/visitor-keys": "8.60.1",
|
||||
"@typescript-eslint/scope-manager": "8.61.1",
|
||||
"@typescript-eslint/type-utils": "8.61.1",
|
||||
"@typescript-eslint/utils": "8.61.1",
|
||||
"@typescript-eslint/visitor-keys": "8.61.1",
|
||||
"ignore": "^7.0.5",
|
||||
"natural-compare": "^1.4.0",
|
||||
"ts-api-utils": "^2.5.0"
|
||||
@@ -938,22 +956,22 @@
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@typescript-eslint/parser": "^8.60.1",
|
||||
"@typescript-eslint/parser": "^8.61.1",
|
||||
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
|
||||
"typescript": ">=4.8.4 <6.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.60.1.tgz",
|
||||
"integrity": "sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==",
|
||||
"version": "8.61.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.1.tgz",
|
||||
"integrity": "sha512-PJ5vePq5/ognBbrIcoC5+SHO5dfpeLPzP9FpLkzWrguoYQEeeSjlJpVwOpo1JRSTEi7dRcwNy4h4dzV70PqHcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.60.1",
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/typescript-estree": "8.60.1",
|
||||
"@typescript-eslint/visitor-keys": "8.60.1",
|
||||
"@typescript-eslint/scope-manager": "8.61.1",
|
||||
"@typescript-eslint/types": "8.61.1",
|
||||
"@typescript-eslint/typescript-estree": "8.61.1",
|
||||
"@typescript-eslint/visitor-keys": "8.61.1",
|
||||
"debug": "^4.4.3"
|
||||
},
|
||||
"engines": {
|
||||
@@ -969,14 +987,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/project-service": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.60.1.tgz",
|
||||
"integrity": "sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==",
|
||||
"version": "8.61.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.1.tgz",
|
||||
"integrity": "sha512-PrC4JYGmR241lYnfhmKGTXkFqv8+ymbTFgSAY0fVXpY82/QkMw5TZPl+vGzuDDU2QYJk9fIDOBTntF+yDv9LEA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/tsconfig-utils": "^8.60.1",
|
||||
"@typescript-eslint/types": "^8.60.1",
|
||||
"@typescript-eslint/tsconfig-utils": "^8.61.1",
|
||||
"@typescript-eslint/types": "^8.61.1",
|
||||
"debug": "^4.4.3"
|
||||
},
|
||||
"engines": {
|
||||
@@ -991,14 +1009,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.60.1.tgz",
|
||||
"integrity": "sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==",
|
||||
"version": "8.61.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.1.tgz",
|
||||
"integrity": "sha512-L2bdIeoQS8FlKAvONAr20w6OcLXeB+qiDKbAooS9A0Ben+iSIkBef0FxqwKWYqt5sa0i4KJtxVyVmhMylKzF5w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/visitor-keys": "8.60.1"
|
||||
"@typescript-eslint/types": "8.61.1",
|
||||
"@typescript-eslint/visitor-keys": "8.61.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -1009,9 +1027,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/tsconfig-utils": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.1.tgz",
|
||||
"integrity": "sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==",
|
||||
"version": "8.61.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.1.tgz",
|
||||
"integrity": "sha512-UN/H4di+OO7EWx2ovME+8t31YO+KVnK0RRKEHR3kOt21/Ay8BOq3M1OMvWs5vNiqcFCYGYoxK3MXPZzmMUE+yg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -1026,15 +1044,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.60.1.tgz",
|
||||
"integrity": "sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==",
|
||||
"version": "8.61.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.1.tgz",
|
||||
"integrity": "sha512-GYRicKmVK0C4fsKgaACaknOUAq9Oa2kwsjnpFhFcS/5p4Ht5IP9OVLbgIgcK4SRk92nVHFluurg1lumD9dBcLw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/typescript-estree": "8.60.1",
|
||||
"@typescript-eslint/utils": "8.60.1",
|
||||
"@typescript-eslint/types": "8.61.1",
|
||||
"@typescript-eslint/typescript-estree": "8.61.1",
|
||||
"@typescript-eslint/utils": "8.61.1",
|
||||
"debug": "^4.4.3",
|
||||
"ts-api-utils": "^2.5.0"
|
||||
},
|
||||
@@ -1051,9 +1069,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.60.1.tgz",
|
||||
"integrity": "sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==",
|
||||
"version": "8.61.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.1.tgz",
|
||||
"integrity": "sha512-G+CRlPqLv7Bz1IZVs03x5K59F1veqL0EJUROAdGhKsEq8qOiRiZbI+HUojPq5l0fEGOKModD9br6lObhB8zkoA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -1065,16 +1083,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.1.tgz",
|
||||
"integrity": "sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==",
|
||||
"version": "8.61.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.1.tgz",
|
||||
"integrity": "sha512-u+oQD3BqYWPc8YV9Zab4vaJElJuwOLPRc10Jm1o/qS+6Qwen14HCWwx0Seo4LnSn2wxea2Ik8DxPt2/FHmuhrg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/project-service": "8.60.1",
|
||||
"@typescript-eslint/tsconfig-utils": "8.60.1",
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/visitor-keys": "8.60.1",
|
||||
"@typescript-eslint/project-service": "8.61.1",
|
||||
"@typescript-eslint/tsconfig-utils": "8.61.1",
|
||||
"@typescript-eslint/types": "8.61.1",
|
||||
"@typescript-eslint/visitor-keys": "8.61.1",
|
||||
"debug": "^4.4.3",
|
||||
"minimatch": "^10.2.2",
|
||||
"semver": "^7.7.3",
|
||||
@@ -1093,16 +1111,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.60.1.tgz",
|
||||
"integrity": "sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==",
|
||||
"version": "8.61.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.1.tgz",
|
||||
"integrity": "sha512-1+P/3Dj6jvtybE1q0HQ6yBt/gq+oKJyLdEv4HdnqasaEXRSYCAsD59mXEVQnM/ULNdQxbX77tdG4jPRjIS6knA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.9.1",
|
||||
"@typescript-eslint/scope-manager": "8.60.1",
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/typescript-estree": "8.60.1"
|
||||
"@typescript-eslint/scope-manager": "8.61.1",
|
||||
"@typescript-eslint/types": "8.61.1",
|
||||
"@typescript-eslint/typescript-estree": "8.61.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -1117,13 +1135,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "8.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.1.tgz",
|
||||
"integrity": "sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==",
|
||||
"version": "8.61.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.1.tgz",
|
||||
"integrity": "sha512-6fJ9MHWtK14C1DSkiMlHUSOmrVebL7150xZJBlJiL62jjhIA4JmOq6flwBgDxIdBKKdoiZRel+dfPD5MLfny3w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.60.1",
|
||||
"@typescript-eslint/types": "8.61.1",
|
||||
"eslint-visitor-keys": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -1148,16 +1166,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/expect": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.8.tgz",
|
||||
"integrity": "sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==",
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.9.tgz",
|
||||
"integrity": "sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "^1.1.0",
|
||||
"@types/chai": "^5.2.2",
|
||||
"@vitest/spy": "4.1.8",
|
||||
"@vitest/utils": "4.1.8",
|
||||
"@vitest/spy": "4.1.9",
|
||||
"@vitest/utils": "4.1.9",
|
||||
"chai": "^6.2.2",
|
||||
"tinyrainbow": "^3.1.0"
|
||||
},
|
||||
@@ -1166,13 +1184,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/mocker": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.8.tgz",
|
||||
"integrity": "sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==",
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.9.tgz",
|
||||
"integrity": "sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/spy": "4.1.8",
|
||||
"@vitest/spy": "4.1.9",
|
||||
"estree-walker": "^3.0.3",
|
||||
"magic-string": "^0.30.21"
|
||||
},
|
||||
@@ -1193,9 +1211,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/pretty-format": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.8.tgz",
|
||||
"integrity": "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==",
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.9.tgz",
|
||||
"integrity": "sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -1206,13 +1224,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/runner": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.8.tgz",
|
||||
"integrity": "sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==",
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.9.tgz",
|
||||
"integrity": "sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/utils": "4.1.8",
|
||||
"@vitest/utils": "4.1.9",
|
||||
"pathe": "^2.0.3"
|
||||
},
|
||||
"funding": {
|
||||
@@ -1220,14 +1238,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/snapshot": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.8.tgz",
|
||||
"integrity": "sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==",
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.9.tgz",
|
||||
"integrity": "sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/pretty-format": "4.1.8",
|
||||
"@vitest/utils": "4.1.8",
|
||||
"@vitest/pretty-format": "4.1.9",
|
||||
"@vitest/utils": "4.1.9",
|
||||
"magic-string": "^0.30.21",
|
||||
"pathe": "^2.0.3"
|
||||
},
|
||||
@@ -1236,9 +1254,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/spy": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.8.tgz",
|
||||
"integrity": "sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==",
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.9.tgz",
|
||||
"integrity": "sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
@@ -1246,13 +1264,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/utils": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.8.tgz",
|
||||
"integrity": "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==",
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.9.tgz",
|
||||
"integrity": "sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/pretty-format": "4.1.8",
|
||||
"@vitest/pretty-format": "4.1.9",
|
||||
"convert-source-map": "^2.0.0",
|
||||
"tinyrainbow": "^3.1.0"
|
||||
},
|
||||
@@ -1275,9 +1293,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.16.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
|
||||
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
|
||||
"version": "8.17.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz",
|
||||
"integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
@@ -1373,21 +1391,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/body-parser": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
|
||||
"integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz",
|
||||
"integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"bytes": "^3.1.2",
|
||||
"content-type": "^1.0.5",
|
||||
"content-type": "^2.0.0",
|
||||
"debug": "^4.4.3",
|
||||
"http-errors": "^2.0.0",
|
||||
"iconv-lite": "^0.7.0",
|
||||
"http-errors": "^2.0.1",
|
||||
"iconv-lite": "^0.7.2",
|
||||
"on-finished": "^2.4.1",
|
||||
"qs": "^6.14.1",
|
||||
"raw-body": "^3.0.1",
|
||||
"type-is": "^2.0.1"
|
||||
"qs": "^6.15.2",
|
||||
"raw-body": "^3.0.2",
|
||||
"type-is": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -1397,6 +1415,20 @@
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/body-parser/node_modules/content-type": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz",
|
||||
"integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "5.0.6",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
|
||||
@@ -1698,11 +1730,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "10.4.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-10.4.1.tgz",
|
||||
"integrity": "sha512-AyIKhnOBuOAdueD7RB3xB+YeAWScb9jHsJBgH2Hcde8InP5JYhqrRR6iTMHyTEwgENK54Cp44e4v8BwNhsuHuw==",
|
||||
"version": "10.5.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-10.5.0.tgz",
|
||||
"integrity": "sha512-1y+7C+vi12bUK1IpZeaV3gsH9fHLBmPvYmPx42pvT/E9yG0IC8g3PUZZgp0+JLJl7ZDK0flc2gc+Aw9dpCvIsQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.2",
|
||||
@@ -2325,9 +2360,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/hono": {
|
||||
"version": "4.12.24",
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.24.tgz",
|
||||
"integrity": "sha512-I36D1s+HgQc55KbhEr4iybfxv/9o1zdpw+XEM6dJa91LqQD0HCoSGdxpRJCZE+aavs87j4V3Ls2OJzq8C/U4iw==",
|
||||
"version": "4.12.26",
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.26.tgz",
|
||||
"integrity": "sha512-uyZtpnYxM9CmQ7QsQknM4zN8EftNqhON1qYeIKM0Se67CCEe2c44xyGURwB0axX2fBDu1dqHrHAc1hmNT8ITkw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
@@ -2673,6 +2708,9 @@
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -2694,6 +2732,9 @@
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -2715,6 +2756,9 @@
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -2736,6 +2780,9 @@
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -2907,9 +2954,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.12",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
|
||||
"integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
|
||||
"version": "3.3.15",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz",
|
||||
"integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -2966,9 +3013,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/obug": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/obug/-/obug-2.1.2.tgz",
|
||||
"integrity": "sha512-AWGB9WFcRXOQs48Z/udjI5ZcZMHXwX8XPByNpOydgcGsDLIzjGizhoMWJyKAWze7AVW/2W1i+/gPX4YtKe5cyg==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/obug/-/obug-2.1.3.tgz",
|
||||
"integrity": "sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
"https://github.com/sponsors/sxzz",
|
||||
@@ -3169,9 +3216,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.8.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz",
|
||||
"integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==",
|
||||
"version": "3.8.4",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.4.tgz",
|
||||
"integrity": "sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
@@ -3319,9 +3366,9 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.8.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz",
|
||||
"integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==",
|
||||
"version": "7.8.5",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
|
||||
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
@@ -3407,15 +3454,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/side-channel": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
|
||||
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
|
||||
"integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"object-inspect": "^1.13.3",
|
||||
"side-channel-list": "^1.0.0",
|
||||
"object-inspect": "^1.13.4",
|
||||
"side-channel-list": "^1.0.1",
|
||||
"side-channel-map": "^1.0.1",
|
||||
"side-channel-weakmap": "^1.0.2"
|
||||
},
|
||||
@@ -3719,9 +3766,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.24.6",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
|
||||
"integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
|
||||
"integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -3841,19 +3888,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vitest": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.8.tgz",
|
||||
"integrity": "sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==",
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.9.tgz",
|
||||
"integrity": "sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/expect": "4.1.8",
|
||||
"@vitest/mocker": "4.1.8",
|
||||
"@vitest/pretty-format": "4.1.8",
|
||||
"@vitest/runner": "4.1.8",
|
||||
"@vitest/snapshot": "4.1.8",
|
||||
"@vitest/spy": "4.1.8",
|
||||
"@vitest/utils": "4.1.8",
|
||||
"@vitest/expect": "4.1.9",
|
||||
"@vitest/mocker": "4.1.9",
|
||||
"@vitest/pretty-format": "4.1.9",
|
||||
"@vitest/runner": "4.1.9",
|
||||
"@vitest/snapshot": "4.1.9",
|
||||
"@vitest/spy": "4.1.9",
|
||||
"@vitest/utils": "4.1.9",
|
||||
"es-module-lexer": "^2.0.0",
|
||||
"expect-type": "^1.3.0",
|
||||
"magic-string": "^0.30.21",
|
||||
@@ -3881,12 +3928,12 @@
|
||||
"@edge-runtime/vm": "*",
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
|
||||
"@vitest/browser-playwright": "4.1.8",
|
||||
"@vitest/browser-preview": "4.1.8",
|
||||
"@vitest/browser-webdriverio": "4.1.8",
|
||||
"@vitest/coverage-istanbul": "4.1.8",
|
||||
"@vitest/coverage-v8": "4.1.8",
|
||||
"@vitest/ui": "4.1.8",
|
||||
"@vitest/browser-playwright": "4.1.9",
|
||||
"@vitest/browser-preview": "4.1.9",
|
||||
"@vitest/browser-webdriverio": "4.1.9",
|
||||
"@vitest/coverage-istanbul": "4.1.9",
|
||||
"@vitest/coverage-v8": "4.1.9",
|
||||
"@vitest/ui": "4.1.9",
|
||||
"happy-dom": "*",
|
||||
"jsdom": "*",
|
||||
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
|
||||
20
package.json
20
package.json
@@ -3,7 +3,7 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"version": "0.43.0",
|
||||
"version": "0.49.0",
|
||||
"description": "An ACP-compatible coding agent powered by the Claude Agent SDK (TypeScript)",
|
||||
"main": "dist/lib.js",
|
||||
"types": "dist/lib.d.ts",
|
||||
@@ -60,22 +60,22 @@
|
||||
"author": "Zed Industries",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "0.25.0",
|
||||
"@anthropic-ai/claude-agent-sdk": "0.3.169",
|
||||
"@agentclientprotocol/sdk": "0.28.1",
|
||||
"@anthropic-ai/claude-agent-sdk": "0.3.185",
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@anthropic-ai/sdk": "0.102.0",
|
||||
"@anthropic-ai/sdk": "0.105.0",
|
||||
"@eslint/js": "10.0.1",
|
||||
"@types/node": "25.9.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.60.1",
|
||||
"@typescript-eslint/parser": "8.60.1",
|
||||
"eslint": "10.4.1",
|
||||
"@types/node": "26.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.61.1",
|
||||
"@typescript-eslint/parser": "8.61.1",
|
||||
"eslint": "10.5.0",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"globals": "17.6.0",
|
||||
"prettier": "3.8.3",
|
||||
"prettier": "3.8.4",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "6.0.3",
|
||||
"vitest": "4.1.8"
|
||||
"vitest": "4.1.9"
|
||||
}
|
||||
}
|
||||
|
||||
1253
src/acp-agent.ts
1253
src/acp-agent.ts
File diff suppressed because it is too large
Load Diff
@@ -116,8 +116,42 @@ function questionFieldKey(index: number): string {
|
||||
return `question_${index}`;
|
||||
}
|
||||
|
||||
/** Form-field key for the optional free-text "custom answer" field. */
|
||||
const CUSTOM_ANSWER_FIELD = "customAnswer";
|
||||
/**
|
||||
* Form-field key for the per-question free-text "custom answer" field that sits
|
||||
* alongside `question_<n>`. Mirrors the first-party clients, where every
|
||||
* question carries its own "Other" box rather than one form-level field.
|
||||
*/
|
||||
function questionCustomFieldKey(index: number): string {
|
||||
return `question_${index}_custom`;
|
||||
}
|
||||
|
||||
/**
|
||||
* `_meta` key under which a bridged enum option carries its structured
|
||||
* `description`/`preview`, since ACP's `EnumOption` has no field for either.
|
||||
* Namespaced like the agent's other `_meta` extensions (`_claude/...`).
|
||||
*/
|
||||
const OPTION_META_KEY = "_claude/askUserQuestionOption";
|
||||
|
||||
/** A single option as supplied by the AskUserQuestion tool. */
|
||||
type AskUserQuestionOption = AskUserQuestion["options"][number];
|
||||
|
||||
/**
|
||||
* Build the `_meta` payload that carries an option's structured `description`
|
||||
* and optional `preview` for clients that can render them as distinct fields.
|
||||
* Returns `undefined` when neither is present, so we don't emit an empty `_meta`.
|
||||
*/
|
||||
function askUserQuestionOptionMeta(
|
||||
option: AskUserQuestionOption,
|
||||
): NonNullable<EnumOption["_meta"]> | undefined {
|
||||
const detail: { description?: string; preview?: string } = {};
|
||||
if (option.description) {
|
||||
detail.description = option.description;
|
||||
}
|
||||
if (option.preview) {
|
||||
detail.preview = option.preview;
|
||||
}
|
||||
return Object.keys(detail).length > 0 ? { [OPTION_META_KEY]: detail } : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the AskUserQuestion tool's questions as an ACP form elicitation.
|
||||
@@ -128,10 +162,11 @@ const CUSTOM_ANSWER_FIELD = "customAnswer";
|
||||
* an array with a titled `anyOf` item enum. The enum `const` is always the
|
||||
* option label, since that is what the tool records as the answer.
|
||||
*
|
||||
* A trailing optional free-text field mirrors the CLI's custom-answer box: the
|
||||
* user can type their own answer instead of (or as well as) picking an option.
|
||||
* Nothing is marked required, so the user can also just skip — matching the
|
||||
* built-in tool, which always offers Skip + a free-text box.
|
||||
* Each question is followed by its own optional free-text "custom answer" field
|
||||
* (`question_<n>_custom`), mirroring the CLI's per-question "Other" box: the
|
||||
* user can type their own answer instead of picking an option, scoped to that
|
||||
* specific question. Nothing is marked required, so the user can also just skip
|
||||
* — matching the built-in tool, which always offers Skip + a free-text box.
|
||||
*/
|
||||
export function askUserQuestionsToCreateRequest(
|
||||
questions: AskUserQuestion[],
|
||||
@@ -142,10 +177,25 @@ export function askUserQuestionsToCreateRequest(
|
||||
const properties: Record<string, ElicitationPropertySchema> = {};
|
||||
|
||||
questions.forEach((question, index) => {
|
||||
const options: EnumOption[] = question.options.map((option) => ({
|
||||
const: option.label,
|
||||
title: option.description ? `${option.label} — ${option.description}` : option.label,
|
||||
}));
|
||||
const options: EnumOption[] = question.options.map((option) => {
|
||||
const enumOption: EnumOption = {
|
||||
const: option.label,
|
||||
// `title` stays a flattened "label — description" string so clients that
|
||||
// only read `const`/`title` still surface the description. Clients that
|
||||
// understand the `_meta` below should prefer its structured fields (and
|
||||
// treat `const` as the clean label) rather than parsing this title.
|
||||
title: option.description ? `${option.label} — ${option.description}` : option.label,
|
||||
};
|
||||
// The SDK option carries a `description` (secondary text) and an optional
|
||||
// `preview` (mockups, code snippets, comparisons shown on focus). Neither
|
||||
// has a structural slot in `EnumOption`, so forward them under ACP's
|
||||
// reserved `_meta` extension point for clients that can render them.
|
||||
const meta = askUserQuestionOptionMeta(option);
|
||||
if (meta) {
|
||||
enumOption._meta = meta;
|
||||
}
|
||||
return enumOption;
|
||||
});
|
||||
|
||||
// For a single question the prompt is carried by `message`, so we don't
|
||||
// repeat it in the field description. With multiple questions each field
|
||||
@@ -156,13 +206,13 @@ export function askUserQuestionsToCreateRequest(
|
||||
properties[questionFieldKey(index)] = question.multiSelect
|
||||
? { type: "array", title, description, items: { anyOf: options } }
|
||||
: { type: "string", title, description, oneOf: options };
|
||||
});
|
||||
|
||||
properties[CUSTOM_ANSWER_FIELD] = {
|
||||
type: "string",
|
||||
title: "Other",
|
||||
description: "Type your own answer instead of choosing an option above (optional).",
|
||||
};
|
||||
properties[questionCustomFieldKey(index)] = {
|
||||
type: "string",
|
||||
title: "Other",
|
||||
description: "Type your own answer instead of choosing an option above (optional).",
|
||||
};
|
||||
});
|
||||
|
||||
const requestedSchema: ElicitationSchema = {
|
||||
type: "object",
|
||||
@@ -190,10 +240,11 @@ export type AskUserQuestionOutcome =
|
||||
*
|
||||
* Selected labels are read back from the indexed form fields and written into
|
||||
* `answers` as a `{ [questionText]: label }` map (comma-joining multi-selects)
|
||||
* — the key shape the tool's own `call()` reads. Free text from the custom-
|
||||
* answer field becomes the tool's top-level `response`. Decline yields empty
|
||||
* answers (the model is told the user skipped rather than the turn aborting);
|
||||
* cancel aborts the tool call.
|
||||
* — the key shape the tool's own `call()` reads. A non-empty per-question
|
||||
* custom-answer field (`question_<n>_custom`) takes precedence over that
|
||||
* question's selection, since the user typed their own answer instead of
|
||||
* picking one. Decline yields empty answers (the model is told the user skipped
|
||||
* rather than the turn aborting); cancel aborts the tool call.
|
||||
*/
|
||||
export function applyAskElicitationResponse(
|
||||
response: CreateElicitationResponse,
|
||||
@@ -213,6 +264,14 @@ export function applyAskElicitationResponse(
|
||||
// stay in sync with what the built-in tool's call() expects to read back.
|
||||
const answers: AskUserQuestionOutput["answers"] = {};
|
||||
questions.forEach((question, index) => {
|
||||
// A typed custom answer wins over the selection: the user chose to write
|
||||
// their own answer for this question instead of picking an option.
|
||||
const custom = content[questionCustomFieldKey(index)];
|
||||
if (typeof custom === "string" && custom.trim() !== "") {
|
||||
answers[question.question] = custom.trim();
|
||||
return;
|
||||
}
|
||||
|
||||
const value = content[questionFieldKey(index)];
|
||||
if (value === undefined || value === null) {
|
||||
return;
|
||||
@@ -224,14 +283,7 @@ export function applyAskElicitationResponse(
|
||||
answers[question.question] = text;
|
||||
});
|
||||
|
||||
const updatedInput: Record<string, unknown> = { ...toolInput, answers };
|
||||
const custom = content[CUSTOM_ANSWER_FIELD];
|
||||
if (typeof custom === "string" && custom.trim() !== "") {
|
||||
const response: AskUserQuestionOutput["response"] = custom;
|
||||
updatedInput.response = response;
|
||||
}
|
||||
|
||||
return { action: "answered", updatedInput };
|
||||
return { action: "answered", updatedInput: { ...toolInput, answers } };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,8 +2,7 @@ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
||||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
import * as os from "node:os";
|
||||
import type { AgentSideConnection } from "@agentclientprotocol/sdk";
|
||||
import type { ClaudeAcpAgent as ClaudeAcpAgentType } from "../acp-agent.js";
|
||||
import type { AcpClient, ClaudeAcpAgent as ClaudeAcpAgentType } from "../acp-agent.js";
|
||||
|
||||
const { querySpy } = vi.hoisted(() => ({
|
||||
querySpy: vi.fn(),
|
||||
@@ -21,13 +20,13 @@ describe("ClaudeAcpAgent settings", () => {
|
||||
let tempDir: string;
|
||||
let originalClaudeConfigDir: string | undefined;
|
||||
|
||||
function createMockClient(): AgentSideConnection {
|
||||
function createMockClient(): AcpClient {
|
||||
return {
|
||||
sessionUpdate: async () => {},
|
||||
requestPermission: async () => ({ outcome: { outcome: "cancelled" } }),
|
||||
readTextFile: async () => ({ content: "" }),
|
||||
writeTextFile: async () => ({}),
|
||||
} as unknown as AgentSideConnection;
|
||||
} as unknown as AcpClient;
|
||||
}
|
||||
|
||||
function mockQuery() {
|
||||
@@ -700,6 +699,118 @@ describe("ClaudeAcpAgent settings", () => {
|
||||
expect(byValue["claude-opus-4-6[1m]"].name).toBe("claude-opus-4-6[1m]");
|
||||
expect(byValue["claude-opus-4-6"].name).toBe("claude-opus-4-6");
|
||||
});
|
||||
|
||||
it("preserves ANTHROPIC_CUSTOM_MODEL_OPTION even when absent from the allowlist", async () => {
|
||||
// Per the model-config docs, ANTHROPIC_CUSTOM_MODEL_OPTION adds an entry
|
||||
// "without replacing the built-in aliases" and "appears at the bottom of
|
||||
// the /model picker", so it is exempt from the availableModels allowlist
|
||||
// (the same way the Default option is "not affected by availableModels").
|
||||
// ACP must match: a slim alias allowlist must not hide the custom model
|
||||
// row, and it appears last, after the allowlisted entries.
|
||||
// https://code.claude.com/docs/en/model-config#add-a-custom-model-option
|
||||
const originalEnv = process.env.ANTHROPIC_CUSTOM_MODEL_OPTION;
|
||||
process.env.ANTHROPIC_CUSTOM_MODEL_OPTION = "claude-opus-4-8[1m]";
|
||||
try {
|
||||
await fs.promises.writeFile(
|
||||
path.join(tempDir, "settings.json"),
|
||||
JSON.stringify({
|
||||
availableModels: ["sonnet", "opus", "haiku"],
|
||||
}),
|
||||
);
|
||||
|
||||
const projectDir = path.join(tempDir, "project");
|
||||
await fs.promises.mkdir(projectDir, { recursive: true });
|
||||
|
||||
mockQueryWithModels([
|
||||
{ value: "default", displayName: "Default", description: "Default model" },
|
||||
{ value: "sonnet", displayName: "Sonnet", description: "Claude Sonnet 4.6" },
|
||||
{ value: "opus", displayName: "Opus", description: "Claude Opus 4.6" },
|
||||
{ value: "haiku", displayName: "Haiku", description: "Claude Haiku 4.5" },
|
||||
{
|
||||
value: "claude-opus-4-8[1m]",
|
||||
displayName: "Opus 4.8",
|
||||
description: "Claude Opus 4.8",
|
||||
},
|
||||
]);
|
||||
|
||||
const { ClaudeAcpAgent } = await import("../acp-agent.js");
|
||||
const agent: ClaudeAcpAgentType = new ClaudeAcpAgent(createMockClient());
|
||||
|
||||
const response = await (agent as any).createSession({
|
||||
cwd: projectDir,
|
||||
mcpServers: [],
|
||||
_meta: { disableBuiltInTools: true },
|
||||
});
|
||||
|
||||
const modelOption = response.configOptions.find((o: any) => o.id === "model");
|
||||
expect(modelOption.options.map((o: any) => o.value)).toEqual([
|
||||
"default",
|
||||
"sonnet",
|
||||
"opus",
|
||||
"haiku",
|
||||
"claude-opus-4-8[1m]",
|
||||
]);
|
||||
const custom = modelOption.options.find((o: any) => o.value === "claude-opus-4-8[1m]");
|
||||
expect(custom.name).toBe("Opus 4.8");
|
||||
expect(custom.description).toBe("Claude Opus 4.8");
|
||||
} finally {
|
||||
if (originalEnv === undefined) {
|
||||
delete process.env.ANTHROPIC_CUSTOM_MODEL_OPTION;
|
||||
} else {
|
||||
process.env.ANTHROPIC_CUSTOM_MODEL_OPTION = originalEnv;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("does not duplicate the custom model option when also in the allowlist", async () => {
|
||||
// If the user lists the custom model's exact ID in availableModels AND it
|
||||
// is set as ANTHROPIC_CUSTOM_MODEL_OPTION, it must appear exactly once.
|
||||
const originalEnv = process.env.ANTHROPIC_CUSTOM_MODEL_OPTION;
|
||||
process.env.ANTHROPIC_CUSTOM_MODEL_OPTION = "claude-opus-4-8[1m]";
|
||||
try {
|
||||
await fs.promises.writeFile(
|
||||
path.join(tempDir, "settings.json"),
|
||||
JSON.stringify({
|
||||
availableModels: ["sonnet", "claude-opus-4-8[1m]"],
|
||||
}),
|
||||
);
|
||||
|
||||
const projectDir = path.join(tempDir, "project");
|
||||
await fs.promises.mkdir(projectDir, { recursive: true });
|
||||
|
||||
mockQueryWithModels([
|
||||
{ value: "default", displayName: "Default", description: "Default model" },
|
||||
{ value: "sonnet", displayName: "Sonnet", description: "Claude Sonnet 4.6" },
|
||||
{
|
||||
value: "claude-opus-4-8[1m]",
|
||||
displayName: "Opus 4.8",
|
||||
description: "Claude Opus 4.8",
|
||||
},
|
||||
]);
|
||||
|
||||
const { ClaudeAcpAgent } = await import("../acp-agent.js");
|
||||
const agent: ClaudeAcpAgentType = new ClaudeAcpAgent(createMockClient());
|
||||
|
||||
const response = await (agent as any).createSession({
|
||||
cwd: projectDir,
|
||||
mcpServers: [],
|
||||
_meta: { disableBuiltInTools: true },
|
||||
});
|
||||
|
||||
const modelOption = response.configOptions.find((o: any) => o.id === "model");
|
||||
expect(modelOption.options.map((o: any) => o.value)).toEqual([
|
||||
"default",
|
||||
"sonnet",
|
||||
"claude-opus-4-8[1m]",
|
||||
]);
|
||||
} finally {
|
||||
if (originalEnv === undefined) {
|
||||
delete process.env.ANTHROPIC_CUSTOM_MODEL_OPTION;
|
||||
} else {
|
||||
process.env.ANTHROPIC_CUSTOM_MODEL_OPTION = originalEnv;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("resolves model aliases like opus[1m] to the correct model", async () => {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,9 @@
|
||||
import { mkdtemp, rm } from "node:fs/promises";
|
||||
import * as os from "node:os";
|
||||
import * as path from "node:path";
|
||||
import { AgentSideConnection, SessionNotification } from "@agentclientprotocol/sdk";
|
||||
import { SessionNotification } from "@agentclientprotocol/sdk";
|
||||
import type { Options } from "@anthropic-ai/claude-agent-sdk";
|
||||
import type { ClaudeAcpAgent as ClaudeAcpAgentType } from "../acp-agent.js";
|
||||
import type { AcpClient, ClaudeAcpAgent as ClaudeAcpAgentType } from "../acp-agent.js";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
let capturedOptions: Options | undefined;
|
||||
@@ -52,7 +52,7 @@ describe("additionalRoots", () => {
|
||||
requestPermission: async () => ({ outcome: { outcome: "cancelled" } }),
|
||||
readTextFile: async () => ({ content: "" }),
|
||||
writeTextFile: async () => ({}),
|
||||
} as unknown as AgentSideConnection);
|
||||
} as unknown as AcpClient);
|
||||
});
|
||||
|
||||
afterEach(
|
||||
|
||||
42
src/tests/agent-discovery.test.ts
Normal file
42
src/tests/agent-discovery.test.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { randomUUID } from "crypto";
|
||||
import { query } from "@anthropic-ai/claude-agent-sdk";
|
||||
import type { SDKUserMessage } from "@anthropic-ai/claude-agent-sdk";
|
||||
import { Pushable } from "../utils.js";
|
||||
import { discoverCustomAgents, BUILTIN_AGENT_NAMES } from "../acp-agent.js";
|
||||
|
||||
// `discoverCustomAgents` distinguishes user/plugin-configured agents from
|
||||
// Claude Code's built-in subagents by name (BUILTIN_AGENT_NAMES), since the
|
||||
// SDK's `AgentInfo` carries no built-in/source flag. That hardcoded set drifts
|
||||
// silently if the SDK changes its default roster: a newly added built-in would
|
||||
// leak into the ACP "Agent" picker as if the user had configured it. This
|
||||
// integration test runs the real SDK so the set is flagged the moment it does.
|
||||
describe.skipIf(!process.env.RUN_INTEGRATION_TESTS)("agent discovery (SDK)", () => {
|
||||
it("BUILTIN_AGENT_NAMES exactly covers the SDK's default agent roster", async () => {
|
||||
const input = new Pushable<SDKUserMessage>();
|
||||
const q = query({
|
||||
prompt: input,
|
||||
options: {
|
||||
systemPrompt: { type: "preset", preset: "claude_code" },
|
||||
sessionId: randomUUID(),
|
||||
// No setting sources → no user/project/local custom agents are loaded,
|
||||
// so `supportedAgents()` reports exactly the intrinsic built-ins
|
||||
// regardless of what the developer has in ~/.claude/agents.
|
||||
settingSources: [],
|
||||
includePartialMessages: true,
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
const reported = (await q.supportedAgents()).map((a) => a.name).sort();
|
||||
expect(reported).toEqual([...BUILTIN_AGENT_NAMES].sort());
|
||||
|
||||
// With the built-ins being the only agents present, discovery surfaces
|
||||
// nothing — the ACP "Agent" picker is correctly omitted.
|
||||
expect(await discoverCustomAgents(q)).toEqual([]);
|
||||
} finally {
|
||||
input.end();
|
||||
q.return(undefined);
|
||||
}
|
||||
}, 30000);
|
||||
});
|
||||
@@ -1,6 +1,5 @@
|
||||
import { describe, expect, it, Mock, vi, afterEach, beforeEach } from "vitest";
|
||||
import { ClaudeAcpAgent } from "../acp-agent.js";
|
||||
import { AgentSideConnection } from "@agentclientprotocol/sdk";
|
||||
import { AcpClient, ClaudeAcpAgent } from "../acp-agent.js";
|
||||
|
||||
const mockQuery = vi.hoisted(() =>
|
||||
vi.fn(() => ({
|
||||
@@ -39,7 +38,7 @@ describe("authorization", () => {
|
||||
async function createAgentMock(): Promise<[ClaudeAcpAgent, Mock]> {
|
||||
const connectionMock = {
|
||||
sessionUpdate: async (_: any) => {},
|
||||
} as AgentSideConnection;
|
||||
} as AcpClient;
|
||||
|
||||
const agent = new ClaudeAcpAgent(connectionMock);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
||||
import { AgentSideConnection, RequestError, SessionNotification } from "@agentclientprotocol/sdk";
|
||||
import { RequestError, SessionNotification } from "@agentclientprotocol/sdk";
|
||||
import type { Options } from "@anthropic-ai/claude-agent-sdk";
|
||||
import type { ClaudeAcpAgent as ClaudeAcpAgentType } from "../acp-agent.js";
|
||||
import type { AcpClient, ClaudeAcpAgent as ClaudeAcpAgentType } from "../acp-agent.js";
|
||||
import * as fs from "node:fs";
|
||||
import * as os from "node:os";
|
||||
import * as path from "node:path";
|
||||
@@ -47,13 +47,13 @@ describe("createSession options merging", () => {
|
||||
let agent: ClaudeAcpAgentType;
|
||||
let ClaudeAcpAgent: typeof ClaudeAcpAgentType;
|
||||
|
||||
function createMockClient(): AgentSideConnection {
|
||||
function createMockClient(): AcpClient {
|
||||
return {
|
||||
sessionUpdate: async (_notification: SessionNotification) => {},
|
||||
requestPermission: async () => ({ outcome: { outcome: "cancelled" } }),
|
||||
readTextFile: async () => ({ content: "" }),
|
||||
writeTextFile: async () => ({}),
|
||||
} as unknown as AgentSideConnection;
|
||||
} as unknown as AcpClient;
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -550,14 +550,15 @@ describe("createSession options merging", () => {
|
||||
});
|
||||
|
||||
it("rejects a cwd that points at a file with invalidParams", async () => {
|
||||
const file = path.join(os.tmpdir(), "claude-acp-cwd-is-a-file.txt");
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "claude-acp-cwd-is-a-file-"));
|
||||
const file = path.join(dir, "not-a-directory.txt");
|
||||
fs.writeFileSync(file, "not a directory");
|
||||
try {
|
||||
await expect(agent.newSession({ cwd: file, mcpServers: [] })).rejects.toMatchObject({
|
||||
code: RequestError.invalidParams().code,
|
||||
});
|
||||
} finally {
|
||||
fs.rmSync(file, { force: true });
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import type { CreateElicitationRequest, CreateElicitationResponse } from "@agentclientprotocol/sdk";
|
||||
import type {
|
||||
CreateElicitationRequest,
|
||||
CreateElicitationResponse,
|
||||
EnumOption,
|
||||
} from "@agentclientprotocol/sdk";
|
||||
import type { ElicitationRequest } from "@anthropic-ai/claude-agent-sdk";
|
||||
import {
|
||||
applyAskElicitationResponse,
|
||||
@@ -19,14 +23,18 @@ const SESSION_ID = "session-1";
|
||||
*/
|
||||
function mkQuestion(
|
||||
question: string,
|
||||
options: Array<{ label: string; description?: string }>,
|
||||
options: Array<{ label: string; description?: string; preview?: string }>,
|
||||
opts: { header?: string; multiSelect?: boolean } = {},
|
||||
): AskUserQuestion {
|
||||
return {
|
||||
question,
|
||||
header: opts.header ?? "",
|
||||
multiSelect: opts.multiSelect ?? false,
|
||||
options: options.map((o) => ({ label: o.label, description: o.description ?? "" })),
|
||||
options: options.map((o) => ({
|
||||
label: o.label,
|
||||
description: o.description ?? "",
|
||||
...(o.preview ? { preview: o.preview } : {}),
|
||||
})),
|
||||
} as AskUserQuestion;
|
||||
}
|
||||
|
||||
@@ -179,7 +187,14 @@ describe("askUserQuestionsToCreateRequest", () => {
|
||||
title: "Library",
|
||||
description: undefined,
|
||||
oneOf: [
|
||||
{ const: "date-fns", title: "date-fns — Lightweight" },
|
||||
{
|
||||
const: "date-fns",
|
||||
title: "date-fns — Lightweight",
|
||||
// Structured description forwarded under `_meta` so clients can render
|
||||
// it as secondary text instead of parsing it out of the title.
|
||||
_meta: { "_claude/askUserQuestionOption": { description: "Lightweight" } },
|
||||
},
|
||||
// No description → no `_meta` emitted.
|
||||
{ const: "luxon", title: "luxon" },
|
||||
],
|
||||
});
|
||||
@@ -187,8 +202,52 @@ describe("askUserQuestionsToCreateRequest", () => {
|
||||
expect(schema.properties?.["Which library?"]).toBeUndefined();
|
||||
});
|
||||
|
||||
it("includes an optional free-text custom-answer field", () => {
|
||||
const questions = [mkQuestion("Which?", [{ label: "A" }, { label: "B" }])];
|
||||
it("forwards option description and preview under _meta for rich clients", () => {
|
||||
const questions = [
|
||||
mkQuestion("Which layout?", [
|
||||
{
|
||||
label: "Grid",
|
||||
description: "Cards in a responsive grid",
|
||||
preview: "```\n[ ] [ ] [ ]\n[ ] [ ] [ ]\n```",
|
||||
},
|
||||
{ label: "List", description: "Stacked rows" },
|
||||
{ label: "Plain" },
|
||||
]),
|
||||
];
|
||||
|
||||
const schema = (
|
||||
askUserQuestionsToCreateRequest(questions, SESSION_ID, undefined) as Extract<
|
||||
CreateElicitationRequest,
|
||||
{ mode: "form" }
|
||||
>
|
||||
).requestedSchema;
|
||||
const oneOf = (schema.properties?.["question_0"] as { oneOf: EnumOption[] }).oneOf;
|
||||
|
||||
// Both description and preview travel structurally; the title still flattens
|
||||
// the description for clients that only read const/title.
|
||||
expect(oneOf[0]).toEqual({
|
||||
const: "Grid",
|
||||
title: "Grid — Cards in a responsive grid",
|
||||
_meta: {
|
||||
"_claude/askUserQuestionOption": {
|
||||
description: "Cards in a responsive grid",
|
||||
preview: "```\n[ ] [ ] [ ]\n[ ] [ ] [ ]\n```",
|
||||
},
|
||||
},
|
||||
});
|
||||
// Description only → preview omitted from _meta.
|
||||
expect(oneOf[1]._meta).toEqual({
|
||||
"_claude/askUserQuestionOption": { description: "Stacked rows" },
|
||||
});
|
||||
// Neither → no _meta at all.
|
||||
expect(oneOf[2]._meta).toBeUndefined();
|
||||
});
|
||||
|
||||
it("includes a per-question optional free-text custom-answer field", () => {
|
||||
const questions = [
|
||||
mkQuestion("Which?", [{ label: "A" }, { label: "B" }]),
|
||||
mkQuestion("What else?", [{ label: "C" }, { label: "D" }]),
|
||||
];
|
||||
const schema = (
|
||||
askUserQuestionsToCreateRequest(questions, SESSION_ID, undefined) as Extract<
|
||||
CreateElicitationRequest,
|
||||
@@ -196,7 +255,15 @@ describe("askUserQuestionsToCreateRequest", () => {
|
||||
>
|
||||
).requestedSchema;
|
||||
|
||||
expect(schema.properties?.["customAnswer"]).toMatchObject({ type: "string", title: "Other" });
|
||||
// Each question gets its own "Other" box, not one shared form-level field.
|
||||
expect(schema.properties?.["question_0_custom"]).toMatchObject({
|
||||
type: "string",
|
||||
title: "Other",
|
||||
});
|
||||
expect(schema.properties?.["question_1_custom"]).toMatchObject({
|
||||
type: "string",
|
||||
title: "Other",
|
||||
});
|
||||
});
|
||||
|
||||
it("builds an array property for multi-select questions and includes per-field question text", () => {
|
||||
@@ -250,10 +317,10 @@ describe("applyAskElicitationResponse", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("maps the free-text custom-answer field to the tool's response", () => {
|
||||
it("folds a per-question custom answer into that question's answer", () => {
|
||||
const response = {
|
||||
action: "accept",
|
||||
content: { question_0: "A", customAnswer: "something else entirely" },
|
||||
content: { question_0: "A", question_1_custom: "something else entirely" },
|
||||
} as CreateElicitationResponse;
|
||||
|
||||
expect(applyAskElicitationResponse(response, toolInput, questions)).toEqual({
|
||||
@@ -261,8 +328,23 @@ describe("applyAskElicitationResponse", () => {
|
||||
updatedInput: {
|
||||
questions,
|
||||
metadata: { source: "test" },
|
||||
answers: { "Single?": "A" },
|
||||
response: "something else entirely",
|
||||
answers: { "Single?": "A", "Multi?": "something else entirely" },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("prefers a question's custom answer over its selection", () => {
|
||||
const response = {
|
||||
action: "accept",
|
||||
content: { question_0: "A", question_0_custom: " my own take " },
|
||||
} as CreateElicitationResponse;
|
||||
|
||||
expect(applyAskElicitationResponse(response, toolInput, questions)).toEqual({
|
||||
action: "answered",
|
||||
updatedInput: {
|
||||
questions,
|
||||
metadata: { source: "test" },
|
||||
answers: { "Single?": "my own take" },
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -270,7 +352,7 @@ describe("applyAskElicitationResponse", () => {
|
||||
it("ignores empty selections and blank custom answers", () => {
|
||||
const response = {
|
||||
action: "accept",
|
||||
content: { question_1: [], customAnswer: " " },
|
||||
content: { question_1: [], question_0_custom: " " },
|
||||
} as CreateElicitationResponse;
|
||||
|
||||
expect(applyAskElicitationResponse(response, toolInput, questions)).toEqual({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, it, expect, beforeEach, vi } from "vitest";
|
||||
import { AgentSideConnection, SessionNotification } from "@agentclientprotocol/sdk";
|
||||
import { SessionNotification } from "@agentclientprotocol/sdk";
|
||||
import type { ModelInfo } from "@anthropic-ai/claude-agent-sdk";
|
||||
import type { ClaudeAcpAgent as ClaudeAcpAgentType } from "../acp-agent.js";
|
||||
import type { AcpClient, ClaudeAcpAgent as ClaudeAcpAgentType } from "../acp-agent.js";
|
||||
|
||||
const { registerHookCallbackSpy } = vi.hoisted(() => ({
|
||||
registerHookCallbackSpy: vi.fn(),
|
||||
@@ -84,7 +84,7 @@ describe("session config options", () => {
|
||||
let setModelSpy: ReturnType<typeof vi.fn>;
|
||||
let applyFlagSettingsSpy: ReturnType<typeof vi.fn>;
|
||||
|
||||
function createMockClient(): AgentSideConnection {
|
||||
function createMockClient(): AcpClient {
|
||||
return {
|
||||
sessionUpdate: async (notification: SessionNotification) => {
|
||||
sessionUpdates.push(notification);
|
||||
@@ -92,7 +92,7 @@ describe("session config options", () => {
|
||||
requestPermission: async () => ({ outcome: { outcome: "cancelled" } }),
|
||||
readTextFile: async () => ({ content: "" }),
|
||||
writeTextFile: async () => ({}),
|
||||
} as unknown as AgentSideConnection;
|
||||
} as unknown as AcpClient;
|
||||
}
|
||||
|
||||
function populateSession() {
|
||||
@@ -216,6 +216,31 @@ describe("session config options", () => {
|
||||
).rejects.toThrow("Invalid value for config option mode: invalid-mode");
|
||||
});
|
||||
|
||||
it("rejects mode and config changes once the query stream has closed (husk session)", async () => {
|
||||
// After an unexpected stream death the session lingers as a husk
|
||||
// (queryClosed=true) so prompt() can answer with a clear error. The
|
||||
// config/mode handlers must do the same rather than calling setModel/
|
||||
// setPermissionMode on the closed query.
|
||||
const session = (agent as unknown as { sessions: Record<string, { queryClosed?: boolean }> })
|
||||
.sessions[SESSION_ID];
|
||||
session.queryClosed = true;
|
||||
|
||||
await expect(
|
||||
agent.setSessionConfigOption({
|
||||
sessionId: SESSION_ID,
|
||||
configId: "model",
|
||||
value: "claude-sonnet-4-6",
|
||||
}),
|
||||
).rejects.toThrow(/start a new session/);
|
||||
await expect(agent.setSessionMode({ sessionId: SESSION_ID, modeId: "plan" })).rejects.toThrow(
|
||||
/start a new session/,
|
||||
);
|
||||
|
||||
// Short-circuited before touching the (closed) query.
|
||||
expect(setModelSpy).not.toHaveBeenCalled();
|
||||
expect(setPermissionModeSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("changes mode, sends current_mode_update but not config_option_update", async () => {
|
||||
await agent.setSessionConfigOption({
|
||||
sessionId: SESSION_ID,
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { randomUUID } from "crypto";
|
||||
import { AgentSideConnection, RequestError, SessionNotification } from "@agentclientprotocol/sdk";
|
||||
import { RequestError, SessionNotification } from "@agentclientprotocol/sdk";
|
||||
import { query, getSessionMessages } from "@anthropic-ai/claude-agent-sdk";
|
||||
import { ClaudeAcpAgent } from "../acp-agent.js";
|
||||
import { AcpClient, ClaudeAcpAgent } from "../acp-agent.js";
|
||||
import { Pushable } from "../utils.js";
|
||||
import type { SDKUserMessage } from "@anthropic-ai/claude-agent-sdk";
|
||||
|
||||
function createMockClient(): AgentSideConnection {
|
||||
function createMockClient(): AcpClient {
|
||||
return {
|
||||
sessionUpdate: async (_notification: SessionNotification) => {},
|
||||
requestPermission: async () => ({ outcome: { outcome: "cancelled" } }),
|
||||
readTextFile: async () => ({ content: "" }),
|
||||
writeTextFile: async () => ({}),
|
||||
} as unknown as AgentSideConnection;
|
||||
} as unknown as AcpClient;
|
||||
}
|
||||
|
||||
describe.skipIf(!process.env.RUN_INTEGRATION_TESTS)("session load/resume lifecycle", () => {
|
||||
@@ -165,7 +165,7 @@ describe.skipIf(!process.env.RUN_INTEGRATION_TESTS)("session load/resume lifecyc
|
||||
requestPermission: async () => ({ outcome: { outcome: "cancelled" } }),
|
||||
readTextFile: async () => ({ content: "" }),
|
||||
writeTextFile: async () => ({}),
|
||||
} as unknown as AgentSideConnection;
|
||||
} as unknown as AcpClient;
|
||||
|
||||
const commandName =
|
||||
"<command-name>/model</command-name>\n <command-message>model</command-message>\n <command-args>opus</command-args>";
|
||||
@@ -274,7 +274,7 @@ describe.skipIf(!process.env.RUN_INTEGRATION_TESTS)("session load/resume lifecyc
|
||||
requestPermission: async () => ({ outcome: { outcome: "cancelled" } }),
|
||||
readTextFile: async () => ({ content: "" }),
|
||||
writeTextFile: async () => ({}),
|
||||
} as unknown as AgentSideConnection;
|
||||
} as unknown as AcpClient;
|
||||
|
||||
// Exact shape from https://github.com/zed-industries/claude-code-acp/issues/579.
|
||||
const concatenated =
|
||||
|
||||
@@ -7,13 +7,26 @@ import * as os from "node:os";
|
||||
describe("SettingsManager", () => {
|
||||
let tempDir: string;
|
||||
let settingsManager: SettingsManager;
|
||||
let originalConfigDir: string | undefined;
|
||||
|
||||
beforeEach(async () => {
|
||||
tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "settings-test-"));
|
||||
// Isolate the user tier. resolveSettings reads the user settings.json from
|
||||
// CLAUDE_CONFIG_DIR at call time; without this it falls back to the real
|
||||
// ~/.claude and the developer's own settings (e.g. availableModels) leak
|
||||
// into the merge, making union-based assertions fail on their machine.
|
||||
originalConfigDir = process.env.CLAUDE_CONFIG_DIR;
|
||||
process.env.CLAUDE_CONFIG_DIR = path.join(tempDir, "user-config");
|
||||
await fs.promises.mkdir(process.env.CLAUDE_CONFIG_DIR, { recursive: true });
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
settingsManager?.dispose();
|
||||
if (originalConfigDir === undefined) {
|
||||
delete process.env.CLAUDE_CONFIG_DIR;
|
||||
} else {
|
||||
process.env.CLAUDE_CONFIG_DIR = originalConfigDir;
|
||||
}
|
||||
await fs.promises.rm(tempDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect, beforeEach } from "vitest";
|
||||
import { AgentSideConnection, ClientCapabilities } from "@agentclientprotocol/sdk";
|
||||
import { ClientCapabilities } from "@agentclientprotocol/sdk";
|
||||
import { ImageBlockParam, ToolResultBlockParam } from "@anthropic-ai/sdk/resources";
|
||||
import {
|
||||
BetaMCPToolResultBlock,
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
BetaBashCodeExecutionResultBlock,
|
||||
BetaBashCodeExecutionToolResultBlockParam,
|
||||
} from "@anthropic-ai/sdk/resources/beta.mjs";
|
||||
import { toAcpNotifications, ToolUseCache, Logger } from "../acp-agent.js";
|
||||
import { AcpClient, toAcpNotifications, ToolUseCache, Logger } from "../acp-agent.js";
|
||||
import {
|
||||
toolUpdateFromToolResult,
|
||||
createPostToolUseHook,
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
} from "../tools.js";
|
||||
|
||||
describe("rawOutput in tool call updates", () => {
|
||||
const mockClient = {} as AgentSideConnection;
|
||||
const mockClient = {} as AcpClient;
|
||||
const mockLogger: Logger = { log: () => {}, error: () => {} };
|
||||
|
||||
it("should include rawOutput with string content for tool_result", () => {
|
||||
@@ -425,7 +425,7 @@ describe("rawOutput in tool call updates", () => {
|
||||
});
|
||||
|
||||
describe("Bash terminal output", () => {
|
||||
const mockClient = {} as AgentSideConnection;
|
||||
const mockClient = {} as AcpClient;
|
||||
const mockLogger: Logger = { log: () => {}, error: () => {} };
|
||||
|
||||
const bashToolUse = {
|
||||
@@ -502,6 +502,23 @@ describe("Bash terminal output", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should route failed commands through the terminal when supportsTerminalOutput is true", () => {
|
||||
const toolResult: ToolResultBlockParam = {
|
||||
type: "tool_result",
|
||||
tool_use_id: "toolu_bash",
|
||||
content: "some error output",
|
||||
is_error: true,
|
||||
};
|
||||
const update = toolUpdateFromToolResult(toolResult, bashToolUse, true);
|
||||
|
||||
expect(update.content).toEqual([{ type: "terminal", terminalId: "toolu_bash" }]);
|
||||
expect(update._meta).toEqual({
|
||||
terminal_info: { terminal_id: "toolu_bash" },
|
||||
terminal_output: { terminal_id: "toolu_bash", data: "some error output" },
|
||||
terminal_exit: { terminal_id: "toolu_bash", exit_code: 1, signal: null },
|
||||
});
|
||||
});
|
||||
|
||||
it("should fall back to stderr when stdout is empty", () => {
|
||||
const toolResult = makeBashResult("", "some error output", 1);
|
||||
const update = toolUpdateFromToolResult(toolResult, bashToolUse, false);
|
||||
@@ -610,10 +627,25 @@ describe("Bash terminal output", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should use error handler when is_error is true (early return before Bash case)", () => {
|
||||
it("should route is_error through the terminal when supportsTerminalOutput is true", () => {
|
||||
const toolResult = makeStringBashResult("command not found: bad_cmd", true);
|
||||
const update = toolUpdateFromToolResult(toolResult, bashToolUse, true);
|
||||
|
||||
// Failed Bash commands skip the early error return and reach the Bash
|
||||
// case so the client receives terminal output with a non-zero exit code
|
||||
// instead of plain markdown details.
|
||||
expect(update.content).toEqual([{ type: "terminal", terminalId: "toolu_bash" }]);
|
||||
expect(update._meta).toEqual({
|
||||
terminal_info: { terminal_id: "toolu_bash" },
|
||||
terminal_output: { terminal_id: "toolu_bash", data: "command not found: bad_cmd" },
|
||||
terminal_exit: { terminal_id: "toolu_bash", exit_code: 1, signal: null },
|
||||
});
|
||||
});
|
||||
|
||||
it("should use error handler when is_error is true and terminal output is unsupported", () => {
|
||||
const toolResult = makeStringBashResult("command not found: bad_cmd", true);
|
||||
const update = toolUpdateFromToolResult(toolResult, bashToolUse, false);
|
||||
|
||||
// is_error with content hits the early error return at the top of
|
||||
// toolUpdateFromToolResult, before reaching the Bash switch case.
|
||||
// So there's no terminal _meta, just error-formatted content.
|
||||
@@ -670,6 +702,77 @@ describe("Bash terminal output", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("with image array tool_result (local Bash image output path)", () => {
|
||||
// The local Bash tool emits image content as
|
||||
// `[{ type: "image", source: { type: "base64", ... } }]` when a
|
||||
// command produces an image (e.g. piping a base64 data URI).
|
||||
const makeImageBashResult = (
|
||||
data: string,
|
||||
media_type: "image/png" | "image/jpeg" | "image/gif" | "image/webp" = "image/png",
|
||||
): ToolResultBlockParam => ({
|
||||
type: "tool_result",
|
||||
tool_use_id: "toolu_bash",
|
||||
content: [
|
||||
{
|
||||
type: "image",
|
||||
source: { type: "base64", media_type, data },
|
||||
} as ImageBlockParam,
|
||||
],
|
||||
});
|
||||
|
||||
it("should surface image content as ACP image content (terminal disabled)", () => {
|
||||
const toolResult = makeImageBashResult("iVBORw0KGgo=");
|
||||
const update = toolUpdateFromToolResult(toolResult, bashToolUse, false);
|
||||
|
||||
expect(update.content).toEqual([
|
||||
{
|
||||
type: "content",
|
||||
content: { type: "image", data: "iVBORw0KGgo=", mimeType: "image/png" },
|
||||
},
|
||||
]);
|
||||
expect(update._meta).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should bypass terminal _meta even when supportsTerminalOutput is true", () => {
|
||||
// Binary content cannot be streamed through the terminal-output
|
||||
// _meta channel, so the fix returns ACP content directly and skips
|
||||
// the terminal info/output/exit triple.
|
||||
const toolResult = makeImageBashResult("iVBORw0KGgo=", "image/jpeg");
|
||||
const update = toolUpdateFromToolResult(toolResult, bashToolUse, true);
|
||||
|
||||
expect(update.content).toEqual([
|
||||
{
|
||||
type: "content",
|
||||
content: { type: "image", data: "iVBORw0KGgo=", mimeType: "image/jpeg" },
|
||||
},
|
||||
]);
|
||||
expect(update._meta).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should still surface multi-block content with text + image mixed", () => {
|
||||
const toolResult: ToolResultBlockParam = {
|
||||
type: "tool_result",
|
||||
tool_use_id: "toolu_bash",
|
||||
content: [
|
||||
{ type: "text", text: "generated:" },
|
||||
{
|
||||
type: "image",
|
||||
source: { type: "base64", media_type: "image/png", data: "AAAA" },
|
||||
} as ImageBlockParam,
|
||||
],
|
||||
};
|
||||
const update = toolUpdateFromToolResult(toolResult, bashToolUse, false);
|
||||
|
||||
expect(update.content).toEqual([
|
||||
{ type: "content", content: { type: "text", text: "generated:" } },
|
||||
{
|
||||
type: "content",
|
||||
content: { type: "image", data: "AAAA", mimeType: "image/png" },
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("toAcpNotifications with clientCapabilities", () => {
|
||||
@@ -897,7 +1000,7 @@ describe("Bash terminal output", () => {
|
||||
sessionUpdate: async (notification: any) => {
|
||||
hookUpdates.push(notification);
|
||||
},
|
||||
} as unknown as AgentSideConnection;
|
||||
} as unknown as AcpClient;
|
||||
|
||||
// Register hook callback by processing tool_use
|
||||
toAcpNotifications(
|
||||
@@ -976,7 +1079,7 @@ describe("Bash terminal output", () => {
|
||||
sessionUpdate: async (notification: any) => {
|
||||
hookUpdates.push(notification);
|
||||
},
|
||||
} as unknown as AgentSideConnection;
|
||||
} as unknown as AcpClient;
|
||||
|
||||
toAcpNotifications(
|
||||
[
|
||||
@@ -1061,7 +1164,7 @@ describe("Bash terminal output", () => {
|
||||
sessionUpdate: async (notification: any) => {
|
||||
hookUpdates.push(notification);
|
||||
},
|
||||
} as unknown as AgentSideConnection;
|
||||
} as unknown as AcpClient;
|
||||
|
||||
toAcpNotifications(
|
||||
[
|
||||
@@ -1115,7 +1218,7 @@ describe("Bash terminal output", () => {
|
||||
sessionUpdate: async (notification: any) => {
|
||||
hookUpdates.push(notification);
|
||||
},
|
||||
} as unknown as AgentSideConnection;
|
||||
} as unknown as AcpClient;
|
||||
|
||||
toAcpNotifications(
|
||||
[
|
||||
@@ -1191,7 +1294,7 @@ describe("Bash terminal output", () => {
|
||||
sessionUpdate: async (notification: any) => {
|
||||
hookUpdates.push(notification);
|
||||
},
|
||||
} as unknown as AgentSideConnection;
|
||||
} as unknown as AcpClient;
|
||||
|
||||
toAcpNotifications(
|
||||
[
|
||||
@@ -1272,7 +1375,7 @@ describe("Bash terminal output", () => {
|
||||
sessionUpdate: async (notification: any) => {
|
||||
hookUpdates.push(notification);
|
||||
},
|
||||
} as unknown as AgentSideConnection;
|
||||
} as unknown as AcpClient;
|
||||
|
||||
// Step 1: Process tool_use chunk — registers the PostToolUse hook callback
|
||||
const toolUseChunk = {
|
||||
@@ -1372,7 +1475,7 @@ describe("Bash terminal output", () => {
|
||||
sessionUpdate: async (notification: any) => {
|
||||
hookUpdates.push(notification);
|
||||
},
|
||||
} as unknown as AgentSideConnection;
|
||||
} as unknown as AcpClient;
|
||||
|
||||
// Process tool_use (registers hook)
|
||||
toAcpNotifications(
|
||||
@@ -1537,7 +1640,7 @@ describe("planEntries - undefined input regression", () => {
|
||||
});
|
||||
|
||||
describe("toAcpNotifications - TodoWrite with undefined input regression", () => {
|
||||
const mockClient = {} as AgentSideConnection;
|
||||
const mockClient = {} as AcpClient;
|
||||
const mockLogger: Logger = { log: () => {}, error: () => {} };
|
||||
|
||||
it("should not throw when TodoWrite tool_use has undefined input", () => {
|
||||
@@ -1672,7 +1775,7 @@ describe("applyTaskCreate / applyTaskUpdate", () => {
|
||||
});
|
||||
|
||||
describe("toAcpNotifications - Task* tools", () => {
|
||||
const mockClient = {} as AgentSideConnection;
|
||||
const mockClient = {} as AcpClient;
|
||||
const mockLogger: Logger = { log: () => {}, error: () => {} };
|
||||
|
||||
it("suppresses tool_call for TaskCreate/TaskUpdate/TaskList/TaskGet on tool_use", () => {
|
||||
|
||||
28
src/tools.ts
28
src/tools.ts
@@ -485,7 +485,8 @@ export function toolUpdateFromToolResult(
|
||||
"is_error" in toolResult &&
|
||||
toolResult.is_error &&
|
||||
toolResult.content &&
|
||||
toolResult.content.length > 0
|
||||
toolResult.content.length > 0 &&
|
||||
!(toolUse?.name === "Bash" && supportsTerminalOutput)
|
||||
) {
|
||||
// Only return errors
|
||||
return toAcpContentUpdate(toolResult.content, true);
|
||||
@@ -529,7 +530,9 @@ export function toolUpdateFromToolResult(
|
||||
// Extract output and exit code from either format:
|
||||
// 1. BetaBashCodeExecutionResultBlock: { type: "bash_code_execution_result", stdout, stderr, return_code }
|
||||
// 2. Plain string content from a regular tool_result
|
||||
// 3. Array content (e.g. [{ type: "text", text: "..." }])
|
||||
// 3. Array content (e.g. [{ type: "text", text: "..." }] for stdout,
|
||||
// or [{ type: "image", source: {...} }] when the local Bash tool
|
||||
// produces an image, e.g. piping a base64 data URI)
|
||||
let output = "";
|
||||
let exitCode = isError ? 1 : 0;
|
||||
|
||||
@@ -544,13 +547,20 @@ export function toolUpdateFromToolResult(
|
||||
exitCode = bashResult.return_code;
|
||||
} else if (typeof result === "string") {
|
||||
output = result;
|
||||
} else if (
|
||||
Array.isArray(result) &&
|
||||
result.length > 0 &&
|
||||
"text" in result[0] &&
|
||||
typeof result[0].text === "string"
|
||||
) {
|
||||
output = result.map((c: any) => c.text).join("\n");
|
||||
} else if (Array.isArray(result) && result.length > 0) {
|
||||
const textOnly = result.every(
|
||||
(c: any) => c && typeof c === "object" && typeof c.text === "string",
|
||||
);
|
||||
if (textOnly) {
|
||||
output = result.map((c: any) => c.text).join("\n");
|
||||
} else {
|
||||
// Image (or mixed non-text) content. Binary payloads can't be
|
||||
// streamed through the terminal-output _meta channel, so bypass
|
||||
// it and surface the blocks as ACP content. This handles the
|
||||
// local Bash tool's image output, which previously failed the
|
||||
// text-only guard and was silently dropped.
|
||||
return toAcpContentUpdate(result, isError);
|
||||
}
|
||||
}
|
||||
|
||||
if (supportsTerminalOutput) {
|
||||
|
||||
Reference in New Issue
Block a user