@x12i/ai-gateway 9.1.6 → 9.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +45 -0
  2. package/dist/activity-manager.d.ts +1 -0
  3. package/dist/activity-manager.js +7 -0
  4. package/dist/ai-tools-client.d.ts +20 -0
  5. package/dist/ai-tools-client.js +91 -0
  6. package/dist/flex-md-loader.d.ts +5 -0
  7. package/dist/flex-md-loader.js +16 -0
  8. package/dist/gateway-config.d.ts +2 -0
  9. package/dist/gateway-config.js +2 -1
  10. package/dist/gateway-mode.d.ts +40 -0
  11. package/dist/gateway-mode.js +75 -0
  12. package/dist/gateway-utils.d.ts +57 -1
  13. package/dist/gateway-utils.js +181 -12
  14. package/dist/gateway.d.ts +3 -0
  15. package/dist/gateway.js +47 -15
  16. package/dist/index.d.ts +6 -1
  17. package/dist/index.js +3 -1
  18. package/dist/output-contract-normalizer.d.ts +21 -0
  19. package/dist/output-contract-normalizer.js +121 -0
  20. package/dist/types.d.ts +35 -0
  21. package/dist-cjs/activity-manager.cjs +21 -19
  22. package/dist-cjs/activity-manager.d.ts +1 -0
  23. package/dist-cjs/ai-tools-client.cjs +91 -0
  24. package/dist-cjs/ai-tools-client.d.ts +20 -0
  25. package/dist-cjs/config/activity-tracking-config.cjs +1 -4
  26. package/dist-cjs/content-normalizer/content-normalizer.cjs +3 -8
  27. package/dist-cjs/content-normalizer/index.cjs +1 -7
  28. package/dist-cjs/content-normalizer/types.cjs +1 -2
  29. package/dist-cjs/flex-md-loader.cjs +35 -65
  30. package/dist-cjs/flex-md-loader.d.ts +5 -0
  31. package/dist-cjs/gateway-config.cjs +25 -63
  32. package/dist-cjs/gateway-config.d.ts +2 -0
  33. package/dist-cjs/gateway-conversion.cjs +10 -48
  34. package/dist-cjs/gateway-instructions.cjs +5 -10
  35. package/dist-cjs/gateway-log-meta.cjs +9 -14
  36. package/dist-cjs/gateway-memory.cjs +2 -6
  37. package/dist-cjs/gateway-messages.cjs +3 -6
  38. package/dist-cjs/gateway-meta.cjs +1 -4
  39. package/dist-cjs/gateway-mode.cjs +75 -0
  40. package/dist-cjs/gateway-mode.d.ts +40 -0
  41. package/dist-cjs/gateway-provider-auto-register.cjs +2 -38
  42. package/dist-cjs/gateway-provider.cjs +10 -22
  43. package/dist-cjs/gateway-rate-limiter-constants.cjs +2 -5
  44. package/dist-cjs/gateway-rate-limiter.cjs +5 -9
  45. package/dist-cjs/gateway-retry.cjs +6 -14
  46. package/dist-cjs/gateway-utils.cjs +201 -83
  47. package/dist-cjs/gateway-utils.d.ts +57 -1
  48. package/dist-cjs/gateway-validation.cjs +2 -6
  49. package/dist-cjs/gateway.cjs +100 -72
  50. package/dist-cjs/gateway.d.ts +3 -0
  51. package/dist-cjs/index.cjs +22 -91
  52. package/dist-cjs/index.d.ts +6 -1
  53. package/dist-cjs/instruction-errors.cjs +2 -7
  54. package/dist-cjs/instruction-optimizer.cjs +4 -10
  55. package/dist-cjs/instructions-parser.cjs +5 -10
  56. package/dist-cjs/logger-factory.cjs +3 -6
  57. package/dist-cjs/memory-path-resolution.cjs +8 -18
  58. package/dist-cjs/message-builder.cjs +11 -47
  59. package/dist-cjs/object-types-library-integration.cjs +3 -8
  60. package/dist-cjs/object-types-library.cjs +5 -10
  61. package/dist-cjs/output-auditor.cjs +1 -4
  62. package/dist-cjs/output-contract-normalizer.cjs +121 -0
  63. package/dist-cjs/output-contract-normalizer.d.ts +21 -0
  64. package/dist-cjs/request-report-generator.cjs +1 -4
  65. package/dist-cjs/response-analyzer/format-type-detector.cjs +1 -5
  66. package/dist-cjs/response-analyzer/index.cjs +3 -9
  67. package/dist-cjs/response-analyzer/object-type-detector.cjs +1 -5
  68. package/dist-cjs/response-analyzer/response-analyzer.cjs +6 -10
  69. package/dist-cjs/response-analyzer/types.cjs +1 -2
  70. package/dist-cjs/response-fallback-fixer.cjs +1 -4
  71. package/dist-cjs/runtime-objects.cjs +7 -13
  72. package/dist-cjs/template-parser.cjs +5 -42
  73. package/dist-cjs/template-render-merge.cjs +2 -6
  74. package/dist-cjs/troubleshooting-helper.cjs +13 -28
  75. package/dist-cjs/types.cjs +1 -2
  76. package/dist-cjs/types.d.ts +35 -0
  77. package/dist-cjs/usage-tracker.cjs +3 -7
  78. package/package.json +11 -5
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import type { AIInvokeRequest, ChatRequest, GatewayConfig, GatewayInvokeRejectionMetadata, GatewayTraceMergedConfig, GatewayTraceRequestIds, ModelConfig } from './types.js';
6
6
  import type { Logxer } from '@x12i/logxer';
7
+ import { type AiModelsCatalogClient, type CostCalculator } from '@x12i/ai-tools';
7
8
  /**
8
9
  * Generates MD5 hash of a string
9
10
  */
@@ -12,13 +13,17 @@ export declare function generateMD5Hash(text: string): string;
12
13
  * Auto-generates taskTypeId from MD5 hash of pre-parsed instructions if not provided
13
14
  */
14
15
  export declare function ensureTaskTypeId(request: ChatRequest, logger: Logxer): Promise<string>;
16
+ export type MergeConfigOptions = {
17
+ defaultModelConfig?: Record<string, unknown>;
18
+ catalog?: AiModelsCatalogClient | null;
19
+ };
15
20
  /**
16
21
  * Merges config with defaults
17
22
  * Supports using internal system action defaults (internalSkill or skillAudit) when useInternalDefaults is set
18
23
  */
19
24
  export declare function mergeConfig(request: ChatRequest & {
20
25
  useInternalDefaults?: 'skill' | 'audit';
21
- }, config: GatewayConfig, logger: Logxer): Promise<ChatRequest['config']>;
26
+ }, config: GatewayConfig, logger: Logxer, mergeOptions?: MergeConfigOptions): Promise<ChatRequest['config']>;
22
27
  /**
23
28
  * Maps provider/router usage objects to gateway token counts (`metadata.tokens`, Activix, trace attempts).
24
29
  * Handles promptTokens/inputTokens, OpenAI-style snake_case, Responses-style input/output tokens, and missing total (sum prompt+completion).
@@ -43,6 +48,57 @@ export declare function extractTokenUsageFromRouterResponse(routerResponse: unkn
43
48
  * Does not compute cost from tokens — adapters must populate normalized fields or raw usage.cost-style keys.
44
49
  */
45
50
  export declare function extractCostUsdFromRouterResponse(routerResponse: unknown): number | undefined;
51
+ /** Activity billing state when token usage is recorded (Run Analysis G8). */
52
+ export type ActivityCostStatus = 'priced' | 'unpriced';
53
+ export type ResolvedActivityCost = {
54
+ cost?: number;
55
+ costStatus?: ActivityCostStatus;
56
+ costBreakdown?: {
57
+ promptCostUsd: number;
58
+ completionCostUsd: number;
59
+ cachingCostUsd?: number;
60
+ reasoningCostUsd?: number;
61
+ audioCostUsd?: number;
62
+ imageCostUsd?: number;
63
+ requestFlatCostUsd?: number;
64
+ };
65
+ };
66
+ export declare function hasNonZeroTokenUsage(tokens: {
67
+ prompt: number;
68
+ completion: number;
69
+ total: number;
70
+ }): boolean;
71
+ /**
72
+ * Gateway fallback when the router does not set `metadata.costStatus`.
73
+ * Prefer {@link resolveCostCompletionForActivity} at invoke boundaries.
74
+ */
75
+ export declare function resolveActivityCostCompletion(tokens: {
76
+ prompt: number;
77
+ completion: number;
78
+ total: number;
79
+ }, costUsd: number | undefined): ResolvedActivityCost;
80
+ /**
81
+ * Activity cost slice for Activix: router `metadata.costStatus` / cost wins when present;
82
+ * otherwise gateway applies the G8 fallback (usage + no price → `unpriced`).
83
+ */
84
+ export declare function resolveCostCompletionForActivity(routerResponse: unknown, tokens: {
85
+ prompt: number;
86
+ completion: number;
87
+ total: number;
88
+ }): ResolvedActivityCost;
89
+ export type ResolveCostCompletionOptions = {
90
+ mergedConfig?: unknown;
91
+ calculator?: CostCalculator | null;
92
+ calculateCost?: boolean;
93
+ };
94
+ /**
95
+ * Router cost passthrough, then optional @x12i/ai-tools catalog pricing when still unpriced.
96
+ */
97
+ export declare function resolveCostCompletionWithAiTools(routerResponse: unknown, tokens: {
98
+ prompt: number;
99
+ completion: number;
100
+ total: number;
101
+ }, options?: ResolveCostCompletionOptions): Promise<ResolvedActivityCost>;
46
102
  /**
47
103
  * Stable routing facts for gateway response metadata (router metadata + merged config fallbacks).
48
104
  * Matches trace-mode resolution; intended for every successful invoke(), not only diagnostics.trace.
@@ -1,11 +1,7 @@
1
- "use strict";
2
1
  /**
3
2
  * Gateway Validation Module
4
3
  * Basic validation for clean proxy implementation
5
4
  */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.validateChatRequest = validateChatRequest;
8
- exports.validateAIRequest = validateAIRequest;
9
5
  function validateMandatoryRuntimeIdentity(request) {
10
6
  const id = request.identity;
11
7
  if (id === undefined || id === null || typeof id !== 'object') {
@@ -16,7 +12,7 @@ function validateMandatoryRuntimeIdentity(request) {
16
12
  /**
17
13
  * Validates ChatRequest has required fields
18
14
  */
19
- function validateChatRequest(request) {
15
+ export function validateChatRequest(request) {
20
16
  if (!request.aiRequestId) {
21
17
  throw new Error('aiRequestId is required');
22
18
  }
@@ -40,7 +36,7 @@ const GATEWAY_ACTION_TYPES = ['skill', 'preSkill', 'postSkill'];
40
36
  /**
41
37
  * Validates AIInvokeRequest has required fields
42
38
  */
43
- function validateAIRequest(request) {
39
+ export function validateAIRequest(request) {
44
40
  if (!request.aiRequestId) {
45
41
  throw new Error('aiRequestId is required for AI requests');
46
42
  }
@@ -1,21 +1,20 @@
1
- "use strict";
2
1
  /**
3
2
  * @x12i/ai-gateway
4
3
  *
5
4
  * Simplified AI Gateway - Clean proxy implementation
6
5
  */
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.AIGateway = void 0;
9
- const gateway_validation_js_1 = require("./gateway-validation.cjs");
10
- const activity_manager_js_1 = require("./activity-manager.cjs");
11
- const gateway_config_js_1 = require("./gateway-config.cjs");
12
- const message_builder_js_1 = require("./message-builder.cjs");
13
- const flex_md_loader_js_1 = require("./flex-md-loader.cjs");
14
- const gateway_utils_js_1 = require("./gateway-utils.cjs");
15
- const gateway_provider_auto_register_js_1 = require("./gateway-provider-auto-register.cjs");
16
- const runtime_objects_js_1 = require("./runtime-objects.cjs");
17
- const gateway_log_meta_js_1 = require("./gateway-log-meta.cjs");
18
- const gateway_retry_js_1 = require("./gateway-retry.cjs");
6
+ import { validateChatRequest, validateAIRequest } from './gateway-validation.js';
7
+ import { ensureGatewayRequestIdentity } from './activity-manager.js';
8
+ import { initializeGatewayComponents } from './gateway-config.js';
9
+ import { buildMessages } from './message-builder.js';
10
+ import { extractJsonFromFlexMd } from './flex-md-loader.js';
11
+ import { enrichParsedContentForOutputContract, resolveOutputContractFieldKeys } from './output-contract-normalizer.js';
12
+ import { attachGatewayInvokeRejectionMetadata, buildInvokeRejectionMetadata, capActivityFullResponsePayload, DEFAULT_ACTIVITY_FULL_RESPONSE_MAX_CHARS, extractCostUsdFromRouterResponse, extractTokenUsageFromRouterResponse, mergeConfig, pickEffectiveModelConfigForMetadata, pickInvokeRoutingMetadataSlice, pickTraceMergedRouterConfig, resolveCostCompletionWithAiTools, tryExtractRouterLikePayloadFromErrorChain } from './gateway-utils.js';
13
+ import { getAiToolsClient } from './ai-tools-client.js';
14
+ import { autoRegisterProviders } from './gateway-provider-auto-register.js';
15
+ import { setGatewayLastJobId, setGatewayRuntimeClients } from './runtime-objects.js';
16
+ import { gatewayLogDebug, withActivityIdentity } from './gateway-log-meta.js';
17
+ import { invokeWithRetry } from './gateway-retry.js';
19
18
  /** Error message thrown by the router when no provider is registered or specified */
20
19
  const NO_PROVIDER_ERROR = 'No provider specified and no providers registered';
21
20
  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).';
@@ -27,7 +26,7 @@ function warnIfSuccessfulInvokeReportsZeroUsageOrCost(logger, identity, meta, in
27
26
  const zeroCost = typeof cost === 'number' && cost === 0;
28
27
  if (!zeroTokens && !zeroCostUsd && !zeroCost)
29
28
  return;
30
- logger.warn('Successful provider response reported zero token usage and/or zero cost; verify router adapter usage and billing metadata', (0, gateway_log_meta_js_1.withActivityIdentity)(identity, {
29
+ logger.warn('Successful provider response reported zero token usage and/or zero cost; verify router adapter usage and billing metadata', withActivityIdentity(identity, {
31
30
  invokeKind,
32
31
  zeroTokens,
33
32
  zeroCostUsd,
@@ -35,28 +34,31 @@ function warnIfSuccessfulInvokeReportsZeroUsageOrCost(logger, identity, meta, in
35
34
  tokens,
36
35
  costUsd,
37
36
  cost,
38
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.anomaly
37
+ debugKind: gatewayLogDebug.anomaly
39
38
  }));
40
39
  }
41
40
  /**
42
41
  * Simplified AI Gateway - Clean proxy implementation
43
42
  */
44
- class AIGateway {
43
+ export class AIGateway {
45
44
  router;
46
45
  config;
47
46
  logger;
48
47
  activityManager;
49
48
  messageBuilderConfig;
49
+ defaultModelConfig = {};
50
50
  _autoRegisterDone = false;
51
+ _aiToolsClient = null;
51
52
  constructor(config = {}, activityManager) {
52
53
  this.config = config;
53
54
  this.activityManager = activityManager;
54
- const components = (0, gateway_config_js_1.initializeGatewayComponents)(config);
55
+ const components = initializeGatewayComponents(config);
55
56
  this.logger = components.logger;
56
57
  this.router = components.router;
57
58
  this.activityManager = components.activityManager;
58
59
  this.messageBuilderConfig = components.messageBuilderConfig;
59
- (0, runtime_objects_js_1.setGatewayRuntimeClients)({
60
+ this.defaultModelConfig = components.defaultModelConfig ?? {};
61
+ setGatewayRuntimeClients({
60
62
  activix: this.activityManager?.getTracker(),
61
63
  logger: this.logger
62
64
  });
@@ -71,20 +73,24 @@ class AIGateway {
71
73
  async invokeChat(request) {
72
74
  const startTime = Date.now();
73
75
  // Basic validation
74
- (0, gateway_validation_js_1.validateChatRequest)(request);
75
- (0, activity_manager_js_1.ensureGatewayRequestIdentity)(request, undefined, this.logger);
76
- (0, runtime_objects_js_1.setGatewayLastJobId)(resolveRuntimeJobId(request));
76
+ validateChatRequest(request);
77
+ ensureGatewayRequestIdentity(request, undefined, this.logger);
78
+ setGatewayLastJobId(resolveRuntimeJobId(request));
77
79
  // Generate simple task type ID
78
80
  const taskTypeId = request.taskTypeId || `task-${Date.now()}`;
79
81
  // Simple message construction
80
82
  const messages = this.buildSimpleMessages(request);
81
83
  // Merge config (modelConfig > request.config > gateway defaults)
82
- const mergedConfig = await (0, gateway_utils_js_1.mergeConfig)(request, this.config, this.logger);
84
+ const aiTools = await this.getAiTools();
85
+ const mergedConfig = await mergeConfig(request, this.config, this.logger, {
86
+ defaultModelConfig: this.defaultModelConfig,
87
+ catalog: aiTools?.catalog ?? null
88
+ });
83
89
  // Activix start snapshot must match what the router receives (modelConfig-only callers omit request.config.model).
84
90
  request._mergedRouterConfig = mergedConfig;
85
91
  // Lazy auto-register providers from env (OPENAI_API_KEY, etc.) so consumers don't have to call init
86
92
  if (!this._autoRegisterDone) {
87
- await (0, gateway_provider_auto_register_js_1.autoRegisterProviders)(this.router, this.logger);
93
+ await autoRegisterProviders(this.router, this.logger);
88
94
  this._autoRegisterDone = true;
89
95
  }
90
96
  // Start activity tracking if available
@@ -111,8 +117,13 @@ class AIGateway {
111
117
  },
112
118
  mode: 'sync'
113
119
  });
114
- const costUsdChat = (0, gateway_utils_js_1.extractCostUsdFromRouterResponse)(response);
115
120
  const metaChat = response?.metadata || {};
121
+ const tokensChat = extractTokenUsageFromRouterResponse(response);
122
+ const costCompletionChat = await resolveCostCompletionWithAiTools(response, tokensChat, {
123
+ mergedConfig,
124
+ calculator: aiTools?.calculator ?? null,
125
+ calculateCost: this.config.aiTools?.calculateCost
126
+ });
116
127
  // Create enhanced response
117
128
  const enhancedResponse = {
118
129
  content: response.content || '',
@@ -120,22 +131,25 @@ class AIGateway {
120
131
  aiRequestId: request.aiRequestId,
121
132
  identity: request.identity,
122
133
  latencyMs: Date.now() - startTime,
123
- tokens: (0, gateway_utils_js_1.extractTokenUsageFromRouterResponse)(response),
134
+ tokens: tokensChat,
124
135
  taskTypeId,
125
136
  agentType: 'chat',
126
- ...(typeof costUsdChat === 'number'
137
+ ...(costCompletionChat.costStatus === 'priced'
127
138
  ? {
128
- costUsd: costUsdChat,
129
- ...(typeof metaChat.cost === 'number' ? { cost: metaChat.cost } : { cost: costUsdChat })
139
+ costUsd: costCompletionChat.cost,
140
+ ...(typeof metaChat.cost === 'number'
141
+ ? { cost: metaChat.cost }
142
+ : { cost: costCompletionChat.cost })
130
143
  }
131
- : {})
144
+ : {}),
145
+ ...(costCompletionChat.costStatus ? { costStatus: costCompletionChat.costStatus } : {})
132
146
  }
133
147
  };
134
148
  // Track activity success if activity was started
135
149
  if (activity) {
136
150
  try {
137
151
  await this.activityManager.logSuccess(activity, {
138
- ...(typeof costUsdChat === 'number' ? { cost: costUsdChat } : {}),
152
+ ...costCompletionChat,
139
153
  response: enhancedResponse,
140
154
  endTime: Date.now(),
141
155
  duration: Date.now() - startTime
@@ -170,9 +184,9 @@ class AIGateway {
170
184
  async invoke(request) {
171
185
  const startTime = Date.now();
172
186
  // Basic validation
173
- (0, gateway_validation_js_1.validateAIRequest)(request);
174
- (0, activity_manager_js_1.ensureGatewayRequestIdentity)(request, undefined, this.logger);
175
- (0, runtime_objects_js_1.setGatewayLastJobId)(resolveRuntimeJobId(request));
187
+ validateAIRequest(request);
188
+ ensureGatewayRequestIdentity(request, undefined, this.logger);
189
+ setGatewayLastJobId(resolveRuntimeJobId(request));
176
190
  // Generate simple task type ID
177
191
  const taskTypeId = request.taskTypeId || `task-${Date.now()}`;
178
192
  // Resolve instructions and build messages using proper components
@@ -183,7 +197,7 @@ class AIGateway {
183
197
  // Use proper instruction resolution and message building
184
198
  let builtMessages;
185
199
  try {
186
- builtMessages = await (0, message_builder_js_1.buildMessages)(request, this.messageBuilderConfig, {
200
+ builtMessages = await buildMessages(request, this.messageBuilderConfig, {
187
201
  parsedSnapshot
188
202
  });
189
203
  messages = builtMessages.messages;
@@ -228,13 +242,13 @@ class AIGateway {
228
242
  failureType: 'validation-failure'
229
243
  }, startTime);
230
244
  }
231
- const rejectMeta = (0, gateway_utils_js_1.buildInvokeRejectionMetadata)({
245
+ const rejectMeta = buildInvokeRejectionMetadata({
232
246
  request,
233
247
  taskTypeId,
234
248
  startTime,
235
249
  gatewayAiRequestId: request.aiRequestId
236
250
  });
237
- (0, gateway_utils_js_1.attachGatewayInvokeRejectionMetadata)(err, rejectMeta);
251
+ attachGatewayInvokeRejectionMetadata(err, rejectMeta);
238
252
  // Re-throw the error so it propagates to the caller
239
253
  throw err;
240
254
  }
@@ -248,14 +262,18 @@ class AIGateway {
248
262
  // Attach parsedSnapshot to request for activity tracking
249
263
  request._parsedRequest = parsedSnapshot;
250
264
  // Merge config (modelConfig > request.config > gateway defaults)
251
- const mergedConfig = await (0, gateway_utils_js_1.mergeConfig)(request, this.config, this.logger);
265
+ const aiTools = await this.getAiTools();
266
+ const mergedConfig = await mergeConfig(request, this.config, this.logger, {
267
+ defaultModelConfig: this.defaultModelConfig,
268
+ catalog: aiTools?.catalog ?? null
269
+ });
252
270
  request._mergedRouterConfig = mergedConfig;
253
271
  const diagnosticsMode = request.diagnostics?.mode;
254
272
  const traceEnabled = diagnosticsMode === 'trace';
255
273
  const includeRawProviderPayload = request.diagnostics?.includeRawProviderPayload === true;
256
274
  // Lazy auto-register providers from env (OPENAI_API_KEY, etc.) so consumers don't have to call init
257
275
  if (!this._autoRegisterDone) {
258
- await (0, gateway_provider_auto_register_js_1.autoRegisterProviders)(this.router, this.logger);
276
+ await autoRegisterProviders(this.router, this.logger);
259
277
  this._autoRegisterDone = true;
260
278
  }
261
279
  // Start activity tracking if available
@@ -346,7 +364,7 @@ class AIGateway {
346
364
  // Track per-retry attempt objects through retry hooks.
347
365
  const attemptIndexByRetry = new Map();
348
366
  try {
349
- const result = await (0, gateway_retry_js_1.invokeWithRetry)({
367
+ const result = await invokeWithRetry({
350
368
  ...baseRequest,
351
369
  request: {
352
370
  ...baseRequest.request,
@@ -386,7 +404,7 @@ class AIGateway {
386
404
  const respAny = tryResp;
387
405
  if (ok && respAny) {
388
406
  const meta = respAny.metadata || {};
389
- const tokenCounts = (0, gateway_utils_js_1.extractTokenUsageFromRouterResponse)(respAny);
407
+ const tokenCounts = extractTokenUsageFromRouterResponse(respAny);
390
408
  a.usage = {
391
409
  tokens: tokenCounts,
392
410
  maxTokensRequested: typeof meta?.maxTokensRequested === 'number'
@@ -415,7 +433,7 @@ class AIGateway {
415
433
  a.routing.requestIds = requestIds;
416
434
  a.modelUsed =
417
435
  meta?.modelUsed || meta?.model || respAny.model || candidate.model;
418
- const attemptCostUsd = (0, gateway_utils_js_1.extractCostUsdFromRouterResponse)(respAny);
436
+ const attemptCostUsd = extractCostUsdFromRouterResponse(respAny);
419
437
  if (typeof attemptCostUsd === 'number')
420
438
  a.costUsd = attemptCostUsd;
421
439
  if (includeRawProviderPayload) {
@@ -480,35 +498,35 @@ class AIGateway {
480
498
  let parsingMethod = undefined;
481
499
  // Actually use flex-md parsing - extract structured data from markdown
482
500
  try {
483
- this.logger.debug('Attempting flex-md extraction', (0, gateway_log_meta_js_1.withActivityIdentity)(request.identity, {
501
+ this.logger.debug('Attempting flex-md extraction', withActivityIdentity(request.identity, {
484
502
  contentLength: content.length,
485
503
  hasInstructions: !!resolvedRequest.instructions,
486
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.intent
504
+ debugKind: gatewayLogDebug.intent
487
505
  }));
488
506
  // Let flex-md extract structured data from the response content
489
- const extractionResult = await (0, flex_md_loader_js_1.extractJsonFromFlexMd)(content, this.logger);
490
- this.logger.debug('Flex-md extraction result', (0, gateway_log_meta_js_1.withActivityIdentity)(request.identity, {
507
+ const extractionResult = await extractJsonFromFlexMd(content, this.logger);
508
+ this.logger.debug('Flex-md extraction result', withActivityIdentity(request.identity, {
491
509
  hasResult: !!extractionResult,
492
510
  hasJson: !!(extractionResult && extractionResult.json),
493
511
  method: extractionResult?.method,
494
512
  jsonType: extractionResult?.json ? typeof extractionResult.json : 'none',
495
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.state
513
+ debugKind: gatewayLogDebug.state
496
514
  }));
497
515
  if (extractionResult && extractionResult.json) {
498
516
  // Successfully extracted structured data
499
517
  parsedContent = extractionResult.json;
500
- this.logger.info('Flex-md extraction successful - parsed into structured object', (0, gateway_log_meta_js_1.withActivityIdentity)(request.identity, {
518
+ this.logger.info('Flex-md extraction successful - parsed into structured object', withActivityIdentity(request.identity, {
501
519
  method: extractionResult.method,
502
520
  extractedKeys: Object.keys(extractionResult.json),
503
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.event
521
+ debugKind: gatewayLogDebug.event
504
522
  }));
505
523
  }
506
524
  else {
507
525
  // Extraction failed, fall back to raw text wrapper
508
- this.logger.warn('Flex-md extraction failed - no structured data extracted', (0, gateway_log_meta_js_1.withActivityIdentity)(request.identity, {
526
+ this.logger.warn('Flex-md extraction failed - no structured data extracted', withActivityIdentity(request.identity, {
509
527
  hasResult: !!extractionResult,
510
528
  method: extractionResult?.method || 'none',
511
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.anomaly
529
+ debugKind: gatewayLogDebug.anomaly
512
530
  }));
513
531
  parsedContent = { rawText: content };
514
532
  }
@@ -516,30 +534,36 @@ class AIGateway {
516
534
  catch (extractionError) {
517
535
  // Extraction failed, fall back to raw text wrapper
518
536
  const errorMessage = extractionError instanceof Error ? extractionError.message : String(extractionError);
519
- this.logger.warn('Flex-md extraction failed - flex-md library compatibility issue', (0, gateway_log_meta_js_1.withActivityIdentity)(request.identity, {
537
+ this.logger.warn('Flex-md extraction failed - flex-md library compatibility issue', withActivityIdentity(request.identity, {
520
538
  error: errorMessage,
521
539
  issue: 'flex-md uses require() in ES module context - needs fixing in flex-md-loader.ts',
522
540
  fallback: 'using rawText wrapper',
523
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.anomaly
541
+ debugKind: gatewayLogDebug.anomaly
524
542
  }));
525
543
  parsedContent = { rawText: content };
526
544
  }
527
545
  contentType = 'structured';
528
546
  parsingMethod = 'flex-md';
529
- let tokens = (0, gateway_utils_js_1.extractTokenUsageFromRouterResponse)(routerResponse);
547
+ const outputContractKeys = resolveOutputContractFieldKeys(request);
548
+ parsedContent = await enrichParsedContentForOutputContract(parsedContent, content, outputContractKeys, this.logger);
549
+ let tokens = extractTokenUsageFromRouterResponse(routerResponse);
530
550
  if (!(tokens.prompt || tokens.completion || tokens.total)) {
531
551
  const alt = routerResponse?.rawResponse ?? routerResponse?.raw;
532
552
  if (alt != null && typeof alt === 'object' && alt !== routerResponse) {
533
- const second = (0, gateway_utils_js_1.extractTokenUsageFromRouterResponse)(alt);
553
+ const second = extractTokenUsageFromRouterResponse(alt);
534
554
  if (second.prompt || second.completion || second.total)
535
555
  tokens = second;
536
556
  }
537
557
  }
538
- const resolvedCostUsd = (0, gateway_utils_js_1.extractCostUsdFromRouterResponse)(routerResponse);
558
+ const costCompletion = await resolveCostCompletionWithAiTools(routerResponse, tokens, {
559
+ mergedConfig,
560
+ calculator: aiTools?.calculator ?? null,
561
+ calculateCost: this.config.aiTools?.calculateCost
562
+ });
539
563
  const routerMetaForCost = routerResponse?.metadata || {};
540
- const routingMetadataSlice = (0, gateway_utils_js_1.pickInvokeRoutingMetadataSlice)(routerResponse, mergedConfig);
541
- const effectiveModelConfig = (0, gateway_utils_js_1.pickEffectiveModelConfigForMetadata)(mergedConfig);
542
- const traceMergedRouterSnapshot = traceEnabled ? (0, gateway_utils_js_1.pickTraceMergedRouterConfig)(mergedConfig) : undefined;
564
+ const routingMetadataSlice = pickInvokeRoutingMetadataSlice(routerResponse, mergedConfig);
565
+ const effectiveModelConfig = pickEffectiveModelConfigForMetadata(mergedConfig);
566
+ const traceMergedRouterSnapshot = traceEnabled ? pickTraceMergedRouterConfig(mergedConfig) : undefined;
543
567
  const enhancedResponse = {
544
568
  content: content,
545
569
  parsedContent: parsedContent,
@@ -554,14 +578,15 @@ class AIGateway {
554
578
  parsingMethod,
555
579
  ...routingMetadataSlice,
556
580
  ...(effectiveModelConfig !== undefined ? { effectiveModelConfig } : {}),
557
- ...(typeof resolvedCostUsd === 'number'
581
+ ...(costCompletion.costStatus === 'priced'
558
582
  ? {
559
- costUsd: resolvedCostUsd,
583
+ costUsd: costCompletion.cost,
560
584
  ...(typeof routerMetaForCost.cost === 'number'
561
585
  ? { cost: routerMetaForCost.cost }
562
- : { cost: resolvedCostUsd })
586
+ : { cost: costCompletion.cost })
563
587
  }
564
588
  : {}),
589
+ ...(costCompletion.costStatus ? { costStatus: costCompletion.costStatus } : {}),
565
590
  ...(traceEnabled
566
591
  ? {
567
592
  requestIds: traceRequestIds,
@@ -582,10 +607,10 @@ class AIGateway {
582
607
  const includeFullProviderBlob = diag?.includeFullProviderResponseInActivity !== false;
583
608
  const maxFullChars = typeof diag?.activityFullResponseMaxChars === 'number' && diag.activityFullResponseMaxChars > 0
584
609
  ? diag.activityFullResponseMaxChars
585
- : gateway_utils_js_1.DEFAULT_ACTIVITY_FULL_RESPONSE_MAX_CHARS;
610
+ : DEFAULT_ACTIVITY_FULL_RESPONSE_MAX_CHARS;
586
611
  const rawFull = routerResponse.rawResponse || routerResponse;
587
612
  const fullResponseForActivity = includeFullProviderBlob
588
- ? (0, gateway_utils_js_1.capActivityFullResponsePayload)(rawFull, maxFullChars)
613
+ ? capActivityFullResponsePayload(rawFull, maxFullChars)
589
614
  : undefined;
590
615
  // Create activity response with proper structure for ActivityTracker
591
616
  const activityResponse = {
@@ -600,7 +625,7 @@ class AIGateway {
600
625
  usage: tokens
601
626
  };
602
627
  await this.activityManager.logSuccess(activity, {
603
- ...(typeof resolvedCostUsd === 'number' ? { cost: resolvedCostUsd } : {}),
628
+ ...costCompletion,
604
629
  response: activityResponse,
605
630
  endTime: Date.now(),
606
631
  duration: Date.now() - startTime
@@ -619,17 +644,17 @@ class AIGateway {
619
644
  costUsd: enhancedResponse.metadata.costUsd,
620
645
  cost: enhancedResponse.metadata.cost
621
646
  }, 'invoke');
622
- this.logger.debug('gateway: enhancedResponse', (0, gateway_log_meta_js_1.withActivityIdentity)(request.identity, {
647
+ this.logger.debug('gateway: enhancedResponse', withActivityIdentity(request.identity, {
623
648
  latencyMs: enhancedResponse.metadata?.latencyMs,
624
649
  contentType: enhancedResponse.metadata?.contentType,
625
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.state
650
+ debugKind: gatewayLogDebug.state
626
651
  }));
627
652
  return enhancedResponse;
628
653
  }
629
654
  catch (error) {
630
655
  const err = error instanceof Error ? error : new Error(String(error));
631
- const partial = (0, gateway_utils_js_1.tryExtractRouterLikePayloadFromErrorChain)(err);
632
- const rejectMeta = (0, gateway_utils_js_1.buildInvokeRejectionMetadata)({
656
+ const partial = tryExtractRouterLikePayloadFromErrorChain(err);
657
+ const rejectMeta = buildInvokeRejectionMetadata({
633
658
  request,
634
659
  taskTypeId,
635
660
  startTime,
@@ -637,11 +662,11 @@ class AIGateway {
637
662
  partialRouterPayload: partial,
638
663
  gatewayAiRequestId: request.aiRequestId
639
664
  });
640
- (0, gateway_utils_js_1.attachGatewayInvokeRejectionMetadata)(err, rejectMeta);
665
+ attachGatewayInvokeRejectionMetadata(err, rejectMeta);
641
666
  if (err.message.includes(NO_PROVIDER_ERROR)) {
642
667
  const wrapped = new Error(err.message + NO_PROVIDER_HINT);
643
668
  wrapped.cause = err;
644
- (0, gateway_utils_js_1.attachGatewayInvokeRejectionMetadata)(wrapped, rejectMeta);
669
+ attachGatewayInvokeRejectionMetadata(wrapped, rejectMeta);
645
670
  throw wrapped;
646
671
  }
647
672
  throw err;
@@ -697,13 +722,16 @@ class AIGateway {
697
722
  }
698
723
  setActivityManager(activityManager) {
699
724
  this.activityManager = activityManager;
700
- (0, runtime_objects_js_1.setGatewayRuntimeClients)({
725
+ setGatewayRuntimeClients({
701
726
  activix: this.activityManager.getTracker(),
702
727
  logger: this.logger
703
728
  });
704
729
  }
730
+ getAiTools() {
731
+ this._aiToolsClient ??= getAiToolsClient(this.config, this.logger);
732
+ return this._aiToolsClient;
733
+ }
705
734
  }
706
- exports.AIGateway = AIGateway;
707
735
  function resolveRuntimeJobId(request) {
708
736
  return request.identity.jobId || request.identity.sessionId || request.aiRequestId;
709
737
  }
@@ -16,7 +16,9 @@ export declare class AIGateway {
16
16
  private logger;
17
17
  private activityManager?;
18
18
  private messageBuilderConfig?;
19
+ private defaultModelConfig;
19
20
  private _autoRegisterDone;
21
+ private _aiToolsClient;
20
22
  constructor(config?: GatewayConfig, activityManager?: ActivityManager);
21
23
  /**
22
24
  * Invoke chat request (without structured output requirements)
@@ -36,4 +38,5 @@ export declare class AIGateway {
36
38
  getLogger(): Logxer;
37
39
  getActivityManager(): ActivityManager | undefined;
38
40
  setActivityManager(activityManager: ActivityManager): void;
41
+ private getAiTools;
39
42
  }