akanjs 3.0.0-alpha.7 → 3.0.0-alpha.71

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 (719) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/README.ko.md +1 -1
  3. package/README.md +1 -1
  4. package/base/baseEnv.ts +7 -4
  5. package/base/primitiveRegistry.ts +59 -12
  6. package/base/symbols.ts +4 -0
  7. package/client/capacitor.ts +34 -0
  8. package/client/clientRuntime.ts +5 -0
  9. package/client/csrTypes.ts +4 -3
  10. package/client/index.ts +1 -0
  11. package/client/locale.ts +2 -2
  12. package/client/router.ts +7 -7
  13. package/client/sharedContext.ts +31 -0
  14. package/client/translator.ts +2 -2
  15. package/client/types.ts +3 -3
  16. package/common/Logger.ts +280 -67
  17. package/common/clientAddress.ts +40 -0
  18. package/common/deepObjectify.ts +24 -9
  19. package/common/index.ts +42 -1
  20. package/common/logContext.ts +27 -0
  21. package/common/mcpExposure.ts +114 -0
  22. package/common/pathGetLoose.ts +31 -0
  23. package/common/pathSet.ts +17 -5
  24. package/common/plainFieldsOf.ts +13 -0
  25. package/common/routeConvention.ts +22 -12
  26. package/common/websocketBinaryFrame.ts +46 -0
  27. package/constant/crystalize.ts +94 -28
  28. package/constant/dateSlot.ts +62 -0
  29. package/constant/deserialize.ts +3 -2
  30. package/constant/fieldInfo.ts +43 -3
  31. package/constant/fieldQueryMeta.ts +35 -0
  32. package/constant/getDefault.ts +16 -11
  33. package/constant/hydrationPlan.ts +72 -0
  34. package/constant/immerify.ts +4 -6
  35. package/constant/index.ts +5 -0
  36. package/constant/labelOf.ts +26 -0
  37. package/constant/mask.ts +67 -0
  38. package/constant/purify.ts +17 -11
  39. package/constant/textFieldPaths.ts +13 -7
  40. package/constant/types.ts +19 -13
  41. package/constant/via.ts +24 -17
  42. package/dictionary/DictionaryLookup.ts +30 -0
  43. package/dictionary/agent.dictionary.ts +31 -0
  44. package/dictionary/agentTurn.dictionary.ts +29 -0
  45. package/dictionary/base.dictionary.ts +81 -0
  46. package/dictionary/dictInfo.ts +11 -2
  47. package/dictionary/dictionary.ts +9 -3
  48. package/dictionary/index.ts +1 -0
  49. package/dictionary/trans.ts +2 -2
  50. package/document/documentQuery.ts +1 -0
  51. package/document/filterMeta.ts +77 -12
  52. package/document/index.ts +1 -0
  53. package/document/noDocumentError.ts +12 -0
  54. package/document/types.ts +0 -1
  55. package/fetch/agentTurn.ts +19 -0
  56. package/fetch/client/fetchClient.ts +137 -37
  57. package/fetch/client/httpClient.ts +95 -20
  58. package/fetch/client/wsClient.ts +27 -12
  59. package/fetch/fetchType/appliedReturn.type.ts +65 -44
  60. package/fetch/fetchType/endpointFetch.type.ts +17 -8
  61. package/fetch/fetchType/sliceFetch.type.ts +27 -50
  62. package/fetch/index.ts +1 -0
  63. package/index.ts +80 -6
  64. package/local/apps/akan/akan-local.db +0 -0
  65. package/local/apps/akan/akan-local.db-shm +0 -0
  66. package/local/apps/akan/akan-local.db-wal +0 -0
  67. package/local/apps/akan/akan-local_solid.db +0 -0
  68. package/local/apps/akan/akan-local_solid.db-shm +0 -0
  69. package/local/apps/akan/akan-local_solid.db-wal +0 -0
  70. package/local/apps/serverLifecycle/serverLifecycle-local.db +0 -0
  71. package/local/apps/serverLifecycle/serverLifecycle-local.db-shm +0 -0
  72. package/local/apps/serverLifecycle/serverLifecycle-local.db-wal +0 -0
  73. package/local/apps/serverLifecycle/serverLifecycle-local_solid.db +0 -0
  74. package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-shm +0 -0
  75. package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-wal +0 -0
  76. package/package.json +27 -18
  77. package/server/akanApp.ts +278 -138
  78. package/server/akanAppHeaders.ts +16 -2
  79. package/server/akanOption.ts +63 -8
  80. package/server/akanServer.ts +387 -32
  81. package/server/animatedImage.ts +83 -0
  82. package/server/assetEncoding.ts +4 -24
  83. package/server/binaryPubsub.ts +55 -0
  84. package/server/console.ts +110 -101
  85. package/server/consoleEvaluator.ts +51 -0
  86. package/server/consolePasteFilter.ts +91 -0
  87. package/server/consoleSession.ts +242 -0
  88. package/server/contentEncoding.ts +83 -0
  89. package/server/devtools/signalSerializer.ts +2 -2
  90. package/server/devtools/types.ts +4 -4
  91. package/server/di/diLifecycle.ts +123 -13
  92. package/server/di/predefinedAdaptor.ts +6 -0
  93. package/server/di/utils.ts +40 -0
  94. package/server/imageOptimizer.ts +154 -57
  95. package/server/lifecycle/runtimeDir.ts +14 -0
  96. package/server/lifecycle/shutdownManager.ts +1 -1
  97. package/server/logging/childOutputReader.ts +137 -0
  98. package/server/logging/hubFileSink.ts +39 -0
  99. package/server/logging/logControlSocket.ts +173 -0
  100. package/server/logging/logForwarder.ts +131 -0
  101. package/server/logging/logHub.ts +0 -0
  102. package/server/logging/logQuery.ts +130 -0
  103. package/server/logging/logStdoutWriter.ts +39 -0
  104. package/server/logging/logStreamRoute.ts +87 -0
  105. package/server/logging/logTailClient.ts +161 -0
  106. package/server/mcp/McpAuth.ts +177 -0
  107. package/server/mcp/McpDispatcher.ts +289 -0
  108. package/server/mcp/McpEventStream.ts +24 -0
  109. package/server/mcp/McpExecutionContext.ts +105 -0
  110. package/server/mcp/McpRouter.ts +621 -0
  111. package/server/mcp/index.ts +5 -0
  112. package/server/processMetricsCollector.ts +1 -1
  113. package/server/resolver/database.resolver.ts +5 -4
  114. package/server/resolver/signal.resolver.ts +208 -86
  115. package/server/routeTreeBuilder.ts +10 -8
  116. package/server/routing/apiRouter.ts +44 -14
  117. package/server/routing/appWsData.ts +24 -2
  118. package/server/routing/eventStream.ts +93 -0
  119. package/server/routing/soloAppRoutes.ts +50 -0
  120. package/server/rscWorker.tsx +36 -22
  121. package/server/rscWorkerHost.ts +59 -8
  122. package/server/semaphore.ts +22 -0
  123. package/server/subRouteIndexDocument.tsx +61 -0
  124. package/server/systemPageDocument.tsx +3 -3
  125. package/server/systemPages.tsx +49 -16
  126. package/server/types.tsx +28 -0
  127. package/server/vendor/akanjs-fetch.ts +1 -0
  128. package/server/webRouter.ts +96 -39
  129. package/service/adapt.ts +4 -4
  130. package/service/agent.service.ts +81 -0
  131. package/service/base.service.ts +2 -1
  132. package/service/index.ts +1 -0
  133. package/service/injectInfo.ts +8 -3
  134. package/service/ipcTypes.ts +6 -0
  135. package/service/predefinedAdaptor/compress.adaptor.ts +5 -1
  136. package/service/predefinedAdaptor/database.adaptor.ts +68 -37
  137. package/service/predefinedAdaptor/deepseekLlm.ts +271 -0
  138. package/service/predefinedAdaptor/index.ts +3 -0
  139. package/service/predefinedAdaptor/insightQuery.ts +183 -0
  140. package/service/predefinedAdaptor/llm.adaptor.ts +115 -0
  141. package/service/predefinedAdaptor/logging.adaptor.ts +1 -1
  142. package/service/predefinedAdaptor/queue.adaptor.ts +5 -2
  143. package/service/predefinedAdaptor/role.adaptor.ts +2 -0
  144. package/service/predefinedAdaptor/schedule.adaptor.ts +12 -5
  145. package/service/predefinedAdaptor/solidPubsub.adaptor.ts +10 -6
  146. package/service/predefinedAdaptor/solidQueue.adaptor.ts +6 -2
  147. package/service/predefinedAdaptor/solidSqlite.ts +11 -9
  148. package/service/predefinedAdaptor/websocket.adaptor.ts +6 -1
  149. package/service/serve.ts +16 -9
  150. package/service/toolNames.ts +119 -0
  151. package/signal/agent/AgentCatalogue.ts +165 -0
  152. package/signal/agent/index.ts +1 -0
  153. package/signal/agent.signal.ts +38 -0
  154. package/signal/agentTurn.ts +8 -0
  155. package/signal/agentTurnStream.ts +60 -0
  156. package/signal/base.signal.ts +2 -1
  157. package/signal/endpointInfo.ts +38 -2
  158. package/signal/guard.ts +28 -1
  159. package/signal/guards.ts +49 -1
  160. package/signal/index.ts +6 -0
  161. package/signal/intercept.ts +4 -4
  162. package/signal/internalArg.ts +21 -4
  163. package/signal/mcp/McpDocument.ts +326 -0
  164. package/signal/mcp/McpProgress.ts +106 -0
  165. package/signal/mcp/McpUriTemplate.ts +80 -0
  166. package/signal/mcp/Msg.ts +368 -0
  167. package/signal/mcp/index.ts +5 -0
  168. package/signal/mcp/mcpProtocol.ts +120 -0
  169. package/signal/middleware.ts +3 -3
  170. package/signal/openapi/openapi.ts +36 -173
  171. package/signal/schema/JsonSchemaBuilder.ts +221 -0
  172. package/signal/schema/index.ts +1 -0
  173. package/signal/serializer/fetch.serializer.ts +51 -0
  174. package/signal/signalContext.ts +324 -76
  175. package/signal/slice.ts +62 -27
  176. package/signal/trace.ts +268 -9
  177. package/signal/types.ts +55 -4
  178. package/store/action.ts +34 -41
  179. package/store/actionTag.ts +33 -0
  180. package/store/agent/AgentBridge.ts +87 -0
  181. package/store/agent/AgentContext.ts +71 -0
  182. package/store/agent/AgentPrompts.ts +111 -0
  183. package/store/agent/ScreenReader.ts +349 -0
  184. package/store/agent/ScreenSettle.ts +45 -0
  185. package/store/agent/ScreenTarget.ts +135 -0
  186. package/store/agent/StoreCatalogue.ts +116 -0
  187. package/store/agent/StoreSurfaceSource.ts +225 -0
  188. package/store/agent/index.ts +13 -0
  189. package/store/agent/storeSurface.ts +28 -0
  190. package/store/agent/types.ts +16 -0
  191. package/store/agentic/AgentValue.ts +119 -0
  192. package/store/agentic/StExposeBuilder.ts +47 -0
  193. package/store/agentic/StExposeDraft.ts +24 -0
  194. package/store/agentic/StStateBuilder.ts +85 -0
  195. package/store/agentic/StStateDraft.ts +23 -0
  196. package/store/agentic/StToolBuilder.ts +279 -0
  197. package/store/agentic/StToolDraft.ts +22 -0
  198. package/store/agentic/attachAgentic.ts +33 -0
  199. package/store/agentic/formFields.ts +194 -0
  200. package/store/agentic/index.ts +12 -0
  201. package/store/agentic/useFieldTool.ts +183 -0
  202. package/store/agentic/useFormTools.ts +77 -0
  203. package/store/agentic/useRelationFieldTool.ts +113 -0
  204. package/store/baseSt.ts +1 -1
  205. package/store/databaseStateNames.ts +31 -0
  206. package/store/formSetterNames.ts +35 -0
  207. package/store/index.ts +8 -0
  208. package/store/rootStore.ts +3 -1
  209. package/store/sliceRole.ts +36 -0
  210. package/store/state.ts +2 -12
  211. package/store/store.ts +9 -0
  212. package/store/storeInstance.ts +185 -20
  213. package/store/storeRegistry.ts +39 -1
  214. package/store/types.ts +5 -0
  215. package/store/withSelector.ts +5 -4
  216. package/test/index.ts +1 -1
  217. package/test/registerDom.ts +4 -0
  218. package/test/sampleOf.ts +2 -0
  219. package/test/signalTestRuntime.ts +5 -5
  220. package/test/testServer.ts +14 -11
  221. package/types/base/baseEnv.d.ts +1 -1
  222. package/types/base/primitiveRegistry.d.ts +20 -8
  223. package/types/base/symbols.d.ts +4 -0
  224. package/types/client/capacitor.d.ts +39 -0
  225. package/types/client/clientRuntime.d.ts +7 -0
  226. package/types/client/index.d.ts +1 -0
  227. package/types/client/sharedContext.d.ts +21 -0
  228. package/types/client/types.d.ts +5 -3
  229. package/types/common/Logger.d.ts +88 -6
  230. package/types/common/clientAddress.d.ts +19 -0
  231. package/types/common/deepObjectify.d.ts +4 -2
  232. package/types/common/index.d.ts +8 -2
  233. package/types/common/logContext.d.ts +17 -0
  234. package/types/common/mcpExposure.d.ts +64 -0
  235. package/types/common/pathGetLoose.d.ts +8 -0
  236. package/types/common/plainFieldsOf.d.ts +6 -0
  237. package/types/common/routeConvention.d.ts +6 -0
  238. package/types/common/websocketBinaryFrame.d.ts +17 -0
  239. package/types/constant/constantRegistry.d.ts +2 -10
  240. package/types/constant/crystalize.d.ts +5 -0
  241. package/types/constant/dateSlot.d.ts +14 -0
  242. package/types/constant/fieldInfo.d.ts +20 -3
  243. package/types/constant/fieldQueryMeta.d.ts +17 -0
  244. package/types/constant/getDefault.d.ts +8 -0
  245. package/types/constant/hydrationPlan.d.ts +24 -0
  246. package/types/constant/index.d.ts +5 -0
  247. package/types/constant/labelOf.d.ts +7 -0
  248. package/types/constant/mask.d.ts +41 -0
  249. package/types/constant/purify.d.ts +2 -2
  250. package/types/constant/types.d.ts +5 -5
  251. package/types/dictionary/DictionaryLookup.d.ts +14 -0
  252. package/types/dictionary/agent.dictionary.d.ts +1 -0
  253. package/types/dictionary/agentTurn.dictionary.d.ts +1 -0
  254. package/types/dictionary/base.dictionary.d.ts +1 -1
  255. package/types/dictionary/dictInfo.d.ts +7 -1
  256. package/types/dictionary/dictionary.d.ts +11 -9
  257. package/types/dictionary/index.d.ts +1 -0
  258. package/types/document/filterMeta.d.ts +24 -4
  259. package/types/document/index.d.ts +1 -0
  260. package/types/document/noDocumentError.d.ts +12 -0
  261. package/types/document/types.d.ts +0 -1
  262. package/types/fetch/agentTurn.d.ts +475 -0
  263. package/types/fetch/client/fetchClient.d.ts +12 -0
  264. package/types/fetch/client/httpClient.d.ts +2 -1
  265. package/types/fetch/fetchType/appliedReturn.type.d.ts +37 -18
  266. package/types/fetch/fetchType/endpointFetch.type.d.ts +8 -5
  267. package/types/fetch/fetchType/sliceFetch.type.d.ts +11 -15
  268. package/types/fetch/index.d.ts +1 -0
  269. package/types/index.d.ts +74 -10
  270. package/types/server/akanApp.d.ts +12 -0
  271. package/types/server/akanAppHeaders.d.ts +7 -1
  272. package/types/server/akanOption.d.ts +36 -6
  273. package/types/server/akanServer.d.ts +67 -9
  274. package/types/server/animatedImage.d.ts +7 -0
  275. package/types/server/assetEncoding.d.ts +1 -1
  276. package/types/server/binaryPubsub.d.ts +18 -0
  277. package/types/server/console.d.ts +11 -1
  278. package/types/server/consoleEvaluator.d.ts +2 -0
  279. package/types/server/consolePasteFilter.d.ts +11 -0
  280. package/types/server/consoleSession.d.ts +22 -0
  281. package/types/server/contentEncoding.d.ts +28 -0
  282. package/types/server/devtools/types.d.ts +4 -4
  283. package/types/server/di/diLifecycle.d.ts +10 -2
  284. package/types/server/di/predefinedAdaptor.d.ts +4 -1
  285. package/types/server/di/utils.d.ts +16 -0
  286. package/types/server/lifecycle/runtimeDir.d.ts +5 -0
  287. package/types/server/logging/childOutputReader.d.ts +40 -0
  288. package/types/server/logging/hubFileSink.d.ts +18 -0
  289. package/types/server/logging/logControlSocket.d.ts +60 -0
  290. package/types/server/logging/logForwarder.d.ts +37 -0
  291. package/types/server/logging/logHub.d.ts +70 -0
  292. package/types/server/logging/logQuery.d.ts +31 -0
  293. package/types/server/logging/logStdoutWriter.d.ts +35 -0
  294. package/types/server/logging/logStreamRoute.d.ts +20 -0
  295. package/types/server/logging/logTailClient.d.ts +42 -0
  296. package/types/server/mcp/McpAuth.d.ts +62 -0
  297. package/types/server/mcp/McpDispatcher.d.ts +61 -0
  298. package/types/server/mcp/McpEventStream.d.ts +17 -0
  299. package/types/server/mcp/McpExecutionContext.d.ts +44 -0
  300. package/types/server/mcp/McpRouter.d.ts +65 -0
  301. package/types/server/mcp/index.d.ts +5 -0
  302. package/types/server/mcp.d.ts +1 -0
  303. package/types/server/resolver/signal.resolver.d.ts +7 -4
  304. package/types/server/routing/apiRouter.d.ts +2 -1
  305. package/types/server/routing/appWsData.d.ts +13 -1
  306. package/types/server/routing/eventStream.d.ts +23 -0
  307. package/types/server/routing/soloAppRoutes.d.ts +17 -0
  308. package/types/server/rscWorkerHost.d.ts +4 -1
  309. package/types/server/semaphore.d.ts +5 -0
  310. package/types/server/subRouteIndexDocument.d.ts +8 -0
  311. package/types/server/systemPageDocument.d.ts +1 -0
  312. package/types/server/systemPages.d.ts +5 -0
  313. package/types/server/types.d.ts +16 -0
  314. package/types/server/vendor/akanjs-fetch.d.ts +1 -0
  315. package/types/server/webRouter.d.ts +15 -4
  316. package/types/service/adapt.d.ts +2 -2
  317. package/types/service/agent.service.d.ts +32 -0
  318. package/types/service/base.service.d.ts +4 -0
  319. package/types/service/index.d.ts +1 -0
  320. package/types/service/injectInfo.d.ts +2 -2
  321. package/types/service/ipcTypes.d.ts +12 -0
  322. package/types/service/predefinedAdaptor/compress.adaptor.d.ts +1 -1
  323. package/types/service/predefinedAdaptor/database.adaptor.d.ts +9 -3
  324. package/types/service/predefinedAdaptor/deepseekLlm.d.ts +76 -0
  325. package/types/service/predefinedAdaptor/index.d.ts +3 -0
  326. package/types/service/predefinedAdaptor/insightQuery.d.ts +50 -0
  327. package/types/service/predefinedAdaptor/llm.adaptor.d.ts +105 -0
  328. package/types/service/predefinedAdaptor/queue.adaptor.d.ts +3 -2
  329. package/types/service/predefinedAdaptor/role.adaptor.d.ts +2 -0
  330. package/types/service/predefinedAdaptor/schedule.adaptor.d.ts +10 -6
  331. package/types/service/predefinedAdaptor/solidQueue.adaptor.d.ts +6 -2
  332. package/types/service/predefinedAdaptor/solidSqlite.d.ts +2 -2
  333. package/types/service/serve.d.ts +3 -3
  334. package/types/service/toolNames.d.ts +35 -0
  335. package/types/signal/agent/AgentCatalogue.d.ts +100 -0
  336. package/types/signal/agent/index.d.ts +1 -0
  337. package/types/signal/agent.d.ts +1 -0
  338. package/types/signal/agent.signal.d.ts +24 -0
  339. package/types/signal/agentTurn.d.ts +9 -0
  340. package/types/signal/agentTurnStream.d.ts +24 -0
  341. package/types/signal/base.signal.d.ts +1 -1
  342. package/types/signal/endpointInfo.d.ts +21 -3
  343. package/types/signal/guard.d.ts +12 -0
  344. package/types/signal/guards.d.ts +23 -1
  345. package/types/signal/index.d.ts +6 -0
  346. package/types/signal/intercept.d.ts +2 -2
  347. package/types/signal/internalArg.d.ts +22 -6
  348. package/types/signal/mcp/McpDocument.d.ts +84 -0
  349. package/types/signal/mcp/McpProgress.d.ts +40 -0
  350. package/types/signal/mcp/McpUriTemplate.d.ts +25 -0
  351. package/types/signal/mcp/Msg.d.ts +143 -0
  352. package/types/signal/mcp/index.d.ts +5 -0
  353. package/types/signal/mcp/mcpProtocol.d.ts +107 -0
  354. package/types/signal/mcp.d.ts +1 -0
  355. package/types/signal/middleware.d.ts +7 -7
  356. package/types/signal/openapi/openapi.d.ts +3 -3
  357. package/types/signal/schema/JsonSchemaBuilder.d.ts +51 -0
  358. package/types/signal/schema/index.d.ts +1 -0
  359. package/types/signal/schema.d.ts +1 -0
  360. package/types/signal/signalContext.d.ts +67 -8
  361. package/types/signal/slice.d.ts +42 -15
  362. package/types/signal/trace.d.ts +52 -2
  363. package/types/signal/types.d.ts +53 -4
  364. package/types/store/action.d.ts +7 -5
  365. package/types/store/actionTag.d.ts +21 -0
  366. package/types/store/agent/AgentBridge.d.ts +37 -0
  367. package/types/store/agent/AgentContext.d.ts +16 -0
  368. package/types/store/agent/AgentPrompts.d.ts +31 -0
  369. package/types/store/agent/ScreenReader.d.ts +29 -0
  370. package/types/store/agent/ScreenSettle.d.ts +22 -0
  371. package/types/store/agent/ScreenTarget.d.ts +34 -0
  372. package/types/store/agent/StoreCatalogue.d.ts +26 -0
  373. package/types/store/agent/StoreSurfaceSource.d.ts +30 -0
  374. package/types/store/agent/index.d.ts +11 -0
  375. package/types/store/agent/storeSurface.d.ts +14 -0
  376. package/types/store/agent/types.d.ts +15 -0
  377. package/types/store/agent.d.ts +1 -0
  378. package/types/store/agentic/AgentValue.d.ts +43 -0
  379. package/types/store/agentic/StExposeBuilder.d.ts +21 -0
  380. package/types/store/agentic/StExposeDraft.d.ts +13 -0
  381. package/types/store/agentic/StStateBuilder.d.ts +21 -0
  382. package/types/store/agentic/StStateDraft.d.ts +12 -0
  383. package/types/store/agentic/StToolBuilder.d.ts +56 -0
  384. package/types/store/agentic/StToolDraft.d.ts +13 -0
  385. package/types/store/agentic/attachAgentic.d.ts +25 -0
  386. package/types/store/agentic/formFields.d.ts +53 -0
  387. package/types/store/agentic/index.d.ts +12 -0
  388. package/types/store/agentic/useFieldTool.d.ts +22 -0
  389. package/types/store/agentic/useFormTools.d.ts +19 -0
  390. package/types/store/agentic/useRelationFieldTool.d.ts +27 -0
  391. package/types/store/agentic.d.ts +1 -0
  392. package/types/store/baseSt.d.ts +35 -39
  393. package/types/store/databaseStateNames.d.ts +25 -0
  394. package/types/store/formSetterNames.d.ts +30 -0
  395. package/types/store/index.d.ts +7 -0
  396. package/types/store/rootStore.d.ts +5 -1
  397. package/types/store/sliceRole.d.ts +25 -0
  398. package/types/store/store.d.ts +5 -1
  399. package/types/store/storeInstance.d.ts +33 -1
  400. package/types/store/storeRegistry.d.ts +5 -0
  401. package/types/store/types.d.ts +4 -0
  402. package/types/store/withSelector.d.ts +5 -4
  403. package/types/test/index.d.ts +1 -1
  404. package/types/test/registerDom.d.ts +1 -0
  405. package/types/test/signalTestRuntime.d.ts +2 -3
  406. package/types/test/testServer.d.ts +6 -4
  407. package/types/ui/Agent/Approval.d.ts +8 -0
  408. package/types/ui/Agent/Attach.d.ts +16 -0
  409. package/types/ui/Agent/Bubble.d.ts +26 -0
  410. package/types/ui/Agent/Chat.d.ts +91 -0
  411. package/types/ui/Agent/ChatCommands.d.ts +34 -0
  412. package/types/ui/Agent/Composer.d.ts +23 -0
  413. package/types/ui/Agent/Context.d.ts +13 -0
  414. package/types/ui/Agent/Dock.d.ts +17 -0
  415. package/types/ui/Agent/Guide.d.ts +9 -0
  416. package/types/ui/Agent/History.d.ts +26 -0
  417. package/types/ui/Agent/Launcher.d.ts +16 -0
  418. package/types/ui/Agent/Markdown.d.ts +19 -0
  419. package/types/ui/Agent/Menu.d.ts +18 -0
  420. package/types/ui/Agent/Mic.d.ts +8 -0
  421. package/types/ui/Agent/Question.d.ts +14 -0
  422. package/types/ui/Agent/Section.d.ts +10 -0
  423. package/types/ui/Agent/Skip.d.ts +22 -0
  424. package/types/ui/Agent/StateKey.d.ts +16 -0
  425. package/types/ui/Agent/Tool.d.ts +15 -0
  426. package/types/ui/Agent/Transcript.d.ts +13 -0
  427. package/types/ui/Agent/Zone.d.ts +48 -0
  428. package/types/ui/Agent/agentSessionOf.d.ts +27 -0
  429. package/types/ui/Agent/attachment.d.ts +34 -0
  430. package/types/ui/Agent/fetchRunner.d.ts +12 -0
  431. package/types/ui/Agent/index.d.ts +19 -0
  432. package/types/ui/Agent/index_.d.ts +1 -0
  433. package/types/ui/Agent/markdownBlocks.d.ts +35 -0
  434. package/types/ui/Agent/markdownSpans.d.ts +2 -0
  435. package/types/ui/Agent/markdownTable.d.ts +16 -0
  436. package/types/ui/Agent/sessionHistory.d.ts +14 -0
  437. package/types/ui/Agent/sessionView.d.ts +15 -0
  438. package/types/ui/Agent/tokenCount.d.ts +6 -0
  439. package/types/ui/Agent/useChatAttachments.d.ts +24 -0
  440. package/types/ui/Agent/useChatVoice.d.ts +30 -0
  441. package/types/ui/Agent/useDraftRecall.d.ts +14 -0
  442. package/types/ui/Agent/useKeyboardInset.d.ts +8 -0
  443. package/types/ui/Agent/useSlashMenu.d.ts +24 -0
  444. package/types/ui/Agent/voice.d.ts +71 -0
  445. package/types/ui/Agent.d.ts +1 -0
  446. package/types/ui/Badge.d.ts +1 -1
  447. package/types/ui/Button.d.ts +1 -1
  448. package/types/ui/Constant/Graph.d.ts +10 -0
  449. package/types/ui/Constant/index.d.ts +2 -1
  450. package/types/ui/Constant/schemaGraph.d.ts +39 -0
  451. package/types/ui/Data/Dashboard.d.ts +16 -3
  452. package/types/ui/Data/Insight.d.ts +1 -1
  453. package/types/ui/Data/ListContainer.d.ts +15 -7
  454. package/types/ui/Data/QueryMaker.d.ts +45 -3
  455. package/types/ui/Data/RefPicker.d.ts +16 -0
  456. package/types/ui/Data/dataExport.d.ts +5 -0
  457. package/types/ui/Data/dataText.d.ts +6 -0
  458. package/types/ui/Data/index.d.ts +2 -0
  459. package/types/ui/Data/index_.d.ts +1 -0
  460. package/types/ui/DatePicker.d.ts +15 -11
  461. package/types/ui/Dialog/LegacyModal.d.ts +13 -0
  462. package/types/ui/Dialog/Provider.d.ts +3 -1
  463. package/types/ui/Dialog/context.d.ts +9 -1
  464. package/types/ui/Dialog/index.d.ts +1 -0
  465. package/types/ui/DraggableList.d.ts +1 -1
  466. package/types/ui/Dropdown.d.ts +5 -1
  467. package/types/ui/Field.d.ts +13 -12
  468. package/types/ui/Layout/BottomTab.d.ts +3 -2
  469. package/types/ui/LegacyModal.d.ts +24 -0
  470. package/types/ui/Loading/ProgressBar.d.ts +4 -0
  471. package/types/ui/Loading/Spin.d.ts +2 -1
  472. package/types/ui/Model/AdminPanel.d.ts +15 -3
  473. package/types/ui/Model/EditModal.d.ts +1 -1
  474. package/types/ui/Model/New.d.ts +3 -1
  475. package/types/ui/Model/NewWrapper.d.ts +2 -0
  476. package/types/ui/Model/NewWrapper_Client.d.ts +2 -1
  477. package/types/ui/Pagination.d.ts +2 -2
  478. package/types/ui/Radio.d.ts +1 -1
  479. package/types/ui/RecentTime.d.ts +18 -1
  480. package/types/ui/Reference/Collapse.d.ts +11 -0
  481. package/types/ui/Reference/Panel.d.ts +29 -0
  482. package/types/ui/Reference/Segmented.d.ts +17 -0
  483. package/types/ui/Reference/Summary.d.ts +13 -0
  484. package/types/ui/Reference/Toolbar.d.ts +21 -0
  485. package/types/ui/Reference/dictText.d.ts +6 -0
  486. package/types/ui/Reference/index.d.ts +7 -0
  487. package/types/ui/Reference/style.d.ts +20 -0
  488. package/types/ui/Reference.d.ts +1 -0
  489. package/types/ui/ScreenNavigator.d.ts +3 -1
  490. package/types/ui/Signal/Arg.d.ts +7 -3
  491. package/types/ui/Signal/Doc.d.ts +4 -6
  492. package/types/ui/Signal/Object.d.ts +2 -1
  493. package/types/ui/Signal/RestApi.d.ts +2 -1
  494. package/types/ui/Signal/WebSocket.d.ts +2 -1
  495. package/types/ui/Signal/endpointEntries.d.ts +20 -0
  496. package/types/ui/Signal/style.d.ts +9 -8
  497. package/types/ui/System/Client.d.ts +1 -2
  498. package/types/ui/System/Common.d.ts +3 -4
  499. package/types/ui/System/Messages.d.ts +1 -1
  500. package/types/ui/Tab/Provider.d.ts +3 -1
  501. package/types/ui/Tab/context.d.ts +4 -2
  502. package/types/ui/ToggleSelect.d.ts +1 -0
  503. package/types/ui/UiOverride/context.d.ts +18 -1
  504. package/types/ui/agentAttrs.d.ts +14 -0
  505. package/types/ui/index.d.ts +22 -1
  506. package/types/ui/overlayLayer.d.ts +13 -0
  507. package/types/ui/overlayPosition.d.ts +28 -0
  508. package/types/ui/recipe/badgeRecipe.d.ts +2 -2
  509. package/types/ui/recipe/buttonRecipe.d.ts +2 -2
  510. package/types/vendor/use-agentic/AgentAbort.d.ts +17 -0
  511. package/types/vendor/use-agentic/AgentProgress.d.ts +27 -0
  512. package/types/vendor/use-agentic/AgentProvider.d.ts +17 -0
  513. package/types/vendor/use-agentic/AgentScope.d.ts +9 -0
  514. package/types/vendor/use-agentic/AgentSession.d.ts +163 -0
  515. package/types/vendor/use-agentic/Agentic.d.ts +21 -0
  516. package/types/vendor/use-agentic/AgenticSurface.d.ts +58 -0
  517. package/types/vendor/use-agentic/Compaction.d.ts +48 -0
  518. package/types/vendor/use-agentic/ToolOutput.d.ts +21 -0
  519. package/types/vendor/use-agentic/Transcript.d.ts +18 -0
  520. package/types/vendor/use-agentic/httpRunner.d.ts +15 -0
  521. package/types/vendor/use-agentic/index.d.ts +19 -0
  522. package/types/vendor/use-agentic/sharedContext.d.ts +15 -0
  523. package/types/vendor/use-agentic/surfaceContext.d.ts +5 -0
  524. package/types/vendor/use-agentic/types.d.ts +182 -0
  525. package/types/vendor/use-agentic/useAgent.d.ts +4 -0
  526. package/types/vendor/use-agentic/useAgentGuide.d.ts +6 -0
  527. package/types/vendor/use-agentic/useAgentResource.d.ts +12 -0
  528. package/types/vendor/use-agentic/useAgentState.d.ts +16 -0
  529. package/types/vendor/use-agentic/useAgentTool.d.ts +16 -0
  530. package/types/vendor/use-agentic.d.ts +1 -0
  531. package/types/webkit/index.d.ts +4 -0
  532. package/types/webkit/useBodyScrollLock.d.ts +2 -0
  533. package/types/webkit/usePageTool.d.ts +19 -0
  534. package/types/webkit/useScreenScope.d.ts +25 -0
  535. package/ui/Agent/Approval.tsx +32 -0
  536. package/ui/Agent/Attach.tsx +77 -0
  537. package/ui/Agent/Bubble.tsx +192 -0
  538. package/ui/Agent/Chat.tsx +525 -0
  539. package/ui/Agent/ChatCommands.ts +141 -0
  540. package/ui/Agent/Composer.tsx +94 -0
  541. package/ui/Agent/Context.tsx +49 -0
  542. package/ui/Agent/Dock.tsx +77 -0
  543. package/ui/Agent/Guide.tsx +16 -0
  544. package/ui/Agent/History.tsx +49 -0
  545. package/ui/Agent/Launcher.tsx +60 -0
  546. package/ui/Agent/Markdown.tsx +142 -0
  547. package/ui/Agent/Menu.tsx +55 -0
  548. package/ui/Agent/Mic.tsx +27 -0
  549. package/ui/Agent/Question.tsx +63 -0
  550. package/ui/Agent/Section.tsx +24 -0
  551. package/ui/Agent/Skip.tsx +30 -0
  552. package/ui/Agent/StateKey.tsx +46 -0
  553. package/ui/Agent/Tool.tsx +59 -0
  554. package/ui/Agent/Transcript.tsx +33 -0
  555. package/ui/Agent/Zone.tsx +116 -0
  556. package/ui/Agent/agentSessionOf.ts +60 -0
  557. package/ui/Agent/attachment.ts +73 -0
  558. package/ui/Agent/fetchRunner.ts +44 -0
  559. package/ui/Agent/index.ts +27 -0
  560. package/ui/Agent/index_.tsx +4 -0
  561. package/ui/Agent/markdownBlocks.ts +137 -0
  562. package/ui/Agent/markdownSpans.tsx +49 -0
  563. package/ui/Agent/markdownTable.ts +54 -0
  564. package/ui/Agent/sessionHistory.ts +62 -0
  565. package/ui/Agent/sessionView.ts +38 -0
  566. package/ui/Agent/tokenCount.ts +10 -0
  567. package/ui/Agent/useChatAttachments.ts +84 -0
  568. package/ui/Agent/useChatVoice.ts +129 -0
  569. package/ui/Agent/useDraftRecall.ts +42 -0
  570. package/ui/Agent/useKeyboardInset.ts +26 -0
  571. package/ui/Agent/useSlashMenu.ts +58 -0
  572. package/ui/Agent/voice.ts +177 -0
  573. package/ui/Badge.tsx +1 -1
  574. package/ui/BottomSheet.tsx +32 -36
  575. package/ui/Button.tsx +3 -1
  576. package/ui/Clipboard.tsx +3 -6
  577. package/ui/Constant/Doc.tsx +265 -254
  578. package/ui/Constant/Graph.tsx +151 -0
  579. package/ui/Constant/index.ts +3 -2
  580. package/ui/Constant/schemaGraph.ts +232 -0
  581. package/ui/Data/CardList.tsx +14 -3
  582. package/ui/Data/Dashboard.tsx +70 -52
  583. package/ui/Data/Insight.tsx +18 -12
  584. package/ui/Data/Item.tsx +42 -56
  585. package/ui/Data/ListContainer.tsx +246 -132
  586. package/ui/Data/Pagination.tsx +10 -3
  587. package/ui/Data/QueryMaker.tsx +160 -11
  588. package/ui/Data/RefPicker.tsx +202 -0
  589. package/ui/Data/TableList.tsx +22 -13
  590. package/ui/Data/dataExport.ts +54 -0
  591. package/ui/Data/dataText.ts +22 -0
  592. package/ui/Data/index.ts +13 -1
  593. package/ui/Data/index_.tsx +1 -0
  594. package/ui/DatePicker.tsx +110 -128
  595. package/ui/Dialog/Close.tsx +3 -7
  596. package/ui/Dialog/LegacyModal.tsx +241 -0
  597. package/ui/Dialog/Modal.tsx +62 -195
  598. package/ui/Dialog/Provider.tsx +47 -3
  599. package/ui/Dialog/Trigger.tsx +3 -7
  600. package/ui/Dialog/context.ts +14 -2
  601. package/ui/Dialog/index.tsx +2 -0
  602. package/ui/DragAction.tsx +3 -2
  603. package/ui/DraggableList.tsx +9 -4
  604. package/ui/Dropdown.tsx +89 -27
  605. package/ui/Empty.tsx +6 -4
  606. package/ui/Field.tsx +128 -58
  607. package/ui/Input.tsx +27 -5
  608. package/ui/KeyboardAvoiding.tsx +2 -2
  609. package/ui/Layout/BottomTab.tsx +32 -37
  610. package/ui/Layout/Sider.tsx +37 -14
  611. package/ui/LegacyModal.tsx +53 -0
  612. package/ui/Link/CsrLink.tsx +1 -1
  613. package/ui/Load/Pagination.tsx +15 -8
  614. package/ui/Load/Units.tsx +30 -7
  615. package/ui/Load/View.tsx +10 -3
  616. package/ui/Loading/Area.tsx +7 -6
  617. package/ui/Loading/Button.tsx +7 -9
  618. package/ui/Loading/Input.tsx +7 -9
  619. package/ui/Loading/ProgressBar.tsx +16 -7
  620. package/ui/Loading/Skeleton.tsx +8 -13
  621. package/ui/Loading/Spin.tsx +20 -14
  622. package/ui/Menu.tsx +1 -1
  623. package/ui/Model/AdminPanel.tsx +52 -12
  624. package/ui/Model/EditModal.tsx +28 -6
  625. package/ui/Model/EditWrapper.tsx +16 -4
  626. package/ui/Model/New.tsx +4 -0
  627. package/ui/Model/NewWrapper.tsx +2 -0
  628. package/ui/Model/NewWrapper_Client.tsx +20 -6
  629. package/ui/Model/Remove.tsx +18 -6
  630. package/ui/Model/RemoveWrapper.tsx +12 -2
  631. package/ui/Model/SureToRemove.tsx +18 -6
  632. package/ui/Model/ViewEditModal.tsx +64 -15
  633. package/ui/Model/ViewModal.tsx +25 -11
  634. package/ui/Model/ViewWrapper.tsx +15 -4
  635. package/ui/Model/index_.tsx +1 -1
  636. package/ui/Pagination.tsx +51 -66
  637. package/ui/Popconfirm.tsx +88 -78
  638. package/ui/Radio.tsx +53 -24
  639. package/ui/RecentTime.tsx +83 -35
  640. package/ui/Reference/Collapse.tsx +26 -0
  641. package/ui/Reference/Panel.tsx +79 -0
  642. package/ui/Reference/Segmented.tsx +41 -0
  643. package/ui/Reference/Summary.tsx +25 -0
  644. package/ui/Reference/Toolbar.tsx +44 -0
  645. package/ui/Reference/dictText.ts +9 -0
  646. package/ui/Reference/index.ts +7 -0
  647. package/ui/Reference/style.ts +45 -0
  648. package/ui/ScreenNavigator.tsx +17 -2
  649. package/ui/Select.tsx +96 -57
  650. package/ui/Signal/Arg.tsx +83 -68
  651. package/ui/Signal/Doc.tsx +163 -129
  652. package/ui/Signal/Listener.tsx +40 -29
  653. package/ui/Signal/Message.tsx +87 -135
  654. package/ui/Signal/Object.tsx +79 -57
  655. package/ui/Signal/PubSub.tsx +72 -113
  656. package/ui/Signal/Request.tsx +2 -22
  657. package/ui/Signal/Response.tsx +19 -45
  658. package/ui/Signal/RestApi.tsx +170 -200
  659. package/ui/Signal/WebSocket.tsx +29 -26
  660. package/ui/Signal/endpointEntries.ts +59 -0
  661. package/ui/Signal/makeExample.ts +10 -3
  662. package/ui/Signal/style.ts +34 -29
  663. package/ui/Switch.tsx +4 -0
  664. package/ui/System/CSR.tsx +1 -1
  665. package/ui/System/Client.tsx +31 -15
  666. package/ui/System/Common.tsx +3 -4
  667. package/ui/System/DevModeToggle.tsx +1 -1
  668. package/ui/System/Gtag.tsx +2 -2
  669. package/ui/System/Messages.tsx +52 -31
  670. package/ui/System/Reconnect.tsx +22 -56
  671. package/ui/System/SelectLanguage.tsx +24 -15
  672. package/ui/System/ThemeToggle.tsx +25 -13
  673. package/ui/Tab/Menu.tsx +24 -12
  674. package/ui/Tab/Menus.tsx +6 -3
  675. package/ui/Tab/Provider.tsx +30 -3
  676. package/ui/Tab/context.ts +8 -4
  677. package/ui/Table.tsx +66 -60
  678. package/ui/ToggleSelect.tsx +8 -7
  679. package/ui/Tooltip.tsx +15 -1
  680. package/ui/UiOverride/context.ts +21 -2
  681. package/ui/Unauthorized.tsx +6 -4
  682. package/ui/agentAttrs.ts +19 -0
  683. package/ui/index.ts +49 -1
  684. package/ui/overlayLayer.ts +12 -2
  685. package/ui/overlayPosition.ts +104 -0
  686. package/ui/recipe/buttonRecipe.ts +2 -2
  687. package/ui/styles.css +31 -0
  688. package/vendor/use-agentic/AgentAbort.ts +29 -0
  689. package/vendor/use-agentic/AgentProgress.ts +40 -0
  690. package/vendor/use-agentic/AgentProvider.tsx +39 -0
  691. package/vendor/use-agentic/AgentScope.tsx +20 -0
  692. package/vendor/use-agentic/AgentSession.ts +750 -0
  693. package/vendor/use-agentic/Agentic.tsx +44 -0
  694. package/vendor/use-agentic/AgenticSurface.ts +333 -0
  695. package/vendor/use-agentic/Compaction.ts +120 -0
  696. package/vendor/use-agentic/ToolOutput.ts +60 -0
  697. package/vendor/use-agentic/Transcript.ts +50 -0
  698. package/vendor/use-agentic/WIRE.md +86 -0
  699. package/vendor/use-agentic/httpRunner.ts +131 -0
  700. package/vendor/use-agentic/index.ts +20 -0
  701. package/vendor/use-agentic/sharedContext.ts +25 -0
  702. package/vendor/use-agentic/surfaceContext.ts +10 -0
  703. package/vendor/use-agentic/types.ts +192 -0
  704. package/vendor/use-agentic/useAgent.ts +18 -0
  705. package/vendor/use-agentic/useAgentGuide.ts +16 -0
  706. package/vendor/use-agentic/useAgentResource.ts +36 -0
  707. package/vendor/use-agentic/useAgentState.ts +64 -0
  708. package/vendor/use-agentic/useAgentTool.ts +55 -0
  709. package/webkit/bootCsr.tsx +10 -8
  710. package/webkit/index.ts +4 -0
  711. package/webkit/lazy.tsx +5 -1
  712. package/webkit/useBodyScrollLock.tsx +29 -0
  713. package/webkit/useFrameRuntime.ts +1 -1
  714. package/webkit/usePageTool.tsx +37 -0
  715. package/webkit/useScreenScope.tsx +60 -0
  716. package/types/ui/Constant/Mermaid.d.ts +0 -8
  717. package/types/ui/Signal/Collapse.d.ts +0 -12
  718. package/ui/Constant/Mermaid.tsx +0 -149
  719. package/ui/Signal/Collapse.tsx +0 -29
@@ -0,0 +1,114 @@
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
+ mcp?: boolean;
20
+ }
21
+
22
+ export interface McpExposureOption {
23
+ /** The model the endpoint belongs to and the name it is published under: one rule reads the key, not the shape. */
24
+ refName: string;
25
+ key: string;
26
+ /**
27
+ * The read-only deployment valve, which is server configuration. The browser explorer cannot know it and so
28
+ * badges what the code decided; the boot log is where a read-only deployment says what it dropped.
29
+ */
30
+ readOnly?: boolean;
31
+ }
32
+
33
+ /** `Any` publishes as the empty schema, which tells a model nothing — so it is left out rather than described. */
34
+ export const isMcpDescribableArg = (arg: { refName: string }) => arg.refName !== "Any";
35
+
36
+ /** Which CRUD verb a generated endpoint key is, or `null` when the key is not one of the five. */
37
+ export const mcpBaseVerbOf = (refName: string, key: string) => {
38
+ const cap = capitalize(refName);
39
+ if (key === refName || key === `light${cap}`) return "get" as const;
40
+ if (key === `create${cap}`) return "create" as const;
41
+ if (key === `update${cap}`) return "update" as const;
42
+ if (key === `remove${cap}`) return "remove" as const;
43
+ return null;
44
+ };
45
+
46
+ /**
47
+ * The hints a client renders beside a tool. Hints only — clients are told to distrust them, so they inform a UI
48
+ * and never stand in for a guard. `openWorldHint` is always false: every endpoint reaches this app's own
49
+ * database, not the wider internet.
50
+ */
51
+ export const mcpHintsOf = (key: string, endpoint: { type: string }) => {
52
+ const readOnly = endpoint.type === "query";
53
+ const destructive = !readOnly && /^(remove|delete)/.test(key);
54
+ return {
55
+ readOnlyHint: readOnly,
56
+ destructiveHint: destructive,
57
+ idempotentHint: readOnly || /^(set|update)/.test(key),
58
+ openWorldHint: false,
59
+ };
60
+ };
61
+
62
+ /** The sentence explaining why this endpoint is not in the catalogue, or `null` when it is. */
63
+ export const mcpRefusalOf = (
64
+ endpoint: McpExposureEndpoint,
65
+ { refName, key, readOnly }: McpExposureOption,
66
+ ): string | null => {
67
+
68
+ if (endpoint.mcp === false)
69
+ return "it declares `mcp: false`, so it is deliberately off the agent shelf. HTTP still serves it.";
70
+
71
+ if (!endpoint.guards?.length)
72
+ return "it declares no guards, and exposure follows them — write `guards: [Public]` if anonymous access is the intent.";
73
+
74
+ if (key === `light${capitalize(refName)}`)
75
+ return `it reads the same document as \`${refName}\` in a smaller shape — call \`${refName}\` instead.`;
76
+ if (endpoint.type === "prompt") return mcpPromptRefusalOf(endpoint);
77
+ if (endpoint.type === "pubsub" || endpoint.type === "message")
78
+ return `\`${endpoint.type}\` rides the websocket, and its internal arguments read a socket an MCP request does not have.`;
79
+ if (readOnly && endpoint.type !== "query")
80
+ return "this deployment is read-only, which drops every endpoint that is not a query.";
81
+ if (endpoint.returns.refName === "Any" || endpoint.returns.refName === "Upload")
82
+ return `a return typed \`${endpoint.returns.refName}\` cannot be described to a model.`;
83
+ if (endpoint.returns.refName === "Binary")
84
+ return "a return typed `Binary` is raw bytes, which cost a model its window and tell it nothing.";
85
+ if (endpoint.fileUpload || endpoint.args.some((arg) => arg.refName === "Upload"))
86
+ return "a file upload has no MCP representation.";
87
+ if (endpoint.type === "mutation" && !endpoint.guards.some((name) => name !== "Public"))
88
+ return "a mutation needs a real guard — `[Public]` is having none, spelled out.";
89
+ const opaque = endpoint.args.find((arg) => !isMcpDescribableArg(arg) && arg.type !== "search" && !arg.nullable);
90
+ if (opaque)
91
+ return `its required argument \`${opaque.name}\` is typed \`Any\`, which is left out of the published schema — expose a named filter slice instead.`;
92
+ return null;
93
+ };
94
+
95
+ /**
96
+ * A prompt is a read exposed on the same terms as a query, so every rejection here is one thing: an argument
97
+ * `prompts/get` cannot carry. Its `arguments` is a flat string map — one string per name, and no schema beside it
98
+ * — which rules out the argument *kinds* the builder already refuses and, just as surely, two argument *types* it
99
+ * accepts. A tool escapes both because it publishes a real JSON Schema.
100
+ */
101
+ export const mcpPromptRefusalOf = (endpoint: McpExposureEndpoint): string | null => {
102
+ const carried = endpoint.args.find((arg) => arg.type === "body" || arg.type === "msg" || arg.type === "room");
103
+ if (carried)
104
+ return `a prompt's arguments travel as a flat string map, so its \`${carried.type}\` argument \`${carried.name}\` cannot be carried.`;
105
+
106
+ const list = endpoint.args.find((arg) => arg.arrDepth);
107
+ if (list)
108
+ return `a prompt argument is one string, so its list argument \`${list.name}\` could never carry more than one value.`;
109
+
110
+ const opaque = endpoint.args.find((arg) => !isMcpDescribableArg(arg));
111
+ if (opaque)
112
+ return `its argument \`${opaque.name}\` is typed \`Any\`, and a prompt has no schema in which to describe one.`;
113
+ return null;
114
+ };
@@ -0,0 +1,31 @@
1
+ type Indexable = Record<string, unknown>;
2
+
3
+ const isIndexable = (value: unknown): value is Indexable => Object(value) === value;
4
+
5
+ /**
6
+ * Reads a dotted path whose segments may themselves contain the separator.
7
+ *
8
+ * Dictionary keys are built as `<refName>.<value>` and an enum value is a real-world identifier — `gpt-5.6-terra`,
9
+ * `v1.2` — so the key is not a clean dotted path and `pathGet` splits it into segments that were never nodes.
10
+ * The tree stores such a key literally, so resolution has to try joined prefixes too.
11
+ */
12
+ export const pathGetLoose = (
13
+ path: string | readonly string[],
14
+ obj: unknown,
15
+ separator = ".",
16
+ fallback: unknown = null,
17
+ ): unknown => {
18
+ const walk = (node: unknown, rest: readonly string[]): unknown => {
19
+ if (!rest.length) return node;
20
+ if (!isIndexable(node)) return undefined;
21
+
22
+ for (let take = 1; take <= rest.length; take += 1) {
23
+ const child = node[rest.slice(0, take).join(separator)];
24
+ if (child === undefined) continue;
25
+ const found = walk(child, rest.slice(take));
26
+ if (found !== undefined) return found;
27
+ }
28
+ return undefined;
29
+ };
30
+ return walk(obj, Array.isArray(path) ? [...path] : (path as string).split(separator)) ?? fallback;
31
+ };
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
  };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Own and inherited enumerable data of an object as a plain record. An Akan model keeps its Date fields as
3
+ * enumerable prototype accessors, which `Object.keys` and a spread never reach; methods are non-enumerable and stay
4
+ * out either way.
5
+ */
6
+ export const plainFieldsOf = (source: object): Record<string, unknown> => {
7
+ const out: Record<string, unknown> = {};
8
+ for (const key in source) {
9
+ const value = (source as Record<string, unknown>)[key];
10
+ if (typeof value !== "function") out[key] = value;
11
+ }
12
+ return out;
13
+ };
@@ -67,27 +67,37 @@ export function isRouteSourceFile(filePath: string): boolean {
67
67
  return tryParseRouteModuleKey(key) !== null;
68
68
  }
69
69
 
70
- export function validatePageSourceFile(filePath: string, options: ValidatePageSourceFileOptions = {}): boolean {
71
- if (!SOURCE_EXT_RE.test(filePath)) return false;
70
+ /**
71
+ * Why a `page/` file breaks the route convention, or null when it is fine. Null also covers a non-source
72
+ * asset, which `page/` tolerates. `akan sync <lib>` reports these alongside its other layout violations,
73
+ * so the rule stays in one place instead of being restated where it cannot afford to throw.
74
+ */
75
+ export function getPageSourceFileViolation(filePath: string): string | null {
76
+ if (!SOURCE_EXT_RE.test(filePath)) return null;
72
77
 
73
78
  const key = filePath.startsWith("./") ? filePath : `./${filePath.split(/[\\/]/).join("/")}`;
74
79
  const match = ROUTE_SOURCE_RE.exec(key);
75
- const displayPath = options.filePath ?? key;
76
- if (!match) throw new Error(`[route-convention] invalid page source file: ${displayPath}`);
80
+ if (!match) return "invalid page source file";
77
81
 
78
82
  const file = match[1] as string;
79
83
  const ext = match[2] as string;
80
84
  const leaf = file.split("/").filter(Boolean).at(-1);
81
- if (!leaf) throw new Error(`[route-convention] invalid page source file: ${displayPath}`);
85
+ if (!leaf) return "invalid page source file";
82
86
 
83
- if (ext !== "tsx") throw new Error(`[route-convention] route source files under page/ must use .tsx: ${displayPath}`);
87
+ if (ext !== "tsx") return "route source files under page/ must use .tsx";
84
88
  if (leaf.startsWith("_") && !RESERVED_ROUTE_FILES.has(leaf) && leaf !== INTERNAL_ROOT_LAYOUT_LEAF)
85
- throw new Error(
86
- `[route-convention] only _index.tsx, _layout.tsx and _overrides.tsx are allowed as reserved route files under page/: ${displayPath}`,
87
- );
88
- if (/^[A-Z]/.test(leaf))
89
- throw new Error(`[route-convention] route page filenames must not start with an uppercase letter: ${displayPath}`);
90
- return true;
89
+ return "only _index.tsx, _layout.tsx and _overrides.tsx are allowed as reserved route files under page/";
90
+ if (/^[A-Z]/.test(leaf)) return "route page filenames must not start with an uppercase letter";
91
+ return null;
92
+ }
93
+
94
+ export function validatePageSourceFile(filePath: string, options: ValidatePageSourceFileOptions = {}): boolean {
95
+ if (!SOURCE_EXT_RE.test(filePath)) return false;
96
+
97
+ const violation = getPageSourceFileViolation(filePath);
98
+ if (!violation) return true;
99
+ const key = filePath.startsWith("./") ? filePath : `./${filePath.split(/[\\/]/).join("/")}`;
100
+ throw new Error(`[route-convention] ${violation}: ${options.filePath ?? key}`);
91
101
  }
92
102
 
93
103
  export function validateSubRoutePageKey(
@@ -0,0 +1,46 @@
1
+ export interface WebsocketBinaryFrame {
2
+ roomId: string;
3
+ payload: Uint8Array;
4
+ }
5
+
6
+ const MAGIC = 0xab;
7
+ const KIND_PUB = 0x01;
8
+ const HEADER_BYTES = 4;
9
+ const MAX_ROOM_BYTES = 0xffff;
10
+
11
+ const encoder = new TextEncoder();
12
+ const decoder = new TextDecoder();
13
+
14
+ /**
15
+ * Framework-owned binary pubsub frame, shared by the publisher and the client dispatcher. A room whose whole
16
+ * return is `Binary` sends its bytes in a websocket binary frame instead of the JSON `{ type: "pub" }` envelope,
17
+ * because `Buffer.toJSON()` turns bytes into `{ type: "Buffer", data: number[] }` — 3.6x the wire and ~300x the
18
+ * encode cost on a 64 KB payload, and a shape `JSON.parse` never restores.
19
+ *
20
+ * Text and binary frames coexist on one socket, so this is additive: every JSON endpoint is untouched, and a
21
+ * federation gateway relays a binary frame unchanged with no code of its own.
22
+ */
23
+ export const websocketBinaryFrameContract = {
24
+ encode: ({ roomId, payload }: WebsocketBinaryFrame): Uint8Array => {
25
+ const room = encoder.encode(roomId);
26
+ if (room.length > MAX_ROOM_BYTES) throw new Error(`Room id is too long to frame: ${roomId}`);
27
+ const frame = new Uint8Array(HEADER_BYTES + room.length + payload.length);
28
+ frame[0] = MAGIC;
29
+ frame[1] = KIND_PUB;
30
+ frame[2] = room.length >> 8;
31
+ frame[3] = room.length & 0xff;
32
+ frame.set(room, HEADER_BYTES);
33
+ frame.set(payload, HEADER_BYTES + room.length);
34
+ return frame;
35
+ },
36
+ decode: (data: ArrayBuffer | Uint8Array): WebsocketBinaryFrame | null => {
37
+ const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
38
+ if (bytes.length < HEADER_BYTES || bytes[0] !== MAGIC || bytes[1] !== KIND_PUB) return null;
39
+ const roomBytes = (bytes[2] << 8) | bytes[3];
40
+ if (bytes.length < HEADER_BYTES + roomBytes) return null;
41
+ return {
42
+ roomId: decoder.decode(bytes.subarray(HEADER_BYTES, HEADER_BYTES + roomBytes)),
43
+ payload: bytes.subarray(HEADER_BYTES + roomBytes),
44
+ };
45
+ },
46
+ } as const;
@@ -8,38 +8,104 @@ import {
8
8
  } from "akanjs/base";
9
9
 
10
10
  import type { FieldProps } from ".";
11
+ import { ConstantRegistry } from "./constantRegistry";
11
12
 
12
13
  export type CrystalizeFunc<Model> = (self: GetStateObject<Model>, isChild?: boolean) => Model;
14
+ export type Converter = (value: unknown) => unknown;
13
15
 
14
- export const crystalize = (field: FieldProps, value: unknown): unknown => {
15
- if (value === undefined || value === null) return value as undefined | null;
16
- if (field.isArray && Array.isArray(value))
17
- return value.map((v: unknown) =>
18
- crystalize({ ...field, isArray: field.arrDepth > 1, arrDepth: field.arrDepth - 1 }, v),
19
- );
20
- const crystalizeValue = PrimitiveRegistry.has(field.modelRef)
21
- ? (value: unknown) => (field.modelRef as unknown as typeof PrimitiveScalar)._parse(value as never)
22
- : (value: unknown) => value as object;
23
- if (field.isMap) {
24
- const mapValueField = {
25
- ...field,
26
- modelRef: field.of ?? field.modelRef,
27
- isMap: false,
28
- isClass: !!field.of && !PrimitiveRegistry.has(field.of),
29
- isScalar: !!field.of && PrimitiveRegistry.has(field.of),
30
- isArray: false,
31
- arrDepth: 0,
32
- };
16
+ /**
17
+ * The relation instances one hydration pass has already built, by model class and then document id.
18
+ *
19
+ * A listing hands the same relation to every row that references it — twenty users wearing one avatar — and
20
+ * each row would otherwise build its own copy of it, re-parsing every `Date` on the way. Sharing is safe
21
+ * because a constant model is `[immerable]`: a store write copies before it mutates.
22
+ *
23
+ * Module-scoped rather than passed down, because `crystalize` is reached through a model's own constructor,
24
+ * which has nowhere to carry it. A pass is wholly synchronous, so no other one can observe this mid-flight.
25
+ */
26
+ let sharedInstances: Map<Cls, Map<string, object>> | null = null;
27
+
28
+ /** Runs one hydration pass, sharing a relation instance across every value in it that names the same id. */
29
+ export const withSharedInstances = <T>(hydrate: () => T): T => {
30
+ if (sharedInstances) return hydrate();
31
+ sharedInstances = new Map();
32
+ try {
33
+ return hydrate();
34
+ } finally {
35
+ sharedInstances = null;
36
+ }
37
+ };
38
+
39
+ type ModelCls = new (obj?: object) => object;
40
+
41
+ const relationIdOf = (value: object): string | null => {
42
+ const id = (value as { id?: unknown }).id;
43
+ return typeof id === "string" && id ? id : null;
44
+ };
45
+
46
+ const modelConverterOf = (props: FieldProps): Converter => {
47
+ const modelRef = props.modelRef as unknown as ModelCls;
48
+
49
+ if (props.isScalar) return (value) => (value instanceof modelRef ? value : new modelRef(value as object));
50
+ return (value) => {
51
+ if (value instanceof modelRef) return value;
52
+
53
+ const id = relationIdOf(value as object);
54
+ if (!sharedInstances || !id) return new modelRef(value as object);
55
+ const byId = sharedInstances.get(modelRef as unknown as Cls) ?? new Map<string, object>();
56
+ if (!sharedInstances.has(modelRef as unknown as Cls)) sharedInstances.set(modelRef as unknown as Cls, byId);
57
+ const shared = byId.get(id) ?? new modelRef(value as object);
58
+ byId.set(id, shared);
59
+ return shared;
60
+ };
61
+ };
62
+
63
+ const mapConverterOf = (props: FieldProps): Converter => {
64
+ const of = props.of as Cls | undefined;
65
+ const valueConverter: Converter = of
66
+ ? singleConverterOf({
67
+ ...props,
68
+ modelRef: of as FieldProps["modelRef"],
69
+ isMap: false,
70
+ isClass: !PrimitiveRegistry.has(of),
71
+ isScalar: PrimitiveRegistry.has(of) || ConstantRegistry.isScalar(of),
72
+ isArray: false,
73
+ arrDepth: 0,
74
+ })
75
+ : (value) => value;
76
+ return (value) => {
77
+
78
+ const entries = value instanceof Map ? [...value.entries()] : Object.entries(value as Record<string, unknown>);
33
79
  return new Map(
34
- Object.entries(value as Record<string, unknown>).map(([key, val]) => [
35
- key,
36
- field.of
37
- ? applyFnToArrayObjects(val, (v: never) => crystalize(mapValueField, v))
38
- : applyFnToArrayObjects(val, crystalizeValue),
39
- ]),
80
+ entries.map(([key, val]: [string, unknown]) => [key, applyFnToArrayObjects(val, valueConverter as never)]),
40
81
  );
82
+ };
83
+ };
84
+
85
+ const singleConverterOf = (props: FieldProps): Converter => {
86
+ if (props.isMap) return mapConverterOf(props);
87
+ if (props.isClass) return modelConverterOf(props);
88
+
89
+ if ((props.modelRef as unknown) === Date) return (value) => dayjs(value as Date);
90
+ if (PrimitiveRegistry.has(props.modelRef as Cls))
91
+ return (value) => (props.modelRef as unknown as typeof PrimitiveScalar)._parse(value as never);
92
+ return (value) => value;
93
+ };
94
+
95
+ const converters = new WeakMap<FieldProps, Converter>();
96
+
97
+ /** The converter for one field, compiled once per `FieldProps` — which `getProps()` freezes and shares per field. */
98
+ export const converterOf = (props: FieldProps): Converter => {
99
+ const cached = converters.get(props);
100
+ if (cached) return cached;
101
+ const single = singleConverterOf(props);
102
+ let convert: Converter = (value) => (value === null || value === undefined ? value : single(value));
103
+ for (let depth = props.arrDepth; depth > 0; depth--) {
104
+ const inner: Converter = convert;
105
+ convert = (value: unknown): unknown => (Array.isArray(value) ? value.map(inner) : inner(value));
41
106
  }
42
- if (field.isClass) return new (field.modelRef as Cls<{ set: (obj: object) => object }>)().set(value as object);
43
- if (field.modelRef === Date) return dayjs(value as Date);
44
- return crystalizeValue(value);
107
+ converters.set(props, convert);
108
+ return convert;
45
109
  };
110
+
111
+ export const crystalize = (field: FieldProps, value: unknown): unknown => converterOf(field)(value);
@@ -0,0 +1,62 @@
1
+ import { type Dayjs, dayjs } from "akanjs/base";
2
+
3
+ /**
4
+ * A Date field stores a native `Date` under a per-key symbol and builds the `Dayjs` its type promises on first
5
+ * read, memoized by that `Date`. A dayjs instance is ~300 bytes and eight getter calls at construction; a `Date`
6
+ * is 40 bytes. A listing carries every row's dates and reads a handful of them, so this is most of what a
7
+ * hydrated list used to cost — see `crystalize`.
8
+ *
9
+ * The slot is a function of the key, not the class (`Symbol.for`): `applyMixins` copies a light model's accessors
10
+ * onto the full model's prototype, so an accessor and the `set()` that fills its slot must agree on the slot
11
+ * whichever class defined either one.
12
+ */
13
+ const slotByKey = new Map<string, symbol>();
14
+ export const dateSlotOf = (key: string): symbol => {
15
+ const cached = slotByKey.get(key);
16
+ if (cached) return cached;
17
+ const slot = Symbol.for(`akan.date.${key}`);
18
+ slotByKey.set(key, slot);
19
+ return slot;
20
+ };
21
+
22
+ const dayjsByDate = new WeakMap<Date, Dayjs>();
23
+ const lazyDayjsOf = (date: Date): Dayjs => {
24
+ const cached = dayjsByDate.get(date);
25
+ if (cached) return cached;
26
+ const value = dayjs(date);
27
+ dayjsByDate.set(date, value);
28
+ return value;
29
+ };
30
+
31
+ /** A caller's own `Date` is copied: the slot must not alias an object the caller can still mutate. */
32
+ export const toDateValue = (value: unknown): Date | null | undefined => {
33
+ if (value === null || value === undefined) return value;
34
+ if (value instanceof Date) return new Date(value.getTime());
35
+ if (dayjs.isDayjs(value)) return value.toDate();
36
+ return new Date(value as string | number);
37
+ };
38
+
39
+ type DateSlotHolder = Record<symbol, Date | null | undefined>;
40
+
41
+ /**
42
+ * Enumerable so `for...in` — `plainFieldsOf`, `immerify`, `deepObjectify` — still sees the field. immer calls a
43
+ * prototype setter with the draft as `this`, so a write through the accessor stays copy-on-write, and the getter
44
+ * writes nothing, so a read never marks a draft modified.
45
+ */
46
+ export const dateAccessorOf = (key: string): PropertyDescriptor => {
47
+ const slot = dateSlotOf(key);
48
+ return {
49
+ enumerable: true,
50
+ configurable: true,
51
+ get(this: DateSlotHolder) {
52
+ const date = this[slot];
53
+ return date === null || date === undefined ? date : lazyDayjsOf(date);
54
+ },
55
+ set(this: DateSlotHolder, value: unknown) {
56
+ this[slot] = toDateValue(value);
57
+ },
58
+ };
59
+ };
60
+
61
+ export const isDateSlotField = (props: { modelRef: unknown; isArray: boolean; isMap: boolean }): boolean =>
62
+ props.modelRef === Date && !props.isArray && !props.isMap;
@@ -1,6 +1,6 @@
1
1
  import { Any, applyFnToArrayObjects, type Cls, FIELD_META, PrimitiveRegistry, type PrimitiveScalar } from "akanjs/base";
2
2
 
3
- import { type ConstantCls, type ConstantModelRef, ConstantRegistry, type FieldProps } from ".";
3
+ import { type ConstantCls, type ConstantModelRef, ConstantRegistry, type FieldProps, withSharedInstances } from ".";
4
4
 
5
5
  const getDeserializeFn = (inputRef: ConstantModelRef | PrimitiveScalar) => {
6
6
  const deserializeFn = PrimitiveRegistry.has(inputRef as Cls)
@@ -66,5 +66,6 @@ export const deserialize = (
66
66
  if (nullable && (value === null || value === undefined)) return null;
67
67
  else if (!nullable && (value === null || value === undefined) && argRef !== Any)
68
68
  throw new Error(`Invalid Value (Nullable) in ${key} ${argRef} for value ${value}`);
69
- return deserializeInput(value, argRef, arrDepth, convertFn) as object[];
69
+
70
+ return withSharedInstances(() => deserializeInput(value, argRef, arrDepth, convertFn)) as object[];
70
71
  };
@@ -106,6 +106,13 @@ export interface ConstantFieldProps<
106
106
  validate?: (value: FieldValue, model: any) => boolean;
107
107
  text?: TextFieldRole;
108
108
  cascade?: CascadeAction;
109
+ /**
110
+ * Renders on the page, never reaches an agent. Stripped wherever a value is masked for an AI caller — the
111
+ * in-page agent's reads and every MCP result — and left untouched everywhere else, so a `File`'s blur
112
+ * placeholder still ships to `<Image>`. Unlike `hidden`/`secret` this is about cost, not secrecy: a field
113
+ * nothing can answer a question with is pure spend on every turn it rides.
114
+ */
115
+ visual?: boolean;
109
116
  meta?: Metadata;
110
117
  }
111
118
  export const fieldPresets = ["email", "password", "url"] as const;
@@ -197,6 +204,7 @@ interface ConstantFieldBuildProps<
197
204
  validate?: (value: FieldValue, model: any) => boolean;
198
205
  text?: TextFieldRole;
199
206
  cascade?: CascadeAction;
207
+ visual: boolean;
200
208
  modelRef: ConstantModelRef;
201
209
  arrDepth: number;
202
210
  optArrDepth: number;
@@ -321,6 +329,7 @@ export class ConstantField<
321
329
  readonly validate?: (value: FieldValue, model: any) => boolean;
322
330
  readonly text?: TextFieldRole;
323
331
  readonly cascade?: CascadeAction;
332
+ readonly visual: boolean;
324
333
  readonly modelRef: ConstantModelRef;
325
334
  readonly arrDepth: number;
326
335
  readonly optArrDepth: number;
@@ -353,6 +362,7 @@ export class ConstantField<
353
362
  this.validate = props.validate;
354
363
  this.text = props.text;
355
364
  this.cascade = props.cascade;
365
+ this.visual = props.visual;
356
366
  this.modelRef = props.modelRef;
357
367
  this.arrDepth = props.arrDepth;
358
368
  this.optArrDepth = props.optArrDepth;
@@ -432,6 +442,7 @@ export class ConstantField<
432
442
  validate: option.validate,
433
443
  text: option.text,
434
444
  cascade: option.cascade,
445
+ visual: option.visual ?? false,
435
446
  modelRef,
436
447
  arrDepth: arrDepth,
437
448
  optArrDepth: optArrDepth,
@@ -478,6 +489,7 @@ export class ConstantField<
478
489
  validate: this.validate,
479
490
  text: this.text,
480
491
  cascade: this.cascade,
492
+ visual: this.visual,
481
493
  modelRef: this.modelRef,
482
494
  arrDepth: this.arrDepth,
483
495
  optArrDepth: this.optArrDepth,
@@ -493,6 +505,14 @@ export interface FieldObject {
493
505
  [key: string]: ConstantField;
494
506
  }
495
507
 
508
+ /**
509
+ * `text` names a column in the plaintext search mirror, so a masked field carrying one would publish what it
510
+ * masks through search — the class build refuses it (`TextFieldPaths`). Removing the key from the option type
511
+ * moves that refusal to the call site, where the fix is obvious. Distributive because `FieldOption` is a union:
512
+ * a plain `Omit` over it would collapse to the keys the members share.
513
+ */
514
+ type WithoutTextRole<Option> = Option extends unknown ? Omit<Option, "text"> : never;
515
+
496
516
  type FieldOption<
497
517
  Value extends ConstantFieldTypeInput,
498
518
  MapValue = Value extends MapConstructor ? typeof PrimitiveScalar : never,
@@ -530,13 +550,33 @@ export const field = <
530
550
  fieldType: "property",
531
551
  });
532
552
 
533
- field.hidden = <
553
+ /**
554
+ * A stored property the page renders and an agent never sees — `field(value, { visual: true })`, spelled short
555
+ * because the reason to reach for it is always the same one. A blur placeholder, a rendered HTML body, a
556
+ * serialized geometry: real data the screen needs, and hundreds of tokens per record that no question is answered
557
+ * from. It stays a plain `property` everywhere else, so persistence, search, forms and the page response are
558
+ * untouched.
559
+ */
560
+ field.visual = <
534
561
  ExplicitType,
535
562
  Value extends ConstantFieldTypeInput = PlainTypeToFieldType<ExplicitType>,
536
563
  MapValue = Value extends MapConstructor ? typeof PrimitiveScalar : never,
537
564
  >(
538
565
  value: Value,
539
566
  option: FieldOption<Value, MapValue> = {},
567
+ ) =>
568
+ new FieldInfo<"property", Value, ExplicitType, MapValue>(value, {
569
+ ...option,
570
+ fieldType: "property",
571
+ visual: true,
572
+ });
573
+ field.hidden = <
574
+ ExplicitType,
575
+ Value extends ConstantFieldTypeInput = PlainTypeToFieldType<ExplicitType>,
576
+ MapValue = Value extends MapConstructor ? typeof PrimitiveScalar : never,
577
+ >(
578
+ value: Value,
579
+ option: WithoutTextRole<FieldOption<Value, MapValue>> = {},
540
580
  ) =>
541
581
  new FieldInfo<"hidden", Value, ExplicitType, MapValue>(value, {
542
582
  ...option,
@@ -549,7 +589,7 @@ field.secret = <
549
589
  MapValue = Value extends MapConstructor ? typeof PrimitiveScalar : never,
550
590
  >(
551
591
  value: Value,
552
- option: FieldOption<Value, MapValue> = {},
592
+ option: WithoutTextRole<FieldOption<Value, MapValue>> = {},
553
593
  ) =>
554
594
  new FieldInfo<"secret", Value | null, ExplicitType | null, MapValue>(value, {
555
595
  ...option,
@@ -564,7 +604,7 @@ export const resolve = <
564
604
  MapValue = Value extends MapConstructor ? typeof PrimitiveScalar : never,
565
605
  >(
566
606
  value: Value,
567
- option: FieldOption<Value, MapValue> = {},
607
+ option: WithoutTextRole<FieldOption<Value, MapValue>> = {},
568
608
  ) =>
569
609
  new FieldInfo<"resolve", Value, ExplicitType, MapValue>(value, {
570
610
  ...option,
@@ -0,0 +1,35 @@
1
+ import { FIELD_META } from "akanjs/base";
2
+ import { ConstantRegistry } from "./constantRegistry";
3
+ import type { FieldObject } from "./fieldInfo";
4
+
5
+ /**
6
+ * The query a field's value stands for, declared on the field itself with `.meta(...)`. A summary counter is the
7
+ * case this exists for: `hau` is however many rows one filter returns, so the tile showing it can open that exact
8
+ * listing without the page restating the filter beside it.
9
+ *
10
+ * The shape is read structurally rather than by class, so an app declares it with whatever builder it already has.
11
+ */
12
+ export interface FieldQueryMeta {
13
+ /** The model the query runs against. */
14
+ refName: string;
15
+ /** One of that model's declared filter keys. */
16
+ queryKey: string | null;
17
+ /** Read when the query is applied, so an arg relative to now — `() => [dayjs().subtract(1, "hour")]` — is current. */
18
+ queryArgs?: unknown[] | (() => unknown[]);
19
+ }
20
+
21
+ const isFieldQueryMeta = (meta: unknown): meta is FieldQueryMeta => {
22
+ if (!meta || typeof meta !== "object") return false;
23
+ const { refName, queryKey, queryArgs } = meta as Record<string, unknown>;
24
+ if (typeof refName !== "string" || !refName) return false;
25
+ if (queryKey !== null && typeof queryKey !== "string") return false;
26
+ return queryArgs === undefined || Array.isArray(queryArgs) || typeof queryArgs === "function";
27
+ };
28
+
29
+ /** The query one field of `refName` names, or nothing when the model, the field, or the declaration is absent. */
30
+ export const fieldQueryMetaOf = (refName: string, field: string): FieldQueryMeta | undefined => {
31
+ const cnst = ConstantRegistry.getDatabase(refName, { allowEmpty: true });
32
+ const fieldMap = cnst?.full[FIELD_META] as FieldObject | undefined;
33
+ const meta = fieldMap?.[field]?.meta;
34
+ return isFieldQueryMeta(meta) ? meta : undefined;
35
+ };