@falai/agent 0.9.0-alpha-1 → 0.9.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 +34 -22
- package/dist/cjs/src/core/Agent.d.ts +77 -59
- package/dist/cjs/src/core/Agent.d.ts.map +1 -1
- package/dist/cjs/src/core/Agent.js +284 -1060
- 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/ResponseModal.d.ts +205 -0
- package/dist/cjs/src/core/ResponseModal.d.ts.map +1 -0
- package/dist/cjs/src/core/ResponseModal.js +1328 -0
- package/dist/cjs/src/core/ResponseModal.js.map +1 -0
- 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 +72 -4
- 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/index.d.ts +3 -1
- package/dist/cjs/src/index.d.ts.map +1 -1
- package/dist/cjs/src/index.js +7 -1
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/cjs/src/types/agent.d.ts +42 -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/ai.d.ts +1 -1
- package/dist/cjs/src/types/ai.d.ts.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/clone.d.ts.map +1 -1
- package/dist/cjs/src/utils/clone.js +0 -4
- package/dist/cjs/src/utils/clone.js.map +1 -1
- package/dist/cjs/src/utils/history.d.ts +30 -1
- package/dist/cjs/src/utils/history.d.ts.map +1 -1
- package/dist/cjs/src/utils/history.js +169 -23
- package/dist/cjs/src/utils/history.js.map +1 -1
- package/dist/cjs/src/utils/index.d.ts +1 -1
- package/dist/cjs/src/utils/index.d.ts.map +1 -1
- package/dist/cjs/src/utils/index.js +5 -1
- package/dist/cjs/src/utils/index.js.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 +77 -59
- package/dist/src/core/Agent.d.ts.map +1 -1
- package/dist/src/core/Agent.js +285 -1061
- 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/ResponseModal.d.ts +205 -0
- package/dist/src/core/ResponseModal.d.ts.map +1 -0
- package/dist/src/core/ResponseModal.js +1323 -0
- package/dist/src/core/ResponseModal.js.map +1 -0
- 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 +72 -4
- 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/index.d.ts +3 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/types/agent.d.ts +42 -21
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/agent.js.map +1 -1
- package/dist/src/types/ai.d.ts +1 -1
- package/dist/src/types/ai.d.ts.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/clone.d.ts.map +1 -1
- package/dist/src/utils/clone.js +0 -4
- package/dist/src/utils/clone.js.map +1 -1
- package/dist/src/utils/history.d.ts +30 -1
- package/dist/src/utils/history.d.ts.map +1 -1
- package/dist/src/utils/history.js +165 -23
- package/dist/src/utils/history.js.map +1 -1
- package/dist/src/utils/index.d.ts +1 -1
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +1 -1
- package/dist/src/utils/index.js.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 +5 -4
- package/docs/api/README.md +195 -4
- package/docs/api/overview.md +232 -13
- 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/docs/guides/migration/README.md +72 -0
- package/docs/guides/migration/response-modal-refactor.md +518 -0
- 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 +197 -119
- 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/modern-streaming-api.ts +309 -0
- 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 +396 -1499
- package/src/core/PersistenceManager.ts +51 -27
- package/src/core/PromptComposer.ts +1 -1
- package/src/core/ResponseEngine.ts +21 -19
- package/src/core/ResponseModal.ts +1722 -0
- package/src/core/ResponsePipeline.ts +175 -60
- 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/index.ts +11 -0
- package/src/types/agent.ts +47 -23
- package/src/types/ai.ts +1 -1
- 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/clone.ts +6 -8
- package/src/utils/history.ts +190 -27
- package/src/utils/index.ts +4 -0
- package/src/utils/session.ts +6 -31
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
SessionState,
|
|
9
9
|
AgentStructuredResponse,
|
|
10
10
|
Tool,
|
|
11
|
+
RouteTransitionConfig,
|
|
11
12
|
} from "../types";
|
|
12
13
|
import { EventKind, MessageRole } from "../types/history";
|
|
13
14
|
import {
|
|
@@ -24,47 +25,51 @@ import { RoutingEngine } from "../core/RoutingEngine";
|
|
|
24
25
|
import { ToolExecutor } from "../core/ToolExecutor";
|
|
25
26
|
import { END_ROUTE_ID } from "../constants";
|
|
26
27
|
|
|
27
|
-
export interface ResponsePreparationResult<TContext> {
|
|
28
|
+
export interface ResponsePreparationResult<TContext, TData = unknown> {
|
|
28
29
|
effectiveContext: TContext;
|
|
29
|
-
session: SessionState
|
|
30
|
+
session: SessionState<TData>;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
export interface RoutingResult<TContext> {
|
|
33
|
-
selectedRoute: Route<TContext,
|
|
34
|
-
selectedStep: Step<TContext,
|
|
33
|
+
export interface RoutingResult<TContext, TData = unknown> {
|
|
34
|
+
selectedRoute: Route<TContext, TData> | undefined;
|
|
35
|
+
selectedStep: Step<TContext, TData> | undefined;
|
|
35
36
|
responseDirectives: string[] | undefined;
|
|
36
|
-
session: SessionState
|
|
37
|
+
session: SessionState<TData>;
|
|
37
38
|
isRouteComplete: boolean;
|
|
39
|
+
completedRoutes?: Route<TContext, TData>[];
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
export interface ToolExecutionResult {
|
|
41
|
-
session: SessionState
|
|
42
|
+
export interface ToolExecutionResult<TData = unknown> {
|
|
43
|
+
session: SessionState<TData>;
|
|
42
44
|
toolCalls:
|
|
43
45
|
| Array<{ toolName: string; arguments: Record<string, unknown> }>
|
|
44
46
|
| undefined;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
export interface DataCollectionResult {
|
|
48
|
-
session: SessionState
|
|
49
|
-
collectedData?:
|
|
49
|
+
export interface DataCollectionResult<TData = unknown> {
|
|
50
|
+
session: SessionState<TData>;
|
|
51
|
+
collectedData?: Partial<TData>;
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
/**
|
|
53
55
|
* Shared response processing logic between respond() and respondStream() methods
|
|
54
56
|
*/
|
|
55
|
-
export class ResponsePipeline<TContext = unknown> {
|
|
57
|
+
export class ResponsePipeline<TContext = unknown, TData = unknown> {
|
|
56
58
|
constructor(
|
|
57
|
-
private readonly options: AgentOptions<TContext>,
|
|
58
|
-
private readonly routes: Route<TContext,
|
|
59
|
-
private readonly tools: Tool<TContext, unknown[], unknown
|
|
60
|
-
private readonly routingEngine: RoutingEngine<TContext>,
|
|
59
|
+
private readonly options: AgentOptions<TContext, TData>,
|
|
60
|
+
private readonly routes: Route<TContext, TData>[],
|
|
61
|
+
private readonly tools: Tool<TContext, TData, unknown[], unknown>[],
|
|
62
|
+
private readonly routingEngine: RoutingEngine<TContext, TData>,
|
|
61
63
|
private readonly updateContext: (
|
|
62
64
|
updates: Partial<TContext>
|
|
63
65
|
) => Promise<void>,
|
|
64
66
|
private readonly updateData: (
|
|
65
|
-
session: SessionState
|
|
66
|
-
dataUpdate: Partial<
|
|
67
|
-
) => Promise<SessionState
|
|
67
|
+
session: SessionState<TData>,
|
|
68
|
+
dataUpdate: Partial<TData>
|
|
69
|
+
) => Promise<SessionState<TData>>,
|
|
70
|
+
private readonly updateCollectedData?: (
|
|
71
|
+
updates: Partial<TData>
|
|
72
|
+
) => Promise<void>
|
|
68
73
|
) {}
|
|
69
74
|
|
|
70
75
|
/**
|
|
@@ -72,8 +77,8 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
72
77
|
*/
|
|
73
78
|
async prepareResponseContext(params: {
|
|
74
79
|
contextOverride?: Partial<TContext>;
|
|
75
|
-
session?: SessionState
|
|
76
|
-
}): Promise<ResponsePreparationResult<TContext>> {
|
|
80
|
+
session?: SessionState<TData>;
|
|
81
|
+
}): Promise<ResponsePreparationResult<TContext, TData>> {
|
|
77
82
|
const { contextOverride, session } = params;
|
|
78
83
|
|
|
79
84
|
// Get current context (may fetch from provider)
|
|
@@ -93,7 +98,7 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
93
98
|
} as TContext;
|
|
94
99
|
|
|
95
100
|
// Initialize or get session (use current session if available)
|
|
96
|
-
const targetSession = session || this.currentSession || createSession();
|
|
101
|
+
const targetSession = session || this.currentSession || createSession<TData>();
|
|
97
102
|
|
|
98
103
|
return {
|
|
99
104
|
effectiveContext,
|
|
@@ -105,18 +110,19 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
105
110
|
* Handle routing and step selection logic
|
|
106
111
|
*/
|
|
107
112
|
async handleRoutingAndStepSelection(params: {
|
|
108
|
-
session: SessionState
|
|
113
|
+
session: SessionState<TData>;
|
|
109
114
|
history: Event[];
|
|
110
115
|
context: TContext;
|
|
111
116
|
signal?: AbortSignal;
|
|
112
|
-
}): Promise<RoutingResult<TContext>> {
|
|
117
|
+
}): Promise<RoutingResult<TContext, TData>> {
|
|
113
118
|
const { session, history, context, signal } = params;
|
|
114
119
|
|
|
115
120
|
// PHASE 2: ROUTING + STEP SELECTION - Determine which route and step to use (combined)
|
|
116
|
-
let selectedRoute: Route<TContext,
|
|
121
|
+
let selectedRoute: Route<TContext, TData> | undefined;
|
|
117
122
|
let responseDirectives: string[] | undefined;
|
|
118
|
-
let selectedStep: Step<TContext,
|
|
123
|
+
let selectedStep: Step<TContext, TData> | undefined;
|
|
119
124
|
let isRouteComplete = false;
|
|
125
|
+
let completedRoutes: Route<TContext, TData>[] = [];
|
|
120
126
|
let targetSession = session;
|
|
121
127
|
|
|
122
128
|
// Check for pending transition from previous route completion
|
|
@@ -178,6 +184,7 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
178
184
|
responseDirectives = orchestration.responseDirectives;
|
|
179
185
|
targetSession = orchestration.session;
|
|
180
186
|
isRouteComplete = orchestration.isRouteComplete || false;
|
|
187
|
+
completedRoutes = orchestration.completedRoutes || [];
|
|
181
188
|
|
|
182
189
|
// Log if route is complete
|
|
183
190
|
if (isRouteComplete) {
|
|
@@ -193,6 +200,7 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
193
200
|
responseDirectives,
|
|
194
201
|
session: targetSession,
|
|
195
202
|
isRouteComplete,
|
|
203
|
+
completedRoutes,
|
|
196
204
|
};
|
|
197
205
|
}
|
|
198
206
|
|
|
@@ -200,18 +208,18 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
200
208
|
* Determine next step and update session
|
|
201
209
|
*/
|
|
202
210
|
determineNextStep(params: {
|
|
203
|
-
selectedRoute: Route<TContext,
|
|
204
|
-
selectedStep: Step<TContext,
|
|
205
|
-
session: SessionState
|
|
211
|
+
selectedRoute: Route<TContext, TData> | undefined;
|
|
212
|
+
selectedStep: Step<TContext, TData> | undefined;
|
|
213
|
+
session: SessionState<TData>;
|
|
206
214
|
isRouteComplete: boolean;
|
|
207
|
-
}): { nextStep: Step<TContext,
|
|
215
|
+
}): { nextStep: Step<TContext, TData> | undefined; session: SessionState<TData> } {
|
|
208
216
|
const { selectedRoute, selectedStep, session, isRouteComplete } = params;
|
|
209
217
|
|
|
210
218
|
if (!selectedRoute || isRouteComplete) {
|
|
211
219
|
return { nextStep: undefined, session };
|
|
212
220
|
}
|
|
213
221
|
|
|
214
|
-
let nextStep: Step<TContext,
|
|
222
|
+
let nextStep: Step<TContext, TData>;
|
|
215
223
|
|
|
216
224
|
// If we have a selected step from the combined routing decision, use it
|
|
217
225
|
if (selectedStep) {
|
|
@@ -253,12 +261,12 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
253
261
|
*/
|
|
254
262
|
async executeToolCalls(params: {
|
|
255
263
|
toolCalls: Array<{ toolName: string; arguments: Record<string, unknown> }>;
|
|
256
|
-
selectedRoute?: Route<TContext,
|
|
264
|
+
selectedRoute?: Route<TContext, TData>;
|
|
257
265
|
context: TContext;
|
|
258
|
-
session: SessionState
|
|
266
|
+
session: SessionState<TData>;
|
|
259
267
|
history: Event[];
|
|
260
268
|
isStreaming?: boolean;
|
|
261
|
-
}): Promise<ToolExecutionResult
|
|
269
|
+
}): Promise<ToolExecutionResult<TData>> {
|
|
262
270
|
const {
|
|
263
271
|
toolCalls,
|
|
264
272
|
selectedRoute,
|
|
@@ -291,11 +299,12 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
291
299
|
continue;
|
|
292
300
|
}
|
|
293
301
|
|
|
294
|
-
const toolExecutor = new ToolExecutor<TContext,
|
|
302
|
+
const toolExecutor = new ToolExecutor<TContext, TData>();
|
|
295
303
|
const result = await toolExecutor.executeTool({
|
|
296
304
|
tool,
|
|
297
305
|
context,
|
|
298
306
|
updateContext: this.updateContext,
|
|
307
|
+
updateData: this.updateCollectedData || (async () => {}),
|
|
299
308
|
history,
|
|
300
309
|
data: updatedSession.data,
|
|
301
310
|
});
|
|
@@ -311,7 +320,7 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
311
320
|
if (result.dataUpdate) {
|
|
312
321
|
updatedSession = await this.updateData(
|
|
313
322
|
updatedSession,
|
|
314
|
-
result.dataUpdate
|
|
323
|
+
result.dataUpdate as Partial<TData>
|
|
315
324
|
);
|
|
316
325
|
logger.debug(
|
|
317
326
|
`[ResponseHandler] ${
|
|
@@ -341,15 +350,15 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
341
350
|
initialToolCalls:
|
|
342
351
|
| Array<{ toolName: string; arguments: Record<string, unknown> }>
|
|
343
352
|
| undefined;
|
|
344
|
-
selectedRoute?: Route<TContext,
|
|
345
|
-
nextStep: Step<TContext,
|
|
353
|
+
selectedRoute?: Route<TContext, TData>;
|
|
354
|
+
nextStep: Step<TContext, TData>;
|
|
346
355
|
responsePrompt: string;
|
|
347
356
|
history: Event[];
|
|
348
357
|
context: TContext;
|
|
349
|
-
session: SessionState
|
|
358
|
+
session: SessionState<TData>;
|
|
350
359
|
responseSchema: Record<string, unknown>;
|
|
351
360
|
isStreaming?: boolean;
|
|
352
|
-
}): Promise<ToolExecutionResult
|
|
361
|
+
}): Promise<ToolExecutionResult<TData>> {
|
|
353
362
|
const {
|
|
354
363
|
initialToolCalls,
|
|
355
364
|
selectedRoute,
|
|
@@ -469,28 +478,35 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
469
478
|
*/
|
|
470
479
|
async handleDataCollection(params: {
|
|
471
480
|
structured: AgentStructuredResponse | undefined;
|
|
472
|
-
nextStep: Step<TContext,
|
|
473
|
-
session: SessionState
|
|
474
|
-
}): Promise<DataCollectionResult
|
|
481
|
+
nextStep: Step<TContext, TData>;
|
|
482
|
+
session: SessionState<TData>;
|
|
483
|
+
}): Promise<DataCollectionResult<TData>> {
|
|
475
484
|
const { structured, nextStep, session } = params;
|
|
476
485
|
|
|
477
486
|
if (!structured || !nextStep.collect) {
|
|
478
487
|
return { session };
|
|
479
488
|
}
|
|
480
489
|
|
|
481
|
-
const collectedData:
|
|
490
|
+
const collectedData: Partial<TData> = {};
|
|
482
491
|
// The structured response includes both base fields and collected extraction fields
|
|
483
492
|
const structuredData = structured as AgentStructuredResponse &
|
|
484
493
|
Record<string, unknown>;
|
|
485
494
|
|
|
486
495
|
for (const field of nextStep.collect) {
|
|
487
|
-
|
|
488
|
-
|
|
496
|
+
const fieldKey = field as string;
|
|
497
|
+
if (fieldKey in structuredData) {
|
|
498
|
+
(collectedData as Record<string, unknown>)[fieldKey] = structuredData[fieldKey];
|
|
489
499
|
}
|
|
490
500
|
}
|
|
491
501
|
|
|
492
502
|
let updatedSession = session;
|
|
493
503
|
if (Object.keys(collectedData).length > 0) {
|
|
504
|
+
// Update agent-level collected data with validation if available
|
|
505
|
+
if (this.updateCollectedData) {
|
|
506
|
+
await this.updateCollectedData(collectedData);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Update session with validated data
|
|
494
510
|
updatedSession = await this.updateData(session, collectedData);
|
|
495
511
|
logger.debug(`[ResponseHandler] Collected data:`, collectedData);
|
|
496
512
|
}
|
|
@@ -523,11 +539,11 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
523
539
|
* Handle route completion logic
|
|
524
540
|
*/
|
|
525
541
|
async handleRouteCompletion(params: {
|
|
526
|
-
selectedRoute: Route<TContext,
|
|
527
|
-
session: SessionState
|
|
542
|
+
selectedRoute: Route<TContext, TData>;
|
|
543
|
+
session: SessionState<TData>;
|
|
528
544
|
context: TContext;
|
|
529
545
|
history: Event[];
|
|
530
|
-
}): Promise<{ session: SessionState
|
|
546
|
+
}): Promise<{ session: SessionState<TData>; hasTransition: boolean }> {
|
|
531
547
|
const { selectedRoute, session, context, history } = params;
|
|
532
548
|
|
|
533
549
|
// Check for onComplete transition
|
|
@@ -590,8 +606,8 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
590
606
|
*/
|
|
591
607
|
private findAvailableTool(
|
|
592
608
|
toolName: string,
|
|
593
|
-
route?: Route<TContext,
|
|
594
|
-
): Tool<TContext, unknown[], unknown
|
|
609
|
+
route?: Route<TContext, TData>
|
|
610
|
+
): Tool<TContext, TData, unknown[], unknown> | undefined {
|
|
595
611
|
// Check route-level tools first (if route provided)
|
|
596
612
|
if (route) {
|
|
597
613
|
const routeTool = route
|
|
@@ -610,12 +626,12 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
610
626
|
* Collect all available tools for the given route and step context
|
|
611
627
|
*/
|
|
612
628
|
private collectAvailableTools(
|
|
613
|
-
route?: Route<TContext,
|
|
614
|
-
step?: Step<TContext,
|
|
629
|
+
route?: Route<TContext, TData>,
|
|
630
|
+
step?: Step<TContext, TData>
|
|
615
631
|
): Array<{ id: string; description?: string; parameters?: unknown }> {
|
|
616
632
|
const availableTools = new Map<
|
|
617
633
|
string,
|
|
618
|
-
Tool<TContext, unknown[], unknown
|
|
634
|
+
Tool<TContext, TData, unknown[], unknown>
|
|
619
635
|
>();
|
|
620
636
|
|
|
621
637
|
// Add agent-level tools
|
|
@@ -633,7 +649,7 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
633
649
|
// Filter by step-level allowed tools if specified
|
|
634
650
|
if (step?.tools) {
|
|
635
651
|
const allowedToolIds = new Set<string>();
|
|
636
|
-
const stepTools: Tool<TContext, unknown[], unknown
|
|
652
|
+
const stepTools: Tool<TContext, TData, unknown[], unknown>[] = [];
|
|
637
653
|
|
|
638
654
|
for (const toolRef of step.tools) {
|
|
639
655
|
if (typeof toolRef === "string") {
|
|
@@ -652,9 +668,9 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
652
668
|
if (allowedToolIds.size > 0) {
|
|
653
669
|
const filteredTools = new Map<
|
|
654
670
|
string,
|
|
655
|
-
Tool<TContext, unknown[], unknown
|
|
671
|
+
Tool<TContext, TData, unknown[], unknown>
|
|
656
672
|
>();
|
|
657
|
-
for (const toolId of allowedToolIds) {
|
|
673
|
+
for (const toolId of Array.from(allowedToolIds)) {
|
|
658
674
|
const tool = availableTools.get(toolId);
|
|
659
675
|
if (tool) {
|
|
660
676
|
filteredTools.set(toolId, tool);
|
|
@@ -694,14 +710,14 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
694
710
|
|
|
695
711
|
// These need to be passed in or accessed differently since ResponseHandler is not part of Agent
|
|
696
712
|
private context?: TContext;
|
|
697
|
-
private currentSession?: SessionState
|
|
713
|
+
private currentSession?: SessionState<TData>;
|
|
698
714
|
|
|
699
715
|
// Setters for context and current session (needed for beforeRespond hook)
|
|
700
716
|
setContext(context: TContext | undefined): void {
|
|
701
717
|
this.context = context;
|
|
702
718
|
}
|
|
703
719
|
|
|
704
|
-
setCurrentSession(session: SessionState | undefined): void {
|
|
720
|
+
setCurrentSession(session: SessionState<TData> | undefined): void {
|
|
705
721
|
this.currentSession = session;
|
|
706
722
|
}
|
|
707
723
|
|
|
@@ -709,7 +725,106 @@ export class ResponsePipeline<TContext = unknown> {
|
|
|
709
725
|
return this.context;
|
|
710
726
|
}
|
|
711
727
|
|
|
712
|
-
public getCurrentSession(): SessionState | undefined {
|
|
728
|
+
public getCurrentSession(): SessionState<TData> | undefined {
|
|
713
729
|
return this.currentSession;
|
|
714
730
|
}
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Handle cross-route completion evaluation and notifications
|
|
734
|
+
* This method evaluates all routes for completion and can trigger completion handlers
|
|
735
|
+
*/
|
|
736
|
+
async handleCrossRouteCompletion(params: {
|
|
737
|
+
routes: Route<TContext, TData>[];
|
|
738
|
+
session: SessionState<TData>;
|
|
739
|
+
context: TContext;
|
|
740
|
+
history: Event[];
|
|
741
|
+
}): Promise<{
|
|
742
|
+
session: SessionState<TData>;
|
|
743
|
+
completedRoutes: Route<TContext, TData>[];
|
|
744
|
+
pendingTransitions: Array<{
|
|
745
|
+
route: Route<TContext, TData>;
|
|
746
|
+
transitionConfig: RouteTransitionConfig<TContext, TData>;
|
|
747
|
+
}>;
|
|
748
|
+
}> {
|
|
749
|
+
const { routes, session, context } = params;
|
|
750
|
+
|
|
751
|
+
// Evaluate all routes for completion
|
|
752
|
+
const completedRoutes: Route<TContext, TData>[] = [];
|
|
753
|
+
const pendingTransitions: Array<{
|
|
754
|
+
route: Route<TContext, TData>;
|
|
755
|
+
transitionConfig: RouteTransitionConfig<TContext, TData>;
|
|
756
|
+
}> = [];
|
|
757
|
+
|
|
758
|
+
for (const route of routes) {
|
|
759
|
+
if (route.isComplete(session.data || {})) {
|
|
760
|
+
completedRoutes.push(route);
|
|
761
|
+
|
|
762
|
+
// Check for onComplete transitions
|
|
763
|
+
const transitionConfig = await route.evaluateOnComplete(
|
|
764
|
+
{ data: session.data },
|
|
765
|
+
context
|
|
766
|
+
);
|
|
767
|
+
|
|
768
|
+
if (transitionConfig) {
|
|
769
|
+
pendingTransitions.push({ route, transitionConfig });
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
logger.debug(
|
|
773
|
+
`[ResponsePipeline] Route completed: ${route.title} ` +
|
|
774
|
+
`(${Math.round(route.getCompletionProgress(session.data || {}) * 100)}%)`
|
|
775
|
+
);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// Log completion status for all routes
|
|
780
|
+
if (completedRoutes.length > 0) {
|
|
781
|
+
logger.debug(
|
|
782
|
+
`[ResponsePipeline] Cross-route completion evaluation: ` +
|
|
783
|
+
`${completedRoutes.length}/${routes.length} routes complete`
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
return {
|
|
788
|
+
session,
|
|
789
|
+
completedRoutes,
|
|
790
|
+
pendingTransitions,
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Update data flow to ensure agent-level data consistency
|
|
796
|
+
* This method ensures that data updates are properly validated and propagated
|
|
797
|
+
*/
|
|
798
|
+
async updateDataFlow(params: {
|
|
799
|
+
session: SessionState<TData>;
|
|
800
|
+
dataUpdate: Partial<TData>;
|
|
801
|
+
routes: Route<TContext, TData>[];
|
|
802
|
+
}): Promise<SessionState<TData>> {
|
|
803
|
+
const { session, dataUpdate, routes } = params;
|
|
804
|
+
|
|
805
|
+
// Update session data
|
|
806
|
+
const updatedSession = await this.updateData(session, dataUpdate);
|
|
807
|
+
|
|
808
|
+
// Update agent-level data if handler is available
|
|
809
|
+
if (this.updateCollectedData) {
|
|
810
|
+
await this.updateCollectedData(dataUpdate);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// Evaluate route completions after data update
|
|
814
|
+
const completionResults = await this.handleCrossRouteCompletion({
|
|
815
|
+
routes,
|
|
816
|
+
session: updatedSession,
|
|
817
|
+
context: this.context!,
|
|
818
|
+
history: [],
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
// Log any newly completed routes
|
|
822
|
+
if (completionResults.completedRoutes.length > 0) {
|
|
823
|
+
logger.debug(
|
|
824
|
+
`[ResponsePipeline] Data update resulted in ${completionResults.completedRoutes.length} completed routes`
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
return completionResults.session;
|
|
829
|
+
}
|
|
715
830
|
}
|
package/src/core/Route.ts
CHANGED
|
@@ -39,8 +39,9 @@ export class Route<TContext = unknown, TData = unknown> {
|
|
|
39
39
|
"step" | "condition" | "skipIf"
|
|
40
40
|
>;
|
|
41
41
|
public readonly responseOutputSchema?: StructuredSchema;
|
|
42
|
-
public readonly schema?: StructuredSchema;
|
|
43
42
|
public readonly initialData?: Partial<TData>;
|
|
43
|
+
public readonly requiredFields?: (keyof TData)[];
|
|
44
|
+
public readonly optionalFields?: (keyof TData)[];
|
|
44
45
|
public readonly onComplete?:
|
|
45
46
|
| string
|
|
46
47
|
| RouteTransitionConfig<TContext, TData>
|
|
@@ -49,7 +50,7 @@ export class Route<TContext = unknown, TData = unknown> {
|
|
|
49
50
|
public routingExtrasSchema?: StructuredSchema;
|
|
50
51
|
public guidelines: Guideline<TContext>[] = [];
|
|
51
52
|
public terms: Term<TContext>[] = [];
|
|
52
|
-
public tools: Tool<TContext, unknown[], unknown
|
|
53
|
+
public tools: Tool<TContext, TData, unknown[], unknown>[] = [];
|
|
53
54
|
public knowledgeBase: Record<string, unknown> = {};
|
|
54
55
|
|
|
55
56
|
constructor(options: RouteOptions<TContext, TData>) {
|
|
@@ -87,8 +88,9 @@ export class Route<TContext = unknown, TData = unknown> {
|
|
|
87
88
|
};
|
|
88
89
|
this.routingExtrasSchema = options.routingExtrasSchema;
|
|
89
90
|
this.responseOutputSchema = options.responseOutputSchema;
|
|
90
|
-
this.schema = options.schema;
|
|
91
91
|
this.initialData = options.initialData;
|
|
92
|
+
this.requiredFields = options.requiredFields;
|
|
93
|
+
this.optionalFields = options.optionalFields;
|
|
92
94
|
this.onComplete = options.onComplete;
|
|
93
95
|
this.hooks = options.hooks;
|
|
94
96
|
|
|
@@ -166,7 +168,7 @@ export class Route<TContext = unknown, TData = unknown> {
|
|
|
166
168
|
/**
|
|
167
169
|
* Register a tool for this route
|
|
168
170
|
*/
|
|
169
|
-
createTool(tool: Tool<TContext, unknown[], unknown
|
|
171
|
+
createTool(tool: Tool<TContext, TData, unknown[], unknown>): this {
|
|
170
172
|
this.tools.push(tool);
|
|
171
173
|
return this;
|
|
172
174
|
}
|
|
@@ -174,7 +176,7 @@ export class Route<TContext = unknown, TData = unknown> {
|
|
|
174
176
|
/**
|
|
175
177
|
* Register multiple tools for this route
|
|
176
178
|
*/
|
|
177
|
-
registerTools(tools: Tool<TContext, unknown[], unknown
|
|
179
|
+
registerTools(tools: Tool<TContext, TData, unknown[], unknown>[]): this {
|
|
178
180
|
tools.forEach((tool) => this.createTool(tool));
|
|
179
181
|
return this;
|
|
180
182
|
}
|
|
@@ -196,7 +198,7 @@ export class Route<TContext = unknown, TData = unknown> {
|
|
|
196
198
|
/**
|
|
197
199
|
* Get all tools for this route
|
|
198
200
|
*/
|
|
199
|
-
getTools(): Tool<TContext, unknown[], unknown
|
|
201
|
+
getTools(): Tool<TContext, TData, unknown[], unknown>[] {
|
|
200
202
|
return [...this.tools];
|
|
201
203
|
}
|
|
202
204
|
|
|
@@ -353,6 +355,56 @@ export class Route<TContext = unknown, TData = unknown> {
|
|
|
353
355
|
}
|
|
354
356
|
}
|
|
355
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Check if this route is complete based on the provided data
|
|
360
|
+
* @param data - Currently collected agent-level data
|
|
361
|
+
* @returns true if all required fields are present, false otherwise
|
|
362
|
+
*/
|
|
363
|
+
isComplete(data: Partial<TData>): boolean {
|
|
364
|
+
if (!this.requiredFields || this.requiredFields.length === 0) {
|
|
365
|
+
return true; // No required fields means route is always complete
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return this.requiredFields.every(field => {
|
|
369
|
+
const value = data[field];
|
|
370
|
+
return value !== undefined && value !== null && value !== '';
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Get the list of missing required fields for this route
|
|
376
|
+
* @param data - Currently collected agent-level data
|
|
377
|
+
* @returns Array of missing required field keys
|
|
378
|
+
*/
|
|
379
|
+
getMissingRequiredFields(data: Partial<TData>): (keyof TData)[] {
|
|
380
|
+
if (!this.requiredFields || this.requiredFields.length === 0) {
|
|
381
|
+
return [];
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
return this.requiredFields.filter(field => {
|
|
385
|
+
const value = data[field];
|
|
386
|
+
return value === undefined || value === null || value === '';
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Get the completion progress for this route as a percentage
|
|
392
|
+
* @param data - Currently collected agent-level data
|
|
393
|
+
* @returns Completion progress as a number between 0 and 1
|
|
394
|
+
*/
|
|
395
|
+
getCompletionProgress(data: Partial<TData>): number {
|
|
396
|
+
if (!this.requiredFields || this.requiredFields.length === 0) {
|
|
397
|
+
return 1; // No required fields means 100% complete
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const completedFields = this.requiredFields.filter(field => {
|
|
401
|
+
const value = data[field];
|
|
402
|
+
return value !== undefined && value !== null && value !== '';
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
return completedFields.length / this.requiredFields.length;
|
|
406
|
+
}
|
|
407
|
+
|
|
356
408
|
/**
|
|
357
409
|
* Evaluate the onComplete handler and return transition config
|
|
358
410
|
* @param session - Current session step
|