@copilotkit/aimock 1.42.1 → 1.43.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 +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +50 -0
- package/README.md +102 -16
- package/dist/agui-mock.cjs +1 -1
- package/dist/agui-mock.cjs.map +1 -1
- package/dist/agui-mock.d.cts.map +1 -1
- package/dist/agui-mock.d.ts.map +1 -1
- package/dist/agui-mock.js +1 -1
- package/dist/agui-mock.js.map +1 -1
- package/dist/agui-recorder.cjs +33 -11
- package/dist/agui-recorder.cjs.map +1 -1
- package/dist/agui-recorder.d.cts +10 -1
- package/dist/agui-recorder.d.cts.map +1 -1
- package/dist/agui-recorder.d.ts +10 -1
- package/dist/agui-recorder.d.ts.map +1 -1
- package/dist/agui-recorder.js +33 -11
- package/dist/agui-recorder.js.map +1 -1
- package/dist/agui-types.d.cts +1 -0
- package/dist/agui-types.d.cts.map +1 -1
- package/dist/agui-types.d.ts +1 -0
- package/dist/agui-types.d.ts.map +1 -1
- package/dist/aimock-cli.cjs +38 -10
- package/dist/aimock-cli.cjs.map +1 -1
- package/dist/aimock-cli.d.cts +5 -0
- package/dist/aimock-cli.d.cts.map +1 -1
- package/dist/aimock-cli.d.ts +5 -0
- package/dist/aimock-cli.d.ts.map +1 -1
- package/dist/aimock-cli.js +38 -10
- package/dist/aimock-cli.js.map +1 -1
- package/dist/batches.cjs +458 -0
- package/dist/batches.cjs.map +1 -0
- package/dist/batches.d.cts +57 -0
- package/dist/batches.d.cts.map +1 -0
- package/dist/batches.d.ts +57 -0
- package/dist/batches.d.ts.map +1 -0
- package/dist/batches.js +453 -0
- package/dist/batches.js.map +1 -0
- package/dist/bedrock-converse.cjs +12 -8
- package/dist/bedrock-converse.cjs.map +1 -1
- package/dist/bedrock-converse.d.cts.map +1 -1
- package/dist/bedrock-converse.d.ts.map +1 -1
- package/dist/bedrock-converse.js +14 -10
- package/dist/bedrock-converse.js.map +1 -1
- package/dist/bedrock.cjs +10 -8
- package/dist/bedrock.cjs.map +1 -1
- package/dist/bedrock.d.cts.map +1 -1
- package/dist/bedrock.d.ts.map +1 -1
- package/dist/bedrock.js +12 -10
- package/dist/bedrock.js.map +1 -1
- package/dist/byteplus-video.cjs +3 -3
- package/dist/byteplus-video.cjs.map +1 -1
- package/dist/byteplus-video.js +4 -4
- package/dist/byteplus-video.js.map +1 -1
- package/dist/chaos.cjs +622 -72
- package/dist/chaos.cjs.map +1 -1
- package/dist/chaos.d.cts +164 -7
- package/dist/chaos.d.cts.map +1 -1
- package/dist/chaos.d.ts +164 -7
- package/dist/chaos.d.ts.map +1 -1
- package/dist/chaos.js +613 -74
- package/dist/chaos.js.map +1 -1
- package/dist/cli.cjs +42 -23
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +42 -23
- package/dist/cli.js.map +1 -1
- package/dist/cohere.cjs +10 -8
- package/dist/cohere.cjs.map +1 -1
- package/dist/cohere.d.cts.map +1 -1
- package/dist/cohere.d.ts.map +1 -1
- package/dist/cohere.js +12 -10
- package/dist/cohere.js.map +1 -1
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/convert.cjs +1 -1
- package/dist/convert.cjs.map +1 -1
- package/dist/convert.js +1 -1
- package/dist/convert.js.map +1 -1
- package/dist/elevenlabs-audio.cjs +3 -3
- package/dist/elevenlabs-audio.cjs.map +1 -1
- package/dist/elevenlabs-audio.js +4 -4
- package/dist/elevenlabs-audio.js.map +1 -1
- package/dist/elevenlabs-voice.cjs +1053 -0
- package/dist/elevenlabs-voice.cjs.map +1 -0
- package/dist/elevenlabs-voice.d.cts +72 -0
- package/dist/elevenlabs-voice.d.cts.map +1 -0
- package/dist/elevenlabs-voice.d.ts +72 -0
- package/dist/elevenlabs-voice.d.ts.map +1 -0
- package/dist/elevenlabs-voice.js +1048 -0
- package/dist/elevenlabs-voice.js.map +1 -0
- package/dist/embeddings.cjs +8 -4
- package/dist/embeddings.cjs.map +1 -1
- package/dist/embeddings.d.cts.map +1 -1
- package/dist/embeddings.d.ts.map +1 -1
- package/dist/embeddings.js +9 -5
- package/dist/embeddings.js.map +1 -1
- package/dist/fal-audio.cjs +3 -3
- package/dist/fal-audio.cjs.map +1 -1
- package/dist/fal-audio.js +4 -4
- package/dist/fal-audio.js.map +1 -1
- package/dist/fal.cjs +28 -4
- package/dist/fal.cjs.map +1 -1
- package/dist/fal.d.cts +16 -1
- package/dist/fal.d.cts.map +1 -1
- package/dist/fal.d.ts +16 -1
- package/dist/fal.d.ts.map +1 -1
- package/dist/fal.js +28 -5
- package/dist/fal.js.map +1 -1
- package/dist/files.cjs +1071 -0
- package/dist/files.cjs.map +1 -0
- package/dist/files.d.cts +68 -0
- package/dist/files.d.cts.map +1 -0
- package/dist/files.d.ts +68 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +1059 -0
- package/dist/files.js.map +1 -0
- package/dist/fine-tuning.cjs +1051 -0
- package/dist/fine-tuning.cjs.map +1 -0
- package/dist/fine-tuning.d.cts +96 -0
- package/dist/fine-tuning.d.cts.map +1 -0
- package/dist/fine-tuning.d.ts +96 -0
- package/dist/fine-tuning.d.ts.map +1 -0
- package/dist/fine-tuning.js +1044 -0
- package/dist/fine-tuning.js.map +1 -0
- package/dist/fixture-loader.cjs +0 -0
- package/dist/fixture-loader.cjs.map +1 -1
- package/dist/fixture-loader.d.cts +37 -5
- package/dist/fixture-loader.d.cts.map +1 -1
- package/dist/fixture-loader.d.ts +37 -5
- package/dist/fixture-loader.d.ts.map +1 -1
- package/dist/fixture-loader.js +0 -0
- package/dist/fixture-loader.js.map +1 -1
- package/dist/gemini-embeddings.cjs +2 -2
- package/dist/gemini-embeddings.cjs.map +1 -1
- package/dist/gemini-embeddings.js +3 -3
- package/dist/gemini-embeddings.js.map +1 -1
- package/dist/gemini-interactions.cjs +13 -7
- package/dist/gemini-interactions.cjs.map +1 -1
- package/dist/gemini-interactions.d.cts.map +1 -1
- package/dist/gemini-interactions.d.ts.map +1 -1
- package/dist/gemini-interactions.js +15 -9
- package/dist/gemini-interactions.js.map +1 -1
- package/dist/gemini.cjs +11 -7
- package/dist/gemini.cjs.map +1 -1
- package/dist/gemini.d.cts.map +1 -1
- package/dist/gemini.d.ts.map +1 -1
- package/dist/gemini.js +13 -9
- package/dist/gemini.js.map +1 -1
- package/dist/grok-video.cjs +14 -14
- package/dist/grok-video.cjs.map +1 -1
- package/dist/grok-video.js +15 -15
- package/dist/grok-video.js.map +1 -1
- package/dist/helpers.cjs +221 -5
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +38 -2
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.ts +38 -2
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +213 -6
- package/dist/helpers.js.map +1 -1
- package/dist/images.cjs +54 -123
- package/dist/images.cjs.map +1 -1
- package/dist/images.d.cts.map +1 -1
- package/dist/images.d.ts.map +1 -1
- package/dist/images.js +55 -124
- package/dist/images.js.map +1 -1
- package/dist/index.cjs +41 -8
- package/dist/index.d.cts +12 -7
- package/dist/index.d.ts +12 -7
- package/dist/index.js +14 -10
- package/dist/jest.cjs +14 -7
- package/dist/jest.cjs.map +1 -1
- package/dist/jest.d.cts +3 -2
- package/dist/jest.d.cts.map +1 -1
- package/dist/jest.d.ts +3 -2
- package/dist/jest.d.ts.map +1 -1
- package/dist/jest.js +14 -7
- package/dist/jest.js.map +1 -1
- package/dist/journal.cjs +41 -4
- package/dist/journal.cjs.map +1 -1
- package/dist/journal.d.cts +44 -3
- package/dist/journal.d.cts.map +1 -1
- package/dist/journal.d.ts +44 -3
- package/dist/journal.d.ts.map +1 -1
- package/dist/journal.js +41 -5
- package/dist/journal.js.map +1 -1
- package/dist/live-fixture.cjs +1192 -0
- package/dist/live-fixture.cjs.map +1 -0
- package/dist/live-fixture.js +1187 -0
- package/dist/live-fixture.js.map +1 -0
- package/dist/live-recorder.cjs +256 -0
- package/dist/live-recorder.cjs.map +1 -0
- package/dist/live-recorder.js +254 -0
- package/dist/live-recorder.js.map +1 -0
- package/dist/live-replay.cjs +286 -0
- package/dist/live-replay.cjs.map +1 -0
- package/dist/live-replay.js +285 -0
- package/dist/live-replay.js.map +1 -0
- package/dist/live-sanitize.cjs +196 -0
- package/dist/live-sanitize.cjs.map +1 -0
- package/dist/live-sanitize.js +196 -0
- package/dist/live-sanitize.js.map +1 -0
- package/dist/live-types.d.cts +71 -0
- package/dist/live-types.d.cts.map +1 -0
- package/dist/live-types.d.ts +71 -0
- package/dist/live-types.d.ts.map +1 -0
- package/dist/llmock.cjs +52 -41
- package/dist/llmock.cjs.map +1 -1
- package/dist/llmock.d.cts +16 -5
- package/dist/llmock.d.cts.map +1 -1
- package/dist/llmock.d.ts +16 -5
- package/dist/llmock.d.ts.map +1 -1
- package/dist/llmock.js +53 -42
- package/dist/llmock.js.map +1 -1
- package/dist/messages.cjs +11 -7
- package/dist/messages.cjs.map +1 -1
- package/dist/messages.d.cts.map +1 -1
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +13 -9
- package/dist/messages.js.map +1 -1
- package/dist/metrics.cjs +258 -5
- package/dist/metrics.cjs.map +1 -1
- package/dist/metrics.d.cts +3 -1
- package/dist/metrics.d.cts.map +1 -1
- package/dist/metrics.d.ts +3 -1
- package/dist/metrics.d.ts.map +1 -1
- package/dist/metrics.js +255 -6
- package/dist/metrics.js.map +1 -1
- package/dist/moderation.cjs +10 -1
- package/dist/moderation.cjs.map +1 -1
- package/dist/moderation.d.cts.map +1 -1
- package/dist/moderation.d.ts.map +1 -1
- package/dist/moderation.js +10 -1
- package/dist/moderation.js.map +1 -1
- package/dist/ollama.cjs +5 -5
- package/dist/ollama.cjs.map +1 -1
- package/dist/ollama.js +6 -6
- package/dist/ollama.js.map +1 -1
- package/dist/openrouter-video.cjs +5 -5
- package/dist/openrouter-video.cjs.map +1 -1
- package/dist/openrouter-video.js +6 -6
- package/dist/openrouter-video.js.map +1 -1
- package/dist/recorder.cjs +45 -9
- package/dist/recorder.cjs.map +1 -1
- package/dist/recorder.d.cts.map +1 -1
- package/dist/recorder.d.ts.map +1 -1
- package/dist/recorder.js +43 -11
- package/dist/recorder.js.map +1 -1
- package/dist/responses.cjs +4 -3
- package/dist/responses.cjs.map +1 -1
- package/dist/responses.js +5 -5
- package/dist/responses.js.map +1 -1
- package/dist/router.cjs +20 -33
- package/dist/router.cjs.map +1 -1
- package/dist/router.d.cts +4 -1
- package/dist/router.d.cts.map +1 -1
- package/dist/router.d.ts +4 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +20 -34
- package/dist/router.js.map +1 -1
- package/dist/server.cjs +701 -625
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +1 -0
- package/dist/server.d.cts.map +1 -1
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +704 -628
- package/dist/server.js.map +1 -1
- package/dist/speech.cjs +2 -2
- package/dist/speech.cjs.map +1 -1
- package/dist/speech.js +3 -3
- package/dist/speech.js.map +1 -1
- package/dist/transcription.cjs +4 -4
- package/dist/transcription.cjs.map +1 -1
- package/dist/transcription.js +5 -5
- package/dist/transcription.js.map +1 -1
- package/dist/types.d.cts +119 -16
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +119 -16
- package/dist/types.d.ts.map +1 -1
- package/dist/validate-cli.cjs +925 -0
- package/dist/validate-cli.cjs.map +1 -0
- package/dist/validate-cli.js +924 -0
- package/dist/validate-cli.js.map +1 -0
- package/dist/veo-video.cjs +13 -13
- package/dist/veo-video.cjs.map +1 -1
- package/dist/veo-video.js +14 -14
- package/dist/veo-video.js.map +1 -1
- package/dist/video.cjs +4 -4
- package/dist/video.cjs.map +1 -1
- package/dist/video.d.cts +1 -1
- package/dist/video.d.cts.map +1 -1
- package/dist/video.d.ts +1 -1
- package/dist/video.d.ts.map +1 -1
- package/dist/video.js +5 -5
- package/dist/video.js.map +1 -1
- package/dist/vitest.cjs +13 -6
- package/dist/vitest.cjs.map +1 -1
- package/dist/vitest.d.cts +2 -1
- package/dist/vitest.d.cts.map +1 -1
- package/dist/vitest.d.ts +2 -1
- package/dist/vitest.d.ts.map +1 -1
- package/dist/vitest.js +14 -7
- package/dist/vitest.js.map +1 -1
- package/dist/watcher.cjs +2 -1
- package/dist/watcher.cjs.map +1 -1
- package/dist/watcher.js +2 -1
- package/dist/watcher.js.map +1 -1
- package/dist/ws-framing.cjs +150 -35
- package/dist/ws-framing.cjs.map +1 -1
- package/dist/ws-framing.d.cts +18 -3
- package/dist/ws-framing.d.cts.map +1 -1
- package/dist/ws-framing.d.ts +18 -3
- package/dist/ws-framing.d.ts.map +1 -1
- package/dist/ws-framing.js +151 -36
- package/dist/ws-framing.js.map +1 -1
- package/dist/ws-gemini-live.cjs +2 -2
- package/dist/ws-gemini-live.d.ts +2 -2
- package/dist/ws-gemini-live.js +2 -2
- package/dist/ws-live.cjs +401 -0
- package/dist/ws-live.cjs.map +1 -0
- package/dist/ws-live.js +400 -0
- package/dist/ws-live.js.map +1 -0
- package/dist/ws-realtime.cjs +46 -2
- package/dist/ws-realtime.cjs.map +1 -1
- package/dist/ws-realtime.d.cts.map +1 -1
- package/dist/ws-realtime.d.ts +2 -2
- package/dist/ws-realtime.d.ts.map +1 -1
- package/dist/ws-realtime.js +46 -2
- package/dist/ws-realtime.js.map +1 -1
- package/dist/ws-responses.cjs +2 -2
- package/dist/ws-responses.js +2 -2
- package/dist/ws-upstream.cjs +118 -0
- package/dist/ws-upstream.cjs.map +1 -0
- package/dist/ws-upstream.js +115 -0
- package/dist/ws-upstream.js.map +1 -0
- package/fixtures/openai-live-client.json +390 -0
- package/fixtures/openai-live-managed.json +709 -0
- package/package.json +1 -1
package/dist/helpers.js
CHANGED
|
@@ -26,6 +26,18 @@ function resolveStrictMode(serverDefault, rawHeaders) {
|
|
|
26
26
|
return serverDefault ?? false;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
+
* Would a fixture miss on this request have been forwarded upstream? This is
|
|
30
|
+
* the ONE rule behind the no-fixture chaos journal `source` label: "proxy"
|
|
31
|
+
* only when record mode has an upstream for THIS provider and strict mode is
|
|
32
|
+
* not refusing the miss first. `effectiveStrict` is the header-resolved value
|
|
33
|
+
* from {@link resolveStrictMode}. `record.providers` is read guarded — a JS
|
|
34
|
+
* caller can hand over `record: {}`.
|
|
35
|
+
*/
|
|
36
|
+
function wouldProxyMiss(effectiveStrict, record, providerKey) {
|
|
37
|
+
if (effectiveStrict || providerKey === void 0) return false;
|
|
38
|
+
return Boolean(record?.providers?.[providerKey]);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
29
41
|
* Returns `true` or `false` when the X-AIMock-Strict header overrides the
|
|
30
42
|
* server default, or `undefined` when it doesn't. Designed to be spread
|
|
31
43
|
* directly into a journal entry's `response` object:
|
|
@@ -142,6 +154,10 @@ function flattenHeaders(headers) {
|
|
|
142
154
|
}
|
|
143
155
|
return flat;
|
|
144
156
|
}
|
|
157
|
+
/** Structural discriminator; registration performs full transcript validation. */
|
|
158
|
+
function isLiveResponse(value) {
|
|
159
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) && "live" in value;
|
|
160
|
+
}
|
|
145
161
|
function isResponseFactory(r) {
|
|
146
162
|
return typeof r === "function";
|
|
147
163
|
}
|
|
@@ -176,6 +192,57 @@ function normalizeFactoryResponse(raw) {
|
|
|
176
192
|
function generateId(prefix = "chatcmpl") {
|
|
177
193
|
return `${prefix}-${randomBytes(12).toString("base64url")}`;
|
|
178
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Resolve the request id for this HTTP request.
|
|
197
|
+
*
|
|
198
|
+
* - When the caller sends a well-formed `X-Request-Id` (1-128 chars of
|
|
199
|
+
* `A-Za-z0-9-_.:`), it is echoed verbatim so distributed traces correlate.
|
|
200
|
+
* - Otherwise (absent, empty, too long, or illegal characters) a fresh
|
|
201
|
+
* `req-…` id is generated — never trust an attacker-controlled correlation
|
|
202
|
+
* value to be a valid log key.
|
|
203
|
+
*
|
|
204
|
+
* Returns `{ id, generated }`. The server normalizes
|
|
205
|
+
* `req.headers["x-request-id"]` to the resolved value, so every downstream
|
|
206
|
+
* `flattenHeaders` journal snapshot carries it with zero per-handler edits —
|
|
207
|
+
* which also means a MINTED id would otherwise ride the egress header set to
|
|
208
|
+
* a real provider. The server therefore passes `generated` to
|
|
209
|
+
* `markMintedRequestId` so `buildForwardHeaders` can drop it; a caller's own
|
|
210
|
+
* id still forwards verbatim.
|
|
211
|
+
*/
|
|
212
|
+
function resolveRequestId(rawHeaders) {
|
|
213
|
+
const raw = rawHeaders["x-request-id"];
|
|
214
|
+
const first = Array.isArray(raw) ? raw[0] : raw;
|
|
215
|
+
if (typeof first === "string") {
|
|
216
|
+
const trimmed = first.trim();
|
|
217
|
+
if (trimmed.length >= 1 && trimmed.length <= 128 && /^[A-Za-z0-9\-_.:]+$/.test(trimmed)) return {
|
|
218
|
+
id: trimmed,
|
|
219
|
+
generated: false
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
id: generateId("req"),
|
|
224
|
+
generated: true
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Requests whose `x-request-id` aimock MINTED (the caller sent none, or sent
|
|
229
|
+
* an unusable one). The normalized header is indistinguishable from a
|
|
230
|
+
* caller-supplied one by inspection, so the provenance is tracked out-of-band
|
|
231
|
+
* and keyed on the request object, exactly like the egress auth marker.
|
|
232
|
+
*/
|
|
233
|
+
const mintedRequestIds = /* @__PURE__ */ new WeakSet();
|
|
234
|
+
/** @internal Record that this request's `x-request-id` is aimock's own. */
|
|
235
|
+
function markMintedRequestId(req, generated) {
|
|
236
|
+
if (generated) mintedRequestIds.add(req);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* @internal True when `x-request-id` on this request was minted by aimock.
|
|
240
|
+
* Egress paths use it to avoid transmitting an invented correlation id to a
|
|
241
|
+
* real provider.
|
|
242
|
+
*/
|
|
243
|
+
function hasMintedRequestId(req) {
|
|
244
|
+
return mintedRequestIds.has(req);
|
|
245
|
+
}
|
|
179
246
|
function generateToolCallId() {
|
|
180
247
|
return `call_${randomBytes(12).toString("base64url")}`;
|
|
181
248
|
}
|
|
@@ -254,6 +321,24 @@ function resolveFixtureBlocks(blocks) {
|
|
|
254
321
|
} else throw new Error(`Invalid fixture block at index ${i}: unknown type ${JSON.stringify(b.type)} (expected "text" or "toolCall")`);
|
|
255
322
|
});
|
|
256
323
|
}
|
|
324
|
+
/** Project normalized ordered blocks without changing the fixture or generating ids. */
|
|
325
|
+
function resolveFixtureBlockOutcome(blocks) {
|
|
326
|
+
const ordered = resolveFixtureBlocks(blocks);
|
|
327
|
+
let content = "";
|
|
328
|
+
const toolCalls = [];
|
|
329
|
+
for (const block of ordered) if (block.type === "text") content += block.text;
|
|
330
|
+
else toolCalls.push({
|
|
331
|
+
name: block.name,
|
|
332
|
+
arguments: block.arguments,
|
|
333
|
+
...block.id !== void 0 ? { id: block.id } : {}
|
|
334
|
+
});
|
|
335
|
+
return {
|
|
336
|
+
ordered,
|
|
337
|
+
content,
|
|
338
|
+
toolCalls,
|
|
339
|
+
hasToolCalls: toolCalls.length > 0
|
|
340
|
+
};
|
|
341
|
+
}
|
|
257
342
|
function isErrorResponse(r) {
|
|
258
343
|
return "error" in r && r.error !== null && typeof r.error === "object" && "message" in r.error && typeof r.error.message === "string";
|
|
259
344
|
}
|
|
@@ -603,7 +688,8 @@ function buildContentWithToolCallsChunks(content, toolCalls, model, chunkSize, r
|
|
|
603
688
|
const chunks = [];
|
|
604
689
|
const fingerprint = overrides?.systemFingerprint;
|
|
605
690
|
if (blocks && blocks.length > 0) {
|
|
606
|
-
const
|
|
691
|
+
const outcome = resolveFixtureBlockOutcome(blocks);
|
|
692
|
+
const ordered = outcome.ordered;
|
|
607
693
|
if (reasoning) for (let i = 0; i < reasoning.length; i += chunkSize) {
|
|
608
694
|
const slice = reasoning.slice(i, i + chunkSize);
|
|
609
695
|
chunks.push({
|
|
@@ -710,7 +796,7 @@ function buildContentWithToolCallsChunks(content, toolCalls, model, chunkSize, r
|
|
|
710
796
|
index: 0,
|
|
711
797
|
delta: {},
|
|
712
798
|
logprobs: null,
|
|
713
|
-
finish_reason: overrides?.finishReason ?? "tool_calls"
|
|
799
|
+
finish_reason: overrides?.finishReason ?? (outcome.hasToolCalls ? "tool_calls" : "stop")
|
|
714
800
|
}],
|
|
715
801
|
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
716
802
|
});
|
|
@@ -859,7 +945,31 @@ function buildContentWithToolCallsCompletion(content, toolCalls, model, reasonin
|
|
|
859
945
|
};
|
|
860
946
|
}
|
|
861
947
|
const DEFAULT_MAX_BODY_BYTES = 10 * 1024 * 1024;
|
|
862
|
-
|
|
948
|
+
/**
|
|
949
|
+
* A body read that stopped because the CLIENT sent more bytes than the route
|
|
950
|
+
* allows. The socket is already destroyed when this rejects, so no status line
|
|
951
|
+
* ever reaches the caller — but the fault is the caller's, and error arms that
|
|
952
|
+
* journal and log the failure need to say so. Carrying the classification on
|
|
953
|
+
* the error type (rather than re-matching the message text) is what lets them:
|
|
954
|
+
* the message is unchanged from the plain `Error` this replaced.
|
|
955
|
+
*/
|
|
956
|
+
var RequestBodyTooLargeError = class extends Error {
|
|
957
|
+
constructor(maxBytes) {
|
|
958
|
+
super(`Request body exceeded size limit of ${maxBytes} bytes`);
|
|
959
|
+
this.maxBytes = maxBytes;
|
|
960
|
+
this.name = "RequestBodyTooLargeError";
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
/**
|
|
964
|
+
* Read a request body as raw bytes, preserving every octet.
|
|
965
|
+
*
|
|
966
|
+
* This is the byte-level primitive {@link readBody} is built on: routes that
|
|
967
|
+
* must not lose bytes (binary file uploads) take the Buffer, everything else
|
|
968
|
+
* keeps taking the decoded string. Splitting it this way leaves the text path
|
|
969
|
+
* byte-identical — `readBody` performs exactly the same `Buffer.concat(...)`
|
|
970
|
+
* + default (utf8) `toString()` it always did, just one call later.
|
|
971
|
+
*/
|
|
972
|
+
function readBodyBuffer(req, maxBytes = DEFAULT_MAX_BODY_BYTES) {
|
|
863
973
|
return new Promise((resolve, reject) => {
|
|
864
974
|
const chunks = [];
|
|
865
975
|
let totalBytes = 0;
|
|
@@ -870,7 +980,7 @@ function readBody(req, maxBytes = DEFAULT_MAX_BODY_BYTES) {
|
|
|
870
980
|
if (totalBytes > maxBytes) {
|
|
871
981
|
settled = true;
|
|
872
982
|
req.destroy();
|
|
873
|
-
reject(
|
|
983
|
+
reject(new RequestBodyTooLargeError(maxBytes));
|
|
874
984
|
return;
|
|
875
985
|
}
|
|
876
986
|
chunks.push(chunk);
|
|
@@ -878,7 +988,7 @@ function readBody(req, maxBytes = DEFAULT_MAX_BODY_BYTES) {
|
|
|
878
988
|
req.on("end", () => {
|
|
879
989
|
if (!settled) {
|
|
880
990
|
settled = true;
|
|
881
|
-
resolve(Buffer.concat(chunks)
|
|
991
|
+
resolve(Buffer.concat(chunks));
|
|
882
992
|
}
|
|
883
993
|
});
|
|
884
994
|
req.on("error", (err) => {
|
|
@@ -890,6 +1000,59 @@ function readBody(req, maxBytes = DEFAULT_MAX_BODY_BYTES) {
|
|
|
890
1000
|
});
|
|
891
1001
|
}
|
|
892
1002
|
/**
|
|
1003
|
+
* Read a request body that may legitimately be over-size, without either
|
|
1004
|
+
* buffering it all or dropping the socket.
|
|
1005
|
+
*
|
|
1006
|
+
* {@link readBodyBuffer} answers an over-size body with `req.destroy()`: no
|
|
1007
|
+
* status line, no body, no CORS headers. That is the right default for routes
|
|
1008
|
+
* whose limit is a pure DoS bound, but it is the wrong answer for a route that
|
|
1009
|
+
* owes the caller a `400` describing what was wrong — the caller cannot read an
|
|
1010
|
+
* error it never receives. So this variant splits the two concerns:
|
|
1011
|
+
*
|
|
1012
|
+
* - `maxBytes` bounds MEMORY. Past it the buffered chunks are dropped and the
|
|
1013
|
+
* body is only counted, so peak retention never exceeds `maxBytes` no matter
|
|
1014
|
+
* how large the body is. The caller gets `buffer: null` and answers itself.
|
|
1015
|
+
* - `drainMaxBytes` bounds WORK, and is the only socket drop here: a body that
|
|
1016
|
+
* keeps coming past it is not worth draining and rejects as `readBodyBuffer`
|
|
1017
|
+
* would.
|
|
1018
|
+
*/
|
|
1019
|
+
function readBodyBufferBounded(req, maxBytes, drainMaxBytes) {
|
|
1020
|
+
return new Promise((resolve, reject) => {
|
|
1021
|
+
let chunks = [];
|
|
1022
|
+
let totalBytes = 0;
|
|
1023
|
+
let settled = false;
|
|
1024
|
+
req.on("data", (chunk) => {
|
|
1025
|
+
if (settled) return;
|
|
1026
|
+
totalBytes += chunk.length;
|
|
1027
|
+
if (chunks !== null && totalBytes > maxBytes) chunks = null;
|
|
1028
|
+
if (totalBytes > drainMaxBytes) {
|
|
1029
|
+
settled = true;
|
|
1030
|
+
req.destroy();
|
|
1031
|
+
reject(new RequestBodyTooLargeError(drainMaxBytes));
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
if (chunks !== null) chunks.push(chunk);
|
|
1035
|
+
});
|
|
1036
|
+
req.on("end", () => {
|
|
1037
|
+
if (settled) return;
|
|
1038
|
+
settled = true;
|
|
1039
|
+
resolve({
|
|
1040
|
+
buffer: chunks === null ? null : Buffer.concat(chunks),
|
|
1041
|
+
bytesRead: totalBytes
|
|
1042
|
+
});
|
|
1043
|
+
});
|
|
1044
|
+
req.on("error", (err) => {
|
|
1045
|
+
if (!settled) {
|
|
1046
|
+
settled = true;
|
|
1047
|
+
reject(err);
|
|
1048
|
+
}
|
|
1049
|
+
});
|
|
1050
|
+
});
|
|
1051
|
+
}
|
|
1052
|
+
function readBody(req, maxBytes = DEFAULT_MAX_BODY_BYTES) {
|
|
1053
|
+
return readBodyBuffer(req, maxBytes).then((buf) => buf.toString());
|
|
1054
|
+
}
|
|
1055
|
+
/**
|
|
893
1056
|
* Case-insensitive substring/regex match used for search, rerank, and
|
|
894
1057
|
* moderation endpoints where exact casing rarely matters. String patterns
|
|
895
1058
|
* are lowercased on both sides before comparison.
|
|
@@ -1121,7 +1284,51 @@ function buildEmbeddingResponse(embeddings, model, usage) {
|
|
|
1121
1284
|
}
|
|
1122
1285
|
};
|
|
1123
1286
|
}
|
|
1287
|
+
/**
|
|
1288
|
+
* Build a stable, human-readable identifier for a fixture's match shape, for
|
|
1289
|
+
* any log line that has to name WHICH fixture it means. The `Fixture` type
|
|
1290
|
+
* carries no `id`/`name`, so the matchers are the only handle a reader has.
|
|
1291
|
+
*
|
|
1292
|
+
* Used by the relaxed-turnIndex warning (`router.ts`) and by the chaos
|
|
1293
|
+
* rejected-value warning (`chaos.ts`); one implementation so the two name the
|
|
1294
|
+
* same fixture the same way. The obvious `JSON.stringify(match)` is unfit: it
|
|
1295
|
+
* DROPS `predicate` functions (non-serialisable) and serialises any RegExp
|
|
1296
|
+
* matcher to `{}`, so a predicate- or regex-gated fixture's warning collapsed to
|
|
1297
|
+
* an uninformative "served fixture {}" / `{"userMessage":{}}` blob.
|
|
1298
|
+
*
|
|
1299
|
+
* Instead we list the PRESENT matcher keys in declaration order, annotating each
|
|
1300
|
+
* by VALUE KIND so predicates and regexes survive: `predicate(fn)`,
|
|
1301
|
+
* `userMessage(regex)`, `userMessage("hello")`, `turnIndex=0`, etc. The
|
|
1302
|
+
* fixture's array `index` is prefixed as a stable positional identifier when
|
|
1303
|
+
* the caller knows it (i.e. `>= 0`); callers holding only the fixture object
|
|
1304
|
+
* pass `-1` and get the matcher summary alone. String/number values are shown
|
|
1305
|
+
* inline (truncated) so a content match remains recognisable; the whole string
|
|
1306
|
+
* is capped to keep the log line bounded.
|
|
1307
|
+
*/
|
|
1308
|
+
const DESCRIBE_MATCH_MAX = 160;
|
|
1309
|
+
function describeMatch(match, index) {
|
|
1310
|
+
const parts = [];
|
|
1311
|
+
for (const [key, value] of Object.entries(match)) {
|
|
1312
|
+
if (value === void 0) continue;
|
|
1313
|
+
if (typeof value === "function") parts.push(key === "predicate" ? "[predicate]" : `${key}[fn]`);
|
|
1314
|
+
else if (value instanceof RegExp) parts.push(`${key}(${value})`);
|
|
1315
|
+
else if (typeof value === "string") {
|
|
1316
|
+
const v = value.length > 40 ? `${value.slice(0, 40)}…` : value;
|
|
1317
|
+
parts.push(`${key}(${JSON.stringify(v)})`);
|
|
1318
|
+
} else if (Array.isArray(value)) parts.push(`${key}(${value.length} item${value.length === 1 ? "" : "s"})`);
|
|
1319
|
+
else if (typeof value === "object" && value !== null) {
|
|
1320
|
+
const json = JSON.stringify(value);
|
|
1321
|
+
parts.push(`${key}(${json.length > 40 ? `${json.slice(0, 40)}…` : json})`);
|
|
1322
|
+
} else parts.push(`${key}=${String(value)}`);
|
|
1323
|
+
}
|
|
1324
|
+
const keys = parts.length > 0 ? parts.join(", ") : "no matchers";
|
|
1325
|
+
const full = `${index >= 0 ? `#${index} ` : ""}{ ${keys} }`;
|
|
1326
|
+
if (full.length <= DESCRIBE_MATCH_MAX) return full;
|
|
1327
|
+
const head = full.slice(0, DESCRIBE_MATCH_MAX - 4);
|
|
1328
|
+
const cut = head.lastIndexOf(", ");
|
|
1329
|
+
return `${cut > 0 ? head.slice(0, cut) : head}, … }`;
|
|
1330
|
+
}
|
|
1124
1331
|
|
|
1125
1332
|
//#endregion
|
|
1126
|
-
export { FORMAT_TO_CONTENT_TYPE, MAX_EMBEDDING_DIMENSIONS, buildContentWithToolCallsChunks, buildContentWithToolCallsCompletion, buildEmbeddingResponse, buildTextChunks, buildTextCompletion, buildToolCallChunks, buildToolCallCompletion, buildUsageChunk, extractOverrides, flattenHeaders, formatToMime, generateDeterministicEmbedding, generateId, generateMessageId, generateToolCallId, generateToolUseId, getContext, getTestId, isAudioResponse, isContentWithToolCallsResponse, isEmbeddingResponse, isErrorResponse, isImageResponse, isJSONResponse, isJsonObject, isResponseFactory, isTextResponse, isToolCallResponse, isTranscriptionResponse, isVideoResponse, matchesPattern, normalizeEmbeddingInput, normalizeTextInput, readBody, resolveFixtureBlocks, resolveReasoningArtifactsForModel, resolveReasoningForModel, resolveResponse, resolveStrictMode, resolveTestId, resolveUsage, serializeErrorResponse, slugifyContext, slugifyTestId, strictNoMatchLogLine, strictNoMatchMessage, strictOverrideField, validateChatMessages, validateEmbeddingDimensions, validateToolsField };
|
|
1333
|
+
export { FORMAT_TO_CONTENT_TYPE, MAX_EMBEDDING_DIMENSIONS, RequestBodyTooLargeError, buildContentWithToolCallsChunks, buildContentWithToolCallsCompletion, buildEmbeddingResponse, buildTextChunks, buildTextCompletion, buildToolCallChunks, buildToolCallCompletion, buildUsageChunk, describeMatch, extractOverrides, flattenHeaders, formatToMime, generateDeterministicEmbedding, generateId, generateMessageId, generateToolCallId, generateToolUseId, getContext, getTestId, hasMintedRequestId, isAudioResponse, isContentWithToolCallsResponse, isEmbeddingResponse, isErrorResponse, isImageResponse, isJSONResponse, isJsonObject, isLiveResponse, isResponseFactory, isTextResponse, isToolCallResponse, isTranscriptionResponse, isVideoResponse, markMintedRequestId, matchesPattern, normalizeEmbeddingInput, normalizeTextInput, readBody, readBodyBufferBounded, resolveFixtureBlockOutcome, resolveFixtureBlocks, resolveReasoningArtifactsForModel, resolveReasoningForModel, resolveRequestId, resolveResponse, resolveStrictMode, resolveTestId, resolveUsage, serializeErrorResponse, slugifyContext, slugifyTestId, strictNoMatchLogLine, strictNoMatchMessage, strictOverrideField, validateChatMessages, validateEmbeddingDimensions, validateToolsField, wouldProxyMiss };
|
|
1127
1334
|
//# sourceMappingURL=helpers.js.map
|