akanjs 3.0.2 → 3.1.0-rc.0

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 (378) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/base/baseEnv.ts +0 -4
  3. package/base/primitiveRegistry.ts +2 -2
  4. package/client/cookie.ts +5 -1
  5. package/client/csrLocation.ts +122 -0
  6. package/client/csrTypes.ts +32 -4
  7. package/client/device.ts +2 -1
  8. package/client/frameConfig.ts +78 -7
  9. package/client/index.ts +3 -0
  10. package/client/makePageProto.tsx +3 -2
  11. package/client/native/external-view.ts +1 -0
  12. package/client/route/RootLayoutDefinition.ts +7 -1
  13. package/client/route/RouteHead.ts +108 -0
  14. package/client/route/index.ts +1 -0
  15. package/client/router.ts +36 -23
  16. package/client/rscNavigation.ts +8 -2
  17. package/client/viewportMeta.ts +60 -0
  18. package/client/webManifest.ts +18 -0
  19. package/common/Logger.ts +7 -2
  20. package/common/PipelineNames.ts +31 -0
  21. package/common/PipelinePattern.ts +70 -0
  22. package/common/PipelinePlanSchema.ts +490 -0
  23. package/common/backoff.ts +14 -0
  24. package/common/index.ts +39 -0
  25. package/common/pipelinePlan.ts +259 -0
  26. package/common/routeConvention.ts +1 -0
  27. package/common/types.ts +17 -0
  28. package/constant/constantRegistry.ts +26 -6
  29. package/dictionary/base.dictionary.ts +8 -0
  30. package/dictionary/trans.ts +9 -1
  31. package/document/into.ts +5 -0
  32. package/fetch/client/fetchClient.ts +135 -31
  33. package/fetch/client/httpClient.ts +45 -0
  34. package/fetch/client/wsClient.ts +125 -16
  35. package/fetch/fetchType/buildFetch.type.ts +1 -0
  36. package/index.ts +243 -10
  37. package/package.json +1 -5
  38. package/server/akanApp.ts +5 -2
  39. package/server/akanServer.ts +44 -8
  40. package/server/artifact/builderRpc.ts +8 -3
  41. package/server/artifact/ipcTypes.ts +5 -2
  42. package/server/di/diLifecycle.ts +39 -3
  43. package/server/di/utils.ts +28 -1
  44. package/server/ed25519Key.ts +48 -0
  45. package/server/index.ts +1 -0
  46. package/server/machine/index.ts +2 -0
  47. package/server/machine/machineAccount.ts +27 -0
  48. package/server/machine/machineToken.ts +151 -0
  49. package/server/mcp/McpApps.ts +256 -0
  50. package/server/mcp/McpDispatcher.ts +31 -7
  51. package/server/mcp/McpRouter.ts +209 -46
  52. package/server/ops/opsToken.ts +3 -10
  53. package/server/resolver/database.resolver.ts +3 -0
  54. package/server/resolver/signal.resolver.ts +40 -3
  55. package/server/routeElementComposer.tsx +78 -2
  56. package/server/routeState.ts +6 -0
  57. package/server/routeTreeBuilder.ts +26 -9
  58. package/server/routing/apiRouter.ts +6 -3
  59. package/server/routing/roomReplay.ts +88 -0
  60. package/server/rscClient.tsx +53 -8
  61. package/server/rscWorker.tsx +141 -27
  62. package/server/rscWorkerHost.ts +18 -5
  63. package/server/sitemap.ts +14 -0
  64. package/server/ssrFromRscRenderer.tsx +12 -6
  65. package/server/ssrTypes.ts +3 -1
  66. package/server/systemPageDocument.tsx +38 -30
  67. package/server/types.tsx +2 -0
  68. package/server/webRouter.ts +74 -5
  69. package/service/injectInfo.ts +9 -1
  70. package/service/ipcTypes.ts +2 -1
  71. package/service/predefinedAdaptor/database.adaptor.ts +1 -146
  72. package/service/predefinedAdaptor/queue.adaptor.ts +44 -6
  73. package/service/predefinedAdaptor/queueBackoff.ts +12 -0
  74. package/service/predefinedAdaptor/solidQueue.adaptor.ts +17 -13
  75. package/service/predefinedAdaptor/sql/SqlDocumentStore.ts +44 -2
  76. package/service/predefinedAdaptor/sql/dialect/postgres.ts +3 -0
  77. package/service/predefinedAdaptor/sql/dialect/sqlite.ts +5 -2
  78. package/service/predefinedAdaptor/sql/search/fts5.ts +1 -1
  79. package/service/predefinedAdaptor/sql/types.ts +8 -6
  80. package/service/predefinedAdaptor/sql/values.ts +0 -23
  81. package/service/serve.ts +5 -1
  82. package/signal/agent.signal.ts +1 -1
  83. package/signal/base.signal.ts +2 -2
  84. package/signal/endpointIdempotency.ts +53 -0
  85. package/signal/internalArg.ts +14 -0
  86. package/signal/mcp/McpDocument.ts +38 -1
  87. package/signal/mcp/mcpProtocol.ts +18 -0
  88. package/signal/signalContext.ts +58 -30
  89. package/signal/signalRegistry.ts +14 -4
  90. package/signal/types.ts +18 -3
  91. package/store/agent/StoreSurfaceSource.ts +1 -1
  92. package/store/agentic/StToolBuilder.ts +3 -0
  93. package/test/conformance.ts +9 -33
  94. package/types/base/baseEnv.d.ts +0 -4
  95. package/types/base/primitiveRegistry.d.ts +1 -1
  96. package/types/client/csrLocation.d.ts +32 -0
  97. package/types/client/csrTypes.d.ts +40 -4
  98. package/types/client/frameConfig.d.ts +14 -2
  99. package/types/client/index.d.ts +3 -0
  100. package/types/client/native/external-view.d.ts +1 -0
  101. package/types/client/route/RootLayoutDefinition.d.ts +2 -1
  102. package/types/client/route/RouteHead.d.ts +13 -0
  103. package/types/client/route/index.d.ts +1 -0
  104. package/types/client/router.d.ts +6 -0
  105. package/types/client/rscNavigation.d.ts +4 -0
  106. package/types/client/viewportMeta.d.ts +18 -0
  107. package/types/client/webManifest.d.ts +4 -0
  108. package/types/common/PipelineNames.d.ts +6 -0
  109. package/types/common/PipelinePattern.d.ts +14 -0
  110. package/types/common/PipelinePlanSchema.d.ts +9 -0
  111. package/types/common/backoff.d.ts +10 -0
  112. package/types/common/index.d.ts +5 -0
  113. package/types/common/pipelinePlan.d.ts +224 -0
  114. package/types/common/types.d.ts +16 -0
  115. package/types/constant/constantRegistry.d.ts +5 -2
  116. package/types/dictionary/base.dictionary.d.ts +1 -1
  117. package/types/dictionary/dictionary.d.ts +8 -8
  118. package/types/document/into.d.ts +9 -0
  119. package/types/fetch/client/fetchClient.d.ts +31 -4
  120. package/types/fetch/client/httpClient.d.ts +8 -0
  121. package/types/fetch/client/wsClient.d.ts +26 -2
  122. package/types/fetch/fetchType/buildFetch.type.d.ts +1 -0
  123. package/types/index.d.ts +230 -9
  124. package/types/server/akanServer.d.ts +16 -1
  125. package/types/server/artifact/builderRpc.d.ts +7 -2
  126. package/types/server/artifact/ipcTypes.d.ts +5 -1
  127. package/types/server/di/utils.d.ts +1 -0
  128. package/types/server/ed25519Key.d.ts +13 -0
  129. package/types/server/index.d.ts +1 -0
  130. package/types/server/machine/index.d.ts +2 -0
  131. package/types/server/machine/machineAccount.d.ts +5 -0
  132. package/types/server/machine/machineToken.d.ts +29 -0
  133. package/types/server/machine.d.ts +1 -0
  134. package/types/server/mcp/McpApps.d.ts +50 -0
  135. package/types/server/mcp/McpDispatcher.d.ts +4 -1
  136. package/types/server/mcp/McpRouter.d.ts +4 -0
  137. package/types/server/resolver/signal.resolver.d.ts +2 -1
  138. package/types/server/routeElementComposer.d.ts +24 -4
  139. package/types/server/routeState.d.ts +4 -1
  140. package/types/server/routing/roomReplay.d.ts +24 -0
  141. package/types/server/rscWorkerHost.d.ts +5 -2
  142. package/types/server/sitemap.d.ts +2 -0
  143. package/types/server/ssrFromRscRenderer.d.ts +3 -3
  144. package/types/server/ssrTypes.d.ts +4 -1
  145. package/types/server/systemPageDocument.d.ts +2 -0
  146. package/types/server/types.d.ts +4 -1
  147. package/types/server/webRouter.d.ts +3 -1
  148. package/types/service/ipcTypes.d.ts +2 -0
  149. package/types/service/predefinedAdaptor/database.adaptor.d.ts +1 -24
  150. package/types/service/predefinedAdaptor/queue.adaptor.d.ts +10 -3
  151. package/types/service/predefinedAdaptor/queueBackoff.d.ts +4 -0
  152. package/types/service/predefinedAdaptor/solidQueue.adaptor.d.ts +3 -3
  153. package/types/service/predefinedAdaptor/sql/SqlDocumentStore.d.ts +6 -1
  154. package/types/service/predefinedAdaptor/sql/dialect/postgres.d.ts +1 -0
  155. package/types/service/predefinedAdaptor/sql/dialect/sqlite.d.ts +1 -0
  156. package/types/service/predefinedAdaptor/sql/search/fts5.d.ts +1 -1
  157. package/types/service/predefinedAdaptor/sql/types.d.ts +9 -5
  158. package/types/service/predefinedAdaptor/sql/values.d.ts +0 -3
  159. package/types/service/serve.d.ts +3 -0
  160. package/types/signal/endpointIdempotency.d.ts +7 -0
  161. package/types/signal/internalArg.d.ts +10 -0
  162. package/types/signal/mcp/McpDocument.d.ts +8 -0
  163. package/types/signal/mcp/mcpProtocol.d.ts +17 -0
  164. package/types/signal/signalContext.d.ts +5 -3
  165. package/types/signal/signalRegistry.d.ts +4 -4
  166. package/types/signal/types.d.ts +21 -1
  167. package/types/store/agentic/StToolBuilder.d.ts +2 -0
  168. package/types/test/conformance.d.ts +7 -10
  169. package/types/ui/Agent/Chat.d.ts +5 -1
  170. package/types/ui/Agent/EmbedApproval.d.ts +1 -0
  171. package/types/ui/Agent/index.d.ts +3 -0
  172. package/types/ui/Agent/useKeyboardFrame.d.ts +2 -0
  173. package/types/ui/Agent/useScreenActions.d.ts +18 -0
  174. package/types/ui/BottomSheet.d.ts +1 -0
  175. package/types/ui/Constant/Doc.d.ts +11 -17
  176. package/types/ui/Constant/index.d.ts +7 -2
  177. package/types/ui/Constant/schemaDoc.d.ts +11 -0
  178. package/types/ui/Dialog/Modal.d.ts +6 -1
  179. package/types/ui/Dialog/index.d.ts +1 -1
  180. package/types/ui/Dialog/modalSurface.d.ts +12 -0
  181. package/types/ui/Layout/BottomTab.d.ts +11 -2
  182. package/types/ui/Layout/FrameSlotFallback.d.ts +9 -0
  183. package/types/ui/Layout/Navbar.d.ts +4 -1
  184. package/types/ui/Layout/TopInset.d.ts +1 -1
  185. package/types/ui/Layout/index.d.ts +3 -3
  186. package/types/ui/Link/Action.d.ts +5 -1
  187. package/types/ui/Link/Anchor.d.ts +5 -3
  188. package/types/ui/Link/activePath.d.ts +13 -0
  189. package/types/ui/Link/index.d.ts +1 -1
  190. package/types/ui/Modal.d.ts +6 -1
  191. package/types/ui/Model/EditModal.d.ts +6 -1
  192. package/types/ui/Model/New.d.ts +6 -1
  193. package/types/ui/Model/ViewEditModal.d.ts +6 -1
  194. package/types/ui/Model/ViewModal.d.ts +6 -1
  195. package/types/ui/Model/newFormOrigin.d.ts +7 -0
  196. package/types/ui/Portal.d.ts +3 -1
  197. package/types/ui/Reference/origin.d.ts +12 -0
  198. package/types/ui/Signal/Doc.d.ts +23 -18
  199. package/types/ui/Signal/Listener.d.ts +2 -6
  200. package/types/ui/Signal/Object.d.ts +6 -10
  201. package/types/ui/Signal/Response.d.ts +3 -6
  202. package/types/ui/Signal/RestApi.d.ts +11 -15
  203. package/types/ui/Signal/WebSocket.d.ts +11 -21
  204. package/types/ui/Signal/endpointEntries.d.ts +8 -0
  205. package/types/ui/Signal/index.d.ts +35 -12
  206. package/types/ui/Signal/signalText.d.ts +178 -0
  207. package/types/ui/System/CSR.d.ts +2 -2
  208. package/types/ui/System/Client.d.ts +4 -3
  209. package/types/ui/System/Common.d.ts +27 -6
  210. package/types/ui/System/SSR.d.ts +6 -6
  211. package/types/ui/Tooltip.d.ts +4 -2
  212. package/types/ui/index.d.ts +2 -1
  213. package/types/ui/overlayLayer.d.ts +6 -0
  214. package/types/ui/overlayPosition.d.ts +17 -0
  215. package/types/vendor/@akanjs/native/packages/cli/src/api.d.ts +14 -3
  216. package/types/vendor/@akanjs/native/packages/cli/src/commands/update.d.ts +1 -1
  217. package/types/vendor/@akanjs/native/packages/cli/src/config.d.ts +30 -5
  218. package/types/vendor/@akanjs/native/packages/cli/src/lib/compat.d.ts +8 -0
  219. package/types/vendor/@akanjs/native/packages/cli/src/lib/desktop-server.d.ts +5 -0
  220. package/types/vendor/@akanjs/native/packages/cli/src/lib/distribution.d.ts +22 -0
  221. package/types/vendor/@akanjs/native/packages/cli/src/lib/project.d.ts +4 -0
  222. package/types/vendor/@akanjs/native/packages/cli/src/lib/publish.d.ts +16 -10
  223. package/types/vendor/@akanjs/native/packages/cli/src/lib/updates.d.ts +51 -7
  224. package/types/vendor/@akanjs/native/packages/cli/src/lib/vectors.d.ts +1 -1
  225. package/types/vendor/@akanjs/native/packages/cli/src/platforms/windows-installer.d.ts +7 -0
  226. package/types/vendor/@akanjs/native/packages/cli/src/platforms/windows.d.ts +5 -0
  227. package/types/vendor/@akanjs/native/packages/core/src/kernel.d.ts +36 -0
  228. package/types/vendor/@akanjs/native/packages/desktop/src/plugin.d.ts +2 -0
  229. package/types/vendor/@akanjs/native/packages/desktop/src/server.d.ts +11 -0
  230. package/types/vendor/@akanjs/native/plugins/external-view/src/desktop.d.ts +17 -0
  231. package/types/vendor/@akanjs/native/plugins/external-view/src/index.d.ts +132 -0
  232. package/types/vendor/@akanjs/native/plugins/external-view/src.d.ts +1 -0
  233. package/types/vendor/@akanjs/native/plugins/updates/src/index.d.ts +8 -0
  234. package/types/vendor/@akanjs/native/plugins/window/src/desktop.d.ts +4 -1
  235. package/types/vendor/@akanjs/native/plugins/window/src/index.d.ts +49 -0
  236. package/types/vendor/use-agentic/types.d.ts +2 -0
  237. package/types/webkit/CsrStack.d.ts +1 -1
  238. package/types/webkit/McpAppAgent.d.ts +14 -0
  239. package/types/webkit/McpAppApprovals.d.ts +8 -0
  240. package/types/webkit/McpAppBridge.d.ts +101 -0
  241. package/types/webkit/McpAppView.d.ts +21 -0
  242. package/types/webkit/index.d.ts +1 -0
  243. package/types/webkit/useLocation.d.ts +1 -1
  244. package/types/webkit/useVisualViewportFrame.d.ts +13 -0
  245. package/ui/Agent/Chat.tsx +29 -10
  246. package/ui/Agent/Composer.tsx +2 -1
  247. package/ui/Agent/EmbedApproval.tsx +17 -0
  248. package/ui/Agent/RichInput.tsx +1 -1
  249. package/ui/Agent/index.ts +2 -0
  250. package/ui/Agent/useKeyboardFrame.ts +10 -0
  251. package/ui/Agent/useScreenActions.ts +45 -0
  252. package/ui/BottomSheet.tsx +82 -53
  253. package/ui/Constant/Doc.tsx +113 -60
  254. package/ui/Constant/index.ts +2 -2
  255. package/ui/Constant/schemaDoc.ts +86 -26
  256. package/ui/Dialog/LegacyModal.tsx +53 -52
  257. package/ui/Dialog/Modal.tsx +93 -49
  258. package/ui/Dialog/modalSurface.ts +61 -0
  259. package/ui/DragAction.tsx +1 -1
  260. package/ui/DraggableList.tsx +1 -1
  261. package/ui/Dropdown.tsx +4 -6
  262. package/ui/KeyboardAvoiding.tsx +1 -1
  263. package/ui/Layout/BottomInset.tsx +20 -14
  264. package/ui/Layout/BottomTab.tsx +42 -16
  265. package/ui/Layout/FrameSlotFallback.tsx +59 -0
  266. package/ui/Layout/Navbar.tsx +37 -11
  267. package/ui/Layout/Sider.tsx +1 -1
  268. package/ui/Layout/TopInset.tsx +15 -14
  269. package/ui/Link/Action.tsx +15 -5
  270. package/ui/Link/Anchor.tsx +25 -13
  271. package/ui/Link/activePath.ts +25 -0
  272. package/ui/Link/index.tsx +1 -1
  273. package/ui/Load/Pagination.tsx +1 -1
  274. package/ui/Load/Units.tsx +1 -1
  275. package/ui/Loading/ProgressBar.tsx +1 -1
  276. package/ui/Modal.tsx +9 -0
  277. package/ui/Model/EditModal.tsx +16 -1
  278. package/ui/Model/New.tsx +25 -2
  279. package/ui/Model/NewWrapper_Client.tsx +2 -0
  280. package/ui/Model/ViewEditModal.tsx +9 -0
  281. package/ui/Model/ViewModal.tsx +16 -1
  282. package/ui/Model/newFormOrigin.ts +45 -0
  283. package/ui/Popconfirm.tsx +5 -7
  284. package/ui/Portal.tsx +4 -7
  285. package/ui/Reference/origin.ts +31 -0
  286. package/ui/ScreenNavigator.tsx +1 -1
  287. package/ui/Select.tsx +2 -7
  288. package/ui/Signal/Arg.tsx +2 -2
  289. package/ui/Signal/Doc.tsx +125 -63
  290. package/ui/Signal/Endpoint.tsx +11 -10
  291. package/ui/Signal/Listener.tsx +7 -10
  292. package/ui/Signal/Object.tsx +7 -14
  293. package/ui/Signal/Response.tsx +24 -24
  294. package/ui/Signal/RestApi.tsx +63 -52
  295. package/ui/Signal/WebSocket.tsx +65 -72
  296. package/ui/Signal/endpointEntries.ts +25 -0
  297. package/ui/Signal/index.ts +23 -6
  298. package/ui/Signal/signalText.ts +59 -0
  299. package/ui/System/CSR.tsx +34 -8
  300. package/ui/System/Client.tsx +36 -5
  301. package/ui/System/Common.tsx +76 -32
  302. package/ui/System/SSR.tsx +73 -31
  303. package/ui/Toast.tsx +1 -1
  304. package/ui/Tooltip.tsx +84 -30
  305. package/ui/index.ts +11 -1
  306. package/ui/overlayLayer.ts +25 -2
  307. package/ui/overlayPosition.ts +90 -0
  308. package/ui/recipe/inputRecipe.ts +8 -1
  309. package/ui/styles.css +152 -0
  310. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeActivity.kt +22 -2
  311. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeKernel.kt +37 -0
  312. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeUpdateReports.kt +169 -0
  313. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeUpdates.kt +110 -38
  314. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeVectors.kt +20 -0
  315. package/vendor/@akanjs/native/native/desktop/Cargo.lock +16 -16
  316. package/vendor/@akanjs/native/native/desktop/src/external.rs +651 -0
  317. package/vendor/@akanjs/native/native/desktop/src/json.rs +23 -0
  318. package/vendor/@akanjs/native/native/desktop/src/lib.rs +228 -5
  319. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeApp.swift +2 -1
  320. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeKernel.swift +47 -1
  321. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeUpdateReports.swift +145 -0
  322. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeUpdates.swift +112 -43
  323. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeVectors.swift +18 -0
  324. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeViewController.swift +24 -2
  325. package/vendor/@akanjs/native/packages/cli/src/api.ts +22 -6
  326. package/vendor/@akanjs/native/packages/cli/src/commands/build.ts +24 -8
  327. package/vendor/@akanjs/native/packages/cli/src/commands/update.ts +11 -9
  328. package/vendor/@akanjs/native/packages/cli/src/config.ts +35 -7
  329. package/vendor/@akanjs/native/packages/cli/src/lib/compat.ts +2 -0
  330. package/vendor/@akanjs/native/packages/cli/src/lib/configkeys.ts +6 -4
  331. package/vendor/@akanjs/native/packages/cli/src/lib/desktop-server.ts +11 -1
  332. package/vendor/@akanjs/native/packages/cli/src/lib/distribution.ts +73 -0
  333. package/vendor/@akanjs/native/packages/cli/src/lib/project.ts +15 -3
  334. package/vendor/@akanjs/native/packages/cli/src/lib/publish.ts +70 -23
  335. package/vendor/@akanjs/native/packages/cli/src/lib/updates.ts +159 -23
  336. package/vendor/@akanjs/native/packages/cli/src/lib/vectors.ts +2 -0
  337. package/vendor/@akanjs/native/packages/cli/src/platforms/android.ts +9 -4
  338. package/vendor/@akanjs/native/packages/cli/src/platforms/desktop-update.ts +1 -1
  339. package/vendor/@akanjs/native/packages/cli/src/platforms/desktop.ts +4 -2
  340. package/vendor/@akanjs/native/packages/cli/src/platforms/ios.ts +9 -4
  341. package/vendor/@akanjs/native/packages/cli/src/platforms/windows-installer.ts +25 -11
  342. package/vendor/@akanjs/native/packages/cli/src/platforms/windows.ts +14 -3
  343. package/vendor/@akanjs/native/packages/core/src/kernel.ts +49 -0
  344. package/vendor/@akanjs/native/packages/core/vectors/updates.json +31 -0
  345. package/vendor/@akanjs/native/packages/desktop/src/main.ts +3 -0
  346. package/vendor/@akanjs/native/packages/desktop/src/plugin.ts +2 -0
  347. package/vendor/@akanjs/native/packages/desktop/src/server.ts +70 -6
  348. package/vendor/@akanjs/native/plugins/external-view/native-plugin.json +23 -0
  349. package/vendor/@akanjs/native/plugins/external-view/src/desktop.ts +321 -0
  350. package/vendor/@akanjs/native/plugins/external-view/src/index.ts +106 -0
  351. package/vendor/@akanjs/native/plugins/updates/android/UpdatesPlugin.kt +133 -41
  352. package/vendor/@akanjs/native/plugins/updates/ios/UpdatesPlugin.swift +101 -36
  353. package/vendor/@akanjs/native/plugins/updates/native-plugin.json +4 -2
  354. package/vendor/@akanjs/native/plugins/updates/src/desktop.ts +15 -1
  355. package/vendor/@akanjs/native/plugins/updates/src/index.ts +7 -1
  356. package/vendor/@akanjs/native/plugins/window/native-plugin.json +4 -0
  357. package/vendor/@akanjs/native/plugins/window/src/desktop.ts +68 -1
  358. package/vendor/@akanjs/native/plugins/window/src/index.ts +47 -0
  359. package/vendor/use-agentic/ToolRunner.ts +8 -1
  360. package/vendor/use-agentic/types.ts +2 -0
  361. package/webkit/CsrRouteTable.ts +1 -0
  362. package/webkit/CsrStack.ts +9 -2
  363. package/webkit/McpAppAgent.ts +138 -0
  364. package/webkit/McpAppApprovals.ts +56 -0
  365. package/webkit/McpAppBridge.ts +291 -0
  366. package/webkit/McpAppView.ts +258 -0
  367. package/webkit/bootCsr.tsx +54 -5
  368. package/webkit/index.ts +1 -0
  369. package/webkit/useCsrValues.ts +16 -10
  370. package/webkit/useFrameRuntime.ts +10 -1
  371. package/webkit/useLocation.ts +4 -3
  372. package/webkit/useVisualViewportFrame.tsx +52 -0
  373. package/service/predefinedAdaptor/sql/driver/libsql.ts +0 -45
  374. package/types/service/predefinedAdaptor/sql/driver/libsql.d.ts +0 -20
  375. package/types/ui/Agent/useKeyboardInset.d.ts +0 -1
  376. package/types/ui/ServerPortal.d.ts +0 -15
  377. package/ui/Agent/useKeyboardInset.ts +0 -19
  378. package/ui/ServerPortal.tsx +0 -49
@@ -20,8 +20,15 @@ export interface ServerManifest {
20
20
  /** The file in resources/server that starts the server. */
21
21
  entry: string;
22
22
  env: Record<string, string>;
23
+ /** Crashes in a row before the launcher gives up, MAX_FAILURES unless named; "forever" never gives up. */
24
+ restart?: number | "forever";
25
+ /** The health route asked every `intervalMs` once the server is ready; `failures` missed in a row restart it. */
26
+ watchdog?: { intervalMs: number; failures: number };
23
27
  }
24
28
 
29
+ /** Answered by the server's own process, solo or behind its gateway, without a database round trip. */
30
+ export const HEALTH_PATH = "/_akan/app/health";
31
+
25
32
  /** Set by the launcher at every start, so desktop.server.env may not name them (cli lib/desktop-server.ts). */
26
33
  export const LAUNCHER_ENV_KEYS = [
27
34
  "BUN_BE_BUN",
@@ -138,6 +145,8 @@ export interface DesktopServerOptions {
138
145
  stopGrace?: number;
139
146
  restartDelay?(failures: number, everReady: boolean): number;
140
147
  now?(): number;
148
+ /** Whether the server at `url` answers its health route; the watchdog's question. */
149
+ probe?(url: string, timeoutMs: number): Promise<boolean>;
141
150
  }
142
151
 
143
152
  export interface DesktopServer {
@@ -186,14 +195,28 @@ export function createServerStatus() {
186
195
  export function readServerManifest(resources: string): ServerManifest | null {
187
196
  const file = join(resources, "server.json");
188
197
  if (!existsSync(file)) return null;
189
- const raw = JSON.parse(readFileSync(file, "utf8")) as { entry?: unknown; env?: unknown };
198
+ const raw = JSON.parse(readFileSync(file, "utf8")) as {
199
+ entry?: unknown;
200
+ env?: unknown;
201
+ restart?: unknown;
202
+ watchdog?: { intervalMs?: unknown; failures?: unknown } | null;
203
+ };
190
204
  if (typeof raw.entry !== "string" || !raw.entry) throw new Error(`${file}: entry must name a file`);
191
205
  const env = Object.fromEntries(
192
206
  Object.entries((raw.env ?? {}) as Record<string, unknown>).filter(
193
207
  (entry): entry is [string, string] => typeof entry[1] === "string",
194
208
  ),
195
209
  );
196
- return { entry: raw.entry, env };
210
+ const restart =
211
+ raw.restart === "forever" || (Number.isInteger(raw.restart) && (raw.restart as number) > 0)
212
+ ? (raw.restart as number | "forever")
213
+ : undefined;
214
+ const { intervalMs, failures } = raw.watchdog ?? {};
215
+ const watchdog =
216
+ Number.isInteger(intervalMs) && (intervalMs as number) > 0 && Number.isInteger(failures) && (failures as number) > 0
217
+ ? { intervalMs: intervalMs as number, failures: failures as number }
218
+ : undefined;
219
+ return { entry: raw.entry, env, ...(restart ? { restart } : {}), ...(watchdog ? { watchdog } : {}) };
197
220
  }
198
221
 
199
222
  export function serverArgv(execPath: string, resources: string, entry: string): string[] {
@@ -299,6 +322,16 @@ export function jwtSecret(dataDir: string): string {
299
322
  return secret;
300
323
  }
301
324
 
325
+ async function probeHealth(url: string, timeoutMs: number): Promise<boolean> {
326
+ try {
327
+ const response = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });
328
+ await response.body?.cancel().catch(() => {});
329
+ return response.ok;
330
+ } catch {
331
+ return false;
332
+ }
333
+ }
334
+
302
335
  export function restartDelay(failures: number, everReady = true): number {
303
336
  return everReady ? Math.min(1000 * 2 ** (failures - 1), 30_000) : BOOT_RESTART_DELAY;
304
337
  }
@@ -404,6 +437,8 @@ export function createDesktopServer(options: DesktopServerOptions): DesktopServe
404
437
  const pickPort = options.freePort ?? loopbackPort;
405
438
  const argv = serverArgv(options.execPath ?? process.execPath, options.resources, options.manifest.entry);
406
439
  const grace = options.stopGrace ?? STOP_GRACE;
440
+ const maxFailures = options.manifest.restart === "forever" ? Infinity : (options.manifest.restart ?? MAX_FAILURES);
441
+ const probe = options.probe ?? probeHealth;
407
442
  const logs = join(dataDir, "runtime", "logs");
408
443
  const outputLog = join(logs, "server-output.log");
409
444
  let outputSize = -1;
@@ -474,19 +509,46 @@ export function createDesktopServer(options: DesktopServerOptions): DesktopServe
474
509
 
475
510
  const failed = (why: string) => {
476
511
  failures++;
477
- const line = `[akan-native] the server ${why} (${failures} of ${MAX_FAILURES} in a row)`;
512
+ const count = Number.isFinite(maxFailures) ? `${failures} of ${maxFailures}` : `${failures}`;
513
+ const line = `[akan-native] the server ${why} (${count} in a row)`;
478
514
  console.error(line);
479
515
  record(line);
480
516
  setState(everReady ? "restarting" : "starting");
481
- if (failures >= MAX_FAILURES)
517
+ if (failures >= maxFailures)
482
518
  return giveUp(
483
- `The app's server stopped ${MAX_FAILURES} times in a row and is not restarted again. Its logs are in ${logs}.`,
519
+ `The app's server stopped ${maxFailures} times in a row and is not restarted again. Its logs are in ${logs}.`,
484
520
  );
485
- restartTimer = setTimeout(() => void launch(), (options.restartDelay ?? restartDelay)(failures, everReady));
521
+
522
+ const paced = everReady || failures >= MAX_FAILURES;
523
+ restartTimer = setTimeout(() => void launch(), (options.restartDelay ?? restartDelay)(failures, paced));
524
+ };
525
+
526
+ const watch = (child: ServerProcess) => {
527
+ const { watchdog } = options.manifest;
528
+ if (!watchdog) return () => {};
529
+ let missed = 0;
530
+ let asking = false;
531
+ const timer = setInterval(async () => {
532
+ if (asking || proc !== child || stopping) return;
533
+ asking = true;
534
+ const healthy = await probe(`http://127.0.0.1:${port}${HEALTH_PATH}`, Math.min(watchdog.intervalMs, 5000));
535
+ asking = false;
536
+ if (proc !== child || stopping) return;
537
+ missed = healthy ? 0 : missed + 1;
538
+ if (missed < watchdog.failures) return;
539
+ const line = `[akan-native] the server missed ${missed} health checks in a row; killing it to restart`;
540
+ console.error(line);
541
+ record(line);
542
+ clearInterval(timer);
543
+ child.kill("SIGKILL");
544
+ }, watchdog.intervalMs);
545
+ timer.unref?.();
546
+ return () => clearInterval(timer);
486
547
  };
487
548
 
488
549
  const run = () => {
489
550
  let readyAt: number | null = null;
551
+ let unwatch = () => {};
490
552
  const child = spawn(argv, {
491
553
  cwd: dataDir,
492
554
  env,
@@ -496,6 +558,7 @@ export function createDesktopServer(options: DesktopServerOptions): DesktopServe
496
558
  if (type !== "ready" || readyAt !== null) return;
497
559
  readyAt = now();
498
560
  setState("up");
561
+ unwatch = watch(child);
499
562
  if (!everReady) {
500
563
  everReady = true;
501
564
  settleReady(true);
@@ -513,6 +576,7 @@ export function createDesktopServer(options: DesktopServerOptions): DesktopServe
513
576
  proc = child;
514
577
  child.exited.then(
515
578
  (code) => {
579
+ unwatch();
516
580
  if (proc === child) proc = null;
517
581
  child.killGroup?.(stopping ? "SIGKILL" : "SIGTERM");
518
582
  if (stopping) return;
@@ -0,0 +1,23 @@
1
+ {
2
+ "id": "external-view",
3
+ "apiVersion": 1,
4
+ "methods": [
5
+ "open",
6
+ "navigate",
7
+ "reload",
8
+ "close",
9
+ "list",
10
+ "setVisible",
11
+ "setBounds",
12
+ "evaluate",
13
+ "sendKey",
14
+ "setMuted",
15
+ "clearData",
16
+ "capture"
17
+ ],
18
+ "events": ["load", "loadFailed", "gone", "consoleMessage"],
19
+ "web": null,
20
+ "desktop": "./src/desktop.ts",
21
+ "ios": null,
22
+ "android": null
23
+ }
@@ -0,0 +1,321 @@
1
+
2
+
3
+ import { mkdirSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { AkanNativeError } from "../../../packages/core/src/index.ts";
7
+ import { type DesktopContext, defineDesktopPlugin } from "../../../packages/desktop/src/plugin.ts";
8
+ import type {
9
+ ExternalViewApi,
10
+ ExternalViewBounds,
11
+ ExternalViewConsoleLevel,
12
+ ExternalViewEvents,
13
+ ExternalViewState,
14
+ } from "./index.ts";
15
+
16
+ const ID = /^[A-Za-z0-9_-]{1,64}$/;
17
+ const LEVELS: ExternalViewConsoleLevel[] = ["debug", "info", "warn", "error"];
18
+ /** consoleMessage per view: this many in CONSOLE_WINDOW_MS, the rest counted and reported with the next one. */
19
+ export const CONSOLE_BURST = 20;
20
+ export const CONSOLE_WINDOW_MS = 10_000;
21
+
22
+ function id(args: unknown): string {
23
+ const value = (args as { id?: unknown } | undefined)?.id;
24
+ if (typeof value !== "string" || !ID.test(value))
25
+ throw new AkanNativeError("INVALID_ARGS", "id must be 1-64 letters, digits, - or _");
26
+ return value;
27
+ }
28
+
29
+ function text(args: unknown, name: string): string {
30
+ const value = (args as Record<string, unknown> | undefined)?.[name];
31
+ if (typeof value !== "string" || !value) throw new AkanNativeError("INVALID_ARGS", `${name} must be a string`);
32
+ return value;
33
+ }
34
+
35
+ function bool(args: unknown, name: string): boolean {
36
+ const value = (args as Record<string, unknown> | undefined)?.[name];
37
+ if (typeof value !== "boolean") throw new AkanNativeError("INVALID_ARGS", `${name} must be a boolean`);
38
+ return value;
39
+ }
40
+
41
+ function bounds(value: unknown): ExternalViewBounds | undefined {
42
+ if (value === undefined || value === "fill") return value;
43
+ const b = value as Record<string, unknown> | null;
44
+ const ok = !!b && ["x", "y", "width", "height"].every((k) => typeof b[k] === "number" && Number.isFinite(b[k]));
45
+ if (!ok || (b?.width as number) <= 0 || (b?.height as number) <= 0)
46
+ throw new AkanNativeError("INVALID_ARGS", 'bounds must be "fill" or { x, y, width, height } with a positive size');
47
+ return value as ExternalViewBounds;
48
+ }
49
+
50
+ export function consoleLevel(value: unknown): ExternalViewConsoleLevel | null {
51
+ if (value === undefined || value === false) return null;
52
+ if (value === true) return "warn";
53
+ if (typeof value === "string" && (LEVELS as string[]).includes(value)) return value as ExternalViewConsoleLevel;
54
+ throw new AkanNativeError("INVALID_ARGS", `console must be a boolean or one of ${LEVELS.join(", ")}`);
55
+ }
56
+
57
+ const shell = (ctx: DesktopContext, op: string, args: Record<string, unknown>) => ctx.shell(`externalView.${op}`, args);
58
+
59
+ /** The engine's own text, which the shell sends on as a string: JSON, or not, as the engine had it. */
60
+ function parsed(value: unknown): unknown {
61
+ if (typeof value !== "string") return value;
62
+ try {
63
+ return JSON.parse(value) as unknown;
64
+ } catch {
65
+ return value;
66
+ }
67
+ }
68
+
69
+ function state(raw: unknown): ExternalViewState {
70
+ const { view, ...rest } = raw as { view: string } & Omit<ExternalViewState, "id">;
71
+ return { id: view, ...rest };
72
+ }
73
+
74
+ /** Chrome's virtual key code for a KeyboardEvent.code, which a trusted key event needs beside `key`. */
75
+ export function virtualKey(code: string): number {
76
+ const letter = /^Key([A-Z])$/.exec(code);
77
+ if (letter?.[1]) return letter[1].charCodeAt(0);
78
+ const digit = /^(?:Digit|Numpad)([0-9])$/.exec(code);
79
+ if (digit?.[1]) return (code.startsWith("Numpad") ? 96 : 48) + Number(digit[1]);
80
+ const fn = /^F([0-9]{1,2})$/.exec(code);
81
+ if (fn?.[1] && Number(fn[1]) >= 1 && Number(fn[1]) <= 24) return 111 + Number(fn[1]);
82
+ const named: Record<string, number> = {
83
+ Space: 32,
84
+ Enter: 13,
85
+ NumpadEnter: 13,
86
+ Escape: 27,
87
+ Tab: 9,
88
+ Backspace: 8,
89
+ Delete: 46,
90
+ ArrowLeft: 37,
91
+ ArrowUp: 38,
92
+ ArrowRight: 39,
93
+ ArrowDown: 40,
94
+ Home: 36,
95
+ End: 35,
96
+ PageUp: 33,
97
+ PageDown: 34,
98
+ Slash: 191,
99
+ Minus: 189,
100
+ Equal: 187,
101
+ Period: 190,
102
+ Comma: 188,
103
+ Semicolon: 186,
104
+ Quote: 222,
105
+ BracketLeft: 219,
106
+ BracketRight: 221,
107
+ Backslash: 220,
108
+ Backquote: 192,
109
+ };
110
+ const known = named[code];
111
+ if (known === undefined) throw new AkanNativeError("INVALID_ARGS", `code ${code} is not a key sendKey knows`);
112
+ return known;
113
+ }
114
+
115
+ interface CdpConsoleCall {
116
+ type?: string;
117
+ args?: { value?: unknown; description?: string; unserializableValue?: string; type?: string }[];
118
+ stackTrace?: { callFrames?: { url?: string; lineNumber?: number }[] };
119
+ }
120
+ interface CdpException {
121
+ exceptionDetails?: {
122
+ text?: string;
123
+ url?: string;
124
+ lineNumber?: number;
125
+ exception?: { description?: string };
126
+ stackTrace?: CdpConsoleCall["stackTrace"];
127
+ };
128
+ }
129
+
130
+ /** One console call or uncaught exception as a message, from the protocol event the shell passed on. */
131
+ export function consoleMessageOf(
132
+ method: string,
133
+ params: unknown,
134
+ ): Omit<ExternalViewEvents["consoleMessage"], "id"> | null {
135
+ if (method === "Runtime.exceptionThrown") {
136
+ const details = (params as CdpException).exceptionDetails ?? {};
137
+ const frame = details.stackTrace?.callFrames?.[0];
138
+ return {
139
+ level: "error",
140
+ text: details.exception?.description ?? details.text ?? "Uncaught exception",
141
+ ...(details.url || frame?.url ? { url: details.url || frame?.url } : {}),
142
+ ...(typeof details.lineNumber === "number" ? { line: details.lineNumber + 1 } : {}),
143
+ };
144
+ }
145
+ if (method !== "Runtime.consoleAPICalled") return null;
146
+ const call = params as CdpConsoleCall;
147
+ const level: ExternalViewConsoleLevel =
148
+ call.type === "error" || call.type === "assert"
149
+ ? "error"
150
+ : call.type === "warning"
151
+ ? "warn"
152
+ : call.type === "debug"
153
+ ? "debug"
154
+ : "info";
155
+ const parts = (call.args ?? []).map((arg) =>
156
+ typeof arg.value === "string"
157
+ ? arg.value
158
+ : String(arg.value ?? arg.unserializableValue ?? arg.description ?? arg.type),
159
+ );
160
+ const frame = call.stackTrace?.callFrames?.[0];
161
+ return {
162
+ level,
163
+ text: parts.join(" "),
164
+ ...(frame?.url ? { url: frame.url } : {}),
165
+ ...(typeof frame?.lineNumber === "number" ? { line: frame.lineNumber + 1 } : {}),
166
+ };
167
+ }
168
+
169
+ /** Lets CONSOLE_BURST messages through per window of time, and counts what it held back for the next one. */
170
+ export function createConsoleCap(now: () => number = Date.now) {
171
+ const views = new Map<string, { since: number; sent: number; dropped: number }>();
172
+ return (view: string): { pass: boolean; dropped: number } => {
173
+ const t = now();
174
+ const entry = views.get(view) ?? { since: t, sent: 0, dropped: 0 };
175
+ if (t - entry.since >= CONSOLE_WINDOW_MS) Object.assign(entry, { since: t, sent: 0 });
176
+ views.set(view, entry);
177
+ if (entry.sent >= CONSOLE_BURST) {
178
+ entry.dropped++;
179
+ return { pass: false, dropped: 0 };
180
+ }
181
+ entry.sent++;
182
+ const dropped = entry.dropped;
183
+ entry.dropped = 0;
184
+ return { pass: true, dropped };
185
+ };
186
+ }
187
+
188
+ export function createDesktopExternalView() {
189
+ /** The console level each view was opened with: the shell sends every message, and this filters them. */
190
+ const levels = new Map<string, ExternalViewConsoleLevel>();
191
+
192
+ return defineDesktopPlugin<ExternalViewApi, ExternalViewEvents>({
193
+ id: "external-view",
194
+ methods: {
195
+ async open(args, ctx) {
196
+ const view = id(args);
197
+ const url = text(args, "url");
198
+ const allowOrigins = (args as { allowOrigins?: unknown }).allowOrigins;
199
+ if (!Array.isArray(allowOrigins) || !allowOrigins.length || allowOrigins.some((o) => typeof o !== "string"))
200
+ throw new AkanNativeError("INVALID_ARGS", "allowOrigins must be a list of origins");
201
+ const level = consoleLevel(args.console);
202
+ const opened = state(
203
+ await shell(ctx, "open", {
204
+ view,
205
+ url,
206
+ allowOrigins,
207
+ ...(args.bounds !== undefined ? { bounds: bounds(args.bounds) } : {}),
208
+ ...(typeof args.initScript === "string" ? { initScript: args.initScript } : {}),
209
+ muted: args.muted === true,
210
+ autoplay: args.autoplay !== false,
211
+ console: level !== null,
212
+ ...(args.window !== undefined ? { window: args.window } : {}),
213
+ }),
214
+ );
215
+ if (level) levels.set(view, level);
216
+ else levels.delete(view);
217
+ return opened;
218
+ },
219
+ async navigate(args, ctx) {
220
+ await shell(ctx, "navigate", { view: id(args), url: text(args, "url") });
221
+ },
222
+ async reload(args, ctx) {
223
+ await shell(ctx, "reload", { view: id(args) });
224
+ },
225
+ async close(args, ctx) {
226
+ const view = id(args);
227
+ await shell(ctx, "close", { view });
228
+ levels.delete(view);
229
+ },
230
+ async list(_args, ctx) {
231
+ return ((await shell(ctx, "list", {})) as unknown[]).map(state);
232
+ },
233
+ async setVisible(args, ctx) {
234
+ await shell(ctx, "setVisible", { view: id(args), visible: bool(args, "visible") });
235
+ },
236
+ async setBounds(args, ctx) {
237
+ await shell(ctx, "setBounds", { view: id(args), bounds: bounds(args.bounds) ?? "fill" });
238
+ },
239
+ async evaluate(args, ctx) {
240
+ return { value: parsed(await shell(ctx, "evaluate", { view: id(args), script: text(args, "script") })) };
241
+ },
242
+ async sendKey(args, ctx) {
243
+ const view = id(args);
244
+ const key = text(args, "key");
245
+ const code = text(args, "code");
246
+ const vk = virtualKey(code);
247
+ const base = { key, code, windowsVirtualKeyCode: vk, nativeVirtualKeyCode: vk };
248
+
249
+ const typed = key.length === 1 ? { text: key, unmodifiedText: key } : {};
250
+ await shell(ctx, "cdp", {
251
+ view,
252
+ method: "Input.dispatchKeyEvent",
253
+ params: { type: "keyDown", ...base, ...typed },
254
+ });
255
+ await shell(ctx, "cdp", { view, method: "Input.dispatchKeyEvent", params: { type: "keyUp", ...base } });
256
+ },
257
+ async setMuted(args, ctx) {
258
+ await shell(ctx, "setMuted", { view: id(args), muted: bool(args, "muted") });
259
+ },
260
+ async clearData(args, ctx) {
261
+ await shell(ctx, "clearData", { view: id(args) });
262
+ },
263
+ async capture(args, ctx) {
264
+ const view = id(args);
265
+ const shot = parsed(
266
+ await shell(ctx, "cdp", { view, method: "Page.captureScreenshot", params: { format: "png" } }),
267
+ ) as { data?: string } | null;
268
+ if (!shot?.data) throw new AkanNativeError("INTERNAL", "the view answered no screenshot");
269
+ const dir = join(tmpdir(), "akan-native-external-view");
270
+ mkdirSync(dir, { recursive: true });
271
+ const file = join(dir, `${view}-${Date.now()}.png`);
272
+ const bytes = Buffer.from(shot.data, "base64");
273
+ await Bun.write(file, bytes);
274
+
275
+ const size = bytes.length >= 24 ? { width: bytes.readUInt32BE(16), height: bytes.readUInt32BE(20) } : {};
276
+ return { ...ctx.registerFile(file, "image/png"), ...size };
277
+ },
278
+ },
279
+ events: {
280
+ load: (emit, ctx) =>
281
+ ctx.onNativeEvent("externalView", (e) => {
282
+ if (e.event !== "load") return;
283
+ emit(
284
+ { id: e.view as string, state: e.state as "started" | "finished", url: e.url as string },
285
+ { window: e.window as number },
286
+ );
287
+ }),
288
+ loadFailed: (emit, ctx) =>
289
+ ctx.onNativeEvent("externalView", (e) => {
290
+ if (e.event !== "loadFailed") return;
291
+ emit(
292
+ { id: e.view as string, url: e.url as string, errorCode: e.errorCode as string },
293
+ { window: e.window as number },
294
+ );
295
+ }),
296
+ gone: (emit, ctx) =>
297
+ ctx.onNativeEvent("externalView", (e) => {
298
+ if (e.event !== "gone") return;
299
+ emit(
300
+ { id: e.view as string, reason: e.reason as string, restarts: e.restarts as number },
301
+ { window: e.window as number },
302
+ );
303
+ }),
304
+ consoleMessage: (emit, ctx) => {
305
+ const cap = createConsoleCap();
306
+ return ctx.onNativeEvent("externalView", (e) => {
307
+ if (e.event !== "cdp") return;
308
+ const view = e.view as string;
309
+ const min = levels.get(view);
310
+ const message = min ? consoleMessageOf(e.method as string, e.params) : null;
311
+ if (!min || !message || LEVELS.indexOf(message.level) < LEVELS.indexOf(min)) return;
312
+ const { pass, dropped } = cap(view);
313
+ if (!pass) return;
314
+ emit({ id: view, ...message, ...(dropped ? { dropped } : {}) }, { window: e.window as number });
315
+ });
316
+ },
317
+ },
318
+ });
319
+ }
320
+
321
+ export default createDesktopExternalView();
@@ -0,0 +1,106 @@
1
+ import { definePlugin, type FileRef } from "../../../packages/core/src/index.ts";
2
+
3
+ /**
4
+ * A third-party page shown first-party inside an app window, for signage: a scoreboard, a menu board. The view is a
5
+ * webview of its own laid over the window's page, which cannot draw over it — hide the view to show the page.
6
+ *
7
+ * Nothing of the app reaches the view: no bridge, no init script of the app, no app scheme. It keeps its own browser
8
+ * profile (cookies, storage, cache), so `clearData` never touches the app's, and it navigates only to `allowOrigins`;
9
+ * popups, downloads and device permissions are refused. Listing the plugin in `native.plugins` is what lets an app
10
+ * open one.
11
+ *
12
+ * Windows has every method. macOS (14 or later, for its separate profile) has all but `sendKey`, `setMuted` and
13
+ * `capture`, and sends no `loadFailed` or `consoleMessage`. Linux, iOS and Android: UNSUPPORTED.
14
+ */
15
+ export type ExternalViewBounds = "fill" | { x: number; y: number; width: number; height: number };
16
+
17
+ export type ExternalViewConsoleLevel = "debug" | "info" | "warn" | "error";
18
+
19
+ export interface ExternalViewOpenOptions {
20
+ /** Names the view in every later call: letters, digits, `-` and `_`. */
21
+ id: string;
22
+ url: string;
23
+ /** The origins it may navigate to (`https://host[:port]`); `url` must be on one. */
24
+ allowOrigins: string[];
25
+ /** Logical pixels in the window's content area; "fill" (default) follows the window's size. */
26
+ bounds?: ExternalViewBounds;
27
+ /** Runs at the start of every top document, before the page's own scripts; read what it keeps with `evaluate`. */
28
+ initScript?: string;
29
+ muted?: boolean;
30
+ /** Media plays with sound without a gesture first (default true): nobody taps a signage screen. */
31
+ autoplay?: boolean;
32
+ /** Sends the page's console as `consoleMessage` from this level up (`true` is "warn"); off by default. */
33
+ console?: boolean | ExternalViewConsoleLevel;
34
+ /** The window it is laid over; the calling page's window by default. */
35
+ window?: number;
36
+ }
37
+
38
+ export interface ExternalViewState {
39
+ id: string;
40
+ window: number;
41
+ url: string;
42
+ visible: boolean;
43
+ /** Times its web process ended and the view loaded its page again. */
44
+ restarts: number;
45
+ }
46
+
47
+ export interface ExternalViewApi {
48
+ /** Opens the view, or brings an open one with this id to these options (a page that mounts again finds it). */
49
+ open(args: ExternalViewOpenOptions): Promise<ExternalViewState>;
50
+ /** Rejects NOT_ALLOWED for a URL on none of its `allowOrigins`. */
51
+ navigate(args: { id: string; url: string }): Promise<void>;
52
+ reload(args: { id: string }): Promise<void>;
53
+ close(args: { id: string }): Promise<void>;
54
+ list(): Promise<ExternalViewState[]>;
55
+ setVisible(args: { id: string; visible: boolean }): Promise<void>;
56
+ setBounds(args: { id: string; bounds: ExternalViewBounds }): Promise<void>;
57
+ /** The script's completion value; a promise is not awaited. An exception answers `null`: catch it in the script. */
58
+ evaluate(args: { id: string; script: string }): Promise<{ value: unknown }>;
59
+ /** A trusted key press (`{ key: "z", code: "KeyZ" }`), whether or not the view has the focus. Windows only. */
60
+ sendKey(args: { id: string; key: string; code: string }): Promise<void>;
61
+ /** The view's own sound only; the system volume is the volume plugin's. Windows only. */
62
+ setMuted(args: { id: string; muted: boolean }): Promise<void>;
63
+ /** Clears the view's cookies, storage and cache; the app's own stay. */
64
+ clearData(args: { id: string }): Promise<void>;
65
+ /** A PNG of the view's content, not of the screen. Windows only. */
66
+ capture(args: { id: string }): Promise<FileRef & { width?: number; height?: number }>;
67
+ }
68
+
69
+ export interface ExternalViewEvents {
70
+ load: { id: string; state: "started" | "finished"; url: string };
71
+ /**
72
+ * A navigation that failed. `errorCode`: `http<status>` for a server's 4xx or 5xx page, else WebView2's own
73
+ * (`hostNameNotResolved`, `cannotConnect`, `timeout`, `certificate`, `disconnected`, …; a refused connection is
74
+ * `unknown`). Windows only.
75
+ */
76
+ loadFailed: { id: string; url: string; errorCode: string };
77
+ /** Its web process ended; the view loads its page again by itself, sooner the first times. */
78
+ gone: { id: string; reason: string; restarts: number };
79
+ /** `dropped`: messages left out before this one, past the rate cap. Windows only. */
80
+ consoleMessage: {
81
+ id: string;
82
+ level: ExternalViewConsoleLevel;
83
+ text: string;
84
+ url?: string;
85
+ line?: number;
86
+ dropped?: number;
87
+ };
88
+ }
89
+
90
+ export const externalView = definePlugin<ExternalViewApi, ExternalViewEvents>("external-view", {
91
+ methods: [
92
+ "open",
93
+ "navigate",
94
+ "reload",
95
+ "close",
96
+ "list",
97
+ "setVisible",
98
+ "setBounds",
99
+ "evaluate",
100
+ "sendKey",
101
+ "setMuted",
102
+ "clearData",
103
+ "capture",
104
+ ],
105
+ events: ["load", "loadFailed", "gone", "consoleMessage"],
106
+ });