@x12i/openrouter-runtime 1.1.0 → 1.4.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/LICENSE +21 -21
- package/README.md +160 -145
- package/dist/index.cjs +153 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -5
- package/dist/index.d.ts +60 -5
- package/dist/index.js +149 -23
- package/dist/index.js.map +1 -1
- package/package.json +41 -41
package/dist/index.d.cts
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
type ApiMode = "chat" | "responses" | "auto";
|
|
2
2
|
type ResolvedApiMode = "chat" | "responses";
|
|
3
3
|
type ToolMode = "disabled" | "allowed" | "required";
|
|
4
|
+
interface RuntimeCallOptions {
|
|
5
|
+
/** Merged onto the compiled JSON body after known fields are assembled. */
|
|
6
|
+
finalizeBody?: (body: Record<string, unknown>) => Record<string, unknown>;
|
|
7
|
+
/**
|
|
8
|
+
* Reads reasoning text from one chat delta.
|
|
9
|
+
* Returned text is emitted as `stream.reasoning.delta` and is not copied into answer text.
|
|
10
|
+
*/
|
|
11
|
+
extractStreamReasoning?: (delta: unknown) => string | undefined;
|
|
12
|
+
/** When true, fusion/advisor/subagent tools do not inherit `request.reasoning`. */
|
|
13
|
+
suppressNestedReasoningFallback?: boolean;
|
|
14
|
+
}
|
|
4
15
|
interface OpenRouterRuntime {
|
|
5
|
-
|
|
16
|
+
compile(request: RuntimeRequest, call?: RuntimeCallOptions): CompiledOpenRouterRequest;
|
|
17
|
+
run(request: RuntimeRequest, call?: RuntimeCallOptions): Promise<RuntimeResponse>;
|
|
6
18
|
/**
|
|
7
19
|
* Explicit streaming chat API. Separate from `run()` by design — never an argument, never the default.
|
|
8
20
|
* Always sends OpenRouter Chat Completions with `stream: true` and yields typed SSE events.
|
|
9
21
|
* The old `stream()` name was removed so mistaken/old clients break loudly.
|
|
10
22
|
*/
|
|
11
|
-
executeStreamingChat(request: RuntimeRequest): AsyncIterable<RuntimeStreamEvent>;
|
|
23
|
+
executeStreamingChat(request: RuntimeRequest, call?: RuntimeCallOptions): AsyncIterable<RuntimeStreamEvent>;
|
|
12
24
|
}
|
|
13
25
|
interface OpenRouterRuntimeOptions {
|
|
14
26
|
apiKey?: string;
|
|
@@ -59,6 +71,16 @@ interface RuntimeRequest {
|
|
|
59
71
|
functionTools?: RuntimeFunctionToolDefinition[];
|
|
60
72
|
toolChoice?: RuntimeToolChoice;
|
|
61
73
|
execution?: RuntimeExecutionPolicy;
|
|
74
|
+
/**
|
|
75
|
+
* Optional agent id for this call.
|
|
76
|
+
* OpenRouter sends it as the activity-log App name (`X-Title` and `X-OpenRouter-Title`).
|
|
77
|
+
* It is also stored in the provider metadata record as `agentId`.
|
|
78
|
+
*/
|
|
79
|
+
agentId?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Optional metadata. String, number, and boolean values are stored in the one provider
|
|
82
|
+
* metadata record. Objects and arrays stay on the normalized response.
|
|
83
|
+
*/
|
|
62
84
|
metadata?: Record<string, unknown>;
|
|
63
85
|
rawOpenRouterOverrides?: Record<string, unknown>;
|
|
64
86
|
}
|
|
@@ -179,6 +201,7 @@ interface FusionPolicy {
|
|
|
179
201
|
maxToolCalls?: number;
|
|
180
202
|
maxCompletionTokens?: number;
|
|
181
203
|
reasoning?: RuntimeReasoningConfig;
|
|
204
|
+
reasoningEffort?: "minimal" | "low" | "medium" | "high" | "max";
|
|
182
205
|
temperature?: number;
|
|
183
206
|
}
|
|
184
207
|
interface AdvisorPolicy {
|
|
@@ -192,6 +215,7 @@ interface AdvisorPolicy {
|
|
|
192
215
|
maxToolCalls?: number;
|
|
193
216
|
maxCompletionTokens?: number;
|
|
194
217
|
reasoning?: RuntimeReasoningConfig;
|
|
218
|
+
reasoningEffort?: "minimal" | "low" | "medium" | "high" | "max";
|
|
195
219
|
temperature?: number;
|
|
196
220
|
}
|
|
197
221
|
interface SubagentPolicy {
|
|
@@ -202,6 +226,7 @@ interface SubagentPolicy {
|
|
|
202
226
|
maxToolCalls?: number;
|
|
203
227
|
maxCompletionTokens?: number;
|
|
204
228
|
reasoning?: RuntimeReasoningConfig;
|
|
229
|
+
reasoningEffort?: "minimal" | "low" | "medium" | "high" | "max";
|
|
205
230
|
temperature?: number;
|
|
206
231
|
}
|
|
207
232
|
type NestedOpenRouterServerToolPolicy = {
|
|
@@ -369,7 +394,7 @@ interface RuntimeStreamEvent {
|
|
|
369
394
|
requestId: string;
|
|
370
395
|
data?: unknown;
|
|
371
396
|
}
|
|
372
|
-
type RuntimeStreamEventType = "stream.start" | "stream.text.delta" | "stream.tool_call.delta" | "stream.usage" | "stream.warning" | "stream.error" | "stream.done";
|
|
397
|
+
type RuntimeStreamEventType = "stream.start" | "stream.text.delta" | "stream.reasoning.delta" | "stream.tool_call.delta" | "stream.usage" | "stream.warning" | "stream.error" | "stream.done";
|
|
373
398
|
interface RuntimeStreamStartEvent extends RuntimeStreamEvent {
|
|
374
399
|
type: "stream.start";
|
|
375
400
|
data: {
|
|
@@ -384,6 +409,12 @@ interface RuntimeStreamTextDeltaEvent extends RuntimeStreamEvent {
|
|
|
384
409
|
text: string;
|
|
385
410
|
};
|
|
386
411
|
}
|
|
412
|
+
interface RuntimeStreamReasoningDeltaEvent extends RuntimeStreamEvent {
|
|
413
|
+
type: "stream.reasoning.delta";
|
|
414
|
+
data: {
|
|
415
|
+
text: string;
|
|
416
|
+
};
|
|
417
|
+
}
|
|
387
418
|
interface RuntimeStreamToolCallDeltaEvent extends RuntimeStreamEvent {
|
|
388
419
|
type: "stream.tool_call.delta";
|
|
389
420
|
data: {
|
|
@@ -425,6 +456,9 @@ declare function createOpenRouterRuntime(options: OpenRouterRuntimeOptions): Ope
|
|
|
425
456
|
|
|
426
457
|
interface RuntimeCompileContext {
|
|
427
458
|
streaming: boolean;
|
|
459
|
+
finalizeBody?: (body: Record<string, unknown>) => Record<string, unknown>;
|
|
460
|
+
/** When set, nested tools do not inherit the parent request reasoning object. */
|
|
461
|
+
suppressNestedReasoningFallback?: boolean;
|
|
428
462
|
}
|
|
429
463
|
interface OpenRouterTool {
|
|
430
464
|
type: string;
|
|
@@ -461,9 +495,30 @@ declare class OpenRouterHttpError extends Error {
|
|
|
461
495
|
constructor(status: number, code: ProviderFailureCode, message: string, body?: unknown | undefined, retryable?: boolean, providerAttempts?: ProviderAttemptError[]);
|
|
462
496
|
}
|
|
463
497
|
|
|
464
|
-
declare function buildOpenRouterServerTools(policy?: RuntimeServerToolsPolicy): OpenRouterTool[];
|
|
498
|
+
declare function buildOpenRouterServerTools(policy?: RuntimeServerToolsPolicy, fallbackReasoning?: RuntimeReasoningConfig): OpenRouterTool[];
|
|
465
499
|
|
|
466
500
|
declare function isRuntimeLoggingEnabled(env?: Record<string, string | undefined> | undefined): boolean;
|
|
467
501
|
declare function createConsoleLogger(): RuntimeLogger;
|
|
468
502
|
|
|
469
|
-
|
|
503
|
+
interface ProviderMetadataLimits {
|
|
504
|
+
maxPairs: number;
|
|
505
|
+
maxKeyLength: number;
|
|
506
|
+
maxValueLength: number;
|
|
507
|
+
keyPattern?: RegExp;
|
|
508
|
+
valuePattern?: RegExp;
|
|
509
|
+
}
|
|
510
|
+
/** OpenRouter and OpenAI metadata: 16 pairs, 64-character keys, 512-character values. */
|
|
511
|
+
declare const OPENROUTER_METADATA_LIMITS: ProviderMetadataLimits;
|
|
512
|
+
/**
|
|
513
|
+
* One provider metadata record.
|
|
514
|
+
* Callers pass `metadata` and `agentId`. Every provider stores the same `m.0`, `m.1`, ...
|
|
515
|
+
* pairs: base64 of the UTF-8 JSON string map, 256 characters per pair, at most 16 pairs.
|
|
516
|
+
* `decodeProviderMetadata` restores that map from any provider log.
|
|
517
|
+
* `limits` stays on the signature for existing callers. The record uses the strictest
|
|
518
|
+
* provider limits, so the pairs do not change between providers.
|
|
519
|
+
*/
|
|
520
|
+
declare function toProviderMetadata(metadata: Record<string, unknown> | undefined, agentId: string | undefined, _limits: ProviderMetadataLimits, base: Record<string, unknown> | undefined): Record<string, string> | undefined;
|
|
521
|
+
/** Restores the string map from the `m.0`, `m.1`, ... pairs stored on a provider log. */
|
|
522
|
+
declare function decodeProviderMetadata(wire: unknown): Record<string, string>;
|
|
523
|
+
|
|
524
|
+
export { type AdvisorPolicy, type ApplyPatchPolicy, type CompiledOpenRouterRequest, type DatetimePolicy, type FusionPolicy, type ImageGenerationPolicy, OPENROUTER_METADATA_LIMITS, OpenRouterHttpError, type OpenRouterRuntime, type OpenRouterRuntimeOptions, type ProviderMetadataLimits, type RuntimeCallOptions, type RuntimeCitation, RuntimeConfigError, type RuntimeDefaults, type RuntimeError, type RuntimeFunctionToolDefinition, type RuntimeGeneratedImage, type RuntimeLogger, type RuntimeMessage, type RuntimePatchProposal, type RuntimePolicyViolation, type RuntimeRequest, type RuntimeResponse, type RuntimeServerToolsPolicy, type RuntimeStreamDoneEvent, type RuntimeStreamErrorEvent, type RuntimeStreamEvent, type RuntimeStreamEventType, type RuntimeStreamReasoningDeltaEvent, type RuntimeStreamStartEvent, type RuntimeStreamTextDeltaEvent, type RuntimeStreamToolCallDeltaEvent, type RuntimeStreamUsageEvent, type RuntimeStreamWarningEvent, type RuntimeToolExecutor, type RuntimeToolUsage, type RuntimeUsage, type RuntimeWarning, type ServerToolKey, type ServerToolUsage, type SubagentPolicy, type WebFetchPolicy, type WebSearchPolicy, buildOpenRouterServerTools, compileRuntimeRequest, createConsoleLogger, createOpenRouterRuntime, decodeProviderMetadata, isRuntimeLoggingEnabled, toProviderMetadata };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
type ApiMode = "chat" | "responses" | "auto";
|
|
2
2
|
type ResolvedApiMode = "chat" | "responses";
|
|
3
3
|
type ToolMode = "disabled" | "allowed" | "required";
|
|
4
|
+
interface RuntimeCallOptions {
|
|
5
|
+
/** Merged onto the compiled JSON body after known fields are assembled. */
|
|
6
|
+
finalizeBody?: (body: Record<string, unknown>) => Record<string, unknown>;
|
|
7
|
+
/**
|
|
8
|
+
* Reads reasoning text from one chat delta.
|
|
9
|
+
* Returned text is emitted as `stream.reasoning.delta` and is not copied into answer text.
|
|
10
|
+
*/
|
|
11
|
+
extractStreamReasoning?: (delta: unknown) => string | undefined;
|
|
12
|
+
/** When true, fusion/advisor/subagent tools do not inherit `request.reasoning`. */
|
|
13
|
+
suppressNestedReasoningFallback?: boolean;
|
|
14
|
+
}
|
|
4
15
|
interface OpenRouterRuntime {
|
|
5
|
-
|
|
16
|
+
compile(request: RuntimeRequest, call?: RuntimeCallOptions): CompiledOpenRouterRequest;
|
|
17
|
+
run(request: RuntimeRequest, call?: RuntimeCallOptions): Promise<RuntimeResponse>;
|
|
6
18
|
/**
|
|
7
19
|
* Explicit streaming chat API. Separate from `run()` by design — never an argument, never the default.
|
|
8
20
|
* Always sends OpenRouter Chat Completions with `stream: true` and yields typed SSE events.
|
|
9
21
|
* The old `stream()` name was removed so mistaken/old clients break loudly.
|
|
10
22
|
*/
|
|
11
|
-
executeStreamingChat(request: RuntimeRequest): AsyncIterable<RuntimeStreamEvent>;
|
|
23
|
+
executeStreamingChat(request: RuntimeRequest, call?: RuntimeCallOptions): AsyncIterable<RuntimeStreamEvent>;
|
|
12
24
|
}
|
|
13
25
|
interface OpenRouterRuntimeOptions {
|
|
14
26
|
apiKey?: string;
|
|
@@ -59,6 +71,16 @@ interface RuntimeRequest {
|
|
|
59
71
|
functionTools?: RuntimeFunctionToolDefinition[];
|
|
60
72
|
toolChoice?: RuntimeToolChoice;
|
|
61
73
|
execution?: RuntimeExecutionPolicy;
|
|
74
|
+
/**
|
|
75
|
+
* Optional agent id for this call.
|
|
76
|
+
* OpenRouter sends it as the activity-log App name (`X-Title` and `X-OpenRouter-Title`).
|
|
77
|
+
* It is also stored in the provider metadata record as `agentId`.
|
|
78
|
+
*/
|
|
79
|
+
agentId?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Optional metadata. String, number, and boolean values are stored in the one provider
|
|
82
|
+
* metadata record. Objects and arrays stay on the normalized response.
|
|
83
|
+
*/
|
|
62
84
|
metadata?: Record<string, unknown>;
|
|
63
85
|
rawOpenRouterOverrides?: Record<string, unknown>;
|
|
64
86
|
}
|
|
@@ -179,6 +201,7 @@ interface FusionPolicy {
|
|
|
179
201
|
maxToolCalls?: number;
|
|
180
202
|
maxCompletionTokens?: number;
|
|
181
203
|
reasoning?: RuntimeReasoningConfig;
|
|
204
|
+
reasoningEffort?: "minimal" | "low" | "medium" | "high" | "max";
|
|
182
205
|
temperature?: number;
|
|
183
206
|
}
|
|
184
207
|
interface AdvisorPolicy {
|
|
@@ -192,6 +215,7 @@ interface AdvisorPolicy {
|
|
|
192
215
|
maxToolCalls?: number;
|
|
193
216
|
maxCompletionTokens?: number;
|
|
194
217
|
reasoning?: RuntimeReasoningConfig;
|
|
218
|
+
reasoningEffort?: "minimal" | "low" | "medium" | "high" | "max";
|
|
195
219
|
temperature?: number;
|
|
196
220
|
}
|
|
197
221
|
interface SubagentPolicy {
|
|
@@ -202,6 +226,7 @@ interface SubagentPolicy {
|
|
|
202
226
|
maxToolCalls?: number;
|
|
203
227
|
maxCompletionTokens?: number;
|
|
204
228
|
reasoning?: RuntimeReasoningConfig;
|
|
229
|
+
reasoningEffort?: "minimal" | "low" | "medium" | "high" | "max";
|
|
205
230
|
temperature?: number;
|
|
206
231
|
}
|
|
207
232
|
type NestedOpenRouterServerToolPolicy = {
|
|
@@ -369,7 +394,7 @@ interface RuntimeStreamEvent {
|
|
|
369
394
|
requestId: string;
|
|
370
395
|
data?: unknown;
|
|
371
396
|
}
|
|
372
|
-
type RuntimeStreamEventType = "stream.start" | "stream.text.delta" | "stream.tool_call.delta" | "stream.usage" | "stream.warning" | "stream.error" | "stream.done";
|
|
397
|
+
type RuntimeStreamEventType = "stream.start" | "stream.text.delta" | "stream.reasoning.delta" | "stream.tool_call.delta" | "stream.usage" | "stream.warning" | "stream.error" | "stream.done";
|
|
373
398
|
interface RuntimeStreamStartEvent extends RuntimeStreamEvent {
|
|
374
399
|
type: "stream.start";
|
|
375
400
|
data: {
|
|
@@ -384,6 +409,12 @@ interface RuntimeStreamTextDeltaEvent extends RuntimeStreamEvent {
|
|
|
384
409
|
text: string;
|
|
385
410
|
};
|
|
386
411
|
}
|
|
412
|
+
interface RuntimeStreamReasoningDeltaEvent extends RuntimeStreamEvent {
|
|
413
|
+
type: "stream.reasoning.delta";
|
|
414
|
+
data: {
|
|
415
|
+
text: string;
|
|
416
|
+
};
|
|
417
|
+
}
|
|
387
418
|
interface RuntimeStreamToolCallDeltaEvent extends RuntimeStreamEvent {
|
|
388
419
|
type: "stream.tool_call.delta";
|
|
389
420
|
data: {
|
|
@@ -425,6 +456,9 @@ declare function createOpenRouterRuntime(options: OpenRouterRuntimeOptions): Ope
|
|
|
425
456
|
|
|
426
457
|
interface RuntimeCompileContext {
|
|
427
458
|
streaming: boolean;
|
|
459
|
+
finalizeBody?: (body: Record<string, unknown>) => Record<string, unknown>;
|
|
460
|
+
/** When set, nested tools do not inherit the parent request reasoning object. */
|
|
461
|
+
suppressNestedReasoningFallback?: boolean;
|
|
428
462
|
}
|
|
429
463
|
interface OpenRouterTool {
|
|
430
464
|
type: string;
|
|
@@ -461,9 +495,30 @@ declare class OpenRouterHttpError extends Error {
|
|
|
461
495
|
constructor(status: number, code: ProviderFailureCode, message: string, body?: unknown | undefined, retryable?: boolean, providerAttempts?: ProviderAttemptError[]);
|
|
462
496
|
}
|
|
463
497
|
|
|
464
|
-
declare function buildOpenRouterServerTools(policy?: RuntimeServerToolsPolicy): OpenRouterTool[];
|
|
498
|
+
declare function buildOpenRouterServerTools(policy?: RuntimeServerToolsPolicy, fallbackReasoning?: RuntimeReasoningConfig): OpenRouterTool[];
|
|
465
499
|
|
|
466
500
|
declare function isRuntimeLoggingEnabled(env?: Record<string, string | undefined> | undefined): boolean;
|
|
467
501
|
declare function createConsoleLogger(): RuntimeLogger;
|
|
468
502
|
|
|
469
|
-
|
|
503
|
+
interface ProviderMetadataLimits {
|
|
504
|
+
maxPairs: number;
|
|
505
|
+
maxKeyLength: number;
|
|
506
|
+
maxValueLength: number;
|
|
507
|
+
keyPattern?: RegExp;
|
|
508
|
+
valuePattern?: RegExp;
|
|
509
|
+
}
|
|
510
|
+
/** OpenRouter and OpenAI metadata: 16 pairs, 64-character keys, 512-character values. */
|
|
511
|
+
declare const OPENROUTER_METADATA_LIMITS: ProviderMetadataLimits;
|
|
512
|
+
/**
|
|
513
|
+
* One provider metadata record.
|
|
514
|
+
* Callers pass `metadata` and `agentId`. Every provider stores the same `m.0`, `m.1`, ...
|
|
515
|
+
* pairs: base64 of the UTF-8 JSON string map, 256 characters per pair, at most 16 pairs.
|
|
516
|
+
* `decodeProviderMetadata` restores that map from any provider log.
|
|
517
|
+
* `limits` stays on the signature for existing callers. The record uses the strictest
|
|
518
|
+
* provider limits, so the pairs do not change between providers.
|
|
519
|
+
*/
|
|
520
|
+
declare function toProviderMetadata(metadata: Record<string, unknown> | undefined, agentId: string | undefined, _limits: ProviderMetadataLimits, base: Record<string, unknown> | undefined): Record<string, string> | undefined;
|
|
521
|
+
/** Restores the string map from the `m.0`, `m.1`, ... pairs stored on a provider log. */
|
|
522
|
+
declare function decodeProviderMetadata(wire: unknown): Record<string, string>;
|
|
523
|
+
|
|
524
|
+
export { type AdvisorPolicy, type ApplyPatchPolicy, type CompiledOpenRouterRequest, type DatetimePolicy, type FusionPolicy, type ImageGenerationPolicy, OPENROUTER_METADATA_LIMITS, OpenRouterHttpError, type OpenRouterRuntime, type OpenRouterRuntimeOptions, type ProviderMetadataLimits, type RuntimeCallOptions, type RuntimeCitation, RuntimeConfigError, type RuntimeDefaults, type RuntimeError, type RuntimeFunctionToolDefinition, type RuntimeGeneratedImage, type RuntimeLogger, type RuntimeMessage, type RuntimePatchProposal, type RuntimePolicyViolation, type RuntimeRequest, type RuntimeResponse, type RuntimeServerToolsPolicy, type RuntimeStreamDoneEvent, type RuntimeStreamErrorEvent, type RuntimeStreamEvent, type RuntimeStreamEventType, type RuntimeStreamReasoningDeltaEvent, type RuntimeStreamStartEvent, type RuntimeStreamTextDeltaEvent, type RuntimeStreamToolCallDeltaEvent, type RuntimeStreamUsageEvent, type RuntimeStreamWarningEvent, type RuntimeToolExecutor, type RuntimeToolUsage, type RuntimeUsage, type RuntimeWarning, type ServerToolKey, type ServerToolUsage, type SubagentPolicy, type WebFetchPolicy, type WebSearchPolicy, buildOpenRouterServerTools, compileRuntimeRequest, createConsoleLogger, createOpenRouterRuntime, decodeProviderMetadata, isRuntimeLoggingEnabled, toProviderMetadata };
|
package/dist/index.js
CHANGED
|
@@ -722,13 +722,22 @@ function endpointFor(baseUrl, apiMode) {
|
|
|
722
722
|
}
|
|
723
723
|
|
|
724
724
|
// src/openrouter/headers.ts
|
|
725
|
-
function buildHeaders(options) {
|
|
725
|
+
function buildHeaders(options, agentId) {
|
|
726
|
+
const requestAppName = agentId?.trim();
|
|
726
727
|
return {
|
|
727
728
|
"content-type": "application/json",
|
|
728
729
|
authorization: `Bearer ${options.apiKey}`,
|
|
729
730
|
...options.appAttribution?.siteUrl ? { "HTTP-Referer": options.appAttribution.siteUrl } : {},
|
|
730
|
-
...options.appAttribution?.appName
|
|
731
|
-
...options.defaultHeaders ?? {}
|
|
731
|
+
...appTitleHeaders(options.appAttribution?.appName),
|
|
732
|
+
...options.defaultHeaders ?? {},
|
|
733
|
+
...requestAppName ? appTitleHeaders(requestAppName) : {}
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
function appTitleHeaders(name) {
|
|
737
|
+
if (!name) return {};
|
|
738
|
+
return {
|
|
739
|
+
"X-Title": name,
|
|
740
|
+
"X-OpenRouter-Title": name
|
|
732
741
|
};
|
|
733
742
|
}
|
|
734
743
|
|
|
@@ -757,7 +766,7 @@ function cleanParameters(parameters) {
|
|
|
757
766
|
function enabled(policy) {
|
|
758
767
|
return !!policy && policy.mode !== "disabled";
|
|
759
768
|
}
|
|
760
|
-
function buildOpenRouterServerTools(policy) {
|
|
769
|
+
function buildOpenRouterServerTools(policy, fallbackReasoning) {
|
|
761
770
|
const tools = [];
|
|
762
771
|
const webSearch = buildWebSearchTool(policy?.webSearch);
|
|
763
772
|
if (webSearch) tools.push(webSearch);
|
|
@@ -769,10 +778,10 @@ function buildOpenRouterServerTools(policy) {
|
|
|
769
778
|
if (image) tools.push(image);
|
|
770
779
|
const patch = buildApplyPatchTool(policy?.applyPatch);
|
|
771
780
|
if (patch) tools.push(patch);
|
|
772
|
-
const fusion = buildFusionTool(policy?.fusion);
|
|
781
|
+
const fusion = buildFusionTool(policy?.fusion, fallbackReasoning);
|
|
773
782
|
if (fusion) tools.push(fusion);
|
|
774
|
-
tools.push(...buildAdvisorTools(policy?.advisor));
|
|
775
|
-
const subagent = buildSubagentTool(policy?.subagent);
|
|
783
|
+
tools.push(...buildAdvisorTools(policy?.advisor, fallbackReasoning));
|
|
784
|
+
const subagent = buildSubagentTool(policy?.subagent, fallbackReasoning);
|
|
776
785
|
if (subagent) tools.push(subagent);
|
|
777
786
|
return tools;
|
|
778
787
|
}
|
|
@@ -831,7 +840,7 @@ function buildApplyPatchTool(policy) {
|
|
|
831
840
|
if (!enabled(policy)) return void 0;
|
|
832
841
|
return { type: "openrouter:apply_patch" };
|
|
833
842
|
}
|
|
834
|
-
function buildFusionTool(policy) {
|
|
843
|
+
function buildFusionTool(policy, fallbackReasoning) {
|
|
835
844
|
if (!enabled(policy)) return void 0;
|
|
836
845
|
return {
|
|
837
846
|
type: "openrouter:fusion",
|
|
@@ -840,12 +849,12 @@ function buildFusionTool(policy) {
|
|
|
840
849
|
model: policy?.judgeModel,
|
|
841
850
|
max_tool_calls: policy?.maxToolCalls ?? 8,
|
|
842
851
|
max_completion_tokens: policy?.maxCompletionTokens,
|
|
843
|
-
reasoning: policy?.reasoning,
|
|
852
|
+
reasoning: policy?.reasoning ?? fallbackReasoning,
|
|
844
853
|
temperature: policy?.temperature
|
|
845
854
|
})
|
|
846
855
|
};
|
|
847
856
|
}
|
|
848
|
-
function buildAdvisorTools(policy) {
|
|
857
|
+
function buildAdvisorTools(policy, fallbackReasoning) {
|
|
849
858
|
const advisors = Array.isArray(policy) ? policy : policy ? [policy] : [];
|
|
850
859
|
return advisors.filter(enabled).map((advisor) => {
|
|
851
860
|
validateNestedTools(advisor.tools);
|
|
@@ -860,13 +869,13 @@ function buildAdvisorTools(policy) {
|
|
|
860
869
|
stream: advisor.stream,
|
|
861
870
|
max_tool_calls: advisor.maxToolCalls,
|
|
862
871
|
max_completion_tokens: advisor.maxCompletionTokens,
|
|
863
|
-
reasoning: advisor.reasoning,
|
|
872
|
+
reasoning: advisor.reasoning ?? fallbackReasoning,
|
|
864
873
|
temperature: advisor.temperature
|
|
865
874
|
})
|
|
866
875
|
};
|
|
867
876
|
});
|
|
868
877
|
}
|
|
869
|
-
function buildSubagentTool(policy) {
|
|
878
|
+
function buildSubagentTool(policy, fallbackReasoning) {
|
|
870
879
|
if (!policy || policy.mode === "disabled") return void 0;
|
|
871
880
|
const subagent = policy;
|
|
872
881
|
validateNestedTools(subagent.tools);
|
|
@@ -878,12 +887,86 @@ function buildSubagentTool(policy) {
|
|
|
878
887
|
tools: subagent.tools,
|
|
879
888
|
max_tool_calls: subagent.maxToolCalls,
|
|
880
889
|
max_completion_tokens: subagent.maxCompletionTokens,
|
|
881
|
-
reasoning: subagent.reasoning,
|
|
890
|
+
reasoning: subagent.reasoning ?? fallbackReasoning,
|
|
882
891
|
temperature: subagent.temperature
|
|
883
892
|
})
|
|
884
893
|
};
|
|
885
894
|
}
|
|
886
895
|
|
|
896
|
+
// src/utils/provider-metadata.ts
|
|
897
|
+
var OPENROUTER_METADATA_LIMITS = {
|
|
898
|
+
maxPairs: 16,
|
|
899
|
+
maxKeyLength: 64,
|
|
900
|
+
maxValueLength: 512
|
|
901
|
+
};
|
|
902
|
+
var PROVIDER_RECORD_CHUNK = 256;
|
|
903
|
+
var PROVIDER_RECORD_MAX_CHUNKS = 16;
|
|
904
|
+
function toProviderMetadata(metadata, agentId, _limits, base) {
|
|
905
|
+
return encodeProviderRecord(collectProviderStrings(metadata, agentId, base));
|
|
906
|
+
}
|
|
907
|
+
function decodeProviderMetadata(wire) {
|
|
908
|
+
if (!isRecord2(wire)) return {};
|
|
909
|
+
const parts = [];
|
|
910
|
+
for (let index = 0; ; index += 1) {
|
|
911
|
+
const chunk = wire[`m.${index}`];
|
|
912
|
+
if (typeof chunk !== "string") break;
|
|
913
|
+
parts.push(chunk);
|
|
914
|
+
}
|
|
915
|
+
if (!parts.length) return {};
|
|
916
|
+
const parsed = JSON.parse(Buffer.from(parts.join(""), "base64").toString("utf8"));
|
|
917
|
+
if (!isRecord2(parsed)) return {};
|
|
918
|
+
const record = {};
|
|
919
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
920
|
+
if (typeof value === "string") record[key] = value;
|
|
921
|
+
}
|
|
922
|
+
return record;
|
|
923
|
+
}
|
|
924
|
+
function encodeProviderRecord(map) {
|
|
925
|
+
const keys = Object.keys(map).sort();
|
|
926
|
+
if (!keys.length) return void 0;
|
|
927
|
+
const ordered = {};
|
|
928
|
+
for (const key of keys) {
|
|
929
|
+
const value = map[key];
|
|
930
|
+
if (value !== void 0) ordered[key] = value;
|
|
931
|
+
}
|
|
932
|
+
const encoded = Buffer.from(JSON.stringify(ordered), "utf8").toString("base64");
|
|
933
|
+
const chunks = Math.ceil(encoded.length / PROVIDER_RECORD_CHUNK);
|
|
934
|
+
if (chunks > PROVIDER_RECORD_MAX_CHUNKS) {
|
|
935
|
+
throw new Error(
|
|
936
|
+
`METADATA_RECORD_TOO_LARGE: provider metadata is ${encoded.length} base64 characters; the maximum is ${PROVIDER_RECORD_CHUNK * PROVIDER_RECORD_MAX_CHUNKS}.`
|
|
937
|
+
);
|
|
938
|
+
}
|
|
939
|
+
const wire = {};
|
|
940
|
+
for (let index = 0; index < chunks; index += 1) {
|
|
941
|
+
wire[`m.${index}`] = encoded.slice(index * PROVIDER_RECORD_CHUNK, (index + 1) * PROVIDER_RECORD_CHUNK);
|
|
942
|
+
}
|
|
943
|
+
return wire;
|
|
944
|
+
}
|
|
945
|
+
function collectProviderStrings(metadata, agentId, base) {
|
|
946
|
+
const map = {};
|
|
947
|
+
appendStrings(map, base);
|
|
948
|
+
appendStrings(map, metadata);
|
|
949
|
+
const trimmedAgentId = agentId?.trim();
|
|
950
|
+
if (trimmedAgentId) map.agentId = trimmedAgentId;
|
|
951
|
+
return map;
|
|
952
|
+
}
|
|
953
|
+
function appendStrings(target, metadata) {
|
|
954
|
+
if (!metadata) return;
|
|
955
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
956
|
+
const asString = asMetadataString(value);
|
|
957
|
+
if (asString !== void 0) target[key] = asString;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
function asMetadataString(value) {
|
|
961
|
+
if (typeof value === "string") return value;
|
|
962
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
963
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
964
|
+
return void 0;
|
|
965
|
+
}
|
|
966
|
+
function isRecord2(value) {
|
|
967
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
968
|
+
}
|
|
969
|
+
|
|
887
970
|
// src/runtime/runtime.ts
|
|
888
971
|
function compileRuntimeRequest(request, defaults, options = { apiKey: "" }, context = {}) {
|
|
889
972
|
const warnings = [];
|
|
@@ -895,7 +978,10 @@ function compileRuntimeRequest(request, defaults, options = { apiKey: "" }, cont
|
|
|
895
978
|
const apiMode = resolveApiMode(request, defaults.apiMode, serverTools);
|
|
896
979
|
validateRuntimeRequest(request, options, apiMode, normalized.model, serverTools);
|
|
897
980
|
const tools = [
|
|
898
|
-
...buildOpenRouterServerTools(
|
|
981
|
+
...buildOpenRouterServerTools(
|
|
982
|
+
serverTools,
|
|
983
|
+
effectiveContext.suppressNestedReasoningFallback ? void 0 : request.reasoning
|
|
984
|
+
),
|
|
899
985
|
...(request.functionTools ?? []).map((tool) => ({
|
|
900
986
|
type: "function",
|
|
901
987
|
function: {
|
|
@@ -905,10 +991,12 @@ function compileRuntimeRequest(request, defaults, options = { apiKey: "" }, cont
|
|
|
905
991
|
}
|
|
906
992
|
}))
|
|
907
993
|
];
|
|
908
|
-
const headers = buildHeaders(options);
|
|
994
|
+
const headers = buildHeaders(options, request.agentId);
|
|
909
995
|
const baseBody = buildBaseBody(request, normalized.model, defaults, tools, serverTools);
|
|
910
|
-
const
|
|
996
|
+
const assembled = apiMode === "chat" ? buildChatBody(request, baseBody) : buildResponsesBody(request, baseBody);
|
|
997
|
+
let body = effectiveContext.finalizeBody ? effectiveContext.finalizeBody(assembled) : assembled;
|
|
911
998
|
enforceStreamingPolicyForRun(body, warnings, effectiveContext);
|
|
999
|
+
body = attachProviderMetadata(body, request);
|
|
912
1000
|
return {
|
|
913
1001
|
apiMode,
|
|
914
1002
|
url: endpointFor(options.baseUrl ?? "https://openrouter.ai/api/v1", apiMode),
|
|
@@ -917,6 +1005,15 @@ function compileRuntimeRequest(request, defaults, options = { apiKey: "" }, cont
|
|
|
917
1005
|
warnings
|
|
918
1006
|
};
|
|
919
1007
|
}
|
|
1008
|
+
function attachProviderMetadata(body, request) {
|
|
1009
|
+
const fromBody = isRecord(body.metadata) ? body.metadata : void 0;
|
|
1010
|
+
const metadata = toProviderMetadata(request.metadata, request.agentId, OPENROUTER_METADATA_LIMITS, fromBody);
|
|
1011
|
+
if (metadata) return { ...body, metadata };
|
|
1012
|
+
if (body.metadata === void 0) return body;
|
|
1013
|
+
const rest = { ...body };
|
|
1014
|
+
delete rest.metadata;
|
|
1015
|
+
return rest;
|
|
1016
|
+
}
|
|
920
1017
|
function enforceStreamingPolicyForRun(body, warnings, context) {
|
|
921
1018
|
if (context.streaming) {
|
|
922
1019
|
body.stream = true;
|
|
@@ -1450,7 +1547,7 @@ function isRetryableStatus2(status) {
|
|
|
1450
1547
|
}
|
|
1451
1548
|
|
|
1452
1549
|
// src/runtime/streaming.ts
|
|
1453
|
-
async function* executeStreamingChat(request, context) {
|
|
1550
|
+
async function* executeStreamingChat(request, context, call = {}) {
|
|
1454
1551
|
const requestId = request.id ?? "unknown";
|
|
1455
1552
|
const options = context.options;
|
|
1456
1553
|
const defaults = context.defaults;
|
|
@@ -1465,7 +1562,11 @@ async function* executeStreamingChat(request, context) {
|
|
|
1465
1562
|
...request,
|
|
1466
1563
|
apiMode: "chat"
|
|
1467
1564
|
};
|
|
1468
|
-
const compiled = compileRuntimeRequest(streamingRequest, defaults, options, {
|
|
1565
|
+
const compiled = compileRuntimeRequest(streamingRequest, defaults, options, {
|
|
1566
|
+
streaming: true,
|
|
1567
|
+
...call.finalizeBody ? { finalizeBody: call.finalizeBody } : {},
|
|
1568
|
+
...call.suppressNestedReasoningFallback ? { suppressNestedReasoningFallback: true } : {}
|
|
1569
|
+
});
|
|
1469
1570
|
if (compiled.body.stream !== true) {
|
|
1470
1571
|
throw new RuntimeConfigError(
|
|
1471
1572
|
"STREAMING_CHAT_MISCONFIGURED",
|
|
@@ -1500,6 +1601,10 @@ async function* executeStreamingChat(request, context) {
|
|
|
1500
1601
|
if (typeof chunk.model === "string") resolvedModel = chunk.model;
|
|
1501
1602
|
const choice = Array.isArray(chunk.choices) && isRecord(chunk.choices[0]) ? chunk.choices[0] : void 0;
|
|
1502
1603
|
const delta = choice && isRecord(choice.delta) ? choice.delta : void 0;
|
|
1604
|
+
if (delta && call.extractStreamReasoning) {
|
|
1605
|
+
const reasoningText = call.extractStreamReasoning(delta);
|
|
1606
|
+
if (reasoningText) yield reasoningDeltaEvent(requestId, reasoningText);
|
|
1607
|
+
}
|
|
1503
1608
|
if (delta && typeof delta.content === "string" && delta.content.length > 0) {
|
|
1504
1609
|
text += delta.content;
|
|
1505
1610
|
yield textDeltaEvent(requestId, delta.content);
|
|
@@ -1594,6 +1699,13 @@ function textDeltaEvent(requestId, text) {
|
|
|
1594
1699
|
data: { text }
|
|
1595
1700
|
};
|
|
1596
1701
|
}
|
|
1702
|
+
function reasoningDeltaEvent(requestId, text) {
|
|
1703
|
+
return {
|
|
1704
|
+
type: "stream.reasoning.delta",
|
|
1705
|
+
requestId,
|
|
1706
|
+
data: { text }
|
|
1707
|
+
};
|
|
1708
|
+
}
|
|
1597
1709
|
function toolCallDeltaEvent(requestId, data) {
|
|
1598
1710
|
return {
|
|
1599
1711
|
type: "stream.tool_call.delta",
|
|
@@ -1663,7 +1775,14 @@ function createOpenRouterRuntime(options) {
|
|
|
1663
1775
|
const defaults = resolveDefaults(options);
|
|
1664
1776
|
const context = { options: resolvedOptions, defaults };
|
|
1665
1777
|
return {
|
|
1666
|
-
|
|
1778
|
+
compile(request, call) {
|
|
1779
|
+
return compileRuntimeRequest(request, defaults, resolvedOptions, {
|
|
1780
|
+
streaming: false,
|
|
1781
|
+
...call?.finalizeBody ? { finalizeBody: call.finalizeBody } : {},
|
|
1782
|
+
...call?.suppressNestedReasoningFallback ? { suppressNestedReasoningFallback: true } : {}
|
|
1783
|
+
});
|
|
1784
|
+
},
|
|
1785
|
+
async run(request, call) {
|
|
1667
1786
|
const requestWithId = { ...request, id: request.id ?? createRuntimeId() };
|
|
1668
1787
|
try {
|
|
1669
1788
|
resolvedOptions.logger?.info?.("runtime.request.started", {
|
|
@@ -1672,7 +1791,11 @@ function createOpenRouterRuntime(options) {
|
|
|
1672
1791
|
entrypoint: "run"
|
|
1673
1792
|
});
|
|
1674
1793
|
await resolvedOptions.hooks?.beforeCompile?.(requestWithId);
|
|
1675
|
-
const compiled = compileRuntimeRequest(requestWithId, defaults, resolvedOptions, {
|
|
1794
|
+
const compiled = compileRuntimeRequest(requestWithId, defaults, resolvedOptions, {
|
|
1795
|
+
streaming: false,
|
|
1796
|
+
...call?.finalizeBody ? { finalizeBody: call.finalizeBody } : {},
|
|
1797
|
+
...call?.suppressNestedReasoningFallback ? { suppressNestedReasoningFallback: true } : {}
|
|
1798
|
+
});
|
|
1676
1799
|
await resolvedOptions.hooks?.afterCompile?.(compiled);
|
|
1677
1800
|
resolvedOptions.logger?.debug?.("runtime.request.compiled", {
|
|
1678
1801
|
requestId: requestWithId.id,
|
|
@@ -1694,9 +1817,9 @@ function createOpenRouterRuntime(options) {
|
|
|
1694
1817
|
return errorResponse(requestWithId, error);
|
|
1695
1818
|
}
|
|
1696
1819
|
},
|
|
1697
|
-
executeStreamingChat(request) {
|
|
1820
|
+
executeStreamingChat(request, call) {
|
|
1698
1821
|
const requestWithId = { ...request, id: request.id ?? createRuntimeId() };
|
|
1699
|
-
return executeStreamingChat(requestWithId, context);
|
|
1822
|
+
return executeStreamingChat(requestWithId, context, call);
|
|
1700
1823
|
}
|
|
1701
1824
|
};
|
|
1702
1825
|
function errorResponse(request, error) {
|
|
@@ -1785,12 +1908,15 @@ function operatorHintFor(code) {
|
|
|
1785
1908
|
}
|
|
1786
1909
|
}
|
|
1787
1910
|
export {
|
|
1911
|
+
OPENROUTER_METADATA_LIMITS,
|
|
1788
1912
|
OpenRouterHttpError,
|
|
1789
1913
|
RuntimeConfigError,
|
|
1790
1914
|
buildOpenRouterServerTools,
|
|
1791
1915
|
compileRuntimeRequest,
|
|
1792
1916
|
createConsoleLogger,
|
|
1793
1917
|
createOpenRouterRuntime,
|
|
1794
|
-
|
|
1918
|
+
decodeProviderMetadata,
|
|
1919
|
+
isRuntimeLoggingEnabled,
|
|
1920
|
+
toProviderMetadata
|
|
1795
1921
|
};
|
|
1796
1922
|
//# sourceMappingURL=index.js.map
|