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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (388) hide show
  1. package/README.ko.md +1 -1
  2. package/README.md +1 -1
  3. package/base/symbols.ts +4 -0
  4. package/client/clientRuntime.ts +8 -0
  5. package/client/cn.ts +7 -0
  6. package/client/csrTypes.ts +2 -0
  7. package/client/frameDebug.ts +3 -2
  8. package/common/Logger.ts +4 -0
  9. package/common/deepObjectify.ts +21 -7
  10. package/common/index.ts +14 -0
  11. package/common/mcpExposure.ts +99 -0
  12. package/common/pathSet.ts +17 -5
  13. package/common/routeConvention.ts +30 -0
  14. package/constant/crystalize.ts +3 -1
  15. package/constant/fieldInfo.ts +6 -0
  16. package/constant/getDefault.ts +37 -9
  17. package/constant/immerify.ts +1 -1
  18. package/constant/index.ts +2 -0
  19. package/constant/labelOf.ts +17 -0
  20. package/constant/mask.ts +60 -0
  21. package/constant/purify.ts +17 -11
  22. package/constant/types.ts +14 -12
  23. package/dictionary/DictionaryLookup.ts +30 -0
  24. package/dictionary/agent.dictionary.ts +31 -0
  25. package/dictionary/agentTurn.dictionary.ts +29 -0
  26. package/dictionary/base.dictionary.ts +8 -0
  27. package/dictionary/dictInfo.ts +8 -0
  28. package/dictionary/dictionary.ts +9 -3
  29. package/dictionary/index.ts +1 -0
  30. package/document/database.ts +21 -0
  31. package/document/filterMeta.ts +7 -0
  32. package/document/index.ts +1 -0
  33. package/document/into.ts +7 -1
  34. package/document/noDocumentError.ts +12 -0
  35. package/fetch/agentTurn.ts +19 -0
  36. package/fetch/client/fetchClient.ts +71 -13
  37. package/fetch/client/wsClient.ts +17 -2
  38. package/fetch/fetchType/endpointFetch.type.ts +10 -4
  39. package/fetch/index.ts +1 -0
  40. package/local/apps/serverLifecycle/serverLifecycle-local.db +0 -0
  41. package/local/apps/serverLifecycle/serverLifecycle-local.db-shm +0 -0
  42. package/local/apps/serverLifecycle/serverLifecycle-local.db-wal +0 -0
  43. package/local/apps/serverLifecycle/serverLifecycle-local_solid.db +0 -0
  44. package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-shm +0 -0
  45. package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-wal +0 -0
  46. package/package.json +11 -9
  47. package/server/akanApp.ts +30 -34
  48. package/server/akanOption.ts +65 -7
  49. package/server/akanServer.ts +172 -7
  50. package/server/animatedImage.ts +83 -0
  51. package/server/artifact/routeClientCache.ts +14 -0
  52. package/server/assetEncoding.ts +47 -0
  53. package/server/devtools/signalSerializer.ts +2 -2
  54. package/server/devtools/types.ts +2 -2
  55. package/server/di/diLifecycle.ts +31 -3
  56. package/server/di/predefinedAdaptor.ts +6 -0
  57. package/server/imageOptimizer.ts +33 -46
  58. package/server/index.ts +1 -2
  59. package/server/mcp/McpAuth.ts +177 -0
  60. package/server/mcp/McpDispatcher.ts +245 -0
  61. package/server/mcp/McpEventStream.ts +76 -0
  62. package/server/mcp/McpExecutionContext.ts +105 -0
  63. package/server/mcp/McpRouter.ts +591 -0
  64. package/server/mcp/index.ts +5 -0
  65. package/server/resolver/CascadeRunner.ts +1 -1
  66. package/server/resolver/database.resolver.ts +42 -5
  67. package/server/resolver/service.resolver.ts +29 -0
  68. package/server/resolver/signal.resolver.ts +16 -1
  69. package/server/routeTreeBuilder.ts +2 -44
  70. package/server/rscWorker.tsx +6 -2
  71. package/server/subRouteIndexDocument.tsx +61 -0
  72. package/server/systemPageDocument.tsx +2 -2
  73. package/server/systemPages.tsx +49 -16
  74. package/server/vendor/akanjs-fetch.ts +1 -0
  75. package/server/webRouter.ts +159 -35
  76. package/service/agent.service.ts +14 -0
  77. package/service/base.service.ts +2 -1
  78. package/service/index.ts +1 -0
  79. package/service/predefinedAdaptor/database.adaptor.ts +78 -24
  80. package/service/predefinedAdaptor/deepseekLlm.ts +230 -0
  81. package/service/predefinedAdaptor/index.ts +3 -0
  82. package/service/predefinedAdaptor/insightQuery.ts +183 -0
  83. package/service/predefinedAdaptor/llm.adaptor.ts +76 -0
  84. package/service/predefinedAdaptor/role.adaptor.ts +2 -0
  85. package/service/predefinedAdaptor/schedule.adaptor.ts +12 -5
  86. package/service/serviceModule.ts +17 -0
  87. package/service/types.ts +4 -0
  88. package/signal/agent/AgentCatalogue.ts +165 -0
  89. package/signal/agent/index.ts +1 -0
  90. package/signal/agent.signal.ts +42 -0
  91. package/signal/agentTurn.ts +8 -0
  92. package/signal/agentTurnStream.ts +48 -0
  93. package/signal/base.signal.ts +2 -1
  94. package/signal/endpointInfo.ts +38 -2
  95. package/signal/guard.ts +13 -1
  96. package/signal/guards.ts +52 -1
  97. package/signal/index.ts +6 -0
  98. package/signal/mcp/McpDocument.ts +286 -0
  99. package/signal/mcp/McpProgress.ts +106 -0
  100. package/signal/mcp/McpUriTemplate.ts +85 -0
  101. package/signal/mcp/Msg.ts +368 -0
  102. package/signal/mcp/index.ts +5 -0
  103. package/signal/mcp/mcpProtocol.ts +120 -0
  104. package/signal/middleware.ts +7 -3
  105. package/signal/openapi/openapi.ts +32 -171
  106. package/signal/schema/JsonSchemaBuilder.ts +211 -0
  107. package/signal/schema/index.ts +1 -0
  108. package/signal/signalContext.ts +85 -9
  109. package/signal/slice.ts +9 -9
  110. package/signal/types.ts +1 -1
  111. package/store/action.ts +11 -22
  112. package/store/actionTag.ts +33 -0
  113. package/store/agent/AgentBridge.ts +323 -0
  114. package/store/agent/AgentContext.ts +74 -0
  115. package/store/agent/AgentPrompts.ts +82 -0
  116. package/store/agent/AgentVisibility.ts +68 -0
  117. package/store/agent/ScreenReader.ts +208 -0
  118. package/store/agent/StoreCatalogue.ts +351 -0
  119. package/store/agent/StoreSurfaceSource.ts +122 -0
  120. package/store/agent/index.ts +9 -0
  121. package/store/agent/storeSurface.ts +28 -0
  122. package/store/agent/types.ts +50 -0
  123. package/store/agentic/StToolBuilder.ts +199 -0
  124. package/store/agentic/attachAgentic.ts +22 -0
  125. package/store/agentic/index.ts +5 -0
  126. package/store/agentic/readableValue.ts +17 -0
  127. package/store/agentic/useStExpose.ts +18 -0
  128. package/store/agentic/useStState.ts +35 -0
  129. package/store/baseSt.ts +7 -0
  130. package/store/databaseStateNames.ts +31 -0
  131. package/store/formSetterNames.ts +21 -0
  132. package/store/index.ts +8 -0
  133. package/store/rootStore.ts +3 -1
  134. package/store/sliceRole.ts +36 -0
  135. package/store/state.ts +2 -12
  136. package/store/store.ts +19 -1
  137. package/store/storeInstance.ts +165 -20
  138. package/store/storeRegistry.ts +16 -1
  139. package/store/types.ts +18 -0
  140. package/store/withSelector.ts +7 -8
  141. package/test/registerDom.ts +4 -0
  142. package/types/base/symbols.d.ts +4 -0
  143. package/types/client/cn.d.ts +5 -0
  144. package/types/client/csrTypes.d.ts +2 -0
  145. package/types/common/Logger.d.ts +2 -0
  146. package/types/common/deepObjectify.d.ts +4 -2
  147. package/types/common/index.d.ts +2 -1
  148. package/types/common/mcpExposure.d.ts +60 -0
  149. package/types/common/routeConvention.d.ts +8 -0
  150. package/types/constant/fieldInfo.d.ts +1 -0
  151. package/types/constant/getDefault.d.ts +5 -0
  152. package/types/constant/index.d.ts +2 -0
  153. package/types/constant/labelOf.d.ts +6 -0
  154. package/types/constant/mask.d.ts +34 -0
  155. package/types/constant/purify.d.ts +2 -2
  156. package/types/constant/types.d.ts +2 -2
  157. package/types/dictionary/DictionaryLookup.d.ts +14 -0
  158. package/types/dictionary/agent.dictionary.d.ts +1 -0
  159. package/types/dictionary/agentTurn.dictionary.d.ts +1 -0
  160. package/types/dictionary/base.dictionary.d.ts +1 -1
  161. package/types/dictionary/dictInfo.d.ts +6 -0
  162. package/types/dictionary/dictionary.d.ts +11 -9
  163. package/types/dictionary/index.d.ts +1 -0
  164. package/types/document/database.d.ts +20 -0
  165. package/types/document/filterMeta.d.ts +1 -0
  166. package/types/document/index.d.ts +1 -0
  167. package/types/document/into.d.ts +6 -1
  168. package/types/document/noDocumentError.d.ts +12 -0
  169. package/types/fetch/agentTurn.d.ts +593 -0
  170. package/types/fetch/client/fetchClient.d.ts +10 -0
  171. package/types/fetch/fetchType/endpointFetch.type.d.ts +5 -3
  172. package/types/fetch/index.d.ts +1 -0
  173. package/types/server/akanOption.d.ts +35 -7
  174. package/types/server/akanServer.d.ts +44 -1
  175. package/types/server/animatedImage.d.ts +7 -0
  176. package/types/server/artifact/routeClientCache.d.ts +6 -0
  177. package/types/server/assetEncoding.d.ts +7 -0
  178. package/types/server/devtools/types.d.ts +2 -2
  179. package/types/server/di/predefinedAdaptor.d.ts +4 -1
  180. package/types/server/index.d.ts +0 -2
  181. package/types/server/mcp/McpAuth.d.ts +62 -0
  182. package/types/server/mcp/McpDispatcher.d.ts +54 -0
  183. package/types/server/mcp/McpEventStream.d.ts +18 -0
  184. package/types/server/mcp/McpExecutionContext.d.ts +44 -0
  185. package/types/server/mcp/McpRouter.d.ts +60 -0
  186. package/types/server/mcp/index.d.ts +5 -0
  187. package/types/server/mcp.d.ts +1 -0
  188. package/types/server/subRouteIndexDocument.d.ts +8 -0
  189. package/types/server/systemPageDocument.d.ts +1 -0
  190. package/types/server/systemPages.d.ts +5 -0
  191. package/types/server/vendor/akanjs-fetch.d.ts +1 -0
  192. package/types/service/agent.service.d.ts +12 -0
  193. package/types/service/base.service.d.ts +4 -0
  194. package/types/service/index.d.ts +1 -0
  195. package/types/service/predefinedAdaptor/database.adaptor.d.ts +24 -2
  196. package/types/service/predefinedAdaptor/deepseekLlm.d.ts +64 -0
  197. package/types/service/predefinedAdaptor/index.d.ts +3 -0
  198. package/types/service/predefinedAdaptor/insightQuery.d.ts +50 -0
  199. package/types/service/predefinedAdaptor/llm.adaptor.d.ts +68 -0
  200. package/types/service/predefinedAdaptor/role.adaptor.d.ts +2 -0
  201. package/types/service/predefinedAdaptor/schedule.adaptor.d.ts +10 -6
  202. package/types/service/types.d.ts +4 -1
  203. package/types/signal/agent/AgentCatalogue.d.ts +100 -0
  204. package/types/signal/agent/index.d.ts +1 -0
  205. package/types/signal/agent.d.ts +1 -0
  206. package/types/signal/agent.signal.d.ts +29 -0
  207. package/types/signal/agentTurn.d.ts +9 -0
  208. package/types/signal/agentTurnStream.d.ts +16 -0
  209. package/types/signal/base.signal.d.ts +1 -1
  210. package/types/signal/endpointInfo.d.ts +21 -3
  211. package/types/signal/guard.d.ts +11 -0
  212. package/types/signal/guards.d.ts +22 -1
  213. package/types/signal/index.d.ts +6 -0
  214. package/types/signal/mcp/McpDocument.d.ts +65 -0
  215. package/types/signal/mcp/McpProgress.d.ts +40 -0
  216. package/types/signal/mcp/McpUriTemplate.d.ts +26 -0
  217. package/types/signal/mcp/Msg.d.ts +143 -0
  218. package/types/signal/mcp/index.d.ts +5 -0
  219. package/types/signal/mcp/mcpProtocol.d.ts +107 -0
  220. package/types/signal/mcp.d.ts +1 -0
  221. package/types/signal/openapi/openapi.d.ts +3 -3
  222. package/types/signal/schema/JsonSchemaBuilder.d.ts +47 -0
  223. package/types/signal/schema/index.d.ts +1 -0
  224. package/types/signal/schema.d.ts +1 -0
  225. package/types/signal/signalContext.d.ts +16 -1
  226. package/types/signal/slice.d.ts +8 -8
  227. package/types/signal/types.d.ts +1 -1
  228. package/types/store/actionTag.d.ts +21 -0
  229. package/types/store/agent/AgentBridge.d.ts +77 -0
  230. package/types/store/agent/AgentContext.d.ts +16 -0
  231. package/types/store/agent/AgentPrompts.d.ts +31 -0
  232. package/types/store/agent/AgentVisibility.d.ts +21 -0
  233. package/types/store/agent/ScreenReader.d.ts +11 -0
  234. package/types/store/agent/StoreCatalogue.d.ts +26 -0
  235. package/types/store/agent/StoreSurfaceSource.d.ts +18 -0
  236. package/types/store/agent/index.d.ts +9 -0
  237. package/types/store/agent/storeSurface.d.ts +14 -0
  238. package/types/store/agent/types.d.ts +49 -0
  239. package/types/store/agent.d.ts +1 -0
  240. package/types/store/agentic/StToolBuilder.d.ts +41 -0
  241. package/types/store/agentic/attachAgentic.d.ts +14 -0
  242. package/types/store/agentic/index.d.ts +5 -0
  243. package/types/store/agentic/readableValue.d.ts +3 -0
  244. package/types/store/agentic/useStExpose.d.ts +8 -0
  245. package/types/store/agentic/useStState.d.ts +12 -0
  246. package/types/store/agentic.d.ts +1 -0
  247. package/types/store/baseSt.d.ts +29 -22
  248. package/types/store/databaseStateNames.d.ts +25 -0
  249. package/types/store/formSetterNames.d.ts +16 -0
  250. package/types/store/index.d.ts +7 -0
  251. package/types/store/rootStore.d.ts +5 -1
  252. package/types/store/sliceRole.d.ts +25 -0
  253. package/types/store/store.d.ts +7 -2
  254. package/types/store/storeInstance.d.ts +33 -1
  255. package/types/store/storeRegistry.d.ts +5 -0
  256. package/types/store/types.d.ts +15 -0
  257. package/types/store/withSelector.d.ts +7 -8
  258. package/types/test/registerDom.d.ts +1 -0
  259. package/types/ui/Agent/Approval.d.ts +7 -0
  260. package/types/ui/Agent/Bubble.d.ts +13 -0
  261. package/types/ui/Agent/Chat.d.ts +24 -0
  262. package/types/ui/Agent/Context.d.ts +9 -0
  263. package/types/ui/Agent/Dock.d.ts +16 -0
  264. package/types/ui/Agent/Guide.d.ts +9 -0
  265. package/types/ui/Agent/Section.d.ts +10 -0
  266. package/types/ui/Agent/StateKey.d.ts +16 -0
  267. package/types/ui/Agent/Tool.d.ts +15 -0
  268. package/types/ui/Agent/Transcript.d.ts +13 -0
  269. package/types/ui/Agent/Zone.d.ts +23 -0
  270. package/types/ui/Agent/fetchRunner.d.ts +12 -0
  271. package/types/ui/Agent/index.d.ts +17 -0
  272. package/types/ui/Agent/index_.d.ts +1 -0
  273. package/types/ui/Agent/sessionHistory.d.ts +12 -0
  274. package/types/ui/Agent.d.ts +1 -0
  275. package/types/ui/Badge.d.ts +1 -1
  276. package/types/ui/Button.d.ts +1 -1
  277. package/types/ui/CsrImage.d.ts +1 -1
  278. package/types/ui/Dropdown.d.ts +2 -0
  279. package/types/ui/Image.d.ts +3 -3
  280. package/types/ui/Layout/BottomInset.d.ts +2 -1
  281. package/types/ui/Layout/index.d.ts +1 -1
  282. package/types/ui/Signal/style.d.ts +4 -1
  283. package/types/ui/UiOverride/context.d.ts +14 -2
  284. package/types/ui/agentAttrs.d.ts +14 -0
  285. package/types/ui/index.d.ts +4 -1
  286. package/types/ui/overlayLayer.d.ts +24 -0
  287. package/types/ui/recipe/badgeRecipe.d.ts +7 -3
  288. package/types/ui/recipe/buttonRecipe.d.ts +7 -3
  289. package/types/ui/recipe/inputRecipe.d.ts +5 -1
  290. package/types/vendor/use-agentic/AgentProvider.d.ts +18 -0
  291. package/types/vendor/use-agentic/AgentScope.d.ts +9 -0
  292. package/types/vendor/use-agentic/AgentSession.d.ts +50 -0
  293. package/types/vendor/use-agentic/Agentic.d.ts +21 -0
  294. package/types/vendor/use-agentic/AgenticSurface.d.ts +44 -0
  295. package/types/vendor/use-agentic/httpRunner.d.ts +15 -0
  296. package/types/vendor/use-agentic/index.d.ts +13 -0
  297. package/types/vendor/use-agentic/surfaceContext.d.ts +5 -0
  298. package/types/vendor/use-agentic/types.d.ts +133 -0
  299. package/types/vendor/use-agentic/useAgent.d.ts +4 -0
  300. package/types/vendor/use-agentic/useAgentGuide.d.ts +6 -0
  301. package/types/vendor/use-agentic/useAgentResource.d.ts +7 -0
  302. package/types/vendor/use-agentic/useAgentState.d.ts +13 -0
  303. package/types/vendor/use-agentic/useAgentTool.d.ts +16 -0
  304. package/types/vendor/use-agentic.d.ts +1 -0
  305. package/types/webkit/index.d.ts +3 -0
  306. package/types/webkit/lazy.d.ts +12 -0
  307. package/types/webkit/useCsrValues.d.ts +3 -3
  308. package/types/webkit/useEscapeKey.d.ts +5 -0
  309. package/types/webkit/useFrameRuntime.d.ts +6 -1
  310. package/types/webkit/useScreenScope.d.ts +18 -0
  311. package/ui/Agent/Approval.tsx +29 -0
  312. package/ui/Agent/Bubble.tsx +74 -0
  313. package/ui/Agent/Chat.tsx +225 -0
  314. package/ui/Agent/Context.tsx +38 -0
  315. package/ui/Agent/Dock.tsx +72 -0
  316. package/ui/Agent/Guide.tsx +16 -0
  317. package/ui/Agent/Section.tsx +24 -0
  318. package/ui/Agent/StateKey.tsx +44 -0
  319. package/ui/Agent/Tool.tsx +66 -0
  320. package/ui/Agent/Transcript.tsx +33 -0
  321. package/ui/Agent/Zone.tsx +48 -0
  322. package/ui/Agent/fetchRunner.ts +30 -0
  323. package/ui/Agent/index.ts +12 -0
  324. package/ui/Agent/index_.tsx +4 -0
  325. package/ui/Agent/sessionHistory.ts +33 -0
  326. package/ui/Badge.tsx +3 -3
  327. package/ui/BottomSheet.tsx +5 -0
  328. package/ui/Button.tsx +6 -2
  329. package/ui/Constant/Doc.tsx +1 -1
  330. package/ui/CsrImage.tsx +1 -1
  331. package/ui/Data/ListContainer.tsx +1 -1
  332. package/ui/DatePicker.tsx +5 -4
  333. package/ui/Dialog/Modal.tsx +12 -15
  334. package/ui/DraggableList.tsx +3 -1
  335. package/ui/Dropdown.tsx +33 -11
  336. package/ui/Field.tsx +30 -16
  337. package/ui/Image.tsx +3 -3
  338. package/ui/Input.tsx +14 -5
  339. package/ui/Layout/BottomInset.tsx +6 -1
  340. package/ui/Load/Units.tsx +11 -2
  341. package/ui/Load/View.tsx +7 -2
  342. package/ui/Loading/ProgressBar.tsx +8 -1
  343. package/ui/Menu.tsx +7 -8
  344. package/ui/Model/EditModal.tsx +37 -2
  345. package/ui/Model/SureToRemove.tsx +2 -1
  346. package/ui/Model/index_.tsx +42 -15
  347. package/ui/ObjectId.tsx +3 -4
  348. package/ui/Pagination.tsx +3 -4
  349. package/ui/Popconfirm.tsx +8 -7
  350. package/ui/Select.tsx +6 -4
  351. package/ui/Signal/RestApi.tsx +43 -16
  352. package/ui/Signal/WebSocket.tsx +1 -1
  353. package/ui/Signal/style.ts +6 -1
  354. package/ui/Switch.tsx +2 -0
  355. package/ui/System/CSR.tsx +6 -2
  356. package/ui/System/ThemeToggle.tsx +55 -33
  357. package/ui/ToggleSelect.tsx +4 -3
  358. package/ui/Tooltip.tsx +2 -1
  359. package/ui/UiOverride/context.ts +14 -2
  360. package/ui/agentAttrs.ts +19 -0
  361. package/ui/index.ts +10 -1
  362. package/ui/overlayLayer.ts +39 -0
  363. package/ui/recipe/badgeRecipe.ts +22 -3
  364. package/ui/recipe/buttonRecipe.ts +51 -2
  365. package/ui/recipe/factory.ts +2 -2
  366. package/ui/recipe/inputRecipe.ts +18 -4
  367. package/vendor/use-agentic/AgentProvider.tsx +39 -0
  368. package/vendor/use-agentic/AgentScope.tsx +20 -0
  369. package/vendor/use-agentic/AgentSession.ts +292 -0
  370. package/vendor/use-agentic/Agentic.tsx +44 -0
  371. package/vendor/use-agentic/AgenticSurface.ts +294 -0
  372. package/vendor/use-agentic/WIRE.md +57 -0
  373. package/vendor/use-agentic/httpRunner.ts +115 -0
  374. package/vendor/use-agentic/index.ts +14 -0
  375. package/vendor/use-agentic/surfaceContext.ts +9 -0
  376. package/vendor/use-agentic/types.ts +144 -0
  377. package/vendor/use-agentic/useAgent.ts +17 -0
  378. package/vendor/use-agentic/useAgentGuide.ts +16 -0
  379. package/vendor/use-agentic/useAgentResource.ts +30 -0
  380. package/vendor/use-agentic/useAgentState.ts +61 -0
  381. package/vendor/use-agentic/useAgentTool.ts +55 -0
  382. package/webkit/bootCsr.tsx +2 -33
  383. package/webkit/index.ts +3 -0
  384. package/webkit/lazy.tsx +27 -3
  385. package/webkit/useCsrValues.ts +121 -4
  386. package/webkit/useEscapeKey.tsx +42 -0
  387. package/webkit/useFrameRuntime.ts +65 -32
  388. package/webkit/useScreenScope.tsx +49 -0
@@ -0,0 +1,368 @@
1
+ import { leakingFieldsOf, type MaskModel, mask } from "akanjs/constant";
2
+ import type { JsonSchema } from "../schema";
3
+
4
+ export type PromptRole = "user" | "assistant";
5
+
6
+ /**
7
+ * What a client may do with a block when it cannot keep all of them.
8
+ *
9
+ * `priority` is the field that matters here: a prompt this server assembles is often mostly context — a document
10
+ * embedded beside the one line asking for something — and a client with a full window drops blocks by this number
11
+ * rather than by position. Leaving it off means every block is equally droppable, so the instruction can go and
12
+ * the attachment stay.
13
+ */
14
+ export interface PromptAnnotations {
15
+ /** Who the block is for. A note meant only for the model is `["assistant"]`, so a UI need not render it. */
16
+ audience?: PromptRole[];
17
+ /** 0 is "drop this first", 1 is "this is the point of the prompt". Anything outside the range is refused. */
18
+ priority?: number;
19
+ /** ISO 8601. Lets a client tell a re-fetched resource from the copy it already holds. */
20
+ lastModified?: string;
21
+ }
22
+
23
+ export interface PromptTextContent {
24
+ type: "text";
25
+ text: string;
26
+ annotations?: PromptAnnotations;
27
+ }
28
+ export interface PromptBinaryContent {
29
+ type: "image" | "audio";
30
+ data: string;
31
+ mimeType: string;
32
+ annotations?: PromptAnnotations;
33
+ }
34
+ export interface PromptResourceLinkContent {
35
+ type: "resource_link";
36
+ uri: string;
37
+ /** Required by the spec: `ResourceLink` extends `BaseMetadata`, whose `name` is not optional. */
38
+ name: string;
39
+ description?: string;
40
+ mimeType?: string;
41
+ annotations?: PromptAnnotations;
42
+ }
43
+ export interface PromptEmbeddedResourceContent {
44
+ type: "resource";
45
+ resource: { uri: string; mimeType: string; text: string };
46
+ annotations?: PromptAnnotations;
47
+ }
48
+ export type PromptContent =
49
+ | PromptTextContent
50
+ | PromptBinaryContent
51
+ | PromptResourceLinkContent
52
+ | PromptEmbeddedResourceContent;
53
+
54
+ export interface PromptMessage {
55
+ role: PromptRole;
56
+ content: PromptContent;
57
+ }
58
+
59
+ /** What a `prompt()` exec may return. A bare string is the 80% case and is wrapped into one user message. */
60
+ export type PromptResult = string | PromptMessage[];
61
+
62
+ /** Enough of the `File` model to link or inline it, structural so the framework does not depend on the lib. */
63
+ export interface PromptFileSource {
64
+ url: string;
65
+ filename?: string;
66
+ mimetype?: string;
67
+ }
68
+
69
+ /**
70
+ * A model class, named by the caller so an attachment can be masked by what it *is* rather than by what it still
71
+ * carries at runtime. The same model any other audience masks by — see `mask` in `akanjs/constant`.
72
+ */
73
+ export type PromptModel = MaskModel;
74
+
75
+ /**
76
+ * The string fields each block type must carry, and the set of legal types at once.
77
+ *
78
+ * A client parses `prompts/get` against a discriminated union, so a block missing one of these is not a thinner
79
+ * block — it matches no member and the whole reply throws on the client. `resource` carries a nested shape instead
80
+ * and is checked on its own.
81
+ */
82
+ const contentFields = new Map<string, readonly string[]>([
83
+ ["text", ["text"]],
84
+ ["image", ["data", "mimeType"]],
85
+ ["audio", ["data", "mimeType"]],
86
+ ["resource_link", ["uri", "name"]],
87
+ ["resource", []],
88
+ ]);
89
+
90
+ /**
91
+ * Builds the messages a `prompt()` endpoint returns.
92
+ *
93
+ * Named `Msg` rather than `msg` because `akanjs/dictionary` already exports a `msg` for toasts.
94
+ *
95
+ * Every attachment builder carries the `user` role. Content the server assembles is context handed *to* the
96
+ * model, which is what the user role means; an assistant-role attachment would be the server putting words in the
97
+ * model's mouth. That is only meaningful for few-shot text, which `Msg.assistant` covers.
98
+ */
99
+ export class Msg {
100
+ /**
101
+ * What every `prompt()` route answers with, as JSON Schema, for the app's OpenAPI document.
102
+ *
103
+ * A prompt declares `Any` on the wire, so the generated response schema was `{}` — a documented `GET` whose body
104
+ * the document could not describe, which is half of the agreement the HTTP route was mounted for. The shape is
105
+ * fixed by the protocol rather than by the endpoint, so it is written once, here: the block types and the fields
106
+ * each must carry come off `contentFields`, so a type added to one cannot describe itself out of the other.
107
+ */
108
+ static readonly schema: JsonSchema = {
109
+ type: "object",
110
+ properties: {
111
+ role: { type: "string", enum: ["user", "assistant"] },
112
+ content: {
113
+ oneOf: [...contentFields].map(([type, fields]) => ({
114
+ type: "object",
115
+ properties: {
116
+ type: { const: type },
117
+ ...Object.fromEntries(fields.map((field) => [field, { type: "string" }])),
118
+
119
+ ...(type === "resource"
120
+ ? {
121
+ resource: {
122
+ type: "object",
123
+ properties: { uri: { type: "string" }, mimeType: { type: "string" }, text: { type: "string" } },
124
+ required: ["uri"],
125
+ },
126
+ }
127
+ : {}),
128
+ ...(type === "resource_link" ? { description: { type: "string" }, mimeType: { type: "string" } } : {}),
129
+ annotations: {
130
+ type: "object",
131
+ properties: {
132
+ audience: { type: "array", items: { type: "string", enum: ["user", "assistant"] } },
133
+ priority: { type: "number", minimum: 0, maximum: 1 },
134
+ lastModified: { type: "string", format: "date-time" },
135
+ },
136
+ },
137
+ },
138
+ required: ["type", ...fields, ...(type === "resource" ? ["resource"] : [])],
139
+ additionalProperties: false,
140
+ })),
141
+ },
142
+ },
143
+ required: ["role", "content"],
144
+ additionalProperties: false,
145
+ };
146
+
147
+ static user(text: string, annotations?: PromptAnnotations): PromptMessage {
148
+ return { role: "user", content: Msg.#annotated({ type: "text", text }, annotations) };
149
+ }
150
+
151
+ static assistant(text: string, annotations?: PromptAnnotations): PromptMessage {
152
+ return { role: "assistant", content: Msg.#annotated({ type: "text", text }, annotations) };
153
+ }
154
+
155
+ /**
156
+ * Embeds the value itself. The payload travels in the prompt, so prefer `link` for anything large.
157
+ *
158
+ * Name the model it is an instance of and the `hidden`/`secret` fields are stripped before it goes out:
159
+ * `Msg.resource(uri, order, { model: cnst.Order })`. A payload you assembled yourself needs no model and is
160
+ * embedded as given — but one that still carries a document's secret fields is refused rather than sent, so
161
+ * the rule is the same either way: a document travels masked, or it does not travel.
162
+ */
163
+ static resource(
164
+ uri: string,
165
+ value: unknown,
166
+ { model, ...annotations }: { model?: PromptModel } & PromptAnnotations = {},
167
+ ): PromptMessage {
168
+ const payload = model ? Msg.mask(model, value) : Msg.#assertMasked(uri, value);
169
+ return {
170
+ role: "user",
171
+ content: Msg.#annotated(
172
+ { type: "resource", resource: { uri, mimeType: "application/json", text: JSON.stringify(payload) } },
173
+ annotations,
174
+ ),
175
+ };
176
+ }
177
+
178
+ /**
179
+ * Strips what a model marks `hidden` or `secret`, by the model the caller names rather than by the one the
180
+ * value happens to still carry.
181
+ *
182
+ * That distinction is the whole fix. A check that reads the class off the value can only mask what arrives as an
183
+ * instance, so a `{ ...doc }` spread, a `toJSON()`, or a round-trip through `JSON.stringify` reached the wire
184
+ * with the metadata already gone and nothing could be done about it. A named model is metadata the value cannot
185
+ * lose, so a hydrated document and a plain object copied out of one mask identically.
186
+ *
187
+ * This is the field half of `resolveReturn` and deliberately not the whole of it. That one also loads every
188
+ * relation it walks past, which is right for a query's return value and wrong for an attachment, where it would
189
+ * turn embedding one document into a fan of queries nobody asked for. So a populated relation is masked in
190
+ * place and one that is still an id is left as an id.
191
+ *
192
+ * Public because a payload can be an assembly of several documents — `{ order, customer }` names no single
193
+ * model, so each piece is masked on its way in.
194
+ *
195
+ * Returns `unknown` rather than the argument's type, because what comes back is missing fields that type still
196
+ * promises. The value's only destination is a JSON payload, so nothing downstream wanted the type anyway.
197
+ */
198
+ static mask(model: PromptModel, value: unknown): unknown {
199
+ return mask(model, value);
200
+ }
201
+
202
+ /**
203
+ * Points at something without paying for it. The client decides whether to fetch, and skips what it already
204
+ * holds — so a prompt that references twenty documents costs twenty URIs rather than twenty payloads.
205
+ */
206
+ static link(
207
+ source: string | PromptFileSource,
208
+ { name, description, ...annotations }: { name?: string; description?: string } & PromptAnnotations = {},
209
+ ): PromptMessage {
210
+ const file = typeof source === "string" ? null : source;
211
+ const uri = typeof source === "string" ? source : source.url;
212
+ return {
213
+ role: "user",
214
+ content: Msg.#annotated(
215
+ {
216
+ type: "resource_link",
217
+ uri,
218
+ name: Msg.#linkName(uri, name ?? file?.filename),
219
+ ...(description ? { description } : {}),
220
+ ...(file?.mimetype ? { mimeType: file.mimetype } : {}),
221
+ },
222
+ annotations,
223
+ ),
224
+ };
225
+ }
226
+
227
+ /**
228
+ * Never absent, because the spec's `name` is required and a client SDK parses the block against a union it then
229
+ * matches nothing in — a link with no name is not a nameless link, it is a `prompts/get` that throws.
230
+ *
231
+ * The last path segment is the fallback rather than the whole URI: for `akan://order/42` it is the identifier a
232
+ * person reading the list would use, and for a file URL it is the filename we would have used anyway.
233
+ */
234
+ static #linkName(uri: string, name?: string) {
235
+ if (name) return name;
236
+ const segment = uri.split(/[?#]/)[0]?.split("/").filter(Boolean).pop();
237
+ return segment ?? uri;
238
+ }
239
+
240
+ static image(data: string, mimeType: string, annotations?: PromptAnnotations): PromptMessage {
241
+ return { role: "user", content: Msg.#annotated({ type: "image", data, mimeType }, annotations) };
242
+ }
243
+
244
+ static audio(data: string, mimeType: string, annotations?: PromptAnnotations): PromptMessage {
245
+ return { role: "user", content: Msg.#annotated({ type: "audio", data, mimeType }, annotations) };
246
+ }
247
+
248
+ /**
249
+ * Inlines a file as base64, costing roughly 1.33× its bytes in the prompt. Worth it only when the client
250
+ * cannot fetch the URL itself — a public asset is cheaper as `Msg.link`. Fetched as this process, so a file
251
+ * behind a caller-scoped signed URL needs its bytes passed to `Msg.image` instead.
252
+ */
253
+ static async imageOf(file: PromptFileSource, annotations?: PromptAnnotations): Promise<PromptMessage> {
254
+ const response = await fetch(file.url, { signal: AbortSignal.timeout(20_000) });
255
+ if (!response.ok) throw new Error(`Failed to inline ${file.url}: ${response.status}`);
256
+ const mimeType = file.mimetype ?? response.headers.get("content-type") ?? "application/octet-stream";
257
+ return Msg.image(Buffer.from(await response.arrayBuffer()).toString("base64"), mimeType, annotations);
258
+ }
259
+
260
+ /**
261
+ * Refuses an undeclared payload that still carries a document's secret fields, rather than sending it.
262
+ *
263
+ * A warning was the older answer, on the reasoning that masking off the value's own class would reach only the
264
+ * payloads that still had one — half masked, half not, and an author who believes prompts are masked is worse
265
+ * off on the unmasked half. `mask` removes that objection by taking the model as an argument instead, so there
266
+ * is now a way to be right about every payload and this is the shape that did not take it.
267
+ *
268
+ * It throws only where it can prove a leak: a value whose class says those fields exist and whose own keys say
269
+ * they are populated. A `Light<Model>`, or anything assembled by hand, declares no such fields and passes.
270
+ */
271
+ static #assertMasked(uri: string, value: unknown) {
272
+ for (const sample of Msg.#samples(value)) Msg.#assertSample(uri, sample);
273
+ return value;
274
+ }
275
+
276
+ /**
277
+ * The values a refusal could be about: the payload, and — when the payload is a plain object — one level into it.
278
+ *
279
+ * A list is homogeneous in practice, so its first element answers for it; walking every element to decide
280
+ * whether to refuse would cost more than the thing it is checking.
281
+ *
282
+ * The level down is what makes the common assembly reachable. A document rarely travels alone — it arrives as
283
+ * `{ order }` or `{ order, customer }` — and a plain object's own constructor carries no field metadata, so a
284
+ * check that stopped at the outer value saw neither the wrapper (which has nothing to show) nor what it wrapped.
285
+ * It stops there rather than recursing: a payload nested two deep is one somebody assembled deliberately, and no
286
+ * depth reaches metadata a spread has already thrown away.
287
+ */
288
+ static #samples(value: unknown): Record<string, unknown>[] {
289
+ const sample = (Array.isArray(value) ? value[0] : value) as Record<string, unknown> | null | undefined;
290
+ if (!sample || typeof sample !== "object") return [];
291
+ if (sample.constructor !== Object) return [sample];
292
+ return Object.values(sample).flatMap((nested) => {
293
+ const inner = (Array.isArray(nested) ? nested[0] : nested) as Record<string, unknown> | null | undefined;
294
+ return inner && typeof inner === "object" && inner.constructor !== Object ? [inner] : [];
295
+ });
296
+ }
297
+
298
+ static #assertSample(uri: string, sample: Record<string, unknown>) {
299
+ const model = sample.constructor as PromptModel | undefined;
300
+ const leaking = model ? leakingFieldsOf(model, sample) : [];
301
+ if (!leaking.length) return;
302
+ throw new Error(
303
+ `Msg.resource("${uri}") embeds ${model?.name} with its hidden/secret fields populated: ${leaking.join(", ")}. Name the model so they are stripped — Msg.resource(uri, value, { model: cnst.${model?.name} }), or Msg.mask(cnst.${model?.name}, value) for one piece of an assembled payload.`,
304
+ );
305
+ }
306
+
307
+ /**
308
+ * An empty annotation object is dropped rather than emitted: a block carrying `annotations: {}` reads to a
309
+ * client as a deliberate "no audience, no priority", which is not the same as saying nothing.
310
+ *
311
+ * A `priority` outside 0..1 throws instead of being clamped. The spec's range is what gives the number its
312
+ * meaning, and a client that meets 5 is free to ignore the field entirely — so a silent clamp would turn a
313
+ * typo into blocks dropped in an order nobody chose.
314
+ */
315
+ static #annotated<T extends PromptContent>(content: T, annotations?: PromptAnnotations): T {
316
+ if (!annotations || !Object.keys(annotations).length) return content;
317
+ const { priority } = annotations;
318
+ if (priority !== undefined && (priority < 0 || priority > 1))
319
+ throw new Error(`Prompt annotation priority must be between 0 and 1, got ${priority}`);
320
+ return { ...content, annotations };
321
+ }
322
+
323
+ /**
324
+ * The one runtime check on a prompt's return value. `prompt()` carries `Any` on the wire so the signal
325
+ * pipeline hands the value back untouched — nothing upstream would notice a malformed message, and the client
326
+ * would receive it as a valid prompt.
327
+ */
328
+ static normalize(value: unknown): PromptMessage[] {
329
+ if (typeof value === "string") return [Msg.user(value)];
330
+ if (!Array.isArray(value)) throw new Error(`A prompt must return a string or PromptMessage[], got ${typeof value}`);
331
+ value.forEach((message, idx) => {
332
+ Msg.#assertMessage(message, idx);
333
+ });
334
+ return value as PromptMessage[];
335
+ }
336
+
337
+ /**
338
+ * Checked down to the fields, not just the discriminator: the shapes this framework can build wrongly are all
339
+ * inside a block a client would then reject, and a check that stops at `content.type` cannot see any of them.
340
+ */
341
+ static #assertMessage(message: unknown, idx: number) {
342
+ const { role, content } = (message ?? {}) as { role?: unknown; content?: unknown };
343
+ if (role !== "user" && role !== "assistant") throw new Error(`Prompt message ${idx} has role "${String(role)}"`);
344
+ const block = (content ?? {}) as Record<string, unknown>;
345
+ const fields = typeof block.type === "string" ? contentFields.get(block.type) : undefined;
346
+ if (!fields) throw new Error(`Prompt message ${idx} has content type "${String(block.type)}"`);
347
+ const missing = fields.filter((field) => typeof block[field] !== "string" || !block[field]);
348
+ if (missing.length) throw new Error(`Prompt message ${idx} (${block.type}) is missing ${missing.join(", ")}`);
349
+ if (block.type === "resource") Msg.#assertResource(block.resource, idx);
350
+ Msg.#assertPriority(block.annotations, idx);
351
+ }
352
+
353
+ /** The one nested block, and the one whose payload may arrive as either `text` or a base64 `blob`. */
354
+ static #assertResource(resource: unknown, idx: number) {
355
+ const { uri, text, blob } = (resource ?? {}) as Record<string, unknown>;
356
+ if (typeof uri !== "string" || !uri) throw new Error(`Prompt message ${idx} (resource) is missing resource.uri`);
357
+ if (typeof text !== "string" && typeof blob !== "string")
358
+ throw new Error(`Prompt message ${idx} (resource) has neither resource.text nor resource.blob`);
359
+ }
360
+
361
+ /** Same range the builders enforce, for a message an author assembled without them. */
362
+ static #assertPriority(annotations: unknown, idx: number) {
363
+ const priority = (annotations as { priority?: unknown } | null)?.priority;
364
+ if (priority === undefined) return;
365
+ if (typeof priority !== "number" || priority < 0 || priority > 1)
366
+ throw new Error(`Prompt message ${idx} has annotations.priority "${String(priority)}", not between 0 and 1`);
367
+ }
368
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./McpDocument";
2
+ export * from "./McpProgress";
3
+ export * from "./McpUriTemplate";
4
+ export * from "./Msg";
5
+ export * from "./mcpProtocol";
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Wire vocabulary for the MCP revisions this server answers.
3
+ *
4
+ * `2026-07-28` made the protocol stateless — no `initialize`, no session id, no server-opened stream — which is
5
+ * what makes a single `POST /mcp` route sufficient. Everything before it is the *legacy* era, still what shipping
6
+ * clients speak (measured: Claude Code 2.1.226 negotiates `2025-11-25`), and supporting it costs almost nothing
7
+ * here because a legacy server *may* decline to issue `Mcp-Session-Id`: without one the client sends no session
8
+ * header and never asks to resume a stream, so both eras run over the same stateless handler.
9
+ *
10
+ * `2025-06-18` is listed for the same reason. The surface this server actually implements — POST-only Streamable
11
+ * HTTP, no sessions, no server-initiated requests — is wire-identical between the two legacy revisions, and a
12
+ * client that proposes a version the server does not list is told to disconnect. Naming only the one revision that
13
+ * was measured turned "we tested against this" into "we refuse everything else".
14
+ */
15
+ export const MCP_MODERN_VERSION = "2026-07-28";
16
+ export const MCP_LEGACY_VERSION = "2025-11-25";
17
+ export const MCP_LEGACY_PRIOR_VERSION = "2025-06-18";
18
+ /** Newest first — `server/discover` and `initialize` both answer with this order, and `#negotiate` reads the ends. */
19
+ export const MCP_SUPPORTED_VERSIONS = [MCP_MODERN_VERSION, MCP_LEGACY_VERSION, MCP_LEGACY_PRIOR_VERSION] as const;
20
+ export type McpProtocolVersion = (typeof MCP_SUPPORTED_VERSIONS)[number];
21
+
22
+ export type McpEra = "modern" | "legacy";
23
+
24
+ export const MCP_META_PREFIX = "io.modelcontextprotocol/";
25
+ export const MCP_META_PROTOCOL_VERSION = `${MCP_META_PREFIX}protocolVersion`;
26
+ export const MCP_META_CLIENT_CAPABILITIES = `${MCP_META_PREFIX}clientCapabilities`;
27
+ export const MCP_META_CLIENT_INFO = `${MCP_META_PREFIX}clientInfo`;
28
+ export const MCP_META_SERVER_INFO = `${MCP_META_PREFIX}serverInfo`;
29
+
30
+ /**
31
+ * `-32020`..`-32099` is reserved by the spec, so nothing outside this table may be minted in that band.
32
+ * `-32002` (resource not found) is retired in the modern revision; unknown resources are `invalidParams`.
33
+ *
34
+ * The band also defines `-32021 missingRequiredClientCapability`, which is absent because this server requires
35
+ * none: it never samples, elicits, or reads roots. It belongs here the day one of those appears, not before — a
36
+ * constant nothing emits reads as a check someone forgot to write.
37
+ */
38
+ export const McpErrorCode = {
39
+ parse: -32700,
40
+ invalidRequest: -32600,
41
+ methodNotFound: -32601,
42
+ invalidParams: -32602,
43
+ internal: -32603,
44
+ headerMismatch: -32020,
45
+ unsupportedProtocolVersion: -32022,
46
+ } as const;
47
+ export type McpErrorCodeValue = (typeof McpErrorCode)[keyof typeof McpErrorCode];
48
+
49
+ export interface McpJsonRpcRequest {
50
+ jsonrpc: "2.0";
51
+ id?: string | number | null;
52
+ method?: string;
53
+ params?: Record<string, unknown>;
54
+ }
55
+
56
+ export interface McpToolAnnotations {
57
+ readOnlyHint?: boolean;
58
+ destructiveHint?: boolean;
59
+ idempotentHint?: boolean;
60
+ openWorldHint?: boolean;
61
+ }
62
+
63
+ export interface McpTool {
64
+ name: string;
65
+ title?: string;
66
+ description?: string;
67
+ inputSchema: Record<string, unknown>;
68
+ outputSchema?: Record<string, unknown>;
69
+ annotations?: McpToolAnnotations;
70
+ }
71
+
72
+ export interface McpResourceTemplate {
73
+ uriTemplate: string;
74
+ name: string;
75
+ title?: string;
76
+ description?: string;
77
+ mimeType?: string;
78
+ }
79
+
80
+ export interface McpResource {
81
+ uri: string;
82
+ name: string;
83
+ title?: string;
84
+ description?: string;
85
+ mimeType?: string;
86
+ }
87
+
88
+ export interface McpPromptArgument {
89
+ name: string;
90
+ description?: string;
91
+ required?: boolean;
92
+ }
93
+
94
+ /**
95
+ * A prompt is user-controlled — the client offers it as a slash command and the model never invokes it — so its
96
+ * `title` and `description` are read by a person, not inferred from a schema the way a tool's are.
97
+ */
98
+ export interface McpPrompt {
99
+ name: string;
100
+ title?: string;
101
+ description?: string;
102
+ arguments?: McpPromptArgument[];
103
+ }
104
+
105
+ export interface McpTextContent {
106
+ type: "text";
107
+ text: string;
108
+ }
109
+
110
+ export interface McpToolResult {
111
+ content: McpTextContent[];
112
+ structuredContent?: unknown;
113
+ isError?: boolean;
114
+ }
115
+
116
+ export interface McpResourceContents {
117
+ uri: string;
118
+ mimeType: string;
119
+ text: string;
120
+ }
@@ -1,4 +1,5 @@
1
1
  import type { BaseEnv, Cls, PromiseOrObject } from "akanjs/base";
2
+ import { Logger } from "akanjs/common";
2
3
  import { type CacheAdaptor, CacheAdaptorRole } from "akanjs/service";
3
4
  import dayjs from "dayjs";
4
5
  import type { SignalContext } from "./signalContext";
@@ -25,11 +26,14 @@ export class Logging extends middleware("logging") {
25
26
  override async use() {
26
27
  return async (context: SignalContext, next: () => Promise<unknown>) => {
27
28
  const start = Date.now();
28
- context.adaptor.logger.debug(`Before ${context.endpointInfo.type}-${context.key} / ${start}`);
29
+
30
+ const debug = Logger.shouldLog("debug");
31
+ if (debug) context.adaptor.logger.debug(`Before ${context.endpointInfo.type}-${context.key} / ${start}`);
29
32
  try {
30
33
  const result = await next();
31
- const duration = Date.now() - start;
32
- context.adaptor.logger.debug(`After ${context.endpointInfo.type}-${context.key} / ${duration}ms`);
34
+ if (debug) {
35
+ context.adaptor.logger.debug(`After ${context.endpointInfo.type}-${context.key} / ${Date.now() - start}ms`);
36
+ }
33
37
  return result;
34
38
  } catch (error) {
35
39
  const duration = Date.now() - start;