diff --git a/package-lock.json b/package-lock.json index 833f6ef4..a2df2b50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,24 +9,24 @@ "version": "0.53.0", "license": "Apache-2.0", "dependencies": { - "@agentclientprotocol/sdk": "1.0.0", - "@anthropic-ai/claude-agent-sdk": "0.3.195", + "@agentclientprotocol/sdk": "1.1.0", + "@anthropic-ai/claude-agent-sdk": "0.3.197", "zod": "^3.25.0 || ^4.0.0" }, "bin": { "claude-agent-acp": "dist/index.js" }, "devDependencies": { - "@anthropic-ai/sdk": "0.106.0", + "@anthropic-ai/sdk": "0.108.0", "@eslint/js": "10.0.1", "@tsconfig/node22": "22.0.5", "@types/node": "26.0.1", - "@typescript-eslint/eslint-plugin": "8.62.0", - "@typescript-eslint/parser": "8.62.0", + "@typescript-eslint/eslint-plugin": "8.62.1", + "@typescript-eslint/parser": "8.62.1", "eslint": "10.6.0", "eslint-config-prettier": "10.1.8", "globals": "17.7.0", - "prettier": "3.9.3", + "prettier": "3.9.4", "ts-node": "10.9.2", "typescript": "6.0.3", "vitest": "4.1.9" @@ -36,31 +36,31 @@ } }, "node_modules/@agentclientprotocol/sdk": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-1.0.0.tgz", - "integrity": "sha512-5FHgLbLZhSAq9F+9SU7AOCXTDzaw/IYx/AvMjrZDs/YFZ9ZPxkdn9ti3fSkny0huHfj2hrqF6pqdns9gN5/Fig==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-1.1.0.tgz", + "integrity": "sha512-NT2KqphUJ3w6EksUL51ZhJgIYgq/ZLGcBPkyMKgRSO5PMVwe9DnKKX+Htnvk6KHh6dUuh34UHK4gKp+4te1Mdg==", "license": "Apache-2.0", "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "node_modules/@anthropic-ai/claude-agent-sdk": { - "version": "0.3.195", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.195.tgz", - "integrity": "sha512-FVmXu9pvOMbuBKWrF8YsYQdQ/upOpv5rS8lFAnFO5jbyXT/2hN7kEPd2vd2GJpaMvNcO/KptyQUK5AxjjTz3+w==", + "version": "0.3.197", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.197.tgz", + "integrity": "sha512-XNIi8W1tb+QfMkcK+5kepOC6BsxG8wtupd72H+pIPzIJypVQhHy7FoX+KBMtTRYwtl+5dsjKyABhjWXebeUilw==", "license": "SEE LICENSE IN README.md", "engines": { "node": ">=18.0.0" }, "optionalDependencies": { - "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.195", - "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.195", - "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.195", - "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.195", - "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.195", - "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.195", - "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.195", - "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.195" + "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.197", + "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.197", + "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.197", + "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.197", + "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.197", + "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.197", + "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.197", + "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.197" }, "peerDependencies": { "@anthropic-ai/sdk": ">=0.93.0", @@ -69,9 +69,9 @@ } }, "node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64": { - "version": "0.3.195", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.195.tgz", - "integrity": "sha512-WIMM/8HRCLsTDHFTIwQvvE8WCA/oaMJtdQxsP7iNyfzIGwXbuOyU95V8vYIhZfaO2yaSpbBRncunq4CtR5H4ng==", + "version": "0.3.197", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.197.tgz", + "integrity": "sha512-jC6WvH5Hr6APTfbMjo4nC6LlyMMqbpCMwiHXIw7/AsQXIHQhZ+cRRMesQlV6UFI1l3O53gLZHzsG9cXwfrPHKw==", "cpu": [ "arm64" ], @@ -82,9 +82,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-darwin-x64": { - "version": "0.3.195", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.195.tgz", - "integrity": "sha512-RY7DB+4LXosE0MJ+XELmakfPrDN1YX4lkk9CTDm28jGCVcESRz9kAEqbyaiC48dZcmN9V1NCLutzINGdcr1TBg==", + "version": "0.3.197", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.197.tgz", + "integrity": "sha512-ZQNvGkMrTyatBlHTIQ4w2i2aLBuvq355UP/FDLnVXIH8l23RsL1x/0w9P+dqB7EmY9OZi/cPxSrpskpo+dZWLA==", "cpu": [ "x64" ], @@ -95,9 +95,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64": { - "version": "0.3.195", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.195.tgz", - "integrity": "sha512-JuIq5Fnz/F1snl0aqi1gcuRZqPWoPNrL9dJ0DuievCxKkO8hnEz/Mmn5Zos7x1X8HE//ZnEvmQXoEQEZXonJew==", + "version": "0.3.197", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.197.tgz", + "integrity": "sha512-pWhQgCtAft4EGM4Zn24HRad1a/k2u6oA+2uM/KCdjehfKtooDiHfMNd1yzXY/n9AEBWP0RHB2Vz3mJ30X2pVAg==", "cpu": [ "arm64" ], @@ -111,9 +111,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64-musl": { - "version": "0.3.195", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.195.tgz", - "integrity": "sha512-ZmyBA/AFzhgutcxb7dbhCm6GTjJytwNYXTxJoKE2B3A409WCYccjMqeji6vCMNxyyfylglGo5D8dVMIxW9aoug==", + "version": "0.3.197", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.197.tgz", + "integrity": "sha512-VuIGXsLGK/aqSQ0tTBqqPVNzjefWS5SWnK8mlYyQitT4s5UDzHXJm0UZBTGxRtlcS0e2+QAHKwbGBCq1ZKSXjg==", "cpu": [ "arm64" ], @@ -127,9 +127,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64": { - "version": "0.3.195", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.195.tgz", - "integrity": "sha512-s1lNi1cL93luoqsItH+fNO4KpIhdkvnVhWGGQUQ/8ftwa2gfmcIQnOg1hG8Ks+KzeD3UUQ8L9YEVHVADnFI/9A==", + "version": "0.3.197", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.197.tgz", + "integrity": "sha512-AUccrbdcv4Hy/GteP/gYLjG/zDP+fe2BFtDMctEfRFVz40DazYDcOyW1+nIgSTQtxf5jSTAVVf3cNuXB2CZwlw==", "cpu": [ "x64" ], @@ -143,9 +143,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-linux-x64-musl": { - "version": "0.3.195", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.195.tgz", - "integrity": "sha512-nf8Q/LauB+ZOC6QDjxNhbsvwUtYjKYnaWJLTYFwhkmsLujePnety1AtT/1ubaUoq5AM1j297DhMlYTasa79OUA==", + "version": "0.3.197", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.197.tgz", + "integrity": "sha512-3Tuy7XhD4UIKE4A4RPmKJcbL7Q/3dcB1hEWQt2lKP7c/DlixeEv+tRzvpnFZKhFX2hy0tkBk3QjkozSAacMC/w==", "cpu": [ "x64" ], @@ -159,9 +159,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-win32-arm64": { - "version": "0.3.195", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.195.tgz", - "integrity": "sha512-hbkDE+xPIZzRWm+D+BKrH9uJH6USIZdDIlsyrIlGi3JFHoieYoA1vdUNyldSS9+F3ZqQtfPjr2Qy08IVB6akYA==", + "version": "0.3.197", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.197.tgz", + "integrity": "sha512-Wx8uiAKBenDuL8lWQmrqnX5ppljaH5unQ9cKiCz2/9Kgf09dgnrwbX8n/FhndCZR8PmYw539eWwYVrSVc/bl6w==", "cpu": [ "arm64" ], @@ -172,9 +172,9 @@ ] }, "node_modules/@anthropic-ai/claude-agent-sdk-win32-x64": { - "version": "0.3.195", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.195.tgz", - "integrity": "sha512-av0piEB3X1Dzhpr8A+DqHVZ9y8s1jpn8enzwX0TKKUPBn5IqLTWC7wD6v66aoUgu4f+g4ThZirmDZA6shyPEZQ==", + "version": "0.3.197", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.197.tgz", + "integrity": "sha512-ZXJO/VvR3SI4G0gwthWeFXWdHB5RXPu3rtfGRcKZ/YgtDeW17rQ+LZIJTk2ywzbLb8EvlghR5JPgn293hC179Q==", "cpu": [ "x64" ], @@ -185,9 +185,9 @@ ] }, "node_modules/@anthropic-ai/sdk": { - "version": "0.106.0", - "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.106.0.tgz", - "integrity": "sha512-ufwVvYNDBj2dzOGupBCTaNzBLxqcTnGOzI4z8Wouxlt+mT3J3HuOmatgCy1VmwCHOUueqZ41ERhm0O99OUcbWA==", + "version": "0.108.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.108.0.tgz", + "integrity": "sha512-XBnl7Nszpbzg0aLnOCmdBi0bOU5goAsQ/L+NPNiuUPowDj8Mbzx0vlIIc1M79BjIvmw5nUM5G3jbrCBStT/0fQ==", "license": "MIT", "dependencies": { "json-schema-to-ts": "^3.1.1", @@ -944,17 +944,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.62.0.tgz", - "integrity": "sha512-o+mpz7EYiMzXoySXiKmzlabIvTVqUuK5yLrAedRPRDA0IpPFMUV1IXt6OqljIxX/kumN6EjUYp41Hqelh6p/Dw==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.62.1.tgz", + "integrity": "sha512-4EQM77WgVNxj7OkL/5b/D/xZsw00G577+UriYTC7JF5opcF3T2AuoeY7ueLaZgSVjSgCS6yOAJB5bRGLPSJUzA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.62.0", - "@typescript-eslint/type-utils": "8.62.0", - "@typescript-eslint/utils": "8.62.0", - "@typescript-eslint/visitor-keys": "8.62.0", + "@typescript-eslint/scope-manager": "8.62.1", + "@typescript-eslint/type-utils": "8.62.1", + "@typescript-eslint/utils": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -967,22 +967,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.62.0", + "@typescript-eslint/parser": "^8.62.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.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.62.0.tgz", - "integrity": "sha512-dzHeT2gySzZtLDsuqxU9AkYgIsQoHAHtRBpOqM+Ofzx1Bwrd2RcCjQJ+6iQbsHOIR6NS33bF2W1k3blN1zLDrA==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.62.1.tgz", + "integrity": "sha512-sPhE4iHuJDSvoAiec+Ro8JyXw8f0ql13HFR82P99nCm9GwTEKG0KYLvDe6REk8BCXuit6vJAv/Yxg5ABaNS2rA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.62.0", - "@typescript-eslint/types": "8.62.0", - "@typescript-eslint/typescript-estree": "8.62.0", - "@typescript-eslint/visitor-keys": "8.62.0", + "@typescript-eslint/scope-manager": "8.62.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/typescript-estree": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1", "debug": "^4.4.3" }, "engines": { @@ -998,14 +998,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.62.0.tgz", - "integrity": "sha512-wexnCqiTg7BOGtbLDftYpRWlmLq4xfoMd7BKFR6Y75sZS3QmRKLdN3yWLhmIYgqMmP/OXWpj3H8odkb5nGURCQ==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.62.1.tgz", + "integrity": "sha512-yQ3RgY5RkSBpsNS1Bx/JQEcA24FOSdfGktoyprAr5u18390UQdtVcfnEv4nIrIshNnavlVyZBKxQwT1fIAE6cg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.62.0", - "@typescript-eslint/types": "^8.62.0", + "@typescript-eslint/tsconfig-utils": "^8.62.1", + "@typescript-eslint/types": "^8.62.1", "debug": "^4.4.3" }, "engines": { @@ -1020,14 +1020,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.62.0.tgz", - "integrity": "sha512-1lX38kNxXIRb8mEc3lbq5mdHq1Pf2+U0nFU65KfT18mtPxxl0fvjuEE92mHuXPuCtElJhOrddOpyMlM3Z0umEA==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.62.1.tgz", + "integrity": "sha512-r4d249KbQ1SFdpeStvob8Ih6aPPIzfqllPVOtvhve6ZcpuVcYo5/7zUWckKpHE7StASX4kTKZTLf0WQm/wPkcg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.62.0", - "@typescript-eslint/visitor-keys": "8.62.0" + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1038,9 +1038,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.0.tgz", - "integrity": "sha512-y2GAdB6ykaXUvuspbYnizQc4oDDz0Tz/Yc7iWrXf9mx8vm/L/0vLHCe0tS2boG96Zy+DivnVDQ9ZUEWoHqqx1g==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.1.tgz", + "integrity": "sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g==", "dev": true, "license": "MIT", "engines": { @@ -1055,15 +1055,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.62.0.tgz", - "integrity": "sha512-+g5O3j0w2ldzC86Pv6fvbO/xhAonbJFIdf/MKQ1d30gndlsVzUOE83ldfSE15Qrl9fhFjK6AovHs5Wpp6vx86w==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.62.1.tgz", + "integrity": "sha512-aXM5xlqXiTxPibXB93cLAURfT3rlizf7uMXISCXy66Isr/9hISJx3yDsKl0L7lKa51b8JpFuNKby0/O0pEm9jg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.62.0", - "@typescript-eslint/typescript-estree": "8.62.0", - "@typescript-eslint/utils": "8.62.0", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/typescript-estree": "8.62.1", + "@typescript-eslint/utils": "8.62.1", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -1080,9 +1080,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.62.0.tgz", - "integrity": "sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.62.1.tgz", + "integrity": "sha512-ooCzJFaf+Hg+uG6fA3NRFGuFjlfNlDhBthbv4ZPU/0elCAFUfnyXUvf/WOpHz/jYwSmvU2GkR2LtyUfy1AxZ1Q==", "dev": true, "license": "MIT", "engines": { @@ -1094,16 +1094,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.0.tgz", - "integrity": "sha512-+hVbNxtW64pIcZWDPGbyaKF7vp2IBTVY5ma1blwwksrjdsbdqqEKvJWMGbBofei4F6Dovx1M0RJgoFeNu2279A==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.1.tgz", + "integrity": "sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.62.0", - "@typescript-eslint/tsconfig-utils": "8.62.0", - "@typescript-eslint/types": "8.62.0", - "@typescript-eslint/visitor-keys": "8.62.0", + "@typescript-eslint/project-service": "8.62.1", + "@typescript-eslint/tsconfig-utils": "8.62.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/visitor-keys": "8.62.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -1122,16 +1122,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.62.0.tgz", - "integrity": "sha512-82r66fi9zYwZ+mTq3vKgwjbZ1PVk/DJzrXFLpG6RnBbdvH8TEGVHIs9H4d2drhkOzf0syZuD/OZvvlu6GDbP4g==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.62.1.tgz", + "integrity": "sha512-sHtbPfuKNZCG+ih8SyjjucqRntSVmp8XgL5u6o9mAhiSn8ds5o/M/XdM0abweme2Tln3szOstOrZ9OXitvPh0g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.62.0", - "@typescript-eslint/types": "8.62.0", - "@typescript-eslint/typescript-estree": "8.62.0" + "@typescript-eslint/scope-manager": "8.62.1", + "@typescript-eslint/types": "8.62.1", + "@typescript-eslint/typescript-estree": "8.62.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1146,13 +1146,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.62.0.tgz", - "integrity": "sha512-CY3uyFSRbcQv3nnSv8S0+lDftMVz6P963PoRlxrV7ew/Md564g9ut60PYzdLM5qW4jFn93GBF+Soi90ISAN+GQ==", + "version": "8.62.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.62.1.tgz", + "integrity": "sha512-4g3BLxfdTMy8iZG0MaBkadnlRrCJ74cQiFbyEVMrkwIoqdyaXXQM22cotDvrl4x28wgIZ9rEJRoM+mmhSJpJ1g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.62.0", + "@typescript-eslint/types": "8.62.1", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -3227,9 +3227,9 @@ } }, "node_modules/prettier": { - "version": "3.9.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.3.tgz", - "integrity": "sha512-HWmu+K+zvHNpaMfSnYeqdqrDbR16cuIXaPx8WoHaviQkDJh1/0BNtOZmHVQI5jc3wXv0H1yXc9wjvFdXh+n3hQ==", + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.4.tgz", + "integrity": "sha512-yWG/o/4oJfo036EKAfK6ACAoDOfHeRHx4tuxkfBZiauURiaSmYwlpOr5LQqKtIkRD2z1PLteme2WoxEnj4tHTg==", "dev": true, "license": "MIT", "bin": { @@ -3826,16 +3826,16 @@ } }, "node_modules/vite": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.0.tgz", - "integrity": "sha512-BuJcQK/56NQTWDGn4ABea3q4SSBdNPWwNZKTkkUpcMPnLoquSYH8llRtSUIgoL1KSCpHt5eghLShn50mH36y7Q==", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.2.tgz", + "integrity": "sha512-6YYPbRXTxx6bRXmOn7XdnQAy5DQNHhDgtjhDHI13oe4pY93kkcdGJWxpGwOm++/Wh0QpQhDrpIoVMrmrsI5AGQ==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", - "postcss": "^8.5.15", - "rolldown": "~1.1.2", + "postcss": "^8.5.16", + "rolldown": "~1.1.3", "tinyglobby": "^0.2.17" }, "bin": { diff --git a/package.json b/package.json index a551ea6f..8fa585e7 100644 --- a/package.json +++ b/package.json @@ -63,21 +63,21 @@ "node": ">=22" }, "dependencies": { - "@agentclientprotocol/sdk": "1.0.0", - "@anthropic-ai/claude-agent-sdk": "0.3.195", + "@agentclientprotocol/sdk": "1.1.0", + "@anthropic-ai/claude-agent-sdk": "0.3.197", "zod": "^3.25.0 || ^4.0.0" }, "devDependencies": { - "@anthropic-ai/sdk": "0.106.0", + "@anthropic-ai/sdk": "0.108.0", "@eslint/js": "10.0.1", "@tsconfig/node22": "22.0.5", "@types/node": "26.0.1", - "@typescript-eslint/eslint-plugin": "8.62.0", - "@typescript-eslint/parser": "8.62.0", + "@typescript-eslint/eslint-plugin": "8.62.1", + "@typescript-eslint/parser": "8.62.1", "eslint": "10.6.0", "eslint-config-prettier": "10.1.8", "globals": "17.7.0", - "prettier": "3.9.3", + "prettier": "3.9.4", "ts-node": "10.9.2", "typescript": "6.0.3", "vitest": "4.1.9" diff --git a/src/acp-agent.ts b/src/acp-agent.ts index 71337d35..7314a158 100644 --- a/src/acp-agent.ts +++ b/src/acp-agent.ts @@ -4021,14 +4021,17 @@ export function buildConfigOptions( // but the SDK model list uses IDs like "claude-opus-4-6-1m". const MODEL_CONTEXT_HINT_PATTERN = /\[(\d+m)\]$/i; -// Captures a model family version such as `4-6` or `4.7` so we can keep -// `claude-opus-4-6` from being copied onto the SDK's `opus` alias when that -// alias currently resolves to a different family version (e.g. Opus 4.7). -const MODEL_FAMILY_VERSION_PATTERN = /\b(\d+)[-.](\d+)\b/; +// Captures a model family version: `4-6`/`4.7` for dated generations, or a +// bare `5` for single-number ones like "Sonnet 5". Used to keep a pinned +// `claude-opus-4-6` from matching the `opus` alias once it points at 4.7. +const MODEL_FAMILY_VERSION_PATTERN = /\b(\d+)(?:[-.](\d+))?\b/; function extractModelFamilyVersion(s: string): string | null { - const match = s.match(MODEL_FAMILY_VERSION_PATTERN); - return match ? `${match[1]}.${match[2]}` : null; + // Strip "[1m]"-style context hints first — that digit is context window + // size, not a model generation version. + const match = s.replace(/\[\d+m\]/gi, "").match(MODEL_FAMILY_VERSION_PATTERN); + if (!match) return null; + return match[2] ? `${match[1]}.${match[2]}` : match[1]; } function modelVersionsCompatible(preference: string, candidate: ModelInfo): boolean { @@ -4074,7 +4077,7 @@ function scoreModelMatch(model: ModelInfo, tokens: string[], contextHint?: strin return score; } -function resolveModelPreference(models: ModelInfo[], preference: string): ModelInfo | null { +export function resolveModelPreference(models: ModelInfo[], preference: string): ModelInfo | null { const trimmed = preference.trim(); if (!trimmed) return null; @@ -4089,6 +4092,18 @@ function resolveModelPreference(models: ModelInfo[], preference: string): ModelI ); if (directMatch) return directMatch; + // Exact match on the alias's canonical resolved id (e.g. a pinned + // "claude-sonnet-5" against the "sonnet" row's `resolvedModel`). SDK- + // reported and unambiguous, so it's tried before the fuzzier tiers below. + // "default" is skipped first since it shares a resolvedModel with + // whichever alias the CLI currently recommends — a specific pin should + // land on that named alias, not "default". + const resolvedMatch = + models.find( + (model) => model.value !== "default" && model.resolvedModel?.toLowerCase() === lower, + ) ?? models.find((model) => model.resolvedModel?.toLowerCase() === lower); + if (resolvedMatch) return resolvedMatch; + // Substring match const includesMatch = models.find((model) => { if (!modelVersionsCompatible(trimmed, model)) return false; @@ -4148,7 +4163,10 @@ function resolveSettingsModel( * - The Default option is unaffected by `availableModels` — it always remains * available, even when the allowlist is `[]`. */ -function applyAvailableModelsAllowlist(sdkModels: ModelInfo[], allowlist: string[]): ModelInfo[] { +export function applyAvailableModelsAllowlist( + sdkModels: ModelInfo[], + allowlist: string[], +): ModelInfo[] { // Default is always preserved per the docs. Synthesize one if the SDK // didn't surface it so downstream code (e.g. `getAvailableModels` picking // `models[0]` as a fallback) still has something to work with. diff --git a/src/tests/model-resolution.test.ts b/src/tests/model-resolution.test.ts new file mode 100644 index 00000000..67530fd0 --- /dev/null +++ b/src/tests/model-resolution.test.ts @@ -0,0 +1,118 @@ +import { describe, it, expect } from "vitest"; +import { randomUUID } from "crypto"; +import { query } from "@anthropic-ai/claude-agent-sdk"; +import type { ModelInfo } from "@anthropic-ai/claude-agent-sdk"; +import { resolveModelPreference, applyAvailableModelsAllowlist } from "../acp-agent.js"; + +// Mirrors a real `supportedModels()` response: alias rows carry +// `resolvedModel`, and "Sonnet 5" has no `major.minor` dot unlike older +// "claude-opus-4-6"-style ids. +const LIVE_SHAPED_MODELS: ModelInfo[] = [ + { + value: "default", + resolvedModel: "claude-opus-4-8[1m]", + displayName: "Default (recommended)", + description: "Use the default model (currently Opus 4.8 (1M context))", + }, + { + value: "opus[1m]", + resolvedModel: "claude-opus-4-8[1m]", + displayName: "Opus", + description: "Opus 4.8 with 1M context · Best for everyday, complex tasks", + }, + { + value: "sonnet", + resolvedModel: "claude-sonnet-5", + displayName: "Sonnet", + description: "Sonnet 5 · Efficient for routine tasks", + }, + { + value: "haiku", + resolvedModel: "claude-haiku-4-5-20251001", + displayName: "Haiku", + description: "Haiku 4.5 · Fastest for quick answers", + }, +]; + +describe("resolveModelPreference - resolvedModel matching", () => { + it("matches a preference that equals an alias's resolvedModel exactly", () => { + expect(resolveModelPreference(LIVE_SHAPED_MODELS, "claude-sonnet-5")?.value).toBe("sonnet"); + expect(resolveModelPreference(LIVE_SHAPED_MODELS, "claude-opus-4-8[1m]")?.value).toBe( + "opus[1m]", + ); + expect(resolveModelPreference(LIVE_SHAPED_MODELS, "claude-haiku-4-5-20251001")?.value).toBe( + "haiku", + ); + }); + + it("is case-insensitive", () => { + expect(resolveModelPreference(LIVE_SHAPED_MODELS, "CLAUDE-SONNET-5")?.value).toBe("sonnet"); + }); + + it("still resolves plain aliases via the direct-match tier", () => { + expect(resolveModelPreference(LIVE_SHAPED_MODELS, "sonnet")?.value).toBe("sonnet"); + expect(resolveModelPreference(LIVE_SHAPED_MODELS, "opus[1m]")?.value).toBe("opus[1m]"); + }); + + it("does not let a retired dated id drift onto a same-family alias of a different generation", () => { + expect(resolveModelPreference(LIVE_SHAPED_MODELS, "claude-sonnet-4-6")).toBeNull(); + }); + + // "opus[1m]"'s `value` has no dotted version, just the context-hint digit + // in "[1m]" — unstripped, that reads as version "1" and blocks the match + // before the matcher reaches the description's real "4.8". + it("does not mistake an alias's context-hint suffix for its version", () => { + expect(resolveModelPreference(LIVE_SHAPED_MODELS, "claude-opus-4-8")?.value).toBe("opus[1m]"); + }); + + it("returns null for a preference that matches nothing", () => { + expect(resolveModelPreference(LIVE_SHAPED_MODELS, "claude-gpt-99")).toBeNull(); + }); +}); + +describe("applyAvailableModelsAllowlist - resolvedModel matching", () => { + it("resolves an allowlist entry pinned to a canonical resolvedModel id", () => { + const result = applyAvailableModelsAllowlist(LIVE_SHAPED_MODELS, ["claude-sonnet-5"]); + const entry = result.find((m) => m.value === "claude-sonnet-5"); + expect(entry).toBeDefined(); + expect(entry?.displayName).toBe("Sonnet"); + }); +}); + +// Runs against the real SDK (no mocks) so the fixture above is flagged the +// moment the SDK's actual model list shape drifts from it. Requires a usable +// ANTHROPIC_API_KEY, hence opt-in via RUN_INTEGRATION_TESTS. +describe.skipIf(!process.env.RUN_INTEGRATION_TESTS)("model resolution (real SDK)", () => { + it("every model's resolvedModel (when present) resolves back to that same row", async () => { + const q = query({ prompt: "hi", options: { sessionId: randomUUID() } }); + try { + const models = await q.supportedModels(); + expect(models.length).toBeGreaterThan(0); + + for (const model of models) { + // "default" shares a resolvedModel with the CLI's recommended named + // alias, and resolution intentionally prefers that alias on a tie. + if (!model.resolvedModel || model.value === "default") continue; + const resolved = resolveModelPreference(models, model.resolvedModel); + expect(resolved?.value).toBe(model.value); + } + } finally { + q.return(undefined); + } + }, 30000); + + it("resolves the well-known 'sonnet' and 'opus' aliases to a model bearing their family name", async () => { + const q = query({ prompt: "hi", options: { sessionId: randomUUID() } }); + try { + const models = await q.supportedModels(); + + const sonnet = resolveModelPreference(models, "sonnet"); + expect(sonnet?.resolvedModel?.toLowerCase()).toContain("sonnet"); + + const opus = resolveModelPreference(models, "opus"); + expect(opus?.resolvedModel?.toLowerCase()).toContain("opus"); + } finally { + q.return(undefined); + } + }, 30000); +}); diff --git a/src/tests/tools.test.ts b/src/tests/tools.test.ts index 9c7f527c..f0660e1e 100644 --- a/src/tests/tools.test.ts +++ b/src/tests/tools.test.ts @@ -1614,6 +1614,68 @@ describe("toolInfoFromToolUse - undefined input regression", () => { const info = toolInfoFromToolUse(toolUse, false); expect(info.title).toBe("Update TODOs"); }); + + it("ReportFindings with undefined input should not throw", () => { + const toolUse = { name: "ReportFindings", id: "toolu_findings_undef", input: undefined }; + const info = toolInfoFromToolUse(toolUse, false); + expect(info.title).toBe("Report findings: none found"); + expect(info.content).toEqual([]); + }); +}); + +describe("toolInfoFromToolUse - ReportFindings", () => { + it("should summarize findings count and list each in content", () => { + const toolUse = { + name: "ReportFindings", + id: "toolu_findings_1", + input: { + findings: [ + { + file: "src/foo.ts", + line: 42, + summary: "Off-by-one in loop bound", + failure_scenario: "Empty array → index out of bounds crash", + }, + { + file: "src/bar.ts", + summary: "Unhandled promise rejection", + failure_scenario: "Network failure → unhandled rejection", + }, + ], + }, + }; + + const info = toolInfoFromToolUse(toolUse, false); + + expect(info.kind).toBe("think"); + expect(info.title).toBe("Report 2 findings"); + expect(info.content).toEqual([ + { + type: "content", + content: { type: "text", text: "**src/foo.ts:42** — Off-by-one in loop bound" }, + }, + { + type: "content", + content: { type: "text", text: "**src/bar.ts** — Unhandled promise rejection" }, + }, + ]); + }); + + it("should report a singular title and empty findings array", () => { + const oneFinding = { + name: "ReportFindings", + id: "toolu_findings_2", + input: { findings: [{ file: "src/baz.ts", summary: "Leak", failure_scenario: "..." }] }, + }; + expect(toolInfoFromToolUse(oneFinding, false).title).toBe("Report 1 finding"); + + const noFindings = { + name: "ReportFindings", + id: "toolu_findings_3", + input: { findings: [] }, + }; + expect(toolInfoFromToolUse(noFindings, false).title).toBe("Report findings: none found"); + }); }); describe("planEntries - undefined input regression", () => { diff --git a/src/tools.ts b/src/tools.ts index 1a0de445..1ee2ab88 100644 --- a/src/tools.ts +++ b/src/tools.ts @@ -15,6 +15,7 @@ import { FileWriteInput, GlobInput, GrepInput, + ReportFindingsInput, TaskCreateInput, TaskCreateOutput, TaskUpdateInput, @@ -371,6 +372,25 @@ export function toolInfoFromToolUse( }; } + case "ReportFindings": { + const input = toolUse.input as ReportFindingsInput | undefined; + const findings = input?.findings ?? []; + return { + title: + findings.length === 0 + ? "Report findings: none found" + : `Report ${findings.length} finding${findings.length === 1 ? "" : "s"}`, + kind: "think", + content: findings.map((finding) => ({ + type: "content" as const, + content: { + type: "text" as const, + text: `**${finding.file}${finding.line ? `:${finding.line}` : ""}** — ${finding.summary}`, + }, + })), + }; + } + case "TaskCreate": { const input = toolUse.input as TaskCreateInput | undefined; return {