@copilotkit/aimock 1.43.0 → 1.44.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 (290) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +15 -0
  4. package/README.md +8 -2
  5. package/dist/agui-handler.d.ts.map +1 -1
  6. package/dist/agui-types.d.ts.map +1 -1
  7. package/dist/bedrock-converse.cjs +32 -4
  8. package/dist/bedrock-converse.cjs.map +1 -1
  9. package/dist/bedrock-converse.d.cts.map +1 -1
  10. package/dist/bedrock-converse.d.ts.map +1 -1
  11. package/dist/bedrock-converse.js +32 -4
  12. package/dist/bedrock-converse.js.map +1 -1
  13. package/dist/chaos.cjs +8 -5
  14. package/dist/chaos.cjs.map +1 -1
  15. package/dist/chaos.d.cts.map +1 -1
  16. package/dist/chaos.d.ts.map +1 -1
  17. package/dist/chaos.js +9 -6
  18. package/dist/chaos.js.map +1 -1
  19. package/dist/cli.cjs +89 -7
  20. package/dist/cli.cjs.map +1 -1
  21. package/dist/cli.js +91 -9
  22. package/dist/cli.js.map +1 -1
  23. package/dist/cohere.cjs +27 -1
  24. package/dist/cohere.cjs.map +1 -1
  25. package/dist/cohere.js +27 -1
  26. package/dist/cohere.js.map +1 -1
  27. package/dist/config-loader.cjs +1 -1
  28. package/dist/config-loader.d.ts.map +1 -1
  29. package/dist/config-loader.js +1 -1
  30. package/dist/constants.cjs +8 -0
  31. package/dist/constants.cjs.map +1 -1
  32. package/dist/constants.d.cts +6 -2
  33. package/dist/constants.d.ts +6 -2
  34. package/dist/constants.js +8 -1
  35. package/dist/constants.js.map +1 -1
  36. package/dist/echo-text.cjs +65 -0
  37. package/dist/echo-text.cjs.map +1 -0
  38. package/dist/echo-text.d.cts +22 -0
  39. package/dist/echo-text.d.cts.map +1 -0
  40. package/dist/echo-text.d.ts +22 -0
  41. package/dist/echo-text.d.ts.map +1 -0
  42. package/dist/echo-text.js +65 -0
  43. package/dist/echo-text.js.map +1 -0
  44. package/dist/embeddings.cjs +18 -1
  45. package/dist/embeddings.cjs.map +1 -1
  46. package/dist/embeddings.d.cts +1 -1
  47. package/dist/embeddings.d.cts.map +1 -1
  48. package/dist/embeddings.d.ts +1 -1
  49. package/dist/embeddings.d.ts.map +1 -1
  50. package/dist/embeddings.js +18 -1
  51. package/dist/embeddings.js.map +1 -1
  52. package/dist/files.cjs +9 -11
  53. package/dist/files.cjs.map +1 -1
  54. package/dist/files.d.cts.map +1 -1
  55. package/dist/files.d.ts.map +1 -1
  56. package/dist/files.js +10 -13
  57. package/dist/files.js.map +1 -1
  58. package/dist/fine-tuning.cjs +1 -19
  59. package/dist/fine-tuning.cjs.map +1 -1
  60. package/dist/fine-tuning.d.cts.map +1 -1
  61. package/dist/fine-tuning.d.ts.map +1 -1
  62. package/dist/fine-tuning.js +2 -20
  63. package/dist/fine-tuning.js.map +1 -1
  64. package/dist/fixture-loader-services.cjs +116 -0
  65. package/dist/fixture-loader-services.cjs.map +1 -0
  66. package/dist/fixture-loader-services.d.cts +48 -0
  67. package/dist/fixture-loader-services.d.cts.map +1 -0
  68. package/dist/fixture-loader-services.d.ts +48 -0
  69. package/dist/fixture-loader-services.d.ts.map +1 -0
  70. package/dist/fixture-loader-services.js +114 -0
  71. package/dist/fixture-loader-services.js.map +1 -0
  72. package/dist/fixture-loader.cjs +172 -11
  73. package/dist/fixture-loader.cjs.map +1 -1
  74. package/dist/fixture-loader.d.cts +95 -1
  75. package/dist/fixture-loader.d.cts.map +1 -1
  76. package/dist/fixture-loader.d.ts +95 -1
  77. package/dist/fixture-loader.d.ts.map +1 -1
  78. package/dist/fixture-loader.js +168 -12
  79. package/dist/fixture-loader.js.map +1 -1
  80. package/dist/gemini-embeddings.cjs +42 -2
  81. package/dist/gemini-embeddings.cjs.map +1 -1
  82. package/dist/gemini-embeddings.js +43 -3
  83. package/dist/gemini-embeddings.js.map +1 -1
  84. package/dist/gemini-interactions.cjs +38 -0
  85. package/dist/gemini-interactions.cjs.map +1 -1
  86. package/dist/gemini-interactions.d.cts.map +1 -1
  87. package/dist/gemini-interactions.d.ts.map +1 -1
  88. package/dist/gemini-interactions.js +38 -0
  89. package/dist/gemini-interactions.js.map +1 -1
  90. package/dist/gemini.cjs +8 -1
  91. package/dist/gemini.cjs.map +1 -1
  92. package/dist/gemini.d.cts.map +1 -1
  93. package/dist/gemini.d.ts.map +1 -1
  94. package/dist/gemini.js +8 -1
  95. package/dist/gemini.js.map +1 -1
  96. package/dist/helpers.cjs +276 -5
  97. package/dist/helpers.cjs.map +1 -1
  98. package/dist/helpers.d.cts.map +1 -1
  99. package/dist/helpers.d.ts.map +1 -1
  100. package/dist/helpers.js +275 -7
  101. package/dist/helpers.js.map +1 -1
  102. package/dist/images.cjs +3 -2
  103. package/dist/images.cjs.map +1 -1
  104. package/dist/images.js +3 -2
  105. package/dist/images.js.map +1 -1
  106. package/dist/index.cjs +30 -1
  107. package/dist/index.d.cts +8 -3
  108. package/dist/index.d.ts +8 -3
  109. package/dist/index.js +9 -3
  110. package/dist/jest.cjs +15 -10
  111. package/dist/jest.cjs.map +1 -1
  112. package/dist/jest.d.cts +4 -2
  113. package/dist/jest.d.cts.map +1 -1
  114. package/dist/jest.d.ts +4 -2
  115. package/dist/jest.d.ts.map +1 -1
  116. package/dist/jest.js +16 -11
  117. package/dist/jest.js.map +1 -1
  118. package/dist/journal.cjs +20 -0
  119. package/dist/journal.cjs.map +1 -1
  120. package/dist/journal.d.cts +16 -0
  121. package/dist/journal.d.cts.map +1 -1
  122. package/dist/journal.d.ts +16 -0
  123. package/dist/journal.d.ts.map +1 -1
  124. package/dist/journal.js +20 -0
  125. package/dist/journal.js.map +1 -1
  126. package/dist/llmock.cjs +82 -10
  127. package/dist/llmock.cjs.map +1 -1
  128. package/dist/llmock.d.cts +35 -0
  129. package/dist/llmock.d.cts.map +1 -1
  130. package/dist/llmock.d.ts +35 -0
  131. package/dist/llmock.d.ts.map +1 -1
  132. package/dist/llmock.js +83 -11
  133. package/dist/llmock.js.map +1 -1
  134. package/dist/mcp-fakes-mount.cjs +216 -0
  135. package/dist/mcp-fakes-mount.cjs.map +1 -0
  136. package/dist/mcp-fakes-mount.js +210 -0
  137. package/dist/mcp-fakes-mount.js.map +1 -0
  138. package/dist/mcp-fakes.cjs +1619 -0
  139. package/dist/mcp-fakes.cjs.map +1 -0
  140. package/dist/mcp-fakes.d.cts +101 -0
  141. package/dist/mcp-fakes.d.cts.map +1 -0
  142. package/dist/mcp-fakes.d.ts +101 -0
  143. package/dist/mcp-fakes.d.ts.map +1 -0
  144. package/dist/mcp-fakes.js +1614 -0
  145. package/dist/mcp-fakes.js.map +1 -0
  146. package/dist/mcp-handler.cjs +331 -17
  147. package/dist/mcp-handler.cjs.map +1 -1
  148. package/dist/mcp-handler.js +330 -18
  149. package/dist/mcp-handler.js.map +1 -1
  150. package/dist/mcp-mock.cjs +217 -49
  151. package/dist/mcp-mock.cjs.map +1 -1
  152. package/dist/mcp-mock.d.cts +66 -1
  153. package/dist/mcp-mock.d.cts.map +1 -1
  154. package/dist/mcp-mock.d.ts +66 -1
  155. package/dist/mcp-mock.d.ts.map +1 -1
  156. package/dist/mcp-mock.js +218 -50
  157. package/dist/mcp-mock.js.map +1 -1
  158. package/dist/mcp-stub.cjs +5 -1
  159. package/dist/mcp-stub.d.cts +3 -1
  160. package/dist/mcp-stub.d.ts +3 -1
  161. package/dist/mcp-stub.js +3 -1
  162. package/dist/mcp-types.d.cts +6 -0
  163. package/dist/mcp-types.d.ts +6 -0
  164. package/dist/message-text.cjs +192 -0
  165. package/dist/message-text.cjs.map +1 -0
  166. package/dist/message-text.d.cts +31 -0
  167. package/dist/message-text.d.cts.map +1 -0
  168. package/dist/message-text.d.ts +31 -0
  169. package/dist/message-text.d.ts.map +1 -0
  170. package/dist/message-text.js +184 -0
  171. package/dist/message-text.js.map +1 -0
  172. package/dist/messages.cjs +38 -0
  173. package/dist/messages.cjs.map +1 -1
  174. package/dist/messages.js +38 -0
  175. package/dist/messages.js.map +1 -1
  176. package/dist/metrics.cjs +46 -66
  177. package/dist/metrics.cjs.map +1 -1
  178. package/dist/metrics.d.cts +14 -6
  179. package/dist/metrics.d.cts.map +1 -1
  180. package/dist/metrics.d.ts +14 -6
  181. package/dist/metrics.d.ts.map +1 -1
  182. package/dist/metrics.js +32 -40
  183. package/dist/metrics.js.map +1 -1
  184. package/dist/ollama.cjs +5 -1
  185. package/dist/ollama.cjs.map +1 -1
  186. package/dist/ollama.d.cts.map +1 -1
  187. package/dist/ollama.d.ts.map +1 -1
  188. package/dist/ollama.js +5 -1
  189. package/dist/ollama.js.map +1 -1
  190. package/dist/openapi.cjs +3405 -0
  191. package/dist/openapi.cjs.map +1 -0
  192. package/dist/openapi.d.cts +30 -0
  193. package/dist/openapi.d.cts.map +1 -0
  194. package/dist/openapi.d.ts +30 -0
  195. package/dist/openapi.d.ts.map +1 -0
  196. package/dist/openapi.js +3404 -0
  197. package/dist/openapi.js.map +1 -0
  198. package/dist/openrouter-video.cjs +4 -4
  199. package/dist/openrouter-video.cjs.map +1 -1
  200. package/dist/openrouter-video.d.cts.map +1 -1
  201. package/dist/openrouter-video.d.ts.map +1 -1
  202. package/dist/openrouter-video.js +4 -4
  203. package/dist/openrouter-video.js.map +1 -1
  204. package/dist/recorder.cjs +9 -1
  205. package/dist/recorder.cjs.map +1 -1
  206. package/dist/recorder.d.cts.map +1 -1
  207. package/dist/recorder.d.ts.map +1 -1
  208. package/dist/recorder.js +9 -1
  209. package/dist/recorder.js.map +1 -1
  210. package/dist/responses.cjs +43 -4
  211. package/dist/responses.cjs.map +1 -1
  212. package/dist/responses.d.cts.map +1 -1
  213. package/dist/responses.d.ts.map +1 -1
  214. package/dist/responses.js +43 -4
  215. package/dist/responses.js.map +1 -1
  216. package/dist/route-registry.cjs +951 -0
  217. package/dist/route-registry.cjs.map +1 -0
  218. package/dist/route-registry.d.cts +33 -0
  219. package/dist/route-registry.d.cts.map +1 -0
  220. package/dist/route-registry.d.ts +33 -0
  221. package/dist/route-registry.d.ts.map +1 -0
  222. package/dist/route-registry.js +866 -0
  223. package/dist/route-registry.js.map +1 -0
  224. package/dist/router.cjs +1 -1
  225. package/dist/router.cjs.map +1 -1
  226. package/dist/router.js +1 -1
  227. package/dist/router.js.map +1 -1
  228. package/dist/server.cjs +590 -191
  229. package/dist/server.cjs.map +1 -1
  230. package/dist/server.d.cts +4 -1
  231. package/dist/server.d.cts.map +1 -1
  232. package/dist/server.d.ts +4 -1
  233. package/dist/server.d.ts.map +1 -1
  234. package/dist/server.js +498 -99
  235. package/dist/server.js.map +1 -1
  236. package/dist/speech.cjs +4 -2
  237. package/dist/speech.cjs.map +1 -1
  238. package/dist/speech.js +4 -2
  239. package/dist/speech.js.map +1 -1
  240. package/dist/suite.cjs +1 -1
  241. package/dist/suite.js +1 -1
  242. package/dist/transcription.cjs +2 -2
  243. package/dist/transcription.cjs.map +1 -1
  244. package/dist/transcription.d.cts.map +1 -1
  245. package/dist/transcription.d.ts.map +1 -1
  246. package/dist/transcription.js +2 -2
  247. package/dist/transcription.js.map +1 -1
  248. package/dist/types.cjs +18 -0
  249. package/dist/types.cjs.map +1 -0
  250. package/dist/types.d.cts +202 -2
  251. package/dist/types.d.cts.map +1 -1
  252. package/dist/types.d.ts +202 -2
  253. package/dist/types.d.ts.map +1 -1
  254. package/dist/types.js +17 -0
  255. package/dist/types.js.map +1 -0
  256. package/dist/validate-cli.cjs +89 -31
  257. package/dist/validate-cli.cjs.map +1 -1
  258. package/dist/validate-cli.js +91 -33
  259. package/dist/validate-cli.js.map +1 -1
  260. package/dist/vector-stores.cjs +1180 -0
  261. package/dist/vector-stores.cjs.map +1 -0
  262. package/dist/vector-stores.d.cts +106 -0
  263. package/dist/vector-stores.d.cts.map +1 -0
  264. package/dist/vector-stores.d.ts +106 -0
  265. package/dist/vector-stores.d.ts.map +1 -0
  266. package/dist/vector-stores.js +1164 -0
  267. package/dist/vector-stores.js.map +1 -0
  268. package/dist/vector-types.d.cts.map +1 -1
  269. package/dist/vector-types.d.ts.map +1 -1
  270. package/dist/video.cjs +19 -0
  271. package/dist/video.cjs.map +1 -1
  272. package/dist/video.d.cts.map +1 -1
  273. package/dist/video.d.ts.map +1 -1
  274. package/dist/video.js +19 -0
  275. package/dist/video.js.map +1 -1
  276. package/dist/vitest.cjs +15 -10
  277. package/dist/vitest.cjs.map +1 -1
  278. package/dist/vitest.d.cts +4 -2
  279. package/dist/vitest.d.cts.map +1 -1
  280. package/dist/vitest.d.ts +4 -2
  281. package/dist/vitest.d.ts.map +1 -1
  282. package/dist/vitest.js +16 -11
  283. package/dist/vitest.js.map +1 -1
  284. package/dist/ws-gemini-live.d.ts +2 -2
  285. package/dist/ws-realtime.d.ts +2 -2
  286. package/dist/ws-responses.cjs +14 -2
  287. package/dist/ws-responses.cjs.map +1 -1
  288. package/dist/ws-responses.js +14 -2
  289. package/dist/ws-responses.js.map +1 -1
  290. package/package.json +4 -1
package/dist/server.cjs CHANGED
@@ -1,5 +1,6 @@
1
1
  const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
2
2
  const require_constants = require('./constants.cjs');
3
+ const require_message_text = require('./message-text.cjs');
3
4
  const require_api_key_auth = require('./api-key-auth.cjs');
4
5
  const require_helpers = require('./helpers.cjs');
5
6
  const require_live_fixture = require('./live-fixture.cjs');
@@ -38,6 +39,7 @@ const require_search = require('./search.cjs');
38
39
  const require_rerank = require('./rerank.cjs');
39
40
  const require_moderation = require('./moderation.cjs');
40
41
  const require_fine_tuning = require('./fine-tuning.cjs');
42
+ const require_vector_stores = require('./vector-stores.cjs');
41
43
  const require_files = require('./files.cjs');
42
44
  const require_batches = require('./batches.cjs');
43
45
  const require_ws_framing = require('./ws-framing.cjs');
@@ -45,42 +47,18 @@ const require_ws_live = require('./ws-live.cjs');
45
47
  const require_ws_responses = require('./ws-responses.cjs');
46
48
  const require_ws_realtime = require('./ws-realtime.cjs');
47
49
  const require_ws_gemini_live = require('./ws-gemini-live.cjs');
50
+ const require_route_registry = require('./route-registry.cjs');
51
+ const require_openapi = require('./openapi.cjs');
48
52
  const require_metrics = require('./metrics.cjs');
53
+ const require_mcp_fakes = require('./mcp-fakes.cjs');
54
+ const require_mcp_mock = require('./mcp-mock.cjs');
55
+ const require_mcp_fakes_mount = require('./mcp-fakes-mount.cjs');
49
56
  let node_http = require("node:http");
50
57
  node_http = require_runtime.__toESM(node_http);
51
58
  let node_async_hooks = require("node:async_hooks");
52
59
 
53
60
  //#region src/server.ts
54
61
  const liveClosers = /* @__PURE__ */ new WeakMap();
55
- const COMPLETIONS_PATH = "/v1/chat/completions";
56
- const RESPONSES_PATH = "/v1/responses";
57
- const LIVE_PATH = "/v1/live/sessions";
58
- const REALTIME_PATH = "/v1/realtime";
59
- const GEMINI_LIVE_PATH = "/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent";
60
- const MESSAGES_PATH = "/v1/messages";
61
- const EMBEDDINGS_PATH = "/v1/embeddings";
62
- const COHERE_CHAT_PATH = "/v2/chat";
63
- const COHERE_EMBED_PATH = "/v2/embed";
64
- const SEARCH_PATH = "/search";
65
- const RERANK_PATH = "/v2/rerank";
66
- const MODERATIONS_PATH = "/v1/moderations";
67
- const IMAGES_PATH = "/v1/images/generations";
68
- const IMAGES_EDIT_PATH = "/v1/images/edits";
69
- const IMAGES_VARIATIONS_PATH = "/v1/images/variations";
70
- const SPEECH_PATH = "/v1/audio/speech";
71
- const TRANSCRIPTIONS_PATH = "/v1/audio/transcriptions";
72
- const TRANSLATIONS_PATH = "/v1/audio/translations";
73
- const VIDEOS_PATH = "/v1/videos";
74
- const GEMINI_PREDICT_RE = /^\/v1beta\/models\/([^:]+):predict$/;
75
- const ELEVENLABS_SOUND_GENERATION_PATH = "/v1/sound-generation";
76
- const ELEVENLABS_TTS_RE = /^\/v1\/text-to-speech\/([^/]+)$/;
77
- const ELEVENLABS_MUSIC_RE = /^\/v1\/music(?:\/(.+))?$/;
78
- const ELEVENLABS_VOICE_DESIGN_PATH = "/v1/text-to-voice/design";
79
- const ELEVENLABS_VOICE_CREATE_PATH = "/v1/text-to-voice";
80
- const ELEVENLABS_VOICE_RE = /^\/v1\/voices\/([^/]+)$/;
81
- const FAL_QUEUE_SUBMIT_RE = /^\/fal\/queue\/submit\/(.+)$/;
82
- const FAL_QUEUE_REQUESTS_RE = /^\/fal\/queue\/requests\/(.+)$/;
83
- const FAL_RUN_RE = /^\/fal\/run\/(.+)$/;
84
62
  const DEFAULT_CHUNK_SIZE = 20;
85
63
  const COMPAT_SUFFIXES = [
86
64
  "/chat/completions",
@@ -109,34 +87,6 @@ function normalizeCompatPath(pathname, logger) {
109
87
  }
110
88
  return pathname;
111
89
  }
112
- const GEMINI_INTERACTIONS_PATH = "/v1beta/interactions";
113
- const GEMINI_PATH_RE = /^\/v1beta\/models\/([^:]+):(generateContent|streamGenerateContent)$/;
114
- const GEMINI_EMBED_RE = /^\/v1beta\/models\/([^:]+):embedContent$/;
115
- const AZURE_DEPLOYMENT_RE = /^\/openai\/deployments\/([^/]+)\/(chat\/completions|embeddings)$/;
116
- const BEDROCK_INVOKE_RE = /^\/model\/([^/]+)\/invoke$/;
117
- const BEDROCK_STREAM_RE = /^\/model\/([^/]+)\/invoke-with-response-stream$/;
118
- const BEDROCK_CONVERSE_RE = /^\/model\/([^/]+)\/converse$/;
119
- const BEDROCK_CONVERSE_STREAM_RE = /^\/model\/([^/]+)\/converse-stream$/;
120
- const VERTEX_AI_RE = /^\/v1\/projects\/[^/]+\/locations\/[^/]+\/publishers\/google\/models\/([^/:]+):(generateContent|streamGenerateContent)$/;
121
- const OLLAMA_CHAT_PATH = "/api/chat";
122
- const OLLAMA_GENERATE_PATH = "/api/generate";
123
- const OLLAMA_EMBEDDINGS_PATH = "/api/embeddings";
124
- const OLLAMA_EMBED_PATH = "/api/embed";
125
- const OLLAMA_TAGS_PATH = "/api/tags";
126
- const OPENROUTER_VIDEOS_PATH = "/api/v1/videos";
127
- const OPENROUTER_VIDEO_MODELS_PATH = "/api/v1/videos/models";
128
- const HEALTH_PATH = "/health";
129
- const READY_PATH = "/ready";
130
- const MODELS_PATH = "/v1/models";
131
- const REQUESTS_PATH = "/v1/_requests";
132
- const BATCHES_PATH = "/v1/batches";
133
- const BATCHES_ID_RE = /^\/v1\/batches\/([^/]+)$/;
134
- const BATCHES_CANCEL_RE = /^\/v1\/batches\/([^/]+)\/cancel$/;
135
- const FILES_PATH = "/v1/files";
136
- const FINE_TUNING_JOBS_PATH = "/v1/fine_tuning/jobs";
137
- const FINE_TUNING_ID_RE = /^\/v1\/fine_tuning\/jobs\/([^/]+)$/;
138
- const FINE_TUNING_CANCEL_RE = /^\/v1\/fine_tuning\/jobs\/([^/]+)\/cancel$/;
139
- const FINE_TUNING_EVENTS_RE = /^\/v1\/fine_tuning\/jobs\/([^/]+)\/events$/;
140
90
  const DEFAULT_MODELS = [
141
91
  "gpt-4",
142
92
  "gpt-4o",
@@ -146,7 +96,7 @@ const DEFAULT_MODELS = [
146
96
  ];
147
97
  const CORS_HEADERS = {
148
98
  "Access-Control-Allow-Origin": "*",
149
- "Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
99
+ "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
150
100
  "Access-Control-Allow-Headers": "*",
151
101
  "Access-Control-Expose-Headers": "X-Total-Count, X-Request-Id"
152
102
  };
@@ -165,7 +115,6 @@ function handleNotFound(res, message) {
165
115
  type: "not_found"
166
116
  } }));
167
117
  }
168
- const CONTROL_PREFIX = "/__aimock";
169
118
  /** The complete `GET /__aimock/fixtures` query-param vocabulary; anything else 400s. */
170
119
  const FIXTURES_PARAMS = new Set(["include"]);
171
120
  /** The complete `GET /__aimock/journal` query-param vocabulary; anything else 400s. */
@@ -204,6 +153,7 @@ function performFullReset(fixtures, targets) {
204
153
  require_elevenlabs_voice.clearElevenLabsVoices();
205
154
  require_files.clearFileStore();
206
155
  require_fine_tuning.clearFineTuningStore();
156
+ require_vector_stores.clearVectorStoreStore();
207
157
  require_gemini_interactions.resetInteractionCounter();
208
158
  require_gemini_interactions.resetEventIdCounter();
209
159
  if (!targets) return;
@@ -216,6 +166,7 @@ function performFullReset(fixtures, targets) {
216
166
  targets.veoVideoJobs.clear();
217
167
  targets.grokVideoJobs.clear();
218
168
  targets.bytePlusVideoJobs.clear();
169
+ for (const { handler } of targets.mounts ?? []) handler.clearMcpFakes?.();
219
170
  if (targets.defaults.registry) targets.defaults.registry.setGauge("aimock_fixtures_loaded", {}, fixtures.length);
220
171
  }
221
172
  /**
@@ -270,9 +221,14 @@ function fixtureResponseKind(response) {
270
221
  * scoping path does not also do. (Splitting on "," additionally broke every
271
222
  * legitimately comma-bearing id.) A raw `path.includes("testId=t1")` both
272
223
  * prefix-collides with `t10` and matches unrelated params like `notTestId`.
224
+ *
225
+ * An MCP mount records the test id it resolved on the entry (I9, B3): a
226
+ * decoded header or query value, or the one bound to the session at
227
+ * `initialize`. That value wins; LLM entries carry none and are attributed as
228
+ * before.
273
229
  */
274
230
  function journalEntryTestId(entry) {
275
- return require_helpers.resolveTestId(entry.headers, entry.path);
231
+ return entry.testId ?? require_helpers.resolveTestId(entry.headers, entry.path);
276
232
  }
277
233
  /**
278
234
  * The testId a chaos override is stored under, and read back with — resolved by
@@ -311,19 +267,186 @@ function effectiveChaos(defaults, scopeId) {
311
267
  if (!current) return {};
312
268
  return require_chaos.isChaosScope(current) ? current.base ?? {} : current;
313
269
  }
270
+ /** The `GET /__aimock/mcp/fakes` query-param vocabulary; anything else 400s. */
271
+ const MCP_FAKES_PARAMS = new Set([
272
+ "testId",
273
+ "context",
274
+ "mount"
275
+ ]);
276
+ /** A block's `mount` path, read without running getters; the add validates it. */
277
+ function controlFakeMountOf(raw) {
278
+ if (typeof raw !== "object" || raw === null) return require_mcp_fakes.MCP_FAKES_DEFAULT_MOUNT;
279
+ const value = Object.getOwnPropertyDescriptor(raw, "mount")?.value;
280
+ return typeof value === "string" ? value : require_mcp_fakes.MCP_FAKES_DEFAULT_MOUNT;
281
+ }
282
+ /**
283
+ * Check one `POST /__aimock/fixtures` `mcpFakes` value against the live
284
+ * mounts (F10, W6) without changing anything. Returns every error in input
285
+ * order (an empty list when the value can be added), and `apply`, which adds
286
+ * the blocks (auto-mounting an MCPMock where no mount serves a block's path)
287
+ * and returns the number of blocks added.
288
+ *
289
+ * The whole value is checked before any mount is touched, and the check
290
+ * never adds to a real mount: each group is added to a throwaway store,
291
+ * whose errors are the ones reported (it numbers the add `control-api#1`, as
292
+ * a new mount would; for an existing MCPMock the rejected group is re-run on
293
+ * its atomic add, so the errors name that mount's next `<n>`, I7). A group
294
+ * whose path no request to it can reach (a mount that is not an MCPMock
295
+ * serves it, an MCPMock answers it as its root, or it is under the control
296
+ * prefix) is a mount conflict (one error per block).
297
+ */
298
+ function planControlApiFakes(raw, mounts) {
299
+ const items = Array.isArray(raw) ? raw.map((block, position) => ({
300
+ position,
301
+ source: {
302
+ source: "control-api",
303
+ blockIndex: position,
304
+ raw: block
305
+ }
306
+ })) : [{
307
+ position: 0,
308
+ source: {
309
+ source: "control-api",
310
+ blockIndex: null,
311
+ raw
312
+ }
313
+ }];
314
+ const groups = /* @__PURE__ */ new Map();
315
+ if (items.length === 0) groups.set(require_mcp_fakes.MCP_FAKES_DEFAULT_MOUNT, {
316
+ path: require_mcp_fakes.MCP_FAKES_DEFAULT_MOUNT,
317
+ positions: [],
318
+ sources: []
319
+ });
320
+ for (const { position, source } of items) {
321
+ const path = controlFakeMountOf(source.raw);
322
+ const group = groups.get(path) ?? {
323
+ path,
324
+ positions: [],
325
+ sources: []
326
+ };
327
+ group.positions.push(position);
328
+ group.sources.push(source);
329
+ groups.set(path, group);
330
+ }
331
+ const found = [];
332
+ /** The paths `apply` auto-mounts, in order. */
333
+ const pending = [];
334
+ for (const group of groups.values()) {
335
+ const target = require_mcp_fakes_mount.findFakeMount(mounts, group.path, pending);
336
+ if (target.kind === "conflict") {
337
+ group.positions.forEach((position) => {
338
+ const where = Array.isArray(raw) ? require_message_text.msg`mcpFakes[${position}]` : require_message_text.msg`mcpFakes`;
339
+ found.push({
340
+ position,
341
+ error: new require_fixture_loader.FixtureLoadError({
342
+ rule: "mcp-fakes/mount-conflict",
343
+ file: null,
344
+ blockId: null,
345
+ entryId: null,
346
+ detail: require_message_text.msg`${where}: ${require_mcp_fakes_mount.mountConflictDetail(group.path, target)}`
347
+ })
348
+ });
349
+ });
350
+ continue;
351
+ }
352
+ let failure = addFailure(() => new require_mcp_fakes.McpFakeStore().add(group.sources, { kind: "control-api" }));
353
+ if (target.kind === "none") pending.push(group.path);
354
+ if (!failure) continue;
355
+ if (target.kind === "mcp" && target.handler.addMcpFakes === require_mcp_mock.MCPMock.prototype.addMcpFakes) {
356
+ const handler = target.handler;
357
+ failure = addFailure(() => handler.addMcpFakes?.(group.sources, { kind: "control-api" })) ?? failure;
358
+ }
359
+ for (const error of failure.errors) found.push({
360
+ position: positionOf(error, group),
361
+ error
362
+ });
363
+ }
364
+ found.sort((a, b) => a.position - b.position);
365
+ return {
366
+ errors: found.map((f) => f.error),
367
+ apply(wiring) {
368
+ let added = 0;
369
+ for (const group of groups.values()) {
370
+ const target = require_mcp_fakes_mount.ensureFakeMount(mounts, group.path, {
371
+ journal: wiring.journal,
372
+ registry: wiring.defaults.registry,
373
+ logger: wiring.defaults.logger
374
+ }, wiring.defaults.logger);
375
+ if ("conflict" in target) continue;
376
+ const result = target.handler.addMcpFakes?.(group.sources, { kind: "control-api" });
377
+ for (const warning of result?.warnings ?? []) wiring.defaults.logger.warn(warning.message);
378
+ added += group.sources.length;
379
+ }
380
+ return added;
381
+ }
382
+ };
383
+ }
384
+ /** The `McpFakesAddError` that `add` throws, or `null` when it adds. */
385
+ function addFailure(add) {
386
+ try {
387
+ add();
388
+ return null;
389
+ } catch (err) {
390
+ if (err instanceof require_mcp_fakes.McpFakesAddError) return err;
391
+ throw err;
392
+ }
393
+ }
394
+ /**
395
+ * The request position of the block an add error names. The add numbers a
396
+ * run-time group's blocks by their place in the group (`[<j>]`), or gives no
397
+ * index to a single-object value; an error tied to no block sorts with the
398
+ * group's first block.
399
+ */
400
+ function positionOf(error, group) {
401
+ const first = group.positions[0] ?? 0;
402
+ if (error.blockId == null || error.file === null) return first;
403
+ const at = group.positions.findIndex((_, j) => error.blockId === require_mcp_fakes.blockIdOf(error.file ?? "", "", j));
404
+ return at === -1 ? first : group.positions[at];
405
+ }
406
+ function hasFakesSnapshot(handler) {
407
+ return "fakesSnapshot" in handler && typeof handler.fakesSnapshot === "function";
408
+ }
409
+ /**
410
+ * `GET /__aimock/mcp/fakes` (spec 6.5, I9): for each MCP mount (or the one
411
+ * named by `mount`), the blocks that apply to the requested test id and
412
+ * context, with every entry id and its consumed state for that test id.
413
+ * A mount is listed when it takes fakes (it implements `addMcpFakes`, the
414
+ * check every other fakes path uses); one with no `fakesSnapshot` lists no
415
+ * blocks.
416
+ */
417
+ function listControlApiFakes(mounts, testId, context, mount) {
418
+ const listed = mounts.flatMap(({ path, handler }) => require_mcp_fakes_mount.isFakeMount(handler) && (mount === null || path === mount) ? [{
419
+ mount: path,
420
+ blocks: hasFakesSnapshot(handler) ? handler.fakesSnapshot(testId, context) : []
421
+ }] : []);
422
+ return mount !== null && listed.length === 0 ? null : listed;
423
+ }
314
424
  /**
315
425
  * Handle requests under `/__aimock/`. Returns `true` if the request was
316
426
  * handled, `false` if the path doesn't match the control prefix.
317
427
  */
318
- async function handleControlAPI(req, res, pathname, searchParams, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, bytePlusVideoJobs, defaults) {
319
- if (!pathname.startsWith(CONTROL_PREFIX)) return false;
320
- const subPath = pathname.slice(9);
428
+ async function handleControlAPI(req, res, pathname, searchParams, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, bytePlusVideoJobs, defaults, mounts) {
429
+ if (!pathname.startsWith(require_route_registry.CONTROL_PREFIX)) return false;
430
+ const subPath = pathname.slice(require_route_registry.CONTROL_PREFIX.length);
321
431
  setCorsHeaders(res);
322
432
  if (subPath === "/health" && req.method === "GET") {
323
433
  res.writeHead(200, { "Content-Type": "application/json" });
324
434
  res.end(JSON.stringify({ status: "ok" }));
325
435
  return true;
326
436
  }
437
+ if (subPath === "/openapi.json" && req.method === "GET") {
438
+ res.writeHead(200, { "Content-Type": "application/json" });
439
+ res.end(JSON.stringify(require_openapi.buildOpenApiDocument()));
440
+ return true;
441
+ }
442
+ if (subPath === "/routes" && req.method === "GET") {
443
+ res.writeHead(200, { "Content-Type": "application/json" });
444
+ res.end(JSON.stringify({
445
+ count: require_openapi.CATALOG_ROUTES.length,
446
+ routes: require_openapi.CATALOG_ROUTES
447
+ }));
448
+ return true;
449
+ }
327
450
  if (subPath === "/journal" && req.method === "GET") {
328
451
  const bad = (message) => {
329
452
  res.writeHead(400, { "Content-Type": "application/json" });
@@ -474,6 +597,24 @@ async function handleControlAPI(req, res, pathname, searchParams, fixtures, jour
474
597
  res.end(JSON.stringify({ chaos: effectiveChaos(defaults, scopeId) }));
475
598
  return true;
476
599
  }
600
+ if (subPath === "/mcp/fakes" && req.method === "GET") {
601
+ const reply = (status, body) => {
602
+ res.writeHead(status, { "Content-Type": "application/json" });
603
+ res.end(JSON.stringify(body));
604
+ return true;
605
+ };
606
+ for (const key of searchParams.keys()) if (!MCP_FAKES_PARAMS.has(key)) return reply(400, { error: `Unknown query parameter: '${key}'. Supported: ${[...MCP_FAKES_PARAMS].join(", ")}` });
607
+ const testId = searchParams.get("testId") || null;
608
+ const context = searchParams.get("context") || null;
609
+ const mount = searchParams.get("mount") || null;
610
+ const listed = listControlApiFakes(mounts, testId, context, mount);
611
+ if (listed === null) return reply(404, { error: require_message_text.build(require_message_text.msg`No MCP mount at ${require_message_text.quote(mount ?? "")}`) });
612
+ return reply(200, {
613
+ testId,
614
+ context,
615
+ mounts: listed
616
+ });
617
+ }
477
618
  if (subPath === "/fixtures" && req.method === "POST") {
478
619
  let raw;
479
620
  try {
@@ -495,29 +636,60 @@ async function handleControlAPI(req, res, pathname, searchParams, fixtures, jour
495
636
  res.end(JSON.stringify({ error: `Invalid JSON: ${msg}` }));
496
637
  return true;
497
638
  }
498
- if (!Array.isArray(parsed.fixtures)) {
639
+ const withFakes = typeof parsed === "object" && parsed !== null && Object.hasOwn(parsed, "mcpFakes");
640
+ if (parsed === null || !Array.isArray(parsed.fixtures) && !(withFakes && parsed.fixtures === void 0)) {
499
641
  res.writeHead(400, { "Content-Type": "application/json" });
500
642
  res.end(JSON.stringify({ error: "Missing or invalid \"fixtures\" array" }));
501
643
  return true;
502
644
  }
503
- const converted = parsed.fixtures.map((e) => require_fixture_loader.entryToFixture(e));
645
+ const entries = Array.isArray(parsed.fixtures) ? parsed.fixtures : [];
646
+ const missingMatchIndex = entries.findIndex((entry) => entry !== null && typeof entry === "object" && !Array.isArray(entry) && entry.match == null);
647
+ if (missingMatchIndex !== -1) {
648
+ res.writeHead(400, { "Content-Type": "application/json" });
649
+ res.end(JSON.stringify({ error: `Fixture at index ${missingMatchIndex} is missing match` }));
650
+ return true;
651
+ }
652
+ const invalidMatchIndex = entries.findIndex((entry) => entry !== null && typeof entry === "object" && !Array.isArray(entry) && entry.match != null && (typeof entry.match !== "object" || Array.isArray(entry.match)));
653
+ if (invalidMatchIndex !== -1) {
654
+ res.writeHead(400, { "Content-Type": "application/json" });
655
+ res.end(JSON.stringify({ error: `Fixture at index ${invalidMatchIndex}: match must be an object` }));
656
+ return true;
657
+ }
658
+ const converted = entries.map((e) => require_fixture_loader.entryToFixture(e));
504
659
  const errors = require_fixture_loader.validateFixtures(converted).filter((i) => i.severity === "error");
505
- if (errors.length > 0) {
660
+ const fakes = withFakes ? planControlApiFakes(parsed.mcpFakes, mounts) : null;
661
+ const fakeErrors = fakes?.errors ?? [];
662
+ const validationFailed = (details) => {
506
663
  res.writeHead(400, { "Content-Type": "application/json" });
507
664
  res.end(JSON.stringify({
508
665
  error: "Validation failed",
509
- details: errors
666
+ details
510
667
  }));
511
668
  return true;
669
+ };
670
+ if (errors.length > 0 || fakeErrors.length > 0) return validationFailed([...errors, ...fakeErrors.map((e) => e.toJSON())]);
671
+ let mcpFakesAdded = 0;
672
+ if (fakes) try {
673
+ mcpFakesAdded = fakes.apply({
674
+ journal,
675
+ defaults
676
+ });
677
+ } catch (err) {
678
+ if (!(err instanceof require_mcp_fakes.McpFakesAddError)) throw err;
679
+ return validationFailed(err.errors.map((e) => e.toJSON()));
512
680
  }
513
681
  fixtures.push(...converted);
514
682
  if (defaults.registry) defaults.registry.setGauge("aimock_fixtures_loaded", {}, fixtures.length);
515
683
  res.writeHead(200, { "Content-Type": "application/json" });
516
- res.end(JSON.stringify({ added: converted.length }));
684
+ res.end(JSON.stringify(withFakes ? {
685
+ added: converted.length,
686
+ mcpFakesAdded
687
+ } : { added: converted.length }));
517
688
  return true;
518
689
  }
519
690
  if (subPath === "/fixtures" && req.method === "DELETE") {
520
691
  require_fixture_loader.clearFixtureQueue(fixtures);
692
+ for (const { handler } of mounts) handler.clearMcpFakes?.();
521
693
  if (defaults.registry) defaults.registry.setGauge("aimock_fixtures_loaded", {}, fixtures.length);
522
694
  res.writeHead(200, { "Content-Type": "application/json" });
523
695
  res.end(JSON.stringify({ cleared: true }));
@@ -530,7 +702,8 @@ async function handleControlAPI(req, res, pathname, searchParams, fixtures, jour
530
702
  veoVideoJobs,
531
703
  grokVideoJobs,
532
704
  bytePlusVideoJobs,
533
- defaults
705
+ defaults,
706
+ mounts
534
707
  });
535
708
  if (subPath === "/reset" && req.method === "POST") {
536
709
  performFullReset(fixtures, resetTargets());
@@ -640,7 +813,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
640
813
  } catch (err) {
641
814
  const msg = err instanceof Error ? err.message : "Failed to read request body";
642
815
  const clientFault = err instanceof require_helpers.RequestBodyTooLargeError;
643
- const route = `${req.method ?? "POST"} ${req.url ?? COMPLETIONS_PATH}`;
816
+ const route = `${req.method ?? "POST"} ${req.url ?? require_route_registry.COMPLETIONS_PATH}`;
644
817
  const clientAbort = clientAbortedMidBody(req, res, err);
645
818
  const bodyLimitDisconnect = clientFault && (req.destroyed || res.destroyed);
646
819
  if (clientAbort || bodyLimitDisconnect) {
@@ -648,7 +821,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
648
821
  defaults.logger.warn(bodyLimitDisconnect ? `${route}: ${msg}` : `${route}: client aborted mid-body (${msg})`);
649
822
  journal.add({
650
823
  method: req.method ?? "POST",
651
- path: req.url ?? COMPLETIONS_PATH,
824
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
652
825
  headers: require_helpers.flattenHeaders(req.headers),
653
826
  body: null,
654
827
  response: {
@@ -665,7 +838,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
665
838
  else defaults.logger.error(`${route}: ${msg}`);
666
839
  journal.add({
667
840
  method: req.method ?? "POST",
668
- path: req.url ?? COMPLETIONS_PATH,
841
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
669
842
  headers: require_helpers.flattenHeaders(req.headers),
670
843
  body: null,
671
844
  response: {
@@ -686,7 +859,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
686
859
  const detail = parseErr instanceof Error ? parseErr.message : "unknown parse error";
687
860
  journal.add({
688
861
  method: req.method ?? "POST",
689
- path: req.url ?? COMPLETIONS_PATH,
862
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
690
863
  headers: require_helpers.flattenHeaders(req.headers),
691
864
  body: null,
692
865
  response: {
@@ -705,7 +878,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
705
878
  if (!require_helpers.isJsonObject(body)) {
706
879
  journal.add({
707
880
  method: req.method ?? "POST",
708
- path: req.url ?? COMPLETIONS_PATH,
881
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
709
882
  headers: require_helpers.flattenHeaders(req.headers),
710
883
  body: null,
711
884
  response: {
@@ -723,7 +896,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
723
896
  if (!Array.isArray(body.messages)) {
724
897
  journal.add({
725
898
  method: req.method ?? "POST",
726
- path: req.url ?? COMPLETIONS_PATH,
899
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
727
900
  headers: require_helpers.flattenHeaders(req.headers),
728
901
  body: null,
729
902
  response: {
@@ -739,8 +912,53 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
739
912
  } }));
740
913
  return;
741
914
  }
915
+ const nullMessageIndex = body.messages.findIndex((message) => message === null);
916
+ if (nullMessageIndex !== -1) {
917
+ const message = `Invalid request: messages[${nullMessageIndex}] must be an object`;
918
+ journal.add({
919
+ method: req.method ?? "POST",
920
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
921
+ headers: require_helpers.flattenHeaders(req.headers),
922
+ body: null,
923
+ response: {
924
+ status: 400,
925
+ fixture: null
926
+ }
927
+ });
928
+ require_sse_writer.writeErrorResponse(res, 400, openRouter ? require_openrouter_chat.serializeOpenRouterError(400, message) : JSON.stringify({ error: {
929
+ message,
930
+ type: "invalid_request_error",
931
+ param: null,
932
+ code: null
933
+ } }));
934
+ return;
935
+ }
936
+ if (new URL(req.url ?? require_route_registry.COMPLETIONS_PATH, "http://localhost").pathname === require_route_registry.COMPLETIONS_PATH) {
937
+ let toolsError = require_helpers.validateToolsField(body.tools);
938
+ if (!toolsError && Array.isArray(body.tools)) {
939
+ const nullFunctionIndex = body.tools.findIndex((tool) => tool?.function === null);
940
+ if (nullFunctionIndex !== -1) toolsError = `tools[${nullFunctionIndex}].function must not be null`;
941
+ }
942
+ if (toolsError) {
943
+ journal.add({
944
+ method: req.method ?? "POST",
945
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
946
+ headers: require_helpers.flattenHeaders(req.headers),
947
+ body: null,
948
+ response: {
949
+ status: 400,
950
+ fixture: null
951
+ }
952
+ });
953
+ require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
954
+ message: toolsError,
955
+ type: "invalid_request_error"
956
+ } }));
957
+ return;
958
+ }
959
+ }
742
960
  const method = req.method ?? "POST";
743
- const path = req.url ?? COMPLETIONS_PATH;
961
+ const path = req.url ?? require_route_registry.COMPLETIONS_PATH;
744
962
  const flatHeaders = require_helpers.flattenHeaders(req.headers);
745
963
  body._endpointType = "chat";
746
964
  body._context = require_helpers.getContext(req);
@@ -851,10 +1069,10 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
851
1069
  if (effectiveStrict) {
852
1070
  const strictStatus = 503;
853
1071
  const strictMessage = require_helpers.strictNoMatchMessage(skippedBySequenceOrTurn);
854
- defaults.logger.error(require_helpers.strictNoMatchLogLine(req.method ?? "POST", req.url ?? COMPLETIONS_PATH, skippedBySequenceOrTurn));
1072
+ defaults.logger.error(require_helpers.strictNoMatchLogLine(req.method ?? "POST", req.url ?? require_route_registry.COMPLETIONS_PATH, skippedBySequenceOrTurn));
855
1073
  journal.add({
856
1074
  method: req.method ?? "POST",
857
- path: req.url ?? COMPLETIONS_PATH,
1075
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
858
1076
  headers: require_helpers.flattenHeaders(req.headers),
859
1077
  body,
860
1078
  response: {
@@ -894,7 +1112,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
894
1112
  req.socket?.on("error", noteClientHangUp);
895
1113
  let outcome;
896
1114
  try {
897
- outcome = await require_recorder.proxyAndRecord(req, res, body, providerKey, req.url ?? COMPLETIONS_PATH, fixtures, defaults, raw, hookOptions);
1115
+ outcome = await require_recorder.proxyAndRecord(req, res, body, providerKey, req.url ?? require_route_registry.COMPLETIONS_PATH, fixtures, defaults, raw, hookOptions);
898
1116
  } finally {
899
1117
  req.socket?.off("end", noteClientHangUp);
900
1118
  req.socket?.off("error", noteClientHangUp);
@@ -904,7 +1122,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
904
1122
  const destroyedMidStream = res.destroyed && !res.writableEnded;
905
1123
  journal.add({
906
1124
  method: req.method ?? "POST",
907
- path: req.url ?? COMPLETIONS_PATH,
1125
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
908
1126
  headers: require_helpers.flattenHeaders(req.headers),
909
1127
  body,
910
1128
  response: {
@@ -926,7 +1144,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
926
1144
  }
927
1145
  journal.add({
928
1146
  method: req.method ?? "POST",
929
- path: req.url ?? COMPLETIONS_PATH,
1147
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
930
1148
  headers: require_helpers.flattenHeaders(req.headers),
931
1149
  body,
932
1150
  response: {
@@ -964,7 +1182,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
964
1182
  const status = response.status ?? 500;
965
1183
  journal.add({
966
1184
  method: req.method ?? "POST",
967
- path: req.url ?? COMPLETIONS_PATH,
1185
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
968
1186
  headers: require_helpers.flattenHeaders(req.headers),
969
1187
  body,
970
1188
  response: {
@@ -978,7 +1196,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
978
1196
  if (require_helpers.isAudioResponse(response)) {
979
1197
  journal.add({
980
1198
  method: req.method ?? "POST",
981
- path: req.url ?? COMPLETIONS_PATH,
1199
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
982
1200
  headers: require_helpers.flattenHeaders(req.headers),
983
1201
  body,
984
1202
  response: {
@@ -1001,7 +1219,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1001
1219
  const blockOutcome = response.blocks && response.blocks.length > 0 ? require_helpers.resolveFixtureBlockOutcome(response.blocks) : void 0;
1002
1220
  const journalEntry = journal.add({
1003
1221
  method: req.method ?? "POST",
1004
- path: req.url ?? COMPLETIONS_PATH,
1222
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
1005
1223
  headers: require_helpers.flattenHeaders(req.headers),
1006
1224
  body,
1007
1225
  response: {
@@ -1047,7 +1265,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1047
1265
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, responseModel, effectiveStrict, defaults.logger);
1048
1266
  const journalEntry = journal.add({
1049
1267
  method: req.method ?? "POST",
1050
- path: req.url ?? COMPLETIONS_PATH,
1268
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
1051
1269
  headers: require_helpers.flattenHeaders(req.headers),
1052
1270
  body,
1053
1271
  response: {
@@ -1089,7 +1307,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1089
1307
  const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, responseModel, effectiveStrict, defaults.logger);
1090
1308
  const journalEntry = journal.add({
1091
1309
  method: req.method ?? "POST",
1092
- path: req.url ?? COMPLETIONS_PATH,
1310
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
1093
1311
  headers: require_helpers.flattenHeaders(req.headers),
1094
1312
  body,
1095
1313
  response: {
@@ -1127,7 +1345,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
1127
1345
  }
1128
1346
  journal.add({
1129
1347
  method: req.method ?? "POST",
1130
- path: req.url ?? COMPLETIONS_PATH,
1348
+ path: req.url ?? require_route_registry.COMPLETIONS_PATH,
1131
1349
  headers: require_helpers.flattenHeaders(req.headers),
1132
1350
  body,
1133
1351
  response: {
@@ -1148,9 +1366,24 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
1148
1366
  }
1149
1367
  /** @internal Config startup uses this to avoid parsing a selected auth source twice. */
1150
1368
  async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mounts, serviceFixtures) {
1369
+ const logger = new require_logger.Logger(options?.logLevel ?? "silent");
1370
+ const mountList = mounts ?? [];
1371
+ const handOff = serviceFixtures?.mcpFakes && serviceFixtures.mcpFakes.length > 0 ? require_mcp_fakes_mount.handOffMcpFakes(mountList, serviceFixtures.mcpFakes, logger) : null;
1372
+ try {
1373
+ return await startServer(fixtures, options, resolvedAuth, mountList, logger, serviceFixtures, () => handOff?.commit());
1374
+ } catch (err) {
1375
+ handOff?.undo();
1376
+ throw err;
1377
+ }
1378
+ }
1379
+ /**
1380
+ * The server of `createServerWithResolvedAuth`, after the MCP fakes hand-off.
1381
+ * `commitHandOff` runs once the server listens; if it throws, the server is
1382
+ * closed and start rejects.
1383
+ */
1384
+ async function startServer(fixtures, options, resolvedAuth, mountList, logger, serviceFixtures, commitHandOff) {
1151
1385
  const host = options?.host ?? "127.0.0.1";
1152
1386
  const port = options?.port ?? 0;
1153
- const logger = new require_logger.Logger(options?.logLevel ?? "silent");
1154
1387
  const registry = options?.metrics ? require_metrics.createMetricsRegistry() : void 0;
1155
1388
  const serverOptions = options ?? {};
1156
1389
  const chaosByTestId = /* @__PURE__ */ new Map();
@@ -1439,9 +1672,10 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1439
1672
  else res.destroy();
1440
1673
  }
1441
1674
  }
1442
- if (mounts) for (const { handler } of mounts) {
1675
+ for (const { handler } of mountList) {
1443
1676
  if (handler.setJournal) handler.setJournal(journal);
1444
1677
  if (registry && handler.setRegistry) handler.setRegistry(registry);
1678
+ if (handler.setLogger) handler.setLogger(logger);
1445
1679
  }
1446
1680
  if (registry) registry.setGauge("aimock_fixtures_loaded", {}, fixtures.length);
1447
1681
  const server = node_http.createServer((req, res) => {
@@ -1464,7 +1698,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1464
1698
  if (recorded) return;
1465
1699
  recorded = true;
1466
1700
  try {
1467
- const normalizedPath = require_metrics.normalizePathLabel(pathname, mounts ? mounts.map((m) => m.path) : []);
1701
+ const normalizedPath = require_metrics.normalizePathLabel(pathname, mountList.map((m) => m.path));
1468
1702
  const method = req.method ?? "UNKNOWN";
1469
1703
  registry.incrementCounter("aimock_requests_total", {
1470
1704
  method,
@@ -1485,7 +1719,36 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1485
1719
  if (!res.writableFinished) recordOutcome(require_metrics.DESTROYED_STATUS_LABEL);
1486
1720
  });
1487
1721
  }
1488
- const parsedUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
1722
+ let parsedUrl;
1723
+ try {
1724
+ parsedUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
1725
+ } catch (err) {
1726
+ const route = `${req.method ?? "?"} ${req.url ?? "?"}`;
1727
+ const msg = err instanceof Error ? err.message : "Internal error";
1728
+ logger.error(`${route}: ${msg}`);
1729
+ if (err instanceof Error && err.stack) logger.debug(err.stack);
1730
+ try {
1731
+ journal.add({
1732
+ method: req.method ?? "?",
1733
+ path: req.url ?? "?",
1734
+ headers: require_helpers.flattenHeaders(req.headers),
1735
+ body: null,
1736
+ response: {
1737
+ status: 400,
1738
+ fixture: null,
1739
+ source: "internal"
1740
+ }
1741
+ });
1742
+ } catch (jErr) {
1743
+ logger.warn(`${route}: journal write failed after handler error: ${jErr instanceof Error ? jErr.message : String(jErr)}`);
1744
+ }
1745
+ setCorsHeaders(res);
1746
+ require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
1747
+ message: "Invalid request target",
1748
+ type: "invalid_request_error"
1749
+ } }));
1750
+ return;
1751
+ }
1489
1752
  pathname = parsedUrl.pathname;
1490
1753
  const originalPathname = pathname;
1491
1754
  const isOpenRouter = require_openrouter_chat.isOpenRouterPath(originalPathname);
@@ -1494,24 +1757,22 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1494
1757
  handleOptions(res);
1495
1758
  return;
1496
1759
  }
1497
- if (!(req.method === "GET" && (pathname === HEALTH_PATH || pathname === READY_PATH || pathname === "/metrics"))) {
1760
+ if (!(req.method === "GET" && (pathname === require_route_registry.HEALTH_PATH || pathname === require_route_registry.READY_PATH || pathname === require_route_registry.METRICS_PATH))) {
1498
1761
  if (!require_api_key_auth.validateRequestApiKey(req, resolvedAuth.policy).ok) {
1499
1762
  require_api_key_auth.writeApiKeyHttpRejection(res, setCorsHeaders);
1500
1763
  return;
1501
1764
  }
1502
1765
  require_api_key_auth.markAuthenticatedRequest(req, resolvedAuth.policy);
1503
1766
  }
1504
- if (pathname.startsWith(CONTROL_PREFIX)) {
1505
- await handleControlAPI(req, res, pathname, parsedUrl.searchParams, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, bytePlusVideoJobs, defaults);
1767
+ if (pathname.startsWith(require_route_registry.CONTROL_PREFIX)) {
1768
+ await handleControlAPI(req, res, pathname, parsedUrl.searchParams, fixtures, journal, videoStates, openRouterVideoJobs, veoVideoJobs, grokVideoJobs, bytePlusVideoJobs, defaults, mountList);
1506
1769
  return;
1507
1770
  }
1508
- if (mounts) {
1509
- for (const { path: mountPath, handler } of mounts) if (pathname === mountPath || pathname.startsWith(mountPath + "/")) {
1510
- const subPath = pathname.slice(mountPath.length) || "/";
1511
- if (await handler.handleRequest(req, res, subPath)) return;
1512
- }
1771
+ for (const { path: mountPath, handler } of mountList) if (pathname === mountPath || pathname.startsWith(mountPath + "/")) {
1772
+ const subPath = pathname.slice(mountPath.length) || "/";
1773
+ if (await handler.handleRequest(req, res, subPath)) return;
1513
1774
  }
1514
- if (pathname === OLLAMA_CHAT_PATH && req.method === "POST") {
1775
+ if (pathname === require_route_registry.OLLAMA_CHAT_PATH && req.method === "POST") {
1515
1776
  try {
1516
1777
  await require_ollama.handleOllama(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
1517
1778
  } catch (err) {
@@ -1519,7 +1780,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1519
1780
  }
1520
1781
  return;
1521
1782
  }
1522
- if (pathname === OLLAMA_GENERATE_PATH && req.method === "POST") {
1783
+ if (pathname === require_route_registry.OLLAMA_GENERATE_PATH && req.method === "POST") {
1523
1784
  try {
1524
1785
  await require_ollama.handleOllamaGenerate(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
1525
1786
  } catch (err) {
@@ -1527,7 +1788,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1527
1788
  }
1528
1789
  return;
1529
1790
  }
1530
- if ((pathname === OLLAMA_EMBEDDINGS_PATH || pathname === OLLAMA_EMBED_PATH) && req.method === "POST") {
1791
+ if ((pathname === require_route_registry.OLLAMA_EMBEDDINGS_PATH || pathname === require_route_registry.OLLAMA_EMBED_PATH) && req.method === "POST") {
1531
1792
  try {
1532
1793
  await require_ollama.handleOllamaEmbeddings(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
1533
1794
  } catch (err) {
@@ -1535,7 +1796,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1535
1796
  }
1536
1797
  return;
1537
1798
  }
1538
- if (pathname === OLLAMA_TAGS_PATH && req.method === "GET") {
1799
+ if (pathname === require_route_registry.OLLAMA_TAGS_PATH && req.method === "GET") {
1539
1800
  setCorsHeaders(res);
1540
1801
  const modelIds = /* @__PURE__ */ new Set();
1541
1802
  for (const f of fixtures) if (f.match.model && typeof f.match.model === "string") modelIds.add(f.match.model);
@@ -1551,7 +1812,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1551
1812
  res.end(JSON.stringify({ models }));
1552
1813
  return;
1553
1814
  }
1554
- const openRouterVideoContentMatch = pathname.match(require_metrics.OPENROUTER_VIDEO_CONTENT_RE);
1815
+ const openRouterVideoContentMatch = pathname.match(require_route_registry.OPENROUTER_VIDEO_CONTENT_RE);
1555
1816
  if (openRouterVideoContentMatch && req.method === "GET") {
1556
1817
  try {
1557
1818
  await require_openrouter_video.handleOpenRouterVideoContent(req, res, openRouterVideoContentMatch[1], journal, defaults, setCorsHeaders, openRouterVideoJobs);
@@ -1560,7 +1821,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1560
1821
  }
1561
1822
  return;
1562
1823
  }
1563
- if (pathname === OPENROUTER_VIDEO_MODELS_PATH && req.method === "GET") {
1824
+ if (pathname === require_route_registry.OPENROUTER_VIDEO_MODELS_PATH && req.method === "GET") {
1564
1825
  try {
1565
1826
  await require_openrouter_video.handleOpenRouterVideoModels(req, res, fixtures, journal, defaults, setCorsHeaders);
1566
1827
  } catch (err) {
@@ -1568,7 +1829,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1568
1829
  }
1569
1830
  return;
1570
1831
  }
1571
- const openRouterVideoStatusMatch = pathname.match(require_metrics.OPENROUTER_VIDEO_STATUS_RE);
1832
+ const openRouterVideoStatusMatch = pathname.match(require_route_registry.OPENROUTER_VIDEO_STATUS_RE);
1572
1833
  if (openRouterVideoStatusMatch && req.method === "GET") {
1573
1834
  try {
1574
1835
  await require_openrouter_video.handleOpenRouterVideoStatus(req, res, openRouterVideoStatusMatch[1], fixtures, journal, defaults, setCorsHeaders, openRouterVideoJobs);
@@ -1577,7 +1838,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1577
1838
  }
1578
1839
  return;
1579
1840
  }
1580
- if (pathname === OPENROUTER_VIDEOS_PATH && req.method === "POST") {
1841
+ if (pathname === require_route_registry.OPENROUTER_VIDEOS_PATH && req.method === "POST") {
1581
1842
  setCorsHeaders(res);
1582
1843
  try {
1583
1844
  await require_openrouter_video.handleOpenRouterVideoCreate(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, openRouterVideoJobs);
@@ -1586,7 +1847,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1586
1847
  }
1587
1848
  return;
1588
1849
  }
1589
- const bytePlusVideoStatusMatch = pathname.match(require_metrics.BYTEPLUS_VIDEO_STATUS_RE);
1850
+ const bytePlusVideoStatusMatch = pathname.match(require_route_registry.BYTEPLUS_VIDEO_STATUS_RE);
1590
1851
  if (bytePlusVideoStatusMatch && req.method === "GET") {
1591
1852
  try {
1592
1853
  await require_byteplus_video.handleBytePlusVideoStatus(req, res, bytePlusVideoStatusMatch[1], fixtures, journal, defaults, setCorsHeaders, bytePlusVideoJobs);
@@ -1595,7 +1856,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1595
1856
  }
1596
1857
  return;
1597
1858
  }
1598
- if (require_metrics.BYTEPLUS_VIDEO_SUBMIT_RE.test(pathname) && req.method === "POST") {
1859
+ if (require_route_registry.BYTEPLUS_VIDEO_SUBMIT_RE.test(pathname) && req.method === "POST") {
1599
1860
  setCorsHeaders(res);
1600
1861
  try {
1601
1862
  await require_byteplus_video.handleBytePlusVideoCreate(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, bytePlusVideoJobs);
@@ -1604,33 +1865,33 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1604
1865
  }
1605
1866
  return;
1606
1867
  }
1607
- if (pathname === "/api/v1/models" && req.method === "GET") {
1868
+ if (pathname === require_route_registry.OPENROUTER_MODELS_PATH && req.method === "GET") {
1608
1869
  require_openrouter_chat.handleOpenRouterModels(req, res, fixtures, journal, defaults, setCorsHeaders);
1609
1870
  return;
1610
1871
  }
1611
- if (pathname === "/api/v1/key" && req.method === "GET") {
1872
+ if (pathname === require_route_registry.OPENROUTER_KEY_PATH && req.method === "GET") {
1612
1873
  require_openrouter_chat.handleOpenRouterKey(req, res, journal, setCorsHeaders);
1613
1874
  return;
1614
1875
  }
1615
- if (pathname === "/api/v1/credits" && req.method === "GET") {
1876
+ if (pathname === require_route_registry.OPENROUTER_CREDITS_PATH && req.method === "GET") {
1616
1877
  require_openrouter_chat.handleOpenRouterCredits(req, res, journal, setCorsHeaders);
1617
1878
  return;
1618
1879
  }
1619
1880
  let azureDeploymentId;
1620
- const azureMatch = pathname.match(AZURE_DEPLOYMENT_RE);
1881
+ const azureMatch = pathname.match(require_route_registry.AZURE_DEPLOYMENT_RE);
1621
1882
  if (azureMatch && req.method === "POST") {
1622
1883
  azureDeploymentId = azureMatch[1];
1623
1884
  pathname = `/v1/${azureMatch[2]}`;
1624
1885
  }
1625
1886
  if (!azureDeploymentId) pathname = normalizeCompatPath(pathname, logger);
1626
- if (pathname === HEALTH_PATH && req.method === "GET") {
1887
+ if (pathname === require_route_registry.HEALTH_PATH && req.method === "GET") {
1627
1888
  setCorsHeaders(res);
1628
- if (mounts && mounts.length > 0) {
1889
+ if (mountList.length > 0) {
1629
1890
  const services = { llm: {
1630
1891
  status: "ok",
1631
1892
  fixtures: fixtures.length
1632
1893
  } };
1633
- for (const { path: mountPath, handler } of mounts) if (handler.health) {
1894
+ for (const { path: mountPath, handler } of mountList) if (handler.health) {
1634
1895
  const name = mountPath.replace(/^\//, "");
1635
1896
  services[name] = handler.health();
1636
1897
  }
@@ -1645,13 +1906,13 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1645
1906
  }
1646
1907
  return;
1647
1908
  }
1648
- if (pathname === READY_PATH && req.method === "GET") {
1909
+ if (pathname === require_route_registry.READY_PATH && req.method === "GET") {
1649
1910
  setCorsHeaders(res);
1650
1911
  res.writeHead(200, { "Content-Type": "application/json" });
1651
1912
  res.end(JSON.stringify({ status: "ready" }));
1652
1913
  return;
1653
1914
  }
1654
- if (pathname === "/metrics" && req.method === "GET") {
1915
+ if (pathname === require_route_registry.METRICS_PATH && req.method === "GET") {
1655
1916
  if (!registry) {
1656
1917
  handleNotFound(res, "Not found");
1657
1918
  return;
@@ -1661,7 +1922,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1661
1922
  res.end(registry.serialize());
1662
1923
  return;
1663
1924
  }
1664
- if (pathname === MODELS_PATH && req.method === "GET") {
1925
+ if (pathname === require_route_registry.MODELS_PATH && req.method === "GET") {
1665
1926
  setCorsHeaders(res);
1666
1927
  const modelIds = /* @__PURE__ */ new Set();
1667
1928
  for (const f of fixtures) if (f.match.model && typeof f.match.model === "string") modelIds.add(f.match.model);
@@ -1678,7 +1939,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1678
1939
  }));
1679
1940
  return;
1680
1941
  }
1681
- const batchesCancelMatch = pathname.match(BATCHES_CANCEL_RE);
1942
+ const batchesCancelMatch = pathname.match(require_route_registry.BATCHES_CANCEL_RE);
1682
1943
  if (batchesCancelMatch && req.method === "POST") {
1683
1944
  try {
1684
1945
  await require_helpers.readBody(req);
@@ -1688,7 +1949,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1688
1949
  }
1689
1950
  return;
1690
1951
  }
1691
- const batchesIdMatch = pathname.match(BATCHES_ID_RE);
1952
+ const batchesIdMatch = pathname.match(require_route_registry.BATCHES_ID_RE);
1692
1953
  if (batchesIdMatch && req.method === "GET") {
1693
1954
  try {
1694
1955
  await require_batches.handleBatchesRetrieve(req, res, batchesIdMatch[1], journal, defaults, setCorsHeaders);
@@ -1697,7 +1958,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1697
1958
  }
1698
1959
  return;
1699
1960
  }
1700
- if (pathname === BATCHES_PATH && req.method === "GET") {
1961
+ if (pathname === require_route_registry.BATCHES_PATH && req.method === "GET") {
1701
1962
  try {
1702
1963
  await require_batches.handleBatchesList(req, res, journal, defaults, setCorsHeaders);
1703
1964
  } catch (err) {
@@ -1705,7 +1966,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1705
1966
  }
1706
1967
  return;
1707
1968
  }
1708
- if (pathname === BATCHES_PATH && req.method === "POST") {
1969
+ if (pathname === require_route_registry.BATCHES_PATH && req.method === "POST") {
1709
1970
  try {
1710
1971
  await require_batches.handleBatchesCreate(req, res, await require_helpers.readBody(req), journal, defaults, setCorsHeaders);
1711
1972
  } catch (err) {
@@ -1713,7 +1974,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1713
1974
  }
1714
1975
  return;
1715
1976
  }
1716
- const filesContentMatch = pathname.match(require_metrics.FILES_CONTENT_RE);
1977
+ const filesContentMatch = pathname.match(require_route_registry.FILES_CONTENT_RE);
1717
1978
  if (filesContentMatch && req.method === "GET") {
1718
1979
  try {
1719
1980
  await require_files.handleFilesContent(req, res, filesContentMatch[1], journal, defaults, setCorsHeaders);
@@ -1722,7 +1983,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1722
1983
  }
1723
1984
  return;
1724
1985
  }
1725
- const filesIdMatch = pathname.match(require_metrics.FILES_ID_RE);
1986
+ const filesIdMatch = pathname.match(require_route_registry.FILES_ID_RE);
1726
1987
  if (filesIdMatch && req.method === "GET") {
1727
1988
  try {
1728
1989
  await require_files.handleFilesRetrieve(req, res, filesIdMatch[1], journal, defaults, setCorsHeaders);
@@ -1739,7 +2000,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1739
2000
  }
1740
2001
  return;
1741
2002
  }
1742
- if (pathname === FILES_PATH && req.method === "GET") {
2003
+ if (pathname === require_route_registry.FILES_PATH && req.method === "GET") {
1743
2004
  try {
1744
2005
  await require_files.handleFilesList(req, res, journal, defaults, setCorsHeaders);
1745
2006
  } catch (err) {
@@ -1747,7 +2008,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1747
2008
  }
1748
2009
  return;
1749
2010
  }
1750
- if (pathname === FILES_PATH && req.method === "POST") {
2011
+ if (pathname === require_route_registry.FILES_PATH && req.method === "POST") {
1751
2012
  try {
1752
2013
  await require_files.handleFilesCreate(req, res, (await require_helpers.readBodyBufferBounded(req, require_files.FILES_BODY_MAX_BYTES, require_files.FILES_BODY_DRAIN_MAX_BYTES)).buffer ?? require_files.FILES_BODY_OVERSIZED, journal, defaults, setCorsHeaders);
1753
2014
  } catch (err) {
@@ -1755,7 +2016,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1755
2016
  }
1756
2017
  return;
1757
2018
  }
1758
- const ftCancelMatch = pathname.match(FINE_TUNING_CANCEL_RE);
2019
+ const ftCancelMatch = pathname.match(require_route_registry.FINE_TUNING_CANCEL_RE);
1759
2020
  if (ftCancelMatch && req.method === "POST") {
1760
2021
  try {
1761
2022
  await require_helpers.readBody(req);
@@ -1765,7 +2026,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1765
2026
  }
1766
2027
  return;
1767
2028
  }
1768
- const ftEventsMatch = pathname.match(FINE_TUNING_EVENTS_RE);
2029
+ const ftEventsMatch = pathname.match(require_route_registry.FINE_TUNING_EVENTS_RE);
1769
2030
  if (ftEventsMatch && req.method === "GET") {
1770
2031
  try {
1771
2032
  await require_fine_tuning.handleFineTuningEvents(req, res, ftEventsMatch[1], journal, defaults, setCorsHeaders);
@@ -1774,7 +2035,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1774
2035
  }
1775
2036
  return;
1776
2037
  }
1777
- const ftIdMatch = pathname.match(FINE_TUNING_ID_RE);
2038
+ const ftIdMatch = pathname.match(require_route_registry.FINE_TUNING_ID_RE);
1778
2039
  if (ftIdMatch && req.method === "GET") {
1779
2040
  try {
1780
2041
  await require_fine_tuning.handleFineTuningRetrieve(req, res, ftIdMatch[1], journal, defaults, setCorsHeaders);
@@ -1783,7 +2044,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1783
2044
  }
1784
2045
  return;
1785
2046
  }
1786
- if (pathname === FINE_TUNING_JOBS_PATH && req.method === "GET") {
2047
+ if (pathname === require_route_registry.FINE_TUNING_JOBS_PATH && req.method === "GET") {
1787
2048
  try {
1788
2049
  await require_fine_tuning.handleFineTuningList(req, res, journal, defaults, setCorsHeaders);
1789
2050
  } catch (err) {
@@ -1791,7 +2052,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1791
2052
  }
1792
2053
  return;
1793
2054
  }
1794
- if (pathname === FINE_TUNING_JOBS_PATH && req.method === "POST") {
2055
+ if (pathname === require_route_registry.FINE_TUNING_JOBS_PATH && req.method === "POST") {
1795
2056
  try {
1796
2057
  await require_fine_tuning.handleFineTuningCreate(req, res, await require_helpers.readBody(req), journal, defaults, setCorsHeaders);
1797
2058
  } catch (err) {
@@ -1799,14 +2060,140 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1799
2060
  }
1800
2061
  return;
1801
2062
  }
1802
- if (pathname === REQUESTS_PATH) {
2063
+ const vsSearchMatch = pathname.match(require_route_registry.VECTOR_STORES_SEARCH_RE);
2064
+ if (vsSearchMatch && req.method === "POST") {
2065
+ try {
2066
+ const raw = await require_helpers.readBody(req);
2067
+ await require_vector_stores.handleVectorStoresSearch(req, res, vsSearchMatch[1], raw, journal, defaults, setCorsHeaders);
2068
+ } catch (err) {
2069
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2070
+ }
2071
+ return;
2072
+ }
2073
+ const vsBatchFilesMatch = pathname.match(require_route_registry.VECTOR_STORES_BATCH_FILES_RE);
2074
+ if (vsBatchFilesMatch && req.method === "GET") {
2075
+ try {
2076
+ await require_vector_stores.handleVectorFileBatchesFiles(req, res, vsBatchFilesMatch[1], vsBatchFilesMatch[2], journal, defaults, setCorsHeaders);
2077
+ } catch (err) {
2078
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2079
+ }
2080
+ return;
2081
+ }
2082
+ const vsBatchCancelMatch = pathname.match(require_route_registry.VECTOR_STORES_BATCH_CANCEL_RE);
2083
+ if (vsBatchCancelMatch && req.method === "POST") {
2084
+ try {
2085
+ await require_helpers.readBody(req);
2086
+ await require_vector_stores.handleVectorFileBatchesCancel(req, res, vsBatchCancelMatch[1], vsBatchCancelMatch[2], journal, defaults, setCorsHeaders);
2087
+ } catch (err) {
2088
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2089
+ }
2090
+ return;
2091
+ }
2092
+ const vsBatchMatch = pathname.match(require_route_registry.VECTOR_STORES_BATCH_RE);
2093
+ if (vsBatchMatch && req.method === "GET") {
2094
+ try {
2095
+ await require_vector_stores.handleVectorFileBatchesRetrieve(req, res, vsBatchMatch[1], vsBatchMatch[2], journal, defaults, setCorsHeaders);
2096
+ } catch (err) {
2097
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2098
+ }
2099
+ return;
2100
+ }
2101
+ const vsFileMatch = pathname.match(require_route_registry.VECTOR_STORES_FILE_RE);
2102
+ if (vsFileMatch && req.method === "GET") {
2103
+ try {
2104
+ await require_vector_stores.handleVectorStoreFilesRetrieve(req, res, vsFileMatch[1], vsFileMatch[2], journal, defaults, setCorsHeaders);
2105
+ } catch (err) {
2106
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2107
+ }
2108
+ return;
2109
+ }
2110
+ if (vsFileMatch && req.method === "DELETE") {
2111
+ try {
2112
+ await require_vector_stores.handleVectorStoreFilesDelete(req, res, vsFileMatch[1], vsFileMatch[2], journal, defaults, setCorsHeaders);
2113
+ } catch (err) {
2114
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2115
+ }
2116
+ return;
2117
+ }
2118
+ const vsIdMatch = pathname.match(require_route_registry.VECTOR_STORES_ID_RE);
2119
+ if (vsIdMatch && req.method === "GET") {
2120
+ try {
2121
+ await require_vector_stores.handleVectorStoresRetrieve(req, res, vsIdMatch[1], journal, defaults, setCorsHeaders);
2122
+ } catch (err) {
2123
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2124
+ }
2125
+ return;
2126
+ }
2127
+ if (vsIdMatch && req.method === "POST") {
2128
+ try {
2129
+ const raw = await require_helpers.readBody(req);
2130
+ await require_vector_stores.handleVectorStoresModify(req, res, vsIdMatch[1], raw, journal, defaults, setCorsHeaders);
2131
+ } catch (err) {
2132
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2133
+ }
2134
+ return;
2135
+ }
2136
+ if (vsIdMatch && req.method === "DELETE") {
2137
+ try {
2138
+ await require_vector_stores.handleVectorStoresDelete(req, res, vsIdMatch[1], journal, defaults, setCorsHeaders);
2139
+ } catch (err) {
2140
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2141
+ }
2142
+ return;
2143
+ }
2144
+ if (require_route_registry.VECTOR_STORES_FILES_RE.test(pathname) && req.method === "POST") {
2145
+ try {
2146
+ const raw = await require_helpers.readBody(req);
2147
+ const storeId = pathname.split("/")[3];
2148
+ await require_vector_stores.handleVectorStoreFilesCreate(req, res, storeId, raw, journal, defaults, setCorsHeaders);
2149
+ } catch (err) {
2150
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2151
+ }
2152
+ return;
2153
+ }
2154
+ if (require_route_registry.VECTOR_STORES_FILES_RE.test(pathname) && req.method === "GET") {
2155
+ try {
2156
+ const storeId = pathname.split("/")[3];
2157
+ await require_vector_stores.handleVectorStoreFilesList(req, res, storeId, journal, defaults, setCorsHeaders);
2158
+ } catch (err) {
2159
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2160
+ }
2161
+ return;
2162
+ }
2163
+ if (require_route_registry.VECTOR_STORES_FILE_BATCHES_RE.test(pathname) && req.method === "POST") {
2164
+ try {
2165
+ const raw = await require_helpers.readBody(req);
2166
+ const storeId = pathname.split("/")[3];
2167
+ await require_vector_stores.handleVectorFileBatchesCreate(req, res, storeId, raw, journal, defaults, setCorsHeaders);
2168
+ } catch (err) {
2169
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2170
+ }
2171
+ return;
2172
+ }
2173
+ if (pathname === require_route_registry.VECTOR_STORES_PATH && req.method === "GET") {
2174
+ try {
2175
+ await require_vector_stores.handleVectorStoresList(req, res, journal, defaults, setCorsHeaders);
2176
+ } catch (err) {
2177
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2178
+ }
2179
+ return;
2180
+ }
2181
+ if (pathname === require_route_registry.VECTOR_STORES_PATH && req.method === "POST") {
2182
+ try {
2183
+ await require_vector_stores.handleVectorStoresCreate(req, res, await require_helpers.readBody(req), journal, defaults, setCorsHeaders);
2184
+ } catch (err) {
2185
+ routeError(req, res, err, pathname, { service: "vector-stores" });
2186
+ }
2187
+ return;
2188
+ }
2189
+ if (pathname === require_route_registry.REQUESTS_PATH) {
1803
2190
  setCorsHeaders(res);
1804
2191
  if (req.method === "GET") {
1805
2192
  const limitParam = parsedUrl.searchParams.get("limit");
1806
2193
  let opts;
1807
2194
  if (limitParam) {
1808
- const limit = parseInt(limitParam, 10);
1809
- if (Number.isNaN(limit) || limit <= 0) {
2195
+ const limit = Number(limitParam);
2196
+ if (!/^\+?\d+$/.test(limitParam.trim()) || !Number.isSafeInteger(limit) || limit <= 0) {
1810
2197
  require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
1811
2198
  message: `Invalid limit parameter: "${limitParam}"`,
1812
2199
  type: "invalid_request_error"
@@ -1829,7 +2216,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1829
2216
  handleNotFound(res, "Not found");
1830
2217
  return;
1831
2218
  }
1832
- if (pathname === RESPONSES_PATH && req.method === "POST") {
2219
+ if (pathname === require_route_registry.RESPONSES_PATH && req.method === "POST") {
1833
2220
  try {
1834
2221
  await require_responses.handleResponses(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
1835
2222
  } catch (err) {
@@ -1837,7 +2224,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1837
2224
  }
1838
2225
  return;
1839
2226
  }
1840
- if (pathname === MESSAGES_PATH && req.method === "POST") {
2227
+ if (pathname === require_route_registry.MESSAGES_PATH && req.method === "POST") {
1841
2228
  try {
1842
2229
  await require_messages.handleMessages(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
1843
2230
  } catch (err) {
@@ -1845,7 +2232,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1845
2232
  }
1846
2233
  return;
1847
2234
  }
1848
- if (pathname === COHERE_CHAT_PATH && req.method === "POST") {
2235
+ if (pathname === require_route_registry.COHERE_CHAT_PATH && req.method === "POST") {
1849
2236
  try {
1850
2237
  await require_cohere.handleCohere(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
1851
2238
  } catch (err) {
@@ -1853,7 +2240,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1853
2240
  }
1854
2241
  return;
1855
2242
  }
1856
- if (pathname === COHERE_EMBED_PATH && req.method === "POST") {
2243
+ if (pathname === require_route_registry.COHERE_EMBED_PATH && req.method === "POST") {
1857
2244
  try {
1858
2245
  await require_cohere.handleCohereEmbed(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
1859
2246
  } catch (err) {
@@ -1861,7 +2248,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1861
2248
  }
1862
2249
  return;
1863
2250
  }
1864
- if (pathname === EMBEDDINGS_PATH && req.method === "POST") {
2251
+ if (pathname === require_route_registry.EMBEDDINGS_PATH && req.method === "POST") {
1865
2252
  try {
1866
2253
  const deploymentId = azureDeploymentId;
1867
2254
  const embeddingsProvider = azureDeploymentId ? "azure" : "openai";
@@ -1875,13 +2262,13 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1875
2262
  } catch (err) {
1876
2263
  if (!(err instanceof SyntaxError)) defaults.logger.error(`Unexpected error in Azure model injection: ${err instanceof Error ? err.message : String(err)}`);
1877
2264
  }
1878
- await require_embeddings.handleEmbeddings(req, res, raw, fixtures, journal, defaults, setCorsHeaders, embeddingsProvider);
2265
+ await require_embeddings.handleEmbeddings(req, res, raw, fixtures, journal, defaults, setCorsHeaders, embeddingsProvider, originalPathname === require_route_registry.EMBEDDINGS_PATH);
1879
2266
  } catch (err) {
1880
2267
  routeError(req, res, err, pathname);
1881
2268
  }
1882
2269
  return;
1883
2270
  }
1884
- if (pathname === IMAGES_PATH && req.method === "POST") {
2271
+ if (pathname === require_route_registry.IMAGES_PATH && req.method === "POST") {
1885
2272
  try {
1886
2273
  await require_images.handleImages(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, "openai", void 0, isBytePlusArk ? "byteplus" : void 0);
1887
2274
  } catch (err) {
@@ -1889,7 +2276,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1889
2276
  }
1890
2277
  return;
1891
2278
  }
1892
- if (pathname === IMAGES_EDIT_PATH && req.method === "POST") {
2279
+ if (pathname === require_route_registry.IMAGES_EDIT_PATH && req.method === "POST") {
1893
2280
  try {
1894
2281
  await require_images.handleImageEdit(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
1895
2282
  } catch (err) {
@@ -1897,7 +2284,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1897
2284
  }
1898
2285
  return;
1899
2286
  }
1900
- if (pathname === IMAGES_VARIATIONS_PATH && req.method === "POST") {
2287
+ if (pathname === require_route_registry.IMAGES_VARIATIONS_PATH && req.method === "POST") {
1901
2288
  try {
1902
2289
  await require_images.handleImageVariations(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
1903
2290
  } catch (err) {
@@ -1905,7 +2292,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1905
2292
  }
1906
2293
  return;
1907
2294
  }
1908
- if (pathname === SPEECH_PATH && req.method === "POST") {
2295
+ if (pathname === require_route_registry.SPEECH_PATH && req.method === "POST") {
1909
2296
  try {
1910
2297
  await require_speech.handleSpeech(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
1911
2298
  } catch (err) {
@@ -1913,7 +2300,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1913
2300
  }
1914
2301
  return;
1915
2302
  }
1916
- if (pathname === TRANSCRIPTIONS_PATH && req.method === "POST") {
2303
+ if (pathname === require_route_registry.TRANSCRIPTIONS_PATH && req.method === "POST") {
1917
2304
  try {
1918
2305
  await require_transcription.handleTranscription(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
1919
2306
  } catch (err) {
@@ -1921,7 +2308,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1921
2308
  }
1922
2309
  return;
1923
2310
  }
1924
- if (pathname === TRANSLATIONS_PATH && req.method === "POST") {
2311
+ if (pathname === require_route_registry.TRANSLATIONS_PATH && req.method === "POST") {
1925
2312
  try {
1926
2313
  await require_transcription.handleTranscription(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, "translation");
1927
2314
  } catch (err) {
@@ -1929,7 +2316,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1929
2316
  }
1930
2317
  return;
1931
2318
  }
1932
- if (pathname === require_metrics.GROK_VIDEO_SUBMIT_PATH && req.method === "POST") {
2319
+ if (pathname === require_route_registry.GROK_VIDEO_SUBMIT_PATH && req.method === "POST") {
1933
2320
  setCorsHeaders(res);
1934
2321
  try {
1935
2322
  await require_grok_video.handleGrokVideoCreate(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, grokVideoJobs);
@@ -1938,7 +2325,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1938
2325
  }
1939
2326
  return;
1940
2327
  }
1941
- if (pathname === VIDEOS_PATH && req.method === "POST") {
2328
+ if (pathname === require_route_registry.VIDEOS_PATH && req.method === "POST") {
1942
2329
  try {
1943
2330
  await require_video.handleVideoCreate(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders, videoStates);
1944
2331
  } catch (err) {
@@ -1946,7 +2333,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1946
2333
  }
1947
2334
  return;
1948
2335
  }
1949
- const grokVideoStatusMatch = pathname.match(require_metrics.GROK_VIDEO_STATUS_RE);
2336
+ const grokVideoStatusMatch = pathname.match(require_route_registry.GROK_VIDEO_STATUS_RE);
1950
2337
  if (grokVideoStatusMatch && grokVideoStatusMatch[1] !== "generations" && req.method === "GET") {
1951
2338
  try {
1952
2339
  await require_grok_video.handleGrokVideoStatus(req, res, grokVideoStatusMatch[1], fixtures, journal, defaults, setCorsHeaders, grokVideoJobs, videoStates);
@@ -1955,7 +2342,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1955
2342
  }
1956
2343
  return;
1957
2344
  }
1958
- const veoPredictMatch = pathname.match(require_metrics.VEO_PREDICT_LRO_RE);
2345
+ const veoPredictMatch = pathname.match(require_route_registry.VEO_PREDICT_LRO_RE);
1959
2346
  if (veoPredictMatch && req.method === "POST") {
1960
2347
  setCorsHeaders(res);
1961
2348
  try {
@@ -1965,7 +2352,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1965
2352
  }
1966
2353
  return;
1967
2354
  }
1968
- const veoOperationMatch = pathname.match(require_metrics.VEO_OPERATION_RE);
2355
+ const veoOperationMatch = pathname.match(require_route_registry.VEO_OPERATION_RE);
1969
2356
  if (veoOperationMatch && req.method === "GET") {
1970
2357
  try {
1971
2358
  await require_veo_video.handleVeoVideoStatus(req, res, veoOperationMatch[1], fixtures, journal, defaults, setCorsHeaders, veoVideoJobs);
@@ -1974,7 +2361,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1974
2361
  }
1975
2362
  return;
1976
2363
  }
1977
- const geminiPredictMatch = pathname.match(GEMINI_PREDICT_RE);
2364
+ const geminiPredictMatch = pathname.match(require_route_registry.GEMINI_PREDICT_RE);
1978
2365
  if (geminiPredictMatch && req.method === "POST") {
1979
2366
  const predictModel = geminiPredictMatch[1];
1980
2367
  try {
@@ -1984,7 +2371,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1984
2371
  }
1985
2372
  return;
1986
2373
  }
1987
- if (pathname === GEMINI_INTERACTIONS_PATH && req.method === "POST") {
2374
+ if (pathname === require_route_registry.GEMINI_INTERACTIONS_PATH && req.method === "POST") {
1988
2375
  try {
1989
2376
  await require_gemini_interactions.handleGeminiInteractions(req, res, await require_helpers.readBody(req), fixtures, journal, defaults, setCorsHeaders);
1990
2377
  } catch (err) {
@@ -1992,7 +2379,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
1992
2379
  }
1993
2380
  return;
1994
2381
  }
1995
- const geminiEmbedMatch = pathname.match(GEMINI_EMBED_RE);
2382
+ const geminiEmbedMatch = pathname.match(require_route_registry.GEMINI_EMBED_RE);
1996
2383
  if (geminiEmbedMatch && req.method === "POST") {
1997
2384
  const embedModel = geminiEmbedMatch[1];
1998
2385
  try {
@@ -2002,7 +2389,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2002
2389
  }
2003
2390
  return;
2004
2391
  }
2005
- const geminiMatch = pathname.match(GEMINI_PATH_RE);
2392
+ const geminiMatch = pathname.match(require_route_registry.GEMINI_PATH_RE);
2006
2393
  if (geminiMatch && req.method === "POST") {
2007
2394
  const geminiModel = geminiMatch[1];
2008
2395
  const streaming = geminiMatch[2] === "streamGenerateContent";
@@ -2013,7 +2400,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2013
2400
  }
2014
2401
  return;
2015
2402
  }
2016
- const vertexMatch = pathname.match(VERTEX_AI_RE);
2403
+ const vertexMatch = pathname.match(require_route_registry.VERTEX_AI_RE);
2017
2404
  if (vertexMatch && req.method === "POST") {
2018
2405
  const vertexModel = vertexMatch[1];
2019
2406
  const streaming = vertexMatch[2] === "streamGenerateContent";
@@ -2024,7 +2411,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2024
2411
  }
2025
2412
  return;
2026
2413
  }
2027
- const bedrockMatch = pathname.match(BEDROCK_INVOKE_RE);
2414
+ const bedrockMatch = pathname.match(require_route_registry.BEDROCK_INVOKE_RE);
2028
2415
  if (bedrockMatch && req.method === "POST") {
2029
2416
  const bedrockModelId = bedrockMatch[1];
2030
2417
  try {
@@ -2034,7 +2421,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2034
2421
  }
2035
2422
  return;
2036
2423
  }
2037
- const bedrockStreamMatch = pathname.match(BEDROCK_STREAM_RE);
2424
+ const bedrockStreamMatch = pathname.match(require_route_registry.BEDROCK_STREAM_RE);
2038
2425
  if (bedrockStreamMatch && req.method === "POST") {
2039
2426
  const bedrockModelId = bedrockStreamMatch[1];
2040
2427
  try {
@@ -2044,7 +2431,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2044
2431
  }
2045
2432
  return;
2046
2433
  }
2047
- const converseMatch = pathname.match(BEDROCK_CONVERSE_RE);
2434
+ const converseMatch = pathname.match(require_route_registry.BEDROCK_CONVERSE_RE);
2048
2435
  if (converseMatch && req.method === "POST") {
2049
2436
  const converseModelId = converseMatch[1];
2050
2437
  try {
@@ -2054,7 +2441,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2054
2441
  }
2055
2442
  return;
2056
2443
  }
2057
- const converseStreamMatch = pathname.match(BEDROCK_CONVERSE_STREAM_RE);
2444
+ const converseStreamMatch = pathname.match(require_route_registry.BEDROCK_CONVERSE_STREAM_RE);
2058
2445
  if (converseStreamMatch && req.method === "POST") {
2059
2446
  const converseStreamModelId = converseStreamMatch[1];
2060
2447
  try {
@@ -2064,7 +2451,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2064
2451
  }
2065
2452
  return;
2066
2453
  }
2067
- if (pathname === SEARCH_PATH && req.method === "POST") {
2454
+ if (pathname === require_route_registry.SEARCH_PATH && req.method === "POST") {
2068
2455
  try {
2069
2456
  await require_search.handleSearch(req, res, await require_helpers.readBody(req), serviceFixtures?.search ?? [], journal, defaults, setCorsHeaders);
2070
2457
  } catch (err) {
@@ -2072,7 +2459,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2072
2459
  }
2073
2460
  return;
2074
2461
  }
2075
- if (pathname === RERANK_PATH && req.method === "POST") {
2462
+ if (pathname === require_route_registry.RERANK_PATH && req.method === "POST") {
2076
2463
  try {
2077
2464
  await require_rerank.handleRerank(req, res, await require_helpers.readBody(req), serviceFixtures?.rerank ?? [], journal, defaults, setCorsHeaders);
2078
2465
  } catch (err) {
@@ -2080,7 +2467,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2080
2467
  }
2081
2468
  return;
2082
2469
  }
2083
- if (pathname === MODERATIONS_PATH && req.method === "POST") {
2470
+ if (pathname === require_route_registry.MODERATIONS_PATH && req.method === "POST") {
2084
2471
  try {
2085
2472
  await require_moderation.handleModeration(req, res, await require_helpers.readBody(req), serviceFixtures?.moderation ?? [], journal, defaults, setCorsHeaders);
2086
2473
  } catch (err) {
@@ -2088,7 +2475,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2088
2475
  }
2089
2476
  return;
2090
2477
  }
2091
- if (pathname === ELEVENLABS_SOUND_GENERATION_PATH && req.method === "POST") {
2478
+ if (pathname === require_route_registry.ELEVENLABS_SOUND_GENERATION_PATH && req.method === "POST") {
2092
2479
  setCorsHeaders(res);
2093
2480
  try {
2094
2481
  await require_elevenlabs_audio.handleElevenLabsAudio(req, res, await require_helpers.readBody(req), fixtures, defaults, journal, "sound-generation");
@@ -2097,7 +2484,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2097
2484
  }
2098
2485
  return;
2099
2486
  }
2100
- if (pathname === ELEVENLABS_VOICE_DESIGN_PATH && req.method === "POST") {
2487
+ if (pathname === require_route_registry.ELEVENLABS_VOICE_DESIGN_PATH && req.method === "POST") {
2101
2488
  setCorsHeaders(res);
2102
2489
  try {
2103
2490
  await require_elevenlabs_voice.handleElevenLabsVoiceDesign(req, res, await require_helpers.readBody(req), fixtures, defaults, journal);
@@ -2106,7 +2493,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2106
2493
  }
2107
2494
  return;
2108
2495
  }
2109
- if (pathname === ELEVENLABS_VOICE_CREATE_PATH && req.method === "POST") {
2496
+ if (pathname === require_route_registry.ELEVENLABS_VOICE_CREATE_PATH && req.method === "POST") {
2110
2497
  setCorsHeaders(res);
2111
2498
  try {
2112
2499
  await require_elevenlabs_voice.handleElevenLabsVoiceCreate(req, res, await require_helpers.readBody(req), fixtures, defaults, journal);
@@ -2115,7 +2502,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2115
2502
  }
2116
2503
  return;
2117
2504
  }
2118
- const elevenLabsVoiceMatch = pathname.match(ELEVENLABS_VOICE_RE);
2505
+ const elevenLabsVoiceMatch = pathname.match(require_route_registry.ELEVENLABS_VOICE_RE);
2119
2506
  if (elevenLabsVoiceMatch && (req.method === "GET" || req.method === "DELETE")) {
2120
2507
  setCorsHeaders(res);
2121
2508
  let voiceId;
@@ -2147,7 +2534,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2147
2534
  }
2148
2535
  return;
2149
2536
  }
2150
- const elevenLabsTTSMatch = pathname.match(ELEVENLABS_TTS_RE);
2537
+ const elevenLabsTTSMatch = pathname.match(require_route_registry.ELEVENLABS_TTS_RE);
2151
2538
  if (elevenLabsTTSMatch && req.method === "POST") {
2152
2539
  setCorsHeaders(res);
2153
2540
  const voiceId = elevenLabsTTSMatch[1];
@@ -2158,7 +2545,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2158
2545
  }
2159
2546
  return;
2160
2547
  }
2161
- const musicMatch = pathname.match(ELEVENLABS_MUSIC_RE);
2548
+ const musicMatch = pathname.match(require_route_registry.ELEVENLABS_MUSIC_RE);
2162
2549
  if (musicMatch && req.method === "POST") {
2163
2550
  setCorsHeaders(res);
2164
2551
  const musicSubType = musicMatch[1] ?? "music";
@@ -2170,7 +2557,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2170
2557
  return;
2171
2558
  }
2172
2559
  let falBody;
2173
- if (require_metrics.FAL_ROUTE_RE.test(pathname) && req.headers["x-fal-target-host"]) {
2560
+ if (require_route_registry.FAL_ROUTE_RE.test(pathname) && req.headers["x-fal-target-host"]) {
2174
2561
  setCorsHeaders(res);
2175
2562
  try {
2176
2563
  falBody = req.method === "POST" || req.method === "PUT" ? await require_helpers.readBody(req) : "";
@@ -2200,7 +2587,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2200
2587
  return;
2201
2588
  }
2202
2589
  }
2203
- if (pathname.match(FAL_QUEUE_SUBMIT_RE) && req.method === "POST") {
2590
+ if (pathname.match(require_route_registry.FAL_QUEUE_SUBMIT_RE) && req.method === "POST") {
2204
2591
  setCorsHeaders(res);
2205
2592
  try {
2206
2593
  await require_fal_audio.handleFalQueue(req, res, falBody ?? await require_helpers.readBody(req), pathname, fixtures, defaults, journal);
@@ -2209,7 +2596,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2209
2596
  }
2210
2597
  return;
2211
2598
  }
2212
- if (pathname.match(FAL_QUEUE_REQUESTS_RE) && (req.method === "GET" || req.method === "POST" || req.method === "PUT")) {
2599
+ if (pathname.match(require_route_registry.FAL_QUEUE_REQUESTS_RE) && (req.method === "GET" || req.method === "POST" || req.method === "PUT")) {
2213
2600
  setCorsHeaders(res);
2214
2601
  try {
2215
2602
  const raw = req.method === "POST" || req.method === "PUT" ? falBody ?? await require_helpers.readBody(req) : "{}";
@@ -2236,7 +2623,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2236
2623
  }
2237
2624
  return;
2238
2625
  }
2239
- if (pathname.match(FAL_RUN_RE) && req.method === "POST") {
2626
+ if (pathname.match(require_route_registry.FAL_RUN_RE) && req.method === "POST") {
2240
2627
  setCorsHeaders(res);
2241
2628
  try {
2242
2629
  await require_fal_audio.handleFalQueue(req, res, falBody ?? await require_helpers.readBody(req), pathname, fixtures, defaults, journal);
@@ -2245,7 +2632,9 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2245
2632
  }
2246
2633
  return;
2247
2634
  }
2248
- if (pathname !== COMPLETIONS_PATH) {
2635
+ if (pathname !== require_route_registry.COMPLETIONS_PATH) {
2636
+ const catalogMatch = require_route_registry.matchRouteDefinition(req.method ?? "", pathname);
2637
+ if (catalogMatch && !(pathname === require_route_registry.METRICS_PATH && !registry)) defaults.logger.warn(`Route drift: ${req.method ?? "?"} ${pathname} matches the route catalog (${catalogMatch.method} ${catalogMatch.path} — ${catalogMatch.description}) but no dispatcher branch served it. The catalog entry or the dispatcher is stale — see route-registry.ts.`);
2249
2638
  handleNotFound(res, "Not found");
2250
2639
  return;
2251
2640
  }
@@ -2325,26 +2714,32 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2325
2714
  server.emit("connection", socket);
2326
2715
  return;
2327
2716
  }
2328
- const parsedUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
2717
+ let parsedUrl;
2718
+ try {
2719
+ parsedUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
2720
+ } catch (err) {
2721
+ const msg = err instanceof Error ? err.message : "Internal error";
2722
+ defaults.logger.warn(`Unhandled upgrade error: ${msg}`);
2723
+ socket.end("HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n");
2724
+ return;
2725
+ }
2329
2726
  let pathname = parsedUrl.pathname;
2330
2727
  if (!require_api_key_auth.validateRequestApiKey(req, resolvedAuth.policy).ok) {
2331
2728
  require_api_key_auth.writeApiKeyUpgradeRejection(socket);
2332
2729
  return;
2333
2730
  }
2334
- if (mounts) {
2335
- for (const { path: mountPath, handler } of mounts) if ((pathname === mountPath || pathname.startsWith(mountPath + "/")) && handler.handleUpgrade) {
2336
- const subPath = pathname.slice(mountPath.length) || "/";
2337
- if (await handler.handleUpgrade(socket, head, subPath)) return;
2338
- }
2731
+ for (const { path: mountPath, handler } of mountList) if ((pathname === mountPath || pathname.startsWith(mountPath + "/")) && handler.handleUpgrade) {
2732
+ const subPath = pathname.slice(mountPath.length) || "/";
2733
+ if (await handler.handleUpgrade(socket, head, subPath)) return;
2339
2734
  }
2340
- if (!pathname.match(AZURE_DEPLOYMENT_RE)) pathname = normalizeCompatPath(pathname, logger);
2341
- if (pathname !== RESPONSES_PATH && pathname !== REALTIME_PATH && pathname !== GEMINI_LIVE_PATH && pathname !== LIVE_PATH) {
2735
+ if (!pathname.match(require_route_registry.AZURE_DEPLOYMENT_RE)) pathname = normalizeCompatPath(pathname, logger);
2736
+ if (pathname !== require_route_registry.RESPONSES_PATH && pathname !== require_route_registry.REALTIME_PATH && pathname !== require_route_registry.GEMINI_LIVE_PATH && pathname !== require_route_registry.LIVE_PATH) {
2342
2737
  socket.write("HTTP/1.1 404 Not Found\r\n\r\n");
2343
2738
  socket.destroy();
2344
2739
  return;
2345
2740
  }
2346
2741
  let liveId;
2347
- if (pathname === LIVE_PATH) {
2742
+ if (pathname === require_route_registry.LIVE_PATH) {
2348
2743
  if (req.method !== "GET" || parsedUrl.searchParams.has("model")) {
2349
2744
  socket.end("HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n");
2350
2745
  return;
@@ -2366,7 +2761,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2366
2761
  if (head.length > 0) socket.unshift(head);
2367
2762
  let ws;
2368
2763
  try {
2369
- ws = require_ws_framing.upgradeToWebSocket(req, socket, pathname === LIVE_PATH ? liveLimits : void 0);
2764
+ ws = require_ws_framing.upgradeToWebSocket(req, socket, pathname === require_route_registry.LIVE_PATH ? liveLimits : void 0);
2370
2765
  } catch (err) {
2371
2766
  const msg = err instanceof Error ? err.message : "WebSocket upgrade failed";
2372
2767
  if (liveId !== void 0) liveSessions.delete(liveId);
@@ -2383,7 +2778,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2383
2778
  activeConnections.delete(ws);
2384
2779
  });
2385
2780
  const wsTestId = require_helpers.getTestId(req);
2386
- if (pathname === LIVE_PATH && liveId !== void 0) {
2781
+ if (pathname === require_route_registry.LIVE_PATH && liveId !== void 0) {
2387
2782
  const sessionId = liveId;
2388
2783
  const dispose = require_ws_live.handleLiveSession(ws, fixtures, journal, {
2389
2784
  defaults,
@@ -2400,13 +2795,13 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2400
2795
  testId: wsTestId,
2401
2796
  dispose
2402
2797
  });
2403
- } else if (pathname === RESPONSES_PATH) require_ws_responses.handleWebSocketResponses(ws, fixtures, journal, {
2798
+ } else if (pathname === require_route_registry.RESPONSES_PATH) require_ws_responses.handleWebSocketResponses(ws, fixtures, journal, {
2404
2799
  ...defaults,
2405
2800
  model: "gpt-4",
2406
2801
  testId: wsTestId,
2407
2802
  upgradeHeaders: req.headers
2408
2803
  });
2409
- else if (pathname === REALTIME_PATH) {
2804
+ else if (pathname === require_route_registry.REALTIME_PATH) {
2410
2805
  const transcriptionIntent = parsedUrl.searchParams.get("intent") === "transcription";
2411
2806
  const model = transcriptionIntent ? "gpt-transcribe" : parsedUrl.searchParams.get("model") ?? "gpt-realtime-2";
2412
2807
  require_ws_realtime.handleWebSocketRealtime(ws, fixtures, journal, {
@@ -2416,7 +2811,7 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2416
2811
  testId: wsTestId,
2417
2812
  upgradeHeaders: req.headers
2418
2813
  });
2419
- } else if (pathname === GEMINI_LIVE_PATH) require_ws_gemini_live.handleWebSocketGeminiLive(ws, fixtures, journal, {
2814
+ } else if (pathname === require_route_registry.GEMINI_LIVE_PATH) require_ws_gemini_live.handleWebSocketGeminiLive(ws, fixtures, journal, {
2420
2815
  ...defaults,
2421
2816
  model: "gemini-2.0-flash",
2422
2817
  testId: wsTestId,
@@ -2445,9 +2840,13 @@ async function createServerWithResolvedAuth(fixtures, options, resolvedAuth, mou
2445
2840
  return;
2446
2841
  }
2447
2842
  const url = `http://${addr.address}:${addr.port}`;
2448
- if (mounts) {
2449
- for (const { path: mountPath, handler } of mounts) if (handler.setBaseUrl) handler.setBaseUrl(url + mountPath);
2843
+ try {
2844
+ commitHandOff();
2845
+ } catch (err) {
2846
+ server.close(() => reject(err));
2847
+ return;
2450
2848
  }
2849
+ for (const { path: mountPath, handler } of mountList) if (handler.setBaseUrl) handler.setBaseUrl(url + mountPath);
2451
2850
  resolve({
2452
2851
  closeLiveSessions,
2453
2852
  server,