@cognipeer/agent-sdk 0.10.5 → 0.12.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/README.md +28 -3
- package/dist/index.cjs +1785 -501
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1073 -661
- package/dist/index.d.ts +1073 -661
- package/dist/index.mjs +1778 -501
- package/dist/index.mjs.map +1 -1
- package/package.json +39 -1
package/dist/index.mjs
CHANGED
|
@@ -18,6 +18,238 @@ var __export = (target, all) => {
|
|
|
18
18
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
+
// src/utils/content.ts
|
|
22
|
+
function isRecord(value) {
|
|
23
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
24
|
+
}
|
|
25
|
+
function nonEmpty(value) {
|
|
26
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
27
|
+
}
|
|
28
|
+
function kindFromMediaType(mediaType) {
|
|
29
|
+
const top = mediaType?.split("/")[0];
|
|
30
|
+
return top === "image" || top === "audio" || top === "video" ? top : "file";
|
|
31
|
+
}
|
|
32
|
+
function inlineDataOf(part) {
|
|
33
|
+
const inline = part.inlineData ?? part.inline_data ?? part.fileData ?? part.file_data;
|
|
34
|
+
return isRecord(inline) ? inline : void 0;
|
|
35
|
+
}
|
|
36
|
+
function mediaKindOf(part) {
|
|
37
|
+
if (!isRecord(part)) return void 0;
|
|
38
|
+
const type = nonEmpty(part.type);
|
|
39
|
+
if (type) return MEDIA_PART_KINDS[type];
|
|
40
|
+
const inline = inlineDataOf(part);
|
|
41
|
+
if (inline) return kindFromMediaType(nonEmpty(inline.mimeType) ?? nonEmpty(inline.mime_type));
|
|
42
|
+
return void 0;
|
|
43
|
+
}
|
|
44
|
+
function hasMediaPart(content) {
|
|
45
|
+
return Array.isArray(content) && content.some((part) => mediaKindOf(part) !== void 0);
|
|
46
|
+
}
|
|
47
|
+
function urlOfPart(part) {
|
|
48
|
+
const image = part.image_url;
|
|
49
|
+
const video = part.video_url;
|
|
50
|
+
return nonEmpty(typeof image === "string" ? image : image?.url) ?? nonEmpty(typeof video === "string" ? video : video?.url) ?? nonEmpty(part.url) ?? nonEmpty(part.source?.url) ?? nonEmpty(inlineDataOf(part)?.fileUri) ?? nonEmpty(inlineDataOf(part)?.file_uri);
|
|
51
|
+
}
|
|
52
|
+
function mediaTypeOfPart(part) {
|
|
53
|
+
const image = isRecord(part.image_url) ? part.image_url : void 0;
|
|
54
|
+
const source = isRecord(part.source) ? part.source : void 0;
|
|
55
|
+
const inline = inlineDataOf(part);
|
|
56
|
+
const audioFormat = nonEmpty(part.input_audio?.format);
|
|
57
|
+
const fromDataUrl = /^data:([^;,]+)/i.exec(urlOfPart(part) ?? "")?.[1];
|
|
58
|
+
return nonEmpty(part.mediaType) ?? nonEmpty(part.media_type) ?? nonEmpty(part.mimeType) ?? nonEmpty(part.mime_type) ?? nonEmpty(source?.mediaType) ?? nonEmpty(source?.media_type) ?? nonEmpty(image?.mediaType) ?? nonEmpty(image?.media_type) ?? nonEmpty(inline?.mimeType) ?? nonEmpty(inline?.mime_type) ?? nonEmpty(fromDataUrl) ?? (audioFormat ? `audio/${audioFormat}` : void 0);
|
|
59
|
+
}
|
|
60
|
+
function nameOfPart(part) {
|
|
61
|
+
const file = isRecord(part.file) ? part.file : void 0;
|
|
62
|
+
const image = isRecord(part.image_url) ? part.image_url : void 0;
|
|
63
|
+
const source = isRecord(part.source) ? part.source : void 0;
|
|
64
|
+
return nonEmpty(part.name) ?? nonEmpty(part.fileName) ?? nonEmpty(part.filename) ?? nonEmpty(part.file_name) ?? nonEmpty(file?.filename) ?? nonEmpty(file?.fileName) ?? nonEmpty(image?.name) ?? nonEmpty(source?.fileName) ?? nonEmpty(source?.filename) ?? nonEmpty(part.fileId) ?? nonEmpty(part.file_id) ?? nonEmpty(file?.file_id) ?? nonEmpty(file?.fileId) ?? nonEmpty(image?.fileId) ?? nonEmpty(image?.file_id) ?? nonEmpty(part.image_file?.file_id);
|
|
65
|
+
}
|
|
66
|
+
function labelFromUrl(url) {
|
|
67
|
+
if (!url || url.startsWith("data:")) return void 0;
|
|
68
|
+
try {
|
|
69
|
+
const parsed = new URL(url);
|
|
70
|
+
if (parsed.protocol === "session-file:") return nonEmpty(parsed.hostname) ?? nonEmpty(parsed.pathname.replace(/^\/+/, ""));
|
|
71
|
+
if (parsed.protocol === "http:" || parsed.protocol === "https:") {
|
|
72
|
+
return nonEmpty(decodeURIComponent(parsed.pathname.split("/").filter(Boolean).pop() ?? ""));
|
|
73
|
+
}
|
|
74
|
+
} catch {
|
|
75
|
+
}
|
|
76
|
+
return void 0;
|
|
77
|
+
}
|
|
78
|
+
function describeContentPart(part) {
|
|
79
|
+
const kind = mediaKindOf(part);
|
|
80
|
+
if (!kind || !isRecord(part)) return void 0;
|
|
81
|
+
const label = nameOfPart(part) ?? mediaTypeOfPart(part) ?? labelFromUrl(urlOfPart(part));
|
|
82
|
+
if (!label) return `[${kind}]`;
|
|
83
|
+
const clean = label.replace(/[\r\n\]]+/g, " ").slice(0, PLACEHOLDER_LABEL_MAX);
|
|
84
|
+
return `[${kind}: ${clean}]`;
|
|
85
|
+
}
|
|
86
|
+
function contentPartToText(part, fallback) {
|
|
87
|
+
if (typeof part === "string") return part;
|
|
88
|
+
if (!isRecord(part)) return part == null ? "" : String(part);
|
|
89
|
+
const media = describeContentPart(part);
|
|
90
|
+
if (media) return media;
|
|
91
|
+
if (typeof part.text === "string") return part.text;
|
|
92
|
+
if (typeof part.content === "string") return part.content;
|
|
93
|
+
if (fallback) return fallback(part);
|
|
94
|
+
try {
|
|
95
|
+
return JSON.stringify(part);
|
|
96
|
+
} catch {
|
|
97
|
+
return String(part);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function contentToString(content) {
|
|
101
|
+
try {
|
|
102
|
+
if (content == null) return "";
|
|
103
|
+
if (typeof content === "string") return content;
|
|
104
|
+
if (Array.isArray(content)) {
|
|
105
|
+
return content.map((p) => {
|
|
106
|
+
if (!p || typeof p !== "object") return String(p);
|
|
107
|
+
if (p.type === "text") return String(p.text ?? "");
|
|
108
|
+
if (p.type === "image_url") {
|
|
109
|
+
const img = p.image_url;
|
|
110
|
+
const url = typeof img === "string" ? img : img?.url;
|
|
111
|
+
if (typeof url === "string" && /^https?:\/\//i.test(url)) {
|
|
112
|
+
const detail = typeof img === "string" ? void 0 : img?.detail;
|
|
113
|
+
return `[image:${url}${detail ? ` detail=${detail}` : ""}]`;
|
|
114
|
+
}
|
|
115
|
+
return describeContentPart(p) ?? "[image]";
|
|
116
|
+
}
|
|
117
|
+
const media = describeContentPart(p);
|
|
118
|
+
if (media) return media;
|
|
119
|
+
return JSON.stringify(p);
|
|
120
|
+
}).join("\n");
|
|
121
|
+
}
|
|
122
|
+
return describeContentPart(content) ?? JSON.stringify(content);
|
|
123
|
+
} catch {
|
|
124
|
+
return String(content);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function mergeContentsToString(contents) {
|
|
128
|
+
return contents.map((c) => contentToString(c)).join("\n");
|
|
129
|
+
}
|
|
130
|
+
function safeStringify(value, pretty = false) {
|
|
131
|
+
if (value == null) return "";
|
|
132
|
+
if (typeof value === "string") return value;
|
|
133
|
+
try {
|
|
134
|
+
return JSON.stringify(value, null, pretty ? 2 : void 0) ?? String(value);
|
|
135
|
+
} catch {
|
|
136
|
+
return String(value);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function extractMessageText(message) {
|
|
140
|
+
if (!message) return "";
|
|
141
|
+
const content = message.content;
|
|
142
|
+
if (typeof content === "string") return content;
|
|
143
|
+
if (Array.isArray(content)) {
|
|
144
|
+
return content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? "").join("");
|
|
145
|
+
}
|
|
146
|
+
return "";
|
|
147
|
+
}
|
|
148
|
+
function textFromContent(content) {
|
|
149
|
+
if (typeof content === "string") return content;
|
|
150
|
+
if (!Array.isArray(content)) return "";
|
|
151
|
+
return content.filter((part) => isTextPart(part)).map((part) => part.text ?? "").join("\n");
|
|
152
|
+
}
|
|
153
|
+
function isTextPart(part) {
|
|
154
|
+
return !!part && typeof part === "object" && part.type === "text";
|
|
155
|
+
}
|
|
156
|
+
function mapTextParts(content, fn) {
|
|
157
|
+
if (typeof content === "string") return fn(content);
|
|
158
|
+
if (!Array.isArray(content)) return content;
|
|
159
|
+
return content.map((part) => isTextPart(part) ? { ...part, text: fn(part.text) } : part);
|
|
160
|
+
}
|
|
161
|
+
function replaceTextContent(content, text) {
|
|
162
|
+
if (typeof content === "string" || content == null) return text;
|
|
163
|
+
if (!Array.isArray(content)) return text;
|
|
164
|
+
const textIndexes = content.reduce((acc, part, index) => {
|
|
165
|
+
if (isTextPart(part)) acc.push(index);
|
|
166
|
+
return acc;
|
|
167
|
+
}, []);
|
|
168
|
+
if (textIndexes.length === 0) {
|
|
169
|
+
return text.length > 0 ? [{ type: "text", text }, ...content] : content;
|
|
170
|
+
}
|
|
171
|
+
const [first, ...rest] = textIndexes;
|
|
172
|
+
const dropped = new Set(rest);
|
|
173
|
+
return content.map((part, index) => index === first ? { ...part, text } : part).filter((_part, index) => !dropped.has(index));
|
|
174
|
+
}
|
|
175
|
+
function normalizeSource(source) {
|
|
176
|
+
if (!source || typeof source !== "object") return {};
|
|
177
|
+
const src = source;
|
|
178
|
+
if (src.type === "base64" && typeof src.data === "string") {
|
|
179
|
+
return {
|
|
180
|
+
sourceType: "base64",
|
|
181
|
+
mediaType: typeof src.mediaType === "string" ? src.mediaType : void 0,
|
|
182
|
+
// base64 encodes 3 bytes per 4 characters; padding makes this an upper bound.
|
|
183
|
+
approxBytes: Math.floor(src.data.length * 3 / 4)
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
if (src.type === "url" && typeof src.url === "string") {
|
|
187
|
+
return {
|
|
188
|
+
sourceType: "url",
|
|
189
|
+
url: src.url,
|
|
190
|
+
mediaType: typeof src.mediaType === "string" ? src.mediaType : void 0
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return {};
|
|
194
|
+
}
|
|
195
|
+
function collectAttachments(content) {
|
|
196
|
+
if (!Array.isArray(content)) return [];
|
|
197
|
+
const attachments = [];
|
|
198
|
+
content.forEach((part, index) => {
|
|
199
|
+
if (!part || typeof part !== "object") return;
|
|
200
|
+
const type = part.type;
|
|
201
|
+
if (!type || type === "text") return;
|
|
202
|
+
if (type === "image" || type === "audio" || type === "video" || type === "file") {
|
|
203
|
+
attachments.push({
|
|
204
|
+
index,
|
|
205
|
+
kind: type,
|
|
206
|
+
fileName: typeof part.fileName === "string" ? part.fileName : void 0,
|
|
207
|
+
...normalizeSource(part.source)
|
|
208
|
+
});
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (type === "image_url") {
|
|
212
|
+
const image = part.image_url;
|
|
213
|
+
const url = typeof image === "string" ? image : image?.url;
|
|
214
|
+
if (typeof url === "string" && url.startsWith("data:")) {
|
|
215
|
+
const comma = url.indexOf(",");
|
|
216
|
+
const header = url.slice(5, comma);
|
|
217
|
+
attachments.push({
|
|
218
|
+
index,
|
|
219
|
+
kind: "image",
|
|
220
|
+
sourceType: "base64",
|
|
221
|
+
mediaType: header.split(";")[0] || void 0,
|
|
222
|
+
approxBytes: Math.floor((url.length - comma - 1) * 3 / 4)
|
|
223
|
+
});
|
|
224
|
+
} else {
|
|
225
|
+
attachments.push({ index, kind: "image", sourceType: "url", url });
|
|
226
|
+
}
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
attachments.push({ index, kind: "unknown" });
|
|
230
|
+
});
|
|
231
|
+
return attachments;
|
|
232
|
+
}
|
|
233
|
+
var MEDIA_PART_KINDS, PLACEHOLDER_LABEL_MAX;
|
|
234
|
+
var init_content = __esm({
|
|
235
|
+
"src/utils/content.ts"() {
|
|
236
|
+
MEDIA_PART_KINDS = {
|
|
237
|
+
image: "image",
|
|
238
|
+
image_url: "image",
|
|
239
|
+
input_image: "image",
|
|
240
|
+
image_file: "image",
|
|
241
|
+
audio: "audio",
|
|
242
|
+
input_audio: "audio",
|
|
243
|
+
video: "video",
|
|
244
|
+
video_url: "video",
|
|
245
|
+
file: "file",
|
|
246
|
+
input_file: "file",
|
|
247
|
+
document: "file"
|
|
248
|
+
};
|
|
249
|
+
PLACEHOLDER_LABEL_MAX = 80;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
|
|
21
253
|
// src/utils/utilTokens.ts
|
|
22
254
|
var utilTokens_exports = {};
|
|
23
255
|
__export(utilTokens_exports, {
|
|
@@ -42,7 +274,7 @@ function getTokenCounter() {
|
|
|
42
274
|
function countApproxTokens(text) {
|
|
43
275
|
return activeTokenCounter(text || "");
|
|
44
276
|
}
|
|
45
|
-
function
|
|
277
|
+
function extractMessageText2(m) {
|
|
46
278
|
if (!m) return "";
|
|
47
279
|
const parts = [];
|
|
48
280
|
parts.push(m.role || "");
|
|
@@ -52,6 +284,7 @@ function extractMessageText(m) {
|
|
|
52
284
|
} else if (Array.isArray(m.content)) {
|
|
53
285
|
for (const c of m.content) {
|
|
54
286
|
if (typeof c === "string") parts.push(c);
|
|
287
|
+
else if (describeContentPart(c)) parts.push(describeContentPart(c));
|
|
55
288
|
else if (c?.text) parts.push(c.text);
|
|
56
289
|
else if (c?.content) parts.push(c.content);
|
|
57
290
|
else if (c?.type === "tool_use" && c?.input) {
|
|
@@ -62,7 +295,7 @@ function extractMessageText(m) {
|
|
|
62
295
|
}
|
|
63
296
|
}
|
|
64
297
|
} else if (m.content != null && typeof m.content === "object") {
|
|
65
|
-
parts.push(JSON.stringify(m.content));
|
|
298
|
+
parts.push(describeContentPart(m.content) ?? JSON.stringify(m.content));
|
|
66
299
|
}
|
|
67
300
|
if (Array.isArray(m.tool_calls)) {
|
|
68
301
|
for (const tc of m.tool_calls) {
|
|
@@ -92,12 +325,13 @@ function extractMessageText(m) {
|
|
|
92
325
|
}
|
|
93
326
|
function countMessagesTokens(messages) {
|
|
94
327
|
if (!Array.isArray(messages) || messages.length === 0) return 0;
|
|
95
|
-
const allText = messages.map(
|
|
328
|
+
const allText = messages.map(extractMessageText2).join("\n");
|
|
96
329
|
return countApproxTokens(allText) + messages.length * 4;
|
|
97
330
|
}
|
|
98
331
|
var activeTokenCounter;
|
|
99
332
|
var init_utilTokens = __esm({
|
|
100
333
|
"src/utils/utilTokens.ts"() {
|
|
334
|
+
init_content();
|
|
101
335
|
activeTokenCounter = defaultTokenCounter;
|
|
102
336
|
}
|
|
103
337
|
});
|
|
@@ -558,6 +792,125 @@ function isOpenAIHostedEndpoint(lcModel) {
|
|
|
558
792
|
}
|
|
559
793
|
}
|
|
560
794
|
|
|
795
|
+
// src/utils/abort.ts
|
|
796
|
+
var POLL_INTERVAL_MS = 100;
|
|
797
|
+
var NOOP = () => void 0;
|
|
798
|
+
function isObject(value) {
|
|
799
|
+
return value !== null && typeof value === "object";
|
|
800
|
+
}
|
|
801
|
+
function isRealSignal(value) {
|
|
802
|
+
return typeof AbortSignal !== "undefined" && value instanceof AbortSignal;
|
|
803
|
+
}
|
|
804
|
+
function isCancellationRequested(source) {
|
|
805
|
+
if (!source) return false;
|
|
806
|
+
for (const candidate of [source.signal, source.cancellationToken]) {
|
|
807
|
+
if (!isObject(candidate)) continue;
|
|
808
|
+
if (candidate.aborted === true || candidate.isCancellationRequested === true) return true;
|
|
809
|
+
}
|
|
810
|
+
return false;
|
|
811
|
+
}
|
|
812
|
+
function linkAbortSignal(source) {
|
|
813
|
+
if (!source) return { signal: void 0, dispose: NOOP };
|
|
814
|
+
const candidates = [];
|
|
815
|
+
for (const candidate of [source.signal, source.cancellationToken]) {
|
|
816
|
+
if (isObject(candidate) && !candidates.includes(candidate)) candidates.push(candidate);
|
|
817
|
+
}
|
|
818
|
+
if (candidates.length === 0) return { signal: void 0, dispose: NOOP };
|
|
819
|
+
const real = candidates.filter(isRealSignal);
|
|
820
|
+
if (candidates.length === 1 && real.length === 1) {
|
|
821
|
+
return { signal: real[0], dispose: NOOP };
|
|
822
|
+
}
|
|
823
|
+
const controller = new AbortController();
|
|
824
|
+
const cleanups = [];
|
|
825
|
+
let polled = [];
|
|
826
|
+
let timer;
|
|
827
|
+
const fire = (reason) => {
|
|
828
|
+
if (controller.signal.aborted) return;
|
|
829
|
+
try {
|
|
830
|
+
controller.abort(reason);
|
|
831
|
+
} catch {
|
|
832
|
+
controller.abort();
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
const dispose = () => {
|
|
836
|
+
if (timer !== void 0) {
|
|
837
|
+
clearInterval(timer);
|
|
838
|
+
timer = void 0;
|
|
839
|
+
}
|
|
840
|
+
polled = [];
|
|
841
|
+
for (const cleanup of cleanups.splice(0)) {
|
|
842
|
+
try {
|
|
843
|
+
cleanup();
|
|
844
|
+
} catch {
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
};
|
|
848
|
+
for (const candidate of candidates) {
|
|
849
|
+
if (candidate.aborted === true || candidate.isCancellationRequested === true) {
|
|
850
|
+
fire(isRealSignal(candidate) ? candidate.reason : void 0);
|
|
851
|
+
return { signal: controller.signal, dispose };
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
for (const candidate of candidates) {
|
|
855
|
+
if (typeof candidate.addEventListener === "function") {
|
|
856
|
+
const onAbort = () => fire(isRealSignal(candidate) ? candidate.reason : void 0);
|
|
857
|
+
candidate.addEventListener("abort", onAbort, { once: true });
|
|
858
|
+
cleanups.push(() => candidate.removeEventListener?.("abort", onAbort));
|
|
859
|
+
continue;
|
|
860
|
+
}
|
|
861
|
+
if (typeof candidate.onCancellationRequested === "function") {
|
|
862
|
+
let handle;
|
|
863
|
+
try {
|
|
864
|
+
handle = candidate.onCancellationRequested(() => fire());
|
|
865
|
+
} catch {
|
|
866
|
+
handle = void 0;
|
|
867
|
+
}
|
|
868
|
+
if (isObject(handle) && typeof handle.dispose === "function") {
|
|
869
|
+
cleanups.push(() => handle.dispose());
|
|
870
|
+
}
|
|
871
|
+
polled.push(candidate);
|
|
872
|
+
continue;
|
|
873
|
+
}
|
|
874
|
+
if ("isCancellationRequested" in candidate || "aborted" in candidate) {
|
|
875
|
+
polled.push(candidate);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
if (polled.length > 0) {
|
|
879
|
+
timer = setInterval(() => {
|
|
880
|
+
for (const candidate of polled) {
|
|
881
|
+
if (candidate.aborted === true || candidate.isCancellationRequested === true) {
|
|
882
|
+
fire();
|
|
883
|
+
dispose();
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}, POLL_INTERVAL_MS);
|
|
888
|
+
timer.unref?.();
|
|
889
|
+
}
|
|
890
|
+
return { signal: controller.signal, dispose };
|
|
891
|
+
}
|
|
892
|
+
function abortableSleep(ms, signal) {
|
|
893
|
+
if (!signal) return new Promise((resolve) => setTimeout(resolve, ms));
|
|
894
|
+
if (signal.aborted) return Promise.reject(abortReason(signal));
|
|
895
|
+
return new Promise((resolve, reject) => {
|
|
896
|
+
const onAbort = () => {
|
|
897
|
+
clearTimeout(timer);
|
|
898
|
+
reject(abortReason(signal));
|
|
899
|
+
};
|
|
900
|
+
const timer = setTimeout(() => {
|
|
901
|
+
signal.removeEventListener("abort", onAbort);
|
|
902
|
+
resolve();
|
|
903
|
+
}, ms);
|
|
904
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
function abortReason(signal) {
|
|
908
|
+
if (signal.reason !== void 0) return signal.reason;
|
|
909
|
+
const error = new Error("This operation was aborted");
|
|
910
|
+
error.name = "AbortError";
|
|
911
|
+
return error;
|
|
912
|
+
}
|
|
913
|
+
|
|
561
914
|
// src/model.ts
|
|
562
915
|
function isSmartModel(m) {
|
|
563
916
|
return !!m && typeof m === "object" && typeof m.invoke === "function";
|
|
@@ -566,6 +919,10 @@ function withTools(model, tools, options) {
|
|
|
566
919
|
if (model?.bindTools) return model.bindTools(tools, options);
|
|
567
920
|
return model;
|
|
568
921
|
}
|
|
922
|
+
function withLinkedSignal(options, signal) {
|
|
923
|
+
if (!signal || options?.signal === signal) return options;
|
|
924
|
+
return { ...options || {}, signal };
|
|
925
|
+
}
|
|
569
926
|
function fromLangchainModel(lcModel) {
|
|
570
927
|
if (!lcModel) throw new Error("fromLangchainModel: model is undefined/null");
|
|
571
928
|
const normalizeContent = (content) => {
|
|
@@ -601,7 +958,13 @@ function fromLangchainModel(lcModel) {
|
|
|
601
958
|
const adapted = {
|
|
602
959
|
invoke: async (messages, options) => {
|
|
603
960
|
const lcMessages = messages.map(toLC);
|
|
604
|
-
const
|
|
961
|
+
const link = linkAbortSignal(options);
|
|
962
|
+
let response;
|
|
963
|
+
try {
|
|
964
|
+
response = await lcModel.invoke(lcMessages, withLinkedSignal(options, link.signal));
|
|
965
|
+
} finally {
|
|
966
|
+
link.dispose();
|
|
967
|
+
}
|
|
605
968
|
if (response && typeof response === "object") {
|
|
606
969
|
const content = response.content ?? response.text ?? "";
|
|
607
970
|
return {
|
|
@@ -619,10 +982,15 @@ function fromLangchainModel(lcModel) {
|
|
|
619
982
|
stream: async function* (messages, options) {
|
|
620
983
|
if (typeof lcModel.stream !== "function") return;
|
|
621
984
|
const lcMessages = messages.map(toLC);
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
985
|
+
const link = linkAbortSignal(options);
|
|
986
|
+
try {
|
|
987
|
+
const streamResult = lcModel.stream(lcMessages, withLinkedSignal(options, link.signal));
|
|
988
|
+
const stream = typeof streamResult?.then === "function" ? await streamResult : streamResult;
|
|
989
|
+
for await (const chunk of stream) {
|
|
990
|
+
yield chunk;
|
|
991
|
+
}
|
|
992
|
+
} finally {
|
|
993
|
+
link.dispose();
|
|
626
994
|
}
|
|
627
995
|
},
|
|
628
996
|
bindTools: (tools, options) => {
|
|
@@ -801,6 +1169,9 @@ function safe(v) {
|
|
|
801
1169
|
const n = Number(v);
|
|
802
1170
|
return Number.isFinite(n) && n >= 0 ? n : 0;
|
|
803
1171
|
}
|
|
1172
|
+
|
|
1173
|
+
// src/utils/tracing.ts
|
|
1174
|
+
init_content();
|
|
804
1175
|
var DEFAULT_COGNIPEER_URL = "https://console.cognipeer.com/api/client/v1/tracing/sessions";
|
|
805
1176
|
function fileSink(path2) {
|
|
806
1177
|
return { type: "file", path: path2 };
|
|
@@ -1545,6 +1916,12 @@ function buildMessageLabel(role, index) {
|
|
|
1545
1916
|
const base = `${normalized.charAt(0).toUpperCase()}${normalized.slice(1)} Message`;
|
|
1546
1917
|
return index > 1 ? `${base} #${index}` : base;
|
|
1547
1918
|
}
|
|
1919
|
+
function structuredMessageParts(content) {
|
|
1920
|
+
if (!hasMediaPart(content)) return void 0;
|
|
1921
|
+
const cloned = sanitizeTracePayload(content);
|
|
1922
|
+
if (!Array.isArray(cloned)) return void 0;
|
|
1923
|
+
return cloned.map((part) => typeof part === "string" ? { type: "text", text: part } : part);
|
|
1924
|
+
}
|
|
1548
1925
|
function toDisplayString(value) {
|
|
1549
1926
|
const sanitized = sanitizeTracePayload(value);
|
|
1550
1927
|
if (sanitized == null) return "";
|
|
@@ -1553,7 +1930,9 @@ function toDisplayString(value) {
|
|
|
1553
1930
|
return sanitized.map((item) => toDisplayString(item)).filter((part) => part && part.trim().length > 0).join("\n");
|
|
1554
1931
|
}
|
|
1555
1932
|
if (typeof sanitized === "object") {
|
|
1556
|
-
|
|
1933
|
+
const media = describeContentPart(sanitized);
|
|
1934
|
+
if (media) return media;
|
|
1935
|
+
if (typeof sanitized.text === "string" && (Object.keys(sanitized).length === 1 || sanitized.type === "text")) {
|
|
1557
1936
|
return sanitized.text;
|
|
1558
1937
|
}
|
|
1559
1938
|
if (typeof sanitized.content === "string") {
|
|
@@ -1625,11 +2004,13 @@ function convertMessageListToSections(messageList) {
|
|
|
1625
2004
|
if (!content || !content.trim().length) continue;
|
|
1626
2005
|
}
|
|
1627
2006
|
}
|
|
2007
|
+
const parts = structuredMessageParts(message?.content);
|
|
1628
2008
|
sections.push({
|
|
1629
2009
|
kind: "message",
|
|
1630
2010
|
label: buildMessageLabel(role, next),
|
|
1631
2011
|
role,
|
|
1632
2012
|
content,
|
|
2013
|
+
...parts ? { parts } : {},
|
|
1633
2014
|
metadata: typeof message?.name === "string" ? { name: message.name } : void 0
|
|
1634
2015
|
});
|
|
1635
2016
|
}
|
|
@@ -2050,6 +2431,15 @@ function estimatePayloadBytes(value) {
|
|
|
2050
2431
|
}
|
|
2051
2432
|
}
|
|
2052
2433
|
}
|
|
2434
|
+
function toMessageUsage(u) {
|
|
2435
|
+
return {
|
|
2436
|
+
prompt_tokens: u.inputTokens,
|
|
2437
|
+
completion_tokens: u.outputTokens,
|
|
2438
|
+
total_tokens: u.totalTokens,
|
|
2439
|
+
prompt_tokens_details: { cached_tokens: u.cachedInputTokens, cache_write_tokens: u.cachedWriteTokens },
|
|
2440
|
+
completion_tokens_details: { reasoning_tokens: u.reasoningTokens }
|
|
2441
|
+
};
|
|
2442
|
+
}
|
|
2053
2443
|
function fromNativeProvider(provider, options) {
|
|
2054
2444
|
let boundTools = options?.__tools;
|
|
2055
2445
|
const modelName = options?.model ?? provider.defaultModel ?? provider.providerName;
|
|
@@ -2057,50 +2447,87 @@ function fromNativeProvider(provider, options) {
|
|
|
2057
2447
|
modelName,
|
|
2058
2448
|
capabilities: resolveCapabilities(provider.providerName),
|
|
2059
2449
|
invoke: async (messages, _invokeOptions) => {
|
|
2060
|
-
const
|
|
2061
|
-
|
|
2062
|
-
|
|
2450
|
+
const link = linkAbortSignal(_invokeOptions);
|
|
2451
|
+
try {
|
|
2452
|
+
let request = buildRequest(messages, boundTools, options, _invokeOptions);
|
|
2453
|
+
if (link.signal) request.signal = link.signal;
|
|
2454
|
+
request = await applyTransform(request);
|
|
2455
|
+
const response = await provider.complete(request);
|
|
2456
|
+
return toBaseChatMessage(response);
|
|
2457
|
+
} finally {
|
|
2458
|
+
link.dispose();
|
|
2459
|
+
}
|
|
2063
2460
|
},
|
|
2064
2461
|
stream: async function* (messages, _invokeOptions) {
|
|
2065
|
-
const
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2462
|
+
const link = linkAbortSignal(_invokeOptions);
|
|
2463
|
+
try {
|
|
2464
|
+
let request = buildRequest(messages, boundTools, options, _invokeOptions);
|
|
2465
|
+
request.stream = true;
|
|
2466
|
+
if (link.signal) request.signal = link.signal;
|
|
2467
|
+
request = await applyTransform(request);
|
|
2468
|
+
let fullContent = "";
|
|
2469
|
+
let allToolCalls = [];
|
|
2470
|
+
let lastUsage;
|
|
2471
|
+
let reasoningBlocks;
|
|
2472
|
+
let reasoningText = "";
|
|
2473
|
+
let finishReason;
|
|
2474
|
+
let responseModel;
|
|
2475
|
+
const toolCallBuffers = /* @__PURE__ */ new Map();
|
|
2476
|
+
for await (const chunk of provider.completeStream(request)) {
|
|
2477
|
+
if (chunk.delta.content) {
|
|
2478
|
+
fullContent += chunk.delta.content;
|
|
2479
|
+
yield chunk.delta.content;
|
|
2480
|
+
}
|
|
2481
|
+
if (chunk.model) responseModel = chunk.model;
|
|
2482
|
+
if (chunk.finishReason) finishReason = chunk.finishReason;
|
|
2483
|
+
if (chunk.delta.reasoning?.blocks?.length) {
|
|
2484
|
+
reasoningBlocks = chunk.delta.reasoning.blocks;
|
|
2485
|
+
}
|
|
2486
|
+
const reasoningDelta = chunk.delta.reasoning?.summary;
|
|
2487
|
+
if (reasoningDelta) {
|
|
2488
|
+
reasoningText += reasoningDelta;
|
|
2489
|
+
yield { type: "reasoning", reasoning_content: reasoningDelta };
|
|
2490
|
+
}
|
|
2491
|
+
if (chunk.delta.toolCalls) {
|
|
2492
|
+
for (const tc of chunk.delta.toolCalls) {
|
|
2493
|
+
if (tc.id) {
|
|
2494
|
+
const existing = toolCallBuffers.get(tc.id);
|
|
2495
|
+
if (existing) {
|
|
2496
|
+
if (tc.arguments) existing.arguments += tc.arguments;
|
|
2497
|
+
if (tc.thoughtSignature) existing.thoughtSignature = tc.thoughtSignature;
|
|
2498
|
+
} else {
|
|
2499
|
+
toolCallBuffers.set(tc.id, {
|
|
2500
|
+
id: tc.id,
|
|
2501
|
+
name: tc.name ?? "",
|
|
2502
|
+
arguments: tc.arguments ?? "",
|
|
2503
|
+
...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
|
|
2504
|
+
});
|
|
2505
|
+
}
|
|
2092
2506
|
}
|
|
2093
2507
|
}
|
|
2094
2508
|
}
|
|
2509
|
+
if (chunk.usage) lastUsage = chunk.usage;
|
|
2095
2510
|
}
|
|
2096
|
-
if (
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2511
|
+
if (link.signal?.aborted) return;
|
|
2512
|
+
allToolCalls = [...toolCallBuffers.values()];
|
|
2513
|
+
const finalMessage = assembleMessage(fullContent, allToolCalls, lastUsage);
|
|
2514
|
+
if (reasoningBlocks?.length || reasoningText) {
|
|
2515
|
+
finalMessage.reasoning = {
|
|
2516
|
+
...reasoningBlocks?.length ? { blocks: reasoningBlocks } : {},
|
|
2517
|
+
...reasoningText ? { summary: reasoningText } : {}
|
|
2518
|
+
};
|
|
2519
|
+
}
|
|
2520
|
+
if (finishReason || responseModel) {
|
|
2521
|
+
finalMessage.response_metadata = {
|
|
2522
|
+
...finalMessage.response_metadata ?? {},
|
|
2523
|
+
...finishReason ? { finish_reason: finishReason } : {},
|
|
2524
|
+
...responseModel ? { model_name: responseModel } : {}
|
|
2525
|
+
};
|
|
2526
|
+
}
|
|
2527
|
+
yield finalMessage;
|
|
2528
|
+
} finally {
|
|
2529
|
+
link.dispose();
|
|
2102
2530
|
}
|
|
2103
|
-
yield finalMessage;
|
|
2104
2531
|
},
|
|
2105
2532
|
bindTools: (tools, _bindOptions) => {
|
|
2106
2533
|
const strict = _bindOptions?.strict ?? false;
|
|
@@ -2109,6 +2536,11 @@ function fromNativeProvider(provider, options) {
|
|
|
2109
2536
|
}
|
|
2110
2537
|
};
|
|
2111
2538
|
return adapted;
|
|
2539
|
+
async function applyTransform(req) {
|
|
2540
|
+
if (!options?.transformRequest) return req;
|
|
2541
|
+
const out = await options.transformRequest(req);
|
|
2542
|
+
return out ?? req;
|
|
2543
|
+
}
|
|
2112
2544
|
function buildRequest(messages, tools, opts, invokeOptions) {
|
|
2113
2545
|
const req = {
|
|
2114
2546
|
model: opts?.model ?? modelName,
|
|
@@ -2116,6 +2548,10 @@ function fromNativeProvider(provider, options) {
|
|
|
2116
2548
|
};
|
|
2117
2549
|
if (opts?.temperature != null) req.temperature = opts.temperature;
|
|
2118
2550
|
if (opts?.maxTokens != null) req.maxTokens = opts.maxTokens;
|
|
2551
|
+
if (opts?.topP != null) req.topP = opts.topP;
|
|
2552
|
+
if (opts?.stop?.length) req.stop = opts.stop;
|
|
2553
|
+
if (opts?.presencePenalty != null) req.presencePenalty = opts.presencePenalty;
|
|
2554
|
+
if (opts?.frequencyPenalty != null) req.frequencyPenalty = opts.frequencyPenalty;
|
|
2119
2555
|
if (tools?.length) req.tools = tools;
|
|
2120
2556
|
if (opts?.extra) req.extra = opts.extra;
|
|
2121
2557
|
const reasoningOverride = invokeOptions?.reasoning;
|
|
@@ -2168,7 +2604,8 @@ function toUnifiedMessage(msg) {
|
|
|
2168
2604
|
unified.toolCalls = msg.tool_calls.map((tc) => ({
|
|
2169
2605
|
id: tc.id,
|
|
2170
2606
|
name: tc.function?.name ?? tc.name ?? "",
|
|
2171
|
-
arguments: tc.function?.arguments ?? tc.arguments ?? "{}"
|
|
2607
|
+
arguments: tc.function?.arguments ?? tc.arguments ?? "{}",
|
|
2608
|
+
...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
|
|
2172
2609
|
}));
|
|
2173
2610
|
}
|
|
2174
2611
|
const reasoning = msg.reasoning;
|
|
@@ -2442,29 +2879,16 @@ function toToolDefinition(tool, strict) {
|
|
|
2442
2879
|
}
|
|
2443
2880
|
return { name, description, parameters, ...useStrict ? { strict: true } : {} };
|
|
2444
2881
|
}
|
|
2882
|
+
function legacyTokenUsage(u) {
|
|
2883
|
+
return { ...toMessageUsage(u), cached_tokens: u.cachedInputTokens, cache_write_tokens: u.cachedWriteTokens };
|
|
2884
|
+
}
|
|
2445
2885
|
function toBaseChatMessage(response) {
|
|
2446
2886
|
const msg = {
|
|
2447
2887
|
role: "assistant",
|
|
2448
2888
|
content: response.content ?? "",
|
|
2449
|
-
usage:
|
|
2450
|
-
prompt_tokens: response.usage.inputTokens,
|
|
2451
|
-
completion_tokens: response.usage.outputTokens,
|
|
2452
|
-
total_tokens: response.usage.totalTokens,
|
|
2453
|
-
prompt_tokens_details: {
|
|
2454
|
-
cached_tokens: response.usage.cachedInputTokens
|
|
2455
|
-
},
|
|
2456
|
-
completion_tokens_details: {
|
|
2457
|
-
reasoning_tokens: response.usage.reasoningTokens
|
|
2458
|
-
}
|
|
2459
|
-
},
|
|
2889
|
+
usage: toMessageUsage(response.usage),
|
|
2460
2890
|
response_metadata: {
|
|
2461
|
-
token_usage:
|
|
2462
|
-
prompt_tokens: response.usage.inputTokens,
|
|
2463
|
-
completion_tokens: response.usage.outputTokens,
|
|
2464
|
-
total_tokens: response.usage.totalTokens,
|
|
2465
|
-
cached_tokens: response.usage.cachedInputTokens,
|
|
2466
|
-
cache_write_tokens: response.usage.cachedWriteTokens
|
|
2467
|
-
},
|
|
2891
|
+
token_usage: legacyTokenUsage(response.usage),
|
|
2468
2892
|
finish_reason: response.finishReason,
|
|
2469
2893
|
model_name: response.model
|
|
2470
2894
|
}
|
|
@@ -2473,7 +2897,8 @@ function toBaseChatMessage(response) {
|
|
|
2473
2897
|
msg.tool_calls = response.toolCalls.map((tc) => ({
|
|
2474
2898
|
id: tc.id,
|
|
2475
2899
|
type: "function",
|
|
2476
|
-
function: { name: tc.name, arguments: tc.arguments }
|
|
2900
|
+
function: { name: tc.name, arguments: tc.arguments },
|
|
2901
|
+
...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
|
|
2477
2902
|
}));
|
|
2478
2903
|
}
|
|
2479
2904
|
if (response.reasoning && (response.reasoning.blocks?.length || response.reasoning.summary)) {
|
|
@@ -2487,32 +2912,15 @@ function assembleMessage(content, toolCalls, usage) {
|
|
|
2487
2912
|
content
|
|
2488
2913
|
};
|
|
2489
2914
|
if (usage) {
|
|
2490
|
-
msg.usage =
|
|
2491
|
-
|
|
2492
|
-
completion_tokens: usage.outputTokens,
|
|
2493
|
-
total_tokens: usage.totalTokens,
|
|
2494
|
-
prompt_tokens_details: {
|
|
2495
|
-
cached_tokens: usage.cachedInputTokens
|
|
2496
|
-
},
|
|
2497
|
-
completion_tokens_details: {
|
|
2498
|
-
reasoning_tokens: usage.reasoningTokens
|
|
2499
|
-
}
|
|
2500
|
-
};
|
|
2501
|
-
msg.response_metadata = {
|
|
2502
|
-
token_usage: {
|
|
2503
|
-
prompt_tokens: usage.inputTokens,
|
|
2504
|
-
completion_tokens: usage.outputTokens,
|
|
2505
|
-
total_tokens: usage.totalTokens,
|
|
2506
|
-
cached_tokens: usage.cachedInputTokens,
|
|
2507
|
-
cache_write_tokens: usage.cachedWriteTokens
|
|
2508
|
-
}
|
|
2509
|
-
};
|
|
2915
|
+
msg.usage = toMessageUsage(usage);
|
|
2916
|
+
msg.response_metadata = { token_usage: legacyTokenUsage(usage) };
|
|
2510
2917
|
}
|
|
2511
2918
|
if (toolCalls.length > 0) {
|
|
2512
2919
|
msg.tool_calls = toolCalls.map((tc) => ({
|
|
2513
2920
|
id: tc.id,
|
|
2514
2921
|
type: "function",
|
|
2515
|
-
function: { name: tc.name, arguments: tc.arguments }
|
|
2922
|
+
function: { name: tc.name, arguments: tc.arguments },
|
|
2923
|
+
...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
|
|
2516
2924
|
}));
|
|
2517
2925
|
}
|
|
2518
2926
|
return msg;
|
|
@@ -2545,8 +2953,8 @@ function resolveCapabilities(provider) {
|
|
|
2545
2953
|
return {
|
|
2546
2954
|
structuredOutput: "tool_based",
|
|
2547
2955
|
strictToolCalling: false,
|
|
2548
|
-
streaming:
|
|
2549
|
-
//
|
|
2956
|
+
streaming: true,
|
|
2957
|
+
// ConverseStream (AWS event-stream frames)
|
|
2550
2958
|
provider: "bedrock"
|
|
2551
2959
|
};
|
|
2552
2960
|
case "vertex":
|
|
@@ -2563,150 +2971,21 @@ function resolveCapabilities(provider) {
|
|
|
2563
2971
|
|
|
2564
2972
|
// src/smart/toolResponses.ts
|
|
2565
2973
|
init_utilTokens();
|
|
2974
|
+
init_content();
|
|
2566
2975
|
|
|
2567
|
-
// src/
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
return `[image:${url || "unknown"}${detail ? ` detail=${detail}` : ""}]`;
|
|
2581
|
-
}
|
|
2582
|
-
return JSON.stringify(p);
|
|
2583
|
-
}).join("\n");
|
|
2584
|
-
}
|
|
2585
|
-
return JSON.stringify(content);
|
|
2586
|
-
} catch {
|
|
2587
|
-
return String(content);
|
|
2588
|
-
}
|
|
2589
|
-
}
|
|
2590
|
-
function mergeContentsToString(contents) {
|
|
2591
|
-
return contents.map((c) => contentToString(c)).join("\n");
|
|
2592
|
-
}
|
|
2593
|
-
function safeStringify(value, pretty = false) {
|
|
2594
|
-
if (value == null) return "";
|
|
2595
|
-
if (typeof value === "string") return value;
|
|
2596
|
-
try {
|
|
2597
|
-
return JSON.stringify(value, null, pretty ? 2 : void 0) ?? String(value);
|
|
2598
|
-
} catch {
|
|
2599
|
-
return String(value);
|
|
2600
|
-
}
|
|
2601
|
-
}
|
|
2602
|
-
function extractMessageText2(message) {
|
|
2603
|
-
if (!message) return "";
|
|
2604
|
-
const content = message.content;
|
|
2605
|
-
if (typeof content === "string") return content;
|
|
2606
|
-
if (Array.isArray(content)) {
|
|
2607
|
-
return content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? "").join("");
|
|
2608
|
-
}
|
|
2609
|
-
return "";
|
|
2610
|
-
}
|
|
2611
|
-
function textFromContent(content) {
|
|
2612
|
-
if (typeof content === "string") return content;
|
|
2613
|
-
if (!Array.isArray(content)) return "";
|
|
2614
|
-
return content.filter((part) => isTextPart(part)).map((part) => part.text ?? "").join("\n");
|
|
2615
|
-
}
|
|
2616
|
-
function isTextPart(part) {
|
|
2617
|
-
return !!part && typeof part === "object" && part.type === "text";
|
|
2618
|
-
}
|
|
2619
|
-
function mapTextParts(content, fn) {
|
|
2620
|
-
if (typeof content === "string") return fn(content);
|
|
2621
|
-
if (!Array.isArray(content)) return content;
|
|
2622
|
-
return content.map((part) => isTextPart(part) ? { ...part, text: fn(part.text) } : part);
|
|
2623
|
-
}
|
|
2624
|
-
function replaceTextContent(content, text) {
|
|
2625
|
-
if (typeof content === "string" || content == null) return text;
|
|
2626
|
-
if (!Array.isArray(content)) return text;
|
|
2627
|
-
const textIndexes = content.reduce((acc, part, index) => {
|
|
2628
|
-
if (isTextPart(part)) acc.push(index);
|
|
2629
|
-
return acc;
|
|
2630
|
-
}, []);
|
|
2631
|
-
if (textIndexes.length === 0) {
|
|
2632
|
-
return text.length > 0 ? [{ type: "text", text }, ...content] : content;
|
|
2633
|
-
}
|
|
2634
|
-
const [first, ...rest] = textIndexes;
|
|
2635
|
-
const dropped = new Set(rest);
|
|
2636
|
-
return content.map((part, index) => index === first ? { ...part, text } : part).filter((_part, index) => !dropped.has(index));
|
|
2637
|
-
}
|
|
2638
|
-
function normalizeSource(source) {
|
|
2639
|
-
if (!source || typeof source !== "object") return {};
|
|
2640
|
-
const src = source;
|
|
2641
|
-
if (src.type === "base64" && typeof src.data === "string") {
|
|
2642
|
-
return {
|
|
2643
|
-
sourceType: "base64",
|
|
2644
|
-
mediaType: typeof src.mediaType === "string" ? src.mediaType : void 0,
|
|
2645
|
-
// base64 encodes 3 bytes per 4 characters; padding makes this an upper bound.
|
|
2646
|
-
approxBytes: Math.floor(src.data.length * 3 / 4)
|
|
2647
|
-
};
|
|
2648
|
-
}
|
|
2649
|
-
if (src.type === "url" && typeof src.url === "string") {
|
|
2650
|
-
return {
|
|
2651
|
-
sourceType: "url",
|
|
2652
|
-
url: src.url,
|
|
2653
|
-
mediaType: typeof src.mediaType === "string" ? src.mediaType : void 0
|
|
2654
|
-
};
|
|
2655
|
-
}
|
|
2656
|
-
return {};
|
|
2657
|
-
}
|
|
2658
|
-
function collectAttachments(content) {
|
|
2659
|
-
if (!Array.isArray(content)) return [];
|
|
2660
|
-
const attachments = [];
|
|
2661
|
-
content.forEach((part, index) => {
|
|
2662
|
-
if (!part || typeof part !== "object") return;
|
|
2663
|
-
const type = part.type;
|
|
2664
|
-
if (!type || type === "text") return;
|
|
2665
|
-
if (type === "image" || type === "audio" || type === "video" || type === "file") {
|
|
2666
|
-
attachments.push({
|
|
2667
|
-
index,
|
|
2668
|
-
kind: type,
|
|
2669
|
-
fileName: typeof part.fileName === "string" ? part.fileName : void 0,
|
|
2670
|
-
...normalizeSource(part.source)
|
|
2671
|
-
});
|
|
2672
|
-
return;
|
|
2673
|
-
}
|
|
2674
|
-
if (type === "image_url") {
|
|
2675
|
-
const image = part.image_url;
|
|
2676
|
-
const url = typeof image === "string" ? image : image?.url;
|
|
2677
|
-
if (typeof url === "string" && url.startsWith("data:")) {
|
|
2678
|
-
const comma = url.indexOf(",");
|
|
2679
|
-
const header = url.slice(5, comma);
|
|
2680
|
-
attachments.push({
|
|
2681
|
-
index,
|
|
2682
|
-
kind: "image",
|
|
2683
|
-
sourceType: "base64",
|
|
2684
|
-
mediaType: header.split(";")[0] || void 0,
|
|
2685
|
-
approxBytes: Math.floor((url.length - comma - 1) * 3 / 4)
|
|
2686
|
-
});
|
|
2687
|
-
} else {
|
|
2688
|
-
attachments.push({ index, kind: "image", sourceType: "url", url });
|
|
2689
|
-
}
|
|
2690
|
-
return;
|
|
2691
|
-
}
|
|
2692
|
-
attachments.push({ index, kind: "unknown" });
|
|
2693
|
-
});
|
|
2694
|
-
return attachments;
|
|
2695
|
-
}
|
|
2696
|
-
|
|
2697
|
-
// src/smart/toolArgCoercion.ts
|
|
2698
|
-
var PLACEHOLDER_TEXT = /* @__PURE__ */ new Set(["", "null", "undefined", "none", "nil", "n/a", "na"]);
|
|
2699
|
-
var ENVELOPE_KEYS = ["input", "args", "arguments", "params", "parameters", "payload"];
|
|
2700
|
-
function defOf(schema) {
|
|
2701
|
-
const def = schema?._def;
|
|
2702
|
-
return def && typeof def === "object" ? def : null;
|
|
2703
|
-
}
|
|
2704
|
-
function isPlaceholder(value) {
|
|
2705
|
-
return typeof value === "string" && PLACEHOLDER_TEXT.has(value.trim().toLowerCase());
|
|
2706
|
-
}
|
|
2707
|
-
function parseJsonish(value) {
|
|
2708
|
-
const text = value.trim();
|
|
2709
|
-
if (!text.startsWith("{") && !text.startsWith("[")) return { ok: false };
|
|
2976
|
+
// src/smart/toolArgCoercion.ts
|
|
2977
|
+
var PLACEHOLDER_TEXT = /* @__PURE__ */ new Set(["", "null", "undefined", "none", "nil", "n/a", "na"]);
|
|
2978
|
+
var ENVELOPE_KEYS = ["input", "args", "arguments", "params", "parameters", "payload"];
|
|
2979
|
+
function defOf(schema) {
|
|
2980
|
+
const def = schema?._def;
|
|
2981
|
+
return def && typeof def === "object" ? def : null;
|
|
2982
|
+
}
|
|
2983
|
+
function isPlaceholder(value) {
|
|
2984
|
+
return typeof value === "string" && PLACEHOLDER_TEXT.has(value.trim().toLowerCase());
|
|
2985
|
+
}
|
|
2986
|
+
function parseJsonish(value) {
|
|
2987
|
+
const text = value.trim();
|
|
2988
|
+
if (!text.startsWith("{") && !text.startsWith("[")) return { ok: false };
|
|
2710
2989
|
try {
|
|
2711
2990
|
return { ok: true, value: JSON.parse(text) };
|
|
2712
2991
|
} catch {
|
|
@@ -3581,6 +3860,7 @@ function detectVolatileContent(text, limit = 20) {
|
|
|
3581
3860
|
|
|
3582
3861
|
// src/smart/contextPilot/jsonCrusher.ts
|
|
3583
3862
|
init_utilTokens();
|
|
3863
|
+
init_content();
|
|
3584
3864
|
var CONTEXT_PILOT_JSON_MARKER_KEY = "__contextPilotDropped";
|
|
3585
3865
|
function findCompressibleArray(output, minItems) {
|
|
3586
3866
|
if (Array.isArray(output)) {
|
|
@@ -3793,6 +4073,7 @@ function compressSearchOutput(text, config, ccrStore) {
|
|
|
3793
4073
|
|
|
3794
4074
|
// src/smart/contextPilot/pipeline.ts
|
|
3795
4075
|
init_utilTokens();
|
|
4076
|
+
init_content();
|
|
3796
4077
|
function createContextPilotRuntime(config) {
|
|
3797
4078
|
return {
|
|
3798
4079
|
ccrStore: new CCRStore({ ttlMs: config.ccr.ttlMs, maxEntries: config.ccr.maxEntries }),
|
|
@@ -4166,6 +4447,8 @@ function createAgentCoreNode(opts) {
|
|
|
4166
4447
|
const streamingEnabled = Boolean(state.ctx?.__streaming);
|
|
4167
4448
|
const cancellationToken = state.ctx?.__cancellationToken;
|
|
4168
4449
|
const abortSignal = state.ctx?.__abortSignal;
|
|
4450
|
+
const onProgress = state.ctx?.__onProgress;
|
|
4451
|
+
const cancelRequested = () => isCancellationRequested({ signal: abortSignal, cancellationToken });
|
|
4169
4452
|
const resolvedForCachePilot = getResolvedSmartConfig(opts, runtime);
|
|
4170
4453
|
if (resolvedForCachePilot.contextPilot.enabled && resolvedForCachePilot.contextPilot.cacheAlignment.enabled) {
|
|
4171
4454
|
const ctxForCacheWarning = state.ctx = state.ctx || {};
|
|
@@ -4324,6 +4607,29 @@ ${append}`;
|
|
|
4324
4607
|
let response;
|
|
4325
4608
|
let modelAttempt = 0;
|
|
4326
4609
|
const maxModelRetries = host?.maxModelRetries ?? 0;
|
|
4610
|
+
const finishCancelledTurn = (partialText) => {
|
|
4611
|
+
const reason = abortSignal?.aborted ? "aborted" : "cancelled";
|
|
4612
|
+
const ctx = state.ctx = state.ctx || {};
|
|
4613
|
+
ctx.__cancelled = { stage: "agent", reason, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
4614
|
+
recordTraceEvent(traceSession, {
|
|
4615
|
+
type: "ai_call",
|
|
4616
|
+
label: "Assistant Cancelled",
|
|
4617
|
+
actor: { scope: "agent", name: actorName, role: "assistant", version: actorVersion },
|
|
4618
|
+
// "skipped", not "error": the call did not fail, the caller ended it —
|
|
4619
|
+
// and an "error" would flip the whole session to error.
|
|
4620
|
+
status: "skipped",
|
|
4621
|
+
durationMs: Date.now() - start,
|
|
4622
|
+
requestBytes: promptBytes,
|
|
4623
|
+
model: getModelName(runtime.model || opts.model),
|
|
4624
|
+
provider: getProviderName(runtime.model || opts.model),
|
|
4625
|
+
messageList: state.messages,
|
|
4626
|
+
toolDefinitions: traceToolDefinitions
|
|
4627
|
+
});
|
|
4628
|
+
onEvent?.({ type: "cancelled", stage: "agent", reason });
|
|
4629
|
+
onProgress?.({ stage: "agent", message: "Cancelled", detail: { reason } });
|
|
4630
|
+
const partial = partialText.trim().length > 0 ? [{ role: "assistant", content: partialText }] : [];
|
|
4631
|
+
return { messages: [...state.messages, ...partial], usage: state.usage };
|
|
4632
|
+
};
|
|
4327
4633
|
while (true) {
|
|
4328
4634
|
start = Date.now();
|
|
4329
4635
|
if (shortCircuited !== void 0) {
|
|
@@ -4339,19 +4645,25 @@ ${append}`;
|
|
|
4339
4645
|
toolDefinitions: traceToolDefinitions
|
|
4340
4646
|
});
|
|
4341
4647
|
} else {
|
|
4648
|
+
let streamedText = "";
|
|
4342
4649
|
try {
|
|
4343
4650
|
const normalizedMessages = normalizeBedrockToolPairing([...wireMessages]);
|
|
4344
4651
|
debugToolPairing(normalizedMessages);
|
|
4345
4652
|
if (streamingEnabled && typeof modelWithTools.stream === "function") {
|
|
4346
|
-
let streamedText = "";
|
|
4347
4653
|
let streamedMessage;
|
|
4654
|
+
let cutByCancel = false;
|
|
4348
4655
|
for await (const chunk of modelWithTools.stream(normalizedMessages, invokeParams)) {
|
|
4349
|
-
if (
|
|
4656
|
+
if (cancelRequested()) {
|
|
4657
|
+
cutByCancel = true;
|
|
4350
4658
|
break;
|
|
4351
4659
|
}
|
|
4352
4660
|
if (chunk && typeof chunk === "object" && chunk.role) {
|
|
4353
4661
|
streamedMessage = chunk;
|
|
4354
4662
|
}
|
|
4663
|
+
if (chunk && typeof chunk === "object" && chunk.type === "reasoning" && typeof chunk.reasoning_content === "string") {
|
|
4664
|
+
onEvent?.({ type: "reasoning", text: chunk.reasoning_content });
|
|
4665
|
+
continue;
|
|
4666
|
+
}
|
|
4355
4667
|
const text = extractText2(chunk);
|
|
4356
4668
|
const isAssembledMessage = Boolean(chunk && typeof chunk === "object" && chunk.role) && text.length > 0 && text === streamedText;
|
|
4357
4669
|
if (text && !isAssembledMessage) {
|
|
@@ -4360,6 +4672,7 @@ ${append}`;
|
|
|
4360
4672
|
onEvent?.({ type: "stream", text });
|
|
4361
4673
|
}
|
|
4362
4674
|
}
|
|
4675
|
+
if (cutByCancel) return finishCancelledTurn(streamedText);
|
|
4363
4676
|
if (streamedMessage) {
|
|
4364
4677
|
response = { ...streamedMessage };
|
|
4365
4678
|
if (response.content == null || response.content === "") {
|
|
@@ -4372,6 +4685,7 @@ ${append}`;
|
|
|
4372
4685
|
response = await modelWithTools.invoke(normalizedMessages, invokeParams);
|
|
4373
4686
|
}
|
|
4374
4687
|
} catch (err) {
|
|
4688
|
+
if (cancelRequested()) return finishCancelledTurn(streamedText);
|
|
4375
4689
|
const durationMs2 = Date.now() - start;
|
|
4376
4690
|
recordTraceEvent(traceSession, {
|
|
4377
4691
|
type: "ai_call",
|
|
@@ -4469,6 +4783,7 @@ ${append}`;
|
|
|
4469
4783
|
}
|
|
4470
4784
|
|
|
4471
4785
|
// src/utils/traceSections.ts
|
|
4786
|
+
init_content();
|
|
4472
4787
|
function truncate(text, max = 500) {
|
|
4473
4788
|
if (!text) return "";
|
|
4474
4789
|
return text.length > max ? `${text.slice(0, max)}\u2026` : text;
|
|
@@ -6359,6 +6674,9 @@ function isCompactedToolContent(content) {
|
|
|
6359
6674
|
return typeof content === "string" && (content === "SUMMARIZED" || content.startsWith("SUMMARIZED_TOOL_RESPONSE") || content.startsWith("ARCHIVED_TOOL_RESPONSE") || content.startsWith("STRUCTURED_TOOL_RESPONSE") || content.startsWith("DROPPED_TOOL_RESPONSE"));
|
|
6360
6675
|
}
|
|
6361
6676
|
|
|
6677
|
+
// src/agent.ts
|
|
6678
|
+
init_content();
|
|
6679
|
+
|
|
6362
6680
|
// src/structuredOutput/manager.ts
|
|
6363
6681
|
var StructuredOutputManager = class {
|
|
6364
6682
|
constructor(schema, strategy, config) {
|
|
@@ -6591,6 +6909,7 @@ function buildSubagentCatalogBlock(subagents, policy, toolNames) {
|
|
|
6591
6909
|
}
|
|
6592
6910
|
|
|
6593
6911
|
// src/plugins/host.ts
|
|
6912
|
+
init_content();
|
|
6594
6913
|
var DEFAULT_PRIORITY = 100;
|
|
6595
6914
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
6596
6915
|
var HOOK_SPECS = {
|
|
@@ -7127,6 +7446,7 @@ function performanceNow() {
|
|
|
7127
7446
|
}
|
|
7128
7447
|
|
|
7129
7448
|
// src/plugins/session.ts
|
|
7449
|
+
init_content();
|
|
7130
7450
|
async function openPluginSession(runHost, params) {
|
|
7131
7451
|
let messages = params.messages;
|
|
7132
7452
|
const startGate = await runHost.runGate("sessionStart", {
|
|
@@ -7596,6 +7916,7 @@ function createAgent(opts) {
|
|
|
7596
7916
|
onProgress?.({ stage: "agent", message: "Invoking model" });
|
|
7597
7917
|
if (cancelIfRequested("before_agent")) break;
|
|
7598
7918
|
state = publish({ ...state, ...await agentCore(state) });
|
|
7919
|
+
if (state.ctx?.__cancelled) break;
|
|
7599
7920
|
onProgress?.({ stage: "agent", message: "Model response received" });
|
|
7600
7921
|
if (checkpointIfRequested("after_agent")) break;
|
|
7601
7922
|
const postGuardrails = getGuardrailConfig(state);
|
|
@@ -7666,7 +7987,7 @@ function createAgent(opts) {
|
|
|
7666
7987
|
if (toolCalls.length === 0) {
|
|
7667
7988
|
if (soManager && !state.ctx?.__finalizedDueToStructuredOutput && !state.ctx?.__structuredOutputForceFinalize && !state.ctx?.__guardrailBlocked) {
|
|
7668
7989
|
if (soManager.strategy.kind === "native") {
|
|
7669
|
-
const assistantText =
|
|
7990
|
+
const assistantText = extractMessageText(lastMsg);
|
|
7670
7991
|
if (assistantText) {
|
|
7671
7992
|
const parsed = soManager.parseFromContent(assistantText);
|
|
7672
7993
|
if (parsed.success) {
|
|
@@ -7722,7 +8043,7 @@ function createAgent(opts) {
|
|
|
7722
8043
|
if (soManager && !state.ctx?.__finalizedDueToStructuredOutput && !structuredFinalizeBlocked) {
|
|
7723
8044
|
const lastForParse = state.messages[state.messages.length - 1];
|
|
7724
8045
|
if (lastForParse?.role === "assistant") {
|
|
7725
|
-
const assistantText =
|
|
8046
|
+
const assistantText = extractMessageText(lastForParse);
|
|
7726
8047
|
if (assistantText) {
|
|
7727
8048
|
const parsed = soManager.parseFromContent(assistantText);
|
|
7728
8049
|
if (parsed.success) {
|
|
@@ -7984,7 +8305,7 @@ function createAgent(opts) {
|
|
|
7984
8305
|
const isTransientSummarizationExit = !!res.ctx?.__needsSummarization;
|
|
7985
8306
|
const finalAssistantMsg = isTransientSummarizationExit ? void 0 : getLastAssistantMessage(res.messages);
|
|
7986
8307
|
const finalIsSyntheticSummary = !isTransientSummarizationExit && finalAssistantMsg && isSyntheticSummaryMessage(finalAssistantMsg);
|
|
7987
|
-
let content = isTransientSummarizationExit || finalIsSyntheticSummary ? "" :
|
|
8308
|
+
let content = isTransientSummarizationExit || finalIsSyntheticSummary ? "" : extractMessageText(finalAssistantMsg);
|
|
7988
8309
|
const finalAnswerBlocked = Boolean(
|
|
7989
8310
|
isTransientSummarizationExit || res.ctx?.__awaitingApproval || res.ctx?.__awaitingUserQuestion || res.ctx?.__cancelled || res.ctx?.__paused || res.ctx?.__limitBreached
|
|
7990
8311
|
);
|
|
@@ -8243,9 +8564,11 @@ function createAgentNode(opts) {
|
|
|
8243
8564
|
|
|
8244
8565
|
// src/nodes/contextSummarize.ts
|
|
8245
8566
|
init_utilTokens();
|
|
8567
|
+
init_content();
|
|
8246
8568
|
|
|
8247
8569
|
// src/smart/contextPolicy.ts
|
|
8248
8570
|
init_utilTokens();
|
|
8571
|
+
init_content();
|
|
8249
8572
|
function collectRecentTurns(messages, lastTurnsToKeep) {
|
|
8250
8573
|
if (lastTurnsToKeep <= 0) return [];
|
|
8251
8574
|
const systemPrefix = messages.filter((message, index) => index === 0 && message.role === "system");
|
|
@@ -8307,7 +8630,7 @@ function isClampProtected(message, index, firstUserIndex) {
|
|
|
8307
8630
|
function clampToBudget(messages, maxContextTokens) {
|
|
8308
8631
|
let working = [...messages];
|
|
8309
8632
|
while (working.length > 2) {
|
|
8310
|
-
const tokenCount = countApproxTokens(working.map(
|
|
8633
|
+
const tokenCount = countApproxTokens(working.map(extractMessageText).join("\n"));
|
|
8311
8634
|
if (tokenCount <= maxContextTokens) return working;
|
|
8312
8635
|
const firstUserIndex = working.findIndex((message) => message.role === "user");
|
|
8313
8636
|
const firstNonSystem = working.findIndex((message, index) => !isClampProtected(message, index, firstUserIndex));
|
|
@@ -8647,7 +8970,7 @@ function createContextSummarizeNode(opts) {
|
|
|
8647
8970
|
let content = "";
|
|
8648
8971
|
if (typeof m.content === "string") content = m.content;
|
|
8649
8972
|
else if (Array.isArray(m.content)) {
|
|
8650
|
-
content = m.content.map((c) => c
|
|
8973
|
+
content = m.content.map((c) => contentPartToText(c, (part) => JSON.stringify(part))).join(" ");
|
|
8651
8974
|
}
|
|
8652
8975
|
if (m.role === "tool" && isSummarizedToolPlaceholder(content)) {
|
|
8653
8976
|
const historyEntry = findToolHistoryEntry(state, m.tool_call_id, m.name);
|
|
@@ -9492,6 +9815,9 @@ async function writeSummaryFactsToMemory(store, config, summary, sourceTurn) {
|
|
|
9492
9815
|
return store.get(config.memory.scope, { limit: config.context.lastTurnsToKeep + summary.stable_facts.length });
|
|
9493
9816
|
}
|
|
9494
9817
|
|
|
9818
|
+
// src/smart/index.ts
|
|
9819
|
+
init_content();
|
|
9820
|
+
|
|
9495
9821
|
// src/smart/skills/types.ts
|
|
9496
9822
|
var DEFAULT_SKILL_POLICY = {
|
|
9497
9823
|
maxOpenSkills: 4,
|
|
@@ -10506,7 +10832,7 @@ function createSmartAgent(opts) {
|
|
|
10506
10832
|
].join("\n");
|
|
10507
10833
|
function latestUserPrompt(messages) {
|
|
10508
10834
|
const latest = [...messages].reverse().find((message) => message.role === "user");
|
|
10509
|
-
return latest ?
|
|
10835
|
+
return latest ? extractMessageText(latest) : "";
|
|
10510
10836
|
}
|
|
10511
10837
|
async function syncMemory(state) {
|
|
10512
10838
|
const query = latestUserPrompt(state.messages || []);
|
|
@@ -11217,6 +11543,182 @@ async function runSmartAgentEvalHarness(params) {
|
|
|
11217
11543
|
}
|
|
11218
11544
|
return results;
|
|
11219
11545
|
}
|
|
11546
|
+
|
|
11547
|
+
// src/providers/types.ts
|
|
11548
|
+
function emptyUsage() {
|
|
11549
|
+
return {
|
|
11550
|
+
inputTokens: 0,
|
|
11551
|
+
outputTokens: 0,
|
|
11552
|
+
totalTokens: 0,
|
|
11553
|
+
cachedInputTokens: 0,
|
|
11554
|
+
cachedWriteTokens: 0,
|
|
11555
|
+
cachedOutputTokens: 0,
|
|
11556
|
+
reasoningTokens: 0
|
|
11557
|
+
};
|
|
11558
|
+
}
|
|
11559
|
+
var ProviderError = class extends Error {
|
|
11560
|
+
constructor(message, provider, statusCode, responseBody) {
|
|
11561
|
+
super(message);
|
|
11562
|
+
this.provider = provider;
|
|
11563
|
+
this.statusCode = statusCode;
|
|
11564
|
+
this.responseBody = responseBody;
|
|
11565
|
+
this.name = "ProviderError";
|
|
11566
|
+
}
|
|
11567
|
+
};
|
|
11568
|
+
|
|
11569
|
+
// src/providers/base.ts
|
|
11570
|
+
var DEFAULT_RETRY = {
|
|
11571
|
+
maxRetries: 3,
|
|
11572
|
+
baseDelayMs: 500,
|
|
11573
|
+
maxDelayMs: 8e3
|
|
11574
|
+
};
|
|
11575
|
+
var BaseProvider = class {
|
|
11576
|
+
constructor() {
|
|
11577
|
+
this.retryPolicy = DEFAULT_RETRY;
|
|
11578
|
+
}
|
|
11579
|
+
/** Applies the transport options shared by every provider config. */
|
|
11580
|
+
configureTransport(config) {
|
|
11581
|
+
this.fetchImpl = config.fetch;
|
|
11582
|
+
this.timeoutMs = typeof config.timeoutMs === "number" && config.timeoutMs > 0 ? config.timeoutMs : void 0;
|
|
11583
|
+
}
|
|
11584
|
+
/**
|
|
11585
|
+
* The single HTTP entry point for every provider call site. Uses the
|
|
11586
|
+
* configured `fetch` and applies `timeoutMs`: the timer covers the time until
|
|
11587
|
+
* the response HEADERS arrive and is cleared after that, so a long-running
|
|
11588
|
+
* stream is never cut by it (use the request `signal` to cancel a stream).
|
|
11589
|
+
* A timeout surfaces as a `ProviderError` with status 408. The caller's
|
|
11590
|
+
* `signal` still aborts the request as before.
|
|
11591
|
+
*/
|
|
11592
|
+
async httpFetch(url, init = {}) {
|
|
11593
|
+
const doFetch = this.fetchImpl ?? fetch;
|
|
11594
|
+
const timeoutMs = this.timeoutMs;
|
|
11595
|
+
if (!timeoutMs) return doFetch(url, init);
|
|
11596
|
+
const controller = new AbortController();
|
|
11597
|
+
const outer = init.signal ?? void 0;
|
|
11598
|
+
let timedOut = false;
|
|
11599
|
+
const onOuterAbort = () => controller.abort(outer?.reason);
|
|
11600
|
+
if (outer) {
|
|
11601
|
+
if (outer.aborted) controller.abort(outer.reason);
|
|
11602
|
+
else outer.addEventListener("abort", onOuterAbort, { once: true });
|
|
11603
|
+
}
|
|
11604
|
+
const timer = setTimeout(() => {
|
|
11605
|
+
timedOut = true;
|
|
11606
|
+
controller.abort(new Error(`timed out after ${timeoutMs}ms`));
|
|
11607
|
+
}, timeoutMs);
|
|
11608
|
+
try {
|
|
11609
|
+
const res = await doFetch(url, { ...init, signal: controller.signal });
|
|
11610
|
+
return res;
|
|
11611
|
+
} catch (err) {
|
|
11612
|
+
if (timedOut) {
|
|
11613
|
+
throw new ProviderError(`${this.providerName} request timed out after ${timeoutMs}ms`, this.providerName, 408);
|
|
11614
|
+
}
|
|
11615
|
+
throw err;
|
|
11616
|
+
} finally {
|
|
11617
|
+
clearTimeout(timer);
|
|
11618
|
+
}
|
|
11619
|
+
}
|
|
11620
|
+
/**
|
|
11621
|
+
* Embeds `request.input`. Implemented by the providers that have an
|
|
11622
|
+
* embeddings endpoint (OpenAI, Azure, openai-compatible, Bedrock, Vertex);
|
|
11623
|
+
* the others reject with a 400 ProviderError.
|
|
11624
|
+
*/
|
|
11625
|
+
async embed(_request) {
|
|
11626
|
+
throw new ProviderError(`${this.providerName} does not support embeddings`, this.providerName, 400);
|
|
11627
|
+
}
|
|
11628
|
+
/**
|
|
11629
|
+
* Helper concrete providers can wrap their fetch with. Retries 429/5xx
|
|
11630
|
+
* with exponential backoff and respects Retry-After if the response
|
|
11631
|
+
* carries one.
|
|
11632
|
+
*
|
|
11633
|
+
* `signal` is the call's cancellation: a run that is cancelled while the
|
|
11634
|
+
* provider is backing off must not sit out the delay, nor start another attempt.
|
|
11635
|
+
*/
|
|
11636
|
+
async doFetchWithRetry(execute, signal) {
|
|
11637
|
+
const policy = this.retryPolicy;
|
|
11638
|
+
const maxRetries = Math.max(0, policy.maxRetries ?? DEFAULT_RETRY.maxRetries);
|
|
11639
|
+
const baseDelay = Math.max(0, policy.baseDelayMs ?? DEFAULT_RETRY.baseDelayMs);
|
|
11640
|
+
const maxDelay = Math.max(baseDelay, policy.maxDelayMs ?? DEFAULT_RETRY.maxDelayMs);
|
|
11641
|
+
let lastResp;
|
|
11642
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
11643
|
+
if (signal?.aborted) throw abortReason(signal);
|
|
11644
|
+
const res = await execute();
|
|
11645
|
+
const isRetryable = res.status === 429 || res.status >= 500 && res.status < 600;
|
|
11646
|
+
if (!isRetryable) return res;
|
|
11647
|
+
const predicate = policy.shouldRetry;
|
|
11648
|
+
if (predicate && !predicate({ status: res.status }, attempt)) return res;
|
|
11649
|
+
if (attempt === maxRetries) {
|
|
11650
|
+
lastResp = res;
|
|
11651
|
+
break;
|
|
11652
|
+
}
|
|
11653
|
+
const retryAfter = res.headers.get("retry-after");
|
|
11654
|
+
let delay2 = Math.min(maxDelay, baseDelay * Math.pow(2, attempt));
|
|
11655
|
+
if (retryAfter) {
|
|
11656
|
+
const asNumber = Number(retryAfter);
|
|
11657
|
+
if (!Number.isNaN(asNumber)) delay2 = Math.min(maxDelay, Math.max(delay2, asNumber * 1e3));
|
|
11658
|
+
}
|
|
11659
|
+
try {
|
|
11660
|
+
await res.text();
|
|
11661
|
+
} catch {
|
|
11662
|
+
}
|
|
11663
|
+
await abortableSleep(delay2, signal);
|
|
11664
|
+
}
|
|
11665
|
+
return lastResp;
|
|
11666
|
+
}
|
|
11667
|
+
};
|
|
11668
|
+
|
|
11669
|
+
// src/providers/jev.ts
|
|
11670
|
+
var JEV_DEFAULT_BASE_URL = "https://api.typesafe.ai";
|
|
11671
|
+
var JevProvider = class extends BaseProvider {
|
|
11672
|
+
constructor(config) {
|
|
11673
|
+
super();
|
|
11674
|
+
this.providerName = "jev";
|
|
11675
|
+
this.configureTransport(config);
|
|
11676
|
+
this.apiKey = config.apiKey;
|
|
11677
|
+
this.baseURL = (config.baseURL ?? JEV_DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
11678
|
+
this.defaultModel = config.defaultModel;
|
|
11679
|
+
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
11680
|
+
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
11681
|
+
}
|
|
11682
|
+
/** Ask System One questions about `state`. */
|
|
11683
|
+
async systemOne(request, options) {
|
|
11684
|
+
const model = request.model ?? this.defaultModel;
|
|
11685
|
+
const body = {
|
|
11686
|
+
...model ? { model } : {},
|
|
11687
|
+
state: request.state,
|
|
11688
|
+
questions: request.questions
|
|
11689
|
+
};
|
|
11690
|
+
const res = await this.doFetchWithRetry(
|
|
11691
|
+
() => this.httpFetch(`${this.baseURL}/v1/systemone`, {
|
|
11692
|
+
method: "POST",
|
|
11693
|
+
headers: {
|
|
11694
|
+
"Content-Type": "application/json",
|
|
11695
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
11696
|
+
...this.defaultHeaders
|
|
11697
|
+
},
|
|
11698
|
+
body: JSON.stringify(body),
|
|
11699
|
+
signal: options?.signal
|
|
11700
|
+
})
|
|
11701
|
+
);
|
|
11702
|
+
if (!res.ok) {
|
|
11703
|
+
const text = await res.text().catch(() => "");
|
|
11704
|
+
throw new ProviderError(`Jev API error ${res.status}: ${text}`, this.providerName, res.status, text);
|
|
11705
|
+
}
|
|
11706
|
+
return await res.json();
|
|
11707
|
+
}
|
|
11708
|
+
async complete(_request) {
|
|
11709
|
+
throw new ProviderError(
|
|
11710
|
+
'Jev is a decision model and has no chat completion; use systemOne() or agentVerdictRule({ engine: "jev" })',
|
|
11711
|
+
this.providerName
|
|
11712
|
+
);
|
|
11713
|
+
}
|
|
11714
|
+
// eslint-disable-next-line require-yield
|
|
11715
|
+
async *completeStream(_request) {
|
|
11716
|
+
throw new ProviderError("Jev does not stream; use systemOne()", this.providerName);
|
|
11717
|
+
}
|
|
11718
|
+
};
|
|
11719
|
+
|
|
11720
|
+
// src/guardrails/checks.ts
|
|
11721
|
+
init_content();
|
|
11220
11722
|
var Ajv = AjvModule?.default ?? AjvModule;
|
|
11221
11723
|
var defaultAjv = new Ajv({ allErrors: true });
|
|
11222
11724
|
defaultAjv.opts.strict = false;
|
|
@@ -11366,14 +11868,82 @@ function defaultPayload(context) {
|
|
|
11366
11868
|
2
|
|
11367
11869
|
);
|
|
11368
11870
|
}
|
|
11871
|
+
var DEFAULT_JEV_THRESHOLD = 0.5;
|
|
11872
|
+
var JEV_QUESTION_KEY = "shouldBlock";
|
|
11873
|
+
var DEFAULT_JEV_QUESTION = "Does this conversation payload pose a safety, security, or policy risk that should stop the agent from continuing? Answer yes when the latest message or action should be blocked, and no when it is safe to allow.";
|
|
11874
|
+
var DEFAULT_JEV_CRITERIA = {
|
|
11875
|
+
true: "The payload is unsafe, non-compliant, or otherwise warrants blocking.",
|
|
11876
|
+
false: "The payload is benign and the agent should be allowed to continue."
|
|
11877
|
+
};
|
|
11878
|
+
function resolveJevClient(config) {
|
|
11879
|
+
if (config.client) return config.client;
|
|
11880
|
+
const apiKey = config.apiKey ?? process.env.TYPESAFE_API_KEY;
|
|
11881
|
+
if (!apiKey) {
|
|
11882
|
+
throw new Error(
|
|
11883
|
+
"Jev engine requires an API key: pass `jev.apiKey`, set TYPESAFE_API_KEY, or pass a `jev.client`."
|
|
11884
|
+
);
|
|
11885
|
+
}
|
|
11886
|
+
return new JevProvider({
|
|
11887
|
+
provider: "jev",
|
|
11888
|
+
apiKey,
|
|
11889
|
+
baseURL: config.baseURL ?? process.env.TYPESAFE_BASE_URL
|
|
11890
|
+
});
|
|
11891
|
+
}
|
|
11369
11892
|
function agentVerdictRule(options) {
|
|
11370
11893
|
const payloadBuilder = options.payloadBuilder || defaultPayload;
|
|
11371
11894
|
const fallbackDisposition = options.dispositionFallback || "block";
|
|
11895
|
+
const engine = options.engine || "llm";
|
|
11896
|
+
const jevOptions = options.jev || {};
|
|
11897
|
+
const jevThreshold = typeof jevOptions.threshold === "number" ? jevOptions.threshold : DEFAULT_JEV_THRESHOLD;
|
|
11898
|
+
let jevClient;
|
|
11899
|
+
async function evaluateWithJev(context) {
|
|
11900
|
+
const client = jevClient ?? (jevClient = resolveJevClient(jevOptions));
|
|
11901
|
+
const instructions = jevOptions.question ? jevOptions.question(context) : DEFAULT_JEV_QUESTION;
|
|
11902
|
+
const result = await client.systemOne({
|
|
11903
|
+
state: payloadBuilder(context),
|
|
11904
|
+
questions: {
|
|
11905
|
+
[JEV_QUESTION_KEY]: {
|
|
11906
|
+
type: "noul",
|
|
11907
|
+
instructions,
|
|
11908
|
+
criteria: jevOptions.criteria ?? DEFAULT_JEV_CRITERIA
|
|
11909
|
+
}
|
|
11910
|
+
},
|
|
11911
|
+
...jevOptions.model ? { model: jevOptions.model } : {}
|
|
11912
|
+
});
|
|
11913
|
+
const answer = result?.answers?.[JEV_QUESTION_KEY];
|
|
11914
|
+
const probability = typeof answer?.noul === "number" ? answer.noul : void 0;
|
|
11915
|
+
if (probability === void 0) {
|
|
11916
|
+
return {
|
|
11917
|
+
passed: false,
|
|
11918
|
+
disposition: fallbackDisposition,
|
|
11919
|
+
reason: "Jev engine did not return a noul probability.",
|
|
11920
|
+
details: { jevModel: result?.model, jevUsage: result?.usage }
|
|
11921
|
+
};
|
|
11922
|
+
}
|
|
11923
|
+
const passed = probability < jevThreshold;
|
|
11924
|
+
return {
|
|
11925
|
+
passed,
|
|
11926
|
+
disposition: passed ? "allow" : fallbackDisposition,
|
|
11927
|
+
reason: passed ? void 0 : `Jev risk probability ${probability.toFixed(3)} met or exceeded threshold ${jevThreshold}.`,
|
|
11928
|
+
details: {
|
|
11929
|
+
jevProbability: probability,
|
|
11930
|
+
jevThreshold,
|
|
11931
|
+
jevModel: result?.model,
|
|
11932
|
+
jevUsage: result?.usage
|
|
11933
|
+
}
|
|
11934
|
+
};
|
|
11935
|
+
}
|
|
11372
11936
|
return {
|
|
11373
11937
|
id: options.id,
|
|
11374
11938
|
title: options.title || "Agent-based guardrail",
|
|
11375
11939
|
description: options.description,
|
|
11376
11940
|
async evaluate(context) {
|
|
11941
|
+
if (engine === "jev") {
|
|
11942
|
+
return evaluateWithJev(context);
|
|
11943
|
+
}
|
|
11944
|
+
if (!options.agent) {
|
|
11945
|
+
throw new Error("agentVerdictRule requires an `agent` when using the default 'llm' engine.");
|
|
11946
|
+
}
|
|
11377
11947
|
const payload = payloadBuilder(context);
|
|
11378
11948
|
const systemPrompt = options.systemPrompt || "You are a safety auditor. Review the provided conversation payload and decide whether it should continue. Return JSON with keys allow (boolean), optional disposition ('allow' | 'warn' | 'block'), optional reason (string), and optional details (object).";
|
|
11379
11949
|
const review = await options.agent.invoke({
|
|
@@ -11589,6 +12159,7 @@ function isHookImplemented(hook) {
|
|
|
11589
12159
|
}
|
|
11590
12160
|
|
|
11591
12161
|
// src/plugins/builtin/guardrail.ts
|
|
12162
|
+
init_content();
|
|
11592
12163
|
var ALLOW = { action: "allow" };
|
|
11593
12164
|
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
|
|
11594
12165
|
var RetryableGuardrailError = class extends Error {
|
|
@@ -11875,7 +12446,7 @@ function createGuardrailPlugin(options) {
|
|
|
11875
12446
|
return { decision: "deny", reason: verdict.message ?? "Request blocked by guardrail policy." };
|
|
11876
12447
|
},
|
|
11877
12448
|
postModelCall: async ({ message }, ctx) => {
|
|
11878
|
-
const text =
|
|
12449
|
+
const text = extractMessageText(message);
|
|
11879
12450
|
if (!text) return void 0;
|
|
11880
12451
|
const verdict = await check({ phase: "output", content: text, hook: "postModelCall" }, ctx);
|
|
11881
12452
|
if (!raiseIfFailed(verdict, ctx) || verdict.action === "allow") return void 0;
|
|
@@ -12145,6 +12716,7 @@ function portkeyGuardrail(config = {}) {
|
|
|
12145
12716
|
}
|
|
12146
12717
|
|
|
12147
12718
|
// src/plugins/builtin/piiRedaction.ts
|
|
12719
|
+
init_content();
|
|
12148
12720
|
function isValidTckn(value) {
|
|
12149
12721
|
const digits = value.replace(/\D/g, "");
|
|
12150
12722
|
if (digits.length !== 11 || digits[0] === "0") return false;
|
|
@@ -12264,7 +12836,7 @@ function piiRedaction(config = {}) {
|
|
|
12264
12836
|
},
|
|
12265
12837
|
postModelCall: ({ message }, ctx) => {
|
|
12266
12838
|
if (!applied.has("modelOutput")) return void 0;
|
|
12267
|
-
const text =
|
|
12839
|
+
const text = extractMessageText(message);
|
|
12268
12840
|
if (!text) return void 0;
|
|
12269
12841
|
const result = redactText(text, detectors, mask);
|
|
12270
12842
|
if (result.findings.length === 0) return void 0;
|
|
@@ -13352,12 +13924,12 @@ function responseCache(config = {}) {
|
|
|
13352
13924
|
};
|
|
13353
13925
|
}
|
|
13354
13926
|
function signRequest(req) {
|
|
13355
|
-
const now = /* @__PURE__ */ new Date();
|
|
13927
|
+
const now = req.now ?? /* @__PURE__ */ new Date();
|
|
13356
13928
|
const dateStamp = toDateStamp(now);
|
|
13357
13929
|
const amzDate = toAmzDate(now);
|
|
13358
13930
|
const parsed = new URL(req.url);
|
|
13359
13931
|
const host = parsed.host;
|
|
13360
|
-
const canonicalUri = parsed.pathname || "/";
|
|
13932
|
+
const canonicalUri = (parsed.pathname || "/").split("/").map((seg) => encodeURIComponent(seg).replace(/[!'()*]/g, (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase())).join("/");
|
|
13361
13933
|
const canonicalQuerystring = sortQueryParams(parsed.searchParams);
|
|
13362
13934
|
const headers = {
|
|
13363
13935
|
...req.headers,
|
|
@@ -14671,140 +15243,8 @@ function languageGuard(config) {
|
|
|
14671
15243
|
};
|
|
14672
15244
|
}
|
|
14673
15245
|
|
|
14674
|
-
// src/
|
|
14675
|
-
|
|
14676
|
-
return {
|
|
14677
|
-
inputTokens: 0,
|
|
14678
|
-
outputTokens: 0,
|
|
14679
|
-
totalTokens: 0,
|
|
14680
|
-
cachedInputTokens: 0,
|
|
14681
|
-
cachedWriteTokens: 0,
|
|
14682
|
-
cachedOutputTokens: 0,
|
|
14683
|
-
reasoningTokens: 0
|
|
14684
|
-
};
|
|
14685
|
-
}
|
|
14686
|
-
var ProviderError = class extends Error {
|
|
14687
|
-
constructor(message, provider, statusCode, responseBody) {
|
|
14688
|
-
super(message);
|
|
14689
|
-
this.provider = provider;
|
|
14690
|
-
this.statusCode = statusCode;
|
|
14691
|
-
this.responseBody = responseBody;
|
|
14692
|
-
this.name = "ProviderError";
|
|
14693
|
-
}
|
|
14694
|
-
};
|
|
14695
|
-
|
|
14696
|
-
// src/providers/base.ts
|
|
14697
|
-
var DEFAULT_RETRY = {
|
|
14698
|
-
maxRetries: 3,
|
|
14699
|
-
baseDelayMs: 500,
|
|
14700
|
-
maxDelayMs: 8e3
|
|
14701
|
-
};
|
|
14702
|
-
var BaseProvider = class {
|
|
14703
|
-
constructor() {
|
|
14704
|
-
this.retryPolicy = DEFAULT_RETRY;
|
|
14705
|
-
}
|
|
14706
|
-
/**
|
|
14707
|
-
* Helper concrete providers can wrap their fetch with. Retries 429/5xx
|
|
14708
|
-
* with exponential backoff and respects Retry-After if the response
|
|
14709
|
-
* carries one.
|
|
14710
|
-
*/
|
|
14711
|
-
async doFetchWithRetry(execute) {
|
|
14712
|
-
const policy = this.retryPolicy;
|
|
14713
|
-
const maxRetries = Math.max(0, policy.maxRetries ?? DEFAULT_RETRY.maxRetries);
|
|
14714
|
-
const baseDelay = Math.max(0, policy.baseDelayMs ?? DEFAULT_RETRY.baseDelayMs);
|
|
14715
|
-
const maxDelay = Math.max(baseDelay, policy.maxDelayMs ?? DEFAULT_RETRY.maxDelayMs);
|
|
14716
|
-
let lastResp;
|
|
14717
|
-
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
14718
|
-
const res = await execute();
|
|
14719
|
-
const isRetryable = res.status === 429 || res.status >= 500 && res.status < 600;
|
|
14720
|
-
if (!isRetryable) return res;
|
|
14721
|
-
const predicate = policy.shouldRetry;
|
|
14722
|
-
if (predicate && !predicate({ status: res.status }, attempt)) return res;
|
|
14723
|
-
if (attempt === maxRetries) {
|
|
14724
|
-
lastResp = res;
|
|
14725
|
-
break;
|
|
14726
|
-
}
|
|
14727
|
-
const retryAfter = res.headers.get("retry-after");
|
|
14728
|
-
let delay2 = Math.min(maxDelay, baseDelay * Math.pow(2, attempt));
|
|
14729
|
-
if (retryAfter) {
|
|
14730
|
-
const asNumber = Number(retryAfter);
|
|
14731
|
-
if (!Number.isNaN(asNumber)) delay2 = Math.min(maxDelay, Math.max(delay2, asNumber * 1e3));
|
|
14732
|
-
}
|
|
14733
|
-
try {
|
|
14734
|
-
await res.text();
|
|
14735
|
-
} catch {
|
|
14736
|
-
}
|
|
14737
|
-
await new Promise((r) => setTimeout(r, delay2));
|
|
14738
|
-
}
|
|
14739
|
-
return lastResp;
|
|
14740
|
-
}
|
|
14741
|
-
};
|
|
14742
|
-
|
|
14743
|
-
// src/providers/utils/sse.ts
|
|
14744
|
-
async function* parseSSEStream(body, signal) {
|
|
14745
|
-
const reader = body.getReader();
|
|
14746
|
-
const decoder = new TextDecoder();
|
|
14747
|
-
let buffer = "";
|
|
14748
|
-
try {
|
|
14749
|
-
while (true) {
|
|
14750
|
-
if (signal?.aborted) ;
|
|
14751
|
-
const { done, value } = await reader.read();
|
|
14752
|
-
if (done) break;
|
|
14753
|
-
buffer += decoder.decode(value, { stream: true });
|
|
14754
|
-
const parts = buffer.split(/\r?\n\r?\n/);
|
|
14755
|
-
buffer = parts.pop() ?? "";
|
|
14756
|
-
for (const part of parts) {
|
|
14757
|
-
if (!part.trim()) continue;
|
|
14758
|
-
const event = parseSSEBlock(part);
|
|
14759
|
-
if (event) yield event;
|
|
14760
|
-
}
|
|
14761
|
-
}
|
|
14762
|
-
if (buffer.trim()) {
|
|
14763
|
-
const event = parseSSEBlock(buffer);
|
|
14764
|
-
if (event) yield event;
|
|
14765
|
-
}
|
|
14766
|
-
} finally {
|
|
14767
|
-
reader.releaseLock();
|
|
14768
|
-
}
|
|
14769
|
-
}
|
|
14770
|
-
function parseSSEBlock(block) {
|
|
14771
|
-
let event;
|
|
14772
|
-
let id;
|
|
14773
|
-
let retry;
|
|
14774
|
-
const dataLines = [];
|
|
14775
|
-
for (const line of block.split(/\r?\n/)) {
|
|
14776
|
-
if (line.startsWith(":")) continue;
|
|
14777
|
-
const colonIdx = line.indexOf(":");
|
|
14778
|
-
let field;
|
|
14779
|
-
let value;
|
|
14780
|
-
if (colonIdx === -1) {
|
|
14781
|
-
field = line;
|
|
14782
|
-
value = "";
|
|
14783
|
-
} else {
|
|
14784
|
-
field = line.slice(0, colonIdx);
|
|
14785
|
-
value = line.slice(colonIdx + 1);
|
|
14786
|
-
if (value.startsWith(" ")) value = value.slice(1);
|
|
14787
|
-
}
|
|
14788
|
-
switch (field) {
|
|
14789
|
-
case "event":
|
|
14790
|
-
event = value;
|
|
14791
|
-
break;
|
|
14792
|
-
case "data":
|
|
14793
|
-
dataLines.push(value);
|
|
14794
|
-
break;
|
|
14795
|
-
case "id":
|
|
14796
|
-
id = value;
|
|
14797
|
-
break;
|
|
14798
|
-
case "retry": {
|
|
14799
|
-
const n = parseInt(value, 10);
|
|
14800
|
-
if (!isNaN(n)) retry = n;
|
|
14801
|
-
break;
|
|
14802
|
-
}
|
|
14803
|
-
}
|
|
14804
|
-
}
|
|
14805
|
-
if (dataLines.length === 0) return null;
|
|
14806
|
-
return { event, data: dataLines.join("\n"), id, retry };
|
|
14807
|
-
}
|
|
15246
|
+
// src/index.ts
|
|
15247
|
+
init_content();
|
|
14808
15248
|
|
|
14809
15249
|
// src/providers/utils/reasoning.ts
|
|
14810
15250
|
var ANTHROPIC_EFFORT_BUDGET = {
|
|
@@ -14827,6 +15267,7 @@ var GEMINI_EFFORT_BUDGET = {
|
|
|
14827
15267
|
high: 12e3
|
|
14828
15268
|
};
|
|
14829
15269
|
var THINKING_OUTPUT_RESERVE = 1024;
|
|
15270
|
+
var MIN_THINKING_BUDGET = 1024;
|
|
14830
15271
|
var THINKING_MIN_MAX_TOKENS = 4096;
|
|
14831
15272
|
function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
|
|
14832
15273
|
if (!reasoning) return;
|
|
@@ -14842,8 +15283,48 @@ function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
|
|
|
14842
15283
|
if (reasoning.providerExtras) Object.assign(body, reasoning.providerExtras);
|
|
14843
15284
|
}
|
|
14844
15285
|
}
|
|
14845
|
-
function
|
|
15286
|
+
function supportsAdaptiveThinking(model) {
|
|
15287
|
+
if (typeof model !== "string") return false;
|
|
15288
|
+
const id = model.toLowerCase();
|
|
15289
|
+
const at = id.indexOf("claude-");
|
|
15290
|
+
if (at < 0) return false;
|
|
15291
|
+
for (const tok of id.slice(at + 7).split("-")) {
|
|
15292
|
+
if (tok === "fable") return true;
|
|
15293
|
+
const m = /^(\d+)(?:@|$)/.exec(tok);
|
|
15294
|
+
if (m) {
|
|
15295
|
+
if (m[1].length <= 2) return Number(m[1]) >= 5;
|
|
15296
|
+
return false;
|
|
15297
|
+
}
|
|
15298
|
+
}
|
|
15299
|
+
return false;
|
|
15300
|
+
}
|
|
15301
|
+
function resolveThinkingForm(model, mode) {
|
|
15302
|
+
if (mode === "adaptive" || mode === "budget") return mode;
|
|
15303
|
+
return supportsAdaptiveThinking(model) ? "adaptive" : "budget";
|
|
15304
|
+
}
|
|
15305
|
+
function applyAdaptiveThinking(_body, reasoning, setThinking, setOutputConfig) {
|
|
15306
|
+
const requested = normalizeEffort(reasoning.effort);
|
|
15307
|
+
if (requested === "none") return false;
|
|
15308
|
+
let effort;
|
|
15309
|
+
if (requested) effort = requested === "minimal" ? "low" : requested;
|
|
15310
|
+
else if (typeof reasoning.budgetTokens === "number" && reasoning.budgetTokens > 0) {
|
|
15311
|
+
effort = reasoning.budgetTokens <= ANTHROPIC_EFFORT_BUDGET.low ? "low" : reasoning.budgetTokens <= ANTHROPIC_EFFORT_BUDGET.medium ? "medium" : "high";
|
|
15312
|
+
}
|
|
15313
|
+
if (!effort) return false;
|
|
15314
|
+
const thinking = { type: "adaptive" };
|
|
15315
|
+
if (reasoning.includeThoughts !== false) thinking.display = "summarized";
|
|
15316
|
+
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
15317
|
+
setThinking({ thinking });
|
|
15318
|
+
setOutputConfig({ effort });
|
|
15319
|
+
return true;
|
|
15320
|
+
}
|
|
15321
|
+
function applyAnthropicReasoning(body, reasoning, opts) {
|
|
14846
15322
|
if (!reasoning) return;
|
|
15323
|
+
if (resolveThinkingForm(opts?.model ?? body.model, opts?.mode) === "adaptive") {
|
|
15324
|
+
const on = applyAdaptiveThinking(body, reasoning, (extra) => body.thinking = extra.thinking, (o) => body.output_config = { ...body.output_config ?? {}, ...o });
|
|
15325
|
+
if (on) stripSamplingParams(body, ["temperature", "top_p", "top_k"]);
|
|
15326
|
+
return;
|
|
15327
|
+
}
|
|
14847
15328
|
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
|
|
14848
15329
|
if (!budget) return;
|
|
14849
15330
|
const currentMax = typeof body.max_tokens === "number" ? body.max_tokens : 0;
|
|
@@ -14851,14 +15332,20 @@ function applyAnthropicReasoning(body, reasoning) {
|
|
|
14851
15332
|
if (currentMax < requiredMax) {
|
|
14852
15333
|
body.max_tokens = requiredMax;
|
|
14853
15334
|
}
|
|
14854
|
-
budget = clampBudget(budget, body.max_tokens);
|
|
15335
|
+
budget = Math.max(MIN_THINKING_BUDGET, clampBudget(budget, body.max_tokens));
|
|
14855
15336
|
const thinking = { type: "enabled", budget_tokens: budget };
|
|
14856
15337
|
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
14857
15338
|
body.thinking = thinking;
|
|
14858
15339
|
stripSamplingParams(body, ["temperature", "top_p", "top_k"]);
|
|
14859
15340
|
}
|
|
14860
|
-
function applyBedrockReasoning(body, reasoning) {
|
|
15341
|
+
function applyBedrockReasoning(body, reasoning, opts) {
|
|
14861
15342
|
if (!reasoning) return;
|
|
15343
|
+
if (resolveThinkingForm(opts?.model ?? body.modelId, opts?.mode) === "adaptive") {
|
|
15344
|
+
const fields = () => body.additionalModelRequestFields ?? (body.additionalModelRequestFields = {});
|
|
15345
|
+
const on = applyAdaptiveThinking(body, reasoning, (extra2) => fields().thinking = extra2.thinking, (o) => fields().output_config = { ...fields().output_config ?? {}, ...o });
|
|
15346
|
+
if (on && body.inferenceConfig) stripSamplingParams(body.inferenceConfig, ["temperature", "topP"]);
|
|
15347
|
+
return;
|
|
15348
|
+
}
|
|
14862
15349
|
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
|
|
14863
15350
|
if (!budget) return;
|
|
14864
15351
|
const inference = body.inferenceConfig ?? (body.inferenceConfig = {});
|
|
@@ -14867,7 +15354,7 @@ function applyBedrockReasoning(body, reasoning) {
|
|
|
14867
15354
|
if (currentMax < requiredMax) {
|
|
14868
15355
|
inference.maxTokens = requiredMax;
|
|
14869
15356
|
}
|
|
14870
|
-
budget = clampBudget(budget, inference.maxTokens);
|
|
15357
|
+
budget = Math.max(MIN_THINKING_BUDGET, clampBudget(budget, inference.maxTokens));
|
|
14871
15358
|
const extra = body.additionalModelRequestFields ?? (body.additionalModelRequestFields = {});
|
|
14872
15359
|
const thinking = { type: "enabled", budget_tokens: budget };
|
|
14873
15360
|
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
@@ -14877,8 +15364,9 @@ function applyBedrockReasoning(body, reasoning) {
|
|
|
14877
15364
|
function applyGeminiReasoning(generationConfig, reasoning) {
|
|
14878
15365
|
if (!reasoning) return;
|
|
14879
15366
|
const budget = resolveBudget(reasoning, GEMINI_EFFORT_BUDGET);
|
|
14880
|
-
|
|
14881
|
-
|
|
15367
|
+
const level = typeof reasoning.thinkingLevel === "string" && reasoning.thinkingLevel ? reasoning.thinkingLevel : void 0;
|
|
15368
|
+
if (budget == null && !level) return;
|
|
15369
|
+
const thinkingConfig = level && budget !== 0 ? { thinkingLevel: level } : { thinkingBudget: budget ?? 0 };
|
|
14882
15370
|
if (reasoning.includeThoughts) thinkingConfig.includeThoughts = true;
|
|
14883
15371
|
if (reasoning.providerExtras) Object.assign(thinkingConfig, reasoning.providerExtras);
|
|
14884
15372
|
generationConfig.thinkingConfig = thinkingConfig;
|
|
@@ -14909,6 +15397,73 @@ function resolveBudget(reasoning, effortBudget) {
|
|
|
14909
15397
|
return void 0;
|
|
14910
15398
|
}
|
|
14911
15399
|
|
|
15400
|
+
// src/providers/utils/sse.ts
|
|
15401
|
+
async function* parseSSEStream(body, signal) {
|
|
15402
|
+
const reader = body.getReader();
|
|
15403
|
+
const decoder = new TextDecoder();
|
|
15404
|
+
let buffer = "";
|
|
15405
|
+
try {
|
|
15406
|
+
while (true) {
|
|
15407
|
+
if (signal?.aborted) throw abortReason(signal);
|
|
15408
|
+
const { done, value } = await reader.read();
|
|
15409
|
+
if (done) break;
|
|
15410
|
+
buffer += decoder.decode(value, { stream: true });
|
|
15411
|
+
const parts = buffer.split(/\r?\n\r?\n/);
|
|
15412
|
+
buffer = parts.pop() ?? "";
|
|
15413
|
+
for (const part of parts) {
|
|
15414
|
+
if (!part.trim()) continue;
|
|
15415
|
+
const event = parseSSEBlock(part);
|
|
15416
|
+
if (event) yield event;
|
|
15417
|
+
}
|
|
15418
|
+
}
|
|
15419
|
+
if (buffer.trim()) {
|
|
15420
|
+
const event = parseSSEBlock(buffer);
|
|
15421
|
+
if (event) yield event;
|
|
15422
|
+
}
|
|
15423
|
+
} finally {
|
|
15424
|
+
reader.cancel().catch(() => void 0);
|
|
15425
|
+
reader.releaseLock();
|
|
15426
|
+
}
|
|
15427
|
+
}
|
|
15428
|
+
function parseSSEBlock(block) {
|
|
15429
|
+
let event;
|
|
15430
|
+
let id;
|
|
15431
|
+
let retry;
|
|
15432
|
+
const dataLines = [];
|
|
15433
|
+
for (const line of block.split(/\r?\n/)) {
|
|
15434
|
+
if (line.startsWith(":")) continue;
|
|
15435
|
+
const colonIdx = line.indexOf(":");
|
|
15436
|
+
let field;
|
|
15437
|
+
let value;
|
|
15438
|
+
if (colonIdx === -1) {
|
|
15439
|
+
field = line;
|
|
15440
|
+
value = "";
|
|
15441
|
+
} else {
|
|
15442
|
+
field = line.slice(0, colonIdx);
|
|
15443
|
+
value = line.slice(colonIdx + 1);
|
|
15444
|
+
if (value.startsWith(" ")) value = value.slice(1);
|
|
15445
|
+
}
|
|
15446
|
+
switch (field) {
|
|
15447
|
+
case "event":
|
|
15448
|
+
event = value;
|
|
15449
|
+
break;
|
|
15450
|
+
case "data":
|
|
15451
|
+
dataLines.push(value);
|
|
15452
|
+
break;
|
|
15453
|
+
case "id":
|
|
15454
|
+
id = value;
|
|
15455
|
+
break;
|
|
15456
|
+
case "retry": {
|
|
15457
|
+
const n = parseInt(value, 10);
|
|
15458
|
+
if (!isNaN(n)) retry = n;
|
|
15459
|
+
break;
|
|
15460
|
+
}
|
|
15461
|
+
}
|
|
15462
|
+
}
|
|
15463
|
+
if (dataLines.length === 0) return null;
|
|
15464
|
+
return { event, data: dataLines.join("\n"), id, retry };
|
|
15465
|
+
}
|
|
15466
|
+
|
|
14912
15467
|
// src/providers/utils/media.ts
|
|
14913
15468
|
var EXTENSION_MIME = {
|
|
14914
15469
|
jpg: "image/jpeg",
|
|
@@ -14984,12 +15539,12 @@ function sanitizeBedrockDocName(name, fallback = "document") {
|
|
|
14984
15539
|
// src/providers/utils/jsonSchemaRefs.ts
|
|
14985
15540
|
var DEFINITION_KEYS = ["definitions", "$defs"];
|
|
14986
15541
|
function inlineJsonSchemaRefs(schema) {
|
|
14987
|
-
if (!
|
|
15542
|
+
if (!isObject2(schema) || !containsRef(schema)) return schema;
|
|
14988
15543
|
const root = structuredClone(schema);
|
|
14989
15544
|
const selfReaching = /* @__PURE__ */ new Map();
|
|
14990
15545
|
const targetOf = (ref) => {
|
|
14991
15546
|
const target = resolvePointer(root, ref);
|
|
14992
|
-
return
|
|
15547
|
+
return isObject2(target) ? target : void 0;
|
|
14993
15548
|
};
|
|
14994
15549
|
const reachesItself = (target) => {
|
|
14995
15550
|
const known = selfReaching.get(target);
|
|
@@ -14997,7 +15552,7 @@ function inlineJsonSchemaRefs(schema) {
|
|
|
14997
15552
|
const seen = /* @__PURE__ */ new Set();
|
|
14998
15553
|
const walk = (node) => {
|
|
14999
15554
|
if (Array.isArray(node)) return node.some(walk);
|
|
15000
|
-
if (!
|
|
15555
|
+
if (!isObject2(node)) return false;
|
|
15001
15556
|
if (typeof node.$ref === "string") {
|
|
15002
15557
|
const next = targetOf(node.$ref);
|
|
15003
15558
|
if (next === target) return true;
|
|
@@ -15015,7 +15570,7 @@ function inlineJsonSchemaRefs(schema) {
|
|
|
15015
15570
|
const keptRefs = /* @__PURE__ */ new Set();
|
|
15016
15571
|
const expand = (node) => {
|
|
15017
15572
|
if (Array.isArray(node)) return node.map(expand);
|
|
15018
|
-
if (!
|
|
15573
|
+
if (!isObject2(node)) return node;
|
|
15019
15574
|
if (typeof node.$ref === "string") {
|
|
15020
15575
|
const target = targetOf(node.$ref);
|
|
15021
15576
|
if (target && !reachesItself(target)) {
|
|
@@ -15037,7 +15592,7 @@ function inlineJsonSchemaRefs(schema) {
|
|
|
15037
15592
|
for (const key of DEFINITION_KEYS) delete result[key];
|
|
15038
15593
|
for (const key of DEFINITION_KEYS) {
|
|
15039
15594
|
const block = root[key];
|
|
15040
|
-
if (!
|
|
15595
|
+
if (!isObject2(block)) continue;
|
|
15041
15596
|
const needed = neededEntries(key, block, keptRefs);
|
|
15042
15597
|
if (needed.length === 0) continue;
|
|
15043
15598
|
const kept = {};
|
|
@@ -15065,13 +15620,13 @@ function collectRefs(node, into) {
|
|
|
15065
15620
|
node.forEach((child) => collectRefs(child, into));
|
|
15066
15621
|
return;
|
|
15067
15622
|
}
|
|
15068
|
-
if (!
|
|
15623
|
+
if (!isObject2(node)) return;
|
|
15069
15624
|
if (typeof node.$ref === "string") into.push(node.$ref);
|
|
15070
15625
|
for (const [k, value] of Object.entries(node)) if (k !== "$ref") collectRefs(value, into);
|
|
15071
15626
|
}
|
|
15072
15627
|
function containsRef(node) {
|
|
15073
15628
|
if (Array.isArray(node)) return node.some(containsRef);
|
|
15074
|
-
if (!
|
|
15629
|
+
if (!isObject2(node)) return false;
|
|
15075
15630
|
if (typeof node.$ref === "string") return true;
|
|
15076
15631
|
return Object.values(node).some(containsRef);
|
|
15077
15632
|
}
|
|
@@ -15088,7 +15643,7 @@ function resolvePointer(document, ref) {
|
|
|
15088
15643
|
if (Array.isArray(current)) {
|
|
15089
15644
|
if (!/^\d+$/.test(segment)) return void 0;
|
|
15090
15645
|
current = current[Number(segment)];
|
|
15091
|
-
} else if (
|
|
15646
|
+
} else if (isObject2(current) && Object.prototype.hasOwnProperty.call(current, segment)) {
|
|
15092
15647
|
current = current[segment];
|
|
15093
15648
|
} else {
|
|
15094
15649
|
return void 0;
|
|
@@ -15096,15 +15651,68 @@ function resolvePointer(document, ref) {
|
|
|
15096
15651
|
}
|
|
15097
15652
|
return current;
|
|
15098
15653
|
}
|
|
15099
|
-
function
|
|
15654
|
+
function isObject2(value) {
|
|
15100
15655
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15101
15656
|
}
|
|
15102
15657
|
|
|
15658
|
+
// src/providers/utils/embeddings.ts
|
|
15659
|
+
function chunkArray(items, size) {
|
|
15660
|
+
const n = Math.max(1, Math.floor(size));
|
|
15661
|
+
const out = [];
|
|
15662
|
+
for (let i = 0; i < items.length; i += n) out.push(items.slice(i, i + n));
|
|
15663
|
+
return out;
|
|
15664
|
+
}
|
|
15665
|
+
async function mapWithConcurrency(items, limit, fn, signal) {
|
|
15666
|
+
const results = new Array(items.length);
|
|
15667
|
+
let next = 0;
|
|
15668
|
+
let failure;
|
|
15669
|
+
let failed = false;
|
|
15670
|
+
const worker = async () => {
|
|
15671
|
+
while (!failed) {
|
|
15672
|
+
if (signal?.aborted) throw signal.reason ?? new Error("aborted");
|
|
15673
|
+
const i = next++;
|
|
15674
|
+
if (i >= items.length) return;
|
|
15675
|
+
try {
|
|
15676
|
+
results[i] = await fn(items[i], i);
|
|
15677
|
+
} catch (err) {
|
|
15678
|
+
failed = true;
|
|
15679
|
+
failure = err;
|
|
15680
|
+
return;
|
|
15681
|
+
}
|
|
15682
|
+
}
|
|
15683
|
+
};
|
|
15684
|
+
await Promise.all(Array.from({ length: Math.min(Math.max(1, limit), items.length) }, worker));
|
|
15685
|
+
if (failed) throw failure;
|
|
15686
|
+
return results;
|
|
15687
|
+
}
|
|
15688
|
+
function decodeBase64Vector(b64) {
|
|
15689
|
+
const buf = Buffer.from(b64, "base64");
|
|
15690
|
+
const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
15691
|
+
const out = new Array(Math.floor(buf.byteLength / 4));
|
|
15692
|
+
for (let i = 0; i < out.length; i++) out[i] = view.getFloat32(i * 4, true);
|
|
15693
|
+
return out;
|
|
15694
|
+
}
|
|
15695
|
+
function assertVectorCount(provider, vectors, expected) {
|
|
15696
|
+
if (vectors.length !== expected) {
|
|
15697
|
+
throw new ProviderError(
|
|
15698
|
+
`${provider} embeddings returned ${vectors.length} vectors for ${expected} inputs`,
|
|
15699
|
+
provider,
|
|
15700
|
+
502
|
|
15701
|
+
);
|
|
15702
|
+
}
|
|
15703
|
+
}
|
|
15704
|
+
function requireEmbeddingModel(provider, model) {
|
|
15705
|
+
if (!model) throw new ProviderError(`${provider} embeddings require a model`, provider, 400);
|
|
15706
|
+
return model;
|
|
15707
|
+
}
|
|
15708
|
+
|
|
15103
15709
|
// src/providers/openai.ts
|
|
15104
|
-
var OpenAIProvider = class
|
|
15710
|
+
var OpenAIProvider = class extends BaseProvider {
|
|
15105
15711
|
constructor(config) {
|
|
15106
15712
|
super();
|
|
15107
15713
|
this.providerName = "openai";
|
|
15714
|
+
this.configureTransport(config);
|
|
15715
|
+
this.maxTokensParam = config.maxTokensParam ?? "auto";
|
|
15108
15716
|
this.apiKey = config.apiKey;
|
|
15109
15717
|
this.baseURL = (config.baseURL ?? "https://api.openai.com/v1").replace(/\/$/, "");
|
|
15110
15718
|
this.defaultModel = config.defaultModel ?? "gpt-4o";
|
|
@@ -15112,10 +15720,14 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15112
15720
|
...config.defaultHeaders,
|
|
15113
15721
|
...config.organization ? { "OpenAI-Organization": config.organization } : {}
|
|
15114
15722
|
};
|
|
15115
|
-
|
|
15116
|
-
const
|
|
15117
|
-
this.
|
|
15118
|
-
this.
|
|
15723
|
+
const legacy = config.responsesApi;
|
|
15724
|
+
const explicit = config.api === "chat" || config.api === "responses" ? config.api : void 0;
|
|
15725
|
+
this.responsesApi = explicit === "responses" ? "always" : explicit === "chat" ? "never" : legacy ?? (config._autoMeansChat ? "never" : "auto");
|
|
15726
|
+
this.apiExplicitChat = explicit === "chat" || explicit === void 0 && legacy === "never";
|
|
15727
|
+
this.apiExplicitResponses = this.responsesApi === "always";
|
|
15728
|
+
this.apiResponsesNative = explicit === "responses";
|
|
15729
|
+
this.responsesApiModels = [...config.responsesApiModels ?? []];
|
|
15730
|
+
this.responsesStreaming = config.responsesStreaming ?? this.apiResponsesNative;
|
|
15119
15731
|
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
15120
15732
|
}
|
|
15121
15733
|
/** True when the caller listed this request's model in `responsesApiModels`. */
|
|
@@ -15141,9 +15753,10 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15141
15753
|
* A model listed in `responsesApiModels` is the caller stating the answer
|
|
15142
15754
|
* for that model alone; `never` still overrides it. */
|
|
15143
15755
|
useResponsesApi(request) {
|
|
15144
|
-
if (this.
|
|
15145
|
-
if (this.
|
|
15756
|
+
if (this.apiExplicitChat) return false;
|
|
15757
|
+
if (this.apiExplicitResponses) return true;
|
|
15146
15758
|
if (this.isResponsesApiModel(request)) return true;
|
|
15759
|
+
if (this.responsesApi !== "auto") return false;
|
|
15147
15760
|
if (!request.reasoning) return false;
|
|
15148
15761
|
return isReasoningModel(request.model || this.defaultModel);
|
|
15149
15762
|
}
|
|
@@ -15152,13 +15765,13 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15152
15765
|
return this.completeResponses(request);
|
|
15153
15766
|
}
|
|
15154
15767
|
const body = this.buildRequestBody(request, false);
|
|
15155
|
-
const res = await this.doFetch(body);
|
|
15768
|
+
const res = await this.doFetch(body, request.signal);
|
|
15156
15769
|
const json = await res.json();
|
|
15157
15770
|
return this.parseResponse(json);
|
|
15158
15771
|
}
|
|
15159
15772
|
async *completeStream(request) {
|
|
15160
15773
|
if (this.useResponsesApi(request)) {
|
|
15161
|
-
if (this.responsesStreaming && this.isResponsesApiModel(request)) {
|
|
15774
|
+
if (this.responsesStreaming && (this.apiResponsesNative || this.isResponsesApiModel(request))) {
|
|
15162
15775
|
yield* this.streamResponses(request);
|
|
15163
15776
|
return;
|
|
15164
15777
|
}
|
|
@@ -15177,13 +15790,13 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15177
15790
|
return;
|
|
15178
15791
|
}
|
|
15179
15792
|
const body = this.buildRequestBody(request, true);
|
|
15180
|
-
const res = await this.doFetch(body);
|
|
15793
|
+
const res = await this.doFetch(body, request.signal);
|
|
15181
15794
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
15182
15795
|
let id = "";
|
|
15183
15796
|
let model = "";
|
|
15184
15797
|
const toolCallBuffers = /* @__PURE__ */ new Map();
|
|
15185
15798
|
let usage;
|
|
15186
|
-
for await (const event of parseSSEStream(res.body)) {
|
|
15799
|
+
for await (const event of parseSSEStream(res.body, request.signal)) {
|
|
15187
15800
|
if (event.data === "[DONE]") break;
|
|
15188
15801
|
let chunk;
|
|
15189
15802
|
try {
|
|
@@ -15208,9 +15821,14 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15208
15821
|
delta: {},
|
|
15209
15822
|
finishReason: mapFinishReason(choice.finish_reason)
|
|
15210
15823
|
};
|
|
15824
|
+
if (typeof choice.finish_reason === "string") out.rawFinishReason = choice.finish_reason;
|
|
15825
|
+
const fields = pickProviderFields(chunk, delta, choice);
|
|
15826
|
+
if (fields) out.providerFields = fields;
|
|
15211
15827
|
if (delta.content) {
|
|
15212
15828
|
out.delta.content = delta.content;
|
|
15213
15829
|
}
|
|
15830
|
+
const reasoningDelta = extractReasoningText(delta);
|
|
15831
|
+
if (reasoningDelta) out.delta.reasoning = { summary: reasoningDelta };
|
|
15214
15832
|
if (delta.tool_calls) {
|
|
15215
15833
|
const partials = [];
|
|
15216
15834
|
for (const tc of delta.tool_calls) {
|
|
@@ -15222,7 +15840,7 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15222
15840
|
if (tc.id) buf.id = tc.id;
|
|
15223
15841
|
if (tc.function?.name) buf.name = tc.function.name;
|
|
15224
15842
|
if (tc.function?.arguments) buf.arguments += tc.function.arguments;
|
|
15225
|
-
partials.push({ id: buf.id, name: buf.name || void 0, arguments: tc.function?.arguments });
|
|
15843
|
+
partials.push({ id: buf.id, name: buf.name || void 0, arguments: tc.function?.arguments, index: idx });
|
|
15226
15844
|
}
|
|
15227
15845
|
out.delta.toolCalls = partials;
|
|
15228
15846
|
}
|
|
@@ -15230,6 +15848,51 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15230
15848
|
yield out;
|
|
15231
15849
|
}
|
|
15232
15850
|
}
|
|
15851
|
+
// ─── Embeddings ──────────────────────────────────────────────────────────
|
|
15852
|
+
/** POST /embeddings, batched (default 2048 inputs per request, the OpenAI cap). */
|
|
15853
|
+
async embed(request) {
|
|
15854
|
+
const model = requireEmbeddingModel(this.providerName, request.model);
|
|
15855
|
+
const batches = chunkArray(request.input, request.batchSize ?? 2048);
|
|
15856
|
+
const vectors = [];
|
|
15857
|
+
const raw = [];
|
|
15858
|
+
let inputTokens = 0;
|
|
15859
|
+
let totalTokens = 0;
|
|
15860
|
+
let responseModel = model;
|
|
15861
|
+
for (const batch of batches) {
|
|
15862
|
+
const body = { model, input: batch };
|
|
15863
|
+
if (request.dimensions != null) body.dimensions = request.dimensions;
|
|
15864
|
+
if (request.encodingFormat) body.encoding_format = request.encodingFormat;
|
|
15865
|
+
if (request.extra) Object.assign(body, request.extra);
|
|
15866
|
+
const res = await this.embeddingsFetch(body, request.signal);
|
|
15867
|
+
const json = await res.json();
|
|
15868
|
+
raw.push(json);
|
|
15869
|
+
const data = Array.isArray(json.data) ? [...json.data] : [];
|
|
15870
|
+
data.sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
|
|
15871
|
+
for (const d of data) {
|
|
15872
|
+
vectors.push(typeof d.embedding === "string" ? decodeBase64Vector(d.embedding) : d.embedding);
|
|
15873
|
+
}
|
|
15874
|
+
inputTokens += json.usage?.prompt_tokens ?? 0;
|
|
15875
|
+
totalTokens += json.usage?.total_tokens ?? json.usage?.prompt_tokens ?? 0;
|
|
15876
|
+
responseModel = json.model ?? responseModel;
|
|
15877
|
+
}
|
|
15878
|
+
assertVectorCount(this.providerName, vectors, request.input.length);
|
|
15879
|
+
return { model: responseModel, vectors, usage: { inputTokens, totalTokens }, raw };
|
|
15880
|
+
}
|
|
15881
|
+
async embeddingsFetch(body, signal) {
|
|
15882
|
+
const url = `${this.baseURL}/embeddings`;
|
|
15883
|
+
const headers = {
|
|
15884
|
+
"Content-Type": "application/json",
|
|
15885
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
15886
|
+
...this.defaultHeaders
|
|
15887
|
+
};
|
|
15888
|
+
const payload = JSON.stringify(body);
|
|
15889
|
+
const res = await this.doFetchWithRetry(() => this.httpFetch(url, { method: "POST", headers, body: payload, signal }), signal);
|
|
15890
|
+
if (!res.ok) {
|
|
15891
|
+
const text = await res.text().catch(() => "");
|
|
15892
|
+
throw new ProviderError(`OpenAI embeddings API error ${res.status}: ${text}`, this.providerName, res.status, text);
|
|
15893
|
+
}
|
|
15894
|
+
return res;
|
|
15895
|
+
}
|
|
15233
15896
|
// ─── Internals ───────────────────────────────────────────────────────────
|
|
15234
15897
|
buildRequestBody(request, stream) {
|
|
15235
15898
|
const body = {
|
|
@@ -15237,15 +15900,27 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15237
15900
|
messages: request.messages.map((m) => this.toOpenAIMessage(m)),
|
|
15238
15901
|
stream
|
|
15239
15902
|
};
|
|
15240
|
-
if (stream) {
|
|
15903
|
+
if (stream && request.streamUsage !== false) {
|
|
15241
15904
|
body.stream_options = { include_usage: true };
|
|
15242
15905
|
}
|
|
15243
|
-
|
|
15244
|
-
|
|
15245
|
-
if (request.
|
|
15906
|
+
const modelId = String(body.model);
|
|
15907
|
+
const reasoningModel = isReasoningModel(modelId) && !/chat/i.test(modelId);
|
|
15908
|
+
if (request.temperature != null && !reasoningModel) body.temperature = request.temperature;
|
|
15909
|
+
if (request.maxTokens != null) {
|
|
15910
|
+
const useCompletionTokens = this.maxTokensParam === "max_completion_tokens" || this.maxTokensParam === "auto" && isReasoningModel(modelId);
|
|
15911
|
+
body[useCompletionTokens ? "max_completion_tokens" : "max_tokens"] = request.maxTokens;
|
|
15912
|
+
}
|
|
15913
|
+
if (request.topP != null && !reasoningModel) body.top_p = request.topP;
|
|
15246
15914
|
if (request.stop) body.stop = request.stop;
|
|
15915
|
+
if (request.presencePenalty != null) body.presence_penalty = request.presencePenalty;
|
|
15916
|
+
if (request.frequencyPenalty != null) body.frequency_penalty = request.frequencyPenalty;
|
|
15917
|
+
if (request.seed != null) body.seed = request.seed;
|
|
15918
|
+
if (request.n != null) body.n = request.n;
|
|
15919
|
+
if (request.logprobs != null) body.logprobs = request.logprobs;
|
|
15920
|
+
if (request.topLogprobs != null) body.top_logprobs = request.topLogprobs;
|
|
15247
15921
|
if (request.tools?.length) {
|
|
15248
15922
|
body.tools = request.tools.map((t) => this.toOpenAITool(t));
|
|
15923
|
+
if (request.parallelToolCalls != null) body.parallel_tool_calls = request.parallelToolCalls;
|
|
15249
15924
|
}
|
|
15250
15925
|
if (request.toolChoice != null && request.tools?.length) {
|
|
15251
15926
|
if (typeof request.toolChoice === "string") {
|
|
@@ -15277,8 +15952,8 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15277
15952
|
// ─── Responses API (reasoning models) ──────────────────────────────────────
|
|
15278
15953
|
async completeResponses(request) {
|
|
15279
15954
|
const body = this.buildResponsesBody(request);
|
|
15280
|
-
if (this.isResponsesApiModel(request)) adaptChatExtrasForResponses(body, request.extra);
|
|
15281
|
-
const res = await this.responsesFetch(body);
|
|
15955
|
+
if (this.apiResponsesNative || this.isResponsesApiModel(request)) adaptChatExtrasForResponses(body, request.extra);
|
|
15956
|
+
const res = await this.responsesFetch(body, request.signal);
|
|
15282
15957
|
const json = await res.json();
|
|
15283
15958
|
return this.parseResponsesResponse(json, request.model || this.defaultModel);
|
|
15284
15959
|
}
|
|
@@ -15294,13 +15969,14 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15294
15969
|
const body = this.buildResponsesBody(request);
|
|
15295
15970
|
adaptChatExtrasForResponses(body, request.extra);
|
|
15296
15971
|
body.stream = true;
|
|
15297
|
-
const res = await this.responsesFetch(body);
|
|
15972
|
+
const res = await this.responsesFetch(body, request.signal);
|
|
15298
15973
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
15299
15974
|
let id = "";
|
|
15300
15975
|
let model = modelId;
|
|
15301
15976
|
const calls = /* @__PURE__ */ new Map();
|
|
15302
15977
|
let final;
|
|
15303
|
-
|
|
15978
|
+
let streamedSummary = false;
|
|
15979
|
+
for await (const event of parseSSEStream(res.body, request.signal)) {
|
|
15304
15980
|
if (event.data === "[DONE]") break;
|
|
15305
15981
|
let data;
|
|
15306
15982
|
try {
|
|
@@ -15317,19 +15993,28 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15317
15993
|
case "response.output_text.delta":
|
|
15318
15994
|
if (data.delta) yield { id, model, delta: { content: data.delta } };
|
|
15319
15995
|
break;
|
|
15996
|
+
case "response.reasoning_summary_part.added":
|
|
15997
|
+
if (streamedSummary) yield { id, model, delta: { reasoning: { summary: "\n\n" } } };
|
|
15998
|
+
break;
|
|
15999
|
+
case "response.reasoning_summary_text.delta":
|
|
16000
|
+
if (typeof data.delta === "string" && data.delta) {
|
|
16001
|
+
streamedSummary = true;
|
|
16002
|
+
yield { id, model, delta: { reasoning: { summary: data.delta } } };
|
|
16003
|
+
}
|
|
16004
|
+
break;
|
|
15320
16005
|
case "response.output_item.added": {
|
|
15321
16006
|
const item = data.item;
|
|
15322
16007
|
if (item?.type !== "function_call") break;
|
|
15323
|
-
const call = { callId: item.call_id ?? item.id ?? "", name: item.name ?? "", arguments: item.arguments ?? "" };
|
|
16008
|
+
const call = { callId: item.call_id ?? item.id ?? "", name: item.name ?? "", arguments: item.arguments ?? "", index: calls.size };
|
|
15324
16009
|
calls.set(item.id ?? call.callId, call);
|
|
15325
|
-
yield { id, model, delta: { toolCalls: [{ id: call.callId, name: call.name, arguments: call.arguments }] } };
|
|
16010
|
+
yield { id, model, delta: { toolCalls: [{ id: call.callId, name: call.name, arguments: call.arguments, index: call.index }] } };
|
|
15326
16011
|
break;
|
|
15327
16012
|
}
|
|
15328
16013
|
case "response.function_call_arguments.delta": {
|
|
15329
16014
|
const call = calls.get(data.item_id);
|
|
15330
16015
|
if (!call || !data.delta) break;
|
|
15331
16016
|
call.arguments += data.delta;
|
|
15332
|
-
yield { id, model, delta: { toolCalls: [{ id: call.callId, arguments: data.delta }] } };
|
|
16017
|
+
yield { id, model, delta: { toolCalls: [{ id: call.callId, arguments: data.delta, index: call.index }] } };
|
|
15333
16018
|
break;
|
|
15334
16019
|
}
|
|
15335
16020
|
case "response.output_item.done": {
|
|
@@ -15338,13 +16023,13 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15338
16023
|
const full = typeof item.arguments === "string" ? item.arguments : "";
|
|
15339
16024
|
const call = calls.get(item.id ?? item.call_id);
|
|
15340
16025
|
if (!call) {
|
|
15341
|
-
const added = { callId: item.call_id ?? item.id ?? "", name: item.name ?? "", arguments: full };
|
|
16026
|
+
const added = { callId: item.call_id ?? item.id ?? "", name: item.name ?? "", arguments: full, index: calls.size };
|
|
15342
16027
|
calls.set(item.id ?? added.callId, added);
|
|
15343
|
-
yield { id, model, delta: { toolCalls: [{ id: added.callId, name: added.name, arguments: full }] } };
|
|
16028
|
+
yield { id, model, delta: { toolCalls: [{ id: added.callId, name: added.name, arguments: full, index: added.index }] } };
|
|
15344
16029
|
} else if (full.length > call.arguments.length && full.startsWith(call.arguments)) {
|
|
15345
16030
|
const rest = full.slice(call.arguments.length);
|
|
15346
16031
|
call.arguments = full;
|
|
15347
|
-
yield { id, model, delta: { toolCalls: [{ id: call.callId, arguments: rest }] } };
|
|
16032
|
+
yield { id, model, delta: { toolCalls: [{ id: call.callId, arguments: rest, index: call.index }] } };
|
|
15348
16033
|
}
|
|
15349
16034
|
break;
|
|
15350
16035
|
}
|
|
@@ -15367,7 +16052,8 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15367
16052
|
yield {
|
|
15368
16053
|
id: final?.id || id,
|
|
15369
16054
|
model: final?.model || model,
|
|
15370
|
-
|
|
16055
|
+
// Summary text already went out as deltas; do not repeat it.
|
|
16056
|
+
delta: final?.reasoning && !streamedSummary ? { reasoning: final.reasoning } : {},
|
|
15371
16057
|
usage: final?.usage,
|
|
15372
16058
|
finishReason: final?.finishReason ?? (calls.size > 0 ? "tool_calls" : "stop")
|
|
15373
16059
|
};
|
|
@@ -15468,7 +16154,7 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15468
16154
|
});
|
|
15469
16155
|
return { role, content };
|
|
15470
16156
|
}
|
|
15471
|
-
async responsesFetch(body) {
|
|
16157
|
+
async responsesFetch(body, signal) {
|
|
15472
16158
|
body.input = expandResponsesInput(body.input);
|
|
15473
16159
|
const url = `${this.baseURL}/responses`;
|
|
15474
16160
|
const headers = {
|
|
@@ -15477,7 +16163,7 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15477
16163
|
...this.defaultHeaders
|
|
15478
16164
|
};
|
|
15479
16165
|
const payload = JSON.stringify(body);
|
|
15480
|
-
const res = await this.doFetchWithRetry(() =>
|
|
16166
|
+
const res = await this.doFetchWithRetry(() => this.httpFetch(url, { method: "POST", headers, body: payload, signal }), signal);
|
|
15481
16167
|
if (!res.ok) {
|
|
15482
16168
|
const text = await res.text().catch(() => "");
|
|
15483
16169
|
throw new ProviderError(
|
|
@@ -15598,7 +16284,7 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15598
16284
|
}
|
|
15599
16285
|
return { type: "function", function: fn };
|
|
15600
16286
|
}
|
|
15601
|
-
async doFetch(body) {
|
|
16287
|
+
async doFetch(body, signal) {
|
|
15602
16288
|
const url = `${this.baseURL}/chat/completions`;
|
|
15603
16289
|
const headers = {
|
|
15604
16290
|
"Content-Type": "application/json",
|
|
@@ -15606,7 +16292,7 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15606
16292
|
...this.defaultHeaders
|
|
15607
16293
|
};
|
|
15608
16294
|
const payload = JSON.stringify(body);
|
|
15609
|
-
const res = await this.doFetchWithRetry(() =>
|
|
16295
|
+
const res = await this.doFetchWithRetry(() => this.httpFetch(url, { method: "POST", headers, body: payload, signal }), signal);
|
|
15610
16296
|
if (!res.ok) {
|
|
15611
16297
|
const text = await res.text().catch(() => "");
|
|
15612
16298
|
throw new ProviderError(
|
|
@@ -15626,6 +16312,8 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15626
16312
|
name: tc.function?.name ?? "",
|
|
15627
16313
|
arguments: tc.function?.arguments ?? "{}"
|
|
15628
16314
|
}));
|
|
16315
|
+
const reasoningText = extractReasoningText(message);
|
|
16316
|
+
const providerFields = pickProviderFields(json, message, choice);
|
|
15629
16317
|
return {
|
|
15630
16318
|
id: json.id ?? "",
|
|
15631
16319
|
model: json.model ?? "",
|
|
@@ -15633,6 +16321,9 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15633
16321
|
toolCalls,
|
|
15634
16322
|
usage: this.extractUsage(json.usage),
|
|
15635
16323
|
finishReason: mapFinishReason(choice?.finish_reason),
|
|
16324
|
+
...typeof choice?.finish_reason === "string" ? { rawFinishReason: choice.finish_reason } : {},
|
|
16325
|
+
...providerFields ? { providerFields } : {},
|
|
16326
|
+
...reasoningText ? { reasoning: { summary: reasoningText } } : {},
|
|
15636
16327
|
raw: json
|
|
15637
16328
|
};
|
|
15638
16329
|
}
|
|
@@ -15651,6 +16342,23 @@ var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
|
15651
16342
|
};
|
|
15652
16343
|
}
|
|
15653
16344
|
};
|
|
16345
|
+
function extractReasoningText(src) {
|
|
16346
|
+
if (!src || typeof src !== "object") return void 0;
|
|
16347
|
+
for (const key of ["reasoning_content", "reasoning"]) {
|
|
16348
|
+
const v = src[key];
|
|
16349
|
+
if (typeof v === "string" && v.length > 0) return v;
|
|
16350
|
+
}
|
|
16351
|
+
return void 0;
|
|
16352
|
+
}
|
|
16353
|
+
function pickProviderFields(top, message, choice) {
|
|
16354
|
+
const out = {};
|
|
16355
|
+
if (top?.system_fingerprint != null) out.system_fingerprint = top.system_fingerprint;
|
|
16356
|
+
if (top?.service_tier != null) out.service_tier = top.service_tier;
|
|
16357
|
+
if (message?.annotations != null) out.annotations = message.annotations;
|
|
16358
|
+
if (message?.refusal != null) out.refusal = message.refusal;
|
|
16359
|
+
if (choice?.logprobs != null) out.logprobs = choice.logprobs;
|
|
16360
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
16361
|
+
}
|
|
15654
16362
|
function isReasoningModel(model) {
|
|
15655
16363
|
if (!model) return false;
|
|
15656
16364
|
const m = model.toLowerCase();
|
|
@@ -15727,38 +16435,88 @@ function mapFinishReason(reason) {
|
|
|
15727
16435
|
}
|
|
15728
16436
|
}
|
|
15729
16437
|
|
|
16438
|
+
// src/providers/utils/toolChoice.ts
|
|
16439
|
+
function supportsForcedToolChoice(model) {
|
|
16440
|
+
if (typeof model !== "string") return true;
|
|
16441
|
+
const id = model.toLowerCase();
|
|
16442
|
+
const at = id.indexOf("claude-");
|
|
16443
|
+
if (at < 0) return true;
|
|
16444
|
+
const toks = id.slice(at + 7).split("-");
|
|
16445
|
+
let family = false;
|
|
16446
|
+
for (const tok of toks) {
|
|
16447
|
+
if (tok === "sonnet" || tok === "opus") {
|
|
16448
|
+
family = true;
|
|
16449
|
+
continue;
|
|
16450
|
+
}
|
|
16451
|
+
const m = /^(\d+)(?:@|:|$)/.exec(tok);
|
|
16452
|
+
if (m) {
|
|
16453
|
+
if (m[1].length > 2) continue;
|
|
16454
|
+
if (Number(m[1]) < 5) return true;
|
|
16455
|
+
if (family) return false;
|
|
16456
|
+
return !toks.some((t) => t === "sonnet" || t === "opus");
|
|
16457
|
+
}
|
|
16458
|
+
}
|
|
16459
|
+
return true;
|
|
16460
|
+
}
|
|
16461
|
+
function forcedToolChoiceRejected(text) {
|
|
16462
|
+
const t = text.toLowerCase();
|
|
16463
|
+
return t.indexOf("tool_choice") >= 0 && t.indexOf("not supported for this model") >= 0;
|
|
16464
|
+
}
|
|
16465
|
+
|
|
15730
16466
|
// src/providers/anthropic.ts
|
|
16467
|
+
var DEFAULT_MAX_TOKENS = 4096;
|
|
16468
|
+
function normalizeExplicitThinking(body) {
|
|
16469
|
+
const t = body.thinking;
|
|
16470
|
+
if (t == null) {
|
|
16471
|
+
delete body.thinking;
|
|
16472
|
+
return;
|
|
16473
|
+
}
|
|
16474
|
+
if (t.type !== "enabled") return;
|
|
16475
|
+
const budget = typeof t.budget_tokens === "number" ? t.budget_tokens : 0;
|
|
16476
|
+
if (budget > 0 && (typeof body.max_tokens !== "number" || body.max_tokens <= budget)) {
|
|
16477
|
+
body.max_tokens = budget + 1024;
|
|
16478
|
+
}
|
|
16479
|
+
for (const k of ["temperature", "top_p", "top_k"]) delete body[k];
|
|
16480
|
+
}
|
|
16481
|
+
function thinkingFormRejected(text) {
|
|
16482
|
+
const t = text.toLowerCase();
|
|
16483
|
+
if (t.indexOf("thinking.type.enabled") >= 0 && t.indexOf("not supported") >= 0) return "enabled";
|
|
16484
|
+
if (t.indexOf("thinking.type.adaptive") >= 0 && t.indexOf("not supported") >= 0 && t.indexOf("thinking.type.enabled") < 0) return "adaptive";
|
|
16485
|
+
return void 0;
|
|
16486
|
+
}
|
|
15731
16487
|
var AnthropicProvider = class extends BaseProvider {
|
|
15732
16488
|
constructor(config) {
|
|
15733
16489
|
super();
|
|
15734
16490
|
this.providerName = "anthropic";
|
|
16491
|
+
this.configureTransport(config);
|
|
15735
16492
|
this.apiKey = config.apiKey;
|
|
15736
16493
|
this.baseURL = (config.baseURL ?? "https://api.anthropic.com").replace(/\/$/, "");
|
|
15737
16494
|
this.defaultModel = config.defaultModel ?? "claude-sonnet-4-20250514";
|
|
15738
16495
|
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
15739
16496
|
this.anthropicVersion = config.anthropicVersion ?? "2023-06-01";
|
|
16497
|
+
this.thinkingMode = config.thinkingMode ?? "auto";
|
|
15740
16498
|
this.promptCachingEnabled = config.prompt_caching?.enabled === true;
|
|
15741
16499
|
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
15742
16500
|
}
|
|
15743
16501
|
async complete(request) {
|
|
15744
|
-
const
|
|
15745
|
-
const res = await this.doFetch(body);
|
|
16502
|
+
const res = await this.send(request, false);
|
|
15746
16503
|
const json = await res.json();
|
|
15747
16504
|
return this.parseResponse(json);
|
|
15748
16505
|
}
|
|
15749
16506
|
async *completeStream(request) {
|
|
15750
|
-
const
|
|
15751
|
-
const res = await this.doFetch(body);
|
|
16507
|
+
const res = await this.send(request, true);
|
|
15752
16508
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
15753
16509
|
let id = "";
|
|
15754
16510
|
let model = "";
|
|
15755
16511
|
let inputTokens = 0;
|
|
15756
16512
|
let outputTokens = 0;
|
|
16513
|
+
let thinkingTokens = 0;
|
|
15757
16514
|
let cacheReadInputTokens = 0;
|
|
15758
16515
|
let cacheCreationInputTokens = 0;
|
|
15759
16516
|
const currentToolCalls = /* @__PURE__ */ new Map();
|
|
16517
|
+
let toolOrdinal = 0;
|
|
15760
16518
|
const reasoningBlocks = /* @__PURE__ */ new Map();
|
|
15761
|
-
for await (const event of parseSSEStream(res.body)) {
|
|
16519
|
+
for await (const event of parseSSEStream(res.body, request.signal)) {
|
|
15762
16520
|
let data;
|
|
15763
16521
|
try {
|
|
15764
16522
|
data = JSON.parse(event.data);
|
|
@@ -15785,8 +16543,11 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
15785
16543
|
currentToolCalls.set(idx, {
|
|
15786
16544
|
id: block.id ?? "",
|
|
15787
16545
|
name: block.name ?? "",
|
|
15788
|
-
arguments: ""
|
|
16546
|
+
arguments: "",
|
|
16547
|
+
ordinal: toolOrdinal++
|
|
15789
16548
|
});
|
|
16549
|
+
const opened = currentToolCalls.get(idx);
|
|
16550
|
+
yield { id, model, delta: { toolCalls: [{ id: opened.id, name: opened.name, arguments: "", index: opened.ordinal }] } };
|
|
15790
16551
|
} else if (block?.type === "thinking") {
|
|
15791
16552
|
reasoningBlocks.set(idx, { type: "thinking", text: block.thinking ?? "", signature: block.signature });
|
|
15792
16553
|
} else if (block?.type === "redacted_thinking") {
|
|
@@ -15824,7 +16585,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
15824
16585
|
id,
|
|
15825
16586
|
model,
|
|
15826
16587
|
delta: {
|
|
15827
|
-
toolCalls: [{ id: tc.id, name: tc.name, arguments: delta.partial_json }]
|
|
16588
|
+
toolCalls: [{ id: tc.id, name: tc.name, arguments: delta.partial_json, index: tc.ordinal }]
|
|
15828
16589
|
}
|
|
15829
16590
|
};
|
|
15830
16591
|
}
|
|
@@ -15837,8 +16598,10 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
15837
16598
|
const delta = data.delta;
|
|
15838
16599
|
if (data.usage) {
|
|
15839
16600
|
outputTokens = data.usage.output_tokens ?? outputTokens;
|
|
16601
|
+
thinkingTokens = data.usage.output_tokens_details?.thinking_tokens ?? thinkingTokens;
|
|
15840
16602
|
}
|
|
15841
16603
|
const finishReason = mapAnthropicStopReason(delta?.stop_reason);
|
|
16604
|
+
const rawFinishReason = typeof delta?.stop_reason === "string" ? delta.stop_reason : void 0;
|
|
15842
16605
|
const usage = {
|
|
15843
16606
|
inputTokens,
|
|
15844
16607
|
outputTokens,
|
|
@@ -15846,7 +16609,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
15846
16609
|
cachedInputTokens: cacheReadInputTokens,
|
|
15847
16610
|
cachedWriteTokens: cacheCreationInputTokens,
|
|
15848
16611
|
cachedOutputTokens: 0,
|
|
15849
|
-
reasoningTokens:
|
|
16612
|
+
reasoningTokens: thinkingTokens
|
|
15850
16613
|
};
|
|
15851
16614
|
const blocks = [...reasoningBlocks.values()].filter(
|
|
15852
16615
|
(b) => b.type === "thinking" && b.signature || b.type === "redacted_thinking" && b.data
|
|
@@ -15856,6 +16619,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
15856
16619
|
model,
|
|
15857
16620
|
delta: blocks.length > 0 ? { reasoning: { blocks } } : {},
|
|
15858
16621
|
finishReason,
|
|
16622
|
+
...rawFinishReason ? { rawFinishReason } : {},
|
|
15859
16623
|
usage
|
|
15860
16624
|
};
|
|
15861
16625
|
break;
|
|
@@ -15870,12 +16634,12 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
15870
16634
|
}
|
|
15871
16635
|
}
|
|
15872
16636
|
// ─── Internals ───────────────────────────────────────────────────────────
|
|
15873
|
-
buildRequestBody(request, stream) {
|
|
16637
|
+
buildRequestBody(request, stream, modeOverride, downgradeToolChoice = false) {
|
|
15874
16638
|
const { system, messages } = this.splitSystemMessages(request.messages);
|
|
15875
16639
|
const body = {
|
|
15876
16640
|
model: request.model || this.defaultModel,
|
|
15877
16641
|
messages: this.toAnthropicMessages(messages),
|
|
15878
|
-
max_tokens: request.maxTokens ??
|
|
16642
|
+
max_tokens: request.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
15879
16643
|
stream
|
|
15880
16644
|
};
|
|
15881
16645
|
if (system) {
|
|
@@ -15896,18 +16660,27 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
15896
16660
|
body.tools = tools;
|
|
15897
16661
|
}
|
|
15898
16662
|
if (request.toolChoice != null) {
|
|
16663
|
+
const forceOk = !downgradeToolChoice && supportsForcedToolChoice(body.model);
|
|
15899
16664
|
if (request.toolChoice === "auto") {
|
|
15900
16665
|
body.tool_choice = { type: "auto" };
|
|
15901
16666
|
} else if (request.toolChoice === "required") {
|
|
15902
|
-
body.tool_choice = { type: "any" };
|
|
16667
|
+
body.tool_choice = forceOk ? { type: "any" } : { type: "auto" };
|
|
15903
16668
|
} else if (request.toolChoice === "none") ; else {
|
|
15904
|
-
body.tool_choice = { type: "tool", name: request.toolChoice.name };
|
|
16669
|
+
body.tool_choice = forceOk ? { type: "tool", name: request.toolChoice.name } : { type: "auto" };
|
|
15905
16670
|
}
|
|
15906
16671
|
}
|
|
15907
16672
|
if (request.extra) {
|
|
15908
16673
|
Object.assign(body, request.extra);
|
|
15909
16674
|
}
|
|
15910
|
-
|
|
16675
|
+
const explicitThinking = request.extra && typeof request.extra === "object" && "thinking" in request.extra;
|
|
16676
|
+
if (explicitThinking) {
|
|
16677
|
+
normalizeExplicitThinking(body);
|
|
16678
|
+
} else {
|
|
16679
|
+
applyAnthropicReasoning(body, request.reasoning, { model: body.model, mode: modeOverride ?? this.thinkingMode });
|
|
16680
|
+
}
|
|
16681
|
+
if (typeof body.max_tokens !== "number" || !(body.max_tokens > 0)) {
|
|
16682
|
+
body.max_tokens = DEFAULT_MAX_TOKENS;
|
|
16683
|
+
}
|
|
15911
16684
|
return body;
|
|
15912
16685
|
}
|
|
15913
16686
|
splitSystemMessages(messages) {
|
|
@@ -16038,7 +16811,35 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
16038
16811
|
input_schema: t.parameters
|
|
16039
16812
|
};
|
|
16040
16813
|
}
|
|
16041
|
-
|
|
16814
|
+
/** Builds and sends the request; retries once with the other thinking form
|
|
16815
|
+
* when the upstream rejects the one we picked. */
|
|
16816
|
+
async send(request, stream) {
|
|
16817
|
+
let mode;
|
|
16818
|
+
let downgrade = false;
|
|
16819
|
+
let flippedThinking = false;
|
|
16820
|
+
for (; ; ) {
|
|
16821
|
+
const body = this.buildRequestBody(request, stream, mode, downgrade);
|
|
16822
|
+
try {
|
|
16823
|
+
return await this.doFetch(body, request.signal);
|
|
16824
|
+
} catch (err) {
|
|
16825
|
+
if (!(err instanceof ProviderError) || err.statusCode !== 400) throw err;
|
|
16826
|
+
const text = String(err.responseBody ?? err.message);
|
|
16827
|
+
if (!downgrade && body.tool_choice && body.tool_choice.type !== "auto" && forcedToolChoiceRejected(text)) {
|
|
16828
|
+
downgrade = true;
|
|
16829
|
+
continue;
|
|
16830
|
+
}
|
|
16831
|
+
const explicit = request.extra && typeof request.extra === "object" && "thinking" in request.extra;
|
|
16832
|
+
if (flippedThinking || explicit || !request.reasoning) throw err;
|
|
16833
|
+
const wrong = thinkingFormRejected(text);
|
|
16834
|
+
if (!wrong) throw err;
|
|
16835
|
+
const used = resolveThinkingForm(request.model ?? this.defaultModel, this.thinkingMode);
|
|
16836
|
+
if (wrong === "enabled" && used !== "budget" || wrong === "adaptive" && used !== "adaptive") throw err;
|
|
16837
|
+
mode = wrong === "enabled" ? "adaptive" : "budget";
|
|
16838
|
+
flippedThinking = true;
|
|
16839
|
+
}
|
|
16840
|
+
}
|
|
16841
|
+
}
|
|
16842
|
+
async doFetch(body, signal) {
|
|
16042
16843
|
const url = `${this.baseURL}/v1/messages`;
|
|
16043
16844
|
const headers = {
|
|
16044
16845
|
"Content-Type": "application/json",
|
|
@@ -16047,7 +16848,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
16047
16848
|
...this.defaultHeaders
|
|
16048
16849
|
};
|
|
16049
16850
|
const payload = JSON.stringify(body);
|
|
16050
|
-
const res = await this.doFetchWithRetry(() =>
|
|
16851
|
+
const res = await this.doFetchWithRetry(() => this.httpFetch(url, { method: "POST", headers, body: payload, signal }), signal);
|
|
16051
16852
|
if (!res.ok) {
|
|
16052
16853
|
const text = await res.text().catch(() => "");
|
|
16053
16854
|
throw new ProviderError(
|
|
@@ -16092,10 +16893,9 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
16092
16893
|
cachedInputTokens: usage.cache_read_input_tokens ?? 0,
|
|
16093
16894
|
cachedWriteTokens: usage.cache_creation_input_tokens ?? 0,
|
|
16094
16895
|
cachedOutputTokens: 0,
|
|
16095
|
-
//
|
|
16096
|
-
//
|
|
16097
|
-
|
|
16098
|
-
reasoningTokens: 0
|
|
16896
|
+
// Thinking tokens are billed inside `output_tokens`; newer models also
|
|
16897
|
+
// report the split as `output_tokens_details.thinking_tokens`.
|
|
16898
|
+
reasoningTokens: usage.output_tokens_details?.thinking_tokens ?? 0
|
|
16099
16899
|
};
|
|
16100
16900
|
return {
|
|
16101
16901
|
id: json.id ?? "",
|
|
@@ -16104,6 +16904,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
16104
16904
|
toolCalls,
|
|
16105
16905
|
usage: tokenUsage,
|
|
16106
16906
|
finishReason: mapAnthropicStopReason(json.stop_reason),
|
|
16907
|
+
...typeof json.stop_reason === "string" ? { rawFinishReason: json.stop_reason } : {},
|
|
16107
16908
|
reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
|
|
16108
16909
|
raw: json
|
|
16109
16910
|
};
|
|
@@ -16149,7 +16950,15 @@ var AzureProvider = class extends OpenAIProvider {
|
|
|
16149
16950
|
provider: "openai",
|
|
16150
16951
|
apiKey: config.apiKey,
|
|
16151
16952
|
defaultModel: config.defaultModel ?? config.deploymentName ?? "gpt-4o",
|
|
16152
|
-
defaultHeaders: config.defaultHeaders
|
|
16953
|
+
defaultHeaders: config.defaultHeaders,
|
|
16954
|
+
retry: config.retry,
|
|
16955
|
+
fetch: config.fetch,
|
|
16956
|
+
timeoutMs: config.timeoutMs,
|
|
16957
|
+
maxTokensParam: config.maxTokensParam,
|
|
16958
|
+
api: config.api,
|
|
16959
|
+
responsesApi: config.responsesApi,
|
|
16960
|
+
responsesApiModels: config.responsesApiModels,
|
|
16961
|
+
responsesStreaming: config.responsesStreaming
|
|
16153
16962
|
});
|
|
16154
16963
|
this.providerName = "azure";
|
|
16155
16964
|
this.endpoint = config.endpoint.replace(/\/$/, "");
|
|
@@ -16157,22 +16966,24 @@ var AzureProvider = class extends OpenAIProvider {
|
|
|
16157
16966
|
this.deploymentName = config.deploymentName;
|
|
16158
16967
|
this.azureApiKey = config.apiKey;
|
|
16159
16968
|
}
|
|
16160
|
-
async doFetch(body) {
|
|
16969
|
+
async doFetch(body, signal) {
|
|
16161
16970
|
const deployment = this.deploymentName ?? body.model;
|
|
16162
16971
|
if (!deployment) {
|
|
16163
16972
|
throw new ProviderError("Azure requires a deploymentName or model", this.providerName);
|
|
16164
16973
|
}
|
|
16165
16974
|
const url = `${this.endpoint}/openai/deployments/${deployment}/chat/completions?api-version=${this.apiVersion}`;
|
|
16166
16975
|
const { model: _model, ...bodyWithoutModel } = body;
|
|
16167
|
-
const
|
|
16976
|
+
const payload = JSON.stringify(bodyWithoutModel);
|
|
16977
|
+
const res = await this.doFetchWithRetry(() => this.httpFetch(url, {
|
|
16168
16978
|
method: "POST",
|
|
16169
16979
|
headers: {
|
|
16170
16980
|
"Content-Type": "application/json",
|
|
16171
16981
|
"api-key": this.azureApiKey,
|
|
16172
16982
|
...this.defaultHeaders
|
|
16173
16983
|
},
|
|
16174
|
-
body:
|
|
16175
|
-
|
|
16984
|
+
body: payload,
|
|
16985
|
+
signal
|
|
16986
|
+
}), signal);
|
|
16176
16987
|
if (!res.ok) {
|
|
16177
16988
|
const text = await res.text().catch(() => "");
|
|
16178
16989
|
throw new ProviderError(
|
|
@@ -16184,10 +16995,36 @@ var AzureProvider = class extends OpenAIProvider {
|
|
|
16184
16995
|
}
|
|
16185
16996
|
return res;
|
|
16186
16997
|
}
|
|
16998
|
+
/** Azure embeddings: the deployment named by the request's model (falling back
|
|
16999
|
+
* to the configured deployment) in the path, api-key auth. */
|
|
17000
|
+
async embeddingsFetch(body, signal) {
|
|
17001
|
+
const deployment = body.model || this.deploymentName;
|
|
17002
|
+
if (!deployment) {
|
|
17003
|
+
throw new ProviderError("Azure embeddings require a deployment name or model", this.providerName, 400);
|
|
17004
|
+
}
|
|
17005
|
+
const url = `${this.endpoint}/openai/deployments/${deployment}/embeddings?api-version=${this.apiVersion}`;
|
|
17006
|
+
const { model: _model, ...bodyWithoutModel } = body;
|
|
17007
|
+
const payload = JSON.stringify(bodyWithoutModel);
|
|
17008
|
+
const res = await this.doFetchWithRetry(() => this.httpFetch(url, {
|
|
17009
|
+
method: "POST",
|
|
17010
|
+
headers: {
|
|
17011
|
+
"Content-Type": "application/json",
|
|
17012
|
+
"api-key": this.azureApiKey,
|
|
17013
|
+
...this.defaultHeaders
|
|
17014
|
+
},
|
|
17015
|
+
body: payload,
|
|
17016
|
+
signal
|
|
17017
|
+
}), signal);
|
|
17018
|
+
if (!res.ok) {
|
|
17019
|
+
const text = await res.text().catch(() => "");
|
|
17020
|
+
throw new ProviderError(`Azure OpenAI embeddings API error ${res.status}: ${text}`, this.providerName, res.status, text);
|
|
17021
|
+
}
|
|
17022
|
+
return res;
|
|
17023
|
+
}
|
|
16187
17024
|
/** Azure exposes the Responses API at /openai/responses with api-key auth.
|
|
16188
17025
|
* Reasoning summaries require a preview api-version; callers can override via
|
|
16189
17026
|
* the `apiVersion` config. */
|
|
16190
|
-
async responsesFetch(body) {
|
|
17027
|
+
async responsesFetch(body, signal) {
|
|
16191
17028
|
body.input = expandAzureResponsesInput(body.input);
|
|
16192
17029
|
const deployment = this.deploymentName ?? body.model;
|
|
16193
17030
|
if (!deployment) {
|
|
@@ -16195,15 +17032,16 @@ var AzureProvider = class extends OpenAIProvider {
|
|
|
16195
17032
|
}
|
|
16196
17033
|
const url = `${this.endpoint}/openai/responses?api-version=${this.apiVersion}`;
|
|
16197
17034
|
const payload = JSON.stringify({ ...body, model: deployment });
|
|
16198
|
-
const res = await
|
|
17035
|
+
const res = await this.doFetchWithRetry(() => this.httpFetch(url, {
|
|
16199
17036
|
method: "POST",
|
|
16200
17037
|
headers: {
|
|
16201
17038
|
"Content-Type": "application/json",
|
|
16202
17039
|
"api-key": this.azureApiKey,
|
|
16203
17040
|
...this.defaultHeaders
|
|
16204
17041
|
},
|
|
16205
|
-
body: payload
|
|
16206
|
-
|
|
17042
|
+
body: payload,
|
|
17043
|
+
signal
|
|
17044
|
+
}), signal);
|
|
16207
17045
|
if (!res.ok) {
|
|
16208
17046
|
const text = await res.text().catch(() => "");
|
|
16209
17047
|
throw new ProviderError(
|
|
@@ -16239,20 +17077,155 @@ var OpenAICompatibleProvider = class extends OpenAIProvider {
|
|
|
16239
17077
|
apiKey: config.apiKey,
|
|
16240
17078
|
baseURL: config.baseURL,
|
|
16241
17079
|
defaultModel: config.defaultModel,
|
|
16242
|
-
defaultHeaders: config.defaultHeaders
|
|
17080
|
+
defaultHeaders: config.defaultHeaders,
|
|
17081
|
+
organization: config.organization,
|
|
17082
|
+
retry: config.retry,
|
|
17083
|
+
fetch: config.fetch,
|
|
17084
|
+
timeoutMs: config.timeoutMs,
|
|
17085
|
+
maxTokensParam: config.maxTokensParam,
|
|
17086
|
+
api: config.api,
|
|
17087
|
+
// Unlike OpenAI / Azure, "auto" on a compatible server means Chat
|
|
17088
|
+
// Completions (the 0.11 default): the model name is the operator's.
|
|
17089
|
+
// `responsesApiModels` still applies; `responsesApi: "auto"` opts in.
|
|
17090
|
+
_autoMeansChat: true,
|
|
17091
|
+
responsesApi: config.responsesApi,
|
|
17092
|
+
responsesApiModels: config.responsesApiModels,
|
|
17093
|
+
responsesStreaming: config.responsesStreaming
|
|
16243
17094
|
});
|
|
16244
17095
|
this.providerName = "openai-compatible";
|
|
16245
17096
|
}
|
|
16246
17097
|
};
|
|
16247
17098
|
|
|
17099
|
+
// src/providers/utils/eventStream.ts
|
|
17100
|
+
var EventStreamError = class extends Error {
|
|
17101
|
+
constructor(message) {
|
|
17102
|
+
super(message);
|
|
17103
|
+
this.name = "EventStreamError";
|
|
17104
|
+
}
|
|
17105
|
+
};
|
|
17106
|
+
var CRC_TABLE = (() => {
|
|
17107
|
+
const table = new Uint32Array(256);
|
|
17108
|
+
for (let n = 0; n < 256; n++) {
|
|
17109
|
+
let c = n;
|
|
17110
|
+
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
17111
|
+
table[n] = c >>> 0;
|
|
17112
|
+
}
|
|
17113
|
+
return table;
|
|
17114
|
+
})();
|
|
17115
|
+
function crc32(bytes, start = 0, end = bytes.length) {
|
|
17116
|
+
let c = 4294967295;
|
|
17117
|
+
for (let i = start; i < end; i++) c = CRC_TABLE[(c ^ bytes[i]) & 255] ^ c >>> 8;
|
|
17118
|
+
return (c ^ 4294967295) >>> 0;
|
|
17119
|
+
}
|
|
17120
|
+
function decodeFrame(frame) {
|
|
17121
|
+
const view = new DataView(frame.buffer, frame.byteOffset, frame.byteLength);
|
|
17122
|
+
const total = view.getUint32(0);
|
|
17123
|
+
const headersLen = view.getUint32(4);
|
|
17124
|
+
if (total !== frame.byteLength) throw new EventStreamError("event-stream frame length mismatch");
|
|
17125
|
+
if (crc32(frame, 0, 8) !== view.getUint32(8)) throw new EventStreamError("event-stream prelude CRC mismatch");
|
|
17126
|
+
if (crc32(frame, 0, total - 4) !== view.getUint32(total - 4)) throw new EventStreamError("event-stream message CRC mismatch");
|
|
17127
|
+
if (12 + headersLen > total - 4) throw new EventStreamError("event-stream headers overflow frame");
|
|
17128
|
+
const headers = {};
|
|
17129
|
+
const td = new TextDecoder();
|
|
17130
|
+
let o = 12;
|
|
17131
|
+
const headersEnd = 12 + headersLen;
|
|
17132
|
+
while (o < headersEnd) {
|
|
17133
|
+
const nameLen = frame[o++];
|
|
17134
|
+
const name = td.decode(frame.subarray(o, o + nameLen));
|
|
17135
|
+
o += nameLen;
|
|
17136
|
+
const type = frame[o++];
|
|
17137
|
+
switch (type) {
|
|
17138
|
+
case 0:
|
|
17139
|
+
headers[name] = true;
|
|
17140
|
+
break;
|
|
17141
|
+
case 1:
|
|
17142
|
+
headers[name] = false;
|
|
17143
|
+
break;
|
|
17144
|
+
case 2:
|
|
17145
|
+
headers[name] = view.getInt8(o);
|
|
17146
|
+
o += 1;
|
|
17147
|
+
break;
|
|
17148
|
+
case 3:
|
|
17149
|
+
headers[name] = view.getInt16(o);
|
|
17150
|
+
o += 2;
|
|
17151
|
+
break;
|
|
17152
|
+
case 4:
|
|
17153
|
+
headers[name] = view.getInt32(o);
|
|
17154
|
+
o += 4;
|
|
17155
|
+
break;
|
|
17156
|
+
case 5:
|
|
17157
|
+
headers[name] = view.getBigInt64(o);
|
|
17158
|
+
o += 8;
|
|
17159
|
+
break;
|
|
17160
|
+
case 6: {
|
|
17161
|
+
const len = view.getUint16(o);
|
|
17162
|
+
o += 2;
|
|
17163
|
+
headers[name] = frame.slice(o, o + len);
|
|
17164
|
+
o += len;
|
|
17165
|
+
break;
|
|
17166
|
+
}
|
|
17167
|
+
case 7: {
|
|
17168
|
+
const len = view.getUint16(o);
|
|
17169
|
+
o += 2;
|
|
17170
|
+
headers[name] = td.decode(frame.subarray(o, o + len));
|
|
17171
|
+
o += len;
|
|
17172
|
+
break;
|
|
17173
|
+
}
|
|
17174
|
+
case 8:
|
|
17175
|
+
headers[name] = view.getBigInt64(o);
|
|
17176
|
+
o += 8;
|
|
17177
|
+
break;
|
|
17178
|
+
case 9:
|
|
17179
|
+
headers[name] = frame.slice(o, o + 16);
|
|
17180
|
+
o += 16;
|
|
17181
|
+
break;
|
|
17182
|
+
default:
|
|
17183
|
+
throw new EventStreamError(`unknown event-stream header type ${type}`);
|
|
17184
|
+
}
|
|
17185
|
+
}
|
|
17186
|
+
return { headers, payload: frame.slice(headersEnd, total - 4) };
|
|
17187
|
+
}
|
|
17188
|
+
async function* parseEventStream(body, signal) {
|
|
17189
|
+
const reader = body.getReader();
|
|
17190
|
+
let buf = new Uint8Array(0);
|
|
17191
|
+
try {
|
|
17192
|
+
while (true) {
|
|
17193
|
+
if (signal?.aborted) throw abortReason(signal);
|
|
17194
|
+
const { done, value } = await reader.read();
|
|
17195
|
+
if (done) break;
|
|
17196
|
+
if (!value?.length) continue;
|
|
17197
|
+
const merged = new Uint8Array(buf.length + value.length);
|
|
17198
|
+
merged.set(buf, 0);
|
|
17199
|
+
merged.set(value, buf.length);
|
|
17200
|
+
buf = merged;
|
|
17201
|
+
while (buf.length >= 12) {
|
|
17202
|
+
const total = new DataView(buf.buffer, buf.byteOffset, buf.byteLength).getUint32(0);
|
|
17203
|
+
if (total < 16) throw new EventStreamError("invalid event-stream frame length");
|
|
17204
|
+
if (buf.length < total) break;
|
|
17205
|
+
yield decodeFrame(buf.subarray(0, total));
|
|
17206
|
+
buf = buf.subarray(total);
|
|
17207
|
+
}
|
|
17208
|
+
}
|
|
17209
|
+
if (buf.length > 0) throw new EventStreamError("event-stream ended inside a frame");
|
|
17210
|
+
} finally {
|
|
17211
|
+
reader.cancel().catch(() => void 0);
|
|
17212
|
+
try {
|
|
17213
|
+
reader.releaseLock();
|
|
17214
|
+
} catch {
|
|
17215
|
+
}
|
|
17216
|
+
}
|
|
17217
|
+
}
|
|
17218
|
+
|
|
16248
17219
|
// src/providers/bedrock.ts
|
|
16249
17220
|
var BedrockProvider = class extends BaseProvider {
|
|
16250
17221
|
constructor(config) {
|
|
16251
17222
|
super();
|
|
16252
17223
|
this.providerName = "bedrock";
|
|
17224
|
+
this.configureTransport(config);
|
|
16253
17225
|
this.region = config.region;
|
|
16254
17226
|
this.defaultModel = config.defaultModel ?? "anthropic.claude-sonnet-4-20250514-v1:0";
|
|
16255
17227
|
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
17228
|
+
this.thinkingMode = config.thinkingMode ?? "auto";
|
|
16256
17229
|
this.promptCachingEnabled = config.prompt_caching?.enabled === true;
|
|
16257
17230
|
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
16258
17231
|
this.credentials = {
|
|
@@ -16269,25 +17242,202 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
16269
17242
|
}
|
|
16270
17243
|
async complete(request) {
|
|
16271
17244
|
const modelId = request.model || this.defaultModel;
|
|
16272
|
-
const
|
|
16273
|
-
|
|
16274
|
-
return this.parseResponse(json, modelId);
|
|
17245
|
+
const res = await this.converseFetch(modelId, request, false);
|
|
17246
|
+
return this.parseResponse(await res.json(), modelId);
|
|
16275
17247
|
}
|
|
17248
|
+
/**
|
|
17249
|
+
* Real streaming over ConverseStream. The response is an AWS event-stream
|
|
17250
|
+
* (binary frames); each frame carries one JSON event: messageStart,
|
|
17251
|
+
* contentBlockStart/Delta/Stop (text, toolUse, reasoningContent),
|
|
17252
|
+
* messageStop and, last, metadata (usage). Text, tool-call argument and
|
|
17253
|
+
* reasoning deltas are yielded as they arrive; one closing chunk carries the
|
|
17254
|
+
* finish reason, usage and the signed reasoning blocks.
|
|
17255
|
+
*/
|
|
16276
17256
|
async *completeStream(request) {
|
|
16277
|
-
const
|
|
17257
|
+
const modelId = request.model || this.defaultModel;
|
|
17258
|
+
const res = await this.converseFetch(modelId, request, true);
|
|
17259
|
+
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
17260
|
+
const id = res.headers.get("x-amzn-requestid") ?? "";
|
|
17261
|
+
const toolsByIndex = /* @__PURE__ */ new Map();
|
|
17262
|
+
const reasoningByIndex = /* @__PURE__ */ new Map();
|
|
17263
|
+
let finishReason;
|
|
17264
|
+
let rawFinishReason;
|
|
17265
|
+
let toolOrdinal = 0;
|
|
17266
|
+
let usage;
|
|
17267
|
+
for await (const msg of parseEventStream(res.body, request.signal)) {
|
|
17268
|
+
const messageType = String(msg.headers[":message-type"] ?? "event");
|
|
17269
|
+
const eventType = String(msg.headers[":event-type"] ?? msg.headers[":exception-type"] ?? "");
|
|
17270
|
+
let data = {};
|
|
17271
|
+
const text = new TextDecoder().decode(msg.payload);
|
|
17272
|
+
if (text) {
|
|
17273
|
+
try {
|
|
17274
|
+
data = JSON.parse(text);
|
|
17275
|
+
} catch {
|
|
17276
|
+
data = { message: text };
|
|
17277
|
+
}
|
|
17278
|
+
}
|
|
17279
|
+
if (messageType === "exception" || messageType === "error") {
|
|
17280
|
+
const code = String(msg.headers[":exception-type"] ?? msg.headers[":error-code"] ?? eventType);
|
|
17281
|
+
throw new ProviderError(
|
|
17282
|
+
`Bedrock stream error ${code}: ${data.message ?? text}`,
|
|
17283
|
+
this.providerName,
|
|
17284
|
+
bedrockExceptionStatus(code),
|
|
17285
|
+
data
|
|
17286
|
+
);
|
|
17287
|
+
}
|
|
17288
|
+
switch (eventType) {
|
|
17289
|
+
case "contentBlockStart": {
|
|
17290
|
+
const idx = data.contentBlockIndex ?? 0;
|
|
17291
|
+
const tu = data.start?.toolUse;
|
|
17292
|
+
if (tu) {
|
|
17293
|
+
const ordinal = toolOrdinal++;
|
|
17294
|
+
toolsByIndex.set(idx, { id: tu.toolUseId ?? "", name: tu.name ?? "", ordinal });
|
|
17295
|
+
yield { id, model: modelId, delta: { toolCalls: [{ id: tu.toolUseId, name: tu.name, arguments: "", index: ordinal }] } };
|
|
17296
|
+
}
|
|
17297
|
+
break;
|
|
17298
|
+
}
|
|
17299
|
+
case "contentBlockDelta": {
|
|
17300
|
+
const idx = data.contentBlockIndex ?? 0;
|
|
17301
|
+
const d = data.delta ?? {};
|
|
17302
|
+
if (typeof d.text === "string" && d.text) {
|
|
17303
|
+
yield { id, model: modelId, delta: { content: d.text } };
|
|
17304
|
+
} else if (d.toolUse) {
|
|
17305
|
+
const tc = toolsByIndex.get(idx);
|
|
17306
|
+
if (tc && typeof d.toolUse.input === "string" && d.toolUse.input) {
|
|
17307
|
+
yield { id, model: modelId, delta: { toolCalls: [{ id: tc.id, name: tc.name, arguments: d.toolUse.input, index: tc.ordinal }] } };
|
|
17308
|
+
}
|
|
17309
|
+
} else if (d.reasoningContent) {
|
|
17310
|
+
const rc = d.reasoningContent;
|
|
17311
|
+
const blk = reasoningByIndex.get(idx) ?? { type: "thinking", text: "" };
|
|
17312
|
+
if (typeof rc.text === "string" && rc.text) {
|
|
17313
|
+
blk.text = (blk.text ?? "") + rc.text;
|
|
17314
|
+
reasoningByIndex.set(idx, blk);
|
|
17315
|
+
yield { id, model: modelId, delta: { reasoning: { summary: rc.text } } };
|
|
17316
|
+
}
|
|
17317
|
+
if (typeof rc.signature === "string" && rc.signature) {
|
|
17318
|
+
blk.signature = (blk.signature ?? "") + rc.signature;
|
|
17319
|
+
reasoningByIndex.set(idx, blk);
|
|
17320
|
+
}
|
|
17321
|
+
if (rc.redactedContent) {
|
|
17322
|
+
reasoningByIndex.set(idx, { type: "redacted_thinking", data: rc.redactedContent });
|
|
17323
|
+
}
|
|
17324
|
+
}
|
|
17325
|
+
break;
|
|
17326
|
+
}
|
|
17327
|
+
case "messageStop":
|
|
17328
|
+
finishReason = mapBedrockStopReason(data.stopReason);
|
|
17329
|
+
if (typeof data.stopReason === "string") rawFinishReason = data.stopReason;
|
|
17330
|
+
break;
|
|
17331
|
+
case "metadata": {
|
|
17332
|
+
const u = data.usage ?? {};
|
|
17333
|
+
usage = {
|
|
17334
|
+
inputTokens: u.inputTokens ?? 0,
|
|
17335
|
+
outputTokens: u.outputTokens ?? 0,
|
|
17336
|
+
totalTokens: u.totalTokens ?? (u.inputTokens ?? 0) + (u.outputTokens ?? 0),
|
|
17337
|
+
cachedInputTokens: u.cacheReadInputTokens ?? u.cacheReadInputTokenCount ?? 0,
|
|
17338
|
+
cachedWriteTokens: u.cacheWriteInputTokens ?? u.cacheWriteInputTokenCount ?? 0,
|
|
17339
|
+
cachedOutputTokens: 0,
|
|
17340
|
+
reasoningTokens: 0
|
|
17341
|
+
};
|
|
17342
|
+
break;
|
|
17343
|
+
}
|
|
17344
|
+
}
|
|
17345
|
+
}
|
|
17346
|
+
const blocks = [...reasoningByIndex.values()].filter(
|
|
17347
|
+
(b) => b.type === "thinking" && b.signature || b.type === "redacted_thinking" && b.data
|
|
17348
|
+
);
|
|
16278
17349
|
yield {
|
|
16279
|
-
id
|
|
16280
|
-
model:
|
|
16281
|
-
delta: {
|
|
16282
|
-
|
|
16283
|
-
|
|
16284
|
-
|
|
16285
|
-
usage: response.usage,
|
|
16286
|
-
finishReason: response.finishReason
|
|
17350
|
+
id,
|
|
17351
|
+
model: modelId,
|
|
17352
|
+
delta: blocks.length > 0 ? { reasoning: { blocks } } : {},
|
|
17353
|
+
finishReason: finishReason ?? "stop",
|
|
17354
|
+
...rawFinishReason ? { rawFinishReason } : {},
|
|
17355
|
+
usage
|
|
16287
17356
|
};
|
|
16288
17357
|
}
|
|
17358
|
+
// ─── Embeddings ──────────────────────────────────────────────────────────
|
|
17359
|
+
/**
|
|
17360
|
+
* InvokeModel embeddings. Supported families (by model id, inference-profile
|
|
17361
|
+
* prefixes such as `us.` allowed):
|
|
17362
|
+
* - Amazon Titan Text Embeddings (v1, v2): one text per call, `dimensions`
|
|
17363
|
+
* (v2: 256/512/1024) and `normalize` via `extra`.
|
|
17364
|
+
* - Cohere Embed (v3, v4): a batch of texts per call (default 96), `inputType`
|
|
17365
|
+
* maps to `input_type`, `dimensions` to `output_dimension` (v4).
|
|
17366
|
+
*/
|
|
17367
|
+
async embed(request) {
|
|
17368
|
+
const model = requireEmbeddingModel(this.providerName, request.model);
|
|
17369
|
+
const id = model.toLowerCase();
|
|
17370
|
+
const raw = [];
|
|
17371
|
+
let inputTokens = 0;
|
|
17372
|
+
let vectors = [];
|
|
17373
|
+
if (id.includes("titan-embed")) {
|
|
17374
|
+
const results = await mapWithConcurrency(request.input, 4, async (text) => {
|
|
17375
|
+
const body = { inputText: text };
|
|
17376
|
+
if (request.dimensions != null && !id.includes("titan-embed-text-v1")) body.dimensions = request.dimensions;
|
|
17377
|
+
if (request.extra) Object.assign(body, request.extra);
|
|
17378
|
+
const res = await this.invokeModel(model, body, request.signal);
|
|
17379
|
+
const json = await res.json();
|
|
17380
|
+
return { json, tokens: json.inputTextTokenCount ?? Number(res.headers.get("x-amzn-bedrock-input-token-count") ?? 0) };
|
|
17381
|
+
}, request.signal);
|
|
17382
|
+
for (const r of results) {
|
|
17383
|
+
raw.push(r.json);
|
|
17384
|
+
inputTokens += r.tokens || 0;
|
|
17385
|
+
vectors.push(r.json.embedding ?? r.json.embeddingsByType?.float);
|
|
17386
|
+
}
|
|
17387
|
+
} else if (id.includes("cohere.embed")) {
|
|
17388
|
+
for (const batch of chunkArray(request.input, request.batchSize ?? 96)) {
|
|
17389
|
+
const body = {
|
|
17390
|
+
texts: batch,
|
|
17391
|
+
input_type: request.inputType ?? "search_document",
|
|
17392
|
+
embedding_types: ["float"]
|
|
17393
|
+
};
|
|
17394
|
+
if (request.dimensions != null) body.output_dimension = request.dimensions;
|
|
17395
|
+
if (request.extra) Object.assign(body, request.extra);
|
|
17396
|
+
const res = await this.invokeModel(model, body, request.signal);
|
|
17397
|
+
const json = await res.json();
|
|
17398
|
+
raw.push(json);
|
|
17399
|
+
const emb = Array.isArray(json.embeddings) ? json.embeddings : json.embeddings?.float;
|
|
17400
|
+
vectors.push(...emb ?? []);
|
|
17401
|
+
inputTokens += Number(res.headers.get("x-amzn-bedrock-input-token-count") ?? 0) || 0;
|
|
17402
|
+
}
|
|
17403
|
+
} else {
|
|
17404
|
+
throw new ProviderError(
|
|
17405
|
+
`Bedrock embeddings are supported for Amazon Titan and Cohere Embed models, not "${model}"`,
|
|
17406
|
+
this.providerName,
|
|
17407
|
+
400
|
|
17408
|
+
);
|
|
17409
|
+
}
|
|
17410
|
+
assertVectorCount(this.providerName, vectors, request.input.length);
|
|
17411
|
+
return { model, vectors, usage: { inputTokens, totalTokens: inputTokens }, raw };
|
|
17412
|
+
}
|
|
17413
|
+
async invokeModel(modelId, body, signal) {
|
|
17414
|
+
const host = `bedrock-runtime.${this.region}.amazonaws.com`;
|
|
17415
|
+
const url = `https://${host}/model/${encodeURIComponent(modelId)}/invoke`;
|
|
17416
|
+
const bodyStr = JSON.stringify(body);
|
|
17417
|
+
const res = await this.doFetchWithRetry(() => {
|
|
17418
|
+
const headers = signRequest({
|
|
17419
|
+
method: "POST",
|
|
17420
|
+
url,
|
|
17421
|
+
headers: {
|
|
17422
|
+
"Content-Type": "application/json",
|
|
17423
|
+
Accept: "application/json",
|
|
17424
|
+
...this.defaultHeaders
|
|
17425
|
+
},
|
|
17426
|
+
body: bodyStr,
|
|
17427
|
+
region: this.region,
|
|
17428
|
+
service: "bedrock",
|
|
17429
|
+
credentials: this.credentials
|
|
17430
|
+
});
|
|
17431
|
+
return this.httpFetch(url, { method: "POST", headers, body: bodyStr, signal });
|
|
17432
|
+
}, signal);
|
|
17433
|
+
if (!res.ok) {
|
|
17434
|
+
const text = await res.text().catch(() => "");
|
|
17435
|
+
throw new ProviderError(`Bedrock API error ${res.status}: ${text}`, this.providerName, res.status, text);
|
|
17436
|
+
}
|
|
17437
|
+
return res;
|
|
17438
|
+
}
|
|
16289
17439
|
// ─── Internals ───────────────────────────────────────────────────────────
|
|
16290
|
-
buildConverseBody(request) {
|
|
17440
|
+
buildConverseBody(request, downgradeToolChoice = false) {
|
|
16291
17441
|
const { system, messages } = this.splitSystemMessages(request.messages);
|
|
16292
17442
|
const body = {
|
|
16293
17443
|
messages: this.toBedrockMessages(messages)
|
|
@@ -16311,8 +17461,9 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
16311
17461
|
body.toolConfig = {
|
|
16312
17462
|
tools
|
|
16313
17463
|
};
|
|
17464
|
+
const forceOk = !downgradeToolChoice && supportsForcedToolChoice(request.model || this.defaultModel);
|
|
16314
17465
|
if (request.toolChoice != null) {
|
|
16315
|
-
if (request.toolChoice === "auto") {
|
|
17466
|
+
if (request.toolChoice === "auto" || !forceOk && request.toolChoice !== "none") {
|
|
16316
17467
|
body.toolConfig.toolChoice = { auto: {} };
|
|
16317
17468
|
} else if (request.toolChoice === "required") {
|
|
16318
17469
|
body.toolConfig.toolChoice = { any: {} };
|
|
@@ -16322,9 +17473,17 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
16322
17473
|
}
|
|
16323
17474
|
}
|
|
16324
17475
|
if (request.extra) {
|
|
16325
|
-
|
|
17476
|
+
const fields = { ...request.extra.additionalModelRequestFields ?? {} };
|
|
17477
|
+
const topLevel = { ...request.extra.__top ?? {} };
|
|
17478
|
+
for (const [key, value] of Object.entries(request.extra)) {
|
|
17479
|
+
if (key === "additionalModelRequestFields" || key === "__top") continue;
|
|
17480
|
+
if (CONVERSE_TOP_LEVEL_FIELDS.has(key)) body[key] = value;
|
|
17481
|
+
else fields[key] = value;
|
|
17482
|
+
}
|
|
17483
|
+
Object.assign(body, topLevel);
|
|
17484
|
+
if (Object.keys(fields).length > 0) body.additionalModelRequestFields = fields;
|
|
16326
17485
|
}
|
|
16327
|
-
applyBedrockReasoning(body, request.reasoning);
|
|
17486
|
+
applyBedrockReasoning(body, request.reasoning, { model: request.model || this.defaultModel, mode: this.thinkingMode });
|
|
16328
17487
|
return body;
|
|
16329
17488
|
}
|
|
16330
17489
|
splitSystemMessages(messages) {
|
|
@@ -16447,9 +17606,22 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
16447
17606
|
}
|
|
16448
17607
|
};
|
|
16449
17608
|
}
|
|
16450
|
-
|
|
17609
|
+
/** Sends the Converse call; retries once with toolChoice auto when the
|
|
17610
|
+
* model rejects forced tool use. */
|
|
17611
|
+
async converseFetch(modelId, request, stream) {
|
|
17612
|
+
const body = this.buildConverseBody(request);
|
|
17613
|
+
try {
|
|
17614
|
+
return await this.doFetch(modelId, body, request.signal, stream);
|
|
17615
|
+
} catch (err) {
|
|
17616
|
+
const tc = body.toolConfig?.toolChoice;
|
|
17617
|
+
if (!(err instanceof ProviderError) || err.statusCode !== 400 || !tc || tc.auto) throw err;
|
|
17618
|
+
if (!forcedToolChoiceRejected(String(err.responseBody ?? err.message))) throw err;
|
|
17619
|
+
return this.doFetch(modelId, this.buildConverseBody(request, true), request.signal, stream);
|
|
17620
|
+
}
|
|
17621
|
+
}
|
|
17622
|
+
async doFetch(modelId, body, signal, stream) {
|
|
16451
17623
|
const host = `bedrock-runtime.${this.region}.amazonaws.com`;
|
|
16452
|
-
const url = `https://${host}/model/${encodeURIComponent(modelId)}
|
|
17624
|
+
const url = `https://${host}/model/${encodeURIComponent(modelId)}/${stream ? "converse-stream" : "converse"}`;
|
|
16453
17625
|
const bodyStr = JSON.stringify(body);
|
|
16454
17626
|
const res = await this.doFetchWithRetry(() => {
|
|
16455
17627
|
const headers = signRequest({
|
|
@@ -16457,7 +17629,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
16457
17629
|
url,
|
|
16458
17630
|
headers: {
|
|
16459
17631
|
"Content-Type": "application/json",
|
|
16460
|
-
Accept: "application/json",
|
|
17632
|
+
Accept: stream ? "application/vnd.amazon.eventstream" : "application/json",
|
|
16461
17633
|
...this.defaultHeaders
|
|
16462
17634
|
},
|
|
16463
17635
|
body: bodyStr,
|
|
@@ -16465,8 +17637,8 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
16465
17637
|
service: "bedrock",
|
|
16466
17638
|
credentials: this.credentials
|
|
16467
17639
|
});
|
|
16468
|
-
return
|
|
16469
|
-
});
|
|
17640
|
+
return this.httpFetch(url, { method: "POST", headers, body: bodyStr, signal });
|
|
17641
|
+
}, signal);
|
|
16470
17642
|
if (!res.ok) {
|
|
16471
17643
|
const text = await res.text().catch(() => "");
|
|
16472
17644
|
throw new ProviderError(
|
|
@@ -16476,7 +17648,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
16476
17648
|
text
|
|
16477
17649
|
);
|
|
16478
17650
|
}
|
|
16479
|
-
return res
|
|
17651
|
+
return res;
|
|
16480
17652
|
}
|
|
16481
17653
|
parseResponse(json, modelId) {
|
|
16482
17654
|
const output = json.output?.message;
|
|
@@ -16512,8 +17684,8 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
16512
17684
|
inputTokens: usage.inputTokens ?? 0,
|
|
16513
17685
|
outputTokens: usage.outputTokens ?? 0,
|
|
16514
17686
|
totalTokens: usage.totalTokens ?? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0),
|
|
16515
|
-
cachedInputTokens: usage.cacheReadInputTokenCount ?? 0,
|
|
16516
|
-
cachedWriteTokens: usage.cacheWriteInputTokenCount ?? 0,
|
|
17687
|
+
cachedInputTokens: usage.cacheReadInputTokens ?? usage.cacheReadInputTokenCount ?? 0,
|
|
17688
|
+
cachedWriteTokens: usage.cacheWriteInputTokens ?? usage.cacheWriteInputTokenCount ?? 0,
|
|
16517
17689
|
cachedOutputTokens: 0,
|
|
16518
17690
|
// Bedrock bills thinking tokens inside outputTokens; no separate count.
|
|
16519
17691
|
reasoningTokens: 0
|
|
@@ -16525,11 +17697,26 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
16525
17697
|
toolCalls,
|
|
16526
17698
|
usage: tokenUsage,
|
|
16527
17699
|
finishReason: mapBedrockStopReason(json.stopReason),
|
|
17700
|
+
...typeof json.stopReason === "string" ? { rawFinishReason: json.stopReason } : {},
|
|
16528
17701
|
reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
|
|
16529
17702
|
raw: json
|
|
16530
17703
|
};
|
|
16531
17704
|
}
|
|
16532
17705
|
};
|
|
17706
|
+
var CONVERSE_TOP_LEVEL_FIELDS = /* @__PURE__ */ new Set([
|
|
17707
|
+
"messages",
|
|
17708
|
+
"system",
|
|
17709
|
+
"inferenceConfig",
|
|
17710
|
+
"toolConfig",
|
|
17711
|
+
"guardrailConfig",
|
|
17712
|
+
"additionalModelRequestFields",
|
|
17713
|
+
"additionalModelResponseFieldPaths",
|
|
17714
|
+
"promptVariables",
|
|
17715
|
+
"requestMetadata",
|
|
17716
|
+
"performanceConfig",
|
|
17717
|
+
"serviceTier",
|
|
17718
|
+
"outputConfig"
|
|
17719
|
+
]);
|
|
16533
17720
|
function appendBedrockReasoning(content, blocks) {
|
|
16534
17721
|
if (!blocks?.length) return;
|
|
16535
17722
|
for (const b of blocks) {
|
|
@@ -16544,6 +17731,23 @@ function appendBedrockReasoning(content, blocks) {
|
|
|
16544
17731
|
}
|
|
16545
17732
|
}
|
|
16546
17733
|
}
|
|
17734
|
+
function bedrockExceptionStatus(code) {
|
|
17735
|
+
switch (code) {
|
|
17736
|
+
case "throttlingException":
|
|
17737
|
+
return 429;
|
|
17738
|
+
case "validationException":
|
|
17739
|
+
return 400;
|
|
17740
|
+
case "modelTimeoutException":
|
|
17741
|
+
return 408;
|
|
17742
|
+
case "serviceUnavailableException":
|
|
17743
|
+
return 503;
|
|
17744
|
+
case "internalServerException":
|
|
17745
|
+
case "modelStreamErrorException":
|
|
17746
|
+
return 500;
|
|
17747
|
+
default:
|
|
17748
|
+
return void 0;
|
|
17749
|
+
}
|
|
17750
|
+
}
|
|
16547
17751
|
function mapBedrockStopReason(reason) {
|
|
16548
17752
|
switch (reason) {
|
|
16549
17753
|
case "end_turn":
|
|
@@ -16552,8 +17756,10 @@ function mapBedrockStopReason(reason) {
|
|
|
16552
17756
|
case "tool_use":
|
|
16553
17757
|
return "tool_calls";
|
|
16554
17758
|
case "max_tokens":
|
|
17759
|
+
case "model_context_window_exceeded":
|
|
16555
17760
|
return "length";
|
|
16556
17761
|
case "content_filtered":
|
|
17762
|
+
case "guardrail_intervened":
|
|
16557
17763
|
case "guardrail":
|
|
16558
17764
|
return "content_filter";
|
|
16559
17765
|
default:
|
|
@@ -16583,10 +17789,12 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16583
17789
|
super();
|
|
16584
17790
|
this.providerName = "vertex";
|
|
16585
17791
|
this.tokenExpiry = 0;
|
|
17792
|
+
this.configureTransport(config);
|
|
16586
17793
|
this.projectId = config.projectId;
|
|
16587
17794
|
this.location = config.location ?? "us-central1";
|
|
16588
17795
|
this.defaultModel = config.defaultModel ?? "gemini-2.0-flash";
|
|
16589
17796
|
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
17797
|
+
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
16590
17798
|
if (config.accessToken) {
|
|
16591
17799
|
this.accessToken = config.accessToken;
|
|
16592
17800
|
this.tokenExpiry = Date.now() + 36e5;
|
|
@@ -16599,7 +17807,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16599
17807
|
const modelId = request.model || this.defaultModel;
|
|
16600
17808
|
const body = this.buildGeminiBody(request);
|
|
16601
17809
|
const url = this.buildUrl(modelId, false);
|
|
16602
|
-
const res = await this.doFetch(url, body);
|
|
17810
|
+
const res = await this.doFetch(url, body, request.signal);
|
|
16603
17811
|
const json = await res.json();
|
|
16604
17812
|
return this.parseResponse(json, modelId);
|
|
16605
17813
|
}
|
|
@@ -16607,11 +17815,12 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16607
17815
|
const modelId = request.model || this.defaultModel;
|
|
16608
17816
|
const body = this.buildGeminiBody(request);
|
|
16609
17817
|
const url = this.buildUrl(modelId, true);
|
|
16610
|
-
const res = await this.doFetch(url, body);
|
|
17818
|
+
const res = await this.doFetch(url, body, request.signal);
|
|
16611
17819
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
17820
|
+
const counter = { next: 0 };
|
|
16612
17821
|
const contentType = res.headers.get("content-type") ?? "";
|
|
16613
17822
|
if (contentType.includes("text/event-stream")) {
|
|
16614
|
-
for await (const event of parseSSEStream(res.body)) {
|
|
17823
|
+
for await (const event of parseSSEStream(res.body, request.signal)) {
|
|
16615
17824
|
if (event.data === "[DONE]") break;
|
|
16616
17825
|
let chunk;
|
|
16617
17826
|
try {
|
|
@@ -16619,7 +17828,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16619
17828
|
} catch {
|
|
16620
17829
|
continue;
|
|
16621
17830
|
}
|
|
16622
|
-
yield this.parseStreamChunk(chunk, modelId);
|
|
17831
|
+
yield this.parseStreamChunk(chunk, modelId, counter);
|
|
16623
17832
|
}
|
|
16624
17833
|
} else {
|
|
16625
17834
|
const reader = res.body.getReader();
|
|
@@ -16637,7 +17846,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16637
17846
|
if (!trimmed || trimmed === "[" || trimmed === "]") continue;
|
|
16638
17847
|
try {
|
|
16639
17848
|
const chunk = JSON.parse(trimmed);
|
|
16640
|
-
yield this.parseStreamChunk(chunk, modelId);
|
|
17849
|
+
yield this.parseStreamChunk(chunk, modelId, counter);
|
|
16641
17850
|
} catch {
|
|
16642
17851
|
buffer = line + "\n" + buffer;
|
|
16643
17852
|
break;
|
|
@@ -16648,16 +17857,59 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16648
17857
|
if (remaining && remaining !== "[" && remaining !== "]") {
|
|
16649
17858
|
try {
|
|
16650
17859
|
const chunk = JSON.parse(remaining);
|
|
16651
|
-
yield this.parseStreamChunk(chunk, modelId);
|
|
17860
|
+
yield this.parseStreamChunk(chunk, modelId, counter);
|
|
16652
17861
|
} catch {
|
|
16653
17862
|
}
|
|
16654
17863
|
}
|
|
16655
17864
|
} finally {
|
|
17865
|
+
reader.cancel().catch(() => void 0);
|
|
16656
17866
|
reader.releaseLock();
|
|
16657
17867
|
}
|
|
16658
17868
|
}
|
|
16659
17869
|
}
|
|
16660
17870
|
// ─── Internals ───────────────────────────────────────────────────────────
|
|
17871
|
+
/**
|
|
17872
|
+
* Vertex `:predict` embeddings (text-embedding-00x, text-multilingual-embedding,
|
|
17873
|
+
* gemini-embedding-001). `inputType` maps to the task type; `dimensions` to
|
|
17874
|
+
* `outputDimensionality`. gemini-embedding takes one instance per request, the
|
|
17875
|
+
* text-embedding models up to `batchSize` (default 100).
|
|
17876
|
+
*/
|
|
17877
|
+
async embed(request) {
|
|
17878
|
+
const model = requireEmbeddingModel(this.providerName, request.model);
|
|
17879
|
+
const perRequest = request.batchSize ?? (/gemini-embedding/i.test(model) ? 1 : 100);
|
|
17880
|
+
const url = `https://${this.location}-aiplatform.googleapis.com/v1/projects/${this.projectId}/locations/${this.location}/publishers/google/models/${model}:predict`;
|
|
17881
|
+
const taskType = request.inputType ? Object.prototype.hasOwnProperty.call(GEMINI_TASK_TYPES, request.inputType) ? GEMINI_TASK_TYPES[request.inputType] : request.inputType.toUpperCase() : void 0;
|
|
17882
|
+
const vectors = [];
|
|
17883
|
+
const raw = [];
|
|
17884
|
+
let inputTokens = 0;
|
|
17885
|
+
for (const batch of chunkArray(request.input, perRequest)) {
|
|
17886
|
+
const body = {
|
|
17887
|
+
instances: batch.map((content) => ({ content, ...taskType ? { task_type: taskType } : {} }))
|
|
17888
|
+
};
|
|
17889
|
+
const { parameters: extraParameters, ...extraRest } = request.extra ?? {};
|
|
17890
|
+
const parameters = {
|
|
17891
|
+
...request.dimensions != null ? { outputDimensionality: request.dimensions } : {},
|
|
17892
|
+
// Caller-supplied parameters are merged in, not replacing the above (an
|
|
17893
|
+
// explicit extra.parameters.outputDimensionality still wins).
|
|
17894
|
+
...extraParameters && typeof extraParameters === "object" ? extraParameters : {}
|
|
17895
|
+
};
|
|
17896
|
+
if (Object.keys(parameters).length > 0) body.parameters = parameters;
|
|
17897
|
+
Object.assign(body, extraRest);
|
|
17898
|
+
const res = await this.doFetch(url, body, request.signal);
|
|
17899
|
+
const json = await res.json();
|
|
17900
|
+
raw.push(json);
|
|
17901
|
+
for (const p of json.predictions ?? []) {
|
|
17902
|
+
const values = p.embeddings?.values;
|
|
17903
|
+
if (!Array.isArray(values)) {
|
|
17904
|
+
throw new ProviderError("Vertex embeddings response has a prediction without an embeddings.values array", this.providerName, void 0, json);
|
|
17905
|
+
}
|
|
17906
|
+
vectors.push(values);
|
|
17907
|
+
inputTokens += p.embeddings?.statistics?.token_count ?? 0;
|
|
17908
|
+
}
|
|
17909
|
+
}
|
|
17910
|
+
assertVectorCount(this.providerName, vectors, request.input.length);
|
|
17911
|
+
return { model, vectors, usage: { inputTokens, totalTokens: inputTokens }, raw };
|
|
17912
|
+
}
|
|
16661
17913
|
buildUrl(modelId, stream) {
|
|
16662
17914
|
const base = `https://${this.location}-aiplatform.googleapis.com/v1`;
|
|
16663
17915
|
const path2 = `projects/${this.projectId}/locations/${this.location}/publishers/google/models/${modelId}`;
|
|
@@ -16755,7 +18007,9 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16755
18007
|
functionCall: {
|
|
16756
18008
|
name: tc.name,
|
|
16757
18009
|
args: safeJsonParse3(tc.arguments)
|
|
16758
|
-
}
|
|
18010
|
+
},
|
|
18011
|
+
// Gemini 3 requires the signature of each functionCall echoed back.
|
|
18012
|
+
...tc.thoughtSignature ? { thoughtSignature: tc.thoughtSignature } : {}
|
|
16759
18013
|
});
|
|
16760
18014
|
}
|
|
16761
18015
|
return { role: "model", parts: parts2 };
|
|
@@ -16852,7 +18106,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16852
18106
|
sign.update(signingInput);
|
|
16853
18107
|
const signature = sign.sign(sa.private_key, "base64url");
|
|
16854
18108
|
const jwt = `${signingInput}.${signature}`;
|
|
16855
|
-
const tokenRes = await
|
|
18109
|
+
const tokenRes = await this.httpFetch("https://oauth2.googleapis.com/token", {
|
|
16856
18110
|
method: "POST",
|
|
16857
18111
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
16858
18112
|
body: `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${jwt}`
|
|
@@ -16864,17 +18118,22 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16864
18118
|
const tokenJson = await tokenRes.json();
|
|
16865
18119
|
return tokenJson.access_token;
|
|
16866
18120
|
}
|
|
16867
|
-
async doFetch(url, body) {
|
|
18121
|
+
async doFetch(url, body, signal) {
|
|
16868
18122
|
const token = await this.getAccessToken();
|
|
16869
|
-
const
|
|
16870
|
-
|
|
16871
|
-
|
|
16872
|
-
|
|
16873
|
-
|
|
16874
|
-
|
|
16875
|
-
|
|
16876
|
-
|
|
16877
|
-
|
|
18123
|
+
const bodyStr = JSON.stringify(body);
|
|
18124
|
+
const res = await this.doFetchWithRetry(
|
|
18125
|
+
() => this.httpFetch(url, {
|
|
18126
|
+
method: "POST",
|
|
18127
|
+
headers: {
|
|
18128
|
+
"Content-Type": "application/json",
|
|
18129
|
+
Authorization: `Bearer ${token}`,
|
|
18130
|
+
...this.defaultHeaders
|
|
18131
|
+
},
|
|
18132
|
+
body: bodyStr,
|
|
18133
|
+
signal
|
|
18134
|
+
}),
|
|
18135
|
+
signal
|
|
18136
|
+
);
|
|
16878
18137
|
if (!res.ok) {
|
|
16879
18138
|
const text = await res.text().catch(() => "");
|
|
16880
18139
|
throw new ProviderError(
|
|
@@ -16904,7 +18163,8 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16904
18163
|
toolCalls.push({
|
|
16905
18164
|
id: `call_${toolCallIdx++}`,
|
|
16906
18165
|
name: part.functionCall.name,
|
|
16907
|
-
arguments: JSON.stringify(part.functionCall.args ?? {})
|
|
18166
|
+
arguments: JSON.stringify(part.functionCall.args ?? {}),
|
|
18167
|
+
...part.thoughtSignature ? { thoughtSignature: part.thoughtSignature } : {}
|
|
16908
18168
|
});
|
|
16909
18169
|
}
|
|
16910
18170
|
}
|
|
@@ -16925,11 +18185,12 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16925
18185
|
toolCalls,
|
|
16926
18186
|
usage: tokenUsage,
|
|
16927
18187
|
finishReason: mapGeminiFinishReason(candidate?.finishReason),
|
|
18188
|
+
...typeof candidate?.finishReason === "string" ? { rawFinishReason: candidate.finishReason } : {},
|
|
16928
18189
|
reasoning: thoughtParts.length > 0 ? { summary: thoughtParts.join("\n").trim() || void 0 } : void 0,
|
|
16929
18190
|
raw: json
|
|
16930
18191
|
};
|
|
16931
18192
|
}
|
|
16932
|
-
parseStreamChunk(chunk, modelId) {
|
|
18193
|
+
parseStreamChunk(chunk, modelId, counter) {
|
|
16933
18194
|
const candidate = chunk.candidates?.[0];
|
|
16934
18195
|
const parts = candidate?.content?.parts ?? [];
|
|
16935
18196
|
const delta = {};
|
|
@@ -16943,9 +18204,12 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16943
18204
|
} else if (part.functionCall) {
|
|
16944
18205
|
if (!delta.toolCalls) delta.toolCalls = [];
|
|
16945
18206
|
delta.toolCalls.push({
|
|
16946
|
-
|
|
18207
|
+
// Unique across the whole stream: the adapter merges chunks by id.
|
|
18208
|
+
id: `call_${counter.next}`,
|
|
18209
|
+
index: counter.next++,
|
|
16947
18210
|
name: part.functionCall.name,
|
|
16948
|
-
arguments: JSON.stringify(part.functionCall.args ?? {})
|
|
18211
|
+
arguments: JSON.stringify(part.functionCall.args ?? {}),
|
|
18212
|
+
...part.thoughtSignature ? { thoughtSignature: part.thoughtSignature } : {}
|
|
16949
18213
|
});
|
|
16950
18214
|
}
|
|
16951
18215
|
}
|
|
@@ -16967,10 +18231,21 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16967
18231
|
model: modelId,
|
|
16968
18232
|
delta,
|
|
16969
18233
|
usage,
|
|
16970
|
-
finishReason: mapGeminiFinishReason(candidate?.finishReason)
|
|
18234
|
+
finishReason: mapGeminiFinishReason(candidate?.finishReason),
|
|
18235
|
+
...typeof candidate?.finishReason === "string" ? { rawFinishReason: candidate.finishReason } : {}
|
|
16971
18236
|
};
|
|
16972
18237
|
}
|
|
16973
18238
|
};
|
|
18239
|
+
var GEMINI_TASK_TYPES = {
|
|
18240
|
+
search_document: "RETRIEVAL_DOCUMENT",
|
|
18241
|
+
search_query: "RETRIEVAL_QUERY",
|
|
18242
|
+
classification: "CLASSIFICATION",
|
|
18243
|
+
clustering: "CLUSTERING",
|
|
18244
|
+
semantic_similarity: "SEMANTIC_SIMILARITY",
|
|
18245
|
+
question_answering: "QUESTION_ANSWERING",
|
|
18246
|
+
fact_verification: "FACT_VERIFICATION",
|
|
18247
|
+
code_retrieval_query: "CODE_RETRIEVAL_QUERY"
|
|
18248
|
+
};
|
|
16974
18249
|
function mapGeminiFinishReason(reason) {
|
|
16975
18250
|
switch (reason) {
|
|
16976
18251
|
case "STOP":
|
|
@@ -17012,11 +18287,13 @@ function createProvider(config) {
|
|
|
17012
18287
|
return new BedrockProvider(config);
|
|
17013
18288
|
case "vertex":
|
|
17014
18289
|
return new VertexProvider(config);
|
|
18290
|
+
case "jev":
|
|
18291
|
+
return new JevProvider(config);
|
|
17015
18292
|
default:
|
|
17016
18293
|
throw new Error(`Unknown provider: ${config.provider}`);
|
|
17017
18294
|
}
|
|
17018
18295
|
}
|
|
17019
18296
|
|
|
17020
|
-
export { ASK_USER_TOOL_NAME, AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, CCRStore, CONSOLE_HOOK_MAP, CONTEXT_PILOT_JSON_MARKER_KEY, CONTROL_PLANE_TOOL_NAMES, DEFAULT_MAX_TOOL_INPUT_FIELD_CHARS, DEFAULT_PROFILE_CONFIGS, DEFAULT_SKILL_POLICY, DEFAULT_SUBAGENT_POLICY, DEFAULT_SUBAGENT_TOOL_NAMES, DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS, DELEGATION_TOOL_NAMES, DedupTracker, GuardrailPhase, HOOK_CONTRACT_VERSION, HOOK_NAMES, HookTimeoutError, InMemoryMemoryStore, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, PREOPEN_TOOL_CALL_PREFIX, ProviderError, SMALL_TIER_SKILL_POLICY, StructuredOutputManager, TOOL_INPUT_DIGEST_KEY, ToolBasedStrategy, VertexProvider, agentVerdictRule, appendBoundTools, auditLog, azureContentSafety, bedrockGuardrail, budgetGuard, buildHandoffTools, buildResponseFormatSection, buildSkillHeaderBlock, buildSubagentCatalogBlock, buildSystemPrompt, buildToolDefinitionsSection, canOpenSkill, canSpawn, captureSnapshot, checkpointing, codePresenceRule, coerceToolArgs, cognipeerGuardrail, cognipeerSink, collectAttachments, collectToolRetentionDeclarations, composeToolSets, compressDiffOutput, compressJsonOutput, compressLogOutput, compressSearchOutput, compressTextOutput, compressToolOutput, contentToString, conversationHistory, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createBindSkillToolsTool, createCodeGuardrail, createContextPilotRuntime, createContextSummarizeNode, createContextTools, createDelegateTool, createGetToolResponseTool, createGuardrail, createGuardrailPlugin, createJsonGuardrail, createManageTodoListAliasTool, createManageTodoTool, createOpenSkillTool, createParallelTool, createPluginHost, createProvider, createRegexGuardrail, createResolverNode, createSearchSkillsTool, createSkillRegistryRef, createSkillTools, createSmartAgent, createSpawnTool, createSubagentRegistryRef, createSubagentTools, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customGuardrail, customSink, dedupeToolsByName, defaultTokenCounter, defineHook, definePlugin, detectLanguage, detectTextFormat, detectVolatileContent, digestToolInputArguments, digestToolInputValue, emptyUsage, evaluateGuardrails, extractLatestUserQuery,
|
|
18297
|
+
export { ASK_USER_TOOL_NAME, AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, CCRStore, CONSOLE_HOOK_MAP, CONTEXT_PILOT_JSON_MARKER_KEY, CONTROL_PLANE_TOOL_NAMES, DEFAULT_MAX_TOOL_INPUT_FIELD_CHARS, DEFAULT_PROFILE_CONFIGS, DEFAULT_SKILL_POLICY, DEFAULT_SUBAGENT_POLICY, DEFAULT_SUBAGENT_TOOL_NAMES, DEFAULT_TOOL_INPUT_DIGEST_HEAD_CHARS, DELEGATION_TOOL_NAMES, DedupTracker, GuardrailPhase, HOOK_CONTRACT_VERSION, HOOK_NAMES, HookTimeoutError, InMemoryMemoryStore, JevProvider, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, PREOPEN_TOOL_CALL_PREFIX, ProviderError, SMALL_TIER_SKILL_POLICY, StructuredOutputManager, TOOL_INPUT_DIGEST_KEY, ToolBasedStrategy, VertexProvider, agentVerdictRule, appendBoundTools, auditLog, azureContentSafety, bedrockGuardrail, budgetGuard, buildHandoffTools, buildResponseFormatSection, buildSkillHeaderBlock, buildSubagentCatalogBlock, buildSystemPrompt, buildToolDefinitionsSection, canOpenSkill, canSpawn, captureSnapshot, checkpointing, codePresenceRule, coerceToolArgs, cognipeerGuardrail, cognipeerSink, collectAttachments, collectToolRetentionDeclarations, composeToolSets, compressDiffOutput, compressJsonOutput, compressLogOutput, compressSearchOutput, compressTextOutput, compressToolOutput, contentPartToText, contentToString, conversationHistory, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createBindSkillToolsTool, createCodeGuardrail, createContextPilotRuntime, createContextSummarizeNode, createContextTools, createDelegateTool, createGetToolResponseTool, createGuardrail, createGuardrailPlugin, createJsonGuardrail, createManageTodoListAliasTool, createManageTodoTool, createOpenSkillTool, createParallelTool, createPluginHost, createProvider, createRegexGuardrail, createResolverNode, createSearchSkillsTool, createSkillRegistryRef, createSkillTools, createSmartAgent, createSpawnTool, createSubagentRegistryRef, createSubagentTools, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customGuardrail, customSink, dedupeToolsByName, defaultTokenCounter, defineHook, definePlugin, describeContentPart, detectLanguage, detectTextFormat, detectVolatileContent, digestToolInputArguments, digestToolInputValue, emptyUsage, evaluateGuardrails, extractLatestUserQuery, extractMessageText, fileCheckpointStore, fileSink, findSubagent, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasMediaPart, hasToolResponseRecoveryReference, httpGuardrail, httpSink, inMemoryCheckpointStore, inMemoryConversationStore, isHookImplemented, isOpenAIHostedEndpoint, isSmartModel, isValidIban, isValidLuhn, isValidTckn, jsonSchemaRule, defaultBuildPayload as langfuseDefaultPayload, langfuseTracing, languageGuard, loadSkillsFromDisk, mapConsoleHookVerdict, mapTextParts, mcp, mediaKindOf, mediaPolicy, normalizeSmartAgentOptions, normalizeVerdicts, openAIModeration, otelTracing, otlpSink, outputGuard, parseApprovalDecision, parseSkillFrontmatter, pathSandbox, piiRedaction, pluginCapabilities, portkeyGateway, portkeyGuardrail, preopenSkills, preopenToolCallId, prepareStrictToolMenu, promptInjectionGuard, rateLimit, readMemoryFacts, redactText, regexGuardrail, regexRule, replaceTextContent, resolveAvailableSkills, resolveAvailableSubagents, resolveInputRetention, resolveMemoryStore, resolveReasoning, resolveStrategy, resolveSubagentTools, resolveSummarizationRetention, resolveToolApprovalState, resolveUserQuestionState, responseCache, restoreSnapshot, restoreToolCalls, runSmartAgentEvalHarness, scoreItemsByRelevance, searchSkills, seedChildMessages, selectTopIndicesInOrder, sessionMetrics, setTokenCounter, startStreamingSession, summarizeObject, supportsAdaptiveThinking, textFromContent, toMessageUsage, toStrictCompatible, toStrictToolSchema, tokenize, toolPolicy, traceSessionToOtlp, validateReasoningConfig, validateToolArgs, webhookApproval, withTools, withinDepth, writeSummaryFactsToMemory };
|
|
17021
18298
|
//# sourceMappingURL=index.mjs.map
|
|
17022
18299
|
//# sourceMappingURL=index.mjs.map
|