Compare commits
11 Commits
e20bbf2b42
...
535ab54128
Author | SHA1 | Date | |
---|---|---|---|
535ab54128 | |||
19872c25b3 | |||
8f6d431ef1 | |||
942755b3e6 | |||
2db3ab8888 | |||
de7d118d7b | |||
eafc15bba6 | |||
d85880ea7a | |||
1f55126c82 | |||
a622fdd1e2 | |||
295c45fa00 |
1
.vscode/openmcp_connection.json
vendored
Normal file
1
.vscode/openmcp_connection.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"items":[]}
|
383
.vscode/tabs.example-servers_puppeteer.json
vendored
Normal file
383
.vscode/tabs.example-servers_puppeteer.json
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -151,7 +151,7 @@ B <--mcp--> m(MCP Server)
|
||||
./dev.ps1
|
||||
```
|
||||
|
||||
> 端口占用: 8080 (renderer) + 8081 (service)
|
||||
> 端口占用: 8282 (renderer) + 8081 (service)
|
||||
|
||||
### Extention Dev
|
||||
|
||||
|
407
package-lock.json
generated
407
package-lock.json
generated
@ -24,6 +24,7 @@
|
||||
"@types/showdown": "^2.0.0",
|
||||
"@types/vscode": "^1.72.0",
|
||||
"copy-webpack-plugin": "^13.0.0",
|
||||
"fork-ts-checker-webpack-plugin": "^9.1.0",
|
||||
"null-loader": "^4.0.1",
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.4.2",
|
||||
@ -34,6 +35,31 @@
|
||||
"vscode": "^1.95.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
|
||||
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.27.1",
|
||||
"js-tokens": "^4.0.0",
|
||||
"picocolors": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
|
||||
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@discoveryjs/json-ext": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
|
||||
@ -539,6 +565,13 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
@ -571,6 +604,13 @@
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/big.js": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
|
||||
@ -607,6 +647,17 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz",
|
||||
@ -722,6 +773,16 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001713",
|
||||
"resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001713.tgz",
|
||||
@ -758,6 +819,22 @@
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
||||
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"readdirp": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.16.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/chrome-trace-event": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
|
||||
@ -823,6 +900,13 @@
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
|
||||
@ -899,6 +983,33 @@
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/cosmiconfig": {
|
||||
"version": "8.3.6",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
|
||||
"integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"import-fresh": "^3.3.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"parse-json": "^5.2.0",
|
||||
"path-type": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/d-fischer"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=4.9.5"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
@ -930,6 +1041,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/deepmerge": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/define-data-property": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||
@ -1046,6 +1167,16 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
@ -1405,6 +1536,87 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/fork-ts-checker-webpack-plugin": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.1.0.tgz",
|
||||
"integrity": "sha512-mpafl89VFPJmhnJ1ssH+8wmM2b50n+Rew5x42NeI2U78aRWgtkEtGmctp7iT16UjquJTjorEmIfESj3DxdW84Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.16.7",
|
||||
"chalk": "^4.1.2",
|
||||
"chokidar": "^4.0.1",
|
||||
"cosmiconfig": "^8.2.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"fs-extra": "^10.0.0",
|
||||
"memfs": "^3.4.1",
|
||||
"minimatch": "^3.0.4",
|
||||
"node-abort-controller": "^3.0.1",
|
||||
"schema-utils": "^3.1.1",
|
||||
"semver": "^7.3.5",
|
||||
"tapable": "^2.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.21.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">3.6.0",
|
||||
"webpack": "^5.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"ajv": "^6.9.1"
|
||||
}
|
||||
},
|
||||
"node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
|
||||
"integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.8",
|
||||
"ajv": "^6.12.5",
|
||||
"ajv-keywords": "^3.5.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
||||
@ -1457,6 +1669,28 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-monkey": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz",
|
||||
"integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==",
|
||||
"dev": true,
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
@ -1649,6 +1883,33 @@
|
||||
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/import-fresh": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
||||
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"parent-module": "^1.0.0",
|
||||
"resolve-from": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/import-fresh/node_modules/resolve-from": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/import-local": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/import-local/-/import-local-3.2.0.tgz",
|
||||
@ -1708,6 +1969,13 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-arrayish": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
||||
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-callable": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
|
||||
@ -1886,6 +2154,26 @@
|
||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/json-parse-even-better-errors": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
|
||||
@ -1911,6 +2199,19 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/kind-of": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz",
|
||||
@ -1929,6 +2230,13 @@
|
||||
"immediate": "~3.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/lines-and-columns": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/loader-runner": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz",
|
||||
@ -1992,6 +2300,19 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/memfs": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz",
|
||||
"integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==",
|
||||
"dev": true,
|
||||
"license": "Unlicense",
|
||||
"dependencies": {
|
||||
"fs-monkey": "^1.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/merge-descriptors": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
|
||||
@ -2044,6 +2365,19 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
@ -2065,6 +2399,13 @@
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/node-abort-controller": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz",
|
||||
"integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-domexception": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||
@ -2326,6 +2667,38 @@
|
||||
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
|
||||
"license": "(MIT AND Zlib)"
|
||||
},
|
||||
"node_modules/parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"callsites": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-json": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
|
||||
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"error-ex": "^1.3.1",
|
||||
"json-parse-even-better-errors": "^2.3.0",
|
||||
"lines-and-columns": "^1.1.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
@ -2368,6 +2741,16 @@
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/path-type": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
|
||||
@ -2493,6 +2876,20 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14.18.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/rechoir": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmmirror.com/rechoir/-/rechoir-0.8.0.tgz",
|
||||
@ -3138,6 +3535,16 @@
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
|
@ -239,6 +239,7 @@
|
||||
"@types/showdown": "^2.0.0",
|
||||
"@types/vscode": "^1.72.0",
|
||||
"copy-webpack-plugin": "^13.0.0",
|
||||
"fork-ts-checker-webpack-plugin": "^9.1.0",
|
||||
"null-loader": "^4.0.1",
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.4.2",
|
||||
|
@ -1,4 +0,0 @@
|
||||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
||||
not ie 11
|
0
renderer/.env.development
Normal file
0
renderer/.env.development
Normal file
0
renderer/.env.production
Normal file
0
renderer/.env.production
Normal file
@ -1,19 +0,0 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
extends: [
|
||||
"plugin:vue/vue3-essential",
|
||||
"eslint:recommended",
|
||||
"@vue/typescript/recommended"
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
},
|
||||
rules: {
|
||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
'vue/multi-word-component-names': 'off'
|
||||
},
|
||||
};
|
30
renderer/.gitignore
vendored
30
renderer/.gitignore
vendored
@ -1,23 +1,31 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
*.tsbuildinfo
|
||||
update.sh
|
@ -1,24 +1,33 @@
|
||||
# app
|
||||
# test-vite
|
||||
|
||||
## Project setup
|
||||
```
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
||||
|
||||
## Type Support for `.vue` Imports in TS
|
||||
|
||||
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
|
||||
|
||||
## Customize configuration
|
||||
|
||||
See [Vite Configuration Reference](https://vite.dev/config/).
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
### Type-Check, Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||
|
@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
presets: ["@vue/cli-plugin-babel/preset"],
|
||||
};
|
1
renderer/env.d.ts
vendored
Normal file
1
renderer/env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
18
renderer/index.html
Normal file
18
renderer/index.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.png">
|
||||
<link rel="stylesheet" href="/default-dark.css">
|
||||
<link rel="stylesheet" href="/vscode.css">
|
||||
<link rel="stylesheet" href="/mcp.css">
|
||||
<link rel="stylesheet" href="/iconfont.css">
|
||||
<link rel="stylesheet" href="/animation.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Vite App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
13659
renderer/package-lock.json
generated
13659
renderer/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,16 @@
|
||||
{
|
||||
"name": "renderer",
|
||||
"version": "0.1.0",
|
||||
"name": "test-vite",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
"serve": "vite",
|
||||
"serve:website": "vite --mode website",
|
||||
"build": "run-p type-check \"build-only {@}\" --",
|
||||
"build:website": "vite build --mode website",
|
||||
"preview": "vite preview",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --build"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.8.3",
|
||||
@ -15,29 +20,22 @@
|
||||
"markdown-it": "^14.1.0",
|
||||
"markdown-it-katex": "^2.0.3",
|
||||
"openai": "^4.93.0",
|
||||
"prismjs": "^1.30.0",
|
||||
"uuid": "^11.1.0",
|
||||
"vue": "^3.2.13",
|
||||
"vue": "^3.5.13",
|
||||
"vue-i18n": "^11.1.0",
|
||||
"vue-router": "^4.0.3"
|
||||
"vue-router": "^4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/markdown-it": "^14.1.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||
"@typescript-eslint/parser": "^5.4.0",
|
||||
"@vue/cli-plugin-babel": "~5.0.0",
|
||||
"@vue/cli-plugin-eslint": "~5.0.0",
|
||||
"@vue/cli-plugin-router": "~5.0.0",
|
||||
"@vue/cli-plugin-typescript": "~5.0.0",
|
||||
"@vue/cli-service": "~5.0.0",
|
||||
"@vue/eslint-config-typescript": "^9.1.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-vue": "^8.0.3",
|
||||
"prettier": "^2.4.1",
|
||||
"typescript": "^4.4.3",
|
||||
"unplugin-auto-import": "^0.17.5",
|
||||
"unplugin-vue-components": "^0.26.0"
|
||||
"@tsconfig/node22": "^22.0.1",
|
||||
"@types/node": "^22.14.0",
|
||||
"@types/prismjs": "^1.26.5",
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"@vue/tsconfig": "^0.7.0",
|
||||
"npm-run-all2": "^7.0.2",
|
||||
"typescript": "~5.8.0",
|
||||
"vite": "^6.2.4",
|
||||
"vite-plugin-vue-devtools": "^7.7.2",
|
||||
"vue-tsc": "^2.2.8"
|
||||
}
|
||||
}
|
||||
|
BIN
renderer/public/favicon.png
Normal file
BIN
renderer/public/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="0 0 824 834" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<path id="path_1" d="M300 0C465.708 0 600 134.292 600 300L600 300C600 465.708 465.708 600 300 600L300 600C134.292 600 0 465.708 0 300L0 300C0 134.292 134.292 0 300 0Z" />
|
||||
<linearGradient id="gradient_2" gradientUnits="userSpaceOnUse" x1="300" y1="0" x2="300" y2="600">
|
||||
<stop offset="0" stop-color="#A1A7F6" />
|
||||
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0.2" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g>
|
||||
<g transform="translate(186 116)">
|
||||
<use p4:href="#path_1" fill="#5A00FF" xmlns:p4="http://www.w3.org/1999/xlink" />
|
||||
<use p4:href="#path_1" fill="url(#gradient_2)" xmlns:p4="http://www.w3.org/1999/xlink" />
|
||||
</g>
|
||||
<path d="M0 110.5C0 49.4725 49.4725 0 110.5 0C171.527 0 221 49.4725 221 110.5C221 171.527 171.527 221 110.5 221C49.4725 221 0 171.527 0 110.5Z" fill="#FFFFFF" fill-rule="evenodd" fill-opacity="0.431" transform="translate(445 458)" />
|
||||
<path d="M0 55.5C0 24.8482 24.8482 0 55.5 0C86.1518 0 111 24.8482 111 55.5C111 86.1518 86.1518 111 55.5 111C24.8482 111 0 86.1518 0 55.5Z" fill="#FFFFFF" fill-rule="evenodd" fill-opacity="0.431" transform="translate(199 386)" />
|
||||
<path d="M0 182.5C0 81.708 81.708 0 182.5 0C283.292 0 365 81.708 365 182.5C365 283.292 283.292 365 182.5 365C81.708 365 0 283.292 0 182.5Z" fill="#FFFFFF" fill-rule="evenodd" fill-opacity="0.424" transform="translate(339 156)" />
|
||||
<path d="M0 57C0 25.5198 25.5198 0 57 0C88.4802 0 114 25.5198 114 57C114 88.4802 88.4802 114 57 114C25.5198 114 0 88.4802 0 57Z" fill="#FFFFFF" fill-rule="evenodd" fill-opacity="0.431" transform="translate(521 188)" />
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.7 KiB |
@ -1,22 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.svg">
|
||||
<link rel="stylesheet" href="default-dark.css">
|
||||
<link rel="stylesheet" href="vscode.css">
|
||||
<link rel="stylesheet" href="mcp.css">
|
||||
<link rel="stylesheet" href="iconfont.css">
|
||||
<link rel="stylesheet" href="animation.css">
|
||||
<title>OpenMCP Client</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -4,6 +4,7 @@
|
||||
<MainPanel></MainPanel>
|
||||
|
||||
<Tour v-if="!userHasReadGuide"/>
|
||||
<PasswordDialog v-if="password"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -17,14 +18,13 @@ import MainPanel from '@/components/main-panel/index.vue';
|
||||
import { setDefaultCss } from './hook/css';
|
||||
import { greenLog, pinkLog } from './views/setting/util';
|
||||
import { useMessageBridge } from './api/message-bridge';
|
||||
import { doConnect, loadEnvVar } from './views/connect/connection';
|
||||
import { getTour, loadSetting } from './hook/setting';
|
||||
import { loadPanels } from './hook/panel';
|
||||
import { initialise } from './views/connect/connection';
|
||||
import { getPlatform } from './api/platform';
|
||||
import Tour from '@/components/guide/tour.vue';
|
||||
import { userHasReadGuide } from './components/guide/tour';
|
||||
|
||||
import { ElLoading } from 'element-plus';
|
||||
import PasswordDialog from '@/components/password-dialog/index.vue';
|
||||
import { privilegeStatus } from './components/password-dialog/status';
|
||||
|
||||
const bridge = useMessageBridge();
|
||||
|
||||
@ -37,23 +37,14 @@ bridge.addCommandListener('hello', data => {
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
onMounted(async () => {
|
||||
const loading = ElLoading.service({
|
||||
fullscreen: true,
|
||||
lock: true,
|
||||
text: 'Loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
});
|
||||
const password = Boolean(import.meta.env.VITE_USE_PASSWORD);
|
||||
privilegeStatus.allow = !Boolean(password);
|
||||
|
||||
onMounted(async () => {
|
||||
// 初始化 css
|
||||
setDefaultCss();
|
||||
|
||||
document.addEventListener('click', () => {
|
||||
Connection.showPanel = false;
|
||||
});
|
||||
|
||||
pinkLog('OpenMCP Client 启动');
|
||||
|
||||
const platform = getPlatform();
|
||||
|
||||
// 跳转到首页
|
||||
@ -65,29 +56,18 @@ onMounted(async () => {
|
||||
}
|
||||
|
||||
// 进行桥接
|
||||
await bridge.awaitForWebsockt();
|
||||
await bridge.awaitForWebsocket();
|
||||
|
||||
pinkLog('准备请求设置');
|
||||
// 根据是否需要密码进行后续的选择
|
||||
if (!privilegeStatus.allow) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 加载全局设置
|
||||
loadSetting();
|
||||
|
||||
// 设置环境变量
|
||||
loadEnvVar();
|
||||
|
||||
// 获取引导状态
|
||||
getTour();
|
||||
|
||||
// 尝试进行初始化连接
|
||||
await doConnect({
|
||||
namespace: platform,
|
||||
updateCommandString: true
|
||||
document.addEventListener('click', () => {
|
||||
Connection.showPanel = false;
|
||||
});
|
||||
|
||||
// loading panels
|
||||
await loadPanels();
|
||||
|
||||
loading.close();
|
||||
await initialise();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
0
renderer/src/api/api.ts
Normal file
0
renderer/src/api/api.ts
Normal file
@ -1,10 +1,12 @@
|
||||
import { pinkLog, redLog } from '@/views/setting/util';
|
||||
import { acquireVsCodeApi, electronApi, getPlatform } from './platform';
|
||||
import { privilegeStatus } from '@/components/password-dialog/status';
|
||||
|
||||
export interface VSCodeMessage {
|
||||
command: string;
|
||||
data?: unknown;
|
||||
callbackId?: string;
|
||||
password?: string;
|
||||
}
|
||||
|
||||
export interface RestFulResponse {
|
||||
@ -24,11 +26,9 @@ export class MessageBridge {
|
||||
private handlers = new Map<string, Set<CommandHandler>>();
|
||||
private isConnected: Promise<boolean> | null = null;
|
||||
|
||||
constructor(private wsUrl: string = 'ws://localhost:8080') {
|
||||
|
||||
// 环境检测优先级:
|
||||
// 1. VS Code WebView 环境
|
||||
// 2. 浏览器 WebSocket 环境
|
||||
constructor(
|
||||
private setupSignature: any
|
||||
) {
|
||||
|
||||
const platform = getPlatform();
|
||||
|
||||
@ -68,7 +68,14 @@ export class MessageBridge {
|
||||
|
||||
// WebSocket 环境连接
|
||||
private setupWebSocket() {
|
||||
this.ws = new WebSocket(this.wsUrl);
|
||||
|
||||
const wsUrl = this.setupSignature;
|
||||
|
||||
if (typeof wsUrl !== 'string') {
|
||||
throw new Error('setupSignature must be a string');
|
||||
}
|
||||
|
||||
this.ws = new WebSocket(wsUrl);
|
||||
|
||||
this.ws.onmessage = (event) => {
|
||||
try {
|
||||
@ -87,6 +94,7 @@ export class MessageBridge {
|
||||
this.postMessage = (message) => {
|
||||
if (this.ws?.readyState === WebSocket.OPEN) {
|
||||
console.log('send', message);
|
||||
message.password = privilegeStatus.password;
|
||||
this.ws.send(JSON.stringify(message));
|
||||
}
|
||||
};
|
||||
@ -100,7 +108,7 @@ export class MessageBridge {
|
||||
});
|
||||
}
|
||||
|
||||
public async awaitForWebsockt() {
|
||||
public async awaitForWebsocket() {
|
||||
if (this.isConnected) {
|
||||
await this.isConnected;
|
||||
}
|
||||
@ -119,13 +127,18 @@ export class MessageBridge {
|
||||
}
|
||||
|
||||
private setupNodejsListener() {
|
||||
const EventEmitter = require('events');
|
||||
|
||||
const eventEmitter = new EventEmitter();
|
||||
|
||||
const emitter = this.setupSignature;
|
||||
if (!emitter.on || !emitter.emit) {
|
||||
return;
|
||||
}
|
||||
|
||||
emitter.on('message/service', (message: VSCodeMessage) => {
|
||||
this.dispatchMessage(message);
|
||||
});
|
||||
|
||||
this.postMessage = (message) => {
|
||||
eventEmitter.emit('server', message);
|
||||
emitter.emit('message/renderer', message);
|
||||
};
|
||||
}
|
||||
|
||||
@ -209,16 +222,18 @@ export class MessageBridge {
|
||||
}
|
||||
|
||||
// 单例实例
|
||||
const messageBridge = new MessageBridge();
|
||||
let messageBridge: MessageBridge;
|
||||
|
||||
export function createMessageBridge(setupSignature: any) {
|
||||
messageBridge = new MessageBridge(setupSignature);
|
||||
}
|
||||
|
||||
// 向外暴露一个独立函数,保证 MessageBridge 是单例的
|
||||
export function useMessageBridge() {
|
||||
if (!messageBridge && getPlatform() !== 'nodejs') {
|
||||
messageBridge = new MessageBridge('ws://localhost:8282');
|
||||
}
|
||||
const bridge = messageBridge;
|
||||
|
||||
return {
|
||||
postMessage: bridge.postMessage.bind(bridge),
|
||||
addCommandListener: bridge.addCommandListener.bind(bridge),
|
||||
commandRequest: bridge.commandRequest.bind(bridge),
|
||||
awaitForWebsockt: bridge.awaitForWebsockt.bind(bridge)
|
||||
};
|
||||
return bridge;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import type { ToolCallContent, ToolItem } from "@/hook/type";
|
||||
import { Ref, ref } from "vue";
|
||||
import { type Ref, ref } from "vue";
|
||||
|
||||
import type { OpenAI } from 'openai';
|
||||
type ChatCompletionChunk = OpenAI.Chat.Completions.ChatCompletionChunk;
|
||||
@ -51,6 +51,7 @@ interface EnableToolItem {
|
||||
name: string;
|
||||
description: string;
|
||||
enabled: boolean;
|
||||
inputSchema?: any;
|
||||
}
|
||||
|
||||
export interface ChatSetting {
|
||||
@ -117,17 +118,31 @@ export type IRenderMessage = ICommonRenderMessage | IToolRenderMessage;
|
||||
export function getToolSchema(enableTools: EnableToolItem[]) {
|
||||
const toolsSchema = [];
|
||||
for (let i = 0; i < enableTools.length; i++) {
|
||||
if (enableTools[i].enabled) {
|
||||
const tool = allTools.value[i];
|
||||
const enableTool = enableTools[i];
|
||||
|
||||
if (enableTool.enabled) {
|
||||
|
||||
if (enableTool.inputSchema) {
|
||||
toolsSchema.push({
|
||||
type: 'function',
|
||||
function: {
|
||||
name: enableTool.name,
|
||||
description: enableTool.description || "",
|
||||
parameters: enableTool.inputSchema
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const tool = allTools.value[i];
|
||||
|
||||
toolsSchema.push({
|
||||
type: 'function',
|
||||
function: {
|
||||
name: tool.name,
|
||||
description: tool.description || "",
|
||||
parameters: tool.inputSchema
|
||||
}
|
||||
});
|
||||
toolsSchema.push({
|
||||
type: 'function',
|
||||
function: {
|
||||
name: tool.name,
|
||||
description: tool.description || "",
|
||||
parameters: tool.inputSchema
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return toolsSchema;
|
||||
|
@ -21,12 +21,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { provide, onMounted, onUnmounted, ref, defineEmits, defineProps, PropType, inject, Ref } from 'vue';
|
||||
import { provide, onMounted, onUnmounted, ref, defineEmits, defineProps, type PropType, inject, type Ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import KRichTextarea from './rich-textarea.vue';
|
||||
import { tabs } from '../../panel';
|
||||
import { ChatMessage, ChatStorage, MessageState, ToolCall, RichTextItem } from './chat';
|
||||
import type { ChatMessage, ChatStorage, ToolCall, RichTextItem } from './chat';
|
||||
import { MessageState } from './chat';
|
||||
|
||||
import { TaskLoop } from '../core/task-loop';
|
||||
import { llmManager, llms } from '@/views/setting/llm';
|
||||
@ -93,7 +94,8 @@ function handleSend(newMessage?: string) {
|
||||
isLoading.value = true;
|
||||
autoScroll.value = true;
|
||||
|
||||
loop = new TaskLoop(streamingContent, streamingToolCalls);
|
||||
loop = new TaskLoop();
|
||||
loop.bindStreaming(streamingContent, streamingToolCalls);
|
||||
|
||||
loop.registerOnError((error) => {
|
||||
console.log('error.msg');
|
||||
|
@ -25,7 +25,7 @@
|
||||
<script setup lang="ts">
|
||||
import { defineComponent, inject, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { ChatStorage } from '../chat';
|
||||
import type { ChatStorage } from '../chat';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
|
@ -26,8 +26,8 @@
|
||||
<script setup lang="ts">
|
||||
import { createApp, inject, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { ChatStorage, EditorContext } from '../chat';
|
||||
import { PromptsGetResponse, PromptTemplate } from '@/hook/type';
|
||||
import type { ChatStorage, EditorContext } from '../chat';
|
||||
import type { PromptsGetResponse, PromptTemplate } from '@/hook/type';
|
||||
|
||||
import PromptTemplates from '@/components/main-panel/prompt/prompt-templates.vue';
|
||||
import PromptReader from '@/components/main-panel/prompt/prompt-reader.vue';
|
||||
|
@ -24,8 +24,8 @@
|
||||
<script setup lang="ts">
|
||||
import { createApp, inject, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { ChatStorage, EditorContext } from '../chat';
|
||||
import { Resources, ResourcesReadResponse, ResourceTemplate } from '@/hook/type';
|
||||
import type { ChatStorage, EditorContext } from '../chat';
|
||||
import type { Resources, ResourcesReadResponse, ResourceTemplate } from '@/hook/type';
|
||||
|
||||
import ResourceList from '@/components/main-panel/resource/resource-list.vue';
|
||||
import ResourceReader from '@/components/main-panel/resource/resouce-reader.vue';
|
||||
|
@ -1,8 +1,13 @@
|
||||
import { ToolCallResponse } from "@/hook/type";
|
||||
import type { ToolCallContent, ToolCallResponse } from "@/hook/type";
|
||||
import { callTool } from "../../tool/tools";
|
||||
import { MessageState, ToolCall } from "../chat-box/chat";
|
||||
import { MessageState, type ToolCall } from "../chat-box/chat";
|
||||
|
||||
export async function handleToolCalls(toolCall: ToolCall) {
|
||||
export interface ToolCallResult {
|
||||
state: MessageState;
|
||||
content: ToolCallContent[];
|
||||
}
|
||||
|
||||
export async function handleToolCalls(toolCall: ToolCall): Promise<ToolCallResult> {
|
||||
// 反序列化 streaming 来的参数字符串
|
||||
const toolName = toolCall.function.name;
|
||||
const argsResult = deserializeToolCallResponse(toolCall.function.arguments);
|
||||
|
@ -1,18 +1,20 @@
|
||||
/* eslint-disable */
|
||||
import type { Ref } from "vue";
|
||||
import { ToolCall, ChatStorage, getToolSchema, MessageState } from "../chat-box/chat";
|
||||
import { useMessageBridge } from "@/api/message-bridge";
|
||||
import { ref, type Ref } from "vue";
|
||||
import { type ToolCall, type ChatStorage, getToolSchema, MessageState } from "../chat-box/chat";
|
||||
import { useMessageBridge, MessageBridge, createMessageBridge } from "@/api/message-bridge";
|
||||
import type { OpenAI } from 'openai';
|
||||
import { llmManager, llms } from "@/views/setting/llm";
|
||||
import { pinkLog, redLog } from "@/views/setting/util";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { handleToolCalls } from "./handle-tool-calls";
|
||||
import { handleToolCalls, type ToolCallResult } from "./handle-tool-calls";
|
||||
import { getPlatform } from "@/api/platform";
|
||||
|
||||
export type ChatCompletionChunk = OpenAI.Chat.Completions.ChatCompletionChunk;
|
||||
export type ChatCompletionCreateParamsBase = OpenAI.Chat.Completions.ChatCompletionCreateParams & { id?: string };
|
||||
export interface TaskLoopOptions {
|
||||
maxEpochs: number;
|
||||
maxJsonParseRetry: number;
|
||||
maxEpochs?: number;
|
||||
maxJsonParseRetry?: number;
|
||||
adapter?: any;
|
||||
}
|
||||
|
||||
export interface IErrorMssage {
|
||||
@ -29,21 +31,40 @@ export interface IDoConversationResult {
|
||||
* @description 对任务循环进行的抽象封装
|
||||
*/
|
||||
export class TaskLoop {
|
||||
private bridge = useMessageBridge();
|
||||
private bridge: MessageBridge;
|
||||
private streamingContent: Ref<string>;
|
||||
private streamingToolCalls: Ref<ToolCall[]>;
|
||||
|
||||
private currentChatId = '';
|
||||
private onError: (error: IErrorMssage) => void = (msg) => {};
|
||||
private onChunk: (chunk: ChatCompletionChunk) => void = (chunk) => {};
|
||||
private onDone: () => void = () => {};
|
||||
private onToolCall: (toolCall: ToolCall) => ToolCall = toolCall => toolCall;
|
||||
private onToolCalled: (toolCallResult: ToolCallResult) => ToolCallResult = toolCallResult => toolCallResult;
|
||||
private onEpoch: () => void = () => {};
|
||||
private completionUsage: ChatCompletionChunk['usage'] | undefined;
|
||||
private llmConfig: any;
|
||||
|
||||
constructor(
|
||||
private readonly streamingContent: Ref<string>,
|
||||
private readonly streamingToolCalls: Ref<ToolCall[]>,
|
||||
private onError: (error: IErrorMssage) => void = (msg) => {},
|
||||
private onChunk: (chunk: ChatCompletionChunk) => void = (chunk) => {},
|
||||
private onDone: () => void = () => {},
|
||||
private onEpoch: () => void = () => {},
|
||||
private readonly taskOptions: TaskLoopOptions = { maxEpochs: 20, maxJsonParseRetry: 3 },
|
||||
private readonly taskOptions: TaskLoopOptions = { maxEpochs: 20, maxJsonParseRetry: 3, adapter: undefined },
|
||||
) {
|
||||
|
||||
this.streamingContent = ref('');
|
||||
this.streamingToolCalls = ref([]);
|
||||
|
||||
// 根据当前环境决定是否要开启 messageBridge
|
||||
const platform = getPlatform();
|
||||
if (platform === 'nodejs') {
|
||||
const adapter = taskOptions.adapter;
|
||||
|
||||
if (!adapter) {
|
||||
throw new Error('adapter is required');
|
||||
}
|
||||
|
||||
createMessageBridge(adapter.emitter);
|
||||
}
|
||||
|
||||
// web 环境下 bridge 会自动加载完成
|
||||
this.bridge = useMessageBridge();
|
||||
}
|
||||
|
||||
private handleChunkDeltaContent(chunk: ChatCompletionChunk) {
|
||||
@ -135,7 +156,7 @@ export class TaskLoop {
|
||||
|
||||
}, { once: true });
|
||||
|
||||
console.log(chatData);
|
||||
// console.log(chatData);
|
||||
|
||||
this.bridge.postMessage({
|
||||
command: 'llm/chat/completions',
|
||||
@ -200,6 +221,10 @@ export class TaskLoop {
|
||||
this.streamingToolCalls.value = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 注册 error 发生时触发的回调函数
|
||||
* @param handler
|
||||
*/
|
||||
public registerOnError(handler: (msg: IErrorMssage) => void) {
|
||||
this.onError = handler;
|
||||
}
|
||||
@ -208,14 +233,38 @@ export class TaskLoop {
|
||||
this.onChunk = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 注册 chat.completion 完成时触发的回调函数
|
||||
* @param handler
|
||||
*/
|
||||
public registerOnDone(handler: () => void) {
|
||||
this.onDone = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 注册每一个 epoch 开始时触发的回调函数
|
||||
* @param handler
|
||||
*/
|
||||
public registerOnEpoch(handler: () => void) {
|
||||
this.onEpoch = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 注册当工具调用前的回调函数,可以拦截并修改 toolcall 的输入
|
||||
* @param handler
|
||||
*/
|
||||
public registerOnToolCall(handler: (toolCall: ToolCall) => ToolCall) {
|
||||
this.onToolCall = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 注册当工具调用完成时的回调函数,会调用这个方法,可以拦截并修改 toolcall 的输出
|
||||
* @param handler
|
||||
*/
|
||||
public registerOnToolCalled(handler: (toolCallResult: ToolCallResult) => ToolCallResult) {
|
||||
this.onToolCalled = handler;
|
||||
}
|
||||
|
||||
public setMaxEpochs(maxEpochs: number) {
|
||||
this.taskOptions.maxEpochs = maxEpochs;
|
||||
}
|
||||
@ -235,6 +284,11 @@ export class TaskLoop {
|
||||
this.llmConfig = config;
|
||||
}
|
||||
|
||||
public bindStreaming(content: Ref<string>, toolCalls: Ref<ToolCall[]>) {
|
||||
this.streamingContent = content;
|
||||
this.streamingToolCalls = toolCalls;
|
||||
}
|
||||
|
||||
public getLlmConfig() {
|
||||
if (this.llmConfig) {
|
||||
return this.llmConfig;
|
||||
@ -262,8 +316,9 @@ export class TaskLoop {
|
||||
});
|
||||
|
||||
let jsonParseErrorRetryCount = 0;
|
||||
const maxEpochs = this.taskOptions.maxEpochs || 20;
|
||||
|
||||
for (let i = 0; i < this.taskOptions.maxEpochs; ++ i) {
|
||||
for (let i = 0; i < maxEpochs; ++ i) {
|
||||
|
||||
this.onEpoch();
|
||||
|
||||
@ -285,8 +340,8 @@ export class TaskLoop {
|
||||
// 发送请求
|
||||
const doConverationResult = await this.doConversation(chatData);
|
||||
|
||||
console.log('[doConverationResult] Response');
|
||||
console.log(doConverationResult);
|
||||
|
||||
|
||||
// 如果存在需要调度的工具
|
||||
if (this.streamingToolCalls.value.length > 0) {
|
||||
@ -304,8 +359,11 @@ export class TaskLoop {
|
||||
|
||||
pinkLog('调用工具数量:' + this.streamingToolCalls.value.length);
|
||||
|
||||
for (const toolCall of this.streamingToolCalls.value || []) {
|
||||
const toolCallResult = await handleToolCalls(toolCall);
|
||||
for (let toolCall of this.streamingToolCalls.value || []) {
|
||||
|
||||
toolCall = this.onToolCall(toolCall);
|
||||
let toolCallResult = await handleToolCalls(toolCall);
|
||||
toolCallResult = this.onToolCalled(toolCallResult);
|
||||
|
||||
if (toolCallResult.state === MessageState.ParseJsonError) {
|
||||
// 如果是因为解析 JSON 错误,则重新开始
|
||||
@ -315,7 +373,7 @@ export class TaskLoop {
|
||||
redLog('解析 JSON 错误 ' + toolCall?.function?.arguments);
|
||||
|
||||
// 如果因为 JSON 错误而失败太多,就只能中断了
|
||||
if (jsonParseErrorRetryCount >= this.taskOptions.maxJsonParseRetry) {
|
||||
if (jsonParseErrorRetryCount >= (this.taskOptions.maxJsonParseRetry || 3)) {
|
||||
tabStorage.messages.push({
|
||||
role: 'assistant',
|
||||
content: `解析 JSON 错误,无法继续调用工具 (累计错误次数 ${this.taskOptions.maxJsonParseRetry})`,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { IExtraInfo } from "../chat-box/chat";
|
||||
import type { IExtraInfo } from "../chat-box/chat";
|
||||
|
||||
export interface UsageStatistic {
|
||||
input: number;
|
||||
|
@ -57,9 +57,11 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, defineComponent, defineProps, onUnmounted, computed, nextTick, watch, provide } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { ElMessage, ScrollbarInstance } from 'element-plus';
|
||||
import { ElMessage, type ScrollbarInstance } from 'element-plus';
|
||||
import { tabs } from '../panel';
|
||||
import { ChatMessage, ChatStorage, IRenderMessage, MessageState, ToolCall } from './chat-box/chat';
|
||||
import type { ChatMessage, ChatStorage, IRenderMessage, ToolCall } from './chat-box/chat';
|
||||
import { MessageState } from './chat-box/chat';
|
||||
|
||||
import * as Message from './message';
|
||||
import ChatBox from './chat-box/index.vue';
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import Prism from "./prism";
|
||||
import Prism from 'prismjs';
|
||||
|
||||
// 定义 escapeHtml 函数
|
||||
function escapeHtml(unsafe: string) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const Prism: {
|
||||
export const Prism: {
|
||||
highlight: (code: string, language: any, lang: string) => string;
|
||||
languages: Record<string, any>;
|
||||
// 添加其他需要的类型定义
|
||||
|
@ -32,7 +32,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, ref, PropType, inject } from 'vue';
|
||||
import { defineProps, ref, type PropType, inject } from 'vue';
|
||||
import { tabs } from '../../panel';
|
||||
import type { ChatStorage, IRenderMessage } from '../chat-box/chat';
|
||||
|
||||
|
@ -27,10 +27,10 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useMessageBridge } from '@/api/message-bridge';
|
||||
import { CasualRestAPI, PromptTemplate, PromptsListResponse } from '@/hook/type';
|
||||
import type { CasualRestAPI, PromptTemplate, PromptsListResponse } from '@/hook/type';
|
||||
import { onMounted, onUnmounted, defineProps, defineEmits, reactive } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { promptsManager, PromptStorage } from './prompts';
|
||||
import { promptsManager, type PromptStorage } from './prompts';
|
||||
import { tabs } from '../panel';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { PromptsGetResponse, PromptTemplate } from '@/hook/type';
|
||||
import type { PromptsGetResponse, PromptTemplate } from '@/hook/type';
|
||||
import { reactive } from 'vue';
|
||||
|
||||
export const promptsManager = reactive<{
|
||||
|
@ -38,8 +38,8 @@ import { defineComponent, defineProps, watch, ref, computed, reactive, defineEmi
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import { tabs } from '../panel';
|
||||
import { parseResourceTemplate, resourcesManager, ResourceStorage } from './resources';
|
||||
import { CasualRestAPI, ResourcesReadResponse } from '@/hook/type';
|
||||
import { parseResourceTemplate, resourcesManager, type ResourceStorage } from './resources';
|
||||
import type{ CasualRestAPI, ResourcesReadResponse } from '@/hook/type';
|
||||
import { useMessageBridge } from '@/api/message-bridge';
|
||||
import { getDefaultValue, normaliseJavascriptType } from '@/hook/mcp';
|
||||
|
||||
|
@ -30,10 +30,10 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useMessageBridge } from '@/api/message-bridge';
|
||||
import { CasualRestAPI, ResourceTemplate, ResourceTemplatesListResponse } from '@/hook/type';
|
||||
import type { CasualRestAPI, ResourceTemplate, ResourceTemplatesListResponse } from '@/hook/type';
|
||||
import { onMounted, onUnmounted, defineProps, ref, reactive } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { resourcesManager, ResourceStorage } from './resources';
|
||||
import { resourcesManager, type ResourceStorage } from './resources';
|
||||
import { tabs } from '../panel';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
|
@ -27,10 +27,10 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useMessageBridge } from '@/api/message-bridge';
|
||||
import { CasualRestAPI, Resources, ResourcesListResponse } from '@/hook/type';
|
||||
import type { CasualRestAPI, Resources, ResourcesListResponse } from '@/hook/type';
|
||||
import { onMounted, onUnmounted, defineProps, defineEmits, reactive } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { resourcesManager, ResourceStorage } from './resources';
|
||||
import { resourcesManager, type ResourceStorage } from './resources';
|
||||
import { tabs } from '../panel';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ResourcesReadResponse, ResourceTemplate, Resources } from '@/hook/type';
|
||||
import type { ResourcesReadResponse, ResourceTemplate, Resources } from '@/hook/type';
|
||||
import { reactive } from 'vue';
|
||||
|
||||
|
||||
|
@ -31,10 +31,10 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useMessageBridge } from '@/api/message-bridge';
|
||||
import { CasualRestAPI, ToolsListResponse } from '@/hook/type';
|
||||
import type { CasualRestAPI, ToolsListResponse } from '@/hook/type';
|
||||
import { onMounted, onUnmounted, defineProps } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { toolsManager, ToolStorage } from './tools';
|
||||
import { toolsManager, type ToolStorage } from './tools';
|
||||
import { tabs } from '../panel';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useMessageBridge } from '@/api/message-bridge';
|
||||
import { mcpSetting } from '@/hook/mcp';
|
||||
import { ToolsListResponse, ToolCallResponse, CasualRestAPI } from '@/hook/type';
|
||||
import type { ToolsListResponse, ToolCallResponse, CasualRestAPI } from '@/hook/type';
|
||||
import { pinkLog } from '@/views/setting/util';
|
||||
import { reactive } from 'vue';
|
||||
|
||||
@ -16,9 +16,9 @@ export interface ToolStorage {
|
||||
formData: Record<string, any>;
|
||||
}
|
||||
|
||||
const bridge = useMessageBridge();
|
||||
|
||||
export function callTool(toolName: string, toolArgs: Record<string, any>) {
|
||||
const bridge = useMessageBridge();
|
||||
return new Promise<ToolCallResponse>((resolve, reject) => {
|
||||
bridge.addCommandListener('tools/call', (data: CasualRestAPI<ToolCallResponse>) => {
|
||||
console.log(data.msg);
|
||||
|
55
renderer/src/components/password-dialog/index.vue
Normal file
55
renderer/src/components/password-dialog/index.vue
Normal file
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" title="请输入密码" :close-on-click-modal="false" :close-on-press-escape="false"
|
||||
:show-close="false" width="30%" top="20vh">
|
||||
<br>
|
||||
<el-input v-model="privilegeStatus.password"
|
||||
type="password"
|
||||
placeholder="请输入密码"
|
||||
@keyup.enter.prevent="handleSubmit"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="handleSubmit">确认</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { privilegeStatus } from './status';
|
||||
import { useMessageBridge } from '@/api/message-bridge';
|
||||
import { initialise } from '@/views/connect/connection';
|
||||
|
||||
const dialogVisible = ref(true);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const bridge = useMessageBridge();
|
||||
const res = await bridge.commandRequest('ciallo', { password: privilegeStatus.password });
|
||||
|
||||
if (res.code === 200) {
|
||||
ElMessage.success('密码验证成功,欢迎回来锦恢');
|
||||
dialogVisible.value = false;
|
||||
|
||||
initialise();
|
||||
|
||||
} else {
|
||||
ElMessage.error('密码验证失败,请重新输入');
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
dialogVisible.value = true;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-dialog {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
z-index: 9999;
|
||||
}
|
||||
</style>
|
6
renderer/src/components/password-dialog/status.ts
Normal file
6
renderer/src/components/password-dialog/status.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { reactive } from "vue";
|
||||
|
||||
export const privilegeStatus = reactive({
|
||||
allow: true,
|
||||
password: ''
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
|
||||
import { createRouter, createWebHistory, type RouteRecordRaw } from "vue-router";
|
||||
|
||||
const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
@ -33,7 +33,7 @@ const routes: Array<RouteRecordRaw> = [
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(process.env.BASE_URL),
|
||||
history: createWebHistory('/'),
|
||||
routes,
|
||||
});
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { useMessageBridge } from '@/api/message-bridge';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { pinkLog } from '../setting/util';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { OpenMcpSupportPlatform } from '@/api/platform';
|
||||
import { ElLoading, ElMessage } from 'element-plus';
|
||||
import { getPlatform, type OpenMcpSupportPlatform } from '@/api/platform';
|
||||
import { getTour, loadSetting } from '@/hook/setting';
|
||||
import { loadPanels } from '@/hook/panel';
|
||||
|
||||
export const connectionMethods = reactive({
|
||||
current: 'STDIO',
|
||||
@ -98,7 +100,7 @@ export async function doConnect(
|
||||
}
|
||||
} else {
|
||||
connectionMethods.current = 'SSE';
|
||||
connectionArgs.urlString = connectionItem.url;
|
||||
connectionArgs.urlString = connectionItem.url || '';
|
||||
|
||||
if (connectionArgs.urlString.length === 0) {
|
||||
return;
|
||||
@ -345,4 +347,37 @@ export async function handleEnvSwitch(enabled: boolean) {
|
||||
|
||||
export async function loadEnvVar() {
|
||||
return await handleEnvSwitch(true);
|
||||
}
|
||||
|
||||
export async function initialise() {
|
||||
|
||||
pinkLog('准备请求设置');
|
||||
|
||||
const loading = ElLoading.service({
|
||||
fullscreen: true,
|
||||
lock: true,
|
||||
text: 'Loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
});
|
||||
const platform = getPlatform();
|
||||
|
||||
// 加载全局设置
|
||||
loadSetting();
|
||||
|
||||
// 设置环境变量
|
||||
await loadEnvVar();
|
||||
|
||||
// 获取引导状态
|
||||
await getTour();
|
||||
|
||||
// 尝试进行初始化连接
|
||||
await doConnect({
|
||||
namespace: platform,
|
||||
updateCommandString: true
|
||||
});
|
||||
|
||||
// loading panels
|
||||
await loadPanels();
|
||||
|
||||
loading.close();
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { ChatStorage } from '@/components/main-panel/chat/chat-box/chat';
|
||||
import type { ChatStorage } from '@/components/main-panel/chat/chat-box/chat';
|
||||
import { TaskLoop } from '@/components/main-panel/chat/core/task-loop';
|
||||
import { llmManager } from './llm';
|
||||
import { reactive, ref } from 'vue';
|
||||
@ -26,9 +26,7 @@ export async function makeSimpleTalk() {
|
||||
// 使用最简单的 hello 来测试
|
||||
const testMessage = 'hello';
|
||||
|
||||
const s1 = ref('');
|
||||
const s2 = ref([]);
|
||||
const loop = new TaskLoop(s1, s2);
|
||||
const loop = new TaskLoop();
|
||||
|
||||
const chatStorage: ChatStorage = {
|
||||
messages: [],
|
||||
@ -62,7 +60,7 @@ export async function makeSimpleTalk() {
|
||||
await loop.start(chatStorage, testMessage);
|
||||
|
||||
const costTime = (performance.now() - startTime!) / 1000;
|
||||
const message = chatStorage.messages.at(-1);
|
||||
const message = chatStorage.messages[chatStorage.messages.length - 1];
|
||||
console.log(chatStorage.messages);
|
||||
|
||||
if (message?.extraInfo) {
|
||||
@ -72,5 +70,4 @@ export async function makeSimpleTalk() {
|
||||
simpleTestResult.tps = (total / costTime).toFixed(2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { markRaw, reactive } from 'vue';
|
||||
import { createTab, debugModes, tabs } from '@/components/main-panel/panel';
|
||||
import { ToolStorage } from '@/components/main-panel/tool/tools';
|
||||
import { ToolCall } from '@/components/main-panel/chat/chat-box/chat';
|
||||
import type { ToolStorage } from '@/components/main-panel/tool/tools';
|
||||
import type { ToolCall } from '@/components/main-panel/chat/chat-box/chat';
|
||||
|
||||
import I18n from '@/i18n';
|
||||
const { t } = I18n.global;
|
||||
|
19
renderer/tsconfig.app.json
Normal file
19
renderer/tsconfig.app.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||
"include": [
|
||||
"env.d.ts",
|
||||
"src/**/*",
|
||||
"src/**/*.vue"
|
||||
],
|
||||
"exclude": [
|
||||
"src/**/__tests__/*"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "nodenext",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"moduleResolution": "nodenext",
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"useDefineForClassFields": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"types": [
|
||||
"webpack-env"
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost"
|
||||
"es2022",
|
||||
"dom"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"tests/**/*.ts",
|
||||
"tests/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
}
|
||||
]
|
||||
}
|
20
renderer/tsconfig.node.json
Normal file
20
renderer/tsconfig.node.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"extends": "@tsconfig/node22/tsconfig.json",
|
||||
"include": [
|
||||
"vite.config.*",
|
||||
"vitest.config.*",
|
||||
"cypress.config.*",
|
||||
"nightwatch.conf.*",
|
||||
"playwright.config.*",
|
||||
"eslint.config.*"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"types": [
|
||||
"node"
|
||||
]
|
||||
}
|
||||
}
|
18
renderer/vite.config.ts
Normal file
18
renderer/vite.config.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
vueDevTools(),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
},
|
||||
},
|
||||
})
|
@ -1,43 +0,0 @@
|
||||
const { defineConfig } = require("@vue/cli-service");
|
||||
|
||||
module.exports = defineConfig({
|
||||
transpileDependencies: true,
|
||||
publicPath: process.env.NODE_ENV === 'production' ? '' : '/',
|
||||
configureWebpack: {
|
||||
optimization: {
|
||||
splitChunks: false
|
||||
}
|
||||
},
|
||||
chainWebpack: config => {
|
||||
// 删除所有预设的代码分割规则
|
||||
config.optimization.delete('splitChunks');
|
||||
|
||||
// 确保路由组件同步加载
|
||||
config.plugins.delete('prefetch');
|
||||
config.plugins.delete('preload');
|
||||
|
||||
// 删除 public 下指定的 css 文件
|
||||
config.plugin('copy').tap(args => {
|
||||
args[0].patterns = args[0].patterns.map((pattern) => {
|
||||
if (pattern.from === "public") {
|
||||
// 忽略指定的 CSS 文件
|
||||
pattern.globOptions = {
|
||||
ignore: [
|
||||
"vscode.css",
|
||||
"default-light.css",
|
||||
"default-dark.css",
|
||||
],
|
||||
};
|
||||
}
|
||||
return pattern;
|
||||
});
|
||||
return args;
|
||||
});
|
||||
},
|
||||
css: {
|
||||
extract: false
|
||||
},
|
||||
devServer: {
|
||||
port: 8081
|
||||
}
|
||||
});
|
@ -1,22 +0,0 @@
|
||||
const AutoImport = require('unplugin-auto-import/webpack')
|
||||
const Components = require('unplugin-vue-components/webpack')
|
||||
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
Components({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
fallback: {
|
||||
"stream": false
|
||||
}
|
||||
},
|
||||
};
|
95
resources/openmcp-sdk-release/README.md
Normal file
95
resources/openmcp-sdk-release/README.md
Normal file
@ -0,0 +1,95 @@
|
||||
<div align="center">
|
||||
|
||||
<img src="./icons/openmcp.png" height="200px"/>
|
||||
|
||||
<h3>OpenMCP: 一体化 MCP Server 调试器</h3>
|
||||
|
||||
<a href="https://qm.qq.com/cgi-bin/qm/qr?k=C6ZUTZvfqWoI12lWe7L93cWa1hUsuVT0&jump_from=webapi&authKey=McW6B1ogTPjPDrCyGttS890tMZGQ1KB3QLuG4aqVNRaYp4vlTSgf2c6dMcNjMuBD" target="_blank" style="display: inline-block; padding: 8px 16px; background-color: #CB81DA; color: white; border-radius: .5em; text-decoration: none;">👉 加入 OpenMCP正式级技术组</a>
|
||||
|
||||
|
||||
<a href="https://discord.gg/af5cfB9a" target="_blank" style="display: inline-block; padding: 8px 16px; background-color: rgb(84, 176, 84); color: white; border-radius: .5em; text-decoration: none;"> 加入 OpenMCP Discord频道</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
npm install openmcp-sdk
|
||||
```
|
||||
|
||||
## 使用
|
||||
|
||||
文件名:main.ts
|
||||
|
||||
```typescript
|
||||
import { TaskLoop } from 'openmcp-sdk/task-loop';
|
||||
import { TaskLoopAdapter } from 'openmcp-sdk/service';
|
||||
|
||||
async function main() {
|
||||
// 创建适配器,负责通信和 mcp 连接
|
||||
const adapter = new TaskLoopAdapter();
|
||||
|
||||
// 连接 mcp 服务器
|
||||
await adapter.connectMcpServer({
|
||||
connectionType: 'STDIO',
|
||||
command: 'node',
|
||||
args: [
|
||||
'~/projects/mcp/servers/src/puppeteer/dist/index.js'
|
||||
]
|
||||
});
|
||||
|
||||
// 获取工具列表
|
||||
const tools = await adapter.listTools();
|
||||
|
||||
// 创建事件循环驱动器
|
||||
const taskLoop = new TaskLoop({ adapter });
|
||||
|
||||
// 配置改次事件循环使用的大模型
|
||||
taskLoop.setLlmConfig({
|
||||
id: 'deepseek',
|
||||
baseUrl: 'https://api.deepseek.com/v1',
|
||||
userToken: process.env['DEEPSEEK_API_TOKEN'],
|
||||
userModel: 'deepseek-chat'
|
||||
});
|
||||
|
||||
// 创建当前事件循环对应的上下文,并且配置当前上下文的设置
|
||||
const storage = {
|
||||
messages: [],
|
||||
settings: {
|
||||
temperature: 0.7,
|
||||
enableTools: tools,
|
||||
systemPrompt: 'you are a clever bot',
|
||||
contextLength: 20
|
||||
}
|
||||
};
|
||||
|
||||
// 本次发出的问题
|
||||
const message = 'hello world';
|
||||
|
||||
// 事件循环结束的句柄
|
||||
taskLoop.registerOnDone(() => {
|
||||
console.log('taskLoop done');
|
||||
});
|
||||
|
||||
// 事件循环每一次 epoch 开始的句柄
|
||||
taskLoop.registerOnError((error) => {
|
||||
console.log('taskLoop error', error);
|
||||
});
|
||||
|
||||
// 事件循环出现 error 时的句柄(出现 error 不一定会停止事件循环)
|
||||
taskLoop.registerOnEpoch(() => {
|
||||
console.log('taskLoop epoch');
|
||||
});
|
||||
|
||||
// 开启事件循环
|
||||
await taskLoop.start(storage, message);
|
||||
|
||||
// 打印上下文,最终的回答在 messages.at(-1) 中
|
||||
console.log(storage.messages);
|
||||
}
|
||||
|
||||
main();
|
||||
```
|
||||
|
||||
star 我们的项目:https://github.com/LSTM-Kirigaya/openmcp-client
|
BIN
resources/openmcp-sdk-release/icons/openmcp.png
Normal file
BIN
resources/openmcp-sdk-release/icons/openmcp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
38
resources/openmcp-sdk-release/package.json
Normal file
38
resources/openmcp-sdk-release/package.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "openmcp-sdk",
|
||||
"version": "0.0.4",
|
||||
"description": "openmcp-sdk",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/LSTM-Kirigaya/openmcp-client"
|
||||
},
|
||||
"keywords": [
|
||||
"mcp",
|
||||
"openmcp",
|
||||
"openmcp-sdk",
|
||||
"llm framework",
|
||||
"agent",
|
||||
"ai agent"
|
||||
],
|
||||
"author": "kirigaya",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/LSTM-Kirigaya/openmcp-client/issues"
|
||||
},
|
||||
"homepage": "https://document.kirigaya.cn/blogs/openmcp/main.html",
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.10.2",
|
||||
"@seald-io/nedb": "^4.1.1",
|
||||
"@vue/server-renderer": "^3.5.13",
|
||||
"axios": "^1.7.7",
|
||||
"bson": "^6.8.0",
|
||||
"openai": "^4.93.0",
|
||||
"pako": "^2.1.0",
|
||||
"tesseract.js": "^6.0.1",
|
||||
"uuid": "^11.1.0",
|
||||
"ws": "^8.18.1"
|
||||
}
|
||||
}
|
154
resources/openmcp-sdk-release/task-loop.d.ts
vendored
Normal file
154
resources/openmcp-sdk-release/task-loop.d.ts
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
/* eslint-disable */
|
||||
import type { OpenAI } from 'openai';
|
||||
|
||||
export type ChatCompletionChunk = OpenAI.Chat.Completions.ChatCompletionChunk;
|
||||
export type ChatCompletionCreateParamsBase = OpenAI.Chat.Completions.ChatCompletionCreateParams & { id?: string };
|
||||
|
||||
export interface TaskLoopOptions {
|
||||
maxEpochs?: number;
|
||||
maxJsonParseRetry?: number;
|
||||
adapter?: any;
|
||||
}
|
||||
|
||||
export type Ref<T> = {
|
||||
value: T;
|
||||
};
|
||||
|
||||
export interface ToolCall {
|
||||
id?: string;
|
||||
index?: number;
|
||||
type: string;
|
||||
function: {
|
||||
name: string;
|
||||
arguments: string;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ToolCallContent {
|
||||
type: string;
|
||||
text: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface ToolCallResult {
|
||||
state: MessageState;
|
||||
content: ToolCallContent[];
|
||||
}
|
||||
|
||||
export enum MessageState {
|
||||
ServerError = 'server internal error',
|
||||
ReceiveChunkError = 'receive chunk error',
|
||||
Timeout = 'timeout',
|
||||
MaxEpochs = 'max epochs',
|
||||
Unknown = 'unknown error',
|
||||
Abort = 'abort',
|
||||
ToolCall = 'tool call failed',
|
||||
None = 'none',
|
||||
Success = 'success',
|
||||
ParseJsonError = 'parse json error'
|
||||
}
|
||||
|
||||
export interface IErrorMssage {
|
||||
state: MessageState;
|
||||
msg: string;
|
||||
}
|
||||
|
||||
export interface IDoConversationResult {
|
||||
stop: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 对任务循环进行的抽象封装
|
||||
*/
|
||||
export class TaskLoop {
|
||||
private streamingContent;
|
||||
private streamingToolCalls;
|
||||
private readonly taskOptions;
|
||||
private bridge;
|
||||
private currentChatId;
|
||||
private onError;
|
||||
private onChunk;
|
||||
private onDone;
|
||||
private onToolCalled;
|
||||
private onEpoch;
|
||||
private completionUsage;
|
||||
private llmConfig;
|
||||
constructor(taskOptions?: TaskLoopOptions);
|
||||
private handleChunkDeltaContent;
|
||||
private handleChunkDeltaToolCalls;
|
||||
private handleChunkUsage;
|
||||
private doConversation;
|
||||
makeChatData(tabStorage: any): ChatCompletionCreateParamsBase | undefined;
|
||||
abort(): void;
|
||||
|
||||
/**
|
||||
* @description 注册 error 发生时触发的回调函数
|
||||
* @param handler
|
||||
*/
|
||||
registerOnError(handler: (msg: IErrorMssage) => void): void;
|
||||
registerOnChunk(handler: (chunk: ChatCompletionChunk) => void): void;
|
||||
|
||||
/**
|
||||
* @description 注册 chat.completion 完成时触发的回调函数
|
||||
* @param handler
|
||||
*/
|
||||
registerOnDone(handler: () => void): void;
|
||||
|
||||
/**
|
||||
* @description 注册每一个 epoch 开始时触发的回调函数
|
||||
* @param handler
|
||||
*/
|
||||
registerOnEpoch(handler: () => void): void;
|
||||
|
||||
/**
|
||||
* @description 注册当工具调用完成时的回调函数,会调用这个方法,可以拦截并修改 toolcall 的输出
|
||||
* @param handler
|
||||
*/
|
||||
registerOnToolCalled(handler: (toolCallResult: ToolCallResult) => ToolCallResult): void;
|
||||
|
||||
/**
|
||||
* @description 注册当工具调用前的回调函数,可以拦截并修改 toolcall 的输入
|
||||
* @param handler
|
||||
*/
|
||||
registerOnToolCall(handler: (toolCall: ToolCall) => ToolCall): void;
|
||||
|
||||
/**
|
||||
* @description 获取当前的 LLM 配置
|
||||
*/
|
||||
getLlmConfig(): any;
|
||||
|
||||
/**
|
||||
* @description 设置当前的 LLM 配置,用于 nodejs 环境运行
|
||||
* @param config
|
||||
* @example
|
||||
* setLlmConfig({
|
||||
* id: 'openai',
|
||||
* baseUrl: 'https://api.openai.com/v1',
|
||||
* userToken: 'sk-xxx',
|
||||
* userModel: 'gpt-3.5-turbo',
|
||||
* })
|
||||
*/
|
||||
setLlmConfig(config: any): void;
|
||||
|
||||
/**
|
||||
* @description 设置最大 epoch 次数
|
||||
* @param maxEpochs
|
||||
*/
|
||||
setMaxEpochs(maxEpochs: number): void;
|
||||
bindStreaming(content: Ref<string>, toolCalls: Ref<ToolCall[]>): void;
|
||||
connectToService(): Promise<void>;
|
||||
/**
|
||||
* @description 开启循环,异步更新 DOM
|
||||
*/
|
||||
start(tabStorage: any, userMessage: string): Promise<void>;
|
||||
}
|
||||
|
||||
export declare const getToolSchema: any;
|
||||
export declare const useMessageBridge: any;
|
||||
export declare const llmManager: any;
|
||||
export declare const llms: any;
|
||||
export declare const pinkLog: any;
|
||||
export declare const redLog: any;
|
||||
export declare const ElMessage: any;
|
||||
export declare const handleToolCalls: any;
|
||||
export declare const getPlatform: any;
|
8
resources/openmcp-sdk-release/tools.js
Normal file
8
resources/openmcp-sdk-release/tools.js
Normal file
@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
ElMessage: {
|
||||
error: console.error,
|
||||
warning: console.warn,
|
||||
info: console.info,
|
||||
success: console.log
|
||||
}
|
||||
}
|
3
service/.gitignore
vendored
3
service/.gitignore
vendored
@ -26,4 +26,5 @@ setting.json
|
||||
|
||||
*.traineddata
|
||||
.env
|
||||
tabs.example-servers_puppeteer.json
|
||||
tabs.*
|
||||
update.sh
|
@ -3,7 +3,7 @@
|
||||
```mermaid
|
||||
graph LR
|
||||
|
||||
renderer <--ws://localhost:8080--> router
|
||||
renderer <--ws://localhost:8282--> router
|
||||
subgraph service
|
||||
router <--setting/save--> app_service
|
||||
router <--resources/read--> mcp_service
|
||||
@ -39,7 +39,7 @@ post_process --tool response--> storage
|
||||
```mermaid
|
||||
graph LR
|
||||
|
||||
renderer <--ws://localhost:8080--> llm_service
|
||||
renderer <--ws://localhost:8282--> llm_service
|
||||
subgraph llm_service_body
|
||||
llm_service --type image --> handle_image
|
||||
llm_service --type text --> handle_text
|
||||
|
@ -1,77 +0,0 @@
|
||||
|
||||
/**
|
||||
* source: https://gist.github.com/Laci21/9dd074f3a5a461ab04adb7db678534d3
|
||||
* issue: https://github.com/modelcontextprotocol/typescript-sdk/issues/217
|
||||
*
|
||||
* This script fixes the MCP SDK issue with pkce-challenge ES Module
|
||||
* It replaces the static require with a dynamic import in the auth.js file
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Path to the file that needs patching
|
||||
const authFilePath = path.resolve(
|
||||
__dirname,
|
||||
'node_modules',
|
||||
'@modelcontextprotocol',
|
||||
'sdk',
|
||||
'dist',
|
||||
'cjs',
|
||||
'client',
|
||||
'auth.js'
|
||||
);
|
||||
|
||||
console.log('Checking if MCP SDK patch is needed...');
|
||||
|
||||
// Check if the file exists
|
||||
if (!fs.existsSync(authFilePath)) {
|
||||
console.error(`Error: File not found at ${authFilePath}`);
|
||||
console.log('Make sure you have installed @modelcontextprotocol/sdk package');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Read the file content
|
||||
const fileContent = fs.readFileSync(authFilePath, 'utf8');
|
||||
|
||||
// Check if the file already contains our patch
|
||||
if (fileContent.includes('loadPkceChallenge')) {
|
||||
console.log('MCP SDK is already patched!');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Check if the file contains the problematic require
|
||||
if (!fileContent.includes("require(\"pkce-challenge\")")) {
|
||||
console.log('The MCP SDK file does not contain the expected require statement.');
|
||||
console.log('This patch may not be needed or the SDK has been updated.');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
console.log('Applying patch to MCP SDK...');
|
||||
|
||||
// The code to replace the problematic require
|
||||
const requireLine = "const pkce_challenge_1 = __importDefault(require(\"pkce-challenge\"));";
|
||||
const replacementCode = `let pkce_challenge_1 = { default: null };
|
||||
async function loadPkceChallenge() {
|
||||
if (!pkce_challenge_1.default) {
|
||||
const mod = await import("pkce-challenge");
|
||||
pkce_challenge_1.default = mod.default;
|
||||
}
|
||||
}`;
|
||||
|
||||
// Replace the require line
|
||||
let patchedContent = fileContent.replace(requireLine, replacementCode);
|
||||
|
||||
// Replace the function call to add the loading step
|
||||
const challengeCall = "const challenge = await (0, pkce_challenge_1.default)();";
|
||||
const replacementCall = "await loadPkceChallenge();\n const challenge = await pkce_challenge_1.default();";
|
||||
patchedContent = patchedContent.replace(challengeCall, replacementCall);
|
||||
|
||||
// Write the patched content back to the file
|
||||
fs.writeFileSync(authFilePath, patchedContent, 'utf8');
|
||||
|
||||
console.log('✅ MCP SDK patched successfully!');
|
||||
console.log('The patch changes:');
|
||||
console.log('1. Replaced static require with dynamic import for pkce-challenge');
|
||||
console.log('2. Added async loading function to handle the import');
|
||||
console.log('\nYou should now be able to run the application without ESM errors.');
|
@ -1,5 +1,5 @@
|
||||
import { requestHandlerStorage } from ".";
|
||||
import { PostMessageble } from "../hook/adapter";
|
||||
import type { PostMessageble } from "../hook/adapter";
|
||||
import { LlmController } from "../llm/llm.controller";
|
||||
import { ClientController } from "../mcp/client.controller";
|
||||
import { ConnectController } from "../mcp/connect.controller";
|
||||
|
@ -1,9 +1,13 @@
|
||||
import { WebSocket } from 'ws';
|
||||
import { EventEmitter } from 'events';
|
||||
import { routeMessage } from '../common/router';
|
||||
import { McpOptions } from '../mcp/client.dto';
|
||||
import { client, connectService } from '../mcp/connect.service';
|
||||
|
||||
// WebSocket 消息格式
|
||||
export interface WebSocketMessage {
|
||||
command: string;
|
||||
data: any;
|
||||
data: any;
|
||||
}
|
||||
|
||||
// 服务器返回的消息格式
|
||||
@ -62,4 +66,77 @@ export class VSCodeWebViewLike {
|
||||
dispose: () => this.messageHandlers.delete(callback),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class TaskLoopAdapter {
|
||||
public emitter: EventEmitter;
|
||||
private messageHandlers: Set<MessageHandler>;
|
||||
|
||||
constructor(option?: any) {
|
||||
this.emitter = new EventEmitter(option);
|
||||
this.messageHandlers = new Set();
|
||||
|
||||
this.emitter.on('message/renderer', (message: WebSocketMessage) => {
|
||||
this.messageHandlers.forEach((handler) => handler(message));
|
||||
});
|
||||
|
||||
// 默认需要将监听的消息导入到 routeMessage 中
|
||||
this.onDidReceiveMessage((message) => {
|
||||
const { command, data } = message;
|
||||
routeMessage(command, data, this);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 发送消息
|
||||
* @param message - 包含 command 和 args 的消息
|
||||
*/
|
||||
public postMessage(message: WebSocketMessage): void {
|
||||
this.emitter.emit('message/service', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 注册接受消息的句柄
|
||||
* @param callback - 消息回调
|
||||
* @returns {{ dispose: () => void }} - 可销毁的监听器
|
||||
*/
|
||||
public onDidReceiveMessage(callback: MessageHandler): { dispose: () => void } {
|
||||
this.messageHandlers.add(callback);
|
||||
return {
|
||||
dispose: () => this.messageHandlers.delete(callback),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 连接到 mcp 服务端
|
||||
* @param mcpOption
|
||||
*/
|
||||
public async connectMcpServer(mcpOption: McpOptions) {
|
||||
const res = await connectService(undefined, mcpOption);
|
||||
if (res.code === 200) {
|
||||
console.log('✅ 成功连接 mcp 服务器: ' + res.msg);
|
||||
const version = client?.getServerVersion();
|
||||
console.log(version);
|
||||
} else {
|
||||
console.error('❌ 连接 mcp 服务器失败:' + res.msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取 mcp 服务器的工具列表
|
||||
* @returns
|
||||
*/
|
||||
public async listTools() {
|
||||
const tools = await client?.listTools();
|
||||
if (tools?.tools) {
|
||||
return tools.tools.map((tool) => {
|
||||
const enabledTools = { ...tool, enabled: true };
|
||||
return enabledTools;
|
||||
});
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
export { routeMessage } from './common/router';
|
||||
export { VSCodeWebViewLike } from './hook/adapter';
|
||||
export { VSCodeWebViewLike, TaskLoopAdapter } from './hook/adapter';
|
||||
export { setVscodeWorkspace, setRunningCWD } from './hook/setting';
|
||||
// TODO: 更加规范
|
||||
export { client } from './mcp/connect.service';
|
@ -6,7 +6,9 @@ export class LlmController {
|
||||
|
||||
@Controller('llm/chat/completions')
|
||||
async chatCompletion(client: RequestClientType, data: any, webview: PostMessageble) {
|
||||
if (!client) {
|
||||
let { tools = [] } = data;
|
||||
|
||||
if (tools.length > 0 && !client) {
|
||||
return {
|
||||
code: 501,
|
||||
msg:'mcp client 尚未连接'
|
||||
|
@ -26,7 +26,7 @@ const logger = pino({
|
||||
});
|
||||
|
||||
export type MessageHandler = (message: VSCodeMessage) => void;
|
||||
const wss = new (WebSocket as any).Server({ port: 8080 });
|
||||
const wss = new (WebSocket as any).Server({ port: 8282 });
|
||||
|
||||
interface IStdioLaunchSignature {
|
||||
type: 'stdio';
|
||||
@ -98,7 +98,7 @@ function updateConnectionOption(data: any) {
|
||||
const devHome = path.join(__dirname, '..', '..');
|
||||
setRunningCWD(devHome);
|
||||
|
||||
wss.on('connection', ws => {
|
||||
wss.on('connection', (ws: any) => {
|
||||
|
||||
// 仿造 webview 进行统一接口访问
|
||||
const webview = new VSCodeWebViewLike(ws);
|
||||
|
@ -37,6 +37,16 @@ export async function connectService(
|
||||
): Promise<RestfulResponse> {
|
||||
try {
|
||||
console.log('ready to connect', option);
|
||||
|
||||
// 对于特殊表示的路径,进行特殊的支持
|
||||
if (option.args) {
|
||||
option.args = option.args.map(arg => {
|
||||
if (arg.startsWith('~/')) {
|
||||
return arg.replace('~', process.env.HOME || '');
|
||||
}
|
||||
return arg;
|
||||
});
|
||||
}
|
||||
|
||||
client = await connect(option);
|
||||
const connectResult = {
|
||||
@ -47,6 +57,10 @@ export async function connectService(
|
||||
return connectResult;
|
||||
} catch (error) {
|
||||
|
||||
console.log('meet error');
|
||||
console.log(error);
|
||||
|
||||
|
||||
// TODO: 这边获取到的 error 不够精致,如何才能获取到更加精准的错误
|
||||
// 比如 error: Failed to spawn: `server.py`
|
||||
// Caused by: No such file or directory (os error 2)
|
||||
|
200
service/src/server.ts
Normal file
200
service/src/server.ts
Normal file
@ -0,0 +1,200 @@
|
||||
import WebSocket from 'ws';
|
||||
import pino from 'pino';
|
||||
|
||||
import { routeMessage } from './common/router';
|
||||
import { VSCodeWebViewLike } from './hook/adapter';
|
||||
import path from 'node:path';
|
||||
import * as fs from 'node:fs';
|
||||
import { setRunningCWD } from './hook/setting';
|
||||
import { exit } from 'node:process';
|
||||
|
||||
export interface VSCodeMessage {
|
||||
command: string;
|
||||
data?: unknown;
|
||||
callbackId?: string;
|
||||
}
|
||||
|
||||
const logger = pino({
|
||||
transport: {
|
||||
target: 'pino-pretty', // 启用 pino-pretty
|
||||
options: {
|
||||
colorize: true, // 开启颜色
|
||||
levelFirst: true, // 先打印日志级别
|
||||
translateTime: 'SYS:yyyy-mm-dd HH:MM:ss', // 格式化时间
|
||||
ignore: 'pid,hostname', // 忽略部分字段
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export type MessageHandler = (message: VSCodeMessage) => void;
|
||||
const wss = new (WebSocket as any).Server({ port: 8282 });
|
||||
|
||||
interface IStdioLaunchSignature {
|
||||
type: 'stdio';
|
||||
commandString: string;
|
||||
cwd: string;
|
||||
}
|
||||
|
||||
interface ISSELaunchSignature {
|
||||
type:'sse';
|
||||
url: string;
|
||||
oauth: string;
|
||||
}
|
||||
|
||||
export type ILaunchSigature = IStdioLaunchSignature | ISSELaunchSignature;
|
||||
|
||||
function refreshConnectionOption(envPath: string) {
|
||||
const defaultOption = {
|
||||
type:'stdio',
|
||||
command: 'mcp',
|
||||
args: ['run', 'main.py'],
|
||||
cwd: '../server'
|
||||
};
|
||||
|
||||
fs.writeFileSync(envPath, JSON.stringify(defaultOption, null, 4));
|
||||
|
||||
return defaultOption;
|
||||
}
|
||||
|
||||
function getInitConnectionOption() {
|
||||
const envPath = path.join(__dirname, '..', '.env');
|
||||
|
||||
if (!fs.existsSync(envPath)) {
|
||||
return refreshConnectionOption(envPath);
|
||||
}
|
||||
|
||||
try {
|
||||
const option = JSON.parse(fs.readFileSync(envPath, 'utf-8'));
|
||||
return option;
|
||||
|
||||
} catch (error) {
|
||||
logger.error('读取 .env 配置文件');
|
||||
return refreshConnectionOption(envPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fs.existsSync(path.join(__dirname, '..', '.env.website.local'))) {
|
||||
console.log('.env.website.local 不存在!');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const authPassword = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '.env.website.local'), 'utf-8')).password;
|
||||
|
||||
function updateConnectionOption(data: any) {
|
||||
const envPath = path.join(__dirname, '..', '.env');
|
||||
|
||||
if (data.connectionType === 'STDIO') {
|
||||
const connectionItem = {
|
||||
type: 'stdio',
|
||||
command: data.command,
|
||||
args: data.args,
|
||||
cwd: data.cwd.replace(/\\/g, '/')
|
||||
};
|
||||
|
||||
fs.writeFileSync(envPath, JSON.stringify(connectionItem, null, 4));
|
||||
} else {
|
||||
const connectionItem = {
|
||||
type: 'sse',
|
||||
url: data.url,
|
||||
oauth: data.oauth
|
||||
};
|
||||
|
||||
fs.writeFileSync(envPath, JSON.stringify(connectionItem, null, 4));
|
||||
}
|
||||
}
|
||||
|
||||
const devHome = path.join(__dirname, '..', '..');
|
||||
setRunningCWD(devHome);
|
||||
|
||||
wss.on('connection', (ws: any) => {
|
||||
|
||||
// 仿造 webview 进行统一接口访问
|
||||
const webview = new VSCodeWebViewLike(ws);
|
||||
|
||||
// 先发送成功建立的消息
|
||||
webview.postMessage({
|
||||
command: 'hello',
|
||||
data: {
|
||||
version: '0.0.1',
|
||||
name: '消息桥连接完成'
|
||||
}
|
||||
});
|
||||
|
||||
const option = getInitConnectionOption();
|
||||
|
||||
// 注册消息接受的管线
|
||||
webview.onDidReceiveMessage(message => {
|
||||
logger.info(`command: [${message.command || 'No Command'}]`);
|
||||
const { command, data, password } = message;
|
||||
|
||||
console.log(command, data);
|
||||
|
||||
|
||||
if (command === 'ciallo') {
|
||||
if (data.password === authPassword) {
|
||||
webview.postMessage({
|
||||
command,
|
||||
data: {
|
||||
code: 200,
|
||||
msg: 'ciallo'
|
||||
}
|
||||
});
|
||||
} else {
|
||||
webview.postMessage({
|
||||
command,
|
||||
data: {
|
||||
code: 403,
|
||||
msg: '没有权限'
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (password !== authPassword) {
|
||||
webview.postMessage({
|
||||
command,
|
||||
data: {
|
||||
code: 403,
|
||||
msg: '没有权限'
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
case 'web/launch-signature':
|
||||
const launchResultMessage: ILaunchSigature = option.type === 'stdio' ?
|
||||
{
|
||||
type: 'stdio',
|
||||
commandString: option.command + ' ' + option.args.join(' '),
|
||||
cwd: option.cwd || ''
|
||||
} :
|
||||
{
|
||||
type: 'sse',
|
||||
url: option.url,
|
||||
oauth: option.oauth || ''
|
||||
};
|
||||
|
||||
const launchResult = {
|
||||
code: 200,
|
||||
msg: launchResultMessage
|
||||
};
|
||||
|
||||
webview.postMessage({
|
||||
command: 'web/launch-signature',
|
||||
data: launchResult
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
case 'web/update-connection-sigature':
|
||||
updateConnectionOption(data);
|
||||
break;
|
||||
|
||||
default:
|
||||
routeMessage(command, data, webview);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
@ -17,7 +17,6 @@ export class SettingController {
|
||||
|
||||
@Controller('setting/load')
|
||||
async loadSetting(client: RequestClientType, data: any, webview: PostMessageble) {
|
||||
console.log('enter loading');
|
||||
|
||||
const config = loadSetting();
|
||||
return {
|
||||
@ -41,7 +40,6 @@ export class SettingController {
|
||||
|
||||
@Controller('setting/get-tour')
|
||||
async getTourController(client: RequestClientType, data: any, webview: PostMessageble) {
|
||||
console.log('enter');
|
||||
|
||||
const { userHasReadGuide } = getTour();
|
||||
|
||||
|
@ -1,175 +0,0 @@
|
||||
{
|
||||
"currentIndex": 2,
|
||||
"tabs": [
|
||||
{
|
||||
"name": "资源",
|
||||
"icon": "icon-file",
|
||||
"type": "blank",
|
||||
"componentIndex": 0,
|
||||
"storage": {
|
||||
"formData": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "工具",
|
||||
"icon": "icon-tool",
|
||||
"type": "blank",
|
||||
"componentIndex": 2,
|
||||
"storage": {
|
||||
"currentToolName": "image_crawler",
|
||||
"formData": {
|
||||
"key_word": "",
|
||||
"image_num": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "交互测试",
|
||||
"icon": "icon-robot",
|
||||
"type": "blank",
|
||||
"componentIndex": 3,
|
||||
"storage": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "帮我找几张 明日方舟 m3 的图片,渲染出来",
|
||||
"extraInfo": {
|
||||
"created": 1745730609368,
|
||||
"state": "success",
|
||||
"serverName": "Huoshan DeepSeek"
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "",
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "call_660r5ehyhh86cjtqnako0mnt",
|
||||
"index": 0,
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "image_crawler",
|
||||
"arguments": "{\"key_word\":\"明日方舟 m3\",\"image_num\":5}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"extraInfo": {
|
||||
"created": 1745730610263,
|
||||
"state": "success",
|
||||
"serverName": "Huoshan DeepSeek"
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "tool",
|
||||
"tool_call_id": "call_660r5ehyhh86cjtqnako0mnt",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[ImageResult(url='https://gd-hbimg.huaban.com/0c97d53a94f333fad66ca70f32601d8c34c2d4db8f53e0-netl2f_fw658', title='', source='bing'), ImageResult(url='https://ts1.tc.mm.bing.net/th/id/R-C.db1a4364345d8b082d4de48cae32ae05?rik=rhE9iKxzhvwzDg', title='', source='bing'), ImageResult(url='https://gd-hbimg.huaban.com/a4b669d3e68da3ee91a12afe7a0bd689038bdc262aece-yasxcI_fw658', title='', source='bing'), ImageResult(url='https://ts1.tc.mm.bing.net/th/id/R-C.d9dc5fcd4b628e805d4b6a0edb0f9a48?rik=RiUbfVRpViaT%2fw', title='', source='bing'), ImageResult(url='https://gd-hbimg.huaban.com/205d12dbf22aec83ff34bd533616575f0939b561136c6-jwF7XH_fw658', title='', source='bing')]"
|
||||
}
|
||||
],
|
||||
"extraInfo": {
|
||||
"created": 1745730610855,
|
||||
"state": "success",
|
||||
"serverName": "Huoshan DeepSeek"
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "以下是根据关键词“明日方舟 m3”找到的图片:\n\n1. \n2. \n3. \n4. \n5. \n\n你可以点击链接查看这些图片。",
|
||||
"extraInfo": {
|
||||
"created": 1745730615968,
|
||||
"state": "success",
|
||||
"serverName": "Huoshan DeepSeek"
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "图源是哪里",
|
||||
"extraInfo": {
|
||||
"created": 1745730806510,
|
||||
"state": "success",
|
||||
"serverName": "Huoshan DeepSeek"
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "这些图片的来源是Bing搜索引擎和Huaban网站。具体来源如下:\n\n1. **Bing**:\n - [Image 2](https://ts1.tc.mm.bing.net/th/id/R-C.db1a4364345d8b082d4de48cae32ae05?rik=rhE9iKxzhvwzDg)\n - [Image 4](https://ts1.tc.mm.bing.net/th/id/R-C.d9dc5fcd4b628e805d4b6a0edb0f9a48?rik=RiUbfVRpViaT%2fw)\n\n2. **Huaban**:\n - [Image 1](https://gd-hbimg.huaban.com/0c97d53a94f333fad66ca70f32601d8c34c2d4db8f53e0-netl2f_fw658)\n - [Image 3](https://gd-hbimg.huaban.com/a4b669d3e68da3ee91a12afe7a0bd689038bdc262aece-yasxcI_fw658)\n - [Image 5](https://gd-hbimg.huaban.com/205d12dbf22aec83ff34bd533616575f0939b561136c6-jwF7XH_fw658)\n\n你可以通过点击链接查看图片的详细信息。",
|
||||
"extraInfo": {
|
||||
"created": 1745730812395,
|
||||
"state": "success",
|
||||
"serverName": "Huoshan DeepSeek"
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "帮我找几张 明日方舟 白面鸮 的图片,渲染出来",
|
||||
"extraInfo": {
|
||||
"created": 1745730909927,
|
||||
"state": "success",
|
||||
"serverName": "Huoshan DeepSeek"
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "",
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "call_ho74cop478w5gbfc0jnuo12f",
|
||||
"index": 0,
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "image_crawler",
|
||||
"arguments": "{\"key_word\":\"明日方舟 白面鸮\",\"image_num\":5}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"extraInfo": {
|
||||
"created": 1745730910906,
|
||||
"state": "success",
|
||||
"serverName": "Huoshan DeepSeek"
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "tool",
|
||||
"tool_call_id": "call_ho74cop478w5gbfc0jnuo12f",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "[ImageResult(url='https://c-ssl.duitang.com/uploads/item/201910/22/20191022190241_dixsc.thumb.1000_0.jpg', title='', source='bing'), ImageResult(url='https://img-baofun.zhhainiao.com/pcwallpaper_ugc_mobile/live/e06866505212ddcce0dabf9afebce225.mp4.jpg', title='', source='bing'), ImageResult(url='https://c-ssl.dtstatic.com/uploads/item/202007/15/20200715183732_iomsj.thumb.1000_0.jpg', title='', source='bing'), ImageResult(url='https://img-baofun.zhhainiao.com/pcwallpaper_ugc_mobile/live/710b67dfa125248f816d63617f551452_preview.jpg', title='', source='bing'), ImageResult(url='https://n.sinaimg.cn/sinacn10122/670/w400h270/20200104/db75-imrkkfx7540303.jpg', title='', source='bing')]"
|
||||
}
|
||||
],
|
||||
"extraInfo": {
|
||||
"created": 1745730911376,
|
||||
"state": "success",
|
||||
"serverName": "Huoshan DeepSeek"
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "以下是根据关键词“明日方舟 白面鸮”找到的图片:\n\n1. \n2. \n3. \n4. \n5. \n\n你可以点击链接查看这些图片。",
|
||||
"extraInfo": {
|
||||
"created": 1745730916072,
|
||||
"state": "success",
|
||||
"serverName": "Huoshan DeepSeek"
|
||||
}
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"modelIndex": 8,
|
||||
"enableTools": [
|
||||
{
|
||||
"name": "image_crawler",
|
||||
"description": "根据关键词从指定搜索引擎爬取图片",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"enableWebSearch": false,
|
||||
"temperature": 0.7,
|
||||
"contextLength": 10,
|
||||
"systemPrompt": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
58
service/tabs.my-browser.json
Normal file
58
service/tabs.my-browser.json
Normal file
@ -0,0 +1,58 @@
|
||||
{
|
||||
"currentIndex": 0,
|
||||
"tabs": [
|
||||
{
|
||||
"name": "交互测试",
|
||||
"icon": "icon-robot",
|
||||
"type": "blank",
|
||||
"componentIndex": 3,
|
||||
"storage": {
|
||||
"messages": [],
|
||||
"settings": {
|
||||
"modelIndex": 7,
|
||||
"enableTools": [
|
||||
{
|
||||
"name": "k_navigate",
|
||||
"description": "Navigate to a URL",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "k_screenshot",
|
||||
"description": "Take a screenshot of the current page or a specific element",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "k_click",
|
||||
"description": "Click an element on the page",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "k_fill",
|
||||
"description": "Fill out an input field",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "k_select",
|
||||
"description": "Select an element on the page with Select tag",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "k_hover",
|
||||
"description": "Hover an element on the page",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "k_evaluate",
|
||||
"description": "Execute JavaScript in the browser console",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"enableWebSearch": false,
|
||||
"temperature": 0.7,
|
||||
"contextLength": 20,
|
||||
"systemPrompt": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"currentIndex": 0,
|
||||
"tabs": [
|
||||
{
|
||||
"name": "Blank test 1",
|
||||
"icon": "icon-blank",
|
||||
"type": "blank",
|
||||
"componentIndex": -1,
|
||||
"storage": {}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
{
|
||||
"currentIndex": 0,
|
||||
"tabs": [
|
||||
{
|
||||
"name": "资源",
|
||||
"icon": "icon-file",
|
||||
"type": "blank",
|
||||
"componentIndex": 0,
|
||||
"storage": {
|
||||
"formData": {},
|
||||
"currentType": "resource",
|
||||
"currentResourceName": "network_log",
|
||||
"lastResourceReadResponse": {
|
||||
"contents": [
|
||||
{
|
||||
"uri": "network://log",
|
||||
"mimeType": "text/plain",
|
||||
"text": "Response from ..."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "工具",
|
||||
"icon": "icon-tool",
|
||||
"type": "blank",
|
||||
"componentIndex": 2,
|
||||
"storage": {
|
||||
"formData": {
|
||||
"a": 0,
|
||||
"b": 0
|
||||
},
|
||||
"currentToolName": "add"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: './src/index.ts',
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'bundle.js',
|
||||
libraryTarget: 'commonjs2' // 使用 commonjs2 模块系统
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js'],
|
||||
fallback: {
|
||||
bufferutil: false,
|
||||
'utf-8-validate': false
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
exclude: /node_modules/,
|
||||
use: 'ts-loader'
|
||||
}
|
||||
]
|
||||
},
|
||||
target: 'node', // 指定目标环境为 Node.js
|
||||
mode: 'production',
|
||||
optimization: {
|
||||
minimize: true
|
||||
}
|
||||
};
|
@ -109,7 +109,7 @@ export async function acquireInstalledConnection(): Promise<IConnectionItem | un
|
||||
// 获取 url
|
||||
const url = await vscode.window.showInputBox({
|
||||
prompt: '请输入连接的 URL',
|
||||
placeHolder: '例如: https://127.0.0.1:8080'
|
||||
placeHolder: '例如: https://127.0.0.1:8282'
|
||||
});
|
||||
|
||||
if (!url) {
|
||||
|
@ -59,7 +59,7 @@ export async function acquireUserCustomConnection(): Promise<IConnectionItem | u
|
||||
// 获取 url
|
||||
const url = await vscode.window.showInputBox({
|
||||
prompt: '请输入连接的 URL',
|
||||
placeHolder: '例如: https://127.0.0.1:8080'
|
||||
placeHolder: '例如: https://127.0.0.1:8282'
|
||||
});
|
||||
|
||||
if (!url) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
const path = require('path');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const webpack = require('webpack');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
mode: 'development', // 设置为 development 模式
|
||||
@ -34,10 +35,15 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
optimization: {
|
||||
minimize: false, // 禁用代码压缩
|
||||
minimize: true, // Enable code compression
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
extractComments: false, // 禁用提取许可证文件
|
||||
extractComments: false, // Disable extracting license files
|
||||
terserOptions: {
|
||||
compress: {
|
||||
drop_console: true, // Remove all console.* calls
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
@ -53,9 +59,17 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
}),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: path.resolve(__dirname, '../resources/openmcp-sdk-release'),
|
||||
to: path.resolve(__dirname, '../openmcp-sdk')
|
||||
}
|
||||
]
|
||||
})
|
||||
],
|
||||
externals: {
|
||||
vue: 'vue', // 不打包 vue 库
|
||||
'element-plus': './tool.js'
|
||||
'element-plus': './tools.js'
|
||||
},
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user