akanjs 3.1.0-rc.2 → 3.1.0-rc.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 (392) hide show
  1. package/base/baseEnv.ts +5 -2
  2. package/client/device.ts +1 -1
  3. package/client/frameConfig.ts +2 -2
  4. package/client/href.ts +35 -0
  5. package/client/index.ts +1 -0
  6. package/client/makePageProto.tsx +3 -2
  7. package/client/router.ts +6 -4
  8. package/client/rscNavigation.ts +1 -1
  9. package/client/transitionTypes.ts +0 -4
  10. package/client/translator.ts +16 -0
  11. package/client/types.ts +3 -2
  12. package/client/viewportMeta.ts +23 -8
  13. package/client/webManifest.ts +5 -3
  14. package/common/TrustedProxy.ts +14 -0
  15. package/common/codeAgentWire.ts +8 -1
  16. package/common/index.ts +1 -0
  17. package/common/interpolateTranslation.ts +17 -3
  18. package/common/isEmail.ts +1 -1
  19. package/common/localeConfig.ts +10 -4
  20. package/common/markdownSpans.ts +1 -1
  21. package/common/restClient.ts +3 -1
  22. package/common/routeConvention.ts +4 -4
  23. package/common/trimSlashes.ts +11 -0
  24. package/common/types.ts +1 -1
  25. package/constant/fieldInfo.ts +2 -2
  26. package/constant/fieldPlan.ts +80 -0
  27. package/constant/index.ts +3 -0
  28. package/constant/inputParser.ts +148 -0
  29. package/constant/invalidInputError.ts +13 -0
  30. package/constant/serialize.ts +36 -20
  31. package/constant/types.ts +1 -1
  32. package/constant/via.ts +2 -0
  33. package/dictionary/base.dictionary.ts +4 -0
  34. package/dictionary/trans.ts +8 -0
  35. package/document/database.ts +3 -6
  36. package/document/documentSchema.ts +1 -1
  37. package/document/noDocumentError.ts +6 -1
  38. package/fetch/client/fetchClient.ts +2 -1
  39. package/fetch/client/sliceInitHandle.ts +2 -3
  40. package/fetch/fetchType/appliedReturn.type.ts +3 -1
  41. package/fetch/types.ts +4 -2
  42. package/index.ts +2 -0
  43. package/package.json +31 -21
  44. package/server/akanApp.ts +15 -3
  45. package/server/akanServer.ts +34 -14
  46. package/server/artifact/routeClientCache.ts +4 -5
  47. package/server/artifact/routeSeedIndexStore.ts +3 -20
  48. package/server/artifact/routeSeedMatcher.ts +70 -0
  49. package/server/console.ts +1 -1
  50. package/server/di/diLifecycle.ts +16 -7
  51. package/server/imageOptimizer.ts +1 -1
  52. package/server/index.ts +1 -0
  53. package/server/machine/machineAccount.ts +28 -3
  54. package/server/machine/machineToken.ts +27 -3
  55. package/server/mcp/McpDispatcher.ts +2 -3
  56. package/server/mcp/McpExecutionContext.ts +9 -3
  57. package/server/migration/docPath.ts +121 -0
  58. package/server/migration/index.ts +15 -0
  59. package/server/migration/migrationChangeLog.ts +86 -0
  60. package/server/migration/migrationChanges.ts +70 -0
  61. package/server/migration/migrationCommand.ts +179 -0
  62. package/server/migration/migrationContext.ts +53 -0
  63. package/server/migration/migrationDefinition.ts +87 -0
  64. package/server/migration/migrationError.ts +45 -0
  65. package/server/migration/migrationLedger.ts +172 -0
  66. package/server/migration/migrationLock.ts +103 -0
  67. package/server/migration/migrationParams.ts +122 -0
  68. package/server/migration/migrationPulse.ts +39 -0
  69. package/server/migration/migrationRunner.ts +525 -0
  70. package/server/migration/migrationScope.ts +93 -0
  71. package/server/migration/migrationTable.ts +258 -0
  72. package/server/migration/migrations.ts +57 -0
  73. package/server/ops/opsCommand.ts +30 -1
  74. package/server/resolver/CascadeRunner.ts +15 -2
  75. package/server/resolver/signal.resolver.ts +35 -55
  76. package/server/routeState.ts +0 -6
  77. package/server/rscClient.tsx +22 -37
  78. package/server/rscNavigationState.ts +3 -5
  79. package/server/rscScrollRestoration.ts +116 -0
  80. package/server/rscWorker.tsx +12 -19
  81. package/server/sitemap.ts +4 -4
  82. package/server/tunnel/TunnelAgent.ts +9 -1
  83. package/server/webRouter.ts +17 -2
  84. package/service/agent.service.ts +21 -1
  85. package/service/endpointCacheKeys.ts +35 -0
  86. package/service/index.ts +1 -0
  87. package/service/injectInfo.ts +2 -2
  88. package/service/predefinedAdaptor/anthropicLlm.ts +37 -17
  89. package/service/predefinedAdaptor/database.adaptor.ts +15 -0
  90. package/service/predefinedAdaptor/documentTransfer.ts +50 -0
  91. package/service/predefinedAdaptor/endpointCacheControl.adaptor.ts +19 -0
  92. package/service/predefinedAdaptor/index.ts +1 -0
  93. package/service/predefinedAdaptor/llm.adaptor.ts +7 -0
  94. package/service/predefinedAdaptor/openaiDialect.ts +53 -17
  95. package/service/predefinedAdaptor/openaiLlm.ts +1 -1
  96. package/service/predefinedAdaptor/sql/MigrationTables.ts +90 -0
  97. package/service/predefinedAdaptor/sql/RawDocumentTable.ts +200 -0
  98. package/service/predefinedAdaptor/sql/SqlDocumentStore.ts +6 -2
  99. package/service/predefinedAdaptor/sql/SqliteInsightSession.ts +4 -1
  100. package/service/predefinedAdaptor/sql/dialect/postgres.ts +0 -1
  101. package/service/predefinedAdaptor/sql/dialect/sqlite.ts +0 -1
  102. package/service/predefinedAdaptor/sql/types.ts +3 -1
  103. package/service/predefinedAdaptor/storage.adaptor.ts +19 -0
  104. package/signal/endpointCache.ts +23 -7
  105. package/signal/endpointErrorContract.ts +37 -0
  106. package/signal/endpointIdempotency.ts +5 -3
  107. package/signal/endpointInfo.ts +4 -1
  108. package/signal/endpointRateLimit.ts +6 -2
  109. package/signal/exception.ts +4 -1
  110. package/signal/index.ts +1 -0
  111. package/signal/mcp/McpDocument.ts +16 -1
  112. package/signal/mcp/McpUriTemplate.ts +1 -1
  113. package/signal/middlewareChain.ts +105 -0
  114. package/signal/openapi/openapi.ts +46 -2
  115. package/signal/serializer/fetch.serializer.ts +1 -0
  116. package/signal/signalContext.ts +110 -82
  117. package/signal/slice.ts +2 -2
  118. package/signal/trace.ts +8 -2
  119. package/signal/types.ts +13 -0
  120. package/store/action.ts +102 -42
  121. package/store/agent/ScreenImage.ts +166 -0
  122. package/store/agent/ScreenReader.ts +2 -1
  123. package/store/agent/StoreSurfaceSource.ts +41 -2
  124. package/store/agent/index.ts +2 -1
  125. package/store/databaseStateNames.ts +1 -0
  126. package/store/formUploadOf.ts +41 -0
  127. package/store/index.ts +1 -0
  128. package/store/liveInsert.ts +2 -2
  129. package/store/state.ts +9 -1
  130. package/store/stateBuilder.ts +8 -2
  131. package/store/storeInstance.ts +12 -3
  132. package/store/withSelector.ts +2 -2
  133. package/types/client/href.d.ts +11 -0
  134. package/types/client/index.d.ts +1 -0
  135. package/types/client/rscNavigation.d.ts +1 -1
  136. package/types/client/transitionTypes.d.ts +0 -2
  137. package/types/client/translator.d.ts +2 -0
  138. package/types/common/codeAgentWire.d.ts +7 -0
  139. package/types/common/index.d.ts +1 -0
  140. package/types/common/trimSlashes.d.ts +2 -0
  141. package/types/common/types.d.ts +1 -1
  142. package/types/constant/fieldInfo.d.ts +2 -2
  143. package/types/constant/fieldPlan.d.ts +33 -0
  144. package/types/constant/index.d.ts +3 -0
  145. package/types/constant/inputParser.d.ts +11 -0
  146. package/types/constant/invalidInputError.d.ts +8 -0
  147. package/types/constant/types.d.ts +1 -1
  148. package/types/dictionary/base.dictionary.d.ts +1 -1
  149. package/types/dictionary/dictionary.d.ts +3 -3
  150. package/types/dictionary/trans.d.ts +3 -0
  151. package/types/document/database.d.ts +2 -3
  152. package/types/document/documentSchema.d.ts +1 -1
  153. package/types/document/noDocumentError.d.ts +6 -1
  154. package/types/fetch/fetchType/appliedReturn.type.d.ts +3 -1
  155. package/types/fetch/types.d.ts +2 -2
  156. package/types/index.d.ts +5 -0
  157. package/types/server/akanServer.d.ts +1 -1
  158. package/types/server/artifact/routeSeedMatcher.d.ts +8 -0
  159. package/types/server/di/diLifecycle.d.ts +1 -0
  160. package/types/server/index.d.ts +1 -0
  161. package/types/server/machine/machineAccount.d.ts +1 -0
  162. package/types/server/machine/machineToken.d.ts +9 -0
  163. package/types/server/migration/docPath.d.ts +20 -0
  164. package/types/server/migration/index.d.ts +15 -0
  165. package/types/server/migration/migrationChangeLog.d.ts +27 -0
  166. package/types/server/migration/migrationChanges.d.ts +27 -0
  167. package/types/server/migration/migrationCommand.d.ts +33 -0
  168. package/types/server/migration/migrationContext.d.ts +28 -0
  169. package/types/server/migration/migrationDefinition.d.ts +42 -0
  170. package/types/server/migration/migrationError.d.ts +15 -0
  171. package/types/server/migration/migrationLedger.d.ts +51 -0
  172. package/types/server/migration/migrationLock.d.ts +34 -0
  173. package/types/server/migration/migrationParams.d.ts +41 -0
  174. package/types/server/migration/migrationPulse.d.ts +15 -0
  175. package/types/server/migration/migrationRunner.d.ts +93 -0
  176. package/types/server/migration/migrationScope.d.ts +42 -0
  177. package/types/server/migration/migrationTable.d.ts +52 -0
  178. package/types/server/migration/migrations.d.ts +12 -0
  179. package/types/server/migration.d.ts +1 -0
  180. package/types/server/ops/opsCommand.d.ts +10 -1
  181. package/types/server/routeState.d.ts +1 -4
  182. package/types/server/rscNavigationState.d.ts +2 -3
  183. package/types/server/rscScrollRestoration.d.ts +14 -0
  184. package/types/server/sitemap.d.ts +1 -1
  185. package/types/service/agent.service.d.ts +2 -0
  186. package/types/service/endpointCacheKeys.d.ts +8 -0
  187. package/types/service/index.d.ts +1 -0
  188. package/types/service/injectInfo.d.ts +2 -2
  189. package/types/service/predefinedAdaptor/anthropicLlm.d.ts +9 -4
  190. package/types/service/predefinedAdaptor/database.adaptor.d.ts +8 -1
  191. package/types/service/predefinedAdaptor/documentTransfer.d.ts +1 -0
  192. package/types/service/predefinedAdaptor/endpointCacheControl.adaptor.d.ts +9 -0
  193. package/types/service/predefinedAdaptor/index.d.ts +1 -0
  194. package/types/service/predefinedAdaptor/llm.adaptor.d.ts +7 -0
  195. package/types/service/predefinedAdaptor/openaiDialect.d.ts +20 -5
  196. package/types/service/predefinedAdaptor/sql/MigrationTables.d.ts +17 -0
  197. package/types/service/predefinedAdaptor/sql/RawDocumentTable.d.ts +38 -0
  198. package/types/service/predefinedAdaptor/sql/types.d.ts +1 -0
  199. package/types/service/predefinedAdaptor/storage.adaptor.d.ts +8 -0
  200. package/types/signal/endpointCache.d.ts +2 -0
  201. package/types/signal/endpointErrorContract.d.ts +10 -0
  202. package/types/signal/endpointIdempotency.d.ts +1 -0
  203. package/types/signal/endpointRateLimit.d.ts +1 -1
  204. package/types/signal/exception.d.ts +4 -1
  205. package/types/signal/index.d.ts +1 -0
  206. package/types/signal/middlewareChain.d.ts +11 -0
  207. package/types/signal/signalContext.d.ts +2 -6
  208. package/types/signal/slice.d.ts +1 -1
  209. package/types/signal/trace.d.ts +1 -1
  210. package/types/signal/types.d.ts +12 -0
  211. package/types/store/action.d.ts +2 -0
  212. package/types/store/agent/ScreenImage.d.ts +27 -0
  213. package/types/store/agent/StoreSurfaceSource.d.ts +1 -1
  214. package/types/store/agent/index.d.ts +2 -1
  215. package/types/store/databaseStateNames.d.ts +1 -0
  216. package/types/store/formUploadOf.d.ts +9 -0
  217. package/types/store/index.d.ts +1 -0
  218. package/types/store/state.d.ts +7 -1
  219. package/types/store/stateBuilder.d.ts +2 -1
  220. package/types/store/storeInstance.d.ts +2 -2
  221. package/types/store/withSelector.d.ts +1 -1
  222. package/types/ui/Agent/Composer.d.ts +2 -0
  223. package/types/ui/Agent/Menu.d.ts +2 -0
  224. package/types/ui/CsrImage.d.ts +2 -0
  225. package/types/ui/Data/CardList.d.ts +1 -1
  226. package/types/ui/Data/Dashboard.d.ts +1 -1
  227. package/types/ui/Data/Insight.d.ts +1 -1
  228. package/types/ui/Data/Item.d.ts +2 -2
  229. package/types/ui/Data/ListContainer.d.ts +1 -1
  230. package/types/ui/Data/Pagination.d.ts +1 -1
  231. package/types/ui/Data/TableList.d.ts +1 -1
  232. package/types/ui/Field/Relation.d.ts +13 -10
  233. package/types/ui/Field/index.d.ts +4 -4
  234. package/types/ui/Field/useRelationOptions.d.ts +3 -1
  235. package/types/ui/Field/useRelationWindow.d.ts +14 -0
  236. package/types/ui/Image.d.ts +3 -1
  237. package/types/ui/Load/View.d.ts +1 -1
  238. package/types/ui/Pagination.d.ts +1 -1
  239. package/types/ui/Signal/Arg.d.ts +1 -1
  240. package/types/ui/System/CSR.d.ts +1 -1
  241. package/types/ui/System/Client.d.ts +1 -1
  242. package/types/ui/System/SSR.d.ts +1 -1
  243. package/types/vendor/@akanjs/native/packages/core/src/plugin.d.ts +3 -3
  244. package/types/vendor/@akanjs/native/packages/desktop/src/page-veto.d.ts +1 -1
  245. package/types/vendor/@akanjs/native/packages/desktop/src/plugin.d.ts +1 -1
  246. package/types/vendor/@akanjs/native/plugins/auth-session/src/desktop.d.ts +2 -2
  247. package/types/vendor/@akanjs/native/plugins/auth-session/src/index.d.ts +1 -1
  248. package/types/vendor/@akanjs/native/plugins/autostart/src/desktop.d.ts +2 -2
  249. package/types/vendor/@akanjs/native/plugins/autostart/src/index.d.ts +1 -1
  250. package/types/vendor/@akanjs/native/plugins/badge/src/desktop.d.ts +1 -1
  251. package/types/vendor/@akanjs/native/plugins/badge/src/index.d.ts +1 -1
  252. package/types/vendor/@akanjs/native/plugins/badge/src/web.d.ts +1 -1
  253. package/types/vendor/@akanjs/native/plugins/biometric/src/index.d.ts +1 -1
  254. package/types/vendor/@akanjs/native/plugins/camera/src/desktop.d.ts +1 -1
  255. package/types/vendor/@akanjs/native/plugins/camera/src/index.d.ts +1 -1
  256. package/types/vendor/@akanjs/native/plugins/camera/src/web.d.ts +1 -1
  257. package/types/vendor/@akanjs/native/plugins/clipboard/src/desktop.d.ts +2 -2
  258. package/types/vendor/@akanjs/native/plugins/clipboard/src/index.d.ts +1 -1
  259. package/types/vendor/@akanjs/native/plugins/clipboard/src/web.d.ts +1 -1
  260. package/types/vendor/@akanjs/native/plugins/contacts/src/index.d.ts +1 -1
  261. package/types/vendor/@akanjs/native/plugins/device/src/desktop.d.ts +2 -2
  262. package/types/vendor/@akanjs/native/plugins/device/src/index.d.ts +1 -1
  263. package/types/vendor/@akanjs/native/plugins/device/src/web.d.ts +1 -1
  264. package/types/vendor/@akanjs/native/plugins/dialog/src/desktop.d.ts +1 -1
  265. package/types/vendor/@akanjs/native/plugins/dialog/src/index.d.ts +1 -1
  266. package/types/vendor/@akanjs/native/plugins/dialog/src/web.d.ts +1 -1
  267. package/types/vendor/@akanjs/native/plugins/dock/src/desktop.d.ts +1 -1
  268. package/types/vendor/@akanjs/native/plugins/dock/src/index.d.ts +1 -1
  269. package/types/vendor/@akanjs/native/plugins/file-picker/src/desktop.d.ts +2 -2
  270. package/types/vendor/@akanjs/native/plugins/file-picker/src/web.d.ts +1 -1
  271. package/types/vendor/@akanjs/native/plugins/filesystem/src/desktop.d.ts +2 -2
  272. package/types/vendor/@akanjs/native/plugins/filesystem/src/web.d.ts +1 -1
  273. package/types/vendor/@akanjs/native/plugins/haptics/src/index.d.ts +1 -1
  274. package/types/vendor/@akanjs/native/plugins/haptics/src/web.d.ts +1 -1
  275. package/types/vendor/@akanjs/native/plugins/http/src/desktop.d.ts +2 -2
  276. package/types/vendor/@akanjs/native/plugins/http/src/web.d.ts +1 -1
  277. package/types/vendor/@akanjs/native/plugins/keep-awake/src/desktop.d.ts +2 -2
  278. package/types/vendor/@akanjs/native/plugins/keep-awake/src/index.d.ts +1 -1
  279. package/types/vendor/@akanjs/native/plugins/keep-awake/src/web.d.ts +1 -1
  280. package/types/vendor/@akanjs/native/plugins/opener/src/desktop.d.ts +2 -2
  281. package/types/vendor/@akanjs/native/plugins/opener/src/index.d.ts +1 -1
  282. package/types/vendor/@akanjs/native/plugins/opener/src/web.d.ts +1 -1
  283. package/types/vendor/@akanjs/native/plugins/preferences/src/desktop.d.ts +1 -1
  284. package/types/vendor/@akanjs/native/plugins/preferences/src/index.d.ts +1 -1
  285. package/types/vendor/@akanjs/native/plugins/preferences/src/web.d.ts +1 -1
  286. package/types/vendor/@akanjs/native/plugins/secure-storage/src/desktop.d.ts +2 -2
  287. package/types/vendor/@akanjs/native/plugins/secure-storage/src/index.d.ts +1 -1
  288. package/types/vendor/@akanjs/native/plugins/share/src/index.d.ts +1 -1
  289. package/types/vendor/@akanjs/native/plugins/share/src/web.d.ts +1 -1
  290. package/types/vendor/@akanjs/native/plugins/single-instance/src/desktop.d.ts +2 -2
  291. package/types/vendor/@akanjs/native/plugins/splash-screen/src/index.d.ts +1 -1
  292. package/types/vendor/@akanjs/native/plugins/splash-screen/src/web.d.ts +1 -1
  293. package/types/vendor/@akanjs/native/plugins/sqlite/src/desktop.d.ts +2 -2
  294. package/types/vendor/@akanjs/native/plugins/toast/src/index.d.ts +1 -1
  295. package/types/vendor/@akanjs/native/plugins/toast/src/web.d.ts +1 -1
  296. package/types/vendor/@akanjs/native/plugins/window/src/index.d.ts +2 -2
  297. package/types/vendor/@akanjs/native/plugins/window-state/src/desktop.d.ts +2 -2
  298. package/types/vendor/@akanjs/native/plugins/window-state/src/index.d.ts +1 -1
  299. package/types/vendor/use-agentic/Compaction.d.ts +3 -1
  300. package/types/vendor/use-agentic/Reference.d.ts +9 -1
  301. package/types/vendor/use-agentic/ToolOutput.d.ts +6 -1
  302. package/types/vendor/use-agentic/ToolReturn.d.ts +18 -0
  303. package/types/vendor/use-agentic/Transcript.d.ts +7 -0
  304. package/types/vendor/use-agentic/index.d.ts +1 -0
  305. package/types/vendor/use-agentic/types.d.ts +6 -0
  306. package/types/webkit/useDebounce.d.ts +1 -1
  307. package/ui/Agent/Chat.tsx +1 -0
  308. package/ui/Agent/Composer.tsx +2 -0
  309. package/ui/Agent/Menu.tsx +5 -1
  310. package/ui/Agent/agentSessionOf.ts +15 -8
  311. package/ui/Agent/mentionDraft.ts +2 -3
  312. package/ui/Agent/useReferenceMenu.ts +1 -0
  313. package/ui/Agent/useSlashMenu.ts +1 -0
  314. package/ui/Clipboard.tsx +1 -0
  315. package/ui/CsrImage.tsx +3 -1
  316. package/ui/Data/CardList.tsx +1 -1
  317. package/ui/Data/Dashboard.tsx +1 -1
  318. package/ui/Data/Insight.tsx +1 -1
  319. package/ui/Data/Item.tsx +5 -2
  320. package/ui/Data/ListContainer.tsx +2 -2
  321. package/ui/Data/Pagination.tsx +1 -1
  322. package/ui/Data/TableList.tsx +1 -1
  323. package/ui/DraggableList.tsx +1 -0
  324. package/ui/Field/Collection.tsx +4 -0
  325. package/ui/Field/Relation.tsx +33 -14
  326. package/ui/Field/useRelationOptions.ts +33 -5
  327. package/ui/Field/useRelationWindow.ts +50 -0
  328. package/ui/Image.tsx +4 -4
  329. package/ui/Input.tsx +1 -0
  330. package/ui/Layout/Sider.tsx +1 -1
  331. package/ui/Link/Anchor.tsx +7 -5
  332. package/ui/Load/Units.tsx +17 -7
  333. package/ui/Load/View.tsx +2 -2
  334. package/ui/Model/Edit.tsx +1 -1
  335. package/ui/Model/EditModal.tsx +11 -5
  336. package/ui/Model/New.tsx +1 -1
  337. package/ui/Model/SureToRemove.tsx +1 -0
  338. package/ui/Model/ViewEditModal.tsx +17 -5
  339. package/ui/Model/ViewModal.tsx +2 -2
  340. package/ui/ObjectId.tsx +5 -1
  341. package/ui/Pagination.tsx +1 -1
  342. package/ui/Signal/Arg.tsx +1 -3
  343. package/ui/Signal/Doc.tsx +5 -1
  344. package/ui/System/CSR.tsx +1 -1
  345. package/ui/System/Client.tsx +1 -1
  346. package/ui/System/Reconnect.tsx +1 -1
  347. package/ui/System/SSR.tsx +3 -36
  348. package/ui/ToggleSelect.tsx +2 -0
  349. package/ui/styles.css +10 -103
  350. package/vendor/@akanjs/native/native/ios/Sources/AkanNativeBridge.swift +3 -2
  351. package/vendor/@akanjs/native/packages/cli/src/lib/addons.ts +4 -1
  352. package/vendor/@akanjs/native/packages/cli/src/lib/apk.ts +2 -2
  353. package/vendor/@akanjs/native/packages/cli/src/lib/codegen.ts +1 -1
  354. package/vendor/@akanjs/native/packages/cli/src/lib/csp.ts +4 -3
  355. package/vendor/@akanjs/native/packages/cli/src/lib/googleservices.ts +7 -1
  356. package/vendor/@akanjs/native/packages/cli/src/lib/hmr.ts +8 -5
  357. package/vendor/@akanjs/native/packages/cli/src/lib/html.ts +18 -3
  358. package/vendor/@akanjs/native/packages/cli/src/lib/manifestmerge.ts +1 -1
  359. package/vendor/@akanjs/native/packages/cli/src/lib/plist.ts +2 -4
  360. package/vendor/@akanjs/native/packages/cli/src/lib/toolchains.ts +1 -1
  361. package/vendor/@akanjs/native/packages/cli/src/lib/updates.ts +10 -4
  362. package/vendor/@akanjs/native/packages/cli/src/lib/xml.ts +4 -3
  363. package/vendor/@akanjs/native/packages/cli/src/platforms/android.ts +3 -3
  364. package/vendor/@akanjs/native/packages/core/src/kernel.ts +3 -3
  365. package/vendor/@akanjs/native/packages/core/src/live.ts +1 -0
  366. package/vendor/@akanjs/native/packages/core/src/plugin.ts +5 -3
  367. package/vendor/@akanjs/native/packages/desktop/src/host.ts +13 -5
  368. package/vendor/@akanjs/native/packages/desktop/src/lifecycle.ts +1 -0
  369. package/vendor/@akanjs/native/packages/desktop/src/page-veto.ts +1 -1
  370. package/vendor/@akanjs/native/packages/desktop/src/plugin.ts +4 -1
  371. package/vendor/@akanjs/native/plugins/camera/src/web.ts +3 -3
  372. package/vendor/@akanjs/native/plugins/file-picker/src/index.ts +4 -1
  373. package/vendor/@akanjs/native/plugins/local-notifications/src/web.ts +1 -1
  374. package/vendor/@akanjs/native/plugins/secure-storage/src/desktop.ts +1 -1
  375. package/vendor/@akanjs/native/plugins/share/src/options.ts +1 -1
  376. package/vendor/@akanjs/native/plugins/single-instance/src/desktop.ts +3 -2
  377. package/vendor/@akanjs/native/plugins/updates/src/desktop.ts +4 -1
  378. package/vendor/@akanjs/native/plugins/window/src/index.ts +2 -2
  379. package/vendor/use-agentic/Compaction.ts +38 -7
  380. package/vendor/use-agentic/Reference.ts +16 -9
  381. package/vendor/use-agentic/ToolOutput.ts +25 -3
  382. package/vendor/use-agentic/ToolReturn.ts +32 -0
  383. package/vendor/use-agentic/ToolRunner.ts +15 -13
  384. package/vendor/use-agentic/Transcript.ts +38 -2
  385. package/vendor/use-agentic/WIRE.md +20 -0
  386. package/vendor/use-agentic/index.ts +1 -0
  387. package/vendor/use-agentic/types.ts +6 -0
  388. package/webkit/McpAppAgent.ts +12 -2
  389. package/webkit/RenderLayer.tsx +23 -4
  390. package/webkit/useDebounce.ts +23 -14
  391. package/client/viewTransition.ts +0 -10
  392. package/types/client/viewTransition.d.ts +0 -3
@@ -36,6 +36,7 @@ interface ActionProps {
36
36
  label: ReactNode;
37
37
  onAct: () => void;
38
38
  closeView: () => void;
39
+ isBlocked?: boolean;
39
40
  }
40
41
 
41
42
  const EditAction = ({ modelName, label, onAct, closeView }: ActionProps) => {
@@ -45,21 +46,30 @@ const EditAction = ({ modelName, label, onAct, closeView }: ActionProps) => {
45
46
  .desc(`Turn the open ${modelName} from its detail view into the edit form.`)
46
47
  .exec(onAct);
47
48
  return (
48
- <button className={buttonRecipe({ variant: "primary" }, "w-full")} onClick={editModel} {...agentAttrs(editModel)}>
49
+ <button
50
+ type="button"
51
+ className={buttonRecipe({ variant: "primary" }, "w-full")}
52
+ onClick={editModel}
53
+ {...agentAttrs(editModel)}
54
+ >
49
55
  <AiOutlineEdit /> {label}
50
56
  </button>
51
57
  );
52
58
  };
53
59
 
54
- const SaveAction = ({ modelName, label, onAct, closeView }: ActionProps) => {
60
+ const SaveAction = ({ modelName, label, onAct, closeView, isBlocked = false }: ActionProps) => {
55
61
  useCloseViewTool(modelName, closeView);
56
62
  const submitModel = st
57
- .tool(`submit${capitalize(modelName)}`)
63
+ .tool(`submit${capitalize(modelName)}`, {
64
+ guard: () => (isBlocked ? `The ${modelName} form is not ready to submit.` : true),
65
+ })
58
66
  .desc(`Save the ${modelName} the open form holds.`)
59
67
  .exec(onAct);
60
68
  return (
61
69
  <button
70
+ type="button"
62
71
  className={buttonRecipe({ variant: "primary" }, "w-full")}
72
+ disabled={isBlocked}
63
73
  onClick={submitModel}
64
74
  {...agentAttrs(submitModel)}
65
75
  >
@@ -94,7 +104,7 @@ export default function ViewEditModal({
94
104
  saveLabel,
95
105
  }: ViewEditModalProps) {
96
106
  const { l } = usePage();
97
- const storeUse = st.use as unknown as { [key: string]: () => unknown };
107
+ const storeUse = st.use as unknown as { [key: string]: (option?: { agent?: boolean }) => unknown };
98
108
  const storeDo = st.do as unknown as { [key: string]: (...args: any[]) => void };
99
109
  const storeSel = st.sel as unknown as <Ret, Val>(selector: (state: { [key: string]: Val }) => Ret) => Ret;
100
110
  const { refName, sliceName } = slice;
@@ -116,11 +126,12 @@ export default function ViewEditModal({
116
126
  const modelLoading = storeUse[names.modelLoading]() as string | boolean;
117
127
  const modelFormLoading = storeUse[names.modelFormLoading]() as string | boolean;
118
128
  const modelFormId = storeSel<string, { id: string }>((state) => state[names.modelForm].id);
129
+ const isUploading = Object.keys(storeUse[`${modelName}FormUploading`]({ agent: false }) as object).length > 0;
119
130
  const canUpdate = !!servedEndpointOf(fetch, `update${ModelName}`);
120
131
  const canRemove = !!servedEndpointOf(fetch, `remove${ModelName}`);
121
132
  const isModalOpen = modelModal === "view" || (modelModal === "edit" && (!!modelFormLoading || !!modelFormId));
122
133
  const Title = () => {
123
- if (!model || modelLoading || !renderTitle) return <></>;
134
+ if (!model || modelLoading || !renderTitle) return null;
124
135
  const render = renderTitle(model);
125
136
  if (typeof render === "string")
126
137
  return <h2 className="flex items-center text-sm md:text-base lg:text-lg xl:text-2xl">{render}</h2>;
@@ -182,6 +193,7 @@ export default function ViewEditModal({
182
193
  modelName={modelName}
183
194
  label={saveLabel ?? l("base.save")}
184
195
  closeView={closeView}
196
+ isBlocked={isUploading}
185
197
  onAct={() => {
186
198
  storeDo[names.submitModel]({ sliceName, modal: "view" });
187
199
  }}
@@ -59,13 +59,13 @@ export default function ViewModal({
59
59
  const modelLoading = storeUse[names.modelLoading]() as string | boolean;
60
60
  const isModalOpen = modelModal === (modal ?? "view") && (modelLoading === id || model?.id === id);
61
61
  const Title = () => {
62
- if (!model || modelLoading || !renderTitle) return <></>;
62
+ if (!model || modelLoading || !renderTitle) return null;
63
63
  const render = renderTitle(model);
64
64
  if (typeof render === "string") return <h2 className="flex items-center text-2xl">{render}</h2>;
65
65
  else return render;
66
66
  };
67
67
  const Action = () => {
68
- if (!model || modelLoading || !renderAction) return <></>;
68
+ if (!model || modelLoading || !renderAction) return null;
69
69
  const render = renderAction(model);
70
70
  return render;
71
71
  };
package/ui/ObjectId.tsx CHANGED
@@ -26,7 +26,11 @@ export const ObjectId = ({ id }: ObjectIdProps) => {
26
26
  <Tooltip content={id} variant="primary">
27
27
  <div className="font-semibold text-xs">{shortenedId}</div>
28
28
  </Tooltip>
29
- <button className={recipe({ variant: "ghost", size: "icon" }, "size-6 rounded-full")} onClick={handleCopyClick}>
29
+ <button
30
+ type="button"
31
+ className={recipe({ variant: "ghost", size: "icon" }, "size-6 rounded-full")}
32
+ onClick={handleCopyClick}
33
+ >
30
34
  {isCopied ? <AiOutlineCheck /> : <AiOutlineCopy />}
31
35
  </button>
32
36
  </div>
package/ui/Pagination.tsx CHANGED
@@ -62,7 +62,7 @@ export const DefaultPagination = ({
62
62
  }
63
63
 
64
64
  const emptyNode = empty ?? renderEmpty;
65
- if (total <= 0) return emptyNode ? <>{emptyNode}</> : null;
65
+ if (total <= 0) return emptyNode || null;
66
66
  return (
67
67
  <div className={cn("flex items-center justify-center gap-1", classNames?.className)}>
68
68
  <button
package/ui/Signal/Arg.tsx CHANGED
@@ -37,9 +37,7 @@ export default function Arg({ argType, value, onChange }: ArgProps) {
37
37
  <Arg.Json value={value as string} onChange={onChange} />
38
38
  ) : argType === "Upload" ? (
39
39
  <Arg.Upload value={value as FileList} onChange={onChange} />
40
- ) : (
41
- <></>
42
- );
40
+ ) : null;
43
41
  }
44
42
 
45
43
  interface ArgTableProps {
package/ui/Signal/Doc.tsx CHANGED
@@ -74,7 +74,10 @@ export const DocSetting = ({ fetch = runtimeFetch, search, onSearch }: DocSettin
74
74
  <Toolbar>
75
75
  <ToolbarField label={l.trans(signalText.baseUrl)}>
76
76
  <Copy text={fetch.origin}>
77
- <button className={buttonRecipe({ variant: "ghost", size: "sm" }, "font-mono text-foreground/80")}>
77
+ <button
78
+ type="button"
79
+ className={buttonRecipe({ variant: "ghost", size: "sm" }, "font-mono text-foreground/80")}
80
+ >
78
81
  {fetch.origin}
79
82
  <AiOutlineCopy className="text-foreground/40" />
80
83
  </button>
@@ -173,6 +176,7 @@ export const DocAuthModal = ({ children }: DocAuthModalProps) => {
173
176
  title={l.trans(signalText.setJwtTitle)}
174
177
  action={
175
178
  <button
179
+ type="button"
176
180
  className={buttonRecipe({ variant: "primary" }, "w-full")}
177
181
  onClick={() => {
178
182
  st.set(
package/ui/System/CSR.tsx CHANGED
@@ -367,7 +367,7 @@ const CSRFrameSlotTargets = ({ slot }: { slot: FrameSlotTarget }) => {
367
367
  };
368
368
 
369
369
  const CSRInner = () => {
370
- return <></>;
370
+ return null;
371
371
  };
372
372
  CSR.Inner = CSRInner;
373
373
 
@@ -53,7 +53,7 @@ import { Messages } from "./Messages";
53
53
  import { Reconnect } from "./Reconnect";
54
54
 
55
55
  export const Client = () => {
56
- return <></>;
56
+ return null;
57
57
  };
58
58
  interface ClientWrapperProps {
59
59
  children: ReactNode;
@@ -29,7 +29,7 @@ export const Reconnect = () => {
29
29
 
30
30
  try {
31
31
  await (fetch as unknown as { ping: () => Promise<string> }).ping();
32
- } catch (e) {
32
+ } catch {
33
33
  setConnectStatus((prev) => (prev === "normal" || prev === "initial" ? "disconnected" : prev));
34
34
  setTimeout(() => {
35
35
  setConnectStatus((prev) => (prev === "disconnected" ? "connecting" : prev));
package/ui/System/SSR.tsx CHANGED
@@ -7,20 +7,10 @@ import {
7
7
  type ReactFont,
8
8
  router,
9
9
  Translator,
10
- transitionTypes,
11
10
  usePage,
12
- viewTransitionClassOf,
13
11
  } from "akanjs/client";
14
12
  import { getRequestFrameState, setRequestTheme } from "akanjs/fetch";
15
- import {
16
- Children,
17
- type CSSProperties,
18
- Fragment,
19
- type ReactNode,
20
- Suspense,
21
- type ViewTransitionClassPerType,
22
- } from "react";
23
- import { ViewTransition } from "../../client/viewTransition";
13
+ import { Children, type CSSProperties, Fragment, type ReactNode, Suspense } from "react";
24
14
  import { FontCss } from "../fontCss";
25
15
  import { frameSlotContainerClassNames, frameSlotContentClassNames, frameSlotStyles } from "../Layout/frameSlot";
26
16
  import { Load } from "../Load";
@@ -28,7 +18,7 @@ import { ClientBridge, ClientInner, ClientPathWrapper, ClientSsrBridge, ClientWr
28
18
  import { getFrameCssVars, isResponsiveFrame, type ProviderProps } from "./Common";
29
19
 
30
20
  export const SSR = () => {
31
- return <></>;
21
+ return null;
32
22
  };
33
23
 
34
24
  export type SSRProviderProps = ProviderProps & {
@@ -124,18 +114,6 @@ const ServerFontFace = ({ fonts }: { fonts: ReactFont[] }) => {
124
114
  );
125
115
  };
126
116
 
127
- const pageViewTransition: ViewTransitionClassPerType = Object.fromEntries([
128
- ["default", "none"],
129
- ...transitionTypes.flatMap((transition) =>
130
- transition === "none"
131
- ? []
132
- : (["push", "pop"] as const).map((direction) => {
133
- const type = viewTransitionClassOf(transition, direction);
134
- return [type, type];
135
- }),
136
- ),
137
- ]);
138
-
139
117
  interface SSRWrapperProps {
140
118
  className?: string;
141
119
  appName: string;
@@ -220,18 +198,7 @@ const SSRWrapper = ({
220
198
  layoutStyle === "mobile" && "left-1/2 h-screen w-full max-w-[600px] -translate-x-1/2",
221
199
  )}
222
200
  >
223
- {ViewTransition ? (
224
- <ViewTransition
225
- default="none"
226
- enter={pageViewTransition}
227
- exit={pageViewTransition}
228
- update={pageViewTransition}
229
- >
230
- {Children.toArray(children)}
231
- </ViewTransition>
232
- ) : (
233
- Children.toArray(children)
234
- )}
201
+ {Children.toArray(children)}
235
202
  </div>
236
203
  </div>
237
204
  </div>
@@ -70,6 +70,7 @@ const DefaultToggleSelect = <I extends string | number | boolean | null>({
70
70
  <Fragment key={idx}>{renderItem(option, { selected: isSelected, disabled: isDisabled, onToggle })}</Fragment>
71
71
  ) : (
72
72
  <button
73
+ type="button"
73
74
  key={idx}
74
75
  disabled={isDisabled}
75
76
  className={cn(toggleBtn, isSelected && selectedCls, isDisabled && "cursor-not-allowed", btnClassName)}
@@ -128,6 +129,7 @@ const DefaultMulti = ({
128
129
  const isDisabled = (disabled ?? false) || (option.disabled ?? false);
129
130
  return (
130
131
  <button
132
+ type="button"
131
133
  key={idx}
132
134
  disabled={isDisabled}
133
135
  className={cn(toggleBtn, isSelected && selectedCls, isDisabled && "cursor-not-allowed", btnClassName)}
package/ui/styles.css CHANGED
@@ -140,6 +140,16 @@ body {
140
140
  -webkit-user-select: none; */
141
141
  }
142
142
 
143
+ /* An installed web app's document does not rubber-band; in a browser tab the page keeps the browser's own feel. */
144
+ @layer base {
145
+ @media (display-mode: standalone) {
146
+ html,
147
+ body {
148
+ overscroll-behavior-y: none;
149
+ }
150
+ }
151
+ }
152
+
143
153
  html.akan-mobile-document,
144
154
  body.akan-mobile-document {
145
155
  width: 100%;
@@ -323,109 +333,6 @@ body.akan-mobile-document {
323
333
  }
324
334
  }
325
335
 
326
- /* Route transitions on the web: an RSC navigation tags itself `akan-<transition>-<push|pop>` from the route's
327
- `.config({ transition })`, and the page content's ViewTransition takes that class. The rest of the page holds. */
328
- :root:active-view-transition-type(akan-nav)::view-transition-old(root),
329
- :root:active-view-transition-type(akan-nav)::view-transition-new(root) {
330
- animation: none;
331
- }
332
- ::view-transition-old(.akan-stack-push) {
333
- animation: 260ms cubic-bezier(0.32, 0.72, 0, 1) both akan-vt-out-left;
334
- }
335
- ::view-transition-new(.akan-stack-push) {
336
- animation: 260ms cubic-bezier(0.32, 0.72, 0, 1) both akan-vt-in-right;
337
- }
338
- ::view-transition-old(.akan-stack-pop) {
339
- animation: 260ms cubic-bezier(0.32, 0.72, 0, 1) both akan-vt-out-right;
340
- }
341
- ::view-transition-new(.akan-stack-pop) {
342
- animation: 260ms cubic-bezier(0.32, 0.72, 0, 1) both akan-vt-in-left;
343
- }
344
- ::view-transition-old(.akan-bottomUp-push),
345
- ::view-transition-new(.akan-bottomUp-pop) {
346
- animation: none;
347
- }
348
- ::view-transition-new(.akan-bottomUp-push) {
349
- animation: 280ms cubic-bezier(0.32, 0.72, 0, 1) both akan-vt-in-up;
350
- }
351
- ::view-transition-old(.akan-bottomUp-pop) {
352
- animation: 240ms ease-in both akan-vt-out-down;
353
- }
354
- ::view-transition-old(.akan-fade-push),
355
- ::view-transition-old(.akan-fade-pop) {
356
- animation: 180ms ease-in both akan-vt-fade-out;
357
- }
358
- ::view-transition-new(.akan-fade-push),
359
- ::view-transition-new(.akan-fade-pop) {
360
- animation: 180ms ease-out both akan-vt-fade-in;
361
- }
362
- ::view-transition-old(.akan-scaleOut-push) {
363
- animation: 220ms ease-in both akan-vt-shrink-out;
364
- }
365
- ::view-transition-new(.akan-scaleOut-push) {
366
- animation: 220ms ease-out both akan-vt-fade-in;
367
- }
368
- ::view-transition-old(.akan-scaleOut-pop) {
369
- animation: 200ms ease-in both akan-vt-fade-out;
370
- }
371
- ::view-transition-new(.akan-scaleOut-pop) {
372
- animation: 220ms ease-out both akan-vt-grow-in;
373
- }
374
- @keyframes akan-vt-in-right {
375
- from {
376
- transform: translateX(100%);
377
- }
378
- }
379
- @keyframes akan-vt-out-left {
380
- to {
381
- transform: translateX(-30%);
382
- opacity: 0.6;
383
- }
384
- }
385
- @keyframes akan-vt-in-left {
386
- from {
387
- transform: translateX(-30%);
388
- opacity: 0.6;
389
- }
390
- }
391
- @keyframes akan-vt-out-right {
392
- to {
393
- transform: translateX(100%);
394
- }
395
- }
396
- @keyframes akan-vt-in-up {
397
- from {
398
- transform: translateY(100%);
399
- }
400
- }
401
- @keyframes akan-vt-out-down {
402
- to {
403
- transform: translateY(100%);
404
- }
405
- }
406
- @keyframes akan-vt-fade-in {
407
- from {
408
- opacity: 0;
409
- }
410
- }
411
- @keyframes akan-vt-fade-out {
412
- to {
413
- opacity: 0;
414
- }
415
- }
416
- @keyframes akan-vt-shrink-out {
417
- to {
418
- transform: scale(0.94);
419
- opacity: 0;
420
- }
421
- }
422
- @keyframes akan-vt-grow-in {
423
- from {
424
- transform: scale(0.94);
425
- opacity: 0;
426
- }
427
- }
428
-
429
336
  /* Always-included keyframes (non-theme animations) */
430
337
  @keyframes smaller {
431
338
  0% {
@@ -194,8 +194,9 @@ final class AkanNativeBridge: NSObject {
194
194
  return AkanNativeLog.info("emit \(plugin).\(event): data is not JSON, dropped")
195
195
  }
196
196
  // Arguments go in as values, so no JS string escaping is involved.
197
- webView.callAsyncJavaScript("window.__AKAN_NATIVE__ && window.__AKAN_NATIVE__.receive(m)", arguments: ["m": text], in: nil, in: .page) { result in
198
- if case .failure(let error) = result { AkanNativeLog.info("emit \(plugin).\(event) failed: \(error)") }
197
+ // The ObjC method: below an iOS 18.4 target Swift's Result overlay links libswiftWebKit.dylib, absent on iOS 18.5.
198
+ webView.__callAsyncJavaScript("window.__AKAN_NATIVE__ && window.__AKAN_NATIVE__.receive(m)", arguments: ["m": text], inFrame: nil, in: .page) { _, error in
199
+ if let error { AkanNativeLog.info("emit \(plugin).\(event) failed: \(error)") }
199
200
  }
200
201
  }
201
202
 
@@ -61,7 +61,10 @@ export function addonReport(serverDir: string, os: AddonOs, arch: AddonArch): Ad
61
61
  `${name} was compiled on this computer at install (binding.gyp, no prebuilt binary): check that it runs on a computer with nothing else installed`,
62
62
  );
63
63
  }
64
- return { problems: problems.sort(), warnings: warnings.sort() };
64
+ return {
65
+ problems: problems.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)),
66
+ warnings: warnings.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)),
67
+ };
65
68
  }
66
69
 
67
70
  /** A path inside the server as the report names it: relative, `/`-separated on every OS. */
@@ -172,7 +172,7 @@ export function assembleApk({ base, dex, assetsDir, extra = [] }: ApkInput): Uin
172
172
  for (const [i, bytes] of dex.entries())
173
173
  entries.push(fileEntry(i === 0 ? "classes.dex" : `classes${i + 1}.dex`, bytes, true));
174
174
  for (const e of extra) entries.push(fileEntry(e.name, e.bytes, false));
175
- for (const file of walk(assetsDir).sort()) {
175
+ for (const file of walk(assetsDir).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))) {
176
176
  const rel = relative(assetsDir, file).split("\\").join("/");
177
177
  const ext = rel.split(".").pop()!.toLowerCase();
178
178
  entries.push(fileEntry(`assets/${rel}`, new Uint8Array(readFileSync(file)), STORE_EXT.has(ext)));
@@ -194,7 +194,7 @@ export function assembleBundleModule({ base, dex, assetsDir, extra = [] }: ApkIn
194
194
  entries.push(fileEntry(`dex/${i === 0 ? "classes.dex" : `classes${i + 1}.dex`}`, bytes, false));
195
195
 
196
196
  for (const e of extra) entries.push(fileEntry(e.name.startsWith("lib/") ? e.name : `root/${e.name}`, e.bytes, false));
197
- for (const file of walk(assetsDir).sort()) {
197
+ for (const file of walk(assetsDir).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))) {
198
198
  const rel = relative(assetsDir, file).split("\\").join("/");
199
199
  const ext = rel.split(".").pop()!.toLowerCase();
200
200
  entries.push(fileEntry(`assets/${rel}`, new Uint8Array(readFileSync(file)), STORE_EXT.has(ext)));
@@ -889,7 +889,7 @@ export function generateKotlin(model: GenModel, pkg: string): string {
889
889
  } else out.push(` ${JSON.stringify(m.name)} -> ${kotlinName(m.name)}(${reply})`);
890
890
  }
891
891
  out.push(
892
- ' else -> call.reject(AkanNativeErrorCode.NOT_FOUND, "unknown method ${call.method}")',
892
+ ` else -> call.reject(AkanNativeErrorCode.NOT_FOUND, "unknown method \${call.method}")`,
893
893
  " }",
894
894
  " }",
895
895
  "}",
@@ -157,9 +157,10 @@ export function injectCspMeta(html: string, policy: string): string {
157
157
  );
158
158
  }
159
159
  const tag = `<meta http-equiv="Content-Security-Policy" content="${policy.replace(/&/g, "&amp;").replace(/"/g, "&quot;")}">`;
160
- const head = /<head(\s[^>]*)?>/i.exec(html);
161
- if (!head) throw new CliError("index.html has no <head> for the Content-Security-Policy <meta>");
162
- const afterHead = head.index + head[0].length;
160
+ const head = /<head[\s>]/i.exec(html);
161
+ const headEnd = head ? html.indexOf(">", head.index) : -1;
162
+ if (headEnd < 0) throw new CliError("index.html has no <head> for the Content-Security-Policy <meta>");
163
+ const afterHead = headEnd + 1;
163
164
  const rest = html.slice(afterHead);
164
165
  const charset = /<meta\b[^>]*\bcharset\s*=[^>]*>/i.exec(rest);
165
166
 
@@ -12,7 +12,13 @@ interface GoogleServices {
12
12
  }
13
13
 
14
14
  const escape = (s: string) =>
15
- s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "\\'").replace(/"/g, '\\"');
15
+ s
16
+ .replace(/\\/g, "\\\\")
17
+ .replace(/&/g, "&amp;")
18
+ .replace(/</g, "&lt;")
19
+ .replace(/>/g, "&gt;")
20
+ .replace(/'/g, "\\'")
21
+ .replace(/"/g, '\\"');
16
22
 
17
23
  /** res/values/google_services.xml for `packageName` (and `fallbackPackage` when it has no client). */
18
24
  export function googleServicesXml(json: string, packageName: string, fallbackPackage = packageName): string {
@@ -25,6 +25,9 @@ export function resolveDevEntry(project: Project): string {
25
25
  );
26
26
  }
27
27
 
28
+ const scriptJson = (value: unknown) =>
29
+ JSON.stringify(value).replace(/[<>\u2028\u2029]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`);
30
+
28
31
  /**
29
32
  * Inline classic script in the dev page. It runs while the document is parsed, so before Bun's
30
33
  * client (a module script, deferred).
@@ -47,17 +50,17 @@ export function devShim(socket?: { origin: string; path?: string; paths?: string
47
50
  socket === undefined
48
51
  ? ""
49
52
  : "var W=window.WebSocket,T=" +
50
- JSON.stringify(socket.origin) +
53
+ scriptJson(socket.origin) +
51
54
  ",P=" +
52
- JSON.stringify([socket.path ?? HMR_PATH, ...(socket.paths ?? [])]) +
55
+ scriptJson([socket.path ?? HMR_PATH, ...(socket.paths ?? [])]) +
53
56
  ";function S(u,p){try{var x=new URL(String(u),location.href);if(P.indexOf(x.pathname)>=0&&x.host===location.host)u=T+x.pathname+x.search}catch(e){}return p===undefined?new W(u):new W(u,p)}" +
54
57
  "S.prototype=W.prototype;S.CONNECTING=0;S.OPEN=1;S.CLOSING=2;S.CLOSED=3;window.WebSocket=S;";
55
58
  const gateway = socket?.origin.replace(/^ws/, "http");
56
- const marker = gateway === undefined ? "" : `window.__AKAN_NATIVE_DEV__={gateway:${JSON.stringify(gateway)}};`;
59
+ const marker = gateway === undefined ? "" : `window.__AKAN_NATIVE_DEV__={gateway:${scriptJson(gateway)}};`;
57
60
  const bodies = !socket?.relayBodies
58
61
  ? ""
59
62
  : "var G=" +
60
- JSON.stringify(gateway) +
63
+ scriptJson(gateway) +
61
64
  ';function R(u,m){try{var x=new URL(String(u),location.href);m=String(m||"GET").toUpperCase();' +
62
65
  'if(x.origin===location.origin&&m!=="GET"&&m!=="HEAD"&&x.pathname.indexOf("/__akan_native/")!==0)return G+x.pathname+x.search}catch(e){}return null}' +
63
66
  "var F=window.fetch;if(F)window.fetch=function(i,o){var q=window.Request&&i instanceof window.Request," +
@@ -387,7 +390,7 @@ export async function startHmrServer(opts: HmrOptions): Promise<HmrServer> {
387
390
  for (const warning of warnings) warnOnce(warning);
388
391
  return new Response(page, { headers: { ...noCache, "content-type": "text/html; charset=utf-8" } });
389
392
  } catch (error) {
390
- const message = error instanceof Error ? error.message : String(error);
393
+ const message = `dev gateway: the page: ${error instanceof Error ? error.message : String(error)}`;
391
394
  warnOnce(message);
392
395
  return new Response(message, { status: 500, headers: { "content-type": "text/plain; charset=utf-8" } });
393
396
  }
@@ -42,9 +42,24 @@ export const EARLY_ERRORS_SCRIPT =
42
42
 
43
43
  /** Puts the early error collector right after the init.js tag (dev builds). */
44
44
  export function injectEarlyErrors(html: string): string {
45
- const init = /<script\b[^>]*\bsrc\s*=\s*["']?[^"'\s>]*__akan_native\/init\.js[^>]*>\s*<\/script>/i.exec(html);
46
- if (!init) return html;
47
- return insertAt(html, init.index + init[0].length, `<script>${EARLY_ERRORS_SCRIPT}</script>`);
45
+ const opening = /<script\b/gi;
46
+ for (let m = opening.exec(html); m; m = opening.exec(html)) {
47
+ const tagEnd = html.indexOf(">", m.index);
48
+ if (tagEnd < 0) break;
49
+ let closeAt = tagEnd + 1;
50
+ while (closeAt < html.length && /\s/.test(html.charAt(closeAt))) closeAt += 1;
51
+ const closeEnd = closeAt + "</script>".length;
52
+ if (html.slice(closeAt, closeEnd).toLowerCase() === "</script>" && loadsInitScript(html.slice(m.index, tagEnd)))
53
+ return insertAt(html, closeEnd, `<script>${EARLY_ERRORS_SCRIPT}</script>`);
54
+ opening.lastIndex = tagEnd + 1;
55
+ }
56
+ return html;
57
+ }
58
+
59
+ function loadsInitScript(tag: string): boolean {
60
+ for (const src of tag.matchAll(/\bsrc\s*=\s*["']?([^"'\s>]*)/gi))
61
+ if (/__akan_native\/init\.js/i.test(src[1] ?? "")) return true;
62
+ return false;
48
63
  }
49
64
 
50
65
  function insertAt(text: string, index: number, insert: string): string {
@@ -28,7 +28,7 @@ const KEPT_APPLICATION_ATTRS = ["android:appComponentFactory"];
28
28
  function clean(element: XmlElement, applicationId: string): XmlElement {
29
29
  element.attrs = element.attrs
30
30
  .filter(([n]) => !n.startsWith("tools:") && n !== "xmlns:tools")
31
- .map(([n, v]) => [n, v.replaceAll("${applicationId}", applicationId)]);
31
+ .map(([n, v]) => [n, v.replaceAll(`\${applicationId}`, applicationId)]);
32
32
  for (const c of element.children) clean(c, applicationId);
33
33
  return element;
34
34
  }
@@ -62,10 +62,8 @@ const unescape = (text: string) =>
62
62
  */
63
63
  export function parsePlist(xml: string): PlistValue {
64
64
  const tokens = [
65
- ...xml
66
- .replace(/<\?xml[^>]*\?>|<!DOCTYPE[^>]*>|<!--[\s\S]*?-->/g, "")
67
- .matchAll(/<(\/?)([a-zA-Z]+)[^>]*?(\/)?>|([^<]+)/g),
68
- ];
65
+ ...xml.matchAll(/<\?xml[^>]*\?>|<!DOCTYPE[^>]*>|<!--[\s\S]*?-->|<(\/?)([a-zA-Z]+)[^>]*?(\/)?>|([^<]+)/g),
66
+ ].filter((t) => t[2] !== undefined || t[4] !== undefined);
69
67
  let i = 0;
70
68
  const next = () => tokens[i++];
71
69
  const text = (tag: string): string => {
@@ -256,7 +256,7 @@ async function withLock<T>(
256
256
  if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
257
257
  }
258
258
  if (opts.ready()) return null;
259
- let stale = true;
259
+ let stale: boolean;
260
260
  try {
261
261
  const [pid, at] = readFileSync(lock, "utf8").trim().split(" ").map(Number);
262
262
  const alive = (() => {
@@ -175,7 +175,7 @@ export function validateUpdates(raw: unknown, problems: string[]): UpdatesConfig
175
175
  }
176
176
  const r = raw as Record<string, unknown>;
177
177
 
178
- if (typeof r.url !== "string" || !/^https?:\/\/[^/?#]+[^?#]*$/.test(r.url))
178
+ if (typeof r.url !== "string" || !/^https?:\/\/[^/?#][^?#]*$/.test(r.url))
179
179
  problems.push("updates.url must be an http(s) URL without a query or fragment");
180
180
  const publicKeys = updatePublicKeys(r, problems);
181
181
  const revokedKeys = updateRevokedKeys(r.revokedKeys, problems);
@@ -187,13 +187,13 @@ export function validateUpdates(raw: unknown, problems: string[]): UpdatesConfig
187
187
  for (const key of Object.keys(r))
188
188
  if (!["url", "publicKey", "publicKeys", "revokedKeys", "channel", "readyTimeout", "report"].includes(key))
189
189
  problems.push(`updates.${key} is not supported`);
190
- if (publicKeys && publicKeys.every((key) => revokedKeys.includes(keyIdOf(key))))
190
+ if (publicKeys?.every((key) => revokedKeys.includes(keyIdOf(key))))
191
191
  problems.push(
192
192
  "updates.revokedKeys revokes every key of updates.publicKeys: a phone built from it would trust none (add one with `akan-native update keygen`)",
193
193
  );
194
194
  if (typeof r.url !== "string" || !publicKeys) return null;
195
195
  return {
196
- url: r.url.replace(/\/+$/, ""),
196
+ url: withoutTrailingSlashes(r.url),
197
197
  publicKeys,
198
198
  revokedKeys,
199
199
  channel: (r.channel as string | undefined) ?? "production",
@@ -202,11 +202,17 @@ export function validateUpdates(raw: unknown, problems: string[]): UpdatesConfig
202
202
  };
203
203
  }
204
204
 
205
+ function withoutTrailingSlashes(url: string): string {
206
+ let end = url.length;
207
+ while (end > 0 && url[end - 1] === "/") end -= 1;
208
+ return url.slice(0, end);
209
+ }
210
+
205
211
  /** `report: { url }`, posted to as it is: the address is the receiver's, a path of its own included. */
206
212
  function updateReportUrl(raw: unknown, problems: string[]): string | null {
207
213
  if (raw === undefined) return null;
208
214
  const url = raw && typeof raw === "object" && !Array.isArray(raw) ? (raw as Record<string, unknown>).url : undefined;
209
- if (typeof url !== "string" || !/^https?:\/\/[^/?#]+[^#]*$/.test(url) || Object.keys(raw as object).length !== 1) {
215
+ if (typeof url !== "string" || !/^https?:\/\/[^/?#][^#]*$/.test(url) || Object.keys(raw as object).length !== 1) {
210
216
  problems.push("updates.report must be { url } with an http(s) URL");
211
217
  return null;
212
218
  }
@@ -27,12 +27,13 @@ export const escapeXml = (text: string) =>
27
27
 
28
28
  /** Parses a document's root element. Text between elements is ignored (manifests have none that matters). */
29
29
  export function parseXml(source: string): XmlElement {
30
- const text = source.replace(/<\?[\s\S]*?\?>|<!--[\s\S]*?-->|<!DOCTYPE[^>]*>/g, "");
31
- const tag = /<(\/?)([\w:.-]+)((?:\s+[\w:.-]+\s*=\s*(?:"[^"]*"|'[^']*'))*)\s*(\/?)>/g;
30
+ const tag =
31
+ /<\?[\s\S]*?\?>|<!--[\s\S]*?-->|<!DOCTYPE[^>]*>|<(\/?)([\w:.-]+)((?:\s+[\w:.-]+\s*=\s*(?:"[^"]*"|'[^']*'))*)\s*(\/?)>/g;
32
32
  const stack: XmlElement[] = [];
33
33
  let root: XmlElement | null = null;
34
- for (let m = tag.exec(text); m; m = tag.exec(text)) {
34
+ for (let m = tag.exec(source); m; m = tag.exec(source)) {
35
35
  const [, closing, name, attrText, selfClosing] = m;
36
+ if (name === undefined) continue;
36
37
  if (closing) {
37
38
  const open = stack.pop();
38
39
  if (!open || open.name !== name) throw new Error(`XML: </${name}> does not close <${open?.name ?? "nothing"}>`);