@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.
- package/.claude-plugin/marketplace.json +17 -0
- package/.claude-plugin/plugin.json +12 -0
- package/LICENSE +21 -0
- package/README.md +82 -0
- package/dist/_virtual/_rolldown/runtime.cjs +29 -0
- package/dist/a2a-handler.cjs +203 -0
- package/dist/a2a-handler.cjs.map +1 -0
- package/dist/a2a-handler.js +199 -0
- package/dist/a2a-handler.js.map +1 -0
- package/dist/a2a-mock.cjs +292 -0
- package/dist/a2a-mock.cjs.map +1 -0
- package/dist/a2a-mock.d.cts +41 -0
- package/dist/a2a-mock.d.cts.map +1 -0
- package/dist/a2a-mock.d.ts +41 -0
- package/dist/a2a-mock.d.ts.map +1 -0
- package/dist/a2a-mock.js +290 -0
- package/dist/a2a-mock.js.map +1 -0
- package/dist/a2a-stub.cjs +4 -0
- package/dist/a2a-stub.d.cts +3 -0
- package/dist/a2a-stub.d.ts +3 -0
- package/dist/a2a-stub.js +3 -0
- package/dist/a2a-types.d.cts +68 -0
- package/dist/a2a-types.d.cts.map +1 -0
- package/dist/a2a-types.d.ts +68 -0
- package/dist/a2a-types.d.ts.map +1 -0
- package/dist/aimock-cli.cjs +112 -0
- package/dist/aimock-cli.cjs.map +1 -0
- package/dist/aimock-cli.d.cts +19 -0
- package/dist/aimock-cli.d.cts.map +1 -0
- package/dist/aimock-cli.d.ts +19 -0
- package/dist/aimock-cli.d.ts.map +1 -0
- package/dist/aimock-cli.js +110 -0
- package/dist/aimock-cli.js.map +1 -0
- package/dist/aws-event-stream.cjs +117 -0
- package/dist/aws-event-stream.cjs.map +1 -0
- package/dist/aws-event-stream.d.cts +38 -0
- package/dist/aws-event-stream.d.cts.map +1 -0
- package/dist/aws-event-stream.d.ts +38 -0
- package/dist/aws-event-stream.d.ts.map +1 -0
- package/dist/aws-event-stream.js +114 -0
- package/dist/aws-event-stream.js.map +1 -0
- package/dist/bedrock-converse.cjs +445 -0
- package/dist/bedrock-converse.cjs.map +1 -0
- package/dist/bedrock-converse.d.cts +50 -0
- package/dist/bedrock-converse.d.cts.map +1 -0
- package/dist/bedrock-converse.d.ts +50 -0
- package/dist/bedrock-converse.d.ts.map +1 -0
- package/dist/bedrock-converse.js +443 -0
- package/dist/bedrock-converse.js.map +1 -0
- package/dist/bedrock.cjs +557 -0
- package/dist/bedrock.cjs.map +1 -0
- package/dist/bedrock.d.cts +41 -0
- package/dist/bedrock.d.cts.map +1 -0
- package/dist/bedrock.d.ts +41 -0
- package/dist/bedrock.d.ts.map +1 -0
- package/dist/bedrock.js +553 -0
- package/dist/bedrock.js.map +1 -0
- package/dist/chaos.cjs +114 -0
- package/dist/chaos.cjs.map +1 -0
- package/dist/chaos.d.cts +27 -0
- package/dist/chaos.d.cts.map +1 -0
- package/dist/chaos.d.ts +27 -0
- package/dist/chaos.d.ts.map +1 -0
- package/dist/chaos.js +113 -0
- package/dist/chaos.js.map +1 -0
- package/dist/cli.cjs +268 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +268 -0
- package/dist/cli.js.map +1 -0
- package/dist/cohere.cjs +434 -0
- package/dist/cohere.cjs.map +1 -0
- package/dist/cohere.d.cts +34 -0
- package/dist/cohere.d.cts.map +1 -0
- package/dist/cohere.d.ts +34 -0
- package/dist/cohere.d.ts.map +1 -0
- package/dist/cohere.js +433 -0
- package/dist/cohere.js.map +1 -0
- package/dist/config-loader.cjs +111 -0
- package/dist/config-loader.cjs.map +1 -0
- package/dist/config-loader.d.cts +100 -0
- package/dist/config-loader.d.cts.map +1 -0
- package/dist/config-loader.d.ts +100 -0
- package/dist/config-loader.d.ts.map +1 -0
- package/dist/config-loader.js +107 -0
- package/dist/config-loader.js.map +1 -0
- package/dist/embeddings.cjs +150 -0
- package/dist/embeddings.cjs.map +1 -0
- package/dist/embeddings.d.cts +12 -0
- package/dist/embeddings.d.cts.map +1 -0
- package/dist/embeddings.d.ts +12 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +150 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/fixture-loader.cjs +269 -0
- package/dist/fixture-loader.cjs.map +1 -0
- package/dist/fixture-loader.d.cts +17 -0
- package/dist/fixture-loader.d.cts.map +1 -0
- package/dist/fixture-loader.d.ts +17 -0
- package/dist/fixture-loader.d.ts.map +1 -0
- package/dist/fixture-loader.js +265 -0
- package/dist/fixture-loader.js.map +1 -0
- package/dist/gemini.cjs +403 -0
- package/dist/gemini.cjs.map +1 -0
- package/dist/gemini.d.cts +10 -0
- package/dist/gemini.d.cts.map +1 -0
- package/dist/gemini.d.ts +10 -0
- package/dist/gemini.d.ts.map +1 -0
- package/dist/gemini.js +403 -0
- package/dist/gemini.js.map +1 -0
- package/dist/helpers.cjs +276 -0
- package/dist/helpers.cjs.map +1 -0
- package/dist/helpers.d.cts +39 -0
- package/dist/helpers.d.cts.map +1 -0
- package/dist/helpers.d.ts +39 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +259 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.cjs +113 -0
- package/dist/index.d.cts +42 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +39 -0
- package/dist/interruption.cjs +40 -0
- package/dist/interruption.cjs.map +1 -0
- package/dist/interruption.d.cts +15 -0
- package/dist/interruption.d.cts.map +1 -0
- package/dist/interruption.d.ts +15 -0
- package/dist/interruption.d.ts.map +1 -0
- package/dist/interruption.js +39 -0
- package/dist/interruption.js.map +1 -0
- package/dist/journal.cjs +65 -0
- package/dist/journal.cjs.map +1 -0
- package/dist/journal.d.cts +23 -0
- package/dist/journal.d.cts.map +1 -0
- package/dist/journal.d.ts +23 -0
- package/dist/journal.d.ts.map +1 -0
- package/dist/journal.js +65 -0
- package/dist/journal.js.map +1 -0
- package/dist/jsonrpc.cjs +91 -0
- package/dist/jsonrpc.cjs.map +1 -0
- package/dist/jsonrpc.d.cts +24 -0
- package/dist/jsonrpc.d.cts.map +1 -0
- package/dist/jsonrpc.d.ts +24 -0
- package/dist/jsonrpc.d.ts.map +1 -0
- package/dist/jsonrpc.js +90 -0
- package/dist/jsonrpc.js.map +1 -0
- package/dist/llmock.cjs +223 -0
- package/dist/llmock.cjs.map +1 -0
- package/dist/llmock.d.cts +70 -0
- package/dist/llmock.d.cts.map +1 -0
- package/dist/llmock.d.ts +70 -0
- package/dist/llmock.d.ts.map +1 -0
- package/dist/llmock.js +223 -0
- package/dist/llmock.js.map +1 -0
- package/dist/logger.cjs +29 -0
- package/dist/logger.cjs.map +1 -0
- package/dist/logger.d.cts +14 -0
- package/dist/logger.d.cts.map +1 -0
- package/dist/logger.d.ts +14 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +28 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp-handler.cjs +189 -0
- package/dist/mcp-handler.cjs.map +1 -0
- package/dist/mcp-handler.js +188 -0
- package/dist/mcp-handler.js.map +1 -0
- package/dist/mcp-mock.cjs +169 -0
- package/dist/mcp-mock.cjs.map +1 -0
- package/dist/mcp-mock.d.cts +40 -0
- package/dist/mcp-mock.d.cts.map +1 -0
- package/dist/mcp-mock.d.ts +40 -0
- package/dist/mcp-mock.d.ts.map +1 -0
- package/dist/mcp-mock.js +167 -0
- package/dist/mcp-mock.js.map +1 -0
- package/dist/mcp-stub.cjs +4 -0
- package/dist/mcp-stub.d.cts +3 -0
- package/dist/mcp-stub.d.ts +3 -0
- package/dist/mcp-stub.js +3 -0
- package/dist/mcp-types.d.cts +65 -0
- package/dist/mcp-types.d.cts.map +1 -0
- package/dist/mcp-types.d.ts +65 -0
- package/dist/mcp-types.d.ts.map +1 -0
- package/dist/messages.cjs +489 -0
- package/dist/messages.cjs.map +1 -0
- package/dist/messages.d.cts +10 -0
- package/dist/messages.d.cts.map +1 -0
- package/dist/messages.d.ts +10 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +489 -0
- package/dist/messages.js.map +1 -0
- package/dist/metrics.cjs +160 -0
- package/dist/metrics.cjs.map +1 -0
- package/dist/metrics.d.cts +24 -0
- package/dist/metrics.d.cts.map +1 -0
- package/dist/metrics.d.ts +24 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +158 -0
- package/dist/metrics.js.map +1 -0
- package/dist/moderation.cjs +91 -0
- package/dist/moderation.cjs.map +1 -0
- package/dist/moderation.d.cts +23 -0
- package/dist/moderation.d.cts.map +1 -0
- package/dist/moderation.d.ts +23 -0
- package/dist/moderation.d.ts.map +1 -0
- package/dist/moderation.js +91 -0
- package/dist/moderation.js.map +1 -0
- package/dist/ndjson-writer.cjs +31 -0
- package/dist/ndjson-writer.cjs.map +1 -0
- package/dist/ndjson-writer.d.cts +17 -0
- package/dist/ndjson-writer.d.cts.map +1 -0
- package/dist/ndjson-writer.d.ts +17 -0
- package/dist/ndjson-writer.d.ts.map +1 -0
- package/dist/ndjson-writer.js +31 -0
- package/dist/ndjson-writer.js.map +1 -0
- package/dist/ollama.cjs +519 -0
- package/dist/ollama.cjs.map +1 -0
- package/dist/ollama.d.cts +34 -0
- package/dist/ollama.d.cts.map +1 -0
- package/dist/ollama.d.ts +34 -0
- package/dist/ollama.d.ts.map +1 -0
- package/dist/ollama.js +517 -0
- package/dist/ollama.js.map +1 -0
- package/dist/recorder.cjs +311 -0
- package/dist/recorder.cjs.map +1 -0
- package/dist/recorder.d.cts +23 -0
- package/dist/recorder.d.cts.map +1 -0
- package/dist/recorder.d.ts +23 -0
- package/dist/recorder.d.ts.map +1 -0
- package/dist/recorder.js +305 -0
- package/dist/recorder.js.map +1 -0
- package/dist/rerank.cjs +71 -0
- package/dist/rerank.cjs.map +1 -0
- package/dist/rerank.d.cts +22 -0
- package/dist/rerank.d.cts.map +1 -0
- package/dist/rerank.d.ts +22 -0
- package/dist/rerank.d.ts.map +1 -0
- package/dist/rerank.js +71 -0
- package/dist/rerank.js.map +1 -0
- package/dist/responses.cjs +637 -0
- package/dist/responses.cjs.map +1 -0
- package/dist/responses.d.cts +16 -0
- package/dist/responses.d.cts.map +1 -0
- package/dist/responses.d.ts +16 -0
- package/dist/responses.d.ts.map +1 -0
- package/dist/responses.js +634 -0
- package/dist/responses.js.map +1 -0
- package/dist/router.cjs +68 -0
- package/dist/router.cjs.map +1 -0
- package/dist/router.d.cts +16 -0
- package/dist/router.d.cts.map +1 -0
- package/dist/router.d.ts +16 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +65 -0
- package/dist/router.js.map +1 -0
- package/dist/search.cjs +59 -0
- package/dist/search.cjs.map +1 -0
- package/dist/search.d.cts +23 -0
- package/dist/search.d.cts.map +1 -0
- package/dist/search.d.ts +23 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +59 -0
- package/dist/search.js.map +1 -0
- package/dist/server.cjs +935 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +28 -0
- package/dist/server.d.cts.map +1 -0
- package/dist/server.d.ts +28 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +933 -0
- package/dist/server.js.map +1 -0
- package/dist/sse-writer.cjs +59 -0
- package/dist/sse-writer.cjs.map +1 -0
- package/dist/sse-writer.d.cts +19 -0
- package/dist/sse-writer.d.cts.map +1 -0
- package/dist/sse-writer.d.ts +19 -0
- package/dist/sse-writer.d.ts.map +1 -0
- package/dist/sse-writer.js +55 -0
- package/dist/sse-writer.js.map +1 -0
- package/dist/stream-collapse.cjs +496 -0
- package/dist/stream-collapse.cjs.map +1 -0
- package/dist/stream-collapse.d.cts +70 -0
- package/dist/stream-collapse.d.cts.map +1 -0
- package/dist/stream-collapse.d.ts +70 -0
- package/dist/stream-collapse.d.ts.map +1 -0
- package/dist/stream-collapse.js +489 -0
- package/dist/stream-collapse.js.map +1 -0
- package/dist/suite.cjs +46 -0
- package/dist/suite.cjs.map +1 -0
- package/dist/suite.d.cts +31 -0
- package/dist/suite.d.cts.map +1 -0
- package/dist/suite.d.ts +31 -0
- package/dist/suite.d.ts.map +1 -0
- package/dist/suite.js +46 -0
- package/dist/suite.js.map +1 -0
- package/dist/types.d.cts +243 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.ts +243 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/url.cjs +21 -0
- package/dist/url.cjs.map +1 -0
- package/dist/url.d.cts +16 -0
- package/dist/url.d.cts.map +1 -0
- package/dist/url.d.ts +16 -0
- package/dist/url.d.ts.map +1 -0
- package/dist/url.js +20 -0
- package/dist/url.js.map +1 -0
- package/dist/vector-handler.cjs +239 -0
- package/dist/vector-handler.cjs.map +1 -0
- package/dist/vector-handler.js +238 -0
- package/dist/vector-handler.js.map +1 -0
- package/dist/vector-mock.cjs +229 -0
- package/dist/vector-mock.cjs.map +1 -0
- package/dist/vector-mock.d.cts +39 -0
- package/dist/vector-mock.d.cts.map +1 -0
- package/dist/vector-mock.d.ts +39 -0
- package/dist/vector-mock.d.ts.map +1 -0
- package/dist/vector-mock.js +227 -0
- package/dist/vector-mock.js.map +1 -0
- package/dist/vector-stub.cjs +4 -0
- package/dist/vector-stub.d.cts +3 -0
- package/dist/vector-stub.d.ts +3 -0
- package/dist/vector-stub.js +3 -0
- package/dist/vector-types.d.cts +32 -0
- package/dist/vector-types.d.cts.map +1 -0
- package/dist/vector-types.d.ts +32 -0
- package/dist/vector-types.d.ts.map +1 -0
- package/dist/watcher.cjs +59 -0
- package/dist/watcher.cjs.map +1 -0
- package/dist/watcher.js +58 -0
- package/dist/watcher.js.map +1 -0
- package/dist/ws-framing.cjs +187 -0
- package/dist/ws-framing.cjs.map +1 -0
- package/dist/ws-framing.d.cts +26 -0
- package/dist/ws-framing.d.cts.map +1 -0
- package/dist/ws-framing.d.ts +26 -0
- package/dist/ws-framing.d.ts.map +1 -0
- package/dist/ws-framing.js +184 -0
- package/dist/ws-framing.js.map +1 -0
- package/dist/ws-gemini-live.cjs +364 -0
- package/dist/ws-gemini-live.cjs.map +1 -0
- package/dist/ws-gemini-live.d.cts +18 -0
- package/dist/ws-gemini-live.d.cts.map +1 -0
- package/dist/ws-gemini-live.d.ts +18 -0
- package/dist/ws-gemini-live.d.ts.map +1 -0
- package/dist/ws-gemini-live.js +364 -0
- package/dist/ws-gemini-live.js.map +1 -0
- package/dist/ws-realtime.cjs +435 -0
- package/dist/ws-realtime.cjs.map +1 -0
- package/dist/ws-realtime.d.cts +17 -0
- package/dist/ws-realtime.d.cts.map +1 -0
- package/dist/ws-realtime.d.ts +17 -0
- package/dist/ws-realtime.d.ts.map +1 -0
- package/dist/ws-realtime.js +435 -0
- package/dist/ws-realtime.js.map +1 -0
- package/dist/ws-responses.cjs +164 -0
- package/dist/ws-responses.cjs.map +1 -0
- package/dist/ws-responses.d.cts +18 -0
- package/dist/ws-responses.d.cts.map +1 -0
- package/dist/ws-responses.d.ts +18 -0
- package/dist/ws-responses.d.ts.map +1 -0
- package/dist/ws-responses.js +164 -0
- package/dist/ws-responses.js.map +1 -0
- package/fixtures/example-greeting.json +12 -0
- package/fixtures/example-multi-turn.json +14 -0
- package/fixtures/example-tool-call.json +15 -0
- package/package.json +118 -0
- package/skills/write-fixtures/SKILL.md +625 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
const require_helpers = require('./helpers.cjs');
|
|
3
|
+
const require_vector_handler = require('./vector-handler.cjs');
|
|
4
|
+
let node_http = require("node:http");
|
|
5
|
+
node_http = require_runtime.__toESM(node_http);
|
|
6
|
+
|
|
7
|
+
//#region src/vector-mock.ts
|
|
8
|
+
var VectorMock = class {
|
|
9
|
+
collections = /* @__PURE__ */ new Map();
|
|
10
|
+
queryHandlers = /* @__PURE__ */ new Map();
|
|
11
|
+
server = null;
|
|
12
|
+
journal = null;
|
|
13
|
+
registry = null;
|
|
14
|
+
options;
|
|
15
|
+
requestHandler;
|
|
16
|
+
constructor(options) {
|
|
17
|
+
this.options = options ?? {};
|
|
18
|
+
this.requestHandler = this.buildHandler();
|
|
19
|
+
}
|
|
20
|
+
addCollection(name, opts) {
|
|
21
|
+
const collection = {
|
|
22
|
+
name,
|
|
23
|
+
dimension: opts.dimension,
|
|
24
|
+
vectors: /* @__PURE__ */ new Map()
|
|
25
|
+
};
|
|
26
|
+
this.collections.set(name, collection);
|
|
27
|
+
this.requestHandler = this.buildHandler();
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
upsert(collection, vectors) {
|
|
31
|
+
let col = this.collections.get(collection);
|
|
32
|
+
if (!col) {
|
|
33
|
+
col = {
|
|
34
|
+
name: collection,
|
|
35
|
+
dimension: vectors.length > 0 ? vectors[0].values.length : 0,
|
|
36
|
+
vectors: /* @__PURE__ */ new Map()
|
|
37
|
+
};
|
|
38
|
+
this.collections.set(collection, col);
|
|
39
|
+
}
|
|
40
|
+
for (const v of vectors) col.vectors.set(v.id, v);
|
|
41
|
+
this.requestHandler = this.buildHandler();
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
onQuery(collection, results) {
|
|
45
|
+
this.queryHandlers.set(collection, results);
|
|
46
|
+
this.requestHandler = this.buildHandler();
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
deleteCollection(name) {
|
|
50
|
+
this.collections.delete(name);
|
|
51
|
+
this.queryHandlers.delete(name);
|
|
52
|
+
this.requestHandler = this.buildHandler();
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
async handleRequest(req, res, pathname) {
|
|
56
|
+
const body = await require_helpers.readBody(req);
|
|
57
|
+
let parsed = {};
|
|
58
|
+
try {
|
|
59
|
+
if (body) parsed = JSON.parse(body);
|
|
60
|
+
} catch {
|
|
61
|
+
if (req.method !== "GET") {
|
|
62
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
63
|
+
res.end(JSON.stringify({ error: "Malformed JSON body" }));
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const handled = this.requestHandler(req, res, pathname, parsed);
|
|
68
|
+
if (handled && this.registry) {
|
|
69
|
+
const { operation, provider } = classifyVectorRequest(req.method ?? "GET", pathname);
|
|
70
|
+
this.registry.incrementCounter("aimock_vector_requests_total", {
|
|
71
|
+
operation,
|
|
72
|
+
provider
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (handled && this.journal) this.journal.add({
|
|
76
|
+
method: req.method ?? "GET",
|
|
77
|
+
path: req.url ?? "/",
|
|
78
|
+
headers: require_helpers.flattenHeaders(req.headers),
|
|
79
|
+
body: null,
|
|
80
|
+
service: "vector",
|
|
81
|
+
response: {
|
|
82
|
+
status: res.statusCode,
|
|
83
|
+
fixture: null
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return handled;
|
|
87
|
+
}
|
|
88
|
+
health() {
|
|
89
|
+
return {
|
|
90
|
+
status: "ok",
|
|
91
|
+
collections: this.collections.size
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
setJournal(journal) {
|
|
95
|
+
this.journal = journal;
|
|
96
|
+
}
|
|
97
|
+
setRegistry(registry) {
|
|
98
|
+
this.registry = registry;
|
|
99
|
+
}
|
|
100
|
+
async start() {
|
|
101
|
+
if (this.server) throw new Error("Server already started");
|
|
102
|
+
const host = this.options.host ?? "127.0.0.1";
|
|
103
|
+
const port = this.options.port ?? 0;
|
|
104
|
+
return new Promise((resolve, reject) => {
|
|
105
|
+
const srv = node_http.createServer((req, res) => {
|
|
106
|
+
const chunks = [];
|
|
107
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
108
|
+
req.on("end", () => {
|
|
109
|
+
const body = Buffer.concat(chunks).toString();
|
|
110
|
+
let parsed = {};
|
|
111
|
+
try {
|
|
112
|
+
if (body) parsed = JSON.parse(body);
|
|
113
|
+
} catch {
|
|
114
|
+
if (req.method !== "GET") {
|
|
115
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
116
|
+
res.end(JSON.stringify({ error: "Malformed JSON body" }));
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const url = new URL(req.url ?? "/", `http://${host}`);
|
|
121
|
+
const handled = this.requestHandler(req, res, url.pathname, parsed);
|
|
122
|
+
if (handled && this.journal) this.journal.add({
|
|
123
|
+
method: req.method ?? "GET",
|
|
124
|
+
path: req.url ?? "/",
|
|
125
|
+
headers: require_helpers.flattenHeaders(req.headers),
|
|
126
|
+
body: null,
|
|
127
|
+
service: "vector",
|
|
128
|
+
response: {
|
|
129
|
+
status: res.statusCode,
|
|
130
|
+
fixture: null
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
if (!handled) {
|
|
134
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
135
|
+
res.end(JSON.stringify({ error: "Not found" }));
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
srv.listen(port, host, () => {
|
|
140
|
+
this.server = srv;
|
|
141
|
+
const addr = srv.address();
|
|
142
|
+
if (typeof addr === "object" && addr !== null) resolve(`http://${host}:${addr.port}`);
|
|
143
|
+
else resolve(`http://${host}:${port}`);
|
|
144
|
+
});
|
|
145
|
+
srv.on("error", reject);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
async stop() {
|
|
149
|
+
if (!this.server) throw new Error("Server not started");
|
|
150
|
+
const srv = this.server;
|
|
151
|
+
this.server = null;
|
|
152
|
+
await new Promise((resolve, reject) => {
|
|
153
|
+
srv.close((err) => err ? reject(err) : resolve());
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
getRequests() {
|
|
157
|
+
if (!this.journal) return [];
|
|
158
|
+
return this.journal.getAll().filter((e) => e.service === "vector");
|
|
159
|
+
}
|
|
160
|
+
reset() {
|
|
161
|
+
this.collections.clear();
|
|
162
|
+
this.queryHandlers.clear();
|
|
163
|
+
this.requestHandler = this.buildHandler();
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
166
|
+
buildHandler() {
|
|
167
|
+
return require_vector_handler.createVectorRequestHandler({
|
|
168
|
+
collections: this.collections,
|
|
169
|
+
queryHandlers: this.queryHandlers
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* Classify a vector request by operation and provider based on HTTP method and pathname.
|
|
175
|
+
*/
|
|
176
|
+
function classifyVectorRequest(method, pathname) {
|
|
177
|
+
if (pathname === "/query" && method === "POST") return {
|
|
178
|
+
operation: "query",
|
|
179
|
+
provider: "pinecone"
|
|
180
|
+
};
|
|
181
|
+
if (pathname === "/vectors/upsert" && method === "POST") return {
|
|
182
|
+
operation: "upsert",
|
|
183
|
+
provider: "pinecone"
|
|
184
|
+
};
|
|
185
|
+
if (pathname === "/vectors/delete" && method === "POST") return {
|
|
186
|
+
operation: "delete",
|
|
187
|
+
provider: "pinecone"
|
|
188
|
+
};
|
|
189
|
+
if (pathname === "/describe-index-stats" && method === "GET") return {
|
|
190
|
+
operation: "describe",
|
|
191
|
+
provider: "pinecone"
|
|
192
|
+
};
|
|
193
|
+
if (/^\/collections\/[^/]+\/points\/search$/.test(pathname) && method === "POST") return {
|
|
194
|
+
operation: "query",
|
|
195
|
+
provider: "qdrant"
|
|
196
|
+
};
|
|
197
|
+
if (/^\/collections\/[^/]+\/points$/.test(pathname) && method === "PUT") return {
|
|
198
|
+
operation: "upsert",
|
|
199
|
+
provider: "qdrant"
|
|
200
|
+
};
|
|
201
|
+
if (/^\/collections\/[^/]+\/points\/delete$/.test(pathname) && method === "POST") return {
|
|
202
|
+
operation: "delete",
|
|
203
|
+
provider: "qdrant"
|
|
204
|
+
};
|
|
205
|
+
if (/^\/api\/v1\/collections\/[^/]+\/query$/.test(pathname) && method === "POST") return {
|
|
206
|
+
operation: "query",
|
|
207
|
+
provider: "chromadb"
|
|
208
|
+
};
|
|
209
|
+
if (/^\/api\/v1\/collections\/[^/]+\/add$/.test(pathname) && method === "POST") return {
|
|
210
|
+
operation: "upsert",
|
|
211
|
+
provider: "chromadb"
|
|
212
|
+
};
|
|
213
|
+
if (pathname === "/api/v1/collections" && method === "GET") return {
|
|
214
|
+
operation: "list",
|
|
215
|
+
provider: "chromadb"
|
|
216
|
+
};
|
|
217
|
+
if (/^\/api\/v1\/collections\/[^/]+$/.test(pathname) && method === "DELETE") return {
|
|
218
|
+
operation: "delete",
|
|
219
|
+
provider: "chromadb"
|
|
220
|
+
};
|
|
221
|
+
return {
|
|
222
|
+
operation: "unknown",
|
|
223
|
+
provider: "unknown"
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
//#endregion
|
|
228
|
+
exports.VectorMock = VectorMock;
|
|
229
|
+
//# sourceMappingURL=vector-mock.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector-mock.cjs","names":["readBody","flattenHeaders","http","createVectorRequestHandler"],"sources":["../src/vector-mock.ts"],"sourcesContent":["import * as http from \"node:http\";\nimport type { Mountable, JournalEntry } from \"./types.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { MetricsRegistry } from \"./metrics.js\";\nimport type {\n VectorMockOptions,\n VectorCollection,\n VectorEntry,\n QueryResult,\n VectorQuery,\n QueryHandler,\n} from \"./vector-types.js\";\nimport { createVectorRequestHandler, type VectorState } from \"./vector-handler.js\";\nimport { flattenHeaders, readBody } from \"./helpers.js\";\n\nexport class VectorMock implements Mountable {\n private collections: Map<string, VectorCollection> = new Map();\n private queryHandlers: Map<string, QueryHandler> = new Map();\n private server: http.Server | null = null;\n private journal: Journal | null = null;\n private registry: MetricsRegistry | null = null;\n private options: VectorMockOptions;\n private requestHandler: ReturnType<typeof createVectorRequestHandler>;\n\n constructor(options?: VectorMockOptions) {\n this.options = options ?? {};\n this.requestHandler = this.buildHandler();\n }\n\n // ---- Configuration ----\n\n addCollection(name: string, opts: { dimension: number }): this {\n const collection: VectorCollection = {\n name,\n dimension: opts.dimension,\n vectors: new Map(),\n };\n this.collections.set(name, collection);\n this.requestHandler = this.buildHandler();\n return this;\n }\n\n upsert(collection: string, vectors: VectorEntry[]): this {\n let col = this.collections.get(collection);\n if (!col) {\n const dim = vectors.length > 0 ? vectors[0].values.length : 0;\n col = { name: collection, dimension: dim, vectors: new Map() };\n this.collections.set(collection, col);\n }\n for (const v of vectors) {\n col.vectors.set(v.id, v);\n }\n this.requestHandler = this.buildHandler();\n return this;\n }\n\n onQuery(\n collection: string,\n results: QueryResult[] | ((query: VectorQuery) => QueryResult[]),\n ): this {\n this.queryHandlers.set(collection, results);\n this.requestHandler = this.buildHandler();\n return this;\n }\n\n deleteCollection(name: string): this {\n this.collections.delete(name);\n this.queryHandlers.delete(name);\n this.requestHandler = this.buildHandler();\n return this;\n }\n\n // ---- Mountable interface ----\n\n async handleRequest(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n ): Promise<boolean> {\n const body = await readBody(req);\n let parsed: Record<string, unknown> = {};\n try {\n if (body) parsed = JSON.parse(body);\n } catch {\n if (req.method !== \"GET\") {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Malformed JSON body\" }));\n return true;\n }\n }\n\n const handled = this.requestHandler(req, res, pathname, parsed);\n\n // Record vector operation metric\n if (handled && this.registry) {\n const { operation, provider } = classifyVectorRequest(req.method ?? \"GET\", pathname);\n this.registry.incrementCounter(\"aimock_vector_requests_total\", { operation, provider });\n }\n\n // Journal the request after the handler completes\n if (handled && this.journal) {\n this.journal.add({\n method: req.method ?? \"GET\",\n path: req.url ?? \"/\",\n headers: flattenHeaders(req.headers),\n body: null,\n service: \"vector\",\n response: { status: res.statusCode, fixture: null },\n });\n }\n\n return handled;\n }\n\n health(): { status: string; collections: number } {\n return {\n status: \"ok\",\n collections: this.collections.size,\n };\n }\n\n setJournal(journal: Journal): void {\n this.journal = journal;\n }\n\n setRegistry(registry: MetricsRegistry): void {\n this.registry = registry;\n }\n\n // ---- Standalone mode ----\n\n async start(): Promise<string> {\n if (this.server) {\n throw new Error(\"Server already started\");\n }\n\n const host = this.options.host ?? \"127.0.0.1\";\n const port = this.options.port ?? 0;\n\n return new Promise((resolve, reject) => {\n const srv = http.createServer((req, res) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n req.on(\"end\", () => {\n const body = Buffer.concat(chunks).toString();\n let parsed: Record<string, unknown> = {};\n try {\n if (body) parsed = JSON.parse(body);\n } catch {\n if (req.method !== \"GET\") {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Malformed JSON body\" }));\n return;\n }\n }\n\n const url = new URL(req.url ?? \"/\", `http://${host}`);\n\n const handled = this.requestHandler(req, res, url.pathname, parsed);\n\n if (handled && this.journal) {\n this.journal.add({\n method: req.method ?? \"GET\",\n path: req.url ?? \"/\",\n headers: flattenHeaders(req.headers),\n body: null,\n service: \"vector\",\n response: { status: res.statusCode, fixture: null },\n });\n }\n if (!handled) {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Not found\" }));\n }\n });\n });\n\n srv.listen(port, host, () => {\n this.server = srv;\n const addr = srv.address();\n if (typeof addr === \"object\" && addr !== null) {\n resolve(`http://${host}:${addr.port}`);\n } else {\n resolve(`http://${host}:${port}`);\n }\n });\n\n srv.on(\"error\", reject);\n });\n }\n\n async stop(): Promise<void> {\n if (!this.server) {\n throw new Error(\"Server not started\");\n }\n const srv = this.server;\n this.server = null;\n await new Promise<void>((resolve, reject) => {\n srv.close((err) => (err ? reject(err) : resolve()));\n });\n }\n\n // ---- Inspection ----\n\n getRequests(): JournalEntry[] {\n if (!this.journal) return [];\n return this.journal.getAll().filter((e) => e.service === \"vector\");\n }\n\n reset(): this {\n this.collections.clear();\n this.queryHandlers.clear();\n this.requestHandler = this.buildHandler();\n return this;\n }\n\n // ---- Internal ----\n\n private buildHandler() {\n const state: VectorState = {\n collections: this.collections,\n queryHandlers: this.queryHandlers,\n };\n return createVectorRequestHandler(state);\n }\n}\n\n// ---- Helpers ----\n\n/**\n * Classify a vector request by operation and provider based on HTTP method and pathname.\n */\nfunction classifyVectorRequest(\n method: string,\n pathname: string,\n): { operation: string; provider: string } {\n // Pinecone paths\n if (pathname === \"/query\" && method === \"POST\") {\n return { operation: \"query\", provider: \"pinecone\" };\n }\n if (pathname === \"/vectors/upsert\" && method === \"POST\") {\n return { operation: \"upsert\", provider: \"pinecone\" };\n }\n if (pathname === \"/vectors/delete\" && method === \"POST\") {\n return { operation: \"delete\", provider: \"pinecone\" };\n }\n if (pathname === \"/describe-index-stats\" && method === \"GET\") {\n return { operation: \"describe\", provider: \"pinecone\" };\n }\n\n // Qdrant paths\n if (/^\\/collections\\/[^/]+\\/points\\/search$/.test(pathname) && method === \"POST\") {\n return { operation: \"query\", provider: \"qdrant\" };\n }\n if (/^\\/collections\\/[^/]+\\/points$/.test(pathname) && method === \"PUT\") {\n return { operation: \"upsert\", provider: \"qdrant\" };\n }\n if (/^\\/collections\\/[^/]+\\/points\\/delete$/.test(pathname) && method === \"POST\") {\n return { operation: \"delete\", provider: \"qdrant\" };\n }\n\n // ChromaDB paths\n if (/^\\/api\\/v1\\/collections\\/[^/]+\\/query$/.test(pathname) && method === \"POST\") {\n return { operation: \"query\", provider: \"chromadb\" };\n }\n if (/^\\/api\\/v1\\/collections\\/[^/]+\\/add$/.test(pathname) && method === \"POST\") {\n return { operation: \"upsert\", provider: \"chromadb\" };\n }\n if (pathname === \"/api/v1/collections\" && method === \"GET\") {\n return { operation: \"list\", provider: \"chromadb\" };\n }\n if (/^\\/api\\/v1\\/collections\\/[^/]+$/.test(pathname) && method === \"DELETE\") {\n return { operation: \"delete\", provider: \"chromadb\" };\n }\n\n return { operation: \"unknown\", provider: \"unknown\" };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Journal } from "./journal.cjs";
|
|
2
|
+
import { MetricsRegistry } from "./metrics.cjs";
|
|
3
|
+
import { JournalEntry, Mountable } from "./types.cjs";
|
|
4
|
+
import { QueryResult, VectorEntry, VectorMockOptions, VectorQuery } from "./vector-types.cjs";
|
|
5
|
+
import * as http from "node:http";
|
|
6
|
+
|
|
7
|
+
//#region src/vector-mock.d.ts
|
|
8
|
+
declare class VectorMock implements Mountable {
|
|
9
|
+
private collections;
|
|
10
|
+
private queryHandlers;
|
|
11
|
+
private server;
|
|
12
|
+
private journal;
|
|
13
|
+
private registry;
|
|
14
|
+
private options;
|
|
15
|
+
private requestHandler;
|
|
16
|
+
constructor(options?: VectorMockOptions);
|
|
17
|
+
addCollection(name: string, opts: {
|
|
18
|
+
dimension: number;
|
|
19
|
+
}): this;
|
|
20
|
+
upsert(collection: string, vectors: VectorEntry[]): this;
|
|
21
|
+
onQuery(collection: string, results: QueryResult[] | ((query: VectorQuery) => QueryResult[])): this;
|
|
22
|
+
deleteCollection(name: string): this;
|
|
23
|
+
handleRequest(req: http.IncomingMessage, res: http.ServerResponse, pathname: string): Promise<boolean>;
|
|
24
|
+
health(): {
|
|
25
|
+
status: string;
|
|
26
|
+
collections: number;
|
|
27
|
+
};
|
|
28
|
+
setJournal(journal: Journal): void;
|
|
29
|
+
setRegistry(registry: MetricsRegistry): void;
|
|
30
|
+
start(): Promise<string>;
|
|
31
|
+
stop(): Promise<void>;
|
|
32
|
+
getRequests(): JournalEntry[];
|
|
33
|
+
reset(): this;
|
|
34
|
+
private buildHandler;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=vector-mock.d.ts.map
|
|
37
|
+
//#endregion
|
|
38
|
+
export { VectorMock };
|
|
39
|
+
//# sourceMappingURL=vector-mock.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector-mock.d.cts","names":[],"sources":["../src/vector-mock.ts"],"sourcesContent":[],"mappings":";;;;;;;cAea,UAAA,YAAsB;;EAAtB,QAAA,aAAW;EAAA,QAAA,MAAA;UASA,OAAA;UAkBc,QAAA;UAgBzB,OAAA;UAAyB,cAAA;aAAgB,CAAA,OAAA,CAAA,EAlC9B,iBAkC8B;eAiBxC,CAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA;IACL,SAAK,EAAA,MAAA;MAET,IAAA;QA2CiB,CAAA,UAAA,EAAA,MAAA,EAAA,OAAA,EA/EgB,WA+EhB,EAAA,CAAA,EAAA,IAAA;SAIE,CAAA,UAAA,EAAA,MAAA,EAAA,OAAA,EAnEX,WAmEW,EAAA,GAAA,CAAA,CAAA,KAAA,EAnEc,WAmEd,EAAA,GAnE8B,WAmE9B,EAAA,CAAA,CAAA,EAAA,IAAA;kBAMP,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,IAAA;eA4DD,CAAA,GAAA,EApHP,IAAA,CAAK,eAoHE,EAAA,GAAA,EAnHP,IAAA,CAAK,cAmHE,EAAA,QAAA,EAAA,MAAA,CAAA,EAjHX,OAiHW,CAAA,OAAA,CAAA;QAaC,CAAA,CAAA,EAAA;IA7LkB,MAAA,EAAA,MAAA;IAAS,WAAA,EAAA,MAAA;;sBA0GtB;wBAIE;WAMP;UA4DD;iBAaC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Journal } from "./journal.js";
|
|
2
|
+
import { MetricsRegistry } from "./metrics.js";
|
|
3
|
+
import { JournalEntry, Mountable } from "./types.js";
|
|
4
|
+
import { QueryResult, VectorEntry, VectorMockOptions, VectorQuery } from "./vector-types.js";
|
|
5
|
+
import * as http from "node:http";
|
|
6
|
+
|
|
7
|
+
//#region src/vector-mock.d.ts
|
|
8
|
+
declare class VectorMock implements Mountable {
|
|
9
|
+
private collections;
|
|
10
|
+
private queryHandlers;
|
|
11
|
+
private server;
|
|
12
|
+
private journal;
|
|
13
|
+
private registry;
|
|
14
|
+
private options;
|
|
15
|
+
private requestHandler;
|
|
16
|
+
constructor(options?: VectorMockOptions);
|
|
17
|
+
addCollection(name: string, opts: {
|
|
18
|
+
dimension: number;
|
|
19
|
+
}): this;
|
|
20
|
+
upsert(collection: string, vectors: VectorEntry[]): this;
|
|
21
|
+
onQuery(collection: string, results: QueryResult[] | ((query: VectorQuery) => QueryResult[])): this;
|
|
22
|
+
deleteCollection(name: string): this;
|
|
23
|
+
handleRequest(req: http.IncomingMessage, res: http.ServerResponse, pathname: string): Promise<boolean>;
|
|
24
|
+
health(): {
|
|
25
|
+
status: string;
|
|
26
|
+
collections: number;
|
|
27
|
+
};
|
|
28
|
+
setJournal(journal: Journal): void;
|
|
29
|
+
setRegistry(registry: MetricsRegistry): void;
|
|
30
|
+
start(): Promise<string>;
|
|
31
|
+
stop(): Promise<void>;
|
|
32
|
+
getRequests(): JournalEntry[];
|
|
33
|
+
reset(): this;
|
|
34
|
+
private buildHandler;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=vector-mock.d.ts.map
|
|
37
|
+
//#endregion
|
|
38
|
+
export { VectorMock };
|
|
39
|
+
//# sourceMappingURL=vector-mock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector-mock.d.ts","names":[],"sources":["../src/vector-mock.ts"],"sourcesContent":[],"mappings":";;;;;;;cAea,UAAA,YAAsB;;EAAtB,QAAA,aAAW;EAAA,QAAA,MAAA;UASA,OAAA;UAkBc,QAAA;UAgBzB,OAAA;UAAyB,cAAA;aAAgB,CAAA,OAAA,CAAA,EAlC9B,iBAkC8B;eAiBxC,CAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA;IACL,SAAK,EAAA,MAAA;MAET,IAAA;QA2CiB,CAAA,UAAA,EAAA,MAAA,EAAA,OAAA,EA/EgB,WA+EhB,EAAA,CAAA,EAAA,IAAA;SAIE,CAAA,UAAA,EAAA,MAAA,EAAA,OAAA,EAnEX,WAmEW,EAAA,GAAA,CAAA,CAAA,KAAA,EAnEc,WAmEd,EAAA,GAnE8B,WAmE9B,EAAA,CAAA,CAAA,EAAA,IAAA;kBAMP,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,IAAA;eA4DD,CAAA,GAAA,EApHP,IAAA,CAAK,eAoHE,EAAA,GAAA,EAnHP,IAAA,CAAK,cAmHE,EAAA,QAAA,EAAA,MAAA,CAAA,EAjHX,OAiHW,CAAA,OAAA,CAAA;QAaC,CAAA,CAAA,EAAA;IA7LkB,MAAA,EAAA,MAAA;IAAS,WAAA,EAAA,MAAA;;sBA0GtB;wBAIE;WAMP;UA4DD;iBAaC"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { flattenHeaders, readBody } from "./helpers.js";
|
|
2
|
+
import { createVectorRequestHandler } from "./vector-handler.js";
|
|
3
|
+
import * as http from "node:http";
|
|
4
|
+
|
|
5
|
+
//#region src/vector-mock.ts
|
|
6
|
+
var VectorMock = class {
|
|
7
|
+
collections = /* @__PURE__ */ new Map();
|
|
8
|
+
queryHandlers = /* @__PURE__ */ new Map();
|
|
9
|
+
server = null;
|
|
10
|
+
journal = null;
|
|
11
|
+
registry = null;
|
|
12
|
+
options;
|
|
13
|
+
requestHandler;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.options = options ?? {};
|
|
16
|
+
this.requestHandler = this.buildHandler();
|
|
17
|
+
}
|
|
18
|
+
addCollection(name, opts) {
|
|
19
|
+
const collection = {
|
|
20
|
+
name,
|
|
21
|
+
dimension: opts.dimension,
|
|
22
|
+
vectors: /* @__PURE__ */ new Map()
|
|
23
|
+
};
|
|
24
|
+
this.collections.set(name, collection);
|
|
25
|
+
this.requestHandler = this.buildHandler();
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
upsert(collection, vectors) {
|
|
29
|
+
let col = this.collections.get(collection);
|
|
30
|
+
if (!col) {
|
|
31
|
+
col = {
|
|
32
|
+
name: collection,
|
|
33
|
+
dimension: vectors.length > 0 ? vectors[0].values.length : 0,
|
|
34
|
+
vectors: /* @__PURE__ */ new Map()
|
|
35
|
+
};
|
|
36
|
+
this.collections.set(collection, col);
|
|
37
|
+
}
|
|
38
|
+
for (const v of vectors) col.vectors.set(v.id, v);
|
|
39
|
+
this.requestHandler = this.buildHandler();
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
onQuery(collection, results) {
|
|
43
|
+
this.queryHandlers.set(collection, results);
|
|
44
|
+
this.requestHandler = this.buildHandler();
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
47
|
+
deleteCollection(name) {
|
|
48
|
+
this.collections.delete(name);
|
|
49
|
+
this.queryHandlers.delete(name);
|
|
50
|
+
this.requestHandler = this.buildHandler();
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
async handleRequest(req, res, pathname) {
|
|
54
|
+
const body = await readBody(req);
|
|
55
|
+
let parsed = {};
|
|
56
|
+
try {
|
|
57
|
+
if (body) parsed = JSON.parse(body);
|
|
58
|
+
} catch {
|
|
59
|
+
if (req.method !== "GET") {
|
|
60
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
61
|
+
res.end(JSON.stringify({ error: "Malformed JSON body" }));
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const handled = this.requestHandler(req, res, pathname, parsed);
|
|
66
|
+
if (handled && this.registry) {
|
|
67
|
+
const { operation, provider } = classifyVectorRequest(req.method ?? "GET", pathname);
|
|
68
|
+
this.registry.incrementCounter("aimock_vector_requests_total", {
|
|
69
|
+
operation,
|
|
70
|
+
provider
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (handled && this.journal) this.journal.add({
|
|
74
|
+
method: req.method ?? "GET",
|
|
75
|
+
path: req.url ?? "/",
|
|
76
|
+
headers: flattenHeaders(req.headers),
|
|
77
|
+
body: null,
|
|
78
|
+
service: "vector",
|
|
79
|
+
response: {
|
|
80
|
+
status: res.statusCode,
|
|
81
|
+
fixture: null
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return handled;
|
|
85
|
+
}
|
|
86
|
+
health() {
|
|
87
|
+
return {
|
|
88
|
+
status: "ok",
|
|
89
|
+
collections: this.collections.size
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
setJournal(journal) {
|
|
93
|
+
this.journal = journal;
|
|
94
|
+
}
|
|
95
|
+
setRegistry(registry) {
|
|
96
|
+
this.registry = registry;
|
|
97
|
+
}
|
|
98
|
+
async start() {
|
|
99
|
+
if (this.server) throw new Error("Server already started");
|
|
100
|
+
const host = this.options.host ?? "127.0.0.1";
|
|
101
|
+
const port = this.options.port ?? 0;
|
|
102
|
+
return new Promise((resolve, reject) => {
|
|
103
|
+
const srv = http.createServer((req, res) => {
|
|
104
|
+
const chunks = [];
|
|
105
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
106
|
+
req.on("end", () => {
|
|
107
|
+
const body = Buffer.concat(chunks).toString();
|
|
108
|
+
let parsed = {};
|
|
109
|
+
try {
|
|
110
|
+
if (body) parsed = JSON.parse(body);
|
|
111
|
+
} catch {
|
|
112
|
+
if (req.method !== "GET") {
|
|
113
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
114
|
+
res.end(JSON.stringify({ error: "Malformed JSON body" }));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const url = new URL(req.url ?? "/", `http://${host}`);
|
|
119
|
+
const handled = this.requestHandler(req, res, url.pathname, parsed);
|
|
120
|
+
if (handled && this.journal) this.journal.add({
|
|
121
|
+
method: req.method ?? "GET",
|
|
122
|
+
path: req.url ?? "/",
|
|
123
|
+
headers: flattenHeaders(req.headers),
|
|
124
|
+
body: null,
|
|
125
|
+
service: "vector",
|
|
126
|
+
response: {
|
|
127
|
+
status: res.statusCode,
|
|
128
|
+
fixture: null
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
if (!handled) {
|
|
132
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
133
|
+
res.end(JSON.stringify({ error: "Not found" }));
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
srv.listen(port, host, () => {
|
|
138
|
+
this.server = srv;
|
|
139
|
+
const addr = srv.address();
|
|
140
|
+
if (typeof addr === "object" && addr !== null) resolve(`http://${host}:${addr.port}`);
|
|
141
|
+
else resolve(`http://${host}:${port}`);
|
|
142
|
+
});
|
|
143
|
+
srv.on("error", reject);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
async stop() {
|
|
147
|
+
if (!this.server) throw new Error("Server not started");
|
|
148
|
+
const srv = this.server;
|
|
149
|
+
this.server = null;
|
|
150
|
+
await new Promise((resolve, reject) => {
|
|
151
|
+
srv.close((err) => err ? reject(err) : resolve());
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
getRequests() {
|
|
155
|
+
if (!this.journal) return [];
|
|
156
|
+
return this.journal.getAll().filter((e) => e.service === "vector");
|
|
157
|
+
}
|
|
158
|
+
reset() {
|
|
159
|
+
this.collections.clear();
|
|
160
|
+
this.queryHandlers.clear();
|
|
161
|
+
this.requestHandler = this.buildHandler();
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
buildHandler() {
|
|
165
|
+
return createVectorRequestHandler({
|
|
166
|
+
collections: this.collections,
|
|
167
|
+
queryHandlers: this.queryHandlers
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Classify a vector request by operation and provider based on HTTP method and pathname.
|
|
173
|
+
*/
|
|
174
|
+
function classifyVectorRequest(method, pathname) {
|
|
175
|
+
if (pathname === "/query" && method === "POST") return {
|
|
176
|
+
operation: "query",
|
|
177
|
+
provider: "pinecone"
|
|
178
|
+
};
|
|
179
|
+
if (pathname === "/vectors/upsert" && method === "POST") return {
|
|
180
|
+
operation: "upsert",
|
|
181
|
+
provider: "pinecone"
|
|
182
|
+
};
|
|
183
|
+
if (pathname === "/vectors/delete" && method === "POST") return {
|
|
184
|
+
operation: "delete",
|
|
185
|
+
provider: "pinecone"
|
|
186
|
+
};
|
|
187
|
+
if (pathname === "/describe-index-stats" && method === "GET") return {
|
|
188
|
+
operation: "describe",
|
|
189
|
+
provider: "pinecone"
|
|
190
|
+
};
|
|
191
|
+
if (/^\/collections\/[^/]+\/points\/search$/.test(pathname) && method === "POST") return {
|
|
192
|
+
operation: "query",
|
|
193
|
+
provider: "qdrant"
|
|
194
|
+
};
|
|
195
|
+
if (/^\/collections\/[^/]+\/points$/.test(pathname) && method === "PUT") return {
|
|
196
|
+
operation: "upsert",
|
|
197
|
+
provider: "qdrant"
|
|
198
|
+
};
|
|
199
|
+
if (/^\/collections\/[^/]+\/points\/delete$/.test(pathname) && method === "POST") return {
|
|
200
|
+
operation: "delete",
|
|
201
|
+
provider: "qdrant"
|
|
202
|
+
};
|
|
203
|
+
if (/^\/api\/v1\/collections\/[^/]+\/query$/.test(pathname) && method === "POST") return {
|
|
204
|
+
operation: "query",
|
|
205
|
+
provider: "chromadb"
|
|
206
|
+
};
|
|
207
|
+
if (/^\/api\/v1\/collections\/[^/]+\/add$/.test(pathname) && method === "POST") return {
|
|
208
|
+
operation: "upsert",
|
|
209
|
+
provider: "chromadb"
|
|
210
|
+
};
|
|
211
|
+
if (pathname === "/api/v1/collections" && method === "GET") return {
|
|
212
|
+
operation: "list",
|
|
213
|
+
provider: "chromadb"
|
|
214
|
+
};
|
|
215
|
+
if (/^\/api\/v1\/collections\/[^/]+$/.test(pathname) && method === "DELETE") return {
|
|
216
|
+
operation: "delete",
|
|
217
|
+
provider: "chromadb"
|
|
218
|
+
};
|
|
219
|
+
return {
|
|
220
|
+
operation: "unknown",
|
|
221
|
+
provider: "unknown"
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
//#endregion
|
|
226
|
+
export { VectorMock };
|
|
227
|
+
//# sourceMappingURL=vector-mock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector-mock.js","names":[],"sources":["../src/vector-mock.ts"],"sourcesContent":["import * as http from \"node:http\";\nimport type { Mountable, JournalEntry } from \"./types.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { MetricsRegistry } from \"./metrics.js\";\nimport type {\n VectorMockOptions,\n VectorCollection,\n VectorEntry,\n QueryResult,\n VectorQuery,\n QueryHandler,\n} from \"./vector-types.js\";\nimport { createVectorRequestHandler, type VectorState } from \"./vector-handler.js\";\nimport { flattenHeaders, readBody } from \"./helpers.js\";\n\nexport class VectorMock implements Mountable {\n private collections: Map<string, VectorCollection> = new Map();\n private queryHandlers: Map<string, QueryHandler> = new Map();\n private server: http.Server | null = null;\n private journal: Journal | null = null;\n private registry: MetricsRegistry | null = null;\n private options: VectorMockOptions;\n private requestHandler: ReturnType<typeof createVectorRequestHandler>;\n\n constructor(options?: VectorMockOptions) {\n this.options = options ?? {};\n this.requestHandler = this.buildHandler();\n }\n\n // ---- Configuration ----\n\n addCollection(name: string, opts: { dimension: number }): this {\n const collection: VectorCollection = {\n name,\n dimension: opts.dimension,\n vectors: new Map(),\n };\n this.collections.set(name, collection);\n this.requestHandler = this.buildHandler();\n return this;\n }\n\n upsert(collection: string, vectors: VectorEntry[]): this {\n let col = this.collections.get(collection);\n if (!col) {\n const dim = vectors.length > 0 ? vectors[0].values.length : 0;\n col = { name: collection, dimension: dim, vectors: new Map() };\n this.collections.set(collection, col);\n }\n for (const v of vectors) {\n col.vectors.set(v.id, v);\n }\n this.requestHandler = this.buildHandler();\n return this;\n }\n\n onQuery(\n collection: string,\n results: QueryResult[] | ((query: VectorQuery) => QueryResult[]),\n ): this {\n this.queryHandlers.set(collection, results);\n this.requestHandler = this.buildHandler();\n return this;\n }\n\n deleteCollection(name: string): this {\n this.collections.delete(name);\n this.queryHandlers.delete(name);\n this.requestHandler = this.buildHandler();\n return this;\n }\n\n // ---- Mountable interface ----\n\n async handleRequest(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n ): Promise<boolean> {\n const body = await readBody(req);\n let parsed: Record<string, unknown> = {};\n try {\n if (body) parsed = JSON.parse(body);\n } catch {\n if (req.method !== \"GET\") {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Malformed JSON body\" }));\n return true;\n }\n }\n\n const handled = this.requestHandler(req, res, pathname, parsed);\n\n // Record vector operation metric\n if (handled && this.registry) {\n const { operation, provider } = classifyVectorRequest(req.method ?? \"GET\", pathname);\n this.registry.incrementCounter(\"aimock_vector_requests_total\", { operation, provider });\n }\n\n // Journal the request after the handler completes\n if (handled && this.journal) {\n this.journal.add({\n method: req.method ?? \"GET\",\n path: req.url ?? \"/\",\n headers: flattenHeaders(req.headers),\n body: null,\n service: \"vector\",\n response: { status: res.statusCode, fixture: null },\n });\n }\n\n return handled;\n }\n\n health(): { status: string; collections: number } {\n return {\n status: \"ok\",\n collections: this.collections.size,\n };\n }\n\n setJournal(journal: Journal): void {\n this.journal = journal;\n }\n\n setRegistry(registry: MetricsRegistry): void {\n this.registry = registry;\n }\n\n // ---- Standalone mode ----\n\n async start(): Promise<string> {\n if (this.server) {\n throw new Error(\"Server already started\");\n }\n\n const host = this.options.host ?? \"127.0.0.1\";\n const port = this.options.port ?? 0;\n\n return new Promise((resolve, reject) => {\n const srv = http.createServer((req, res) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n req.on(\"end\", () => {\n const body = Buffer.concat(chunks).toString();\n let parsed: Record<string, unknown> = {};\n try {\n if (body) parsed = JSON.parse(body);\n } catch {\n if (req.method !== \"GET\") {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Malformed JSON body\" }));\n return;\n }\n }\n\n const url = new URL(req.url ?? \"/\", `http://${host}`);\n\n const handled = this.requestHandler(req, res, url.pathname, parsed);\n\n if (handled && this.journal) {\n this.journal.add({\n method: req.method ?? \"GET\",\n path: req.url ?? \"/\",\n headers: flattenHeaders(req.headers),\n body: null,\n service: \"vector\",\n response: { status: res.statusCode, fixture: null },\n });\n }\n if (!handled) {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Not found\" }));\n }\n });\n });\n\n srv.listen(port, host, () => {\n this.server = srv;\n const addr = srv.address();\n if (typeof addr === \"object\" && addr !== null) {\n resolve(`http://${host}:${addr.port}`);\n } else {\n resolve(`http://${host}:${port}`);\n }\n });\n\n srv.on(\"error\", reject);\n });\n }\n\n async stop(): Promise<void> {\n if (!this.server) {\n throw new Error(\"Server not started\");\n }\n const srv = this.server;\n this.server = null;\n await new Promise<void>((resolve, reject) => {\n srv.close((err) => (err ? reject(err) : resolve()));\n });\n }\n\n // ---- Inspection ----\n\n getRequests(): JournalEntry[] {\n if (!this.journal) return [];\n return this.journal.getAll().filter((e) => e.service === \"vector\");\n }\n\n reset(): this {\n this.collections.clear();\n this.queryHandlers.clear();\n this.requestHandler = this.buildHandler();\n return this;\n }\n\n // ---- Internal ----\n\n private buildHandler() {\n const state: VectorState = {\n collections: this.collections,\n queryHandlers: this.queryHandlers,\n };\n return createVectorRequestHandler(state);\n }\n}\n\n// ---- Helpers ----\n\n/**\n * Classify a vector request by operation and provider based on HTTP method and pathname.\n */\nfunction classifyVectorRequest(\n method: string,\n pathname: string,\n): { operation: string; provider: string } {\n // Pinecone paths\n if (pathname === \"/query\" && method === \"POST\") {\n return { operation: \"query\", provider: \"pinecone\" };\n }\n if (pathname === \"/vectors/upsert\" && method === \"POST\") {\n return { operation: \"upsert\", provider: \"pinecone\" };\n }\n if (pathname === \"/vectors/delete\" && method === \"POST\") {\n return { operation: \"delete\", provider: \"pinecone\" };\n }\n if (pathname === \"/describe-index-stats\" && method === \"GET\") {\n return { operation: \"describe\", provider: \"pinecone\" };\n }\n\n // Qdrant paths\n if (/^\\/collections\\/[^/]+\\/points\\/search$/.test(pathname) && method === \"POST\") {\n return { operation: \"query\", provider: \"qdrant\" };\n }\n if (/^\\/collections\\/[^/]+\\/points$/.test(pathname) && method === \"PUT\") {\n return { operation: \"upsert\", provider: \"qdrant\" };\n }\n if (/^\\/collections\\/[^/]+\\/points\\/delete$/.test(pathname) && method === \"POST\") {\n return { operation: \"delete\", provider: \"qdrant\" };\n }\n\n // ChromaDB paths\n if (/^\\/api\\/v1\\/collections\\/[^/]+\\/query$/.test(pathname) && method === \"POST\") {\n return { operation: \"query\", provider: \"chromadb\" };\n }\n if (/^\\/api\\/v1\\/collections\\/[^/]+\\/add$/.test(pathname) && method === \"POST\") {\n return { operation: \"upsert\", provider: \"chromadb\" };\n }\n if (pathname === \"/api/v1/collections\" && method === \"GET\") {\n return { operation: \"list\", provider: \"chromadb\" };\n }\n if (/^\\/api\\/v1\\/collections\\/[^/]+$/.test(pathname) && method === \"DELETE\") {\n return { operation: \"delete\", provider: \"chromadb\" };\n }\n\n return { operation: \"unknown\", provider: \"unknown\" };\n}\n"],"mappings":";;;;;AAeA,IAAa,aAAb,MAA6C;CAC3C,AAAQ,8BAA6C,IAAI,KAAK;CAC9D,AAAQ,gCAA2C,IAAI,KAAK;CAC5D,AAAQ,SAA6B;CACrC,AAAQ,UAA0B;CAClC,AAAQ,WAAmC;CAC3C,AAAQ;CACR,AAAQ;CAER,YAAY,SAA6B;AACvC,OAAK,UAAU,WAAW,EAAE;AAC5B,OAAK,iBAAiB,KAAK,cAAc;;CAK3C,cAAc,MAAc,MAAmC;EAC7D,MAAM,aAA+B;GACnC;GACA,WAAW,KAAK;GAChB,yBAAS,IAAI,KAAK;GACnB;AACD,OAAK,YAAY,IAAI,MAAM,WAAW;AACtC,OAAK,iBAAiB,KAAK,cAAc;AACzC,SAAO;;CAGT,OAAO,YAAoB,SAA8B;EACvD,IAAI,MAAM,KAAK,YAAY,IAAI,WAAW;AAC1C,MAAI,CAAC,KAAK;AAER,SAAM;IAAE,MAAM;IAAY,WADd,QAAQ,SAAS,IAAI,QAAQ,GAAG,OAAO,SAAS;IAClB,yBAAS,IAAI,KAAK;IAAE;AAC9D,QAAK,YAAY,IAAI,YAAY,IAAI;;AAEvC,OAAK,MAAM,KAAK,QACd,KAAI,QAAQ,IAAI,EAAE,IAAI,EAAE;AAE1B,OAAK,iBAAiB,KAAK,cAAc;AACzC,SAAO;;CAGT,QACE,YACA,SACM;AACN,OAAK,cAAc,IAAI,YAAY,QAAQ;AAC3C,OAAK,iBAAiB,KAAK,cAAc;AACzC,SAAO;;CAGT,iBAAiB,MAAoB;AACnC,OAAK,YAAY,OAAO,KAAK;AAC7B,OAAK,cAAc,OAAO,KAAK;AAC/B,OAAK,iBAAiB,KAAK,cAAc;AACzC,SAAO;;CAKT,MAAM,cACJ,KACA,KACA,UACkB;EAClB,MAAM,OAAO,MAAM,SAAS,IAAI;EAChC,IAAI,SAAkC,EAAE;AACxC,MAAI;AACF,OAAI,KAAM,UAAS,KAAK,MAAM,KAAK;UAC7B;AACN,OAAI,IAAI,WAAW,OAAO;AACxB,QAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,uBAAuB,CAAC,CAAC;AACzD,WAAO;;;EAIX,MAAM,UAAU,KAAK,eAAe,KAAK,KAAK,UAAU,OAAO;AAG/D,MAAI,WAAW,KAAK,UAAU;GAC5B,MAAM,EAAE,WAAW,aAAa,sBAAsB,IAAI,UAAU,OAAO,SAAS;AACpF,QAAK,SAAS,iBAAiB,gCAAgC;IAAE;IAAW;IAAU,CAAC;;AAIzF,MAAI,WAAW,KAAK,QAClB,MAAK,QAAQ,IAAI;GACf,QAAQ,IAAI,UAAU;GACtB,MAAM,IAAI,OAAO;GACjB,SAAS,eAAe,IAAI,QAAQ;GACpC,MAAM;GACN,SAAS;GACT,UAAU;IAAE,QAAQ,IAAI;IAAY,SAAS;IAAM;GACpD,CAAC;AAGJ,SAAO;;CAGT,SAAkD;AAChD,SAAO;GACL,QAAQ;GACR,aAAa,KAAK,YAAY;GAC/B;;CAGH,WAAW,SAAwB;AACjC,OAAK,UAAU;;CAGjB,YAAY,UAAiC;AAC3C,OAAK,WAAW;;CAKlB,MAAM,QAAyB;AAC7B,MAAI,KAAK,OACP,OAAM,IAAI,MAAM,yBAAyB;EAG3C,MAAM,OAAO,KAAK,QAAQ,QAAQ;EAClC,MAAM,OAAO,KAAK,QAAQ,QAAQ;AAElC,SAAO,IAAI,SAAS,SAAS,WAAW;GACtC,MAAM,MAAM,KAAK,cAAc,KAAK,QAAQ;IAC1C,MAAM,SAAmB,EAAE;AAC3B,QAAI,GAAG,SAAS,UAAkB,OAAO,KAAK,MAAM,CAAC;AACrD,QAAI,GAAG,aAAa;KAClB,MAAM,OAAO,OAAO,OAAO,OAAO,CAAC,UAAU;KAC7C,IAAI,SAAkC,EAAE;AACxC,SAAI;AACF,UAAI,KAAM,UAAS,KAAK,MAAM,KAAK;aAC7B;AACN,UAAI,IAAI,WAAW,OAAO;AACxB,WAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,WAAI,IAAI,KAAK,UAAU,EAAE,OAAO,uBAAuB,CAAC,CAAC;AACzD;;;KAIJ,MAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,UAAU,OAAO;KAErD,MAAM,UAAU,KAAK,eAAe,KAAK,KAAK,IAAI,UAAU,OAAO;AAEnE,SAAI,WAAW,KAAK,QAClB,MAAK,QAAQ,IAAI;MACf,QAAQ,IAAI,UAAU;MACtB,MAAM,IAAI,OAAO;MACjB,SAAS,eAAe,IAAI,QAAQ;MACpC,MAAM;MACN,SAAS;MACT,UAAU;OAAE,QAAQ,IAAI;OAAY,SAAS;OAAM;MACpD,CAAC;AAEJ,SAAI,CAAC,SAAS;AACZ,UAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,UAAI,IAAI,KAAK,UAAU,EAAE,OAAO,aAAa,CAAC,CAAC;;MAEjD;KACF;AAEF,OAAI,OAAO,MAAM,YAAY;AAC3B,SAAK,SAAS;IACd,MAAM,OAAO,IAAI,SAAS;AAC1B,QAAI,OAAO,SAAS,YAAY,SAAS,KACvC,SAAQ,UAAU,KAAK,GAAG,KAAK,OAAO;QAEtC,SAAQ,UAAU,KAAK,GAAG,OAAO;KAEnC;AAEF,OAAI,GAAG,SAAS,OAAO;IACvB;;CAGJ,MAAM,OAAsB;AAC1B,MAAI,CAAC,KAAK,OACR,OAAM,IAAI,MAAM,qBAAqB;EAEvC,MAAM,MAAM,KAAK;AACjB,OAAK,SAAS;AACd,QAAM,IAAI,SAAe,SAAS,WAAW;AAC3C,OAAI,OAAO,QAAS,MAAM,OAAO,IAAI,GAAG,SAAS,CAAE;IACnD;;CAKJ,cAA8B;AAC5B,MAAI,CAAC,KAAK,QAAS,QAAO,EAAE;AAC5B,SAAO,KAAK,QAAQ,QAAQ,CAAC,QAAQ,MAAM,EAAE,YAAY,SAAS;;CAGpE,QAAc;AACZ,OAAK,YAAY,OAAO;AACxB,OAAK,cAAc,OAAO;AAC1B,OAAK,iBAAiB,KAAK,cAAc;AACzC,SAAO;;CAKT,AAAQ,eAAe;AAKrB,SAAO,2BAJoB;GACzB,aAAa,KAAK;GAClB,eAAe,KAAK;GACrB,CACuC;;;;;;AAS5C,SAAS,sBACP,QACA,UACyC;AAEzC,KAAI,aAAa,YAAY,WAAW,OACtC,QAAO;EAAE,WAAW;EAAS,UAAU;EAAY;AAErD,KAAI,aAAa,qBAAqB,WAAW,OAC/C,QAAO;EAAE,WAAW;EAAU,UAAU;EAAY;AAEtD,KAAI,aAAa,qBAAqB,WAAW,OAC/C,QAAO;EAAE,WAAW;EAAU,UAAU;EAAY;AAEtD,KAAI,aAAa,2BAA2B,WAAW,MACrD,QAAO;EAAE,WAAW;EAAY,UAAU;EAAY;AAIxD,KAAI,yCAAyC,KAAK,SAAS,IAAI,WAAW,OACxE,QAAO;EAAE,WAAW;EAAS,UAAU;EAAU;AAEnD,KAAI,iCAAiC,KAAK,SAAS,IAAI,WAAW,MAChE,QAAO;EAAE,WAAW;EAAU,UAAU;EAAU;AAEpD,KAAI,yCAAyC,KAAK,SAAS,IAAI,WAAW,OACxE,QAAO;EAAE,WAAW;EAAU,UAAU;EAAU;AAIpD,KAAI,yCAAyC,KAAK,SAAS,IAAI,WAAW,OACxE,QAAO;EAAE,WAAW;EAAS,UAAU;EAAY;AAErD,KAAI,uCAAuC,KAAK,SAAS,IAAI,WAAW,OACtE,QAAO;EAAE,WAAW;EAAU,UAAU;EAAY;AAEtD,KAAI,aAAa,yBAAyB,WAAW,MACnD,QAAO;EAAE,WAAW;EAAQ,UAAU;EAAY;AAEpD,KAAI,kCAAkC,KAAK,SAAS,IAAI,WAAW,SACjE,QAAO;EAAE,WAAW;EAAU,UAAU;EAAY;AAGtD,QAAO;EAAE,WAAW;EAAW,UAAU;EAAW"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { QueryHandler, QueryResult, VectorCollection, VectorEntry, VectorMockOptions, VectorQuery } from "./vector-types.cjs";
|
|
2
|
+
import { VectorMock } from "./vector-mock.cjs";
|
|
3
|
+
export { type QueryHandler, type QueryResult, type VectorCollection, type VectorEntry, VectorMock, type VectorMockOptions, type VectorQuery };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { QueryHandler, QueryResult, VectorCollection, VectorEntry, VectorMockOptions, VectorQuery } from "./vector-types.js";
|
|
2
|
+
import { VectorMock } from "./vector-mock.js";
|
|
3
|
+
export { type QueryHandler, type QueryResult, type VectorCollection, type VectorEntry, VectorMock, type VectorMockOptions, type VectorQuery };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/vector-types.d.ts
|
|
2
|
+
interface VectorMockOptions {
|
|
3
|
+
port?: number;
|
|
4
|
+
host?: string;
|
|
5
|
+
}
|
|
6
|
+
interface VectorCollection {
|
|
7
|
+
name: string;
|
|
8
|
+
dimension: number;
|
|
9
|
+
vectors: Map<string, VectorEntry>;
|
|
10
|
+
}
|
|
11
|
+
interface VectorEntry {
|
|
12
|
+
id: string;
|
|
13
|
+
values: number[];
|
|
14
|
+
metadata?: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
interface QueryResult {
|
|
17
|
+
id: string;
|
|
18
|
+
score: number;
|
|
19
|
+
metadata?: Record<string, unknown>;
|
|
20
|
+
values?: number[];
|
|
21
|
+
}
|
|
22
|
+
interface VectorQuery {
|
|
23
|
+
vector?: number[];
|
|
24
|
+
topK?: number;
|
|
25
|
+
filter?: unknown;
|
|
26
|
+
collection: string;
|
|
27
|
+
}
|
|
28
|
+
type QueryHandler = QueryResult[] | ((query: VectorQuery) => QueryResult[]);
|
|
29
|
+
//# sourceMappingURL=vector-types.d.ts.map
|
|
30
|
+
//#endregion
|
|
31
|
+
export { QueryHandler, QueryResult, VectorCollection, VectorEntry, VectorMockOptions, VectorQuery };
|
|
32
|
+
//# sourceMappingURL=vector-types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector-types.d.cts","names":[],"sources":["../src/vector-types.ts"],"sourcesContent":[],"mappings":";UAAiB,iBAAA;EAAA,IAAA,CAAA,EAAA,MAAA;EAKA,IAAA,CAAA,EAAA,MAAA;;AAGM,UAHN,gBAAA,CAGM;MAAZ,EAAA,MAAA;EAAG,SAAA,EAAA,MAAA;EAGG,OAAA,EAHN,GAGM,CAAA,MAAW,EAHL,WAMJ,CAAA;AAGnB;AAOiB,UAbA,WAAA,CAaW;EAOhB,EAAA,EAAA,MAAA;EAAY,MAAA,EAAA,MAAA,EAAA;UAAG,CAAA,EAjBd,MAiBc,CAAA,MAAA,EAAA,OAAA,CAAA;;AAAyC,UAdnD,WAAA,CAcmD;EAAW,EAAA,EAAA,MAAA;;aAXlE;;;UAII,WAAA;;;;;;KAOL,YAAA,GAAe,yBAAyB,gBAAgB"}
|