@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
package/CHANGELOG.md CHANGED
@@ -1,5 +1,1056 @@
1
1
  # @flink-app/flink
2
2
 
3
+ ## 2.0.0-alpha.100
4
+
5
+ ### Patch Changes
6
+
7
+ - 6e8166a: Fix handler `Params`/`Query` metadata extraction for semicolon-free `type` aliases (#77). The build-time source parser previously required `;` delimiters: a `type Params = { ... }` written without trailing/field semicolons would either extract only the first property or fail entirely (registering empty param metadata silently). `findTypeDefinition` now terminates an object type alias at its closing brace when no trailing `;` is present, and `extractPropertiesFromObjectType` now treats a top-level newline as a property separator while still preserving multi-line union/nested-object types.
8
+
9
+ ## 2.0.0-alpha.99
10
+
11
+ ### Minor Changes
12
+
13
+ - ed9cd2c: Extend `onError` callback to also fire for request validation (400 Bad request) and response validation (500 Bad response) failures, in addition to handler-thrown errors. Streaming handler errors continue to be delivered via `stream.error()` and do not trigger `onError`.
14
+
15
+ The callback context now also includes the app context as `ctx`, so handlers can use repos/plugins (e.g. `context.ctx.repos.errorLogRepo`) from within `onError`. `FlinkOptions` is now generic over the app context (`FlinkOptions<C>`) with a default of `FlinkContext`, keeping existing usages backward compatible.
16
+
17
+ ## 2.0.0-alpha.98
18
+
19
+ ### Minor Changes
20
+
21
+ - 2f4a132: feat: expose verified token on the request
22
+
23
+ The JWT auth plugin now populates `req.token` (the decoded, signature-verified
24
+ payload) and `req.rawToken` (the original token string) after successful
25
+ authentication. Handlers can read token claims such as `jti` directly instead of
26
+ re-extracting and re-decoding the bearer token with an unverified decode.
27
+
28
+ ```ts
29
+ // Before
30
+ const authHeader = req.headers.authorization;
31
+ const bearer = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : undefined;
32
+ const decoded = bearer ? (jsonwebtoken.decode(bearer) as { jti?: string }) : null;
33
+ const sessionId = decoded?.jti ?? legacySessionId(req.user._id);
34
+
35
+ // After
36
+ const { jti } = (req.token as { jti?: string }) ?? {};
37
+ const sessionId = jti ?? legacySessionId(req.user._id);
38
+ ```
39
+
40
+ `token` / `rawToken` are added as optional fields on the core `FlinkRequest`
41
+ type, populated by auth plugins that have a token concept.
42
+
43
+ ## 2.0.0-alpha.97
44
+
45
+ ### Minor Changes
46
+
47
+ - eed6bc1: Pass host application context to auth plugins.
48
+
49
+ `FlinkAuthPlugin.authenticateRequest` now receives the host app's context as an optional third argument. Flink core supplies it on every authenticated request, so auth plugins can access repos/services without the caller wiring up a lazy accessor or maintaining a module-level mutable reference.
50
+
51
+ For `@flink-app/jwt-auth-plugin`, this means `getUser` receives the context directly:
52
+
53
+ ```typescript
54
+ jwtAuthPlugin({
55
+ getUser: async (tokenData, req, ctx) => {
56
+ const user = await ctx?.repos.userRepo.getById(tokenData._id);
57
+ return user ? { username: user.username, _id: user._id } : null;
58
+ },
59
+ });
60
+ ```
61
+
62
+ The `getContext` option previously added in alpha.96 is no longer needed and has been removed — remove it from your `jwtAuthPlugin({ … })` call. The third `ctx` parameter on `getUser` is optional, so callbacks that ignore it are unaffected.
63
+
64
+ ## 2.0.0-alpha.96
65
+
66
+ ### Patch Changes
67
+
68
+ - Fix double-JSON-encoding of tool results on conversation reload.
69
+
70
+ `ConversationAgent.convertToAgentMessages` was re-stringifying tool result payloads that `ToolExecutor.formatResultForAI` had already serialized to a JSON string. Each reload escaped the value one more level, corrupting tool history on every continuation turn (visible through any LLM adapter, including Anthropic). Strings are now passed through untouched; non-string values are still stringified for backward compatibility with older storage rows.
71
+
72
+ ## 2.0.0-alpha.95
73
+
74
+ ## 2.0.0-alpha.94
75
+
76
+ ## 2.0.0-alpha.93
77
+
78
+ ## 2.0.0-alpha.92
79
+
80
+ ### Minor Changes
81
+
82
+ - 8d23d56: Add global `AgentObserver` for app-level agent tracing
83
+
84
+ A new `observer` option on `FlinkOptions.ai` lets applications register a single, app-wide hook that fires for every agent execution — covering both streamed and awaited (`response.result`) callers without per-agent plumbing.
85
+
86
+ Events expose data that was previously only internal to `AgentRunner`:
87
+
88
+ - `onRun` — pre-loop, with resolved system instructions and initial messages.
89
+ - `onLlmCall` — per step, immediately before the adapter call. `messages` reflects post-compaction state and `tools` reflects per-step permission filtering.
90
+ - `onStep` — per step end, with `assistantText`, per-step `toolCalls`, and `usage`.
91
+ - `onFinish` — post-loop (success or error), with the final result, total `durationMs`, and the error message on failure.
92
+
93
+ All events share a stable `runId` per execution; the same ID is now also returned on `AgentExecuteResult.runId` so apps can correlate persisted results with observer traces.
94
+
95
+ Observer callbacks are fire-and-forget: they may return a promise but the framework does not await them, and any thrown/rejected errors are caught and logged without affecting agent execution.
96
+
97
+ The existing per-agent `beforeRun` / `onStep` / `afterRun` hooks remain unchanged — use the observer for cross-cutting concerns (tracing, APM, cost accounting, dev tools) and per-agent hooks for business logic that needs to block or mutate state (conversation persistence, guardrails).
98
+
99
+ Example:
100
+
101
+ ```typescript
102
+ new FlinkApp({
103
+ ai: {
104
+ llms: { default: new AnthropicAdapter({ ... }) },
105
+ observer: {
106
+ onRun(e) {
107
+ trace.start(e.runId, { agentId: e.agentId, instructions: e.instructions });
108
+ },
109
+ onLlmCall(e) {
110
+ trace.recordLlmCall(e.runId, e.step, e.messages, e.tools);
111
+ },
112
+ onStep(e) {
113
+ trace.recordStep(e.runId, e.step, e.assistantText, e.toolCalls, e.usage);
114
+ },
115
+ onFinish(e) {
116
+ trace.finish(e.runId, { result: e.result, error: e.error, durationMs: e.durationMs });
117
+ },
118
+ },
119
+ },
120
+ });
121
+ ```
122
+
123
+ ## 2.0.0-alpha.91
124
+
125
+ ## 2.0.0-alpha.90
126
+
127
+ ### Minor Changes
128
+
129
+ - 0d84b5f: Add optional `meta` field to error responses for structured context
130
+
131
+ The `error` object in `FlinkResponse` now supports an optional `meta?: unknown`
132
+ field for passing structured payloads alongside an error (e.g. payment decline
133
+ codes, retry hints, gateway metadata). All six error helpers (`notFound`,
134
+ `conflict`, `badRequest`, `unauthorized`, `forbidden`, `internalServerError`)
135
+ accept it as an optional third argument.
136
+
137
+ The value must be JSON-serializable. If serialization fails (e.g. `BigInt`,
138
+ circular references), the framework silently strips `meta` and logs a warning
139
+ before sending the response.
140
+
141
+ ```typescript
142
+ return badRequest("Payment declined", "paymentDeclined", {
143
+ gatewayCode: "insufficient_funds",
144
+ attemptId: "att_123",
145
+ });
146
+ ```
147
+
148
+ Fully additive — existing callers are unaffected.
149
+
150
+ ## 2.0.0-alpha.89
151
+
152
+ ## 2.0.0-alpha.88
153
+
154
+ ## 2.0.0-alpha.87
155
+
156
+ ### Patch Changes
157
+
158
+ - Register Handlebars raw helper so {{{{raw}}}}...{{{{/raw}}}} blocks in agent instruction files pass content through literally instead of silently dropping it
159
+
160
+ ## 2.0.0-alpha.86
161
+
162
+ ## 2.0.0-alpha.85
163
+
164
+ ## 2.0.0-alpha.84
165
+
166
+ ## 2.0.0-alpha.83
167
+
168
+ ### Minor Changes
169
+
170
+ - Add FlinkService as optional business logic layer with auto-discovery, ctx injection, async onInit(), and mockCtx() test helper
171
+
172
+ ## 2.0.0-alpha.82
173
+
174
+ ## 2.0.0-alpha.81
175
+
176
+ ## 2.0.0-alpha.80
177
+
178
+ ## 2.0.0-alpha.79
179
+
180
+ ## 2.0.0-alpha.78
181
+
182
+ ## 2.0.0-alpha.77
183
+
184
+ ## 2.0.0-alpha.76
185
+
186
+ ## 2.0.0-alpha.75
187
+
188
+ ## 2.0.0-alpha.74
189
+
190
+ ### Patch Changes
191
+
192
+ - feat: add leader election for horizontally scaled job scheduling
193
+
194
+ Adds MongoDB-based leader election so that when multiple instances of a Flink app are running, only one (the leader) executes scheduled jobs. If the leader goes down, another instance takes over automatically. Includes dedicated scheduler logger and improved robustness.
195
+
196
+ - fix: add updateById method to FlinkRepo for convenient document updates by ID
197
+
198
+ ## 2.0.0-alpha.73
199
+
200
+ ### Patch Changes
201
+
202
+ - fix(flink): register static routes before parameterized routes to prevent e.g. GET /jobs/by-tags being matched by GET /jobs/:id
203
+
204
+ ## 2.0.0-alpha.72
205
+
206
+ ### Patch Changes
207
+
208
+ - fix(test-utils): accept typed FlinkApp instances in init() by casting internally
209
+
210
+ ## 2.0.0-alpha.71
211
+
212
+ ## 2.0.0-alpha.70
213
+
214
+ ## 2.0.0-alpha.69
215
+
216
+ ## 2.0.0-alpha.68
217
+
218
+ ## 2.0.0-alpha.67
219
+
220
+ ### Patch Changes
221
+
222
+ - 418cb54: feat(instructions): add `{{import "..."}}` directive for composable markdown instruction files
223
+
224
+ Markdown instruction files can now import other markdown files using `{{import "./path/to/file.md"}}`. Imports resolve relative to the containing file, support recursive chaining, and detect circular imports with a clear error message. Handlebars template variables continue to work normally across all imported content.
225
+
226
+ - 70d574c: refactor(agent): remove debug flag in favour of log levels
227
+
228
+ The `debug` property on `FlinkAgent` and `FlinkAgentProps` is removed. Verbose agent logging (LLM requests, responses, tool calls, compaction) is now always emitted at the `debug` log level and can be enabled via the standard Flink log level configuration (e.g. `LOG_LEVEL=debug` or per-logger overrides). This removes a redundant knob that duplicated what log levels already provide.
229
+
230
+ ## 2.0.0-alpha.66
231
+
232
+ ### Patch Changes
233
+
234
+ - 5593d26: fix(tools): resolve cross-schema \$ref into \$defs for LLM providers
235
+
236
+ Tools using auto-generated schemas with TypeScript type references (e.g. a shared Canvas.ElementInput type) produced schemas with \$ref values like `"Canvas.ElementInput"`. AJV handled these fine via its schema registry, but OpenAI rejects them with "reference can only point to definitions defined at the top level of the schema".
237
+
238
+ ToolExecutor now resolves all cross-schema refs into a self-contained \$defs block, rewriting \$ref values to the standard #/\$defs/... format before returning the schema to LLM adapters. The openai-adapter sanitizer also now recurses into \$defs entries.
239
+
240
+ ## 2.0.0-alpha.65
241
+
242
+ ## 2.0.0-alpha.64
243
+
244
+ ### Patch Changes
245
+
246
+ - 95b99ee: Add image and binary Buffer response support
247
+
248
+ Handlers can now return a Node.js `Buffer` as `data` when `responseType` is set to an image or binary MIME type. The buffer is sent as raw bytes with the correct `Content-Type` — no JSON wrapping.
249
+
250
+ Common image and binary MIME types are now first-class literals in `RouteProps.responseType` with autocomplete support: `"image/png"`, `"image/jpeg"`, `"image/gif"`, `"image/webp"`, `"image/svg+xml"`, `"application/pdf"`, `"application/octet-stream"`.
251
+
252
+ Example:
253
+
254
+ ```typescript
255
+ export const Route: RouteProps = {
256
+ path: "/logo",
257
+ responseType: "image/png",
258
+ };
259
+
260
+ const handler: GetHandler<Ctx, Buffer> = async () => {
261
+ const buf = await fs.promises.readFile("./assets/logo.png");
262
+ return { data: buf };
263
+ };
264
+ ```
265
+
266
+ ## 2.0.0-alpha.63
267
+
268
+ ### Patch Changes
269
+
270
+ - 810df2c: Fix FlinkJob afterDelay: "0ms" running in a tight loop instead of once. Zero-delay jobs now run immediately via setImmediate (exactly once) rather than being registered with a 0ms scheduler interval. Also adds specs covering uncaught exception handling for all job scheduling modes.
271
+ - 8dd0752: fix: prevent server crash when handler returns no data with a response schema defined
272
+
273
+ When a PATCH (or any) handler returned `{ status: 204 }` without a `data` field,
274
+ `JSON.stringify(undefined)` returned the JS value `undefined`, causing
275
+ `JSON.parse(undefined)` to throw a `SyntaxError` that crashed the entire server process.
276
+
277
+ New behaviour:
278
+
279
+ - Status 204 + no data → skip validation silently (intentional no-content response)
280
+ - Non-204 status + no data + response schema defined → return 500 bad response with a
281
+ descriptive error message (surfaces the developer mistake without crashing the server)
282
+ - Data present → validate against schema as before
283
+
284
+ ## 2.0.0-alpha.62
285
+
286
+ ### Minor Changes
287
+
288
+ - Add file-based agent instructions with Handlebars templating
289
+
290
+ The `instructions()` method now supports returning a file path or `{ file, params? }` object:
291
+
292
+ - Return a string ending in `.md`, `.txt`, `.yaml`, `.yml`, `.xml`, etc. to auto-load from disk
293
+ - Return `{ file: "instructions/agent.md", params: { tier: "premium" } }` for Handlebars templates
294
+ - All paths resolve relative to the project root (`process.cwd()`)
295
+ - Files are cached with mtime-based invalidation
296
+ - Template variables `{{ctx}}`, `{{agentContext}}`, and `{{user}}` are always available
297
+
298
+ Also fixes a bug where `getRequestPermissions()` returning `[]` outside a request context
299
+ would override `user.permissions` in the fallback chain, causing permission checks to fail.
300
+
301
+ ## 2.0.0-alpha.61
302
+
303
+ ## 2.0.0-alpha.60
304
+
305
+ ## 2.0.0-alpha.59
306
+
307
+ ### Minor Changes
308
+
309
+ - dbc2119: feat: add generic compiler extension system and @flink-app/inbound-email-plugin
310
+
311
+ Add `compilerPlugins` to `FlinkConfig` and `FlinkCompilerPlugin` interface so plugins can declare custom scan directories for auto-discovery. The TypeScript compiler reads these at build time, generates the corresponding `.flink/generatedXxx.ts` registration files, and includes them in the start script.
312
+
313
+ Introduce `@flink-app/inbound-email-plugin` as the first consumer of this system. It starts an SMTP server and automatically routes inbound emails to matching `EmailHandler` files discovered in `src/email-handlers/`. User and permission context are injected via `AsyncLocalStorage` for seamless integration with Flink tools and agents.
314
+
315
+ ## 2.0.0-alpha.58
316
+
317
+ ### Patch Changes
318
+
319
+ - Move @flink-app/ts-source-to-json-schema to dependencies (was incorrectly in devDependencies) and make @swc/core an optional peer dependency with graceful fallback to tsc
320
+
321
+ ## 2.0.0-alpha.57
322
+
323
+ ### Minor Changes
324
+
325
+ - ef7f495: Add AsyncLocalStorage for automatic user/permissions injection in tools
326
+
327
+ **New Features:**
328
+
329
+ - Tools now receive `user` and `permissions` parameters automatically from AsyncLocalStorage
330
+ - Declarative permissions in tool definitions - framework checks before execution
331
+ - No more need for explicit `agent.withUser()` bindings
332
+ - Context flows automatically: handler → agent → tools
333
+
334
+ **API Changes:**
335
+
336
+ - `ToolExecutor.execute()` signature: `(input, overrides?)` instead of `(input, user?, permissions?)`
337
+ - `FlinkTool` handler signature includes `user?` and `permissions?` parameters
338
+ - Permission checking supports explicit permissions without requiring user object
339
+
340
+ **Testing:**
341
+
342
+ - New test utilities: `withRequestContext()`, `createMockUser()`, `createMockRequestContext()`
343
+ - Override support for unit testing: `execute(input, { user, permissions })`
344
+ - 13 new AsyncLocalStorage integration tests
345
+
346
+ **Developer Experience:**
347
+
348
+ ```typescript
349
+ // Before: Manual user passing
350
+ await agent.withUser(req.user).execute({ message: "..." });
351
+
352
+ // After: Automatic context flow
353
+ await agent.execute({ message: "..." });
354
+
355
+ // Tools with declarative permissions
356
+ export const Tool: FlinkToolProps = {
357
+ permissions: ["car:read"], // ✨ Checked by framework
358
+ };
359
+
360
+ const handler: FlinkTool<Ctx, In, Out> = async ({
361
+ input,
362
+ ctx,
363
+ user,
364
+ permissions, // ✨ Auto-injected
365
+ }) => {
366
+ // Permission already verified - just implement logic
367
+ };
368
+ ```
369
+
370
+ - 2d53aa4: feat: automatic schema derivation for FlinkTools
371
+
372
+ FlinkTools now support automatic schema generation from TypeScript type parameters, eliminating the need for manual Zod or JSON Schema definitions.
373
+
374
+ **New Features:**
375
+
376
+ - Auto-generate input/output schemas from `FlinkTool<Ctx, Input, Output>` type parameters
377
+ - Support for TypeScript interfaces, inline types, and primitive types
378
+ - Three-tier validation precedence: Manual Zod > Manual JSON > Auto-generated
379
+ - Automatic ToolResult unwrapping (extracts `T` from `ToolResult<T>`)
380
+
381
+ **Breaking Changes:** None - fully backward compatible with existing tools
382
+
383
+ **Migration:**
384
+
385
+ ```typescript
386
+ // Before (manual schemas required)
387
+ export const Tool: FlinkToolProps = {
388
+ id: "search-cars",
389
+ description: "Search for cars",
390
+ inputSchema: z.object({ brand: z.string() }),
391
+ outputSchema: z.string(),
392
+ };
393
+
394
+ const SearchTool: FlinkTool<AppCtx, z.infer<typeof Tool.inputSchema>, z.infer<typeof Tool.outputSchema>> = async ({ input }) => {
395
+ return { success: true, data: "result" };
396
+ };
397
+
398
+ // After (schemas auto-generated from types)
399
+ interface SearchInput {
400
+ brand: string;
401
+ }
402
+
403
+ export const Tool: FlinkToolProps = {
404
+ id: "search-cars",
405
+ description: "Search for cars",
406
+ // No schemas needed!
407
+ };
408
+
409
+ const SearchTool: FlinkTool<AppCtx, SearchInput, string> = async ({ input }) => {
410
+ return { success: true, data: "result" };
411
+ };
412
+ ```
413
+
414
+ **Technical Details:**
415
+
416
+ - Schemas extracted during TypeScript compilation via ts-morph
417
+ - JSON schemas generated via ts-json-schema-generator
418
+ - `__schemas` export automatically added to tool source files
419
+ - JSDoc comments preserved in generated schemas
420
+
421
+ - b3cc5d1: feat(ai): add comprehensive cache metrics support for token usage tracking
422
+
423
+ ## Overview
424
+
425
+ Added detailed cache metrics to LLM adapters for better cost optimization and performance tracking. Both OpenAI and Anthropic adapters now capture and expose cache-related token counts.
426
+
427
+ ## What's New
428
+
429
+ ### LLMUsage Interface
430
+
431
+ - New `LLMUsage` interface with cache-related fields:
432
+ - `cachedInputTokens`: Tokens served from cache (lower cost)
433
+ - `cacheCreationInputTokens`: Tokens written to cache (Anthropic only, higher cost)
434
+
435
+ ### OpenAI Adapter
436
+
437
+ - Captures `cached_tokens` from `input_tokens_details`
438
+ - Provides 10% cost savings for cached tokens
439
+ - Includes cache metrics in usage logs
440
+
441
+ ### Anthropic Adapter
442
+
443
+ - Captures `cache_read_input_tokens` (10% cost)
444
+ - Captures `cache_creation_input_tokens` (125% cost)
445
+ - Full visibility into cache economics
446
+
447
+ ### AgentRunner
448
+
449
+ - Automatically aggregates cache metrics across multi-turn conversations
450
+ - Includes cache data in sub-agent call tracking
451
+ - Available in `AgentExecuteResult.usage`
452
+
453
+ ## Cache Economics
454
+
455
+ **OpenAI:**
456
+
457
+ - Cached tokens: ~10% of regular token cost
458
+ - Significant savings for repeated context
459
+
460
+ **Anthropic:**
461
+
462
+ - Cache read: 10% of regular token cost
463
+ - Cache write: 125% of regular token cost (one-time cost, then 10% on reads)
464
+ - Minimum cache threshold: 2048 tokens
465
+
466
+ ## Example Usage
467
+
468
+ ```typescript
469
+ const result = await agent.execute({ message: "Hello" });
470
+
471
+ console.log(result.usage);
472
+ // {
473
+ // inputTokens: 2006,
474
+ // outputTokens: 300,
475
+ // cachedInputTokens: 1920, // 95% cache hit!
476
+ // }
477
+
478
+ // Calculate actual billed input tokens
479
+ const billedTokens = result.usage.inputTokens - (result.usage.cachedInputTokens || 0);
480
+ console.log(`Only ${billedTokens} tokens charged at full rate`);
481
+ ```
482
+
483
+ ## Breaking Changes
484
+
485
+ None - all cache fields are optional and backwards compatible.
486
+
487
+ - d377fac: Add context compaction feature for automatic message history management in agents
488
+
489
+ Agents can now automatically manage message history size during long-running conversations using two new optional callbacks: `shouldCompact` and `compactHistory`. This prevents context window overflow and helps control token costs.
490
+
491
+ Features:
492
+
493
+ - `shouldCompact` callback to determine when compaction is needed (message count, size, token estimation, or custom logic)
494
+ - `compactHistory` callback to perform the actual compaction (sliding window, keep first+last, summarization, or custom strategy)
495
+ - Default compaction strategy (keep last 10 messages) when only `shouldCompact` is provided
496
+ - Async support for both callbacks
497
+ - Comprehensive error handling - failures are logged but don't break execution
498
+ - Debug logging to monitor compaction events
499
+ - Compaction occurs before each LLM call in the agentic loop
500
+
501
+ Example usage:
502
+
503
+ ```typescript
504
+ export default class ChatAgent extends FlinkAgent<AppCtx> {
505
+ id = "chat-agent";
506
+ description = "Chat assistant with history management";
507
+ instructions = "You are a helpful assistant...";
508
+
509
+ // Compact when history exceeds 20 messages
510
+ shouldCompact = (messages, step) => messages.length > 20;
511
+
512
+ // Keep only last 10 messages
513
+ compactHistory = (messages, step) => messages.slice(-10);
514
+ }
515
+ ```
516
+
517
+ This is a fully opt-in feature with no impact on existing agents.
518
+
519
+ - 90f80c7: Add `responseType` route option for non-JSON responses
520
+
521
+ Set `responseType` in `RouteProps` to send the handler's `data` field as a raw
522
+ response with the given content type instead of the standard JSON envelope.
523
+ Response schema validation is automatically skipped.
524
+
525
+ Accepts Express shorthand names (`"html"`, `"csv"`, `"text"`, `"xml"`) or any
526
+ full MIME type string.
527
+
528
+ ```typescript
529
+ export const Route: RouteProps = {
530
+ path: "/dashboard",
531
+ responseType: "html",
532
+ };
533
+
534
+ const handler: GetHandler<Ctx, void> = async ({ ctx }) => {
535
+ return {
536
+ data: `<!DOCTYPE html><html><body><h1>Dashboard</h1></body></html>`,
537
+ };
538
+ };
539
+
540
+ export default handler;
541
+ ```
542
+
543
+ ```typescript
544
+ export const Route: RouteProps = {
545
+ path: "/export",
546
+ responseType: "csv",
547
+ };
548
+
549
+ const handler: GetHandler<Ctx, void> = async ({ ctx }) => {
550
+ return { data: `id,name\n1,Alice\n2,Bob` };
551
+ };
552
+
553
+ export default handler;
554
+ ```
555
+
556
+ - f0887e7: feat: simplified conversation persistence with InMemoryConversationAgent
557
+
558
+ **New Features:**
559
+
560
+ 1. **ConversationAgent Base Class** - Abstract base class for automatic conversation persistence:
561
+
562
+ ```typescript
563
+ export default class ChatAgent extends ConversationAgent<AppContext> {
564
+ id = "chat-agent";
565
+ description = "Chat assistant with automatic persistence";
566
+ instructions = "You are a helpful assistant...";
567
+ tools = ["search-knowledge"];
568
+
569
+ protected async loadConversation(conversationId: string) {
570
+ const conv = await this.ctx.repos.conversationRepo.getById(conversationId);
571
+ return conv
572
+ ? {
573
+ messages: conv.messages,
574
+ providerMetadata: conv.providerMetadata,
575
+ }
576
+ : null;
577
+ }
578
+
579
+ protected async saveConversation(conversationId: string, data: ConversationData) {
580
+ await this.ctx.repos.conversationRepo.upsert({
581
+ _id: conversationId,
582
+ messages: data.messages,
583
+ providerMetadata: data.providerMetadata,
584
+ });
585
+ }
586
+ }
587
+ ```
588
+
589
+ 2. **InMemoryConversationAgent** - Opinionated convenience class for rapid prototyping:
590
+
591
+ ```typescript
592
+ export default class MyAgent extends InMemoryConversationAgent<AppContext> {
593
+ id = "my-agent";
594
+ description = "Quick prototype agent";
595
+ instructions = "You are a helpful assistant...";
596
+ tools = ["search-knowledge"];
597
+ // That's it! Storage already implemented
598
+ }
599
+
600
+ // Testing utilities
601
+ InMemoryConversationAgent.clearAll();
602
+ InMemoryConversationAgent.getConversationCount();
603
+ InMemoryConversationAgent.getAllConversationIds();
604
+ ```
605
+
606
+ 3. **Provider Metadata Tracking** - Framework preserves provider-specific metadata:
607
+
608
+ ```typescript
609
+ const result = await agent.execute({
610
+ message: "Hello",
611
+ conversationId: "conv-123",
612
+ }).result;
613
+
614
+ // Metadata preserved for debugging/future use
615
+ console.log(result.providerMetadata); // { openai: { ... } }
616
+ ```
617
+
618
+ **Simplified Architecture:**
619
+
620
+ Removed persistence strategies in favor of always sending full conversation history:
621
+
622
+ - ❌ Removed: `ConversationPersistenceStrategy` type ("auto" | "provider-optimized" | "full-history")
623
+ - ❌ Removed: `persistenceStrategy` property from ConversationAgent
624
+ - ❌ Removed: `persistenceStrategy` parameter from LLMAdapter.stream()
625
+ - ❌ Removed: OpenAI's previousResponseId optimization and instruction hashing
626
+ - ✅ Kept: Provider metadata preservation (for tracking/debugging/future use)
627
+ - ✅ Kept: Full conversation history always sent for reliability
628
+
629
+ **Benefits:**
630
+
631
+ - **Simplicity**: Single code path, easier to understand and maintain
632
+ - **Reliability**: No optimization edge cases or hybrid logic bugs
633
+ - **Debuggability**: Full conversation history always available
634
+ - **Rapid Prototyping**: InMemoryConversationAgent removes boilerplate
635
+ - **Future-Proof**: Can re-introduce optimizations with different architecture if needed
636
+
637
+ **Breaking Changes:**
638
+
639
+ For LLM Adapter Implementers:
640
+
641
+ - Must remove `persistenceStrategy` parameter from `stream()` method signature
642
+
643
+ For Agent Users (Optional Cleanup):
644
+
645
+ - Remove `persistenceStrategy` property from ConversationAgent subclasses (no longer used)
646
+ - Remove `persistenceStrategy` from execute options (no longer supported)
647
+
648
+ **Migration:**
649
+
650
+ Existing ConversationAgent implementations continue to work - just remove any `persistenceStrategy` references:
651
+
652
+ ```typescript
653
+ // Before
654
+ export default class MyAgent extends ConversationAgent<AppContext> {
655
+ persistenceStrategy = "full-history"; // ❌ Remove this
656
+
657
+ protected async loadConversation(conversationId: string) { ... }
658
+ protected async saveConversation(conversationId: string, data: ConversationData) { ... }
659
+ }
660
+
661
+ // After
662
+ export default class MyAgent extends ConversationAgent<AppContext> {
663
+ // ✅ Just implement storage methods
664
+ protected async loadConversation(conversationId: string) { ... }
665
+ protected async saveConversation(conversationId: string, data: ConversationData) { ... }
666
+ }
667
+ ```
668
+
669
+ For rapid prototyping, use InMemoryConversationAgent instead:
670
+
671
+ ```typescript
672
+ // New option: Zero boilerplate
673
+ export default class MyAgent extends InMemoryConversationAgent<AppContext> {
674
+ id = "my-agent";
675
+ description = "Quick prototype";
676
+ instructions = "...";
677
+ tools = [];
678
+ // Storage already implemented!
679
+ }
680
+ ```
681
+
682
+ - 68c46d3: feat(logging): add Java-style hierarchical prefix matching for component logging
683
+
684
+ Introduces hierarchical prefix matching inspired by Java logging frameworks (Log4j, Logback):
685
+
686
+ **Key Features:**
687
+
688
+ - **Dot notation**: `flink.ai.openai` (like Java packages)
689
+ - **Lowercase naming**: All logger names normalized to lowercase
690
+ - **Case-insensitive**: `Flink.AI.OpenAI` → `flink.ai.openai`
691
+ - **Hierarchical matching**: `flink.ai` matches all `flink.ai.*` loggers
692
+ - **Precedence**: More specific configs override less specific (Java inheritance)
693
+
694
+ **Usage:**
695
+
696
+ Environment variables:
697
+
698
+ ```bash
699
+ # Simple hierarchical config (recommended)
700
+ LOG_LEVELS=flink.ai:debug,flink.database:warn
701
+
702
+ # Fine-grained overrides
703
+ LOG_LEVELS=flink.ai:debug,flink.ai.openai:trace
704
+
705
+ # Wildcard patterns (advanced)
706
+ LOG_LEVELS=flink.ai.*:debug,flink.database.**:warn
707
+ ```
708
+
709
+ Programmatic API:
710
+
711
+ ```typescript
712
+ // Hierarchical prefix (Java-style)
713
+ FlinkLogFactory.setHierarchicalLevel("flink.ai", "debug");
714
+
715
+ // Exact match
716
+ FlinkLogFactory.setComponentLevel("flink.ai.openai", "trace");
717
+
718
+ // Wildcard pattern
719
+ FlinkLogFactory.setWildcardLevel("flink.database.*", "warn");
720
+
721
+ // Get effective level
722
+ FlinkLogFactory.getEffectiveLevel("flink.ai.openai"); // "trace"
723
+ ```
724
+
725
+ **Breaking Changes:**
726
+
727
+ - None - fully backward compatible with existing exact match configurations
728
+
729
+ **Migration:**
730
+ Existing logger names can be migrated to dot notation for hierarchical matching:
731
+
732
+ ```typescript
733
+ // Before: FlinkLogFactory.createLogger("OpenAI")
734
+ // After: FlinkLogFactory.createLogger("flink.ai.openai")
735
+ ```
736
+
737
+ - ### `flink dev` - Fast development mode with SWC
738
+
739
+ - Add `flink dev` command with fast watch mode using SWC for near-instant recompilation
740
+ - Migrate compilation from `ts.emit()` to SWC for ~20x faster builds
741
+ - Add background `tsc --watch` for async type checking during dev mode
742
+ - Add build timing logs for performance visibility
743
+
744
+ ### Logging configuration via `flink.config.js`
745
+
746
+ - Add support for `flink.config.js` configuration file for logging setup
747
+ - Refactor `FlinkLogFactory` for simpler log export and configuration
748
+
749
+ ### Plugin handler JSON schema support
750
+
751
+ - Add direct JSON schema support for plugin handlers via `inputJsonSchema`/`outputJsonSchema`
752
+ - Allows plugins (generic-auth, management-api) to define handler schemas without TypeScript type extraction
753
+
754
+ ### CLI improvements
755
+
756
+ - Fix tsc binary resolution by walking up directory tree (monorepo support)
757
+ - Put tsc watch buildinfo in `.flink/` instead of project root
758
+ - Extract shared CLI utilities and deduplicate compiler pipeline
759
+
760
+ ### Compiler fixes
761
+
762
+ - Fix void/any type handling in schema extraction
763
+ - Use project source files for SWC emit instead of disk globs
764
+ - Move `__file` metadata to registration objects instead of source files
765
+
766
+ ### `create-flink-app` updates
767
+
768
+ - Modernize default template with `flink dev` and `flink.config.js` logging config
769
+
770
+ ### Patch Changes
771
+
772
+ - 4ad44c0: fix: preserve assistant messages in conversation history
773
+
774
+ Fixed critical bugs where assistant messages were being filtered out:
775
+
776
+ **Core Framework Fix:**
777
+
778
+ - `AgentRunner.convertMessages()` now properly converts `toolCalls` array to `LLMContentBlock[]` format
779
+ - Assistant messages with tool calls are preserved with correct content block structure
780
+
781
+ **OpenAI Adapter Fix:**
782
+
783
+ - Removed incorrect code that was skipping assistant text messages
784
+ - OpenAI Responses API DOES support `{ role: "assistant", content: "..." }` in input
785
+ - Full conversation history now works correctly (both with and without `previousResponseId`)
786
+
787
+ **Result:**
788
+
789
+ - ✅ Multi-turn conversations work with full history (client-side)
790
+ - ✅ Multi-turn conversations work with `previousResponseId` (server-side, optimal)
791
+ - ✅ No more consecutive user messages violating API requirements
792
+ - ✅ Assistant messages preserved in all scenarios
793
+
794
+ - 4ad44c0: fix: enable JSDoc descriptions in generated JSON schemas
795
+
796
+ **Changed `jsDoc` mode from "basic" to "extended"** in TypeScript schema generator to properly extract JSDoc comments from source files.
797
+
798
+ **What works now:**
799
+
800
+ - ✅ JSDoc comments are now included as `description` fields in generated JSON schemas
801
+ - ✅ Works for schemas using direct type references: `GetHandler<Ctx, Car>`
802
+ - ✅ Works for schemas using `extends`: `interface Foo extends Car {}`
803
+
804
+ **Example:**
805
+
806
+ ```typescript
807
+ // Schema with JSDoc
808
+ interface Car {
809
+ /**
810
+ * Vehicle model name
811
+ */
812
+ model: string;
813
+ }
814
+
815
+ // Generated JSON Schema now includes:
816
+ {
817
+ "properties": {
818
+ "model": {
819
+ "type": "string",
820
+ "description": "Vehicle model name" // ✅ Description preserved!
821
+ }
822
+ }
823
+ }
824
+ ```
825
+
826
+ **Limitations:**
827
+
828
+ - ❌ Doesn't work for utility types like `Partial<Car>`, `Omit<Car, "id">` where inline properties are generated
829
+ - For these cases, define explicit intermediate interfaces with JSDoc instead
830
+
831
+ **Migration:** No action required - existing schemas without JSDoc continue to work. Add JSDoc block comments to schema properties to get descriptions in generated JSON schemas.
832
+
833
+ ## 2.0.0-alpha.57
834
+
835
+ ### Minor Changes
836
+
837
+ - feat: add content-hash-based schema caching for 70% faster builds
838
+
839
+ Implements intelligent schema caching to dramatically improve build performance when schemas and their dependencies haven't changed. This provides **70% faster schema generation** on subsequent builds with accurate, content-based cache invalidation.
840
+
841
+ **Performance Impact:**
842
+
843
+ - First build: Baseline (generates all schemas)
844
+ - Subsequent builds: 70% faster schema generation when schemas unchanged
845
+ - Partial changes: Only regenerates affected schemas and their dependents
846
+
847
+ **How It Works:**
848
+
849
+ - Computes SHA-256 content hashes of schema files and all dependencies
850
+ - Cache stored in `.flink/schema-cache.json` (automatically gitignored)
851
+ - Tracks handler/tool source files and their transitive dependencies
852
+ - Cache invalidates when:
853
+ - Schema file content changes
854
+ - Any dependency content changes (imports, types, etc.)
855
+ - Dependency set changes (imports added/removed)
856
+ - TypeScript version changes (major/minor)
857
+
858
+ **Example Build Output:**
859
+
860
+ ```bash
861
+ # First build (cache miss)
862
+ ✓ Schema generation completed in 510ms (28 handlers, 4 tools)
863
+ [Cache: 0 hits, 28 misses, 0 invalidated]
864
+
865
+ # Second build (cache hit)
866
+ ✓ Schema generation completed in 153ms (28 handlers, 4 tools)
867
+ [Cache: 28 hits, 0 misses, 0 invalidated]
868
+
869
+ # After modifying Car.ts
870
+ ✓ Schema generation completed in 250ms (28 handlers, 4 tools)
871
+ [Cache: 5 hits, 0 misses, 23 invalidated]
872
+ ```
873
+
874
+ **Benefits:**
875
+
876
+ - Zero configuration - automatic and transparent
877
+ - Git-friendly - content-based hashing works correctly with git operations
878
+ - Accurate invalidation - only regenerates when actual content changes
879
+ - Smart dependency tracking - tracks all imported types and their dependencies
880
+
881
+ **Migration:** No action needed - caching is automatic. The cache file is gitignored and can be safely deleted if needed.
882
+
883
+ ## 2.0.0-alpha.56
884
+
885
+ ### Patch Changes
886
+
887
+ - Zod 3.x compat
888
+ - 0203256: fix: add Zod 3.x compatibility for tool schema generation
889
+
890
+ Tools now work with both Zod 3.25+ and Zod 4.x. The `ToolExecutor` will use:
891
+
892
+ - Zod 4's built-in `z.toJSONSchema()` if available
893
+ - `zod-to-json-schema` package for Zod 3.x compatibility (fallback)
894
+
895
+ This allows apps to use their preferred Zod version without upgrading to 4.x.
896
+
897
+ **Changes:**
898
+
899
+ - Improved `fallbackSchema()` to use `zod-to-json-schema` instead of returning empty schema
900
+ - Added Zod as peer dependency (>=3.25.0 <5.0.0) for version flexibility
901
+ - Better error handling and logging for schema generation failures
902
+
903
+ **Migration:** No action needed - fully backward compatible.
904
+
905
+ ## 2.0.0-alpha.55
906
+
907
+ ### Minor Changes
908
+
909
+ - 497b7c2: feat: add dynamic instructions via callback for FlinkAgent
910
+
911
+ Agent instructions can now be either a static string or a callback function that generates dynamic instructions based on context. This enables powerful use cases like:
912
+
913
+ - Multi-language support (respond in user's preferred language)
914
+ - Multi-tenant SaaS (tenant-specific business rules and behavior)
915
+ - User tier-based behavior (VIP vs standard customers)
916
+ - Context-aware responses (conversation history, time-based, metadata-driven)
917
+
918
+ **Breaking Changes:** None - fully backwards compatible with existing string instructions.
919
+
920
+ **Example:**
921
+
922
+ ```typescript
923
+ export default class SupportAgent extends FlinkAgent<AppCtx> {
924
+ description = "Customer support specialist";
925
+
926
+ instructions = async (ctx, agentContext) => {
927
+ const profile = await ctx.repos.userRepo.getById(agentContext.user.id);
928
+ return `You are a support agent. Customer: ${profile.name}, Tier: ${profile.tier}`;
929
+ };
930
+
931
+ tools = [];
932
+ }
933
+ ```
934
+
935
+ The callback receives:
936
+
937
+ - `ctx`: FlinkContext with access to repos, plugins, etc.
938
+ - `agentContext`: AgentExecuteContext with user, conversationId, metadata
939
+
940
+ Instructions are resolved once per execution at the start of the agentic loop, providing natural caching and optimal performance.
941
+
942
+ ### Patch Changes
943
+
944
+ - 3267206: chore: remove deprecated declarative agent pattern and update documentation
945
+
946
+ Removed the unused `Agent?: FlinkAgentProps` property from FlinkAgentFile type. This old declarative pattern was never used - agents have always used the class-based pattern (extending FlinkAgent).
947
+
948
+ Also updated TypeScriptCompiler documentation to accurately reflect that agents are classes extending FlinkAgent, removing outdated references to "declarative props" and "(new pattern)" comments.
949
+
950
+ This cleanup simplifies the codebase and removes confusion about supported agent patterns.
951
+
952
+ - 3267206: fix: prevent infinite delegation loop in circular delegation test
953
+
954
+ Fixed test bug where createStreamingMock would reuse the last mocked response indefinitely. In the circular delegation test, both agents' last response was a tool_use that delegated, causing the test to loop until maxSteps (10) was reached, generating thousands of log lines.
955
+
956
+ Added final response with no tool calls to properly terminate the delegation chain. This reduces test output from thousands of lines to expected levels while maintaining proper test coverage of recursion depth limits.
957
+
958
+ ## 2.0.0-alpha.53
959
+
960
+ ### Patch Changes
961
+
962
+ - 669c806: fix: revert worker thread parallelization due to memory issues
963
+
964
+ Reverts the worker thread implementation for JSON schema generation due to critical memory exhaustion issues in large projects. Each worker was loading the entire TypeScript program (100-200MB), causing 1-2GB memory usage with multiple workers and crashing development environments.
965
+
966
+ The single-threaded schema generation remains stable and reliable for all project sizes.
967
+
968
+ ## 2.0.0-alpha.52
969
+
970
+ ### Patch Changes
971
+
972
+ - fe9f8f2: Improved compilation performance by parallelizing handler schema extraction. Projects with many handlers (90+) will see 3-10x faster build times.
973
+
974
+ ## 2.0.0-alpha.51
975
+
976
+ ## 2.0.0-alpha.50
977
+
978
+ ### Patch Changes
979
+
980
+ - Fix compiler incorrectly treating all files in src/tools/ as tools. The compiler now checks for FlinkToolProps export early and skips utility files, type definitions, and index files that aren't actual tools, preventing false "Missing FlinkToolProps export" errors.
981
+
982
+ ## 2.0.0-alpha.49
983
+
984
+ ### Patch Changes
985
+
986
+ - Typescript include fix
987
+
988
+ ## 2.0.0-alpha.48
989
+
990
+ ### Minor Changes
991
+
992
+ - AI features
993
+
994
+ ## 1.0.0
995
+
996
+ ### Minor Changes
997
+
998
+ - Align minor version, from now all packages in monorepo will have same version
999
+ - 5c2ff97: Add schema validation bypass options to RouteProps
1000
+
1001
+ Handlers can now control schema validation behavior via the new `validation` property in `RouteProps`:
1002
+
1003
+ - `ValidationMode.Validate` (default): Validate both request and response
1004
+ - `ValidationMode.SkipValidation`: Skip both request and response validation
1005
+ - `ValidationMode.ValidateRequest`: Validate only request, skip response validation
1006
+ - `ValidationMode.ValidateResponse`: Validate only response, skip request validation
1007
+
1008
+ This is useful for handlers that need custom validation logic or want to bypass validation for performance reasons. The feature is opt-in and defaults to existing behavior.
1009
+
1010
+ **Security Considerations:**
1011
+
1012
+ ⚠️ Use validation bypass options carefully:
1013
+
1014
+ - `SkipValidation` and `ValidateRequest: false` allow unvalidated data to reach handlers, which can introduce security risks
1015
+ - Only skip validation when you have implemented custom validation logic or the endpoint is internal/trusted
1016
+ - Suitable use cases include: webhook handlers with custom signature verification, performance-critical internal endpoints, or handlers using alternative validation methods
1017
+ - When skipping response validation, ensure your code returns consistent data shapes to avoid breaking API contracts
1018
+
1019
+ Example usage:
1020
+
1021
+ ```typescript
1022
+ // Skip validation for webhook with custom verification
1023
+ export const Route: RouteProps = {
1024
+ path: "/webhook",
1025
+ validation: ValidationMode.SkipValidation,
1026
+ };
1027
+
1028
+ // Validate request but allow flexible response during development
1029
+ export const Route: RouteProps = {
1030
+ path: "/api/debug",
1031
+ validation: ValidationMode.ValidateRequest,
1032
+ };
1033
+ ```
1034
+
1035
+ ### Patch Changes
1036
+
1037
+ - ee21c29: Normalize query parameters to predictable string types
1038
+
1039
+ Query parameters are now automatically normalized to `string | string[]` types before reaching handlers:
1040
+
1041
+ - Single values: converted to strings (e.g., `?page=1` → `{ page: "1" }`)
1042
+ - Repeated parameters: converted to string arrays (e.g., `?tag=a&tag=b` → `{ tag: ["a", "b"] }`)
1043
+ - All types (numbers, booleans, etc.) from Express parser are converted to strings
1044
+
1045
+ **Breaking Change (Minor):**
1046
+
1047
+ - `Query` type changed from `{ [x: string]: string | string[] | undefined }` to `Record<string, string | string[]>`
1048
+ - `Params` type changed from `Request["params"]` to explicit `Record<string, string>`
1049
+ - Removed `undefined` from query/param types since normalization ensures values are never undefined
1050
+ - Updated OAuth and OIDC plugin query type definitions to satisfy new Query constraint
1051
+
1052
+ This ensures predictable query and path parameter handling regardless of Express parser configuration. Handlers can reliably parse string values as needed using `Number()`, `parseInt()`, boolean comparisons, etc.
1053
+
3
1054
  ## 0.14.3
4
1055
 
5
1056
  ### Patch Changes