akanjs 3.0.0-alpha.2 → 3.0.0-alpha.21

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 (388) hide show
  1. package/README.ko.md +1 -1
  2. package/README.md +1 -1
  3. package/base/symbols.ts +4 -0
  4. package/client/clientRuntime.ts +8 -0
  5. package/client/cn.ts +7 -0
  6. package/client/csrTypes.ts +2 -0
  7. package/client/frameDebug.ts +3 -2
  8. package/common/Logger.ts +4 -0
  9. package/common/deepObjectify.ts +21 -7
  10. package/common/index.ts +14 -0
  11. package/common/mcpExposure.ts +99 -0
  12. package/common/pathSet.ts +17 -5
  13. package/common/routeConvention.ts +30 -0
  14. package/constant/crystalize.ts +3 -1
  15. package/constant/fieldInfo.ts +6 -0
  16. package/constant/getDefault.ts +37 -9
  17. package/constant/immerify.ts +1 -1
  18. package/constant/index.ts +2 -0
  19. package/constant/labelOf.ts +17 -0
  20. package/constant/mask.ts +60 -0
  21. package/constant/purify.ts +17 -11
  22. package/constant/types.ts +14 -12
  23. package/dictionary/DictionaryLookup.ts +30 -0
  24. package/dictionary/agent.dictionary.ts +31 -0
  25. package/dictionary/agentTurn.dictionary.ts +29 -0
  26. package/dictionary/base.dictionary.ts +8 -0
  27. package/dictionary/dictInfo.ts +8 -0
  28. package/dictionary/dictionary.ts +9 -3
  29. package/dictionary/index.ts +1 -0
  30. package/document/database.ts +21 -0
  31. package/document/filterMeta.ts +7 -0
  32. package/document/index.ts +1 -0
  33. package/document/into.ts +7 -1
  34. package/document/noDocumentError.ts +12 -0
  35. package/fetch/agentTurn.ts +19 -0
  36. package/fetch/client/fetchClient.ts +71 -13
  37. package/fetch/client/wsClient.ts +17 -2
  38. package/fetch/fetchType/endpointFetch.type.ts +10 -4
  39. package/fetch/index.ts +1 -0
  40. package/local/apps/serverLifecycle/serverLifecycle-local.db +0 -0
  41. package/local/apps/serverLifecycle/serverLifecycle-local.db-shm +0 -0
  42. package/local/apps/serverLifecycle/serverLifecycle-local.db-wal +0 -0
  43. package/local/apps/serverLifecycle/serverLifecycle-local_solid.db +0 -0
  44. package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-shm +0 -0
  45. package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-wal +0 -0
  46. package/package.json +11 -9
  47. package/server/akanApp.ts +30 -34
  48. package/server/akanOption.ts +65 -7
  49. package/server/akanServer.ts +172 -7
  50. package/server/animatedImage.ts +83 -0
  51. package/server/artifact/routeClientCache.ts +14 -0
  52. package/server/assetEncoding.ts +47 -0
  53. package/server/devtools/signalSerializer.ts +2 -2
  54. package/server/devtools/types.ts +2 -2
  55. package/server/di/diLifecycle.ts +31 -3
  56. package/server/di/predefinedAdaptor.ts +6 -0
  57. package/server/imageOptimizer.ts +33 -46
  58. package/server/index.ts +1 -2
  59. package/server/mcp/McpAuth.ts +177 -0
  60. package/server/mcp/McpDispatcher.ts +245 -0
  61. package/server/mcp/McpEventStream.ts +76 -0
  62. package/server/mcp/McpExecutionContext.ts +105 -0
  63. package/server/mcp/McpRouter.ts +591 -0
  64. package/server/mcp/index.ts +5 -0
  65. package/server/resolver/CascadeRunner.ts +1 -1
  66. package/server/resolver/database.resolver.ts +42 -5
  67. package/server/resolver/service.resolver.ts +29 -0
  68. package/server/resolver/signal.resolver.ts +16 -1
  69. package/server/routeTreeBuilder.ts +2 -44
  70. package/server/rscWorker.tsx +6 -2
  71. package/server/subRouteIndexDocument.tsx +61 -0
  72. package/server/systemPageDocument.tsx +2 -2
  73. package/server/systemPages.tsx +49 -16
  74. package/server/vendor/akanjs-fetch.ts +1 -0
  75. package/server/webRouter.ts +159 -35
  76. package/service/agent.service.ts +14 -0
  77. package/service/base.service.ts +2 -1
  78. package/service/index.ts +1 -0
  79. package/service/predefinedAdaptor/database.adaptor.ts +78 -24
  80. package/service/predefinedAdaptor/deepseekLlm.ts +230 -0
  81. package/service/predefinedAdaptor/index.ts +3 -0
  82. package/service/predefinedAdaptor/insightQuery.ts +183 -0
  83. package/service/predefinedAdaptor/llm.adaptor.ts +76 -0
  84. package/service/predefinedAdaptor/role.adaptor.ts +2 -0
  85. package/service/predefinedAdaptor/schedule.adaptor.ts +12 -5
  86. package/service/serviceModule.ts +17 -0
  87. package/service/types.ts +4 -0
  88. package/signal/agent/AgentCatalogue.ts +165 -0
  89. package/signal/agent/index.ts +1 -0
  90. package/signal/agent.signal.ts +42 -0
  91. package/signal/agentTurn.ts +8 -0
  92. package/signal/agentTurnStream.ts +48 -0
  93. package/signal/base.signal.ts +2 -1
  94. package/signal/endpointInfo.ts +38 -2
  95. package/signal/guard.ts +13 -1
  96. package/signal/guards.ts +52 -1
  97. package/signal/index.ts +6 -0
  98. package/signal/mcp/McpDocument.ts +286 -0
  99. package/signal/mcp/McpProgress.ts +106 -0
  100. package/signal/mcp/McpUriTemplate.ts +85 -0
  101. package/signal/mcp/Msg.ts +368 -0
  102. package/signal/mcp/index.ts +5 -0
  103. package/signal/mcp/mcpProtocol.ts +120 -0
  104. package/signal/middleware.ts +7 -3
  105. package/signal/openapi/openapi.ts +32 -171
  106. package/signal/schema/JsonSchemaBuilder.ts +211 -0
  107. package/signal/schema/index.ts +1 -0
  108. package/signal/signalContext.ts +85 -9
  109. package/signal/slice.ts +9 -9
  110. package/signal/types.ts +1 -1
  111. package/store/action.ts +11 -22
  112. package/store/actionTag.ts +33 -0
  113. package/store/agent/AgentBridge.ts +323 -0
  114. package/store/agent/AgentContext.ts +74 -0
  115. package/store/agent/AgentPrompts.ts +82 -0
  116. package/store/agent/AgentVisibility.ts +68 -0
  117. package/store/agent/ScreenReader.ts +208 -0
  118. package/store/agent/StoreCatalogue.ts +351 -0
  119. package/store/agent/StoreSurfaceSource.ts +122 -0
  120. package/store/agent/index.ts +9 -0
  121. package/store/agent/storeSurface.ts +28 -0
  122. package/store/agent/types.ts +50 -0
  123. package/store/agentic/StToolBuilder.ts +199 -0
  124. package/store/agentic/attachAgentic.ts +22 -0
  125. package/store/agentic/index.ts +5 -0
  126. package/store/agentic/readableValue.ts +17 -0
  127. package/store/agentic/useStExpose.ts +18 -0
  128. package/store/agentic/useStState.ts +35 -0
  129. package/store/baseSt.ts +7 -0
  130. package/store/databaseStateNames.ts +31 -0
  131. package/store/formSetterNames.ts +21 -0
  132. package/store/index.ts +8 -0
  133. package/store/rootStore.ts +3 -1
  134. package/store/sliceRole.ts +36 -0
  135. package/store/state.ts +2 -12
  136. package/store/store.ts +19 -1
  137. package/store/storeInstance.ts +165 -20
  138. package/store/storeRegistry.ts +16 -1
  139. package/store/types.ts +18 -0
  140. package/store/withSelector.ts +7 -8
  141. package/test/registerDom.ts +4 -0
  142. package/types/base/symbols.d.ts +4 -0
  143. package/types/client/cn.d.ts +5 -0
  144. package/types/client/csrTypes.d.ts +2 -0
  145. package/types/common/Logger.d.ts +2 -0
  146. package/types/common/deepObjectify.d.ts +4 -2
  147. package/types/common/index.d.ts +2 -1
  148. package/types/common/mcpExposure.d.ts +60 -0
  149. package/types/common/routeConvention.d.ts +8 -0
  150. package/types/constant/fieldInfo.d.ts +1 -0
  151. package/types/constant/getDefault.d.ts +5 -0
  152. package/types/constant/index.d.ts +2 -0
  153. package/types/constant/labelOf.d.ts +6 -0
  154. package/types/constant/mask.d.ts +34 -0
  155. package/types/constant/purify.d.ts +2 -2
  156. package/types/constant/types.d.ts +2 -2
  157. package/types/dictionary/DictionaryLookup.d.ts +14 -0
  158. package/types/dictionary/agent.dictionary.d.ts +1 -0
  159. package/types/dictionary/agentTurn.dictionary.d.ts +1 -0
  160. package/types/dictionary/base.dictionary.d.ts +1 -1
  161. package/types/dictionary/dictInfo.d.ts +6 -0
  162. package/types/dictionary/dictionary.d.ts +11 -9
  163. package/types/dictionary/index.d.ts +1 -0
  164. package/types/document/database.d.ts +20 -0
  165. package/types/document/filterMeta.d.ts +1 -0
  166. package/types/document/index.d.ts +1 -0
  167. package/types/document/into.d.ts +6 -1
  168. package/types/document/noDocumentError.d.ts +12 -0
  169. package/types/fetch/agentTurn.d.ts +593 -0
  170. package/types/fetch/client/fetchClient.d.ts +10 -0
  171. package/types/fetch/fetchType/endpointFetch.type.d.ts +5 -3
  172. package/types/fetch/index.d.ts +1 -0
  173. package/types/server/akanOption.d.ts +35 -7
  174. package/types/server/akanServer.d.ts +44 -1
  175. package/types/server/animatedImage.d.ts +7 -0
  176. package/types/server/artifact/routeClientCache.d.ts +6 -0
  177. package/types/server/assetEncoding.d.ts +7 -0
  178. package/types/server/devtools/types.d.ts +2 -2
  179. package/types/server/di/predefinedAdaptor.d.ts +4 -1
  180. package/types/server/index.d.ts +0 -2
  181. package/types/server/mcp/McpAuth.d.ts +62 -0
  182. package/types/server/mcp/McpDispatcher.d.ts +54 -0
  183. package/types/server/mcp/McpEventStream.d.ts +18 -0
  184. package/types/server/mcp/McpExecutionContext.d.ts +44 -0
  185. package/types/server/mcp/McpRouter.d.ts +60 -0
  186. package/types/server/mcp/index.d.ts +5 -0
  187. package/types/server/mcp.d.ts +1 -0
  188. package/types/server/subRouteIndexDocument.d.ts +8 -0
  189. package/types/server/systemPageDocument.d.ts +1 -0
  190. package/types/server/systemPages.d.ts +5 -0
  191. package/types/server/vendor/akanjs-fetch.d.ts +1 -0
  192. package/types/service/agent.service.d.ts +12 -0
  193. package/types/service/base.service.d.ts +4 -0
  194. package/types/service/index.d.ts +1 -0
  195. package/types/service/predefinedAdaptor/database.adaptor.d.ts +24 -2
  196. package/types/service/predefinedAdaptor/deepseekLlm.d.ts +64 -0
  197. package/types/service/predefinedAdaptor/index.d.ts +3 -0
  198. package/types/service/predefinedAdaptor/insightQuery.d.ts +50 -0
  199. package/types/service/predefinedAdaptor/llm.adaptor.d.ts +68 -0
  200. package/types/service/predefinedAdaptor/role.adaptor.d.ts +2 -0
  201. package/types/service/predefinedAdaptor/schedule.adaptor.d.ts +10 -6
  202. package/types/service/types.d.ts +4 -1
  203. package/types/signal/agent/AgentCatalogue.d.ts +100 -0
  204. package/types/signal/agent/index.d.ts +1 -0
  205. package/types/signal/agent.d.ts +1 -0
  206. package/types/signal/agent.signal.d.ts +29 -0
  207. package/types/signal/agentTurn.d.ts +9 -0
  208. package/types/signal/agentTurnStream.d.ts +16 -0
  209. package/types/signal/base.signal.d.ts +1 -1
  210. package/types/signal/endpointInfo.d.ts +21 -3
  211. package/types/signal/guard.d.ts +11 -0
  212. package/types/signal/guards.d.ts +22 -1
  213. package/types/signal/index.d.ts +6 -0
  214. package/types/signal/mcp/McpDocument.d.ts +65 -0
  215. package/types/signal/mcp/McpProgress.d.ts +40 -0
  216. package/types/signal/mcp/McpUriTemplate.d.ts +26 -0
  217. package/types/signal/mcp/Msg.d.ts +143 -0
  218. package/types/signal/mcp/index.d.ts +5 -0
  219. package/types/signal/mcp/mcpProtocol.d.ts +107 -0
  220. package/types/signal/mcp.d.ts +1 -0
  221. package/types/signal/openapi/openapi.d.ts +3 -3
  222. package/types/signal/schema/JsonSchemaBuilder.d.ts +47 -0
  223. package/types/signal/schema/index.d.ts +1 -0
  224. package/types/signal/schema.d.ts +1 -0
  225. package/types/signal/signalContext.d.ts +16 -1
  226. package/types/signal/slice.d.ts +8 -8
  227. package/types/signal/types.d.ts +1 -1
  228. package/types/store/actionTag.d.ts +21 -0
  229. package/types/store/agent/AgentBridge.d.ts +77 -0
  230. package/types/store/agent/AgentContext.d.ts +16 -0
  231. package/types/store/agent/AgentPrompts.d.ts +31 -0
  232. package/types/store/agent/AgentVisibility.d.ts +21 -0
  233. package/types/store/agent/ScreenReader.d.ts +11 -0
  234. package/types/store/agent/StoreCatalogue.d.ts +26 -0
  235. package/types/store/agent/StoreSurfaceSource.d.ts +18 -0
  236. package/types/store/agent/index.d.ts +9 -0
  237. package/types/store/agent/storeSurface.d.ts +14 -0
  238. package/types/store/agent/types.d.ts +49 -0
  239. package/types/store/agent.d.ts +1 -0
  240. package/types/store/agentic/StToolBuilder.d.ts +41 -0
  241. package/types/store/agentic/attachAgentic.d.ts +14 -0
  242. package/types/store/agentic/index.d.ts +5 -0
  243. package/types/store/agentic/readableValue.d.ts +3 -0
  244. package/types/store/agentic/useStExpose.d.ts +8 -0
  245. package/types/store/agentic/useStState.d.ts +12 -0
  246. package/types/store/agentic.d.ts +1 -0
  247. package/types/store/baseSt.d.ts +29 -22
  248. package/types/store/databaseStateNames.d.ts +25 -0
  249. package/types/store/formSetterNames.d.ts +16 -0
  250. package/types/store/index.d.ts +7 -0
  251. package/types/store/rootStore.d.ts +5 -1
  252. package/types/store/sliceRole.d.ts +25 -0
  253. package/types/store/store.d.ts +7 -2
  254. package/types/store/storeInstance.d.ts +33 -1
  255. package/types/store/storeRegistry.d.ts +5 -0
  256. package/types/store/types.d.ts +15 -0
  257. package/types/store/withSelector.d.ts +7 -8
  258. package/types/test/registerDom.d.ts +1 -0
  259. package/types/ui/Agent/Approval.d.ts +7 -0
  260. package/types/ui/Agent/Bubble.d.ts +13 -0
  261. package/types/ui/Agent/Chat.d.ts +24 -0
  262. package/types/ui/Agent/Context.d.ts +9 -0
  263. package/types/ui/Agent/Dock.d.ts +16 -0
  264. package/types/ui/Agent/Guide.d.ts +9 -0
  265. package/types/ui/Agent/Section.d.ts +10 -0
  266. package/types/ui/Agent/StateKey.d.ts +16 -0
  267. package/types/ui/Agent/Tool.d.ts +15 -0
  268. package/types/ui/Agent/Transcript.d.ts +13 -0
  269. package/types/ui/Agent/Zone.d.ts +23 -0
  270. package/types/ui/Agent/fetchRunner.d.ts +12 -0
  271. package/types/ui/Agent/index.d.ts +17 -0
  272. package/types/ui/Agent/index_.d.ts +1 -0
  273. package/types/ui/Agent/sessionHistory.d.ts +12 -0
  274. package/types/ui/Agent.d.ts +1 -0
  275. package/types/ui/Badge.d.ts +1 -1
  276. package/types/ui/Button.d.ts +1 -1
  277. package/types/ui/CsrImage.d.ts +1 -1
  278. package/types/ui/Dropdown.d.ts +2 -0
  279. package/types/ui/Image.d.ts +3 -3
  280. package/types/ui/Layout/BottomInset.d.ts +2 -1
  281. package/types/ui/Layout/index.d.ts +1 -1
  282. package/types/ui/Signal/style.d.ts +4 -1
  283. package/types/ui/UiOverride/context.d.ts +14 -2
  284. package/types/ui/agentAttrs.d.ts +14 -0
  285. package/types/ui/index.d.ts +4 -1
  286. package/types/ui/overlayLayer.d.ts +24 -0
  287. package/types/ui/recipe/badgeRecipe.d.ts +7 -3
  288. package/types/ui/recipe/buttonRecipe.d.ts +7 -3
  289. package/types/ui/recipe/inputRecipe.d.ts +5 -1
  290. package/types/vendor/use-agentic/AgentProvider.d.ts +18 -0
  291. package/types/vendor/use-agentic/AgentScope.d.ts +9 -0
  292. package/types/vendor/use-agentic/AgentSession.d.ts +50 -0
  293. package/types/vendor/use-agentic/Agentic.d.ts +21 -0
  294. package/types/vendor/use-agentic/AgenticSurface.d.ts +44 -0
  295. package/types/vendor/use-agentic/httpRunner.d.ts +15 -0
  296. package/types/vendor/use-agentic/index.d.ts +13 -0
  297. package/types/vendor/use-agentic/surfaceContext.d.ts +5 -0
  298. package/types/vendor/use-agentic/types.d.ts +133 -0
  299. package/types/vendor/use-agentic/useAgent.d.ts +4 -0
  300. package/types/vendor/use-agentic/useAgentGuide.d.ts +6 -0
  301. package/types/vendor/use-agentic/useAgentResource.d.ts +7 -0
  302. package/types/vendor/use-agentic/useAgentState.d.ts +13 -0
  303. package/types/vendor/use-agentic/useAgentTool.d.ts +16 -0
  304. package/types/vendor/use-agentic.d.ts +1 -0
  305. package/types/webkit/index.d.ts +3 -0
  306. package/types/webkit/lazy.d.ts +12 -0
  307. package/types/webkit/useCsrValues.d.ts +3 -3
  308. package/types/webkit/useEscapeKey.d.ts +5 -0
  309. package/types/webkit/useFrameRuntime.d.ts +6 -1
  310. package/types/webkit/useScreenScope.d.ts +18 -0
  311. package/ui/Agent/Approval.tsx +29 -0
  312. package/ui/Agent/Bubble.tsx +74 -0
  313. package/ui/Agent/Chat.tsx +225 -0
  314. package/ui/Agent/Context.tsx +38 -0
  315. package/ui/Agent/Dock.tsx +72 -0
  316. package/ui/Agent/Guide.tsx +16 -0
  317. package/ui/Agent/Section.tsx +24 -0
  318. package/ui/Agent/StateKey.tsx +44 -0
  319. package/ui/Agent/Tool.tsx +66 -0
  320. package/ui/Agent/Transcript.tsx +33 -0
  321. package/ui/Agent/Zone.tsx +48 -0
  322. package/ui/Agent/fetchRunner.ts +30 -0
  323. package/ui/Agent/index.ts +12 -0
  324. package/ui/Agent/index_.tsx +4 -0
  325. package/ui/Agent/sessionHistory.ts +33 -0
  326. package/ui/Badge.tsx +3 -3
  327. package/ui/BottomSheet.tsx +5 -0
  328. package/ui/Button.tsx +6 -2
  329. package/ui/Constant/Doc.tsx +1 -1
  330. package/ui/CsrImage.tsx +1 -1
  331. package/ui/Data/ListContainer.tsx +1 -1
  332. package/ui/DatePicker.tsx +5 -4
  333. package/ui/Dialog/Modal.tsx +12 -15
  334. package/ui/DraggableList.tsx +3 -1
  335. package/ui/Dropdown.tsx +33 -11
  336. package/ui/Field.tsx +30 -16
  337. package/ui/Image.tsx +3 -3
  338. package/ui/Input.tsx +14 -5
  339. package/ui/Layout/BottomInset.tsx +6 -1
  340. package/ui/Load/Units.tsx +11 -2
  341. package/ui/Load/View.tsx +7 -2
  342. package/ui/Loading/ProgressBar.tsx +8 -1
  343. package/ui/Menu.tsx +7 -8
  344. package/ui/Model/EditModal.tsx +37 -2
  345. package/ui/Model/SureToRemove.tsx +2 -1
  346. package/ui/Model/index_.tsx +42 -15
  347. package/ui/ObjectId.tsx +3 -4
  348. package/ui/Pagination.tsx +3 -4
  349. package/ui/Popconfirm.tsx +8 -7
  350. package/ui/Select.tsx +6 -4
  351. package/ui/Signal/RestApi.tsx +43 -16
  352. package/ui/Signal/WebSocket.tsx +1 -1
  353. package/ui/Signal/style.ts +6 -1
  354. package/ui/Switch.tsx +2 -0
  355. package/ui/System/CSR.tsx +6 -2
  356. package/ui/System/ThemeToggle.tsx +55 -33
  357. package/ui/ToggleSelect.tsx +4 -3
  358. package/ui/Tooltip.tsx +2 -1
  359. package/ui/UiOverride/context.ts +14 -2
  360. package/ui/agentAttrs.ts +19 -0
  361. package/ui/index.ts +10 -1
  362. package/ui/overlayLayer.ts +39 -0
  363. package/ui/recipe/badgeRecipe.ts +22 -3
  364. package/ui/recipe/buttonRecipe.ts +51 -2
  365. package/ui/recipe/factory.ts +2 -2
  366. package/ui/recipe/inputRecipe.ts +18 -4
  367. package/vendor/use-agentic/AgentProvider.tsx +39 -0
  368. package/vendor/use-agentic/AgentScope.tsx +20 -0
  369. package/vendor/use-agentic/AgentSession.ts +292 -0
  370. package/vendor/use-agentic/Agentic.tsx +44 -0
  371. package/vendor/use-agentic/AgenticSurface.ts +294 -0
  372. package/vendor/use-agentic/WIRE.md +57 -0
  373. package/vendor/use-agentic/httpRunner.ts +115 -0
  374. package/vendor/use-agentic/index.ts +14 -0
  375. package/vendor/use-agentic/surfaceContext.ts +9 -0
  376. package/vendor/use-agentic/types.ts +144 -0
  377. package/vendor/use-agentic/useAgent.ts +17 -0
  378. package/vendor/use-agentic/useAgentGuide.ts +16 -0
  379. package/vendor/use-agentic/useAgentResource.ts +30 -0
  380. package/vendor/use-agentic/useAgentState.ts +61 -0
  381. package/vendor/use-agentic/useAgentTool.ts +55 -0
  382. package/webkit/bootCsr.tsx +2 -33
  383. package/webkit/index.ts +3 -0
  384. package/webkit/lazy.tsx +27 -3
  385. package/webkit/useCsrValues.ts +121 -4
  386. package/webkit/useEscapeKey.tsx +42 -0
  387. package/webkit/useFrameRuntime.ts +65 -32
  388. package/webkit/useScreenScope.tsx +49 -0
@@ -204,7 +204,7 @@ export class SignalSerializer {
204
204
  return Object.entries(nodes).flatMap(([key, node]) => {
205
205
  const info = meta[key];
206
206
  if (!info) return [];
207
- const transport = node.type === "query" || node.type === "mutation" ? "http" : "ws";
207
+ const transport = node.type === "pubsub" || node.type === "message" ? "ws" : "http";
208
208
  return [
209
209
  {
210
210
  signal,
@@ -212,7 +212,7 @@ export class SignalSerializer {
212
212
  source: typeof source === "function" ? source(key) : source,
213
213
  type: node.type,
214
214
  transport,
215
- method: node.type === "query" ? "GET" : node.type === "mutation" ? "POST" : null,
215
+ method: node.type === "mutation" ? "POST" : transport === "http" ? "GET" : null,
216
216
  path:
217
217
  transport === "ws"
218
218
  ? SignalSerializer.#joinPath(prefix, websocketPrefix)
@@ -134,7 +134,7 @@ export interface ConstantData {
134
134
  export type { ArgType, SerializedArg, SerializedReturns };
135
135
 
136
136
  export interface EndpointNode {
137
- type: "query" | "mutation" | "pubsub" | "message";
137
+ type: "query" | "mutation" | "pubsub" | "message" | "prompt";
138
138
  args: SerializedArg[];
139
139
  returns: SerializedReturns;
140
140
  path?: string;
@@ -192,7 +192,7 @@ export interface RouteRow {
192
192
  signal: string;
193
193
  key: string;
194
194
  source: "declared" | "crud" | "slice";
195
- type: "query" | "mutation" | "message" | "pubsub";
195
+ type: "query" | "mutation" | "message" | "pubsub" | "prompt";
196
196
  transport: "http" | "ws";
197
197
  method: "GET" | "POST" | null;
198
198
  /** Fully prefixed, `:param` placeholders intact — e.g. `/api/user/:userId`. */
@@ -12,6 +12,8 @@ import {
12
12
  srv,
13
13
  type WebsocketAdaptor,
14
14
  } from "akanjs/service";
15
+ import { agent as agentSignal } from "../../signal/agent.signal";
16
+ import { agentTurnConstant, agentTurnDocument } from "../../signal/agentTurn";
15
17
  import { Base, BaseEndpoint, BaseInternal } from "../../signal/base.signal";
16
18
  import type { Endpoint } from "../../signal/endpoint";
17
19
  import type { Internal } from "../../signal/internal";
@@ -82,14 +84,24 @@ export class DiLifecycle {
82
84
  };
83
85
  }
84
86
 
87
+ static #envOn(...names: string[]) {
88
+ return !names.some((name) => process.env[name] === "false" || process.env[name] === "0");
89
+ }
90
+
85
91
  constructor(env: BaseEnv, serverMode: "federation" | "batch" | "all", ...libs: AkanLib[]) {
86
92
  this.#env = env;
87
- this.#predefinedAdaptor = getPredefinedAdaptor(env.databaseMode ?? "single");
93
+
94
+ this.#predefinedAdaptor = { ...getPredefinedAdaptor(env.databaseMode ?? "single") };
88
95
  this.#libs = libs;
89
96
  this.#service.set("base", {
90
97
  service: srv.base,
91
98
  signal: SignalRegistry.registerService("base" as const, BaseInternal, BaseEndpoint, Base),
92
99
  });
100
+
101
+ const frameworkAgent: ServiceModule | null = DiLifecycle.#envOn("AKAN_AGENT", "AKAN_PUBLIC_AGENT")
102
+ ? { service: srv.agent, signal: agentSignal }
103
+ : null;
104
+ if (frameworkAgent) this.#service.set("agent", frameworkAgent);
93
105
  this.#middleware.set(Logging.refName, Logging);
94
106
  const defaultOption = createDefaultAkanOption();
95
107
  defaultOption.getMiddlewares().forEach((middleware) => {
@@ -102,6 +114,14 @@ export class DiLifecycle {
102
114
  lib.option.getMiddlewares().forEach((middleware) => {
103
115
  this.#middleware.set(middleware.refName, middleware);
104
116
  });
117
+ lib.option.getAdaptorOverrides().forEach(({ role, adaptor }) => {
118
+ const roleKey = Object.entries(this.#predefinedAdaptorRole).find(([, roleCls]) => roleCls === role)?.[0];
119
+ if (!roleKey) {
120
+ this.logger.warn(`applyAdaptor got an unknown role "${role.refName}" — override ignored`);
121
+ return;
122
+ }
123
+ (this.#predefinedAdaptor as Record<string, AdaptorCls>)[roleKey] = adaptor;
124
+ });
105
125
  this.webProxies.push(...lib.option.getWebProxies());
106
126
  lib.database.forEach((mod) => {
107
127
  databaseCandidates.set(mod.constant.refName, { refName: mod.constant.refName, module: mod });
@@ -122,6 +142,10 @@ export class DiLifecycle {
122
142
  if (disabledModules.has(refName)) return;
123
143
  this.#service.set(refName, module as ServiceModule);
124
144
  });
145
+ if (frameworkAgent && this.#service.get("agent") !== frameworkAgent)
146
+ this.logger.info("agent relay is provided by a lib module — the framework's is skipped");
147
+ if (!this.#scalar.has("agentTurn"))
148
+ this.#scalar.set("agentTurn", { constant: agentTurnConstant, database: agentTurnDocument });
125
149
  this.#database.forEach((mod) => {
126
150
  const { adaptor, schema } = DatabaseResolver.resolveDatabase(mod.constant, mod.database);
127
151
  this.#adaptor.set(adaptor.refName, adaptor);
@@ -365,7 +389,11 @@ export class DiLifecycle {
365
389
  }
366
390
 
367
391
  async #initializeUses() {
368
- const uses = Object.assign({}, ...this.#libs.map((lib) => lib.option.getUses(this.#env)));
392
+
393
+ const uses = Object.assign(
394
+ { llmOption: Object.assign({}, ...this.#libs.map((lib) => lib.option.getLlm(this.#env))) },
395
+ ...this.#libs.map((lib) => lib.option.getUses(this.#env)),
396
+ );
369
397
  const entries = Object.entries(uses);
370
398
  await runStage(
371
399
  "uses",
@@ -473,7 +501,7 @@ export class DiLifecycle {
473
501
  );
474
502
  }
475
503
 
476
- this.#cascade.seal((refName) => this.getService(refName));
504
+ this.#cascade.seal((refName: string) => this.getService(refName));
477
505
  }
478
506
 
479
507
  async #initializeInternal() {
@@ -10,8 +10,11 @@ import {
10
10
  ConsoleLogger,
11
11
  type DatabaseAdaptor,
12
12
  DatabaseAdaptorRole,
13
+ DeepseekLlm,
13
14
  JsonCompressor,
14
15
  LibsqlDatabase,
16
+ type LlmAdaptor,
17
+ LlmAdaptorRole,
15
18
  type LoggingAdaptor,
16
19
  LoggingAdaptorRole,
17
20
  PostgresDatabase,
@@ -41,6 +44,7 @@ export interface PredefinedAdaptor {
41
44
  logging: AdaptorCls<LoggingAdaptor>;
42
45
  websocket: AdaptorCls<WebsocketAdaptor>;
43
46
  compress: AdaptorCls<CompressAdaptor>;
47
+ llm: AdaptorCls<LlmAdaptor>;
44
48
  }
45
49
 
46
50
  export const predefinedAdaptorRole = {
@@ -52,6 +56,7 @@ export const predefinedAdaptorRole = {
52
56
  logging: LoggingAdaptorRole,
53
57
  websocket: WebsocketAdaptorRole,
54
58
  compress: CompressAdaptorRole,
59
+ llm: LlmAdaptorRole,
55
60
  } satisfies PredefinedAdaptor;
56
61
 
57
62
  export const predefinedAdaptor = {
@@ -63,6 +68,7 @@ export const predefinedAdaptor = {
63
68
  logging: ConsoleLogger,
64
69
  websocket: SolidPubSub,
65
70
  compress: JsonCompressor,
71
+ llm: DeepseekLlm,
66
72
  };
67
73
 
68
74
  export const getPredefinedAdaptor = (mode: DatabaseMode = "single"): PredefinedAdaptor => {
@@ -1,6 +1,8 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import fs from "node:fs/promises";
3
3
  import path from "node:path";
4
+ import { Logger } from "akanjs/common";
5
+ import { isAnimatedImage } from "./animatedImage";
4
6
  import { ImageOptimizerError } from "./imageOptimizerError";
5
7
  import {
6
8
  type AkanImageConfig,
@@ -10,18 +12,6 @@ import {
10
12
  mergeAkanImageConfig,
11
13
  } from "./types";
12
14
 
13
- type SharpFactory = typeof import("sharp");
14
-
15
- let sharpLoad: Promise<SharpFactory> | null = null;
16
-
17
- function loadSharp(): Promise<SharpFactory> {
18
- sharpLoad ??= import("sharp").then((mod) => {
19
- const loaded = mod as unknown as { default?: SharpFactory } & SharpFactory;
20
- return loaded.default ?? loaded;
21
- });
22
- return sharpLoad;
23
- }
24
-
25
15
  export interface ImageOptimizerOptions {
26
16
  publicDir: string;
27
17
  cacheDir: string;
@@ -59,18 +49,37 @@ export class ImageOptimizer {
59
49
  static readonly #webp = "image/webp";
60
50
  static readonly #gif = "image/gif";
61
51
  static readonly #avif = "image/avif";
52
+ static readonly #heic = "image/heic";
62
53
  static readonly #bypassTypes = new Set(["image/x-icon", "image/x-icns", "image/bmp", "image/jxl", "image/heic"]);
63
54
 
64
55
  #publicDir: string;
65
56
  #cacheDir: string;
66
57
  #prodMode: boolean;
67
58
  #config: AkanImageConfig;
59
+ #logger = new Logger("ImageOptimizer");
68
60
 
69
61
  constructor({ publicDir, cacheDir, prodMode, config }: ImageOptimizerOptions) {
70
62
  this.#publicDir = publicDir;
71
63
  this.#cacheDir = cacheDir;
72
64
  this.#prodMode = prodMode;
73
- this.#config = mergeAkanImageConfig(config);
65
+ const merged = mergeAkanImageConfig(config);
66
+ const formats = merged.formats.filter((format) => ImageOptimizer.#isCodecAvailable(format));
67
+ if (formats.length !== merged.formats.length) {
68
+ const dropped = merged.formats.filter((format) => !formats.includes(format));
69
+ this.#logger.warn(`${dropped.join(", ")} needs an OS codec this platform does not have; serving webp instead`);
70
+ }
71
+ this.#config = { ...merged, formats: formats.length ? formats : ["image/webp"] };
72
+ }
73
+
74
+ /**
75
+ * AVIF, HEIC and TIFF ride the OS codec, which only the `system` backend has — macOS and Windows.
76
+ * A Linux container runs the `bun` backend, where both encode and decode raise
77
+ * `ERR_IMAGE_FORMAT_UNSUPPORTED`, so those types are decided up front rather than thrown at.
78
+ */
79
+ static #isCodecAvailable(contentType: string): boolean {
80
+ if (contentType !== ImageOptimizer.#avif && contentType !== ImageOptimizer.#heic && contentType !== "image/tiff")
81
+ return true;
82
+ return Bun.Image.backend === "system";
74
83
  }
75
84
 
76
85
  async handle(req: Request): Promise<Response> {
@@ -217,7 +226,8 @@ export class ImageOptimizer {
217
226
  const shouldBypass =
218
227
  inputType === ImageOptimizer.#svg ||
219
228
  ImageOptimizer.#bypassTypes.has(inputType) ||
220
- (await ImageOptimizer.#isAnimated(source.buffer, inputType));
229
+ !ImageOptimizer.#isCodecAvailable(inputType) ||
230
+ isAnimatedImage(source.buffer, inputType);
221
231
  const outputType =
222
232
  shouldBypass || !params.outputType || inputType === ImageOptimizer.#webp || inputType === ImageOptimizer.#avif
223
233
  ? inputType
@@ -240,7 +250,7 @@ export class ImageOptimizer {
240
250
  let cacheable = true;
241
251
  if (!shouldBypass) {
242
252
  try {
243
- buffer = await ImageOptimizer.#optimizeWithSharp(source.buffer, {
253
+ buffer = await ImageOptimizer.#optimize(source.buffer, {
244
254
  width: params.width,
245
255
  quality: params.quality,
246
256
  contentType: outputType,
@@ -281,24 +291,17 @@ export class ImageOptimizer {
281
291
  return new Response(ImageOptimizer.#toArrayBuffer(image.buffer), { headers });
282
292
  }
283
293
 
284
- static async #optimizeWithSharp(
294
+ static async #optimize(
285
295
  buffer: Buffer,
286
296
  options: { width: number; quality: number; contentType: string },
287
297
  ): Promise<Buffer> {
288
- const sharp = await loadSharp();
289
- if (sharp.concurrency() > 1) sharp.concurrency(Math.max(Math.floor(sharp.concurrency() / 2), 1));
290
- const transformer = sharp(buffer, {
291
- limitInputPixels: 268_402_689,
292
- sequentialRead: true,
293
- }).resize(options.width, undefined, { withoutEnlargement: true });
294
-
295
- if (options.contentType === ImageOptimizer.#avif)
296
- return await transformer.avif({ quality: options.quality }).toBuffer();
297
- if (options.contentType === ImageOptimizer.#webp)
298
- return await transformer.webp({ quality: options.quality }).toBuffer();
299
- if (options.contentType === ImageOptimizer.#png)
300
- return await transformer.png({ quality: options.quality }).toBuffer();
301
- return await transformer.jpeg({ quality: options.quality }).toBuffer();
298
+ const image = new Bun.Image(buffer).resize(options.width, undefined, { withoutEnlargement: true });
299
+
300
+ if (options.contentType === ImageOptimizer.#avif) return await image.avif({ quality: options.quality }).toBuffer();
301
+ if (options.contentType === ImageOptimizer.#webp) return await image.webp({ quality: options.quality }).toBuffer();
302
+
303
+ if (options.contentType === ImageOptimizer.#png) return await image.png().toBuffer();
304
+ return await image.jpeg({ quality: options.quality }).toBuffer();
302
305
  }
303
306
 
304
307
  static #getPreferredOutputType(accept: string, formats: AkanImageFormat[]): AkanImageFormat | "" {
@@ -375,22 +378,6 @@ export class ImageOptimizer {
375
378
  return Buffer.concat(chunks);
376
379
  }
377
380
 
378
- static async #isAnimated(buffer: Buffer, contentType: string): Promise<boolean> {
379
- if (
380
- contentType !== ImageOptimizer.#gif &&
381
- contentType !== ImageOptimizer.#webp &&
382
- contentType !== ImageOptimizer.#png
383
- )
384
- return false;
385
- try {
386
- const sharp = await loadSharp();
387
- const metadata = await sharp(buffer, { animated: true }).metadata();
388
- return Boolean(metadata.pages && metadata.pages > 1);
389
- } catch {
390
- return false;
391
- }
392
- }
393
-
394
381
  static #detectContentType(buffer: Buffer): string | null {
395
382
  if (buffer.length < 12) return null;
396
383
  if (buffer[0] === 0xff && buffer[1] === 0xd8 && buffer[2] === 0xff) return ImageOptimizer.#jpeg;
package/server/index.ts CHANGED
@@ -9,8 +9,7 @@ export * from "./devtools";
9
9
  export type { ChangeBatch, ChangeKind } from "./hmr/changeBatch";
10
10
  export * from "./processMetricsCollector";
11
11
  export * from "./proxy";
12
- export * from "./routeElementComposer";
13
- export * from "./routeTreeBuilder";
12
+
14
13
  export * from "./sitemap";
15
14
  export type { SsrManifest, SsrManifestEntry } from "./ssrTypes";
16
15
  export * from "./types";
@@ -0,0 +1,177 @@
1
+ import type { HttpRoutes } from "../types";
2
+
3
+ export interface McpAuthOption {
4
+ /** Where a client may obtain a token, published in the metadata document for it to discover. */
5
+ authorizationServers?: string[];
6
+ /** Scopes every call must carry. Declaring any turns `insufficient_scope` enforcement on. */
7
+ scopes?: string[];
8
+ /** Overrides the resource identifier when the public URL differs from what the request reports. */
9
+ resource?: string;
10
+ }
11
+
12
+ export interface McpAuthProps extends McpAuthOption {
13
+ /** Path the MCP endpoint is mounted at. Its absolute URL is this server's OAuth resource identifier. */
14
+ path: string;
15
+ }
16
+
17
+ interface McpAuthFailure {
18
+ status: 401 | 403;
19
+ error: "invalid_token" | "insufficient_scope";
20
+ description: string;
21
+ }
22
+
23
+ /**
24
+ * The OAuth 2.1 protected-resource half of the MCP authorization spec: the RFC 9728 metadata document, the
25
+ * `WWW-Authenticate` challenge that points at it, and the token checks that can be made without an issuer.
26
+ *
27
+ * The authorization server itself is a separate project. What lives here is what a resource server owes a
28
+ * client regardless of who mints the tokens, so wiring one up later needs no change on this side.
29
+ */
30
+ export class McpAuth {
31
+ static readonly wellKnownPath = "/.well-known/oauth-protected-resource";
32
+
33
+ readonly #props: McpAuthProps;
34
+
35
+ constructor(props: McpAuthProps) {
36
+ this.#props = props;
37
+ }
38
+
39
+ /**
40
+ * Both spellings of the metadata path. RFC 9728 inserts the resource's path into the well-known URL, and MCP
41
+ * clients try that form first and the bare one second; serving only one leaves half the clients at a 404.
42
+ */
43
+ createRoutes(): HttpRoutes {
44
+ const handler = { GET: (req: Request) => this.#metadata(req) };
45
+ return {
46
+ [McpAuth.wellKnownPath]: handler,
47
+ [`${McpAuth.wellKnownPath}${this.#props.path}`]: handler,
48
+ };
49
+ }
50
+
51
+ unauthorized(req: Request, failure?: McpAuthFailure) {
52
+ const { status, error, description } = failure ?? {
53
+ status: 401 as const,
54
+ error: "invalid_token" as const,
55
+ description: "Authentication is required to use this MCP server.",
56
+ };
57
+ return Response.json(
58
+ { error, error_description: description },
59
+ { status, headers: { "WWW-Authenticate": this.#challenge(req, error, description) } },
60
+ );
61
+ }
62
+
63
+ /**
64
+ * Refuses a bearer token that is already provably unusable, before the signal pipeline sees it.
65
+ *
66
+ * The claims are read **without verifying the signature**, which is sound only because every branch below can
67
+ * deny and none can grant: a forged token still has to pass the app's own middleware afterwards, so the worst
68
+ * a crafted payload achieves is refusing itself. What this buys is the failure mode it removes — an expired or
69
+ * foreign token otherwise degrades to an anonymous caller, and the agent is told a tool does not exist rather
70
+ * than that it needs to authenticate.
71
+ */
72
+ reject(req: Request): Response | null {
73
+ const claims = McpAuth.#claims(req);
74
+ if (!claims) return null;
75
+ const failure = this.#failureOf(claims, req);
76
+ return failure ? this.unauthorized(req, failure) : null;
77
+ }
78
+
79
+ #failureOf(claims: Record<string, unknown>, req: Request): McpAuthFailure | null {
80
+ const { exp, aud } = claims;
81
+ if (typeof exp === "number" && exp * 1000 <= Date.now())
82
+ return { status: 401, error: "invalid_token", description: "The access token has expired." };
83
+ const audience = (Array.isArray(aud) ? aud : typeof aud === "string" ? [aud] : []).filter(
84
+ (value): value is string => typeof value === "string",
85
+ );
86
+
87
+ if (this.#props.authorizationServers?.length && !audience.length)
88
+ return { status: 401, error: "invalid_token", description: "The access token names no resource." };
89
+ if (audience.length && !audience.includes(this.#resource(req)))
90
+ return { status: 401, error: "invalid_token", description: "The access token was issued for another resource." };
91
+ const missing = this.#missingScopes(claims);
92
+
93
+ if (missing.length)
94
+ return { status: 403, error: "insufficient_scope", description: `Missing required scope: ${missing.join(" ")}.` };
95
+ return null;
96
+ }
97
+
98
+ /**
99
+ * Enforced only when `scopes` is configured, because this server's own tokens carry no scope claim at all —
100
+ * declaring one is how a deployment says its issuer mints them.
101
+ */
102
+ #missingScopes(claims: Record<string, unknown>) {
103
+ const required = this.#props.scopes ?? [];
104
+ if (!required.length) return [];
105
+ const raw = claims.scope ?? claims.scp;
106
+ const granted = new Set(Array.isArray(raw) ? raw.map(String) : String(raw ?? "").split(/\s+/));
107
+ return required.filter((scope) => !granted.has(scope));
108
+ }
109
+
110
+ #metadata(req: Request) {
111
+ const { authorizationServers, scopes } = this.#props;
112
+ return Response.json(
113
+ {
114
+ resource: this.#resource(req),
115
+ ...(authorizationServers?.length ? { authorization_servers: authorizationServers } : {}),
116
+ bearer_methods_supported: ["header"],
117
+ ...(scopes?.length ? { scopes_supported: scopes } : {}),
118
+ },
119
+ {
120
+
121
+ headers: { "access-control-allow-origin": "*", "cache-control": "public, max-age=3600" },
122
+ },
123
+ );
124
+ }
125
+
126
+ #challenge(req: Request, error: string, description: string) {
127
+ const scopes = this.#props.scopes ?? [];
128
+ return [
129
+ "Bearer",
130
+ [
131
+ `resource_metadata="${new URL(McpAuth.wellKnownPath + this.#props.path, McpAuth.origin(req)).href}"`,
132
+ `error="${error}"`,
133
+ `error_description="${description}"`,
134
+ ...(scopes.length ? [`scope="${scopes.join(" ")}"`] : []),
135
+ ].join(", "),
136
+ ].join(" ");
137
+ }
138
+
139
+ #resource(req: Request) {
140
+ return this.#props.resource ?? new URL(this.#props.path, McpAuth.origin(req)).href;
141
+ }
142
+
143
+ /**
144
+ * The public origin, not the one the request arrived on. Behind a proxy `req.url` names the internal host the
145
+ * proxy dialed, and publishing that as the resource identifier is not cosmetic: an authorization server issues
146
+ * `aud` for the URL the *client* used, so every correctly-issued token would then fail the audience check.
147
+ *
148
+ * `McpRouter` compares an `Origin` header against this too — the same proxy that makes `req.url` wrong for the
149
+ * metadata document makes it wrong for a same-origin check, and there the cost is a flat 403.
150
+ *
151
+ * `x-forwarded-host` is a request header, so this is exactly as trustworthy as the edge that overwrites it, and
152
+ * a deployment whose edge merely appends leaves both the same-origin comparison and the audience a token is
153
+ * checked against to the caller. A browser cannot reach it — a custom header is not on a preflight, and the
154
+ * `OPTIONS` is judged on the real host — but a direct caller can. `AKAN_MCP_RESOURCE` pins the identifier for a
155
+ * deployment that cannot make the guarantee.
156
+ */
157
+ static origin(req: Request) {
158
+ const url = new URL(req.url);
159
+ const forwarded = (header: string) => req.headers.get(header)?.split(",")[0]?.trim();
160
+ const host = forwarded("x-forwarded-host") ?? req.headers.get("host") ?? url.host;
161
+ return `${forwarded("x-forwarded-proto") ?? url.protocol.replace(":", "")}://${host}`;
162
+ }
163
+
164
+ static #claims(req: Request): Record<string, unknown> | null {
165
+ const [scheme, token] = (req.headers.get("authorization") ?? "").split(" ");
166
+ if (scheme !== "Bearer" || !token) return null;
167
+ const segments = token.split(".");
168
+
169
+ if (segments.length !== 3) return null;
170
+ try {
171
+ const claims: unknown = JSON.parse(Buffer.from(segments[1], "base64url").toString("utf8"));
172
+ return claims && typeof claims === "object" ? (claims as Record<string, unknown>) : null;
173
+ } catch {
174
+ return null;
175
+ }
176
+ }
177
+ }