@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
@@ -0,0 +1,479 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { fromClaudeMessages, toClaudeMessage } from "./anthropic-compat.js";
3
+ /**
4
+ * Creates a properly typed mock OpenResponsesNonStreamingResponse for testing.
5
+ * This factory provides all required fields with sensible defaults.
6
+ */
7
+ function createMockResponse(overrides) {
8
+ return {
9
+ id: "resp_test",
10
+ object: "response",
11
+ createdAt: Date.now(),
12
+ model: "openai/gpt-4",
13
+ status: "completed",
14
+ error: null,
15
+ incompleteDetails: null,
16
+ temperature: null,
17
+ topP: null,
18
+ metadata: null,
19
+ tools: [],
20
+ toolChoice: "auto",
21
+ parallelToolCalls: false,
22
+ ...overrides,
23
+ };
24
+ }
25
+ describe("fromClaudeMessages", () => {
26
+ describe("basic message conversion", () => {
27
+ it("converts user message with string content", () => {
28
+ const claudeMessages = [
29
+ { role: "user", content: "Hello, how are you?" },
30
+ ];
31
+ const result = fromClaudeMessages(claudeMessages);
32
+ expect(result).toEqual([
33
+ { role: "user", content: "Hello, how are you?" },
34
+ ]);
35
+ });
36
+ it("converts assistant message with string content", () => {
37
+ const claudeMessages = [
38
+ { role: "assistant", content: "I am doing well, thank you!" },
39
+ ];
40
+ const result = fromClaudeMessages(claudeMessages);
41
+ expect(result).toEqual([
42
+ { role: "assistant", content: "I am doing well, thank you!" },
43
+ ]);
44
+ });
45
+ it("converts multiple messages in conversation", () => {
46
+ const claudeMessages = [
47
+ { role: "user", content: "Hi" },
48
+ { role: "assistant", content: "Hello!" },
49
+ { role: "user", content: "How are you?" },
50
+ ];
51
+ const result = fromClaudeMessages(claudeMessages);
52
+ expect(result).toEqual([
53
+ { role: "user", content: "Hi" },
54
+ { role: "assistant", content: "Hello!" },
55
+ { role: "user", content: "How are you?" },
56
+ ]);
57
+ });
58
+ });
59
+ describe("text block content conversion", () => {
60
+ it("converts user message with text block array", () => {
61
+ const claudeMessages = [
62
+ {
63
+ role: "user",
64
+ content: [{ type: "text", text: "Hello from text block" }],
65
+ },
66
+ ];
67
+ const result = fromClaudeMessages(claudeMessages);
68
+ expect(result).toEqual([
69
+ { role: "user", content: "Hello from text block" },
70
+ ]);
71
+ });
72
+ it("combines multiple text blocks into single content string", () => {
73
+ const claudeMessages = [
74
+ {
75
+ role: "user",
76
+ content: [
77
+ { type: "text", text: "First part. " },
78
+ { type: "text", text: "Second part." },
79
+ ],
80
+ },
81
+ ];
82
+ const result = fromClaudeMessages(claudeMessages);
83
+ expect(result).toEqual([
84
+ { role: "user", content: "First part. Second part." },
85
+ ]);
86
+ });
87
+ });
88
+ describe("tool_result block conversion", () => {
89
+ it("converts tool_result with string content to function_call_output", () => {
90
+ const claudeMessages = [
91
+ {
92
+ role: "user",
93
+ content: [
94
+ {
95
+ type: "tool_result",
96
+ tool_use_id: "tool_123",
97
+ content: "Tool execution result",
98
+ },
99
+ ],
100
+ },
101
+ ];
102
+ const result = fromClaudeMessages(claudeMessages);
103
+ expect(result).toEqual([
104
+ {
105
+ type: "function_call_output",
106
+ callId: "tool_123",
107
+ output: "Tool execution result",
108
+ },
109
+ ]);
110
+ });
111
+ it("converts tool_result with text block array to function_call_output", () => {
112
+ const claudeMessages = [
113
+ {
114
+ role: "user",
115
+ content: [
116
+ {
117
+ type: "tool_result",
118
+ tool_use_id: "tool_456",
119
+ content: [
120
+ { type: "text", text: "Result part 1. " },
121
+ { type: "text", text: "Result part 2." },
122
+ ],
123
+ },
124
+ ],
125
+ },
126
+ ];
127
+ const result = fromClaudeMessages(claudeMessages);
128
+ expect(result).toEqual([
129
+ {
130
+ type: "function_call_output",
131
+ callId: "tool_456",
132
+ output: "Result part 1. Result part 2.",
133
+ },
134
+ ]);
135
+ });
136
+ it("handles mixed text and tool_result blocks", () => {
137
+ const claudeMessages = [
138
+ {
139
+ role: "user",
140
+ content: [
141
+ { type: "text", text: "Here is some context. " },
142
+ {
143
+ type: "tool_result",
144
+ tool_use_id: "tool_789",
145
+ content: "Tool output",
146
+ },
147
+ { type: "text", text: "And some more text." },
148
+ ],
149
+ },
150
+ ];
151
+ const result = fromClaudeMessages(claudeMessages);
152
+ // Should produce both the text message and the function_call_output
153
+ expect(result).toEqual([
154
+ {
155
+ type: "function_call_output",
156
+ callId: "tool_789",
157
+ output: "Tool output",
158
+ },
159
+ { role: "user", content: "Here is some context. And some more text." },
160
+ ]);
161
+ });
162
+ });
163
+ describe("tool_use blocks (should be skipped)", () => {
164
+ it("skips tool_use blocks as they are output from assistant", () => {
165
+ const claudeMessages = [
166
+ {
167
+ role: "assistant",
168
+ content: [
169
+ { type: "text", text: "Let me help you with that." },
170
+ {
171
+ type: "tool_use",
172
+ id: "tool_abc",
173
+ name: "get_weather",
174
+ input: { location: "SF" },
175
+ },
176
+ ],
177
+ },
178
+ ];
179
+ const result = fromClaudeMessages(claudeMessages);
180
+ // Only the text should be captured, tool_use is from previous response
181
+ expect(result).toEqual([
182
+ { role: "assistant", content: "Let me help you with that." },
183
+ ]);
184
+ });
185
+ });
186
+ describe("image blocks (should be skipped)", () => {
187
+ it("skips image blocks", () => {
188
+ const claudeMessages = [
189
+ {
190
+ role: "user",
191
+ content: [
192
+ { type: "text", text: "Look at this image:" },
193
+ {
194
+ type: "image",
195
+ source: {
196
+ type: "base64",
197
+ media_type: "image/png",
198
+ data: "base64data...",
199
+ },
200
+ },
201
+ ],
202
+ },
203
+ ];
204
+ const result = fromClaudeMessages(claudeMessages);
205
+ // Only the text should be captured
206
+ expect(result).toEqual([
207
+ { role: "user", content: "Look at this image:" },
208
+ ]);
209
+ });
210
+ });
211
+ describe("empty and edge cases", () => {
212
+ it("handles empty messages array", () => {
213
+ const result = fromClaudeMessages([]);
214
+ expect(result).toEqual([]);
215
+ });
216
+ it("handles message with empty string content", () => {
217
+ const claudeMessages = [
218
+ { role: "user", content: "" },
219
+ ];
220
+ const result = fromClaudeMessages(claudeMessages);
221
+ expect(result).toEqual([{ role: "user", content: "" }]);
222
+ });
223
+ it("handles message with empty content array", () => {
224
+ const claudeMessages = [
225
+ { role: "user", content: [] },
226
+ ];
227
+ const result = fromClaudeMessages(claudeMessages);
228
+ // Should produce empty array since no text and no tool_results
229
+ expect(result).toEqual([]);
230
+ });
231
+ });
232
+ });
233
+ describe("toClaudeMessage", () => {
234
+ describe("basic message conversion", () => {
235
+ it("converts response with text output to ClaudeMessage", () => {
236
+ const response = createMockResponse({
237
+ id: "resp_123",
238
+ output: [
239
+ {
240
+ id: "msg_1",
241
+ type: "message",
242
+ role: "assistant",
243
+ status: "completed",
244
+ content: [
245
+ {
246
+ type: "output_text",
247
+ text: "Hello! How can I help you?",
248
+ annotations: [],
249
+ },
250
+ ],
251
+ },
252
+ ],
253
+ usage: {
254
+ inputTokens: 10,
255
+ outputTokens: 20,
256
+ totalTokens: 30,
257
+ inputTokensDetails: { cachedTokens: 0 },
258
+ outputTokensDetails: { reasoningTokens: 0 },
259
+ },
260
+ });
261
+ const result = toClaudeMessage(response);
262
+ expect(result).toEqual({
263
+ id: "resp_123",
264
+ type: "message",
265
+ role: "assistant",
266
+ model: "openai/gpt-4",
267
+ content: [
268
+ {
269
+ type: "text",
270
+ text: "Hello! How can I help you?",
271
+ },
272
+ ],
273
+ stop_reason: "end_turn",
274
+ stop_sequence: null,
275
+ usage: {
276
+ input_tokens: 10,
277
+ output_tokens: 20,
278
+ cache_creation_input_tokens: 0,
279
+ cache_read_input_tokens: 0,
280
+ },
281
+ });
282
+ });
283
+ });
284
+ describe("function call conversion", () => {
285
+ it("converts function_call output to tool_use block", () => {
286
+ const response = createMockResponse({
287
+ id: "resp_456",
288
+ output: [
289
+ {
290
+ type: "function_call",
291
+ callId: "call_abc",
292
+ name: "get_weather",
293
+ arguments: '{"location":"San Francisco"}',
294
+ id: "fc_1",
295
+ status: "completed",
296
+ },
297
+ ],
298
+ usage: {
299
+ inputTokens: 15,
300
+ outputTokens: 25,
301
+ totalTokens: 40,
302
+ inputTokensDetails: { cachedTokens: 0 },
303
+ outputTokensDetails: { reasoningTokens: 0 },
304
+ },
305
+ });
306
+ const result = toClaudeMessage(response);
307
+ expect(result.content).toEqual([
308
+ {
309
+ type: "tool_use",
310
+ id: "call_abc",
311
+ name: "get_weather",
312
+ input: { location: "San Francisco" },
313
+ },
314
+ ]);
315
+ expect(result.stop_reason).toBe("tool_use");
316
+ });
317
+ });
318
+ describe("reasoning conversion", () => {
319
+ it("converts reasoning output to thinking block", () => {
320
+ const response = createMockResponse({
321
+ id: "resp_789",
322
+ model: "openai/o1",
323
+ output: [
324
+ {
325
+ type: "reasoning",
326
+ id: "reason_1",
327
+ summary: [
328
+ {
329
+ type: "summary_text",
330
+ text: "I need to think about this carefully...",
331
+ },
332
+ ],
333
+ },
334
+ {
335
+ id: "msg_2",
336
+ type: "message",
337
+ role: "assistant",
338
+ status: "completed",
339
+ content: [
340
+ {
341
+ type: "output_text",
342
+ text: "Here is my answer.",
343
+ annotations: [],
344
+ },
345
+ ],
346
+ },
347
+ ],
348
+ usage: {
349
+ inputTokens: 20,
350
+ outputTokens: 100,
351
+ totalTokens: 120,
352
+ inputTokensDetails: { cachedTokens: 0 },
353
+ outputTokensDetails: { reasoningTokens: 0 },
354
+ },
355
+ });
356
+ const result = toClaudeMessage(response);
357
+ expect(result.content).toEqual([
358
+ {
359
+ type: "thinking",
360
+ thinking: "I need to think about this carefully...",
361
+ signature: "",
362
+ },
363
+ {
364
+ type: "text",
365
+ text: "Here is my answer.",
366
+ },
367
+ ]);
368
+ });
369
+ });
370
+ describe("stop reason mapping", () => {
371
+ it("maps completed status to end_turn", () => {
372
+ const response = createMockResponse({
373
+ id: "resp_1",
374
+ output: [
375
+ {
376
+ id: "msg_1",
377
+ type: "message",
378
+ role: "assistant",
379
+ status: "completed",
380
+ content: [{ type: "output_text", text: "Done", annotations: [] }],
381
+ },
382
+ ],
383
+ usage: {
384
+ inputTokens: 5,
385
+ outputTokens: 5,
386
+ totalTokens: 10,
387
+ inputTokensDetails: { cachedTokens: 0 },
388
+ outputTokensDetails: { reasoningTokens: 0 },
389
+ },
390
+ });
391
+ const result = toClaudeMessage(response);
392
+ expect(result.stop_reason).toBe("end_turn");
393
+ });
394
+ it("maps incomplete with max_output_tokens to max_tokens", () => {
395
+ const response = createMockResponse({
396
+ id: "resp_2",
397
+ status: "incomplete",
398
+ incompleteDetails: { reason: "max_output_tokens" },
399
+ output: [
400
+ {
401
+ id: "msg_1",
402
+ type: "message",
403
+ role: "assistant",
404
+ status: "incomplete",
405
+ content: [
406
+ { type: "output_text", text: "Partial...", annotations: [] },
407
+ ],
408
+ },
409
+ ],
410
+ usage: {
411
+ inputTokens: 5,
412
+ outputTokens: 100,
413
+ totalTokens: 105,
414
+ inputTokensDetails: { cachedTokens: 0 },
415
+ outputTokensDetails: { reasoningTokens: 0 },
416
+ },
417
+ });
418
+ const result = toClaudeMessage(response);
419
+ expect(result.stop_reason).toBe("max_tokens");
420
+ });
421
+ it("maps response with function calls to tool_use", () => {
422
+ const response = createMockResponse({
423
+ id: "resp_3",
424
+ output: [
425
+ {
426
+ type: "function_call",
427
+ callId: "call_1",
428
+ name: "test_tool",
429
+ arguments: "{}",
430
+ id: "fc_1",
431
+ status: "completed",
432
+ },
433
+ ],
434
+ usage: {
435
+ inputTokens: 5,
436
+ outputTokens: 10,
437
+ totalTokens: 15,
438
+ inputTokensDetails: { cachedTokens: 0 },
439
+ outputTokensDetails: { reasoningTokens: 0 },
440
+ },
441
+ });
442
+ const result = toClaudeMessage(response);
443
+ expect(result.stop_reason).toBe("tool_use");
444
+ });
445
+ });
446
+ describe("usage mapping", () => {
447
+ it("maps usage with cached tokens", () => {
448
+ const response = createMockResponse({
449
+ id: "resp_1",
450
+ output: [
451
+ {
452
+ id: "msg_1",
453
+ type: "message",
454
+ role: "assistant",
455
+ status: "completed",
456
+ content: [{ type: "output_text", text: "OK", annotations: [] }],
457
+ },
458
+ ],
459
+ usage: {
460
+ inputTokens: 100,
461
+ outputTokens: 50,
462
+ totalTokens: 150,
463
+ inputTokensDetails: {
464
+ cachedTokens: 80,
465
+ },
466
+ outputTokensDetails: { reasoningTokens: 0 },
467
+ },
468
+ });
469
+ const result = toClaudeMessage(response);
470
+ expect(result.usage).toEqual({
471
+ input_tokens: 100,
472
+ output_tokens: 50,
473
+ cache_creation_input_tokens: 80,
474
+ cache_read_input_tokens: 0,
475
+ });
476
+ });
477
+ });
478
+ });
479
+ //# sourceMappingURL=anthropic-compat.test.js.map
@@ -0,0 +1,53 @@
1
+ import type * as models from '../models/index.js';
2
+ import type { StopWhen, Tool, TurnContext } from './tool-types.js';
3
+ /**
4
+ * A field can be either a value of type T or a function that computes T
5
+ */
6
+ export type FieldOrAsyncFunction<T> = T | ((context: TurnContext) => T | Promise<T>);
7
+ /**
8
+ * Input type for callModel function
9
+ * Each field can independently be a static value or a function that computes the value
10
+ * Generic over TTools to enable proper type inference for stopWhen conditions
11
+ */
12
+ export type CallModelInput<TTools extends readonly Tool[] = readonly Tool[]> = {
13
+ [K in keyof Omit<models.OpenResponsesRequest, 'stream' | 'tools'>]?: FieldOrAsyncFunction<models.OpenResponsesRequest[K]>;
14
+ } & {
15
+ tools?: TTools;
16
+ stopWhen?: StopWhen<TTools>;
17
+ };
18
+ /**
19
+ * Resolved CallModelInput (all functions evaluated to values)
20
+ * This is the type after all async functions have been resolved to their values
21
+ */
22
+ export type ResolvedCallModelInput = Omit<models.OpenResponsesRequest, 'stream' | 'tools'> & {
23
+ tools?: never;
24
+ };
25
+ /**
26
+ * Resolve all async functions in CallModelInput to their values
27
+ *
28
+ * @param input - Input with possible functions
29
+ * @param context - Turn context for function execution
30
+ * @returns Resolved input with all values (no functions)
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const resolved = await resolveAsyncFunctions(
35
+ * {
36
+ * model: 'gpt-4',
37
+ * temperature: (ctx) => ctx.numberOfTurns * 0.1,
38
+ * input: 'Hello',
39
+ * },
40
+ * { numberOfTurns: 2, messageHistory: [] }
41
+ * );
42
+ * // resolved.temperature === 0.2
43
+ * ```
44
+ */
45
+ export declare function resolveAsyncFunctions(input: CallModelInput, context: TurnContext): Promise<ResolvedCallModelInput>;
46
+ /**
47
+ * Check if input has any async functions that need resolution
48
+ *
49
+ * @param input - Input to check
50
+ * @returns True if any field is a function
51
+ */
52
+ export declare function hasAsyncFunctions(input: unknown): boolean;
53
+ //# sourceMappingURL=async-params.d.ts.map
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Type guard to check if a value is a parameter function
3
+ * Parameter functions take TurnContext and return a value or promise
4
+ */
5
+ function isParameterFunction(value) {
6
+ return typeof value === 'function';
7
+ }
8
+ /**
9
+ * Build a resolved request object from entries
10
+ * This validates the structure matches the expected ResolvedCallModelInput shape
11
+ */
12
+ function buildResolvedRequest(entries) {
13
+ const obj = Object.fromEntries(entries);
14
+ return obj;
15
+ }
16
+ /**
17
+ * Resolve all async functions in CallModelInput to their values
18
+ *
19
+ * @param input - Input with possible functions
20
+ * @param context - Turn context for function execution
21
+ * @returns Resolved input with all values (no functions)
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const resolved = await resolveAsyncFunctions(
26
+ * {
27
+ * model: 'gpt-4',
28
+ * temperature: (ctx) => ctx.numberOfTurns * 0.1,
29
+ * input: 'Hello',
30
+ * },
31
+ * { numberOfTurns: 2, messageHistory: [] }
32
+ * );
33
+ * // resolved.temperature === 0.2
34
+ * ```
35
+ */
36
+ export async function resolveAsyncFunctions(input, context) {
37
+ // Build array of resolved entries
38
+ const resolvedEntries = [];
39
+ // Iterate over all keys in the input
40
+ for (const [key, value] of Object.entries(input)) {
41
+ // Skip stopWhen - it's handled separately in ModelResult
42
+ // Note: tools are already in API format at this point (converted in callModel()), so we include them
43
+ if (key === 'stopWhen') {
44
+ continue;
45
+ }
46
+ if (isParameterFunction(value)) {
47
+ try {
48
+ // Execute the function with context and store the result
49
+ const result = await Promise.resolve(value(context));
50
+ resolvedEntries.push([key, result]);
51
+ }
52
+ catch (error) {
53
+ // Wrap errors with context about which field failed
54
+ throw new Error(`Failed to resolve async function for field "${key}": ${error instanceof Error ? error.message : String(error)}`);
55
+ }
56
+ }
57
+ else {
58
+ // Not a function, use as-is
59
+ resolvedEntries.push([key, value]);
60
+ }
61
+ }
62
+ return buildResolvedRequest(resolvedEntries);
63
+ }
64
+ /**
65
+ * Check if input has any async functions that need resolution
66
+ *
67
+ * @param input - Input to check
68
+ * @returns True if any field is a function
69
+ */
70
+ export function hasAsyncFunctions(input) {
71
+ if (!input || typeof input !== 'object') {
72
+ return false;
73
+ }
74
+ return Object.values(input).some((value) => typeof value === 'function');
75
+ }
76
+ //# sourceMappingURL=async-params.js.map
package/esm/lib/base64.js CHANGED
@@ -1,5 +1,6 @@
1
1
  /*
2
2
  * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
3
+ * @generated-id: 598522066688
3
4
  */
4
5
  import * as z from "zod/v4";
5
6
  export function bytesToBase64(u8arr) {
@@ -0,0 +1,46 @@
1
+ import type * as models from "../models/index.js";
2
+ import { extractMessageFromResponse } from "./stream-transformers.js";
3
+ /**
4
+ * Convert OpenAI chat-style messages to OpenResponses input format.
5
+ *
6
+ * This function transforms Message[] (OpenAI chat format) to OpenResponsesInput
7
+ * format that can be passed directly to callModel().
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { fromChatMessages } from '@openrouter/sdk';
12
+ *
13
+ * const chatMessages = [
14
+ * { role: "system", content: "You are a helpful assistant." },
15
+ * { role: "user", content: "Hello!" },
16
+ * ];
17
+ *
18
+ * const response = openrouter.callModel({
19
+ * model: "openai/gpt-4",
20
+ * input: fromChatMessages(chatMessages),
21
+ * });
22
+ * ```
23
+ */
24
+ export declare function fromChatMessages(messages: models.Message[]): models.OpenResponsesInput;
25
+ /**
26
+ * Convert an OpenResponses response to OpenAI chat message format.
27
+ *
28
+ * This function transforms OpenResponsesNonStreamingResponse to AssistantMessage
29
+ * (OpenAI chat format) for compatibility with code expecting chat responses.
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * import { toChatMessage } from '@openrouter/sdk';
34
+ *
35
+ * const response = await openrouter.callModel({
36
+ * model: "openai/gpt-4",
37
+ * input: "Hello!",
38
+ * });
39
+ *
40
+ * const openResponsesResult = await response.getResponse();
41
+ * const chatMessage = toChatMessage(openResponsesResult);
42
+ * // chatMessage is now { role: "assistant", content: "..." }
43
+ * ```
44
+ */
45
+ export declare const toChatMessage: typeof extractMessageFromResponse;
46
+ //# sourceMappingURL=chat-compat.d.ts.map