diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..236f435 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,169 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Development Commands + +### Setup and Installation +```bash +npm run setup # Install dependencies and prepare OCR resources +``` + +### Development +```bash +npm run serve # Start all services in development mode (uses Turbo) +npm run build # Build all modules +npm run build:all # Build all modules (alias) +npm run build:electron # Build only Electron app +``` + +### Service Development +```bash +cd service +npm run serve # Start service with hot reload (nodemon + tsx) +npm run build # Compile TypeScript to dist/ +npm run debug # Start with Node.js inspector +npm run typecheck # Type checking without emit +``` + +### Renderer Development +```bash +cd renderer +npm run serve # Start Vite dev server +npm run build # Build for production +npm run serve:website # Start in website mode +npm run type-check # Vue TypeScript checking +``` + +### VSCode Extension +```bash +npm run vscode:prepublish # Prepare for VSCode publishing (Rollup build) +npm run compile # Compile TypeScript +npm run watch # Watch mode compilation +vsce package # Create VSIX package for distribution +vsce publish # Publish to VSCode Marketplace (requires auth) +``` + +### Quality Assurance +```bash +npm run lint # ESLint for TypeScript files +npm run pretest # Run compile and lint +npm run test # Run tests +``` + +## Architecture Overview + +### Multi-Module Structure +OpenMCP follows a **layered modular architecture** with three main deployment targets: + +1. **VSCode Extension** (`src/extension.ts`) - IDE integration +2. **Service Layer** (`service/`) - Node.js backend handling MCP protocol +3. **Renderer Layer** (`renderer/`) - Vue.js frontend for UI + +### Key Architectural Patterns + +#### Message Bridge Communication +The system uses a **message bridge pattern** for cross-platform communication: +- **VSCode**: Uses `vscode.postMessage` API +- **Electron**: Uses IPC communication +- **Web**: Uses WebSocket connections +- **Node.js**: Uses EventEmitter for SDK mode + +All communication flows through `MessageBridge` class in `renderer/src/api/message-bridge.ts`. + +#### MCP Client Management +- **Connection Management**: `service/src/mcp/connect.service.ts` handles multiple MCP server connections +- **Client Pooling**: `clientMap` maintains active MCP client instances with UUID-based identification +- **Transport Abstraction**: Supports STDIO, SSE, and StreamableHTTP transports +- **Auto-reconnection**: `McpServerConnectMonitor` handles connection monitoring + +#### Request/Response Flow +``` +Frontend (Vue) → MessageBridge → Service Router → MCP Controllers → MCP SDK → External MCP Servers +``` + +### Important Service Patterns + +#### Preprocessing Commands +`service/src/mcp/connect.service.ts` includes **automatic environment setup**: +- Python projects: Auto-runs `uv sync` and installs MCP CLI +- Node.js projects: Auto-runs `npm install` if node_modules missing +- Path resolution: Handles `~/` home directory expansion + +#### OCR Integration +Built-in OCR using Tesseract.js: +- Images from MCP responses are automatically processed +- Base64 images saved to temp files and queued for OCR +- Results delivered via worker threads + +### Frontend Architecture (Vue 3) + +#### State Management +- **Panel System**: Tab-based interface in `renderer/src/components/main-panel/` +- **Reactive Connections**: MCP connection state managed reactively +- **Multi-language**: Vue i18n with support for 9 languages + +#### Core Components +- **Chat Interface**: `main-panel/chat/` - LLM interaction with MCP tools +- **Tool Testing**: `main-panel/tool/` - Direct MCP tool invocation +- **Resource Browser**: `main-panel/resource/` - MCP resource exploration +- **Prompt Manager**: `main-panel/prompt/` - System prompt templates + +### Build System + +#### Turbo Monorepo +Uses Turbo for coordinated builds across modules: +- **Dependency ordering**: Renderer builds before Electron +- **Parallel execution**: Service and Renderer can build concurrently +- **Task caching**: Disabled for development iterations + +#### Rollup Configuration +VSCode extension uses Rollup for optimal bundling: +- **ES modules**: Output as ESM format +- **External dependencies**: VSCode API marked as external +- **TypeScript**: Direct compilation without webpack + +## Development Workflow + +### Adding New MCP Features +1. **Service Layer**: Add controller in `service/src/mcp/` +2. **Router Registration**: Add to `ModuleControllers` in `service/src/common/router.ts` +3. **Frontend Integration**: Add API calls in `renderer/src/api/` +4. **UI Components**: Create components in `renderer/src/components/` + +### Testing MCP Servers +1. **Connection**: Configure in connection panel (STDIO/SSE/HTTP) +2. **Validation**: Test tools/resources in respective panels +3. **Integration**: Verify LLM interaction in chat interface + +### Packaging VSCode Extension + +1. **Build Dependencies**: Run `npm run build` to build all modules +2. **Prepare Extension**: Run `npm run vscode:prepublish` to bundle extension code +3. **Create Package**: Run `vsce package` to generate `.vsix` file +4. **Install Locally**: Use `code --install-extension openmcp-x.x.x.vsix` for testing +5. **Publish**: Run `vsce publish` (requires marketplace publisher account) + +### Platform-Specific Considerations + +- **VSCode**: Uses webview API, limited to extension context +- **Electron**: Full desktop app capabilities, local service spawning +- **Web**: Requires external service, WebSocket limitations +- **SDK**: Embedded in other Node.js applications + +## Important Files + +### Configuration + +- `turbo.json` - Monorepo build orchestration +- `rollup.config.js` - VSCode extension bundling +- `service/package.json` - Backend dependencies and scripts +- `renderer/package.json` - Frontend dependencies and scripts + +### Core Architecture + +- `src/extension.ts` - VSCode extension entry point +- `service/src/main.ts` - Service WebSocket server +- `service/src/common/router.ts` - Request routing system +- `renderer/src/api/message-bridge.ts` - Cross-platform communication +- `service/src/mcp/client.service.ts` - MCP client implementation diff --git a/README.md b/README.md index 290bae8..b97c7fc 100644 --- a/README.md +++ b/README.md @@ -151,4 +151,11 @@ Build for deployment: ```bash npm run build ``` + +build vscode extension: + +```bash +npm run build:plugin +``` + Then just press F5, いただきます (Let's begin) diff --git a/package-lock.json b/package-lock.json index 6e14d09..79017cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "openmcp", - "version": "0.1.6", + "version": "0.1.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "openmcp", - "version": "0.1.6", + "version": "0.1.7", "workspaces": [ "service", "renderer" @@ -20,12 +20,12 @@ "openai": "^5.0.1", "pako": "^2.1.0", "tesseract.js": "^6.0.1", - "tslib": "^2.8.1", "uuid": "^11.1.0", "ws": "^8.18.1" }, "devDependencies": { - "@rollup/plugin-commonjs": "^28.0.3", + "@rollup/plugin-babel": "^6.0.4", + "@rollup/plugin-commonjs": "^28.0.5", "@rollup/plugin-inject": "^5.0.5", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.1", @@ -36,21 +36,20 @@ "@types/vscode": "^1.72.0", "@vscode/test-cli": "^0.0.11", "@vscode/test-electron": "^2.5.2", - "copy-webpack-plugin": "^13.0.0", - "fork-ts-checker-webpack-plugin": "^9.1.0", "null-loader": "^4.0.1", "rollup": "^4.43.0", + "rollup-plugin-copy": "^3.5.0", + "rollup-plugin-typescript2": "^0.36.0", "rollup-plugin-visualizer": "^6.0.1", "ts-loader": "^9.5.1", + "tslib": "^2.8.1", "turbo": "^2.5.3", "typescript": "^5.4.2", "vite": "^6.3.5", "vite-plugin-dts": "^4.5.4", "vite-plugin-static-copy": "^3.0.0", "vite-plugin-vue-devtools": "^7.7.6", - "vue-tsc": "^2.2.10", - "webpack": "^5.99.5", - "webpack-cli": "^5.1.4" + "vue-tsc": "^2.2.10" }, "engines": { "vscode": "^1.95.0" @@ -572,14 +571,6 @@ "node": ">=10" } }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/@element-plus/icons-vue": { "version": "2.3.1", "license": "MIT", @@ -1173,6 +1164,7 @@ "version": "0.3.6", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -1407,6 +1399,44 @@ "version": "0.4.1", "license": "MIT" }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@openmcp/renderer": { "resolved": "renderer", "link": true @@ -1499,10 +1529,37 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@rollup/plugin-babel": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz", + "integrity": "sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@rollup/pluginutils": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + }, + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/plugin-commonjs": { - "version": "28.0.3", - "resolved": "https://registry.npmmirror.com/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.3.tgz", - "integrity": "sha512-pyltgilam1QPdn+Zd9gaCfOLcnjMEJ9gV+bTw6/r73INdvzf1ah9zLIJBm+kW7R6IUFIQ1YO+VqZtYxZNWFPEQ==", + "version": "28.0.5", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.5.tgz", + "integrity": "sha512-lytLp2JgAMwqJY6ve3OSROXr2XuEYHjnsQN3hmnxC+w11dI91LuUw4Yc1kk2FqKXeMG8psoFejFgK+znoij0cg==", "dev": true, "license": "MIT", "dependencies": { @@ -1551,7 +1608,7 @@ }, "node_modules/@rollup/plugin-json": { "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", "dev": true, "license": "MIT", @@ -1572,7 +1629,7 @@ }, "node_modules/@rollup/plugin-node-resolve": { "version": "16.0.1", - "resolved": "https://registry.npmmirror.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.1.tgz", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.1.tgz", "integrity": "sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==", "dev": true, "license": "MIT", @@ -2180,6 +2237,7 @@ "version": "9.6.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -2189,6 +2247,7 @@ "version": "3.7.7", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -2220,6 +2279,27 @@ "@types/send": "*" } }, + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, "node_modules/@types/http-errors": { "version": "2.0.4", "dev": true, @@ -2272,6 +2352,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/mocha": { "version": "10.0.10", "resolved": "https://registry.npmmirror.com/@types/mocha/-/mocha-10.0.10.tgz", @@ -2902,6 +2989,7 @@ "version": "1.14.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" @@ -2910,22 +2998,26 @@ "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.13.2", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.13.2", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.14.1", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.13.2", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", @@ -2935,12 +3027,14 @@ "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.13.2", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.14.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -2952,6 +3046,7 @@ "version": "1.13.2", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -2960,6 +3055,7 @@ "version": "1.13.2", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -2967,12 +3063,14 @@ "node_modules/@webassemblyjs/utf8": { "version": "1.13.2", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.14.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -2988,6 +3086,7 @@ "version": "1.14.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", @@ -3000,6 +3099,7 @@ "version": "1.14.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -3011,6 +3111,7 @@ "version": "1.14.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", @@ -3024,61 +3125,23 @@ "version": "1.14.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, - "node_modules/@webpack-cli/configtest": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "dev": true, - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/@xtuc/long": { "version": "4.2.2", "dev": true, - "license": "Apache-2.0" + "license": "Apache-2.0", + "peer": true }, "node_modules/abort-controller": { "version": "3.0.0", @@ -3135,6 +3198,7 @@ "version": "8.17.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -3165,6 +3229,7 @@ "version": "2.1.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ajv": "^8.0.0" }, @@ -3181,6 +3246,7 @@ "version": "5.1.0", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -3243,6 +3309,16 @@ "version": "2.0.1", "license": "Python-2.0" }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/async-validator": { "version": "4.2.5", "license": "MIT" @@ -3402,7 +3478,8 @@ "node_modules/buffer-from": { "version": "1.1.2", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/bundle-name": { "version": "4.1.0", @@ -3556,14 +3633,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/callsites": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-6.3.0.tgz", @@ -3629,6 +3698,7 @@ "version": "1.0.4", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6.0" } @@ -3831,28 +3901,6 @@ "url": "https://github.com/sponsors/mesqueeb" } }, - "node_modules/copy-webpack-plugin": { - "version": "13.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "glob-parent": "^6.0.1", - "normalize-path": "^3.0.0", - "schema-utils": "^4.2.0", - "serialize-javascript": "^6.0.2", - "tinyglobby": "^0.2.12" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - } - }, "node_modules/core-js": { "version": "3.42.0", "hasInstallScript": true, @@ -3880,31 +3928,6 @@ "node": ">= 0.10" } }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "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/crelt": { "version": "1.0.6", "license": "MIT" @@ -4050,6 +4073,19 @@ "node": ">=0.3.1" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "license": "MIT", @@ -4163,14 +4199,6 @@ "node": ">=4" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, "node_modules/error-stack-parser-es": { "version": "0.1.5", "dev": true, @@ -4196,7 +4224,8 @@ "node_modules/es-module-lexer": { "version": "1.7.0", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/es-object-atoms": { "version": "1.1.1", @@ -4624,6 +4653,7 @@ "version": "5.1.1", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -4636,6 +4666,7 @@ "version": "4.3.0", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -4647,6 +4678,7 @@ "version": "5.3.0", "dev": true, "license": "BSD-2-Clause", + "peer": true, "engines": { "node": ">=4.0" } @@ -4655,6 +4687,7 @@ "version": "4.3.0", "dev": true, "license": "BSD-2-Clause", + "peer": true, "engines": { "node": ">=4.0" } @@ -4681,6 +4714,7 @@ "version": "3.3.0", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.8.x" } @@ -4795,6 +4829,36 @@ "version": "3.1.3", "license": "MIT" }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/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/fast-json-stable-stringify": { "version": "2.1.0", "license": "MIT" @@ -4823,7 +4887,8 @@ "url": "https://opencollective.com/fastify" } ], - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/fastest-levenshtein": { "version": "1.0.16", @@ -4833,6 +4898,16 @@ "node": ">= 4.9.1" } }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fdir": { "version": "6.4.4", "dev": true, @@ -4886,6 +4961,40 @@ "node": ">= 0.8" } }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/find-up": { "version": "4.1.0", "dev": true, @@ -4954,88 +5063,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "9.1.0", - "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", - "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", - "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", - "dev": true, - "license": "MIT" - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "3.3.0", - "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/fork-ts-checker-webpack-plugin/node_modules/semver": { - "version": "7.7.2", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/form-data": { "version": "4.0.2", "license": "MIT", @@ -5097,6 +5124,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": { @@ -5108,11 +5137,6 @@ "node": ">=12" } }, - "node_modules/fs-monkey": { - "version": "1.0.6", - "dev": true, - "license": "Unlicense" - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -5252,21 +5276,11 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/glob-to-regexp": { "version": "0.4.1", "dev": true, - "license": "BSD-2-Clause" + "license": "BSD-2-Clause", + "peer": true }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.0.2", @@ -5302,6 +5316,48 @@ "node": ">=4" } }, + "node_modules/globby": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", + "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/globby/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/gopd": { "version": "1.2.0", "license": "MIT", @@ -5462,6 +5518,16 @@ "version": "6.2.2", "license": "Apache-2.0" }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", @@ -5473,21 +5539,6 @@ "version": "3.0.6", "license": "MIT" }, - "node_modules/import-fresh": { - "version": "3.3.1", - "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-lazy": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", @@ -5561,11 +5612,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "dev": true, - "license": "MIT" - }, "node_modules/is-binary-path": { "version": "2.1.0", "dev": true, @@ -5895,6 +5941,7 @@ "version": "27.5.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -5908,6 +5955,7 @@ "version": "8.1.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -5962,7 +6010,8 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/json-schema-traverse": { "version": "1.0.0", @@ -6055,11 +6104,6 @@ "immediate": "~3.0.5" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "dev": true, - "license": "MIT" - }, "node_modules/linkify-it": { "version": "5.0.0", "license": "MIT", @@ -6071,6 +6115,7 @@ "version": "4.3.0", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6.11.5" } @@ -6268,17 +6313,6 @@ "node": ">= 0.8" } }, - "node_modules/memfs": { - "version": "3.5.3", - "dev": true, - "license": "Unlicense", - "dependencies": { - "fs-monkey": "^1.0.4" - }, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/memoize-one": { "version": "6.0.0", "license": "MIT" @@ -6303,7 +6337,18 @@ "node_modules/merge-stream": { "version": "2.0.0", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } }, "node_modules/micromatch": { "version": "4.0.8", @@ -6610,12 +6655,8 @@ "node_modules/neo-async": { "version": "2.6.2", "dev": true, - "license": "MIT" - }, - "node_modules/node-abort-controller": { - "version": "3.1.1", - "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/node-domexception": { "version": "1.0.0", @@ -7253,34 +7294,6 @@ "version": "2.1.0", "license": "(MIT AND Zlib)" }, - "node_modules/parent-module": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "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/parse-ms": { "version": "4.0.0", "dev": true, @@ -7664,6 +7677,27 @@ ], "license": "MIT" }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/quick-format-unescaped": { "version": "4.0.4", "license": "MIT" @@ -7829,14 +7863,6 @@ "node": ">=8" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "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", @@ -7864,6 +7890,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rfdc": { "version": "1.4.1", "dev": true, @@ -7909,6 +7946,133 @@ "fsevents": "~2.3.2" } }, + "node_modules/rollup-plugin-copy": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.5.0.tgz", + "integrity": "sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^8.0.1", + "colorette": "^1.1.0", + "fs-extra": "^8.1.0", + "globby": "10.0.1", + "is-plain-object": "^3.0.0" + }, + "engines": { + "node": ">=8.3" + } + }, + "node_modules/rollup-plugin-copy/node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup-plugin-copy/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/rollup-plugin-copy/node_modules/is-plain-object": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup-plugin-copy/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/rollup-plugin-copy/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/rollup-plugin-typescript2": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.36.0.tgz", + "integrity": "sha512-NB2CSQDxSe9+Oe2ahZbf+B4bh7pHwjV5L+RSYpCu7Q5ROuN94F9b6ioWwKfz3ueL3KTtmX4o2MUH2cgHDIEUsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^4.1.2", + "find-cache-dir": "^3.3.2", + "fs-extra": "^10.0.0", + "semver": "^7.5.4", + "tslib": "^2.6.2" + }, + "peerDependencies": { + "rollup": ">=1.26.3", + "typescript": ">=2.4.0" + } + }, + "node_modules/rollup-plugin-typescript2/node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/rollup-plugin-typescript2/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/rollup-plugin-typescript2/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/rollup-plugin-visualizer": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-6.0.1.tgz", @@ -8021,6 +8185,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "funding": [ @@ -8069,6 +8257,7 @@ "version": "4.3.2", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -8311,6 +8500,16 @@ "node": ">=18" } }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/sonic-boom": { "version": "4.2.0", "license": "MIT", @@ -8337,6 +8536,7 @@ "version": "0.5.21", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -8346,6 +8546,7 @@ "version": "0.6.1", "dev": true, "license": "BSD-3-Clause", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -8553,6 +8754,7 @@ "version": "5.39.2", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.14.0", @@ -8570,6 +8772,7 @@ "version": "5.3.14", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", @@ -8602,7 +8805,8 @@ "node_modules/terser/node_modules/commander": { "version": "2.20.3", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/tesseract.js": { "version": "6.0.1", @@ -8770,8 +8974,9 @@ }, "node_modules/tslib": { "version": "2.8.1", - "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, "license": "0BSD" }, "node_modules/tsx": { @@ -9402,6 +9607,7 @@ "version": "2.4.2", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -9425,6 +9631,7 @@ "version": "5.99.8", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", @@ -9467,71 +9674,6 @@ } } }, - "node_modules/webpack-cli": { - "version": "5.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^2.1.1", - "@webpack-cli/info": "^2.0.2", - "@webpack-cli/serve": "^2.0.5", - "colorette": "^2.0.14", - "commander": "^10.0.1", - "cross-spawn": "^7.0.3", - "envinfo": "^7.7.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^3.1.1", - "rechoir": "^0.8.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "10.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/webpack-merge": { - "version": "5.10.0", - "dev": true, - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/webpack-node-externals": { "version": "3.0.0", "dev": true, @@ -9544,6 +9686,7 @@ "version": "3.2.3", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10.13.0" } @@ -9552,6 +9695,7 @@ "version": "1.52.0", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -9560,6 +9704,7 @@ "version": "2.1.35", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "mime-db": "1.52.0" }, diff --git a/package.json b/package.json index c5ed5a1..f007817 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "openmcp", "displayName": "OpenMCP", "description": "An all in one MCP Client/TestTool", - "version": "0.1.6", + "version": "0.1.7", "publisher": "kirigaya", "author": { "name": "kirigaya", @@ -224,15 +224,14 @@ "setup": "npm i && npm run prepare:ocr", "serve": "turbo serve", "build": "turbo build && tsc -p ./", - "build:electron": "turbo build --filter=@openmcp/electron", - "build:all": "turbo build", + "build:plugin": "npm run build && tsc && vsce package", "vscode:prepublish": "rollup --config rollup.config.js", "compile": "tsc -p ./", "watch": "tsc -watch -p ./", "pretest": "npm run build", "lint": "eslint src --ext ts", "test": "node ./dist/test/e2e/runTest.js", - "prepare:ocr": "rollup --config rollup.tesseract.js", + "prepare:ocr": "rollup -c rollup.tesseract.js --bundleConfigAsCjs", "build:task-loop": "npx vite build --config renderer/vite.config.task-loop.mjs && node renderer/scripts/task-loop.build.mjs" }, "dependencies": { @@ -249,7 +248,8 @@ "ws": "^8.18.1" }, "devDependencies": { - "@rollup/plugin-commonjs": "^28.0.3", + "@rollup/plugin-babel": "^6.0.4", + "@rollup/plugin-commonjs": "^28.0.5", "@rollup/plugin-inject": "^5.0.5", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.1", @@ -264,6 +264,7 @@ "fork-ts-checker-webpack-plugin": "^9.1.0", "null-loader": "^4.0.1", "rollup": "^4.43.0", + "rollup-plugin-copy": "^3.5.0", "rollup-plugin-visualizer": "^6.0.1", "ts-loader": "^9.5.1", "turbo": "^2.5.3", diff --git a/renderer/public/images/openrouter.ai.ico b/renderer/public/images/openrouter.ai.ico new file mode 100644 index 0000000..53f4035 --- /dev/null +++ b/renderer/public/images/openrouter.ai.ico @@ -0,0 +1,3 @@ +# OpenRouter Icon Placeholder +# This would normally be an actual .ico file +# For now, using a placeholder that follows the naming convention \ No newline at end of file diff --git a/renderer/src/components/main-panel/tool/tool-list.vue b/renderer/src/components/main-panel/tool/tool-list.vue index 2ecb94a..fd1dcff 100644 --- a/renderer/src/components/main-panel/tool/tool-list.vue +++ b/renderer/src/components/main-panel/tool/tool-list.vue @@ -17,7 +17,13 @@
{{ tool.name }} - {{ tool.description || '' }} + + {{ tool.description || '' }} +
@@ -27,7 +33,7 @@ - \ No newline at end of file diff --git a/renderer/src/views/setting/llm.ts b/renderer/src/views/setting/llm.ts index 9e2e68c..17b022c 100644 --- a/renderer/src/views/setting/llm.ts +++ b/renderer/src/views/setting/llm.ts @@ -22,6 +22,9 @@ export interface BasicLlmDescription { website: string, userToken: string, userModel: string, + isDynamic?: boolean, + modelsEndpoint?: string, + supportsPricing?: boolean, [key: string]: any } diff --git a/rollup.config.js b/rollup.config.js index 0e5104b..f75e364 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -11,7 +11,7 @@ export default { sourcemap: true }, plugins: [ - json(), + json(), resolve({ browser: true }), // 支持 node_modules 解析 commonjs(), // 转换 CommonJS 模块 typescript() // 处理 TypeScript diff --git a/rollup.tesseract.js b/rollup.tesseract.js index 0ff642b..92326cc 100644 --- a/rollup.tesseract.js +++ b/rollup.tesseract.js @@ -1,15 +1,37 @@ -import resolve from '@rollup/plugin-node-resolve'; +import path from 'path'; +import { nodeResolve } from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; +import { babel } from '@rollup/plugin-babel'; +import json from '@rollup/plugin-json'; // ✅ 新增 +import copy from 'rollup-plugin-copy'; export default { - input: 'src/ocr-worker.ts', + input: './node_modules/tesseract.js/src/worker-script/node/index.js', output: { - file: 'dist/ocr-worker.js', - format: 'es' + file: path.resolve(__dirname, '..', 'resources', 'ocr', 'worker.js'), + format: 'cjs', + exports: 'auto' }, plugins: [ - resolve(), - commonjs() + json(), // ✅ 插入 JSON 插件 + nodeResolve({ + browser: false, + preferBuiltins: true + }), + commonjs(), + babel({ + babelHelpers: 'bundled', + exclude: 'node_modules/**', + presets: ['@babel/preset-env'] + }), + copy({ + targets: [ + { + src: path.resolve(__dirname, '..', 'node_modules', 'tesseract.js-core', 'tesseract*'), + dest: path.resolve(__dirname, '..', 'resources', 'ocr') + } + ] + }) ], - external: ['tesseract.js'] // 显式排除 Tesseract -}; \ No newline at end of file + external: ['bufferutil', 'utf-8-validate'] +}; diff --git a/service/src/hook/llm.ts b/service/src/hook/llm.ts index 07be9d5..f822090 100644 --- a/service/src/hook/llm.ts +++ b/service/src/hook/llm.ts @@ -130,6 +130,21 @@ export const llms = [ website: 'https://kimi.moonshot.cn', userToken: '', userModel: 'moonshot-v1-8k' + }, + { + id: 'openrouter', + name: 'OpenRouter', + baseUrl: 'https://openrouter.ai/api/v1', + models: [], // 动态加载 + provider: 'OpenRouter', + isOpenAICompatible: true, + description: '400+ AI models from multiple providers in one API', + website: 'https://openrouter.ai', + userToken: '', + userModel: '', + isDynamic: true, + modelsEndpoint: 'https://openrouter.ai/api/v1/models', + supportsPricing: true } ]; diff --git a/service/src/hook/openrouter.ts b/service/src/hook/openrouter.ts new file mode 100644 index 0000000..e058bb7 --- /dev/null +++ b/service/src/hook/openrouter.ts @@ -0,0 +1,100 @@ +export interface OpenRouterModel { + id: string; + name: string; + description?: string; + context_length: number; + pricing: { + prompt: string; + completion: string; + }; + architecture?: { + input_modalities?: string[]; + output_modalities?: string[]; + tokenizer?: string; + }; + supported_parameters?: string[]; +} + +export interface OpenRouterModelsResponse { + data: OpenRouterModel[]; +} + +// 模型缓存,避免频繁API调用 +let modelsCache: { models: OpenRouterModel[]; timestamp: number } | null = null; +const CACHE_DURATION = 5 * 60 * 1000; // 5分钟缓存 + +export async function fetchOpenRouterModels(): Promise { + const now = Date.now(); + + // 检查缓存 + if (modelsCache && (now - modelsCache.timestamp) < CACHE_DURATION) { + return modelsCache.models; + } + + try { + const response = await fetch('https://openrouter.ai/api/v1/models'); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data: OpenRouterModelsResponse = await response.json(); + + const models = data.data.map(model => ({ + id: model.id, + name: model.name, + description: model.description, + context_length: model.context_length, + pricing: model.pricing, + architecture: model.architecture, + supported_parameters: model.supported_parameters + })); + + // 更新缓存 + modelsCache = { + models, + timestamp: now + }; + + console.log(`Fetched ${models.length} OpenRouter models`); + return models; + } catch (error) { + console.error('Failed to fetch OpenRouter models:', error); + // 返回缓存的模型(如果有)或空数组 + return modelsCache?.models || []; + } +} + +export async function getOpenRouterModelsByCategory(category?: string): Promise { + try { + const url = category + ? `https://openrouter.ai/api/v1/models?category=${encodeURIComponent(category)}` + : 'https://openrouter.ai/api/v1/models'; + + const response = await fetch(url); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data: OpenRouterModelsResponse = await response.json(); + return data.data; + } catch (error) { + console.error(`Failed to fetch OpenRouter models for category ${category}:`, error); + return []; + } +} + +// 清除缓存的函数 +export function clearOpenRouterCache(): void { + modelsCache = null; +} + +// 获取模型的简化信息,用于下拉框显示 +export function getSimplifiedModels(models: OpenRouterModel[]): { id: string; name: string; pricing?: string }[] { + return models.map(model => ({ + id: model.id, + name: model.name, + pricing: model.pricing ? `$${model.pricing.prompt}/1K` : undefined + })); +} \ No newline at end of file diff --git a/service/src/llm/llm.controller.ts b/service/src/llm/llm.controller.ts index 6eff52e..c42d203 100644 --- a/service/src/llm/llm.controller.ts +++ b/service/src/llm/llm.controller.ts @@ -1,11 +1,9 @@ -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 { axiosFetch } from "src/hook/axios-fetch.js"; +import { fetchOpenRouterModels, getSimplifiedModels } from "../hook/openrouter.js"; export class LlmController { @Controller('llm/chat/completions') @@ -57,4 +55,66 @@ export class LlmController { msg: models.data } } + + @Controller('llm/models/openrouter') + async getOpenRouterModels(data: RequestData, webview: PostMessageble) { + try { + const models = await fetchOpenRouterModels(); + const simplifiedModels = getSimplifiedModels(models); + + // 转换为标准格式,与其他模型API保持一致 + const standardModels = simplifiedModels.map(model => ({ + id: model.id, + object: 'model', + name: model.name, + pricing: model.pricing + })); + + return { + code: 200, + msg: standardModels + }; + } catch (error) { + console.error('Failed to fetch OpenRouter models:', error); + return { + code: 500, + msg: `Failed to fetch OpenRouter models: ${error instanceof Error ? error.message : String(error)}` + }; + } + } + + @Controller('llm/models/dynamic') + async getDynamicModels(data: RequestData, webview: PostMessageble) { + const { providerId } = data; + + try { + if (providerId === 'openrouter') { + const models = await fetchOpenRouterModels(); + const simplifiedModels = getSimplifiedModels(models); + + const standardModels = simplifiedModels.map(model => ({ + id: model.id, + object: 'model', + name: model.name, + pricing: model.pricing + })); + + return { + code: 200, + msg: standardModels + }; + } else { + return { + code: 400, + msg: `Unsupported dynamic provider: ${providerId}` + }; + } + } catch (error) { + console.error(`Failed to fetch dynamic models for ${providerId}:`, error); + return { + code: 500, + msg: `Failed to fetch models: ${error instanceof Error ? error.message : String(error)}` + }; + } + } } \ No newline at end of file diff --git a/service/src/llm/llm.service.ts b/service/src/llm/llm.service.ts index f6dd53f..a132fab 100644 --- a/service/src/llm/llm.service.ts +++ b/service/src/llm/llm.service.ts @@ -35,9 +35,17 @@ export async function streamingChatCompletion( }); + // 构建OpenRouter特定的请求头 + const defaultHeaders: Record = {}; + if (baseURL && baseURL.includes('openrouter.ai')) { + defaultHeaders['HTTP-Referer'] = 'https://github.com/openmcp/openmcp-client'; + defaultHeaders['X-Title'] = 'OpenMCP Client'; + } + const client = new OpenAI({ baseURL, apiKey, + defaultHeaders: Object.keys(defaultHeaders).length > 0 ? defaultHeaders : undefined }); const seriableTools = (tools.length === 0) ? undefined: tools; diff --git a/service/src/setting/setting.service.ts b/service/src/setting/setting.service.ts index bf04fc9..40233d3 100644 --- a/service/src/setting/setting.service.ts +++ b/service/src/setting/setting.service.ts @@ -53,9 +53,28 @@ export function loadSetting(): IConfig { try { const configData = fs.readFileSync(configPath, 'utf-8'); const config = JSON.parse(configData) as IConfig; + if (!config.LLM_INFO || (Array.isArray(config.LLM_INFO) && config.LLM_INFO.length === 0)) { config.LLM_INFO = llms; - } + } else { + // 自动同步新的提供商:检查默认配置中是否有新的提供商未在用户配置中 + const existingIds = new Set(config.LLM_INFO.map((llm: any) => llm.id)); + const newProviders = llms.filter((llm: any) => !existingIds.has(llm.id)); + + if (newProviders.length > 0) { + console.log(`Adding ${newProviders.length} new providers:`, newProviders.map(p => p.name)); + config.LLM_INFO.push(...newProviders); + + // 自动保存更新后的配置 + try { + fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8'); + console.log('Configuration updated with new providers'); + } catch (saveError) { + console.error('Failed to save updated configuration:', saveError); + } + } + } + return config; } catch (error) { console.error('Error loading config file, creating new one:', error); diff --git a/src/test/e2e/runTest.ts b/src/test/e2e/runTest.ts deleted file mode 100644 index 6df6ee3..0000000 --- a/src/test/e2e/runTest.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as path from 'path'; - -import { runTests } from '@vscode/test-electron'; -import { fileURLToPath } from 'url'; - -// 将 import.meta.url 转换为文件路径 -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -async function main() { - try { - // The folder containing the Extension Manifest package.json - // Passed to `--extensionDevelopmentPath` - const extensionDevelopmentPath = path.resolve(__dirname, '../../../'); - console.log('Extension Path:', extensionDevelopmentPath); // 添加日志验证路径 - // The path to the extension test script - // Passed to --extensionTestsPath - const extensionTestsPath = path.resolve(__dirname, './suite/index.js'); - - // Download VS Code, unzip it and run the integration test - await runTests({ - extensionDevelopmentPath: extensionDevelopmentPath, - extensionTestsPath: extensionTestsPath, - }); - } catch (err) { - console.error('Failed to run tests'); - console.error(err); - process.exit(1); - } -} - -main(); \ No newline at end of file diff --git a/src/test/e2e/suite/extension.test.ts b/src/test/e2e/suite/extension.test.ts deleted file mode 100644 index 479bc2b..0000000 --- a/src/test/e2e/suite/extension.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -import * as assert from 'assert'; - -// You can import and use all API from the 'vscode' module -// as well as import your extension to test it -import * as vscode from 'vscode'; -// import * as myExtension from '../../extension'; - -suite('Extension Test Suite', () => { - // vscode.window.showInformationMessage('Start all tests.'); - console.log("Running sample test") - test('Sample test', () => { - assert.strictEqual([1, 2, 3].indexOf(5), -1); - assert.strictEqual([1, 2, 3].indexOf(0), -1); - }); -}); \ No newline at end of file diff --git a/src/test/e2e/suite/index.ts b/src/test/e2e/suite/index.ts deleted file mode 100644 index b1f560e..0000000 --- a/src/test/e2e/suite/index.ts +++ /dev/null @@ -1,43 +0,0 @@ - -import * as path from 'path'; -import Mocha from 'mocha'; -import {glob} from 'glob'; -import { fileURLToPath } from 'url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - - -export function run(): Promise { - // Create the mocha test - const mocha = new Mocha({ - ui: 'tdd' - }); - - const testsRoot = path.resolve(__dirname, '..'); - - return new Promise((c, e) => { - glob('**/**.test.js', { cwd: testsRoot }).then((files: string[]) => { - // Add files to the test suite - console.log('Test files found:', files); // Log the found test files - files.forEach((f: string) => mocha.addFile(path.resolve(testsRoot, f))); - - try { - // Run the mocha test - console.log("Running test:", files) - mocha.run(failures => { - if (failures > 0) { - e(new Error(`${failures} tests failed.`)); - } else { - c(); - } - }); - } catch (err) { - console.error(err); - e(err); - } - }).catch(err => { - e(err); - }); - }); -} diff --git a/tsconfig.json b/tsconfig.json index 07490ba..754b990 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,8 @@ "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, + "importHelpers": false, + "noEmitHelpers": false, "experimentalDecorators": true, // 允许访问 openmcp-sdk 目录 "paths": {