@x12i/ai-gateway 11.0.1 → 11.0.2

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.
@@ -5,5 +5,6 @@ export type OpenRouterRuntimeProviderOptions = {
5
5
  apiKey: string;
6
6
  logger?: Logxer;
7
7
  runtime?: OpenRouterRuntime;
8
+ debugOpenRouterBody?: boolean;
8
9
  };
9
10
  export declare function createOpenRouterRuntimeProvider(options: OpenRouterRuntimeProviderOptions): ProviderModule;
@@ -1,6 +1,37 @@
1
1
  import { createOpenRouterRuntime, RuntimeConfigError, OpenRouterHttpError, } from '@x12i/openrouter-runtime';
2
2
  import { OPENROUTER_RUNTIME_OPERATION } from './map-gateway-request.js';
3
3
  import { throwMappedOpenRouterHttpError, throwMappedRuntimeConfigError, throwMappedRuntimeResponseErrors, } from './map-runtime-errors.js';
4
+ import { redactRawOpenRouterPayload } from './map-trace.js';
5
+ function hasOwn(obj, key) {
6
+ return Object.prototype.hasOwnProperty.call(obj, key);
7
+ }
8
+ function summarizeStreamValue(value) {
9
+ if (value == null || ['boolean', 'number', 'string'].includes(typeof value))
10
+ return value;
11
+ if (Array.isArray(value))
12
+ return `[array:${value.length}]`;
13
+ return `[${typeof value}]`;
14
+ }
15
+ function collectStreamFields(value, path = 'body', depth = 0, out = []) {
16
+ if (out.length >= 20 || depth > 8 || value == null || typeof value !== 'object')
17
+ return out;
18
+ if (Array.isArray(value)) {
19
+ for (let i = 0; i < value.length && out.length < 20; i += 1) {
20
+ collectStreamFields(value[i], `${path}[${i}]`, depth + 1, out);
21
+ }
22
+ return out;
23
+ }
24
+ for (const [key, child] of Object.entries(value)) {
25
+ const childPath = `${path}.${key}`;
26
+ if (key === 'stream') {
27
+ out.push({ path: childPath, value: summarizeStreamValue(child) });
28
+ if (out.length >= 20)
29
+ return out;
30
+ }
31
+ collectStreamFields(child, childPath, depth + 1, out);
32
+ }
33
+ return out;
34
+ }
4
35
  function summarizeServerTools(serverTools) {
5
36
  if (!serverTools)
6
37
  return undefined;
@@ -26,9 +57,19 @@ function summarizeCompiledTools(compiled) {
26
57
  toolCount: tools.length,
27
58
  toolTypes,
28
59
  bodyKeys: Object.keys(compiled.body),
60
+ hasTopLevelStream: hasOwn(compiled.body, 'stream'),
61
+ topLevelStream: compiled.body.stream,
62
+ streamFields: collectStreamFields(compiled.body),
29
63
  };
30
64
  }
65
+ function shouldDebugOpenRouterBody(options) {
66
+ if (options.debugOpenRouterBody === true)
67
+ return true;
68
+ const env = process.env.AI_GATEWAY_DEBUG_OPENROUTER_BODY?.toLowerCase();
69
+ return env === '1' || env === 'true' || env === 'yes';
70
+ }
31
71
  export function createOpenRouterRuntimeProvider(options) {
72
+ const debugOpenRouterBody = shouldDebugOpenRouterBody(options);
32
73
  const runtime = options.runtime ??
33
74
  createOpenRouterRuntime({
34
75
  apiKey: options.apiKey,
@@ -48,7 +89,19 @@ export function createOpenRouterRuntimeProvider(options) {
48
89
  ? {
49
90
  beforeOpenRouterRequest: (compiled) => {
50
91
  const summary = summarizeCompiledTools(compiled);
51
- options.logger?.debug('OpenRouter runtime compiled request tools', summary);
92
+ options.logger?.debug('OpenRouter runtime compiled request before fetch', {
93
+ ...summary,
94
+ url: compiled.url,
95
+ });
96
+ if (debugOpenRouterBody) {
97
+ const redactedBody = redactRawOpenRouterPayload(compiled.body);
98
+ options.logger?.debug('OpenRouter runtime compiled request body before fetch', {
99
+ apiMode: compiled.apiMode,
100
+ url: compiled.url,
101
+ body: redactedBody,
102
+ bodyJson: JSON.stringify(redactedBody, null, 2),
103
+ });
104
+ }
52
105
  },
53
106
  }
54
107
  : undefined,
@@ -68,13 +121,17 @@ export function createOpenRouterRuntimeProvider(options) {
68
121
  const rawOverrideKeys = runtimeRequest.rawOpenRouterOverrides
69
122
  ? Object.keys(runtimeRequest.rawOpenRouterOverrides)
70
123
  : [];
124
+ const rawOverrides = runtimeRequest.rawOpenRouterOverrides ?? {};
125
+ const rawOverrideHasStream = hasOwn(rawOverrides, 'stream');
71
126
  options.logger?.debug('OpenRouter runtime request server tools', {
72
127
  requestId: spec.requestId,
73
128
  model: runtimeRequest.model,
74
129
  apiMode: runtimeRequest.apiMode,
75
130
  serverTools: summarizeServerTools(runtimeRequest.serverTools),
76
131
  rawOverrideKeys,
77
- rawOverridesToolsPresent: Object.prototype.hasOwnProperty.call(runtimeRequest.rawOpenRouterOverrides ?? {}, 'tools'),
132
+ rawOverrideHasStream,
133
+ rawOverrideStream: rawOverrides.stream,
134
+ rawOverridesToolsPresent: Object.prototype.hasOwnProperty.call(rawOverrides, 'tools'),
78
135
  });
79
136
  try {
80
137
  const response = await runtime.run(runtimeRequest);
@@ -22,21 +22,8 @@ function buildGenerationOverrides(config) {
22
22
  overrides.stop = config.stop;
23
23
  return overrides;
24
24
  }
25
- function hasActiveServerTools(serverTools) {
26
- if (!serverTools)
27
- return false;
28
- return Object.values(serverTools).some((value) => {
29
- if (Array.isArray(value))
30
- return value.some((item) => item.mode !== 'disabled');
31
- return !!value && value.mode !== 'disabled';
32
- });
33
- }
34
- function buildRawOpenRouterOverrides(generationOverrides, trustedRaw, serverTools) {
35
- const raw = { ...trustedRaw };
36
- if (hasActiveServerTools(serverTools)) {
37
- delete raw.tools;
38
- }
39
- const merged = { ...generationOverrides, ...raw };
25
+ function buildRawOpenRouterOverrides(generationOverrides, trustedRaw) {
26
+ const merged = { ...generationOverrides, ...trustedRaw };
40
27
  return Object.keys(merged).length ? merged : undefined;
41
28
  }
42
29
  export function mapGatewayRequestToRuntimeRequest(request, exec) {
@@ -45,7 +32,7 @@ export function mapGatewayRequestToRuntimeRequest(request, exec) {
45
32
  const generationOverrides = buildGenerationOverrides(config);
46
33
  const trustedRaw = openrouter?.rawOverrides ?? {};
47
34
  const serverTools = mapGatewayServerTools(config.serverTools);
48
- const rawOpenRouterOverrides = buildRawOpenRouterOverrides(generationOverrides, trustedRaw, serverTools);
35
+ const rawOpenRouterOverrides = buildRawOpenRouterOverrides(generationOverrides, trustedRaw);
49
36
  const aiRequestId = (typeof request.aiRequestId === 'string' && request.aiRequestId) ||
50
37
  (typeof request.identity?.aiRequestId === 'string' ? request.identity.aiRequestId : undefined);
51
38
  return {
@@ -1,14 +1,19 @@
1
1
  import { createOpenRouterRuntimeAdapter } from './create-openrouter-runtime-adapter.js';
2
2
  import { createOpenRouterRuntimeProvider } from './create-openrouter-runtime-provider.js';
3
3
  export function registerOpenRouterRuntime(router, options) {
4
- const { apiKey, logger } = options;
5
- const provider = createOpenRouterRuntimeProvider({ apiKey, logger });
4
+ const { apiKey, logger, runtimeConfig } = options;
5
+ const provider = createOpenRouterRuntimeProvider({
6
+ apiKey,
7
+ logger,
8
+ debugOpenRouterBody: runtimeConfig?.debugOpenRouterBody,
9
+ });
6
10
  router.registerProvider(provider);
7
11
  const adapter = createOpenRouterRuntimeAdapter();
8
12
  router.getAdapterRegistry().register(adapter);
9
13
  logger?.info('Registered OpenRouter runtime provider and adapter', {
10
14
  provider: 'openrouter',
11
15
  runtimeEnabled: true,
16
+ debugOpenRouterBody: runtimeConfig?.debugOpenRouterBody,
12
17
  });
13
18
  }
14
19
  export { shouldUseOpenRouterRuntime, resolveOpenRouterRuntimeDefaults } from './should-use-openrouter-runtime.js';
package/dist/types.d.ts CHANGED
@@ -176,6 +176,12 @@ export interface GatewayOpenRouterRuntimeConfig {
176
176
  enabled?: boolean;
177
177
  apiMode?: 'chat' | 'responses' | 'auto';
178
178
  includeRawInTrace?: boolean;
179
+ /**
180
+ * Emit the exact compiled OpenRouter request body at debug level before fetch.
181
+ * Intended for short-lived diagnostics; request prompts/content are included.
182
+ * Can also be enabled with AI_GATEWAY_DEBUG_OPENROUTER_BODY=1.
183
+ */
184
+ debugOpenRouterBody?: boolean;
179
185
  }
180
186
  export interface GatewayServerToolUsage {
181
187
  requested: boolean;
@@ -1,6 +1,37 @@
1
1
  import { createOpenRouterRuntime, RuntimeConfigError, OpenRouterHttpError, } from '@x12i/openrouter-runtime';
2
2
  import { OPENROUTER_RUNTIME_OPERATION } from './map-gateway-request.js';
3
3
  import { throwMappedOpenRouterHttpError, throwMappedRuntimeConfigError, throwMappedRuntimeResponseErrors, } from './map-runtime-errors.js';
4
+ import { redactRawOpenRouterPayload } from './map-trace.js';
5
+ function hasOwn(obj, key) {
6
+ return Object.prototype.hasOwnProperty.call(obj, key);
7
+ }
8
+ function summarizeStreamValue(value) {
9
+ if (value == null || ['boolean', 'number', 'string'].includes(typeof value))
10
+ return value;
11
+ if (Array.isArray(value))
12
+ return `[array:${value.length}]`;
13
+ return `[${typeof value}]`;
14
+ }
15
+ function collectStreamFields(value, path = 'body', depth = 0, out = []) {
16
+ if (out.length >= 20 || depth > 8 || value == null || typeof value !== 'object')
17
+ return out;
18
+ if (Array.isArray(value)) {
19
+ for (let i = 0; i < value.length && out.length < 20; i += 1) {
20
+ collectStreamFields(value[i], `${path}[${i}]`, depth + 1, out);
21
+ }
22
+ return out;
23
+ }
24
+ for (const [key, child] of Object.entries(value)) {
25
+ const childPath = `${path}.${key}`;
26
+ if (key === 'stream') {
27
+ out.push({ path: childPath, value: summarizeStreamValue(child) });
28
+ if (out.length >= 20)
29
+ return out;
30
+ }
31
+ collectStreamFields(child, childPath, depth + 1, out);
32
+ }
33
+ return out;
34
+ }
4
35
  function summarizeServerTools(serverTools) {
5
36
  if (!serverTools)
6
37
  return undefined;
@@ -26,9 +57,19 @@ function summarizeCompiledTools(compiled) {
26
57
  toolCount: tools.length,
27
58
  toolTypes,
28
59
  bodyKeys: Object.keys(compiled.body),
60
+ hasTopLevelStream: hasOwn(compiled.body, 'stream'),
61
+ topLevelStream: compiled.body.stream,
62
+ streamFields: collectStreamFields(compiled.body),
29
63
  };
30
64
  }
65
+ function shouldDebugOpenRouterBody(options) {
66
+ if (options.debugOpenRouterBody === true)
67
+ return true;
68
+ const env = process.env.AI_GATEWAY_DEBUG_OPENROUTER_BODY?.toLowerCase();
69
+ return env === '1' || env === 'true' || env === 'yes';
70
+ }
31
71
  export function createOpenRouterRuntimeProvider(options) {
72
+ const debugOpenRouterBody = shouldDebugOpenRouterBody(options);
32
73
  const runtime = options.runtime ??
33
74
  createOpenRouterRuntime({
34
75
  apiKey: options.apiKey,
@@ -48,7 +89,19 @@ export function createOpenRouterRuntimeProvider(options) {
48
89
  ? {
49
90
  beforeOpenRouterRequest: (compiled) => {
50
91
  const summary = summarizeCompiledTools(compiled);
51
- options.logger?.debug('OpenRouter runtime compiled request tools', summary);
92
+ options.logger?.debug('OpenRouter runtime compiled request before fetch', {
93
+ ...summary,
94
+ url: compiled.url,
95
+ });
96
+ if (debugOpenRouterBody) {
97
+ const redactedBody = redactRawOpenRouterPayload(compiled.body);
98
+ options.logger?.debug('OpenRouter runtime compiled request body before fetch', {
99
+ apiMode: compiled.apiMode,
100
+ url: compiled.url,
101
+ body: redactedBody,
102
+ bodyJson: JSON.stringify(redactedBody, null, 2),
103
+ });
104
+ }
52
105
  },
53
106
  }
54
107
  : undefined,
@@ -68,13 +121,17 @@ export function createOpenRouterRuntimeProvider(options) {
68
121
  const rawOverrideKeys = runtimeRequest.rawOpenRouterOverrides
69
122
  ? Object.keys(runtimeRequest.rawOpenRouterOverrides)
70
123
  : [];
124
+ const rawOverrides = runtimeRequest.rawOpenRouterOverrides ?? {};
125
+ const rawOverrideHasStream = hasOwn(rawOverrides, 'stream');
71
126
  options.logger?.debug('OpenRouter runtime request server tools', {
72
127
  requestId: spec.requestId,
73
128
  model: runtimeRequest.model,
74
129
  apiMode: runtimeRequest.apiMode,
75
130
  serverTools: summarizeServerTools(runtimeRequest.serverTools),
76
131
  rawOverrideKeys,
77
- rawOverridesToolsPresent: Object.prototype.hasOwnProperty.call(runtimeRequest.rawOpenRouterOverrides ?? {}, 'tools'),
132
+ rawOverrideHasStream,
133
+ rawOverrideStream: rawOverrides.stream,
134
+ rawOverridesToolsPresent: Object.prototype.hasOwnProperty.call(rawOverrides, 'tools'),
78
135
  });
79
136
  try {
80
137
  const response = await runtime.run(runtimeRequest);
@@ -5,5 +5,6 @@ export type OpenRouterRuntimeProviderOptions = {
5
5
  apiKey: string;
6
6
  logger?: Logxer;
7
7
  runtime?: OpenRouterRuntime;
8
+ debugOpenRouterBody?: boolean;
8
9
  };
9
10
  export declare function createOpenRouterRuntimeProvider(options: OpenRouterRuntimeProviderOptions): ProviderModule;
@@ -22,21 +22,8 @@ function buildGenerationOverrides(config) {
22
22
  overrides.stop = config.stop;
23
23
  return overrides;
24
24
  }
25
- function hasActiveServerTools(serverTools) {
26
- if (!serverTools)
27
- return false;
28
- return Object.values(serverTools).some((value) => {
29
- if (Array.isArray(value))
30
- return value.some((item) => item.mode !== 'disabled');
31
- return !!value && value.mode !== 'disabled';
32
- });
33
- }
34
- function buildRawOpenRouterOverrides(generationOverrides, trustedRaw, serverTools) {
35
- const raw = { ...trustedRaw };
36
- if (hasActiveServerTools(serverTools)) {
37
- delete raw.tools;
38
- }
39
- const merged = { ...generationOverrides, ...raw };
25
+ function buildRawOpenRouterOverrides(generationOverrides, trustedRaw) {
26
+ const merged = { ...generationOverrides, ...trustedRaw };
40
27
  return Object.keys(merged).length ? merged : undefined;
41
28
  }
42
29
  export function mapGatewayRequestToRuntimeRequest(request, exec) {
@@ -45,7 +32,7 @@ export function mapGatewayRequestToRuntimeRequest(request, exec) {
45
32
  const generationOverrides = buildGenerationOverrides(config);
46
33
  const trustedRaw = openrouter?.rawOverrides ?? {};
47
34
  const serverTools = mapGatewayServerTools(config.serverTools);
48
- const rawOpenRouterOverrides = buildRawOpenRouterOverrides(generationOverrides, trustedRaw, serverTools);
35
+ const rawOpenRouterOverrides = buildRawOpenRouterOverrides(generationOverrides, trustedRaw);
49
36
  const aiRequestId = (typeof request.aiRequestId === 'string' && request.aiRequestId) ||
50
37
  (typeof request.identity?.aiRequestId === 'string' ? request.identity.aiRequestId : undefined);
51
38
  return {
@@ -1,14 +1,19 @@
1
1
  import { createOpenRouterRuntimeAdapter } from './create-openrouter-runtime-adapter.js';
2
2
  import { createOpenRouterRuntimeProvider } from './create-openrouter-runtime-provider.js';
3
3
  export function registerOpenRouterRuntime(router, options) {
4
- const { apiKey, logger } = options;
5
- const provider = createOpenRouterRuntimeProvider({ apiKey, logger });
4
+ const { apiKey, logger, runtimeConfig } = options;
5
+ const provider = createOpenRouterRuntimeProvider({
6
+ apiKey,
7
+ logger,
8
+ debugOpenRouterBody: runtimeConfig?.debugOpenRouterBody,
9
+ });
6
10
  router.registerProvider(provider);
7
11
  const adapter = createOpenRouterRuntimeAdapter();
8
12
  router.getAdapterRegistry().register(adapter);
9
13
  logger?.info('Registered OpenRouter runtime provider and adapter', {
10
14
  provider: 'openrouter',
11
15
  runtimeEnabled: true,
16
+ debugOpenRouterBody: runtimeConfig?.debugOpenRouterBody,
12
17
  });
13
18
  }
14
19
  export { shouldUseOpenRouterRuntime, resolveOpenRouterRuntimeDefaults } from './should-use-openrouter-runtime.js';
@@ -176,6 +176,12 @@ export interface GatewayOpenRouterRuntimeConfig {
176
176
  enabled?: boolean;
177
177
  apiMode?: 'chat' | 'responses' | 'auto';
178
178
  includeRawInTrace?: boolean;
179
+ /**
180
+ * Emit the exact compiled OpenRouter request body at debug level before fetch.
181
+ * Intended for short-lived diagnostics; request prompts/content are included.
182
+ * Can also be enabled with AI_GATEWAY_DEBUG_OPENROUTER_BODY=1.
183
+ */
184
+ debugOpenRouterBody?: boolean;
179
185
  }
180
186
  export interface GatewayServerToolUsage {
181
187
  requested: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@x12i/ai-gateway",
3
- "version": "11.0.1",
3
+ "version": "11.0.2",
4
4
  "description": "AI Gateway - Unified interface for LLM provider routing and management",
5
5
  "type": "module",
6
6
  "exports": {
@@ -44,11 +44,11 @@
44
44
  "dependencies": {
45
45
  "@x12i/activix": "^9.0.2",
46
46
  "@x12i/ai-profiles": "^3.4.1",
47
- "@x12i/ai-providers-router": "^4.11.0",
47
+ "@x12i/ai-providers-router": "^4.11.1",
48
48
  "@x12i/ai-tools": "^3.3.5",
49
49
  "@x12i/flex-md": "^4.8.0",
50
50
  "@x12i/logxer": "^5.1.0",
51
- "@x12i/openrouter-runtime": "^1.0.4",
51
+ "@x12i/openrouter-runtime": "^1.0.5",
52
52
  "@x12i/rendrix": "^4.3.0"
53
53
  },
54
54
  "devDependencies": {