save work
This commit is contained in:
parent
8cf7147b11
commit
c52c4339e0
@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
preset: "ts-jest",
|
preset: "ts-jest",
|
||||||
testEnvironment: "node",
|
testEnvironment: "node",
|
||||||
testMatch: ["<rootDir>/src/__test__/**/*.test.ts"],
|
testMatch: ["<rootDir>/test/**/*.test.ts"],
|
||||||
};
|
};
|
393
package-lock.json
generated
393
package-lock.json
generated
@ -8,7 +8,6 @@
|
|||||||
"name": "devchat",
|
"name": "devchat",
|
||||||
"version": "0.1.65",
|
"version": "0.1.65",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
|
||||||
"@tiptap/extension-link": "^2.0.3",
|
"@tiptap/extension-link": "^2.0.3",
|
||||||
"@tiptap/pm": "^2.0.0",
|
"@tiptap/pm": "^2.0.0",
|
||||||
"@tiptap/starter-kit": "^2.0.3",
|
"@tiptap/starter-kit": "^2.0.3",
|
||||||
@ -2230,11 +2229,6 @@
|
|||||||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@iarna/toml": {
|
|
||||||
"version": "2.2.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
|
|
||||||
"integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="
|
|
||||||
},
|
|
||||||
"node_modules/@istanbuljs/load-nyc-config": {
|
"node_modules/@istanbuljs/load-nyc-config": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
||||||
@ -4628,13 +4622,13 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/body-parser": {
|
"node_modules/body-parser": {
|
||||||
"version": "1.20.2",
|
"version": "1.20.1",
|
||||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
|
||||||
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
|
"integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bytes": "3.1.2",
|
"bytes": "3.1.2",
|
||||||
"content-type": "~1.0.5",
|
"content-type": "~1.0.4",
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
"depd": "2.0.0",
|
"depd": "2.0.0",
|
||||||
"destroy": "1.2.0",
|
"destroy": "1.2.0",
|
||||||
@ -4642,7 +4636,7 @@
|
|||||||
"iconv-lite": "0.4.24",
|
"iconv-lite": "0.4.24",
|
||||||
"on-finished": "2.4.1",
|
"on-finished": "2.4.1",
|
||||||
"qs": "6.11.0",
|
"qs": "6.11.0",
|
||||||
"raw-body": "2.5.2",
|
"raw-body": "2.5.1",
|
||||||
"type-is": "~1.6.18",
|
"type-is": "~1.6.18",
|
||||||
"unpipe": "1.0.0"
|
"unpipe": "1.0.0"
|
||||||
},
|
},
|
||||||
@ -4805,19 +4799,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/call-bind": {
|
"node_modules/call-bind": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
||||||
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"es-define-property": "^1.0.0",
|
"function-bind": "^1.1.1",
|
||||||
"es-errors": "^1.3.0",
|
"get-intrinsic": "^1.0.2"
|
||||||
"function-bind": "^1.1.2",
|
|
||||||
"get-intrinsic": "^1.2.4",
|
|
||||||
"set-function-length": "^1.2.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4"
|
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
@ -5242,9 +5230,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/cookie": {
|
"node_modules/cookie": {
|
||||||
"version": "0.6.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
||||||
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
@ -5526,23 +5514,6 @@
|
|||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/define-data-property": {
|
|
||||||
"version": "1.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
|
||||||
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"es-define-property": "^1.0.0",
|
|
||||||
"es-errors": "^1.3.0",
|
|
||||||
"gopd": "^1.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/define-lazy-prop": {
|
"node_modules/define-lazy-prop": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
|
||||||
@ -5951,27 +5922,6 @@
|
|||||||
"is-arrayish": "^0.2.1"
|
"is-arrayish": "^0.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/es-define-property": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"get-intrinsic": "^1.2.4"
|
|
||||||
},
|
|
||||||
"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==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/es-module-lexer": {
|
"node_modules/es-module-lexer": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz",
|
||||||
@ -6267,17 +6217,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/express": {
|
"node_modules/express": {
|
||||||
"version": "4.19.2",
|
"version": "4.18.2",
|
||||||
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
|
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
|
||||||
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
|
"integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "~1.3.8",
|
"accepts": "~1.3.8",
|
||||||
"array-flatten": "1.1.1",
|
"array-flatten": "1.1.1",
|
||||||
"body-parser": "1.20.2",
|
"body-parser": "1.20.1",
|
||||||
"content-disposition": "0.5.4",
|
"content-disposition": "0.5.4",
|
||||||
"content-type": "~1.0.4",
|
"content-type": "~1.0.4",
|
||||||
"cookie": "0.6.0",
|
"cookie": "0.5.0",
|
||||||
"cookie-signature": "1.0.6",
|
"cookie-signature": "1.0.6",
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
"depd": "2.0.0",
|
"depd": "2.0.0",
|
||||||
@ -6611,9 +6561,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.15.6",
|
"version": "1.15.2",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@ -6744,13 +6694,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/function-bind": {
|
"node_modules/function-bind": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"node_modules/gensync": {
|
"node_modules/gensync": {
|
||||||
"version": "1.0.0-beta.2",
|
"version": "1.0.0-beta.2",
|
||||||
@ -6779,19 +6726,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/get-intrinsic": {
|
"node_modules/get-intrinsic": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
|
||||||
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
"integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"es-errors": "^1.3.0",
|
"function-bind": "^1.1.1",
|
||||||
"function-bind": "^1.1.2",
|
"has": "^1.0.3",
|
||||||
"has-proto": "^1.0.1",
|
"has-symbols": "^1.0.3"
|
||||||
"has-symbols": "^1.0.3",
|
|
||||||
"hasown": "^2.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4"
|
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
@ -6910,18 +6852,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/gopd": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"get-intrinsic": "^1.1.3"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/graceful-fs": {
|
"node_modules/graceful-fs": {
|
||||||
"version": "4.2.11",
|
"version": "4.2.11",
|
||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||||
@ -6959,30 +6889,6 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/has-property-descriptors": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"es-define-property": "^1.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/has-proto": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/has-symbols": {
|
"node_modules/has-symbols": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||||
@ -6995,18 +6901,6 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"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==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"function-bind": "^1.1.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/hast-util-from-parse5": {
|
"node_modules/hast-util-from-parse5": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz",
|
||||||
@ -9411,9 +9305,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/object-inspect": {
|
"node_modules/object-inspect": {
|
||||||
"version": "1.13.1",
|
"version": "1.12.3",
|
||||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
|
||||||
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
|
"integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
@ -10212,9 +10106,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/raw-body": {
|
"node_modules/raw-body": {
|
||||||
"version": "2.5.2",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
|
||||||
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
|
"integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bytes": "3.1.2",
|
"bytes": "3.1.2",
|
||||||
@ -10785,23 +10679,6 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/set-function-length": {
|
|
||||||
"version": "1.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
|
||||||
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"define-data-property": "^1.1.4",
|
|
||||||
"es-errors": "^1.3.0",
|
|
||||||
"function-bind": "^1.1.2",
|
|
||||||
"get-intrinsic": "^1.2.4",
|
|
||||||
"gopd": "^1.0.1",
|
|
||||||
"has-property-descriptors": "^1.0.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/setimmediate": {
|
"node_modules/setimmediate": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||||
@ -10862,18 +10739,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/side-channel": {
|
"node_modules/side-channel": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
||||||
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
|
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"call-bind": "^1.0.7",
|
"call-bind": "^1.0.0",
|
||||||
"es-errors": "^1.3.0",
|
"get-intrinsic": "^1.0.2",
|
||||||
"get-intrinsic": "^1.2.4",
|
"object-inspect": "^1.9.0"
|
||||||
"object-inspect": "^1.13.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4"
|
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
@ -12063,9 +11936,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/webpack-dev-middleware": {
|
"node_modules/webpack-dev-middleware": {
|
||||||
"version": "5.3.4",
|
"version": "5.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz",
|
||||||
"integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==",
|
"integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"colorette": "^2.0.10",
|
"colorette": "^2.0.10",
|
||||||
@ -13988,11 +13861,6 @@
|
|||||||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@iarna/toml": {
|
|
||||||
"version": "2.2.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
|
|
||||||
"integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="
|
|
||||||
},
|
|
||||||
"@istanbuljs/load-nyc-config": {
|
"@istanbuljs/load-nyc-config": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
||||||
@ -15854,13 +15722,13 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"body-parser": {
|
"body-parser": {
|
||||||
"version": "1.20.2",
|
"version": "1.20.1",
|
||||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
|
||||||
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
|
"integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"bytes": "3.1.2",
|
"bytes": "3.1.2",
|
||||||
"content-type": "~1.0.5",
|
"content-type": "~1.0.4",
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
"depd": "2.0.0",
|
"depd": "2.0.0",
|
||||||
"destroy": "1.2.0",
|
"destroy": "1.2.0",
|
||||||
@ -15868,7 +15736,7 @@
|
|||||||
"iconv-lite": "0.4.24",
|
"iconv-lite": "0.4.24",
|
||||||
"on-finished": "2.4.1",
|
"on-finished": "2.4.1",
|
||||||
"qs": "6.11.0",
|
"qs": "6.11.0",
|
||||||
"raw-body": "2.5.2",
|
"raw-body": "2.5.1",
|
||||||
"type-is": "~1.6.18",
|
"type-is": "~1.6.18",
|
||||||
"unpipe": "1.0.0"
|
"unpipe": "1.0.0"
|
||||||
},
|
},
|
||||||
@ -15991,16 +15859,13 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"call-bind": {
|
"call-bind": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
||||||
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"es-define-property": "^1.0.0",
|
"function-bind": "^1.1.1",
|
||||||
"es-errors": "^1.3.0",
|
"get-intrinsic": "^1.0.2"
|
||||||
"function-bind": "^1.1.2",
|
|
||||||
"get-intrinsic": "^1.2.4",
|
|
||||||
"set-function-length": "^1.2.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"callsites": {
|
"callsites": {
|
||||||
@ -16306,9 +16171,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"cookie": {
|
"cookie": {
|
||||||
"version": "0.6.0",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
||||||
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"cookie-signature": {
|
"cookie-signature": {
|
||||||
@ -16511,17 +16376,6 @@
|
|||||||
"execa": "^5.0.0"
|
"execa": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"define-data-property": {
|
|
||||||
"version": "1.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
|
||||||
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"es-define-property": "^1.0.0",
|
|
||||||
"es-errors": "^1.3.0",
|
|
||||||
"gopd": "^1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"define-lazy-prop": {
|
"define-lazy-prop": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
|
||||||
@ -16832,21 +16686,6 @@
|
|||||||
"is-arrayish": "^0.2.1"
|
"is-arrayish": "^0.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es-define-property": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"get-intrinsic": "^1.2.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"es-errors": {
|
|
||||||
"version": "1.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
|
||||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"es-module-lexer": {
|
"es-module-lexer": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz",
|
||||||
@ -17063,17 +16902,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"express": {
|
"express": {
|
||||||
"version": "4.19.2",
|
"version": "4.18.2",
|
||||||
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
|
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
|
||||||
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
|
"integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"accepts": "~1.3.8",
|
"accepts": "~1.3.8",
|
||||||
"array-flatten": "1.1.1",
|
"array-flatten": "1.1.1",
|
||||||
"body-parser": "1.20.2",
|
"body-parser": "1.20.1",
|
||||||
"content-disposition": "0.5.4",
|
"content-disposition": "0.5.4",
|
||||||
"content-type": "~1.0.4",
|
"content-type": "~1.0.4",
|
||||||
"cookie": "0.6.0",
|
"cookie": "0.5.0",
|
||||||
"cookie-signature": "1.0.6",
|
"cookie-signature": "1.0.6",
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
"depd": "2.0.0",
|
"depd": "2.0.0",
|
||||||
@ -17331,9 +17170,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"follow-redirects": {
|
"follow-redirects": {
|
||||||
"version": "1.15.6",
|
"version": "1.15.2",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
|
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
|
||||||
},
|
},
|
||||||
"form-data": {
|
"form-data": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@ -17421,9 +17260,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"function-bind": {
|
"function-bind": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"gensync": {
|
"gensync": {
|
||||||
@ -17444,16 +17283,14 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"get-intrinsic": {
|
"get-intrinsic": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
|
||||||
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
"integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"es-errors": "^1.3.0",
|
"function-bind": "^1.1.1",
|
||||||
"function-bind": "^1.1.2",
|
"has": "^1.0.3",
|
||||||
"has-proto": "^1.0.1",
|
"has-symbols": "^1.0.3"
|
||||||
"has-symbols": "^1.0.3",
|
|
||||||
"hasown": "^2.0.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"get-package-type": {
|
"get-package-type": {
|
||||||
@ -17538,15 +17375,6 @@
|
|||||||
"slash": "^3.0.0"
|
"slash": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"gopd": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"get-intrinsic": "^1.1.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"graceful-fs": {
|
"graceful-fs": {
|
||||||
"version": "4.2.11",
|
"version": "4.2.11",
|
||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||||
@ -17578,36 +17406,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
|
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
|
||||||
},
|
},
|
||||||
"has-property-descriptors": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"es-define-property": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"has-proto": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"has-symbols": {
|
"has-symbols": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"hasown": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"function-bind": "^1.1.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hast-util-from-parse5": {
|
"hast-util-from-parse5": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz",
|
||||||
@ -19428,9 +19232,9 @@
|
|||||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
|
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
|
||||||
},
|
},
|
||||||
"object-inspect": {
|
"object-inspect": {
|
||||||
"version": "1.13.1",
|
"version": "1.12.3",
|
||||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
|
||||||
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
|
"integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"object.omit": {
|
"object.omit": {
|
||||||
@ -20063,9 +19867,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"raw-body": {
|
"raw-body": {
|
||||||
"version": "2.5.2",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
|
||||||
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
|
"integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"bytes": "3.1.2",
|
"bytes": "3.1.2",
|
||||||
@ -20520,20 +20324,6 @@
|
|||||||
"send": "0.18.0"
|
"send": "0.18.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"set-function-length": {
|
|
||||||
"version": "1.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
|
||||||
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"define-data-property": "^1.1.4",
|
|
||||||
"es-errors": "^1.3.0",
|
|
||||||
"function-bind": "^1.1.2",
|
|
||||||
"get-intrinsic": "^1.2.4",
|
|
||||||
"gopd": "^1.0.1",
|
|
||||||
"has-property-descriptors": "^1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"setimmediate": {
|
"setimmediate": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||||
@ -20582,15 +20372,14 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"side-channel": {
|
"side-channel": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
||||||
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
|
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"call-bind": "^1.0.7",
|
"call-bind": "^1.0.0",
|
||||||
"es-errors": "^1.3.0",
|
"get-intrinsic": "^1.0.2",
|
||||||
"get-intrinsic": "^1.2.4",
|
"object-inspect": "^1.9.0"
|
||||||
"object-inspect": "^1.13.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"signal-exit": {
|
"signal-exit": {
|
||||||
@ -21434,9 +21223,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"webpack-dev-middleware": {
|
"webpack-dev-middleware": {
|
||||||
"version": "5.3.4",
|
"version": "5.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz",
|
||||||
"integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==",
|
"integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"colorette": "^2.0.10",
|
"colorette": "^2.0.10",
|
||||||
|
@ -24,6 +24,13 @@ import {
|
|||||||
import { installRequirements } from "../util/python_installer/package_install";
|
import { installRequirements } from "../util/python_installer/package_install";
|
||||||
import { chatWithDevChat } from "../handler/chatHandler";
|
import { chatWithDevChat } from "../handler/chatHandler";
|
||||||
import { focusDevChatInput } from "../handler/focusHandler";
|
import { focusDevChatInput } from "../handler/focusHandler";
|
||||||
|
import { sendCommandListByDevChatRun } from '../handler/workflowCommandHandler';
|
||||||
|
import DevChat from "../toolwrapper/devchat";
|
||||||
|
import { createEnvByConda, createEnvByMamba } from '../util/python_installer/app_install';
|
||||||
|
import { installRequirements } from '../util/python_installer/package_install';
|
||||||
|
import { chatWithDevChat } from '../handler/chatHandler';
|
||||||
|
import { focusDevChatInput } from '../handler/focusHandler';
|
||||||
|
import { DevChatConfig } from '../util/config';
|
||||||
|
|
||||||
const readdir = util.promisify(fs.readdir);
|
const readdir = util.promisify(fs.readdir);
|
||||||
const stat = util.promisify(fs.stat);
|
const stat = util.promisify(fs.stat);
|
||||||
@ -46,7 +53,7 @@ async function copyDirectory(src: string, dest: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerOpenChatPanelCommand(context: vscode.ExtensionContext) {
|
export function registerOpenChatPanelCommand(context: vscode.ExtensionContext) {
|
||||||
let disposable = vscode.commands.registerCommand(
|
let disposable = vscode.commands.registerCommand(
|
||||||
"devchat.openChatPanel",
|
"devchat.openChatPanel",
|
||||||
async () => {
|
async () => {
|
||||||
@ -64,7 +71,7 @@ async function ensureChatPanel(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerAddContextCommand(context: vscode.ExtensionContext) {
|
export function registerAddContextCommand(context: vscode.ExtensionContext) {
|
||||||
const callback = async (uri: { fsPath: any }) => {
|
const callback = async (uri: { fsPath: any }) => {
|
||||||
if (!(await ensureChatPanel(context))) {
|
if (!(await ensureChatPanel(context))) {
|
||||||
return;
|
return;
|
||||||
@ -83,7 +90,7 @@ function registerAddContextCommand(context: vscode.ExtensionContext) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerAskForCodeCommand(context: vscode.ExtensionContext) {
|
export function registerAskForCodeCommand(context: vscode.ExtensionContext) {
|
||||||
const callback = async () => {
|
const callback = async () => {
|
||||||
const editor = vscode.window.activeTextEditor;
|
const editor = vscode.window.activeTextEditor;
|
||||||
if (editor) {
|
if (editor) {
|
||||||
@ -108,7 +115,7 @@ function registerAskForCodeCommand(context: vscode.ExtensionContext) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerAskForFileCommand(context: vscode.ExtensionContext) {
|
export function registerAskForFileCommand(context: vscode.ExtensionContext) {
|
||||||
const callback = async () => {
|
const callback = async () => {
|
||||||
const editor = vscode.window.activeTextEditor;
|
const editor = vscode.window.activeTextEditor;
|
||||||
if (editor) {
|
if (editor) {
|
||||||
@ -130,78 +137,6 @@ function registerAskForFileCommand(context: vscode.ExtensionContext) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function regAccessKeyCommand(
|
|
||||||
context: vscode.ExtensionContext,
|
|
||||||
provider: string
|
|
||||||
) {
|
|
||||||
context.subscriptions.push(
|
|
||||||
vscode.commands.registerCommand(
|
|
||||||
`DevChat.AccessKey.${provider}`,
|
|
||||||
async () => {
|
|
||||||
vscode.commands.executeCommand("devchat-view.focus");
|
|
||||||
const passwordInput: string | undefined =
|
|
||||||
(await vscode.window.showInputBox({
|
|
||||||
password: true,
|
|
||||||
title: `Set ${provider} Key`,
|
|
||||||
placeHolder: `Input your ${provider} key. (Leave blank to clear the stored key.)`,
|
|
||||||
})) ?? undefined;
|
|
||||||
if (passwordInput === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (provider === "DevChat" && passwordInput.trim() !== "") {
|
|
||||||
if (!passwordInput.trim().startsWith("DC.")) {
|
|
||||||
UiUtilWrapper.showErrorMessage(
|
|
||||||
"Your key is invalid! DevChat Access Key is: DC.xxxxx"
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (passwordInput.trim() !== "" && !isValidApiKey(passwordInput)) {
|
|
||||||
UiUtilWrapper.showErrorMessage("Your key is invalid!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await ApiKeyManager.writeApiKeySecret(passwordInput, provider);
|
|
||||||
|
|
||||||
// update default model
|
|
||||||
const defaultModel = await ApiKeyManager.llmModel();
|
|
||||||
if (!defaultModel) {
|
|
||||||
const modelList = await ApiKeyManager.getValidModels();
|
|
||||||
if (modelList && modelList.length > 0) {
|
|
||||||
// update default llm model
|
|
||||||
await UiUtilWrapper.updateConfiguration(
|
|
||||||
"devchat",
|
|
||||||
"defaultModel",
|
|
||||||
modelList[0]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// reload webview
|
|
||||||
ExtensionContextHolder.provider?.reloadWebview();
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function registerAccessKeySettingCommand(
|
|
||||||
context: vscode.ExtensionContext
|
|
||||||
) {
|
|
||||||
regAccessKeyCommand(context, "OpenAI");
|
|
||||||
regAccessKeyCommand(context, "Cohere");
|
|
||||||
regAccessKeyCommand(context, "Anthropic");
|
|
||||||
regAccessKeyCommand(context, "Replicate");
|
|
||||||
regAccessKeyCommand(context, "HuggingFace");
|
|
||||||
regAccessKeyCommand(context, "TogetherAI");
|
|
||||||
regAccessKeyCommand(context, "OpenRouter");
|
|
||||||
regAccessKeyCommand(context, "VertexAI");
|
|
||||||
regAccessKeyCommand(context, "AI21");
|
|
||||||
regAccessKeyCommand(context, "BaseTen");
|
|
||||||
regAccessKeyCommand(context, "Azure");
|
|
||||||
regAccessKeyCommand(context, "SageMaker");
|
|
||||||
regAccessKeyCommand(context, "Bedrock");
|
|
||||||
regAccessKeyCommand(context, "DevChat");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function registerStatusBarItemClickCommand(
|
export function registerStatusBarItemClickCommand(
|
||||||
context: vscode.ExtensionContext
|
context: vscode.ExtensionContext
|
||||||
@ -216,20 +151,13 @@ export function registerStatusBarItemClickCommand(
|
|||||||
export function regPythonPathCommand(context: vscode.ExtensionContext) {
|
export function regPythonPathCommand(context: vscode.ExtensionContext) {
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
vscode.commands.registerCommand("devchat.PythonPath", async () => {
|
vscode.commands.registerCommand("devchat.PythonPath", async () => {
|
||||||
const pythonPath =
|
const pythonPath = (await vscode.window.showInputBox({
|
||||||
(await vscode.window.showInputBox({
|
|
||||||
title: "Set Python Path",
|
title: "Set Python Path",
|
||||||
placeHolder: "Set Python Path",
|
placeHolder: "Set Python Path",
|
||||||
})) ?? "";
|
})) ?? "";
|
||||||
|
|
||||||
if (pythonPath) {
|
if (pythonPath) {
|
||||||
vscode.workspace
|
new DevChatConfig().set("python_for_chat", pythonPath);
|
||||||
.getConfiguration("DevChat")
|
|
||||||
.update(
|
|
||||||
"PythonForChat",
|
|
||||||
pythonPath,
|
|
||||||
vscode.ConfigurationTarget.Global
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -438,6 +366,77 @@ export function registerInstallCommandsPython(
|
|||||||
// vscode.window.showInformationMessage(`All slash Commands are ready to use! Please input / to try workflow commands!`);
|
// vscode.window.showInformationMessage(`All slash Commands are ready to use! Please input / to try workflow commands!`);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function registerInstallCommandsPython(context: vscode.ExtensionContext) {
|
||||||
|
let disposable = vscode.commands.registerCommand('DevChat.InstallCommandPython', async () => {
|
||||||
|
// steps of install command python
|
||||||
|
// 1. install python >= 3.11
|
||||||
|
// 2. check requirements.txt in ~/.chat dir
|
||||||
|
// 3. install requirements.txt
|
||||||
|
|
||||||
|
// 1. install python >= 3.11
|
||||||
|
logger.channel()?.info(`create env for python ...`);
|
||||||
|
logger.channel()?.info(`try to create env by mamba ...`);
|
||||||
|
let pythonCommand = await createEnvByMamba("devchat-commands", "", "3.11.4");
|
||||||
|
|
||||||
|
if (!pythonCommand || pythonCommand === "") {
|
||||||
|
logger.channel()?.info(`create env by mamba failed, try to create env by conda ...`);
|
||||||
|
pythonCommand = await createEnvByConda("devchat-commands", "", "3.11.4");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pythonCommand || pythonCommand === "") {
|
||||||
|
logger.channel()?.error(`create virtual python env failed, you need create it by yourself with command: "conda create -n devchat-commands python=3.11.4"`);
|
||||||
|
logger.channel()?.show();
|
||||||
|
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. check requirements.txt in ~/.chat dir
|
||||||
|
// ~/.chat/requirements.txt
|
||||||
|
const usrRequirementsFile = path.join(os.homedir(), '.chat', 'workflows', 'usr', 'requirements.txt');
|
||||||
|
const orgRequirementsFile = path.join(os.homedir(), '.chat', 'workflows', 'org', 'requirements.txt');
|
||||||
|
const sysRequirementsFile = path.join(os.homedir(), '.chat', 'workflows', 'sys', 'requirements.txt');
|
||||||
|
let requirementsFile = sysRequirementsFile;
|
||||||
|
if (fs.existsSync(orgRequirementsFile)) {
|
||||||
|
requirementsFile = orgRequirementsFile;
|
||||||
|
}
|
||||||
|
if (fs.existsSync(usrRequirementsFile)) {
|
||||||
|
requirementsFile = usrRequirementsFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs.existsSync(requirementsFile)) {
|
||||||
|
// logger.channel()?.warn(`requirements.txt not found in ~/.chat/workflows dir.`);
|
||||||
|
// logger.channel()?.show();
|
||||||
|
// vscode.window.showErrorMessage(`Error: see OUTPUT for more detail!`);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. install requirements.txt
|
||||||
|
// run command: pip install -r {requirementsFile}
|
||||||
|
let isInstalled = false;
|
||||||
|
// try 3 times
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
let otherSource: string | undefined = undefined;
|
||||||
|
if (i>1) {
|
||||||
|
otherSource = 'https://pypi.tuna.tsinghua.edu.cn/simple/';
|
||||||
|
}
|
||||||
|
isInstalled = await installRequirements(pythonCommand, requirementsFile, otherSource);
|
||||||
|
if (isInstalled) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
logger.channel()?.info(`Install packages failed, try again: ${i + 1}`);
|
||||||
|
}
|
||||||
|
if (!isInstalled) {
|
||||||
|
logger.channel()?.error(`Install packages failed, you can install it with command: "${pythonCommand} -m pip install -r ~/.chat/requirements.txt"`);
|
||||||
|
logger.channel()?.show();
|
||||||
|
vscode.window.showErrorMessage(`Error: see OUTPUT for more detail!`);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
new DevChatConfig().set("python_for_commands", pythonCommand.trim());
|
||||||
|
// vscode.window.showInformationMessage(`All slash Commands are ready to use! Please input / to try workflow commands!`);
|
||||||
|
});
|
||||||
|
|
||||||
context.subscriptions.push(disposable);
|
context.subscriptions.push(disposable);
|
||||||
}
|
}
|
||||||
@ -490,6 +489,7 @@ export function registerCodeLensRangeCommand(context: vscode.ExtensionContext) {
|
|||||||
context.subscriptions.push(disposable);
|
context.subscriptions.push(disposable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function registerHandleUri(context: vscode.ExtensionContext) {
|
export function registerHandleUri(context: vscode.ExtensionContext) {
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
vscode.window.registerUriHandler({
|
vscode.window.registerUriHandler({
|
||||||
@ -497,25 +497,7 @@ export function registerHandleUri(context: vscode.ExtensionContext) {
|
|||||||
// 解析 URI 并执行相应的操作
|
// 解析 URI 并执行相应的操作
|
||||||
if (uri.path.includes("accesskey")) {
|
if (uri.path.includes("accesskey")) {
|
||||||
const accessKey = uri.path.split("/")[2];
|
const accessKey = uri.path.split("/")[2];
|
||||||
const modelConfig: any = UiUtilWrapper.getConfiguration(
|
new DevChatConfig().set("provides.devchat.api_key", accessKey);
|
||||||
"devchat",
|
|
||||||
"Provider.devchat"
|
|
||||||
);
|
|
||||||
const providerConfigNew: any = {};
|
|
||||||
if (Object.keys(modelConfig).length !== 0) {
|
|
||||||
for (const key of Object.keys(modelConfig || {})) {
|
|
||||||
const property = modelConfig![key];
|
|
||||||
providerConfigNew[key] = property;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
providerConfigNew.access_key = accessKey;
|
|
||||||
vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(
|
|
||||||
"Provider.devchat",
|
|
||||||
providerConfigNew,
|
|
||||||
vscode.ConfigurationTarget.Global
|
|
||||||
);
|
|
||||||
ensureChatPanel(context);
|
ensureChatPanel(context);
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -529,7 +511,7 @@ export function registerHandleUri(context: vscode.ExtensionContext) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerExplainCommand(context: vscode.ExtensionContext) {
|
export function registerExplainCommand(context: vscode.ExtensionContext) {
|
||||||
const callback = async () => {
|
const callback = async () => {
|
||||||
const editor = vscode.window.activeTextEditor;
|
const editor = vscode.window.activeTextEditor;
|
||||||
if (editor) {
|
if (editor) {
|
||||||
@ -548,7 +530,7 @@ function registerExplainCommand(context: vscode.ExtensionContext) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerCommentCommand(context: vscode.ExtensionContext) {
|
export function registerCommentCommand(context: vscode.ExtensionContext) {
|
||||||
const callback = async () => {
|
const callback = async () => {
|
||||||
const editor = vscode.window.activeTextEditor;
|
const editor = vscode.window.activeTextEditor;
|
||||||
if (editor) {
|
if (editor) {
|
||||||
@ -567,7 +549,7 @@ function registerCommentCommand(context: vscode.ExtensionContext) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerFixCommand(context: vscode.ExtensionContext) {
|
export function registerFixCommand(context: vscode.ExtensionContext) {
|
||||||
const callback = async () => {
|
const callback = async () => {
|
||||||
const editor = vscode.window.activeTextEditor;
|
const editor = vscode.window.activeTextEditor;
|
||||||
if (editor) {
|
if (editor) {
|
||||||
@ -585,13 +567,3 @@ function registerFixCommand(context: vscode.ExtensionContext) {
|
|||||||
vscode.commands.registerCommand("devchat.fix_chinese", callback)
|
vscode.commands.registerCommand("devchat.fix_chinese", callback)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
|
||||||
registerOpenChatPanelCommand,
|
|
||||||
registerAddContextCommand,
|
|
||||||
registerAskForCodeCommand,
|
|
||||||
registerAskForFileCommand,
|
|
||||||
registerExplainCommand,
|
|
||||||
registerFixCommand,
|
|
||||||
registerCommentCommand,
|
|
||||||
};
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
import { UiUtilWrapper } from "../util/uiUtil";
|
import { UiUtilWrapper } from "../util/uiUtil";
|
||||||
import { runCommand } from "../util/commonUtil";
|
import { runCommand } from "../util/commonUtil";
|
||||||
import { logger } from "../util/logger";
|
import { logger } from "../util/logger";
|
||||||
|
import { DevChatConfig } from "../util/config";
|
||||||
|
|
||||||
let devchatStatus = '';
|
let devchatStatus = '';
|
||||||
|
|
||||||
@ -42,14 +43,14 @@ function getDefaultPythonCommand(): string | undefined {
|
|||||||
|
|
||||||
export function getValidPythonCommand(): string | undefined {
|
export function getValidPythonCommand(): string | undefined {
|
||||||
try {
|
try {
|
||||||
const pythonCommand = UiUtilWrapper.getConfiguration('DevChat', 'PythonForChat');
|
const pythonCommand = new DevChatConfig().get('python_for_chat');
|
||||||
if (pythonCommand) {
|
if (pythonCommand) {
|
||||||
return pythonCommand;
|
return pythonCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultPythonCommand = getDefaultPythonCommand();
|
const defaultPythonCommand = getDefaultPythonCommand();
|
||||||
if (defaultPythonCommand) {
|
if (defaultPythonCommand) {
|
||||||
UiUtilWrapper.updateConfiguration('DevChat', 'PythonForChat', defaultPythonCommand);
|
new DevChatConfig().set('python_for_chat', defaultPythonCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
return defaultPythonCommand;
|
return defaultPythonCommand;
|
||||||
|
484
src/extension.ts
484
src/extension.ts
@ -5,432 +5,118 @@ import {
|
|||||||
registerAddContextCommand,
|
registerAddContextCommand,
|
||||||
registerAskForCodeCommand,
|
registerAskForCodeCommand,
|
||||||
registerAskForFileCommand,
|
registerAskForFileCommand,
|
||||||
registerAccessKeySettingCommand,
|
|
||||||
regApplyDiffResultCommand,
|
regApplyDiffResultCommand,
|
||||||
registerStatusBarItemClickCommand,
|
registerStatusBarItemClickCommand,
|
||||||
regPythonPathCommand,
|
regPythonPathCommand,
|
||||||
registerInstallCommandsCommand,
|
registerInstallCommandsCommand,
|
||||||
registerUpdateChatModelsCommand,
|
|
||||||
registerInstallCommandsPython,
|
registerInstallCommandsPython,
|
||||||
registerDevChatChatCommand,
|
registerDevChatChatCommand,
|
||||||
registerHandleUri,
|
registerHandleUri,
|
||||||
registerExplainCommand,
|
|
||||||
registerCodeLensRangeCommand,
|
registerCodeLensRangeCommand,
|
||||||
|
registerUpdateChatModelsCommand,
|
||||||
registerCommentCommand,
|
registerCommentCommand,
|
||||||
registerFixCommand,
|
registerFixCommand,
|
||||||
} from "./contributes/commands";
|
registerExplainCommand,
|
||||||
import { regLanguageContext } from "./contributes/context";
|
|
||||||
import { regDevChatView } from "./contributes/views";
|
|
||||||
|
|
||||||
import { ExtensionContextHolder } from "./util/extensionContext";
|
} from './contributes/commands';
|
||||||
import { logger } from "./util/logger";
|
import { regLanguageContext } from './contributes/context';
|
||||||
import { LoggerChannelVscode } from "./util/logger_vscode";
|
import { regDevChatView } from './contributes/views';
|
||||||
import { createStatusBarItem } from "./panel/statusBarView";
|
|
||||||
import { UiUtilWrapper } from "./util/uiUtil";
|
|
||||||
import { UiUtilVscode } from "./util/uiUtil_vscode";
|
|
||||||
import { ApiKeyManager } from "./util/apiKey";
|
|
||||||
import { startRpcServer } from "./ide_services/services";
|
|
||||||
import { registerCodeLensProvider } from "./panel/codeLens";
|
|
||||||
import { stopDevChatBase } from "./handler/sendMessageBase";
|
|
||||||
import exp from "constants";
|
|
||||||
|
|
||||||
/**
|
import { ExtensionContextHolder } from './util/extensionContext';
|
||||||
* ABC isProviderHasSetted
|
import { logger } from './util/logger';
|
||||||
* @returns
|
import { LoggerChannelVscode } from './util/logger_vscode';
|
||||||
*/
|
import { createStatusBarItem } from './panel/statusBarView';
|
||||||
async function isProviderHasSetted() {
|
import { UiUtilWrapper } from './util/uiUtil';
|
||||||
try {
|
import { UiUtilVscode } from './util/uiUtil_vscode';
|
||||||
const providerProperty = "Provider.devchat";
|
import { startRpcServer } from './ide_services/services';
|
||||||
const providerConfig: any = UiUtilWrapper.getConfiguration(
|
import { registerCodeLensProvider } from './panel/codeLens';
|
||||||
"devchat",
|
import { stopDevChatBase } from './handler/sendMessageBase';
|
||||||
providerProperty
|
import { DevChatConfig } from './util/config';
|
||||||
);
|
|
||||||
if (providerConfig && Object.keys(providerConfig).length > 0) {
|
|
||||||
return true;
|
async function migrateConfig() {
|
||||||
|
const devchatProvider = "providers.devchat";
|
||||||
|
const devchatProviderConfig: any = new DevChatConfig().get(devchatProvider);
|
||||||
|
if (devchatProviderConfig) {
|
||||||
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
const providerPropertyOpenAI = "Provider.openai";
|
const devchatVScodeProvider: any = vscode.workspace.getConfiguration("devchat").get("Provider.devchat");
|
||||||
const providerConfigOpenAI: any = UiUtilWrapper.getConfiguration(
|
if (devchatVScodeProvider && Object.keys(devchatVScodeProvider).length > 0) {
|
||||||
"devchat",
|
if (devchatVScodeProvider["access_key"]) {
|
||||||
providerPropertyOpenAI
|
new DevChatConfig().set("providers.devchat.api_key", devchatVScodeProvider["access_key"]);
|
||||||
);
|
}
|
||||||
if (providerConfigOpenAI && Object.keys(providerConfigOpenAI).length > 0) {
|
if (devchatVScodeProvider["api_base"]) {
|
||||||
return true;
|
new DevChatConfig().set("providers.devchat.api_base", devchatVScodeProvider["api_base"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const openaiVScodeProvider: any = vscode.workspace.getConfiguration("devchat").get("Provider.openai");
|
||||||
|
if (openaiVScodeProvider && Object.keys(openaiVScodeProvider).length > 0) {
|
||||||
|
if (openaiVScodeProvider["access_key"]) {
|
||||||
|
new DevChatConfig().set("providers.openai.api_key", openaiVScodeProvider["access_key"]);
|
||||||
|
}
|
||||||
|
if (openaiVScodeProvider["api_base"]) {
|
||||||
|
new DevChatConfig().set("providers.openai.api_base", openaiVScodeProvider["api_base"]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiOpenaiKey = await ApiKeyManager.getProviderApiKey("openai");
|
const devchatSecretKey = await UiUtilWrapper.secretStorageGet(`Access_KEY_DevChat`);
|
||||||
if (apiOpenaiKey) {
|
const openaiSecretKey = await UiUtilWrapper.secretStorageGet(`Access_KEY_OpenAI`);
|
||||||
return true;
|
|
||||||
|
if (devchatSecretKey) {
|
||||||
|
new DevChatConfig().set("providers.devchat.api_key", devchatSecretKey);
|
||||||
}
|
}
|
||||||
const devchatKey = await ApiKeyManager.getProviderApiKey("devchat");
|
if (openaiSecretKey) {
|
||||||
if (devchatKey) {
|
new DevChatConfig().set("providers.openai.api_key", openaiSecretKey);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
const enableFunctionCalling = vscode.workspace.getConfiguration("DevChat").get("EnableFunctionCalling");
|
||||||
} catch (error) {
|
if (enableFunctionCalling) {
|
||||||
return false;
|
new DevChatConfig().set("enable_function_calling", enableFunctionCalling);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function configUpdateTo1115() {
|
|
||||||
const supportModels = ["Model.gpt-3-5-1106", "Model.gpt-4-turbo"];
|
|
||||||
|
|
||||||
for (const model of supportModels) {
|
|
||||||
const modelConfig1: any = UiUtilWrapper.getConfiguration("devchat", model);
|
|
||||||
if (modelConfig1 && Object.keys(modelConfig1).length === 0) {
|
|
||||||
let modelConfigNew = {};
|
|
||||||
modelConfigNew = { provider: "devchat" };
|
|
||||||
if (model.startsWith("Model.gpt-")) {
|
|
||||||
modelConfigNew = { provider: "openai" };
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(model, modelConfigNew, vscode.ConfigurationTarget.Global);
|
|
||||||
} catch (error) {
|
|
||||||
logger.channel()?.error(`update Model.ERNIE-Bot error: ${error}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function configUpdateTo0924() {
|
|
||||||
if (await isProviderHasSetted()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const defaultModel: any = UiUtilWrapper.getConfiguration(
|
|
||||||
"devchat",
|
|
||||||
"defaultModel"
|
|
||||||
);
|
|
||||||
|
|
||||||
let devchatKey = UiUtilWrapper.getConfiguration(
|
|
||||||
"DevChat",
|
|
||||||
"Access_Key_DevChat"
|
|
||||||
);
|
|
||||||
let openaiKey = UiUtilWrapper.getConfiguration("DevChat", "Api_Key_OpenAI");
|
|
||||||
const endpointKey = UiUtilWrapper.getConfiguration("DevChat", "API_ENDPOINT");
|
|
||||||
|
|
||||||
devchatKey = undefined;
|
|
||||||
openaiKey = undefined;
|
|
||||||
if (!devchatKey && !openaiKey) {
|
|
||||||
openaiKey = await UiUtilWrapper.secretStorageGet("openai_OPENAI_API_KEY");
|
|
||||||
devchatKey = await UiUtilWrapper.secretStorageGet("devchat_OPENAI_API_KEY");
|
|
||||||
await UiUtilWrapper.storeSecret("openai_OPENAI_API_KEY", "");
|
|
||||||
await UiUtilWrapper.storeSecret("devchat_OPENAI_API_KEY", "");
|
|
||||||
}
|
|
||||||
if (!devchatKey && !openaiKey) {
|
|
||||||
openaiKey = process.env.OPENAI_API_KEY;
|
|
||||||
}
|
|
||||||
|
|
||||||
let modelConfigNew = {};
|
|
||||||
let providerConfigNew = {};
|
|
||||||
if (openaiKey) {
|
|
||||||
providerConfigNew["access_key"] = openaiKey;
|
|
||||||
if (endpointKey) {
|
|
||||||
providerConfigNew["api_base"] = endpointKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
await vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(
|
|
||||||
"Provider.openai",
|
|
||||||
providerConfigNew,
|
|
||||||
vscode.ConfigurationTarget.Global
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (devchatKey) {
|
|
||||||
providerConfigNew["access_key"] = devchatKey;
|
|
||||||
if (endpointKey) {
|
|
||||||
providerConfigNew["api_base"] = endpointKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
await vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(
|
|
||||||
"Provider.devchat",
|
|
||||||
providerConfigNew,
|
|
||||||
vscode.ConfigurationTarget.Global
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const supportModels = [
|
|
||||||
"Model.gpt-3-5",
|
|
||||||
"Model.gpt-3-5-1106",
|
|
||||||
"Model.gpt-3-5-16k",
|
|
||||||
"Model.gpt-4",
|
|
||||||
"Model.gpt-4-turbo",
|
|
||||||
"Model.xinghuo-2",
|
|
||||||
"Model.chatglm_pro",
|
|
||||||
"Model.ERNIE-Bot",
|
|
||||||
"Model.CodeLlama-34b-Instruct",
|
|
||||||
"Model.llama-2-70b-chat",
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const model of supportModels) {
|
|
||||||
const modelConfig1: any = UiUtilWrapper.getConfiguration("devchat", model);
|
|
||||||
if (modelConfig1 && Object.keys(modelConfig1).length === 0) {
|
|
||||||
modelConfigNew = { provider: "devchat" };
|
|
||||||
if (model.startsWith("Model.gpt-")) {
|
|
||||||
modelConfigNew = { provider: "openai" };
|
|
||||||
}
|
|
||||||
|
|
||||||
await vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(model, modelConfigNew, vscode.ConfigurationTarget.Global);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function configUpdate0912To0924() {
|
|
||||||
if (await isProviderHasSetted()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const oldModels = [
|
|
||||||
"Model.gpt-3-5",
|
|
||||||
"Model.gpt-3-5-16k",
|
|
||||||
"Model.gpt-4",
|
|
||||||
"Model.claude-2",
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const model of oldModels) {
|
|
||||||
const modelConfig: any = UiUtilWrapper.getConfiguration("devchat", model);
|
|
||||||
if (modelConfig && Object.keys(modelConfig).length !== 0) {
|
|
||||||
let modelProperties: any = {};
|
|
||||||
for (const key of Object.keys(modelConfig || {})) {
|
|
||||||
const property = modelConfig![key];
|
|
||||||
modelProperties[key] = property;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modelConfig["api_key"]) {
|
|
||||||
let providerConfigNew = {};
|
|
||||||
providerConfigNew["access_key"] = modelConfig["api_key"];
|
|
||||||
if (modelConfig["api_base"]) {
|
|
||||||
providerConfigNew["api_base"] = modelConfig["api_base"];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modelConfig["api_key"].startsWith("DC.")) {
|
|
||||||
modelProperties["provider"] = "devchat";
|
|
||||||
await vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(
|
|
||||||
"Provider.devchat",
|
|
||||||
providerConfigNew,
|
|
||||||
vscode.ConfigurationTarget.Global
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
modelProperties["provider"] = "openai";
|
new DevChatConfig().set("enable_function_calling", false);
|
||||||
await vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(
|
|
||||||
"Provider.openai",
|
|
||||||
providerConfigNew,
|
|
||||||
vscode.ConfigurationTarget.Global
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete modelProperties["api_key"];
|
const betaInvitationCode = vscode.workspace.getConfiguration("DevChat").get("betaInvitationCode");
|
||||||
delete modelProperties["api_base"];
|
if (betaInvitationCode) {
|
||||||
try {
|
new DevChatConfig().set("beta_invitation_code", betaInvitationCode);
|
||||||
await vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(model, modelProperties, vscode.ConfigurationTarget.Global);
|
|
||||||
} catch (error) {
|
|
||||||
logger.channel()?.error(`error: ${error}`);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!modelProperties["provider"]) {
|
new DevChatConfig().set("beta_invitation_code", "");
|
||||||
delete modelProperties["api_base"];
|
|
||||||
modelProperties["provider"] = "devchat";
|
|
||||||
try {
|
|
||||||
await vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(
|
|
||||||
model,
|
|
||||||
modelProperties,
|
|
||||||
vscode.ConfigurationTarget.Global
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
logger.channel()?.error(`error: ${error}`);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function configUpdateto240205() {
|
const maxLogCount = vscode.workspace.getConfiguration("DevChat").get("maxLogCount");
|
||||||
// rename Model.CodeLlama-34b-Instruct to Model.CodeLlama-70b
|
if (maxLogCount) {
|
||||||
// add new Model.Mixtral-8x7B
|
new DevChatConfig().set("max_log_count", maxLogCount);
|
||||||
// add new Model.Minimax-abab6
|
|
||||||
const supportModels = [
|
|
||||||
"Model.CodeLlama-70b",
|
|
||||||
"Model.Mixtral-8x7B",
|
|
||||||
"Model.Minimax-abab6",
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const model of supportModels) {
|
|
||||||
const modelConfig1: any = UiUtilWrapper.getConfiguration("devchat", model);
|
|
||||||
if (modelConfig1 && Object.keys(modelConfig1).length === 0) {
|
|
||||||
let modelConfigNew = {};
|
|
||||||
modelConfigNew = { provider: "devchat" };
|
|
||||||
try {
|
|
||||||
await vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(model, modelConfigNew, vscode.ConfigurationTarget.Global);
|
|
||||||
} catch (error) {
|
|
||||||
logger.channel()?.error(`error: ${error}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setLangDefaultValue() {
|
|
||||||
const lang = vscode.env.language;
|
|
||||||
if (!UiUtilWrapper.getConfiguration("DevChat", "Language")) {
|
|
||||||
if (lang.startsWith("zh-")) {
|
|
||||||
UiUtilWrapper.updateConfiguration("DevChat", "Language", "zh");
|
|
||||||
} else {
|
} else {
|
||||||
UiUtilWrapper.updateConfiguration("DevChat", "Language", "en");
|
new DevChatConfig().set("max_log_count", 20);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateInvalidSettings() {
|
|
||||||
const oldModels = [
|
|
||||||
"Model.gpt-3-5",
|
|
||||||
"Model.gpt-3-5-16k",
|
|
||||||
"Model.gpt-4",
|
|
||||||
"Model.claude-2",
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const model of oldModels) {
|
|
||||||
const modelConfig: any = UiUtilWrapper.getConfiguration("devchat", model);
|
|
||||||
if (modelConfig && Object.keys(modelConfig).length !== 0) {
|
|
||||||
let modelProperties: any = {};
|
|
||||||
for (const key of Object.keys(modelConfig || {})) {
|
|
||||||
const property = modelConfig![key];
|
|
||||||
modelProperties[key] = property;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modelConfig["api_key"]) {
|
const pythonForChat = vscode.workspace.getConfiguration("DevChat").get("PythonForChat");
|
||||||
delete modelProperties["api_key"];
|
if (pythonForChat) {
|
||||||
delete modelProperties["api_base"];
|
new DevChatConfig().set("python_for_chat", pythonForChat);
|
||||||
modelProperties["provider"] = "devchat";
|
} else {
|
||||||
try {
|
new DevChatConfig().set("python_for_chat", "");
|
||||||
await vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(model, modelProperties, vscode.ConfigurationTarget.Global);
|
|
||||||
} catch (error) {
|
|
||||||
logger.channel()?.error(`error: ${error}`);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateInvalidDefaultModel() {
|
const pythonForCommands = vscode.workspace.getConfiguration("DevChat").get("PythonForCommands");
|
||||||
const defaultModel: any = UiUtilWrapper.getConfiguration(
|
if (pythonForCommands) {
|
||||||
"devchat",
|
new DevChatConfig().set("python_for_commands", pythonForCommands);
|
||||||
"defaultModel"
|
} else {
|
||||||
);
|
new DevChatConfig().set("python_for_commands", "");
|
||||||
if (
|
|
||||||
defaultModel === "gpt-3.5-turbo-1106" ||
|
|
||||||
defaultModel === "gpt-3.5-turbo-16k"
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
await vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(
|
|
||||||
"defaultModel",
|
|
||||||
"gpt-3.5-turbo",
|
|
||||||
vscode.ConfigurationTarget.Global
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
logger.channel()?.error(`update Model.ERNIE-Bot error: ${error}`);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// "gpt-3.5-turbo-1106",
|
const language = vscode.workspace.getConfiguration("DevChat").get("Language");
|
||||||
// "gpt-3.5-turbo-16k",
|
if (language) {
|
||||||
|
new DevChatConfig().set("language", language);
|
||||||
|
} else {
|
||||||
|
new DevChatConfig().set("language", "en");
|
||||||
|
}
|
||||||
|
|
||||||
async function configSetModelDefaultParams() {
|
const defaultModel = vscode.workspace.getConfiguration("devchat").get("defaultModel");
|
||||||
const modelParams = {
|
if (defaultModel) {
|
||||||
"Model.gpt-3-5": {
|
new DevChatConfig().set("default_model", defaultModel);
|
||||||
max_input_tokens: 13000,
|
} else {
|
||||||
},
|
new DevChatConfig().set("default_model", "");
|
||||||
"Model.gpt-4": {
|
|
||||||
max_input_tokens: 6000,
|
|
||||||
},
|
|
||||||
"Model.gpt-4-turbo": {
|
|
||||||
max_input_tokens: 32000,
|
|
||||||
},
|
|
||||||
"Model.claude-3-opus": {
|
|
||||||
max_input_tokens: 32000,
|
|
||||||
},
|
|
||||||
"Model.claude-3-sonnet": {
|
|
||||||
max_input_tokens: 32000,
|
|
||||||
},
|
|
||||||
"Model.xinghuo-2": {
|
|
||||||
max_input_tokens: 6000,
|
|
||||||
},
|
|
||||||
"Model.chatglm_pro": {
|
|
||||||
max_input_tokens: 8000,
|
|
||||||
},
|
|
||||||
"Model.ERNIE-Bot": {
|
|
||||||
max_input_tokens: 8000,
|
|
||||||
},
|
|
||||||
"Model.CodeLlama-70b": {
|
|
||||||
max_input_tokens: 4000,
|
|
||||||
},
|
|
||||||
"Model.Mixtral-8x7B": {
|
|
||||||
max_input_tokens: 4000,
|
|
||||||
},
|
|
||||||
"Model.Minimax-abab6": {
|
|
||||||
max_input_tokens: 4000,
|
|
||||||
},
|
|
||||||
"Model.llama-2-70b-chat": {
|
|
||||||
max_input_tokens: 4000,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// set default params
|
|
||||||
for (const model of Object.keys(modelParams)) {
|
|
||||||
const modelConfig: any = UiUtilWrapper.getConfiguration("devchat", model);
|
|
||||||
if (!modelConfig["max_input_tokens"]) {
|
|
||||||
modelConfig["max_input_tokens"] = modelParams[model]["max_input_tokens"];
|
|
||||||
try {
|
|
||||||
await vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(model, modelConfig, vscode.ConfigurationTarget.Global);
|
|
||||||
} catch (error) {
|
|
||||||
logger.channel()?.error(`update Model.ERNIE-Bot error: ${error}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateClaudePrivider() {
|
|
||||||
const claudeModels = ["Model.claude-3-opus", "Model.claude-3-sonnet"];
|
|
||||||
|
|
||||||
for (const model of claudeModels) {
|
|
||||||
const modelConfig: any = UiUtilWrapper.getConfiguration("devchat", model);
|
|
||||||
if (modelConfig && Object.keys(modelConfig).length === 0) {
|
|
||||||
const modelProperties: any = {
|
|
||||||
provider: "devchat",
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
await vscode.workspace
|
|
||||||
.getConfiguration("devchat")
|
|
||||||
.update(model, modelProperties, vscode.ConfigurationTarget.Global);
|
|
||||||
} catch (error) {
|
|
||||||
logger.channel()?.error(`update ${model} error: ${error}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,21 +126,11 @@ async function activate(context: vscode.ExtensionContext) {
|
|||||||
logger.init(LoggerChannelVscode.getInstance());
|
logger.init(LoggerChannelVscode.getInstance());
|
||||||
UiUtilWrapper.init(new UiUtilVscode());
|
UiUtilWrapper.init(new UiUtilVscode());
|
||||||
|
|
||||||
await configUpdateTo0924();
|
await migrateConfig();
|
||||||
await configUpdate0912To0924();
|
|
||||||
await configUpdateTo1115();
|
|
||||||
await setLangDefaultValue();
|
|
||||||
await updateInvalidSettings();
|
|
||||||
await updateInvalidDefaultModel();
|
|
||||||
await configUpdateto240205();
|
|
||||||
await updateClaudePrivider();
|
|
||||||
await configSetModelDefaultParams();
|
|
||||||
|
|
||||||
regLanguageContext();
|
regLanguageContext();
|
||||||
|
|
||||||
regDevChatView(context);
|
regDevChatView(context);
|
||||||
|
|
||||||
registerAccessKeySettingCommand(context);
|
|
||||||
registerOpenChatPanelCommand(context);
|
registerOpenChatPanelCommand(context);
|
||||||
registerAddContextCommand(context);
|
registerAddContextCommand(context);
|
||||||
registerAskForCodeCommand(context);
|
registerAskForCodeCommand(context);
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
Update config
|
|
||||||
*/
|
|
||||||
|
|
||||||
import * as vscode from 'vscode';
|
|
||||||
import { regInMessage, regOutMessage } from '../util/reg_messages';
|
|
||||||
import { UiUtilWrapper } from '../util/uiUtil';
|
|
||||||
import { MessageHandler } from './messageHandler';
|
|
||||||
import { ApiKeyManager } from '../util/apiKey';
|
|
||||||
|
|
||||||
regInMessage({command: 'getUserAccessKey'});
|
|
||||||
regOutMessage({command: 'getUserAccessKey', accessKey: "DC.xxx", keyType: "DevChat", endPoint: "https://xxx"});
|
|
||||||
export async function getUserAccessKey(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
|
||||||
const workspaceDir = UiUtilWrapper.workspaceFoldersFirstPath();
|
|
||||||
const llmModelData = await ApiKeyManager.llmModel();
|
|
||||||
if (!llmModelData || !llmModelData.api_key) {
|
|
||||||
MessageHandler.sendMessage(panel,
|
|
||||||
{
|
|
||||||
"command": "getUserAccessKey",
|
|
||||||
"accessKey": "",
|
|
||||||
"keyType": "",
|
|
||||||
"endPoint": ""
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const keyData = {
|
|
||||||
"command": "getUserAccessKey",
|
|
||||||
"accessKey": llmModelData.api_key,
|
|
||||||
"keyType": llmModelData.api_key?.startsWith("DC.") ? "DevChat" : "others",
|
|
||||||
"endPoint": llmModelData.api_base ? llmModelData.api_base : ""
|
|
||||||
};
|
|
||||||
MessageHandler.sendMessage(panel, keyData, false);
|
|
||||||
}
|
|
29
src/handler/configHandler.ts
Normal file
29
src/handler/configHandler.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
Commands for handling configuration read and write
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import { regInMessage, regOutMessage } from '../util/reg_messages';
|
||||||
|
import { MessageHandler } from './messageHandler';
|
||||||
|
import { DevChatConfig } from '../util/config';
|
||||||
|
|
||||||
|
regInMessage({command: 'readConfig', key: ''}); // when key is "", it will get all config values
|
||||||
|
regOutMessage({command: 'readConfig', key: '', value: 'any'});
|
||||||
|
export async function readConfig(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
||||||
|
if (message.key === '*' || message.key === '') {
|
||||||
|
const config = new DevChatConfig().getAll();
|
||||||
|
MessageHandler.sendMessage(panel, {command: 'readConfig', key: message.key, value: config});
|
||||||
|
} else {
|
||||||
|
const config = new DevChatConfig().get(message.key);
|
||||||
|
MessageHandler.sendMessage(panel, {command: 'readConfig', key: message.key, value: config});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
regInMessage({command: 'writeConfig', key: '', value: 'any'}); // when key is "", it will rewrite all config values
|
||||||
|
export async function writeConfig(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
||||||
|
if (message.key === '*' || message.key === '') {
|
||||||
|
new DevChatConfig().setAll(message.value);
|
||||||
|
} else {
|
||||||
|
new DevChatConfig().set(message.key, message.value);
|
||||||
|
}
|
||||||
|
}
|
@ -11,12 +11,11 @@ import { addConext } from './contextHandler';
|
|||||||
import { getContextDetail } from './contextHandler';
|
import { getContextDetail } from './contextHandler';
|
||||||
import { listAllMessages } from './listMessages';
|
import { listAllMessages } from './listMessages';
|
||||||
import { doVscodeCommand } from './vscodeCommandHandler';
|
import { doVscodeCommand } from './vscodeCommandHandler';
|
||||||
import { getSetting, updateSetting } from './userSettingHandler';
|
|
||||||
import { featureToggle, getFeatureToggles } from './featureToggleHandler';
|
import { featureToggle, getFeatureToggles } from './featureToggleHandler';
|
||||||
import { getUserAccessKey } from './accessKeyHandler';
|
|
||||||
import { getValidLlmModelList } from './llmModelHandler';
|
|
||||||
import { readFile, writeFile } from './fileHandler';
|
import { readFile, writeFile } from './fileHandler';
|
||||||
import { getTopics, deleteTopic } from './topicHandler';
|
import { getTopics, deleteTopic } from './topicHandler';
|
||||||
|
import { readConfig, writeConfig } from './configHandler';
|
||||||
|
import { getSetting, getUserAccessKey, getValidLlmModelList, updateSetting } from './removehandler';
|
||||||
|
|
||||||
|
|
||||||
// According to the context menu selected by the user, add the corresponding context file
|
// According to the context menu selected by the user, add the corresponding context file
|
||||||
@ -70,15 +69,9 @@ messageHandler.registerHandler('deleteChatMessage', deleteChatMessage);
|
|||||||
// Response: none
|
// Response: none
|
||||||
messageHandler.registerHandler('doCommand', doVscodeCommand);
|
messageHandler.registerHandler('doCommand', doVscodeCommand);
|
||||||
|
|
||||||
messageHandler.registerHandler('updateSetting', updateSetting);
|
|
||||||
messageHandler.registerHandler('getSetting', getSetting);
|
|
||||||
messageHandler.registerHandler('featureToggle', featureToggle);
|
messageHandler.registerHandler('featureToggle', featureToggle);
|
||||||
messageHandler.registerHandler('featureToggles', getFeatureToggles);
|
messageHandler.registerHandler('featureToggles', getFeatureToggles);
|
||||||
|
|
||||||
messageHandler.registerHandler('getUserAccessKey', getUserAccessKey);
|
|
||||||
|
|
||||||
messageHandler.registerHandler('regModelList', getValidLlmModelList);
|
|
||||||
|
|
||||||
messageHandler.registerHandler('userInput', userInput);
|
messageHandler.registerHandler('userInput', userInput);
|
||||||
|
|
||||||
messageHandler.registerHandler('readFile', readFile);
|
messageHandler.registerHandler('readFile', readFile);
|
||||||
@ -87,3 +80,10 @@ messageHandler.registerHandler('writeFile', writeFile);
|
|||||||
messageHandler.registerHandler('getTopics', getTopics);
|
messageHandler.registerHandler('getTopics', getTopics);
|
||||||
messageHandler.registerHandler('deleteTopic', deleteTopic);
|
messageHandler.registerHandler('deleteTopic', deleteTopic);
|
||||||
|
|
||||||
|
messageHandler.registerHandler('readConfig', readConfig);
|
||||||
|
messageHandler.registerHandler('writeConfig', writeConfig);
|
||||||
|
|
||||||
|
messageHandler.registerHandler('regModelList', getValidLlmModelList);
|
||||||
|
messageHandler.registerHandler('updateSetting', updateSetting);
|
||||||
|
messageHandler.registerHandler('getSetting', getSetting);
|
||||||
|
messageHandler.registerHandler('getUserAccessKey', getUserAccessKey);
|
@ -137,9 +137,3 @@ export async function historyMessagesBase(topicId: string): Promise<LoadHistoryM
|
|||||||
entries: logEntriesFlat.length > 0 ? logEntriesFlat : [],
|
entries: logEntriesFlat.length > 0 ? logEntriesFlat : [],
|
||||||
} as LoadHistoryMessages;
|
} as LoadHistoryMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function onApiKeyBase(apiKey: string): Promise<{ command: string, text: string, hash: string, user: string, date: string, isError: boolean }> {
|
|
||||||
return {
|
|
||||||
command: 'receiveMessage', text: `You need config access key for specified llmodel in setting view.`, hash: '', user: 'system', date: '', isError: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { MessageHandler } from './messageHandler';
|
import { MessageHandler } from './messageHandler';
|
||||||
import { regInMessage, regOutMessage } from '../util/reg_messages';
|
import { regInMessage, regOutMessage } from '../util/reg_messages';
|
||||||
import { historyMessagesBase, LoadHistoryMessages, loadTopicHistoryFromCurrentMessageHistory, onApiKeyBase } from './historyMessagesBase';
|
import { historyMessagesBase, LoadHistoryMessages, loadTopicHistoryFromCurrentMessageHistory } from './historyMessagesBase';
|
||||||
import { UiUtilWrapper } from '../util/uiUtil';
|
import { UiUtilWrapper } from '../util/uiUtil';
|
||||||
|
import { DevChatConfig } from '../util/config';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ regInMessage({command: 'historyMessages', topicId: '', page: 0});
|
|||||||
regOutMessage({command: 'loadHistoryMessages', entries: [{hash: '',user: '',date: '',request: '',response: '',context: [{content: '',role: ''}]}]});
|
regOutMessage({command: 'loadHistoryMessages', entries: [{hash: '',user: '',date: '',request: '',response: '',context: [{content: '',role: ''}]}]});
|
||||||
export async function getHistoryMessages(message: {command: string, topicId: string, page: number}, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
export async function getHistoryMessages(message: {command: string, topicId: string, page: number}, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
||||||
// if history message has load, send it to webview
|
// if history message has load, send it to webview
|
||||||
const maxCount = Number(UiUtilWrapper.getConfiguration('DevChat', 'maxLogCount'));
|
const maxCount = Number(new DevChatConfig().get('max_log_count'));
|
||||||
const skip = maxCount * (message.page ? message.page : 0);
|
const skip = maxCount * (message.page ? message.page : 0);
|
||||||
const topicId = message.topicId;
|
const topicId = message.topicId;
|
||||||
|
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
import * as vscode from 'vscode';
|
|
||||||
import { MessageHandler } from './messageHandler';
|
|
||||||
import { regInMessage, regOutMessage } from '../util/reg_messages';
|
|
||||||
import { ApiKeyManager } from '../util/apiKey';
|
|
||||||
|
|
||||||
|
|
||||||
regInMessage({command: 'regModelList'});
|
|
||||||
regOutMessage({command: 'regModelList', result: [{name: ''}]});
|
|
||||||
export async function getValidLlmModelList(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
|
||||||
const modelList = await ApiKeyManager.getValidModels();
|
|
||||||
|
|
||||||
MessageHandler.sendMessage(panel, { command: 'regModelList', result: modelList });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -19,6 +19,7 @@ export class MessageHandler {
|
|||||||
|
|
||||||
|
|
||||||
async handleMessage(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
async handleMessage(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
||||||
|
try {
|
||||||
let isNeedSendResponse = false;
|
let isNeedSendResponse = false;
|
||||||
if (message.command === 'sendMessage') {
|
if (message.command === 'sendMessage') {
|
||||||
try {
|
try {
|
||||||
@ -48,6 +49,11 @@ export class MessageHandler {
|
|||||||
if (isNeedSendResponse) {
|
if (isNeedSendResponse) {
|
||||||
MessageHandler.sendMessage(panel, { command: 'receiveMessage', text: 'finish', hash: '', user: '', date: 1, isError: false });
|
MessageHandler.sendMessage(panel, { command: 'receiveMessage', text: 'finish', hash: '', user: '', date: 1, isError: false });
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
logger.channel()?.error(`Error handling the message: "${JSON.stringify(message)}"`);
|
||||||
|
logger.channel()?.show();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static sendMessage(panel: vscode.WebviewPanel|vscode.WebviewView, message : any, log: boolean = true): void {
|
public static sendMessage(panel: vscode.WebviewPanel|vscode.WebviewView, message : any, log: boolean = true): void {
|
||||||
|
49
src/handler/removehandler.ts
Normal file
49
src/handler/removehandler.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import { MessageHandler } from './messageHandler';
|
||||||
|
import { regInMessage, regOutMessage } from '../util/reg_messages';
|
||||||
|
import { ApiKeyManager } from '../util/apiKey';
|
||||||
|
import { UiUtilWrapper } from '../util/uiUtil';
|
||||||
|
|
||||||
|
|
||||||
|
regInMessage({command: 'regModelList'});
|
||||||
|
regOutMessage({command: 'regModelList', result: [{name: ''}]});
|
||||||
|
export async function getValidLlmModelList(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
||||||
|
const modelList = ["model1", "model2", "model3"];
|
||||||
|
|
||||||
|
MessageHandler.sendMessage(panel, { command: 'regModelList', result: modelList });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
regInMessage({command: 'updateSetting', key1: "DevChat", key2: "OpenAI", value:"xxxx"});
|
||||||
|
export async function updateSetting(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
regInMessage({command: 'getSetting', key1: "DevChat", key2: "OpenAI"});
|
||||||
|
regOutMessage({command: 'getSetting', key1: "DevChat", key2: "OpenAI", value: "GPT-4"});
|
||||||
|
export async function getSetting(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
||||||
|
if (message.key2 === "Language") {
|
||||||
|
MessageHandler.sendMessage(panel, {"command": "getSetting", "key1": message.key1, "key2": message.key2, "value": "en"});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MessageHandler.sendMessage(panel, {"command": "getSetting", "key1": message.key1, "key2": message.key2, "value": "model2"});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
regInMessage({command: 'getUserAccessKey'});
|
||||||
|
regOutMessage({command: 'getUserAccessKey', accessKey: "DC.xxx", keyType: "DevChat", endPoint: "https://xxx"});
|
||||||
|
export async function getUserAccessKey(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
||||||
|
MessageHandler.sendMessage(panel,
|
||||||
|
{
|
||||||
|
"command": "getUserAccessKey",
|
||||||
|
"accessKey": "",
|
||||||
|
"keyType": "",
|
||||||
|
"endPoint": ""
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
Update config
|
|
||||||
*/
|
|
||||||
|
|
||||||
import * as vscode from 'vscode';
|
|
||||||
import { regInMessage, regOutMessage } from '../util/reg_messages';
|
|
||||||
import { UiUtilWrapper } from '../util/uiUtil';
|
|
||||||
import { MessageHandler } from './messageHandler';
|
|
||||||
|
|
||||||
regInMessage({command: 'updateSetting', key1: "DevChat", key2: "OpenAI", value:"xxxx"});
|
|
||||||
export async function updateSetting(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
|
||||||
UiUtilWrapper.updateConfiguration(message.key1, message.key2, message.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
regInMessage({command: 'getSetting', key1: "DevChat", key2: "OpenAI"});
|
|
||||||
regOutMessage({command: 'getSetting', key1: "DevChat", key2: "OpenAI", value: "GPT-4"});
|
|
||||||
export async function getSetting(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
|
||||||
MessageHandler.sendMessage(panel, {"command": "getSetting", "key1": message.key1, "key2": message.key2, "value": UiUtilWrapper.getConfiguration(message.key1, message.key2)});
|
|
||||||
}
|
|
@ -61,8 +61,3 @@ export async function sendCommandListByDevChatRun() {
|
|||||||
await getWorkflowCommandList({}, existPannel!);
|
await getWorkflowCommandList({}, existPannel!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateChatModels() {
|
|
||||||
const modelList = await ApiKeyManager.getValidModels();
|
|
||||||
MessageHandler.sendMessage(existPannel!, { command: 'regModelList', result: modelList });
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { UiUtilWrapper } from "../../util/uiUtil";
|
import { DevChatConfig } from "../../util/config";
|
||||||
|
|
||||||
export async function ideLanguage() {
|
export async function ideLanguage() {
|
||||||
const language = UiUtilWrapper.getConfiguration("DevChat", "Language");
|
const language = new DevChatConfig().get('language');
|
||||||
// 'en' stands for English, 'zh' stands for Simplified Chinese
|
// 'en' stands for English, 'zh' stands for Simplified Chinese
|
||||||
return language;
|
return language;
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,8 @@ import * as vscode from 'vscode';
|
|||||||
|
|
||||||
import { dependencyCheck } from './statusBarViewBase';
|
import { dependencyCheck } from './statusBarViewBase';
|
||||||
import { ProgressBar } from '../util/progressBar';
|
import { ProgressBar } from '../util/progressBar';
|
||||||
import { ExtensionContextHolder } from '../util/extensionContext';
|
|
||||||
import { UiUtilWrapper } from '../util/uiUtil';
|
|
||||||
import { logger } from '../util/logger';
|
import { logger } from '../util/logger';
|
||||||
|
import { DevChatConfig } from '../util/config';
|
||||||
|
|
||||||
|
|
||||||
export function createStatusBarItem(context: vscode.ExtensionContext): vscode.StatusBarItem {
|
export function createStatusBarItem(context: vscode.ExtensionContext): vscode.StatusBarItem {
|
||||||
@ -26,7 +25,7 @@ export function createStatusBarItem(context: vscode.ExtensionContext): vscode.St
|
|||||||
function checkDevChatCommandsStatus() {
|
function checkDevChatCommandsStatus() {
|
||||||
const timerDevchatCommands = setInterval(async () => {
|
const timerDevchatCommands = setInterval(async () => {
|
||||||
try {
|
try {
|
||||||
const pythonCommand = UiUtilWrapper.getConfiguration("DevChat", "PythonForCommands");
|
const pythonCommand = new DevChatConfig().get('python_for_commands');
|
||||||
if (!pythonCommand) {
|
if (!pythonCommand) {
|
||||||
statusBarItem.text = `$(pass)DevChat$(warning)`;
|
statusBarItem.text = `$(pass)DevChat$(warning)`;
|
||||||
statusBarItem.tooltip = `ready to chat, command functionality limited`;
|
statusBarItem.tooltip = `ready to chat, command functionality limited`;
|
||||||
@ -48,7 +47,7 @@ export function createStatusBarItem(context: vscode.ExtensionContext): vscode.St
|
|||||||
try {
|
try {
|
||||||
progressBar.update("Checking dependencies", 0);
|
progressBar.update("Checking dependencies", 0);
|
||||||
|
|
||||||
const [devchatStatus, apiKeyStatus] = await dependencyCheck();
|
const devchatStatus = await dependencyCheck();
|
||||||
if (devchatStatus !== 'has statisfied the dependency' && devchatStatus !== 'DevChat has been installed') {
|
if (devchatStatus !== 'has statisfied the dependency' && devchatStatus !== 'DevChat has been installed') {
|
||||||
statusBarItem.text = `$(warning)DevChat`;
|
statusBarItem.text = `$(warning)DevChat`;
|
||||||
statusBarItem.tooltip = `${devchatStatus}`;
|
statusBarItem.tooltip = `${devchatStatus}`;
|
||||||
@ -64,14 +63,6 @@ export function createStatusBarItem(context: vscode.ExtensionContext): vscode.St
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (apiKeyStatus !== 'has valid access key') {
|
|
||||||
statusBarItem.text = `$(warning)DevChat`;
|
|
||||||
statusBarItem.tooltip = `${apiKeyStatus}`;
|
|
||||||
statusBarItem.command = 'DevChat.AccessKey.DevChat';
|
|
||||||
progressBar.update(`Checking dependencies: ${apiKeyStatus}.`, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
statusBarItem.text = `$(pass)DevChat`;
|
statusBarItem.text = `$(pass)DevChat`;
|
||||||
statusBarItem.tooltip = `ready to chat`;
|
statusBarItem.tooltip = `ready to chat`;
|
||||||
statusBarItem.command = 'devcaht.onStatusBarClick';
|
statusBarItem.command = 'devcaht.onStatusBarClick';
|
||||||
|
@ -7,22 +7,12 @@ import { ApiKeyManager } from '../util/apiKey';
|
|||||||
import { installDevchat } from '../util/python_installer/install_devchat';
|
import { installDevchat } from '../util/python_installer/install_devchat';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function getExtensionVersion(): string {
|
|
||||||
const packageJsonPath = path.join(UiUtilWrapper.extensionPath(), 'package.json');
|
|
||||||
const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
|
|
||||||
const packageJson = JSON.parse(packageJsonContent);
|
|
||||||
|
|
||||||
return packageJson.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
let devchatStatus = '';
|
let devchatStatus = '';
|
||||||
let apiKeyStatus = '';
|
let apiKeyStatus = '';
|
||||||
|
|
||||||
let preDevchatStatus = '';
|
let preDevchatStatus = '';
|
||||||
let preApiKeyStatus = '';
|
|
||||||
|
|
||||||
export async function dependencyCheck(): Promise<[string, string]> {
|
export async function dependencyCheck(): Promise<string> {
|
||||||
// there are some different status of devchat:
|
// there are some different status of devchat:
|
||||||
// 0. not checked
|
// 0. not checked
|
||||||
// 1. has statisfied the dependency
|
// 1. has statisfied the dependency
|
||||||
@ -62,33 +52,12 @@ export async function dependencyCheck(): Promise<[string, string]> {
|
|||||||
return "";
|
return "";
|
||||||
};
|
};
|
||||||
|
|
||||||
// define subfunction to check api key
|
|
||||||
const getApiKeyStatus = async (): Promise<string> => {
|
|
||||||
if (apiKeyStatus === '' || apiKeyStatus === 'Click "DevChat" status icon to set key') {
|
|
||||||
const defaultModel = await ApiKeyManager.llmModel();
|
|
||||||
if (defaultModel) {
|
|
||||||
apiKeyStatus = 'has valid access key';
|
|
||||||
return apiKeyStatus;
|
|
||||||
} else {
|
|
||||||
apiKeyStatus = 'Click "DevChat" status icon to set key';
|
|
||||||
return apiKeyStatus;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return apiKeyStatus;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const devchatPackageStatus = await getDevChatStatus();
|
const devchatPackageStatus = await getDevChatStatus();
|
||||||
const apiAccessKeyStatus = await getApiKeyStatus();
|
|
||||||
|
|
||||||
if (devchatPackageStatus !== preDevchatStatus) {
|
if (devchatPackageStatus !== preDevchatStatus) {
|
||||||
logger.channel()?.info(`devchat status: ${devchatPackageStatus}`);
|
logger.channel()?.info(`devchat status: ${devchatPackageStatus}`);
|
||||||
preDevchatStatus = devchatPackageStatus;
|
preDevchatStatus = devchatPackageStatus;
|
||||||
}
|
}
|
||||||
if (apiAccessKeyStatus !== preApiKeyStatus) {
|
|
||||||
logger.channel()?.info(`api key status: ${apiAccessKeyStatus}`);
|
|
||||||
preApiKeyStatus = apiAccessKeyStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [devchatPackageStatus, apiAccessKeyStatus];
|
return devchatPackageStatus;
|
||||||
}
|
}
|
@ -4,12 +4,13 @@ import * as fs from 'fs';
|
|||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
|
|
||||||
import { logger } from '../util/logger';
|
import { logger } from '../util/logger';
|
||||||
import { CommandRun, saveModelSettings } from "../util/commonUtil";
|
import { CommandRun } from "../util/commonUtil";
|
||||||
import { UiUtilWrapper } from '../util/uiUtil';
|
import { UiUtilWrapper } from '../util/uiUtil';
|
||||||
import { ApiKeyManager } from '../util/apiKey';
|
import { ApiKeyManager } from '../util/apiKey';
|
||||||
import { assertValue } from '../util/check';
|
import { assertValue } from '../util/check';
|
||||||
import { getFileContent } from '../util/commonUtil';
|
import { getFileContent } from '../util/commonUtil';
|
||||||
import * as toml from '@iarna/toml';
|
import * as toml from '@iarna/toml';
|
||||||
|
import { DevChatConfig } from '../util/config';
|
||||||
|
|
||||||
const readFileAsync = fs.promises.readFile;
|
const readFileAsync = fs.promises.readFile;
|
||||||
|
|
||||||
@ -122,7 +123,7 @@ class DevChat {
|
|||||||
assertValue(!llmModelData || !llmModelData.model, 'You must select a LLM model to use for conversations');
|
assertValue(!llmModelData || !llmModelData.model, 'You must select a LLM model to use for conversations');
|
||||||
args.push("-m", llmModelData.model);
|
args.push("-m", llmModelData.model);
|
||||||
|
|
||||||
const functionCalling = UiUtilWrapper.getConfiguration('DevChat', 'EnableFunctionCalling');
|
const functionCalling = new DevChatConfig().get('enable_function_calling');
|
||||||
if (functionCalling) {
|
if (functionCalling) {
|
||||||
args.push("-a");
|
args.push("-a");
|
||||||
}
|
}
|
||||||
@ -139,7 +140,7 @@ class DevChat {
|
|||||||
if (options.maxCount) {
|
if (options.maxCount) {
|
||||||
args.push('--max-count', `${options.maxCount}`);
|
args.push('--max-count', `${options.maxCount}`);
|
||||||
} else {
|
} else {
|
||||||
const maxLogCount = UiUtilWrapper.getConfiguration('DevChat', 'maxLogCount');
|
const maxLogCount = new DevChatConfig().get('max_log_count');
|
||||||
args.push('--max-count', `${maxLogCount}`);
|
args.push('--max-count', `${maxLogCount}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +211,7 @@ class DevChat {
|
|||||||
"PYTHONPATH": UiUtilWrapper.extensionPath() + "/tools/site-packages"
|
"PYTHONPATH": UiUtilWrapper.extensionPath() + "/tools/site-packages"
|
||||||
};
|
};
|
||||||
|
|
||||||
const pythonApp = UiUtilWrapper.getConfiguration("DevChat", "PythonForChat") || "python3";
|
const pythonApp = new DevChatConfig().get('python_for_chat') || "python3";
|
||||||
|
|
||||||
// run command
|
// run command
|
||||||
const { exitCode: code, stdout, stderr } = await this.commandRun.spawnAsync(
|
const { exitCode: code, stdout, stderr } = await this.commandRun.spawnAsync(
|
||||||
@ -250,7 +251,7 @@ class DevChat {
|
|||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
"PYTHONUTF8": 1,
|
"PYTHONUTF8": 1,
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
"command_python": UiUtilWrapper.getConfiguration('DevChat', 'PythonForCommands') || "",
|
"command_python": new DevChatConfig().get('python_for_commands') || "",
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
"PYTHONPATH": UiUtilWrapper.extensionPath() + "/tools/site-packages",
|
"PYTHONPATH": UiUtilWrapper.extensionPath() + "/tools/site-packages",
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
@ -266,9 +267,6 @@ class DevChat {
|
|||||||
env: envs
|
env: envs
|
||||||
};
|
};
|
||||||
|
|
||||||
// save llm model config
|
|
||||||
await saveModelSettings();
|
|
||||||
|
|
||||||
logger.channel()?.info(`api_key: ${llmModelData.api_key.replace(/^(.{4})(.*)(.{4})$/, (_, first, middle, last) => first + middle.replace(/./g, '*') + last)}`);
|
logger.channel()?.info(`api_key: ${llmModelData.api_key.replace(/^(.{4})(.*)(.{4})$/, (_, first, middle, last) => first + middle.replace(/./g, '*') + last)}`);
|
||||||
logger.channel()?.info(`api_base: ${llmModelData.api_base}`);
|
logger.channel()?.info(`api_base: ${llmModelData.api_base}`);
|
||||||
|
|
||||||
@ -281,7 +279,7 @@ class DevChat {
|
|||||||
onData(data);
|
onData(data);
|
||||||
};
|
};
|
||||||
// run command
|
// run command
|
||||||
const pythonApp = UiUtilWrapper.getConfiguration("DevChat", "PythonForChat") || "python3";
|
const pythonApp = new DevChatConfig().get('python_for_chat') || "python3";
|
||||||
logger.channel()?.info(`Running devchat:${pythonApp} ${args.join(" ")}`);
|
logger.channel()?.info(`Running devchat:${pythonApp} ${args.join(" ")}`);
|
||||||
const { exitCode: code, stdout, stderr } = await this.commandRun.spawnAsync(pythonApp, args, spawnAsyncOptions, onStdoutPartial, undefined, undefined, undefined);
|
const { exitCode: code, stdout, stderr } = await this.commandRun.spawnAsync(pythonApp, args, spawnAsyncOptions, onStdoutPartial, undefined, undefined, undefined);
|
||||||
// handle result
|
// handle result
|
||||||
|
@ -1,215 +1,48 @@
|
|||||||
// src/apiKey.ts
|
// src/apiKey.ts
|
||||||
|
|
||||||
|
import DevChat from '@/toolwrapper/devchat';
|
||||||
import { UiUtilWrapper } from './uiUtil';
|
import { UiUtilWrapper } from './uiUtil';
|
||||||
|
import { DevChatConfig } from './config';
|
||||||
|
import { logger } from './logger';
|
||||||
|
|
||||||
export class ApiKeyManager {
|
export class ApiKeyManager {
|
||||||
static toProviderKey(provider: string) : string | undefined {
|
|
||||||
let providerNameMap = {
|
|
||||||
"openai": "OpenAI",
|
|
||||||
"devchat": "DevChat"
|
|
||||||
};
|
|
||||||
return providerNameMap[provider];
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getValidModels(): Promise<string[]> {
|
|
||||||
const modelProperties = async (modelPropertyName: string, modelName: string) => {
|
|
||||||
const modelConfig = UiUtilWrapper.getConfiguration("devchat", modelPropertyName);
|
|
||||||
if (!modelConfig) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
let modelProperties: any = {};
|
|
||||||
for (const key of Object.keys(modelConfig || {})) {
|
|
||||||
const property = modelConfig![key];
|
|
||||||
modelProperties[key] = property;
|
|
||||||
}
|
|
||||||
if (!modelConfig["provider"]) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const apiKey = await this.getProviderApiKey(modelConfig["provider"]);
|
|
||||||
if (apiKey) {
|
|
||||||
modelProperties["api_key"] = apiKey;
|
|
||||||
} else {
|
|
||||||
const apiKeyDevChat = await this.getProviderApiKey("devchat");
|
|
||||||
if (apiKeyDevChat) {
|
|
||||||
modelProperties["api_key"] = apiKeyDevChat;
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
modelProperties['model'] = modelName;
|
|
||||||
return modelProperties;
|
|
||||||
};
|
|
||||||
|
|
||||||
let modelList : string[] = [];
|
|
||||||
const openaiModel = await modelProperties('Model.gpt-3-5', "gpt-3.5-turbo");
|
|
||||||
if (openaiModel) {
|
|
||||||
modelList.push(openaiModel.model);
|
|
||||||
}
|
|
||||||
const openaiModel3 = await modelProperties('Model.gpt-4', "gpt-4");
|
|
||||||
if (openaiModel3) {
|
|
||||||
modelList.push(openaiModel3.model);
|
|
||||||
}
|
|
||||||
const openaiModel4 = await modelProperties('Model.gpt-4-turbo', "gpt-4-turbo-preview");
|
|
||||||
if (openaiModel4) {
|
|
||||||
modelList.push(openaiModel4.model);
|
|
||||||
}
|
|
||||||
const claude3sonnetModel = await modelProperties('Model.claude-3-sonnet', "claude-3-sonnet");
|
|
||||||
if (claude3sonnetModel) {
|
|
||||||
modelList.push(claude3sonnetModel.model);
|
|
||||||
}
|
|
||||||
const claude3opusModel = await modelProperties('Model.claude-3-opus', "claude-3-opus");
|
|
||||||
if (claude3opusModel) {
|
|
||||||
modelList.push(claude3opusModel.model);
|
|
||||||
}
|
|
||||||
const xinghuoModel = await modelProperties('Model.xinghuo-2', "xinghuo-3.5");
|
|
||||||
if (xinghuoModel) {
|
|
||||||
modelList.push(xinghuoModel.model);
|
|
||||||
}
|
|
||||||
const glmModel = await modelProperties('Model.chatglm_pro', "GLM-4");
|
|
||||||
if (glmModel) {
|
|
||||||
modelList.push(glmModel.model);
|
|
||||||
}
|
|
||||||
const erniebotModel = await modelProperties('Model.ERNIE-Bot', "ERNIE-Bot-4.0");
|
|
||||||
if (erniebotModel) {
|
|
||||||
modelList.push(erniebotModel.model);
|
|
||||||
}
|
|
||||||
const llamaCode2Model = await modelProperties('Model.CodeLlama-70b', "togetherai/codellama/CodeLlama-70b-Instruct-hf");
|
|
||||||
if (llamaCode2Model) {
|
|
||||||
modelList.push(llamaCode2Model.model);
|
|
||||||
}
|
|
||||||
const mixtralCode2Model = await modelProperties('Model.Mixtral-8x7B', "togetherai/mistralai/Mixtral-8x7B-Instruct-v0.1");
|
|
||||||
if (mixtralCode2Model) {
|
|
||||||
modelList.push(mixtralCode2Model.model);
|
|
||||||
}
|
|
||||||
const minimaxCode2Model = await modelProperties('Model.Minimax-abab6', "minimax/abab6-chat");
|
|
||||||
if (minimaxCode2Model) {
|
|
||||||
modelList.push(minimaxCode2Model.model);
|
|
||||||
}
|
|
||||||
const llama70BModel = await modelProperties('Model.llama-2-70b-chat', "llama-2-70b-chat");
|
|
||||||
if (llama70BModel) {
|
|
||||||
modelList.push(llama70BModel.model);
|
|
||||||
}
|
|
||||||
|
|
||||||
return modelList;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async llmModel() {
|
static async llmModel() {
|
||||||
// inner function to update default model
|
const defaultModel = new DevChatConfig().get('default_model');
|
||||||
const updateDefaultModelWithValidModels = async () => {
|
if (!defaultModel) {
|
||||||
const validModels = await this.getValidModels();
|
return undefined;
|
||||||
if (validModels.length > 0) {
|
}
|
||||||
await UiUtilWrapper.updateConfiguration('devchat', 'defaultModel', validModels[0]);
|
|
||||||
return validModels[0];
|
// get model provider
|
||||||
|
const defaultModelProvider = new DevChatConfig().get(`models.${defaultModel}.provider`);
|
||||||
|
if (!defaultModelProvider) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get provider config
|
||||||
|
const defaultProvider = new DevChatConfig().get(`providers.${defaultModelProvider}`);
|
||||||
|
const devchatProvider = new DevChatConfig().get(`providers.devchat`);
|
||||||
|
|
||||||
|
let defaultModelConfig = new DevChatConfig().get(`models.${defaultModel}`);
|
||||||
|
defaultModelConfig["model"] = defaultModel;
|
||||||
|
if (defaultProvider) {
|
||||||
|
for (const key of Object.keys(defaultProvider || {})) {
|
||||||
|
const property = defaultProvider[key];
|
||||||
|
defaultModelConfig[key] = property;
|
||||||
|
}
|
||||||
|
return defaultModelConfig;
|
||||||
|
} else if (devchatProvider) {
|
||||||
|
for (const key of Object.keys(devchatProvider || {})) {
|
||||||
|
const property = devchatProvider[key];
|
||||||
|
defaultModelConfig[key] = property;
|
||||||
|
}
|
||||||
|
if (!defaultModelConfig["api_base"]) {
|
||||||
|
logger.channel()?.error("api_base is not set in devchat provider!!!");
|
||||||
|
logger.channel()?.show();
|
||||||
|
}
|
||||||
|
return defaultModelConfig;
|
||||||
} else {
|
} else {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// inner function to get model properties
|
|
||||||
const modelProperties = async (modelPropertyName: string, modelName: string) => {
|
|
||||||
const modelConfig = UiUtilWrapper.getConfiguration("devchat", modelPropertyName);
|
|
||||||
if (!modelConfig) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
let modelProperties: any = {};
|
|
||||||
for (const key of Object.keys(modelConfig || {})) {
|
|
||||||
const property = modelConfig![key];
|
|
||||||
modelProperties[key] = property;
|
|
||||||
}
|
|
||||||
if (!modelConfig["provider"]) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const apiKey = await this.getProviderApiKey(modelConfig["provider"]);
|
|
||||||
const apiBase = await this.getProviderApiBase(modelConfig["provider"]);
|
|
||||||
|
|
||||||
if (apiKey) {
|
|
||||||
modelProperties["api_key"] = apiKey;
|
|
||||||
} else {
|
|
||||||
const apiKeyDevChat = await this.getProviderApiKey("devchat");
|
|
||||||
if (apiKeyDevChat) {
|
|
||||||
modelProperties["api_key"] = apiKeyDevChat;
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apiBase) {
|
|
||||||
modelProperties["api_base"] = apiBase;
|
|
||||||
} else if (!apiKey) {
|
|
||||||
const devchatApiBase = await this.getProviderApiBase("devchat");
|
|
||||||
if (devchatApiBase) {
|
|
||||||
modelProperties["api_base"] = devchatApiBase;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!modelProperties["api_base"] && modelProperties["api_key"]?.startsWith("DC.")) {
|
|
||||||
modelProperties["api_base"] = "https://api.devchat.ai/v1";
|
|
||||||
}
|
|
||||||
|
|
||||||
modelProperties['model'] = modelName;
|
|
||||||
return modelProperties;
|
|
||||||
};
|
|
||||||
|
|
||||||
// inner function visit all models
|
|
||||||
const getModelPropertiesByName = async (modelName: string) => {
|
|
||||||
if (modelName === "gpt-3.5-turbo") {
|
|
||||||
return await modelProperties('Model.gpt-3-5', "gpt-3.5-turbo");
|
|
||||||
}
|
|
||||||
if (modelName === "gpt-4") {
|
|
||||||
return await modelProperties('Model.gpt-4', "gpt-4");
|
|
||||||
}
|
|
||||||
if (modelName === "gpt-4-turbo-preview") {
|
|
||||||
return await modelProperties('Model.gpt-4-turbo', "gpt-4-turbo-preview");
|
|
||||||
}
|
|
||||||
if (modelName === "claude-3-sonnet") {
|
|
||||||
return await modelProperties('Model.claude-3-sonnet', "claude-3-sonnet");
|
|
||||||
}
|
|
||||||
if (modelName === "claude-3-opus") {
|
|
||||||
return await modelProperties('Model.claude-3-opus', "claude-3-opus");
|
|
||||||
}
|
|
||||||
if (modelName === "xinghuo-3.5") {
|
|
||||||
return await modelProperties('Model.xinghuo-2', "xinghuo-3.5");
|
|
||||||
}
|
|
||||||
if (modelName === "GLM-4") {
|
|
||||||
return await modelProperties('Model.chatglm_pro', "GLM-4");
|
|
||||||
}
|
|
||||||
if (modelName === "ERNIE-Bot-4.0") {
|
|
||||||
return await modelProperties('Model.ERNIE-Bot', "ERNIE-Bot-4.0");
|
|
||||||
}
|
|
||||||
if (modelName === "togetherai/codellama/CodeLlama-70b-Instruct-hf") {
|
|
||||||
return await modelProperties('Model.CodeLlama-70b', "togetherai/codellama/CodeLlama-70b-Instruct-hf");
|
|
||||||
}
|
|
||||||
if (modelName === "togetherai/mistralai/Mixtral-8x7B-Instruct-v0.1") {
|
|
||||||
return await modelProperties('Model.Mixtral-8x7B', "togetherai/mistralai/Mixtral-8x7B-Instruct-v0.1");
|
|
||||||
}
|
|
||||||
if (modelName === "minimax/abab6-chat") {
|
|
||||||
return await modelProperties('Model.Minimax-abab6', "minimax/abab6-chat");
|
|
||||||
}
|
|
||||||
if (modelName === "llama-2-70b-chat") {
|
|
||||||
return await modelProperties('Model.llama-2-70b-chat', "llama-2-70b-chat");
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
let llmModelT: string | undefined = UiUtilWrapper.getConfiguration('devchat', 'defaultModel');
|
|
||||||
if (llmModelT) {
|
|
||||||
const defaultModel = await getModelPropertiesByName(llmModelT);
|
|
||||||
if (defaultModel) {
|
|
||||||
return defaultModel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset default model
|
|
||||||
llmModelT = await updateDefaultModelWithValidModels();
|
|
||||||
if (!llmModelT) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return getModelPropertiesByName(llmModelT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static getKeyType(apiKey: string): string | undefined {
|
static getKeyType(apiKey: string): string | undefined {
|
||||||
@ -221,43 +54,4 @@ export class ApiKeyManager {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async writeApiKeySecret(apiKey: string, llmType: string = "Unknow"): Promise<void> {
|
|
||||||
await UiUtilWrapper.storeSecret(`Access_KEY_${llmType}`, apiKey);
|
|
||||||
}
|
|
||||||
static async loadApiKeySecret(llmType: string = "Unknow"): Promise<string | undefined> {
|
|
||||||
return await UiUtilWrapper.secretStorageGet(`Access_KEY_${llmType}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get some provider's api key
|
|
||||||
static async getProviderApiKey(provider: string): Promise<string | undefined> {
|
|
||||||
// read key from configration first
|
|
||||||
const providerProperty = `Provider.${provider}`;
|
|
||||||
const providerConfig = UiUtilWrapper.getConfiguration("devchat", providerProperty);
|
|
||||||
if (providerConfig) {
|
|
||||||
if (providerConfig["access_key"]) {
|
|
||||||
return providerConfig["access_key"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const providerName = this.toProviderKey(provider);
|
|
||||||
if (!providerName) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return await this.loadApiKeySecret(providerName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get some provider's api base
|
|
||||||
static async getProviderApiBase(provider: string): Promise<string | undefined> {
|
|
||||||
// read key from configration first
|
|
||||||
const providerProperty = `Provider.${provider}`;
|
|
||||||
const providerConfig = UiUtilWrapper.getConfiguration("devchat", providerProperty);
|
|
||||||
if (providerConfig) {
|
|
||||||
if (providerConfig["api_base"]) {
|
|
||||||
return providerConfig["api_base"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -14,54 +14,6 @@ import { UiUtilWrapper } from './uiUtil';
|
|||||||
import { ApiKeyManager } from './apiKey';
|
import { ApiKeyManager } from './apiKey';
|
||||||
var kill = require('tree-kill');
|
var kill = require('tree-kill');
|
||||||
|
|
||||||
export async function saveModelSettings(): Promise<void> {
|
|
||||||
// support models
|
|
||||||
const supportModels = {
|
|
||||||
"Model.gpt-3-5": "gpt-3.5-turbo",
|
|
||||||
"Model.gpt-4": "gpt-4",
|
|
||||||
"Model.gpt-4-turbo": "gpt-4-turbo-preview",
|
|
||||||
"Model.claude-3-sonnet": "claude-3-sonnet",
|
|
||||||
"Model.claude-3-opus": "claude-3-opus",
|
|
||||||
"Model.xinghuo-2": "xinghuo-3.5",
|
|
||||||
"Model.chatglm_pro": "GLM-4",
|
|
||||||
"Model.ERNIE-Bot": "ERNIE-Bot-4.0",
|
|
||||||
"Model.CodeLlama-70b": "togetherai/codellama/CodeLlama-70b-Instruct-hf",
|
|
||||||
"Model.Mixtral-8x7B": "togetherai/mistralai/Mixtral-8x7B-Instruct-v0.1",
|
|
||||||
"Model.Minimax-abab6": "minimax/abab6-chat",
|
|
||||||
"Model.llama-2-70b-chat": "llama-2-70b-chat"
|
|
||||||
};
|
|
||||||
// is enable stream
|
|
||||||
const openaiStream = UiUtilWrapper.getConfiguration('DevChat', 'OpenAI.stream');
|
|
||||||
|
|
||||||
let devchatConfig = {};
|
|
||||||
for (const model of Object.keys(supportModels)) {
|
|
||||||
const modelConfig = UiUtilWrapper.getConfiguration('devchat', model);
|
|
||||||
if (modelConfig) {
|
|
||||||
devchatConfig[supportModels[model]] = {
|
|
||||||
"stream": openaiStream
|
|
||||||
};
|
|
||||||
for (const key of Object.keys(modelConfig || {})) {
|
|
||||||
const property = modelConfig![key];
|
|
||||||
devchatConfig[supportModels[model]][key] = property;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let devchatModels = {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
||||||
"default_model": "gpt-3.5-turbo",
|
|
||||||
"models": devchatConfig
|
|
||||||
};
|
|
||||||
|
|
||||||
// write to config file
|
|
||||||
const os = process.platform;
|
|
||||||
const userHome = os === 'win32' ? fs.realpathSync(process.env.USERPROFILE || '') : process.env.HOME;
|
|
||||||
|
|
||||||
const configPath = path.join(userHome!, '.chat', 'config.yml');
|
|
||||||
// write devchatConfig to configPath
|
|
||||||
const yamlString = yaml.stringify(devchatModels);
|
|
||||||
fs.writeFileSync(configPath, yamlString);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createOpenAiKeyEnv() {
|
async function createOpenAiKeyEnv() {
|
||||||
let envs = {...process.env};
|
let envs = {...process.env};
|
||||||
|
60
src/util/config.ts
Normal file
60
src/util/config.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import fs from 'fs';
|
||||||
|
import yaml from 'yaml';
|
||||||
|
import path from 'path';
|
||||||
|
import { logger } from './logger';
|
||||||
|
|
||||||
|
|
||||||
|
export class DevChatConfig {
|
||||||
|
private configFilePath: string;
|
||||||
|
private data: any;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
// 视操作系统的差异,可能需要调整路径 ~/.chat/config.yml
|
||||||
|
this.configFilePath = path.join(process.env.HOME || process.env.USERPROFILE || '', '.chat', 'config.yml');
|
||||||
|
this.readConfigFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
private readConfigFile() {
|
||||||
|
try {
|
||||||
|
const fileContents = fs.readFileSync(this.configFilePath, 'utf8');
|
||||||
|
this.data = yaml.parse(fileContents);
|
||||||
|
} catch (error) {
|
||||||
|
logger.channel()?.error(`Error reading the config file: ${error}`);
|
||||||
|
logger.channel()?.show();
|
||||||
|
this.data = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private writeConfigFile() {
|
||||||
|
try {
|
||||||
|
const yamlStr = yaml.stringify(this.data);
|
||||||
|
fs.writeFileSync(this.configFilePath, yamlStr, 'utf8');
|
||||||
|
} catch (error) {
|
||||||
|
logger.channel()?.error(`Error writing the config file: ${error}`);
|
||||||
|
logger.channel()?.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get(key: string): any {
|
||||||
|
return key.split('.').reduce((prev, curr) => prev ? prev[curr] : undefined, this.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public set(key: string, value: any): void {
|
||||||
|
let keys = key.split('.');
|
||||||
|
let lastKey = keys.pop();
|
||||||
|
let lastObj = keys.reduce((prev, k) => prev[k] = prev[k] || {}, this.data); // 这创建一个嵌套的对象结构,如果不存在的话
|
||||||
|
if (lastKey) {
|
||||||
|
lastObj[lastKey] = value; // 设置值
|
||||||
|
}
|
||||||
|
this.writeConfigFile(); // 更新配置文件
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAll(): any {
|
||||||
|
return this.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setAll(newData: any): void {
|
||||||
|
this.data = newData;
|
||||||
|
this.writeConfigFile(); // 更新配置文件
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
import { DevChatConfig } from '../config';
|
||||||
|
|
||||||
const featureTogglesJson = `
|
const featureTogglesJson = `
|
||||||
{
|
{
|
||||||
@ -13,7 +14,7 @@ const featureToggles = JSON.parse(featureTogglesJson);
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
export function FT(feature: string): boolean {
|
export function FT(feature: string): boolean {
|
||||||
const betaInvitationCode = vscode.workspace.getConfiguration('DevChat').get<string>('betaInvitationCode');
|
const betaInvitationCode = new DevChatConfig().get('beta_invitation_code');
|
||||||
const expectedInvitationCode = 'WELCOMEADDTODEVCHAT';
|
const expectedInvitationCode = 'WELCOMEADDTODEVCHAT';
|
||||||
|
|
||||||
return betaInvitationCode === expectedInvitationCode || featureToggles[feature] === true;
|
return betaInvitationCode === expectedInvitationCode || featureToggles[feature] === true;
|
||||||
|
@ -9,6 +9,7 @@ import * as os from 'os';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { UiUtilWrapper } from "../uiUtil";
|
import { UiUtilWrapper } from "../uiUtil";
|
||||||
|
import { DevChatConfig } from "../config";
|
||||||
import { getValidPythonCommand } from "../../contributes/commandsBase";
|
import { getValidPythonCommand } from "../../contributes/commandsBase";
|
||||||
|
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ export async function installDevchat(): Promise<string> {
|
|||||||
fs.writeFileSync(pythonPathFile, content);
|
fs.writeFileSync(pythonPathFile, content);
|
||||||
|
|
||||||
// update DevChat.PythonForChat configration
|
// update DevChat.PythonForChat configration
|
||||||
await UiUtilWrapper.updateConfiguration("DevChat", "PythonForChat", pythonApp);
|
await new DevChatConfig().set("python_for_chat", pythonApp);
|
||||||
return pythonApp;
|
return pythonApp;
|
||||||
} else {
|
} else {
|
||||||
// if current os is not windows, we need to get default python path
|
// if current os is not windows, we need to get default python path
|
||||||
@ -69,7 +70,7 @@ export async function installDevchat(): Promise<string> {
|
|||||||
}
|
}
|
||||||
logger.channel()?.info(`Create env success: ${pythonCommand}`);
|
logger.channel()?.info(`Create env success: ${pythonCommand}`);
|
||||||
|
|
||||||
await UiUtilWrapper.updateConfiguration("DevChat", "PythonForChat", pythonCommand);
|
await new DevChatConfig().set("python_for_chat", pythonCommand);
|
||||||
return pythonCommand;
|
return pythonCommand;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
export interface UiUtil {
|
export interface UiUtil {
|
||||||
languageId(uri: string): Promise<string>;
|
languageId(uri: string): Promise<string>;
|
||||||
workspaceFoldersFirstPath(): string | undefined;
|
workspaceFoldersFirstPath(): string | undefined;
|
||||||
getConfiguration(key1: string, key2: string): string | undefined;
|
|
||||||
updateConfiguration(key1: string, key2: string, value: string): Promise<void>;
|
|
||||||
secretStorageGet(key: string): Promise<string | undefined>;
|
secretStorageGet(key: string): Promise<string | undefined>;
|
||||||
writeFile(uri: string, content: string): Promise<void>;
|
writeFile(uri: string, content: string): Promise<void>;
|
||||||
showInputBox(option: object): Promise<string | undefined>;
|
showInputBox(option: object): Promise<string | undefined>;
|
||||||
@ -33,12 +31,6 @@ export class UiUtilWrapper {
|
|||||||
public static workspaceFoldersFirstPath(): string | undefined {
|
public static workspaceFoldersFirstPath(): string | undefined {
|
||||||
return this._uiUtil?.workspaceFoldersFirstPath();
|
return this._uiUtil?.workspaceFoldersFirstPath();
|
||||||
}
|
}
|
||||||
public static getConfiguration(key1: string, key2: string): string | undefined {
|
|
||||||
return this._uiUtil?.getConfiguration(key1, key2);
|
|
||||||
}
|
|
||||||
public static async updateConfiguration(key1: string, key2: string, value: string): Promise<void> {
|
|
||||||
return await this._uiUtil?.updateConfiguration(key1, key2, value);
|
|
||||||
}
|
|
||||||
public static async secretStorageGet(key: string): Promise<string | undefined> {
|
public static async secretStorageGet(key: string): Promise<string | undefined> {
|
||||||
return await this._uiUtil?.secretStorageGet(key);
|
return await this._uiUtil?.secretStorageGet(key);
|
||||||
}
|
}
|
||||||
|
@ -14,19 +14,6 @@ export class UiUtilVscode implements UiUtil {
|
|||||||
return vscode.workspace.workspaceFolders?.[0].uri.fsPath;
|
return vscode.workspace.workspaceFolders?.[0].uri.fsPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getConfiguration(key1: string, key2: string): string | undefined {
|
|
||||||
return vscode.workspace.getConfiguration(key1).get(key2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async updateConfiguration(key1: string, key2: string, value: string): Promise<void> {
|
|
||||||
try {
|
|
||||||
await vscode.workspace.getConfiguration(key1).update(key2, value, vscode.ConfigurationTarget.Global);
|
|
||||||
await vscode.workspace.getConfiguration(key1).update(key2, value, vscode.ConfigurationTarget.Workspace);
|
|
||||||
} catch(error) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
public async secretStorageGet(key: string): Promise<string | undefined> {
|
public async secretStorageGet(key: string): Promise<string | undefined> {
|
||||||
try {
|
try {
|
||||||
const secretStorage: vscode.SecretStorage = ExtensionContextHolder.context!.secrets;
|
const secretStorage: vscode.SecretStorage = ExtensionContextHolder.context!.secrets;
|
||||||
|
@ -1,153 +0,0 @@
|
|||||||
import { expect } from 'chai';
|
|
||||||
import 'mocha';
|
|
||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import { CustomActions } from '../../src/action/customAction';
|
|
||||||
|
|
||||||
describe('CustomActions', () => {
|
|
||||||
const customActions = CustomActions.getInstance();
|
|
||||||
|
|
||||||
it('should return an empty action list', () => {
|
|
||||||
const actions = customActions.getActions();
|
|
||||||
expect(actions).to.deep.equal([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return a non-empty action instruction with actions', () => {
|
|
||||||
// Add a sample action to the customActions instance
|
|
||||||
customActions.getActions().push({
|
|
||||||
name: 'sampleAction',
|
|
||||||
description: 'A sample action for testing',
|
|
||||||
type: ['test'],
|
|
||||||
action: 'sample',
|
|
||||||
handler: [],
|
|
||||||
args: [],
|
|
||||||
handlerAction: async (args: { [key: string]: string }) => {
|
|
||||||
return { exitCode: 0, stdout: '', stderr: '' };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const instruction = customActions.actionInstruction();
|
|
||||||
expect(instruction).to.include('sampleAction: A sample action for testing');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return action instruction with args', () => {
|
|
||||||
// Add a sample action with args to the customActions instance
|
|
||||||
customActions.getActions().push({
|
|
||||||
name: 'sampleActionWithArgs',
|
|
||||||
description: 'A sample action with args for testing',
|
|
||||||
type: ['test'],
|
|
||||||
action: 'sample',
|
|
||||||
handler: [],
|
|
||||||
args: [
|
|
||||||
{
|
|
||||||
"name": "arg1",
|
|
||||||
"description": "Argument 1",
|
|
||||||
"type": "string",
|
|
||||||
"from": "content.fileName"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "arg2",
|
|
||||||
"description": "Argument 2",
|
|
||||||
"type": "number",
|
|
||||||
"from": "content.content"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
handlerAction: async (args: { [key: string]: string }) => {
|
|
||||||
return { exitCode: 0, stdout: '', stderr: '' };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const instruction = customActions.actionInstruction();
|
|
||||||
expect(instruction).to.include('sampleActionWithArgs: A sample action with args for testing');
|
|
||||||
expect(instruction).to.include('Args:');
|
|
||||||
expect(instruction).to.include('name: arg1 type: (string) description: Argument 1');
|
|
||||||
expect(instruction).to.include('name: arg2 type: (number) description: Argument 2');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse actions from workflows directory', () => {
|
|
||||||
// Create a temporary workflows directory with a sample action
|
|
||||||
const workflowsDir = path.join(__dirname, 'temp_workflows');
|
|
||||||
fs.mkdirSync(workflowsDir);
|
|
||||||
fs.mkdirSync(path.join(workflowsDir, 'sample_extension'));
|
|
||||||
fs.mkdirSync(path.join(workflowsDir, 'sample_extension', 'action'));
|
|
||||||
fs.mkdirSync(path.join(workflowsDir, 'sample_extension', 'action', 'sample_action'));
|
|
||||||
const settingsPath = path.join(workflowsDir, 'sample_extension', 'action', 'sample_action', '_setting_.json');
|
|
||||||
const sampleActionSettings = {
|
|
||||||
name: 'sampleParsedAction',
|
|
||||||
description: 'A sample parsed action for testing',
|
|
||||||
type: ['test'],
|
|
||||||
action: 'sample',
|
|
||||||
handler: [],
|
|
||||||
args: [],
|
|
||||||
};
|
|
||||||
fs.writeFileSync(settingsPath, JSON.stringify(sampleActionSettings));
|
|
||||||
|
|
||||||
// Call parseActions with the temporary workflows directory
|
|
||||||
customActions.parseActions(workflowsDir);
|
|
||||||
|
|
||||||
// Check if the parsed action is in the actions list
|
|
||||||
const actions = customActions.getActions();
|
|
||||||
const parsedAction = actions.find(action => action.name === 'sampleParsedAction');
|
|
||||||
expect(parsedAction).to.not.be.undefined;
|
|
||||||
expect(parsedAction?.description).to.equal('A sample parsed action for testing');
|
|
||||||
|
|
||||||
// Clean up the temporary workflows directory
|
|
||||||
fs.unlinkSync(settingsPath);
|
|
||||||
fs.rmdirSync(path.join(workflowsDir, 'sample_extension', 'action', 'sample_action'));
|
|
||||||
fs.rmdirSync(path.join(workflowsDir, 'sample_extension', 'action'));
|
|
||||||
fs.rmdirSync(path.join(workflowsDir, 'sample_extension'));
|
|
||||||
fs.rmdirSync(workflowsDir);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should parse handlerAction correctly from directory with echo command', async () => {
|
|
||||||
// Create a temporary directory for the sample action
|
|
||||||
const workflowsDir = path.join(__dirname, 'temp_workflows');
|
|
||||||
fs.mkdirSync(workflowsDir);
|
|
||||||
fs.mkdirSync(path.join(workflowsDir, 'sample_extension'));
|
|
||||||
fs.mkdirSync(path.join(workflowsDir, 'sample_extension', 'action'));
|
|
||||||
fs.mkdirSync(path.join(workflowsDir, 'sample_extension', 'action', 'sample_action'));
|
|
||||||
const settingsPath = path.join(workflowsDir, 'sample_extension', 'action', 'sample_action', '_setting_.json');
|
|
||||||
const sampleActionJson = {
|
|
||||||
name: 'sampleAction',
|
|
||||||
description: 'A sample action with a handlerAction method for testing',
|
|
||||||
type: ['test'],
|
|
||||||
action: 'sample',
|
|
||||||
handler: ["echo", "${arg1}"],
|
|
||||||
args: [
|
|
||||||
{ name: 'arg1', type: 'string' },
|
|
||||||
{ name: 'arg2', type: 'string' },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
fs.writeFileSync(settingsPath, JSON.stringify(sampleActionJson));
|
|
||||||
|
|
||||||
|
|
||||||
// Call parseActions with the temporary directory
|
|
||||||
customActions.parseActions(workflowsDir);
|
|
||||||
const actions = customActions.getActions();
|
|
||||||
|
|
||||||
// Clean up the temporary directory
|
|
||||||
fs.unlinkSync(settingsPath);
|
|
||||||
fs.rmdirSync(path.join(workflowsDir, 'sample_extension', 'action', 'sample_action'));
|
|
||||||
fs.rmdirSync(path.join(workflowsDir, 'sample_extension', 'action'));
|
|
||||||
fs.rmdirSync(path.join(workflowsDir, 'sample_extension'));
|
|
||||||
fs.rmdirSync(workflowsDir);
|
|
||||||
|
|
||||||
// Check if the returned actions array has the expected length
|
|
||||||
expect(actions.length).equal(1);
|
|
||||||
|
|
||||||
// Get the parsed action object
|
|
||||||
const parsedAction = actions[0];
|
|
||||||
|
|
||||||
// Call the handlerAction method with valid args
|
|
||||||
const validResult = await parsedAction.handlerAction({ arg1: 'value1', arg2: 'value2' });
|
|
||||||
|
|
||||||
// Check if the returned CommandResult is as expected
|
|
||||||
expect(validResult).to.deep.equal({ exitCode: 0, stdout: 'value1\n', stderr: '' });
|
|
||||||
|
|
||||||
// Call the handlerAction method with invalid args
|
|
||||||
const invalidResult = await parsedAction.handlerAction({ arg1: 'wrongValue', arg2: 'value2' });
|
|
||||||
|
|
||||||
// Check if the returned CommandResult is as expected
|
|
||||||
expect(invalidResult).to.deep.equal({ exitCode: 0, stdout: 'wrongValue\n', stderr: '' });
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,31 +0,0 @@
|
|||||||
// test/apiKey.test.ts
|
|
||||||
|
|
||||||
import { expect } from 'chai';
|
|
||||||
import { ApiKeyManager } from '../../src/util/apiKey';
|
|
||||||
import { UiUtilWrapper } from '../../src/util/uiUtil';
|
|
||||||
import sinon from 'sinon';
|
|
||||||
|
|
||||||
describe('ApiKeyManager', () => {
|
|
||||||
afterEach(() => {
|
|
||||||
sinon.restore();
|
|
||||||
delete process.env.OPENAI_API_KEY;
|
|
||||||
delete process.env.OPENAI_API_BASE;
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getKeyType', () => {
|
|
||||||
it('should return "sk" for sk keys', () => {
|
|
||||||
const keyType = ApiKeyManager.getKeyType('sk-key');
|
|
||||||
expect(keyType).to.equal('sk');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return "DC" for DC keys', () => {
|
|
||||||
const keyType = ApiKeyManager.getKeyType('DC.key');
|
|
||||||
expect(keyType).to.equal('DC');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return undefined for invalid keys', () => {
|
|
||||||
const keyType = ApiKeyManager.getKeyType('invalid.key');
|
|
||||||
expect(keyType).to.be.undefined;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
69
test/util/config.test.ts
Normal file
69
test/util/config.test.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { expect } from 'chai';
|
||||||
|
import { describe, it, beforeEach, afterEach } from 'mocha';
|
||||||
|
import fs from 'fs';
|
||||||
|
import yaml from 'yaml';
|
||||||
|
import { DevChatConfig } from '../../src/util/config'; // 调整路径以指向config.ts的实际位置
|
||||||
|
import sinon from 'sinon';
|
||||||
|
import { logger } from '../../src/util/logger'; // 调整路径以指向logger的实际位置
|
||||||
|
|
||||||
|
describe('DevChatConfig', () => {
|
||||||
|
let readFileStub: sinon.SinonStub;
|
||||||
|
let writeFileStub: sinon.SinonStub;
|
||||||
|
let loggerStub: sinon.SinonStub;
|
||||||
|
|
||||||
|
const mockData = {
|
||||||
|
username: 'DevUser',
|
||||||
|
theme: 'dark',
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// Mock fs.readFileSync to return a YAML string based on mockData
|
||||||
|
readFileStub = sinon.stub(fs, 'readFileSync').returns(yaml.stringify(mockData));
|
||||||
|
|
||||||
|
// Mock fs.writeFileSync to fake the writing process
|
||||||
|
writeFileStub = sinon.stub(fs, 'writeFileSync');
|
||||||
|
|
||||||
|
// Mock the logger to prevent logging during tests
|
||||||
|
loggerStub = sinon.stub(logger, 'channel').callsFake(() => ({
|
||||||
|
info: sinon.fake(),
|
||||||
|
warn: sinon.fake(),
|
||||||
|
error: sinon.fake(),
|
||||||
|
debug: sinon.fake(),
|
||||||
|
show: sinon.fake(),
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
// Restore the original functionalities
|
||||||
|
readFileStub.restore();
|
||||||
|
writeFileStub.restore();
|
||||||
|
loggerStub.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should read config file and get the correct value for a given key', () => {
|
||||||
|
const config = new DevChatConfig();
|
||||||
|
expect(config.get('username')).to.equal('DevUser');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set a new key-value pair and write to the config file', () => {
|
||||||
|
const config = new DevChatConfig();
|
||||||
|
const newKey = 'notifications.enabled';
|
||||||
|
const newValue = true;
|
||||||
|
|
||||||
|
config.set(newKey, newValue);
|
||||||
|
|
||||||
|
expect(config.get('notifications.enabled')).to.equal(true);
|
||||||
|
// Check if fs.writeFileSync was called
|
||||||
|
sinon.assert.calledOnce(writeFileStub);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle errors when reading an invalid config file', () => {
|
||||||
|
readFileStub.throws(new Error('Failed to read file'));
|
||||||
|
|
||||||
|
// Constructing the config will attempt to read the file and log an error
|
||||||
|
const config = new DevChatConfig();
|
||||||
|
|
||||||
|
// Check if the error was logged
|
||||||
|
sinon.assert.called(loggerStub);
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user