@copilotkit/aimock 1.42.0 → 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 +56 -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.cts.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 +229 -7
- 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 +221 -8
- 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/vector-types.d.cts.map +1 -1
- package/dist/vector-types.d.ts.map +1 -1
- 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({
|
|
@@ -613,7 +699,10 @@ function buildContentWithToolCallsChunks(content, toolCalls, model, chunkSize, r
|
|
|
613
699
|
model: effectiveModel,
|
|
614
700
|
choices: [{
|
|
615
701
|
index: 0,
|
|
616
|
-
delta: {
|
|
702
|
+
delta: {
|
|
703
|
+
...i === 0 && { role: overrides?.role ?? "assistant" },
|
|
704
|
+
reasoning_content: slice
|
|
705
|
+
},
|
|
617
706
|
logprobs: null,
|
|
618
707
|
finish_reason: null
|
|
619
708
|
}],
|
|
@@ -707,7 +796,7 @@ function buildContentWithToolCallsChunks(content, toolCalls, model, chunkSize, r
|
|
|
707
796
|
index: 0,
|
|
708
797
|
delta: {},
|
|
709
798
|
logprobs: null,
|
|
710
|
-
finish_reason: overrides?.finishReason ?? "tool_calls"
|
|
799
|
+
finish_reason: overrides?.finishReason ?? (outcome.hasToolCalls ? "tool_calls" : "stop")
|
|
711
800
|
}],
|
|
712
801
|
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
713
802
|
});
|
|
@@ -722,7 +811,10 @@ function buildContentWithToolCallsChunks(content, toolCalls, model, chunkSize, r
|
|
|
722
811
|
model: effectiveModel,
|
|
723
812
|
choices: [{
|
|
724
813
|
index: 0,
|
|
725
|
-
delta: {
|
|
814
|
+
delta: {
|
|
815
|
+
...i === 0 && { role: overrides?.role ?? "assistant" },
|
|
816
|
+
reasoning_content: slice
|
|
817
|
+
},
|
|
726
818
|
logprobs: null,
|
|
727
819
|
finish_reason: null
|
|
728
820
|
}],
|
|
@@ -853,7 +945,31 @@ function buildContentWithToolCallsCompletion(content, toolCalls, model, reasonin
|
|
|
853
945
|
};
|
|
854
946
|
}
|
|
855
947
|
const DEFAULT_MAX_BODY_BYTES = 10 * 1024 * 1024;
|
|
856
|
-
|
|
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) {
|
|
857
973
|
return new Promise((resolve, reject) => {
|
|
858
974
|
const chunks = [];
|
|
859
975
|
let totalBytes = 0;
|
|
@@ -864,7 +980,7 @@ function readBody(req, maxBytes = DEFAULT_MAX_BODY_BYTES) {
|
|
|
864
980
|
if (totalBytes > maxBytes) {
|
|
865
981
|
settled = true;
|
|
866
982
|
req.destroy();
|
|
867
|
-
reject(
|
|
983
|
+
reject(new RequestBodyTooLargeError(maxBytes));
|
|
868
984
|
return;
|
|
869
985
|
}
|
|
870
986
|
chunks.push(chunk);
|
|
@@ -872,9 +988,59 @@ function readBody(req, maxBytes = DEFAULT_MAX_BODY_BYTES) {
|
|
|
872
988
|
req.on("end", () => {
|
|
873
989
|
if (!settled) {
|
|
874
990
|
settled = true;
|
|
875
|
-
resolve(Buffer.concat(chunks)
|
|
991
|
+
resolve(Buffer.concat(chunks));
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
req.on("error", (err) => {
|
|
995
|
+
if (!settled) {
|
|
996
|
+
settled = true;
|
|
997
|
+
reject(err);
|
|
876
998
|
}
|
|
877
999
|
});
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
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
|
+
});
|
|
878
1044
|
req.on("error", (err) => {
|
|
879
1045
|
if (!settled) {
|
|
880
1046
|
settled = true;
|
|
@@ -883,6 +1049,9 @@ function readBody(req, maxBytes = DEFAULT_MAX_BODY_BYTES) {
|
|
|
883
1049
|
});
|
|
884
1050
|
});
|
|
885
1051
|
}
|
|
1052
|
+
function readBody(req, maxBytes = DEFAULT_MAX_BODY_BYTES) {
|
|
1053
|
+
return readBodyBuffer(req, maxBytes).then((buf) => buf.toString());
|
|
1054
|
+
}
|
|
886
1055
|
/**
|
|
887
1056
|
* Case-insensitive substring/regex match used for search, rerank, and
|
|
888
1057
|
* moderation endpoints where exact casing rarely matters. String patterns
|
|
@@ -1115,7 +1284,51 @@ function buildEmbeddingResponse(embeddings, model, usage) {
|
|
|
1115
1284
|
}
|
|
1116
1285
|
};
|
|
1117
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
|
+
}
|
|
1118
1331
|
|
|
1119
1332
|
//#endregion
|
|
1120
|
-
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 };
|
|
1121
1334
|
//# sourceMappingURL=helpers.js.map
|