diff --git a/package-lock.json b/package-lock.json index 9bb4d53d..ade36f6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,8 @@ "version": "0.94.0", "license": "Apache-2.0", "dependencies": { - "@agentclientprotocol/sdk": "2.0.0", - "@anthropic-ai/claude-agent-sdk": "0.3.303", + "@agentclientprotocol/sdk": "2.0.1", + "@anthropic-ai/claude-agent-sdk": "0.3.309", "diff": "9.0.0", "zod": "4.6.7" }, @@ -18,12 +18,12 @@ "claude-agent-acp": "dist/index.js" }, "devDependencies": { - "@anthropic-ai/sdk": "0.135.0", + "@anthropic-ai/sdk": "1.1.0", "@eslint/js": "10.0.1", "@tsconfig/node22": "22.0.6", "@types/node": "26.6.5", - "@typescript-eslint/eslint-plugin": "8.71.2", - "@typescript-eslint/parser": "8.71.2", + "@typescript-eslint/eslint-plugin": "8.72.0", + "@typescript-eslint/parser": "8.72.0", "ajv": "8.20.0", "ajv-formats": "3.0.1", "eslint": "10.13.0", @@ -39,31 +39,31 @@ } }, "node_modules/@agentclientprotocol/sdk": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-2.0.0.tgz", - "integrity": "sha512-Za5gWOPQ44aBOdegDJZ+OjCAPn7POc0cw8BlFJQ1mmUY1OoUWxRi3+QZT4gdZnyEWgKXyfeGRb0Oo1ag9YkQ1w==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-2.0.1.tgz", + "integrity": "sha512-v4E/NcBTGFEKmorGso8ysAjJTkNh5UMJPP4aDznyMNmnP9t10g/aCCo/Djy7RYaYZy5ZROFK3G5cEj9tDgGOTQ==", "license": "Apache-2.0", "peerDependencies": { "zod": "^3.25.76 || ^4.0.0" } }, "node_modules/@anthropic-ai/claude-agent-sdk": { - "version": "0.3.303", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.303.tgz", - "integrity": "sha512-XBql04V40xr+fmGJh8AmIpqRZKFNrs99BzXzzSVlx+uE5NjFCzKmkNKTdMD0DQtDvFJlijOLoh1siaH+au9Psw==", + "version": "0.3.309", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.309.tgz", + "integrity": "sha512-Tou0fXBkxKJDcgT09v3Iv/Jd7bNgapgfAiHxGPctAADPFQhidfhZbcv7at1cVL0Lon5sbs+OzP/pEOigw2TI0A==", "license": "SEE LICENSE IN README.md", "engines": { "node": ">=18.0.0" }, "optionalDependencies": { - "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.303", - "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.303", - "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.303", - "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.303", - "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.303", - "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.303", - "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.303", - "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.303" + "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.309", + "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.309", + "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.309", + "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.309", + "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.309", + "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.309", + "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.309", + "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.309" }, "peerDependencies": { "@anthropic-ai/sdk": ">=0.93.0", @@ -72,9 +72,9 @@ } }, "node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64": { - "version": "0.3.303", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.303.tgz", - "integrity": "sha512-QAWV9Zd7i7FQDaUSwZNVXJirqCS9CSF4aPwbkGwLvLH83qcfFOmnyxWUg1H7dU6tJFLOCyDLQzc3xzUA4dakoA==", + "version": "0.3.309", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.309.tgz", + "integrity": "sha512-qC93iDGEioaXqWsYazcZzNv3hd8d4VHkCFgb+AzvbkCWOzZHnRu1EqF4Iz5kCTLDs4VdMvCa1NkzlUwtTedBVw==", "cpu": [ "arm64" ], @@ -85,9 +85,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-darwin-x64": { - "version": "0.3.303", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.303.tgz", - "integrity": "sha512-o931musaryuq04fMaEjceCEmgsBrLh39WvwsQWmv070h9jXS8EmWRFpdSILv1xrUFXiukRSq8yUDRVzg+FvTug==", + "version": "0.3.309", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.309.tgz", + "integrity": "sha512-RvP0UOcYxn42c1lgByoMufHaMOH86U2ThGGFupOxBKATY4Q6WJd6M1CukQ/qygfgJ8lcxvK8GOOd3SIny4kQ8Q==", "cpu": [ "x64" ], @@ -98,12 +98,15 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64": { - "version": "0.3.303", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.303.tgz", - "integrity": "sha512-c04i9i1BU3j9G3D7XdVzXTdM3/sDpQH+1o8jNcMPnztOTYbNFmH/cacgeX9x3N112r+5VhCEHXGILoe5GxVxeg==", + "version": "0.3.309", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.309.tgz", + "integrity": "sha512-+8rQwzycuXTW2e/C+yotvP/SDiEDHxItdPvIriGAf2ixh7nPRjVuzHOj1tamgVO0J8nmpPvIAO4edzJ7VZCcAg==", "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], "license": "SEE LICENSE IN LICENSE.md", "optional": true, "os": [ @@ -111,12 +114,15 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64-musl": { - "version": "0.3.303", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.303.tgz", - "integrity": "sha512-a/OsLTEx9ly9hC26cXidg9mtTMA00SQnEiTN9P4IPNj64uSp/7uBnlWl0VeUoVFbgKYYq6XrGRcD6F1ilQsYxg==", + "version": "0.3.309", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.309.tgz", + "integrity": "sha512-14ZD9hdUeobw+jr166YvCZyZwSYG3hDWi5S4yQxpSCrRuY/1z4Kl1AfymUlugiN3UT4Q1rif32K6GnjRJBvQdA==", "cpu": [ "arm64" ], + "libc": [ + "musl" + ], "license": "SEE LICENSE IN LICENSE.md", "optional": true, "os": [ @@ -124,12 +130,15 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64": { - "version": "0.3.303", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.303.tgz", - "integrity": "sha512-lsm1sX2+9Wos8glBbn86M8leFuK60LKB1cJdS0b2HiTSwiDCqpUKYRGJNUlW1JdUTwJB5nDv6S8/FOJExm1/tw==", + "version": "0.3.309", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.309.tgz", + "integrity": "sha512-96G8/uTArlvTTg0qGtiP36W76Ug/YT0gMBh8KX7J2RigdOTrk6QkHtUeCzrw6yff5hEIzecN7EWNw6uh9USo4A==", "cpu": [ "x64" ], + "libc": [ + "glibc" + ], "license": "SEE LICENSE IN LICENSE.md", "optional": true, "os": [ @@ -137,12 +146,15 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64-musl": { - "version": "0.3.303", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.303.tgz", - "integrity": "sha512-yixAa3ZOZd1hiI4mpoukzT9TnuDCzSEHyh7pHcbYTRmdRE2y8bAOmI0eiMFJPivnG4iyGhS2C4XNAe6hAjl30w==", + "version": "0.3.309", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.309.tgz", + "integrity": "sha512-9ViOt4MGMiE2h8V+JUPR5l9F0ZTFuhKC3jawIL/MrMfYY1m2Gt3gcMuP7h7YK914a4tmpXrmITWrpTOu1WOZQQ==", "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "SEE LICENSE IN LICENSE.md", "optional": true, "os": [ @@ -150,9 +162,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-win32-arm64": { - "version": "0.3.303", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.303.tgz", - "integrity": "sha512-AnEseiw5E1JF3XRaGIZN880V/i2OxCaTOQJF9F1+oELleSdvLnCUxCE6/baGvaZjrgvffO9YbYChBpgUKj9j7A==", + "version": "0.3.309", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.309.tgz", + "integrity": "sha512-lDsmw5hguDF7KNMG2OvvKlG0Zgs9bKlrX9Gs2Rv/NjLVl0PIy1TUsh7byOsUR4pXwoMU1toyU1CKqBc/Au8hHw==", "cpu": [ "arm64" ], @@ -163,9 +175,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-win32-x64": { - "version": "0.3.303", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.303.tgz", - "integrity": "sha512-j5kABFEQ6x6T5AB/glmn0r9VwZRbzcH+nSEOWglB69ODNfkZA2btjcz9r794+2BLqJ9QAyswiYWcOX4sDz/RmQ==", + "version": "0.3.309", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.309.tgz", + "integrity": "sha512-otGHQimz6F++6SajGqSAKBclRPGTn60cx+8u3dnhMa5yovKZ5SgChFgstFsiDIWr/ZBqpJysvFemSgHX61mlmQ==", "cpu": [ "x64" ], @@ -176,10 +188,10 @@ ] }, "node_modules/@anthropic-ai/sdk": { - "version": "0.135.0", - "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.135.0.tgz", - "integrity": "sha512-WWrdL57JhU5KoynpTjt9GXK6k7ud9nPw2uw/Trn+oBXh6s0KpjhAccWZm2Qxw08ARYG1UDQj5iC+JO42j1rt/g==", - "license": "MIT", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-1.1.0.tgz", + "integrity": "sha512-Op/fKMsfVwFCfObc87leLOFlORE0RjOvLzRzPCWWLI7Ww6bobpKR6YmYC8ZYgulRh+m2a/3/61VUXoWHFtCXIw==", + "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.4.1", "json-schema-to-ts": "^3.1.1", @@ -919,17 +931,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.2.tgz", - "integrity": "sha512-K72/pvT7qpm8q3k8G5u93NCSN1RcLxX5h7Gw0bQpbMXviBHeY6Nx1WEwmk9wP+eKTSQ8ecxvcgt/ZX/rB938xQ==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.72.0.tgz", + "integrity": "sha512-aysKgysPX9XOv/dk95UkvUDe++Q3n3dJPG9CEWT3RUccxfkPJ+Qn6nhKPDhZXU6Ofo9kgwGWwKyQCnZIXTgngg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/type-utils": "8.71.2", - "@typescript-eslint/utils": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", + "@typescript-eslint/scope-manager": "8.72.0", + "@typescript-eslint/type-utils": "8.72.0", + "@typescript-eslint/utils": "8.72.0", + "@typescript-eslint/visitor-keys": "8.72.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -942,22 +954,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.71.2", + "@typescript-eslint/parser": "^8.72.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.2.tgz", - "integrity": "sha512-aTtmZjp/x3gsGHkDs04/1I8kNogBJkpQaeGaN0PfiG43NzDEmW2n+OP5im9wfsvyX0yP1UZWBrAGtDBfH9jEVw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.72.0.tgz", + "integrity": "sha512-0O+x3ynciD6zuXb1CKSu165haQV6ey53DKhHHUnujP7U+XlltJG+/keT0Xhd1HXCze+IHf7Tvt39ovyepX/LNw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", + "@typescript-eslint/scope-manager": "8.72.0", + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/typescript-estree": "8.72.0", + "@typescript-eslint/visitor-keys": "8.72.0", "debug": "^4.4.3" }, "engines": { @@ -973,14 +985,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.2.tgz", - "integrity": "sha512-Pd68GsLVh5ZXlcEccFPdhSOvtHZ/2WU0XsA8zmXOS3F158lVlcTLhfQ6qvtL1RzbMie0Kp8xtbVwAg4nejKPHw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.72.0.tgz", + "integrity": "sha512-bzHngBbmIgzj6TsTjVUCntGx6FFLgE7mPjpO0PzHycOaZHXqS43XnrkFIHRS16LLr/xO6FHSXG3GJFo/F4bSBQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.71.2", - "@typescript-eslint/types": "^8.71.2", + "@typescript-eslint/tsconfig-utils": "^8.72.0", + "@typescript-eslint/types": "^8.72.0", "debug": "^4.4.3" }, "engines": { @@ -995,14 +1007,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.2.tgz", - "integrity": "sha512-YF4wgg5iUX5Obywoac27B56FhozMNFhdJSbh11H5GBAwmBtfyRhmgTQqW9tRNNmHDvsZ2CX6UGzoz+YfYn2Leg==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.72.0.tgz", + "integrity": "sha512-JewPyJOYcXBSAS7PIgufscHOwZqhTGyBRiQJhhuDln66tMchxvvt7nJ90JKKIoOelmdHA3kAQbm9cEUHc4JSEA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2" + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/visitor-keys": "8.72.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1013,9 +1025,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.2.tgz", - "integrity": "sha512-jz49TAWokm/7yWD9/o837nYax9DyALxIPOImdImvVzo6canBCZYzin8zJyqNR5k1j9K1DE0bVvr0XYB+99uAdg==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.72.0.tgz", + "integrity": "sha512-0vbxCf7xLVPSjcOdm6eQbgViH8EDJ8xnl1laLT9yoqSz2YmcSfSg5Vdl0JUvZf6rcuJ0ZivJIuMD4edTg8obaA==", "dev": true, "license": "MIT", "engines": { @@ -1030,15 +1042,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.2.tgz", - "integrity": "sha512-cC8UaalCViJkb3rH/xLIvidEwoFRtMZMUqDjjJMGEKaTFwYRHYBcoczlEGHuvkHEO8svRDrgZ0yQgOArFmwang==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.72.0.tgz", + "integrity": "sha512-gEXxmmbSTSOVTC37IYYvremOM31v+UN2W772bJxmVYPhAOPSUxtacyb7wkm1EhkYKU6KzFJsdU44DCV4to0LWw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2", - "@typescript-eslint/utils": "8.71.2", + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/typescript-estree": "8.72.0", + "@typescript-eslint/utils": "8.72.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -1055,9 +1067,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.2.tgz", - "integrity": "sha512-y5Ukl3oVp7e/VGxqIoEXoeb/Roj71PAJ4WG/N/RGj+eeDvKRLM15kGr9MijLbN0i03S52zxu31Z98E5gWChJKw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.72.0.tgz", + "integrity": "sha512-Adfoy59kxNEjT5E5fnyrp7GpHYuWs8ONbdohu4ez6IU46qDq8LltG90tLmkucZB2uhYL8mqBjtXqGd8yhfjXqQ==", "dev": true, "license": "MIT", "engines": { @@ -1069,16 +1081,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.2.tgz", - "integrity": "sha512-DgNOEsl4pdYzwSL+N/Cl33tX1Hlw3FvId73LnKXfq7jnrF2viOEn7X+P7RBkkSWCVm92gnWd28GIC5vJuLREeA==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.72.0.tgz", + "integrity": "sha512-gwLfFgWcw15tN2KXDCJvxEOQjPn+P3j/n3eSqkZ5sX4VpW9Cosodr+tWwBZRvJT3TcKx6HnPRGZMCNAiP1Xhug==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.71.2", - "@typescript-eslint/tsconfig-utils": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", + "@typescript-eslint/project-service": "8.72.0", + "@typescript-eslint/tsconfig-utils": "8.72.0", + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/visitor-keys": "8.72.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -1097,16 +1109,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.2.tgz", - "integrity": "sha512-RyKa1G1M9rKHDhrk+HJtiF1MvLD5Ux2JW3TSkzw+02pRALdpJb+QzG1Y5em+LvCgzGwgg8H7mBRFKljNz7ImPw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.72.0.tgz", + "integrity": "sha512-0up3oArJZBYnzOaEXKo8DmI43QvMZyPoFEt9LWzRJcyl/RcJjfKKPebknN1VbTgXBf3M/KggUh5uUMdURLnseg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2" + "@typescript-eslint/scope-manager": "8.72.0", + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/typescript-estree": "8.72.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1121,13 +1133,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.2.tgz", - "integrity": "sha512-zozlN0UA32bSG2zkKAgQyRYSbEISVoyU6vvkKYo2aSny74D8Jh4e+POkJ6Lk0dlezZi5x7TtD+88Xb06IB8nhg==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.72.0.tgz", + "integrity": "sha512-E2mroviasaWecDzTGiGMtuEguuLVOeRggnrIn93CJuxYJzQBHbyymlT08aVQydbBal5538o+JkBKXh2sRuCyIA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/types": "8.72.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { diff --git a/package.json b/package.json index 96b7300d..e3114df3 100644 --- a/package.json +++ b/package.json @@ -65,18 +65,18 @@ "node": ">=22" }, "dependencies": { - "@agentclientprotocol/sdk": "2.0.0", - "@anthropic-ai/claude-agent-sdk": "0.3.303", + "@agentclientprotocol/sdk": "2.0.1", + "@anthropic-ai/claude-agent-sdk": "0.3.309", "diff": "9.0.0", "zod": "4.6.7" }, "devDependencies": { - "@anthropic-ai/sdk": "0.135.0", + "@anthropic-ai/sdk": "1.1.0", "@eslint/js": "10.0.1", "@tsconfig/node22": "22.0.6", "@types/node": "26.6.5", - "@typescript-eslint/eslint-plugin": "8.71.2", - "@typescript-eslint/parser": "8.71.2", + "@typescript-eslint/eslint-plugin": "8.72.0", + "@typescript-eslint/parser": "8.72.0", "ajv": "8.20.0", "ajv-formats": "3.0.1", "eslint": "10.13.0", diff --git a/src/acp-agent.ts b/src/acp-agent.ts index e9049160..289b1bd6 100644 --- a/src/acp-agent.ts +++ b/src/acp-agent.ts @@ -5876,9 +5876,28 @@ export class ClaudeAcpAgent { // turn activation and settlement stay driven by echoes/results/idle. // (Raw-mode emission above still forwards these frames.) if ((message as { type: string }).type === "command_lifecycle") { - const frame = message as unknown as { command_uuid: string; state: string }; + const frame = message as unknown as { + command_uuid: string; + state: string; + wakeup_source?: string; + scheduled_for?: number; + }; switch (frame.state) { case "started": { + // CLIs 2.1.307+ (capability lifecycle_wakeup_source_v1) mark a + // command that a scheduler fire started. With no prompt of ours + // open, it starts an autonomous turn: name the fire as its cause, + // whether `session_state_changed` already opened the task or not. + const cause = scheduledFireCause(frame); + if ( + cause && + asyncTasks.enabled && + !session.cancelled && + !session.activeTurn && + !firstUnsettledQueuedTurn() + ) { + await asyncTasks.autonomousTurnStarted(cause); + } // Remember dispatch on the live turn so a cancel() that orphans // it seeds the right state (see Turn.commandStarted)... const queued = findUnsettledTurn(frame.command_uuid); @@ -13973,3 +13992,29 @@ function getMatchingModelUsage(modelUsage: Record, currentMo return { key: bestKey, usage: modelUsage[bestKey] }; } } + +/** + * What a `command_lifecycle` "started" frame says started the command: a + * ScheduleWakeup (dynamic `/loop`) wakeup, with the time it was set for in + * epoch milliseconds, or another scheduled task such as a cron job. Undefined + * for any other command, and for a value this adapter does not know. The time + * is given in UTC because the agent does not know the client's time zone. + */ +function scheduledFireCause(frame: { + wakeup_source?: string; + scheduled_for?: number; +}): string | undefined { + switch (frame.wakeup_source) { + case "loop_wakeup": { + const scheduledFor = + typeof frame.scheduled_for === "number" ? new Date(frame.scheduled_for) : undefined; + return scheduledFor && !Number.isNaN(scheduledFor.getTime()) + ? `A scheduled wakeup fired (set for ${scheduledFor.toISOString()}).` + : "A scheduled wakeup fired."; + } + case "schedule_wakeup": + return "A scheduled task fired."; + default: + return undefined; + } +} diff --git a/src/async-tasks.ts b/src/async-tasks.ts index fb859f69..3c390dc6 100644 --- a/src/async-tasks.ts +++ b/src/async-tasks.ts @@ -458,18 +458,25 @@ export class AsyncTaskRuntime { * example to answer a task notification. ACP v1 has no session state, and * the client already got the stop reason of its last prompt, so this task is * the only sign that the agent works. The tool calls of the turn are in the - * transcript already, so the task is not shown there. Does nothing while - * such a task is open. + * transcript already, so the task is not shown there. + * + * [cause] names what started the turn when Claude Code says so, for example + * "A scheduled wakeup fired." It replaces the description of a task that is + * already open; without it, an open task is left as it is. */ - async autonomousTurnStarted(): Promise { - if (!this.enabled || this.autonomousTurn) return; + async autonomousTurnStarted(cause?: string): Promise { + if (!this.enabled) return; + if (this.autonomousTurn) { + if (cause) await this.publishProgress(this.autonomousTurn, { description: cause }); + return; + } const task = this.task(`autonomous-turn-${randomUUID()}`); task.autonomousTurn = true; task.startedObserved = true; task.name = "Claude is working"; task.taskType = "turn"; task.description = - this.lastNotificationSummary ?? "Claude Code started a turn without a prompt."; + cause ?? this.lastNotificationSummary ?? "Claude Code started a turn without a prompt."; task.showInTranscript = false; this.lastNotificationSummary = undefined; this.autonomousTurn = task; diff --git a/src/subagent-history.ts b/src/subagent-history.ts index 26fc00f0..d807ab7a 100644 --- a/src/subagent-history.ts +++ b/src/subagent-history.ts @@ -292,9 +292,13 @@ function isForkDirectiveMessage(message: { type?: unknown; message?: unknown }): * The transcript of a `subagent_type: "fork"` child without the context it * inherited. A fork transcript starts with a copy of the parent's launching * assistant message (its text, thinking and every tool_use, including the - * Agent call itself), then a user message with a "Fork started — processing - * in background" tool_result for each of those tool_uses and the text - * `…\nYour directive: `. A fork + * Agent call itself), then a user message with a placeholder tool_result for + * each of those tool_uses and the text + * `…\nYour directive: `. Since + * Claude Code 2.1.307 the fork's own Agent call gets "Fork started — that fork + * is you." and the other tool_uses get "This is the parent's call, not + * yours. …"; before that, every one got "Fork started — processing in + * background". Only the directive text is matched here. A fork * launched from inside a subagent also gets a copy of that subagent's history * before them. None of it is the child's own work: replayed as is, the * parent's text and tool calls would show again in the child. diff --git a/src/tests/acp-agent.test.ts b/src/tests/acp-agent.test.ts index 95e63bed..41c196d3 100644 --- a/src/tests/acp-agent.test.ts +++ b/src/tests/acp-agent.test.ts @@ -2269,6 +2269,57 @@ describe("usage Markdown", () => { expect(formatted).not.toContain("lowest"); }); + it("renders each window's recommendations in order, escaped, before its MCP table", () => { + const formatted = formatUsageResponse({ + ...usageResponse, + behaviors: { + ...usageResponse.behaviors, + day: { + ...usageResponse.behaviors.day, + recommendations: [ + { key: "mcp_server", pct: 41, title: "Disable my_server", detail: "/mcp" }, + { key: "effort", pct: 12, title: "Lower effort | max" }, + ], + fix: { keys: ["mcp_server"], messages: ["/mcp disable my_server"] }, + }, + week: { + ...usageResponse.behaviors.week, + mcp_servers: [], + recommendations: [{ key: "agent", pct: 5, title: "Trim the reviewer agent" }], + }, + }, + }); + const day = formatted.slice( + formatted.indexOf("**Last 24h**"), + formatted.indexOf("**Last 7d**"), + ); + expect(day).toContain( + "- **41%** Disable my\\_server · /mcp\n- **12%** Lower effort \\| max\n\n| MCP server |", + ); + expect(formatted).not.toContain("undefined"); + expect(formatted).not.toContain("/mcp disable"); + expect( + formatted.endsWith( + "**Last 7d** · 43 requests · 5 sessions\n\n- **5%** Trim the reviewer agent", + ), + ).toBe(true); + }); + + it("falls back to the CLI text for a malformed recommendation", () => { + expect( + parseUsageResponse({ + ...usageResponse, + behaviors: { + ...usageResponse.behaviors, + day: { + ...usageResponse.behaviors.day, + recommendations: [{ key: "effort", pct: "high", title: "Lower effort" }], + }, + }, + }), + ).toBeNull(); + }); + it("recognizes only exact local usage commands", () => { expect(isUsageCommandText(" /usage ")).toBe(true); expect(isUsageCommandText("/cost")).toBe(false); @@ -3837,7 +3888,8 @@ describe("subagent transcript replay", () => { it("replays a fork child without the launching message and boilerplate it inherited", async () => { // A `subagent_type: "fork"` transcript starts with a copy of the // launching message (same API message id) and a directive message with - // a "Fork started" result for each of its tool_uses. + // a placeholder result for each of its tool_uses, worded as Claude Code + // 2.1.307+ writes them. const launching = [ { type: "text", text: "I'll fork a worker." }, toolUse("toolu_fork", "Agent", { @@ -3850,7 +3902,15 @@ describe("subagent transcript replay", () => { const forkStarted = (id: string) => ({ type: "tool_result", tool_use_id: id, - content: [{ type: "text", text: "Fork started — processing in background" }], + content: [ + { + type: "text", + text: + id === "toolu_fork" + ? "Fork started — that fork is you." + : "This is the parent's call, not yours. It may not have run yet, and its result goes to the parent.", + }, + ], }); const trace = await replayRfd( [ @@ -24163,6 +24223,93 @@ describe("deferred settlement for live background subagents (issues #864/#866)", ]); }); + describe("started by a scheduler fire", () => { + const lifecycleStarted = (fire: { wakeup_source?: string; scheduled_for?: number }) => + ({ + type: "command_lifecycle", + command_uuid: "scheduler-fire", + state: "started", + ...fire, + uuid: randomUUID(), + session_id: "test-session", + }) as any; + + const autonomousTurn = async (fireFrames: (afterRunning: boolean) => any[]) => { + const { agent, asyncTaskUpdates } = await airAgent(); + let wake = () => {}; + const woken = new Promise((resolve) => (wake = resolve)); + injectGeneratorSession(agent, (input) => { + async function* messageGenerator() { + const iter = input[Symbol.asyncIterator](); + yield userEcho((await iter.next()).value); + yield running(); + yield resultMessage(); + yield idle(); + await woken; + yield* fireFrames(false); + yield running(); + yield* fireFrames(true); + yield assistantText("woke up"); + yield resultMessage(); + yield idle(); + } + return messageGenerator(); + }); + await agent.prompt({ sessionId: "test-session", prompt: [{ type: "text", text: "go" }] }); + wake(); + await agent.sessions["test-session"]?.consumer; + return asyncTaskUpdates() + .filter((update) => update.sessionUpdate !== "async_task_state_update") + .map(({ sessionUpdate, description }) => ({ sessionUpdate, description })); + }; + + it("names a ScheduleWakeup fire that arrives before the running state", async () => { + const updates = await autonomousTurn((afterRunning) => + afterRunning + ? [] + : [ + lifecycleStarted({ + wakeup_source: "loop_wakeup", + scheduled_for: 1_790_000_000_000, + }), + ], + ); + expect(updates).toEqual([ + { + sessionUpdate: "async_task_spawned", + description: "A scheduled wakeup fired (set for 2026-09-21T14:13:20.000Z).", + }, + ]); + }); + + it("renames the open task for a scheduled task fire after the running state", async () => { + const updates = await autonomousTurn((afterRunning) => + afterRunning ? [lifecycleStarted({ wakeup_source: "schedule_wakeup" })] : [], + ); + expect(updates).toEqual([ + { + sessionUpdate: "async_task_spawned", + description: "Claude Code started a turn without a prompt.", + }, + { sessionUpdate: "async_task_progress", description: "A scheduled task fired." }, + ]); + }); + + it("leaves the task as before for a started frame without a known wakeup source", async () => { + const updates = await autonomousTurn((afterRunning) => + afterRunning + ? [lifecycleStarted({}), lifecycleStarted({ wakeup_source: "future_source" })] + : [], + ); + expect(updates).toEqual([ + { + sessionUpdate: "async_task_spawned", + description: "Claude Code started a turn without a prompt.", + }, + ]); + }); + }); + it("ends the turn task when a prompt is folded into the turn", async () => { const { agent, updates, asyncTaskUpdates } = await airAgent(); let wake = () => {}; diff --git a/src/tests/subagent-history.test.ts b/src/tests/subagent-history.test.ts index 3c7652fc..11a617f2 100644 --- a/src/tests/subagent-history.test.ts +++ b/src/tests/subagent-history.test.ts @@ -41,7 +41,8 @@ const launch = (uuid: string, launchId: string) => ({ }); /** * The directive message that Claude Code writes after the copy of the launching - * message in a `subagent_type: "fork"` child's transcript. + * message in a `subagent_type: "fork"` child's transcript, with the tool_result + * text of Claude Code before 2.1.307. */ const forkDirective = (uuid: string, launchIds: string[], prompt: string) => ({ ...base, diff --git a/src/usage-markdown.ts b/src/usage-markdown.ts index b3a4fdfa..54361d9d 100644 --- a/src/usage-markdown.ts +++ b/src/usage-markdown.ts @@ -8,10 +8,18 @@ const usageWindowSchema = z .nullable() .optional(); const contributionSchema = z.object({ name: z.string(), pct: percentSchema }); +// Claude Code 2.1.305+ suggests one change per notable source, largest share first. +const recommendationSchema = z.object({ + key: z.string(), + pct: percentSchema, + title: z.string(), + detail: z.string().optional(), +}); const behaviorPeriodSchema = z.object({ request_count: countSchema, session_count: countSchema, mcp_servers: z.array(contributionSchema), + recommendations: z.array(recommendationSchema).optional(), }); const modelUsageSchema = z.object({ inputTokens: countSchema, @@ -133,12 +141,23 @@ function appendContributions( request_count: number; session_count: number; mcp_servers: { name: string; pct: number }[]; + recommendations?: { pct: number; title: string; detail?: string }[]; }, ): void { lines.push( "", `**${label}** · ${period.request_count} requests · ${period.session_count} sessions`, ); + // Rendered in the order Claude Code sends them, as its own `/usage` does. The + // window's `fix` is left out: its messages must be queued at priority "later" + // with `client_composed` set, which an ACP prompt cannot express. + if (period.recommendations?.length) { + lines.push(""); + for (const recommendation of period.recommendations) { + const detail = recommendation.detail ? ` · ${escapeMarkdown(recommendation.detail)}` : ""; + lines.push(`- **${recommendation.pct}%** ${escapeMarkdown(recommendation.title)}${detail}`); + } + } if (period.mcp_servers.length === 0) return; lines.push("", "| MCP server | Usage |", "|:--|--:|"); for (const server of [...period.mcp_servers].sort((a, b) => b.pct - a.pct).slice(0, 3)) {