@x12i/ai-gateway 9.6.3 → 9.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -3
- package/dist/ai-tools-client.d.ts +27 -3
- package/dist/ai-tools-client.js +54 -8
- package/dist/gateway-config.d.ts +2 -0
- package/dist/gateway-config.js +16 -10
- package/dist/gateway-log-meta.d.ts +5 -1
- package/dist/gateway-log-meta.js +19 -1
- package/dist/gateway-provider-auto-register.js +1 -1
- package/dist/gateway-utils.d.ts +2 -1
- package/dist/gateway-utils.js +9 -7
- package/dist/gateway.d.ts +2 -0
- package/dist/gateway.js +601 -578
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -2
- package/dist/logger-factory.d.ts +2 -0
- package/dist/logger-factory.js +11 -14
- package/dist/openrouter-routing.d.ts +12 -0
- package/dist/openrouter-routing.js +27 -0
- package/dist/runtime-objects.d.ts +2 -19
- package/dist/types.d.ts +4 -1
- package/dist-cjs/ai-tools-client.cjs +54 -8
- package/dist-cjs/ai-tools-client.d.ts +27 -3
- package/dist-cjs/gateway-config.cjs +16 -10
- package/dist-cjs/gateway-config.d.ts +2 -0
- package/dist-cjs/gateway-log-meta.cjs +19 -1
- package/dist-cjs/gateway-log-meta.d.ts +5 -1
- package/dist-cjs/gateway-provider-auto-register.cjs +1 -1
- package/dist-cjs/gateway-utils.cjs +9 -7
- package/dist-cjs/gateway-utils.d.ts +2 -1
- package/dist-cjs/gateway.cjs +601 -578
- package/dist-cjs/gateway.d.ts +2 -0
- package/dist-cjs/index.cjs +3 -2
- package/dist-cjs/index.d.ts +4 -3
- package/dist-cjs/logger-factory.cjs +11 -14
- package/dist-cjs/logger-factory.d.ts +2 -0
- package/dist-cjs/openrouter-routing.cjs +27 -0
- package/dist-cjs/openrouter-routing.d.ts +12 -0
- package/dist-cjs/runtime-objects.d.ts +2 -19
- package/dist-cjs/types.d.ts +4 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -87,8 +87,11 @@ console.log(response.content, response.metadata?.costUsd, response.metadata?.tok
|
|
|
87
87
|
|
|
88
88
|
### Providers without manual `register()`
|
|
89
89
|
|
|
90
|
-
- **OpenRouter:** Set **`OPENROUTER_API_KEY`** in `.env
|
|
91
|
-
- **
|
|
90
|
+
- **OpenRouter:** Set **`OPENROUTER_API_KEY`** in `.env`. The gateway always passes this key to the router when set. **By default, OpenRouter is preferred** for routing (including when you also have direct keys such as `OPENAI_API_KEY`). **`@x12i/ai-tools` ≥ 2.1** resolves model + provider agnostically (`openrouter` + `cheap` or `openai` + `gpt-4o` — same pipeline). Profile aliases (`cheap`, `balanced`, …) set `routedViaOpenRouter` from env. You do not need `USE_OPENROUTER=true` when the key is present.
|
|
91
|
+
- **`USE_OPENROUTER=false`:** Do **not** prefer OpenRouter when a direct provider API key exists — use the direct provider instead. OpenRouter is **still** used as **fallback** when the request targets a provider without a direct key (e.g. `anthropic` without `ANTHROPIC_API_KEY`). It does not disable OpenRouter while `OPENROUTER_API_KEY` is set.
|
|
92
|
+
- **Direct providers:** Set `OPENAI_API_KEY`, `GROK_API_KEY`, etc. Registered lazily on first invoke.
|
|
93
|
+
|
|
94
|
+
Details: [OpenRouter env](./docs/OPENROUTER_ENV.md).
|
|
92
95
|
|
|
93
96
|
Load `.env` before constructing the gateway if another package creates it first.
|
|
94
97
|
|
|
@@ -130,7 +133,9 @@ Defaults load from `defaults/model-config.json`, `instructions-blocks.json`, and
|
|
|
130
133
|
| `mode` / `MODE` | Operational mode (`dev`, `debug`, `prod`) |
|
|
131
134
|
| `AI_GATEWAY_LOGS_LEVEL` | Log level when using default logger (`AI_GATEWAY` prefix) |
|
|
132
135
|
| `FLEX_MD_MIN_COMPLIANCE_LEVEL` | `L0`–`L3` output-format validation (default `L0`) |
|
|
133
|
-
|
|
|
136
|
+
| `OPENROUTER_API_KEY` | OpenRouter key; always wired when set (required for profile/OpenRouter routes) |
|
|
137
|
+
| `USE_OPENROUTER` | Optional; default **prefer** OpenRouter when key is set. `false` = use direct provider keys when present; OpenRouter still used as fallback when a provider has no key |
|
|
138
|
+
| Other provider keys | `OPENAI_API_KEY`, `GROK_API_KEY`, etc. |
|
|
134
139
|
|
|
135
140
|
Logging details: [Logger initialization](./docs/LOGGER_INITIALIZATION.md).
|
|
136
141
|
|
|
@@ -230,6 +235,8 @@ Live tests use `LIVE_TEST_PROVIDER` / `LIVE_TEST_MODEL` (default `openrouter` +
|
|
|
230
235
|
| [LOGGER_INITIALIZATION.md](./docs/LOGGER_INITIALIZATION.md) | Logxer setup |
|
|
231
236
|
| [flex-md-compliance.md](./docs/flex-md-compliance.md) | Output format levels |
|
|
232
237
|
| [PROMPT_TEMPLATE_USAGE.md](./docs/PROMPT_TEMPLATE_USAGE.md) | Rendrix templates |
|
|
238
|
+
| [OPENROUTER_ENV.md](./docs/OPENROUTER_ENV.md) | `OPENROUTER_API_KEY` and `USE_OPENROUTER` semantics |
|
|
239
|
+
| [UPSTREAM_PROFILE_RESOLUTION_AND_OPENROUTER_FALLBACK.md](./docs/UPSTREAM_PROFILE_RESOLUTION_AND_OPENROUTER_FALLBACK.md) | Profile routing and OpenRouter fallback checklist |
|
|
233
240
|
| [upstream-reports/README.md](./docs/upstream-reports/README.md) | Upstream issues (one file per package/gap) |
|
|
234
241
|
| [UPSTREAM_TEMPLATE_RENDERING_AND_PARSER_V4.md](./docs/UPSTREAM_TEMPLATE_RENDERING_AND_PARSER_V4.md) | Parser v4 |
|
|
235
242
|
| [RUNTIME_OBJECTS_OBSERVABILITY.md](./docs/RUNTIME_OBJECTS_OBSERVABILITY.md) | Runtime object keys |
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Lazy @x12i/ai-tools catalog + cost calculator bootstrap.
|
|
3
3
|
*/
|
|
4
|
-
import { AiModelsCatalogClient, CostCalculator, type ModelResolutionSuccess } from '@x12i/ai-tools';
|
|
4
|
+
import { AiModelsCatalogClient, CostCalculator, type ModelResolutionSuccess, type ModelResolverOptions, type OpenRouterRoutingConfig } from '@x12i/ai-tools';
|
|
5
5
|
import type { Logxer } from '@x12i/logxer';
|
|
6
6
|
import type { ChatRequest, GatewayConfig } from './types.js';
|
|
7
7
|
export type AiToolsClientBundle = {
|
|
8
8
|
catalog: AiModelsCatalogClient;
|
|
9
9
|
calculator: CostCalculator;
|
|
10
|
+
routingEnv: OpenRouterRoutingConfig;
|
|
10
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Per-invoke resolver options: ai-tools decides OpenRouter vs direct from env + optional gateway prefer override.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildModelResolverOptions(config: GatewayConfig, routingEnv?: OpenRouterRoutingConfig): ModelResolverOptions;
|
|
11
16
|
/**
|
|
12
17
|
* Returns catalog + calculator, or null when disabled or bootstrap fails.
|
|
13
18
|
*/
|
|
@@ -15,6 +20,25 @@ export declare function getAiToolsClient(config: GatewayConfig, logger: Logxer):
|
|
|
15
20
|
/** Reset singleton (tests). */
|
|
16
21
|
export declare function resetAiToolsClientForTests(): void;
|
|
17
22
|
/**
|
|
18
|
-
* Map catalog resolution to router
|
|
23
|
+
* Map catalog resolution to router `{ provider, model }` (agnostic to openrouter vs vendor input).
|
|
24
|
+
*/
|
|
25
|
+
export declare function applyModelResolution(merged: NonNullable<ChatRequest['config']>, resolution: ModelResolutionSuccess, gatewayDefaultEngine?: string, inputModel?: string): void;
|
|
26
|
+
type RouterConfigSlice = {
|
|
27
|
+
provider?: string;
|
|
28
|
+
model?: string;
|
|
29
|
+
allowOpenRouterProxy?: boolean;
|
|
30
|
+
providerProxy?: string;
|
|
31
|
+
};
|
|
32
|
+
type ModelResolutionMeta = {
|
|
33
|
+
routedViaOpenRouter?: boolean;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Router invoke flags after mergeConfig + ai-tools resolution (OpenRouter vs direct transport).
|
|
19
37
|
*/
|
|
20
|
-
export declare function
|
|
38
|
+
export declare function applyOpenRouterInvokePolicy(merged: RouterConfigSlice, options: {
|
|
39
|
+
openRouterApiKey?: string;
|
|
40
|
+
preferOpenRouter?: boolean;
|
|
41
|
+
routingEnv?: OpenRouterRoutingConfig;
|
|
42
|
+
resolution?: ModelResolutionMeta;
|
|
43
|
+
}): void;
|
|
44
|
+
export {};
|
package/dist/ai-tools-client.js
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Lazy @x12i/ai-tools catalog + cost calculator bootstrap.
|
|
3
3
|
*/
|
|
4
|
-
import { AiModelsCatalogClient, CostCalculator } from '@x12i/ai-tools';
|
|
4
|
+
import { AiModelsCatalogClient, CostCalculator, isEffectiveOpenRouterTransport, loadOpenRouterRoutingEnv, resolveModelVendorFromResolution } from '@x12i/ai-tools';
|
|
5
5
|
import { gatewayLogDebug, withActivityIdentity } from './gateway-log-meta.js';
|
|
6
|
+
import { resolvePreferOpenRouter } from './openrouter-routing.js';
|
|
6
7
|
let sharedClientPromise = null;
|
|
7
8
|
let sharedConfigKey;
|
|
8
9
|
let bootstrapFailedLogged = false;
|
|
9
10
|
function configKey(config) {
|
|
10
11
|
return `${config.aiTools?.cacheTtlMs ?? ''}:${config.aiTools?.costIncludeBreakdown ?? ''}:${config.aiTools?.bundledOnly ?? ''}`;
|
|
11
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Per-invoke resolver options: ai-tools decides OpenRouter vs direct from env + optional gateway prefer override.
|
|
15
|
+
*/
|
|
16
|
+
export function buildModelResolverOptions(config, routingEnv) {
|
|
17
|
+
const env = routingEnv ?? loadOpenRouterRoutingEnv();
|
|
18
|
+
const prefer = resolvePreferOpenRouter(config);
|
|
19
|
+
return {
|
|
20
|
+
routingEnv: env,
|
|
21
|
+
...(prefer ? { routeViaOpenRouter: true } : {}),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
12
24
|
/**
|
|
13
25
|
* Returns catalog + calculator, or null when disabled or bootstrap fails.
|
|
14
26
|
*/
|
|
@@ -34,33 +46,43 @@ export function resetAiToolsClientForTests() {
|
|
|
34
46
|
}
|
|
35
47
|
async function bootstrapAiTools(config, logger) {
|
|
36
48
|
try {
|
|
49
|
+
const routingEnv = loadOpenRouterRoutingEnv();
|
|
37
50
|
const catalog = new AiModelsCatalogClient({
|
|
38
51
|
cacheTtlMs: config.aiTools?.cacheTtlMs,
|
|
39
|
-
...(config.aiTools?.bundledOnly ? { bundledOnly: true } : {})
|
|
52
|
+
...(config.aiTools?.bundledOnly ? { bundledOnly: true } : {}),
|
|
53
|
+
resolverOptions: { routingEnv },
|
|
40
54
|
});
|
|
41
55
|
const calculator = new CostCalculator(catalog, {
|
|
42
|
-
includeBreakdown: config.aiTools?.costIncludeBreakdown === true
|
|
56
|
+
includeBreakdown: config.aiTools?.costIncludeBreakdown === true,
|
|
43
57
|
});
|
|
44
58
|
logger.debug('ai-tools catalog client ready', {
|
|
45
|
-
debugKind: gatewayLogDebug.state
|
|
59
|
+
debugKind: gatewayLogDebug.state,
|
|
46
60
|
});
|
|
47
|
-
return { catalog, calculator };
|
|
61
|
+
return { catalog, calculator, routingEnv };
|
|
48
62
|
}
|
|
49
63
|
catch (error) {
|
|
50
64
|
if (!bootstrapFailedLogged) {
|
|
51
65
|
bootstrapFailedLogged = true;
|
|
52
66
|
logger.warn('ai-tools catalog bootstrap failed; model resolution and catalog cost calculation disabled', withActivityIdentity(undefined, {
|
|
53
67
|
error: error instanceof Error ? error.message : String(error),
|
|
54
|
-
debugKind: gatewayLogDebug.anomaly
|
|
68
|
+
debugKind: gatewayLogDebug.anomaly,
|
|
55
69
|
}));
|
|
56
70
|
}
|
|
57
71
|
return null;
|
|
58
72
|
}
|
|
59
73
|
}
|
|
60
74
|
/**
|
|
61
|
-
* Map catalog resolution to router
|
|
75
|
+
* Map catalog resolution to router `{ provider, model }` (agnostic to openrouter vs vendor input).
|
|
62
76
|
*/
|
|
63
|
-
export function applyModelResolution(merged, resolution, gatewayDefaultEngine) {
|
|
77
|
+
export function applyModelResolution(merged, resolution, gatewayDefaultEngine, inputModel) {
|
|
78
|
+
const ref = resolveModelVendorFromResolution(resolution, inputModel ?? merged.model ?? '', {
|
|
79
|
+
asOpenRouter: resolution.routedViaOpenRouter,
|
|
80
|
+
});
|
|
81
|
+
if (ref) {
|
|
82
|
+
merged.provider = ref.provider;
|
|
83
|
+
merged.model = ref.model;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
64
86
|
if (resolution.routedViaOpenRouter) {
|
|
65
87
|
merged.provider = 'openrouter';
|
|
66
88
|
merged.model = resolution.modelId;
|
|
@@ -81,3 +103,27 @@ export function applyModelResolution(merged, resolution, gatewayDefaultEngine) {
|
|
|
81
103
|
merged.provider = gatewayDefaultEngine;
|
|
82
104
|
}
|
|
83
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Router invoke flags after mergeConfig + ai-tools resolution (OpenRouter vs direct transport).
|
|
108
|
+
*/
|
|
109
|
+
export function applyOpenRouterInvokePolicy(merged, options) {
|
|
110
|
+
if (!options.openRouterApiKey?.trim())
|
|
111
|
+
return;
|
|
112
|
+
const routingEnv = options.routingEnv ?? loadOpenRouterRoutingEnv();
|
|
113
|
+
const viaOpenRouter = options.resolution?.routedViaOpenRouter === true ||
|
|
114
|
+
(options.resolution?.routedViaOpenRouter !== false &&
|
|
115
|
+
isEffectiveOpenRouterTransport(routingEnv, {
|
|
116
|
+
provider: merged.provider,
|
|
117
|
+
modelId: merged.model,
|
|
118
|
+
routeViaOpenRouter: options.preferOpenRouter ? true : undefined,
|
|
119
|
+
}));
|
|
120
|
+
if (viaOpenRouter) {
|
|
121
|
+
merged.allowOpenRouterProxy = true;
|
|
122
|
+
if (merged.provider && merged.provider !== 'openrouter') {
|
|
123
|
+
merged.providerProxy = 'openrouter';
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
merged.allowOpenRouterProxy = false;
|
|
128
|
+
}
|
|
129
|
+
}
|
package/dist/gateway-config.d.ts
CHANGED
|
@@ -51,4 +51,6 @@ export declare function initializeGatewayComponents(config: GatewayConfig): {
|
|
|
51
51
|
usageTracker: UsageTracker;
|
|
52
52
|
messageBuilderConfig: MessageBuilderConfig;
|
|
53
53
|
defaultModelConfig: Record<string, unknown>;
|
|
54
|
+
preferOpenRouter: boolean;
|
|
55
|
+
openRouterApiKey?: string;
|
|
54
56
|
};
|
package/dist/gateway-config.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import * as fs from 'fs';
|
|
6
6
|
import * as path from 'path';
|
|
7
7
|
import { fileURLToPath } from 'url';
|
|
8
|
+
import { resolveOpenRouterApiKey, resolvePreferOpenRouter, } from './openrouter-routing.js';
|
|
8
9
|
/** Resolve current module directory across ESM/CJS builds. */
|
|
9
10
|
function getModuleDir() {
|
|
10
11
|
if (typeof __dirname !== 'undefined') {
|
|
@@ -193,16 +194,19 @@ export function initializeGatewayComponents(config) {
|
|
|
193
194
|
routerConfig.autoDiscover = config.autoDiscover;
|
|
194
195
|
if (config.usageTracker !== undefined)
|
|
195
196
|
routerConfig.usageTracker = config.usageTracker;
|
|
196
|
-
// OpenRouter:
|
|
197
|
-
//
|
|
198
|
-
const
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
const useOpenRouter = config.openRouter?.enabled !== undefined ? config.openRouter?.enabled : process.env.USE_OPENROUTER;
|
|
202
|
-
if (openRouterKey && useOpenRouter !== false && useOpenRouter !== 'false') {
|
|
203
|
-
routerConfig.openRouter = { enabled: true };
|
|
197
|
+
// OpenRouter: always pass apiKey when set (fallback for providers without direct keys).
|
|
198
|
+
// USE_OPENROUTER=false only disables *preferring* OpenRouter when direct provider keys exist.
|
|
199
|
+
const openRouterKey = resolveOpenRouterApiKey(config);
|
|
200
|
+
const preferOpenRouter = resolvePreferOpenRouter(config);
|
|
201
|
+
if (openRouterKey) {
|
|
204
202
|
routerConfig.openrouter = { apiKey: openRouterKey };
|
|
205
|
-
routerConfig.
|
|
203
|
+
routerConfig.openRouter = {
|
|
204
|
+
enabled: true,
|
|
205
|
+
prefer: preferOpenRouter,
|
|
206
|
+
};
|
|
207
|
+
if (preferOpenRouter) {
|
|
208
|
+
routerConfig.defaultMode = 'openrouter';
|
|
209
|
+
}
|
|
206
210
|
}
|
|
207
211
|
const router = new LLMProviderRouter(routerConfig);
|
|
208
212
|
// Set up BETWEEN-CALLS rate limiting as a request interceptor (applies to all provider calls)
|
|
@@ -302,6 +306,8 @@ export function initializeGatewayComponents(config) {
|
|
|
302
306
|
optimixerManager,
|
|
303
307
|
usageTracker,
|
|
304
308
|
messageBuilderConfig,
|
|
305
|
-
defaultModelConfig
|
|
309
|
+
defaultModelConfig,
|
|
310
|
+
preferOpenRouter,
|
|
311
|
+
openRouterApiKey: openRouterKey,
|
|
306
312
|
};
|
|
307
313
|
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Maps gateway {@link ActivityIdentity} into Logxer {@link LogMeta} fields for correlation and querying.
|
|
3
3
|
*/
|
|
4
|
-
import type { LogMeta } from '@x12i/logxer';
|
|
4
|
+
import type { LogMeta, LogRuntimeContext } from '@x12i/logxer';
|
|
5
5
|
import type { ActivityIdentity } from './types.js';
|
|
6
6
|
/** Subset of identity forwarded on every structured log line (plus full envelope under `identity`). */
|
|
7
7
|
export declare function activityIdentityToLogMeta(identity: Partial<ActivityIdentity> | undefined): LogMeta;
|
|
8
8
|
export declare function withActivityIdentity(identity: Partial<ActivityIdentity> | undefined, data?: LogMeta, debugKind?: LogMeta['debugKind']): LogMeta;
|
|
9
|
+
/** Map gateway identity into Logxer ALS correlation context (`runWithLogContext`). */
|
|
10
|
+
export declare function activityIdentityToLogContext(identity: Partial<ActivityIdentity> | undefined): LogRuntimeContext;
|
|
11
|
+
/** Run gateway work with Logxer correlation context for `getJobLogs` and structured envelopes. */
|
|
12
|
+
export declare function withGatewayLogContext<T>(identity: Partial<ActivityIdentity> | undefined, fn: () => T | Promise<T>): Promise<T>;
|
|
9
13
|
export declare const gatewayLogDebug: {
|
|
10
14
|
readonly anomaly: "ANOMALY";
|
|
11
15
|
readonly trace: "TRACE";
|
package/dist/gateway-log-meta.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DebugLogAbstract } from '@x12i/logxer';
|
|
1
|
+
import { DebugLogAbstract, runWithLogContext } from '@x12i/logxer';
|
|
2
2
|
/** Subset of identity forwarded on every structured log line (plus full envelope under `identity`). */
|
|
3
3
|
export function activityIdentityToLogMeta(identity) {
|
|
4
4
|
if (!identity) {
|
|
@@ -27,6 +27,24 @@ export function withActivityIdentity(identity, data, debugKind) {
|
|
|
27
27
|
...(debugKind !== undefined ? { debugKind } : {})
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
|
+
/** Map gateway identity into Logxer ALS correlation context (`runWithLogContext`). */
|
|
31
|
+
export function activityIdentityToLogContext(identity) {
|
|
32
|
+
if (!identity) {
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
jobId: identity.jobId,
|
|
37
|
+
taskId: identity.taskId,
|
|
38
|
+
graphId: identity.graphId,
|
|
39
|
+
nodeId: identity.nodeId,
|
|
40
|
+
sessionId: identity.sessionId,
|
|
41
|
+
correlationId: identity.aiRequestId
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** Run gateway work with Logxer correlation context for `getJobLogs` and structured envelopes. */
|
|
45
|
+
export function withGatewayLogContext(identity, fn) {
|
|
46
|
+
return runWithLogContext(activityIdentityToLogContext(identity), fn);
|
|
47
|
+
}
|
|
30
48
|
export const gatewayLogDebug = {
|
|
31
49
|
anomaly: DebugLogAbstract.ANOMALY,
|
|
32
50
|
trace: DebugLogAbstract.TRACE,
|
|
@@ -146,7 +146,7 @@ export async function autoRegisterProviders(router, logger) {
|
|
|
146
146
|
optionalEnvVars: PROVIDER_CONFIGS
|
|
147
147
|
.filter(p => p.optional)
|
|
148
148
|
.map(p => p.envVar),
|
|
149
|
-
openRouter: 'Set OPENROUTER_API_KEY (
|
|
149
|
+
openRouter: 'Set OPENROUTER_API_KEY for OpenRouter (default route when set). USE_OPENROUTER=false prefers direct provider keys when present; OpenRouter is still used when a requested provider has no key.',
|
|
150
150
|
note: 'You can still manually register providers using gateway.register(provider)'
|
|
151
151
|
});
|
|
152
152
|
}
|
package/dist/gateway-utils.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { AIInvokeRequest, ChatRequest, GatewayConfig, GatewayFallbackAttempt, GatewayInvokeRejectionMetadata, GatewayTraceAttempt, GatewayTraceMergedConfig, GatewayTraceRequestIds, GatewayTraceUsageSummary, ModelConfig } from './types.js';
|
|
6
6
|
import type { Logxer } from '@x12i/logxer';
|
|
7
|
-
import { type AiCostResult, type AiModelsCatalogClient, type CostCalculator } from '@x12i/ai-tools';
|
|
7
|
+
import { type AiCostResult, type AiModelsCatalogClient, type CostCalculator, type OpenRouterRoutingConfig } from '@x12i/ai-tools';
|
|
8
8
|
/**
|
|
9
9
|
* Generates MD5 hash of a string
|
|
10
10
|
*/
|
|
@@ -16,6 +16,7 @@ export declare function ensureTaskTypeId(request: ChatRequest, logger: Logxer):
|
|
|
16
16
|
export type MergeConfigOptions = {
|
|
17
17
|
defaultModelConfig?: Record<string, unknown>;
|
|
18
18
|
catalog?: AiModelsCatalogClient | null;
|
|
19
|
+
routingEnv?: OpenRouterRoutingConfig;
|
|
19
20
|
};
|
|
20
21
|
/**
|
|
21
22
|
* True when any caller-controlled config source set `maxTokens` (Optimixer should not override).
|
package/dist/gateway-utils.js
CHANGED
|
@@ -9,7 +9,7 @@ import { extractHttpStatusCode } from './gateway-retry.js';
|
|
|
9
9
|
import { gatewayLogDebug, withActivityIdentity } from './gateway-log-meta.js';
|
|
10
10
|
import { getPreParsedInstructions } from './gateway-instructions.js';
|
|
11
11
|
import { getModelMaxTokensFromFlexMd } from './flex-md-loader.js';
|
|
12
|
-
import { applyModelResolution } from './ai-tools-client.js';
|
|
12
|
+
import { applyModelResolution, buildModelResolverOptions } from './ai-tools-client.js';
|
|
13
13
|
import { getGatewayOperationalMode, isProdGatewayMode, resolveGatewayDefaultModel, warnDefaultModelSubstitution } from './gateway-mode.js';
|
|
14
14
|
/**
|
|
15
15
|
* Generates MD5 hash of a string
|
|
@@ -65,14 +65,15 @@ async function tryResolveSubstitutedDefaultModel(merged, request, config, logger
|
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
67
67
|
try {
|
|
68
|
+
const resolverOptions = buildModelResolverOptions(config, mergeOptions?.routingEnv);
|
|
68
69
|
const resolution = await catalog.resolveModel({
|
|
69
70
|
provider: merged.provider,
|
|
70
|
-
model: merged.model
|
|
71
|
-
});
|
|
71
|
+
model: merged.model,
|
|
72
|
+
}, resolverOptions);
|
|
72
73
|
if (!resolution.found) {
|
|
73
74
|
return;
|
|
74
75
|
}
|
|
75
|
-
applyModelResolution(merged, resolution, config.defaultEngine);
|
|
76
|
+
applyModelResolution(merged, resolution, config.defaultEngine, merged.model);
|
|
76
77
|
request._modelResolution = {
|
|
77
78
|
modelId: resolution.modelId,
|
|
78
79
|
routedViaOpenRouter: resolution.routedViaOpenRouter,
|
|
@@ -182,12 +183,13 @@ export async function mergeConfig(request, config, logger, mergeOptions) {
|
|
|
182
183
|
}
|
|
183
184
|
else if (resolveModels && mergeOptions?.catalog) {
|
|
184
185
|
try {
|
|
186
|
+
const resolverOptions = buildModelResolverOptions(config, mergeOptions?.routingEnv);
|
|
185
187
|
const resolution = await mergeOptions.catalog.resolveModel({
|
|
186
188
|
provider: merged.provider,
|
|
187
|
-
model: explicitModel
|
|
188
|
-
});
|
|
189
|
+
model: explicitModel,
|
|
190
|
+
}, resolverOptions);
|
|
189
191
|
if (resolution.found) {
|
|
190
|
-
applyModelResolution(merged, resolution, config.defaultEngine);
|
|
192
|
+
applyModelResolution(merged, resolution, config.defaultEngine, explicitModel);
|
|
191
193
|
request._modelResolution = {
|
|
192
194
|
modelId: resolution.modelId,
|
|
193
195
|
routedViaOpenRouter: resolution.routedViaOpenRouter,
|
package/dist/gateway.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export declare class AIGateway {
|
|
|
20
20
|
private defaultModelConfig;
|
|
21
21
|
private _autoRegisterDone;
|
|
22
22
|
private _aiToolsClient;
|
|
23
|
+
private readonly preferOpenRouter;
|
|
24
|
+
private readonly openRouterApiKey?;
|
|
23
25
|
constructor(config?: GatewayConfig, activityManager?: ActivityManager);
|
|
24
26
|
/**
|
|
25
27
|
* Invoke chat request (without structured output requirements)
|