@x12i/ai-gateway 7.9.1
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 +4259 -0
- package/config.defaults.json +31 -0
- package/dist/activity-manager.d.ts +206 -0
- package/dist/activity-manager.js +1051 -0
- package/dist/config/activity-tracking-config.d.ts +11 -0
- package/dist/config/activity-tracking-config.js +15 -0
- package/dist/config.defaults.json +31 -0
- package/dist/content-normalizer/content-normalizer.d.ts +46 -0
- package/dist/content-normalizer/content-normalizer.js +393 -0
- package/dist/content-normalizer/index.d.ts +7 -0
- package/dist/content-normalizer/index.js +6 -0
- package/dist/content-normalizer/types.d.ts +33 -0
- package/dist/content-normalizer/types.js +4 -0
- package/dist/defaults/instructions-blocks.json +61 -0
- package/dist/defaults/model-config.json +16 -0
- package/dist/defaults/template-rendering.json +6 -0
- package/dist/flex-md-loader.d.ts +109 -0
- package/dist/flex-md-loader.js +940 -0
- package/dist/gateway-config.d.ts +49 -0
- package/dist/gateway-config.js +292 -0
- package/dist/gateway-conversion.d.ts +29 -0
- package/dist/gateway-conversion.js +174 -0
- package/dist/gateway-instructions.d.ts +30 -0
- package/dist/gateway-instructions.js +62 -0
- package/dist/gateway-memory.d.ts +51 -0
- package/dist/gateway-memory.js +207 -0
- package/dist/gateway-messages.d.ts +23 -0
- package/dist/gateway-messages.js +83 -0
- package/dist/gateway-meta.d.ts +25 -0
- package/dist/gateway-meta.js +87 -0
- package/dist/gateway-provider-auto-register.d.ts +17 -0
- package/dist/gateway-provider-auto-register.js +159 -0
- package/dist/gateway-provider.d.ts +54 -0
- package/dist/gateway-provider.js +202 -0
- package/dist/gateway-rate-limiter-constants.d.ts +16 -0
- package/dist/gateway-rate-limiter-constants.js +16 -0
- package/dist/gateway-rate-limiter.d.ts +56 -0
- package/dist/gateway-rate-limiter.js +107 -0
- package/dist/gateway-retry.d.ts +49 -0
- package/dist/gateway-retry.js +204 -0
- package/dist/gateway-utils.d.ts +21 -0
- package/dist/gateway-utils.js +181 -0
- package/dist/gateway-validation.d.ts +13 -0
- package/dist/gateway-validation.js +50 -0
- package/dist/gateway.d.ts +39 -0
- package/dist/gateway.js +430 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +55 -0
- package/dist/instruction-errors.d.ts +16 -0
- package/dist/instruction-errors.js +29 -0
- package/dist/instruction-optimizer.d.ts +113 -0
- package/dist/instruction-optimizer.js +293 -0
- package/dist/instructions-parser.d.ts +31 -0
- package/dist/instructions-parser.js +56 -0
- package/dist/logger-factory.d.ts +17 -0
- package/dist/logger-factory.js +42 -0
- package/dist/message-builder.d.ts +41 -0
- package/dist/message-builder.js +522 -0
- package/dist/object-types-library-integration.d.ts +22 -0
- package/dist/object-types-library-integration.js +27 -0
- package/dist/object-types-library.d.ts +351 -0
- package/dist/object-types-library.js +210 -0
- package/dist/output-auditor.d.ts +44 -0
- package/dist/output-auditor.js +49 -0
- package/dist/request-report-generator.d.ts +60 -0
- package/dist/request-report-generator.js +169 -0
- package/dist/response-analyzer/format-type-detector.d.ts +35 -0
- package/dist/response-analyzer/format-type-detector.js +115 -0
- package/dist/response-analyzer/index.d.ts +9 -0
- package/dist/response-analyzer/index.js +8 -0
- package/dist/response-analyzer/object-type-detector.d.ts +42 -0
- package/dist/response-analyzer/object-type-detector.js +95 -0
- package/dist/response-analyzer/response-analyzer.d.ts +38 -0
- package/dist/response-analyzer/response-analyzer.js +97 -0
- package/dist/response-analyzer/types.d.ts +97 -0
- package/dist/response-analyzer/types.js +4 -0
- package/dist/response-fallback-fixer.d.ts +11 -0
- package/dist/response-fallback-fixer.js +123 -0
- package/dist/runtime-objects.d.ts +52 -0
- package/dist/runtime-objects.js +46 -0
- package/dist/template-parser.d.ts +58 -0
- package/dist/template-parser.js +99 -0
- package/dist/template-render-merge.d.ts +9 -0
- package/dist/template-render-merge.js +40 -0
- package/dist/troubleshooting-helper.d.ts +123 -0
- package/dist/troubleshooting-helper.js +596 -0
- package/dist/types.d.ts +1173 -0
- package/dist/types.js +6 -0
- package/dist/usage-tracker.d.ts +78 -0
- package/dist/usage-tracker.js +79 -0
- package/dist-cjs/activity-manager.cjs +1056 -0
- package/dist-cjs/activity-manager.d.ts +206 -0
- package/dist-cjs/config/activity-tracking-config.cjs +18 -0
- package/dist-cjs/config/activity-tracking-config.d.ts +11 -0
- package/dist-cjs/config.defaults.json +31 -0
- package/dist-cjs/content-normalizer/content-normalizer.cjs +398 -0
- package/dist-cjs/content-normalizer/content-normalizer.d.ts +46 -0
- package/dist-cjs/content-normalizer/index.cjs +12 -0
- package/dist-cjs/content-normalizer/index.d.ts +7 -0
- package/dist-cjs/content-normalizer/types.cjs +5 -0
- package/dist-cjs/content-normalizer/types.d.ts +33 -0
- package/dist-cjs/defaults/instructions-blocks.json +61 -0
- package/dist-cjs/defaults/model-config.json +16 -0
- package/dist-cjs/defaults/template-rendering.json +6 -0
- package/dist-cjs/flex-md-loader.cjs +986 -0
- package/dist-cjs/flex-md-loader.d.ts +109 -0
- package/dist-cjs/gateway-config.cjs +331 -0
- package/dist-cjs/gateway-config.d.ts +49 -0
- package/dist-cjs/gateway-conversion.cjs +212 -0
- package/dist-cjs/gateway-conversion.d.ts +29 -0
- package/dist-cjs/gateway-instructions.cjs +67 -0
- package/dist-cjs/gateway-instructions.d.ts +30 -0
- package/dist-cjs/gateway-memory.cjs +211 -0
- package/dist-cjs/gateway-memory.d.ts +51 -0
- package/dist-cjs/gateway-messages.cjs +86 -0
- package/dist-cjs/gateway-messages.d.ts +23 -0
- package/dist-cjs/gateway-meta.cjs +90 -0
- package/dist-cjs/gateway-meta.d.ts +25 -0
- package/dist-cjs/gateway-provider-auto-register.cjs +195 -0
- package/dist-cjs/gateway-provider-auto-register.d.ts +17 -0
- package/dist-cjs/gateway-provider.cjs +214 -0
- package/dist-cjs/gateway-provider.d.ts +54 -0
- package/dist-cjs/gateway-rate-limiter-constants.cjs +19 -0
- package/dist-cjs/gateway-rate-limiter-constants.d.ts +16 -0
- package/dist-cjs/gateway-rate-limiter.cjs +111 -0
- package/dist-cjs/gateway-rate-limiter.d.ts +56 -0
- package/dist-cjs/gateway-retry.cjs +212 -0
- package/dist-cjs/gateway-retry.d.ts +49 -0
- package/dist-cjs/gateway-utils.cjs +219 -0
- package/dist-cjs/gateway-utils.d.ts +21 -0
- package/dist-cjs/gateway-validation.cjs +54 -0
- package/dist-cjs/gateway-validation.d.ts +13 -0
- package/dist-cjs/gateway.cjs +434 -0
- package/dist-cjs/gateway.d.ts +39 -0
- package/dist-cjs/index.cjs +108 -0
- package/dist-cjs/index.d.ts +36 -0
- package/dist-cjs/instruction-errors.cjs +34 -0
- package/dist-cjs/instruction-errors.d.ts +16 -0
- package/dist-cjs/instruction-optimizer.cjs +299 -0
- package/dist-cjs/instruction-optimizer.d.ts +113 -0
- package/dist-cjs/instructions-parser.cjs +61 -0
- package/dist-cjs/instructions-parser.d.ts +31 -0
- package/dist-cjs/logger-factory.cjs +45 -0
- package/dist-cjs/logger-factory.d.ts +17 -0
- package/dist-cjs/message-builder.cjs +558 -0
- package/dist-cjs/message-builder.d.ts +41 -0
- package/dist-cjs/object-types-library-integration.cjs +32 -0
- package/dist-cjs/object-types-library-integration.d.ts +22 -0
- package/dist-cjs/object-types-library.cjs +215 -0
- package/dist-cjs/object-types-library.d.ts +351 -0
- package/dist-cjs/output-auditor.cjs +52 -0
- package/dist-cjs/output-auditor.d.ts +44 -0
- package/dist-cjs/request-report-generator.cjs +172 -0
- package/dist-cjs/request-report-generator.d.ts +60 -0
- package/dist-cjs/response-analyzer/format-type-detector.cjs +119 -0
- package/dist-cjs/response-analyzer/format-type-detector.d.ts +35 -0
- package/dist-cjs/response-analyzer/index.cjs +14 -0
- package/dist-cjs/response-analyzer/index.d.ts +9 -0
- package/dist-cjs/response-analyzer/object-type-detector.cjs +99 -0
- package/dist-cjs/response-analyzer/object-type-detector.d.ts +42 -0
- package/dist-cjs/response-analyzer/response-analyzer.cjs +101 -0
- package/dist-cjs/response-analyzer/response-analyzer.d.ts +38 -0
- package/dist-cjs/response-analyzer/types.cjs +5 -0
- package/dist-cjs/response-analyzer/types.d.ts +97 -0
- package/dist-cjs/response-fallback-fixer.cjs +126 -0
- package/dist-cjs/response-fallback-fixer.d.ts +11 -0
- package/dist-cjs/runtime-objects.cjs +52 -0
- package/dist-cjs/runtime-objects.d.ts +52 -0
- package/dist-cjs/template-parser.cjs +136 -0
- package/dist-cjs/template-parser.d.ts +58 -0
- package/dist-cjs/template-render-merge.cjs +43 -0
- package/dist-cjs/template-render-merge.d.ts +9 -0
- package/dist-cjs/troubleshooting-helper.cjs +611 -0
- package/dist-cjs/troubleshooting-helper.d.ts +123 -0
- package/dist-cjs/types.cjs +7 -0
- package/dist-cjs/types.d.ts +1173 -0
- package/dist-cjs/usage-tracker.cjs +83 -0
- package/dist-cjs/usage-tracker.d.ts +78 -0
- package/package.json +91 -0
package/dist/gateway.js
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @x12i/ai-gateway
|
|
3
|
+
*
|
|
4
|
+
* Simplified AI Gateway - Clean proxy implementation
|
|
5
|
+
*/
|
|
6
|
+
import { validateChatRequest, validateAIRequest } from './gateway-validation.js';
|
|
7
|
+
import { ensureGatewayRequestIdentity } from './activity-manager.js';
|
|
8
|
+
import { initializeGatewayComponents, loadConfig } from './gateway-config.js';
|
|
9
|
+
import { buildMessages } from './message-builder.js';
|
|
10
|
+
import { extractJsonFromFlexMd } from './flex-md-loader.js';
|
|
11
|
+
import { mergeConfig } from './gateway-utils.js';
|
|
12
|
+
import { autoRegisterProviders } from './gateway-provider-auto-register.js';
|
|
13
|
+
import { setGatewayLastJobId, setGatewayRuntimeClients } from './runtime-objects.js';
|
|
14
|
+
/** Error message thrown by the router when no provider is registered or specified */
|
|
15
|
+
const NO_PROVIDER_ERROR = 'No provider specified and no providers registered';
|
|
16
|
+
const NO_PROVIDER_HINT = ' Set OPEN_ROUTER_KEY (or OPENROUTER_API_KEY) in the environment to use OpenRouter, or register a provider with the router (e.g. via autoRegisterProviders or gateway config).';
|
|
17
|
+
/**
|
|
18
|
+
* Simplified AI Gateway - Clean proxy implementation
|
|
19
|
+
*/
|
|
20
|
+
export class AIGateway {
|
|
21
|
+
router;
|
|
22
|
+
config;
|
|
23
|
+
logger;
|
|
24
|
+
activityManager;
|
|
25
|
+
messageBuilderConfig;
|
|
26
|
+
_autoRegisterDone = false;
|
|
27
|
+
constructor(config = {}, activityManager) {
|
|
28
|
+
this.config = config;
|
|
29
|
+
this.activityManager = activityManager;
|
|
30
|
+
// Load configuration and initialize components
|
|
31
|
+
const { defaultModelConfig, defaultInstructionsBlocks, defaultTemplateRendering } = loadConfig();
|
|
32
|
+
const components = initializeGatewayComponents(config, defaultModelConfig, defaultInstructionsBlocks, defaultTemplateRendering);
|
|
33
|
+
this.logger = components.logger;
|
|
34
|
+
this.router = components.router;
|
|
35
|
+
this.activityManager = components.activityManager;
|
|
36
|
+
this.messageBuilderConfig = components.messageBuilderConfig;
|
|
37
|
+
setGatewayRuntimeClients({
|
|
38
|
+
activix: this.activityManager?.getTracker(),
|
|
39
|
+
logger: this.logger
|
|
40
|
+
});
|
|
41
|
+
this.logger.info('AI Gateway initialized with full component stack', {
|
|
42
|
+
hasActivityManager: !!this.activityManager,
|
|
43
|
+
hasMessageBuilder: !!this.messageBuilderConfig
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Invoke chat request (without structured output requirements)
|
|
48
|
+
*/
|
|
49
|
+
async invokeChat(request) {
|
|
50
|
+
const startTime = Date.now();
|
|
51
|
+
// Basic validation
|
|
52
|
+
validateChatRequest(request);
|
|
53
|
+
if (!this.activityManager) {
|
|
54
|
+
ensureGatewayRequestIdentity(request);
|
|
55
|
+
}
|
|
56
|
+
setGatewayLastJobId(resolveRuntimeJobId(request));
|
|
57
|
+
// Generate simple task type ID
|
|
58
|
+
const taskTypeId = request.taskTypeId || `task-${Date.now()}`;
|
|
59
|
+
// Simple message construction
|
|
60
|
+
const messages = this.buildSimpleMessages(request);
|
|
61
|
+
// Merge config (modelConfig > request.config > gateway defaults)
|
|
62
|
+
const mergedConfig = await mergeConfig(request, this.config, this.logger);
|
|
63
|
+
// Lazy auto-register providers from env (OPENAI_API_KEY, etc.) so consumers don't have to call init
|
|
64
|
+
if (!this._autoRegisterDone) {
|
|
65
|
+
await autoRegisterProviders(this.router, this.logger);
|
|
66
|
+
this._autoRegisterDone = true;
|
|
67
|
+
}
|
|
68
|
+
// Start activity tracking if available
|
|
69
|
+
let activity = undefined;
|
|
70
|
+
if (this.activityManager) {
|
|
71
|
+
try {
|
|
72
|
+
activity = await this.activityManager.startActivity(request, startTime);
|
|
73
|
+
}
|
|
74
|
+
catch (activityError) {
|
|
75
|
+
// Log activity tracking error but don't fail the request
|
|
76
|
+
this.logger.warn('Failed to start activity tracking', {
|
|
77
|
+
aiRequestId: request.aiRequestId,
|
|
78
|
+
error: activityError instanceof Error ? activityError.message : String(activityError)
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
// Call router directly with merged config
|
|
84
|
+
const response = await this.router.invoke({
|
|
85
|
+
request: {
|
|
86
|
+
messages,
|
|
87
|
+
config: mergedConfig,
|
|
88
|
+
identity: request.identity
|
|
89
|
+
},
|
|
90
|
+
mode: 'sync'
|
|
91
|
+
});
|
|
92
|
+
// Create enhanced response
|
|
93
|
+
const enhancedResponse = {
|
|
94
|
+
content: response.content || '',
|
|
95
|
+
metadata: {
|
|
96
|
+
aiRequestId: request.aiRequestId,
|
|
97
|
+
identity: request.identity,
|
|
98
|
+
latencyMs: Date.now() - startTime,
|
|
99
|
+
tokens: response.usage || { prompt: 0, completion: 0, total: 0 },
|
|
100
|
+
taskTypeId,
|
|
101
|
+
agentType: 'chat'
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
// Track activity success if activity was started
|
|
105
|
+
if (activity) {
|
|
106
|
+
try {
|
|
107
|
+
await this.activityManager.logSuccess(activity, {
|
|
108
|
+
response: enhancedResponse,
|
|
109
|
+
endTime: Date.now(),
|
|
110
|
+
duration: Date.now() - startTime
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
catch (activityError) {
|
|
114
|
+
// Log activity tracking error but don't fail the request
|
|
115
|
+
this.logger.warn('Failed to track activity success', {
|
|
116
|
+
aiRequestId: request.aiRequestId,
|
|
117
|
+
error: activityError instanceof Error ? activityError.message : String(activityError)
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return enhancedResponse;
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
125
|
+
if (err.message.includes(NO_PROVIDER_ERROR)) {
|
|
126
|
+
throw new Error(err.message + NO_PROVIDER_HINT);
|
|
127
|
+
}
|
|
128
|
+
throw err;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Invoke AI request (with structured output support)
|
|
133
|
+
*/
|
|
134
|
+
async invoke(request) {
|
|
135
|
+
const startTime = Date.now();
|
|
136
|
+
// Basic validation
|
|
137
|
+
validateAIRequest(request);
|
|
138
|
+
if (!this.activityManager) {
|
|
139
|
+
ensureGatewayRequestIdentity(request);
|
|
140
|
+
}
|
|
141
|
+
setGatewayLastJobId(resolveRuntimeJobId(request));
|
|
142
|
+
// Generate simple task type ID
|
|
143
|
+
const taskTypeId = request.taskTypeId || `task-${Date.now()}`;
|
|
144
|
+
// Resolve instructions and build messages using proper components
|
|
145
|
+
let resolvedRequest = request;
|
|
146
|
+
let messages = [];
|
|
147
|
+
// Create parsedSnapshot to store parsed request data and messages
|
|
148
|
+
const parsedSnapshot = {};
|
|
149
|
+
// Use proper instruction resolution and message building
|
|
150
|
+
let builtMessages;
|
|
151
|
+
try {
|
|
152
|
+
builtMessages = await buildMessages(request, this.messageBuilderConfig, {
|
|
153
|
+
parsedSnapshot
|
|
154
|
+
});
|
|
155
|
+
messages = builtMessages.messages;
|
|
156
|
+
resolvedRequest = request;
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
// If message building fails (e.g., prompt/instruction resolution error), log as bad request
|
|
160
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
161
|
+
const endTime = Date.now();
|
|
162
|
+
const duration = endTime - startTime;
|
|
163
|
+
// Determine if this is a prompt/instruction resolution error
|
|
164
|
+
// If a key was provided but couldn't be resolved to content, it's a bad request
|
|
165
|
+
const errWithCode = err; // Type assertion for error with optional code property
|
|
166
|
+
const isResolutionError = err.name === 'InstructionNotFoundError' ||
|
|
167
|
+
err.name === 'InstructionBackendError' ||
|
|
168
|
+
err.name === 'TemplateResolutionError' ||
|
|
169
|
+
errWithCode.code === 'PROMPT_NOT_FOUND' ||
|
|
170
|
+
errWithCode.code === 'PROMPT_RESOLUTION_ERROR' ||
|
|
171
|
+
errWithCode.code === 'PROMPT_RENDERED_EMPTY' ||
|
|
172
|
+
errWithCode.code === 'TEMPLATE_RESOLUTION_ERROR' ||
|
|
173
|
+
errWithCode.code === 'TEMPLATE_VARIABLE_MISSING' ||
|
|
174
|
+
err.message.includes('Failed to resolve') ||
|
|
175
|
+
err.message.includes('Failed to render prompt template') ||
|
|
176
|
+
err.message.includes('not found') ||
|
|
177
|
+
err.message.includes('Instruction not found') ||
|
|
178
|
+
err.message.includes('Prompt not found');
|
|
179
|
+
if (isResolutionError && this.activityManager) {
|
|
180
|
+
// Log to bad requests collection
|
|
181
|
+
await this.activityManager.logBadRequest(request, err, {
|
|
182
|
+
endTime,
|
|
183
|
+
duration,
|
|
184
|
+
error: err.message,
|
|
185
|
+
errorType: errWithCode.code || 'MessageBuildError',
|
|
186
|
+
diagnosticInfo: {
|
|
187
|
+
errorCode: errWithCode.code,
|
|
188
|
+
errorName: err.name,
|
|
189
|
+
failureType: 'validation-failure',
|
|
190
|
+
stage: 'message-building',
|
|
191
|
+
prompt: request.prompt,
|
|
192
|
+
instructions: typeof request.instructions === 'string' ? request.instructions.substring(0, 100) : '(object)'
|
|
193
|
+
},
|
|
194
|
+
failureType: 'validation-failure'
|
|
195
|
+
}, startTime);
|
|
196
|
+
}
|
|
197
|
+
// Re-throw the error so it propagates to the caller
|
|
198
|
+
throw err;
|
|
199
|
+
}
|
|
200
|
+
// Store messages in parsedSnapshot for activity tracking
|
|
201
|
+
parsedSnapshot.messages = messages;
|
|
202
|
+
// parsed.instructions and parsed.prompt are set by buildMessages to the resolved/rendered content
|
|
203
|
+
// (after key resolution and Rendrix). Do not overwrite with raw request keys.
|
|
204
|
+
if (parsedSnapshot.context === undefined) {
|
|
205
|
+
parsedSnapshot.context = request.context;
|
|
206
|
+
}
|
|
207
|
+
// Attach parsedSnapshot to request for activity tracking
|
|
208
|
+
request._parsedRequest = parsedSnapshot;
|
|
209
|
+
// Merge config (modelConfig > request.config > gateway defaults)
|
|
210
|
+
const mergedConfig = await mergeConfig(request, this.config, this.logger);
|
|
211
|
+
// Lazy auto-register providers from env (OPENAI_API_KEY, etc.) so consumers don't have to call init
|
|
212
|
+
if (!this._autoRegisterDone) {
|
|
213
|
+
await autoRegisterProviders(this.router, this.logger);
|
|
214
|
+
this._autoRegisterDone = true;
|
|
215
|
+
}
|
|
216
|
+
// Start activity tracking if available
|
|
217
|
+
let activity = undefined;
|
|
218
|
+
if (this.activityManager) {
|
|
219
|
+
try {
|
|
220
|
+
activity = await this.activityManager.startActivity(request, startTime);
|
|
221
|
+
}
|
|
222
|
+
catch (activityError) {
|
|
223
|
+
// Log activity tracking error but don't fail the request
|
|
224
|
+
this.logger.warn('Failed to start activity tracking', {
|
|
225
|
+
aiRequestId: request.aiRequestId,
|
|
226
|
+
error: activityError instanceof Error ? activityError.message : String(activityError)
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
// Call router directly with merged config
|
|
232
|
+
const response = await this.router.invoke({
|
|
233
|
+
request: {
|
|
234
|
+
messages,
|
|
235
|
+
config: mergedConfig,
|
|
236
|
+
identity: request.identity
|
|
237
|
+
},
|
|
238
|
+
mode: 'sync'
|
|
239
|
+
});
|
|
240
|
+
// Contract output processing removed - expectedSchema no longer supported
|
|
241
|
+
// Create enhanced response - extract content properly from router response
|
|
242
|
+
const routerResponse = response;
|
|
243
|
+
// Extract content from router response - router returns outputText, not content
|
|
244
|
+
let content = routerResponse.content || routerResponse.outputText || '';
|
|
245
|
+
// If content is still empty, try to extract from ai-activities metadata
|
|
246
|
+
if (!content && routerResponse.metadata?.['ai-activities-response']?.outputText) {
|
|
247
|
+
content = routerResponse.metadata['ai-activities-response'].outputText;
|
|
248
|
+
}
|
|
249
|
+
// Parse content using available parsers (flex-md, content normalizer, etc.)
|
|
250
|
+
let parsedContent = undefined;
|
|
251
|
+
let contentType = undefined;
|
|
252
|
+
let parsingMethod = undefined;
|
|
253
|
+
// Actually use flex-md parsing - extract structured data from markdown
|
|
254
|
+
try {
|
|
255
|
+
this.logger.debug('Attempting flex-md extraction', {
|
|
256
|
+
aiRequestId: request.aiRequestId,
|
|
257
|
+
contentLength: content.length,
|
|
258
|
+
hasInstructions: !!resolvedRequest.instructions
|
|
259
|
+
});
|
|
260
|
+
// Let flex-md extract structured data from the response content
|
|
261
|
+
const extractionResult = await extractJsonFromFlexMd(content);
|
|
262
|
+
this.logger.debug('Flex-md extraction result', {
|
|
263
|
+
aiRequestId: request.aiRequestId,
|
|
264
|
+
hasResult: !!extractionResult,
|
|
265
|
+
hasJson: !!(extractionResult && extractionResult.json),
|
|
266
|
+
method: extractionResult?.method,
|
|
267
|
+
jsonType: extractionResult?.json ? typeof extractionResult.json : 'none'
|
|
268
|
+
});
|
|
269
|
+
if (extractionResult && extractionResult.json) {
|
|
270
|
+
// Successfully extracted structured data
|
|
271
|
+
parsedContent = extractionResult.json;
|
|
272
|
+
this.logger.info('Flex-md extraction successful - parsed into structured object', {
|
|
273
|
+
aiRequestId: request.aiRequestId,
|
|
274
|
+
method: extractionResult.method,
|
|
275
|
+
extractedKeys: Object.keys(extractionResult.json)
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
// Extraction failed, fall back to raw text wrapper
|
|
280
|
+
this.logger.warn('Flex-md extraction failed - no structured data extracted', {
|
|
281
|
+
aiRequestId: request.aiRequestId,
|
|
282
|
+
hasResult: !!extractionResult,
|
|
283
|
+
method: extractionResult?.method || 'none'
|
|
284
|
+
});
|
|
285
|
+
parsedContent = { rawText: content };
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
catch (extractionError) {
|
|
289
|
+
// Extraction failed, fall back to raw text wrapper
|
|
290
|
+
const errorMessage = extractionError instanceof Error ? extractionError.message : String(extractionError);
|
|
291
|
+
this.logger.warn('Flex-md extraction failed - flex-md library compatibility issue', {
|
|
292
|
+
aiRequestId: request.aiRequestId,
|
|
293
|
+
error: errorMessage,
|
|
294
|
+
issue: 'flex-md uses require() in ES module context - needs fixing in flex-md-loader.ts',
|
|
295
|
+
fallback: 'using rawText wrapper'
|
|
296
|
+
});
|
|
297
|
+
parsedContent = { rawText: content };
|
|
298
|
+
}
|
|
299
|
+
contentType = 'structured';
|
|
300
|
+
parsingMethod = 'flex-md';
|
|
301
|
+
// Extract token usage properly
|
|
302
|
+
let tokens = { prompt: 0, completion: 0, total: 0 };
|
|
303
|
+
if (routerResponse.usage) {
|
|
304
|
+
tokens = {
|
|
305
|
+
prompt: routerResponse.usage.promptTokens || routerResponse.usage.inputTokens || 0,
|
|
306
|
+
completion: routerResponse.usage.completionTokens || routerResponse.usage.outputTokens || 0,
|
|
307
|
+
total: routerResponse.usage.totalTokens || 0
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
else if (routerResponse.metadata?.['ai-activities-response']?.usage) {
|
|
311
|
+
const usage = routerResponse.metadata['ai-activities-response'].usage;
|
|
312
|
+
tokens = {
|
|
313
|
+
prompt: usage.promptTokens || usage.inputTokens || 0,
|
|
314
|
+
completion: usage.completionTokens || usage.outputTokens || 0,
|
|
315
|
+
total: usage.totalTokens || 0
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
const enhancedResponse = {
|
|
319
|
+
content: content,
|
|
320
|
+
parsedContent: parsedContent,
|
|
321
|
+
metadata: {
|
|
322
|
+
aiRequestId: request.aiRequestId,
|
|
323
|
+
identity: request.identity,
|
|
324
|
+
latencyMs: Date.now() - startTime,
|
|
325
|
+
tokens: tokens,
|
|
326
|
+
taskTypeId,
|
|
327
|
+
agentType: 'ai',
|
|
328
|
+
contentType,
|
|
329
|
+
parsingMethod
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
// Track activity success if activity was started
|
|
333
|
+
if (activity) {
|
|
334
|
+
try {
|
|
335
|
+
// Create activity response with proper structure for ActivityTracker
|
|
336
|
+
const activityResponse = {
|
|
337
|
+
content: {
|
|
338
|
+
rawContent: content, // Store the actual response content as rawContent
|
|
339
|
+
fullResponse: routerResponse.rawResponse || routerResponse // Include full router response
|
|
340
|
+
},
|
|
341
|
+
parsed: parsedContent, // Include parsed content in activity record
|
|
342
|
+
metadata: enhancedResponse.metadata,
|
|
343
|
+
status: 'success',
|
|
344
|
+
error: null,
|
|
345
|
+
usage: tokens
|
|
346
|
+
};
|
|
347
|
+
await this.activityManager.logSuccess(activity, {
|
|
348
|
+
response: activityResponse,
|
|
349
|
+
endTime: Date.now(),
|
|
350
|
+
duration: Date.now() - startTime
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
catch (activityError) {
|
|
354
|
+
// Log activity tracking error but don't fail the request
|
|
355
|
+
this.logger.warn('Failed to track activity success', {
|
|
356
|
+
aiRequestId: request.aiRequestId,
|
|
357
|
+
error: activityError instanceof Error ? activityError.message : String(activityError)
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
console.debug('gateway: enhancedResponse:', enhancedResponse);
|
|
362
|
+
return enhancedResponse;
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
366
|
+
if (err.message.includes(NO_PROVIDER_ERROR)) {
|
|
367
|
+
throw new Error(err.message + NO_PROVIDER_HINT);
|
|
368
|
+
}
|
|
369
|
+
throw err;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Build simple messages from request (instructions and prompt as literal template text; no registry).
|
|
374
|
+
*/
|
|
375
|
+
buildSimpleMessages(request) {
|
|
376
|
+
const messages = [];
|
|
377
|
+
// Add instructions as system message if present
|
|
378
|
+
if (request.instructions) {
|
|
379
|
+
const instructions = typeof request.instructions === 'string'
|
|
380
|
+
? request.instructions
|
|
381
|
+
: 'Default instructions';
|
|
382
|
+
messages.push({ role: 'system', content: instructions });
|
|
383
|
+
}
|
|
384
|
+
// Add context as assistant message if present
|
|
385
|
+
if (request.context) {
|
|
386
|
+
const context = typeof request.context === 'string'
|
|
387
|
+
? request.context
|
|
388
|
+
: JSON.stringify(request.context);
|
|
389
|
+
messages.push({ role: 'assistant', content: context });
|
|
390
|
+
}
|
|
391
|
+
// Add prompt/input as user message
|
|
392
|
+
// Input field has been removed - prompt template should contain {{input}} which resolves from workingMemory.input
|
|
393
|
+
const userContent = request.prompt || '';
|
|
394
|
+
if (userContent) {
|
|
395
|
+
messages.push({ role: 'user', content: userContent });
|
|
396
|
+
}
|
|
397
|
+
// Add direct messages if present
|
|
398
|
+
if (request.messages) {
|
|
399
|
+
messages.push(...request.messages);
|
|
400
|
+
}
|
|
401
|
+
return messages;
|
|
402
|
+
}
|
|
403
|
+
// Provider management methods
|
|
404
|
+
register(provider) {
|
|
405
|
+
this.router.registerProvider(provider);
|
|
406
|
+
}
|
|
407
|
+
listProviders() {
|
|
408
|
+
return this.router.listProviders ? this.router.listProviders() : [];
|
|
409
|
+
}
|
|
410
|
+
// Utility methods
|
|
411
|
+
getRouter() {
|
|
412
|
+
return this.router;
|
|
413
|
+
}
|
|
414
|
+
getLogger() {
|
|
415
|
+
return this.logger;
|
|
416
|
+
}
|
|
417
|
+
getActivityManager() {
|
|
418
|
+
return this.activityManager;
|
|
419
|
+
}
|
|
420
|
+
setActivityManager(activityManager) {
|
|
421
|
+
this.activityManager = activityManager;
|
|
422
|
+
setGatewayRuntimeClients({
|
|
423
|
+
activix: this.activityManager.getTracker(),
|
|
424
|
+
logger: this.logger
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
function resolveRuntimeJobId(request) {
|
|
429
|
+
return request.identity?.jobId ?? request.jobId ?? request.identity?.sessionId ?? request.aiRequestId;
|
|
430
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @x12i/ai-gateway
|
|
3
|
+
*
|
|
4
|
+
* Unified gateway for LLM provider routing and management.
|
|
5
|
+
* This package exposes all functionality from @x12i/ai-providers-router
|
|
6
|
+
* with enhanced features: context propagation, usage tier tracking, and comprehensive metadata.
|
|
7
|
+
*/
|
|
8
|
+
export { LLMProviderRouter } from '@x12i/ai-providers-router';
|
|
9
|
+
export type { RouterConfig, HealthCheckResult } from '@x12i/ai-providers-router';
|
|
10
|
+
export { createRouter, createRouterFromConfig } from '@x12i/ai-providers-router';
|
|
11
|
+
export type { CreateRouterConfig } from '@x12i/ai-providers-router';
|
|
12
|
+
export { ProviderNotFoundError, FallbackExhaustedError } from '@x12i/ai-providers-router';
|
|
13
|
+
export type { RequestInterceptor, ResponseInterceptor } from '@x12i/ai-providers-router';
|
|
14
|
+
export type { UsageTracker } from '@x12i/ai-providers-router';
|
|
15
|
+
export * from '@x12i/ai-providers-router';
|
|
16
|
+
export { AIGateway } from './gateway.js';
|
|
17
|
+
export { InstructionNotFoundError, InstructionBackendError } from './instruction-errors.js';
|
|
18
|
+
export { autoRegisterProviders } from './gateway-provider-auto-register.js';
|
|
19
|
+
export type { GatewayConfig, ProviderModelRef, ModelConfig, RetryConfig, ChatRequest, AIRequest, EnhancedLLMResponse, InstructionMetadata, ValidationRule, ResponseTransformationConfig, TemplateRenderOptions } from './types.js';
|
|
20
|
+
export { mergeTemplateRenderOptions } from './template-render-merge.js';
|
|
21
|
+
export type { UsageTier } from './types.js';
|
|
22
|
+
export { Activix } from '@x12i/activix';
|
|
23
|
+
export type { ActivixRunContext, FindByRunContextCriteria } from '@x12i/activix';
|
|
24
|
+
export { ActivityManager, ensureGatewayRequestIdentity } from './activity-manager.js';
|
|
25
|
+
export type { ActivityIdentity } from './types.js';
|
|
26
|
+
export { createLogxer } from '@x12i/logxer';
|
|
27
|
+
export type { Logxer } from '@x12i/logxer';
|
|
28
|
+
export { runtimeObjects } from './runtime-objects.js';
|
|
29
|
+
export type { ActivixQueryableClient, LogxerQueryableClient, PackageRuntimeObjects, RuntimeObjects } from './runtime-objects.js';
|
|
30
|
+
export { GatewayRateLimiter } from './gateway-rate-limiter.js';
|
|
31
|
+
export { DEFAULT_RATE_LIMIT_MIN_INTERVAL_MS, DEFAULT_RATE_LIMIT_ENABLED } from './gateway-rate-limiter-constants.js';
|
|
32
|
+
export { validateAIRequest, validateJSON, extractJSON, validateResponse, diagnoseRequest, diagnoseResponse, supportsJSONMode, createTestAIRequest, createValidationTestCases, runValidationTests, formatDiagnostic, assertValidAIRequest } from './troubleshooting-helper.js';
|
|
33
|
+
export type { ValidationResult, DiagnosticInfo } from './troubleshooting-helper.js';
|
|
34
|
+
export { OBJECT_TYPES_LIBRARY, getObjectType, getObjectTypesForAgent } from './object-types-library.js';
|
|
35
|
+
export type { ReasoningResult, AuditReport, ScopeDefinition, DiscoveryFindings, ActionPlan, ExecutionResult } from './object-types-library.js';
|
|
36
|
+
export { initializeObjectTypesLibrary, getObjectTypesLibrary, resetObjectTypesLibrary } from './object-types-library-integration.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @x12i/ai-gateway
|
|
3
|
+
*
|
|
4
|
+
* Unified gateway for LLM provider routing and management.
|
|
5
|
+
* This package exposes all functionality from @x12i/ai-providers-router
|
|
6
|
+
* with enhanced features: context propagation, usage tier tracking, and comprehensive metadata.
|
|
7
|
+
*/
|
|
8
|
+
// Re-export router class and types (base functionality)
|
|
9
|
+
export { LLMProviderRouter } from '@x12i/ai-providers-router';
|
|
10
|
+
// Re-export factory functions
|
|
11
|
+
export { createRouter, createRouterFromConfig } from '@x12i/ai-providers-router';
|
|
12
|
+
// Re-export error classes
|
|
13
|
+
export { ProviderNotFoundError, FallbackExhaustedError } from '@x12i/ai-providers-router';
|
|
14
|
+
// Re-export all from router (includes everything it exports)
|
|
15
|
+
export * from '@x12i/ai-providers-router';
|
|
16
|
+
// Export enhanced gateway
|
|
17
|
+
export { AIGateway } from './gateway.js';
|
|
18
|
+
export { InstructionNotFoundError, InstructionBackendError } from './instruction-errors.js';
|
|
19
|
+
export { autoRegisterProviders } from './gateway-provider-auto-register.js';
|
|
20
|
+
export { mergeTemplateRenderOptions } from './template-render-merge.js';
|
|
21
|
+
// Usage tracking: UsageTracker class methods are available but consumption calculation is disabled
|
|
22
|
+
// (x-models was previously used for RPM/TPM tracking but is no longer integrated)
|
|
23
|
+
// Re-export activity tracking primitives (Activix)
|
|
24
|
+
export { Activix } from '@x12i/activix';
|
|
25
|
+
export { ActivityManager, ensureGatewayRequestIdentity } from './activity-manager.js';
|
|
26
|
+
// Re-export logging (@x12i/logxer)
|
|
27
|
+
export { createLogxer } from '@x12i/logxer';
|
|
28
|
+
// Runtime observability surface (leaf package: no downstream runtime objects)
|
|
29
|
+
export { runtimeObjects } from './runtime-objects.js';
|
|
30
|
+
// Export rate limiter
|
|
31
|
+
export { GatewayRateLimiter } from './gateway-rate-limiter.js';
|
|
32
|
+
export { DEFAULT_RATE_LIMIT_MIN_INTERVAL_MS, DEFAULT_RATE_LIMIT_ENABLED } from './gateway-rate-limiter-constants.js';
|
|
33
|
+
// Export troubleshooting helpers
|
|
34
|
+
export { validateAIRequest, validateJSON, extractJSON, validateResponse, diagnoseRequest, diagnoseResponse, supportsJSONMode, createTestAIRequest, createValidationTestCases, runValidationTests, formatDiagnostic, assertValidAIRequest } from './troubleshooting-helper.js';
|
|
35
|
+
// Export object types library
|
|
36
|
+
export { OBJECT_TYPES_LIBRARY, getObjectType, getObjectTypesForAgent } from './object-types-library.js';
|
|
37
|
+
// Re-export outputs library integration functions
|
|
38
|
+
export { initializeObjectTypesLibrary, getObjectTypesLibrary, resetObjectTypesLibrary } from './object-types-library-integration.js';
|
|
39
|
+
// Re-export outputs library types and utilities for convenience
|
|
40
|
+
// Note: Since we use dynamic imports for the outputs library, these types may not be available
|
|
41
|
+
// at compile time if the package isn't installed. Users can import directly from
|
|
42
|
+
// @x12i/outputs-library if they need these types or utilities.
|
|
43
|
+
//
|
|
44
|
+
// Recommended: Import types and utilities directly from @x12i/outputs-library:
|
|
45
|
+
// import type { ClassificationOutput } from '@x12i/outputs-library/types';
|
|
46
|
+
// import { ResponseParser } from '@x12i/outputs-library/parsers';
|
|
47
|
+
// import type { ObjectTypesLibrary, FlexMdSupport } from '@x12i/outputs-library';
|
|
48
|
+
//
|
|
49
|
+
// The gateway integrates with the outputs library internally via dynamic imports,
|
|
50
|
+
// so these re-exports are optional and mainly for convenience.
|
|
51
|
+
//
|
|
52
|
+
// For outputs-library v3.3.1+ with flex-md support:
|
|
53
|
+
// - ObjectTypesLibrary class with flex-md methods (getFlexMdTemplate, getFlexMdFormatSpec, etc.)
|
|
54
|
+
// - FlexMdSupport type for object type definitions
|
|
55
|
+
// - All flex-md methods are available on the library instance returned by getObjectTypesLibrary()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Errors for instruction / prompt template and instructions-block resolution.
|
|
3
|
+
*/
|
|
4
|
+
export declare class InstructionNotFoundError extends Error {
|
|
5
|
+
key: string;
|
|
6
|
+
backend: string;
|
|
7
|
+
originalKey: string;
|
|
8
|
+
constructor(key: string, backend: string, message: string, originalKey: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class InstructionBackendError extends Error {
|
|
11
|
+
key: string;
|
|
12
|
+
backend: string;
|
|
13
|
+
isRetryable: boolean;
|
|
14
|
+
originalError?: Error | undefined;
|
|
15
|
+
constructor(key: string, backend: string, message: string, isRetryable: boolean, originalError?: Error | undefined);
|
|
16
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Errors for instruction / prompt template and instructions-block resolution.
|
|
3
|
+
*/
|
|
4
|
+
export class InstructionNotFoundError extends Error {
|
|
5
|
+
key;
|
|
6
|
+
backend;
|
|
7
|
+
originalKey;
|
|
8
|
+
constructor(key, backend, message, originalKey) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.key = key;
|
|
11
|
+
this.backend = backend;
|
|
12
|
+
this.originalKey = originalKey;
|
|
13
|
+
this.name = 'InstructionNotFoundError';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export class InstructionBackendError extends Error {
|
|
17
|
+
key;
|
|
18
|
+
backend;
|
|
19
|
+
isRetryable;
|
|
20
|
+
originalError;
|
|
21
|
+
constructor(key, backend, message, isRetryable, originalError) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.key = key;
|
|
24
|
+
this.backend = backend;
|
|
25
|
+
this.isRetryable = isRetryable;
|
|
26
|
+
this.originalError = originalError;
|
|
27
|
+
this.name = 'InstructionBackendError';
|
|
28
|
+
}
|
|
29
|
+
}
|