@x12i/ai-gateway 9.6.7 → 9.6.9
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/defaults/log-diagnostics.json +176 -0
- package/dist/gateway-config.js +10 -1
- package/dist/gateway-log-diagnostics.d.ts +23 -0
- package/dist/gateway-log-diagnostics.js +72 -0
- package/dist/gateway-log-levels.d.ts +23 -0
- package/dist/gateway-log-levels.js +33 -0
- package/dist/gateway-mode.js +13 -4
- package/dist/gateway-retry.js +19 -4
- package/dist/gateway.js +44 -18
- package/dist/index.d.ts +7 -3
- package/dist/index.js +5 -2
- package/dist/logger-factory.d.ts +11 -3
- package/dist/logger-factory.js +32 -6
- package/dist/optimixer-manager.js +16 -6
- package/dist/runtime-objects.d.ts +1 -1
- package/dist/runtime-objects.js +10 -1
- package/dist/types.d.ts +8 -1
- package/dist-cjs/defaults/log-diagnostics.json +176 -0
- package/dist-cjs/gateway-config.cjs +10 -1
- package/dist-cjs/gateway-log-diagnostics.cjs +72 -0
- package/dist-cjs/gateway-log-diagnostics.d.ts +23 -0
- package/dist-cjs/gateway-log-levels.cjs +33 -0
- package/dist-cjs/gateway-log-levels.d.ts +23 -0
- package/dist-cjs/gateway-mode.cjs +13 -4
- package/dist-cjs/gateway-retry.cjs +19 -4
- package/dist-cjs/gateway.cjs +44 -18
- package/dist-cjs/index.cjs +5 -2
- package/dist-cjs/index.d.ts +7 -3
- package/dist-cjs/logger-factory.cjs +32 -6
- package/dist-cjs/logger-factory.d.ts +11 -3
- package/dist-cjs/optimixer-manager.cjs +16 -6
- package/dist-cjs/runtime-objects.cjs +10 -1
- package/dist-cjs/runtime-objects.d.ts +1 -1
- package/dist-cjs/types.d.ts +8 -1
- package/package.json +4 -4
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
{
|
|
2
|
+
"GATEWAY_ZERO_USAGE_OR_COST": {
|
|
3
|
+
"defaultLevel": "warn",
|
|
4
|
+
"title": "Successful invoke reported zero token usage and/or zero cost",
|
|
5
|
+
"impact": "Billing and usage metadata may be missing from the provider adapter.",
|
|
6
|
+
"possibleCauses": [
|
|
7
|
+
"Router adapter did not populate usage fields.",
|
|
8
|
+
"Provider response omitted token counts.",
|
|
9
|
+
"Cost calculation was skipped or returned zero."
|
|
10
|
+
],
|
|
11
|
+
"remediation": [
|
|
12
|
+
"Verify router adapter usage extraction.",
|
|
13
|
+
"Confirm ai-tools cost resolution is enabled when pricing is expected."
|
|
14
|
+
],
|
|
15
|
+
"retryable": false,
|
|
16
|
+
"userActionRequired": false,
|
|
17
|
+
"confidence": "medium"
|
|
18
|
+
},
|
|
19
|
+
"GATEWAY_FALLBACK_CHAIN_EXHAUSTED": {
|
|
20
|
+
"defaultLevel": "error",
|
|
21
|
+
"title": "Provider fallback chain exhausted without a successful response",
|
|
22
|
+
"impact": "The AI request failed after all configured provider/model candidates were tried.",
|
|
23
|
+
"possibleCauses": [
|
|
24
|
+
"All providers in the chain returned errors.",
|
|
25
|
+
"Rate limits or auth failures across candidates.",
|
|
26
|
+
"Model or profile misconfiguration."
|
|
27
|
+
],
|
|
28
|
+
"remediation": [
|
|
29
|
+
"Inspect fallbackAttempts in the log evidence.",
|
|
30
|
+
"Verify API keys and provider registration.",
|
|
31
|
+
"Review trace-mode metadata.attempts when enabled."
|
|
32
|
+
],
|
|
33
|
+
"retryable": true,
|
|
34
|
+
"userActionRequired": true,
|
|
35
|
+
"confidence": "high"
|
|
36
|
+
},
|
|
37
|
+
"GATEWAY_FLEX_MD_EXTRACTION_FAILED": {
|
|
38
|
+
"defaultLevel": "warn",
|
|
39
|
+
"title": "Flex-md extraction did not produce structured output",
|
|
40
|
+
"impact": "Parsed content falls back to a rawText wrapper; downstream contract validation may fail.",
|
|
41
|
+
"possibleCauses": [
|
|
42
|
+
"Model response was plain text without expected markdown structure.",
|
|
43
|
+
"flex-md headers or fenced blocks were missing.",
|
|
44
|
+
"Response was truncated before structured content completed."
|
|
45
|
+
],
|
|
46
|
+
"remediation": [
|
|
47
|
+
"Inspect raw response sample.",
|
|
48
|
+
"Tighten instructions for markdown/JSON output format.",
|
|
49
|
+
"Check max token allocation."
|
|
50
|
+
],
|
|
51
|
+
"retryable": true,
|
|
52
|
+
"userActionRequired": false,
|
|
53
|
+
"confidence": "medium"
|
|
54
|
+
},
|
|
55
|
+
"GATEWAY_FLEX_MD_EXTRACTION_ERROR": {
|
|
56
|
+
"defaultLevel": "warn",
|
|
57
|
+
"title": "Flex-md extraction threw during parsing",
|
|
58
|
+
"impact": "Structured parsing failed; gateway uses rawText fallback.",
|
|
59
|
+
"possibleCauses": [
|
|
60
|
+
"flex-md library compatibility or loader issue.",
|
|
61
|
+
"Malformed markdown in the model response.",
|
|
62
|
+
"Unexpected response shape from the provider."
|
|
63
|
+
],
|
|
64
|
+
"remediation": [
|
|
65
|
+
"Review the exception evidence.",
|
|
66
|
+
"Confirm flex-md version alignment with the gateway.",
|
|
67
|
+
"Inspect raw provider content."
|
|
68
|
+
],
|
|
69
|
+
"retryable": true,
|
|
70
|
+
"userActionRequired": false,
|
|
71
|
+
"confidence": "medium"
|
|
72
|
+
},
|
|
73
|
+
"GATEWAY_DEFAULT_MODEL_SUBSTITUTED": {
|
|
74
|
+
"defaultLevel": "warn",
|
|
75
|
+
"title": "Gateway substituted the configured default model",
|
|
76
|
+
"impact": "The request may run on a different provider/model than the caller specified.",
|
|
77
|
+
"possibleCauses": [
|
|
78
|
+
"Request omitted model while gateway defaults apply.",
|
|
79
|
+
"Operational mode requires a packaged default engine.",
|
|
80
|
+
"Profile resolution fell back to gateway defaults."
|
|
81
|
+
],
|
|
82
|
+
"remediation": [
|
|
83
|
+
"Pass an explicit model on the request when substitution is undesired.",
|
|
84
|
+
"Review default model configuration and AI_TOOLS routing."
|
|
85
|
+
],
|
|
86
|
+
"retryable": false,
|
|
87
|
+
"userActionRequired": false,
|
|
88
|
+
"confidence": "high"
|
|
89
|
+
},
|
|
90
|
+
"GATEWAY_RETRY_MAX_EXCEEDED": {
|
|
91
|
+
"defaultLevel": "warn",
|
|
92
|
+
"title": "Provider invoke retries exhausted",
|
|
93
|
+
"impact": "The router call failed after the configured retry budget.",
|
|
94
|
+
"possibleCauses": [
|
|
95
|
+
"Transient network or server errors persisted.",
|
|
96
|
+
"Throttling (429) without sufficient backoff.",
|
|
97
|
+
"Non-recoverable provider outage."
|
|
98
|
+
],
|
|
99
|
+
"remediation": [
|
|
100
|
+
"Inspect error and status code evidence.",
|
|
101
|
+
"Increase retry limits or backoff if appropriate.",
|
|
102
|
+
"Check provider status and rate limits."
|
|
103
|
+
],
|
|
104
|
+
"retryable": true,
|
|
105
|
+
"userActionRequired": false,
|
|
106
|
+
"confidence": "high"
|
|
107
|
+
},
|
|
108
|
+
"GATEWAY_RETRY_ATTEMPT": {
|
|
109
|
+
"defaultLevel": "warn",
|
|
110
|
+
"title": "Retrying provider invoke after error",
|
|
111
|
+
"impact": "Request latency increases while the gateway retries.",
|
|
112
|
+
"possibleCauses": [
|
|
113
|
+
"Transient HTTP or network failure.",
|
|
114
|
+
"Rate limiting with backoff.",
|
|
115
|
+
"Timeout from the provider."
|
|
116
|
+
],
|
|
117
|
+
"remediation": [
|
|
118
|
+
"Monitor retry counts per job.",
|
|
119
|
+
"Tune retry policy if retries are frequent."
|
|
120
|
+
],
|
|
121
|
+
"retryable": true,
|
|
122
|
+
"userActionRequired": false,
|
|
123
|
+
"confidence": "medium"
|
|
124
|
+
},
|
|
125
|
+
"GATEWAY_OPTIMIXER_ACTIVIX_UNAVAILABLE": {
|
|
126
|
+
"defaultLevel": "warn",
|
|
127
|
+
"title": "Optimixer enabled but Activix is unavailable",
|
|
128
|
+
"impact": "Adaptive max_tokens prediction is disabled for this gateway instance.",
|
|
129
|
+
"possibleCauses": [
|
|
130
|
+
"Activity tracking is disabled or Activix failed to initialize.",
|
|
131
|
+
"Mongo connection or collection configuration is missing."
|
|
132
|
+
],
|
|
133
|
+
"remediation": [
|
|
134
|
+
"Enable activity tracking with a working Activix connection.",
|
|
135
|
+
"Verify activixCollection configuration."
|
|
136
|
+
],
|
|
137
|
+
"retryable": false,
|
|
138
|
+
"userActionRequired": true,
|
|
139
|
+
"confidence": "high"
|
|
140
|
+
},
|
|
141
|
+
"GATEWAY_OPTIMIXER_INIT_FAILED": {
|
|
142
|
+
"defaultLevel": "warn",
|
|
143
|
+
"title": "Optimixer initialization failed",
|
|
144
|
+
"impact": "Adaptive max_tokens prediction is disabled.",
|
|
145
|
+
"possibleCauses": [
|
|
146
|
+
"Activix schema or collection mismatch.",
|
|
147
|
+
"Optimixer configuration error.",
|
|
148
|
+
"Dependency or network failure during create()."
|
|
149
|
+
],
|
|
150
|
+
"remediation": [
|
|
151
|
+
"Check Activix connectivity and collection names.",
|
|
152
|
+
"Review optimixer gateway config."
|
|
153
|
+
],
|
|
154
|
+
"retryable": false,
|
|
155
|
+
"userActionRequired": true,
|
|
156
|
+
"confidence": "high"
|
|
157
|
+
},
|
|
158
|
+
"GATEWAY_OPTIMIXER_PREDICT_FAILED": {
|
|
159
|
+
"defaultLevel": "warn",
|
|
160
|
+
"title": "Optimixer predictAiMaxTokens failed",
|
|
161
|
+
"impact": "Caller should use fallback max_tokens for the invoke.",
|
|
162
|
+
"possibleCauses": [
|
|
163
|
+
"Insufficient historical samples for the template.",
|
|
164
|
+
"Token estimation or profile resolution failed.",
|
|
165
|
+
"Optimixer internal error."
|
|
166
|
+
],
|
|
167
|
+
"remediation": [
|
|
168
|
+
"Set explicit max_tokens on the request.",
|
|
169
|
+
"Verify templateId and model profile fields.",
|
|
170
|
+
"Check prediction history in Activix."
|
|
171
|
+
],
|
|
172
|
+
"retryable": true,
|
|
173
|
+
"userActionRequired": false,
|
|
174
|
+
"confidence": "medium"
|
|
175
|
+
}
|
|
176
|
+
}
|
package/dist/gateway-config.js
CHANGED
|
@@ -162,7 +162,10 @@ export function initializeGatewayComponents(config) {
|
|
|
162
162
|
const logger = createGatewayLogger({
|
|
163
163
|
enableLogging: config.enableLogging ?? true,
|
|
164
164
|
packageName: config.packageName,
|
|
165
|
-
customLogger: config.logger
|
|
165
|
+
customLogger: config.logger,
|
|
166
|
+
logging: config.logging,
|
|
167
|
+
packageLogLevels: config.packageLogLevels,
|
|
168
|
+
logLevel: config.logLevel
|
|
166
169
|
});
|
|
167
170
|
const { defaultModelConfig, defaultInstructionsBlocks, defaultTemplateRendering } = loadConfig(logger);
|
|
168
171
|
logger.verbose('Gateway initializing', {
|
|
@@ -194,6 +197,12 @@ export function initializeGatewayComponents(config) {
|
|
|
194
197
|
routerConfig.autoDiscover = config.autoDiscover;
|
|
195
198
|
if (config.usageTracker !== undefined)
|
|
196
199
|
routerConfig.usageTracker = config.usageTracker;
|
|
200
|
+
if (config.verbose !== undefined)
|
|
201
|
+
routerConfig.verbose = config.verbose;
|
|
202
|
+
if (config.logLevel !== undefined)
|
|
203
|
+
routerConfig.logLevel = config.logLevel;
|
|
204
|
+
if (config.logging !== undefined)
|
|
205
|
+
routerConfig.logging = config.logging;
|
|
197
206
|
// OpenRouter: always pass apiKey when set (fallback for providers without direct keys).
|
|
198
207
|
// USE_OPENROUTER=false only disables *preferring* OpenRouter when direct provider keys exist.
|
|
199
208
|
const openRouterKey = resolveOpenRouterApiKey(config);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { exceptionEvidence, fieldEvidence, type LogMeta, type Logxer } from '@x12i/logxer';
|
|
2
|
+
import type { ActivityIdentity } from './types.js';
|
|
3
|
+
export { exceptionEvidence, fieldEvidence };
|
|
4
|
+
/** Stable diagnostic codes backed by `src/defaults/log-diagnostics.json`. */
|
|
5
|
+
export declare const GatewayLogCode: {
|
|
6
|
+
readonly ZERO_USAGE_OR_COST: "GATEWAY_ZERO_USAGE_OR_COST";
|
|
7
|
+
readonly FALLBACK_CHAIN_EXHAUSTED: "GATEWAY_FALLBACK_CHAIN_EXHAUSTED";
|
|
8
|
+
readonly FLEX_MD_EXTRACTION_FAILED: "GATEWAY_FLEX_MD_EXTRACTION_FAILED";
|
|
9
|
+
readonly FLEX_MD_EXTRACTION_ERROR: "GATEWAY_FLEX_MD_EXTRACTION_ERROR";
|
|
10
|
+
readonly DEFAULT_MODEL_SUBSTITUTED: "GATEWAY_DEFAULT_MODEL_SUBSTITUTED";
|
|
11
|
+
readonly RETRY_MAX_EXCEEDED: "GATEWAY_RETRY_MAX_EXCEEDED";
|
|
12
|
+
readonly RETRY_ATTEMPT: "GATEWAY_RETRY_ATTEMPT";
|
|
13
|
+
readonly OPTIMIXER_ACTIVIX_UNAVAILABLE: "GATEWAY_OPTIMIXER_ACTIVIX_UNAVAILABLE";
|
|
14
|
+
readonly OPTIMIXER_INIT_FAILED: "GATEWAY_OPTIMIXER_INIT_FAILED";
|
|
15
|
+
readonly OPTIMIXER_PREDICT_FAILED: "GATEWAY_OPTIMIXER_PREDICT_FAILED";
|
|
16
|
+
};
|
|
17
|
+
export type GatewayLogCode = (typeof GatewayLogCode)[keyof typeof GatewayLogCode];
|
|
18
|
+
/** Resolve packaged `defaults/log-diagnostics.json` for createLogxer diagnostics.catalogPath. */
|
|
19
|
+
export declare function resolveLogDiagnosticsCatalogPath(): string | undefined;
|
|
20
|
+
export declare function gatewayWarnCode(logger: Logxer, code: GatewayLogCode | string, identity: Partial<ActivityIdentity> | undefined, data?: LogMeta): void;
|
|
21
|
+
export declare function gatewayErrorCode(logger: Logxer, code: GatewayLogCode | string, identity: Partial<ActivityIdentity> | undefined, data?: LogMeta): void;
|
|
22
|
+
export declare function gatewayInfoCode(logger: Logxer, code: GatewayLogCode | string, identity: Partial<ActivityIdentity> | undefined, data?: LogMeta): void;
|
|
23
|
+
export declare function gatewayAnomalyMeta(identity: Partial<ActivityIdentity> | undefined, data?: LogMeta): LogMeta;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logxer 4.4+ diagnostic catalog codes and helpers for structured anomaly logging.
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { exceptionEvidence, fieldEvidence } from '@x12i/logxer';
|
|
8
|
+
import { gatewayLogDebug, withActivityIdentity } from './gateway-log-meta.js';
|
|
9
|
+
export { exceptionEvidence, fieldEvidence };
|
|
10
|
+
/** Stable diagnostic codes backed by `src/defaults/log-diagnostics.json`. */
|
|
11
|
+
export const GatewayLogCode = {
|
|
12
|
+
ZERO_USAGE_OR_COST: 'GATEWAY_ZERO_USAGE_OR_COST',
|
|
13
|
+
FALLBACK_CHAIN_EXHAUSTED: 'GATEWAY_FALLBACK_CHAIN_EXHAUSTED',
|
|
14
|
+
FLEX_MD_EXTRACTION_FAILED: 'GATEWAY_FLEX_MD_EXTRACTION_FAILED',
|
|
15
|
+
FLEX_MD_EXTRACTION_ERROR: 'GATEWAY_FLEX_MD_EXTRACTION_ERROR',
|
|
16
|
+
DEFAULT_MODEL_SUBSTITUTED: 'GATEWAY_DEFAULT_MODEL_SUBSTITUTED',
|
|
17
|
+
RETRY_MAX_EXCEEDED: 'GATEWAY_RETRY_MAX_EXCEEDED',
|
|
18
|
+
RETRY_ATTEMPT: 'GATEWAY_RETRY_ATTEMPT',
|
|
19
|
+
OPTIMIXER_ACTIVIX_UNAVAILABLE: 'GATEWAY_OPTIMIXER_ACTIVIX_UNAVAILABLE',
|
|
20
|
+
OPTIMIXER_INIT_FAILED: 'GATEWAY_OPTIMIXER_INIT_FAILED',
|
|
21
|
+
OPTIMIXER_PREDICT_FAILED: 'GATEWAY_OPTIMIXER_PREDICT_FAILED'
|
|
22
|
+
};
|
|
23
|
+
function getModuleDir() {
|
|
24
|
+
if (typeof __dirname !== 'undefined') {
|
|
25
|
+
return __dirname;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const getMetaUrl = new Function('return import.meta.url');
|
|
29
|
+
const metaUrl = getMetaUrl();
|
|
30
|
+
if (metaUrl && metaUrl.startsWith('file:')) {
|
|
31
|
+
return path.dirname(fileURLToPath(metaUrl));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// fall through
|
|
36
|
+
}
|
|
37
|
+
return process.cwd();
|
|
38
|
+
}
|
|
39
|
+
/** Resolve packaged `defaults/log-diagnostics.json` for createLogxer diagnostics.catalogPath. */
|
|
40
|
+
export function resolveLogDiagnosticsCatalogPath() {
|
|
41
|
+
const moduleDir = getModuleDir();
|
|
42
|
+
const cwd = process.cwd();
|
|
43
|
+
const candidates = [
|
|
44
|
+
moduleDir,
|
|
45
|
+
path.resolve(moduleDir, '..'),
|
|
46
|
+
path.resolve(moduleDir, '../dist'),
|
|
47
|
+
path.resolve(moduleDir, '../dist-cjs'),
|
|
48
|
+
path.resolve(moduleDir, '../src'),
|
|
49
|
+
path.join(cwd, 'dist'),
|
|
50
|
+
path.join(cwd, 'dist-cjs'),
|
|
51
|
+
path.join(cwd, 'src')
|
|
52
|
+
];
|
|
53
|
+
for (const dir of candidates) {
|
|
54
|
+
const catalogPath = path.join(dir, 'defaults', 'log-diagnostics.json');
|
|
55
|
+
if (fs.existsSync(catalogPath)) {
|
|
56
|
+
return catalogPath;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
export function gatewayWarnCode(logger, code, identity, data) {
|
|
62
|
+
logger.warnCode(code, withActivityIdentity(identity, data));
|
|
63
|
+
}
|
|
64
|
+
export function gatewayErrorCode(logger, code, identity, data) {
|
|
65
|
+
logger.errorCode(code, withActivityIdentity(identity, data));
|
|
66
|
+
}
|
|
67
|
+
export function gatewayInfoCode(logger, code, identity, data) {
|
|
68
|
+
logger.infoCode(code, withActivityIdentity(identity, data));
|
|
69
|
+
}
|
|
70
|
+
export function gatewayAnomalyMeta(identity, data) {
|
|
71
|
+
return withActivityIdentity(identity, data, gatewayLogDebug.anomaly);
|
|
72
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logxer ≥ 4.5 — process-wide package log levels for the gateway dependency stack.
|
|
3
|
+
* @see node_modules/@x12i/logxer/docs/package-log-levels-stack.md
|
|
4
|
+
*/
|
|
5
|
+
import { type PackageLogLevelsConfig } from '@x12i/logxer';
|
|
6
|
+
/** Stable ERC 2.0 env prefix — controls `AI_GATEWAY_LOGS_LEVEL`, etc. */
|
|
7
|
+
export declare const GATEWAY_LOG_ENV_PREFIX = "AI_GATEWAY";
|
|
8
|
+
/** Known `envPrefix` values in this package's dependency stack (for hosts / `.env`). */
|
|
9
|
+
export declare const GATEWAY_STACK_LOG_PREFIXES: {
|
|
10
|
+
readonly gateway: "AI_GATEWAY";
|
|
11
|
+
readonly router: "AI_PROVIDER_ROUTER";
|
|
12
|
+
readonly flexMd: "FLEX_MD";
|
|
13
|
+
readonly optimixer: "OPTIMIXER";
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Load bulk env (`LOGXER_PACKAGE_LEVELS`, `LOGXER_PACKAGE_LOGS_DEFAULT`) and merge optional host config.
|
|
17
|
+
* Idempotent — safe to call from `createGatewayLogger` / `initializeGatewayComponents`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function initializeGatewayPackageLogLevels(options?: {
|
|
20
|
+
packageLogLevels?: PackageLogLevelsConfig;
|
|
21
|
+
}): void;
|
|
22
|
+
/** Reset init flag (tests). */
|
|
23
|
+
export declare function resetGatewayPackageLogLevelsInit(): void;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logxer ≥ 4.5 — process-wide package log levels for the gateway dependency stack.
|
|
3
|
+
* @see node_modules/@x12i/logxer/docs/package-log-levels-stack.md
|
|
4
|
+
*/
|
|
5
|
+
import { applyPackageLogLevelsFromEnv, mergePackageLogLevelsConfig } from '@x12i/logxer';
|
|
6
|
+
import { ROUTER_LOG_ENV_PREFIX } from '@x12i/ai-providers-router';
|
|
7
|
+
/** Stable ERC 2.0 env prefix — controls `AI_GATEWAY_LOGS_LEVEL`, etc. */
|
|
8
|
+
export const GATEWAY_LOG_ENV_PREFIX = 'AI_GATEWAY';
|
|
9
|
+
/** Known `envPrefix` values in this package's dependency stack (for hosts / `.env`). */
|
|
10
|
+
export const GATEWAY_STACK_LOG_PREFIXES = {
|
|
11
|
+
gateway: GATEWAY_LOG_ENV_PREFIX,
|
|
12
|
+
router: ROUTER_LOG_ENV_PREFIX,
|
|
13
|
+
flexMd: 'FLEX_MD',
|
|
14
|
+
optimixer: 'OPTIMIXER'
|
|
15
|
+
};
|
|
16
|
+
let packageLogLevelsInitialized = false;
|
|
17
|
+
/**
|
|
18
|
+
* Load bulk env (`LOGXER_PACKAGE_LEVELS`, `LOGXER_PACKAGE_LOGS_DEFAULT`) and merge optional host config.
|
|
19
|
+
* Idempotent — safe to call from `createGatewayLogger` / `initializeGatewayComponents`.
|
|
20
|
+
*/
|
|
21
|
+
export function initializeGatewayPackageLogLevels(options) {
|
|
22
|
+
if (!packageLogLevelsInitialized) {
|
|
23
|
+
applyPackageLogLevelsFromEnv();
|
|
24
|
+
packageLogLevelsInitialized = true;
|
|
25
|
+
}
|
|
26
|
+
if (options?.packageLogLevels) {
|
|
27
|
+
mergePackageLogLevelsConfig(options.packageLogLevels);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Reset init flag (tests). */
|
|
31
|
+
export function resetGatewayPackageLogLevelsInit() {
|
|
32
|
+
packageLogLevelsInitialized = false;
|
|
33
|
+
}
|
package/dist/gateway-mode.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Gateway operational mode (prod vs dev/debug) and default model resolution.
|
|
3
3
|
*/
|
|
4
|
-
import { gatewayLogDebug
|
|
4
|
+
import { gatewayLogDebug } from './gateway-log-meta.js';
|
|
5
|
+
import { fieldEvidence, GatewayLogCode, gatewayWarnCode } from './gateway-log-diagnostics.js';
|
|
5
6
|
/** Profile name resolved via ai-tools + {@link @x12i/ai-profiles} when catalog is enabled. */
|
|
6
7
|
export const CODE_DEFAULT_MODEL = 'cheap';
|
|
7
8
|
/**
|
|
@@ -69,8 +70,16 @@ export function resolveGatewayDefaultModel(defaultModelConfig, gatewayDefaultEng
|
|
|
69
70
|
};
|
|
70
71
|
}
|
|
71
72
|
export function warnDefaultModelSubstitution(logger, identity, details) {
|
|
72
|
-
logger.
|
|
73
|
+
gatewayWarnCode(logger, GatewayLogCode.DEFAULT_MODEL_SUBSTITUTED, identity, {
|
|
73
74
|
...details,
|
|
74
|
-
debugKind: gatewayLogDebug.anomaly
|
|
75
|
-
|
|
75
|
+
debugKind: gatewayLogDebug.anomaly,
|
|
76
|
+
evidence: [
|
|
77
|
+
fieldEvidence('defaultModel', details.defaultModel),
|
|
78
|
+
fieldEvidence('defaultSource', details.defaultSource),
|
|
79
|
+
fieldEvidence('reason', details.reason),
|
|
80
|
+
fieldEvidence('mode', details.mode),
|
|
81
|
+
...(details.originalModel ? [fieldEvidence('originalModel', details.originalModel)] : []),
|
|
82
|
+
...(details.originalProvider ? [fieldEvidence('originalProvider', details.originalProvider)] : [])
|
|
83
|
+
]
|
|
84
|
+
});
|
|
76
85
|
}
|
package/dist/gateway-retry.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* NOTE: Retry delays use SIMPLE SLEEP (not smart rate limiting).
|
|
6
6
|
* Between-calls rate limiting is handled separately in gateway-rate-limiter.ts (smart).
|
|
7
7
|
*/
|
|
8
|
+
import { exceptionEvidence, fieldEvidence, GatewayLogCode, gatewayWarnCode } from './gateway-log-diagnostics.js';
|
|
8
9
|
/**
|
|
9
10
|
* Determines if an error is a network error (fetch failed, DNS, connectivity)
|
|
10
11
|
*/
|
|
@@ -146,12 +147,18 @@ export async function invokeWithRetry(routerRequest, retryConfig, jobId, router,
|
|
|
146
147
|
}
|
|
147
148
|
// If this was the last attempt, throw the error
|
|
148
149
|
if (attempt >= maxRetries) {
|
|
149
|
-
logger.
|
|
150
|
+
gatewayWarnCode(logger, GatewayLogCode.RETRY_MAX_EXCEEDED, undefined, {
|
|
150
151
|
jobId,
|
|
151
152
|
error: lastError.message,
|
|
152
153
|
errorName: lastError.name,
|
|
153
154
|
totalAttempts: attempt + 1,
|
|
154
|
-
maxRetries
|
|
155
|
+
maxRetries,
|
|
156
|
+
evidence: [
|
|
157
|
+
fieldEvidence('jobId', jobId),
|
|
158
|
+
fieldEvidence('totalAttempts', attempt + 1),
|
|
159
|
+
fieldEvidence('maxRetries', maxRetries),
|
|
160
|
+
exceptionEvidence(lastError)
|
|
161
|
+
]
|
|
155
162
|
});
|
|
156
163
|
throw lastError;
|
|
157
164
|
}
|
|
@@ -187,7 +194,7 @@ export async function invokeWithRetry(routerRequest, retryConfig, jobId, router,
|
|
|
187
194
|
errorType,
|
|
188
195
|
delayMs: Math.round(delay)
|
|
189
196
|
});
|
|
190
|
-
logger.
|
|
197
|
+
gatewayWarnCode(logger, GatewayLogCode.RETRY_ATTEMPT, undefined, {
|
|
191
198
|
jobId,
|
|
192
199
|
error: lastError.message,
|
|
193
200
|
errorName: lastError.name,
|
|
@@ -195,7 +202,15 @@ export async function invokeWithRetry(routerRequest, retryConfig, jobId, router,
|
|
|
195
202
|
attempt: attempt + 1,
|
|
196
203
|
maxRetries: maxRetries + 1,
|
|
197
204
|
delayMs: Math.round(delay),
|
|
198
|
-
statusCode
|
|
205
|
+
statusCode,
|
|
206
|
+
evidence: [
|
|
207
|
+
fieldEvidence('jobId', jobId),
|
|
208
|
+
fieldEvidence('attempt', attempt + 1),
|
|
209
|
+
fieldEvidence('errorType', errorType),
|
|
210
|
+
fieldEvidence('delayMs', Math.round(delay)),
|
|
211
|
+
...(statusCode !== undefined ? [fieldEvidence('statusCode', statusCode)] : []),
|
|
212
|
+
exceptionEvidence(lastError)
|
|
213
|
+
]
|
|
199
214
|
});
|
|
200
215
|
await sleep(delay);
|
|
201
216
|
}
|
package/dist/gateway.js
CHANGED
|
@@ -16,6 +16,7 @@ import { autoRegisterProviders } from './gateway-provider-auto-register.js';
|
|
|
16
16
|
import { applyOpenRouterInvokePolicy } from './ai-tools-client.js';
|
|
17
17
|
import { setGatewayLastJobId, setGatewayRuntimeClients } from './runtime-objects.js';
|
|
18
18
|
import { gatewayLogDebug, withActivityIdentity, withGatewayLogContext } from './gateway-log-meta.js';
|
|
19
|
+
import { exceptionEvidence, fieldEvidence, GatewayLogCode, gatewayErrorCode, gatewayWarnCode } from './gateway-log-diagnostics.js';
|
|
19
20
|
import { invokeWithRetry } from './gateway-retry.js';
|
|
20
21
|
/** Error message thrown by the router when no provider is registered or specified */
|
|
21
22
|
const NO_PROVIDER_ERROR = 'No provider specified and no providers registered';
|
|
@@ -28,16 +29,24 @@ function warnIfSuccessfulInvokeReportsZeroUsageOrCost(logger, identity, meta, in
|
|
|
28
29
|
const zeroCost = typeof cost === 'number' && cost === 0;
|
|
29
30
|
if (!zeroTokens && !zeroCostUsd && !zeroCost)
|
|
30
31
|
return;
|
|
31
|
-
logger.
|
|
32
|
+
gatewayWarnCode(logger, GatewayLogCode.ZERO_USAGE_OR_COST, identity, {
|
|
32
33
|
invokeKind,
|
|
33
34
|
zeroTokens,
|
|
34
35
|
zeroCostUsd,
|
|
35
36
|
zeroCostField: zeroCost,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
debugKind: gatewayLogDebug.anomaly,
|
|
38
|
+
evidence: [
|
|
39
|
+
fieldEvidence('tokens.prompt', tokens.prompt),
|
|
40
|
+
fieldEvidence('tokens.completion', tokens.completion),
|
|
41
|
+
fieldEvidence('tokens.total', tokens.total),
|
|
42
|
+
fieldEvidence('costUsd', costUsd),
|
|
43
|
+
fieldEvidence('cost', cost)
|
|
44
|
+
],
|
|
45
|
+
diagnostics: {
|
|
46
|
+
expected: 'Successful invoke should include non-zero token usage or cost when billing metadata is available.',
|
|
47
|
+
actual: `zeroTokens=${zeroTokens}, zeroCostUsd=${zeroCostUsd}, zeroCost=${zeroCost}`
|
|
48
|
+
}
|
|
49
|
+
});
|
|
41
50
|
}
|
|
42
51
|
/**
|
|
43
52
|
* Simplified AI Gateway - Clean proxy implementation
|
|
@@ -494,12 +503,20 @@ export class AIGateway {
|
|
|
494
503
|
if (!response) {
|
|
495
504
|
const fallbackAttempts = buildGatewayFallbackAttemptsFromTrace(traceAttempts, deduped, lastError);
|
|
496
505
|
const providersTried = [...new Set(deduped.map((c) => c.provider))];
|
|
497
|
-
this.logger.
|
|
506
|
+
gatewayErrorCode(this.logger, GatewayLogCode.FALLBACK_CHAIN_EXHAUSTED, request.identity, {
|
|
498
507
|
providersTried,
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
508
|
+
debugKind: gatewayLogDebug.anomaly,
|
|
509
|
+
evidence: [
|
|
510
|
+
fieldEvidence('providersTried', providersTried),
|
|
511
|
+
fieldEvidence('candidateCount', deduped.length),
|
|
512
|
+
fieldEvidence('fallbackAttempts', fallbackAttempts),
|
|
513
|
+
...(lastError ? [fieldEvidence('lastError.message', lastError.message)] : [])
|
|
514
|
+
],
|
|
515
|
+
diagnostics: {
|
|
516
|
+
expected: 'At least one provider/model candidate in the fallback chain should succeed.',
|
|
517
|
+
actual: 'All candidates failed or returned no response.'
|
|
518
|
+
}
|
|
519
|
+
});
|
|
503
520
|
const exhausted = new FallbackExhaustedError(mapGatewayFallbackAttemptsToRouter(fallbackAttempts));
|
|
504
521
|
exhausted.message = formatFallbackExhaustionMessage(fallbackAttempts, deduped);
|
|
505
522
|
if (lastError) {
|
|
@@ -570,23 +587,32 @@ export class AIGateway {
|
|
|
570
587
|
}
|
|
571
588
|
else {
|
|
572
589
|
// Extraction failed, fall back to raw text wrapper
|
|
573
|
-
this.logger.
|
|
590
|
+
gatewayWarnCode(this.logger, GatewayLogCode.FLEX_MD_EXTRACTION_FAILED, request.identity, {
|
|
574
591
|
hasResult: !!extractionResult,
|
|
575
592
|
method: extractionResult?.method || 'none',
|
|
576
|
-
debugKind: gatewayLogDebug.anomaly
|
|
577
|
-
|
|
593
|
+
debugKind: gatewayLogDebug.anomaly,
|
|
594
|
+
evidence: [
|
|
595
|
+
fieldEvidence('content.length', content.length),
|
|
596
|
+
fieldEvidence('extraction.method', extractionResult?.method || 'none')
|
|
597
|
+
]
|
|
598
|
+
});
|
|
578
599
|
parsedContent = { rawText: content };
|
|
579
600
|
}
|
|
580
601
|
}
|
|
581
602
|
catch (extractionError) {
|
|
582
603
|
// Extraction failed, fall back to raw text wrapper
|
|
583
604
|
const errorMessage = extractionError instanceof Error ? extractionError.message : String(extractionError);
|
|
584
|
-
this.logger.
|
|
605
|
+
gatewayWarnCode(this.logger, GatewayLogCode.FLEX_MD_EXTRACTION_ERROR, request.identity, {
|
|
585
606
|
error: errorMessage,
|
|
586
|
-
issue: 'flex-md uses require() in ES module context - needs fixing in flex-md-loader.ts',
|
|
587
607
|
fallback: 'using rawText wrapper',
|
|
588
|
-
debugKind: gatewayLogDebug.anomaly
|
|
589
|
-
|
|
608
|
+
debugKind: gatewayLogDebug.anomaly,
|
|
609
|
+
evidence: [
|
|
610
|
+
fieldEvidence('content.length', content.length),
|
|
611
|
+
...(extractionError instanceof Error
|
|
612
|
+
? [exceptionEvidence(extractionError)]
|
|
613
|
+
: [fieldEvidence('error.message', errorMessage)])
|
|
614
|
+
]
|
|
615
|
+
});
|
|
590
616
|
parsedContent = { rawText: content };
|
|
591
617
|
}
|
|
592
618
|
contentType = 'structured';
|
package/dist/index.d.ts
CHANGED
|
@@ -35,9 +35,13 @@ export { ActivityManager, ensureGatewayRequestIdentity } from './activity-manage
|
|
|
35
35
|
export { OptimixerManager } from './optimixer-manager.js';
|
|
36
36
|
export type { ActivityIdentity } from './types.js';
|
|
37
37
|
export { activityIdentityToLogContext, activityIdentityToLogMeta, withActivityIdentity, withGatewayLogContext, gatewayLogDebug } from './gateway-log-meta.js';
|
|
38
|
-
export { createGatewayLogger
|
|
39
|
-
export {
|
|
40
|
-
export
|
|
38
|
+
export { createGatewayLogger } from './logger-factory.js';
|
|
39
|
+
export { GATEWAY_LOG_ENV_PREFIX, GATEWAY_STACK_LOG_PREFIXES, initializeGatewayPackageLogLevels, resetGatewayPackageLogLevelsInit } from './gateway-log-levels.js';
|
|
40
|
+
export { GatewayLogCode, gatewayErrorCode, gatewayInfoCode, gatewayWarnCode, gatewayAnomalyMeta, resolveLogDiagnosticsCatalogPath, exceptionEvidence, fieldEvidence } from './gateway-log-diagnostics.js';
|
|
41
|
+
export type { GatewayLogCode as GatewayDiagnosticCode } from './gateway-log-diagnostics.js';
|
|
42
|
+
export { createLogxer, DebugLogAbstract, runWithLogContext, getStationRuntimeIdentity, mergeRuntimeIdentity, conditionEvidence, sourceEvidence, logReferenceEvidence, readAgentLoggingInstructions, resolveAgentLoggingInstructionsPath, applyPackageLogLevelsFromEnv, configurePackageLogLevels, mergePackageLogLevelsConfig, setPackageLogLevel, resolveStackLogLevelForPrefix, resolvePackageLogsLevel, parseLogxerPackageLevelsEnv, LOGXER_PACKAGE_LEVELS_ENV, LOGXER_PACKAGE_LOGS_DEFAULT_ENV } from '@x12i/logxer';
|
|
43
|
+
export { ROUTER_LOG_ENV_PREFIX } from '@x12i/ai-providers-router';
|
|
44
|
+
export type { Logxer, LogMeta, RuntimeIdentity, LogRuntimeContext, GetJobLogsInput, GetJobLogsResult, QueryableLogLine, LogDiagnostics, DiagnosticEvidence, ScopeCriteria, ScopeLogsResult, StackLoggingOptions, PackageLogLevelsConfig, PackageLogLevelSetting } from '@x12i/logxer';
|
|
41
45
|
export { runtimeObjects } from './runtime-objects.js';
|
|
42
46
|
export type { ActivixQueryableClient, LogxerQueryableClient, PackageRuntimeObjects, RuntimeObjects } from './runtime-objects.js';
|
|
43
47
|
export { GatewayRateLimiter } from './gateway-rate-limiter.js';
|
package/dist/index.js
CHANGED
|
@@ -30,9 +30,12 @@ export { normalizeToActivixCostShape } from '@x12i/activix';
|
|
|
30
30
|
export { ActivityManager, ensureGatewayRequestIdentity } from './activity-manager.js';
|
|
31
31
|
export { OptimixerManager } from './optimixer-manager.js';
|
|
32
32
|
export { activityIdentityToLogContext, activityIdentityToLogMeta, withActivityIdentity, withGatewayLogContext, gatewayLogDebug } from './gateway-log-meta.js';
|
|
33
|
-
export { createGatewayLogger
|
|
33
|
+
export { createGatewayLogger } from './logger-factory.js';
|
|
34
|
+
export { GATEWAY_LOG_ENV_PREFIX, GATEWAY_STACK_LOG_PREFIXES, initializeGatewayPackageLogLevels, resetGatewayPackageLogLevelsInit } from './gateway-log-levels.js';
|
|
35
|
+
export { GatewayLogCode, gatewayErrorCode, gatewayInfoCode, gatewayWarnCode, gatewayAnomalyMeta, resolveLogDiagnosticsCatalogPath, exceptionEvidence, fieldEvidence } from './gateway-log-diagnostics.js';
|
|
34
36
|
// Re-export logging (@x12i/logxer)
|
|
35
|
-
export { createLogxer, DebugLogAbstract, runWithLogContext, getStationRuntimeIdentity, mergeRuntimeIdentity } from '@x12i/logxer';
|
|
37
|
+
export { createLogxer, DebugLogAbstract, runWithLogContext, getStationRuntimeIdentity, mergeRuntimeIdentity, conditionEvidence, sourceEvidence, logReferenceEvidence, readAgentLoggingInstructions, resolveAgentLoggingInstructionsPath, applyPackageLogLevelsFromEnv, configurePackageLogLevels, mergePackageLogLevelsConfig, setPackageLogLevel, resolveStackLogLevelForPrefix, resolvePackageLogsLevel, parseLogxerPackageLevelsEnv, LOGXER_PACKAGE_LEVELS_ENV, LOGXER_PACKAGE_LOGS_DEFAULT_ENV } from '@x12i/logxer';
|
|
38
|
+
export { ROUTER_LOG_ENV_PREFIX } from '@x12i/ai-providers-router';
|
|
36
39
|
// Runtime observability surface (leaf package: no downstream runtime objects)
|
|
37
40
|
export { runtimeObjects } from './runtime-objects.js';
|
|
38
41
|
// Export rate limiter
|
package/dist/logger-factory.d.ts
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Creates and configures logxer instances for the gateway
|
|
5
5
|
*/
|
|
6
|
-
import { type Logxer } from '@x12i/logxer';
|
|
7
|
-
|
|
8
|
-
export
|
|
6
|
+
import { type LogLevel, type Logxer, type PackageLogLevelsConfig, type StackLoggingOptions } from '@x12i/logxer';
|
|
7
|
+
import { GATEWAY_LOG_ENV_PREFIX } from './gateway-log-levels.js';
|
|
8
|
+
export { GATEWAY_LOG_ENV_PREFIX };
|
|
9
|
+
/** True for the internal no-op logger when `enableLogging` is false. */
|
|
10
|
+
export declare function isNoOpGatewayLogger(logger: Logxer): boolean;
|
|
9
11
|
/**
|
|
10
12
|
* Creates a logger instance based on configuration
|
|
11
13
|
*
|
|
@@ -16,4 +18,10 @@ export declare function createGatewayLogger(config: {
|
|
|
16
18
|
enableLogging: boolean;
|
|
17
19
|
packageName?: string;
|
|
18
20
|
customLogger?: Logxer;
|
|
21
|
+
/** Parent/host pass-through (logxer ≥ 4.5). Forwarded as `createLogxer(..., { stack })`. */
|
|
22
|
+
logging?: StackLoggingOptions;
|
|
23
|
+
/** Merged into the process registry after `applyPackageLogLevelsFromEnv()`. */
|
|
24
|
+
packageLogLevels?: PackageLogLevelsConfig;
|
|
25
|
+
/** Explicit level for this gateway logger instance (wins over stack/registry/env). */
|
|
26
|
+
logLevel?: LogLevel;
|
|
19
27
|
}): Logxer;
|