@openrouter/sdk 0.3.2 → 0.3.10

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 (319) hide show
  1. package/.zed/settings.json +10 -0
  2. package/_speakeasy/.github/action-inputs-config.json +53 -0
  3. package/_speakeasy/.github/action-security-config.json +88 -0
  4. package/esm/core.js +1 -0
  5. package/esm/funcs/analyticsGetUserActivity.js +1 -0
  6. package/esm/funcs/apiKeysCreate.js +1 -0
  7. package/esm/funcs/apiKeysDelete.js +1 -0
  8. package/esm/funcs/apiKeysGet.js +1 -0
  9. package/esm/funcs/apiKeysGetCurrentKeyMetadata.js +1 -0
  10. package/esm/funcs/apiKeysList.js +1 -0
  11. package/esm/funcs/apiKeysUpdate.js +1 -0
  12. package/esm/funcs/betaResponsesSend.js +1 -0
  13. package/esm/funcs/call-model.d.ts +118 -0
  14. package/esm/funcs/call-model.js +137 -0
  15. package/esm/funcs/chatSend.js +1 -0
  16. package/esm/funcs/completionsGenerate.js +1 -0
  17. package/esm/funcs/creditsCreateCoinbaseCharge.js +1 -0
  18. package/esm/funcs/creditsGetCredits.js +1 -0
  19. package/esm/funcs/embeddingsGenerate.js +1 -0
  20. package/esm/funcs/embeddingsListModels.js +1 -0
  21. package/esm/funcs/endpointsList.js +1 -0
  22. package/esm/funcs/endpointsListZdrEndpoints.js +1 -0
  23. package/esm/funcs/generationsGetGeneration.js +1 -0
  24. package/esm/funcs/modelsCount.js +1 -0
  25. package/esm/funcs/modelsList.js +1 -0
  26. package/esm/funcs/modelsListForUser.js +1 -0
  27. package/esm/funcs/oAuthCreateAuthCode.js +1 -0
  28. package/esm/funcs/oAuthExchangeAuthCodeForAPIKey.js +1 -0
  29. package/esm/funcs/parametersGetParameters.js +1 -0
  30. package/esm/funcs/providersList.js +1 -0
  31. package/esm/hooks/hooks.js +1 -0
  32. package/esm/hooks/index.js +1 -0
  33. package/esm/hooks/types.js +1 -0
  34. package/esm/index.d.ts +20 -5
  35. package/esm/index.js +21 -4
  36. package/esm/lib/anthropic-compat.d.ts +50 -0
  37. package/esm/lib/anthropic-compat.js +223 -0
  38. package/esm/lib/anthropic-compat.test.d.ts +2 -0
  39. package/esm/lib/anthropic-compat.test.js +479 -0
  40. package/esm/lib/async-params.d.ts +53 -0
  41. package/esm/lib/async-params.js +76 -0
  42. package/esm/lib/base64.js +1 -0
  43. package/esm/lib/chat-compat.d.ts +46 -0
  44. package/esm/lib/chat-compat.js +112 -0
  45. package/esm/lib/chat-compat.test.d.ts +2 -0
  46. package/esm/lib/chat-compat.test.js +282 -0
  47. package/esm/lib/claude-constants.d.ts +22 -0
  48. package/esm/lib/claude-constants.js +20 -0
  49. package/esm/lib/claude-type-guards.d.ts +10 -0
  50. package/esm/lib/claude-type-guards.js +70 -0
  51. package/esm/lib/config.d.ts +2 -2
  52. package/esm/lib/config.js +3 -2
  53. package/esm/lib/dlv.js +1 -0
  54. package/esm/lib/encodings.js +1 -0
  55. package/esm/lib/env.js +1 -0
  56. package/esm/lib/event-streams.js +1 -0
  57. package/esm/lib/files.js +1 -0
  58. package/esm/lib/http.js +1 -0
  59. package/esm/lib/is-plain-object.js +1 -0
  60. package/esm/lib/logger.js +1 -0
  61. package/esm/lib/matchers.js +1 -0
  62. package/esm/lib/{response-wrapper.d.ts → model-result.d.ts} +29 -43
  63. package/esm/lib/{response-wrapper.js → model-result.js} +146 -175
  64. package/esm/lib/next-turn-params.d.ts +30 -0
  65. package/esm/lib/next-turn-params.js +129 -0
  66. package/esm/lib/primitives.js +1 -0
  67. package/esm/lib/retries.js +1 -0
  68. package/esm/lib/reusable-stream.js +10 -10
  69. package/esm/lib/schemas.js +1 -0
  70. package/esm/lib/sdks.js +1 -0
  71. package/esm/lib/security.js +1 -0
  72. package/esm/lib/stop-conditions.d.ts +80 -0
  73. package/esm/lib/stop-conditions.js +104 -0
  74. package/esm/lib/stream-transformers.d.ts +30 -4
  75. package/esm/lib/stream-transformers.js +467 -98
  76. package/esm/lib/stream-type-guards.d.ts +29 -0
  77. package/esm/lib/stream-type-guards.js +109 -0
  78. package/esm/lib/tool-executor.d.ts +7 -6
  79. package/esm/lib/tool-executor.js +4 -0
  80. package/esm/lib/tool-orchestrator.d.ts +7 -7
  81. package/esm/lib/tool-orchestrator.js +38 -10
  82. package/esm/lib/tool-types.d.ts +163 -29
  83. package/esm/lib/tool-types.js +6 -0
  84. package/esm/lib/tool.d.ts +99 -0
  85. package/esm/lib/tool.js +71 -0
  86. package/esm/lib/turn-context.d.ts +50 -0
  87. package/esm/lib/turn-context.js +59 -0
  88. package/esm/lib/url.js +1 -0
  89. package/esm/models/activityitem.js +1 -0
  90. package/esm/models/assistantmessage.js +1 -0
  91. package/esm/models/badgatewayresponseerrordata.js +1 -0
  92. package/esm/models/badrequestresponseerrordata.js +1 -0
  93. package/esm/models/chatcompletionfinishreason.js +1 -0
  94. package/esm/models/chaterror.js +1 -0
  95. package/esm/models/chatgenerationparams.js +1 -0
  96. package/esm/models/chatgenerationtokenusage.js +1 -0
  97. package/esm/models/chatmessagecontentitem.js +1 -0
  98. package/esm/models/chatmessagecontentitemaudio.js +1 -0
  99. package/esm/models/chatmessagecontentitemcachecontrol.js +1 -0
  100. package/esm/models/chatmessagecontentitemimage.js +1 -0
  101. package/esm/models/chatmessagecontentitemtext.js +1 -0
  102. package/esm/models/chatmessagecontentitemvideo.js +1 -0
  103. package/esm/models/chatmessagetokenlogprob.js +1 -0
  104. package/esm/models/chatmessagetokenlogprobs.js +1 -0
  105. package/esm/models/chatmessagetoolcall.js +1 -0
  106. package/esm/models/chatresponse.js +1 -0
  107. package/esm/models/chatresponsechoice.js +1 -0
  108. package/esm/models/chatstreamingchoice.js +1 -0
  109. package/esm/models/chatstreamingmessagechunk.js +1 -0
  110. package/esm/models/chatstreamingmessagetoolcall.js +1 -0
  111. package/esm/models/chatstreamingresponsechunk.js +1 -0
  112. package/esm/models/chatstreamoptions.js +1 -0
  113. package/esm/models/claude-message.d.ts +218 -0
  114. package/esm/models/claude-message.js +6 -0
  115. package/esm/models/completionchoice.js +1 -0
  116. package/esm/models/completioncreateparams.js +1 -0
  117. package/esm/models/completionlogprobs.js +1 -0
  118. package/esm/models/completionresponse.js +1 -0
  119. package/esm/models/completionusage.js +1 -0
  120. package/esm/models/createchargerequest.js +1 -0
  121. package/esm/models/datacollection.js +1 -0
  122. package/esm/models/defaultparameters.js +1 -0
  123. package/esm/models/edgenetworktimeoutresponseerrordata.js +1 -0
  124. package/esm/models/endpointstatus.js +1 -0
  125. package/esm/models/errors/badgatewayresponseerror.js +1 -0
  126. package/esm/models/errors/badrequestresponseerror.js +1 -0
  127. package/esm/models/errors/chaterror.js +1 -0
  128. package/esm/models/errors/edgenetworktimeoutresponseerror.js +1 -0
  129. package/esm/models/errors/forbiddenresponseerror.js +1 -0
  130. package/esm/models/errors/httpclienterrors.js +1 -0
  131. package/esm/models/errors/index.js +1 -0
  132. package/esm/models/errors/internalserverresponseerror.js +1 -0
  133. package/esm/models/errors/notfoundresponseerror.js +1 -0
  134. package/esm/models/errors/openrouterdefaulterror.js +1 -0
  135. package/esm/models/errors/openroutererror.js +1 -0
  136. package/esm/models/errors/payloadtoolargeresponseerror.js +1 -0
  137. package/esm/models/errors/paymentrequiredresponseerror.js +1 -0
  138. package/esm/models/errors/provideroverloadedresponseerror.js +1 -0
  139. package/esm/models/errors/requesttimeoutresponseerror.js +1 -0
  140. package/esm/models/errors/responsevalidationerror.js +1 -0
  141. package/esm/models/errors/sdkvalidationerror.js +1 -0
  142. package/esm/models/errors/serviceunavailableresponseerror.js +1 -0
  143. package/esm/models/errors/toomanyrequestsresponseerror.js +1 -0
  144. package/esm/models/errors/unauthorizedresponseerror.js +1 -0
  145. package/esm/models/errors/unprocessableentityresponseerror.js +1 -0
  146. package/esm/models/filecitation.js +1 -0
  147. package/esm/models/filepath.js +1 -0
  148. package/esm/models/forbiddenresponseerrordata.js +1 -0
  149. package/esm/models/imagegenerationstatus.js +1 -0
  150. package/esm/models/index.d.ts +1 -0
  151. package/esm/models/index.js +2 -0
  152. package/esm/models/inputmodality.js +1 -0
  153. package/esm/models/instructtype.js +1 -0
  154. package/esm/models/internalserverresponseerrordata.js +1 -0
  155. package/esm/models/jsonschemaconfig.js +1 -0
  156. package/esm/models/listendpointsresponse.js +1 -0
  157. package/esm/models/message.js +1 -0
  158. package/esm/models/model.js +1 -0
  159. package/esm/models/modelarchitecture.js +1 -0
  160. package/esm/models/modelgroup.js +1 -0
  161. package/esm/models/modelscountresponse.js +1 -0
  162. package/esm/models/modelslistresponse.js +1 -0
  163. package/esm/models/namedtoolchoice.js +1 -0
  164. package/esm/models/notfoundresponseerrordata.js +1 -0
  165. package/esm/models/openairesponsesannotation.js +1 -0
  166. package/esm/models/openairesponsesincludable.js +1 -0
  167. package/esm/models/openairesponsesincompletedetails.js +1 -0
  168. package/esm/models/openairesponsesinputunion.js +1 -0
  169. package/esm/models/openairesponsesprompt.js +1 -0
  170. package/esm/models/openairesponsesreasoningconfig.js +1 -0
  171. package/esm/models/openairesponsesreasoningeffort.js +1 -0
  172. package/esm/models/openairesponsesrefusalcontent.js +1 -0
  173. package/esm/models/openairesponsesresponsestatus.js +1 -0
  174. package/esm/models/openairesponsesservicetier.js +1 -0
  175. package/esm/models/openairesponsestoolchoiceunion.js +1 -0
  176. package/esm/models/openairesponsestruncation.js +1 -0
  177. package/esm/models/openresponseseasyinputmessage.js +1 -0
  178. package/esm/models/openresponseserrorevent.js +1 -0
  179. package/esm/models/openresponsesfunctioncalloutput.js +1 -0
  180. package/esm/models/openresponsesfunctiontoolcall.js +1 -0
  181. package/esm/models/openresponsesimagegencallcompleted.js +1 -0
  182. package/esm/models/openresponsesimagegencallgenerating.js +1 -0
  183. package/esm/models/openresponsesimagegencallinprogress.js +1 -0
  184. package/esm/models/openresponsesimagegencallpartialimage.js +1 -0
  185. package/esm/models/openresponsesinput.js +1 -0
  186. package/esm/models/openresponsesinputmessageitem.js +1 -0
  187. package/esm/models/openresponseslogprobs.js +1 -0
  188. package/esm/models/openresponsesnonstreamingresponse.js +1 -0
  189. package/esm/models/openresponsesreasoning.js +1 -0
  190. package/esm/models/openresponsesreasoningconfig.js +1 -0
  191. package/esm/models/openresponsesreasoningdeltaevent.js +1 -0
  192. package/esm/models/openresponsesreasoningdoneevent.js +1 -0
  193. package/esm/models/openresponsesreasoningsummarypartaddedevent.js +1 -0
  194. package/esm/models/openresponsesreasoningsummarytextdeltaevent.js +1 -0
  195. package/esm/models/openresponsesreasoningsummarytextdoneevent.js +1 -0
  196. package/esm/models/openresponsesrequest.js +1 -0
  197. package/esm/models/openresponsesresponsetext.js +1 -0
  198. package/esm/models/openresponsesstreamevent.js +1 -0
  199. package/esm/models/openresponsestoplogprobs.js +1 -0
  200. package/esm/models/openresponsesusage.js +1 -0
  201. package/esm/models/openresponseswebsearch20250826tool.js +1 -0
  202. package/esm/models/openresponseswebsearchpreview20250311tool.js +1 -0
  203. package/esm/models/openresponseswebsearchpreviewtool.js +1 -0
  204. package/esm/models/openresponseswebsearchtool.js +1 -0
  205. package/esm/models/operations/createauthkeyscode.js +1 -0
  206. package/esm/models/operations/createcoinbasecharge.js +1 -0
  207. package/esm/models/operations/createembeddings.js +1 -0
  208. package/esm/models/operations/createkeys.js +1 -0
  209. package/esm/models/operations/createresponses.js +1 -0
  210. package/esm/models/operations/deletekeys.js +1 -0
  211. package/esm/models/operations/exchangeauthcodeforapikey.js +1 -0
  212. package/esm/models/operations/getcredits.js +1 -0
  213. package/esm/models/operations/getcurrentkey.js +1 -0
  214. package/esm/models/operations/getgeneration.js +1 -0
  215. package/esm/models/operations/getkey.js +1 -0
  216. package/esm/models/operations/getmodels.js +1 -0
  217. package/esm/models/operations/getparameters.js +1 -0
  218. package/esm/models/operations/getuseractivity.js +1 -0
  219. package/esm/models/operations/index.js +1 -0
  220. package/esm/models/operations/list.js +1 -0
  221. package/esm/models/operations/listendpoints.js +1 -0
  222. package/esm/models/operations/listendpointszdr.js +1 -0
  223. package/esm/models/operations/listmodelsuser.js +1 -0
  224. package/esm/models/operations/listproviders.js +1 -0
  225. package/esm/models/operations/sendchatcompletionrequest.js +1 -0
  226. package/esm/models/operations/updatekeys.js +1 -0
  227. package/esm/models/outputitemimagegenerationcall.js +1 -0
  228. package/esm/models/outputmessage.js +1 -0
  229. package/esm/models/outputmodality.js +1 -0
  230. package/esm/models/parameter.js +1 -0
  231. package/esm/models/payloadtoolargeresponseerrordata.js +1 -0
  232. package/esm/models/paymentrequiredresponseerrordata.js +1 -0
  233. package/esm/models/pdfparserengine.js +1 -0
  234. package/esm/models/pdfparseroptions.js +1 -0
  235. package/esm/models/perrequestlimits.js +1 -0
  236. package/esm/models/providername.js +1 -0
  237. package/esm/models/provideroverloadedresponseerrordata.js +1 -0
  238. package/esm/models/providerpreferences.js +1 -0
  239. package/esm/models/providersort.js +1 -0
  240. package/esm/models/providersortconfig.js +1 -0
  241. package/esm/models/providersortunion.js +1 -0
  242. package/esm/models/publicendpoint.js +1 -0
  243. package/esm/models/publicpricing.js +1 -0
  244. package/esm/models/quantization.js +1 -0
  245. package/esm/models/reasoningsummarytext.js +1 -0
  246. package/esm/models/reasoningsummaryverbosity.js +1 -0
  247. package/esm/models/reasoningtextcontent.js +1 -0
  248. package/esm/models/requesttimeoutresponseerrordata.js +1 -0
  249. package/esm/models/responseformatjsonschema.js +1 -0
  250. package/esm/models/responseformattextconfig.js +1 -0
  251. package/esm/models/responseformattextgrammar.js +1 -0
  252. package/esm/models/responseinputaudio.js +1 -0
  253. package/esm/models/responseinputfile.js +1 -0
  254. package/esm/models/responseinputimage.js +1 -0
  255. package/esm/models/responseinputtext.js +1 -0
  256. package/esm/models/responseoutputtext.js +1 -0
  257. package/esm/models/responseserrorfield.js +1 -0
  258. package/esm/models/responsesformatjsonobject.js +1 -0
  259. package/esm/models/responsesformattext.js +1 -0
  260. package/esm/models/responsesformattextjsonschemaconfig.js +1 -0
  261. package/esm/models/responsesimagegenerationcall.js +1 -0
  262. package/esm/models/responsesoutputitem.js +1 -0
  263. package/esm/models/responsesoutputitemfilesearchcall.js +1 -0
  264. package/esm/models/responsesoutputitemfunctioncall.js +1 -0
  265. package/esm/models/responsesoutputitemreasoning.js +1 -0
  266. package/esm/models/responsesoutputmessage.js +1 -0
  267. package/esm/models/responsessearchcontextsize.js +1 -0
  268. package/esm/models/responseswebsearchcalloutput.js +1 -0
  269. package/esm/models/responseswebsearchuserlocation.js +1 -0
  270. package/esm/models/responsetextconfig.js +1 -0
  271. package/esm/models/schema0.js +1 -0
  272. package/esm/models/schema3.js +1 -0
  273. package/esm/models/security.js +1 -0
  274. package/esm/models/serviceunavailableresponseerrordata.js +1 -0
  275. package/esm/models/systemmessage.js +1 -0
  276. package/esm/models/toolcallstatus.js +1 -0
  277. package/esm/models/tooldefinitionjson.js +1 -0
  278. package/esm/models/toolresponsemessage.js +1 -0
  279. package/esm/models/toomanyrequestsresponseerrordata.js +1 -0
  280. package/esm/models/topproviderinfo.js +1 -0
  281. package/esm/models/unauthorizedresponseerrordata.js +1 -0
  282. package/esm/models/unprocessableentityresponseerrordata.js +1 -0
  283. package/esm/models/urlcitation.js +1 -0
  284. package/esm/models/usermessage.js +1 -0
  285. package/esm/models/websearchengine.js +1 -0
  286. package/esm/models/websearchpreviewtooluserlocation.js +1 -0
  287. package/esm/models/websearchstatus.js +1 -0
  288. package/esm/sdk/analytics.js +1 -0
  289. package/esm/sdk/apikeys.js +1 -0
  290. package/esm/sdk/beta.js +1 -0
  291. package/esm/sdk/chat.js +1 -0
  292. package/esm/sdk/completions.js +1 -0
  293. package/esm/sdk/credits.js +1 -0
  294. package/esm/sdk/embeddings.js +1 -0
  295. package/esm/sdk/endpoints.js +1 -0
  296. package/esm/sdk/generations.js +1 -0
  297. package/esm/sdk/index.js +1 -0
  298. package/esm/sdk/models.js +1 -0
  299. package/esm/sdk/oauth.js +1 -0
  300. package/esm/sdk/parameters.js +1 -0
  301. package/esm/sdk/providers.js +1 -0
  302. package/esm/sdk/responses.js +1 -0
  303. package/esm/sdk/sdk.d.ts +4 -10
  304. package/esm/sdk/sdk.js +2 -1
  305. package/esm/types/async.js +1 -0
  306. package/esm/types/blobs.js +1 -0
  307. package/esm/types/constdatetime.js +1 -0
  308. package/esm/types/discriminatedUnion.js +1 -0
  309. package/esm/types/enums.js +1 -0
  310. package/esm/types/fp.js +1 -0
  311. package/esm/types/index.js +1 -0
  312. package/esm/types/operations.js +1 -0
  313. package/esm/types/rfcdate.js +1 -0
  314. package/esm/types/streams.js +1 -0
  315. package/esm/types/unrecognized.js +1 -0
  316. package/jsr.json +1 -1
  317. package/package.json +6 -3
  318. package/esm/funcs/callModel.d.ts +0 -87
  319. package/esm/funcs/callModel.js +0 -215
@@ -1,13 +1,13 @@
1
+ import { isOutputTextDeltaEvent, isReasoningDeltaEvent, isFunctionCallArgumentsDeltaEvent, isOutputItemAddedEvent, isOutputItemDoneEvent, isResponseCompletedEvent, isResponseFailedEvent, isResponseIncompleteEvent, isFunctionCallArgumentsDoneEvent, isOutputMessage, isFunctionCallOutputItem, isReasoningOutputItem, isWebSearchCallOutputItem, isFileSearchCallOutputItem, isImageGenerationCallOutputItem, isOutputTextPart, isRefusalPart, isFileCitationAnnotation, isURLCitationAnnotation, isFilePathAnnotation, } from './stream-type-guards.js';
1
2
  /**
2
3
  * Extract text deltas from responses stream events
3
4
  */
4
5
  export async function* extractTextDeltas(stream) {
5
6
  const consumer = stream.createConsumer();
6
7
  for await (const event of consumer) {
7
- if ('type' in event && event.type === 'response.output_text.delta') {
8
- const deltaEvent = event;
9
- if (deltaEvent.delta) {
10
- yield deltaEvent.delta;
8
+ if (isOutputTextDeltaEvent(event)) {
9
+ if (event.delta) {
10
+ yield event.delta;
11
11
  }
12
12
  }
13
13
  }
@@ -18,10 +18,9 @@ export async function* extractTextDeltas(stream) {
18
18
  export async function* extractReasoningDeltas(stream) {
19
19
  const consumer = stream.createConsumer();
20
20
  for await (const event of consumer) {
21
- if ('type' in event && event.type === 'response.reasoning_text.delta') {
22
- const deltaEvent = event;
23
- if (deltaEvent.delta) {
24
- yield deltaEvent.delta;
21
+ if (isReasoningDeltaEvent(event)) {
22
+ if (event.delta) {
23
+ yield event.delta;
25
24
  }
26
25
  }
27
26
  }
@@ -32,22 +31,22 @@ export async function* extractReasoningDeltas(stream) {
32
31
  export async function* extractToolDeltas(stream) {
33
32
  const consumer = stream.createConsumer();
34
33
  for await (const event of consumer) {
35
- if ('type' in event && event.type === 'response.function_call_arguments.delta') {
36
- const deltaEvent = event;
37
- if (deltaEvent.delta) {
38
- yield deltaEvent.delta;
34
+ if (isFunctionCallArgumentsDeltaEvent(event)) {
35
+ if (event.delta) {
36
+ yield event.delta;
39
37
  }
40
38
  }
41
39
  }
42
40
  }
43
41
  /**
44
- * Build incremental message updates from responses stream events
45
- * Returns AssistantMessage (chat format) instead of ResponsesOutputMessage
42
+ * Core message stream builder - shared logic for both formats
43
+ * Accumulates text deltas and yields updates
46
44
  */
47
- export async function* buildMessageStream(stream) {
45
+ async function* buildMessageStreamCore(stream) {
48
46
  const consumer = stream.createConsumer();
49
- // Track the accumulated text
47
+ // Track the accumulated text and message info
50
48
  let currentText = '';
49
+ let currentId = '';
51
50
  let hasStarted = false;
52
51
  for await (const event of consumer) {
53
52
  if (!('type' in event)) {
@@ -55,36 +54,95 @@ export async function* buildMessageStream(stream) {
55
54
  }
56
55
  switch (event.type) {
57
56
  case 'response.output_item.added': {
58
- const itemEvent = event;
59
- if (itemEvent.item && 'type' in itemEvent.item && itemEvent.item.type === 'message') {
60
- hasStarted = true;
61
- currentText = '';
57
+ if (isOutputItemAddedEvent(event)) {
58
+ if (event.item && isOutputMessage(event.item)) {
59
+ hasStarted = true;
60
+ currentText = '';
61
+ currentId = event.item.id;
62
+ }
62
63
  }
63
64
  break;
64
65
  }
65
66
  case 'response.output_text.delta': {
66
- const deltaEvent = event;
67
- if (hasStarted && deltaEvent.delta) {
68
- currentText += deltaEvent.delta;
69
- // Yield updated message
70
- yield {
71
- role: 'assistant',
72
- content: currentText,
73
- };
67
+ if (isOutputTextDeltaEvent(event)) {
68
+ if (hasStarted && event.delta) {
69
+ currentText += event.delta;
70
+ yield {
71
+ type: 'delta',
72
+ text: currentText,
73
+ messageId: currentId,
74
+ };
75
+ }
74
76
  }
75
77
  break;
76
78
  }
77
79
  case 'response.output_item.done': {
78
- const itemDoneEvent = event;
79
- if (itemDoneEvent.item &&
80
- 'type' in itemDoneEvent.item &&
81
- itemDoneEvent.item.type === 'message') {
82
- // Yield final complete message
83
- const outputMessage = itemDoneEvent.item;
84
- yield convertToAssistantMessage(outputMessage);
80
+ if (isOutputItemDoneEvent(event)) {
81
+ if (event.item && isOutputMessage(event.item)) {
82
+ yield {
83
+ type: 'complete',
84
+ completeMessage: event.item,
85
+ };
86
+ }
85
87
  }
86
88
  break;
87
89
  }
90
+ case 'response.completed':
91
+ case 'response.failed':
92
+ case 'response.incomplete':
93
+ // Stream is complete, stop consuming
94
+ return;
95
+ default:
96
+ // Ignore other event types - this is intentionally not exhaustive
97
+ // as we only care about specific events for message building
98
+ break;
99
+ }
100
+ }
101
+ }
102
+ /**
103
+ * Build incremental message updates from responses stream events
104
+ * Returns ResponsesOutputMessage (assistant/responses format)
105
+ */
106
+ export async function* buildResponsesMessageStream(stream) {
107
+ for await (const update of buildMessageStreamCore(stream)) {
108
+ if (update.type === 'delta' && update.text !== undefined && update.messageId !== undefined) {
109
+ // Yield incremental update in ResponsesOutputMessage format
110
+ yield {
111
+ id: update.messageId,
112
+ type: 'message',
113
+ role: 'assistant',
114
+ status: 'in_progress',
115
+ content: [
116
+ {
117
+ type: 'output_text',
118
+ text: update.text,
119
+ annotations: [],
120
+ },
121
+ ],
122
+ };
123
+ }
124
+ else if (update.type === 'complete' && update.completeMessage) {
125
+ // Yield final complete message
126
+ yield update.completeMessage;
127
+ }
128
+ }
129
+ }
130
+ /**
131
+ * Build incremental message updates from responses stream events
132
+ * Returns AssistantMessage (chat format) instead of ResponsesOutputMessage
133
+ */
134
+ export async function* buildMessageStream(stream) {
135
+ for await (const update of buildMessageStreamCore(stream)) {
136
+ if (update.type === 'delta' && update.text !== undefined) {
137
+ // Yield incremental update in chat format
138
+ yield {
139
+ role: 'assistant',
140
+ content: update.text,
141
+ };
142
+ }
143
+ else if (update.type === 'complete' && update.completeMessage) {
144
+ // Yield final complete message converted to chat format
145
+ yield convertToAssistantMessage(update.completeMessage);
88
146
  }
89
147
  }
90
148
  }
@@ -97,19 +155,16 @@ export async function consumeStreamForCompletion(stream) {
97
155
  if (!('type' in event)) {
98
156
  continue;
99
157
  }
100
- if (event.type === 'response.completed') {
101
- const completedEvent = event;
102
- return completedEvent.response;
158
+ if (isResponseCompletedEvent(event)) {
159
+ return event.response;
103
160
  }
104
- if (event.type === 'response.failed') {
105
- const failedEvent = event;
161
+ if (isResponseFailedEvent(event)) {
106
162
  // The failed event contains the full response with error information
107
- throw new Error(`Response failed: ${JSON.stringify(failedEvent.response.error)}`);
163
+ throw new Error(`Response failed: ${JSON.stringify(event.response.error)}`);
108
164
  }
109
- if (event.type === 'response.incomplete') {
110
- const incompleteEvent = event;
165
+ if (isResponseIncompleteEvent(event)) {
111
166
  // Return the incomplete response
112
- return incompleteEvent.response;
167
+ return event.response;
113
168
  }
114
169
  }
115
170
  throw new Error('Stream ended without completion event');
@@ -129,7 +184,7 @@ function convertToAssistantMessage(outputMessage) {
129
184
  };
130
185
  }
131
186
  /**
132
- * Extract the first message from a completed response
187
+ * Extract the first message from a completed response (chat format)
133
188
  */
134
189
  export function extractMessageFromResponse(response) {
135
190
  const messageItem = response.output.find((item) => 'type' in item && item.type === 'message');
@@ -138,6 +193,16 @@ export function extractMessageFromResponse(response) {
138
193
  }
139
194
  return convertToAssistantMessage(messageItem);
140
195
  }
196
+ /**
197
+ * Extract the first message from a completed response (responses format)
198
+ */
199
+ export function extractResponsesMessageFromResponse(response) {
200
+ const messageItem = response.output.find((item) => 'type' in item && item.type === 'message');
201
+ if (!messageItem) {
202
+ throw new Error('No message found in response output');
203
+ }
204
+ return messageItem;
205
+ }
141
206
  /**
142
207
  * Extract text from a response, either from outputText or by concatenating message content
143
208
  */
@@ -146,6 +211,12 @@ export function extractTextFromResponse(response) {
146
211
  if (response.outputText) {
147
212
  return response.outputText;
148
213
  }
214
+ // Check if there's a message in the output
215
+ const hasMessage = response.output.some((item) => 'type' in item && item.type === 'message');
216
+ if (!hasMessage) {
217
+ // No message in response (e.g., only function calls)
218
+ return '';
219
+ }
149
220
  // Otherwise, extract from the first message (convert to AssistantMessage which has string content)
150
221
  const message = extractMessageFromResponse(response);
151
222
  // AssistantMessage.content is string | Array | null | undefined
@@ -161,22 +232,22 @@ export function extractTextFromResponse(response) {
161
232
  export function extractToolCallsFromResponse(response) {
162
233
  const toolCalls = [];
163
234
  for (const item of response.output) {
164
- if ('type' in item && item.type === 'function_call') {
165
- const functionCallItem = item;
235
+ if (isFunctionCallOutputItem(item)) {
166
236
  try {
167
- const parsedArguments = JSON.parse(functionCallItem.arguments);
237
+ const parsedArguments = JSON.parse(item.arguments);
168
238
  toolCalls.push({
169
- id: functionCallItem.callId,
170
- name: functionCallItem.name,
239
+ id: item.callId,
240
+ name: item.name,
171
241
  arguments: parsedArguments,
172
242
  });
173
243
  }
174
- catch (_error) {
244
+ catch (error) {
245
+ console.warn(`Failed to parse tool call arguments for ${item.name}:`, error instanceof Error ? error.message : String(error), `\nArguments: ${item.arguments.substring(0, 100)}${item.arguments.length > 100 ? '...' : ''}`);
175
246
  // Include the tool call with unparsed arguments
176
247
  toolCalls.push({
177
- id: functionCallItem.callId,
178
- name: functionCallItem.name,
179
- arguments: functionCallItem.arguments, // Keep as string if parsing fails
248
+ id: item.callId,
249
+ name: item.name,
250
+ arguments: item.arguments, // Keep as string if parsing fails
180
251
  });
181
252
  }
182
253
  }
@@ -197,75 +268,72 @@ export async function* buildToolCallStream(stream) {
197
268
  }
198
269
  switch (event.type) {
199
270
  case 'response.output_item.added': {
200
- const itemEvent = event;
201
- if (itemEvent.item && 'type' in itemEvent.item && itemEvent.item.type === 'function_call') {
202
- const functionCallItem = itemEvent.item;
203
- toolCallsInProgress.set(functionCallItem.callId, {
204
- id: functionCallItem.callId,
205
- name: functionCallItem.name,
271
+ if (isOutputItemAddedEvent(event) && event.item && isFunctionCallOutputItem(event.item)) {
272
+ toolCallsInProgress.set(event.item.callId, {
273
+ id: event.item.callId,
274
+ name: event.item.name,
206
275
  argumentsAccumulated: '',
207
276
  });
208
277
  }
209
278
  break;
210
279
  }
211
280
  case 'response.function_call_arguments.delta': {
212
- const deltaEvent = event;
213
- const toolCall = toolCallsInProgress.get(deltaEvent.itemId);
214
- if (toolCall && deltaEvent.delta) {
215
- toolCall.argumentsAccumulated += deltaEvent.delta;
281
+ if (isFunctionCallArgumentsDeltaEvent(event)) {
282
+ const toolCall = toolCallsInProgress.get(event.itemId);
283
+ if (toolCall && event.delta) {
284
+ toolCall.argumentsAccumulated += event.delta;
285
+ }
216
286
  }
217
287
  break;
218
288
  }
219
289
  case 'response.function_call_arguments.done': {
220
- const doneEvent = event;
221
- const toolCall = toolCallsInProgress.get(doneEvent.itemId);
222
- if (toolCall) {
223
- // Parse complete arguments
224
- try {
225
- const parsedArguments = JSON.parse(doneEvent.arguments);
226
- yield {
227
- id: toolCall.id,
228
- name: doneEvent.name,
229
- arguments: parsedArguments,
230
- };
231
- }
232
- catch (_error) {
233
- // Yield with unparsed arguments if parsing fails
234
- yield {
235
- id: toolCall.id,
236
- name: doneEvent.name,
237
- arguments: doneEvent.arguments,
238
- };
290
+ if (isFunctionCallArgumentsDoneEvent(event)) {
291
+ const toolCall = toolCallsInProgress.get(event.itemId);
292
+ if (toolCall) {
293
+ // Parse complete arguments
294
+ try {
295
+ const parsedArguments = JSON.parse(event.arguments);
296
+ yield {
297
+ id: toolCall.id,
298
+ name: event.name,
299
+ arguments: parsedArguments,
300
+ };
301
+ }
302
+ catch (error) {
303
+ console.warn(`Failed to parse tool call arguments for ${event.name}:`, error instanceof Error ? error.message : String(error), `\nArguments: ${event.arguments.substring(0, 100)}${event.arguments.length > 100 ? '...' : ''}`);
304
+ // Yield with unparsed arguments if parsing fails
305
+ yield {
306
+ id: toolCall.id,
307
+ name: event.name,
308
+ arguments: event.arguments,
309
+ };
310
+ }
311
+ // Clean up
312
+ toolCallsInProgress.delete(event.itemId);
239
313
  }
240
- // Clean up
241
- toolCallsInProgress.delete(doneEvent.itemId);
242
314
  }
243
315
  break;
244
316
  }
245
317
  case 'response.output_item.done': {
246
- const itemDoneEvent = event;
247
- if (itemDoneEvent.item &&
248
- 'type' in itemDoneEvent.item &&
249
- itemDoneEvent.item.type === 'function_call') {
250
- const functionCallItem = itemDoneEvent.item;
318
+ if (isOutputItemDoneEvent(event) && event.item && isFunctionCallOutputItem(event.item)) {
251
319
  // Yield final tool call if we haven't already
252
- if (toolCallsInProgress.has(functionCallItem.callId)) {
320
+ if (toolCallsInProgress.has(event.item.callId)) {
253
321
  try {
254
- const parsedArguments = JSON.parse(functionCallItem.arguments);
322
+ const parsedArguments = JSON.parse(event.item.arguments);
255
323
  yield {
256
- id: functionCallItem.callId,
257
- name: functionCallItem.name,
324
+ id: event.item.callId,
325
+ name: event.item.name,
258
326
  arguments: parsedArguments,
259
327
  };
260
328
  }
261
329
  catch (_error) {
262
330
  yield {
263
- id: functionCallItem.callId,
264
- name: functionCallItem.name,
265
- arguments: functionCallItem.arguments,
331
+ id: event.item.callId,
332
+ name: event.item.name,
333
+ arguments: event.item.arguments,
266
334
  };
267
335
  }
268
- toolCallsInProgress.delete(functionCallItem.callId);
336
+ toolCallsInProgress.delete(event.item.callId);
269
337
  }
270
338
  }
271
339
  break;
@@ -279,4 +347,305 @@ export async function* buildToolCallStream(stream) {
279
347
  export function responseHasToolCalls(response) {
280
348
  return response.output.some((item) => 'type' in item && item.type === 'function_call');
281
349
  }
350
+ /**
351
+ * Convert OpenRouter annotations to Claude citations
352
+ */
353
+ function mapAnnotationsToCitations(annotations) {
354
+ if (!annotations || annotations.length === 0) {
355
+ return undefined;
356
+ }
357
+ const citations = [];
358
+ for (const annotation of annotations) {
359
+ if (!('type' in annotation)) {
360
+ continue;
361
+ }
362
+ switch (annotation.type) {
363
+ case 'file_citation': {
364
+ if (isFileCitationAnnotation(annotation)) {
365
+ citations.push({
366
+ type: 'char_location',
367
+ cited_text: '',
368
+ document_index: annotation.index,
369
+ document_title: annotation.filename,
370
+ file_id: annotation.fileId,
371
+ start_char_index: 0,
372
+ end_char_index: 0,
373
+ });
374
+ }
375
+ break;
376
+ }
377
+ case 'url_citation': {
378
+ if (isURLCitationAnnotation(annotation)) {
379
+ citations.push({
380
+ type: 'web_search_result_location',
381
+ cited_text: '',
382
+ title: annotation.title,
383
+ url: annotation.url,
384
+ encrypted_index: '',
385
+ });
386
+ }
387
+ break;
388
+ }
389
+ case 'file_path': {
390
+ if (isFilePathAnnotation(annotation)) {
391
+ citations.push({
392
+ type: 'char_location',
393
+ cited_text: '',
394
+ document_index: annotation.index,
395
+ document_title: '',
396
+ file_id: annotation.fileId,
397
+ start_char_index: 0,
398
+ end_char_index: 0,
399
+ });
400
+ }
401
+ break;
402
+ }
403
+ default: {
404
+ // Exhaustiveness check - TypeScript will error if we don't handle all annotation types
405
+ const exhaustiveCheck = annotation;
406
+ // Cast to unknown for runtime debugging if type system bypassed
407
+ // This should never execute - throw with JSON of the unhandled value
408
+ throw new Error(`Unhandled annotation type. This indicates a new annotation type was added. ` +
409
+ `Annotation: ${JSON.stringify(exhaustiveCheck)}`);
410
+ }
411
+ }
412
+ }
413
+ return citations.length > 0 ? citations : undefined;
414
+ }
415
+ /**
416
+ * Map OpenResponses status to Claude stop reason
417
+ */
418
+ function mapStopReason(response) {
419
+ // Check if any tool calls exist in the response
420
+ const hasToolCalls = response.output.some((item) => 'type' in item && item.type === 'function_call');
421
+ if (hasToolCalls) {
422
+ return 'tool_use';
423
+ }
424
+ // Check the response status
425
+ if (response.status === 'completed') {
426
+ return 'end_turn';
427
+ }
428
+ if (response.status === 'incomplete') {
429
+ // Check incomplete reason if available
430
+ const incompleteReason = response.incompleteDetails?.reason;
431
+ if (incompleteReason === 'max_output_tokens') {
432
+ return 'max_tokens';
433
+ }
434
+ return 'end_turn';
435
+ }
436
+ return 'end_turn';
437
+ }
438
+ /**
439
+ * Convert OpenResponsesNonStreamingResponse to ClaudeMessage format
440
+ * Compatible with the Anthropic SDK BetaMessage type
441
+ */
442
+ export function convertToClaudeMessage(response) {
443
+ const content = [];
444
+ const unsupportedContent = [];
445
+ for (const item of response.output) {
446
+ if (!('type' in item)) {
447
+ // Handle items without type field
448
+ // Convert unknown item to a record format for storage
449
+ const itemData = typeof item === 'object' && item !== null
450
+ ? item
451
+ : { value: item };
452
+ unsupportedContent.push({
453
+ original_type: 'unknown',
454
+ data: itemData,
455
+ reason: 'Output item missing type field',
456
+ });
457
+ continue;
458
+ }
459
+ switch (item.type) {
460
+ case 'message': {
461
+ if (isOutputMessage(item)) {
462
+ for (const part of item.content) {
463
+ if (!('type' in part)) {
464
+ // Convert unknown part to a record format for storage
465
+ const partData = typeof part === 'object' && part !== null
466
+ ? part
467
+ : { value: part };
468
+ unsupportedContent.push({
469
+ original_type: 'unknown_message_part',
470
+ data: partData,
471
+ reason: 'Message content part missing type field',
472
+ });
473
+ continue;
474
+ }
475
+ if (isOutputTextPart(part)) {
476
+ const citations = mapAnnotationsToCitations(part.annotations);
477
+ content.push({
478
+ type: 'text',
479
+ text: part.text,
480
+ ...(citations && {
481
+ citations,
482
+ }),
483
+ });
484
+ }
485
+ else if (isRefusalPart(part)) {
486
+ unsupportedContent.push({
487
+ original_type: 'refusal',
488
+ data: {
489
+ refusal: part.refusal,
490
+ },
491
+ reason: 'Claude does not have a native refusal content type',
492
+ });
493
+ }
494
+ else {
495
+ // Exhaustiveness check - TypeScript will error if we don't handle all part types
496
+ const exhaustiveCheck = part;
497
+ // This should never execute - new content type was added
498
+ throw new Error(`Unhandled message content type. This indicates a new content type was added. ` +
499
+ `Part: ${JSON.stringify(exhaustiveCheck)}`);
500
+ }
501
+ }
502
+ }
503
+ break;
504
+ }
505
+ case 'function_call': {
506
+ if (isFunctionCallOutputItem(item)) {
507
+ let parsedInput;
508
+ try {
509
+ parsedInput = JSON.parse(item.arguments);
510
+ }
511
+ catch (error) {
512
+ console.warn(`Failed to parse tool call arguments for ${item.name}:`, error instanceof Error ? error.message : String(error), `\nArguments: ${item.arguments.substring(0, 100)}${item.arguments.length > 100 ? '...' : ''}`);
513
+ // Preserve raw arguments if JSON parsing fails
514
+ parsedInput = {
515
+ _raw_arguments: item.arguments,
516
+ };
517
+ }
518
+ content.push({
519
+ type: 'tool_use',
520
+ id: item.callId,
521
+ name: item.name,
522
+ input: parsedInput,
523
+ });
524
+ }
525
+ break;
526
+ }
527
+ case 'reasoning': {
528
+ if (isReasoningOutputItem(item)) {
529
+ if (item.summary && item.summary.length > 0) {
530
+ for (const summaryItem of item.summary) {
531
+ if (summaryItem.type === 'summary_text' && summaryItem.text) {
532
+ content.push({
533
+ type: 'thinking',
534
+ thinking: summaryItem.text,
535
+ signature: '',
536
+ });
537
+ }
538
+ }
539
+ }
540
+ if (item.encryptedContent) {
541
+ unsupportedContent.push({
542
+ original_type: 'reasoning_encrypted',
543
+ data: {
544
+ id: item.id,
545
+ encrypted_content: item.encryptedContent,
546
+ },
547
+ reason: 'Encrypted reasoning content preserved for round-trip',
548
+ });
549
+ }
550
+ }
551
+ break;
552
+ }
553
+ case 'web_search_call': {
554
+ if (isWebSearchCallOutputItem(item)) {
555
+ content.push({
556
+ type: 'server_tool_use',
557
+ id: item.id,
558
+ name: 'web_search',
559
+ input: {
560
+ status: item.status,
561
+ },
562
+ });
563
+ }
564
+ break;
565
+ }
566
+ case 'file_search_call': {
567
+ if (isFileSearchCallOutputItem(item)) {
568
+ content.push({
569
+ type: 'tool_use',
570
+ id: item.id,
571
+ name: 'file_search',
572
+ input: {
573
+ queries: item.queries,
574
+ status: item.status,
575
+ },
576
+ });
577
+ }
578
+ break;
579
+ }
580
+ case 'image_generation_call': {
581
+ if (isImageGenerationCallOutputItem(item)) {
582
+ unsupportedContent.push({
583
+ original_type: 'image_generation_call',
584
+ data: {
585
+ id: item.id,
586
+ result: item.result,
587
+ status: item.status,
588
+ },
589
+ reason: 'Claude does not support image outputs in assistant messages',
590
+ });
591
+ }
592
+ break;
593
+ }
594
+ default: {
595
+ // Exhaustiveness check - if a new output type is added, TypeScript will error here
596
+ const exhaustiveCheck = item;
597
+ // This line should never execute - it means a new type was added to the union
598
+ // Throw an error instead of silently continuing to ensure we catch new types
599
+ throw new Error(`Unhandled output item type. This indicates a new output type was added to the API. ` +
600
+ `Item: ${JSON.stringify(exhaustiveCheck)}`);
601
+ }
602
+ }
603
+ }
604
+ return {
605
+ id: response.id,
606
+ type: 'message',
607
+ role: 'assistant',
608
+ model: response.model ?? 'unknown',
609
+ content,
610
+ stop_reason: mapStopReason(response),
611
+ stop_sequence: null,
612
+ usage: {
613
+ input_tokens: response.usage?.inputTokens ?? 0,
614
+ output_tokens: response.usage?.outputTokens ?? 0,
615
+ cache_creation_input_tokens: response.usage?.inputTokensDetails?.cachedTokens ?? 0,
616
+ cache_read_input_tokens: 0,
617
+ },
618
+ ...(unsupportedContent.length > 0 && {
619
+ unsupported_content: unsupportedContent,
620
+ }),
621
+ };
622
+ }
623
+ /**
624
+ * Extract unsupported content by original type
625
+ */
626
+ export function extractUnsupportedContent(message, originalType) {
627
+ if (!message.unsupported_content) {
628
+ return [];
629
+ }
630
+ return message.unsupported_content.filter((item) => item.original_type === originalType);
631
+ }
632
+ /**
633
+ * Check if message has any unsupported content
634
+ */
635
+ export function hasUnsupportedContent(message) {
636
+ return !!(message.unsupported_content && message.unsupported_content.length > 0);
637
+ }
638
+ /**
639
+ * Get summary of unsupported content types
640
+ */
641
+ export function getUnsupportedContentSummary(message) {
642
+ if (!message.unsupported_content) {
643
+ return {};
644
+ }
645
+ const summary = {};
646
+ for (const item of message.unsupported_content) {
647
+ summary[item.original_type] = (summary[item.original_type] || 0) + 1;
648
+ }
649
+ return summary;
650
+ }
282
651
  //# sourceMappingURL=stream-transformers.js.map