@openrouter/agent 0.1.0

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 (98) hide show
  1. package/README.md +367 -0
  2. package/esm/api-shape-helpers/claude-message.d.ts +218 -0
  3. package/esm/api-shape-helpers/claude-message.d.ts.map +1 -0
  4. package/esm/api-shape-helpers/claude-message.js +6 -0
  5. package/esm/api-shape-helpers/claude-message.js.map +1 -0
  6. package/esm/index.d.ts +22 -0
  7. package/esm/index.d.ts.map +1 -0
  8. package/esm/index.js +27 -0
  9. package/esm/index.js.map +1 -0
  10. package/esm/inner-loop/call-model.d.ts +67 -0
  11. package/esm/inner-loop/call-model.d.ts.map +1 -0
  12. package/esm/inner-loop/call-model.js +116 -0
  13. package/esm/inner-loop/call-model.js.map +1 -0
  14. package/esm/lib/anthropic-compat.d.ts +51 -0
  15. package/esm/lib/anthropic-compat.d.ts.map +1 -0
  16. package/esm/lib/anthropic-compat.js +216 -0
  17. package/esm/lib/anthropic-compat.js.map +1 -0
  18. package/esm/lib/anthropic-compat.test.d.ts +2 -0
  19. package/esm/lib/anthropic-compat.test.d.ts.map +1 -0
  20. package/esm/lib/anthropic-compat.test.js +668 -0
  21. package/esm/lib/anthropic-compat.test.js.map +1 -0
  22. package/esm/lib/async-params.d.ts +107 -0
  23. package/esm/lib/async-params.d.ts.map +1 -0
  24. package/esm/lib/async-params.js +94 -0
  25. package/esm/lib/async-params.js.map +1 -0
  26. package/esm/lib/chat-compat.d.ts +46 -0
  27. package/esm/lib/chat-compat.d.ts.map +1 -0
  28. package/esm/lib/chat-compat.js +111 -0
  29. package/esm/lib/chat-compat.js.map +1 -0
  30. package/esm/lib/chat-compat.test.d.ts +2 -0
  31. package/esm/lib/chat-compat.test.d.ts.map +1 -0
  32. package/esm/lib/chat-compat.test.js +405 -0
  33. package/esm/lib/chat-compat.test.js.map +1 -0
  34. package/esm/lib/claude-constants.d.ts +22 -0
  35. package/esm/lib/claude-constants.d.ts.map +1 -0
  36. package/esm/lib/claude-constants.js +20 -0
  37. package/esm/lib/claude-constants.js.map +1 -0
  38. package/esm/lib/claude-type-guards.d.ts +10 -0
  39. package/esm/lib/claude-type-guards.d.ts.map +1 -0
  40. package/esm/lib/claude-type-guards.js +68 -0
  41. package/esm/lib/claude-type-guards.js.map +1 -0
  42. package/esm/lib/conversation-state.d.ts +61 -0
  43. package/esm/lib/conversation-state.d.ts.map +1 -0
  44. package/esm/lib/conversation-state.js +230 -0
  45. package/esm/lib/conversation-state.js.map +1 -0
  46. package/esm/lib/model-result.d.ts +370 -0
  47. package/esm/lib/model-result.d.ts.map +1 -0
  48. package/esm/lib/model-result.js +1483 -0
  49. package/esm/lib/model-result.js.map +1 -0
  50. package/esm/lib/next-turn-params.d.ts +30 -0
  51. package/esm/lib/next-turn-params.d.ts.map +1 -0
  52. package/esm/lib/next-turn-params.js +129 -0
  53. package/esm/lib/next-turn-params.js.map +1 -0
  54. package/esm/lib/reusable-stream.d.ts +39 -0
  55. package/esm/lib/reusable-stream.d.ts.map +1 -0
  56. package/esm/lib/reusable-stream.js +192 -0
  57. package/esm/lib/reusable-stream.js.map +1 -0
  58. package/esm/lib/stop-conditions.d.ts +80 -0
  59. package/esm/lib/stop-conditions.d.ts.map +1 -0
  60. package/esm/lib/stop-conditions.js +104 -0
  61. package/esm/lib/stop-conditions.js.map +1 -0
  62. package/esm/lib/stream-transformers.d.ts +109 -0
  63. package/esm/lib/stream-transformers.d.ts.map +1 -0
  64. package/esm/lib/stream-transformers.js +856 -0
  65. package/esm/lib/stream-transformers.js.map +1 -0
  66. package/esm/lib/stream-type-guards.d.ts +29 -0
  67. package/esm/lib/stream-type-guards.d.ts.map +1 -0
  68. package/esm/lib/stream-type-guards.js +85 -0
  69. package/esm/lib/stream-type-guards.js.map +1 -0
  70. package/esm/lib/tool-context.d.ts +68 -0
  71. package/esm/lib/tool-context.d.ts.map +1 -0
  72. package/esm/lib/tool-context.js +188 -0
  73. package/esm/lib/tool-context.js.map +1 -0
  74. package/esm/lib/tool-event-broadcaster.d.ts +44 -0
  75. package/esm/lib/tool-event-broadcaster.d.ts.map +1 -0
  76. package/esm/lib/tool-event-broadcaster.js +162 -0
  77. package/esm/lib/tool-event-broadcaster.js.map +1 -0
  78. package/esm/lib/tool-executor.d.ts +73 -0
  79. package/esm/lib/tool-executor.d.ts.map +1 -0
  80. package/esm/lib/tool-executor.js +267 -0
  81. package/esm/lib/tool-executor.js.map +1 -0
  82. package/esm/lib/tool-orchestrator.d.ts +50 -0
  83. package/esm/lib/tool-orchestrator.d.ts.map +1 -0
  84. package/esm/lib/tool-orchestrator.js +180 -0
  85. package/esm/lib/tool-orchestrator.js.map +1 -0
  86. package/esm/lib/tool-types.d.ts +572 -0
  87. package/esm/lib/tool-types.d.ts.map +1 -0
  88. package/esm/lib/tool-types.js +80 -0
  89. package/esm/lib/tool-types.js.map +1 -0
  90. package/esm/lib/tool.d.ts +108 -0
  91. package/esm/lib/tool.d.ts.map +1 -0
  92. package/esm/lib/tool.js +84 -0
  93. package/esm/lib/tool.js.map +1 -0
  94. package/esm/lib/turn-context.d.ts +50 -0
  95. package/esm/lib/turn-context.d.ts.map +1 -0
  96. package/esm/lib/turn-context.js +61 -0
  97. package/esm/lib/turn-context.js.map +1 -0
  98. package/package.json +125 -0
@@ -0,0 +1,67 @@
1
+ import type { OpenRouterCore } from '@openrouter/sdk/core';
2
+ import type { RequestOptions } from '@openrouter/sdk/lib/sdks';
3
+ import type { $ZodObject, $ZodShape, infer as zodInfer } from 'zod/v4/core';
4
+ import type { CallModelInput } from '../lib/async-params.js';
5
+ import type { Tool } from '../lib/tool-types.js';
6
+ import { ModelResult } from '../lib/model-result.js';
7
+ export type { CallModelInput } from '../lib/async-params.js';
8
+ /**
9
+ * Get a response with multiple consumption patterns
10
+ *
11
+ * @remarks
12
+ * Creates a response using the OpenResponses API and returns
13
+ * a wrapper that allows consuming the response in multiple ways:
14
+ *
15
+ * - `await response.getText()` - Get just the text content (tools auto-executed)
16
+ * - `await response.getResponse()` - Get full response with usage data (inputTokens, cachedTokens, etc.)
17
+ * - `for await (const delta of response.getTextStream())` - Stream text deltas
18
+ * - `for await (const delta of response.getReasoningStream())` - Stream reasoning deltas
19
+ * - `for await (const event of response.getToolStream())` - Stream tool events (incl. preliminary results)
20
+ * - `for await (const toolCall of response.getToolCallsStream())` - Stream structured tool calls
21
+ * - `await response.getToolCalls()` - Get all tool calls from completed response
22
+ * - `for await (const msg of response.getNewMessagesStream())` - Stream cumulative message snapshots
23
+ * - `for await (const event of response.getFullResponsesStream())` - Stream all events (incl. tool preliminary)
24
+ *
25
+ * All consumption patterns can be used concurrently on the same response.
26
+ *
27
+ * **Context:**
28
+ *
29
+ * Tools can declare a `contextSchema` to receive typed context data.
30
+ * The `context` parameter on callModel is typed as the intersection of all tool schemas:
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const result = callModel(client, {
35
+ * model: 'gpt-4',
36
+ * input: 'Hello',
37
+ * tools: [weatherTool, dbTool] as const,
38
+ * context: {
39
+ * get_weather: { apiKey: 'sk-...' },
40
+ * db_query: { dbUrl: 'postgres://...' },
41
+ * },
42
+ * });
43
+ * ```
44
+ *
45
+ * Context can also be a function or async function:
46
+ * ```typescript
47
+ * context: (turn) => ({
48
+ * get_weather: { apiKey: turn.numberOfTurns > 1 ? refreshedKey : initialKey },
49
+ * })
50
+ * ```
51
+ *
52
+ * **Stop Conditions:**
53
+ *
54
+ * Control when tool execution stops using the `stopWhen` parameter:
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * stopWhen: stepCountIs(3)
59
+ * stopWhen: [stepCountIs(10), maxCost(0.50), hasToolCall('finalize')]
60
+ * ```
61
+ *
62
+ * Default: `stepCountIs(5)` if not specified
63
+ */
64
+ export declare function callModel<TTools extends readonly Tool[], TSharedSchema extends $ZodObject<$ZodShape> | undefined = undefined, TShared extends Record<string, unknown> = TSharedSchema extends $ZodObject<$ZodShape> ? zodInfer<TSharedSchema> : Record<string, never>>(client: OpenRouterCore, request: CallModelInput<TTools, TShared> & {
65
+ sharedContextSchema?: TSharedSchema;
66
+ }, options?: RequestOptions): ModelResult<TTools, TShared>;
67
+ //# sourceMappingURL=call-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-model.d.ts","sourceRoot":"","sources":["../../src/inner-loop/call-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,IAAI,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,EAA2B,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAI9E,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,wBAAgB,SAAS,CACvB,MAAM,SAAS,SAAS,IAAI,EAAE,EAC9B,aAAa,SAAS,UAAU,CAAC,SAAS,CAAC,GAAG,SAAS,GAAG,SAAS,EACnE,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,SAAS,UAAU,CAAC,SAAS,CAAC,GACjF,QAAQ,CAAC,aAAa,CAAC,GACvB,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAEzB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACzC,mBAAmB,CAAC,EAAE,aAAa,CAAC;CACrC,EACD,OAAO,CAAC,EAAE,cAAc,GACvB,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CA2E9B"}
@@ -0,0 +1,116 @@
1
+ import { ModelResult } from '../lib/model-result.js';
2
+ import { convertToolsToAPIFormat } from '../lib/tool-executor.js';
3
+ /**
4
+ * Get a response with multiple consumption patterns
5
+ *
6
+ * @remarks
7
+ * Creates a response using the OpenResponses API and returns
8
+ * a wrapper that allows consuming the response in multiple ways:
9
+ *
10
+ * - `await response.getText()` - Get just the text content (tools auto-executed)
11
+ * - `await response.getResponse()` - Get full response with usage data (inputTokens, cachedTokens, etc.)
12
+ * - `for await (const delta of response.getTextStream())` - Stream text deltas
13
+ * - `for await (const delta of response.getReasoningStream())` - Stream reasoning deltas
14
+ * - `for await (const event of response.getToolStream())` - Stream tool events (incl. preliminary results)
15
+ * - `for await (const toolCall of response.getToolCallsStream())` - Stream structured tool calls
16
+ * - `await response.getToolCalls()` - Get all tool calls from completed response
17
+ * - `for await (const msg of response.getNewMessagesStream())` - Stream cumulative message snapshots
18
+ * - `for await (const event of response.getFullResponsesStream())` - Stream all events (incl. tool preliminary)
19
+ *
20
+ * All consumption patterns can be used concurrently on the same response.
21
+ *
22
+ * **Context:**
23
+ *
24
+ * Tools can declare a `contextSchema` to receive typed context data.
25
+ * The `context` parameter on callModel is typed as the intersection of all tool schemas:
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const result = callModel(client, {
30
+ * model: 'gpt-4',
31
+ * input: 'Hello',
32
+ * tools: [weatherTool, dbTool] as const,
33
+ * context: {
34
+ * get_weather: { apiKey: 'sk-...' },
35
+ * db_query: { dbUrl: 'postgres://...' },
36
+ * },
37
+ * });
38
+ * ```
39
+ *
40
+ * Context can also be a function or async function:
41
+ * ```typescript
42
+ * context: (turn) => ({
43
+ * get_weather: { apiKey: turn.numberOfTurns > 1 ? refreshedKey : initialKey },
44
+ * })
45
+ * ```
46
+ *
47
+ * **Stop Conditions:**
48
+ *
49
+ * Control when tool execution stops using the `stopWhen` parameter:
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * stopWhen: stepCountIs(3)
54
+ * stopWhen: [stepCountIs(10), maxCost(0.50), hasToolCall('finalize')]
55
+ * ```
56
+ *
57
+ * Default: `stepCountIs(5)` if not specified
58
+ */
59
+ export function callModel(client, request, options) {
60
+ // Destructure state management options along with tools and stopWhen
61
+ const { tools, stopWhen, state, requireApproval, approveToolCalls, rejectToolCalls, context, sharedContextSchema, onTurnStart, onTurnEnd, ...apiRequest } = request;
62
+ // Convert tools to API format - no cast needed now that convertToolsToAPIFormat accepts readonly
63
+ const apiTools = tools ? convertToolsToAPIFormat(tools) : undefined;
64
+ // Build the request with converted tools
65
+ // Note: async functions are resolved later in ModelResult.executeToolsIfNeeded()
66
+ // The request can have async fields (functions) or sync fields, and the tools are converted to API format
67
+ const finalRequest = {
68
+ ...apiRequest,
69
+ };
70
+ if (apiTools !== undefined) {
71
+ finalRequest['tools'] = apiTools;
72
+ }
73
+ // Inject x-openrouter-callmodel header into every callModel request
74
+ const callModelOptions = {
75
+ ...options,
76
+ headers: {
77
+ ...Object.fromEntries(new Headers(options?.headers ?? options?.fetchOptions?.headers ?? undefined)),
78
+ 'x-openrouter-callmodel': 'true',
79
+ },
80
+ };
81
+ return new ModelResult({
82
+ client,
83
+ request: finalRequest,
84
+ options: callModelOptions,
85
+ tools,
86
+ ...(stopWhen !== undefined && {
87
+ stopWhen,
88
+ }),
89
+ // Pass state management options
90
+ ...(state !== undefined && {
91
+ state,
92
+ }),
93
+ ...(requireApproval !== undefined && {
94
+ requireApproval,
95
+ }),
96
+ ...(approveToolCalls !== undefined && {
97
+ approveToolCalls,
98
+ }),
99
+ ...(rejectToolCalls !== undefined && {
100
+ rejectToolCalls,
101
+ }),
102
+ ...(context !== undefined && {
103
+ context,
104
+ }),
105
+ ...(sharedContextSchema !== undefined && {
106
+ sharedContextSchema,
107
+ }),
108
+ ...(onTurnStart !== undefined && {
109
+ onTurnStart,
110
+ }),
111
+ ...(onTurnEnd !== undefined && {
112
+ onTurnEnd,
113
+ }),
114
+ });
115
+ }
116
+ //# sourceMappingURL=call-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-model.js","sourceRoot":"","sources":["../../src/inner-loop/call-model.ts"],"names":[],"mappings":"AAMA,OAAO,EAA2B,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAKlE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,MAAM,UAAU,SAAS,CAOvB,MAAsB,EACtB,OAEC,EACD,OAAwB;IAExB,qEAAqE;IACrE,MAAM,EACJ,KAAK,EACL,QAAQ,EACR,KAAK,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,OAAO,EACP,mBAAmB,EACnB,WAAW,EACX,SAAS,EACT,GAAG,UAAU,EACd,GAAG,OAAO,CAAC;IAEZ,iGAAiG;IACjG,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAEpE,yCAAyC;IACzC,iFAAiF;IACjF,0GAA0G;IAC1G,MAAM,YAAY,GAA4B;QAC5C,GAAG,UAAU;KACd,CAAC;IAEF,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,YAAY,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC;IACnC,CAAC;IAED,oEAAoE;IACpE,MAAM,gBAAgB,GAAmB;QACvC,GAAG,OAAO;QACV,OAAO,EAAE;YACP,GAAG,MAAM,CAAC,WAAW,CACnB,IAAI,OAAO,CAAC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,YAAY,EAAE,OAAO,IAAI,SAAS,CAAC,CAC7E;YACD,wBAAwB,EAAE,MAAM;SACjC;KACF,CAAC;IAEF,OAAO,IAAI,WAAW,CAAkB;QACtC,MAAM;QACN,OAAO,EAAE,YAAY;QACrB,OAAO,EAAE,gBAAgB;QACzB,KAAK;QACL,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI;YAC5B,QAAQ;SACT,CAAC;QACF,gCAAgC;QAChC,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI;YACzB,KAAK;SACN,CAAC;QACF,GAAG,CAAC,eAAe,KAAK,SAAS,IAAI;YACnC,eAAe;SAChB,CAAC;QACF,GAAG,CAAC,gBAAgB,KAAK,SAAS,IAAI;YACpC,gBAAgB;SACjB,CAAC;QACF,GAAG,CAAC,eAAe,KAAK,SAAS,IAAI;YACnC,eAAe;SAChB,CAAC;QACF,GAAG,CAAC,OAAO,KAAK,SAAS,IAAI;YAC3B,OAAO;SACR,CAAC;QACF,GAAG,CAAC,mBAAmB,KAAK,SAAS,IAAI;YACvC,mBAAmB;SACpB,CAAC;QACF,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI;YAC/B,WAAW;SACZ,CAAC;QACF,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI;YAC7B,SAAS;SACV,CAAC;KACoC,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,51 @@
1
+ import type * as models from '@openrouter/sdk/models';
2
+ import type { ClaudeMessageParam } from '../api-shape-helpers/claude-message.js';
3
+ import { convertToClaudeMessage } from './stream-transformers.js';
4
+ /**
5
+ * Convert Anthropic Claude-style messages to OpenResponses input format.
6
+ *
7
+ * This function transforms ClaudeMessageParam[] (Anthropic SDK format) to
8
+ * OpenResponsesInput format that can be passed directly to callModel().
9
+ *
10
+ * Note: Some Claude features are lost in conversion as OpenRouter doesn't support them:
11
+ * - cache_control on content blocks
12
+ * - is_error flag on tool_result blocks
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { fromClaudeMessages } from '@openrouter/sdk';
17
+ *
18
+ * const claudeMessages = [
19
+ * { role: "user", content: "Hello!" },
20
+ * { role: "assistant", content: "Hi there!" },
21
+ * ];
22
+ *
23
+ * const response = openrouter.callModel({
24
+ * model: "anthropic/claude-3-sonnet",
25
+ * input: fromClaudeMessages(claudeMessages),
26
+ * });
27
+ * ```
28
+ */
29
+ export declare function fromClaudeMessages(messages: ClaudeMessageParam[]): models.InputsUnion;
30
+ /**
31
+ * Convert an OpenResponses response to Anthropic Claude message format.
32
+ *
33
+ * This function transforms OpenResponsesResult to ClaudeMessage
34
+ * (Anthropic SDK format) for compatibility with code expecting Claude responses.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * import { toClaudeMessage } from '@openrouter/sdk';
39
+ *
40
+ * const response = await openrouter.callModel({
41
+ * model: "anthropic/claude-3-sonnet",
42
+ * input: "Hello!",
43
+ * });
44
+ *
45
+ * const openResponsesResult = await response.getResponse();
46
+ * const claudeMessage = toClaudeMessage(openResponsesResult);
47
+ * // claudeMessage is now compatible with Anthropic SDK types
48
+ * ```
49
+ */
50
+ export declare const toClaudeMessage: typeof convertToClaudeMessage;
51
+ //# sourceMappingURL=anthropic-compat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-compat.d.ts","sourceRoot":"","sources":["../../src/lib/anthropic-compat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAEV,kBAAkB,EAInB,MAAM,wCAAwC,CAAC;AAMhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAoClE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAAC,WAAW,CA8JrF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,eAAe,+BAAyB,CAAC"}
@@ -0,0 +1,216 @@
1
+ import { EasyInputMessageRoleAssistant, EasyInputMessageRoleUser, } from '@openrouter/sdk/models/easyinputmessage';
2
+ import { convertToClaudeMessage } from './stream-transformers.js';
3
+ /**
4
+ * Maps Claude role strings to OpenResponses role types
5
+ */
6
+ function mapClaudeRole(role) {
7
+ if (role === 'user') {
8
+ return EasyInputMessageRoleUser.User;
9
+ }
10
+ return EasyInputMessageRoleAssistant.Assistant;
11
+ }
12
+ /**
13
+ * Creates a properly typed EasyInputMessage with string or structured content.
14
+ */
15
+ function createEasyInputMessage(role, content) {
16
+ return {
17
+ role: mapClaudeRole(role),
18
+ content,
19
+ };
20
+ }
21
+ /**
22
+ * Creates a properly typed FunctionCallOutputItem
23
+ */
24
+ function createFunctionCallOutput(callId, output) {
25
+ return {
26
+ type: 'function_call_output',
27
+ callId,
28
+ output,
29
+ };
30
+ }
31
+ /**
32
+ * Convert Anthropic Claude-style messages to OpenResponses input format.
33
+ *
34
+ * This function transforms ClaudeMessageParam[] (Anthropic SDK format) to
35
+ * OpenResponsesInput format that can be passed directly to callModel().
36
+ *
37
+ * Note: Some Claude features are lost in conversion as OpenRouter doesn't support them:
38
+ * - cache_control on content blocks
39
+ * - is_error flag on tool_result blocks
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * import { fromClaudeMessages } from '@openrouter/sdk';
44
+ *
45
+ * const claudeMessages = [
46
+ * { role: "user", content: "Hello!" },
47
+ * { role: "assistant", content: "Hi there!" },
48
+ * ];
49
+ *
50
+ * const response = openrouter.callModel({
51
+ * model: "anthropic/claude-3-sonnet",
52
+ * input: fromClaudeMessages(claudeMessages),
53
+ * });
54
+ * ```
55
+ */
56
+ export function fromClaudeMessages(messages) {
57
+ const result = [];
58
+ for (const msg of messages) {
59
+ const { role, content } = msg;
60
+ if (typeof content === 'string') {
61
+ result.push(createEasyInputMessage(role, content));
62
+ continue;
63
+ }
64
+ // Separate content blocks into categories for clearer processing
65
+ const textBlocks = [];
66
+ const imageBlocks = [];
67
+ const toolUseBlocks = [];
68
+ const toolResultBlocks = [];
69
+ for (const block of content) {
70
+ switch (block.type) {
71
+ case 'text':
72
+ textBlocks.push(block);
73
+ break;
74
+ case 'image':
75
+ imageBlocks.push(block);
76
+ break;
77
+ case 'tool_use':
78
+ toolUseBlocks.push(block);
79
+ break;
80
+ case 'tool_result':
81
+ toolResultBlocks.push(block);
82
+ break;
83
+ default: {
84
+ // Exhaustiveness check - TypeScript will error if we don't handle all block types
85
+ const exhaustiveCheck = block;
86
+ throw new Error(`Unhandled content block type: ${JSON.stringify(exhaustiveCheck)}`);
87
+ }
88
+ }
89
+ }
90
+ // Process tool use blocks first (they go directly to result)
91
+ for (const toolUseBlock of toolUseBlocks) {
92
+ result.push({
93
+ type: 'function_call',
94
+ callId: toolUseBlock.id,
95
+ name: toolUseBlock.name,
96
+ arguments: JSON.stringify(toolUseBlock.input),
97
+ id: toolUseBlock.id,
98
+ status: 'completed',
99
+ });
100
+ }
101
+ // Process tool result blocks
102
+ for (const toolResultBlock of toolResultBlocks) {
103
+ let toolOutput = '';
104
+ if (typeof toolResultBlock.content === 'string') {
105
+ toolOutput = toolResultBlock.content;
106
+ }
107
+ else {
108
+ // Extract text and handle images separately
109
+ const textParts = [];
110
+ const imageParts = [];
111
+ for (const part of toolResultBlock.content) {
112
+ if (part.type === 'text') {
113
+ textParts.push(part.text);
114
+ }
115
+ else if (part.type === 'image') {
116
+ imageParts.push(part);
117
+ }
118
+ }
119
+ toolOutput = textParts.join('');
120
+ // Map images to image_generation_call items
121
+ imageParts.forEach((imagePart, i) => {
122
+ let imageUrl;
123
+ if (imagePart.source.type === 'url') {
124
+ imageUrl = imagePart.source.url;
125
+ }
126
+ else if (imagePart.source.type === 'base64') {
127
+ imageUrl = `data:${imagePart.source.media_type};base64,${imagePart.source.data}`;
128
+ }
129
+ else {
130
+ const exhaustiveCheck = imagePart.source;
131
+ throw new Error(`Unhandled image source type: ${exhaustiveCheck}`);
132
+ }
133
+ result.push({
134
+ type: 'image_generation_call',
135
+ id: `${toolResultBlock.tool_use_id}-image-${i}`,
136
+ result: imageUrl,
137
+ status: 'completed',
138
+ });
139
+ });
140
+ }
141
+ // Add the function call output for the text portion (if any)
142
+ if (toolOutput.length > 0) {
143
+ result.push(createFunctionCallOutput(toolResultBlock.tool_use_id, toolOutput));
144
+ }
145
+ }
146
+ // Process text and image blocks (these become message content)
147
+ if (textBlocks.length > 0 || imageBlocks.length > 0) {
148
+ const contentItems = [];
149
+ // Add text blocks
150
+ for (const textBlock of textBlocks) {
151
+ contentItems.push({
152
+ type: 'input_text',
153
+ text: textBlock.text,
154
+ });
155
+ }
156
+ // Add image blocks
157
+ for (const imageBlock of imageBlocks) {
158
+ let imageUrl;
159
+ if (imageBlock.source.type === 'url') {
160
+ imageUrl = imageBlock.source.url;
161
+ }
162
+ else if (imageBlock.source.type === 'base64') {
163
+ imageUrl = `data:${imageBlock.source.media_type};base64,${imageBlock.source.data}`;
164
+ }
165
+ else {
166
+ const exhaustiveCheck = imageBlock.source;
167
+ throw new Error(`Unhandled image source type: ${exhaustiveCheck}`);
168
+ }
169
+ contentItems.push({
170
+ type: 'input_image',
171
+ detail: 'auto',
172
+ imageUrl,
173
+ });
174
+ }
175
+ // Determine output format based on content
176
+ if (imageBlocks.length > 0) {
177
+ // Use EasyInputMessage with structured content array for messages with images
178
+ // (InputMessageItem doesn't support the assistant role)
179
+ result.push(createEasyInputMessage(role, contentItems));
180
+ }
181
+ else {
182
+ // Use simple string format for text-only messages
183
+ const textContent = contentItems
184
+ .filter((item) => item.type === 'input_text')
185
+ .map((item) => item.text)
186
+ .join('');
187
+ if (textContent.length > 0) {
188
+ result.push(createEasyInputMessage(role, textContent));
189
+ }
190
+ }
191
+ }
192
+ }
193
+ return result;
194
+ }
195
+ /**
196
+ * Convert an OpenResponses response to Anthropic Claude message format.
197
+ *
198
+ * This function transforms OpenResponsesResult to ClaudeMessage
199
+ * (Anthropic SDK format) for compatibility with code expecting Claude responses.
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * import { toClaudeMessage } from '@openrouter/sdk';
204
+ *
205
+ * const response = await openrouter.callModel({
206
+ * model: "anthropic/claude-3-sonnet",
207
+ * input: "Hello!",
208
+ * });
209
+ *
210
+ * const openResponsesResult = await response.getResponse();
211
+ * const claudeMessage = toClaudeMessage(openResponsesResult);
212
+ * // claudeMessage is now compatible with Anthropic SDK types
213
+ * ```
214
+ */
215
+ export const toClaudeMessage = convertToClaudeMessage;
216
+ //# sourceMappingURL=anthropic-compat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-compat.js","sourceRoot":"","sources":["../../src/lib/anthropic-compat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=anthropic-compat.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-compat.test.d.ts","sourceRoot":"","sources":["../../src/lib/anthropic-compat.test.ts"],"names":[],"mappings":""}