@cognipeer/agent-sdk 0.10.5 → 0.12.0

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