@falai/agent 0.9.0-alpha-1 → 0.9.0-alpha-2
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 +34 -22
- package/dist/cjs/src/core/Agent.d.ts +52 -24
- package/dist/cjs/src/core/Agent.d.ts.map +1 -1
- package/dist/cjs/src/core/Agent.js +266 -39
- package/dist/cjs/src/core/Agent.js.map +1 -1
- package/dist/cjs/src/core/PersistenceManager.d.ts.map +1 -1
- package/dist/cjs/src/core/PersistenceManager.js +48 -25
- package/dist/cjs/src/core/PersistenceManager.js.map +1 -1
- package/dist/cjs/src/core/PromptComposer.d.ts +1 -1
- package/dist/cjs/src/core/PromptComposer.d.ts.map +1 -1
- package/dist/cjs/src/core/PromptComposer.js.map +1 -1
- package/dist/cjs/src/core/ResponseEngine.d.ts +13 -12
- package/dist/cjs/src/core/ResponseEngine.d.ts.map +1 -1
- package/dist/cjs/src/core/ResponseEngine.js +4 -4
- package/dist/cjs/src/core/ResponseEngine.js.map +1 -1
- package/dist/cjs/src/core/ResponsePipeline.d.ts +66 -38
- package/dist/cjs/src/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/cjs/src/core/ResponsePipeline.js +71 -3
- package/dist/cjs/src/core/ResponsePipeline.js.map +1 -1
- package/dist/cjs/src/core/Route.d.ts +24 -5
- package/dist/cjs/src/core/Route.d.ts.map +1 -1
- package/dist/cjs/src/core/Route.js +45 -1
- package/dist/cjs/src/core/Route.js.map +1 -1
- package/dist/cjs/src/core/RoutingEngine.d.ts +31 -6
- package/dist/cjs/src/core/RoutingEngine.d.ts.map +1 -1
- package/dist/cjs/src/core/RoutingEngine.js +113 -9
- package/dist/cjs/src/core/RoutingEngine.js.map +1 -1
- package/dist/cjs/src/core/SessionManager.d.ts +14 -4
- package/dist/cjs/src/core/SessionManager.d.ts.map +1 -1
- package/dist/cjs/src/core/SessionManager.js +25 -5
- package/dist/cjs/src/core/SessionManager.js.map +1 -1
- package/dist/cjs/src/core/Step.d.ts +10 -10
- package/dist/cjs/src/core/Step.d.ts.map +1 -1
- package/dist/cjs/src/core/Step.js.map +1 -1
- package/dist/cjs/src/core/ToolExecutor.d.ts +4 -2
- package/dist/cjs/src/core/ToolExecutor.d.ts.map +1 -1
- package/dist/cjs/src/core/ToolExecutor.js +13 -3
- package/dist/cjs/src/core/ToolExecutor.js.map +1 -1
- package/dist/cjs/src/types/agent.d.ts +41 -21
- package/dist/cjs/src/types/agent.d.ts.map +1 -1
- package/dist/cjs/src/types/agent.js.map +1 -1
- package/dist/cjs/src/types/index.d.ts +1 -1
- package/dist/cjs/src/types/index.d.ts.map +1 -1
- package/dist/cjs/src/types/index.js.map +1 -1
- package/dist/cjs/src/types/persistence.d.ts +0 -1
- package/dist/cjs/src/types/persistence.d.ts.map +1 -1
- package/dist/cjs/src/types/route.d.ts +22 -16
- package/dist/cjs/src/types/route.d.ts.map +1 -1
- package/dist/cjs/src/types/session.d.ts +6 -11
- package/dist/cjs/src/types/session.d.ts.map +1 -1
- package/dist/cjs/src/types/tool.d.ts +12 -6
- package/dist/cjs/src/types/tool.d.ts.map +1 -1
- package/dist/cjs/src/utils/session.d.ts +2 -2
- package/dist/cjs/src/utils/session.d.ts.map +1 -1
- package/dist/cjs/src/utils/session.js +6 -26
- package/dist/cjs/src/utils/session.js.map +1 -1
- package/dist/src/core/Agent.d.ts +52 -24
- package/dist/src/core/Agent.d.ts.map +1 -1
- package/dist/src/core/Agent.js +266 -39
- package/dist/src/core/Agent.js.map +1 -1
- package/dist/src/core/PersistenceManager.d.ts.map +1 -1
- package/dist/src/core/PersistenceManager.js +48 -25
- package/dist/src/core/PersistenceManager.js.map +1 -1
- package/dist/src/core/PromptComposer.d.ts +1 -1
- package/dist/src/core/PromptComposer.d.ts.map +1 -1
- package/dist/src/core/PromptComposer.js.map +1 -1
- package/dist/src/core/ResponseEngine.d.ts +13 -12
- package/dist/src/core/ResponseEngine.d.ts.map +1 -1
- package/dist/src/core/ResponseEngine.js +4 -4
- package/dist/src/core/ResponseEngine.js.map +1 -1
- package/dist/src/core/ResponsePipeline.d.ts +66 -38
- package/dist/src/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/src/core/ResponsePipeline.js +71 -3
- package/dist/src/core/ResponsePipeline.js.map +1 -1
- package/dist/src/core/Route.d.ts +24 -5
- package/dist/src/core/Route.d.ts.map +1 -1
- package/dist/src/core/Route.js +45 -1
- package/dist/src/core/Route.js.map +1 -1
- package/dist/src/core/RoutingEngine.d.ts +31 -6
- package/dist/src/core/RoutingEngine.d.ts.map +1 -1
- package/dist/src/core/RoutingEngine.js +113 -9
- package/dist/src/core/RoutingEngine.js.map +1 -1
- package/dist/src/core/SessionManager.d.ts +14 -4
- package/dist/src/core/SessionManager.d.ts.map +1 -1
- package/dist/src/core/SessionManager.js +25 -5
- package/dist/src/core/SessionManager.js.map +1 -1
- package/dist/src/core/Step.d.ts +10 -10
- package/dist/src/core/Step.d.ts.map +1 -1
- package/dist/src/core/Step.js.map +1 -1
- package/dist/src/core/ToolExecutor.d.ts +4 -2
- package/dist/src/core/ToolExecutor.d.ts.map +1 -1
- package/dist/src/core/ToolExecutor.js +13 -3
- package/dist/src/core/ToolExecutor.js.map +1 -1
- package/dist/src/types/agent.d.ts +41 -21
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/agent.js.map +1 -1
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/types/persistence.d.ts +0 -1
- package/dist/src/types/persistence.d.ts.map +1 -1
- package/dist/src/types/route.d.ts +22 -16
- package/dist/src/types/route.d.ts.map +1 -1
- package/dist/src/types/session.d.ts +6 -11
- package/dist/src/types/session.d.ts.map +1 -1
- package/dist/src/types/tool.d.ts +12 -6
- package/dist/src/types/tool.d.ts.map +1 -1
- package/dist/src/utils/session.d.ts +2 -2
- package/dist/src/utils/session.d.ts.map +1 -1
- package/dist/src/utils/session.js +6 -26
- package/dist/src/utils/session.js.map +1 -1
- package/docs/README.md +3 -3
- package/docs/api/README.md +35 -4
- package/docs/api/overview.md +166 -12
- package/docs/core/agent/README.md +162 -17
- package/docs/core/agent/context-management.md +39 -15
- package/docs/core/agent/session-management.md +49 -16
- package/docs/core/ai-integration/prompt-composition.md +38 -14
- package/docs/core/ai-integration/response-processing.md +28 -17
- package/docs/core/conversation-flows/data-collection.md +103 -25
- package/docs/core/conversation-flows/route-dsl.md +45 -22
- package/docs/core/conversation-flows/routes.md +74 -18
- package/docs/core/conversation-flows/step-transitions.md +3 -3
- package/docs/core/conversation-flows/steps.md +39 -15
- package/docs/core/routing/intelligent-routing.md +18 -9
- package/docs/core/tools/tool-definition.md +8 -8
- package/docs/core/tools/tool-execution.md +26 -26
- package/docs/core/tools/tool-scoping.md +5 -5
- package/docs/guides/getting-started/README.md +54 -32
- package/examples/advanced-patterns/knowledge-based-agent.ts +37 -28
- package/examples/advanced-patterns/persistent-onboarding.ts +70 -41
- package/examples/advanced-patterns/route-lifecycle-hooks.ts +28 -2
- package/examples/advanced-patterns/streaming-responses.ts +28 -23
- package/examples/ai-providers/anthropic-integration.ts +40 -33
- package/examples/ai-providers/openai-integration.ts +25 -25
- package/examples/conversation-flows/completion-transitions.ts +36 -32
- package/examples/core-concepts/basic-agent.ts +76 -78
- package/examples/core-concepts/schema-driven-extraction.ts +20 -16
- package/examples/core-concepts/session-management.ts +65 -53
- package/examples/integrations/database-integration.ts +49 -34
- package/examples/integrations/healthcare-integration.ts +96 -91
- package/examples/integrations/search-integration.ts +79 -82
- package/examples/integrations/server-session-management.ts +25 -17
- package/examples/persistence/database-persistence.ts +61 -45
- package/examples/persistence/memory-sessions.ts +52 -63
- package/examples/persistence/redis-persistence.ts +81 -95
- package/examples/tools/basic-tools.ts +73 -62
- package/examples/tools/data-enrichment-tools.ts +52 -44
- package/package.json +1 -1
- package/src/core/Agent.ts +418 -128
- package/src/core/PersistenceManager.ts +51 -27
- package/src/core/PromptComposer.ts +1 -1
- package/src/core/ResponseEngine.ts +21 -19
- package/src/core/ResponsePipeline.ts +174 -59
- package/src/core/Route.ts +58 -6
- package/src/core/RoutingEngine.ts +174 -27
- package/src/core/SessionManager.ts +32 -8
- package/src/core/Step.ts +20 -12
- package/src/core/ToolExecutor.ts +19 -5
- package/src/types/agent.ts +46 -23
- package/src/types/index.ts +2 -0
- package/src/types/persistence.ts +0 -1
- package/src/types/route.ts +22 -16
- package/src/types/session.ts +6 -12
- package/src/types/tool.ts +15 -9
- package/src/utils/session.ts +6 -31
|
@@ -16,17 +16,39 @@ const ToolExecutor_1 = require("./ToolExecutor");
|
|
|
16
16
|
const ResponsePipeline_1 = require("./ResponsePipeline");
|
|
17
17
|
const constants_1 = require("../constants");
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* Error thrown when data validation fails
|
|
20
20
|
*/
|
|
21
|
+
class DataValidationError extends Error {
|
|
22
|
+
constructor(errors, message) {
|
|
23
|
+
super(message || "Data validation failed");
|
|
24
|
+
this.errors = errors;
|
|
25
|
+
this.name = "DataValidationError";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Error thrown when route configuration is invalid
|
|
30
|
+
*/
|
|
31
|
+
class RouteConfigurationError extends Error {
|
|
32
|
+
constructor(routeTitle, invalidFields, message) {
|
|
33
|
+
super(message || `Route configuration error in '${routeTitle}'`);
|
|
34
|
+
this.routeTitle = routeTitle;
|
|
35
|
+
this.invalidFields = invalidFields;
|
|
36
|
+
this.name = "RouteConfigurationError";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Main Agent class with generic context and data support
|
|
41
|
+
*/
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
43
|
class Agent {
|
|
22
44
|
constructor(options) {
|
|
23
45
|
this.options = options;
|
|
24
46
|
this.terms = [];
|
|
25
47
|
this.guidelines = [];
|
|
26
48
|
this.tools = [];
|
|
27
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
49
|
this.routes = [];
|
|
29
50
|
this.knowledgeBase = {};
|
|
51
|
+
this.collectedData = {};
|
|
30
52
|
// Set log level based on debug option
|
|
31
53
|
if (options.debug) {
|
|
32
54
|
utils_1.logger.setLevel(utils_1.LoggerLevel.DEBUG);
|
|
@@ -35,8 +57,25 @@ class Agent {
|
|
|
35
57
|
if (options.context !== undefined && options.contextProvider) {
|
|
36
58
|
throw new Error("Cannot provide both 'context' and 'contextProvider'. Choose one.");
|
|
37
59
|
}
|
|
60
|
+
// Initialize and validate agent-level schema if provided
|
|
61
|
+
if (options.schema) {
|
|
62
|
+
this.schema = options.schema;
|
|
63
|
+
this.validateSchema(this.schema);
|
|
64
|
+
utils_1.logger.debug("[Agent] Agent-level schema initialized and validated");
|
|
65
|
+
}
|
|
38
66
|
// Initialize context if provided
|
|
39
67
|
this.context = options.context;
|
|
68
|
+
// Initialize collected data with initial data if provided
|
|
69
|
+
if (options.initialData) {
|
|
70
|
+
if (this.schema) {
|
|
71
|
+
const validation = this.validateData(options.initialData);
|
|
72
|
+
if (!validation.valid) {
|
|
73
|
+
throw new Error(`Initial data validation failed: ${validation.errors.map(e => e.message).join(', ')}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
this.collectedData = { ...options.initialData };
|
|
77
|
+
utils_1.logger.debug("[Agent] Initial data set:", this.collectedData);
|
|
78
|
+
}
|
|
40
79
|
// Initialize current session if provided
|
|
41
80
|
this.currentSession = options.session;
|
|
42
81
|
// Initialize routing and response engines
|
|
@@ -46,15 +85,32 @@ class Agent {
|
|
|
46
85
|
switchThreshold: 70,
|
|
47
86
|
});
|
|
48
87
|
this.responseEngine = new ResponseEngine_1.ResponseEngine();
|
|
49
|
-
this.responsePipeline = new ResponsePipeline_1.ResponsePipeline(options, this.routes, this.tools, this.routingEngine, this.updateContext.bind(this), this.updateData.bind(this));
|
|
88
|
+
this.responsePipeline = new ResponsePipeline_1.ResponsePipeline(options, this.routes, this.tools, this.routingEngine, this.updateContext.bind(this), this.updateData.bind(this), this.updateCollectedData.bind(this));
|
|
50
89
|
// Initialize persistence if configured
|
|
51
90
|
if (options.persistence) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
91
|
+
try {
|
|
92
|
+
// Validate persistence configuration
|
|
93
|
+
if (!options.persistence.adapter) {
|
|
94
|
+
throw new Error("Persistence adapter is required when persistence is configured");
|
|
95
|
+
}
|
|
96
|
+
if (!options.persistence.adapter.sessionRepository) {
|
|
97
|
+
throw new Error("Persistence adapter must provide a sessionRepository");
|
|
98
|
+
}
|
|
99
|
+
if (!options.persistence.adapter.messageRepository) {
|
|
100
|
+
throw new Error("Persistence adapter must provide a messageRepository");
|
|
101
|
+
}
|
|
102
|
+
this.persistenceManager = new PersistenceManager_1.PersistenceManager(options.persistence);
|
|
103
|
+
// Initialize the adapter if it has an initialize method
|
|
104
|
+
if (options.persistence.adapter.initialize) {
|
|
105
|
+
options.persistence.adapter.initialize().catch((error) => {
|
|
106
|
+
utils_1.logger.error("[Agent] Persistence adapter initialization failed:", error instanceof Error ? error.message : String(error));
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
112
|
+
utils_1.logger.error("[Agent] Failed to initialize persistence:", errorMessage);
|
|
113
|
+
throw new Error(`Failed to initialize persistence: ${errorMessage}`);
|
|
58
114
|
}
|
|
59
115
|
}
|
|
60
116
|
// Initialize from options - use create methods for consistency
|
|
@@ -92,6 +148,116 @@ class Agent {
|
|
|
92
148
|
});
|
|
93
149
|
}
|
|
94
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Validate the agent-level schema structure
|
|
153
|
+
* @private
|
|
154
|
+
*/
|
|
155
|
+
validateSchema(schema) {
|
|
156
|
+
if (!schema || typeof schema !== 'object') {
|
|
157
|
+
throw new Error("Agent schema must be a valid JSON Schema object. " +
|
|
158
|
+
"Provide a schema with 'type': 'object' and 'properties' to define the data structure.");
|
|
159
|
+
}
|
|
160
|
+
if (schema.type !== 'object') {
|
|
161
|
+
throw new Error(`Agent schema must be of type 'object', but received '${String(schema.type)}'. ` +
|
|
162
|
+
"Agent-level schemas must define object structures for data collection.");
|
|
163
|
+
}
|
|
164
|
+
if (!schema.properties || typeof schema.properties !== 'object') {
|
|
165
|
+
throw new Error("Agent schema must have a 'properties' field defining the data fields. " +
|
|
166
|
+
"Example: { type: 'object', properties: { name: { type: 'string' }, email: { type: 'string' } } }");
|
|
167
|
+
}
|
|
168
|
+
utils_1.logger.debug("[Agent] Schema validation passed");
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Validate data against the agent-level schema
|
|
172
|
+
*/
|
|
173
|
+
validateData(data) {
|
|
174
|
+
if (!this.schema) {
|
|
175
|
+
// No schema defined, consider all data valid
|
|
176
|
+
return { valid: true, errors: [], warnings: [] };
|
|
177
|
+
}
|
|
178
|
+
const errors = [];
|
|
179
|
+
const warnings = [];
|
|
180
|
+
// Basic validation - check if provided fields exist in schema
|
|
181
|
+
if (this.schema.properties) {
|
|
182
|
+
for (const [key, value] of Object.entries(data)) {
|
|
183
|
+
if (!(key in this.schema.properties)) {
|
|
184
|
+
errors.push({
|
|
185
|
+
field: key,
|
|
186
|
+
value,
|
|
187
|
+
message: `Field '${key}' is not defined in agent schema`,
|
|
188
|
+
schemaPath: `properties.${key}`
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// Check required fields if specified
|
|
194
|
+
if (this.schema.required && Array.isArray(this.schema.required)) {
|
|
195
|
+
for (const requiredField of this.schema.required) {
|
|
196
|
+
if (!(requiredField in data) || data[requiredField] === undefined) {
|
|
197
|
+
warnings.push({
|
|
198
|
+
field: requiredField,
|
|
199
|
+
value: undefined,
|
|
200
|
+
message: `Required field '${requiredField}' is missing`,
|
|
201
|
+
schemaPath: `required`
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
valid: errors.length === 0,
|
|
208
|
+
errors,
|
|
209
|
+
warnings
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Check if a field is valid according to the agent schema
|
|
214
|
+
* @param field - The field key to validate
|
|
215
|
+
* @returns true if field exists in schema or no schema is defined, false otherwise
|
|
216
|
+
*/
|
|
217
|
+
isValidSchemaField(field) {
|
|
218
|
+
if (!this.schema || !this.schema.properties) {
|
|
219
|
+
// No schema defined, consider all fields valid
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
return field in this.schema.properties;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Get the current collected data
|
|
226
|
+
*/
|
|
227
|
+
getCollectedData() {
|
|
228
|
+
return { ...this.collectedData };
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Update collected data with validation
|
|
232
|
+
*/
|
|
233
|
+
async updateCollectedData(updates) {
|
|
234
|
+
// Validate the updates
|
|
235
|
+
const validation = this.validateData(updates);
|
|
236
|
+
if (!validation.valid) {
|
|
237
|
+
const errorMessages = validation.errors.map(e => e.message).join(', ');
|
|
238
|
+
throw new DataValidationError(validation.errors, `Data validation failed: ${errorMessages}`);
|
|
239
|
+
}
|
|
240
|
+
// Log warnings if any
|
|
241
|
+
if (validation.warnings.length > 0) {
|
|
242
|
+
const warningMessages = validation.warnings.map(w => w.message).join(', ');
|
|
243
|
+
utils_1.logger.warn(`[Agent] Data validation warnings: ${warningMessages}`);
|
|
244
|
+
}
|
|
245
|
+
// Merge updates with current data
|
|
246
|
+
const previousData = { ...this.collectedData };
|
|
247
|
+
this.collectedData = {
|
|
248
|
+
...this.collectedData,
|
|
249
|
+
...updates
|
|
250
|
+
};
|
|
251
|
+
// Trigger agent-level lifecycle hook if configured
|
|
252
|
+
if (this.options.hooks?.onDataUpdate) {
|
|
253
|
+
this.collectedData = await this.options.hooks.onDataUpdate(this.collectedData, previousData);
|
|
254
|
+
}
|
|
255
|
+
// Update current session if it exists to keep it in sync
|
|
256
|
+
if (this.currentSession) {
|
|
257
|
+
this.currentSession = (0, utils_1.mergeCollected)(this.currentSession, this.collectedData);
|
|
258
|
+
}
|
|
259
|
+
utils_1.logger.debug("[Agent] Collected data updated:", updates);
|
|
260
|
+
}
|
|
95
261
|
/**
|
|
96
262
|
* Get agent name
|
|
97
263
|
*/
|
|
@@ -117,10 +283,25 @@ class Agent {
|
|
|
117
283
|
return this.options.identity;
|
|
118
284
|
}
|
|
119
285
|
/**
|
|
120
|
-
* Create a new route (journey)
|
|
121
|
-
* @template TData - Type of data collected throughout the route
|
|
286
|
+
* Create a new route (journey) using agent-level data type
|
|
122
287
|
*/
|
|
123
288
|
createRoute(options) {
|
|
289
|
+
// Validate that requiredFields exist in agent schema
|
|
290
|
+
if (options.requiredFields && this.schema?.properties) {
|
|
291
|
+
const invalidRequiredFields = options.requiredFields.filter(field => !(String(field) in this.schema.properties));
|
|
292
|
+
if (invalidRequiredFields.length > 0) {
|
|
293
|
+
throw new RouteConfigurationError(options.title, invalidRequiredFields.map(f => String(f)), `Invalid required fields in route '${options.title}': ${invalidRequiredFields.join(', ')}. ` +
|
|
294
|
+
`Must be valid keys from agent schema. Available fields: ${Object.keys(this.schema.properties).join(', ')}.`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// Validate that optionalFields exist in agent schema
|
|
298
|
+
if (options.optionalFields && this.schema?.properties) {
|
|
299
|
+
const invalidOptionalFields = options.optionalFields.filter(field => !(String(field) in this.schema.properties));
|
|
300
|
+
if (invalidOptionalFields.length > 0) {
|
|
301
|
+
throw new RouteConfigurationError(options.title, invalidOptionalFields.map(f => String(f)), `Invalid optional fields in route '${options.title}': ${invalidOptionalFields.join(', ')}. ` +
|
|
302
|
+
`Must be valid keys from agent schema. Available fields: ${Object.keys(this.schema.properties).join(', ')}.`);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
124
305
|
const route = new Route_1.Route(options);
|
|
125
306
|
this.routes.push(route);
|
|
126
307
|
return route;
|
|
@@ -205,6 +386,8 @@ class Agent {
|
|
|
205
386
|
if (this.options.hooks?.onDataUpdate) {
|
|
206
387
|
newCollected = (await this.options.hooks.onDataUpdate(newCollected, previousCollected));
|
|
207
388
|
}
|
|
389
|
+
// Update agent's collected data to stay in sync
|
|
390
|
+
this.collectedData = { ...newCollected };
|
|
208
391
|
// Return updated session
|
|
209
392
|
return (0, utils_1.mergeCollected)(session, newCollected);
|
|
210
393
|
}
|
|
@@ -219,6 +402,12 @@ class Agent {
|
|
|
219
402
|
// Otherwise return the stored context
|
|
220
403
|
return this.context;
|
|
221
404
|
}
|
|
405
|
+
/**
|
|
406
|
+
* Get current schema
|
|
407
|
+
*/
|
|
408
|
+
getSchema() {
|
|
409
|
+
return this.schema;
|
|
410
|
+
}
|
|
222
411
|
/**
|
|
223
412
|
* Generate a response based on history and context as a stream
|
|
224
413
|
*/
|
|
@@ -235,6 +424,11 @@ class Agent {
|
|
|
235
424
|
});
|
|
236
425
|
const { effectiveContext } = responseContext;
|
|
237
426
|
session = responseContext.session;
|
|
427
|
+
// Merge agent's collected data into session (agent data takes precedence)
|
|
428
|
+
if (Object.keys(this.collectedData).length > 0) {
|
|
429
|
+
session = (0, utils_1.mergeCollected)(session, this.collectedData);
|
|
430
|
+
utils_1.logger.debug("[Agent] Merged agent collected data into session:", this.collectedData);
|
|
431
|
+
}
|
|
238
432
|
// Update our stored context if it was modified by beforeRespond hook
|
|
239
433
|
this.context = this.responsePipeline.getStoredContext();
|
|
240
434
|
// PHASE 1: PREPARE - Execute prepare function if current step has one
|
|
@@ -274,7 +468,7 @@ class Agent {
|
|
|
274
468
|
// Get last user message
|
|
275
469
|
const lastUserMessage = (0, utils_1.getLastMessageFromHistory)(history);
|
|
276
470
|
// Build response schema for this route (with collect fields from step)
|
|
277
|
-
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextStep);
|
|
471
|
+
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextStep, this.schema);
|
|
278
472
|
// Check if selected route and next step are defined
|
|
279
473
|
if (!selectedRoute || !nextStep) {
|
|
280
474
|
utils_1.logger.error("[Agent] Selected route or next step is not defined", {
|
|
@@ -301,6 +495,7 @@ class Agent {
|
|
|
301
495
|
combinedTerms: this.mergeTerms(this.getTerms(), selectedRoute.getTerms()),
|
|
302
496
|
context: effectiveContext,
|
|
303
497
|
session,
|
|
498
|
+
agentSchema: this.schema,
|
|
304
499
|
});
|
|
305
500
|
// Collect available tools for AI
|
|
306
501
|
const availableTools = this.collectAvailableTools(selectedRoute, nextStep);
|
|
@@ -336,6 +531,7 @@ class Agent {
|
|
|
336
531
|
tool: tool,
|
|
337
532
|
context: effectiveContext,
|
|
338
533
|
updateContext: this.updateContext.bind(this),
|
|
534
|
+
updateData: this.updateCollectedData.bind(this),
|
|
339
535
|
history,
|
|
340
536
|
data: session.data,
|
|
341
537
|
toolArguments: toolCall.arguments,
|
|
@@ -419,6 +615,7 @@ class Agent {
|
|
|
419
615
|
tool: tool,
|
|
420
616
|
context: effectiveContext,
|
|
421
617
|
updateContext: this.updateContext.bind(this),
|
|
618
|
+
updateData: this.updateCollectedData.bind(this),
|
|
422
619
|
history: updatedHistory,
|
|
423
620
|
data: session.data,
|
|
424
621
|
toolArguments: toolCall.arguments,
|
|
@@ -452,12 +649,16 @@ class Agent {
|
|
|
452
649
|
// The structured response includes both base fields and collected extraction fields
|
|
453
650
|
const structuredData = chunk.structured;
|
|
454
651
|
for (const field of nextStep.collect) {
|
|
455
|
-
|
|
456
|
-
|
|
652
|
+
const fieldKey = String(field);
|
|
653
|
+
if (fieldKey in structuredData) {
|
|
654
|
+
collectedData[fieldKey] = structuredData[fieldKey];
|
|
457
655
|
}
|
|
458
656
|
}
|
|
459
|
-
// Merge collected data into session
|
|
657
|
+
// Merge collected data into session using agent-level data validation
|
|
460
658
|
if (Object.keys(collectedData).length > 0) {
|
|
659
|
+
// Update agent-level collected data with validation
|
|
660
|
+
await this.updateCollectedData(collectedData);
|
|
661
|
+
// Update session with validated data
|
|
461
662
|
session = await this.updateData(session, collectedData);
|
|
462
663
|
utils_1.logger.debug(`[Agent] Collected data:`, collectedData);
|
|
463
664
|
}
|
|
@@ -520,7 +721,7 @@ class Agent {
|
|
|
520
721
|
"Summarize what was accomplished and confirm completion based on the conversation history and collected data",
|
|
521
722
|
});
|
|
522
723
|
// Build response schema for completion
|
|
523
|
-
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep);
|
|
724
|
+
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep, this.schema);
|
|
524
725
|
const templateContext = {
|
|
525
726
|
context: effectiveContext,
|
|
526
727
|
session,
|
|
@@ -544,6 +745,7 @@ class Agent {
|
|
|
544
745
|
combinedTerms: this.mergeTerms(this.getTerms(), selectedRoute.getTerms()),
|
|
545
746
|
context: effectiveContext,
|
|
546
747
|
session,
|
|
748
|
+
agentSchema: this.schema,
|
|
547
749
|
});
|
|
548
750
|
// Stream completion message using AI provider
|
|
549
751
|
const stream = this.options.provider.generateMessageStream({
|
|
@@ -669,6 +871,11 @@ class Agent {
|
|
|
669
871
|
let session = (0, utils_1.cloneDeep)(params.session) ||
|
|
670
872
|
(0, utils_1.cloneDeep)(this.currentSession) ||
|
|
671
873
|
(await this.session.getOrCreate());
|
|
874
|
+
// Merge agent's collected data into session (agent data takes precedence)
|
|
875
|
+
if (Object.keys(this.collectedData).length > 0) {
|
|
876
|
+
session = (0, utils_1.mergeCollected)(session, this.collectedData);
|
|
877
|
+
utils_1.logger.debug("[Agent] Merged agent collected data into session:", this.collectedData);
|
|
878
|
+
}
|
|
672
879
|
// PHASE 1: PREPARE - Execute prepare function if current step has one
|
|
673
880
|
if (session.currentRoute && session.currentStep) {
|
|
674
881
|
const currentRoute = this.routes.find((r) => r.id === session.currentRoute?.id);
|
|
@@ -766,7 +973,7 @@ class Agent {
|
|
|
766
973
|
// Get last user message
|
|
767
974
|
const lastUserMessage = (0, utils_1.getLastMessageFromHistory)(history);
|
|
768
975
|
// Build response schema for this route (with collect fields from step)
|
|
769
|
-
responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextStep);
|
|
976
|
+
responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextStep, this.schema);
|
|
770
977
|
// Build response prompt
|
|
771
978
|
responsePrompt = await this.responseEngine.buildResponsePrompt({
|
|
772
979
|
route: selectedRoute,
|
|
@@ -785,6 +992,7 @@ class Agent {
|
|
|
785
992
|
combinedTerms: this.mergeTerms(this.getTerms(), selectedRoute.getTerms()),
|
|
786
993
|
context: effectiveContext,
|
|
787
994
|
session,
|
|
995
|
+
agentSchema: this.schema,
|
|
788
996
|
});
|
|
789
997
|
// Collect available tools for AI
|
|
790
998
|
availableTools = this.collectAvailableTools(selectedRoute, nextStep);
|
|
@@ -802,7 +1010,7 @@ class Agent {
|
|
|
802
1010
|
session,
|
|
803
1011
|
});
|
|
804
1012
|
// Use agent-level tools only
|
|
805
|
-
availableTools =
|
|
1013
|
+
availableTools = this.collectAvailableTools();
|
|
806
1014
|
responseSchema = undefined;
|
|
807
1015
|
}
|
|
808
1016
|
// Generate message using AI provider (common for both route and no-route cases)
|
|
@@ -837,6 +1045,7 @@ class Agent {
|
|
|
837
1045
|
tool: tool,
|
|
838
1046
|
context: effectiveContext,
|
|
839
1047
|
updateContext: this.updateContext.bind(this),
|
|
1048
|
+
updateData: this.updateCollectedData.bind(this),
|
|
840
1049
|
history,
|
|
841
1050
|
data: session.data,
|
|
842
1051
|
toolArguments: toolCall.arguments,
|
|
@@ -915,6 +1124,7 @@ class Agent {
|
|
|
915
1124
|
tool: tool,
|
|
916
1125
|
context: effectiveContext,
|
|
917
1126
|
updateContext: this.updateContext.bind(this),
|
|
1127
|
+
updateData: this.updateCollectedData.bind(this),
|
|
918
1128
|
history: updatedHistory,
|
|
919
1129
|
data: session.data,
|
|
920
1130
|
toolArguments: toolCall.arguments,
|
|
@@ -949,12 +1159,16 @@ class Agent {
|
|
|
949
1159
|
// The structured response includes both base fields and collected extraction fields
|
|
950
1160
|
const structuredData = result.structured;
|
|
951
1161
|
for (const field of nextStep.collect) {
|
|
952
|
-
|
|
953
|
-
|
|
1162
|
+
const fieldKey = String(field);
|
|
1163
|
+
if (fieldKey in structuredData) {
|
|
1164
|
+
collectedData[fieldKey] = structuredData[fieldKey];
|
|
954
1165
|
}
|
|
955
1166
|
}
|
|
956
|
-
// Merge collected data into session
|
|
1167
|
+
// Merge collected data into session using agent-level data validation
|
|
957
1168
|
if (Object.keys(collectedData).length > 0) {
|
|
1169
|
+
// Update agent-level collected data with validation
|
|
1170
|
+
await this.updateCollectedData(collectedData);
|
|
1171
|
+
// Update session with validated data
|
|
958
1172
|
session = await this.updateData(session, collectedData);
|
|
959
1173
|
utils_1.logger.debug(`[Agent] Collected data:`, collectedData);
|
|
960
1174
|
}
|
|
@@ -980,16 +1194,16 @@ class Agent {
|
|
|
980
1194
|
prompt: endStepSpec.prompt ||
|
|
981
1195
|
"Summarize what was accomplished and confirm completion based on the conversation history and collected data",
|
|
982
1196
|
});
|
|
1197
|
+
if (!selectedRoute) {
|
|
1198
|
+
throw new Error("Selected route is not defined");
|
|
1199
|
+
}
|
|
983
1200
|
// Build response schema for completion
|
|
984
|
-
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep);
|
|
1201
|
+
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep, this.schema);
|
|
985
1202
|
const templateContext = {
|
|
986
1203
|
context: effectiveContext,
|
|
987
1204
|
session,
|
|
988
1205
|
history,
|
|
989
1206
|
};
|
|
990
|
-
if (!selectedRoute) {
|
|
991
|
-
throw new Error("Selected route is not defined");
|
|
992
|
-
}
|
|
993
1207
|
// Build completion response prompt
|
|
994
1208
|
const completionPrompt = await this.responseEngine.buildResponsePrompt({
|
|
995
1209
|
route: selectedRoute,
|
|
@@ -1008,6 +1222,7 @@ class Agent {
|
|
|
1008
1222
|
combinedTerms: this.mergeTerms(this.getTerms(), selectedRoute.getTerms()),
|
|
1009
1223
|
context: effectiveContext,
|
|
1010
1224
|
session,
|
|
1225
|
+
agentSchema: this.schema,
|
|
1011
1226
|
});
|
|
1012
1227
|
// Generate completion message using AI provider
|
|
1013
1228
|
const completionResult = await this.options.provider.generateMessage({
|
|
@@ -1253,6 +1468,7 @@ class Agent {
|
|
|
1253
1468
|
tool,
|
|
1254
1469
|
context,
|
|
1255
1470
|
updateContext: this.updateContext.bind(this),
|
|
1471
|
+
updateData: this.updateCollectedData.bind(this),
|
|
1256
1472
|
history: [], // Empty history for prepare/finalize
|
|
1257
1473
|
data,
|
|
1258
1474
|
});
|
|
@@ -1330,19 +1546,19 @@ class Agent {
|
|
|
1330
1546
|
this.currentSession = undefined;
|
|
1331
1547
|
}
|
|
1332
1548
|
/**
|
|
1333
|
-
* Get collected data from current session
|
|
1549
|
+
* Get collected data from current session or agent-level collected data
|
|
1334
1550
|
* @param routeId - Optional route ID to get data for (uses current route if not provided)
|
|
1335
|
-
* @returns The collected data from the current session
|
|
1551
|
+
* @returns The collected data from the current session or agent-level data
|
|
1336
1552
|
*/
|
|
1337
|
-
getData(
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
return (this.currentSession.
|
|
1343
|
-
{});
|
|
1553
|
+
getData() {
|
|
1554
|
+
// If we have a current session, use session data
|
|
1555
|
+
if (this.currentSession) {
|
|
1556
|
+
// With agent-level data, all routes share the same data structure
|
|
1557
|
+
// No need for route-specific data access
|
|
1558
|
+
return (this.currentSession.data) || {};
|
|
1344
1559
|
}
|
|
1345
|
-
return
|
|
1560
|
+
// Otherwise, return agent-level collected data
|
|
1561
|
+
return this.getCollectedData();
|
|
1346
1562
|
}
|
|
1347
1563
|
/**
|
|
1348
1564
|
* Manually transition to a different route
|
|
@@ -1385,14 +1601,14 @@ class Agent {
|
|
|
1385
1601
|
pendingTransition: {
|
|
1386
1602
|
targetRouteId: targetRoute.id,
|
|
1387
1603
|
condition: renderedCondition,
|
|
1388
|
-
reason: "
|
|
1604
|
+
reason: "route_complete",
|
|
1389
1605
|
},
|
|
1390
1606
|
};
|
|
1391
1607
|
// Update current session if using it
|
|
1392
1608
|
if (!session && this.currentSession) {
|
|
1393
1609
|
this.currentSession = updatedSession;
|
|
1394
1610
|
}
|
|
1395
|
-
utils_1.logger.debug(`[Agent] Set pending
|
|
1611
|
+
utils_1.logger.debug(`[Agent] Set pending transition to route: ${targetRoute.title}`);
|
|
1396
1612
|
return updatedSession;
|
|
1397
1613
|
}
|
|
1398
1614
|
/**
|
|
@@ -1414,7 +1630,14 @@ class Agent {
|
|
|
1414
1630
|
history = this.session.getHistory();
|
|
1415
1631
|
}
|
|
1416
1632
|
// Get or create session
|
|
1417
|
-
|
|
1633
|
+
let session = await this.session.getOrCreate();
|
|
1634
|
+
// Merge agent's collected data into session (agent data takes precedence)
|
|
1635
|
+
if (Object.keys(this.collectedData).length > 0) {
|
|
1636
|
+
session = (0, utils_1.mergeCollected)(session, this.collectedData);
|
|
1637
|
+
// Update the session manager with the merged data
|
|
1638
|
+
await this.session.setData(this.collectedData);
|
|
1639
|
+
utils_1.logger.debug("[Agent] Merged agent collected data into chat session:", this.collectedData);
|
|
1640
|
+
}
|
|
1418
1641
|
// Use existing respond method with session-managed history
|
|
1419
1642
|
const result = await this.respond({
|
|
1420
1643
|
history,
|
|
@@ -1426,7 +1649,11 @@ class Agent {
|
|
|
1426
1649
|
if (!options?.history) {
|
|
1427
1650
|
await this.session.addMessage("assistant", result.message);
|
|
1428
1651
|
}
|
|
1429
|
-
|
|
1652
|
+
// Ensure the result includes the current session
|
|
1653
|
+
return {
|
|
1654
|
+
...result,
|
|
1655
|
+
session: result.session || this.session.current,
|
|
1656
|
+
};
|
|
1430
1657
|
}
|
|
1431
1658
|
}
|
|
1432
1659
|
exports.Agent = Agent;
|