@dxos/plugin-client 0.10.0 → 0.11.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 (358) hide show
  1. package/dist/lib/ClientPlugin.mjs +65 -0
  2. package/dist/lib/ClientPlugin.mjs.map +1 -0
  3. package/dist/lib/ClientPlugin.node.mjs +904 -0
  4. package/dist/lib/ClientPlugin.node.mjs.map +1 -0
  5. package/dist/lib/ClientPlugin.workerd.mjs +10 -0
  6. package/dist/lib/ClientPlugin.workerd.mjs.map +1 -0
  7. package/dist/lib/capabilities/node.mjs +13 -0
  8. package/dist/lib/capabilities/node.mjs.map +1 -0
  9. package/dist/lib/capabilities.mjs +23 -0
  10. package/dist/lib/capabilities.mjs.map +1 -0
  11. package/dist/lib/chunk-AccountContainer.mjs +190 -0
  12. package/dist/lib/chunk-AccountContainer.mjs.map +1 -0
  13. package/dist/lib/chunk-DevicesContainer.mjs +275 -0
  14. package/dist/lib/chunk-DevicesContainer.mjs.map +1 -0
  15. package/dist/lib/chunk-InvitationsContainer.mjs +149 -0
  16. package/dist/lib/chunk-InvitationsContainer.mjs.map +1 -0
  17. package/dist/lib/chunk-JoinDialog.mjs +35 -0
  18. package/dist/lib/chunk-JoinDialog.mjs.map +1 -0
  19. package/dist/lib/chunk-ProfileContainer.mjs +145 -0
  20. package/dist/lib/chunk-ProfileContainer.mjs.map +1 -0
  21. package/dist/lib/chunk-RecoveryCodeDialog.mjs +72 -0
  22. package/dist/lib/chunk-RecoveryCodeDialog.mjs.map +1 -0
  23. package/dist/lib/chunk-RecoveryCredentialsContainer.mjs +65 -0
  24. package/dist/lib/chunk-RecoveryCredentialsContainer.mjs.map +1 -0
  25. package/dist/lib/chunk-ResetDialog.mjs +47 -0
  26. package/dist/lib/chunk-ResetDialog.mjs.map +1 -0
  27. package/dist/lib/chunk-UsageContainer.mjs +217 -0
  28. package/dist/lib/chunk-UsageContainer.mjs.map +1 -0
  29. package/dist/lib/{neutral/account-cache-YVQKLNV2.mjs → chunk-account-cache.mjs} +10 -12
  30. package/dist/lib/chunk-account-cache.mjs.map +1 -0
  31. package/dist/lib/chunk-app-graph-builder.mjs +111 -0
  32. package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
  33. package/dist/lib/chunk-client.mjs +90 -0
  34. package/dist/lib/chunk-client.mjs.map +1 -0
  35. package/dist/lib/{neutral/chunk-GSKMAS3S.mjs → chunk-constants.mjs} +5 -8
  36. package/dist/lib/chunk-constants.mjs.map +1 -0
  37. package/dist/lib/chunk-create-agent.mjs +23 -0
  38. package/dist/lib/chunk-create-agent.mjs.map +1 -0
  39. package/dist/lib/chunk-create-identity.mjs +28 -0
  40. package/dist/lib/chunk-create-identity.mjs.map +1 -0
  41. package/dist/lib/chunk-create-passkey.mjs +85 -0
  42. package/dist/lib/chunk-create-passkey.mjs.map +1 -0
  43. package/dist/lib/chunk-create-recovery-code.mjs +31 -0
  44. package/dist/lib/chunk-create-recovery-code.mjs.map +1 -0
  45. package/dist/lib/chunk-hooks.mjs +29 -0
  46. package/dist/lib/chunk-hooks.mjs.map +1 -0
  47. package/dist/lib/chunk-hub-http-client.mjs +14 -0
  48. package/dist/lib/chunk-hub-http-client.mjs.map +1 -0
  49. package/dist/lib/chunk-join-identity.mjs +20 -0
  50. package/dist/lib/chunk-join-identity.mjs.map +1 -0
  51. package/dist/lib/chunk-layer-specs.mjs +107 -0
  52. package/dist/lib/chunk-layer-specs.mjs.map +1 -0
  53. package/dist/lib/{neutral/chunk-6G4KZLBG.mjs → chunk-meta.mjs} +13 -20
  54. package/dist/lib/chunk-meta.mjs.map +1 -0
  55. package/dist/lib/chunk-migrations.mjs +29 -0
  56. package/dist/lib/chunk-migrations.mjs.map +1 -0
  57. package/dist/lib/chunk-navigation-handler.mjs +71 -0
  58. package/dist/lib/chunk-navigation-handler.mjs.map +1 -0
  59. package/dist/lib/chunk-navigation-target-loader.mjs +46 -0
  60. package/dist/lib/chunk-navigation-target-loader.mjs.map +1 -0
  61. package/dist/lib/chunk-open-usage.mjs +14 -0
  62. package/dist/lib/chunk-open-usage.mjs.map +1 -0
  63. package/dist/lib/chunk-operation-handler.mjs +11 -0
  64. package/dist/lib/chunk-operation-handler.mjs.map +1 -0
  65. package/dist/lib/chunk-operations.mjs +212 -0
  66. package/dist/lib/chunk-operations.mjs.map +1 -0
  67. package/dist/lib/chunk-progress.mjs +10 -0
  68. package/dist/lib/chunk-progress.mjs.map +1 -0
  69. package/dist/lib/chunk-react-context.mjs +30 -0
  70. package/dist/lib/chunk-react-context.mjs.map +1 -0
  71. package/dist/lib/chunk-react-surface.mjs +70 -0
  72. package/dist/lib/chunk-react-surface.mjs.map +1 -0
  73. package/dist/lib/chunk-recover-identity.mjs +17 -0
  74. package/dist/lib/chunk-recover-identity.mjs.map +1 -0
  75. package/dist/lib/chunk-redeem-passkey.mjs +72 -0
  76. package/dist/lib/chunk-redeem-passkey.mjs.map +1 -0
  77. package/dist/lib/chunk-redeem-token.mjs +24 -0
  78. package/dist/lib/chunk-redeem-token.mjs.map +1 -0
  79. package/dist/lib/chunk-remote-trace-monitor.mjs +37 -0
  80. package/dist/lib/chunk-remote-trace-monitor.mjs.map +1 -0
  81. package/dist/lib/chunk-reset-storage.mjs +17 -0
  82. package/dist/lib/chunk-reset-storage.mjs.map +1 -0
  83. package/dist/lib/chunk-resolve-navigation-targets.mjs +32 -0
  84. package/dist/lib/chunk-resolve-navigation-targets.mjs.map +1 -0
  85. package/dist/lib/chunk-schema-defs.mjs +53 -0
  86. package/dist/lib/chunk-schema-defs.mjs.map +1 -0
  87. package/dist/lib/chunk-share-identity.mjs +16 -0
  88. package/dist/lib/chunk-share-identity.mjs.map +1 -0
  89. package/dist/lib/chunk-space-replication-progress.mjs +94 -0
  90. package/dist/lib/chunk-space-replication-progress.mjs.map +1 -0
  91. package/dist/lib/chunk-trace-progress.mjs +69 -0
  92. package/dist/lib/chunk-trace-progress.mjs.map +1 -0
  93. package/dist/lib/chunk-update-profile.mjs +15 -0
  94. package/dist/lib/chunk-update-profile.mjs.map +1 -0
  95. package/dist/lib/components.mjs +0 -0
  96. package/dist/lib/containers.mjs +15 -0
  97. package/dist/lib/containers.mjs.map +1 -0
  98. package/dist/lib/index.mjs +27 -0
  99. package/dist/lib/index.mjs.map +1 -0
  100. package/dist/lib/meta.mjs +2 -0
  101. package/dist/lib/operations.mjs +2 -0
  102. package/dist/lib/plugin.mjs +9 -0
  103. package/dist/lib/plugin.mjs.map +1 -0
  104. package/dist/lib/testing.mjs +21 -0
  105. package/dist/lib/testing.mjs.map +1 -0
  106. package/dist/lib/translations.mjs +111 -0
  107. package/dist/lib/translations.mjs.map +1 -0
  108. package/dist/lib/types.mjs +139 -0
  109. package/dist/lib/types.mjs.map +1 -0
  110. package/dist/types/src/ClientPlugin.d.ts.map +1 -1
  111. package/dist/types/src/capabilities/account-cache.d.ts +1 -1
  112. package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
  113. package/dist/types/src/capabilities/client.d.ts +1 -1
  114. package/dist/types/src/capabilities/client.d.ts.map +1 -1
  115. package/dist/types/src/capabilities/hub-http-client.d.ts +1 -1
  116. package/dist/types/src/capabilities/index.d.ts +6 -1
  117. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  118. package/dist/types/src/capabilities/layer-specs.d.ts +1 -1
  119. package/dist/types/src/capabilities/migrations.d.ts +1 -1
  120. package/dist/types/src/capabilities/navigation-handler/navigation-handler.d.ts +3 -1
  121. package/dist/types/src/capabilities/navigation-handler/navigation-handler.d.ts.map +1 -1
  122. package/dist/types/src/capabilities/navigation-target-loader.d.ts +11 -0
  123. package/dist/types/src/capabilities/navigation-target-loader.d.ts.map +1 -0
  124. package/dist/types/src/capabilities/node.d.ts +2 -1
  125. package/dist/types/src/capabilities/node.d.ts.map +1 -1
  126. package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
  127. package/dist/types/src/capabilities/react-context.d.ts +1 -1
  128. package/dist/types/src/capabilities/react-context.d.ts.map +1 -1
  129. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  130. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  131. package/dist/types/src/capabilities/remote-trace-monitor.d.ts +15 -0
  132. package/dist/types/src/capabilities/remote-trace-monitor.d.ts.map +1 -0
  133. package/dist/types/src/capabilities/schema-defs.d.ts +1 -1
  134. package/dist/types/src/capabilities/space-replication-progress.d.ts +11 -0
  135. package/dist/types/src/capabilities/space-replication-progress.d.ts.map +1 -0
  136. package/dist/types/src/capabilities/trace-progress.d.ts +17 -0
  137. package/dist/types/src/capabilities/trace-progress.d.ts.map +1 -0
  138. package/dist/types/src/commands/account/login/login.d.ts +2 -1
  139. package/dist/types/src/commands/account/login/login.d.ts.map +1 -1
  140. package/dist/types/src/commands/account/logout/logout.d.ts +1 -1
  141. package/dist/types/src/commands/account/logout/logout.d.ts.map +1 -1
  142. package/dist/types/src/commands/halo/index.d.ts.map +1 -1
  143. package/dist/types/src/commands/halo/share/share.d.ts.map +1 -1
  144. package/dist/types/src/commands/profile/create.d.ts.map +1 -1
  145. package/dist/types/src/containers/AccountContainer/AccountContainer.d.ts +4 -1
  146. package/dist/types/src/containers/AccountContainer/AccountContainer.d.ts.map +1 -1
  147. package/dist/types/src/containers/AccountContainer/AccountContainer.stories.d.ts +4 -1
  148. package/dist/types/src/containers/AccountContainer/AccountContainer.stories.d.ts.map +1 -1
  149. package/dist/types/src/containers/DevicesContainer/DevicesContainer.d.ts +4 -1
  150. package/dist/types/src/containers/DevicesContainer/DevicesContainer.d.ts.map +1 -1
  151. package/dist/types/src/containers/DevicesContainer/DevicesContainer.stories.d.ts +4 -1
  152. package/dist/types/src/containers/DevicesContainer/DevicesContainer.stories.d.ts.map +1 -1
  153. package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.d.ts +4 -1
  154. package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.d.ts.map +1 -1
  155. package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.stories.d.ts +4 -1
  156. package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.stories.d.ts.map +1 -1
  157. package/dist/types/src/containers/JoinDialog/JoinDialog.d.ts +4 -1
  158. package/dist/types/src/containers/JoinDialog/JoinDialog.d.ts.map +1 -1
  159. package/dist/types/src/containers/JoinDialog/JoinDialog.stories.d.ts +4 -1
  160. package/dist/types/src/containers/JoinDialog/JoinDialog.stories.d.ts.map +1 -1
  161. package/dist/types/src/containers/ProfileContainer/ProfileContainer.d.ts +4 -1
  162. package/dist/types/src/containers/ProfileContainer/ProfileContainer.d.ts.map +1 -1
  163. package/dist/types/src/containers/ProfileContainer/ProfileContainer.stories.d.ts +4 -1
  164. package/dist/types/src/containers/ProfileContainer/ProfileContainer.stories.d.ts.map +1 -1
  165. package/dist/types/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.d.ts +4 -1
  166. package/dist/types/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.d.ts.map +1 -1
  167. package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.d.ts +4 -1
  168. package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.d.ts.map +1 -1
  169. package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.stories.d.ts +4 -1
  170. package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.stories.d.ts.map +1 -1
  171. package/dist/types/src/containers/ResetDialog/ResetDialog.d.ts +4 -1
  172. package/dist/types/src/containers/ResetDialog/ResetDialog.d.ts.map +1 -1
  173. package/dist/types/src/containers/ResetDialog/ResetDialog.stories.d.ts +4 -1
  174. package/dist/types/src/containers/ResetDialog/ResetDialog.stories.d.ts.map +1 -1
  175. package/dist/types/src/containers/UsageContainer/UsageContainer.d.ts +4 -5
  176. package/dist/types/src/containers/UsageContainer/UsageContainer.d.ts.map +1 -1
  177. package/dist/types/src/containers/UsageContainer/UsageView.d.ts +4 -7
  178. package/dist/types/src/containers/UsageContainer/UsageView.d.ts.map +1 -1
  179. package/dist/types/src/containers/UsageContainer/UsageView.stories.d.ts +4 -2
  180. package/dist/types/src/containers/UsageContainer/UsageView.stories.d.ts.map +1 -1
  181. package/dist/types/src/halo-services-layer.d.ts +19 -0
  182. package/dist/types/src/halo-services-layer.d.ts.map +1 -0
  183. package/dist/types/src/index.d.ts +3 -0
  184. package/dist/types/src/index.d.ts.map +1 -1
  185. package/dist/types/src/operations/definitions.d.ts +9 -1
  186. package/dist/types/src/operations/definitions.d.ts.map +1 -1
  187. package/dist/types/src/operations/errors.d.ts +109 -0
  188. package/dist/types/src/operations/errors.d.ts.map +1 -0
  189. package/dist/types/src/operations/errors.test.d.ts +2 -0
  190. package/dist/types/src/operations/errors.test.d.ts.map +1 -0
  191. package/dist/types/src/operations/index.d.ts +1 -0
  192. package/dist/types/src/operations/index.d.ts.map +1 -1
  193. package/dist/types/src/operations/redeem-passkey.d.ts.map +1 -1
  194. package/dist/types/src/operations/resolve-navigation-targets.d.ts +5 -0
  195. package/dist/types/src/operations/resolve-navigation-targets.d.ts.map +1 -0
  196. package/dist/types/src/operations/update-profile.d.ts +5 -0
  197. package/dist/types/src/operations/update-profile.d.ts.map +1 -0
  198. package/dist/types/src/progress/index.d.ts +2 -0
  199. package/dist/types/src/progress/index.d.ts.map +1 -0
  200. package/dist/types/src/progress/progress-keys.d.ts +6 -0
  201. package/dist/types/src/progress/progress-keys.d.ts.map +1 -0
  202. package/dist/types/src/testing/initializeIdentity.d.ts +5 -1
  203. package/dist/types/src/testing/initializeIdentity.d.ts.map +1 -1
  204. package/dist/types/src/translations.d.ts.map +1 -1
  205. package/dist/types/src/types/capabilities.d.ts +10 -1
  206. package/dist/types/src/types/capabilities.d.ts.map +1 -1
  207. package/dist/types/src/types/schema.d.ts +6 -0
  208. package/dist/types/src/types/schema.d.ts.map +1 -1
  209. package/dist/types/tsconfig.tsbuildinfo +1 -1
  210. package/package.json +60 -55
  211. package/src/ClientPlugin.ts +25 -2
  212. package/src/capabilities/app-graph-builder.ts +1 -1
  213. package/src/capabilities/client.ts +26 -0
  214. package/src/capabilities/index.ts +10 -0
  215. package/src/capabilities/layer-specs.ts +64 -2
  216. package/src/capabilities/migrations.ts +9 -1
  217. package/src/capabilities/navigation-handler/navigation-handler.ts +20 -3
  218. package/src/capabilities/navigation-target-loader.ts +70 -0
  219. package/src/capabilities/react-context.tsx +20 -2
  220. package/src/capabilities/{react-surface.tsx → react-surface.ts} +14 -12
  221. package/src/capabilities/remote-trace-monitor.ts +62 -0
  222. package/src/capabilities/space-replication-progress.ts +143 -0
  223. package/src/capabilities/trace-progress.ts +84 -0
  224. package/src/commands/account/login/login.ts +48 -6
  225. package/src/commands/account/logout/logout.ts +4 -0
  226. package/src/commands/halo/index.ts +6 -2
  227. package/src/commands/halo/share/share.ts +16 -5
  228. package/src/commands/profile/create.ts +23 -40
  229. package/src/containers/AccountContainer/AccountContainer.tsx +6 -5
  230. package/src/containers/DevicesContainer/DevicesContainer.tsx +2 -0
  231. package/src/containers/InvitationsContainer/InvitationsContainer.tsx +2 -0
  232. package/src/containers/JoinDialog/JoinDialog.tsx +2 -0
  233. package/src/containers/ProfileContainer/ProfileContainer.tsx +19 -13
  234. package/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.tsx +2 -0
  235. package/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.tsx +7 -9
  236. package/src/containers/ResetDialog/ResetDialog.tsx +2 -0
  237. package/src/containers/UsageContainer/UsageContainer.tsx +10 -1
  238. package/src/containers/UsageContainer/UsageView.stories.tsx +0 -12
  239. package/src/containers/UsageContainer/UsageView.tsx +9 -10
  240. package/src/halo-services-layer.ts +29 -0
  241. package/src/index.ts +9 -0
  242. package/src/operations/definitions.ts +9 -1
  243. package/src/operations/errors.test.ts +27 -0
  244. package/src/operations/errors.ts +47 -0
  245. package/src/operations/index.ts +3 -0
  246. package/src/operations/open-usage.ts +3 -3
  247. package/src/operations/redeem-passkey.ts +85 -55
  248. package/src/operations/resolve-navigation-targets.ts +71 -0
  249. package/src/operations/share-identity.ts +3 -3
  250. package/src/operations/update-profile.ts +20 -0
  251. package/src/progress/index.ts +5 -0
  252. package/src/progress/progress-keys.ts +15 -0
  253. package/src/testing/initializeIdentity.ts +10 -2
  254. package/src/translations.ts +2 -0
  255. package/src/types/capabilities.ts +15 -1
  256. package/src/types/schema.ts +7 -0
  257. package/dist/lib/neutral/AccountContainer-7SF53UON.mjs +0 -186
  258. package/dist/lib/neutral/AccountContainer-7SF53UON.mjs.map +0 -7
  259. package/dist/lib/neutral/ClientPlugin.mjs +0 -72
  260. package/dist/lib/neutral/ClientPlugin.mjs.map +0 -7
  261. package/dist/lib/neutral/ClientPlugin.node.mjs +0 -1156
  262. package/dist/lib/neutral/ClientPlugin.node.mjs.map +0 -7
  263. package/dist/lib/neutral/ClientPlugin.workerd.mjs +0 -16
  264. package/dist/lib/neutral/ClientPlugin.workerd.mjs.map +0 -7
  265. package/dist/lib/neutral/DevicesContainer-PRWIN36N.mjs +0 -271
  266. package/dist/lib/neutral/DevicesContainer-PRWIN36N.mjs.map +0 -7
  267. package/dist/lib/neutral/InvitationsContainer-BI5RAWET.mjs +0 -143
  268. package/dist/lib/neutral/InvitationsContainer-BI5RAWET.mjs.map +0 -7
  269. package/dist/lib/neutral/JoinDialog-4BWV4CYB.mjs +0 -53
  270. package/dist/lib/neutral/JoinDialog-4BWV4CYB.mjs.map +0 -7
  271. package/dist/lib/neutral/ProfileContainer-YEAYOTX5.mjs +0 -169
  272. package/dist/lib/neutral/ProfileContainer-YEAYOTX5.mjs.map +0 -7
  273. package/dist/lib/neutral/RecoveryCodeDialog-7EPNKCLB.mjs +0 -59
  274. package/dist/lib/neutral/RecoveryCodeDialog-7EPNKCLB.mjs.map +0 -7
  275. package/dist/lib/neutral/RecoveryCredentialsContainer-6BZ2IWX7.mjs +0 -60
  276. package/dist/lib/neutral/RecoveryCredentialsContainer-6BZ2IWX7.mjs.map +0 -7
  277. package/dist/lib/neutral/ResetDialog-KUWX45JY.mjs +0 -57
  278. package/dist/lib/neutral/ResetDialog-KUWX45JY.mjs.map +0 -7
  279. package/dist/lib/neutral/UsageContainer-2DWCVVE4.mjs +0 -241
  280. package/dist/lib/neutral/UsageContainer-2DWCVVE4.mjs.map +0 -7
  281. package/dist/lib/neutral/account-cache-YVQKLNV2.mjs.map +0 -7
  282. package/dist/lib/neutral/app-graph-builder-RVXTD6OE.mjs +0 -159
  283. package/dist/lib/neutral/app-graph-builder-RVXTD6OE.mjs.map +0 -7
  284. package/dist/lib/neutral/capabilities/index.mjs +0 -34
  285. package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
  286. package/dist/lib/neutral/capabilities/node.mjs +0 -21
  287. package/dist/lib/neutral/capabilities/node.mjs.map +0 -7
  288. package/dist/lib/neutral/chunk-6G4KZLBG.mjs.map +0 -7
  289. package/dist/lib/neutral/chunk-7DEIKHB7.mjs +0 -199
  290. package/dist/lib/neutral/chunk-7DEIKHB7.mjs.map +0 -7
  291. package/dist/lib/neutral/chunk-A7WDDIWY.mjs +0 -162
  292. package/dist/lib/neutral/chunk-A7WDDIWY.mjs.map +0 -7
  293. package/dist/lib/neutral/chunk-GSKMAS3S.mjs.map +0 -7
  294. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
  295. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
  296. package/dist/lib/neutral/chunk-JY35S2CN.mjs +0 -27
  297. package/dist/lib/neutral/chunk-JY35S2CN.mjs.map +0 -7
  298. package/dist/lib/neutral/chunk-ZFABGG2E.mjs +0 -8
  299. package/dist/lib/neutral/chunk-ZFABGG2E.mjs.map +0 -7
  300. package/dist/lib/neutral/client-7I5Y5SOA.mjs +0 -62
  301. package/dist/lib/neutral/client-7I5Y5SOA.mjs.map +0 -7
  302. package/dist/lib/neutral/components/index.mjs +0 -1
  303. package/dist/lib/neutral/components/index.mjs.map +0 -7
  304. package/dist/lib/neutral/containers/index.mjs +0 -25
  305. package/dist/lib/neutral/containers/index.mjs.map +0 -7
  306. package/dist/lib/neutral/create-agent-6UKJMZS5.mjs +0 -26
  307. package/dist/lib/neutral/create-agent-6UKJMZS5.mjs.map +0 -7
  308. package/dist/lib/neutral/create-identity-ULCRB3YH.mjs +0 -42
  309. package/dist/lib/neutral/create-identity-ULCRB3YH.mjs.map +0 -7
  310. package/dist/lib/neutral/create-passkey-I7VDS3AC.mjs +0 -81
  311. package/dist/lib/neutral/create-passkey-I7VDS3AC.mjs.map +0 -7
  312. package/dist/lib/neutral/create-recovery-code-DH2B6EGP.mjs +0 -36
  313. package/dist/lib/neutral/create-recovery-code-DH2B6EGP.mjs.map +0 -7
  314. package/dist/lib/neutral/hub-http-client-WOJUCDKV.mjs +0 -19
  315. package/dist/lib/neutral/hub-http-client-WOJUCDKV.mjs.map +0 -7
  316. package/dist/lib/neutral/index.mjs +0 -25
  317. package/dist/lib/neutral/index.mjs.map +0 -7
  318. package/dist/lib/neutral/join-identity-PJCHDNLH.mjs +0 -27
  319. package/dist/lib/neutral/join-identity-PJCHDNLH.mjs.map +0 -7
  320. package/dist/lib/neutral/layer-specs-YI7BVWKZ.mjs +0 -59
  321. package/dist/lib/neutral/layer-specs-YI7BVWKZ.mjs.map +0 -7
  322. package/dist/lib/neutral/meta.json +0 -1
  323. package/dist/lib/neutral/meta.mjs +0 -8
  324. package/dist/lib/neutral/meta.mjs.map +0 -7
  325. package/dist/lib/neutral/migrations-7FTW55ER.mjs +0 -23
  326. package/dist/lib/neutral/migrations-7FTW55ER.mjs.map +0 -7
  327. package/dist/lib/neutral/navigation-handler-MQ6MZXLX.mjs +0 -46
  328. package/dist/lib/neutral/navigation-handler-MQ6MZXLX.mjs.map +0 -7
  329. package/dist/lib/neutral/open-usage-OJVTPGOY.mjs +0 -27
  330. package/dist/lib/neutral/open-usage-OJVTPGOY.mjs.map +0 -7
  331. package/dist/lib/neutral/operation-handler-E3HB7E2T.mjs +0 -13
  332. package/dist/lib/neutral/operation-handler-E3HB7E2T.mjs.map +0 -7
  333. package/dist/lib/neutral/operations/index.mjs +0 -12
  334. package/dist/lib/neutral/operations/index.mjs.map +0 -7
  335. package/dist/lib/neutral/plugin.mjs +0 -17
  336. package/dist/lib/neutral/plugin.mjs.map +0 -7
  337. package/dist/lib/neutral/react-context-V74T6JOJ.mjs +0 -23
  338. package/dist/lib/neutral/react-context-V74T6JOJ.mjs.map +0 -7
  339. package/dist/lib/neutral/react-surface-HPXRA65U.mjs +0 -75
  340. package/dist/lib/neutral/react-surface-HPXRA65U.mjs.map +0 -7
  341. package/dist/lib/neutral/recover-identity-B7YM2BR4.mjs +0 -26
  342. package/dist/lib/neutral/recover-identity-B7YM2BR4.mjs.map +0 -7
  343. package/dist/lib/neutral/redeem-passkey-TYP4XLHO.mjs +0 -66
  344. package/dist/lib/neutral/redeem-passkey-TYP4XLHO.mjs.map +0 -7
  345. package/dist/lib/neutral/redeem-token-2J33R3PV.mjs +0 -29
  346. package/dist/lib/neutral/redeem-token-2J33R3PV.mjs.map +0 -7
  347. package/dist/lib/neutral/reset-storage-K47HZTGP.mjs +0 -26
  348. package/dist/lib/neutral/reset-storage-K47HZTGP.mjs.map +0 -7
  349. package/dist/lib/neutral/schema-defs-IHBCKTMM.mjs +0 -51
  350. package/dist/lib/neutral/schema-defs-IHBCKTMM.mjs.map +0 -7
  351. package/dist/lib/neutral/share-identity-TOROBLWL.mjs +0 -31
  352. package/dist/lib/neutral/share-identity-TOROBLWL.mjs.map +0 -7
  353. package/dist/lib/neutral/testing/index.mjs +0 -25
  354. package/dist/lib/neutral/testing/index.mjs.map +0 -7
  355. package/dist/lib/neutral/translations.mjs +0 -124
  356. package/dist/lib/neutral/translations.mjs.map +0 -7
  357. package/dist/lib/neutral/types/index.mjs +0 -16
  358. package/dist/lib/neutral/types/index.mjs.map +0 -7
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import * as Effect from 'effect/Effect';
6
- import React, { type ComponentProps } from 'react';
6
+ import { type ComponentProps } from 'react';
7
7
 
8
8
  import { Capabilities, Capability } from '@dxos/app-framework';
9
9
  import { Surface } from '@dxos/app-framework/ui';
@@ -36,37 +36,39 @@ export default Capability.makeModule(
36
36
  Surface.create({
37
37
  id: Account.Profile,
38
38
  filter: AppSurface.literal(AppSurface.Article, Account.Profile),
39
- component: () => <ProfileContainer />,
39
+ component: ProfileContainer,
40
40
  }),
41
41
  Surface.create({
42
42
  id: Account.Devices,
43
43
  filter: AppSurface.literal(AppSurface.Article, Account.Devices),
44
- component: () => <DevicesContainer createInvitationUrl={createInvitationUrl} />,
44
+ component: DevicesContainer,
45
+ props: () => ({ createInvitationUrl }),
45
46
  }),
46
47
  Surface.create({
47
48
  id: Account.Security,
48
49
  filter: AppSurface.literal(AppSurface.Article, Account.Security),
49
- component: () => <RecoveryCredentialsContainer />,
50
+ component: RecoveryCredentialsContainer,
50
51
  }),
51
52
  Surface.create({
52
53
  id: Account.Account,
53
54
  filter: AppSurface.literal(AppSurface.Article, Account.Account),
54
- component: () => <AccountContainer />,
55
+ component: AccountContainer,
55
56
  }),
56
57
  Surface.create({
57
58
  id: Account.Invitations,
58
59
  filter: AppSurface.literal(AppSurface.Article, Account.Invitations),
59
- component: () => <InvitationsContainer />,
60
+ component: InvitationsContainer,
60
61
  }),
61
62
  Surface.create({
62
63
  id: Account.Usage,
63
64
  filter: AppSurface.literal(AppSurface.Article, Account.Usage),
64
- component: () => <UsageContainer />,
65
+ component: UsageContainer,
65
66
  }),
66
67
  Surface.create({
67
68
  id: JOIN_DIALOG,
68
69
  filter: AppSurface.component<ComponentProps<typeof JoinDialog>>(AppSurface.Dialog, JOIN_DIALOG),
69
- component: ({ data }) => <JoinDialog {...data.props} />,
70
+ component: JoinDialog,
71
+ props: ({ data: { props } }) => ({ ...props }),
70
72
  }),
71
73
  Surface.create({
72
74
  id: RECOVERY_CODE_DIALOG,
@@ -74,14 +76,14 @@ export default Capability.makeModule(
74
76
  AppSurface.Dialog,
75
77
  RECOVERY_CODE_DIALOG,
76
78
  ),
77
- component: ({ data }) => <RecoveryCodeDialog {...data.props} />,
79
+ component: RecoveryCodeDialog,
80
+ props: ({ data: { props } }) => ({ ...props }),
78
81
  }),
79
82
  Surface.create({
80
83
  id: RESET_DIALOG,
81
84
  filter: AppSurface.component<Pick<ComponentProps<typeof ResetDialog>, 'mode'>>(AppSurface.Dialog, RESET_DIALOG),
82
- component: ({ data }) => (
83
- <ResetDialog {...data.props} onReset={onReset} capabilityManager={capabilityManager} />
84
- ),
85
+ component: ResetDialog,
86
+ props: ({ data: { props } }) => ({ ...props, onReset, capabilityManager }),
85
87
  }),
86
88
  ]);
87
89
  }),
@@ -0,0 +1,62 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Option from 'effect/Option';
7
+ import * as Stream from 'effect/Stream';
8
+
9
+ import { Capabilities, Capability } from '@dxos/app-framework';
10
+ import { RemoteTraceMonitor } from '@dxos/compute-runtime';
11
+
12
+ import { ClientCapabilities } from '#types';
13
+
14
+ /**
15
+ * Contributes a swarm-backed {@link Capabilities.RemoteTraceMonitor} (DX-1125). Remote runtimes
16
+ * (edge intrinsics / function-invoker) broadcast their ephemeral trace messages over the space swarm;
17
+ * this monitor subscribes via the client's network service and decodes them so the aggregate
18
+ * {@link Process.Monitor.subscribeToTraceMessages} surfaces remote progress.
19
+ *
20
+ * The client is resolved lazily inside the subscribe closure (invoked only when a consumer
21
+ * subscribes, well after `ClientReady`), so this module can be collected at `SetupProcessManager`
22
+ * before the client capability exists.
23
+ */
24
+ export default Capability.makeModule(
25
+ Effect.fnUntraced(function* () {
26
+ const capabilityManager = yield* Capability.Service;
27
+
28
+ const monitor = RemoteTraceMonitor.createSwarmRemoteTraceMonitor({
29
+ subscribe: (tags) =>
30
+ // Empty tag set matches nothing (avoids a firehose) — skip the subscription entirely.
31
+ tags.length === 0
32
+ ? Stream.empty
33
+ : Stream.unwrap(
34
+ Effect.sync(() => {
35
+ const client = capabilityManager.getAll(ClientCapabilities.Client)[0];
36
+ if (!client) {
37
+ return Stream.empty;
38
+ }
39
+ // The subscribing peer is nominal for broadcasts: the edge keys the subscription off
40
+ // the WebSocket connection, not this object; it only affects point-to-point filtering.
41
+ const peer = {
42
+ peerKey:
43
+ client.halo.device?.deviceKey.toHex() ?? client.halo.identity.get()?.identityKey.toHex() ?? '',
44
+ };
45
+ return client.services.rpc.NetworkService.subscribeMessages({ peer, tags }).pipe(
46
+ // Carry the envelope tags with the payload — the wire payload drops ref meta
47
+ // (`trigger`), and decode restores it from the tags for cancel addressing.
48
+ Stream.filterMap((message) =>
49
+ message.payload?.value
50
+ ? Option.some({ payload: message.payload.value, tags: message.tags })
51
+ : Option.none(),
52
+ ),
53
+ // Never fail the aggregate monitor stream on a transient network error.
54
+ Stream.catchAll(() => Stream.empty),
55
+ );
56
+ }),
57
+ ),
58
+ });
59
+
60
+ return Capability.contributes(Capabilities.RemoteTraceMonitor, monitor);
61
+ }),
62
+ );
@@ -0,0 +1,143 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Fiber from 'effect/Fiber';
7
+ import * as Scope from 'effect/Scope';
8
+ import * as Stream from 'effect/Stream';
9
+
10
+ import { Capabilities, Capability } from '@dxos/app-framework';
11
+ import { AppCapabilities } from '@dxos/app-toolkit';
12
+ import { type Space, SpaceState } from '@dxos/client/echo';
13
+ import { ServiceResolver } from '@dxos/compute';
14
+ import { Database } from '@dxos/echo';
15
+
16
+ import { ClientCapabilities } from '#types';
17
+
18
+ import { createSpaceFeedReplicationProgressKey, createSpaceReplicationProgressKey } from '../progress';
19
+
20
+ type MonitorUpdate = {
21
+ readonly label: string;
22
+ readonly current: number;
23
+ readonly total: number;
24
+ readonly note?: string;
25
+ };
26
+
27
+ /**
28
+ * Publishes per-space replication backlog — automerge documents and ECHO feed blocks — into the
29
+ * {@link AppCapabilities.ProgressRegistry}. Subscribes to the combined sync-state stream and drops
30
+ * monitors once a space catches up.
31
+ */
32
+ export default Capability.makeModule(
33
+ Effect.fnUntraced(function* () {
34
+ const client = yield* Capability.get(ClientCapabilities.Client);
35
+ const registry = yield* Capability.get(AppCapabilities.ProgressRegistry);
36
+ const processManagerRuntime = yield* Capability.get(Capabilities.ProcessManagerRuntime);
37
+
38
+ const monitors = new Map<string, AppCapabilities.ProgressMonitor>();
39
+
40
+ yield* Effect.addFinalizer(() =>
41
+ Effect.sync(() => {
42
+ for (const monitor of monitors.values()) {
43
+ monitor.remove();
44
+ }
45
+ monitors.clear();
46
+ }),
47
+ );
48
+
49
+ const applyMonitor = (key: string, update: MonitorUpdate | undefined): void => {
50
+ if (update === undefined) {
51
+ monitors.get(key)?.remove();
52
+ monitors.delete(key);
53
+ return;
54
+ }
55
+
56
+ let monitor = monitors.get(key);
57
+ if (!monitor) {
58
+ monitor = registry.register(key, { label: update.label, total: update.total });
59
+ monitors.set(key, monitor);
60
+ }
61
+ monitor.set(update.current);
62
+ monitor.total(update.total);
63
+ if (update.note !== undefined) {
64
+ monitor.note(update.note);
65
+ }
66
+ };
67
+
68
+ // A space that has not finished initializing throws from its `properties` getter, and the
69
+ // spaces subscription fires before initialization completes (startup, space creation) — so
70
+ // the name is read lazily per sync-state update, and only once the space is SPACE_READY.
71
+ const getSpaceName = (space: Space): string | undefined =>
72
+ space.state.get() === SpaceState.SPACE_READY ? space.properties.name : undefined;
73
+
74
+ const runtime = yield* Effect.runtime<Scope.Scope>();
75
+ const subscribeSpace = (space: Space): void =>
76
+ void Effect.gen(function* () {
77
+ const fiber = processManagerRuntime.runFork(
78
+ Database.subscribeToSyncState().pipe(
79
+ Stream.runForEach(
80
+ Effect.fnUntraced(function* (state) {
81
+ const name = getSpaceName(space);
82
+ applyMonitor(createSpaceReplicationProgressKey(space.id), toDocumentUpdate(name, state));
83
+ applyMonitor(createSpaceFeedReplicationProgressKey(space.id), toFeedUpdate(name, state));
84
+ }),
85
+ ),
86
+ Effect.provide(ServiceResolver.provide({ space: space.id }, Database.Service)),
87
+ ),
88
+ );
89
+
90
+ yield* Effect.addFinalizer(() => Fiber.interrupt(fiber));
91
+ }).pipe(Effect.provide(runtime), Effect.runFork);
92
+
93
+ const spacesSubscription = client.spaces.subscribe((spaces) => {
94
+ for (const space of spaces) {
95
+ subscribeSpace(space);
96
+ }
97
+ });
98
+ yield* Effect.addFinalizer(() => Effect.sync(() => spacesSubscription.unsubscribe()));
99
+ for (const space of client.spaces.get()) {
100
+ subscribeSpace(space);
101
+ }
102
+ }),
103
+ );
104
+
105
+ /** Derives the automerge document monitor state, or `undefined` when caught up. */
106
+ const toDocumentUpdate = (name: string | undefined, state: Database.SyncState): MonitorUpdate | undefined => {
107
+ const unsynced = state.unsyncedDocumentCount;
108
+ if (unsynced === 0) {
109
+ return undefined;
110
+ }
111
+
112
+ const total = state.totalDocumentCount > 0 ? state.totalDocumentCount : unsynced;
113
+ return {
114
+ label: getSpaceProgressLabel(name ?? 'Space', 'CRDTs'),
115
+ current: Math.max(0, total - unsynced),
116
+ total,
117
+ };
118
+ };
119
+
120
+ /** Derives the ECHO feed block monitor state, or `undefined` when caught up. */
121
+ const toFeedUpdate = (name: string | undefined, state: Database.SyncState): MonitorUpdate | undefined => {
122
+ const blocksToPull = Number(state.blocksToPull);
123
+ const blocksToPush = Number(state.blocksToPush);
124
+ const pending = blocksToPull + blocksToPush;
125
+ if (pending === 0) {
126
+ return undefined;
127
+ }
128
+
129
+ const totalBlocks = Number(state.totalBlocks);
130
+ const total = totalBlocks > 0 ? totalBlocks : pending;
131
+ return {
132
+ label: getSpaceProgressLabel(name ?? 'Space', 'Feeds'),
133
+ current: Math.max(0, total - pending),
134
+ total,
135
+ note: `↓${blocksToPull} ↑${blocksToPush}`,
136
+ };
137
+ };
138
+
139
+ /** Human label for a space progress monitor. */
140
+ const getSpaceProgressLabel = (name: string | undefined, suffix?: string): string => {
141
+ const name_ = name ?? 'Space';
142
+ return suffix ? `${name_} · ${suffix}` : name_;
143
+ };
@@ -0,0 +1,84 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Fiber from 'effect/Fiber';
7
+ import * as Stream from 'effect/Stream';
8
+
9
+ import { Capabilities, Capability } from '@dxos/app-framework';
10
+ import { AppCapabilities, type CancelTarget, createProgressTraceSink, resolveTriggerId } from '@dxos/app-toolkit';
11
+ import { Trace } from '@dxos/compute';
12
+ import { RemoteProcessManager } from '@dxos/compute-runtime';
13
+ import { log } from '@dxos/log';
14
+
15
+ /**
16
+ * Projects remote (edge-runtime) `status.update` trace events into the {@link AppCapabilities.ProgressRegistry}
17
+ * (DX-1125). Subscribes to the aggregate {@link Process.Monitor.subscribeToTraceMessages}, whose remote
18
+ * source is the swarm-backed monitor contributed by `remote-trace-monitor`.
19
+ *
20
+ * Only edge-runtime messages are projected here: local progress already flows through the
21
+ * `plugin-progress` trace sink, and both write the same progress keys — projecting local messages
22
+ * twice would let two writers clobber each other's registry handles.
23
+ *
24
+ * Cancel on this path always routes to {@link RemoteProcessManager} (edge) — local terminate is
25
+ * handled by the `plugin-progress` sink, which never sees these messages.
26
+ */
27
+ export default Capability.makeModule(
28
+ Effect.fnUntraced(function* () {
29
+ const capabilityManager = yield* Capability.Service;
30
+ const monitor = yield* Capability.get(Capabilities.ProcessMonitor);
31
+ const processManagerRuntime = yield* Capability.get(Capabilities.ProcessManagerRuntime);
32
+ const resolver = yield* Capability.get(Capabilities.ServiceResolver);
33
+
34
+ // Edge-only cancel. Soft-fails (the meter has already cleared locally), but never silently: an
35
+ // unresolvable manager or a rejected request means the run may still be going on the edge.
36
+ const cancelRemote = (space: string, trigger: string, pid?: string) =>
37
+ Effect.runFork(
38
+ resolver.resolve(RemoteProcessManager.Service, {}).pipe(
39
+ Effect.flatMap((manager) => manager.cancel?.({ space, trigger, pid }) ?? Effect.void),
40
+ Effect.scoped,
41
+ Effect.catchAllCause((cause) =>
42
+ Effect.sync(() => log.warn('edge progress cancel failed', { space, trigger, pid, cause })),
43
+ ),
44
+ ),
45
+ );
46
+
47
+ const progressSink = createProgressTraceSink(() => capabilityManager.getAll(AppCapabilities.ProgressRegistry)[0], {
48
+ // An edge run is a chain of bounded invocations, each with a fresh pid, so a pid tombstone
49
+ // would only mask one chain link and the next would resurrect the meter — suppress the key
50
+ // until the run's terminal status, matching the local (single-pid) cancel behaviour.
51
+ cancelScope: 'run',
52
+ cancelProcess: (target: CancelTarget) => {
53
+ const triggerId = resolveTriggerId(target);
54
+ if (target.space && triggerId) {
55
+ cancelRemote(target.space, triggerId, target.pid);
56
+ } else {
57
+ // Never drop a user's cancel silently — an unresolvable target means the trace meta lost
58
+ // its addressing (e.g. the swarm wire codec), which must surface in the log.
59
+ log.warn('edge progress cancel dropped: unresolvable target', {
60
+ space: target.space,
61
+ trigger: target.trigger?.uri.toString(),
62
+ pid: target.pid,
63
+ });
64
+ }
65
+ },
66
+ });
67
+
68
+ // TODO(mykola): Possible bug source. Use `Effect.forkDaemon`.
69
+ const fiber = processManagerRuntime.runFork(
70
+ monitor.subscribeToTraceMessages({ type: Trace.StatusUpdate.key }).pipe(
71
+ Stream.runForEach((message) =>
72
+ Effect.sync(() => {
73
+ const runtimeName = message.meta.runtimeName;
74
+ if (runtimeName && Trace.isEdgeRuntime(runtimeName)) {
75
+ progressSink.write(message);
76
+ }
77
+ }),
78
+ ),
79
+ ),
80
+ );
81
+
82
+ yield* Effect.addFinalizer(() => Fiber.interrupt(fiber));
83
+ }),
84
+ );
@@ -11,6 +11,7 @@ import * as Effect from 'effect/Effect';
11
11
  import * as Match from 'effect/Match';
12
12
  import * as Option from 'effect/Option';
13
13
 
14
+ import { Capabilities, Plugin } from '@dxos/app-framework';
14
15
  import { CommandConfig, performRecoveryOAuthFlow, print } from '@dxos/cli-util';
15
16
  import { type Client, ClientService } from '@dxos/client';
16
17
  import { Invitation, InvitationEncoder } from '@dxos/client/invitations';
@@ -19,6 +20,8 @@ import { HubHttpClient } from '@dxos/edge-client';
19
20
  import { invariant } from '@dxos/invariant';
20
21
  import { ATPROTO_OAUTH_SCOPES, OAuthProvider } from '@dxos/protocols';
21
22
 
23
+ import { ClientOperation } from '#operations';
24
+
22
25
  import { printIdentity, waitForState } from '../../halo/util';
23
26
 
24
27
  type LoginMethod = 'email' | 'atproto' | 'device-invitation' | 'recovery-code';
@@ -56,6 +59,8 @@ export const login = Command.make(
56
59
  Effect.fn(function* ({ method, input }) {
57
60
  const { json } = yield* CommandConfig;
58
61
  const client = yield* ClientService;
62
+ const manager = yield* Plugin.Service;
63
+ const { invoke } = manager.capabilities.get(Capabilities.OperationInvoker);
59
64
  // TODO(wittjosiah): How to surface this error to the user cleanly?
60
65
  invariant(!client.halo.identity.get(), 'Already logged in. Run `dx account logout` first.');
61
66
 
@@ -69,7 +74,7 @@ export const login = Command.make(
69
74
 
70
75
  const identity = yield* Match.value(resolvedMethod).pipe(
71
76
  Match.when('atproto', () => loginWithAtproto(client, resolvedInput)),
72
- Match.when('email', () => loginWithEmail(client, resolvedInput)),
77
+ Match.when('email', () => loginWithEmail(client, resolvedInput, invoke)),
73
78
  Match.when('recovery-code', () => loginWithRecoveryCode(client, resolvedInput)),
74
79
  Match.when('device-invitation', () => loginWithDeviceInvitation(client, resolvedInput)),
75
80
  Match.exhaustive,
@@ -108,16 +113,53 @@ const loginWithRecoveryCode = (client: Client, recoveryCode: string) =>
108
113
  Effect.tryPromise(() => client.halo.recoverIdentity({ recoveryCode }));
109
114
 
110
115
  /**
111
- * Email login: hub-service inlines a one-time `token` for test emails and emails it out-of-band
112
- * otherwise. Redeems the token to admit this device into HALO.
116
+ * Email login, mirroring the gate's login tab (`WelcomeScreen.handleLogin`). Hub-service answers in
117
+ * one of three ways:
118
+ *
119
+ * - `needsIdentity`: the address may bind a fresh Account but has no identity yet. Create one
120
+ * locally and retry with its DID; the hub then admits it directly — there is no token because
121
+ * there is nothing to recover — and we provision the agent as the gate does.
122
+ * - `token`: an Account exists and the hub returned a one-time recovery token inline.
123
+ * - neither: the link went out by email, so prompt for the token from the message.
113
124
  */
114
- const loginWithEmail = (client: Client, email: string) =>
125
+ const loginWithEmail = (client: Client, email: string, invoke: Capabilities.OperationInvoker['invoke']) =>
115
126
  Effect.gen(function* () {
116
127
  const hubUrl = client.config.values?.runtime?.app?.env?.DX_HUB_URL;
117
128
  invariant(hubUrl, 'Hub URL not configured (runtime.app.env.DX_HUB_URL).');
118
129
  const hub = new HubHttpClient(hubUrl);
119
- const { token: inlineToken } = yield* Effect.tryPromise(() => hub.login(DxContext.default(), { email }));
120
- let token = inlineToken;
130
+ const result = yield* Effect.tryPromise(() => hub.login(DxContext.default(), { email }));
131
+
132
+ if (result.needsIdentity) {
133
+ // `CreateIdentity` fires `IdentityCreated`, which is what provisions the personal space.
134
+ yield* invoke(ClientOperation.CreateIdentity, { displayName: email.split('@')[0] });
135
+ const identity = client.halo.identity.get();
136
+ invariant(identity, 'identity should exist after create');
137
+ // The local identity outlives any failure from here on, and the `Already logged in` guard
138
+ // above rejects a plain retry, so a rejected request and a non-admitting response both need
139
+ // the same recovery guidance.
140
+ const notAdmitted = (detail: string) =>
141
+ new Error(
142
+ `Hub did not admit ${email} (${detail}). A local identity was created and remains bound to ` +
143
+ 'this profile; run `dx account logout` to clear it before retrying.',
144
+ );
145
+
146
+ const retry = yield* Effect.tryPromise({
147
+ try: () =>
148
+ hub.login(DxContext.default(), {
149
+ email,
150
+ identityDid: identity.did,
151
+ identityKey: identity.identityKey.toHex(),
152
+ }),
153
+ catch: (cause) => notAdmitted(cause instanceof Error ? cause.message : String(cause)),
154
+ });
155
+ if (!retry.admitted) {
156
+ return yield* Effect.fail(notAdmitted('no admission granted'));
157
+ }
158
+ yield* invoke(ClientOperation.CreateAgent);
159
+ return identity;
160
+ }
161
+
162
+ let token = result.token;
121
163
  if (!token) {
122
164
  yield* Console.log(`A login link was sent to ${email}. Paste the token from the email below.`);
123
165
  token = yield* Prompt.text({ message: 'Login token' }).pipe(Prompt.run);
@@ -40,6 +40,10 @@ export const logout = Command.make(
40
40
  () => Effect.void,
41
41
  ),
42
42
  );
43
+ // Recreate the (now empty) data root: the client's SQLite storage opens a file inside it
44
+ // without creating the directory first, so leaving it absent makes every later command fail
45
+ // with "unable to open database file" — including the login this logout exists to enable.
46
+ yield* fs.makeDirectory(path, { recursive: true });
43
47
  if (json) {
44
48
  yield* Console.log(JSON.stringify({ profile, loggedOut: true }, null, 2));
45
49
  } else {
@@ -4,18 +4,22 @@
4
4
 
5
5
  import * as Command from '@effect/cli/Command';
6
6
 
7
+ import { create } from './create';
7
8
  import { credential } from './credential';
8
9
  import { identity } from './identity';
9
10
  import { keys } from './keys';
10
11
  import { seed } from './seed';
12
+ import { share } from './share';
11
13
  import { update } from './update';
12
14
 
13
15
  // `create`, `join`, and `recover` are superseded by `dx account login`, which logs in to an
14
16
  // existing identity via the same methods as Composer (email / atproto / device-invitation /
15
17
  // recovery-code). Note: `join` was omitted and the `device-invitation` login method may hang —
16
- // both rely on p2p networking which does not work in bun.
18
+ // both rely on p2p networking which does not work in bun. `create` and `share` are registered
19
+ // for the CLI-first pairing flow (CLI hosts the device invitation; the browser joins), which
20
+ // runs over the edge messenger rather than raw p2p.
17
21
 
18
22
  export const halo: Command.Command<any, any, any, any> = Command.make('halo').pipe(
19
23
  Command.withDescription('Manage HALO identity.'),
20
- Command.withSubcommands([credential, identity, keys, seed, update]),
24
+ Command.withSubcommands([create, credential, identity, keys, seed, share, update]),
21
25
  );
@@ -24,6 +24,13 @@ export const handler = Effect.fn(function* ({
24
24
  const { json } = yield* CommandConfig;
25
25
  const client = yield* ClientService;
26
26
 
27
+ // Validate up front — an invalid host inside `onConnecting` would abort after the invitation
28
+ // is already hosted, without printing the codes.
29
+ yield* Effect.try({
30
+ try: () => new URL(host),
31
+ catch: () => new Error(`--host must be an absolute URL: ${host}`),
32
+ });
33
+
27
34
  // Always use persistent and delegated (auth required) due to P2P limitations
28
35
  const observable = client.halo.share({
29
36
  authMethod: Invitation.AuthMethod.SHARED_SECRET,
@@ -42,16 +49,20 @@ export const handler = Effect.fn(function* ({
42
49
  // Copy auth code to clipboard
43
50
  yield* copyToClipboard(authCode).pipe(Effect.catchAll(() => Effect.void));
44
51
 
52
+ const url = new URL(host);
53
+ url.searchParams.set('deviceInvitationCode', invitationCode);
54
+
45
55
  if (!json) {
46
56
  yield* Console.log(`\nSecret: ${authCode} (copied to clipboard)\n`);
57
+ yield* Console.log(`\nInvitation: ${invitationCode}\n`);
58
+ // Print the joinable URL even when not opening so it can be pasted manually.
59
+ yield* Console.log(`\nURL: ${url.toString()}\n`);
47
60
  }
48
61
 
49
62
  if (open) {
50
- const url = new URL(host);
51
- url.searchParams.append('deviceInvitationCode', invitationCode);
52
- yield* openBrowser(url.toString()).pipe(Effect.catchAll(() => Effect.void));
53
- } else if (!json) {
54
- yield* Console.log(`\nInvitation: ${invitationCode}\n`);
63
+ yield* openBrowser(url.toString()).pipe(
64
+ Effect.catchAll(() => Console.error(`Failed to open browser: ${url.toString()}`)),
65
+ );
55
66
  }
56
67
  }),
57
68
  },
@@ -17,47 +17,30 @@ import { trim } from '@dxos/util';
17
17
 
18
18
  import { printProfileCreated } from './util';
19
19
 
20
+ // `edgeFeatures` must match Composer's defaults (see composer-app/dx.yml): without
21
+ // `signaling: true` the client silently falls back to an isolated in-memory signal manager and
22
+ // device invitations hang at "Connecting…" (host and guest never meet in the swarm).
23
+ const makeTemplate = (edgeUrl: string) => trim`
24
+ version: 1
25
+ runtime:
26
+ client:
27
+ storage:
28
+ persistent: true
29
+ edgeFeatures:
30
+ signaling: true
31
+ subductionReplicator: true
32
+ feedReplicator: true
33
+ agents: true
34
+ services:
35
+ edge:
36
+ url: ${edgeUrl}
37
+ `;
38
+
20
39
  const TEMPLATES = {
21
- default: trim`
22
- version: 1
23
- runtime:
24
- client:
25
- storage:
26
- persistent: true
27
- services:
28
- edge:
29
- url: https://edge-production.dxos.workers.dev
30
- `,
31
- main: trim`
32
- version: 1
33
- runtime:
34
- client:
35
- storage:
36
- persistent: true
37
- services:
38
- edge:
39
- url: https://edge-main.dxos.workers.dev
40
- `,
41
- dev: trim`
42
- version: 1
43
- runtime:
44
- client:
45
- storage:
46
- persistent: true
47
- services:
48
- edge:
49
- url: https://edge.dxos.workers.dev
50
- `,
51
- local: trim`
52
- version: 1
53
- runtime:
54
- client:
55
- storage:
56
- persistent: true
57
- services:
58
- edge:
59
- url: http://localhost:8787
60
- `,
40
+ default: makeTemplate('https://edge-production.dxos.workers.dev'),
41
+ main: makeTemplate('https://edge-main.dxos.workers.dev'),
42
+ dev: makeTemplate('https://edge.dxos.workers.dev'),
43
+ local: makeTemplate('http://localhost:8787'),
61
44
  } as const;
62
45
 
63
46
  export const create = Command.make(
@@ -8,8 +8,7 @@ import React, { type FormEvent, useCallback, useState } from 'react';
8
8
  import { useCapability, useOperationInvoker } from '@dxos/app-framework/ui';
9
9
  import { LayoutOperation } from '@dxos/app-toolkit';
10
10
  import { Context } from '@dxos/context';
11
- import { createDidFromIdentityKey } from '@dxos/credentials';
12
- import { useIdentity } from '@dxos/react-client/halo';
11
+ import { useIdentity } from '@dxos/halo-react';
13
12
  import { Button, Icon, IconButton, Input, Message, useAsyncEffect, useTranslation } from '@dxos/react-ui';
14
13
  import { Form } from '@dxos/react-ui-form';
15
14
 
@@ -81,7 +80,7 @@ export const AccountContainer = () => {
81
80
  return;
82
81
  }
83
82
  try {
84
- const identityDid = identity ? await createDidFromIdentityKey(identity.identityKey) : undefined;
83
+ const identityDid = identity?.did;
85
84
  await hubHttp.requestAccess(new Context(), { email, identityDid });
86
85
  } catch {
87
86
  // Surface a generic confirmation; failure details would leak signal.
@@ -122,7 +121,7 @@ export const AccountContainer = () => {
122
121
  <>
123
122
  <Message.Root valence='warning'>
124
123
  <Message.Title icon='ph--warning--duotone'>{t('no-edge-access.title')}</Message.Title>
125
- <Message.Content>{t('no-edge-access.description')}</Message.Content>
124
+ <Message.Body>{t('no-edge-access.description')}</Message.Body>
126
125
  </Message.Root>
127
126
  <Form.Row label={t('request-access.label')} description={t('request-access.description')}>
128
127
  {requestSubmitted ? (
@@ -149,7 +148,7 @@ export const AccountContainer = () => {
149
148
  ) : accountState === 'error' && !account ? (
150
149
  <Message.Root valence='error'>
151
150
  <Message.Title icon='ph--cloud-x--duotone'>{t('account-offline.title')}</Message.Title>
152
- <Message.Content>{t('account-offline.description')}</Message.Content>
151
+ <Message.Body>{t('account-offline.description')}</Message.Body>
153
152
  </Message.Root>
154
153
  ) : account ? (
155
154
  <>
@@ -181,3 +180,5 @@ export const AccountContainer = () => {
181
180
  </Form.Root>
182
181
  );
183
182
  };
183
+
184
+ AccountContainer.displayName = 'AccountContainer';
@@ -293,3 +293,5 @@ const InvitationComplete = ({ statusValue }: { statusValue: number }) => {
293
293
  <Icon icon='ph--x--regular' size={6} classNames='m-1.5' />
294
294
  );
295
295
  };
296
+
297
+ DevicesContainer.displayName = 'DevicesContainer';
@@ -138,3 +138,5 @@ const RedeemedInvitationItem = ({ row }: { row: AccountCacheInvitation }) => {
138
138
  </Listbox.Item>
139
139
  );
140
140
  };
141
+
142
+ InvitationsContainer.displayName = 'InvitationsContainer';
@@ -54,3 +54,5 @@ export const JoinDialog = (props: JoinPanelProps) => {
54
54
  </Dialog.Content>
55
55
  );
56
56
  };
57
+
58
+ JoinDialog.displayName = 'JoinDialog';