@cognipeer/agent-sdk 0.10.4 → 0.10.6
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/dist/index.cjs +1011 -288
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +846 -659
- package/dist/index.d.ts +846 -659
- package/dist/index.mjs +1006 -288
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -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
|
}
|
|
@@ -2057,50 +2438,63 @@ function fromNativeProvider(provider, options) {
|
|
|
2057
2438
|
modelName,
|
|
2058
2439
|
capabilities: resolveCapabilities(provider.providerName),
|
|
2059
2440
|
invoke: async (messages, _invokeOptions) => {
|
|
2060
|
-
const
|
|
2061
|
-
|
|
2062
|
-
|
|
2441
|
+
const link = linkAbortSignal(_invokeOptions);
|
|
2442
|
+
try {
|
|
2443
|
+
const request = buildRequest(messages, boundTools, options, _invokeOptions);
|
|
2444
|
+
if (link.signal) request.signal = link.signal;
|
|
2445
|
+
const response = await provider.complete(request);
|
|
2446
|
+
return toBaseChatMessage(response);
|
|
2447
|
+
} finally {
|
|
2448
|
+
link.dispose();
|
|
2449
|
+
}
|
|
2063
2450
|
},
|
|
2064
2451
|
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
|
-
|
|
2452
|
+
const link = linkAbortSignal(_invokeOptions);
|
|
2453
|
+
try {
|
|
2454
|
+
const request = buildRequest(messages, boundTools, options, _invokeOptions);
|
|
2455
|
+
request.stream = true;
|
|
2456
|
+
if (link.signal) request.signal = link.signal;
|
|
2457
|
+
let fullContent = "";
|
|
2458
|
+
let allToolCalls = [];
|
|
2459
|
+
let lastUsage;
|
|
2460
|
+
let reasoningBlocks;
|
|
2461
|
+
const toolCallBuffers = /* @__PURE__ */ new Map();
|
|
2462
|
+
for await (const chunk of provider.completeStream(request)) {
|
|
2463
|
+
if (chunk.delta.content) {
|
|
2464
|
+
fullContent += chunk.delta.content;
|
|
2465
|
+
yield chunk.delta.content;
|
|
2466
|
+
}
|
|
2467
|
+
if (chunk.delta.reasoning?.blocks?.length) {
|
|
2468
|
+
reasoningBlocks = chunk.delta.reasoning.blocks;
|
|
2469
|
+
}
|
|
2470
|
+
if (chunk.delta.toolCalls) {
|
|
2471
|
+
for (const tc of chunk.delta.toolCalls) {
|
|
2472
|
+
if (tc.id) {
|
|
2473
|
+
const existing = toolCallBuffers.get(tc.id);
|
|
2474
|
+
if (existing) {
|
|
2475
|
+
if (tc.arguments) existing.arguments += tc.arguments;
|
|
2476
|
+
} else {
|
|
2477
|
+
toolCallBuffers.set(tc.id, {
|
|
2478
|
+
id: tc.id,
|
|
2479
|
+
name: tc.name ?? "",
|
|
2480
|
+
arguments: tc.arguments ?? ""
|
|
2481
|
+
});
|
|
2482
|
+
}
|
|
2092
2483
|
}
|
|
2093
2484
|
}
|
|
2094
2485
|
}
|
|
2486
|
+
if (chunk.usage) lastUsage = chunk.usage;
|
|
2095
2487
|
}
|
|
2096
|
-
if (
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2488
|
+
if (link.signal?.aborted) return;
|
|
2489
|
+
allToolCalls = [...toolCallBuffers.values()];
|
|
2490
|
+
const finalMessage = assembleMessage(fullContent, allToolCalls, lastUsage);
|
|
2491
|
+
if (reasoningBlocks?.length) {
|
|
2492
|
+
finalMessage.reasoning = { blocks: reasoningBlocks };
|
|
2493
|
+
}
|
|
2494
|
+
yield finalMessage;
|
|
2495
|
+
} finally {
|
|
2496
|
+
link.dispose();
|
|
2102
2497
|
}
|
|
2103
|
-
yield finalMessage;
|
|
2104
2498
|
},
|
|
2105
2499
|
bindTools: (tools, _bindOptions) => {
|
|
2106
2500
|
const strict = _bindOptions?.strict ?? false;
|
|
@@ -2563,136 +2957,7 @@ function resolveCapabilities(provider) {
|
|
|
2563
2957
|
|
|
2564
2958
|
// src/smart/toolResponses.ts
|
|
2565
2959
|
init_utilTokens();
|
|
2566
|
-
|
|
2567
|
-
// src/utils/content.ts
|
|
2568
|
-
function contentToString(content) {
|
|
2569
|
-
try {
|
|
2570
|
-
if (content == null) return "";
|
|
2571
|
-
if (typeof content === "string") return content;
|
|
2572
|
-
if (Array.isArray(content)) {
|
|
2573
|
-
return content.map((p) => {
|
|
2574
|
-
if (!p || typeof p !== "object") return String(p);
|
|
2575
|
-
if (p.type === "text") return String(p.text ?? "");
|
|
2576
|
-
if (p.type === "image_url") {
|
|
2577
|
-
const img = p.image_url;
|
|
2578
|
-
const url = typeof img === "string" ? img : img?.url;
|
|
2579
|
-
const detail = typeof img === "string" ? void 0 : img?.detail;
|
|
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
|
-
}
|
|
2960
|
+
init_content();
|
|
2696
2961
|
|
|
2697
2962
|
// src/smart/toolArgCoercion.ts
|
|
2698
2963
|
var PLACEHOLDER_TEXT = /* @__PURE__ */ new Set(["", "null", "undefined", "none", "nil", "n/a", "na"]);
|
|
@@ -3581,6 +3846,7 @@ function detectVolatileContent(text, limit = 20) {
|
|
|
3581
3846
|
|
|
3582
3847
|
// src/smart/contextPilot/jsonCrusher.ts
|
|
3583
3848
|
init_utilTokens();
|
|
3849
|
+
init_content();
|
|
3584
3850
|
var CONTEXT_PILOT_JSON_MARKER_KEY = "__contextPilotDropped";
|
|
3585
3851
|
function findCompressibleArray(output, minItems) {
|
|
3586
3852
|
if (Array.isArray(output)) {
|
|
@@ -3793,6 +4059,7 @@ function compressSearchOutput(text, config, ccrStore) {
|
|
|
3793
4059
|
|
|
3794
4060
|
// src/smart/contextPilot/pipeline.ts
|
|
3795
4061
|
init_utilTokens();
|
|
4062
|
+
init_content();
|
|
3796
4063
|
function createContextPilotRuntime(config) {
|
|
3797
4064
|
return {
|
|
3798
4065
|
ccrStore: new CCRStore({ ttlMs: config.ccr.ttlMs, maxEntries: config.ccr.maxEntries }),
|
|
@@ -4166,6 +4433,8 @@ function createAgentCoreNode(opts) {
|
|
|
4166
4433
|
const streamingEnabled = Boolean(state.ctx?.__streaming);
|
|
4167
4434
|
const cancellationToken = state.ctx?.__cancellationToken;
|
|
4168
4435
|
const abortSignal = state.ctx?.__abortSignal;
|
|
4436
|
+
const onProgress = state.ctx?.__onProgress;
|
|
4437
|
+
const cancelRequested = () => isCancellationRequested({ signal: abortSignal, cancellationToken });
|
|
4169
4438
|
const resolvedForCachePilot = getResolvedSmartConfig(opts, runtime);
|
|
4170
4439
|
if (resolvedForCachePilot.contextPilot.enabled && resolvedForCachePilot.contextPilot.cacheAlignment.enabled) {
|
|
4171
4440
|
const ctxForCacheWarning = state.ctx = state.ctx || {};
|
|
@@ -4321,9 +4590,32 @@ ${append}`;
|
|
|
4321
4590
|
}
|
|
4322
4591
|
return merged;
|
|
4323
4592
|
};
|
|
4324
|
-
let response;
|
|
4325
|
-
let modelAttempt = 0;
|
|
4326
|
-
const maxModelRetries = host?.maxModelRetries ?? 0;
|
|
4593
|
+
let response;
|
|
4594
|
+
let modelAttempt = 0;
|
|
4595
|
+
const maxModelRetries = host?.maxModelRetries ?? 0;
|
|
4596
|
+
const finishCancelledTurn = (partialText) => {
|
|
4597
|
+
const reason = abortSignal?.aborted ? "aborted" : "cancelled";
|
|
4598
|
+
const ctx = state.ctx = state.ctx || {};
|
|
4599
|
+
ctx.__cancelled = { stage: "agent", reason, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
4600
|
+
recordTraceEvent(traceSession, {
|
|
4601
|
+
type: "ai_call",
|
|
4602
|
+
label: "Assistant Cancelled",
|
|
4603
|
+
actor: { scope: "agent", name: actorName, role: "assistant", version: actorVersion },
|
|
4604
|
+
// "skipped", not "error": the call did not fail, the caller ended it —
|
|
4605
|
+
// and an "error" would flip the whole session to error.
|
|
4606
|
+
status: "skipped",
|
|
4607
|
+
durationMs: Date.now() - start,
|
|
4608
|
+
requestBytes: promptBytes,
|
|
4609
|
+
model: getModelName(runtime.model || opts.model),
|
|
4610
|
+
provider: getProviderName(runtime.model || opts.model),
|
|
4611
|
+
messageList: state.messages,
|
|
4612
|
+
toolDefinitions: traceToolDefinitions
|
|
4613
|
+
});
|
|
4614
|
+
onEvent?.({ type: "cancelled", stage: "agent", reason });
|
|
4615
|
+
onProgress?.({ stage: "agent", message: "Cancelled", detail: { reason } });
|
|
4616
|
+
const partial = partialText.trim().length > 0 ? [{ role: "assistant", content: partialText }] : [];
|
|
4617
|
+
return { messages: [...state.messages, ...partial], usage: state.usage };
|
|
4618
|
+
};
|
|
4327
4619
|
while (true) {
|
|
4328
4620
|
start = Date.now();
|
|
4329
4621
|
if (shortCircuited !== void 0) {
|
|
@@ -4339,14 +4631,16 @@ ${append}`;
|
|
|
4339
4631
|
toolDefinitions: traceToolDefinitions
|
|
4340
4632
|
});
|
|
4341
4633
|
} else {
|
|
4634
|
+
let streamedText = "";
|
|
4342
4635
|
try {
|
|
4343
4636
|
const normalizedMessages = normalizeBedrockToolPairing([...wireMessages]);
|
|
4344
4637
|
debugToolPairing(normalizedMessages);
|
|
4345
4638
|
if (streamingEnabled && typeof modelWithTools.stream === "function") {
|
|
4346
|
-
let streamedText = "";
|
|
4347
4639
|
let streamedMessage;
|
|
4640
|
+
let cutByCancel = false;
|
|
4348
4641
|
for await (const chunk of modelWithTools.stream(normalizedMessages, invokeParams)) {
|
|
4349
|
-
if (
|
|
4642
|
+
if (cancelRequested()) {
|
|
4643
|
+
cutByCancel = true;
|
|
4350
4644
|
break;
|
|
4351
4645
|
}
|
|
4352
4646
|
if (chunk && typeof chunk === "object" && chunk.role) {
|
|
@@ -4360,6 +4654,7 @@ ${append}`;
|
|
|
4360
4654
|
onEvent?.({ type: "stream", text });
|
|
4361
4655
|
}
|
|
4362
4656
|
}
|
|
4657
|
+
if (cutByCancel) return finishCancelledTurn(streamedText);
|
|
4363
4658
|
if (streamedMessage) {
|
|
4364
4659
|
response = { ...streamedMessage };
|
|
4365
4660
|
if (response.content == null || response.content === "") {
|
|
@@ -4372,6 +4667,7 @@ ${append}`;
|
|
|
4372
4667
|
response = await modelWithTools.invoke(normalizedMessages, invokeParams);
|
|
4373
4668
|
}
|
|
4374
4669
|
} catch (err) {
|
|
4670
|
+
if (cancelRequested()) return finishCancelledTurn(streamedText);
|
|
4375
4671
|
const durationMs2 = Date.now() - start;
|
|
4376
4672
|
recordTraceEvent(traceSession, {
|
|
4377
4673
|
type: "ai_call",
|
|
@@ -4469,6 +4765,7 @@ ${append}`;
|
|
|
4469
4765
|
}
|
|
4470
4766
|
|
|
4471
4767
|
// src/utils/traceSections.ts
|
|
4768
|
+
init_content();
|
|
4472
4769
|
function truncate(text, max = 500) {
|
|
4473
4770
|
if (!text) return "";
|
|
4474
4771
|
return text.length > max ? `${text.slice(0, max)}\u2026` : text;
|
|
@@ -6359,6 +6656,9 @@ function isCompactedToolContent(content) {
|
|
|
6359
6656
|
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
6657
|
}
|
|
6361
6658
|
|
|
6659
|
+
// src/agent.ts
|
|
6660
|
+
init_content();
|
|
6661
|
+
|
|
6362
6662
|
// src/structuredOutput/manager.ts
|
|
6363
6663
|
var StructuredOutputManager = class {
|
|
6364
6664
|
constructor(schema, strategy, config) {
|
|
@@ -6591,6 +6891,7 @@ function buildSubagentCatalogBlock(subagents, policy, toolNames) {
|
|
|
6591
6891
|
}
|
|
6592
6892
|
|
|
6593
6893
|
// src/plugins/host.ts
|
|
6894
|
+
init_content();
|
|
6594
6895
|
var DEFAULT_PRIORITY = 100;
|
|
6595
6896
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
6596
6897
|
var HOOK_SPECS = {
|
|
@@ -7127,6 +7428,7 @@ function performanceNow() {
|
|
|
7127
7428
|
}
|
|
7128
7429
|
|
|
7129
7430
|
// src/plugins/session.ts
|
|
7431
|
+
init_content();
|
|
7130
7432
|
async function openPluginSession(runHost, params) {
|
|
7131
7433
|
let messages = params.messages;
|
|
7132
7434
|
const startGate = await runHost.runGate("sessionStart", {
|
|
@@ -7596,6 +7898,7 @@ function createAgent(opts) {
|
|
|
7596
7898
|
onProgress?.({ stage: "agent", message: "Invoking model" });
|
|
7597
7899
|
if (cancelIfRequested("before_agent")) break;
|
|
7598
7900
|
state = publish({ ...state, ...await agentCore(state) });
|
|
7901
|
+
if (state.ctx?.__cancelled) break;
|
|
7599
7902
|
onProgress?.({ stage: "agent", message: "Model response received" });
|
|
7600
7903
|
if (checkpointIfRequested("after_agent")) break;
|
|
7601
7904
|
const postGuardrails = getGuardrailConfig(state);
|
|
@@ -7666,7 +7969,7 @@ function createAgent(opts) {
|
|
|
7666
7969
|
if (toolCalls.length === 0) {
|
|
7667
7970
|
if (soManager && !state.ctx?.__finalizedDueToStructuredOutput && !state.ctx?.__structuredOutputForceFinalize && !state.ctx?.__guardrailBlocked) {
|
|
7668
7971
|
if (soManager.strategy.kind === "native") {
|
|
7669
|
-
const assistantText =
|
|
7972
|
+
const assistantText = extractMessageText(lastMsg);
|
|
7670
7973
|
if (assistantText) {
|
|
7671
7974
|
const parsed = soManager.parseFromContent(assistantText);
|
|
7672
7975
|
if (parsed.success) {
|
|
@@ -7722,7 +8025,7 @@ function createAgent(opts) {
|
|
|
7722
8025
|
if (soManager && !state.ctx?.__finalizedDueToStructuredOutput && !structuredFinalizeBlocked) {
|
|
7723
8026
|
const lastForParse = state.messages[state.messages.length - 1];
|
|
7724
8027
|
if (lastForParse?.role === "assistant") {
|
|
7725
|
-
const assistantText =
|
|
8028
|
+
const assistantText = extractMessageText(lastForParse);
|
|
7726
8029
|
if (assistantText) {
|
|
7727
8030
|
const parsed = soManager.parseFromContent(assistantText);
|
|
7728
8031
|
if (parsed.success) {
|
|
@@ -7984,7 +8287,7 @@ function createAgent(opts) {
|
|
|
7984
8287
|
const isTransientSummarizationExit = !!res.ctx?.__needsSummarization;
|
|
7985
8288
|
const finalAssistantMsg = isTransientSummarizationExit ? void 0 : getLastAssistantMessage(res.messages);
|
|
7986
8289
|
const finalIsSyntheticSummary = !isTransientSummarizationExit && finalAssistantMsg && isSyntheticSummaryMessage(finalAssistantMsg);
|
|
7987
|
-
let content = isTransientSummarizationExit || finalIsSyntheticSummary ? "" :
|
|
8290
|
+
let content = isTransientSummarizationExit || finalIsSyntheticSummary ? "" : extractMessageText(finalAssistantMsg);
|
|
7988
8291
|
const finalAnswerBlocked = Boolean(
|
|
7989
8292
|
isTransientSummarizationExit || res.ctx?.__awaitingApproval || res.ctx?.__awaitingUserQuestion || res.ctx?.__cancelled || res.ctx?.__paused || res.ctx?.__limitBreached
|
|
7990
8293
|
);
|
|
@@ -8243,9 +8546,11 @@ function createAgentNode(opts) {
|
|
|
8243
8546
|
|
|
8244
8547
|
// src/nodes/contextSummarize.ts
|
|
8245
8548
|
init_utilTokens();
|
|
8549
|
+
init_content();
|
|
8246
8550
|
|
|
8247
8551
|
// src/smart/contextPolicy.ts
|
|
8248
8552
|
init_utilTokens();
|
|
8553
|
+
init_content();
|
|
8249
8554
|
function collectRecentTurns(messages, lastTurnsToKeep) {
|
|
8250
8555
|
if (lastTurnsToKeep <= 0) return [];
|
|
8251
8556
|
const systemPrefix = messages.filter((message, index) => index === 0 && message.role === "system");
|
|
@@ -8307,7 +8612,7 @@ function isClampProtected(message, index, firstUserIndex) {
|
|
|
8307
8612
|
function clampToBudget(messages, maxContextTokens) {
|
|
8308
8613
|
let working = [...messages];
|
|
8309
8614
|
while (working.length > 2) {
|
|
8310
|
-
const tokenCount = countApproxTokens(working.map(
|
|
8615
|
+
const tokenCount = countApproxTokens(working.map(extractMessageText).join("\n"));
|
|
8311
8616
|
if (tokenCount <= maxContextTokens) return working;
|
|
8312
8617
|
const firstUserIndex = working.findIndex((message) => message.role === "user");
|
|
8313
8618
|
const firstNonSystem = working.findIndex((message, index) => !isClampProtected(message, index, firstUserIndex));
|
|
@@ -8647,7 +8952,7 @@ function createContextSummarizeNode(opts) {
|
|
|
8647
8952
|
let content = "";
|
|
8648
8953
|
if (typeof m.content === "string") content = m.content;
|
|
8649
8954
|
else if (Array.isArray(m.content)) {
|
|
8650
|
-
content = m.content.map((c) => c
|
|
8955
|
+
content = m.content.map((c) => contentPartToText(c, (part) => JSON.stringify(part))).join(" ");
|
|
8651
8956
|
}
|
|
8652
8957
|
if (m.role === "tool" && isSummarizedToolPlaceholder(content)) {
|
|
8653
8958
|
const historyEntry = findToolHistoryEntry(state, m.tool_call_id, m.name);
|
|
@@ -9492,6 +9797,9 @@ async function writeSummaryFactsToMemory(store, config, summary, sourceTurn) {
|
|
|
9492
9797
|
return store.get(config.memory.scope, { limit: config.context.lastTurnsToKeep + summary.stable_facts.length });
|
|
9493
9798
|
}
|
|
9494
9799
|
|
|
9800
|
+
// src/smart/index.ts
|
|
9801
|
+
init_content();
|
|
9802
|
+
|
|
9495
9803
|
// src/smart/skills/types.ts
|
|
9496
9804
|
var DEFAULT_SKILL_POLICY = {
|
|
9497
9805
|
maxOpenSkills: 4,
|
|
@@ -10506,7 +10814,7 @@ function createSmartAgent(opts) {
|
|
|
10506
10814
|
].join("\n");
|
|
10507
10815
|
function latestUserPrompt(messages) {
|
|
10508
10816
|
const latest = [...messages].reverse().find((message) => message.role === "user");
|
|
10509
|
-
return latest ?
|
|
10817
|
+
return latest ? extractMessageText(latest) : "";
|
|
10510
10818
|
}
|
|
10511
10819
|
async function syncMemory(state) {
|
|
10512
10820
|
const query = latestUserPrompt(state.messages || []);
|
|
@@ -11217,6 +11525,132 @@ async function runSmartAgentEvalHarness(params) {
|
|
|
11217
11525
|
}
|
|
11218
11526
|
return results;
|
|
11219
11527
|
}
|
|
11528
|
+
|
|
11529
|
+
// src/providers/base.ts
|
|
11530
|
+
var DEFAULT_RETRY = {
|
|
11531
|
+
maxRetries: 3,
|
|
11532
|
+
baseDelayMs: 500,
|
|
11533
|
+
maxDelayMs: 8e3
|
|
11534
|
+
};
|
|
11535
|
+
var BaseProvider = class {
|
|
11536
|
+
constructor() {
|
|
11537
|
+
this.retryPolicy = DEFAULT_RETRY;
|
|
11538
|
+
}
|
|
11539
|
+
/**
|
|
11540
|
+
* Helper concrete providers can wrap their fetch with. Retries 429/5xx
|
|
11541
|
+
* with exponential backoff and respects Retry-After if the response
|
|
11542
|
+
* carries one.
|
|
11543
|
+
*
|
|
11544
|
+
* `signal` is the call's cancellation: a run that is cancelled while the
|
|
11545
|
+
* provider is backing off must not sit out the delay, nor start another attempt.
|
|
11546
|
+
*/
|
|
11547
|
+
async doFetchWithRetry(execute, signal) {
|
|
11548
|
+
const policy = this.retryPolicy;
|
|
11549
|
+
const maxRetries = Math.max(0, policy.maxRetries ?? DEFAULT_RETRY.maxRetries);
|
|
11550
|
+
const baseDelay = Math.max(0, policy.baseDelayMs ?? DEFAULT_RETRY.baseDelayMs);
|
|
11551
|
+
const maxDelay = Math.max(baseDelay, policy.maxDelayMs ?? DEFAULT_RETRY.maxDelayMs);
|
|
11552
|
+
let lastResp;
|
|
11553
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
11554
|
+
if (signal?.aborted) throw abortReason(signal);
|
|
11555
|
+
const res = await execute();
|
|
11556
|
+
const isRetryable = res.status === 429 || res.status >= 500 && res.status < 600;
|
|
11557
|
+
if (!isRetryable) return res;
|
|
11558
|
+
const predicate = policy.shouldRetry;
|
|
11559
|
+
if (predicate && !predicate({ status: res.status }, attempt)) return res;
|
|
11560
|
+
if (attempt === maxRetries) {
|
|
11561
|
+
lastResp = res;
|
|
11562
|
+
break;
|
|
11563
|
+
}
|
|
11564
|
+
const retryAfter = res.headers.get("retry-after");
|
|
11565
|
+
let delay2 = Math.min(maxDelay, baseDelay * Math.pow(2, attempt));
|
|
11566
|
+
if (retryAfter) {
|
|
11567
|
+
const asNumber = Number(retryAfter);
|
|
11568
|
+
if (!Number.isNaN(asNumber)) delay2 = Math.min(maxDelay, Math.max(delay2, asNumber * 1e3));
|
|
11569
|
+
}
|
|
11570
|
+
try {
|
|
11571
|
+
await res.text();
|
|
11572
|
+
} catch {
|
|
11573
|
+
}
|
|
11574
|
+
await abortableSleep(delay2, signal);
|
|
11575
|
+
}
|
|
11576
|
+
return lastResp;
|
|
11577
|
+
}
|
|
11578
|
+
};
|
|
11579
|
+
|
|
11580
|
+
// src/providers/types.ts
|
|
11581
|
+
function emptyUsage() {
|
|
11582
|
+
return {
|
|
11583
|
+
inputTokens: 0,
|
|
11584
|
+
outputTokens: 0,
|
|
11585
|
+
totalTokens: 0,
|
|
11586
|
+
cachedInputTokens: 0,
|
|
11587
|
+
cachedWriteTokens: 0,
|
|
11588
|
+
cachedOutputTokens: 0,
|
|
11589
|
+
reasoningTokens: 0
|
|
11590
|
+
};
|
|
11591
|
+
}
|
|
11592
|
+
var ProviderError = class extends Error {
|
|
11593
|
+
constructor(message, provider, statusCode, responseBody) {
|
|
11594
|
+
super(message);
|
|
11595
|
+
this.provider = provider;
|
|
11596
|
+
this.statusCode = statusCode;
|
|
11597
|
+
this.responseBody = responseBody;
|
|
11598
|
+
this.name = "ProviderError";
|
|
11599
|
+
}
|
|
11600
|
+
};
|
|
11601
|
+
|
|
11602
|
+
// src/providers/jev.ts
|
|
11603
|
+
var JEV_DEFAULT_BASE_URL = "https://api.typesafe.ai";
|
|
11604
|
+
var JevProvider = class extends BaseProvider {
|
|
11605
|
+
constructor(config) {
|
|
11606
|
+
super();
|
|
11607
|
+
this.providerName = "jev";
|
|
11608
|
+
this.apiKey = config.apiKey;
|
|
11609
|
+
this.baseURL = (config.baseURL ?? JEV_DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
11610
|
+
this.defaultModel = config.defaultModel;
|
|
11611
|
+
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
11612
|
+
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
11613
|
+
}
|
|
11614
|
+
/** Ask System One questions about `state`. */
|
|
11615
|
+
async systemOne(request, options) {
|
|
11616
|
+
const model = request.model ?? this.defaultModel;
|
|
11617
|
+
const body = {
|
|
11618
|
+
...model ? { model } : {},
|
|
11619
|
+
state: request.state,
|
|
11620
|
+
questions: request.questions
|
|
11621
|
+
};
|
|
11622
|
+
const res = await this.doFetchWithRetry(
|
|
11623
|
+
() => fetch(`${this.baseURL}/v1/systemone`, {
|
|
11624
|
+
method: "POST",
|
|
11625
|
+
headers: {
|
|
11626
|
+
"Content-Type": "application/json",
|
|
11627
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
11628
|
+
...this.defaultHeaders
|
|
11629
|
+
},
|
|
11630
|
+
body: JSON.stringify(body),
|
|
11631
|
+
signal: options?.signal
|
|
11632
|
+
})
|
|
11633
|
+
);
|
|
11634
|
+
if (!res.ok) {
|
|
11635
|
+
const text = await res.text().catch(() => "");
|
|
11636
|
+
throw new ProviderError(`Jev API error ${res.status}: ${text}`, this.providerName, res.status, text);
|
|
11637
|
+
}
|
|
11638
|
+
return await res.json();
|
|
11639
|
+
}
|
|
11640
|
+
async complete(_request) {
|
|
11641
|
+
throw new ProviderError(
|
|
11642
|
+
'Jev is a decision model and has no chat completion; use systemOne() or agentVerdictRule({ engine: "jev" })',
|
|
11643
|
+
this.providerName
|
|
11644
|
+
);
|
|
11645
|
+
}
|
|
11646
|
+
// eslint-disable-next-line require-yield
|
|
11647
|
+
async *completeStream(_request) {
|
|
11648
|
+
throw new ProviderError("Jev does not stream; use systemOne()", this.providerName);
|
|
11649
|
+
}
|
|
11650
|
+
};
|
|
11651
|
+
|
|
11652
|
+
// src/guardrails/checks.ts
|
|
11653
|
+
init_content();
|
|
11220
11654
|
var Ajv = AjvModule?.default ?? AjvModule;
|
|
11221
11655
|
var defaultAjv = new Ajv({ allErrors: true });
|
|
11222
11656
|
defaultAjv.opts.strict = false;
|
|
@@ -11366,14 +11800,82 @@ function defaultPayload(context) {
|
|
|
11366
11800
|
2
|
|
11367
11801
|
);
|
|
11368
11802
|
}
|
|
11803
|
+
var DEFAULT_JEV_THRESHOLD = 0.5;
|
|
11804
|
+
var JEV_QUESTION_KEY = "shouldBlock";
|
|
11805
|
+
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.";
|
|
11806
|
+
var DEFAULT_JEV_CRITERIA = {
|
|
11807
|
+
true: "The payload is unsafe, non-compliant, or otherwise warrants blocking.",
|
|
11808
|
+
false: "The payload is benign and the agent should be allowed to continue."
|
|
11809
|
+
};
|
|
11810
|
+
function resolveJevClient(config) {
|
|
11811
|
+
if (config.client) return config.client;
|
|
11812
|
+
const apiKey = config.apiKey ?? process.env.TYPESAFE_API_KEY;
|
|
11813
|
+
if (!apiKey) {
|
|
11814
|
+
throw new Error(
|
|
11815
|
+
"Jev engine requires an API key: pass `jev.apiKey`, set TYPESAFE_API_KEY, or pass a `jev.client`."
|
|
11816
|
+
);
|
|
11817
|
+
}
|
|
11818
|
+
return new JevProvider({
|
|
11819
|
+
provider: "jev",
|
|
11820
|
+
apiKey,
|
|
11821
|
+
baseURL: config.baseURL ?? process.env.TYPESAFE_BASE_URL
|
|
11822
|
+
});
|
|
11823
|
+
}
|
|
11369
11824
|
function agentVerdictRule(options) {
|
|
11370
11825
|
const payloadBuilder = options.payloadBuilder || defaultPayload;
|
|
11371
11826
|
const fallbackDisposition = options.dispositionFallback || "block";
|
|
11827
|
+
const engine = options.engine || "llm";
|
|
11828
|
+
const jevOptions = options.jev || {};
|
|
11829
|
+
const jevThreshold = typeof jevOptions.threshold === "number" ? jevOptions.threshold : DEFAULT_JEV_THRESHOLD;
|
|
11830
|
+
let jevClient;
|
|
11831
|
+
async function evaluateWithJev(context) {
|
|
11832
|
+
const client = jevClient ?? (jevClient = resolveJevClient(jevOptions));
|
|
11833
|
+
const instructions = jevOptions.question ? jevOptions.question(context) : DEFAULT_JEV_QUESTION;
|
|
11834
|
+
const result = await client.systemOne({
|
|
11835
|
+
state: payloadBuilder(context),
|
|
11836
|
+
questions: {
|
|
11837
|
+
[JEV_QUESTION_KEY]: {
|
|
11838
|
+
type: "noul",
|
|
11839
|
+
instructions,
|
|
11840
|
+
criteria: jevOptions.criteria ?? DEFAULT_JEV_CRITERIA
|
|
11841
|
+
}
|
|
11842
|
+
},
|
|
11843
|
+
...jevOptions.model ? { model: jevOptions.model } : {}
|
|
11844
|
+
});
|
|
11845
|
+
const answer = result?.answers?.[JEV_QUESTION_KEY];
|
|
11846
|
+
const probability = typeof answer?.noul === "number" ? answer.noul : void 0;
|
|
11847
|
+
if (probability === void 0) {
|
|
11848
|
+
return {
|
|
11849
|
+
passed: false,
|
|
11850
|
+
disposition: fallbackDisposition,
|
|
11851
|
+
reason: "Jev engine did not return a noul probability.",
|
|
11852
|
+
details: { jevModel: result?.model, jevUsage: result?.usage }
|
|
11853
|
+
};
|
|
11854
|
+
}
|
|
11855
|
+
const passed = probability < jevThreshold;
|
|
11856
|
+
return {
|
|
11857
|
+
passed,
|
|
11858
|
+
disposition: passed ? "allow" : fallbackDisposition,
|
|
11859
|
+
reason: passed ? void 0 : `Jev risk probability ${probability.toFixed(3)} met or exceeded threshold ${jevThreshold}.`,
|
|
11860
|
+
details: {
|
|
11861
|
+
jevProbability: probability,
|
|
11862
|
+
jevThreshold,
|
|
11863
|
+
jevModel: result?.model,
|
|
11864
|
+
jevUsage: result?.usage
|
|
11865
|
+
}
|
|
11866
|
+
};
|
|
11867
|
+
}
|
|
11372
11868
|
return {
|
|
11373
11869
|
id: options.id,
|
|
11374
11870
|
title: options.title || "Agent-based guardrail",
|
|
11375
11871
|
description: options.description,
|
|
11376
11872
|
async evaluate(context) {
|
|
11873
|
+
if (engine === "jev") {
|
|
11874
|
+
return evaluateWithJev(context);
|
|
11875
|
+
}
|
|
11876
|
+
if (!options.agent) {
|
|
11877
|
+
throw new Error("agentVerdictRule requires an `agent` when using the default 'llm' engine.");
|
|
11878
|
+
}
|
|
11377
11879
|
const payload = payloadBuilder(context);
|
|
11378
11880
|
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
11881
|
const review = await options.agent.invoke({
|
|
@@ -11589,6 +12091,7 @@ function isHookImplemented(hook) {
|
|
|
11589
12091
|
}
|
|
11590
12092
|
|
|
11591
12093
|
// src/plugins/builtin/guardrail.ts
|
|
12094
|
+
init_content();
|
|
11592
12095
|
var ALLOW = { action: "allow" };
|
|
11593
12096
|
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
|
|
11594
12097
|
var RetryableGuardrailError = class extends Error {
|
|
@@ -11875,7 +12378,7 @@ function createGuardrailPlugin(options) {
|
|
|
11875
12378
|
return { decision: "deny", reason: verdict.message ?? "Request blocked by guardrail policy." };
|
|
11876
12379
|
},
|
|
11877
12380
|
postModelCall: async ({ message }, ctx) => {
|
|
11878
|
-
const text =
|
|
12381
|
+
const text = extractMessageText(message);
|
|
11879
12382
|
if (!text) return void 0;
|
|
11880
12383
|
const verdict = await check({ phase: "output", content: text, hook: "postModelCall" }, ctx);
|
|
11881
12384
|
if (!raiseIfFailed(verdict, ctx) || verdict.action === "allow") return void 0;
|
|
@@ -12145,6 +12648,7 @@ function portkeyGuardrail(config = {}) {
|
|
|
12145
12648
|
}
|
|
12146
12649
|
|
|
12147
12650
|
// src/plugins/builtin/piiRedaction.ts
|
|
12651
|
+
init_content();
|
|
12148
12652
|
function isValidTckn(value) {
|
|
12149
12653
|
const digits = value.replace(/\D/g, "");
|
|
12150
12654
|
if (digits.length !== 11 || digits[0] === "0") return false;
|
|
@@ -12264,7 +12768,7 @@ function piiRedaction(config = {}) {
|
|
|
12264
12768
|
},
|
|
12265
12769
|
postModelCall: ({ message }, ctx) => {
|
|
12266
12770
|
if (!applied.has("modelOutput")) return void 0;
|
|
12267
|
-
const text =
|
|
12771
|
+
const text = extractMessageText(message);
|
|
12268
12772
|
if (!text) return void 0;
|
|
12269
12773
|
const result = redactText(text, detectors, mask);
|
|
12270
12774
|
if (result.findings.length === 0) return void 0;
|
|
@@ -14671,74 +15175,8 @@ function languageGuard(config) {
|
|
|
14671
15175
|
};
|
|
14672
15176
|
}
|
|
14673
15177
|
|
|
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
|
-
};
|
|
15178
|
+
// src/index.ts
|
|
15179
|
+
init_content();
|
|
14742
15180
|
|
|
14743
15181
|
// src/providers/utils/sse.ts
|
|
14744
15182
|
async function* parseSSEStream(body, signal) {
|
|
@@ -14747,7 +15185,7 @@ async function* parseSSEStream(body, signal) {
|
|
|
14747
15185
|
let buffer = "";
|
|
14748
15186
|
try {
|
|
14749
15187
|
while (true) {
|
|
14750
|
-
if (signal?.aborted) ;
|
|
15188
|
+
if (signal?.aborted) throw abortReason(signal);
|
|
14751
15189
|
const { done, value } = await reader.read();
|
|
14752
15190
|
if (done) break;
|
|
14753
15191
|
buffer += decoder.decode(value, { stream: true });
|
|
@@ -14764,6 +15202,7 @@ async function* parseSSEStream(body, signal) {
|
|
|
14764
15202
|
if (event) yield event;
|
|
14765
15203
|
}
|
|
14766
15204
|
} finally {
|
|
15205
|
+
reader.cancel().catch(() => void 0);
|
|
14767
15206
|
reader.releaseLock();
|
|
14768
15207
|
}
|
|
14769
15208
|
}
|
|
@@ -14981,8 +15420,127 @@ function sanitizeBedrockDocName(name, fallback = "document") {
|
|
|
14981
15420
|
return cleaned || fallback;
|
|
14982
15421
|
}
|
|
14983
15422
|
|
|
15423
|
+
// src/providers/utils/jsonSchemaRefs.ts
|
|
15424
|
+
var DEFINITION_KEYS = ["definitions", "$defs"];
|
|
15425
|
+
function inlineJsonSchemaRefs(schema) {
|
|
15426
|
+
if (!isObject2(schema) || !containsRef(schema)) return schema;
|
|
15427
|
+
const root = structuredClone(schema);
|
|
15428
|
+
const selfReaching = /* @__PURE__ */ new Map();
|
|
15429
|
+
const targetOf = (ref) => {
|
|
15430
|
+
const target = resolvePointer(root, ref);
|
|
15431
|
+
return isObject2(target) ? target : void 0;
|
|
15432
|
+
};
|
|
15433
|
+
const reachesItself = (target) => {
|
|
15434
|
+
const known = selfReaching.get(target);
|
|
15435
|
+
if (known !== void 0) return known;
|
|
15436
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15437
|
+
const walk = (node) => {
|
|
15438
|
+
if (Array.isArray(node)) return node.some(walk);
|
|
15439
|
+
if (!isObject2(node)) return false;
|
|
15440
|
+
if (typeof node.$ref === "string") {
|
|
15441
|
+
const next = targetOf(node.$ref);
|
|
15442
|
+
if (next === target) return true;
|
|
15443
|
+
if (next && !seen.has(next)) {
|
|
15444
|
+
seen.add(next);
|
|
15445
|
+
if (walk(next)) return true;
|
|
15446
|
+
}
|
|
15447
|
+
}
|
|
15448
|
+
return Object.entries(node).some(([key, value]) => key !== "$ref" && walk(value));
|
|
15449
|
+
};
|
|
15450
|
+
const result2 = walk(target);
|
|
15451
|
+
selfReaching.set(target, result2);
|
|
15452
|
+
return result2;
|
|
15453
|
+
};
|
|
15454
|
+
const keptRefs = /* @__PURE__ */ new Set();
|
|
15455
|
+
const expand = (node) => {
|
|
15456
|
+
if (Array.isArray(node)) return node.map(expand);
|
|
15457
|
+
if (!isObject2(node)) return node;
|
|
15458
|
+
if (typeof node.$ref === "string") {
|
|
15459
|
+
const target = targetOf(node.$ref);
|
|
15460
|
+
if (target && !reachesItself(target)) {
|
|
15461
|
+
const { $ref: _inlined, ...siblings } = node;
|
|
15462
|
+
return { ...expand(target), ...expandEntries(siblings) };
|
|
15463
|
+
}
|
|
15464
|
+
keptRefs.add(node.$ref);
|
|
15465
|
+
return expandEntries(node);
|
|
15466
|
+
}
|
|
15467
|
+
return expandEntries(node);
|
|
15468
|
+
};
|
|
15469
|
+
const expandEntries = (node) => {
|
|
15470
|
+
const out = {};
|
|
15471
|
+
for (const [key, value] of Object.entries(node)) out[key] = key === "$ref" ? value : expand(value);
|
|
15472
|
+
return out;
|
|
15473
|
+
};
|
|
15474
|
+
const { definitions: _definitions, $defs: _defs, ...rootBody } = root;
|
|
15475
|
+
const result = typeof root.$ref === "string" ? expand(rootBody) : expandEntries(rootBody);
|
|
15476
|
+
for (const key of DEFINITION_KEYS) delete result[key];
|
|
15477
|
+
for (const key of DEFINITION_KEYS) {
|
|
15478
|
+
const block = root[key];
|
|
15479
|
+
if (!isObject2(block)) continue;
|
|
15480
|
+
const needed = neededEntries(key, block, keptRefs);
|
|
15481
|
+
if (needed.length === 0) continue;
|
|
15482
|
+
const kept = {};
|
|
15483
|
+
for (const name of Object.keys(block)) if (needed.includes(name)) kept[name] = block[name];
|
|
15484
|
+
result[key] = kept;
|
|
15485
|
+
}
|
|
15486
|
+
return result;
|
|
15487
|
+
}
|
|
15488
|
+
function neededEntries(key, block, keptRefs) {
|
|
15489
|
+
const needed = [];
|
|
15490
|
+
const queue = [...keptRefs];
|
|
15491
|
+
while (queue.length > 0) {
|
|
15492
|
+
const ref = queue.shift();
|
|
15493
|
+
const segments = pointerSegments(ref);
|
|
15494
|
+
if (!segments || segments[0] !== key || segments.length < 2) continue;
|
|
15495
|
+
const name = segments[1];
|
|
15496
|
+
if (needed.includes(name) || !(name in block)) continue;
|
|
15497
|
+
needed.push(name);
|
|
15498
|
+
collectRefs(block[name], queue);
|
|
15499
|
+
}
|
|
15500
|
+
return needed;
|
|
15501
|
+
}
|
|
15502
|
+
function collectRefs(node, into) {
|
|
15503
|
+
if (Array.isArray(node)) {
|
|
15504
|
+
node.forEach((child) => collectRefs(child, into));
|
|
15505
|
+
return;
|
|
15506
|
+
}
|
|
15507
|
+
if (!isObject2(node)) return;
|
|
15508
|
+
if (typeof node.$ref === "string") into.push(node.$ref);
|
|
15509
|
+
for (const [k, value] of Object.entries(node)) if (k !== "$ref") collectRefs(value, into);
|
|
15510
|
+
}
|
|
15511
|
+
function containsRef(node) {
|
|
15512
|
+
if (Array.isArray(node)) return node.some(containsRef);
|
|
15513
|
+
if (!isObject2(node)) return false;
|
|
15514
|
+
if (typeof node.$ref === "string") return true;
|
|
15515
|
+
return Object.values(node).some(containsRef);
|
|
15516
|
+
}
|
|
15517
|
+
function pointerSegments(ref) {
|
|
15518
|
+
if (ref === "#") return [];
|
|
15519
|
+
if (!ref.startsWith("#/")) return null;
|
|
15520
|
+
return ref.slice(2).split("/").map((segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
15521
|
+
}
|
|
15522
|
+
function resolvePointer(document, ref) {
|
|
15523
|
+
const segments = pointerSegments(ref);
|
|
15524
|
+
if (!segments) return void 0;
|
|
15525
|
+
let current = document;
|
|
15526
|
+
for (const segment of segments) {
|
|
15527
|
+
if (Array.isArray(current)) {
|
|
15528
|
+
if (!/^\d+$/.test(segment)) return void 0;
|
|
15529
|
+
current = current[Number(segment)];
|
|
15530
|
+
} else if (isObject2(current) && Object.prototype.hasOwnProperty.call(current, segment)) {
|
|
15531
|
+
current = current[segment];
|
|
15532
|
+
} else {
|
|
15533
|
+
return void 0;
|
|
15534
|
+
}
|
|
15535
|
+
}
|
|
15536
|
+
return current;
|
|
15537
|
+
}
|
|
15538
|
+
function isObject2(value) {
|
|
15539
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15540
|
+
}
|
|
15541
|
+
|
|
14984
15542
|
// src/providers/openai.ts
|
|
14985
|
-
var OpenAIProvider = class extends BaseProvider {
|
|
15543
|
+
var OpenAIProvider = class _OpenAIProvider extends BaseProvider {
|
|
14986
15544
|
constructor(config) {
|
|
14987
15545
|
super();
|
|
14988
15546
|
this.providerName = "openai";
|
|
@@ -14994,8 +15552,21 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
14994
15552
|
...config.organization ? { "OpenAI-Organization": config.organization } : {}
|
|
14995
15553
|
};
|
|
14996
15554
|
this.responsesApi = config.responsesApi ?? "auto";
|
|
15555
|
+
const ownInstance = new.target === _OpenAIProvider;
|
|
15556
|
+
this.responsesApiModels = ownInstance ? [...config.responsesApiModels ?? []] : [];
|
|
15557
|
+
this.responsesStreaming = ownInstance && config.responsesStreaming === true;
|
|
14997
15558
|
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
14998
15559
|
}
|
|
15560
|
+
/** True when the caller listed this request's model in `responsesApiModels`. */
|
|
15561
|
+
isResponsesApiModel(request) {
|
|
15562
|
+
if (this.responsesApiModels.length === 0) return false;
|
|
15563
|
+
const model = request.model || this.defaultModel;
|
|
15564
|
+
return this.responsesApiModels.some((entry) => {
|
|
15565
|
+
if (typeof entry === "string") return entry === model;
|
|
15566
|
+
entry.lastIndex = 0;
|
|
15567
|
+
return entry.test(model);
|
|
15568
|
+
});
|
|
15569
|
+
}
|
|
14999
15570
|
/** True when this request should go to the Responses API rather than Chat
|
|
15000
15571
|
* Completions — which exposes `reasoning.effort` and reasoning summaries that
|
|
15001
15572
|
* Chat Completions silently drops.
|
|
@@ -15004,10 +15575,14 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15004
15575
|
* carries a reasoning config AND the model name looks like an o-series/gpt-5
|
|
15005
15576
|
* model. `never`/`always` let a caller state the answer instead, because the
|
|
15006
15577
|
* name check is a guess and the two APIs differ in far more than reasoning —
|
|
15007
|
-
* see `responsesApi` in OpenAIProviderConfig.
|
|
15578
|
+
* see `responsesApi` in OpenAIProviderConfig.
|
|
15579
|
+
*
|
|
15580
|
+
* A model listed in `responsesApiModels` is the caller stating the answer
|
|
15581
|
+
* for that model alone; `never` still overrides it. */
|
|
15008
15582
|
useResponsesApi(request) {
|
|
15009
15583
|
if (this.responsesApi === "never") return false;
|
|
15010
15584
|
if (this.responsesApi === "always") return true;
|
|
15585
|
+
if (this.isResponsesApiModel(request)) return true;
|
|
15011
15586
|
if (!request.reasoning) return false;
|
|
15012
15587
|
return isReasoningModel(request.model || this.defaultModel);
|
|
15013
15588
|
}
|
|
@@ -15016,12 +15591,16 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15016
15591
|
return this.completeResponses(request);
|
|
15017
15592
|
}
|
|
15018
15593
|
const body = this.buildRequestBody(request, false);
|
|
15019
|
-
const res = await this.doFetch(body);
|
|
15594
|
+
const res = await this.doFetch(body, request.signal);
|
|
15020
15595
|
const json = await res.json();
|
|
15021
15596
|
return this.parseResponse(json);
|
|
15022
15597
|
}
|
|
15023
15598
|
async *completeStream(request) {
|
|
15024
15599
|
if (this.useResponsesApi(request)) {
|
|
15600
|
+
if (this.responsesStreaming && this.isResponsesApiModel(request)) {
|
|
15601
|
+
yield* this.streamResponses(request);
|
|
15602
|
+
return;
|
|
15603
|
+
}
|
|
15025
15604
|
const response = await this.completeResponses(request);
|
|
15026
15605
|
yield {
|
|
15027
15606
|
id: response.id,
|
|
@@ -15037,13 +15616,13 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15037
15616
|
return;
|
|
15038
15617
|
}
|
|
15039
15618
|
const body = this.buildRequestBody(request, true);
|
|
15040
|
-
const res = await this.doFetch(body);
|
|
15619
|
+
const res = await this.doFetch(body, request.signal);
|
|
15041
15620
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
15042
15621
|
let id = "";
|
|
15043
15622
|
let model = "";
|
|
15044
15623
|
const toolCallBuffers = /* @__PURE__ */ new Map();
|
|
15045
15624
|
let usage;
|
|
15046
|
-
for await (const event of parseSSEStream(res.body)) {
|
|
15625
|
+
for await (const event of parseSSEStream(res.body, request.signal)) {
|
|
15047
15626
|
if (event.data === "[DONE]") break;
|
|
15048
15627
|
let chunk;
|
|
15049
15628
|
try {
|
|
@@ -15137,10 +15716,101 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15137
15716
|
// ─── Responses API (reasoning models) ──────────────────────────────────────
|
|
15138
15717
|
async completeResponses(request) {
|
|
15139
15718
|
const body = this.buildResponsesBody(request);
|
|
15140
|
-
|
|
15719
|
+
if (this.isResponsesApiModel(request)) adaptChatExtrasForResponses(body, request.extra);
|
|
15720
|
+
const res = await this.responsesFetch(body, request.signal);
|
|
15141
15721
|
const json = await res.json();
|
|
15142
15722
|
return this.parseResponsesResponse(json, request.model || this.defaultModel);
|
|
15143
15723
|
}
|
|
15724
|
+
/** Real Responses SSE streaming, for models opted in through
|
|
15725
|
+
* `responsesApiModels` with `responsesStreaming` on. Emits the same chunk
|
|
15726
|
+
* shapes as the Chat Completions stream: text deltas as they arrive, a tool
|
|
15727
|
+
* call's id + name when it opens and its argument fragments under that id,
|
|
15728
|
+
* then one final chunk with usage, finish reason and any reasoning summary
|
|
15729
|
+
* (taken from the completed response, exactly as the non-streaming parse
|
|
15730
|
+
* reads it). */
|
|
15731
|
+
async *streamResponses(request) {
|
|
15732
|
+
const modelId = request.model || this.defaultModel;
|
|
15733
|
+
const body = this.buildResponsesBody(request);
|
|
15734
|
+
adaptChatExtrasForResponses(body, request.extra);
|
|
15735
|
+
body.stream = true;
|
|
15736
|
+
const res = await this.responsesFetch(body, request.signal);
|
|
15737
|
+
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
15738
|
+
let id = "";
|
|
15739
|
+
let model = modelId;
|
|
15740
|
+
const calls = /* @__PURE__ */ new Map();
|
|
15741
|
+
let final;
|
|
15742
|
+
for await (const event of parseSSEStream(res.body, request.signal)) {
|
|
15743
|
+
if (event.data === "[DONE]") break;
|
|
15744
|
+
let data;
|
|
15745
|
+
try {
|
|
15746
|
+
data = JSON.parse(event.data);
|
|
15747
|
+
} catch {
|
|
15748
|
+
continue;
|
|
15749
|
+
}
|
|
15750
|
+
switch (data.type ?? event.event) {
|
|
15751
|
+
case "response.created":
|
|
15752
|
+
case "response.in_progress":
|
|
15753
|
+
id = data.response?.id ?? id;
|
|
15754
|
+
model = data.response?.model ?? model;
|
|
15755
|
+
break;
|
|
15756
|
+
case "response.output_text.delta":
|
|
15757
|
+
if (data.delta) yield { id, model, delta: { content: data.delta } };
|
|
15758
|
+
break;
|
|
15759
|
+
case "response.output_item.added": {
|
|
15760
|
+
const item = data.item;
|
|
15761
|
+
if (item?.type !== "function_call") break;
|
|
15762
|
+
const call = { callId: item.call_id ?? item.id ?? "", name: item.name ?? "", arguments: item.arguments ?? "" };
|
|
15763
|
+
calls.set(item.id ?? call.callId, call);
|
|
15764
|
+
yield { id, model, delta: { toolCalls: [{ id: call.callId, name: call.name, arguments: call.arguments }] } };
|
|
15765
|
+
break;
|
|
15766
|
+
}
|
|
15767
|
+
case "response.function_call_arguments.delta": {
|
|
15768
|
+
const call = calls.get(data.item_id);
|
|
15769
|
+
if (!call || !data.delta) break;
|
|
15770
|
+
call.arguments += data.delta;
|
|
15771
|
+
yield { id, model, delta: { toolCalls: [{ id: call.callId, arguments: data.delta }] } };
|
|
15772
|
+
break;
|
|
15773
|
+
}
|
|
15774
|
+
case "response.output_item.done": {
|
|
15775
|
+
const item = data.item;
|
|
15776
|
+
if (item?.type !== "function_call") break;
|
|
15777
|
+
const full = typeof item.arguments === "string" ? item.arguments : "";
|
|
15778
|
+
const call = calls.get(item.id ?? item.call_id);
|
|
15779
|
+
if (!call) {
|
|
15780
|
+
const added = { callId: item.call_id ?? item.id ?? "", name: item.name ?? "", arguments: full };
|
|
15781
|
+
calls.set(item.id ?? added.callId, added);
|
|
15782
|
+
yield { id, model, delta: { toolCalls: [{ id: added.callId, name: added.name, arguments: full }] } };
|
|
15783
|
+
} else if (full.length > call.arguments.length && full.startsWith(call.arguments)) {
|
|
15784
|
+
const rest = full.slice(call.arguments.length);
|
|
15785
|
+
call.arguments = full;
|
|
15786
|
+
yield { id, model, delta: { toolCalls: [{ id: call.callId, arguments: rest }] } };
|
|
15787
|
+
}
|
|
15788
|
+
break;
|
|
15789
|
+
}
|
|
15790
|
+
case "response.completed":
|
|
15791
|
+
case "response.incomplete":
|
|
15792
|
+
final = this.parseResponsesResponse(data.response ?? {}, modelId);
|
|
15793
|
+
break;
|
|
15794
|
+
case "response.failed":
|
|
15795
|
+
case "error": {
|
|
15796
|
+
const err = data.response?.error ?? data.error ?? data;
|
|
15797
|
+
throw new ProviderError(
|
|
15798
|
+
`OpenAI Responses API stream error: ${err?.message ?? "unknown error"}`,
|
|
15799
|
+
this.providerName,
|
|
15800
|
+
void 0,
|
|
15801
|
+
data
|
|
15802
|
+
);
|
|
15803
|
+
}
|
|
15804
|
+
}
|
|
15805
|
+
}
|
|
15806
|
+
yield {
|
|
15807
|
+
id: final?.id || id,
|
|
15808
|
+
model: final?.model || model,
|
|
15809
|
+
delta: final?.reasoning ? { reasoning: final.reasoning } : {},
|
|
15810
|
+
usage: final?.usage,
|
|
15811
|
+
finishReason: final?.finishReason ?? (calls.size > 0 ? "tool_calls" : "stop")
|
|
15812
|
+
};
|
|
15813
|
+
}
|
|
15144
15814
|
buildResponsesBody(request) {
|
|
15145
15815
|
const body = {
|
|
15146
15816
|
model: request.model || this.defaultModel,
|
|
@@ -15170,7 +15840,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15170
15840
|
format: {
|
|
15171
15841
|
type: "json_schema",
|
|
15172
15842
|
name: request.responseFormat.name ?? "response",
|
|
15173
|
-
schema: request.responseFormat.schema,
|
|
15843
|
+
schema: inlineJsonSchemaRefs(request.responseFormat.schema),
|
|
15174
15844
|
strict: true
|
|
15175
15845
|
}
|
|
15176
15846
|
};
|
|
@@ -15237,7 +15907,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15237
15907
|
});
|
|
15238
15908
|
return { role, content };
|
|
15239
15909
|
}
|
|
15240
|
-
async responsesFetch(body) {
|
|
15910
|
+
async responsesFetch(body, signal) {
|
|
15241
15911
|
body.input = expandResponsesInput(body.input);
|
|
15242
15912
|
const url = `${this.baseURL}/responses`;
|
|
15243
15913
|
const headers = {
|
|
@@ -15246,7 +15916,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15246
15916
|
...this.defaultHeaders
|
|
15247
15917
|
};
|
|
15248
15918
|
const payload = JSON.stringify(body);
|
|
15249
|
-
const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload }));
|
|
15919
|
+
const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload, signal }), signal);
|
|
15250
15920
|
if (!res.ok) {
|
|
15251
15921
|
const text = await res.text().catch(() => "");
|
|
15252
15922
|
throw new ProviderError(
|
|
@@ -15367,7 +16037,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15367
16037
|
}
|
|
15368
16038
|
return { type: "function", function: fn };
|
|
15369
16039
|
}
|
|
15370
|
-
async doFetch(body) {
|
|
16040
|
+
async doFetch(body, signal) {
|
|
15371
16041
|
const url = `${this.baseURL}/chat/completions`;
|
|
15372
16042
|
const headers = {
|
|
15373
16043
|
"Content-Type": "application/json",
|
|
@@ -15375,7 +16045,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
15375
16045
|
...this.defaultHeaders
|
|
15376
16046
|
};
|
|
15377
16047
|
const payload = JSON.stringify(body);
|
|
15378
|
-
const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload }));
|
|
16048
|
+
const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload, signal }), signal);
|
|
15379
16049
|
if (!res.ok) {
|
|
15380
16050
|
const text = await res.text().catch(() => "");
|
|
15381
16051
|
throw new ProviderError(
|
|
@@ -15425,6 +16095,48 @@ function isReasoningModel(model) {
|
|
|
15425
16095
|
const m = model.toLowerCase();
|
|
15426
16096
|
return /(^|[/_-])o[0-9]/.test(m) || m.startsWith("o1") || m.startsWith("o3") || m.startsWith("o4") || m.includes("gpt-5") || m.includes("gpt5");
|
|
15427
16097
|
}
|
|
16098
|
+
function adaptChatExtrasForResponses(body, extra) {
|
|
16099
|
+
const native = extra ?? {};
|
|
16100
|
+
if ("reasoning_effort" in body) {
|
|
16101
|
+
const effort = body.reasoning_effort;
|
|
16102
|
+
delete body.reasoning_effort;
|
|
16103
|
+
if (effort != null) {
|
|
16104
|
+
const reasoning = body.reasoning && typeof body.reasoning === "object" ? body.reasoning : {};
|
|
16105
|
+
if (reasoning.effort == null) body.reasoning = { ...reasoning, effort };
|
|
16106
|
+
}
|
|
16107
|
+
}
|
|
16108
|
+
for (const key of ["max_tokens", "max_completion_tokens"]) {
|
|
16109
|
+
if (!(key in body)) continue;
|
|
16110
|
+
const value = body[key];
|
|
16111
|
+
delete body[key];
|
|
16112
|
+
if (value != null && !("max_output_tokens" in native)) body.max_output_tokens = value;
|
|
16113
|
+
}
|
|
16114
|
+
if ("response_format" in body) {
|
|
16115
|
+
const format = toResponsesTextFormat(body.response_format);
|
|
16116
|
+
delete body.response_format;
|
|
16117
|
+
if (format && !("text" in native)) body.text = { ...body.text, format };
|
|
16118
|
+
}
|
|
16119
|
+
if (body.stream_options && typeof body.stream_options === "object" && "include_usage" in body.stream_options) {
|
|
16120
|
+
const { include_usage: _dropped, ...rest } = body.stream_options;
|
|
16121
|
+
if (Object.keys(rest).length > 0) body.stream_options = rest;
|
|
16122
|
+
else delete body.stream_options;
|
|
16123
|
+
}
|
|
16124
|
+
}
|
|
16125
|
+
function toResponsesTextFormat(rf) {
|
|
16126
|
+
if (!rf || typeof rf !== "object") return void 0;
|
|
16127
|
+
if (rf.type === "json_schema") {
|
|
16128
|
+
const js = rf.json_schema ?? {};
|
|
16129
|
+
return {
|
|
16130
|
+
type: "json_schema",
|
|
16131
|
+
name: js.name ?? "response",
|
|
16132
|
+
schema: inlineJsonSchemaRefs(js.schema),
|
|
16133
|
+
...js.description != null ? { description: js.description } : {},
|
|
16134
|
+
...js.strict != null ? { strict: js.strict } : {}
|
|
16135
|
+
};
|
|
16136
|
+
}
|
|
16137
|
+
if (rf.type === "json_object" || rf.type === "text") return { type: rf.type };
|
|
16138
|
+
return void 0;
|
|
16139
|
+
}
|
|
15428
16140
|
function expandResponsesInput(input) {
|
|
15429
16141
|
const out = [];
|
|
15430
16142
|
for (const item of input) {
|
|
@@ -15469,13 +16181,13 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
15469
16181
|
}
|
|
15470
16182
|
async complete(request) {
|
|
15471
16183
|
const body = this.buildRequestBody(request, false);
|
|
15472
|
-
const res = await this.doFetch(body);
|
|
16184
|
+
const res = await this.doFetch(body, request.signal);
|
|
15473
16185
|
const json = await res.json();
|
|
15474
16186
|
return this.parseResponse(json);
|
|
15475
16187
|
}
|
|
15476
16188
|
async *completeStream(request) {
|
|
15477
16189
|
const body = this.buildRequestBody(request, true);
|
|
15478
|
-
const res = await this.doFetch(body);
|
|
16190
|
+
const res = await this.doFetch(body, request.signal);
|
|
15479
16191
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
15480
16192
|
let id = "";
|
|
15481
16193
|
let model = "";
|
|
@@ -15485,7 +16197,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
15485
16197
|
let cacheCreationInputTokens = 0;
|
|
15486
16198
|
const currentToolCalls = /* @__PURE__ */ new Map();
|
|
15487
16199
|
const reasoningBlocks = /* @__PURE__ */ new Map();
|
|
15488
|
-
for await (const event of parseSSEStream(res.body)) {
|
|
16200
|
+
for await (const event of parseSSEStream(res.body, request.signal)) {
|
|
15489
16201
|
let data;
|
|
15490
16202
|
try {
|
|
15491
16203
|
data = JSON.parse(event.data);
|
|
@@ -15765,7 +16477,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
15765
16477
|
input_schema: t.parameters
|
|
15766
16478
|
};
|
|
15767
16479
|
}
|
|
15768
|
-
async doFetch(body) {
|
|
16480
|
+
async doFetch(body, signal) {
|
|
15769
16481
|
const url = `${this.baseURL}/v1/messages`;
|
|
15770
16482
|
const headers = {
|
|
15771
16483
|
"Content-Type": "application/json",
|
|
@@ -15774,7 +16486,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
15774
16486
|
...this.defaultHeaders
|
|
15775
16487
|
};
|
|
15776
16488
|
const payload = JSON.stringify(body);
|
|
15777
|
-
const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload }));
|
|
16489
|
+
const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload, signal }), signal);
|
|
15778
16490
|
if (!res.ok) {
|
|
15779
16491
|
const text = await res.text().catch(() => "");
|
|
15780
16492
|
throw new ProviderError(
|
|
@@ -15884,7 +16596,7 @@ var AzureProvider = class extends OpenAIProvider {
|
|
|
15884
16596
|
this.deploymentName = config.deploymentName;
|
|
15885
16597
|
this.azureApiKey = config.apiKey;
|
|
15886
16598
|
}
|
|
15887
|
-
async doFetch(body) {
|
|
16599
|
+
async doFetch(body, signal) {
|
|
15888
16600
|
const deployment = this.deploymentName ?? body.model;
|
|
15889
16601
|
if (!deployment) {
|
|
15890
16602
|
throw new ProviderError("Azure requires a deploymentName or model", this.providerName);
|
|
@@ -15898,7 +16610,8 @@ var AzureProvider = class extends OpenAIProvider {
|
|
|
15898
16610
|
"api-key": this.azureApiKey,
|
|
15899
16611
|
...this.defaultHeaders
|
|
15900
16612
|
},
|
|
15901
|
-
body: JSON.stringify(bodyWithoutModel)
|
|
16613
|
+
body: JSON.stringify(bodyWithoutModel),
|
|
16614
|
+
signal
|
|
15902
16615
|
});
|
|
15903
16616
|
if (!res.ok) {
|
|
15904
16617
|
const text = await res.text().catch(() => "");
|
|
@@ -15914,7 +16627,7 @@ var AzureProvider = class extends OpenAIProvider {
|
|
|
15914
16627
|
/** Azure exposes the Responses API at /openai/responses with api-key auth.
|
|
15915
16628
|
* Reasoning summaries require a preview api-version; callers can override via
|
|
15916
16629
|
* the `apiVersion` config. */
|
|
15917
|
-
async responsesFetch(body) {
|
|
16630
|
+
async responsesFetch(body, signal) {
|
|
15918
16631
|
body.input = expandAzureResponsesInput(body.input);
|
|
15919
16632
|
const deployment = this.deploymentName ?? body.model;
|
|
15920
16633
|
if (!deployment) {
|
|
@@ -15929,7 +16642,8 @@ var AzureProvider = class extends OpenAIProvider {
|
|
|
15929
16642
|
"api-key": this.azureApiKey,
|
|
15930
16643
|
...this.defaultHeaders
|
|
15931
16644
|
},
|
|
15932
|
-
body: payload
|
|
16645
|
+
body: payload,
|
|
16646
|
+
signal
|
|
15933
16647
|
});
|
|
15934
16648
|
if (!res.ok) {
|
|
15935
16649
|
const text = await res.text().catch(() => "");
|
|
@@ -15997,7 +16711,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
15997
16711
|
async complete(request) {
|
|
15998
16712
|
const modelId = request.model || this.defaultModel;
|
|
15999
16713
|
const body = this.buildConverseBody(request);
|
|
16000
|
-
const json = await this.doFetch(modelId, body);
|
|
16714
|
+
const json = await this.doFetch(modelId, body, request.signal);
|
|
16001
16715
|
return this.parseResponse(json, modelId);
|
|
16002
16716
|
}
|
|
16003
16717
|
async *completeStream(request) {
|
|
@@ -16174,7 +16888,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
16174
16888
|
}
|
|
16175
16889
|
};
|
|
16176
16890
|
}
|
|
16177
|
-
async doFetch(modelId, body) {
|
|
16891
|
+
async doFetch(modelId, body, signal) {
|
|
16178
16892
|
const host = `bedrock-runtime.${this.region}.amazonaws.com`;
|
|
16179
16893
|
const url = `https://${host}/model/${encodeURIComponent(modelId)}/converse`;
|
|
16180
16894
|
const bodyStr = JSON.stringify(body);
|
|
@@ -16192,8 +16906,8 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
16192
16906
|
service: "bedrock",
|
|
16193
16907
|
credentials: this.credentials
|
|
16194
16908
|
});
|
|
16195
|
-
return fetch(url, { method: "POST", headers, body: bodyStr });
|
|
16196
|
-
});
|
|
16909
|
+
return fetch(url, { method: "POST", headers, body: bodyStr, signal });
|
|
16910
|
+
}, signal);
|
|
16197
16911
|
if (!res.ok) {
|
|
16198
16912
|
const text = await res.text().catch(() => "");
|
|
16199
16913
|
throw new ProviderError(
|
|
@@ -16326,7 +17040,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16326
17040
|
const modelId = request.model || this.defaultModel;
|
|
16327
17041
|
const body = this.buildGeminiBody(request);
|
|
16328
17042
|
const url = this.buildUrl(modelId, false);
|
|
16329
|
-
const res = await this.doFetch(url, body);
|
|
17043
|
+
const res = await this.doFetch(url, body, request.signal);
|
|
16330
17044
|
const json = await res.json();
|
|
16331
17045
|
return this.parseResponse(json, modelId);
|
|
16332
17046
|
}
|
|
@@ -16334,11 +17048,11 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16334
17048
|
const modelId = request.model || this.defaultModel;
|
|
16335
17049
|
const body = this.buildGeminiBody(request);
|
|
16336
17050
|
const url = this.buildUrl(modelId, true);
|
|
16337
|
-
const res = await this.doFetch(url, body);
|
|
17051
|
+
const res = await this.doFetch(url, body, request.signal);
|
|
16338
17052
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
16339
17053
|
const contentType = res.headers.get("content-type") ?? "";
|
|
16340
17054
|
if (contentType.includes("text/event-stream")) {
|
|
16341
|
-
for await (const event of parseSSEStream(res.body)) {
|
|
17055
|
+
for await (const event of parseSSEStream(res.body, request.signal)) {
|
|
16342
17056
|
if (event.data === "[DONE]") break;
|
|
16343
17057
|
let chunk;
|
|
16344
17058
|
try {
|
|
@@ -16380,6 +17094,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16380
17094
|
}
|
|
16381
17095
|
}
|
|
16382
17096
|
} finally {
|
|
17097
|
+
reader.cancel().catch(() => void 0);
|
|
16383
17098
|
reader.releaseLock();
|
|
16384
17099
|
}
|
|
16385
17100
|
}
|
|
@@ -16591,7 +17306,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16591
17306
|
const tokenJson = await tokenRes.json();
|
|
16592
17307
|
return tokenJson.access_token;
|
|
16593
17308
|
}
|
|
16594
|
-
async doFetch(url, body) {
|
|
17309
|
+
async doFetch(url, body, signal) {
|
|
16595
17310
|
const token = await this.getAccessToken();
|
|
16596
17311
|
const res = await fetch(url, {
|
|
16597
17312
|
method: "POST",
|
|
@@ -16600,7 +17315,8 @@ var VertexProvider = class extends BaseProvider {
|
|
|
16600
17315
|
Authorization: `Bearer ${token}`,
|
|
16601
17316
|
...this.defaultHeaders
|
|
16602
17317
|
},
|
|
16603
|
-
body: JSON.stringify(body)
|
|
17318
|
+
body: JSON.stringify(body),
|
|
17319
|
+
signal
|
|
16604
17320
|
});
|
|
16605
17321
|
if (!res.ok) {
|
|
16606
17322
|
const text = await res.text().catch(() => "");
|
|
@@ -16739,11 +17455,13 @@ function createProvider(config) {
|
|
|
16739
17455
|
return new BedrockProvider(config);
|
|
16740
17456
|
case "vertex":
|
|
16741
17457
|
return new VertexProvider(config);
|
|
17458
|
+
case "jev":
|
|
17459
|
+
return new JevProvider(config);
|
|
16742
17460
|
default:
|
|
16743
17461
|
throw new Error(`Unknown provider: ${config.provider}`);
|
|
16744
17462
|
}
|
|
16745
17463
|
}
|
|
16746
17464
|
|
|
16747
|
-
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,
|
|
17465
|
+
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, textFromContent, toStrictCompatible, toStrictToolSchema, tokenize, toolPolicy, traceSessionToOtlp, validateReasoningConfig, validateToolArgs, webhookApproval, withTools, withinDepth, writeSummaryFactsToMemory };
|
|
16748
17466
|
//# sourceMappingURL=index.mjs.map
|
|
16749
17467
|
//# sourceMappingURL=index.mjs.map
|