@caupulican/pi-ai 0.81.39 → 0.81.41

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 (126) hide show
  1. package/dist/env-api-keys.d.ts +5 -0
  2. package/dist/env-api-keys.d.ts.map +1 -1
  3. package/dist/env-api-keys.js +20 -4
  4. package/dist/env-api-keys.js.map +1 -1
  5. package/dist/image-models.generated.d.ts +15 -0
  6. package/dist/image-models.generated.d.ts.map +1 -1
  7. package/dist/image-models.generated.js +15 -0
  8. package/dist/image-models.generated.js.map +1 -1
  9. package/dist/index.d.ts +3 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +3 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/models.d.ts +7 -0
  14. package/dist/models.d.ts.map +1 -1
  15. package/dist/models.generated.d.ts +1847 -423
  16. package/dist/models.generated.d.ts.map +1 -1
  17. package/dist/models.generated.js +1511 -500
  18. package/dist/models.generated.js.map +1 -1
  19. package/dist/models.js +9 -0
  20. package/dist/models.js.map +1 -1
  21. package/dist/providers/amazon-bedrock.d.ts.map +1 -1
  22. package/dist/providers/amazon-bedrock.js +135 -79
  23. package/dist/providers/amazon-bedrock.js.map +1 -1
  24. package/dist/providers/anthropic.d.ts.map +1 -1
  25. package/dist/providers/anthropic.js +79 -42
  26. package/dist/providers/anthropic.js.map +1 -1
  27. package/dist/providers/azure-openai-responses.d.ts.map +1 -1
  28. package/dist/providers/azure-openai-responses.js +13 -6
  29. package/dist/providers/azure-openai-responses.js.map +1 -1
  30. package/dist/providers/bedrock-sso.d.ts +6 -0
  31. package/dist/providers/bedrock-sso.d.ts.map +1 -0
  32. package/dist/providers/bedrock-sso.js +39 -0
  33. package/dist/providers/bedrock-sso.js.map +1 -0
  34. package/dist/providers/faux.d.ts +1 -0
  35. package/dist/providers/faux.d.ts.map +1 -1
  36. package/dist/providers/faux.js +1 -0
  37. package/dist/providers/faux.js.map +1 -1
  38. package/dist/providers/images/openrouter.d.ts.map +1 -1
  39. package/dist/providers/images/openrouter.js +8 -3
  40. package/dist/providers/images/openrouter.js.map +1 -1
  41. package/dist/providers/mistral.d.ts.map +1 -1
  42. package/dist/providers/mistral.js +20 -15
  43. package/dist/providers/mistral.js.map +1 -1
  44. package/dist/providers/openai-codex-account.d.ts +32 -0
  45. package/dist/providers/openai-codex-account.d.ts.map +1 -0
  46. package/dist/providers/openai-codex-account.js +157 -0
  47. package/dist/providers/openai-codex-account.js.map +1 -0
  48. package/dist/providers/openai-codex-auth.d.ts +11 -0
  49. package/dist/providers/openai-codex-auth.d.ts.map +1 -0
  50. package/dist/providers/openai-codex-auth.js +43 -0
  51. package/dist/providers/openai-codex-auth.js.map +1 -0
  52. package/dist/providers/openai-codex-responses.d.ts +1 -0
  53. package/dist/providers/openai-codex-responses.d.ts.map +1 -1
  54. package/dist/providers/openai-codex-responses.js +97 -72
  55. package/dist/providers/openai-codex-responses.js.map +1 -1
  56. package/dist/providers/openai-completions.d.ts.map +1 -1
  57. package/dist/providers/openai-completions.js +35 -15
  58. package/dist/providers/openai-completions.js.map +1 -1
  59. package/dist/providers/openai-responses-shared.d.ts +5 -0
  60. package/dist/providers/openai-responses-shared.d.ts.map +1 -1
  61. package/dist/providers/openai-responses-shared.js +42 -5
  62. package/dist/providers/openai-responses-shared.js.map +1 -1
  63. package/dist/providers/openai-responses.d.ts +1 -0
  64. package/dist/providers/openai-responses.d.ts.map +1 -1
  65. package/dist/providers/openai-responses.js +28 -9
  66. package/dist/providers/openai-responses.js.map +1 -1
  67. package/dist/providers/openrouter-cache.d.ts +3 -0
  68. package/dist/providers/openrouter-cache.d.ts.map +1 -0
  69. package/dist/providers/openrouter-cache.js +4 -0
  70. package/dist/providers/openrouter-cache.js.map +1 -0
  71. package/dist/providers/simple-options.d.ts.map +1 -1
  72. package/dist/providers/simple-options.js +2 -0
  73. package/dist/providers/simple-options.js.map +1 -1
  74. package/dist/stream.d.ts.map +1 -1
  75. package/dist/stream.js +12 -4
  76. package/dist/stream.js.map +1 -1
  77. package/dist/types.d.ts +27 -4
  78. package/dist/types.d.ts.map +1 -1
  79. package/dist/types.js.map +1 -1
  80. package/dist/utils/abort-signals.d.ts +1 -0
  81. package/dist/utils/abort-signals.d.ts.map +1 -1
  82. package/dist/utils/abort-signals.js +7 -2
  83. package/dist/utils/abort-signals.js.map +1 -1
  84. package/dist/utils/error-body.d.ts.map +1 -1
  85. package/dist/utils/error-body.js +8 -3
  86. package/dist/utils/error-body.js.map +1 -1
  87. package/dist/utils/oauth/index.d.ts +3 -0
  88. package/dist/utils/oauth/index.d.ts.map +1 -1
  89. package/dist/utils/oauth/index.js +9 -0
  90. package/dist/utils/oauth/index.js.map +1 -1
  91. package/dist/utils/oauth/kimi-coding.d.ts +5 -0
  92. package/dist/utils/oauth/kimi-coding.d.ts.map +1 -0
  93. package/dist/utils/oauth/kimi-coding.js +173 -0
  94. package/dist/utils/oauth/kimi-coding.js.map +1 -0
  95. package/dist/utils/oauth/openai-codex.d.ts.map +1 -1
  96. package/dist/utils/oauth/openai-codex.js +2 -21
  97. package/dist/utils/oauth/openai-codex.js.map +1 -1
  98. package/dist/utils/oauth/openrouter.d.ts +5 -0
  99. package/dist/utils/oauth/openrouter.d.ts.map +1 -0
  100. package/dist/utils/oauth/openrouter.js +197 -0
  101. package/dist/utils/oauth/openrouter.js.map +1 -0
  102. package/dist/utils/oauth/xai.d.ts +6 -0
  103. package/dist/utils/oauth/xai.d.ts.map +1 -0
  104. package/dist/utils/oauth/xai.js +154 -0
  105. package/dist/utils/oauth/xai.js.map +1 -0
  106. package/dist/utils/overflow.d.ts +1 -0
  107. package/dist/utils/overflow.d.ts.map +1 -1
  108. package/dist/utils/overflow.js +3 -0
  109. package/dist/utils/overflow.js.map +1 -1
  110. package/dist/utils/provider-retry.d.ts +11 -0
  111. package/dist/utils/provider-retry.d.ts.map +1 -0
  112. package/dist/utils/provider-retry.js +66 -0
  113. package/dist/utils/provider-retry.js.map +1 -0
  114. package/dist/utils/tool-names.d.ts +6 -1
  115. package/dist/utils/tool-names.d.ts.map +1 -1
  116. package/dist/utils/tool-names.js +22 -9
  117. package/dist/utils/tool-names.js.map +1 -1
  118. package/dist/utils/tool-repair/text-protocol.d.ts +3 -0
  119. package/dist/utils/tool-repair/text-protocol.d.ts.map +1 -1
  120. package/dist/utils/tool-repair/text-protocol.js +10 -0
  121. package/dist/utils/tool-repair/text-protocol.js.map +1 -1
  122. package/dist/utils/uuid.d.ts +3 -0
  123. package/dist/utils/uuid.d.ts.map +1 -0
  124. package/dist/utils/uuid.js +48 -0
  125. package/dist/utils/uuid.js.map +1 -0
  126. package/package.json +2 -2
@@ -3,8 +3,10 @@ import { calculateCost } from "../models.js";
3
3
  import { AssistantMessageEventStream } from "../utils/event-stream.js";
4
4
  import { headersToRecord } from "../utils/headers.js";
5
5
  import { parseJsonWithRepair, parseStreamingJson } from "../utils/json-parse.js";
6
+ import { retryProviderRequest } from "../utils/provider-retry.js";
6
7
  import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
7
8
  import { StreamingLineDecoder } from "../utils/streaming-lines.js";
9
+ import { createToolNameMap } from "../utils/tool-names.js";
8
10
  import { resolveCloudflareBaseUrl } from "./cloudflare.js";
9
11
  import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
10
12
  import { adjustMaxTokensForThinking, buildBaseOptions } from "./simple-options.js";
@@ -60,15 +62,6 @@ const claudeCodeTools = [
60
62
  const ccToolLookup = new Map(claudeCodeTools.map((t) => [t.toLowerCase(), t]));
61
63
  // Convert tool name to CC canonical casing if it matches (case-insensitive)
62
64
  const toClaudeCodeName = (name) => ccToolLookup.get(name.toLowerCase()) ?? name;
63
- const fromClaudeCodeName = (name, tools) => {
64
- if (tools && tools.length > 0) {
65
- const lowerName = name.toLowerCase();
66
- const matchedTool = tools.find((tool) => tool.name.toLowerCase() === lowerName);
67
- if (matchedTool)
68
- return matchedTool.name;
69
- }
70
- return name;
71
- };
72
65
  /**
73
66
  * Convert content blocks to Anthropic API format
74
67
  */
@@ -112,6 +105,7 @@ function getAnthropicCompat(model) {
112
105
  const isFireworks = model.provider === "fireworks";
113
106
  const isCloudflareAiGatewayAnthropic = model.provider === "cloudflare-ai-gateway" && model.baseUrl.includes("anthropic");
114
107
  return {
108
+ authFormat: model.compat?.authFormat ?? "api-key",
115
109
  supportsEagerToolInputStreaming: model.compat?.supportsEagerToolInputStreaming ?? !isFireworks,
116
110
  supportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? !isFireworks,
117
111
  sendSessionAffinityHeaders: model.compat?.sendSessionAffinityHeaders ?? !!(isFireworks || isCloudflareAiGatewayAnthropic),
@@ -129,6 +123,9 @@ function mergeHeaders(...headerSources) {
129
123
  }
130
124
  return merged;
131
125
  }
126
+ function hasAuthorizationHeader(...headerSources) {
127
+ return headerSources.some((headers) => Object.entries(headers ?? {}).some(([name, value]) => name.toLowerCase() === "authorization" && value.trim().length > 0));
128
+ }
132
129
  const ANTHROPIC_MESSAGE_EVENTS = new Set([
133
130
  "message_start",
134
131
  "message_delta",
@@ -281,7 +278,7 @@ export const streamAnthropic = (model, context, options) => {
281
278
  }
282
279
  else {
283
280
  const apiKey = options?.apiKey;
284
- if (!apiKey) {
281
+ if (!apiKey && !hasAuthorizationHeader(model.headers, options?.headers)) {
285
282
  throw new Error(`No API key for provider: ${model.provider}`);
286
283
  }
287
284
  let copilotDynamicHeaders;
@@ -298,7 +295,8 @@ export const streamAnthropic = (model, context, options) => {
298
295
  client = created.client;
299
296
  isOAuth = created.isOAuthToken;
300
297
  }
301
- let params = buildParams(model, context, isOAuth, options);
298
+ const toolNameMap = createToolNameMap(context.tools ?? [], isOAuth ? { normalizeName: toClaudeCodeName } : undefined);
299
+ let params = buildParams(model, context, isOAuth, toolNameMap, options);
302
300
  const nextParams = await options?.onPayload?.(params, model);
303
301
  if (nextParams !== undefined) {
304
302
  params = nextParams;
@@ -306,9 +304,13 @@ export const streamAnthropic = (model, context, options) => {
306
304
  const requestOptions = {
307
305
  ...(options?.signal ? { signal: options.signal } : {}),
308
306
  ...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
309
- maxRetries: options?.maxRetries ?? 0,
307
+ maxRetries: 0,
310
308
  };
311
- const response = await client.messages.create({ ...params, stream: true }, requestOptions).asResponse();
309
+ const response = await retryProviderRequest(() => client.messages.create({ ...params, stream: true }, requestOptions).asResponse(), {
310
+ maxRetries: options?.maxRetries,
311
+ maxRetryDelayMs: options?.maxRetryDelayMs,
312
+ signal: options?.signal,
313
+ });
312
314
  await options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);
313
315
  stream.push({ type: "start", partial: output });
314
316
  const blocks = output.content;
@@ -364,9 +366,7 @@ export const streamAnthropic = (model, context, options) => {
364
366
  const block = {
365
367
  type: "toolCall",
366
368
  id: event.content_block.id,
367
- name: isOAuth
368
- ? fromClaudeCodeName(event.content_block.name, context.tools)
369
- : event.content_block.name,
369
+ name: toolNameMap.toOriginalName(event.content_block.name),
370
370
  arguments: event.content_block.input ?? {},
371
371
  partialJson: "",
372
372
  index: event.index,
@@ -468,24 +468,27 @@ export const streamAnthropic = (model, context, options) => {
468
468
  }
469
469
  // Only update usage fields if present (not null).
470
470
  // Preserves input_tokens from message_start when proxies omit it in message_delta.
471
- if (event.usage.input_tokens != null) {
472
- output.usage.input = event.usage.input_tokens;
473
- }
474
- if (event.usage.output_tokens != null) {
475
- output.usage.output = event.usage.output_tokens;
476
- }
477
- if (event.usage.cache_read_input_tokens != null) {
478
- output.usage.cacheRead = event.usage.cache_read_input_tokens;
479
- }
480
- if (event.usage.cache_creation_input_tokens != null) {
481
- output.usage.cacheWrite = event.usage.cache_creation_input_tokens;
471
+ if (event.usage) {
472
+ if (event.usage.input_tokens != null) {
473
+ output.usage.input = event.usage.input_tokens;
474
+ }
475
+ if (event.usage.output_tokens != null) {
476
+ output.usage.output = event.usage.output_tokens;
477
+ }
478
+ if (event.usage.cache_read_input_tokens != null) {
479
+ output.usage.cacheRead = event.usage.cache_read_input_tokens;
480
+ }
481
+ if (event.usage.cache_creation_input_tokens != null) {
482
+ output.usage.cacheWrite = event.usage.cache_creation_input_tokens;
483
+ }
484
+ const providerCost = event.usage.cost;
485
+ if (providerCost !== undefined) {
486
+ output.usage.cost.total = providerCost || 0;
487
+ }
482
488
  }
483
489
  // Anthropic doesn't provide total_tokens, compute from components
484
490
  output.usage.totalTokens =
485
491
  output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
486
- if (event.usage.cost !== undefined) {
487
- output.usage.cost.total = event.usage.cost || 0;
488
- }
489
492
  calculateCost(model, output.usage);
490
493
  }
491
494
  }
@@ -534,7 +537,7 @@ function mapThinkingLevelToEffort(model, level) {
534
537
  }
535
538
  export const streamSimpleAnthropic = (model, context, options) => {
536
539
  const apiKey = options?.apiKey;
537
- if (!apiKey) {
540
+ if (!apiKey && !hasAuthorizationHeader(model.headers, options?.headers)) {
538
541
  throw new Error(`No API key for provider: ${model.provider}`);
539
542
  }
540
543
  const base = buildBaseOptions(model, options, apiKey);
@@ -574,6 +577,23 @@ function createClient(model, apiKey, interleavedThinking, useFineGrainedToolStre
574
577
  if (needsInterleavedBeta) {
575
578
  betaFeatures.push(INTERLEAVED_THINKING_BETA);
576
579
  }
580
+ if (!apiKey && hasAuthorizationHeader(model.headers, optionsHeaders)) {
581
+ const client = new Anthropic({
582
+ apiKey: null,
583
+ authToken: null,
584
+ baseURL: model.provider === "cloudflare-ai-gateway" ? resolveCloudflareBaseUrl(model) : model.baseUrl,
585
+ dangerouslyAllowBrowser: true,
586
+ defaultHeaders: mergeHeaders({
587
+ accept: "application/json",
588
+ "anthropic-dangerous-direct-browser-access": "true",
589
+ ...(betaFeatures.length > 0 ? { "anthropic-beta": betaFeatures.join(",") } : {}),
590
+ }, model.headers, optionsHeaders),
591
+ });
592
+ return { client, isOAuthToken: false };
593
+ }
594
+ if (!apiKey) {
595
+ throw new Error(`No API key for provider: ${model.provider}`);
596
+ }
577
597
  if (model.provider === "cloudflare-ai-gateway") {
578
598
  const client = new Anthropic({
579
599
  apiKey: null,
@@ -591,6 +611,20 @@ function createClient(model, apiKey, interleavedThinking, useFineGrainedToolStre
591
611
  });
592
612
  return { client, isOAuthToken: false };
593
613
  }
614
+ if (getAnthropicCompat(model).authFormat === "bearer") {
615
+ const client = new Anthropic({
616
+ apiKey: null,
617
+ authToken: apiKey,
618
+ baseURL: model.baseUrl,
619
+ dangerouslyAllowBrowser: true,
620
+ defaultHeaders: mergeHeaders({
621
+ accept: "application/json",
622
+ "anthropic-dangerous-direct-browser-access": "true",
623
+ ...(betaFeatures.length > 0 ? { "anthropic-beta": betaFeatures.join(",") } : {}),
624
+ }, model.headers, dynamicHeaders, optionsHeaders),
625
+ });
626
+ return { client, isOAuthToken: false };
627
+ }
594
628
  // Copilot: Bearer auth, selective betas.
595
629
  if (model.provider === "github-copilot") {
596
630
  const client = new Anthropic({
@@ -638,12 +672,12 @@ function createClient(model, apiKey, interleavedThinking, useFineGrainedToolStre
638
672
  });
639
673
  return { client, isOAuthToken: false };
640
674
  }
641
- function buildParams(model, context, isOAuthToken, options) {
675
+ function buildParams(model, context, isOAuthToken, toolNameMap, options) {
642
676
  const { cacheControl } = getCacheControl(model, options?.cacheRetention);
643
677
  const compat = getAnthropicCompat(model);
644
678
  const params = {
645
679
  model: model.id,
646
- messages: convertMessages(context.messages, model, isOAuthToken, cacheControl, compat.allowEmptySignature),
680
+ messages: convertMessages(context.messages, model, toolNameMap, cacheControl, compat.allowEmptySignature),
647
681
  max_tokens: options?.maxTokens ?? model.maxTokens,
648
682
  stream: true,
649
683
  };
@@ -680,7 +714,7 @@ function buildParams(model, context, isOAuthToken, options) {
680
714
  params.temperature = options.temperature;
681
715
  }
682
716
  if (context.tools && context.tools.length > 0) {
683
- params.tools = convertTools(context.tools, isOAuthToken, compat.supportsEagerToolInputStreaming, compat.supportsCacheControlOnTools ? cacheControl : undefined);
717
+ params.tools = convertTools(context.tools, toolNameMap, compat.supportsEagerToolInputStreaming, compat.supportsCacheControlOnTools ? cacheControl : undefined);
684
718
  }
685
719
  // Configure thinking mode: adaptive, budget-based, or explicitly disabled.
686
720
  if (model.reasoning) {
@@ -723,7 +757,8 @@ function buildParams(model, context, isOAuthToken, options) {
723
757
  params.tool_choice = { type: options.toolChoice };
724
758
  }
725
759
  else {
726
- params.tool_choice = options.toolChoice;
760
+ const providerName = toolNameMap.toProviderName(options.toolChoice.name);
761
+ params.tool_choice = { type: "tool", name: providerName };
727
762
  }
728
763
  }
729
764
  return params;
@@ -732,7 +767,7 @@ function buildParams(model, context, isOAuthToken, options) {
732
767
  function normalizeToolCallId(id) {
733
768
  return id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
734
769
  }
735
- function convertMessages(messages, model, isOAuthToken, cacheControl, allowEmptySignature = false) {
770
+ function convertMessages(messages, model, toolNameMap, cacheControl, allowEmptySignature = false) {
736
771
  const params = [];
737
772
  // Transform messages for cross-provider compatibility
738
773
  const transformedMessages = transformMessages(messages, model, normalizeToolCallId);
@@ -825,12 +860,14 @@ function convertMessages(messages, model, isOAuthToken, cacheControl, allowEmpty
825
860
  });
826
861
  continue;
827
862
  }
828
- if (block.thinking.trim().length === 0)
863
+ const thinkingSignature = block.thinkingSignature;
864
+ const hasThinkingSignature = !!thinkingSignature && thinkingSignature.trim().length > 0;
865
+ if (block.thinking.trim().length === 0 && !hasThinkingSignature)
829
866
  continue;
830
867
  // If thinking signature is missing/empty (e.g., from aborted stream),
831
868
  // convert to plain text for Anthropic. Some compatible providers emit
832
869
  // and accept empty signatures, so let marked models preserve the block.
833
- if (!block.thinkingSignature || block.thinkingSignature.trim().length === 0) {
870
+ if (!hasThinkingSignature) {
834
871
  blocks.push(allowEmptySignature
835
872
  ? {
836
873
  type: "thinking",
@@ -846,7 +883,7 @@ function convertMessages(messages, model, isOAuthToken, cacheControl, allowEmpty
846
883
  blocks.push({
847
884
  type: "thinking",
848
885
  thinking: sanitizeSurrogates(block.thinking),
849
- signature: block.thinkingSignature,
886
+ signature: thinkingSignature,
850
887
  });
851
888
  }
852
889
  }
@@ -854,7 +891,7 @@ function convertMessages(messages, model, isOAuthToken, cacheControl, allowEmpty
854
891
  blocks.push({
855
892
  type: "tool_use",
856
893
  id: block.id,
857
- name: isOAuthToken ? toClaudeCodeName(block.name) : block.name,
894
+ name: toolNameMap.toProviderName(block.name),
858
895
  input: block.arguments ?? {},
859
896
  });
860
897
  }
@@ -924,13 +961,13 @@ function convertMessages(messages, model, isOAuthToken, cacheControl, allowEmpty
924
961
  function shouldUseFineGrainedToolStreamingBeta(model, context) {
925
962
  return !!context.tools?.length && !getAnthropicCompat(model).supportsEagerToolInputStreaming;
926
963
  }
927
- function convertTools(tools, isOAuthToken, supportsEagerToolInputStreaming, cacheControl) {
964
+ function convertTools(tools, toolNameMap, supportsEagerToolInputStreaming, cacheControl) {
928
965
  if (!tools)
929
966
  return [];
930
967
  return tools.map((tool, index) => {
931
968
  const schema = tool.parameters;
932
969
  return {
933
- name: isOAuthToken ? toClaudeCodeName(tool.name) : tool.name,
970
+ name: toolNameMap.toProviderName(tool.name),
934
971
  description: tool.description,
935
972
  ...(supportsEagerToolInputStreaming ? { eager_input_streaming: true } : {}),
936
973
  input_schema: {