@code-yeongyu/senpi-ai 2026.7.31 → 2026.8.3

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.
Files changed (119) hide show
  1. package/README.md +2 -1
  2. package/dist/api/anthropic-messages.d.ts.map +1 -1
  3. package/dist/api/anthropic-messages.js +56 -25
  4. package/dist/api/anthropic-messages.js.map +1 -1
  5. package/dist/api/anthropic-tool-pairs.d.ts +3 -0
  6. package/dist/api/anthropic-tool-pairs.d.ts.map +1 -0
  7. package/dist/api/anthropic-tool-pairs.js +134 -0
  8. package/dist/api/anthropic-tool-pairs.js.map +1 -0
  9. package/dist/api/azure-openai-responses.d.ts.map +1 -1
  10. package/dist/api/azure-openai-responses.js +7 -3
  11. package/dist/api/azure-openai-responses.js.map +1 -1
  12. package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
  13. package/dist/api/bedrock-converse-stream.js +64 -4
  14. package/dist/api/bedrock-converse-stream.js.map +1 -1
  15. package/dist/api/google-generative-ai.d.ts.map +1 -1
  16. package/dist/api/google-generative-ai.js +12 -2
  17. package/dist/api/google-generative-ai.js.map +1 -1
  18. package/dist/api/google-shared.d.ts.map +1 -1
  19. package/dist/api/google-shared.js +13 -6
  20. package/dist/api/google-shared.js.map +1 -1
  21. package/dist/api/google-vertex.d.ts.map +1 -1
  22. package/dist/api/google-vertex.js +12 -2
  23. package/dist/api/google-vertex.js.map +1 -1
  24. package/dist/api/mistral-conversations.d.ts.map +1 -1
  25. package/dist/api/mistral-conversations.js +19 -10
  26. package/dist/api/mistral-conversations.js.map +1 -1
  27. package/dist/api/openai-codex-responses/fallback-state.d.ts +24 -0
  28. package/dist/api/openai-codex-responses/fallback-state.d.ts.map +1 -0
  29. package/dist/api/openai-codex-responses/fallback-state.js +70 -0
  30. package/dist/api/openai-codex-responses/fallback-state.js.map +1 -0
  31. package/dist/api/openai-codex-responses.d.ts +2 -16
  32. package/dist/api/openai-codex-responses.d.ts.map +1 -1
  33. package/dist/api/openai-codex-responses.js +94 -105
  34. package/dist/api/openai-codex-responses.js.map +1 -1
  35. package/dist/api/openai-completions.d.ts.map +1 -1
  36. package/dist/api/openai-completions.js +19 -10
  37. package/dist/api/openai-completions.js.map +1 -1
  38. package/dist/api/openai-prompt-cache.d.ts +1 -0
  39. package/dist/api/openai-prompt-cache.d.ts.map +1 -1
  40. package/dist/api/openai-prompt-cache.js +7 -0
  41. package/dist/api/openai-prompt-cache.js.map +1 -1
  42. package/dist/api/openai-responses-shared.d.ts.map +1 -1
  43. package/dist/api/openai-responses-shared.js +11 -1
  44. package/dist/api/openai-responses-shared.js.map +1 -1
  45. package/dist/api/openai-responses.d.ts.map +1 -1
  46. package/dist/api/openai-responses.js +9 -5
  47. package/dist/api/openai-responses.js.map +1 -1
  48. package/dist/api/openrouter-images.js +3 -2
  49. package/dist/api/openrouter-images.js.map +1 -1
  50. package/dist/api/pi-messages.js +2 -2
  51. package/dist/api/pi-messages.js.map +1 -1
  52. package/dist/api/simple-options.d.ts.map +1 -1
  53. package/dist/api/simple-options.js +1 -0
  54. package/dist/api/simple-options.js.map +1 -1
  55. package/dist/auth/oauth/openrouter.d.ts +3 -1
  56. package/dist/auth/oauth/openrouter.d.ts.map +1 -1
  57. package/dist/auth/oauth/openrouter.js +81 -26
  58. package/dist/auth/oauth/openrouter.js.map +1 -1
  59. package/dist/auth/resolve.d.ts +2 -0
  60. package/dist/auth/resolve.d.ts.map +1 -1
  61. package/dist/auth/resolve.js +16 -8
  62. package/dist/auth/resolve.js.map +1 -1
  63. package/dist/index.d.ts +1 -0
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +1 -0
  66. package/dist/index.js.map +1 -1
  67. package/dist/model.d.ts +2 -1
  68. package/dist/model.d.ts.map +1 -1
  69. package/dist/model.js.map +1 -1
  70. package/dist/models.d.ts +14 -0
  71. package/dist/models.d.ts.map +1 -1
  72. package/dist/models.js +95 -19
  73. package/dist/models.js.map +1 -1
  74. package/dist/providers/data/.manifest.json +1 -1
  75. package/dist/providers/data/amazon-bedrock.json +1 -1
  76. package/dist/providers/data/azure-openai-responses.json +1 -1
  77. package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  78. package/dist/providers/data/fireworks.json +1 -1
  79. package/dist/providers/data/github-copilot.json +1 -1
  80. package/dist/providers/data/huggingface.json +1 -1
  81. package/dist/providers/data/mistral.json +1 -1
  82. package/dist/providers/data/openai-codex.json +1 -1
  83. package/dist/providers/data/openai.json +1 -1
  84. package/dist/providers/data/opencode-go.json +1 -1
  85. package/dist/providers/data/opencode.json +1 -1
  86. package/dist/providers/data/openrouter.json +1 -1
  87. package/dist/providers/data/qwen-token-plan-cn.json +1 -1
  88. package/dist/providers/data/qwen-token-plan.json +1 -1
  89. package/dist/providers/data/together.json +1 -1
  90. package/dist/providers/data/vercel-ai-gateway.json +1 -1
  91. package/dist/providers/data/zai-coding-cn.json +1 -1
  92. package/dist/providers/data/zai.json +1 -1
  93. package/dist/providers/faux.d.ts.map +1 -1
  94. package/dist/providers/faux.js +4 -1
  95. package/dist/providers/faux.js.map +1 -1
  96. package/dist/providers/opencode-go.js +1 -1
  97. package/dist/providers/opencode-go.js.map +1 -1
  98. package/dist/types.d.ts +18 -1
  99. package/dist/types.d.ts.map +1 -1
  100. package/dist/types.js.map +1 -1
  101. package/dist/utils/error-body.d.ts.map +1 -1
  102. package/dist/utils/error-body.js +23 -4
  103. package/dist/utils/error-body.js.map +1 -1
  104. package/dist/utils/prompt-cache-ttl.d.ts.map +1 -1
  105. package/dist/utils/prompt-cache-ttl.js +10 -1
  106. package/dist/utils/prompt-cache-ttl.js.map +1 -1
  107. package/dist/utils/provider-retry.d.ts +3 -0
  108. package/dist/utils/provider-retry.d.ts.map +1 -1
  109. package/dist/utils/provider-retry.js +13 -12
  110. package/dist/utils/provider-retry.js.map +1 -1
  111. package/dist/utils/retry-hint.d.ts +24 -0
  112. package/dist/utils/retry-hint.d.ts.map +1 -0
  113. package/dist/utils/retry-hint.js +233 -0
  114. package/dist/utils/retry-hint.js.map +1 -0
  115. package/dist/utils/unavailable-tool-text.d.ts +3 -0
  116. package/dist/utils/unavailable-tool-text.d.ts.map +1 -0
  117. package/dist/utils/unavailable-tool-text.js +36 -0
  118. package/dist/utils/unavailable-tool-text.js.map +1 -0
  119. package/package.json +10 -6
package/README.md CHANGED
@@ -874,7 +874,8 @@ for await (const event of s) {
874
874
 
875
875
  Every `AssistantMessage` includes a `stopReason` field that indicates how the generation ended:
876
876
 
877
- - `"stop"` - Normal completion, the model finished its response
877
+ - `"pending"` - Only present in partial messages when we do not know what the stop reason will be
878
+ - `"stop"` - This is the final message the model will produce this turn
878
879
  - `"length"` - Output hit the maximum token limit
879
880
  - `"toolUse"` - Model is calling tools and expects tool results
880
881
  - `"error"` - An error occurred during generation
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-messages.d.ts","sourceRoot":"","sources":["../../src/api/anthropic-messages.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAU1C,OAAO,KAAK,EAWX,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAOb,MAAM,aAAa,CAAC;AA+BrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AA6JlE,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAE1E,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG,SAAS,CAAC;AAoEhE,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACtD;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACnB;AA8zBD,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,oBAAoB,EAAE,gBAAgB,CAqYzE,CAAC;AA0FF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,oBAAoB,EAAE,mBAAmB,CA2ClF,CAAC"}
1
+ {"version":3,"file":"anthropic-messages.d.ts","sourceRoot":"","sources":["../../src/api/anthropic-messages.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAU1C,OAAO,KAAK,EAWX,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAOb,MAAM,aAAa,CAAC;AAiCrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AA6JlE,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAE1E,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG,SAAS,CAAC;AAoEhE,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACtD;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACnB;AA4zBD,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,oBAAoB,EAAE,gBAAgB,CA6ZzE,CAAC;AA0FF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,oBAAoB,EAAE,mBAAmB,CA2ClF,CAAC"}
@@ -9,10 +9,13 @@ import { parseJsonWithRepair, parseStreamingJson } from "../utils/json-parse.js"
9
9
  import { getAnthropicCompat, isAnthropicApiBaseUrl } from "../utils/prompt-cache-ttl.js";
10
10
  import { getProviderEnvValue } from "../utils/provider-env.js";
11
11
  import { retryProviderRequest } from "../utils/provider-retry.js";
12
+ import { appendRetryAfterMsMarker, extract429RetryAfterMs } from "../utils/retry-hint.js";
12
13
  import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
13
14
  import { applyServerFallbackAbort, parseServerFallbackReceipt, parseStickyFallbackReceipt, } from "../utils/server-fallback-receipt.js";
14
15
  import { normalizeToolCallId } from "../utils/tool-call-id.js";
15
16
  import { isForcedToolChoiceUnsupportedError, omitToolChoiceParam } from "../utils/tool-choice-fallback.js";
17
+ import { demotedToolCallText, demotedToolResultText } from "../utils/unavailable-tool-text.js";
18
+ import { sanitizeAnthropicToolPairs } from "./anthropic-tool-pairs.js";
16
19
  import { resolveCloudflareBaseUrl } from "./cloudflare.js";
17
20
  import { resolveJsonSchemaStrictSampling } from "./constrained-sampling.js";
18
21
  import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
@@ -571,6 +574,8 @@ function demoteUnavailableToolReferences(params) {
571
574
  if (demotedCallNames.size === 0 && danglingReferenceNames.size === 0)
572
575
  return params;
573
576
  let changed = false;
577
+ const availableToolNames = [...definedNames];
578
+ const seenDemotedCallNames = new Set();
574
579
  const rewrittenMessages = [];
575
580
  for (const message of messages) {
576
581
  if (!Array.isArray(message.content)) {
@@ -584,7 +589,12 @@ function demoteUnavailableToolReferences(params) {
584
589
  const demotedName = demotedCallNames.get(block.id);
585
590
  if (demotedName !== undefined) {
586
591
  messageChanged = true;
587
- content.push({ type: "text", text: demotedToolCallText(demotedName, block.input) });
592
+ const firstOccurrence = !seenDemotedCallNames.has(demotedName);
593
+ seenDemotedCallNames.add(demotedName);
594
+ content.push({
595
+ type: "text",
596
+ text: demotedToolCallText(demotedName, availableToolNames, firstOccurrence),
597
+ });
588
598
  continue;
589
599
  }
590
600
  }
@@ -592,7 +602,7 @@ function demoteUnavailableToolReferences(params) {
592
602
  const demotedName = demotedCallNames.get(block.tool_use_id);
593
603
  if (demotedName !== undefined) {
594
604
  messageChanged = true;
595
- content.push({ type: "text", text: demotedToolResultText(demotedName, block.content) });
605
+ content.push({ type: "text", text: demotedToolResultText(demotedName, toolResultText(block.content)) });
596
606
  continue;
597
607
  }
598
608
  if (danglingReferenceNames.size > 0 && Array.isArray(block.content)) {
@@ -648,19 +658,6 @@ function collectToolReferenceNames(value, names) {
648
658
  for (const nested of Object.values(value))
649
659
  collectToolReferenceNames(nested, names);
650
660
  }
651
- function demotedToolCallText(name, input) {
652
- let serializedInput;
653
- try {
654
- serializedInput = JSON.stringify(input ?? {});
655
- }
656
- catch {
657
- serializedInput = "{}";
658
- }
659
- return `[Called tool "${name}" (no longer available in this session) with input: ${serializedInput}]`;
660
- }
661
- function demotedToolResultText(name, content) {
662
- return `[Result of unavailable tool "${name}": ${toolResultText(content)}]`;
663
- }
664
661
  function toolResultText(content) {
665
662
  if (typeof content === "string")
666
663
  return content;
@@ -840,7 +837,12 @@ async function* iterateAnthropicEvents(response, signal) {
840
837
  let sawMessageEnd = false;
841
838
  for await (const sse of iterateSseMessages(response.body, signal)) {
842
839
  if (sse.event === "error") {
843
- throw new Error(sse.data);
840
+ let errorText = sse.data;
841
+ const hintMs = extract429RetryAfterMs({ bodyText: sse.data });
842
+ if (hintMs !== undefined) {
843
+ errorText = appendRetryAfterMsMarker(errorText, hintMs);
844
+ }
845
+ throw new Error(errorText);
844
846
  }
845
847
  if (!ANTHROPIC_MESSAGE_EVENTS.has(sse.event ?? "")) {
846
848
  continue;
@@ -881,7 +883,7 @@ export const stream = (model, context, options) => {
881
883
  totalTokens: 0,
882
884
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
883
885
  },
884
- stopReason: "stop",
886
+ stopReason: "pending",
885
887
  timestamp: Date.now(),
886
888
  };
887
889
  const serverFallbackAbort = new AbortController();
@@ -911,7 +913,7 @@ export const stream = (model, context, options) => {
911
913
  }
912
914
  const cacheRetention = resolveCacheRetention(options?.cacheRetention ?? model.cacheRetention, options?.env, "long");
913
915
  const cacheSessionId = cacheRetention === "none" ? undefined : options?.sessionId;
914
- const created = createClient(model, apiKey, options?.interleavedThinking ?? true, shouldUseFineGrainedToolStreamingBeta(model, context), optionsHeaders, copilotDynamicHeaders, cacheSessionId, options?.env);
916
+ const created = createClient(model, apiKey, options?.interleavedThinking ?? true, shouldUseFineGrainedToolStreamingBeta(model, context), optionsHeaders, options?.fetch, copilotDynamicHeaders, cacheSessionId, options?.env);
915
917
  client = created.client;
916
918
  isOAuth = created.isOAuthToken;
917
919
  }
@@ -927,7 +929,7 @@ export const stream = (model, context, options) => {
927
929
  }
928
930
  params = sanitizeAdaptiveThinkingPayload(model, params, options);
929
931
  params = sanitizeUnsupportedNativeTools(model, params);
930
- params = demoteUnavailableToolReferences(params);
932
+ params = sanitizeAnthropicToolPairs(demoteUnavailableToolReferences(params));
931
933
  const payloadRequestMetadata = extractPayloadRequestMetadata(params);
932
934
  params = payloadRequestMetadata.params;
933
935
  const requestOptions = {
@@ -1007,7 +1009,7 @@ export const stream = (model, context, options) => {
1007
1009
  if (event.content_block.type === "text") {
1008
1010
  const block = {
1009
1011
  type: "text",
1010
- text: "",
1012
+ text: event.content_block.text ?? "",
1011
1013
  index: event.index,
1012
1014
  };
1013
1015
  output.content.push(block);
@@ -1016,8 +1018,8 @@ export const stream = (model, context, options) => {
1016
1018
  else if (event.content_block.type === "thinking") {
1017
1019
  const block = {
1018
1020
  type: "thinking",
1019
- thinking: "",
1020
- thinkingSignature: "",
1021
+ thinking: event.content_block.thinking ?? "",
1022
+ thinkingSignature: event.content_block.signature ?? "",
1021
1023
  index: event.index,
1022
1024
  };
1023
1025
  output.content.push(block);
@@ -1159,6 +1161,7 @@ export const stream = (model, context, options) => {
1159
1161
  }
1160
1162
  else if (event.type === "message_delta") {
1161
1163
  if (event.delta.stop_reason) {
1164
+ output.rawStopReason = event.delta.stop_reason;
1162
1165
  const stopReasonResult = mapStopReason(event.delta.stop_reason, event.delta.stop_details);
1163
1166
  output.stopReason = stopReasonResult.stopReason;
1164
1167
  if (stopReasonResult.errorMessage) {
@@ -1204,6 +1207,9 @@ export const stream = (model, context, options) => {
1204
1207
  if (serverFallbackReceipt !== undefined) {
1205
1208
  applyServerFallbackAbort(output, serverFallbackReceipt);
1206
1209
  }
1210
+ if (output.stopReason === "pending") {
1211
+ throw new Error("Anthropic stream ended without a stop reason");
1212
+ }
1207
1213
  if (output.stopReason === "aborted" || output.stopReason === "error") {
1208
1214
  throw new Error(output.errorMessage || "An unknown error occurred");
1209
1215
  }
@@ -1226,7 +1232,24 @@ export const stream = (model, context, options) => {
1226
1232
  delete block.partialJson;
1227
1233
  }
1228
1234
  output.stopReason = options?.signal?.aborted ? "aborted" : "error";
1229
- output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
1235
+ let errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
1236
+ // When a 429 SDK error carries response headers, extract the server's
1237
+ // retry-after hint and append the canonical marker so the orchestration
1238
+ // layer can recover the full delay.
1239
+ if (error instanceof Error && error.status === 429) {
1240
+ const sdkHeaders = error.headers;
1241
+ if (sdkHeaders instanceof Headers) {
1242
+ const hintMs = extract429RetryAfterMs({
1243
+ status: 429,
1244
+ headers: sdkHeaders,
1245
+ bodyText: errorMessage,
1246
+ });
1247
+ if (hintMs !== undefined) {
1248
+ errorMessage = appendRetryAfterMsMarker(errorMessage, hintMs);
1249
+ }
1250
+ }
1251
+ }
1252
+ output.errorMessage = errorMessage;
1230
1253
  stream.push({ type: "error", reason: output.stopReason, error: output });
1231
1254
  stream.end();
1232
1255
  }
@@ -1336,7 +1359,7 @@ export const streamSimple = (model, context, options) => {
1336
1359
  function isOAuthToken(apiKey) {
1337
1360
  return apiKey.includes("sk-ant-oat");
1338
1361
  }
1339
- function createClient(model, apiKey, interleavedThinking, useFineGrainedToolStreamingBeta, optionsHeaders, dynamicHeaders, sessionId, env) {
1362
+ function createClient(model, apiKey, interleavedThinking, useFineGrainedToolStreamingBeta, optionsHeaders, fetch, dynamicHeaders, sessionId, env) {
1340
1363
  // Adaptive thinking models have interleaved thinking built in, so skip the beta header.
1341
1364
  const needsInterleavedBeta = interleavedThinking && !supportsAdaptiveThinking(model);
1342
1365
  const betaFeatures = [];
@@ -1352,6 +1375,7 @@ function createClient(model, apiKey, interleavedThinking, useFineGrainedToolStre
1352
1375
  authToken: null,
1353
1376
  baseURL: resolveCloudflareBaseUrl(model, env),
1354
1377
  dangerouslyAllowBrowser: true,
1378
+ fetch,
1355
1379
  defaultHeaders: sanitizeAdaptiveThinkingHeaders(model, mergeHeaders({
1356
1380
  accept: "application/json",
1357
1381
  "anthropic-dangerous-direct-browser-access": "true",
@@ -1370,6 +1394,7 @@ function createClient(model, apiKey, interleavedThinking, useFineGrainedToolStre
1370
1394
  authToken: apiKey,
1371
1395
  baseURL: model.baseUrl,
1372
1396
  dangerouslyAllowBrowser: true,
1397
+ fetch,
1373
1398
  defaultHeaders: sanitizeAdaptiveThinkingHeaders(model, mergeHeaders({
1374
1399
  accept: "application/json",
1375
1400
  "anthropic-dangerous-direct-browser-access": "true",
@@ -1385,6 +1410,7 @@ function createClient(model, apiKey, interleavedThinking, useFineGrainedToolStre
1385
1410
  authToken: apiKey,
1386
1411
  baseURL: model.baseUrl,
1387
1412
  dangerouslyAllowBrowser: true,
1413
+ fetch,
1388
1414
  defaultHeaders: sanitizeAdaptiveThinkingHeaders(model, mergeHeaders({
1389
1415
  accept: "application/json",
1390
1416
  "anthropic-dangerous-direct-browser-access": "true",
@@ -1402,6 +1428,7 @@ function createClient(model, apiKey, interleavedThinking, useFineGrainedToolStre
1402
1428
  authToken: null,
1403
1429
  baseURL: model.baseUrl,
1404
1430
  dangerouslyAllowBrowser: true,
1431
+ fetch,
1405
1432
  defaultHeaders: sanitizeAdaptiveThinkingHeaders(model, mergeHeaders({
1406
1433
  accept: "application/json",
1407
1434
  "anthropic-dangerous-direct-browser-access": "true",
@@ -1847,7 +1874,11 @@ function mapStopReason(reason, stopDetails) {
1847
1874
  case "stop_sequence":
1848
1875
  return { stopReason: "stop" }; // We don't supply stop sequences, so this should never happen
1849
1876
  case "sensitive": // Content flagged by safety filters (not yet in SDK types)
1850
- return { stopReason: "error", stopDetails: { type: "sensitive" } };
1877
+ return {
1878
+ stopReason: "error",
1879
+ errorMessage: "Provider stopped with: sensitive",
1880
+ stopDetails: { type: "sensitive" },
1881
+ };
1851
1882
  default:
1852
1883
  // Handle unknown stop reasons gracefully (API may add new values)
1853
1884
  throw new Error(`Unhandled stop reason: ${reason}`);