@flink-app/flink 1.0.0 → 2.0.0-alpha.101

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