@eminent337/aery-ai 0.67.76 → 0.67.78

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 (182) hide show
  1. package/README.md +0 -0
  2. package/package.json +110 -110
  3. package/dist/api-registry.d.ts +0 -20
  4. package/dist/api-registry.d.ts.map +0 -1
  5. package/dist/api-registry.js +0 -44
  6. package/dist/api-registry.js.map +0 -1
  7. package/dist/bedrock-provider.d.ts +0 -5
  8. package/dist/bedrock-provider.d.ts.map +0 -1
  9. package/dist/bedrock-provider.js +0 -6
  10. package/dist/bedrock-provider.js.map +0 -1
  11. package/dist/cli.d.ts +0 -3
  12. package/dist/cli.d.ts.map +0 -1
  13. package/dist/cli.js +0 -116
  14. package/dist/cli.js.map +0 -1
  15. package/dist/env-api-keys.d.ts +0 -18
  16. package/dist/env-api-keys.d.ts.map +0 -1
  17. package/dist/env-api-keys.js +0 -162
  18. package/dist/env-api-keys.js.map +0 -1
  19. package/dist/index.d.ts +0 -26
  20. package/dist/index.d.ts.map +0 -1
  21. package/dist/index.js +0 -14
  22. package/dist/index.js.map +0 -1
  23. package/dist/models.d.ts +0 -25
  24. package/dist/models.d.ts.map +0 -1
  25. package/dist/models.generated.d.ts +0 -15860
  26. package/dist/models.generated.d.ts.map +0 -1
  27. package/dist/models.generated.js +0 -15589
  28. package/dist/models.generated.js.map +0 -1
  29. package/dist/models.js +0 -63
  30. package/dist/models.js.map +0 -1
  31. package/dist/oauth.d.ts +0 -2
  32. package/dist/oauth.d.ts.map +0 -1
  33. package/dist/oauth.js +0 -2
  34. package/dist/oauth.js.map +0 -1
  35. package/dist/providers/amazon-bedrock.d.ts +0 -38
  36. package/dist/providers/amazon-bedrock.d.ts.map +0 -1
  37. package/dist/providers/amazon-bedrock.js +0 -759
  38. package/dist/providers/amazon-bedrock.js.map +0 -1
  39. package/dist/providers/anthropic.d.ts +0 -54
  40. package/dist/providers/anthropic.d.ts.map +0 -1
  41. package/dist/providers/anthropic.js +0 -931
  42. package/dist/providers/anthropic.js.map +0 -1
  43. package/dist/providers/azure-openai-responses.d.ts +0 -15
  44. package/dist/providers/azure-openai-responses.d.ts.map +0 -1
  45. package/dist/providers/azure-openai-responses.js +0 -202
  46. package/dist/providers/azure-openai-responses.js.map +0 -1
  47. package/dist/providers/cloudflare.d.ts +0 -7
  48. package/dist/providers/cloudflare.d.ts.map +0 -1
  49. package/dist/providers/cloudflare.js +0 -19
  50. package/dist/providers/cloudflare.js.map +0 -1
  51. package/dist/providers/faux.d.ts +0 -56
  52. package/dist/providers/faux.d.ts.map +0 -1
  53. package/dist/providers/faux.js +0 -368
  54. package/dist/providers/faux.js.map +0 -1
  55. package/dist/providers/github-copilot-headers.d.ts +0 -8
  56. package/dist/providers/github-copilot-headers.d.ts.map +0 -1
  57. package/dist/providers/github-copilot-headers.js +0 -29
  58. package/dist/providers/github-copilot-headers.js.map +0 -1
  59. package/dist/providers/google-gemini-cli.d.ts +0 -74
  60. package/dist/providers/google-gemini-cli.d.ts.map +0 -1
  61. package/dist/providers/google-gemini-cli.js +0 -779
  62. package/dist/providers/google-gemini-cli.js.map +0 -1
  63. package/dist/providers/google-shared.d.ts +0 -65
  64. package/dist/providers/google-shared.d.ts.map +0 -1
  65. package/dist/providers/google-shared.js +0 -338
  66. package/dist/providers/google-shared.js.map +0 -1
  67. package/dist/providers/google-vertex.d.ts +0 -15
  68. package/dist/providers/google-vertex.d.ts.map +0 -1
  69. package/dist/providers/google-vertex.js +0 -441
  70. package/dist/providers/google-vertex.js.map +0 -1
  71. package/dist/providers/google.d.ts +0 -13
  72. package/dist/providers/google.d.ts.map +0 -1
  73. package/dist/providers/google.js +0 -399
  74. package/dist/providers/google.js.map +0 -1
  75. package/dist/providers/mistral.d.ts +0 -25
  76. package/dist/providers/mistral.d.ts.map +0 -1
  77. package/dist/providers/mistral.js +0 -534
  78. package/dist/providers/mistral.js.map +0 -1
  79. package/dist/providers/openai-codex-responses.d.ts +0 -11
  80. package/dist/providers/openai-codex-responses.d.ts.map +0 -1
  81. package/dist/providers/openai-codex-responses.js +0 -779
  82. package/dist/providers/openai-codex-responses.js.map +0 -1
  83. package/dist/providers/openai-completions.d.ts +0 -19
  84. package/dist/providers/openai-completions.d.ts.map +0 -1
  85. package/dist/providers/openai-completions.js +0 -909
  86. package/dist/providers/openai-completions.js.map +0 -1
  87. package/dist/providers/openai-responses-shared.d.ts +0 -18
  88. package/dist/providers/openai-responses-shared.d.ts.map +0 -1
  89. package/dist/providers/openai-responses-shared.js +0 -479
  90. package/dist/providers/openai-responses-shared.js.map +0 -1
  91. package/dist/providers/openai-responses.d.ts +0 -13
  92. package/dist/providers/openai-responses.d.ts.map +0 -1
  93. package/dist/providers/openai-responses.js +0 -206
  94. package/dist/providers/openai-responses.js.map +0 -1
  95. package/dist/providers/register-builtins.d.ts +0 -38
  96. package/dist/providers/register-builtins.d.ts.map +0 -1
  97. package/dist/providers/register-builtins.js +0 -261
  98. package/dist/providers/register-builtins.js.map +0 -1
  99. package/dist/providers/simple-options.d.ts +0 -8
  100. package/dist/providers/simple-options.d.ts.map +0 -1
  101. package/dist/providers/simple-options.js +0 -38
  102. package/dist/providers/simple-options.js.map +0 -1
  103. package/dist/providers/transform-messages.d.ts +0 -8
  104. package/dist/providers/transform-messages.d.ts.map +0 -1
  105. package/dist/providers/transform-messages.js +0 -184
  106. package/dist/providers/transform-messages.js.map +0 -1
  107. package/dist/stream.d.ts +0 -8
  108. package/dist/stream.d.ts.map +0 -1
  109. package/dist/stream.js +0 -27
  110. package/dist/stream.js.map +0 -1
  111. package/dist/types.d.ts +0 -397
  112. package/dist/types.d.ts.map +0 -1
  113. package/dist/types.js +0 -2
  114. package/dist/types.js.map +0 -1
  115. package/dist/utils/event-stream.d.ts +0 -21
  116. package/dist/utils/event-stream.d.ts.map +0 -1
  117. package/dist/utils/event-stream.js +0 -81
  118. package/dist/utils/event-stream.js.map +0 -1
  119. package/dist/utils/hash.d.ts +0 -3
  120. package/dist/utils/hash.d.ts.map +0 -1
  121. package/dist/utils/hash.js +0 -14
  122. package/dist/utils/hash.js.map +0 -1
  123. package/dist/utils/headers.d.ts +0 -2
  124. package/dist/utils/headers.d.ts.map +0 -1
  125. package/dist/utils/headers.js +0 -8
  126. package/dist/utils/headers.js.map +0 -1
  127. package/dist/utils/json-parse.d.ts +0 -16
  128. package/dist/utils/json-parse.d.ts.map +0 -1
  129. package/dist/utils/json-parse.js +0 -113
  130. package/dist/utils/json-parse.js.map +0 -1
  131. package/dist/utils/oauth/anthropic.d.ts +0 -25
  132. package/dist/utils/oauth/anthropic.d.ts.map +0 -1
  133. package/dist/utils/oauth/anthropic.js +0 -335
  134. package/dist/utils/oauth/anthropic.js.map +0 -1
  135. package/dist/utils/oauth/github-copilot.d.ts +0 -30
  136. package/dist/utils/oauth/github-copilot.d.ts.map +0 -1
  137. package/dist/utils/oauth/github-copilot.js +0 -292
  138. package/dist/utils/oauth/github-copilot.js.map +0 -1
  139. package/dist/utils/oauth/google-antigravity.d.ts +0 -26
  140. package/dist/utils/oauth/google-antigravity.d.ts.map +0 -1
  141. package/dist/utils/oauth/google-antigravity.js +0 -377
  142. package/dist/utils/oauth/google-antigravity.js.map +0 -1
  143. package/dist/utils/oauth/google-gemini-cli.d.ts +0 -26
  144. package/dist/utils/oauth/google-gemini-cli.d.ts.map +0 -1
  145. package/dist/utils/oauth/google-gemini-cli.js +0 -482
  146. package/dist/utils/oauth/google-gemini-cli.js.map +0 -1
  147. package/dist/utils/oauth/index.d.ts +0 -61
  148. package/dist/utils/oauth/index.d.ts.map +0 -1
  149. package/dist/utils/oauth/index.js +0 -131
  150. package/dist/utils/oauth/index.js.map +0 -1
  151. package/dist/utils/oauth/oauth-page.d.ts +0 -3
  152. package/dist/utils/oauth/oauth-page.d.ts.map +0 -1
  153. package/dist/utils/oauth/oauth-page.js +0 -105
  154. package/dist/utils/oauth/oauth-page.js.map +0 -1
  155. package/dist/utils/oauth/openai-codex.d.ts +0 -34
  156. package/dist/utils/oauth/openai-codex.d.ts.map +0 -1
  157. package/dist/utils/oauth/openai-codex.js +0 -374
  158. package/dist/utils/oauth/openai-codex.js.map +0 -1
  159. package/dist/utils/oauth/pkce.d.ts +0 -13
  160. package/dist/utils/oauth/pkce.d.ts.map +0 -1
  161. package/dist/utils/oauth/pkce.js +0 -31
  162. package/dist/utils/oauth/pkce.js.map +0 -1
  163. package/dist/utils/oauth/types.d.ts +0 -47
  164. package/dist/utils/oauth/types.d.ts.map +0 -1
  165. package/dist/utils/oauth/types.js +0 -2
  166. package/dist/utils/oauth/types.js.map +0 -1
  167. package/dist/utils/overflow.d.ts +0 -53
  168. package/dist/utils/overflow.d.ts.map +0 -1
  169. package/dist/utils/overflow.js +0 -132
  170. package/dist/utils/overflow.js.map +0 -1
  171. package/dist/utils/sanitize-unicode.d.ts +0 -22
  172. package/dist/utils/sanitize-unicode.d.ts.map +0 -1
  173. package/dist/utils/sanitize-unicode.js +0 -26
  174. package/dist/utils/sanitize-unicode.js.map +0 -1
  175. package/dist/utils/typebox-helpers.d.ts +0 -17
  176. package/dist/utils/typebox-helpers.d.ts.map +0 -1
  177. package/dist/utils/typebox-helpers.js +0 -21
  178. package/dist/utils/typebox-helpers.js.map +0 -1
  179. package/dist/utils/validation.d.ts +0 -18
  180. package/dist/utils/validation.d.ts.map +0 -1
  181. package/dist/utils/validation.js +0 -281
  182. package/dist/utils/validation.js.map +0 -1
@@ -1,8 +0,0 @@
1
- import type { Api, Model, SimpleStreamOptions, StreamOptions, ThinkingBudgets, ThinkingLevel } from "../types.js";
2
- export declare function buildBaseOptions(model: Model<Api>, options?: SimpleStreamOptions, apiKey?: string): StreamOptions;
3
- export declare function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, "xhigh"> | undefined;
4
- export declare function adjustMaxTokensForThinking(baseMaxTokens: number, modelMaxTokens: number, reasoningLevel: ThinkingLevel, customBudgets?: ThinkingBudgets): {
5
- maxTokens: number;
6
- thinkingBudget: number;
7
- };
8
- //# sourceMappingURL=simple-options.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"simple-options.d.ts","sourceRoot":"","sources":["../../src/providers/simple-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAElH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa,CAgBjH;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG,SAAS,CAE7G;AAED,wBAAgB,0BAA0B,CACzC,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,aAAa,EAC7B,aAAa,CAAC,EAAE,eAAe,GAC7B;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAmB/C","sourcesContent":["import type { Api, Model, SimpleStreamOptions, StreamOptions, ThinkingBudgets, ThinkingLevel } from \"../types.js\";\n\nexport function buildBaseOptions(model: Model<Api>, options?: SimpleStreamOptions, apiKey?: string): StreamOptions {\n\treturn {\n\t\ttemperature: options?.temperature,\n\t\tmaxTokens: options?.maxTokens ?? (model.maxTokens > 0 ? Math.min(model.maxTokens, 32000) : undefined),\n\t\tsignal: options?.signal,\n\t\tapiKey: apiKey || options?.apiKey,\n\t\tcacheRetention: options?.cacheRetention,\n\t\tsessionId: options?.sessionId,\n\t\theaders: options?.headers,\n\t\tonPayload: options?.onPayload,\n\t\tonResponse: options?.onResponse,\n\t\ttimeoutMs: options?.timeoutMs,\n\t\tmaxRetries: options?.maxRetries,\n\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\tmetadata: options?.metadata,\n\t};\n}\n\nexport function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, \"xhigh\"> | undefined {\n\treturn effort === \"xhigh\" ? \"high\" : effort;\n}\n\nexport function adjustMaxTokensForThinking(\n\tbaseMaxTokens: number,\n\tmodelMaxTokens: number,\n\treasoningLevel: ThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): { maxTokens: number; thinkingBudget: number } {\n\tconst defaultBudgets: ThinkingBudgets = {\n\t\tminimal: 1024,\n\t\tlow: 2048,\n\t\tmedium: 8192,\n\t\thigh: 16384,\n\t};\n\tconst budgets = { ...defaultBudgets, ...customBudgets };\n\n\tconst minOutputTokens = 1024;\n\tconst level = clampReasoning(reasoningLevel)!;\n\tlet thinkingBudget = budgets[level]!;\n\tconst maxTokens = Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);\n\n\tif (maxTokens <= thinkingBudget) {\n\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t}\n\n\treturn { maxTokens, thinkingBudget };\n}\n"]}
@@ -1,38 +0,0 @@
1
- export function buildBaseOptions(model, options, apiKey) {
2
- return {
3
- temperature: options?.temperature,
4
- maxTokens: options?.maxTokens ?? (model.maxTokens > 0 ? Math.min(model.maxTokens, 32000) : undefined),
5
- signal: options?.signal,
6
- apiKey: apiKey || options?.apiKey,
7
- cacheRetention: options?.cacheRetention,
8
- sessionId: options?.sessionId,
9
- headers: options?.headers,
10
- onPayload: options?.onPayload,
11
- onResponse: options?.onResponse,
12
- timeoutMs: options?.timeoutMs,
13
- maxRetries: options?.maxRetries,
14
- maxRetryDelayMs: options?.maxRetryDelayMs,
15
- metadata: options?.metadata,
16
- };
17
- }
18
- export function clampReasoning(effort) {
19
- return effort === "xhigh" ? "high" : effort;
20
- }
21
- export function adjustMaxTokensForThinking(baseMaxTokens, modelMaxTokens, reasoningLevel, customBudgets) {
22
- const defaultBudgets = {
23
- minimal: 1024,
24
- low: 2048,
25
- medium: 8192,
26
- high: 16384,
27
- };
28
- const budgets = { ...defaultBudgets, ...customBudgets };
29
- const minOutputTokens = 1024;
30
- const level = clampReasoning(reasoningLevel);
31
- let thinkingBudget = budgets[level];
32
- const maxTokens = Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);
33
- if (maxTokens <= thinkingBudget) {
34
- thinkingBudget = Math.max(0, maxTokens - minOutputTokens);
35
- }
36
- return { maxTokens, thinkingBudget };
37
- }
38
- //# sourceMappingURL=simple-options.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"simple-options.js","sourceRoot":"","sources":["../../src/providers/simple-options.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAAC,KAAiB,EAAE,OAA6B,EAAE,MAAe,EAAiB;IAClH,OAAO;QACN,WAAW,EAAE,OAAO,EAAE,WAAW;QACjC,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACrG,MAAM,EAAE,OAAO,EAAE,MAAM;QACvB,MAAM,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM;QACjC,cAAc,EAAE,OAAO,EAAE,cAAc;QACvC,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,OAAO,EAAE,OAAO,EAAE,OAAO;QACzB,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,UAAU,EAAE,OAAO,EAAE,UAAU;QAC/B,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,UAAU,EAAE,OAAO,EAAE,UAAU;QAC/B,eAAe,EAAE,OAAO,EAAE,eAAe;QACzC,QAAQ,EAAE,OAAO,EAAE,QAAQ;KAC3B,CAAC;AAAA,CACF;AAED,MAAM,UAAU,cAAc,CAAC,MAAiC,EAA+C;IAC9G,OAAO,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AAAA,CAC5C;AAED,MAAM,UAAU,0BAA0B,CACzC,aAAqB,EACrB,cAAsB,EACtB,cAA6B,EAC7B,aAA+B,EACiB;IAChD,MAAM,cAAc,GAAoB;QACvC,OAAO,EAAE,IAAI;QACb,GAAG,EAAE,IAAI;QACT,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,KAAK;KACX,CAAC;IACF,MAAM,OAAO,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,aAAa,EAAE,CAAC;IAExD,MAAM,eAAe,GAAG,IAAI,CAAC;IAC7B,MAAM,KAAK,GAAG,cAAc,CAAC,cAAc,CAAE,CAAC;IAC9C,IAAI,cAAc,GAAG,OAAO,CAAC,KAAK,CAAE,CAAC;IACrC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,cAAc,EAAE,cAAc,CAAC,CAAC;IAE3E,IAAI,SAAS,IAAI,cAAc,EAAE,CAAC;QACjC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,eAAe,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;AAAA,CACrC","sourcesContent":["import type { Api, Model, SimpleStreamOptions, StreamOptions, ThinkingBudgets, ThinkingLevel } from \"../types.js\";\n\nexport function buildBaseOptions(model: Model<Api>, options?: SimpleStreamOptions, apiKey?: string): StreamOptions {\n\treturn {\n\t\ttemperature: options?.temperature,\n\t\tmaxTokens: options?.maxTokens ?? (model.maxTokens > 0 ? Math.min(model.maxTokens, 32000) : undefined),\n\t\tsignal: options?.signal,\n\t\tapiKey: apiKey || options?.apiKey,\n\t\tcacheRetention: options?.cacheRetention,\n\t\tsessionId: options?.sessionId,\n\t\theaders: options?.headers,\n\t\tonPayload: options?.onPayload,\n\t\tonResponse: options?.onResponse,\n\t\ttimeoutMs: options?.timeoutMs,\n\t\tmaxRetries: options?.maxRetries,\n\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\tmetadata: options?.metadata,\n\t};\n}\n\nexport function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, \"xhigh\"> | undefined {\n\treturn effort === \"xhigh\" ? \"high\" : effort;\n}\n\nexport function adjustMaxTokensForThinking(\n\tbaseMaxTokens: number,\n\tmodelMaxTokens: number,\n\treasoningLevel: ThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): { maxTokens: number; thinkingBudget: number } {\n\tconst defaultBudgets: ThinkingBudgets = {\n\t\tminimal: 1024,\n\t\tlow: 2048,\n\t\tmedium: 8192,\n\t\thigh: 16384,\n\t};\n\tconst budgets = { ...defaultBudgets, ...customBudgets };\n\n\tconst minOutputTokens = 1024;\n\tconst level = clampReasoning(reasoningLevel)!;\n\tlet thinkingBudget = budgets[level]!;\n\tconst maxTokens = Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);\n\n\tif (maxTokens <= thinkingBudget) {\n\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t}\n\n\treturn { maxTokens, thinkingBudget };\n}\n"]}
@@ -1,8 +0,0 @@
1
- import type { Api, AssistantMessage, Message, Model } from "../types.js";
2
- /**
3
- * Normalize tool call ID for cross-provider compatibility.
4
- * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.
5
- * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).
6
- */
7
- export declare function transformMessages<TApi extends Api>(messages: Message[], model: Model<TApi>, normalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string): Message[];
8
- //# sourceMappingURL=transform-messages.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"transform-messages.d.ts","sourceRoot":"","sources":["../../src/providers/transform-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,GAAG,EACH,gBAAgB,EAEhB,OAAO,EACP,KAAK,EAIL,MAAM,aAAa,CAAC;AAiDrB;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,SAAS,GAAG,EACjD,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,mBAAmB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,gBAAgB,KAAK,MAAM,GACxF,OAAO,EAAE,CAwJX","sourcesContent":["import type {\n\tApi,\n\tAssistantMessage,\n\tImageContent,\n\tMessage,\n\tModel,\n\tTextContent,\n\tToolCall,\n\tToolResultMessage,\n} from \"../types.js\";\n\nconst NON_VISION_USER_IMAGE_PLACEHOLDER = \"(image omitted: model does not support images)\";\nconst NON_VISION_TOOL_IMAGE_PLACEHOLDER = \"(tool image omitted: model does not support images)\";\n\nfunction replaceImagesWithPlaceholder(content: (TextContent | ImageContent)[], placeholder: string): TextContent[] {\n\tconst result: TextContent[] = [];\n\tlet previousWasPlaceholder = false;\n\n\tfor (const block of content) {\n\t\tif (block.type === \"image\") {\n\t\t\tif (!previousWasPlaceholder) {\n\t\t\t\tresult.push({ type: \"text\", text: placeholder });\n\t\t\t}\n\t\t\tpreviousWasPlaceholder = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult.push(block);\n\t\tpreviousWasPlaceholder = block.text === placeholder;\n\t}\n\n\treturn result;\n}\n\nfunction downgradeUnsupportedImages<TApi extends Api>(messages: Message[], model: Model<TApi>): Message[] {\n\tif (model.input.includes(\"image\")) {\n\t\treturn messages;\n\t}\n\n\treturn messages.map((msg) => {\n\t\tif (msg.role === \"user\" && Array.isArray(msg.content)) {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\tif (msg.role === \"toolResult\") {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\treturn msg;\n\t});\n}\n\n/**\n * Normalize tool call ID for cross-provider compatibility.\n * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.\n * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).\n */\nexport function transformMessages<TApi extends Api>(\n\tmessages: Message[],\n\tmodel: Model<TApi>,\n\tnormalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string,\n): Message[] {\n\t// Build a map of original tool call IDs to normalized IDs\n\tconst toolCallIdMap = new Map<string, string>();\n\tconst imageAwareMessages = downgradeUnsupportedImages(messages, model);\n\n\t// First pass: transform messages (unsupported image downgrade, thinking blocks, tool call ID normalization)\n\tconst transformed = imageAwareMessages.map((msg) => {\n\t\t// User messages pass through unchanged\n\t\tif (msg.role === \"user\") {\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Handle toolResult messages - normalize toolCallId if we have a mapping\n\t\tif (msg.role === \"toolResult\") {\n\t\t\tconst normalizedId = toolCallIdMap.get(msg.toolCallId);\n\t\t\tif (normalizedId && normalizedId !== msg.toolCallId) {\n\t\t\t\treturn { ...msg, toolCallId: normalizedId };\n\t\t\t}\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Assistant messages need transformation check\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tconst isSameModel =\n\t\t\t\tassistantMsg.provider === model.provider &&\n\t\t\t\tassistantMsg.api === model.api &&\n\t\t\t\tassistantMsg.model === model.id;\n\n\t\t\tconst transformedContent = assistantMsg.content.flatMap((block) => {\n\t\t\t\tif (block.type === \"thinking\") {\n\t\t\t\t\t// Redacted thinking is opaque encrypted content, only valid for the same model.\n\t\t\t\t\t// Drop it for cross-model to avoid API errors.\n\t\t\t\t\tif (block.redacted) {\n\t\t\t\t\t\treturn isSameModel ? block : [];\n\t\t\t\t\t}\n\t\t\t\t\t// For same model: keep thinking blocks with signatures (needed for replay)\n\t\t\t\t\t// even if the thinking text is empty (OpenAI encrypted reasoning)\n\t\t\t\t\tif (isSameModel && block.thinkingSignature) return block;\n\t\t\t\t\t// Skip empty thinking blocks, convert others to plain text\n\t\t\t\t\tif (!block.thinking || block.thinking.trim() === \"\") return [];\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.thinking,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"toolCall\") {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\tlet normalizedToolCall: ToolCall = toolCall;\n\n\t\t\t\t\tif (!isSameModel && toolCall.thoughtSignature) {\n\t\t\t\t\t\tnormalizedToolCall = { ...toolCall };\n\t\t\t\t\t\tdelete (normalizedToolCall as { thoughtSignature?: string }).thoughtSignature;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!isSameModel && normalizeToolCallId) {\n\t\t\t\t\t\tconst normalizedId = normalizeToolCallId(toolCall.id, model, assistantMsg);\n\t\t\t\t\t\tif (normalizedId !== toolCall.id) {\n\t\t\t\t\t\t\ttoolCallIdMap.set(toolCall.id, normalizedId);\n\t\t\t\t\t\t\tnormalizedToolCall = { ...normalizedToolCall, id: normalizedId };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn normalizedToolCall;\n\t\t\t\t}\n\n\t\t\t\treturn block;\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\t...assistantMsg,\n\t\t\t\tcontent: transformedContent,\n\t\t\t};\n\t\t}\n\t\treturn msg;\n\t});\n\n\t// Second pass: insert synthetic empty tool results for orphaned tool calls\n\t// This preserves thinking signatures and satisfies API requirements\n\tconst result: Message[] = [];\n\tlet pendingToolCalls: ToolCall[] = [];\n\tlet existingToolResultIds = new Set<string>();\n\tconst insertSyntheticToolResults = () => {\n\t\tif (pendingToolCalls.length > 0) {\n\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t}\n\t\t\t}\n\t\t\tpendingToolCalls = [];\n\t\t\texistingToolResultIds = new Set();\n\t\t}\n\t};\n\n\tfor (let i = 0; i < transformed.length; i++) {\n\t\tconst msg = transformed[i];\n\n\t\tif (msg.role === \"assistant\") {\n\t\t\t// If we have pending orphaned tool calls from a previous assistant, insert synthetic results now\n\t\t\tinsertSyntheticToolResults();\n\n\t\t\t// Skip errored/aborted assistant messages entirely.\n\t\t\t// These are incomplete turns that shouldn't be replayed:\n\t\t\t// - May have partial content (reasoning without message, incomplete tool calls)\n\t\t\t// - Replaying them can cause API errors (e.g., OpenAI \"reasoning without following item\")\n\t\t\t// - The model should retry from the last valid state\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Track tool calls from this assistant message\n\t\t\tconst toolCalls = assistantMsg.content.filter((b) => b.type === \"toolCall\") as ToolCall[];\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tpendingToolCalls = toolCalls;\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\texistingToolResultIds.add(msg.toolCallId);\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"user\") {\n\t\t\t// User message interrupts tool flow - insert synthetic results for orphaned calls\n\t\t\tinsertSyntheticToolResults();\n\t\t\tresult.push(msg);\n\t\t} else {\n\t\t\tresult.push(msg);\n\t\t}\n\t}\n\n\t// If the conversation ends with unresolved tool calls, synthesize results now.\n\tinsertSyntheticToolResults();\n\n\treturn result;\n}\n"]}
@@ -1,184 +0,0 @@
1
- const NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
2
- const NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
3
- function replaceImagesWithPlaceholder(content, placeholder) {
4
- const result = [];
5
- let previousWasPlaceholder = false;
6
- for (const block of content) {
7
- if (block.type === "image") {
8
- if (!previousWasPlaceholder) {
9
- result.push({ type: "text", text: placeholder });
10
- }
11
- previousWasPlaceholder = true;
12
- continue;
13
- }
14
- result.push(block);
15
- previousWasPlaceholder = block.text === placeholder;
16
- }
17
- return result;
18
- }
19
- function downgradeUnsupportedImages(messages, model) {
20
- if (model.input.includes("image")) {
21
- return messages;
22
- }
23
- return messages.map((msg) => {
24
- if (msg.role === "user" && Array.isArray(msg.content)) {
25
- return {
26
- ...msg,
27
- content: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER),
28
- };
29
- }
30
- if (msg.role === "toolResult") {
31
- return {
32
- ...msg,
33
- content: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER),
34
- };
35
- }
36
- return msg;
37
- });
38
- }
39
- /**
40
- * Normalize tool call ID for cross-provider compatibility.
41
- * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.
42
- * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).
43
- */
44
- export function transformMessages(messages, model, normalizeToolCallId) {
45
- // Build a map of original tool call IDs to normalized IDs
46
- const toolCallIdMap = new Map();
47
- const imageAwareMessages = downgradeUnsupportedImages(messages, model);
48
- // First pass: transform messages (unsupported image downgrade, thinking blocks, tool call ID normalization)
49
- const transformed = imageAwareMessages.map((msg) => {
50
- // User messages pass through unchanged
51
- if (msg.role === "user") {
52
- return msg;
53
- }
54
- // Handle toolResult messages - normalize toolCallId if we have a mapping
55
- if (msg.role === "toolResult") {
56
- const normalizedId = toolCallIdMap.get(msg.toolCallId);
57
- if (normalizedId && normalizedId !== msg.toolCallId) {
58
- return { ...msg, toolCallId: normalizedId };
59
- }
60
- return msg;
61
- }
62
- // Assistant messages need transformation check
63
- if (msg.role === "assistant") {
64
- const assistantMsg = msg;
65
- const isSameModel = assistantMsg.provider === model.provider &&
66
- assistantMsg.api === model.api &&
67
- assistantMsg.model === model.id;
68
- const transformedContent = assistantMsg.content.flatMap((block) => {
69
- if (block.type === "thinking") {
70
- // Redacted thinking is opaque encrypted content, only valid for the same model.
71
- // Drop it for cross-model to avoid API errors.
72
- if (block.redacted) {
73
- return isSameModel ? block : [];
74
- }
75
- // For same model: keep thinking blocks with signatures (needed for replay)
76
- // even if the thinking text is empty (OpenAI encrypted reasoning)
77
- if (isSameModel && block.thinkingSignature)
78
- return block;
79
- // Skip empty thinking blocks, convert others to plain text
80
- if (!block.thinking || block.thinking.trim() === "")
81
- return [];
82
- if (isSameModel)
83
- return block;
84
- return {
85
- type: "text",
86
- text: block.thinking,
87
- };
88
- }
89
- if (block.type === "text") {
90
- if (isSameModel)
91
- return block;
92
- return {
93
- type: "text",
94
- text: block.text,
95
- };
96
- }
97
- if (block.type === "toolCall") {
98
- const toolCall = block;
99
- let normalizedToolCall = toolCall;
100
- if (!isSameModel && toolCall.thoughtSignature) {
101
- normalizedToolCall = { ...toolCall };
102
- delete normalizedToolCall.thoughtSignature;
103
- }
104
- if (!isSameModel && normalizeToolCallId) {
105
- const normalizedId = normalizeToolCallId(toolCall.id, model, assistantMsg);
106
- if (normalizedId !== toolCall.id) {
107
- toolCallIdMap.set(toolCall.id, normalizedId);
108
- normalizedToolCall = { ...normalizedToolCall, id: normalizedId };
109
- }
110
- }
111
- return normalizedToolCall;
112
- }
113
- return block;
114
- });
115
- return {
116
- ...assistantMsg,
117
- content: transformedContent,
118
- };
119
- }
120
- return msg;
121
- });
122
- // Second pass: insert synthetic empty tool results for orphaned tool calls
123
- // This preserves thinking signatures and satisfies API requirements
124
- const result = [];
125
- let pendingToolCalls = [];
126
- let existingToolResultIds = new Set();
127
- const insertSyntheticToolResults = () => {
128
- if (pendingToolCalls.length > 0) {
129
- for (const tc of pendingToolCalls) {
130
- if (!existingToolResultIds.has(tc.id)) {
131
- result.push({
132
- role: "toolResult",
133
- toolCallId: tc.id,
134
- toolName: tc.name,
135
- content: [{ type: "text", text: "No result provided" }],
136
- isError: true,
137
- timestamp: Date.now(),
138
- });
139
- }
140
- }
141
- pendingToolCalls = [];
142
- existingToolResultIds = new Set();
143
- }
144
- };
145
- for (let i = 0; i < transformed.length; i++) {
146
- const msg = transformed[i];
147
- if (msg.role === "assistant") {
148
- // If we have pending orphaned tool calls from a previous assistant, insert synthetic results now
149
- insertSyntheticToolResults();
150
- // Skip errored/aborted assistant messages entirely.
151
- // These are incomplete turns that shouldn't be replayed:
152
- // - May have partial content (reasoning without message, incomplete tool calls)
153
- // - Replaying them can cause API errors (e.g., OpenAI "reasoning without following item")
154
- // - The model should retry from the last valid state
155
- const assistantMsg = msg;
156
- if (assistantMsg.stopReason === "error" || assistantMsg.stopReason === "aborted") {
157
- continue;
158
- }
159
- // Track tool calls from this assistant message
160
- const toolCalls = assistantMsg.content.filter((b) => b.type === "toolCall");
161
- if (toolCalls.length > 0) {
162
- pendingToolCalls = toolCalls;
163
- existingToolResultIds = new Set();
164
- }
165
- result.push(msg);
166
- }
167
- else if (msg.role === "toolResult") {
168
- existingToolResultIds.add(msg.toolCallId);
169
- result.push(msg);
170
- }
171
- else if (msg.role === "user") {
172
- // User message interrupts tool flow - insert synthetic results for orphaned calls
173
- insertSyntheticToolResults();
174
- result.push(msg);
175
- }
176
- else {
177
- result.push(msg);
178
- }
179
- }
180
- // If the conversation ends with unresolved tool calls, synthesize results now.
181
- insertSyntheticToolResults();
182
- return result;
183
- }
184
- //# sourceMappingURL=transform-messages.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"transform-messages.js","sourceRoot":"","sources":["../../src/providers/transform-messages.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tApi,\n\tAssistantMessage,\n\tImageContent,\n\tMessage,\n\tModel,\n\tTextContent,\n\tToolCall,\n\tToolResultMessage,\n} from \"../types.js\";\n\nconst NON_VISION_USER_IMAGE_PLACEHOLDER = \"(image omitted: model does not support images)\";\nconst NON_VISION_TOOL_IMAGE_PLACEHOLDER = \"(tool image omitted: model does not support images)\";\n\nfunction replaceImagesWithPlaceholder(content: (TextContent | ImageContent)[], placeholder: string): TextContent[] {\n\tconst result: TextContent[] = [];\n\tlet previousWasPlaceholder = false;\n\n\tfor (const block of content) {\n\t\tif (block.type === \"image\") {\n\t\t\tif (!previousWasPlaceholder) {\n\t\t\t\tresult.push({ type: \"text\", text: placeholder });\n\t\t\t}\n\t\t\tpreviousWasPlaceholder = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult.push(block);\n\t\tpreviousWasPlaceholder = block.text === placeholder;\n\t}\n\n\treturn result;\n}\n\nfunction downgradeUnsupportedImages<TApi extends Api>(messages: Message[], model: Model<TApi>): Message[] {\n\tif (model.input.includes(\"image\")) {\n\t\treturn messages;\n\t}\n\n\treturn messages.map((msg) => {\n\t\tif (msg.role === \"user\" && Array.isArray(msg.content)) {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\tif (msg.role === \"toolResult\") {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\treturn msg;\n\t});\n}\n\n/**\n * Normalize tool call ID for cross-provider compatibility.\n * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.\n * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).\n */\nexport function transformMessages<TApi extends Api>(\n\tmessages: Message[],\n\tmodel: Model<TApi>,\n\tnormalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string,\n): Message[] {\n\t// Build a map of original tool call IDs to normalized IDs\n\tconst toolCallIdMap = new Map<string, string>();\n\tconst imageAwareMessages = downgradeUnsupportedImages(messages, model);\n\n\t// First pass: transform messages (unsupported image downgrade, thinking blocks, tool call ID normalization)\n\tconst transformed = imageAwareMessages.map((msg) => {\n\t\t// User messages pass through unchanged\n\t\tif (msg.role === \"user\") {\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Handle toolResult messages - normalize toolCallId if we have a mapping\n\t\tif (msg.role === \"toolResult\") {\n\t\t\tconst normalizedId = toolCallIdMap.get(msg.toolCallId);\n\t\t\tif (normalizedId && normalizedId !== msg.toolCallId) {\n\t\t\t\treturn { ...msg, toolCallId: normalizedId };\n\t\t\t}\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Assistant messages need transformation check\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tconst isSameModel =\n\t\t\t\tassistantMsg.provider === model.provider &&\n\t\t\t\tassistantMsg.api === model.api &&\n\t\t\t\tassistantMsg.model === model.id;\n\n\t\t\tconst transformedContent = assistantMsg.content.flatMap((block) => {\n\t\t\t\tif (block.type === \"thinking\") {\n\t\t\t\t\t// Redacted thinking is opaque encrypted content, only valid for the same model.\n\t\t\t\t\t// Drop it for cross-model to avoid API errors.\n\t\t\t\t\tif (block.redacted) {\n\t\t\t\t\t\treturn isSameModel ? block : [];\n\t\t\t\t\t}\n\t\t\t\t\t// For same model: keep thinking blocks with signatures (needed for replay)\n\t\t\t\t\t// even if the thinking text is empty (OpenAI encrypted reasoning)\n\t\t\t\t\tif (isSameModel && block.thinkingSignature) return block;\n\t\t\t\t\t// Skip empty thinking blocks, convert others to plain text\n\t\t\t\t\tif (!block.thinking || block.thinking.trim() === \"\") return [];\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.thinking,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"toolCall\") {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\tlet normalizedToolCall: ToolCall = toolCall;\n\n\t\t\t\t\tif (!isSameModel && toolCall.thoughtSignature) {\n\t\t\t\t\t\tnormalizedToolCall = { ...toolCall };\n\t\t\t\t\t\tdelete (normalizedToolCall as { thoughtSignature?: string }).thoughtSignature;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!isSameModel && normalizeToolCallId) {\n\t\t\t\t\t\tconst normalizedId = normalizeToolCallId(toolCall.id, model, assistantMsg);\n\t\t\t\t\t\tif (normalizedId !== toolCall.id) {\n\t\t\t\t\t\t\ttoolCallIdMap.set(toolCall.id, normalizedId);\n\t\t\t\t\t\t\tnormalizedToolCall = { ...normalizedToolCall, id: normalizedId };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn normalizedToolCall;\n\t\t\t\t}\n\n\t\t\t\treturn block;\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\t...assistantMsg,\n\t\t\t\tcontent: transformedContent,\n\t\t\t};\n\t\t}\n\t\treturn msg;\n\t});\n\n\t// Second pass: insert synthetic empty tool results for orphaned tool calls\n\t// This preserves thinking signatures and satisfies API requirements\n\tconst result: Message[] = [];\n\tlet pendingToolCalls: ToolCall[] = [];\n\tlet existingToolResultIds = new Set<string>();\n\tconst insertSyntheticToolResults = () => {\n\t\tif (pendingToolCalls.length > 0) {\n\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t}\n\t\t\t}\n\t\t\tpendingToolCalls = [];\n\t\t\texistingToolResultIds = new Set();\n\t\t}\n\t};\n\n\tfor (let i = 0; i < transformed.length; i++) {\n\t\tconst msg = transformed[i];\n\n\t\tif (msg.role === \"assistant\") {\n\t\t\t// If we have pending orphaned tool calls from a previous assistant, insert synthetic results now\n\t\t\tinsertSyntheticToolResults();\n\n\t\t\t// Skip errored/aborted assistant messages entirely.\n\t\t\t// These are incomplete turns that shouldn't be replayed:\n\t\t\t// - May have partial content (reasoning without message, incomplete tool calls)\n\t\t\t// - Replaying them can cause API errors (e.g., OpenAI \"reasoning without following item\")\n\t\t\t// - The model should retry from the last valid state\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Track tool calls from this assistant message\n\t\t\tconst toolCalls = assistantMsg.content.filter((b) => b.type === \"toolCall\") as ToolCall[];\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tpendingToolCalls = toolCalls;\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\texistingToolResultIds.add(msg.toolCallId);\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"user\") {\n\t\t\t// User message interrupts tool flow - insert synthetic results for orphaned calls\n\t\t\tinsertSyntheticToolResults();\n\t\t\tresult.push(msg);\n\t\t} else {\n\t\t\tresult.push(msg);\n\t\t}\n\t}\n\n\t// If the conversation ends with unresolved tool calls, synthesize results now.\n\tinsertSyntheticToolResults();\n\n\treturn result;\n}\n"]}
package/dist/stream.d.ts DELETED
@@ -1,8 +0,0 @@
1
- import "./providers/register-builtins.js";
2
- import type { Api, AssistantMessage, AssistantMessageEventStream, Context, Model, ProviderStreamOptions, SimpleStreamOptions } from "./types.js";
3
- export { getEnvApiKey } from "./env-api-keys.js";
4
- export declare function stream<TApi extends Api>(model: Model<TApi>, context: Context, options?: ProviderStreamOptions): AssistantMessageEventStream;
5
- export declare function complete<TApi extends Api>(model: Model<TApi>, context: Context, options?: ProviderStreamOptions): Promise<AssistantMessage>;
6
- export declare function streamSimple<TApi extends Api>(model: Model<TApi>, context: Context, options?: SimpleStreamOptions): AssistantMessageEventStream;
7
- export declare function completeSimple<TApi extends Api>(model: Model<TApi>, context: Context, options?: SimpleStreamOptions): Promise<AssistantMessage>;
8
- //# sourceMappingURL=stream.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAG1C,OAAO,KAAK,EACX,GAAG,EACH,gBAAgB,EAChB,2BAA2B,EAC3B,OAAO,EACP,KAAK,EACL,qBAAqB,EACrB,mBAAmB,EAEnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAUjD,wBAAgB,MAAM,CAAC,IAAI,SAAS,GAAG,EACtC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,qBAAqB,GAC7B,2BAA2B,CAG7B;AAED,wBAAsB,QAAQ,CAAC,IAAI,SAAS,GAAG,EAC9C,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CAG3B;AAED,wBAAgB,YAAY,CAAC,IAAI,SAAS,GAAG,EAC5C,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,2BAA2B,CAG7B;AAED,wBAAsB,cAAc,CAAC,IAAI,SAAS,GAAG,EACpD,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAG3B","sourcesContent":["import \"./providers/register-builtins.js\";\n\nimport { getApiProvider } from \"./api-registry.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tModel,\n\tProviderStreamOptions,\n\tSimpleStreamOptions,\n\tStreamOptions,\n} from \"./types.js\";\n\nexport { getEnvApiKey } from \"./env-api-keys.js\";\n\nfunction resolveApiProvider(api: Api) {\n\tconst provider = getApiProvider(api);\n\tif (!provider) {\n\t\tthrow new Error(`No API provider registered for api: ${api}`);\n\t}\n\treturn provider;\n}\n\nexport function stream<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.stream(model, context, options as StreamOptions);\n}\n\nexport async function complete<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = stream(model, context, options);\n\treturn s.result();\n}\n\nexport function streamSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.streamSimple(model, context, options);\n}\n\nexport async function completeSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = streamSimple(model, context, options);\n\treturn s.result();\n}\n"]}
package/dist/stream.js DELETED
@@ -1,27 +0,0 @@
1
- import "./providers/register-builtins.js";
2
- import { getApiProvider } from "./api-registry.js";
3
- export { getEnvApiKey } from "./env-api-keys.js";
4
- function resolveApiProvider(api) {
5
- const provider = getApiProvider(api);
6
- if (!provider) {
7
- throw new Error(`No API provider registered for api: ${api}`);
8
- }
9
- return provider;
10
- }
11
- export function stream(model, context, options) {
12
- const provider = resolveApiProvider(model.api);
13
- return provider.stream(model, context, options);
14
- }
15
- export async function complete(model, context, options) {
16
- const s = stream(model, context, options);
17
- return s.result();
18
- }
19
- export function streamSimple(model, context, options) {
20
- const provider = resolveApiProvider(model.api);
21
- return provider.streamSimple(model, context, options);
22
- }
23
- export async function completeSimple(model, context, options) {
24
- const s = streamSimple(model, context, options);
25
- return s.result();
26
- }
27
- //# sourceMappingURL=stream.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,kCAAkC,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAYnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,SAAS,kBAAkB,CAAC,GAAQ,EAAE;IACrC,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,uCAAuC,GAAG,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,QAAQ,CAAC;AAAA,CAChB;AAED,MAAM,UAAU,MAAM,CACrB,KAAkB,EAClB,OAAgB,EAChB,OAA+B,EACD;IAC9B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAwB,CAAC,CAAC;AAAA,CACjE;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC7B,KAAkB,EAClB,OAAgB,EAChB,OAA+B,EACH;IAC5B,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;AAAA,CAClB;AAED,MAAM,UAAU,YAAY,CAC3B,KAAkB,EAClB,OAAgB,EAChB,OAA6B,EACC;IAC9B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAAA,CACtD;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,KAAkB,EAClB,OAAgB,EAChB,OAA6B,EACD;IAC5B,MAAM,CAAC,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;AAAA,CAClB","sourcesContent":["import \"./providers/register-builtins.js\";\n\nimport { getApiProvider } from \"./api-registry.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tModel,\n\tProviderStreamOptions,\n\tSimpleStreamOptions,\n\tStreamOptions,\n} from \"./types.js\";\n\nexport { getEnvApiKey } from \"./env-api-keys.js\";\n\nfunction resolveApiProvider(api: Api) {\n\tconst provider = getApiProvider(api);\n\tif (!provider) {\n\t\tthrow new Error(`No API provider registered for api: ${api}`);\n\t}\n\treturn provider;\n}\n\nexport function stream<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.stream(model, context, options as StreamOptions);\n}\n\nexport async function complete<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: ProviderStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = stream(model, context, options);\n\treturn s.result();\n}\n\nexport function streamSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream {\n\tconst provider = resolveApiProvider(model.api);\n\treturn provider.streamSimple(model, context, options);\n}\n\nexport async function completeSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = streamSimple(model, context, options);\n\treturn s.result();\n}\n"]}