@falai/agent 0.6.9 → 0.8.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.
Files changed (242) hide show
  1. package/README.md +78 -82
  2. package/dist/adapters/MemoryAdapter.d.ts +1 -1
  3. package/dist/adapters/MemoryAdapter.js +3 -3
  4. package/dist/adapters/MemoryAdapter.js.map +1 -1
  5. package/dist/adapters/MongoAdapter.d.ts +1 -1
  6. package/dist/adapters/MongoAdapter.js +3 -3
  7. package/dist/adapters/MongoAdapter.js.map +1 -1
  8. package/dist/adapters/OpenSearchAdapter.js +7 -7
  9. package/dist/adapters/OpenSearchAdapter.js.map +1 -1
  10. package/dist/adapters/PostgreSQLAdapter.d.ts +1 -1
  11. package/dist/adapters/PostgreSQLAdapter.js +10 -10
  12. package/dist/adapters/PostgreSQLAdapter.js.map +1 -1
  13. package/dist/adapters/PrismaAdapter.d.ts +1 -1
  14. package/dist/adapters/PrismaAdapter.js +4 -4
  15. package/dist/adapters/PrismaAdapter.js.map +1 -1
  16. package/dist/adapters/RedisAdapter.d.ts +1 -1
  17. package/dist/adapters/RedisAdapter.js +3 -3
  18. package/dist/adapters/RedisAdapter.js.map +1 -1
  19. package/dist/adapters/SQLiteAdapter.d.ts +4 -4
  20. package/dist/adapters/SQLiteAdapter.d.ts.map +1 -1
  21. package/dist/adapters/SQLiteAdapter.js +12 -12
  22. package/dist/adapters/SQLiteAdapter.js.map +1 -1
  23. package/dist/adapters/index.d.ts +1 -1
  24. package/dist/adapters/index.d.ts.map +1 -1
  25. package/dist/cjs/adapters/MemoryAdapter.d.ts +1 -1
  26. package/dist/cjs/adapters/MemoryAdapter.js +3 -3
  27. package/dist/cjs/adapters/MemoryAdapter.js.map +1 -1
  28. package/dist/cjs/adapters/MongoAdapter.d.ts +1 -1
  29. package/dist/cjs/adapters/MongoAdapter.js +3 -3
  30. package/dist/cjs/adapters/MongoAdapter.js.map +1 -1
  31. package/dist/cjs/adapters/OpenSearchAdapter.js +7 -7
  32. package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -1
  33. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts +1 -1
  34. package/dist/cjs/adapters/PostgreSQLAdapter.js +10 -10
  35. package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -1
  36. package/dist/cjs/adapters/PrismaAdapter.d.ts +1 -1
  37. package/dist/cjs/adapters/PrismaAdapter.js +4 -4
  38. package/dist/cjs/adapters/PrismaAdapter.js.map +1 -1
  39. package/dist/cjs/adapters/RedisAdapter.d.ts +1 -1
  40. package/dist/cjs/adapters/RedisAdapter.js +3 -3
  41. package/dist/cjs/adapters/RedisAdapter.js.map +1 -1
  42. package/dist/cjs/adapters/SQLiteAdapter.d.ts +4 -4
  43. package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +1 -1
  44. package/dist/cjs/adapters/SQLiteAdapter.js +12 -12
  45. package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -1
  46. package/dist/cjs/adapters/index.d.ts +1 -1
  47. package/dist/cjs/adapters/index.d.ts.map +1 -1
  48. package/dist/cjs/constants/index.d.ts +4 -4
  49. package/dist/cjs/constants/index.js +5 -5
  50. package/dist/cjs/core/Agent.d.ts +22 -22
  51. package/dist/cjs/core/Agent.d.ts.map +1 -1
  52. package/dist/cjs/core/Agent.js +168 -160
  53. package/dist/cjs/core/Agent.js.map +1 -1
  54. package/dist/cjs/core/Events.d.ts +6 -6
  55. package/dist/cjs/core/Events.d.ts.map +1 -1
  56. package/dist/cjs/core/PersistenceManager.d.ts +13 -13
  57. package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
  58. package/dist/cjs/core/PersistenceManager.js +24 -24
  59. package/dist/cjs/core/PersistenceManager.js.map +1 -1
  60. package/dist/cjs/core/ResponseEngine.d.ts +3 -8
  61. package/dist/cjs/core/ResponseEngine.d.ts.map +1 -1
  62. package/dist/cjs/core/ResponseEngine.js +8 -8
  63. package/dist/cjs/core/ResponseEngine.js.map +1 -1
  64. package/dist/cjs/core/Route.d.ts +17 -17
  65. package/dist/cjs/core/Route.d.ts.map +1 -1
  66. package/dist/cjs/core/Route.js +33 -33
  67. package/dist/cjs/core/Route.js.map +1 -1
  68. package/dist/cjs/core/RoutingEngine.d.ts +31 -31
  69. package/dist/cjs/core/RoutingEngine.d.ts.map +1 -1
  70. package/dist/cjs/core/RoutingEngine.js +196 -196
  71. package/dist/cjs/core/RoutingEngine.js.map +1 -1
  72. package/dist/cjs/core/Step.d.ts +72 -0
  73. package/dist/cjs/core/Step.d.ts.map +1 -0
  74. package/dist/cjs/core/Step.js +150 -0
  75. package/dist/cjs/core/Step.js.map +1 -0
  76. package/dist/cjs/core/ToolExecutor.d.ts +5 -5
  77. package/dist/cjs/core/ToolExecutor.d.ts.map +1 -1
  78. package/dist/cjs/core/ToolExecutor.js +8 -8
  79. package/dist/cjs/core/ToolExecutor.js.map +1 -1
  80. package/dist/cjs/core/Transition.d.ts +14 -14
  81. package/dist/cjs/core/Transition.d.ts.map +1 -1
  82. package/dist/cjs/core/Transition.js +48 -19
  83. package/dist/cjs/core/Transition.js.map +1 -1
  84. package/dist/cjs/index.d.ts +7 -7
  85. package/dist/cjs/index.d.ts.map +1 -1
  86. package/dist/cjs/index.js +8 -8
  87. package/dist/cjs/index.js.map +1 -1
  88. package/dist/cjs/types/agent.d.ts +9 -9
  89. package/dist/cjs/types/agent.d.ts.map +1 -1
  90. package/dist/cjs/types/ai.d.ts +2 -2
  91. package/dist/cjs/types/ai.d.ts.map +1 -1
  92. package/dist/cjs/types/history.d.ts +3 -3
  93. package/dist/cjs/types/history.d.ts.map +1 -1
  94. package/dist/cjs/types/index.d.ts +1 -1
  95. package/dist/cjs/types/index.d.ts.map +1 -1
  96. package/dist/cjs/types/persistence.d.ts +5 -5
  97. package/dist/cjs/types/persistence.d.ts.map +1 -1
  98. package/dist/cjs/types/route.d.ts +57 -52
  99. package/dist/cjs/types/route.d.ts.map +1 -1
  100. package/dist/cjs/types/session.d.ts +27 -27
  101. package/dist/cjs/types/session.d.ts.map +1 -1
  102. package/dist/cjs/types/session.js +48 -50
  103. package/dist/cjs/types/session.js.map +1 -1
  104. package/dist/cjs/types/tool.d.ts +13 -13
  105. package/dist/cjs/types/tool.d.ts.map +1 -1
  106. package/dist/cjs/utils/id.d.ts +8 -3
  107. package/dist/cjs/utils/id.d.ts.map +1 -1
  108. package/dist/cjs/utils/id.js +16 -7
  109. package/dist/cjs/utils/id.js.map +1 -1
  110. package/dist/constants/index.d.ts +4 -4
  111. package/dist/constants/index.js +4 -4
  112. package/dist/core/Agent.d.ts +22 -22
  113. package/dist/core/Agent.d.ts.map +1 -1
  114. package/dist/core/Agent.js +170 -162
  115. package/dist/core/Agent.js.map +1 -1
  116. package/dist/core/Events.d.ts +6 -6
  117. package/dist/core/Events.d.ts.map +1 -1
  118. package/dist/core/PersistenceManager.d.ts +13 -13
  119. package/dist/core/PersistenceManager.d.ts.map +1 -1
  120. package/dist/core/PersistenceManager.js +25 -25
  121. package/dist/core/PersistenceManager.js.map +1 -1
  122. package/dist/core/ResponseEngine.d.ts +3 -8
  123. package/dist/core/ResponseEngine.d.ts.map +1 -1
  124. package/dist/core/ResponseEngine.js +8 -8
  125. package/dist/core/ResponseEngine.js.map +1 -1
  126. package/dist/core/Route.d.ts +17 -17
  127. package/dist/core/Route.d.ts.map +1 -1
  128. package/dist/core/Route.js +33 -33
  129. package/dist/core/Route.js.map +1 -1
  130. package/dist/core/RoutingEngine.d.ts +31 -31
  131. package/dist/core/RoutingEngine.d.ts.map +1 -1
  132. package/dist/core/RoutingEngine.js +197 -197
  133. package/dist/core/RoutingEngine.js.map +1 -1
  134. package/dist/core/Step.d.ts +72 -0
  135. package/dist/core/Step.d.ts.map +1 -0
  136. package/dist/core/Step.js +146 -0
  137. package/dist/core/Step.js.map +1 -0
  138. package/dist/core/ToolExecutor.d.ts +5 -5
  139. package/dist/core/ToolExecutor.d.ts.map +1 -1
  140. package/dist/core/ToolExecutor.js +8 -8
  141. package/dist/core/ToolExecutor.js.map +1 -1
  142. package/dist/core/Transition.d.ts +14 -14
  143. package/dist/core/Transition.d.ts.map +1 -1
  144. package/dist/core/Transition.js +48 -19
  145. package/dist/core/Transition.js.map +1 -1
  146. package/dist/index.d.ts +7 -7
  147. package/dist/index.d.ts.map +1 -1
  148. package/dist/index.js +4 -4
  149. package/dist/index.js.map +1 -1
  150. package/dist/types/agent.d.ts +9 -9
  151. package/dist/types/agent.d.ts.map +1 -1
  152. package/dist/types/ai.d.ts +2 -2
  153. package/dist/types/ai.d.ts.map +1 -1
  154. package/dist/types/history.d.ts +3 -3
  155. package/dist/types/history.d.ts.map +1 -1
  156. package/dist/types/index.d.ts +1 -1
  157. package/dist/types/index.d.ts.map +1 -1
  158. package/dist/types/persistence.d.ts +5 -5
  159. package/dist/types/persistence.d.ts.map +1 -1
  160. package/dist/types/route.d.ts +57 -52
  161. package/dist/types/route.d.ts.map +1 -1
  162. package/dist/types/session.d.ts +27 -27
  163. package/dist/types/session.d.ts.map +1 -1
  164. package/dist/types/session.js +44 -46
  165. package/dist/types/session.js.map +1 -1
  166. package/dist/types/tool.d.ts +13 -13
  167. package/dist/types/tool.d.ts.map +1 -1
  168. package/dist/utils/id.d.ts +8 -3
  169. package/dist/utils/id.d.ts.map +1 -1
  170. package/dist/utils/id.js +14 -6
  171. package/dist/utils/id.js.map +1 -1
  172. package/docs/ADAPTERS.md +21 -21
  173. package/docs/AGENT.md +63 -61
  174. package/docs/API_REFERENCE.md +218 -220
  175. package/docs/ARCHITECTURE.md +99 -104
  176. package/docs/CONTEXT_MANAGEMENT.md +84 -91
  177. package/docs/CONTRIBUTING.md +3 -3
  178. package/docs/DOCS.md +18 -18
  179. package/docs/DOMAINS.md +18 -18
  180. package/docs/EXAMPLES.md +44 -44
  181. package/docs/GETTING_STARTED.md +63 -66
  182. package/docs/PERSISTENCE.md +70 -74
  183. package/docs/PROVIDERS.md +6 -6
  184. package/docs/README.md +6 -6
  185. package/docs/ROUTES.md +218 -220
  186. package/docs/STEPS.md +883 -0
  187. package/examples/business-onboarding.ts +85 -82
  188. package/examples/company-qna-agent.ts +69 -68
  189. package/examples/custom-database-persistence.ts +89 -91
  190. package/examples/declarative-agent.ts +33 -33
  191. package/examples/domain-scoping.ts +20 -20
  192. package/examples/extracted-data-modification.ts +93 -98
  193. package/examples/healthcare-agent.ts +90 -92
  194. package/examples/openai-agent.ts +30 -33
  195. package/examples/opensearch-persistence.ts +46 -48
  196. package/examples/persistent-onboarding.ts +67 -68
  197. package/examples/prisma-persistence.ts +111 -115
  198. package/examples/prisma-schema.example.prisma +3 -3
  199. package/examples/redis-persistence.ts +70 -76
  200. package/examples/route-transitions.ts +72 -48
  201. package/examples/rules-prohibitions.ts +31 -31
  202. package/examples/streaming-agent.ts +29 -29
  203. package/examples/travel-agent.ts +95 -110
  204. package/package.json +1 -1
  205. package/src/adapters/MemoryAdapter.ts +4 -4
  206. package/src/adapters/MongoAdapter.ts +4 -4
  207. package/src/adapters/OpenSearchAdapter.ts +8 -8
  208. package/src/adapters/PostgreSQLAdapter.ts +11 -11
  209. package/src/adapters/PrismaAdapter.ts +5 -5
  210. package/src/adapters/RedisAdapter.ts +4 -4
  211. package/src/adapters/SQLiteAdapter.ts +16 -16
  212. package/src/adapters/index.ts +1 -1
  213. package/src/constants/index.ts +4 -4
  214. package/src/core/Agent.ts +218 -214
  215. package/src/core/Events.ts +12 -12
  216. package/src/core/PersistenceManager.ts +32 -36
  217. package/src/core/ResponseEngine.ts +11 -17
  218. package/src/core/Route.ts +55 -49
  219. package/src/core/RoutingEngine.ts +252 -258
  220. package/src/core/Step.ts +197 -0
  221. package/src/core/ToolExecutor.ts +11 -11
  222. package/src/core/Transition.ts +72 -26
  223. package/src/index.ts +8 -8
  224. package/src/types/agent.ts +9 -9
  225. package/src/types/ai.ts +2 -2
  226. package/src/types/history.ts +3 -3
  227. package/src/types/index.ts +1 -1
  228. package/src/types/persistence.ts +6 -6
  229. package/src/types/route.ts +77 -61
  230. package/src/types/session.ts +75 -78
  231. package/src/types/tool.ts +17 -17
  232. package/src/utils/id.ts +15 -6
  233. package/dist/cjs/core/State.d.ts +0 -72
  234. package/dist/cjs/core/State.d.ts.map +0 -1
  235. package/dist/cjs/core/State.js +0 -148
  236. package/dist/cjs/core/State.js.map +0 -1
  237. package/dist/core/State.d.ts +0 -72
  238. package/dist/core/State.d.ts.map +0 -1
  239. package/dist/core/State.js +0 -144
  240. package/dist/core/State.js.map +0 -1
  241. package/docs/STATES.md +0 -888
  242. package/src/core/State.ts +0 -212
@@ -1,11 +1,11 @@
1
1
  import type { Event } from "../types/history";
2
2
  import type { Route } from "./Route";
3
- import type { State } from "./State";
3
+ import type { Step } from "./Step";
4
4
  import type { StructuredSchema } from "../types/schema";
5
5
  import type { RoutingDecision } from "../types/routing";
6
- import type { SessionState } from "../types/session";
6
+ import type { SessionStep } from "../types/session";
7
7
  import type { AiProvider } from "../types/ai";
8
- import { enterRoute, mergeExtracted } from "../types/session";
8
+ import { enterRoute, mergeCollected } from "../types/session";
9
9
  import { PromptComposer } from "./PromptComposer";
10
10
  import { getLastMessageFromHistory } from "../utils/event";
11
11
  import { logger } from "../utils/logger";
@@ -13,8 +13,8 @@ import { logger } from "../utils/logger";
13
13
  export interface RoutingDecisionOutput {
14
14
  context: string;
15
15
  routes: Record<string, number>;
16
- selectedStateId?: string; // For active route, which state to transition to
17
- stateReasoning?: string; // Why this state was selected
16
+ selectedStepId?: string; // For active route, which step to transition to
17
+ stepReasoning?: string; // Why this step was selected
18
18
  responseDirectives?: string[];
19
19
  extractions?: Array<{
20
20
  name: string;
@@ -37,12 +37,12 @@ export class RoutingEngine<TContext = unknown> {
37
37
 
38
38
  /**
39
39
  * Optimized decision for single-route scenarios
40
- * Skips route scoring and only does state selection
40
+ * Skips route scoring and only does step selection
41
41
  * @private
42
42
  */
43
- private async decideSingleRouteState(params: {
43
+ private async decideSingleRouteStep(params: {
44
44
  route: Route<TContext, unknown>;
45
- session: SessionState;
45
+ session: SessionStep;
46
46
  history: Event[];
47
47
  agentMeta?: {
48
48
  name?: string;
@@ -50,17 +50,18 @@ export class RoutingEngine<TContext = unknown> {
50
50
  description?: string;
51
51
  personality?: string;
52
52
  };
53
- ai: AiProvider;
53
+ provider: AiProvider;
54
54
  context: TContext;
55
55
  signal?: AbortSignal;
56
56
  }): Promise<{
57
57
  selectedRoute?: Route<TContext>;
58
- selectedState?: State<TContext>;
58
+ selectedStep?: Step<TContext>;
59
59
  responseDirectives?: string[];
60
- session: SessionState;
60
+ session: SessionStep;
61
61
  isRouteComplete?: boolean;
62
62
  }> {
63
- const { route, session, history, agentMeta, ai, context, signal } = params;
63
+ const { route, session, history, agentMeta, provider, context, signal } =
64
+ params;
64
65
 
65
66
  let updatedSession = session;
66
67
  const selectedRoute = route;
@@ -69,7 +70,7 @@ export class RoutingEngine<TContext = unknown> {
69
70
  if (!session.currentRoute || session.currentRoute.id !== route.id) {
70
71
  updatedSession = enterRoute(session, route.id, route.title);
71
72
  if (route.initialData) {
72
- updatedSession = mergeExtracted(updatedSession, route.initialData);
73
+ updatedSession = mergeCollected(updatedSession, route.initialData);
73
74
  logger.debug(
74
75
  `[RoutingEngine] Single-route: Merged initial data:`,
75
76
  route.initialData
@@ -80,18 +81,18 @@ export class RoutingEngine<TContext = unknown> {
80
81
  );
81
82
  }
82
83
 
83
- // Get candidate states
84
- const currentState = updatedSession.currentState
85
- ? route.getState(updatedSession.currentState.id)
84
+ // Get candidate steps
85
+ const currentStep = updatedSession.currentStep
86
+ ? route.getStep(updatedSession.currentStep.id)
86
87
  : undefined;
87
- const candidates = this.getCandidateStates(
88
+ const candidates = this.getCandidateSteps(
88
89
  route,
89
- currentState,
90
- updatedSession.extracted || {}
90
+ currentStep,
91
+ updatedSession.data || {}
91
92
  );
92
93
 
93
94
  if (candidates.length === 0) {
94
- logger.warn(`[RoutingEngine] Single-route: No valid states found`);
95
+ logger.warn(`[RoutingEngine] Single-route: No valid steps found`);
95
96
  return { selectedRoute, session: updatedSession };
96
97
  }
97
98
 
@@ -100,233 +101,229 @@ export class RoutingEngine<TContext = unknown> {
100
101
  const isRouteComplete = candidates[0].isRouteComplete;
101
102
  if (isRouteComplete) {
102
103
  logger.debug(
103
- `[RoutingEngine] Single-route: Route complete - all data collected, END_STATE reached`
104
+ `[RoutingEngine] Single-route: Route complete - all data collected, END_ROUTE reached`
104
105
  );
105
- // Don't return a selectedState when route is complete - there's no state to enter
106
+ // Don't return a selectedStep when route is complete - there's no step to enter
106
107
  return {
107
108
  selectedRoute,
108
- selectedState: undefined,
109
+ selectedStep: undefined,
109
110
  session: updatedSession,
110
111
  isRouteComplete: true,
111
112
  };
112
113
  } else {
113
114
  logger.debug(
114
- `[RoutingEngine] Single-route: Only one valid state: ${candidates[0].state.id}`
115
+ `[RoutingEngine] Single-route: Only one valid step: ${candidates[0].step.id}`
115
116
  );
116
117
  return {
117
118
  selectedRoute,
118
- selectedState: candidates[0].state,
119
+ selectedStep: candidates[0].step,
119
120
  session: updatedSession,
120
121
  isRouteComplete: false,
121
122
  };
122
123
  }
123
124
  }
124
125
 
125
- // Multiple candidates - use AI to select best state
126
+ // Multiple candidates - use AI to select best step
126
127
  const lastUserMessage = getLastMessageFromHistory(history);
127
- const statePrompt = this.buildStateSelectionPrompt(
128
+ const stepPrompt = this.buildStepSelectionPrompt(
128
129
  route,
129
- currentState,
130
+ currentStep,
130
131
  candidates,
131
- updatedSession.extracted || {},
132
+ updatedSession.data || {},
132
133
  history,
133
134
  lastUserMessage,
134
135
  agentMeta
135
136
  );
136
137
 
137
- const stateSchema = this.buildStateSelectionSchema(
138
- candidates.map((c) => c.state.id)
138
+ const stepSchema = this.buildStepSelectionSchema(
139
+ candidates.map((c) => c.step.id)
139
140
  );
140
141
 
141
- const stateResult = await ai.generateMessage<
142
+ const stepResult = await provider.generateMessage<
142
143
  TContext,
143
144
  {
144
145
  reasoning: string;
145
- selectedStateId: string;
146
+ selectedStepId: string;
146
147
  responseDirectives?: string[];
147
148
  }
148
149
  >({
149
- prompt: statePrompt,
150
+ prompt: stepPrompt,
150
151
  history,
151
152
  context,
152
153
  signal,
153
154
  parameters: {
154
- jsonSchema: stateSchema,
155
- schemaName: "state_selection",
155
+ jsonSchema: stepSchema,
156
+ schemaName: "step_selection",
156
157
  },
157
158
  });
158
159
 
159
- const selectedStateId = stateResult.structured?.selectedStateId;
160
- const selectedState = candidates.find(
161
- (c) => c.state.id === selectedStateId
162
- )?.state;
160
+ const selectedStepId = stepResult.structured?.selectedStepId;
161
+ const selectedStep = candidates.find(
162
+ (c) => c.step.id === selectedStepId
163
+ )?.step;
163
164
 
164
- if (selectedState) {
165
+ if (selectedStep) {
165
166
  logger.debug(
166
- `[RoutingEngine] Single-route: AI selected state: ${selectedState.id}`
167
+ `[RoutingEngine] Single-route: AI selected step: ${selectedStep.id}`
167
168
  );
168
169
  logger.debug(
169
- `[RoutingEngine] Single-route: Reasoning: ${stateResult.structured?.reasoning}`
170
+ `[RoutingEngine] Single-route: Reasoning: ${stepResult.structured?.reasoning}`
170
171
  );
171
172
  } else {
172
173
  logger.warn(
173
- `[RoutingEngine] Single-route: Invalid state ID returned, using first candidate`
174
+ `[RoutingEngine] Single-route: Invalid step ID returned, using first candidate`
174
175
  );
175
176
  }
176
177
 
177
178
  return {
178
179
  selectedRoute,
179
- selectedState: selectedState || candidates[0].state,
180
- responseDirectives: stateResult.structured?.responseDirectives,
180
+ selectedStep: selectedStep || candidates[0].step,
181
+ responseDirectives: stepResult.structured?.responseDirectives,
181
182
  session: updatedSession,
182
183
  };
183
184
  }
184
185
 
185
186
  /**
186
- * Recursively traverse state chain to find first non-skipped state or END_STATE
187
+ * Recursively traverse step chain to find first non-skipped step or END_ROUTE
187
188
  * @private
188
189
  */
189
- private findFirstValidStateRecursive<TExtracted = unknown>(
190
- currentState: State<TContext, TExtracted>,
191
- extracted: Partial<TExtracted>,
190
+ private findFirstValidStepRecursive<TData = unknown>(
191
+ currentStep: Step<TContext, TData>,
192
+ data: Partial<TData>,
192
193
  visited: Set<string>
193
194
  ): {
194
- state?: State<TContext, TExtracted>;
195
+ step?: Step<TContext, TData>;
195
196
  condition?: string;
196
197
  isRouteComplete?: boolean;
197
198
  } {
198
199
  // Prevent infinite loops
199
- if (visited.has(currentState.id)) {
200
+ if (visited.has(currentStep.id)) {
200
201
  return {};
201
202
  }
202
- visited.add(currentState.id);
203
+ visited.add(currentStep.id);
203
204
 
204
- const transitions = currentState.getTransitions();
205
+ const transitions = currentStep.getTransitions();
205
206
 
206
207
  for (const transition of transitions) {
207
208
  const target = transition.getTarget();
208
209
 
209
- // Check for END_STATE transition
210
+ // Check for END_ROUTE transition
210
211
  if (
211
212
  !target &&
212
- transition.spec.state &&
213
- typeof transition.spec.state === "symbol"
213
+ transition.spec.step &&
214
+ typeof transition.spec.step === "symbol"
214
215
  ) {
215
- // Found END_STATE - route is complete
216
+ // Found END_ROUTE - route is complete
216
217
  return {
217
- isRouteComplete: true
218
+ isRouteComplete: true,
218
219
  };
219
220
  }
220
221
 
221
222
  if (!target) continue;
222
223
 
223
- // If target should NOT be skipped, we found our state
224
- if (!target.shouldSkip(extracted)) {
224
+ // If target should NOT be skipped, we found our step
225
+ if (!target.shouldSkip(data)) {
225
226
  logger.debug(
226
- `[RoutingEngine] Found valid state after skipping: ${target.id}`
227
+ `[RoutingEngine] Found valid step after skipping: ${target.id}`
227
228
  );
228
229
  return {
229
- state: target,
230
+ step: target,
230
231
  condition: transition.condition,
231
232
  };
232
233
  }
233
234
 
234
235
  // Target should be skipped too - recurse deeper
235
236
  logger.debug(
236
- `[RoutingEngine] Skipping state ${target.id} (skipIf condition met), continuing traversal...`
237
- );
238
- const result = this.findFirstValidStateRecursive(
239
- target,
240
- extracted,
241
- visited
237
+ `[RoutingEngine] Skipping step ${target.id} (skipIf condition met), continuing traversal...`
242
238
  );
239
+ const result = this.findFirstValidStepRecursive(target, data, visited);
243
240
 
244
- // If we found something (a valid state or END_STATE), return it
245
- if (result.state || result.isRouteComplete) {
241
+ // If we found something (a valid step or END_ROUTE), return it
242
+ if (result.step || result.isRouteComplete) {
246
243
  return result;
247
244
  }
248
245
  }
249
246
 
250
- // No valid states or END_STATE found in this branch
247
+ // No valid steps or END_ROUTE found in this branch
251
248
  return {};
252
249
  }
253
250
 
254
251
  /**
255
- * Identify valid next candidate states based on current state and extracted data
256
- * Returns state with isRouteComplete flag if route is complete (all states skipped + has END_STATE transition)
252
+ * Identify valid next candidate steps based on current step and collected data
253
+ * Returns step with isRouteComplete flag if route is complete (all steps skipped + has END_ROUTE transition)
257
254
  */
258
- getCandidateStates<TExtracted = unknown>(
259
- route: Route<TContext, TExtracted>,
260
- currentState: State<TContext, TExtracted> | undefined,
261
- extracted: Partial<TExtracted>
255
+ getCandidateSteps<TData = unknown>(
256
+ route: Route<TContext, TData>,
257
+ currentStep: Step<TContext, TData> | undefined,
258
+ data: Partial<TData>
262
259
  ): Array<{
263
- state: State<TContext, TExtracted>;
260
+ step: Step<TContext, TData>;
264
261
  condition?: string;
265
- requiredData?: string[];
266
- gatherFields?: string[];
262
+ requires?: string[];
263
+ collectFields?: string[];
267
264
  isRouteComplete?: boolean;
268
265
  }> {
269
266
  const candidates: Array<{
270
- state: State<TContext, TExtracted>;
267
+ step: Step<TContext, TData>;
271
268
  condition?: string;
272
- requiredData?: string[];
273
- gatherFields?: string[];
269
+ requires?: string[];
270
+ collectFields?: string[];
274
271
  isRouteComplete?: boolean;
275
272
  }> = [];
276
273
 
277
- if (!currentState) {
278
- const initialState = route.initialState;
279
- if (initialState.shouldSkip(extracted)) {
280
- // Initial state should be skipped - recursively traverse to find first non-skipped state or END_STATE
281
- const result = this.findFirstValidStateRecursive(
282
- initialState,
283
- extracted,
274
+ if (!currentStep) {
275
+ const initialStep = route.initialStep;
276
+ if (initialStep.shouldSkip(data)) {
277
+ // Initial step should be skipped - recursively traverse to find first non-skipped step or END_ROUTE
278
+ const result = this.findFirstValidStepRecursive(
279
+ initialStep,
280
+ data,
284
281
  new Set<string>()
285
282
  );
286
283
 
287
284
  if (result.isRouteComplete) {
288
- // All states are skipped and we reached END_STATE
285
+ // All steps are skipped and we reached END_ROUTE
289
286
  logger.debug(
290
- `[RoutingEngine] Route complete on entry: all states skipped, END_STATE reached`
287
+ `[RoutingEngine] Route complete on entry: all steps skipped, END_ROUTE reached`
291
288
  );
292
289
  return [
293
290
  {
294
- state: initialState,
291
+ step: initialStep,
295
292
  condition: "Route complete - all data collected on entry",
296
293
  isRouteComplete: true,
297
294
  },
298
295
  ];
299
- } else if (result.state) {
300
- // Found a non-skipped state
296
+ } else if (result.step) {
297
+ // Found a non-skipped step
301
298
  candidates.push({
302
- state: result.state,
299
+ step: result.step,
303
300
  condition: result.condition,
304
- requiredData: result.state.requiredData,
305
- gatherFields: result.state.gatherFields,
301
+ requires: result.step.requires,
302
+ collectFields: result.step.collectFields,
306
303
  });
307
304
  }
308
- // If no state found and not complete, fall through to return empty candidates
305
+ // If no step found and not complete, fall through to return empty candidates
309
306
  } else {
310
307
  candidates.push({
311
- state: initialState,
312
- requiredData: initialState.requiredData,
313
- gatherFields: initialState.gatherFields,
308
+ step: initialStep,
309
+ requires: initialStep.requires,
310
+ collectFields: initialStep.collectFields,
314
311
  });
315
312
  }
316
313
  return candidates;
317
314
  }
318
315
 
319
- const transitions = currentState.getTransitions();
316
+ const transitions = currentStep.getTransitions();
320
317
  let hasEndRoute = false;
321
318
 
322
319
  for (const transition of transitions) {
323
320
  const target = transition.getTarget();
324
321
 
325
- // Check for END_STATE transition (no target state)
322
+ // Check for END_ROUTE transition (no target step)
326
323
  if (
327
324
  !target &&
328
- transition.spec.state &&
329
- typeof transition.spec.state === "symbol"
325
+ transition.spec.step &&
326
+ typeof transition.spec.step === "symbol"
330
327
  ) {
331
328
  hasEndRoute = true;
332
329
  continue;
@@ -334,64 +331,64 @@ export class RoutingEngine<TContext = unknown> {
334
331
 
335
332
  if (!target) continue;
336
333
 
337
- if (target.shouldSkip(extracted)) {
334
+ if (target.shouldSkip(data)) {
338
335
  logger.debug(
339
- `[RoutingEngine] Skipping state ${target.id} (skipIf condition met)`
336
+ `[RoutingEngine] Skipping step ${target.id} (skipIf condition met)`
340
337
  );
341
338
 
342
- // Recursively traverse to find next valid state or END_STATE
343
- const result = this.findFirstValidStateRecursive(
339
+ // Recursively traverse to find next valid step or END_ROUTE
340
+ const result = this.findFirstValidStepRecursive(
344
341
  target,
345
- extracted,
346
- new Set<string>([currentState.id]) // Already visited current state
342
+ data,
343
+ new Set<string>([currentStep.id]) // Already visited current step
347
344
  );
348
345
 
349
346
  if (result.isRouteComplete) {
350
347
  hasEndRoute = true;
351
- } else if (result.state) {
352
- // Found a non-skipped state deeper in the chain
348
+ } else if (result.step) {
349
+ // Found a non-skipped step deeper in the chain
353
350
  candidates.push({
354
- state: result.state,
351
+ step: result.step,
355
352
  condition: result.condition || transition.condition,
356
- requiredData: result.state.requiredData,
357
- gatherFields: result.state.gatherFields,
353
+ requires: result.step.requires,
354
+ collectFields: result.step.collectFields,
358
355
  });
359
356
  }
360
357
  continue;
361
358
  }
362
359
 
363
360
  candidates.push({
364
- state: target,
361
+ step: target,
365
362
  condition: transition.condition,
366
- requiredData: target.requiredData,
367
- gatherFields: target.gatherFields,
363
+ requires: target.requires,
364
+ collectFields: target.collectFields,
368
365
  });
369
366
  }
370
367
 
371
368
  // If no valid candidates found
372
369
  if (candidates.length === 0) {
373
- // If current state has END_STATE transition, the route is complete
370
+ // If current step has END_ROUTE transition, the route is complete
374
371
  if (hasEndRoute) {
375
372
  logger.debug(
376
- `[RoutingEngine] Route complete: all states processed, END_STATE reached`
373
+ `[RoutingEngine] Route complete: all steps processed, END_ROUTE reached`
377
374
  );
378
- // Return current state with completion flag
375
+ // Return current step with completion flag
379
376
  return [
380
377
  {
381
- state: currentState,
378
+ step: currentStep,
382
379
  condition: "Route complete - all data collected",
383
380
  isRouteComplete: true,
384
381
  },
385
382
  ];
386
383
  }
387
384
 
388
- // Otherwise, stay in current state if it's still valid
389
- if (!currentState.shouldSkip(extracted)) {
385
+ // Otherwise, stay in current step if it's still valid
386
+ if (!currentStep.shouldSkip(data)) {
390
387
  candidates.push({
391
- state: currentState,
392
- condition: "Continue in current state (no valid transitions)",
393
- requiredData: currentState.requiredData,
394
- gatherFields: currentState.gatherFields,
388
+ step: currentStep,
389
+ condition: "Continue in current step (no valid transitions)",
390
+ requires: currentStep.requires,
391
+ collectFields: currentStep.collectFields,
395
392
  });
396
393
  }
397
394
  }
@@ -400,14 +397,14 @@ export class RoutingEngine<TContext = unknown> {
400
397
  }
401
398
 
402
399
  /**
403
- * Full routing orchestration: builds prompt and schema, calls AI, selects route/state,
400
+ * Full routing orchestration: builds prompt and schema, calls AI, selects route/step,
404
401
  * and updates the session (including initialData merge when entering a new route).
405
402
  *
406
- * OPTIMIZATION: If there's only 1 route, skips route scoring and only does state selection.
403
+ * OPTIMIZATION: If there's only 1 route, skips route scoring and only does step selection.
407
404
  */
408
- async decideRouteAndState(params: {
405
+ async decideRouteAndStep(params: {
409
406
  routes: Route<TContext, unknown>[];
410
- session: SessionState;
407
+ session: SessionStep;
411
408
  history: Event[];
412
409
  agentMeta?: {
413
410
  name?: string;
@@ -415,30 +412,31 @@ export class RoutingEngine<TContext = unknown> {
415
412
  description?: string;
416
413
  personality?: string;
417
414
  };
418
- ai: AiProvider;
415
+ provider: AiProvider;
419
416
  context: TContext;
420
417
  signal?: AbortSignal;
421
418
  }): Promise<{
422
419
  selectedRoute?: Route<TContext>;
423
- selectedState?: State<TContext>;
420
+ selectedStep?: Step<TContext>;
424
421
  responseDirectives?: string[];
425
- session: SessionState;
422
+ session: SessionStep;
426
423
  isRouteComplete?: boolean;
427
424
  }> {
428
- const { routes, session, history, agentMeta, ai, context, signal } = params;
425
+ const { routes, session, history, agentMeta, provider, context, signal } =
426
+ params;
429
427
 
430
428
  if (routes.length === 0) {
431
429
  return { session };
432
430
  }
433
431
 
434
- // OPTIMIZATION: Single route - skip route scoring, only do state selection
432
+ // OPTIMIZATION: Single route - skip route scoring, only do step selection
435
433
  if (routes.length === 1) {
436
- return this.decideSingleRouteState({
434
+ return this.decideSingleRouteStep({
437
435
  route: routes[0],
438
436
  session,
439
437
  history,
440
438
  agentMeta,
441
- ai,
439
+ provider,
442
440
  context,
443
441
  signal,
444
442
  });
@@ -446,13 +444,13 @@ export class RoutingEngine<TContext = unknown> {
446
444
 
447
445
  const lastUserMessage = getLastMessageFromHistory(history);
448
446
 
449
- let activeRouteStates:
447
+ let activeRouteSteps:
450
448
  | Array<{
451
- stateId: string;
449
+ stepId: string;
452
450
  description: string;
453
451
  condition?: string;
454
- requiredData?: string[];
455
- gatherFields?: string[];
452
+ requires?: string[];
453
+ collectFields?: string[];
456
454
  }>
457
455
  | undefined;
458
456
  let activeRoute: Route<TContext> | undefined;
@@ -461,13 +459,13 @@ export class RoutingEngine<TContext = unknown> {
461
459
  if (session.currentRoute) {
462
460
  activeRoute = routes.find((r) => r.id === session.currentRoute?.id);
463
461
  if (activeRoute) {
464
- const currentState = session.currentState
465
- ? activeRoute.getState(session.currentState.id)
462
+ const currentStep = session.currentStep
463
+ ? activeRoute.getStep(session.currentStep.id)
466
464
  : undefined;
467
- const candidates = this.getCandidateStates(
465
+ const candidates = this.getCandidateSteps(
468
466
  activeRoute,
469
- currentState,
470
- session.extracted || {}
467
+ currentStep,
468
+ session.data || {}
471
469
  );
472
470
 
473
471
  // Check if route is complete
@@ -476,18 +474,18 @@ export class RoutingEngine<TContext = unknown> {
476
474
  logger.debug(
477
475
  `[RoutingEngine] Route ${activeRoute.title} is complete - all data collected`
478
476
  );
479
- // Don't include states in routing if route is complete
480
- activeRouteStates = undefined;
477
+ // Don't include steps in routing if route is complete
478
+ activeRouteSteps = undefined;
481
479
  } else {
482
- activeRouteStates = candidates.map((c) => ({
483
- stateId: c.state.id,
484
- description: c.state.description || "",
480
+ activeRouteSteps = candidates.map((c) => ({
481
+ stepId: c.step.id,
482
+ description: c.step.description || "",
485
483
  condition: c.condition,
486
- requiredData: c.requiredData,
487
- gatherFields: c.gatherFields,
484
+ requires: c.requires,
485
+ collectFields: c.collectFields,
488
486
  }));
489
487
  logger.debug(
490
- `[RoutingEngine] Found ${activeRouteStates.length} candidate states for active route`
488
+ `[RoutingEngine] Found ${activeRouteSteps.length} candidate steps for active route`
491
489
  );
492
490
  }
493
491
  }
@@ -496,7 +494,7 @@ export class RoutingEngine<TContext = unknown> {
496
494
  const routingSchema = this.buildDynamicRoutingSchema(
497
495
  routes,
498
496
  undefined,
499
- activeRouteStates
497
+ activeRouteSteps
500
498
  );
501
499
 
502
500
  const routingPrompt = this.buildRoutingPrompt(
@@ -505,10 +503,10 @@ export class RoutingEngine<TContext = unknown> {
505
503
  lastUserMessage,
506
504
  agentMeta,
507
505
  session,
508
- activeRouteStates
506
+ activeRouteSteps
509
507
  );
510
508
 
511
- const routingResult = await ai.generateMessage<
509
+ const routingResult = await provider.generateMessage<
512
510
  TContext,
513
511
  RoutingDecisionOutput
514
512
  >({
@@ -523,7 +521,7 @@ export class RoutingEngine<TContext = unknown> {
523
521
  });
524
522
 
525
523
  let selectedRoute: Route<TContext> | undefined;
526
- let selectedState: State<TContext> | undefined;
524
+ let selectedStep: Step<TContext> | undefined;
527
525
  let responseDirectives: string[] | undefined;
528
526
  let updatedSession = session;
529
527
 
@@ -538,18 +536,18 @@ export class RoutingEngine<TContext = unknown> {
538
536
 
539
537
  if (
540
538
  selectedRoute === activeRoute &&
541
- routingResult.structured.selectedStateId &&
539
+ routingResult.structured.selectedStepId &&
542
540
  activeRoute
543
541
  ) {
544
- selectedState = activeRoute.getState(
545
- routingResult.structured.selectedStateId
542
+ selectedStep = activeRoute.getStep(
543
+ routingResult.structured.selectedStepId
546
544
  );
547
- if (selectedState) {
545
+ if (selectedStep) {
548
546
  logger.debug(
549
- `[RoutingEngine] AI selected state: ${selectedState.id} in active route`
547
+ `[RoutingEngine] AI selected step: ${selectedStep.id} in active route`
550
548
  );
551
549
  logger.debug(
552
- `[RoutingEngine] State reasoning: ${routingResult.structured.stateReasoning}`
550
+ `[RoutingEngine] Step reasoning: ${routingResult.structured.stepReasoning}`
553
551
  );
554
552
  }
555
553
  }
@@ -566,7 +564,7 @@ export class RoutingEngine<TContext = unknown> {
566
564
  selectedRoute.title
567
565
  );
568
566
  if (selectedRoute.initialData) {
569
- updatedSession = mergeExtracted(
567
+ updatedSession = mergeCollected(
570
568
  updatedSession,
571
569
  selectedRoute.initialData
572
570
  );
@@ -582,7 +580,7 @@ export class RoutingEngine<TContext = unknown> {
582
580
 
583
581
  return {
584
582
  selectedRoute,
585
- selectedState,
583
+ selectedStep,
586
584
  responseDirectives,
587
585
  session: updatedSession,
588
586
  isRouteComplete,
@@ -590,19 +588,19 @@ export class RoutingEngine<TContext = unknown> {
590
588
  }
591
589
 
592
590
  /**
593
- * Build prompt for state selection within a single route
591
+ * Build prompt for step selection within a single route
594
592
  * @private
595
593
  */
596
- private buildStateSelectionPrompt(
594
+ private buildStepSelectionPrompt(
597
595
  route: Route<TContext>,
598
- currentState: State<TContext> | undefined,
596
+ currentStep: Step<TContext> | undefined,
599
597
  candidates: Array<{
600
- state: State<TContext>;
598
+ step: Step<TContext>;
601
599
  condition?: string;
602
- requiredData?: string[];
603
- gatherFields?: string[];
600
+ requires?: string[];
601
+ collectFields?: string[];
604
602
  }>,
605
- extracted: Partial<unknown>,
603
+ data: Partial<unknown>,
606
604
  history: Event[],
607
605
  lastMessage: string,
608
606
  agentMeta?: {
@@ -632,71 +630,71 @@ export class RoutingEngine<TContext = unknown> {
632
630
  `Active Route: ${route.title}\nDescription: ${route.description || "N/A"}`
633
631
  );
634
632
 
635
- // Add current state context
636
- if (currentState) {
633
+ // Add current step context
634
+ if (currentStep) {
637
635
  pc.addInstruction(
638
- `Current State: ${currentState.id}\nDescription: ${
639
- currentState.description || "N/A"
636
+ `Current Step: ${currentStep.id}\nDescription: ${
637
+ currentStep.description || "N/A"
640
638
  }`
641
639
  );
642
640
  } else {
643
- pc.addInstruction("Current State: None (entering route)");
641
+ pc.addInstruction("Current Step: None (entering route)");
644
642
  }
645
643
 
646
- // Add extracted data context
647
- if (Object.keys(extracted).length > 0) {
644
+ // Add collected data context
645
+ if (Object.keys(data).length > 0) {
648
646
  pc.addInstruction(
649
- `Extracted Data So Far:\n${JSON.stringify(extracted, null, 2)}`
647
+ `Collected Data So Far:\n${JSON.stringify(data, null, 2)}`
650
648
  );
651
649
  } else {
652
- pc.addInstruction("Extracted Data: None yet");
650
+ pc.addInstruction("Collected Data: None yet");
653
651
  }
654
652
 
655
653
  // Add conversation history
656
654
  pc.addInteractionHistory(history);
657
655
  pc.addLastMessage(lastMessage);
658
656
 
659
- // Add candidate states
660
- const stateDescriptions = candidates.map((candidate, idx) => {
657
+ // Add candidate steps
658
+ const stepDescriptions = candidates.map((candidate, idx) => {
661
659
  const parts = [
662
- `${idx + 1}. State ID: ${candidate.state.id}`,
663
- ` Description: ${candidate.state.description || "N/A"}`,
660
+ `${idx + 1}. Step ID: ${candidate.step.id}`,
661
+ ` Description: ${candidate.step.description || "N/A"}`,
664
662
  ];
665
663
 
666
664
  if (candidate.condition) {
667
665
  parts.push(` Condition: ${candidate.condition}`);
668
666
  }
669
667
 
670
- if (candidate.requiredData && candidate.requiredData.length > 0) {
671
- parts.push(` Required Data: ${candidate.requiredData.join(", ")}`);
668
+ if (candidate.requires && candidate.requires.length > 0) {
669
+ parts.push(` Required Data: ${candidate.requires.join(", ")}`);
672
670
  }
673
671
 
674
- if (candidate.gatherFields && candidate.gatherFields.length > 0) {
675
- parts.push(` Gathers: ${candidate.gatherFields.join(", ")}`);
672
+ if (candidate.collectFields && candidate.collectFields.length > 0) {
673
+ parts.push(` Collects: ${candidate.collectFields.join(", ")}`);
676
674
  }
677
675
 
678
676
  return parts.join("\n");
679
677
  });
680
678
 
681
679
  pc.addInstruction(
682
- `Available States to Transition To:\n${stateDescriptions.join("\n\n")}`
680
+ `Available Steps to Transition To:\n${stepDescriptions.join("\n\n")}`
683
681
  );
684
682
 
685
683
  // Add decision instructions
686
684
  pc.addInstruction(
687
685
  [
688
- "Task: Decide which state to transition to based on:",
686
+ "Task: Decide which step to transition to based on:",
689
687
  "1. The user's current message and intent",
690
688
  "2. The conversation history and context",
691
- "3. The extracted data we already have",
692
- "4. The conditions and requirements of each state",
689
+ "3. The collected data we already have",
690
+ "4. The conditions and requirements of each step",
693
691
  "5. The logical flow of the conversation",
694
692
  "",
695
693
  "Rules:",
696
- "- If a state has a condition, evaluate whether it's met based on context",
697
- "- If a state requires data we don't have, consider if we should gather it now",
698
- "- Choose the state that makes the most sense for moving the conversation forward",
699
- "- States with skipIf conditions that are met have already been filtered out",
694
+ "- If a step has a condition, evaluate whether it's met based on context",
695
+ "- If a step requires data we don't have, consider if we should collect it now",
696
+ "- Choose the step that makes the most sense for moving the conversation forward",
697
+ "- Steps with skipIf conditions that are met have already been filtered out",
700
698
  "",
701
699
  "Return ONLY JSON matching the provided schema.",
702
700
  ].join("\n")
@@ -706,25 +704,25 @@ export class RoutingEngine<TContext = unknown> {
706
704
  }
707
705
 
708
706
  /**
709
- * Build schema for state selection
707
+ * Build schema for step selection
710
708
  * @private
711
709
  */
712
- private buildStateSelectionSchema(validStateIds: string[]): StructuredSchema {
710
+ private buildStepSelectionSchema(validStepIds: string[]): StructuredSchema {
713
711
  return {
714
712
  description:
715
- "State transition decision based on conversation context and extracted data",
713
+ "Step transition decision based on conversation context and collected data",
716
714
  type: "object",
717
715
  properties: {
718
716
  reasoning: {
719
717
  type: "string",
720
718
  nullable: false,
721
- description: "Brief explanation of why this state was selected",
719
+ description: "Brief explanation of why this step was selected",
722
720
  },
723
- selectedStateId: {
721
+ selectedStepId: {
724
722
  type: "string",
725
723
  nullable: false,
726
- description: "The ID of the selected state to transition to",
727
- enum: validStateIds,
724
+ description: "The ID of the selected step to transition to",
725
+ enum: validStepIds,
728
726
  },
729
727
  responseDirectives: {
730
728
  type: "array",
@@ -733,7 +731,7 @@ export class RoutingEngine<TContext = unknown> {
733
731
  "Optional bullet points the response should address (concise)",
734
732
  },
735
733
  },
736
- required: ["reasoning", "selectedStateId"],
734
+ required: ["reasoning", "selectedStepId"],
737
735
  additionalProperties: false,
738
736
  };
739
737
  }
@@ -741,7 +739,7 @@ export class RoutingEngine<TContext = unknown> {
741
739
  buildDynamicRoutingSchema(
742
740
  routes: Route<TContext>[],
743
741
  extrasSchema?: StructuredSchema,
744
- activeRouteStates?: { stateId: string; description: string }[]
742
+ activeRouteSteps?: { stepId: string; description: string }[]
745
743
  ): StructuredSchema {
746
744
  const routeIds = routes.map((r) => r.id);
747
745
  const routeProperties: Record<string, StructuredSchema> = {};
@@ -783,25 +781,25 @@ export class RoutingEngine<TContext = unknown> {
783
781
  additionalProperties: false,
784
782
  };
785
783
 
786
- // Add state selection fields if there's an active route with states
787
- if (activeRouteStates && activeRouteStates.length > 0) {
784
+ // Add step selection fields if there's an active route with steps
785
+ if (activeRouteSteps && activeRouteSteps.length > 0) {
788
786
  base.properties = base.properties || {};
789
- base.properties.selectedStateId = {
787
+ base.properties.selectedStepId = {
790
788
  type: "string",
791
789
  nullable: false,
792
790
  description:
793
- "The state ID to transition to within the active route (required if continuing in current route)",
794
- enum: activeRouteStates.map((s) => s.stateId),
791
+ "The step ID to transition to within the active route (required if continuing in current route)",
792
+ enum: activeRouteSteps.map((s) => s.stepId),
795
793
  };
796
- base.properties.stateReasoning = {
794
+ base.properties.stepReasoning = {
797
795
  type: "string",
798
796
  nullable: false,
799
- description: "Brief explanation of why this state was selected",
797
+ description: "Brief explanation of why this step was selected",
800
798
  };
801
799
  base.required = [
802
800
  ...(base.required || []),
803
- "selectedStateId",
804
- "stateReasoning",
801
+ "selectedStepId",
802
+ "stepReasoning",
805
803
  ];
806
804
  }
807
805
 
@@ -823,13 +821,13 @@ export class RoutingEngine<TContext = unknown> {
823
821
  description?: string;
824
822
  personality?: string;
825
823
  },
826
- session?: SessionState,
827
- activeRouteStates?: Array<{
828
- stateId: string;
824
+ session?: SessionStep,
825
+ activeRouteSteps?: Array<{
826
+ stepId: string;
829
827
  description: string;
830
828
  condition?: string;
831
- requiredData?: string[];
832
- gatherFields?: string[];
829
+ requires?: string[];
830
+ collectFields?: string[];
833
831
  }>
834
832
  ): string {
835
833
  const pc = new PromptComposer();
@@ -853,54 +851,50 @@ export class RoutingEngine<TContext = unknown> {
853
851
  "Current conversation context:",
854
852
  `- Active route: ${session.currentRoute.title} (${session.currentRoute.id})`,
855
853
  ];
856
- if (session.currentState) {
857
- sessionInfo.push(`- Current state: ${session.currentState.id}`);
858
- if (session.currentState.description) {
859
- sessionInfo.push(` "${session.currentState.description}"`);
854
+ if (session.currentStep) {
855
+ sessionInfo.push(`- Current step: ${session.currentStep.id}`);
856
+ if (session.currentStep.description) {
857
+ sessionInfo.push(` "${session.currentStep.description}"`);
860
858
  }
861
859
  }
862
- if (session.extracted && Object.keys(session.extracted).length > 0) {
863
- sessionInfo.push(
864
- `- Extracted data: ${JSON.stringify(session.extracted)}`
865
- );
860
+ if (session.data && Object.keys(session.data).length > 0) {
861
+ sessionInfo.push(`- Collected data: ${JSON.stringify(session.data)}`);
866
862
  }
867
863
  sessionInfo.push(
868
864
  "Note: User is mid-conversation. They may want to continue current route or switch to a new one based on their intent."
869
865
  );
870
866
  pc.addInstruction(sessionInfo.join("\n"));
871
867
 
872
- // Add available states for the active route
873
- if (activeRouteStates && activeRouteStates.length > 0) {
874
- const stateInfo = [
868
+ // Add available steps for the active route
869
+ if (activeRouteSteps && activeRouteSteps.length > 0) {
870
+ const stepInfo = [
875
871
  "",
876
- "Available states in active route (choose one to transition to):",
872
+ "Available steps in active route (choose one to transition to):",
877
873
  ];
878
- activeRouteStates.forEach((state, idx) => {
879
- stateInfo.push(`${idx + 1}. State: ${state.stateId}`);
880
- if (state.description) {
881
- stateInfo.push(` Description: ${state.description}`);
874
+ activeRouteSteps.forEach((step, idx) => {
875
+ stepInfo.push(`${idx + 1}. Step: ${step.stepId}`);
876
+ if (step.description) {
877
+ stepInfo.push(` Description: ${step.description}`);
882
878
  }
883
- if (state.condition) {
884
- stateInfo.push(` Condition: ${state.condition}`);
879
+ if (step.condition) {
880
+ stepInfo.push(` Condition: ${step.condition}`);
885
881
  }
886
- if (state.requiredData && state.requiredData.length > 0) {
887
- stateInfo.push(
888
- ` Required data: ${state.requiredData.join(", ")}`
889
- );
882
+ if (step.requires && step.requires.length > 0) {
883
+ stepInfo.push(` Required data: ${step.requires.join(", ")}`);
890
884
  }
891
- if (state.gatherFields && state.gatherFields.length > 0) {
892
- stateInfo.push(` Will gather: ${state.gatherFields.join(", ")}`);
885
+ if (step.collectFields && step.collectFields.length > 0) {
886
+ stepInfo.push(` Will collect: ${step.collectFields.join(", ")}`);
893
887
  }
894
888
  });
895
- stateInfo.push("");
896
- stateInfo.push(
897
- "IMPORTANT: You MUST select a state to transition to. Evaluate which state makes the most sense based on:"
889
+ stepInfo.push("");
890
+ stepInfo.push(
891
+ "IMPORTANT: You MUST select a step to transition to. Evaluate which step makes the most sense based on:"
898
892
  );
899
- stateInfo.push("- The conversation flow and what's been collected");
900
- stateInfo.push("- What data is still needed vs already present");
901
- stateInfo.push("- The logical next step in the conversation");
902
- stateInfo.push("- Whether conditions for states are met");
903
- pc.addInstruction(stateInfo.join("\n"));
893
+ stepInfo.push("- The conversation flow and what's been collected");
894
+ stepInfo.push("- What data is still needed vs already present");
895
+ stepInfo.push("- The logical next step in the conversation");
896
+ stepInfo.push("- Whether conditions for steps are met");
897
+ pc.addInstruction(stepInfo.join("\n"));
904
898
  }
905
899
  }
906
900