@handy_wote/pi-ai 0.81.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 (346) hide show
  1. package/README.md +1623 -0
  2. package/dist/api/anthropic-messages.d.ts +71 -0
  3. package/dist/api/anthropic-messages.d.ts.map +1 -0
  4. package/dist/api/anthropic-messages.js +1024 -0
  5. package/dist/api/anthropic-messages.js.map +1 -0
  6. package/dist/api/anthropic-messages.lazy.d.ts +3 -0
  7. package/dist/api/anthropic-messages.lazy.d.ts.map +1 -0
  8. package/dist/api/anthropic-messages.lazy.js +3 -0
  9. package/dist/api/anthropic-messages.lazy.js.map +1 -0
  10. package/dist/api/azure-openai-responses.d.ts +15 -0
  11. package/dist/api/azure-openai-responses.d.ts.map +1 -0
  12. package/dist/api/azure-openai-responses.js +221 -0
  13. package/dist/api/azure-openai-responses.js.map +1 -0
  14. package/dist/api/azure-openai-responses.lazy.d.ts +3 -0
  15. package/dist/api/azure-openai-responses.lazy.d.ts.map +1 -0
  16. package/dist/api/azure-openai-responses.lazy.js +3 -0
  17. package/dist/api/azure-openai-responses.lazy.js.map +1 -0
  18. package/dist/api/bedrock-converse-stream.d.ts +38 -0
  19. package/dist/api/bedrock-converse-stream.d.ts.map +1 -0
  20. package/dist/api/bedrock-converse-stream.js +883 -0
  21. package/dist/api/bedrock-converse-stream.js.map +1 -0
  22. package/dist/api/bedrock-converse-stream.lazy.d.ts +9 -0
  23. package/dist/api/bedrock-converse-stream.lazy.d.ts.map +1 -0
  24. package/dist/api/bedrock-converse-stream.lazy.js +30 -0
  25. package/dist/api/bedrock-converse-stream.lazy.js.map +1 -0
  26. package/dist/api/cloudflare.d.ts +9 -0
  27. package/dist/api/cloudflare.d.ts.map +1 -0
  28. package/dist/api/cloudflare.js +9 -0
  29. package/dist/api/cloudflare.js.map +1 -0
  30. package/dist/api/github-copilot-headers.d.ts +8 -0
  31. package/dist/api/github-copilot-headers.d.ts.map +1 -0
  32. package/dist/api/github-copilot-headers.js +29 -0
  33. package/dist/api/github-copilot-headers.js.map +1 -0
  34. package/dist/api/google-generative-ai.d.ts +13 -0
  35. package/dist/api/google-generative-ai.d.ts.map +1 -0
  36. package/dist/api/google-generative-ai.js +407 -0
  37. package/dist/api/google-generative-ai.js.map +1 -0
  38. package/dist/api/google-generative-ai.lazy.d.ts +3 -0
  39. package/dist/api/google-generative-ai.lazy.d.ts.map +1 -0
  40. package/dist/api/google-generative-ai.lazy.js +3 -0
  41. package/dist/api/google-generative-ai.lazy.js.map +1 -0
  42. package/dist/api/google-shared.d.ts +70 -0
  43. package/dist/api/google-shared.d.ts.map +1 -0
  44. package/dist/api/google-shared.js +329 -0
  45. package/dist/api/google-shared.js.map +1 -0
  46. package/dist/api/google-vertex.d.ts +15 -0
  47. package/dist/api/google-vertex.d.ts.map +1 -0
  48. package/dist/api/google-vertex.js +456 -0
  49. package/dist/api/google-vertex.js.map +1 -0
  50. package/dist/api/google-vertex.lazy.d.ts +3 -0
  51. package/dist/api/google-vertex.lazy.d.ts.map +1 -0
  52. package/dist/api/google-vertex.lazy.js +3 -0
  53. package/dist/api/google-vertex.lazy.js.map +1 -0
  54. package/dist/api/lazy.d.ts +15 -0
  55. package/dist/api/lazy.d.ts.map +1 -0
  56. package/dist/api/lazy.js +58 -0
  57. package/dist/api/lazy.js.map +1 -0
  58. package/dist/api/mistral-conversations.d.ts +25 -0
  59. package/dist/api/mistral-conversations.d.ts.map +1 -0
  60. package/dist/api/mistral-conversations.js +555 -0
  61. package/dist/api/mistral-conversations.js.map +1 -0
  62. package/dist/api/mistral-conversations.lazy.d.ts +3 -0
  63. package/dist/api/mistral-conversations.lazy.d.ts.map +1 -0
  64. package/dist/api/mistral-conversations.lazy.js +3 -0
  65. package/dist/api/mistral-conversations.lazy.js.map +1 -0
  66. package/dist/api/openai-codex-responses.d.ts +31 -0
  67. package/dist/api/openai-codex-responses.d.ts.map +1 -0
  68. package/dist/api/openai-codex-responses.js +1222 -0
  69. package/dist/api/openai-codex-responses.js.map +1 -0
  70. package/dist/api/openai-codex-responses.lazy.d.ts +3 -0
  71. package/dist/api/openai-codex-responses.lazy.d.ts.map +1 -0
  72. package/dist/api/openai-codex-responses.lazy.js +3 -0
  73. package/dist/api/openai-codex-responses.lazy.js.map +1 -0
  74. package/dist/api/openai-completions.d.ts +20 -0
  75. package/dist/api/openai-completions.d.ts.map +1 -0
  76. package/dist/api/openai-completions.js +1120 -0
  77. package/dist/api/openai-completions.js.map +1 -0
  78. package/dist/api/openai-completions.lazy.d.ts +3 -0
  79. package/dist/api/openai-completions.lazy.d.ts.map +1 -0
  80. package/dist/api/openai-completions.lazy.js +3 -0
  81. package/dist/api/openai-completions.lazy.js.map +1 -0
  82. package/dist/api/openai-prompt-cache.d.ts +3 -0
  83. package/dist/api/openai-prompt-cache.d.ts.map +1 -0
  84. package/dist/api/openai-prompt-cache.js +10 -0
  85. package/dist/api/openai-prompt-cache.js.map +1 -0
  86. package/dist/api/openai-responses-shared.d.ts +20 -0
  87. package/dist/api/openai-responses-shared.d.ts.map +1 -0
  88. package/dist/api/openai-responses-shared.js +535 -0
  89. package/dist/api/openai-responses-shared.js.map +1 -0
  90. package/dist/api/openai-responses.d.ts +14 -0
  91. package/dist/api/openai-responses.d.ts.map +1 -0
  92. package/dist/api/openai-responses.js +246 -0
  93. package/dist/api/openai-responses.js.map +1 -0
  94. package/dist/api/openai-responses.lazy.d.ts +3 -0
  95. package/dist/api/openai-responses.lazy.d.ts.map +1 -0
  96. package/dist/api/openai-responses.lazy.js +3 -0
  97. package/dist/api/openai-responses.lazy.js.map +1 -0
  98. package/dist/api/openrouter-images.d.ts +3 -0
  99. package/dist/api/openrouter-images.d.ts.map +1 -0
  100. package/dist/api/openrouter-images.js +126 -0
  101. package/dist/api/openrouter-images.js.map +1 -0
  102. package/dist/api/openrouter-images.lazy.d.ts +3 -0
  103. package/dist/api/openrouter-images.lazy.d.ts.map +1 -0
  104. package/dist/api/openrouter-images.lazy.js +4 -0
  105. package/dist/api/openrouter-images.lazy.js.map +1 -0
  106. package/dist/api/pi-messages.d.ts +97 -0
  107. package/dist/api/pi-messages.d.ts.map +1 -0
  108. package/dist/api/pi-messages.js +307 -0
  109. package/dist/api/pi-messages.js.map +1 -0
  110. package/dist/api/pi-messages.lazy.d.ts +3 -0
  111. package/dist/api/pi-messages.lazy.d.ts.map +1 -0
  112. package/dist/api/pi-messages.lazy.js +3 -0
  113. package/dist/api/pi-messages.lazy.js.map +1 -0
  114. package/dist/api/simple-options.d.ts +9 -0
  115. package/dist/api/simple-options.d.ts.map +1 -0
  116. package/dist/api/simple-options.js +52 -0
  117. package/dist/api/simple-options.js.map +1 -0
  118. package/dist/api/transform-messages.d.ts +8 -0
  119. package/dist/api/transform-messages.d.ts.map +1 -0
  120. package/dist/api/transform-messages.js +187 -0
  121. package/dist/api/transform-messages.js.map +1 -0
  122. package/dist/auth/context.d.ts +7 -0
  123. package/dist/auth/context.d.ts.map +1 -0
  124. package/dist/auth/context.js +42 -0
  125. package/dist/auth/context.js.map +1 -0
  126. package/dist/auth/credential-store.d.ts +17 -0
  127. package/dist/auth/credential-store.d.ts.map +1 -0
  128. package/dist/auth/credential-store.js +40 -0
  129. package/dist/auth/credential-store.js.map +1 -0
  130. package/dist/auth/helpers.d.ts +21 -0
  131. package/dist/auth/helpers.d.ts.map +1 -0
  132. package/dist/auth/helpers.js +48 -0
  133. package/dist/auth/helpers.js.map +1 -0
  134. package/dist/auth/oauth/anthropic.d.ts +9 -0
  135. package/dist/auth/oauth/anthropic.d.ts.map +1 -0
  136. package/dist/auth/oauth/anthropic.js +302 -0
  137. package/dist/auth/oauth/anthropic.js.map +1 -0
  138. package/dist/auth/oauth/device-code.d.ts +23 -0
  139. package/dist/auth/oauth/device-code.d.ts.map +1 -0
  140. package/dist/auth/oauth/device-code.js +69 -0
  141. package/dist/auth/oauth/device-code.js.map +1 -0
  142. package/dist/auth/oauth/github-copilot.d.ts +6 -0
  143. package/dist/auth/oauth/github-copilot.d.ts.map +1 -0
  144. package/dist/auth/oauth/github-copilot.js +313 -0
  145. package/dist/auth/oauth/github-copilot.js.map +1 -0
  146. package/dist/auth/oauth/load.d.ts +23 -0
  147. package/dist/auth/oauth/load.d.ts.map +1 -0
  148. package/dist/auth/oauth/load.js +49 -0
  149. package/dist/auth/oauth/load.js.map +1 -0
  150. package/dist/auth/oauth/oauth-page.d.ts +3 -0
  151. package/dist/auth/oauth/oauth-page.d.ts.map +1 -0
  152. package/dist/auth/oauth/oauth-page.js +105 -0
  153. package/dist/auth/oauth/oauth-page.js.map +1 -0
  154. package/dist/auth/oauth/openai-codex.d.ts +9 -0
  155. package/dist/auth/oauth/openai-codex.d.ts.map +1 -0
  156. package/dist/auth/oauth/openai-codex.js +443 -0
  157. package/dist/auth/oauth/openai-codex.js.map +1 -0
  158. package/dist/auth/oauth/pkce.d.ts +13 -0
  159. package/dist/auth/oauth/pkce.d.ts.map +1 -0
  160. package/dist/auth/oauth/pkce.js +31 -0
  161. package/dist/auth/oauth/pkce.js.map +1 -0
  162. package/dist/auth/oauth/radius.d.ts +16 -0
  163. package/dist/auth/oauth/radius.d.ts.map +1 -0
  164. package/dist/auth/oauth/radius.js +321 -0
  165. package/dist/auth/oauth/radius.js.map +1 -0
  166. package/dist/auth/oauth/xai.d.ts +6 -0
  167. package/dist/auth/oauth/xai.d.ts.map +1 -0
  168. package/dist/auth/oauth/xai.js +189 -0
  169. package/dist/auth/oauth/xai.js.map +1 -0
  170. package/dist/auth/resolve.d.ts +24 -0
  171. package/dist/auth/resolve.d.ts.map +1 -0
  172. package/dist/auth/resolve.js +103 -0
  173. package/dist/auth/resolve.js.map +1 -0
  174. package/dist/auth/types.d.ts +219 -0
  175. package/dist/auth/types.d.ts.map +1 -0
  176. package/dist/auth/types.js +2 -0
  177. package/dist/auth/types.js.map +1 -0
  178. package/dist/bedrock-provider.d.ts +5 -0
  179. package/dist/bedrock-provider.d.ts.map +1 -0
  180. package/dist/bedrock-provider.js +6 -0
  181. package/dist/bedrock-provider.js.map +1 -0
  182. package/dist/bun-oauth.d.ts +3 -0
  183. package/dist/bun-oauth.d.ts.map +1 -0
  184. package/dist/bun-oauth.js +17 -0
  185. package/dist/bun-oauth.js.map +1 -0
  186. package/dist/cli.d.ts +3 -0
  187. package/dist/cli.d.ts.map +1 -0
  188. package/dist/cli.js +115 -0
  189. package/dist/cli.js.map +1 -0
  190. package/dist/compat/extension-oauth-types.d.ts +39 -0
  191. package/dist/compat/extension-oauth-types.d.ts.map +1 -0
  192. package/dist/compat/extension-oauth-types.js +2 -0
  193. package/dist/compat/extension-oauth-types.js.map +1 -0
  194. package/dist/compat.d.ts +70 -0
  195. package/dist/compat.d.ts.map +1 -0
  196. package/dist/compat.js +189 -0
  197. package/dist/compat.js.map +1 -0
  198. package/dist/env-api-keys.d.ts +18 -0
  199. package/dist/env-api-keys.d.ts.map +1 -0
  200. package/dist/env-api-keys.js +148 -0
  201. package/dist/env-api-keys.js.map +1 -0
  202. package/dist/image-models.d.ts +10 -0
  203. package/dist/image-models.d.ts.map +1 -0
  204. package/dist/image-models.js +24 -0
  205. package/dist/image-models.js.map +1 -0
  206. package/dist/images-api-registry.d.ts +14 -0
  207. package/dist/images-api-registry.d.ts.map +1 -0
  208. package/dist/images-api-registry.js +22 -0
  209. package/dist/images-api-registry.js.map +1 -0
  210. package/dist/images-models.d.ts +95 -0
  211. package/dist/images-models.d.ts.map +1 -0
  212. package/dist/images-models.js +142 -0
  213. package/dist/images-models.js.map +1 -0
  214. package/dist/images.d.ts +4 -0
  215. package/dist/images.d.ts.map +1 -0
  216. package/dist/images.js +14 -0
  217. package/dist/images.js.map +1 -0
  218. package/dist/index.d.ts +35 -0
  219. package/dist/index.d.ts.map +1 -0
  220. package/dist/index.js +22 -0
  221. package/dist/index.js.map +1 -0
  222. package/dist/legacy-api-aliases.d.ts +42 -0
  223. package/dist/legacy-api-aliases.d.ts.map +1 -0
  224. package/dist/legacy-api-aliases.js +49 -0
  225. package/dist/legacy-api-aliases.js.map +1 -0
  226. package/dist/models-store.d.ts +27 -0
  227. package/dist/models-store.d.ts.map +1 -0
  228. package/dist/models-store.js +14 -0
  229. package/dist/models-store.js.map +1 -0
  230. package/dist/models.d.ts +178 -0
  231. package/dist/models.d.ts.map +1 -0
  232. package/dist/models.js +432 -0
  233. package/dist/models.js.map +1 -0
  234. package/dist/oauth.d.ts +3 -0
  235. package/dist/oauth.d.ts.map +1 -0
  236. package/dist/oauth.js +2 -0
  237. package/dist/oauth.js.map +1 -0
  238. package/dist/providers/all.d.ts +6 -0
  239. package/dist/providers/all.d.ts.map +1 -0
  240. package/dist/providers/all.js +9 -0
  241. package/dist/providers/all.js.map +1 -0
  242. package/dist/providers/anthropic-compat.d.ts +10 -0
  243. package/dist/providers/anthropic-compat.d.ts.map +1 -0
  244. package/dist/providers/anthropic-compat.js +20 -0
  245. package/dist/providers/anthropic-compat.js.map +1 -0
  246. package/dist/providers/faux.d.ts +97 -0
  247. package/dist/providers/faux.d.ts.map +1 -0
  248. package/dist/providers/faux.js +395 -0
  249. package/dist/providers/faux.js.map +1 -0
  250. package/dist/providers/images/register-builtins.d.ts +4 -0
  251. package/dist/providers/images/register-builtins.d.ts.map +1 -0
  252. package/dist/providers/images/register-builtins.js +34 -0
  253. package/dist/providers/images/register-builtins.js.map +1 -0
  254. package/dist/providers/openai-compat.d.ts +10 -0
  255. package/dist/providers/openai-compat.d.ts.map +1 -0
  256. package/dist/providers/openai-compat.js +24 -0
  257. package/dist/providers/openai-compat.js.map +1 -0
  258. package/dist/providers/openrouter-images.d.ts +3 -0
  259. package/dist/providers/openrouter-images.d.ts.map +1 -0
  260. package/dist/providers/openrouter-images.js +15 -0
  261. package/dist/providers/openrouter-images.js.map +1 -0
  262. package/dist/providers/radius.d.ts +9 -0
  263. package/dist/providers/radius.d.ts.map +1 -0
  264. package/dist/providers/radius.js +70 -0
  265. package/dist/providers/radius.js.map +1 -0
  266. package/dist/session-resources.d.ts +4 -0
  267. package/dist/session-resources.d.ts.map +1 -0
  268. package/dist/session-resources.js +22 -0
  269. package/dist/session-resources.js.map +1 -0
  270. package/dist/types.d.ts +629 -0
  271. package/dist/types.d.ts.map +1 -0
  272. package/dist/types.js +2 -0
  273. package/dist/types.js.map +1 -0
  274. package/dist/utils/abort-signals.d.ts +6 -0
  275. package/dist/utils/abort-signals.d.ts.map +1 -0
  276. package/dist/utils/abort-signals.js +34 -0
  277. package/dist/utils/abort-signals.js.map +1 -0
  278. package/dist/utils/deferred-tools.d.ts +9 -0
  279. package/dist/utils/deferred-tools.d.ts.map +1 -0
  280. package/dist/utils/deferred-tools.js +36 -0
  281. package/dist/utils/deferred-tools.js.map +1 -0
  282. package/dist/utils/diagnostics.d.ts +19 -0
  283. package/dist/utils/diagnostics.d.ts.map +1 -0
  284. package/dist/utils/diagnostics.js +25 -0
  285. package/dist/utils/diagnostics.js.map +1 -0
  286. package/dist/utils/error-body.d.ts +25 -0
  287. package/dist/utils/error-body.d.ts.map +1 -0
  288. package/dist/utils/error-body.js +109 -0
  289. package/dist/utils/error-body.js.map +1 -0
  290. package/dist/utils/estimate.d.ts +17 -0
  291. package/dist/utils/estimate.d.ts.map +1 -0
  292. package/dist/utils/estimate.js +116 -0
  293. package/dist/utils/estimate.js.map +1 -0
  294. package/dist/utils/event-stream.d.ts +21 -0
  295. package/dist/utils/event-stream.d.ts.map +1 -0
  296. package/dist/utils/event-stream.js +81 -0
  297. package/dist/utils/event-stream.js.map +1 -0
  298. package/dist/utils/hash.d.ts +3 -0
  299. package/dist/utils/hash.d.ts.map +1 -0
  300. package/dist/utils/hash.js +14 -0
  301. package/dist/utils/hash.js.map +1 -0
  302. package/dist/utils/headers.d.ts +4 -0
  303. package/dist/utils/headers.d.ts.map +1 -0
  304. package/dist/utils/headers.js +18 -0
  305. package/dist/utils/headers.js.map +1 -0
  306. package/dist/utils/json-parse.d.ts +16 -0
  307. package/dist/utils/json-parse.d.ts.map +1 -0
  308. package/dist/utils/json-parse.js +113 -0
  309. package/dist/utils/json-parse.js.map +1 -0
  310. package/dist/utils/node-http-proxy.d.ts +4 -0
  311. package/dist/utils/node-http-proxy.d.ts.map +1 -0
  312. package/dist/utils/node-http-proxy.js +92 -0
  313. package/dist/utils/node-http-proxy.js.map +1 -0
  314. package/dist/utils/overflow.d.ts +59 -0
  315. package/dist/utils/overflow.d.ts.map +1 -0
  316. package/dist/utils/overflow.js +161 -0
  317. package/dist/utils/overflow.js.map +1 -0
  318. package/dist/utils/provider-env.d.ts +7 -0
  319. package/dist/utils/provider-env.d.ts.map +1 -0
  320. package/dist/utils/provider-env.js +44 -0
  321. package/dist/utils/provider-env.js.map +1 -0
  322. package/dist/utils/retry.d.ts +53 -0
  323. package/dist/utils/retry.d.ts.map +1 -0
  324. package/dist/utils/retry.js +170 -0
  325. package/dist/utils/retry.js.map +1 -0
  326. package/dist/utils/sanitize-unicode.d.ts +22 -0
  327. package/dist/utils/sanitize-unicode.d.ts.map +1 -0
  328. package/dist/utils/sanitize-unicode.js +26 -0
  329. package/dist/utils/sanitize-unicode.js.map +1 -0
  330. package/dist/utils/text.d.ts +6 -0
  331. package/dist/utils/text.d.ts.map +1 -0
  332. package/dist/utils/text.js +10 -0
  333. package/dist/utils/text.js.map +1 -0
  334. package/dist/utils/typebox-helpers.d.ts +17 -0
  335. package/dist/utils/typebox-helpers.d.ts.map +1 -0
  336. package/dist/utils/typebox-helpers.js +21 -0
  337. package/dist/utils/typebox-helpers.js.map +1 -0
  338. package/dist/utils/uuid.d.ts +3 -0
  339. package/dist/utils/uuid.d.ts.map +1 -0
  340. package/dist/utils/uuid.js +46 -0
  341. package/dist/utils/uuid.js.map +1 -0
  342. package/dist/utils/validation.d.ts +18 -0
  343. package/dist/utils/validation.d.ts.map +1 -0
  344. package/dist/utils/validation.js +269 -0
  345. package/dist/utils/validation.js.map +1 -0
  346. package/package.json +95 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-responses.d.ts","sourceRoot":"","sources":["../../src/api/openai-responses.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAC;AAE7F,OAAO,KAAK,EASX,mBAAmB,EACnB,cAAc,EACd,aAAa,EAEb,MAAM,aAAa,CAAC;AAqErB,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IAC5D,eAAe,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;IAC1E,gBAAgB,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;IAC1D,WAAW,CAAC,EAAE,6BAA6B,CAAC,cAAc,CAAC,CAAC;IAC5D,UAAU,CAAC,EAAE,6BAA6B,CAAC,aAAa,CAAC,CAAC;CAC1D;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,kBAAkB,EAAE,sBAAsB,CA4E7E,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,kBAAkB,EAAE,mBAAmB,CAehF,CAAC","sourcesContent":["import OpenAI from \"openai\";\nimport type { ResponseCreateParamsStreaming } from \"openai/resources/responses/responses.js\";\nimport { clampThinkingLevel } from \"../models.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tOpenAIResponsesCompat,\n\tProviderEnv,\n\tProviderHeaders,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tUsage,\n} from \"../types.ts\";\nimport { splitDeferredTools } from \"../utils/deferred-tools.ts\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\nimport { buildCopilotDynamicHeaders, hasCopilotVisionInput } from \"./github-copilot-headers.ts\";\nimport { clampOpenAIPromptCacheKey } from \"./openai-prompt-cache.ts\";\nimport { convertResponsesMessages, convertResponsesTools, processResponsesStream } from \"./openai-responses-shared.ts\";\nimport { buildBaseOptions } from \"./simple-options.ts\";\n\nconst OPENAI_TOOL_CALL_PROVIDERS = new Set([\"openai\", \"openai-codex\", \"opencode\"]);\n// OpenAI Responses rejects max_output_tokens below 16: https://github.com/earendil-works/pi/issues/6265\nconst OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;\n\nfunction hasHeader(headers: ProviderHeaders | undefined, name: string): boolean {\n\tif (!headers) return false;\n\tconst expected = name.toLowerCase();\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (key.toLowerCase() === expected && value !== null && value.trim().length > 0) return true;\n\t}\n\treturn false;\n}\n\nfunction getClientApiKey(provider: string, apiKey: string | undefined, headers: ProviderHeaders | undefined): string {\n\tif (apiKey) return apiKey;\n\tif (hasHeader(headers, \"authorization\") || hasHeader(headers, \"cf-aig-authorization\")) return \"unused\";\n\tthrow new Error(`No API key for provider: ${provider}`);\n}\n\nfunction detectSessionAffinityFormat(model: Pick<Model<\"openai-responses\">, \"provider\" | \"baseUrl\">) {\n\treturn model.provider === \"openrouter\" || model.baseUrl.includes(\"openrouter.ai\") ? \"openrouter\" : \"openai\";\n}\n\n/**\n * Resolve cache retention preference.\n * Defaults to \"short\" and uses PI_CACHE_RETENTION for backward compatibility.\n */\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\tif (getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\") {\n\t\treturn \"long\";\n\t}\n\treturn \"short\";\n}\n\nfunction getCompat(model: Model<\"openai-responses\">): Required<OpenAIResponsesCompat> {\n\treturn {\n\t\tsupportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,\n\t\tsessionAffinityFormat: model.compat?.sessionAffinityFormat ?? detectSessionAffinityFormat(model),\n\t\tsupportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,\n\t\tsupportsToolSearch: model.compat?.supportsToolSearch ?? false,\n\t};\n}\n\nfunction getPromptCacheRetention(\n\tcompat: Required<OpenAIResponsesCompat>,\n\tcacheRetention: CacheRetention,\n): \"24h\" | undefined {\n\treturn cacheRetention === \"long\" && compat.supportsLongCacheRetention ? \"24h\" : undefined;\n}\n\nfunction formatOpenAIResponsesError(error: unknown): string {\n\treturn formatProviderError(normalizeProviderError(error), \"OpenAI API error\");\n}\n\n// OpenAI Responses-specific options\nexport interface OpenAIResponsesOptions extends StreamOptions {\n\treasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n\treasoningSummary?: \"auto\" | \"detailed\" | \"concise\" | null;\n\tserviceTier?: ResponseCreateParamsStreaming[\"service_tier\"];\n\ttoolChoice?: ResponseCreateParamsStreaming[\"tool_choice\"];\n}\n\n/**\n * Generate function for OpenAI Responses API\n */\nexport const stream: StreamFunction<\"openai-responses\", OpenAIResponsesOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: OpenAIResponsesOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t// Start async processing\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: model.api as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\t// Create OpenAI client\n\t\t\tconst apiKey = getClientApiKey(model.provider, options?.apiKey, options?.headers);\n\t\t\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\t\t\tconst cacheSessionId = cacheRetention === \"none\" ? undefined : options?.sessionId;\n\t\t\tconst client = createClient(model, context, apiKey, options?.headers, cacheSessionId);\n\t\t\tlet params = buildParams(model, context, options);\n\t\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\t\tif (nextParams !== undefined) {\n\t\t\t\tparams = nextParams as ResponseCreateParamsStreaming;\n\t\t\t}\n\t\t\tconst requestOptions = {\n\t\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\t\tmaxRetries: options?.maxRetries ?? 0,\n\t\t\t};\n\t\t\tconst { data: openaiStream, response } = await client.responses.create(params, requestOptions).withResponse();\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tawait processResponsesStream(openaiStream, output, stream, model, {\n\t\t\t\tserviceTier: options?.serviceTier,\n\t\t\t\tapplyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model),\n\t\t\t});\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unknown error occurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) {\n\t\t\t\tdelete (block as { index?: number }).index;\n\t\t\t\t// partialJson is only a streaming scratch buffer; never persist it.\n\t\t\t\tdelete (block as { partialJson?: string }).partialJson;\n\t\t\t}\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = formatOpenAIResponsesError(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nexport const streamSimple: StreamFunction<\"openai-responses\", SimpleStreamOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tgetClientApiKey(model.provider, options?.apiKey, options?.headers);\n\n\tconst base = buildBaseOptions(model, context, options, options?.apiKey);\n\tconst clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;\n\tconst reasoningEffort = clampedReasoning === \"off\" ? undefined : clampedReasoning;\n\n\treturn stream(model, context, {\n\t\t...base,\n\t\treasoningEffort,\n\t} satisfies OpenAIResponsesOptions);\n};\n\nfunction createClient(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\tapiKey: string,\n\toptionsHeaders?: ProviderHeaders,\n\tsessionId?: string,\n) {\n\tconst compat = getCompat(model);\n\tconst headers: ProviderHeaders = { ...model.headers };\n\tif (model.provider === \"github-copilot\") {\n\t\tconst hasImages = hasCopilotVisionInput(context.messages);\n\t\tconst copilotHeaders = buildCopilotDynamicHeaders({\n\t\t\tmessages: context.messages,\n\t\t\thasImages,\n\t\t});\n\t\tObject.assign(headers, copilotHeaders);\n\t}\n\n\tif (sessionId) {\n\t\tif (compat.sessionAffinityFormat === \"openrouter\") {\n\t\t\theaders[\"x-session-id\"] = sessionId;\n\t\t} else {\n\t\t\tif (compat.sessionAffinityFormat === \"openai\") {\n\t\t\t\theaders.session_id = sessionId;\n\t\t\t}\n\t\t\theaders[\"x-client-request-id\"] = sessionId;\n\t\t}\n\t}\n\n\t// Merge options headers last so they can override defaults\n\tif (optionsHeaders) {\n\t\tObject.assign(headers, optionsHeaders);\n\t}\n\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders: headers,\n\t});\n}\n\nfunction buildParams(model: Model<\"openai-responses\">, context: Context, options?: OpenAIResponsesOptions) {\n\tconst compat = getCompat(model);\n\tconst toolPlacement = splitDeferredTools(context, compat.supportsToolSearch);\n\tconst messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS, {\n\t\tdeferredTools: toolPlacement.deferred,\n\t});\n\n\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\tconst params: ResponseCreateParamsStreaming = {\n\t\tmodel: model.id,\n\t\tinput: messages,\n\t\tstream: true,\n\t\tprompt_cache_key: cacheRetention === \"none\" ? undefined : clampOpenAIPromptCacheKey(options?.sessionId),\n\t\tprompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),\n\t\tstore: false,\n\t};\n\n\tif (options?.maxTokens) {\n\t\tparams.max_output_tokens = Math.max(options.maxTokens, OPENAI_RESPONSES_MIN_OUTPUT_TOKENS);\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options?.temperature;\n\t}\n\n\tif (options?.serviceTier !== undefined) {\n\t\tparams.service_tier = options.serviceTier;\n\t}\n\n\tif (toolPlacement.immediate.length > 0) {\n\t\tparams.tools = convertResponsesTools(toolPlacement.immediate);\n\t}\n\n\tif (options?.toolChoice !== undefined) {\n\t\tparams.tool_choice = options.toolChoice;\n\t}\n\n\tif (model.reasoning) {\n\t\tif (options?.reasoningEffort || options?.reasoningSummary) {\n\t\t\tconst effort = options?.reasoningEffort\n\t\t\t\t? (model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort)\n\t\t\t\t: \"medium\";\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: effort as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t\tsummary: options?.reasoningSummary || \"auto\",\n\t\t\t};\n\t\t\tparams.include = [\"reasoning.encrypted_content\"];\n\t\t} else if (model.provider !== \"github-copilot\" && model.thinkingLevelMap?.off !== null) {\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: (model.thinkingLevelMap?.off ?? \"none\") as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t};\n\t\t}\n\t\tif (model.provider === \"xai\") params.include = [\"reasoning.encrypted_content\"];\n\t}\n\n\treturn params;\n}\n\nfunction getServiceTierCostMultiplier(\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n): number {\n\tswitch (serviceTier) {\n\t\tcase \"flex\":\n\t\t\treturn 0.5;\n\t\tcase \"priority\":\n\t\t\treturn model.id === \"gpt-5.5\" ? 2.5 : 2;\n\t\tdefault:\n\t\t\treturn 1;\n\t}\n}\n\nfunction applyServiceTierPricing(\n\tusage: Usage,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n) {\n\tconst multiplier = getServiceTierCostMultiplier(model, serviceTier);\n\tif (multiplier === 1) return;\n\n\tusage.cost.input *= multiplier;\n\tusage.cost.output *= multiplier;\n\tusage.cost.cacheRead *= multiplier;\n\tusage.cost.cacheWrite *= multiplier;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n}\n"]}
@@ -0,0 +1,246 @@
1
+ import OpenAI from "openai";
2
+ import { clampThinkingLevel } from "../models.js";
3
+ import { splitDeferredTools } from "../utils/deferred-tools.js";
4
+ import { formatProviderError, normalizeProviderError } from "../utils/error-body.js";
5
+ import { AssistantMessageEventStream } from "../utils/event-stream.js";
6
+ import { headersToRecord } from "../utils/headers.js";
7
+ import { getProviderEnvValue } from "../utils/provider-env.js";
8
+ import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
9
+ import { clampOpenAIPromptCacheKey } from "./openai-prompt-cache.js";
10
+ import { convertResponsesMessages, convertResponsesTools, processResponsesStream } from "./openai-responses-shared.js";
11
+ import { buildBaseOptions } from "./simple-options.js";
12
+ const OPENAI_TOOL_CALL_PROVIDERS = new Set(["openai", "openai-codex", "opencode"]);
13
+ // OpenAI Responses rejects max_output_tokens below 16: https://github.com/earendil-works/pi/issues/6265
14
+ const OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;
15
+ function hasHeader(headers, name) {
16
+ if (!headers)
17
+ return false;
18
+ const expected = name.toLowerCase();
19
+ for (const [key, value] of Object.entries(headers)) {
20
+ if (key.toLowerCase() === expected && value !== null && value.trim().length > 0)
21
+ return true;
22
+ }
23
+ return false;
24
+ }
25
+ function getClientApiKey(provider, apiKey, headers) {
26
+ if (apiKey)
27
+ return apiKey;
28
+ if (hasHeader(headers, "authorization") || hasHeader(headers, "cf-aig-authorization"))
29
+ return "unused";
30
+ throw new Error(`No API key for provider: ${provider}`);
31
+ }
32
+ function detectSessionAffinityFormat(model) {
33
+ return model.provider === "openrouter" || model.baseUrl.includes("openrouter.ai") ? "openrouter" : "openai";
34
+ }
35
+ /**
36
+ * Resolve cache retention preference.
37
+ * Defaults to "short" and uses PI_CACHE_RETENTION for backward compatibility.
38
+ */
39
+ function resolveCacheRetention(cacheRetention, env) {
40
+ if (cacheRetention) {
41
+ return cacheRetention;
42
+ }
43
+ if (getProviderEnvValue("PI_CACHE_RETENTION", env) === "long") {
44
+ return "long";
45
+ }
46
+ return "short";
47
+ }
48
+ function getCompat(model) {
49
+ return {
50
+ supportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,
51
+ sessionAffinityFormat: model.compat?.sessionAffinityFormat ?? detectSessionAffinityFormat(model),
52
+ supportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,
53
+ supportsToolSearch: model.compat?.supportsToolSearch ?? false,
54
+ };
55
+ }
56
+ function getPromptCacheRetention(compat, cacheRetention) {
57
+ return cacheRetention === "long" && compat.supportsLongCacheRetention ? "24h" : undefined;
58
+ }
59
+ function formatOpenAIResponsesError(error) {
60
+ return formatProviderError(normalizeProviderError(error), "OpenAI API error");
61
+ }
62
+ /**
63
+ * Generate function for OpenAI Responses API
64
+ */
65
+ export const stream = (model, context, options) => {
66
+ const stream = new AssistantMessageEventStream();
67
+ // Start async processing
68
+ (async () => {
69
+ const output = {
70
+ role: "assistant",
71
+ content: [],
72
+ api: model.api,
73
+ provider: model.provider,
74
+ model: model.id,
75
+ usage: {
76
+ input: 0,
77
+ output: 0,
78
+ cacheRead: 0,
79
+ cacheWrite: 0,
80
+ totalTokens: 0,
81
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
82
+ },
83
+ stopReason: "stop",
84
+ timestamp: Date.now(),
85
+ };
86
+ try {
87
+ // Create OpenAI client
88
+ const apiKey = getClientApiKey(model.provider, options?.apiKey, options?.headers);
89
+ const cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);
90
+ const cacheSessionId = cacheRetention === "none" ? undefined : options?.sessionId;
91
+ const client = createClient(model, context, apiKey, options?.headers, cacheSessionId);
92
+ let params = buildParams(model, context, options);
93
+ const nextParams = await options?.onPayload?.(params, model);
94
+ if (nextParams !== undefined) {
95
+ params = nextParams;
96
+ }
97
+ const requestOptions = {
98
+ ...(options?.signal ? { signal: options.signal } : {}),
99
+ ...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
100
+ maxRetries: options?.maxRetries ?? 0,
101
+ };
102
+ const { data: openaiStream, response } = await client.responses.create(params, requestOptions).withResponse();
103
+ await options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);
104
+ stream.push({ type: "start", partial: output });
105
+ await processResponsesStream(openaiStream, output, stream, model, {
106
+ serviceTier: options?.serviceTier,
107
+ applyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model),
108
+ });
109
+ if (options?.signal?.aborted) {
110
+ throw new Error("Request was aborted");
111
+ }
112
+ if (output.stopReason === "aborted" || output.stopReason === "error") {
113
+ throw new Error("An unknown error occurred");
114
+ }
115
+ stream.push({ type: "done", reason: output.stopReason, message: output });
116
+ stream.end();
117
+ }
118
+ catch (error) {
119
+ for (const block of output.content) {
120
+ delete block.index;
121
+ // partialJson is only a streaming scratch buffer; never persist it.
122
+ delete block.partialJson;
123
+ }
124
+ output.stopReason = options?.signal?.aborted ? "aborted" : "error";
125
+ output.errorMessage = formatOpenAIResponsesError(error);
126
+ stream.push({ type: "error", reason: output.stopReason, error: output });
127
+ stream.end();
128
+ }
129
+ })();
130
+ return stream;
131
+ };
132
+ export const streamSimple = (model, context, options) => {
133
+ getClientApiKey(model.provider, options?.apiKey, options?.headers);
134
+ const base = buildBaseOptions(model, context, options, options?.apiKey);
135
+ const clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;
136
+ const reasoningEffort = clampedReasoning === "off" ? undefined : clampedReasoning;
137
+ return stream(model, context, {
138
+ ...base,
139
+ reasoningEffort,
140
+ });
141
+ };
142
+ function createClient(model, context, apiKey, optionsHeaders, sessionId) {
143
+ const compat = getCompat(model);
144
+ const headers = { ...model.headers };
145
+ if (model.provider === "github-copilot") {
146
+ const hasImages = hasCopilotVisionInput(context.messages);
147
+ const copilotHeaders = buildCopilotDynamicHeaders({
148
+ messages: context.messages,
149
+ hasImages,
150
+ });
151
+ Object.assign(headers, copilotHeaders);
152
+ }
153
+ if (sessionId) {
154
+ if (compat.sessionAffinityFormat === "openrouter") {
155
+ headers["x-session-id"] = sessionId;
156
+ }
157
+ else {
158
+ if (compat.sessionAffinityFormat === "openai") {
159
+ headers.session_id = sessionId;
160
+ }
161
+ headers["x-client-request-id"] = sessionId;
162
+ }
163
+ }
164
+ // Merge options headers last so they can override defaults
165
+ if (optionsHeaders) {
166
+ Object.assign(headers, optionsHeaders);
167
+ }
168
+ return new OpenAI({
169
+ apiKey,
170
+ baseURL: model.baseUrl,
171
+ dangerouslyAllowBrowser: true,
172
+ defaultHeaders: headers,
173
+ });
174
+ }
175
+ function buildParams(model, context, options) {
176
+ const compat = getCompat(model);
177
+ const toolPlacement = splitDeferredTools(context, compat.supportsToolSearch);
178
+ const messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS, {
179
+ deferredTools: toolPlacement.deferred,
180
+ });
181
+ const cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);
182
+ const params = {
183
+ model: model.id,
184
+ input: messages,
185
+ stream: true,
186
+ prompt_cache_key: cacheRetention === "none" ? undefined : clampOpenAIPromptCacheKey(options?.sessionId),
187
+ prompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),
188
+ store: false,
189
+ };
190
+ if (options?.maxTokens) {
191
+ params.max_output_tokens = Math.max(options.maxTokens, OPENAI_RESPONSES_MIN_OUTPUT_TOKENS);
192
+ }
193
+ if (options?.temperature !== undefined) {
194
+ params.temperature = options?.temperature;
195
+ }
196
+ if (options?.serviceTier !== undefined) {
197
+ params.service_tier = options.serviceTier;
198
+ }
199
+ if (toolPlacement.immediate.length > 0) {
200
+ params.tools = convertResponsesTools(toolPlacement.immediate);
201
+ }
202
+ if (options?.toolChoice !== undefined) {
203
+ params.tool_choice = options.toolChoice;
204
+ }
205
+ if (model.reasoning) {
206
+ if (options?.reasoningEffort || options?.reasoningSummary) {
207
+ const effort = options?.reasoningEffort
208
+ ? (model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort)
209
+ : "medium";
210
+ params.reasoning = {
211
+ effort: effort,
212
+ summary: options?.reasoningSummary || "auto",
213
+ };
214
+ params.include = ["reasoning.encrypted_content"];
215
+ }
216
+ else if (model.provider !== "github-copilot" && model.thinkingLevelMap?.off !== null) {
217
+ params.reasoning = {
218
+ effort: (model.thinkingLevelMap?.off ?? "none"),
219
+ };
220
+ }
221
+ if (model.provider === "xai")
222
+ params.include = ["reasoning.encrypted_content"];
223
+ }
224
+ return params;
225
+ }
226
+ function getServiceTierCostMultiplier(model, serviceTier) {
227
+ switch (serviceTier) {
228
+ case "flex":
229
+ return 0.5;
230
+ case "priority":
231
+ return model.id === "gpt-5.5" ? 2.5 : 2;
232
+ default:
233
+ return 1;
234
+ }
235
+ }
236
+ function applyServiceTierPricing(usage, serviceTier, model) {
237
+ const multiplier = getServiceTierCostMultiplier(model, serviceTier);
238
+ if (multiplier === 1)
239
+ return;
240
+ usage.cost.input *= multiplier;
241
+ usage.cost.output *= multiplier;
242
+ usage.cost.cacheRead *= multiplier;
243
+ usage.cost.cacheWrite *= multiplier;
244
+ usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
245
+ }
246
+ //# sourceMappingURL=openai-responses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-responses.js","sourceRoot":"","sources":["../../src/api/openai-responses.ts"],"names":[],"mappings":"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","sourcesContent":["import OpenAI from \"openai\";\nimport type { ResponseCreateParamsStreaming } from \"openai/resources/responses/responses.js\";\nimport { clampThinkingLevel } from \"../models.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tOpenAIResponsesCompat,\n\tProviderEnv,\n\tProviderHeaders,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tUsage,\n} from \"../types.ts\";\nimport { splitDeferredTools } from \"../utils/deferred-tools.ts\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\nimport { buildCopilotDynamicHeaders, hasCopilotVisionInput } from \"./github-copilot-headers.ts\";\nimport { clampOpenAIPromptCacheKey } from \"./openai-prompt-cache.ts\";\nimport { convertResponsesMessages, convertResponsesTools, processResponsesStream } from \"./openai-responses-shared.ts\";\nimport { buildBaseOptions } from \"./simple-options.ts\";\n\nconst OPENAI_TOOL_CALL_PROVIDERS = new Set([\"openai\", \"openai-codex\", \"opencode\"]);\n// OpenAI Responses rejects max_output_tokens below 16: https://github.com/earendil-works/pi/issues/6265\nconst OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;\n\nfunction hasHeader(headers: ProviderHeaders | undefined, name: string): boolean {\n\tif (!headers) return false;\n\tconst expected = name.toLowerCase();\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (key.toLowerCase() === expected && value !== null && value.trim().length > 0) return true;\n\t}\n\treturn false;\n}\n\nfunction getClientApiKey(provider: string, apiKey: string | undefined, headers: ProviderHeaders | undefined): string {\n\tif (apiKey) return apiKey;\n\tif (hasHeader(headers, \"authorization\") || hasHeader(headers, \"cf-aig-authorization\")) return \"unused\";\n\tthrow new Error(`No API key for provider: ${provider}`);\n}\n\nfunction detectSessionAffinityFormat(model: Pick<Model<\"openai-responses\">, \"provider\" | \"baseUrl\">) {\n\treturn model.provider === \"openrouter\" || model.baseUrl.includes(\"openrouter.ai\") ? \"openrouter\" : \"openai\";\n}\n\n/**\n * Resolve cache retention preference.\n * Defaults to \"short\" and uses PI_CACHE_RETENTION for backward compatibility.\n */\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\tif (getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\") {\n\t\treturn \"long\";\n\t}\n\treturn \"short\";\n}\n\nfunction getCompat(model: Model<\"openai-responses\">): Required<OpenAIResponsesCompat> {\n\treturn {\n\t\tsupportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,\n\t\tsessionAffinityFormat: model.compat?.sessionAffinityFormat ?? detectSessionAffinityFormat(model),\n\t\tsupportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,\n\t\tsupportsToolSearch: model.compat?.supportsToolSearch ?? false,\n\t};\n}\n\nfunction getPromptCacheRetention(\n\tcompat: Required<OpenAIResponsesCompat>,\n\tcacheRetention: CacheRetention,\n): \"24h\" | undefined {\n\treturn cacheRetention === \"long\" && compat.supportsLongCacheRetention ? \"24h\" : undefined;\n}\n\nfunction formatOpenAIResponsesError(error: unknown): string {\n\treturn formatProviderError(normalizeProviderError(error), \"OpenAI API error\");\n}\n\n// OpenAI Responses-specific options\nexport interface OpenAIResponsesOptions extends StreamOptions {\n\treasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n\treasoningSummary?: \"auto\" | \"detailed\" | \"concise\" | null;\n\tserviceTier?: ResponseCreateParamsStreaming[\"service_tier\"];\n\ttoolChoice?: ResponseCreateParamsStreaming[\"tool_choice\"];\n}\n\n/**\n * Generate function for OpenAI Responses API\n */\nexport const stream: StreamFunction<\"openai-responses\", OpenAIResponsesOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: OpenAIResponsesOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t// Start async processing\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: model.api as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\t// Create OpenAI client\n\t\t\tconst apiKey = getClientApiKey(model.provider, options?.apiKey, options?.headers);\n\t\t\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\t\t\tconst cacheSessionId = cacheRetention === \"none\" ? undefined : options?.sessionId;\n\t\t\tconst client = createClient(model, context, apiKey, options?.headers, cacheSessionId);\n\t\t\tlet params = buildParams(model, context, options);\n\t\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\t\tif (nextParams !== undefined) {\n\t\t\t\tparams = nextParams as ResponseCreateParamsStreaming;\n\t\t\t}\n\t\t\tconst requestOptions = {\n\t\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\t\tmaxRetries: options?.maxRetries ?? 0,\n\t\t\t};\n\t\t\tconst { data: openaiStream, response } = await client.responses.create(params, requestOptions).withResponse();\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tawait processResponsesStream(openaiStream, output, stream, model, {\n\t\t\t\tserviceTier: options?.serviceTier,\n\t\t\t\tapplyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model),\n\t\t\t});\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unknown error occurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) {\n\t\t\t\tdelete (block as { index?: number }).index;\n\t\t\t\t// partialJson is only a streaming scratch buffer; never persist it.\n\t\t\t\tdelete (block as { partialJson?: string }).partialJson;\n\t\t\t}\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = formatOpenAIResponsesError(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nexport const streamSimple: StreamFunction<\"openai-responses\", SimpleStreamOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tgetClientApiKey(model.provider, options?.apiKey, options?.headers);\n\n\tconst base = buildBaseOptions(model, context, options, options?.apiKey);\n\tconst clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;\n\tconst reasoningEffort = clampedReasoning === \"off\" ? undefined : clampedReasoning;\n\n\treturn stream(model, context, {\n\t\t...base,\n\t\treasoningEffort,\n\t} satisfies OpenAIResponsesOptions);\n};\n\nfunction createClient(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\tapiKey: string,\n\toptionsHeaders?: ProviderHeaders,\n\tsessionId?: string,\n) {\n\tconst compat = getCompat(model);\n\tconst headers: ProviderHeaders = { ...model.headers };\n\tif (model.provider === \"github-copilot\") {\n\t\tconst hasImages = hasCopilotVisionInput(context.messages);\n\t\tconst copilotHeaders = buildCopilotDynamicHeaders({\n\t\t\tmessages: context.messages,\n\t\t\thasImages,\n\t\t});\n\t\tObject.assign(headers, copilotHeaders);\n\t}\n\n\tif (sessionId) {\n\t\tif (compat.sessionAffinityFormat === \"openrouter\") {\n\t\t\theaders[\"x-session-id\"] = sessionId;\n\t\t} else {\n\t\t\tif (compat.sessionAffinityFormat === \"openai\") {\n\t\t\t\theaders.session_id = sessionId;\n\t\t\t}\n\t\t\theaders[\"x-client-request-id\"] = sessionId;\n\t\t}\n\t}\n\n\t// Merge options headers last so they can override defaults\n\tif (optionsHeaders) {\n\t\tObject.assign(headers, optionsHeaders);\n\t}\n\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders: headers,\n\t});\n}\n\nfunction buildParams(model: Model<\"openai-responses\">, context: Context, options?: OpenAIResponsesOptions) {\n\tconst compat = getCompat(model);\n\tconst toolPlacement = splitDeferredTools(context, compat.supportsToolSearch);\n\tconst messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS, {\n\t\tdeferredTools: toolPlacement.deferred,\n\t});\n\n\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\tconst params: ResponseCreateParamsStreaming = {\n\t\tmodel: model.id,\n\t\tinput: messages,\n\t\tstream: true,\n\t\tprompt_cache_key: cacheRetention === \"none\" ? undefined : clampOpenAIPromptCacheKey(options?.sessionId),\n\t\tprompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),\n\t\tstore: false,\n\t};\n\n\tif (options?.maxTokens) {\n\t\tparams.max_output_tokens = Math.max(options.maxTokens, OPENAI_RESPONSES_MIN_OUTPUT_TOKENS);\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options?.temperature;\n\t}\n\n\tif (options?.serviceTier !== undefined) {\n\t\tparams.service_tier = options.serviceTier;\n\t}\n\n\tif (toolPlacement.immediate.length > 0) {\n\t\tparams.tools = convertResponsesTools(toolPlacement.immediate);\n\t}\n\n\tif (options?.toolChoice !== undefined) {\n\t\tparams.tool_choice = options.toolChoice;\n\t}\n\n\tif (model.reasoning) {\n\t\tif (options?.reasoningEffort || options?.reasoningSummary) {\n\t\t\tconst effort = options?.reasoningEffort\n\t\t\t\t? (model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort)\n\t\t\t\t: \"medium\";\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: effort as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t\tsummary: options?.reasoningSummary || \"auto\",\n\t\t\t};\n\t\t\tparams.include = [\"reasoning.encrypted_content\"];\n\t\t} else if (model.provider !== \"github-copilot\" && model.thinkingLevelMap?.off !== null) {\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: (model.thinkingLevelMap?.off ?? \"none\") as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t};\n\t\t}\n\t\tif (model.provider === \"xai\") params.include = [\"reasoning.encrypted_content\"];\n\t}\n\n\treturn params;\n}\n\nfunction getServiceTierCostMultiplier(\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n): number {\n\tswitch (serviceTier) {\n\t\tcase \"flex\":\n\t\t\treturn 0.5;\n\t\tcase \"priority\":\n\t\t\treturn model.id === \"gpt-5.5\" ? 2.5 : 2;\n\t\tdefault:\n\t\t\treturn 1;\n\t}\n}\n\nfunction applyServiceTierPricing(\n\tusage: Usage,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n) {\n\tconst multiplier = getServiceTierCostMultiplier(model, serviceTier);\n\tif (multiplier === 1) return;\n\n\tusage.cost.input *= multiplier;\n\tusage.cost.output *= multiplier;\n\tusage.cost.cacheRead *= multiplier;\n\tusage.cost.cacheWrite *= multiplier;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { ProviderStreams } from "../types.ts";
2
+ export declare const openAIResponsesApi: () => ProviderStreams;
3
+ //# sourceMappingURL=openai-responses.lazy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-responses.lazy.d.ts","sourceRoot":"","sources":["../../src/api/openai-responses.lazy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,eAAO,MAAM,kBAAkB,uBAAwE,CAAC","sourcesContent":["import type { ProviderStreams } from \"../types.ts\";\nimport { lazyApi } from \"./lazy.ts\";\n\nexport const openAIResponsesApi = (): ProviderStreams => lazyApi(() => import(\"./openai-responses.ts\"));\n"]}
@@ -0,0 +1,3 @@
1
+ import { lazyApi } from "./lazy.js";
2
+ export const openAIResponsesApi = () => lazyApi(() => import("./openai-responses.js"));
3
+ //# sourceMappingURL=openai-responses.lazy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-responses.lazy.js","sourceRoot":"","sources":["../../src/api/openai-responses.lazy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAoB,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC,CAAC","sourcesContent":["import type { ProviderStreams } from \"../types.ts\";\nimport { lazyApi } from \"./lazy.ts\";\n\nexport const openAIResponsesApi = (): ProviderStreams => lazyApi(() => import(\"./openai-responses.ts\"));\n"]}
@@ -0,0 +1,3 @@
1
+ import type { ImagesFunction, ImagesOptions } from "../types.ts";
2
+ export declare const generateImages: ImagesFunction<"openrouter-images", ImagesOptions>;
3
+ //# sourceMappingURL=openrouter-images.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter-images.d.ts","sourceRoot":"","sources":["../../src/api/openrouter-images.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAIX,cAAc,EAEd,aAAa,EAGb,MAAM,aAAa,CAAC;AAqBrB,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,mBAAmB,EAAE,aAAa,CAmE7E,CAAC","sourcesContent":["import OpenAI from \"openai\";\nimport type {\n\tChatCompletion,\n\tChatCompletionContentPart,\n\tChatCompletionContentPartImage,\n\tChatCompletionContentPartText,\n\tChatCompletionCreateParamsNonStreaming,\n} from \"openai/resources/chat/completions.js\";\nimport type {\n\tAssistantImages,\n\tImageContent,\n\tImagesContext,\n\tImagesFunction,\n\tImagesModel,\n\tImagesOptions,\n\tProviderHeaders,\n\tTextContent,\n} from \"../types.ts\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.ts\";\nimport { headersToRecord, providerHeadersToRecord } from \"../utils/headers.ts\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.ts\";\n\ninterface OpenRouterGeneratedImage {\n\timage_url?: string | { url?: string };\n}\n\ntype OpenRouterImageGenerationMessage = ChatCompletion[\"choices\"][number][\"message\"] & {\n\timages?: OpenRouterGeneratedImage[];\n};\n\ntype OpenRouterImageGenerationChoice = ChatCompletion[\"choices\"][number] & {\n\tmessage: OpenRouterImageGenerationMessage;\n};\n\ntype OpenRouterImageGenerationResponse = ChatCompletion & {\n\tchoices: OpenRouterImageGenerationChoice[];\n};\n\nexport const generateImages: ImagesFunction<\"openrouter-images\", ImagesOptions> = async (\n\tmodel: ImagesModel<\"openrouter-images\">,\n\tcontext: ImagesContext,\n\toptions?: ImagesOptions,\n) => {\n\tconst output: AssistantImages = {\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\toutput: [],\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n\n\ttry {\n\t\tconst apiKey = options?.apiKey;\n\t\tif (!apiKey) {\n\t\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t\t}\n\t\tconst client = createClient(model, apiKey, options?.headers);\n\t\tlet params = buildParams(model, context);\n\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\tif (nextParams !== undefined) {\n\t\t\tparams = nextParams as typeof params;\n\t\t}\n\t\tconst requestOptions = {\n\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\tmaxRetries: options?.maxRetries ?? 0,\n\t\t};\n\t\tconst { data: response, response: rawResponse } = await client.chat.completions\n\t\t\t.create(params as unknown as ChatCompletionCreateParamsNonStreaming, requestOptions)\n\t\t\t.withResponse();\n\t\tawait options?.onResponse?.({ status: rawResponse.status, headers: headersToRecord(rawResponse.headers) }, model);\n\n\t\tconst imageResponse = response as OpenRouterImageGenerationResponse;\n\t\toutput.responseId = imageResponse.id;\n\t\tif (imageResponse.usage) {\n\t\t\toutput.usage = parseUsage(imageResponse.usage, model);\n\t\t}\n\n\t\tconst choice = imageResponse.choices[0];\n\t\tif (choice) {\n\t\t\tconst content = choice.message.content;\n\t\t\tif (typeof content === \"string\" && content.length > 0) {\n\t\t\t\toutput.output.push({ type: \"text\", text: content } satisfies TextContent);\n\t\t\t}\n\n\t\t\tfor (const image of choice.message.images ?? []) {\n\t\t\t\tconst imageUrl = typeof image.image_url === \"string\" ? image.image_url : image.image_url?.url;\n\t\t\t\tif (!imageUrl?.startsWith(\"data:\")) continue;\n\t\t\t\tconst matches = imageUrl.match(/^data:([^;]+);base64,(.+)$/);\n\t\t\t\tif (!matches) continue;\n\t\t\t\toutput.output.push({\n\t\t\t\t\ttype: \"image\",\n\t\t\t\t\tmimeType: matches[1],\n\t\t\t\t\tdata: matches[2],\n\t\t\t\t} satisfies ImageContent);\n\t\t\t}\n\t\t}\n\n\t\treturn output;\n\t} catch (error) {\n\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\toutput.errorMessage = formatProviderError(normalizeProviderError(error));\n\t\treturn output;\n\t}\n};\n\nfunction createClient(\n\tmodel: ImagesModel<\"openrouter-images\">,\n\tapiKey: string,\n\toptionsHeaders?: ProviderHeaders,\n): OpenAI {\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders: providerHeadersToRecord({ ...model.headers, ...optionsHeaders }),\n\t});\n}\n\ntype OpenRouterImagesCreateParams = Omit<ChatCompletionCreateParamsNonStreaming, \"modalities\"> & {\n\tmodalities: Array<\"image\" | \"text\">;\n};\n\nfunction buildParams(model: ImagesModel<\"openrouter-images\">, context: ImagesContext): OpenRouterImagesCreateParams {\n\tconst content: ChatCompletionContentPart[] = context.input.map((item): ChatCompletionContentPart => {\n\t\tif (item.type === \"text\") {\n\t\t\treturn {\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t} satisfies ChatCompletionContentPartText;\n\t\t}\n\t\treturn {\n\t\t\ttype: \"image_url\",\n\t\t\timage_url: {\n\t\t\t\turl: `data:${item.mimeType};base64,${item.data}`,\n\t\t\t},\n\t\t} satisfies ChatCompletionContentPartImage;\n\t});\n\n\treturn {\n\t\tmodel: model.id,\n\t\tmessages: [\n\t\t\t{\n\t\t\t\trole: \"user\" as const,\n\t\t\t\tcontent,\n\t\t\t},\n\t\t],\n\t\tstream: false,\n\t\tmodalities: model.output.includes(\"text\") ? [\"image\", \"text\"] : [\"image\"],\n\t};\n}\n\nfunction parseUsage(\n\trawUsage: {\n\t\tprompt_tokens?: number;\n\t\tcompletion_tokens?: number;\n\t\tprompt_tokens_details?: { cached_tokens?: number; cache_write_tokens?: number };\n\t},\n\tmodel: ImagesModel<\"openrouter-images\">,\n) {\n\tconst promptTokens = rawUsage.prompt_tokens || 0;\n\tconst reportedCachedTokens = rawUsage.prompt_tokens_details?.cached_tokens || 0;\n\tconst cacheWriteTokens = rawUsage.prompt_tokens_details?.cache_write_tokens || 0;\n\tconst cacheReadTokens =\n\t\tcacheWriteTokens > 0 ? Math.max(0, reportedCachedTokens - cacheWriteTokens) : reportedCachedTokens;\n\tconst input = Math.max(0, promptTokens - cacheReadTokens - cacheWriteTokens);\n\tconst output = rawUsage.completion_tokens || 0;\n\tconst usage = {\n\t\tinput,\n\t\toutput,\n\t\tcacheRead: cacheReadTokens,\n\t\tcacheWrite: cacheWriteTokens,\n\t\ttotalTokens: input + output + cacheReadTokens + cacheWriteTokens,\n\t\tcost: {\n\t\t\tinput: (model.cost.input / 1000000) * input,\n\t\t\toutput: (model.cost.output / 1000000) * output,\n\t\t\tcacheRead: (model.cost.cacheRead / 1000000) * cacheReadTokens,\n\t\t\tcacheWrite: (model.cost.cacheWrite / 1000000) * cacheWriteTokens,\n\t\t\ttotal: 0,\n\t\t},\n\t};\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n\treturn usage;\n}\n"]}
@@ -0,0 +1,126 @@
1
+ import OpenAI from "openai";
2
+ import { formatProviderError, normalizeProviderError } from "../utils/error-body.js";
3
+ import { headersToRecord, providerHeadersToRecord } from "../utils/headers.js";
4
+ import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
5
+ export const generateImages = async (model, context, options) => {
6
+ const output = {
7
+ api: model.api,
8
+ provider: model.provider,
9
+ model: model.id,
10
+ output: [],
11
+ stopReason: "stop",
12
+ timestamp: Date.now(),
13
+ };
14
+ try {
15
+ const apiKey = options?.apiKey;
16
+ if (!apiKey) {
17
+ throw new Error(`No API key for provider: ${model.provider}`);
18
+ }
19
+ const client = createClient(model, apiKey, options?.headers);
20
+ let params = buildParams(model, context);
21
+ const nextParams = await options?.onPayload?.(params, model);
22
+ if (nextParams !== undefined) {
23
+ params = nextParams;
24
+ }
25
+ const requestOptions = {
26
+ ...(options?.signal ? { signal: options.signal } : {}),
27
+ ...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
28
+ maxRetries: options?.maxRetries ?? 0,
29
+ };
30
+ const { data: response, response: rawResponse } = await client.chat.completions
31
+ .create(params, requestOptions)
32
+ .withResponse();
33
+ await options?.onResponse?.({ status: rawResponse.status, headers: headersToRecord(rawResponse.headers) }, model);
34
+ const imageResponse = response;
35
+ output.responseId = imageResponse.id;
36
+ if (imageResponse.usage) {
37
+ output.usage = parseUsage(imageResponse.usage, model);
38
+ }
39
+ const choice = imageResponse.choices[0];
40
+ if (choice) {
41
+ const content = choice.message.content;
42
+ if (typeof content === "string" && content.length > 0) {
43
+ output.output.push({ type: "text", text: content });
44
+ }
45
+ for (const image of choice.message.images ?? []) {
46
+ const imageUrl = typeof image.image_url === "string" ? image.image_url : image.image_url?.url;
47
+ if (!imageUrl?.startsWith("data:"))
48
+ continue;
49
+ const matches = imageUrl.match(/^data:([^;]+);base64,(.+)$/);
50
+ if (!matches)
51
+ continue;
52
+ output.output.push({
53
+ type: "image",
54
+ mimeType: matches[1],
55
+ data: matches[2],
56
+ });
57
+ }
58
+ }
59
+ return output;
60
+ }
61
+ catch (error) {
62
+ output.stopReason = options?.signal?.aborted ? "aborted" : "error";
63
+ output.errorMessage = formatProviderError(normalizeProviderError(error));
64
+ return output;
65
+ }
66
+ };
67
+ function createClient(model, apiKey, optionsHeaders) {
68
+ return new OpenAI({
69
+ apiKey,
70
+ baseURL: model.baseUrl,
71
+ dangerouslyAllowBrowser: true,
72
+ defaultHeaders: providerHeadersToRecord({ ...model.headers, ...optionsHeaders }),
73
+ });
74
+ }
75
+ function buildParams(model, context) {
76
+ const content = context.input.map((item) => {
77
+ if (item.type === "text") {
78
+ return {
79
+ type: "text",
80
+ text: sanitizeSurrogates(item.text),
81
+ };
82
+ }
83
+ return {
84
+ type: "image_url",
85
+ image_url: {
86
+ url: `data:${item.mimeType};base64,${item.data}`,
87
+ },
88
+ };
89
+ });
90
+ return {
91
+ model: model.id,
92
+ messages: [
93
+ {
94
+ role: "user",
95
+ content,
96
+ },
97
+ ],
98
+ stream: false,
99
+ modalities: model.output.includes("text") ? ["image", "text"] : ["image"],
100
+ };
101
+ }
102
+ function parseUsage(rawUsage, model) {
103
+ const promptTokens = rawUsage.prompt_tokens || 0;
104
+ const reportedCachedTokens = rawUsage.prompt_tokens_details?.cached_tokens || 0;
105
+ const cacheWriteTokens = rawUsage.prompt_tokens_details?.cache_write_tokens || 0;
106
+ const cacheReadTokens = cacheWriteTokens > 0 ? Math.max(0, reportedCachedTokens - cacheWriteTokens) : reportedCachedTokens;
107
+ const input = Math.max(0, promptTokens - cacheReadTokens - cacheWriteTokens);
108
+ const output = rawUsage.completion_tokens || 0;
109
+ const usage = {
110
+ input,
111
+ output,
112
+ cacheRead: cacheReadTokens,
113
+ cacheWrite: cacheWriteTokens,
114
+ totalTokens: input + output + cacheReadTokens + cacheWriteTokens,
115
+ cost: {
116
+ input: (model.cost.input / 1000000) * input,
117
+ output: (model.cost.output / 1000000) * output,
118
+ cacheRead: (model.cost.cacheRead / 1000000) * cacheReadTokens,
119
+ cacheWrite: (model.cost.cacheWrite / 1000000) * cacheWriteTokens,
120
+ total: 0,
121
+ },
122
+ };
123
+ usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
124
+ return usage;
125
+ }
126
+ //# sourceMappingURL=openrouter-images.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter-images.js","sourceRoot":"","sources":["../../src/api/openrouter-images.ts"],"names":[],"mappings":"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","sourcesContent":["import OpenAI from \"openai\";\nimport type {\n\tChatCompletion,\n\tChatCompletionContentPart,\n\tChatCompletionContentPartImage,\n\tChatCompletionContentPartText,\n\tChatCompletionCreateParamsNonStreaming,\n} from \"openai/resources/chat/completions.js\";\nimport type {\n\tAssistantImages,\n\tImageContent,\n\tImagesContext,\n\tImagesFunction,\n\tImagesModel,\n\tImagesOptions,\n\tProviderHeaders,\n\tTextContent,\n} from \"../types.ts\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.ts\";\nimport { headersToRecord, providerHeadersToRecord } from \"../utils/headers.ts\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.ts\";\n\ninterface OpenRouterGeneratedImage {\n\timage_url?: string | { url?: string };\n}\n\ntype OpenRouterImageGenerationMessage = ChatCompletion[\"choices\"][number][\"message\"] & {\n\timages?: OpenRouterGeneratedImage[];\n};\n\ntype OpenRouterImageGenerationChoice = ChatCompletion[\"choices\"][number] & {\n\tmessage: OpenRouterImageGenerationMessage;\n};\n\ntype OpenRouterImageGenerationResponse = ChatCompletion & {\n\tchoices: OpenRouterImageGenerationChoice[];\n};\n\nexport const generateImages: ImagesFunction<\"openrouter-images\", ImagesOptions> = async (\n\tmodel: ImagesModel<\"openrouter-images\">,\n\tcontext: ImagesContext,\n\toptions?: ImagesOptions,\n) => {\n\tconst output: AssistantImages = {\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\toutput: [],\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n\n\ttry {\n\t\tconst apiKey = options?.apiKey;\n\t\tif (!apiKey) {\n\t\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t\t}\n\t\tconst client = createClient(model, apiKey, options?.headers);\n\t\tlet params = buildParams(model, context);\n\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\tif (nextParams !== undefined) {\n\t\t\tparams = nextParams as typeof params;\n\t\t}\n\t\tconst requestOptions = {\n\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\tmaxRetries: options?.maxRetries ?? 0,\n\t\t};\n\t\tconst { data: response, response: rawResponse } = await client.chat.completions\n\t\t\t.create(params as unknown as ChatCompletionCreateParamsNonStreaming, requestOptions)\n\t\t\t.withResponse();\n\t\tawait options?.onResponse?.({ status: rawResponse.status, headers: headersToRecord(rawResponse.headers) }, model);\n\n\t\tconst imageResponse = response as OpenRouterImageGenerationResponse;\n\t\toutput.responseId = imageResponse.id;\n\t\tif (imageResponse.usage) {\n\t\t\toutput.usage = parseUsage(imageResponse.usage, model);\n\t\t}\n\n\t\tconst choice = imageResponse.choices[0];\n\t\tif (choice) {\n\t\t\tconst content = choice.message.content;\n\t\t\tif (typeof content === \"string\" && content.length > 0) {\n\t\t\t\toutput.output.push({ type: \"text\", text: content } satisfies TextContent);\n\t\t\t}\n\n\t\t\tfor (const image of choice.message.images ?? []) {\n\t\t\t\tconst imageUrl = typeof image.image_url === \"string\" ? image.image_url : image.image_url?.url;\n\t\t\t\tif (!imageUrl?.startsWith(\"data:\")) continue;\n\t\t\t\tconst matches = imageUrl.match(/^data:([^;]+);base64,(.+)$/);\n\t\t\t\tif (!matches) continue;\n\t\t\t\toutput.output.push({\n\t\t\t\t\ttype: \"image\",\n\t\t\t\t\tmimeType: matches[1],\n\t\t\t\t\tdata: matches[2],\n\t\t\t\t} satisfies ImageContent);\n\t\t\t}\n\t\t}\n\n\t\treturn output;\n\t} catch (error) {\n\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\toutput.errorMessage = formatProviderError(normalizeProviderError(error));\n\t\treturn output;\n\t}\n};\n\nfunction createClient(\n\tmodel: ImagesModel<\"openrouter-images\">,\n\tapiKey: string,\n\toptionsHeaders?: ProviderHeaders,\n): OpenAI {\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders: providerHeadersToRecord({ ...model.headers, ...optionsHeaders }),\n\t});\n}\n\ntype OpenRouterImagesCreateParams = Omit<ChatCompletionCreateParamsNonStreaming, \"modalities\"> & {\n\tmodalities: Array<\"image\" | \"text\">;\n};\n\nfunction buildParams(model: ImagesModel<\"openrouter-images\">, context: ImagesContext): OpenRouterImagesCreateParams {\n\tconst content: ChatCompletionContentPart[] = context.input.map((item): ChatCompletionContentPart => {\n\t\tif (item.type === \"text\") {\n\t\t\treturn {\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t} satisfies ChatCompletionContentPartText;\n\t\t}\n\t\treturn {\n\t\t\ttype: \"image_url\",\n\t\t\timage_url: {\n\t\t\t\turl: `data:${item.mimeType};base64,${item.data}`,\n\t\t\t},\n\t\t} satisfies ChatCompletionContentPartImage;\n\t});\n\n\treturn {\n\t\tmodel: model.id,\n\t\tmessages: [\n\t\t\t{\n\t\t\t\trole: \"user\" as const,\n\t\t\t\tcontent,\n\t\t\t},\n\t\t],\n\t\tstream: false,\n\t\tmodalities: model.output.includes(\"text\") ? [\"image\", \"text\"] : [\"image\"],\n\t};\n}\n\nfunction parseUsage(\n\trawUsage: {\n\t\tprompt_tokens?: number;\n\t\tcompletion_tokens?: number;\n\t\tprompt_tokens_details?: { cached_tokens?: number; cache_write_tokens?: number };\n\t},\n\tmodel: ImagesModel<\"openrouter-images\">,\n) {\n\tconst promptTokens = rawUsage.prompt_tokens || 0;\n\tconst reportedCachedTokens = rawUsage.prompt_tokens_details?.cached_tokens || 0;\n\tconst cacheWriteTokens = rawUsage.prompt_tokens_details?.cache_write_tokens || 0;\n\tconst cacheReadTokens =\n\t\tcacheWriteTokens > 0 ? Math.max(0, reportedCachedTokens - cacheWriteTokens) : reportedCachedTokens;\n\tconst input = Math.max(0, promptTokens - cacheReadTokens - cacheWriteTokens);\n\tconst output = rawUsage.completion_tokens || 0;\n\tconst usage = {\n\t\tinput,\n\t\toutput,\n\t\tcacheRead: cacheReadTokens,\n\t\tcacheWrite: cacheWriteTokens,\n\t\ttotalTokens: input + output + cacheReadTokens + cacheWriteTokens,\n\t\tcost: {\n\t\t\tinput: (model.cost.input / 1000000) * input,\n\t\t\toutput: (model.cost.output / 1000000) * output,\n\t\t\tcacheRead: (model.cost.cacheRead / 1000000) * cacheReadTokens,\n\t\t\tcacheWrite: (model.cost.cacheWrite / 1000000) * cacheWriteTokens,\n\t\t\ttotal: 0,\n\t\t},\n\t};\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n\treturn usage;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { ProviderImages } from "../types.ts";
2
+ export declare const openrouterImagesApi: () => ProviderImages;
3
+ //# sourceMappingURL=openrouter-images.lazy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter-images.lazy.d.ts","sourceRoot":"","sources":["../../src/api/openrouter-images.lazy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,aAAa,CAAC;AAE/D,eAAO,MAAM,mBAAmB,sBAO9B,CAAC","sourcesContent":["import type { ImagesModel, ProviderImages } from \"../types.ts\";\n\nexport const openrouterImagesApi = (): ProviderImages => ({\n\tgenerateImages: async (model, context, options) =>\n\t\t(await import(\"./openrouter-images.ts\")).generateImages(\n\t\t\tmodel as ImagesModel<\"openrouter-images\">,\n\t\t\tcontext,\n\t\t\toptions,\n\t\t),\n});\n"]}
@@ -0,0 +1,4 @@
1
+ export const openrouterImagesApi = () => ({
2
+ generateImages: async (model, context, options) => (await import("./openrouter-images.js")).generateImages(model, context, options),
3
+ });
4
+ //# sourceMappingURL=openrouter-images.lazy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter-images.lazy.js","sourceRoot":"","sources":["../../src/api/openrouter-images.lazy.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAmB,EAAE,CAAC,CAAC;IACzD,cAAc,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CACjD,CAAC,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAAC,cAAc,CACtD,KAAyC,EACzC,OAAO,EACP,OAAO,CACP;CACF,CAAC,CAAC","sourcesContent":["import type { ImagesModel, ProviderImages } from \"../types.ts\";\n\nexport const openrouterImagesApi = (): ProviderImages => ({\n\tgenerateImages: async (model, context, options) =>\n\t\t(await import(\"./openrouter-images.ts\")).generateImages(\n\t\t\tmodel as ImagesModel<\"openrouter-images\">,\n\t\t\tcontext,\n\t\t\toptions,\n\t\t),\n});\n"]}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * pi-messages API implementation.
3
+ *
4
+ * Streams pi's own message protocol directly to a backend: the request is a
5
+ * single POST of `{ model, context, options }` to `<baseUrl>/messages`, the
6
+ * response is an SSE stream of serialized assistant-message events plus a
7
+ * terminal `done`/`error` event. This is the wire protocol spoken by the
8
+ * Radius gateway, but any backend implementing it can be used, e.g. via a
9
+ * models.json custom provider with `"api": "pi-messages"`.
10
+ */
11
+ import type { AssistantMessage, SimpleStreamOptions, StreamFunction, StreamOptions, ThinkingLevel, ToolCall } from "../types.ts";
12
+ export interface PiMessagesOptions extends StreamOptions {
13
+ reasoning?: ThinkingLevel;
14
+ toolChoice?: "auto" | "none" | "required" | {
15
+ type: "function";
16
+ function: {
17
+ name: string;
18
+ };
19
+ };
20
+ /** Ask the backend for debug metadata (e.g. routing response headers). */
21
+ debug?: boolean;
22
+ }
23
+ type PiMessagesUsage = AssistantMessage["usage"];
24
+ type PiMessagesStopReason = AssistantMessage["stopReason"];
25
+ /** Impact summary of a server-side message rewrite (e.g. a gateway policy). */
26
+ export type PiMessagesRewriteImpact = {
27
+ policyId: string;
28
+ policyVersion: number;
29
+ changed: boolean;
30
+ tokenCountChange: number;
31
+ messageCountChange: number;
32
+ systemPromptChanged: boolean;
33
+ };
34
+ /** Serialized assistant-message event as sent by a pi-messages backend. */
35
+ export type PiMessagesEvent = {
36
+ type: "start";
37
+ } | {
38
+ type: "text_start";
39
+ contentIndex: number;
40
+ } | {
41
+ type: "text_delta";
42
+ contentIndex: number;
43
+ delta: string;
44
+ } | {
45
+ type: "text_end";
46
+ contentIndex: number;
47
+ content: string;
48
+ contentSignature?: string;
49
+ } | {
50
+ type: "thinking_start";
51
+ contentIndex: number;
52
+ } | {
53
+ type: "thinking_delta";
54
+ contentIndex: number;
55
+ delta: string;
56
+ } | {
57
+ type: "thinking_end";
58
+ contentIndex: number;
59
+ content: string;
60
+ contentSignature?: string;
61
+ redacted?: boolean;
62
+ } | {
63
+ type: "toolcall_start";
64
+ contentIndex: number;
65
+ id: string;
66
+ toolName: string;
67
+ } | {
68
+ type: "toolcall_delta";
69
+ contentIndex: number;
70
+ delta: string;
71
+ } | {
72
+ type: "toolcall_end";
73
+ contentIndex: number;
74
+ toolCall: ToolCall;
75
+ } | {
76
+ type: "done";
77
+ reason: Extract<PiMessagesStopReason, "stop" | "length" | "toolUse">;
78
+ usage: PiMessagesUsage;
79
+ responseId?: string;
80
+ rewrite?: PiMessagesRewriteImpact;
81
+ } | {
82
+ type: "error";
83
+ reason: Extract<PiMessagesStopReason, "aborted" | "error">;
84
+ usage: PiMessagesUsage;
85
+ errorMessage?: string;
86
+ responseId?: string;
87
+ rewrite?: PiMessagesRewriteImpact;
88
+ };
89
+ export declare class PiMessagesResponseError extends Error {
90
+ code?: string;
91
+ readonly diagnosticDetails: Record<string, unknown>;
92
+ constructor(message: string, code: string | undefined, diagnosticDetails: Record<string, unknown>);
93
+ }
94
+ export declare const stream: StreamFunction<"pi-messages", PiMessagesOptions>;
95
+ export declare const streamSimple: StreamFunction<"pi-messages", SimpleStreamOptions>;
96
+ export {};
97
+ //# sourceMappingURL=pi-messages.d.ts.map