@x12i/ai-gateway 7.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4259 -0
- package/config.defaults.json +31 -0
- package/dist/activity-manager.d.ts +206 -0
- package/dist/activity-manager.js +1051 -0
- package/dist/config/activity-tracking-config.d.ts +11 -0
- package/dist/config/activity-tracking-config.js +15 -0
- package/dist/config.defaults.json +31 -0
- package/dist/content-normalizer/content-normalizer.d.ts +46 -0
- package/dist/content-normalizer/content-normalizer.js +393 -0
- package/dist/content-normalizer/index.d.ts +7 -0
- package/dist/content-normalizer/index.js +6 -0
- package/dist/content-normalizer/types.d.ts +33 -0
- package/dist/content-normalizer/types.js +4 -0
- package/dist/defaults/instructions-blocks.json +61 -0
- package/dist/defaults/model-config.json +16 -0
- package/dist/defaults/template-rendering.json +6 -0
- package/dist/flex-md-loader.d.ts +109 -0
- package/dist/flex-md-loader.js +940 -0
- package/dist/gateway-config.d.ts +49 -0
- package/dist/gateway-config.js +292 -0
- package/dist/gateway-conversion.d.ts +29 -0
- package/dist/gateway-conversion.js +174 -0
- package/dist/gateway-instructions.d.ts +30 -0
- package/dist/gateway-instructions.js +62 -0
- package/dist/gateway-memory.d.ts +51 -0
- package/dist/gateway-memory.js +207 -0
- package/dist/gateway-messages.d.ts +23 -0
- package/dist/gateway-messages.js +83 -0
- package/dist/gateway-meta.d.ts +25 -0
- package/dist/gateway-meta.js +87 -0
- package/dist/gateway-provider-auto-register.d.ts +17 -0
- package/dist/gateway-provider-auto-register.js +159 -0
- package/dist/gateway-provider.d.ts +54 -0
- package/dist/gateway-provider.js +202 -0
- package/dist/gateway-rate-limiter-constants.d.ts +16 -0
- package/dist/gateway-rate-limiter-constants.js +16 -0
- package/dist/gateway-rate-limiter.d.ts +56 -0
- package/dist/gateway-rate-limiter.js +107 -0
- package/dist/gateway-retry.d.ts +49 -0
- package/dist/gateway-retry.js +204 -0
- package/dist/gateway-utils.d.ts +21 -0
- package/dist/gateway-utils.js +181 -0
- package/dist/gateway-validation.d.ts +13 -0
- package/dist/gateway-validation.js +50 -0
- package/dist/gateway.d.ts +39 -0
- package/dist/gateway.js +430 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +55 -0
- package/dist/instruction-errors.d.ts +16 -0
- package/dist/instruction-errors.js +29 -0
- package/dist/instruction-optimizer.d.ts +113 -0
- package/dist/instruction-optimizer.js +293 -0
- package/dist/instructions-parser.d.ts +31 -0
- package/dist/instructions-parser.js +56 -0
- package/dist/logger-factory.d.ts +17 -0
- package/dist/logger-factory.js +42 -0
- package/dist/message-builder.d.ts +41 -0
- package/dist/message-builder.js +522 -0
- package/dist/object-types-library-integration.d.ts +22 -0
- package/dist/object-types-library-integration.js +27 -0
- package/dist/object-types-library.d.ts +351 -0
- package/dist/object-types-library.js +210 -0
- package/dist/output-auditor.d.ts +44 -0
- package/dist/output-auditor.js +49 -0
- package/dist/request-report-generator.d.ts +60 -0
- package/dist/request-report-generator.js +169 -0
- package/dist/response-analyzer/format-type-detector.d.ts +35 -0
- package/dist/response-analyzer/format-type-detector.js +115 -0
- package/dist/response-analyzer/index.d.ts +9 -0
- package/dist/response-analyzer/index.js +8 -0
- package/dist/response-analyzer/object-type-detector.d.ts +42 -0
- package/dist/response-analyzer/object-type-detector.js +95 -0
- package/dist/response-analyzer/response-analyzer.d.ts +38 -0
- package/dist/response-analyzer/response-analyzer.js +97 -0
- package/dist/response-analyzer/types.d.ts +97 -0
- package/dist/response-analyzer/types.js +4 -0
- package/dist/response-fallback-fixer.d.ts +11 -0
- package/dist/response-fallback-fixer.js +123 -0
- package/dist/runtime-objects.d.ts +52 -0
- package/dist/runtime-objects.js +46 -0
- package/dist/template-parser.d.ts +58 -0
- package/dist/template-parser.js +99 -0
- package/dist/template-render-merge.d.ts +9 -0
- package/dist/template-render-merge.js +40 -0
- package/dist/troubleshooting-helper.d.ts +123 -0
- package/dist/troubleshooting-helper.js +596 -0
- package/dist/types.d.ts +1173 -0
- package/dist/types.js +6 -0
- package/dist/usage-tracker.d.ts +78 -0
- package/dist/usage-tracker.js +79 -0
- package/dist-cjs/activity-manager.cjs +1056 -0
- package/dist-cjs/activity-manager.d.ts +206 -0
- package/dist-cjs/config/activity-tracking-config.cjs +18 -0
- package/dist-cjs/config/activity-tracking-config.d.ts +11 -0
- package/dist-cjs/config.defaults.json +31 -0
- package/dist-cjs/content-normalizer/content-normalizer.cjs +398 -0
- package/dist-cjs/content-normalizer/content-normalizer.d.ts +46 -0
- package/dist-cjs/content-normalizer/index.cjs +12 -0
- package/dist-cjs/content-normalizer/index.d.ts +7 -0
- package/dist-cjs/content-normalizer/types.cjs +5 -0
- package/dist-cjs/content-normalizer/types.d.ts +33 -0
- package/dist-cjs/defaults/instructions-blocks.json +61 -0
- package/dist-cjs/defaults/model-config.json +16 -0
- package/dist-cjs/defaults/template-rendering.json +6 -0
- package/dist-cjs/flex-md-loader.cjs +986 -0
- package/dist-cjs/flex-md-loader.d.ts +109 -0
- package/dist-cjs/gateway-config.cjs +331 -0
- package/dist-cjs/gateway-config.d.ts +49 -0
- package/dist-cjs/gateway-conversion.cjs +212 -0
- package/dist-cjs/gateway-conversion.d.ts +29 -0
- package/dist-cjs/gateway-instructions.cjs +67 -0
- package/dist-cjs/gateway-instructions.d.ts +30 -0
- package/dist-cjs/gateway-memory.cjs +211 -0
- package/dist-cjs/gateway-memory.d.ts +51 -0
- package/dist-cjs/gateway-messages.cjs +86 -0
- package/dist-cjs/gateway-messages.d.ts +23 -0
- package/dist-cjs/gateway-meta.cjs +90 -0
- package/dist-cjs/gateway-meta.d.ts +25 -0
- package/dist-cjs/gateway-provider-auto-register.cjs +195 -0
- package/dist-cjs/gateway-provider-auto-register.d.ts +17 -0
- package/dist-cjs/gateway-provider.cjs +214 -0
- package/dist-cjs/gateway-provider.d.ts +54 -0
- package/dist-cjs/gateway-rate-limiter-constants.cjs +19 -0
- package/dist-cjs/gateway-rate-limiter-constants.d.ts +16 -0
- package/dist-cjs/gateway-rate-limiter.cjs +111 -0
- package/dist-cjs/gateway-rate-limiter.d.ts +56 -0
- package/dist-cjs/gateway-retry.cjs +212 -0
- package/dist-cjs/gateway-retry.d.ts +49 -0
- package/dist-cjs/gateway-utils.cjs +219 -0
- package/dist-cjs/gateway-utils.d.ts +21 -0
- package/dist-cjs/gateway-validation.cjs +54 -0
- package/dist-cjs/gateway-validation.d.ts +13 -0
- package/dist-cjs/gateway.cjs +434 -0
- package/dist-cjs/gateway.d.ts +39 -0
- package/dist-cjs/index.cjs +108 -0
- package/dist-cjs/index.d.ts +36 -0
- package/dist-cjs/instruction-errors.cjs +34 -0
- package/dist-cjs/instruction-errors.d.ts +16 -0
- package/dist-cjs/instruction-optimizer.cjs +299 -0
- package/dist-cjs/instruction-optimizer.d.ts +113 -0
- package/dist-cjs/instructions-parser.cjs +61 -0
- package/dist-cjs/instructions-parser.d.ts +31 -0
- package/dist-cjs/logger-factory.cjs +45 -0
- package/dist-cjs/logger-factory.d.ts +17 -0
- package/dist-cjs/message-builder.cjs +558 -0
- package/dist-cjs/message-builder.d.ts +41 -0
- package/dist-cjs/object-types-library-integration.cjs +32 -0
- package/dist-cjs/object-types-library-integration.d.ts +22 -0
- package/dist-cjs/object-types-library.cjs +215 -0
- package/dist-cjs/object-types-library.d.ts +351 -0
- package/dist-cjs/output-auditor.cjs +52 -0
- package/dist-cjs/output-auditor.d.ts +44 -0
- package/dist-cjs/request-report-generator.cjs +172 -0
- package/dist-cjs/request-report-generator.d.ts +60 -0
- package/dist-cjs/response-analyzer/format-type-detector.cjs +119 -0
- package/dist-cjs/response-analyzer/format-type-detector.d.ts +35 -0
- package/dist-cjs/response-analyzer/index.cjs +14 -0
- package/dist-cjs/response-analyzer/index.d.ts +9 -0
- package/dist-cjs/response-analyzer/object-type-detector.cjs +99 -0
- package/dist-cjs/response-analyzer/object-type-detector.d.ts +42 -0
- package/dist-cjs/response-analyzer/response-analyzer.cjs +101 -0
- package/dist-cjs/response-analyzer/response-analyzer.d.ts +38 -0
- package/dist-cjs/response-analyzer/types.cjs +5 -0
- package/dist-cjs/response-analyzer/types.d.ts +97 -0
- package/dist-cjs/response-fallback-fixer.cjs +126 -0
- package/dist-cjs/response-fallback-fixer.d.ts +11 -0
- package/dist-cjs/runtime-objects.cjs +52 -0
- package/dist-cjs/runtime-objects.d.ts +52 -0
- package/dist-cjs/template-parser.cjs +136 -0
- package/dist-cjs/template-parser.d.ts +58 -0
- package/dist-cjs/template-render-merge.cjs +43 -0
- package/dist-cjs/template-render-merge.d.ts +9 -0
- package/dist-cjs/troubleshooting-helper.cjs +611 -0
- package/dist-cjs/troubleshooting-helper.d.ts +123 -0
- package/dist-cjs/types.cjs +7 -0
- package/dist-cjs/types.d.ts +1173 -0
- package/dist-cjs/usage-tracker.cjs +83 -0
- package/dist-cjs/usage-tracker.d.ts +78 -0
- package/package.json +91 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway Memory Module
|
|
3
|
+
* Handles working memory and template parameter resolution
|
|
4
|
+
*/
|
|
5
|
+
import type { ChatRequest, AIRequest, GatewayConfig } from './types.js';
|
|
6
|
+
import type { Logxer } from '@x12i/logxer';
|
|
7
|
+
type Request = ChatRequest | AIRequest;
|
|
8
|
+
/**
|
|
9
|
+
* Builds workingMemory structure from request fields, enriching with metadata
|
|
10
|
+
* Merges existing workingMemory (from request or memory component) with request metadata
|
|
11
|
+
*
|
|
12
|
+
* Implements tiered token resolution:
|
|
13
|
+
* - Tier 1 (highest): templateTokens (handled in resolveTemplateParams, merged into shortTermMemory)
|
|
14
|
+
* - Tier 2: workingMemory (this method) - checks existing workingMemory first
|
|
15
|
+
* - Tier 3: derived from request fields or other memories (fallback)
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildWorkingMemory(request: Request, existingWorkingMemory?: unknown, otherMemories?: {
|
|
18
|
+
shortTermMemory?: {
|
|
19
|
+
[key: string]: any;
|
|
20
|
+
};
|
|
21
|
+
experienceMemory?: {
|
|
22
|
+
[key: string]: any;
|
|
23
|
+
};
|
|
24
|
+
knowledgeMemory?: {
|
|
25
|
+
[key: string]: any;
|
|
26
|
+
};
|
|
27
|
+
}): unknown;
|
|
28
|
+
/**
|
|
29
|
+
* Resolves template parameters with smart fallback logic
|
|
30
|
+
* Priority: Request args (tier 1) -> Memory component (tier 2) -> Gateway config (tier 3) -> defaults
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveTemplateParams(request: Request, config: GatewayConfig, logger: Logxer): Promise<{
|
|
33
|
+
workingMemory: unknown;
|
|
34
|
+
shortTermMemory?: {
|
|
35
|
+
[key: string]: string | number | boolean | object | object[];
|
|
36
|
+
};
|
|
37
|
+
experienceMemory?: {
|
|
38
|
+
knowHows?: object | object[] | string[] | string;
|
|
39
|
+
narratives?: object | object[] | string[] | string;
|
|
40
|
+
experiences?: object | object[] | string[] | string;
|
|
41
|
+
insights?: object | object[] | string[] | string;
|
|
42
|
+
learnings?: object | object[] | string[] | string;
|
|
43
|
+
lessons?: object | object[] | string[] | string;
|
|
44
|
+
frameworks?: object | object[] | string[] | string;
|
|
45
|
+
tools?: object | object[] | string[] | string;
|
|
46
|
+
};
|
|
47
|
+
knowledgeMemory?: {
|
|
48
|
+
[key: string]: string | number | boolean | object | object[];
|
|
49
|
+
};
|
|
50
|
+
}>;
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway Memory Module
|
|
3
|
+
* Handles working memory and template parameter resolution
|
|
4
|
+
*/
|
|
5
|
+
// Type guard to check if request is AIRequest (has primaryObjectType)
|
|
6
|
+
function isAIRequest(request) {
|
|
7
|
+
return 'primaryObjectType' in request &&
|
|
8
|
+
typeof request.primaryObjectType === 'object' &&
|
|
9
|
+
request.primaryObjectType !== null &&
|
|
10
|
+
typeof request.primaryObjectType.type === 'string';
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Builds workingMemory structure from request fields, enriching with metadata
|
|
14
|
+
* Merges existing workingMemory (from request or memory component) with request metadata
|
|
15
|
+
*
|
|
16
|
+
* Implements tiered token resolution:
|
|
17
|
+
* - Tier 1 (highest): templateTokens (handled in resolveTemplateParams, merged into shortTermMemory)
|
|
18
|
+
* - Tier 2: workingMemory (this method) - checks existing workingMemory first
|
|
19
|
+
* - Tier 3: derived from request fields or other memories (fallback)
|
|
20
|
+
*/
|
|
21
|
+
export function buildWorkingMemory(request, existingWorkingMemory, otherMemories) {
|
|
22
|
+
// Start with existing workingMemory if provided, otherwise empty object
|
|
23
|
+
const workingMemory = existingWorkingMemory && typeof existingWorkingMemory === 'object'
|
|
24
|
+
? { ...existingWorkingMemory }
|
|
25
|
+
: request.workingMemory && typeof request.workingMemory === 'object'
|
|
26
|
+
? { ...request.workingMemory }
|
|
27
|
+
: {};
|
|
28
|
+
// Ensure required job and task fields exist (required by Rendrix)
|
|
29
|
+
if (!workingMemory.job) {
|
|
30
|
+
workingMemory.job = {};
|
|
31
|
+
}
|
|
32
|
+
if (!workingMemory.task) {
|
|
33
|
+
workingMemory.task = {};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Token Resolution with Tiered Fallback
|
|
37
|
+
* Tier 1: templateTokens (handled in resolveTemplateParams, merged into shortTermMemory)
|
|
38
|
+
* Tier 2: workingMemory (check existing workingMemory first)
|
|
39
|
+
* Tier 3: derive from request fields or other memories
|
|
40
|
+
*/
|
|
41
|
+
// Resolve {{taskDescription}} token
|
|
42
|
+
// Tier 2: Check workingMemory first
|
|
43
|
+
// Tier 3: Fallback to request.instructions or derive from task.objective
|
|
44
|
+
if (workingMemory.taskDescription === undefined) {
|
|
45
|
+
// Tier 3: Derive from request.instructions (if available)
|
|
46
|
+
if (request.instructions) {
|
|
47
|
+
workingMemory.taskDescription = request.instructions;
|
|
48
|
+
}
|
|
49
|
+
else if (workingMemory.task?.objective) {
|
|
50
|
+
// Fallback to task.objective if instructions not available
|
|
51
|
+
workingMemory.taskDescription = workingMemory.task.objective;
|
|
52
|
+
}
|
|
53
|
+
else if (otherMemories) {
|
|
54
|
+
// Tier 3: Check other memories (experienceMemory, knowledgeMemory)
|
|
55
|
+
// Note: shortTermMemory is tier 1, so we skip it here
|
|
56
|
+
const fromExp = otherMemories.experienceMemory?.['taskDescription'];
|
|
57
|
+
const fromKnow = otherMemories.knowledgeMemory?.['taskDescription'];
|
|
58
|
+
if (fromExp !== undefined) {
|
|
59
|
+
workingMemory.taskDescription = fromExp;
|
|
60
|
+
}
|
|
61
|
+
else if (fromKnow !== undefined) {
|
|
62
|
+
workingMemory.taskDescription = fromKnow;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Resolve {{input}} token
|
|
67
|
+
// Input must come from workingMemory.input (request.input has been removed)
|
|
68
|
+
// If not in workingMemory, check other memories as fallback
|
|
69
|
+
if (workingMemory.input === undefined && otherMemories) {
|
|
70
|
+
const fromExp = otherMemories.experienceMemory?.['input'];
|
|
71
|
+
const fromKnow = otherMemories.knowledgeMemory?.['input'];
|
|
72
|
+
if (fromExp !== undefined) {
|
|
73
|
+
workingMemory.input = fromExp;
|
|
74
|
+
}
|
|
75
|
+
else if (fromKnow !== undefined) {
|
|
76
|
+
workingMemory.input = fromKnow;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Resolve {{role}} token
|
|
80
|
+
// Tier 2: Check workingMemory first
|
|
81
|
+
// Tier 3: Derive from request.agentType or message role context
|
|
82
|
+
if (workingMemory.role === undefined) {
|
|
83
|
+
// Tier 3: Derive from request.agentType or default to context
|
|
84
|
+
if (request.agentType) {
|
|
85
|
+
workingMemory.role = request.agentType;
|
|
86
|
+
}
|
|
87
|
+
else if (isAIRequest(request)) {
|
|
88
|
+
workingMemory.role = 'ai-reasoner';
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
workingMemory.role = 'chat';
|
|
92
|
+
}
|
|
93
|
+
// Tier 3: Check other memories (can override derivation)
|
|
94
|
+
if (otherMemories) {
|
|
95
|
+
const fromExp = otherMemories.experienceMemory?.['role'];
|
|
96
|
+
const fromKnow = otherMemories.knowledgeMemory?.['role'];
|
|
97
|
+
if (fromExp !== undefined) {
|
|
98
|
+
workingMemory.role = fromExp;
|
|
99
|
+
}
|
|
100
|
+
else if (fromKnow !== undefined) {
|
|
101
|
+
workingMemory.role = fromKnow;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Populate job fields from request if not already present in existing memory
|
|
106
|
+
if (!workingMemory.job.objective && request.instructions) {
|
|
107
|
+
workingMemory.job.objective = request.instructions;
|
|
108
|
+
}
|
|
109
|
+
if (!workingMemory.job.context && request.context) {
|
|
110
|
+
workingMemory.job.context = request.context;
|
|
111
|
+
}
|
|
112
|
+
// Input field has been removed - data should come from workingMemory.input
|
|
113
|
+
if (!workingMemory.job.narrative && request.prompt) {
|
|
114
|
+
workingMemory.job.narrative = request.prompt;
|
|
115
|
+
}
|
|
116
|
+
if (!workingMemory.job.id && request.jobId) {
|
|
117
|
+
workingMemory.job.id = request.jobId;
|
|
118
|
+
}
|
|
119
|
+
// Populate task fields from request if not already present in existing memory
|
|
120
|
+
if (!workingMemory.task.objective && request.instructions) {
|
|
121
|
+
workingMemory.task.objective = request.instructions;
|
|
122
|
+
}
|
|
123
|
+
if (!workingMemory.task.context && request.context) {
|
|
124
|
+
workingMemory.task.context = request.context;
|
|
125
|
+
}
|
|
126
|
+
// Input field has been removed - data should come from workingMemory.input
|
|
127
|
+
if (!workingMemory.task.id && request.taskId) {
|
|
128
|
+
workingMemory.task.id = request.taskId;
|
|
129
|
+
}
|
|
130
|
+
// Add entity information if not present
|
|
131
|
+
if (!workingMemory.entity && request.agentId) {
|
|
132
|
+
workingMemory.entity = {
|
|
133
|
+
name: request.agentId,
|
|
134
|
+
type: request.agentType || (isAIRequest(request) ? 'ai-reasoner' : 'chat')
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return workingMemory;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Resolves template parameters with smart fallback logic
|
|
141
|
+
* Priority: Request args (tier 1) -> Memory component (tier 2) -> Gateway config (tier 3) -> defaults
|
|
142
|
+
*/
|
|
143
|
+
export async function resolveTemplateParams(request, config, logger) {
|
|
144
|
+
// Tier 1: Request args (highest priority)
|
|
145
|
+
let workingMemory = request.workingMemory;
|
|
146
|
+
// Tier 2: Memory component integration (if available)
|
|
147
|
+
// When memoryManager is configured, it handles fetching, merging, enriching, and updating
|
|
148
|
+
if (config.memoryManager && config.memoryResolution) {
|
|
149
|
+
try {
|
|
150
|
+
// Build memory context from request
|
|
151
|
+
// Note: Spread request first, then add providedMemories to avoid duplicate properties
|
|
152
|
+
const memoryContext = {
|
|
153
|
+
...request,
|
|
154
|
+
providedMemories: {
|
|
155
|
+
workingMemory
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
// Determine which memories need to be fetched
|
|
159
|
+
const memoryResolution = config.memoryResolution;
|
|
160
|
+
const needsWorkingMemory = memoryResolution.fetchWorkingMemory !== false && !workingMemory;
|
|
161
|
+
// Call memoryManager.resolveMemories() which handles:
|
|
162
|
+
// 1. Fetching missing memories from storage
|
|
163
|
+
// 2. Merging input memories with fetched memories
|
|
164
|
+
// 3. Enriching memories if configured
|
|
165
|
+
// 4. Updating existing memories in storage if updateExistingMemories is true
|
|
166
|
+
// 5. Returning final merged memory
|
|
167
|
+
const memoryManager = config.memoryManager;
|
|
168
|
+
if (memoryManager && typeof memoryManager.resolveMemories === 'function') {
|
|
169
|
+
const resolved = await memoryManager.resolveMemories(memoryContext, {
|
|
170
|
+
fetchWorkingMemory: needsWorkingMemory,
|
|
171
|
+
updateExistingMemories: memoryResolution.updateExistingMemories ?? false,
|
|
172
|
+
updateScope: memoryResolution.updateScope ?? ['workingMemory'],
|
|
173
|
+
enrichment: memoryResolution.enrichment ?? { experience: 'none', knowledge: 'none' },
|
|
174
|
+
resolutionStrategy: memoryResolution.resolutionStrategy ?? 'fetch-on-demand'
|
|
175
|
+
});
|
|
176
|
+
// Use resolved memories (already merged from input + fetched, enriched if configured)
|
|
177
|
+
// Input memories take precedence, but resolved memories fill in missing pieces
|
|
178
|
+
workingMemory = resolved.workingMemory || workingMemory;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
// If memory component fails, fall back to request-only mode
|
|
183
|
+
logger?.warn('Memory component resolution failed, using request-only mode', {
|
|
184
|
+
error: error instanceof Error ? error.message : String(error),
|
|
185
|
+
jobId: request.jobId
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Build proper workingMemory structure (merge with request fields if needed)
|
|
190
|
+
// This implements tiered token resolution: tier 2 (workingMemory) and tier 3 (derive from request fields)
|
|
191
|
+
const finalWorkingMemory = buildWorkingMemory(request, workingMemory);
|
|
192
|
+
// Merge templateTokens (tier 1 - highest priority) into shortTermMemory AFTER memory resolution
|
|
193
|
+
// This ensures templateTokens override everything (workingMemory and other memories)
|
|
194
|
+
// Rendrix priority: shortTermMemory > workingMemory > experienceMemory > knowledgeMemory
|
|
195
|
+
if (request.templateTokens && Object.keys(request.templateTokens).length > 0) {
|
|
196
|
+
logger?.debug('Merged templateTokens into shortTermMemory (tier 1 - highest priority)', {
|
|
197
|
+
jobId: request.jobId,
|
|
198
|
+
tokenKeys: Object.keys(request.templateTokens)
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
// Note: taskConfig removed - Rendrix 3.0.0+ no longer accepts it
|
|
202
|
+
// taskConfig is deprecated and no longer used
|
|
203
|
+
return {
|
|
204
|
+
workingMemory: finalWorkingMemory
|
|
205
|
+
// taskConfig removed - Rendrix 3.0.0+ no longer uses it
|
|
206
|
+
};
|
|
207
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway Messages Module
|
|
3
|
+
* Handles message construction using direct message builder
|
|
4
|
+
*/
|
|
5
|
+
import type { ChatRequest, AIRequest } from './types.js';
|
|
6
|
+
import type { Logxer } from '@x12i/logxer';
|
|
7
|
+
import { type MessageBuilderConfig } from './message-builder.js';
|
|
8
|
+
type Request = ChatRequest | AIRequest;
|
|
9
|
+
/**
|
|
10
|
+
* Constructs messages from instructions/prompt/input/context
|
|
11
|
+
*
|
|
12
|
+
* Uses direct message builder which handles:
|
|
13
|
+
* - Token resolution (3-tier system)
|
|
14
|
+
* - Template parsing (via Rendrix, @x12i/rendrix)
|
|
15
|
+
* - Instruction block resolution and composition
|
|
16
|
+
* - Flex-md format specification
|
|
17
|
+
* - Message assembly
|
|
18
|
+
*/
|
|
19
|
+
export declare function constructMessages(request: Request, config: MessageBuilderConfig, logger: Logxer, parsedSnapshot?: any): Promise<Array<{
|
|
20
|
+
role: string;
|
|
21
|
+
content: string;
|
|
22
|
+
}>>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway Messages Module
|
|
3
|
+
* Handles message construction using direct message builder
|
|
4
|
+
*/
|
|
5
|
+
import { buildMessages } from './message-builder.js';
|
|
6
|
+
// Type guard to check if request is AIRequest
|
|
7
|
+
// AIRequest is distinguished by having primaryObjectType, objectTypes, or other AIRequest-specific fields
|
|
8
|
+
function isAIRequest(request) {
|
|
9
|
+
return 'primaryObjectType' in request ||
|
|
10
|
+
('objectTypes' in request && Array.isArray(request.objectTypes)) ||
|
|
11
|
+
'skillId' in request ||
|
|
12
|
+
'masterSkillId' in request ||
|
|
13
|
+
'reasoningEncrypted' in request;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Constructs messages from instructions/prompt/input/context
|
|
17
|
+
*
|
|
18
|
+
* Uses direct message builder which handles:
|
|
19
|
+
* - Token resolution (3-tier system)
|
|
20
|
+
* - Template parsing (via Rendrix, @x12i/rendrix)
|
|
21
|
+
* - Instruction block resolution and composition
|
|
22
|
+
* - Flex-md format specification
|
|
23
|
+
* - Message assembly
|
|
24
|
+
*/
|
|
25
|
+
export async function constructMessages(request, config, logger, parsedSnapshot) {
|
|
26
|
+
logger.verbose('Constructing messages from request', {
|
|
27
|
+
jobId: request.jobId,
|
|
28
|
+
agentId: request.agentId,
|
|
29
|
+
hasInstructions: !!request.instructions,
|
|
30
|
+
hasContext: !!request.context,
|
|
31
|
+
hasPrompt: !!request.prompt,
|
|
32
|
+
hasWorkingMemory: !!request.workingMemory
|
|
33
|
+
});
|
|
34
|
+
// LOGGING: Construct messages phase (instructions should already be resolved)
|
|
35
|
+
const traceId = request.jobId || `trace-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
36
|
+
const agentId = request.agentId;
|
|
37
|
+
logger.info('instructions.constructMessages.entry', {
|
|
38
|
+
traceId,
|
|
39
|
+
jobId: request.jobId,
|
|
40
|
+
agentId,
|
|
41
|
+
'instructionsType': typeof request.instructions,
|
|
42
|
+
'instructionsLength': typeof request.instructions === 'string' ? request.instructions.length : 'N/A',
|
|
43
|
+
'hasResolvedText': !!request.resolvedInstructionsText
|
|
44
|
+
});
|
|
45
|
+
// Always use flex-md format - no modes needed
|
|
46
|
+
let finalInstructions = request.instructions;
|
|
47
|
+
// Add examples for few-shot learning if using standard type
|
|
48
|
+
if (isAIRequest(request)) {
|
|
49
|
+
const resolvedType = request._resolvedTypes?.primary;
|
|
50
|
+
if (resolvedType?.isStandard && resolvedType.definition?.examples) {
|
|
51
|
+
const examples = resolvedType.definition.examples;
|
|
52
|
+
if (examples.length > 0) {
|
|
53
|
+
// Use first 3 examples for few-shot learning
|
|
54
|
+
const fewShotExamples = examples
|
|
55
|
+
.slice(0, 3)
|
|
56
|
+
.map((ex) => `Input: ${ex.input}\nOutput: ${ex.output}`)
|
|
57
|
+
.join('\n\n');
|
|
58
|
+
// Append to instructions
|
|
59
|
+
if (typeof finalInstructions === 'string') {
|
|
60
|
+
finalInstructions = `${finalInstructions}\n\nExamples:\n${fewShotExamples}`;
|
|
61
|
+
logger.debug('Added few-shot examples to instructions', {
|
|
62
|
+
jobId: request.jobId,
|
|
63
|
+
exampleCount: Math.min(examples.length, 3),
|
|
64
|
+
totalExamples: examples.length
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Update request with final instructions (for message builder)
|
|
71
|
+
const requestWithExamples = { ...request, instructions: finalInstructions };
|
|
72
|
+
// Build messages using direct message builder
|
|
73
|
+
const result = await buildMessages(requestWithExamples, config, {
|
|
74
|
+
useSystemContextFallback: true,
|
|
75
|
+
includeInputRecognition: isAIRequest(request),
|
|
76
|
+
includeReinforcement: isAIRequest(request),
|
|
77
|
+
parsedSnapshot
|
|
78
|
+
});
|
|
79
|
+
if (parsedSnapshot && result.metadata) {
|
|
80
|
+
parsedSnapshot._requestBuilderMetadata = result.metadata;
|
|
81
|
+
}
|
|
82
|
+
return result.messages;
|
|
83
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway Meta Operations Module
|
|
3
|
+
* Handles meta operations like instruction optimization and testing
|
|
4
|
+
*/
|
|
5
|
+
import type { EnhancedLLMResponse, GatewayConfig } from './types.js';
|
|
6
|
+
import type { Logxer } from '@x12i/logxer';
|
|
7
|
+
import type { AIGateway } from './gateway.js';
|
|
8
|
+
/**
|
|
9
|
+
* Test instructions by running them and analyzing the response
|
|
10
|
+
*/
|
|
11
|
+
export declare function testInstructions(instructions: string, testInput: string, expectedSchema: Record<string, unknown> | undefined, options: {
|
|
12
|
+
agentId?: string;
|
|
13
|
+
model?: string;
|
|
14
|
+
provider?: string;
|
|
15
|
+
}, config: GatewayConfig, gateway: AIGateway, logger: Logxer): Promise<{
|
|
16
|
+
passed: boolean;
|
|
17
|
+
response: EnhancedLLMResponse;
|
|
18
|
+
analysis: {
|
|
19
|
+
isValidJson: boolean;
|
|
20
|
+
matchesSchema: boolean;
|
|
21
|
+
hasProse: boolean;
|
|
22
|
+
issues: string[];
|
|
23
|
+
qualityScore: number;
|
|
24
|
+
};
|
|
25
|
+
}>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway Meta Operations Module
|
|
3
|
+
* Handles meta operations like instruction optimization and testing
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Test instructions by running them and analyzing the response
|
|
7
|
+
*/
|
|
8
|
+
export async function testInstructions(instructions, testInput, expectedSchema, options, config, gateway, logger) {
|
|
9
|
+
// Get internal system action config (instruction audit)
|
|
10
|
+
const internalConfig = config.internalSystemActions?.instructionAudit;
|
|
11
|
+
const defaultEngine = config.defaultEngine || 'openai';
|
|
12
|
+
const defaultModel = internalConfig?.model || 'gpt-5-nano';
|
|
13
|
+
const defaultProvider = internalConfig?.engine || defaultEngine;
|
|
14
|
+
const { agentId = 'instruction-tester', model = options.model || defaultModel, // Use internal config default if not provided
|
|
15
|
+
provider = options.provider || defaultProvider // Use internal config default if not provided
|
|
16
|
+
} = options;
|
|
17
|
+
if (!model) {
|
|
18
|
+
throw new Error('Model must be provided in options.model or configured as default');
|
|
19
|
+
}
|
|
20
|
+
// Create test request with internal system action config
|
|
21
|
+
const testRequest = {
|
|
22
|
+
jobId: `test-instructions-${Date.now()}`,
|
|
23
|
+
agentId,
|
|
24
|
+
instructions,
|
|
25
|
+
input: testInput,
|
|
26
|
+
config: {
|
|
27
|
+
model,
|
|
28
|
+
provider,
|
|
29
|
+
temperature: internalConfig?.temperature ?? 0.7, // Use internal config or default
|
|
30
|
+
maxTokens: internalConfig?.maxTokens ?? 2000 // Use internal config or default
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
// Run the test
|
|
34
|
+
const response = await gateway.invoke(testRequest);
|
|
35
|
+
// Analyze the response
|
|
36
|
+
const analysis = {
|
|
37
|
+
isValidJson: !!response.parsedContent && typeof response.parsedContent === 'object',
|
|
38
|
+
matchesSchema: false,
|
|
39
|
+
hasProse: false,
|
|
40
|
+
issues: [],
|
|
41
|
+
qualityScore: 0
|
|
42
|
+
};
|
|
43
|
+
// Check for prose
|
|
44
|
+
const contentStr = response.content || '';
|
|
45
|
+
const proseIndicators = ["I'm sorry", "Please provide", "Sure!", "Here is", "Let me", "I can", "I'll"];
|
|
46
|
+
analysis.hasProse = proseIndicators.some(indicator => contentStr.toLowerCase().includes(indicator.toLowerCase()));
|
|
47
|
+
// Check if matches schema
|
|
48
|
+
if (expectedSchema && response.parsedContent) {
|
|
49
|
+
const parsed = response.parsedContent;
|
|
50
|
+
const schemaKeys = Object.keys(expectedSchema);
|
|
51
|
+
const responseKeys = Object.keys(parsed);
|
|
52
|
+
analysis.matchesSchema = schemaKeys.every(key => responseKeys.includes(key));
|
|
53
|
+
}
|
|
54
|
+
else if (response.parsedContent) {
|
|
55
|
+
analysis.matchesSchema = true; // No schema to match against
|
|
56
|
+
}
|
|
57
|
+
// Collect issues
|
|
58
|
+
if (!analysis.isValidJson) {
|
|
59
|
+
analysis.issues.push('Response is not valid JSON');
|
|
60
|
+
}
|
|
61
|
+
if (analysis.hasProse) {
|
|
62
|
+
analysis.issues.push('Response contains conversational prose');
|
|
63
|
+
}
|
|
64
|
+
if (!analysis.matchesSchema && expectedSchema) {
|
|
65
|
+
analysis.issues.push('Response does not match expected schema');
|
|
66
|
+
}
|
|
67
|
+
if (!response.parsedContent) {
|
|
68
|
+
analysis.issues.push('Response missing parsedContent');
|
|
69
|
+
}
|
|
70
|
+
// Calculate quality score (0-10)
|
|
71
|
+
let score = 10;
|
|
72
|
+
if (!analysis.isValidJson)
|
|
73
|
+
score -= 5;
|
|
74
|
+
if (analysis.hasProse)
|
|
75
|
+
score -= 3;
|
|
76
|
+
if (!analysis.matchesSchema && expectedSchema)
|
|
77
|
+
score -= 2;
|
|
78
|
+
if (!response.parsedContent)
|
|
79
|
+
score -= 5;
|
|
80
|
+
analysis.qualityScore = Math.max(0, score);
|
|
81
|
+
const passed = analysis.issues.length === 0 && analysis.qualityScore >= 7;
|
|
82
|
+
return {
|
|
83
|
+
passed,
|
|
84
|
+
response,
|
|
85
|
+
analysis
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway Provider Auto-Registration Module
|
|
3
|
+
* Automatically registers providers based on environment variables
|
|
4
|
+
*/
|
|
5
|
+
import type { LLMProviderRouter } from '@x12i/ai-providers-router';
|
|
6
|
+
import type { Logxer } from '@x12i/logxer';
|
|
7
|
+
/**
|
|
8
|
+
* Auto-registers providers based on environment variables
|
|
9
|
+
* Only registers providers that:
|
|
10
|
+
* 1. Have their API key set in environment variables
|
|
11
|
+
* 2. Have their provider package installed
|
|
12
|
+
*
|
|
13
|
+
* @param router - LLM provider router instance
|
|
14
|
+
* @param logger - Logger instance
|
|
15
|
+
* @returns Array of provider names that were successfully registered
|
|
16
|
+
*/
|
|
17
|
+
export declare function autoRegisterProviders(router: LLMProviderRouter, logger: Logxer): Promise<string[]>;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway Provider Auto-Registration Module
|
|
3
|
+
* Automatically registers providers based on environment variables
|
|
4
|
+
*/
|
|
5
|
+
const PROVIDER_CONFIGS = [
|
|
6
|
+
{
|
|
7
|
+
name: 'openai',
|
|
8
|
+
packageName: '@x12i/ai-provider-openai',
|
|
9
|
+
className: 'OpenAIProvider',
|
|
10
|
+
envVar: 'OPENAI_API_KEY'
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: 'grok',
|
|
14
|
+
packageName: '@x12i/ai-provider-grok',
|
|
15
|
+
className: 'GrokProvider',
|
|
16
|
+
envVar: 'GROK_API_KEY'
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'anthropic',
|
|
20
|
+
packageName: '@x12i/ai-provider-anthropic',
|
|
21
|
+
className: 'AnthropicProvider',
|
|
22
|
+
envVar: 'ANTHROPIC_API_KEY',
|
|
23
|
+
optional: true // Optional - may not be installed
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'google',
|
|
27
|
+
packageName: '@x12i/ai-provider-google',
|
|
28
|
+
className: 'GoogleProvider',
|
|
29
|
+
envVar: 'GOOGLE_API_KEY',
|
|
30
|
+
optional: true // Optional - may not be installed
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'cohere',
|
|
34
|
+
packageName: '@x12i/ai-provider-cohere',
|
|
35
|
+
className: 'CohereProvider',
|
|
36
|
+
envVar: 'COHERE_API_KEY',
|
|
37
|
+
optional: true // Optional - may not be installed
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'mistral',
|
|
41
|
+
packageName: '@x12i/ai-provider-mistral',
|
|
42
|
+
className: 'MistralProvider',
|
|
43
|
+
envVar: 'MISTRAL_API_KEY',
|
|
44
|
+
optional: true // Optional - may not be installed
|
|
45
|
+
}
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* Auto-registers providers based on environment variables
|
|
49
|
+
* Only registers providers that:
|
|
50
|
+
* 1. Have their API key set in environment variables
|
|
51
|
+
* 2. Have their provider package installed
|
|
52
|
+
*
|
|
53
|
+
* @param router - LLM provider router instance
|
|
54
|
+
* @param logger - Logger instance
|
|
55
|
+
* @returns Array of provider names that were successfully registered
|
|
56
|
+
*/
|
|
57
|
+
export async function autoRegisterProviders(router, logger) {
|
|
58
|
+
const registeredProviders = [];
|
|
59
|
+
logger.debug('Auto-registering providers from environment variables');
|
|
60
|
+
for (const providerConfig of PROVIDER_CONFIGS) {
|
|
61
|
+
const apiKey = process.env[providerConfig.envVar];
|
|
62
|
+
// Skip if API key is not set
|
|
63
|
+
if (!apiKey) {
|
|
64
|
+
if (!providerConfig.optional) {
|
|
65
|
+
logger.debug(`Skipping ${providerConfig.name} provider: ${providerConfig.envVar} not set`);
|
|
66
|
+
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
// Dynamically import the provider package
|
|
71
|
+
// Use dynamic import() for ES module compatibility
|
|
72
|
+
let ProviderClass;
|
|
73
|
+
try {
|
|
74
|
+
const providerModule = await import(providerConfig.packageName);
|
|
75
|
+
ProviderClass = providerModule[providerConfig.className] || providerModule.default;
|
|
76
|
+
if (!ProviderClass) {
|
|
77
|
+
logger.debug(`Provider class ${providerConfig.className} not found in ${providerConfig.packageName}`);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch (importError) {
|
|
82
|
+
if (!providerConfig.optional) {
|
|
83
|
+
logger.warn(`Failed to import ${providerConfig.packageName}`, {
|
|
84
|
+
error: importError instanceof Error ? importError.message : String(importError),
|
|
85
|
+
note: `Install it with: npm install ${providerConfig.packageName}`
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
// Instantiate the provider
|
|
91
|
+
const provider = new ProviderClass({
|
|
92
|
+
apiKey: apiKey
|
|
93
|
+
});
|
|
94
|
+
// Get provider name for both module creation and logging
|
|
95
|
+
const providerName = typeof provider.getProviderName === 'function'
|
|
96
|
+
? provider.getProviderName()
|
|
97
|
+
: providerConfig.name;
|
|
98
|
+
// Register with router as ProviderModule
|
|
99
|
+
const providerModule = {
|
|
100
|
+
name: providerName,
|
|
101
|
+
capabilities: {
|
|
102
|
+
modes: {
|
|
103
|
+
sync: true,
|
|
104
|
+
stream: false,
|
|
105
|
+
batch: false
|
|
106
|
+
},
|
|
107
|
+
operations: ['invoke'],
|
|
108
|
+
maxConcurrency: 10
|
|
109
|
+
},
|
|
110
|
+
execute: async (request) => {
|
|
111
|
+
// Use aiCall if available, otherwise assume invoke
|
|
112
|
+
if (typeof provider.aiCall === 'function') {
|
|
113
|
+
return await provider.aiCall(request);
|
|
114
|
+
}
|
|
115
|
+
else if (typeof provider.invoke === 'function') {
|
|
116
|
+
return await provider.invoke(request);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
throw new Error(`Provider ${providerName} has neither aiCall nor invoke method`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
router.registerProvider(providerModule);
|
|
124
|
+
registeredProviders.push(providerName);
|
|
125
|
+
logger.info(`Auto-registered provider: ${providerName}`, {
|
|
126
|
+
provider: providerName,
|
|
127
|
+
envVar: providerConfig.envVar,
|
|
128
|
+
hasApiKey: !!apiKey
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
logger.error(`Failed to auto-register ${providerConfig.name} provider`, {
|
|
133
|
+
provider: providerConfig.name,
|
|
134
|
+
package: providerConfig.packageName,
|
|
135
|
+
error: error instanceof Error ? error.message : String(error),
|
|
136
|
+
stack: error instanceof Error ? error.stack : undefined
|
|
137
|
+
});
|
|
138
|
+
// Continue with other providers even if one fails
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (registeredProviders.length === 0) {
|
|
142
|
+
logger.warn('No providers were auto-registered. Make sure API keys are set in environment variables:', {
|
|
143
|
+
requiredEnvVars: PROVIDER_CONFIGS
|
|
144
|
+
.filter(p => !p.optional)
|
|
145
|
+
.map(p => p.envVar),
|
|
146
|
+
optionalEnvVars: PROVIDER_CONFIGS
|
|
147
|
+
.filter(p => p.optional)
|
|
148
|
+
.map(p => p.envVar),
|
|
149
|
+
openRouter: 'Set OPEN_ROUTER_KEY or OPENROUTER_API_KEY (and do not set USE_OPENROUTER=false) to use OpenRouter without registering a provider.',
|
|
150
|
+
note: 'You can still manually register providers using gateway.register(provider)'
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
logger.info(`Auto-registered ${registeredProviders.length} provider(s)`, {
|
|
155
|
+
providers: registeredProviders
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
return registeredProviders;
|
|
159
|
+
}
|