akanjs 3.0.0-alpha.4 → 3.0.0-alpha.41

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 (585) hide show
  1. package/README.ko.md +1 -1
  2. package/README.md +1 -1
  3. package/base/baseEnv.ts +1 -1
  4. package/base/symbols.ts +5 -0
  5. package/client/capacitor.ts +34 -0
  6. package/client/clientRuntime.ts +10 -0
  7. package/common/Logger.ts +4 -0
  8. package/common/deepObjectify.ts +21 -7
  9. package/common/index.ts +14 -0
  10. package/common/mcpExposure.ts +99 -0
  11. package/common/pathSet.ts +17 -5
  12. package/common/routeConvention.ts +30 -0
  13. package/constant/cascadePaths.ts +79 -8
  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 +43 -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 +23 -1
  31. package/document/databaseRegistry.ts +2 -2
  32. package/document/filterMeta.ts +7 -0
  33. package/document/index.ts +1 -0
  34. package/document/into.ts +17 -7
  35. package/document/noDocumentError.ts +12 -0
  36. package/fetch/agentTurn.ts +19 -0
  37. package/fetch/client/fetchClient.ts +72 -14
  38. package/fetch/client/httpClient.ts +12 -10
  39. package/fetch/client/wsClient.ts +17 -2
  40. package/fetch/fetchType/endpointFetch.type.ts +10 -4
  41. package/fetch/index.ts +1 -0
  42. package/index.ts +1 -1
  43. package/local/apps/serverLifecycle/serverLifecycle-local.db +0 -0
  44. package/local/apps/serverLifecycle/serverLifecycle-local.db-shm +0 -0
  45. package/local/apps/serverLifecycle/serverLifecycle-local.db-wal +0 -0
  46. package/local/apps/serverLifecycle/serverLifecycle-local_solid.db +0 -0
  47. package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-shm +0 -0
  48. package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-wal +0 -0
  49. package/package.json +11 -13
  50. package/server/SSR_MEMORY_DIAGNOSIS.md +19 -2
  51. package/server/akanApp.ts +38 -34
  52. package/server/akanOption.ts +63 -8
  53. package/server/akanServer.ts +193 -18
  54. package/server/animatedImage.ts +83 -0
  55. package/server/artifact/routeClientCache.ts +14 -0
  56. package/server/assetEncoding.ts +47 -0
  57. package/server/cachePolicy.ts +114 -12
  58. package/server/devtools/signalSerializer.ts +2 -2
  59. package/server/devtools/types.ts +4 -4
  60. package/server/di/diLifecycle.ts +131 -23
  61. package/server/di/predefinedAdaptor.ts +6 -0
  62. package/server/di/utils.ts +40 -0
  63. package/server/imageOptimizer.ts +33 -46
  64. package/server/index.ts +1 -2
  65. package/server/lifecycle/shutdownManager.ts +1 -1
  66. package/server/mcp/McpAuth.ts +177 -0
  67. package/server/mcp/McpDispatcher.ts +245 -0
  68. package/server/mcp/McpEventStream.ts +76 -0
  69. package/server/mcp/McpExecutionContext.ts +105 -0
  70. package/server/mcp/McpRouter.ts +593 -0
  71. package/server/mcp/index.ts +5 -0
  72. package/server/processMetricsCollector.ts +4 -0
  73. package/server/resolver/CascadeRunner.ts +201 -0
  74. package/server/resolver/database.resolver.ts +65 -8
  75. package/server/resolver/index.ts +1 -0
  76. package/server/resolver/service.resolver.ts +38 -25
  77. package/server/resolver/signal.resolver.ts +68 -18
  78. package/server/routeTreeBuilder.ts +2 -44
  79. package/server/rscWorker.tsx +38 -6
  80. package/server/rscWorkerHost.ts +61 -12
  81. package/server/ssrFromRscRenderer.tsx +2 -2
  82. package/server/subRouteIndexDocument.tsx +61 -0
  83. package/server/systemPageDocument.tsx +3 -3
  84. package/server/systemPages.tsx +49 -16
  85. package/server/vendor/akanjs-fetch.ts +1 -0
  86. package/server/webRouter.ts +72 -35
  87. package/service/agent.service.ts +60 -0
  88. package/service/base.service.ts +2 -1
  89. package/service/index.ts +1 -0
  90. package/service/injectInfo.ts +8 -3
  91. package/service/ipcTypes.ts +25 -0
  92. package/service/predefinedAdaptor/database.adaptor.ts +105 -49
  93. package/service/predefinedAdaptor/deepseekLlm.ts +242 -0
  94. package/service/predefinedAdaptor/index.ts +3 -0
  95. package/service/predefinedAdaptor/insightQuery.ts +183 -0
  96. package/service/predefinedAdaptor/llm.adaptor.ts +107 -0
  97. package/service/predefinedAdaptor/queue.adaptor.ts +5 -2
  98. package/service/predefinedAdaptor/role.adaptor.ts +2 -0
  99. package/service/predefinedAdaptor/schedule.adaptor.ts +12 -5
  100. package/service/predefinedAdaptor/solidQueue.adaptor.ts +6 -2
  101. package/service/predefinedAdaptor/solidSqlite.ts +11 -9
  102. package/service/serve.ts +5 -1
  103. package/service/serviceModule.ts +17 -0
  104. package/service/types.ts +6 -0
  105. package/signal/agent/AgentCatalogue.ts +165 -0
  106. package/signal/agent/index.ts +1 -0
  107. package/signal/agent.signal.ts +38 -0
  108. package/signal/agentTurn.ts +8 -0
  109. package/signal/agentTurnStream.ts +48 -0
  110. package/signal/base.signal.ts +2 -1
  111. package/signal/endpointInfo.ts +38 -2
  112. package/signal/guard.ts +28 -1
  113. package/signal/guards.ts +49 -1
  114. package/signal/index.ts +6 -0
  115. package/signal/mcp/McpDocument.ts +286 -0
  116. package/signal/mcp/McpProgress.ts +106 -0
  117. package/signal/mcp/McpUriTemplate.ts +85 -0
  118. package/signal/mcp/Msg.ts +368 -0
  119. package/signal/mcp/index.ts +5 -0
  120. package/signal/mcp/mcpProtocol.ts +120 -0
  121. package/signal/middleware.ts +10 -6
  122. package/signal/openapi/openapi.ts +35 -173
  123. package/signal/schema/JsonSchemaBuilder.ts +211 -0
  124. package/signal/schema/index.ts +1 -0
  125. package/signal/serializer/fetch.serializer.ts +5 -0
  126. package/signal/signalContext.ts +74 -11
  127. package/signal/slice.ts +9 -9
  128. package/signal/types.ts +9 -1
  129. package/store/action.ts +16 -22
  130. package/store/actionTag.ts +33 -0
  131. package/store/agent/AgentBridge.ts +87 -0
  132. package/store/agent/AgentContext.ts +71 -0
  133. package/store/agent/AgentPrompts.ts +100 -0
  134. package/store/agent/ScreenReader.ts +319 -0
  135. package/store/agent/ScreenSettle.ts +45 -0
  136. package/store/agent/ScreenTarget.ts +129 -0
  137. package/store/agent/StateWait.ts +139 -0
  138. package/store/agent/StoreCatalogue.ts +116 -0
  139. package/store/agent/StoreSurfaceSource.ts +282 -0
  140. package/store/agent/index.ts +14 -0
  141. package/store/agent/storeSurface.ts +28 -0
  142. package/store/agent/types.ts +16 -0
  143. package/store/agentic/StToolBuilder.ts +261 -0
  144. package/store/agentic/attachAgentic.ts +27 -0
  145. package/store/agentic/formFields.ts +194 -0
  146. package/store/agentic/index.ts +9 -0
  147. package/store/agentic/readableValue.ts +17 -0
  148. package/store/agentic/useFieldTool.ts +187 -0
  149. package/store/agentic/useFormTools.ts +79 -0
  150. package/store/agentic/useRelationFieldTool.ts +114 -0
  151. package/store/agentic/useStExpose.ts +18 -0
  152. package/store/agentic/useStState.ts +49 -0
  153. package/store/baseSt.ts +1 -1
  154. package/store/databaseStateNames.ts +31 -0
  155. package/store/formSetterNames.ts +35 -0
  156. package/store/index.ts +8 -0
  157. package/store/rootStore.ts +3 -1
  158. package/store/sliceRole.ts +36 -0
  159. package/store/state.ts +2 -12
  160. package/store/store.ts +9 -0
  161. package/store/storeInstance.ts +185 -20
  162. package/store/storeRegistry.ts +39 -1
  163. package/store/types.ts +12 -0
  164. package/store/withSelector.ts +7 -8
  165. package/test/index.ts +1 -1
  166. package/test/registerDom.ts +4 -0
  167. package/test/signalTestRuntime.ts +5 -5
  168. package/test/testServer.ts +8 -5
  169. package/types/base/baseEnv.d.ts +1 -1
  170. package/types/base/symbols.d.ts +5 -0
  171. package/types/client/capacitor.d.ts +39 -0
  172. package/types/client/clientRuntime.d.ts +2 -0
  173. package/types/common/Logger.d.ts +2 -0
  174. package/types/common/deepObjectify.d.ts +4 -2
  175. package/types/common/index.d.ts +2 -1
  176. package/types/common/mcpExposure.d.ts +60 -0
  177. package/types/common/routeConvention.d.ts +8 -0
  178. package/types/constant/cascadePaths.d.ts +22 -4
  179. package/types/constant/fieldInfo.d.ts +1 -0
  180. package/types/constant/getDefault.d.ts +5 -0
  181. package/types/constant/index.d.ts +2 -0
  182. package/types/constant/labelOf.d.ts +6 -0
  183. package/types/constant/mask.d.ts +34 -0
  184. package/types/constant/purify.d.ts +2 -2
  185. package/types/constant/types.d.ts +2 -2
  186. package/types/dictionary/DictionaryLookup.d.ts +14 -0
  187. package/types/dictionary/agent.dictionary.d.ts +1 -0
  188. package/types/dictionary/agentTurn.dictionary.d.ts +1 -0
  189. package/types/dictionary/base.dictionary.d.ts +1 -1
  190. package/types/dictionary/dictInfo.d.ts +6 -0
  191. package/types/dictionary/dictionary.d.ts +11 -9
  192. package/types/dictionary/index.d.ts +1 -0
  193. package/types/document/database.d.ts +22 -1
  194. package/types/document/databaseRegistry.d.ts +2 -2
  195. package/types/document/filterMeta.d.ts +1 -0
  196. package/types/document/index.d.ts +1 -0
  197. package/types/document/into.d.ts +12 -6
  198. package/types/document/noDocumentError.d.ts +12 -0
  199. package/types/fetch/agentTurn.d.ts +593 -0
  200. package/types/fetch/client/fetchClient.d.ts +10 -0
  201. package/types/fetch/client/httpClient.d.ts +2 -1
  202. package/types/fetch/fetchType/endpointFetch.type.d.ts +5 -3
  203. package/types/fetch/index.d.ts +1 -0
  204. package/types/index.d.ts +1 -1
  205. package/types/server/akanApp.d.ts +5 -0
  206. package/types/server/akanOption.d.ts +36 -6
  207. package/types/server/akanServer.d.ts +53 -7
  208. package/types/server/animatedImage.d.ts +7 -0
  209. package/types/server/artifact/routeClientCache.d.ts +6 -0
  210. package/types/server/assetEncoding.d.ts +7 -0
  211. package/types/server/cachePolicy.d.ts +33 -2
  212. package/types/server/devtools/types.d.ts +4 -4
  213. package/types/server/di/diLifecycle.d.ts +10 -2
  214. package/types/server/di/predefinedAdaptor.d.ts +4 -1
  215. package/types/server/di/utils.d.ts +16 -0
  216. package/types/server/index.d.ts +0 -2
  217. package/types/server/mcp/McpAuth.d.ts +62 -0
  218. package/types/server/mcp/McpDispatcher.d.ts +54 -0
  219. package/types/server/mcp/McpEventStream.d.ts +18 -0
  220. package/types/server/mcp/McpExecutionContext.d.ts +44 -0
  221. package/types/server/mcp/McpRouter.d.ts +61 -0
  222. package/types/server/mcp/index.d.ts +5 -0
  223. package/types/server/mcp.d.ts +1 -0
  224. package/types/server/resolver/CascadeRunner.d.ts +13 -0
  225. package/types/server/resolver/database.resolver.d.ts +6 -2
  226. package/types/server/resolver/index.d.ts +1 -0
  227. package/types/server/resolver/service.resolver.d.ts +3 -3
  228. package/types/server/resolver/signal.resolver.d.ts +5 -3
  229. package/types/server/rscWorkerHost.d.ts +13 -0
  230. package/types/server/subRouteIndexDocument.d.ts +8 -0
  231. package/types/server/systemPageDocument.d.ts +1 -0
  232. package/types/server/systemPages.d.ts +5 -0
  233. package/types/server/vendor/akanjs-fetch.d.ts +1 -0
  234. package/types/service/agent.service.d.ts +24 -0
  235. package/types/service/base.service.d.ts +4 -0
  236. package/types/service/index.d.ts +1 -0
  237. package/types/service/injectInfo.d.ts +2 -2
  238. package/types/service/ipcTypes.d.ts +24 -0
  239. package/types/service/predefinedAdaptor/database.adaptor.d.ts +28 -6
  240. package/types/service/predefinedAdaptor/deepseekLlm.d.ts +70 -0
  241. package/types/service/predefinedAdaptor/index.d.ts +3 -0
  242. package/types/service/predefinedAdaptor/insightQuery.d.ts +50 -0
  243. package/types/service/predefinedAdaptor/llm.adaptor.d.ts +97 -0
  244. package/types/service/predefinedAdaptor/queue.adaptor.d.ts +3 -2
  245. package/types/service/predefinedAdaptor/role.adaptor.d.ts +2 -0
  246. package/types/service/predefinedAdaptor/schedule.adaptor.d.ts +10 -6
  247. package/types/service/predefinedAdaptor/solidQueue.adaptor.d.ts +6 -2
  248. package/types/service/predefinedAdaptor/solidSqlite.d.ts +2 -2
  249. package/types/service/types.d.ts +5 -1
  250. package/types/signal/agent/AgentCatalogue.d.ts +100 -0
  251. package/types/signal/agent/index.d.ts +1 -0
  252. package/types/signal/agent.d.ts +1 -0
  253. package/types/signal/agent.signal.d.ts +24 -0
  254. package/types/signal/agentTurn.d.ts +9 -0
  255. package/types/signal/agentTurnStream.d.ts +16 -0
  256. package/types/signal/base.signal.d.ts +1 -1
  257. package/types/signal/endpointInfo.d.ts +21 -3
  258. package/types/signal/guard.d.ts +12 -0
  259. package/types/signal/guards.d.ts +23 -1
  260. package/types/signal/index.d.ts +6 -0
  261. package/types/signal/mcp/McpDocument.d.ts +65 -0
  262. package/types/signal/mcp/McpProgress.d.ts +40 -0
  263. package/types/signal/mcp/McpUriTemplate.d.ts +26 -0
  264. package/types/signal/mcp/Msg.d.ts +143 -0
  265. package/types/signal/mcp/index.d.ts +5 -0
  266. package/types/signal/mcp/mcpProtocol.d.ts +107 -0
  267. package/types/signal/mcp.d.ts +1 -0
  268. package/types/signal/middleware.d.ts +7 -7
  269. package/types/signal/openapi/openapi.d.ts +3 -3
  270. package/types/signal/schema/JsonSchemaBuilder.d.ts +47 -0
  271. package/types/signal/schema/index.d.ts +1 -0
  272. package/types/signal/schema.d.ts +1 -0
  273. package/types/signal/signalContext.d.ts +18 -3
  274. package/types/signal/slice.d.ts +8 -8
  275. package/types/signal/types.d.ts +8 -1
  276. package/types/store/actionTag.d.ts +21 -0
  277. package/types/store/agent/AgentBridge.d.ts +37 -0
  278. package/types/store/agent/AgentContext.d.ts +16 -0
  279. package/types/store/agent/AgentPrompts.d.ts +31 -0
  280. package/types/store/agent/ScreenReader.d.ts +24 -0
  281. package/types/store/agent/ScreenSettle.d.ts +22 -0
  282. package/types/store/agent/ScreenTarget.d.ts +33 -0
  283. package/types/store/agent/StateWait.d.ts +36 -0
  284. package/types/store/agent/StoreCatalogue.d.ts +26 -0
  285. package/types/store/agent/StoreSurfaceSource.d.ts +22 -0
  286. package/types/store/agent/index.d.ts +12 -0
  287. package/types/store/agent/storeSurface.d.ts +14 -0
  288. package/types/store/agent/types.d.ts +15 -0
  289. package/types/store/agent.d.ts +1 -0
  290. package/types/store/agentic/StToolBuilder.d.ts +57 -0
  291. package/types/store/agentic/attachAgentic.d.ts +19 -0
  292. package/types/store/agentic/formFields.d.ts +53 -0
  293. package/types/store/agentic/index.d.ts +9 -0
  294. package/types/store/agentic/readableValue.d.ts +3 -0
  295. package/types/store/agentic/useFieldTool.d.ts +22 -0
  296. package/types/store/agentic/useFormTools.d.ts +19 -0
  297. package/types/store/agentic/useRelationFieldTool.d.ts +27 -0
  298. package/types/store/agentic/useStExpose.d.ts +8 -0
  299. package/types/store/agentic/useStState.d.ts +12 -0
  300. package/types/store/agentic.d.ts +1 -0
  301. package/types/store/baseSt.d.ts +34 -34
  302. package/types/store/databaseStateNames.d.ts +25 -0
  303. package/types/store/formSetterNames.d.ts +30 -0
  304. package/types/store/index.d.ts +7 -0
  305. package/types/store/rootStore.d.ts +5 -1
  306. package/types/store/sliceRole.d.ts +25 -0
  307. package/types/store/store.d.ts +5 -1
  308. package/types/store/storeInstance.d.ts +33 -1
  309. package/types/store/storeRegistry.d.ts +5 -0
  310. package/types/store/types.d.ts +8 -0
  311. package/types/store/withSelector.d.ts +7 -8
  312. package/types/test/index.d.ts +1 -1
  313. package/types/test/registerDom.d.ts +1 -0
  314. package/types/test/signalTestRuntime.d.ts +2 -3
  315. package/types/test/testServer.d.ts +6 -4
  316. package/types/ui/Agent/Approval.d.ts +7 -0
  317. package/types/ui/Agent/Attach.d.ts +16 -0
  318. package/types/ui/Agent/Bubble.d.ts +17 -0
  319. package/types/ui/Agent/Chat.d.ts +42 -0
  320. package/types/ui/Agent/ChatCommands.d.ts +34 -0
  321. package/types/ui/Agent/Context.d.ts +9 -0
  322. package/types/ui/Agent/Dock.d.ts +17 -0
  323. package/types/ui/Agent/Guide.d.ts +9 -0
  324. package/types/ui/Agent/Markdown.d.ts +11 -0
  325. package/types/ui/Agent/Menu.d.ts +12 -0
  326. package/types/ui/Agent/Mic.d.ts +8 -0
  327. package/types/ui/Agent/Question.d.ts +13 -0
  328. package/types/ui/Agent/Section.d.ts +10 -0
  329. package/types/ui/Agent/StateKey.d.ts +16 -0
  330. package/types/ui/Agent/Tool.d.ts +15 -0
  331. package/types/ui/Agent/Transcript.d.ts +13 -0
  332. package/types/ui/Agent/Zone.d.ts +23 -0
  333. package/types/ui/Agent/attachment.d.ts +23 -0
  334. package/types/ui/Agent/fetchRunner.d.ts +12 -0
  335. package/types/ui/Agent/index.d.ts +17 -0
  336. package/types/ui/Agent/index_.d.ts +1 -0
  337. package/types/ui/Agent/markdownBlocks.d.ts +34 -0
  338. package/types/ui/Agent/markdownSpans.d.ts +2 -0
  339. package/types/ui/Agent/markdownTable.d.ts +16 -0
  340. package/types/ui/Agent/sessionHistory.d.ts +12 -0
  341. package/types/ui/Agent/voice.d.ts +66 -0
  342. package/types/ui/Agent.d.ts +1 -0
  343. package/types/ui/Badge.d.ts +1 -1
  344. package/types/ui/Button.d.ts +1 -1
  345. package/types/ui/Constant/Graph.d.ts +10 -0
  346. package/types/ui/Constant/index.d.ts +2 -1
  347. package/types/ui/Constant/schemaGraph.d.ts +39 -0
  348. package/types/ui/CsrImage.d.ts +1 -1
  349. package/types/ui/Data/Dashboard.d.ts +3 -2
  350. package/types/ui/Data/Insight.d.ts +1 -1
  351. package/types/ui/Data/ListContainer.d.ts +3 -3
  352. package/types/ui/Data/dataExport.d.ts +5 -0
  353. package/types/ui/Data/dataText.d.ts +6 -0
  354. package/types/ui/Dialog/LegacyModal.d.ts +13 -0
  355. package/types/ui/Dialog/Provider.d.ts +3 -1
  356. package/types/ui/Dialog/context.d.ts +8 -0
  357. package/types/ui/Dialog/index.d.ts +1 -0
  358. package/types/ui/DraggableList.d.ts +1 -1
  359. package/types/ui/Dropdown.d.ts +7 -1
  360. package/types/ui/Field.d.ts +1 -0
  361. package/types/ui/Image.d.ts +3 -3
  362. package/types/ui/Layout/BottomTab.d.ts +3 -2
  363. package/types/ui/LegacyModal.d.ts +24 -0
  364. package/types/ui/Loading/ProgressBar.d.ts +4 -0
  365. package/types/ui/Loading/Spin.d.ts +2 -1
  366. package/types/ui/Model/AdminPanel.d.ts +9 -2
  367. package/types/ui/Model/EditModal.d.ts +1 -1
  368. package/types/ui/Model/New.d.ts +3 -1
  369. package/types/ui/Model/NewWrapper.d.ts +2 -0
  370. package/types/ui/Model/NewWrapper_Client.d.ts +2 -1
  371. package/types/ui/Pagination.d.ts +2 -2
  372. package/types/ui/Radio.d.ts +1 -1
  373. package/types/ui/Reference/Collapse.d.ts +11 -0
  374. package/types/ui/Reference/Panel.d.ts +29 -0
  375. package/types/ui/Reference/Segmented.d.ts +17 -0
  376. package/types/ui/Reference/Summary.d.ts +13 -0
  377. package/types/ui/Reference/Toolbar.d.ts +21 -0
  378. package/types/ui/Reference/dictText.d.ts +6 -0
  379. package/types/ui/Reference/index.d.ts +7 -0
  380. package/types/ui/Reference/style.d.ts +20 -0
  381. package/types/ui/Reference.d.ts +1 -0
  382. package/types/ui/ScreenNavigator.d.ts +3 -1
  383. package/types/ui/Signal/Doc.d.ts +4 -6
  384. package/types/ui/Signal/Object.d.ts +2 -1
  385. package/types/ui/Signal/RestApi.d.ts +2 -1
  386. package/types/ui/Signal/WebSocket.d.ts +2 -1
  387. package/types/ui/Signal/endpointEntries.d.ts +20 -0
  388. package/types/ui/Signal/style.d.ts +9 -8
  389. package/types/ui/System/Messages.d.ts +1 -1
  390. package/types/ui/Tab/Provider.d.ts +3 -1
  391. package/types/ui/Tab/context.d.ts +3 -1
  392. package/types/ui/UiOverride/context.d.ts +2 -0
  393. package/types/ui/agentAttrs.d.ts +14 -0
  394. package/types/ui/index.d.ts +7 -1
  395. package/types/ui/overlayLayer.d.ts +37 -0
  396. package/types/ui/overlayPosition.d.ts +28 -0
  397. package/types/ui/recipe/badgeRecipe.d.ts +2 -2
  398. package/types/ui/recipe/buttonRecipe.d.ts +2 -2
  399. package/types/vendor/use-agentic/AgentAbort.d.ts +17 -0
  400. package/types/vendor/use-agentic/AgentProgress.d.ts +27 -0
  401. package/types/vendor/use-agentic/AgentProvider.d.ts +18 -0
  402. package/types/vendor/use-agentic/AgentScope.d.ts +9 -0
  403. package/types/vendor/use-agentic/AgentSession.d.ts +100 -0
  404. package/types/vendor/use-agentic/Agentic.d.ts +21 -0
  405. package/types/vendor/use-agentic/AgenticSurface.d.ts +52 -0
  406. package/types/vendor/use-agentic/httpRunner.d.ts +15 -0
  407. package/types/vendor/use-agentic/index.d.ts +15 -0
  408. package/types/vendor/use-agentic/surfaceContext.d.ts +5 -0
  409. package/types/vendor/use-agentic/types.d.ts +170 -0
  410. package/types/vendor/use-agentic/useAgent.d.ts +4 -0
  411. package/types/vendor/use-agentic/useAgentGuide.d.ts +6 -0
  412. package/types/vendor/use-agentic/useAgentResource.d.ts +12 -0
  413. package/types/vendor/use-agentic/useAgentState.d.ts +16 -0
  414. package/types/vendor/use-agentic/useAgentTool.d.ts +16 -0
  415. package/types/vendor/use-agentic.d.ts +1 -0
  416. package/types/webkit/index.d.ts +5 -0
  417. package/types/webkit/lazy.d.ts +12 -0
  418. package/types/webkit/useBodyScrollLock.d.ts +2 -0
  419. package/types/webkit/useEscapeKey.d.ts +5 -0
  420. package/types/webkit/usePageTool.d.ts +19 -0
  421. package/types/webkit/useScreenScope.d.ts +25 -0
  422. package/ui/Agent/Approval.tsx +29 -0
  423. package/ui/Agent/Attach.tsx +77 -0
  424. package/ui/Agent/Bubble.tsx +123 -0
  425. package/ui/Agent/Chat.tsx +468 -0
  426. package/ui/Agent/ChatCommands.ts +131 -0
  427. package/ui/Agent/Context.tsx +38 -0
  428. package/ui/Agent/Dock.tsx +75 -0
  429. package/ui/Agent/Guide.tsx +16 -0
  430. package/ui/Agent/Markdown.tsx +125 -0
  431. package/ui/Agent/Menu.tsx +58 -0
  432. package/ui/Agent/Mic.tsx +27 -0
  433. package/ui/Agent/Question.tsx +60 -0
  434. package/ui/Agent/Section.tsx +24 -0
  435. package/ui/Agent/StateKey.tsx +46 -0
  436. package/ui/Agent/Tool.tsx +73 -0
  437. package/ui/Agent/Transcript.tsx +33 -0
  438. package/ui/Agent/Zone.tsx +52 -0
  439. package/ui/Agent/attachment.ts +53 -0
  440. package/ui/Agent/fetchRunner.ts +30 -0
  441. package/ui/Agent/index.ts +12 -0
  442. package/ui/Agent/index_.tsx +4 -0
  443. package/ui/Agent/markdownBlocks.ts +135 -0
  444. package/ui/Agent/markdownSpans.tsx +49 -0
  445. package/ui/Agent/markdownTable.ts +54 -0
  446. package/ui/Agent/sessionHistory.ts +52 -0
  447. package/ui/Agent/voice.ts +168 -0
  448. package/ui/Badge.tsx +1 -1
  449. package/ui/BottomSheet.tsx +37 -36
  450. package/ui/Button.tsx +3 -1
  451. package/ui/Clipboard.tsx +3 -6
  452. package/ui/Constant/Doc.tsx +265 -254
  453. package/ui/Constant/Graph.tsx +151 -0
  454. package/ui/Constant/index.ts +3 -2
  455. package/ui/Constant/schemaGraph.ts +232 -0
  456. package/ui/CsrImage.tsx +1 -1
  457. package/ui/Data/CardList.tsx +14 -3
  458. package/ui/Data/Dashboard.tsx +34 -50
  459. package/ui/Data/Insight.tsx +18 -12
  460. package/ui/Data/Item.tsx +42 -56
  461. package/ui/Data/ListContainer.tsx +226 -126
  462. package/ui/Data/Pagination.tsx +10 -3
  463. package/ui/Data/TableList.tsx +22 -13
  464. package/ui/Data/dataExport.ts +54 -0
  465. package/ui/Data/dataText.ts +22 -0
  466. package/ui/DatePicker.tsx +1 -1
  467. package/ui/Dialog/Close.tsx +3 -7
  468. package/ui/Dialog/LegacyModal.tsx +241 -0
  469. package/ui/Dialog/Modal.tsx +66 -202
  470. package/ui/Dialog/Provider.tsx +46 -3
  471. package/ui/Dialog/Trigger.tsx +3 -7
  472. package/ui/Dialog/context.ts +11 -0
  473. package/ui/Dialog/index.tsx +2 -0
  474. package/ui/DraggableList.tsx +6 -2
  475. package/ui/Dropdown.tsx +106 -22
  476. package/ui/Empty.tsx +6 -4
  477. package/ui/Field.tsx +88 -27
  478. package/ui/Image.tsx +3 -3
  479. package/ui/Input.tsx +27 -5
  480. package/ui/KeyboardAvoiding.tsx +2 -2
  481. package/ui/Layout/BottomTab.tsx +32 -37
  482. package/ui/Layout/Sider.tsx +31 -14
  483. package/ui/LegacyModal.tsx +53 -0
  484. package/ui/Link/CsrLink.tsx +1 -1
  485. package/ui/Load/Pagination.tsx +15 -8
  486. package/ui/Load/Units.tsx +25 -4
  487. package/ui/Load/View.tsx +10 -3
  488. package/ui/Loading/Area.tsx +7 -6
  489. package/ui/Loading/Button.tsx +7 -9
  490. package/ui/Loading/Input.tsx +7 -9
  491. package/ui/Loading/ProgressBar.tsx +16 -7
  492. package/ui/Loading/Skeleton.tsx +8 -13
  493. package/ui/Loading/Spin.tsx +20 -14
  494. package/ui/Menu.tsx +1 -1
  495. package/ui/Model/AdminPanel.tsx +41 -11
  496. package/ui/Model/EditModal.tsx +66 -7
  497. package/ui/Model/EditWrapper.tsx +19 -4
  498. package/ui/Model/New.tsx +4 -0
  499. package/ui/Model/NewWrapper.tsx +2 -0
  500. package/ui/Model/NewWrapper_Client.tsx +21 -6
  501. package/ui/Model/Remove.tsx +17 -6
  502. package/ui/Model/RemoveWrapper.tsx +11 -2
  503. package/ui/Model/SureToRemove.tsx +21 -6
  504. package/ui/Model/ViewEditModal.tsx +67 -15
  505. package/ui/Model/ViewModal.tsx +26 -11
  506. package/ui/Model/ViewWrapper.tsx +14 -4
  507. package/ui/Model/index_.tsx +42 -15
  508. package/ui/Pagination.tsx +51 -66
  509. package/ui/Popconfirm.tsx +85 -77
  510. package/ui/Radio.tsx +53 -24
  511. package/ui/Reference/Collapse.tsx +26 -0
  512. package/ui/Reference/Panel.tsx +79 -0
  513. package/ui/Reference/Segmented.tsx +41 -0
  514. package/ui/Reference/Summary.tsx +25 -0
  515. package/ui/Reference/Toolbar.tsx +44 -0
  516. package/ui/Reference/dictText.ts +9 -0
  517. package/ui/Reference/index.ts +7 -0
  518. package/ui/Reference/style.ts +45 -0
  519. package/ui/ScreenNavigator.tsx +14 -0
  520. package/ui/Select.tsx +91 -57
  521. package/ui/Signal/Arg.tsx +50 -52
  522. package/ui/Signal/Doc.tsx +163 -129
  523. package/ui/Signal/Listener.tsx +24 -28
  524. package/ui/Signal/Message.tsx +87 -135
  525. package/ui/Signal/Object.tsx +79 -57
  526. package/ui/Signal/PubSub.tsx +72 -113
  527. package/ui/Signal/Request.tsx +2 -22
  528. package/ui/Signal/Response.tsx +19 -45
  529. package/ui/Signal/RestApi.tsx +170 -200
  530. package/ui/Signal/WebSocket.tsx +29 -26
  531. package/ui/Signal/endpointEntries.ts +59 -0
  532. package/ui/Signal/style.ts +34 -29
  533. package/ui/Switch.tsx +4 -0
  534. package/ui/System/CSR.tsx +1 -1
  535. package/ui/System/Client.tsx +5 -5
  536. package/ui/System/DevModeToggle.tsx +1 -1
  537. package/ui/System/Gtag.tsx +2 -2
  538. package/ui/System/Messages.tsx +52 -31
  539. package/ui/System/Reconnect.tsx +22 -56
  540. package/ui/System/SelectLanguage.tsx +23 -15
  541. package/ui/System/ThemeToggle.tsx +12 -10
  542. package/ui/Tab/Menu.tsx +24 -12
  543. package/ui/Tab/Menus.tsx +6 -3
  544. package/ui/Tab/Provider.tsx +31 -3
  545. package/ui/Tab/context.ts +5 -2
  546. package/ui/Table.tsx +66 -60
  547. package/ui/ToggleSelect.tsx +4 -6
  548. package/ui/Tooltip.tsx +17 -2
  549. package/ui/UiOverride/context.ts +2 -0
  550. package/ui/Unauthorized.tsx +6 -4
  551. package/ui/agentAttrs.ts +19 -0
  552. package/ui/index.ts +13 -1
  553. package/ui/overlayLayer.ts +48 -0
  554. package/ui/overlayPosition.ts +104 -0
  555. package/ui/recipe/buttonRecipe.ts +2 -2
  556. package/ui/styles.css +27 -0
  557. package/vendor/use-agentic/AgentAbort.ts +29 -0
  558. package/vendor/use-agentic/AgentProgress.ts +40 -0
  559. package/vendor/use-agentic/AgentProvider.tsx +39 -0
  560. package/vendor/use-agentic/AgentScope.tsx +20 -0
  561. package/vendor/use-agentic/AgentSession.ts +506 -0
  562. package/vendor/use-agentic/Agentic.tsx +44 -0
  563. package/vendor/use-agentic/AgenticSurface.ts +318 -0
  564. package/vendor/use-agentic/WIRE.md +75 -0
  565. package/vendor/use-agentic/httpRunner.ts +115 -0
  566. package/vendor/use-agentic/index.ts +16 -0
  567. package/vendor/use-agentic/surfaceContext.ts +9 -0
  568. package/vendor/use-agentic/types.ts +183 -0
  569. package/vendor/use-agentic/useAgent.ts +17 -0
  570. package/vendor/use-agentic/useAgentGuide.ts +16 -0
  571. package/vendor/use-agentic/useAgentResource.ts +36 -0
  572. package/vendor/use-agentic/useAgentState.ts +65 -0
  573. package/vendor/use-agentic/useAgentTool.ts +55 -0
  574. package/webkit/bootCsr.tsx +2 -33
  575. package/webkit/index.ts +5 -0
  576. package/webkit/lazy.tsx +27 -3
  577. package/webkit/useBodyScrollLock.tsx +29 -0
  578. package/webkit/useEscapeKey.tsx +42 -0
  579. package/webkit/useFrameRuntime.ts +32 -29
  580. package/webkit/usePageTool.tsx +39 -0
  581. package/webkit/useScreenScope.tsx +60 -0
  582. package/types/ui/Constant/Mermaid.d.ts +0 -8
  583. package/types/ui/Signal/Collapse.d.ts +0 -12
  584. package/ui/Constant/Mermaid.tsx +0 -149
  585. package/ui/Signal/Collapse.tsx +0 -29
package/README.ko.md CHANGED
@@ -26,7 +26,7 @@ generated reference가 같은 의도에서 이어집니다.
26
26
 
27
27
  ## 요구사항
28
28
 
29
- - [Bun](https://bun.sh) `>=1.3.13`
29
+ - [Bun](https://bun.sh) `>=1.4.0`
30
30
  - TypeScript 중심의 애플리케이션 코드
31
31
  - React 기반 UI surface
32
32
 
package/README.md CHANGED
@@ -25,7 +25,7 @@ server, app packaging, deployment artifacts, and generated references.
25
25
 
26
26
  ## Requirements
27
27
 
28
- - [Bun](https://bun.sh) `>=1.3.13`
28
+ - [Bun](https://bun.sh) `>=1.4.0`
29
29
  - TypeScript-first application code
30
30
  - React-based UI surfaces
31
31
 
package/base/baseEnv.ts CHANGED
@@ -15,7 +15,7 @@ export interface BaseEnv {
15
15
  operationMode: "local" | "edge" | "cloud" | "module";
16
16
  databaseMode?: DatabaseMode;
17
17
  }
18
- export type BackendEnv = BaseEnv & {
18
+ export type BackendEnv = {
19
19
  hostname?: string | null;
20
20
  port?: number;
21
21
  database?: {
package/base/symbols.ts CHANGED
@@ -3,6 +3,7 @@ export const SLICE_META = Symbol.for("akan.slice");
3
3
  export const FILTER_META = Symbol.for("akan.filter");
4
4
  export const LOADER_META = Symbol.for("akan.loader");
5
5
  export const INJECT_META = Symbol.for("akan.inject");
6
+ export const LIBS_REMOVE_HOOK = Symbol.for("akan.service.libsRemoveHook");
6
7
  export const ENDPOINT_META = Symbol.for("akan.endpoint");
7
8
  export const ENDPOINT_DICT_SHAPE: unique symbol = Symbol.for("akan.endpoint.dictShape") as never;
8
9
  export const SLICE_DICT_SHAPE: unique symbol = Symbol.for("akan.slice.dictShape") as never;
@@ -12,6 +13,10 @@ export const STATE_META = Symbol.for("akan.state");
12
13
  export const STATE_INIT_META = Symbol.for("akan.state.init");
13
14
  export const STATE_DERIVED_META = Symbol.for("akan.state.derived");
14
15
  export const ACTION_META = Symbol.for("akan.action");
16
+ /** Which module declared each action. See `ActionOwner`. */
17
+ export const ACTION_OWNER_META = Symbol.for("akan.action.owner");
18
+ /** What a dispatcher does, carried on the function so a component handed one can annotate the DOM with it. */
19
+ export const ACTION_TAG = Symbol.for("akan.action.tag");
15
20
  export const SERVER_VALUE = Symbol.for("akan.value.server");
16
21
  export const CLIENT_VALUE = Symbol.for("akan.value.client");
17
22
  export const DEFAULT_VALUE = Symbol.for("akan.value.default");
@@ -46,6 +46,28 @@ export type CapacitorContactsModule = {
46
46
  };
47
47
  };
48
48
 
49
+ export type CapacitorSpeechRecognitionModule = {
50
+ SpeechRecognition: {
51
+ available: () => Promise<{ available: boolean }>;
52
+ checkPermissions: () => Promise<{ speechRecognition: CapacitorPermissionState }>;
53
+ requestPermissions: () => Promise<{ speechRecognition: CapacitorPermissionState }>;
54
+ start: (options: Record<string, unknown>) => Promise<{ matches?: string[] }>;
55
+ stop: () => Promise<void>;
56
+ removeAllListeners: () => Promise<void> | void;
57
+ addListener: (
58
+ eventName: string,
59
+ listenerFunc: (data: { matches?: string[] }) => void,
60
+ ) => Promise<{ remove: () => Promise<void> | void }> | { remove: () => Promise<void> | void };
61
+ };
62
+ };
63
+
64
+ export type CapacitorTextToSpeechModule = {
65
+ TextToSpeech: {
66
+ speak: (options: { text: string; lang?: string; rate?: number }) => Promise<void>;
67
+ stop: () => Promise<void>;
68
+ };
69
+ };
70
+
49
71
  export type CapacitorCoreModule = {
50
72
  CapacitorCookies: {
51
73
  setCookie: (options: { key: string; value: string; path?: string }) => Promise<void> | void;
@@ -155,6 +177,8 @@ type CapacitorModuleMap = {
155
177
  preferences: CapacitorPreferencesModule;
156
178
  pushNotifications: CapacitorPushNotificationsModule;
157
179
  safeArea: CapacitorSafeAreaModule;
180
+ speechRecognition: CapacitorSpeechRecognitionModule;
181
+ textToSpeech: CapacitorTextToSpeechModule;
158
182
  updater: CapacitorUpdaterModule;
159
183
  };
160
184
 
@@ -257,6 +281,16 @@ export const loadCapacitorSafeArea = () =>
257
281
  SafeArea: getCapacitorPlugin<CapacitorSafeAreaModule["SafeArea"]>("SafeArea"),
258
282
  }));
259
283
 
284
+ export const loadCapacitorSpeechRecognition = () =>
285
+ loadCapacitorModule("speechRecognition", async () => ({
286
+ SpeechRecognition: getCapacitorPlugin<CapacitorSpeechRecognitionModule["SpeechRecognition"]>("SpeechRecognition"),
287
+ }));
288
+
289
+ export const loadCapacitorTextToSpeech = () =>
290
+ loadCapacitorModule("textToSpeech", async () => ({
291
+ TextToSpeech: getCapacitorPlugin<CapacitorTextToSpeechModule["TextToSpeech"]>("TextToSpeech"),
292
+ }));
293
+
260
294
  export const loadCapacitorUpdater = () =>
261
295
  loadCapacitorModule("updater", async () => ({
262
296
  CapacitorUpdater: getCapacitorPlugin<CapacitorUpdaterModule["CapacitorUpdater"]>("CapacitorUpdater"),
@@ -47,6 +47,8 @@ type RuntimeFetch = typeof globalThis.fetch & {
47
47
  serializedSignal: Record<string, unknown>;
48
48
  setJwt: (jwt: string | null) => void;
49
49
  slice: Record<string, SliceMeta>;
50
+ /** Sort keys per model refName, registered from each serialized signal's filter. */
51
+ sortKeyMap?: Map<string, string[]>;
50
52
  ws: RuntimeWs;
51
53
  [key: string]: unknown;
52
54
  };
@@ -75,6 +77,13 @@ globalWithRuntime[CLIENT_RUNTIME_KEY] = state;
75
77
  const missingRuntimeError = () =>
76
78
  new Error("Akan client runtime is not registered. Import the generated app client first.");
77
79
 
80
+ const applyRuntimeErrorConstructor = (runtime: ClientRuntime) => {
81
+ const instance = (runtime.fetch as RuntimeFetch | undefined)?.instance as
82
+ | { setErrorConstructor?: (Err: unknown) => void }
83
+ | undefined;
84
+ if (typeof instance?.setErrorConstructor === "function") instance.setErrorConstructor(runtime.Err);
85
+ };
86
+
78
87
  export const registerClientRuntime = <Runtime>(
79
88
  runtime: Runtime,
80
89
  { scope = "app" }: { scope?: RuntimeScope } = {},
@@ -82,6 +91,7 @@ export const registerClientRuntime = <Runtime>(
82
91
  if (state.scope === "app" && scope === "lib") return runtime;
83
92
  state.runtime = runtime as ClientRuntime;
84
93
  state.scope = scope;
94
+ applyRuntimeErrorConstructor(state.runtime);
85
95
  return runtime;
86
96
  };
87
97
 
package/common/Logger.ts CHANGED
@@ -60,6 +60,10 @@ export class Logger {
60
60
  static isVerbose() {
61
61
  return Logger.#levelIdx <= 1;
62
62
  }
63
+ /** For hot-path callers that would otherwise build a message the level is about to discard. */
64
+ static shouldLog(logLevel: LogLevel) {
65
+ return Logger.#shouldLog(logLevel);
66
+ }
63
67
 
64
68
  name?: string;
65
69
  constructor(name?: string) {
@@ -1,9 +1,16 @@
1
1
  import { isDayjs } from "./isDayjs";
2
2
 
3
- export const deepObjectify = <T = unknown>(
4
- obj: T | null | undefined,
5
- option: { serializable?: boolean; convertDate?: "string" | "number" } = {},
6
- ): T => {
3
+ interface DeepObjectifyOption {
4
+ serializable?: boolean;
5
+ convertDate?: "string" | "number";
6
+ }
7
+
8
+ const objectifyChild = (value: unknown, option: DeepObjectifyOption): unknown => {
9
+ const modelValue = value as { __ModelType__?: string } | null | undefined;
10
+ return modelValue?.__ModelType__ && !option.serializable ? value : deepObjectify(value, option);
11
+ };
12
+
13
+ export const deepObjectify = <T = unknown>(obj: T | null | undefined, option: DeepObjectifyOption = {}): T => {
7
14
  if (isDayjs(obj) || obj?.constructor === Date) {
8
15
  if (!option.serializable && !option.convertDate) return obj as T;
9
16
  if (option.convertDate === "string") return obj.toISOString() as T;
@@ -12,13 +19,20 @@ export const deepObjectify = <T = unknown>(
12
19
  else return (isDayjs(obj) ? obj.toDate() : obj) as T;
13
20
  } else if (Array.isArray(obj)) {
14
21
  return obj.map((o: unknown) => deepObjectify(o, option)) as T;
22
+ } else if (obj instanceof Map) {
23
+
24
+ const entries = [...obj.entries()].map(
25
+ ([key, value]: [string, unknown]) => [key, objectifyChild(value, option)] as const,
26
+ );
27
+ return (option.serializable ? Object.fromEntries(entries) : new Map(entries)) as T;
28
+ } else if (obj instanceof Set) {
29
+ const values = [...obj.values()].map((value: unknown) => objectifyChild(value, option));
30
+ return (option.serializable ? values : new Set(values)) as T;
15
31
  } else if (obj && typeof obj === "object") {
16
32
  const val: Record<string, unknown> = {};
17
33
  const objRecord = obj as Record<string, unknown>;
18
34
  Object.keys(obj).forEach((key) => {
19
- const fieldValue = objRecord[key] as { __ModelType__: string } | null | undefined;
20
- if (fieldValue?.__ModelType__ && !option.serializable) val[key] = fieldValue;
21
- else if (typeof objRecord[key] !== "function") val[key] = deepObjectify(fieldValue, option);
35
+ if (typeof objRecord[key] !== "function") val[key] = objectifyChild(objRecord[key], option);
22
36
  });
23
37
  return val as T;
24
38
  } else {
package/common/index.ts CHANGED
@@ -27,6 +27,15 @@ export {
27
27
  resolveAkanI18nConfig,
28
28
  } from "./localeConfig";
29
29
  export { lowerlize } from "./lowerlize";
30
+ export {
31
+ isMcpDescribableArg,
32
+ type McpExposureEndpoint,
33
+ type McpExposureOption,
34
+ mcpBaseVerbOf,
35
+ mcpHintsOf,
36
+ mcpPromptRefusalOf,
37
+ mcpRefusalOf,
38
+ } from "./mcpExposure";
30
39
  export { mergeVersion } from "./mergeVersion";
31
40
  export { objectify } from "./objectify";
32
41
  export { pathGet } from "./pathGet";
@@ -36,12 +45,17 @@ export { randomPicks } from "./randomPicks";
36
45
  export {
37
46
  assertUniqueRoutePatterns,
38
47
  compareRouteSpecificity,
48
+ getRouteExports,
39
49
  isRouteSourceFile,
40
50
  isSpecialRouteLeaf,
51
+ LAYOUT_ROUTE_EXPORTS,
41
52
  matchRoutePattern,
42
53
  normalizeRoutePattern,
54
+ PAGE_ROUTE_EXPORTS,
43
55
  type ParsedRouteModuleKey,
44
56
  parseRouteModuleKey,
57
+ RESERVED_ROUTE_CONFIG_EXPORTS,
58
+ ROOT_LAYOUT_ROUTE_EXPORTS,
45
59
  type RouteModuleKind,
46
60
  routeSegmentToPatternPart,
47
61
  routeSegmentToTreePath,
@@ -0,0 +1,99 @@
1
+ import { capitalize } from "./capitalize";
2
+
3
+ /**
4
+ * What MCP says about one endpoint: whether it is published, why it is not, and the hints it carries.
5
+ *
6
+ * Structurally typed like the rest of `common/` so the same rules answer on both sides — the server builds its
7
+ * catalogue from them and the browser API explorer badges an endpoint from them. A second implementation would
8
+ * eventually disagree, and an audit surface that disagrees with the catalogue is worse than none.
9
+ *
10
+ * Every rejection returns the sentence an author reads, at boot in the server log and in the explorer. Fail-closed
11
+ * with no reason leaves an author whose endpoint is missing from the catalogue nowhere to look but the source.
12
+ */
13
+ export interface McpExposureEndpoint {
14
+ type: string;
15
+ returns: { refName: string };
16
+ args: { name: string; refName: string; type: string; arrDepth?: number; nullable?: boolean }[];
17
+ guards?: string[];
18
+ fileUpload?: boolean;
19
+ }
20
+
21
+ export interface McpExposureOption {
22
+ /**
23
+ * The read-only deployment valve, which is server configuration. The browser explorer cannot know it and so
24
+ * badges what the code decided; the boot log is where a read-only deployment says what it dropped.
25
+ */
26
+ readOnly?: boolean;
27
+ }
28
+
29
+ /** `Any` publishes as the empty schema, which tells a model nothing — so it is left out rather than described. */
30
+ export const isMcpDescribableArg = (arg: { refName: string }) => arg.refName !== "Any";
31
+
32
+ /** Which CRUD verb a generated endpoint key is, or `null` when the key is not one of the five. */
33
+ export const mcpBaseVerbOf = (refName: string, key: string) => {
34
+ const cap = capitalize(refName);
35
+ if (key === refName || key === `light${cap}`) return "get" as const;
36
+ if (key === `create${cap}`) return "create" as const;
37
+ if (key === `update${cap}`) return "update" as const;
38
+ if (key === `remove${cap}`) return "remove" as const;
39
+ return null;
40
+ };
41
+
42
+ /**
43
+ * The hints a client renders beside a tool. Hints only — clients are told to distrust them, so they inform a UI
44
+ * and never stand in for a guard. `openWorldHint` is always false: every endpoint reaches this app's own
45
+ * database, not the wider internet.
46
+ */
47
+ export const mcpHintsOf = (key: string, endpoint: { type: string }) => {
48
+ const readOnly = endpoint.type === "query";
49
+ const destructive = !readOnly && /^(remove|delete)/.test(key);
50
+ return {
51
+ readOnlyHint: readOnly,
52
+ destructiveHint: destructive,
53
+ idempotentHint: readOnly || /^(set|update)/.test(key),
54
+ openWorldHint: false,
55
+ };
56
+ };
57
+
58
+ /** The sentence explaining why this endpoint is not in the catalogue, or `null` when it is. */
59
+ export const mcpRefusalOf = (endpoint: McpExposureEndpoint, { readOnly }: McpExposureOption = {}): string | null => {
60
+
61
+ if (!endpoint.guards?.length)
62
+ return "it declares no guards, and exposure follows them — write `guards: [Public]` if anonymous access is the intent.";
63
+ if (endpoint.type === "prompt") return mcpPromptRefusalOf(endpoint);
64
+ if (endpoint.type === "pubsub" || endpoint.type === "message")
65
+ return `\`${endpoint.type}\` rides the websocket, and its internal arguments read a socket an MCP request does not have.`;
66
+ if (readOnly && endpoint.type !== "query")
67
+ return "this deployment is read-only, which drops every endpoint that is not a query.";
68
+ if (endpoint.returns.refName === "Any" || endpoint.returns.refName === "Upload")
69
+ return `a return typed \`${endpoint.returns.refName}\` cannot be described to a model.`;
70
+ if (endpoint.fileUpload || endpoint.args.some((arg) => arg.refName === "Upload"))
71
+ return "a file upload has no MCP representation.";
72
+ if (endpoint.type === "mutation" && !endpoint.guards.some((name) => name !== "Public"))
73
+ return "a mutation needs a real guard — `[Public]` is having none, spelled out.";
74
+ const opaque = endpoint.args.find((arg) => !isMcpDescribableArg(arg) && arg.type !== "search" && !arg.nullable);
75
+ if (opaque)
76
+ return `its required argument \`${opaque.name}\` is typed \`Any\`, which is left out of the published schema — expose a named filter slice instead.`;
77
+ return null;
78
+ };
79
+
80
+ /**
81
+ * A prompt is a read exposed on the same terms as a query, so every rejection here is one thing: an argument
82
+ * `prompts/get` cannot carry. Its `arguments` is a flat string map — one string per name, and no schema beside it
83
+ * — which rules out the argument *kinds* the builder already refuses and, just as surely, two argument *types* it
84
+ * accepts. A tool escapes both because it publishes a real JSON Schema.
85
+ */
86
+ export const mcpPromptRefusalOf = (endpoint: McpExposureEndpoint): string | null => {
87
+ const carried = endpoint.args.find((arg) => arg.type === "body" || arg.type === "msg" || arg.type === "room");
88
+ if (carried)
89
+ return `a prompt's arguments travel as a flat string map, so its \`${carried.type}\` argument \`${carried.name}\` cannot be carried.`;
90
+
91
+ const list = endpoint.args.find((arg) => arg.arrDepth);
92
+ if (list)
93
+ return `a prompt argument is one string, so its list argument \`${list.name}\` could never carry more than one value.`;
94
+
95
+ const opaque = endpoint.args.find((arg) => !isMcpDescribableArg(arg));
96
+ if (opaque)
97
+ return `its argument \`${opaque.name}\` is typed \`Any\`, and a prompt has no schema in which to describe one.`;
98
+ return null;
99
+ };
package/common/pathSet.ts CHANGED
@@ -1,16 +1,28 @@
1
1
  type MutableIndexable = Record<string | number, unknown>;
2
2
  type PathSegment = string | number;
3
+ type Container = MutableIndexable | Map<PathSegment, unknown>;
3
4
 
4
5
  const toPathSegments = (path: string | readonly PathSegment[]) =>
5
6
  Array.isArray(path) ? [...path] : path.toString().match(/[^.[\]]+/g) || [];
6
7
 
8
+ const readChild = (container: Container, key: PathSegment) =>
9
+ container instanceof Map ? container.get(key) : container[key];
10
+
11
+ const writeChild = (container: Container, key: PathSegment, value: unknown) => {
12
+ if (container instanceof Map) container.set(key, value);
13
+ else container[key] = value;
14
+ };
15
+
7
16
  export const pathSet = <T>(obj: T, path: string | readonly PathSegment[], value: unknown): T => {
8
17
  if (Object(obj) !== obj) return obj;
9
18
  const pathSegments = toPathSegments(path);
10
- pathSegments.slice(0, -1).reduce<MutableIndexable>((a, c, i) => {
11
- if (Object(a[c]) === a[c]) return a[c] as MutableIndexable;
12
- a[c] = Math.abs(Number(pathSegments[i + 1])) >> 0 === +pathSegments[i + 1] ? [] : {};
13
- return a[c] as MutableIndexable;
14
- }, obj as MutableIndexable)[pathSegments[pathSegments.length - 1]] = value;
19
+ const parent = pathSegments.slice(0, -1).reduce<Container>((a, c, i) => {
20
+ const child = readChild(a, c);
21
+ if (Object(child) === child) return child as Container;
22
+ const created = Math.abs(Number(pathSegments[i + 1])) >> 0 === +pathSegments[i + 1] ? [] : {};
23
+ writeChild(a, c, created);
24
+ return created as unknown as Container;
25
+ }, obj as Container);
26
+ writeChild(parent, pathSegments[pathSegments.length - 1], value);
15
27
  return obj;
16
28
  };
@@ -9,6 +9,36 @@ const DIRECTORY_SCOPED_LEAVES = new Set(["_layout", "_index", "_overrides"]);
9
9
 
10
10
  export type RouteModuleKind = "page" | "layout" | "overrides";
11
11
 
12
+ export const PAGE_ROUTE_EXPORTS: ReadonlySet<string> = new Set([
13
+ "default",
14
+ "pageConfig",
15
+ "head",
16
+ "metadata",
17
+ "generateHead",
18
+ "generateMetadata",
19
+ "Loading",
20
+ ]);
21
+ export const LAYOUT_ROUTE_EXPORTS: ReadonlySet<string> = new Set([...PAGE_ROUTE_EXPORTS, "NotFound", "Error"]);
22
+ export const ROOT_LAYOUT_ROUTE_EXPORTS: ReadonlySet<string> = new Set([
23
+ ...LAYOUT_ROUTE_EXPORTS,
24
+ "fonts",
25
+ "manifest",
26
+ "theme",
27
+ "reconnect",
28
+ "wsConnect",
29
+ "layoutStyle",
30
+ "gaTrackingId",
31
+ ]);
32
+ /** Root-layout exports that are plain config rather than components, so a PascalCase check cannot allow them. */
33
+ export const RESERVED_ROUTE_CONFIG_EXPORTS: ReadonlySet<string> = new Set(
34
+ [...ROOT_LAYOUT_ROUTE_EXPORTS].filter((name) => name !== "default" && !/^[A-Z]/.test(name)),
35
+ );
36
+
37
+ export function getRouteExports(kind: "page" | "layout", { rootLayout = false } = {}): ReadonlySet<string> {
38
+ if (kind === "page") return PAGE_ROUTE_EXPORTS;
39
+ return rootLayout ? ROOT_LAYOUT_ROUTE_EXPORTS : LAYOUT_ROUTE_EXPORTS;
40
+ }
41
+
12
42
  export interface ParsedRouteModuleKey {
13
43
  key: string;
14
44
  kind: RouteModuleKind;
@@ -1,32 +1,103 @@
1
+ import { type Cls, PrimitiveRegistry, type PrimitiveScalar } from "akanjs/base";
1
2
  import type { ConstantField, FieldObject } from "./fieldInfo";
2
3
  import type { ConstantModelRef } from "./via";
3
4
 
4
- /** What happens to the documents a relation field points at when the owner is removed. */
5
- export const cascadeActions = ["remove"] as const;
5
+ /**
6
+ * Which end of a relation goes away with the other. `removeRef` removes what the field points at when this
7
+ * document is removed; `removeWith` removes this document when what the field points at is removed. The two
8
+ * read identically on a relation field, so the value has to name the direction — a mistake here is a data loss.
9
+ */
10
+ export const cascadeActions = ["removeRef", "removeWith"] as const;
6
11
  export type CascadeAction = (typeof cascadeActions)[number];
7
12
 
13
+ /** How a `removeWith` field names the owner whose removal takes this document with it. */
14
+ export interface CascadeWithPath {
15
+ readonly key: string;
16
+ /** Set when the field is a relation. Resolved to a refName later: the owner may not be registered yet. */
17
+ readonly modelRef: ConstantModelRef | null;
18
+ /** Set when the field declares `ref`, which names the owner at declaration. */
19
+ readonly refName: string | null;
20
+ /** Set when the field declares `refPath`: the sibling field holding the owner's refName. */
21
+ readonly typeKey: string | null;
22
+ /** The refNames `typeKey` may hold. Empty unless the field is polymorphic. */
23
+ readonly typeValues: readonly string[];
24
+ }
25
+
26
+ const idNames = new Set(["ID", "String"]);
27
+
8
28
  export class CascadePaths {
9
- /** Field key → the model its ids point at. Resolved to a refName later: the target may not be registered yet. */
10
- readonly remove = new Map<string, ConstantModelRef>();
29
+ /** Field key → the model its ids point at, removed when this document is. */
30
+ readonly removeRef = new Map<string, ConstantModelRef>();
31
+ /** Field key → the owner whose removal removes this document. */
32
+ readonly removeWith = new Map<string, CascadeWithPath>();
11
33
 
12
34
  collect(fieldMap: FieldObject) {
13
35
  for (const [key, field] of Object.entries(fieldMap)) {
14
36
  if (!field.cascade) continue;
15
- this.#assertCascadable(key, field.cascade, field);
16
- this.remove.set(key, field.modelRef);
37
+ this.#assertKnownAction(key, field.cascade);
38
+ if (field.cascade === "removeRef") this.removeRef.set(key, this.#readOwnedRelation(key, field));
39
+ else this.removeWith.set(key, this.#readOwnerPath(key, field, fieldMap));
17
40
  }
18
41
  return this;
19
42
  }
20
43
 
21
- #assertCascadable(key: string, action: CascadeAction, field: ConstantField) {
22
-
44
+ #assertKnownAction(key: string, action: CascadeAction) {
45
+
23
46
  if (!cascadeActions.includes(action)) {
24
47
  throw new Error(`Cascade field "${key}" declares cascade: "${action}", which is not one of ${cascadeActions}`);
25
48
  }
49
+ }
50
+
51
+ #readOwnedRelation(key: string, field: ConstantField) {
26
52
 
27
53
  if (!field.isClass || field.isScalar) {
28
54
  throw new Error(`Cascade field "${key}" is not a model reference and has no document to remove`);
29
55
  }
30
56
  if (field.arrDepth > 1) throw new Error(`Cascade field "${key}" is a nested array and cannot cascade`);
57
+ return field.modelRef;
58
+ }
59
+
60
+ #readOwnerPath(key: string, field: ConstantField, fieldMap: FieldObject): CascadeWithPath {
61
+
62
+ if (field.arrDepth > 0) throw new Error(`Cascade field "${key}" is an array and names more than one owner`);
63
+ if (field.isMap) throw new Error(`Cascade field "${key}" is a Map and names no owner`);
64
+ if (field.refPath) return this.#readPolymorphicOwner(key, field, fieldMap);
65
+ if (field.ref) {
66
+ this.#assertHoldsId(key, field);
67
+ return { key, modelRef: null, refName: field.ref, typeKey: null, typeValues: [] };
68
+ }
69
+ if (field.isClass && !field.isScalar) {
70
+ return { key, modelRef: field.modelRef, refName: null, typeKey: null, typeValues: [] };
71
+ }
72
+ throw new Error(
73
+ `Cascade field "${key}" declares cascade: "removeWith" but names no owner; make it a model reference, ` +
74
+ `or add ref: "<model>" / refPath: "<typeField>"`,
75
+ );
76
+ }
77
+
78
+ #readPolymorphicOwner(key: string, field: ConstantField, fieldMap: FieldObject): CascadeWithPath {
79
+ if (field.ref) throw new Error(`Cascade field "${key}" declares both ref and refPath; keep one`);
80
+ this.#assertHoldsId(key, field);
81
+ const typeKey = field.refPath as string;
82
+ const typeField = fieldMap[typeKey];
83
+ if (!typeField) throw new Error(`Cascade field "${key}" declares refPath: "${typeKey}", which is not a field`);
84
+
85
+ if (!typeField.enum) {
86
+ throw new Error(
87
+ `Cascade field "${key}" declares refPath: "${typeKey}", which must be an enumOf(...) naming the owner ` +
88
+ `refNames it may hold`,
89
+ );
90
+ }
91
+ const typeValues = typeField.enum.values.map((value) => String(value));
92
+ return { key, modelRef: null, refName: null, typeKey, typeValues };
93
+ }
94
+
95
+ #assertHoldsId(key: string, field: ConstantField) {
96
+ const modelRef = field.modelRef as unknown as Cls;
97
+ const refName = PrimitiveRegistry.has(modelRef)
98
+ ? PrimitiveRegistry.getName(modelRef as unknown as typeof PrimitiveScalar)
99
+ : null;
100
+ if (refName && idNames.has(refName)) return;
101
+ throw new Error(`Cascade field "${key}" declares ref or refPath and must hold an ID`);
31
102
  }
32
103
  }
@@ -30,8 +30,10 @@ export const crystalize = (field: FieldProps, value: unknown): unknown => {
30
30
  isArray: false,
31
31
  arrDepth: 0,
32
32
  };
33
+
34
+ const entries = value instanceof Map ? [...value.entries()] : Object.entries(value as Record<string, unknown>);
33
35
  return new Map(
34
- Object.entries(value as Record<string, unknown>).map(([key, val]) => [
36
+ entries.map(([key, val]: [string, unknown]) => [
35
37
  key,
36
38
  field.of
37
39
  ? applyFnToArrayObjects(val, (v: never) => crystalize(mapValueField, v))
@@ -450,7 +450,13 @@ export class ConstantField<
450
450
  get isMap() {
451
451
  return (this.modelRef as Cls) === Map;
452
452
  }
453
+
454
+ #props: FieldProps | null = null;
453
455
  getProps(): FieldProps {
456
+ this.#props ??= Object.freeze(this.#buildProps());
457
+ return this.#props;
458
+ }
459
+ #buildProps(): FieldProps {
454
460
  return {
455
461
  nullable: this.nullable as unknown as boolean,
456
462
  ref: this.ref,
@@ -2,17 +2,45 @@ import { DEFAULT_VALUE, FIELD_META, type PrimitiveScalar } from "akanjs/base";
2
2
  import type { FieldObject } from ".";
3
3
  import type { DefaultOf } from "./types";
4
4
 
5
+ interface DefaultPlan {
6
+ /** Fields whose default is a value that can be shared: a primitive, `null`, or the field's own literal. */
7
+ shared: Record<string, unknown>;
8
+ /** Fields that have to be produced per call — a thunk, a fresh array, or a nested scalar record. */
9
+ perCall: [key: string, make: () => unknown][];
10
+ }
11
+
12
+ const planCache = new WeakMap<FieldObject, DefaultPlan>();
13
+
14
+ /**
15
+ * The split is what keeps this faithful: `default: () => dayjs()` still means "now" on every call, and an array
16
+ * or nested-scalar default is still a fresh object, so two documents filled from the same model never end up
17
+ * sharing one. Only values that were already shared before this cache existed live in `shared`.
18
+ */
5
19
  export const getDefault = <T>(fieldObj: FieldObject): DefaultOf<T> => {
6
- const result: Record<string, unknown> = {};
20
+ let plan = planCache.get(fieldObj);
21
+ if (!plan) {
22
+ plan = buildPlan(fieldObj);
23
+ planCache.set(fieldObj, plan);
24
+ }
25
+ const result: Record<string, unknown> = { ...plan.shared };
26
+ for (const [key, make] of plan.perCall) result[key] = make();
27
+ return result as DefaultOf<T>;
28
+ };
29
+
30
+ const buildPlan = (fieldObj: FieldObject): DefaultPlan => {
31
+ const shared: Record<string, unknown> = {};
32
+ const perCall: [string, () => unknown][] = [];
7
33
  for (const [key, field] of Object.entries(fieldObj)) {
8
- if (field.fieldType === "hidden" || field.fieldType === "secret") result[key] = null;
34
+ if (field.fieldType === "hidden" || field.fieldType === "secret") shared[key] = null;
9
35
  else if (field.default !== undefined && field.default !== null) {
10
- if (typeof field.default === "function") result[key] = (field.default as () => object)();
11
- else result[key] = field.default as object;
12
- } else if (field.isArray) result[key] = [];
13
- else if (field.nullable) result[key] = null;
14
- else if (field.isClass) result[key] = field.isScalar ? getDefault(field.modelRef[FIELD_META]) : null;
15
- else result[key] = (field.modelRef as unknown as typeof PrimitiveScalar)[DEFAULT_VALUE];
36
+ if (typeof field.default === "function") perCall.push([key, field.default as () => unknown]);
37
+ else shared[key] = field.default as object;
38
+ } else if (field.isArray) perCall.push([key, () => []]);
39
+ else if (field.nullable) shared[key] = null;
40
+ else if (field.isClass) {
41
+ if (field.isScalar) perCall.push([key, () => getDefault(field.modelRef[FIELD_META])]);
42
+ else shared[key] = null;
43
+ } else shared[key] = (field.modelRef as unknown as typeof PrimitiveScalar)[DEFAULT_VALUE];
16
44
  }
17
- return result as DefaultOf<T>;
45
+ return { shared, perCall };
18
46
  };
@@ -9,7 +9,7 @@ export const immerify = <T extends object>(modelRef: ConstantModelRef, objOrArr:
9
9
  }) as Record<string, unknown>;
10
10
  const objRecord = objOrArr as Record<string, unknown>;
11
11
  Object.entries(modelRef[FIELD_META]).forEach(([key, field]) => {
12
- if (field.isScalar && field.isClass && !!objRecord[key])
12
+ if (field.isScalar && field.isClass && objRecord[key])
13
13
  immeredObj[key] = immerify(field.modelRef, objRecord[key] as object);
14
14
  });
15
15
  return immeredObj as T;
package/constant/index.ts CHANGED
@@ -5,6 +5,8 @@ export * from "./deserialize";
5
5
  export * from "./fieldInfo";
6
6
  export * from "./getDefault";
7
7
  export * from "./immerify";
8
+ export * from "./labelOf";
9
+ export * from "./mask";
8
10
  export * from "./purify";
9
11
  export * from "./serialize";
10
12
  export * from "./textFieldPathSet";
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The one line a human scans for, derived from what the model already declared: the `text: "title"` search role
3
+ * names exactly that field, so an agent-facing label costs no new declaration. Falls back to the conventional
4
+ * `title`/`name` keys; the id is the caller's floor.
5
+ */
6
+ export const labelOf = (model: unknown, value: unknown): string | undefined => {
7
+ if (!value || typeof value !== "object") return undefined;
8
+ const source = value as Record<string, unknown>;
9
+ const paths = (model as { text?: { title?: Iterable<string> } } | null)?.text?.title;
10
+ const titlePath = [...(paths ?? [])].find((path) => !path.includes(".") && !path.includes("["));
11
+ for (const key of [titlePath, "title", "name"]) {
12
+ if (!key) continue;
13
+ const candidate = source[key];
14
+ if (typeof candidate === "string" && candidate) return candidate;
15
+ }
16
+ return undefined;
17
+ };