@copilotkit/aimock 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (368) hide show
  1. package/.claude-plugin/marketplace.json +17 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/LICENSE +21 -0
  4. package/README.md +82 -0
  5. package/dist/_virtual/_rolldown/runtime.cjs +29 -0
  6. package/dist/a2a-handler.cjs +203 -0
  7. package/dist/a2a-handler.cjs.map +1 -0
  8. package/dist/a2a-handler.js +199 -0
  9. package/dist/a2a-handler.js.map +1 -0
  10. package/dist/a2a-mock.cjs +292 -0
  11. package/dist/a2a-mock.cjs.map +1 -0
  12. package/dist/a2a-mock.d.cts +41 -0
  13. package/dist/a2a-mock.d.cts.map +1 -0
  14. package/dist/a2a-mock.d.ts +41 -0
  15. package/dist/a2a-mock.d.ts.map +1 -0
  16. package/dist/a2a-mock.js +290 -0
  17. package/dist/a2a-mock.js.map +1 -0
  18. package/dist/a2a-stub.cjs +4 -0
  19. package/dist/a2a-stub.d.cts +3 -0
  20. package/dist/a2a-stub.d.ts +3 -0
  21. package/dist/a2a-stub.js +3 -0
  22. package/dist/a2a-types.d.cts +68 -0
  23. package/dist/a2a-types.d.cts.map +1 -0
  24. package/dist/a2a-types.d.ts +68 -0
  25. package/dist/a2a-types.d.ts.map +1 -0
  26. package/dist/aimock-cli.cjs +112 -0
  27. package/dist/aimock-cli.cjs.map +1 -0
  28. package/dist/aimock-cli.d.cts +19 -0
  29. package/dist/aimock-cli.d.cts.map +1 -0
  30. package/dist/aimock-cli.d.ts +19 -0
  31. package/dist/aimock-cli.d.ts.map +1 -0
  32. package/dist/aimock-cli.js +110 -0
  33. package/dist/aimock-cli.js.map +1 -0
  34. package/dist/aws-event-stream.cjs +117 -0
  35. package/dist/aws-event-stream.cjs.map +1 -0
  36. package/dist/aws-event-stream.d.cts +38 -0
  37. package/dist/aws-event-stream.d.cts.map +1 -0
  38. package/dist/aws-event-stream.d.ts +38 -0
  39. package/dist/aws-event-stream.d.ts.map +1 -0
  40. package/dist/aws-event-stream.js +114 -0
  41. package/dist/aws-event-stream.js.map +1 -0
  42. package/dist/bedrock-converse.cjs +445 -0
  43. package/dist/bedrock-converse.cjs.map +1 -0
  44. package/dist/bedrock-converse.d.cts +50 -0
  45. package/dist/bedrock-converse.d.cts.map +1 -0
  46. package/dist/bedrock-converse.d.ts +50 -0
  47. package/dist/bedrock-converse.d.ts.map +1 -0
  48. package/dist/bedrock-converse.js +443 -0
  49. package/dist/bedrock-converse.js.map +1 -0
  50. package/dist/bedrock.cjs +557 -0
  51. package/dist/bedrock.cjs.map +1 -0
  52. package/dist/bedrock.d.cts +41 -0
  53. package/dist/bedrock.d.cts.map +1 -0
  54. package/dist/bedrock.d.ts +41 -0
  55. package/dist/bedrock.d.ts.map +1 -0
  56. package/dist/bedrock.js +553 -0
  57. package/dist/bedrock.js.map +1 -0
  58. package/dist/chaos.cjs +114 -0
  59. package/dist/chaos.cjs.map +1 -0
  60. package/dist/chaos.d.cts +27 -0
  61. package/dist/chaos.d.cts.map +1 -0
  62. package/dist/chaos.d.ts +27 -0
  63. package/dist/chaos.d.ts.map +1 -0
  64. package/dist/chaos.js +113 -0
  65. package/dist/chaos.js.map +1 -0
  66. package/dist/cli.cjs +268 -0
  67. package/dist/cli.cjs.map +1 -0
  68. package/dist/cli.d.cts +1 -0
  69. package/dist/cli.d.ts +1 -0
  70. package/dist/cli.js +268 -0
  71. package/dist/cli.js.map +1 -0
  72. package/dist/cohere.cjs +434 -0
  73. package/dist/cohere.cjs.map +1 -0
  74. package/dist/cohere.d.cts +34 -0
  75. package/dist/cohere.d.cts.map +1 -0
  76. package/dist/cohere.d.ts +34 -0
  77. package/dist/cohere.d.ts.map +1 -0
  78. package/dist/cohere.js +433 -0
  79. package/dist/cohere.js.map +1 -0
  80. package/dist/config-loader.cjs +111 -0
  81. package/dist/config-loader.cjs.map +1 -0
  82. package/dist/config-loader.d.cts +100 -0
  83. package/dist/config-loader.d.cts.map +1 -0
  84. package/dist/config-loader.d.ts +100 -0
  85. package/dist/config-loader.d.ts.map +1 -0
  86. package/dist/config-loader.js +107 -0
  87. package/dist/config-loader.js.map +1 -0
  88. package/dist/embeddings.cjs +150 -0
  89. package/dist/embeddings.cjs.map +1 -0
  90. package/dist/embeddings.d.cts +12 -0
  91. package/dist/embeddings.d.cts.map +1 -0
  92. package/dist/embeddings.d.ts +12 -0
  93. package/dist/embeddings.d.ts.map +1 -0
  94. package/dist/embeddings.js +150 -0
  95. package/dist/embeddings.js.map +1 -0
  96. package/dist/fixture-loader.cjs +269 -0
  97. package/dist/fixture-loader.cjs.map +1 -0
  98. package/dist/fixture-loader.d.cts +17 -0
  99. package/dist/fixture-loader.d.cts.map +1 -0
  100. package/dist/fixture-loader.d.ts +17 -0
  101. package/dist/fixture-loader.d.ts.map +1 -0
  102. package/dist/fixture-loader.js +265 -0
  103. package/dist/fixture-loader.js.map +1 -0
  104. package/dist/gemini.cjs +403 -0
  105. package/dist/gemini.cjs.map +1 -0
  106. package/dist/gemini.d.cts +10 -0
  107. package/dist/gemini.d.cts.map +1 -0
  108. package/dist/gemini.d.ts +10 -0
  109. package/dist/gemini.d.ts.map +1 -0
  110. package/dist/gemini.js +403 -0
  111. package/dist/gemini.js.map +1 -0
  112. package/dist/helpers.cjs +276 -0
  113. package/dist/helpers.cjs.map +1 -0
  114. package/dist/helpers.d.cts +39 -0
  115. package/dist/helpers.d.cts.map +1 -0
  116. package/dist/helpers.d.ts +39 -0
  117. package/dist/helpers.d.ts.map +1 -0
  118. package/dist/helpers.js +259 -0
  119. package/dist/helpers.js.map +1 -0
  120. package/dist/index.cjs +113 -0
  121. package/dist/index.d.cts +42 -0
  122. package/dist/index.d.ts +42 -0
  123. package/dist/index.js +39 -0
  124. package/dist/interruption.cjs +40 -0
  125. package/dist/interruption.cjs.map +1 -0
  126. package/dist/interruption.d.cts +15 -0
  127. package/dist/interruption.d.cts.map +1 -0
  128. package/dist/interruption.d.ts +15 -0
  129. package/dist/interruption.d.ts.map +1 -0
  130. package/dist/interruption.js +39 -0
  131. package/dist/interruption.js.map +1 -0
  132. package/dist/journal.cjs +65 -0
  133. package/dist/journal.cjs.map +1 -0
  134. package/dist/journal.d.cts +23 -0
  135. package/dist/journal.d.cts.map +1 -0
  136. package/dist/journal.d.ts +23 -0
  137. package/dist/journal.d.ts.map +1 -0
  138. package/dist/journal.js +65 -0
  139. package/dist/journal.js.map +1 -0
  140. package/dist/jsonrpc.cjs +91 -0
  141. package/dist/jsonrpc.cjs.map +1 -0
  142. package/dist/jsonrpc.d.cts +24 -0
  143. package/dist/jsonrpc.d.cts.map +1 -0
  144. package/dist/jsonrpc.d.ts +24 -0
  145. package/dist/jsonrpc.d.ts.map +1 -0
  146. package/dist/jsonrpc.js +90 -0
  147. package/dist/jsonrpc.js.map +1 -0
  148. package/dist/llmock.cjs +223 -0
  149. package/dist/llmock.cjs.map +1 -0
  150. package/dist/llmock.d.cts +70 -0
  151. package/dist/llmock.d.cts.map +1 -0
  152. package/dist/llmock.d.ts +70 -0
  153. package/dist/llmock.d.ts.map +1 -0
  154. package/dist/llmock.js +223 -0
  155. package/dist/llmock.js.map +1 -0
  156. package/dist/logger.cjs +29 -0
  157. package/dist/logger.cjs.map +1 -0
  158. package/dist/logger.d.cts +14 -0
  159. package/dist/logger.d.cts.map +1 -0
  160. package/dist/logger.d.ts +14 -0
  161. package/dist/logger.d.ts.map +1 -0
  162. package/dist/logger.js +28 -0
  163. package/dist/logger.js.map +1 -0
  164. package/dist/mcp-handler.cjs +189 -0
  165. package/dist/mcp-handler.cjs.map +1 -0
  166. package/dist/mcp-handler.js +188 -0
  167. package/dist/mcp-handler.js.map +1 -0
  168. package/dist/mcp-mock.cjs +169 -0
  169. package/dist/mcp-mock.cjs.map +1 -0
  170. package/dist/mcp-mock.d.cts +40 -0
  171. package/dist/mcp-mock.d.cts.map +1 -0
  172. package/dist/mcp-mock.d.ts +40 -0
  173. package/dist/mcp-mock.d.ts.map +1 -0
  174. package/dist/mcp-mock.js +167 -0
  175. package/dist/mcp-mock.js.map +1 -0
  176. package/dist/mcp-stub.cjs +4 -0
  177. package/dist/mcp-stub.d.cts +3 -0
  178. package/dist/mcp-stub.d.ts +3 -0
  179. package/dist/mcp-stub.js +3 -0
  180. package/dist/mcp-types.d.cts +65 -0
  181. package/dist/mcp-types.d.cts.map +1 -0
  182. package/dist/mcp-types.d.ts +65 -0
  183. package/dist/mcp-types.d.ts.map +1 -0
  184. package/dist/messages.cjs +489 -0
  185. package/dist/messages.cjs.map +1 -0
  186. package/dist/messages.d.cts +10 -0
  187. package/dist/messages.d.cts.map +1 -0
  188. package/dist/messages.d.ts +10 -0
  189. package/dist/messages.d.ts.map +1 -0
  190. package/dist/messages.js +489 -0
  191. package/dist/messages.js.map +1 -0
  192. package/dist/metrics.cjs +160 -0
  193. package/dist/metrics.cjs.map +1 -0
  194. package/dist/metrics.d.cts +24 -0
  195. package/dist/metrics.d.cts.map +1 -0
  196. package/dist/metrics.d.ts +24 -0
  197. package/dist/metrics.d.ts.map +1 -0
  198. package/dist/metrics.js +158 -0
  199. package/dist/metrics.js.map +1 -0
  200. package/dist/moderation.cjs +91 -0
  201. package/dist/moderation.cjs.map +1 -0
  202. package/dist/moderation.d.cts +23 -0
  203. package/dist/moderation.d.cts.map +1 -0
  204. package/dist/moderation.d.ts +23 -0
  205. package/dist/moderation.d.ts.map +1 -0
  206. package/dist/moderation.js +91 -0
  207. package/dist/moderation.js.map +1 -0
  208. package/dist/ndjson-writer.cjs +31 -0
  209. package/dist/ndjson-writer.cjs.map +1 -0
  210. package/dist/ndjson-writer.d.cts +17 -0
  211. package/dist/ndjson-writer.d.cts.map +1 -0
  212. package/dist/ndjson-writer.d.ts +17 -0
  213. package/dist/ndjson-writer.d.ts.map +1 -0
  214. package/dist/ndjson-writer.js +31 -0
  215. package/dist/ndjson-writer.js.map +1 -0
  216. package/dist/ollama.cjs +519 -0
  217. package/dist/ollama.cjs.map +1 -0
  218. package/dist/ollama.d.cts +34 -0
  219. package/dist/ollama.d.cts.map +1 -0
  220. package/dist/ollama.d.ts +34 -0
  221. package/dist/ollama.d.ts.map +1 -0
  222. package/dist/ollama.js +517 -0
  223. package/dist/ollama.js.map +1 -0
  224. package/dist/recorder.cjs +311 -0
  225. package/dist/recorder.cjs.map +1 -0
  226. package/dist/recorder.d.cts +23 -0
  227. package/dist/recorder.d.cts.map +1 -0
  228. package/dist/recorder.d.ts +23 -0
  229. package/dist/recorder.d.ts.map +1 -0
  230. package/dist/recorder.js +305 -0
  231. package/dist/recorder.js.map +1 -0
  232. package/dist/rerank.cjs +71 -0
  233. package/dist/rerank.cjs.map +1 -0
  234. package/dist/rerank.d.cts +22 -0
  235. package/dist/rerank.d.cts.map +1 -0
  236. package/dist/rerank.d.ts +22 -0
  237. package/dist/rerank.d.ts.map +1 -0
  238. package/dist/rerank.js +71 -0
  239. package/dist/rerank.js.map +1 -0
  240. package/dist/responses.cjs +637 -0
  241. package/dist/responses.cjs.map +1 -0
  242. package/dist/responses.d.cts +16 -0
  243. package/dist/responses.d.cts.map +1 -0
  244. package/dist/responses.d.ts +16 -0
  245. package/dist/responses.d.ts.map +1 -0
  246. package/dist/responses.js +634 -0
  247. package/dist/responses.js.map +1 -0
  248. package/dist/router.cjs +68 -0
  249. package/dist/router.cjs.map +1 -0
  250. package/dist/router.d.cts +16 -0
  251. package/dist/router.d.cts.map +1 -0
  252. package/dist/router.d.ts +16 -0
  253. package/dist/router.d.ts.map +1 -0
  254. package/dist/router.js +65 -0
  255. package/dist/router.js.map +1 -0
  256. package/dist/search.cjs +59 -0
  257. package/dist/search.cjs.map +1 -0
  258. package/dist/search.d.cts +23 -0
  259. package/dist/search.d.cts.map +1 -0
  260. package/dist/search.d.ts +23 -0
  261. package/dist/search.d.ts.map +1 -0
  262. package/dist/search.js +59 -0
  263. package/dist/search.js.map +1 -0
  264. package/dist/server.cjs +935 -0
  265. package/dist/server.cjs.map +1 -0
  266. package/dist/server.d.cts +28 -0
  267. package/dist/server.d.cts.map +1 -0
  268. package/dist/server.d.ts +28 -0
  269. package/dist/server.d.ts.map +1 -0
  270. package/dist/server.js +933 -0
  271. package/dist/server.js.map +1 -0
  272. package/dist/sse-writer.cjs +59 -0
  273. package/dist/sse-writer.cjs.map +1 -0
  274. package/dist/sse-writer.d.cts +19 -0
  275. package/dist/sse-writer.d.cts.map +1 -0
  276. package/dist/sse-writer.d.ts +19 -0
  277. package/dist/sse-writer.d.ts.map +1 -0
  278. package/dist/sse-writer.js +55 -0
  279. package/dist/sse-writer.js.map +1 -0
  280. package/dist/stream-collapse.cjs +496 -0
  281. package/dist/stream-collapse.cjs.map +1 -0
  282. package/dist/stream-collapse.d.cts +70 -0
  283. package/dist/stream-collapse.d.cts.map +1 -0
  284. package/dist/stream-collapse.d.ts +70 -0
  285. package/dist/stream-collapse.d.ts.map +1 -0
  286. package/dist/stream-collapse.js +489 -0
  287. package/dist/stream-collapse.js.map +1 -0
  288. package/dist/suite.cjs +46 -0
  289. package/dist/suite.cjs.map +1 -0
  290. package/dist/suite.d.cts +31 -0
  291. package/dist/suite.d.cts.map +1 -0
  292. package/dist/suite.d.ts +31 -0
  293. package/dist/suite.d.ts.map +1 -0
  294. package/dist/suite.js +46 -0
  295. package/dist/suite.js.map +1 -0
  296. package/dist/types.d.cts +243 -0
  297. package/dist/types.d.cts.map +1 -0
  298. package/dist/types.d.ts +243 -0
  299. package/dist/types.d.ts.map +1 -0
  300. package/dist/url.cjs +21 -0
  301. package/dist/url.cjs.map +1 -0
  302. package/dist/url.d.cts +16 -0
  303. package/dist/url.d.cts.map +1 -0
  304. package/dist/url.d.ts +16 -0
  305. package/dist/url.d.ts.map +1 -0
  306. package/dist/url.js +20 -0
  307. package/dist/url.js.map +1 -0
  308. package/dist/vector-handler.cjs +239 -0
  309. package/dist/vector-handler.cjs.map +1 -0
  310. package/dist/vector-handler.js +238 -0
  311. package/dist/vector-handler.js.map +1 -0
  312. package/dist/vector-mock.cjs +229 -0
  313. package/dist/vector-mock.cjs.map +1 -0
  314. package/dist/vector-mock.d.cts +39 -0
  315. package/dist/vector-mock.d.cts.map +1 -0
  316. package/dist/vector-mock.d.ts +39 -0
  317. package/dist/vector-mock.d.ts.map +1 -0
  318. package/dist/vector-mock.js +227 -0
  319. package/dist/vector-mock.js.map +1 -0
  320. package/dist/vector-stub.cjs +4 -0
  321. package/dist/vector-stub.d.cts +3 -0
  322. package/dist/vector-stub.d.ts +3 -0
  323. package/dist/vector-stub.js +3 -0
  324. package/dist/vector-types.d.cts +32 -0
  325. package/dist/vector-types.d.cts.map +1 -0
  326. package/dist/vector-types.d.ts +32 -0
  327. package/dist/vector-types.d.ts.map +1 -0
  328. package/dist/watcher.cjs +59 -0
  329. package/dist/watcher.cjs.map +1 -0
  330. package/dist/watcher.js +58 -0
  331. package/dist/watcher.js.map +1 -0
  332. package/dist/ws-framing.cjs +187 -0
  333. package/dist/ws-framing.cjs.map +1 -0
  334. package/dist/ws-framing.d.cts +26 -0
  335. package/dist/ws-framing.d.cts.map +1 -0
  336. package/dist/ws-framing.d.ts +26 -0
  337. package/dist/ws-framing.d.ts.map +1 -0
  338. package/dist/ws-framing.js +184 -0
  339. package/dist/ws-framing.js.map +1 -0
  340. package/dist/ws-gemini-live.cjs +364 -0
  341. package/dist/ws-gemini-live.cjs.map +1 -0
  342. package/dist/ws-gemini-live.d.cts +18 -0
  343. package/dist/ws-gemini-live.d.cts.map +1 -0
  344. package/dist/ws-gemini-live.d.ts +18 -0
  345. package/dist/ws-gemini-live.d.ts.map +1 -0
  346. package/dist/ws-gemini-live.js +364 -0
  347. package/dist/ws-gemini-live.js.map +1 -0
  348. package/dist/ws-realtime.cjs +435 -0
  349. package/dist/ws-realtime.cjs.map +1 -0
  350. package/dist/ws-realtime.d.cts +17 -0
  351. package/dist/ws-realtime.d.cts.map +1 -0
  352. package/dist/ws-realtime.d.ts +17 -0
  353. package/dist/ws-realtime.d.ts.map +1 -0
  354. package/dist/ws-realtime.js +435 -0
  355. package/dist/ws-realtime.js.map +1 -0
  356. package/dist/ws-responses.cjs +164 -0
  357. package/dist/ws-responses.cjs.map +1 -0
  358. package/dist/ws-responses.d.cts +18 -0
  359. package/dist/ws-responses.d.cts.map +1 -0
  360. package/dist/ws-responses.d.ts +18 -0
  361. package/dist/ws-responses.d.ts.map +1 -0
  362. package/dist/ws-responses.js +164 -0
  363. package/dist/ws-responses.js.map +1 -0
  364. package/fixtures/example-greeting.json +12 -0
  365. package/fixtures/example-multi-turn.json +14 -0
  366. package/fixtures/example-tool-call.json +15 -0
  367. package/package.json +118 -0
  368. package/skills/write-fixtures/SKILL.md +625 -0
package/dist/url.cjs ADDED
@@ -0,0 +1,21 @@
1
+
2
+ //#region src/url.ts
3
+ /**
4
+ * Resolve an upstream URL by joining a base URL with a request pathname.
5
+ *
6
+ * Uses RFC 3986 relative resolution: the base URL's path prefix is preserved
7
+ * by ensuring a trailing slash (marking it as a "directory") and stripping the
8
+ * leading slash from the pathname (making it relative, not absolute).
9
+ *
10
+ * Without this, `new URL("/v1/chat/completions", "https://openrouter.ai/api")`
11
+ * resolves to `https://openrouter.ai/v1/chat/completions` — losing the `/api` prefix.
12
+ */
13
+ function resolveUpstreamUrl(base, pathname) {
14
+ const normalizedBase = base.endsWith("/") ? base : base + "/";
15
+ const relativePath = pathname.startsWith("/") ? pathname.slice(1) : pathname;
16
+ return new URL(relativePath, normalizedBase);
17
+ }
18
+
19
+ //#endregion
20
+ exports.resolveUpstreamUrl = resolveUpstreamUrl;
21
+ //# sourceMappingURL=url.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.cjs","names":[],"sources":["../src/url.ts"],"sourcesContent":["/**\n * Resolve an upstream URL by joining a base URL with a request pathname.\n *\n * Uses RFC 3986 relative resolution: the base URL's path prefix is preserved\n * by ensuring a trailing slash (marking it as a \"directory\") and stripping the\n * leading slash from the pathname (making it relative, not absolute).\n *\n * Without this, `new URL(\"/v1/chat/completions\", \"https://openrouter.ai/api\")`\n * resolves to `https://openrouter.ai/v1/chat/completions` — losing the `/api` prefix.\n */\nexport function resolveUpstreamUrl(base: string, pathname: string): URL {\n const normalizedBase = base.endsWith(\"/\") ? base : base + \"/\";\n const relativePath = pathname.startsWith(\"/\") ? pathname.slice(1) : pathname;\n return new URL(relativePath, normalizedBase);\n}\n"],"mappings":";;;;;;;;;;;;AAUA,SAAgB,mBAAmB,MAAc,UAAuB;CACtE,MAAM,iBAAiB,KAAK,SAAS,IAAI,GAAG,OAAO,OAAO;CAC1D,MAAM,eAAe,SAAS,WAAW,IAAI,GAAG,SAAS,MAAM,EAAE,GAAG;AACpE,QAAO,IAAI,IAAI,cAAc,eAAe"}
package/dist/url.d.cts ADDED
@@ -0,0 +1,16 @@
1
+ //#region src/url.d.ts
2
+ /**
3
+ * Resolve an upstream URL by joining a base URL with a request pathname.
4
+ *
5
+ * Uses RFC 3986 relative resolution: the base URL's path prefix is preserved
6
+ * by ensuring a trailing slash (marking it as a "directory") and stripping the
7
+ * leading slash from the pathname (making it relative, not absolute).
8
+ *
9
+ * Without this, `new URL("/v1/chat/completions", "https://openrouter.ai/api")`
10
+ * resolves to `https://openrouter.ai/v1/chat/completions` — losing the `/api` prefix.
11
+ */
12
+ declare function resolveUpstreamUrl(base: string, pathname: string): URL;
13
+ //# sourceMappingURL=url.d.ts.map
14
+ //#endregion
15
+ export { resolveUpstreamUrl };
16
+ //# sourceMappingURL=url.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.cts","names":[],"sources":["../src/url.ts"],"sourcesContent":[],"mappings":";;AAUA;;;;;;;;;iBAAgB,kBAAA,kCAAoD"}
package/dist/url.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ //#region src/url.d.ts
2
+ /**
3
+ * Resolve an upstream URL by joining a base URL with a request pathname.
4
+ *
5
+ * Uses RFC 3986 relative resolution: the base URL's path prefix is preserved
6
+ * by ensuring a trailing slash (marking it as a "directory") and stripping the
7
+ * leading slash from the pathname (making it relative, not absolute).
8
+ *
9
+ * Without this, `new URL("/v1/chat/completions", "https://openrouter.ai/api")`
10
+ * resolves to `https://openrouter.ai/v1/chat/completions` — losing the `/api` prefix.
11
+ */
12
+ declare function resolveUpstreamUrl(base: string, pathname: string): URL;
13
+ //# sourceMappingURL=url.d.ts.map
14
+ //#endregion
15
+ export { resolveUpstreamUrl };
16
+ //# sourceMappingURL=url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.ts","names":[],"sources":["../src/url.ts"],"sourcesContent":[],"mappings":";;AAUA;;;;;;;;;iBAAgB,kBAAA,kCAAoD"}
package/dist/url.js ADDED
@@ -0,0 +1,20 @@
1
+ //#region src/url.ts
2
+ /**
3
+ * Resolve an upstream URL by joining a base URL with a request pathname.
4
+ *
5
+ * Uses RFC 3986 relative resolution: the base URL's path prefix is preserved
6
+ * by ensuring a trailing slash (marking it as a "directory") and stripping the
7
+ * leading slash from the pathname (making it relative, not absolute).
8
+ *
9
+ * Without this, `new URL("/v1/chat/completions", "https://openrouter.ai/api")`
10
+ * resolves to `https://openrouter.ai/v1/chat/completions` — losing the `/api` prefix.
11
+ */
12
+ function resolveUpstreamUrl(base, pathname) {
13
+ const normalizedBase = base.endsWith("/") ? base : base + "/";
14
+ const relativePath = pathname.startsWith("/") ? pathname.slice(1) : pathname;
15
+ return new URL(relativePath, normalizedBase);
16
+ }
17
+
18
+ //#endregion
19
+ export { resolveUpstreamUrl };
20
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","names":[],"sources":["../src/url.ts"],"sourcesContent":["/**\n * Resolve an upstream URL by joining a base URL with a request pathname.\n *\n * Uses RFC 3986 relative resolution: the base URL's path prefix is preserved\n * by ensuring a trailing slash (marking it as a \"directory\") and stripping the\n * leading slash from the pathname (making it relative, not absolute).\n *\n * Without this, `new URL(\"/v1/chat/completions\", \"https://openrouter.ai/api\")`\n * resolves to `https://openrouter.ai/v1/chat/completions` — losing the `/api` prefix.\n */\nexport function resolveUpstreamUrl(base: string, pathname: string): URL {\n const normalizedBase = base.endsWith(\"/\") ? base : base + \"/\";\n const relativePath = pathname.startsWith(\"/\") ? pathname.slice(1) : pathname;\n return new URL(relativePath, normalizedBase);\n}\n"],"mappings":";;;;;;;;;;;AAUA,SAAgB,mBAAmB,MAAc,UAAuB;CACtE,MAAM,iBAAiB,KAAK,SAAS,IAAI,GAAG,OAAO,OAAO;CAC1D,MAAM,eAAe,SAAS,WAAW,IAAI,GAAG,SAAS,MAAM,EAAE,GAAG;AACpE,QAAO,IAAI,IAAI,cAAc,eAAe"}
@@ -0,0 +1,239 @@
1
+
2
+ //#region src/vector-handler.ts
3
+ function jsonResponse(res, status, body) {
4
+ const payload = JSON.stringify(body);
5
+ res.writeHead(status, {
6
+ "Content-Type": "application/json",
7
+ "Content-Length": String(Buffer.byteLength(payload))
8
+ });
9
+ res.end(payload);
10
+ }
11
+ function resolveQuery(state, collectionName, query) {
12
+ const handler = state.queryHandlers.get(collectionName);
13
+ if (!handler) return [];
14
+ if (typeof handler === "function") return handler(query);
15
+ return handler;
16
+ }
17
+ function handlePinecone(state, req, res, pathname, body) {
18
+ if (req.method === "POST" && pathname === "/query") {
19
+ const namespace = body.namespace ?? "default";
20
+ if (!state.collections.get(namespace)) {
21
+ jsonResponse(res, 404, { error: { message: `Collection '${namespace}' not found` } });
22
+ return { handled: true };
23
+ }
24
+ const query = {
25
+ vector: body.vector,
26
+ topK: body.topK,
27
+ filter: body.filter,
28
+ collection: namespace
29
+ };
30
+ const results = resolveQuery(state, namespace, query);
31
+ const topK = query.topK ?? 10;
32
+ jsonResponse(res, 200, { matches: results.slice(0, topK).map((r) => ({
33
+ id: r.id,
34
+ score: r.score,
35
+ ...r.metadata !== void 0 && { metadata: r.metadata }
36
+ })) });
37
+ return { handled: true };
38
+ }
39
+ if (req.method === "POST" && pathname === "/vectors/upsert") {
40
+ const vectors = body.vectors ?? [];
41
+ const namespace = body.namespace ?? "default";
42
+ let collection = state.collections.get(namespace);
43
+ if (!collection) {
44
+ collection = {
45
+ name: namespace,
46
+ dimension: vectors.length > 0 ? vectors[0].values.length : 0,
47
+ vectors: /* @__PURE__ */ new Map()
48
+ };
49
+ state.collections.set(namespace, collection);
50
+ }
51
+ for (const v of vectors) {
52
+ const entry = {
53
+ id: v.id,
54
+ values: v.values,
55
+ metadata: v.metadata
56
+ };
57
+ collection.vectors.set(v.id, entry);
58
+ }
59
+ jsonResponse(res, 200, { upsertedCount: vectors.length });
60
+ return { handled: true };
61
+ }
62
+ if (req.method === "POST" && pathname === "/vectors/delete") {
63
+ const ids = body.ids ?? [];
64
+ const namespace = body.namespace ?? "default";
65
+ const collection = state.collections.get(namespace);
66
+ if (collection) for (const id of ids) collection.vectors.delete(id);
67
+ jsonResponse(res, 200, {});
68
+ return { handled: true };
69
+ }
70
+ if (req.method === "GET" && pathname === "/describe-index-stats") {
71
+ let totalVectorCount = 0;
72
+ let dimension = 0;
73
+ for (const col of state.collections.values()) {
74
+ totalVectorCount += col.vectors.size;
75
+ if (col.dimension > 0) dimension = col.dimension;
76
+ }
77
+ jsonResponse(res, 200, {
78
+ dimension,
79
+ totalVectorCount
80
+ });
81
+ return { handled: true };
82
+ }
83
+ return { handled: false };
84
+ }
85
+ const QDRANT_SEARCH_RE = /^\/collections\/([^/]+)\/points\/search$/;
86
+ const QDRANT_UPSERT_RE = /^\/collections\/([^/]+)\/points$/;
87
+ const QDRANT_DELETE_RE = /^\/collections\/([^/]+)\/points\/delete$/;
88
+ function handleQdrant(state, req, res, pathname, body) {
89
+ let match = pathname.match(QDRANT_SEARCH_RE);
90
+ if (match && req.method === "POST") {
91
+ const name = decodeURIComponent(match[1]);
92
+ if (!state.collections.get(name)) {
93
+ jsonResponse(res, 404, { status: { error: `Collection '${name}' not found` } });
94
+ return { handled: true };
95
+ }
96
+ const results = resolveQuery(state, name, {
97
+ vector: body.vector,
98
+ topK: body.limit,
99
+ filter: body.filter,
100
+ collection: name
101
+ });
102
+ const limit = body.limit ?? 10;
103
+ jsonResponse(res, 200, { result: results.slice(0, limit).map((r) => ({
104
+ id: r.id,
105
+ score: r.score,
106
+ ...r.metadata !== void 0 && { payload: r.metadata }
107
+ })) });
108
+ return { handled: true };
109
+ }
110
+ match = pathname.match(QDRANT_UPSERT_RE);
111
+ if (match && req.method === "PUT") {
112
+ const name = decodeURIComponent(match[1]);
113
+ let collection = state.collections.get(name);
114
+ const points = body.points ?? [];
115
+ if (!collection) {
116
+ collection = {
117
+ name,
118
+ dimension: points.length > 0 ? points[0].vector.length : 0,
119
+ vectors: /* @__PURE__ */ new Map()
120
+ };
121
+ state.collections.set(name, collection);
122
+ }
123
+ for (const p of points) {
124
+ const entry = {
125
+ id: String(p.id),
126
+ values: p.vector,
127
+ metadata: p.payload
128
+ };
129
+ collection.vectors.set(String(p.id), entry);
130
+ }
131
+ jsonResponse(res, 200, { status: "ok" });
132
+ return { handled: true };
133
+ }
134
+ match = pathname.match(QDRANT_DELETE_RE);
135
+ if (match && req.method === "POST") {
136
+ const name = decodeURIComponent(match[1]);
137
+ const collection = state.collections.get(name);
138
+ const points = body.points ?? [];
139
+ if (collection) for (const id of points) collection.vectors.delete(String(id));
140
+ jsonResponse(res, 200, { status: "ok" });
141
+ return { handled: true };
142
+ }
143
+ return { handled: false };
144
+ }
145
+ const CHROMA_QUERY_RE = /^\/api\/v1\/collections\/([^/]+)\/query$/;
146
+ const CHROMA_ADD_RE = /^\/api\/v1\/collections\/([^/]+)\/add$/;
147
+ const CHROMA_COLLECTION_RE = /^\/api\/v1\/collections\/([^/]+)$/;
148
+ const CHROMA_COLLECTIONS = "/api/v1/collections";
149
+ function handleChromaDB(state, req, res, pathname, body) {
150
+ let match = pathname.match(CHROMA_QUERY_RE);
151
+ if (match && req.method === "POST") {
152
+ const name = decodeURIComponent(match[1]);
153
+ if (!state.collections.get(name)) {
154
+ jsonResponse(res, 404, { error: `Collection '${name}' not found` });
155
+ return { handled: true };
156
+ }
157
+ const queryEmbeddings = body.query_embeddings ?? [];
158
+ const nResults = body.n_results ?? 10;
159
+ const allIds = [];
160
+ const allDistances = [];
161
+ const allMetadatas = [];
162
+ for (const embedding of queryEmbeddings) {
163
+ const results = resolveQuery(state, name, {
164
+ vector: embedding,
165
+ topK: nResults,
166
+ filter: body.where,
167
+ collection: name
168
+ }).slice(0, nResults);
169
+ allIds.push(results.map((r) => r.id));
170
+ allDistances.push(results.map((r) => r.score));
171
+ allMetadatas.push(results.map((r) => r.metadata ?? null));
172
+ }
173
+ jsonResponse(res, 200, {
174
+ ids: allIds,
175
+ distances: allDistances,
176
+ metadatas: allMetadatas
177
+ });
178
+ return { handled: true };
179
+ }
180
+ match = pathname.match(CHROMA_ADD_RE);
181
+ if (match && req.method === "POST") {
182
+ const name = decodeURIComponent(match[1]);
183
+ let collection = state.collections.get(name);
184
+ const ids = body.ids ?? [];
185
+ const embeddings = body.embeddings ?? [];
186
+ const metadatas = body.metadatas ?? [];
187
+ if (!collection) {
188
+ collection = {
189
+ name,
190
+ dimension: embeddings.length > 0 ? embeddings[0].length : 0,
191
+ vectors: /* @__PURE__ */ new Map()
192
+ };
193
+ state.collections.set(name, collection);
194
+ }
195
+ for (let i = 0; i < ids.length; i++) {
196
+ const entry = {
197
+ id: ids[i],
198
+ values: embeddings[i] ?? [],
199
+ metadata: metadatas[i]
200
+ };
201
+ collection.vectors.set(ids[i], entry);
202
+ }
203
+ jsonResponse(res, 200, true);
204
+ return { handled: true };
205
+ }
206
+ if (req.method === "GET" && pathname === CHROMA_COLLECTIONS) {
207
+ jsonResponse(res, 200, Array.from(state.collections.values()).map((c) => ({
208
+ id: c.name,
209
+ name: c.name,
210
+ metadata: null
211
+ })));
212
+ return { handled: true };
213
+ }
214
+ match = pathname.match(CHROMA_COLLECTION_RE);
215
+ if (match && req.method === "DELETE") {
216
+ const name = decodeURIComponent(match[1]);
217
+ if (!state.collections.has(name)) {
218
+ jsonResponse(res, 404, { error: `Collection '${name}' not found` });
219
+ return { handled: true };
220
+ }
221
+ state.collections.delete(name);
222
+ state.queryHandlers.delete(name);
223
+ jsonResponse(res, 200, { status: "ok" });
224
+ return { handled: true };
225
+ }
226
+ return { handled: false };
227
+ }
228
+ function createVectorRequestHandler(state) {
229
+ return (req, res, pathname, body) => {
230
+ if (handlePinecone(state, req, res, pathname, body).handled) return true;
231
+ if (handleQdrant(state, req, res, pathname, body).handled) return true;
232
+ if (handleChromaDB(state, req, res, pathname, body).handled) return true;
233
+ return false;
234
+ };
235
+ }
236
+
237
+ //#endregion
238
+ exports.createVectorRequestHandler = createVectorRequestHandler;
239
+ //# sourceMappingURL=vector-handler.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector-handler.cjs","names":[],"sources":["../src/vector-handler.ts"],"sourcesContent":["import type * as http from \"node:http\";\nimport type {\n VectorCollection,\n VectorEntry,\n VectorQuery,\n QueryResult,\n QueryHandler,\n} from \"./vector-types.js\";\n\nexport interface VectorState {\n collections: Map<string, VectorCollection>;\n queryHandlers: Map<string, QueryHandler>;\n}\n\ninterface RouteResult {\n handled: boolean;\n}\n\nfunction jsonResponse(res: http.ServerResponse, status: number, body: unknown): void {\n const payload = JSON.stringify(body);\n res.writeHead(status, {\n \"Content-Type\": \"application/json\",\n \"Content-Length\": String(Buffer.byteLength(payload)),\n });\n res.end(payload);\n}\n\nfunction resolveQuery(\n state: VectorState,\n collectionName: string,\n query: VectorQuery,\n): QueryResult[] {\n const handler = state.queryHandlers.get(collectionName);\n if (!handler) return [];\n if (typeof handler === \"function\") return handler(query);\n return handler;\n}\n\n// ---- Pinecone-compatible endpoints ----\n\nfunction handlePinecone(\n state: VectorState,\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n body: Record<string, unknown>,\n): RouteResult {\n // POST /query\n if (req.method === \"POST\" && pathname === \"/query\") {\n const namespace = (body.namespace as string) ?? \"default\";\n const collection = state.collections.get(namespace);\n if (!collection) {\n jsonResponse(res, 404, { error: { message: `Collection '${namespace}' not found` } });\n return { handled: true };\n }\n\n const query: VectorQuery = {\n vector: body.vector as number[] | undefined,\n topK: body.topK as number | undefined,\n filter: body.filter,\n collection: namespace,\n };\n const results = resolveQuery(state, namespace, query);\n const topK = query.topK ?? 10;\n const matches = results.slice(0, topK).map((r) => ({\n id: r.id,\n score: r.score,\n ...(r.metadata !== undefined && { metadata: r.metadata }),\n }));\n\n jsonResponse(res, 200, { matches });\n return { handled: true };\n }\n\n // POST /vectors/upsert\n if (req.method === \"POST\" && pathname === \"/vectors/upsert\") {\n const vectors = (body.vectors ?? []) as Array<{\n id: string;\n values: number[];\n metadata?: Record<string, unknown>;\n }>;\n const namespace = (body.namespace as string) ?? \"default\";\n\n let collection = state.collections.get(namespace);\n if (!collection) {\n const dim = vectors.length > 0 ? vectors[0].values.length : 0;\n collection = { name: namespace, dimension: dim, vectors: new Map() };\n state.collections.set(namespace, collection);\n }\n\n for (const v of vectors) {\n const entry: VectorEntry = { id: v.id, values: v.values, metadata: v.metadata };\n collection.vectors.set(v.id, entry);\n }\n\n jsonResponse(res, 200, { upsertedCount: vectors.length });\n return { handled: true };\n }\n\n // POST /vectors/delete\n if (req.method === \"POST\" && pathname === \"/vectors/delete\") {\n const ids = (body.ids ?? []) as string[];\n const namespace = (body.namespace as string) ?? \"default\";\n const collection = state.collections.get(namespace);\n if (collection) {\n for (const id of ids) {\n collection.vectors.delete(id);\n }\n }\n jsonResponse(res, 200, {});\n return { handled: true };\n }\n\n // GET /describe-index-stats\n if (req.method === \"GET\" && pathname === \"/describe-index-stats\") {\n let totalVectorCount = 0;\n let dimension = 0;\n for (const col of state.collections.values()) {\n totalVectorCount += col.vectors.size;\n if (col.dimension > 0) dimension = col.dimension;\n }\n jsonResponse(res, 200, { dimension, totalVectorCount });\n return { handled: true };\n }\n\n return { handled: false };\n}\n\n// ---- Qdrant-compatible endpoints ----\n\nconst QDRANT_SEARCH_RE = /^\\/collections\\/([^/]+)\\/points\\/search$/;\nconst QDRANT_UPSERT_RE = /^\\/collections\\/([^/]+)\\/points$/;\nconst QDRANT_DELETE_RE = /^\\/collections\\/([^/]+)\\/points\\/delete$/;\n\nfunction handleQdrant(\n state: VectorState,\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n body: Record<string, unknown>,\n): RouteResult {\n // POST /collections/{name}/points/search\n let match = pathname.match(QDRANT_SEARCH_RE);\n if (match && req.method === \"POST\") {\n const name = decodeURIComponent(match[1]);\n const collection = state.collections.get(name);\n if (!collection) {\n jsonResponse(res, 404, { status: { error: `Collection '${name}' not found` } });\n return { handled: true };\n }\n\n const query: VectorQuery = {\n vector: body.vector as number[] | undefined,\n topK: body.limit as number | undefined,\n filter: body.filter,\n collection: name,\n };\n const results = resolveQuery(state, name, query);\n const limit = (body.limit as number) ?? 10;\n const result = results.slice(0, limit).map((r) => ({\n id: r.id,\n score: r.score,\n ...(r.metadata !== undefined && { payload: r.metadata }),\n }));\n\n jsonResponse(res, 200, { result });\n return { handled: true };\n }\n\n // PUT /collections/{name}/points\n match = pathname.match(QDRANT_UPSERT_RE);\n if (match && req.method === \"PUT\") {\n const name = decodeURIComponent(match[1]);\n let collection = state.collections.get(name);\n const points = (body.points ?? []) as Array<{\n id: string;\n vector: number[];\n payload?: Record<string, unknown>;\n }>;\n\n if (!collection) {\n const dim = points.length > 0 ? points[0].vector.length : 0;\n collection = { name, dimension: dim, vectors: new Map() };\n state.collections.set(name, collection);\n }\n\n for (const p of points) {\n const entry: VectorEntry = { id: String(p.id), values: p.vector, metadata: p.payload };\n collection.vectors.set(String(p.id), entry);\n }\n\n jsonResponse(res, 200, { status: \"ok\" });\n return { handled: true };\n }\n\n // POST /collections/{name}/points/delete\n match = pathname.match(QDRANT_DELETE_RE);\n if (match && req.method === \"POST\") {\n const name = decodeURIComponent(match[1]);\n const collection = state.collections.get(name);\n const points = (body.points ?? []) as string[];\n if (collection) {\n for (const id of points) {\n collection.vectors.delete(String(id));\n }\n }\n jsonResponse(res, 200, { status: \"ok\" });\n return { handled: true };\n }\n\n return { handled: false };\n}\n\n// ---- ChromaDB-compatible endpoints ----\n\nconst CHROMA_QUERY_RE = /^\\/api\\/v1\\/collections\\/([^/]+)\\/query$/;\nconst CHROMA_ADD_RE = /^\\/api\\/v1\\/collections\\/([^/]+)\\/add$/;\nconst CHROMA_COLLECTION_RE = /^\\/api\\/v1\\/collections\\/([^/]+)$/;\nconst CHROMA_COLLECTIONS = \"/api/v1/collections\";\n\nfunction handleChromaDB(\n state: VectorState,\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n body: Record<string, unknown>,\n): RouteResult {\n // POST /api/v1/collections/{id}/query\n let match = pathname.match(CHROMA_QUERY_RE);\n if (match && req.method === \"POST\") {\n const name = decodeURIComponent(match[1]);\n const collection = state.collections.get(name);\n if (!collection) {\n jsonResponse(res, 404, { error: `Collection '${name}' not found` });\n return { handled: true };\n }\n\n const queryEmbeddings = (body.query_embeddings ?? []) as number[][];\n const nResults = (body.n_results as number) ?? 10;\n\n // Process each query embedding\n const allIds: string[][] = [];\n const allDistances: number[][] = [];\n const allMetadatas: Array<Array<Record<string, unknown> | null>> = [];\n\n for (const embedding of queryEmbeddings) {\n const query: VectorQuery = {\n vector: embedding,\n topK: nResults,\n filter: body.where,\n collection: name,\n };\n const results = resolveQuery(state, name, query).slice(0, nResults);\n\n allIds.push(results.map((r) => r.id));\n allDistances.push(results.map((r) => r.score));\n allMetadatas.push(results.map((r) => r.metadata ?? null));\n }\n\n jsonResponse(res, 200, {\n ids: allIds,\n distances: allDistances,\n metadatas: allMetadatas,\n });\n return { handled: true };\n }\n\n // POST /api/v1/collections/{id}/add\n match = pathname.match(CHROMA_ADD_RE);\n if (match && req.method === \"POST\") {\n const name = decodeURIComponent(match[1]);\n let collection = state.collections.get(name);\n\n const ids = (body.ids ?? []) as string[];\n const embeddings = (body.embeddings ?? []) as number[][];\n const metadatas = (body.metadatas ?? []) as Array<Record<string, unknown> | undefined>;\n\n if (!collection) {\n const dim = embeddings.length > 0 ? embeddings[0].length : 0;\n collection = { name, dimension: dim, vectors: new Map() };\n state.collections.set(name, collection);\n }\n\n for (let i = 0; i < ids.length; i++) {\n const entry: VectorEntry = {\n id: ids[i],\n values: embeddings[i] ?? [],\n metadata: metadatas[i],\n };\n collection.vectors.set(ids[i], entry);\n }\n\n jsonResponse(res, 200, true);\n return { handled: true };\n }\n\n // GET /api/v1/collections — list collections\n if (req.method === \"GET\" && pathname === CHROMA_COLLECTIONS) {\n const collections = Array.from(state.collections.values()).map((c) => ({\n id: c.name,\n name: c.name,\n metadata: null,\n }));\n jsonResponse(res, 200, collections);\n return { handled: true };\n }\n\n // DELETE /api/v1/collections/{id}\n match = pathname.match(CHROMA_COLLECTION_RE);\n if (match && req.method === \"DELETE\") {\n const name = decodeURIComponent(match[1]);\n if (!state.collections.has(name)) {\n jsonResponse(res, 404, { error: `Collection '${name}' not found` });\n return { handled: true };\n }\n state.collections.delete(name);\n state.queryHandlers.delete(name);\n jsonResponse(res, 200, { status: \"ok\" });\n return { handled: true };\n }\n\n return { handled: false };\n}\n\n// ---- Main dispatch ----\n\nexport function createVectorRequestHandler(state: VectorState) {\n return (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n body: Record<string, unknown>,\n ): boolean => {\n const pinecone = handlePinecone(state, req, res, pathname, body);\n if (pinecone.handled) return true;\n\n const qdrant = handleQdrant(state, req, res, pathname, body);\n if (qdrant.handled) return true;\n\n const chroma = handleChromaDB(state, req, res, pathname, body);\n if (chroma.handled) return true;\n\n return false;\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,238 @@
1
+ //#region src/vector-handler.ts
2
+ function jsonResponse(res, status, body) {
3
+ const payload = JSON.stringify(body);
4
+ res.writeHead(status, {
5
+ "Content-Type": "application/json",
6
+ "Content-Length": String(Buffer.byteLength(payload))
7
+ });
8
+ res.end(payload);
9
+ }
10
+ function resolveQuery(state, collectionName, query) {
11
+ const handler = state.queryHandlers.get(collectionName);
12
+ if (!handler) return [];
13
+ if (typeof handler === "function") return handler(query);
14
+ return handler;
15
+ }
16
+ function handlePinecone(state, req, res, pathname, body) {
17
+ if (req.method === "POST" && pathname === "/query") {
18
+ const namespace = body.namespace ?? "default";
19
+ if (!state.collections.get(namespace)) {
20
+ jsonResponse(res, 404, { error: { message: `Collection '${namespace}' not found` } });
21
+ return { handled: true };
22
+ }
23
+ const query = {
24
+ vector: body.vector,
25
+ topK: body.topK,
26
+ filter: body.filter,
27
+ collection: namespace
28
+ };
29
+ const results = resolveQuery(state, namespace, query);
30
+ const topK = query.topK ?? 10;
31
+ jsonResponse(res, 200, { matches: results.slice(0, topK).map((r) => ({
32
+ id: r.id,
33
+ score: r.score,
34
+ ...r.metadata !== void 0 && { metadata: r.metadata }
35
+ })) });
36
+ return { handled: true };
37
+ }
38
+ if (req.method === "POST" && pathname === "/vectors/upsert") {
39
+ const vectors = body.vectors ?? [];
40
+ const namespace = body.namespace ?? "default";
41
+ let collection = state.collections.get(namespace);
42
+ if (!collection) {
43
+ collection = {
44
+ name: namespace,
45
+ dimension: vectors.length > 0 ? vectors[0].values.length : 0,
46
+ vectors: /* @__PURE__ */ new Map()
47
+ };
48
+ state.collections.set(namespace, collection);
49
+ }
50
+ for (const v of vectors) {
51
+ const entry = {
52
+ id: v.id,
53
+ values: v.values,
54
+ metadata: v.metadata
55
+ };
56
+ collection.vectors.set(v.id, entry);
57
+ }
58
+ jsonResponse(res, 200, { upsertedCount: vectors.length });
59
+ return { handled: true };
60
+ }
61
+ if (req.method === "POST" && pathname === "/vectors/delete") {
62
+ const ids = body.ids ?? [];
63
+ const namespace = body.namespace ?? "default";
64
+ const collection = state.collections.get(namespace);
65
+ if (collection) for (const id of ids) collection.vectors.delete(id);
66
+ jsonResponse(res, 200, {});
67
+ return { handled: true };
68
+ }
69
+ if (req.method === "GET" && pathname === "/describe-index-stats") {
70
+ let totalVectorCount = 0;
71
+ let dimension = 0;
72
+ for (const col of state.collections.values()) {
73
+ totalVectorCount += col.vectors.size;
74
+ if (col.dimension > 0) dimension = col.dimension;
75
+ }
76
+ jsonResponse(res, 200, {
77
+ dimension,
78
+ totalVectorCount
79
+ });
80
+ return { handled: true };
81
+ }
82
+ return { handled: false };
83
+ }
84
+ const QDRANT_SEARCH_RE = /^\/collections\/([^/]+)\/points\/search$/;
85
+ const QDRANT_UPSERT_RE = /^\/collections\/([^/]+)\/points$/;
86
+ const QDRANT_DELETE_RE = /^\/collections\/([^/]+)\/points\/delete$/;
87
+ function handleQdrant(state, req, res, pathname, body) {
88
+ let match = pathname.match(QDRANT_SEARCH_RE);
89
+ if (match && req.method === "POST") {
90
+ const name = decodeURIComponent(match[1]);
91
+ if (!state.collections.get(name)) {
92
+ jsonResponse(res, 404, { status: { error: `Collection '${name}' not found` } });
93
+ return { handled: true };
94
+ }
95
+ const results = resolveQuery(state, name, {
96
+ vector: body.vector,
97
+ topK: body.limit,
98
+ filter: body.filter,
99
+ collection: name
100
+ });
101
+ const limit = body.limit ?? 10;
102
+ jsonResponse(res, 200, { result: results.slice(0, limit).map((r) => ({
103
+ id: r.id,
104
+ score: r.score,
105
+ ...r.metadata !== void 0 && { payload: r.metadata }
106
+ })) });
107
+ return { handled: true };
108
+ }
109
+ match = pathname.match(QDRANT_UPSERT_RE);
110
+ if (match && req.method === "PUT") {
111
+ const name = decodeURIComponent(match[1]);
112
+ let collection = state.collections.get(name);
113
+ const points = body.points ?? [];
114
+ if (!collection) {
115
+ collection = {
116
+ name,
117
+ dimension: points.length > 0 ? points[0].vector.length : 0,
118
+ vectors: /* @__PURE__ */ new Map()
119
+ };
120
+ state.collections.set(name, collection);
121
+ }
122
+ for (const p of points) {
123
+ const entry = {
124
+ id: String(p.id),
125
+ values: p.vector,
126
+ metadata: p.payload
127
+ };
128
+ collection.vectors.set(String(p.id), entry);
129
+ }
130
+ jsonResponse(res, 200, { status: "ok" });
131
+ return { handled: true };
132
+ }
133
+ match = pathname.match(QDRANT_DELETE_RE);
134
+ if (match && req.method === "POST") {
135
+ const name = decodeURIComponent(match[1]);
136
+ const collection = state.collections.get(name);
137
+ const points = body.points ?? [];
138
+ if (collection) for (const id of points) collection.vectors.delete(String(id));
139
+ jsonResponse(res, 200, { status: "ok" });
140
+ return { handled: true };
141
+ }
142
+ return { handled: false };
143
+ }
144
+ const CHROMA_QUERY_RE = /^\/api\/v1\/collections\/([^/]+)\/query$/;
145
+ const CHROMA_ADD_RE = /^\/api\/v1\/collections\/([^/]+)\/add$/;
146
+ const CHROMA_COLLECTION_RE = /^\/api\/v1\/collections\/([^/]+)$/;
147
+ const CHROMA_COLLECTIONS = "/api/v1/collections";
148
+ function handleChromaDB(state, req, res, pathname, body) {
149
+ let match = pathname.match(CHROMA_QUERY_RE);
150
+ if (match && req.method === "POST") {
151
+ const name = decodeURIComponent(match[1]);
152
+ if (!state.collections.get(name)) {
153
+ jsonResponse(res, 404, { error: `Collection '${name}' not found` });
154
+ return { handled: true };
155
+ }
156
+ const queryEmbeddings = body.query_embeddings ?? [];
157
+ const nResults = body.n_results ?? 10;
158
+ const allIds = [];
159
+ const allDistances = [];
160
+ const allMetadatas = [];
161
+ for (const embedding of queryEmbeddings) {
162
+ const results = resolveQuery(state, name, {
163
+ vector: embedding,
164
+ topK: nResults,
165
+ filter: body.where,
166
+ collection: name
167
+ }).slice(0, nResults);
168
+ allIds.push(results.map((r) => r.id));
169
+ allDistances.push(results.map((r) => r.score));
170
+ allMetadatas.push(results.map((r) => r.metadata ?? null));
171
+ }
172
+ jsonResponse(res, 200, {
173
+ ids: allIds,
174
+ distances: allDistances,
175
+ metadatas: allMetadatas
176
+ });
177
+ return { handled: true };
178
+ }
179
+ match = pathname.match(CHROMA_ADD_RE);
180
+ if (match && req.method === "POST") {
181
+ const name = decodeURIComponent(match[1]);
182
+ let collection = state.collections.get(name);
183
+ const ids = body.ids ?? [];
184
+ const embeddings = body.embeddings ?? [];
185
+ const metadatas = body.metadatas ?? [];
186
+ if (!collection) {
187
+ collection = {
188
+ name,
189
+ dimension: embeddings.length > 0 ? embeddings[0].length : 0,
190
+ vectors: /* @__PURE__ */ new Map()
191
+ };
192
+ state.collections.set(name, collection);
193
+ }
194
+ for (let i = 0; i < ids.length; i++) {
195
+ const entry = {
196
+ id: ids[i],
197
+ values: embeddings[i] ?? [],
198
+ metadata: metadatas[i]
199
+ };
200
+ collection.vectors.set(ids[i], entry);
201
+ }
202
+ jsonResponse(res, 200, true);
203
+ return { handled: true };
204
+ }
205
+ if (req.method === "GET" && pathname === CHROMA_COLLECTIONS) {
206
+ jsonResponse(res, 200, Array.from(state.collections.values()).map((c) => ({
207
+ id: c.name,
208
+ name: c.name,
209
+ metadata: null
210
+ })));
211
+ return { handled: true };
212
+ }
213
+ match = pathname.match(CHROMA_COLLECTION_RE);
214
+ if (match && req.method === "DELETE") {
215
+ const name = decodeURIComponent(match[1]);
216
+ if (!state.collections.has(name)) {
217
+ jsonResponse(res, 404, { error: `Collection '${name}' not found` });
218
+ return { handled: true };
219
+ }
220
+ state.collections.delete(name);
221
+ state.queryHandlers.delete(name);
222
+ jsonResponse(res, 200, { status: "ok" });
223
+ return { handled: true };
224
+ }
225
+ return { handled: false };
226
+ }
227
+ function createVectorRequestHandler(state) {
228
+ return (req, res, pathname, body) => {
229
+ if (handlePinecone(state, req, res, pathname, body).handled) return true;
230
+ if (handleQdrant(state, req, res, pathname, body).handled) return true;
231
+ if (handleChromaDB(state, req, res, pathname, body).handled) return true;
232
+ return false;
233
+ };
234
+ }
235
+
236
+ //#endregion
237
+ export { createVectorRequestHandler };
238
+ //# sourceMappingURL=vector-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector-handler.js","names":[],"sources":["../src/vector-handler.ts"],"sourcesContent":["import type * as http from \"node:http\";\nimport type {\n VectorCollection,\n VectorEntry,\n VectorQuery,\n QueryResult,\n QueryHandler,\n} from \"./vector-types.js\";\n\nexport interface VectorState {\n collections: Map<string, VectorCollection>;\n queryHandlers: Map<string, QueryHandler>;\n}\n\ninterface RouteResult {\n handled: boolean;\n}\n\nfunction jsonResponse(res: http.ServerResponse, status: number, body: unknown): void {\n const payload = JSON.stringify(body);\n res.writeHead(status, {\n \"Content-Type\": \"application/json\",\n \"Content-Length\": String(Buffer.byteLength(payload)),\n });\n res.end(payload);\n}\n\nfunction resolveQuery(\n state: VectorState,\n collectionName: string,\n query: VectorQuery,\n): QueryResult[] {\n const handler = state.queryHandlers.get(collectionName);\n if (!handler) return [];\n if (typeof handler === \"function\") return handler(query);\n return handler;\n}\n\n// ---- Pinecone-compatible endpoints ----\n\nfunction handlePinecone(\n state: VectorState,\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n body: Record<string, unknown>,\n): RouteResult {\n // POST /query\n if (req.method === \"POST\" && pathname === \"/query\") {\n const namespace = (body.namespace as string) ?? \"default\";\n const collection = state.collections.get(namespace);\n if (!collection) {\n jsonResponse(res, 404, { error: { message: `Collection '${namespace}' not found` } });\n return { handled: true };\n }\n\n const query: VectorQuery = {\n vector: body.vector as number[] | undefined,\n topK: body.topK as number | undefined,\n filter: body.filter,\n collection: namespace,\n };\n const results = resolveQuery(state, namespace, query);\n const topK = query.topK ?? 10;\n const matches = results.slice(0, topK).map((r) => ({\n id: r.id,\n score: r.score,\n ...(r.metadata !== undefined && { metadata: r.metadata }),\n }));\n\n jsonResponse(res, 200, { matches });\n return { handled: true };\n }\n\n // POST /vectors/upsert\n if (req.method === \"POST\" && pathname === \"/vectors/upsert\") {\n const vectors = (body.vectors ?? []) as Array<{\n id: string;\n values: number[];\n metadata?: Record<string, unknown>;\n }>;\n const namespace = (body.namespace as string) ?? \"default\";\n\n let collection = state.collections.get(namespace);\n if (!collection) {\n const dim = vectors.length > 0 ? vectors[0].values.length : 0;\n collection = { name: namespace, dimension: dim, vectors: new Map() };\n state.collections.set(namespace, collection);\n }\n\n for (const v of vectors) {\n const entry: VectorEntry = { id: v.id, values: v.values, metadata: v.metadata };\n collection.vectors.set(v.id, entry);\n }\n\n jsonResponse(res, 200, { upsertedCount: vectors.length });\n return { handled: true };\n }\n\n // POST /vectors/delete\n if (req.method === \"POST\" && pathname === \"/vectors/delete\") {\n const ids = (body.ids ?? []) as string[];\n const namespace = (body.namespace as string) ?? \"default\";\n const collection = state.collections.get(namespace);\n if (collection) {\n for (const id of ids) {\n collection.vectors.delete(id);\n }\n }\n jsonResponse(res, 200, {});\n return { handled: true };\n }\n\n // GET /describe-index-stats\n if (req.method === \"GET\" && pathname === \"/describe-index-stats\") {\n let totalVectorCount = 0;\n let dimension = 0;\n for (const col of state.collections.values()) {\n totalVectorCount += col.vectors.size;\n if (col.dimension > 0) dimension = col.dimension;\n }\n jsonResponse(res, 200, { dimension, totalVectorCount });\n return { handled: true };\n }\n\n return { handled: false };\n}\n\n// ---- Qdrant-compatible endpoints ----\n\nconst QDRANT_SEARCH_RE = /^\\/collections\\/([^/]+)\\/points\\/search$/;\nconst QDRANT_UPSERT_RE = /^\\/collections\\/([^/]+)\\/points$/;\nconst QDRANT_DELETE_RE = /^\\/collections\\/([^/]+)\\/points\\/delete$/;\n\nfunction handleQdrant(\n state: VectorState,\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n body: Record<string, unknown>,\n): RouteResult {\n // POST /collections/{name}/points/search\n let match = pathname.match(QDRANT_SEARCH_RE);\n if (match && req.method === \"POST\") {\n const name = decodeURIComponent(match[1]);\n const collection = state.collections.get(name);\n if (!collection) {\n jsonResponse(res, 404, { status: { error: `Collection '${name}' not found` } });\n return { handled: true };\n }\n\n const query: VectorQuery = {\n vector: body.vector as number[] | undefined,\n topK: body.limit as number | undefined,\n filter: body.filter,\n collection: name,\n };\n const results = resolveQuery(state, name, query);\n const limit = (body.limit as number) ?? 10;\n const result = results.slice(0, limit).map((r) => ({\n id: r.id,\n score: r.score,\n ...(r.metadata !== undefined && { payload: r.metadata }),\n }));\n\n jsonResponse(res, 200, { result });\n return { handled: true };\n }\n\n // PUT /collections/{name}/points\n match = pathname.match(QDRANT_UPSERT_RE);\n if (match && req.method === \"PUT\") {\n const name = decodeURIComponent(match[1]);\n let collection = state.collections.get(name);\n const points = (body.points ?? []) as Array<{\n id: string;\n vector: number[];\n payload?: Record<string, unknown>;\n }>;\n\n if (!collection) {\n const dim = points.length > 0 ? points[0].vector.length : 0;\n collection = { name, dimension: dim, vectors: new Map() };\n state.collections.set(name, collection);\n }\n\n for (const p of points) {\n const entry: VectorEntry = { id: String(p.id), values: p.vector, metadata: p.payload };\n collection.vectors.set(String(p.id), entry);\n }\n\n jsonResponse(res, 200, { status: \"ok\" });\n return { handled: true };\n }\n\n // POST /collections/{name}/points/delete\n match = pathname.match(QDRANT_DELETE_RE);\n if (match && req.method === \"POST\") {\n const name = decodeURIComponent(match[1]);\n const collection = state.collections.get(name);\n const points = (body.points ?? []) as string[];\n if (collection) {\n for (const id of points) {\n collection.vectors.delete(String(id));\n }\n }\n jsonResponse(res, 200, { status: \"ok\" });\n return { handled: true };\n }\n\n return { handled: false };\n}\n\n// ---- ChromaDB-compatible endpoints ----\n\nconst CHROMA_QUERY_RE = /^\\/api\\/v1\\/collections\\/([^/]+)\\/query$/;\nconst CHROMA_ADD_RE = /^\\/api\\/v1\\/collections\\/([^/]+)\\/add$/;\nconst CHROMA_COLLECTION_RE = /^\\/api\\/v1\\/collections\\/([^/]+)$/;\nconst CHROMA_COLLECTIONS = \"/api/v1/collections\";\n\nfunction handleChromaDB(\n state: VectorState,\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n body: Record<string, unknown>,\n): RouteResult {\n // POST /api/v1/collections/{id}/query\n let match = pathname.match(CHROMA_QUERY_RE);\n if (match && req.method === \"POST\") {\n const name = decodeURIComponent(match[1]);\n const collection = state.collections.get(name);\n if (!collection) {\n jsonResponse(res, 404, { error: `Collection '${name}' not found` });\n return { handled: true };\n }\n\n const queryEmbeddings = (body.query_embeddings ?? []) as number[][];\n const nResults = (body.n_results as number) ?? 10;\n\n // Process each query embedding\n const allIds: string[][] = [];\n const allDistances: number[][] = [];\n const allMetadatas: Array<Array<Record<string, unknown> | null>> = [];\n\n for (const embedding of queryEmbeddings) {\n const query: VectorQuery = {\n vector: embedding,\n topK: nResults,\n filter: body.where,\n collection: name,\n };\n const results = resolveQuery(state, name, query).slice(0, nResults);\n\n allIds.push(results.map((r) => r.id));\n allDistances.push(results.map((r) => r.score));\n allMetadatas.push(results.map((r) => r.metadata ?? null));\n }\n\n jsonResponse(res, 200, {\n ids: allIds,\n distances: allDistances,\n metadatas: allMetadatas,\n });\n return { handled: true };\n }\n\n // POST /api/v1/collections/{id}/add\n match = pathname.match(CHROMA_ADD_RE);\n if (match && req.method === \"POST\") {\n const name = decodeURIComponent(match[1]);\n let collection = state.collections.get(name);\n\n const ids = (body.ids ?? []) as string[];\n const embeddings = (body.embeddings ?? []) as number[][];\n const metadatas = (body.metadatas ?? []) as Array<Record<string, unknown> | undefined>;\n\n if (!collection) {\n const dim = embeddings.length > 0 ? embeddings[0].length : 0;\n collection = { name, dimension: dim, vectors: new Map() };\n state.collections.set(name, collection);\n }\n\n for (let i = 0; i < ids.length; i++) {\n const entry: VectorEntry = {\n id: ids[i],\n values: embeddings[i] ?? [],\n metadata: metadatas[i],\n };\n collection.vectors.set(ids[i], entry);\n }\n\n jsonResponse(res, 200, true);\n return { handled: true };\n }\n\n // GET /api/v1/collections — list collections\n if (req.method === \"GET\" && pathname === CHROMA_COLLECTIONS) {\n const collections = Array.from(state.collections.values()).map((c) => ({\n id: c.name,\n name: c.name,\n metadata: null,\n }));\n jsonResponse(res, 200, collections);\n return { handled: true };\n }\n\n // DELETE /api/v1/collections/{id}\n match = pathname.match(CHROMA_COLLECTION_RE);\n if (match && req.method === \"DELETE\") {\n const name = decodeURIComponent(match[1]);\n if (!state.collections.has(name)) {\n jsonResponse(res, 404, { error: `Collection '${name}' not found` });\n return { handled: true };\n }\n state.collections.delete(name);\n state.queryHandlers.delete(name);\n jsonResponse(res, 200, { status: \"ok\" });\n return { handled: true };\n }\n\n return { handled: false };\n}\n\n// ---- Main dispatch ----\n\nexport function createVectorRequestHandler(state: VectorState) {\n return (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n body: Record<string, unknown>,\n ): boolean => {\n const pinecone = handlePinecone(state, req, res, pathname, body);\n if (pinecone.handled) return true;\n\n const qdrant = handleQdrant(state, req, res, pathname, body);\n if (qdrant.handled) return true;\n\n const chroma = handleChromaDB(state, req, res, pathname, body);\n if (chroma.handled) return true;\n\n return false;\n };\n}\n"],"mappings":"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"}