@falai/agent 0.9.0-alpha-2 → 0.9.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 +42 -34
- package/dist/cjs/src/core/Agent.d.ts +48 -44
- package/dist/cjs/src/core/Agent.d.ts.map +1 -1
- package/dist/cjs/src/core/Agent.js +151 -1110
- package/dist/cjs/src/core/Agent.js.map +1 -1
- package/dist/cjs/src/core/ResponseModal.d.ts +211 -0
- package/dist/cjs/src/core/ResponseModal.d.ts.map +1 -0
- package/dist/cjs/src/core/ResponseModal.js +1394 -0
- package/dist/cjs/src/core/ResponseModal.js.map +1 -0
- package/dist/cjs/src/core/ResponsePipeline.d.ts +8 -4
- package/dist/cjs/src/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/cjs/src/core/ResponsePipeline.js +48 -20
- package/dist/cjs/src/core/ResponsePipeline.js.map +1 -1
- package/dist/cjs/src/core/Route.d.ts +12 -5
- package/dist/cjs/src/core/Route.d.ts.map +1 -1
- package/dist/cjs/src/core/Route.js +26 -5
- package/dist/cjs/src/core/Route.js.map +1 -1
- package/dist/cjs/src/core/RoutingEngine.d.ts +5 -0
- package/dist/cjs/src/core/RoutingEngine.d.ts.map +1 -1
- package/dist/cjs/src/core/RoutingEngine.js +37 -25
- package/dist/cjs/src/core/RoutingEngine.js.map +1 -1
- package/dist/cjs/src/core/SessionManager.d.ts +9 -1
- package/dist/cjs/src/core/SessionManager.d.ts.map +1 -1
- package/dist/cjs/src/core/SessionManager.js +27 -5
- package/dist/cjs/src/core/SessionManager.js.map +1 -1
- package/dist/cjs/src/core/Step.d.ts +60 -7
- package/dist/cjs/src/core/Step.d.ts.map +1 -1
- package/dist/cjs/src/core/Step.js +151 -4
- package/dist/cjs/src/core/Step.js.map +1 -1
- package/dist/cjs/src/core/ToolManager.d.ts +234 -0
- package/dist/cjs/src/core/ToolManager.d.ts.map +1 -0
- package/dist/cjs/src/core/ToolManager.js +1117 -0
- package/dist/cjs/src/core/ToolManager.js.map +1 -0
- package/dist/cjs/src/index.d.ts +5 -4
- package/dist/cjs/src/index.d.ts.map +1 -1
- package/dist/cjs/src/index.js +11 -3
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/cjs/src/types/agent.d.ts +2 -1
- package/dist/cjs/src/types/agent.d.ts.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 +3 -2
- package/dist/cjs/src/types/index.d.ts.map +1 -1
- package/dist/cjs/src/types/index.js +3 -1
- package/dist/cjs/src/types/index.js.map +1 -1
- package/dist/cjs/src/types/route.d.ts +6 -4
- package/dist/cjs/src/types/route.d.ts.map +1 -1
- package/dist/cjs/src/types/tool.d.ts +84 -14
- package/dist/cjs/src/types/tool.d.ts.map +1 -1
- package/dist/cjs/src/types/tool.js +13 -0
- package/dist/cjs/src/types/tool.js.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/src/core/Agent.d.ts +48 -44
- package/dist/src/core/Agent.d.ts.map +1 -1
- package/dist/src/core/Agent.js +152 -1111
- package/dist/src/core/Agent.js.map +1 -1
- package/dist/src/core/ResponseModal.d.ts +211 -0
- package/dist/src/core/ResponseModal.d.ts.map +1 -0
- package/dist/src/core/ResponseModal.js +1389 -0
- package/dist/src/core/ResponseModal.js.map +1 -0
- package/dist/src/core/ResponsePipeline.d.ts +8 -4
- package/dist/src/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/src/core/ResponsePipeline.js +48 -20
- package/dist/src/core/ResponsePipeline.js.map +1 -1
- package/dist/src/core/Route.d.ts +12 -5
- package/dist/src/core/Route.d.ts.map +1 -1
- package/dist/src/core/Route.js +26 -5
- package/dist/src/core/Route.js.map +1 -1
- package/dist/src/core/RoutingEngine.d.ts +5 -0
- package/dist/src/core/RoutingEngine.d.ts.map +1 -1
- package/dist/src/core/RoutingEngine.js +37 -25
- package/dist/src/core/RoutingEngine.js.map +1 -1
- package/dist/src/core/SessionManager.d.ts +9 -1
- package/dist/src/core/SessionManager.d.ts.map +1 -1
- package/dist/src/core/SessionManager.js +27 -5
- package/dist/src/core/SessionManager.js.map +1 -1
- package/dist/src/core/Step.d.ts +60 -7
- package/dist/src/core/Step.d.ts.map +1 -1
- package/dist/src/core/Step.js +151 -4
- package/dist/src/core/Step.js.map +1 -1
- package/dist/src/core/ToolManager.d.ts +234 -0
- package/dist/src/core/ToolManager.d.ts.map +1 -0
- package/dist/src/core/ToolManager.js +1111 -0
- package/dist/src/core/ToolManager.js.map +1 -0
- package/dist/src/index.d.ts +5 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/types/agent.d.ts +2 -1
- package/dist/src/types/agent.d.ts.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 +3 -2
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js +1 -0
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/types/route.d.ts +6 -4
- package/dist/src/types/route.d.ts.map +1 -1
- package/dist/src/types/tool.d.ts +84 -14
- package/dist/src/types/tool.d.ts.map +1 -1
- package/dist/src/types/tool.js +12 -1
- package/dist/src/types/tool.js.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/docs/CONTRIBUTING.md +40 -0
- package/docs/README.md +14 -6
- package/docs/api/README.md +235 -45
- package/docs/api/overview.md +140 -33
- package/docs/core/agent/session-management.md +152 -5
- package/docs/core/ai-integration/response-processing.md +115 -4
- package/docs/core/conversation-flows/routes.md +130 -0
- package/docs/core/error-handling.md +638 -0
- package/docs/core/tools/tool-definition.md +684 -60
- package/docs/core/tools/tool-scoping.md +244 -53
- package/docs/guides/error-handling-patterns.md +578 -0
- package/docs/guides/getting-started/README.md +139 -28
- 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 +6 -6
- package/examples/advanced-patterns/persistent-onboarding.ts +30 -43
- package/examples/advanced-patterns/streaming-responses.ts +169 -96
- package/examples/ai-providers/anthropic-integration.ts +9 -5
- package/examples/ai-providers/openai-integration.ts +11 -7
- package/examples/core-concepts/basic-agent.ts +106 -67
- package/examples/core-concepts/modern-streaming-api.ts +309 -0
- package/examples/core-concepts/schema-driven-extraction.ts +10 -7
- package/examples/core-concepts/session-management.ts +71 -18
- package/examples/integrations/healthcare-integration.ts +15 -29
- package/examples/integrations/server-session-management.ts +3 -3
- package/examples/persistence/memory-sessions.ts +3 -3
- package/examples/tools/basic-tools.ts +293 -89
- package/examples/tools/data-enrichment-tools.ts +185 -75
- package/package.json +1 -1
- package/src/core/Agent.ts +190 -1529
- package/src/core/ResponseModal.ts +1798 -0
- package/src/core/ResponsePipeline.ts +83 -57
- package/src/core/Route.ts +39 -12
- package/src/core/RoutingEngine.ts +46 -42
- package/src/core/SessionManager.ts +39 -7
- package/src/core/Step.ts +198 -20
- package/src/core/ToolManager.ts +1394 -0
- package/src/index.ts +19 -3
- package/src/types/agent.ts +2 -1
- package/src/types/ai.ts +1 -1
- package/src/types/index.ts +13 -2
- package/src/types/route.ts +6 -4
- package/src/types/tool.ts +116 -25
- package/src/utils/clone.ts +6 -8
- package/src/utils/history.ts +190 -27
- package/src/utils/index.ts +4 -0
- package/dist/cjs/src/core/ToolExecutor.d.ts +0 -45
- package/dist/cjs/src/core/ToolExecutor.d.ts.map +0 -1
- package/dist/cjs/src/core/ToolExecutor.js +0 -84
- package/dist/cjs/src/core/ToolExecutor.js.map +0 -1
- package/dist/src/core/ToolExecutor.d.ts +0 -45
- package/dist/src/core/ToolExecutor.d.ts.map +0 -1
- package/dist/src/core/ToolExecutor.js +0 -80
- package/dist/src/core/ToolExecutor.js.map +0 -1
- package/docs/core/tools/tool-execution.md +0 -815
- package/src/core/ToolExecutor.ts +0 -126
|
@@ -104,7 +104,7 @@ const response3 = await agent.respond("Also book me a hotel in Tokyo");
|
|
|
104
104
|
|
|
105
105
|
**SessionManager API:**
|
|
106
106
|
|
|
107
|
-
The `SessionManager` provides a clean API for session operations:
|
|
107
|
+
The `SessionManager` provides a clean API for session operations with comprehensive error handling:
|
|
108
108
|
|
|
109
109
|
```typescript
|
|
110
110
|
// Access the session manager
|
|
@@ -114,13 +114,19 @@ const sessionManager = agent.session;
|
|
|
114
114
|
await sessionManager.getOrCreate("user-123");
|
|
115
115
|
await sessionManager.getOrCreate(); // Auto-generates ID
|
|
116
116
|
|
|
117
|
-
// History management
|
|
118
|
-
|
|
119
|
-
await sessionManager.addMessage("
|
|
117
|
+
// History management with error handling
|
|
118
|
+
try {
|
|
119
|
+
await sessionManager.addMessage("user", "Hello");
|
|
120
|
+
await sessionManager.addMessage("assistant", "Hi there!");
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error("Failed to add message to history:", error);
|
|
123
|
+
// Message will be rolled back automatically
|
|
124
|
+
}
|
|
125
|
+
|
|
120
126
|
const history = sessionManager.getHistory();
|
|
121
127
|
sessionManager.clearHistory();
|
|
122
128
|
|
|
123
|
-
// Data access
|
|
129
|
+
// Data access with synchronization
|
|
124
130
|
const data = sessionManager.getData<FlightData>();
|
|
125
131
|
await sessionManager.setData({ destination: "Paris" });
|
|
126
132
|
|
|
@@ -130,6 +136,147 @@ await sessionManager.delete();
|
|
|
130
136
|
const newSession = await sessionManager.reset(true); // Preserve history
|
|
131
137
|
```
|
|
132
138
|
|
|
139
|
+
### Agent-Session Data Synchronization
|
|
140
|
+
|
|
141
|
+
The framework ensures bidirectional synchronization between agent collected data and session data:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// Agent data updates automatically sync with session
|
|
145
|
+
const agent = new Agent<{}, BookingData>({
|
|
146
|
+
sessionId: "user-123",
|
|
147
|
+
// ... other config
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
// Update agent data - automatically syncs with session
|
|
152
|
+
await agent.updateCollectedData({
|
|
153
|
+
destination: "Tokyo",
|
|
154
|
+
passengers: 2
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Session data is automatically updated
|
|
158
|
+
const sessionData = agent.session.getData<BookingData>();
|
|
159
|
+
console.log(sessionData.destination); // "Tokyo"
|
|
160
|
+
|
|
161
|
+
// Update session data - automatically syncs with agent
|
|
162
|
+
await agent.session.setData({
|
|
163
|
+
checkInDate: "2025-03-15"
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Agent data is automatically updated
|
|
167
|
+
const agentData = agent.getCollectedData();
|
|
168
|
+
console.log(agentData.checkInDate); // "2025-03-15"
|
|
169
|
+
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.error("Data synchronization failed:", error);
|
|
172
|
+
// Both agent and session data remain in consistent state
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Error Handling in Data Synchronization
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
class SessionManager<TData> {
|
|
180
|
+
async setData(data: Partial<TData>): Promise<void> {
|
|
181
|
+
const previousData = { ...this.session.data };
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
// Validate data if schema is available
|
|
185
|
+
if (this.schema) {
|
|
186
|
+
this.validateData(data);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Update session data
|
|
190
|
+
this.session.data = { ...this.session.data, ...data };
|
|
191
|
+
|
|
192
|
+
// Sync with agent collected data
|
|
193
|
+
if (this.agent) {
|
|
194
|
+
await this.agent.updateCollectedData(data);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Persist changes
|
|
198
|
+
await this.save();
|
|
199
|
+
|
|
200
|
+
} catch (error) {
|
|
201
|
+
// Rollback session data on any failure
|
|
202
|
+
this.session.data = previousData;
|
|
203
|
+
|
|
204
|
+
console.error("Session data update failed, rolled back:", error);
|
|
205
|
+
throw new Error(`Data synchronization failed: ${error.message}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async addMessage(role: "user" | "assistant", content: string): Promise<void> {
|
|
210
|
+
const message: HistoryItem = {
|
|
211
|
+
role,
|
|
212
|
+
content,
|
|
213
|
+
timestamp: new Date().toISOString()
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
// Add to session history
|
|
218
|
+
this.session.history.push(message);
|
|
219
|
+
|
|
220
|
+
// Persist immediately for reliability
|
|
221
|
+
await this.save();
|
|
222
|
+
|
|
223
|
+
} catch (error) {
|
|
224
|
+
// Remove message from history on persistence failure
|
|
225
|
+
this.session.history.pop();
|
|
226
|
+
|
|
227
|
+
console.error("Failed to persist message:", error);
|
|
228
|
+
throw new Error(`Message persistence failed: ${error.message}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Chat Method with Proper Error Handling
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
class Agent<TContext, TData> {
|
|
238
|
+
async chat(message: string, sessionId?: string): Promise<AgentResponse<TData>> {
|
|
239
|
+
try {
|
|
240
|
+
// Ensure session is loaded
|
|
241
|
+
if (!this.session || this.session.id !== sessionId) {
|
|
242
|
+
await this.loadSession(sessionId);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Add user message to history BEFORE processing
|
|
246
|
+
await this.session.addMessage("user", message);
|
|
247
|
+
|
|
248
|
+
// Process the message
|
|
249
|
+
const response = await this.respond({
|
|
250
|
+
message,
|
|
251
|
+
sessionId: this.session.id
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Add assistant response to history
|
|
255
|
+
if (response.message) {
|
|
256
|
+
await this.session.addMessage("assistant", response.message);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return response;
|
|
260
|
+
|
|
261
|
+
} catch (error) {
|
|
262
|
+
console.error("Chat method failed:", error);
|
|
263
|
+
|
|
264
|
+
// Try to remove the user message if response failed
|
|
265
|
+
try {
|
|
266
|
+
const history = this.session.getHistory();
|
|
267
|
+
if (history.length > 0 && history[history.length - 1].role === "user") {
|
|
268
|
+
await this.session.removeLastMessage();
|
|
269
|
+
}
|
|
270
|
+
} catch (rollbackError) {
|
|
271
|
+
console.error("Failed to rollback user message:", rollbackError);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
throw new Error(`Chat failed: ${error.message}`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
133
280
|
**Why?** Automatic session management provides:
|
|
134
281
|
|
|
135
282
|
- **Zero Boilerplate** - No manual session creation or persistence code
|
|
@@ -118,10 +118,121 @@ agentContext.lastResponseTime = Date.now();
|
|
|
118
118
|
|
|
119
119
|
Robust error handling for various failure scenarios:
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
### Schema Validation Failures
|
|
122
|
+
|
|
123
|
+
When AI responses don't match expected schemas, the system gracefully falls back:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
const processResponse = async (response: string, schema: JSONSchema) => {
|
|
127
|
+
try {
|
|
128
|
+
// Try schema-based extraction first
|
|
129
|
+
const extracted = await extractWithSchema(response, schema);
|
|
130
|
+
return { success: true, data: extracted };
|
|
131
|
+
} catch (schemaError) {
|
|
132
|
+
console.warn("Schema extraction failed, falling back to manual parsing:", schemaError.message);
|
|
133
|
+
|
|
134
|
+
// Fallback to manual extraction
|
|
135
|
+
try {
|
|
136
|
+
const manualData = await manualExtraction(response);
|
|
137
|
+
return { success: true, data: manualData, fallback: true };
|
|
138
|
+
} catch (fallbackError) {
|
|
139
|
+
return {
|
|
140
|
+
success: false,
|
|
141
|
+
error: `Both schema and manual extraction failed: ${fallbackError.message}`
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Tool Execution Errors
|
|
149
|
+
|
|
150
|
+
Tool failures are handled gracefully with proper error propagation:
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
const executeTool = async (tool: Tool, params: any) => {
|
|
154
|
+
try {
|
|
155
|
+
const result = await tool.handler(params);
|
|
156
|
+
return { success: true, result };
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error(`Tool ${tool.id} execution failed:`, error);
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
success: false,
|
|
162
|
+
error: error.message,
|
|
163
|
+
fallbackMessage: "I encountered an issue while processing your request. Please try again."
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Context Update Failures
|
|
170
|
+
|
|
171
|
+
Context updates include rollback mechanisms:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
const updateContext = async (newContext: any, previousContext: any) => {
|
|
175
|
+
try {
|
|
176
|
+
await persistContext(newContext);
|
|
177
|
+
return { success: true };
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.error("Context update failed, rolling back:", error);
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
await persistContext(previousContext);
|
|
183
|
+
return { success: false, rolledBack: true, error: error.message };
|
|
184
|
+
} catch (rollbackError) {
|
|
185
|
+
return {
|
|
186
|
+
success: false,
|
|
187
|
+
rolledBack: false,
|
|
188
|
+
error: `Update and rollback both failed: ${rollbackError.message}`
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Streaming Error Propagation
|
|
196
|
+
|
|
197
|
+
Streaming responses properly propagate provider errors:
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
async function* processStreamingResponse(provider: AIProvider, prompt: string) {
|
|
201
|
+
try {
|
|
202
|
+
for await (const chunk of provider.generateMessageStream(prompt)) {
|
|
203
|
+
yield { success: true, chunk };
|
|
204
|
+
}
|
|
205
|
+
} catch (error) {
|
|
206
|
+
// Ensure streaming errors are properly propagated
|
|
207
|
+
yield { success: false, error: error.message };
|
|
208
|
+
throw error; // Re-throw to stop the stream
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Routing Errors
|
|
214
|
+
|
|
215
|
+
Safe fallback to default behavior when routing fails:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
const selectRoute = async (routes: Route[], context: any) => {
|
|
219
|
+
try {
|
|
220
|
+
const selectedRoute = await aiRouting.selectBestRoute(routes, context);
|
|
221
|
+
return { success: true, route: selectedRoute };
|
|
222
|
+
} catch (routingError) {
|
|
223
|
+
console.warn("AI routing failed, using default route:", routingError.message);
|
|
224
|
+
|
|
225
|
+
// Fallback to first available route or default
|
|
226
|
+
const fallbackRoute = routes.find(r => r.isDefault) || routes[0];
|
|
227
|
+
return {
|
|
228
|
+
success: true,
|
|
229
|
+
route: fallbackRoute,
|
|
230
|
+
fallback: true,
|
|
231
|
+
error: routingError.message
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
```
|
|
125
236
|
|
|
126
237
|
## Streaming Response Processing
|
|
127
238
|
|
|
@@ -74,6 +74,8 @@ Routes are selected by the AI routing system based on user intent and conversati
|
|
|
74
74
|
|
|
75
75
|
Routes complete when all their required fields are present in the agent's collected data, regardless of which route collected the data. This enables flexible cross-route completion scenarios.
|
|
76
76
|
|
|
77
|
+
### Basic Route Completion
|
|
78
|
+
|
|
77
79
|
```typescript
|
|
78
80
|
// Route completion evaluation
|
|
79
81
|
const isComplete = bookingRoute.isComplete(agent.getCollectedData());
|
|
@@ -86,6 +88,134 @@ if (missingFields.length > 0) {
|
|
|
86
88
|
}
|
|
87
89
|
```
|
|
88
90
|
|
|
91
|
+
### Route Completion with Error Handling
|
|
92
|
+
|
|
93
|
+
Proper error handling ensures accurate route completion detection:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
const checkRouteCompletion = async (route: Route, agent: Agent) => {
|
|
97
|
+
try {
|
|
98
|
+
const collectedData = agent.getCollectedData();
|
|
99
|
+
|
|
100
|
+
// Check data-based completion
|
|
101
|
+
if (route.isComplete(collectedData)) {
|
|
102
|
+
return { complete: true, reason: "all_required_data_collected" };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Check step-based completion (for routes with skipIf conditions)
|
|
106
|
+
const allStepsProcessed = route.steps.every(step => {
|
|
107
|
+
if (step.skipIf && step.skipIf(collectedData)) {
|
|
108
|
+
return true; // Step is skipped, counts as processed
|
|
109
|
+
}
|
|
110
|
+
return step.isCompleted;
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
if (allStepsProcessed) {
|
|
114
|
+
return { complete: true, reason: "all_steps_processed" };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Check for explicit route termination
|
|
118
|
+
if (route.hasExplicitEnd()) {
|
|
119
|
+
return { complete: true, reason: "explicit_end_route" };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
complete: false,
|
|
124
|
+
missingFields: route.getMissingRequiredFields(collectedData),
|
|
125
|
+
progress: route.getCompletionProgress(collectedData)
|
|
126
|
+
};
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.error("Route completion check failed:", error);
|
|
129
|
+
return {
|
|
130
|
+
complete: false,
|
|
131
|
+
error: error.message,
|
|
132
|
+
fallback: true
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Usage with error handling
|
|
138
|
+
const completionResult = await checkRouteCompletion(bookingRoute, agent);
|
|
139
|
+
|
|
140
|
+
if (completionResult.error) {
|
|
141
|
+
console.warn("Completion check failed, assuming incomplete:", completionResult.error);
|
|
142
|
+
} else if (completionResult.complete) {
|
|
143
|
+
console.log(`Route completed: ${completionResult.reason}`);
|
|
144
|
+
} else {
|
|
145
|
+
console.log(`Route ${Math.round(completionResult.progress * 100)}% complete`);
|
|
146
|
+
console.log(`Missing: ${completionResult.missingFields.join(', ')}`);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Handling Routes with Conditional Steps
|
|
151
|
+
|
|
152
|
+
Routes with `skipIf` conditions require special completion logic:
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
const conditionalRoute = agent.createRoute({
|
|
156
|
+
title: "Conditional Booking",
|
|
157
|
+
requiredFields: ["destination", "dates", "passengers"]
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const askDestination = conditionalRoute.initialStep.nextStep({
|
|
161
|
+
prompt: "Where would you like to go?",
|
|
162
|
+
collect: ["destination"],
|
|
163
|
+
skipIf: (data) => !!data.destination, // Skip if already collected
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const askDates = askDestination.nextStep({
|
|
167
|
+
prompt: "When would you like to travel?",
|
|
168
|
+
collect: ["dates"],
|
|
169
|
+
skipIf: (data) => !!data.dates,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const confirmBooking = askDates.nextStep({
|
|
173
|
+
prompt: "Confirm your booking details",
|
|
174
|
+
requires: ["destination", "dates", "passengers"],
|
|
175
|
+
onComplete: () => ({ endRoute: true }) // Explicit route termination
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Completion detection handles skipped steps
|
|
179
|
+
const response = await agent.respond({
|
|
180
|
+
message: "I want to go to Paris on March 15th for 2 passengers",
|
|
181
|
+
sessionId: "user-123"
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// All steps may be skipped due to complete data extraction
|
|
185
|
+
// Route should still be marked as complete
|
|
186
|
+
console.log("Route complete:", response.isRouteComplete); // Should be true
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Error Recovery in Route Completion
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
const safeRouteCompletion = async (route: Route, agent: Agent) => {
|
|
193
|
+
const maxRetries = 3;
|
|
194
|
+
let attempt = 0;
|
|
195
|
+
|
|
196
|
+
while (attempt < maxRetries) {
|
|
197
|
+
try {
|
|
198
|
+
return await checkRouteCompletion(route, agent);
|
|
199
|
+
} catch (error) {
|
|
200
|
+
attempt++;
|
|
201
|
+
console.warn(`Route completion check attempt ${attempt} failed:`, error.message);
|
|
202
|
+
|
|
203
|
+
if (attempt >= maxRetries) {
|
|
204
|
+
// Final fallback - assume incomplete
|
|
205
|
+
return {
|
|
206
|
+
complete: false,
|
|
207
|
+
error: `Completion check failed after ${maxRetries} attempts: ${error.message}`,
|
|
208
|
+
fallback: true
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Brief delay before retry
|
|
213
|
+
await new Promise(resolve => setTimeout(resolve, 100 * attempt));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
```
|
|
218
|
+
|
|
89
219
|
## Route Transitions
|
|
90
220
|
|
|
91
221
|
Routes can automatically transition to other routes upon completion using the `onComplete` configuration. With agent-level data, the target route may already have some of its required data.
|