@x12i/ai-gateway 10.3.1 → 10.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.
Files changed (66) hide show
  1. package/README.md +92 -1
  2. package/dist/activity-manager.js +33 -0
  3. package/dist/gateway-config.js +15 -0
  4. package/dist/gateway-utils.d.ts +8 -1
  5. package/dist/gateway-utils.js +73 -1
  6. package/dist/gateway.js +18 -3
  7. package/dist/index.d.ts +4 -3
  8. package/dist/index.js +3 -2
  9. package/dist/instruction-errors.d.ts +21 -0
  10. package/dist/instruction-errors.js +36 -0
  11. package/dist/openrouter-runtime-adapter/create-openrouter-runtime-adapter.d.ts +23 -0
  12. package/dist/openrouter-runtime-adapter/create-openrouter-runtime-adapter.js +31 -0
  13. package/dist/openrouter-runtime-adapter/create-openrouter-runtime-provider.d.ts +9 -0
  14. package/dist/openrouter-runtime-adapter/create-openrouter-runtime-provider.js +41 -0
  15. package/dist/openrouter-runtime-adapter/index.d.ts +8 -0
  16. package/dist/openrouter-runtime-adapter/index.js +8 -0
  17. package/dist/openrouter-runtime-adapter/map-gateway-request.d.ts +26 -0
  18. package/dist/openrouter-runtime-adapter/map-gateway-request.js +62 -0
  19. package/dist/openrouter-runtime-adapter/map-runtime-errors.d.ts +5 -0
  20. package/dist/openrouter-runtime-adapter/map-runtime-errors.js +60 -0
  21. package/dist/openrouter-runtime-adapter/map-runtime-response.d.ts +31 -0
  22. package/dist/openrouter-runtime-adapter/map-runtime-response.js +153 -0
  23. package/dist/openrouter-runtime-adapter/map-server-tools.d.ts +3 -0
  24. package/dist/openrouter-runtime-adapter/map-server-tools.js +143 -0
  25. package/dist/openrouter-runtime-adapter/map-trace.d.ts +5 -0
  26. package/dist/openrouter-runtime-adapter/map-trace.js +45 -0
  27. package/dist/openrouter-runtime-adapter/register-openrouter-runtime.d.ts +10 -0
  28. package/dist/openrouter-runtime-adapter/register-openrouter-runtime.js +14 -0
  29. package/dist/openrouter-runtime-adapter/should-use-openrouter-runtime.d.ts +14 -0
  30. package/dist/openrouter-runtime-adapter/should-use-openrouter-runtime.js +29 -0
  31. package/dist/openrouter-runtime-adapter/validate-server-tools.d.ts +30 -0
  32. package/dist/openrouter-runtime-adapter/validate-server-tools.js +151 -0
  33. package/dist/types.d.ts +234 -0
  34. package/dist-cjs/activity-manager.cjs +33 -0
  35. package/dist-cjs/gateway-config.cjs +15 -0
  36. package/dist-cjs/gateway-utils.cjs +73 -1
  37. package/dist-cjs/gateway-utils.d.ts +8 -1
  38. package/dist-cjs/gateway.cjs +18 -3
  39. package/dist-cjs/index.cjs +3 -2
  40. package/dist-cjs/index.d.ts +4 -3
  41. package/dist-cjs/instruction-errors.cjs +36 -0
  42. package/dist-cjs/instruction-errors.d.ts +21 -0
  43. package/dist-cjs/openrouter-runtime-adapter/create-openrouter-runtime-adapter.cjs +31 -0
  44. package/dist-cjs/openrouter-runtime-adapter/create-openrouter-runtime-adapter.d.ts +23 -0
  45. package/dist-cjs/openrouter-runtime-adapter/create-openrouter-runtime-provider.cjs +41 -0
  46. package/dist-cjs/openrouter-runtime-adapter/create-openrouter-runtime-provider.d.ts +9 -0
  47. package/dist-cjs/openrouter-runtime-adapter/index.cjs +8 -0
  48. package/dist-cjs/openrouter-runtime-adapter/index.d.ts +8 -0
  49. package/dist-cjs/openrouter-runtime-adapter/map-gateway-request.cjs +62 -0
  50. package/dist-cjs/openrouter-runtime-adapter/map-gateway-request.d.ts +26 -0
  51. package/dist-cjs/openrouter-runtime-adapter/map-runtime-errors.cjs +60 -0
  52. package/dist-cjs/openrouter-runtime-adapter/map-runtime-errors.d.ts +5 -0
  53. package/dist-cjs/openrouter-runtime-adapter/map-runtime-response.cjs +153 -0
  54. package/dist-cjs/openrouter-runtime-adapter/map-runtime-response.d.ts +31 -0
  55. package/dist-cjs/openrouter-runtime-adapter/map-server-tools.cjs +143 -0
  56. package/dist-cjs/openrouter-runtime-adapter/map-server-tools.d.ts +3 -0
  57. package/dist-cjs/openrouter-runtime-adapter/map-trace.cjs +45 -0
  58. package/dist-cjs/openrouter-runtime-adapter/map-trace.d.ts +5 -0
  59. package/dist-cjs/openrouter-runtime-adapter/register-openrouter-runtime.cjs +14 -0
  60. package/dist-cjs/openrouter-runtime-adapter/register-openrouter-runtime.d.ts +10 -0
  61. package/dist-cjs/openrouter-runtime-adapter/should-use-openrouter-runtime.cjs +29 -0
  62. package/dist-cjs/openrouter-runtime-adapter/should-use-openrouter-runtime.d.ts +14 -0
  63. package/dist-cjs/openrouter-runtime-adapter/validate-server-tools.cjs +151 -0
  64. package/dist-cjs/openrouter-runtime-adapter/validate-server-tools.d.ts +30 -0
  65. package/dist-cjs/types.d.ts +234 -0
  66. package/package.json +3 -1
@@ -0,0 +1,62 @@
1
+ import { mapGatewayServerTools } from './map-server-tools.js';
2
+ export const OPENROUTER_RUNTIME_OPERATION = 'openrouter-runtime.run';
3
+ function mapMessages(messages) {
4
+ if (!messages?.length)
5
+ return [];
6
+ return messages.map((m) => ({
7
+ role: m.role,
8
+ content: m.content,
9
+ ...(m.name ? { name: m.name } : {}),
10
+ ...(m.toolCallId ? { toolCallId: m.toolCallId } : {}),
11
+ }));
12
+ }
13
+ function buildGenerationOverrides(config) {
14
+ const overrides = {};
15
+ if (config.topP !== undefined)
16
+ overrides.top_p = config.topP;
17
+ if (config.frequencyPenalty !== undefined)
18
+ overrides.frequency_penalty = config.frequencyPenalty;
19
+ if (config.presencePenalty !== undefined)
20
+ overrides.presence_penalty = config.presencePenalty;
21
+ if (Array.isArray(config.stop) && config.stop.length)
22
+ overrides.stop = config.stop;
23
+ return overrides;
24
+ }
25
+ export function mapGatewayRequestToRuntimeRequest(request, exec) {
26
+ const config = request.config ?? {};
27
+ const openrouter = config.openrouter;
28
+ const generationOverrides = buildGenerationOverrides(config);
29
+ const trustedRaw = openrouter?.rawOverrides ?? {};
30
+ const rawOpenRouterOverrides = Object.keys(generationOverrides).length || Object.keys(trustedRaw).length
31
+ ? { ...generationOverrides, ...trustedRaw }
32
+ : undefined;
33
+ const aiRequestId = (typeof request.aiRequestId === 'string' && request.aiRequestId) ||
34
+ (typeof request.identity?.aiRequestId === 'string' ? request.identity.aiRequestId : undefined);
35
+ return {
36
+ id: aiRequestId,
37
+ model: typeof config.model === 'string' ? config.model : undefined,
38
+ apiMode: openrouter?.apiMode ?? 'auto',
39
+ messages: mapMessages(request.messages),
40
+ temperature: typeof config.temperature === 'number' ? config.temperature : undefined,
41
+ maxTokens: typeof config.maxTokens === 'number' ? config.maxTokens : undefined,
42
+ reasoning: config.reasoning != null && typeof config.reasoning === 'object'
43
+ ? config.reasoning
44
+ : undefined,
45
+ serverTools: mapGatewayServerTools(config.serverTools),
46
+ execution: exec?.timeoutMs ? { timeoutMs: exec.timeoutMs } : undefined,
47
+ rawOpenRouterOverrides,
48
+ metadata: {
49
+ source: 'ai-gateway',
50
+ sourcePackage: '@x12i/ai-gateway',
51
+ provider: 'openrouter',
52
+ identity: request.identity,
53
+ actionType: request.actionType,
54
+ actionRef: request.actionRef,
55
+ aiRequestId,
56
+ agentId: request.agentId,
57
+ },
58
+ };
59
+ }
60
+ export function mapGatewayRequestToRuntimeRequestFromRouter(input) {
61
+ return mapGatewayRequestToRuntimeRequest(input.request, { timeoutMs: input.exec?.timeoutMs });
62
+ }
@@ -0,0 +1,5 @@
1
+ import { OpenRouterHttpError, RuntimeConfigError, type RuntimeResponse } from '@x12i/openrouter-runtime';
2
+ export declare function throwMappedRuntimeConfigError(err: RuntimeConfigError): never;
3
+ export declare function throwMappedOpenRouterHttpError(err: OpenRouterHttpError): never;
4
+ export declare function throwMappedRuntimeResponseErrors(response: RuntimeResponse): void;
5
+ export declare function mapRuntimeErrorToGatewayError(err: unknown): Error;
@@ -0,0 +1,60 @@
1
+ import { OpenRouterHttpError, RuntimeConfigError, } from '@x12i/openrouter-runtime';
2
+ import { GatewayPolicyViolationError, GatewayValidationError, ProviderConfigError, ProviderInvokeError, } from '../instruction-errors.js';
3
+ export function throwMappedRuntimeConfigError(err) {
4
+ const code = err.code;
5
+ if (code === 'OPENROUTER_API_KEY_MISSING') {
6
+ throw new ProviderConfigError(code, err.message);
7
+ }
8
+ if (code === 'MODEL_MISSING') {
9
+ throw new GatewayValidationError(code, err.message);
10
+ }
11
+ if (code === 'INPUT_MISSING') {
12
+ throw new GatewayValidationError(code, err.message);
13
+ }
14
+ if (code === 'APPLY_PATCH_REQUIRES_RESPONSES_API') {
15
+ throw new GatewayValidationError(code, err.message);
16
+ }
17
+ throw new GatewayValidationError(code, err.message);
18
+ }
19
+ export function throwMappedOpenRouterHttpError(err) {
20
+ throw new ProviderInvokeError(err.code, err.message, {
21
+ status: err.status,
22
+ retryable: err.retryable,
23
+ });
24
+ }
25
+ export function throwMappedRuntimeResponseErrors(response) {
26
+ if (response.status === 'completed')
27
+ return;
28
+ const primary = response.errors[0];
29
+ if (!primary) {
30
+ throw new ProviderInvokeError('OPENROUTER_REQUEST_FAILED', 'OpenRouter runtime request failed');
31
+ }
32
+ if (primary.source === 'policy' || response.status === 'policy_violation') {
33
+ throw new GatewayPolicyViolationError(primary.code, primary.message);
34
+ }
35
+ if (primary.retryable) {
36
+ throw new ProviderInvokeError(primary.code, primary.message, { retryable: true });
37
+ }
38
+ throw new ProviderInvokeError(primary.code, primary.message);
39
+ }
40
+ export function mapRuntimeErrorToGatewayError(err) {
41
+ if (err instanceof RuntimeConfigError) {
42
+ try {
43
+ throwMappedRuntimeConfigError(err);
44
+ }
45
+ catch (mapped) {
46
+ return mapped;
47
+ }
48
+ }
49
+ if (err instanceof OpenRouterHttpError) {
50
+ try {
51
+ throwMappedOpenRouterHttpError(err);
52
+ }
53
+ catch (mapped) {
54
+ return mapped;
55
+ }
56
+ }
57
+ if (err instanceof Error)
58
+ return err;
59
+ return new Error(String(err));
60
+ }
@@ -0,0 +1,31 @@
1
+ import type { AIResponse } from '@x12i/ai-providers-router';
2
+ import type { RuntimeResponse } from '@x12i/openrouter-runtime';
3
+ import type { GatewayCitation, GatewayGeneratedImage, GatewayOpenRouterRuntimeMetadata, GatewayPatchProposal, GatewayServerToolUsageMap } from '../types.js';
4
+ export declare function mapRuntimeToolUsage(toolUsage: RuntimeResponse['toolUsage']): GatewayServerToolUsageMap;
5
+ export declare function mapRuntimeCitations(citations: RuntimeResponse['citations']): GatewayCitation[];
6
+ export declare function mapRuntimeImages(images: RuntimeResponse['images']): GatewayGeneratedImage[];
7
+ export declare function mapRuntimePatches(patches: RuntimeResponse['patches']): GatewayPatchProposal[];
8
+ export declare function buildOpenRouterRuntimeMetadata(response: RuntimeResponse): GatewayOpenRouterRuntimeMetadata;
9
+ export type OpenRouterRuntimeRouterMetadata = {
10
+ serverTools?: GatewayServerToolUsageMap;
11
+ citations?: GatewayCitation[];
12
+ generatedImages?: GatewayGeneratedImage[];
13
+ patchProposals?: GatewayPatchProposal[];
14
+ openrouterRuntime?: GatewayOpenRouterRuntimeMetadata;
15
+ costUsd?: number;
16
+ costStatus?: 'priced' | 'unpriced';
17
+ };
18
+ export declare function extractOpenRouterRuntimeRouterMetadata(routerResponse: unknown): OpenRouterRuntimeRouterMetadata;
19
+ export declare function parseRuntimeResponseToAIResponse(input: {
20
+ requestId: string;
21
+ execResult: {
22
+ rawResponse: unknown;
23
+ };
24
+ }): AIResponse;
25
+ export declare function pickOpenRouterRuntimeMetadataSlice(routerResponse: unknown): {
26
+ serverTools?: GatewayServerToolUsageMap;
27
+ citations?: GatewayCitation[];
28
+ generatedImages?: GatewayGeneratedImage[];
29
+ patchProposals?: GatewayPatchProposal[];
30
+ openrouterRuntime?: GatewayOpenRouterRuntimeMetadata;
31
+ };
@@ -0,0 +1,153 @@
1
+ const EMPTY_REASONING = {
2
+ requested: { effort: 'none', visibility: 'none' },
3
+ applied: { effort: 'none', visibility: 'none' },
4
+ artifacts: {},
5
+ availability: {
6
+ supportsEffort: false,
7
+ supportsSummary: false,
8
+ supportsTrace: false,
9
+ supportsEncrypted: false,
10
+ },
11
+ };
12
+ export function mapRuntimeToolUsage(toolUsage) {
13
+ const st = toolUsage.serverTools;
14
+ return {
15
+ webSearch: st.webSearch,
16
+ webFetch: st.webFetch,
17
+ datetime: st.datetime,
18
+ imageGeneration: st.imageGeneration,
19
+ applyPatch: st.applyPatch,
20
+ fusion: st.fusion,
21
+ advisor: st.advisor,
22
+ subagent: st.subagent,
23
+ };
24
+ }
25
+ export function mapRuntimeCitations(citations) {
26
+ return citations.map((c) => ({
27
+ type: 'url',
28
+ url: c.url,
29
+ title: c.title,
30
+ excerpt: c.excerpt,
31
+ startIndex: c.startIndex,
32
+ endIndex: c.endIndex,
33
+ sourceProvider: 'openrouter',
34
+ }));
35
+ }
36
+ export function mapRuntimeImages(images) {
37
+ return images.map((img) => ({
38
+ imageUrl: img.imageUrl,
39
+ status: img.status,
40
+ error: img.error,
41
+ raw: img.raw,
42
+ }));
43
+ }
44
+ export function mapRuntimePatches(patches) {
45
+ return patches.map((p) => ({
46
+ callId: p.callId,
47
+ status: p.status,
48
+ operation: p.operation,
49
+ raw: p.raw,
50
+ }));
51
+ }
52
+ export function buildOpenRouterRuntimeMetadata(response) {
53
+ const policyViolations = response.errors
54
+ .filter((e) => e.source === 'policy')
55
+ .map((e) => ({ code: e.code, message: e.message, details: e.details }));
56
+ return {
57
+ apiMode: response.apiMode,
58
+ warnings: response.warnings.map((w) => ({
59
+ code: w.code,
60
+ message: w.message,
61
+ details: w.details,
62
+ })),
63
+ policyViolations,
64
+ requestIds: response.id ? [response.id] : undefined,
65
+ };
66
+ }
67
+ export function extractOpenRouterRuntimeRouterMetadata(routerResponse) {
68
+ if (routerResponse == null || typeof routerResponse !== 'object')
69
+ return {};
70
+ const r = routerResponse;
71
+ const meta = r.metadata != null && typeof r.metadata === 'object'
72
+ ? r.metadata
73
+ : {};
74
+ const out = {};
75
+ if (meta.serverTools != null)
76
+ out.serverTools = meta.serverTools;
77
+ if (meta.citations != null)
78
+ out.citations = meta.citations;
79
+ if (meta.generatedImages != null)
80
+ out.generatedImages = meta.generatedImages;
81
+ if (meta.patchProposals != null)
82
+ out.patchProposals = meta.patchProposals;
83
+ if (meta.openrouterRuntime != null) {
84
+ out.openrouterRuntime = meta.openrouterRuntime;
85
+ }
86
+ if (typeof meta.costUsd === 'number')
87
+ out.costUsd = meta.costUsd;
88
+ if (meta.costStatus === 'priced' || meta.costStatus === 'unpriced') {
89
+ out.costStatus = meta.costStatus;
90
+ }
91
+ return out;
92
+ }
93
+ export function parseRuntimeResponseToAIResponse(input) {
94
+ const response = input.execResult.rawResponse;
95
+ const usage = response.usage;
96
+ const promptTokens = usage?.inputTokens ?? 0;
97
+ const completionTokens = usage?.outputTokens ?? 0;
98
+ const totalTokens = usage?.totalTokens ?? promptTokens + completionTokens;
99
+ const serverTools = mapRuntimeToolUsage(response.toolUsage);
100
+ const citations = mapRuntimeCitations(response.citations);
101
+ const generatedImages = mapRuntimeImages(response.images);
102
+ const patchProposals = mapRuntimePatches(response.patches);
103
+ const openrouterRuntime = buildOpenRouterRuntimeMetadata(response);
104
+ const costUsd = usage?.costUsd;
105
+ const metadata = {
106
+ provider: 'openrouter',
107
+ modelUsed: response.model,
108
+ serverTools,
109
+ citations,
110
+ generatedImages,
111
+ patchProposals,
112
+ openrouterRuntime,
113
+ requestIds: {
114
+ openrouterRequestId: response.id,
115
+ },
116
+ };
117
+ if (typeof costUsd === 'number' && Number.isFinite(costUsd)) {
118
+ metadata.costUsd = costUsd;
119
+ metadata.cost = costUsd;
120
+ metadata.costStatus = 'priced';
121
+ }
122
+ else if (usage && (promptTokens || completionTokens || totalTokens)) {
123
+ metadata.costStatus = 'unpriced';
124
+ }
125
+ return {
126
+ requestId: input.requestId,
127
+ provider: 'openrouter',
128
+ rawResponse: response,
129
+ outputText: response.text,
130
+ usage: {
131
+ promptTokens,
132
+ completionTokens,
133
+ totalTokens,
134
+ },
135
+ reasoning: EMPTY_REASONING,
136
+ metadata,
137
+ };
138
+ }
139
+ export function pickOpenRouterRuntimeMetadataSlice(routerResponse) {
140
+ const extracted = extractOpenRouterRuntimeRouterMetadata(routerResponse);
141
+ const out = {};
142
+ if (extracted.serverTools)
143
+ out.serverTools = extracted.serverTools;
144
+ if (extracted.citations?.length)
145
+ out.citations = extracted.citations;
146
+ if (extracted.generatedImages?.length)
147
+ out.generatedImages = extracted.generatedImages;
148
+ if (extracted.patchProposals?.length)
149
+ out.patchProposals = extracted.patchProposals;
150
+ if (extracted.openrouterRuntime)
151
+ out.openrouterRuntime = extracted.openrouterRuntime;
152
+ return out;
153
+ }
@@ -0,0 +1,3 @@
1
+ import type { GatewayServerToolsConfig } from '../types.js';
2
+ import type { RuntimeServerToolsPolicy } from '@x12i/openrouter-runtime';
3
+ export declare function mapGatewayServerTools(config?: GatewayServerToolsConfig): RuntimeServerToolsPolicy | undefined;
@@ -0,0 +1,143 @@
1
+ function mapWebSearch(src) {
2
+ if (!src)
3
+ return undefined;
4
+ return {
5
+ mode: src.mode,
6
+ engine: src.engine,
7
+ maxResults: src.maxResults,
8
+ maxTotalResults: src.maxTotalResults,
9
+ searchContextSize: src.searchContextSize,
10
+ allowedDomains: src.allowedDomains,
11
+ excludedDomains: src.excludedDomains,
12
+ userLocation: src.userLocation,
13
+ requireCitations: src.requireCitations,
14
+ onFailure: src.onFailure,
15
+ };
16
+ }
17
+ function mapWebFetch(src) {
18
+ if (!src)
19
+ return undefined;
20
+ return {
21
+ mode: src.mode,
22
+ engine: src.engine,
23
+ maxUses: src.maxUses,
24
+ maxContentTokens: src.maxContentTokens,
25
+ allowedDomains: src.allowedDomains,
26
+ blockedDomains: src.blockedDomains,
27
+ onFailure: src.onFailure,
28
+ };
29
+ }
30
+ function mapDatetime(src) {
31
+ if (!src)
32
+ return undefined;
33
+ return { mode: src.mode, timezone: src.timezone };
34
+ }
35
+ function mapImageGeneration(src) {
36
+ if (!src)
37
+ return undefined;
38
+ return {
39
+ mode: src.mode,
40
+ model: src.model,
41
+ quality: src.quality,
42
+ size: src.size,
43
+ aspectRatio: src.aspectRatio,
44
+ background: src.background,
45
+ outputFormat: src.outputFormat,
46
+ outputCompression: src.outputCompression,
47
+ moderation: src.moderation,
48
+ };
49
+ }
50
+ function mapApplyPatch(src) {
51
+ if (!src)
52
+ return undefined;
53
+ return {
54
+ mode: src.mode,
55
+ behavior: src.behavior ?? 'return_only',
56
+ workspaceRoot: src.workspaceRoot,
57
+ allowDelete: src.allowDelete,
58
+ allowCreate: src.allowCreate,
59
+ allowUpdate: src.allowUpdate,
60
+ };
61
+ }
62
+ function mapFusion(src) {
63
+ if (!src)
64
+ return undefined;
65
+ return {
66
+ mode: src.mode,
67
+ analysisModels: src.analysisModels,
68
+ judgeModel: src.judgeModel,
69
+ maxToolCalls: src.maxToolCalls,
70
+ maxCompletionTokens: src.maxCompletionTokens,
71
+ reasoning: src.reasoning,
72
+ temperature: src.temperature,
73
+ };
74
+ }
75
+ function mapNestedTools(tools) {
76
+ if (!tools?.length)
77
+ return undefined;
78
+ return tools.map((t) => ({ type: t.type, parameters: t.parameters }));
79
+ }
80
+ function mapAdvisor(src) {
81
+ if (!src)
82
+ return undefined;
83
+ const mapOne = (a) => ({
84
+ mode: a.mode,
85
+ name: a.name,
86
+ model: a.model,
87
+ instructions: a.instructions,
88
+ tools: mapNestedTools(a.tools),
89
+ forwardTranscript: a.forwardTranscript,
90
+ stream: a.stream,
91
+ maxToolCalls: a.maxToolCalls,
92
+ maxCompletionTokens: a.maxCompletionTokens,
93
+ reasoning: a.reasoning,
94
+ temperature: a.temperature,
95
+ });
96
+ if (Array.isArray(src))
97
+ return src.map(mapOne);
98
+ return mapOne(src);
99
+ }
100
+ function mapSubagent(src) {
101
+ if (!src)
102
+ return undefined;
103
+ return {
104
+ mode: src.mode,
105
+ model: src.model,
106
+ instructions: src.instructions,
107
+ tools: mapNestedTools(src.tools),
108
+ maxToolCalls: src.maxToolCalls,
109
+ maxCompletionTokens: src.maxCompletionTokens,
110
+ reasoning: src.reasoning,
111
+ temperature: src.temperature,
112
+ };
113
+ }
114
+ export function mapGatewayServerTools(config) {
115
+ if (!config)
116
+ return undefined;
117
+ const out = {};
118
+ const webSearch = mapWebSearch(config.webSearch);
119
+ const webFetch = mapWebFetch(config.webFetch);
120
+ const datetime = mapDatetime(config.datetime);
121
+ const imageGeneration = mapImageGeneration(config.imageGeneration);
122
+ const applyPatch = mapApplyPatch(config.applyPatch);
123
+ const fusion = mapFusion(config.fusion);
124
+ const advisor = mapAdvisor(config.advisor);
125
+ const subagent = mapSubagent(config.subagent);
126
+ if (webSearch)
127
+ out.webSearch = webSearch;
128
+ if (webFetch)
129
+ out.webFetch = webFetch;
130
+ if (datetime)
131
+ out.datetime = datetime;
132
+ if (imageGeneration)
133
+ out.imageGeneration = imageGeneration;
134
+ if (applyPatch)
135
+ out.applyPatch = applyPatch;
136
+ if (fusion)
137
+ out.fusion = fusion;
138
+ if (advisor)
139
+ out.advisor = advisor;
140
+ if (subagent)
141
+ out.subagent = subagent;
142
+ return Object.keys(out).length ? out : undefined;
143
+ }
@@ -0,0 +1,5 @@
1
+ import type { GatewayTraceAttempt, GatewayOpenRouterRuntimeMetadata } from '../types.js';
2
+ import type { OpenRouterRuntimeRouterMetadata } from './map-runtime-response.js';
3
+ export declare function buildTraceAttemptOpenRouterRuntimeSlice(metadata: OpenRouterRuntimeRouterMetadata): GatewayTraceAttempt['openrouterRuntime'];
4
+ export declare function enrichTraceOpenRouterRuntimeMetadata(base: GatewayOpenRouterRuntimeMetadata | undefined, metadata: OpenRouterRuntimeRouterMetadata, traceEnabled: boolean): GatewayOpenRouterRuntimeMetadata | undefined;
5
+ export declare function redactRawOpenRouterPayload(raw: unknown, maxChars?: number): unknown;
@@ -0,0 +1,45 @@
1
+ export function buildTraceAttemptOpenRouterRuntimeSlice(metadata) {
2
+ if (!metadata.openrouterRuntime && !metadata.serverTools)
3
+ return undefined;
4
+ return {
5
+ apiMode: metadata.openrouterRuntime?.apiMode,
6
+ serverTools: metadata.serverTools,
7
+ citationCount: metadata.citations?.length ?? 0,
8
+ generatedImageCount: metadata.generatedImages?.length ?? 0,
9
+ patchProposalCount: metadata.patchProposals?.length ?? 0,
10
+ };
11
+ }
12
+ export function enrichTraceOpenRouterRuntimeMetadata(base, metadata, traceEnabled) {
13
+ if (!traceEnabled && !base)
14
+ return base;
15
+ const merged = {
16
+ apiMode: base?.apiMode ?? metadata.openrouterRuntime?.apiMode ?? 'chat',
17
+ warnings: base?.warnings ?? metadata.openrouterRuntime?.warnings ?? [],
18
+ policyViolations: base?.policyViolations ?? metadata.openrouterRuntime?.policyViolations ?? [],
19
+ requestIds: base?.requestIds ?? metadata.openrouterRuntime?.requestIds,
20
+ };
21
+ if (traceEnabled) {
22
+ merged.serverToolsRequested = metadata.serverTools;
23
+ merged.serverToolsUsed = metadata.serverTools;
24
+ merged.citations = metadata.citations;
25
+ merged.generatedImages = metadata.generatedImages;
26
+ merged.patchProposals = metadata.patchProposals;
27
+ }
28
+ return merged;
29
+ }
30
+ export function redactRawOpenRouterPayload(raw, maxChars = 32_000) {
31
+ if (raw == null)
32
+ return raw;
33
+ try {
34
+ const text = JSON.stringify(raw);
35
+ const redacted = text
36
+ .replace(/"(Authorization|authorization|api[_-]?key)"\s*:\s*"[^"]*"/gi, '"$1":"[REDACTED]"')
37
+ .replace(/Bearer\s+[A-Za-z0-9._-]+/g, 'Bearer [REDACTED]');
38
+ if (redacted.length <= maxChars)
39
+ return JSON.parse(redacted);
40
+ return { truncated: true, preview: redacted.slice(0, maxChars) };
41
+ }
42
+ catch {
43
+ return { truncated: true };
44
+ }
45
+ }
@@ -0,0 +1,10 @@
1
+ import type { LLMProviderRouter } from '@x12i/ai-providers-router';
2
+ import type { Logxer } from '@x12i/logxer';
3
+ import type { GatewayOpenRouterRuntimeConfig } from '../types.js';
4
+ export type RegisterOpenRouterRuntimeOptions = {
5
+ apiKey: string;
6
+ logger?: Logxer;
7
+ runtimeConfig?: GatewayOpenRouterRuntimeConfig;
8
+ };
9
+ export declare function registerOpenRouterRuntime(router: LLMProviderRouter, options: RegisterOpenRouterRuntimeOptions): void;
10
+ export { shouldUseOpenRouterRuntime, resolveOpenRouterRuntimeDefaults } from './should-use-openrouter-runtime.js';
@@ -0,0 +1,14 @@
1
+ import { createOpenRouterRuntimeAdapter } from './create-openrouter-runtime-adapter.js';
2
+ import { createOpenRouterRuntimeProvider } from './create-openrouter-runtime-provider.js';
3
+ export function registerOpenRouterRuntime(router, options) {
4
+ const { apiKey, logger } = options;
5
+ const provider = createOpenRouterRuntimeProvider({ apiKey, logger });
6
+ router.registerProvider(provider);
7
+ const adapter = createOpenRouterRuntimeAdapter();
8
+ router.getAdapterRegistry().register(adapter);
9
+ logger?.info('Registered OpenRouter runtime provider and adapter', {
10
+ provider: 'openrouter',
11
+ runtimeEnabled: true,
12
+ });
13
+ }
14
+ export { shouldUseOpenRouterRuntime, resolveOpenRouterRuntimeDefaults } from './should-use-openrouter-runtime.js';
@@ -0,0 +1,14 @@
1
+ import type { GatewayConfig } from '../types.js';
2
+ /**
3
+ * Whether the gateway should register @x12i/openrouter-runtime instead of the router's legacy OpenRouter provider.
4
+ *
5
+ * - AI_GATEWAY_USE_LEGACY_OPENROUTER=1 → legacy router OpenRouter
6
+ * - AI_GATEWAY_USE_OPENROUTER_RUNTIME=0 → legacy
7
+ * - GatewayConfig.openrouterRuntime.enabled=false → legacy
8
+ * - default → runtime enabled
9
+ */
10
+ export declare function shouldUseOpenRouterRuntime(config?: GatewayConfig): boolean;
11
+ export declare function resolveOpenRouterRuntimeDefaults(config?: GatewayConfig): {
12
+ apiMode: 'chat' | 'responses' | 'auto';
13
+ includeRawInTrace: boolean;
14
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Whether the gateway should register @x12i/openrouter-runtime instead of the router's legacy OpenRouter provider.
3
+ *
4
+ * - AI_GATEWAY_USE_LEGACY_OPENROUTER=1 → legacy router OpenRouter
5
+ * - AI_GATEWAY_USE_OPENROUTER_RUNTIME=0 → legacy
6
+ * - GatewayConfig.openrouterRuntime.enabled=false → legacy
7
+ * - default → runtime enabled
8
+ */
9
+ export function shouldUseOpenRouterRuntime(config) {
10
+ const legacyEnv = process.env.AI_GATEWAY_USE_LEGACY_OPENROUTER;
11
+ if (legacyEnv === '1' || legacyEnv === 'true') {
12
+ return false;
13
+ }
14
+ const runtimeEnv = process.env.AI_GATEWAY_USE_OPENROUTER_RUNTIME;
15
+ if (runtimeEnv === '0' || runtimeEnv === 'false') {
16
+ return false;
17
+ }
18
+ if (config?.openrouterRuntime?.enabled === false) {
19
+ return false;
20
+ }
21
+ return true;
22
+ }
23
+ export function resolveOpenRouterRuntimeDefaults(config) {
24
+ const rt = config?.openrouterRuntime;
25
+ return {
26
+ apiMode: rt?.apiMode ?? 'auto',
27
+ includeRawInTrace: rt?.includeRawInTrace ?? false,
28
+ };
29
+ }
@@ -0,0 +1,30 @@
1
+ import type { GatewayOpenRouterConfig, GatewayServerToolsConfig } from '../types.js';
2
+ export type ServerToolValidationWarning = {
3
+ code: string;
4
+ message: string;
5
+ };
6
+ export declare function hasAnyServerToolMode(serverTools: GatewayServerToolsConfig | undefined, mode: 'allowed' | 'required'): boolean;
7
+ export declare function hasAnyActiveServerTool(serverTools?: GatewayServerToolsConfig): boolean;
8
+ export declare function hasRequiredServerTool(serverTools?: GatewayServerToolsConfig): boolean;
9
+ export declare function validateApplyPatchConfig(serverTools: GatewayServerToolsConfig | undefined, openrouter: GatewayOpenRouterConfig | undefined): void;
10
+ export type PostRoutingServerToolsResult = {
11
+ serverTools?: GatewayServerToolsConfig;
12
+ warnings: ServerToolValidationWarning[];
13
+ forceOpenRouter: boolean;
14
+ };
15
+ export declare function applyPostRoutingServerToolsPolicy(input: {
16
+ provider: string | undefined;
17
+ serverTools?: GatewayServerToolsConfig;
18
+ openrouter?: GatewayOpenRouterConfig;
19
+ openRouterApiKey?: string;
20
+ }): PostRoutingServerToolsResult;
21
+ export type OnlineVariantMigrationResult = {
22
+ model: string;
23
+ serverTools?: GatewayServerToolsConfig;
24
+ warning?: ServerToolValidationWarning;
25
+ };
26
+ export declare function applyOnlineVariantMigration(model: string, serverTools?: GatewayServerToolsConfig): OnlineVariantMigrationResult;
27
+ export declare function mergeServerToolsConfig(...layers: (GatewayServerToolsConfig | undefined)[]): GatewayServerToolsConfig | undefined;
28
+ export declare function mergeOpenRouterConfig(...layers: (GatewayOpenRouterConfig | undefined)[]): GatewayOpenRouterConfig | undefined;
29
+ /** Default applyPatch behavior when not specified. */
30
+ export declare function normalizeApplyPatchDefaults(serverTools?: GatewayServerToolsConfig): GatewayServerToolsConfig | undefined;