@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/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
- run(request: RuntimeRequest): Promise<RuntimeResponse>;
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
- export { type AdvisorPolicy, type ApplyPatchPolicy, type CompiledOpenRouterRequest, type DatetimePolicy, type FusionPolicy, type ImageGenerationPolicy, OpenRouterHttpError, type OpenRouterRuntime, type OpenRouterRuntimeOptions, 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 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, isRuntimeLoggingEnabled };
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
- run(request: RuntimeRequest): Promise<RuntimeResponse>;
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
- export { type AdvisorPolicy, type ApplyPatchPolicy, type CompiledOpenRouterRequest, type DatetimePolicy, type FusionPolicy, type ImageGenerationPolicy, OpenRouterHttpError, type OpenRouterRuntime, type OpenRouterRuntimeOptions, 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 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, isRuntimeLoggingEnabled };
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 ? { "X-Title": 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(serverTools),
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 body = apiMode === "chat" ? buildChatBody(request, baseBody) : buildResponsesBody(request, baseBody);
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, { streaming: true });
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
- async run(request) {
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, { streaming: false });
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
- isRuntimeLoggingEnabled
1918
+ decodeProviderMetadata,
1919
+ isRuntimeLoggingEnabled,
1920
+ toProviderMetadata
1795
1921
  };
1796
1922
  //# sourceMappingURL=index.js.map