支持DeepSeek

This commit is contained in:
2025-12-10 16:24:06 +08:00
parent ff3ec65139
commit a53bf1d6e4
5 changed files with 363 additions and 560 deletions
+132 -403
View File
@@ -9,11 +9,14 @@
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@anthropic-ai/sdk": "^0.32.0", "@ai-sdk/anthropic": "^2.0.54",
"@ai-sdk/deepseek": "^1.0.31",
"ai": "^5.0.108",
"chalk": "^5.3.0", "chalk": "^5.3.0",
"commander": "^12.1.0", "commander": "^12.1.0",
"inquirer": "^12.0.0", "inquirer": "^12.0.0",
"ora": "^8.1.0" "ora": "^8.1.0",
"zod": "^4.1.13"
}, },
"bin": { "bin": {
"ai-assist": "dist/index.js" "ai-assist": "dist/index.js"
@@ -24,35 +27,83 @@
"typescript": "^5.6.0" "typescript": "^5.6.0"
} }
}, },
"node_modules/@anthropic-ai/sdk": { "node_modules/@ai-sdk/anthropic": {
"version": "0.32.1", "version": "2.0.54",
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.32.1.tgz", "resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-2.0.54.tgz",
"integrity": "sha512-U9JwTrDvdQ9iWuABVsMLj8nJVwAyQz6QXvgLsVhryhCEPkLsbcP/MXxm+jYcAwLoV8ESbaTTjnD4kuAFa+Hyjg==", "integrity": "sha512-6OSFMkt5NkAchH7o0W+dI2h6yR8EPXx7Yl6txyh0gadLlkf1UU/ScyoYlkxAW8UtGju/+apvwVTdLYEQuIsVVQ==",
"license": "MIT", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@types/node": "^18.11.18", "@ai-sdk/provider": "2.0.0",
"@types/node-fetch": "^2.6.4", "@ai-sdk/provider-utils": "3.0.18"
"abort-controller": "^3.0.0", },
"agentkeepalive": "^4.2.1", "engines": {
"form-data-encoder": "1.7.2", "node": ">=18"
"formdata-node": "^4.3.2", },
"node-fetch": "^2.6.7" "peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
} }
}, },
"node_modules/@anthropic-ai/sdk/node_modules/@types/node": { "node_modules/@ai-sdk/deepseek": {
"version": "18.19.130", "version": "1.0.31",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", "resolved": "https://registry.npmjs.org/@ai-sdk/deepseek/-/deepseek-1.0.31.tgz",
"integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", "integrity": "sha512-Il7WJp8bA3CmlreYSl1YzCucGTn2e5P81IANYIIEeLtWrbK0Y9CLoOCROj8xKYyUSMKlINyGZX2uP79cKewtSg==",
"license": "MIT", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"undici-types": "~5.26.4" "@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.18"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
} }
}, },
"node_modules/@anthropic-ai/sdk/node_modules/undici-types": { "node_modules/@ai-sdk/gateway": {
"version": "5.26.5", "version": "2.0.18",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-2.0.18.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "integrity": "sha512-sDQcW+6ck2m0pTIHW6BPHD7S125WD3qNkx/B8sEzJp/hurocmJ5Cni0ybExg6sQMGo+fr/GWOwpHF1cmCdg5rQ==",
"license": "MIT" "license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.18",
"@vercel/oidc": "3.0.5"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/@ai-sdk/provider": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.0.tgz",
"integrity": "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==",
"license": "Apache-2.0",
"dependencies": {
"json-schema": "^0.4.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@ai-sdk/provider-utils": {
"version": "3.0.18",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.18.tgz",
"integrity": "sha512-ypv1xXMsgGcNKUP+hglKqtdDuMg68nWHucPPAhIENrbFAI+xCHiqPVN8Zllxyv1TNZwGWUghPxJXU+Mqps0YRQ==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@standard-schema/spec": "^1.0.0",
"eventsource-parser": "^3.0.6"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
}
}, },
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.27.1", "version": "0.27.1",
@@ -830,47 +881,56 @@
} }
} }
}, },
"node_modules/@opentelemetry/api": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
"integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
"license": "Apache-2.0",
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/@standard-schema/spec": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
"integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
"license": "MIT"
},
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "22.19.2", "version": "22.19.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.2.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.2.tgz",
"integrity": "sha512-LPM2G3Syo1GLzXLGJAKdqoU35XvrWzGJ21/7sgZTUpbkBaOasTj8tjwn6w+hCkqaa1TfJ/w67rJSwYItlJ2mYw==", "integrity": "sha512-LPM2G3Syo1GLzXLGJAKdqoU35XvrWzGJ21/7sgZTUpbkBaOasTj8tjwn6w+hCkqaa1TfJ/w67rJSwYItlJ2mYw==",
"devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"undici-types": "~6.21.0" "undici-types": "~6.21.0"
} }
}, },
"node_modules/@types/node-fetch": { "node_modules/@vercel/oidc": {
"version": "2.6.13", "version": "3.0.5",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.0.5.tgz",
"integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", "integrity": "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw==",
"license": "MIT", "license": "Apache-2.0",
"dependencies": { "engines": {
"@types/node": "*", "node": ">= 20"
"form-data": "^4.0.4"
} }
}, },
"node_modules/abort-controller": { "node_modules/ai": {
"version": "3.0.0", "version": "5.0.108",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "resolved": "https://registry.npmjs.org/ai/-/ai-5.0.108.tgz",
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "integrity": "sha512-Jex3Lb7V41NNpuqJHKgrwoU6BCLHdI1Pg4qb4GJH4jRIDRXUBySJErHjyN4oTCwbiYCeb/8II9EnqSRPq9EifA==",
"license": "MIT", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"event-target-shim": "^5.0.0" "@ai-sdk/gateway": "2.0.18",
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.18",
"@opentelemetry/api": "1.9.0"
}, },
"engines": { "engines": {
"node": ">=6.5" "node": ">=18"
}
},
"node_modules/agentkeepalive": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
"integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==",
"license": "MIT",
"dependencies": {
"humanize-ms": "^1.2.1"
}, },
"engines": { "peerDependencies": {
"node": ">= 8.0.0" "zod": "^3.25.76 || ^4.1.8"
} }
}, },
"node_modules/ansi-regex": { "node_modules/ansi-regex": {
@@ -900,25 +960,6 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1" "url": "https://github.com/chalk/ansi-styles?sponsor=1"
} }
}, },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/chalk": { "node_modules/chalk": {
"version": "5.6.2", "version": "5.6.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
@@ -991,18 +1032,6 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/commander": { "node_modules/commander": {
"version": "12.1.0", "version": "12.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
@@ -1012,80 +1041,12 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "10.6.0", "version": "10.6.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
"integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.27.1", "version": "0.27.1",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.1.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.1.tgz",
@@ -1128,48 +1089,13 @@
"@esbuild/win32-x64": "0.27.1" "@esbuild/win32-x64": "0.27.1"
} }
}, },
"node_modules/event-target-shim": { "node_modules/eventsource-parser": {
"version": "5.0.1", "version": "3.0.6",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz",
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6" "node": ">=18.0.0"
}
},
"node_modules/form-data": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/form-data-encoder": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
"integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==",
"license": "MIT"
},
"node_modules/formdata-node": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
"integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
"license": "MIT",
"dependencies": {
"node-domexception": "1.0.0",
"web-streams-polyfill": "4.0.0-beta.3"
},
"engines": {
"node": ">= 12.20"
} }
}, },
"node_modules/fsevents": { "node_modules/fsevents": {
@@ -1187,15 +1113,6 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0" "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
} }
}, },
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-east-asian-width": { "node_modules/get-east-asian-width": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz",
@@ -1208,43 +1125,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/get-tsconfig": { "node_modules/get-tsconfig": {
"version": "4.13.0", "version": "4.13.0",
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz",
@@ -1258,66 +1138,6 @@
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
} }
}, },
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/humanize-ms": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
"integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.0.0"
}
},
"node_modules/iconv-lite": { "node_modules/iconv-lite": {
"version": "0.7.0", "version": "0.7.0",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz",
@@ -1393,6 +1213,12 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/json-schema": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
"license": "(AFL-2.1 OR BSD-3-Clause)"
},
"node_modules/log-symbols": { "node_modules/log-symbols": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz",
@@ -1421,36 +1247,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mimic-function": { "node_modules/mimic-function": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
@@ -1463,12 +1259,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/mute-stream": { "node_modules/mute-stream": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz",
@@ -1478,46 +1268,6 @@
"node": "^18.17.0 || >=20.5.0" "node": "^18.17.0 || >=20.5.0"
} }
}, },
"node_modules/node-domexception": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
"deprecated": "Use your platform's native DOMException instead",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "github",
"url": "https://paypal.me/jimmywarting"
}
],
"license": "MIT",
"engines": {
"node": ">=10.5.0"
}
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"license": "MIT",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/onetime": { "node_modules/onetime": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz",
@@ -1662,12 +1412,6 @@
"url": "https://github.com/chalk/strip-ansi?sponsor=1" "url": "https://github.com/chalk/strip-ansi?sponsor=1"
} }
}, },
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"license": "MIT"
},
"node_modules/tslib": { "node_modules/tslib": {
"version": "2.8.1", "version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -1712,33 +1456,9 @@
"version": "6.21.0", "version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/web-streams-polyfill": {
"version": "4.0.0-beta.3",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
"integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
"license": "MIT",
"engines": {
"node": ">= 14"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"license": "BSD-2-Clause"
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"license": "MIT",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/wrap-ansi": { "node_modules/wrap-ansi": {
"version": "6.2.0", "version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
@@ -1805,6 +1525,15 @@
"funding": { "funding": {
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
},
"node_modules/zod": {
"version": "4.1.13",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz",
"integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
} }
} }
} }
+14 -5
View File
@@ -13,19 +13,28 @@
"dev": "tsx src/index.ts", "dev": "tsx src/index.ts",
"lint": "eslint src/**/*.ts" "lint": "eslint src/**/*.ts"
}, },
"keywords": ["ai", "cli", "assistant", "claude", "terminal"], "keywords": [
"ai",
"cli",
"assistant",
"claude",
"terminal"
],
"author": "", "author": "",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@anthropic-ai/sdk": "^0.32.0", "@ai-sdk/anthropic": "^2.0.54",
"@ai-sdk/deepseek": "^1.0.31",
"ai": "^5.0.108",
"chalk": "^5.3.0", "chalk": "^5.3.0",
"commander": "^12.1.0", "commander": "^12.1.0",
"inquirer": "^12.0.0",
"ora": "^8.1.0", "ora": "^8.1.0",
"inquirer": "^12.0.0" "zod": "^4.1.13"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"typescript": "^5.6.0", "tsx": "^4.19.0",
"tsx": "^4.19.0" "typescript": "^5.6.0"
} }
} }
+91 -123
View File
@@ -1,73 +1,66 @@
import Anthropic from '@anthropic-ai/sdk'; import { createAnthropic } from '@ai-sdk/anthropic';
import type { Tool, ToolResult, Message, AgentConfig } from '../types/index.js'; import { createDeepSeek } from '@ai-sdk/deepseek';
import { generateText, streamText, type ModelMessage, type Tool as AITool, type LanguageModel } from 'ai';
import type { Tool, ToolResult, Message, AgentConfig, ProviderType } from '../types/index.js';
import { buildZodSchema } from '../types/index.js';
// Provider 工厂函数类型
type ProviderFactory = (apiKey: string) => (model: string) => LanguageModel;
// Provider 注册表
const providers: Record<ProviderType, ProviderFactory> = {
anthropic: (apiKey) => {
const client = createAnthropic({ apiKey });
return (model) => client(model);
},
deepseek: (apiKey) => {
const client = createDeepSeek({ apiKey });
return (model) => client(model);
},
};
export class Agent { export class Agent {
private client: Anthropic; private getModel: (model: string) => LanguageModel;
private config: AgentConfig; private config: AgentConfig;
private tools: Map<string, Tool> = new Map(); private tools: Map<string, Tool> = new Map();
private conversationHistory: Message[] = []; private conversationHistory: ModelMessage[] = [];
constructor(config: AgentConfig) { constructor(config: AgentConfig) {
this.config = config; this.config = config;
this.client = new Anthropic({
apiKey: config.apiKey, const providerFactory = providers[config.provider];
}); if (!providerFactory) {
throw new Error(`不支持的 provider: ${config.provider}`);
}
this.getModel = providerFactory(config.apiKey);
} }
// 注册工具 // 注册工具
registerTool(tool: Tool): void { registerTool(customTool: Tool): void {
this.tools.set(tool.name, tool); this.tools.set(customTool.name, customTool);
} }
// 获取所有工具定义(用于 Claude API) // 将自定义工具转换为 Vercel AI SDK 的工具格式
private getToolDefinitions(): Anthropic.Tool[] { private getVercelTools(): Record<string, AITool> {
return Array.from(this.tools.values()).map((tool) => ({ const vercelTools: Record<string, AITool> = {};
name: tool.name,
description: tool.description,
input_schema: {
type: 'object' as const,
properties: Object.fromEntries(
Object.entries(tool.parameters).map(([key, param]) => [
key,
{
type: param.type,
description: param.description,
},
])
),
required: Object.entries(tool.parameters)
.filter(([, param]) => param.required)
.map(([key]) => key),
},
}));
}
// 执行工具 for (const [name, customTool] of this.tools) {
private async executeTool( const schema = buildZodSchema(customTool.parameters);
toolName: string,
input: Record<string, unknown> vercelTools[name] = {
): Promise<ToolResult> { description: customTool.description,
const tool = this.tools.get(toolName); inputSchema: schema,
if (!tool) { execute: async (params) => {
return { const result = await customTool.execute(params as Record<string, unknown>);
success: false, return result;
output: '', },
error: `Tool "${toolName}" not found`, } as AITool;
};
} }
try { return vercelTools;
return await tool.execute(input);
} catch (error) {
return {
success: false,
output: '',
error: error instanceof Error ? error.message : String(error),
};
}
} }
// 发送消息并处理响应 // 发送消息并处理响应(流式)
async chat( async chat(
userMessage: string, userMessage: string,
onStream?: (text: string) => void onStream?: (text: string) => void
@@ -78,84 +71,52 @@ export class Agent {
content: userMessage, content: userMessage,
}); });
const messages: Anthropic.MessageParam[] = this.conversationHistory.map( const vercelTools = this.getVercelTools();
(msg) => ({
role: msg.role,
content: msg.content,
})
);
let fullResponse = ''; let fullResponse = '';
// 循环处理,直到没有工具调用 if (onStream) {
while (true) { // 流式模式
const response = await this.client.messages.create({ const result = streamText({
model: this.config.model, model: this.getModel(this.config.model),
max_tokens: this.config.maxTokens,
system: this.config.systemPrompt, system: this.config.systemPrompt,
tools: this.getToolDefinitions(), messages: this.conversationHistory,
messages, tools: vercelTools,
}); maxOutputTokens: this.config.maxTokens,
onChunk: ({ chunk }) => {
// 处理响应内容 if (chunk.type === 'tool-call') {
const textBlocks: string[] = []; onStream(`\n[调用工具: ${chunk.toolName}]\n`);
const toolUseBlocks: Anthropic.ToolUseBlock[] = []; } else if (chunk.type === 'tool-result') {
const output = (chunk as { output?: ToolResult }).output;
for (const block of response.content) { if (output && typeof output === 'object') {
if (block.type === 'text') { if (output.success) {
textBlocks.push(block.text); onStream(`[结果: ${output.output}]\n`);
if (onStream) { } else {
onStream(block.text); onStream(`[错误: ${output.error}]\n`);
}
}
} }
} else if (block.type === 'tool_use') { },
toolUseBlocks.push(block);
}
}
fullResponse += textBlocks.join('');
// 如果没有工具调用,结束循环
if (toolUseBlocks.length === 0) {
break;
}
// 添加 assistant 消息
messages.push({
role: 'assistant',
content: response.content,
}); });
// 处理工具调用 // 流式输出文本
const toolResults: Anthropic.ToolResultBlockParam[] = []; for await (const chunk of result.textStream) {
fullResponse += chunk;
for (const toolUse of toolUseBlocks) { onStream(chunk);
if (onStream) {
onStream(`\n[调用工具: ${toolUse.name}]\n`);
}
const result = await this.executeTool(
toolUse.name,
toolUse.input as Record<string, unknown>
);
if (onStream) {
onStream(
result.success ? `[结果: ${result.output}]\n` : `[错误: ${result.error}]\n`
);
}
toolResults.push({
type: 'tool_result',
tool_use_id: toolUse.id,
content: result.success ? result.output : `Error: ${result.error}`,
});
} }
// 添加工具结果 // 等待完成
messages.push({ await result.response;
role: 'user', } else {
content: toolResults, // 非流式模式
const result = await generateText({
model: this.getModel(this.config.model),
system: this.config.systemPrompt,
messages: this.conversationHistory,
tools: vercelTools,
maxOutputTokens: this.config.maxTokens,
}); });
fullResponse = result.text;
} }
// 保存助手响应到历史 // 保存助手响应到历史
@@ -174,6 +135,13 @@ export class Agent {
// 获取对话历史 // 获取对话历史
getHistory(): Message[] { getHistory(): Message[] {
return [...this.conversationHistory]; return this.conversationHistory
.filter((msg): msg is ModelMessage & { role: 'user' | 'assistant' } =>
msg.role === 'user' || msg.role === 'assistant'
)
.map((msg) => ({
role: msg.role,
content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content),
}));
} }
} }
+53 -8
View File
@@ -1,37 +1,45 @@
import { z } from 'zod';
// 消息类型 // 消息类型
export interface Message { export interface Message {
role: 'user' | 'assistant'; role: 'user' | 'assistant';
content: string; content: string;
} }
// 工具定义 // 工具参数定义
export interface Tool {
name: string;
description: string;
parameters: Record<string, ToolParameter>;
execute: (params: Record<string, unknown>) => Promise<ToolResult>;
}
export interface ToolParameter { export interface ToolParameter {
type: 'string' | 'number' | 'boolean' | 'array' | 'object'; type: 'string' | 'number' | 'boolean' | 'array' | 'object';
description: string; description: string;
required?: boolean; required?: boolean;
} }
// 工具执行结果
export interface ToolResult { export interface ToolResult {
success: boolean; success: boolean;
output: string; output: string;
error?: string; error?: string;
} }
// 工具定义(兼容 Vercel AI SDK 的 tool 格式)
export interface Tool {
name: string;
description: string;
parameters: Record<string, ToolParameter>;
execute: (params: Record<string, unknown>) => Promise<ToolResult>;
}
// 工具调用请求 // 工具调用请求
export interface ToolCall { export interface ToolCall {
name: string; name: string;
input: Record<string, unknown>; input: Record<string, unknown>;
} }
// 支持的 Provider 类型
export type ProviderType = 'anthropic' | 'deepseek';
// Agent 配置 // Agent 配置
export interface AgentConfig { export interface AgentConfig {
provider: ProviderType;
apiKey: string; apiKey: string;
model: string; model: string;
maxTokens: number; maxTokens: number;
@@ -43,3 +51,40 @@ export interface ConversationContext {
messages: Message[]; messages: Message[];
workingDirectory: string; workingDirectory: string;
} }
// 将自定义 Tool 转换为 Vercel AI SDK 的 zod schema
export function buildZodSchema(parameters: Record<string, ToolParameter>): z.ZodObject<Record<string, z.ZodTypeAny>> {
const schemaObj: Record<string, z.ZodTypeAny> = {};
for (const [key, param] of Object.entries(parameters)) {
let fieldSchema: z.ZodTypeAny;
switch (param.type) {
case 'string':
fieldSchema = z.string().describe(param.description);
break;
case 'number':
fieldSchema = z.number().describe(param.description);
break;
case 'boolean':
fieldSchema = z.boolean().describe(param.description);
break;
case 'array':
fieldSchema = z.array(z.unknown()).describe(param.description);
break;
case 'object':
fieldSchema = z.record(z.string(), z.unknown()).describe(param.description);
break;
default:
fieldSchema = z.unknown().describe(param.description);
}
if (!param.required) {
fieldSchema = fieldSchema.optional();
}
schemaObj[key] = fieldSchema;
}
return z.object(schemaObj);
}
+73 -21
View File
@@ -1,17 +1,25 @@
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import * as os from 'os'; import * as os from 'os';
import type { AgentConfig } from '../types/index.js'; import type { AgentConfig, ProviderType } from '../types/index.js';
const CONFIG_DIR = path.join(os.homedir(), '.ai-terminal-assistant'); const CONFIG_DIR = path.join(os.homedir(), '.ai-terminal-assistant');
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json'); const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
interface StoredConfig { interface StoredConfig {
provider?: ProviderType;
apiKey?: string; apiKey?: string;
deepseekApiKey?: string;
model?: string; model?: string;
maxTokens?: number; maxTokens?: number;
} }
// 默认模型配置
const DEFAULT_MODELS: Record<ProviderType, string> = {
anthropic: 'claude-sonnet-4-20250514',
deepseek: 'deepseek-chat',
};
// 默认系统提示词 // 默认系统提示词
const DEFAULT_SYSTEM_PROMPT = `你是一个运行在终端中的 AI 编程助手。你可以帮助用户: const DEFAULT_SYSTEM_PROMPT = `你是一个运行在终端中的 AI 编程助手。你可以帮助用户:
- 读取和写入文件 - 读取和写入文件
@@ -29,12 +37,14 @@ const DEFAULT_SYSTEM_PROMPT = `你是一个运行在终端中的 AI 编程助手
// 加载配置 // 加载配置
export function loadConfig(): AgentConfig { export function loadConfig(): AgentConfig {
// 优先从环境变量获取 // 从环境变量获取
const apiKey = process.env.ANTHROPIC_API_KEY; const provider = (process.env.AI_PROVIDER as ProviderType) || 'anthropic';
const model = process.env.AI_MODEL || 'claude-sonnet-4-20250514'; const anthropicApiKey = process.env.ANTHROPIC_API_KEY;
const deepseekApiKey = process.env.DEEPSEEK_API_KEY;
const model = process.env.AI_MODEL;
const maxTokens = parseInt(process.env.AI_MAX_TOKENS || '4096', 10); const maxTokens = parseInt(process.env.AI_MAX_TOKENS || '4096', 10);
// 如果环境变量没有,尝试从配置文件读取 // 从配置文件读取
let storedConfig: StoredConfig = {}; let storedConfig: StoredConfig = {};
if (fs.existsSync(CONFIG_FILE)) { if (fs.existsSync(CONFIG_FILE)) {
try { try {
@@ -45,18 +55,32 @@ export function loadConfig(): AgentConfig {
} }
} }
const finalApiKey = apiKey || storedConfig.apiKey; // 确定最终的 provider
const finalProvider = storedConfig.provider || provider;
// 根据 provider 获取对应的 API Key
let finalApiKey: string | undefined;
if (finalProvider === 'anthropic') {
finalApiKey = anthropicApiKey || storedConfig.apiKey;
} else if (finalProvider === 'deepseek') {
finalApiKey = deepseekApiKey || storedConfig.deepseekApiKey;
}
if (!finalApiKey) { if (!finalApiKey) {
console.error('❌ 错误: 未设置 ANTHROPIC_API_KEY'); const envVar = finalProvider === 'anthropic' ? 'ANTHROPIC_API_KEY' : 'DEEPSEEK_API_KEY';
console.error('请设置环境变量: export ANTHROPIC_API_KEY=your-api-key'); console.error(`❌ 错误: 未设置 ${envVar}`);
console.error('或运行: ai-assist --init 进行初始化配置'); console.error(`请设置环境变量: export ${envVar}=your-api-key`);
console.error('或运行: ai-assist init 进行初始化配置');
process.exit(1); process.exit(1);
} }
// 确定模型
const finalModel = model || storedConfig.model || DEFAULT_MODELS[finalProvider];
return { return {
provider: finalProvider,
apiKey: finalApiKey, apiKey: finalApiKey,
model: storedConfig.model || model, model: finalModel,
maxTokens: storedConfig.maxTokens || maxTokens, maxTokens: storedConfig.maxTokens || maxTokens,
systemPrompt: DEFAULT_SYSTEM_PROMPT, systemPrompt: DEFAULT_SYSTEM_PROMPT,
}; };
@@ -91,24 +115,52 @@ export async function initConfig(): Promise<void> {
console.log('\n🔧 初始化 AI Terminal Assistant 配置\n'); console.log('\n🔧 初始化 AI Terminal Assistant 配置\n');
// 选择 provider
const { provider } = await inquirer.prompt([
{
type: 'list',
name: 'provider',
message: '选择 AI 服务商:',
choices: [
{ name: 'Anthropic (Claude)', value: 'anthropic' },
{ name: 'DeepSeek', value: 'deepseek' },
],
default: 'anthropic',
},
]);
// 根据 provider 显示不同的模型选项
const modelChoices =
provider === 'anthropic'
? [
{ name: 'Claude Sonnet 4 (推荐,平衡性能和成本)', value: 'claude-sonnet-4-20250514' },
{ name: 'Claude Opus 4 (最强,成本较高)', value: 'claude-opus-4-20250514' },
{ name: 'Claude 3.5 Haiku (快速,成本低)', value: 'claude-3-5-haiku-20241022' },
]
: [
{ name: 'DeepSeek Chat (推荐)', value: 'deepseek-chat' },
{ name: 'DeepSeek Reasoner (推理增强)', value: 'deepseek-reasoner' },
];
const apiKeyField = provider === 'anthropic' ? 'apiKey' : 'deepseekApiKey';
const apiKeyMessage =
provider === 'anthropic'
? '请输入你的 Anthropic API Key:'
: '请输入你的 DeepSeek API Key:';
const answers = await inquirer.prompt([ const answers = await inquirer.prompt([
{ {
type: 'password', type: 'password',
name: 'apiKey', name: apiKeyField,
message: '请输入你的 Anthropic API Key:', message: apiKeyMessage,
validate: (input: string) => validate: (input: string) => input.length > 0 || 'API Key 不能为空',
input.length > 0 || 'API Key 不能为空',
}, },
{ {
type: 'list', type: 'list',
name: 'model', name: 'model',
message: '选择默认模型:', message: '选择默认模型:',
choices: [ choices: modelChoices,
{ name: 'Claude Sonnet 4 (推荐,平衡性能和成本)', value: 'claude-sonnet-4-20250514' }, default: DEFAULT_MODELS[provider as ProviderType],
{ name: 'Claude Opus 4 (最强,成本较高)', value: 'claude-opus-4-20250514' },
{ name: 'Claude 3.5 Haiku (快速,成本低)', value: 'claude-3-5-haiku-20241022' },
],
default: 'claude-sonnet-4-20250514',
}, },
{ {
type: 'number', type: 'number',
@@ -118,7 +170,7 @@ export async function initConfig(): Promise<void> {
}, },
]); ]);
saveConfig(answers); saveConfig({ provider, ...answers });
console.log('\n✅ 配置已保存到', CONFIG_FILE); console.log('\n✅ 配置已保存到', CONFIG_FILE);
console.log('现在可以运行 ai-assist 开始使用了!\n'); console.log('现在可以运行 ai-assist 开始使用了!\n');
} }