@psnext/slingcli 2.4.20260507-3 → 2.4.20260509-1

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 (393) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -1
  3. package/bin/sling.js +12 -12
  4. package/node_modules/@aws-sdk/client-bedrock-runtime/package.json +2 -2
  5. package/node_modules/@aws-sdk/token-providers/package.json +1 -1
  6. package/node_modules/{@mariozechner → @earendil-works}/pi-agent-core/dist/agent-loop.js +1 -1
  7. package/node_modules/{@mariozechner → @earendil-works}/pi-agent-core/dist/agent.js +4 -3
  8. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js +526 -0
  9. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.js +243 -0
  10. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +616 -0
  11. package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js +348 -0
  12. package/node_modules/@earendil-works/pi-agent-core/dist/harness/execution-env.js +3 -0
  13. package/node_modules/@earendil-works/pi-agent-core/dist/harness/factory.js +9 -0
  14. package/node_modules/@earendil-works/pi-agent-core/dist/harness/messages.js +102 -0
  15. package/node_modules/@earendil-works/pi-agent-core/dist/harness/prompt-templates.js +194 -0
  16. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/jsonl.js +92 -0
  17. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/memory.js +42 -0
  18. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/shared.js +31 -0
  19. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.js +196 -0
  20. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/jsonl.js +170 -0
  21. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/memory.js +90 -0
  22. package/node_modules/@earendil-works/pi-agent-core/dist/harness/skills.js +258 -0
  23. package/node_modules/@earendil-works/pi-agent-core/dist/harness/system-prompt.js +30 -0
  24. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.js +16 -0
  25. package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.js +97 -0
  26. package/node_modules/@earendil-works/pi-agent-core/dist/index.js +26 -0
  27. package/node_modules/{@mariozechner → @earendil-works}/pi-agent-core/dist/proxy.js +1 -1
  28. package/node_modules/{@mariozechner → @earendil-works}/pi-agent-core/package.json +7 -5
  29. package/node_modules/{@mariozechner → @earendil-works}/pi-ai/dist/cli.js +6 -6
  30. package/node_modules/{@mariozechner → @earendil-works}/pi-ai/dist/env-api-keys.js +1 -0
  31. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +307 -0
  32. package/node_modules/@earendil-works/pi-ai/dist/image-models.js +23 -0
  33. package/node_modules/@earendil-works/pi-ai/dist/images-api-registry.js +22 -0
  34. package/node_modules/@earendil-works/pi-ai/dist/images.js +14 -0
  35. package/node_modules/{@mariozechner → @earendil-works}/pi-ai/dist/index.js +4 -0
  36. package/node_modules/{@mariozechner → @earendil-works}/pi-ai/dist/models.generated.js +427 -122
  37. package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.js +129 -0
  38. package/node_modules/@earendil-works/pi-ai/dist/providers/images/register-builtins.js +34 -0
  39. package/node_modules/{@mariozechner → @earendil-works}/pi-ai/dist/providers/openai-codex-responses.js +1 -1
  40. package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/openai-completions.js +150 -122
  41. package/node_modules/{@mariozechner → @earendil-works}/pi-ai/dist/providers/openai-responses-shared.js +14 -1
  42. package/node_modules/{@mariozechner → @earendil-works}/pi-ai/dist/utils/oauth/openai-codex.js +25 -14
  43. package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/overflow.js +3 -0
  44. package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/package.json +5 -4
  45. package/node_modules/@earendil-works/pi-coding-agent/dist/bun/register-bedrock.js +4 -0
  46. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/cli/args.js +1 -0
  47. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/cli/config-selector.js +1 -1
  48. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/cli/list-models.js +1 -1
  49. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/cli/session-picker.js +1 -1
  50. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/config.js +52 -30
  51. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/agent-session.js +1 -1
  52. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/auth-storage.js +2 -2
  53. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/compaction/branch-summarization.js +1 -1
  54. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/compaction/compaction.js +1 -1
  55. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/utils.js +153 -0
  56. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/export-html/template.css +45 -1
  57. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/export-html/template.js +68 -4
  58. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/extensions/loader.js +26 -12
  59. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/keybindings.js +1 -1
  60. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/model-registry.js +3 -2
  61. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/model-resolver.js +2 -1
  62. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/package-manager.js +22 -5
  63. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/provider-display-names.js +1 -0
  64. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/sdk.js +3 -3
  65. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/bash.js +1 -1
  66. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/edit.js +1 -1
  67. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/find.js +1 -1
  68. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/grep.js +1 -1
  69. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/ls.js +1 -1
  70. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/read.js +3 -2
  71. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/render-utils.js +1 -1
  72. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/truncate.js +205 -0
  73. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/write.js +1 -1
  74. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/main.js +2 -2
  75. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/migrations.js +3 -3
  76. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +1 -1
  77. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +1 -1
  78. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/bordered-loader.js +1 -1
  79. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/branch-summary-message.js +1 -1
  80. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/compaction-summary-message.js +1 -1
  81. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/config-selector.js +25 -3
  82. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/custom-editor.js +1 -1
  83. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/custom-message.js +1 -1
  84. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/earendil-announcement.js +1 -1
  85. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/extension-editor.js +1 -1
  86. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/extension-input.js +1 -1
  87. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/extension-selector.js +1 -1
  88. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/footer.js +1 -1
  89. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/keybinding-hints.js +36 -0
  90. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +4 -3
  91. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/model-selector.js +2 -2
  92. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/oauth-selector.js +1 -1
  93. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/scoped-models-selector.js +1 -1
  94. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/session-selector-search.js +1 -1
  95. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/session-selector.js +1 -1
  96. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +4 -2
  97. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/show-images-selector.js +1 -1
  98. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +1 -1
  99. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/theme-selector.js +1 -1
  100. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/thinking-selector.js +1 -1
  101. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +1 -1
  102. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/tree-selector.js +3 -2
  103. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/user-message-selector.js +1 -1
  104. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/user-message.js +1 -1
  105. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/visual-truncate.js +1 -1
  106. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/interactive-mode.js +47 -32
  107. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/theme/dark.json +1 -1
  108. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/theme/light.json +1 -1
  109. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/theme/theme.js +1 -1
  110. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/package-manager-cli.js +42 -39
  111. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/clipboard.js +9 -2
  112. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/paths.js +16 -0
  113. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/version-check.js +9 -2
  114. package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/package.json +9 -8
  115. package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/components/image.js +14 -7
  116. package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/components/markdown.js +24 -84
  117. package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/terminal-image.js +10 -4
  118. package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/tui.js +73 -4
  119. package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/utils.js +33 -7
  120. package/node_modules/{@mariozechner → @earendil-works}/pi-tui/package.json +3 -3
  121. package/node_modules/@mariozechner/clipboard/README.md +58 -0
  122. package/node_modules/@mariozechner/clipboard/index.d.ts +23 -0
  123. package/node_modules/@mariozechner/clipboard-linux-x64-gnu/README.md +3 -0
  124. package/node_modules/@types/node/README.md +1 -1
  125. package/node_modules/@types/node/http2.d.ts +4 -1
  126. package/node_modules/@types/node/package.json +2 -2
  127. package/node_modules/@types/node/stream/web.d.ts +4 -0
  128. package/node_modules/brace-expansion/dist/commonjs/index.js +1 -1
  129. package/node_modules/brace-expansion/dist/commonjs/index.js.map +1 -1
  130. package/node_modules/brace-expansion/dist/esm/index.js +1 -1
  131. package/node_modules/brace-expansion/dist/esm/index.js.map +1 -1
  132. package/node_modules/brace-expansion/package.json +1 -1
  133. package/node_modules/fast-xml-builder/CHANGELOG.md +4 -0
  134. package/node_modules/fast-xml-builder/lib/fxb.cjs +1 -1
  135. package/node_modules/fast-xml-builder/lib/fxb.d.cts +91 -1
  136. package/node_modules/fast-xml-builder/lib/fxb.min.js +1 -1
  137. package/node_modules/fast-xml-builder/lib/fxb.min.js.map +1 -1
  138. package/node_modules/fast-xml-builder/package.json +3 -2
  139. package/node_modules/fast-xml-builder/src/fxb.d.ts +92 -3
  140. package/node_modules/fast-xml-builder/src/fxb.js +92 -31
  141. package/node_modules/fast-xml-builder/src/orderedJs2Xml.js +87 -33
  142. package/node_modules/get-east-asian-width/lookup-data.js +15 -12
  143. package/node_modules/get-east-asian-width/lookup.js +25 -22
  144. package/node_modules/get-east-asian-width/package.json +1 -1
  145. package/node_modules/jiti/README.md +258 -0
  146. package/node_modules/jiti/dist/babel.cjs +257 -0
  147. package/node_modules/jiti/dist/jiti.cjs +1 -0
  148. package/node_modules/jiti/lib/jiti.mjs +29 -0
  149. package/node_modules/jiti/lib/types.d.ts +420 -0
  150. package/node_modules/jiti/package.json +146 -0
  151. package/node_modules/protobufjs/dist/light/protobuf.js +5 -3
  152. package/node_modules/protobufjs/dist/light/protobuf.js.map +1 -1
  153. package/node_modules/protobufjs/dist/light/protobuf.min.js +3 -3
  154. package/node_modules/protobufjs/dist/light/protobuf.min.js.map +1 -1
  155. package/node_modules/protobufjs/dist/minimal/protobuf.js +2 -2
  156. package/node_modules/protobufjs/dist/minimal/protobuf.min.js +2 -2
  157. package/node_modules/protobufjs/dist/protobuf.js +5 -3
  158. package/node_modules/protobufjs/dist/protobuf.js.map +1 -1
  159. package/node_modules/protobufjs/dist/protobuf.min.js +3 -3
  160. package/node_modules/protobufjs/dist/protobuf.min.js.map +1 -1
  161. package/node_modules/protobufjs/package.json +1 -1
  162. package/node_modules/protobufjs/src/namespace.js +3 -1
  163. package/node_modules/semver/README.md +19 -4
  164. package/node_modules/semver/bin/semver.js +14 -10
  165. package/node_modules/semver/functions/truncate.js +48 -0
  166. package/node_modules/semver/index.js +2 -0
  167. package/node_modules/semver/internal/re.js +1 -1
  168. package/node_modules/semver/package.json +3 -3
  169. package/node_modules/semver/range.bnf +5 -4
  170. package/node_modules/socks/package.json +2 -2
  171. package/node_modules/xml-naming/README.md +189 -0
  172. package/node_modules/xml-naming/package.json +54 -0
  173. package/node_modules/xml-naming/src/index.d.ts +74 -0
  174. package/node_modules/xml-naming/src/index.js +270 -0
  175. package/package.json +6 -6
  176. package/sling-default-packages.json +2 -1
  177. package/slingshot/index.js +442 -23
  178. package/node_modules/@mariozechner/jiti/dist/babel.cjs +0 -246
  179. package/node_modules/@mariozechner/jiti/dist/jiti.cjs +0 -1
  180. package/node_modules/@mariozechner/jiti/package.json +0 -96
  181. package/node_modules/@mariozechner/pi-agent-core/dist/index.js +0 -9
  182. package/node_modules/@mariozechner/pi-agent-core/node_modules/@mariozechner/pi-ai/dist/cli.js +0 -116
  183. package/node_modules/@mariozechner/pi-agent-core/node_modules/@mariozechner/pi-ai/dist/env-api-keys.js +0 -166
  184. package/node_modules/@mariozechner/pi-agent-core/node_modules/@mariozechner/pi-ai/dist/index.js +0 -15
  185. package/node_modules/@mariozechner/pi-agent-core/node_modules/@mariozechner/pi-ai/dist/models.generated.js +0 -16568
  186. package/node_modules/@mariozechner/pi-agent-core/node_modules/@mariozechner/pi-ai/dist/providers/amazon-bedrock.js +0 -753
  187. package/node_modules/@mariozechner/pi-agent-core/node_modules/@mariozechner/pi-ai/dist/providers/openai-codex-responses.js +0 -909
  188. package/node_modules/@mariozechner/pi-agent-core/node_modules/@mariozechner/pi-ai/dist/providers/openai-responses-shared.js +0 -479
  189. package/node_modules/@mariozechner/pi-agent-core/node_modules/@mariozechner/pi-ai/dist/utils/oauth/openai-codex.js +0 -374
  190. package/node_modules/@mariozechner/pi-ai/dist/api-registry.js +0 -44
  191. package/node_modules/@mariozechner/pi-ai/dist/bedrock-provider.js +0 -6
  192. package/node_modules/@mariozechner/pi-ai/dist/models.js +0 -71
  193. package/node_modules/@mariozechner/pi-ai/dist/oauth.js +0 -2
  194. package/node_modules/@mariozechner/pi-ai/dist/providers/anthropic.js +0 -951
  195. package/node_modules/@mariozechner/pi-ai/dist/providers/azure-openai-responses.js +0 -208
  196. package/node_modules/@mariozechner/pi-ai/dist/providers/cloudflare.js +0 -26
  197. package/node_modules/@mariozechner/pi-ai/dist/providers/faux.js +0 -368
  198. package/node_modules/@mariozechner/pi-ai/dist/providers/github-copilot-headers.js +0 -29
  199. package/node_modules/@mariozechner/pi-ai/dist/providers/google-shared.js +0 -329
  200. package/node_modules/@mariozechner/pi-ai/dist/providers/google-vertex.js +0 -442
  201. package/node_modules/@mariozechner/pi-ai/dist/providers/google.js +0 -400
  202. package/node_modules/@mariozechner/pi-ai/dist/providers/mistral.js +0 -535
  203. package/node_modules/@mariozechner/pi-ai/dist/providers/openai-completions.js +0 -908
  204. package/node_modules/@mariozechner/pi-ai/dist/providers/openai-responses.js +0 -220
  205. package/node_modules/@mariozechner/pi-ai/dist/providers/register-builtins.js +0 -243
  206. package/node_modules/@mariozechner/pi-ai/dist/providers/simple-options.js +0 -39
  207. package/node_modules/@mariozechner/pi-ai/dist/providers/transform-messages.js +0 -184
  208. package/node_modules/@mariozechner/pi-ai/dist/stream.js +0 -27
  209. package/node_modules/@mariozechner/pi-ai/dist/types.js +0 -2
  210. package/node_modules/@mariozechner/pi-ai/dist/utils/event-stream.js +0 -81
  211. package/node_modules/@mariozechner/pi-ai/dist/utils/hash.js +0 -14
  212. package/node_modules/@mariozechner/pi-ai/dist/utils/headers.js +0 -8
  213. package/node_modules/@mariozechner/pi-ai/dist/utils/json-parse.js +0 -113
  214. package/node_modules/@mariozechner/pi-ai/dist/utils/oauth/anthropic.js +0 -335
  215. package/node_modules/@mariozechner/pi-ai/dist/utils/oauth/github-copilot.js +0 -292
  216. package/node_modules/@mariozechner/pi-ai/dist/utils/oauth/index.js +0 -121
  217. package/node_modules/@mariozechner/pi-ai/dist/utils/oauth/oauth-page.js +0 -105
  218. package/node_modules/@mariozechner/pi-ai/dist/utils/oauth/pkce.js +0 -31
  219. package/node_modules/@mariozechner/pi-ai/dist/utils/oauth/types.js +0 -2
  220. package/node_modules/@mariozechner/pi-ai/dist/utils/overflow.js +0 -146
  221. package/node_modules/@mariozechner/pi-ai/dist/utils/sanitize-unicode.js +0 -26
  222. package/node_modules/@mariozechner/pi-ai/dist/utils/typebox-helpers.js +0 -21
  223. package/node_modules/@mariozechner/pi-ai/dist/utils/validation.js +0 -281
  224. package/node_modules/@mariozechner/pi-ai/package.json +0 -108
  225. package/node_modules/@mariozechner/pi-coding-agent/dist/bun/register-bedrock.js +0 -4
  226. package/node_modules/@mariozechner/pi-coding-agent/dist/modes/interactive/components/keybinding-hints.js +0 -22
  227. package/node_modules/@mariozechner/pi-coding-agent/node_modules/@mariozechner/pi-agent-core/dist/agent-loop.js +0 -458
  228. package/node_modules/@mariozechner/pi-coding-agent/node_modules/@mariozechner/pi-agent-core/dist/agent.js +0 -398
  229. package/node_modules/@mariozechner/pi-coding-agent/node_modules/@mariozechner/pi-agent-core/dist/index.js +0 -9
  230. package/node_modules/@mariozechner/pi-coding-agent/node_modules/@mariozechner/pi-agent-core/dist/proxy.js +0 -278
  231. package/node_modules/@mariozechner/pi-coding-agent/node_modules/@mariozechner/pi-agent-core/dist/types.js +0 -2
  232. package/node_modules/@mariozechner/pi-coding-agent/node_modules/@mariozechner/pi-agent-core/package.json +0 -45
  233. package/node_modules/socks/.claude/settings.local.json +0 -26
  234. package/node_modules/std-env/LICENCE +0 -22
  235. package/node_modules/std-env/README.md +0 -118
  236. package/node_modules/std-env/dist/index.cjs +0 -1
  237. package/node_modules/std-env/dist/index.d.cts +0 -92
  238. package/node_modules/std-env/dist/index.d.mts +0 -92
  239. package/node_modules/std-env/dist/index.d.ts +0 -92
  240. package/node_modules/std-env/dist/index.mjs +0 -1
  241. package/node_modules/std-env/package.json +0 -46
  242. package/node_modules/yoctocolors/base.d.ts +0 -47
  243. package/node_modules/yoctocolors/base.js +0 -94
  244. package/node_modules/yoctocolors/index.d.ts +0 -2
  245. package/node_modules/yoctocolors/index.js +0 -2
  246. package/node_modules/yoctocolors/license +0 -9
  247. package/node_modules/yoctocolors/package.json +0 -69
  248. package/node_modules/yoctocolors/readme.md +0 -138
  249. /package/node_modules/{@mariozechner/pi-coding-agent/dist/core → @earendil-works/pi-agent-core/dist/harness}/compaction/utils.js +0 -0
  250. /package/node_modules/{@mariozechner/pi-coding-agent/dist/core/tools → @earendil-works/pi-agent-core/dist/harness/utils}/truncate.js +0 -0
  251. /package/node_modules/{@mariozechner → @earendil-works}/pi-agent-core/dist/types.js +0 -0
  252. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/api-registry.js +0 -0
  253. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/bedrock-provider.js +0 -0
  254. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/models.js +0 -0
  255. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/oauth.js +0 -0
  256. /package/node_modules/{@mariozechner → @earendil-works}/pi-ai/dist/providers/amazon-bedrock.js +0 -0
  257. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/anthropic.js +0 -0
  258. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/azure-openai-responses.js +0 -0
  259. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/cloudflare.js +0 -0
  260. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/faux.js +0 -0
  261. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/github-copilot-headers.js +0 -0
  262. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/google-shared.js +0 -0
  263. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/google-vertex.js +0 -0
  264. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/google.js +0 -0
  265. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/mistral.js +0 -0
  266. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/openai-responses.js +0 -0
  267. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/register-builtins.js +0 -0
  268. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/simple-options.js +0 -0
  269. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/providers/transform-messages.js +0 -0
  270. /package/node_modules/{@mariozechner → @earendil-works}/pi-ai/dist/session-resources.js +0 -0
  271. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/stream.js +0 -0
  272. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/types.js +0 -0
  273. /package/node_modules/{@mariozechner → @earendil-works}/pi-ai/dist/utils/diagnostics.js +0 -0
  274. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/event-stream.js +0 -0
  275. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/hash.js +0 -0
  276. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/headers.js +0 -0
  277. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/json-parse.js +0 -0
  278. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/oauth/anthropic.js +0 -0
  279. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/oauth/github-copilot.js +0 -0
  280. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/oauth/index.js +0 -0
  281. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/oauth/oauth-page.js +0 -0
  282. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/oauth/pkce.js +0 -0
  283. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/oauth/types.js +0 -0
  284. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/sanitize-unicode.js +0 -0
  285. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/typebox-helpers.js +0 -0
  286. /package/node_modules/{@mariozechner/pi-agent-core/node_modules/@mariozechner → @earendil-works}/pi-ai/dist/utils/validation.js +0 -0
  287. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/bun/cli.js +0 -0
  288. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/bun/restore-sandbox-env.js +0 -0
  289. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/cli/file-processor.js +0 -0
  290. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/cli/initial-message.js +0 -0
  291. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/cli.js +0 -0
  292. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/agent-session-runtime.js +0 -0
  293. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/agent-session-services.js +0 -0
  294. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/auth-guidance.js +0 -0
  295. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/bash-executor.js +0 -0
  296. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/compaction/index.js +0 -0
  297. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/defaults.js +0 -0
  298. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/diagnostics.js +0 -0
  299. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/event-bus.js +0 -0
  300. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/exec.js +0 -0
  301. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/export-html/ansi-to-html.js +0 -0
  302. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/export-html/index.js +0 -0
  303. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/export-html/template.html +0 -0
  304. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/export-html/tool-renderer.js +0 -0
  305. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/export-html/vendor/highlight.min.js +0 -0
  306. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/export-html/vendor/marked.min.js +0 -0
  307. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/extensions/index.js +0 -0
  308. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/extensions/runner.js +0 -0
  309. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/extensions/types.js +0 -0
  310. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/extensions/wrapper.js +0 -0
  311. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/footer-data-provider.js +0 -0
  312. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/index.js +0 -0
  313. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/messages.js +0 -0
  314. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/output-guard.js +0 -0
  315. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/prompt-templates.js +0 -0
  316. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/resolve-config-value.js +0 -0
  317. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/resource-loader.js +0 -0
  318. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/session-cwd.js +0 -0
  319. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/session-manager.js +0 -0
  320. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/settings-manager.js +0 -0
  321. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/skills.js +0 -0
  322. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/slash-commands.js +0 -0
  323. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/source-info.js +0 -0
  324. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/system-prompt.js +0 -0
  325. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/telemetry.js +0 -0
  326. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/timings.js +0 -0
  327. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/edit-diff.js +0 -0
  328. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/file-mutation-queue.js +0 -0
  329. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/index.js +0 -0
  330. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/output-accumulator.js +0 -0
  331. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/path-utils.js +0 -0
  332. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/core/tools/tool-definition-wrapper.js +0 -0
  333. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/index.js +0 -0
  334. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/index.js +0 -0
  335. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/assets/clankolas.png +0 -0
  336. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/armin.js +0 -0
  337. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/countdown-timer.js +0 -0
  338. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/daxnuts.js +0 -0
  339. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/diff.js +0 -0
  340. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +0 -0
  341. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/components/index.js +0 -0
  342. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/interactive/theme/theme-schema.json +0 -0
  343. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/print-mode.js +0 -0
  344. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/rpc/jsonl.js +0 -0
  345. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/rpc/rpc-client.js +0 -0
  346. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/rpc/rpc-mode.js +0 -0
  347. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/modes/rpc/rpc-types.js +0 -0
  348. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/changelog.js +0 -0
  349. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/child-process.js +0 -0
  350. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/clipboard-image.js +0 -0
  351. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/clipboard-native.js +0 -0
  352. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/exif-orientation.js +0 -0
  353. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/frontmatter.js +0 -0
  354. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/fs-watch.js +0 -0
  355. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/git.js +0 -0
  356. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/image-convert.js +0 -0
  357. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/image-resize.js +0 -0
  358. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/mime.js +0 -0
  359. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/photon.js +0 -0
  360. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/pi-user-agent.js +0 -0
  361. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/shell.js +0 -0
  362. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/sleep.js +0 -0
  363. /package/node_modules/{@mariozechner → @earendil-works}/pi-coding-agent/dist/utils/tools-manager.js +0 -0
  364. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/autocomplete.js +0 -0
  365. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/components/box.js +0 -0
  366. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/components/cancellable-loader.js +0 -0
  367. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/components/editor.js +0 -0
  368. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/components/input.js +0 -0
  369. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/components/loader.js +0 -0
  370. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/components/select-list.js +0 -0
  371. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/components/settings-list.js +0 -0
  372. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/components/spacer.js +0 -0
  373. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/components/text.js +0 -0
  374. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/components/truncated-text.js +0 -0
  375. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/editor-component.js +0 -0
  376. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/fuzzy.js +0 -0
  377. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/index.js +0 -0
  378. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/keybindings.js +0 -0
  379. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/keys.js +0 -0
  380. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/kill-ring.js +0 -0
  381. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/stdin-buffer.js +0 -0
  382. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/terminal.js +0 -0
  383. /package/node_modules/{@mariozechner → @earendil-works}/pi-tui/dist/undo-stack.js +0 -0
  384. /package/node_modules/{@mariozechner/jiti → jiti}/LICENSE +0 -0
  385. /package/node_modules/{@mariozechner/jiti → jiti}/lib/jiti-cli.mjs +0 -0
  386. /package/node_modules/{@mariozechner/jiti → jiti}/lib/jiti-hooks.mjs +0 -0
  387. /package/node_modules/{@mariozechner/jiti → jiti}/lib/jiti-native.mjs +0 -0
  388. /package/node_modules/{@mariozechner/jiti → jiti}/lib/jiti-register.d.mts +0 -0
  389. /package/node_modules/{@mariozechner/jiti → jiti}/lib/jiti-register.mjs +0 -0
  390. /package/node_modules/{@mariozechner/jiti/lib/jiti.mjs → jiti/lib/jiti-static.mjs} +0 -0
  391. /package/node_modules/{@mariozechner/jiti → jiti}/lib/jiti.cjs +0 -0
  392. /package/node_modules/{@mariozechner/jiti → jiti}/lib/jiti.d.cts +0 -0
  393. /package/node_modules/{@mariozechner/jiti → jiti}/lib/jiti.d.mts +0 -0
@@ -1,908 +0,0 @@
1
- import OpenAI from "openai";
2
- import { getEnvApiKey } from "../env-api-keys.js";
3
- import { calculateCost, clampThinkingLevel } from "../models.js";
4
- import { AssistantMessageEventStream } from "../utils/event-stream.js";
5
- import { headersToRecord } from "../utils/headers.js";
6
- import { parseStreamingJson } from "../utils/json-parse.js";
7
- import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
8
- import { isCloudflareProvider, resolveCloudflareBaseUrl } from "./cloudflare.js";
9
- import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
10
- import { buildBaseOptions } from "./simple-options.js";
11
- import { transformMessages } from "./transform-messages.js";
12
- /**
13
- * Check if conversation messages contain tool calls or tool results.
14
- * This is needed because Anthropic (via proxy) requires the tools param
15
- * to be present when messages include tool_calls or tool role messages.
16
- */
17
- function hasToolHistory(messages) {
18
- for (const msg of messages) {
19
- if (msg.role === "toolResult") {
20
- return true;
21
- }
22
- if (msg.role === "assistant") {
23
- if (msg.content.some((block) => block.type === "toolCall")) {
24
- return true;
25
- }
26
- }
27
- }
28
- return false;
29
- }
30
- function isTextContentBlock(block) {
31
- return block.type === "text";
32
- }
33
- function isThinkingContentBlock(block) {
34
- return block.type === "thinking";
35
- }
36
- function isToolCallBlock(block) {
37
- return block.type === "toolCall";
38
- }
39
- function isImageContentBlock(block) {
40
- return block.type === "image";
41
- }
42
- function resolveCacheRetention(cacheRetention) {
43
- if (cacheRetention) {
44
- return cacheRetention;
45
- }
46
- if (typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long") {
47
- return "long";
48
- }
49
- return "short";
50
- }
51
- export const streamOpenAICompletions = (model, context, options) => {
52
- const stream = new AssistantMessageEventStream();
53
- (async () => {
54
- const output = {
55
- role: "assistant",
56
- content: [],
57
- api: model.api,
58
- provider: model.provider,
59
- model: model.id,
60
- usage: {
61
- input: 0,
62
- output: 0,
63
- cacheRead: 0,
64
- cacheWrite: 0,
65
- totalTokens: 0,
66
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
67
- },
68
- stopReason: "stop",
69
- timestamp: Date.now(),
70
- };
71
- try {
72
- const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
73
- const compat = getCompat(model);
74
- const cacheRetention = resolveCacheRetention(options?.cacheRetention);
75
- const cacheSessionId = cacheRetention === "none" ? undefined : options?.sessionId;
76
- const client = createClient(model, context, apiKey, options?.headers, cacheSessionId, compat);
77
- let params = buildParams(model, context, options, compat, cacheRetention);
78
- const nextParams = await options?.onPayload?.(params, model);
79
- if (nextParams !== undefined) {
80
- params = nextParams;
81
- }
82
- const requestOptions = {
83
- ...(options?.signal ? { signal: options.signal } : {}),
84
- ...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
85
- ...(options?.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}),
86
- };
87
- const { data: openaiStream, response } = await client.chat.completions
88
- .create(params, requestOptions)
89
- .withResponse();
90
- await options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);
91
- stream.push({ type: "start", partial: output });
92
- let currentBlock = null;
93
- const blocks = output.content;
94
- const getContentIndex = (block) => (block ? blocks.indexOf(block) : -1);
95
- const currentContentIndex = () => getContentIndex(currentBlock);
96
- const finishCurrentBlock = (block) => {
97
- if (block) {
98
- const contentIndex = getContentIndex(block);
99
- if (contentIndex === -1) {
100
- return;
101
- }
102
- if (block.type === "text") {
103
- stream.push({
104
- type: "text_end",
105
- contentIndex,
106
- content: block.text,
107
- partial: output,
108
- });
109
- }
110
- else if (block.type === "thinking") {
111
- stream.push({
112
- type: "thinking_end",
113
- contentIndex,
114
- content: block.thinking,
115
- partial: output,
116
- });
117
- }
118
- else if (block.type === "toolCall") {
119
- block.arguments = parseStreamingJson(block.partialArgs);
120
- // Finalize in-place and strip the scratch buffers so replay only
121
- // carries parsed arguments.
122
- delete block.partialArgs;
123
- delete block.streamIndex;
124
- stream.push({
125
- type: "toolcall_end",
126
- contentIndex,
127
- toolCall: block,
128
- partial: output,
129
- });
130
- }
131
- }
132
- };
133
- for await (const chunk of openaiStream) {
134
- if (!chunk || typeof chunk !== "object")
135
- continue;
136
- // OpenAI documents ChatCompletionChunk.id as the unique chat completion identifier,
137
- // and each chunk in a streamed completion carries the same id.
138
- output.responseId ||= chunk.id;
139
- if (typeof chunk.model === "string" && chunk.model.length > 0 && chunk.model !== model.id) {
140
- output.responseModel ||= chunk.model;
141
- }
142
- if (chunk.usage) {
143
- output.usage = parseChunkUsage(chunk.usage, model);
144
- }
145
- const choice = Array.isArray(chunk.choices) ? chunk.choices[0] : undefined;
146
- if (!choice)
147
- continue;
148
- // Fallback: some providers (e.g., Moonshot) return usage
149
- // in choice.usage instead of the standard chunk.usage
150
- if (!chunk.usage && choice.usage) {
151
- output.usage = parseChunkUsage(choice.usage, model);
152
- }
153
- if (choice.finish_reason) {
154
- const finishReasonResult = mapStopReason(choice.finish_reason);
155
- output.stopReason = finishReasonResult.stopReason;
156
- if (finishReasonResult.errorMessage) {
157
- output.errorMessage = finishReasonResult.errorMessage;
158
- }
159
- }
160
- if (choice.delta) {
161
- if (choice.delta.content !== null &&
162
- choice.delta.content !== undefined &&
163
- choice.delta.content.length > 0) {
164
- if (!currentBlock || currentBlock.type !== "text") {
165
- finishCurrentBlock(currentBlock);
166
- currentBlock = { type: "text", text: "" };
167
- output.content.push(currentBlock);
168
- stream.push({ type: "text_start", contentIndex: currentContentIndex(), partial: output });
169
- }
170
- if (currentBlock.type === "text") {
171
- currentBlock.text += choice.delta.content;
172
- stream.push({
173
- type: "text_delta",
174
- contentIndex: currentContentIndex(),
175
- delta: choice.delta.content,
176
- partial: output,
177
- });
178
- }
179
- }
180
- // Some endpoints return reasoning in reasoning_content (llama.cpp),
181
- // or reasoning (other openai compatible endpoints)
182
- // Use the first non-empty reasoning field to avoid duplication
183
- // (e.g., chutes.ai returns both reasoning_content and reasoning with same content)
184
- const reasoningFields = ["reasoning_content", "reasoning", "reasoning_text"];
185
- let foundReasoningField = null;
186
- for (const field of reasoningFields) {
187
- if (choice.delta[field] !== null &&
188
- choice.delta[field] !== undefined &&
189
- choice.delta[field].length > 0) {
190
- if (!foundReasoningField) {
191
- foundReasoningField = field;
192
- break;
193
- }
194
- }
195
- }
196
- if (foundReasoningField) {
197
- if (!currentBlock || currentBlock.type !== "thinking") {
198
- finishCurrentBlock(currentBlock);
199
- currentBlock = {
200
- type: "thinking",
201
- thinking: "",
202
- thinkingSignature: foundReasoningField,
203
- };
204
- output.content.push(currentBlock);
205
- stream.push({ type: "thinking_start", contentIndex: currentContentIndex(), partial: output });
206
- }
207
- if (currentBlock.type === "thinking") {
208
- const delta = choice.delta[foundReasoningField];
209
- currentBlock.thinking += delta;
210
- stream.push({
211
- type: "thinking_delta",
212
- contentIndex: currentContentIndex(),
213
- delta,
214
- partial: output,
215
- });
216
- }
217
- }
218
- if (choice?.delta?.tool_calls) {
219
- for (const toolCall of choice.delta.tool_calls) {
220
- const streamIndex = typeof toolCall.index === "number" ? toolCall.index : undefined;
221
- const sameToolCall = currentBlock?.type === "toolCall" &&
222
- ((streamIndex !== undefined && currentBlock.streamIndex === streamIndex) ||
223
- (streamIndex === undefined && toolCall.id && currentBlock.id === toolCall.id));
224
- if (!sameToolCall) {
225
- finishCurrentBlock(currentBlock);
226
- currentBlock = {
227
- type: "toolCall",
228
- id: toolCall.id || "",
229
- name: toolCall.function?.name || "",
230
- arguments: {},
231
- partialArgs: "",
232
- streamIndex,
233
- };
234
- output.content.push(currentBlock);
235
- stream.push({
236
- type: "toolcall_start",
237
- contentIndex: getContentIndex(currentBlock),
238
- partial: output,
239
- });
240
- }
241
- const currentToolCallBlock = currentBlock?.type === "toolCall" ? currentBlock : null;
242
- if (currentToolCallBlock) {
243
- if (!currentToolCallBlock.id && toolCall.id)
244
- currentToolCallBlock.id = toolCall.id;
245
- if (!currentToolCallBlock.name && toolCall.function?.name) {
246
- currentToolCallBlock.name = toolCall.function.name;
247
- }
248
- if (currentToolCallBlock.streamIndex === undefined && streamIndex !== undefined) {
249
- currentToolCallBlock.streamIndex = streamIndex;
250
- }
251
- let delta = "";
252
- if (toolCall.function?.arguments) {
253
- delta = toolCall.function.arguments;
254
- currentToolCallBlock.partialArgs += toolCall.function.arguments;
255
- currentToolCallBlock.arguments = parseStreamingJson(currentToolCallBlock.partialArgs);
256
- }
257
- stream.push({
258
- type: "toolcall_delta",
259
- contentIndex: getContentIndex(currentToolCallBlock),
260
- delta,
261
- partial: output,
262
- });
263
- }
264
- }
265
- }
266
- const reasoningDetails = choice.delta.reasoning_details;
267
- if (reasoningDetails && Array.isArray(reasoningDetails)) {
268
- for (const detail of reasoningDetails) {
269
- if (detail.type === "reasoning.encrypted" && detail.id && detail.data) {
270
- const matchingToolCall = output.content.find((b) => b.type === "toolCall" && b.id === detail.id);
271
- if (matchingToolCall) {
272
- matchingToolCall.thoughtSignature = JSON.stringify(detail);
273
- }
274
- }
275
- }
276
- }
277
- }
278
- }
279
- finishCurrentBlock(currentBlock);
280
- if (options?.signal?.aborted) {
281
- throw new Error("Request was aborted");
282
- }
283
- if (output.stopReason === "aborted") {
284
- throw new Error("Request was aborted");
285
- }
286
- if (output.stopReason === "error") {
287
- throw new Error(output.errorMessage || "Provider returned an error stop reason");
288
- }
289
- stream.push({ type: "done", reason: output.stopReason, message: output });
290
- stream.end();
291
- }
292
- catch (error) {
293
- for (const block of output.content) {
294
- delete block.index;
295
- // Streaming scratch buffers are only used during parsing; never persist them.
296
- delete block.partialArgs;
297
- delete block.streamIndex;
298
- }
299
- output.stopReason = options?.signal?.aborted ? "aborted" : "error";
300
- output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
301
- // Some providers via OpenRouter give additional information in this field.
302
- const rawMetadata = error?.error?.metadata?.raw;
303
- if (rawMetadata)
304
- output.errorMessage += `\n${rawMetadata}`;
305
- stream.push({ type: "error", reason: output.stopReason, error: output });
306
- stream.end();
307
- }
308
- })();
309
- return stream;
310
- };
311
- export const streamSimpleOpenAICompletions = (model, context, options) => {
312
- const apiKey = options?.apiKey || getEnvApiKey(model.provider);
313
- if (!apiKey) {
314
- throw new Error(`No API key for provider: ${model.provider}`);
315
- }
316
- const base = buildBaseOptions(model, options, apiKey);
317
- const clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;
318
- const reasoningEffort = clampedReasoning === "off" ? undefined : clampedReasoning;
319
- const toolChoice = options?.toolChoice;
320
- return streamOpenAICompletions(model, context, {
321
- ...base,
322
- reasoningEffort,
323
- toolChoice,
324
- });
325
- };
326
- function createClient(model, context, apiKey, optionsHeaders, sessionId, compat = getCompat(model)) {
327
- if (!apiKey) {
328
- if (!process.env.OPENAI_API_KEY) {
329
- throw new Error("OpenAI API key is required. Set OPENAI_API_KEY environment variable or pass it as an argument.");
330
- }
331
- apiKey = process.env.OPENAI_API_KEY;
332
- }
333
- const headers = { ...model.headers };
334
- if (model.provider === "github-copilot") {
335
- const hasImages = hasCopilotVisionInput(context.messages);
336
- const copilotHeaders = buildCopilotDynamicHeaders({
337
- messages: context.messages,
338
- hasImages,
339
- });
340
- Object.assign(headers, copilotHeaders);
341
- }
342
- if (sessionId && compat.sendSessionAffinityHeaders) {
343
- headers.session_id = sessionId;
344
- headers["x-client-request-id"] = sessionId;
345
- headers["x-session-affinity"] = sessionId;
346
- }
347
- // Merge options headers last so they can override defaults
348
- if (optionsHeaders) {
349
- Object.assign(headers, optionsHeaders);
350
- }
351
- const defaultHeaders = model.provider === "cloudflare-ai-gateway"
352
- ? {
353
- ...headers,
354
- Authorization: headers.Authorization ?? null,
355
- "cf-aig-authorization": `Bearer ${apiKey}`,
356
- }
357
- : headers;
358
- return new OpenAI({
359
- apiKey,
360
- baseURL: isCloudflareProvider(model.provider) ? resolveCloudflareBaseUrl(model) : model.baseUrl,
361
- dangerouslyAllowBrowser: true,
362
- defaultHeaders,
363
- });
364
- }
365
- function buildParams(model, context, options, compat = getCompat(model), cacheRetention = resolveCacheRetention(options?.cacheRetention)) {
366
- const messages = convertMessages(model, context, compat);
367
- const cacheControl = getCompatCacheControl(compat, cacheRetention);
368
- const params = {
369
- model: model.id,
370
- messages,
371
- stream: true,
372
- prompt_cache_key: (model.baseUrl.includes("api.openai.com") && cacheRetention !== "none") ||
373
- (cacheRetention === "long" && compat.supportsLongCacheRetention)
374
- ? options?.sessionId
375
- : undefined,
376
- prompt_cache_retention: cacheRetention === "long" && compat.supportsLongCacheRetention ? "24h" : undefined,
377
- };
378
- if (compat.supportsUsageInStreaming !== false) {
379
- params.stream_options = { include_usage: true };
380
- }
381
- if (compat.supportsStore) {
382
- params.store = false;
383
- }
384
- if (options?.maxTokens) {
385
- if (compat.maxTokensField === "max_tokens") {
386
- params.max_tokens = options.maxTokens;
387
- }
388
- else {
389
- params.max_completion_tokens = options.maxTokens;
390
- }
391
- }
392
- if (options?.temperature !== undefined) {
393
- params.temperature = options.temperature;
394
- }
395
- if (context.tools && context.tools.length > 0) {
396
- params.tools = convertTools(context.tools, compat);
397
- if (compat.zaiToolStream) {
398
- params.tool_stream = true;
399
- }
400
- }
401
- else if (hasToolHistory(context.messages)) {
402
- // Anthropic (via LiteLLM/proxy) requires tools param when conversation has tool_calls/tool_results
403
- params.tools = [];
404
- }
405
- if (cacheControl) {
406
- applyAnthropicCacheControl(messages, params.tools, cacheControl);
407
- }
408
- if (options?.toolChoice) {
409
- params.tool_choice = options.toolChoice;
410
- }
411
- if (compat.thinkingFormat === "zai" && model.reasoning) {
412
- params.enable_thinking = !!options?.reasoningEffort;
413
- }
414
- else if (compat.thinkingFormat === "qwen" && model.reasoning) {
415
- params.enable_thinking = !!options?.reasoningEffort;
416
- }
417
- else if (compat.thinkingFormat === "qwen-chat-template" && model.reasoning) {
418
- params.chat_template_kwargs = {
419
- enable_thinking: !!options?.reasoningEffort,
420
- preserve_thinking: true,
421
- };
422
- }
423
- else if (compat.thinkingFormat === "deepseek" && model.reasoning) {
424
- params.thinking = { type: options?.reasoningEffort ? "enabled" : "disabled" };
425
- if (options?.reasoningEffort) {
426
- params.reasoning_effort =
427
- model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
428
- }
429
- }
430
- else if (compat.thinkingFormat === "openrouter" && model.reasoning) {
431
- // OpenRouter normalizes reasoning across providers via a nested reasoning object.
432
- const openRouterParams = params;
433
- if (options?.reasoningEffort) {
434
- openRouterParams.reasoning = {
435
- effort: model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort,
436
- };
437
- }
438
- else if (model.thinkingLevelMap?.off !== null) {
439
- openRouterParams.reasoning = { effort: model.thinkingLevelMap?.off ?? "none" };
440
- }
441
- }
442
- else if (options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) {
443
- // OpenAI-style reasoning_effort
444
- params.reasoning_effort = model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
445
- }
446
- else if (!options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) {
447
- const offValue = model.thinkingLevelMap?.off;
448
- if (typeof offValue === "string") {
449
- params.reasoning_effort = offValue;
450
- }
451
- }
452
- // OpenRouter provider routing preferences
453
- if (model.baseUrl.includes("openrouter.ai") && model.compat?.openRouterRouting) {
454
- params.provider = model.compat.openRouterRouting;
455
- }
456
- // Vercel AI Gateway provider routing preferences
457
- if (model.baseUrl.includes("ai-gateway.vercel.sh") && model.compat?.vercelGatewayRouting) {
458
- const routing = model.compat.vercelGatewayRouting;
459
- if (routing.only || routing.order) {
460
- const gatewayOptions = {};
461
- if (routing.only)
462
- gatewayOptions.only = routing.only;
463
- if (routing.order)
464
- gatewayOptions.order = routing.order;
465
- params.providerOptions = { gateway: gatewayOptions };
466
- }
467
- }
468
- return params;
469
- }
470
- function getCompatCacheControl(compat, cacheRetention) {
471
- if (compat.cacheControlFormat !== "anthropic" || cacheRetention === "none") {
472
- return undefined;
473
- }
474
- const ttl = cacheRetention === "long" && compat.supportsLongCacheRetention ? "1h" : undefined;
475
- return { type: "ephemeral", ...(ttl ? { ttl } : {}) };
476
- }
477
- function applyAnthropicCacheControl(messages, tools, cacheControl) {
478
- addCacheControlToSystemPrompt(messages, cacheControl);
479
- addCacheControlToLastTool(tools, cacheControl);
480
- addCacheControlToLastConversationMessage(messages, cacheControl);
481
- }
482
- function addCacheControlToSystemPrompt(messages, cacheControl) {
483
- for (const message of messages) {
484
- if (message.role === "system" || message.role === "developer") {
485
- addCacheControlToInstructionMessage(message, cacheControl);
486
- return;
487
- }
488
- }
489
- }
490
- function addCacheControlToLastConversationMessage(messages, cacheControl) {
491
- for (let i = messages.length - 1; i >= 0; i--) {
492
- const message = messages[i];
493
- if (message.role === "user" || message.role === "assistant") {
494
- if (addCacheControlToMessage(message, cacheControl)) {
495
- return;
496
- }
497
- }
498
- }
499
- }
500
- function addCacheControlToLastTool(tools, cacheControl) {
501
- if (!tools || tools.length === 0) {
502
- return;
503
- }
504
- const lastTool = tools[tools.length - 1];
505
- lastTool.cache_control = cacheControl;
506
- }
507
- function addCacheControlToInstructionMessage(message, cacheControl) {
508
- return addCacheControlToTextContent(message, cacheControl);
509
- }
510
- function addCacheControlToMessage(message, cacheControl) {
511
- if (message.role === "user" || message.role === "assistant") {
512
- return addCacheControlToTextContent(message, cacheControl);
513
- }
514
- return false;
515
- }
516
- function addCacheControlToTextContent(message, cacheControl) {
517
- const content = message.content;
518
- if (typeof content === "string") {
519
- if (content.length === 0) {
520
- return false;
521
- }
522
- message.content = [
523
- {
524
- type: "text",
525
- text: content,
526
- cache_control: cacheControl,
527
- },
528
- ];
529
- return true;
530
- }
531
- if (!Array.isArray(content)) {
532
- return false;
533
- }
534
- for (let i = content.length - 1; i >= 0; i--) {
535
- const part = content[i];
536
- if (part?.type === "text") {
537
- const textPart = part;
538
- textPart.cache_control = cacheControl;
539
- return true;
540
- }
541
- }
542
- return false;
543
- }
544
- export function convertMessages(model, context, compat) {
545
- const params = [];
546
- const normalizeToolCallId = (id) => {
547
- // Handle pipe-separated IDs from OpenAI Responses API
548
- // Format: {call_id}|{id} where {id} can be 400+ chars with special chars (+, /, =)
549
- // These come from providers like github-copilot, openai-codex, opencode
550
- // Extract just the call_id part and normalize it
551
- if (id.includes("|")) {
552
- const [callId] = id.split("|");
553
- // Sanitize to allowed chars and truncate to 40 chars (OpenAI limit)
554
- return callId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 40);
555
- }
556
- if (model.provider === "openai")
557
- return id.length > 40 ? id.slice(0, 40) : id;
558
- return id;
559
- };
560
- const transformedMessages = transformMessages(context.messages, model, (id) => normalizeToolCallId(id));
561
- if (context.systemPrompt) {
562
- const useDeveloperRole = model.reasoning && compat.supportsDeveloperRole;
563
- const role = useDeveloperRole ? "developer" : "system";
564
- params.push({ role: role, content: sanitizeSurrogates(context.systemPrompt) });
565
- }
566
- let lastRole = null;
567
- for (let i = 0; i < transformedMessages.length; i++) {
568
- const msg = transformedMessages[i];
569
- // Some providers don't allow user messages directly after tool results
570
- // Insert a synthetic assistant message to bridge the gap
571
- if (compat.requiresAssistantAfterToolResult && lastRole === "toolResult" && msg.role === "user") {
572
- params.push({
573
- role: "assistant",
574
- content: "I have processed the tool results.",
575
- });
576
- }
577
- if (msg.role === "user") {
578
- if (typeof msg.content === "string") {
579
- params.push({
580
- role: "user",
581
- content: sanitizeSurrogates(msg.content),
582
- });
583
- }
584
- else {
585
- const content = msg.content.map((item) => {
586
- if (item.type === "text") {
587
- return {
588
- type: "text",
589
- text: sanitizeSurrogates(item.text),
590
- };
591
- }
592
- else {
593
- return {
594
- type: "image_url",
595
- image_url: {
596
- url: `data:${item.mimeType};base64,${item.data}`,
597
- },
598
- };
599
- }
600
- });
601
- if (content.length === 0)
602
- continue;
603
- params.push({
604
- role: "user",
605
- content,
606
- });
607
- }
608
- }
609
- else if (msg.role === "assistant") {
610
- // Some providers don't accept null content, use empty string instead
611
- const assistantMsg = {
612
- role: "assistant",
613
- content: compat.requiresAssistantAfterToolResult ? "" : null,
614
- };
615
- const assistantTextParts = msg.content
616
- .filter(isTextContentBlock)
617
- .filter((block) => block.text.trim().length > 0)
618
- .map((block) => ({
619
- type: "text",
620
- text: sanitizeSurrogates(block.text),
621
- }));
622
- const assistantText = assistantTextParts.map((part) => part.text).join("");
623
- const nonEmptyThinkingBlocks = msg.content
624
- .filter(isThinkingContentBlock)
625
- .filter((block) => block.thinking.trim().length > 0);
626
- if (nonEmptyThinkingBlocks.length > 0) {
627
- if (compat.requiresThinkingAsText) {
628
- // Convert thinking blocks to plain text (no tags to avoid model mimicking them)
629
- const thinkingText = nonEmptyThinkingBlocks
630
- .map((block) => sanitizeSurrogates(block.thinking))
631
- .join("\n\n");
632
- assistantMsg.content = [{ type: "text", text: thinkingText }, ...assistantTextParts];
633
- }
634
- else {
635
- // Always send assistant content as a plain string (OpenAI Chat Completions
636
- // API standard format). Sending as an array of {type:"text", text:"..."}
637
- // objects is non-standard and causes some models (e.g. DeepSeek V3.2 via
638
- // NVIDIA NIM) to mirror the content-block structure literally in their
639
- // output, producing recursive nesting like [{'type':'text','text':'[{...}]'}].
640
- if (assistantText.length > 0) {
641
- assistantMsg.content = assistantText;
642
- }
643
- // Use the signature from the first thinking block if available (for llama.cpp server + gpt-oss)
644
- const signature = nonEmptyThinkingBlocks[0].thinkingSignature;
645
- if (signature && signature.length > 0) {
646
- assistantMsg[signature] = nonEmptyThinkingBlocks.map((block) => block.thinking).join("\n");
647
- }
648
- }
649
- }
650
- else if (assistantText.length > 0) {
651
- // Always send assistant content as a plain string (OpenAI Chat Completions
652
- // API standard format). Sending as an array of {type:"text", text:"..."}
653
- // objects is non-standard and causes some models (e.g. DeepSeek V3.2 via
654
- // NVIDIA NIM) to mirror the content-block structure literally in their
655
- // output, producing recursive nesting like [{'type':'text','text':'[{...}]'}].
656
- assistantMsg.content = assistantText;
657
- }
658
- const toolCalls = msg.content.filter(isToolCallBlock);
659
- if (toolCalls.length > 0) {
660
- assistantMsg.tool_calls = toolCalls.map((tc) => ({
661
- id: tc.id,
662
- type: "function",
663
- function: {
664
- name: tc.name,
665
- arguments: JSON.stringify(tc.arguments),
666
- },
667
- }));
668
- const reasoningDetails = toolCalls
669
- .filter((tc) => tc.thoughtSignature)
670
- .map((tc) => {
671
- try {
672
- return JSON.parse(tc.thoughtSignature);
673
- }
674
- catch {
675
- return null;
676
- }
677
- })
678
- .filter(Boolean);
679
- if (reasoningDetails.length > 0) {
680
- assistantMsg.reasoning_details = reasoningDetails;
681
- }
682
- }
683
- if (compat.requiresReasoningContentOnAssistantMessages &&
684
- model.reasoning &&
685
- assistantMsg.reasoning_content === undefined) {
686
- assistantMsg.reasoning_content = "";
687
- }
688
- // Skip assistant messages that have no content and no tool calls.
689
- // Some providers require "either content or tool_calls, but not none".
690
- // Other providers also don't accept empty assistant messages.
691
- // This handles aborted assistant responses that got no content.
692
- const content = assistantMsg.content;
693
- const hasContent = content !== null &&
694
- content !== undefined &&
695
- (typeof content === "string" ? content.length > 0 : content.length > 0);
696
- if (!hasContent && !assistantMsg.tool_calls) {
697
- continue;
698
- }
699
- params.push(assistantMsg);
700
- }
701
- else if (msg.role === "toolResult") {
702
- const imageBlocks = [];
703
- let j = i;
704
- for (; j < transformedMessages.length && transformedMessages[j].role === "toolResult"; j++) {
705
- const toolMsg = transformedMessages[j];
706
- // Extract text and image content
707
- const textResult = toolMsg.content
708
- .filter(isTextContentBlock)
709
- .map((block) => block.text)
710
- .join("\n");
711
- const hasImages = toolMsg.content.some((c) => c.type === "image");
712
- // Always send tool result with text (or placeholder if only images)
713
- const hasText = textResult.length > 0;
714
- // Some providers require the 'name' field in tool results
715
- const toolResultMsg = {
716
- role: "tool",
717
- content: sanitizeSurrogates(hasText ? textResult : "(see attached image)"),
718
- tool_call_id: toolMsg.toolCallId,
719
- };
720
- if (compat.requiresToolResultName && toolMsg.toolName) {
721
- toolResultMsg.name = toolMsg.toolName;
722
- }
723
- params.push(toolResultMsg);
724
- if (hasImages && model.input.includes("image")) {
725
- for (const block of toolMsg.content) {
726
- if (isImageContentBlock(block)) {
727
- imageBlocks.push({
728
- type: "image_url",
729
- image_url: {
730
- url: `data:${block.mimeType};base64,${block.data}`,
731
- },
732
- });
733
- }
734
- }
735
- }
736
- }
737
- i = j - 1;
738
- if (imageBlocks.length > 0) {
739
- if (compat.requiresAssistantAfterToolResult) {
740
- params.push({
741
- role: "assistant",
742
- content: "I have processed the tool results.",
743
- });
744
- }
745
- params.push({
746
- role: "user",
747
- content: [
748
- {
749
- type: "text",
750
- text: "Attached image(s) from tool result:",
751
- },
752
- ...imageBlocks,
753
- ],
754
- });
755
- lastRole = "user";
756
- }
757
- else {
758
- lastRole = "toolResult";
759
- }
760
- continue;
761
- }
762
- lastRole = msg.role;
763
- }
764
- return params;
765
- }
766
- function convertTools(tools, compat) {
767
- return tools.map((tool) => ({
768
- type: "function",
769
- function: {
770
- name: tool.name,
771
- description: tool.description,
772
- parameters: tool.parameters, // TypeBox already generates JSON Schema
773
- // Only include strict if provider supports it. Some reject unknown fields.
774
- ...(compat.supportsStrictMode !== false && { strict: false }),
775
- },
776
- }));
777
- }
778
- function parseChunkUsage(rawUsage, model) {
779
- const promptTokens = rawUsage.prompt_tokens || 0;
780
- const reportedCachedTokens = rawUsage.prompt_tokens_details?.cached_tokens ?? rawUsage.prompt_cache_hit_tokens ?? 0;
781
- const cacheWriteTokens = rawUsage.prompt_tokens_details?.cache_write_tokens || 0;
782
- // Normalize to pi-ai semantics:
783
- // - cacheRead: hits from cache created by previous requests only
784
- // - cacheWrite: tokens written to cache in this request
785
- // Some OpenAI-compatible providers (observed on OpenRouter) report cached_tokens
786
- // as (previous hits + current writes). In that case, remove cacheWrite from cacheRead.
787
- const cacheReadTokens = cacheWriteTokens > 0 ? Math.max(0, reportedCachedTokens - cacheWriteTokens) : reportedCachedTokens;
788
- const input = Math.max(0, promptTokens - cacheReadTokens - cacheWriteTokens);
789
- // OpenAI completion_tokens already includes reasoning_tokens.
790
- const outputTokens = rawUsage.completion_tokens || 0;
791
- const usage = {
792
- input,
793
- output: outputTokens,
794
- cacheRead: cacheReadTokens,
795
- cacheWrite: cacheWriteTokens,
796
- totalTokens: input + outputTokens + cacheReadTokens + cacheWriteTokens,
797
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
798
- };
799
- calculateCost(model, usage);
800
- return usage;
801
- }
802
- function mapStopReason(reason) {
803
- if (reason === null)
804
- return { stopReason: "stop" };
805
- switch (reason) {
806
- case "stop":
807
- case "end":
808
- return { stopReason: "stop" };
809
- case "length":
810
- return { stopReason: "length" };
811
- case "function_call":
812
- case "tool_calls":
813
- return { stopReason: "toolUse" };
814
- case "content_filter":
815
- return { stopReason: "error", errorMessage: "Provider finish_reason: content_filter" };
816
- case "network_error":
817
- return { stopReason: "error", errorMessage: "Provider finish_reason: network_error" };
818
- default:
819
- return {
820
- stopReason: "error",
821
- errorMessage: `Provider finish_reason: ${reason}`,
822
- };
823
- }
824
- }
825
- /**
826
- * Detect compatibility settings from provider and baseUrl for known providers.
827
- * Provider takes precedence over URL-based detection since it's explicitly configured.
828
- * Returns a fully resolved OpenAICompletionsCompat object with all fields set.
829
- */
830
- function detectCompat(model) {
831
- const provider = model.provider;
832
- const baseUrl = model.baseUrl;
833
- const isZai = provider === "zai" || baseUrl.includes("api.z.ai");
834
- const isMoonshot = provider === "moonshotai" || provider === "moonshotai-cn" || baseUrl.includes("api.moonshot.");
835
- const isCloudflareWorkersAI = provider === "cloudflare-workers-ai" || baseUrl.includes("api.cloudflare.com");
836
- const isCloudflareAiGateway = provider === "cloudflare-ai-gateway" || baseUrl.includes("gateway.ai.cloudflare.com");
837
- const isNonStandard = provider === "cerebras" ||
838
- baseUrl.includes("cerebras.ai") ||
839
- provider === "xai" ||
840
- baseUrl.includes("api.x.ai") ||
841
- baseUrl.includes("chutes.ai") ||
842
- baseUrl.includes("deepseek.com") ||
843
- isZai ||
844
- isMoonshot ||
845
- provider === "opencode" ||
846
- baseUrl.includes("opencode.ai") ||
847
- isCloudflareWorkersAI ||
848
- isCloudflareAiGateway;
849
- const useMaxTokens = baseUrl.includes("chutes.ai") || isMoonshot || isCloudflareAiGateway;
850
- const isGrok = provider === "xai" || baseUrl.includes("api.x.ai");
851
- const isDeepSeek = provider === "deepseek" || baseUrl.includes("deepseek.com");
852
- const cacheControlFormat = provider === "openrouter" && model.id.startsWith("anthropic/") ? "anthropic" : undefined;
853
- return {
854
- supportsStore: !isNonStandard,
855
- supportsDeveloperRole: !isNonStandard,
856
- supportsReasoningEffort: !isGrok && !isZai && !isMoonshot && !isCloudflareAiGateway,
857
- supportsUsageInStreaming: true,
858
- maxTokensField: useMaxTokens ? "max_tokens" : "max_completion_tokens",
859
- requiresToolResultName: false,
860
- requiresAssistantAfterToolResult: false,
861
- requiresThinkingAsText: false,
862
- requiresReasoningContentOnAssistantMessages: isDeepSeek,
863
- thinkingFormat: isDeepSeek
864
- ? "deepseek"
865
- : isZai
866
- ? "zai"
867
- : provider === "openrouter" || baseUrl.includes("openrouter.ai")
868
- ? "openrouter"
869
- : "openai",
870
- openRouterRouting: {},
871
- vercelGatewayRouting: {},
872
- zaiToolStream: false,
873
- supportsStrictMode: !isMoonshot && !isCloudflareAiGateway,
874
- cacheControlFormat,
875
- sendSessionAffinityHeaders: false,
876
- supportsLongCacheRetention: !(isCloudflareWorkersAI || isCloudflareAiGateway),
877
- };
878
- }
879
- /**
880
- * Get resolved compatibility settings for a model.
881
- * Uses explicit model.compat if provided, otherwise auto-detects from provider/URL.
882
- */
883
- function getCompat(model) {
884
- const detected = detectCompat(model);
885
- if (!model.compat)
886
- return detected;
887
- return {
888
- supportsStore: model.compat.supportsStore ?? detected.supportsStore,
889
- supportsDeveloperRole: model.compat.supportsDeveloperRole ?? detected.supportsDeveloperRole,
890
- supportsReasoningEffort: model.compat.supportsReasoningEffort ?? detected.supportsReasoningEffort,
891
- supportsUsageInStreaming: model.compat.supportsUsageInStreaming ?? detected.supportsUsageInStreaming,
892
- maxTokensField: model.compat.maxTokensField ?? detected.maxTokensField,
893
- requiresToolResultName: model.compat.requiresToolResultName ?? detected.requiresToolResultName,
894
- requiresAssistantAfterToolResult: model.compat.requiresAssistantAfterToolResult ?? detected.requiresAssistantAfterToolResult,
895
- requiresThinkingAsText: model.compat.requiresThinkingAsText ?? detected.requiresThinkingAsText,
896
- requiresReasoningContentOnAssistantMessages: model.compat.requiresReasoningContentOnAssistantMessages ??
897
- detected.requiresReasoningContentOnAssistantMessages,
898
- thinkingFormat: model.compat.thinkingFormat ?? detected.thinkingFormat,
899
- openRouterRouting: model.compat.openRouterRouting ?? {},
900
- vercelGatewayRouting: model.compat.vercelGatewayRouting ?? detected.vercelGatewayRouting,
901
- zaiToolStream: model.compat.zaiToolStream ?? detected.zaiToolStream,
902
- supportsStrictMode: model.compat.supportsStrictMode ?? detected.supportsStrictMode,
903
- cacheControlFormat: model.compat.cacheControlFormat ?? detected.cacheControlFormat,
904
- sendSessionAffinityHeaders: model.compat.sendSessionAffinityHeaders ?? detected.sendSessionAffinityHeaders,
905
- supportsLongCacheRetention: model.compat.supportsLongCacheRetention ?? detected.supportsLongCacheRetention,
906
- };
907
- }
908
- //# sourceMappingURL=openai-completions.js.map