@copilotkit/aimock 1.13.0 → 1.14.1
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 +2 -2
- package/.claude-plugin/plugin.json +4 -4
- package/README.md +12 -7
- package/dist/cli.cjs +13 -2
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +13 -2
- package/dist/cli.js.map +1 -1
- package/dist/config-loader.d.cts.map +1 -1
- package/dist/fixture-loader.cjs +131 -29
- package/dist/fixture-loader.cjs.map +1 -1
- package/dist/fixture-loader.d.cts +9 -2
- package/dist/fixture-loader.d.cts.map +1 -1
- package/dist/fixture-loader.d.ts +9 -2
- package/dist/fixture-loader.d.ts.map +1 -1
- package/dist/fixture-loader.js +132 -31
- package/dist/fixture-loader.js.map +1 -1
- package/dist/gemini.cjs +76 -55
- 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 +77 -56
- package/dist/gemini.js.map +1 -1
- package/dist/helpers.cjs +142 -76
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +14 -4
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.ts +14 -4
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +142 -77
- package/dist/helpers.js.map +1 -1
- package/dist/index.cjs +10 -0
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/journal.cjs +6 -0
- package/dist/journal.cjs.map +1 -1
- package/dist/journal.d.cts +15 -1
- package/dist/journal.d.cts.map +1 -1
- package/dist/journal.d.ts +15 -1
- package/dist/journal.d.ts.map +1 -1
- package/dist/journal.js +6 -0
- package/dist/journal.js.map +1 -1
- package/dist/llmock.cjs +1 -1
- package/dist/llmock.cjs.map +1 -1
- package/dist/llmock.d.cts +6 -6
- package/dist/llmock.d.cts.map +1 -1
- package/dist/llmock.d.ts +6 -6
- package/dist/llmock.d.ts.map +1 -1
- package/dist/llmock.js +2 -2
- package/dist/llmock.js.map +1 -1
- package/dist/messages.cjs +69 -63
- 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 +70 -64
- package/dist/messages.js.map +1 -1
- package/dist/recorder.cjs +1 -1
- package/dist/recorder.cjs.map +1 -1
- package/dist/recorder.js +1 -1
- package/dist/recorder.js.map +1 -1
- package/dist/responses.cjs +66 -57
- package/dist/responses.cjs.map +1 -1
- package/dist/responses.d.cts +3 -3
- package/dist/responses.d.cts.map +1 -1
- package/dist/responses.d.ts +3 -3
- package/dist/responses.d.ts.map +1 -1
- package/dist/responses.js +67 -58
- package/dist/responses.js.map +1 -1
- package/dist/server.cjs +58 -31
- 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 +59 -32
- package/dist/server.js.map +1 -1
- package/dist/stream-collapse.cjs.map +1 -1
- package/dist/stream-collapse.d.cts.map +1 -1
- package/dist/stream-collapse.d.ts.map +1 -1
- package/dist/stream-collapse.js.map +1 -1
- package/dist/types.d.cts +74 -11
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +74 -11
- package/dist/types.d.ts.map +1 -1
- package/dist/vector-types.d.ts.map +1 -1
- package/fixtures/example-multi-turn.json +1 -1
- package/fixtures/example-tool-call.json +1 -1
- package/fixtures/examples/adk/gemini-agent.json +47 -0
- package/fixtures/examples/crewai/multi-agent-crew.json +16 -0
- package/fixtures/examples/langchain/agent-loop.json +27 -0
- package/fixtures/examples/llamaindex/aimock-config.json +62 -0
- package/fixtures/examples/llamaindex/rag-pipeline.json +34 -0
- package/fixtures/examples/mastra/agent-workflow.json +32 -0
- package/fixtures/examples/pydanticai/structured-output.json +15 -0
- package/package.json +2 -1
- package/skills/write-fixtures/SKILL.md +148 -22
package/dist/helpers.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AudioResponse, EmbeddingResponse, FixtureResponse, ImageResponse, SSEChunk, ToolCall, TranscriptionResponse, VideoResponse } from "./types.js";
|
|
1
|
+
import { AudioResponse, ChatCompletion, ContentWithToolCallsResponse, EmbeddingResponse, ErrorResponse, FixtureResponse, ImageResponse, ResponseOverrides, SSEChunk, TextResponse, ToolCall, ToolCallResponse, TranscriptionResponse, VideoResponse } from "./types.js";
|
|
2
2
|
import * as http from "node:http";
|
|
3
3
|
|
|
4
4
|
//#region src/helpers.d.ts
|
|
@@ -7,13 +7,22 @@ declare function generateId(prefix?: string): string;
|
|
|
7
7
|
declare function generateToolCallId(): string;
|
|
8
8
|
declare function generateMessageId(): string;
|
|
9
9
|
declare function generateToolUseId(): string;
|
|
10
|
+
declare function isTextResponse(r: FixtureResponse): r is TextResponse;
|
|
11
|
+
declare function isToolCallResponse(r: FixtureResponse): r is ToolCallResponse;
|
|
12
|
+
declare function isContentWithToolCallsResponse(r: FixtureResponse): r is ContentWithToolCallsResponse;
|
|
13
|
+
declare function isErrorResponse(r: FixtureResponse): r is ErrorResponse;
|
|
10
14
|
declare function isEmbeddingResponse(r: FixtureResponse): r is EmbeddingResponse;
|
|
11
15
|
declare function isImageResponse(r: FixtureResponse): r is ImageResponse;
|
|
12
16
|
declare function isAudioResponse(r: FixtureResponse): r is AudioResponse;
|
|
13
17
|
declare function isTranscriptionResponse(r: FixtureResponse): r is TranscriptionResponse;
|
|
14
18
|
declare function isVideoResponse(r: FixtureResponse): r is VideoResponse;
|
|
15
|
-
declare function
|
|
16
|
-
declare function
|
|
19
|
+
declare function extractOverrides(response: TextResponse | ToolCallResponse | ContentWithToolCallsResponse): ResponseOverrides;
|
|
20
|
+
declare function buildTextChunks(content: string, model: string, chunkSize: number, reasoning?: string, overrides?: ResponseOverrides): SSEChunk[];
|
|
21
|
+
declare function buildToolCallChunks(toolCalls: ToolCall[], model: string, chunkSize: number, overrides?: ResponseOverrides): SSEChunk[];
|
|
22
|
+
declare function buildTextCompletion(content: string, model: string, reasoning?: string, overrides?: ResponseOverrides): ChatCompletion;
|
|
23
|
+
declare function buildToolCallCompletion(toolCalls: ToolCall[], model: string, overrides?: ResponseOverrides): ChatCompletion;
|
|
24
|
+
declare function buildContentWithToolCallsChunks(content: string, toolCalls: ToolCall[], model: string, chunkSize: number, reasoning?: string, overrides?: ResponseOverrides): SSEChunk[];
|
|
25
|
+
declare function buildContentWithToolCallsCompletion(content: string, toolCalls: ToolCall[], model: string, reasoning?: string, overrides?: ResponseOverrides): ChatCompletion;
|
|
17
26
|
/**
|
|
18
27
|
* Generate a deterministic embedding vector from input text.
|
|
19
28
|
* Hashes the input with SHA-256 and spreads the hash bytes across
|
|
@@ -38,6 +47,7 @@ interface EmbeddingAPIResponse {
|
|
|
38
47
|
*/
|
|
39
48
|
declare function buildEmbeddingResponse(embeddings: number[][], model: string): EmbeddingAPIResponse;
|
|
40
49
|
//# sourceMappingURL=helpers.d.ts.map
|
|
50
|
+
|
|
41
51
|
//#endregion
|
|
42
|
-
export { EmbeddingAPIResponse, buildEmbeddingResponse, buildTextChunks, buildToolCallChunks, flattenHeaders, generateDeterministicEmbedding, generateId, generateMessageId, generateToolCallId, generateToolUseId, isAudioResponse, isEmbeddingResponse, isImageResponse, isTranscriptionResponse, isVideoResponse };
|
|
52
|
+
export { EmbeddingAPIResponse, buildContentWithToolCallsChunks, buildContentWithToolCallsCompletion, buildEmbeddingResponse, buildTextChunks, buildTextCompletion, buildToolCallChunks, buildToolCallCompletion, extractOverrides, flattenHeaders, generateDeterministicEmbedding, generateId, generateMessageId, generateToolCallId, generateToolUseId, isAudioResponse, isContentWithToolCallsResponse, isEmbeddingResponse, isErrorResponse, isImageResponse, isTextResponse, isToolCallResponse, isTranscriptionResponse, isVideoResponse };
|
|
43
53
|
//# sourceMappingURL=helpers.d.ts.map
|
package/dist/helpers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","names":[],"sources":["../src/helpers.ts"],"sourcesContent":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","names":[],"sources":["../src/helpers.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/helpers.js
CHANGED
|
@@ -28,10 +28,10 @@ function generateToolUseId() {
|
|
|
28
28
|
return `toolu_${randomBytes(12).toString("base64url")}`;
|
|
29
29
|
}
|
|
30
30
|
function isTextResponse(r) {
|
|
31
|
-
return "content" in r && typeof r.content === "string";
|
|
31
|
+
return "content" in r && typeof r.content === "string" && !("toolCalls" in r);
|
|
32
32
|
}
|
|
33
33
|
function isToolCallResponse(r) {
|
|
34
|
-
return "toolCalls" in r && Array.isArray(r.toolCalls);
|
|
34
|
+
return "toolCalls" in r && Array.isArray(r.toolCalls) && !("content" in r && typeof r.content === "string");
|
|
35
35
|
}
|
|
36
36
|
function isContentWithToolCallsResponse(r) {
|
|
37
37
|
return "content" in r && typeof r.content === "string" && "toolCalls" in r && Array.isArray(r.toolCalls);
|
|
@@ -54,37 +54,53 @@ function isTranscriptionResponse(r) {
|
|
|
54
54
|
function isVideoResponse(r) {
|
|
55
55
|
return "video" in r && r.video != null && typeof r.video === "object";
|
|
56
56
|
}
|
|
57
|
-
function
|
|
58
|
-
const
|
|
59
|
-
|
|
57
|
+
function extractOverrides(response) {
|
|
58
|
+
const r = response;
|
|
59
|
+
return {
|
|
60
|
+
...r.id !== void 0 && { id: r.id },
|
|
61
|
+
...r.created !== void 0 && { created: r.created },
|
|
62
|
+
...r.model !== void 0 && { model: r.model },
|
|
63
|
+
...r.usage !== void 0 && { usage: r.usage },
|
|
64
|
+
...r.systemFingerprint !== void 0 && { systemFingerprint: r.systemFingerprint },
|
|
65
|
+
...r.finishReason !== void 0 && { finishReason: r.finishReason },
|
|
66
|
+
...r.role !== void 0 && { role: r.role }
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function buildTextChunks(content, model, chunkSize, reasoning, overrides) {
|
|
70
|
+
const id = overrides?.id ?? generateId();
|
|
71
|
+
const created = overrides?.created ?? Math.floor(Date.now() / 1e3);
|
|
72
|
+
const effectiveModel = overrides?.model ?? model;
|
|
60
73
|
const chunks = [];
|
|
74
|
+
const fingerprint = overrides?.systemFingerprint;
|
|
61
75
|
if (reasoning) for (let i = 0; i < reasoning.length; i += chunkSize) {
|
|
62
76
|
const slice = reasoning.slice(i, i + chunkSize);
|
|
63
77
|
chunks.push({
|
|
64
78
|
id,
|
|
65
79
|
object: "chat.completion.chunk",
|
|
66
80
|
created,
|
|
67
|
-
model,
|
|
81
|
+
model: effectiveModel,
|
|
68
82
|
choices: [{
|
|
69
83
|
index: 0,
|
|
70
84
|
delta: { reasoning_content: slice },
|
|
71
85
|
finish_reason: null
|
|
72
|
-
}]
|
|
86
|
+
}],
|
|
87
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
73
88
|
});
|
|
74
89
|
}
|
|
75
90
|
chunks.push({
|
|
76
91
|
id,
|
|
77
92
|
object: "chat.completion.chunk",
|
|
78
93
|
created,
|
|
79
|
-
model,
|
|
94
|
+
model: effectiveModel,
|
|
80
95
|
choices: [{
|
|
81
96
|
index: 0,
|
|
82
97
|
delta: {
|
|
83
|
-
role: "assistant",
|
|
98
|
+
role: overrides?.role ?? "assistant",
|
|
84
99
|
content: ""
|
|
85
100
|
},
|
|
86
101
|
finish_reason: null
|
|
87
|
-
}]
|
|
102
|
+
}],
|
|
103
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
88
104
|
});
|
|
89
105
|
for (let i = 0; i < content.length; i += chunkSize) {
|
|
90
106
|
const slice = content.slice(i, i + chunkSize);
|
|
@@ -92,44 +108,49 @@ function buildTextChunks(content, model, chunkSize, reasoning) {
|
|
|
92
108
|
id,
|
|
93
109
|
object: "chat.completion.chunk",
|
|
94
110
|
created,
|
|
95
|
-
model,
|
|
111
|
+
model: effectiveModel,
|
|
96
112
|
choices: [{
|
|
97
113
|
index: 0,
|
|
98
114
|
delta: { content: slice },
|
|
99
115
|
finish_reason: null
|
|
100
|
-
}]
|
|
116
|
+
}],
|
|
117
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
101
118
|
});
|
|
102
119
|
}
|
|
103
120
|
chunks.push({
|
|
104
121
|
id,
|
|
105
122
|
object: "chat.completion.chunk",
|
|
106
123
|
created,
|
|
107
|
-
model,
|
|
124
|
+
model: effectiveModel,
|
|
108
125
|
choices: [{
|
|
109
126
|
index: 0,
|
|
110
127
|
delta: {},
|
|
111
|
-
finish_reason: "stop"
|
|
112
|
-
}]
|
|
128
|
+
finish_reason: overrides?.finishReason ?? "stop"
|
|
129
|
+
}],
|
|
130
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
113
131
|
});
|
|
114
132
|
return chunks;
|
|
115
133
|
}
|
|
116
|
-
function buildToolCallChunks(toolCalls, model, chunkSize) {
|
|
117
|
-
const id = generateId();
|
|
118
|
-
const created = Math.floor(Date.now() / 1e3);
|
|
134
|
+
function buildToolCallChunks(toolCalls, model, chunkSize, overrides) {
|
|
135
|
+
const id = overrides?.id ?? generateId();
|
|
136
|
+
const created = overrides?.created ?? Math.floor(Date.now() / 1e3);
|
|
137
|
+
const effectiveModel = overrides?.model ?? model;
|
|
119
138
|
const chunks = [];
|
|
139
|
+
const fingerprint = overrides?.systemFingerprint;
|
|
120
140
|
chunks.push({
|
|
121
141
|
id,
|
|
122
142
|
object: "chat.completion.chunk",
|
|
123
143
|
created,
|
|
124
|
-
model,
|
|
144
|
+
model: effectiveModel,
|
|
125
145
|
choices: [{
|
|
126
146
|
index: 0,
|
|
127
147
|
delta: {
|
|
128
|
-
role: "assistant",
|
|
148
|
+
role: overrides?.role ?? "assistant",
|
|
129
149
|
content: null
|
|
130
150
|
},
|
|
131
151
|
finish_reason: null
|
|
132
|
-
}]
|
|
152
|
+
}],
|
|
153
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
133
154
|
});
|
|
134
155
|
for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {
|
|
135
156
|
const tc = toolCalls[tcIdx];
|
|
@@ -138,7 +159,7 @@ function buildToolCallChunks(toolCalls, model, chunkSize) {
|
|
|
138
159
|
id,
|
|
139
160
|
object: "chat.completion.chunk",
|
|
140
161
|
created,
|
|
141
|
-
model,
|
|
162
|
+
model: effectiveModel,
|
|
142
163
|
choices: [{
|
|
143
164
|
index: 0,
|
|
144
165
|
delta: { tool_calls: [{
|
|
@@ -151,7 +172,8 @@ function buildToolCallChunks(toolCalls, model, chunkSize) {
|
|
|
151
172
|
}
|
|
152
173
|
}] },
|
|
153
174
|
finish_reason: null
|
|
154
|
-
}]
|
|
175
|
+
}],
|
|
176
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
155
177
|
});
|
|
156
178
|
const args = tc.arguments;
|
|
157
179
|
for (let i = 0; i < args.length; i += chunkSize) {
|
|
@@ -160,7 +182,7 @@ function buildToolCallChunks(toolCalls, model, chunkSize) {
|
|
|
160
182
|
id,
|
|
161
183
|
object: "chat.completion.chunk",
|
|
162
184
|
created,
|
|
163
|
-
model,
|
|
185
|
+
model: effectiveModel,
|
|
164
186
|
choices: [{
|
|
165
187
|
index: 0,
|
|
166
188
|
delta: { tool_calls: [{
|
|
@@ -168,7 +190,8 @@ function buildToolCallChunks(toolCalls, model, chunkSize) {
|
|
|
168
190
|
function: { arguments: slice }
|
|
169
191
|
}] },
|
|
170
192
|
finish_reason: null
|
|
171
|
-
}]
|
|
193
|
+
}],
|
|
194
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
172
195
|
});
|
|
173
196
|
}
|
|
174
197
|
}
|
|
@@ -176,48 +199,60 @@ function buildToolCallChunks(toolCalls, model, chunkSize) {
|
|
|
176
199
|
id,
|
|
177
200
|
object: "chat.completion.chunk",
|
|
178
201
|
created,
|
|
179
|
-
model,
|
|
202
|
+
model: effectiveModel,
|
|
180
203
|
choices: [{
|
|
181
204
|
index: 0,
|
|
182
205
|
delta: {},
|
|
183
|
-
finish_reason: "tool_calls"
|
|
184
|
-
}]
|
|
206
|
+
finish_reason: overrides?.finishReason ?? "tool_calls"
|
|
207
|
+
}],
|
|
208
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
185
209
|
});
|
|
186
210
|
return chunks;
|
|
187
211
|
}
|
|
188
|
-
function buildTextCompletion(content, model, reasoning) {
|
|
212
|
+
function buildTextCompletion(content, model, reasoning, overrides) {
|
|
213
|
+
const defaultUsage = {
|
|
214
|
+
prompt_tokens: 0,
|
|
215
|
+
completion_tokens: 0,
|
|
216
|
+
total_tokens: 0
|
|
217
|
+
};
|
|
189
218
|
return {
|
|
190
|
-
id: generateId(),
|
|
219
|
+
id: overrides?.id ?? generateId(),
|
|
191
220
|
object: "chat.completion",
|
|
192
|
-
created: Math.floor(Date.now() / 1e3),
|
|
193
|
-
model,
|
|
221
|
+
created: overrides?.created ?? Math.floor(Date.now() / 1e3),
|
|
222
|
+
model: overrides?.model ?? model,
|
|
194
223
|
choices: [{
|
|
195
224
|
index: 0,
|
|
196
225
|
message: {
|
|
197
|
-
role: "assistant",
|
|
226
|
+
role: overrides?.role ?? "assistant",
|
|
198
227
|
content,
|
|
199
228
|
refusal: null,
|
|
200
229
|
...reasoning ? { reasoning_content: reasoning } : {}
|
|
201
230
|
},
|
|
202
|
-
finish_reason: "stop"
|
|
231
|
+
finish_reason: overrides?.finishReason ?? "stop"
|
|
203
232
|
}],
|
|
204
|
-
usage: {
|
|
205
|
-
prompt_tokens:
|
|
206
|
-
completion_tokens:
|
|
207
|
-
total_tokens: 0
|
|
208
|
-
}
|
|
233
|
+
usage: overrides?.usage ? {
|
|
234
|
+
prompt_tokens: overrides.usage.prompt_tokens ?? defaultUsage.prompt_tokens,
|
|
235
|
+
completion_tokens: overrides.usage.completion_tokens ?? defaultUsage.completion_tokens,
|
|
236
|
+
total_tokens: overrides.usage.total_tokens ?? (overrides.usage.prompt_tokens ?? 0) + (overrides.usage.completion_tokens ?? 0)
|
|
237
|
+
} : defaultUsage,
|
|
238
|
+
...overrides?.systemFingerprint !== void 0 && { system_fingerprint: overrides.systemFingerprint }
|
|
209
239
|
};
|
|
210
240
|
}
|
|
211
|
-
function buildToolCallCompletion(toolCalls, model) {
|
|
241
|
+
function buildToolCallCompletion(toolCalls, model, overrides) {
|
|
242
|
+
const defaultUsage = {
|
|
243
|
+
prompt_tokens: 0,
|
|
244
|
+
completion_tokens: 0,
|
|
245
|
+
total_tokens: 0
|
|
246
|
+
};
|
|
212
247
|
return {
|
|
213
|
-
id: generateId(),
|
|
248
|
+
id: overrides?.id ?? generateId(),
|
|
214
249
|
object: "chat.completion",
|
|
215
|
-
created: Math.floor(Date.now() / 1e3),
|
|
216
|
-
model,
|
|
250
|
+
created: overrides?.created ?? Math.floor(Date.now() / 1e3),
|
|
251
|
+
model: overrides?.model ?? model,
|
|
217
252
|
choices: [{
|
|
218
253
|
index: 0,
|
|
219
254
|
message: {
|
|
220
|
-
role: "assistant",
|
|
255
|
+
role: overrides?.role ?? "assistant",
|
|
221
256
|
content: null,
|
|
222
257
|
refusal: null,
|
|
223
258
|
tool_calls: toolCalls.map((tc) => ({
|
|
@@ -229,32 +264,51 @@ function buildToolCallCompletion(toolCalls, model) {
|
|
|
229
264
|
}
|
|
230
265
|
}))
|
|
231
266
|
},
|
|
232
|
-
finish_reason: "tool_calls"
|
|
267
|
+
finish_reason: overrides?.finishReason ?? "tool_calls"
|
|
233
268
|
}],
|
|
234
|
-
usage: {
|
|
235
|
-
prompt_tokens:
|
|
236
|
-
completion_tokens:
|
|
237
|
-
total_tokens: 0
|
|
238
|
-
}
|
|
269
|
+
usage: overrides?.usage ? {
|
|
270
|
+
prompt_tokens: overrides.usage.prompt_tokens ?? defaultUsage.prompt_tokens,
|
|
271
|
+
completion_tokens: overrides.usage.completion_tokens ?? defaultUsage.completion_tokens,
|
|
272
|
+
total_tokens: overrides.usage.total_tokens ?? (overrides.usage.prompt_tokens ?? 0) + (overrides.usage.completion_tokens ?? 0)
|
|
273
|
+
} : defaultUsage,
|
|
274
|
+
...overrides?.systemFingerprint !== void 0 && { system_fingerprint: overrides.systemFingerprint }
|
|
239
275
|
};
|
|
240
276
|
}
|
|
241
|
-
function buildContentWithToolCallsChunks(content, toolCalls, model, chunkSize) {
|
|
242
|
-
const id = generateId();
|
|
243
|
-
const created = Math.floor(Date.now() / 1e3);
|
|
277
|
+
function buildContentWithToolCallsChunks(content, toolCalls, model, chunkSize, reasoning, overrides) {
|
|
278
|
+
const id = overrides?.id ?? generateId();
|
|
279
|
+
const created = overrides?.created ?? Math.floor(Date.now() / 1e3);
|
|
280
|
+
const effectiveModel = overrides?.model ?? model;
|
|
244
281
|
const chunks = [];
|
|
282
|
+
const fingerprint = overrides?.systemFingerprint;
|
|
283
|
+
if (reasoning) for (let i = 0; i < reasoning.length; i += chunkSize) {
|
|
284
|
+
const slice = reasoning.slice(i, i + chunkSize);
|
|
285
|
+
chunks.push({
|
|
286
|
+
id,
|
|
287
|
+
object: "chat.completion.chunk",
|
|
288
|
+
created,
|
|
289
|
+
model: effectiveModel,
|
|
290
|
+
choices: [{
|
|
291
|
+
index: 0,
|
|
292
|
+
delta: { reasoning_content: slice },
|
|
293
|
+
finish_reason: null
|
|
294
|
+
}],
|
|
295
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
296
|
+
});
|
|
297
|
+
}
|
|
245
298
|
chunks.push({
|
|
246
299
|
id,
|
|
247
300
|
object: "chat.completion.chunk",
|
|
248
301
|
created,
|
|
249
|
-
model,
|
|
302
|
+
model: effectiveModel,
|
|
250
303
|
choices: [{
|
|
251
304
|
index: 0,
|
|
252
305
|
delta: {
|
|
253
|
-
role: "assistant",
|
|
306
|
+
role: overrides?.role ?? "assistant",
|
|
254
307
|
content: ""
|
|
255
308
|
},
|
|
256
309
|
finish_reason: null
|
|
257
|
-
}]
|
|
310
|
+
}],
|
|
311
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
258
312
|
});
|
|
259
313
|
for (let i = 0; i < content.length; i += chunkSize) {
|
|
260
314
|
const slice = content.slice(i, i + chunkSize);
|
|
@@ -262,12 +316,13 @@ function buildContentWithToolCallsChunks(content, toolCalls, model, chunkSize) {
|
|
|
262
316
|
id,
|
|
263
317
|
object: "chat.completion.chunk",
|
|
264
318
|
created,
|
|
265
|
-
model,
|
|
319
|
+
model: effectiveModel,
|
|
266
320
|
choices: [{
|
|
267
321
|
index: 0,
|
|
268
322
|
delta: { content: slice },
|
|
269
323
|
finish_reason: null
|
|
270
|
-
}]
|
|
324
|
+
}],
|
|
325
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
271
326
|
});
|
|
272
327
|
}
|
|
273
328
|
for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {
|
|
@@ -277,7 +332,7 @@ function buildContentWithToolCallsChunks(content, toolCalls, model, chunkSize) {
|
|
|
277
332
|
id,
|
|
278
333
|
object: "chat.completion.chunk",
|
|
279
334
|
created,
|
|
280
|
-
model,
|
|
335
|
+
model: effectiveModel,
|
|
281
336
|
choices: [{
|
|
282
337
|
index: 0,
|
|
283
338
|
delta: { tool_calls: [{
|
|
@@ -290,7 +345,8 @@ function buildContentWithToolCallsChunks(content, toolCalls, model, chunkSize) {
|
|
|
290
345
|
}
|
|
291
346
|
}] },
|
|
292
347
|
finish_reason: null
|
|
293
|
-
}]
|
|
348
|
+
}],
|
|
349
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
294
350
|
});
|
|
295
351
|
const args = tc.arguments;
|
|
296
352
|
for (let i = 0; i < args.length; i += chunkSize) {
|
|
@@ -299,7 +355,7 @@ function buildContentWithToolCallsChunks(content, toolCalls, model, chunkSize) {
|
|
|
299
355
|
id,
|
|
300
356
|
object: "chat.completion.chunk",
|
|
301
357
|
created,
|
|
302
|
-
model,
|
|
358
|
+
model: effectiveModel,
|
|
303
359
|
choices: [{
|
|
304
360
|
index: 0,
|
|
305
361
|
delta: { tool_calls: [{
|
|
@@ -307,7 +363,8 @@ function buildContentWithToolCallsChunks(content, toolCalls, model, chunkSize) {
|
|
|
307
363
|
function: { arguments: slice }
|
|
308
364
|
}] },
|
|
309
365
|
finish_reason: null
|
|
310
|
-
}]
|
|
366
|
+
}],
|
|
367
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
311
368
|
});
|
|
312
369
|
}
|
|
313
370
|
}
|
|
@@ -315,27 +372,34 @@ function buildContentWithToolCallsChunks(content, toolCalls, model, chunkSize) {
|
|
|
315
372
|
id,
|
|
316
373
|
object: "chat.completion.chunk",
|
|
317
374
|
created,
|
|
318
|
-
model,
|
|
375
|
+
model: effectiveModel,
|
|
319
376
|
choices: [{
|
|
320
377
|
index: 0,
|
|
321
378
|
delta: {},
|
|
322
|
-
finish_reason: "tool_calls"
|
|
323
|
-
}]
|
|
379
|
+
finish_reason: overrides?.finishReason ?? "tool_calls"
|
|
380
|
+
}],
|
|
381
|
+
...fingerprint !== void 0 && { system_fingerprint: fingerprint }
|
|
324
382
|
});
|
|
325
383
|
return chunks;
|
|
326
384
|
}
|
|
327
|
-
function buildContentWithToolCallsCompletion(content, toolCalls, model) {
|
|
385
|
+
function buildContentWithToolCallsCompletion(content, toolCalls, model, reasoning, overrides) {
|
|
386
|
+
const defaultUsage = {
|
|
387
|
+
prompt_tokens: 0,
|
|
388
|
+
completion_tokens: 0,
|
|
389
|
+
total_tokens: 0
|
|
390
|
+
};
|
|
328
391
|
return {
|
|
329
|
-
id: generateId(),
|
|
392
|
+
id: overrides?.id ?? generateId(),
|
|
330
393
|
object: "chat.completion",
|
|
331
|
-
created: Math.floor(Date.now() / 1e3),
|
|
332
|
-
model,
|
|
394
|
+
created: overrides?.created ?? Math.floor(Date.now() / 1e3),
|
|
395
|
+
model: overrides?.model ?? model,
|
|
333
396
|
choices: [{
|
|
334
397
|
index: 0,
|
|
335
398
|
message: {
|
|
336
|
-
role: "assistant",
|
|
399
|
+
role: overrides?.role ?? "assistant",
|
|
337
400
|
content,
|
|
338
401
|
refusal: null,
|
|
402
|
+
...reasoning ? { reasoning_content: reasoning } : {},
|
|
339
403
|
tool_calls: toolCalls.map((tc) => ({
|
|
340
404
|
id: tc.id || generateToolCallId(),
|
|
341
405
|
type: "function",
|
|
@@ -345,13 +409,14 @@ function buildContentWithToolCallsCompletion(content, toolCalls, model) {
|
|
|
345
409
|
}
|
|
346
410
|
}))
|
|
347
411
|
},
|
|
348
|
-
finish_reason: "tool_calls"
|
|
412
|
+
finish_reason: overrides?.finishReason ?? "tool_calls"
|
|
349
413
|
}],
|
|
350
|
-
usage: {
|
|
351
|
-
prompt_tokens:
|
|
352
|
-
completion_tokens:
|
|
353
|
-
total_tokens: 0
|
|
354
|
-
}
|
|
414
|
+
usage: overrides?.usage ? {
|
|
415
|
+
prompt_tokens: overrides.usage.prompt_tokens ?? defaultUsage.prompt_tokens,
|
|
416
|
+
completion_tokens: overrides.usage.completion_tokens ?? defaultUsage.completion_tokens,
|
|
417
|
+
total_tokens: overrides.usage.total_tokens ?? (overrides.usage.prompt_tokens ?? 0) + (overrides.usage.completion_tokens ?? 0)
|
|
418
|
+
} : defaultUsage,
|
|
419
|
+
...overrides?.systemFingerprint !== void 0 && { system_fingerprint: overrides.systemFingerprint }
|
|
355
420
|
};
|
|
356
421
|
}
|
|
357
422
|
function readBody(req) {
|
|
@@ -414,5 +479,5 @@ function buildEmbeddingResponse(embeddings, model) {
|
|
|
414
479
|
}
|
|
415
480
|
|
|
416
481
|
//#endregion
|
|
417
|
-
export { buildContentWithToolCallsChunks, buildContentWithToolCallsCompletion, buildEmbeddingResponse, buildTextChunks, buildTextCompletion, buildToolCallChunks, buildToolCallCompletion, flattenHeaders, generateDeterministicEmbedding, generateId, generateMessageId, generateToolCallId, generateToolUseId, getTestId, isAudioResponse, isContentWithToolCallsResponse, isEmbeddingResponse, isErrorResponse, isImageResponse, isTextResponse, isToolCallResponse, isTranscriptionResponse, isVideoResponse, matchesPattern, readBody };
|
|
482
|
+
export { buildContentWithToolCallsChunks, buildContentWithToolCallsCompletion, buildEmbeddingResponse, buildTextChunks, buildTextCompletion, buildToolCallChunks, buildToolCallCompletion, extractOverrides, flattenHeaders, generateDeterministicEmbedding, generateId, generateMessageId, generateToolCallId, generateToolUseId, getTestId, isAudioResponse, isContentWithToolCallsResponse, isEmbeddingResponse, isErrorResponse, isImageResponse, isTextResponse, isToolCallResponse, isTranscriptionResponse, isVideoResponse, matchesPattern, readBody };
|
|
418
483
|
//# sourceMappingURL=helpers.js.map
|
package/dist/helpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","names":[],"sources":["../src/helpers.ts"],"sourcesContent":["import { createHash, randomBytes } from \"node:crypto\";\nimport type * as http from \"node:http\";\nimport type {\n FixtureResponse,\n TextResponse,\n ToolCallResponse,\n ContentWithToolCallsResponse,\n ErrorResponse,\n EmbeddingResponse,\n ImageResponse,\n AudioResponse,\n TranscriptionResponse,\n VideoResponse,\n SSEChunk,\n ToolCall,\n ChatCompletion,\n} from \"./types.js\";\n\nconst REDACTED_HEADERS = new Set([\"authorization\", \"x-api-key\", \"api-key\"]);\n\nexport function flattenHeaders(headers: http.IncomingHttpHeaders): Record<string, string> {\n const flat: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value === undefined) continue;\n if (REDACTED_HEADERS.has(key.toLowerCase())) {\n flat[key] = \"[REDACTED]\";\n } else {\n flat[key] = Array.isArray(value) ? value.join(\", \") : value;\n }\n }\n return flat;\n}\n\nexport function generateId(prefix = \"chatcmpl\"): string {\n return `${prefix}-${randomBytes(12).toString(\"base64url\")}`;\n}\n\nexport function generateToolCallId(): string {\n return `call_${randomBytes(12).toString(\"base64url\")}`;\n}\n\nexport function generateMessageId(): string {\n return `msg_${randomBytes(12).toString(\"base64url\")}`;\n}\n\nexport function generateToolUseId(): string {\n return `toolu_${randomBytes(12).toString(\"base64url\")}`;\n}\n\nexport function isTextResponse(r: FixtureResponse): r is TextResponse {\n return \"content\" in r && typeof (r as TextResponse).content === \"string\";\n}\n\nexport function isToolCallResponse(r: FixtureResponse): r is ToolCallResponse {\n return \"toolCalls\" in r && Array.isArray((r as ToolCallResponse).toolCalls);\n}\n\nexport function isContentWithToolCallsResponse(\n r: FixtureResponse,\n): r is ContentWithToolCallsResponse {\n return (\n \"content\" in r &&\n typeof (r as ContentWithToolCallsResponse).content === \"string\" &&\n \"toolCalls\" in r &&\n Array.isArray((r as ContentWithToolCallsResponse).toolCalls)\n );\n}\n\nexport function isErrorResponse(r: FixtureResponse): r is ErrorResponse {\n return (\n \"error\" in r &&\n (r as ErrorResponse).error !== null &&\n typeof (r as ErrorResponse).error === \"object\"\n );\n}\n\nexport function isEmbeddingResponse(r: FixtureResponse): r is EmbeddingResponse {\n return \"embedding\" in r && Array.isArray((r as EmbeddingResponse).embedding);\n}\n\nexport function isImageResponse(r: FixtureResponse): r is ImageResponse {\n return (\n (\"image\" in r && r.image != null) ||\n (\"images\" in r && Array.isArray((r as ImageResponse).images))\n );\n}\n\nexport function isAudioResponse(r: FixtureResponse): r is AudioResponse {\n return \"audio\" in r && typeof (r as AudioResponse).audio === \"string\";\n}\n\nexport function isTranscriptionResponse(r: FixtureResponse): r is TranscriptionResponse {\n return (\n \"transcription\" in r &&\n (r as TranscriptionResponse).transcription != null &&\n typeof (r as TranscriptionResponse).transcription === \"object\"\n );\n}\n\nexport function isVideoResponse(r: FixtureResponse): r is VideoResponse {\n return (\n \"video\" in r &&\n (r as VideoResponse).video != null &&\n typeof (r as VideoResponse).video === \"object\"\n );\n}\n\nexport function buildTextChunks(\n content: string,\n model: string,\n chunkSize: number,\n reasoning?: string,\n): SSEChunk[] {\n const id = generateId();\n const created = Math.floor(Date.now() / 1000);\n const chunks: SSEChunk[] = [];\n\n // Reasoning chunks (emitted before content, OpenRouter format)\n if (reasoning) {\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [{ index: 0, delta: { reasoning_content: slice }, finish_reason: null }],\n });\n }\n }\n\n // Role chunk\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [{ index: 0, delta: { role: \"assistant\", content: \"\" }, finish_reason: null }],\n });\n\n // Content chunks\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [{ index: 0, delta: { content: slice }, finish_reason: null }],\n });\n }\n\n // Finish chunk\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [{ index: 0, delta: {}, finish_reason: \"stop\" }],\n });\n\n return chunks;\n}\n\nexport function buildToolCallChunks(\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n): SSEChunk[] {\n const id = generateId();\n const created = Math.floor(Date.now() / 1000);\n const chunks: SSEChunk[] = [];\n\n // Role chunk\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [{ index: 0, delta: { role: \"assistant\", content: null }, finish_reason: null }],\n });\n\n // Tool call chunks — one initial chunk per tool call, then argument chunks\n for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {\n const tc = toolCalls[tcIdx];\n const tcId = tc.id || generateToolCallId();\n\n // Initial tool call chunk (id + function name)\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [\n {\n index: 0,\n delta: {\n tool_calls: [\n {\n index: tcIdx,\n id: tcId,\n type: \"function\",\n function: { name: tc.name, arguments: \"\" },\n },\n ],\n },\n finish_reason: null,\n },\n ],\n });\n\n // Argument streaming chunks\n const args = tc.arguments;\n for (let i = 0; i < args.length; i += chunkSize) {\n const slice = args.slice(i, i + chunkSize);\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [\n {\n index: 0,\n delta: {\n tool_calls: [{ index: tcIdx, function: { arguments: slice } }],\n },\n finish_reason: null,\n },\n ],\n });\n }\n }\n\n // Finish chunk\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [{ index: 0, delta: {}, finish_reason: \"tool_calls\" }],\n });\n\n return chunks;\n}\n\n// Non-streaming response builders\n\nexport function buildTextCompletion(\n content: string,\n model: string,\n reasoning?: string,\n): ChatCompletion {\n return {\n id: generateId(),\n object: \"chat.completion\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n message: {\n role: \"assistant\",\n content,\n refusal: null,\n ...(reasoning ? { reasoning_content: reasoning } : {}),\n },\n finish_reason: \"stop\",\n },\n ],\n usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n };\n}\n\nexport function buildToolCallCompletion(toolCalls: ToolCall[], model: string): ChatCompletion {\n return {\n id: generateId(),\n object: \"chat.completion\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n message: {\n role: \"assistant\",\n content: null,\n refusal: null,\n tool_calls: toolCalls.map((tc) => ({\n id: tc.id || generateToolCallId(),\n type: \"function\" as const,\n function: { name: tc.name, arguments: tc.arguments },\n })),\n },\n finish_reason: \"tool_calls\",\n },\n ],\n usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n };\n}\n\nexport function buildContentWithToolCallsChunks(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n): SSEChunk[] {\n const id = generateId();\n const created = Math.floor(Date.now() / 1000);\n const chunks: SSEChunk[] = [];\n\n // Role chunk\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [{ index: 0, delta: { role: \"assistant\", content: \"\" }, finish_reason: null }],\n });\n\n // Content chunks\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [{ index: 0, delta: { content: slice }, finish_reason: null }],\n });\n }\n\n // Tool call chunks — one initial chunk per tool call, then argument chunks\n for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {\n const tc = toolCalls[tcIdx];\n const tcId = tc.id || generateToolCallId();\n\n // Initial tool call chunk (id + function name)\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [\n {\n index: 0,\n delta: {\n tool_calls: [\n {\n index: tcIdx,\n id: tcId,\n type: \"function\",\n function: { name: tc.name, arguments: \"\" },\n },\n ],\n },\n finish_reason: null,\n },\n ],\n });\n\n // Argument streaming chunks\n const args = tc.arguments;\n for (let i = 0; i < args.length; i += chunkSize) {\n const slice = args.slice(i, i + chunkSize);\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [\n {\n index: 0,\n delta: {\n tool_calls: [{ index: tcIdx, function: { arguments: slice } }],\n },\n finish_reason: null,\n },\n ],\n });\n }\n }\n\n // Finish chunk\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model,\n choices: [{ index: 0, delta: {}, finish_reason: \"tool_calls\" }],\n });\n\n return chunks;\n}\n\nexport function buildContentWithToolCallsCompletion(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n): ChatCompletion {\n return {\n id: generateId(),\n object: \"chat.completion\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n message: {\n role: \"assistant\",\n content,\n refusal: null,\n tool_calls: toolCalls.map((tc) => ({\n id: tc.id || generateToolCallId(),\n type: \"function\" as const,\n function: { name: tc.name, arguments: tc.arguments },\n })),\n },\n finish_reason: \"tool_calls\",\n },\n ],\n usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n };\n}\n\n// ─── HTTP helpers ─────────────────────────────────────────────────────────\n\nexport function readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n req.on(\"end\", () => resolve(Buffer.concat(chunks).toString()));\n req.on(\"error\", reject);\n });\n}\n\n// ─── Pattern matching ─────────────────────────────────────────────────────\n\nexport function matchesPattern(text: string, pattern: string | RegExp): boolean {\n if (typeof pattern === \"string\") {\n return text.toLowerCase().includes(pattern.toLowerCase());\n }\n return pattern.test(text);\n}\n\nexport function getTestId(req: http.IncomingMessage): string {\n const headerValue = req.headers[\"x-test-id\"];\n if (Array.isArray(headerValue)) {\n if (headerValue.length > 0 && headerValue[0]) return headerValue[0];\n } else if (typeof headerValue === \"string\" && headerValue) {\n return headerValue;\n }\n\n const url = req.url ?? \"/\";\n const qIdx = url.indexOf(\"?\");\n if (qIdx !== -1) {\n const params = new URLSearchParams(url.slice(qIdx + 1));\n const queryValue = params.get(\"testId\");\n if (queryValue) return queryValue;\n }\n\n // Duplicated from journal.ts DEFAULT_TEST_ID — importing it here would create\n // a circular dependency (journal.ts imports from helpers.ts).\n return \"__default__\";\n}\n\n// ─── Embedding helpers ─────────────────────────────────────────────────────\n\nconst DEFAULT_EMBEDDING_DIMENSIONS = 1536;\n\n/**\n * Generate a deterministic embedding vector from input text.\n * Hashes the input with SHA-256 and spreads the hash bytes across\n * the requested number of dimensions, producing values in [-1, 1].\n */\nexport function generateDeterministicEmbedding(\n input: string,\n dimensions: number = DEFAULT_EMBEDDING_DIMENSIONS,\n): number[] {\n let currentHash = createHash(\"sha256\").update(input).digest();\n const embedding: number[] = new Array(dimensions);\n for (let i = 0; i < dimensions; i++) {\n if (i > 0 && i % 32 === 0) {\n currentHash = createHash(\"sha256\").update(currentHash).digest();\n }\n // Map 0-255 → -1.0 to 1.0\n embedding[i] = currentHash[i % 32] / 127.5 - 1;\n }\n return embedding;\n}\n\nexport interface EmbeddingAPIResponse {\n object: \"list\";\n data: { object: \"embedding\"; index: number; embedding: number[] }[];\n model: string;\n usage: { prompt_tokens: number; total_tokens: number };\n}\n\n/**\n * Build an OpenAI-format embeddings API response for one or more inputs.\n */\nexport function buildEmbeddingResponse(\n embeddings: number[][],\n model: string,\n): EmbeddingAPIResponse {\n return {\n object: \"list\",\n data: embeddings.map((embedding, index) => ({\n object: \"embedding\" as const,\n index,\n embedding,\n })),\n model,\n usage: { prompt_tokens: 0, total_tokens: 0 },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"helpers.js","names":[],"sources":["../src/helpers.ts"],"sourcesContent":["import { createHash, randomBytes } from \"node:crypto\";\nimport type * as http from \"node:http\";\nimport type {\n FixtureResponse,\n TextResponse,\n ToolCallResponse,\n ContentWithToolCallsResponse,\n ErrorResponse,\n EmbeddingResponse,\n ImageResponse,\n AudioResponse,\n TranscriptionResponse,\n VideoResponse,\n SSEChunk,\n ToolCall,\n ChatCompletion,\n ResponseOverrides,\n} from \"./types.js\";\n\nconst REDACTED_HEADERS = new Set([\"authorization\", \"x-api-key\", \"api-key\"]);\n\nexport function flattenHeaders(headers: http.IncomingHttpHeaders): Record<string, string> {\n const flat: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value === undefined) continue;\n if (REDACTED_HEADERS.has(key.toLowerCase())) {\n flat[key] = \"[REDACTED]\";\n } else {\n flat[key] = Array.isArray(value) ? value.join(\", \") : value;\n }\n }\n return flat;\n}\n\nexport function generateId(prefix = \"chatcmpl\"): string {\n return `${prefix}-${randomBytes(12).toString(\"base64url\")}`;\n}\n\nexport function generateToolCallId(): string {\n return `call_${randomBytes(12).toString(\"base64url\")}`;\n}\n\nexport function generateMessageId(): string {\n return `msg_${randomBytes(12).toString(\"base64url\")}`;\n}\n\nexport function generateToolUseId(): string {\n return `toolu_${randomBytes(12).toString(\"base64url\")}`;\n}\n\nexport function isTextResponse(r: FixtureResponse): r is TextResponse {\n return \"content\" in r && typeof (r as TextResponse).content === \"string\" && !(\"toolCalls\" in r);\n}\n\nexport function isToolCallResponse(r: FixtureResponse): r is ToolCallResponse {\n return (\n \"toolCalls\" in r &&\n Array.isArray((r as ToolCallResponse).toolCalls) &&\n !(\"content\" in r && typeof (r as unknown as Record<string, unknown>).content === \"string\")\n );\n}\n\nexport function isContentWithToolCallsResponse(\n r: FixtureResponse,\n): r is ContentWithToolCallsResponse {\n return (\n \"content\" in r &&\n typeof (r as ContentWithToolCallsResponse).content === \"string\" &&\n \"toolCalls\" in r &&\n Array.isArray((r as ContentWithToolCallsResponse).toolCalls)\n );\n}\n\nexport function isErrorResponse(r: FixtureResponse): r is ErrorResponse {\n return (\n \"error\" in r &&\n (r as ErrorResponse).error !== null &&\n typeof (r as ErrorResponse).error === \"object\"\n );\n}\n\nexport function isEmbeddingResponse(r: FixtureResponse): r is EmbeddingResponse {\n return \"embedding\" in r && Array.isArray((r as EmbeddingResponse).embedding);\n}\n\nexport function isImageResponse(r: FixtureResponse): r is ImageResponse {\n return (\n (\"image\" in r && r.image != null) ||\n (\"images\" in r && Array.isArray((r as ImageResponse).images))\n );\n}\n\nexport function isAudioResponse(r: FixtureResponse): r is AudioResponse {\n return \"audio\" in r && typeof (r as AudioResponse).audio === \"string\";\n}\n\nexport function isTranscriptionResponse(r: FixtureResponse): r is TranscriptionResponse {\n return (\n \"transcription\" in r &&\n (r as TranscriptionResponse).transcription != null &&\n typeof (r as TranscriptionResponse).transcription === \"object\"\n );\n}\n\nexport function isVideoResponse(r: FixtureResponse): r is VideoResponse {\n return (\n \"video\" in r &&\n (r as VideoResponse).video != null &&\n typeof (r as VideoResponse).video === \"object\"\n );\n}\n\nexport function extractOverrides(\n response: TextResponse | ToolCallResponse | ContentWithToolCallsResponse,\n): ResponseOverrides {\n const r = response;\n return {\n ...(r.id !== undefined && { id: r.id }),\n ...(r.created !== undefined && { created: r.created }),\n ...(r.model !== undefined && { model: r.model }),\n ...(r.usage !== undefined && { usage: r.usage }),\n ...(r.systemFingerprint !== undefined && { systemFingerprint: r.systemFingerprint }),\n ...(r.finishReason !== undefined && { finishReason: r.finishReason }),\n ...(r.role !== undefined && { role: r.role }),\n };\n}\n\nexport function buildTextChunks(\n content: string,\n model: string,\n chunkSize: number,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): SSEChunk[] {\n const id = overrides?.id ?? generateId();\n const created = overrides?.created ?? Math.floor(Date.now() / 1000);\n const effectiveModel = overrides?.model ?? model;\n const chunks: SSEChunk[] = [];\n const fingerprint = overrides?.systemFingerprint;\n\n // Reasoning chunks (emitted before content, OpenRouter format)\n if (reasoning) {\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [{ index: 0, delta: { reasoning_content: slice }, finish_reason: null }],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n }\n }\n\n // Role chunk\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [\n {\n index: 0,\n delta: { role: overrides?.role ?? \"assistant\", content: \"\" },\n finish_reason: null,\n },\n ],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n\n // Content chunks\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [{ index: 0, delta: { content: slice }, finish_reason: null }],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n }\n\n // Finish chunk\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [{ index: 0, delta: {}, finish_reason: overrides?.finishReason ?? \"stop\" }],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n\n return chunks;\n}\n\nexport function buildToolCallChunks(\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n overrides?: ResponseOverrides,\n): SSEChunk[] {\n const id = overrides?.id ?? generateId();\n const created = overrides?.created ?? Math.floor(Date.now() / 1000);\n const effectiveModel = overrides?.model ?? model;\n const chunks: SSEChunk[] = [];\n const fingerprint = overrides?.systemFingerprint;\n\n // Role chunk\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [\n {\n index: 0,\n delta: { role: overrides?.role ?? \"assistant\", content: null },\n finish_reason: null,\n },\n ],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n\n // Tool call chunks — one initial chunk per tool call, then argument chunks\n for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {\n const tc = toolCalls[tcIdx];\n const tcId = tc.id || generateToolCallId();\n\n // Initial tool call chunk (id + function name)\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [\n {\n index: 0,\n delta: {\n tool_calls: [\n {\n index: tcIdx,\n id: tcId,\n type: \"function\",\n function: { name: tc.name, arguments: \"\" },\n },\n ],\n },\n finish_reason: null,\n },\n ],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n\n // Argument streaming chunks\n const args = tc.arguments;\n for (let i = 0; i < args.length; i += chunkSize) {\n const slice = args.slice(i, i + chunkSize);\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [\n {\n index: 0,\n delta: {\n tool_calls: [{ index: tcIdx, function: { arguments: slice } }],\n },\n finish_reason: null,\n },\n ],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n }\n }\n\n // Finish chunk\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [{ index: 0, delta: {}, finish_reason: overrides?.finishReason ?? \"tool_calls\" }],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n\n return chunks;\n}\n\n// Non-streaming response builders\n\nexport function buildTextCompletion(\n content: string,\n model: string,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): ChatCompletion {\n const defaultUsage = { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 };\n return {\n id: overrides?.id ?? generateId(),\n object: \"chat.completion\",\n created: overrides?.created ?? Math.floor(Date.now() / 1000),\n model: overrides?.model ?? model,\n choices: [\n {\n index: 0,\n message: {\n role: overrides?.role ?? \"assistant\",\n content,\n refusal: null,\n ...(reasoning ? { reasoning_content: reasoning } : {}),\n },\n finish_reason: overrides?.finishReason ?? \"stop\",\n },\n ],\n usage: overrides?.usage\n ? {\n prompt_tokens: overrides.usage.prompt_tokens ?? defaultUsage.prompt_tokens,\n completion_tokens: overrides.usage.completion_tokens ?? defaultUsage.completion_tokens,\n total_tokens:\n overrides.usage.total_tokens ??\n (overrides.usage.prompt_tokens ?? 0) + (overrides.usage.completion_tokens ?? 0),\n }\n : defaultUsage,\n ...(overrides?.systemFingerprint !== undefined && {\n system_fingerprint: overrides.systemFingerprint,\n }),\n };\n}\n\nexport function buildToolCallCompletion(\n toolCalls: ToolCall[],\n model: string,\n overrides?: ResponseOverrides,\n): ChatCompletion {\n const defaultUsage = { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 };\n return {\n id: overrides?.id ?? generateId(),\n object: \"chat.completion\",\n created: overrides?.created ?? Math.floor(Date.now() / 1000),\n model: overrides?.model ?? model,\n choices: [\n {\n index: 0,\n message: {\n role: overrides?.role ?? \"assistant\",\n content: null,\n refusal: null,\n tool_calls: toolCalls.map((tc) => ({\n id: tc.id || generateToolCallId(),\n type: \"function\" as const,\n function: { name: tc.name, arguments: tc.arguments },\n })),\n },\n finish_reason: overrides?.finishReason ?? \"tool_calls\",\n },\n ],\n usage: overrides?.usage\n ? {\n prompt_tokens: overrides.usage.prompt_tokens ?? defaultUsage.prompt_tokens,\n completion_tokens: overrides.usage.completion_tokens ?? defaultUsage.completion_tokens,\n total_tokens:\n overrides.usage.total_tokens ??\n (overrides.usage.prompt_tokens ?? 0) + (overrides.usage.completion_tokens ?? 0),\n }\n : defaultUsage,\n ...(overrides?.systemFingerprint !== undefined && {\n system_fingerprint: overrides.systemFingerprint,\n }),\n };\n}\n\nexport function buildContentWithToolCallsChunks(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n chunkSize: number,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): SSEChunk[] {\n const id = overrides?.id ?? generateId();\n const created = overrides?.created ?? Math.floor(Date.now() / 1000);\n const effectiveModel = overrides?.model ?? model;\n const chunks: SSEChunk[] = [];\n const fingerprint = overrides?.systemFingerprint;\n\n // Reasoning chunks (emitted before content, OpenRouter format)\n if (reasoning) {\n for (let i = 0; i < reasoning.length; i += chunkSize) {\n const slice = reasoning.slice(i, i + chunkSize);\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [{ index: 0, delta: { reasoning_content: slice }, finish_reason: null }],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n }\n }\n\n // Role chunk\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [\n {\n index: 0,\n delta: { role: overrides?.role ?? \"assistant\", content: \"\" },\n finish_reason: null,\n },\n ],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n\n // Content chunks\n for (let i = 0; i < content.length; i += chunkSize) {\n const slice = content.slice(i, i + chunkSize);\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [{ index: 0, delta: { content: slice }, finish_reason: null }],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n }\n\n // Tool call chunks — one initial chunk per tool call, then argument chunks\n for (let tcIdx = 0; tcIdx < toolCalls.length; tcIdx++) {\n const tc = toolCalls[tcIdx];\n const tcId = tc.id || generateToolCallId();\n\n // Initial tool call chunk (id + function name)\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [\n {\n index: 0,\n delta: {\n tool_calls: [\n {\n index: tcIdx,\n id: tcId,\n type: \"function\",\n function: { name: tc.name, arguments: \"\" },\n },\n ],\n },\n finish_reason: null,\n },\n ],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n\n // Argument streaming chunks\n const args = tc.arguments;\n for (let i = 0; i < args.length; i += chunkSize) {\n const slice = args.slice(i, i + chunkSize);\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [\n {\n index: 0,\n delta: {\n tool_calls: [{ index: tcIdx, function: { arguments: slice } }],\n },\n finish_reason: null,\n },\n ],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n }\n }\n\n // Finish chunk\n chunks.push({\n id,\n object: \"chat.completion.chunk\",\n created,\n model: effectiveModel,\n choices: [{ index: 0, delta: {}, finish_reason: overrides?.finishReason ?? \"tool_calls\" }],\n ...(fingerprint !== undefined && { system_fingerprint: fingerprint }),\n });\n\n return chunks;\n}\n\nexport function buildContentWithToolCallsCompletion(\n content: string,\n toolCalls: ToolCall[],\n model: string,\n reasoning?: string,\n overrides?: ResponseOverrides,\n): ChatCompletion {\n const defaultUsage = { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 };\n return {\n id: overrides?.id ?? generateId(),\n object: \"chat.completion\",\n created: overrides?.created ?? Math.floor(Date.now() / 1000),\n model: overrides?.model ?? model,\n choices: [\n {\n index: 0,\n message: {\n role: overrides?.role ?? \"assistant\",\n content,\n refusal: null,\n ...(reasoning ? { reasoning_content: reasoning } : {}),\n tool_calls: toolCalls.map((tc) => ({\n id: tc.id || generateToolCallId(),\n type: \"function\" as const,\n function: { name: tc.name, arguments: tc.arguments },\n })),\n },\n finish_reason: overrides?.finishReason ?? \"tool_calls\",\n },\n ],\n usage: overrides?.usage\n ? {\n prompt_tokens: overrides.usage.prompt_tokens ?? defaultUsage.prompt_tokens,\n completion_tokens: overrides.usage.completion_tokens ?? defaultUsage.completion_tokens,\n total_tokens:\n overrides.usage.total_tokens ??\n (overrides.usage.prompt_tokens ?? 0) + (overrides.usage.completion_tokens ?? 0),\n }\n : defaultUsage,\n ...(overrides?.systemFingerprint !== undefined && {\n system_fingerprint: overrides.systemFingerprint,\n }),\n };\n}\n\n// ─── HTTP helpers ─────────────────────────────────────────────────────────\n\nexport function readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n req.on(\"end\", () => resolve(Buffer.concat(chunks).toString()));\n req.on(\"error\", reject);\n });\n}\n\n// ─── Pattern matching ─────────────────────────────────────────────────────\n\nexport function matchesPattern(text: string, pattern: string | RegExp): boolean {\n if (typeof pattern === \"string\") {\n return text.toLowerCase().includes(pattern.toLowerCase());\n }\n return pattern.test(text);\n}\n\nexport function getTestId(req: http.IncomingMessage): string {\n const headerValue = req.headers[\"x-test-id\"];\n if (Array.isArray(headerValue)) {\n if (headerValue.length > 0 && headerValue[0]) return headerValue[0];\n } else if (typeof headerValue === \"string\" && headerValue) {\n return headerValue;\n }\n\n const url = req.url ?? \"/\";\n const qIdx = url.indexOf(\"?\");\n if (qIdx !== -1) {\n const params = new URLSearchParams(url.slice(qIdx + 1));\n const queryValue = params.get(\"testId\");\n if (queryValue) return queryValue;\n }\n\n // Duplicated from journal.ts DEFAULT_TEST_ID — importing it here would create\n // a circular dependency (journal.ts imports from helpers.ts).\n return \"__default__\";\n}\n\n// ─── Embedding helpers ─────────────────────────────────────────────────────\n\nconst DEFAULT_EMBEDDING_DIMENSIONS = 1536;\n\n/**\n * Generate a deterministic embedding vector from input text.\n * Hashes the input with SHA-256 and spreads the hash bytes across\n * the requested number of dimensions, producing values in [-1, 1].\n */\nexport function generateDeterministicEmbedding(\n input: string,\n dimensions: number = DEFAULT_EMBEDDING_DIMENSIONS,\n): number[] {\n let currentHash = createHash(\"sha256\").update(input).digest();\n const embedding: number[] = new Array(dimensions);\n for (let i = 0; i < dimensions; i++) {\n if (i > 0 && i % 32 === 0) {\n currentHash = createHash(\"sha256\").update(currentHash).digest();\n }\n // Map 0-255 → -1.0 to 1.0\n embedding[i] = currentHash[i % 32] / 127.5 - 1;\n }\n return embedding;\n}\n\nexport interface EmbeddingAPIResponse {\n object: \"list\";\n data: { object: \"embedding\"; index: number; embedding: number[] }[];\n model: string;\n usage: { prompt_tokens: number; total_tokens: number };\n}\n\n/**\n * Build an OpenAI-format embeddings API response for one or more inputs.\n */\nexport function buildEmbeddingResponse(\n embeddings: number[][],\n model: string,\n): EmbeddingAPIResponse {\n return {\n object: \"list\",\n data: embeddings.map((embedding, index) => ({\n object: \"embedding\" as const,\n index,\n embedding,\n })),\n model,\n usage: { prompt_tokens: 0, total_tokens: 0 },\n };\n}\n"],"mappings":"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"}
|