@copilotkit/aimock 1.24.1 → 1.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +38 -0
- package/README.md +21 -11
- package/dist/agui-types.d.cts.map +1 -1
- package/dist/agui-types.d.ts.map +1 -1
- package/dist/aws-event-stream.cjs +2 -1
- package/dist/aws-event-stream.cjs.map +1 -1
- package/dist/aws-event-stream.d.cts +3 -1
- package/dist/aws-event-stream.d.cts.map +1 -1
- package/dist/aws-event-stream.d.ts +3 -1
- package/dist/aws-event-stream.d.ts.map +1 -1
- package/dist/aws-event-stream.js +2 -1
- package/dist/aws-event-stream.js.map +1 -1
- package/dist/bedrock-converse.cjs +8 -2
- package/dist/bedrock-converse.cjs.map +1 -1
- package/dist/bedrock-converse.d.cts.map +1 -1
- package/dist/bedrock-converse.d.ts.map +1 -1
- package/dist/bedrock-converse.js +8 -2
- package/dist/bedrock-converse.js.map +1 -1
- package/dist/bedrock.cjs +8 -2
- package/dist/bedrock.cjs.map +1 -1
- package/dist/bedrock.d.cts.map +1 -1
- package/dist/bedrock.d.ts.map +1 -1
- package/dist/bedrock.js +8 -2
- package/dist/bedrock.js.map +1 -1
- package/dist/cli.cjs +36 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +36 -1
- package/dist/cli.js.map +1 -1
- package/dist/cohere.cjs +206 -2
- package/dist/cohere.cjs.map +1 -1
- package/dist/cohere.d.cts.map +1 -1
- package/dist/cohere.d.ts.map +1 -1
- package/dist/cohere.js +207 -4
- package/dist/cohere.js.map +1 -1
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/elevenlabs-audio.cjs +173 -1
- package/dist/elevenlabs-audio.cjs.map +1 -1
- package/dist/elevenlabs-audio.d.cts.map +1 -1
- package/dist/elevenlabs-audio.d.ts.map +1 -1
- package/dist/elevenlabs-audio.js +173 -2
- package/dist/elevenlabs-audio.js.map +1 -1
- package/dist/embeddings.cjs +1 -1
- package/dist/embeddings.cjs.map +1 -1
- package/dist/embeddings.js +1 -1
- package/dist/embeddings.js.map +1 -1
- package/dist/fal-audio.cjs +2 -4
- package/dist/fal-audio.cjs.map +1 -1
- package/dist/fal-audio.js +2 -4
- package/dist/fal-audio.js.map +1 -1
- package/dist/fal.cjs +2 -2
- package/dist/fal.cjs.map +1 -1
- package/dist/fal.d.cts.map +1 -1
- package/dist/fal.d.ts.map +1 -1
- package/dist/fal.js +2 -2
- package/dist/fal.js.map +1 -1
- package/dist/fixture-loader.cjs +16 -3
- package/dist/fixture-loader.cjs.map +1 -1
- package/dist/fixture-loader.d.cts.map +1 -1
- package/dist/fixture-loader.d.ts.map +1 -1
- package/dist/fixture-loader.js +16 -3
- package/dist/fixture-loader.js.map +1 -1
- package/dist/gemini-embeddings.cjs +166 -0
- package/dist/gemini-embeddings.cjs.map +1 -0
- package/dist/gemini-embeddings.js +166 -0
- package/dist/gemini-embeddings.js.map +1 -0
- package/dist/gemini-interactions.cjs +10 -2
- package/dist/gemini-interactions.cjs.map +1 -1
- package/dist/gemini-interactions.d.cts.map +1 -1
- package/dist/gemini-interactions.d.ts.map +1 -1
- package/dist/gemini-interactions.js +10 -2
- package/dist/gemini-interactions.js.map +1 -1
- package/dist/gemini.cjs +12 -2
- package/dist/gemini.cjs.map +1 -1
- package/dist/gemini.d.cts.map +1 -1
- package/dist/gemini.d.ts.map +1 -1
- package/dist/gemini.js +12 -2
- package/dist/gemini.js.map +1 -1
- package/dist/helpers.cjs +70 -33
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +9 -5
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.ts +9 -5
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +68 -34
- package/dist/helpers.js.map +1 -1
- package/dist/images.cjs +295 -13
- package/dist/images.cjs.map +1 -1
- package/dist/images.d.cts +9 -1
- package/dist/images.d.cts.map +1 -1
- package/dist/images.d.ts +9 -1
- package/dist/images.d.ts.map +1 -1
- package/dist/images.js +294 -14
- package/dist/images.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/llmock.cjs +16 -1
- package/dist/llmock.cjs.map +1 -1
- package/dist/llmock.d.cts +2 -0
- package/dist/llmock.d.cts.map +1 -1
- package/dist/llmock.d.ts +2 -0
- package/dist/llmock.d.ts.map +1 -1
- package/dist/llmock.js +16 -1
- package/dist/llmock.js.map +1 -1
- package/dist/messages.cjs +9 -2
- package/dist/messages.cjs.map +1 -1
- package/dist/messages.d.cts.map +1 -1
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +9 -2
- package/dist/messages.js.map +1 -1
- package/dist/metrics.cjs +2 -0
- package/dist/metrics.cjs.map +1 -1
- package/dist/metrics.d.cts.map +1 -1
- package/dist/metrics.d.ts.map +1 -1
- package/dist/metrics.js +2 -0
- package/dist/metrics.js.map +1 -1
- package/dist/ndjson-writer.cjs +2 -1
- package/dist/ndjson-writer.cjs.map +1 -1
- package/dist/ndjson-writer.d.cts +3 -2
- package/dist/ndjson-writer.d.cts.map +1 -1
- package/dist/ndjson-writer.d.ts +3 -2
- package/dist/ndjson-writer.d.ts.map +1 -1
- package/dist/ndjson-writer.js +2 -1
- package/dist/ndjson-writer.js.map +1 -1
- package/dist/ollama.cjs +197 -2
- package/dist/ollama.cjs.map +1 -1
- package/dist/ollama.d.cts.map +1 -1
- package/dist/ollama.d.ts.map +1 -1
- package/dist/ollama.js +198 -4
- package/dist/ollama.js.map +1 -1
- package/dist/recorder.cjs +49 -5
- package/dist/recorder.cjs.map +1 -1
- package/dist/recorder.d.cts.map +1 -1
- package/dist/recorder.d.ts.map +1 -1
- package/dist/recorder.js +49 -5
- package/dist/recorder.js.map +1 -1
- package/dist/responses.cjs +11 -2
- package/dist/responses.cjs.map +1 -1
- package/dist/responses.d.cts.map +1 -1
- package/dist/responses.d.ts.map +1 -1
- package/dist/responses.js +11 -2
- package/dist/responses.js.map +1 -1
- package/dist/server.cjs +196 -49
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +201 -54
- package/dist/server.js.map +1 -1
- package/dist/speech.cjs +1 -1
- package/dist/speech.cjs.map +1 -1
- package/dist/speech.js +1 -1
- package/dist/speech.js.map +1 -1
- package/dist/sse-writer.cjs +48 -10
- package/dist/sse-writer.cjs.map +1 -1
- package/dist/sse-writer.d.cts +12 -4
- package/dist/sse-writer.d.cts.map +1 -1
- package/dist/sse-writer.d.ts +12 -4
- package/dist/sse-writer.d.ts.map +1 -1
- package/dist/sse-writer.js +48 -10
- package/dist/sse-writer.js.map +1 -1
- package/dist/transcription.cjs +9 -6
- package/dist/transcription.cjs.map +1 -1
- package/dist/transcription.d.cts +2 -2
- package/dist/transcription.d.cts.map +1 -1
- package/dist/transcription.d.ts +2 -2
- package/dist/transcription.d.ts.map +1 -1
- package/dist/transcription.js +8 -7
- package/dist/transcription.js.map +1 -1
- package/dist/types.d.cts +45 -3
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +45 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/video.cjs +1 -1
- package/dist/video.cjs.map +1 -1
- package/dist/video.d.cts.map +1 -1
- package/dist/video.d.ts.map +1 -1
- package/dist/video.js +1 -1
- package/dist/video.js.map +1 -1
- package/dist/ws-gemini-live.cjs +14 -4
- package/dist/ws-gemini-live.cjs.map +1 -1
- package/dist/ws-gemini-live.d.cts +1 -0
- package/dist/ws-gemini-live.d.cts.map +1 -1
- package/dist/ws-gemini-live.d.ts +1 -0
- package/dist/ws-gemini-live.d.ts.map +1 -1
- package/dist/ws-gemini-live.js +15 -5
- package/dist/ws-gemini-live.js.map +1 -1
- package/dist/ws-realtime.cjs +21 -4
- package/dist/ws-realtime.cjs.map +1 -1
- package/dist/ws-realtime.d.cts +1 -0
- package/dist/ws-realtime.d.cts.map +1 -1
- package/dist/ws-realtime.d.ts +1 -0
- package/dist/ws-realtime.d.ts.map +1 -1
- package/dist/ws-realtime.js +22 -5
- package/dist/ws-realtime.js.map +1 -1
- package/dist/ws-responses.cjs +8 -5
- package/dist/ws-responses.cjs.map +1 -1
- package/dist/ws-responses.d.cts +1 -0
- package/dist/ws-responses.d.cts.map +1 -1
- package/dist/ws-responses.d.ts +1 -0
- package/dist/ws-responses.d.ts.map +1 -1
- package/dist/ws-responses.js +9 -6
- package/dist/ws-responses.js.map +1 -1
- 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
|
-
"/
|
|
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";
|
|
@@ -168,7 +179,7 @@ async function handleControlAPI(req, res, pathname, fixtures, journal, videoStat
|
|
|
168
179
|
res.end(JSON.stringify({ error: "Missing or invalid \"fixtures\" array" }));
|
|
169
180
|
return true;
|
|
170
181
|
}
|
|
171
|
-
const converted = parsed.fixtures.map(entryToFixture);
|
|
182
|
+
const converted = parsed.fixtures.map((e) => entryToFixture(e));
|
|
172
183
|
const errors = validateFixtures(converted).filter((i) => i.severity === "error");
|
|
173
184
|
if (errors.length > 0) {
|
|
174
185
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
@@ -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,30 @@ 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,
|
|
516
|
+
recordedTimings: fixture.recordedTimings,
|
|
517
|
+
replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed
|
|
493
518
|
})) {
|
|
494
519
|
if (!res.writableEnded) res.destroy();
|
|
495
520
|
journalEntry.response.interrupted = true;
|
|
@@ -513,17 +538,29 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
|
|
|
513
538
|
}
|
|
514
539
|
});
|
|
515
540
|
if (body.stream !== true) {
|
|
516
|
-
const completion = buildTextCompletion(response.content, body.model, response.reasoning, overrides);
|
|
541
|
+
const completion = buildTextCompletion(response.content, body.model, response.reasoning, overrides, body.messages);
|
|
517
542
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
518
543
|
res.end(JSON.stringify(completion));
|
|
519
544
|
} else {
|
|
520
545
|
const chunks = buildTextChunks(response.content, body.model, chunkSize, response.reasoning, overrides);
|
|
546
|
+
const usageChunk = includeUsage ? buildUsageChunk(chunks[0]?.id ?? "chatcmpl-unknown", overrides?.model ?? body.model, chunks[0]?.created ?? Math.floor(Date.now() / 1e3), overrides?.usage ? {
|
|
547
|
+
prompt_tokens: overrides.usage.prompt_tokens ?? 0,
|
|
548
|
+
completion_tokens: overrides.usage.completion_tokens ?? 0,
|
|
549
|
+
total_tokens: overrides.usage.total_tokens ?? (overrides.usage.prompt_tokens ?? 0) + (overrides.usage.completion_tokens ?? 0)
|
|
550
|
+
} : {
|
|
551
|
+
prompt_tokens: estimatePromptTokens(body.messages),
|
|
552
|
+
completion_tokens: estimateTokens(response.content),
|
|
553
|
+
total_tokens: estimatePromptTokens(body.messages) + estimateTokens(response.content)
|
|
554
|
+
}, overrides?.systemFingerprint) : void 0;
|
|
521
555
|
const interruption = createInterruptionSignal(fixture);
|
|
522
556
|
if (!await writeSSEStream(res, chunks, {
|
|
523
557
|
latency,
|
|
524
558
|
streamingProfile: fixture.streamingProfile,
|
|
525
559
|
signal: interruption?.signal,
|
|
526
|
-
onChunkSent: interruption?.tick
|
|
560
|
+
onChunkSent: interruption?.tick,
|
|
561
|
+
usageChunk,
|
|
562
|
+
recordedTimings: fixture.recordedTimings,
|
|
563
|
+
replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed
|
|
527
564
|
})) {
|
|
528
565
|
if (!res.writableEnded) res.destroy();
|
|
529
566
|
journalEntry.response.interrupted = true;
|
|
@@ -547,17 +584,30 @@ async function handleCompletions(req, res, fixtures, journal, defaults, modelFal
|
|
|
547
584
|
}
|
|
548
585
|
});
|
|
549
586
|
if (body.stream !== true) {
|
|
550
|
-
const completion = buildToolCallCompletion(response.toolCalls, body.model, overrides);
|
|
587
|
+
const completion = buildToolCallCompletion(response.toolCalls, body.model, overrides, body.messages);
|
|
551
588
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
552
589
|
res.end(JSON.stringify(completion));
|
|
553
590
|
} else {
|
|
554
591
|
const chunks = buildToolCallChunks(response.toolCalls, body.model, chunkSize, overrides);
|
|
592
|
+
const completionText = response.toolCalls.map((tc) => tc.name + tc.arguments).join("");
|
|
593
|
+
const usageChunk = includeUsage ? buildUsageChunk(chunks[0]?.id ?? "chatcmpl-unknown", overrides?.model ?? body.model, chunks[0]?.created ?? Math.floor(Date.now() / 1e3), overrides?.usage ? {
|
|
594
|
+
prompt_tokens: overrides.usage.prompt_tokens ?? 0,
|
|
595
|
+
completion_tokens: overrides.usage.completion_tokens ?? 0,
|
|
596
|
+
total_tokens: overrides.usage.total_tokens ?? (overrides.usage.prompt_tokens ?? 0) + (overrides.usage.completion_tokens ?? 0)
|
|
597
|
+
} : {
|
|
598
|
+
prompt_tokens: estimatePromptTokens(body.messages),
|
|
599
|
+
completion_tokens: estimateTokens(completionText),
|
|
600
|
+
total_tokens: estimatePromptTokens(body.messages) + estimateTokens(completionText)
|
|
601
|
+
}, overrides?.systemFingerprint) : void 0;
|
|
555
602
|
const interruption = createInterruptionSignal(fixture);
|
|
556
603
|
if (!await writeSSEStream(res, chunks, {
|
|
557
604
|
latency,
|
|
558
605
|
streamingProfile: fixture.streamingProfile,
|
|
559
606
|
signal: interruption?.signal,
|
|
560
|
-
onChunkSent: interruption?.tick
|
|
607
|
+
onChunkSent: interruption?.tick,
|
|
608
|
+
usageChunk,
|
|
609
|
+
recordedTimings: fixture.recordedTimings,
|
|
610
|
+
replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed
|
|
561
611
|
})) {
|
|
562
612
|
if (!res.writableEnded) res.destroy();
|
|
563
613
|
journalEntry.response.interrupted = true;
|
|
@@ -591,6 +641,7 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
|
|
|
591
641
|
const defaults = {
|
|
592
642
|
latency: serverOptions.latency ?? 0,
|
|
593
643
|
chunkSize: Math.max(1, serverOptions.chunkSize ?? DEFAULT_CHUNK_SIZE),
|
|
644
|
+
replaySpeed: serverOptions.replaySpeed ?? 1,
|
|
594
645
|
logger,
|
|
595
646
|
get chaos() {
|
|
596
647
|
return serverOptions.chaos;
|
|
@@ -686,6 +737,61 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
|
|
|
686
737
|
if (await handler.handleRequest(req, res, subPath)) return;
|
|
687
738
|
}
|
|
688
739
|
}
|
|
740
|
+
if (pathname === OLLAMA_CHAT_PATH && req.method === "POST") {
|
|
741
|
+
try {
|
|
742
|
+
await handleOllama(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
|
|
743
|
+
} catch (err) {
|
|
744
|
+
const msg = err instanceof Error ? err.message : "Internal error";
|
|
745
|
+
if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
746
|
+
message: msg,
|
|
747
|
+
type: "server_error"
|
|
748
|
+
} }));
|
|
749
|
+
else if (!res.writableEnded) res.destroy();
|
|
750
|
+
}
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
if (pathname === OLLAMA_GENERATE_PATH && req.method === "POST") {
|
|
754
|
+
try {
|
|
755
|
+
await handleOllamaGenerate(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
|
|
756
|
+
} catch (err) {
|
|
757
|
+
const msg = err instanceof Error ? err.message : "Internal error";
|
|
758
|
+
if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
759
|
+
message: msg,
|
|
760
|
+
type: "server_error"
|
|
761
|
+
} }));
|
|
762
|
+
else if (!res.writableEnded) res.destroy();
|
|
763
|
+
}
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
if (pathname === OLLAMA_EMBEDDINGS_PATH && req.method === "POST") {
|
|
767
|
+
try {
|
|
768
|
+
await handleOllamaEmbeddings(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
|
|
769
|
+
} catch (err) {
|
|
770
|
+
const msg = err instanceof Error ? err.message : "Internal error";
|
|
771
|
+
if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
772
|
+
message: msg,
|
|
773
|
+
type: "server_error"
|
|
774
|
+
} }));
|
|
775
|
+
else if (!res.writableEnded) res.destroy();
|
|
776
|
+
}
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
if (pathname === OLLAMA_TAGS_PATH && req.method === "GET") {
|
|
780
|
+
setCorsHeaders(res);
|
|
781
|
+
const modelIds = /* @__PURE__ */ new Set();
|
|
782
|
+
for (const f of fixtures) if (f.match.model && typeof f.match.model === "string") modelIds.add(f.match.model);
|
|
783
|
+
const models = (modelIds.size > 0 ? [...modelIds] : DEFAULT_MODELS).map((name) => ({
|
|
784
|
+
name,
|
|
785
|
+
model: name,
|
|
786
|
+
modified_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
787
|
+
size: 0,
|
|
788
|
+
digest: "",
|
|
789
|
+
details: {}
|
|
790
|
+
}));
|
|
791
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
792
|
+
res.end(JSON.stringify({ models }));
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
689
795
|
let azureDeploymentId;
|
|
690
796
|
const azureMatch = pathname.match(AZURE_DEPLOYMENT_RE);
|
|
691
797
|
if (azureMatch && req.method === "POST") {
|
|
@@ -832,6 +938,19 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
|
|
|
832
938
|
}
|
|
833
939
|
return;
|
|
834
940
|
}
|
|
941
|
+
if (pathname === COHERE_EMBED_PATH && req.method === "POST") {
|
|
942
|
+
try {
|
|
943
|
+
await handleCohereEmbed(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
|
|
944
|
+
} catch (err) {
|
|
945
|
+
const msg = err instanceof Error ? err.message : "Internal error";
|
|
946
|
+
if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
947
|
+
message: msg,
|
|
948
|
+
type: "server_error"
|
|
949
|
+
} }));
|
|
950
|
+
else if (!res.writableEnded) res.destroy();
|
|
951
|
+
}
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
835
954
|
if (pathname === EMBEDDINGS_PATH && req.method === "POST") {
|
|
836
955
|
try {
|
|
837
956
|
const deploymentId = azureDeploymentId;
|
|
@@ -870,6 +989,32 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
|
|
|
870
989
|
}
|
|
871
990
|
return;
|
|
872
991
|
}
|
|
992
|
+
if (pathname === IMAGES_EDIT_PATH && req.method === "POST") {
|
|
993
|
+
try {
|
|
994
|
+
await handleImageEdit(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
|
|
995
|
+
} catch (err) {
|
|
996
|
+
const msg = err instanceof Error ? err.message : "Internal error";
|
|
997
|
+
if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
998
|
+
message: msg,
|
|
999
|
+
type: "server_error"
|
|
1000
|
+
} }));
|
|
1001
|
+
else if (!res.writableEnded) res.destroy();
|
|
1002
|
+
}
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
if (pathname === IMAGES_VARIATIONS_PATH && req.method === "POST") {
|
|
1006
|
+
try {
|
|
1007
|
+
await handleImageVariations(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
|
|
1008
|
+
} catch (err) {
|
|
1009
|
+
const msg = err instanceof Error ? err.message : "Internal error";
|
|
1010
|
+
if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
1011
|
+
message: msg,
|
|
1012
|
+
type: "server_error"
|
|
1013
|
+
} }));
|
|
1014
|
+
else if (!res.writableEnded) res.destroy();
|
|
1015
|
+
}
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
873
1018
|
if (pathname === SPEECH_PATH && req.method === "POST") {
|
|
874
1019
|
try {
|
|
875
1020
|
await handleSpeech(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders);
|
|
@@ -896,6 +1041,19 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
|
|
|
896
1041
|
}
|
|
897
1042
|
return;
|
|
898
1043
|
}
|
|
1044
|
+
if (pathname === TRANSLATIONS_PATH && req.method === "POST") {
|
|
1045
|
+
try {
|
|
1046
|
+
await handleTranscription(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders, "translation");
|
|
1047
|
+
} catch (err) {
|
|
1048
|
+
const msg = err instanceof Error ? err.message : "Internal error";
|
|
1049
|
+
if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
1050
|
+
message: msg,
|
|
1051
|
+
type: "server_error"
|
|
1052
|
+
} }));
|
|
1053
|
+
else if (!res.writableEnded) res.destroy();
|
|
1054
|
+
}
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
899
1057
|
if (pathname === VIDEOS_PATH && req.method === "POST") {
|
|
900
1058
|
try {
|
|
901
1059
|
await handleVideoCreate(req, res, await readBody(req), fixtures, journal, defaults, setCorsHeaders, videoStates);
|
|
@@ -948,6 +1106,21 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
|
|
|
948
1106
|
}
|
|
949
1107
|
return;
|
|
950
1108
|
}
|
|
1109
|
+
const geminiEmbedMatch = pathname.match(GEMINI_EMBED_RE);
|
|
1110
|
+
if (geminiEmbedMatch && req.method === "POST") {
|
|
1111
|
+
const embedModel = geminiEmbedMatch[1];
|
|
1112
|
+
try {
|
|
1113
|
+
await handleGeminiEmbedContent(req, res, await readBody(req), embedModel, fixtures, journal, defaults, setCorsHeaders);
|
|
1114
|
+
} catch (err) {
|
|
1115
|
+
const msg = err instanceof Error ? err.message : "Internal error";
|
|
1116
|
+
if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
1117
|
+
message: msg,
|
|
1118
|
+
type: "server_error"
|
|
1119
|
+
} }));
|
|
1120
|
+
else if (!res.writableEnded) res.destroy();
|
|
1121
|
+
}
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
951
1124
|
const geminiMatch = pathname.match(GEMINI_PATH_RE);
|
|
952
1125
|
if (geminiMatch && req.method === "POST") {
|
|
953
1126
|
const geminiModel = geminiMatch[1];
|
|
@@ -1050,22 +1223,9 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
|
|
|
1050
1223
|
}
|
|
1051
1224
|
return;
|
|
1052
1225
|
}
|
|
1053
|
-
if (pathname ===
|
|
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") {
|
|
1226
|
+
if (pathname === SEARCH_PATH && req.method === "POST") {
|
|
1067
1227
|
try {
|
|
1068
|
-
await
|
|
1228
|
+
await handleSearch(req, res, await readBody(req), serviceFixtures?.search ?? [], journal, defaults, setCorsHeaders);
|
|
1069
1229
|
} catch (err) {
|
|
1070
1230
|
const msg = err instanceof Error ? err.message : "Internal error";
|
|
1071
1231
|
if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
@@ -1076,25 +1236,9 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
|
|
|
1076
1236
|
}
|
|
1077
1237
|
return;
|
|
1078
1238
|
}
|
|
1079
|
-
if (pathname ===
|
|
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") {
|
|
1239
|
+
if (pathname === RERANK_PATH && req.method === "POST") {
|
|
1096
1240
|
try {
|
|
1097
|
-
await
|
|
1241
|
+
await handleRerank(req, res, await readBody(req), serviceFixtures?.rerank ?? [], journal, defaults, setCorsHeaders);
|
|
1098
1242
|
} catch (err) {
|
|
1099
1243
|
const msg = err instanceof Error ? err.message : "Internal error";
|
|
1100
1244
|
if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
@@ -1105,9 +1249,9 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
|
|
|
1105
1249
|
}
|
|
1106
1250
|
return;
|
|
1107
1251
|
}
|
|
1108
|
-
if (pathname ===
|
|
1252
|
+
if (pathname === MODERATIONS_PATH && req.method === "POST") {
|
|
1109
1253
|
try {
|
|
1110
|
-
await
|
|
1254
|
+
await handleModeration(req, res, await readBody(req), serviceFixtures?.moderation ?? [], journal, defaults, setCorsHeaders);
|
|
1111
1255
|
} catch (err) {
|
|
1112
1256
|
const msg = err instanceof Error ? err.message : "Internal error";
|
|
1113
1257
|
if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
@@ -1118,9 +1262,10 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
|
|
|
1118
1262
|
}
|
|
1119
1263
|
return;
|
|
1120
1264
|
}
|
|
1121
|
-
if (pathname ===
|
|
1265
|
+
if (pathname === ELEVENLABS_SOUND_GENERATION_PATH && req.method === "POST") {
|
|
1266
|
+
setCorsHeaders(res);
|
|
1122
1267
|
try {
|
|
1123
|
-
await
|
|
1268
|
+
await handleElevenLabsAudio(req, res, await readBody(req), fixtures, defaults, journal, "sound-generation");
|
|
1124
1269
|
} catch (err) {
|
|
1125
1270
|
const msg = err instanceof Error ? err.message : "Internal error";
|
|
1126
1271
|
if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
|
|
@@ -1131,10 +1276,12 @@ async function createServer(fixtures, options, mounts, serviceFixtures) {
|
|
|
1131
1276
|
}
|
|
1132
1277
|
return;
|
|
1133
1278
|
}
|
|
1134
|
-
|
|
1279
|
+
const elevenLabsTTSMatch = pathname.match(ELEVENLABS_TTS_RE);
|
|
1280
|
+
if (elevenLabsTTSMatch && req.method === "POST") {
|
|
1135
1281
|
setCorsHeaders(res);
|
|
1282
|
+
const voiceId = elevenLabsTTSMatch[1];
|
|
1136
1283
|
try {
|
|
1137
|
-
await
|
|
1284
|
+
await handleElevenLabsTTS(req, res, await readBody(req), fixtures, defaults, journal, voiceId);
|
|
1138
1285
|
} catch (err) {
|
|
1139
1286
|
const msg = err instanceof Error ? err.message : "Internal error";
|
|
1140
1287
|
if (!res.headersSent) writeErrorResponse(res, 500, JSON.stringify({ error: {
|