@falai/agent 0.6.8 → 0.7.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 +62 -59
- package/dist/adapters/MemoryAdapter.js +2 -2
- package/dist/adapters/MemoryAdapter.js.map +1 -1
- package/dist/adapters/MongoAdapter.js +2 -2
- package/dist/adapters/MongoAdapter.js.map +1 -1
- package/dist/adapters/OpenSearchAdapter.js +7 -7
- package/dist/adapters/OpenSearchAdapter.js.map +1 -1
- package/dist/adapters/PostgreSQLAdapter.js +9 -9
- package/dist/adapters/PostgreSQLAdapter.js.map +1 -1
- package/dist/adapters/PrismaAdapter.js +3 -3
- package/dist/adapters/PrismaAdapter.js.map +1 -1
- package/dist/adapters/RedisAdapter.js +2 -2
- package/dist/adapters/RedisAdapter.js.map +1 -1
- package/dist/adapters/SQLiteAdapter.d.ts +3 -3
- package/dist/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/dist/adapters/SQLiteAdapter.js +11 -11
- package/dist/adapters/SQLiteAdapter.js.map +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/cjs/adapters/MemoryAdapter.js +2 -2
- package/dist/cjs/adapters/MemoryAdapter.js.map +1 -1
- package/dist/cjs/adapters/MongoAdapter.js +2 -2
- package/dist/cjs/adapters/MongoAdapter.js.map +1 -1
- package/dist/cjs/adapters/OpenSearchAdapter.js +7 -7
- package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -1
- package/dist/cjs/adapters/PostgreSQLAdapter.js +9 -9
- package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -1
- package/dist/cjs/adapters/PrismaAdapter.js +3 -3
- package/dist/cjs/adapters/PrismaAdapter.js.map +1 -1
- package/dist/cjs/adapters/RedisAdapter.js +2 -2
- package/dist/cjs/adapters/RedisAdapter.js.map +1 -1
- package/dist/cjs/adapters/SQLiteAdapter.d.ts +3 -3
- package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/SQLiteAdapter.js +11 -11
- package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -1
- package/dist/cjs/adapters/index.d.ts +1 -1
- package/dist/cjs/adapters/index.d.ts.map +1 -1
- package/dist/cjs/constants/index.d.ts +4 -4
- package/dist/cjs/constants/index.js +5 -5
- package/dist/cjs/core/Agent.d.ts +22 -22
- package/dist/cjs/core/Agent.d.ts.map +1 -1
- package/dist/cjs/core/Agent.js +160 -152
- package/dist/cjs/core/Agent.js.map +1 -1
- package/dist/cjs/core/Events.d.ts +6 -6
- package/dist/cjs/core/Events.d.ts.map +1 -1
- package/dist/cjs/core/PersistenceManager.d.ts +13 -13
- package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
- package/dist/cjs/core/PersistenceManager.js +24 -24
- package/dist/cjs/core/PersistenceManager.js.map +1 -1
- package/dist/cjs/core/ResponseEngine.d.ts +3 -8
- package/dist/cjs/core/ResponseEngine.d.ts.map +1 -1
- package/dist/cjs/core/ResponseEngine.js +8 -8
- package/dist/cjs/core/ResponseEngine.js.map +1 -1
- package/dist/cjs/core/Route.d.ts +17 -17
- package/dist/cjs/core/Route.d.ts.map +1 -1
- package/dist/cjs/core/Route.js +33 -33
- package/dist/cjs/core/Route.js.map +1 -1
- package/dist/cjs/core/RoutingEngine.d.ts +30 -30
- package/dist/cjs/core/RoutingEngine.d.ts.map +1 -1
- package/dist/cjs/core/RoutingEngine.js +192 -192
- package/dist/cjs/core/RoutingEngine.js.map +1 -1
- package/dist/cjs/core/Step.d.ts +72 -0
- package/dist/cjs/core/Step.d.ts.map +1 -0
- package/dist/cjs/core/Step.js +150 -0
- package/dist/cjs/core/Step.js.map +1 -0
- package/dist/cjs/core/ToolExecutor.d.ts +5 -5
- package/dist/cjs/core/ToolExecutor.d.ts.map +1 -1
- package/dist/cjs/core/ToolExecutor.js +8 -8
- package/dist/cjs/core/ToolExecutor.js.map +1 -1
- package/dist/cjs/core/Transition.d.ts +14 -14
- package/dist/cjs/core/Transition.d.ts.map +1 -1
- package/dist/cjs/core/Transition.js +48 -19
- package/dist/cjs/core/Transition.js.map +1 -1
- package/dist/cjs/index.d.ts +7 -7
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +8 -8
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/agent.d.ts +8 -8
- package/dist/cjs/types/agent.d.ts.map +1 -1
- package/dist/cjs/types/ai.d.ts +2 -2
- package/dist/cjs/types/ai.d.ts.map +1 -1
- package/dist/cjs/types/history.d.ts +3 -3
- package/dist/cjs/types/history.d.ts.map +1 -1
- package/dist/cjs/types/index.d.ts +1 -1
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/persistence.d.ts +5 -5
- package/dist/cjs/types/persistence.d.ts.map +1 -1
- package/dist/cjs/types/route.d.ts +57 -52
- package/dist/cjs/types/route.d.ts.map +1 -1
- package/dist/cjs/types/session.d.ts +27 -27
- package/dist/cjs/types/session.d.ts.map +1 -1
- package/dist/cjs/types/session.js +48 -50
- package/dist/cjs/types/session.js.map +1 -1
- package/dist/cjs/types/tool.d.ts +13 -13
- package/dist/cjs/types/tool.d.ts.map +1 -1
- package/dist/cjs/utils/id.d.ts +8 -3
- package/dist/cjs/utils/id.d.ts.map +1 -1
- package/dist/cjs/utils/id.js +16 -7
- package/dist/cjs/utils/id.js.map +1 -1
- package/dist/constants/index.d.ts +4 -4
- package/dist/constants/index.js +4 -4
- package/dist/core/Agent.d.ts +22 -22
- package/dist/core/Agent.d.ts.map +1 -1
- package/dist/core/Agent.js +162 -154
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/Events.d.ts +6 -6
- package/dist/core/Events.d.ts.map +1 -1
- package/dist/core/PersistenceManager.d.ts +13 -13
- package/dist/core/PersistenceManager.d.ts.map +1 -1
- package/dist/core/PersistenceManager.js +25 -25
- package/dist/core/PersistenceManager.js.map +1 -1
- package/dist/core/ResponseEngine.d.ts +3 -8
- package/dist/core/ResponseEngine.d.ts.map +1 -1
- package/dist/core/ResponseEngine.js +8 -8
- package/dist/core/ResponseEngine.js.map +1 -1
- package/dist/core/Route.d.ts +17 -17
- package/dist/core/Route.d.ts.map +1 -1
- package/dist/core/Route.js +33 -33
- package/dist/core/Route.js.map +1 -1
- package/dist/core/RoutingEngine.d.ts +30 -30
- package/dist/core/RoutingEngine.d.ts.map +1 -1
- package/dist/core/RoutingEngine.js +193 -193
- package/dist/core/RoutingEngine.js.map +1 -1
- package/dist/core/Step.d.ts +72 -0
- package/dist/core/Step.d.ts.map +1 -0
- package/dist/core/Step.js +146 -0
- package/dist/core/Step.js.map +1 -0
- package/dist/core/ToolExecutor.d.ts +5 -5
- package/dist/core/ToolExecutor.d.ts.map +1 -1
- package/dist/core/ToolExecutor.js +8 -8
- package/dist/core/ToolExecutor.js.map +1 -1
- package/dist/core/Transition.d.ts +14 -14
- package/dist/core/Transition.d.ts.map +1 -1
- package/dist/core/Transition.js +48 -19
- package/dist/core/Transition.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/types/agent.d.ts +8 -8
- package/dist/types/agent.d.ts.map +1 -1
- package/dist/types/ai.d.ts +2 -2
- package/dist/types/ai.d.ts.map +1 -1
- package/dist/types/history.d.ts +3 -3
- package/dist/types/history.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/persistence.d.ts +5 -5
- package/dist/types/persistence.d.ts.map +1 -1
- package/dist/types/route.d.ts +57 -52
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/session.d.ts +27 -27
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js +44 -46
- package/dist/types/session.js.map +1 -1
- package/dist/types/tool.d.ts +13 -13
- package/dist/types/tool.d.ts.map +1 -1
- package/dist/utils/id.d.ts +8 -3
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +14 -6
- package/dist/utils/id.js.map +1 -1
- package/docs/ADAPTERS.md +21 -21
- package/docs/AGENT.md +57 -55
- package/docs/API_REFERENCE.md +218 -220
- package/docs/ARCHITECTURE.md +99 -104
- package/docs/CONTEXT_MANAGEMENT.md +81 -88
- package/docs/DOCS.md +18 -18
- package/docs/DOMAINS.md +16 -16
- package/docs/EXAMPLES.md +43 -43
- package/docs/GETTING_STARTED.md +60 -63
- package/docs/PERSISTENCE.md +66 -70
- package/docs/PROVIDERS.md +2 -2
- package/docs/README.md +6 -6
- package/docs/ROUTES.md +218 -220
- package/docs/STEPS.md +883 -0
- package/examples/business-onboarding.ts +84 -81
- package/examples/company-qna-agent.ts +68 -67
- package/examples/custom-database-persistence.ts +87 -89
- package/examples/declarative-agent.ts +32 -32
- package/examples/domain-scoping.ts +18 -18
- package/examples/extracted-data-modification.ts +92 -97
- package/examples/healthcare-agent.ts +89 -91
- package/examples/openai-agent.ts +29 -32
- package/examples/opensearch-persistence.ts +43 -45
- package/examples/persistent-onboarding.ts +65 -66
- package/examples/prisma-persistence.ts +108 -112
- package/examples/prisma-schema.example.prisma +3 -3
- package/examples/redis-persistence.ts +67 -73
- package/examples/route-transitions.ts +71 -47
- package/examples/rules-prohibitions.ts +28 -28
- package/examples/streaming-agent.ts +24 -24
- package/examples/travel-agent.ts +94 -109
- package/package.json +1 -1
- package/src/adapters/MemoryAdapter.ts +3 -3
- package/src/adapters/MongoAdapter.ts +3 -3
- package/src/adapters/OpenSearchAdapter.ts +8 -8
- package/src/adapters/PostgreSQLAdapter.ts +10 -10
- package/src/adapters/PrismaAdapter.ts +4 -4
- package/src/adapters/RedisAdapter.ts +3 -3
- package/src/adapters/SQLiteAdapter.ts +15 -15
- package/src/adapters/index.ts +1 -1
- package/src/constants/index.ts +4 -4
- package/src/core/Agent.ts +210 -206
- package/src/core/Events.ts +12 -12
- package/src/core/PersistenceManager.ts +32 -36
- package/src/core/ResponseEngine.ts +11 -17
- package/src/core/Route.ts +55 -49
- package/src/core/RoutingEngine.ts +244 -252
- package/src/core/Step.ts +197 -0
- package/src/core/ToolExecutor.ts +11 -11
- package/src/core/Transition.ts +72 -26
- package/src/index.ts +8 -8
- package/src/types/agent.ts +8 -8
- package/src/types/ai.ts +2 -2
- package/src/types/history.ts +3 -3
- package/src/types/index.ts +1 -1
- package/src/types/persistence.ts +6 -6
- package/src/types/route.ts +77 -61
- package/src/types/session.ts +75 -78
- package/src/types/tool.ts +17 -17
- package/src/utils/id.ts +15 -6
- package/dist/cjs/core/State.d.ts +0 -72
- package/dist/cjs/core/State.d.ts.map +0 -1
- package/dist/cjs/core/State.js +0 -148
- package/dist/cjs/core/State.js.map +0 -1
- package/dist/core/State.d.ts +0 -72
- package/dist/core/State.d.ts.map +0 -1
- package/dist/core/State.js +0 -144
- package/dist/core/State.js.map +0 -1
- package/docs/STATES.md +0 -888
- package/src/core/State.ts +0 -212
package/dist/core/Agent.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Core Agent implementation
|
|
3
3
|
*/
|
|
4
|
-
import { createSession, enterRoute,
|
|
4
|
+
import { createSession, enterRoute, enterStep, mergeCollected, } from "../types/session";
|
|
5
5
|
import { PromptComposer } from "./PromptComposer";
|
|
6
6
|
import { logger, LoggerLevel } from "../utils/logger";
|
|
7
7
|
import { Route } from "./Route";
|
|
8
|
-
import {
|
|
8
|
+
import { Step } from "./Step";
|
|
9
9
|
import { DomainRegistry } from "./DomainRegistry";
|
|
10
10
|
import { PersistenceManager } from "./PersistenceManager";
|
|
11
11
|
import { RoutingEngine } from "./RoutingEngine";
|
|
12
12
|
import { ResponseEngine } from "./ResponseEngine";
|
|
13
13
|
import { ToolExecutor } from "./ToolExecutor";
|
|
14
14
|
import { getLastMessageFromHistory } from "../utils/event";
|
|
15
|
-
import {
|
|
15
|
+
import { END_ROUTE_ID } from "../constants";
|
|
16
16
|
/**
|
|
17
17
|
* Main Agent class with generic context support
|
|
18
18
|
*/
|
|
@@ -98,7 +98,7 @@ export class Agent {
|
|
|
98
98
|
}
|
|
99
99
|
/**
|
|
100
100
|
* Create a new route (journey)
|
|
101
|
-
* @template
|
|
101
|
+
* @template TData - Type of data collected throughout the route
|
|
102
102
|
*/
|
|
103
103
|
createRoute(options) {
|
|
104
104
|
const route = new Route(options);
|
|
@@ -175,23 +175,23 @@ export class Agent {
|
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
/**
|
|
178
|
-
* Update
|
|
179
|
-
* Triggers the
|
|
178
|
+
* Update collected data in session with lifecycle hook support
|
|
179
|
+
* Triggers the onDataUpdate lifecycle hook if configured
|
|
180
180
|
* @internal
|
|
181
181
|
*/
|
|
182
|
-
async
|
|
183
|
-
const
|
|
184
|
-
// Merge new
|
|
185
|
-
let
|
|
186
|
-
...session.
|
|
187
|
-
...
|
|
182
|
+
async updateData(session, collectedUpdate) {
|
|
183
|
+
const previousCollected = { ...session.data };
|
|
184
|
+
// Merge new collected data
|
|
185
|
+
let newCollected = {
|
|
186
|
+
...session.data,
|
|
187
|
+
...collectedUpdate,
|
|
188
188
|
};
|
|
189
189
|
// Trigger lifecycle hook if configured
|
|
190
|
-
if (this.options.hooks?.
|
|
191
|
-
|
|
190
|
+
if (this.options.hooks?.onDataUpdate) {
|
|
191
|
+
newCollected = (await this.options.hooks.onDataUpdate(newCollected, previousCollected));
|
|
192
192
|
}
|
|
193
193
|
// Return updated session
|
|
194
|
-
return
|
|
194
|
+
return mergeCollected(session, newCollected);
|
|
195
195
|
}
|
|
196
196
|
/**
|
|
197
197
|
* Get current context (fetches from provider if configured)
|
|
@@ -225,37 +225,37 @@ export class Agent {
|
|
|
225
225
|
};
|
|
226
226
|
// Initialize or get session (use current session if available)
|
|
227
227
|
let session = params.session || this.currentSession || createSession();
|
|
228
|
-
// PHASE 1: TOOL EXECUTION - Execute tools if current
|
|
229
|
-
if (session.currentRoute && session.
|
|
228
|
+
// PHASE 1: TOOL EXECUTION - Execute tools if current step has tool
|
|
229
|
+
if (session.currentRoute && session.currentStep) {
|
|
230
230
|
const currentRoute = this.routes.find((r) => r.id === session.currentRoute?.id);
|
|
231
231
|
if (currentRoute) {
|
|
232
|
-
const
|
|
233
|
-
if (
|
|
234
|
-
const transitions =
|
|
235
|
-
const toolTransition = transitions.find((t) => t.spec.
|
|
236
|
-
if (toolTransition?.spec.
|
|
232
|
+
const currentStep = currentRoute.getStep(session.currentStep.id);
|
|
233
|
+
if (currentStep) {
|
|
234
|
+
const transitions = currentStep.getTransitions();
|
|
235
|
+
const toolTransition = transitions.find((t) => t.spec.tool);
|
|
236
|
+
if (toolTransition?.spec.tool) {
|
|
237
237
|
const toolExecutor = new ToolExecutor();
|
|
238
238
|
// Get allowed domains from current route for security enforcement
|
|
239
239
|
const allowedDomains = currentRoute.getDomains();
|
|
240
|
-
const result = await toolExecutor.executeTool(toolTransition.spec.
|
|
240
|
+
const result = await toolExecutor.executeTool(toolTransition.spec.tool, effectiveContext, this.updateContext.bind(this), history, session.data, allowedDomains);
|
|
241
241
|
// Update context with tool results
|
|
242
242
|
if (result.contextUpdate) {
|
|
243
243
|
await this.updateContext(result.contextUpdate);
|
|
244
244
|
}
|
|
245
|
-
// Update
|
|
246
|
-
if (result.
|
|
247
|
-
session = await this.
|
|
248
|
-
logger.debug(`[Agent] Tool updated
|
|
245
|
+
// Update collected data with tool results
|
|
246
|
+
if (result.collectedUpdate) {
|
|
247
|
+
session = await this.updateData(session, result.collectedUpdate);
|
|
248
|
+
logger.debug(`[Agent] Tool updated collected data:`, result.collectedUpdate);
|
|
249
249
|
}
|
|
250
250
|
logger.debug(`[Agent] Executed tool: ${result.toolName} (success: ${result.success})`);
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
253
|
}
|
|
254
254
|
}
|
|
255
|
-
// PHASE 2: ROUTING +
|
|
255
|
+
// PHASE 2: ROUTING + STEP SELECTION - Determine which route and step to use (combined)
|
|
256
256
|
let selectedRoute;
|
|
257
257
|
let responseDirectives;
|
|
258
|
-
let
|
|
258
|
+
let selectedStep;
|
|
259
259
|
let isRouteComplete = false;
|
|
260
260
|
// Check for pending transition from previous route completion
|
|
261
261
|
if (session.pendingTransition) {
|
|
@@ -270,7 +270,7 @@ export class Agent {
|
|
|
270
270
|
session = enterRoute(session, targetRoute.id, targetRoute.title);
|
|
271
271
|
// Merge initial data if available
|
|
272
272
|
if (targetRoute.initialData) {
|
|
273
|
-
session =
|
|
273
|
+
session = mergeCollected(session, targetRoute.initialData);
|
|
274
274
|
}
|
|
275
275
|
selectedRoute = targetRoute;
|
|
276
276
|
}
|
|
@@ -285,7 +285,7 @@ export class Agent {
|
|
|
285
285
|
}
|
|
286
286
|
// If no pending transition or transition handled, do normal routing
|
|
287
287
|
if (this.routes.length > 0 && !selectedRoute) {
|
|
288
|
-
const orchestration = await this.routingEngine.
|
|
288
|
+
const orchestration = await this.routingEngine.decideRouteAndStep({
|
|
289
289
|
routes: this.routes,
|
|
290
290
|
session,
|
|
291
291
|
history,
|
|
@@ -300,45 +300,45 @@ export class Agent {
|
|
|
300
300
|
signal,
|
|
301
301
|
});
|
|
302
302
|
selectedRoute = orchestration.selectedRoute;
|
|
303
|
-
|
|
303
|
+
selectedStep = orchestration.selectedStep;
|
|
304
304
|
responseDirectives = orchestration.responseDirectives;
|
|
305
305
|
session = orchestration.session;
|
|
306
306
|
isRouteComplete = orchestration.isRouteComplete || false;
|
|
307
307
|
// Log if route is complete
|
|
308
308
|
if (isRouteComplete) {
|
|
309
|
-
logger.debug(`[Agent] Route complete: all required data collected,
|
|
309
|
+
logger.debug(`[Agent] Route complete: all required data collected, END_ROUTE reached`);
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
|
-
// PHASE 3: DETERMINE NEXT
|
|
312
|
+
// PHASE 3: DETERMINE NEXT STEP - Use step from combined decision or get initial step
|
|
313
313
|
if (selectedRoute && !isRouteComplete) {
|
|
314
|
-
let
|
|
315
|
-
// If we have a selected
|
|
316
|
-
if (
|
|
317
|
-
|
|
314
|
+
let nextStep;
|
|
315
|
+
// If we have a selected step from the combined routing decision, use it
|
|
316
|
+
if (selectedStep) {
|
|
317
|
+
nextStep = selectedStep;
|
|
318
318
|
}
|
|
319
319
|
else {
|
|
320
|
-
// New route or no
|
|
321
|
-
const candidates = this.routingEngine.
|
|
320
|
+
// New route or no step selected - get initial step or first valid step
|
|
321
|
+
const candidates = this.routingEngine.getCandidateSteps(selectedRoute, undefined, session.data || {});
|
|
322
322
|
if (candidates.length > 0) {
|
|
323
|
-
|
|
324
|
-
logger.debug(`[Agent] Using first valid
|
|
323
|
+
nextStep = candidates[0].step;
|
|
324
|
+
logger.debug(`[Agent] Using first valid step: ${nextStep.id} for new route`);
|
|
325
325
|
}
|
|
326
326
|
else {
|
|
327
|
-
// Fallback to initial
|
|
328
|
-
|
|
329
|
-
logger.warn(`[Agent] No valid
|
|
327
|
+
// Fallback to initial step even if it should be skipped
|
|
328
|
+
nextStep = selectedRoute.initialStep;
|
|
329
|
+
logger.warn(`[Agent] No valid steps found, using initial step: ${nextStep.id}`);
|
|
330
330
|
}
|
|
331
331
|
}
|
|
332
|
-
// Update session with next
|
|
333
|
-
session =
|
|
334
|
-
logger.debug(`[Agent] Entered
|
|
335
|
-
// PHASE 4: RESPONSE GENERATION - Stream message using selected route and
|
|
332
|
+
// Update session with next step
|
|
333
|
+
session = enterStep(session, nextStep.id, nextStep.description);
|
|
334
|
+
logger.debug(`[Agent] Entered step: ${nextStep.id}`);
|
|
335
|
+
// PHASE 4: RESPONSE GENERATION - Stream message using selected route and step
|
|
336
336
|
// Get last user message
|
|
337
337
|
const lastUserMessage = getLastMessageFromHistory(history);
|
|
338
|
-
// Build response schema for this route (with
|
|
339
|
-
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute,
|
|
338
|
+
// Build response schema for this route (with collect fields from step)
|
|
339
|
+
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextStep);
|
|
340
340
|
// Build response prompt
|
|
341
|
-
const responsePrompt = this.responseEngine.buildResponsePrompt(selectedRoute,
|
|
341
|
+
const responsePrompt = this.responseEngine.buildResponsePrompt(selectedRoute, nextStep, selectedRoute.getRules(), selectedRoute.getProhibitions(), responseDirectives, history, lastUserMessage, {
|
|
342
342
|
name: this.options.name,
|
|
343
343
|
goal: this.options.goal,
|
|
344
344
|
description: this.options.description,
|
|
@@ -358,20 +358,20 @@ export class Agent {
|
|
|
358
358
|
// Stream chunks to caller
|
|
359
359
|
for await (const chunk of stream) {
|
|
360
360
|
const toolCalls = undefined;
|
|
361
|
-
// Extract
|
|
362
|
-
if (chunk.done && chunk.structured &&
|
|
363
|
-
const
|
|
364
|
-
// The structured response includes both base fields and
|
|
361
|
+
// Extract collected data on final chunk
|
|
362
|
+
if (chunk.done && chunk.structured && nextStep.collectFields) {
|
|
363
|
+
const collectedData = {};
|
|
364
|
+
// The structured response includes both base fields and collected extraction fields
|
|
365
365
|
const structuredData = chunk.structured;
|
|
366
|
-
for (const field of
|
|
366
|
+
for (const field of nextStep.collectFields) {
|
|
367
367
|
if (field in structuredData) {
|
|
368
|
-
|
|
368
|
+
collectedData[field] = structuredData[field];
|
|
369
369
|
}
|
|
370
370
|
}
|
|
371
|
-
// Merge
|
|
372
|
-
if (Object.keys(
|
|
373
|
-
session = await this.
|
|
374
|
-
logger.debug(`[Agent]
|
|
371
|
+
// Merge collected data into session
|
|
372
|
+
if (Object.keys(collectedData).length > 0) {
|
|
373
|
+
session = await this.updateData(session, collectedData);
|
|
374
|
+
logger.debug(`[Agent] Collected data:`, collectedData);
|
|
375
375
|
}
|
|
376
376
|
}
|
|
377
377
|
// Extract any additional data from structured response on final chunk
|
|
@@ -382,13 +382,13 @@ export class Agent {
|
|
|
382
382
|
await this.updateContext(chunk.structured
|
|
383
383
|
.contextUpdate);
|
|
384
384
|
}
|
|
385
|
-
// Auto-save session
|
|
385
|
+
// Auto-save session step on final chunk
|
|
386
386
|
if (chunk.done &&
|
|
387
387
|
this.persistenceManager &&
|
|
388
388
|
session.id &&
|
|
389
389
|
this.options.persistence?.autoSave !== false) {
|
|
390
|
-
await this.persistenceManager.
|
|
391
|
-
logger.debug(`[Agent] Auto-saved session
|
|
390
|
+
await this.persistenceManager.saveSessionStep(session.id, session);
|
|
391
|
+
logger.debug(`[Agent] Auto-saved session step to persistence: ${session.id}`);
|
|
392
392
|
}
|
|
393
393
|
// Update current session if we have one
|
|
394
394
|
if (chunk.done && this.currentSession) {
|
|
@@ -407,14 +407,16 @@ export class Agent {
|
|
|
407
407
|
else if (isRouteComplete && selectedRoute) {
|
|
408
408
|
// Route is complete - generate completion message then check for onComplete transition
|
|
409
409
|
const lastUserMessage = getLastMessageFromHistory(history);
|
|
410
|
-
// Get
|
|
411
|
-
const
|
|
412
|
-
// Create a temporary
|
|
413
|
-
const
|
|
410
|
+
// Get endStep spec from route
|
|
411
|
+
const endStepSpec = selectedRoute.endStepSpec;
|
|
412
|
+
// Create a temporary step for completion message generation using endStep configuration
|
|
413
|
+
const completionStep = new Step(selectedRoute.id, endStepSpec.instructions ||
|
|
414
|
+
"Summarize what was accomplished and confirm completion", endStepSpec.id || END_ROUTE_ID, endStepSpec.collect, undefined, endStepSpec.requires, endStepSpec.instructions ||
|
|
415
|
+
"Summarize what was accomplished and confirm completion based on the conversation history and collected data");
|
|
414
416
|
// Build response schema for completion
|
|
415
|
-
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute,
|
|
417
|
+
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep);
|
|
416
418
|
// Build completion response prompt
|
|
417
|
-
const completionPrompt = this.responseEngine.buildResponsePrompt(selectedRoute,
|
|
419
|
+
const completionPrompt = this.responseEngine.buildResponsePrompt(selectedRoute, completionStep, selectedRoute.getRules(), selectedRoute.getProhibitions(), undefined, // No directives for completion
|
|
418
420
|
history, lastUserMessage, {
|
|
419
421
|
name: this.options.name,
|
|
420
422
|
goal: this.options.goal,
|
|
@@ -434,11 +436,11 @@ export class Agent {
|
|
|
434
436
|
});
|
|
435
437
|
logger.debug(`[Agent] Streaming completion message for route: ${selectedRoute.title}`);
|
|
436
438
|
// Check for onComplete transition
|
|
437
|
-
const transitionConfig = await selectedRoute.evaluateOnComplete({
|
|
439
|
+
const transitionConfig = await selectedRoute.evaluateOnComplete({ data: session.data }, effectiveContext);
|
|
438
440
|
if (transitionConfig) {
|
|
439
441
|
// Find target route by ID or title
|
|
440
|
-
const targetRoute = this.routes.find((r) => r.id === transitionConfig.
|
|
441
|
-
r.title === transitionConfig.
|
|
442
|
+
const targetRoute = this.routes.find((r) => r.id === transitionConfig.nextStep ||
|
|
443
|
+
r.title === transitionConfig.nextStep);
|
|
442
444
|
if (targetRoute) {
|
|
443
445
|
// Set pending transition in session
|
|
444
446
|
session = {
|
|
@@ -452,12 +454,12 @@ export class Agent {
|
|
|
452
454
|
logger.debug(`[Agent] Route ${selectedRoute.title} completed with pending transition to: ${targetRoute.title}`);
|
|
453
455
|
}
|
|
454
456
|
else {
|
|
455
|
-
logger.warn(`[Agent] Route ${selectedRoute.title} completed but target route not found: ${transitionConfig.
|
|
457
|
+
logger.warn(`[Agent] Route ${selectedRoute.title} completed but target route not found: ${transitionConfig.nextStep}`);
|
|
456
458
|
}
|
|
457
459
|
}
|
|
458
|
-
// Set
|
|
459
|
-
session =
|
|
460
|
-
logger.debug(`[Agent] Route ${selectedRoute.title} completed. Entered
|
|
460
|
+
// Set step to END_ROUTE marker
|
|
461
|
+
session = enterStep(session, END_ROUTE_ID, "Route completed");
|
|
462
|
+
logger.debug(`[Agent] Route ${selectedRoute.title} completed. Entered END_ROUTE step.`);
|
|
461
463
|
// Stream completion chunks
|
|
462
464
|
for await (const chunk of stream) {
|
|
463
465
|
// Update current session if we have one
|
|
@@ -541,37 +543,37 @@ export class Agent {
|
|
|
541
543
|
};
|
|
542
544
|
// Initialize or get session (use current session if available)
|
|
543
545
|
let session = params.session || this.currentSession || createSession();
|
|
544
|
-
// PHASE 1: TOOL EXECUTION - Execute tools if current
|
|
545
|
-
if (session.currentRoute && session.
|
|
546
|
+
// PHASE 1: TOOL EXECUTION - Execute tools if current step has tool
|
|
547
|
+
if (session.currentRoute && session.currentStep) {
|
|
546
548
|
const currentRoute = this.routes.find((r) => r.id === session.currentRoute?.id);
|
|
547
549
|
if (currentRoute) {
|
|
548
|
-
const
|
|
549
|
-
if (
|
|
550
|
-
const transitions =
|
|
551
|
-
const toolTransition = transitions.find((t) => t.spec.
|
|
552
|
-
if (toolTransition?.spec.
|
|
550
|
+
const currentStep = currentRoute.getStep(session.currentStep.id);
|
|
551
|
+
if (currentStep) {
|
|
552
|
+
const transitions = currentStep.getTransitions();
|
|
553
|
+
const toolTransition = transitions.find((t) => t.spec.tool);
|
|
554
|
+
if (toolTransition?.spec.tool) {
|
|
553
555
|
const toolExecutor = new ToolExecutor();
|
|
554
556
|
// Get allowed domains from current route for security enforcement
|
|
555
557
|
const allowedDomains = currentRoute.getDomains();
|
|
556
|
-
const result = await toolExecutor.executeTool(toolTransition.spec.
|
|
558
|
+
const result = await toolExecutor.executeTool(toolTransition.spec.tool, effectiveContext, this.updateContext.bind(this), history, session.data, allowedDomains);
|
|
557
559
|
// Update context with tool results
|
|
558
560
|
if (result.contextUpdate) {
|
|
559
561
|
await this.updateContext(result.contextUpdate);
|
|
560
562
|
}
|
|
561
|
-
// Update
|
|
562
|
-
if (result.
|
|
563
|
-
session = await this.
|
|
564
|
-
logger.debug(`[Agent] Tool updated
|
|
563
|
+
// Update collected data with tool results
|
|
564
|
+
if (result.collectedUpdate) {
|
|
565
|
+
session = await this.updateData(session, result.collectedUpdate);
|
|
566
|
+
logger.debug(`[Agent] Tool updated collected data:`, result.collectedUpdate);
|
|
565
567
|
}
|
|
566
568
|
logger.debug(`[Agent] Executed tool: ${result.toolName} (success: ${result.success})`);
|
|
567
569
|
}
|
|
568
570
|
}
|
|
569
571
|
}
|
|
570
572
|
}
|
|
571
|
-
// PHASE 2: ROUTING +
|
|
573
|
+
// PHASE 2: ROUTING + STEP SELECTION - Determine which route and step to use (combined)
|
|
572
574
|
let selectedRoute;
|
|
573
575
|
let responseDirectives;
|
|
574
|
-
let
|
|
576
|
+
let selectedStep;
|
|
575
577
|
let isRouteComplete = false;
|
|
576
578
|
// Check for pending transition from previous route completion
|
|
577
579
|
if (session.pendingTransition) {
|
|
@@ -586,7 +588,7 @@ export class Agent {
|
|
|
586
588
|
session = enterRoute(session, targetRoute.id, targetRoute.title);
|
|
587
589
|
// Merge initial data if available
|
|
588
590
|
if (targetRoute.initialData) {
|
|
589
|
-
session =
|
|
591
|
+
session = mergeCollected(session, targetRoute.initialData);
|
|
590
592
|
}
|
|
591
593
|
selectedRoute = targetRoute;
|
|
592
594
|
}
|
|
@@ -601,7 +603,7 @@ export class Agent {
|
|
|
601
603
|
}
|
|
602
604
|
// If no pending transition or transition handled, do normal routing
|
|
603
605
|
if (this.routes.length > 0 && !selectedRoute) {
|
|
604
|
-
const orchestration = await this.routingEngine.
|
|
606
|
+
const orchestration = await this.routingEngine.decideRouteAndStep({
|
|
605
607
|
routes: this.routes,
|
|
606
608
|
session,
|
|
607
609
|
history,
|
|
@@ -616,47 +618,47 @@ export class Agent {
|
|
|
616
618
|
signal,
|
|
617
619
|
});
|
|
618
620
|
selectedRoute = orchestration.selectedRoute;
|
|
619
|
-
|
|
621
|
+
selectedStep = orchestration.selectedStep;
|
|
620
622
|
responseDirectives = orchestration.responseDirectives;
|
|
621
623
|
session = orchestration.session;
|
|
622
624
|
isRouteComplete = orchestration.isRouteComplete || false;
|
|
623
625
|
// Log if route is complete
|
|
624
626
|
if (isRouteComplete) {
|
|
625
|
-
logger.debug(`[Agent] Route complete: all required data collected,
|
|
627
|
+
logger.debug(`[Agent] Route complete: all required data collected, END_ROUTE reached`);
|
|
626
628
|
}
|
|
627
629
|
}
|
|
628
|
-
// PHASE 3: DETERMINE NEXT
|
|
630
|
+
// PHASE 3: DETERMINE NEXT STEP - Use step from combined decision or get initial step
|
|
629
631
|
let message;
|
|
630
632
|
const toolCalls = undefined;
|
|
631
633
|
if (selectedRoute && !isRouteComplete) {
|
|
632
|
-
let
|
|
633
|
-
// If we have a selected
|
|
634
|
-
if (
|
|
635
|
-
|
|
634
|
+
let nextStep;
|
|
635
|
+
// If we have a selected step from the combined routing decision, use it
|
|
636
|
+
if (selectedStep) {
|
|
637
|
+
nextStep = selectedStep;
|
|
636
638
|
}
|
|
637
639
|
else {
|
|
638
|
-
// New route or no
|
|
639
|
-
const candidates = this.routingEngine.
|
|
640
|
+
// New route or no step selected - get initial step or first valid step
|
|
641
|
+
const candidates = this.routingEngine.getCandidateSteps(selectedRoute, undefined, session.data || {});
|
|
640
642
|
if (candidates.length > 0) {
|
|
641
|
-
|
|
642
|
-
logger.debug(`[Agent] Using first valid
|
|
643
|
+
nextStep = candidates[0].step;
|
|
644
|
+
logger.debug(`[Agent] Using first valid step: ${nextStep.id} for new route`);
|
|
643
645
|
}
|
|
644
646
|
else {
|
|
645
|
-
// Fallback to initial
|
|
646
|
-
|
|
647
|
-
logger.warn(`[Agent] No valid
|
|
647
|
+
// Fallback to initial step even if it should be skipped
|
|
648
|
+
nextStep = selectedRoute.initialStep;
|
|
649
|
+
logger.warn(`[Agent] No valid steps found, using initial step: ${nextStep.id}`);
|
|
648
650
|
}
|
|
649
651
|
}
|
|
650
|
-
// Update session with next
|
|
651
|
-
session =
|
|
652
|
-
logger.debug(`[Agent] Entered
|
|
653
|
-
// PHASE 4: RESPONSE GENERATION - Generate message using selected route and
|
|
652
|
+
// Update session with next step
|
|
653
|
+
session = enterStep(session, nextStep.id, nextStep.description);
|
|
654
|
+
logger.debug(`[Agent] Entered step: ${nextStep.id}`);
|
|
655
|
+
// PHASE 4: RESPONSE GENERATION - Generate message using selected route and step
|
|
654
656
|
// Get last user message
|
|
655
657
|
const lastUserMessage = getLastMessageFromHistory(history);
|
|
656
|
-
// Build response schema for this route (with
|
|
657
|
-
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute,
|
|
658
|
+
// Build response schema for this route (with collect fields from step)
|
|
659
|
+
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextStep);
|
|
658
660
|
// Build response prompt
|
|
659
|
-
const responsePrompt = this.responseEngine.buildResponsePrompt(selectedRoute,
|
|
661
|
+
const responsePrompt = this.responseEngine.buildResponsePrompt(selectedRoute, nextStep, selectedRoute.getRules(), selectedRoute.getProhibitions(), responseDirectives, history, lastUserMessage, {
|
|
660
662
|
name: this.options.name,
|
|
661
663
|
goal: this.options.goal,
|
|
662
664
|
description: this.options.description,
|
|
@@ -674,20 +676,20 @@ export class Agent {
|
|
|
674
676
|
},
|
|
675
677
|
});
|
|
676
678
|
message = result.structured?.message || result.message;
|
|
677
|
-
// Extract
|
|
678
|
-
if (result.structured &&
|
|
679
|
-
const
|
|
680
|
-
// The structured response includes both base fields and
|
|
679
|
+
// Extract collected data from response
|
|
680
|
+
if (result.structured && nextStep.collectFields) {
|
|
681
|
+
const collectedData = {};
|
|
682
|
+
// The structured response includes both base fields and collected extraction fields
|
|
681
683
|
const structuredData = result.structured;
|
|
682
|
-
for (const field of
|
|
684
|
+
for (const field of nextStep.collectFields) {
|
|
683
685
|
if (field in structuredData) {
|
|
684
|
-
|
|
686
|
+
collectedData[field] = structuredData[field];
|
|
685
687
|
}
|
|
686
688
|
}
|
|
687
|
-
// Merge
|
|
688
|
-
if (Object.keys(
|
|
689
|
-
session = await this.
|
|
690
|
-
logger.debug(`[Agent]
|
|
689
|
+
// Merge collected data into session
|
|
690
|
+
if (Object.keys(collectedData).length > 0) {
|
|
691
|
+
session = await this.updateData(session, collectedData);
|
|
692
|
+
logger.debug(`[Agent] Collected data:`, collectedData);
|
|
691
693
|
}
|
|
692
694
|
}
|
|
693
695
|
// Extract any additional data from structured response
|
|
@@ -701,14 +703,16 @@ export class Agent {
|
|
|
701
703
|
else if (isRouteComplete && selectedRoute) {
|
|
702
704
|
// Route is complete - generate completion message then check for onComplete transition
|
|
703
705
|
const lastUserMessage = getLastMessageFromHistory(history);
|
|
704
|
-
// Get
|
|
705
|
-
const
|
|
706
|
-
// Create a temporary
|
|
707
|
-
const
|
|
706
|
+
// Get endStep spec from route
|
|
707
|
+
const endStepSpec = selectedRoute.endStepSpec;
|
|
708
|
+
// Create a temporary step for completion message generation using endStep configuration
|
|
709
|
+
const completionStep = new Step(selectedRoute.id, endStepSpec.instructions ||
|
|
710
|
+
"Summarize what was accomplished and confirm completion", endStepSpec.id || END_ROUTE_ID, endStepSpec.collect, undefined, endStepSpec.requires, endStepSpec.instructions ||
|
|
711
|
+
"Summarize what was accomplished and confirm completion based on the conversation history and collected data");
|
|
708
712
|
// Build response schema for completion
|
|
709
|
-
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute,
|
|
713
|
+
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep);
|
|
710
714
|
// Build completion response prompt
|
|
711
|
-
const completionPrompt = this.responseEngine.buildResponsePrompt(selectedRoute,
|
|
715
|
+
const completionPrompt = this.responseEngine.buildResponsePrompt(selectedRoute, completionStep, selectedRoute.getRules(), selectedRoute.getProhibitions(), undefined, // No directives for completion
|
|
712
716
|
history, lastUserMessage, {
|
|
713
717
|
name: this.options.name,
|
|
714
718
|
goal: this.options.goal,
|
|
@@ -726,14 +730,15 @@ export class Agent {
|
|
|
726
730
|
schemaName: "completion_message",
|
|
727
731
|
},
|
|
728
732
|
});
|
|
729
|
-
message =
|
|
733
|
+
message =
|
|
734
|
+
completionResult.structured?.message || completionResult.message;
|
|
730
735
|
logger.debug(`[Agent] Generated completion message for route: ${selectedRoute.title}`);
|
|
731
736
|
// Check for onComplete transition
|
|
732
|
-
const transitionConfig = await selectedRoute.evaluateOnComplete({
|
|
737
|
+
const transitionConfig = await selectedRoute.evaluateOnComplete({ data: session.data }, effectiveContext);
|
|
733
738
|
if (transitionConfig) {
|
|
734
739
|
// Find target route by ID or title
|
|
735
|
-
const targetRoute = this.routes.find((r) => r.id === transitionConfig.
|
|
736
|
-
r.title === transitionConfig.
|
|
740
|
+
const targetRoute = this.routes.find((r) => r.id === transitionConfig.nextStep ||
|
|
741
|
+
r.title === transitionConfig.nextStep);
|
|
737
742
|
if (targetRoute) {
|
|
738
743
|
// Set pending transition in session
|
|
739
744
|
session = {
|
|
@@ -747,12 +752,12 @@ export class Agent {
|
|
|
747
752
|
logger.debug(`[Agent] Route ${selectedRoute.title} completed with pending transition to: ${targetRoute.title}`);
|
|
748
753
|
}
|
|
749
754
|
else {
|
|
750
|
-
logger.warn(`[Agent] Route ${selectedRoute.title} completed but target route not found: ${transitionConfig.
|
|
755
|
+
logger.warn(`[Agent] Route ${selectedRoute.title} completed but target route not found: ${transitionConfig.nextStep}`);
|
|
751
756
|
}
|
|
752
757
|
}
|
|
753
|
-
// Set
|
|
754
|
-
session =
|
|
755
|
-
logger.debug(`[Agent] Route ${selectedRoute.title} completed. Entered
|
|
758
|
+
// Set step to END_ROUTE marker
|
|
759
|
+
session = enterStep(session, END_ROUTE_ID, "Route completed");
|
|
760
|
+
logger.debug(`[Agent] Route ${selectedRoute.title} completed. Entered END_ROUTE step.`);
|
|
756
761
|
}
|
|
757
762
|
else {
|
|
758
763
|
// Fallback: No routes defined, generate a simple response
|
|
@@ -787,12 +792,12 @@ export class Agent {
|
|
|
787
792
|
});
|
|
788
793
|
message = result.structured?.message || result.message;
|
|
789
794
|
}
|
|
790
|
-
// Auto-save session
|
|
795
|
+
// Auto-save session step to persistence if configured
|
|
791
796
|
if (this.persistenceManager &&
|
|
792
797
|
session.id &&
|
|
793
798
|
this.options.persistence?.autoSave !== false) {
|
|
794
|
-
await this.persistenceManager.
|
|
795
|
-
logger.debug(`[Agent] Auto-saved session
|
|
799
|
+
await this.persistenceManager.saveSessionStep(session.id, session);
|
|
800
|
+
logger.debug(`[Agent] Auto-saved session step to persistence: ${session.id}`);
|
|
796
801
|
}
|
|
797
802
|
// Update current session if we have one
|
|
798
803
|
if (this.currentSession) {
|
|
@@ -800,9 +805,9 @@ export class Agent {
|
|
|
800
805
|
}
|
|
801
806
|
return {
|
|
802
807
|
message,
|
|
803
|
-
session, // Return updated session with route/
|
|
808
|
+
session, // Return updated session with route/step info
|
|
804
809
|
toolCalls,
|
|
805
|
-
isRouteComplete, // Indicates if the route has reached
|
|
810
|
+
isRouteComplete, // Indicates if the route has reached END_ROUTE with all data collected
|
|
806
811
|
};
|
|
807
812
|
}
|
|
808
813
|
/**
|
|
@@ -877,7 +882,7 @@ export class Agent {
|
|
|
877
882
|
}
|
|
878
883
|
/**
|
|
879
884
|
* Set the current session for convenience methods
|
|
880
|
-
* @param session - Session
|
|
885
|
+
* @param session - Session step to use for subsequent calls
|
|
881
886
|
*/
|
|
882
887
|
setCurrentSession(session) {
|
|
883
888
|
this.currentSession = session;
|
|
@@ -895,37 +900,38 @@ export class Agent {
|
|
|
895
900
|
this.currentSession = undefined;
|
|
896
901
|
}
|
|
897
902
|
/**
|
|
898
|
-
* Get
|
|
903
|
+
* Get collected data from current session
|
|
899
904
|
* @param routeId - Optional route ID to get data for (uses current route if not provided)
|
|
900
|
-
* @returns The
|
|
905
|
+
* @returns The collected data from the current session
|
|
901
906
|
*/
|
|
902
|
-
|
|
907
|
+
getData(routeId) {
|
|
903
908
|
if (!this.currentSession) {
|
|
904
909
|
return {};
|
|
905
910
|
}
|
|
906
911
|
if (routeId) {
|
|
907
|
-
return (this.currentSession.
|
|
912
|
+
return (this.currentSession.dataByRoute?.[routeId] ||
|
|
913
|
+
{});
|
|
908
914
|
}
|
|
909
|
-
return this.currentSession.
|
|
915
|
+
return this.currentSession.data || {};
|
|
910
916
|
}
|
|
911
917
|
/**
|
|
912
918
|
* Manually transition to a different route
|
|
913
919
|
* Sets a pending transition that will be executed on the next respond() call
|
|
914
920
|
*
|
|
915
921
|
* @param routeIdOrTitle - Route ID or title to transition to
|
|
916
|
-
* @param session - Session
|
|
922
|
+
* @param session - Session step to update (uses current session if not provided)
|
|
917
923
|
* @param condition - Optional AI-evaluated condition for the transition
|
|
918
924
|
* @returns Updated session with pending transition
|
|
919
925
|
*
|
|
920
926
|
* @example
|
|
921
927
|
* // After route completes
|
|
922
928
|
* if (response.isRouteComplete && response.session) {
|
|
923
|
-
* const updatedSession = agent.
|
|
929
|
+
* const updatedSession = agent.nextStepRoute("feedback-collection", response.session);
|
|
924
930
|
* // Next respond() call will automatically transition to feedback route
|
|
925
931
|
* const nextResponse = await agent.respond({ history, session: updatedSession });
|
|
926
932
|
* }
|
|
927
933
|
*/
|
|
928
|
-
|
|
934
|
+
nextStepRoute(routeIdOrTitle, session, condition) {
|
|
929
935
|
const targetSession = session || this.currentSession;
|
|
930
936
|
if (!targetSession) {
|
|
931
937
|
throw new Error("No session provided and no current session available. Please provide a session to transition.");
|
|
@@ -933,7 +939,9 @@ export class Agent {
|
|
|
933
939
|
// Find target route by ID or title
|
|
934
940
|
const targetRoute = this.routes.find((r) => r.id === routeIdOrTitle || r.title === routeIdOrTitle);
|
|
935
941
|
if (!targetRoute) {
|
|
936
|
-
throw new Error(`Route not found: ${routeIdOrTitle}. Available routes: ${this.routes
|
|
942
|
+
throw new Error(`Route not found: ${routeIdOrTitle}. Available routes: ${this.routes
|
|
943
|
+
.map((r) => r.title)
|
|
944
|
+
.join(", ")}`);
|
|
937
945
|
}
|
|
938
946
|
const updatedSession = {
|
|
939
947
|
...targetSession,
|