@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.cjs CHANGED
@@ -27,6 +27,7 @@ const require_fal = require('./fal.cjs');
27
27
  const require_openrouter_video = require('./openrouter-video.cjs');
28
28
  const require_veo_video = require('./veo-video.cjs');
29
29
  const require_grok_video = require('./grok-video.cjs');
30
+ const require_byteplus_video = require('./byteplus-video.cjs');
30
31
  const require_elevenlabs_audio = require('./elevenlabs-audio.cjs');
31
32
  const require_ollama = require('./ollama.cjs');
32
33
  const require_cohere = require('./cohere.cjs');
@@ -169,13 +170,14 @@ function performFullReset(fixtures, targets) {
169
170
  targets.openRouterVideoJobs.clear();
170
171
  targets.veoVideoJobs.clear();
171
172
  targets.grokVideoJobs.clear();
173
+ targets.bytePlusVideoJobs.clear();
172
174
  if (targets.defaults.registry) targets.defaults.registry.setGauge("aimock_fixtures_loaded", {}, fixtures.length);
173
175
  }
174
176
  /**
175
177
  * Handle requests under `/__aimock/`. Returns `true` if the request was
176
178
  * handled, `false` if the path doesn't match the control prefix.
177
179
  */
178
- async function handleControlAPI(req, res, pathname, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, defaults) {
180
+ async function handleControlAPI(req, res, pathname, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, bytePlusVideoJobs, defaults) {
179
181
  if (!pathname.startsWith(CONTROL_PREFIX)) return false;
180
182
  const subPath = pathname.slice(9);
181
183
  setCorsHeaders(res);
@@ -189,6 +191,11 @@ async function handleControlAPI(req, res, pathname, fixtures, journal, videoStat
189
191
  res.end(JSON.stringify(journal.getAll()));
190
192
  return true;
191
193
  }
194
+ if (subPath === "/fixtures" && req.method === "GET") {
195
+ res.writeHead(200, { "Content-Type": "application/json" });
196
+ res.end(JSON.stringify({ count: fixtures.length }));
197
+ return true;
198
+ }
192
199
  if (subPath === "/fixtures" && req.method === "POST") {
193
200
  let raw;
194
201
  try {
@@ -244,6 +251,7 @@ async function handleControlAPI(req, res, pathname, fixtures, journal, videoStat
244
251
  openRouterVideoJobs,
245
252
  veoVideoJobs,
246
253
  grokVideoJobs,
254
+ bytePlusVideoJobs,
247
255
  defaults
248
256
  });
249
257
  if (subPath === "/reset" && req.method === "POST") {
@@ -793,6 +801,9 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
793
801
  },
794
802
  get grokVideo() {
795
803
  return serverOptions.grokVideo;
804
+ },
805
+ get bytePlusVideo() {
806
+ return serverOptions.bytePlusVideo;
796
807
  }
797
808
  };
798
809
  if (options?.chaos) {
@@ -828,6 +839,10 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
828
839
  {
829
840
  name: "grokVideo",
830
841
  config: options?.grokVideo
842
+ },
843
+ {
844
+ name: "bytePlusVideo",
845
+ config: options?.bytePlusVideo
831
846
  }
832
847
  ]) {
833
848
  if (!config) continue;
@@ -842,6 +857,16 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
842
857
  const cap = options?.record?.openRouterVideo?.maxContentBytes;
843
858
  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})`);
844
859
  }
860
+ {
861
+ const bytePlusBase = options?.record?.providers?.byteplus;
862
+ if (bytePlusBase !== void 0) {
863
+ let basePath;
864
+ try {
865
+ basePath = new URL(bytePlusBase).pathname;
866
+ } catch {}
867
+ 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).`);
868
+ }
869
+ }
845
870
  const journal = new require_journal.Journal({
846
871
  maxEntries: options?.journalMaxEntries ?? 1e3,
847
872
  fixtureCountsMaxTestIds: options?.fixtureCountsMaxTestIds ?? 500
@@ -850,6 +875,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
850
875
  const openRouterVideoJobs = new require_openrouter_video.OpenRouterVideoJobMap();
851
876
  const veoVideoJobs = new require_veo_video.VeoVideoJobMap();
852
877
  const grokVideoJobs = new require_grok_video.GrokVideoJobMap();
878
+ const bytePlusVideoJobs = new require_byteplus_video.BytePlusVideoJobMap();
853
879
  if (mounts) for (const { handler } of mounts) {
854
880
  if (handler.setJournal) handler.setJournal(journal);
855
881
  if (registry && handler.setRegistry) handler.setRegistry(registry);
@@ -875,7 +901,9 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
875
901
  const startTime = registry ? process.hrtime.bigint() : 0n;
876
902
  const parsedUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
877
903
  let pathname = parsedUrl.pathname;
878
- const isOpenRouter = require_openrouter_chat.isOpenRouterPath(pathname);
904
+ const originalPathname = pathname;
905
+ const isOpenRouter = require_openrouter_chat.isOpenRouterPath(originalPathname);
906
+ const isBytePlusArk = defaults.record?.providers.byteplus !== void 0 && originalPathname.startsWith("/api/v3/");
879
907
  if (registry) res.on("finish", () => {
880
908
  try {
881
909
  const normalizedPath = require_metrics.normalizePathLabel(pathname);
@@ -907,7 +935,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
907
935
  require_api_key_auth.markAuthenticatedRequest(req, resolvedAuth.policy);
908
936
  }
909
937
  if (pathname.startsWith(CONTROL_PREFIX)) {
910
- await handleControlAPI(req, res, pathname, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, defaults);
938
+ await handleControlAPI(req, res, pathname, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, bytePlusVideoJobs, defaults);
911
939
  return;
912
940
  }
913
941
  if (mounts) {
@@ -1090,6 +1118,66 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1090
1118
  }
1091
1119
  return;
1092
1120
  }
1121
+ const bytePlusVideoStatusMatch = pathname.match(require_metrics.BYTEPLUS_VIDEO_STATUS_RE);
1122
+ if (bytePlusVideoStatusMatch && req.method === "GET") {
1123
+ try {
1124
+ await require_byteplus_video.handleBytePlusVideoStatus(req, res, bytePlusVideoStatusMatch[1], fixtures, journal, defaults, setCorsHeaders, bytePlusVideoJobs);
1125
+ } catch (err) {
1126
+ const msg = err instanceof Error ? err.message : "Internal error";
1127
+ defaults.logger.error(`byteplus-video status: ${msg}`);
1128
+ if (!res.headersSent) {
1129
+ try {
1130
+ journal.add({
1131
+ method: req.method ?? "GET",
1132
+ path: req.url ?? pathname,
1133
+ headers: require_helpers.flattenHeaders(req.headers),
1134
+ body: null,
1135
+ response: {
1136
+ status: 500,
1137
+ fixture: null
1138
+ }
1139
+ });
1140
+ } catch (jErr) {
1141
+ defaults.logger.warn(`byteplus-video status: journal write failed after handler error: ${jErr instanceof Error ? jErr.message : String(jErr)}`);
1142
+ }
1143
+ require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
1144
+ message: msg,
1145
+ type: "server_error"
1146
+ } }));
1147
+ } else if (!res.writableEnded) res.destroy();
1148
+ }
1149
+ return;
1150
+ }
1151
+ if (require_metrics.BYTEPLUS_VIDEO_SUBMIT_RE.test(pathname) && req.method === "POST") {
1152
+ setCorsHeaders(res);
1153
+ try {
1154
+ await require_byteplus_video.handleBytePlusVideoCreate(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, bytePlusVideoJobs);
1155
+ } catch (err) {
1156
+ const msg = err instanceof Error ? err.message : "Internal error";
1157
+ defaults.logger.error(`byteplus-video submit: ${msg}`);
1158
+ if (!res.headersSent) {
1159
+ try {
1160
+ journal.add({
1161
+ method: req.method ?? "POST",
1162
+ path: req.url ?? pathname,
1163
+ headers: require_helpers.flattenHeaders(req.headers),
1164
+ body: null,
1165
+ response: {
1166
+ status: 500,
1167
+ fixture: null
1168
+ }
1169
+ });
1170
+ } catch (jErr) {
1171
+ defaults.logger.warn(`byteplus-video submit: journal write failed after handler error: ${jErr instanceof Error ? jErr.message : String(jErr)}`);
1172
+ }
1173
+ require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
1174
+ message: msg,
1175
+ type: "server_error"
1176
+ } }));
1177
+ } else if (!res.writableEnded) res.destroy();
1178
+ }
1179
+ return;
1180
+ }
1093
1181
  if (pathname === "/api/v1/models" && req.method === "GET") {
1094
1182
  require_openrouter_chat.handleOpenRouterModels(req, res, fixtures, journal, defaults, setCorsHeaders);
1095
1183
  return;
@@ -1288,7 +1376,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1288
1376
  }
1289
1377
  if (pathname === IMAGES_PATH && req.method === "POST") {
1290
1378
  try {
1291
- await require_images.handleImages(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
1379
+ await require_images.handleImages(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, "openai", void 0, isBytePlusArk ? "byteplus" : void 0);
1292
1380
  } catch (err) {
1293
1381
  const msg = err instanceof Error ? err.message : "Internal error";
1294
1382
  if (!res.headersSent) require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
@@ -1827,7 +1915,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1827
1915
  handleNotFound(res, "Not found");
1828
1916
  return;
1829
1917
  }
1830
- const completionsProvider = azureDeploymentId ? "azure" : isOpenRouter ? "openrouter" : "openai";
1918
+ const completionsProvider = azureDeploymentId ? "azure" : isOpenRouter ? "openrouter" : isBytePlusArk ? "byteplus" : "openai";
1831
1919
  try {
1832
1920
  await handleCompletions(req, res, fixtures, journal, defaults, azureDeploymentId, completionsProvider, isOpenRouter);
1833
1921
  } catch (err) {
@@ -1855,7 +1943,48 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1855
1943
  if (!socket.destroyed) socket.destroy();
1856
1944
  });
1857
1945
  });
1946
+ /**
1947
+ * Body bytes the platform already parsed onto `req` for an upgrade request.
1948
+ *
1949
+ * Node >= 26 delivers an upgrade request's body here and leaves `head`
1950
+ * empty; Node <= 24 leaves the body in `head` and ends `req` with nothing.
1951
+ * The stream has already ended in both cases, so this resolves on the next
1952
+ * tick either way — it never waits on the network.
1953
+ */
1954
+ function drainParsedRequestBody(req) {
1955
+ return new Promise((resolve) => {
1956
+ const chunks = [];
1957
+ let settled = false;
1958
+ const done = () => {
1959
+ if (settled) return;
1960
+ settled = true;
1961
+ resolve(Buffer.concat(chunks));
1962
+ };
1963
+ req.on("data", (c) => chunks.push(c));
1964
+ req.on("end", done);
1965
+ req.on("error", done);
1966
+ req.on("close", done);
1967
+ req.resume();
1968
+ });
1969
+ }
1858
1970
  async function handleUpgradeRequest(req, socket, head) {
1971
+ if ((req.headers.upgrade ?? "").toLowerCase() !== "websocket") {
1972
+ const parsedBody = await drainParsedRequestBody(req);
1973
+ const requestLine = `${req.method} ${req.url} HTTP/${req.httpVersion}\r\n`;
1974
+ const headerLines = [];
1975
+ for (let i = 0; i < req.rawHeaders.length; i += 2) {
1976
+ if (/^(?:upgrade|connection)$/i.test(req.rawHeaders[i])) continue;
1977
+ headerLines.push(`${req.rawHeaders[i]}: ${req.rawHeaders[i + 1]}`);
1978
+ }
1979
+ const rebuilt = Buffer.from(requestLine + headerLines.join("\r\n") + "\r\n\r\n");
1980
+ socket.unshift(Buffer.concat([
1981
+ rebuilt,
1982
+ parsedBody,
1983
+ head
1984
+ ]));
1985
+ server.emit("connection", socket);
1986
+ return;
1987
+ }
1859
1988
  const parsedUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
1860
1989
  let pathname = parsedUrl.pathname;
1861
1990
  if (!require_api_key_auth.validateRequestApiKey(req, resolvedAuth.policy).ok) {
@@ -1924,6 +2053,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1924
2053
  openRouterVideoJobs.clear();
1925
2054
  veoVideoJobs.clear();
1926
2055
  grokVideoJobs.clear();
2056
+ bytePlusVideoJobs.clear();
1927
2057
  originalClose(callback);
1928
2058
  return this;
1929
2059
  };
@@ -1947,7 +2077,8 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1947
2077
  videoStates,
1948
2078
  openRouterVideoJobs,
1949
2079
  veoVideoJobs,
1950
- grokVideoJobs
2080
+ grokVideoJobs,
2081
+ bytePlusVideoJobs
1951
2082
  });
1952
2083
  });
1953
2084
  });