Commit
Β·
ec2237a
1
Parent(s):
3624cee
added pythonic tool calls
Browse files- dist/assets/{index-DxhcZCe7.js β index-DU4-Hcde.js} +0 -0
- dist/assets/{textGenerationWorker-ns1jR_Qy.js β textGenerationWorker-CYbgGXFl.js} +0 -0
- dist/index.html +1 -1
- package-lock.json +366 -7
- package.json +4 -2
- src/chat/ChatForm.tsx +1 -1
- src/textGeneration/TextGeneration.ts +3 -3
- src/textGeneration/types.ts +4 -1
- src/textGeneration/worker/textGenerationWorker.ts +19 -13
- src/utils/calculateDownloadProgress.ts +7 -0
- src/utils/context/chatSettings/ChatSettingsModalForm.tsx +36 -4
- src/utils/models.ts +80 -8
- src/utils/tools.ts +1 -1
- src/utils/{webMcp.ts β webMcp/execute.ts} +36 -177
- src/utils/webMcp/extract.ts +206 -0
- src/utils/webMcp/format.ts +9 -0
- src/utils/webMcp/index.ts +3 -0
- src/utils/webMcp/types.ts +46 -0
- src/utils/webMcp/webMcp.test.ts +182 -0
dist/assets/{index-DxhcZCe7.js β index-DU4-Hcde.js}
RENAMED
|
The diff for this file is too large to render.
See raw diff
|
|
|
dist/assets/{textGenerationWorker-ns1jR_Qy.js β textGenerationWorker-CYbgGXFl.js}
RENAMED
|
The diff for this file is too large to render.
See raw diff
|
|
|
dist/index.html
CHANGED
|
@@ -11,7 +11,7 @@
|
|
| 11 |
rel="stylesheet"
|
| 12 |
/>
|
| 13 |
<title>Transformers.js TextGeneration</title>
|
| 14 |
-
<script type="module" crossorigin src="/assets/index-
|
| 15 |
<link rel="stylesheet" crossorigin href="/assets/index-CYRNQXs7.css">
|
| 16 |
</head>
|
| 17 |
<body>
|
|
|
|
| 11 |
rel="stylesheet"
|
| 12 |
/>
|
| 13 |
<title>Transformers.js TextGeneration</title>
|
| 14 |
+
<script type="module" crossorigin src="/assets/index-DU4-Hcde.js"></script>
|
| 15 |
<link rel="stylesheet" crossorigin href="/assets/index-CYRNQXs7.css">
|
| 16 |
</head>
|
| 17 |
<body>
|
package-lock.json
CHANGED
|
@@ -40,7 +40,8 @@
|
|
| 40 |
"typescript-eslint": "^8.44.0",
|
| 41 |
"vite": "^7.1.7",
|
| 42 |
"vite-plugin-html-config": "^2.0.2",
|
| 43 |
-
"vite-tsconfig-paths": "^5.1.4"
|
|
|
|
| 44 |
}
|
| 45 |
},
|
| 46 |
"../../transformers.js": {
|
|
@@ -75,10 +76,8 @@
|
|
| 75 |
"license": "Apache-2.0",
|
| 76 |
"dependencies": {
|
| 77 |
"@huggingface/jinja": "^0.5.1",
|
| 78 |
-
"esbuild": "^0.27.0",
|
| 79 |
"onnxruntime-node": "1.24.0-dev.20251104-75d35474d5",
|
| 80 |
"onnxruntime-web": "1.24.0-dev.20251104-75d35474d5",
|
| 81 |
-
"rimraf": "^6.1.2",
|
| 82 |
"sharp": "^0.34.3"
|
| 83 |
},
|
| 84 |
"devDependencies": {
|
|
@@ -90,7 +89,10 @@
|
|
| 90 |
"jsdoc-to-markdown": "^9.1.1",
|
| 91 |
"prettier": "3.4.2",
|
| 92 |
"typescript": "^5.8.3",
|
| 93 |
-
"wavefile": "11.0.0"
|
|
|
|
|
|
|
|
|
|
| 94 |
}
|
| 95 |
},
|
| 96 |
"node_modules/@babel/code-frame": {
|
|
@@ -1490,6 +1492,13 @@
|
|
| 1490 |
"win32"
|
| 1491 |
]
|
| 1492 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1493 |
"node_modules/@tailwindcss/node": {
|
| 1494 |
"version": "4.1.13",
|
| 1495 |
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.13.tgz",
|
|
@@ -1870,6 +1879,24 @@
|
|
| 1870 |
"@babel/types": "^7.28.2"
|
| 1871 |
}
|
| 1872 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1873 |
"node_modules/@types/estree": {
|
| 1874 |
"version": "1.0.8",
|
| 1875 |
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
|
@@ -2213,6 +2240,117 @@
|
|
| 2213 |
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
|
| 2214 |
}
|
| 2215 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2216 |
"node_modules/acorn": {
|
| 2217 |
"version": "8.15.0",
|
| 2218 |
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
|
@@ -2276,6 +2414,16 @@
|
|
| 2276 |
"dev": true,
|
| 2277 |
"license": "Python-2.0"
|
| 2278 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2279 |
"node_modules/autoprefixer": {
|
| 2280 |
"version": "10.4.21",
|
| 2281 |
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
|
|
@@ -2420,6 +2568,16 @@
|
|
| 2420 |
],
|
| 2421 |
"license": "CC-BY-4.0"
|
| 2422 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2423 |
"node_modules/chalk": {
|
| 2424 |
"version": "4.1.2",
|
| 2425 |
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
|
@@ -2593,6 +2751,13 @@
|
|
| 2593 |
"node": ">=10.13.0"
|
| 2594 |
}
|
| 2595 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2596 |
"node_modules/esbuild": {
|
| 2597 |
"version": "0.25.10",
|
| 2598 |
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz",
|
|
@@ -2826,6 +2991,16 @@
|
|
| 2826 |
"node": ">=4.0"
|
| 2827 |
}
|
| 2828 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2829 |
"node_modules/esutils": {
|
| 2830 |
"version": "2.0.3",
|
| 2831 |
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
|
@@ -2836,6 +3011,16 @@
|
|
| 2836 |
"node": ">=0.10.0"
|
| 2837 |
}
|
| 2838 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2839 |
"node_modules/fast-deep-equal": {
|
| 2840 |
"version": "3.1.3",
|
| 2841 |
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
|
@@ -3556,9 +3741,9 @@
|
|
| 3556 |
}
|
| 3557 |
},
|
| 3558 |
"node_modules/magic-string": {
|
| 3559 |
-
"version": "0.30.
|
| 3560 |
-
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.
|
| 3561 |
-
"integrity": "sha512-
|
| 3562 |
"dev": true,
|
| 3563 |
"license": "MIT",
|
| 3564 |
"dependencies": {
|
|
@@ -3675,6 +3860,17 @@
|
|
| 3675 |
"node": ">=0.10.0"
|
| 3676 |
}
|
| 3677 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3678 |
"node_modules/optionator": {
|
| 3679 |
"version": "0.9.4",
|
| 3680 |
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
|
@@ -3758,6 +3954,13 @@
|
|
| 3758 |
"node": ">=8"
|
| 3759 |
}
|
| 3760 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3761 |
"node_modules/picocolors": {
|
| 3762 |
"version": "1.1.1",
|
| 3763 |
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
|
@@ -4160,6 +4363,13 @@
|
|
| 4160 |
"url": "https://www.paypal.me/tiviesantos"
|
| 4161 |
}
|
| 4162 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4163 |
"node_modules/source-map-js": {
|
| 4164 |
"version": "1.2.1",
|
| 4165 |
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
|
@@ -4170,6 +4380,20 @@
|
|
| 4170 |
"node": ">=0.10.0"
|
| 4171 |
}
|
| 4172 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4173 |
"node_modules/strip-json-comments": {
|
| 4174 |
"version": "3.1.1",
|
| 4175 |
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
|
@@ -4244,6 +4468,23 @@
|
|
| 4244 |
"node": ">=18"
|
| 4245 |
}
|
| 4246 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4247 |
"node_modules/tinyglobby": {
|
| 4248 |
"version": "0.2.15",
|
| 4249 |
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
|
@@ -4274,6 +4515,16 @@
|
|
| 4274 |
"url": "https://github.com/sponsors/jonschlinkert"
|
| 4275 |
}
|
| 4276 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4277 |
"node_modules/to-regex-range": {
|
| 4278 |
"version": "5.0.1",
|
| 4279 |
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
|
@@ -4555,6 +4806,97 @@
|
|
| 4555 |
"url": "https://github.com/sponsors/jonschlinkert"
|
| 4556 |
}
|
| 4557 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4558 |
"node_modules/which": {
|
| 4559 |
"version": "2.0.2",
|
| 4560 |
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
|
@@ -4571,6 +4913,23 @@
|
|
| 4571 |
"node": ">= 8"
|
| 4572 |
}
|
| 4573 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4574 |
"node_modules/word-wrap": {
|
| 4575 |
"version": "1.2.5",
|
| 4576 |
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
|
|
|
| 40 |
"typescript-eslint": "^8.44.0",
|
| 41 |
"vite": "^7.1.7",
|
| 42 |
"vite-plugin-html-config": "^2.0.2",
|
| 43 |
+
"vite-tsconfig-paths": "^5.1.4",
|
| 44 |
+
"vitest": "^4.0.15"
|
| 45 |
}
|
| 46 |
},
|
| 47 |
"../../transformers.js": {
|
|
|
|
| 76 |
"license": "Apache-2.0",
|
| 77 |
"dependencies": {
|
| 78 |
"@huggingface/jinja": "^0.5.1",
|
|
|
|
| 79 |
"onnxruntime-node": "1.24.0-dev.20251104-75d35474d5",
|
| 80 |
"onnxruntime-web": "1.24.0-dev.20251104-75d35474d5",
|
|
|
|
| 81 |
"sharp": "^0.34.3"
|
| 82 |
},
|
| 83 |
"devDependencies": {
|
|
|
|
| 89 |
"jsdoc-to-markdown": "^9.1.1",
|
| 90 |
"prettier": "3.4.2",
|
| 91 |
"typescript": "^5.8.3",
|
| 92 |
+
"wavefile": "11.0.0",
|
| 93 |
+
"webpack": "^5.99.9",
|
| 94 |
+
"webpack-cli": "^6.0.1",
|
| 95 |
+
"webpack-dev-server": "^5.2.2"
|
| 96 |
}
|
| 97 |
},
|
| 98 |
"node_modules/@babel/code-frame": {
|
|
|
|
| 1492 |
"win32"
|
| 1493 |
]
|
| 1494 |
},
|
| 1495 |
+
"node_modules/@standard-schema/spec": {
|
| 1496 |
+
"version": "1.0.0",
|
| 1497 |
+
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
|
| 1498 |
+
"integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
|
| 1499 |
+
"dev": true,
|
| 1500 |
+
"license": "MIT"
|
| 1501 |
+
},
|
| 1502 |
"node_modules/@tailwindcss/node": {
|
| 1503 |
"version": "4.1.13",
|
| 1504 |
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.13.tgz",
|
|
|
|
| 1879 |
"@babel/types": "^7.28.2"
|
| 1880 |
}
|
| 1881 |
},
|
| 1882 |
+
"node_modules/@types/chai": {
|
| 1883 |
+
"version": "5.2.3",
|
| 1884 |
+
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
|
| 1885 |
+
"integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
|
| 1886 |
+
"dev": true,
|
| 1887 |
+
"license": "MIT",
|
| 1888 |
+
"dependencies": {
|
| 1889 |
+
"@types/deep-eql": "*",
|
| 1890 |
+
"assertion-error": "^2.0.1"
|
| 1891 |
+
}
|
| 1892 |
+
},
|
| 1893 |
+
"node_modules/@types/deep-eql": {
|
| 1894 |
+
"version": "4.0.2",
|
| 1895 |
+
"resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
|
| 1896 |
+
"integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
|
| 1897 |
+
"dev": true,
|
| 1898 |
+
"license": "MIT"
|
| 1899 |
+
},
|
| 1900 |
"node_modules/@types/estree": {
|
| 1901 |
"version": "1.0.8",
|
| 1902 |
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
|
|
|
| 2240 |
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
|
| 2241 |
}
|
| 2242 |
},
|
| 2243 |
+
"node_modules/@vitest/expect": {
|
| 2244 |
+
"version": "4.0.15",
|
| 2245 |
+
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.15.tgz",
|
| 2246 |
+
"integrity": "sha512-Gfyva9/GxPAWXIWjyGDli9O+waHDC0Q0jaLdFP1qPAUUfo1FEXPXUfUkp3eZA0sSq340vPycSyOlYUeM15Ft1w==",
|
| 2247 |
+
"dev": true,
|
| 2248 |
+
"license": "MIT",
|
| 2249 |
+
"dependencies": {
|
| 2250 |
+
"@standard-schema/spec": "^1.0.0",
|
| 2251 |
+
"@types/chai": "^5.2.2",
|
| 2252 |
+
"@vitest/spy": "4.0.15",
|
| 2253 |
+
"@vitest/utils": "4.0.15",
|
| 2254 |
+
"chai": "^6.2.1",
|
| 2255 |
+
"tinyrainbow": "^3.0.3"
|
| 2256 |
+
},
|
| 2257 |
+
"funding": {
|
| 2258 |
+
"url": "https://opencollective.com/vitest"
|
| 2259 |
+
}
|
| 2260 |
+
},
|
| 2261 |
+
"node_modules/@vitest/mocker": {
|
| 2262 |
+
"version": "4.0.15",
|
| 2263 |
+
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.15.tgz",
|
| 2264 |
+
"integrity": "sha512-CZ28GLfOEIFkvCFngN8Sfx5h+Se0zN+h4B7yOsPVCcgtiO7t5jt9xQh2E1UkFep+eb9fjyMfuC5gBypwb07fvQ==",
|
| 2265 |
+
"dev": true,
|
| 2266 |
+
"license": "MIT",
|
| 2267 |
+
"dependencies": {
|
| 2268 |
+
"@vitest/spy": "4.0.15",
|
| 2269 |
+
"estree-walker": "^3.0.3",
|
| 2270 |
+
"magic-string": "^0.30.21"
|
| 2271 |
+
},
|
| 2272 |
+
"funding": {
|
| 2273 |
+
"url": "https://opencollective.com/vitest"
|
| 2274 |
+
},
|
| 2275 |
+
"peerDependencies": {
|
| 2276 |
+
"msw": "^2.4.9",
|
| 2277 |
+
"vite": "^6.0.0 || ^7.0.0-0"
|
| 2278 |
+
},
|
| 2279 |
+
"peerDependenciesMeta": {
|
| 2280 |
+
"msw": {
|
| 2281 |
+
"optional": true
|
| 2282 |
+
},
|
| 2283 |
+
"vite": {
|
| 2284 |
+
"optional": true
|
| 2285 |
+
}
|
| 2286 |
+
}
|
| 2287 |
+
},
|
| 2288 |
+
"node_modules/@vitest/pretty-format": {
|
| 2289 |
+
"version": "4.0.15",
|
| 2290 |
+
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.15.tgz",
|
| 2291 |
+
"integrity": "sha512-SWdqR8vEv83WtZcrfLNqlqeQXlQLh2iilO1Wk1gv4eiHKjEzvgHb2OVc3mIPyhZE6F+CtfYjNlDJwP5MN6Km7A==",
|
| 2292 |
+
"dev": true,
|
| 2293 |
+
"license": "MIT",
|
| 2294 |
+
"dependencies": {
|
| 2295 |
+
"tinyrainbow": "^3.0.3"
|
| 2296 |
+
},
|
| 2297 |
+
"funding": {
|
| 2298 |
+
"url": "https://opencollective.com/vitest"
|
| 2299 |
+
}
|
| 2300 |
+
},
|
| 2301 |
+
"node_modules/@vitest/runner": {
|
| 2302 |
+
"version": "4.0.15",
|
| 2303 |
+
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.15.tgz",
|
| 2304 |
+
"integrity": "sha512-+A+yMY8dGixUhHmNdPUxOh0la6uVzun86vAbuMT3hIDxMrAOmn5ILBHm8ajrqHE0t8R9T1dGnde1A5DTnmi3qw==",
|
| 2305 |
+
"dev": true,
|
| 2306 |
+
"license": "MIT",
|
| 2307 |
+
"dependencies": {
|
| 2308 |
+
"@vitest/utils": "4.0.15",
|
| 2309 |
+
"pathe": "^2.0.3"
|
| 2310 |
+
},
|
| 2311 |
+
"funding": {
|
| 2312 |
+
"url": "https://opencollective.com/vitest"
|
| 2313 |
+
}
|
| 2314 |
+
},
|
| 2315 |
+
"node_modules/@vitest/snapshot": {
|
| 2316 |
+
"version": "4.0.15",
|
| 2317 |
+
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.15.tgz",
|
| 2318 |
+
"integrity": "sha512-A7Ob8EdFZJIBjLjeO0DZF4lqR6U7Ydi5/5LIZ0xcI+23lYlsYJAfGn8PrIWTYdZQRNnSRlzhg0zyGu37mVdy5g==",
|
| 2319 |
+
"dev": true,
|
| 2320 |
+
"license": "MIT",
|
| 2321 |
+
"dependencies": {
|
| 2322 |
+
"@vitest/pretty-format": "4.0.15",
|
| 2323 |
+
"magic-string": "^0.30.21",
|
| 2324 |
+
"pathe": "^2.0.3"
|
| 2325 |
+
},
|
| 2326 |
+
"funding": {
|
| 2327 |
+
"url": "https://opencollective.com/vitest"
|
| 2328 |
+
}
|
| 2329 |
+
},
|
| 2330 |
+
"node_modules/@vitest/spy": {
|
| 2331 |
+
"version": "4.0.15",
|
| 2332 |
+
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.15.tgz",
|
| 2333 |
+
"integrity": "sha512-+EIjOJmnY6mIfdXtE/bnozKEvTC4Uczg19yeZ2vtCz5Yyb0QQ31QWVQ8hswJ3Ysx/K2EqaNsVanjr//2+P3FHw==",
|
| 2334 |
+
"dev": true,
|
| 2335 |
+
"license": "MIT",
|
| 2336 |
+
"funding": {
|
| 2337 |
+
"url": "https://opencollective.com/vitest"
|
| 2338 |
+
}
|
| 2339 |
+
},
|
| 2340 |
+
"node_modules/@vitest/utils": {
|
| 2341 |
+
"version": "4.0.15",
|
| 2342 |
+
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.15.tgz",
|
| 2343 |
+
"integrity": "sha512-HXjPW2w5dxhTD0dLwtYHDnelK3j8sR8cWIaLxr22evTyY6q8pRCjZSmhRWVjBaOVXChQd6AwMzi9pucorXCPZA==",
|
| 2344 |
+
"dev": true,
|
| 2345 |
+
"license": "MIT",
|
| 2346 |
+
"dependencies": {
|
| 2347 |
+
"@vitest/pretty-format": "4.0.15",
|
| 2348 |
+
"tinyrainbow": "^3.0.3"
|
| 2349 |
+
},
|
| 2350 |
+
"funding": {
|
| 2351 |
+
"url": "https://opencollective.com/vitest"
|
| 2352 |
+
}
|
| 2353 |
+
},
|
| 2354 |
"node_modules/acorn": {
|
| 2355 |
"version": "8.15.0",
|
| 2356 |
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
|
|
|
| 2414 |
"dev": true,
|
| 2415 |
"license": "Python-2.0"
|
| 2416 |
},
|
| 2417 |
+
"node_modules/assertion-error": {
|
| 2418 |
+
"version": "2.0.1",
|
| 2419 |
+
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
|
| 2420 |
+
"integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
|
| 2421 |
+
"dev": true,
|
| 2422 |
+
"license": "MIT",
|
| 2423 |
+
"engines": {
|
| 2424 |
+
"node": ">=12"
|
| 2425 |
+
}
|
| 2426 |
+
},
|
| 2427 |
"node_modules/autoprefixer": {
|
| 2428 |
"version": "10.4.21",
|
| 2429 |
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
|
|
|
|
| 2568 |
],
|
| 2569 |
"license": "CC-BY-4.0"
|
| 2570 |
},
|
| 2571 |
+
"node_modules/chai": {
|
| 2572 |
+
"version": "6.2.1",
|
| 2573 |
+
"resolved": "https://registry.npmjs.org/chai/-/chai-6.2.1.tgz",
|
| 2574 |
+
"integrity": "sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==",
|
| 2575 |
+
"dev": true,
|
| 2576 |
+
"license": "MIT",
|
| 2577 |
+
"engines": {
|
| 2578 |
+
"node": ">=18"
|
| 2579 |
+
}
|
| 2580 |
+
},
|
| 2581 |
"node_modules/chalk": {
|
| 2582 |
"version": "4.1.2",
|
| 2583 |
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
|
|
|
| 2751 |
"node": ">=10.13.0"
|
| 2752 |
}
|
| 2753 |
},
|
| 2754 |
+
"node_modules/es-module-lexer": {
|
| 2755 |
+
"version": "1.7.0",
|
| 2756 |
+
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
|
| 2757 |
+
"integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
|
| 2758 |
+
"dev": true,
|
| 2759 |
+
"license": "MIT"
|
| 2760 |
+
},
|
| 2761 |
"node_modules/esbuild": {
|
| 2762 |
"version": "0.25.10",
|
| 2763 |
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz",
|
|
|
|
| 2991 |
"node": ">=4.0"
|
| 2992 |
}
|
| 2993 |
},
|
| 2994 |
+
"node_modules/estree-walker": {
|
| 2995 |
+
"version": "3.0.3",
|
| 2996 |
+
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
|
| 2997 |
+
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
|
| 2998 |
+
"dev": true,
|
| 2999 |
+
"license": "MIT",
|
| 3000 |
+
"dependencies": {
|
| 3001 |
+
"@types/estree": "^1.0.0"
|
| 3002 |
+
}
|
| 3003 |
+
},
|
| 3004 |
"node_modules/esutils": {
|
| 3005 |
"version": "2.0.3",
|
| 3006 |
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
|
|
|
| 3011 |
"node": ">=0.10.0"
|
| 3012 |
}
|
| 3013 |
},
|
| 3014 |
+
"node_modules/expect-type": {
|
| 3015 |
+
"version": "1.2.2",
|
| 3016 |
+
"resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz",
|
| 3017 |
+
"integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==",
|
| 3018 |
+
"dev": true,
|
| 3019 |
+
"license": "Apache-2.0",
|
| 3020 |
+
"engines": {
|
| 3021 |
+
"node": ">=12.0.0"
|
| 3022 |
+
}
|
| 3023 |
+
},
|
| 3024 |
"node_modules/fast-deep-equal": {
|
| 3025 |
"version": "3.1.3",
|
| 3026 |
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
|
|
|
| 3741 |
}
|
| 3742 |
},
|
| 3743 |
"node_modules/magic-string": {
|
| 3744 |
+
"version": "0.30.21",
|
| 3745 |
+
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
| 3746 |
+
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
|
| 3747 |
"dev": true,
|
| 3748 |
"license": "MIT",
|
| 3749 |
"dependencies": {
|
|
|
|
| 3860 |
"node": ">=0.10.0"
|
| 3861 |
}
|
| 3862 |
},
|
| 3863 |
+
"node_modules/obug": {
|
| 3864 |
+
"version": "2.1.1",
|
| 3865 |
+
"resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz",
|
| 3866 |
+
"integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==",
|
| 3867 |
+
"dev": true,
|
| 3868 |
+
"funding": [
|
| 3869 |
+
"https://github.com/sponsors/sxzz",
|
| 3870 |
+
"https://opencollective.com/debug"
|
| 3871 |
+
],
|
| 3872 |
+
"license": "MIT"
|
| 3873 |
+
},
|
| 3874 |
"node_modules/optionator": {
|
| 3875 |
"version": "0.9.4",
|
| 3876 |
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
|
|
|
| 3954 |
"node": ">=8"
|
| 3955 |
}
|
| 3956 |
},
|
| 3957 |
+
"node_modules/pathe": {
|
| 3958 |
+
"version": "2.0.3",
|
| 3959 |
+
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
| 3960 |
+
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
| 3961 |
+
"dev": true,
|
| 3962 |
+
"license": "MIT"
|
| 3963 |
+
},
|
| 3964 |
"node_modules/picocolors": {
|
| 3965 |
"version": "1.1.1",
|
| 3966 |
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
|
|
|
| 4363 |
"url": "https://www.paypal.me/tiviesantos"
|
| 4364 |
}
|
| 4365 |
},
|
| 4366 |
+
"node_modules/siginfo": {
|
| 4367 |
+
"version": "2.0.0",
|
| 4368 |
+
"resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
|
| 4369 |
+
"integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
|
| 4370 |
+
"dev": true,
|
| 4371 |
+
"license": "ISC"
|
| 4372 |
+
},
|
| 4373 |
"node_modules/source-map-js": {
|
| 4374 |
"version": "1.2.1",
|
| 4375 |
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
|
|
|
| 4380 |
"node": ">=0.10.0"
|
| 4381 |
}
|
| 4382 |
},
|
| 4383 |
+
"node_modules/stackback": {
|
| 4384 |
+
"version": "0.0.2",
|
| 4385 |
+
"resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
|
| 4386 |
+
"integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
|
| 4387 |
+
"dev": true,
|
| 4388 |
+
"license": "MIT"
|
| 4389 |
+
},
|
| 4390 |
+
"node_modules/std-env": {
|
| 4391 |
+
"version": "3.10.0",
|
| 4392 |
+
"resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
|
| 4393 |
+
"integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
|
| 4394 |
+
"dev": true,
|
| 4395 |
+
"license": "MIT"
|
| 4396 |
+
},
|
| 4397 |
"node_modules/strip-json-comments": {
|
| 4398 |
"version": "3.1.1",
|
| 4399 |
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
|
|
|
| 4468 |
"node": ">=18"
|
| 4469 |
}
|
| 4470 |
},
|
| 4471 |
+
"node_modules/tinybench": {
|
| 4472 |
+
"version": "2.9.0",
|
| 4473 |
+
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
|
| 4474 |
+
"integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
|
| 4475 |
+
"dev": true,
|
| 4476 |
+
"license": "MIT"
|
| 4477 |
+
},
|
| 4478 |
+
"node_modules/tinyexec": {
|
| 4479 |
+
"version": "1.0.2",
|
| 4480 |
+
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz",
|
| 4481 |
+
"integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==",
|
| 4482 |
+
"dev": true,
|
| 4483 |
+
"license": "MIT",
|
| 4484 |
+
"engines": {
|
| 4485 |
+
"node": ">=18"
|
| 4486 |
+
}
|
| 4487 |
+
},
|
| 4488 |
"node_modules/tinyglobby": {
|
| 4489 |
"version": "0.2.15",
|
| 4490 |
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
|
|
|
| 4515 |
"url": "https://github.com/sponsors/jonschlinkert"
|
| 4516 |
}
|
| 4517 |
},
|
| 4518 |
+
"node_modules/tinyrainbow": {
|
| 4519 |
+
"version": "3.0.3",
|
| 4520 |
+
"resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz",
|
| 4521 |
+
"integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==",
|
| 4522 |
+
"dev": true,
|
| 4523 |
+
"license": "MIT",
|
| 4524 |
+
"engines": {
|
| 4525 |
+
"node": ">=14.0.0"
|
| 4526 |
+
}
|
| 4527 |
+
},
|
| 4528 |
"node_modules/to-regex-range": {
|
| 4529 |
"version": "5.0.1",
|
| 4530 |
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
|
|
|
| 4806 |
"url": "https://github.com/sponsors/jonschlinkert"
|
| 4807 |
}
|
| 4808 |
},
|
| 4809 |
+
"node_modules/vitest": {
|
| 4810 |
+
"version": "4.0.15",
|
| 4811 |
+
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.15.tgz",
|
| 4812 |
+
"integrity": "sha512-n1RxDp8UJm6N0IbJLQo+yzLZ2sQCDyl1o0LeugbPWf8+8Fttp29GghsQBjYJVmWq3gBFfe9Hs1spR44vovn2wA==",
|
| 4813 |
+
"dev": true,
|
| 4814 |
+
"license": "MIT",
|
| 4815 |
+
"dependencies": {
|
| 4816 |
+
"@vitest/expect": "4.0.15",
|
| 4817 |
+
"@vitest/mocker": "4.0.15",
|
| 4818 |
+
"@vitest/pretty-format": "4.0.15",
|
| 4819 |
+
"@vitest/runner": "4.0.15",
|
| 4820 |
+
"@vitest/snapshot": "4.0.15",
|
| 4821 |
+
"@vitest/spy": "4.0.15",
|
| 4822 |
+
"@vitest/utils": "4.0.15",
|
| 4823 |
+
"es-module-lexer": "^1.7.0",
|
| 4824 |
+
"expect-type": "^1.2.2",
|
| 4825 |
+
"magic-string": "^0.30.21",
|
| 4826 |
+
"obug": "^2.1.1",
|
| 4827 |
+
"pathe": "^2.0.3",
|
| 4828 |
+
"picomatch": "^4.0.3",
|
| 4829 |
+
"std-env": "^3.10.0",
|
| 4830 |
+
"tinybench": "^2.9.0",
|
| 4831 |
+
"tinyexec": "^1.0.2",
|
| 4832 |
+
"tinyglobby": "^0.2.15",
|
| 4833 |
+
"tinyrainbow": "^3.0.3",
|
| 4834 |
+
"vite": "^6.0.0 || ^7.0.0",
|
| 4835 |
+
"why-is-node-running": "^2.3.0"
|
| 4836 |
+
},
|
| 4837 |
+
"bin": {
|
| 4838 |
+
"vitest": "vitest.mjs"
|
| 4839 |
+
},
|
| 4840 |
+
"engines": {
|
| 4841 |
+
"node": "^20.0.0 || ^22.0.0 || >=24.0.0"
|
| 4842 |
+
},
|
| 4843 |
+
"funding": {
|
| 4844 |
+
"url": "https://opencollective.com/vitest"
|
| 4845 |
+
},
|
| 4846 |
+
"peerDependencies": {
|
| 4847 |
+
"@edge-runtime/vm": "*",
|
| 4848 |
+
"@opentelemetry/api": "^1.9.0",
|
| 4849 |
+
"@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
|
| 4850 |
+
"@vitest/browser-playwright": "4.0.15",
|
| 4851 |
+
"@vitest/browser-preview": "4.0.15",
|
| 4852 |
+
"@vitest/browser-webdriverio": "4.0.15",
|
| 4853 |
+
"@vitest/ui": "4.0.15",
|
| 4854 |
+
"happy-dom": "*",
|
| 4855 |
+
"jsdom": "*"
|
| 4856 |
+
},
|
| 4857 |
+
"peerDependenciesMeta": {
|
| 4858 |
+
"@edge-runtime/vm": {
|
| 4859 |
+
"optional": true
|
| 4860 |
+
},
|
| 4861 |
+
"@opentelemetry/api": {
|
| 4862 |
+
"optional": true
|
| 4863 |
+
},
|
| 4864 |
+
"@types/node": {
|
| 4865 |
+
"optional": true
|
| 4866 |
+
},
|
| 4867 |
+
"@vitest/browser-playwright": {
|
| 4868 |
+
"optional": true
|
| 4869 |
+
},
|
| 4870 |
+
"@vitest/browser-preview": {
|
| 4871 |
+
"optional": true
|
| 4872 |
+
},
|
| 4873 |
+
"@vitest/browser-webdriverio": {
|
| 4874 |
+
"optional": true
|
| 4875 |
+
},
|
| 4876 |
+
"@vitest/ui": {
|
| 4877 |
+
"optional": true
|
| 4878 |
+
},
|
| 4879 |
+
"happy-dom": {
|
| 4880 |
+
"optional": true
|
| 4881 |
+
},
|
| 4882 |
+
"jsdom": {
|
| 4883 |
+
"optional": true
|
| 4884 |
+
}
|
| 4885 |
+
}
|
| 4886 |
+
},
|
| 4887 |
+
"node_modules/vitest/node_modules/picomatch": {
|
| 4888 |
+
"version": "4.0.3",
|
| 4889 |
+
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
| 4890 |
+
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
| 4891 |
+
"dev": true,
|
| 4892 |
+
"license": "MIT",
|
| 4893 |
+
"engines": {
|
| 4894 |
+
"node": ">=12"
|
| 4895 |
+
},
|
| 4896 |
+
"funding": {
|
| 4897 |
+
"url": "https://github.com/sponsors/jonschlinkert"
|
| 4898 |
+
}
|
| 4899 |
+
},
|
| 4900 |
"node_modules/which": {
|
| 4901 |
"version": "2.0.2",
|
| 4902 |
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
|
|
|
| 4913 |
"node": ">= 8"
|
| 4914 |
}
|
| 4915 |
},
|
| 4916 |
+
"node_modules/why-is-node-running": {
|
| 4917 |
+
"version": "2.3.0",
|
| 4918 |
+
"resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
|
| 4919 |
+
"integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
|
| 4920 |
+
"dev": true,
|
| 4921 |
+
"license": "MIT",
|
| 4922 |
+
"dependencies": {
|
| 4923 |
+
"siginfo": "^2.0.0",
|
| 4924 |
+
"stackback": "0.0.2"
|
| 4925 |
+
},
|
| 4926 |
+
"bin": {
|
| 4927 |
+
"why-is-node-running": "cli.js"
|
| 4928 |
+
},
|
| 4929 |
+
"engines": {
|
| 4930 |
+
"node": ">=8"
|
| 4931 |
+
}
|
| 4932 |
+
},
|
| 4933 |
"node_modules/word-wrap": {
|
| 4934 |
"version": "1.2.5",
|
| 4935 |
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
package.json
CHANGED
|
@@ -7,7 +7,8 @@
|
|
| 7 |
"dev": "vite",
|
| 8 |
"build": "tsc -b && vite build",
|
| 9 |
"lint": "eslint .",
|
| 10 |
-
"preview": "vite preview"
|
|
|
|
| 11 |
},
|
| 12 |
"dependencies": {
|
| 13 |
"@huggingface/transformers": "../transformers.js",
|
|
@@ -42,6 +43,7 @@
|
|
| 42 |
"typescript-eslint": "^8.44.0",
|
| 43 |
"vite": "^7.1.7",
|
| 44 |
"vite-plugin-html-config": "^2.0.2",
|
| 45 |
-
"vite-tsconfig-paths": "^5.1.4"
|
|
|
|
| 46 |
}
|
| 47 |
}
|
|
|
|
| 7 |
"dev": "vite",
|
| 8 |
"build": "tsc -b && vite build",
|
| 9 |
"lint": "eslint .",
|
| 10 |
+
"preview": "vite preview",
|
| 11 |
+
"test": "vitest"
|
| 12 |
},
|
| 13 |
"dependencies": {
|
| 14 |
"@huggingface/transformers": "../transformers.js",
|
|
|
|
| 43 |
"typescript-eslint": "^8.44.0",
|
| 44 |
"vite": "^7.1.7",
|
| 45 |
"vite-plugin-html-config": "^2.0.2",
|
| 46 |
+
"vite-tsconfig-paths": "^5.1.4",
|
| 47 |
+
"vitest": "^4.0.15"
|
| 48 |
}
|
| 49 |
}
|
src/chat/ChatForm.tsx
CHANGED
|
@@ -22,7 +22,7 @@ export default function ChatForm({
|
|
| 22 |
}) {
|
| 23 |
const { control, handleSubmit, reset } = useForm<FormParams>({
|
| 24 |
defaultValues: {
|
| 25 |
-
input: "",
|
| 26 |
},
|
| 27 |
});
|
| 28 |
|
|
|
|
| 22 |
}) {
|
| 23 |
const { control, handleSubmit, reset } = useForm<FormParams>({
|
| 24 |
defaultValues: {
|
| 25 |
+
input: "Whats the current time?",
|
| 26 |
},
|
| 27 |
});
|
| 28 |
|
src/textGeneration/TextGeneration.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
| 1 |
import { type Message } from "@huggingface/transformers";
|
| 2 |
-
|
| 3 |
import {
|
| 4 |
-
type WebMCPTool,
|
| 5 |
executeToolCall,
|
| 6 |
splitResponse,
|
| 7 |
webMCPToolToChatTemplateTool,
|
| 8 |
-
} from "
|
|
|
|
|
|
|
| 9 |
import {
|
| 10 |
type ChatMessage,
|
| 11 |
type ChatMessageAssistant,
|
|
|
|
| 1 |
import { type Message } from "@huggingface/transformers";
|
|
|
|
| 2 |
import {
|
|
|
|
| 3 |
executeToolCall,
|
| 4 |
splitResponse,
|
| 5 |
webMCPToolToChatTemplateTool,
|
| 6 |
+
} from "@utils/webMcp";
|
| 7 |
+
import type { WebMCPTool } from "@utils/webMcp/types.ts";
|
| 8 |
+
|
| 9 |
import {
|
| 10 |
type ChatMessage,
|
| 11 |
type ChatMessageAssistant,
|
src/textGeneration/types.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
| 1 |
import { type Message } from "@huggingface/transformers";
|
| 2 |
|
| 3 |
import type { MODELS } from "../utils/models.ts";
|
| 4 |
-
import type {
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
export enum RequestType {
|
| 7 |
INITIALIZE_MODEL,
|
|
|
|
| 1 |
import { type Message } from "@huggingface/transformers";
|
| 2 |
|
| 3 |
import type { MODELS } from "../utils/models.ts";
|
| 4 |
+
import type {
|
| 5 |
+
ChatTemplateTool,
|
| 6 |
+
ToolCallPayload,
|
| 7 |
+
} from "../utils/webMcp/types.ts";
|
| 8 |
|
| 9 |
export enum RequestType {
|
| 10 |
INITIALIZE_MODEL,
|
src/textGeneration/worker/textGenerationWorker.ts
CHANGED
|
@@ -121,6 +121,9 @@ self.onmessage = async ({ data }: MessageEvent<Request>) => {
|
|
| 121 |
let numTokens = 0;
|
| 122 |
let tps: number = 0;
|
| 123 |
|
|
|
|
|
|
|
|
|
|
| 124 |
const tokenCallbackFunction = () => {
|
| 125 |
firstTokenTime ??= performance.now();
|
| 126 |
if (numTokens++ > 0) {
|
|
@@ -128,16 +131,17 @@ self.onmessage = async ({ data }: MessageEvent<Request>) => {
|
|
| 128 |
}
|
| 129 |
};
|
| 130 |
|
| 131 |
-
const callbackFunction = (chunk: string) =>
|
| 132 |
postMessage({
|
| 133 |
type: ResponseType.GENERATE_TEXT_CHUNK,
|
| 134 |
-
chunk,
|
| 135 |
requestId,
|
| 136 |
});
|
|
|
|
| 137 |
|
| 138 |
const streamer = new TextStreamer(tokenizer, {
|
| 139 |
skip_prompt: true,
|
| 140 |
-
skip_special_tokens:
|
| 141 |
token_callback_function: tokenCallbackFunction,
|
| 142 |
callback_function: callbackFunction,
|
| 143 |
});
|
|
@@ -157,16 +161,18 @@ self.onmessage = async ({ data }: MessageEvent<Request>) => {
|
|
| 157 |
const ended = performance.now();
|
| 158 |
|
| 159 |
const lengthOfInput = input.input_ids.dims[1];
|
| 160 |
-
const response =
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
|
|
|
|
|
|
| 170 |
|
| 171 |
const template = tokenizer.batch_decode(sequences, {
|
| 172 |
skip_special_tokens: false,
|
|
|
|
| 121 |
let numTokens = 0;
|
| 122 |
let tps: number = 0;
|
| 123 |
|
| 124 |
+
const removeEosToken = (content: string): string =>
|
| 125 |
+
content.replace(tokenizer.eos_token, "");
|
| 126 |
+
|
| 127 |
const tokenCallbackFunction = () => {
|
| 128 |
firstTokenTime ??= performance.now();
|
| 129 |
if (numTokens++ > 0) {
|
|
|
|
| 131 |
}
|
| 132 |
};
|
| 133 |
|
| 134 |
+
const callbackFunction = (chunk: string) => {
|
| 135 |
postMessage({
|
| 136 |
type: ResponseType.GENERATE_TEXT_CHUNK,
|
| 137 |
+
chunk: removeEosToken(chunk),
|
| 138 |
requestId,
|
| 139 |
});
|
| 140 |
+
};
|
| 141 |
|
| 142 |
const streamer = new TextStreamer(tokenizer, {
|
| 143 |
skip_prompt: true,
|
| 144 |
+
skip_special_tokens: false,
|
| 145 |
token_callback_function: tokenCallbackFunction,
|
| 146 |
callback_function: callbackFunction,
|
| 147 |
});
|
|
|
|
| 161 |
const ended = performance.now();
|
| 162 |
|
| 163 |
const lengthOfInput = input.input_ids.dims[1];
|
| 164 |
+
const response = removeEosToken(
|
| 165 |
+
tokenizer.batch_decode(
|
| 166 |
+
/**
|
| 167 |
+
* First argument (null): Don't slice dimension 0 (the batch dimension) - keep all batches
|
| 168 |
+
* Second argument ([lengthOfInput, Number.MAX_SAFE_INTEGER]): For dimension 1 (the sequence/token dimension), slice from index lengthOfInput to the end
|
| 169 |
+
*/
|
| 170 |
+
sequences.slice(null, [lengthOfInput, Number.MAX_SAFE_INTEGER]),
|
| 171 |
+
{
|
| 172 |
+
skip_special_tokens: false,
|
| 173 |
+
}
|
| 174 |
+
)[0]
|
| 175 |
+
);
|
| 176 |
|
| 177 |
const template = tokenizer.batch_decode(sequences, {
|
| 178 |
skip_special_tokens: false,
|
src/utils/calculateDownloadProgress.ts
CHANGED
|
@@ -62,6 +62,13 @@ export const calculateDownloadProgress = (
|
|
| 62 |
const percentage =
|
| 63 |
totalSize > 0 ? round((totalLoaded / totalSize) * 100, 2) : 0;
|
| 64 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
callback({
|
| 66 |
percentage,
|
| 67 |
total: totalSize,
|
|
|
|
| 62 |
const percentage =
|
| 63 |
totalSize > 0 ? round((totalLoaded / totalSize) * 100, 2) : 0;
|
| 64 |
|
| 65 |
+
/*if (percentage === 100) {
|
| 66 |
+
console.log("totalSize");
|
| 67 |
+
console.log(totalSize);
|
| 68 |
+
console.log("filesRecord");
|
| 69 |
+
console.log(filesRecord);
|
| 70 |
+
}*/
|
| 71 |
+
|
| 72 |
callback({
|
| 73 |
percentage,
|
| 74 |
total: totalSize,
|
src/utils/context/chatSettings/ChatSettingsModalForm.tsx
CHANGED
|
@@ -34,10 +34,42 @@ export default function ChatSettingsModalForm({
|
|
| 34 |
defaultValues,
|
| 35 |
});
|
| 36 |
|
| 37 |
-
const modelOptions = Object.
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
const toolOptions = TOOLS.map((tool) => ({
|
| 43 |
name: tool.name,
|
|
|
|
| 34 |
defaultValues,
|
| 35 |
});
|
| 36 |
|
| 37 |
+
const modelOptions = Object.values(
|
| 38 |
+
Object.entries(MODELS).reduce(
|
| 39 |
+
(groups, [key, model]) => {
|
| 40 |
+
const groupName = model.group;
|
| 41 |
+
|
| 42 |
+
if (!groups[groupName]) {
|
| 43 |
+
groups[groupName] = {
|
| 44 |
+
label: groupName.charAt(0).toUpperCase() + groupName.slice(1),
|
| 45 |
+
options: [],
|
| 46 |
+
};
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
groups[groupName].options.push({
|
| 50 |
+
value: key,
|
| 51 |
+
label: `${model.title} - ${formatBytes(model.size)}${downloadedModels.includes(key) ? " *" : ""}`,
|
| 52 |
+
title: model.title,
|
| 53 |
+
});
|
| 54 |
+
|
| 55 |
+
return groups;
|
| 56 |
+
},
|
| 57 |
+
{} as Record<
|
| 58 |
+
string,
|
| 59 |
+
{
|
| 60 |
+
label: string;
|
| 61 |
+
options: Array<{ value: string; label: string; title: string }>;
|
| 62 |
+
}
|
| 63 |
+
>
|
| 64 |
+
)
|
| 65 |
+
)
|
| 66 |
+
.sort((a, b) => a.label.localeCompare(b.label))
|
| 67 |
+
.map((group) => ({
|
| 68 |
+
...group,
|
| 69 |
+
options: group.options
|
| 70 |
+
.sort((a, b) => a.title.localeCompare(b.title))
|
| 71 |
+
.map(({ value, label }) => ({ value, label })),
|
| 72 |
+
}));
|
| 73 |
|
| 74 |
const toolOptions = TOOLS.map((tool) => ({
|
| 75 |
name: tool.name,
|
src/utils/models.ts
CHANGED
|
@@ -8,9 +8,26 @@ export interface Model {
|
|
| 8 |
device: "webgpu";
|
| 9 |
size: number;
|
| 10 |
files: Record<string, number>;
|
|
|
|
| 11 |
}
|
| 12 |
|
| 13 |
export const MODELS: Record<string, Model> = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
apertus8BInstruct2509q4f16: {
|
| 15 |
modelId: "onnx-community/Apertus-8B-Instruct-2509-ONNX",
|
| 16 |
title: "Apertus 8B Instruct 2509 (q4f16)",
|
|
@@ -25,21 +42,28 @@ export const MODELS: Record<string, Model> = {
|
|
| 25 |
"onnx/model_q4f16.onnx_data_2": 487_391_232,
|
| 26 |
"onnx/model_q4f16.onnx_data": 2_093_498_368,
|
| 27 |
},
|
|
|
|
| 28 |
},
|
| 29 |
-
|
| 30 |
modelId: "onnx-community/Apertus-8B-Instruct-2509-ONNX",
|
| 31 |
-
title: "Apertus 8B Instruct 2509 (
|
| 32 |
-
dtype: "
|
| 33 |
device: "webgpu",
|
| 34 |
-
size:
|
| 35 |
files: {
|
| 36 |
"config.json": 1_193,
|
| 37 |
"generation_config.json": 141,
|
| 38 |
-
"onnx/
|
| 39 |
-
"onnx/
|
| 40 |
-
"onnx/
|
| 41 |
-
"onnx/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
},
|
|
|
|
| 43 |
},
|
| 44 |
gemma3270m: {
|
| 45 |
modelId: "onnx-community/gemma-3-270m-it-ONNX",
|
|
@@ -55,6 +79,7 @@ export const MODELS: Record<string, Model> = {
|
|
| 55 |
"onnx/model.onnx": 201_742,
|
| 56 |
"onnx/model.onnx_data": 1_139_501_568,
|
| 57 |
},
|
|
|
|
| 58 |
},
|
| 59 |
granite350m: {
|
| 60 |
modelId: "onnx-community/granite-4.0-350m-ONNX-web",
|
|
@@ -70,6 +95,7 @@ export const MODELS: Record<string, Model> = {
|
|
| 70 |
"onnx/model_fp16.onnx": 202_945,
|
| 71 |
"onnx/model_fp16.onnx_data": 708_954_112,
|
| 72 |
},
|
|
|
|
| 73 |
},
|
| 74 |
granite1B: {
|
| 75 |
modelId: "onnx-community/granite-4.0-1b-ONNX-web",
|
|
@@ -85,6 +111,7 @@ export const MODELS: Record<string, Model> = {
|
|
| 85 |
"generation_config.json": 147,
|
| 86 |
"onnx/model_q4.onnx_data": 1_781_145_600,
|
| 87 |
},
|
|
|
|
| 88 |
},
|
| 89 |
granite3B: {
|
| 90 |
modelId: "onnx-community/granite-4.0-micro-ONNX-web",
|
|
@@ -101,6 +128,7 @@ export const MODELS: Record<string, Model> = {
|
|
| 101 |
"onnx/model_q4f16.onnx_data_1": 212_336_640,
|
| 102 |
"generation_config.json": 152,
|
| 103 |
},
|
|
|
|
| 104 |
},
|
| 105 |
qwen34B: {
|
| 106 |
modelId: "onnx-community/Qwen3-4B-ONNX",
|
|
@@ -117,6 +145,7 @@ export const MODELS: Record<string, Model> = {
|
|
| 117 |
"onnx/model_q4f16.onnx_data_1": 677_150_720,
|
| 118 |
"onnx/model_q4f16.onnx_data": 2_096_005_120,
|
| 119 |
},
|
|
|
|
| 120 |
},
|
| 121 |
smolLM33B: {
|
| 122 |
modelId: "HuggingFaceTB/SmolLM3-3B-ONNX",
|
|
@@ -132,6 +161,49 @@ export const MODELS: Record<string, Model> = {
|
|
| 132 |
"generation_config.json": 182,
|
| 133 |
"onnx/model_q4f16.onnx_data": 2_124_320_768,
|
| 134 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
},
|
| 136 |
} as const;
|
| 137 |
|
|
|
|
| 8 |
device: "webgpu";
|
| 9 |
size: number;
|
| 10 |
files: Record<string, number>;
|
| 11 |
+
group: string;
|
| 12 |
}
|
| 13 |
|
| 14 |
export const MODELS: Record<string, Model> = {
|
| 15 |
+
apertus8BInstruct2509q4: {
|
| 16 |
+
modelId: "onnx-community/Apertus-8B-Instruct-2509-ONNX",
|
| 17 |
+
title: "Apertus 8B Instruct 2509 (q4)",
|
| 18 |
+
dtype: "q4",
|
| 19 |
+
device: "webgpu",
|
| 20 |
+
size: 5_194_104_473,
|
| 21 |
+
files: {
|
| 22 |
+
"config.json": 1_193,
|
| 23 |
+
"generation_config.json": 141,
|
| 24 |
+
"onnx/model_q4.onnx_data_2": 1_015_676_928,
|
| 25 |
+
"onnx/model_q4.onnx": 489_827,
|
| 26 |
+
"onnx/model_q4.onnx_data": 2_082_095_104,
|
| 27 |
+
"onnx/model_q4.onnx_data_1": 2_095_841_280,
|
| 28 |
+
},
|
| 29 |
+
group: "Apertus",
|
| 30 |
+
},
|
| 31 |
apertus8BInstruct2509q4f16: {
|
| 32 |
modelId: "onnx-community/Apertus-8B-Instruct-2509-ONNX",
|
| 33 |
title: "Apertus 8B Instruct 2509 (q4f16)",
|
|
|
|
| 42 |
"onnx/model_q4f16.onnx_data_2": 487_391_232,
|
| 43 |
"onnx/model_q4f16.onnx_data": 2_093_498_368,
|
| 44 |
},
|
| 45 |
+
group: "Apertus",
|
| 46 |
},
|
| 47 |
+
apertus8BInstruct2509fp16: {
|
| 48 |
modelId: "onnx-community/Apertus-8B-Instruct-2509-ONNX",
|
| 49 |
+
title: "Apertus 8B Instruct 2509 (fp16)",
|
| 50 |
+
dtype: "fp16",
|
| 51 |
device: "webgpu",
|
| 52 |
+
size: 14_119_488_832,
|
| 53 |
files: {
|
| 54 |
"config.json": 1_193,
|
| 55 |
"generation_config.json": 141,
|
| 56 |
+
"onnx/model_fp16.onnx": 559_114,
|
| 57 |
+
"onnx/model_fp16.onnx_data": 2_046_918_656,
|
| 58 |
+
"onnx/model_fp16.onnx_data_1": 1_921_122_304,
|
| 59 |
+
"onnx/model_fp16.onnx_data_2": 2_005_041_152,
|
| 60 |
+
"onnx/model_fp16.onnx_data_3": 1_921_122_304,
|
| 61 |
+
"onnx/model_fp16.onnx_data_4": 2_005_041_152,
|
| 62 |
+
"onnx/model_fp16.onnx_data_5": 1_921_122_304,
|
| 63 |
+
"onnx/model_fp16.onnx_data_7": 1_224_818_688,
|
| 64 |
+
"onnx/model_fp16.onnx_data_8": 1_073_741_824,
|
| 65 |
},
|
| 66 |
+
group: "Apertus",
|
| 67 |
},
|
| 68 |
gemma3270m: {
|
| 69 |
modelId: "onnx-community/gemma-3-270m-it-ONNX",
|
|
|
|
| 79 |
"onnx/model.onnx": 201_742,
|
| 80 |
"onnx/model.onnx_data": 1_139_501_568,
|
| 81 |
},
|
| 82 |
+
group: "Gemma",
|
| 83 |
},
|
| 84 |
granite350m: {
|
| 85 |
modelId: "onnx-community/granite-4.0-350m-ONNX-web",
|
|
|
|
| 95 |
"onnx/model_fp16.onnx": 202_945,
|
| 96 |
"onnx/model_fp16.onnx_data": 708_954_112,
|
| 97 |
},
|
| 98 |
+
group: "Granite",
|
| 99 |
},
|
| 100 |
granite1B: {
|
| 101 |
modelId: "onnx-community/granite-4.0-1b-ONNX-web",
|
|
|
|
| 111 |
"generation_config.json": 147,
|
| 112 |
"onnx/model_q4.onnx_data": 1_781_145_600,
|
| 113 |
},
|
| 114 |
+
group: "Granite",
|
| 115 |
},
|
| 116 |
granite3B: {
|
| 117 |
modelId: "onnx-community/granite-4.0-micro-ONNX-web",
|
|
|
|
| 128 |
"onnx/model_q4f16.onnx_data_1": 212_336_640,
|
| 129 |
"generation_config.json": 152,
|
| 130 |
},
|
| 131 |
+
group: "Granite",
|
| 132 |
},
|
| 133 |
qwen34B: {
|
| 134 |
modelId: "onnx-community/Qwen3-4B-ONNX",
|
|
|
|
| 145 |
"onnx/model_q4f16.onnx_data_1": 677_150_720,
|
| 146 |
"onnx/model_q4f16.onnx_data": 2_096_005_120,
|
| 147 |
},
|
| 148 |
+
group: "Qwen",
|
| 149 |
},
|
| 150 |
smolLM33B: {
|
| 151 |
modelId: "HuggingFaceTB/SmolLM3-3B-ONNX",
|
|
|
|
| 161 |
"generation_config.json": 182,
|
| 162 |
"onnx/model_q4f16.onnx_data": 2_124_320_768,
|
| 163 |
},
|
| 164 |
+
group: "SmolLM3",
|
| 165 |
+
},
|
| 166 |
+
lfm2350: {
|
| 167 |
+
modelId: "onnx-community/LFM2-350M-ONNX",
|
| 168 |
+
title: "LFM2-350M (q4f16)",
|
| 169 |
+
dtype: "q4f16",
|
| 170 |
+
device: "webgpu",
|
| 171 |
+
size: 312_526_859,
|
| 172 |
+
files: {
|
| 173 |
+
"config.json": 1_384,
|
| 174 |
+
"onnx/model_q4f16.onnx": 180_763,
|
| 175 |
+
"onnx/model_q4f16.onnx_data": 312_344_576,
|
| 176 |
+
"generation_config.json": 136,
|
| 177 |
+
},
|
| 178 |
+
group: "Liquid AI LFM2",
|
| 179 |
+
},
|
| 180 |
+
lfm2700: {
|
| 181 |
+
modelId: "onnx-community/LFM2-700M-ONNX",
|
| 182 |
+
title: "LFM2-700M (q4f16)",
|
| 183 |
+
dtype: "q4f16",
|
| 184 |
+
device: "webgpu",
|
| 185 |
+
size: 579_061_875,
|
| 186 |
+
files: {
|
| 187 |
+
"config.json": 1386,
|
| 188 |
+
"generation_config.json": 136,
|
| 189 |
+
"onnx/model_q4f16.onnx": 180865,
|
| 190 |
+
"onnx/model_q4f16.onnx_data": 578879488,
|
| 191 |
+
},
|
| 192 |
+
group: "Liquid AI LFM2",
|
| 193 |
+
},
|
| 194 |
+
lfm21B: {
|
| 195 |
+
modelId: "onnx-community/LFM2-1.2B-ONNX",
|
| 196 |
+
title: "LFM2-1.2B (q4f16)",
|
| 197 |
+
dtype: "q4f16",
|
| 198 |
+
device: "webgpu",
|
| 199 |
+
size: 868_010_193,
|
| 200 |
+
files: {
|
| 201 |
+
"config.json": 1_387,
|
| 202 |
+
"onnx/model_q4f16.onnx": 180_958,
|
| 203 |
+
"onnx/model_q4f16.onnx_data": 867_827_712,
|
| 204 |
+
"generation_config.json": 136,
|
| 205 |
+
},
|
| 206 |
+
group: "Liquid AI LFM2",
|
| 207 |
},
|
| 208 |
} as const;
|
| 209 |
|
src/utils/tools.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
import type { WebMCPTool } from "@utils/webMcp.ts";
|
| 2 |
|
| 3 |
const getCurrentTimeTool: WebMCPTool = {
|
| 4 |
name: "get_current_time",
|
|
|
|
| 1 |
+
import type { WebMCPTool } from "@utils/webMcp/types.ts";
|
| 2 |
|
| 3 |
const getCurrentTimeTool: WebMCPTool = {
|
| 4 |
name: "get_current_time",
|
src/utils/{webMcp.ts β webMcp/execute.ts}
RENAMED
|
@@ -1,48 +1,45 @@
|
|
| 1 |
-
|
| 2 |
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
description: string;
|
| 12 |
-
default?: number;
|
| 13 |
-
}
|
| 14 |
-
| {
|
| 15 |
-
type: "boolean";
|
| 16 |
-
description: string;
|
| 17 |
-
default?: boolean;
|
| 18 |
-
};
|
| 19 |
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
required: Array<string>;
|
| 27 |
};
|
| 28 |
-
|
| 29 |
-
}
|
| 30 |
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
|
|
|
| 36 |
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
})
|
|
|
|
|
|
|
| 44 |
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
tool: WebMCPTool,
|
| 47 |
args: Record<string, any>
|
| 48 |
): Record<string, any> => {
|
|
@@ -75,141 +72,3 @@ export const validateWebMCPToolArguments = (
|
|
| 75 |
|
| 76 |
return returnArgs;
|
| 77 |
};
|
| 78 |
-
|
| 79 |
-
export const executeWebMCPTool = async (
|
| 80 |
-
tool: WebMCPTool,
|
| 81 |
-
args: Record<string, any> | string | undefined
|
| 82 |
-
) => {
|
| 83 |
-
// Handle case where args is a JSON string instead of an object
|
| 84 |
-
let parsedArgs: Record<string, any> = {};
|
| 85 |
-
|
| 86 |
-
if (typeof args === "string") {
|
| 87 |
-
try {
|
| 88 |
-
parsedArgs = JSON.parse(args);
|
| 89 |
-
} catch (error) {
|
| 90 |
-
parsedArgs = {};
|
| 91 |
-
}
|
| 92 |
-
} else if (args) {
|
| 93 |
-
parsedArgs = args;
|
| 94 |
-
}
|
| 95 |
-
|
| 96 |
-
const validatedArgs = validateWebMCPToolArguments(tool, parsedArgs);
|
| 97 |
-
return await tool.execute(validatedArgs);
|
| 98 |
-
};
|
| 99 |
-
|
| 100 |
-
export interface ToolCallPayload {
|
| 101 |
-
name: string;
|
| 102 |
-
arguments?: Record<string, any> | string;
|
| 103 |
-
id: string;
|
| 104 |
-
}
|
| 105 |
-
|
| 106 |
-
export const extractToolCalls = (
|
| 107 |
-
text: string
|
| 108 |
-
): { toolCalls: ToolCallPayload[]; message: string } => {
|
| 109 |
-
const matches = Array.from(
|
| 110 |
-
text.matchAll(/<tool_call>([\s\S]*?)<\/tool_call>/g)
|
| 111 |
-
);
|
| 112 |
-
const toolCalls: ToolCallPayload[] = [];
|
| 113 |
-
|
| 114 |
-
for (const match of matches) {
|
| 115 |
-
try {
|
| 116 |
-
const parsed = JSON.parse(match[1].trim());
|
| 117 |
-
if (parsed && typeof parsed.name === "string") {
|
| 118 |
-
toolCalls.push({
|
| 119 |
-
name: parsed.name,
|
| 120 |
-
arguments: parsed.arguments ?? {},
|
| 121 |
-
id: JSON.stringify({
|
| 122 |
-
name: parsed.name,
|
| 123 |
-
arguments: parsed.arguments ?? {},
|
| 124 |
-
}),
|
| 125 |
-
});
|
| 126 |
-
}
|
| 127 |
-
} catch {
|
| 128 |
-
// ignore malformed tool call payloads
|
| 129 |
-
}
|
| 130 |
-
}
|
| 131 |
-
|
| 132 |
-
// Remove both complete and incomplete tool calls
|
| 133 |
-
// Complete: <tool_call>...</tool_call>
|
| 134 |
-
// Incomplete: <tool_call>... (no closing tag yet)
|
| 135 |
-
const message = text
|
| 136 |
-
.replace(/<tool_call>[\s\S]*?(?:<\/tool_call>|$)/g, "")
|
| 137 |
-
.trim();
|
| 138 |
-
|
| 139 |
-
return { toolCalls, message };
|
| 140 |
-
};
|
| 141 |
-
|
| 142 |
-
export const splitResponse = (
|
| 143 |
-
text: string
|
| 144 |
-
): Array<string | ToolCallPayload> => {
|
| 145 |
-
const result: Array<string | ToolCallPayload> = [];
|
| 146 |
-
let lastIndex = 0;
|
| 147 |
-
|
| 148 |
-
// Match only complete tool calls (with closing tag)
|
| 149 |
-
const regex = /<tool_call>([\s\S]*?)<\/tool_call>/g;
|
| 150 |
-
let match: RegExpExecArray | null;
|
| 151 |
-
|
| 152 |
-
while ((match = regex.exec(text)) !== null) {
|
| 153 |
-
// Add text before the tool call
|
| 154 |
-
const textBefore = text.slice(lastIndex, match.index);
|
| 155 |
-
if (textBefore) {
|
| 156 |
-
result.push(textBefore);
|
| 157 |
-
}
|
| 158 |
-
|
| 159 |
-
// Parse and add the tool call
|
| 160 |
-
try {
|
| 161 |
-
const parsed = JSON.parse(match[1].trim());
|
| 162 |
-
if (parsed && typeof parsed.name === "string") {
|
| 163 |
-
result.push({
|
| 164 |
-
name: parsed.name,
|
| 165 |
-
arguments: parsed.arguments ?? {},
|
| 166 |
-
id: JSON.stringify({
|
| 167 |
-
name: parsed.name,
|
| 168 |
-
arguments: parsed.arguments ?? {},
|
| 169 |
-
}),
|
| 170 |
-
});
|
| 171 |
-
}
|
| 172 |
-
} catch {
|
| 173 |
-
// ignore malformed tool call payloads
|
| 174 |
-
}
|
| 175 |
-
|
| 176 |
-
lastIndex = regex.lastIndex;
|
| 177 |
-
}
|
| 178 |
-
|
| 179 |
-
// Check if there's an incomplete tool call
|
| 180 |
-
const incompleteToolCallIndex = text.indexOf("<tool_call>", lastIndex);
|
| 181 |
-
|
| 182 |
-
if (incompleteToolCallIndex !== -1) {
|
| 183 |
-
// There's an incomplete tool call, only add text up to it
|
| 184 |
-
const textBefore = text.slice(lastIndex, incompleteToolCallIndex);
|
| 185 |
-
if (textBefore) {
|
| 186 |
-
result.push(textBefore);
|
| 187 |
-
}
|
| 188 |
-
} else {
|
| 189 |
-
// No incomplete tool call, add remaining text
|
| 190 |
-
const remainingText = text.slice(lastIndex);
|
| 191 |
-
if (remainingText) {
|
| 192 |
-
result.push(remainingText);
|
| 193 |
-
}
|
| 194 |
-
}
|
| 195 |
-
|
| 196 |
-
return result;
|
| 197 |
-
};
|
| 198 |
-
|
| 199 |
-
export const executeToolCall = async (
|
| 200 |
-
toolCall: ToolCallPayload,
|
| 201 |
-
tools: Array<WebMCPTool>
|
| 202 |
-
): Promise<{ id: string; result: string; time: number }> => {
|
| 203 |
-
const started = performance.now();
|
| 204 |
-
const toolToUse = tools.find((t) => t.name === toolCall.name);
|
| 205 |
-
if (!toolToUse)
|
| 206 |
-
throw new Error(`Tool '${toolCall.name}' not found or is disabled.`);
|
| 207 |
-
|
| 208 |
-
const result = await executeWebMCPTool(toolToUse, toolCall.arguments);
|
| 209 |
-
const ended = performance.now();
|
| 210 |
-
return {
|
| 211 |
-
id: toolCall.id,
|
| 212 |
-
result,
|
| 213 |
-
time: ended - started,
|
| 214 |
-
};
|
| 215 |
-
};
|
|
|
|
| 1 |
+
import type { ToolCallPayload, WebMCPTool } from "./types.ts";
|
| 2 |
|
| 3 |
+
export const executeToolCall = async (
|
| 4 |
+
toolCall: ToolCallPayload,
|
| 5 |
+
tools: Array<WebMCPTool>
|
| 6 |
+
): Promise<{ id: string; result: string; time: number }> => {
|
| 7 |
+
const started = performance.now();
|
| 8 |
+
const toolToUse = tools.find((t) => t.name === toolCall.name);
|
| 9 |
+
if (!toolToUse)
|
| 10 |
+
throw new Error(`Tool '${toolCall.name}' not found or is disabled.`);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
+
const result = await executeWebMCPTool(toolToUse, toolCall.arguments);
|
| 13 |
+
const ended = performance.now();
|
| 14 |
+
return {
|
| 15 |
+
id: toolCall.id,
|
| 16 |
+
result,
|
| 17 |
+
time: ended - started,
|
|
|
|
| 18 |
};
|
| 19 |
+
};
|
|
|
|
| 20 |
|
| 21 |
+
const executeWebMCPTool = async (
|
| 22 |
+
tool: WebMCPTool,
|
| 23 |
+
args: Record<string, any> | string | undefined
|
| 24 |
+
) => {
|
| 25 |
+
// Handle case where args is a JSON string instead of an object
|
| 26 |
+
let parsedArgs: Record<string, any> = {};
|
| 27 |
|
| 28 |
+
if (typeof args === "string") {
|
| 29 |
+
try {
|
| 30 |
+
parsedArgs = JSON.parse(args);
|
| 31 |
+
} catch (error) {
|
| 32 |
+
parsedArgs = {};
|
| 33 |
+
}
|
| 34 |
+
} else if (args) {
|
| 35 |
+
parsedArgs = args;
|
| 36 |
+
}
|
| 37 |
|
| 38 |
+
const validatedArgs = validateWebMCPToolArguments(tool, parsedArgs);
|
| 39 |
+
return await tool.execute(validatedArgs);
|
| 40 |
+
};
|
| 41 |
+
|
| 42 |
+
const validateWebMCPToolArguments = (
|
| 43 |
tool: WebMCPTool,
|
| 44 |
args: Record<string, any>
|
| 45 |
): Record<string, any> => {
|
|
|
|
| 72 |
|
| 73 |
return returnArgs;
|
| 74 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/utils/webMcp/extract.ts
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import type { ToolCallMatch, ToolCallPayload } from "./types.ts";
|
| 2 |
+
|
| 3 |
+
export const splitResponse = (
|
| 4 |
+
text: string
|
| 5 |
+
): Array<string | ToolCallPayload> => {
|
| 6 |
+
const result: Array<string | ToolCallPayload> = [];
|
| 7 |
+
|
| 8 |
+
const toolCallMatches: ToolCallMatch[] = [];
|
| 9 |
+
|
| 10 |
+
// Match XML syntax: <tool_call>...</tool_call>
|
| 11 |
+
const xmlRegex = /<tool_call>([\s\S]*?)<\/tool_call>/g;
|
| 12 |
+
let xmlMatch: RegExpExecArray | null;
|
| 13 |
+
while ((xmlMatch = xmlRegex.exec(text)) !== null) {
|
| 14 |
+
toolCallMatches.push({
|
| 15 |
+
start: xmlMatch.index,
|
| 16 |
+
end: xmlRegex.lastIndex,
|
| 17 |
+
content: xmlMatch[1],
|
| 18 |
+
syntax: "xml",
|
| 19 |
+
});
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
// Match pipe syntax: <|tool_call_start|>...<|tool_call_end|>
|
| 23 |
+
const pipeRegex = /<\|tool_call_start\|>([\s\S]*?)<\|tool_call_end\|>/g;
|
| 24 |
+
let pipeMatch: RegExpExecArray | null;
|
| 25 |
+
while ((pipeMatch = pipeRegex.exec(text)) !== null) {
|
| 26 |
+
toolCallMatches.push({
|
| 27 |
+
start: pipeMatch.index,
|
| 28 |
+
end: pipeRegex.lastIndex,
|
| 29 |
+
content: pipeMatch[1],
|
| 30 |
+
syntax: "pipes",
|
| 31 |
+
});
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
toolCallMatches.sort((a, b) => a.start - b.start);
|
| 35 |
+
|
| 36 |
+
let lastIndex = 0;
|
| 37 |
+
|
| 38 |
+
for (const match of toolCallMatches) {
|
| 39 |
+
const textBefore = text.slice(lastIndex, match.start);
|
| 40 |
+
if (textBefore.trim()) {
|
| 41 |
+
result.push(textBefore.trim());
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
let toolCall: ToolCallPayload | null = null;
|
| 45 |
+
|
| 46 |
+
if (match.syntax === "xml") {
|
| 47 |
+
// JSON syntax in XML tags
|
| 48 |
+
toolCall = extractXmlJsonToolCall(match.content);
|
| 49 |
+
} else {
|
| 50 |
+
// Pythonic function call syntax in pipe tags
|
| 51 |
+
toolCall = extractPythonicToolCall(match.content);
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
if (toolCall) {
|
| 55 |
+
result.push(toolCall);
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
lastIndex = match.end;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
const incompleteXml = text.indexOf("<tool_call>", lastIndex);
|
| 62 |
+
const incompletePipe = text.indexOf("<|tool_call_start|>", lastIndex);
|
| 63 |
+
|
| 64 |
+
let incompleteIndex = -1;
|
| 65 |
+
if (incompleteXml !== -1 && incompletePipe !== -1) {
|
| 66 |
+
incompleteIndex = Math.min(incompleteXml, incompletePipe);
|
| 67 |
+
} else if (incompleteXml !== -1) {
|
| 68 |
+
incompleteIndex = incompleteXml;
|
| 69 |
+
} else if (incompletePipe !== -1) {
|
| 70 |
+
incompleteIndex = incompletePipe;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
if (incompleteIndex !== -1) {
|
| 74 |
+
const textBefore = text.slice(lastIndex, incompleteIndex);
|
| 75 |
+
if (textBefore.trim()) {
|
| 76 |
+
result.push(textBefore.trim());
|
| 77 |
+
}
|
| 78 |
+
} else {
|
| 79 |
+
const remainingText = text.slice(lastIndex);
|
| 80 |
+
if (remainingText.trim()) {
|
| 81 |
+
result.push(remainingText.trim());
|
| 82 |
+
}
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
return result;
|
| 86 |
+
};
|
| 87 |
+
|
| 88 |
+
/**
|
| 89 |
+
* XML/JSON tool calling
|
| 90 |
+
* used by Granite 4.0
|
| 91 |
+
*/
|
| 92 |
+
|
| 93 |
+
// used for Granite 4.0 models
|
| 94 |
+
export const extractXmlJsonToolCall = (
|
| 95 |
+
text: string
|
| 96 |
+
): ToolCallPayload | null => {
|
| 97 |
+
const parsed = JSON.parse(text.trim());
|
| 98 |
+
try {
|
| 99 |
+
if (parsed && typeof parsed.name === "string") {
|
| 100 |
+
return {
|
| 101 |
+
name: parsed.name,
|
| 102 |
+
arguments: parsed.arguments ?? {},
|
| 103 |
+
id: JSON.stringify({
|
| 104 |
+
name: parsed.name,
|
| 105 |
+
arguments: parsed.arguments ?? {},
|
| 106 |
+
}),
|
| 107 |
+
};
|
| 108 |
+
}
|
| 109 |
+
} catch (e) {
|
| 110 |
+
return null;
|
| 111 |
+
}
|
| 112 |
+
};
|
| 113 |
+
|
| 114 |
+
/**
|
| 115 |
+
* Pipe/Pythonic tool calling
|
| 116 |
+
* used by Liquid AI LFM2
|
| 117 |
+
*/
|
| 118 |
+
|
| 119 |
+
export const extractPythonicToolCall = (
|
| 120 |
+
text: string
|
| 121 |
+
): ToolCallPayload | null => {
|
| 122 |
+
try {
|
| 123 |
+
// Remove surrounding brackets if present: [get_joke(...)] -> get_joke(...)
|
| 124 |
+
const trimmed = text.trim().replace(/^\[|]$/g, "");
|
| 125 |
+
|
| 126 |
+
// Extract function name and arguments: get_joke(category="Programming")
|
| 127 |
+
const functionMatch = trimmed.match(/^(\w+)\((.*)\)$/s);
|
| 128 |
+
if (!functionMatch) return null;
|
| 129 |
+
|
| 130 |
+
const name = functionMatch[1];
|
| 131 |
+
const argsString = functionMatch[2];
|
| 132 |
+
|
| 133 |
+
// Parse arguments using the helper function
|
| 134 |
+
const args: Record<string, any> = {};
|
| 135 |
+
|
| 136 |
+
if (argsString.trim()) {
|
| 137 |
+
const argPairs = parsePythonicArguments(argsString);
|
| 138 |
+
|
| 139 |
+
for (const pair of argPairs) {
|
| 140 |
+
// Match key=value patterns where value can be quoted or unquoted
|
| 141 |
+
const argMatch = pair.match(/^(\w+)=(.+)$/);
|
| 142 |
+
if (argMatch) {
|
| 143 |
+
const key = argMatch[1];
|
| 144 |
+
let value = argMatch[2].trim();
|
| 145 |
+
|
| 146 |
+
// Remove quotes if present
|
| 147 |
+
if (
|
| 148 |
+
(value.startsWith('"') && value.endsWith('"')) ||
|
| 149 |
+
(value.startsWith("'") && value.endsWith("'"))
|
| 150 |
+
) {
|
| 151 |
+
value = value.slice(1, -1);
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
args[key] = value;
|
| 155 |
+
}
|
| 156 |
+
}
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
+
return {
|
| 160 |
+
name,
|
| 161 |
+
arguments: args,
|
| 162 |
+
id: JSON.stringify({ name, arguments: args }),
|
| 163 |
+
};
|
| 164 |
+
} catch {
|
| 165 |
+
return null;
|
| 166 |
+
}
|
| 167 |
+
};
|
| 168 |
+
|
| 169 |
+
const parsePythonicArguments = (argsString: string): string[] => {
|
| 170 |
+
const args: string[] = [];
|
| 171 |
+
let current = "";
|
| 172 |
+
let inQuotes = false;
|
| 173 |
+
let quoteChar = "";
|
| 174 |
+
let depth = 0;
|
| 175 |
+
|
| 176 |
+
for (let i = 0; i < argsString.length; i++) {
|
| 177 |
+
const char = argsString[i];
|
| 178 |
+
|
| 179 |
+
if (!inQuotes && (char === '"' || char === "'")) {
|
| 180 |
+
inQuotes = true;
|
| 181 |
+
quoteChar = char;
|
| 182 |
+
current += char;
|
| 183 |
+
} else if (inQuotes && char === quoteChar) {
|
| 184 |
+
inQuotes = false;
|
| 185 |
+
quoteChar = "";
|
| 186 |
+
current += char;
|
| 187 |
+
} else if (!inQuotes && char === "(") {
|
| 188 |
+
depth++;
|
| 189 |
+
current += char;
|
| 190 |
+
} else if (!inQuotes && char === ")") {
|
| 191 |
+
depth--;
|
| 192 |
+
current += char;
|
| 193 |
+
} else if (!inQuotes && char === "," && depth === 0) {
|
| 194 |
+
args.push(current.trim());
|
| 195 |
+
current = "";
|
| 196 |
+
} else {
|
| 197 |
+
current += char;
|
| 198 |
+
}
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
if (current.trim()) {
|
| 202 |
+
args.push(current.trim());
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
return args;
|
| 206 |
+
};
|
src/utils/webMcp/format.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import type { ChatTemplateTool, WebMCPTool } from "./types.ts";
|
| 2 |
+
|
| 3 |
+
export const webMCPToolToChatTemplateTool = (
|
| 4 |
+
webMCPTool: WebMCPTool
|
| 5 |
+
): ChatTemplateTool => ({
|
| 6 |
+
name: webMCPTool.name,
|
| 7 |
+
description: webMCPTool.description,
|
| 8 |
+
parameters: webMCPTool.inputSchema,
|
| 9 |
+
});
|
src/utils/webMcp/index.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export { splitResponse } from "./extract.ts";
|
| 2 |
+
export { executeToolCall } from "./execute.ts";
|
| 3 |
+
export { webMCPToolToChatTemplateTool } from "./format.ts";
|
src/utils/webMcp/types.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
type WebMCPProperty =
|
| 2 |
+
| {
|
| 3 |
+
type: "string";
|
| 4 |
+
description: string;
|
| 5 |
+
default?: string;
|
| 6 |
+
}
|
| 7 |
+
| {
|
| 8 |
+
type: "number";
|
| 9 |
+
description: string;
|
| 10 |
+
default?: number;
|
| 11 |
+
}
|
| 12 |
+
| {
|
| 13 |
+
type: "boolean";
|
| 14 |
+
description: string;
|
| 15 |
+
default?: boolean;
|
| 16 |
+
};
|
| 17 |
+
|
| 18 |
+
export interface WebMCPTool {
|
| 19 |
+
name: string;
|
| 20 |
+
description: string;
|
| 21 |
+
inputSchema: {
|
| 22 |
+
type: "object";
|
| 23 |
+
properties: Record<string, WebMCPProperty>;
|
| 24 |
+
required: Array<string>;
|
| 25 |
+
};
|
| 26 |
+
execute: (args: Record<string, any>) => Promise<string>;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
export interface ChatTemplateTool {
|
| 30 |
+
name: string;
|
| 31 |
+
description: string;
|
| 32 |
+
parameters: Record<string, any>;
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
export interface ToolCallPayload {
|
| 36 |
+
name: string;
|
| 37 |
+
arguments?: Record<string, any> | string;
|
| 38 |
+
id: string;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
export interface ToolCallMatch {
|
| 42 |
+
start: number;
|
| 43 |
+
end: number;
|
| 44 |
+
content: string;
|
| 45 |
+
syntax: "xml" | "pipes";
|
| 46 |
+
}
|
src/utils/webMcp/webMcp.test.ts
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { describe, expect, test } from "vitest";
|
| 2 |
+
|
| 3 |
+
import { splitResponse } from "./index";
|
| 4 |
+
|
| 5 |
+
describe("splitResponse", () => {
|
| 6 |
+
test("simple text response", () => {
|
| 7 |
+
expect(splitResponse("hello")).toStrictEqual(["hello"]);
|
| 8 |
+
expect(
|
| 9 |
+
splitResponse(
|
| 10 |
+
"You are a helpful assistant with access to the following tools"
|
| 11 |
+
)
|
| 12 |
+
).toStrictEqual([
|
| 13 |
+
"You are a helpful assistant with access to the following tools",
|
| 14 |
+
]);
|
| 15 |
+
});
|
| 16 |
+
|
| 17 |
+
describe("XML/Json tool calling", () => {
|
| 18 |
+
test("full tool call", () => {
|
| 19 |
+
expect(
|
| 20 |
+
splitResponse(
|
| 21 |
+
`<tool_call>{"name": "get_current_time", "arguments": {}}</tool_call>`
|
| 22 |
+
)
|
| 23 |
+
).toStrictEqual([
|
| 24 |
+
{
|
| 25 |
+
name: "get_current_time",
|
| 26 |
+
arguments: {},
|
| 27 |
+
id: '{"name":"get_current_time","arguments":{}}',
|
| 28 |
+
},
|
| 29 |
+
]);
|
| 30 |
+
});
|
| 31 |
+
|
| 32 |
+
test("full tool call with arguments", () => {
|
| 33 |
+
expect(
|
| 34 |
+
splitResponse(
|
| 35 |
+
`<tool_call>{"name": "get_joke", "arguments": {"category": "Programming"}}</tool_call>`
|
| 36 |
+
)
|
| 37 |
+
).toStrictEqual([
|
| 38 |
+
{
|
| 39 |
+
name: "get_joke",
|
| 40 |
+
arguments: {
|
| 41 |
+
category: "Programming",
|
| 42 |
+
},
|
| 43 |
+
id: '{"name":"get_joke","arguments":{"category":"Programming"}}',
|
| 44 |
+
},
|
| 45 |
+
]);
|
| 46 |
+
});
|
| 47 |
+
|
| 48 |
+
test("partial tool call", () => {
|
| 49 |
+
expect(splitResponse(`<tool_call>{"name":`)).toStrictEqual([]);
|
| 50 |
+
});
|
| 51 |
+
|
| 52 |
+
test("partial tool call with leading text", () => {
|
| 53 |
+
expect(splitResponse(`Hello world <tool_call>{"name":`)).toStrictEqual([
|
| 54 |
+
"Hello world",
|
| 55 |
+
]);
|
| 56 |
+
});
|
| 57 |
+
|
| 58 |
+
test("tool call with leading text", () => {
|
| 59 |
+
expect(
|
| 60 |
+
splitResponse(
|
| 61 |
+
`Hello world <tool_call>{"name": "get_current_time", "arguments": {}}</tool_call>`
|
| 62 |
+
)
|
| 63 |
+
).toStrictEqual([
|
| 64 |
+
"Hello world",
|
| 65 |
+
{
|
| 66 |
+
name: "get_current_time",
|
| 67 |
+
arguments: {},
|
| 68 |
+
id: '{"name":"get_current_time","arguments":{}}',
|
| 69 |
+
},
|
| 70 |
+
]);
|
| 71 |
+
});
|
| 72 |
+
|
| 73 |
+
test("tool call with surrounding text", () => {
|
| 74 |
+
expect(
|
| 75 |
+
splitResponse(
|
| 76 |
+
`Hello world <tool_call>{"name": "get_current_time", "arguments": {}}</tool_call> This is a test`
|
| 77 |
+
)
|
| 78 |
+
).toStrictEqual([
|
| 79 |
+
"Hello world",
|
| 80 |
+
{
|
| 81 |
+
name: "get_current_time",
|
| 82 |
+
arguments: {},
|
| 83 |
+
id: '{"name":"get_current_time","arguments":{}}',
|
| 84 |
+
},
|
| 85 |
+
"This is a test",
|
| 86 |
+
]);
|
| 87 |
+
});
|
| 88 |
+
});
|
| 89 |
+
|
| 90 |
+
describe("Pipe/Pythonic tool calling", () => {
|
| 91 |
+
test("full tool call without arguments", () => {
|
| 92 |
+
expect(
|
| 93 |
+
splitResponse(
|
| 94 |
+
`<|tool_call_start|>[get_current_time()]<|tool_call_end|>`
|
| 95 |
+
)
|
| 96 |
+
).toStrictEqual([
|
| 97 |
+
{
|
| 98 |
+
name: "get_current_time",
|
| 99 |
+
arguments: {},
|
| 100 |
+
id: '{"name":"get_current_time","arguments":{}}',
|
| 101 |
+
},
|
| 102 |
+
]);
|
| 103 |
+
});
|
| 104 |
+
|
| 105 |
+
test("full tool call with single argument", () => {
|
| 106 |
+
expect(
|
| 107 |
+
splitResponse(
|
| 108 |
+
`<|tool_call_start|>[get_joke(category="Programming")]<|tool_call_end|>`
|
| 109 |
+
)
|
| 110 |
+
).toStrictEqual([
|
| 111 |
+
{
|
| 112 |
+
name: "get_joke",
|
| 113 |
+
arguments: {
|
| 114 |
+
category: "Programming",
|
| 115 |
+
},
|
| 116 |
+
id: '{"name":"get_joke","arguments":{"category":"Programming"}}',
|
| 117 |
+
},
|
| 118 |
+
]);
|
| 119 |
+
});
|
| 120 |
+
|
| 121 |
+
test("full tool call with multiple arguments", () => {
|
| 122 |
+
expect(
|
| 123 |
+
splitResponse(
|
| 124 |
+
`<|tool_call_start|>[get_joke(category="Programming", type="setup", contains="error")]<|tool_call_end|>`
|
| 125 |
+
)
|
| 126 |
+
).toStrictEqual([
|
| 127 |
+
{
|
| 128 |
+
name: "get_joke",
|
| 129 |
+
arguments: {
|
| 130 |
+
category: "Programming",
|
| 131 |
+
type: "setup",
|
| 132 |
+
contains: "error",
|
| 133 |
+
},
|
| 134 |
+
id: '{"name":"get_joke","arguments":{"category":"Programming","type":"setup","contains":"error"}}',
|
| 135 |
+
},
|
| 136 |
+
]);
|
| 137 |
+
});
|
| 138 |
+
|
| 139 |
+
test("partial tool call", () => {
|
| 140 |
+
expect(splitResponse(`<|tool_call_start|>[get_current`)).toStrictEqual(
|
| 141 |
+
[]
|
| 142 |
+
);
|
| 143 |
+
});
|
| 144 |
+
|
| 145 |
+
test("partial tool call with leading text", () => {
|
| 146 |
+
expect(
|
| 147 |
+
splitResponse(`Hello world <|tool_call_start|>[get_joke(`)
|
| 148 |
+
).toStrictEqual(["Hello world"]);
|
| 149 |
+
});
|
| 150 |
+
|
| 151 |
+
test("tool call with leading text", () => {
|
| 152 |
+
expect(
|
| 153 |
+
splitResponse(
|
| 154 |
+
`Hello world <|tool_call_start|>[get_current_time()]<|tool_call_end|>`
|
| 155 |
+
)
|
| 156 |
+
).toStrictEqual([
|
| 157 |
+
"Hello world",
|
| 158 |
+
{
|
| 159 |
+
name: "get_current_time",
|
| 160 |
+
arguments: {},
|
| 161 |
+
id: '{"name":"get_current_time","arguments":{}}',
|
| 162 |
+
},
|
| 163 |
+
]);
|
| 164 |
+
});
|
| 165 |
+
|
| 166 |
+
test("tool call with surrounding text", () => {
|
| 167 |
+
expect(
|
| 168 |
+
splitResponse(
|
| 169 |
+
`Hello world <|tool_call_start|>[get_current_time()]<|tool_call_end|> This is a test`
|
| 170 |
+
)
|
| 171 |
+
).toStrictEqual([
|
| 172 |
+
"Hello world",
|
| 173 |
+
{
|
| 174 |
+
name: "get_current_time",
|
| 175 |
+
arguments: {},
|
| 176 |
+
id: '{"name":"get_current_time","arguments":{}}',
|
| 177 |
+
},
|
| 178 |
+
"This is a test",
|
| 179 |
+
]);
|
| 180 |
+
});
|
| 181 |
+
});
|
| 182 |
+
});
|