mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-24 17:15:50 +00:00
feat: 全部类型问题解决
This commit is contained in:
26
bun.lock
26
bun.lock
@@ -4,6 +4,9 @@
|
|||||||
"workspaces": {
|
"workspaces": {
|
||||||
"": {
|
"": {
|
||||||
"name": "claude-code",
|
"name": "claude-code",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/lodash-es": "^4.17.12",
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@alcalzone/ansi-tokenize": "^0.3.0",
|
"@alcalzone/ansi-tokenize": "^0.3.0",
|
||||||
"@ant/claude-for-chrome-mcp": "workspace:*",
|
"@ant/claude-for-chrome-mcp": "workspace:*",
|
||||||
@@ -51,11 +54,18 @@
|
|||||||
"@smithy/node-http-handler": "^4.5.1",
|
"@smithy/node-http-handler": "^4.5.1",
|
||||||
"@types/bun": "^1.3.11",
|
"@types/bun": "^1.3.11",
|
||||||
"@types/cacache": "^20.0.1",
|
"@types/cacache": "^20.0.1",
|
||||||
|
"@types/picomatch": "^4.0.3",
|
||||||
"@types/plist": "^3.0.5",
|
"@types/plist": "^3.0.5",
|
||||||
|
"@types/proper-lockfile": "^4.1.4",
|
||||||
|
"@types/qrcode": "^1.5.6",
|
||||||
"@types/react": "^19.2.14",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-reconciler": "^0.33.0",
|
"@types/react-reconciler": "^0.33.0",
|
||||||
|
"@types/semver": "^7.7.1",
|
||||||
"@types/sharp": "^0.32.0",
|
"@types/sharp": "^0.32.0",
|
||||||
|
"@types/shell-quote": "^1.7.5",
|
||||||
|
"@types/stack-utils": "^2.0.3",
|
||||||
"@types/turndown": "^5.0.6",
|
"@types/turndown": "^5.0.6",
|
||||||
|
"@types/ws": "^8.18.1",
|
||||||
"ajv": "^8.18.0",
|
"ajv": "^8.18.0",
|
||||||
"asciichart": "^1.5.25",
|
"asciichart": "^1.5.25",
|
||||||
"audio-capture-napi": "workspace:*",
|
"audio-capture-napi": "workspace:*",
|
||||||
@@ -986,16 +996,30 @@
|
|||||||
|
|
||||||
"@types/pg-pool": ["@types/pg-pool@2.0.7", "https://registry.npmmirror.com/@types/pg-pool/-/pg-pool-2.0.7.tgz", { "dependencies": { "@types/pg": "*" } }, "sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng=="],
|
"@types/pg-pool": ["@types/pg-pool@2.0.7", "https://registry.npmmirror.com/@types/pg-pool/-/pg-pool-2.0.7.tgz", { "dependencies": { "@types/pg": "*" } }, "sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng=="],
|
||||||
|
|
||||||
|
"@types/picomatch": ["@types/picomatch@4.0.3", "https://registry.npmmirror.com/@types/picomatch/-/picomatch-4.0.3.tgz", {}, "sha512-iG0T6+nYJ9FAPmx9SsUlnwcq1ZVRuCXcVEvWnntoPlrOpwtSTKNDC9uVAxTsC3PUvJ+99n4RpAcNgBbHX3JSnQ=="],
|
||||||
|
|
||||||
"@types/plist": ["@types/plist@3.0.5", "https://registry.npmmirror.com/@types/plist/-/plist-3.0.5.tgz", { "dependencies": { "@types/node": "*", "xmlbuilder": ">=11.0.1" } }, "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA=="],
|
"@types/plist": ["@types/plist@3.0.5", "https://registry.npmmirror.com/@types/plist/-/plist-3.0.5.tgz", { "dependencies": { "@types/node": "*", "xmlbuilder": ">=11.0.1" } }, "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA=="],
|
||||||
|
|
||||||
|
"@types/proper-lockfile": ["@types/proper-lockfile@4.1.4", "https://registry.npmmirror.com/@types/proper-lockfile/-/proper-lockfile-4.1.4.tgz", { "dependencies": { "@types/retry": "*" } }, "sha512-uo2ABllncSqg9F1D4nugVl9v93RmjxF6LJzQLMLDdPaXCUIDPeOJ21Gbqi43xNKzBi/WQ0Q0dICqufzQbMjipQ=="],
|
||||||
|
|
||||||
|
"@types/qrcode": ["@types/qrcode@1.5.6", "https://registry.npmmirror.com/@types/qrcode/-/qrcode-1.5.6.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw=="],
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.2.14", "https://registry.npmmirror.com/@types/react/-/react-19.2.14.tgz", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
"@types/react": ["@types/react@19.2.14", "https://registry.npmmirror.com/@types/react/-/react-19.2.14.tgz", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
||||||
|
|
||||||
"@types/react-dom": ["@types/react-dom@19.2.3", "https://registry.npmmirror.com/@types/react-dom/-/react-dom-19.2.3.tgz", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
"@types/react-dom": ["@types/react-dom@19.2.3", "https://registry.npmmirror.com/@types/react-dom/-/react-dom-19.2.3.tgz", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
||||||
|
|
||||||
"@types/react-reconciler": ["@types/react-reconciler@0.33.0", "https://registry.npmmirror.com/@types/react-reconciler/-/react-reconciler-0.33.0.tgz", { "peerDependencies": { "@types/react": "*" } }, "sha512-HZOXsKT0tGI9LlUw2LuedXsVeB88wFa536vVL0M6vE8zN63nI+sSr1ByxmPToP5K5bukaVscyeCJcF9guVNJ1g=="],
|
"@types/react-reconciler": ["@types/react-reconciler@0.33.0", "https://registry.npmmirror.com/@types/react-reconciler/-/react-reconciler-0.33.0.tgz", { "peerDependencies": { "@types/react": "*" } }, "sha512-HZOXsKT0tGI9LlUw2LuedXsVeB88wFa536vVL0M6vE8zN63nI+sSr1ByxmPToP5K5bukaVscyeCJcF9guVNJ1g=="],
|
||||||
|
|
||||||
|
"@types/retry": ["@types/retry@0.12.5", "https://registry.npmmirror.com/@types/retry/-/retry-0.12.5.tgz", {}, "sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw=="],
|
||||||
|
|
||||||
|
"@types/semver": ["@types/semver@7.7.1", "https://registry.npmmirror.com/@types/semver/-/semver-7.7.1.tgz", {}, "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA=="],
|
||||||
|
|
||||||
"@types/sharp": ["@types/sharp@0.32.0", "https://registry.npmmirror.com/@types/sharp/-/sharp-0.32.0.tgz", { "dependencies": { "sharp": "*" } }, "sha512-OOi3kL+FZDnPhVzsfD37J88FNeZh6gQsGcLc95NbeURRGvmSjeXiDcyWzF2o3yh/gQAUn2uhh/e+CPCa5nwAxw=="],
|
"@types/sharp": ["@types/sharp@0.32.0", "https://registry.npmmirror.com/@types/sharp/-/sharp-0.32.0.tgz", { "dependencies": { "sharp": "*" } }, "sha512-OOi3kL+FZDnPhVzsfD37J88FNeZh6gQsGcLc95NbeURRGvmSjeXiDcyWzF2o3yh/gQAUn2uhh/e+CPCa5nwAxw=="],
|
||||||
|
|
||||||
|
"@types/shell-quote": ["@types/shell-quote@1.7.5", "https://registry.npmmirror.com/@types/shell-quote/-/shell-quote-1.7.5.tgz", {}, "sha512-+UE8GAGRPbJVQDdxi16dgadcBfQ+KG2vgZhV1+3A1XmHbmwcdwhCUwIdy+d3pAGrbvgRoVSjeI9vOWyq376Yzw=="],
|
||||||
|
|
||||||
|
"@types/stack-utils": ["@types/stack-utils@2.0.3", "https://registry.npmmirror.com/@types/stack-utils/-/stack-utils-2.0.3.tgz", {}, "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="],
|
||||||
|
|
||||||
"@types/tedious": ["@types/tedious@4.0.14", "https://registry.npmmirror.com/@types/tedious/-/tedious-4.0.14.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw=="],
|
"@types/tedious": ["@types/tedious@4.0.14", "https://registry.npmmirror.com/@types/tedious/-/tedious-4.0.14.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw=="],
|
||||||
|
|
||||||
"@types/turndown": ["@types/turndown@5.0.6", "https://registry.npmmirror.com/@types/turndown/-/turndown-5.0.6.tgz", {}, "sha512-ru00MoyeeouE5BX4gRL+6m/BsDfbRayOskWqUvh7CLGW+UXxHQItqALa38kKnOiZPqJrtzJUgAC2+F0rL1S4Pg=="],
|
"@types/turndown": ["@types/turndown@5.0.6", "https://registry.npmmirror.com/@types/turndown/-/turndown-5.0.6.tgz", {}, "sha512-ru00MoyeeouE5BX4gRL+6m/BsDfbRayOskWqUvh7CLGW+UXxHQItqALa38kKnOiZPqJrtzJUgAC2+F0rL1S4Pg=="],
|
||||||
@@ -1004,6 +1028,8 @@
|
|||||||
|
|
||||||
"@types/wrap-ansi": ["@types/wrap-ansi@3.0.0", "https://registry.npmmirror.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", {}, "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g=="],
|
"@types/wrap-ansi": ["@types/wrap-ansi@3.0.0", "https://registry.npmmirror.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", {}, "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g=="],
|
||||||
|
|
||||||
|
"@types/ws": ["@types/ws@8.18.1", "https://registry.npmmirror.com/@types/ws/-/ws-8.18.1.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
|
||||||
|
|
||||||
"@typespec/ts-http-runtime": ["@typespec/ts-http-runtime@0.3.4", "https://registry.npmmirror.com/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.4.tgz", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" } }, "sha512-CI0NhTrz4EBaa0U+HaaUZrJhPoso8sG7ZFya8uQoBA57fjzrjRSv87ekCjLZOFExN+gXE/z0xuN2QfH4H2HrLQ=="],
|
"@typespec/ts-http-runtime": ["@typespec/ts-http-runtime@0.3.4", "https://registry.npmmirror.com/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.4.tgz", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" } }, "sha512-CI0NhTrz4EBaa0U+HaaUZrJhPoso8sG7ZFya8uQoBA57fjzrjRSv87ekCjLZOFExN+gXE/z0xuN2QfH4H2HrLQ=="],
|
||||||
|
|
||||||
"@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="],
|
"@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="],
|
||||||
|
|||||||
15
package.json
15
package.json
@@ -53,9 +53,10 @@
|
|||||||
"docs:dev": "npx mintlify dev",
|
"docs:dev": "npx mintlify dev",
|
||||||
"rcs": "bun run scripts/rcs.ts"
|
"rcs": "bun run scripts/rcs.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {},
|
"dependencies": {
|
||||||
|
"@types/lodash-es": "^4.17.12"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"openai": "^6.33.0",
|
|
||||||
"@alcalzone/ansi-tokenize": "^0.3.0",
|
"@alcalzone/ansi-tokenize": "^0.3.0",
|
||||||
"@ant/claude-for-chrome-mcp": "workspace:*",
|
"@ant/claude-for-chrome-mcp": "workspace:*",
|
||||||
"@ant/computer-use-input": "workspace:*",
|
"@ant/computer-use-input": "workspace:*",
|
||||||
@@ -68,6 +69,7 @@
|
|||||||
"@anthropic-ai/sandbox-runtime": "^0.0.44",
|
"@anthropic-ai/sandbox-runtime": "^0.0.44",
|
||||||
"@anthropic-ai/sdk": "^0.80.0",
|
"@anthropic-ai/sdk": "^0.80.0",
|
||||||
"@anthropic-ai/vertex-sdk": "^0.14.4",
|
"@anthropic-ai/vertex-sdk": "^0.14.4",
|
||||||
|
"@anthropic/ink": "workspace:*",
|
||||||
"@aws-sdk/client-bedrock": "^3.1020.0",
|
"@aws-sdk/client-bedrock": "^3.1020.0",
|
||||||
"@aws-sdk/client-bedrock-runtime": "^3.1020.0",
|
"@aws-sdk/client-bedrock-runtime": "^3.1020.0",
|
||||||
"@aws-sdk/client-sts": "^3.1020.0",
|
"@aws-sdk/client-sts": "^3.1020.0",
|
||||||
@@ -101,11 +103,18 @@
|
|||||||
"@smithy/node-http-handler": "^4.5.1",
|
"@smithy/node-http-handler": "^4.5.1",
|
||||||
"@types/bun": "^1.3.11",
|
"@types/bun": "^1.3.11",
|
||||||
"@types/cacache": "^20.0.1",
|
"@types/cacache": "^20.0.1",
|
||||||
|
"@types/picomatch": "^4.0.3",
|
||||||
"@types/plist": "^3.0.5",
|
"@types/plist": "^3.0.5",
|
||||||
|
"@types/proper-lockfile": "^4.1.4",
|
||||||
|
"@types/qrcode": "^1.5.6",
|
||||||
"@types/react": "^19.2.14",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-reconciler": "^0.33.0",
|
"@types/react-reconciler": "^0.33.0",
|
||||||
|
"@types/semver": "^7.7.1",
|
||||||
"@types/sharp": "^0.32.0",
|
"@types/sharp": "^0.32.0",
|
||||||
|
"@types/shell-quote": "^1.7.5",
|
||||||
|
"@types/stack-utils": "^2.0.3",
|
||||||
"@types/turndown": "^5.0.6",
|
"@types/turndown": "^5.0.6",
|
||||||
|
"@types/ws": "^8.18.1",
|
||||||
"ajv": "^8.18.0",
|
"ajv": "^8.18.0",
|
||||||
"asciichart": "^1.5.25",
|
"asciichart": "^1.5.25",
|
||||||
"audio-capture-napi": "workspace:*",
|
"audio-capture-napi": "workspace:*",
|
||||||
@@ -132,7 +141,6 @@
|
|||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
"https-proxy-agent": "^8.0.0",
|
"https-proxy-agent": "^8.0.0",
|
||||||
"ignore": "^7.0.5",
|
"ignore": "^7.0.5",
|
||||||
"@anthropic/ink": "workspace:*",
|
|
||||||
"image-processor-napi": "workspace:*",
|
"image-processor-napi": "workspace:*",
|
||||||
"indent-string": "^5.0.0",
|
"indent-string": "^5.0.0",
|
||||||
"jsonc-parser": "^3.3.1",
|
"jsonc-parser": "^3.3.1",
|
||||||
@@ -141,6 +149,7 @@
|
|||||||
"lru-cache": "^11.2.7",
|
"lru-cache": "^11.2.7",
|
||||||
"marked": "^17.0.5",
|
"marked": "^17.0.5",
|
||||||
"modifiers-napi": "workspace:*",
|
"modifiers-napi": "workspace:*",
|
||||||
|
"openai": "^6.33.0",
|
||||||
"p-map": "^7.0.4",
|
"p-map": "^7.0.4",
|
||||||
"picomatch": "^4.0.4",
|
"picomatch": "^4.0.4",
|
||||||
"plist": "^3.1.0",
|
"plist": "^3.1.0",
|
||||||
|
|||||||
@@ -2148,7 +2148,7 @@ async function handleScreenshot(
|
|||||||
|
|
||||||
const monitorNote = await buildMonitorNote(
|
const monitorNote = await buildMonitorNote(
|
||||||
adapter,
|
adapter,
|
||||||
shot.displayId,
|
shot.displayId ?? 0,
|
||||||
overrides.lastScreenshot?.displayId,
|
overrides.lastScreenshot?.displayId,
|
||||||
overrides.onDisplayPinned !== undefined,
|
overrides.onDisplayPinned !== undefined,
|
||||||
);
|
);
|
||||||
@@ -2217,7 +2217,7 @@ async function handleScreenshot(
|
|||||||
|
|
||||||
const monitorNote = await buildMonitorNote(
|
const monitorNote = await buildMonitorNote(
|
||||||
adapter,
|
adapter,
|
||||||
shot.displayId,
|
shot.displayId ?? 0,
|
||||||
overrides.lastScreenshot?.displayId,
|
overrides.lastScreenshot?.displayId,
|
||||||
overrides.onDisplayPinned !== undefined,
|
overrides.onDisplayPinned !== undefined,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,6 +16,12 @@
|
|||||||
*/
|
*/
|
||||||
import bidiFactory from 'bidi-js'
|
import bidiFactory from 'bidi-js'
|
||||||
|
|
||||||
|
type BidiInstance = {
|
||||||
|
getEmbeddingLevels: (text: string, defaultDirection?: string) => { paragraphLevel: number; levels: Uint8Array }
|
||||||
|
getReorderSegments: (text: string, embeddingLevels: { paragraphLevel: number; levels: Uint8Array }, start?: number, end?: number) => [number, number][]
|
||||||
|
getVisualOrder: (reorderSegments: [number, number][]) => number[]
|
||||||
|
}
|
||||||
|
|
||||||
type ClusteredChar = {
|
type ClusteredChar = {
|
||||||
value: string
|
value: string
|
||||||
width: number
|
width: number
|
||||||
@@ -23,7 +29,7 @@ type ClusteredChar = {
|
|||||||
hyperlink: string | undefined
|
hyperlink: string | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
let bidiInstance: ReturnType<typeof bidiFactory> | undefined
|
let bidiInstance: BidiInstance | undefined
|
||||||
let needsSoftwareBidi: boolean | undefined
|
let needsSoftwareBidi: boolean | undefined
|
||||||
|
|
||||||
function needsBidi(): boolean {
|
function needsBidi(): boolean {
|
||||||
@@ -38,7 +44,7 @@ function needsBidi(): boolean {
|
|||||||
|
|
||||||
function getBidi() {
|
function getBidi() {
|
||||||
if (!bidiInstance) {
|
if (!bidiInstance) {
|
||||||
bidiInstance = bidiFactory()
|
bidiInstance = (bidiFactory as unknown as () => BidiInstance)()
|
||||||
}
|
}
|
||||||
return bidiInstance
|
return bidiInstance
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1883,8 +1883,8 @@ export default class Ink {
|
|||||||
let reentered = false
|
let reentered = false
|
||||||
const intercept = (
|
const intercept = (
|
||||||
chunk: Uint8Array | string,
|
chunk: Uint8Array | string,
|
||||||
encodingOrCb?: BufferEncoding | ((err?: Error) => void),
|
encodingOrCb?: BufferEncoding | ((err?: Error | null) => void),
|
||||||
cb?: (err?: Error) => void,
|
cb?: (err?: Error | null) => void,
|
||||||
): boolean => {
|
): boolean => {
|
||||||
const callback = typeof encodingOrCb === 'function' ? encodingOrCb : cb
|
const callback = typeof encodingOrCb === 'function' ? encodingOrCb : cb
|
||||||
// Reentrancy guard: logger.debug → writeToStderr → here. Pass
|
// Reentrancy guard: logger.debug → writeToStderr → here. Pass
|
||||||
|
|||||||
@@ -563,16 +563,16 @@ export class QueryEngine {
|
|||||||
for (const msg of messagesFromUserInput) {
|
for (const msg of messagesFromUserInput) {
|
||||||
if (
|
if (
|
||||||
msg.type === 'user' &&
|
msg.type === 'user' &&
|
||||||
typeof msg.message.content === 'string' &&
|
typeof msg.message!.content === 'string' &&
|
||||||
(msg.message.content.includes(`<${LOCAL_COMMAND_STDOUT_TAG}>`) ||
|
(msg.message!.content.includes(`<${LOCAL_COMMAND_STDOUT_TAG}>`) ||
|
||||||
msg.message.content.includes(`<${LOCAL_COMMAND_STDERR_TAG}>`) ||
|
msg.message!.content.includes(`<${LOCAL_COMMAND_STDERR_TAG}>`) ||
|
||||||
msg.isCompactSummary)
|
msg.isCompactSummary)
|
||||||
) {
|
) {
|
||||||
yield {
|
yield {
|
||||||
type: 'user',
|
type: 'user',
|
||||||
message: {
|
message: {
|
||||||
...msg.message,
|
...msg.message,
|
||||||
content: stripAnsi(msg.message.content),
|
content: stripAnsi(msg.message!.content),
|
||||||
},
|
},
|
||||||
session_id: getSessionId(),
|
session_id: getSessionId(),
|
||||||
parent_tool_use_id: null,
|
parent_tool_use_id: null,
|
||||||
@@ -1089,7 +1089,7 @@ export class QueryEngine {
|
|||||||
const edeResultType = result?.type ?? 'undefined'
|
const edeResultType = result?.type ?? 'undefined'
|
||||||
const edeLastContentType =
|
const edeLastContentType =
|
||||||
result?.type === 'assistant'
|
result?.type === 'assistant'
|
||||||
? (last(result.message.content)?.type ?? 'none')
|
? (last(result.message!.content as import('@anthropic-ai/sdk/resources/beta/messages/messages.js').BetaContentBlock[])?.type ?? 'none')
|
||||||
: 'n/a'
|
: 'n/a'
|
||||||
|
|
||||||
// Flush buffered transcript writes before yielding result.
|
// Flush buffered transcript writes before yielding result.
|
||||||
@@ -1147,7 +1147,7 @@ export class QueryEngine {
|
|||||||
let isApiError = false
|
let isApiError = false
|
||||||
|
|
||||||
if (result.type === 'assistant') {
|
if (result.type === 'assistant') {
|
||||||
const lastContent = last(result.message.content)
|
const lastContent = last(result.message!.content as import('@anthropic-ai/sdk/resources/beta/messages/messages.js').BetaContentBlock[])
|
||||||
if (
|
if (
|
||||||
lastContent?.type === 'text' &&
|
lastContent?.type === 'text' &&
|
||||||
!SYNTHETIC_MESSAGES.has(lastContent.text)
|
!SYNTHETIC_MESSAGES.has(lastContent.text)
|
||||||
|
|||||||
@@ -1429,7 +1429,7 @@ export function registerHookCallbacks(
|
|||||||
if (!STATE.registeredHooks[eventKey]) {
|
if (!STATE.registeredHooks[eventKey]) {
|
||||||
STATE.registeredHooks[eventKey] = []
|
STATE.registeredHooks[eventKey] = []
|
||||||
}
|
}
|
||||||
STATE.registeredHooks[eventKey]!.push(...matchers)
|
STATE.registeredHooks[eventKey]!.push(...(matchers ?? []))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1451,7 +1451,7 @@ export function clearRegisteredPluginHooks(): void {
|
|||||||
const filtered: Partial<Record<HookEvent, RegisteredHookMatcher[]>> = {}
|
const filtered: Partial<Record<HookEvent, RegisteredHookMatcher[]>> = {}
|
||||||
for (const [event, matchers] of Object.entries(STATE.registeredHooks)) {
|
for (const [event, matchers] of Object.entries(STATE.registeredHooks)) {
|
||||||
// Keep only callback hooks (those without pluginRoot)
|
// Keep only callback hooks (those without pluginRoot)
|
||||||
const callbackHooks = matchers.filter(m => !('pluginRoot' in m))
|
const callbackHooks = (matchers ?? []).filter(m => !('pluginRoot' in m))
|
||||||
if (callbackHooks.length > 0) {
|
if (callbackHooks.length > 0) {
|
||||||
filtered[event as HookEvent] = callbackHooks
|
filtered[event as HookEvent] = callbackHooks
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,12 +105,12 @@ export function extractTitleText(m: Message): string | undefined {
|
|||||||
if (m.type !== 'user' || m.isMeta || m.toolUseResult || m.isCompactSummary)
|
if (m.type !== 'user' || m.isMeta || m.toolUseResult || m.isCompactSummary)
|
||||||
return undefined
|
return undefined
|
||||||
if (m.origin && (m.origin as { kind?: string }).kind !== 'human') return undefined
|
if (m.origin && (m.origin as { kind?: string }).kind !== 'human') return undefined
|
||||||
const content = m.message.content
|
const content = m.message!.content
|
||||||
let raw: string | undefined
|
let raw: string | undefined
|
||||||
if (typeof content === 'string') {
|
if (typeof content === 'string') {
|
||||||
raw = content
|
raw = content
|
||||||
} else {
|
} else {
|
||||||
for (const block of content) {
|
for (const block of content ?? []) {
|
||||||
if (block.type === 'text') {
|
if (block.type === 'text') {
|
||||||
raw = block.text
|
raw = block.text
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
waitForPolicyLimitsToLoad,
|
waitForPolicyLimitsToLoad,
|
||||||
} from '../services/policyLimits/index.js'
|
} from '../services/policyLimits/index.js'
|
||||||
import type { Message } from '../types/message.js'
|
import type { Message } from '../types/message.js'
|
||||||
|
import type { ContentBlockParam } from '@anthropic-ai/sdk/resources/index.js'
|
||||||
import {
|
import {
|
||||||
checkAndRefreshOAuthTokenIfNeeded,
|
checkAndRefreshOAuthTokenIfNeeded,
|
||||||
getClaudeAIOAuthTokens,
|
getClaudeAIOAuthTokens,
|
||||||
@@ -289,7 +290,7 @@ export async function initReplBridge(
|
|||||||
isSyntheticMessage(msg)
|
isSyntheticMessage(msg)
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
const rawContent = getContentText(msg.message.content)
|
const rawContent = getContentText(msg.message!.content as string | ContentBlockParam[])
|
||||||
if (!rawContent) continue
|
if (!rawContent) continue
|
||||||
const derived = deriveTitle(rawContent)
|
const derived = deriveTitle(rawContent)
|
||||||
if (!derived) continue
|
if (!derived) continue
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ export function getCompanionIntroAttachment(
|
|||||||
// Skip if already announced for this companion.
|
// Skip if already announced for this companion.
|
||||||
for (const msg of messages ?? []) {
|
for (const msg of messages ?? []) {
|
||||||
if (msg.type !== 'attachment') continue
|
if (msg.type !== 'attachment') continue
|
||||||
if (msg.attachment.type !== 'companion_intro') continue
|
if (msg.attachment!.type !== 'companion_intro') continue
|
||||||
if (msg.attachment.name === companion.name) return []
|
if (msg.attachment!.name === companion.name) return []
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -1180,7 +1180,7 @@ function runHeadlessStreaming(
|
|||||||
removeInterruptedMessage(mutableMessages, turnInterruptionState.message)
|
removeInterruptedMessage(mutableMessages, turnInterruptionState.message)
|
||||||
enqueue({
|
enqueue({
|
||||||
mode: 'prompt',
|
mode: 'prompt',
|
||||||
value: turnInterruptionState.message.message.content,
|
value: turnInterruptionState.message.message!.content as string | ContentBlockParam[],
|
||||||
uuid: randomUUID(),
|
uuid: randomUUID(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1231,13 +1231,13 @@ function runHeadlessStreaming(
|
|||||||
output.enqueue({
|
output.enqueue({
|
||||||
type: 'user',
|
type: 'user',
|
||||||
content: crumb.message.content,
|
content: crumb.message.content,
|
||||||
message: crumb.message,
|
message: crumb.message as unknown,
|
||||||
session_id: getSessionId(),
|
session_id: getSessionId(),
|
||||||
parent_tool_use_id: null,
|
parent_tool_use_id: null,
|
||||||
uuid: crumb.uuid,
|
uuid: crumb.uuid,
|
||||||
timestamp: crumb.timestamp,
|
timestamp: crumb.timestamp,
|
||||||
isReplay: true,
|
isReplay: true,
|
||||||
} as SDKUserMessageReplay as StdoutMessage)
|
} as unknown as StdoutMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1969,12 +1969,12 @@ function runHeadlessStreaming(
|
|||||||
output.enqueue({
|
output.enqueue({
|
||||||
type: 'user',
|
type: 'user',
|
||||||
content: c.value,
|
content: c.value,
|
||||||
message: { role: 'user', content: c.value },
|
message: { role: 'user', content: c.value } as unknown,
|
||||||
session_id: getSessionId(),
|
session_id: getSessionId(),
|
||||||
parent_tool_use_id: null,
|
parent_tool_use_id: null,
|
||||||
uuid: c.uuid as string,
|
uuid: c.uuid as string,
|
||||||
isReplay: true,
|
isReplay: true,
|
||||||
} as SDKUserMessageReplay as StdoutMessage)
|
} as unknown as StdoutMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4090,13 +4090,13 @@ function runHeadlessStreaming(
|
|||||||
output.enqueue({
|
output.enqueue({
|
||||||
type: 'user',
|
type: 'user',
|
||||||
content: (userMsg.message as { content?: string })?.content ?? '',
|
content: (userMsg.message as { content?: string })?.content ?? '',
|
||||||
message: userMsg.message as { role: string; content: unknown },
|
message: userMsg.message as unknown,
|
||||||
session_id: sessionId,
|
session_id: sessionId,
|
||||||
parent_tool_use_id: null,
|
parent_tool_use_id: null,
|
||||||
uuid: userMsg.uuid as string,
|
uuid: userMsg.uuid as string,
|
||||||
timestamp: (userMsg as { timestamp?: string }).timestamp,
|
timestamp: (userMsg as { timestamp?: string }).timestamp,
|
||||||
isReplay: true,
|
isReplay: true,
|
||||||
} as unknown as SDKUserMessageReplay as StdoutMessage)
|
} as unknown as StdoutMessage)
|
||||||
}
|
}
|
||||||
// Historical dup = transcript already has this turn's output, so it
|
// Historical dup = transcript already has this turn's output, so it
|
||||||
// ran but its lifecycle was never closed (interrupted before ack).
|
// ran but its lifecycle was never closed (interrupted before ack).
|
||||||
@@ -4554,7 +4554,7 @@ async function handleRewindFiles(
|
|||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
canRewind: true,
|
canRewind: true,
|
||||||
filesChanged: diffStats?.filesChanged,
|
filesChanged: diffStats?.filesChanged ?? [],
|
||||||
insertions: diffStats?.insertions,
|
insertions: diffStats?.insertions,
|
||||||
deletions: diffStats?.deletions,
|
deletions: diffStats?.deletions,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -463,8 +463,8 @@ const loadAllCommands = memoize(async (cwd: string): Promise<Command[]> => {
|
|||||||
...bundledSkills,
|
...bundledSkills,
|
||||||
...builtinPluginSkills,
|
...builtinPluginSkills,
|
||||||
...skillDirCommands,
|
...skillDirCommands,
|
||||||
...workflowCommands,
|
...(workflowCommands as Command[]),
|
||||||
...pluginCommands,
|
...(pluginCommands as Command[]),
|
||||||
...pluginSkills,
|
...pluginSkills,
|
||||||
...COMMANDS(),
|
...COMMANDS(),
|
||||||
]
|
]
|
||||||
|
|||||||
3
src/commands/ant-trace/index.d.ts
vendored
Normal file
3
src/commands/ant-trace/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
3
src/commands/autofix-pr/index.d.ts
vendored
Normal file
3
src/commands/autofix-pr/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
3
src/commands/backfill-sessions/index.d.ts
vendored
Normal file
3
src/commands/backfill-sessions/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
@@ -44,7 +44,7 @@ export function deriveFirstPrompt(
|
|||||||
typeof content === 'string'
|
typeof content === 'string'
|
||||||
? content
|
? content
|
||||||
: content.find(
|
: content.find(
|
||||||
(block): block is { type: 'text'; text: string } =>
|
(block: { type: string; text?: string }): block is { type: 'text'; text: string } =>
|
||||||
block.type === 'text',
|
block.type === 'text',
|
||||||
)?.text
|
)?.text
|
||||||
if (!raw) return 'Branched conversation'
|
if (!raw) return 'Branched conversation'
|
||||||
|
|||||||
3
src/commands/break-cache/index.d.ts
vendored
Normal file
3
src/commands/break-cache/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
@@ -154,7 +154,7 @@ function BridgeDisconnectDialog({ onDone }: Props): React.ReactNode {
|
|||||||
type: 'utf8',
|
type: 'utf8',
|
||||||
errorCorrectionLevel: 'L',
|
errorCorrectionLevel: 'L',
|
||||||
small: true,
|
small: true,
|
||||||
})
|
} as Parameters<typeof qrToString>[1])
|
||||||
.then(setQrText)
|
.then(setQrText)
|
||||||
.catch(() => setQrText(''))
|
.catch(() => setQrText(''))
|
||||||
}, [showQR, displayUrl])
|
}, [showQR, displayUrl])
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ function BtwSideQuestion({
|
|||||||
*/
|
*/
|
||||||
function stripInProgressAssistantMessage(messages: Message[]): Message[] {
|
function stripInProgressAssistantMessage(messages: Message[]): Message[] {
|
||||||
const last = messages.at(-1)
|
const last = messages.at(-1)
|
||||||
if (last?.type === 'assistant' && last.message.stop_reason === null) {
|
if (last?.type === 'assistant' && last.message!.stop_reason === null) {
|
||||||
return messages.slice(0, -1)
|
return messages.slice(0, -1)
|
||||||
}
|
}
|
||||||
return messages
|
return messages
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ export async function call(
|
|||||||
return React.createElement(CompanionCard, {
|
return React.createElement(CompanionCard, {
|
||||||
companion,
|
companion,
|
||||||
lastReaction,
|
lastReaction,
|
||||||
onDone,
|
onDone: onDone as unknown as Parameters<typeof CompanionCard>[0]['onDone'],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
src/commands/bughunter/index.d.ts
vendored
Normal file
3
src/commands/bughunter/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { feature } from 'bun:bundle'
|
import { feature } from 'bun:bundle'
|
||||||
import chalk from 'chalk'
|
import chalk from 'chalk'
|
||||||
|
import type { SDKStatus } from '../../entrypoints/agentSdkTypes.js'
|
||||||
import { markPostCompaction } from 'src/bootstrap/state.js'
|
import { markPostCompaction } from 'src/bootstrap/state.js'
|
||||||
import { getSystemPrompt } from '../../constants/prompts.js'
|
import { getSystemPrompt } from '../../constants/prompts.js'
|
||||||
import { getSystemContext, getUserContext } from '../../context.js'
|
import { getSystemContext, getUserContext } from '../../context.js'
|
||||||
@@ -223,7 +224,7 @@ async function compactViaReactive(
|
|||||||
context.setStreamMode?.('requesting')
|
context.setStreamMode?.('requesting')
|
||||||
context.setResponseLength?.(() => 0)
|
context.setResponseLength?.(() => 0)
|
||||||
context.onCompactProgress?.({ type: 'compact_end' })
|
context.onCompactProgress?.({ type: 'compact_end' })
|
||||||
context.setSDKStatus?.(null)
|
context.setSDKStatus?.("" as SDKStatus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
src/commands/ctx_viz/index.d.ts
vendored
Normal file
3
src/commands/ctx_viz/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
3
src/commands/debug-tool-call/index.d.ts
vendored
Normal file
3
src/commands/debug-tool-call/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
3
src/commands/env/index.d.ts
vendored
Normal file
3
src/commands/env/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
@@ -55,7 +55,7 @@ export async function call(
|
|||||||
AgentTool.call(
|
AgentTool.call(
|
||||||
input,
|
input,
|
||||||
context,
|
context,
|
||||||
context.canUseTool,
|
context.canUseTool!,
|
||||||
lastAssistantMessage
|
lastAssistantMessage
|
||||||
).catch(error => {
|
).catch(error => {
|
||||||
logForDebugging(`Fork subagent async error: ${error}`, { level: 'error' })
|
logForDebugging(`Fork subagent async error: ${error}`, { level: 'error' })
|
||||||
|
|||||||
3
src/commands/good-claude/index.d.ts
vendored
Normal file
3
src/commands/good-claude/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
@@ -1,4 +1,30 @@
|
|||||||
// Auto-generated stub — replace with real implementation
|
export type Workflow = 'claude' | 'claude-review' | string
|
||||||
export type Workflow = any;
|
|
||||||
export type State = any;
|
export type Warning = {
|
||||||
export type Warning = any;
|
title: string
|
||||||
|
message: string
|
||||||
|
instructions: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type State = {
|
||||||
|
step: string
|
||||||
|
selectedRepoName: string
|
||||||
|
currentRepo: string
|
||||||
|
useCurrentRepo: boolean
|
||||||
|
apiKeyOrOAuthToken: string
|
||||||
|
useExistingKey: boolean
|
||||||
|
currentWorkflowInstallStep: number
|
||||||
|
warnings: Warning[]
|
||||||
|
secretExists: boolean
|
||||||
|
secretName: string
|
||||||
|
useExistingSecret: boolean
|
||||||
|
workflowExists: boolean
|
||||||
|
selectedWorkflows: Workflow[]
|
||||||
|
selectedApiKeyOption: 'existing' | 'new' | 'oauth'
|
||||||
|
authType: 'api_key' | 'oauth_token'
|
||||||
|
workflowAction?: string
|
||||||
|
error?: string
|
||||||
|
errorReason?: string
|
||||||
|
errorInstructions?: string[]
|
||||||
|
[key: string]: unknown
|
||||||
|
}
|
||||||
|
|||||||
3
src/commands/issue/index.d.ts
vendored
Normal file
3
src/commands/issue/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
3
src/commands/mock-limits/index.d.ts
vendored
Normal file
3
src/commands/mock-limits/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
3
src/commands/oauth-refresh/index.d.ts
vendored
Normal file
3
src/commands/oauth-refresh/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
3
src/commands/onboarding/index.d.ts
vendored
Normal file
3
src/commands/onboarding/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
3
src/commands/perf-issue/index.d.ts
vendored
Normal file
3
src/commands/perf-issue/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
@@ -25,7 +25,9 @@ function getEnvVarForProvider(provider: string): string {
|
|||||||
// Get merged env: process.env + settings.env (from userSettings)
|
// Get merged env: process.env + settings.env (from userSettings)
|
||||||
function getMergedEnv(): Record<string, string> {
|
function getMergedEnv(): Record<string, string> {
|
||||||
const settings = getSettings_DEPRECATED()
|
const settings = getSettings_DEPRECATED()
|
||||||
const merged = { ...process.env }
|
const merged: Record<string, string> = Object.fromEntries(
|
||||||
|
Object.entries(process.env).filter((e): e is [string, string] => e[1] !== undefined)
|
||||||
|
)
|
||||||
if (settings?.env) {
|
if (settings?.env) {
|
||||||
Object.assign(merged, settings.env)
|
Object.assign(merged, settings.env)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import {
|
|||||||
formatPreconditionError,
|
formatPreconditionError,
|
||||||
getRemoteTaskSessionUrl,
|
getRemoteTaskSessionUrl,
|
||||||
registerRemoteAgentTask,
|
registerRemoteAgentTask,
|
||||||
|
type BackgroundRemoteSessionPrecondition,
|
||||||
} from '../../tasks/RemoteAgentTask/RemoteAgentTask.js'
|
} from '../../tasks/RemoteAgentTask/RemoteAgentTask.js'
|
||||||
import { isEnterpriseSubscriber, isTeamSubscriber } from '../../utils/auth.js'
|
import { isEnterpriseSubscriber, isTeamSubscriber } from '../../utils/auth.js'
|
||||||
import { detectCurrentRepositoryWithHost } from '../../utils/detectRepository.js'
|
import { detectCurrentRepositoryWithHost } from '../../utils/detectRepository.js'
|
||||||
@@ -147,7 +148,7 @@ export async function launchRemoteReview(
|
|||||||
',',
|
',',
|
||||||
) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||||
})
|
})
|
||||||
const reasons = blockers.map(formatPreconditionError).join('\n')
|
const reasons = (blockers as BackgroundRemoteSessionPrecondition[]).map(formatPreconditionError).join('\n')
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
|||||||
3
src/commands/share/index.d.ts
vendored
Normal file
3
src/commands/share/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
3
src/commands/summary/index.d.ts
vendored
Normal file
3
src/commands/summary/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
3
src/commands/teleport/index.d.ts
vendored
Normal file
3
src/commands/teleport/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { Command } from '../../types/command.js'
|
||||||
|
declare const _default: Command
|
||||||
|
export default _default
|
||||||
@@ -64,7 +64,7 @@ export function BridgeDialog({ onDone }: Props): React.ReactNode {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
qrToString(displayUrl, {
|
qrToString(displayUrl, {
|
||||||
type: 'utf8',
|
type: 'terminal',
|
||||||
errorCorrectionLevel: 'L',
|
errorCorrectionLevel: 'L',
|
||||||
small: true,
|
small: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -613,7 +613,7 @@ async function generateTitle(
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const _firstBlock = response.message.content[0] as unknown as Record<string, unknown> | undefined
|
const _firstBlock = response?.message?.content?.[0] as unknown as Record<string, unknown> | undefined
|
||||||
const title =
|
const title =
|
||||||
_firstBlock?.type === 'text'
|
_firstBlock?.type === 'text'
|
||||||
? (_firstBlock.text as string)
|
? (_firstBlock.text as string)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ function hasMemoryFileRead(messages: Message[]): boolean {
|
|||||||
if (message.type !== 'assistant') {
|
if (message.type !== 'assistant') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const content = message.message.content
|
const content = message.message!.content
|
||||||
if (!Array.isArray(content)) {
|
if (!Array.isArray(content)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,8 +242,8 @@ export function countUnseenAssistantTurns(
|
|||||||
|
|
||||||
function assistantHasVisibleText(m: Message): boolean {
|
function assistantHasVisibleText(m: Message): boolean {
|
||||||
if (m.type !== 'assistant') return false
|
if (m.type !== 'assistant') return false
|
||||||
if (!Array.isArray(m.message.content)) return false
|
if (!Array.isArray(m.message!.content)) return false
|
||||||
for (const b of m.message.content) {
|
for (const b of m.message!.content) {
|
||||||
if (typeof b !== 'string' && b.type === 'text' && b.text.trim() !== '') return true
|
if (typeof b !== 'string' && b.type === 'text' && b.text.trim() !== '') return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -748,9 +748,9 @@ function UserMessageOption({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = userMessage.message.content
|
const content = userMessage.message!.content
|
||||||
const lastBlock =
|
const lastBlock =
|
||||||
typeof content === 'string' ? null : content[content.length - 1]
|
typeof content === 'string' ? null : content![content!.length - 1]
|
||||||
const rawMessageText =
|
const rawMessageText =
|
||||||
typeof content === 'string'
|
typeof content === 'string'
|
||||||
? content.trim()
|
? content.trim()
|
||||||
@@ -897,8 +897,8 @@ export function selectableUserMessagesFilter(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
Array.isArray(message.message.content) &&
|
Array.isArray(message.message!.content) &&
|
||||||
message.message.content[0]?.type === 'tool_result'
|
message.message!.content[0]?.type === 'tool_result'
|
||||||
) {
|
) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -912,9 +912,9 @@ export function selectableUserMessagesFilter(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = message.message.content
|
const content = message.message!.content
|
||||||
const lastBlock =
|
const lastBlock =
|
||||||
typeof content === 'string' ? null : content[content.length - 1]
|
typeof content === 'string' ? null : content![content!.length - 1]
|
||||||
const messageText =
|
const messageText =
|
||||||
typeof content === 'string'
|
typeof content === 'string'
|
||||||
? content.trim()
|
? content.trim()
|
||||||
@@ -960,7 +960,7 @@ export function messagesAfterAreOnlySynthetic(
|
|||||||
|
|
||||||
// Assistant with actual content = meaningful
|
// Assistant with actual content = meaningful
|
||||||
if (msg.type === 'assistant') {
|
if (msg.type === 'assistant') {
|
||||||
const content = msg.message.content
|
const content = msg.message!.content
|
||||||
if (Array.isArray(content)) {
|
if (Array.isArray(content)) {
|
||||||
const hasMeaningfulContent = content.some(
|
const hasMeaningfulContent = content.some(
|
||||||
block =>
|
block =>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export function MessageTimestamp({
|
|||||||
isTranscriptMode &&
|
isTranscriptMode &&
|
||||||
message.timestamp &&
|
message.timestamp &&
|
||||||
message.type === 'assistant' &&
|
message.type === 'assistant' &&
|
||||||
(Array.isArray(message.message.content) ? (message.message.content as {type: string}[]).some(c => c.type === 'text') : false)
|
(Array.isArray(message.message!.content) ? (message.message!.content as {type: string}[]).some(c => c.type === 'text') : false)
|
||||||
|
|
||||||
if (!shouldShowTimestamp) {
|
if (!shouldShowTimestamp) {
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -460,7 +460,7 @@ const MessagesImpl = ({
|
|||||||
for (let i = normalizedMessages.length - 1; i >= 0; i--) {
|
for (let i = normalizedMessages.length - 1; i >= 0; i--) {
|
||||||
const msg = normalizedMessages[i]
|
const msg = normalizedMessages[i]
|
||||||
if (msg?.type === 'assistant') {
|
if (msg?.type === 'assistant') {
|
||||||
const content = msg.message.content as Array<{ type: string }>
|
const content = msg.message!.content as Array<{ type: string }>
|
||||||
// Find the last thinking block in this message
|
// Find the last thinking block in this message
|
||||||
for (let j = content.length - 1; j >= 0; j--) {
|
for (let j = content.length - 1; j >= 0; j--) {
|
||||||
if (content[j]?.type === 'thinking') {
|
if (content[j]?.type === 'thinking') {
|
||||||
@@ -468,7 +468,7 @@ const MessagesImpl = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (msg?.type === 'user') {
|
} else if (msg?.type === 'user') {
|
||||||
const content = msg.message.content as Array<{ type: string }>
|
const content = msg.message!.content as Array<{ type: string }>
|
||||||
const hasToolResult = content.some(
|
const hasToolResult = content.some(
|
||||||
block => block.type === 'tool_result',
|
block => block.type === 'tool_result',
|
||||||
)
|
)
|
||||||
@@ -488,7 +488,7 @@ const MessagesImpl = ({
|
|||||||
for (let i = normalizedMessages.length - 1; i >= 0; i--) {
|
for (let i = normalizedMessages.length - 1; i >= 0; i--) {
|
||||||
const msg = normalizedMessages[i]
|
const msg = normalizedMessages[i]
|
||||||
if (msg?.type === 'user') {
|
if (msg?.type === 'user') {
|
||||||
const content = msg.message.content as Array<{ type: string; text?: string }>
|
const content = msg.message!.content as Array<{ type: string; text?: string }>
|
||||||
// Check if any text content is bash output
|
// Check if any text content is bash output
|
||||||
for (const block of content) {
|
for (const block of content) {
|
||||||
if (block.type === 'text') {
|
if (block.type === 'text') {
|
||||||
@@ -741,7 +741,8 @@ const MessagesImpl = ({
|
|||||||
(msg: RenderableMessage): boolean => {
|
(msg: RenderableMessage): boolean => {
|
||||||
if (msg.type === 'collapsed_read_search') return true
|
if (msg.type === 'collapsed_read_search') return true
|
||||||
if (msg.type === 'assistant') {
|
if (msg.type === 'assistant') {
|
||||||
const b = msg.message.content[0] as unknown as AdvisorBlock | undefined
|
const content = msg.message!.content
|
||||||
|
const b = (Array.isArray(content) ? content[0] : undefined) as unknown as AdvisorBlock | undefined
|
||||||
return (
|
return (
|
||||||
b != null &&
|
b != null &&
|
||||||
isAdvisorBlock(b) &&
|
isAdvisorBlock(b) &&
|
||||||
@@ -750,11 +751,11 @@ const MessagesImpl = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (msg.type !== 'user') return false
|
if (msg.type !== 'user') return false
|
||||||
const b = (msg.message.content as Array<{ type: string; tool_use_id?: string; is_error?: boolean; [key: string]: unknown }>)[0]
|
const b = (msg.message!.content as Array<{ type: string; tool_use_id?: string; is_error?: boolean; [key: string]: unknown }>)[0]
|
||||||
if (b?.type !== 'tool_result' || b.is_error || !msg.toolUseResult)
|
if (b?.type !== 'tool_result' || b.is_error || !msg.toolUseResult)
|
||||||
return false
|
return false
|
||||||
const name = lookupsRef.current.toolUseByToolUseID.get(
|
const name = lookupsRef.current.toolUseByToolUseID.get(
|
||||||
b.tool_use_id,
|
b.tool_use_id ?? '',
|
||||||
)?.name
|
)?.name
|
||||||
const tool = name ? findToolByName(tools, name) : undefined
|
const tool = name ? findToolByName(tools, name) : undefined
|
||||||
return tool?.isResultTruncated?.(msg.toolUseResult as never) ?? false
|
return tool?.isResultTruncated?.(msg.toolUseResult as never) ?? false
|
||||||
@@ -1111,7 +1112,7 @@ export function shouldRenderStatically(
|
|||||||
case 'user':
|
case 'user':
|
||||||
case 'assistant': {
|
case 'assistant': {
|
||||||
if (message.type === 'assistant') {
|
if (message.type === 'assistant') {
|
||||||
const block = (message.message.content as Array<{ type: string; id?: string }>)[0]
|
const block = (message.message!.content as Array<{ type: string; id?: string }>)[0]
|
||||||
if (block?.type === 'server_tool_use') {
|
if (block?.type === 'server_tool_use') {
|
||||||
return lookups.resolvedToolUseIDs.has(block.id!)
|
return lookups.resolvedToolUseIDs.has(block.id!)
|
||||||
}
|
}
|
||||||
@@ -1142,7 +1143,7 @@ export function shouldRenderStatically(
|
|||||||
}
|
}
|
||||||
case 'grouped_tool_use': {
|
case 'grouped_tool_use': {
|
||||||
const allResolved = message.messages.every(msg => {
|
const allResolved = message.messages.every(msg => {
|
||||||
const content = (msg.message.content as Array<{ type: string; id?: string }>)[0]
|
const content = (msg.message!.content as Array<{ type: string; id?: string }>)[0]
|
||||||
return (
|
return (
|
||||||
content?.type === 'tool_use' &&
|
content?.type === 'tool_use' &&
|
||||||
lookups.resolvedToolUseIDs.has(content.id!)
|
lookups.resolvedToolUseIDs.has(content.id!)
|
||||||
@@ -1155,5 +1156,7 @@ export function shouldRenderStatically(
|
|||||||
// (In transcript mode, we already returned true at the top of this function)
|
// (In transcript mode, we already returned true at the top of this function)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3140,8 +3140,8 @@ function getInitialPasteId(messages: Message[]): number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check text paste references in message content
|
// Check text paste references in message content
|
||||||
if (Array.isArray(message.message.content)) {
|
if (Array.isArray(message.message!.content)) {
|
||||||
for (const block of message.message.content) {
|
for (const block of message.message!.content) {
|
||||||
if (block.type === 'text') {
|
if (block.type === 'text') {
|
||||||
const refs = parseReferences(block.text)
|
const refs = parseReferences(block.text)
|
||||||
for (const ref of refs) {
|
for (const ref of refs) {
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ export function isNavigableMessage(msg: NavigableMessage): boolean {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
type PrimaryInput = {
|
type PrimaryInput = {
|
||||||
@@ -395,6 +396,7 @@ export function copyTextOf(msg: NavigableMessage): string {
|
|||||||
return `[${a.type}]`
|
return `[${a.type}]`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
function toolResultText(r: NormalizedUserMessage): string {
|
function toolResultText(r: NormalizedUserMessage): string {
|
||||||
|
|||||||
@@ -63,6 +63,6 @@ export function isNullRenderingAttachment(
|
|||||||
): boolean {
|
): boolean {
|
||||||
return (
|
return (
|
||||||
msg.type === 'attachment' &&
|
msg.type === 'attachment' &&
|
||||||
NULL_RENDERING_ATTACHMENT_TYPES.has(msg.attachment.type as Attachment['type'])
|
NULL_RENDERING_ATTACHMENT_TYPES.has(msg.attachment!.type as Attachment['type'])
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export function FallbackPermissionRequest({
|
|||||||
event: 'accept',
|
event: 'accept',
|
||||||
metadata: {
|
metadata: {
|
||||||
language_name: 'none',
|
language_name: 'none',
|
||||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||||
platform: env.platform,
|
platform: env.platform,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -66,7 +66,7 @@ export function FallbackPermissionRequest({
|
|||||||
event: 'accept',
|
event: 'accept',
|
||||||
metadata: {
|
metadata: {
|
||||||
language_name: 'none',
|
language_name: 'none',
|
||||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||||
platform: env.platform,
|
platform: env.platform,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -92,7 +92,7 @@ export function FallbackPermissionRequest({
|
|||||||
event: 'reject',
|
event: 'reject',
|
||||||
metadata: {
|
metadata: {
|
||||||
language_name: 'none',
|
language_name: 'none',
|
||||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||||
platform: env.platform,
|
platform: env.platform,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -111,7 +111,7 @@ export function FallbackPermissionRequest({
|
|||||||
event: 'reject',
|
event: 'reject',
|
||||||
metadata: {
|
metadata: {
|
||||||
language_name: 'none',
|
language_name: 'none',
|
||||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||||
platform: env.platform,
|
platform: env.platform,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export function useFilePermissionDialog<T extends ToolInput>({
|
|||||||
const onChange = useCallback(
|
const onChange = useCallback(
|
||||||
(option: PermissionOption, input: T, feedback?: string) => {
|
(option: PermissionOption, input: T, feedback?: string) => {
|
||||||
const params: PermissionHandlerParams = {
|
const params: PermissionHandlerParams = {
|
||||||
messageId: toolUseConfirm.assistantMessage.message.id,
|
messageId: toolUseConfirm.assistantMessage.message.id!,
|
||||||
path: filePath,
|
path: filePath,
|
||||||
toolUseConfirm,
|
toolUseConfirm,
|
||||||
toolPermissionContext,
|
toolPermissionContext,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import * as React from 'react'
|
|||||||
import { Suspense, use, useMemo } from 'react'
|
import { Suspense, use, useMemo } from 'react'
|
||||||
import { Box, NoSelect, Text } from '@anthropic/ink'
|
import { Box, NoSelect, Text } from '@anthropic/ink'
|
||||||
import type {
|
import type {
|
||||||
|
NotebookCell,
|
||||||
NotebookCellType,
|
NotebookCellType,
|
||||||
NotebookContent,
|
NotebookContent,
|
||||||
} from '../../../types/notebook.js'
|
} from '../../../types/notebook.js'
|
||||||
@@ -79,7 +80,7 @@ function NotebookEditToolDiffInner({
|
|||||||
}
|
}
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
const cell = notebookData.cells.find(cell => cell.id === cell_id)
|
const cell = notebookData.cells.find((cell: NotebookCell) => cell.id === cell_id)
|
||||||
if (!cell) {
|
if (!cell) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ export function SkillPermissionRequest(
|
|||||||
event: 'accept',
|
event: 'accept',
|
||||||
metadata: {
|
metadata: {
|
||||||
language_name: 'none',
|
language_name: 'none',
|
||||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||||
platform: env.platform,
|
platform: env.platform,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -142,7 +142,7 @@ export function SkillPermissionRequest(
|
|||||||
event: 'accept',
|
event: 'accept',
|
||||||
metadata: {
|
metadata: {
|
||||||
language_name: 'none',
|
language_name: 'none',
|
||||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||||
platform: env.platform,
|
platform: env.platform,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -169,7 +169,7 @@ export function SkillPermissionRequest(
|
|||||||
event: 'accept',
|
event: 'accept',
|
||||||
metadata: {
|
metadata: {
|
||||||
language_name: 'none',
|
language_name: 'none',
|
||||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||||
platform: env.platform,
|
platform: env.platform,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -201,7 +201,7 @@ export function SkillPermissionRequest(
|
|||||||
event: 'reject',
|
event: 'reject',
|
||||||
metadata: {
|
metadata: {
|
||||||
language_name: 'none',
|
language_name: 'none',
|
||||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||||
platform: env.platform,
|
platform: env.platform,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -220,7 +220,7 @@ export function SkillPermissionRequest(
|
|||||||
event: 'reject',
|
event: 'reject',
|
||||||
metadata: {
|
metadata: {
|
||||||
language_name: 'none',
|
language_name: 'none',
|
||||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||||
platform: env.platform,
|
platform: env.platform,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ export function usePermissionRequestLogging(
|
|||||||
event: 'response',
|
event: 'response',
|
||||||
metadata: {
|
metadata: {
|
||||||
language_name: unaryEvent.language_name,
|
language_name: unaryEvent.language_name,
|
||||||
message_id: toolUseConfirm.assistantMessage.message.id,
|
message_id: toolUseConfirm.assistantMessage.message.id!,
|
||||||
platform: env.platform,
|
platform: env.platform,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export function logUnaryPermissionEvent(
|
|||||||
event,
|
event,
|
||||||
metadata: {
|
metadata: {
|
||||||
language_name: 'none',
|
language_name: 'none',
|
||||||
message_id,
|
message_id: message_id!,
|
||||||
platform: getHostPlatformForAnalytics(),
|
platform: getHostPlatformForAnalytics(),
|
||||||
hasFeedback: hasFeedback ?? false,
|
hasFeedback: hasFeedback ?? false,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { feature } from 'bun:bundle'
|
import { feature } from 'bun:bundle'
|
||||||
import figures from 'figures'
|
import figures from 'figures'
|
||||||
|
import type { AgentId } from '../../types/ids.js'
|
||||||
import React, {
|
import React, {
|
||||||
type ReactNode,
|
type ReactNode,
|
||||||
useEffect,
|
useEffect,
|
||||||
@@ -535,12 +536,12 @@ export function BackgroundTasksDialog({
|
|||||||
}
|
}
|
||||||
onSkipAgent={
|
onSkipAgent={
|
||||||
task.status === 'running' && skipWorkflowAgent
|
task.status === 'running' && skipWorkflowAgent
|
||||||
? agentId => skipWorkflowAgent(task.id, agentId, setAppState)
|
? (agentId: AgentId) => skipWorkflowAgent(task.id, agentId, setAppState)
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
onRetryAgent={
|
onRetryAgent={
|
||||||
task.status === 'running' && retryWorkflowAgent
|
task.status === 'running' && retryWorkflowAgent
|
||||||
? agentId => retryWorkflowAgent(task.id, agentId, setAppState)
|
? (agentId: AgentId) => retryWorkflowAgent(task.id, agentId, setAppState)
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
onBack={goBackToList}
|
onBack={goBackToList}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ export async function launchAssistantSessionChooser(
|
|||||||
return showSetupDialog<string | null>(root, done => (
|
return showSetupDialog<string | null>(root, done => (
|
||||||
<AssistantSessionChooser
|
<AssistantSessionChooser
|
||||||
sessions={props.sessions}
|
sessions={props.sessions}
|
||||||
onSelect={id => done(id)}
|
onSelect={(id: string) => done(id)}
|
||||||
onCancel={() => done(null)}
|
onCancel={() => done(null)}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ function createPermissionContext(
|
|||||||
setToolPermissionContext: (context: ToolPermissionContext) => void,
|
setToolPermissionContext: (context: ToolPermissionContext) => void,
|
||||||
queueOps?: PermissionQueueOps,
|
queueOps?: PermissionQueueOps,
|
||||||
) {
|
) {
|
||||||
const messageId = assistantMessage.message.id
|
const messageId = assistantMessage.message.id!
|
||||||
const ctx = {
|
const ctx = {
|
||||||
tool,
|
tool,
|
||||||
input,
|
input,
|
||||||
@@ -234,7 +234,7 @@ function createPermissionContext(
|
|||||||
const finalInput = decision.updatedInput ?? updatedInput ?? input
|
const finalInput = decision.updatedInput ?? updatedInput ?? input
|
||||||
return await this.handleHookAllow(
|
return await this.handleHookAllow(
|
||||||
finalInput,
|
finalInput,
|
||||||
decision.updatedPermissions ?? [],
|
(decision.updatedPermissions ?? []) as unknown as import('../../types/permissions.js').PermissionUpdate[],
|
||||||
permissionPromptStartTimeMs,
|
permissionPromptStartTimeMs,
|
||||||
)
|
)
|
||||||
} else if (decision.behavior === 'deny') {
|
} else if (decision.behavior === 'deny') {
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ function useCanUseTool(
|
|||||||
tool,
|
tool,
|
||||||
input,
|
input,
|
||||||
toolUseContext,
|
toolUseContext,
|
||||||
messageId: ctx.messageId,
|
messageId: ctx.messageId!,
|
||||||
toolUseID,
|
toolUseID,
|
||||||
},
|
},
|
||||||
{ decision: 'reject', source: 'config' },
|
{ decision: 'reject', source: 'config' },
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export function isSessionContainerCompatible(messages: Message[]): boolean {
|
|||||||
if (msg.type !== 'assistant') {
|
if (msg.type !== 'assistant') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const content = msg.message.content
|
const content = msg.message!.content
|
||||||
if (!Array.isArray(content)) {
|
if (!Array.isArray(content)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ function countHunkLines(hunks: StructuredPatchHunk[]): {
|
|||||||
|
|
||||||
function getUserPromptPreview(message: Message): string {
|
function getUserPromptPreview(message: Message): string {
|
||||||
if (message.type !== 'user') return ''
|
if (message.type !== 'user') return ''
|
||||||
const content = message.message.content
|
const content = message.message!.content
|
||||||
const text = typeof content === 'string' ? content : ''
|
const text = typeof content === 'string' ? content : ''
|
||||||
// Truncate to ~30 chars
|
// Truncate to ~30 chars
|
||||||
if (text.length <= 30) return text
|
if (text.length <= 30) return text
|
||||||
@@ -124,8 +124,8 @@ export function useTurnDiffs(messages: Message[]): TurnDiff[] {
|
|||||||
// Check if this is a user prompt (not a tool result)
|
// Check if this is a user prompt (not a tool result)
|
||||||
const isToolResult =
|
const isToolResult =
|
||||||
message.toolUseResult ||
|
message.toolUseResult ||
|
||||||
(Array.isArray(message.message.content) &&
|
(Array.isArray(message.message!.content) &&
|
||||||
message.message.content[0]?.type === 'tool_result')
|
message.message!.content[0]?.type === 'tool_result')
|
||||||
|
|
||||||
if (!isToolResult && !message.isMeta) {
|
if (!isToolResult && !message.isMeta) {
|
||||||
// Start a new turn on user prompt
|
// Start a new turn on user prompt
|
||||||
|
|||||||
@@ -4458,7 +4458,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
...(uploaderReady && {
|
...(uploaderReady && {
|
||||||
onTurnComplete: (messages: MessageType[]) => {
|
onTurnComplete: (messages: MessageType[]) => {
|
||||||
void uploaderReady.then((uploader) =>
|
void uploaderReady.then((uploader) =>
|
||||||
uploader?.(messages),
|
(uploader as ((msgs: MessageType[]) => void) | null)?.(messages),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -4616,13 +4616,13 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
createLocalSSHSession,
|
createLocalSSHSession,
|
||||||
SSHSessionError,
|
SSHSessionError,
|
||||||
} = await import("./ssh/createSSHSession.js");
|
} = await import("./ssh/createSSHSession.js");
|
||||||
let sshSession;
|
let sshSession: import('./ssh/createSSHSession.js').SSHSession | undefined;
|
||||||
try {
|
try {
|
||||||
if (_pendingSSH.local) {
|
if (_pendingSSH.local) {
|
||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
"Starting local ssh-proxy test session...\n",
|
"Starting local ssh-proxy test session...\n",
|
||||||
);
|
);
|
||||||
sshSession = createLocalSSHSession({
|
sshSession = await createLocalSSHSession({
|
||||||
cwd: _pendingSSH.cwd,
|
cwd: _pendingSSH.cwd,
|
||||||
permissionMode: _pendingSSH.permissionMode,
|
permissionMode: _pendingSSH.permissionMode,
|
||||||
dangerouslySkipPermissions:
|
dangerouslySkipPermissions:
|
||||||
@@ -4649,7 +4649,7 @@ async function run(): Promise<CommanderCommand> {
|
|||||||
},
|
},
|
||||||
isTTY
|
isTTY
|
||||||
? {
|
? {
|
||||||
onProgress: (msg) => {
|
onProgress: (msg: string) => {
|
||||||
hadProgress = true;
|
hadProgress = true;
|
||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\r ${msg}\x1b[K`,
|
`\r ${msg}\x1b[K`,
|
||||||
|
|||||||
10
src/query.ts
10
src/query.ts
@@ -803,7 +803,7 @@ async function* queryLoop(
|
|||||||
if (
|
if (
|
||||||
contextCollapse?.isWithheldPromptTooLong(
|
contextCollapse?.isWithheldPromptTooLong(
|
||||||
message as Message,
|
message as Message,
|
||||||
isPromptTooLongMessage,
|
isPromptTooLongMessage as (msg: Message) => boolean,
|
||||||
querySource,
|
querySource,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
@@ -1084,7 +1084,7 @@ async function* queryLoop(
|
|||||||
// prevents a spiral and the error surfaces.
|
// prevents a spiral and the error surfaces.
|
||||||
const isWithheldMedia =
|
const isWithheldMedia =
|
||||||
mediaRecoveryEnabled &&
|
mediaRecoveryEnabled &&
|
||||||
reactiveCompact?.isWithheldMediaSizeError(lastMessage)
|
reactiveCompact?.isWithheldMediaSizeError(lastMessage as Message)
|
||||||
if (isWithheld413) {
|
if (isWithheld413) {
|
||||||
// First: drain all staged context-collapses. Gated on the PREVIOUS
|
// First: drain all staged context-collapses. Gated on the PREVIOUS
|
||||||
// transition not being collapse_drain_retry — if we already drained
|
// transition not being collapse_drain_retry — if we already drained
|
||||||
@@ -1173,8 +1173,8 @@ async function* queryLoop(
|
|||||||
// so hooks have nothing meaningful to evaluate. Running stop hooks
|
// so hooks have nothing meaningful to evaluate. Running stop hooks
|
||||||
// on prompt-too-long creates a death spiral: error → hook blocking
|
// on prompt-too-long creates a death spiral: error → hook blocking
|
||||||
// → retry → error → … (the hook injects more tokens each cycle).
|
// → retry → error → … (the hook injects more tokens each cycle).
|
||||||
yield lastMessage
|
yield lastMessage!
|
||||||
void executeStopFailureHooks(lastMessage, toolUseContext)
|
void executeStopFailureHooks(lastMessage!, toolUseContext)
|
||||||
return { reason: isWithheldMedia ? 'image_error' : 'prompt_too_long' }
|
return { reason: isWithheldMedia ? 'image_error' : 'prompt_too_long' }
|
||||||
} else if (feature('CONTEXT_COLLAPSE') && isWithheld413) {
|
} else if (feature('CONTEXT_COLLAPSE') && isWithheld413) {
|
||||||
// reactiveCompact compiled out but contextCollapse withheld and
|
// reactiveCompact compiled out but contextCollapse withheld and
|
||||||
@@ -1390,7 +1390,7 @@ async function* queryLoop(
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
update.message.type === 'attachment' &&
|
update.message.type === 'attachment' &&
|
||||||
update.message.attachment.type === 'hook_stopped_continuation'
|
update.message.attachment!.type === 'hook_stopped_continuation'
|
||||||
) {
|
) {
|
||||||
shouldPreventContinuation = true
|
shouldPreventContinuation = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ export async function* handleStopHooks(
|
|||||||
// but before gracefulShutdownSync (see drainPendingExtraction).
|
// but before gracefulShutdownSync (see drainPendingExtraction).
|
||||||
void extractMemoriesModule!.executeExtractMemories(
|
void extractMemoriesModule!.executeExtractMemories(
|
||||||
stopHookContext,
|
stopHookContext,
|
||||||
toolUseContext.appendSystemMessage,
|
toolUseContext.appendSystemMessage as ((msg: import('../types/message.js').SystemMessage) => void) | undefined,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (!toolUseContext.agentId) {
|
if (!toolUseContext.agentId) {
|
||||||
@@ -215,7 +215,7 @@ export async function* handleStopHooks(
|
|||||||
}
|
}
|
||||||
// Track errors and output from attachments
|
// Track errors and output from attachments
|
||||||
if (result.message.type === 'attachment') {
|
if (result.message.type === 'attachment') {
|
||||||
const attachment = result.message.attachment
|
const attachment = result.message.attachment!
|
||||||
if (
|
if (
|
||||||
'hookEvent' in attachment &&
|
'hookEvent' in attachment &&
|
||||||
(attachment.hookEvent === 'Stop' ||
|
(attachment.hookEvent === 'Stop' ||
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ import { createUserMessage } from '../utils/messages.js'
|
|||||||
function convertAssistantMessage(msg: SDKAssistantMessage): AssistantMessage {
|
function convertAssistantMessage(msg: SDKAssistantMessage): AssistantMessage {
|
||||||
return {
|
return {
|
||||||
type: 'assistant',
|
type: 'assistant',
|
||||||
message: msg.message,
|
message: msg.message!,
|
||||||
uuid: msg.uuid,
|
uuid: msg.uuid!,
|
||||||
requestId: undefined,
|
requestId: undefined,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
error: msg.error,
|
error: msg.error,
|
||||||
@@ -64,7 +64,7 @@ function convertResultMessage(msg: SDKResultMessage): SystemMessage {
|
|||||||
subtype: 'informational',
|
subtype: 'informational',
|
||||||
content,
|
content,
|
||||||
level: isError ? 'warning' : 'info',
|
level: isError ? 'warning' : 'info',
|
||||||
uuid: msg.uuid,
|
uuid: msg.uuid!,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ function convertInitMessage(msg: SDKSystemMessage): SystemMessage {
|
|||||||
subtype: 'informational',
|
subtype: 'informational',
|
||||||
content: `Remote session initialized (model: ${msg.model})`,
|
content: `Remote session initialized (model: ${msg.model})`,
|
||||||
level: 'info',
|
level: 'info',
|
||||||
uuid: msg.uuid,
|
uuid: msg.uuid!,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ function convertStatusMessage(msg: SDKStatusMessage): SystemMessage | null {
|
|||||||
? 'Compacting conversation…'
|
? 'Compacting conversation…'
|
||||||
: `Status: ${msg.status}`,
|
: `Status: ${msg.status}`,
|
||||||
level: 'info',
|
level: 'info',
|
||||||
uuid: msg.uuid,
|
uuid: msg.uuid!,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@ function convertToolProgressMessage(
|
|||||||
subtype: 'informational',
|
subtype: 'informational',
|
||||||
content: `Tool ${msg.tool_name} running for ${msg.elapsed_time_seconds}s…`,
|
content: `Tool ${msg.tool_name} running for ${msg.elapsed_time_seconds}s…`,
|
||||||
level: 'info',
|
level: 'info',
|
||||||
uuid: msg.uuid,
|
uuid: msg.uuid!,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
toolUseID: msg.tool_use_id,
|
toolUseID: msg.tool_use_id,
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ function convertCompactBoundaryMessage(
|
|||||||
subtype: 'compact_boundary',
|
subtype: 'compact_boundary',
|
||||||
content: 'Conversation compacted',
|
content: 'Conversation compacted',
|
||||||
level: 'info',
|
level: 'info',
|
||||||
uuid: msg.uuid,
|
uuid: msg.uuid!,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
compactMetadata: fromSDKCompactMetadata(msg.compact_metadata),
|
compactMetadata: fromSDKCompactMetadata(msg.compact_metadata),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2974,11 +2974,11 @@ export function REPL({
|
|||||||
for (const m of messagesRef.current) {
|
for (const m of messagesRef.current) {
|
||||||
if (
|
if (
|
||||||
m.type === 'attachment' &&
|
m.type === 'attachment' &&
|
||||||
m.attachment.type === 'queued_command' &&
|
m.attachment!.type === 'queued_command' &&
|
||||||
m.attachment.commandMode === 'task-notification' &&
|
m.attachment!.commandMode === 'task-notification' &&
|
||||||
typeof m.attachment.prompt === 'string'
|
typeof m.attachment!.prompt === 'string'
|
||||||
) {
|
) {
|
||||||
existingPrompts.add(m.attachment.prompt);
|
existingPrompts.add(m.attachment!.prompt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const uniqueNotifications = notificationMessages.filter(
|
const uniqueNotifications = notificationMessages.filter(
|
||||||
@@ -3156,7 +3156,7 @@ export function REPL({
|
|||||||
// title silently fell through to the "Claude Code" default.
|
// title silently fell through to the "Claude Code" default.
|
||||||
if (!titleDisabled && !sessionTitle && !agentTitle && !haikuTitleAttemptedRef.current) {
|
if (!titleDisabled && !sessionTitle && !agentTitle && !haikuTitleAttemptedRef.current) {
|
||||||
const firstUserMessage = newMessages.find(m => m.type === 'user' && !m.isMeta);
|
const firstUserMessage = newMessages.find(m => m.type === 'user' && !m.isMeta);
|
||||||
const text = firstUserMessage?.type === 'user' ? getContentText(firstUserMessage.message.content) : null;
|
const text = firstUserMessage?.type === 'user' ? getContentText(firstUserMessage.message!.content as string | ContentBlockParam[]) : null;
|
||||||
// Skip synthetic breadcrumbs — slash-command output, prompt-skill
|
// Skip synthetic breadcrumbs — slash-command output, prompt-skill
|
||||||
// expansions (/commit → <command-message>), local-command headers
|
// expansions (/commit → <command-message>), local-command headers
|
||||||
// (/help → <command-name>), and bash-mode (!cmd → <bash-input>).
|
// (/help → <command-name>), and bash-mode (!cmd → <bash-input>).
|
||||||
@@ -3419,7 +3419,7 @@ export function REPL({
|
|||||||
// replayed as user-visible text.
|
// replayed as user-visible text.
|
||||||
newMessages
|
newMessages
|
||||||
.filter((m): m is UserMessage => m.type === 'user' && !m.isMeta)
|
.filter((m): m is UserMessage => m.type === 'user' && !m.isMeta)
|
||||||
.map(_ => getContentText(_.message.content))
|
.map(_ => getContentText(_.message.content as string | ContentBlockParam[]))
|
||||||
.filter(_ => _ !== null)
|
.filter(_ => _ !== null)
|
||||||
.forEach((msg, i) => {
|
.forEach((msg, i) => {
|
||||||
enqueue({ value: msg, mode: 'prompt' });
|
enqueue({ value: msg, mode: 'prompt' });
|
||||||
@@ -3658,13 +3658,13 @@ export function REPL({
|
|||||||
...prev,
|
...prev,
|
||||||
initialMessage: null,
|
initialMessage: null,
|
||||||
toolPermissionContext: updatedToolPermissionContext,
|
toolPermissionContext: updatedToolPermissionContext,
|
||||||
...(shouldStorePlanForVerification && {
|
...(shouldStorePlanForVerification ? {
|
||||||
pendingPlanVerification: {
|
pendingPlanVerification: {
|
||||||
plan: initialMsg.message.planContent as string,
|
plan: initialMsg.message.planContent as string,
|
||||||
verificationStarted: false,
|
verificationStarted: false,
|
||||||
verificationCompleted: false,
|
verificationCompleted: false,
|
||||||
},
|
},
|
||||||
}),
|
} : {}),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -4381,7 +4381,7 @@ export function REPL({
|
|||||||
const newPastedContents: Record<number, PastedContent> = {};
|
const newPastedContents: Record<number, PastedContent> = {};
|
||||||
imageBlocks.forEach((block, index) => {
|
imageBlocks.forEach((block, index) => {
|
||||||
if (block.source.type === 'base64') {
|
if (block.source.type === 'base64') {
|
||||||
const id = message.imagePasteIds?.[index] ?? index + 1;
|
const id = (message.imagePasteIds as number[] | undefined)?.[index] ?? index + 1;
|
||||||
newPastedContents[id] = {
|
newPastedContents[id] = {
|
||||||
id,
|
id,
|
||||||
type: 'image',
|
type: 'image',
|
||||||
@@ -4880,7 +4880,7 @@ export function REPL({
|
|||||||
// Count completed hooks
|
// Count completed hooks
|
||||||
const completedCount = count(messages, m => {
|
const completedCount = count(messages, m => {
|
||||||
if (m.type !== 'attachment') return false;
|
if (m.type !== 'attachment') return false;
|
||||||
const attachment = m.attachment;
|
const attachment = m.attachment!;
|
||||||
return (
|
return (
|
||||||
'hookEvent' in attachment &&
|
'hookEvent' in attachment &&
|
||||||
(attachment.hookEvent === 'Stop' || attachment.hookEvent === 'SubagentStop') &&
|
(attachment.hookEvent === 'Stop' || attachment.hookEvent === 'SubagentStop') &&
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ export function startAgentSummarization(
|
|||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const contentArr = Array.isArray(msg.message.content) ? msg.message.content : []
|
const contentArr = Array.isArray(msg.message!.content) ? msg.message!.content : []
|
||||||
const textBlock = contentArr.find(b => b.type === 'text')
|
const textBlock = contentArr.find(b => b.type === 'text')
|
||||||
if (textBlock?.type === 'text' && textBlock.text.trim()) {
|
if (textBlock?.type === 'text' && textBlock.text.trim()) {
|
||||||
const summaryText = textBlock.text.trim()
|
const summaryText = textBlock.text.trim()
|
||||||
|
|||||||
@@ -243,11 +243,11 @@ export function getParentCacheSuppressReason(
|
|||||||
): string | null {
|
): string | null {
|
||||||
if (!lastAssistantMessage) return null
|
if (!lastAssistantMessage) return null
|
||||||
|
|
||||||
const usage = lastAssistantMessage.message.usage
|
const usage = lastAssistantMessage.message!.usage
|
||||||
const inputTokens = usage.input_tokens ?? 0
|
const inputTokens = usage!.input_tokens ?? 0
|
||||||
const cacheWriteTokens = usage.cache_creation_input_tokens ?? 0
|
const cacheWriteTokens = usage!.cache_creation_input_tokens ?? 0
|
||||||
// The fork re-processes the parent's output (never cached) plus its own prompt.
|
// The fork re-processes the parent's output (never cached) plus its own prompt.
|
||||||
const outputTokens = usage.output_tokens ?? 0
|
const outputTokens = usage!.output_tokens ?? 0
|
||||||
|
|
||||||
return (inputTokens as number) + (cacheWriteTokens as number) + (outputTokens as number) >
|
return (inputTokens as number) + (cacheWriteTokens as number) + (outputTokens as number) >
|
||||||
MAX_PARENT_UNCACHED_TOKENS
|
MAX_PARENT_UNCACHED_TOKENS
|
||||||
@@ -339,7 +339,7 @@ export async function generateSuggestion(
|
|||||||
|
|
||||||
for (const msg of result.messages) {
|
for (const msg of result.messages) {
|
||||||
if (msg.type !== 'assistant') continue
|
if (msg.type !== 'assistant') continue
|
||||||
const contentArr = Array.isArray(msg.message.content) ? msg.message.content as Array<{ type: string; text?: string }> : []
|
const contentArr = Array.isArray(msg.message!.content) ? msg.message!.content as Array<{ type: string; text?: string }> : []
|
||||||
const textBlock = contentArr.find(b => b.type === 'text')
|
const textBlock = contentArr.find(b => b.type === 'text')
|
||||||
if (textBlock?.type === 'text' && typeof textBlock.text === 'string') {
|
if (textBlock?.type === 'text' && typeof textBlock.text === 'string') {
|
||||||
const suggestion = textBlock.text.trim()
|
const suggestion = textBlock.text.trim()
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ function getBoundaryDetail(
|
|||||||
function isUserMessageWithArrayContent(
|
function isUserMessageWithArrayContent(
|
||||||
m: Message,
|
m: Message,
|
||||||
): m is Message & { message: { content: unknown[] } } {
|
): m is Message & { message: { content: unknown[] } } {
|
||||||
return m.type === 'user' && 'message' in m && Array.isArray(m.message.content)
|
return m.type === 'user' && 'message' in m && Array.isArray(m.message?.content)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function prepareMessagesForInjection(messages: Message[]): Message[] {
|
export function prepareMessagesForInjection(messages: Message[]): Message[] {
|
||||||
@@ -254,9 +254,9 @@ export function prepareMessagesForInjection(messages: Message[]): Message[] {
|
|||||||
|
|
||||||
return messages
|
return messages
|
||||||
.map(msg => {
|
.map(msg => {
|
||||||
if (!('message' in msg) || !Array.isArray(msg.message.content)) return msg
|
if (!('message' in msg) || !Array.isArray(msg.message?.content)) return msg
|
||||||
const content = msg.message.content.filter(keep)
|
const content = msg.message!.content.filter(keep)
|
||||||
if (content.length === msg.message.content.length) return msg
|
if (content.length === msg.message!.content.length) return msg
|
||||||
if (content.length === 0) return null
|
if (content.length === 0) return null
|
||||||
// Drop messages where all remaining blocks are whitespace-only text
|
// Drop messages where all remaining blocks are whitespace-only text
|
||||||
// (API rejects these with 400: "text content blocks must contain non-whitespace text")
|
// (API rejects these with 400: "text content blocks must contain non-whitespace text")
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ function countToolCallsSince(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (message.type === 'assistant') {
|
if (message.type === 'assistant') {
|
||||||
const content = message.message.content
|
const content = message.message!.content
|
||||||
if (Array.isArray(content)) {
|
if (Array.isArray(content)) {
|
||||||
toolCallCount += count(content, block => block.type === 'tool_use')
|
toolCallCount += count(content, block => block.type === 'tool_use')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -579,13 +579,13 @@ export function userMessageToMessageParam(
|
|||||||
querySource?: QuerySource,
|
querySource?: QuerySource,
|
||||||
): MessageParam {
|
): MessageParam {
|
||||||
if (addCache) {
|
if (addCache) {
|
||||||
if (typeof message.message.content === 'string') {
|
if (typeof message.message!.content === 'string') {
|
||||||
return {
|
return {
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: message.message.content,
|
text: message.message!.content,
|
||||||
...(enablePromptCaching && {
|
...(enablePromptCaching && {
|
||||||
cache_control: getCacheControl({ querySource }),
|
cache_control: getCacheControl({ querySource }),
|
||||||
}),
|
}),
|
||||||
@@ -595,9 +595,9 @@ export function userMessageToMessageParam(
|
|||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: message.message.content.map((_, i) => ({
|
content: message.message!.content!.map((_, i) => ({
|
||||||
..._,
|
..._,
|
||||||
...(i === message.message.content.length - 1
|
...(i === message.message!.content!.length - 1
|
||||||
? enablePromptCaching
|
? enablePromptCaching
|
||||||
? { cache_control: getCacheControl({ querySource }) }
|
? { cache_control: getCacheControl({ querySource }) }
|
||||||
: {}
|
: {}
|
||||||
@@ -611,9 +611,9 @@ export function userMessageToMessageParam(
|
|||||||
// to addCacheBreakpoints share the same array and each splices in duplicate cache_edits.
|
// to addCacheBreakpoints share the same array and each splices in duplicate cache_edits.
|
||||||
return {
|
return {
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: Array.isArray(message.message.content)
|
content: (Array.isArray(message.message!.content)
|
||||||
? [...message.message.content]
|
? [...message.message!.content]
|
||||||
: message.message.content,
|
: message.message!.content) as import('@anthropic-ai/sdk/resources/beta/messages/messages.js').BetaContentBlockParam[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,13 +624,13 @@ export function assistantMessageToMessageParam(
|
|||||||
querySource?: QuerySource,
|
querySource?: QuerySource,
|
||||||
): MessageParam {
|
): MessageParam {
|
||||||
if (addCache) {
|
if (addCache) {
|
||||||
if (typeof message.message.content === 'string') {
|
if (typeof message.message!.content === 'string') {
|
||||||
return {
|
return {
|
||||||
role: 'assistant',
|
role: 'assistant',
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: message.message.content,
|
text: message.message!.content,
|
||||||
...(enablePromptCaching && {
|
...(enablePromptCaching && {
|
||||||
cache_control: getCacheControl({ querySource }),
|
cache_control: getCacheControl({ querySource }),
|
||||||
}),
|
}),
|
||||||
@@ -640,11 +640,11 @@ export function assistantMessageToMessageParam(
|
|||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
role: 'assistant',
|
role: 'assistant',
|
||||||
content: message.message.content.map((_, i) => {
|
content: message.message!.content!.map((_, i) => {
|
||||||
const contentBlock = stripGeminiProviderMetadata(_)
|
const contentBlock = stripGeminiProviderMetadata(_)
|
||||||
return {
|
return {
|
||||||
...contentBlock,
|
...contentBlock,
|
||||||
...(i === message.message.content.length - 1 &&
|
...(i === message.message!.content!.length - 1 &&
|
||||||
contentBlock.type !== 'thinking' &&
|
contentBlock.type !== 'thinking' &&
|
||||||
contentBlock.type !== 'redacted_thinking' &&
|
contentBlock.type !== 'redacted_thinking' &&
|
||||||
(feature('CONNECTOR_TEXT')
|
(feature('CONNECTOR_TEXT')
|
||||||
@@ -662,9 +662,9 @@ export function assistantMessageToMessageParam(
|
|||||||
return {
|
return {
|
||||||
role: 'assistant',
|
role: 'assistant',
|
||||||
content:
|
content:
|
||||||
typeof message.message.content === 'string'
|
typeof message.message!.content === 'string'
|
||||||
? message.message.content
|
? message.message!.content
|
||||||
: message.message.content.map(stripGeminiProviderMetadata) as BetaContentBlockParam[],
|
: message.message!.content!.map(stripGeminiProviderMetadata) as BetaContentBlockParam[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -972,8 +972,8 @@ export function stripExcessMediaItems(
|
|||||||
): (UserMessage | AssistantMessage)[] {
|
): (UserMessage | AssistantMessage)[] {
|
||||||
let toRemove = 0
|
let toRemove = 0
|
||||||
for (const msg of messages) {
|
for (const msg of messages) {
|
||||||
if (!Array.isArray(msg.message.content)) continue
|
if (!Array.isArray(msg.message!.content)) continue
|
||||||
for (const block of msg.message.content) {
|
for (const block of msg.message!.content) {
|
||||||
if (isMedia(block)) toRemove++
|
if (isMedia(block)) toRemove++
|
||||||
if (isToolResult(block) && Array.isArray(block.content)) {
|
if (isToolResult(block) && Array.isArray(block.content)) {
|
||||||
for (const nested of block.content) {
|
for (const nested of block.content) {
|
||||||
@@ -987,7 +987,7 @@ export function stripExcessMediaItems(
|
|||||||
|
|
||||||
return messages.map(msg => {
|
return messages.map(msg => {
|
||||||
if (toRemove <= 0) return msg
|
if (toRemove <= 0) return msg
|
||||||
const content = msg.message.content
|
const content = msg.message!.content
|
||||||
if (!Array.isArray(content)) return msg
|
if (!Array.isArray(content)) return msg
|
||||||
|
|
||||||
const before = toRemove
|
const before = toRemove
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export function isPromptTooLongMessage(msg: AssistantMessage): boolean {
|
|||||||
if (!msg.isApiErrorMessage) {
|
if (!msg.isApiErrorMessage) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const content = msg.message.content
|
const content = msg.message!.content
|
||||||
if (!Array.isArray(content)) {
|
if (!Array.isArray(content)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -230,7 +230,7 @@ function logToolUseToolResultMismatch(
|
|||||||
for (let i = 0; i < messagesForAPI.length; i++) {
|
for (let i = 0; i < messagesForAPI.length; i++) {
|
||||||
const msg = messagesForAPI[i]
|
const msg = messagesForAPI[i]
|
||||||
if (!msg) continue
|
if (!msg) continue
|
||||||
const content = msg.message.content
|
const content = msg.message!.content
|
||||||
if (Array.isArray(content)) {
|
if (Array.isArray(content)) {
|
||||||
for (const block of content) {
|
for (const block of content) {
|
||||||
if (
|
if (
|
||||||
@@ -252,7 +252,7 @@ function logToolUseToolResultMismatch(
|
|||||||
const msg = messages[i]
|
const msg = messages[i]
|
||||||
if (!msg) continue
|
if (!msg) continue
|
||||||
if (msg.type === 'assistant' && 'message' in msg) {
|
if (msg.type === 'assistant' && 'message' in msg) {
|
||||||
const content = msg.message.content
|
const content = msg.message!.content
|
||||||
if (Array.isArray(content)) {
|
if (Array.isArray(content)) {
|
||||||
for (const block of content) {
|
for (const block of content) {
|
||||||
if (
|
if (
|
||||||
@@ -274,10 +274,10 @@ function logToolUseToolResultMismatch(
|
|||||||
for (let i = normalizedIndex + 1; i < messagesForAPI.length; i++) {
|
for (let i = normalizedIndex + 1; i < messagesForAPI.length; i++) {
|
||||||
const msg = messagesForAPI[i]
|
const msg = messagesForAPI[i]
|
||||||
if (!msg) continue
|
if (!msg) continue
|
||||||
const content = msg.message.content
|
const content = msg.message!.content
|
||||||
if (Array.isArray(content)) {
|
if (Array.isArray(content)) {
|
||||||
for (const block of content) {
|
for (const block of content) {
|
||||||
const role = msg.message.role
|
const role = msg.message!.role
|
||||||
if (block.type === 'tool_use' && 'id' in block) {
|
if (block.type === 'tool_use' && 'id' in block) {
|
||||||
normalizedSeq.push(`${role}:tool_use:${block.id}`)
|
normalizedSeq.push(`${role}:tool_use:${block.id}`)
|
||||||
} else if (block.type === 'tool_result' && 'tool_use_id' in block) {
|
} else if (block.type === 'tool_result' && 'tool_use_id' in block) {
|
||||||
@@ -307,10 +307,10 @@ function logToolUseToolResultMismatch(
|
|||||||
case 'user':
|
case 'user':
|
||||||
case 'assistant': {
|
case 'assistant': {
|
||||||
if ('message' in msg) {
|
if ('message' in msg) {
|
||||||
const content = msg.message.content
|
const content = msg.message!.content
|
||||||
if (Array.isArray(content)) {
|
if (Array.isArray(content)) {
|
||||||
for (const block of content) {
|
for (const block of content) {
|
||||||
const role = msg.message.role
|
const role = msg.message!.role
|
||||||
if (block.type === 'tool_use' && 'id' in block) {
|
if (block.type === 'tool_use' && 'id' in block) {
|
||||||
preNormalizedSeq.push(`${role}:tool_use:${block.id}`)
|
preNormalizedSeq.push(`${role}:tool_use:${block.id}`)
|
||||||
} else if (
|
} else if (
|
||||||
@@ -331,14 +331,14 @@ function logToolUseToolResultMismatch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (typeof content === 'string') {
|
} else if (typeof content === 'string') {
|
||||||
preNormalizedSeq.push(`${msg.message.role}:string_content`)
|
preNormalizedSeq.push(`${msg.message!.role}:string_content`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'attachment':
|
case 'attachment':
|
||||||
if ('attachment' in msg) {
|
if ('attachment' in msg) {
|
||||||
preNormalizedSeq.push(`attachment:${msg.attachment.type}`)
|
preNormalizedSeq.push(`attachment:${msg.attachment!.type}`)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case 'system':
|
case 'system':
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ function convertInternalUserMessage(
|
|||||||
return {
|
return {
|
||||||
role: 'user',
|
role: 'user',
|
||||||
parts: content.flatMap(block =>
|
parts: content.flatMap(block =>
|
||||||
convertUserContentBlockToGeminiParts(block, toolNamesById),
|
convertUserContentBlockToGeminiParts(block as unknown as string | Record<string, unknown>, toolNamesById),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,9 +45,8 @@ export async function* adaptGeminiStreamToAnthropic(
|
|||||||
cache_read_input_tokens: 0,
|
cache_read_input_tokens: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as BetaRawMessageStreamEvent
|
} as unknown as BetaRawMessageStreamEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
const candidate = chunk.candidates?.[0]
|
const candidate = chunk.candidates?.[0]
|
||||||
const parts = candidate?.content?.parts ?? []
|
const parts = candidate?.content?.parts ?? []
|
||||||
|
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ describe('buildOpenAIRequestBody — thinking params', () => {
|
|||||||
const body = buildOpenAIRequestBody({ ...baseParams, enableThinking: true })
|
const body = buildOpenAIRequestBody({ ...baseParams, enableThinking: true })
|
||||||
expect(body.thinking).toEqual({ type: 'enabled' })
|
expect(body.thinking).toEqual({ type: 'enabled' })
|
||||||
expect(body.enable_thinking).toBe(true)
|
expect(body.enable_thinking).toBe(true)
|
||||||
expect(body.chat_template_kwargs.thinking).toBe(true)
|
expect(body.chat_template_kwargs!.thinking).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('does NOT include thinking params when disabled', () => {
|
test('does NOT include thinking params when disabled', () => {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import type {
|
|||||||
SystemAPIErrorMessage,
|
SystemAPIErrorMessage,
|
||||||
AssistantMessage,
|
AssistantMessage,
|
||||||
} from '../../../types/message.js'
|
} from '../../../types/message.js'
|
||||||
|
import type { AgentId } from '../../../types/ids.js'
|
||||||
import type { Tools } from '../../../Tool.js'
|
import type { Tools } from '../../../Tool.js'
|
||||||
import type { Stream } from 'openai/streaming.mjs'
|
import type { Stream } from 'openai/streaming.mjs'
|
||||||
import type {
|
import type {
|
||||||
@@ -149,7 +150,7 @@ function assembleFinalAssistantOutputs(params: {
|
|||||||
outputs.push({
|
outputs.push({
|
||||||
message: {
|
message: {
|
||||||
...partialMessage,
|
...partialMessage,
|
||||||
content: normalizeContentFromAPI(allBlocks, tools, agentId),
|
content: normalizeContentFromAPI(allBlocks, tools, agentId as AgentId | undefined),
|
||||||
usage,
|
usage,
|
||||||
stop_reason: stopReason,
|
stop_reason: stopReason,
|
||||||
stop_sequence: null,
|
stop_sequence: null,
|
||||||
|
|||||||
@@ -111,9 +111,10 @@ export async function* adaptOpenAIStreamToAnthropic(
|
|||||||
cache_read_input_tokens: cachedReadTokens,
|
cache_read_input_tokens: cachedReadTokens,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as BetaRawMessageStreamEvent
|
} as unknown as BetaRawMessageStreamEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip chunks that carry only usage data (no delta content)
|
||||||
if (!delta) continue
|
if (!delta) continue
|
||||||
|
|
||||||
// Handle reasoning_content → Anthropic thinking block
|
// Handle reasoning_content → Anthropic thinking block
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ function makeDreamProgressWatcher(
|
|||||||
let text = ''
|
let text = ''
|
||||||
let toolUseCount = 0
|
let toolUseCount = 0
|
||||||
const touchedPaths: string[] = []
|
const touchedPaths: string[] = []
|
||||||
const contentBlocks = msg.message.content as ContentBlockParam[]
|
const contentBlocks = msg.message!.content as ContentBlockParam[]
|
||||||
for (const block of contentBlocks) {
|
for (const block of contentBlocks) {
|
||||||
if (block.type === 'text') {
|
if (block.type === 'text') {
|
||||||
text += block.text
|
text += block.text
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ describe("groupMessagesByApiRound", () => {
|
|||||||
test("preserves message order within groups", () => {
|
test("preserves message order within groups", () => {
|
||||||
const messages = [makeMsg("assistant", "a1"), makeMsg("user", "u2")];
|
const messages = [makeMsg("assistant", "a1"), makeMsg("user", "u2")];
|
||||||
const groups = groupMessagesByApiRound(messages);
|
const groups = groupMessagesByApiRound(messages);
|
||||||
expect(groups[0][0].message.id).toBe("a1");
|
expect(groups[0]![0]!.message!.id).toBe("a1");
|
||||||
expect(groups[0][1].message.id).toBe("u2");
|
expect(groups[0]![1]!.message!.id).toBe("u2");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("handles system messages", () => {
|
test("handles system messages", () => {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import {
|
|||||||
getAgentListingDeltaAttachment,
|
getAgentListingDeltaAttachment,
|
||||||
getDeferredToolsDeltaAttachment,
|
getDeferredToolsDeltaAttachment,
|
||||||
getMcpInstructionsDeltaAttachment,
|
getMcpInstructionsDeltaAttachment,
|
||||||
|
type Attachment,
|
||||||
} from '../../utils/attachments.js'
|
} from '../../utils/attachments.js'
|
||||||
import { getMemoryPath } from '../../utils/config.js'
|
import { getMemoryPath } from '../../utils/config.js'
|
||||||
import { COMPACT_MAX_OUTPUT_TOKENS } from '../../utils/context.js'
|
import { COMPACT_MAX_OUTPUT_TOKENS } from '../../utils/context.js'
|
||||||
@@ -114,6 +115,7 @@ import {
|
|||||||
roughTokenCountEstimation,
|
roughTokenCountEstimation,
|
||||||
roughTokenCountEstimationForMessages,
|
roughTokenCountEstimationForMessages,
|
||||||
} from '../tokenEstimation.js'
|
} from '../tokenEstimation.js'
|
||||||
|
import type { SDKStatus } from '../../entrypoints/agentSdkTypes.js'
|
||||||
import { groupMessagesByApiRound } from './grouping.js'
|
import { groupMessagesByApiRound } from './grouping.js'
|
||||||
import {
|
import {
|
||||||
getCompactPrompt,
|
getCompactPrompt,
|
||||||
@@ -150,7 +152,7 @@ export function stripImagesFromMessages(messages: Message[]): Message[] {
|
|||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = message.message.content
|
const content = message.message!.content
|
||||||
if (!Array.isArray(content)) {
|
if (!Array.isArray(content)) {
|
||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
@@ -216,8 +218,8 @@ export function stripReinjectedAttachments(messages: Message[]): Message[] {
|
|||||||
m =>
|
m =>
|
||||||
!(
|
!(
|
||||||
m.type === 'attachment' &&
|
m.type === 'attachment' &&
|
||||||
(m.attachment.type === 'skill_discovery' ||
|
(m.attachment!.type === 'skill_discovery' ||
|
||||||
m.attachment.type === 'skill_listing')
|
m.attachment!.type === 'skill_listing')
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -251,8 +253,8 @@ export function truncateHeadForPTLRetry(
|
|||||||
// (drops only the marker, re-adds it, zero progress on retry 2+).
|
// (drops only the marker, re-adds it, zero progress on retry 2+).
|
||||||
const input =
|
const input =
|
||||||
messages[0]?.type === 'user' &&
|
messages[0]?.type === 'user' &&
|
||||||
messages[0].isMeta &&
|
messages[0]?.isMeta &&
|
||||||
messages[0].message.content === PTL_RETRY_MARKER
|
messages[0]?.message?.content === PTL_RETRY_MARKER
|
||||||
? messages.slice(1)
|
? messages.slice(1)
|
||||||
: messages
|
: messages
|
||||||
|
|
||||||
@@ -760,7 +762,7 @@ export async function compactConversation(
|
|||||||
context.setStreamMode?.('requesting')
|
context.setStreamMode?.('requesting')
|
||||||
context.setResponseLength?.(() => 0)
|
context.setResponseLength?.(() => 0)
|
||||||
context.onCompactProgress?.({ type: 'compact_end' })
|
context.onCompactProgress?.({ type: 'compact_end' })
|
||||||
context.setSDKStatus?.(null)
|
context.setSDKStatus?.("" as SDKStatus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1103,7 +1105,7 @@ export async function partialCompactConversation(
|
|||||||
context.setStreamMode?.('requesting')
|
context.setStreamMode?.('requesting')
|
||||||
context.setResponseLength?.(() => 0)
|
context.setResponseLength?.(() => 0)
|
||||||
context.onCompactProgress?.({ type: 'compact_end' })
|
context.onCompactProgress?.({ type: 'compact_end' })
|
||||||
context.setSDKStatus?.(null)
|
context.setSDKStatus?.("" as SDKStatus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1453,7 +1455,7 @@ export async function createPostCompactFileAttachments(
|
|||||||
)
|
)
|
||||||
|
|
||||||
let usedTokens = 0
|
let usedTokens = 0
|
||||||
return results.filter((result): result is AttachmentMessage => {
|
return results.filter((result): result is AttachmentMessage<Attachment> => {
|
||||||
if (result === null) {
|
if (result === null) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -1613,10 +1615,10 @@ export async function createAsyncAgentAttachmentsIfNeeded(
|
|||||||
function collectReadToolFilePaths(messages: Message[]): Set<string> {
|
function collectReadToolFilePaths(messages: Message[]): Set<string> {
|
||||||
const stubIds = new Set<string>()
|
const stubIds = new Set<string>()
|
||||||
for (const message of messages) {
|
for (const message of messages) {
|
||||||
if (message.type !== 'user' || !Array.isArray(message.message.content)) {
|
if (message.type !== 'user' || !Array.isArray(message.message!.content)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for (const block of message.message.content) {
|
for (const block of message.message!.content) {
|
||||||
if (
|
if (
|
||||||
block.type === 'tool_result' &&
|
block.type === 'tool_result' &&
|
||||||
typeof block.content === 'string' &&
|
typeof block.content === 'string' &&
|
||||||
@@ -1631,11 +1633,11 @@ function collectReadToolFilePaths(messages: Message[]): Set<string> {
|
|||||||
for (const message of messages) {
|
for (const message of messages) {
|
||||||
if (
|
if (
|
||||||
message.type !== 'assistant' ||
|
message.type !== 'assistant' ||
|
||||||
!Array.isArray(message.message.content)
|
!Array.isArray(message.message!.content)
|
||||||
) {
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for (const block of message.message.content) {
|
for (const block of message.message!.content) {
|
||||||
if (
|
if (
|
||||||
block.type !== 'tool_use' ||
|
block.type !== 'tool_use' ||
|
||||||
block.name !== FILE_READ_TOOL_NAME ||
|
block.name !== FILE_READ_TOOL_NAME ||
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export function groupMessagesByApiRound(messages: Message[]): Message[][] {
|
|||||||
for (const msg of messages) {
|
for (const msg of messages) {
|
||||||
if (
|
if (
|
||||||
msg.type === 'assistant' &&
|
msg.type === 'assistant' &&
|
||||||
msg.message.id !== lastAssistantId &&
|
msg.message!.id !== lastAssistantId &&
|
||||||
current.length > 0
|
current.length > 0
|
||||||
) {
|
) {
|
||||||
groups.push(current)
|
groups.push(current)
|
||||||
@@ -52,7 +52,7 @@ export function groupMessagesByApiRound(messages: Message[]): Message[][] {
|
|||||||
current.push(msg)
|
current.push(msg)
|
||||||
}
|
}
|
||||||
if (msg.type === 'assistant') {
|
if (msg.type === 'assistant') {
|
||||||
lastAssistantId = msg.message.id
|
lastAssistantId = msg.message!.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -169,11 +169,11 @@ export function estimateMessageTokens(messages: Message[]): number {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Array.isArray(message.message.content)) {
|
if (!Array.isArray(message.message!.content)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const block of message.message.content) {
|
for (const block of message.message!.content) {
|
||||||
if (block.type === 'text') {
|
if (block.type === 'text') {
|
||||||
totalTokens += roughTokenCountEstimation(block.text)
|
totalTokens += roughTokenCountEstimation(block.text)
|
||||||
} else if (block.type === 'tool_result') {
|
} else if (block.type === 'tool_result') {
|
||||||
@@ -228,9 +228,9 @@ function collectCompactableToolIds(messages: Message[]): string[] {
|
|||||||
for (const message of messages) {
|
for (const message of messages) {
|
||||||
if (
|
if (
|
||||||
message.type === 'assistant' &&
|
message.type === 'assistant' &&
|
||||||
Array.isArray(message.message.content)
|
Array.isArray(message.message!.content)
|
||||||
) {
|
) {
|
||||||
for (const block of message.message.content) {
|
for (const block of message.message!.content) {
|
||||||
if (block.type === 'tool_use' && COMPACTABLE_TOOLS.has(block.name)) {
|
if (block.type === 'tool_use' && COMPACTABLE_TOOLS.has(block.name)) {
|
||||||
ids.push(block.id)
|
ids.push(block.id)
|
||||||
}
|
}
|
||||||
@@ -313,9 +313,9 @@ async function cachedMicrocompactPath(
|
|||||||
const compactableToolIds = new Set(collectCompactableToolIds(messages))
|
const compactableToolIds = new Set(collectCompactableToolIds(messages))
|
||||||
// Second pass: register tool results grouped by user message
|
// Second pass: register tool results grouped by user message
|
||||||
for (const message of messages) {
|
for (const message of messages) {
|
||||||
if (message.type === 'user' && Array.isArray(message.message.content)) {
|
if (message.type === 'user' && Array.isArray(message.message!.content)) {
|
||||||
const groupIds: string[] = []
|
const groupIds: string[] = []
|
||||||
for (const block of message.message.content) {
|
for (const block of message.message!.content) {
|
||||||
if (
|
if (
|
||||||
block.type === 'tool_result' &&
|
block.type === 'tool_result' &&
|
||||||
compactableToolIds.has(block.tool_use_id) &&
|
compactableToolIds.has(block.tool_use_id) &&
|
||||||
@@ -375,7 +375,7 @@ async function cachedMicrocompactPath(
|
|||||||
const baseline =
|
const baseline =
|
||||||
lastAsst?.type === 'assistant'
|
lastAsst?.type === 'assistant'
|
||||||
? ((
|
? ((
|
||||||
lastAsst.message.usage as unknown as Record<
|
lastAsst.message!.usage as unknown as Record<
|
||||||
string,
|
string,
|
||||||
number | undefined
|
number | undefined
|
||||||
>
|
>
|
||||||
@@ -468,11 +468,11 @@ function maybeTimeBasedMicrocompact(
|
|||||||
|
|
||||||
let tokensSaved = 0
|
let tokensSaved = 0
|
||||||
const result: Message[] = messages.map(message => {
|
const result: Message[] = messages.map(message => {
|
||||||
if (message.type !== 'user' || !Array.isArray(message.message.content)) {
|
if (message.type !== 'user' || !Array.isArray(message.message!.content)) {
|
||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
let touched = false
|
let touched = false
|
||||||
const newContent = message.message.content.map(block => {
|
const newContent = message.message!.content.map(block => {
|
||||||
if (
|
if (
|
||||||
block.type === 'tool_result' &&
|
block.type === 'tool_result' &&
|
||||||
clearSet.has(block.tool_use_id) &&
|
clearSet.has(block.tool_use_id) &&
|
||||||
|
|||||||
@@ -134,11 +134,11 @@ async function initSessionMemoryCompactConfig(): Promise<void> {
|
|||||||
*/
|
*/
|
||||||
export function hasTextBlocks(message: Message): boolean {
|
export function hasTextBlocks(message: Message): boolean {
|
||||||
if (message.type === 'assistant') {
|
if (message.type === 'assistant') {
|
||||||
const content = message.message.content
|
const content = message.message!.content
|
||||||
return Array.isArray(content) && content.some(block => block.type === 'text')
|
return Array.isArray(content) && content.some(block => block.type === 'text')
|
||||||
}
|
}
|
||||||
if (message.type === 'user') {
|
if (message.type === 'user') {
|
||||||
const content = message.message.content
|
const content = message.message!.content
|
||||||
if (typeof content === 'string') {
|
if (typeof content === 'string') {
|
||||||
return content.length > 0
|
return content.length > 0
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ function getToolResultIds(message: Message): string[] {
|
|||||||
if (message.type !== 'user') {
|
if (message.type !== 'user') {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
const content = message.message.content
|
const content = message.message!.content
|
||||||
if (!Array.isArray(content)) {
|
if (!Array.isArray(content)) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@@ -176,7 +176,7 @@ function hasToolUseWithIds(message: Message, toolUseIds: Set<string>): boolean {
|
|||||||
if (message.type !== 'assistant') {
|
if (message.type !== 'assistant') {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
const content = message.message.content
|
const content = message.message!.content
|
||||||
if (!Array.isArray(content)) {
|
if (!Array.isArray(content)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -251,8 +251,8 @@ export function adjustIndexToPreserveAPIInvariants(
|
|||||||
const toolUseIdsInKeptRange = new Set<string>()
|
const toolUseIdsInKeptRange = new Set<string>()
|
||||||
for (let i = adjustedIndex; i < messages.length; i++) {
|
for (let i = adjustedIndex; i < messages.length; i++) {
|
||||||
const msg = messages[i]!
|
const msg = messages[i]!
|
||||||
if (msg.type === 'assistant' && Array.isArray(msg.message.content)) {
|
if (msg.type === 'assistant' && Array.isArray(msg.message!.content)) {
|
||||||
for (const block of msg.message.content) {
|
for (const block of msg.message!.content) {
|
||||||
if (block.type === 'tool_use') {
|
if (block.type === 'tool_use') {
|
||||||
toolUseIdsInKeptRange.add(block.id)
|
toolUseIdsInKeptRange.add(block.id)
|
||||||
}
|
}
|
||||||
@@ -273,9 +273,9 @@ export function adjustIndexToPreserveAPIInvariants(
|
|||||||
// Remove found tool_use_ids from the set
|
// Remove found tool_use_ids from the set
|
||||||
if (
|
if (
|
||||||
message.type === 'assistant' &&
|
message.type === 'assistant' &&
|
||||||
Array.isArray(message.message.content)
|
Array.isArray(message.message!.content)
|
||||||
) {
|
) {
|
||||||
for (const block of message.message.content) {
|
for (const block of message.message!.content) {
|
||||||
if (block.type === 'tool_use' && neededToolUseIds.has(block.id)) {
|
if (block.type === 'tool_use' && neededToolUseIds.has(block.id)) {
|
||||||
neededToolUseIds.delete(block.id)
|
neededToolUseIds.delete(block.id)
|
||||||
}
|
}
|
||||||
@@ -290,8 +290,8 @@ export function adjustIndexToPreserveAPIInvariants(
|
|||||||
const messageIdsInKeptRange = new Set<string>()
|
const messageIdsInKeptRange = new Set<string>()
|
||||||
for (let i = adjustedIndex; i < messages.length; i++) {
|
for (let i = adjustedIndex; i < messages.length; i++) {
|
||||||
const msg = messages[i]!
|
const msg = messages[i]!
|
||||||
if (msg.type === 'assistant' && msg.message.id) {
|
if (msg.type === 'assistant' && msg.message!.id) {
|
||||||
messageIdsInKeptRange.add(msg.message.id)
|
messageIdsInKeptRange.add(msg.message!.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,8 +301,8 @@ export function adjustIndexToPreserveAPIInvariants(
|
|||||||
const message = messages[i]!
|
const message = messages[i]!
|
||||||
if (
|
if (
|
||||||
message.type === 'assistant' &&
|
message.type === 'assistant' &&
|
||||||
message.message.id &&
|
message.message!.id &&
|
||||||
messageIdsInKeptRange.has(message.message.id)
|
messageIdsInKeptRange.has(message.message!.id)
|
||||||
) {
|
) {
|
||||||
// This message has the same message.id as one in the kept range
|
// This message has the same message.id as one in the kept range
|
||||||
// Include it so thinking blocks can be properly merged
|
// Include it so thinking blocks can be properly merged
|
||||||
|
|||||||
@@ -443,7 +443,7 @@ const externalTips: Tip[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'desktop-shortcut',
|
id: 'desktop-shortcut',
|
||||||
content: async ctx => {
|
content: async (ctx: TipContext) => {
|
||||||
const blue = color('suggestion', ctx.theme)
|
const blue = color('suggestion', ctx.theme)
|
||||||
return `Continue your session in Claude Code Desktop with ${blue('/desktop')}`
|
return `Continue your session in Claude Code Desktop with ${blue('/desktop')}`
|
||||||
},
|
},
|
||||||
@@ -489,24 +489,24 @@ const externalTips: Tip[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'frontend-design-plugin',
|
id: 'frontend-design-plugin',
|
||||||
content: async ctx => {
|
content: async (ctx: TipContext) => {
|
||||||
const blue = color('suggestion', ctx.theme)
|
const blue = color('suggestion', ctx.theme)
|
||||||
return `Working with HTML/CSS? Install the frontend-design plugin:\n${blue(`/plugin install frontend-design@${OFFICIAL_MARKETPLACE_NAME}`)}`
|
return `Working with HTML/CSS? Install the frontend-design plugin:\n${blue(`/plugin install frontend-design@${OFFICIAL_MARKETPLACE_NAME}`)}`
|
||||||
},
|
},
|
||||||
cooldownSessions: 3,
|
cooldownSessions: 3,
|
||||||
isRelevant: async context =>
|
isRelevant: async (context: TipContext) =>
|
||||||
isMarketplacePluginRelevant('frontend-design', context, {
|
isMarketplacePluginRelevant('frontend-design', context, {
|
||||||
filePath: /\.(html|css|htm)$/i,
|
filePath: /\.(html|css|htm)$/i,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'vercel-plugin',
|
id: 'vercel-plugin',
|
||||||
content: async ctx => {
|
content: async (ctx: TipContext) => {
|
||||||
const blue = color('suggestion', ctx.theme)
|
const blue = color('suggestion', ctx.theme)
|
||||||
return `Working with Vercel? Install the vercel plugin:\n${blue(`/plugin install vercel@${OFFICIAL_MARKETPLACE_NAME}`)}`
|
return `Working with Vercel? Install the vercel plugin:\n${blue(`/plugin install vercel@${OFFICIAL_MARKETPLACE_NAME}`)}`
|
||||||
},
|
},
|
||||||
cooldownSessions: 3,
|
cooldownSessions: 3,
|
||||||
isRelevant: async context =>
|
isRelevant: async (context: TipContext) =>
|
||||||
isMarketplacePluginRelevant('vercel', context, {
|
isMarketplacePluginRelevant('vercel', context, {
|
||||||
filePath: /(?:^|[/\\])vercel\.json$/i,
|
filePath: /(?:^|[/\\])vercel\.json$/i,
|
||||||
cli: ['vercel'],
|
cli: ['vercel'],
|
||||||
@@ -514,7 +514,7 @@ const externalTips: Tip[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'effort-high-nudge',
|
id: 'effort-high-nudge',
|
||||||
content: async ctx => {
|
content: async (ctx: TipContext) => {
|
||||||
const blue = color('suggestion', ctx.theme)
|
const blue = color('suggestion', ctx.theme)
|
||||||
const cmd = blue('/effort high')
|
const cmd = blue('/effort high')
|
||||||
const variant = getFeatureValue_CACHED_MAY_BE_STALE<
|
const variant = getFeatureValue_CACHED_MAY_BE_STALE<
|
||||||
@@ -544,7 +544,7 @@ const externalTips: Tip[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'subagent-fanout-nudge',
|
id: 'subagent-fanout-nudge',
|
||||||
content: async ctx => {
|
content: async (ctx: TipContext) => {
|
||||||
const blue = color('suggestion', ctx.theme)
|
const blue = color('suggestion', ctx.theme)
|
||||||
const variant = getFeatureValue_CACHED_MAY_BE_STALE<
|
const variant = getFeatureValue_CACHED_MAY_BE_STALE<
|
||||||
'off' | 'copy_a' | 'copy_b'
|
'off' | 'copy_a' | 'copy_b'
|
||||||
@@ -566,7 +566,7 @@ const externalTips: Tip[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'loop-command-nudge',
|
id: 'loop-command-nudge',
|
||||||
content: async ctx => {
|
content: async (ctx: TipContext) => {
|
||||||
const blue = color('suggestion', ctx.theme)
|
const blue = color('suggestion', ctx.theme)
|
||||||
const variant = getFeatureValue_CACHED_MAY_BE_STALE<
|
const variant = getFeatureValue_CACHED_MAY_BE_STALE<
|
||||||
'off' | 'copy_a' | 'copy_b'
|
'off' | 'copy_a' | 'copy_b'
|
||||||
@@ -589,7 +589,7 @@ const externalTips: Tip[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'guest-passes',
|
id: 'guest-passes',
|
||||||
content: async ctx => {
|
content: async (ctx: TipContext) => {
|
||||||
const claude = color('claude', ctx.theme)
|
const claude = color('claude', ctx.theme)
|
||||||
const reward = getCachedReferrerReward()
|
const reward = getCachedReferrerReward()
|
||||||
return reward
|
return reward
|
||||||
@@ -608,7 +608,7 @@ const externalTips: Tip[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'overage-credit',
|
id: 'overage-credit',
|
||||||
content: async ctx => {
|
content: async (ctx: TipContext) => {
|
||||||
const claude = color('claude', ctx.theme)
|
const claude = color('claude', ctx.theme)
|
||||||
const info = getCachedOverageCreditGrant()
|
const info = getCachedOverageCreditGrant()
|
||||||
const amount = info ? formatGrantAmount(info) : null
|
const amount = info ? formatGrantAmount(info) : null
|
||||||
|
|||||||
@@ -346,8 +346,8 @@ export class StreamingToolExecutor {
|
|||||||
|
|
||||||
const isErrorResult =
|
const isErrorResult =
|
||||||
update.message.type === 'user' &&
|
update.message.type === 'user' &&
|
||||||
Array.isArray(update.message.message.content) &&
|
Array.isArray(update.message.message!.content) &&
|
||||||
update.message.message.content.some(
|
update.message.message!.content.some(
|
||||||
_ => _.type === 'tool_result' && _.is_error === true,
|
_ => _.type === 'tool_result' && _.is_error === true,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -815,7 +815,7 @@ async function checkPermissionsAndCallTool(
|
|||||||
tool,
|
tool,
|
||||||
processedInput,
|
processedInput,
|
||||||
toolUseID,
|
toolUseID,
|
||||||
assistantMessage.message.id,
|
assistantMessage.message.id!,
|
||||||
requestId,
|
requestId,
|
||||||
mcpServerType,
|
mcpServerType,
|
||||||
mcpServerBaseUrl,
|
mcpServerBaseUrl,
|
||||||
@@ -1497,7 +1497,7 @@ async function checkPermissionsAndCallTool(
|
|||||||
toolUseContext,
|
toolUseContext,
|
||||||
tool,
|
tool,
|
||||||
toolUseID,
|
toolUseID,
|
||||||
assistantMessage.message.id,
|
assistantMessage.message.id!,
|
||||||
processedInput,
|
processedInput,
|
||||||
toolOutput,
|
toolOutput,
|
||||||
requestId,
|
requestId,
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export async function* runPostToolUseHooks<Input extends AnyObject, Output>(
|
|||||||
// IMPORTANT: We emit a cancelled event per hook
|
// IMPORTANT: We emit a cancelled event per hook
|
||||||
if (
|
if (
|
||||||
result.message?.type === 'attachment' &&
|
result.message?.type === 'attachment' &&
|
||||||
result.message.attachment.type === 'hook_cancelled'
|
result.message.attachment!.type === 'hook_cancelled'
|
||||||
) {
|
) {
|
||||||
logEvent('tengu_post_tool_hooks_cancelled', {
|
logEvent('tengu_post_tool_hooks_cancelled', {
|
||||||
toolName: sanitizeToolNameForAnalytics(tool.name),
|
toolName: sanitizeToolNameForAnalytics(tool.name),
|
||||||
@@ -96,7 +96,7 @@ export async function* runPostToolUseHooks<Input extends AnyObject, Output>(
|
|||||||
result.message &&
|
result.message &&
|
||||||
!(
|
!(
|
||||||
result.message.type === 'attachment' &&
|
result.message.type === 'attachment' &&
|
||||||
result.message.attachment.type === 'hook_blocking_error'
|
result.message.attachment!.type === 'hook_blocking_error'
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
yield { message: result.message as AttachmentMessage | ProgressMessage<HookProgress> }
|
yield { message: result.message as AttachmentMessage | ProgressMessage<HookProgress> }
|
||||||
@@ -223,7 +223,7 @@ export async function* runPostToolUseFailureHooks<Input extends AnyObject>(
|
|||||||
// Check if we were aborted during hook execution
|
// Check if we were aborted during hook execution
|
||||||
if (
|
if (
|
||||||
result.message?.type === 'attachment' &&
|
result.message?.type === 'attachment' &&
|
||||||
result.message.attachment.type === 'hook_cancelled'
|
result.message.attachment!.type === 'hook_cancelled'
|
||||||
) {
|
) {
|
||||||
logEvent('tengu_post_tool_failure_hooks_cancelled', {
|
logEvent('tengu_post_tool_failure_hooks_cancelled', {
|
||||||
toolName: sanitizeToolNameForAnalytics(tool.name),
|
toolName: sanitizeToolNameForAnalytics(tool.name),
|
||||||
@@ -248,7 +248,7 @@ export async function* runPostToolUseFailureHooks<Input extends AnyObject>(
|
|||||||
result.message &&
|
result.message &&
|
||||||
!(
|
!(
|
||||||
result.message.type === 'attachment' &&
|
result.message.type === 'attachment' &&
|
||||||
result.message.attachment.type === 'hook_blocking_error'
|
result.message.attachment!.type === 'hook_blocking_error'
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
yield { message: result.message as AttachmentMessage | ProgressMessage<HookProgress> }
|
yield { message: result.message as AttachmentMessage | ProgressMessage<HookProgress> }
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ function mapMessages(
|
|||||||
if (typeof _ === 'string') {
|
if (typeof _ === 'string') {
|
||||||
return f(_)
|
return f(_)
|
||||||
}
|
}
|
||||||
return _.map(_ => {
|
return _!.map(_ => {
|
||||||
switch (_.type) {
|
switch (_.type) {
|
||||||
case 'tool_result':
|
case 'tool_result':
|
||||||
if (typeof _.content === 'string') {
|
if (typeof _.content === 'string') {
|
||||||
|
|||||||
@@ -106,14 +106,14 @@ export function updateProgressFromMessage(
|
|||||||
if (message.type !== 'assistant') {
|
if (message.type !== 'assistant') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const usage = message.message.usage as BetaUsage
|
const usage = message.message!.usage as BetaUsage
|
||||||
// Keep latest input (it's cumulative in the API), sum outputs
|
// Keep latest input (it's cumulative in the API), sum outputs
|
||||||
tracker.latestInputTokens =
|
tracker.latestInputTokens =
|
||||||
(usage.input_tokens as number) +
|
(usage.input_tokens as number) +
|
||||||
(usage.cache_creation_input_tokens ?? 0) +
|
(usage.cache_creation_input_tokens ?? 0) +
|
||||||
(usage.cache_read_input_tokens ?? 0)
|
(usage.cache_read_input_tokens ?? 0)
|
||||||
tracker.cumulativeOutputTokens += usage.output_tokens as number
|
tracker.cumulativeOutputTokens += usage.output_tokens as number
|
||||||
for (const content of (message.message.content ?? []) as Array<{ type: string; name?: string; input?: unknown }>) {
|
for (const content of (message.message!.content ?? []) as Array<{ type: string; name?: string; input?: unknown }>) {
|
||||||
if (content.type === 'tool_use') {
|
if (content.type === 'tool_use') {
|
||||||
tracker.toolUseCount++
|
tracker.toolUseCount++
|
||||||
// Omit StructuredOutput from preview - it's an internal tool
|
// Omit StructuredOutput from preview - it's an internal tool
|
||||||
|
|||||||
@@ -423,11 +423,11 @@ export function startBackgroundSession({
|
|||||||
const contentBlocks = (msg.message?.content ?? []) as Array<{ type: string; text?: string; name?: string; input?: unknown }>
|
const contentBlocks = (msg.message?.content ?? []) as Array<{ type: string; text?: string; name?: string; input?: unknown }>
|
||||||
for (const block of contentBlocks) {
|
for (const block of contentBlocks) {
|
||||||
if (block.type === 'text') {
|
if (block.type === 'text') {
|
||||||
tokenCount += roughTokenCountEstimation(block.text)
|
tokenCount += roughTokenCountEstimation(block.text ?? '')
|
||||||
} else if (block.type === 'tool_use') {
|
} else if (block.type === 'tool_use') {
|
||||||
toolCount++
|
toolCount++
|
||||||
const activity: ToolActivity = {
|
const activity: ToolActivity = {
|
||||||
toolName: block.name,
|
toolName: block.name ?? '',
|
||||||
input: block.input as Record<string, unknown>,
|
input: block.input as Record<string, unknown>,
|
||||||
}
|
}
|
||||||
recentActivities.push(activity)
|
recentActivities.push(activity)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import {
|
|||||||
type BackgroundRemoteSessionPrecondition,
|
type BackgroundRemoteSessionPrecondition,
|
||||||
checkBackgroundRemoteSessionEligibility,
|
checkBackgroundRemoteSessionEligibility,
|
||||||
} from '../../utils/background/remote/remoteSession.js'
|
} from '../../utils/background/remote/remoteSession.js'
|
||||||
|
export type { BackgroundRemoteSessionPrecondition }
|
||||||
import { logForDebugging } from '../../utils/debug.js'
|
import { logForDebugging } from '../../utils/debug.js'
|
||||||
import { logError } from '../../utils/log.js'
|
import { logError } from '../../utils/log.js'
|
||||||
import { enqueuePendingNotification } from '../../utils/messageQueueManager.js'
|
import { enqueuePendingNotification } from '../../utils/messageQueueManager.js'
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import {
|
|||||||
formatPreconditionError,
|
formatPreconditionError,
|
||||||
getRemoteTaskSessionUrl,
|
getRemoteTaskSessionUrl,
|
||||||
registerRemoteAgentTask,
|
registerRemoteAgentTask,
|
||||||
|
type BackgroundRemoteSessionPrecondition,
|
||||||
} from '../../tasks/RemoteAgentTask/RemoteAgentTask.js'
|
} from '../../tasks/RemoteAgentTask/RemoteAgentTask.js'
|
||||||
import { assembleToolPool } from '../../tools.js'
|
import { assembleToolPool } from '../../tools.js'
|
||||||
import { asAgentId } from '../../types/ids.js'
|
import { asAgentId } from '../../types/ids.js'
|
||||||
@@ -668,7 +669,7 @@ export const AgentTool = buildTool({
|
|||||||
if (process.env.USER_TYPE === 'ant' && effectiveIsolation === 'remote') {
|
if (process.env.USER_TYPE === 'ant' && effectiveIsolation === 'remote') {
|
||||||
const eligibility = await checkRemoteAgentEligibility()
|
const eligibility = await checkRemoteAgentEligibility()
|
||||||
if (!eligibility.eligible) {
|
if (!eligibility.eligible) {
|
||||||
const reasons = (eligibility as { eligible: false; errors: Array<{ type: string; message?: string }> }).errors
|
const reasons = (eligibility as { eligible: false; errors: BackgroundRemoteSessionPrecondition[] }).errors
|
||||||
.map(formatPreconditionError)
|
.map(formatPreconditionError)
|
||||||
.join('\n')
|
.join('\n')
|
||||||
throw new Error(`Cannot launch remote agent:\n${reasons}`)
|
throw new Error(`Cannot launch remote agent:\n${reasons}`)
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import type {
|
import type {
|
||||||
|
ContentBlock,
|
||||||
ToolResultBlockParam,
|
ToolResultBlockParam,
|
||||||
ToolUseBlockParam,
|
ToolUseBlockParam,
|
||||||
} from '@anthropic-ai/sdk/resources/index.mjs'
|
} from '@anthropic-ai/sdk/resources/index.mjs'
|
||||||
|
type BetaContentBlock = ContentBlock | ToolResultBlockParam
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { ConfigurableShortcutHint } from 'src/components/ConfigurableShortcutHint.js'
|
import { ConfigurableShortcutHint } from 'src/components/ConfigurableShortcutHint.js'
|
||||||
import {
|
import {
|
||||||
@@ -555,7 +557,7 @@ export function renderToolUseProgressMessage(
|
|||||||
}
|
}
|
||||||
const message = msg.data.message
|
const message = msg.data.message
|
||||||
return message.message.content.some(
|
return message.message.content.some(
|
||||||
content => content.type === 'tool_use',
|
(content: BetaContentBlock) => content.type === 'tool_use',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -630,7 +632,7 @@ export function renderToolUseProgressMessage(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return data.message.message.content.some(
|
return data.message.message.content.some(
|
||||||
content => content.type === 'tool_use',
|
(content: BetaContentBlock) => content.type === 'tool_use',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -799,7 +801,7 @@ function calculateAgentStats(progressMessages: ProgressMessage<Progress>[]): {
|
|||||||
const message = msg.data.message
|
const message = msg.data.message
|
||||||
return (
|
return (
|
||||||
message.type === 'user' &&
|
message.type === 'user' &&
|
||||||
message.message.content.some(content => content.type === 'tool_result')
|
message.message.content.some((content: BetaContentBlock) => content.type === 'tool_result')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1078,14 +1080,14 @@ export function extractLastToolInfo(
|
|||||||
const message = msg.data.message
|
const message = msg.data.message
|
||||||
return (
|
return (
|
||||||
message.type === 'user' &&
|
message.type === 'user' &&
|
||||||
message.message.content.some(c => c.type === 'tool_result')
|
message.message.content.some((c: BetaContentBlock) => c.type === 'tool_result')
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
if (lastToolResult?.data.message.type === 'user') {
|
if (lastToolResult?.data.message.type === 'user') {
|
||||||
const toolResultBlock = lastToolResult.data.message.message.content.find(
|
const toolResultBlock = lastToolResult.data.message.message.content.find(
|
||||||
c => c.type === 'tool_result',
|
(c: BetaContentBlock) => c.type === 'tool_result',
|
||||||
)
|
)
|
||||||
|
|
||||||
if (toolResultBlock?.type === 'tool_result') {
|
if (toolResultBlock?.type === 'tool_result') {
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export const FORK_AGENT = {
|
|||||||
export function isInForkChild(messages: MessageType[]): boolean {
|
export function isInForkChild(messages: MessageType[]): boolean {
|
||||||
return messages.some(m => {
|
return messages.some(m => {
|
||||||
if (m.type !== 'user') return false
|
if (m.type !== 'user') return false
|
||||||
const content = m.message.content
|
const content = m.message!.content
|
||||||
if (!Array.isArray(content)) return false
|
if (!Array.isArray(content)) return false
|
||||||
return content.some(
|
return content.some(
|
||||||
block =>
|
block =>
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ export const NotebookEditTool = buildTool({
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// First try to find the cell by its actual ID
|
// First try to find the cell by its actual ID
|
||||||
const cellIndex = notebook.cells.findIndex(cell => cell.id === cell_id)
|
const cellIndex = notebook.cells.findIndex((cell: NotebookCell) => cell.id === cell_id)
|
||||||
|
|
||||||
if (cellIndex === -1) {
|
if (cellIndex === -1) {
|
||||||
// If not found, try to parse as a numeric index (cell-N format)
|
// If not found, try to parse as a numeric index (cell-N format)
|
||||||
@@ -352,7 +352,7 @@ export const NotebookEditTool = buildTool({
|
|||||||
cellIndex = 0 // Default to inserting at the beginning if no cell_id is provided
|
cellIndex = 0 // Default to inserting at the beginning if no cell_id is provided
|
||||||
} else {
|
} else {
|
||||||
// First try to find the cell by its actual ID
|
// First try to find the cell by its actual ID
|
||||||
cellIndex = notebook.cells.findIndex(cell => cell.id === cell_id)
|
cellIndex = notebook.cells.findIndex((cell: NotebookCell) => cell.id === cell_id)
|
||||||
|
|
||||||
// If not found, try to parse as a numeric index (cell-N format)
|
// If not found, try to parse as a numeric index (cell-N format)
|
||||||
if (cellIndex === -1) {
|
if (cellIndex === -1) {
|
||||||
|
|||||||
@@ -519,9 +519,9 @@ export async function applyPromptToMarkdown(
|
|||||||
throw new AbortError()
|
throw new AbortError()
|
||||||
}
|
}
|
||||||
|
|
||||||
const { content } = assistantMessage.message
|
const { content } = assistantMessage.message!
|
||||||
if (content.length > 0) {
|
if (content!.length > 0) {
|
||||||
const contentBlock = content[0]
|
const contentBlock = content![0]
|
||||||
if (contentBlock && typeof contentBlock === 'object' && 'text' in contentBlock) {
|
if (contentBlock && typeof contentBlock === 'object' && 'text' in contentBlock) {
|
||||||
return (contentBlock as { text: string }).text
|
return (contentBlock as { text: string }).text
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/types/internal-modules.d.ts
vendored
15
src/types/internal-modules.d.ts
vendored
@@ -15,4 +15,17 @@ declare module "bun:ffi" {
|
|||||||
export function dlopen<T extends Record<string, { args: readonly string[]; returns: string }>>(path: string, symbols: T): { symbols: { [K in keyof T]: (...args: unknown[]) => unknown }; close(): void };
|
export function dlopen<T extends Record<string, { args: readonly string[]; returns: string }>>(path: string, symbols: T): { symbols: { [K in keyof T]: (...args: unknown[]) => unknown }; close(): void };
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Third-party modules without @types packages
|
||||||
|
declare module 'bidi-js' {
|
||||||
|
function getEmbeddingLevels(text: string, defaultDirection?: string): { paragraphLevel: number; levels: Uint8Array }
|
||||||
|
function getReorderSegments(text: string, embeddingLevels: { paragraphLevel: number; levels: Uint8Array }, start?: number, end?: number): [number, number][]
|
||||||
|
function getVisualOrder(reorderSegments: [number, number][]): number[]
|
||||||
|
export { getEmbeddingLevels, getReorderSegments, getVisualOrder }
|
||||||
|
export default { getEmbeddingLevels, getReorderSegments, getVisualOrder }
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'asciichart' {
|
||||||
|
function plot(series: number[] | number[][], config?: Record<string, unknown>): string
|
||||||
|
export { plot }
|
||||||
|
export default { plot }
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export type Message = {
|
|||||||
isCompactSummary?: boolean
|
isCompactSummary?: boolean
|
||||||
toolUseResult?: unknown
|
toolUseResult?: unknown
|
||||||
isVisibleInTranscriptOnly?: boolean
|
isVisibleInTranscriptOnly?: boolean
|
||||||
attachment?: { type: string; toolUseID?: string; [key: string]: unknown }
|
attachment?: { type: string; toolUseID?: string; [key: string]: unknown; addedNames: string[]; addedLines: string[]; removedNames: string[] }
|
||||||
message?: {
|
message?: {
|
||||||
role?: string
|
role?: string
|
||||||
id?: string
|
id?: string
|
||||||
@@ -48,12 +48,19 @@ export type Message = {
|
|||||||
[key: string]: unknown
|
[key: string]: unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AssistantMessage = Message & { type: 'assistant' }
|
export type AssistantMessage = Message & {
|
||||||
export type AttachmentMessage<T = unknown> = Message & { type: 'attachment'; attachment: { type: string; [key: string]: unknown } }
|
type: 'assistant'
|
||||||
|
message: NonNullable<Message['message']>
|
||||||
|
}
|
||||||
|
export type AttachmentMessage<T = { type: string; [key: string]: unknown }> = Message & { type: 'attachment'; attachment: T }
|
||||||
export type ProgressMessage<T = unknown> = Message & { type: 'progress'; data: T }
|
export type ProgressMessage<T = unknown> = Message & { type: 'progress'; data: T }
|
||||||
export type SystemLocalCommandMessage = Message & { type: 'system' }
|
export type SystemLocalCommandMessage = Message & { type: 'system' }
|
||||||
export type SystemMessage = Message & { type: 'system' }
|
export type SystemMessage = Message & { type: 'system' }
|
||||||
export type UserMessage = Message & { type: 'user' }
|
export type UserMessage = Message & {
|
||||||
|
type: 'user'
|
||||||
|
message: NonNullable<Message['message']>
|
||||||
|
imagePasteIds?: number[]
|
||||||
|
}
|
||||||
export type NormalizedUserMessage = UserMessage
|
export type NormalizedUserMessage = UserMessage
|
||||||
export type RequestStartEvent = { type: string; [key: string]: unknown }
|
export type RequestStartEvent = { type: string; [key: string]: unknown }
|
||||||
export type StreamEvent = { type: string; [key: string]: unknown }
|
export type StreamEvent = { type: string; [key: string]: unknown }
|
||||||
|
|||||||
@@ -86,9 +86,9 @@ describe("createAssistantMessage", () => {
|
|||||||
test("creates assistant message with string content", () => {
|
test("creates assistant message with string content", () => {
|
||||||
const msg = createAssistantMessage({ content: "hello" });
|
const msg = createAssistantMessage({ content: "hello" });
|
||||||
expect(msg.type).toBe("assistant");
|
expect(msg.type).toBe("assistant");
|
||||||
expect(msg.message.role).toBe("assistant");
|
expect(msg.message!.role).toBe("assistant");
|
||||||
expect(msg.message.content).toHaveLength(1);
|
expect(msg.message!.content![0] as any).toBeTruthy();
|
||||||
expect((msg.message.content[0] as any).text).toBe("hello");
|
expect((msg.message!.content![0] as any).text).toBe("hello");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("creates assistant message with content blocks", () => {
|
test("creates assistant message with content blocks", () => {
|
||||||
@@ -501,7 +501,7 @@ describe("normalizeMessagesForAPI", () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const normalized = normalizeMessagesForAPI([assistant]);
|
const normalized = normalizeMessagesForAPI([assistant]);
|
||||||
const block = (normalized[0] as AssistantMessage).message.content[0] as any;
|
const block = (normalized[0] as AssistantMessage).message!.content![0] as any;
|
||||||
|
|
||||||
expect(block.type).toBe("tool_use");
|
expect(block.type).toBe("tool_use");
|
||||||
expect(block._geminiThoughtSignature).toBe("sig-123");
|
expect(block._geminiThoughtSignature).toBe("sig-123");
|
||||||
|
|||||||
@@ -445,8 +445,8 @@ async function countBuiltInToolTokens(
|
|||||||
if (messages) {
|
if (messages) {
|
||||||
const deferredToolNameSet = new Set(deferredBuiltinTools.map(t => t.name))
|
const deferredToolNameSet = new Set(deferredBuiltinTools.map(t => t.name))
|
||||||
for (const msg of messages) {
|
for (const msg of messages) {
|
||||||
if (msg.type === 'assistant' && Array.isArray(msg.message.content)) {
|
if (msg.type === 'assistant' && Array.isArray(msg.message!.content)) {
|
||||||
for (const block of msg.message.content) {
|
for (const block of msg.message!.content) {
|
||||||
if (
|
if (
|
||||||
typeof block !== 'string' &&
|
typeof block !== 'string' &&
|
||||||
'type' in block &&
|
'type' in block &&
|
||||||
@@ -683,8 +683,8 @@ export async function countMcpToolTokens(
|
|||||||
if (isDeferred && messages) {
|
if (isDeferred && messages) {
|
||||||
const mcpToolNameSet = new Set(mcpTools.map(t => t.name))
|
const mcpToolNameSet = new Set(mcpTools.map(t => t.name))
|
||||||
for (const msg of messages) {
|
for (const msg of messages) {
|
||||||
if (msg.type === 'assistant' && Array.isArray(msg.message.content)) {
|
if (msg.type === 'assistant' && Array.isArray(msg.message!.content)) {
|
||||||
for (const block of msg.message.content) {
|
for (const block of msg.message!.content) {
|
||||||
if (
|
if (
|
||||||
typeof block !== 'string' &&
|
typeof block !== 'string' &&
|
||||||
'type' in block &&
|
'type' in block &&
|
||||||
@@ -786,7 +786,7 @@ function processAssistantMessage(
|
|||||||
breakdown: MessageBreakdown,
|
breakdown: MessageBreakdown,
|
||||||
): void {
|
): void {
|
||||||
// Process each content block individually
|
// Process each content block individually
|
||||||
const contentBlocks = Array.isArray(msg.message.content) ? msg.message.content : []
|
const contentBlocks = Array.isArray(msg.message!.content) ? msg.message!.content : []
|
||||||
for (const block of contentBlocks) {
|
for (const block of contentBlocks) {
|
||||||
const blockStr = jsonStringify(block)
|
const blockStr = jsonStringify(block)
|
||||||
const blockTokens = roughTokenCountEstimation(blockStr)
|
const blockTokens = roughTokenCountEstimation(blockStr)
|
||||||
@@ -811,20 +811,19 @@ function processUserMessage(
|
|||||||
toolUseIdToName: Map<string, string>,
|
toolUseIdToName: Map<string, string>,
|
||||||
): void {
|
): void {
|
||||||
// Handle both string and array content
|
// Handle both string and array content
|
||||||
if (typeof msg.message.content === 'string') {
|
if (typeof msg.message!.content === 'string') {
|
||||||
// Simple string content
|
// Simple string content
|
||||||
const tokens = roughTokenCountEstimation(msg.message.content)
|
const tokens = roughTokenCountEstimation(msg.message!.content)
|
||||||
breakdown.userMessageTokens += tokens
|
breakdown.userMessageTokens += tokens
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process each content block individually
|
// Process each content block individually
|
||||||
for (const block of msg.message.content) {
|
for (const block of (msg.message!.content ?? [])) {
|
||||||
const blockStr = jsonStringify(block)
|
const blockStr = jsonStringify(block)
|
||||||
const blockTokens = roughTokenCountEstimation(blockStr)
|
const blockTokens = roughTokenCountEstimation(blockStr)
|
||||||
|
|
||||||
if ('type' in block && block.type === 'tool_result') {
|
if ('type' in block && block.type === 'tool_result') {
|
||||||
breakdown.toolResultTokens += blockTokens
|
|
||||||
const toolUseId = 'tool_use_id' in block ? block.tool_use_id : undefined
|
const toolUseId = 'tool_use_id' in block ? block.tool_use_id : undefined
|
||||||
const toolName =
|
const toolName =
|
||||||
(toolUseId ? toolUseIdToName.get(toolUseId) : undefined) || 'unknown'
|
(toolUseId ? toolUseIdToName.get(toolUseId) : undefined) || 'unknown'
|
||||||
@@ -874,8 +873,8 @@ async function approximateMessageTokens(
|
|||||||
// Build a map of tool_use_id to tool_name for easier lookup
|
// Build a map of tool_use_id to tool_name for easier lookup
|
||||||
const toolUseIdToName = new Map<string, string>()
|
const toolUseIdToName = new Map<string, string>()
|
||||||
for (const msg of microcompactResult.messages) {
|
for (const msg of microcompactResult.messages) {
|
||||||
if (msg.type === 'assistant' && Array.isArray(msg.message.content)) {
|
if (msg.type === 'assistant' && Array.isArray(msg.message!.content)) {
|
||||||
for (const block of msg.message.content) {
|
for (const block of msg.message!.content) {
|
||||||
if (typeof block !== 'string' && 'type' in block && block.type === 'tool_use') {
|
if (typeof block !== 'string' && 'type' in block && block.type === 'tool_use') {
|
||||||
const toolUseId = 'id' in block ? (block.id as string) : undefined
|
const toolUseId = 'id' in block ? (block.id as string) : undefined
|
||||||
const toolName =
|
const toolName =
|
||||||
|
|||||||
@@ -193,8 +193,8 @@ export function installAsciicastRecorder(): void {
|
|||||||
) as typeof process.stdout.write
|
) as typeof process.stdout.write
|
||||||
process.stdout.write = function (
|
process.stdout.write = function (
|
||||||
chunk: string | Uint8Array,
|
chunk: string | Uint8Array,
|
||||||
encodingOrCb?: BufferEncoding | ((err?: Error) => void),
|
encodingOrCb?: BufferEncoding | ((err?: Error | null) => void),
|
||||||
cb?: (err?: Error) => void,
|
cb?: (err?: Error | null) => void,
|
||||||
): boolean {
|
): boolean {
|
||||||
// Record the output event
|
// Record the output event
|
||||||
const elapsed = (performance.now() - startTime) / 1000
|
const elapsed = (performance.now() - startTime) / 1000
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user