@copilotkit/aimock 1.39.0 → 1.41.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.
Files changed (88) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +46 -0
  4. package/README.md +4 -2
  5. package/dist/agui-stub.d.cts +2 -2
  6. package/dist/agui-stub.d.ts +2 -2
  7. package/dist/agui-types.d.cts +66 -3
  8. package/dist/agui-types.d.cts.map +1 -1
  9. package/dist/agui-types.d.ts +66 -3
  10. package/dist/agui-types.d.ts.map +1 -1
  11. package/dist/byteplus-video.cjs +954 -0
  12. package/dist/byteplus-video.cjs.map +1 -0
  13. package/dist/byteplus-video.d.cts +176 -0
  14. package/dist/byteplus-video.d.cts.map +1 -0
  15. package/dist/byteplus-video.d.ts +176 -0
  16. package/dist/byteplus-video.d.ts.map +1 -0
  17. package/dist/byteplus-video.js +947 -0
  18. package/dist/byteplus-video.js.map +1 -0
  19. package/dist/cli.cjs +5 -1
  20. package/dist/cli.cjs.map +1 -1
  21. package/dist/cli.js +5 -1
  22. package/dist/cli.js.map +1 -1
  23. package/dist/helpers.cjs +8 -4
  24. package/dist/helpers.cjs.map +1 -1
  25. package/dist/helpers.d.cts.map +1 -1
  26. package/dist/helpers.d.ts.map +1 -1
  27. package/dist/helpers.js +8 -4
  28. package/dist/helpers.js.map +1 -1
  29. package/dist/images.cjs +2 -2
  30. package/dist/images.cjs.map +1 -1
  31. package/dist/images.d.cts +11 -3
  32. package/dist/images.d.cts.map +1 -1
  33. package/dist/images.d.ts +11 -3
  34. package/dist/images.d.ts.map +1 -1
  35. package/dist/images.js +2 -2
  36. package/dist/images.js.map +1 -1
  37. package/dist/index.cjs +7 -0
  38. package/dist/index.d.cts +3 -2
  39. package/dist/index.d.ts +3 -2
  40. package/dist/index.js +2 -1
  41. package/dist/metrics.cjs +20 -0
  42. package/dist/metrics.cjs.map +1 -1
  43. package/dist/metrics.d.cts.map +1 -1
  44. package/dist/metrics.d.ts.map +1 -1
  45. package/dist/metrics.js +19 -1
  46. package/dist/metrics.js.map +1 -1
  47. package/dist/openrouter-chat.cjs +41 -0
  48. package/dist/openrouter-chat.cjs.map +1 -1
  49. package/dist/openrouter-chat.js +41 -0
  50. package/dist/openrouter-chat.js.map +1 -1
  51. package/dist/provider-auth.cjs +2 -0
  52. package/dist/provider-auth.cjs.map +1 -1
  53. package/dist/provider-auth.js +2 -0
  54. package/dist/provider-auth.js.map +1 -1
  55. package/dist/recorder.cjs +77 -8
  56. package/dist/recorder.cjs.map +1 -1
  57. package/dist/recorder.d.cts.map +1 -1
  58. package/dist/recorder.d.ts.map +1 -1
  59. package/dist/recorder.js +77 -8
  60. package/dist/recorder.js.map +1 -1
  61. package/dist/router.cjs +1 -0
  62. package/dist/router.cjs.map +1 -1
  63. package/dist/router.d.cts.map +1 -1
  64. package/dist/router.d.ts.map +1 -1
  65. package/dist/router.js +1 -0
  66. package/dist/router.js.map +1 -1
  67. package/dist/server.cjs +137 -6
  68. package/dist/server.cjs.map +1 -1
  69. package/dist/server.d.cts +2 -0
  70. package/dist/server.d.cts.map +1 -1
  71. package/dist/server.d.ts +2 -0
  72. package/dist/server.d.ts.map +1 -1
  73. package/dist/server.js +138 -7
  74. package/dist/server.js.map +1 -1
  75. package/dist/stream-collapse.cjs +21 -6
  76. package/dist/stream-collapse.cjs.map +1 -1
  77. package/dist/stream-collapse.d.cts +16 -0
  78. package/dist/stream-collapse.d.cts.map +1 -1
  79. package/dist/stream-collapse.d.ts +16 -0
  80. package/dist/stream-collapse.d.ts.map +1 -1
  81. package/dist/stream-collapse.js +21 -6
  82. package/dist/stream-collapse.js.map +1 -1
  83. package/dist/types.d.cts +41 -6
  84. package/dist/types.d.cts.map +1 -1
  85. package/dist/types.d.ts +41 -6
  86. package/dist/types.d.ts.map +1 -1
  87. package/dist/vector-types.d.cts.map +1 -1
  88. package/package.json +4 -3
package/dist/server.d.cts CHANGED
@@ -7,6 +7,7 @@ import { VideoStateMap } from "./video.cjs";
7
7
  import { OpenRouterVideoJobMap } from "./openrouter-video.cjs";
8
8
  import { VeoVideoJobMap } from "./veo-video.cjs";
9
9
  import { GrokVideoJobMap } from "./grok-video.cjs";
10
+ import { BytePlusVideoJobMap } from "./byteplus-video.cjs";
10
11
  import * as http$1 from "node:http";
11
12
 
12
13
  //#region src/server.d.ts
@@ -19,6 +20,7 @@ interface ServerInstance {
19
20
  openRouterVideoJobs: OpenRouterVideoJobMap;
20
21
  veoVideoJobs: VeoVideoJobMap;
21
22
  grokVideoJobs: GrokVideoJobMap;
23
+ bytePlusVideoJobs: BytePlusVideoJobMap;
22
24
  }
23
25
  /**
24
26
  * The per-server state a full reset clears. `ServerInstance` structurally
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.cts","names":[],"sources":["../src/server.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;UAyHiB,cAAA;EAAA,MAAA,EACP,MAAA,CAAK,MADgB;EAAA,OAAA,EAEpB,OAFoB;KACrB,EAAA,MAAK;UACJ,EAEC,eAFD;aAEC,EACG,aADH;qBACG,EACQ,qBADR;cACQ,EACP,cADO;eACP,EACC,eADD;;;AAorChB;;;;;UAAiB,eAAA;UACP;UACA;cACI;;iBAMQ,YAAA,WACV,qBACA,4BACD;;WAA+B;sBACtB,kBACjB,QAAQ"}
1
+ {"version":3,"file":"server.d.cts","names":[],"sources":["../src/server.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;UAgIiB,cAAA;EAAA,MAAA,EACP,MAAA,CAAK,MADgB;EAAA,OAAA,EAEpB,OAFoB;KACrB,EAAA,MAAK;UACJ,EAEC,eAFD;aAEC,EACG,aADH;qBACG,EACQ,qBADR;cACQ,EACP,cADO;eACP,EACC,eADD;mBACC,EACI,mBADJ;;;AA+rCjB;;;;;UAAiB,eAAA;UACP;UACA;cACI;;iBAMQ,YAAA,WACV,qBACA,4BACD;;WAA+B;sBACtB,kBACjB,QAAQ"}
package/dist/server.d.ts CHANGED
@@ -7,6 +7,7 @@ import { VideoStateMap } from "./video.js";
7
7
  import { OpenRouterVideoJobMap } from "./openrouter-video.js";
8
8
  import { VeoVideoJobMap } from "./veo-video.js";
9
9
  import { GrokVideoJobMap } from "./grok-video.js";
10
+ import { BytePlusVideoJobMap } from "./byteplus-video.js";
10
11
  import * as http$1 from "node:http";
11
12
 
12
13
  //#region src/server.d.ts
@@ -19,6 +20,7 @@ interface ServerInstance {
19
20
  openRouterVideoJobs: OpenRouterVideoJobMap;
20
21
  veoVideoJobs: VeoVideoJobMap;
21
22
  grokVideoJobs: GrokVideoJobMap;
23
+ bytePlusVideoJobs: BytePlusVideoJobMap;
22
24
  }
23
25
  /**
24
26
  * The per-server state a full reset clears. `ServerInstance` structurally
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","names":[],"sources":["../src/server.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;UAyHiB,cAAA;EAAA,MAAA,EACP,MAAA,CAAK,MADgB;EAAA,OAAA,EAEpB,OAFoB;KACrB,EAAA,MAAK;UACJ,EAEC,eAFD;aAEC,EACG,aADH;qBACG,EACQ,qBADR;cACQ,EACP,cADO;eACP,EACC,eADD;;;AAorChB;;;;;UAAiB,eAAA;UACP;UACA;cACI;;iBAMQ,YAAA,WACV,qBACA,4BACD;;WAA+B;sBACtB,kBACjB,QAAQ"}
1
+ {"version":3,"file":"server.d.ts","names":[],"sources":["../src/server.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;UAgIiB,cAAA;EAAA,MAAA,EACP,MAAA,CAAK,MADgB;EAAA,OAAA,EAEpB,OAFoB;KACrB,EAAA,MAAK;UACJ,EAEC,eAFD;aAEC,EACG,aADH;qBACG,EACQ,qBADR;cACQ,EACP,cADO;eACP,EACC,eADD;mBACC,EACI,mBADJ;;;AA+rCjB;;;;;UAAiB,eAAA;UACP;UACA;cACI;;iBAMQ,YAAA,WACV,qBACA,4BACD;;WAA+B;sBACtB,kBACjB,QAAQ"}
package/dist/server.js CHANGED
@@ -26,6 +26,7 @@ import { falQueueStates, handleFal } from "./fal.js";
26
26
  import { OPENROUTER_VIDEO_DEFAULT_MAX_CONTENT_BYTES, OpenRouterVideoJobMap, handleOpenRouterVideoContent, handleOpenRouterVideoCreate, handleOpenRouterVideoModels, handleOpenRouterVideoStatus } from "./openrouter-video.js";
27
27
  import { VeoVideoJobMap, handleVeoVideoCreate, handleVeoVideoStatus } from "./veo-video.js";
28
28
  import { GrokVideoJobMap, handleGrokVideoCreate, handleGrokVideoStatus } from "./grok-video.js";
29
+ import { BytePlusVideoJobMap, handleBytePlusVideoCreate, handleBytePlusVideoStatus } from "./byteplus-video.js";
29
30
  import { handleElevenLabsAudio, handleElevenLabsTTS } from "./elevenlabs-audio.js";
30
31
  import { handleOllama, handleOllamaEmbeddings, handleOllamaGenerate } from "./ollama.js";
31
32
  import { handleCohere, handleCohereEmbed } from "./cohere.js";
@@ -36,7 +37,7 @@ import { upgradeToWebSocket } from "./ws-framing.js";
36
37
  import { handleWebSocketResponses } from "./ws-responses.js";
37
38
  import { handleWebSocketRealtime } from "./ws-realtime.js";
38
39
  import { handleWebSocketGeminiLive } from "./ws-gemini-live.js";
39
- import { GROK_VIDEO_STATUS_RE, GROK_VIDEO_SUBMIT_PATH, OPENROUTER_VIDEO_CONTENT_RE, OPENROUTER_VIDEO_STATUS_RE, VEO_OPERATION_RE, VEO_PREDICT_LRO_RE, createMetricsRegistry, normalizePathLabel } from "./metrics.js";
40
+ import { BYTEPLUS_VIDEO_STATUS_RE, BYTEPLUS_VIDEO_SUBMIT_RE, GROK_VIDEO_STATUS_RE, GROK_VIDEO_SUBMIT_PATH, OPENROUTER_VIDEO_CONTENT_RE, OPENROUTER_VIDEO_STATUS_RE, VEO_OPERATION_RE, VEO_PREDICT_LRO_RE, createMetricsRegistry, normalizePathLabel } from "./metrics.js";
40
41
  import * as http$1 from "node:http";
41
42
 
42
43
  //#region src/server.ts
@@ -167,13 +168,14 @@ function performFullReset(fixtures, targets) {
167
168
  targets.openRouterVideoJobs.clear();
168
169
  targets.veoVideoJobs.clear();
169
170
  targets.grokVideoJobs.clear();
171
+ targets.bytePlusVideoJobs.clear();
170
172
  if (targets.defaults.registry) targets.defaults.registry.setGauge("aimock_fixtures_loaded", {}, fixtures.length);
171
173
  }
172
174
  /**
173
175
  * Handle requests under `/__aimock/`. Returns `true` if the request was
174
176
  * handled, `false` if the path doesn't match the control prefix.
175
177
  */
176
- async function handleControlAPI(req, res, pathname, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, defaults) {
178
+ async function handleControlAPI(req, res, pathname, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, bytePlusVideoJobs, defaults) {
177
179
  if (!pathname.startsWith(CONTROL_PREFIX)) return false;
178
180
  const subPath = pathname.slice(9);
179
181
  setCorsHeaders(res);
@@ -187,6 +189,11 @@ async function handleControlAPI(req, res, pathname, fixtures, journal, videoStat
187
189
  res.end(JSON.stringify(journal.getAll()));
188
190
  return true;
189
191
  }
192
+ if (subPath === "/fixtures" && req.method === "GET") {
193
+ res.writeHead(200, { "Content-Type": "application/json" });
194
+ res.end(JSON.stringify({ count: fixtures.length }));
195
+ return true;
196
+ }
190
197
  if (subPath === "/fixtures" && req.method === "POST") {
191
198
  let raw;
192
199
  try {
@@ -242,6 +249,7 @@ async function handleControlAPI(req, res, pathname, fixtures, journal, videoStat
242
249
  openRouterVideoJobs,
243
250
  veoVideoJobs,
244
251
  grokVideoJobs,
252
+ bytePlusVideoJobs,
245
253
  defaults
246
254
  });
247
255
  if (subPath === "/reset" && req.method === "POST") {
@@ -791,6 +799,9 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
791
799
  },
792
800
  get grokVideo() {
793
801
  return serverOptions.grokVideo;
802
+ },
803
+ get bytePlusVideo() {
804
+ return serverOptions.bytePlusVideo;
794
805
  }
795
806
  };
796
807
  if (options?.chaos) {
@@ -826,6 +837,10 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
826
837
  {
827
838
  name: "grokVideo",
828
839
  config: options?.grokVideo
840
+ },
841
+ {
842
+ name: "bytePlusVideo",
843
+ config: options?.bytePlusVideo
829
844
  }
830
845
  ]) {
831
846
  if (!config) continue;
@@ -840,6 +855,16 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
840
855
  const cap = options?.record?.openRouterVideo?.maxContentBytes;
841
856
  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 (${OPENROUTER_VIDEO_DEFAULT_MAX_CONTENT_BYTES})`);
842
857
  }
858
+ {
859
+ const bytePlusBase = options?.record?.providers?.byteplus;
860
+ if (bytePlusBase !== void 0) {
861
+ let basePath;
862
+ try {
863
+ basePath = new URL(bytePlusBase).pathname;
864
+ } catch {}
865
+ 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).`);
866
+ }
867
+ }
843
868
  const journal = new Journal({
844
869
  maxEntries: options?.journalMaxEntries ?? 1e3,
845
870
  fixtureCountsMaxTestIds: options?.fixtureCountsMaxTestIds ?? 500
@@ -848,6 +873,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
848
873
  const openRouterVideoJobs = new OpenRouterVideoJobMap();
849
874
  const veoVideoJobs = new VeoVideoJobMap();
850
875
  const grokVideoJobs = new GrokVideoJobMap();
876
+ const bytePlusVideoJobs = new BytePlusVideoJobMap();
851
877
  if (mounts) for (const { handler } of mounts) {
852
878
  if (handler.setJournal) handler.setJournal(journal);
853
879
  if (registry && handler.setRegistry) handler.setRegistry(registry);
@@ -873,7 +899,9 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
873
899
  const startTime = registry ? process.hrtime.bigint() : 0n;
874
900
  const parsedUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
875
901
  let pathname = parsedUrl.pathname;
876
- const isOpenRouter = isOpenRouterPath(pathname);
902
+ const originalPathname = pathname;
903
+ const isOpenRouter = isOpenRouterPath(originalPathname);
904
+ const isBytePlusArk = defaults.record?.providers.byteplus !== void 0 && originalPathname.startsWith("/api/v3/");
877
905
  if (registry) res.on("finish", () => {
878
906
  try {
879
907
  const normalizedPath = normalizePathLabel(pathname);
@@ -905,7 +933,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
905
933
  markAuthenticatedRequest(req, resolvedAuth.policy);
906
934
  }
907
935
  if (pathname.startsWith(CONTROL_PREFIX)) {
908
- await handleControlAPI(req, res, pathname, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, defaults);
936
+ await handleControlAPI(req, res, pathname, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, bytePlusVideoJobs, defaults);
909
937
  return;
910
938
  }
911
939
  if (mounts) {
@@ -1088,6 +1116,66 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1088
1116
  }
1089
1117
  return;
1090
1118
  }
1119
+ const bytePlusVideoStatusMatch = pathname.match(BYTEPLUS_VIDEO_STATUS_RE);
1120
+ if (bytePlusVideoStatusMatch && req.method === "GET") {
1121
+ try {
1122
+ await handleBytePlusVideoStatus(req, res, bytePlusVideoStatusMatch[1], fixtures, journal, defaults, setCorsHeaders, bytePlusVideoJobs);
1123
+ } catch (err) {
1124
+ const msg = err instanceof Error ? err.message : "Internal error";
1125
+ defaults.logger.error(`byteplus-video status: ${msg}`);
1126
+ if (!res.headersSent) {
1127
+ try {
1128
+ journal.add({
1129
+ method: req.method ?? "GET",
1130
+ path: req.url ?? pathname,
1131
+ headers: flattenHeaders(req.headers),
1132
+ body: null,
1133
+ response: {
1134
+ status: 500,
1135
+ fixture: null
1136
+ }
1137
+ });
1138
+ } catch (jErr) {
1139
+ defaults.logger.warn(`byteplus-video status: journal write failed after handler error: ${jErr instanceof Error ? jErr.message : String(jErr)}`);
1140
+ }
1141
+ writeErrorResponse(res, 500, JSON.stringify({ error: {
1142
+ message: msg,
1143
+ type: "server_error"
1144
+ } }));
1145
+ } else if (!res.writableEnded) res.destroy();
1146
+ }
1147
+ return;
1148
+ }
1149
+ if (BYTEPLUS_VIDEO_SUBMIT_RE.test(pathname) && req.method === "POST") {
1150
+ setCorsHeaders(res);
1151
+ try {
1152
+ await handleBytePlusVideoCreate(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders, bytePlusVideoJobs);
1153
+ } catch (err) {
1154
+ const msg = err instanceof Error ? err.message : "Internal error";
1155
+ defaults.logger.error(`byteplus-video submit: ${msg}`);
1156
+ if (!res.headersSent) {
1157
+ try {
1158
+ journal.add({
1159
+ method: req.method ?? "POST",
1160
+ path: req.url ?? pathname,
1161
+ headers: flattenHeaders(req.headers),
1162
+ body: null,
1163
+ response: {
1164
+ status: 500,
1165
+ fixture: null
1166
+ }
1167
+ });
1168
+ } catch (jErr) {
1169
+ defaults.logger.warn(`byteplus-video submit: journal write failed after handler error: ${jErr instanceof Error ? jErr.message : String(jErr)}`);
1170
+ }
1171
+ writeErrorResponse(res, 500, JSON.stringify({ error: {
1172
+ message: msg,
1173
+ type: "server_error"
1174
+ } }));
1175
+ } else if (!res.writableEnded) res.destroy();
1176
+ }
1177
+ return;
1178
+ }
1091
1179
  if (pathname === "/api/v1/models" && req.method === "GET") {
1092
1180
  handleOpenRouterModels(req, res, fixtures, journal, defaults, setCorsHeaders);
1093
1181
  return;
@@ -1286,7 +1374,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1286
1374
  }
1287
1375
  if (pathname === IMAGES_PATH && req.method === "POST") {
1288
1376
  try {
1289
- await handleImages(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
1377
+ await handleImages(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders, "openai", void 0, isBytePlusArk ? "byteplus" : void 0);
1290
1378
  } catch (err) {
1291
1379
  const msg = err instanceof Error ? err.message : "Internal error";
1292
1380
  if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
@@ -1825,7 +1913,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1825
1913
  handleNotFound(res, "Not found");
1826
1914
  return;
1827
1915
  }
1828
- const completionsProvider = azureDeploymentId ? "azure" : isOpenRouter ? "openrouter" : "openai";
1916
+ const completionsProvider = azureDeploymentId ? "azure" : isOpenRouter ? "openrouter" : isBytePlusArk ? "byteplus" : "openai";
1829
1917
  try {
1830
1918
  await handleCompletions(req, res, fixtures, journal, defaults, azureDeploymentId, completionsProvider, isOpenRouter);
1831
1919
  } catch (err) {
@@ -1853,7 +1941,48 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1853
1941
  if (!socket.destroyed) socket.destroy();
1854
1942
  });
1855
1943
  });
1944
+ /**
1945
+ * Body bytes the platform already parsed onto `req` for an upgrade request.
1946
+ *
1947
+ * Node >= 26 delivers an upgrade request's body here and leaves `head`
1948
+ * empty; Node <= 24 leaves the body in `head` and ends `req` with nothing.
1949
+ * The stream has already ended in both cases, so this resolves on the next
1950
+ * tick either way — it never waits on the network.
1951
+ */
1952
+ function drainParsedRequestBody(req) {
1953
+ return new Promise((resolve) => {
1954
+ const chunks = [];
1955
+ let settled = false;
1956
+ const done = () => {
1957
+ if (settled) return;
1958
+ settled = true;
1959
+ resolve(Buffer.concat(chunks));
1960
+ };
1961
+ req.on("data", (c) => chunks.push(c));
1962
+ req.on("end", done);
1963
+ req.on("error", done);
1964
+ req.on("close", done);
1965
+ req.resume();
1966
+ });
1967
+ }
1856
1968
  async function handleUpgradeRequest(req, socket, head) {
1969
+ if ((req.headers.upgrade ?? "").toLowerCase() !== "websocket") {
1970
+ const parsedBody = await drainParsedRequestBody(req);
1971
+ const requestLine = `${req.method} ${req.url} HTTP/${req.httpVersion}\r\n`;
1972
+ const headerLines = [];
1973
+ for (let i = 0; i < req.rawHeaders.length; i += 2) {
1974
+ if (/^(?:upgrade|connection)$/i.test(req.rawHeaders[i])) continue;
1975
+ headerLines.push(`${req.rawHeaders[i]}: ${req.rawHeaders[i + 1]}`);
1976
+ }
1977
+ const rebuilt = Buffer.from(requestLine + headerLines.join("\r\n") + "\r\n\r\n");
1978
+ socket.unshift(Buffer.concat([
1979
+ rebuilt,
1980
+ parsedBody,
1981
+ head
1982
+ ]));
1983
+ server.emit("connection", socket);
1984
+ return;
1985
+ }
1857
1986
  const parsedUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
1858
1987
  let pathname = parsedUrl.pathname;
1859
1988
  if (!validateRequestApiKey(req, resolvedAuth.policy).ok) {
@@ -1922,6 +2051,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1922
2051
  openRouterVideoJobs.clear();
1923
2052
  veoVideoJobs.clear();
1924
2053
  grokVideoJobs.clear();
2054
+ bytePlusVideoJobs.clear();
1925
2055
  originalClose(callback);
1926
2056
  return this;
1927
2057
  };
@@ -1945,7 +2075,8 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1945
2075
  videoStates,
1946
2076
  openRouterVideoJobs,
1947
2077
  veoVideoJobs,
1948
- grokVideoJobs
2078
+ grokVideoJobs,
2079
+ bytePlusVideoJobs
1949
2080
  });
1950
2081
  });
1951
2082
  });