@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,150 @@
|
|
|
1
|
+
import { buildEmbeddingResponse, flattenHeaders, generateDeterministicEmbedding, isEmbeddingResponse, isErrorResponse } from "./helpers.js";
|
|
2
|
+
import { matchFixture } from "./router.js";
|
|
3
|
+
import { writeErrorResponse } from "./sse-writer.js";
|
|
4
|
+
import { applyChaos } from "./chaos.js";
|
|
5
|
+
import { proxyAndRecord } from "./recorder.js";
|
|
6
|
+
|
|
7
|
+
//#region src/embeddings.ts
|
|
8
|
+
async function handleEmbeddings(req, res, raw, fixtures, journal, defaults, setCorsHeaders) {
|
|
9
|
+
const { logger } = defaults;
|
|
10
|
+
setCorsHeaders(res);
|
|
11
|
+
let embeddingReq;
|
|
12
|
+
try {
|
|
13
|
+
embeddingReq = JSON.parse(raw);
|
|
14
|
+
} catch {
|
|
15
|
+
journal.add({
|
|
16
|
+
method: req.method ?? "POST",
|
|
17
|
+
path: req.url ?? "/v1/embeddings",
|
|
18
|
+
headers: flattenHeaders(req.headers),
|
|
19
|
+
body: null,
|
|
20
|
+
response: {
|
|
21
|
+
status: 400,
|
|
22
|
+
fixture: null
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
writeErrorResponse(res, 400, JSON.stringify({ error: {
|
|
26
|
+
message: "Malformed JSON",
|
|
27
|
+
type: "invalid_request_error",
|
|
28
|
+
code: "invalid_json"
|
|
29
|
+
} }));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const inputs = Array.isArray(embeddingReq.input) ? embeddingReq.input : [embeddingReq.input];
|
|
33
|
+
const combinedInput = inputs.join(" ");
|
|
34
|
+
const syntheticReq = {
|
|
35
|
+
model: embeddingReq.model,
|
|
36
|
+
messages: [],
|
|
37
|
+
embeddingInput: combinedInput
|
|
38
|
+
};
|
|
39
|
+
const fixture = matchFixture(fixtures, syntheticReq, journal.fixtureMatchCounts);
|
|
40
|
+
if (fixture) journal.incrementFixtureMatchCount(fixture, fixtures);
|
|
41
|
+
if (applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
|
|
42
|
+
method: req.method ?? "POST",
|
|
43
|
+
path: req.url ?? "/v1/embeddings",
|
|
44
|
+
headers: flattenHeaders(req.headers),
|
|
45
|
+
body: syntheticReq
|
|
46
|
+
}, defaults.registry, defaults.logger)) return;
|
|
47
|
+
if (fixture) {
|
|
48
|
+
const response = fixture.response;
|
|
49
|
+
if (isErrorResponse(response)) {
|
|
50
|
+
const status = response.status ?? 500;
|
|
51
|
+
journal.add({
|
|
52
|
+
method: req.method ?? "POST",
|
|
53
|
+
path: req.url ?? "/v1/embeddings",
|
|
54
|
+
headers: flattenHeaders(req.headers),
|
|
55
|
+
body: syntheticReq,
|
|
56
|
+
response: {
|
|
57
|
+
status,
|
|
58
|
+
fixture
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
writeErrorResponse(res, status, JSON.stringify(response));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (isEmbeddingResponse(response)) {
|
|
65
|
+
journal.add({
|
|
66
|
+
method: req.method ?? "POST",
|
|
67
|
+
path: req.url ?? "/v1/embeddings",
|
|
68
|
+
headers: flattenHeaders(req.headers),
|
|
69
|
+
body: syntheticReq,
|
|
70
|
+
response: {
|
|
71
|
+
status: 200,
|
|
72
|
+
fixture
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
const body = buildEmbeddingResponse(inputs.map(() => [...response.embedding]), embeddingReq.model);
|
|
76
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
77
|
+
res.end(JSON.stringify(body));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
journal.add({
|
|
81
|
+
method: req.method ?? "POST",
|
|
82
|
+
path: req.url ?? "/v1/embeddings",
|
|
83
|
+
headers: flattenHeaders(req.headers),
|
|
84
|
+
body: syntheticReq,
|
|
85
|
+
response: {
|
|
86
|
+
status: 500,
|
|
87
|
+
fixture
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
91
|
+
message: "Fixture response did not match any known embedding type (must have embedding or error)",
|
|
92
|
+
type: "server_error"
|
|
93
|
+
} }));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (defaults.record) {
|
|
97
|
+
if (await proxyAndRecord(req, res, syntheticReq, "openai", req.url ?? "/v1/embeddings", fixtures, defaults, raw)) {
|
|
98
|
+
journal.add({
|
|
99
|
+
method: req.method ?? "POST",
|
|
100
|
+
path: req.url ?? "/v1/embeddings",
|
|
101
|
+
headers: flattenHeaders(req.headers),
|
|
102
|
+
body: syntheticReq,
|
|
103
|
+
response: {
|
|
104
|
+
status: res.statusCode ?? 200,
|
|
105
|
+
fixture: null
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (defaults.strict) {
|
|
112
|
+
logger.error(`STRICT: No fixture matched for ${req.method ?? "POST"} ${req.url ?? "/v1/embeddings"}`);
|
|
113
|
+
journal.add({
|
|
114
|
+
method: req.method ?? "POST",
|
|
115
|
+
path: req.url ?? "/v1/embeddings",
|
|
116
|
+
headers: flattenHeaders(req.headers),
|
|
117
|
+
body: syntheticReq,
|
|
118
|
+
response: {
|
|
119
|
+
status: 503,
|
|
120
|
+
fixture: null
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
writeErrorResponse(res, 503, JSON.stringify({ error: {
|
|
124
|
+
message: "Strict mode: no fixture matched",
|
|
125
|
+
type: "invalid_request_error",
|
|
126
|
+
code: "no_fixture_match"
|
|
127
|
+
} }));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
logger.warn(`No embedding fixture matched for "${combinedInput.slice(0, 80)}" — returning deterministic fallback`);
|
|
131
|
+
const dimensions = embeddingReq.dimensions ?? 1536;
|
|
132
|
+
const embeddings = inputs.map((input) => generateDeterministicEmbedding(input, dimensions));
|
|
133
|
+
journal.add({
|
|
134
|
+
method: req.method ?? "POST",
|
|
135
|
+
path: req.url ?? "/v1/embeddings",
|
|
136
|
+
headers: flattenHeaders(req.headers),
|
|
137
|
+
body: syntheticReq,
|
|
138
|
+
response: {
|
|
139
|
+
status: 200,
|
|
140
|
+
fixture: null
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
const body = buildEmbeddingResponse(embeddings, embeddingReq.model);
|
|
144
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
145
|
+
res.end(JSON.stringify(body));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
//#endregion
|
|
149
|
+
export { handleEmbeddings };
|
|
150
|
+
//# sourceMappingURL=embeddings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.js","names":[],"sources":["../src/embeddings.ts"],"sourcesContent":["/**\n * OpenAI Embeddings API support for LLMock.\n *\n * Handles POST /v1/embeddings requests. Matches fixtures using the `inputText`\n * field, and falls back to generating a deterministic embedding from the input\n * text hash when no fixture matches.\n */\n\nimport type * as http from \"node:http\";\nimport type { ChatCompletionRequest, Fixture, HandlerDefaults } from \"./types.js\";\nimport {\n isEmbeddingResponse,\n isErrorResponse,\n generateDeterministicEmbedding,\n buildEmbeddingResponse,\n flattenHeaders,\n} from \"./helpers.js\";\nimport { matchFixture } from \"./router.js\";\nimport { writeErrorResponse } from \"./sse-writer.js\";\nimport type { Journal } from \"./journal.js\";\nimport { applyChaos } from \"./chaos.js\";\nimport { proxyAndRecord } from \"./recorder.js\";\n\n// ─── Embeddings API request types ──────────────────────────────────────────\n\ninterface EmbeddingRequest {\n input: string | string[];\n model: string;\n encoding_format?: \"float\" | \"base64\";\n dimensions?: number;\n [key: string]: unknown;\n}\n\n// ─── Request handler ───────────────────────────────────────────────────────\n\nexport async function handleEmbeddings(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n raw: string,\n fixtures: Fixture[],\n journal: Journal,\n defaults: HandlerDefaults,\n setCorsHeaders: (res: http.ServerResponse) => void,\n): Promise<void> {\n const { logger } = defaults;\n setCorsHeaders(res);\n\n let embeddingReq: EmbeddingRequest;\n try {\n embeddingReq = JSON.parse(raw) as EmbeddingRequest;\n } catch {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: null,\n response: { status: 400, fixture: null },\n });\n writeErrorResponse(\n res,\n 400,\n JSON.stringify({\n error: {\n message: \"Malformed JSON\",\n type: \"invalid_request_error\",\n code: \"invalid_json\",\n },\n }),\n );\n return;\n }\n\n // Normalize input to array of strings\n const inputs: string[] = Array.isArray(embeddingReq.input)\n ? embeddingReq.input\n : [embeddingReq.input];\n\n // Concatenate all inputs for matching purposes\n const combinedInput = inputs.join(\" \");\n\n // Build a synthetic ChatCompletionRequest for the fixture router.\n // We attach `embeddingInput` so the router's inputText matching can use it.\n const syntheticReq: ChatCompletionRequest = {\n model: embeddingReq.model,\n messages: [],\n embeddingInput: combinedInput,\n };\n\n const fixture = matchFixture(fixtures, syntheticReq, journal.fixtureMatchCounts);\n\n if (fixture) {\n journal.incrementFixtureMatchCount(fixture, fixtures);\n }\n\n if (\n applyChaos(\n res,\n fixture,\n defaults.chaos,\n req.headers,\n journal,\n {\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n },\n defaults.registry,\n defaults.logger,\n )\n )\n return;\n\n if (fixture) {\n const response = fixture.response;\n\n // Error response\n if (isErrorResponse(response)) {\n const status = response.status ?? 500;\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status, fixture },\n });\n writeErrorResponse(res, status, JSON.stringify(response));\n return;\n }\n\n // Embedding response — use the fixture's embedding for each input\n if (isEmbeddingResponse(response)) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture },\n });\n const embeddings = inputs.map(() => [...response.embedding]);\n const body = buildEmbeddingResponse(embeddings, embeddingReq.model);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n return;\n }\n\n // Fixture matched but response type is not compatible with embeddings\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 500, fixture },\n });\n writeErrorResponse(\n res,\n 500,\n JSON.stringify({\n error: {\n message:\n \"Fixture response did not match any known embedding type (must have embedding or error)\",\n type: \"server_error\",\n },\n }),\n );\n return;\n }\n\n // No fixture match — try record-and-replay proxy if configured\n if (defaults.record) {\n const proxied = await proxyAndRecord(\n req,\n res,\n syntheticReq,\n \"openai\",\n req.url ?? \"/v1/embeddings\",\n fixtures,\n defaults,\n raw,\n );\n if (proxied) {\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: res.statusCode ?? 200, fixture: null },\n });\n return;\n }\n }\n\n if (defaults.strict) {\n logger.error(\n `STRICT: No fixture matched for ${req.method ?? \"POST\"} ${req.url ?? \"/v1/embeddings\"}`,\n );\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 503, fixture: null },\n });\n writeErrorResponse(\n res,\n 503,\n JSON.stringify({\n error: {\n message: \"Strict mode: no fixture matched\",\n type: \"invalid_request_error\",\n code: \"no_fixture_match\",\n },\n }),\n );\n return;\n }\n\n // No fixture match — generate deterministic embeddings from input text\n logger.warn(\n `No embedding fixture matched for \"${combinedInput.slice(0, 80)}\" — returning deterministic fallback`,\n );\n const dimensions = embeddingReq.dimensions ?? 1536;\n const embeddings = inputs.map((input) => generateDeterministicEmbedding(input, dimensions));\n\n journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? \"/v1/embeddings\",\n headers: flattenHeaders(req.headers),\n body: syntheticReq,\n response: { status: 200, fixture: null },\n });\n\n const body = buildEmbeddingResponse(embeddings, embeddingReq.model);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
const require_helpers = require('./helpers.cjs');
|
|
3
|
+
let node_path = require("node:path");
|
|
4
|
+
let node_fs = require("node:fs");
|
|
5
|
+
|
|
6
|
+
//#region src/fixture-loader.ts
|
|
7
|
+
function entryToFixture(entry) {
|
|
8
|
+
return {
|
|
9
|
+
match: {
|
|
10
|
+
userMessage: entry.match.userMessage,
|
|
11
|
+
inputText: entry.match.inputText,
|
|
12
|
+
toolCallId: entry.match.toolCallId,
|
|
13
|
+
toolName: entry.match.toolName,
|
|
14
|
+
model: entry.match.model,
|
|
15
|
+
responseFormat: entry.match.responseFormat,
|
|
16
|
+
...entry.match.sequenceIndex !== void 0 && { sequenceIndex: entry.match.sequenceIndex }
|
|
17
|
+
},
|
|
18
|
+
response: entry.response,
|
|
19
|
+
...entry.latency !== void 0 && { latency: entry.latency },
|
|
20
|
+
...entry.chunkSize !== void 0 && { chunkSize: entry.chunkSize },
|
|
21
|
+
...entry.truncateAfterChunks !== void 0 && { truncateAfterChunks: entry.truncateAfterChunks },
|
|
22
|
+
...entry.disconnectAfterMs !== void 0 && { disconnectAfterMs: entry.disconnectAfterMs },
|
|
23
|
+
...entry.streamingProfile !== void 0 && { streamingProfile: entry.streamingProfile },
|
|
24
|
+
...entry.chaos !== void 0 && { chaos: entry.chaos }
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function warn(logger, msg, ...rest) {
|
|
28
|
+
if (logger) logger.warn(msg, ...rest);
|
|
29
|
+
else console.warn(`[fixture-loader] ${msg}`, ...rest);
|
|
30
|
+
}
|
|
31
|
+
function loadFixtureFile(filePath, logger) {
|
|
32
|
+
let raw;
|
|
33
|
+
try {
|
|
34
|
+
raw = (0, node_fs.readFileSync)(filePath, "utf-8");
|
|
35
|
+
} catch (err) {
|
|
36
|
+
warn(logger, `Could not read file ${filePath}:`, err);
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
let parsed;
|
|
40
|
+
try {
|
|
41
|
+
parsed = JSON.parse(raw);
|
|
42
|
+
} catch (err) {
|
|
43
|
+
warn(logger, `Invalid JSON in ${filePath}:`, err);
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
if (typeof parsed !== "object" || parsed === null || !Array.isArray(parsed.fixtures)) {
|
|
47
|
+
warn(logger, `Missing or invalid "fixtures" array in ${filePath}`);
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
return parsed.fixtures.map(entryToFixture);
|
|
51
|
+
}
|
|
52
|
+
function loadFixturesFromDir(dirPath, logger) {
|
|
53
|
+
let entries;
|
|
54
|
+
try {
|
|
55
|
+
entries = (0, node_fs.readdirSync)(dirPath);
|
|
56
|
+
} catch (err) {
|
|
57
|
+
warn(logger, `Could not read directory ${dirPath}:`, err);
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
const jsonFiles = [];
|
|
61
|
+
for (const name of entries) {
|
|
62
|
+
const fullPath = (0, node_path.join)(dirPath, name);
|
|
63
|
+
try {
|
|
64
|
+
if ((0, node_fs.statSync)(fullPath).isDirectory()) {
|
|
65
|
+
warn(logger, `Skipping subdirectory ${fullPath} (fixtures are not loaded recursively)`);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
} catch (err) {
|
|
69
|
+
if (err.code !== "ENOENT") warn(logger, `Could not stat ${fullPath}:`, err);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (name.endsWith(".json")) jsonFiles.push(name);
|
|
73
|
+
}
|
|
74
|
+
jsonFiles.sort();
|
|
75
|
+
const fixtures = [];
|
|
76
|
+
for (const name of jsonFiles) {
|
|
77
|
+
const filePath = (0, node_path.join)(dirPath, name);
|
|
78
|
+
fixtures.push(...loadFixtureFile(filePath, logger));
|
|
79
|
+
}
|
|
80
|
+
return fixtures;
|
|
81
|
+
}
|
|
82
|
+
function validateFixtures(fixtures) {
|
|
83
|
+
const results = [];
|
|
84
|
+
const seenUserMessages = /* @__PURE__ */ new Map();
|
|
85
|
+
for (let i = 0; i < fixtures.length; i++) {
|
|
86
|
+
const f = fixtures[i];
|
|
87
|
+
const response = f.response;
|
|
88
|
+
if (!require_helpers.isTextResponse(response) && !require_helpers.isToolCallResponse(response) && !require_helpers.isErrorResponse(response) && !require_helpers.isEmbeddingResponse(response)) results.push({
|
|
89
|
+
severity: "error",
|
|
90
|
+
fixtureIndex: i,
|
|
91
|
+
message: "response is not a recognized type (must have content, toolCalls, error, or embedding)"
|
|
92
|
+
});
|
|
93
|
+
if (require_helpers.isTextResponse(response)) {
|
|
94
|
+
if (response.content === "") results.push({
|
|
95
|
+
severity: "error",
|
|
96
|
+
fixtureIndex: i,
|
|
97
|
+
message: "content is empty string"
|
|
98
|
+
});
|
|
99
|
+
if (response.reasoning !== void 0) {
|
|
100
|
+
if (typeof response.reasoning !== "string") results.push({
|
|
101
|
+
severity: "error",
|
|
102
|
+
fixtureIndex: i,
|
|
103
|
+
message: "reasoning must be a string"
|
|
104
|
+
});
|
|
105
|
+
else if (response.reasoning === "") results.push({
|
|
106
|
+
severity: "warning",
|
|
107
|
+
fixtureIndex: i,
|
|
108
|
+
message: "reasoning is empty string — no reasoning events will be emitted"
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
if (response.webSearches !== void 0) if (!Array.isArray(response.webSearches)) results.push({
|
|
112
|
+
severity: "error",
|
|
113
|
+
fixtureIndex: i,
|
|
114
|
+
message: "webSearches must be an array of strings"
|
|
115
|
+
});
|
|
116
|
+
else if (response.webSearches.length === 0) results.push({
|
|
117
|
+
severity: "warning",
|
|
118
|
+
fixtureIndex: i,
|
|
119
|
+
message: "webSearches is empty array — no web search events will be emitted"
|
|
120
|
+
});
|
|
121
|
+
else for (let j = 0; j < response.webSearches.length; j++) {
|
|
122
|
+
if (typeof response.webSearches[j] !== "string") {
|
|
123
|
+
results.push({
|
|
124
|
+
severity: "error",
|
|
125
|
+
fixtureIndex: i,
|
|
126
|
+
message: `webSearches[${j}] is not a string`
|
|
127
|
+
});
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
if (response.webSearches[j] === "") results.push({
|
|
131
|
+
severity: "warning",
|
|
132
|
+
fixtureIndex: i,
|
|
133
|
+
message: `webSearches[${j}] is empty string`
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (require_helpers.isToolCallResponse(response)) {
|
|
138
|
+
if (response.toolCalls.length === 0) results.push({
|
|
139
|
+
severity: "warning",
|
|
140
|
+
fixtureIndex: i,
|
|
141
|
+
message: "toolCalls array is empty — fixture will never produce tool calls"
|
|
142
|
+
});
|
|
143
|
+
for (let j = 0; j < response.toolCalls.length; j++) {
|
|
144
|
+
const tc = response.toolCalls[j];
|
|
145
|
+
if (!tc.name) results.push({
|
|
146
|
+
severity: "error",
|
|
147
|
+
fixtureIndex: i,
|
|
148
|
+
message: `toolCalls[${j}].name is empty`
|
|
149
|
+
});
|
|
150
|
+
try {
|
|
151
|
+
JSON.parse(tc.arguments);
|
|
152
|
+
} catch {
|
|
153
|
+
results.push({
|
|
154
|
+
severity: "error",
|
|
155
|
+
fixtureIndex: i,
|
|
156
|
+
message: `toolCalls[${j}].arguments is not valid JSON: ${tc.arguments}`
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (require_helpers.isErrorResponse(response)) {
|
|
162
|
+
if (!response.error.message) results.push({
|
|
163
|
+
severity: "error",
|
|
164
|
+
fixtureIndex: i,
|
|
165
|
+
message: "error.message is empty"
|
|
166
|
+
});
|
|
167
|
+
if (response.status !== void 0 && (response.status < 100 || response.status > 599)) results.push({
|
|
168
|
+
severity: "error",
|
|
169
|
+
fixtureIndex: i,
|
|
170
|
+
message: `error status ${response.status} is not a valid HTTP status code`
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
if (require_helpers.isEmbeddingResponse(response)) {
|
|
174
|
+
if (response.embedding.length === 0) results.push({
|
|
175
|
+
severity: "error",
|
|
176
|
+
fixtureIndex: i,
|
|
177
|
+
message: "embedding array is empty"
|
|
178
|
+
});
|
|
179
|
+
for (let j = 0; j < response.embedding.length; j++) if (typeof response.embedding[j] !== "number") {
|
|
180
|
+
results.push({
|
|
181
|
+
severity: "error",
|
|
182
|
+
fixtureIndex: i,
|
|
183
|
+
message: `embedding[${j}] is not a number`
|
|
184
|
+
});
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (f.latency !== void 0 && f.latency < 0) results.push({
|
|
189
|
+
severity: "error",
|
|
190
|
+
fixtureIndex: i,
|
|
191
|
+
message: "latency must be >= 0"
|
|
192
|
+
});
|
|
193
|
+
if (f.chunkSize !== void 0 && f.chunkSize < 1) results.push({
|
|
194
|
+
severity: "error",
|
|
195
|
+
fixtureIndex: i,
|
|
196
|
+
message: "chunkSize must be >= 1"
|
|
197
|
+
});
|
|
198
|
+
if (f.truncateAfterChunks !== void 0 && f.truncateAfterChunks < 1) results.push({
|
|
199
|
+
severity: "error",
|
|
200
|
+
fixtureIndex: i,
|
|
201
|
+
message: "truncateAfterChunks must be >= 1"
|
|
202
|
+
});
|
|
203
|
+
if (f.disconnectAfterMs !== void 0 && f.disconnectAfterMs < 0) results.push({
|
|
204
|
+
severity: "error",
|
|
205
|
+
fixtureIndex: i,
|
|
206
|
+
message: "disconnectAfterMs must be >= 0"
|
|
207
|
+
});
|
|
208
|
+
if (f.streamingProfile !== void 0) {
|
|
209
|
+
const sp = f.streamingProfile;
|
|
210
|
+
if (sp.ttft !== void 0 && sp.ttft < 0) results.push({
|
|
211
|
+
severity: "error",
|
|
212
|
+
fixtureIndex: i,
|
|
213
|
+
message: "streamingProfile.ttft must be >= 0"
|
|
214
|
+
});
|
|
215
|
+
if (sp.tps !== void 0 && sp.tps <= 0) results.push({
|
|
216
|
+
severity: "error",
|
|
217
|
+
fixtureIndex: i,
|
|
218
|
+
message: "streamingProfile.tps must be > 0"
|
|
219
|
+
});
|
|
220
|
+
if (sp.jitter !== void 0 && (sp.jitter < 0 || sp.jitter > 1)) results.push({
|
|
221
|
+
severity: "error",
|
|
222
|
+
fixtureIndex: i,
|
|
223
|
+
message: "streamingProfile.jitter must be between 0 and 1"
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
if (f.chaos !== void 0) {
|
|
227
|
+
const ch = f.chaos;
|
|
228
|
+
if (ch.dropRate !== void 0 && (ch.dropRate < 0 || ch.dropRate > 1)) results.push({
|
|
229
|
+
severity: "error",
|
|
230
|
+
fixtureIndex: i,
|
|
231
|
+
message: "chaos.dropRate must be between 0 and 1"
|
|
232
|
+
});
|
|
233
|
+
if (ch.malformedRate !== void 0 && (ch.malformedRate < 0 || ch.malformedRate > 1)) results.push({
|
|
234
|
+
severity: "error",
|
|
235
|
+
fixtureIndex: i,
|
|
236
|
+
message: "chaos.malformedRate must be between 0 and 1"
|
|
237
|
+
});
|
|
238
|
+
if (ch.disconnectRate !== void 0 && (ch.disconnectRate < 0 || ch.disconnectRate > 1)) results.push({
|
|
239
|
+
severity: "error",
|
|
240
|
+
fixtureIndex: i,
|
|
241
|
+
message: "chaos.disconnectRate must be between 0 and 1"
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
const um = f.match.userMessage;
|
|
245
|
+
if (typeof um === "string" && um) {
|
|
246
|
+
const prev = seenUserMessages.get(um);
|
|
247
|
+
if (prev !== void 0) results.push({
|
|
248
|
+
severity: "warning",
|
|
249
|
+
fixtureIndex: i,
|
|
250
|
+
message: `duplicate userMessage '${um}' — shadows fixture ${prev}`
|
|
251
|
+
});
|
|
252
|
+
else seenUserMessages.set(um, i);
|
|
253
|
+
}
|
|
254
|
+
const match = f.match;
|
|
255
|
+
if (!(match.userMessage !== void 0 || match.inputText !== void 0 || match.responseFormat !== void 0 || match.toolCallId !== void 0 || match.toolName !== void 0 || match.model !== void 0 || match.predicate !== void 0) && i < fixtures.length - 1) results.push({
|
|
256
|
+
severity: "warning",
|
|
257
|
+
fixtureIndex: i,
|
|
258
|
+
message: `empty match acts as catch-all but is not the last fixture — shadows fixtures ${i + 1}+`
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
return results;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
//#endregion
|
|
265
|
+
exports.entryToFixture = entryToFixture;
|
|
266
|
+
exports.loadFixtureFile = loadFixtureFile;
|
|
267
|
+
exports.loadFixturesFromDir = loadFixturesFromDir;
|
|
268
|
+
exports.validateFixtures = validateFixtures;
|
|
269
|
+
//# sourceMappingURL=fixture-loader.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixture-loader.cjs","names":["isTextResponse","isToolCallResponse","isErrorResponse","isEmbeddingResponse"],"sources":["../src/fixture-loader.ts"],"sourcesContent":["import { readFileSync, readdirSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Fixture, FixtureFile, FixtureFileEntry } from \"./types.js\";\nimport {\n isTextResponse,\n isToolCallResponse,\n isErrorResponse,\n isEmbeddingResponse,\n} from \"./helpers.js\";\nimport type { Logger } from \"./logger.js\";\n\nexport function entryToFixture(entry: FixtureFileEntry): Fixture {\n return {\n match: {\n userMessage: entry.match.userMessage,\n inputText: entry.match.inputText,\n toolCallId: entry.match.toolCallId,\n toolName: entry.match.toolName,\n model: entry.match.model,\n responseFormat: entry.match.responseFormat,\n ...(entry.match.sequenceIndex !== undefined && { sequenceIndex: entry.match.sequenceIndex }),\n },\n response: entry.response,\n ...(entry.latency !== undefined && { latency: entry.latency }),\n ...(entry.chunkSize !== undefined && { chunkSize: entry.chunkSize }),\n ...(entry.truncateAfterChunks !== undefined && {\n truncateAfterChunks: entry.truncateAfterChunks,\n }),\n ...(entry.disconnectAfterMs !== undefined && { disconnectAfterMs: entry.disconnectAfterMs }),\n ...(entry.streamingProfile !== undefined && { streamingProfile: entry.streamingProfile }),\n ...(entry.chaos !== undefined && { chaos: entry.chaos }),\n };\n}\n\n// Logging helper — uses logger if provided, falls back to console.warn.\nfunction warn(logger: Logger | undefined, msg: string, ...rest: unknown[]): void {\n if (logger) {\n logger.warn(msg, ...rest);\n } else {\n console.warn(`[fixture-loader] ${msg}`, ...rest);\n }\n}\n\nexport function loadFixtureFile(filePath: string, logger?: Logger): Fixture[] {\n let raw: string;\n try {\n raw = readFileSync(filePath, \"utf-8\");\n } catch (err) {\n warn(logger, `Could not read file ${filePath}:`, err);\n return [];\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n warn(logger, `Invalid JSON in ${filePath}:`, err);\n return [];\n }\n\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n !Array.isArray((parsed as FixtureFile).fixtures)\n ) {\n warn(logger, `Missing or invalid \"fixtures\" array in ${filePath}`);\n return [];\n }\n\n return (parsed as FixtureFile).fixtures.map(entryToFixture);\n}\n\nexport function loadFixturesFromDir(dirPath: string, logger?: Logger): Fixture[] {\n let entries: string[];\n try {\n entries = readdirSync(dirPath);\n } catch (err) {\n warn(logger, `Could not read directory ${dirPath}:`, err);\n return [];\n }\n\n const jsonFiles: string[] = [];\n for (const name of entries) {\n const fullPath = join(dirPath, name);\n try {\n if (statSync(fullPath).isDirectory()) {\n warn(logger, `Skipping subdirectory ${fullPath} (fixtures are not loaded recursively)`);\n continue;\n }\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\") {\n warn(logger, `Could not stat ${fullPath}:`, err);\n }\n continue;\n }\n if (name.endsWith(\".json\")) {\n jsonFiles.push(name);\n }\n }\n jsonFiles.sort();\n\n const fixtures: Fixture[] = [];\n for (const name of jsonFiles) {\n const filePath = join(dirPath, name);\n fixtures.push(...loadFixtureFile(filePath, logger));\n }\n\n return fixtures;\n}\n\n// ---------------------------------------------------------------------------\n// Fixture validation\n// ---------------------------------------------------------------------------\n\nexport interface ValidationResult {\n severity: \"error\" | \"warning\";\n fixtureIndex: number;\n message: string;\n}\n\nexport function validateFixtures(fixtures: Fixture[]): ValidationResult[] {\n const results: ValidationResult[] = [];\n\n const seenUserMessages = new Map<string, number>();\n\n for (let i = 0; i < fixtures.length; i++) {\n const f = fixtures[i];\n const response = f.response;\n\n // --- Error checks ---\n\n // Response type recognition\n if (\n !isTextResponse(response) &&\n !isToolCallResponse(response) &&\n !isErrorResponse(response) &&\n !isEmbeddingResponse(response)\n ) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message:\n \"response is not a recognized type (must have content, toolCalls, error, or embedding)\",\n });\n }\n\n // Text response checks\n if (isTextResponse(response)) {\n if (response.content === \"\") {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"content is empty string\",\n });\n }\n if (response.reasoning !== undefined) {\n if (typeof response.reasoning !== \"string\") {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"reasoning must be a string\",\n });\n } else if (response.reasoning === \"\") {\n results.push({\n severity: \"warning\",\n fixtureIndex: i,\n message: \"reasoning is empty string — no reasoning events will be emitted\",\n });\n }\n }\n if (response.webSearches !== undefined) {\n if (!Array.isArray(response.webSearches)) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"webSearches must be an array of strings\",\n });\n } else if (response.webSearches.length === 0) {\n results.push({\n severity: \"warning\",\n fixtureIndex: i,\n message: \"webSearches is empty array — no web search events will be emitted\",\n });\n } else {\n for (let j = 0; j < response.webSearches.length; j++) {\n if (typeof response.webSearches[j] !== \"string\") {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: `webSearches[${j}] is not a string`,\n });\n break;\n }\n if (response.webSearches[j] === \"\") {\n results.push({\n severity: \"warning\",\n fixtureIndex: i,\n message: `webSearches[${j}] is empty string`,\n });\n }\n }\n }\n }\n }\n\n // Tool call response checks\n if (isToolCallResponse(response)) {\n if (response.toolCalls.length === 0) {\n results.push({\n severity: \"warning\",\n fixtureIndex: i,\n message: \"toolCalls array is empty — fixture will never produce tool calls\",\n });\n }\n for (let j = 0; j < response.toolCalls.length; j++) {\n const tc = response.toolCalls[j];\n if (!tc.name) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: `toolCalls[${j}].name is empty`,\n });\n }\n try {\n JSON.parse(tc.arguments);\n } catch {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: `toolCalls[${j}].arguments is not valid JSON: ${tc.arguments}`,\n });\n }\n }\n }\n\n // Error response checks\n if (isErrorResponse(response)) {\n if (!response.error.message) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"error.message is empty\",\n });\n }\n if (response.status !== undefined && (response.status < 100 || response.status > 599)) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: `error status ${response.status} is not a valid HTTP status code`,\n });\n }\n }\n\n // Embedding response checks\n if (isEmbeddingResponse(response)) {\n if (response.embedding.length === 0) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"embedding array is empty\",\n });\n }\n for (let j = 0; j < response.embedding.length; j++) {\n if (typeof response.embedding[j] !== \"number\") {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: `embedding[${j}] is not a number`,\n });\n break; // one error is enough\n }\n }\n }\n\n // Numeric sanity checks\n if (f.latency !== undefined && f.latency < 0) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"latency must be >= 0\",\n });\n }\n if (f.chunkSize !== undefined && f.chunkSize < 1) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"chunkSize must be >= 1\",\n });\n }\n if (f.truncateAfterChunks !== undefined && f.truncateAfterChunks < 1) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"truncateAfterChunks must be >= 1\",\n });\n }\n if (f.disconnectAfterMs !== undefined && f.disconnectAfterMs < 0) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"disconnectAfterMs must be >= 0\",\n });\n }\n if (f.streamingProfile !== undefined) {\n const sp = f.streamingProfile;\n if (sp.ttft !== undefined && sp.ttft < 0) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"streamingProfile.ttft must be >= 0\",\n });\n }\n if (sp.tps !== undefined && sp.tps <= 0) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"streamingProfile.tps must be > 0\",\n });\n }\n if (sp.jitter !== undefined && (sp.jitter < 0 || sp.jitter > 1)) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"streamingProfile.jitter must be between 0 and 1\",\n });\n }\n }\n if (f.chaos !== undefined) {\n const ch = f.chaos;\n if (ch.dropRate !== undefined && (ch.dropRate < 0 || ch.dropRate > 1)) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"chaos.dropRate must be between 0 and 1\",\n });\n }\n if (ch.malformedRate !== undefined && (ch.malformedRate < 0 || ch.malformedRate > 1)) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"chaos.malformedRate must be between 0 and 1\",\n });\n }\n if (ch.disconnectRate !== undefined && (ch.disconnectRate < 0 || ch.disconnectRate > 1)) {\n results.push({\n severity: \"error\",\n fixtureIndex: i,\n message: \"chaos.disconnectRate must be between 0 and 1\",\n });\n }\n }\n\n // --- Warning checks ---\n\n // Duplicate userMessage shadowing\n const um = f.match.userMessage;\n if (typeof um === \"string\" && um) {\n const prev = seenUserMessages.get(um);\n if (prev !== undefined) {\n results.push({\n severity: \"warning\",\n fixtureIndex: i,\n message: `duplicate userMessage '${um}' — shadows fixture ${prev}`,\n });\n } else {\n seenUserMessages.set(um, i);\n }\n }\n\n // Catch-all not in last position\n const match = f.match;\n const hasDiscriminator =\n match.userMessage !== undefined ||\n match.inputText !== undefined ||\n match.responseFormat !== undefined ||\n match.toolCallId !== undefined ||\n match.toolName !== undefined ||\n match.model !== undefined ||\n match.predicate !== undefined;\n\n if (!hasDiscriminator && i < fixtures.length - 1) {\n results.push({\n severity: \"warning\",\n fixtureIndex: i,\n message: `empty match acts as catch-all but is not the last fixture — shadows fixtures ${i + 1}+`,\n });\n }\n }\n\n return results;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Logger } from "./logger.cjs";
|
|
2
|
+
import { Fixture } from "./types.cjs";
|
|
3
|
+
|
|
4
|
+
//#region src/fixture-loader.d.ts
|
|
5
|
+
declare function loadFixtureFile(filePath: string, logger?: Logger): Fixture[];
|
|
6
|
+
declare function loadFixturesFromDir(dirPath: string, logger?: Logger): Fixture[];
|
|
7
|
+
interface ValidationResult {
|
|
8
|
+
severity: "error" | "warning";
|
|
9
|
+
fixtureIndex: number;
|
|
10
|
+
message: string;
|
|
11
|
+
}
|
|
12
|
+
declare function validateFixtures(fixtures: Fixture[]): ValidationResult[];
|
|
13
|
+
//# sourceMappingURL=fixture-loader.d.ts.map
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
export { ValidationResult, loadFixtureFile, loadFixturesFromDir, validateFixtures };
|
|
17
|
+
//# sourceMappingURL=fixture-loader.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixture-loader.d.cts","names":[],"sources":["../src/fixture-loader.ts"],"sourcesContent":[],"mappings":";;;;iBA2CgB,eAAA,4BAA2C,SAAS;AAApD,iBA6BA,mBAAA,CA7Be,OAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EA6B+B,MA7B/B,CAAA,EA6BwC,OA7BxC,EAAA;AAAA,UAwEd,gBAAA,CAxEc;UAA4B,EAAA,OAAA,GAAA,SAAA;cAAS,EAAA,MAAA;EAAO,OAAA,EAAA,MAAA;AA6B3E;AAAmC,iBAiDnB,gBAAA,CAjDmB,QAAA,EAiDQ,OAjDR,EAAA,CAAA,EAiDoB,gBAjDpB,EAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Logger } from "./logger.js";
|
|
2
|
+
import { Fixture } from "./types.js";
|
|
3
|
+
|
|
4
|
+
//#region src/fixture-loader.d.ts
|
|
5
|
+
declare function loadFixtureFile(filePath: string, logger?: Logger): Fixture[];
|
|
6
|
+
declare function loadFixturesFromDir(dirPath: string, logger?: Logger): Fixture[];
|
|
7
|
+
interface ValidationResult {
|
|
8
|
+
severity: "error" | "warning";
|
|
9
|
+
fixtureIndex: number;
|
|
10
|
+
message: string;
|
|
11
|
+
}
|
|
12
|
+
declare function validateFixtures(fixtures: Fixture[]): ValidationResult[];
|
|
13
|
+
//# sourceMappingURL=fixture-loader.d.ts.map
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
export { ValidationResult, loadFixtureFile, loadFixturesFromDir, validateFixtures };
|
|
17
|
+
//# sourceMappingURL=fixture-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixture-loader.d.ts","names":[],"sources":["../src/fixture-loader.ts"],"sourcesContent":[],"mappings":";;;;iBA2CgB,eAAA,4BAA2C,SAAS;AAApD,iBA6BA,mBAAA,CA7Be,OAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EA6B+B,MA7B/B,CAAA,EA6BwC,OA7BxC,EAAA;AAAA,UAwEd,gBAAA,CAxEc;UAA4B,EAAA,OAAA,GAAA,SAAA;cAAS,EAAA,MAAA;EAAO,OAAA,EAAA,MAAA;AA6B3E;AAAmC,iBAiDnB,gBAAA,CAjDmB,QAAA,EAiDQ,OAjDR,EAAA,CAAA,EAiDoB,gBAjDpB,EAAA"}
|