@x12i/ai-gateway 9.1.5 → 9.2.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.
- package/dist/activity-manager.d.ts +1 -0
- package/dist/activity-manager.js +7 -0
- package/dist/flex-md-loader.d.ts +5 -0
- package/dist/flex-md-loader.js +16 -0
- package/dist/gateway-utils.d.ts +29 -0
- package/dist/gateway-utils.js +44 -0
- package/dist/gateway.js +21 -13
- package/dist/index.d.ts +6 -1
- package/dist/index.js +3 -1
- package/dist/memory-path-resolution.d.ts +33 -0
- package/dist/memory-path-resolution.js +172 -0
- package/dist/output-contract-normalizer.d.ts +21 -0
- package/dist/output-contract-normalizer.js +121 -0
- package/dist/template-parser.js +5 -3
- package/dist/types.d.ts +18 -0
- package/dist-cjs/activity-manager.cjs +7 -0
- package/dist-cjs/activity-manager.d.ts +1 -0
- package/dist-cjs/flex-md-loader.cjs +17 -0
- package/dist-cjs/flex-md-loader.d.ts +5 -0
- package/dist-cjs/gateway-utils.cjs +47 -0
- package/dist-cjs/gateway-utils.d.ts +29 -0
- package/dist-cjs/gateway.cjs +20 -12
- package/dist-cjs/index.cjs +18 -1
- package/dist-cjs/index.d.ts +6 -1
- package/dist-cjs/memory-path-resolution.cjs +182 -0
- package/dist-cjs/memory-path-resolution.d.ts +33 -0
- package/dist-cjs/output-contract-normalizer.cjs +126 -0
- package/dist-cjs/output-contract-normalizer.d.ts +21 -0
- package/dist-cjs/template-parser.cjs +5 -3
- package/dist-cjs/types.d.ts +18 -0
- package/package.json +2 -2
package/dist/template-parser.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Uses @x12i/rendrix (v4+) to parse templates with workingMemory.
|
|
5
5
|
* TemplateResolutionError from the parser is rethrown; other errors fall back to the raw template.
|
|
6
6
|
*/
|
|
7
|
+
import { prepareWorkingMemoryForTemplateRender } from './memory-path-resolution.js';
|
|
7
8
|
let rendrixModule = null;
|
|
8
9
|
let parserLoadPromise = null;
|
|
9
10
|
async function loadRendrix() {
|
|
@@ -48,6 +49,7 @@ export async function parseTemplate(template, workingMemory, taskConfig, shortTe
|
|
|
48
49
|
if (!workingMemory) {
|
|
49
50
|
return template;
|
|
50
51
|
}
|
|
52
|
+
const wmForRender = prepareWorkingMemoryForTemplateRender(workingMemory);
|
|
51
53
|
await loadRendrix();
|
|
52
54
|
if (!rendrixModule) {
|
|
53
55
|
return template;
|
|
@@ -57,18 +59,18 @@ export async function parseTemplate(template, workingMemory, taskConfig, shortTe
|
|
|
57
59
|
? rendrixModule
|
|
58
60
|
: rendrixModule.default || rendrixModule;
|
|
59
61
|
if (typeof api.render === 'function') {
|
|
60
|
-
return await api.render(template,
|
|
62
|
+
return await api.render(template, wmForRender, shortTermMemory, experienceMemory, knowledgeMemory, undefined, // functionsMap
|
|
61
63
|
undefined, // choiceOptions
|
|
62
64
|
undefined, // filesContent
|
|
63
65
|
templateRenderOptions);
|
|
64
66
|
}
|
|
65
67
|
if (typeof api.parse === 'function') {
|
|
66
|
-
return await api.parse(template,
|
|
68
|
+
return await api.parse(template, wmForRender);
|
|
67
69
|
}
|
|
68
70
|
else if (typeof api === 'function') {
|
|
69
71
|
const parser = new api();
|
|
70
72
|
if (typeof parser.parse === 'function') {
|
|
71
|
-
return await parser.parse(template,
|
|
73
|
+
return await parser.parse(template, wmForRender);
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
return template;
|
package/dist/types.d.ts
CHANGED
|
@@ -626,6 +626,10 @@ interface BaseLLMRequest extends Omit<LLMRequest, 'messages' | 'input' | 'reques
|
|
|
626
626
|
* Working memory (optional) - Affects all template parsing
|
|
627
627
|
* Passed to Rendrix (v4+) for template variable substitution.
|
|
628
628
|
* Plain {{path}} tokens are MUST paths: undefined after merge throws TemplateResolutionError (rethrown by the gateway).
|
|
629
|
+
*
|
|
630
|
+
* Dual roots (graph-engine / ai-tasks contract): `inputs` is the caller / graph-entry bag;
|
|
631
|
+
* `input` is the merged MAIN payload (object or JSON string). Smart-input and `input.*` / `inputs.*`
|
|
632
|
+
* paths resolve with cross-root fallback before render (see `resolveGatewayMemoryPathValue`).
|
|
629
633
|
*/
|
|
630
634
|
workingMemory?: unknown;
|
|
631
635
|
/**
|
|
@@ -697,6 +701,14 @@ interface BaseLLMRequest extends Omit<LLMRequest, 'messages' | 'input' | 'reques
|
|
|
697
701
|
* attach heavy diagnostic objects or raw provider payloads.
|
|
698
702
|
*/
|
|
699
703
|
diagnostics?: DiagnosticsOptions;
|
|
704
|
+
/**
|
|
705
|
+
* Explicit output contract from graph-engine / ai-tasks: field names or `{ properties }`.
|
|
706
|
+
* Also accepted on `workingMemory.inputs.outputContract`. When absent, the gateway does not
|
|
707
|
+
* infer contract fields from other request shapes (`expectedSchema`, config, etc.).
|
|
708
|
+
*/
|
|
709
|
+
outputContract?: string[] | {
|
|
710
|
+
properties: Record<string, unknown>;
|
|
711
|
+
};
|
|
700
712
|
}
|
|
701
713
|
/**
|
|
702
714
|
* Chat request for conversational use cases
|
|
@@ -928,6 +940,12 @@ export interface EnhancedLLMResponse<TContent = unknown> extends Omit<AIResponse
|
|
|
928
940
|
* Cost in USD (if available)
|
|
929
941
|
*/
|
|
930
942
|
cost?: number;
|
|
943
|
+
/**
|
|
944
|
+
* Billing state for Run Analysis / Activix when usage is recorded.
|
|
945
|
+
* - `priced`: {@link cost} / {@link costUsd} is a finite number from the router
|
|
946
|
+
* - `unpriced`: usage exists but no price table / adapter cost was returned
|
|
947
|
+
*/
|
|
948
|
+
costStatus?: 'priced' | 'unpriced';
|
|
931
949
|
/**
|
|
932
950
|
* Cost in USD (preferred stable key when the router exposes it).
|
|
933
951
|
* When both are present, costUsd should mirror cost.
|
|
@@ -159,6 +159,12 @@ function pickActivixCompletionRoutingMetadata(response) {
|
|
|
159
159
|
if (m.effectiveModelConfig != null && typeof m.effectiveModelConfig === 'object') {
|
|
160
160
|
out.effectiveModelConfig = m.effectiveModelConfig;
|
|
161
161
|
}
|
|
162
|
+
if (typeof m.cost === 'number' && Number.isFinite(m.cost))
|
|
163
|
+
out.cost = m.cost;
|
|
164
|
+
if (typeof m.costUsd === 'number' && Number.isFinite(m.costUsd))
|
|
165
|
+
out.costUsd = m.costUsd;
|
|
166
|
+
if (m.costStatus === 'priced' || m.costStatus === 'unpriced')
|
|
167
|
+
out.costStatus = m.costStatus;
|
|
162
168
|
return out;
|
|
163
169
|
}
|
|
164
170
|
function mergeGatewayActivityIdentity(request, aiRequestId, extras) {
|
|
@@ -848,6 +854,7 @@ class ActivityManager {
|
|
|
848
854
|
}
|
|
849
855
|
await this.activix.completeRecord(activity.activityId, {
|
|
850
856
|
cost: details.cost,
|
|
857
|
+
...(details.costStatus ? { costStatus: details.costStatus } : {}),
|
|
851
858
|
response: details.response,
|
|
852
859
|
outer: {
|
|
853
860
|
output: details.response,
|
|
@@ -50,6 +50,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
50
50
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
51
|
exports.loadFlexMd = loadFlexMd;
|
|
52
52
|
exports.extractJsonFromFlexMd = extractJsonFromFlexMd;
|
|
53
|
+
exports.parseMarkdownSectionsFromContent = parseMarkdownSectionsFromContent;
|
|
53
54
|
exports.isFlexMdAvailable = isFlexMdAvailable;
|
|
54
55
|
exports.getModelMaxTokensFromFlexMd = getModelMaxTokensFromFlexMd;
|
|
55
56
|
exports.getFlexMdModule = getFlexMdModule;
|
|
@@ -549,6 +550,22 @@ function fallbackMarkdownParser(content, logger) {
|
|
|
549
550
|
method: 'fallback-raw-text'
|
|
550
551
|
};
|
|
551
552
|
}
|
|
553
|
+
/**
|
|
554
|
+
* Section-based markdown → camelCase field map (e.g. `### Short Answer` → `shortAnswer`).
|
|
555
|
+
* Used when output contracts need structured `parsed` fields but flex-md returned only `rawText`.
|
|
556
|
+
*/
|
|
557
|
+
function parseMarkdownSectionsFromContent(content, logger) {
|
|
558
|
+
const parsed = fallbackMarkdownParser(content, logger);
|
|
559
|
+
const json = parsed.json;
|
|
560
|
+
if (json != null && typeof json === 'object' && !Array.isArray(json)) {
|
|
561
|
+
const keys = Object.keys(json);
|
|
562
|
+
if (keys.length === 1 && keys[0] === 'rawText') {
|
|
563
|
+
return {};
|
|
564
|
+
}
|
|
565
|
+
return json;
|
|
566
|
+
}
|
|
567
|
+
return {};
|
|
568
|
+
}
|
|
552
569
|
/**
|
|
553
570
|
* Fallback JSON extraction when flex-md is not available
|
|
554
571
|
*/
|
|
@@ -43,6 +43,11 @@ export declare function extractJsonFromFlexMd(content: string, logger?: Logxer):
|
|
|
43
43
|
json: any;
|
|
44
44
|
method: string;
|
|
45
45
|
} | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Section-based markdown → camelCase field map (e.g. `### Short Answer` → `shortAnswer`).
|
|
48
|
+
* Used when output contracts need structured `parsed` fields but flex-md returned only `rawText`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function parseMarkdownSectionsFromContent(content: string, logger?: Logxer): Record<string, unknown>;
|
|
46
51
|
/**
|
|
47
52
|
* Check if flex-md module is available
|
|
48
53
|
*/
|
|
@@ -44,6 +44,9 @@ exports.mergeConfig = mergeConfig;
|
|
|
44
44
|
exports.normalizeRouterUsageTokens = normalizeRouterUsageTokens;
|
|
45
45
|
exports.extractTokenUsageFromRouterResponse = extractTokenUsageFromRouterResponse;
|
|
46
46
|
exports.extractCostUsdFromRouterResponse = extractCostUsdFromRouterResponse;
|
|
47
|
+
exports.hasNonZeroTokenUsage = hasNonZeroTokenUsage;
|
|
48
|
+
exports.resolveActivityCostCompletion = resolveActivityCostCompletion;
|
|
49
|
+
exports.resolveCostCompletionForActivity = resolveCostCompletionForActivity;
|
|
47
50
|
exports.pickInvokeRoutingMetadataSlice = pickInvokeRoutingMetadataSlice;
|
|
48
51
|
exports.pickEffectiveModelConfigForMetadata = pickEffectiveModelConfigForMetadata;
|
|
49
52
|
exports.pickTraceMergedRouterConfig = pickTraceMergedRouterConfig;
|
|
@@ -366,6 +369,50 @@ function extractCostUsdFromRouterResponse(routerResponse) {
|
|
|
366
369
|
}
|
|
367
370
|
return undefined;
|
|
368
371
|
}
|
|
372
|
+
function hasNonZeroTokenUsage(tokens) {
|
|
373
|
+
return !!(tokens.prompt || tokens.completion || tokens.total);
|
|
374
|
+
}
|
|
375
|
+
function pickRouterCostStatus(routerResponse) {
|
|
376
|
+
if (routerResponse == null || typeof routerResponse !== 'object')
|
|
377
|
+
return undefined;
|
|
378
|
+
const r = routerResponse;
|
|
379
|
+
const meta = r.metadata != null && typeof r.metadata === 'object'
|
|
380
|
+
? r.metadata
|
|
381
|
+
: undefined;
|
|
382
|
+
const status = meta?.costStatus ?? r.costStatus;
|
|
383
|
+
return status === 'priced' || status === 'unpriced' ? status : undefined;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Gateway fallback when the router does not set `metadata.costStatus`.
|
|
387
|
+
* Prefer {@link resolveCostCompletionForActivity} at invoke boundaries.
|
|
388
|
+
*/
|
|
389
|
+
function resolveActivityCostCompletion(tokens, costUsd) {
|
|
390
|
+
if (typeof costUsd === 'number' && Number.isFinite(costUsd)) {
|
|
391
|
+
return { cost: costUsd, costStatus: 'priced' };
|
|
392
|
+
}
|
|
393
|
+
if (hasNonZeroTokenUsage(tokens)) {
|
|
394
|
+
return { costStatus: 'unpriced' };
|
|
395
|
+
}
|
|
396
|
+
return {};
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Activity cost slice for Activix: router `metadata.costStatus` / cost wins when present;
|
|
400
|
+
* otherwise gateway applies the G8 fallback (usage + no price → `unpriced`).
|
|
401
|
+
*/
|
|
402
|
+
function resolveCostCompletionForActivity(routerResponse, tokens) {
|
|
403
|
+
const routerStatus = pickRouterCostStatus(routerResponse);
|
|
404
|
+
const costUsd = extractCostUsdFromRouterResponse(routerResponse);
|
|
405
|
+
if (routerStatus === 'priced') {
|
|
406
|
+
return {
|
|
407
|
+
...(typeof costUsd === 'number' && Number.isFinite(costUsd) ? { cost: costUsd } : {}),
|
|
408
|
+
costStatus: 'priced'
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
if (routerStatus === 'unpriced') {
|
|
412
|
+
return { costStatus: 'unpriced' };
|
|
413
|
+
}
|
|
414
|
+
return resolveActivityCostCompletion(tokens, costUsd);
|
|
415
|
+
}
|
|
369
416
|
/**
|
|
370
417
|
* Stable routing facts for gateway response metadata (router metadata + merged config fallbacks).
|
|
371
418
|
* Matches trace-mode resolution; intended for every successful invoke(), not only diagnostics.trace.
|
|
@@ -43,6 +43,35 @@ export declare function extractTokenUsageFromRouterResponse(routerResponse: unkn
|
|
|
43
43
|
* Does not compute cost from tokens — adapters must populate normalized fields or raw usage.cost-style keys.
|
|
44
44
|
*/
|
|
45
45
|
export declare function extractCostUsdFromRouterResponse(routerResponse: unknown): number | undefined;
|
|
46
|
+
/** Activity billing state when token usage is recorded (Run Analysis G8). */
|
|
47
|
+
export type ActivityCostStatus = 'priced' | 'unpriced';
|
|
48
|
+
export type ResolvedActivityCost = {
|
|
49
|
+
cost?: number;
|
|
50
|
+
costStatus?: ActivityCostStatus;
|
|
51
|
+
};
|
|
52
|
+
export declare function hasNonZeroTokenUsage(tokens: {
|
|
53
|
+
prompt: number;
|
|
54
|
+
completion: number;
|
|
55
|
+
total: number;
|
|
56
|
+
}): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Gateway fallback when the router does not set `metadata.costStatus`.
|
|
59
|
+
* Prefer {@link resolveCostCompletionForActivity} at invoke boundaries.
|
|
60
|
+
*/
|
|
61
|
+
export declare function resolveActivityCostCompletion(tokens: {
|
|
62
|
+
prompt: number;
|
|
63
|
+
completion: number;
|
|
64
|
+
total: number;
|
|
65
|
+
}, costUsd: number | undefined): ResolvedActivityCost;
|
|
66
|
+
/**
|
|
67
|
+
* Activity cost slice for Activix: router `metadata.costStatus` / cost wins when present;
|
|
68
|
+
* otherwise gateway applies the G8 fallback (usage + no price → `unpriced`).
|
|
69
|
+
*/
|
|
70
|
+
export declare function resolveCostCompletionForActivity(routerResponse: unknown, tokens: {
|
|
71
|
+
prompt: number;
|
|
72
|
+
completion: number;
|
|
73
|
+
total: number;
|
|
74
|
+
}): ResolvedActivityCost;
|
|
46
75
|
/**
|
|
47
76
|
* Stable routing facts for gateway response metadata (router metadata + merged config fallbacks).
|
|
48
77
|
* Matches trace-mode resolution; intended for every successful invoke(), not only diagnostics.trace.
|
package/dist-cjs/gateway.cjs
CHANGED
|
@@ -11,6 +11,7 @@ const activity_manager_js_1 = require("./activity-manager.cjs");
|
|
|
11
11
|
const gateway_config_js_1 = require("./gateway-config.cjs");
|
|
12
12
|
const message_builder_js_1 = require("./message-builder.cjs");
|
|
13
13
|
const flex_md_loader_js_1 = require("./flex-md-loader.cjs");
|
|
14
|
+
const output_contract_normalizer_js_1 = require("./output-contract-normalizer.cjs");
|
|
14
15
|
const gateway_utils_js_1 = require("./gateway-utils.cjs");
|
|
15
16
|
const gateway_provider_auto_register_js_1 = require("./gateway-provider-auto-register.cjs");
|
|
16
17
|
const runtime_objects_js_1 = require("./runtime-objects.cjs");
|
|
@@ -111,8 +112,9 @@ class AIGateway {
|
|
|
111
112
|
},
|
|
112
113
|
mode: 'sync'
|
|
113
114
|
});
|
|
114
|
-
const costUsdChat = (0, gateway_utils_js_1.extractCostUsdFromRouterResponse)(response);
|
|
115
115
|
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);
|
|
116
118
|
// Create enhanced response
|
|
117
119
|
const enhancedResponse = {
|
|
118
120
|
content: response.content || '',
|
|
@@ -120,22 +122,25 @@ class AIGateway {
|
|
|
120
122
|
aiRequestId: request.aiRequestId,
|
|
121
123
|
identity: request.identity,
|
|
122
124
|
latencyMs: Date.now() - startTime,
|
|
123
|
-
tokens:
|
|
125
|
+
tokens: tokensChat,
|
|
124
126
|
taskTypeId,
|
|
125
127
|
agentType: 'chat',
|
|
126
|
-
...(
|
|
128
|
+
...(costCompletionChat.costStatus === 'priced'
|
|
127
129
|
? {
|
|
128
|
-
costUsd:
|
|
129
|
-
...(typeof metaChat.cost === 'number'
|
|
130
|
+
costUsd: costCompletionChat.cost,
|
|
131
|
+
...(typeof metaChat.cost === 'number'
|
|
132
|
+
? { cost: metaChat.cost }
|
|
133
|
+
: { cost: costCompletionChat.cost })
|
|
130
134
|
}
|
|
131
|
-
: {})
|
|
135
|
+
: {}),
|
|
136
|
+
...(costCompletionChat.costStatus ? { costStatus: costCompletionChat.costStatus } : {})
|
|
132
137
|
}
|
|
133
138
|
};
|
|
134
139
|
// Track activity success if activity was started
|
|
135
140
|
if (activity) {
|
|
136
141
|
try {
|
|
137
142
|
await this.activityManager.logSuccess(activity, {
|
|
138
|
-
...
|
|
143
|
+
...costCompletionChat,
|
|
139
144
|
response: enhancedResponse,
|
|
140
145
|
endTime: Date.now(),
|
|
141
146
|
duration: Date.now() - startTime
|
|
@@ -526,6 +531,8 @@ class AIGateway {
|
|
|
526
531
|
}
|
|
527
532
|
contentType = 'structured';
|
|
528
533
|
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);
|
|
529
536
|
let tokens = (0, gateway_utils_js_1.extractTokenUsageFromRouterResponse)(routerResponse);
|
|
530
537
|
if (!(tokens.prompt || tokens.completion || tokens.total)) {
|
|
531
538
|
const alt = routerResponse?.rawResponse ?? routerResponse?.raw;
|
|
@@ -535,7 +542,7 @@ class AIGateway {
|
|
|
535
542
|
tokens = second;
|
|
536
543
|
}
|
|
537
544
|
}
|
|
538
|
-
const
|
|
545
|
+
const costCompletion = (0, gateway_utils_js_1.resolveCostCompletionForActivity)(routerResponse, tokens);
|
|
539
546
|
const routerMetaForCost = routerResponse?.metadata || {};
|
|
540
547
|
const routingMetadataSlice = (0, gateway_utils_js_1.pickInvokeRoutingMetadataSlice)(routerResponse, mergedConfig);
|
|
541
548
|
const effectiveModelConfig = (0, gateway_utils_js_1.pickEffectiveModelConfigForMetadata)(mergedConfig);
|
|
@@ -554,14 +561,15 @@ class AIGateway {
|
|
|
554
561
|
parsingMethod,
|
|
555
562
|
...routingMetadataSlice,
|
|
556
563
|
...(effectiveModelConfig !== undefined ? { effectiveModelConfig } : {}),
|
|
557
|
-
...(
|
|
564
|
+
...(costCompletion.costStatus === 'priced'
|
|
558
565
|
? {
|
|
559
|
-
costUsd:
|
|
566
|
+
costUsd: costCompletion.cost,
|
|
560
567
|
...(typeof routerMetaForCost.cost === 'number'
|
|
561
568
|
? { cost: routerMetaForCost.cost }
|
|
562
|
-
: { cost:
|
|
569
|
+
: { cost: costCompletion.cost })
|
|
563
570
|
}
|
|
564
571
|
: {}),
|
|
572
|
+
...(costCompletion.costStatus ? { costStatus: costCompletion.costStatus } : {}),
|
|
565
573
|
...(traceEnabled
|
|
566
574
|
? {
|
|
567
575
|
requestIds: traceRequestIds,
|
|
@@ -600,7 +608,7 @@ class AIGateway {
|
|
|
600
608
|
usage: tokens
|
|
601
609
|
};
|
|
602
610
|
await this.activityManager.logSuccess(activity, {
|
|
603
|
-
...
|
|
611
|
+
...costCompletion,
|
|
604
612
|
response: activityResponse,
|
|
605
613
|
endTime: Date.now(),
|
|
606
614
|
duration: Date.now() - startTime
|
package/dist-cjs/index.cjs
CHANGED
|
@@ -21,7 +21,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
21
21
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
22
22
|
};
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
exports.
|
|
24
|
+
exports.createValidationTestCases = exports.createTestAIRequest = exports.supportsJSONMode = exports.diagnoseResponse = exports.diagnoseRequest = exports.validateResponse = exports.extractJSON = exports.validateJSON = exports.validateAIRequest = exports.DEFAULT_RATE_LIMIT_ENABLED = exports.DEFAULT_RATE_LIMIT_MIN_INTERVAL_MS = exports.GatewayRateLimiter = exports.runtimeObjects = exports.DebugLogAbstract = exports.createLogxer = exports.gatewayLogDebug = exports.withActivityIdentity = exports.activityIdentityToLogMeta = exports.ensureGatewayRequestIdentity = exports.ActivityManager = exports.Activix = exports.resolveGatewayMemoryPathValue = exports.prepareWorkingMemoryForTemplateRender = exports.parseLooseJsonObject = exports.mapSmartInputPathsInputsToInput = exports.extractCallerInputsBag = exports.coalesceMergedInputBucket = exports.buildMemoryResolutionRootFromWorkingMemory = exports.GATEWAY_DUAL_MEMORY_ROOTS = exports.mergeTemplateRenderOptions = exports.mergeGatewayAndRequestTemplateRenderOptions = exports.resolveOutputContractFieldKeys = exports.enrichParsedContentForOutputContract = exports.contractSpecToFieldKeys = exports.hasNonZeroTokenUsage = exports.resolveCostCompletionForActivity = exports.resolveActivityCostCompletion = exports.pickRequestIdsFromRouterLike = exports.tryExtractRouterLikePayloadFromErrorChain = exports.buildInvokeRejectionMetadata = exports.attachGatewayInvokeRejectionMetadata = exports.autoRegisterProviders = exports.InstructionBackendError = exports.InstructionNotFoundError = exports.AIGateway = exports.FallbackExhaustedError = exports.ProviderNotFoundError = exports.createRouterFromConfig = exports.createRouter = exports.LLMProviderRouter = void 0;
|
|
25
|
+
exports.resetObjectTypesLibrary = exports.getObjectTypesLibrary = exports.initializeObjectTypesLibrary = exports.getObjectTypesForAgent = exports.getObjectType = exports.OBJECT_TYPES_LIBRARY = exports.assertValidAIRequest = exports.formatDiagnostic = exports.runValidationTests = void 0;
|
|
25
26
|
// Re-export router class and types (base functionality)
|
|
26
27
|
var ai_providers_router_1 = require("@x12i/ai-providers-router");
|
|
27
28
|
Object.defineProperty(exports, "LLMProviderRouter", { enumerable: true, get: function () { return ai_providers_router_1.LLMProviderRouter; } });
|
|
@@ -48,9 +49,25 @@ Object.defineProperty(exports, "attachGatewayInvokeRejectionMetadata", { enumera
|
|
|
48
49
|
Object.defineProperty(exports, "buildInvokeRejectionMetadata", { enumerable: true, get: function () { return gateway_utils_js_1.buildInvokeRejectionMetadata; } });
|
|
49
50
|
Object.defineProperty(exports, "tryExtractRouterLikePayloadFromErrorChain", { enumerable: true, get: function () { return gateway_utils_js_1.tryExtractRouterLikePayloadFromErrorChain; } });
|
|
50
51
|
Object.defineProperty(exports, "pickRequestIdsFromRouterLike", { enumerable: true, get: function () { return gateway_utils_js_1.pickRequestIdsFromRouterLike; } });
|
|
52
|
+
Object.defineProperty(exports, "resolveActivityCostCompletion", { enumerable: true, get: function () { return gateway_utils_js_1.resolveActivityCostCompletion; } });
|
|
53
|
+
Object.defineProperty(exports, "resolveCostCompletionForActivity", { enumerable: true, get: function () { return gateway_utils_js_1.resolveCostCompletionForActivity; } });
|
|
54
|
+
Object.defineProperty(exports, "hasNonZeroTokenUsage", { enumerable: true, get: function () { return gateway_utils_js_1.hasNonZeroTokenUsage; } });
|
|
55
|
+
var output_contract_normalizer_js_1 = require("./output-contract-normalizer.cjs");
|
|
56
|
+
Object.defineProperty(exports, "contractSpecToFieldKeys", { enumerable: true, get: function () { return output_contract_normalizer_js_1.contractSpecToFieldKeys; } });
|
|
57
|
+
Object.defineProperty(exports, "enrichParsedContentForOutputContract", { enumerable: true, get: function () { return output_contract_normalizer_js_1.enrichParsedContentForOutputContract; } });
|
|
58
|
+
Object.defineProperty(exports, "resolveOutputContractFieldKeys", { enumerable: true, get: function () { return output_contract_normalizer_js_1.resolveOutputContractFieldKeys; } });
|
|
51
59
|
var template_render_merge_js_1 = require("./template-render-merge.cjs");
|
|
52
60
|
Object.defineProperty(exports, "mergeGatewayAndRequestTemplateRenderOptions", { enumerable: true, get: function () { return template_render_merge_js_1.mergeGatewayAndRequestTemplateRenderOptions; } });
|
|
53
61
|
Object.defineProperty(exports, "mergeTemplateRenderOptions", { enumerable: true, get: function () { return template_render_merge_js_1.mergeTemplateRenderOptions; } });
|
|
62
|
+
var memory_path_resolution_js_1 = require("./memory-path-resolution.cjs");
|
|
63
|
+
Object.defineProperty(exports, "GATEWAY_DUAL_MEMORY_ROOTS", { enumerable: true, get: function () { return memory_path_resolution_js_1.GATEWAY_DUAL_MEMORY_ROOTS; } });
|
|
64
|
+
Object.defineProperty(exports, "buildMemoryResolutionRootFromWorkingMemory", { enumerable: true, get: function () { return memory_path_resolution_js_1.buildMemoryResolutionRootFromWorkingMemory; } });
|
|
65
|
+
Object.defineProperty(exports, "coalesceMergedInputBucket", { enumerable: true, get: function () { return memory_path_resolution_js_1.coalesceMergedInputBucket; } });
|
|
66
|
+
Object.defineProperty(exports, "extractCallerInputsBag", { enumerable: true, get: function () { return memory_path_resolution_js_1.extractCallerInputsBag; } });
|
|
67
|
+
Object.defineProperty(exports, "mapSmartInputPathsInputsToInput", { enumerable: true, get: function () { return memory_path_resolution_js_1.mapSmartInputPathsInputsToInput; } });
|
|
68
|
+
Object.defineProperty(exports, "parseLooseJsonObject", { enumerable: true, get: function () { return memory_path_resolution_js_1.parseLooseJsonObject; } });
|
|
69
|
+
Object.defineProperty(exports, "prepareWorkingMemoryForTemplateRender", { enumerable: true, get: function () { return memory_path_resolution_js_1.prepareWorkingMemoryForTemplateRender; } });
|
|
70
|
+
Object.defineProperty(exports, "resolveGatewayMemoryPathValue", { enumerable: true, get: function () { return memory_path_resolution_js_1.resolveGatewayMemoryPathValue; } });
|
|
54
71
|
// Usage tracking: UsageTracker class methods are available but consumption calculation is disabled
|
|
55
72
|
// (x-models was previously used for RPM/TPM tracking but is no longer integrated)
|
|
56
73
|
// Re-export activity tracking primitives (Activix)
|
package/dist-cjs/index.d.ts
CHANGED
|
@@ -17,9 +17,14 @@ export { AIGateway } from './gateway.js';
|
|
|
17
17
|
export { InstructionNotFoundError, InstructionBackendError } from './instruction-errors.js';
|
|
18
18
|
export { autoRegisterProviders } from './gateway-provider-auto-register.js';
|
|
19
19
|
export type { GatewayConfig, ProviderModelRef, ModelConfig, RetryConfig, ChatRequest, AIInvokeRequest, AIRequest, GatewayActionType, GatewayInvokeRejectionMetadata, GatewayTraceRequestIds, GatewayTraceMergedConfig, EnhancedLLMResponse, InstructionMetadata, ValidationRule, TemplateRenderOptions, SmartInputConfig, SmartInputRenderOptions } from './types.js';
|
|
20
|
-
export { attachGatewayInvokeRejectionMetadata, buildInvokeRejectionMetadata, tryExtractRouterLikePayloadFromErrorChain, pickRequestIdsFromRouterLike } from './gateway-utils.js';
|
|
20
|
+
export { attachGatewayInvokeRejectionMetadata, buildInvokeRejectionMetadata, tryExtractRouterLikePayloadFromErrorChain, pickRequestIdsFromRouterLike, resolveActivityCostCompletion, resolveCostCompletionForActivity, hasNonZeroTokenUsage } from './gateway-utils.js';
|
|
21
|
+
export type { ActivityCostStatus, ResolvedActivityCost } from './gateway-utils.js';
|
|
22
|
+
export { contractSpecToFieldKeys, enrichParsedContentForOutputContract, resolveOutputContractFieldKeys } from './output-contract-normalizer.js';
|
|
23
|
+
export type { OutputContractSpec } from './output-contract-normalizer.js';
|
|
21
24
|
export { mergeGatewayAndRequestTemplateRenderOptions, mergeTemplateRenderOptions } from './template-render-merge.js';
|
|
22
25
|
export type { GatewayTemplateRenderRequestSlice } from './template-render-merge.js';
|
|
26
|
+
export { GATEWAY_DUAL_MEMORY_ROOTS, buildMemoryResolutionRootFromWorkingMemory, coalesceMergedInputBucket, extractCallerInputsBag, mapSmartInputPathsInputsToInput, parseLooseJsonObject, prepareWorkingMemoryForTemplateRender, resolveGatewayMemoryPathValue } from './memory-path-resolution.js';
|
|
27
|
+
export type { GatewayDualMemoryRoot } from './memory-path-resolution.js';
|
|
23
28
|
export type { UsageTier } from './types.js';
|
|
24
29
|
export { Activix } from '@x12i/activix';
|
|
25
30
|
export type { ActivixRunContext, FindByRunContextCriteria, GetJobActivitiesInput, GetJobActivitiesResult } from '@x12i/activix';
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Dual memory roots `input` (merged MAIN payload) and `inputs` (caller / graph-entry bag).
|
|
4
|
+
* Aligned with @exellix/graph-engine ≥ 5.5.0 resolution rules for template / smart-input paths.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.GATEWAY_DUAL_MEMORY_ROOTS = void 0;
|
|
8
|
+
exports.parseLooseJsonObject = parseLooseJsonObject;
|
|
9
|
+
exports.extractCallerInputsBag = extractCallerInputsBag;
|
|
10
|
+
exports.coalesceMergedInputBucket = coalesceMergedInputBucket;
|
|
11
|
+
exports.resolveGatewayMemoryPathValue = resolveGatewayMemoryPathValue;
|
|
12
|
+
exports.buildMemoryResolutionRootFromWorkingMemory = buildMemoryResolutionRootFromWorkingMemory;
|
|
13
|
+
exports.prepareWorkingMemoryForTemplateRender = prepareWorkingMemoryForTemplateRender;
|
|
14
|
+
exports.mapSmartInputPathsInputsToInput = mapSmartInputPathsInputsToInput;
|
|
15
|
+
exports.GATEWAY_DUAL_MEMORY_ROOTS = ['input', 'inputs'];
|
|
16
|
+
function isPlainObject(value) {
|
|
17
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Parse JSON object shapes from strings (matches graph-engine `parseLooseJsonObject`).
|
|
21
|
+
*/
|
|
22
|
+
function parseLooseJsonObject(value) {
|
|
23
|
+
if (isPlainObject(value))
|
|
24
|
+
return value;
|
|
25
|
+
if (typeof value !== 'string')
|
|
26
|
+
return undefined;
|
|
27
|
+
const trimmed = value.trim();
|
|
28
|
+
if (!trimmed.startsWith('{'))
|
|
29
|
+
return undefined;
|
|
30
|
+
try {
|
|
31
|
+
const parsed = JSON.parse(trimmed);
|
|
32
|
+
return isPlainObject(parsed) ? parsed : undefined;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Caller / graph-entry bag from `workingMemory.inputs`. */
|
|
39
|
+
function extractCallerInputsBag(workingMemory) {
|
|
40
|
+
if (!isPlainObject(workingMemory))
|
|
41
|
+
return undefined;
|
|
42
|
+
const inputs = workingMemory.inputs;
|
|
43
|
+
return isPlainObject(inputs) ? inputs : undefined;
|
|
44
|
+
}
|
|
45
|
+
/** Merged MAIN bucket from `workingMemory.input` (object or parsed JSON string). */
|
|
46
|
+
function coalesceMergedInputBucket(workingMemory) {
|
|
47
|
+
if (!isPlainObject(workingMemory))
|
|
48
|
+
return undefined;
|
|
49
|
+
const raw = workingMemory.input;
|
|
50
|
+
if (raw === undefined || raw === null)
|
|
51
|
+
return undefined;
|
|
52
|
+
const parsed = parseLooseJsonObject(raw);
|
|
53
|
+
return parsed !== undefined ? parsed : raw;
|
|
54
|
+
}
|
|
55
|
+
function getValueAtPath(obj, path) {
|
|
56
|
+
if (obj == null)
|
|
57
|
+
return undefined;
|
|
58
|
+
if (path === '' || path === 'this' || path === '.')
|
|
59
|
+
return obj;
|
|
60
|
+
const parts = path.split('.');
|
|
61
|
+
let cur = obj;
|
|
62
|
+
for (const part of parts) {
|
|
63
|
+
if (cur == null || typeof cur !== 'object')
|
|
64
|
+
return undefined;
|
|
65
|
+
cur = cur[part];
|
|
66
|
+
}
|
|
67
|
+
return cur;
|
|
68
|
+
}
|
|
69
|
+
function asObjectBucket(value) {
|
|
70
|
+
const parsed = parseLooseJsonObject(value);
|
|
71
|
+
if (parsed)
|
|
72
|
+
return parsed;
|
|
73
|
+
return isPlainObject(value) ? value : undefined;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Shallow-deep merge for template lookup: primary wins per key; nested plain objects merge recursively.
|
|
77
|
+
*/
|
|
78
|
+
function mergeBucketViews(primary, fallback) {
|
|
79
|
+
const pObj = asObjectBucket(primary);
|
|
80
|
+
const fObj = asObjectBucket(fallback);
|
|
81
|
+
if (!pObj && !fObj) {
|
|
82
|
+
if (primary !== undefined && primary !== null)
|
|
83
|
+
return primary;
|
|
84
|
+
return fallback;
|
|
85
|
+
}
|
|
86
|
+
if (!pObj)
|
|
87
|
+
return { ...fObj };
|
|
88
|
+
if (!fObj)
|
|
89
|
+
return { ...pObj };
|
|
90
|
+
const keys = new Set([...Object.keys(pObj), ...Object.keys(fObj)]);
|
|
91
|
+
const view = {};
|
|
92
|
+
for (const key of keys) {
|
|
93
|
+
const pv = pObj[key];
|
|
94
|
+
const fv = fObj[key];
|
|
95
|
+
if (isPlainObject(pv) && isPlainObject(fv)) {
|
|
96
|
+
view[key] = mergeBucketViews(pv, fv);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
view[key] = pv !== undefined ? pv : fv;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return view;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Resolve a dotted path against working memory with dual-root rules:
|
|
106
|
+
* - `inputs` / `inputs.*` → caller bag first, then merged `input`
|
|
107
|
+
* - `input` / `input.*` → merged `input` first, then caller `inputs`
|
|
108
|
+
* - other paths → direct lookup on working memory
|
|
109
|
+
*/
|
|
110
|
+
function resolveGatewayMemoryPathValue(workingMemory, path) {
|
|
111
|
+
const trimmed = path.trim();
|
|
112
|
+
if (!trimmed)
|
|
113
|
+
return undefined;
|
|
114
|
+
const dot = trimmed.indexOf('.');
|
|
115
|
+
const root = dot >= 0 ? trimmed.slice(0, dot) : trimmed;
|
|
116
|
+
const tail = dot >= 0 ? trimmed.slice(dot + 1) : '';
|
|
117
|
+
if (root === 'inputs') {
|
|
118
|
+
const primary = extractCallerInputsBag(workingMemory);
|
|
119
|
+
const fallback = coalesceMergedInputBucket(workingMemory);
|
|
120
|
+
if (!tail) {
|
|
121
|
+
if (primary && Object.keys(primary).length > 0)
|
|
122
|
+
return primary;
|
|
123
|
+
return fallback;
|
|
124
|
+
}
|
|
125
|
+
const fromPrimary = primary ? getValueAtPath(primary, tail) : undefined;
|
|
126
|
+
if (fromPrimary !== undefined)
|
|
127
|
+
return fromPrimary;
|
|
128
|
+
return fallback !== undefined ? getValueAtPath(fallback, tail) : undefined;
|
|
129
|
+
}
|
|
130
|
+
if (root === 'input') {
|
|
131
|
+
const primary = coalesceMergedInputBucket(workingMemory);
|
|
132
|
+
const fallback = extractCallerInputsBag(workingMemory);
|
|
133
|
+
if (!tail) {
|
|
134
|
+
if (primary !== undefined && primary !== null)
|
|
135
|
+
return primary;
|
|
136
|
+
return fallback;
|
|
137
|
+
}
|
|
138
|
+
const fromPrimary = primary !== undefined ? getValueAtPath(primary, tail) : undefined;
|
|
139
|
+
if (fromPrimary !== undefined)
|
|
140
|
+
return fromPrimary;
|
|
141
|
+
return fallback ? getValueAtPath(fallback, tail) : undefined;
|
|
142
|
+
}
|
|
143
|
+
return getValueAtPath(workingMemory, trimmed);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Working-memory view for Rendrix / smart-input: preserves all keys but overlays
|
|
147
|
+
* `input` and `inputs` with dual-root merge views (does not rewrite authored paths).
|
|
148
|
+
*/
|
|
149
|
+
function buildMemoryResolutionRootFromWorkingMemory(workingMemory) {
|
|
150
|
+
if (!isPlainObject(workingMemory))
|
|
151
|
+
return {};
|
|
152
|
+
const inputsBag = extractCallerInputsBag(workingMemory);
|
|
153
|
+
const mergedInput = coalesceMergedInputBucket(workingMemory);
|
|
154
|
+
return {
|
|
155
|
+
...workingMemory,
|
|
156
|
+
input: mergeBucketViews(mergedInput, inputsBag),
|
|
157
|
+
inputs: mergeBucketViews(inputsBag, mergedInput)
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* When WM carries `input` and/or `inputs`, return a resolution root for template rendering.
|
|
162
|
+
* Otherwise returns the original reference unchanged.
|
|
163
|
+
*/
|
|
164
|
+
function prepareWorkingMemoryForTemplateRender(workingMemory) {
|
|
165
|
+
if (!isPlainObject(workingMemory))
|
|
166
|
+
return workingMemory;
|
|
167
|
+
if (workingMemory.input === undefined && workingMemory.inputs === undefined) {
|
|
168
|
+
return workingMemory;
|
|
169
|
+
}
|
|
170
|
+
return buildMemoryResolutionRootFromWorkingMemory(workingMemory);
|
|
171
|
+
}
|
|
172
|
+
/** Optional migration: rewrite `inputs.*` smart-input / memory paths to `input.*`. */
|
|
173
|
+
function mapSmartInputPathsInputsToInput(paths) {
|
|
174
|
+
return paths.map((p) => {
|
|
175
|
+
const t = p.trim();
|
|
176
|
+
if (t === 'inputs')
|
|
177
|
+
return 'input';
|
|
178
|
+
if (t.startsWith('inputs.'))
|
|
179
|
+
return `input.${t.slice('inputs.'.length)}`;
|
|
180
|
+
return p;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dual memory roots `input` (merged MAIN payload) and `inputs` (caller / graph-entry bag).
|
|
3
|
+
* Aligned with @exellix/graph-engine ≥ 5.5.0 resolution rules for template / smart-input paths.
|
|
4
|
+
*/
|
|
5
|
+
export declare const GATEWAY_DUAL_MEMORY_ROOTS: readonly ["input", "inputs"];
|
|
6
|
+
export type GatewayDualMemoryRoot = (typeof GATEWAY_DUAL_MEMORY_ROOTS)[number];
|
|
7
|
+
/**
|
|
8
|
+
* Parse JSON object shapes from strings (matches graph-engine `parseLooseJsonObject`).
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseLooseJsonObject(value: unknown): Record<string, unknown> | undefined;
|
|
11
|
+
/** Caller / graph-entry bag from `workingMemory.inputs`. */
|
|
12
|
+
export declare function extractCallerInputsBag(workingMemory: unknown): Record<string, unknown> | undefined;
|
|
13
|
+
/** Merged MAIN bucket from `workingMemory.input` (object or parsed JSON string). */
|
|
14
|
+
export declare function coalesceMergedInputBucket(workingMemory: unknown): unknown;
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a dotted path against working memory with dual-root rules:
|
|
17
|
+
* - `inputs` / `inputs.*` → caller bag first, then merged `input`
|
|
18
|
+
* - `input` / `input.*` → merged `input` first, then caller `inputs`
|
|
19
|
+
* - other paths → direct lookup on working memory
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveGatewayMemoryPathValue(workingMemory: unknown, path: string): unknown;
|
|
22
|
+
/**
|
|
23
|
+
* Working-memory view for Rendrix / smart-input: preserves all keys but overlays
|
|
24
|
+
* `input` and `inputs` with dual-root merge views (does not rewrite authored paths).
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildMemoryResolutionRootFromWorkingMemory(workingMemory: unknown): Record<string, unknown>;
|
|
27
|
+
/**
|
|
28
|
+
* When WM carries `input` and/or `inputs`, return a resolution root for template rendering.
|
|
29
|
+
* Otherwise returns the original reference unchanged.
|
|
30
|
+
*/
|
|
31
|
+
export declare function prepareWorkingMemoryForTemplateRender(workingMemory: unknown): unknown;
|
|
32
|
+
/** Optional migration: rewrite `inputs.*` smart-input / memory paths to `input.*`. */
|
|
33
|
+
export declare function mapSmartInputPathsInputsToInput(paths: string[]): string[];
|