@dxos/plugin-client 0.12.0-next-73daef452f1464b62efdbca75fb0067c1066f264 → 0.13.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 (580) hide show
  1. package/dist/lib/Account.mjs +29 -10
  2. package/dist/lib/Account.mjs.map +1 -1
  3. package/dist/lib/CliLogin.mjs +78 -0
  4. package/dist/lib/CliLogin.mjs.map +1 -0
  5. package/dist/lib/ClientCapabilities.mjs +25 -1
  6. package/dist/lib/ClientCapabilities.mjs.map +1 -1
  7. package/dist/lib/ClientEvents.mjs +7 -3
  8. package/dist/lib/ClientEvents.mjs.map +1 -1
  9. package/dist/lib/{chunk-definitions.mjs → ClientOperation.mjs} +11 -7
  10. package/dist/lib/ClientOperation.mjs.map +1 -0
  11. package/dist/lib/ClientOptions.mjs.map +1 -1
  12. package/dist/lib/PasskeyError.mjs +69 -12
  13. package/dist/lib/PasskeyError.mjs.map +1 -1
  14. package/dist/lib/capabilities.browser.mjs +134 -0
  15. package/dist/lib/capabilities.browser.mjs.map +1 -0
  16. package/dist/lib/capabilities.mjs +47 -10
  17. package/dist/lib/capabilities.mjs.map +1 -1
  18. package/dist/lib/capabilities.node.mjs +40 -7
  19. package/dist/lib/capabilities.node.mjs.map +1 -1
  20. package/dist/lib/capabilities.tauri.mjs +134 -0
  21. package/dist/lib/capabilities.tauri.mjs.map +1 -0
  22. package/dist/lib/capabilities.workerd.mjs +24 -4
  23. package/dist/lib/capabilities.workerd.mjs.map +1 -1
  24. package/dist/lib/chunk-AccountContainer.mjs +53 -41
  25. package/dist/lib/chunk-AccountContainer.mjs.map +1 -1
  26. package/dist/lib/chunk-CliLoginDialog.mjs +146 -0
  27. package/dist/lib/chunk-CliLoginDialog.mjs.map +1 -0
  28. package/dist/lib/chunk-ContactPickerContainer.mjs +120 -0
  29. package/dist/lib/chunk-ContactPickerContainer.mjs.map +1 -0
  30. package/dist/lib/chunk-ContactsContainer.mjs +53 -0
  31. package/dist/lib/chunk-ContactsContainer.mjs.map +1 -0
  32. package/dist/lib/chunk-DevicesContainer.mjs +48 -112
  33. package/dist/lib/chunk-DevicesContainer.mjs.map +1 -1
  34. package/dist/lib/chunk-HaloServices.mjs +28 -0
  35. package/dist/lib/chunk-HaloServices.mjs.map +1 -0
  36. package/dist/lib/chunk-InvitationsContainer.mjs +61 -39
  37. package/dist/lib/chunk-InvitationsContainer.mjs.map +1 -1
  38. package/dist/lib/chunk-JoinDialog.mjs +10 -9
  39. package/dist/lib/chunk-JoinDialog.mjs.map +1 -1
  40. package/dist/lib/chunk-ProfileContainer.mjs +60 -39
  41. package/dist/lib/chunk-ProfileContainer.mjs.map +1 -1
  42. package/dist/lib/chunk-RecoveryCodeDialog.mjs +26 -21
  43. package/dist/lib/chunk-RecoveryCodeDialog.mjs.map +1 -1
  44. package/dist/lib/chunk-RecoveryCredentialsContainer.mjs +95 -65
  45. package/dist/lib/chunk-RecoveryCredentialsContainer.mjs.map +1 -1
  46. package/dist/lib/chunk-ResetDialog.mjs +26 -14
  47. package/dist/lib/chunk-ResetDialog.mjs.map +1 -1
  48. package/dist/lib/chunk-SpaceInvitationContainer.mjs +50 -0
  49. package/dist/lib/chunk-SpaceInvitationContainer.mjs.map +1 -0
  50. package/dist/lib/chunk-UsageContainer.mjs +22 -20
  51. package/dist/lib/chunk-UsageContainer.mjs.map +1 -1
  52. package/dist/lib/chunk-account-cache.mjs +2 -2
  53. package/dist/lib/chunk-account-cache.mjs.map +1 -1
  54. package/dist/lib/chunk-app-graph-builder.mjs +159 -60
  55. package/dist/lib/chunk-app-graph-builder.mjs.map +1 -1
  56. package/dist/lib/chunk-client-services.mjs +21 -0
  57. package/dist/lib/chunk-client-services.mjs.map +1 -0
  58. package/dist/lib/chunk-client.mjs +27 -20
  59. package/dist/lib/chunk-client.mjs.map +1 -1
  60. package/dist/lib/chunk-constants.mjs +2 -1
  61. package/dist/lib/chunk-constants.mjs.map +1 -1
  62. package/dist/lib/chunk-create-agent.mjs +1 -1
  63. package/dist/lib/chunk-create-agent.mjs.map +1 -1
  64. package/dist/lib/chunk-create-identity.mjs +2 -2
  65. package/dist/lib/chunk-create-identity.mjs.map +1 -1
  66. package/dist/lib/chunk-create-passkey.mjs +49 -40
  67. package/dist/lib/chunk-create-passkey.mjs.map +1 -1
  68. package/dist/lib/chunk-create-recovery-code.mjs +2 -2
  69. package/dist/lib/chunk-create-recovery-code.mjs.map +1 -1
  70. package/dist/lib/chunk-grant-service-access.mjs +1 -1
  71. package/dist/lib/chunk-grant-service-access.mjs.map +1 -1
  72. package/dist/lib/chunk-halo.mjs +414 -0
  73. package/dist/lib/chunk-halo.mjs.map +1 -0
  74. package/dist/lib/chunk-identity-lifecycle.mjs +74 -0
  75. package/dist/lib/chunk-identity-lifecycle.mjs.map +1 -0
  76. package/dist/lib/chunk-join-identity.mjs +2 -2
  77. package/dist/lib/chunk-join-identity.mjs.map +1 -1
  78. package/dist/lib/chunk-layer-specs.mjs +72 -5
  79. package/dist/lib/chunk-layer-specs.mjs.map +1 -1
  80. package/dist/lib/chunk-navigation-handler.mjs +28 -5
  81. package/dist/lib/chunk-navigation-handler.mjs.map +1 -1
  82. package/dist/lib/chunk-navigation-target-loader.mjs +8 -9
  83. package/dist/lib/chunk-navigation-target-loader.mjs.map +1 -1
  84. package/dist/lib/chunk-open-usage.mjs +3 -3
  85. package/dist/lib/chunk-open-usage.mjs.map +1 -1
  86. package/dist/lib/chunk-react-context.mjs +5 -5
  87. package/dist/lib/chunk-react-context.mjs.map +1 -1
  88. package/dist/lib/chunk-react-surface.mjs +80 -64
  89. package/dist/lib/chunk-react-surface.mjs.map +1 -1
  90. package/dist/lib/chunk-recover-identity.mjs +2 -2
  91. package/dist/lib/chunk-recover-identity.mjs.map +1 -1
  92. package/dist/lib/chunk-redeem-passkey.mjs +7 -5
  93. package/dist/lib/chunk-redeem-passkey.mjs.map +1 -1
  94. package/dist/lib/chunk-redeem-token.mjs +1 -1
  95. package/dist/lib/chunk-redeem-token.mjs.map +1 -1
  96. package/dist/lib/chunk-remote-trace-monitor.mjs +3 -2
  97. package/dist/lib/chunk-remote-trace-monitor.mjs.map +1 -1
  98. package/dist/lib/chunk-reset-storage.mjs +6 -3
  99. package/dist/lib/chunk-reset-storage.mjs.map +1 -1
  100. package/dist/lib/chunk-resolve-navigation-targets.mjs +3 -3
  101. package/dist/lib/chunk-resolve-navigation-targets.mjs.map +1 -1
  102. package/dist/lib/chunk-revoke-recovery-credential.mjs +1 -1
  103. package/dist/lib/chunk-revoke-recovery-credential.mjs.map +1 -1
  104. package/dist/lib/chunk-share-identity.mjs +2 -2
  105. package/dist/lib/chunk-share-identity.mjs.map +1 -1
  106. package/dist/lib/chunk-space-replication-progress.mjs +49 -7
  107. package/dist/lib/chunk-space-replication-progress.mjs.map +1 -1
  108. package/dist/lib/chunk-trace-progress.mjs +5 -5
  109. package/dist/lib/chunk-trace-progress.mjs.map +1 -1
  110. package/dist/lib/chunk-update-profile.mjs +1 -1
  111. package/dist/lib/chunk-update-profile.mjs.map +1 -1
  112. package/dist/lib/chunk-useAccountUrl.mjs +23 -0
  113. package/dist/lib/chunk-useAccountUrl.mjs.map +1 -0
  114. package/dist/lib/chunk-useHubClient.mjs +30 -0
  115. package/dist/lib/chunk-useHubClient.mjs.map +1 -0
  116. package/dist/lib/commands.mjs +1 -1
  117. package/dist/lib/commands.mjs.map +1 -1
  118. package/dist/lib/commands.node.mjs +771 -1
  119. package/dist/lib/commands.node.mjs.map +1 -1
  120. package/dist/lib/components.mjs +91 -0
  121. package/dist/lib/components.mjs.map +1 -0
  122. package/dist/lib/containers.mjs +5 -1
  123. package/dist/lib/containers.mjs.map +1 -1
  124. package/dist/lib/index.mjs +2 -27
  125. package/dist/lib/meta.mjs.map +1 -1
  126. package/dist/lib/ns/HaloServices.mjs +2 -0
  127. package/dist/lib/operations.mjs +3 -3
  128. package/dist/lib/operations.mjs.map +1 -1
  129. package/dist/lib/plugin.mjs +2 -2
  130. package/dist/lib/plugin.mjs.map +1 -1
  131. package/dist/lib/testing.mjs +71 -2
  132. package/dist/lib/testing.mjs.map +1 -1
  133. package/dist/lib/translations.mjs +26 -5
  134. package/dist/lib/translations.mjs.map +1 -1
  135. package/dist/lib/types.mjs +3 -1
  136. package/dist/types/src/HaloServices.d.ts +2 -0
  137. package/dist/types/src/HaloServices.d.ts.map +1 -0
  138. package/dist/types/src/capabilities/client-services.d.ts +9 -0
  139. package/dist/types/src/capabilities/client-services.d.ts.map +1 -0
  140. package/dist/types/src/capabilities/client.d.ts +33 -2
  141. package/dist/types/src/capabilities/client.d.ts.map +1 -1
  142. package/dist/types/src/capabilities/commands.d.ts +1 -1
  143. package/dist/types/src/capabilities/commands.d.ts.map +1 -1
  144. package/dist/types/src/capabilities/commands.node.d.ts +1 -1
  145. package/dist/types/src/capabilities/commands.node.d.ts.map +1 -1
  146. package/dist/types/src/capabilities/gen/browser.d.ts +45 -0
  147. package/dist/types/src/capabilities/gen/browser.d.ts.map +1 -0
  148. package/dist/types/src/capabilities/gen/node.d.ts +3 -1
  149. package/dist/types/src/capabilities/gen/node.d.ts.map +1 -1
  150. package/dist/types/src/capabilities/gen/tauri.d.ts +45 -0
  151. package/dist/types/src/capabilities/gen/tauri.d.ts.map +1 -0
  152. package/dist/types/src/capabilities/gen/workerd.d.ts +2 -0
  153. package/dist/types/src/capabilities/gen/workerd.d.ts.map +1 -1
  154. package/dist/types/src/capabilities/identity-lifecycle.d.ts +14 -0
  155. package/dist/types/src/capabilities/identity-lifecycle.d.ts.map +1 -0
  156. package/dist/types/src/capabilities/index.d.ts +5 -3
  157. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  158. package/dist/types/src/capabilities/navigation-handler/index.d.ts +1 -1
  159. package/dist/types/src/capabilities/navigation-handler/index.d.ts.map +1 -1
  160. package/dist/types/src/capabilities/navigation-handler/navigation-handler.d.ts.map +1 -1
  161. package/dist/types/src/capabilities/navigation-target-loader.d.ts +1 -6
  162. package/dist/types/src/capabilities/navigation-target-loader.d.ts.map +1 -1
  163. package/dist/types/src/capabilities/react-surface.d.ts +2 -2
  164. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  165. package/dist/types/src/capabilities/remote-trace-monitor.d.ts +1 -1
  166. package/dist/types/src/capabilities/remote-trace-monitor.d.ts.map +1 -1
  167. package/dist/types/src/capabilities/trace-progress.d.ts +2 -2
  168. package/dist/types/src/commands/account/index.d.ts +1 -1
  169. package/dist/types/src/commands/account/index.d.ts.map +1 -1
  170. package/dist/types/src/commands/account/invitation/create/create.d.ts +4 -3
  171. package/dist/types/src/commands/account/invitation/create/create.d.ts.map +1 -1
  172. package/dist/types/src/commands/account/invitation/create/index.d.ts +1 -1
  173. package/dist/types/src/commands/account/invitation/create/index.d.ts.map +1 -1
  174. package/dist/types/src/commands/account/invitation/index.d.ts +2 -2
  175. package/dist/types/src/commands/account/invitation/index.d.ts.map +1 -1
  176. package/dist/types/src/commands/account/login/index.d.ts +1 -1
  177. package/dist/types/src/commands/account/login/index.d.ts.map +1 -1
  178. package/dist/types/src/commands/account/login/login.d.ts +6 -5
  179. package/dist/types/src/commands/account/login/login.d.ts.map +1 -1
  180. package/dist/types/src/commands/account/logout/index.d.ts +1 -1
  181. package/dist/types/src/commands/account/logout/index.d.ts.map +1 -1
  182. package/dist/types/src/commands/account/logout/logout.d.ts +2 -2
  183. package/dist/types/src/commands/account/logout/logout.d.ts.map +1 -1
  184. package/dist/types/src/commands/account/signup/index.d.ts +1 -1
  185. package/dist/types/src/commands/account/signup/index.d.ts.map +1 -1
  186. package/dist/types/src/commands/account/signup/signup.d.ts +5 -4
  187. package/dist/types/src/commands/account/signup/signup.d.ts.map +1 -1
  188. package/dist/types/src/commands/account/util.d.ts +1 -1
  189. package/dist/types/src/commands/account/util.d.ts.map +1 -1
  190. package/dist/types/src/commands/config/index.d.ts +1 -1
  191. package/dist/types/src/commands/config/index.d.ts.map +1 -1
  192. package/dist/types/src/commands/config/view.d.ts +1 -1
  193. package/dist/types/src/commands/config/view.d.ts.map +1 -1
  194. package/dist/types/src/commands/device/index.d.ts +1 -1
  195. package/dist/types/src/commands/device/index.d.ts.map +1 -1
  196. package/dist/types/src/commands/device/info/index.d.ts +1 -1
  197. package/dist/types/src/commands/device/info/index.d.ts.map +1 -1
  198. package/dist/types/src/commands/device/info/info.d.ts +1 -1
  199. package/dist/types/src/commands/device/info/info.d.ts.map +1 -1
  200. package/dist/types/src/commands/device/list/index.d.ts +1 -1
  201. package/dist/types/src/commands/device/list/index.d.ts.map +1 -1
  202. package/dist/types/src/commands/device/list/list.d.ts +1 -1
  203. package/dist/types/src/commands/device/list/list.d.ts.map +1 -1
  204. package/dist/types/src/commands/device/update/index.d.ts +1 -1
  205. package/dist/types/src/commands/device/update/index.d.ts.map +1 -1
  206. package/dist/types/src/commands/device/update/update.d.ts +1 -1
  207. package/dist/types/src/commands/device/update/update.d.ts.map +1 -1
  208. package/dist/types/src/commands/device/util.d.ts +1 -1
  209. package/dist/types/src/commands/device/util.d.ts.map +1 -1
  210. package/dist/types/src/commands/edge/index.d.ts +1 -1
  211. package/dist/types/src/commands/edge/index.d.ts.map +1 -1
  212. package/dist/types/src/commands/edge/status.d.ts +1 -1
  213. package/dist/types/src/commands/edge/status.d.ts.map +1 -1
  214. package/dist/types/src/commands/errors.d.ts +33 -0
  215. package/dist/types/src/commands/errors.d.ts.map +1 -0
  216. package/dist/types/src/commands/halo/credential/add/add.d.ts +5 -4
  217. package/dist/types/src/commands/halo/credential/add/add.d.ts.map +1 -1
  218. package/dist/types/src/commands/halo/credential/add/index.d.ts +1 -1
  219. package/dist/types/src/commands/halo/credential/add/index.d.ts.map +1 -1
  220. package/dist/types/src/commands/halo/credential/index.d.ts +2 -2
  221. package/dist/types/src/commands/halo/credential/index.d.ts.map +1 -1
  222. package/dist/types/src/commands/halo/credential/list/index.d.ts +1 -1
  223. package/dist/types/src/commands/halo/credential/list/index.d.ts.map +1 -1
  224. package/dist/types/src/commands/halo/credential/list/list.d.ts +1 -1
  225. package/dist/types/src/commands/halo/credential/list/list.d.ts.map +1 -1
  226. package/dist/types/src/commands/halo/identity/identity.d.ts +1 -1
  227. package/dist/types/src/commands/halo/identity/identity.d.ts.map +1 -1
  228. package/dist/types/src/commands/halo/identity/index.d.ts +1 -1
  229. package/dist/types/src/commands/halo/identity/index.d.ts.map +1 -1
  230. package/dist/types/src/commands/halo/index.d.ts +1 -1
  231. package/dist/types/src/commands/halo/index.d.ts.map +1 -1
  232. package/dist/types/src/commands/halo/keys/index.d.ts +1 -1
  233. package/dist/types/src/commands/halo/keys/index.d.ts.map +1 -1
  234. package/dist/types/src/commands/halo/keys/keys.d.ts +1 -1
  235. package/dist/types/src/commands/halo/keys/keys.d.ts.map +1 -1
  236. package/dist/types/src/commands/halo/seed/index.d.ts +1 -1
  237. package/dist/types/src/commands/halo/seed/index.d.ts.map +1 -1
  238. package/dist/types/src/commands/halo/seed/seed.d.ts +1 -1
  239. package/dist/types/src/commands/halo/seed/seed.d.ts.map +1 -1
  240. package/dist/types/src/commands/halo/share/index.d.ts +1 -1
  241. package/dist/types/src/commands/halo/share/index.d.ts.map +1 -1
  242. package/dist/types/src/commands/halo/share/share.d.ts +4 -3
  243. package/dist/types/src/commands/halo/share/share.d.ts.map +1 -1
  244. package/dist/types/src/commands/halo/update/index.d.ts +1 -1
  245. package/dist/types/src/commands/halo/update/index.d.ts.map +1 -1
  246. package/dist/types/src/commands/halo/update/update.d.ts +1 -1
  247. package/dist/types/src/commands/halo/update/update.d.ts.map +1 -1
  248. package/dist/types/src/commands/halo/util.d.ts +2 -2
  249. package/dist/types/src/commands/halo/util.d.ts.map +1 -1
  250. package/dist/types/src/commands/index.d.ts +6 -6
  251. package/dist/types/src/commands/index.d.ts.map +1 -1
  252. package/dist/types/src/commands/profile/create.d.ts +1 -1
  253. package/dist/types/src/commands/profile/create.d.ts.map +1 -1
  254. package/dist/types/src/commands/profile/delete.d.ts +1 -1
  255. package/dist/types/src/commands/profile/delete.d.ts.map +1 -1
  256. package/dist/types/src/commands/profile/import.d.ts +5 -4
  257. package/dist/types/src/commands/profile/import.d.ts.map +1 -1
  258. package/dist/types/src/commands/profile/index.d.ts +2 -2
  259. package/dist/types/src/commands/profile/index.d.ts.map +1 -1
  260. package/dist/types/src/commands/profile/inspect.d.ts +1 -1
  261. package/dist/types/src/commands/profile/inspect.d.ts.map +1 -1
  262. package/dist/types/src/commands/profile/list.d.ts +1 -1
  263. package/dist/types/src/commands/profile/list.d.ts.map +1 -1
  264. package/dist/types/src/commands/profile/reset.d.ts +2 -2
  265. package/dist/types/src/commands/profile/reset.d.ts.map +1 -1
  266. package/dist/types/src/components/DevicesForm/DevicesForm.d.ts +19 -0
  267. package/dist/types/src/components/DevicesForm/DevicesForm.d.ts.map +1 -0
  268. package/dist/types/src/components/DevicesForm/DevicesForm.stories.d.ts +207 -0
  269. package/dist/types/src/components/DevicesForm/DevicesForm.stories.d.ts.map +1 -0
  270. package/dist/types/src/components/DevicesForm/index.d.ts +2 -0
  271. package/dist/types/src/components/DevicesForm/index.d.ts.map +1 -0
  272. package/dist/types/src/components/index.d.ts +1 -0
  273. package/dist/types/src/components/index.d.ts.map +1 -1
  274. package/dist/types/src/constants.d.ts +1 -0
  275. package/dist/types/src/constants.d.ts.map +1 -1
  276. package/dist/types/src/containers/AccountContainer/AccountContainer.stories.d.ts +1 -1
  277. package/dist/types/src/containers/AccountContainer/AccountContainer.stories.d.ts.map +1 -1
  278. package/dist/types/src/containers/AccountContainer/index.d.ts +1 -1
  279. package/dist/types/src/containers/AccountContainer/index.d.ts.map +1 -1
  280. package/dist/types/src/containers/CliLoginDialog/CliLoginDialog.d.ts +12 -0
  281. package/dist/types/src/containers/CliLoginDialog/CliLoginDialog.d.ts.map +1 -0
  282. package/dist/types/src/containers/CliLoginDialog/index.d.ts +4 -0
  283. package/dist/types/src/containers/CliLoginDialog/index.d.ts.map +1 -0
  284. package/dist/types/src/containers/ContactPickerContainer/ContactPickerContainer.d.ts +8 -0
  285. package/dist/types/src/containers/ContactPickerContainer/ContactPickerContainer.d.ts.map +1 -0
  286. package/dist/types/src/containers/ContactPickerContainer/ContactPickerContainer.stories.d.ts +206 -0
  287. package/dist/types/src/containers/ContactPickerContainer/ContactPickerContainer.stories.d.ts.map +1 -0
  288. package/dist/types/src/containers/ContactPickerContainer/index.d.ts +2 -0
  289. package/dist/types/src/containers/ContactPickerContainer/index.d.ts.map +1 -0
  290. package/dist/types/src/containers/ContactsContainer/ContactsContainer.d.ts +3 -0
  291. package/dist/types/src/containers/ContactsContainer/ContactsContainer.d.ts.map +1 -0
  292. package/dist/types/src/containers/ContactsContainer/ContactsContainer.stories.d.ts +203 -0
  293. package/dist/types/src/containers/ContactsContainer/ContactsContainer.stories.d.ts.map +1 -0
  294. package/dist/types/src/containers/ContactsContainer/index.d.ts +2 -0
  295. package/dist/types/src/containers/ContactsContainer/index.d.ts.map +1 -0
  296. package/dist/types/src/containers/DevicesContainer/DevicesContainer.d.ts.map +1 -1
  297. package/dist/types/src/containers/DevicesContainer/DevicesContainer.stories.d.ts +19 -1
  298. package/dist/types/src/containers/DevicesContainer/DevicesContainer.stories.d.ts.map +1 -1
  299. package/dist/types/src/containers/DevicesContainer/index.d.ts +1 -1
  300. package/dist/types/src/containers/DevicesContainer/index.d.ts.map +1 -1
  301. package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.stories.d.ts +1 -1
  302. package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.stories.d.ts.map +1 -1
  303. package/dist/types/src/containers/InvitationsContainer/index.d.ts +1 -1
  304. package/dist/types/src/containers/InvitationsContainer/index.d.ts.map +1 -1
  305. package/dist/types/src/containers/JoinDialog/JoinDialog.d.ts.map +1 -1
  306. package/dist/types/src/containers/JoinDialog/JoinDialog.stories.d.ts +1 -1
  307. package/dist/types/src/containers/JoinDialog/JoinDialog.stories.d.ts.map +1 -1
  308. package/dist/types/src/containers/JoinDialog/index.d.ts +1 -1
  309. package/dist/types/src/containers/JoinDialog/index.d.ts.map +1 -1
  310. package/dist/types/src/containers/ProfileContainer/ProfileContainer.d.ts.map +1 -1
  311. package/dist/types/src/containers/ProfileContainer/ProfileContainer.stories.d.ts +1 -1
  312. package/dist/types/src/containers/ProfileContainer/ProfileContainer.stories.d.ts.map +1 -1
  313. package/dist/types/src/containers/ProfileContainer/index.d.ts +1 -1
  314. package/dist/types/src/containers/ProfileContainer/index.d.ts.map +1 -1
  315. package/dist/types/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.d.ts.map +1 -1
  316. package/dist/types/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.stories.d.ts.map +1 -1
  317. package/dist/types/src/containers/RecoveryCodeDialog/index.d.ts +2 -2
  318. package/dist/types/src/containers/RecoveryCodeDialog/index.d.ts.map +1 -1
  319. package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.d.ts.map +1 -1
  320. package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.stories.d.ts +1 -1
  321. package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.stories.d.ts.map +1 -1
  322. package/dist/types/src/containers/RecoveryCredentialsContainer/index.d.ts +1 -1
  323. package/dist/types/src/containers/RecoveryCredentialsContainer/index.d.ts.map +1 -1
  324. package/dist/types/src/containers/ResetDialog/ResetDialog.d.ts +6 -7
  325. package/dist/types/src/containers/ResetDialog/ResetDialog.d.ts.map +1 -1
  326. package/dist/types/src/containers/ResetDialog/ResetDialog.stories.d.ts +2 -2
  327. package/dist/types/src/containers/ResetDialog/ResetDialog.stories.d.ts.map +1 -1
  328. package/dist/types/src/containers/ResetDialog/index.d.ts +2 -2
  329. package/dist/types/src/containers/ResetDialog/index.d.ts.map +1 -1
  330. package/dist/types/src/containers/SpaceInvitationContainer/SpaceInvitationContainer.d.ts +10 -0
  331. package/dist/types/src/containers/SpaceInvitationContainer/SpaceInvitationContainer.d.ts.map +1 -0
  332. package/dist/types/src/containers/SpaceInvitationContainer/index.d.ts +2 -0
  333. package/dist/types/src/containers/SpaceInvitationContainer/index.d.ts.map +1 -0
  334. package/dist/types/src/containers/UsageContainer/UsageView.d.ts.map +1 -1
  335. package/dist/types/src/containers/UsageContainer/UsageView.stories.d.ts +1 -1
  336. package/dist/types/src/containers/UsageContainer/UsageView.stories.d.ts.map +1 -1
  337. package/dist/types/src/containers/UsageContainer/index.d.ts +1 -1
  338. package/dist/types/src/containers/UsageContainer/index.d.ts.map +1 -1
  339. package/dist/types/src/containers/index.d.ts +9 -3
  340. package/dist/types/src/containers/index.d.ts.map +1 -1
  341. package/dist/types/src/hooks/index.d.ts +2 -2
  342. package/dist/types/src/hooks/index.d.ts.map +1 -1
  343. package/dist/types/src/index.d.ts +2 -5
  344. package/dist/types/src/index.d.ts.map +1 -1
  345. package/dist/types/src/operations/create-agent.d.ts +2 -2
  346. package/dist/types/src/operations/create-agent.d.ts.map +1 -1
  347. package/dist/types/src/operations/create-identity.d.ts +2 -2
  348. package/dist/types/src/operations/create-identity.d.ts.map +1 -1
  349. package/dist/types/src/operations/create-passkey.d.ts +2 -2
  350. package/dist/types/src/operations/create-passkey.d.ts.map +1 -1
  351. package/dist/types/src/operations/create-recovery-code.d.ts +2 -2
  352. package/dist/types/src/operations/create-recovery-code.d.ts.map +1 -1
  353. package/dist/types/src/operations/grant-service-access.d.ts +2 -2
  354. package/dist/types/src/operations/grant-service-access.d.ts.map +1 -1
  355. package/dist/types/src/operations/index.d.ts +1 -1
  356. package/dist/types/src/operations/index.d.ts.map +1 -1
  357. package/dist/types/src/operations/join-identity.d.ts +2 -2
  358. package/dist/types/src/operations/join-identity.d.ts.map +1 -1
  359. package/dist/types/src/operations/open-usage.d.ts +2 -2
  360. package/dist/types/src/operations/open-usage.d.ts.map +1 -1
  361. package/dist/types/src/operations/recover-identity.d.ts +2 -2
  362. package/dist/types/src/operations/recover-identity.d.ts.map +1 -1
  363. package/dist/types/src/operations/redeem-passkey.d.ts +2 -2
  364. package/dist/types/src/operations/redeem-passkey.d.ts.map +1 -1
  365. package/dist/types/src/operations/redeem-token.d.ts +2 -2
  366. package/dist/types/src/operations/redeem-token.d.ts.map +1 -1
  367. package/dist/types/src/operations/reset-storage.d.ts +2 -2
  368. package/dist/types/src/operations/reset-storage.d.ts.map +1 -1
  369. package/dist/types/src/operations/revoke-recovery-credential.d.ts +2 -2
  370. package/dist/types/src/operations/revoke-recovery-credential.d.ts.map +1 -1
  371. package/dist/types/src/operations/share-identity.d.ts +2 -2
  372. package/dist/types/src/operations/share-identity.d.ts.map +1 -1
  373. package/dist/types/src/operations/update-profile.d.ts +2 -2
  374. package/dist/types/src/operations/update-profile.d.ts.map +1 -1
  375. package/dist/types/src/plugin.d.ts.map +1 -1
  376. package/dist/types/src/progress/index.d.ts +2 -2
  377. package/dist/types/src/progress/index.d.ts.map +1 -1
  378. package/dist/types/src/progress/space-sync-progress.d.ts +10 -1
  379. package/dist/types/src/progress/space-sync-progress.d.ts.map +1 -1
  380. package/dist/types/src/testing/ClientPluginManager.d.ts +18 -0
  381. package/dist/types/src/testing/ClientPluginManager.d.ts.map +1 -0
  382. package/dist/types/src/testing/createFakeContacts.d.ts +16 -0
  383. package/dist/types/src/testing/createFakeContacts.d.ts.map +1 -0
  384. package/dist/types/src/testing/index.d.ts +4 -2
  385. package/dist/types/src/testing/index.d.ts.map +1 -1
  386. package/dist/types/src/testing/initializeIdentity.d.ts +1 -1
  387. package/dist/types/src/testing/initializeIdentity.d.ts.map +1 -1
  388. package/dist/types/src/translations.d.ts +2 -2
  389. package/dist/types/src/translations.d.ts.map +1 -1
  390. package/dist/types/src/types/Account.d.ts +21 -7
  391. package/dist/types/src/types/Account.d.ts.map +1 -1
  392. package/dist/types/src/types/CliLogin.d.ts +33 -0
  393. package/dist/types/src/types/CliLogin.d.ts.map +1 -0
  394. package/dist/types/src/types/ClientCapabilities.d.ts +32 -3
  395. package/dist/types/src/types/ClientCapabilities.d.ts.map +1 -1
  396. package/dist/types/src/types/ClientEvents.d.ts +5 -1
  397. package/dist/types/src/types/ClientEvents.d.ts.map +1 -1
  398. package/dist/types/src/{operations/definitions.d.ts → types/ClientOperation.d.ts} +2 -1
  399. package/dist/types/src/types/ClientOperation.d.ts.map +1 -0
  400. package/dist/types/src/types/ClientOptions.d.ts +1 -8
  401. package/dist/types/src/types/ClientOptions.d.ts.map +1 -1
  402. package/dist/types/src/types/PasskeyError.d.ts +112 -11
  403. package/dist/types/src/types/PasskeyError.d.ts.map +1 -1
  404. package/dist/types/src/types/index.d.ts +9 -7
  405. package/dist/types/src/types/index.d.ts.map +1 -1
  406. package/dist/types/tsconfig.tsbuildinfo +1 -1
  407. package/package.json +72 -61
  408. package/src/HaloServices.ts +7 -0
  409. package/src/capabilities/account-cache.ts +2 -2
  410. package/src/capabilities/app-graph-builder.ts +165 -69
  411. package/src/capabilities/client-services.ts +25 -0
  412. package/src/capabilities/client.ts +17 -12
  413. package/src/capabilities/commands.node.ts +1 -1
  414. package/src/capabilities/commands.ts +1 -1
  415. package/src/capabilities/gen/browser.ts +192 -0
  416. package/src/capabilities/gen/node.ts +48 -19
  417. package/src/capabilities/gen/tauri.ts +192 -0
  418. package/src/capabilities/gen/workerd.ts +41 -13
  419. package/src/capabilities/identity-lifecycle.ts +86 -0
  420. package/src/capabilities/index.ts +57 -26
  421. package/src/capabilities/layer-specs.ts +107 -4
  422. package/src/capabilities/navigation-handler/index.ts +2 -2
  423. package/src/capabilities/navigation-handler/navigation-handler.ts +20 -1
  424. package/src/capabilities/navigation-target-loader.ts +15 -10
  425. package/src/capabilities/react-context.tsx +2 -2
  426. package/src/capabilities/react-surface.ts +43 -18
  427. package/src/capabilities/remote-trace-monitor.ts +5 -2
  428. package/src/capabilities/schema-defs.test.ts +2 -2
  429. package/src/capabilities/space-replication-progress.ts +12 -7
  430. package/src/capabilities/trace-progress.ts +6 -6
  431. package/src/commands/account/index.ts +5 -5
  432. package/src/commands/account/invitation/create/create.ts +9 -5
  433. package/src/commands/account/invitation/create/index.ts +1 -1
  434. package/src/commands/account/invitation/index.ts +2 -2
  435. package/src/commands/account/login/index.ts +1 -1
  436. package/src/commands/account/login/login.ts +108 -37
  437. package/src/commands/account/logout/index.ts +1 -1
  438. package/src/commands/account/logout/logout.ts +8 -5
  439. package/src/commands/account/signup/index.ts +1 -1
  440. package/src/commands/account/signup/signup.ts +33 -19
  441. package/src/commands/account/util.test.ts +1 -1
  442. package/src/commands/account/util.ts +2 -2
  443. package/src/commands/config/index.ts +2 -2
  444. package/src/commands/config/view.ts +1 -1
  445. package/src/commands/device/index.ts +4 -4
  446. package/src/commands/device/info/index.ts +1 -1
  447. package/src/commands/device/info/info.test.ts +4 -3
  448. package/src/commands/device/info/info.ts +5 -4
  449. package/src/commands/device/list/index.ts +1 -1
  450. package/src/commands/device/list/list.test.ts +2 -2
  451. package/src/commands/device/list/list.ts +2 -2
  452. package/src/commands/device/update/index.ts +1 -1
  453. package/src/commands/device/update/update.ts +8 -9
  454. package/src/commands/device/util.ts +6 -5
  455. package/src/commands/edge/index.ts +2 -2
  456. package/src/commands/edge/status.ts +1 -1
  457. package/src/commands/errors.ts +8 -0
  458. package/src/commands/halo/credential/add/add.ts +13 -16
  459. package/src/commands/halo/credential/add/index.ts +1 -1
  460. package/src/commands/halo/credential/index.ts +3 -3
  461. package/src/commands/halo/credential/list/index.ts +1 -1
  462. package/src/commands/halo/credential/list/list.test.ts +2 -2
  463. package/src/commands/halo/credential/list/list.ts +15 -14
  464. package/src/commands/halo/identity/identity.test.ts +7 -3
  465. package/src/commands/halo/identity/identity.ts +2 -2
  466. package/src/commands/halo/identity/index.ts +1 -1
  467. package/src/commands/halo/index.ts +7 -7
  468. package/src/commands/halo/keys/index.ts +1 -1
  469. package/src/commands/halo/keys/keys.test.ts +5 -4
  470. package/src/commands/halo/keys/keys.ts +6 -5
  471. package/src/commands/halo/seed/index.ts +1 -1
  472. package/src/commands/halo/seed/seed.ts +1 -1
  473. package/src/commands/halo/share/index.ts +1 -1
  474. package/src/commands/halo/share/share.ts +15 -10
  475. package/src/commands/halo/update/index.ts +1 -1
  476. package/src/commands/halo/update/update.test.ts +2 -2
  477. package/src/commands/halo/update/update.ts +7 -17
  478. package/src/commands/halo/util.ts +11 -7
  479. package/src/commands/index.ts +6 -6
  480. package/src/commands/profile/create.ts +5 -5
  481. package/src/commands/profile/delete.ts +4 -4
  482. package/src/commands/profile/import.ts +17 -14
  483. package/src/commands/profile/index.ts +7 -7
  484. package/src/commands/profile/inspect.ts +9 -6
  485. package/src/commands/profile/list.ts +2 -2
  486. package/src/commands/profile/reset.ts +9 -6
  487. package/src/components/DevicesForm/DevicesForm.stories.tsx +62 -0
  488. package/src/components/DevicesForm/DevicesForm.tsx +100 -0
  489. package/src/components/DevicesForm/index.ts +5 -0
  490. package/src/components/index.ts +2 -0
  491. package/src/constants.ts +1 -0
  492. package/src/containers/AccountContainer/AccountContainer.stories.tsx +3 -3
  493. package/src/containers/AccountContainer/AccountContainer.tsx +54 -43
  494. package/src/containers/AccountContainer/index.ts +1 -1
  495. package/src/containers/CliLoginDialog/CliLoginDialog.tsx +159 -0
  496. package/src/containers/CliLoginDialog/index.ts +8 -0
  497. package/src/containers/ContactPickerContainer/ContactPickerContainer.stories.tsx +66 -0
  498. package/src/containers/ContactPickerContainer/ContactPickerContainer.tsx +126 -0
  499. package/src/containers/ContactPickerContainer/index.ts +5 -0
  500. package/src/containers/ContactsContainer/ContactsContainer.stories.tsx +48 -0
  501. package/src/containers/ContactsContainer/ContactsContainer.tsx +61 -0
  502. package/src/containers/ContactsContainer/index.ts +5 -0
  503. package/src/containers/DevicesContainer/DevicesContainer.stories.tsx +3 -3
  504. package/src/containers/DevicesContainer/DevicesContainer.tsx +45 -103
  505. package/src/containers/DevicesContainer/index.ts +1 -1
  506. package/src/containers/InvitationsContainer/InvitationsContainer.stories.tsx +3 -3
  507. package/src/containers/InvitationsContainer/InvitationsContainer.tsx +63 -60
  508. package/src/containers/InvitationsContainer/index.ts +1 -1
  509. package/src/containers/JoinDialog/JoinDialog.stories.tsx +5 -7
  510. package/src/containers/JoinDialog/JoinDialog.tsx +10 -9
  511. package/src/containers/JoinDialog/index.ts +1 -1
  512. package/src/containers/ProfileContainer/ProfileContainer.stories.tsx +3 -3
  513. package/src/containers/ProfileContainer/ProfileContainer.tsx +72 -55
  514. package/src/containers/ProfileContainer/index.ts +1 -1
  515. package/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.stories.tsx +5 -6
  516. package/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.tsx +27 -29
  517. package/src/containers/RecoveryCodeDialog/index.ts +2 -2
  518. package/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.stories.tsx +7 -7
  519. package/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.tsx +69 -41
  520. package/src/containers/RecoveryCredentialsContainer/index.ts +1 -1
  521. package/src/containers/ResetDialog/ResetDialog.stories.tsx +9 -21
  522. package/src/containers/ResetDialog/ResetDialog.tsx +35 -24
  523. package/src/containers/ResetDialog/index.ts +2 -2
  524. package/src/containers/SpaceInvitationContainer/SpaceInvitationContainer.tsx +62 -0
  525. package/src/containers/SpaceInvitationContainer/index.ts +8 -0
  526. package/src/containers/UsageContainer/UsageContainer.tsx +4 -4
  527. package/src/containers/UsageContainer/UsageView.stories.tsx +1 -1
  528. package/src/containers/UsageContainer/UsageView.tsx +22 -24
  529. package/src/containers/UsageContainer/index.ts +1 -1
  530. package/src/containers/index.ts +23 -12
  531. package/src/hooks/index.ts +2 -2
  532. package/src/hooks/useAccountUrl.ts +1 -1
  533. package/src/hooks/useHubClient.ts +3 -3
  534. package/src/index.ts +2 -5
  535. package/src/meta.ts +1 -1
  536. package/src/operations/create-agent.ts +2 -2
  537. package/src/operations/create-identity.ts +5 -3
  538. package/src/operations/create-passkey.ts +59 -37
  539. package/src/operations/create-recovery-code.ts +16 -15
  540. package/src/operations/grant-service-access.ts +9 -8
  541. package/src/operations/index.ts +17 -30
  542. package/src/operations/join-identity.ts +3 -3
  543. package/src/operations/open-usage.ts +3 -3
  544. package/src/operations/recover-identity.ts +3 -3
  545. package/src/operations/redeem-passkey.ts +63 -65
  546. package/src/operations/redeem-token.ts +2 -2
  547. package/src/operations/reset-storage.ts +4 -3
  548. package/src/operations/resolve-navigation-targets.ts +1 -1
  549. package/src/operations/revoke-recovery-credential.ts +9 -8
  550. package/src/operations/share-identity.ts +2 -2
  551. package/src/operations/update-profile.ts +2 -2
  552. package/src/plugin.test.ts +2 -2
  553. package/src/plugin.ts +30 -25
  554. package/src/progress/index.ts +2 -2
  555. package/src/progress/space-sync-progress.test.ts +36 -13
  556. package/src/progress/space-sync-progress.ts +21 -6
  557. package/src/schema-defs.test.ts +2 -2
  558. package/src/testing/ClientPluginManager.tsx +44 -0
  559. package/src/testing/createFakeContacts.ts +57 -0
  560. package/src/testing/index.ts +4 -2
  561. package/src/testing/initializeIdentity.ts +6 -2
  562. package/src/translations.ts +33 -9
  563. package/src/types/Account.ts +27 -11
  564. package/src/types/CliLogin.ts +78 -0
  565. package/src/types/ClientCapabilities.ts +38 -4
  566. package/src/types/ClientEvents.ts +5 -1
  567. package/src/{operations/definitions.ts → types/ClientOperation.ts} +5 -1
  568. package/src/types/ClientOptions.ts +3 -7
  569. package/src/types/PasskeyError.test.ts +96 -1
  570. package/src/types/PasskeyError.ts +85 -15
  571. package/src/types/index.ts +9 -7
  572. package/dist/lib/chunk-commands.mjs +0 -1090
  573. package/dist/lib/chunk-commands.mjs.map +0 -1
  574. package/dist/lib/chunk-definitions.mjs.map +0 -1
  575. package/dist/lib/chunk-hooks.mjs +0 -49
  576. package/dist/lib/chunk-hooks.mjs.map +0 -1
  577. package/dist/lib/chunk-progress.mjs +0 -35
  578. package/dist/lib/chunk-progress.mjs.map +0 -1
  579. package/dist/lib/index.mjs.map +0 -1
  580. package/dist/types/src/operations/definitions.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"chunk-UsageContainer.mjs","names":[],"sources":["../../src/containers/UsageContainer/UsageView.tsx","../../src/containers/UsageContainer/UsageContainer.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\nimport React, { useCallback, useMemo, useState } from 'react';\n\nimport { type GetProfileUsageResponse, type MeteringLimit, type MeteringUsageItem } from '@dxos/protocols';\nimport { Banner, Progress, useTranslation } from '@dxos/react-ui';\nimport { Form, type FormFieldProvider } from '@dxos/react-ui-form';\n\nimport { meta } from '#meta';\n\nexport type UsageViewState = 'loading' | 'ready' | 'error' | 'unavailable';\n\ntype UsageViewCommonProps = {\n /** Epoch milliseconds of the last successful fetch. */\n lastUpdated?: number;\n /** Invoked when the user requests a refresh. */\n onRefresh?: () => void;\n};\n\n/**\n * Discriminated on `state`: the payload is required (and only present) when `state` is `'ready'`, so a\n * missing payload can't be silently rendered as an empty plan.\n */\nexport type UsageViewProps =\n | (UsageViewCommonProps & { state: Exclude<UsageViewState, 'ready'>; data?: undefined })\n | (UsageViewCommonProps & { state: 'ready'; data: GetProfileUsageResponse });\n\ntype TFunction = (key: string, options?: Record<string, unknown>) => string;\n\n/**\n * Whether a usage row falls under a limit. Subtype segments are matched positionally against\n * `subtypePattern` where `*` matches any segment.\n */\nconst usageMatchesLimit = (item: MeteringUsageItem, limit: MeteringLimit): boolean => {\n if (item.eventType !== limit.eventType || item.valueKey !== limit.valueKey) {\n return false;\n }\n return limit.subtypePattern.every((pattern, index) => pattern === '*' || pattern === item.subtypePattern[index]);\n};\n\n/** Sum every usage item that falls under the limit. */\nconst sumUsageForLimit = (usage: GetProfileUsageResponse['usage'], limit: MeteringLimit): number =>\n usage.reduce((total, item) => (usageMatchesLimit(item, limit) ? total + item.amount : total), 0);\n\n/** Humanize a camelCase value key, e.g. `outputTokens` → `output tokens`. */\nconst formatValueKey = (valueKey: string): string =>\n valueKey\n .replace(/([A-Z])/g, ' $1')\n .trim()\n .toLowerCase();\n\n/**\n * Human label for a limit: a scope followed by the value key, e.g.\n * `{ eventType: 'ai', valueKey: 'outputTokens', subtypePattern: ['*'] }` → `All models · output tokens`,\n * `{ eventType: 'ai', valueKey: 'inputTokens', subtypePattern: ['claude-opus-4'] }` → `claude-opus-4 · input tokens`.\n */\nconst formatLimitLabel = (limit: MeteringLimit, t: TFunction): string => {\n const metric = formatValueKey(limit.valueKey);\n const subtype = limit.subtypePattern.filter((segment) => segment && segment !== '*').join('/');\n if (limit.eventType === 'ai') {\n return `${subtype || t('usage-all-models.label')} · ${metric}`;\n }\n return `${subtype ? `${limit.eventType}/${subtype}` : limit.eventType} · ${metric}`;\n};\n\nconst formatAmount = (amount: number): string => amount.toLocaleString();\n\nconst SECONDS_PER_HOUR = 60 * 60;\n\n/** Render `windowHours` as a localized \"N months / days / hours\" string. */\nconst formatWindow = (windowHours: number, t: TFunction): string => {\n if (windowHours % (24 * 30) === 0) {\n return t('usage-window-months.label', { count: windowHours / (24 * 30) });\n }\n if (windowHours % 24 === 0) {\n return t('usage-window-days.label', { count: windowHours / 24 });\n }\n return t('usage-window-hours.label', { count: windowHours });\n};\n\ntype UsageRow = {\n key: string;\n /** Field label (schema `title` annotation). */\n label: string;\n /** Field caption (schema `description` annotation). */\n caption: string;\n /** Consumption as a whole percentage (`0`–`100`); `undefined` for an unlimited limit. */\n percent?: number;\n windowHours: number;\n};\n\n/** One display row per limit, shorter windows first. A `null` limit is reported as unlimited. */\nconst computeRows = (data: GetProfileUsageResponse, t: TFunction): UsageRow[] =>\n data.limits\n .map((limit): UsageRow => {\n const used = sumUsageForLimit(data.usage, limit);\n const label = formatLimitLabel(limit, t);\n const windowHours = limit.windowDuration / SECONDS_PER_HOUR;\n const window = formatWindow(windowHours, t);\n const key = `${limit.eventType}/${limit.subtypePattern.join(',')}/${limit.valueKey}/${limit.windowDuration}/${limit.limit ?? 'unlimited'}`;\n if (limit.limit === null) {\n return {\n key,\n label,\n caption: t('usage-unlimited.description', { used: formatAmount(used), window }),\n windowHours,\n };\n }\n const percent = limit.limit > 0 ? Math.min(100, Math.round((used / limit.limit) * 100)) : used > 0 ? 100 : 0;\n return {\n key,\n label,\n caption: `${t('usage-percent-used.label', { percent })} · ${t('usage-limit.description', { used: formatAmount(used), limit: formatAmount(limit.limit), window })}`,\n percent,\n windowHours,\n };\n })\n .sort((left, right) => left.windowHours - right.windowHours);\n\n/**\n * A single usage field: an optional number carrying its label/caption as `title`/`description`\n * annotations and the consumption percentage as its value. Optional so the form renders no required\n * markers; `Schema.Number` keeps the field context-free (`R = never`) so the struct stays assignable to `Form`.\n */\nconst usageField = (title: string, description: string) =>\n Schema.optional(Schema.Number.annotate({ title, description }));\n\n/**\n * Build the Effect schema (one annotated field per limit) and matching values. Unlimited limits have no\n * value, so their field reads `undefined` and the renderer shows the \"Unlimited\" label instead of a meter.\n */\nconst buildUsageForm = (rows: UsageRow[]) => {\n const fields: Record<string, ReturnType<typeof usageField>> = {};\n const values: Record<string, number> = {};\n rows.forEach((row, index) => {\n const field = `metric_${index}`;\n fields[field] = usageField(row.label, row.caption);\n if (row.percent !== undefined) {\n values[field] = row.percent;\n }\n });\n return { schema: Schema.Struct(fields), values };\n};\n\n/** Non-data states shown as a single `Message`, keyed by message variant (translation keys for the copy). */\nconst STATE_MESSAGES = {\n unavailable: {\n valence: 'warning',\n icon: 'ph--cloud-slash--duotone',\n title: 'usage-unavailable.title',\n description: 'usage-unavailable.description',\n },\n error: {\n valence: 'error',\n icon: 'ph--cloud-x--duotone',\n title: 'usage-offline.title',\n description: 'usage-offline.description',\n },\n empty: {\n valence: 'neutral',\n icon: 'ph--chart-bar--duotone',\n title: 'usage-empty.title',\n description: 'usage-empty.description',\n },\n} as const;\n\n/**\n * Presentational view of profile usage: renders loading/error/unavailable/empty states, or a\n * schema-driven settings form (one read-only field per limit), plus a refresh control and a\n * collapsible raw-response viewer. Pure — all data via props.\n */\nexport const UsageView = ({ state, data, lastUpdated, onRefresh }: UsageViewProps) => {\n const { t } = useTranslation(meta.profile.key);\n const [rawExpanded, setRawExpanded] = useState(false);\n\n const { schema, values, empty } = useMemo(() => {\n const rows = data ? computeRows(data, t) : [];\n return { ...buildUsageForm(rows), empty: rows.length === 0 };\n }, [data, t]);\n\n // Non-data states resolve to a `Message`; `loading` shows a spinner and `ready` with data shows the form.\n const message =\n state === 'unavailable'\n ? STATE_MESSAGES.unavailable\n : state === 'error'\n ? STATE_MESSAGES.error\n : state === 'ready' && empty\n ? STATE_MESSAGES.empty\n : undefined;\n\n // Render each metric as a meter from its percentage value; unlimited limits (no value) show a label.\n const meterFieldProvider = useCallback<FormFieldProvider>(\n ({ fieldProps: { label, description, getValue } }) => {\n const percent = getValue();\n return (\n <Form.Row label={label} description={description}>\n {typeof percent === 'number' ? (\n <Progress progress={percent / 100} aria-label={t('usage-percent-used.label', { percent })} />\n ) : (\n t('usage-unlimited.label')\n )}\n </Form.Row>\n );\n },\n [t],\n );\n\n return (\n <Form.Root variant='settings' layout='static' schema={schema} values={values}>\n <Form.Viewport scroll>\n <Form.Content>\n <Form.Section title={t('usage-section.title')} description={t('usage-section.description')}>\n {message ? (\n <Banner.Root valence={message.valence}>\n <Banner.Content>\n <Banner.Title icon={message.icon}>{t(message.title)}</Banner.Title>\n <Banner.Body>{t(message.description)}</Banner.Body>\n </Banner.Content>\n </Banner.Root>\n ) : (\n <Form.FieldSet fieldProvider={meterFieldProvider} />\n )}\n </Form.Section>\n\n {/* {state === 'ready' && data && (\n <Form.Section>\n <Form.Row\n label={\n lastUpdated !== undefined\n ? t('usage-last-updated.label', { time: new Date(lastUpdated).toLocaleTimeString() })\n : t('usage-refresh.label')\n }\n >\n {onRefresh && (\n <IconButton\n iconOnly\n variant='ghost'\n icon='ph--arrow-clockwise--regular'\n label={t('usage-refresh.label')}\n onClick={onRefresh}\n />\n )}\n </Form.Row>\n </Form.Section>\n )} */}\n\n {/* {state === 'ready' && data && (\n <Form.Section>\n <Form.Row label={t('usage-raw-json.label')}>\n <ToggleIconButton\n iconOnly\n variant='ghost'\n active={rawExpanded}\n icon='ph--caret-right--regular'\n label={t('usage-raw-json.label')}\n onClick={() => setRawExpanded((value) => !value)}\n />\n </Form.Row>\n {rawExpanded && <JsonHighlighter data={data} testId='usage-raw-json' />}\n </Form.Section>\n )} */}\n </Form.Content>\n </Form.Viewport>\n </Form.Root>\n );\n};\n\nUsageView.displayName = 'UsageView';\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useState } from 'react';\n\nimport { Context } from '@dxos/context';\nimport { log } from '@dxos/log';\nimport { type GetProfileUsageResponse } from '@dxos/protocols';\nimport { useAsyncEffect } from '@dxos/react-ui';\n\nimport { useHubHttpClient } from '../../hooks';\nimport { UsageView, type UsageViewState } from './UsageView';\n\n/** State + payload kept together so `ready` always carries data (mirrors the discriminated `UsageViewProps`). */\ntype UsageFetchState =\n | {\n state: Exclude<UsageViewState, 'ready'>;\n }\n | {\n state: 'ready';\n data: GetProfileUsageResponse;\n };\n\n/**\n * Fetches rolling-window profile usage from the hub service and renders it.\n * Connected wrapper around the presentational {@link UsageView}.\n */\nexport const UsageContainer = () => {\n const hubHttp = useHubHttpClient();\n const [fetchState, setFetchState] = useState<UsageFetchState>({ state: 'loading' });\n const [lastUpdated, setLastUpdated] = useState<number | undefined>();\n const [refreshCount, setRefreshCount] = useState(0);\n\n useAsyncEffect(async () => {\n if (!hubHttp) {\n setFetchState({ state: 'unavailable' });\n return;\n }\n // Keep prior data visible while refetching; only show the loading state on first load.\n setFetchState((previous) => (previous.state === 'ready' ? previous : { state: 'loading' }));\n try {\n const result = await hubHttp.getProfileUsage(new Context());\n setFetchState({ state: 'ready', data: result });\n setLastUpdated(Date.now());\n } catch (err) {\n log.catch(err);\n setFetchState({ state: 'error' });\n }\n }, [hubHttp, refreshCount]);\n\n const handleRefresh = useCallback(() => setRefreshCount((count) => count + 1), []);\n\n return <UsageView {...fetchState} lastUpdated={lastUpdated} onRefresh={handleRefresh} />;\n};\n\nUsageContainer.displayName = 'UsageContainer';\n"],"mappings":"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"}
1
+ {"version":3,"file":"chunk-UsageContainer.mjs","names":[],"sources":["../../src/containers/UsageContainer/UsageView.tsx","../../src/containers/UsageContainer/UsageContainer.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\nimport React, { useCallback, useMemo, useState } from 'react';\n\nimport { type GetProfileUsageResponse, type MeteringLimit, type MeteringUsageItem } from '@dxos/protocols';\nimport { Form, type FormFieldProvider } from '@dxos/react-ui-form';\nimport * as Banner from '@dxos/react-ui/Banner';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as Status from '@dxos/react-ui/Status';\n\nimport { meta } from '#meta';\n\nexport type UsageViewState = 'loading' | 'ready' | 'error' | 'unavailable';\n\ntype UsageViewCommonProps = {\n /** Epoch milliseconds of the last successful fetch. */\n lastUpdated?: number;\n /** Invoked when the user requests a refresh. */\n onRefresh?: () => void;\n};\n\n/**\n * Discriminated on `state`: the payload is required (and only present) when `state` is `'ready'`, so a\n * missing payload can't be silently rendered as an empty plan.\n */\nexport type UsageViewProps =\n | (UsageViewCommonProps & { state: Exclude<UsageViewState, 'ready'>; data?: undefined })\n | (UsageViewCommonProps & { state: 'ready'; data: GetProfileUsageResponse });\n\ntype TFunction = (key: string, options?: Record<string, unknown>) => string;\n\n/**\n * Whether a usage row falls under a limit. Subtype segments are matched positionally against\n * `subtypePattern` where `*` matches any segment.\n */\nconst usageMatchesLimit = (item: MeteringUsageItem, limit: MeteringLimit): boolean => {\n if (item.eventType !== limit.eventType || item.valueKey !== limit.valueKey) {\n return false;\n }\n return limit.subtypePattern.every((pattern, index) => pattern === '*' || pattern === item.subtypePattern[index]);\n};\n\n/** Sum every usage item that falls under the limit. */\nconst sumUsageForLimit = (usage: GetProfileUsageResponse['usage'], limit: MeteringLimit): number =>\n usage.reduce((total, item) => (usageMatchesLimit(item, limit) ? total + item.amount : total), 0);\n\n/** Humanize a camelCase value key, e.g. `outputTokens` → `output tokens`. */\nconst formatValueKey = (valueKey: string): string =>\n valueKey\n .replace(/([A-Z])/g, ' $1')\n .trim()\n .toLowerCase();\n\n/**\n * Human label for a limit: a scope followed by the value key, e.g.\n * `{ eventType: 'ai', valueKey: 'outputTokens', subtypePattern: ['*'] }` → `All models · output tokens`,\n * `{ eventType: 'ai', valueKey: 'inputTokens', subtypePattern: ['claude-opus-4'] }` → `claude-opus-4 · input tokens`.\n */\nconst formatLimitLabel = (limit: MeteringLimit, t: TFunction): string => {\n const metric = formatValueKey(limit.valueKey);\n const subtype = limit.subtypePattern.filter((segment) => segment && segment !== '*').join('/');\n if (limit.eventType === 'ai') {\n return `${subtype || t('usage-all-models.label')} · ${metric}`;\n }\n return `${subtype ? `${limit.eventType}/${subtype}` : limit.eventType} · ${metric}`;\n};\n\nconst SECONDS_PER_HOUR = 60 * 60;\n\n/** Render `windowHours` as a localized \"N months / days / hours\" string. */\nconst formatWindow = (windowHours: number, t: TFunction): string => {\n if (windowHours % (24 * 30) === 0) {\n return t('usage-window-months.label', { count: windowHours / (24 * 30) });\n }\n if (windowHours % 24 === 0) {\n return t('usage-window-days.label', { count: windowHours / 24 });\n }\n return t('usage-window-hours.label', { count: windowHours });\n};\n\ntype UsageRow = {\n key: string;\n /** Field label (schema `title` annotation). */\n label: string;\n /** Field caption (schema `description` annotation). */\n caption: string;\n /** Consumption as a whole percentage (`0`–`100`); `undefined` for an unlimited limit. */\n percent?: number;\n windowHours: number;\n};\n\n/** One display row per limit, shorter windows first. A `null` limit is reported as unlimited. */\nconst computeRows = (data: GetProfileUsageResponse, t: TFunction): UsageRow[] =>\n data.limits\n .map((limit): UsageRow => {\n const used = sumUsageForLimit(data.usage, limit);\n const label = formatLimitLabel(limit, t);\n const windowHours = limit.windowDuration / SECONDS_PER_HOUR;\n const window = formatWindow(windowHours, t);\n const key = `${limit.eventType}/${limit.subtypePattern.join(',')}/${limit.valueKey}/${limit.windowDuration}/${limit.limit ?? 'unlimited'}`;\n if (limit.limit === null) {\n return {\n key,\n label,\n caption: t('usage-unlimited.description', { used: used.toLocaleString(), window }),\n windowHours,\n };\n }\n const percent = limit.limit > 0 ? Math.min(100, Math.round((used / limit.limit) * 100)) : used > 0 ? 100 : 0;\n return {\n key,\n label,\n caption: `${t('usage-percent-used.label', { percent })} · ${t('usage-limit.description', { used: used.toLocaleString(), limit: limit.limit.toLocaleString(), window })}`,\n percent,\n windowHours,\n };\n })\n .sort((left, right) => left.windowHours - right.windowHours);\n\n/**\n * A single usage field: an optional number carrying its label/caption as `title`/`description`\n * annotations and the consumption percentage as its value. Optional so the form renders no required\n * markers; `Schema.Number` keeps the field context-free (`R = never`) so the struct stays assignable to `Form`.\n */\nconst usageField = (title: string, description: string) =>\n Schema.optional(Schema.Number.annotate({ title, description }));\n\n/**\n * Build the Effect schema (one annotated field per limit) and matching values. Unlimited limits have no\n * value, so their field reads `undefined` and the renderer shows the \"Unlimited\" label instead of a meter.\n */\nconst buildUsageForm = (rows: UsageRow[]) => {\n const fields: Record<string, ReturnType<typeof usageField>> = {};\n const values: Record<string, number> = {};\n rows.forEach((row, index) => {\n const field = `metric_${index}`;\n fields[field] = usageField(row.label, row.caption);\n if (row.percent !== undefined) {\n values[field] = row.percent;\n }\n });\n return { schema: Schema.Struct(fields), values };\n};\n\n/** Non-data states shown as a single `Message`, keyed by message variant (translation keys for the copy). */\nconst STATE_MESSAGES = {\n unavailable: {\n valence: 'warning',\n icon: 'ph--cloud-slash--duotone',\n title: 'usage-unavailable.title',\n description: 'usage-unavailable.description',\n },\n error: {\n valence: 'error',\n icon: 'ph--cloud-x--duotone',\n title: 'usage-offline.title',\n description: 'usage-offline.description',\n },\n empty: {\n valence: 'neutral',\n icon: 'ph--chart-bar--duotone',\n title: 'usage-empty.title',\n description: 'usage-empty.description',\n },\n} as const;\n\n/**\n * Presentational view of profile usage: renders loading/error/unavailable/empty states, or a\n * schema-driven settings form (one read-only field per limit), plus a refresh control and a\n * collapsible raw-response viewer. Pure — all data via props.\n */\nexport const UsageView = ({ state, data, lastUpdated, onRefresh }: UsageViewProps) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n const [rawExpanded, setRawExpanded] = useState(false);\n\n const { schema, values, empty } = useMemo(() => {\n const rows = data ? computeRows(data, t) : [];\n return { ...buildUsageForm(rows), empty: rows.length === 0 };\n }, [data, t]);\n\n // Non-data states resolve to a `Message`; `loading` shows a spinner and `ready` with data shows the form.\n const message =\n state === 'unavailable'\n ? STATE_MESSAGES.unavailable\n : state === 'error'\n ? STATE_MESSAGES.error\n : state === 'ready' && empty\n ? STATE_MESSAGES.empty\n : undefined;\n\n // Render each metric as a meter from its percentage value; unlimited limits (no value) show a label.\n const meterFieldProvider = useCallback<FormFieldProvider>(\n ({ fieldProps: { label, description, getValue } }) => {\n const percent = getValue();\n return (\n <Form.Field standalone label={label} description={description}>\n {typeof percent === 'number' ? (\n <Status.Progress value={percent / 100} label={t('usage-percent-used.label', { percent })} />\n ) : (\n t('usage-unlimited.label')\n )}\n </Form.Field>\n );\n },\n [t],\n );\n\n return (\n <Form.Root variant='settings' layout='static' schema={schema} values={values}>\n <Form.Viewport scroll>\n <Form.Content>\n <Form.FieldSet label={t('usage-section.title')} description={t('usage-section.description')}>\n {message ? (\n <Banner.Root valence={message.valence}>\n <Banner.Title icon={message.icon}>{t(message.title)}</Banner.Title>\n <Banner.Body>{t(message.description)}</Banner.Body>\n </Banner.Root>\n ) : (\n <Form.Fields fieldProvider={meterFieldProvider} />\n )}\n </Form.FieldSet>\n\n {/* {state === 'ready' && data && (\n <Form.FieldSet>\n <Form.Field standalone\n label={\n lastUpdated !== undefined\n ? t('usage-last-updated.label', { time: new Date(lastUpdated).toLocaleTimeString() })\n : t('usage-refresh.label')\n }\n >\n {onRefresh && (\n <IconButton\n iconOnly\n variant='ghost'\n icon='ph--arrow-clockwise--regular'\n label={t('usage-refresh.label')}\n onClick={onRefresh}\n />\n )}\n </Form.Field>\n </Form.FieldSet>\n )} */}\n\n {/* {state === 'ready' && data && (\n <Form.FieldSet>\n <Form.Field standalone label={t('usage-raw-json.label')}>\n <ToggleIconButton\n iconOnly\n variant='ghost'\n active={rawExpanded}\n icon='ph--caret-right--regular'\n label={t('usage-raw-json.label')}\n onClick={() => setRawExpanded((value) => !value)}\n />\n </Form.Field>\n {rawExpanded && <JsonHighlighter data={data} testId='usage-raw-json' />}\n </Form.FieldSet>\n )} */}\n </Form.Content>\n </Form.Viewport>\n </Form.Root>\n );\n};\n\nUsageView.displayName = 'UsageView';\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useState } from 'react';\n\nimport { Context } from '@dxos/context';\nimport { log } from '@dxos/log';\nimport { type GetProfileUsageResponse } from '@dxos/protocols';\nimport * as Hooks from '@dxos/react-ui/Hooks';\n\nimport { useHubHttpClient } from '../../hooks/index.ts';\nimport { UsageView, type UsageViewState } from './UsageView.tsx';\n\n/** State + payload kept together so `ready` always carries data (mirrors the discriminated `UsageViewProps`). */\ntype UsageFetchState =\n | {\n state: Exclude<UsageViewState, 'ready'>;\n }\n | {\n state: 'ready';\n data: GetProfileUsageResponse;\n };\n\n/**\n * Fetches rolling-window profile usage from the hub service and renders it.\n * Connected wrapper around the presentational {@link UsageView}.\n */\nexport const UsageContainer = () => {\n const hubHttp = useHubHttpClient();\n const [fetchState, setFetchState] = useState<UsageFetchState>({ state: 'loading' });\n const [lastUpdated, setLastUpdated] = useState<number | undefined>();\n const [refreshCount, setRefreshCount] = useState(0);\n\n Hooks.useAsyncEffect(async () => {\n if (!hubHttp) {\n setFetchState({ state: 'unavailable' });\n return;\n }\n // Keep prior data visible while refetching; only show the loading state on first load.\n setFetchState((previous) => (previous.state === 'ready' ? previous : { state: 'loading' }));\n try {\n const result = await hubHttp.getProfileUsage(new Context());\n setFetchState({ state: 'ready', data: result });\n setLastUpdated(Date.now());\n } catch (err) {\n log.catch(err);\n setFetchState({ state: 'error' });\n }\n }, [hubHttp, refreshCount]);\n\n const handleRefresh = useCallback(() => setRefreshCount((count) => count + 1), []);\n\n return <UsageView {...fetchState} lastUpdated={lastUpdated} onRefresh={handleRefresh} />;\n};\n\nUsageContainer.displayName = 'UsageContainer';\n"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import * as Capability from "@dxos/app-framework/Capability";
2
2
  import { AccountCache, ClientCapabilities } from "#types";
3
3
  import * as Effect from "effect/Effect";
4
- import { createKvsStore } from "@dxos/effect";
4
+ import * as KvsStore from "@dxos/effect/KvsStore";
5
5
  //#region src/capabilities/account-cache.ts
6
- var account_cache_default = Capability.makeModule(() => Effect.succeed(Capability.contribute(ClientCapabilities.AccountCache, createKvsStore({
6
+ var account_cache_default = Capability.makeModule(() => Effect.succeed(Capability.contribute(ClientCapabilities.AccountCache, KvsStore.make({
7
7
  key: "composer.account",
8
8
  schema: AccountCache.AccountCache,
9
9
  defaultValue: () => ({})
@@ -1 +1 @@
1
- {"version":3,"file":"chunk-account-cache.mjs","names":[],"sources":["../../src/capabilities/account-cache.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport { createKvsStore } from '@dxos/effect';\n\nimport { AccountCache, ClientCapabilities } from '#types';\n\nexport default Capability.makeModule(() =>\n Effect.succeed(\n Capability.contribute(\n ClientCapabilities.AccountCache,\n createKvsStore<AccountCache.AccountCache>({\n key: 'composer.account',\n schema: AccountCache.AccountCache,\n defaultValue: () => ({}),\n }),\n ),\n ),\n);\n"],"mappings":";;;;;AAWA,IAAA,wBAAe,WAAW,iBACxB,OAAO,QACL,WAAW,WACT,mBAAmB,cACnB,eAA0C;CACxC,KAAK;CACL,QAAQ,aAAa;CACrB,qBAAqB,CAAC;AACxB,CAAC,CACH,CACF,CACF"}
1
+ {"version":3,"file":"chunk-account-cache.mjs","names":[],"sources":["../../src/capabilities/account-cache.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as KvsStore from '@dxos/effect/KvsStore';\n\nimport { AccountCache, ClientCapabilities } from '#types';\n\nexport default Capability.makeModule(() =>\n Effect.succeed(\n Capability.contribute(\n ClientCapabilities.AccountCache,\n KvsStore.make<AccountCache.AccountCache>({\n key: 'composer.account',\n schema: AccountCache.AccountCache,\n defaultValue: () => ({}),\n }),\n ),\n ),\n);\n"],"mappings":";;;;;AAWA,IAAA,wBAAe,WAAW,iBACxB,OAAO,QACL,WAAW,WACT,mBAAmB,cACnB,SAAS,KAAgC;CACvC,KAAK;CACL,QAAQ,aAAa;CACrB,qBAAqB,CAAC;AACxB,CAAC,CACH,CACF,CACF"}
@@ -4,8 +4,8 @@ import { Account, ClientCapabilities } from "#types";
4
4
  import * as Effect from "effect/Effect";
5
5
  import * as Option from "effect/Option";
6
6
  import { ClientOperation } from "#operations";
7
- import { meta } from "#meta";
8
7
  import { Identity } from "@dxos/halo";
8
+ import { meta } from "#meta";
9
9
  import * as Operation from "@dxos/compute/Operation";
10
10
  import * as AppGraphBuilder from "@dxos/app-graph/AppGraphBuilder";
11
11
  import * as AppGraphNode from "@dxos/app-graph/AppGraphNode";
@@ -15,6 +15,7 @@ import * as GraphNodeMatcher from "@dxos/graph/GraphNodeMatcher";
15
15
  //#region src/capabilities/app-graph-builder.ts
16
16
  var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function* () {
17
17
  const clientAtom = yield* Capability.atom(ClientCapabilities.Client);
18
+ const hasHub = (clients) => !!clients[0]?.config.values?.runtime?.app?.env?.DX_HUB_URL;
18
19
  const identityServiceAtom = yield* Capability.atom(ClientCapabilities.IdentityService);
19
20
  const extensions = yield* AppGraphBuilder.createExtension({
20
21
  id: "root",
@@ -39,7 +40,7 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
39
40
  const [identityService] = get(identityServiceAtom);
40
41
  const identity = identityService ? Option.getOrUndefined(get(Identity.atom(identityService))) : void 0;
41
42
  const status = get(CreateAtom.fromObservable(client.mesh.networkStatus));
42
- const hub = !!client.config.values?.runtime?.app?.env?.DX_HUB_URL;
43
+ hasHub([client]);
43
44
  return [AppGraphNode.make({
44
45
  id: Account.id,
45
46
  type: meta.profile.key,
@@ -52,67 +53,165 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
52
53
  hue: identity?.data?.hue,
53
54
  emoji: identity?.data?.emoji,
54
55
  status: status.swarm === ConnectionState.OFFLINE ? "error" : "active"
55
- },
56
- nodes: [
57
- AppGraphNode.make({
58
- id: Account.Profile,
59
- data: Account.Profile,
60
- type: meta.profile.key,
61
- properties: {
62
- label: ["profile.label", { ns: meta.profile.key }],
63
- icon: "ph--user--regular"
64
- }
65
- }),
66
- ...hub ? [AppGraphNode.make({
67
- id: Account.Account,
68
- data: Account.Account,
69
- type: meta.profile.key,
70
- properties: {
71
- label: ["account-panel.label", { ns: meta.profile.key }],
72
- icon: "ph--identification-card--regular"
73
- }
74
- })] : [],
75
- AppGraphNode.make({
76
- id: Account.Security,
77
- data: Account.Security,
78
- type: meta.profile.key,
79
- properties: {
80
- label: ["security.label", { ns: meta.profile.key }],
81
- icon: "ph--key--regular"
82
- }
83
- }),
84
- AppGraphNode.make({
85
- id: Account.Devices,
86
- data: Account.Devices,
87
- type: meta.profile.key,
88
- properties: {
89
- label: ["devices.label", { ns: meta.profile.key }],
90
- icon: "ph--devices--regular",
91
- testId: "clientPlugin.devices"
92
- }
93
- }),
94
- ...hub ? [AppGraphNode.make({
95
- id: Account.Invitations,
96
- data: Account.Invitations,
97
- type: meta.profile.key,
98
- properties: {
99
- label: ["invitations-panel.label", { ns: meta.profile.key }],
100
- icon: "ph--ticket--regular"
101
- }
102
- }), AppGraphNode.make({
103
- id: Account.Usage,
104
- data: Account.Usage,
105
- type: meta.profile.key,
106
- properties: {
107
- label: ["usage-panel.label", { ns: meta.profile.key }],
108
- icon: "ph--chart-bar--regular"
109
- }
110
- })] : []
111
- ]
56
+ }
57
+ })];
58
+ }).pipe(Effect.orDie)
59
+ });
60
+ const accountProfile = yield* AppGraphBuilder.createExtension({
61
+ id: "accountProfile",
62
+ url: {
63
+ key: Account.Profile,
64
+ kind: "singleton",
65
+ path: []
66
+ },
67
+ match: GraphNodeMatcher.whenId(Account.workspacePath),
68
+ connector: (_node, get) => Effect.gen(function* () {
69
+ return [AppGraphNode.make({
70
+ id: Account.Profile,
71
+ data: Account.path(Account.Profile),
72
+ type: meta.profile.key,
73
+ properties: {
74
+ label: ["profile.label", { ns: meta.profile.key }],
75
+ icon: "ph--user--regular",
76
+ testId: "clientPlugin.profile"
77
+ }
78
+ })];
79
+ }).pipe(Effect.orDie)
80
+ });
81
+ const accountAccount = yield* AppGraphBuilder.createExtension({
82
+ id: "accountAccount",
83
+ url: {
84
+ key: Account.Account,
85
+ kind: "singleton",
86
+ path: []
87
+ },
88
+ match: GraphNodeMatcher.whenId(Account.workspacePath),
89
+ connector: (_node, get) => Effect.gen(function* () {
90
+ if (!hasHub(get(clientAtom))) return [];
91
+ return [AppGraphNode.make({
92
+ id: Account.Account,
93
+ data: Account.path(Account.Account),
94
+ type: meta.profile.key,
95
+ properties: {
96
+ label: ["account-panel.label", { ns: meta.profile.key }],
97
+ icon: "ph--identification-card--regular"
98
+ }
99
+ })];
100
+ }).pipe(Effect.orDie)
101
+ });
102
+ const accountSecurity = yield* AppGraphBuilder.createExtension({
103
+ id: "accountSecurity",
104
+ url: {
105
+ key: Account.Security,
106
+ kind: "singleton",
107
+ path: []
108
+ },
109
+ match: GraphNodeMatcher.whenId(Account.workspacePath),
110
+ connector: (_node, get) => Effect.gen(function* () {
111
+ return [AppGraphNode.make({
112
+ id: Account.Security,
113
+ data: Account.path(Account.Security),
114
+ type: meta.profile.key,
115
+ properties: {
116
+ label: ["security.label", { ns: meta.profile.key }],
117
+ icon: "ph--key--regular",
118
+ testId: "clientPlugin.security"
119
+ }
120
+ })];
121
+ }).pipe(Effect.orDie)
122
+ });
123
+ const accountDevices = yield* AppGraphBuilder.createExtension({
124
+ id: "accountDevices",
125
+ url: {
126
+ key: Account.Devices,
127
+ kind: "singleton",
128
+ path: []
129
+ },
130
+ match: GraphNodeMatcher.whenId(Account.workspacePath),
131
+ connector: (_node, get) => Effect.gen(function* () {
132
+ return [AppGraphNode.make({
133
+ id: Account.Devices,
134
+ data: Account.path(Account.Devices),
135
+ type: meta.profile.key,
136
+ properties: {
137
+ label: ["devices.label", { ns: meta.profile.key }],
138
+ icon: "ph--devices--regular",
139
+ testId: "clientPlugin.devices"
140
+ }
141
+ })];
142
+ }).pipe(Effect.orDie)
143
+ });
144
+ const accountContacts = yield* AppGraphBuilder.createExtension({
145
+ id: "accountContacts",
146
+ url: {
147
+ key: Account.Contacts,
148
+ kind: "singleton",
149
+ path: []
150
+ },
151
+ match: GraphNodeMatcher.whenId(Account.workspacePath),
152
+ connector: () => Effect.succeed([AppGraphNode.make({
153
+ id: Account.Contacts,
154
+ data: Account.path(Account.Contacts),
155
+ type: meta.profile.key,
156
+ properties: {
157
+ label: ["contacts.label", { ns: meta.profile.key }],
158
+ icon: "ph--address-book--regular",
159
+ testId: "clientPlugin.contacts"
160
+ }
161
+ })])
162
+ });
163
+ const accountInvitations = yield* AppGraphBuilder.createExtension({
164
+ id: "accountInvitations",
165
+ url: {
166
+ key: Account.Invitations,
167
+ kind: "singleton",
168
+ path: []
169
+ },
170
+ match: GraphNodeMatcher.whenId(Account.workspacePath),
171
+ connector: (_node, get) => Effect.gen(function* () {
172
+ if (!hasHub(get(clientAtom))) return [];
173
+ return [AppGraphNode.make({
174
+ id: Account.Invitations,
175
+ data: Account.path(Account.Invitations),
176
+ type: meta.profile.key,
177
+ properties: {
178
+ label: ["invitations-panel.label", { ns: meta.profile.key }],
179
+ icon: "ph--ticket--regular"
180
+ }
181
+ })];
182
+ }).pipe(Effect.orDie)
183
+ });
184
+ const accountUsage = yield* AppGraphBuilder.createExtension({
185
+ id: "accountUsage",
186
+ url: {
187
+ key: Account.Usage,
188
+ kind: "singleton",
189
+ path: []
190
+ },
191
+ match: GraphNodeMatcher.whenId(Account.workspacePath),
192
+ connector: (_node, get) => Effect.gen(function* () {
193
+ if (!hasHub(get(clientAtom))) return [];
194
+ return [AppGraphNode.make({
195
+ id: Account.Usage,
196
+ data: Account.path(Account.Usage),
197
+ type: meta.profile.key,
198
+ properties: {
199
+ label: ["usage-panel.label", { ns: meta.profile.key }],
200
+ icon: "ph--chart-bar--regular"
201
+ }
112
202
  })];
113
203
  }).pipe(Effect.orDie)
114
204
  });
115
- return Capability.contribute(AppCapabilities.AppGraphBuilder, extensions);
205
+ return Capability.contribute(AppCapabilities.AppGraphBuilder, [
206
+ ...extensions,
207
+ ...accountProfile,
208
+ ...accountAccount,
209
+ ...accountSecurity,
210
+ ...accountDevices,
211
+ ...accountContacts,
212
+ ...accountInvitations,
213
+ ...accountUsage
214
+ ]);
116
215
  }));
117
216
  //#endregion
118
217
  export { app_graph_builder_default as default };
@@ -1 +1 @@
1
- {"version":3,"file":"chunk-app-graph-builder.mjs","names":[],"sources":["../../src/capabilities/app-graph-builder.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Option from 'effect/Option';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraphBuilder from '@dxos/app-graph/AppGraphBuilder';\nimport * as AppGraphNode from '@dxos/app-graph/AppGraphNode';\nimport * as CreateAtom from '@dxos/app-graph/CreateAtom';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport { ConnectionState } from '@dxos/client/mesh';\nimport * as Operation from '@dxos/compute/Operation';\nimport * as GraphNodeMatcher from '@dxos/graph/GraphNodeMatcher';\nimport { Identity } from '@dxos/halo';\n\nimport { meta } from '#meta';\nimport { ClientOperation } from '#operations';\nimport { Account, ClientCapabilities } from '#types';\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n // Read the client through its atom so the extension establishes a reactive dependency:\n // the connector may evaluate before the client module finishes activating (dependency\n // modules contribute individually, not batched per wave) and re-evaluates when it lands.\n const clientAtom = yield* Capability.atom(ClientCapabilities.Client);\n const identityServiceAtom = yield* Capability.atom(ClientCapabilities.IdentityService);\n const extensions = yield* AppGraphBuilder.createExtension({\n id: 'root',\n match: GraphNodeMatcher.whenRoot,\n actions: () =>\n Effect.succeed([\n {\n id: 'openUserAccount',\n data: () => Operation.invoke(ClientOperation.ShareIdentity),\n properties: {\n label: ['open-user-account.label', { ns: meta.profile.key }],\n icon: 'ph--user--regular',\n disposition: 'menu',\n keyBinding: {\n macos: 'meta+shift+.',\n // TODO(wittjosiah): Test on windows to see if it behaves the same as linux.\n windows: 'alt+shift+.',\n linux: 'alt+shift+>',\n },\n },\n },\n ]),\n connector: (node, get) =>\n Effect.gen(function* () {\n const [client] = get(clientAtom);\n if (!client) {\n return [];\n }\n const [identityService] = get(identityServiceAtom);\n const identity = identityService ? Option.getOrUndefined(get(Identity.atom(identityService))) : undefined;\n const status = get(CreateAtom.fromObservable(client.mesh.networkStatus));\n // Account, invitations, and usage are all hub-service reads; without a hub URL there is\n // no `HubHttpClient` capability and those panels render empty shells forever.\n const hub = !!client.config.values?.runtime?.app?.env?.DX_HUB_URL;\n\n return [\n AppGraphNode.make({\n id: Account.id,\n type: meta.profile.key,\n properties: {\n label: ['account.label', { ns: meta.profile.key }],\n icon: 'ph--user--regular',\n disposition: 'user-account',\n testId: 'clientPlugin.account',\n // NOTE: This currently needs to be the identity key because the fallback is generated from hex.\n userId: identity?.identityKey,\n hue: identity?.data?.hue,\n emoji: identity?.data?.emoji,\n status: status.swarm === ConnectionState.OFFLINE ? 'error' : 'active',\n },\n nodes: [\n AppGraphNode.make({\n id: Account.Profile,\n data: Account.Profile,\n type: meta.profile.key,\n properties: {\n label: ['profile.label', { ns: meta.profile.key }],\n icon: 'ph--user--regular',\n },\n }),\n ...(hub\n ? [\n AppGraphNode.make({\n id: Account.Account,\n data: Account.Account,\n type: meta.profile.key,\n properties: {\n label: ['account-panel.label', { ns: meta.profile.key }],\n icon: 'ph--identification-card--regular',\n },\n }),\n ]\n : []),\n AppGraphNode.make({\n id: Account.Security,\n data: Account.Security,\n type: meta.profile.key,\n properties: {\n label: ['security.label', { ns: meta.profile.key }],\n icon: 'ph--key--regular',\n },\n }),\n AppGraphNode.make({\n id: Account.Devices,\n data: Account.Devices,\n type: meta.profile.key,\n properties: {\n label: ['devices.label', { ns: meta.profile.key }],\n icon: 'ph--devices--regular',\n testId: 'clientPlugin.devices',\n },\n }),\n ...(hub\n ? [\n AppGraphNode.make({\n id: Account.Invitations,\n data: Account.Invitations,\n type: meta.profile.key,\n properties: {\n label: ['invitations-panel.label', { ns: meta.profile.key }],\n icon: 'ph--ticket--regular',\n },\n }),\n AppGraphNode.make({\n id: Account.Usage,\n data: Account.Usage,\n type: meta.profile.key,\n properties: {\n label: ['usage-panel.label', { ns: meta.profile.key }],\n icon: 'ph--chart-bar--regular',\n },\n }),\n ]\n : []),\n ],\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n return Capability.contribute(AppCapabilities.AppGraphBuilder, extensions);\n }),\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"chunk-app-graph-builder.mjs","names":[],"sources":["../../src/capabilities/app-graph-builder.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Option from 'effect/Option';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraphBuilder from '@dxos/app-graph/AppGraphBuilder';\nimport * as AppGraphNode from '@dxos/app-graph/AppGraphNode';\nimport * as CreateAtom from '@dxos/app-graph/CreateAtom';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport { type Client } from '@dxos/client';\nimport { ConnectionState } from '@dxos/client/mesh';\nimport * as Operation from '@dxos/compute/Operation';\nimport * as GraphNodeMatcher from '@dxos/graph/GraphNodeMatcher';\nimport { Identity } from '@dxos/halo';\n\nimport { meta } from '#meta';\nimport { ClientOperation } from '#operations';\nimport { Account, ClientCapabilities } from '#types';\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n // Read the client through its atom so the extension establishes a reactive dependency:\n // the connector may evaluate before the client module finishes activating (dependency\n // modules contribute individually, not batched per wave) and re-evaluates when it lands.\n const clientAtom = yield* Capability.atom(ClientCapabilities.Client);\n // Panels backed by hub services render an empty shell without one, so they contribute no node.\n const hasHub = (clients: readonly Client[]): boolean => !!clients[0]?.config.values?.runtime?.app?.env?.DX_HUB_URL;\n const identityServiceAtom = yield* Capability.atom(ClientCapabilities.IdentityService);\n const extensions = yield* AppGraphBuilder.createExtension({\n id: 'root',\n match: GraphNodeMatcher.whenRoot,\n actions: () =>\n Effect.succeed([\n {\n id: 'openUserAccount',\n data: () => Operation.invoke(ClientOperation.ShareIdentity),\n properties: {\n label: ['open-user-account.label', { ns: meta.profile.key }],\n icon: 'ph--user--regular',\n disposition: 'menu',\n keyBinding: {\n macos: 'meta+shift+.',\n // TODO(wittjosiah): Test on windows to see if it behaves the same as linux.\n windows: 'alt+shift+.',\n linux: 'alt+shift+>',\n },\n },\n },\n ]),\n connector: (node, get) =>\n Effect.gen(function* () {\n const [client] = get(clientAtom);\n if (!client) {\n return [];\n }\n const [identityService] = get(identityServiceAtom);\n const identity = identityService ? Option.getOrUndefined(get(Identity.atom(identityService))) : undefined;\n const status = get(CreateAtom.fromObservable(client.mesh.networkStatus));\n const hub = hasHub([client]);\n\n return [\n AppGraphNode.make({\n id: Account.id,\n type: meta.profile.key,\n properties: {\n label: ['account.label', { ns: meta.profile.key }],\n icon: 'ph--user--regular',\n disposition: 'user-account',\n testId: 'clientPlugin.account',\n // NOTE: This currently needs to be the identity key because the fallback is generated from hex.\n userId: identity?.identityKey,\n hue: identity?.data?.hue,\n emoji: identity?.data?.emoji,\n status: status.swarm === ConnectionState.OFFLINE ? 'error' : 'active',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n const accountProfile = yield* AppGraphBuilder.createExtension({\n id: 'accountProfile',\n url: { key: Account.Profile, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: (_node, get) =>\n Effect.gen(function* () {\n return [\n AppGraphNode.make({\n id: Account.Profile,\n data: Account.path(Account.Profile),\n type: meta.profile.key,\n properties: {\n label: ['profile.label', { ns: meta.profile.key }],\n icon: 'ph--user--regular',\n testId: 'clientPlugin.profile',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n const accountAccount = yield* AppGraphBuilder.createExtension({\n id: 'accountAccount',\n url: { key: Account.Account, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: (_node, get) =>\n Effect.gen(function* () {\n if (!hasHub(get(clientAtom))) {\n return [];\n }\n return [\n AppGraphNode.make({\n id: Account.Account,\n data: Account.path(Account.Account),\n type: meta.profile.key,\n properties: {\n label: ['account-panel.label', { ns: meta.profile.key }],\n icon: 'ph--identification-card--regular',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n const accountSecurity = yield* AppGraphBuilder.createExtension({\n id: 'accountSecurity',\n url: { key: Account.Security, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: (_node, get) =>\n Effect.gen(function* () {\n return [\n AppGraphNode.make({\n id: Account.Security,\n data: Account.path(Account.Security),\n type: meta.profile.key,\n properties: {\n label: ['security.label', { ns: meta.profile.key }],\n icon: 'ph--key--regular',\n testId: 'clientPlugin.security',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n const accountDevices = yield* AppGraphBuilder.createExtension({\n id: 'accountDevices',\n url: { key: Account.Devices, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: (_node, get) =>\n Effect.gen(function* () {\n return [\n AppGraphNode.make({\n id: Account.Devices,\n data: Account.path(Account.Devices),\n type: meta.profile.key,\n properties: {\n label: ['devices.label', { ns: meta.profile.key }],\n icon: 'ph--devices--regular',\n testId: 'clientPlugin.devices',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n const accountContacts = yield* AppGraphBuilder.createExtension({\n id: 'accountContacts',\n url: { key: Account.Contacts, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: () =>\n Effect.succeed([\n AppGraphNode.make({\n id: Account.Contacts,\n data: Account.path(Account.Contacts),\n type: meta.profile.key,\n properties: {\n label: ['contacts.label', { ns: meta.profile.key }],\n icon: 'ph--address-book--regular',\n testId: 'clientPlugin.contacts',\n },\n }),\n ]),\n });\n\n const accountInvitations = yield* AppGraphBuilder.createExtension({\n id: 'accountInvitations',\n url: { key: Account.Invitations, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: (_node, get) =>\n Effect.gen(function* () {\n if (!hasHub(get(clientAtom))) {\n return [];\n }\n return [\n AppGraphNode.make({\n id: Account.Invitations,\n data: Account.path(Account.Invitations),\n type: meta.profile.key,\n properties: {\n label: ['invitations-panel.label', { ns: meta.profile.key }],\n icon: 'ph--ticket--regular',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n const accountUsage = yield* AppGraphBuilder.createExtension({\n id: 'accountUsage',\n url: { key: Account.Usage, kind: 'singleton', path: [] },\n match: GraphNodeMatcher.whenId(Account.workspacePath),\n connector: (_node, get) =>\n Effect.gen(function* () {\n if (!hasHub(get(clientAtom))) {\n return [];\n }\n return [\n AppGraphNode.make({\n id: Account.Usage,\n data: Account.path(Account.Usage),\n type: meta.profile.key,\n properties: {\n label: ['usage-panel.label', { ns: meta.profile.key }],\n icon: 'ph--chart-bar--regular',\n },\n }),\n ];\n }).pipe(Effect.orDie),\n });\n\n return Capability.contribute(AppCapabilities.AppGraphBuilder, [\n ...extensions,\n ...accountProfile,\n ...accountAccount,\n ...accountSecurity,\n ...accountDevices,\n ...accountContacts,\n ...accountInvitations,\n ...accountUsage,\n ]);\n }),\n);\n"],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import * as Capability from "@dxos/app-framework/Capability";
2
+ import { ClientCapabilities } from "#types";
3
+ import * as Effect from "effect/Effect";
4
+ //#region src/capabilities/client-services.ts
5
+ /**
6
+ * Exposes the pieces of the client that plugins read directly — config, the EDGE HTTP client and
7
+ * the ECHO graph — as capabilities, so those plugins need not depend on `@dxos/client`.
8
+ */
9
+ var client_services_default = Capability.makeModule(Effect.fnUntraced(function* () {
10
+ const client = yield* ClientCapabilities.Client;
11
+ const edgeUrl = client.config.get("runtime.services.edge.url");
12
+ return [
13
+ Capability.contribute(ClientCapabilities.Config, client.config),
14
+ Capability.contribute(ClientCapabilities.Hypergraph, client.graph),
15
+ ...edgeUrl ? [Capability.contribute(ClientCapabilities.EdgeHttpClient, client.edge.http)] : []
16
+ ];
17
+ }));
18
+ //#endregion
19
+ export { client_services_default as default };
20
+
21
+ //# sourceMappingURL=chunk-client-services.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-client-services.mjs","names":[],"sources":["../../src/capabilities/client-services.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capability from '@dxos/app-framework/Capability';\n\nimport { ClientCapabilities } from '#types';\n\n/**\n * Exposes the pieces of the client that plugins read directly — config, the EDGE HTTP client and\n * the ECHO graph — as capabilities, so those plugins need not depend on `@dxos/client`.\n */\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n const client = yield* ClientCapabilities.Client;\n const edgeUrl = client.config.get('runtime.services.edge.url');\n return [\n Capability.contribute(ClientCapabilities.Config, client.config),\n Capability.contribute(ClientCapabilities.Hypergraph, client.graph),\n ...(edgeUrl ? [Capability.contribute(ClientCapabilities.EdgeHttpClient, client.edge.http)] : []),\n ];\n }),\n);\n"],"mappings":";;;;;;;;AAcA,IAAA,0BAAe,WAAW,WACxB,OAAO,WAAW,aAAa;CAC7B,MAAM,SAAS,OAAO,mBAAmB;CACzC,MAAM,UAAU,OAAO,OAAO,IAAI,2BAA2B;CAC7D,OAAO;EACL,WAAW,WAAW,mBAAmB,QAAQ,OAAO,MAAM;EAC9D,WAAW,WAAW,mBAAmB,YAAY,OAAO,KAAK;EACjE,GAAI,UAAU,CAAC,WAAW,WAAW,mBAAmB,gBAAgB,OAAO,KAAK,IAAI,CAAC,IAAI,CAAC;CAChG;AACF,CAAC,CACH"}
@@ -2,24 +2,27 @@ import * as Capabilities from "@dxos/app-framework/Capabilities";
2
2
  import * as Capability from "@dxos/app-framework/Capability";
3
3
  import { ClientCapabilities, ClientEvents } from "#types";
4
4
  import * as Effect from "effect/Effect";
5
- import { Client, ClientService } from "@dxos/client";
5
+ import { Client, ClientService, fromClient } from "@dxos/client";
6
+ import { BaseError } from "@dxos/errors";
6
7
  import * as Plugin from "@dxos/app-framework/Plugin";
7
8
  import { INITIALIZE_TIMEOUT } from "@dxos/client-protocol";
8
9
  import * as Cause from "effect/Cause";
9
10
  import { log } from "@dxos/log";
10
11
  import * as Layer from "effect/Layer";
11
- import { EffectEx } from "@dxos/effect";
12
12
  import * as Exit from "effect/Exit";
13
+ import * as EffectEx from "@dxos/effect/EffectEx";
13
14
  import { makeIdentityService, makeSpaceService } from "@dxos/halo-adapter-client";
14
15
  //#region src/capabilities/client.ts
15
16
  var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-client/src/capabilities/client.ts";
16
- var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client: hostClient, onClientInitialized, onClientInitializationError, onSpacesReady, initializeTimeout = INITIALIZE_TIMEOUT, awaitInitialization = false, ...options }) {
17
+ /** The client did not finish initializing inside the configured timeout. */
18
+ var ClientInitError = class extends BaseError.extend("ClientInitError", "Client failed to initialize.") {};
19
+ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client: hostClient, onClientInitialized, onClientInitializationError, onSpacesAvailable, initializeTimeout = INITIALIZE_TIMEOUT, awaitInitialization = false, ...options }) {
17
20
  const capabilityManager = yield* Capability.Service;
18
21
  const pluginManager = yield* Plugin.Service;
19
22
  log(hostClient ? "adopting host client" : "creating client", void 0, {
20
23
  "~LogMeta": "~LogMeta",
21
24
  F: __dxlog_file,
22
- L: 39,
25
+ L: 43,
23
26
  S: this
24
27
  });
25
28
  const client = hostClient ?? new Client(options);
@@ -27,7 +30,7 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
27
30
  log("initializing client (forked)...", void 0, {
28
31
  "~LogMeta": "~LogMeta",
29
32
  F: __dxlog_file,
30
- L: 45,
33
+ L: 49,
31
34
  S: this
32
35
  });
33
36
  let subscription;
@@ -35,14 +38,14 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
35
38
  log.info("client capability: destroying client", void 0, {
36
39
  "~LogMeta": "~LogMeta",
37
40
  F: __dxlog_file,
38
- L: 54,
41
+ L: 58,
39
42
  S: this
40
43
  });
41
44
  subscription?.unsubscribe();
42
45
  yield* Effect.tryPromise(() => client.destroy()).pipe(Effect.catch((error) => Effect.sync(() => log.warn("client destroy failed", { error: String(error) }, {
43
46
  "~LogMeta": "~LogMeta",
44
47
  F: __dxlog_file,
45
- L: 58,
48
+ L: 62,
46
49
  S: this
47
50
  }))));
48
51
  }));
@@ -52,7 +55,7 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
52
55
  log("client.initialize() returned successfully", void 0, {
53
56
  "~LogMeta": "~LogMeta",
54
57
  F: __dxlog_file,
55
- L: 73,
58
+ L: 77,
56
59
  S: this
57
60
  });
58
61
  if (onClientInitialized) yield* onClientInitialized({ client });
@@ -60,7 +63,7 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
60
63
  log("called client initialized callback", void 0, {
61
64
  "~LogMeta": "~LogMeta",
62
65
  F: __dxlog_file,
63
- L: 78,
66
+ L: 82,
64
67
  S: this
65
68
  });
66
69
  yield* Plugin.activate(ClientEvents.Initialized);
@@ -73,20 +76,20 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
73
76
  log.info("client reconnected, reloading to re-establish session", void 0, {
74
77
  "~LogMeta": "~LogMeta",
75
78
  F: __dxlog_file,
76
- L: 104,
79
+ L: 108,
77
80
  S: this
78
81
  });
79
82
  if (client.resetting) window.location.href = window.location.origin;
80
83
  else window.location.reload();
81
84
  });
82
- let spacesReadyFired = false;
85
+ let spacesAvailableFired = false;
83
86
  subscription = client.spaces.subscribe(async () => {
84
- if (!spacesReadyFired) {
85
- spacesReadyFired = true;
87
+ if (!spacesAvailableFired) {
88
+ spacesAvailableFired = true;
86
89
  performance.mark("milestone:spaces-ready");
87
90
  const exit = await Effect.gen(function* () {
88
- yield* Plugin.activate(ClientEvents.SpacesReady);
89
- if (onSpacesReady) yield* onSpacesReady({ client });
91
+ yield* Plugin.activate(ClientEvents.SpacesAvailable);
92
+ if (onSpacesAvailable) yield* onSpacesAvailable({ client });
90
93
  }).pipe(Effect.provideService(Capability.Service, capabilityManager), Effect.provideService(Plugin.Service, pluginManager), Effect.runPromiseExit);
91
94
  if (Exit.isFailure(exit) && !Cause.hasInterruptsOnly(exit.cause)) EffectEx.throwCause(exit.cause);
92
95
  }
@@ -95,7 +98,7 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
95
98
  log.error("client initialization failed", { error: String(error) }, {
96
99
  "~LogMeta": "~LogMeta",
97
100
  F: __dxlog_file,
98
- L: 141,
101
+ L: 145,
99
102
  S: this
100
103
  });
101
104
  if (onClientInitializationError) yield* onClientInitializationError({ error });
@@ -103,21 +106,25 @@ var client_default = Capability.makeModule(Effect.fnUntraced(function* ({ client
103
106
  log("client capability ready (initialization in flight)", void 0, {
104
107
  "~LogMeta": "~LogMeta",
105
108
  F: __dxlog_file,
106
- L: 155,
109
+ L: 159,
107
110
  S: this
108
111
  });
109
112
  const clientServiceLayer = awaitInitialization ? Layer.effect(ClientService, Effect.tryPromise({
110
113
  try: () => client.waitUntilInitialized({ timeout: initializeTimeout }),
111
- catch: (error) => /* @__PURE__ */ new Error(`Client failed to initialize within ${initializeTimeout}ms: ${String(error)}`)
112
- }).pipe(Effect.as(client))) : ClientService.fromClient(client);
114
+ catch: (error) => new ClientInitError({
115
+ context: { initializeTimeout },
116
+ cause: error
117
+ })
118
+ }).pipe(Effect.as(client))) : fromClient(client);
113
119
  return [
114
120
  Capability.contribute(ClientCapabilities.Client, client),
121
+ Capability.contribute(ClientCapabilities.InitializeTimeout, initializeTimeout),
115
122
  Capability.contribute(Capabilities.Layer, clientServiceLayer),
116
123
  Capability.contribute(ClientCapabilities.IdentityService, makeIdentityService(client)),
117
124
  Capability.contribute(ClientCapabilities.SpaceService, makeSpaceService(client))
118
125
  ];
119
126
  }));
120
127
  //#endregion
121
- export { client_default as default };
128
+ export { ClientInitError, client_default as default };
122
129
 
123
130
  //# sourceMappingURL=chunk-client.mjs.map