@flink-app/flink 0.14.3 → 2.0.0-alpha.100

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 (280) hide show
  1. package/CHANGELOG.md +1051 -0
  2. package/SCHEMA_EXTRACTION_ANALYSIS.md +494 -0
  3. package/SIMPLE_AST_FEASIBILITY.md +570 -0
  4. package/bin/flink.ts +13 -2
  5. package/cli/build.ts +24 -44
  6. package/cli/clean.ts +13 -25
  7. package/cli/cli-utils.ts +190 -17
  8. package/cli/dev.ts +252 -0
  9. package/cli/loadEnvFiles.ts +116 -0
  10. package/cli/run.ts +45 -62
  11. package/dist/bin/flink.js +61 -2
  12. package/dist/cli/build.js +20 -25
  13. package/dist/cli/clean.js +12 -10
  14. package/dist/cli/cli-utils.d.ts +34 -3
  15. package/dist/cli/cli-utils.js +193 -12
  16. package/dist/cli/dev.d.ts +2 -0
  17. package/dist/cli/dev.js +279 -0
  18. package/dist/cli/loadEnvFiles.d.ts +30 -0
  19. package/dist/cli/loadEnvFiles.js +113 -0
  20. package/dist/cli/run.js +47 -46
  21. package/dist/src/DependencyTracker.d.ts +44 -0
  22. package/dist/src/DependencyTracker.js +239 -0
  23. package/dist/src/FlinkApp.d.ts +163 -10
  24. package/dist/src/FlinkApp.js +847 -184
  25. package/dist/src/FlinkContext.d.ts +41 -0
  26. package/dist/src/FlinkErrors.d.ts +19 -6
  27. package/dist/src/FlinkErrors.js +36 -42
  28. package/dist/src/FlinkHttpHandler.d.ts +219 -26
  29. package/dist/src/FlinkHttpHandler.js +37 -1
  30. package/dist/src/FlinkJob.d.ts +10 -0
  31. package/dist/src/FlinkLog.d.ts +82 -18
  32. package/dist/src/FlinkLog.js +165 -13
  33. package/dist/src/FlinkLogFactory.d.ts +288 -0
  34. package/dist/src/FlinkLogFactory.js +619 -0
  35. package/dist/src/FlinkRepo.d.ts +10 -2
  36. package/dist/src/FlinkRepo.js +11 -1
  37. package/dist/src/FlinkRequestContext.d.ts +63 -0
  38. package/dist/src/FlinkRequestContext.js +74 -0
  39. package/dist/src/FlinkResponse.d.ts +6 -0
  40. package/dist/src/FlinkService.d.ts +38 -0
  41. package/dist/src/FlinkService.js +46 -0
  42. package/dist/src/LeaderElection.d.ts +45 -0
  43. package/dist/src/LeaderElection.js +269 -0
  44. package/dist/src/SchemaCache.d.ts +84 -0
  45. package/dist/src/SchemaCache.js +289 -0
  46. package/dist/src/TypeScriptCompiler.d.ts +161 -51
  47. package/dist/src/TypeScriptCompiler.js +1253 -617
  48. package/dist/src/TypeScriptUtils.js +4 -0
  49. package/dist/src/ai/AgentRunner.d.ts +39 -0
  50. package/dist/src/ai/AgentRunner.js +760 -0
  51. package/dist/src/ai/ConversationAgent.d.ts +279 -0
  52. package/dist/src/ai/ConversationAgent.js +404 -0
  53. package/dist/src/ai/ConversationFlinkAgent.d.ts +278 -0
  54. package/dist/src/ai/ConversationFlinkAgent.js +404 -0
  55. package/dist/src/ai/FlinkAgent.d.ts +690 -0
  56. package/dist/src/ai/FlinkAgent.js +729 -0
  57. package/dist/src/ai/FlinkTool.d.ts +135 -0
  58. package/dist/src/ai/FlinkTool.js +2 -0
  59. package/dist/src/ai/InMemoryConversationAgent.d.ts +121 -0
  60. package/dist/src/ai/InMemoryConversationAgent.js +209 -0
  61. package/dist/src/ai/LLMAdapter.d.ts +148 -0
  62. package/dist/src/ai/LLMAdapter.js +2 -0
  63. package/dist/src/ai/PersistentFlinkAgent.d.ts +278 -0
  64. package/dist/src/ai/PersistentFlinkAgent.js +403 -0
  65. package/dist/src/ai/SubAgentExecutor.d.ts +38 -0
  66. package/dist/src/ai/SubAgentExecutor.js +223 -0
  67. package/dist/src/ai/ToolExecutor.d.ts +64 -0
  68. package/dist/src/ai/ToolExecutor.js +497 -0
  69. package/dist/src/ai/agentInstructions.d.ts +68 -0
  70. package/dist/src/ai/agentInstructions.js +286 -0
  71. package/dist/src/ai/index.d.ts +8 -0
  72. package/dist/src/ai/index.js +26 -0
  73. package/dist/src/ai/instructionFileLoader.d.ts +44 -0
  74. package/dist/src/ai/instructionFileLoader.js +179 -0
  75. package/dist/src/auth/FlinkAuthPlugin.d.ts +1 -1
  76. package/dist/src/handlers/StreamWriterFactory.d.ts +20 -0
  77. package/dist/src/handlers/StreamWriterFactory.js +83 -0
  78. package/dist/src/index.d.ts +14 -0
  79. package/dist/src/index.js +17 -0
  80. package/dist/src/loadPluginSchemas.d.ts +45 -0
  81. package/dist/src/loadPluginSchemas.js +143 -0
  82. package/dist/src/schema-extraction/ComplexTypeDetection.d.ts +40 -0
  83. package/dist/src/schema-extraction/ComplexTypeDetection.js +75 -0
  84. package/dist/src/schema-extraction/TypeScriptSourceParser.d.ts +321 -0
  85. package/dist/src/schema-extraction/TypeScriptSourceParser.js +925 -0
  86. package/dist/src/schema-extraction/TypeScriptSourceParser.spec.d.ts +1 -0
  87. package/dist/src/schema-extraction/TypeScriptSourceParser.spec.js +233 -0
  88. package/dist/src/schema-extraction/TypeScriptTokenizer.d.ts +57 -0
  89. package/dist/src/schema-extraction/TypeScriptTokenizer.js +177 -0
  90. package/dist/src/schema-extraction/index.d.ts +2 -0
  91. package/dist/src/schema-extraction/index.js +20 -0
  92. package/dist/src/schema-extraction/types.d.ts +31 -0
  93. package/dist/src/schema-extraction/types.js +2 -0
  94. package/dist/src/utils/loadFlinkConfig.d.ts +53 -0
  95. package/dist/src/utils/loadFlinkConfig.js +77 -0
  96. package/dist/src/utils.d.ts +30 -0
  97. package/dist/src/utils.js +52 -0
  98. package/dist/src/workers/SchemaGeneratorWorker.d.ts +1 -0
  99. package/dist/src/workers/SchemaGeneratorWorker.js +49 -0
  100. package/dist/src/workers/WorkerPool.d.ts +60 -0
  101. package/dist/src/workers/WorkerPool.js +306 -0
  102. package/examples/logging-hierarchical-example.ts +125 -0
  103. package/package.json +29 -4
  104. package/readme.md +499 -0
  105. package/spec/AgentDescendantDetection.spec.ts +335 -0
  106. package/spec/AgentDuplicateDetection.spec.ts +112 -0
  107. package/spec/AgentObserver.spec.ts +266 -0
  108. package/spec/AgentRunner.spec.ts +1062 -0
  109. package/spec/AsyncLocalStorageContext.spec.ts +223 -0
  110. package/spec/ConversationHooks.spec.ts +257 -0
  111. package/spec/FlinkAgent.spec.ts +681 -0
  112. package/spec/FlinkApp.htmlResponse.spec.ts +260 -0
  113. package/spec/FlinkApp.onError.invocation.spec.ts +151 -0
  114. package/spec/FlinkApp.onError.spec.ts +1 -2
  115. package/spec/FlinkApp.query.spec.ts +107 -0
  116. package/spec/FlinkApp.routeOrdering.spec.ts +61 -0
  117. package/spec/FlinkApp.undefinedResponse.spec.ts +123 -0
  118. package/spec/FlinkApp.validationMode.spec.ts +155 -0
  119. package/spec/FlinkJob.spec.ts +171 -0
  120. package/spec/FlinkLogFactory.spec.ts +337 -0
  121. package/spec/FlinkRepo.spec.ts +1 -1
  122. package/spec/LeaderElection.spec.ts +174 -0
  123. package/spec/StreamingIntegration.spec.ts +139 -0
  124. package/spec/ToolExecutor.spec.ts +465 -0
  125. package/spec/TypeScriptCompiler.spec.ts +1 -1
  126. package/spec/TypeScriptSourceParser.spec.ts +1215 -0
  127. package/spec/TypeScriptTokenizer.spec.ts +366 -0
  128. package/spec/ai/ContextCompaction.spec.ts +405 -0
  129. package/spec/ai/ConversationAgent.spec.ts +520 -0
  130. package/spec/ai/InMemoryConversationAgent.spec.ts +144 -0
  131. package/spec/ai/agentInstructions.spec.ts +358 -0
  132. package/spec/fixtures/agent-instructions/TestAgent.ts +24 -0
  133. package/spec/fixtures/agent-instructions/simple.md +3 -0
  134. package/spec/fixtures/agent-instructions/template.md +18 -0
  135. package/spec/fixtures/agent-instructions/yaml-format.yaml +9 -0
  136. package/spec/mock-project/dist/.tsbuildinfo +1 -0
  137. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCar.js +56 -0
  138. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCar2.js +58 -0
  139. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithArraySchema.js +52 -0
  140. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithArraySchema2.js +52 -0
  141. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithArraySchema3.js +52 -0
  142. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithLiteralSchema.js +54 -0
  143. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithLiteralSchema2.js +54 -0
  144. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithSchemaInFile.js +57 -0
  145. package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithSchemaInFile2.js +57 -0
  146. package/spec/mock-project/dist/spec/mock-project/src/handlers/ManuallyAddedHandler.js +53 -0
  147. package/spec/mock-project/dist/spec/mock-project/src/handlers/ManuallyAddedHandler2.js +55 -0
  148. package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchCar.js +57 -0
  149. package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchOnboardingSession.js +75 -0
  150. package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchOrderWithComplexTypes.js +57 -0
  151. package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchProductWithIntersection.js +58 -0
  152. package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchUserWithUnion.js +58 -0
  153. package/spec/mock-project/dist/spec/mock-project/src/handlers/PostCar.js +54 -0
  154. package/spec/mock-project/dist/spec/mock-project/src/handlers/PostLogin.js +55 -0
  155. package/spec/mock-project/dist/spec/mock-project/src/handlers/PostLogout.js +54 -0
  156. package/spec/mock-project/dist/spec/mock-project/src/handlers/PutCar.js +54 -0
  157. package/spec/mock-project/dist/spec/mock-project/src/index.js +83 -0
  158. package/spec/mock-project/dist/spec/mock-project/src/repos/CarRepo.js +26 -0
  159. package/spec/mock-project/dist/spec/mock-project/src/schemas/Car.js +2 -0
  160. package/spec/mock-project/dist/spec/mock-project/src/schemas/DefaultExportSchema.js +2 -0
  161. package/spec/mock-project/dist/spec/mock-project/src/schemas/FileWithTwoSchemas.js +2 -0
  162. package/spec/mock-project/dist/src/FlinkApp.js +1000 -0
  163. package/spec/mock-project/dist/src/FlinkContext.js +2 -0
  164. package/spec/mock-project/dist/src/FlinkErrors.js +143 -0
  165. package/spec/mock-project/dist/src/FlinkHttpHandler.js +47 -0
  166. package/spec/mock-project/dist/src/FlinkJob.js +2 -0
  167. package/spec/mock-project/dist/src/FlinkLog.js +119 -0
  168. package/spec/mock-project/dist/src/FlinkLogFactory.js +617 -0
  169. package/spec/mock-project/dist/src/FlinkPlugin.js +2 -0
  170. package/spec/mock-project/dist/src/FlinkRepo.js +224 -0
  171. package/spec/mock-project/dist/src/FlinkRequestContext.js +74 -0
  172. package/spec/mock-project/dist/src/FlinkResponse.js +2 -0
  173. package/spec/mock-project/dist/src/ai/AgentExecutor.js +279 -0
  174. package/spec/mock-project/dist/src/ai/AgentRunner.js +632 -0
  175. package/spec/mock-project/dist/src/ai/ConversationAgent.js +402 -0
  176. package/spec/mock-project/dist/src/ai/ConversationFlinkAgent.js +422 -0
  177. package/spec/mock-project/dist/src/ai/FlinkAgent.js +699 -0
  178. package/spec/mock-project/dist/src/ai/FlinkTool.js +2 -0
  179. package/spec/mock-project/dist/src/ai/InMemoryConversationAgent.js +209 -0
  180. package/spec/mock-project/dist/src/ai/LLMAdapter.js +2 -0
  181. package/spec/mock-project/dist/src/ai/SubAgentExecutor.js +223 -0
  182. package/spec/mock-project/dist/src/ai/ToolExecutor.js +412 -0
  183. package/spec/mock-project/dist/src/ai/agentInstructions.js +246 -0
  184. package/spec/mock-project/dist/src/auth/FlinkAuthPlugin.js +2 -0
  185. package/spec/mock-project/dist/src/auth/FlinkAuthUser.js +2 -0
  186. package/spec/mock-project/dist/src/handlers/GetCar.js +26 -52
  187. package/spec/mock-project/dist/src/handlers/GetCar.js.map +1 -0
  188. package/spec/mock-project/dist/src/handlers/GetCar2.js +32 -54
  189. package/spec/mock-project/dist/src/handlers/GetCar2.js.map +1 -0
  190. package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema.js +26 -48
  191. package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema.js.map +1 -0
  192. package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema2.js +28 -48
  193. package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema2.js.map +1 -0
  194. package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema3.js +29 -48
  195. package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema3.js.map +1 -0
  196. package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema.js +26 -50
  197. package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema.js.map +1 -0
  198. package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema2.js +28 -50
  199. package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema2.js.map +1 -0
  200. package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile.js +27 -53
  201. package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile.js.map +1 -0
  202. package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile2.js +29 -53
  203. package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile2.js.map +1 -0
  204. package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler.js +16 -49
  205. package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler.js.map +1 -0
  206. package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler2.js +25 -50
  207. package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler2.js.map +1 -0
  208. package/spec/mock-project/dist/src/handlers/PatchCar.js +27 -53
  209. package/spec/mock-project/dist/src/handlers/PatchCar.js.map +1 -0
  210. package/spec/mock-project/dist/src/handlers/PatchOnboardingSession.js +44 -70
  211. package/spec/mock-project/dist/src/handlers/PatchOnboardingSession.js.map +1 -0
  212. package/spec/mock-project/dist/src/handlers/PatchOrderWithComplexTypes.js +27 -53
  213. package/spec/mock-project/dist/src/handlers/PatchOrderWithComplexTypes.js.map +1 -0
  214. package/spec/mock-project/dist/src/handlers/PatchProductWithIntersection.js +28 -54
  215. package/spec/mock-project/dist/src/handlers/PatchProductWithIntersection.js.map +1 -0
  216. package/spec/mock-project/dist/src/handlers/PatchUserWithUnion.js +28 -54
  217. package/spec/mock-project/dist/src/handlers/PatchUserWithUnion.js.map +1 -0
  218. package/spec/mock-project/dist/src/handlers/PostCar.js +24 -50
  219. package/spec/mock-project/dist/src/handlers/PostCar.js.map +1 -0
  220. package/spec/mock-project/dist/src/handlers/PostLogin.js +25 -51
  221. package/spec/mock-project/dist/src/handlers/PostLogin.js.map +1 -0
  222. package/spec/mock-project/dist/src/handlers/PostLogout.js +24 -50
  223. package/spec/mock-project/dist/src/handlers/PostLogout.js.map +1 -0
  224. package/spec/mock-project/dist/src/handlers/PutCar.js +24 -50
  225. package/spec/mock-project/dist/src/handlers/PutCar.js.map +1 -0
  226. package/spec/mock-project/dist/src/handlers/StreamWriterFactory.js +83 -0
  227. package/spec/mock-project/dist/src/index.js +52 -76
  228. package/spec/mock-project/dist/src/index.js.map +1 -0
  229. package/spec/mock-project/dist/src/mock-data-generator.js +9 -0
  230. package/spec/mock-project/dist/src/repos/CarRepo.js +12 -24
  231. package/spec/mock-project/dist/src/repos/CarRepo.js.map +1 -0
  232. package/spec/mock-project/dist/src/schemas/Car.js +3 -1
  233. package/spec/mock-project/dist/src/schemas/Car.js.map +1 -0
  234. package/spec/mock-project/dist/src/schemas/DefaultExportSchema.js +3 -1
  235. package/spec/mock-project/dist/src/schemas/DefaultExportSchema.js.map +1 -0
  236. package/spec/mock-project/dist/src/schemas/FileWithTwoSchemas.js +3 -1
  237. package/spec/mock-project/dist/src/schemas/FileWithTwoSchemas.js.map +1 -0
  238. package/spec/mock-project/dist/src/utils.js +290 -0
  239. package/spec/mock-project/tsconfig.json +6 -1
  240. package/spec/schema-generation-nested-objects.spec.ts +97 -0
  241. package/spec/testHelpers.ts +49 -0
  242. package/spec/utils.caseConversion.spec.ts +78 -0
  243. package/spec/utils.spec.ts +13 -13
  244. package/src/DependencyTracker.ts +166 -0
  245. package/src/FlinkApp.ts +919 -155
  246. package/src/FlinkContext.ts +43 -0
  247. package/src/FlinkErrors.ts +32 -12
  248. package/src/FlinkHttpHandler.ts +246 -28
  249. package/src/FlinkJob.ts +11 -0
  250. package/src/FlinkLog.ts +119 -12
  251. package/src/FlinkLogFactory.ts +699 -0
  252. package/src/FlinkRepo.ts +10 -3
  253. package/src/FlinkRequestContext.ts +95 -0
  254. package/src/FlinkResponse.ts +6 -0
  255. package/src/FlinkService.ts +49 -0
  256. package/src/LeaderElection.ts +203 -0
  257. package/src/SchemaCache.ts +232 -0
  258. package/src/TypeScriptCompiler.ts +1347 -610
  259. package/src/TypeScriptUtils.ts +5 -0
  260. package/src/ai/AgentRunner.ts +646 -0
  261. package/src/ai/ConversationAgent.ts +413 -0
  262. package/src/ai/FlinkAgent.ts +1069 -0
  263. package/src/ai/FlinkTool.ts +165 -0
  264. package/src/ai/InMemoryConversationAgent.ts +149 -0
  265. package/src/ai/LLMAdapter.ts +126 -0
  266. package/src/ai/ToolExecutor.ts +485 -0
  267. package/src/ai/agentInstructions.ts +245 -0
  268. package/src/ai/index.ts +8 -0
  269. package/src/ai/instructionFileLoader.ts +156 -0
  270. package/src/auth/FlinkAuthPlugin.ts +2 -1
  271. package/src/handlers/StreamWriterFactory.ts +84 -0
  272. package/src/index.ts +14 -0
  273. package/src/loadPluginSchemas.ts +141 -0
  274. package/src/schema-extraction/TypeScriptSourceParser.ts +1058 -0
  275. package/src/schema-extraction/TypeScriptTokenizer.ts +205 -0
  276. package/src/schema-extraction/index.ts +2 -0
  277. package/src/schema-extraction/types.ts +34 -0
  278. package/src/utils/loadFlinkConfig.ts +89 -0
  279. package/src/utils.ts +52 -0
  280. package/tsconfig.json +6 -1
@@ -0,0 +1,279 @@
1
+ import { FlinkContext } from "../FlinkContext";
2
+ import { AgentExecuteContext, AgentExecuteInput, AgentExecuteResult, AgentFinishContext, FlinkAgent } from "./FlinkAgent";
3
+ export declare const logger: import("../FlinkLogFactory").ComponentLogger;
4
+ /**
5
+ * Storage message format - flexible structure for conversation persistence.
6
+ *
7
+ * Supports text content, tool calls, and tool results in a single message.
8
+ * More flexible than FlinkAgent's union Message type for storage purposes.
9
+ */
10
+ export interface StorageMessage {
11
+ role: "user" | "assistant" | "system" | "tool";
12
+ content?: string;
13
+ toolCalls?: Array<{
14
+ id: string;
15
+ name: string;
16
+ input: any;
17
+ }>;
18
+ toolResults?: Array<{
19
+ id: string;
20
+ result: any;
21
+ }>;
22
+ }
23
+ /**
24
+ * Conversation data structure for persistent storage.
25
+ *
26
+ * @property messages - Array of conversation messages in the storage format
27
+ * @property providerMetadata - Provider-specific metadata (e.g., OpenAI's responseId, instructionsHash)
28
+ */
29
+ export interface ConversationData {
30
+ messages: StorageMessage[];
31
+ providerMetadata?: Record<string, any>;
32
+ }
33
+ /**
34
+ * Abstract base class for agents with automatic conversation persistence.
35
+ *
36
+ * ConversationAgent eliminates boilerplate by automatically:
37
+ * - Loading conversation history before agent execution
38
+ * - Saving messages and provider metadata after execution
39
+ * - Enabling LLM provider optimizations (e.g., OpenAI's previousResponseId for 40-80% cost savings)
40
+ *
41
+ * ## Benefits
42
+ *
43
+ * - **Type Safety**: Abstract methods enforce consistent storage implementation
44
+ * - **Backend Flexibility**: Works with MongoDB, Redis, in-memory, or any storage backend
45
+ * - **Sub-Agent Aware**: Automatically skips persistence for sub-agent calls (parent handles it)
46
+ * - **Metadata Tracking**: Preserves provider metadata for debugging and future extensibility
47
+ *
48
+ * ## Usage Examples
49
+ *
50
+ * ### MongoDB Storage
51
+ * ```typescript
52
+ * export default class CarAgent extends ConversationAgent<AppContext> {
53
+ * id = "car-agent";
54
+ * description = "Car assistant with persistent conversations";
55
+ * instructions = "You are a helpful car expert...";
56
+ * tools = ["search-cars"];
57
+ *
58
+ * protected async loadConversation(conversationId: string) {
59
+ * const conv = await this.ctx.repos.conversationRepo.getById(conversationId);
60
+ * return conv ? {
61
+ * messages: conv.messages,
62
+ * providerMetadata: conv.providerMetadata,
63
+ * } : null;
64
+ * }
65
+ *
66
+ * protected async saveConversation(
67
+ * conversationId: string,
68
+ * data: ConversationData,
69
+ * result: AgentExecuteResult,
70
+ * context: AgentFinishContext
71
+ * ) {
72
+ * await this.ctx.repos.conversationRepo.upsert({
73
+ * _id: conversationId,
74
+ * agentId: this.id,
75
+ * userId: context.user?.id,
76
+ * messages: data.messages,
77
+ * providerMetadata: data.providerMetadata,
78
+ * updatedAt: new Date(),
79
+ * });
80
+ * }
81
+ * }
82
+ * ```
83
+ *
84
+ * ### Redis Storage
85
+ * ```typescript
86
+ * export default class CarAgent extends ConversationAgent<AppContext> {
87
+ * id = "car-agent";
88
+ * description = "Car assistant with Redis-backed conversations";
89
+ * instructions = "You are a helpful car expert...";
90
+ * tools = ["search-cars"];
91
+ *
92
+ * protected async loadConversation(conversationId: string) {
93
+ * const key = `conversation:${conversationId}`;
94
+ * const data = await this.ctx.redis.get(key);
95
+ * return data ? JSON.parse(data) : null;
96
+ * }
97
+ *
98
+ * protected async saveConversation(
99
+ * conversationId: string,
100
+ * data: ConversationData
101
+ * ) {
102
+ * const key = `conversation:${conversationId}`;
103
+ * await this.ctx.redis.setex(
104
+ * key,
105
+ * 86400, // 24 hour TTL
106
+ * JSON.stringify(data)
107
+ * );
108
+ * }
109
+ * }
110
+ * ```
111
+ *
112
+ * ### In-Memory Storage (Development/Testing)
113
+ * ```typescript
114
+ * const conversationStore = new Map<string, ConversationData>();
115
+ *
116
+ * export default class CarAgent extends ConversationAgent<AppContext> {
117
+ * id = "car-agent";
118
+ * description = "Car assistant with in-memory conversations";
119
+ * instructions = "You are a helpful car expert...";
120
+ * tools = ["search-cars"];
121
+ *
122
+ * protected async loadConversation(conversationId: string) {
123
+ * return conversationStore.get(conversationId) || null;
124
+ * }
125
+ *
126
+ * protected async saveConversation(
127
+ * conversationId: string,
128
+ * data: ConversationData
129
+ * ) {
130
+ * conversationStore.set(conversationId, data);
131
+ * }
132
+ * }
133
+ * ```
134
+ *
135
+ * ## Handler Usage
136
+ *
137
+ * ```typescript
138
+ * const handler: PostHandler<AppContext, Input, Output> = async ({ ctx, body, req }) => {
139
+ * const conversationId = body.conversationId || generateId();
140
+ *
141
+ * const result = await ctx.agents.carAgent
142
+ * .withUser(req.user)
143
+ * .execute({ message: body.message, conversationId });
144
+ *
145
+ * return {
146
+ * conversationId,
147
+ * message: (await result.result).message,
148
+ * };
149
+ * };
150
+ * ```
151
+ *
152
+ * ## Provider Metadata Flow
153
+ *
154
+ * 1. First turn: Agent executes, LLM returns metadata (e.g., `{ openai: { responseId: "..." } }`)
155
+ * 2. saveConversation() stores messages + metadata
156
+ * 3. Second turn: loadConversation() returns messages + metadata
157
+ * 4. beforeRun() populates input.providerMetadata (always preserved)
158
+ * 5. LLM adapter receives metadata for tracking/debugging purposes
159
+ * 6. Full conversation history is always sent to ensure reliability
160
+ *
161
+ * @template Context - Application context type extending FlinkContext
162
+ *
163
+ * @see {@link https://flink.dev/docs/ai/agents/persistence | Persistence Guide}
164
+ * @see {@link https://platform.openai.com/docs/guides/conversation-history | OpenAI Conversation History}
165
+ */
166
+ export declare abstract class ConversationAgent<Context extends FlinkContext = FlinkContext> extends FlinkAgent<Context> {
167
+ /**
168
+ * Load conversation history and provider metadata for the given conversation ID.
169
+ *
170
+ * Called automatically in beforeRun() before agent execution.
171
+ *
172
+ * @param conversationId - Unique identifier for the conversation
173
+ * @returns Conversation data (messages + providerMetadata), or null if not found
174
+ *
175
+ * @example
176
+ * ```typescript
177
+ * protected async loadConversation(conversationId: string) {
178
+ * const conv = await this.ctx.repos.conversationRepo.getById(conversationId);
179
+ * return conv ? {
180
+ * messages: conv.messages,
181
+ * providerMetadata: conv.providerMetadata,
182
+ * } : null;
183
+ * }
184
+ * ```
185
+ */
186
+ protected abstract loadConversation(conversationId: string): Promise<ConversationData | null>;
187
+ /**
188
+ * Save conversation history and provider metadata.
189
+ *
190
+ * Called automatically in afterRun() after agent execution completes successfully.
191
+ *
192
+ * @param conversationId - Unique identifier for the conversation
193
+ * @param data - Conversation data to save (messages + providerMetadata)
194
+ * @param result - Agent execution result (for access to final output if needed)
195
+ * @param context - Agent finish context (includes user, isSubAgent, etc.)
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * protected async saveConversation(
200
+ * conversationId: string,
201
+ * data: ConversationData,
202
+ * result: AgentExecuteResult,
203
+ * context: AgentFinishContext
204
+ * ) {
205
+ * await this.ctx.repos.conversationRepo.upsert({
206
+ * _id: conversationId,
207
+ * agentId: this.id,
208
+ * userId: context.user?.id,
209
+ * messages: data.messages,
210
+ * providerMetadata: data.providerMetadata,
211
+ * updatedAt: new Date(),
212
+ * });
213
+ * }
214
+ * ```
215
+ */
216
+ protected abstract saveConversation(conversationId: string, data: ConversationData, result: AgentExecuteResult, context: AgentFinishContext): Promise<void>;
217
+ /**
218
+ * Lifecycle hook: Load conversation history before agent execution.
219
+ *
220
+ * Automatically populates input.history and input.providerMetadata from storage.
221
+ *
222
+ * @internal
223
+ */
224
+ protected beforeRun(input: AgentExecuteInput, context: AgentExecuteContext): Promise<void>;
225
+ /**
226
+ * Lifecycle hook: Save conversation history after agent execution.
227
+ *
228
+ * Automatically converts LLM messages to storage format and saves with provider metadata.
229
+ * Skips save for sub-agent calls (parent agent handles persistence).
230
+ *
231
+ * @internal
232
+ */
233
+ protected afterRun(result: AgentExecuteResult, context: AgentFinishContext): Promise<void>;
234
+ /**
235
+ * Convert storage messages back to agent Message format for input.history.
236
+ *
237
+ * @param storageMessages - Messages from storage in StorageMessage format
238
+ * @returns Message array compatible with AgentExecuteInput.history
239
+ *
240
+ * @internal
241
+ */
242
+ private convertToAgentMessages;
243
+ /**
244
+ * Convert LLM adapter messages to storage format for persistence.
245
+ *
246
+ * @param llmMessages - Messages from LLM adapter in their native format
247
+ * @returns StorageMessage array
248
+ *
249
+ * @internal
250
+ */
251
+ private convertToMessages;
252
+ /**
253
+ * Extract text content from message content blocks.
254
+ *
255
+ * @param blocks - Content blocks from LLM message
256
+ * @returns Concatenated text content, or undefined if no text blocks
257
+ *
258
+ * @internal
259
+ */
260
+ private extractTextFromBlocks;
261
+ /**
262
+ * Extract tool calls from message content blocks.
263
+ *
264
+ * @param blocks - Content blocks from LLM message
265
+ * @returns Array of tool call objects
266
+ *
267
+ * @internal
268
+ */
269
+ private extractToolCalls;
270
+ /**
271
+ * Extract tool results from message content blocks.
272
+ *
273
+ * @param blocks - Content blocks from LLM message
274
+ * @returns Array of tool result objects
275
+ *
276
+ * @internal
277
+ */
278
+ private extractToolResults;
279
+ }
@@ -0,0 +1,404 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
18
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
19
+ return new (P || (P = Promise))(function (resolve, reject) {
20
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
21
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
22
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
23
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
24
+ });
25
+ };
26
+ var __generator = (this && this.__generator) || function (thisArg, body) {
27
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
28
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
29
+ function verb(n) { return function (v) { return step([n, v]); }; }
30
+ function step(op) {
31
+ if (f) throw new TypeError("Generator is already executing.");
32
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
33
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
34
+ if (y = 0, t) op = [op[0] & 2, t.value];
35
+ switch (op[0]) {
36
+ case 0: case 1: t = op; break;
37
+ case 4: _.label++; return { value: op[1], done: false };
38
+ case 5: _.label++; y = op[1]; op = [0]; continue;
39
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
40
+ default:
41
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
42
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
43
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
44
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
45
+ if (t[2]) _.ops.pop();
46
+ _.trys.pop(); continue;
47
+ }
48
+ op = body.call(thisArg, _);
49
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
50
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
51
+ }
52
+ };
53
+ Object.defineProperty(exports, "__esModule", { value: true });
54
+ exports.ConversationAgent = exports.logger = void 0;
55
+ var FlinkLogFactory_1 = require("../FlinkLogFactory");
56
+ var FlinkAgent_1 = require("./FlinkAgent");
57
+ exports.logger = FlinkLogFactory_1.FlinkLogFactory.createLogger("flink.ai.conversation-agent");
58
+ /**
59
+ * Abstract base class for agents with automatic conversation persistence.
60
+ *
61
+ * ConversationAgent eliminates boilerplate by automatically:
62
+ * - Loading conversation history before agent execution
63
+ * - Saving messages and provider metadata after execution
64
+ * - Enabling LLM provider optimizations (e.g., OpenAI's previousResponseId for 40-80% cost savings)
65
+ *
66
+ * ## Benefits
67
+ *
68
+ * - **Type Safety**: Abstract methods enforce consistent storage implementation
69
+ * - **Backend Flexibility**: Works with MongoDB, Redis, in-memory, or any storage backend
70
+ * - **Sub-Agent Aware**: Automatically skips persistence for sub-agent calls (parent handles it)
71
+ * - **Metadata Tracking**: Preserves provider metadata for debugging and future extensibility
72
+ *
73
+ * ## Usage Examples
74
+ *
75
+ * ### MongoDB Storage
76
+ * ```typescript
77
+ * export default class CarAgent extends ConversationAgent<AppContext> {
78
+ * id = "car-agent";
79
+ * description = "Car assistant with persistent conversations";
80
+ * instructions = "You are a helpful car expert...";
81
+ * tools = ["search-cars"];
82
+ *
83
+ * protected async loadConversation(conversationId: string) {
84
+ * const conv = await this.ctx.repos.conversationRepo.getById(conversationId);
85
+ * return conv ? {
86
+ * messages: conv.messages,
87
+ * providerMetadata: conv.providerMetadata,
88
+ * } : null;
89
+ * }
90
+ *
91
+ * protected async saveConversation(
92
+ * conversationId: string,
93
+ * data: ConversationData,
94
+ * result: AgentExecuteResult,
95
+ * context: AgentFinishContext
96
+ * ) {
97
+ * await this.ctx.repos.conversationRepo.upsert({
98
+ * _id: conversationId,
99
+ * agentId: this.id,
100
+ * userId: context.user?.id,
101
+ * messages: data.messages,
102
+ * providerMetadata: data.providerMetadata,
103
+ * updatedAt: new Date(),
104
+ * });
105
+ * }
106
+ * }
107
+ * ```
108
+ *
109
+ * ### Redis Storage
110
+ * ```typescript
111
+ * export default class CarAgent extends ConversationAgent<AppContext> {
112
+ * id = "car-agent";
113
+ * description = "Car assistant with Redis-backed conversations";
114
+ * instructions = "You are a helpful car expert...";
115
+ * tools = ["search-cars"];
116
+ *
117
+ * protected async loadConversation(conversationId: string) {
118
+ * const key = `conversation:${conversationId}`;
119
+ * const data = await this.ctx.redis.get(key);
120
+ * return data ? JSON.parse(data) : null;
121
+ * }
122
+ *
123
+ * protected async saveConversation(
124
+ * conversationId: string,
125
+ * data: ConversationData
126
+ * ) {
127
+ * const key = `conversation:${conversationId}`;
128
+ * await this.ctx.redis.setex(
129
+ * key,
130
+ * 86400, // 24 hour TTL
131
+ * JSON.stringify(data)
132
+ * );
133
+ * }
134
+ * }
135
+ * ```
136
+ *
137
+ * ### In-Memory Storage (Development/Testing)
138
+ * ```typescript
139
+ * const conversationStore = new Map<string, ConversationData>();
140
+ *
141
+ * export default class CarAgent extends ConversationAgent<AppContext> {
142
+ * id = "car-agent";
143
+ * description = "Car assistant with in-memory conversations";
144
+ * instructions = "You are a helpful car expert...";
145
+ * tools = ["search-cars"];
146
+ *
147
+ * protected async loadConversation(conversationId: string) {
148
+ * return conversationStore.get(conversationId) || null;
149
+ * }
150
+ *
151
+ * protected async saveConversation(
152
+ * conversationId: string,
153
+ * data: ConversationData
154
+ * ) {
155
+ * conversationStore.set(conversationId, data);
156
+ * }
157
+ * }
158
+ * ```
159
+ *
160
+ * ## Handler Usage
161
+ *
162
+ * ```typescript
163
+ * const handler: PostHandler<AppContext, Input, Output> = async ({ ctx, body, req }) => {
164
+ * const conversationId = body.conversationId || generateId();
165
+ *
166
+ * const result = await ctx.agents.carAgent
167
+ * .withUser(req.user)
168
+ * .execute({ message: body.message, conversationId });
169
+ *
170
+ * return {
171
+ * conversationId,
172
+ * message: (await result.result).message,
173
+ * };
174
+ * };
175
+ * ```
176
+ *
177
+ * ## Provider Metadata Flow
178
+ *
179
+ * 1. First turn: Agent executes, LLM returns metadata (e.g., `{ openai: { responseId: "..." } }`)
180
+ * 2. saveConversation() stores messages + metadata
181
+ * 3. Second turn: loadConversation() returns messages + metadata
182
+ * 4. beforeRun() populates input.providerMetadata (always preserved)
183
+ * 5. LLM adapter receives metadata for tracking/debugging purposes
184
+ * 6. Full conversation history is always sent to ensure reliability
185
+ *
186
+ * @template Context - Application context type extending FlinkContext
187
+ *
188
+ * @see {@link https://flink.dev/docs/ai/agents/persistence | Persistence Guide}
189
+ * @see {@link https://platform.openai.com/docs/guides/conversation-history | OpenAI Conversation History}
190
+ */
191
+ var ConversationAgent = /** @class */ (function (_super) {
192
+ __extends(ConversationAgent, _super);
193
+ function ConversationAgent() {
194
+ return _super !== null && _super.apply(this, arguments) || this;
195
+ }
196
+ /**
197
+ * Lifecycle hook: Load conversation history before agent execution.
198
+ *
199
+ * Automatically populates input.history and input.providerMetadata from storage.
200
+ *
201
+ * @internal
202
+ */
203
+ ConversationAgent.prototype.beforeRun = function (input, context) {
204
+ return __awaiter(this, void 0, void 0, function () {
205
+ var conversationId, conversationData, error_1;
206
+ return __generator(this, function (_a) {
207
+ switch (_a.label) {
208
+ case 0:
209
+ conversationId = input.conversationId;
210
+ if (!conversationId) {
211
+ exports.logger.debug("[".concat(this.id, "] No conversationId provided, starting fresh conversation"));
212
+ return [2 /*return*/];
213
+ }
214
+ _a.label = 1;
215
+ case 1:
216
+ _a.trys.push([1, 3, , 4]);
217
+ return [4 /*yield*/, this.loadConversation(conversationId)];
218
+ case 2:
219
+ conversationData = _a.sent();
220
+ if (conversationData) {
221
+ input.history = this.convertToAgentMessages(conversationData.messages);
222
+ // Always preserve provider metadata (for tracking and future use)
223
+ input.providerMetadata = conversationData.providerMetadata;
224
+ exports.logger.debug("[".concat(this.id, "] Loaded conversation ").concat(conversationId, ": ").concat(conversationData.messages.length, " messages"));
225
+ }
226
+ else {
227
+ exports.logger.debug("[".concat(this.id, "] No conversation found for ").concat(conversationId, ", starting fresh"));
228
+ }
229
+ return [3 /*break*/, 4];
230
+ case 3:
231
+ error_1 = _a.sent();
232
+ exports.logger.error("[".concat(this.id, "] Failed to load conversation ").concat(conversationId, ":"), error_1);
233
+ throw error_1; // Propagate load errors
234
+ case 4: return [2 /*return*/];
235
+ }
236
+ });
237
+ });
238
+ };
239
+ /**
240
+ * Lifecycle hook: Save conversation history after agent execution.
241
+ *
242
+ * Automatically converts LLM messages to storage format and saves with provider metadata.
243
+ * Skips save for sub-agent calls (parent agent handles persistence).
244
+ *
245
+ * @internal
246
+ */
247
+ ConversationAgent.prototype.afterRun = function (result, context) {
248
+ return __awaiter(this, void 0, void 0, function () {
249
+ var conversationId, messages, providerMetadata, conversationData, error_2;
250
+ return __generator(this, function (_a) {
251
+ switch (_a.label) {
252
+ case 0:
253
+ conversationId = context.conversationId;
254
+ if (!conversationId) {
255
+ exports.logger.debug("[".concat(this.id, "] No conversationId provided, skipping save"));
256
+ return [2 /*return*/];
257
+ }
258
+ _a.label = 1;
259
+ case 1:
260
+ _a.trys.push([1, 3, , 4]);
261
+ messages = this.convertToMessages(context.messages);
262
+ providerMetadata = result.providerMetadata;
263
+ conversationData = {
264
+ messages: messages,
265
+ providerMetadata: providerMetadata,
266
+ };
267
+ return [4 /*yield*/, this.saveConversation(conversationId, conversationData, result, context)];
268
+ case 2:
269
+ _a.sent();
270
+ exports.logger.debug("[".concat(this.id, "] Saved conversation ").concat(conversationId, ": ").concat(messages.length, " messages, metadata=").concat(JSON.stringify(providerMetadata)));
271
+ return [3 /*break*/, 4];
272
+ case 3:
273
+ error_2 = _a.sent();
274
+ // Log but don't throw - request already succeeded, don't fail it now
275
+ exports.logger.error("[".concat(this.id, "] Failed to save conversation ").concat(conversationId, ":"), error_2);
276
+ return [3 /*break*/, 4];
277
+ case 4: return [2 /*return*/];
278
+ }
279
+ });
280
+ });
281
+ };
282
+ /**
283
+ * Convert storage messages back to agent Message format for input.history.
284
+ *
285
+ * @param storageMessages - Messages from storage in StorageMessage format
286
+ * @returns Message array compatible with AgentExecuteInput.history
287
+ *
288
+ * @internal
289
+ */
290
+ ConversationAgent.prototype.convertToAgentMessages = function (storageMessages) {
291
+ return storageMessages.flatMap(function (msg) {
292
+ // Check for tool results first (can be on user or tool role messages)
293
+ if (msg.toolResults && msg.toolResults.length > 0) {
294
+ // Tool results stored in storage format, convert to agent format
295
+ // Each tool result becomes a separate Message
296
+ return msg.toolResults.map(function (toolResult) { return ({
297
+ role: "tool",
298
+ toolCallId: toolResult.id,
299
+ toolName: "", // Not stored, but required by type
300
+ // Tool results are persisted as already-stringified payloads (see formatResultForAI).
301
+ // JSON.stringify-ing again would double-encode strings into escaped JSON literals.
302
+ result: typeof toolResult.result === "string" ? toolResult.result : JSON.stringify(toolResult.result),
303
+ }); });
304
+ }
305
+ else if (msg.role === "user") {
306
+ return [{ role: "user", content: msg.content || "" }];
307
+ }
308
+ else if (msg.role === "assistant") {
309
+ return [
310
+ {
311
+ role: "assistant",
312
+ content: msg.content || "",
313
+ toolCalls: msg.toolCalls,
314
+ },
315
+ ];
316
+ }
317
+ else {
318
+ // Fallback for unexpected cases
319
+ return [{ role: "user", content: msg.content || "" }];
320
+ }
321
+ });
322
+ };
323
+ /**
324
+ * Convert LLM adapter messages to storage format for persistence.
325
+ *
326
+ * @param llmMessages - Messages from LLM adapter in their native format
327
+ * @returns StorageMessage array
328
+ *
329
+ * @internal
330
+ */
331
+ ConversationAgent.prototype.convertToMessages = function (llmMessages) {
332
+ var _this = this;
333
+ return llmMessages.map(function (msg) {
334
+ var message = {
335
+ role: msg.role,
336
+ };
337
+ // Handle content blocks
338
+ if (Array.isArray(msg.content)) {
339
+ var text = _this.extractTextFromBlocks(msg.content);
340
+ if (text)
341
+ message.content = text;
342
+ var toolCalls = _this.extractToolCalls(msg.content);
343
+ if (toolCalls.length > 0)
344
+ message.toolCalls = toolCalls;
345
+ var toolResults = _this.extractToolResults(msg.content);
346
+ if (toolResults.length > 0)
347
+ message.toolResults = toolResults;
348
+ }
349
+ else if (typeof msg.content === "string") {
350
+ message.content = msg.content;
351
+ }
352
+ return message;
353
+ });
354
+ };
355
+ /**
356
+ * Extract text content from message content blocks.
357
+ *
358
+ * @param blocks - Content blocks from LLM message
359
+ * @returns Concatenated text content, or undefined if no text blocks
360
+ *
361
+ * @internal
362
+ */
363
+ ConversationAgent.prototype.extractTextFromBlocks = function (blocks) {
364
+ var textBlocks = blocks.filter(function (block) { return block.type === "text"; });
365
+ if (textBlocks.length === 0)
366
+ return undefined;
367
+ return textBlocks.map(function (block) { return block.text; }).join("");
368
+ };
369
+ /**
370
+ * Extract tool calls from message content blocks.
371
+ *
372
+ * @param blocks - Content blocks from LLM message
373
+ * @returns Array of tool call objects
374
+ *
375
+ * @internal
376
+ */
377
+ ConversationAgent.prototype.extractToolCalls = function (blocks) {
378
+ return blocks
379
+ .filter(function (block) { return block.type === "tool_use"; })
380
+ .map(function (block) { return ({
381
+ id: block.id,
382
+ name: block.name,
383
+ input: block.input,
384
+ }); });
385
+ };
386
+ /**
387
+ * Extract tool results from message content blocks.
388
+ *
389
+ * @param blocks - Content blocks from LLM message
390
+ * @returns Array of tool result objects
391
+ *
392
+ * @internal
393
+ */
394
+ ConversationAgent.prototype.extractToolResults = function (blocks) {
395
+ return blocks
396
+ .filter(function (block) { return block.type === "tool_result"; })
397
+ .map(function (block) { return ({
398
+ id: block.tool_use_id,
399
+ result: block.content,
400
+ }); });
401
+ };
402
+ return ConversationAgent;
403
+ }(FlinkAgent_1.FlinkAgent));
404
+ exports.ConversationAgent = ConversationAgent;