@copilotkit/aimock 1.40.0 → 1.42.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 +28 -1
- package/README.md +5 -3
- package/dist/a2a-mock.cjs +18 -11
- package/dist/a2a-mock.cjs.map +1 -1
- package/dist/a2a-mock.d.cts +1 -0
- package/dist/a2a-mock.d.cts.map +1 -1
- package/dist/a2a-mock.d.ts +1 -0
- package/dist/a2a-mock.d.ts.map +1 -1
- package/dist/a2a-mock.js +18 -11
- package/dist/a2a-mock.js.map +1 -1
- package/dist/agui-handler.d.cts.map +1 -1
- package/dist/agui-handler.d.ts.map +1 -1
- package/dist/agui-mock.cjs +2 -0
- 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 +2 -0
- package/dist/agui-mock.js.map +1 -1
- package/dist/bedrock-converse.cjs +36 -2
- 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 +37 -3
- package/dist/bedrock-converse.js.map +1 -1
- package/dist/bedrock.cjs +50 -13
- 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 +51 -14
- package/dist/bedrock.js.map +1 -1
- package/dist/byteplus-video.cjs +954 -0
- package/dist/byteplus-video.cjs.map +1 -0
- package/dist/byteplus-video.d.cts +176 -0
- package/dist/byteplus-video.d.cts.map +1 -0
- package/dist/byteplus-video.d.ts +176 -0
- package/dist/byteplus-video.d.ts.map +1 -0
- package/dist/byteplus-video.js +947 -0
- package/dist/byteplus-video.js.map +1 -0
- package/dist/chaos.cjs +36 -7
- package/dist/chaos.cjs.map +1 -1
- package/dist/chaos.d.cts +8 -3
- package/dist/chaos.d.cts.map +1 -1
- package/dist/chaos.d.ts +8 -3
- package/dist/chaos.d.ts.map +1 -1
- package/dist/chaos.js +36 -8
- package/dist/chaos.js.map +1 -1
- package/dist/cli.cjs +5 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +5 -1
- package/dist/cli.js.map +1 -1
- package/dist/cohere.cjs +58 -5
- 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 +59 -6
- package/dist/cohere.js.map +1 -1
- package/dist/config-loader.d.cts.map +1 -1
- package/dist/elevenlabs-audio.cjs +36 -2
- package/dist/elevenlabs-audio.cjs.map +1 -1
- package/dist/elevenlabs-audio.d.cts.map +1 -1
- package/dist/elevenlabs-audio.d.ts.map +1 -1
- package/dist/elevenlabs-audio.js +37 -3
- package/dist/elevenlabs-audio.js.map +1 -1
- package/dist/embeddings.cjs +58 -3
- 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 +59 -4
- package/dist/embeddings.js.map +1 -1
- package/dist/fal-audio.cjs +38 -2
- package/dist/fal-audio.cjs.map +1 -1
- package/dist/fal-audio.d.cts.map +1 -1
- package/dist/fal-audio.d.ts.map +1 -1
- package/dist/fal-audio.js +39 -3
- package/dist/fal-audio.js.map +1 -1
- package/dist/fixture-loader.cjs +0 -0
- package/dist/fixture-loader.cjs.map +1 -1
- package/dist/fixture-loader.d.cts +9 -1
- package/dist/fixture-loader.d.cts.map +1 -1
- package/dist/fixture-loader.d.ts +9 -1
- 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 +19 -1
- package/dist/gemini-embeddings.cjs.map +1 -1
- package/dist/gemini-embeddings.js +20 -2
- package/dist/gemini-embeddings.js.map +1 -1
- package/dist/gemini-interactions.cjs +15 -1
- 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 +16 -2
- package/dist/gemini-interactions.js.map +1 -1
- package/dist/gemini.cjs +70 -6
- 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 +71 -7
- package/dist/gemini.js.map +1 -1
- package/dist/grok-video.cjs +2 -2
- package/dist/grok-video.cjs.map +1 -1
- package/dist/grok-video.d.cts.map +1 -1
- package/dist/grok-video.d.ts.map +1 -1
- package/dist/grok-video.js +2 -2
- package/dist/grok-video.js.map +1 -1
- package/dist/helpers.cjs +160 -5
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +152 -6
- package/dist/helpers.js.map +1 -1
- package/dist/images.cjs +24 -6
- package/dist/images.cjs.map +1 -1
- package/dist/images.d.cts +11 -3
- package/dist/images.d.cts.map +1 -1
- package/dist/images.d.ts +11 -3
- package/dist/images.d.ts.map +1 -1
- package/dist/images.js +25 -7
- package/dist/images.js.map +1 -1
- package/dist/index.cjs +7 -0
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/llmock.cjs +15 -0
- package/dist/llmock.cjs.map +1 -1
- package/dist/llmock.d.cts +12 -0
- package/dist/llmock.d.cts.map +1 -1
- package/dist/llmock.d.ts +12 -0
- package/dist/llmock.d.ts.map +1 -1
- package/dist/llmock.js +16 -1
- package/dist/llmock.js.map +1 -1
- package/dist/mcp-mock.cjs +11 -0
- package/dist/mcp-mock.cjs.map +1 -1
- package/dist/mcp-mock.d.cts.map +1 -1
- package/dist/mcp-mock.d.ts.map +1 -1
- package/dist/mcp-mock.js +11 -0
- package/dist/mcp-mock.js.map +1 -1
- package/dist/messages.cjs +18 -1
- 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 +19 -2
- package/dist/messages.js.map +1 -1
- package/dist/metrics.cjs +20 -0
- package/dist/metrics.cjs.map +1 -1
- package/dist/metrics.d.cts.map +1 -1
- package/dist/metrics.d.ts.map +1 -1
- package/dist/metrics.js +19 -1
- package/dist/metrics.js.map +1 -1
- package/dist/moderation.cjs +67 -3
- package/dist/moderation.cjs.map +1 -1
- package/dist/moderation.d.cts +1 -0
- package/dist/moderation.d.cts.map +1 -1
- package/dist/moderation.d.ts +1 -0
- package/dist/moderation.d.ts.map +1 -1
- package/dist/moderation.js +68 -4
- package/dist/moderation.js.map +1 -1
- package/dist/ollama.cjs +75 -5
- package/dist/ollama.cjs.map +1 -1
- package/dist/ollama.d.cts.map +1 -1
- package/dist/ollama.d.ts.map +1 -1
- package/dist/ollama.js +76 -6
- package/dist/ollama.js.map +1 -1
- package/dist/openrouter-video.cjs +4 -4
- package/dist/openrouter-video.cjs.map +1 -1
- package/dist/openrouter-video.d.cts.map +1 -1
- package/dist/openrouter-video.d.ts.map +1 -1
- package/dist/openrouter-video.js +4 -4
- package/dist/openrouter-video.js.map +1 -1
- package/dist/provider-auth.cjs +2 -0
- package/dist/provider-auth.cjs.map +1 -1
- package/dist/provider-auth.js +2 -0
- package/dist/provider-auth.js.map +1 -1
- package/dist/rerank.cjs +65 -2
- package/dist/rerank.cjs.map +1 -1
- package/dist/rerank.d.cts +1 -1
- package/dist/rerank.d.cts.map +1 -1
- package/dist/rerank.d.ts +1 -1
- package/dist/rerank.d.ts.map +1 -1
- package/dist/rerank.js +66 -3
- package/dist/rerank.js.map +1 -1
- package/dist/responses.cjs +18 -1
- package/dist/responses.cjs.map +1 -1
- package/dist/responses.d.cts.map +1 -1
- package/dist/responses.d.ts.map +1 -1
- package/dist/responses.js +19 -2
- package/dist/responses.js.map +1 -1
- package/dist/router.cjs +1 -0
- package/dist/router.cjs.map +1 -1
- package/dist/router.d.cts.map +1 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +1 -0
- package/dist/router.js.map +1 -1
- package/dist/search.cjs +67 -3
- package/dist/search.cjs.map +1 -1
- package/dist/search.d.cts +1 -0
- package/dist/search.d.cts.map +1 -1
- package/dist/search.d.ts +1 -0
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +68 -4
- package/dist/search.js.map +1 -1
- package/dist/server.cjs +406 -17
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +2 -0
- package/dist/server.d.cts.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +410 -21
- package/dist/server.js.map +1 -1
- package/dist/speech.cjs +18 -1
- package/dist/speech.cjs.map +1 -1
- package/dist/speech.d.cts.map +1 -1
- package/dist/speech.d.ts.map +1 -1
- package/dist/speech.js +19 -2
- package/dist/speech.js.map +1 -1
- package/dist/stream-collapse.cjs +2 -1
- package/dist/stream-collapse.cjs.map +1 -1
- package/dist/stream-collapse.js +2 -1
- package/dist/stream-collapse.js.map +1 -1
- package/dist/transcription.cjs +21 -2
- package/dist/transcription.cjs.map +1 -1
- package/dist/transcription.d.cts.map +1 -1
- package/dist/transcription.d.ts.map +1 -1
- package/dist/transcription.js +21 -2
- package/dist/transcription.js.map +1 -1
- package/dist/types.d.cts +58 -5
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +58 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/vector-mock.cjs +88 -0
- package/dist/vector-mock.cjs.map +1 -1
- package/dist/vector-mock.d.cts.map +1 -1
- package/dist/vector-mock.d.ts.map +1 -1
- package/dist/vector-mock.js +89 -1
- package/dist/vector-mock.js.map +1 -1
- package/dist/vector-types.d.cts.map +1 -1
- package/dist/veo-video.cjs +2 -2
- package/dist/veo-video.cjs.map +1 -1
- package/dist/veo-video.d.cts.map +1 -1
- package/dist/veo-video.d.ts.map +1 -1
- package/dist/veo-video.js +2 -2
- package/dist/veo-video.js.map +1 -1
- package/dist/video.cjs +19 -2
- package/dist/video.cjs.map +1 -1
- package/dist/video.d.cts.map +1 -1
- package/dist/video.d.ts.map +1 -1
- package/dist/video.js +20 -3
- package/dist/video.js.map +1 -1
- package/package.json +2 -2
package/dist/server.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
const require_constants = require('./constants.cjs');
|
|
2
3
|
const require_api_key_auth = require('./api-key-auth.cjs');
|
|
3
4
|
const require_helpers = require('./helpers.cjs');
|
|
4
5
|
const require_logger = require('./logger.cjs');
|
|
@@ -27,6 +28,7 @@ const require_fal = require('./fal.cjs');
|
|
|
27
28
|
const require_openrouter_video = require('./openrouter-video.cjs');
|
|
28
29
|
const require_veo_video = require('./veo-video.cjs');
|
|
29
30
|
const require_grok_video = require('./grok-video.cjs');
|
|
31
|
+
const require_byteplus_video = require('./byteplus-video.cjs');
|
|
30
32
|
const require_elevenlabs_audio = require('./elevenlabs-audio.cjs');
|
|
31
33
|
const require_ollama = require('./ollama.cjs');
|
|
32
34
|
const require_cohere = require('./cohere.cjs');
|
|
@@ -126,7 +128,8 @@ const DEFAULT_MODELS = [
|
|
|
126
128
|
const CORS_HEADERS = {
|
|
127
129
|
"Access-Control-Allow-Origin": "*",
|
|
128
130
|
"Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
|
|
129
|
-
"Access-Control-Allow-Headers": "*"
|
|
131
|
+
"Access-Control-Allow-Headers": "*",
|
|
132
|
+
"Access-Control-Expose-Headers": "X-Total-Count"
|
|
130
133
|
};
|
|
131
134
|
function setCorsHeaders(res) {
|
|
132
135
|
for (const [key, value] of Object.entries(CORS_HEADERS)) res.setHeader(key, value);
|
|
@@ -144,11 +147,24 @@ function handleNotFound(res, message) {
|
|
|
144
147
|
} }));
|
|
145
148
|
}
|
|
146
149
|
const CONTROL_PREFIX = "/__aimock";
|
|
150
|
+
/** The complete `GET /__aimock/fixtures` query-param vocabulary; anything else 400s. */
|
|
151
|
+
const FIXTURES_PARAMS = new Set(["include"]);
|
|
152
|
+
/** The complete `GET /__aimock/journal` query-param vocabulary; anything else 400s. */
|
|
153
|
+
const JOURNAL_PARAMS = new Set([
|
|
154
|
+
"limit",
|
|
155
|
+
"offset",
|
|
156
|
+
"path",
|
|
157
|
+
"method",
|
|
158
|
+
"status",
|
|
159
|
+
"service",
|
|
160
|
+
"testId"
|
|
161
|
+
]);
|
|
147
162
|
/**
|
|
148
163
|
* Perform a full reset: clear the fixtures array, the journal (entries *and*
|
|
149
164
|
* per-test fixture match-counts, i.e. sequence position), the video and fal.ai
|
|
150
|
-
* job/queue state,
|
|
151
|
-
* the
|
|
165
|
+
* job/queue state, the Gemini interaction/event-id counters, and any runtime
|
|
166
|
+
* chaos override (reverting to the construction-time chaos config), then
|
|
167
|
+
* re-zero the `aimock_fixtures_loaded` gauge.
|
|
152
168
|
*
|
|
153
169
|
* `targets` is `null` when no server is running (an in-process `reset()` before
|
|
154
170
|
* `start()`). The process-global generation state is reset either way, since it
|
|
@@ -165,17 +181,112 @@ function performFullReset(fixtures, targets) {
|
|
|
165
181
|
require_gemini_interactions.resetEventIdCounter();
|
|
166
182
|
if (!targets) return;
|
|
167
183
|
targets.journal.clear();
|
|
184
|
+
targets.defaults.chaos = void 0;
|
|
168
185
|
targets.videoStates.clear();
|
|
169
186
|
targets.openRouterVideoJobs.clear();
|
|
170
187
|
targets.veoVideoJobs.clear();
|
|
171
188
|
targets.grokVideoJobs.clear();
|
|
189
|
+
targets.bytePlusVideoJobs.clear();
|
|
172
190
|
if (targets.defaults.registry) targets.defaults.registry.setGauge("aimock_fixtures_loaded", {}, fixtures.length);
|
|
173
191
|
}
|
|
174
192
|
/**
|
|
193
|
+
* JSON-safe redaction for control-API inspection output. Functions (fixture
|
|
194
|
+
* `predicate`s, response factories) and RegExps do not survive
|
|
195
|
+
* JSON.stringify as anything useful, so they become marker strings.
|
|
196
|
+
*/
|
|
197
|
+
function redactForInspection(value) {
|
|
198
|
+
if (typeof value === "function") return "[function]";
|
|
199
|
+
if (value instanceof RegExp) return String(value);
|
|
200
|
+
if (Array.isArray(value)) return value.map(redactForInspection);
|
|
201
|
+
if (value !== null && typeof value === "object") {
|
|
202
|
+
const out = {};
|
|
203
|
+
for (const [key, entry] of Object.entries(value)) out[key] = redactForInspection(entry);
|
|
204
|
+
return out;
|
|
205
|
+
}
|
|
206
|
+
return value;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* One-line kind label for a fixture response used by
|
|
210
|
+
* `GET /__aimock/fixtures?include=fixtures` (e.g. "text", "error").
|
|
211
|
+
* Response factories are reported as "factory".
|
|
212
|
+
*
|
|
213
|
+
* Discriminates with the same `is*Response` guards the request handlers use,
|
|
214
|
+
* in the same order — NOT by inspecting keys. Every response shape extends
|
|
215
|
+
* `ResponseOverrides` (`id`/`created`/`model`/`usage`), so a recorded fixture's
|
|
216
|
+
* first key is usually an envelope override rather than the discriminant. The
|
|
217
|
+
* audio-before-content/toolCalls order is the ORDERING CONTRACT documented on
|
|
218
|
+
* `AudioResponse` in types.ts: those shapes structurally overlap.
|
|
219
|
+
*/
|
|
220
|
+
function fixtureResponseKind(response) {
|
|
221
|
+
if (require_helpers.isResponseFactory(response)) return "factory";
|
|
222
|
+
if (require_helpers.isErrorResponse(response)) return "error";
|
|
223
|
+
if (require_helpers.isAudioResponse(response)) return "audio";
|
|
224
|
+
if (require_helpers.isVideoResponse(response)) return "video";
|
|
225
|
+
if (require_helpers.isTranscriptionResponse(response)) return "transcription";
|
|
226
|
+
if (require_helpers.isImageResponse(response)) return "image";
|
|
227
|
+
if (require_helpers.isEmbeddingResponse(response)) return "embedding";
|
|
228
|
+
if (require_helpers.isJSONResponse(response)) return "json";
|
|
229
|
+
if (require_helpers.isContentWithToolCallsResponse(response)) return "contentWithToolCalls";
|
|
230
|
+
if (require_helpers.isToolCallResponse(response)) return "toolCalls";
|
|
231
|
+
if (require_helpers.isTextResponse(response)) return "text";
|
|
232
|
+
return "unknown";
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Resolve a journal entry's testId exactly the way `getTestId` resolves an
|
|
236
|
+
* incoming request's: the `X-Test-Id` header wins, then `?testId=` parsed out
|
|
237
|
+
* of the query string, then `DEFAULT_TEST_ID`. The
|
|
238
|
+
* filter and the server's own per-test isolation must never disagree — and a
|
|
239
|
+
* raw `path.includes("testId=t1")` both prefix-collides with `t10` and matches
|
|
240
|
+
* unrelated params like `notTestId`.
|
|
241
|
+
*/
|
|
242
|
+
function journalEntryTestId(entry) {
|
|
243
|
+
const header = entry.headers["x-test-id"];
|
|
244
|
+
if (header) return header;
|
|
245
|
+
const qIdx = entry.path.indexOf("?");
|
|
246
|
+
if (qIdx !== -1) {
|
|
247
|
+
const queryValue = new URLSearchParams(entry.path.slice(qIdx + 1)).get("testId");
|
|
248
|
+
if (queryValue) return queryValue;
|
|
249
|
+
}
|
|
250
|
+
return require_constants.DEFAULT_TEST_ID;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* The testId a chaos override is stored under, and read back with — resolved by
|
|
254
|
+
* `getTestId`, i.e. `X-Test-Id` header then `?testId=`, exactly as
|
|
255
|
+
* `resolveScopedDefaults` resolves the traffic being evaluated. A control call
|
|
256
|
+
* and the requests it is meant to affect can then never land in different
|
|
257
|
+
* scopes. `DEFAULT_TEST_ID` (neither header nor param) means the server-wide
|
|
258
|
+
* baseline.
|
|
259
|
+
*
|
|
260
|
+
* Returns `null` when `X-Test-Id` is PRESENT but blank. `String(testId ?? "")`
|
|
261
|
+
* in a harness produces that trivially, and silently treating it as "untagged"
|
|
262
|
+
* would install a server-wide baseline that fails every other test — the exact
|
|
263
|
+
* cross-test leak per-testId scoping exists to prevent. Callers must 400.
|
|
264
|
+
*/
|
|
265
|
+
function chaosScopeId(req) {
|
|
266
|
+
const headerValue = req.headers["x-test-id"];
|
|
267
|
+
const raw = Array.isArray(headerValue) ? headerValue[0] : headerValue;
|
|
268
|
+
if (typeof raw === "string" && raw.trim() === "") return null;
|
|
269
|
+
return require_helpers.getTestId(req);
|
|
270
|
+
}
|
|
271
|
+
/** 400 for a control call whose `X-Test-Id` is present but blank. */
|
|
272
|
+
function writeBlankTestId(res) {
|
|
273
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
274
|
+
res.end(JSON.stringify({ error: "Invalid 'X-Test-Id': header is present but empty" }));
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
/** The chaos config in effect for one testId: its override, else the baseline. */
|
|
278
|
+
function effectiveChaos(defaults, scopeId) {
|
|
279
|
+
const scoped = defaults.chaosByTestId?.get(scopeId);
|
|
280
|
+
if (scoped) return scoped;
|
|
281
|
+
const current = defaults.chaos;
|
|
282
|
+
if (!current) return {};
|
|
283
|
+
return require_chaos.isChaosScope(current) ? current.base ?? {} : current;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
175
286
|
* Handle requests under `/__aimock/`. Returns `true` if the request was
|
|
176
287
|
* handled, `false` if the path doesn't match the control prefix.
|
|
177
288
|
*/
|
|
178
|
-
async function handleControlAPI(req, res, pathname, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, defaults) {
|
|
289
|
+
async function handleControlAPI(req, res, pathname, searchParams, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, bytePlusVideoJobs, defaults) {
|
|
179
290
|
if (!pathname.startsWith(CONTROL_PREFIX)) return false;
|
|
180
291
|
const subPath = pathname.slice(9);
|
|
181
292
|
setCorsHeaders(res);
|
|
@@ -185,13 +296,148 @@ async function handleControlAPI(req, res, pathname, fixtures, journal, videoStat
|
|
|
185
296
|
return true;
|
|
186
297
|
}
|
|
187
298
|
if (subPath === "/journal" && req.method === "GET") {
|
|
188
|
-
|
|
189
|
-
|
|
299
|
+
const bad = (message) => {
|
|
300
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
301
|
+
res.end(JSON.stringify({ error: message }));
|
|
302
|
+
return true;
|
|
303
|
+
};
|
|
304
|
+
for (const key of searchParams.keys()) if (!JOURNAL_PARAMS.has(key)) return bad(`Unknown query parameter: '${key}'. Supported: ${[...JOURNAL_PARAMS].join(", ")}`);
|
|
305
|
+
const parseNonNegativeInt = (name, fallback) => {
|
|
306
|
+
const raw = searchParams.get(name);
|
|
307
|
+
if (raw === null) return fallback;
|
|
308
|
+
if (!/^\d+$/.test(raw.trim())) return null;
|
|
309
|
+
return Number(raw);
|
|
310
|
+
};
|
|
311
|
+
const limit = parseNonNegativeInt("limit", -1);
|
|
312
|
+
const offset = parseNonNegativeInt("offset", 0);
|
|
313
|
+
if (limit === null) return bad("Invalid 'limit': must be an integer >= 0");
|
|
314
|
+
if (offset === null) return bad("Invalid 'offset': must be an integer >= 0");
|
|
315
|
+
let statusFilter;
|
|
316
|
+
const statusRaw = searchParams.get("status");
|
|
317
|
+
if (statusRaw !== null) {
|
|
318
|
+
if (!/^\d+$/.test(statusRaw.trim())) return bad("Invalid 'status': must be an integer");
|
|
319
|
+
statusFilter = Number(statusRaw);
|
|
320
|
+
}
|
|
321
|
+
const pathFilter = searchParams.get("path");
|
|
322
|
+
const methodFilter = searchParams.get("method");
|
|
323
|
+
const serviceFilter = searchParams.get("service");
|
|
324
|
+
const testIdFilter = searchParams.get("testId");
|
|
325
|
+
let entries = journal.getAll();
|
|
326
|
+
if (methodFilter !== null) {
|
|
327
|
+
const want = methodFilter.toUpperCase();
|
|
328
|
+
entries = entries.filter((e) => e.method.toUpperCase() === want);
|
|
329
|
+
}
|
|
330
|
+
if (pathFilter !== null) entries = entries.filter((e) => e.path.includes(pathFilter));
|
|
331
|
+
if (statusFilter !== void 0) entries = entries.filter((e) => e.response.status === statusFilter);
|
|
332
|
+
if (serviceFilter !== null) entries = entries.filter((e) => e.service === serviceFilter);
|
|
333
|
+
if (testIdFilter !== null) entries = entries.filter((e) => journalEntryTestId(e) === testIdFilter);
|
|
334
|
+
const total = entries.length;
|
|
335
|
+
if (offset > 0) entries = entries.slice(offset);
|
|
336
|
+
if (limit >= 0) entries = entries.slice(0, limit);
|
|
337
|
+
res.writeHead(200, {
|
|
338
|
+
"Content-Type": "application/json",
|
|
339
|
+
"X-Total-Count": String(total)
|
|
340
|
+
});
|
|
341
|
+
res.end(JSON.stringify(entries));
|
|
190
342
|
return true;
|
|
191
343
|
}
|
|
192
344
|
if (subPath === "/fixtures" && req.method === "GET") {
|
|
345
|
+
for (const key of searchParams.keys()) if (!FIXTURES_PARAMS.has(key)) {
|
|
346
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
347
|
+
res.end(JSON.stringify({ error: `Unknown query parameter: '${key}'. Supported: ${[...FIXTURES_PARAMS].join(", ")}` }));
|
|
348
|
+
return true;
|
|
349
|
+
}
|
|
350
|
+
const include = searchParams.get("include");
|
|
351
|
+
if (include === null) {
|
|
352
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
353
|
+
res.end(JSON.stringify({ count: fixtures.length }));
|
|
354
|
+
return true;
|
|
355
|
+
}
|
|
356
|
+
if (include !== "fixtures") {
|
|
357
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
358
|
+
res.end(JSON.stringify({ error: "Invalid 'include': expected 'fixtures'" }));
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
361
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
362
|
+
res.end(JSON.stringify({
|
|
363
|
+
count: fixtures.length,
|
|
364
|
+
fixtures: fixtures.map((fixture, index) => ({
|
|
365
|
+
index,
|
|
366
|
+
match: redactForInspection(fixture.match),
|
|
367
|
+
responseKind: fixtureResponseKind(fixture.response),
|
|
368
|
+
...fixture.latency !== void 0 ? { latency: fixture.latency } : {},
|
|
369
|
+
...fixture.chaos !== void 0 ? { chaos: fixture.chaos } : {}
|
|
370
|
+
}))
|
|
371
|
+
}));
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
if (subPath === "/chaos" && req.method === "GET") {
|
|
375
|
+
const scopeId = chaosScopeId(req);
|
|
376
|
+
if (scopeId === null) return writeBlankTestId(res);
|
|
193
377
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
194
|
-
res.end(JSON.stringify({
|
|
378
|
+
res.end(JSON.stringify({ chaos: effectiveChaos(defaults, scopeId) }));
|
|
379
|
+
return true;
|
|
380
|
+
}
|
|
381
|
+
if (subPath === "/chaos" && req.method === "DELETE") {
|
|
382
|
+
const scopeId = chaosScopeId(req);
|
|
383
|
+
if (scopeId === null) return writeBlankTestId(res);
|
|
384
|
+
defaults.chaosByTestId?.delete(scopeId);
|
|
385
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
386
|
+
res.end(JSON.stringify({ chaos: effectiveChaos(defaults, scopeId) }));
|
|
387
|
+
return true;
|
|
388
|
+
}
|
|
389
|
+
if (subPath === "/chaos" && req.method === "POST") {
|
|
390
|
+
const scopeId = chaosScopeId(req);
|
|
391
|
+
if (scopeId === null) return writeBlankTestId(res);
|
|
392
|
+
let raw;
|
|
393
|
+
try {
|
|
394
|
+
raw = await require_helpers.readBody(req);
|
|
395
|
+
} catch (err) {
|
|
396
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
397
|
+
defaults.logger.error(`POST /__aimock/chaos: failed to read body: ${msg}`);
|
|
398
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
399
|
+
res.end(JSON.stringify({ error: `Failed to read request body: ${msg}` }));
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
let parsed;
|
|
403
|
+
try {
|
|
404
|
+
parsed = JSON.parse(raw);
|
|
405
|
+
} catch (err) {
|
|
406
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
407
|
+
defaults.logger.error(`POST /__aimock/chaos: invalid JSON: ${msg}`);
|
|
408
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
409
|
+
res.end(JSON.stringify({ error: `Invalid JSON: ${msg}` }));
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
413
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
414
|
+
res.end(JSON.stringify({ error: "Invalid body: expected a JSON object" }));
|
|
415
|
+
return true;
|
|
416
|
+
}
|
|
417
|
+
const allowed = [
|
|
418
|
+
"dropRate",
|
|
419
|
+
"malformedRate",
|
|
420
|
+
"disconnectRate"
|
|
421
|
+
];
|
|
422
|
+
for (const key of Object.keys(parsed)) if (!allowed.includes(key)) {
|
|
423
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
424
|
+
res.end(JSON.stringify({ error: `Unknown chaos field: '${key}'` }));
|
|
425
|
+
return true;
|
|
426
|
+
}
|
|
427
|
+
const next = {};
|
|
428
|
+
for (const key of allowed) {
|
|
429
|
+
const value = parsed[key];
|
|
430
|
+
if (value === void 0) continue;
|
|
431
|
+
if (typeof value !== "number" || Number.isNaN(value) || value < 0 || value > 1) {
|
|
432
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
433
|
+
res.end(JSON.stringify({ error: `Invalid '${key}': must be a number between 0 and 1` }));
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
436
|
+
next[key] = value;
|
|
437
|
+
}
|
|
438
|
+
defaults.chaosByTestId?.set(scopeId, next);
|
|
439
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
440
|
+
res.end(JSON.stringify({ chaos: effectiveChaos(defaults, scopeId) }));
|
|
195
441
|
return true;
|
|
196
442
|
}
|
|
197
443
|
if (subPath === "/fixtures" && req.method === "POST") {
|
|
@@ -249,6 +495,7 @@ async function handleControlAPI(req, res, pathname, fixtures, journal, videoStat
|
|
|
249
495
|
openRouterVideoJobs,
|
|
250
496
|
veoVideoJobs,
|
|
251
497
|
grokVideoJobs,
|
|
498
|
+
bytePlusVideoJobs,
|
|
252
499
|
defaults
|
|
253
500
|
});
|
|
254
501
|
if (subPath === "/reset" && req.method === "POST") {
|
|
@@ -299,8 +546,37 @@ async function handleControlAPI(req, res, pathname, fixtures, journal, videoStat
|
|
|
299
546
|
res.end(JSON.stringify({ error: `Invalid JSON: ${msg}` }));
|
|
300
547
|
return true;
|
|
301
548
|
}
|
|
549
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
550
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
551
|
+
res.end(JSON.stringify({ error: "Invalid body: expected a JSON object" }));
|
|
552
|
+
return true;
|
|
553
|
+
}
|
|
302
554
|
const status = parsed.status ?? 500;
|
|
555
|
+
if (!require_fixture_loader.isInjectableStatus(status)) {
|
|
556
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
557
|
+
res.end(JSON.stringify({ error: `Invalid 'status': must be ${require_fixture_loader.INJECTED_STATUS_RANGE}` }));
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
303
560
|
const errorBody = parsed.body;
|
|
561
|
+
if (errorBody !== void 0 && errorBody !== null) {
|
|
562
|
+
if (typeof errorBody !== "object" || Array.isArray(errorBody)) {
|
|
563
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
564
|
+
res.end(JSON.stringify({ error: "Invalid 'body': must be an object" }));
|
|
565
|
+
return true;
|
|
566
|
+
}
|
|
567
|
+
for (const field of [
|
|
568
|
+
"message",
|
|
569
|
+
"type",
|
|
570
|
+
"code"
|
|
571
|
+
]) {
|
|
572
|
+
const value = errorBody[field];
|
|
573
|
+
if (value !== void 0 && value !== null && typeof value !== "string") {
|
|
574
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
575
|
+
res.end(JSON.stringify({ error: `Invalid 'body.${field}': must be a string` }));
|
|
576
|
+
return true;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
304
580
|
const errorFixture = {
|
|
305
581
|
match: { predicate: () => true },
|
|
306
582
|
response: {
|
|
@@ -360,7 +636,6 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
|
|
|
360
636
|
let body;
|
|
361
637
|
try {
|
|
362
638
|
body = JSON.parse(raw);
|
|
363
|
-
if (modelFallback && !body.model) body.model = modelFallback;
|
|
364
639
|
} catch (parseErr) {
|
|
365
640
|
const detail = parseErr instanceof Error ? parseErr.message : "unknown parse error";
|
|
366
641
|
journal.add({
|
|
@@ -381,6 +656,24 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
|
|
|
381
656
|
} }));
|
|
382
657
|
return;
|
|
383
658
|
}
|
|
659
|
+
if (!require_helpers.isJsonObject(body)) {
|
|
660
|
+
journal.add({
|
|
661
|
+
method: req.method ?? "POST",
|
|
662
|
+
path: req.url ?? COMPLETIONS_PATH,
|
|
663
|
+
headers: require_helpers.flattenHeaders(req.headers),
|
|
664
|
+
body: null,
|
|
665
|
+
response: {
|
|
666
|
+
status: 400,
|
|
667
|
+
fixture: null
|
|
668
|
+
}
|
|
669
|
+
});
|
|
670
|
+
require_sse_writer.writeErrorResponse(res, 400, openRouter ? require_openrouter_chat.serializeOpenRouterError(400, "Request body must be a JSON object") : JSON.stringify({ error: {
|
|
671
|
+
message: "Request body must be a JSON object",
|
|
672
|
+
type: "invalid_request_error"
|
|
673
|
+
} }));
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
if (modelFallback && !body.model) body.model = modelFallback;
|
|
384
677
|
if (!Array.isArray(body.messages)) {
|
|
385
678
|
journal.add({
|
|
386
679
|
method: req.method ?? "POST",
|
|
@@ -472,7 +765,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
|
|
|
472
765
|
const snippet = typeof lastUserMsg?.content === "string" ? lastUserMsg.content.slice(0, 80) : "";
|
|
473
766
|
defaults.logger.debug(`No fixture matched for request (model=${body.model ?? "?"}, msg="${snippet}")`);
|
|
474
767
|
}
|
|
475
|
-
const chaosAction = require_chaos.evaluateChaos(fixture, defaults.chaos, req.headers, defaults.logger);
|
|
768
|
+
const chaosAction = require_chaos.evaluateChaos(fixture, defaults.chaos, req.headers, defaults.logger, req.url);
|
|
476
769
|
const chaosContext = {
|
|
477
770
|
method,
|
|
478
771
|
path,
|
|
@@ -769,13 +1062,27 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
769
1062
|
const logger = new require_logger.Logger(options?.logLevel ?? "silent");
|
|
770
1063
|
const registry = options?.metrics ? require_metrics.createMetricsRegistry() : void 0;
|
|
771
1064
|
const serverOptions = options ?? {};
|
|
1065
|
+
const chaosByTestId = /* @__PURE__ */ new Map();
|
|
772
1066
|
const defaults = {
|
|
773
1067
|
latency: serverOptions.latency ?? 0,
|
|
774
1068
|
chunkSize: Math.max(1, serverOptions.chunkSize ?? DEFAULT_CHUNK_SIZE),
|
|
775
1069
|
replaySpeed: serverOptions.replaySpeed ?? 1,
|
|
776
1070
|
logger,
|
|
1071
|
+
chaosByTestId,
|
|
777
1072
|
get chaos() {
|
|
778
|
-
return
|
|
1073
|
+
return {
|
|
1074
|
+
base: chaosByTestId.get(require_constants.DEFAULT_TEST_ID) ?? serverOptions.chaos,
|
|
1075
|
+
byTestId: chaosByTestId
|
|
1076
|
+
};
|
|
1077
|
+
},
|
|
1078
|
+
set chaos(value) {
|
|
1079
|
+
if (value === void 0) {
|
|
1080
|
+
chaosByTestId.clear();
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
const base = require_chaos.isChaosScope(value) ? value.base : value;
|
|
1084
|
+
if (base === void 0) chaosByTestId.delete(require_constants.DEFAULT_TEST_ID);
|
|
1085
|
+
else chaosByTestId.set(require_constants.DEFAULT_TEST_ID, base);
|
|
779
1086
|
},
|
|
780
1087
|
registry,
|
|
781
1088
|
get record() {
|
|
@@ -798,6 +1105,9 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
798
1105
|
},
|
|
799
1106
|
get grokVideo() {
|
|
800
1107
|
return serverOptions.grokVideo;
|
|
1108
|
+
},
|
|
1109
|
+
get bytePlusVideo() {
|
|
1110
|
+
return serverOptions.bytePlusVideo;
|
|
801
1111
|
}
|
|
802
1112
|
};
|
|
803
1113
|
if (options?.chaos) {
|
|
@@ -833,6 +1143,10 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
833
1143
|
{
|
|
834
1144
|
name: "grokVideo",
|
|
835
1145
|
config: options?.grokVideo
|
|
1146
|
+
},
|
|
1147
|
+
{
|
|
1148
|
+
name: "bytePlusVideo",
|
|
1149
|
+
config: options?.bytePlusVideo
|
|
836
1150
|
}
|
|
837
1151
|
]) {
|
|
838
1152
|
if (!config) continue;
|
|
@@ -847,6 +1161,16 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
847
1161
|
const cap = options?.record?.openRouterVideo?.maxContentBytes;
|
|
848
1162
|
if (cap !== void 0 && (!Number.isInteger(cap) || cap < 0)) logger.warn(`record.openRouterVideo.maxContentBytes (${cap}) is not a non-negative integer — using the default cap (${require_openrouter_video.OPENROUTER_VIDEO_DEFAULT_MAX_CONTENT_BYTES})`);
|
|
849
1163
|
}
|
|
1164
|
+
{
|
|
1165
|
+
const bytePlusBase = options?.record?.providers?.byteplus;
|
|
1166
|
+
if (bytePlusBase !== void 0) {
|
|
1167
|
+
let basePath;
|
|
1168
|
+
try {
|
|
1169
|
+
basePath = new URL(bytePlusBase).pathname;
|
|
1170
|
+
} catch {}
|
|
1171
|
+
if (basePath !== void 0 && /(^|\/)api\/v3\/?$/.test(basePath)) throw new Error(`record.providers.byteplus (${bytePlusBase}) ends in /api/v3, but aimock appends the /api/v3 prefix itself — every BytePlus request would go to /api/v3/api/v3/... and fail upstream. Configure the ORIGIN only (e.g. https://ark.ap-southeast.bytepluses.com).`);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
850
1174
|
const journal = new require_journal.Journal({
|
|
851
1175
|
maxEntries: options?.journalMaxEntries ?? 1e3,
|
|
852
1176
|
fixtureCountsMaxTestIds: options?.fixtureCountsMaxTestIds ?? 500
|
|
@@ -855,6 +1179,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
855
1179
|
const openRouterVideoJobs = new require_openrouter_video.OpenRouterVideoJobMap();
|
|
856
1180
|
const veoVideoJobs = new require_veo_video.VeoVideoJobMap();
|
|
857
1181
|
const grokVideoJobs = new require_grok_video.GrokVideoJobMap();
|
|
1182
|
+
const bytePlusVideoJobs = new require_byteplus_video.BytePlusVideoJobMap();
|
|
858
1183
|
if (mounts) for (const { handler } of mounts) {
|
|
859
1184
|
if (handler.setJournal) handler.setJournal(journal);
|
|
860
1185
|
if (registry && handler.setRegistry) handler.setRegistry(registry);
|
|
@@ -880,7 +1205,9 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
880
1205
|
const startTime = registry ? process.hrtime.bigint() : 0n;
|
|
881
1206
|
const parsedUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
|
|
882
1207
|
let pathname = parsedUrl.pathname;
|
|
883
|
-
const
|
|
1208
|
+
const originalPathname = pathname;
|
|
1209
|
+
const isOpenRouter = require_openrouter_chat.isOpenRouterPath(originalPathname);
|
|
1210
|
+
const isBytePlusArk = defaults.record?.providers.byteplus !== void 0 && originalPathname.startsWith("/api/v3/");
|
|
884
1211
|
if (registry) res.on("finish", () => {
|
|
885
1212
|
try {
|
|
886
1213
|
const normalizedPath = require_metrics.normalizePathLabel(pathname);
|
|
@@ -912,7 +1239,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
912
1239
|
require_api_key_auth.markAuthenticatedRequest(req, resolvedAuth.policy);
|
|
913
1240
|
}
|
|
914
1241
|
if (pathname.startsWith(CONTROL_PREFIX)) {
|
|
915
|
-
await handleControlAPI(req, res, pathname, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, defaults);
|
|
1242
|
+
await handleControlAPI(req, res, pathname, parsedUrl.searchParams, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, bytePlusVideoJobs, defaults);
|
|
916
1243
|
return;
|
|
917
1244
|
}
|
|
918
1245
|
if (mounts) {
|
|
@@ -1095,6 +1422,66 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
1095
1422
|
}
|
|
1096
1423
|
return;
|
|
1097
1424
|
}
|
|
1425
|
+
const bytePlusVideoStatusMatch = pathname.match(require_metrics.BYTEPLUS_VIDEO_STATUS_RE);
|
|
1426
|
+
if (bytePlusVideoStatusMatch && req.method === "GET") {
|
|
1427
|
+
try {
|
|
1428
|
+
await require_byteplus_video.handleBytePlusVideoStatus(req, res, bytePlusVideoStatusMatch[1], fixtures, journal, defaults, setCorsHeaders, bytePlusVideoJobs);
|
|
1429
|
+
} catch (err) {
|
|
1430
|
+
const msg = err instanceof Error ? err.message : "Internal error";
|
|
1431
|
+
defaults.logger.error(`byteplus-video status: ${msg}`);
|
|
1432
|
+
if (!res.headersSent) {
|
|
1433
|
+
try {
|
|
1434
|
+
journal.add({
|
|
1435
|
+
method: req.method ?? "GET",
|
|
1436
|
+
path: req.url ?? pathname,
|
|
1437
|
+
headers: require_helpers.flattenHeaders(req.headers),
|
|
1438
|
+
body: null,
|
|
1439
|
+
response: {
|
|
1440
|
+
status: 500,
|
|
1441
|
+
fixture: null
|
|
1442
|
+
}
|
|
1443
|
+
});
|
|
1444
|
+
} catch (jErr) {
|
|
1445
|
+
defaults.logger.warn(`byteplus-video status: journal write failed after handler error: ${jErr instanceof Error ? jErr.message : String(jErr)}`);
|
|
1446
|
+
}
|
|
1447
|
+
require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
1448
|
+
message: msg,
|
|
1449
|
+
type: "server_error"
|
|
1450
|
+
} }));
|
|
1451
|
+
} else if (!res.writableEnded) res.destroy();
|
|
1452
|
+
}
|
|
1453
|
+
return;
|
|
1454
|
+
}
|
|
1455
|
+
if (require_metrics.BYTEPLUS_VIDEO_SUBMIT_RE.test(pathname) && req.method === "POST") {
|
|
1456
|
+
setCorsHeaders(res);
|
|
1457
|
+
try {
|
|
1458
|
+
await require_byteplus_video.handleBytePlusVideoCreate(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, bytePlusVideoJobs);
|
|
1459
|
+
} catch (err) {
|
|
1460
|
+
const msg = err instanceof Error ? err.message : "Internal error";
|
|
1461
|
+
defaults.logger.error(`byteplus-video submit: ${msg}`);
|
|
1462
|
+
if (!res.headersSent) {
|
|
1463
|
+
try {
|
|
1464
|
+
journal.add({
|
|
1465
|
+
method: req.method ?? "POST",
|
|
1466
|
+
path: req.url ?? pathname,
|
|
1467
|
+
headers: require_helpers.flattenHeaders(req.headers),
|
|
1468
|
+
body: null,
|
|
1469
|
+
response: {
|
|
1470
|
+
status: 500,
|
|
1471
|
+
fixture: null
|
|
1472
|
+
}
|
|
1473
|
+
});
|
|
1474
|
+
} catch (jErr) {
|
|
1475
|
+
defaults.logger.warn(`byteplus-video submit: journal write failed after handler error: ${jErr instanceof Error ? jErr.message : String(jErr)}`);
|
|
1476
|
+
}
|
|
1477
|
+
require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
1478
|
+
message: msg,
|
|
1479
|
+
type: "server_error"
|
|
1480
|
+
} }));
|
|
1481
|
+
} else if (!res.writableEnded) res.destroy();
|
|
1482
|
+
}
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1098
1485
|
if (pathname === "/api/v1/models" && req.method === "GET") {
|
|
1099
1486
|
require_openrouter_chat.handleOpenRouterModels(req, res, fixtures, journal, defaults, setCorsHeaders);
|
|
1100
1487
|
return;
|
|
@@ -1293,7 +1680,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
1293
1680
|
}
|
|
1294
1681
|
if (pathname === IMAGES_PATH && req.method === "POST") {
|
|
1295
1682
|
try {
|
|
1296
|
-
await require_images.handleImages(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
|
|
1683
|
+
await require_images.handleImages(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, "openai", void 0, isBytePlusArk ? "byteplus" : void 0);
|
|
1297
1684
|
} catch (err) {
|
|
1298
1685
|
const msg = err instanceof Error ? err.message : "Internal error";
|
|
1299
1686
|
if (!res.headersSent) require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
@@ -1744,7 +2131,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
1744
2131
|
try {
|
|
1745
2132
|
falBody = req.method === "POST" || req.method === "PUT" ? await require_helpers.readBody(req) : "";
|
|
1746
2133
|
const raw = falBody;
|
|
1747
|
-
const chaosAction = require_chaos.evaluateChaos(null, defaults.chaos, req.headers, defaults.logger);
|
|
2134
|
+
const chaosAction = require_chaos.evaluateChaos(null, defaults.chaos, req.headers, defaults.logger, req.url);
|
|
1748
2135
|
if (chaosAction) {
|
|
1749
2136
|
require_chaos.applyChaosAction(chaosAction, res, null, journal, {
|
|
1750
2137
|
method: req.method ?? "GET",
|
|
@@ -1786,7 +2173,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
1786
2173
|
setCorsHeaders(res);
|
|
1787
2174
|
try {
|
|
1788
2175
|
const raw = req.method === "POST" || req.method === "PUT" ? falBody ?? await require_helpers.readBody(req) : "{}";
|
|
1789
|
-
const chaosAction = require_chaos.evaluateChaos(null, defaults.chaos, req.headers, defaults.logger);
|
|
2176
|
+
const chaosAction = require_chaos.evaluateChaos(null, defaults.chaos, req.headers, defaults.logger, req.url);
|
|
1790
2177
|
if (chaosAction) {
|
|
1791
2178
|
require_chaos.applyChaosAction(chaosAction, res, null, journal, {
|
|
1792
2179
|
method: req.method ?? "GET",
|
|
@@ -1832,7 +2219,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
1832
2219
|
handleNotFound(res, "Not found");
|
|
1833
2220
|
return;
|
|
1834
2221
|
}
|
|
1835
|
-
const completionsProvider = azureDeploymentId ? "azure" : isOpenRouter ? "openrouter" : "openai";
|
|
2222
|
+
const completionsProvider = azureDeploymentId ? "azure" : isOpenRouter ? "openrouter" : isBytePlusArk ? "byteplus" : "openai";
|
|
1836
2223
|
try {
|
|
1837
2224
|
await handleCompletions(req, res, fixtures, journal, defaults, azureDeploymentId, completionsProvider, isOpenRouter);
|
|
1838
2225
|
} catch (err) {
|
|
@@ -1970,6 +2357,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
1970
2357
|
openRouterVideoJobs.clear();
|
|
1971
2358
|
veoVideoJobs.clear();
|
|
1972
2359
|
grokVideoJobs.clear();
|
|
2360
|
+
bytePlusVideoJobs.clear();
|
|
1973
2361
|
originalClose(callback);
|
|
1974
2362
|
return this;
|
|
1975
2363
|
};
|
|
@@ -1993,7 +2381,8 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
|
|
|
1993
2381
|
videoStates,
|
|
1994
2382
|
openRouterVideoJobs,
|
|
1995
2383
|
veoVideoJobs,
|
|
1996
|
-
grokVideoJobs
|
|
2384
|
+
grokVideoJobs,
|
|
2385
|
+
bytePlusVideoJobs
|
|
1997
2386
|
});
|
|
1998
2387
|
});
|
|
1999
2388
|
});
|