@copilotkit/aimock 1.24.0 → 1.25.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 (154) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +35 -0
  4. package/README.md +17 -11
  5. package/dist/agui-types.d.cts.map +1 -1
  6. package/dist/agui-types.d.ts.map +1 -1
  7. package/dist/bedrock-converse.cjs +2 -2
  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 +2 -2
  12. package/dist/bedrock-converse.js.map +1 -1
  13. package/dist/bedrock.cjs +2 -2
  14. package/dist/bedrock.cjs.map +1 -1
  15. package/dist/bedrock.d.cts.map +1 -1
  16. package/dist/bedrock.d.ts.map +1 -1
  17. package/dist/bedrock.js +2 -2
  18. package/dist/bedrock.js.map +1 -1
  19. package/dist/cli.cjs +25 -1
  20. package/dist/cli.cjs.map +1 -1
  21. package/dist/cli.js +25 -1
  22. package/dist/cli.js.map +1 -1
  23. package/dist/cohere.cjs +198 -1
  24. package/dist/cohere.cjs.map +1 -1
  25. package/dist/cohere.d.cts.map +1 -1
  26. package/dist/cohere.d.ts.map +1 -1
  27. package/dist/cohere.js +199 -3
  28. package/dist/cohere.js.map +1 -1
  29. package/dist/elevenlabs-audio.cjs +173 -1
  30. package/dist/elevenlabs-audio.cjs.map +1 -1
  31. package/dist/elevenlabs-audio.d.cts.map +1 -1
  32. package/dist/elevenlabs-audio.d.ts.map +1 -1
  33. package/dist/elevenlabs-audio.js +173 -2
  34. package/dist/elevenlabs-audio.js.map +1 -1
  35. package/dist/embeddings.cjs +1 -1
  36. package/dist/embeddings.cjs.map +1 -1
  37. package/dist/embeddings.js +1 -1
  38. package/dist/embeddings.js.map +1 -1
  39. package/dist/fal-audio.cjs +2 -4
  40. package/dist/fal-audio.cjs.map +1 -1
  41. package/dist/fal-audio.js +2 -4
  42. package/dist/fal-audio.js.map +1 -1
  43. package/dist/fal.cjs +2 -2
  44. package/dist/fal.cjs.map +1 -1
  45. package/dist/fal.d.cts.map +1 -1
  46. package/dist/fal.d.ts.map +1 -1
  47. package/dist/fal.js +2 -2
  48. package/dist/fal.js.map +1 -1
  49. package/dist/gemini-embeddings.cjs +166 -0
  50. package/dist/gemini-embeddings.cjs.map +1 -0
  51. package/dist/gemini-embeddings.js +166 -0
  52. package/dist/gemini-embeddings.js.map +1 -0
  53. package/dist/gemini-interactions.cjs +1 -1
  54. package/dist/gemini-interactions.cjs.map +1 -1
  55. package/dist/gemini-interactions.js +1 -1
  56. package/dist/gemini-interactions.js.map +1 -1
  57. package/dist/gemini.cjs +5 -3
  58. package/dist/gemini.cjs.map +1 -1
  59. package/dist/gemini.d.cts.map +1 -1
  60. package/dist/gemini.d.ts.map +1 -1
  61. package/dist/gemini.js +5 -3
  62. package/dist/gemini.js.map +1 -1
  63. package/dist/helpers.cjs +70 -33
  64. package/dist/helpers.cjs.map +1 -1
  65. package/dist/helpers.d.cts +9 -5
  66. package/dist/helpers.d.cts.map +1 -1
  67. package/dist/helpers.d.ts +9 -5
  68. package/dist/helpers.d.ts.map +1 -1
  69. package/dist/helpers.js +68 -34
  70. package/dist/helpers.js.map +1 -1
  71. package/dist/images.cjs +295 -13
  72. package/dist/images.cjs.map +1 -1
  73. package/dist/images.d.cts +9 -1
  74. package/dist/images.d.cts.map +1 -1
  75. package/dist/images.d.ts +9 -1
  76. package/dist/images.d.ts.map +1 -1
  77. package/dist/images.js +294 -14
  78. package/dist/images.js.map +1 -1
  79. package/dist/index.cjs +1 -1
  80. package/dist/index.d.cts +2 -2
  81. package/dist/index.d.ts +2 -2
  82. package/dist/index.js +1 -1
  83. package/dist/llmock.cjs +15 -0
  84. package/dist/llmock.cjs.map +1 -1
  85. package/dist/llmock.d.cts +2 -0
  86. package/dist/llmock.d.cts.map +1 -1
  87. package/dist/llmock.d.ts +2 -0
  88. package/dist/llmock.d.ts.map +1 -1
  89. package/dist/llmock.js +15 -0
  90. package/dist/llmock.js.map +1 -1
  91. package/dist/messages.cjs +1 -1
  92. package/dist/messages.cjs.map +1 -1
  93. package/dist/messages.js +1 -1
  94. package/dist/messages.js.map +1 -1
  95. package/dist/metrics.cjs +2 -0
  96. package/dist/metrics.cjs.map +1 -1
  97. package/dist/metrics.d.cts.map +1 -1
  98. package/dist/metrics.d.ts.map +1 -1
  99. package/dist/metrics.js +2 -0
  100. package/dist/metrics.js.map +1 -1
  101. package/dist/ollama.cjs +189 -2
  102. package/dist/ollama.cjs.map +1 -1
  103. package/dist/ollama.d.cts.map +1 -1
  104. package/dist/ollama.d.ts.map +1 -1
  105. package/dist/ollama.js +190 -4
  106. package/dist/ollama.js.map +1 -1
  107. package/dist/recorder.cjs +11 -4
  108. package/dist/recorder.cjs.map +1 -1
  109. package/dist/recorder.js +11 -4
  110. package/dist/recorder.js.map +1 -1
  111. package/dist/responses.cjs +1 -1
  112. package/dist/responses.cjs.map +1 -1
  113. package/dist/responses.js +1 -1
  114. package/dist/responses.js.map +1 -1
  115. package/dist/server.cjs +188 -48
  116. package/dist/server.cjs.map +1 -1
  117. package/dist/server.d.cts.map +1 -1
  118. package/dist/server.d.ts.map +1 -1
  119. package/dist/server.js +193 -53
  120. package/dist/server.js.map +1 -1
  121. package/dist/speech.cjs +1 -1
  122. package/dist/speech.cjs.map +1 -1
  123. package/dist/speech.js +1 -1
  124. package/dist/speech.js.map +1 -1
  125. package/dist/sse-writer.cjs +20 -2
  126. package/dist/sse-writer.cjs.map +1 -1
  127. package/dist/sse-writer.d.cts +8 -2
  128. package/dist/sse-writer.d.cts.map +1 -1
  129. package/dist/sse-writer.d.ts +8 -2
  130. package/dist/sse-writer.d.ts.map +1 -1
  131. package/dist/sse-writer.js +20 -2
  132. package/dist/sse-writer.js.map +1 -1
  133. package/dist/transcription.cjs +9 -6
  134. package/dist/transcription.cjs.map +1 -1
  135. package/dist/transcription.d.cts +2 -2
  136. package/dist/transcription.d.cts.map +1 -1
  137. package/dist/transcription.d.ts +2 -2
  138. package/dist/transcription.d.ts.map +1 -1
  139. package/dist/transcription.js +8 -7
  140. package/dist/transcription.js.map +1 -1
  141. package/dist/types.d.cts +28 -2
  142. package/dist/types.d.cts.map +1 -1
  143. package/dist/types.d.ts +28 -2
  144. package/dist/types.d.ts.map +1 -1
  145. package/dist/vector-types.d.cts.map +1 -1
  146. package/dist/video.cjs +1 -1
  147. package/dist/video.cjs.map +1 -1
  148. package/dist/video.d.cts.map +1 -1
  149. package/dist/video.d.ts.map +1 -1
  150. package/dist/video.js +1 -1
  151. package/dist/video.js.map +1 -1
  152. package/dist/ws-gemini-live.d.ts +2 -2
  153. package/dist/ws-realtime.d.ts +2 -2
  154. package/package.json +2 -2
package/dist/server.js CHANGED
@@ -1,4 +1,4 @@
1
- import { buildContentWithToolCallsChunks, buildContentWithToolCallsCompletion, buildTextChunks, buildTextCompletion, buildToolCallChunks, buildToolCallCompletion, extractOverrides, flattenHeaders, getTestId, isAudioResponse, isContentWithToolCallsResponse, isErrorResponse, isTextResponse, isToolCallResponse, readBody, resolveResponse, resolveStrictMode, serializeErrorResponse, strictOverrideField } from "./helpers.js";
1
+ import { buildContentWithToolCallsChunks, buildContentWithToolCallsCompletion, buildTextChunks, buildTextCompletion, buildToolCallChunks, buildToolCallCompletion, buildUsageChunk, estimatePromptTokens, estimateTokens, extractOverrides, flattenHeaders, getTestId, isAudioResponse, isContentWithToolCallsResponse, isErrorResponse, isTextResponse, isToolCallResponse, readBody, resolveResponse, resolveStrictMode, serializeErrorResponse, strictOverrideField } from "./helpers.js";
2
2
  import { Logger } from "./logger.js";
3
3
  import { Journal } from "./journal.js";
4
4
  import { matchFixture } from "./router.js";
@@ -10,19 +10,20 @@ import { proxyAndRecord } from "./recorder.js";
10
10
  import { handleResponses } from "./responses.js";
11
11
  import { handleMessages } from "./messages.js";
12
12
  import { handleGemini } from "./gemini.js";
13
+ import { handleGeminiEmbedContent } from "./gemini-embeddings.js";
13
14
  import { handleBedrock, handleBedrockStream } from "./bedrock.js";
14
15
  import { handleConverse, handleConverseStream } from "./bedrock-converse.js";
15
16
  import { handleGeminiInteractions, resetEventIdCounter, resetInteractionCounter } from "./gemini-interactions.js";
16
17
  import { handleEmbeddings } from "./embeddings.js";
17
- import { handleImages } from "./images.js";
18
- import { handleSpeech } from "./speech.js";
19
18
  import { handleTranscription } from "./transcription.js";
19
+ import { handleImageEdit, handleImageVariations, handleImages } from "./images.js";
20
+ import { handleSpeech } from "./speech.js";
20
21
  import { VideoStateMap, handleVideoCreate, handleVideoStatus } from "./video.js";
21
- import { handleElevenLabsAudio } from "./elevenlabs-audio.js";
22
+ import { handleElevenLabsAudio, handleElevenLabsTTS } from "./elevenlabs-audio.js";
22
23
  import { falQueueStates, handleFal } from "./fal.js";
23
24
  import { falJobs, handleFalQueue } from "./fal-audio.js";
24
- import { handleOllama, handleOllamaGenerate } from "./ollama.js";
25
- import { handleCohere } from "./cohere.js";
25
+ import { handleOllama, handleOllamaEmbeddings, handleOllamaGenerate } from "./ollama.js";
26
+ import { handleCohere, handleCohereEmbed } from "./cohere.js";
26
27
  import { handleSearch } from "./search.js";
27
28
  import { handleRerank } from "./rerank.js";
28
29
  import { handleModeration } from "./moderation.js";
@@ -41,16 +42,21 @@ const GEMINI_LIVE_PATH = "/ws/google.ai.generativelanguage.v1beta.GenerativeServ
41
42
  const MESSAGES_PATH = "/v1/messages";
42
43
  const EMBEDDINGS_PATH = "/v1/embeddings";
43
44
  const COHERE_CHAT_PATH = "/v2/chat";
45
+ const COHERE_EMBED_PATH = "/v2/embed";
44
46
  const SEARCH_PATH = "/search";
45
47
  const RERANK_PATH = "/v2/rerank";
46
48
  const MODERATIONS_PATH = "/v1/moderations";
47
49
  const IMAGES_PATH = "/v1/images/generations";
50
+ const IMAGES_EDIT_PATH = "/v1/images/edit";
51
+ const IMAGES_VARIATIONS_PATH = "/v1/images/variations";
48
52
  const SPEECH_PATH = "/v1/audio/speech";
49
53
  const TRANSCRIPTIONS_PATH = "/v1/audio/transcriptions";
54
+ const TRANSLATIONS_PATH = "/v1/audio/translations";
50
55
  const VIDEOS_PATH = "/v1/videos";
51
56
  const VIDEOS_STATUS_RE = /^\/v1\/videos\/([^/]+)$/;
52
57
  const GEMINI_PREDICT_RE = /^\/v1beta\/models\/([^:]+):predict$/;
53
58
  const ELEVENLABS_SOUND_GENERATION_PATH = "/v1/sound-generation";
59
+ const ELEVENLABS_TTS_RE = /^\/v1\/text-to-speech\/([^/]+)$/;
54
60
  const ELEVENLABS_MUSIC_RE = /^\/v1\/music(?:\/(.+))?$/;
55
61
  const FAL_QUEUE_SUBMIT_RE = /^\/fal\/queue\/submit\/(.+)$/;
56
62
  const FAL_QUEUE_REQUESTS_RE = /^\/fal\/queue\/requests\/(.+)$/;
@@ -63,7 +69,10 @@ const COMPAT_SUFFIXES = [
63
69
  "/responses",
64
70
  "/audio/speech",
65
71
  "/audio/transcriptions",
66
- "/images/generations"
72
+ "/audio/translations",
73
+ "/images/generations",
74
+ "/images/edit",
75
+ "/images/variations"
67
76
  ];
68
77
  /**
69
78
  * Normalize OpenAI-compatible paths with arbitrary prefixes.
@@ -83,6 +92,7 @@ function normalizeCompatPath(pathname, logger) {
83
92
  }
84
93
  const GEMINI_INTERACTIONS_PATH = "/v1beta/interactions";
85
94
  const GEMINI_PATH_RE = /^\/v1beta\/models\/([^:]+):(generateContent|streamGenerateContent)$/;
95
+ const GEMINI_EMBED_RE = /^\/v1beta\/models\/([^:]+):embedContent$/;
86
96
  const AZURE_DEPLOYMENT_RE = /^\/openai\/deployments\/([^/]+)\/(chat\/completions|embeddings)$/;
87
97
  const BEDROCK_INVOKE_RE = /^\/model\/([^/]+)\/invoke$/;
88
98
  const BEDROCK_STREAM_RE = /^\/model\/([^/]+)\/invoke-with-response-stream$/;
@@ -91,6 +101,7 @@ const BEDROCK_CONVERSE_STREAM_RE = /^\/model\/([^/]+)\/converse-stream$/;
91
101
  const VERTEX_AI_RE = /^\/v1\/projects\/[^/]+\/locations\/[^/]+\/publishers\/google\/models\/([^/:]+):(generateContent|streamGenerateContent)$/;
92
102
  const OLLAMA_CHAT_PATH = "/api/chat";
93
103
  const OLLAMA_GENERATE_PATH = "/api/generate";
104
+ const OLLAMA_EMBEDDINGS_PATH = "/api/embeddings";
94
105
  const OLLAMA_TAGS_PATH = "/api/tags";
95
106
  const HEALTH_PATH = "/health";
96
107
  const READY_PATH = "/ready";
@@ -433,6 +444,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
433
444
  const response = await resolveResponse(fixture, body);
434
445
  const latency = fixture.latency ?? defaults.latency;
435
446
  const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
447
+ const includeUsage = body.stream === true && body.stream_options?.include_usage === true;
436
448
  if (isErrorResponse(response)) {
437
449
  const status = response.status ?? 500;
438
450
  journal.add({
@@ -445,7 +457,7 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
445
457
  fixture
446
458
  }
447
459
  });
448
- writeErrorResponse(res, status, serializeErrorResponse(response));
460
+ writeErrorResponse(res, status, serializeErrorResponse(response), { retryAfter: response.retryAfter });
449
461
  return;
450
462
  }
451
463
  if (isAudioResponse(response)) {
@@ -479,17 +491,28 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
479
491
  }
480
492
  });
481
493
  if (body.stream !== true) {
482
- const completion = buildContentWithToolCallsCompletion(response.content, response.toolCalls, body.model, response.reasoning, overrides);
494
+ const completion = buildContentWithToolCallsCompletion(response.content, response.toolCalls, body.model, response.reasoning, overrides, body.messages);
483
495
  res.writeHead(200, { "Content-Type": "application/json" });
484
496
  res.end(JSON.stringify(completion));
485
497
  } else {
486
498
  const chunks = buildContentWithToolCallsChunks(response.content, response.toolCalls, body.model, chunkSize, response.reasoning, overrides);
499
+ const completionText = response.content + response.toolCalls.map((tc) => tc.name + tc.arguments).join("");
500
+ const usageChunk = includeUsage ? buildUsageChunk(chunks[0]?.id ?? "chatcmpl-unknown", overrides?.model ?? body.model, chunks[0]?.created ?? Math.floor(Date.now() / 1e3), overrides?.usage ? {
501
+ prompt_tokens: overrides.usage.prompt_tokens ?? 0,
502
+ completion_tokens: overrides.usage.completion_tokens ?? 0,
503
+ total_tokens: overrides.usage.total_tokens ?? (overrides.usage.prompt_tokens ?? 0) + (overrides.usage.completion_tokens ?? 0)
504
+ } : {
505
+ prompt_tokens: estimatePromptTokens(body.messages),
506
+ completion_tokens: estimateTokens(completionText),
507
+ total_tokens: estimatePromptTokens(body.messages) + estimateTokens(completionText)
508
+ }, overrides?.systemFingerprint) : void 0;
487
509
  const interruption = createInterruptionSignal(fixture);
488
510
  if (!await writeSSEStream(res, chunks, {
489
511
  latency,
490
512
  streamingProfile: fixture.streamingProfile,
491
513
  signal: interruption?.signal,
492
- onChunkSent: interruption?.tick
514
+ onChunkSent: interruption?.tick,
515
+ usageChunk
493
516
  })) {
494
517
  if (!res.writableEnded) res.destroy();
495
518
  journalEntry.response.interrupted = true;
@@ -513,17 +536,27 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
513
536
  }
514
537
  });
515
538
  if (body.stream !== true) {
516
- const completion = buildTextCompletion(response.content, body.model, response.reasoning, overrides);
539
+ const completion = buildTextCompletion(response.content, body.model, response.reasoning, overrides, body.messages);
517
540
  res.writeHead(200, { "Content-Type": "application/json" });
518
541
  res.end(JSON.stringify(completion));
519
542
  } else {
520
543
  const chunks = buildTextChunks(response.content, body.model, chunkSize, response.reasoning, overrides);
544
+ const usageChunk = includeUsage ? buildUsageChunk(chunks[0]?.id ?? "chatcmpl-unknown", overrides?.model ?? body.model, chunks[0]?.created ?? Math.floor(Date.now() / 1e3), overrides?.usage ? {
545
+ prompt_tokens: overrides.usage.prompt_tokens ?? 0,
546
+ completion_tokens: overrides.usage.completion_tokens ?? 0,
547
+ total_tokens: overrides.usage.total_tokens ?? (overrides.usage.prompt_tokens ?? 0) + (overrides.usage.completion_tokens ?? 0)
548
+ } : {
549
+ prompt_tokens: estimatePromptTokens(body.messages),
550
+ completion_tokens: estimateTokens(response.content),
551
+ total_tokens: estimatePromptTokens(body.messages) + estimateTokens(response.content)
552
+ }, overrides?.systemFingerprint) : void 0;
521
553
  const interruption = createInterruptionSignal(fixture);
522
554
  if (!await writeSSEStream(res, chunks, {
523
555
  latency,
524
556
  streamingProfile: fixture.streamingProfile,
525
557
  signal: interruption?.signal,
526
- onChunkSent: interruption?.tick
558
+ onChunkSent: interruption?.tick,
559
+ usageChunk
527
560
  })) {
528
561
  if (!res.writableEnded) res.destroy();
529
562
  journalEntry.response.interrupted = true;
@@ -547,17 +580,28 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
547
580
  }
548
581
  });
549
582
  if (body.stream !== true) {
550
- const completion = buildToolCallCompletion(response.toolCalls, body.model, overrides);
583
+ const completion = buildToolCallCompletion(response.toolCalls, body.model, overrides, body.messages);
551
584
  res.writeHead(200, { "Content-Type": "application/json" });
552
585
  res.end(JSON.stringify(completion));
553
586
  } else {
554
587
  const chunks = buildToolCallChunks(response.toolCalls, body.model, chunkSize, overrides);
588
+ const completionText = response.toolCalls.map((tc) => tc.name + tc.arguments).join("");
589
+ const usageChunk = includeUsage ? buildUsageChunk(chunks[0]?.id ?? "chatcmpl-unknown", overrides?.model ?? body.model, chunks[0]?.created ?? Math.floor(Date.now() / 1e3), overrides?.usage ? {
590
+ prompt_tokens: overrides.usage.prompt_tokens ?? 0,
591
+ completion_tokens: overrides.usage.completion_tokens ?? 0,
592
+ total_tokens: overrides.usage.total_tokens ?? (overrides.usage.prompt_tokens ?? 0) + (overrides.usage.completion_tokens ?? 0)
593
+ } : {
594
+ prompt_tokens: estimatePromptTokens(body.messages),
595
+ completion_tokens: estimateTokens(completionText),
596
+ total_tokens: estimatePromptTokens(body.messages) + estimateTokens(completionText)
597
+ }, overrides?.systemFingerprint) : void 0;
555
598
  const interruption = createInterruptionSignal(fixture);
556
599
  if (!await writeSSEStream(res, chunks, {
557
600
  latency,
558
601
  streamingProfile: fixture.streamingProfile,
559
602
  signal: interruption?.signal,
560
- onChunkSent: interruption?.tick
603
+ onChunkSent: interruption?.tick,
604
+ usageChunk
561
605
  })) {
562
606
  if (!res.writableEnded) res.destroy();
563
607
  journalEntry.response.interrupted = true;
@@ -686,6 +730,61 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
686
730
  if (await handler.handleRequest(req, res, subPath)) return;
687
731
  }
688
732
  }
733
+ if (pathname === OLLAMA_CHAT_PATH && req.method === "POST") {
734
+ try {
735
+ await handleOllama(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
736
+ } catch (err) {
737
+ const msg = err instanceof Error ? err.message : "Internal error";
738
+ if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
739
+ message: msg,
740
+ type: "server_error"
741
+ } }));
742
+ else if (!res.writableEnded) res.destroy();
743
+ }
744
+ return;
745
+ }
746
+ if (pathname === OLLAMA_GENERATE_PATH && req.method === "POST") {
747
+ try {
748
+ await handleOllamaGenerate(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
749
+ } catch (err) {
750
+ const msg = err instanceof Error ? err.message : "Internal error";
751
+ if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
752
+ message: msg,
753
+ type: "server_error"
754
+ } }));
755
+ else if (!res.writableEnded) res.destroy();
756
+ }
757
+ return;
758
+ }
759
+ if (pathname === OLLAMA_EMBEDDINGS_PATH && req.method === "POST") {
760
+ try {
761
+ await handleOllamaEmbeddings(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
762
+ } catch (err) {
763
+ const msg = err instanceof Error ? err.message : "Internal error";
764
+ if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
765
+ message: msg,
766
+ type: "server_error"
767
+ } }));
768
+ else if (!res.writableEnded) res.destroy();
769
+ }
770
+ return;
771
+ }
772
+ if (pathname === OLLAMA_TAGS_PATH && req.method === "GET") {
773
+ setCorsHeaders(res);
774
+ const modelIds = /* @__PURE__ */ new Set();
775
+ for (const f of fixtures) if (f.match.model && typeof f.match.model === "string") modelIds.add(f.match.model);
776
+ const models = (modelIds.size > 0 ? [...modelIds] : DEFAULT_MODELS).map((name) => ({
777
+ name,
778
+ model: name,
779
+ modified_at: (/* @__PURE__ */ new Date()).toISOString(),
780
+ size: 0,
781
+ digest: "",
782
+ details: {}
783
+ }));
784
+ res.writeHead(200, { "Content-Type": "application/json" });
785
+ res.end(JSON.stringify({ models }));
786
+ return;
787
+ }
689
788
  let azureDeploymentId;
690
789
  const azureMatch = pathname.match(AZURE_DEPLOYMENT_RE);
691
790
  if (azureMatch && req.method === "POST") {
@@ -832,6 +931,19 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
832
931
  }
833
932
  return;
834
933
  }
934
+ if (pathname === COHERE_EMBED_PATH && req.method === "POST") {
935
+ try {
936
+ await handleCohereEmbed(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
937
+ } catch (err) {
938
+ const msg = err instanceof Error ? err.message : "Internal error";
939
+ if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
940
+ message: msg,
941
+ type: "server_error"
942
+ } }));
943
+ else if (!res.writableEnded) res.destroy();
944
+ }
945
+ return;
946
+ }
835
947
  if (pathname === EMBEDDINGS_PATH && req.method === "POST") {
836
948
  try {
837
949
  const deploymentId = azureDeploymentId;
@@ -870,6 +982,32 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
870
982
  }
871
983
  return;
872
984
  }
985
+ if (pathname === IMAGES_EDIT_PATH && req.method === "POST") {
986
+ try {
987
+ await handleImageEdit(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
988
+ } catch (err) {
989
+ const msg = err instanceof Error ? err.message : "Internal error";
990
+ if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
991
+ message: msg,
992
+ type: "server_error"
993
+ } }));
994
+ else if (!res.writableEnded) res.destroy();
995
+ }
996
+ return;
997
+ }
998
+ if (pathname === IMAGES_VARIATIONS_PATH && req.method === "POST") {
999
+ try {
1000
+ await handleImageVariations(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
1001
+ } catch (err) {
1002
+ const msg = err instanceof Error ? err.message : "Internal error";
1003
+ if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
1004
+ message: msg,
1005
+ type: "server_error"
1006
+ } }));
1007
+ else if (!res.writableEnded) res.destroy();
1008
+ }
1009
+ return;
1010
+ }
873
1011
  if (pathname === SPEECH_PATH && req.method === "POST") {
874
1012
  try {
875
1013
  await handleSpeech(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
@@ -896,6 +1034,19 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
896
1034
  }
897
1035
  return;
898
1036
  }
1037
+ if (pathname === TRANSLATIONS_PATH && req.method === "POST") {
1038
+ try {
1039
+ await handleTranscription(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders, "translation");
1040
+ } catch (err) {
1041
+ const msg = err instanceof Error ? err.message : "Internal error";
1042
+ if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
1043
+ message: msg,
1044
+ type: "server_error"
1045
+ } }));
1046
+ else if (!res.writableEnded) res.destroy();
1047
+ }
1048
+ return;
1049
+ }
899
1050
  if (pathname === VIDEOS_PATH && req.method === "POST") {
900
1051
  try {
901
1052
  await handleVideoCreate(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders, videoStates);
@@ -948,6 +1099,21 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
948
1099
  }
949
1100
  return;
950
1101
  }
1102
+ const geminiEmbedMatch = pathname.match(GEMINI_EMBED_RE);
1103
+ if (geminiEmbedMatch && req.method === "POST") {
1104
+ const embedModel = geminiEmbedMatch[1];
1105
+ try {
1106
+ await handleGeminiEmbedContent(req, res, await readBody(req), embedModel, fixtures, journal, defaults, setCorsHeaders);
1107
+ } catch (err) {
1108
+ const msg = err instanceof Error ? err.message : "Internal error";
1109
+ if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
1110
+ message: msg,
1111
+ type: "server_error"
1112
+ } }));
1113
+ else if (!res.writableEnded) res.destroy();
1114
+ }
1115
+ return;
1116
+ }
951
1117
  const geminiMatch = pathname.match(GEMINI_PATH_RE);
952
1118
  if (geminiMatch && req.method === "POST") {
953
1119
  const geminiModel = geminiMatch[1];
@@ -1050,22 +1216,9 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
1050
1216
  }
1051
1217
  return;
1052
1218
  }
1053
- if (pathname === OLLAMA_CHAT_PATH && req.method === "POST") {
1054
- try {
1055
- await handleOllama(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
1056
- } catch (err) {
1057
- const msg = err instanceof Error ? err.message : "Internal error";
1058
- if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
1059
- message: msg,
1060
- type: "server_error"
1061
- } }));
1062
- else if (!res.writableEnded) res.destroy();
1063
- }
1064
- return;
1065
- }
1066
- if (pathname === OLLAMA_GENERATE_PATH && req.method === "POST") {
1219
+ if (pathname === SEARCH_PATH && req.method === "POST") {
1067
1220
  try {
1068
- await handleOllamaGenerate(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
1221
+ await handleSearch(req, res, await readBody(req), serviceFixtures?.search ?? [], journal, defaults, setCorsHeaders);
1069
1222
  } catch (err) {
1070
1223
  const msg = err instanceof Error ? err.message : "Internal error";
1071
1224
  if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
@@ -1076,25 +1229,9 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
1076
1229
  }
1077
1230
  return;
1078
1231
  }
1079
- if (pathname === OLLAMA_TAGS_PATH && req.method === "GET") {
1080
- setCorsHeaders(res);
1081
- const modelIds = /* @__PURE__ */ new Set();
1082
- for (const f of fixtures) if (f.match.model && typeof f.match.model === "string") modelIds.add(f.match.model);
1083
- const models = (modelIds.size > 0 ? [...modelIds] : DEFAULT_MODELS).map((name) => ({
1084
- name,
1085
- model: name,
1086
- modified_at: (/* @__PURE__ */ new Date()).toISOString(),
1087
- size: 0,
1088
- digest: "",
1089
- details: {}
1090
- }));
1091
- res.writeHead(200, { "Content-Type": "application/json" });
1092
- res.end(JSON.stringify({ models }));
1093
- return;
1094
- }
1095
- if (pathname === SEARCH_PATH && req.method === "POST") {
1232
+ if (pathname === RERANK_PATH && req.method === "POST") {
1096
1233
  try {
1097
- await handleSearch(req, res, await readBody(req), serviceFixtures?.search ?? [], journal, defaults, setCorsHeaders);
1234
+ await handleRerank(req, res, await readBody(req), serviceFixtures?.rerank ?? [], journal, defaults, setCorsHeaders);
1098
1235
  } catch (err) {
1099
1236
  const msg = err instanceof Error ? err.message : "Internal error";
1100
1237
  if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
@@ -1105,9 +1242,9 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
1105
1242
  }
1106
1243
  return;
1107
1244
  }
1108
- if (pathname === RERANK_PATH && req.method === "POST") {
1245
+ if (pathname === MODERATIONS_PATH && req.method === "POST") {
1109
1246
  try {
1110
- await handleRerank(req, res, await readBody(req), serviceFixtures?.rerank ?? [], journal, defaults, setCorsHeaders);
1247
+ await handleModeration(req, res, await readBody(req), serviceFixtures?.moderation ?? [], journal, defaults, setCorsHeaders);
1111
1248
  } catch (err) {
1112
1249
  const msg = err instanceof Error ? err.message : "Internal error";
1113
1250
  if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
@@ -1118,9 +1255,10 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
1118
1255
  }
1119
1256
  return;
1120
1257
  }
1121
- if (pathname === MODERATIONS_PATH && req.method === "POST") {
1258
+ if (pathname === ELEVENLABS_SOUND_GENERATION_PATH && req.method === "POST") {
1259
+ setCorsHeaders(res);
1122
1260
  try {
1123
- await handleModeration(req, res, await readBody(req), serviceFixtures?.moderation ?? [], journal, defaults, setCorsHeaders);
1261
+ await handleElevenLabsAudio(req, res, await readBody(req), fixtures, defaults, journal, "sound-generation");
1124
1262
  } catch (err) {
1125
1263
  const msg = err instanceof Error ? err.message : "Internal error";
1126
1264
  if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
@@ -1131,10 +1269,12 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
1131
1269
  }
1132
1270
  return;
1133
1271
  }
1134
- if (pathname === ELEVENLABS_SOUND_GENERATION_PATH && req.method === "POST") {
1272
+ const elevenLabsTTSMatch = pathname.match(ELEVENLABS_TTS_RE);
1273
+ if (elevenLabsTTSMatch && req.method === "POST") {
1135
1274
  setCorsHeaders(res);
1275
+ const voiceId = elevenLabsTTSMatch[1];
1136
1276
  try {
1137
- await handleElevenLabsAudio(req, res, await readBody(req), fixtures, defaults, journal, "sound-generation");
1277
+ await handleElevenLabsTTS(req, res, await readBody(req), fixtures, defaults, journal, voiceId);
1138
1278
  } catch (err) {
1139
1279
  const msg = err instanceof Error ? err.message : "Internal error";
1140
1280
  if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {