@falai/agent 0.9.0-alpha-1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/README.md +34 -22
  2. package/dist/cjs/src/core/Agent.d.ts +77 -59
  3. package/dist/cjs/src/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/src/core/Agent.js +284 -1060
  5. package/dist/cjs/src/core/Agent.js.map +1 -1
  6. package/dist/cjs/src/core/PersistenceManager.d.ts.map +1 -1
  7. package/dist/cjs/src/core/PersistenceManager.js +48 -25
  8. package/dist/cjs/src/core/PersistenceManager.js.map +1 -1
  9. package/dist/cjs/src/core/PromptComposer.d.ts +1 -1
  10. package/dist/cjs/src/core/PromptComposer.d.ts.map +1 -1
  11. package/dist/cjs/src/core/PromptComposer.js.map +1 -1
  12. package/dist/cjs/src/core/ResponseEngine.d.ts +13 -12
  13. package/dist/cjs/src/core/ResponseEngine.d.ts.map +1 -1
  14. package/dist/cjs/src/core/ResponseEngine.js +4 -4
  15. package/dist/cjs/src/core/ResponseEngine.js.map +1 -1
  16. package/dist/cjs/src/core/ResponseModal.d.ts +205 -0
  17. package/dist/cjs/src/core/ResponseModal.d.ts.map +1 -0
  18. package/dist/cjs/src/core/ResponseModal.js +1328 -0
  19. package/dist/cjs/src/core/ResponseModal.js.map +1 -0
  20. package/dist/cjs/src/core/ResponsePipeline.d.ts +66 -38
  21. package/dist/cjs/src/core/ResponsePipeline.d.ts.map +1 -1
  22. package/dist/cjs/src/core/ResponsePipeline.js +72 -4
  23. package/dist/cjs/src/core/ResponsePipeline.js.map +1 -1
  24. package/dist/cjs/src/core/Route.d.ts +24 -5
  25. package/dist/cjs/src/core/Route.d.ts.map +1 -1
  26. package/dist/cjs/src/core/Route.js +45 -1
  27. package/dist/cjs/src/core/Route.js.map +1 -1
  28. package/dist/cjs/src/core/RoutingEngine.d.ts +31 -6
  29. package/dist/cjs/src/core/RoutingEngine.d.ts.map +1 -1
  30. package/dist/cjs/src/core/RoutingEngine.js +113 -9
  31. package/dist/cjs/src/core/RoutingEngine.js.map +1 -1
  32. package/dist/cjs/src/core/SessionManager.d.ts +14 -4
  33. package/dist/cjs/src/core/SessionManager.d.ts.map +1 -1
  34. package/dist/cjs/src/core/SessionManager.js +25 -5
  35. package/dist/cjs/src/core/SessionManager.js.map +1 -1
  36. package/dist/cjs/src/core/Step.d.ts +10 -10
  37. package/dist/cjs/src/core/Step.d.ts.map +1 -1
  38. package/dist/cjs/src/core/Step.js.map +1 -1
  39. package/dist/cjs/src/core/ToolExecutor.d.ts +4 -2
  40. package/dist/cjs/src/core/ToolExecutor.d.ts.map +1 -1
  41. package/dist/cjs/src/core/ToolExecutor.js +13 -3
  42. package/dist/cjs/src/core/ToolExecutor.js.map +1 -1
  43. package/dist/cjs/src/index.d.ts +3 -1
  44. package/dist/cjs/src/index.d.ts.map +1 -1
  45. package/dist/cjs/src/index.js +7 -1
  46. package/dist/cjs/src/index.js.map +1 -1
  47. package/dist/cjs/src/types/agent.d.ts +42 -21
  48. package/dist/cjs/src/types/agent.d.ts.map +1 -1
  49. package/dist/cjs/src/types/agent.js.map +1 -1
  50. package/dist/cjs/src/types/ai.d.ts +1 -1
  51. package/dist/cjs/src/types/ai.d.ts.map +1 -1
  52. package/dist/cjs/src/types/index.d.ts +1 -1
  53. package/dist/cjs/src/types/index.d.ts.map +1 -1
  54. package/dist/cjs/src/types/index.js.map +1 -1
  55. package/dist/cjs/src/types/persistence.d.ts +0 -1
  56. package/dist/cjs/src/types/persistence.d.ts.map +1 -1
  57. package/dist/cjs/src/types/route.d.ts +22 -16
  58. package/dist/cjs/src/types/route.d.ts.map +1 -1
  59. package/dist/cjs/src/types/session.d.ts +6 -11
  60. package/dist/cjs/src/types/session.d.ts.map +1 -1
  61. package/dist/cjs/src/types/tool.d.ts +12 -6
  62. package/dist/cjs/src/types/tool.d.ts.map +1 -1
  63. package/dist/cjs/src/utils/clone.d.ts.map +1 -1
  64. package/dist/cjs/src/utils/clone.js +0 -4
  65. package/dist/cjs/src/utils/clone.js.map +1 -1
  66. package/dist/cjs/src/utils/history.d.ts +30 -1
  67. package/dist/cjs/src/utils/history.d.ts.map +1 -1
  68. package/dist/cjs/src/utils/history.js +169 -23
  69. package/dist/cjs/src/utils/history.js.map +1 -1
  70. package/dist/cjs/src/utils/index.d.ts +1 -1
  71. package/dist/cjs/src/utils/index.d.ts.map +1 -1
  72. package/dist/cjs/src/utils/index.js +5 -1
  73. package/dist/cjs/src/utils/index.js.map +1 -1
  74. package/dist/cjs/src/utils/session.d.ts +2 -2
  75. package/dist/cjs/src/utils/session.d.ts.map +1 -1
  76. package/dist/cjs/src/utils/session.js +6 -26
  77. package/dist/cjs/src/utils/session.js.map +1 -1
  78. package/dist/src/core/Agent.d.ts +77 -59
  79. package/dist/src/core/Agent.d.ts.map +1 -1
  80. package/dist/src/core/Agent.js +285 -1061
  81. package/dist/src/core/Agent.js.map +1 -1
  82. package/dist/src/core/PersistenceManager.d.ts.map +1 -1
  83. package/dist/src/core/PersistenceManager.js +48 -25
  84. package/dist/src/core/PersistenceManager.js.map +1 -1
  85. package/dist/src/core/PromptComposer.d.ts +1 -1
  86. package/dist/src/core/PromptComposer.d.ts.map +1 -1
  87. package/dist/src/core/PromptComposer.js.map +1 -1
  88. package/dist/src/core/ResponseEngine.d.ts +13 -12
  89. package/dist/src/core/ResponseEngine.d.ts.map +1 -1
  90. package/dist/src/core/ResponseEngine.js +4 -4
  91. package/dist/src/core/ResponseEngine.js.map +1 -1
  92. package/dist/src/core/ResponseModal.d.ts +205 -0
  93. package/dist/src/core/ResponseModal.d.ts.map +1 -0
  94. package/dist/src/core/ResponseModal.js +1323 -0
  95. package/dist/src/core/ResponseModal.js.map +1 -0
  96. package/dist/src/core/ResponsePipeline.d.ts +66 -38
  97. package/dist/src/core/ResponsePipeline.d.ts.map +1 -1
  98. package/dist/src/core/ResponsePipeline.js +72 -4
  99. package/dist/src/core/ResponsePipeline.js.map +1 -1
  100. package/dist/src/core/Route.d.ts +24 -5
  101. package/dist/src/core/Route.d.ts.map +1 -1
  102. package/dist/src/core/Route.js +45 -1
  103. package/dist/src/core/Route.js.map +1 -1
  104. package/dist/src/core/RoutingEngine.d.ts +31 -6
  105. package/dist/src/core/RoutingEngine.d.ts.map +1 -1
  106. package/dist/src/core/RoutingEngine.js +113 -9
  107. package/dist/src/core/RoutingEngine.js.map +1 -1
  108. package/dist/src/core/SessionManager.d.ts +14 -4
  109. package/dist/src/core/SessionManager.d.ts.map +1 -1
  110. package/dist/src/core/SessionManager.js +25 -5
  111. package/dist/src/core/SessionManager.js.map +1 -1
  112. package/dist/src/core/Step.d.ts +10 -10
  113. package/dist/src/core/Step.d.ts.map +1 -1
  114. package/dist/src/core/Step.js.map +1 -1
  115. package/dist/src/core/ToolExecutor.d.ts +4 -2
  116. package/dist/src/core/ToolExecutor.d.ts.map +1 -1
  117. package/dist/src/core/ToolExecutor.js +13 -3
  118. package/dist/src/core/ToolExecutor.js.map +1 -1
  119. package/dist/src/index.d.ts +3 -1
  120. package/dist/src/index.d.ts.map +1 -1
  121. package/dist/src/index.js +2 -1
  122. package/dist/src/index.js.map +1 -1
  123. package/dist/src/types/agent.d.ts +42 -21
  124. package/dist/src/types/agent.d.ts.map +1 -1
  125. package/dist/src/types/agent.js.map +1 -1
  126. package/dist/src/types/ai.d.ts +1 -1
  127. package/dist/src/types/ai.d.ts.map +1 -1
  128. package/dist/src/types/index.d.ts +1 -1
  129. package/dist/src/types/index.d.ts.map +1 -1
  130. package/dist/src/types/index.js.map +1 -1
  131. package/dist/src/types/persistence.d.ts +0 -1
  132. package/dist/src/types/persistence.d.ts.map +1 -1
  133. package/dist/src/types/route.d.ts +22 -16
  134. package/dist/src/types/route.d.ts.map +1 -1
  135. package/dist/src/types/session.d.ts +6 -11
  136. package/dist/src/types/session.d.ts.map +1 -1
  137. package/dist/src/types/tool.d.ts +12 -6
  138. package/dist/src/types/tool.d.ts.map +1 -1
  139. package/dist/src/utils/clone.d.ts.map +1 -1
  140. package/dist/src/utils/clone.js +0 -4
  141. package/dist/src/utils/clone.js.map +1 -1
  142. package/dist/src/utils/history.d.ts +30 -1
  143. package/dist/src/utils/history.d.ts.map +1 -1
  144. package/dist/src/utils/history.js +165 -23
  145. package/dist/src/utils/history.js.map +1 -1
  146. package/dist/src/utils/index.d.ts +1 -1
  147. package/dist/src/utils/index.d.ts.map +1 -1
  148. package/dist/src/utils/index.js +1 -1
  149. package/dist/src/utils/index.js.map +1 -1
  150. package/dist/src/utils/session.d.ts +2 -2
  151. package/dist/src/utils/session.d.ts.map +1 -1
  152. package/dist/src/utils/session.js +6 -26
  153. package/dist/src/utils/session.js.map +1 -1
  154. package/docs/README.md +5 -4
  155. package/docs/api/README.md +195 -4
  156. package/docs/api/overview.md +232 -13
  157. package/docs/core/agent/README.md +162 -17
  158. package/docs/core/agent/context-management.md +39 -15
  159. package/docs/core/agent/session-management.md +49 -16
  160. package/docs/core/ai-integration/prompt-composition.md +38 -14
  161. package/docs/core/ai-integration/response-processing.md +28 -17
  162. package/docs/core/conversation-flows/data-collection.md +103 -25
  163. package/docs/core/conversation-flows/route-dsl.md +45 -22
  164. package/docs/core/conversation-flows/routes.md +74 -18
  165. package/docs/core/conversation-flows/step-transitions.md +3 -3
  166. package/docs/core/conversation-flows/steps.md +39 -15
  167. package/docs/core/routing/intelligent-routing.md +18 -9
  168. package/docs/core/tools/tool-definition.md +8 -8
  169. package/docs/core/tools/tool-execution.md +26 -26
  170. package/docs/core/tools/tool-scoping.md +5 -5
  171. package/docs/guides/getting-started/README.md +54 -32
  172. package/docs/guides/migration/README.md +72 -0
  173. package/docs/guides/migration/response-modal-refactor.md +518 -0
  174. package/examples/advanced-patterns/knowledge-based-agent.ts +37 -28
  175. package/examples/advanced-patterns/persistent-onboarding.ts +70 -41
  176. package/examples/advanced-patterns/route-lifecycle-hooks.ts +28 -2
  177. package/examples/advanced-patterns/streaming-responses.ts +197 -119
  178. package/examples/ai-providers/anthropic-integration.ts +40 -33
  179. package/examples/ai-providers/openai-integration.ts +25 -25
  180. package/examples/conversation-flows/completion-transitions.ts +36 -32
  181. package/examples/core-concepts/basic-agent.ts +76 -78
  182. package/examples/core-concepts/modern-streaming-api.ts +309 -0
  183. package/examples/core-concepts/schema-driven-extraction.ts +20 -16
  184. package/examples/core-concepts/session-management.ts +65 -53
  185. package/examples/integrations/database-integration.ts +49 -34
  186. package/examples/integrations/healthcare-integration.ts +96 -91
  187. package/examples/integrations/search-integration.ts +79 -82
  188. package/examples/integrations/server-session-management.ts +25 -17
  189. package/examples/persistence/database-persistence.ts +61 -45
  190. package/examples/persistence/memory-sessions.ts +52 -63
  191. package/examples/persistence/redis-persistence.ts +81 -95
  192. package/examples/tools/basic-tools.ts +73 -62
  193. package/examples/tools/data-enrichment-tools.ts +52 -44
  194. package/package.json +1 -1
  195. package/src/core/Agent.ts +396 -1499
  196. package/src/core/PersistenceManager.ts +51 -27
  197. package/src/core/PromptComposer.ts +1 -1
  198. package/src/core/ResponseEngine.ts +21 -19
  199. package/src/core/ResponseModal.ts +1722 -0
  200. package/src/core/ResponsePipeline.ts +175 -60
  201. package/src/core/Route.ts +58 -6
  202. package/src/core/RoutingEngine.ts +174 -27
  203. package/src/core/SessionManager.ts +32 -8
  204. package/src/core/Step.ts +20 -12
  205. package/src/core/ToolExecutor.ts +19 -5
  206. package/src/index.ts +11 -0
  207. package/src/types/agent.ts +47 -23
  208. package/src/types/ai.ts +1 -1
  209. package/src/types/index.ts +2 -0
  210. package/src/types/persistence.ts +0 -1
  211. package/src/types/route.ts +22 -16
  212. package/src/types/session.ts +6 -12
  213. package/src/types/tool.ts +15 -9
  214. package/src/utils/clone.ts +6 -8
  215. package/src/utils/history.ts +190 -27
  216. package/src/utils/index.ts +4 -0
  217. package/src/utils/session.ts +6 -31
@@ -3,33 +3,53 @@
3
3
  * Convert simplified history format to internal Event format
4
4
  */
5
5
 
6
- import type { Event, MessageEventData } from "../types";
6
+ import type { Event, MessageEventData, ToolEventData, StatusEventData } from "../types";
7
7
  import { EventKind, MessageRole } from "../types";
8
- import type { History, HistoryItem } from "../types/history";
8
+ import type { History, HistoryItem, UserHistoryItem, AssistantHistoryItem, ToolHistoryItem } from "../types/history";
9
9
 
10
10
  /**
11
11
  * Convert a simplified history item to an internal Event
12
+ * @param item - The HistoryItem to convert
13
+ * @returns Event with proper type-safe structure
14
+ * @throws Error if the history item is malformed or has invalid data
12
15
  */
13
- function convertHistoryItemToEvent(item: HistoryItem): Event {
16
+ export function historyItemToEvent(item: HistoryItem): Event<MessageEventData | ToolEventData | StatusEventData> {
17
+ if (!item || typeof item !== 'object') {
18
+ throw new Error('Invalid history item: must be a non-null object');
19
+ }
20
+
21
+ if (!item.role || typeof item.role !== 'string') {
22
+ throw new Error('Invalid history item: role is required and must be a string');
23
+ }
24
+
14
25
  const timestamp = new Date().toISOString();
15
26
 
16
27
  switch (item.role) {
17
28
  case "user": {
29
+ const userItem = item;
30
+ if (typeof userItem.content !== 'string') {
31
+ throw new Error('Invalid user history item: content must be a string');
32
+ }
33
+
18
34
  return {
19
35
  kind: EventKind.MESSAGE,
20
36
  source: MessageRole.USER,
21
37
  timestamp,
22
38
  data: {
23
39
  participant: {
24
- display_name: item.name || "User",
40
+ display_name: userItem.name || "User",
25
41
  },
26
- message: item.content,
42
+ message: userItem.content,
27
43
  },
28
44
  };
29
45
  }
30
46
  case "assistant": {
31
- // Handle assistant message with optional tool calls
32
- const event: Event = {
47
+ const assistantItem = item;
48
+ if (assistantItem.content !== null && typeof assistantItem.content !== 'string') {
49
+ throw new Error('Invalid assistant history item: content must be a string or null');
50
+ }
51
+
52
+ const event: Event<MessageEventData> = {
33
53
  kind: EventKind.MESSAGE,
34
54
  source: MessageRole.ASSISTANT,
35
55
  timestamp,
@@ -37,19 +57,36 @@ function convertHistoryItemToEvent(item: HistoryItem): Event {
37
57
  participant: {
38
58
  display_name: "Assistant",
39
59
  },
40
- message: item.content || "",
60
+ message: assistantItem.content || "",
41
61
  },
42
62
  };
43
63
 
44
- // If there are tool calls, we need to create a separate tool event
45
- // But for now, we'll just store the tool calls in the message data
46
- if (item.tool_calls && item.tool_calls.length > 0) {
47
- (event.data as MessageEventData).toolCalls = item.tool_calls;
64
+ // If there are tool calls, validate and add them
65
+ if (assistantItem.tool_calls && assistantItem.tool_calls.length > 0) {
66
+ if (!Array.isArray(assistantItem.tool_calls)) {
67
+ throw new Error('Invalid assistant history item: tool_calls must be an array');
68
+ }
69
+
70
+ for (const toolCall of assistantItem.tool_calls) {
71
+ if (!toolCall.id || !toolCall.name || typeof toolCall.arguments !== 'object') {
72
+ throw new Error('Invalid tool call: id, name, and arguments are required');
73
+ }
74
+ }
75
+
76
+ event.data.toolCalls = assistantItem.tool_calls;
48
77
  }
49
78
 
50
79
  return event;
51
80
  }
52
81
  case "tool": {
82
+ const toolItem = item;
83
+ if (!toolItem.tool_call_id || typeof toolItem.tool_call_id !== 'string') {
84
+ throw new Error('Invalid tool history item: tool_call_id is required and must be a string');
85
+ }
86
+ if (!toolItem.name || typeof toolItem.name !== 'string') {
87
+ throw new Error('Invalid tool history item: name is required and must be a string');
88
+ }
89
+
53
90
  return {
54
91
  kind: EventKind.TOOL,
55
92
  source: MessageRole.AGENT,
@@ -57,10 +94,10 @@ function convertHistoryItemToEvent(item: HistoryItem): Event {
57
94
  data: {
58
95
  tool_calls: [
59
96
  {
60
- tool_id: item.tool_call_id,
97
+ tool_id: toolItem.tool_call_id,
61
98
  arguments: {}, // Tool results don't have arguments
62
99
  result: {
63
- data: item.content,
100
+ data: toolItem.content,
64
101
  },
65
102
  },
66
103
  ],
@@ -68,6 +105,11 @@ function convertHistoryItemToEvent(item: HistoryItem): Event {
68
105
  };
69
106
  }
70
107
  case "system": {
108
+ const systemItem = item;
109
+ if (typeof systemItem.content !== 'string') {
110
+ throw new Error('Invalid system history item: content must be a string');
111
+ }
112
+
71
113
  return {
72
114
  kind: EventKind.MESSAGE,
73
115
  source: MessageRole.SYSTEM,
@@ -76,31 +118,152 @@ function convertHistoryItemToEvent(item: HistoryItem): Event {
76
118
  participant: {
77
119
  display_name: "System",
78
120
  },
79
- message: item.content,
121
+ message: systemItem.content,
80
122
  },
81
123
  };
82
124
  }
83
125
  default:
84
- // This should never happen due to TypeScript, but fallback just in case
126
+ throw new Error(`Invalid history item role: ${String((item as { role?: unknown }).role)}`);
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Convert an array of HistoryItems to Events
132
+ * @param history - Array of HistoryItems to convert
133
+ * @returns Array of Events with proper type-safe structure
134
+ * @throws Error if any history item is malformed
135
+ */
136
+ export function historyToEvents(history: History): Event<MessageEventData | ToolEventData | StatusEventData>[] {
137
+ if (!Array.isArray(history)) {
138
+ throw new Error('Invalid history: must be an array');
139
+ }
140
+
141
+ return history.map((item, index) => {
142
+ try {
143
+ return historyItemToEvent(item);
144
+ } catch (error) {
145
+ throw new Error(`Error converting history item at index ${index}: ${error instanceof Error ? error.message : 'Unknown error'}`);
146
+ }
147
+ });
148
+ }
149
+
150
+ /**
151
+ * Convert an Event back to a HistoryItem
152
+ * @param event - The Event to convert
153
+ * @returns HistoryItem with simplified structure
154
+ * @throws Error if the event is malformed or has invalid data
155
+ */
156
+ export function eventToHistoryItem(event: Event): HistoryItem {
157
+ if (!event || typeof event !== 'object') {
158
+ throw new Error('Invalid event: must be a non-null object');
159
+ }
160
+
161
+ if (!event.kind || !event.source || !event.data) {
162
+ throw new Error('Invalid event: kind, source, and data are required');
163
+ }
164
+
165
+ switch (event.kind) {
166
+ case EventKind.MESSAGE: {
167
+ const messageData = event.data as MessageEventData;
168
+ if (!messageData.message && messageData.message !== '') {
169
+ throw new Error('Invalid message event: message is required');
170
+ }
171
+
172
+ switch (event.source) {
173
+ case MessageRole.USER: {
174
+ const userItem: UserHistoryItem = {
175
+ role: "user",
176
+ content: messageData.message,
177
+ };
178
+
179
+ if (messageData.participant?.display_name && messageData.participant.display_name !== "User") {
180
+ userItem.name = messageData.participant.display_name;
181
+ }
182
+
183
+ return userItem;
184
+ }
185
+ case MessageRole.ASSISTANT: {
186
+ const assistantItem: AssistantHistoryItem = {
187
+ role: "assistant",
188
+ content: messageData.message || null,
189
+ };
190
+
191
+ if (messageData.toolCalls && messageData.toolCalls.length > 0) {
192
+ assistantItem.tool_calls = messageData.toolCalls;
193
+ }
194
+
195
+ return assistantItem;
196
+ }
197
+ case MessageRole.SYSTEM: {
198
+ return {
199
+ role: "system",
200
+ content: messageData.message,
201
+ };
202
+ }
203
+ default:
204
+ throw new Error(`Unsupported message source for conversion: ${event.source}`);
205
+ }
206
+ }
207
+ case EventKind.TOOL: {
208
+ const toolData = event.data as ToolEventData;
209
+ if (!toolData.tool_calls || !Array.isArray(toolData.tool_calls) || toolData.tool_calls.length === 0) {
210
+ throw new Error('Invalid tool event: tool_calls array is required and must not be empty');
211
+ }
212
+
213
+ const firstToolCall = toolData.tool_calls[0];
214
+ if (!firstToolCall.tool_id) {
215
+ throw new Error('Invalid tool call: tool_id is required');
216
+ }
217
+
218
+ const toolItem: ToolHistoryItem = {
219
+ role: "tool",
220
+ tool_call_id: firstToolCall.tool_id,
221
+ name: firstToolCall.tool_id, // Use tool_id as name for simplicity
222
+ content: firstToolCall.result?.data,
223
+ };
224
+
225
+ return toolItem;
226
+ }
227
+ case EventKind.STATUS: {
228
+ // Status events don't have a direct HistoryItem equivalent
229
+ // Convert to system message for compatibility
230
+ const statusData = event.data as StatusEventData;
85
231
  return {
86
- kind: EventKind.MESSAGE,
87
- source: MessageRole.SYSTEM,
88
- timestamp,
89
- data: {
90
- participant: {
91
- display_name: "Unknown",
92
- },
93
- message: "Unknown message type",
94
- },
232
+ role: "system",
233
+ content: statusData.status || "Status update",
95
234
  };
235
+ }
236
+ default:
237
+ throw new Error(`Unsupported event kind for conversion: ${String(event.kind)}`);
96
238
  }
97
239
  }
98
240
 
241
+ /**
242
+ * Convert an array of Events back to HistoryItems
243
+ * @param events - Array of Events to convert
244
+ * @returns Array of HistoryItems with simplified structure
245
+ * @throws Error if any event is malformed
246
+ */
247
+ export function eventsToHistory(events: Event[]): History {
248
+ if (!Array.isArray(events)) {
249
+ throw new Error('Invalid events: must be an array');
250
+ }
251
+
252
+ return events.map((event, index) => {
253
+ try {
254
+ return eventToHistoryItem(event);
255
+ } catch (error) {
256
+ throw new Error(`Error converting event at index ${index}: ${error instanceof Error ? error.message : 'Unknown error'}`);
257
+ }
258
+ });
259
+ }
260
+
99
261
  /**
100
262
  * Normalize a simplified history array to internal Event array
263
+ * @deprecated Use historyToEvents instead
101
264
  */
102
265
  export function normalizeHistory(history: History): Event[] {
103
- return history.map(convertHistoryItemToEvent);
266
+ return historyToEvents(history);
104
267
  }
105
268
 
106
269
  /**
@@ -140,4 +303,4 @@ export function toolMessage(
140
303
  */
141
304
  export function systemMessage(content: string): HistoryItem {
142
305
  return { role: "system", content };
143
- }
306
+ }
@@ -39,6 +39,10 @@ export { getLastMessageFromHistory } from "./event";
39
39
  // History utilities
40
40
  export {
41
41
  normalizeHistory,
42
+ historyItemToEvent,
43
+ historyToEvents,
44
+ eventToHistoryItem,
45
+ eventsToHistory,
42
46
  userMessage,
43
47
  assistantMessage,
44
48
  toolMessage,
@@ -16,8 +16,7 @@ export function createSession<TData = Record<string, unknown>>(
16
16
 
17
17
  return {
18
18
  id,
19
- data: {} as Partial<TData>,
20
- dataByRoute: {},
19
+ data: {} as Partial<TData>, // Agent-level data structure
21
20
  routeHistory: [],
22
21
  metadata: {
23
22
  ...metadata,
@@ -44,23 +43,13 @@ export function cloneSession<TData>(
44
43
 
45
44
  /**
46
45
  * Helper to update session with new route
47
- * Preserves collected data per route in dataByRoute map
46
+ * With agent-level data, routes share the same data structure
48
47
  */
49
48
  export function enterRoute<TData = Record<string, unknown>>(
50
49
  session: SessionState<TData>,
51
50
  routeId: string,
52
51
  routeTitle: string
53
52
  ): SessionState<TData> {
54
- // Save current route's collected data before switching (if any)
55
- const dataByRoute = { ...session.dataByRoute };
56
- if (
57
- session.currentRoute &&
58
- session.data &&
59
- Object.keys(session.data).length > 0
60
- ) {
61
- dataByRoute[session.currentRoute.id] = session.data;
62
- }
63
-
64
53
  // Exit current route if exists
65
54
  const routeHistory = [...(session.routeHistory || [])];
66
55
  if (session.currentRoute) {
@@ -72,10 +61,7 @@ export function enterRoute<TData = Record<string, unknown>>(
72
61
  }
73
62
  }
74
63
 
75
- // Load collected data for new route (if resuming) or start fresh
76
- const newCollected = dataByRoute[routeId] || {};
77
-
78
- // Enter new route
64
+ // Enter new route - data persists across routes at agent level
79
65
  const now = new Date();
80
66
  return {
81
67
  ...session,
@@ -85,8 +71,7 @@ export function enterRoute<TData = Record<string, unknown>>(
85
71
  enteredAt: now,
86
72
  },
87
73
  currentStep: undefined,
88
- data: newCollected, // Load route's data or start fresh
89
- dataByRoute,
74
+ // data remains the same - shared across all routes
90
75
  routeHistory: [
91
76
  ...routeHistory,
92
77
  {
@@ -126,7 +111,7 @@ export function enterStep<TData = Record<string, unknown>>(
126
111
 
127
112
  /**
128
113
  * Helper to merge collected data into session
129
- * Updates both data and dataByRoute for current route
114
+ * Updates agent-level data structure
130
115
  */
131
116
  export function mergeCollected<TData = Record<string, unknown>>(
132
117
  session: SessionState<TData>,
@@ -137,16 +122,9 @@ export function mergeCollected<TData = Record<string, unknown>>(
137
122
  ...data,
138
123
  } as Partial<TData>;
139
124
 
140
- // Also update the dataByRoute map for the current route
141
- const dataByRoute = { ...session.dataByRoute };
142
- if (session.currentRoute) {
143
- dataByRoute[session.currentRoute.id] = newCollected;
144
- }
145
-
146
125
  return {
147
126
  ...session,
148
- data: newCollected,
149
- dataByRoute,
127
+ data: newCollected, // Agent-level data update
150
128
  metadata: {
151
129
  ...session.metadata,
152
130
  lastUpdatedAt: new Date(),
@@ -170,7 +148,6 @@ export function sessionStepToData<TData = Record<string, unknown>>(
170
148
  currentStep: session.currentStep?.id,
171
149
  collectedData: {
172
150
  data: session.data || {},
173
- dataByRoute: session.dataByRoute || {}, // Include per-route data
174
151
  routeHistory: session.routeHistory,
175
152
  history: session.history, // Include conversation history
176
153
  currentRouteTitle: session.currentRoute?.title,
@@ -196,7 +173,6 @@ export function sessionDataToStep<TData = Record<string, unknown>>(
196
173
  ): SessionState<TData> {
197
174
  const collectedData: CollectedStateData<TData> = data.collectedData || {
198
175
  data: {},
199
- dataByRoute: {},
200
176
  routeHistory: [],
201
177
  history: [],
202
178
  metadata: {},
@@ -221,7 +197,6 @@ export function sessionDataToStep<TData = Record<string, unknown>>(
221
197
  }
222
198
  : undefined,
223
199
  data: collectedData.data || {},
224
- dataByRoute: collectedData.dataByRoute || {},
225
200
  routeHistory: collectedData.routeHistory || [],
226
201
  history: collectedData.history || [],
227
202
  metadata: collectedData.metadata || {},