@x12i/ai-gateway 9.2.0 → 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 (69) hide show
  1. package/README.md +45 -0
  2. package/dist/ai-tools-client.d.ts +20 -0
  3. package/dist/ai-tools-client.js +91 -0
  4. package/dist/gateway-config.d.ts +2 -0
  5. package/dist/gateway-config.js +2 -1
  6. package/dist/gateway-mode.d.ts +40 -0
  7. package/dist/gateway-mode.js +75 -0
  8. package/dist/gateway-utils.d.ts +28 -1
  9. package/dist/gateway-utils.js +137 -12
  10. package/dist/gateway.d.ts +3 -0
  11. package/dist/gateway.js +29 -5
  12. package/dist/index.d.ts +3 -1
  13. package/dist/index.js +2 -1
  14. package/dist/types.d.ts +21 -0
  15. package/dist-cjs/activity-manager.cjs +14 -19
  16. package/dist-cjs/ai-tools-client.cjs +91 -0
  17. package/dist-cjs/ai-tools-client.d.ts +20 -0
  18. package/dist-cjs/config/activity-tracking-config.cjs +1 -4
  19. package/dist-cjs/content-normalizer/content-normalizer.cjs +3 -8
  20. package/dist-cjs/content-normalizer/index.cjs +1 -7
  21. package/dist-cjs/content-normalizer/types.cjs +1 -2
  22. package/dist-cjs/flex-md-loader.cjs +20 -67
  23. package/dist-cjs/gateway-config.cjs +25 -63
  24. package/dist-cjs/gateway-config.d.ts +2 -0
  25. package/dist-cjs/gateway-conversion.cjs +10 -48
  26. package/dist-cjs/gateway-instructions.cjs +5 -10
  27. package/dist-cjs/gateway-log-meta.cjs +9 -14
  28. package/dist-cjs/gateway-memory.cjs +2 -6
  29. package/dist-cjs/gateway-messages.cjs +3 -6
  30. package/dist-cjs/gateway-meta.cjs +1 -4
  31. package/dist-cjs/gateway-mode.cjs +75 -0
  32. package/dist-cjs/gateway-mode.d.ts +40 -0
  33. package/dist-cjs/gateway-provider-auto-register.cjs +2 -38
  34. package/dist-cjs/gateway-provider.cjs +10 -22
  35. package/dist-cjs/gateway-rate-limiter-constants.cjs +2 -5
  36. package/dist-cjs/gateway-rate-limiter.cjs +5 -9
  37. package/dist-cjs/gateway-retry.cjs +6 -14
  38. package/dist-cjs/gateway-utils.cjs +160 -89
  39. package/dist-cjs/gateway-utils.d.ts +28 -1
  40. package/dist-cjs/gateway-validation.cjs +2 -6
  41. package/dist-cjs/gateway.cjs +86 -66
  42. package/dist-cjs/gateway.d.ts +3 -0
  43. package/dist-cjs/index.cjs +22 -98
  44. package/dist-cjs/index.d.ts +3 -1
  45. package/dist-cjs/instruction-errors.cjs +2 -7
  46. package/dist-cjs/instruction-optimizer.cjs +4 -10
  47. package/dist-cjs/instructions-parser.cjs +5 -10
  48. package/dist-cjs/logger-factory.cjs +3 -6
  49. package/dist-cjs/memory-path-resolution.cjs +8 -18
  50. package/dist-cjs/message-builder.cjs +11 -47
  51. package/dist-cjs/object-types-library-integration.cjs +3 -8
  52. package/dist-cjs/object-types-library.cjs +5 -10
  53. package/dist-cjs/output-auditor.cjs +1 -4
  54. package/dist-cjs/output-contract-normalizer.cjs +9 -14
  55. package/dist-cjs/request-report-generator.cjs +1 -4
  56. package/dist-cjs/response-analyzer/format-type-detector.cjs +1 -5
  57. package/dist-cjs/response-analyzer/index.cjs +3 -9
  58. package/dist-cjs/response-analyzer/object-type-detector.cjs +1 -5
  59. package/dist-cjs/response-analyzer/response-analyzer.cjs +6 -10
  60. package/dist-cjs/response-analyzer/types.cjs +1 -2
  61. package/dist-cjs/response-fallback-fixer.cjs +1 -4
  62. package/dist-cjs/runtime-objects.cjs +7 -13
  63. package/dist-cjs/template-parser.cjs +5 -42
  64. package/dist-cjs/template-render-merge.cjs +2 -6
  65. package/dist-cjs/troubleshooting-helper.cjs +13 -28
  66. package/dist-cjs/types.cjs +1 -2
  67. package/dist-cjs/types.d.ts +21 -0
  68. package/dist-cjs/usage-tracker.cjs +3 -7
  69. 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).
@@ -48,6 +53,15 @@ export type ActivityCostStatus = 'priced' | 'unpriced';
48
53
  export type ResolvedActivityCost = {
49
54
  cost?: number;
50
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
+ };
51
65
  };
52
66
  export declare function hasNonZeroTokenUsage(tokens: {
53
67
  prompt: number;
@@ -72,6 +86,19 @@ export declare function resolveCostCompletionForActivity(routerResponse: unknown
72
86
  completion: number;
73
87
  total: number;
74
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>;
75
102
  /**
76
103
  * Stable routing facts for gateway response metadata (router metadata + merged config fallbacks).
77
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,22 +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 output_contract_normalizer_js_1 = require("./output-contract-normalizer.cjs");
15
- const gateway_utils_js_1 = require("./gateway-utils.cjs");
16
- const gateway_provider_auto_register_js_1 = require("./gateway-provider-auto-register.cjs");
17
- const runtime_objects_js_1 = require("./runtime-objects.cjs");
18
- const gateway_log_meta_js_1 = require("./gateway-log-meta.cjs");
19
- 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';
20
18
  /** Error message thrown by the router when no provider is registered or specified */
21
19
  const NO_PROVIDER_ERROR = 'No provider specified and no providers registered';
22
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).';
@@ -28,7 +26,7 @@ function warnIfSuccessfulInvokeReportsZeroUsageOrCost(logger, identity, meta, in
28
26
  const zeroCost = typeof cost === 'number' && cost === 0;
29
27
  if (!zeroTokens && !zeroCostUsd && !zeroCost)
30
28
  return;
31
- 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, {
32
30
  invokeKind,
33
31
  zeroTokens,
34
32
  zeroCostUsd,
@@ -36,28 +34,31 @@ function warnIfSuccessfulInvokeReportsZeroUsageOrCost(logger, identity, meta, in
36
34
  tokens,
37
35
  costUsd,
38
36
  cost,
39
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.anomaly
37
+ debugKind: gatewayLogDebug.anomaly
40
38
  }));
41
39
  }
42
40
  /**
43
41
  * Simplified AI Gateway - Clean proxy implementation
44
42
  */
45
- class AIGateway {
43
+ export class AIGateway {
46
44
  router;
47
45
  config;
48
46
  logger;
49
47
  activityManager;
50
48
  messageBuilderConfig;
49
+ defaultModelConfig = {};
51
50
  _autoRegisterDone = false;
51
+ _aiToolsClient = null;
52
52
  constructor(config = {}, activityManager) {
53
53
  this.config = config;
54
54
  this.activityManager = activityManager;
55
- const components = (0, gateway_config_js_1.initializeGatewayComponents)(config);
55
+ const components = initializeGatewayComponents(config);
56
56
  this.logger = components.logger;
57
57
  this.router = components.router;
58
58
  this.activityManager = components.activityManager;
59
59
  this.messageBuilderConfig = components.messageBuilderConfig;
60
- (0, runtime_objects_js_1.setGatewayRuntimeClients)({
60
+ this.defaultModelConfig = components.defaultModelConfig ?? {};
61
+ setGatewayRuntimeClients({
61
62
  activix: this.activityManager?.getTracker(),
62
63
  logger: this.logger
63
64
  });
@@ -72,20 +73,24 @@ class AIGateway {
72
73
  async invokeChat(request) {
73
74
  const startTime = Date.now();
74
75
  // Basic validation
75
- (0, gateway_validation_js_1.validateChatRequest)(request);
76
- (0, activity_manager_js_1.ensureGatewayRequestIdentity)(request, undefined, this.logger);
77
- (0, runtime_objects_js_1.setGatewayLastJobId)(resolveRuntimeJobId(request));
76
+ validateChatRequest(request);
77
+ ensureGatewayRequestIdentity(request, undefined, this.logger);
78
+ setGatewayLastJobId(resolveRuntimeJobId(request));
78
79
  // Generate simple task type ID
79
80
  const taskTypeId = request.taskTypeId || `task-${Date.now()}`;
80
81
  // Simple message construction
81
82
  const messages = this.buildSimpleMessages(request);
82
83
  // Merge config (modelConfig > request.config > gateway defaults)
83
- 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
+ });
84
89
  // Activix start snapshot must match what the router receives (modelConfig-only callers omit request.config.model).
85
90
  request._mergedRouterConfig = mergedConfig;
86
91
  // Lazy auto-register providers from env (OPENAI_API_KEY, etc.) so consumers don't have to call init
87
92
  if (!this._autoRegisterDone) {
88
- await (0, gateway_provider_auto_register_js_1.autoRegisterProviders)(this.router, this.logger);
93
+ await autoRegisterProviders(this.router, this.logger);
89
94
  this._autoRegisterDone = true;
90
95
  }
91
96
  // Start activity tracking if available
@@ -113,8 +118,12 @@ class AIGateway {
113
118
  mode: 'sync'
114
119
  });
115
120
  const metaChat = response?.metadata || {};
116
- const tokensChat = (0, gateway_utils_js_1.extractTokenUsageFromRouterResponse)(response);
117
- const costCompletionChat = (0, gateway_utils_js_1.resolveCostCompletionForActivity)(response, tokensChat);
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
+ });
118
127
  // Create enhanced response
119
128
  const enhancedResponse = {
120
129
  content: response.content || '',
@@ -175,9 +184,9 @@ class AIGateway {
175
184
  async invoke(request) {
176
185
  const startTime = Date.now();
177
186
  // Basic validation
178
- (0, gateway_validation_js_1.validateAIRequest)(request);
179
- (0, activity_manager_js_1.ensureGatewayRequestIdentity)(request, undefined, this.logger);
180
- (0, runtime_objects_js_1.setGatewayLastJobId)(resolveRuntimeJobId(request));
187
+ validateAIRequest(request);
188
+ ensureGatewayRequestIdentity(request, undefined, this.logger);
189
+ setGatewayLastJobId(resolveRuntimeJobId(request));
181
190
  // Generate simple task type ID
182
191
  const taskTypeId = request.taskTypeId || `task-${Date.now()}`;
183
192
  // Resolve instructions and build messages using proper components
@@ -188,7 +197,7 @@ class AIGateway {
188
197
  // Use proper instruction resolution and message building
189
198
  let builtMessages;
190
199
  try {
191
- builtMessages = await (0, message_builder_js_1.buildMessages)(request, this.messageBuilderConfig, {
200
+ builtMessages = await buildMessages(request, this.messageBuilderConfig, {
192
201
  parsedSnapshot
193
202
  });
194
203
  messages = builtMessages.messages;
@@ -233,13 +242,13 @@ class AIGateway {
233
242
  failureType: 'validation-failure'
234
243
  }, startTime);
235
244
  }
236
- const rejectMeta = (0, gateway_utils_js_1.buildInvokeRejectionMetadata)({
245
+ const rejectMeta = buildInvokeRejectionMetadata({
237
246
  request,
238
247
  taskTypeId,
239
248
  startTime,
240
249
  gatewayAiRequestId: request.aiRequestId
241
250
  });
242
- (0, gateway_utils_js_1.attachGatewayInvokeRejectionMetadata)(err, rejectMeta);
251
+ attachGatewayInvokeRejectionMetadata(err, rejectMeta);
243
252
  // Re-throw the error so it propagates to the caller
244
253
  throw err;
245
254
  }
@@ -253,14 +262,18 @@ class AIGateway {
253
262
  // Attach parsedSnapshot to request for activity tracking
254
263
  request._parsedRequest = parsedSnapshot;
255
264
  // Merge config (modelConfig > request.config > gateway defaults)
256
- 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
+ });
257
270
  request._mergedRouterConfig = mergedConfig;
258
271
  const diagnosticsMode = request.diagnostics?.mode;
259
272
  const traceEnabled = diagnosticsMode === 'trace';
260
273
  const includeRawProviderPayload = request.diagnostics?.includeRawProviderPayload === true;
261
274
  // Lazy auto-register providers from env (OPENAI_API_KEY, etc.) so consumers don't have to call init
262
275
  if (!this._autoRegisterDone) {
263
- await (0, gateway_provider_auto_register_js_1.autoRegisterProviders)(this.router, this.logger);
276
+ await autoRegisterProviders(this.router, this.logger);
264
277
  this._autoRegisterDone = true;
265
278
  }
266
279
  // Start activity tracking if available
@@ -351,7 +364,7 @@ class AIGateway {
351
364
  // Track per-retry attempt objects through retry hooks.
352
365
  const attemptIndexByRetry = new Map();
353
366
  try {
354
- const result = await (0, gateway_retry_js_1.invokeWithRetry)({
367
+ const result = await invokeWithRetry({
355
368
  ...baseRequest,
356
369
  request: {
357
370
  ...baseRequest.request,
@@ -391,7 +404,7 @@ class AIGateway {
391
404
  const respAny = tryResp;
392
405
  if (ok && respAny) {
393
406
  const meta = respAny.metadata || {};
394
- const tokenCounts = (0, gateway_utils_js_1.extractTokenUsageFromRouterResponse)(respAny);
407
+ const tokenCounts = extractTokenUsageFromRouterResponse(respAny);
395
408
  a.usage = {
396
409
  tokens: tokenCounts,
397
410
  maxTokensRequested: typeof meta?.maxTokensRequested === 'number'
@@ -420,7 +433,7 @@ class AIGateway {
420
433
  a.routing.requestIds = requestIds;
421
434
  a.modelUsed =
422
435
  meta?.modelUsed || meta?.model || respAny.model || candidate.model;
423
- const attemptCostUsd = (0, gateway_utils_js_1.extractCostUsdFromRouterResponse)(respAny);
436
+ const attemptCostUsd = extractCostUsdFromRouterResponse(respAny);
424
437
  if (typeof attemptCostUsd === 'number')
425
438
  a.costUsd = attemptCostUsd;
426
439
  if (includeRawProviderPayload) {
@@ -485,35 +498,35 @@ class AIGateway {
485
498
  let parsingMethod = undefined;
486
499
  // Actually use flex-md parsing - extract structured data from markdown
487
500
  try {
488
- 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, {
489
502
  contentLength: content.length,
490
503
  hasInstructions: !!resolvedRequest.instructions,
491
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.intent
504
+ debugKind: gatewayLogDebug.intent
492
505
  }));
493
506
  // Let flex-md extract structured data from the response content
494
- const extractionResult = await (0, flex_md_loader_js_1.extractJsonFromFlexMd)(content, this.logger);
495
- 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, {
496
509
  hasResult: !!extractionResult,
497
510
  hasJson: !!(extractionResult && extractionResult.json),
498
511
  method: extractionResult?.method,
499
512
  jsonType: extractionResult?.json ? typeof extractionResult.json : 'none',
500
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.state
513
+ debugKind: gatewayLogDebug.state
501
514
  }));
502
515
  if (extractionResult && extractionResult.json) {
503
516
  // Successfully extracted structured data
504
517
  parsedContent = extractionResult.json;
505
- 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, {
506
519
  method: extractionResult.method,
507
520
  extractedKeys: Object.keys(extractionResult.json),
508
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.event
521
+ debugKind: gatewayLogDebug.event
509
522
  }));
510
523
  }
511
524
  else {
512
525
  // Extraction failed, fall back to raw text wrapper
513
- 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, {
514
527
  hasResult: !!extractionResult,
515
528
  method: extractionResult?.method || 'none',
516
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.anomaly
529
+ debugKind: gatewayLogDebug.anomaly
517
530
  }));
518
531
  parsedContent = { rawText: content };
519
532
  }
@@ -521,32 +534,36 @@ class AIGateway {
521
534
  catch (extractionError) {
522
535
  // Extraction failed, fall back to raw text wrapper
523
536
  const errorMessage = extractionError instanceof Error ? extractionError.message : String(extractionError);
524
- 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, {
525
538
  error: errorMessage,
526
539
  issue: 'flex-md uses require() in ES module context - needs fixing in flex-md-loader.ts',
527
540
  fallback: 'using rawText wrapper',
528
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.anomaly
541
+ debugKind: gatewayLogDebug.anomaly
529
542
  }));
530
543
  parsedContent = { rawText: content };
531
544
  }
532
545
  contentType = 'structured';
533
546
  parsingMethod = 'flex-md';
534
- const outputContractKeys = (0, output_contract_normalizer_js_1.resolveOutputContractFieldKeys)(request);
535
- parsedContent = await (0, output_contract_normalizer_js_1.enrichParsedContentForOutputContract)(parsedContent, content, outputContractKeys, this.logger);
536
- 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);
537
550
  if (!(tokens.prompt || tokens.completion || tokens.total)) {
538
551
  const alt = routerResponse?.rawResponse ?? routerResponse?.raw;
539
552
  if (alt != null && typeof alt === 'object' && alt !== routerResponse) {
540
- const second = (0, gateway_utils_js_1.extractTokenUsageFromRouterResponse)(alt);
553
+ const second = extractTokenUsageFromRouterResponse(alt);
541
554
  if (second.prompt || second.completion || second.total)
542
555
  tokens = second;
543
556
  }
544
557
  }
545
- const costCompletion = (0, gateway_utils_js_1.resolveCostCompletionForActivity)(routerResponse, tokens);
558
+ const costCompletion = await resolveCostCompletionWithAiTools(routerResponse, tokens, {
559
+ mergedConfig,
560
+ calculator: aiTools?.calculator ?? null,
561
+ calculateCost: this.config.aiTools?.calculateCost
562
+ });
546
563
  const routerMetaForCost = routerResponse?.metadata || {};
547
- const routingMetadataSlice = (0, gateway_utils_js_1.pickInvokeRoutingMetadataSlice)(routerResponse, mergedConfig);
548
- const effectiveModelConfig = (0, gateway_utils_js_1.pickEffectiveModelConfigForMetadata)(mergedConfig);
549
- 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;
550
567
  const enhancedResponse = {
551
568
  content: content,
552
569
  parsedContent: parsedContent,
@@ -590,10 +607,10 @@ class AIGateway {
590
607
  const includeFullProviderBlob = diag?.includeFullProviderResponseInActivity !== false;
591
608
  const maxFullChars = typeof diag?.activityFullResponseMaxChars === 'number' && diag.activityFullResponseMaxChars > 0
592
609
  ? diag.activityFullResponseMaxChars
593
- : gateway_utils_js_1.DEFAULT_ACTIVITY_FULL_RESPONSE_MAX_CHARS;
610
+ : DEFAULT_ACTIVITY_FULL_RESPONSE_MAX_CHARS;
594
611
  const rawFull = routerResponse.rawResponse || routerResponse;
595
612
  const fullResponseForActivity = includeFullProviderBlob
596
- ? (0, gateway_utils_js_1.capActivityFullResponsePayload)(rawFull, maxFullChars)
613
+ ? capActivityFullResponsePayload(rawFull, maxFullChars)
597
614
  : undefined;
598
615
  // Create activity response with proper structure for ActivityTracker
599
616
  const activityResponse = {
@@ -627,17 +644,17 @@ class AIGateway {
627
644
  costUsd: enhancedResponse.metadata.costUsd,
628
645
  cost: enhancedResponse.metadata.cost
629
646
  }, 'invoke');
630
- this.logger.debug('gateway: enhancedResponse', (0, gateway_log_meta_js_1.withActivityIdentity)(request.identity, {
647
+ this.logger.debug('gateway: enhancedResponse', withActivityIdentity(request.identity, {
631
648
  latencyMs: enhancedResponse.metadata?.latencyMs,
632
649
  contentType: enhancedResponse.metadata?.contentType,
633
- debugKind: gateway_log_meta_js_1.gatewayLogDebug.state
650
+ debugKind: gatewayLogDebug.state
634
651
  }));
635
652
  return enhancedResponse;
636
653
  }
637
654
  catch (error) {
638
655
  const err = error instanceof Error ? error : new Error(String(error));
639
- const partial = (0, gateway_utils_js_1.tryExtractRouterLikePayloadFromErrorChain)(err);
640
- const rejectMeta = (0, gateway_utils_js_1.buildInvokeRejectionMetadata)({
656
+ const partial = tryExtractRouterLikePayloadFromErrorChain(err);
657
+ const rejectMeta = buildInvokeRejectionMetadata({
641
658
  request,
642
659
  taskTypeId,
643
660
  startTime,
@@ -645,11 +662,11 @@ class AIGateway {
645
662
  partialRouterPayload: partial,
646
663
  gatewayAiRequestId: request.aiRequestId
647
664
  });
648
- (0, gateway_utils_js_1.attachGatewayInvokeRejectionMetadata)(err, rejectMeta);
665
+ attachGatewayInvokeRejectionMetadata(err, rejectMeta);
649
666
  if (err.message.includes(NO_PROVIDER_ERROR)) {
650
667
  const wrapped = new Error(err.message + NO_PROVIDER_HINT);
651
668
  wrapped.cause = err;
652
- (0, gateway_utils_js_1.attachGatewayInvokeRejectionMetadata)(wrapped, rejectMeta);
669
+ attachGatewayInvokeRejectionMetadata(wrapped, rejectMeta);
653
670
  throw wrapped;
654
671
  }
655
672
  throw err;
@@ -705,13 +722,16 @@ class AIGateway {
705
722
  }
706
723
  setActivityManager(activityManager) {
707
724
  this.activityManager = activityManager;
708
- (0, runtime_objects_js_1.setGatewayRuntimeClients)({
725
+ setGatewayRuntimeClients({
709
726
  activix: this.activityManager.getTracker(),
710
727
  logger: this.logger
711
728
  });
712
729
  }
730
+ getAiTools() {
731
+ this._aiToolsClient ??= getAiToolsClient(this.config, this.logger);
732
+ return this._aiToolsClient;
733
+ }
713
734
  }
714
- exports.AIGateway = AIGateway;
715
735
  function resolveRuntimeJobId(request) {
716
736
  return request.identity.jobId || request.identity.sessionId || request.aiRequestId;
717
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
  }