@agentionai/agents 1.7.0-beta.0 → 1.8.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.
- package/README.md +4 -2
- package/dist/agents/Agent.d.ts +9 -2
- package/dist/agents/Agent.js +4 -0
- package/dist/agents/AgentConfig.d.ts +76 -2
- package/dist/agents/anthropic/ClaudeAgent.js +2 -2
- package/dist/agents/errors/AgentError.d.ts +34 -2
- package/dist/agents/errors/AgentError.js +37 -1
- package/dist/agents/google/GeminiAgent.js +7 -2
- package/dist/agents/mistral/MistralAgent.js +5 -2
- package/dist/agents/openai/OpenAiAgent.js +8 -2
- package/dist/agents/openai-compatible/OpenAICompatibleAgent.js +2 -2
- package/dist/agents/openrouter/OpenRouterAgent.d.ts +234 -0
- package/dist/agents/openrouter/OpenRouterAgent.js +754 -0
- package/dist/agents/openrouter/types.d.ts +164 -0
- package/dist/agents/openrouter/types.js +15 -0
- package/dist/history/transformers.d.ts +80 -0
- package/dist/history/transformers.js +156 -1
- package/dist/history/types.d.ts +22 -2
- package/dist/history/types.js +13 -2
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -1
- package/dist/openrouter.d.ts +6 -0
- package/dist/openrouter.js +24 -0
- package/dist/viz/types.d.ts +1 -1
- package/package.json +10 -1
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenRouter request-shaping types.
|
|
3
|
+
*
|
|
4
|
+
* Declared structurally rather than imported from `@openrouter/sdk` so that
|
|
5
|
+
* consumers who have not installed the optional peer dependency still typecheck
|
|
6
|
+
* — the same approach `lib/mcp/types.ts` takes for the MCP SDK. Assignability
|
|
7
|
+
* against the SDK's own types is asserted in `types.spec.ts`, which fails the
|
|
8
|
+
* build if OpenRouter's shapes drift away from these.
|
|
9
|
+
*
|
|
10
|
+
* Field names are camelCase because that is what the SDK accepts; it
|
|
11
|
+
* zod-serializes them to the snake_case the HTTP API expects.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Provider sorting strategy applied when no explicit `order` is given.
|
|
15
|
+
*
|
|
16
|
+
* - `"price"` — cheapest endpoint first
|
|
17
|
+
* - `"throughput"` — highest tokens/second first
|
|
18
|
+
* - `"latency"` — lowest time-to-first-token first
|
|
19
|
+
* - `"exacto"` — OpenRouter's accuracy-verified endpoints first
|
|
20
|
+
*
|
|
21
|
+
* Setting any of these disables load balancing.
|
|
22
|
+
*/
|
|
23
|
+
export type OpenRouterProviderSort = "price" | "throughput" | "latency" | "exacto";
|
|
24
|
+
/**
|
|
25
|
+
* Maximum price to pay for a request, in USD per million tokens (per image or
|
|
26
|
+
* per request for the corresponding fields). Values are strings, as the API
|
|
27
|
+
* takes them.
|
|
28
|
+
*/
|
|
29
|
+
export type OpenRouterMaxPrice = {
|
|
30
|
+
/** USD per million prompt tokens */
|
|
31
|
+
prompt?: string;
|
|
32
|
+
/** USD per million completion tokens */
|
|
33
|
+
completion?: string;
|
|
34
|
+
/** USD per image */
|
|
35
|
+
image?: string;
|
|
36
|
+
/** USD per request */
|
|
37
|
+
request?: string;
|
|
38
|
+
/** USD per audio unit */
|
|
39
|
+
audio?: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Where OpenRouter is allowed to route a request.
|
|
43
|
+
*
|
|
44
|
+
* Directly relevant to throttling: `order`/`only`/`ignore` decide which
|
|
45
|
+
* upstream providers are in play, and `allowFallbacks` (default `true`) is what
|
|
46
|
+
* lets OpenRouter move past one that is rate limited or down.
|
|
47
|
+
*
|
|
48
|
+
* @see https://openrouter.ai/docs/guides/features/provider-routing
|
|
49
|
+
*/
|
|
50
|
+
export type OpenRouterProviderPreferences = {
|
|
51
|
+
/**
|
|
52
|
+
* Ordered list of provider slugs. The router uses the first one in this list
|
|
53
|
+
* that serves the requested model, falling back to the next when it is
|
|
54
|
+
* unavailable.
|
|
55
|
+
*/
|
|
56
|
+
order?: string[] | null;
|
|
57
|
+
/** Provider slugs to allow, merged with your account-wide allow list. */
|
|
58
|
+
only?: string[] | null;
|
|
59
|
+
/** Provider slugs to skip, merged with your account-wide ignore list. */
|
|
60
|
+
ignore?: string[] | null;
|
|
61
|
+
/**
|
|
62
|
+
* Whether backup providers may serve the request.
|
|
63
|
+
*
|
|
64
|
+
* `true` (default) moves to the next best provider when the primary is
|
|
65
|
+
* unavailable — including when it rate limits you. `false` returns the
|
|
66
|
+
* upstream error instead, which is what you want when `order` names the only
|
|
67
|
+
* provider you will accept.
|
|
68
|
+
*/
|
|
69
|
+
allowFallbacks?: boolean | null;
|
|
70
|
+
/** Sorting strategy used when `order` is not set. Disables load balancing. */
|
|
71
|
+
sort?: OpenRouterProviderSort | null;
|
|
72
|
+
/** Cap on what the request may cost. */
|
|
73
|
+
maxPrice?: OpenRouterMaxPrice;
|
|
74
|
+
/**
|
|
75
|
+
* Route only to providers that support every parameter sent. Off by default,
|
|
76
|
+
* in which case providers silently drop parameters they do not understand.
|
|
77
|
+
*/
|
|
78
|
+
requireParameters?: boolean | null;
|
|
79
|
+
/**
|
|
80
|
+
* `"deny"` restricts routing to providers that do not store prompts.
|
|
81
|
+
* `"allow"` (default) permits providers that may retain and train on them.
|
|
82
|
+
*/
|
|
83
|
+
dataCollection?: "allow" | "deny" | null;
|
|
84
|
+
/** Restrict routing to Zero Data Retention endpoints. */
|
|
85
|
+
zdr?: boolean | null;
|
|
86
|
+
/** Quantization levels to accept (e.g. `"fp8"`, `"bf16"`). */
|
|
87
|
+
quantizations?: OpenRouterQuantization[] | null;
|
|
88
|
+
/** Deprioritize endpoints slower than this p50 latency, in seconds. */
|
|
89
|
+
preferredMaxLatency?: number | null;
|
|
90
|
+
/** Deprioritize endpoints below this p50 throughput, in tokens/second. */
|
|
91
|
+
preferredMinThroughput?: number | null;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* How hard a reasoning model should think. `"none"` disables reasoning where
|
|
95
|
+
* the model allows it; which values a given model accepts is model-dependent
|
|
96
|
+
* and OpenRouter normalizes the rest per upstream provider.
|
|
97
|
+
*/
|
|
98
|
+
/**
|
|
99
|
+
* Quantization levels accepted when filtering providers, e.g. `"fp8"`, `"bf16"`.
|
|
100
|
+
*
|
|
101
|
+
* Kept as an explicit string-literal union (rather than `string`) so a caller's
|
|
102
|
+
* config is assignable to `@openrouter/sdk`'s branded `Quantization` enum —
|
|
103
|
+
* see `types.spec.ts`. OpenRouter may add values over time; unknown ones are
|
|
104
|
+
* rejected by the SDK at runtime.
|
|
105
|
+
*/
|
|
106
|
+
export type OpenRouterQuantization = "int4" | "int8" | "fp4" | "mxfp4" | "nvfp4" | "fp6" | "fp8" | "mxfp8" | "fp16" | "bf16" | "fp32" | "unknown";
|
|
107
|
+
export type OpenRouterReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
108
|
+
/** Reasoning configuration sent with the request. */
|
|
109
|
+
export type OpenRouterReasoningConfig = {
|
|
110
|
+
effort?: OpenRouterReasoningEffort | null;
|
|
111
|
+
/** Verbosity of the reasoning summary, on models that produce one. */
|
|
112
|
+
summary?: string | null;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Retry policy handed to the SDK per chat request.
|
|
116
|
+
*
|
|
117
|
+
* Mirrors the SDK's own `RetryConfig`. See
|
|
118
|
+
* {@link OpenRouterSpecificConfig.retry} for why the agent does not simply take
|
|
119
|
+
* the SDK's defaults.
|
|
120
|
+
*/
|
|
121
|
+
export type OpenRouterRetryConfig = {
|
|
122
|
+
strategy: "none";
|
|
123
|
+
} | {
|
|
124
|
+
strategy: "backoff";
|
|
125
|
+
backoff?: {
|
|
126
|
+
/** Base delay in ms; the nth retry waits `initialInterval * n ** exponent`. */
|
|
127
|
+
initialInterval: number;
|
|
128
|
+
/** Ceiling on a single wait, in ms — also caps a long `Retry-After`. */
|
|
129
|
+
maxInterval: number;
|
|
130
|
+
exponent: number;
|
|
131
|
+
/** Total ms the retry loop may run before giving up. */
|
|
132
|
+
maxElapsedTime: number;
|
|
133
|
+
};
|
|
134
|
+
/** Also retry timeouts and connection failures. */
|
|
135
|
+
retryConnectionErrors?: boolean;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* The cost and routing facts OpenRouter reports for a completed turn, which no
|
|
139
|
+
* other provider in this library exposes.
|
|
140
|
+
*
|
|
141
|
+
* Populated after each `execute()` / `executeStream()` on
|
|
142
|
+
* {@link OpenRouterAgent.lastGeneration}, summed across the turn's API calls
|
|
143
|
+
* where the field is additive.
|
|
144
|
+
*/
|
|
145
|
+
export type OpenRouterGenerationInfo = {
|
|
146
|
+
/** Generation id of the last API call, for lookups against `/generation`. */
|
|
147
|
+
id?: string;
|
|
148
|
+
/**
|
|
149
|
+
* Model that actually answered. Differs from the configured model when a
|
|
150
|
+
* fallback in `models` was used, or when routing through `openrouter/auto`.
|
|
151
|
+
*/
|
|
152
|
+
model?: string;
|
|
153
|
+
/**
|
|
154
|
+
* Cost in USD credits, summed over every API call in the turn (a tool loop
|
|
155
|
+
* bills once per hop). Undefined when OpenRouter does not report a cost —
|
|
156
|
+
* BYOK requests being the usual case.
|
|
157
|
+
*/
|
|
158
|
+
cost?: number;
|
|
159
|
+
/** Whether the request was served through a Bring Your Own Key configuration. */
|
|
160
|
+
isByok?: boolean;
|
|
161
|
+
/** Number of provider attempts OpenRouter made before one succeeded. */
|
|
162
|
+
attempts?: number;
|
|
163
|
+
};
|
|
164
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenRouter request-shaping types.
|
|
4
|
+
*
|
|
5
|
+
* Declared structurally rather than imported from `@openrouter/sdk` so that
|
|
6
|
+
* consumers who have not installed the optional peer dependency still typecheck
|
|
7
|
+
* — the same approach `lib/mcp/types.ts` takes for the MCP SDK. Assignability
|
|
8
|
+
* against the SDK's own types is asserted in `types.spec.ts`, which fails the
|
|
9
|
+
* build if OpenRouter's shapes drift away from these.
|
|
10
|
+
*
|
|
11
|
+
* Field names are camelCase because that is what the SDK accepts; it
|
|
12
|
+
* zod-serializes them to the snake_case the HTTP API expects.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -154,6 +154,86 @@ export declare const chatCompletionsTransformer: {
|
|
|
154
154
|
*/
|
|
155
155
|
toolResultEntry(tool_call_id: string, output: string): HistoryEntry;
|
|
156
156
|
};
|
|
157
|
+
/**
|
|
158
|
+
* Convert normalized entries to/from the message format `@openrouter/sdk`
|
|
159
|
+
* accepts.
|
|
160
|
+
*
|
|
161
|
+
* The wire format is OpenAI Chat Completions, but the SDK's TypeScript surface
|
|
162
|
+
* is camelCase (`toolCalls`, `toolCallId`, `reasoningDetails`) and it
|
|
163
|
+
* zod-serializes to snake_case on the way out — so this cannot reuse
|
|
164
|
+
* {@link chatCompletionsTransformer}, whose output is already snake_case.
|
|
165
|
+
*
|
|
166
|
+
* Beyond the casing it also carries `reasoning_details` through the round trip,
|
|
167
|
+
* which the OpenAI-compatible path has no equivalent for.
|
|
168
|
+
*/
|
|
169
|
+
export declare const openRouterTransformer: {
|
|
170
|
+
/**
|
|
171
|
+
* Convert normalized entries to OpenRouter message format.
|
|
172
|
+
* Tool results become role:"tool" messages; tool calls ride on the assistant message.
|
|
173
|
+
*/
|
|
174
|
+
toProvider(entries: HistoryEntry[]): OpenRouterMessage[];
|
|
175
|
+
/**
|
|
176
|
+
* Convert an OpenRouter assistant message to a normalized HistoryEntry.
|
|
177
|
+
*/
|
|
178
|
+
fromProviderMessage(message: OpenRouterResponseMessage): HistoryEntry;
|
|
179
|
+
/**
|
|
180
|
+
* Create a normalized tool result entry for an OpenRouter tool call
|
|
181
|
+
*/
|
|
182
|
+
toolResultEntry(tool_call_id: string, output: string): HistoryEntry;
|
|
183
|
+
};
|
|
184
|
+
type OpenRouterToolCallParam = {
|
|
185
|
+
id: string;
|
|
186
|
+
type: "function";
|
|
187
|
+
function: {
|
|
188
|
+
name: string;
|
|
189
|
+
arguments: string;
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
type OpenRouterContentPart = {
|
|
193
|
+
type: "text";
|
|
194
|
+
text: string;
|
|
195
|
+
} | {
|
|
196
|
+
type: "image_url";
|
|
197
|
+
imageUrl: {
|
|
198
|
+
url: string;
|
|
199
|
+
detail?: "auto" | "low" | "high";
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
export type OpenRouterMessage = {
|
|
203
|
+
role: "system";
|
|
204
|
+
content: string;
|
|
205
|
+
} | {
|
|
206
|
+
role: "user";
|
|
207
|
+
content: string | OpenRouterContentPart[];
|
|
208
|
+
} | {
|
|
209
|
+
role: "assistant";
|
|
210
|
+
content: string | null;
|
|
211
|
+
toolCalls?: OpenRouterToolCallParam[];
|
|
212
|
+
/** Plain reasoning text replayed from a previous turn. */
|
|
213
|
+
reasoning?: string;
|
|
214
|
+
/**
|
|
215
|
+
* Opaque reasoning blocks replayed verbatim. Omitted entirely when the
|
|
216
|
+
* turn carried none.
|
|
217
|
+
*/
|
|
218
|
+
reasoningDetails?: unknown[];
|
|
219
|
+
} | {
|
|
220
|
+
role: "tool";
|
|
221
|
+
toolCallId: string;
|
|
222
|
+
content: string;
|
|
223
|
+
};
|
|
224
|
+
type OpenRouterResponseMessage = {
|
|
225
|
+
role: string;
|
|
226
|
+
content?: string | null;
|
|
227
|
+
toolCalls?: Array<{
|
|
228
|
+
id: string;
|
|
229
|
+
function?: {
|
|
230
|
+
name: string;
|
|
231
|
+
arguments: string;
|
|
232
|
+
};
|
|
233
|
+
}>;
|
|
234
|
+
reasoning?: string | null;
|
|
235
|
+
reasoningDetails?: unknown[];
|
|
236
|
+
};
|
|
157
237
|
type ChatCompletionToolCallParam = {
|
|
158
238
|
id: string;
|
|
159
239
|
type: "function";
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Transform between normalized HistoryEntry format and provider-specific formats.
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.chatCompletionsTransformer = exports.ollamaTransformer = exports.geminiTransformer = exports.mistralTransformer = exports.openAiTransformer = exports.anthropicTransformer = void 0;
|
|
8
|
+
exports.openRouterTransformer = exports.chatCompletionsTransformer = exports.ollamaTransformer = exports.geminiTransformer = exports.mistralTransformer = exports.openAiTransformer = exports.anthropicTransformer = void 0;
|
|
9
9
|
const types_1 = require("./types");
|
|
10
10
|
// =============================================================================
|
|
11
11
|
// Anthropic Transformer
|
|
@@ -759,4 +759,159 @@ exports.chatCompletionsTransformer = {
|
|
|
759
759
|
};
|
|
760
760
|
},
|
|
761
761
|
};
|
|
762
|
+
// =============================================================================
|
|
763
|
+
// OpenRouter Transformer
|
|
764
|
+
// =============================================================================
|
|
765
|
+
/**
|
|
766
|
+
* Convert normalized entries to/from the message format `@openrouter/sdk`
|
|
767
|
+
* accepts.
|
|
768
|
+
*
|
|
769
|
+
* The wire format is OpenAI Chat Completions, but the SDK's TypeScript surface
|
|
770
|
+
* is camelCase (`toolCalls`, `toolCallId`, `reasoningDetails`) and it
|
|
771
|
+
* zod-serializes to snake_case on the way out — so this cannot reuse
|
|
772
|
+
* {@link chatCompletionsTransformer}, whose output is already snake_case.
|
|
773
|
+
*
|
|
774
|
+
* Beyond the casing it also carries `reasoning_details` through the round trip,
|
|
775
|
+
* which the OpenAI-compatible path has no equivalent for.
|
|
776
|
+
*/
|
|
777
|
+
exports.openRouterTransformer = {
|
|
778
|
+
/**
|
|
779
|
+
* Convert normalized entries to OpenRouter message format.
|
|
780
|
+
* Tool results become role:"tool" messages; tool calls ride on the assistant message.
|
|
781
|
+
*/
|
|
782
|
+
toProvider(entries) {
|
|
783
|
+
const messages = [];
|
|
784
|
+
for (const entry of entries) {
|
|
785
|
+
const textBlocks = entry.content.filter(types_1.isTextContent);
|
|
786
|
+
const toolUseBlocks = entry.content.filter(types_1.isToolUseContent);
|
|
787
|
+
const toolResultBlocks = entry.content.filter(types_1.isToolResultContent);
|
|
788
|
+
const thinkingBlocks = entry.content.filter(types_1.isThinkingContent);
|
|
789
|
+
const imageUrlBlocks = entry.content.filter(types_1.isImageUrlContent);
|
|
790
|
+
const imageBase64Blocks = entry.content.filter(types_1.isImageBase64Content);
|
|
791
|
+
const hasImages = imageUrlBlocks.length > 0 || imageBase64Blocks.length > 0;
|
|
792
|
+
if (entry.role === "system") {
|
|
793
|
+
messages.push({
|
|
794
|
+
role: "system",
|
|
795
|
+
content: textBlocks.map((c) => c.text).join("\n"),
|
|
796
|
+
});
|
|
797
|
+
continue;
|
|
798
|
+
}
|
|
799
|
+
if (entry.role === "assistant") {
|
|
800
|
+
const msg = {
|
|
801
|
+
role: "assistant",
|
|
802
|
+
content: textBlocks.map((c) => c.text).join("\n") || null,
|
|
803
|
+
};
|
|
804
|
+
const reasoning = thinkingBlocks
|
|
805
|
+
.map((block) => block.thinking)
|
|
806
|
+
.filter((thought) => thought.length > 0)
|
|
807
|
+
.join("\n");
|
|
808
|
+
if (reasoning) {
|
|
809
|
+
msg.reasoning = reasoning;
|
|
810
|
+
}
|
|
811
|
+
// The signed/encrypted blocks matter more than the text: OpenRouter
|
|
812
|
+
// rebuilds the upstream provider's native thinking blocks from these,
|
|
813
|
+
// and Anthropic and OpenAI models reject a tool-using turn whose
|
|
814
|
+
// signature did not come back. Only set the key when there is one, so
|
|
815
|
+
// requests for non-reasoning models stay byte-identical.
|
|
816
|
+
const reasoningDetails = thinkingBlocks.flatMap((block) => block.reasoningDetails ?? []);
|
|
817
|
+
if (reasoningDetails.length > 0) {
|
|
818
|
+
msg.reasoningDetails = reasoningDetails;
|
|
819
|
+
}
|
|
820
|
+
if (toolUseBlocks.length > 0) {
|
|
821
|
+
msg.toolCalls = toolUseBlocks.map((block) => ({
|
|
822
|
+
id: block.id,
|
|
823
|
+
type: "function",
|
|
824
|
+
function: {
|
|
825
|
+
name: block.name,
|
|
826
|
+
arguments: JSON.stringify(block.input),
|
|
827
|
+
},
|
|
828
|
+
}));
|
|
829
|
+
}
|
|
830
|
+
messages.push(msg);
|
|
831
|
+
continue;
|
|
832
|
+
}
|
|
833
|
+
// User role — text, images, or tool results
|
|
834
|
+
if (toolResultBlocks.length > 0) {
|
|
835
|
+
for (const result of toolResultBlocks) {
|
|
836
|
+
messages.push({
|
|
837
|
+
role: "tool",
|
|
838
|
+
toolCallId: result.tool_use_id,
|
|
839
|
+
content: result.content,
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
else if (hasImages) {
|
|
844
|
+
const parts = [];
|
|
845
|
+
for (const block of entry.content) {
|
|
846
|
+
if ((0, types_1.isTextContent)(block)) {
|
|
847
|
+
parts.push({ type: "text", text: block.text });
|
|
848
|
+
}
|
|
849
|
+
else if ((0, types_1.isImageUrlContent)(block)) {
|
|
850
|
+
parts.push({
|
|
851
|
+
type: "image_url",
|
|
852
|
+
imageUrl: {
|
|
853
|
+
url: block.url,
|
|
854
|
+
...(block.detail ? { detail: block.detail } : {}),
|
|
855
|
+
},
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
else if ((0, types_1.isImageBase64Content)(block)) {
|
|
859
|
+
parts.push({
|
|
860
|
+
type: "image_url",
|
|
861
|
+
imageUrl: { url: `data:${block.mimeType};base64,${block.data}` },
|
|
862
|
+
});
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
messages.push({ role: "user", content: parts });
|
|
866
|
+
}
|
|
867
|
+
else if (textBlocks.length > 0) {
|
|
868
|
+
messages.push({
|
|
869
|
+
role: "user",
|
|
870
|
+
content: textBlocks.map((c) => c.text).join("\n"),
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
return messages;
|
|
875
|
+
},
|
|
876
|
+
/**
|
|
877
|
+
* Convert an OpenRouter assistant message to a normalized HistoryEntry.
|
|
878
|
+
*/
|
|
879
|
+
fromProviderMessage(message) {
|
|
880
|
+
const content = [];
|
|
881
|
+
// Reasoning first, matching the order the model produced it in. Both the
|
|
882
|
+
// plain text and the opaque details are kept: the text is what a caller
|
|
883
|
+
// reads, the details are what the next request has to echo back.
|
|
884
|
+
const reasoningText = typeof message.reasoning === "string" ? message.reasoning : "";
|
|
885
|
+
const reasoningDetails = message.reasoningDetails ?? [];
|
|
886
|
+
if (reasoningText || reasoningDetails.length > 0) {
|
|
887
|
+
content.push((0, types_1.thinking)(reasoningText, undefined, undefined, reasoningDetails));
|
|
888
|
+
}
|
|
889
|
+
if (typeof message.content === "string" && message.content) {
|
|
890
|
+
content.push((0, types_1.text)(message.content));
|
|
891
|
+
}
|
|
892
|
+
if (message.toolCalls) {
|
|
893
|
+
message.toolCalls.forEach((call) => {
|
|
894
|
+
if (!call.function)
|
|
895
|
+
return;
|
|
896
|
+
const args = JSON.parse(call.function.arguments || "{}");
|
|
897
|
+
content.push((0, types_1.toolUse)(call.id, call.function.name, args));
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
return {
|
|
901
|
+
role: "assistant",
|
|
902
|
+
content,
|
|
903
|
+
meta: { provider: "openrouter" },
|
|
904
|
+
};
|
|
905
|
+
},
|
|
906
|
+
/**
|
|
907
|
+
* Create a normalized tool result entry for an OpenRouter tool call
|
|
908
|
+
*/
|
|
909
|
+
toolResultEntry(tool_call_id, output) {
|
|
910
|
+
return {
|
|
911
|
+
role: "user",
|
|
912
|
+
content: [(0, types_1.toolResult)(tool_call_id, output)],
|
|
913
|
+
meta: { provider: "openrouter", tool_call_id },
|
|
914
|
+
};
|
|
915
|
+
},
|
|
916
|
+
};
|
|
762
917
|
//# sourceMappingURL=transformers.js.map
|
package/dist/history/types.d.ts
CHANGED
|
@@ -51,6 +51,19 @@ export type ThinkingContent = {
|
|
|
51
51
|
thinking: string;
|
|
52
52
|
signature?: string;
|
|
53
53
|
redactedData?: string;
|
|
54
|
+
/**
|
|
55
|
+
* Provider-opaque reasoning blocks that have to be echoed back verbatim.
|
|
56
|
+
*
|
|
57
|
+
* OpenRouter returns `reasoning_details` beside the plain `reasoning` text and
|
|
58
|
+
* requires them back on the next request — the `reasoning.encrypted` variant
|
|
59
|
+
* carries the upstream provider's signed thinking (Anthropic's `signature`,
|
|
60
|
+
* OpenAI's encrypted reasoning), which cannot be reconstructed from the text.
|
|
61
|
+
* Dropping them makes a multi-turn tool call fail on those models.
|
|
62
|
+
*
|
|
63
|
+
* Nothing here reads the contents; they only have to survive the round trip,
|
|
64
|
+
* so they stay untyped rather than modelling every provider's block shapes.
|
|
65
|
+
*/
|
|
66
|
+
reasoningDetails?: unknown[];
|
|
54
67
|
};
|
|
55
68
|
/**
|
|
56
69
|
* Supported image MIME types across all providers
|
|
@@ -124,10 +137,17 @@ export type LlamaCppMeta = {
|
|
|
124
137
|
provider: "llamacpp";
|
|
125
138
|
tool_call_id?: string;
|
|
126
139
|
};
|
|
140
|
+
/**
|
|
141
|
+
* OpenRouter-specific metadata
|
|
142
|
+
*/
|
|
143
|
+
export type OpenRouterMeta = {
|
|
144
|
+
provider: "openrouter";
|
|
145
|
+
tool_call_id?: string;
|
|
146
|
+
};
|
|
127
147
|
/**
|
|
128
148
|
* Union of all provider metadata types
|
|
129
149
|
*/
|
|
130
|
-
export type ProviderMeta = AnthropicMeta | OpenAiMeta | MistralMeta | GeminiMeta | OllamaMeta | LlamaCppMeta;
|
|
150
|
+
export type ProviderMeta = AnthropicMeta | OpenAiMeta | MistralMeta | GeminiMeta | OllamaMeta | LlamaCppMeta | OpenRouterMeta;
|
|
131
151
|
/**
|
|
132
152
|
* Valid roles for history entries
|
|
133
153
|
*/
|
|
@@ -187,7 +207,7 @@ export declare function toolUse(id: string, name: string, input: Record<string,
|
|
|
187
207
|
/**
|
|
188
208
|
* Create a thinking content block. Pass `redactedData` for redacted thinking.
|
|
189
209
|
*/
|
|
190
|
-
export declare function thinking(thinkingText: string, signature?: string, redactedData?: string): ThinkingContent;
|
|
210
|
+
export declare function thinking(thinkingText: string, signature?: string, redactedData?: string, reasoningDetails?: unknown[]): ThinkingContent;
|
|
191
211
|
/**
|
|
192
212
|
* Create a tool result content block
|
|
193
213
|
*/
|
package/dist/history/types.js
CHANGED
|
@@ -70,8 +70,19 @@ function toolUse(id, name, input, thoughtSignature) {
|
|
|
70
70
|
/**
|
|
71
71
|
* Create a thinking content block. Pass `redactedData` for redacted thinking.
|
|
72
72
|
*/
|
|
73
|
-
function thinking(thinkingText, signature, redactedData) {
|
|
74
|
-
|
|
73
|
+
function thinking(thinkingText, signature, redactedData, reasoningDetails) {
|
|
74
|
+
// As in `toolUse()`, only set the passthrough key when there is something in
|
|
75
|
+
// it, so a block stored without details serializes exactly as it did before
|
|
76
|
+
// the field existed.
|
|
77
|
+
return {
|
|
78
|
+
type: "thinking",
|
|
79
|
+
thinking: thinkingText,
|
|
80
|
+
signature,
|
|
81
|
+
redactedData,
|
|
82
|
+
...(reasoningDetails && reasoningDetails.length > 0
|
|
83
|
+
? { reasoningDetails }
|
|
84
|
+
: {}),
|
|
85
|
+
};
|
|
75
86
|
}
|
|
76
87
|
/**
|
|
77
88
|
* Create a tool result content block
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,9 @@ export { LlamaCppAgent } from "./agents/llamacpp/LlamaCppAgent";
|
|
|
11
11
|
export type { LlamaCppModelCard, LlamaCppModelMeta, } from "./agents/llamacpp/LlamaCppAgent";
|
|
12
12
|
export { OpenAICompatibleAgent } from "./agents/openai-compatible/OpenAICompatibleAgent";
|
|
13
13
|
export type { OpenAICompatibleConfig, StreamChunk } from "./agents/openai-compatible/OpenAICompatibleAgent";
|
|
14
|
+
export { OpenRouterAgent } from "./agents/openrouter/OpenRouterAgent";
|
|
15
|
+
export type { OpenRouterConfig, OpenRouterModelCard, } from "./agents/openrouter/OpenRouterAgent";
|
|
16
|
+
export type { OpenRouterProviderPreferences, OpenRouterProviderSort, OpenRouterMaxPrice, OpenRouterReasoningConfig, OpenRouterReasoningEffort, OpenRouterRetryConfig, OpenRouterGenerationInfo, } from "./agents/openrouter/types";
|
|
14
17
|
export * from "./agents/model-types";
|
|
15
18
|
export * from "./agents/AgentConfig";
|
|
16
19
|
export * from "./agents/AgentEvent";
|
|
@@ -18,7 +21,7 @@ export * from "./agents/errors/AgentError";
|
|
|
18
21
|
export * from "./agents/cancellation";
|
|
19
22
|
export * from "./history/History";
|
|
20
23
|
export * from "./history/types";
|
|
21
|
-
export { anthropicTransformer, openAiTransformer, mistralTransformer, geminiTransformer, ollamaTransformer, chatCompletionsTransformer, } from "./history/transformers";
|
|
24
|
+
export { anthropicTransformer, openAiTransformer, mistralTransformer, geminiTransformer, ollamaTransformer, chatCompletionsTransformer, openRouterTransformer, } from "./history/transformers";
|
|
22
25
|
export * from "./graph/AgentGraph";
|
|
23
26
|
export * from "./tools/Tool";
|
|
24
27
|
export * from "./tools/BuiltInTool";
|
package/dist/index.js
CHANGED
|
@@ -22,7 +22,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
22
22
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.chatCompletionsTransformer = exports.ollamaTransformer = exports.geminiTransformer = exports.mistralTransformer = exports.openAiTransformer = exports.anthropicTransformer = exports.OpenAICompatibleAgent = exports.LlamaCppAgent = exports.OllamaAgent = exports.GEMINI_RETIRED_MODELS = exports.GeminiAgent = exports.MistralAgent = exports.OpenAiAgent = void 0;
|
|
25
|
+
exports.openRouterTransformer = exports.chatCompletionsTransformer = exports.ollamaTransformer = exports.geminiTransformer = exports.mistralTransformer = exports.openAiTransformer = exports.anthropicTransformer = exports.OpenRouterAgent = exports.OpenAICompatibleAgent = exports.LlamaCppAgent = exports.OllamaAgent = exports.GEMINI_RETIRED_MODELS = exports.GeminiAgent = exports.MistralAgent = exports.OpenAiAgent = void 0;
|
|
26
26
|
// Agents
|
|
27
27
|
__exportStar(require("./agents/BaseAgent"), exports);
|
|
28
28
|
__exportStar(require("./agents/anthropic/ClaudeAgent"), exports);
|
|
@@ -39,6 +39,8 @@ var LlamaCppAgent_1 = require("./agents/llamacpp/LlamaCppAgent");
|
|
|
39
39
|
Object.defineProperty(exports, "LlamaCppAgent", { enumerable: true, get: function () { return LlamaCppAgent_1.LlamaCppAgent; } });
|
|
40
40
|
var OpenAICompatibleAgent_1 = require("./agents/openai-compatible/OpenAICompatibleAgent");
|
|
41
41
|
Object.defineProperty(exports, "OpenAICompatibleAgent", { enumerable: true, get: function () { return OpenAICompatibleAgent_1.OpenAICompatibleAgent; } });
|
|
42
|
+
var OpenRouterAgent_1 = require("./agents/openrouter/OpenRouterAgent");
|
|
43
|
+
Object.defineProperty(exports, "OpenRouterAgent", { enumerable: true, get: function () { return OpenRouterAgent_1.OpenRouterAgent; } });
|
|
42
44
|
__exportStar(require("./agents/model-types"), exports);
|
|
43
45
|
__exportStar(require("./agents/AgentConfig"), exports);
|
|
44
46
|
__exportStar(require("./agents/AgentEvent"), exports);
|
|
@@ -54,6 +56,7 @@ Object.defineProperty(exports, "mistralTransformer", { enumerable: true, get: fu
|
|
|
54
56
|
Object.defineProperty(exports, "geminiTransformer", { enumerable: true, get: function () { return transformers_1.geminiTransformer; } });
|
|
55
57
|
Object.defineProperty(exports, "ollamaTransformer", { enumerable: true, get: function () { return transformers_1.ollamaTransformer; } });
|
|
56
58
|
Object.defineProperty(exports, "chatCompletionsTransformer", { enumerable: true, get: function () { return transformers_1.chatCompletionsTransformer; } });
|
|
59
|
+
Object.defineProperty(exports, "openRouterTransformer", { enumerable: true, get: function () { return transformers_1.openRouterTransformer; } });
|
|
57
60
|
// Graph
|
|
58
61
|
__exportStar(require("./graph/AgentGraph"), exports);
|
|
59
62
|
// Tools
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from "./core";
|
|
2
|
+
export { OpenRouterAgent } from "./agents/openrouter/OpenRouterAgent";
|
|
3
|
+
export type { OpenRouterConfig, OpenRouterModelCard, StreamChunk, } from "./agents/openrouter/OpenRouterAgent";
|
|
4
|
+
export type { OpenRouterProviderPreferences, OpenRouterProviderSort, OpenRouterMaxPrice, OpenRouterReasoningConfig, OpenRouterReasoningEffort, OpenRouterRetryConfig, OpenRouterGenerationInfo, } from "./agents/openrouter/types";
|
|
5
|
+
export { openRouterTransformer } from "./history/transformers";
|
|
6
|
+
//# sourceMappingURL=openrouter.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.openRouterTransformer = exports.OpenRouterAgent = void 0;
|
|
18
|
+
// OpenRouter Agent Entry Point
|
|
19
|
+
__exportStar(require("./core"), exports);
|
|
20
|
+
var OpenRouterAgent_1 = require("./agents/openrouter/OpenRouterAgent");
|
|
21
|
+
Object.defineProperty(exports, "OpenRouterAgent", { enumerable: true, get: function () { return OpenRouterAgent_1.OpenRouterAgent; } });
|
|
22
|
+
var transformers_1 = require("./history/transformers");
|
|
23
|
+
Object.defineProperty(exports, "openRouterTransformer", { enumerable: true, get: function () { return transformers_1.openRouterTransformer; } });
|
|
24
|
+
//# sourceMappingURL=openrouter.js.map
|
package/dist/viz/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Visualization event types and interfaces for agent monitoring.
|
|
3
3
|
* These types define the contract between agention-lib and @agention/viz.
|
|
4
4
|
*/
|
|
5
|
-
export type VizVendor = "anthropic" | "openai" | "mistral" | "gemini" | "ollama" | "llamacpp";
|
|
5
|
+
export type VizVendor = "anthropic" | "openai" | "mistral" | "gemini" | "ollama" | "llamacpp" | "openrouter";
|
|
6
6
|
export type VizEventType = "session.start" | "session.end" | "pipeline.start" | "pipeline.end" | "executor.start" | "executor.end" | "agent.start" | "agent.complete" | "agent.error" | "tool.start" | "tool.complete" | "tool.error" | "message.user" | "message.assistant";
|
|
7
7
|
export type VizExecutorType = "sequential" | "parallel" | "map" | "voting" | "router";
|
|
8
8
|
export type VizStopReason = "end_turn" | "tool_use" | "max_tokens" | "stop_sequence" | "error";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentionai/agents",
|
|
3
3
|
"author": "Laurent Zuijdwijk",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.8.0",
|
|
5
5
|
"description": "Agent Library",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -38,6 +38,10 @@
|
|
|
38
38
|
"types": "./dist/llamacpp.d.ts",
|
|
39
39
|
"default": "./dist/llamacpp.js"
|
|
40
40
|
},
|
|
41
|
+
"./openrouter": {
|
|
42
|
+
"types": "./dist/openrouter.d.ts",
|
|
43
|
+
"default": "./dist/openrouter.js"
|
|
44
|
+
},
|
|
41
45
|
"./embeddings": {
|
|
42
46
|
"types": "./dist/embeddings/index.d.ts",
|
|
43
47
|
"default": "./dist/embeddings/index.js"
|
|
@@ -114,6 +118,7 @@
|
|
|
114
118
|
"@lancedb/lancedb": "^0.23.0",
|
|
115
119
|
"@mistralai/mistralai": "^1.13.0",
|
|
116
120
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
121
|
+
"@openrouter/sdk": "^1.2.37",
|
|
117
122
|
"@types/jest": "^29.5.0",
|
|
118
123
|
"@types/node": "^18.15.11",
|
|
119
124
|
"apache-arrow": "^18.1.0",
|
|
@@ -145,6 +150,7 @@
|
|
|
145
150
|
"@lancedb/lancedb": "^0.23.0",
|
|
146
151
|
"@mistralai/mistralai": "^1.13.0",
|
|
147
152
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
153
|
+
"@openrouter/sdk": "^1.2.29",
|
|
148
154
|
"apache-arrow": "^18.0.0",
|
|
149
155
|
"ollama": "^0.5.18",
|
|
150
156
|
"openai": "^6.16.0",
|
|
@@ -180,6 +186,9 @@
|
|
|
180
186
|
},
|
|
181
187
|
"ollama": {
|
|
182
188
|
"optional": true
|
|
189
|
+
},
|
|
190
|
+
"@openrouter/sdk": {
|
|
191
|
+
"optional": true
|
|
183
192
|
}
|
|
184
193
|
},
|
|
185
194
|
"dependencies": {
|