@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.
Files changed (179) hide show
  1. package/README.md +42 -34
  2. package/dist/cjs/src/core/Agent.d.ts +48 -44
  3. package/dist/cjs/src/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/src/core/Agent.js +151 -1110
  5. package/dist/cjs/src/core/Agent.js.map +1 -1
  6. package/dist/cjs/src/core/ResponseModal.d.ts +211 -0
  7. package/dist/cjs/src/core/ResponseModal.d.ts.map +1 -0
  8. package/dist/cjs/src/core/ResponseModal.js +1394 -0
  9. package/dist/cjs/src/core/ResponseModal.js.map +1 -0
  10. package/dist/cjs/src/core/ResponsePipeline.d.ts +8 -4
  11. package/dist/cjs/src/core/ResponsePipeline.d.ts.map +1 -1
  12. package/dist/cjs/src/core/ResponsePipeline.js +48 -20
  13. package/dist/cjs/src/core/ResponsePipeline.js.map +1 -1
  14. package/dist/cjs/src/core/Route.d.ts +12 -5
  15. package/dist/cjs/src/core/Route.d.ts.map +1 -1
  16. package/dist/cjs/src/core/Route.js +26 -5
  17. package/dist/cjs/src/core/Route.js.map +1 -1
  18. package/dist/cjs/src/core/RoutingEngine.d.ts +5 -0
  19. package/dist/cjs/src/core/RoutingEngine.d.ts.map +1 -1
  20. package/dist/cjs/src/core/RoutingEngine.js +37 -25
  21. package/dist/cjs/src/core/RoutingEngine.js.map +1 -1
  22. package/dist/cjs/src/core/SessionManager.d.ts +9 -1
  23. package/dist/cjs/src/core/SessionManager.d.ts.map +1 -1
  24. package/dist/cjs/src/core/SessionManager.js +27 -5
  25. package/dist/cjs/src/core/SessionManager.js.map +1 -1
  26. package/dist/cjs/src/core/Step.d.ts +60 -7
  27. package/dist/cjs/src/core/Step.d.ts.map +1 -1
  28. package/dist/cjs/src/core/Step.js +151 -4
  29. package/dist/cjs/src/core/Step.js.map +1 -1
  30. package/dist/cjs/src/core/ToolManager.d.ts +234 -0
  31. package/dist/cjs/src/core/ToolManager.d.ts.map +1 -0
  32. package/dist/cjs/src/core/ToolManager.js +1117 -0
  33. package/dist/cjs/src/core/ToolManager.js.map +1 -0
  34. package/dist/cjs/src/index.d.ts +5 -4
  35. package/dist/cjs/src/index.d.ts.map +1 -1
  36. package/dist/cjs/src/index.js +11 -3
  37. package/dist/cjs/src/index.js.map +1 -1
  38. package/dist/cjs/src/types/agent.d.ts +2 -1
  39. package/dist/cjs/src/types/agent.d.ts.map +1 -1
  40. package/dist/cjs/src/types/ai.d.ts +1 -1
  41. package/dist/cjs/src/types/ai.d.ts.map +1 -1
  42. package/dist/cjs/src/types/index.d.ts +3 -2
  43. package/dist/cjs/src/types/index.d.ts.map +1 -1
  44. package/dist/cjs/src/types/index.js +3 -1
  45. package/dist/cjs/src/types/index.js.map +1 -1
  46. package/dist/cjs/src/types/route.d.ts +6 -4
  47. package/dist/cjs/src/types/route.d.ts.map +1 -1
  48. package/dist/cjs/src/types/tool.d.ts +84 -14
  49. package/dist/cjs/src/types/tool.d.ts.map +1 -1
  50. package/dist/cjs/src/types/tool.js +13 -0
  51. package/dist/cjs/src/types/tool.js.map +1 -1
  52. package/dist/cjs/src/utils/clone.d.ts.map +1 -1
  53. package/dist/cjs/src/utils/clone.js +0 -4
  54. package/dist/cjs/src/utils/clone.js.map +1 -1
  55. package/dist/cjs/src/utils/history.d.ts +30 -1
  56. package/dist/cjs/src/utils/history.d.ts.map +1 -1
  57. package/dist/cjs/src/utils/history.js +169 -23
  58. package/dist/cjs/src/utils/history.js.map +1 -1
  59. package/dist/cjs/src/utils/index.d.ts +1 -1
  60. package/dist/cjs/src/utils/index.d.ts.map +1 -1
  61. package/dist/cjs/src/utils/index.js +5 -1
  62. package/dist/cjs/src/utils/index.js.map +1 -1
  63. package/dist/src/core/Agent.d.ts +48 -44
  64. package/dist/src/core/Agent.d.ts.map +1 -1
  65. package/dist/src/core/Agent.js +152 -1111
  66. package/dist/src/core/Agent.js.map +1 -1
  67. package/dist/src/core/ResponseModal.d.ts +211 -0
  68. package/dist/src/core/ResponseModal.d.ts.map +1 -0
  69. package/dist/src/core/ResponseModal.js +1389 -0
  70. package/dist/src/core/ResponseModal.js.map +1 -0
  71. package/dist/src/core/ResponsePipeline.d.ts +8 -4
  72. package/dist/src/core/ResponsePipeline.d.ts.map +1 -1
  73. package/dist/src/core/ResponsePipeline.js +48 -20
  74. package/dist/src/core/ResponsePipeline.js.map +1 -1
  75. package/dist/src/core/Route.d.ts +12 -5
  76. package/dist/src/core/Route.d.ts.map +1 -1
  77. package/dist/src/core/Route.js +26 -5
  78. package/dist/src/core/Route.js.map +1 -1
  79. package/dist/src/core/RoutingEngine.d.ts +5 -0
  80. package/dist/src/core/RoutingEngine.d.ts.map +1 -1
  81. package/dist/src/core/RoutingEngine.js +37 -25
  82. package/dist/src/core/RoutingEngine.js.map +1 -1
  83. package/dist/src/core/SessionManager.d.ts +9 -1
  84. package/dist/src/core/SessionManager.d.ts.map +1 -1
  85. package/dist/src/core/SessionManager.js +27 -5
  86. package/dist/src/core/SessionManager.js.map +1 -1
  87. package/dist/src/core/Step.d.ts +60 -7
  88. package/dist/src/core/Step.d.ts.map +1 -1
  89. package/dist/src/core/Step.js +151 -4
  90. package/dist/src/core/Step.js.map +1 -1
  91. package/dist/src/core/ToolManager.d.ts +234 -0
  92. package/dist/src/core/ToolManager.d.ts.map +1 -0
  93. package/dist/src/core/ToolManager.js +1111 -0
  94. package/dist/src/core/ToolManager.js.map +1 -0
  95. package/dist/src/index.d.ts +5 -4
  96. package/dist/src/index.d.ts.map +1 -1
  97. package/dist/src/index.js +3 -2
  98. package/dist/src/index.js.map +1 -1
  99. package/dist/src/types/agent.d.ts +2 -1
  100. package/dist/src/types/agent.d.ts.map +1 -1
  101. package/dist/src/types/ai.d.ts +1 -1
  102. package/dist/src/types/ai.d.ts.map +1 -1
  103. package/dist/src/types/index.d.ts +3 -2
  104. package/dist/src/types/index.d.ts.map +1 -1
  105. package/dist/src/types/index.js +1 -0
  106. package/dist/src/types/index.js.map +1 -1
  107. package/dist/src/types/route.d.ts +6 -4
  108. package/dist/src/types/route.d.ts.map +1 -1
  109. package/dist/src/types/tool.d.ts +84 -14
  110. package/dist/src/types/tool.d.ts.map +1 -1
  111. package/dist/src/types/tool.js +12 -1
  112. package/dist/src/types/tool.js.map +1 -1
  113. package/dist/src/utils/clone.d.ts.map +1 -1
  114. package/dist/src/utils/clone.js +0 -4
  115. package/dist/src/utils/clone.js.map +1 -1
  116. package/dist/src/utils/history.d.ts +30 -1
  117. package/dist/src/utils/history.d.ts.map +1 -1
  118. package/dist/src/utils/history.js +165 -23
  119. package/dist/src/utils/history.js.map +1 -1
  120. package/dist/src/utils/index.d.ts +1 -1
  121. package/dist/src/utils/index.d.ts.map +1 -1
  122. package/dist/src/utils/index.js +1 -1
  123. package/dist/src/utils/index.js.map +1 -1
  124. package/docs/CONTRIBUTING.md +40 -0
  125. package/docs/README.md +14 -6
  126. package/docs/api/README.md +235 -45
  127. package/docs/api/overview.md +140 -33
  128. package/docs/core/agent/session-management.md +152 -5
  129. package/docs/core/ai-integration/response-processing.md +115 -4
  130. package/docs/core/conversation-flows/routes.md +130 -0
  131. package/docs/core/error-handling.md +638 -0
  132. package/docs/core/tools/tool-definition.md +684 -60
  133. package/docs/core/tools/tool-scoping.md +244 -53
  134. package/docs/guides/error-handling-patterns.md +578 -0
  135. package/docs/guides/getting-started/README.md +139 -28
  136. package/docs/guides/migration/README.md +72 -0
  137. package/docs/guides/migration/response-modal-refactor.md +518 -0
  138. package/examples/advanced-patterns/knowledge-based-agent.ts +6 -6
  139. package/examples/advanced-patterns/persistent-onboarding.ts +30 -43
  140. package/examples/advanced-patterns/streaming-responses.ts +169 -96
  141. package/examples/ai-providers/anthropic-integration.ts +9 -5
  142. package/examples/ai-providers/openai-integration.ts +11 -7
  143. package/examples/core-concepts/basic-agent.ts +106 -67
  144. package/examples/core-concepts/modern-streaming-api.ts +309 -0
  145. package/examples/core-concepts/schema-driven-extraction.ts +10 -7
  146. package/examples/core-concepts/session-management.ts +71 -18
  147. package/examples/integrations/healthcare-integration.ts +15 -29
  148. package/examples/integrations/server-session-management.ts +3 -3
  149. package/examples/persistence/memory-sessions.ts +3 -3
  150. package/examples/tools/basic-tools.ts +293 -89
  151. package/examples/tools/data-enrichment-tools.ts +185 -75
  152. package/package.json +1 -1
  153. package/src/core/Agent.ts +190 -1529
  154. package/src/core/ResponseModal.ts +1798 -0
  155. package/src/core/ResponsePipeline.ts +83 -57
  156. package/src/core/Route.ts +39 -12
  157. package/src/core/RoutingEngine.ts +46 -42
  158. package/src/core/SessionManager.ts +39 -7
  159. package/src/core/Step.ts +198 -20
  160. package/src/core/ToolManager.ts +1394 -0
  161. package/src/index.ts +19 -3
  162. package/src/types/agent.ts +2 -1
  163. package/src/types/ai.ts +1 -1
  164. package/src/types/index.ts +13 -2
  165. package/src/types/route.ts +6 -4
  166. package/src/types/tool.ts +116 -25
  167. package/src/utils/clone.ts +6 -8
  168. package/src/utils/history.ts +190 -27
  169. package/src/utils/index.ts +4 -0
  170. package/dist/cjs/src/core/ToolExecutor.d.ts +0 -45
  171. package/dist/cjs/src/core/ToolExecutor.d.ts.map +0 -1
  172. package/dist/cjs/src/core/ToolExecutor.js +0 -84
  173. package/dist/cjs/src/core/ToolExecutor.js.map +0 -1
  174. package/dist/src/core/ToolExecutor.d.ts +0 -45
  175. package/dist/src/core/ToolExecutor.d.ts.map +0 -1
  176. package/dist/src/core/ToolExecutor.js +0 -80
  177. package/dist/src/core/ToolExecutor.js.map +0 -1
  178. package/docs/core/tools/tool-execution.md +0 -815
  179. package/src/core/ToolExecutor.ts +0 -126
@@ -9,6 +9,7 @@ import type { SessionState } from "../types/session";
9
9
  import type { History, HistoryItem } from "../types/history";
10
10
  import { PersistenceManager } from "./PersistenceManager";
11
11
  import type { PersistenceAdapter } from "../types/persistence";
12
+ import type { Agent } from "./Agent";
12
13
 
13
14
  /**
14
15
  * SessionManager handles session lifecycle and conversation history
@@ -16,11 +17,16 @@ import type { PersistenceAdapter } from "../types/persistence";
16
17
  export class SessionManager<TData = unknown> {
17
18
  private currentSession?: SessionState<TData>;
18
19
  private persistenceManager?: PersistenceManager<TData>;
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ private agent?: Agent<any, TData>;
22
+ private defaultSessionId?: string;
19
23
 
20
24
  constructor(
21
25
  persistenceManagerOrAdapter?:
22
26
  | PersistenceManager<TData>
23
- | PersistenceAdapter<TData>
27
+ | PersistenceAdapter<TData>,
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ agent?: Agent<any, TData>
24
30
  ) {
25
31
  if (persistenceManagerOrAdapter) {
26
32
  // Check if it's a PersistenceManager or an adapter
@@ -33,6 +39,16 @@ export class SessionManager<TData = unknown> {
33
39
  });
34
40
  }
35
41
  }
42
+
43
+ this.agent = agent;
44
+ }
45
+
46
+ /**
47
+ * Set the default session ID to use when getOrCreate is called without parameters
48
+ * @internal Used by Agent to set the sessionId from constructor options
49
+ */
50
+ setDefaultSessionId(sessionId: string): void {
51
+ this.defaultSessionId = sessionId;
36
52
  }
37
53
 
38
54
  /**
@@ -40,16 +56,24 @@ export class SessionManager<TData = unknown> {
40
56
  * Works for sessionIds that exist, don't exist, or auto-generated IDs
41
57
  */
42
58
  async getOrCreate(sessionId?: string): Promise<SessionState<TData>> {
59
+ // Use provided sessionId or fall back to default
60
+ const effectiveSessionId = sessionId || this.defaultSessionId;
61
+
43
62
  // If we already have a session and no sessionId specified, return it
44
- if (this.currentSession && !sessionId) {
63
+ if (this.currentSession && !effectiveSessionId) {
64
+ return this.currentSession;
65
+ }
66
+
67
+ // If we have a session with the same ID, return it
68
+ if (this.currentSession && this.currentSession.id === effectiveSessionId) {
45
69
  return this.currentSession;
46
70
  }
47
71
 
48
72
  // If sessionId provided, try to load it first
49
- if (sessionId && this.persistenceManager) {
73
+ if (effectiveSessionId && this.persistenceManager) {
50
74
  try {
51
75
  const session = await this.persistenceManager.loadSessionState(
52
- sessionId
76
+ effectiveSessionId
53
77
  );
54
78
  if (session) {
55
79
  this.currentSession = session;
@@ -62,7 +86,7 @@ export class SessionManager<TData = unknown> {
62
86
  }
63
87
 
64
88
  // Create new session (with provided ID or auto-generated)
65
- return this.create(sessionId);
89
+ return this.create(effectiveSessionId);
66
90
  }
67
91
 
68
92
  /**
@@ -117,6 +141,9 @@ export class SessionManager<TData = unknown> {
117
141
  session.history.push(historyItem);
118
142
  session.metadata!.lastUpdatedAt = new Date();
119
143
 
144
+ // Ensure currentSession is updated
145
+ this.currentSession = session;
146
+
120
147
  // Auto-save to persistence
121
148
  await this.save();
122
149
  }
@@ -205,7 +232,12 @@ export class SessionManager<TData = unknown> {
205
232
  ...data,
206
233
  };
207
234
  this.currentSession.metadata!.lastUpdatedAt = new Date();
208
-
235
+
236
+ // Synchronize with agent's collected data for bidirectional sync
237
+ if (this.agent) {
238
+ await this.agent.updateCollectedData(this.currentSession.data);
239
+ }
240
+
209
241
  // Auto-save to persistence
210
242
  await this.save();
211
243
  }
@@ -226,7 +258,7 @@ export class SessionManager<TData = unknown> {
226
258
  if (this.currentSession) {
227
259
  this.currentSession.data = {} as Partial<TData>;
228
260
  this.currentSession.metadata!.lastUpdatedAt = new Date();
229
-
261
+
230
262
  // Auto-save to persistence
231
263
  await this.save();
232
264
  }
package/src/core/Step.ts CHANGED
@@ -11,8 +11,9 @@ import type {
11
11
  Guideline,
12
12
  Tool,
13
13
  } from "../types";
14
+ import { ToolScope } from "../types";
14
15
  import { Template } from "../types/template";
15
-
16
+ import { Agent } from './Agent'
16
17
  import { END_ROUTE, END_ROUTE_ID } from "../constants";
17
18
  import { generateStepId } from "../utils/id";
18
19
 
@@ -32,17 +33,21 @@ export class Step<TContext = unknown, TData = unknown> {
32
33
  public prompt?: Template<TContext, TData>;
33
34
  public prepare?:
34
35
  | string
35
- | Tool<TContext, TData, unknown[], unknown>
36
+ | Tool<TContext, TData>
36
37
  | ((context: TContext, data?: Partial<TData>) => void | Promise<void>);
37
38
  public finalize?:
38
39
  | string
39
- | Tool<TContext, TData, unknown[], unknown>
40
+ | Tool<TContext, TData>
40
41
  | ((context: TContext, data?: Partial<TData>) => void | Promise<void>);
41
- public tools?: (string | Tool<TContext, TData, unknown[], unknown>)[];
42
+ public tools?: (string | Tool<TContext, TData>)[];
43
+
44
+ // Reference to parent agent for ToolManager access
45
+ private parentAgent?: Agent<TContext, TData>;
42
46
 
43
47
  constructor(
44
- routeId: string,
45
- options: StepOptions<TContext, TData> = {}
48
+ routeId: string,
49
+ options: StepOptions<TContext, TData> = {},
50
+ parentAgent?: Agent<TContext, TData>
46
51
  ) {
47
52
  // Use provided ID or generate a deterministic one
48
53
  this.id = options.id || generateStepId(routeId, options.description);
@@ -57,6 +62,9 @@ export class Step<TContext = unknown, TData = unknown> {
57
62
  this.prepare = options.prepare;
58
63
  this.finalize = options.finalize;
59
64
  this.tools = options.tools;
65
+
66
+ // Store reference to parent agent for ToolManager access
67
+ this.parentAgent = parentAgent;
60
68
  }
61
69
 
62
70
  /**
@@ -70,31 +78,31 @@ export class Step<TContext = unknown, TData = unknown> {
70
78
  requires?: (keyof TData)[];
71
79
  prompt?: Template<TContext, TData>;
72
80
  prepare?:
73
- | string
74
- | Tool<TContext, TData, unknown[], unknown>
75
- | ((context: TContext, data?: Partial<TData>) => void | Promise<void>);
81
+ | string
82
+ | Tool<TContext, TData>
83
+ | ((context: TContext, data?: Partial<TData>) => void | Promise<void>);
76
84
  finalize?:
77
- | string
78
- | Tool<TContext, TData, unknown[], unknown>
79
- | ((context: TContext, data?: Partial<TData>) => void | Promise<void>);
80
- tools?: (string | Tool<TContext, TData, unknown[], unknown>)[];
85
+ | string
86
+ | Tool<TContext, TData>
87
+ | ((context: TContext, data?: Partial<TData>) => void | Promise<void>);
88
+ tools?: (string | Tool<TContext, TData>)[];
81
89
  }): this {
82
90
  if (config.description !== undefined) {
83
91
  this.description = config.description;
84
92
  }
85
-
93
+
86
94
  if (config.collect !== undefined) {
87
95
  this.collect = config.collect;
88
96
  }
89
-
97
+
90
98
  if (config.skipIf !== undefined) {
91
99
  this.skipIf = config.skipIf;
92
100
  }
93
-
101
+
94
102
  if (config.requires !== undefined) {
95
103
  this.requires = config.requires;
96
104
  }
97
-
105
+
98
106
  if (config.prompt !== undefined) {
99
107
  this.prompt = config.prompt;
100
108
  }
@@ -137,7 +145,7 @@ export class Step<TContext = unknown, TData = unknown> {
137
145
  const endStep = new Step<TContext, TData>(this.routeId, {
138
146
  ...spec,
139
147
  id: END_ROUTE_ID,
140
- });
148
+ }, this.parentAgent);
141
149
  this.nextSteps.push(endStep);
142
150
  return this.createTerminalRef();
143
151
  }
@@ -150,7 +158,7 @@ export class Step<TContext = unknown, TData = unknown> {
150
158
  }
151
159
 
152
160
  // Create new target step for prompt or tool
153
- const targetStep = new Step<TContext, TData>(this.routeId, spec);
161
+ const targetStep = new Step<TContext, TData>(this.routeId, spec, this.parentAgent);
154
162
  this.nextSteps.push(targetStep);
155
163
 
156
164
  return this.createStepRefWithTransition(targetStep.getRef(), targetStep);
@@ -174,7 +182,7 @@ export class Step<TContext = unknown, TData = unknown> {
174
182
  : branchSpec.step;
175
183
 
176
184
  // Create a new step for this branch
177
- const branchStep = new Step<TContext, TData>(this.routeId, stepOptions);
185
+ const branchStep = new Step<TContext, TData>(this.routeId, stepOptions, this.parentAgent);
178
186
  // Add it to our transitions
179
187
  this.nextSteps.push(branchStep);
180
188
  // Create a step result for chaining
@@ -202,6 +210,170 @@ export class Step<TContext = unknown, TData = unknown> {
202
210
  return [...this.guidelines];
203
211
  }
204
212
 
213
+ /**
214
+ * Add a tool to this step using the unified Tool interface
215
+ * Creates and adds the tool to step scope in one operation
216
+ */
217
+ addTool(
218
+ tool: Tool<TContext, TData>
219
+ ): this {
220
+ // Validate tool before adding
221
+ if (!tool || !tool.id || !tool.handler) {
222
+ throw new Error('Invalid tool: must have id and handler properties');
223
+ }
224
+
225
+ // Add to step's tools array
226
+ if (!this.tools) {
227
+ this.tools = [];
228
+ }
229
+ this.tools.push(tool);
230
+
231
+ return this;
232
+ }
233
+
234
+ /**
235
+ * Resolve tool references in the tools array
236
+ * Supports both string IDs (resolved from registry) and inline tool objects
237
+ */
238
+ resolveTools(): Tool<TContext, TData>[] {
239
+ if (!this.tools) {
240
+ return [];
241
+ }
242
+
243
+ const resolvedTools: Tool<TContext, TData>[] = [];
244
+
245
+ for (const toolRef of this.tools) {
246
+ if (typeof toolRef === 'string') {
247
+ // Tool ID - try to resolve from ToolManager using proper scope resolution
248
+ if (this.parentAgent?.tool) {
249
+ const registeredTool = this.parentAgent.tool.find(toolRef);
250
+ if (registeredTool) {
251
+ resolvedTools.push(registeredTool);
252
+ } else {
253
+ // Tool not found - log warning but don't fail
254
+ console.warn(`[Step] Tool ID '${toolRef}' not found in any scope for step ${this.id}`);
255
+ }
256
+ } else {
257
+ console.warn(`[Step] No parent agent available to resolve tool ID '${toolRef}' for step ${this.id}`);
258
+ }
259
+ } else {
260
+ // Inline tool object - validate and use directly
261
+ if (toolRef && toolRef.id && typeof toolRef.handler === 'function') {
262
+ resolvedTools.push(toolRef);
263
+ } else {
264
+ console.warn(`[Step] Invalid inline tool object in step ${this.id}:`, toolRef);
265
+ }
266
+ }
267
+ }
268
+
269
+ return resolvedTools;
270
+ }
271
+
272
+ /**
273
+ * Get all tools available to this step (both inline and resolved from registry)
274
+ */
275
+ getAvailableTools(): (string | Tool<TContext, TData>)[] {
276
+ return this.tools ? [...this.tools] : [];
277
+ }
278
+
279
+ /**
280
+ * Get all resolved tools available to this step using ToolManager
281
+ * This method provides the complete set of tools accessible from this step
282
+ */
283
+ getAllAvailableTools(): Tool<TContext, TData>[] {
284
+ if (!this.parentAgent?.tool) {
285
+ // Fallback to local resolution if no ToolManager available
286
+ return this.resolveTools();
287
+ }
288
+
289
+ // Use ToolManager to get all available tools for this step context
290
+ return this.parentAgent.tool.getAvailable(ToolScope.ALL, this, undefined);
291
+ }
292
+
293
+ /**
294
+ * Find a specific tool by ID using ToolManager resolution
295
+ * This method respects the tool resolution hierarchy: step → route → agent → registry
296
+ */
297
+ findTool(toolId: string, scope?: ToolScope): Tool<TContext, TData> | undefined {
298
+ if (!this.parentAgent?.tool) {
299
+ // Fallback to local resolution if no ToolManager available
300
+ const resolved = this.resolveTools();
301
+ return resolved.find(tool => tool.id === toolId || tool.name === toolId);
302
+ }
303
+
304
+ // Use ToolManager to find the tool with proper scope resolution
305
+ return this.parentAgent.tool.find(toolId, scope || ToolScope.ALL, this, undefined);
306
+ }
307
+
308
+ /**
309
+ * Get tools from a specific scope
310
+ */
311
+ getToolsFromScope(scope: ToolScope): Tool<TContext, TData>[] {
312
+ if (!this.parentAgent?.tool) {
313
+ // Fallback to local resolution if no ToolManager available
314
+ return scope === ToolScope.STEP ? this.resolveTools() : [];
315
+ }
316
+
317
+ return this.parentAgent.tool.getAvailable(scope, this, undefined);
318
+ }
319
+
320
+ /**
321
+ * Get only step-level tools (inline tools in this step)
322
+ */
323
+ getStepTools(): Tool<TContext, TData>[] {
324
+ return this.getToolsFromScope(ToolScope.STEP);
325
+ }
326
+
327
+ /**
328
+ * Get only registered tools accessible from this step
329
+ */
330
+ getRegisteredTools(): Tool<TContext, TData>[] {
331
+ return this.getToolsFromScope(ToolScope.REGISTERED);
332
+ }
333
+
334
+ /**
335
+ * Validate that all tool references in this step can be resolved
336
+ * Returns validation result with details about missing tools
337
+ */
338
+ validateToolReferences(): {
339
+ valid: boolean;
340
+ missing: string[];
341
+ found: string[];
342
+ details: Array<{ id: string; found: boolean; scope?: string; }>;
343
+ } {
344
+ if (!this.tools || this.tools.length === 0) {
345
+ return { valid: true, missing: [], found: [], details: [] };
346
+ }
347
+
348
+ // Extract tool IDs from the tools array
349
+ const toolIds: string[] = [];
350
+ for (const toolRef of this.tools) {
351
+ if (typeof toolRef === 'string') {
352
+ toolIds.push(toolRef);
353
+ } else if (toolRef && toolRef.id) {
354
+ toolIds.push(toolRef.id);
355
+ }
356
+ }
357
+
358
+ if (!this.parentAgent?.tool) {
359
+ // Fallback validation without ToolManager
360
+ const resolved = this.resolveTools();
361
+ const resolvedIds = resolved.map(tool => tool.id);
362
+ const missing = toolIds.filter(id => !resolvedIds.includes(id));
363
+ const found = toolIds.filter(id => resolvedIds.includes(id));
364
+
365
+ return {
366
+ valid: missing.length === 0,
367
+ missing,
368
+ found,
369
+ details: toolIds.map(id => ({ id, found: resolvedIds.includes(id) }))
370
+ };
371
+ }
372
+
373
+ // Use ToolManager validation
374
+ return this.parentAgent.tool.validateToolReferences(toolIds, this);
375
+ }
376
+
205
377
  /**
206
378
  * Get all transitions from this step
207
379
  */
@@ -250,6 +422,8 @@ export class Step<TContext = unknown, TData = unknown> {
250
422
  stepInstance.nextStep(spec),
251
423
  branch: (branches: BranchSpec<TContext, TData>[]) =>
252
424
  stepInstance.branch(branches),
425
+ endRoute: (options?: Omit<StepOptions<TContext, TData>, "step">) =>
426
+ stepInstance.endRoute(options),
253
427
  };
254
428
  }
255
429
 
@@ -270,6 +444,8 @@ export class Step<TContext = unknown, TData = unknown> {
270
444
  branch: () => {
271
445
  throw new Error("Cannot branch from END_ROUTE step");
272
446
  },
447
+ endRoute: (options?: Omit<StepOptions<TContext, TData>, "step">) =>
448
+ this.endRoute(options),
273
449
  };
274
450
  }
275
451
 
@@ -282,6 +458,8 @@ export class Step<TContext = unknown, TData = unknown> {
282
458
  nextStep: (spec: StepOptions<TContext, TData>) => this.nextStep(spec),
283
459
  branch: (branches: BranchSpec<TContext, TData>[]) =>
284
460
  this.branch(branches),
461
+ endRoute: (options?: Omit<StepOptions<TContext, TData>, "step">) =>
462
+ this.endRoute(options),
285
463
  };
286
464
  }
287
465
  }