@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.
- package/README.md +45 -0
- package/dist/ai-tools-client.d.ts +20 -0
- package/dist/ai-tools-client.js +91 -0
- package/dist/gateway-config.d.ts +2 -0
- package/dist/gateway-config.js +2 -1
- package/dist/gateway-mode.d.ts +40 -0
- package/dist/gateway-mode.js +75 -0
- package/dist/gateway-utils.d.ts +28 -1
- package/dist/gateway-utils.js +137 -12
- package/dist/gateway.d.ts +3 -0
- package/dist/gateway.js +29 -5
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/types.d.ts +21 -0
- package/dist-cjs/activity-manager.cjs +14 -19
- package/dist-cjs/ai-tools-client.cjs +91 -0
- package/dist-cjs/ai-tools-client.d.ts +20 -0
- package/dist-cjs/config/activity-tracking-config.cjs +1 -4
- package/dist-cjs/content-normalizer/content-normalizer.cjs +3 -8
- package/dist-cjs/content-normalizer/index.cjs +1 -7
- package/dist-cjs/content-normalizer/types.cjs +1 -2
- package/dist-cjs/flex-md-loader.cjs +20 -67
- package/dist-cjs/gateway-config.cjs +25 -63
- package/dist-cjs/gateway-config.d.ts +2 -0
- package/dist-cjs/gateway-conversion.cjs +10 -48
- package/dist-cjs/gateway-instructions.cjs +5 -10
- package/dist-cjs/gateway-log-meta.cjs +9 -14
- package/dist-cjs/gateway-memory.cjs +2 -6
- package/dist-cjs/gateway-messages.cjs +3 -6
- package/dist-cjs/gateway-meta.cjs +1 -4
- package/dist-cjs/gateway-mode.cjs +75 -0
- package/dist-cjs/gateway-mode.d.ts +40 -0
- package/dist-cjs/gateway-provider-auto-register.cjs +2 -38
- package/dist-cjs/gateway-provider.cjs +10 -22
- package/dist-cjs/gateway-rate-limiter-constants.cjs +2 -5
- package/dist-cjs/gateway-rate-limiter.cjs +5 -9
- package/dist-cjs/gateway-retry.cjs +6 -14
- package/dist-cjs/gateway-utils.cjs +160 -89
- package/dist-cjs/gateway-utils.d.ts +28 -1
- package/dist-cjs/gateway-validation.cjs +2 -6
- package/dist-cjs/gateway.cjs +86 -66
- package/dist-cjs/gateway.d.ts +3 -0
- package/dist-cjs/index.cjs +22 -98
- package/dist-cjs/index.d.ts +3 -1
- package/dist-cjs/instruction-errors.cjs +2 -7
- package/dist-cjs/instruction-optimizer.cjs +4 -10
- package/dist-cjs/instructions-parser.cjs +5 -10
- package/dist-cjs/logger-factory.cjs +3 -6
- package/dist-cjs/memory-path-resolution.cjs +8 -18
- package/dist-cjs/message-builder.cjs +11 -47
- package/dist-cjs/object-types-library-integration.cjs +3 -8
- package/dist-cjs/object-types-library.cjs +5 -10
- package/dist-cjs/output-auditor.cjs +1 -4
- package/dist-cjs/output-contract-normalizer.cjs +9 -14
- package/dist-cjs/request-report-generator.cjs +1 -4
- package/dist-cjs/response-analyzer/format-type-detector.cjs +1 -5
- package/dist-cjs/response-analyzer/index.cjs +3 -9
- package/dist-cjs/response-analyzer/object-type-detector.cjs +1 -5
- package/dist-cjs/response-analyzer/response-analyzer.cjs +6 -10
- package/dist-cjs/response-analyzer/types.cjs +1 -2
- package/dist-cjs/response-fallback-fixer.cjs +1 -4
- package/dist-cjs/runtime-objects.cjs +7 -13
- package/dist-cjs/template-parser.cjs +5 -42
- package/dist-cjs/template-render-merge.cjs +2 -6
- package/dist-cjs/troubleshooting-helper.cjs +13 -28
- package/dist-cjs/types.cjs +1 -2
- package/dist-cjs/types.d.ts +21 -0
- package/dist-cjs/usage-tracker.cjs +3 -7
- package/package.json +11 -5
package/dist/index.d.ts
CHANGED
|
@@ -17,7 +17,9 @@ 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, resolveActivityCostCompletion, resolveCostCompletionForActivity, hasNonZeroTokenUsage } from './gateway-utils.js';
|
|
20
|
+
export { attachGatewayInvokeRejectionMetadata, buildInvokeRejectionMetadata, tryExtractRouterLikePayloadFromErrorChain, pickRequestIdsFromRouterLike, resolveActivityCostCompletion, resolveCostCompletionForActivity, resolveCostCompletionWithAiTools, hasNonZeroTokenUsage } from './gateway-utils.js';
|
|
21
|
+
export { getGatewayOperationalMode, isProdGatewayMode, resolveGatewayDefaultModel, parseModelProviderSpec, CODE_DEFAULT_MODEL } from './gateway-mode.js';
|
|
22
|
+
export type { GatewayOperationalMode, GatewayDefaultModelSource, DefaultModelSubstitutionReason, ResolvedGatewayDefault } from './gateway-mode.js';
|
|
21
23
|
export type { ActivityCostStatus, ResolvedActivityCost } from './gateway-utils.js';
|
|
22
24
|
export { contractSpecToFieldKeys, enrichParsedContentForOutputContract, resolveOutputContractFieldKeys } from './output-contract-normalizer.js';
|
|
23
25
|
export type { OutputContractSpec } from './output-contract-normalizer.js';
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,8 @@ export * from '@x12i/ai-providers-router';
|
|
|
17
17
|
export { AIGateway } from './gateway.js';
|
|
18
18
|
export { InstructionNotFoundError, InstructionBackendError } from './instruction-errors.js';
|
|
19
19
|
export { autoRegisterProviders } from './gateway-provider-auto-register.js';
|
|
20
|
-
export { attachGatewayInvokeRejectionMetadata, buildInvokeRejectionMetadata, tryExtractRouterLikePayloadFromErrorChain, pickRequestIdsFromRouterLike, resolveActivityCostCompletion, resolveCostCompletionForActivity, hasNonZeroTokenUsage } from './gateway-utils.js';
|
|
20
|
+
export { attachGatewayInvokeRejectionMetadata, buildInvokeRejectionMetadata, tryExtractRouterLikePayloadFromErrorChain, pickRequestIdsFromRouterLike, resolveActivityCostCompletion, resolveCostCompletionForActivity, resolveCostCompletionWithAiTools, hasNonZeroTokenUsage } from './gateway-utils.js';
|
|
21
|
+
export { getGatewayOperationalMode, isProdGatewayMode, resolveGatewayDefaultModel, parseModelProviderSpec, CODE_DEFAULT_MODEL } from './gateway-mode.js';
|
|
21
22
|
export { contractSpecToFieldKeys, enrichParsedContentForOutputContract, resolveOutputContractFieldKeys } from './output-contract-normalizer.js';
|
|
22
23
|
export { mergeGatewayAndRequestTemplateRenderOptions, mergeTemplateRenderOptions } from './template-render-merge.js';
|
|
23
24
|
export { GATEWAY_DUAL_MEMORY_ROOTS, buildMemoryResolutionRootFromWorkingMemory, coalesceMergedInputBucket, extractCallerInputsBag, mapSmartInputPathsInputsToInput, parseLooseJsonObject, prepareWorkingMemoryForTemplateRender, resolveGatewayMemoryPathValue } from './memory-path-resolution.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -340,6 +340,27 @@ export interface GatewayConfig extends Omit<RouterConfig, 'defaultEngine' | 'log
|
|
|
340
340
|
openRouter?: {
|
|
341
341
|
enabled?: boolean;
|
|
342
342
|
};
|
|
343
|
+
/**
|
|
344
|
+
* Operational mode override (`process.env.mode` / `MODE` when omitted).
|
|
345
|
+
* - `prod`: unresolved models fall back to {@link AI_GATEWAY_DEFAULT_MODEL} / packaged default (with Logxer warn).
|
|
346
|
+
* - `dev` / `debug`: unresolved models throw {@link ModelResolutionError} from `@x12i/ai-tools`.
|
|
347
|
+
*/
|
|
348
|
+
mode?: 'dev' | 'debug' | 'prod';
|
|
349
|
+
/**
|
|
350
|
+
* @x12i/ai-tools integration: catalog model resolution (request) and cost calculation (response).
|
|
351
|
+
*/
|
|
352
|
+
aiTools?: {
|
|
353
|
+
/** @default true */
|
|
354
|
+
enabled?: boolean;
|
|
355
|
+
/** Inject Catalox; otherwise `createCataloxFromEnv()` from `@x12i/catalox/firebase`. */
|
|
356
|
+
catalox?: import('@x12i/catalox').Catalox;
|
|
357
|
+
cacheTtlMs?: number;
|
|
358
|
+
/** @default true */
|
|
359
|
+
resolveModels?: boolean;
|
|
360
|
+
/** @default true */
|
|
361
|
+
calculateCost?: boolean;
|
|
362
|
+
costIncludeBreakdown?: boolean;
|
|
363
|
+
};
|
|
343
364
|
/**
|
|
344
365
|
* InstructionsBlocks overrides
|
|
345
366
|
* Key: block name, Value: block content
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Activity Manager
|
|
4
3
|
*
|
|
5
4
|
* Manages activity tracking for LLM requests.
|
|
6
5
|
* Wraps the ActivityTracker and provides convenience methods.
|
|
7
6
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const activix_1 = require("@x12i/activix");
|
|
12
|
-
const activity_tracking_config_js_1 = require("./config/activity-tracking-config.cjs");
|
|
13
|
-
const gateway_log_meta_js_1 = require("./gateway-log-meta.cjs");
|
|
7
|
+
import { Activix, activixActivityIo, activixOuterTier, resolveActivixLogsDatabaseName, resolveActivixMongoUriFromEnv } from '@x12i/activix';
|
|
8
|
+
import { resolveActivityTrackingConfig } from './config/activity-tracking-config.js';
|
|
9
|
+
import { gatewayLogDebug, withActivityIdentity } from './gateway-log-meta.js';
|
|
14
10
|
function readAiRequestIdFromRequest(request) {
|
|
15
11
|
const aiRequestId = request.aiRequestId;
|
|
16
12
|
if (typeof aiRequestId === 'string' && aiRequestId.trim().length > 0) {
|
|
@@ -116,10 +112,10 @@ function resolveSessionIdForRequest(request, incomingIdentity, aiRequestId) {
|
|
|
116
112
|
function logUpstreamIdentityWarnings(logger, incomingIdentity, merged) {
|
|
117
113
|
const aiRequestId = merged.aiRequestId;
|
|
118
114
|
if (!incomingIdentity || typeof incomingIdentity !== 'object') {
|
|
119
|
-
logger?.warn('missingRuntimeIdentityObject',
|
|
115
|
+
logger?.warn('missingRuntimeIdentityObject', withActivityIdentity(merged, {
|
|
120
116
|
message: 'request.identity is missing; upstream must send the mandatory runtime identity object',
|
|
121
117
|
aiRequestId,
|
|
122
|
-
debugKind:
|
|
118
|
+
debugKind: gatewayLogDebug.anomaly
|
|
123
119
|
}));
|
|
124
120
|
return;
|
|
125
121
|
}
|
|
@@ -129,11 +125,11 @@ function logUpstreamIdentityWarnings(logger, incomingIdentity, merged) {
|
|
|
129
125
|
if (!trimIdentityString(incomingIdentity.taskId))
|
|
130
126
|
missing.push('taskId');
|
|
131
127
|
if (missing.length > 0) {
|
|
132
|
-
logger?.warn('missingUpstreamIdentityFields',
|
|
128
|
+
logger?.warn('missingUpstreamIdentityFields', withActivityIdentity(merged, {
|
|
133
129
|
message: `Upstream identity is missing required field(s): ${missing.join(', ')}. jobId and taskId must be set on request.identity by the client; the gateway does not generate them.`,
|
|
134
130
|
missingFields: missing,
|
|
135
131
|
aiRequestId,
|
|
136
|
-
debugKind:
|
|
132
|
+
debugKind: gatewayLogDebug.anomaly
|
|
137
133
|
}));
|
|
138
134
|
}
|
|
139
135
|
}
|
|
@@ -218,7 +214,7 @@ function mergeGatewayActivityIdentity(request, aiRequestId, extras) {
|
|
|
218
214
|
*
|
|
219
215
|
* @param logger - Optional Logxer used to WARN when mandatory upstream `identity.jobId` / `identity.taskId` are absent.
|
|
220
216
|
*/
|
|
221
|
-
function ensureGatewayRequestIdentity(request, extras, logger) {
|
|
217
|
+
export function ensureGatewayRequestIdentity(request, extras, logger) {
|
|
222
218
|
const aiRequestId = readAiRequestIdFromRequest(request);
|
|
223
219
|
const identity = mergeGatewayActivityIdentity(request, aiRequestId, {
|
|
224
220
|
...graphIdentityExtrasFromRequest(request),
|
|
@@ -236,12 +232,12 @@ function buildActivixStartIo(aiRequestId, activityType, requestData) {
|
|
|
236
232
|
Object.keys(requestData).length > 0
|
|
237
233
|
? { activityType, request: requestData }
|
|
238
234
|
: { activityType };
|
|
239
|
-
return
|
|
235
|
+
return activixActivityIo(activixOuterTier(input, null, { aiRequestId }));
|
|
240
236
|
}
|
|
241
237
|
/**
|
|
242
238
|
* Manages activity tracking lifecycle
|
|
243
239
|
*/
|
|
244
|
-
class ActivityManager {
|
|
240
|
+
export class ActivityManager {
|
|
245
241
|
activix;
|
|
246
242
|
initPromise;
|
|
247
243
|
mainCollectionName;
|
|
@@ -251,7 +247,7 @@ class ActivityManager {
|
|
|
251
247
|
constructor(config) {
|
|
252
248
|
this.logger = config.logger;
|
|
253
249
|
if (config.enableActivityTracking) {
|
|
254
|
-
const { collectionName, badRequestsCollectionName } =
|
|
250
|
+
const { collectionName, badRequestsCollectionName } = resolveActivityTrackingConfig();
|
|
255
251
|
this.mainCollectionName = collectionName;
|
|
256
252
|
this.badRequestsCollectionName = badRequestsCollectionName;
|
|
257
253
|
try {
|
|
@@ -263,7 +259,7 @@ class ActivityManager {
|
|
|
263
259
|
failed: 'failed',
|
|
264
260
|
timeout: 'timeout'
|
|
265
261
|
};
|
|
266
|
-
this.activix = config.customTracker ?? new
|
|
262
|
+
this.activix = config.customTracker ?? new Activix({
|
|
267
263
|
// Keep mode explicit for operational clarity (matches integration checklist expectations).
|
|
268
264
|
storageMode: 'automatic',
|
|
269
265
|
collections: [
|
|
@@ -312,8 +308,8 @@ class ActivityManager {
|
|
|
312
308
|
return;
|
|
313
309
|
}
|
|
314
310
|
const backend = ax.storageBackend;
|
|
315
|
-
const mongoDb = backend === 'database' ?
|
|
316
|
-
const mongoUriConfigured = Boolean(
|
|
311
|
+
const mongoDb = backend === 'database' ? resolveActivixLogsDatabaseName() : undefined;
|
|
312
|
+
const mongoUriConfigured = Boolean(resolveActivixMongoUriFromEnv());
|
|
317
313
|
this.logger.info('Activity tracking persistence backend ready', {
|
|
318
314
|
storageBackend: backend,
|
|
319
315
|
mongoDatabase: mongoDb,
|
|
@@ -1162,4 +1158,3 @@ class ActivityManager {
|
|
|
1162
1158
|
}
|
|
1163
1159
|
}
|
|
1164
1160
|
}
|
|
1165
|
-
exports.ActivityManager = ActivityManager;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy @x12i/ai-tools catalog + cost calculator bootstrap.
|
|
3
|
+
*/
|
|
4
|
+
import { AiModelsCatalogClient, CostCalculator, ensureAiModelsCatalog } from '@x12i/ai-tools';
|
|
5
|
+
import { gatewayLogDebug, withActivityIdentity } from './gateway-log-meta.js';
|
|
6
|
+
let sharedClientPromise = null;
|
|
7
|
+
let sharedConfigKey;
|
|
8
|
+
let bootstrapFailedLogged = false;
|
|
9
|
+
function configKey(config) {
|
|
10
|
+
const injected = config.aiTools?.catalox ? 'injected' : 'env';
|
|
11
|
+
return `${injected}:${config.aiTools?.cacheTtlMs ?? ''}:${config.aiTools?.costIncludeBreakdown ?? ''}`;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Returns catalog + calculator, or null when disabled or bootstrap fails.
|
|
15
|
+
*/
|
|
16
|
+
export async function getAiToolsClient(config, logger) {
|
|
17
|
+
if (config.aiTools?.enabled === false) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const key = configKey(config);
|
|
21
|
+
if (sharedClientPromise && sharedConfigKey !== key) {
|
|
22
|
+
sharedClientPromise = null;
|
|
23
|
+
}
|
|
24
|
+
sharedConfigKey = key;
|
|
25
|
+
if (!sharedClientPromise) {
|
|
26
|
+
sharedClientPromise = bootstrapAiTools(config, logger);
|
|
27
|
+
}
|
|
28
|
+
return sharedClientPromise;
|
|
29
|
+
}
|
|
30
|
+
/** Reset singleton (tests). */
|
|
31
|
+
export function resetAiToolsClientForTests() {
|
|
32
|
+
sharedClientPromise = null;
|
|
33
|
+
sharedConfigKey = undefined;
|
|
34
|
+
bootstrapFailedLogged = false;
|
|
35
|
+
}
|
|
36
|
+
async function bootstrapAiTools(config, logger) {
|
|
37
|
+
try {
|
|
38
|
+
let catalox = config.aiTools?.catalox;
|
|
39
|
+
if (!catalox) {
|
|
40
|
+
const { createCataloxFromEnv } = await import('@x12i/catalox/firebase');
|
|
41
|
+
const bootstrapped = createCataloxFromEnv();
|
|
42
|
+
catalox = bootstrapped.catalox;
|
|
43
|
+
}
|
|
44
|
+
await ensureAiModelsCatalog(catalox);
|
|
45
|
+
const catalog = new AiModelsCatalogClient({
|
|
46
|
+
catalox,
|
|
47
|
+
cacheTtlMs: config.aiTools?.cacheTtlMs
|
|
48
|
+
});
|
|
49
|
+
const calculator = new CostCalculator(catalog, {
|
|
50
|
+
includeBreakdown: config.aiTools?.costIncludeBreakdown === true
|
|
51
|
+
});
|
|
52
|
+
logger.debug('ai-tools catalog client ready', {
|
|
53
|
+
debugKind: gatewayLogDebug.state
|
|
54
|
+
});
|
|
55
|
+
return { catalog, calculator };
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (!bootstrapFailedLogged) {
|
|
59
|
+
bootstrapFailedLogged = true;
|
|
60
|
+
logger.warn('ai-tools catalog bootstrap failed; model resolution and catalog cost calculation disabled', withActivityIdentity(undefined, {
|
|
61
|
+
error: error instanceof Error ? error.message : String(error),
|
|
62
|
+
debugKind: gatewayLogDebug.anomaly
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Map catalog resolution to router config provider/model fields.
|
|
70
|
+
*/
|
|
71
|
+
export function applyModelResolution(merged, resolution, gatewayDefaultEngine) {
|
|
72
|
+
if (resolution.routedViaOpenRouter) {
|
|
73
|
+
merged.provider = 'openrouter';
|
|
74
|
+
merged.model = resolution.modelId;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const slash = resolution.modelId.indexOf('/');
|
|
78
|
+
if (slash > 0) {
|
|
79
|
+
merged.provider = resolution.record?.providerId ?? resolution.modelId.slice(0, slash);
|
|
80
|
+
merged.model = resolution.modelId.slice(slash + 1);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
merged.model = resolution.modelId;
|
|
84
|
+
if (resolution.record?.providerId) {
|
|
85
|
+
merged.provider = resolution.record.providerId;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (!merged.provider && gatewayDefaultEngine) {
|
|
89
|
+
merged.provider = gatewayDefaultEngine;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy @x12i/ai-tools catalog + cost calculator bootstrap.
|
|
3
|
+
*/
|
|
4
|
+
import { AiModelsCatalogClient, CostCalculator, type ModelResolutionSuccess } from '@x12i/ai-tools';
|
|
5
|
+
import type { Logxer } from '@x12i/logxer';
|
|
6
|
+
import type { ChatRequest, GatewayConfig } from './types.js';
|
|
7
|
+
export type AiToolsClientBundle = {
|
|
8
|
+
catalog: AiModelsCatalogClient;
|
|
9
|
+
calculator: CostCalculator;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Returns catalog + calculator, or null when disabled or bootstrap fails.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getAiToolsClient(config: GatewayConfig, logger: Logxer): Promise<AiToolsClientBundle | null>;
|
|
15
|
+
/** Reset singleton (tests). */
|
|
16
|
+
export declare function resetAiToolsClientForTests(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Map catalog resolution to router config provider/model fields.
|
|
19
|
+
*/
|
|
20
|
+
export declare function applyModelResolution(merged: NonNullable<ChatRequest['config']>, resolution: ModelResolutionSuccess, gatewayDefaultEngine?: string): void;
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Centralized activity tracking configuration.
|
|
4
3
|
* Package-level Mongo collection names are fixed literals here (no env override).
|
|
5
4
|
* Main gateway rows: `ai-actions`; bad requests: `bad-requests` (see constants below).
|
|
6
5
|
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.resolveActivityTrackingConfig = resolveActivityTrackingConfig;
|
|
9
6
|
const ACTIVITY_COLLECTION_NAME = 'ai-actions';
|
|
10
7
|
const BAD_REQUESTS_COLLECTION_NAME = 'bad-requests';
|
|
11
|
-
function resolveActivityTrackingConfig() {
|
|
8
|
+
export function resolveActivityTrackingConfig() {
|
|
12
9
|
// Collection names are intentionally hardcoded at package level.
|
|
13
10
|
return {
|
|
14
11
|
mongoUri: '',
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Content Normalizer
|
|
4
3
|
*
|
|
@@ -6,10 +5,6 @@
|
|
|
6
5
|
* Fixes the "[object Object]" bug by properly handling objects.
|
|
7
6
|
* Preserves both rawText and parsedContent for downstream consumers.
|
|
8
7
|
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.normalizeContent = normalizeContent;
|
|
11
|
-
exports.isEmptyContent = isEmptyContent;
|
|
12
|
-
exports.getResponseDiagnostics = getResponseDiagnostics;
|
|
13
8
|
/**
|
|
14
9
|
* Extracts content from router response, checking multiple possible locations
|
|
15
10
|
*
|
|
@@ -187,7 +182,7 @@ function determineContentType(value, parsedContent) {
|
|
|
187
182
|
* @param response - Router response object
|
|
188
183
|
* @returns Normalized content with metadata
|
|
189
184
|
*/
|
|
190
|
-
function normalizeContent(response, logger) {
|
|
185
|
+
export function normalizeContent(response, logger) {
|
|
191
186
|
// Extract content value from response
|
|
192
187
|
const contentValue = extractContentValue(response);
|
|
193
188
|
// CRITICAL: Check if router already converted object to "[object Object]" string
|
|
@@ -375,7 +370,7 @@ function normalizeContent(response, logger) {
|
|
|
375
370
|
* @param normalized - Normalized content result
|
|
376
371
|
* @returns True if content is empty
|
|
377
372
|
*/
|
|
378
|
-
function isEmptyContent(normalized) {
|
|
373
|
+
export function isEmptyContent(normalized) {
|
|
379
374
|
return !normalized.content || normalized.content.trim().length === 0;
|
|
380
375
|
}
|
|
381
376
|
/**
|
|
@@ -385,7 +380,7 @@ function isEmptyContent(normalized) {
|
|
|
385
380
|
* @param response - Router response object
|
|
386
381
|
* @returns Diagnostic information
|
|
387
382
|
*/
|
|
388
|
-
function getResponseDiagnostics(response) {
|
|
383
|
+
export function getResponseDiagnostics(response) {
|
|
389
384
|
return {
|
|
390
385
|
responseKeys: Object.keys(response),
|
|
391
386
|
hasMessage: !!(response?.message),
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* Content Normalizer Module
|
|
4
3
|
*
|
|
5
4
|
* Exports all public APIs for content normalization
|
|
6
5
|
*/
|
|
7
|
-
|
|
8
|
-
exports.getResponseDiagnostics = exports.isEmptyContent = exports.normalizeContent = void 0;
|
|
9
|
-
var content_normalizer_js_1 = require("./content-normalizer.cjs");
|
|
10
|
-
Object.defineProperty(exports, "normalizeContent", { enumerable: true, get: function () { return content_normalizer_js_1.normalizeContent; } });
|
|
11
|
-
Object.defineProperty(exports, "isEmptyContent", { enumerable: true, get: function () { return content_normalizer_js_1.isEmptyContent; } });
|
|
12
|
-
Object.defineProperty(exports, "getResponseDiagnostics", { enumerable: true, get: function () { return content_normalizer_js_1.getResponseDiagnostics; } });
|
|
6
|
+
export { normalizeContent, isEmptyContent, getResponseDiagnostics } from './content-normalizer.js';
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* @x12i/flex-md Loader
|
|
4
3
|
*
|
|
@@ -14,55 +13,9 @@
|
|
|
14
13
|
* - Native output format support: Extracts and uses flex-md native output formats from instructions
|
|
15
14
|
* based on compliance level when no explicit format is provided
|
|
16
15
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
-
}
|
|
23
|
-
Object.defineProperty(o, k2, desc);
|
|
24
|
-
}) : (function(o, m, k, k2) {
|
|
25
|
-
if (k2 === undefined) k2 = k;
|
|
26
|
-
o[k2] = m[k];
|
|
27
|
-
}));
|
|
28
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
-
}) : function(o, v) {
|
|
31
|
-
o["default"] = v;
|
|
32
|
-
});
|
|
33
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
-
var ownKeys = function(o) {
|
|
35
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
-
var ar = [];
|
|
37
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
-
return ar;
|
|
39
|
-
};
|
|
40
|
-
return ownKeys(o);
|
|
41
|
-
};
|
|
42
|
-
return function (mod) {
|
|
43
|
-
if (mod && mod.__esModule) return mod;
|
|
44
|
-
var result = {};
|
|
45
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
-
__setModuleDefault(result, mod);
|
|
47
|
-
return result;
|
|
48
|
-
};
|
|
49
|
-
})();
|
|
50
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
-
exports.loadFlexMd = loadFlexMd;
|
|
52
|
-
exports.extractJsonFromFlexMd = extractJsonFromFlexMd;
|
|
53
|
-
exports.parseMarkdownSectionsFromContent = parseMarkdownSectionsFromContent;
|
|
54
|
-
exports.isFlexMdAvailable = isFlexMdAvailable;
|
|
55
|
-
exports.getModelMaxTokensFromFlexMd = getModelMaxTokensFromFlexMd;
|
|
56
|
-
exports.getFlexMdModule = getFlexMdModule;
|
|
57
|
-
exports.buildDynamicInstructions = buildDynamicInstructions;
|
|
58
|
-
exports.enrichInstructionsWithFlexMd = enrichInstructionsWithFlexMd;
|
|
59
|
-
exports.getStrictnessDefaults = getStrictnessDefaults;
|
|
60
|
-
exports.enforceFlexMdFormat = enforceFlexMdFormat;
|
|
61
|
-
exports.hasFlexMdContract = hasFlexMdContract;
|
|
62
|
-
exports.detectComplianceLevel = detectComplianceLevel;
|
|
63
|
-
const path = __importStar(require("path"));
|
|
64
|
-
const url_1 = require("url");
|
|
65
|
-
const logxer_1 = require("@x12i/logxer");
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
import { pathToFileURL } from 'url';
|
|
18
|
+
import { DebugLogAbstract } from '@x12i/logxer';
|
|
66
19
|
let flexMdModule = null;
|
|
67
20
|
let flexMdLoadError = null;
|
|
68
21
|
let flexMdLoading = null;
|
|
@@ -79,7 +32,7 @@ async function importFlexMdModule() {
|
|
|
79
32
|
const { createRequire } = await importModule('module');
|
|
80
33
|
const requireFn = typeof require === 'function' ? require : createRequire(path.join(process.cwd(), 'noop.cjs'));
|
|
81
34
|
const cjsEntryPath = requireFn.resolve('@x12i/flex-md');
|
|
82
|
-
const cjsEntryUrl =
|
|
35
|
+
const cjsEntryUrl = pathToFileURL(cjsEntryPath).href;
|
|
83
36
|
try {
|
|
84
37
|
return await importModule(cjsEntryUrl);
|
|
85
38
|
}
|
|
@@ -97,7 +50,7 @@ async function importFlexMdModule() {
|
|
|
97
50
|
* Load flex-md module (ES Module) asynchronously
|
|
98
51
|
* Caches the result to avoid multiple imports
|
|
99
52
|
*/
|
|
100
|
-
async function loadFlexMd() {
|
|
53
|
+
export async function loadFlexMd() {
|
|
101
54
|
// Return cached module if available
|
|
102
55
|
if (flexMdModule) {
|
|
103
56
|
return flexMdModule;
|
|
@@ -376,7 +329,7 @@ async function extractFlexMdOutputFormatFromInstructions(instructions, complianc
|
|
|
376
329
|
* - Other flex-md options
|
|
377
330
|
* @returns Parsed JSON object and method used, or null if parsing fails
|
|
378
331
|
*/
|
|
379
|
-
async function extractJsonFromFlexMd(content, logger) {
|
|
332
|
+
export async function extractJsonFromFlexMd(content, logger) {
|
|
380
333
|
// ARCHITECTURE: ai-gateway layer only handles unstructured parsing
|
|
381
334
|
// Schema-driven parsing is handled at skills layer with nx-md-parser
|
|
382
335
|
// No schema parameter - this layer doesn't know about schemas
|
|
@@ -406,8 +359,8 @@ async function extractJsonFromFlexMd(content, logger) {
|
|
|
406
359
|
if (result && typeof result === 'object' && result !== null) {
|
|
407
360
|
const json = result.json || result.data || result.result || result;
|
|
408
361
|
if (json && typeof json === 'object' && json !== null) {
|
|
409
|
-
logger?.debug('extractJsonFromFlexMd: using extractFromMarkdown', { debugKind:
|
|
410
|
-
logger?.debug('extractJsonFromFlexMd: parsed json', { json, debugKind:
|
|
362
|
+
logger?.debug('extractJsonFromFlexMd: using extractFromMarkdown', { debugKind: DebugLogAbstract.TRACE });
|
|
363
|
+
logger?.debug('extractJsonFromFlexMd: parsed json', { json, debugKind: DebugLogAbstract.STATE });
|
|
411
364
|
return { json, method: 'extractFromMarkdown' };
|
|
412
365
|
}
|
|
413
366
|
}
|
|
@@ -531,11 +484,11 @@ function fallbackMarkdownParser(content, logger) {
|
|
|
531
484
|
result[key] = parseMarkdownList(currentContent);
|
|
532
485
|
detectedHeaders.push(key);
|
|
533
486
|
}
|
|
534
|
-
logger?.debug('Fallback parser detected headers', { detectedHeaders, debugKind:
|
|
487
|
+
logger?.debug('Fallback parser detected headers', { detectedHeaders, debugKind: DebugLogAbstract.STATE });
|
|
535
488
|
const expectedHeaders = ['shortAnswer', 'fullAnswer', 'assumptions', 'unknowns', 'evidence'];
|
|
536
489
|
const missingHeaders = expectedHeaders.filter(h => !detectedHeaders.includes(h));
|
|
537
490
|
if (missingHeaders.length > 0) {
|
|
538
|
-
logger?.debug('Fallback parser missing expected headers', { missingHeaders, debugKind:
|
|
491
|
+
logger?.debug('Fallback parser missing expected headers', { missingHeaders, debugKind: DebugLogAbstract.STATE });
|
|
539
492
|
}
|
|
540
493
|
// If we extracted some structure, return it
|
|
541
494
|
if (Object.keys(result).length > 0) {
|
|
@@ -554,7 +507,7 @@ function fallbackMarkdownParser(content, logger) {
|
|
|
554
507
|
* Section-based markdown → camelCase field map (e.g. `### Short Answer` → `shortAnswer`).
|
|
555
508
|
* Used when output contracts need structured `parsed` fields but flex-md returned only `rawText`.
|
|
556
509
|
*/
|
|
557
|
-
function parseMarkdownSectionsFromContent(content, logger) {
|
|
510
|
+
export function parseMarkdownSectionsFromContent(content, logger) {
|
|
558
511
|
const parsed = fallbackMarkdownParser(content, logger);
|
|
559
512
|
const json = parsed.json;
|
|
560
513
|
if (json != null && typeof json === 'object' && !Array.isArray(json)) {
|
|
@@ -597,7 +550,7 @@ function extractJsonFallback(content) {
|
|
|
597
550
|
/**
|
|
598
551
|
* Check if flex-md module is available
|
|
599
552
|
*/
|
|
600
|
-
function isFlexMdAvailable() {
|
|
553
|
+
export function isFlexMdAvailable() {
|
|
601
554
|
return flexMdModule !== null;
|
|
602
555
|
}
|
|
603
556
|
/**
|
|
@@ -608,7 +561,7 @@ function isFlexMdAvailable() {
|
|
|
608
561
|
* @param model - Model name (e.g., 'gpt-4', 'claude-3-opus')
|
|
609
562
|
* @returns maxTokens if found, null otherwise
|
|
610
563
|
*/
|
|
611
|
-
async function getModelMaxTokensFromFlexMd(provider, model) {
|
|
564
|
+
export async function getModelMaxTokensFromFlexMd(provider, model) {
|
|
612
565
|
try {
|
|
613
566
|
const flexMd = await loadFlexMd();
|
|
614
567
|
if (!flexMd || typeof flexMd !== 'object') {
|
|
@@ -687,7 +640,7 @@ async function getModelMaxTokensFromFlexMd(provider, model) {
|
|
|
687
640
|
/**
|
|
688
641
|
* Get flex-md module directly (must call loadFlexMd() first)
|
|
689
642
|
*/
|
|
690
|
-
function getFlexMdModule() {
|
|
643
|
+
export function getFlexMdModule() {
|
|
691
644
|
if (!flexMdModule) {
|
|
692
645
|
throw new Error('flex-md module not loaded. Call loadFlexMd() first.');
|
|
693
646
|
}
|
|
@@ -754,7 +707,7 @@ function generateFormatInstructionsFromSchema(schema, options) {
|
|
|
754
707
|
parts.push('\n\nIMPORTANT: Return your answer as JSON inside the markdown fenced block. The JSON must match the schema above exactly.');
|
|
755
708
|
return parts.join('\n');
|
|
756
709
|
}
|
|
757
|
-
async function buildDynamicInstructions(schemaObject, options) {
|
|
710
|
+
export async function buildDynamicInstructions(schemaObject, options) {
|
|
758
711
|
try {
|
|
759
712
|
const flexMd = await loadFlexMd();
|
|
760
713
|
// Check if dynamic instruction feature is available (flex-md 3.1+)
|
|
@@ -786,7 +739,7 @@ async function buildDynamicInstructions(schemaObject, options) {
|
|
|
786
739
|
* @param strictnessLevel - Compliance level ('L0' | 'L1' | 'L2' | 'L3')
|
|
787
740
|
* @returns Enriched instructions with flex-md guidance
|
|
788
741
|
*/
|
|
789
|
-
async function enrichInstructionsWithFlexMd(instructions, strictnessLevel = 'L0') {
|
|
742
|
+
export async function enrichInstructionsWithFlexMd(instructions, strictnessLevel = 'L0') {
|
|
790
743
|
try {
|
|
791
744
|
const flexMd = await loadFlexMd();
|
|
792
745
|
// Use native flex-md function if available (flex-md 3.2+)
|
|
@@ -814,7 +767,7 @@ async function enrichInstructionsWithFlexMd(instructions, strictnessLevel = 'L0'
|
|
|
814
767
|
* @param strictnessLevel - Compliance level ('L0' | 'L1' | 'L2' | 'L3')
|
|
815
768
|
* @returns Configuration object with level-specific defaults
|
|
816
769
|
*/
|
|
817
|
-
async function getStrictnessDefaults(strictnessLevel = 'L0') {
|
|
770
|
+
export async function getStrictnessDefaults(strictnessLevel = 'L0') {
|
|
818
771
|
try {
|
|
819
772
|
const flexMd = await loadFlexMd();
|
|
820
773
|
if (flexMd.strictnessDefaults && typeof flexMd.strictnessDefaults === 'function') {
|
|
@@ -835,7 +788,7 @@ async function getStrictnessDefaults(strictnessLevel = 'L0') {
|
|
|
835
788
|
* @param strictnessLevel - Compliance level ('L0' | 'L1' | 'L2' | 'L3')
|
|
836
789
|
* @returns Instructions with flex-md enforcement rules
|
|
837
790
|
*/
|
|
838
|
-
async function enforceFlexMdFormat(instructions, outputFormatSpec, strictnessLevel = 'L0') {
|
|
791
|
+
export async function enforceFlexMdFormat(instructions, outputFormatSpec, strictnessLevel = 'L0') {
|
|
839
792
|
try {
|
|
840
793
|
const flexMd = await loadFlexMd();
|
|
841
794
|
if (flexMd.enforceFlexMd && typeof flexMd.enforceFlexMd === 'function') {
|
|
@@ -861,7 +814,7 @@ async function enforceFlexMdFormat(instructions, outputFormatSpec, strictnessLev
|
|
|
861
814
|
* @param complianceLevel - Required compliance level
|
|
862
815
|
* @returns true if instructions meet the compliance level
|
|
863
816
|
*/
|
|
864
|
-
async function hasFlexMdContract(instructions, complianceLevel = 'L0') {
|
|
817
|
+
export async function hasFlexMdContract(instructions, complianceLevel = 'L0') {
|
|
865
818
|
if (!instructions || instructions.trim() === '') {
|
|
866
819
|
return false;
|
|
867
820
|
}
|
|
@@ -929,7 +882,7 @@ async function hasFlexMdContract(instructions, complianceLevel = 'L0') {
|
|
|
929
882
|
* @param instructions - Instructions text to check
|
|
930
883
|
* @returns The highest compliance level met ('L0' | 'L1' | 'L2' | 'L3' | null if none)
|
|
931
884
|
*/
|
|
932
|
-
async function detectComplianceLevel(instructions) {
|
|
885
|
+
export async function detectComplianceLevel(instructions) {
|
|
933
886
|
if (!instructions || instructions.trim() === '') {
|
|
934
887
|
return null;
|
|
935
888
|
}
|