diff --git a/package-lock.json b/package-lock.json index 0247b63..e773f77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2183,34 +2183,6 @@ "node": ">= 10" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "license": "MIT" - }, "node_modules/@tsconfig/node22": { "version": "22.0.1", "resolved": "https://registry.npmjs.org/@tsconfig/node22/-/node22-22.0.1.tgz", @@ -2527,20 +2499,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/verror": { "version": "1.10.11", "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", @@ -3362,19 +3320,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -3481,33 +3426,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/app-builder-bin": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", @@ -3673,13 +3591,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT" - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -3820,19 +3731,6 @@ "node": "*" } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/birpc": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.3.0.tgz", @@ -4072,7 +3970,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "dev": true, "license": "MIT", "dependencies": { "run-applescript": "^7.0.0" @@ -4816,7 +4713,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "dev": true, "license": "MIT", "dependencies": { "bundle-name": "^4.1.0", @@ -4833,7 +4729,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -4873,7 +4768,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -4927,16 +4821,6 @@ "license": "MIT", "optional": true }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/dir-compare": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", @@ -5050,16 +4934,6 @@ "node": ">= 0.4" } }, - "node_modules/dynamic-dedupe": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", - "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -6599,6 +6473,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -7109,19 +6996,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -7167,7 +7041,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, "license": "MIT", "bin": { "is-docker": "cli.js" @@ -7234,7 +7107,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, "license": "MIT", "dependencies": { "is-docker": "^3.0.0" @@ -7373,7 +7245,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, "license": "MIT", "dependencies": { "is-inside-container": "^1.0.0" @@ -7849,13 +7720,6 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "license": "ISC" - }, "node_modules/markdown-it": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", @@ -8562,7 +8426,6 @@ "version": "10.1.2", "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", "integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==", - "dev": true, "license": "MIT", "dependencies": { "default-browser": "^5.2.1", @@ -9429,6 +9292,16 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/responselike": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", @@ -9459,20 +9332,6 @@ "dev": true, "license": "MIT" }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/roarr": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", @@ -9552,7 +9411,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -10452,16 +10310,6 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "license": "MIT", - "bin": { - "tree-kill": "cli.js" - } - }, "node_modules/truncate-utf8-bytes": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", @@ -10506,170 +10354,39 @@ "node": ">=10" } }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, "license": "MIT", "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-node-dev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", - "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^3.5.1", - "dynamic-dedupe": "^0.3.0", + "json5": "^2.2.2", "minimist": "^1.2.6", - "mkdirp": "^1.0.4", - "resolve": "^1.0.0", - "rimraf": "^2.6.1", - "source-map-support": "^0.5.12", - "tree-kill": "^1.2.2", - "ts-node": "^10.4.0", - "tsconfig": "^7.0.0" - }, - "bin": { - "ts-node-dev": "lib/bin.js", - "tsnd": "lib/bin.js" + "strip-bom": "^3.0.0" }, "engines": { - "node": ">=0.8.0" - }, - "peerDependencies": { - "node-notifier": "*", - "typescript": "*" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=6" } }, - "node_modules/ts-node-dev/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/tsx": { + "version": "4.19.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.4.tgz", + "integrity": "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==", "dev": true, "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" }, "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=18.0.0" }, "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/ts-node-dev/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ts-node-dev/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/ts-node-dev/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/tsconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", - "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/strip-bom": "^3.0.0", - "@types/strip-json-comments": "0.0.30", - "strip-bom": "^3.0.0", - "strip-json-comments": "^2.0.0" - } - }, - "node_modules/tsconfig/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "fsevents": "~2.3.3" } }, "node_modules/turbo": { @@ -10942,13 +10659,6 @@ "uuid": "dist/esm/bin/uuid" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "license": "MIT" - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -11384,16 +11094,6 @@ "node": ">=8.0" } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -11451,16 +11151,6 @@ "fd-slicer": "~1.1.0" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/yoctocolors": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", @@ -11830,6 +11520,7 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.12.1", "@seald-io/nedb": "^4.1.1", + "open": "^10.1.2", "axios": "^1.9.0", "openai": "^5.0.1", "pako": "^2.1.0", @@ -11848,9 +11539,9 @@ "@types/pako": "^2.0.3", "@types/ws": "^8.18.0", "esbuild": "^0.25.3", - "ts-node": "^10.9.2", - "ts-node-dev": "^2.0.0", - "typescript": "^5.6.3", + "tsconfig-paths": "^4.2.0", + "tsx": "^4.19.4", + "typescript": "^5.8.3", "webpack-cli": "^6.0.1", "webpack-node-externals": "^3.0.0" } diff --git a/service/package.json b/service/package.json index 0c3c624..7f1f46f 100644 --- a/service/package.json +++ b/service/package.json @@ -4,16 +4,15 @@ "description": "", "main": "dist/index.js", "types": "dist/index.d.ts", - "type": "commonjs", + "type": "module", "scripts": { - "dev": "ts-node-dev --respawn --transpile-only src/main.ts", - "serve": "ts-node-dev --respawn --transpile-only src/main.ts", + "serve": "tsx watch src/main.ts", "build": "tsc", "build:watch": "tsc --watch", "postbuild": "node ./scripts/post-build.mjs", - "start": "node dist/main.js", - "start:prod": "NODE_ENV=production node dist/main.js", - "debug": "node --inspect -r ts-node/register src/main.ts", + "start": "node --experimental-specifier-resolution=node dist/main.js", + "start:prod": "NODE_ENV=production node --experimental-specifier-resolution=node dist/main.js", + "debug": "node --inspect --no-warnings=ExperimentalWarning -r tsx/esm src/main.ts", "clean": "rm -rf dist", "lint": "eslint src --ext .ts,.tsx", "typecheck": "tsc --noEmit" @@ -29,15 +28,16 @@ "@types/pako": "^2.0.3", "@types/ws": "^8.18.0", "esbuild": "^0.25.3", - "ts-node": "^10.9.2", - "ts-node-dev": "^2.0.0", - "typescript": "^5.6.3", + "tsconfig-paths": "^4.2.0", + "tsx": "^4.19.4", + "typescript": "^5.8.3", "webpack-cli": "^6.0.1", "webpack-node-externals": "^3.0.0" }, "dependencies": { "@modelcontextprotocol/sdk": "^1.12.1", "@seald-io/nedb": "^4.1.1", + "open": "^10.1.2", "axios": "^1.9.0", "openai": "^5.0.1", "pako": "^2.1.0", diff --git a/service/src/common/index.dto.ts b/service/src/common/index.dto.ts index 9d302f7..03c57b0 100644 --- a/service/src/common/index.dto.ts +++ b/service/src/common/index.dto.ts @@ -1,5 +1,5 @@ -import { PostMessageble } from "../hook/adapter"; -import { McpClient } from "../mcp/client.service"; +import { PostMessageble } from "../hook/adapter.js"; +import { McpClient } from "../mcp/client.service.js"; export type RequestClientType = McpClient | undefined; diff --git a/service/src/common/index.ts b/service/src/common/index.ts index 67dc21a..66af1c2 100644 --- a/service/src/common/index.ts +++ b/service/src/common/index.ts @@ -1,5 +1,4 @@ -import { MapperDescriptor, RequestHandler, RequestClientType, RestfulResponse, ControllerOption, RequestHandlerStore } from "./index.dto"; -export { MapperDescriptor, RequestHandler, RequestClientType }; +import { MapperDescriptor, RestfulResponse, ControllerOption, RequestHandlerStore } from "./index.dto.js"; export const requestHandlerStorage = new Map>(); diff --git a/service/src/common/router.ts b/service/src/common/router.ts index 630e037..54da9b5 100644 --- a/service/src/common/router.ts +++ b/service/src/common/router.ts @@ -1,11 +1,11 @@ -import { requestHandlerStorage } from "."; -import type { PostMessageble } from "../hook/adapter"; -import { LlmController } from "../llm/llm.controller"; -import { ClientController } from "../mcp/client.controller"; -import { ConnectController } from "../mcp/connect.controller"; -import { OcrController } from "../mcp/ocr.controller"; -import { PanelController } from "../panel/panel.controller"; -import { SettingController } from "../setting/setting.controller"; +import { requestHandlerStorage } from "./index.js"; +import type { PostMessageble } from "../hook/adapter.js"; +import { LlmController } from "../llm/llm.controller.js"; +import { ClientController } from "../mcp/client.controller.js"; +import { ConnectController } from "../mcp/connect.controller.js"; +import { OcrController } from "../mcp/ocr.controller.js"; +import { PanelController } from "../panel/panel.controller.js"; +import { SettingController } from "../setting/setting.controller.js"; export const ModuleControllers = [ ConnectController, diff --git a/service/src/hook/adapter.ts b/service/src/hook/adapter.ts index 825625e..b78d3d3 100644 --- a/service/src/hook/adapter.ts +++ b/service/src/hook/adapter.ts @@ -1,8 +1,8 @@ import { WebSocket } from 'ws'; import { EventEmitter } from 'events'; -import { routeMessage } from '../common/router'; -import { McpOptions } from '../mcp/client.dto'; -import { clientMap, connectService } from '../mcp/connect.service'; +import { routeMessage } from '../common/router.js'; +import { McpOptions } from '../mcp/client.dto.js'; +import { clientMap, connectService } from '../mcp/connect.service.js'; // WebSocket 消息格式 export interface WebSocketMessage { @@ -136,7 +136,7 @@ export class TaskLoopAdapter { for (const client of clientMap.values()) { const clientTools = await client?.listTools(); if (clientTools?.tools) { - const enabledTools = clientTools.tools.map((tool) => { + const enabledTools = clientTools.tools.map((tool: any) => { const enabledTools = {...tool, enabled: true }; return enabledTools; }); diff --git a/service/src/hook/db.ts b/service/src/hook/db.ts index a233196..8e79fe6 100644 --- a/service/src/hook/db.ts +++ b/service/src/hook/db.ts @@ -9,6 +9,7 @@ interface Entity { } const dbConnections: Record = {}; +const DatastoreCtor = Datastore as unknown as { new(options: any): any }; export class LocalDB { private db: any; @@ -28,7 +29,7 @@ export class LocalDB { const filename = path.join(dbPath, `${this.tableName}.db`); if (!dbConnections[filename]) { - dbConnections[filename] = new Datastore({ + dbConnections[filename] = new DatastoreCtor({ filename, autoload: true, timestampData: true diff --git a/service/src/index.ts b/service/src/index.ts index 900dcba..038cd47 100644 --- a/service/src/index.ts +++ b/service/src/index.ts @@ -1,5 +1,5 @@ -export { routeMessage } from './common/router'; -export { VSCodeWebViewLike, TaskLoopAdapter } from './hook/adapter'; -export { setVscodeWorkspace, setRunningCWD } from './hook/setting'; +export { routeMessage } from './common/router.js'; +export { VSCodeWebViewLike, TaskLoopAdapter } from './hook/adapter.js'; +export { setVscodeWorkspace, setRunningCWD } from './hook/setting.js'; // TODO: 更加规范 -export { clientMap } from './mcp/connect.service'; \ No newline at end of file +export { clientMap } from './mcp/connect.service.js'; \ No newline at end of file diff --git a/service/src/llm/llm.controller.ts b/service/src/llm/llm.controller.ts index ccd94f2..3958248 100644 --- a/service/src/llm/llm.controller.ts +++ b/service/src/llm/llm.controller.ts @@ -1,9 +1,10 @@ +import { RequestClientType } from "../common/index.dto.js"; +import { Controller } from "../common/index.js"; +import { RequestData } from "../common/index.dto.js"; +import { PostMessageble } from "../hook/adapter.js"; +import { getClient } from "../mcp/connect.service.js"; +import { abortMessageService, streamingChatCompletion } from "./llm.service.js"; import { OpenAI } from "openai"; -import { Controller } from "../common"; -import { RequestData } from "../common/index.dto"; -import { PostMessageble } from "../hook/adapter"; -import { abortMessageService, streamingChatCompletion } from "./llm.service"; - export class LlmController { @Controller('llm/chat/completions') diff --git a/service/src/llm/llm.service.ts b/service/src/llm/llm.service.ts index 695612a..d2366d9 100644 --- a/service/src/llm/llm.service.ts +++ b/service/src/llm/llm.service.ts @@ -1,11 +1,11 @@ -import { PostMessageble } from "../hook/adapter"; +import { PostMessageble } from "../hook/adapter.js"; import { OpenAI } from "openai"; -import { MyMessageType, MyToolMessageType } from "./llm.dto"; -import { RestfulResponse } from "../common/index.dto"; -import { ocrDB } from "../hook/db"; -import type { ToolCallContent } from "../mcp/client.dto"; -import { ocrWorkerStorage } from "../mcp/ocr.service"; -import { axiosFetch } from "../hook/axios-fetch"; +import { MyMessageType, MyToolMessageType } from "./llm.dto.js"; +import { RestfulResponse } from "../common/index.dto.js"; +import { ocrDB } from "../hook/db.js"; +import type { ToolCallContent } from "../mcp/client.dto.js"; +import { ocrWorkerStorage } from "../mcp/ocr.service.js"; +import { axiosFetch } from "../hook/axios-fetch.js"; export let currentStream: AsyncIterable | null = null; diff --git a/service/src/main.ts b/service/src/main.ts index 54c9a09..5063957 100644 --- a/service/src/main.ts +++ b/service/src/main.ts @@ -1,11 +1,12 @@ import { WebSocketServer } from 'ws'; -import pino from 'pino'; - -import { routeMessage } from './common/router'; -import { VSCodeWebViewLike } from './hook/adapter'; +import {pino} from 'pino'; +import { fileURLToPath } from 'url'; +import { dirname } from 'path'; +import { routeMessage } from './common/router.js'; +import { VSCodeWebViewLike } from './hook/adapter.js'; import path from 'node:path'; import * as fs from 'node:fs'; -import { setRunningCWD } from './hook/setting'; +import { setRunningCWD } from './hook/setting.js'; import axios from 'axios'; export interface VSCodeMessage { @@ -85,7 +86,7 @@ function updateConnectionOption(data: any) { fs.writeFileSync(envPath, JSON.stringify(connection, null, 4)); } - +const __dirname = dirname(fileURLToPath(import.meta.url)); const devHome = path.join(__dirname, '..', '..'); setRunningCWD(devHome); diff --git a/service/src/mcp/auth.service.ts b/service/src/mcp/auth.service.ts new file mode 100644 index 0000000..0bdc631 --- /dev/null +++ b/service/src/mcp/auth.service.ts @@ -0,0 +1,186 @@ +import { createServer } from 'node:http'; +import { URL } from 'node:url'; +import { OAuthClientInformation, OAuthClientInformationFull, OAuthClientMetadata, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js'; +import { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js'; +import open from 'open'; + +// const CALLBACK_PORT = 16203; // Use different port than auth server (3001) +// const CALLBACK_URL = `http://localhost:${CALLBACK_PORT}/callback`; + +/** + * @description 内存中的OAuth客户端提供者 + */ +class InMemoryOAuthClientProvider implements OAuthClientProvider { + private _clientInformation?: OAuthClientInformationFull; + private _tokens?: OAuthTokens; + private _codeVerifier?: string; + + constructor( + private readonly _redirectUrl: string | URL, + private readonly _clientMetadata: OAuthClientMetadata, + onRedirect?: (url: URL) => void + ) { + this._onRedirect = onRedirect || ((url) => { + console.log(`Redirect to: ${url.toString()}`); + }); + } + + private _onRedirect: (url: URL) => void; + + get redirectUrl(): string | URL { + return this._redirectUrl; + } + + get clientMetadata(): OAuthClientMetadata { + return this._clientMetadata; + } + + clientInformation(): OAuthClientInformation | undefined { + return this._clientInformation; + } + + saveClientInformation(clientInformation: OAuthClientInformationFull): void { + this._clientInformation = clientInformation; + } + + tokens(): OAuthTokens | undefined { + return this._tokens; + } + + saveTokens(tokens: OAuthTokens): void { + this._tokens = tokens; + } + + redirectToAuthorization(authorizationUrl: URL): void { + this._onRedirect(authorizationUrl); + } + + saveCodeVerifier(codeVerifier: string): void { + this._codeVerifier = codeVerifier; + } + + codeVerifier(): string { + if (!this._codeVerifier) { + throw new Error('No code verifier saved'); + } + return this._codeVerifier; + } +} + + +export class OAuthClient { + port: number; + callbackUrl: string; + + constructor() { + console.log('🔐 Initializing OAuth client...'); + // 初始化OAuth客户端 + this.port = Math.floor(Math.random() * (50000 - 40000 + 1)) + 40000; + //TODO: 如果端口被占用,重新生成一个端口 + this.callbackUrl = `http://localhost:${this.port}/callback`; + + } + /** + * @description 开启本地服务器上,并监听OAuth回调请求,并解析授权码或错误信息 + * @returns {Promise} 返回授权码 + * @throws {Error} 如果没有收到授权码或发生错误 + */ + + public async waitForOAuthCallback(): Promise { + return new Promise((resolve, reject) => { + const server = createServer((req, res) => { + // Ignore favicon requests + if (req.url === '/favicon.ico') { + res.writeHead(404); + res.end(); + return; + } + + console.log(`📥 Received callback: ${req.url}`); + const parsedUrl = new URL(req.url || '', 'http://localhost'); + const code = parsedUrl.searchParams.get('code'); + const error = parsedUrl.searchParams.get('error'); + + if (code) { + console.log(`✅ Authorization code received: ${code?.substring(0, 10)}...`); + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end(` + + +

Authorization Successful!

+

You can close this window and return to the terminal.

+ + + + `); + + resolve(code); + setTimeout(() => server.close(), 3000); + } else if (error) { + console.log(`❌ Authorization error: ${error}`); + res.writeHead(400, { 'Content-Type': 'text/html' }); + res.end(` + + +

Authorization Failed

+

Error: ${error}

+ + + `); + reject(new Error(`OAuth authorization failed: ${error}`)); + } else { + console.log(`❌ No authorization code or error in callback`); + res.writeHead(400); + res.end('Bad request'); + reject(new Error('No authorization code provided')); + } + }); + + server.listen(this.port, () => { + console.log(`OAuth callback server started on http://localhost:${this.port}`); + }); + }); + } + + + + /** + * @description 获取Oauth认证provider + * @return {Promise} 返回一个OAuthClientProvider实例 + */ + public async getOAuthProvider(): Promise { + + const clientMetadata: OAuthClientMetadata = { + client_name: 'Simple OAuth MCP Client', + redirect_uris: [this.callbackUrl], + grant_types: ['authorization_code', 'refresh_token'], + response_types: ['code'], + token_endpoint_auth_method: 'none', + }; + + console.log('🔐 Creating OAuth provider...'); + const oauthProvider = new InMemoryOAuthClientProvider( + this.callbackUrl, + clientMetadata, + (redirectUrl: URL) => { + console.log(`📌 OAuth redirect handler called - opening browser`); + console.log(`Opening browser to: ${redirectUrl.toString()}`); + this.openBrowser(redirectUrl.toString()); + } + ); + console.log('🔐 OAuth provider created'); + return oauthProvider; + } + + /** + * @description 打开浏览器 + * @param url 授权URL + */ + + public async openBrowser(url: string): Promise { + console.log(`🌐 Opening browser for authorization: ${url}`); + await open(url); // 自动适配不同操作系统 + } +} + + diff --git a/service/src/mcp/client.controller.ts b/service/src/mcp/client.controller.ts index 19efaf7..06dd877 100644 --- a/service/src/mcp/client.controller.ts +++ b/service/src/mcp/client.controller.ts @@ -1,8 +1,8 @@ -import { Controller } from "../common"; -import { RequestData } from "../common/index.dto"; -import { PostMessageble } from "../hook/adapter"; -import { postProcessMcpToolcallResponse } from "./client.service"; -import { getClient } from "./connect.service"; +import { Controller } from "../common/index.js"; +import { RequestData } from "../common/index.dto.js"; +import { PostMessageble } from "../hook/adapter.js"; +import { postProcessMcpToolcallResponse } from "./client.service.js"; +import { getClient } from "./connect.service.js"; export class ClientController { diff --git a/service/src/mcp/client.dto.ts b/service/src/mcp/client.dto.ts index cd30ce0..4f2764c 100644 --- a/service/src/mcp/client.dto.ts +++ b/service/src/mcp/client.dto.ts @@ -1,7 +1,7 @@ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"; import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; -import { Implementation } from "@modelcontextprotocol/sdk/types"; +import { Implementation } from "@modelcontextprotocol/sdk/types.js"; export interface GetPromptOption { promptId: string; diff --git a/service/src/mcp/client.service.ts b/service/src/mcp/client.service.ts index 0fd6661..7e9c736 100644 --- a/service/src/mcp/client.service.ts +++ b/service/src/mcp/client.service.ts @@ -3,16 +3,20 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"; import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; -import type { McpOptions, McpTransport, IServerVersion, ToolCallResponse, ToolCallContent } from './client.dto'; -import { PostMessageble } from "../hook/adapter"; -import { createOcrWorker, saveBase64ImageData } from "./ocr.service"; - +import type { McpOptions, McpTransport, IServerVersion, ToolCallResponse, ToolCallContent } from './client.dto.js'; +import { PostMessageble } from "../hook/adapter.js"; +import { createOcrWorker, saveBase64ImageData } from "./ocr.service.js"; +import { OAuthClient } from "./auth.service.js"; +import { UnauthorizedError } from '@modelcontextprotocol/sdk/client/auth.js'; +import { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js'; // 增强的客户端类 export class McpClient { private client: Client; private transport?: McpTransport; private options: McpOptions; private serverVersion: IServerVersion; + private oAuthClient: OAuthClient; + private oauthPovider?: OAuthClientProvider; constructor(options: McpOptions) { this.options = options; @@ -31,14 +35,18 @@ export class McpClient { } } ); + + this.oAuthClient = new OAuthClient(); } // 连接方法 public async connect(): Promise { - + if (!this.oauthPovider){ + this.oauthPovider = await this.oAuthClient.getOAuthProvider(); + } // 根据连接类型创建传输层 switch (this.options.connectionType) { - case 'STDIO': + case 'STDIO': this.transport = new StdioClientTransport({ command: this.options.command || '', args: this.options.args || [], @@ -55,20 +63,22 @@ export class McpClient { this.transport = new SSEClientTransport( new URL(this.options.url), { - // authProvider: + authProvider: this.oauthPovider } ); break; - + case 'STREAMABLE_HTTP': if (!this.options.url) { throw new Error('URL is required for STREAMABLE_HTTP connection'); } this.transport = new StreamableHTTPClientTransport( - new URL(this.options.url) + new URL(this.options.url), + { + authProvider:this.oauthPovider + } ); - break; default: throw new Error(`Unsupported connection type: ${this.options.connectionType}`); @@ -76,11 +86,32 @@ export class McpClient { // 建立连接 if (this.transport) { - await this.client.connect(this.transport); - console.log(`Connected to MCP server via ${this.options.connectionType}`); + try { + console.log(`🔌 Connecting to MCP server via ${this.options.connectionType}...`); + await this.client.connect(this.transport); + console.log(`Connected to MCP server via ${this.options.connectionType}`); + } catch (error) { + if (error instanceof UnauthorizedError) { + if (!(this.transport instanceof StreamableHTTPClientTransport) && !(this.transport instanceof SSEClientTransport)) { + console.error('❌ OAuth is only supported for StreamableHTTP and SSE transports. Please use one of these transports for OAuth authentication.'); + return; + } + console.log('🔐 OAuth required - waiting for authorization...'); + const callbackPromise = this.oAuthClient.waitForOAuthCallback(); + const authCode = await callbackPromise; + await this.transport.finishAuth(authCode); + console.log('🔐 Authorization code received:', authCode); + console.log('🔌 Reconnecting with authenticated transport...'); + await this.connect(); // 递归重试 + } else { + console.error('❌ Connection failed with non-auth error:', error); + throw error; + } + } } } + public getServerVersion() { if (this.serverVersion) { return this.serverVersion; @@ -94,7 +125,7 @@ export class McpClient { // 断开连接 public async disconnect(): Promise { await this.client.close(); - + console.log('Disconnected from MCP server'); } @@ -104,7 +135,7 @@ export class McpClient { } // 获取提示 - public async getPrompt(name: string, args: Record = {}) { + public async getPrompt(name: string, args: Record = {}) { return await this.client.getPrompt({ name, arguments: args }); @@ -136,7 +167,6 @@ export class McpClient { public async callTool(options: { name: string; arguments: Record, callToolOption?: any }) { const { callToolOption, ...methodArgs } = options; const res = await this.client.callTool(methodArgs, undefined, callToolOption); - return res; } } @@ -155,10 +185,10 @@ async function handleImage( if (content.data && content.mimeType) { const filename = saveBase64ImageData(content.data, content.mimeType); content.data = filename; - + // 加入工作线程 const worker = createOcrWorker(filename, webview); - + content._meta = { ocr: true, workerId: worker.id @@ -189,7 +219,7 @@ export function postProcessMcpToolcallResponse( case 'image': handleImage(content, webview); break; - + default: break; } diff --git a/service/src/mcp/connect.controller.ts b/service/src/mcp/connect.controller.ts index 3b2906b..35af81e 100644 --- a/service/src/mcp/connect.controller.ts +++ b/service/src/mcp/connect.controller.ts @@ -1,7 +1,7 @@ -import { Controller } from '../common'; -import { PostMessageble } from '../hook/adapter'; -import { RequestData } from '../common/index.dto'; -import { connectService, getClient } from './connect.service'; +import { Controller } from '../common/index.js'; +import { PostMessageble } from '../hook/adapter.js'; +import { RequestData } from '../common/index.dto.js'; +import { connectService, getClient } from './connect.service.js'; export class ConnectController { diff --git a/service/src/mcp/connect.service.ts b/service/src/mcp/connect.service.ts index 01cf3a4..372b76c 100644 --- a/service/src/mcp/connect.service.ts +++ b/service/src/mcp/connect.service.ts @@ -1,13 +1,13 @@ import { exec, execSync, spawnSync } from 'node:child_process'; -import { RequestClientType } from '../common'; -import { connect } from './client.service'; -import { RestfulResponse } from '../common/index.dto'; -import { McpOptions } from './client.dto'; +import { RequestClientType } from '../common/index.dto.js'; +import { connect } from './client.service.js'; +import { RestfulResponse } from '../common/index.dto.js'; +import { McpOptions } from './client.dto.js'; import * as crypto from 'node:crypto'; import path from 'node:path'; import fs from 'node:fs'; import * as os from 'os'; -import { PostMessageble } from '../hook/adapter'; +import { PostMessageble } from '../hook/adapter.js'; export const clientMap: Map = new Map(); export function getClient(clientId?: string): RequestClientType | undefined { diff --git a/service/src/mcp/ocr.controller.ts b/service/src/mcp/ocr.controller.ts index 6a997bd..d762ecf 100644 --- a/service/src/mcp/ocr.controller.ts +++ b/service/src/mcp/ocr.controller.ts @@ -1,7 +1,8 @@ -import { Controller, RequestClientType } from "../common"; -import { PostMessageble } from "../hook/adapter"; -import { diskStorage } from "../hook/db"; -import { createOcrWorker, saveBase64ImageData } from "./ocr.service"; +import { RequestClientType } from "../common/index.dto.js"; +import { Controller } from "../common/index.js"; +import { PostMessageble } from "../hook/adapter.js"; +import { diskStorage } from "../hook/db.js"; +import { createOcrWorker, saveBase64ImageData } from "./ocr.service.js"; export class OcrController { @Controller('ocr/get-ocr-image') diff --git a/service/src/mcp/ocr.service.ts b/service/src/mcp/ocr.service.ts index 91225ce..48dad82 100644 --- a/service/src/mcp/ocr.service.ts +++ b/service/src/mcp/ocr.service.ts @@ -1,12 +1,12 @@ import Tesseract from 'tesseract.js'; -import { PostMessageble } from '../hook/adapter'; +import { PostMessageble } from '../hook/adapter.js'; import { v4 as uuidv4 } from 'uuid'; -import { OcrWorker } from './ocr.dto'; -import { diskStorage, ocrDB } from '../hook/db'; +import { OcrWorker } from './ocr.dto.js'; +import { diskStorage, ocrDB } from '../hook/db.js'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; -import { RUNNING_CWD } from '../hook/setting'; +import { RUNNING_CWD } from '../hook/setting.js'; export const ocrWorkerStorage = new Map(); diff --git a/service/src/panel/panel.controller.ts b/service/src/panel/panel.controller.ts index 7b7321d..5fe918e 100644 --- a/service/src/panel/panel.controller.ts +++ b/service/src/panel/panel.controller.ts @@ -1,9 +1,9 @@ -import { Controller } from "../common"; -import { PostMessageble } from "../hook/adapter"; -import { RequestData } from "../common/index.dto"; -import { getClient } from "../mcp/connect.service"; -import { systemPromptDB } from "../hook/db"; -import { loadTabSaveConfig, saveTabSaveConfig } from "./panel.service"; +import { Controller } from "../common/index.js"; +import { PostMessageble } from "../hook/adapter.js"; +import { RequestData } from "../common/index.dto.js"; +import { getClient } from "../mcp/connect.service.js"; +import { systemPromptDB } from "../hook/db.js"; +import { loadTabSaveConfig, saveTabSaveConfig } from "./panel.service.js"; export class PanelController { @Controller('panel/save') diff --git a/service/src/panel/panel.service.ts b/service/src/panel/panel.service.ts index 7d41096..5d12b59 100644 --- a/service/src/panel/panel.service.ts +++ b/service/src/panel/panel.service.ts @@ -1,9 +1,9 @@ import * as fs from 'fs'; import * as path from 'path'; -import { VSCODE_WORKSPACE } from '../hook/setting'; -import { IServerVersion } from '../mcp/client.dto'; -import { SaveTab } from './panel.dto'; -import { IConfig } from '../setting/setting.dto'; +import { VSCODE_WORKSPACE } from '../hook/setting.js'; +import { IServerVersion } from '../mcp/client.dto.js'; +import { SaveTab } from './panel.dto.js'; +import { IConfig } from '../setting/setting.dto.js'; const DEFAULT_TABS: SaveTab = { tabs: [], diff --git a/service/src/server.ts b/service/src/server.ts index 24f8fd5..f20c0a5 100644 --- a/service/src/server.ts +++ b/service/src/server.ts @@ -1,11 +1,11 @@ import { WebSocketServer } from 'ws'; import pino from 'pino'; -import { routeMessage } from './common/router'; -import { VSCodeWebViewLike } from './hook/adapter'; +import { routeMessage } from './common/router.js'; +import { VSCodeWebViewLike } from './hook/adapter.js'; import path from 'node:path'; import * as fs from 'node:fs'; -import { setRunningCWD } from './hook/setting'; +import { setRunningCWD } from './hook/setting.js'; import { exit } from 'node:process'; export interface VSCodeMessage { @@ -14,7 +14,7 @@ export interface VSCodeMessage { callbackId?: string; } -const logger = pino({ +const logger = pino.default({ transport: { target: 'pino-pretty', // 启用 pino-pretty options: { diff --git a/service/src/setting/setting.controller.ts b/service/src/setting/setting.controller.ts index 0b6ffa1..c275902 100644 --- a/service/src/setting/setting.controller.ts +++ b/service/src/setting/setting.controller.ts @@ -1,8 +1,8 @@ -import { Controller } from "../common"; -import { PostMessageble } from "../hook/adapter"; -import { RequestData } from "../common/index.dto"; -import { getClient } from "../mcp/connect.service"; -import { getTour, loadSetting, saveSetting, setTour } from "./setting.service"; +import { Controller } from "../common/index.js"; +import { PostMessageble } from "../hook/adapter.js"; +import { RequestData } from "../common/index.dto.js"; +import { getClient } from "../mcp/connect.service.js"; +import { getTour, loadSetting, saveSetting, setTour } from "./setting.service.js"; export class SettingController { diff --git a/service/src/setting/setting.service.ts b/service/src/setting/setting.service.ts index ed5e553..bf04fc9 100644 --- a/service/src/setting/setting.service.ts +++ b/service/src/setting/setting.service.ts @@ -1,9 +1,9 @@ import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; -import { VSCODE_WORKSPACE } from '../hook/setting'; -import { IConfig } from './setting.dto'; -import { llms } from '../hook/llm'; +import { VSCODE_WORKSPACE } from '../hook/setting.js'; +import { IConfig } from './setting.dto.js'; +import { llms } from '../hook/llm.js'; function getConfigurationPath() { const homeDir = os.homedir(); diff --git a/service/tsconfig.json b/service/tsconfig.json index 0ba20ea..b372d45 100644 --- a/service/tsconfig.json +++ b/service/tsconfig.json @@ -1,7 +1,9 @@ { "compilerOptions": { + "baseUrl": ".", "target": "ES6", - "module": "commonjs", + "module": "NodeNext", + "moduleResolution": "NodeNext", "strict": true, "esModuleInterop": true, "skipLibCheck": true, @@ -10,13 +12,16 @@ "declaration": true, "declarationMap": true, "experimentalDecorators": true, - "moduleResolution": "node" }, "paths": { "@/*": [ "src/*" ] }, - "include": ["src/**/*"], - "exclude": ["node_modules", "src/main.ts"] // 排除 main.ts -} + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + ] +} \ No newline at end of file diff --git a/src/sidebar/workspace.controller.ts b/src/sidebar/workspace.controller.ts index d144c5b..e6f119a 100644 --- a/src/sidebar/workspace.controller.ts +++ b/src/sidebar/workspace.controller.ts @@ -16,25 +16,37 @@ export class McpWorkspaceConnectProvider implements vscode.TreeDataProvider { // TODO: 读取 configDir 下的所有文件,作为子节点 const connection = getWorkspaceConnectionConfig(); - const sidebarItems = connection.items.map((item, index) => { - // 连接的名字 - const nItem = Array.isArray(item) ? item[0] : item; - const itemName = `${nItem.name} (${nItem.type || nItem.connectionType})` - return new ConnectionViewItem(itemName, vscode.TreeItemCollapsibleState.None, item, 'server'); - }) + + // 校验 connection 和 connection.items + if (!connection || !Array.isArray(connection.items)) { + return Promise.resolve([]); + } + + const sidebarItems = connection.items + .filter(item => item !== null && item !== undefined) + .map((item, index) => { + // 连接的名字 + const nItem = Array.isArray(item) ? item[0] : item; + if (!nItem || typeof nItem !== 'object') { + return null; + } + const name = nItem.name || '未命名'; + const type = nItem.type || nItem.connectionType || '未知类型'; + const itemName = `${name} (${type})`; + return new ConnectionViewItem(itemName, vscode.TreeItemCollapsibleState.None, item, 'server'); + }) + .filter(Boolean) as ConnectionViewItem[]; // 过滤掉为 null 的项 // 返回子节点 return Promise.resolve(sidebarItems); } - @RegisterCommand('revealWebviewPanel') public revealWebviewPanel(context: vscode.ExtensionContext, view: ConnectionViewItem) { const item = view.item; - const masterNode = Array.isArray(item)? item[0] : item; + const masterNode = Array.isArray(item) ? item[0] : item; const name = masterNode.filePath || masterNode.name || ''; revealOpenMcpWebviewPanel(context, 'workspace', name, item); }