@dxos/plugin-client 0.9.0 → 0.9.1-staging.ee54ba693a

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 (236) hide show
  1. package/dist/lib/neutral/{AccountContainer-FZ3IC6H4.mjs → AccountContainer-7SF53UON.mjs} +17 -13
  2. package/dist/lib/neutral/AccountContainer-7SF53UON.mjs.map +7 -0
  3. package/dist/lib/neutral/ClientPlugin.node.mjs +477 -370
  4. package/dist/lib/neutral/ClientPlugin.node.mjs.map +4 -4
  5. package/dist/lib/neutral/{DevicesContainer-6MWNUC3I.mjs → DevicesContainer-PRWIN36N.mjs} +36 -27
  6. package/dist/lib/neutral/DevicesContainer-PRWIN36N.mjs.map +7 -0
  7. package/dist/lib/neutral/{InvitationsContainer-ME722VKS.mjs → InvitationsContainer-BI5RAWET.mjs} +43 -32
  8. package/dist/lib/neutral/InvitationsContainer-BI5RAWET.mjs.map +7 -0
  9. package/dist/lib/neutral/{JoinDialog-2NXAKPLP.mjs → JoinDialog-4BWV4CYB.mjs} +2 -2
  10. package/dist/lib/neutral/JoinDialog-4BWV4CYB.mjs.map +7 -0
  11. package/dist/lib/neutral/{ProfileContainer-VPX3FPWG.mjs → ProfileContainer-YEAYOTX5.mjs} +22 -21
  12. package/dist/lib/neutral/ProfileContainer-YEAYOTX5.mjs.map +7 -0
  13. package/dist/lib/neutral/{RecoveryCodeDialog-EWHB6U5T.mjs → RecoveryCodeDialog-7EPNKCLB.mjs} +2 -2
  14. package/dist/lib/neutral/RecoveryCodeDialog-7EPNKCLB.mjs.map +7 -0
  15. package/dist/lib/neutral/{RecoveryCredentialsContainer-IPBGDMIA.mjs → RecoveryCredentialsContainer-6BZ2IWX7.mjs} +24 -15
  16. package/dist/lib/neutral/RecoveryCredentialsContainer-6BZ2IWX7.mjs.map +7 -0
  17. package/dist/lib/neutral/UsageContainer-2DWCVVE4.mjs +241 -0
  18. package/dist/lib/neutral/UsageContainer-2DWCVVE4.mjs.map +7 -0
  19. package/dist/lib/neutral/account-cache-YVQKLNV2.mjs +16 -0
  20. package/dist/lib/neutral/account-cache-YVQKLNV2.mjs.map +7 -0
  21. package/dist/lib/neutral/{app-graph-builder-A74W7C36.mjs → app-graph-builder-RVXTD6OE.mjs} +30 -16
  22. package/dist/lib/neutral/app-graph-builder-RVXTD6OE.mjs.map +7 -0
  23. package/dist/lib/neutral/capabilities/index.mjs +6 -6
  24. package/dist/lib/neutral/capabilities/node.mjs +3 -3
  25. package/dist/lib/neutral/chunk-6G4KZLBG.mjs +28 -0
  26. package/dist/lib/neutral/chunk-6G4KZLBG.mjs.map +7 -0
  27. package/dist/lib/neutral/{chunk-D6HPCLTS.mjs → chunk-7DEIKHB7.mjs} +16 -2
  28. package/dist/lib/neutral/chunk-7DEIKHB7.mjs.map +7 -0
  29. package/dist/lib/neutral/chunk-A7WDDIWY.mjs +162 -0
  30. package/dist/lib/neutral/chunk-A7WDDIWY.mjs.map +7 -0
  31. package/dist/lib/neutral/chunk-GSKMAS3S.mjs +13 -0
  32. package/dist/lib/neutral/chunk-GSKMAS3S.mjs.map +7 -0
  33. package/dist/lib/neutral/{chunk-JEF2FQGB.mjs → chunk-JY35S2CN.mjs} +2 -2
  34. package/dist/lib/neutral/{chunk-JEF2FQGB.mjs.map → chunk-JY35S2CN.mjs.map} +1 -1
  35. package/dist/lib/neutral/chunk-ZFABGG2E.mjs +8 -0
  36. package/dist/lib/neutral/{chunk-NTVDGDQ3.mjs.map → chunk-ZFABGG2E.mjs.map} +2 -2
  37. package/dist/lib/neutral/containers/index.mjs +10 -8
  38. package/dist/lib/neutral/containers/index.mjs.map +3 -3
  39. package/dist/lib/neutral/{create-agent-6HLW4D3A.mjs → create-agent-6UKJMZS5.mjs} +3 -3
  40. package/dist/lib/neutral/{create-identity-JIWAR5GW.mjs → create-identity-ULCRB3YH.mjs} +3 -3
  41. package/dist/lib/neutral/{create-passkey-FOXEMXGF.mjs → create-passkey-I7VDS3AC.mjs} +7 -7
  42. package/dist/lib/neutral/create-passkey-I7VDS3AC.mjs.map +7 -0
  43. package/dist/lib/neutral/{create-recovery-code-ZWDKLPH4.mjs → create-recovery-code-DH2B6EGP.mjs} +4 -4
  44. package/dist/lib/neutral/index.mjs +6 -4
  45. package/dist/lib/neutral/{join-identity-QEQFAE2S.mjs → join-identity-PJCHDNLH.mjs} +3 -3
  46. package/dist/lib/neutral/{layer-specs-CQLXQBQJ.mjs → layer-specs-YI7BVWKZ.mjs} +6 -8
  47. package/dist/lib/neutral/layer-specs-YI7BVWKZ.mjs.map +7 -0
  48. package/dist/lib/neutral/meta.json +1 -1
  49. package/dist/lib/neutral/meta.mjs +1 -1
  50. package/dist/lib/neutral/{navigation-handler-LU26CDFR.mjs → navigation-handler-MQ6MZXLX.mjs} +3 -3
  51. package/dist/lib/neutral/open-usage-OJVTPGOY.mjs +27 -0
  52. package/dist/lib/neutral/open-usage-OJVTPGOY.mjs.map +7 -0
  53. package/dist/lib/neutral/operations/index.mjs +2 -2
  54. package/dist/lib/neutral/plugin.mjs +3 -3
  55. package/dist/lib/neutral/{react-context-B5LXMHVM.mjs → react-context-V74T6JOJ.mjs} +2 -2
  56. package/dist/lib/neutral/{react-context-B5LXMHVM.mjs.map → react-context-V74T6JOJ.mjs.map} +3 -3
  57. package/dist/lib/neutral/{react-surface-DEKGWTCD.mjs → react-surface-HPXRA65U.mjs} +8 -3
  58. package/dist/lib/neutral/react-surface-HPXRA65U.mjs.map +7 -0
  59. package/dist/lib/neutral/{recover-identity-JNFKLCUD.mjs → recover-identity-B7YM2BR4.mjs} +3 -3
  60. package/dist/lib/neutral/{redeem-passkey-4SBAI4AG.mjs → redeem-passkey-TYP4XLHO.mjs} +10 -10
  61. package/dist/lib/neutral/redeem-passkey-TYP4XLHO.mjs.map +7 -0
  62. package/dist/lib/neutral/{redeem-token-POBD6TMN.mjs → redeem-token-2J33R3PV.mjs} +3 -3
  63. package/dist/lib/neutral/{reset-storage-LQKUV5RA.mjs → reset-storage-K47HZTGP.mjs} +3 -3
  64. package/dist/lib/neutral/{share-identity-KNQ2XNXV.mjs → share-identity-TOROBLWL.mjs} +6 -6
  65. package/dist/lib/neutral/share-identity-TOROBLWL.mjs.map +7 -0
  66. package/dist/lib/neutral/testing/index.mjs +2 -2
  67. package/dist/lib/neutral/testing/index.mjs.map +3 -3
  68. package/dist/lib/neutral/translations.mjs +24 -1
  69. package/dist/lib/neutral/translations.mjs.map +3 -3
  70. package/dist/lib/neutral/types/index.mjs +3 -1
  71. package/dist/types/dx.config.d.ts +28 -0
  72. package/dist/types/dx.config.d.ts.map +1 -0
  73. package/dist/types/src/capabilities/account-cache.d.ts +1 -31
  74. package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -2
  75. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  76. package/dist/types/src/capabilities/client.d.ts +1 -2
  77. package/dist/types/src/capabilities/client.d.ts.map +1 -1
  78. package/dist/types/src/capabilities/hub-http-client.d.ts +1 -2
  79. package/dist/types/src/capabilities/hub-http-client.d.ts.map +1 -1
  80. package/dist/types/src/capabilities/index.d.ts +9 -43
  81. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  82. package/dist/types/src/capabilities/layer-specs.d.ts +1 -2
  83. package/dist/types/src/capabilities/layer-specs.d.ts.map +1 -1
  84. package/dist/types/src/capabilities/migrations.d.ts +1 -1
  85. package/dist/types/src/capabilities/navigation-handler/index.d.ts +1 -1
  86. package/dist/types/src/capabilities/navigation-handler/index.d.ts.map +1 -1
  87. package/dist/types/src/capabilities/navigation-handler/navigation-handler.d.ts +1 -2
  88. package/dist/types/src/capabilities/navigation-handler/navigation-handler.d.ts.map +1 -1
  89. package/dist/types/src/capabilities/node.d.ts +6 -6
  90. package/dist/types/src/capabilities/node.d.ts.map +1 -1
  91. package/dist/types/src/capabilities/react-context.d.ts +1 -6
  92. package/dist/types/src/capabilities/react-context.d.ts.map +1 -1
  93. package/dist/types/src/capabilities/react-surface.d.ts +2 -2
  94. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  95. package/dist/types/src/capabilities/schema-defs.d.ts +1 -1
  96. package/dist/types/src/commands/account/index.d.ts +3 -0
  97. package/dist/types/src/commands/account/index.d.ts.map +1 -0
  98. package/dist/types/src/commands/account/login/index.d.ts +2 -0
  99. package/dist/types/src/commands/account/login/index.d.ts.map +1 -0
  100. package/dist/types/src/commands/account/login/login.d.ts +12 -0
  101. package/dist/types/src/commands/account/login/login.d.ts.map +1 -0
  102. package/dist/types/src/commands/account/logout/index.d.ts +2 -0
  103. package/dist/types/src/commands/account/logout/index.d.ts.map +1 -0
  104. package/dist/types/src/commands/account/logout/logout.d.ts +9 -0
  105. package/dist/types/src/commands/account/logout/logout.d.ts.map +1 -0
  106. package/dist/types/src/commands/halo/join/join.d.ts +1 -1
  107. package/dist/types/src/commands/halo/join/join.d.ts.map +1 -1
  108. package/dist/types/src/commands/halo/util.d.ts +4 -0
  109. package/dist/types/src/commands/halo/util.d.ts.map +1 -1
  110. package/dist/types/src/commands/index.d.ts +1 -0
  111. package/dist/types/src/commands/index.d.ts.map +1 -1
  112. package/dist/types/src/constants.d.ts.map +1 -1
  113. package/dist/types/src/containers/AccountContainer/AccountContainer.d.ts.map +1 -1
  114. package/dist/types/src/containers/AccountContainer/AccountContainer.stories.d.ts +14 -0
  115. package/dist/types/src/containers/AccountContainer/AccountContainer.stories.d.ts.map +1 -0
  116. package/dist/types/src/containers/DevicesContainer/DevicesContainer.d.ts.map +1 -1
  117. package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.d.ts.map +1 -1
  118. package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.stories.d.ts +14 -0
  119. package/dist/types/src/containers/InvitationsContainer/InvitationsContainer.stories.d.ts.map +1 -0
  120. package/dist/types/src/containers/ProfileContainer/ProfileContainer.d.ts.map +1 -1
  121. package/dist/types/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.d.ts.map +1 -1
  122. package/dist/types/src/containers/UsageContainer/UsageContainer.d.ts +7 -0
  123. package/dist/types/src/containers/UsageContainer/UsageContainer.d.ts.map +1 -0
  124. package/dist/types/src/containers/UsageContainer/UsageView.d.ts +28 -0
  125. package/dist/types/src/containers/UsageContainer/UsageView.d.ts.map +1 -0
  126. package/dist/types/src/containers/UsageContainer/UsageView.stories.d.ts +21 -0
  127. package/dist/types/src/containers/UsageContainer/UsageView.stories.d.ts.map +1 -0
  128. package/dist/types/src/containers/UsageContainer/index.d.ts +2 -0
  129. package/dist/types/src/containers/UsageContainer/index.d.ts.map +1 -0
  130. package/dist/types/src/containers/index.d.ts +1 -0
  131. package/dist/types/src/containers/index.d.ts.map +1 -1
  132. package/dist/types/src/hooks/index.d.ts +2 -0
  133. package/dist/types/src/hooks/index.d.ts.map +1 -0
  134. package/dist/types/src/{state/use-hub-http.d.ts → hooks/useHubClient.d.ts} +1 -1
  135. package/dist/types/src/hooks/useHubClient.d.ts.map +1 -0
  136. package/dist/types/src/meta.d.ts +32 -2
  137. package/dist/types/src/meta.d.ts.map +1 -1
  138. package/dist/types/src/operations/create-passkey.d.ts.map +1 -1
  139. package/dist/types/src/operations/definitions.d.ts +1 -0
  140. package/dist/types/src/operations/definitions.d.ts.map +1 -1
  141. package/dist/types/src/operations/index.d.ts.map +1 -1
  142. package/dist/types/src/operations/open-usage.d.ts +5 -0
  143. package/dist/types/src/operations/open-usage.d.ts.map +1 -0
  144. package/dist/types/src/testing/initializeIdentity.d.ts.map +1 -1
  145. package/dist/types/src/translations.d.ts.map +1 -1
  146. package/dist/types/src/{state → types}/account-cache.d.ts.map +1 -1
  147. package/dist/types/src/types/capabilities.d.ts.map +1 -1
  148. package/dist/types/src/types/events.d.ts.map +1 -1
  149. package/dist/types/src/types/index.d.ts +1 -0
  150. package/dist/types/src/types/index.d.ts.map +1 -1
  151. package/dist/types/src/types/schema.d.ts +1 -0
  152. package/dist/types/src/types/schema.d.ts.map +1 -1
  153. package/dist/types/tsconfig.tsbuildinfo +1 -1
  154. package/dx.config.ts +19 -0
  155. package/package.json +47 -44
  156. package/src/ClientPlugin.node.ts +2 -2
  157. package/src/ClientPlugin.test.ts +1 -1
  158. package/src/capabilities/account-cache.ts +1 -3
  159. package/src/capabilities/app-graph-builder.ts +81 -71
  160. package/src/capabilities/layer-specs.ts +4 -6
  161. package/src/capabilities/react-context.tsx +1 -1
  162. package/src/capabilities/react-surface.tsx +6 -0
  163. package/src/commands/account/index.ts +13 -0
  164. package/src/commands/account/login/index.ts +5 -0
  165. package/src/commands/account/login/login.ts +147 -0
  166. package/src/commands/account/logout/index.ts +5 -0
  167. package/src/commands/account/logout/logout.ts +49 -0
  168. package/src/commands/halo/create/create.ts +2 -2
  169. package/src/commands/halo/index.ts +6 -6
  170. package/src/commands/halo/join/join.ts +2 -13
  171. package/src/commands/halo/util.ts +24 -0
  172. package/src/commands/index.ts +1 -0
  173. package/src/constants.ts +3 -3
  174. package/src/containers/AccountContainer/AccountContainer.stories.tsx +46 -0
  175. package/src/containers/AccountContainer/AccountContainer.tsx +67 -63
  176. package/src/containers/DevicesContainer/DevicesContainer.tsx +72 -54
  177. package/src/containers/InvitationsContainer/InvitationsContainer.stories.tsx +46 -0
  178. package/src/containers/InvitationsContainer/InvitationsContainer.tsx +65 -62
  179. package/src/containers/JoinDialog/JoinDialog.tsx +1 -1
  180. package/src/containers/ProfileContainer/ProfileContainer.tsx +38 -28
  181. package/src/containers/RecoveryCodeDialog/RecoveryCodeDialog.tsx +1 -1
  182. package/src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.tsx +52 -43
  183. package/src/containers/UsageContainer/UsageContainer.tsx +48 -0
  184. package/src/containers/UsageContainer/UsageView.stories.tsx +127 -0
  185. package/src/containers/UsageContainer/UsageView.tsx +270 -0
  186. package/src/containers/UsageContainer/index.ts +5 -0
  187. package/src/containers/index.ts +1 -0
  188. package/src/hooks/index.ts +5 -0
  189. package/src/meta.ts +3 -12
  190. package/src/operations/create-passkey.ts +6 -4
  191. package/src/operations/definitions.ts +12 -1
  192. package/src/operations/index.ts +1 -0
  193. package/src/operations/open-usage.ts +24 -0
  194. package/src/operations/redeem-passkey.ts +7 -7
  195. package/src/operations/share-identity.ts +3 -3
  196. package/src/testing/initializeIdentity.ts +5 -2
  197. package/src/translations.ts +25 -1
  198. package/src/types/capabilities.ts +8 -6
  199. package/src/types/events.ts +5 -5
  200. package/src/types/index.ts +1 -0
  201. package/src/types/schema.ts +23 -16
  202. package/dist/lib/neutral/AccountContainer-FZ3IC6H4.mjs.map +0 -7
  203. package/dist/lib/neutral/DevicesContainer-6MWNUC3I.mjs.map +0 -7
  204. package/dist/lib/neutral/InvitationsContainer-ME722VKS.mjs.map +0 -7
  205. package/dist/lib/neutral/JoinDialog-2NXAKPLP.mjs.map +0 -7
  206. package/dist/lib/neutral/ProfileContainer-VPX3FPWG.mjs.map +0 -7
  207. package/dist/lib/neutral/RecoveryCodeDialog-EWHB6U5T.mjs.map +0 -7
  208. package/dist/lib/neutral/RecoveryCredentialsContainer-IPBGDMIA.mjs.map +0 -7
  209. package/dist/lib/neutral/account-cache-4EKGEUJI.mjs +0 -43
  210. package/dist/lib/neutral/account-cache-4EKGEUJI.mjs.map +0 -7
  211. package/dist/lib/neutral/app-graph-builder-A74W7C36.mjs.map +0 -7
  212. package/dist/lib/neutral/chunk-D6HPCLTS.mjs.map +0 -7
  213. package/dist/lib/neutral/chunk-JOCCVODY.mjs +0 -21
  214. package/dist/lib/neutral/chunk-JOCCVODY.mjs.map +0 -7
  215. package/dist/lib/neutral/chunk-NTVDGDQ3.mjs +0 -8
  216. package/dist/lib/neutral/chunk-TUK3ELUU.mjs +0 -135
  217. package/dist/lib/neutral/chunk-TUK3ELUU.mjs.map +0 -7
  218. package/dist/lib/neutral/chunk-WWCVZG3K.mjs +0 -13
  219. package/dist/lib/neutral/chunk-WWCVZG3K.mjs.map +0 -7
  220. package/dist/lib/neutral/create-passkey-FOXEMXGF.mjs.map +0 -7
  221. package/dist/lib/neutral/layer-specs-CQLXQBQJ.mjs.map +0 -7
  222. package/dist/lib/neutral/react-surface-DEKGWTCD.mjs.map +0 -7
  223. package/dist/lib/neutral/redeem-passkey-4SBAI4AG.mjs.map +0 -7
  224. package/dist/lib/neutral/share-identity-KNQ2XNXV.mjs.map +0 -7
  225. package/dist/types/src/state/use-hub-http.d.ts.map +0 -1
  226. /package/dist/lib/neutral/{create-agent-6HLW4D3A.mjs.map → create-agent-6UKJMZS5.mjs.map} +0 -0
  227. /package/dist/lib/neutral/{create-identity-JIWAR5GW.mjs.map → create-identity-ULCRB3YH.mjs.map} +0 -0
  228. /package/dist/lib/neutral/{create-recovery-code-ZWDKLPH4.mjs.map → create-recovery-code-DH2B6EGP.mjs.map} +0 -0
  229. /package/dist/lib/neutral/{join-identity-QEQFAE2S.mjs.map → join-identity-PJCHDNLH.mjs.map} +0 -0
  230. /package/dist/lib/neutral/{navigation-handler-LU26CDFR.mjs.map → navigation-handler-MQ6MZXLX.mjs.map} +0 -0
  231. /package/dist/lib/neutral/{recover-identity-JNFKLCUD.mjs.map → recover-identity-B7YM2BR4.mjs.map} +0 -0
  232. /package/dist/lib/neutral/{redeem-token-POBD6TMN.mjs.map → redeem-token-2J33R3PV.mjs.map} +0 -0
  233. /package/dist/lib/neutral/{reset-storage-LQKUV5RA.mjs.map → reset-storage-K47HZTGP.mjs.map} +0 -0
  234. /package/dist/types/src/{state → types}/account-cache.d.ts +0 -0
  235. /package/src/{state/use-hub-http.ts → hooks/useHubClient.ts} +0 -0
  236. /package/src/{state → types}/account-cache.ts +0 -0
@@ -4,48 +4,57 @@ import "./chunk-J5LGTIGS.mjs";
4
4
  import React from "react";
5
5
  import { useOperationInvoker } from "@dxos/app-framework/ui";
6
6
  import { useCredentials } from "@dxos/react-client/halo";
7
- import { Icon, IconButton, List, ListItem, Message, useTranslation } from "@dxos/react-ui";
8
- import { Settings } from "@dxos/react-ui-form";
7
+ import { Icon, IconButton, Message, useTranslation } from "@dxos/react-ui";
8
+ import { Form } from "@dxos/react-ui-form";
9
+ import { Listbox } from "@dxos/react-ui-list";
9
10
  import { meta } from "#meta";
10
11
  import { ClientOperation } from "#operations";
11
- var MANAGE_CREDENTIALS_DIALOG = `${meta.id}.ManageCredentialsDialog`;
12
+ var MANAGE_CREDENTIALS_DIALOG = `${meta.profile.key}.ManageCredentialsDialog`;
12
13
  var RecoveryCredentialsContainer = () => {
13
- const { t } = useTranslation(meta.id);
14
+ const { t } = useTranslation(meta.profile.key);
14
15
  const { invokePromise } = useOperationInvoker();
15
16
  const credentials = useCredentials();
16
17
  const recoveryCredentials = credentials.filter((credential) => credential.subject.assertion["@type"] === "dxos.halo.credentials.IdentityRecovery");
17
- return /* @__PURE__ */ React.createElement(Settings.Viewport, null, /* @__PURE__ */ React.createElement(Settings.Section, {
18
+ return /* @__PURE__ */ React.createElement(Form.Root, {
19
+ variant: "settings"
20
+ }, /* @__PURE__ */ React.createElement(Form.Viewport, {
21
+ scroll: true
22
+ }, /* @__PURE__ */ React.createElement(Form.Content, null, /* @__PURE__ */ React.createElement(Form.Section, {
18
23
  title: t("recovery-setup-dialog.title"),
19
24
  description: t("recovery-setup-dialog.description")
20
- }, /* @__PURE__ */ React.createElement(Settings.Item, {
21
- title: t("create-passkey.label"),
25
+ }, /* @__PURE__ */ React.createElement(Form.Row, {
26
+ label: t("create-passkey.label"),
22
27
  description: t("create-passkey.description")
23
28
  }, /* @__PURE__ */ React.createElement(IconButton, {
24
29
  label: t("create-passkey.label"),
25
30
  icon: "ph--key--duotone",
26
31
  variant: "primary",
27
32
  onClick: () => invokePromise(ClientOperation.CreatePasskey)
28
- })), /* @__PURE__ */ React.createElement(Settings.Item, {
29
- title: t("create-recovery-code.label"),
33
+ })), /* @__PURE__ */ React.createElement(Form.Row, {
34
+ label: t("create-recovery-code.label"),
30
35
  description: t("create-recovery-code.description")
31
36
  }, /* @__PURE__ */ React.createElement(IconButton, {
32
37
  label: t("create-recovery-code.label"),
33
38
  icon: "ph--receipt--duotone",
34
39
  variant: "default",
35
40
  onClick: () => invokePromise(ClientOperation.CreateRecoveryCode)
36
- }))), /* @__PURE__ */ React.createElement(Settings.Section, {
41
+ }))), /* @__PURE__ */ React.createElement(Form.Section, {
37
42
  title: t("credentials-list.label")
38
43
  }, recoveryCredentials.length < 1 ? /* @__PURE__ */ React.createElement(Message.Root, {
39
44
  valence: "error"
40
45
  }, /* @__PURE__ */ React.createElement(Message.Title, {
41
46
  icon: "ph--shield-warning--duotone"
42
- }, t("no-credentials.title")), /* @__PURE__ */ React.createElement(Message.Content, null, t("no-credentials.message"))) : /* @__PURE__ */ React.createElement(List, null, recoveryCredentials.map((credential) => /* @__PURE__ */ React.createElement(ListItem.Root, {
43
- key: credential.id?.toHex()
44
- }, /* @__PURE__ */ React.createElement(ListItem.Endcap, null, /* @__PURE__ */ React.createElement(Icon, {
47
+ }, t("no-credentials.title")), /* @__PURE__ */ React.createElement(Message.Content, null, t("no-credentials.message"))) : /* @__PURE__ */ React.createElement(Listbox.Root, null, /* @__PURE__ */ React.createElement(Listbox.Content, {
48
+ classNames: "gap-1"
49
+ }, recoveryCredentials.map((credential, index) => /* @__PURE__ */ React.createElement(Listbox.Item, {
50
+ key: credential.id?.toHex() ?? index,
51
+ id: credential.id?.toHex() ?? `${index}`,
52
+ classNames: "gap-2"
53
+ }, /* @__PURE__ */ React.createElement(Icon, {
45
54
  icon: "ph--key--regular"
46
- })), /* @__PURE__ */ React.createElement(ListItem.Heading, null, credential.issuanceDate.toLocaleString()))))));
55
+ }), /* @__PURE__ */ React.createElement(Listbox.ItemLabel, null, credential.issuanceDate.toLocaleString())))))))));
47
56
  };
48
57
  export {
49
58
  RecoveryCredentialsContainer as default
50
59
  };
51
- //# sourceMappingURL=RecoveryCredentialsContainer-IPBGDMIA.mjs.map
60
+ //# sourceMappingURL=RecoveryCredentialsContainer-6BZ2IWX7.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/containers/RecoveryCredentialsContainer/RecoveryCredentialsContainer.tsx"],
4
+ "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport React from 'react';\n\nimport { useOperationInvoker } from '@dxos/app-framework/ui';\nimport { useCredentials } from '@dxos/react-client/halo';\nimport { Icon, IconButton, Message, useTranslation } from '@dxos/react-ui';\nimport { Form } from '@dxos/react-ui-form';\nimport { Listbox } from '@dxos/react-ui-list';\n\nimport { meta } from '#meta';\nimport { ClientOperation } from '#operations';\n\nexport const MANAGE_CREDENTIALS_DIALOG = `${meta.profile.key}.ManageCredentialsDialog`;\n\nexport const RecoveryCredentialsContainer = () => {\n const { t } = useTranslation(meta.profile.key);\n const { invokePromise } = useOperationInvoker();\n const credentials = useCredentials();\n const recoveryCredentials = credentials.filter(\n (credential) => credential.subject.assertion['@type'] === 'dxos.halo.credentials.IdentityRecovery',\n );\n\n return (\n <Form.Root variant='settings'>\n <Form.Viewport scroll>\n <Form.Content>\n <Form.Section title={t('recovery-setup-dialog.title')} description={t('recovery-setup-dialog.description')}>\n <Form.Row label={t('create-passkey.label')} description={t('create-passkey.description')}>\n <IconButton\n label={t('create-passkey.label')}\n icon='ph--key--duotone'\n variant='primary'\n onClick={() => invokePromise(ClientOperation.CreatePasskey)}\n />\n </Form.Row>\n <Form.Row label={t('create-recovery-code.label')} description={t('create-recovery-code.description')}>\n <IconButton\n label={t('create-recovery-code.label')}\n icon='ph--receipt--duotone'\n variant='default'\n onClick={() => invokePromise(ClientOperation.CreateRecoveryCode)}\n />\n </Form.Row>\n </Form.Section>\n <Form.Section title={t('credentials-list.label')}>\n {recoveryCredentials.length < 1 ? (\n <Message.Root valence='error'>\n <Message.Title icon='ph--shield-warning--duotone'>{t('no-credentials.title')}</Message.Title>\n <Message.Content>{t('no-credentials.message')}</Message.Content>\n </Message.Root>\n ) : (\n <Listbox.Root>\n <Listbox.Content classNames='gap-1'>\n {recoveryCredentials.map((credential, index) => (\n <Listbox.Item\n key={credential.id?.toHex() ?? index}\n id={credential.id?.toHex() ?? `${index}`}\n classNames='gap-2'\n >\n <Icon icon='ph--key--regular' />\n <Listbox.ItemLabel>{credential.issuanceDate.toLocaleString()}</Listbox.ItemLabel>\n </Listbox.Item>\n ))}\n </Listbox.Content>\n </Listbox.Root>\n )}\n </Form.Section>\n </Form.Content>\n </Form.Viewport>\n </Form.Root>\n );\n};\n"],
5
+ "mappings": ";;;AAIA,OAAOA,WAAW;AAElB,SAASC,2BAA2B;AACpC,SAASC,sBAAsB;AAC/B,SAASC,MAAMC,YAAYC,SAASC,sBAAsB;AAC1D,SAASC,YAAY;AACrB,SAASC,eAAe;AAExB,SAASC,YAAY;AACrB,SAASC,uBAAuB;AAEzB,IAAMC,4BAA4B,GAAGF,KAAKG,QAAQC,GAAG;AAErD,IAAMC,+BAA+B,MAAA;AAC1C,QAAM,EAAEC,EAAC,IAAKT,eAAeG,KAAKG,QAAQC,GAAG;AAC7C,QAAM,EAAEG,cAAa,IAAKf,oBAAAA;AAC1B,QAAMgB,cAAcf,eAAAA;AACpB,QAAMgB,sBAAsBD,YAAYE,OACtC,CAACC,eAAeA,WAAWC,QAAQC,UAAU,OAAA,MAAa,wCAAA;AAG5D,SACE,sBAAA,cAACf,KAAKgB,MAAI;IAACC,SAAQ;KACjB,sBAAA,cAACjB,KAAKkB,UAAQ;IAACC,QAAAA;KACb,sBAAA,cAACnB,KAAKoB,SAAO,MACX,sBAAA,cAACpB,KAAKqB,SAAO;IAACC,OAAOd,EAAE,6BAAA;IAAgCe,aAAaf,EAAE,mCAAA;KACpE,sBAAA,cAACR,KAAKwB,KAAG;IAACC,OAAOjB,EAAE,sBAAA;IAAyBe,aAAaf,EAAE,4BAAA;KACzD,sBAAA,cAACX,YAAAA;IACC4B,OAAOjB,EAAE,sBAAA;IACTkB,MAAK;IACLT,SAAQ;IACRU,SAAS,MAAMlB,cAAcN,gBAAgByB,aAAa;OAG9D,sBAAA,cAAC5B,KAAKwB,KAAG;IAACC,OAAOjB,EAAE,4BAAA;IAA+Be,aAAaf,EAAE,kCAAA;KAC/D,sBAAA,cAACX,YAAAA;IACC4B,OAAOjB,EAAE,4BAAA;IACTkB,MAAK;IACLT,SAAQ;IACRU,SAAS,MAAMlB,cAAcN,gBAAgB0B,kBAAkB;QAIrE,sBAAA,cAAC7B,KAAKqB,SAAO;IAACC,OAAOd,EAAE,wBAAA;KACpBG,oBAAoBmB,SAAS,IAC5B,sBAAA,cAAChC,QAAQkB,MAAI;IAACe,SAAQ;KACpB,sBAAA,cAACjC,QAAQkC,OAAK;IAACN,MAAK;KAA+BlB,EAAE,sBAAA,CAAA,GACrD,sBAAA,cAACV,QAAQsB,SAAO,MAAEZ,EAAE,wBAAA,CAAA,CAAA,IAGtB,sBAAA,cAACP,QAAQe,MAAI,MACX,sBAAA,cAACf,QAAQmB,SAAO;IAACa,YAAW;KACzBtB,oBAAoBuB,IAAI,CAACrB,YAAYsB,UACpC,sBAAA,cAAClC,QAAQmC,MAAI;IACX9B,KAAKO,WAAWwB,IAAIC,MAAAA,KAAWH;IAC/BE,IAAIxB,WAAWwB,IAAIC,MAAAA,KAAW,GAAGH,KAAAA;IACjCF,YAAW;KAEX,sBAAA,cAACrC,MAAAA;IAAK8B,MAAK;MACX,sBAAA,cAACzB,QAAQsC,WAAS,MAAE1B,WAAW2B,aAAaC,eAAc,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAWhF;",
6
+ "names": ["React", "useOperationInvoker", "useCredentials", "Icon", "IconButton", "Message", "useTranslation", "Form", "Listbox", "meta", "ClientOperation", "MANAGE_CREDENTIALS_DIALOG", "profile", "key", "RecoveryCredentialsContainer", "t", "invokePromise", "credentials", "recoveryCredentials", "filter", "credential", "subject", "assertion", "Root", "variant", "Viewport", "scroll", "Content", "Section", "title", "description", "Row", "label", "icon", "onClick", "CreatePasskey", "CreateRecoveryCode", "length", "valence", "Title", "classNames", "map", "index", "Item", "id", "toHex", "ItemLabel", "issuanceDate", "toLocaleString"]
7
+ }
@@ -0,0 +1,241 @@
1
+ import {
2
+ useHubHttpClient
3
+ } from "./chunk-JY35S2CN.mjs";
4
+ import "./chunk-J5LGTIGS.mjs";
5
+
6
+ // src/containers/UsageContainer/UsageContainer.tsx
7
+ import React2, { useCallback as useCallback2, useState as useState2 } from "react";
8
+ import { Context } from "@dxos/context";
9
+ import { log } from "@dxos/log";
10
+ import { useAsyncEffect } from "@dxos/react-ui";
11
+
12
+ // src/containers/UsageContainer/UsageView.tsx
13
+ import * as Schema from "effect/Schema";
14
+ import React, { useCallback, useMemo, useState } from "react";
15
+ import { IconButton, Message, Status, ToggleIconButton, useTranslation } from "@dxos/react-ui";
16
+ import { Form } from "@dxos/react-ui-form";
17
+ import { JsonHighlighter } from "@dxos/react-ui-syntax-highlighter";
18
+ import { meta } from "#meta";
19
+ var usageMatchesLimit = (item, limit) => {
20
+ if (item.eventType !== limit.eventType || item.valueKey !== limit.valueKey) {
21
+ return false;
22
+ }
23
+ return limit.subtypePattern.every((pattern, index) => pattern === "*" || pattern === item.subtypePattern[index]);
24
+ };
25
+ var sumUsageForLimit = (usage, limit) => usage.reduce((total, item) => usageMatchesLimit(item, limit) ? total + item.amount : total, 0);
26
+ var formatValueKey = (valueKey) => valueKey.replace(/([A-Z])/g, " $1").trim().toLowerCase();
27
+ var formatLimitLabel = (limit, t) => {
28
+ const metric = formatValueKey(limit.valueKey);
29
+ const subtype = limit.subtypePattern.filter((segment) => segment && segment !== "*").join("/");
30
+ if (limit.eventType === "ai") {
31
+ return `${subtype || t("usage-all-models.label")} \xB7 ${metric}`;
32
+ }
33
+ return `${subtype ? `${limit.eventType}/${subtype}` : limit.eventType} \xB7 ${metric}`;
34
+ };
35
+ var formatAmount = (amount) => amount.toLocaleString();
36
+ var SECONDS_PER_HOUR = 60 * 60;
37
+ var formatWindow = (windowHours, t) => {
38
+ if (windowHours % (24 * 30) === 0) {
39
+ return t("usage-window-months.label", {
40
+ count: windowHours / (24 * 30)
41
+ });
42
+ }
43
+ if (windowHours % 24 === 0) {
44
+ return t("usage-window-days.label", {
45
+ count: windowHours / 24
46
+ });
47
+ }
48
+ return t("usage-window-hours.label", {
49
+ count: windowHours
50
+ });
51
+ };
52
+ var computeRows = (data, t) => data.limits.map((limit) => {
53
+ const used = sumUsageForLimit(data.usage, limit);
54
+ const label = formatLimitLabel(limit, t);
55
+ const windowHours = limit.windowDuration / SECONDS_PER_HOUR;
56
+ const window = formatWindow(windowHours, t);
57
+ const key = `${limit.eventType}/${limit.subtypePattern.join(",")}/${limit.valueKey}/${limit.windowDuration}/${limit.limit ?? "unlimited"}`;
58
+ if (limit.limit === null) {
59
+ return {
60
+ key,
61
+ label,
62
+ caption: t("usage-unlimited.description", {
63
+ used: formatAmount(used),
64
+ window
65
+ }),
66
+ windowHours
67
+ };
68
+ }
69
+ const percent = limit.limit > 0 ? Math.min(100, Math.round(used / limit.limit * 100)) : used > 0 ? 100 : 0;
70
+ return {
71
+ key,
72
+ label,
73
+ caption: `${t("usage-percent-used.label", {
74
+ percent
75
+ })} \xB7 ${t("usage-limit.description", {
76
+ used: formatAmount(used),
77
+ limit: formatAmount(limit.limit),
78
+ window
79
+ })}`,
80
+ percent,
81
+ windowHours
82
+ };
83
+ }).sort((left, right) => left.windowHours - right.windowHours);
84
+ var usageField = (title, description) => Schema.optional(Schema.Number.annotations({
85
+ title,
86
+ description
87
+ }));
88
+ var buildUsageForm = (rows) => {
89
+ const fields = {};
90
+ const values = {};
91
+ rows.forEach((row, index) => {
92
+ const field = `metric_${index}`;
93
+ fields[field] = usageField(row.label, row.caption);
94
+ if (row.percent !== void 0) {
95
+ values[field] = row.percent;
96
+ }
97
+ });
98
+ return {
99
+ schema: Schema.Struct(fields),
100
+ values
101
+ };
102
+ };
103
+ var STATE_MESSAGES = {
104
+ unavailable: {
105
+ valence: "warning",
106
+ icon: "ph--cloud-slash--duotone",
107
+ title: "usage-unavailable.title",
108
+ description: "usage-unavailable.description"
109
+ },
110
+ error: {
111
+ valence: "error",
112
+ icon: "ph--cloud-x--duotone",
113
+ title: "usage-offline.title",
114
+ description: "usage-offline.description"
115
+ },
116
+ empty: {
117
+ valence: "neutral",
118
+ icon: "ph--chart-bar--duotone",
119
+ title: "usage-empty.title",
120
+ description: "usage-empty.description"
121
+ }
122
+ };
123
+ var UsageView = ({ state, data, lastUpdated, onRefresh }) => {
124
+ const { t } = useTranslation(meta.profile.key);
125
+ const [rawExpanded, setRawExpanded] = useState(false);
126
+ const { schema, values, empty } = useMemo(() => {
127
+ const rows = data ? computeRows(data, t) : [];
128
+ return {
129
+ ...buildUsageForm(rows),
130
+ empty: rows.length === 0
131
+ };
132
+ }, [
133
+ data,
134
+ t
135
+ ]);
136
+ const message = state === "unavailable" ? STATE_MESSAGES.unavailable : state === "error" ? STATE_MESSAGES.error : state === "ready" && empty ? STATE_MESSAGES.empty : void 0;
137
+ const meterFieldProvider = useCallback(({ fieldProps: { label, description, getValue } }) => {
138
+ const percent = getValue();
139
+ return /* @__PURE__ */ React.createElement(Form.Row, {
140
+ label,
141
+ description
142
+ }, typeof percent === "number" ? /* @__PURE__ */ React.createElement(Status, {
143
+ progress: percent / 100,
144
+ "aria-label": t("usage-percent-used.label", {
145
+ percent
146
+ })
147
+ }) : t("usage-unlimited.label"));
148
+ }, [
149
+ t
150
+ ]);
151
+ return /* @__PURE__ */ React.createElement(Form.Root, {
152
+ variant: "settings",
153
+ layout: "static",
154
+ schema,
155
+ values
156
+ }, /* @__PURE__ */ React.createElement(Form.Viewport, {
157
+ scroll: true
158
+ }, /* @__PURE__ */ React.createElement(Form.Content, null, /* @__PURE__ */ React.createElement(Form.Section, {
159
+ title: t("usage-section.title"),
160
+ description: t("usage-section.description")
161
+ }, state === "loading" ? /* @__PURE__ */ React.createElement(Status, {
162
+ indeterminate: true,
163
+ "aria-label": t("usage-section.title")
164
+ }) : message ? /* @__PURE__ */ React.createElement(Message.Root, {
165
+ valence: message.valence
166
+ }, /* @__PURE__ */ React.createElement(Message.Title, {
167
+ icon: message.icon
168
+ }, t(message.title)), /* @__PURE__ */ React.createElement(Message.Content, null, t(message.description))) : /* @__PURE__ */ React.createElement(Form.FieldSet, {
169
+ fieldProvider: meterFieldProvider
170
+ })), state === "ready" && data && /* @__PURE__ */ React.createElement(Form.Section, null, /* @__PURE__ */ React.createElement(Form.Row, {
171
+ label: lastUpdated !== void 0 ? t("usage-last-updated.label", {
172
+ time: new Date(lastUpdated).toLocaleTimeString()
173
+ }) : t("usage-refresh.label")
174
+ }, onRefresh && /* @__PURE__ */ React.createElement(IconButton, {
175
+ iconOnly: true,
176
+ variant: "ghost",
177
+ icon: "ph--arrow-clockwise--regular",
178
+ label: t("usage-refresh.label"),
179
+ onClick: onRefresh
180
+ }))), state === "ready" && data && /* @__PURE__ */ React.createElement(Form.Section, null, /* @__PURE__ */ React.createElement(Form.Row, {
181
+ label: t("usage-raw-json.label")
182
+ }, /* @__PURE__ */ React.createElement(ToggleIconButton, {
183
+ iconOnly: true,
184
+ variant: "ghost",
185
+ active: rawExpanded,
186
+ icon: "ph--caret-right--regular",
187
+ label: t("usage-raw-json.label"),
188
+ onClick: () => setRawExpanded((value) => !value)
189
+ })), rawExpanded && /* @__PURE__ */ React.createElement(JsonHighlighter, {
190
+ data,
191
+ testId: "usage-raw-json"
192
+ })))));
193
+ };
194
+
195
+ // src/containers/UsageContainer/UsageContainer.tsx
196
+ var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-client/src/containers/UsageContainer/UsageContainer.tsx";
197
+ var UsageContainer = () => {
198
+ const hubHttp = useHubHttpClient();
199
+ const [fetchState, setFetchState] = useState2({
200
+ state: "loading"
201
+ });
202
+ const [lastUpdated, setLastUpdated] = useState2();
203
+ const [refreshCount, setRefreshCount] = useState2(0);
204
+ useAsyncEffect(async () => {
205
+ if (!hubHttp) {
206
+ setFetchState({
207
+ state: "unavailable"
208
+ });
209
+ return;
210
+ }
211
+ setFetchState((previous) => previous.state === "ready" ? previous : {
212
+ state: "loading"
213
+ });
214
+ try {
215
+ const result = await hubHttp.getProfileUsage(new Context(void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 32 }));
216
+ setFetchState({
217
+ state: "ready",
218
+ data: result
219
+ });
220
+ setLastUpdated(Date.now());
221
+ } catch (err) {
222
+ log.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 39, S: void 0 });
223
+ setFetchState({
224
+ state: "error"
225
+ });
226
+ }
227
+ }, [
228
+ hubHttp,
229
+ refreshCount
230
+ ]);
231
+ const handleRefresh = useCallback2(() => setRefreshCount((count) => count + 1), []);
232
+ return /* @__PURE__ */ React2.createElement(UsageView, {
233
+ ...fetchState,
234
+ lastUpdated,
235
+ onRefresh: handleRefresh
236
+ });
237
+ };
238
+ export {
239
+ UsageContainer as default
240
+ };
241
+ //# sourceMappingURL=UsageContainer-2DWCVVE4.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/containers/UsageContainer/UsageContainer.tsx", "../../../src/containers/UsageContainer/UsageView.tsx"],
4
+ "sourcesContent": ["//\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 = { state: Exclude<UsageViewState, 'ready'> } | { state: 'ready'; data: GetProfileUsageResponse };\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", "//\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 { IconButton, Message, Status, ToggleIconButton, useTranslation } from '@dxos/react-ui';\nimport { Form, type FormFieldProvider } from '@dxos/react-ui-form';\nimport { JsonHighlighter } from '@dxos/react-ui-syntax-highlighter';\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.annotations({ 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 <Status 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 {state === 'loading' ? (\n <Status indeterminate aria-label={t('usage-section.title')} />\n ) : message ? (\n <Message.Root valence={message.valence}>\n <Message.Title icon={message.icon}>{t(message.title)}</Message.Title>\n <Message.Content>{t(message.description)}</Message.Content>\n </Message.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"],
5
+ "mappings": "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",
6
+ "names": ["React", "useCallback", "useState", "Context", "log", "useAsyncEffect", "Schema", "React", "useCallback", "useMemo", "useState", "IconButton", "Message", "Status", "ToggleIconButton", "useTranslation", "Form", "JsonHighlighter", "meta", "usageMatchesLimit", "item", "limit", "eventType", "valueKey", "subtypePattern", "every", "pattern", "index", "sumUsageForLimit", "usage", "reduce", "total", "amount", "formatValueKey", "replace", "trim", "toLowerCase", "formatLimitLabel", "t", "metric", "subtype", "filter", "segment", "join", "formatAmount", "toLocaleString", "SECONDS_PER_HOUR", "formatWindow", "windowHours", "count", "computeRows", "data", "limits", "map", "used", "label", "windowDuration", "window", "key", "caption", "percent", "Math", "min", "round", "sort", "left", "right", "usageField", "title", "description", "optional", "Number", "annotations", "buildUsageForm", "rows", "fields", "values", "forEach", "row", "field", "undefined", "schema", "Struct", "STATE_MESSAGES", "unavailable", "valence", "icon", "error", "empty", "UsageView", "state", "lastUpdated", "onRefresh", "profile", "rawExpanded", "setRawExpanded", "length", "message", "meterFieldProvider", "fieldProps", "getValue", "Row", "progress", "aria-label", "Root", "variant", "layout", "Viewport", "scroll", "Content", "Section", "indeterminate", "Title", "FieldSet", "fieldProvider", "time", "Date", "toLocaleTimeString", "iconOnly", "onClick", "active", "value", "testId", "fetchState", "setFetchState", "state", "useState", "lastUpdated", "useAsyncEffect", "result", "setLastUpdated", "log", "err", "hubHttp", "useCallback", "onRefresh"]
7
+ }
@@ -0,0 +1,16 @@
1
+ import "./chunk-J5LGTIGS.mjs";
2
+
3
+ // src/capabilities/account-cache.ts
4
+ import * as Effect from "effect/Effect";
5
+ import { Capability } from "@dxos/app-framework";
6
+ import { createKvsStore } from "@dxos/effect";
7
+ import { AccountCache, ClientCapabilities } from "#types";
8
+ var account_cache_default = Capability.makeModule(() => Effect.succeed(Capability.contributes(ClientCapabilities.AccountCache, createKvsStore({
9
+ key: "composer.account",
10
+ schema: AccountCache,
11
+ defaultValue: () => ({})
12
+ }))));
13
+ export {
14
+ account_cache_default as default
15
+ };
16
+ //# sourceMappingURL=account-cache-YVQKLNV2.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/capabilities/account-cache.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Capability } from '@dxos/app-framework';\nimport { createKvsStore } from '@dxos/effect';\n\nimport { AccountCache, ClientCapabilities } from '#types';\n\nexport default Capability.makeModule(() =>\n Effect.succeed(\n Capability.contributes(\n ClientCapabilities.AccountCache,\n createKvsStore<AccountCache>({\n key: 'composer.account',\n schema: AccountCache,\n defaultValue: () => ({}),\n }),\n ),\n ),\n);\n"],
5
+ "mappings": ";;;AAIA,YAAYA,YAAY;AAExB,SAASC,kBAAkB;AAC3B,SAASC,sBAAsB;AAE/B,SAASC,cAAcC,0BAA0B;AAEjD,IAAA,wBAAeH,WAAWI,WAAW,MAC5BC,eACLL,WAAWM,YACTH,mBAAmBD,cACnBD,eAA6B;EAC3BM,KAAK;EACLC,QAAQN;EACRO,cAAc,OAAO,CAAC;AACxB,CAAA,CAAA,CAAA,CAAA;",
6
+ "names": ["Effect", "Capability", "createKvsStore", "AccountCache", "ClientCapabilities", "makeModule", "succeed", "contributes", "key", "schema", "defaultValue"]
7
+ }
@@ -22,7 +22,7 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
22
22
  label: [
23
23
  "open-user-account.label",
24
24
  {
25
- ns: meta.id
25
+ ns: meta.profile.key
26
26
  }
27
27
  ],
28
28
  icon: "ph--user--regular",
@@ -36,19 +36,19 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
36
36
  }
37
37
  }
38
38
  ]),
39
- connector: Effect.fnUntraced(function* (node, get) {
39
+ connector: (node, get) => Effect.gen(function* () {
40
40
  const client = yield* Capability.get(ClientCapabilities.Client);
41
41
  const identity = get(CreateAtom.fromObservable(client.halo.identity));
42
42
  const status = get(CreateAtom.fromObservable(client.mesh.networkStatus));
43
43
  return [
44
44
  Node.make({
45
45
  id: Account.id,
46
- type: meta.id,
46
+ type: meta.profile.key,
47
47
  properties: {
48
48
  label: [
49
49
  "account.label",
50
50
  {
51
- ns: meta.id
51
+ ns: meta.profile.key
52
52
  }
53
53
  ],
54
54
  icon: "ph--user--regular",
@@ -64,12 +64,12 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
64
64
  Node.make({
65
65
  id: Account.Profile,
66
66
  data: Account.Profile,
67
- type: meta.id,
67
+ type: meta.profile.key,
68
68
  properties: {
69
69
  label: [
70
70
  "profile.label",
71
71
  {
72
- ns: meta.id
72
+ ns: meta.profile.key
73
73
  }
74
74
  ],
75
75
  icon: "ph--user--regular"
@@ -78,12 +78,12 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
78
78
  Node.make({
79
79
  id: Account.Account,
80
80
  data: Account.Account,
81
- type: meta.id,
81
+ type: meta.profile.key,
82
82
  properties: {
83
83
  label: [
84
84
  "account-panel.label",
85
85
  {
86
- ns: meta.id
86
+ ns: meta.profile.key
87
87
  }
88
88
  ],
89
89
  icon: "ph--identification-card--regular"
@@ -92,12 +92,12 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
92
92
  Node.make({
93
93
  id: Account.Devices,
94
94
  data: Account.Devices,
95
- type: meta.id,
95
+ type: meta.profile.key,
96
96
  properties: {
97
97
  label: [
98
98
  "devices.label",
99
99
  {
100
- ns: meta.id
100
+ ns: meta.profile.key
101
101
  }
102
102
  ],
103
103
  icon: "ph--devices--regular",
@@ -107,12 +107,12 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
107
107
  Node.make({
108
108
  id: Account.Security,
109
109
  data: Account.Security,
110
- type: meta.id,
110
+ type: meta.profile.key,
111
111
  properties: {
112
112
  label: [
113
113
  "security.label",
114
114
  {
115
- ns: meta.id
115
+ ns: meta.profile.key
116
116
  }
117
117
  ],
118
118
  icon: "ph--key--regular"
@@ -121,25 +121,39 @@ var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function
121
121
  Node.make({
122
122
  id: Account.Invitations,
123
123
  data: Account.Invitations,
124
- type: meta.id,
124
+ type: meta.profile.key,
125
125
  properties: {
126
126
  label: [
127
127
  "invitations-panel.label",
128
128
  {
129
- ns: meta.id
129
+ ns: meta.profile.key
130
130
  }
131
131
  ],
132
132
  icon: "ph--ticket--regular"
133
133
  }
134
+ }),
135
+ Node.make({
136
+ id: Account.Usage,
137
+ data: Account.Usage,
138
+ type: meta.profile.key,
139
+ properties: {
140
+ label: [
141
+ "usage-panel.label",
142
+ {
143
+ ns: meta.profile.key
144
+ }
145
+ ],
146
+ icon: "ph--chart-bar--regular"
147
+ }
134
148
  })
135
149
  ]
136
150
  })
137
151
  ];
138
- })
152
+ }).pipe(Effect.orDie)
139
153
  });
140
154
  return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);
141
155
  }));
142
156
  export {
143
157
  app_graph_builder_default as default
144
158
  };
145
- //# sourceMappingURL=app-graph-builder-A74W7C36.mjs.map
159
+ //# sourceMappingURL=app-graph-builder-RVXTD6OE.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/capabilities/app-graph-builder.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Capability } from '@dxos/app-framework';\nimport { AppCapabilities } from '@dxos/app-toolkit';\nimport { Operation } from '@dxos/compute';\nimport { CreateAtom, GraphBuilder, Node, NodeMatcher } from '@dxos/plugin-graph';\nimport { ConnectionState } from '@dxos/react-client/mesh';\n\nimport { meta } from '#meta';\nimport { ClientOperation } from '#operations';\nimport { Account, ClientCapabilities } from '#types';\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n const extensions = yield* GraphBuilder.createExtension({\n id: 'root',\n match: NodeMatcher.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 = yield* Capability.get(ClientCapabilities.Client);\n const identity = get(CreateAtom.fromObservable(client.halo.identity));\n const status = get(CreateAtom.fromObservable(client.mesh.networkStatus));\n\n return [\n Node.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.toHex(),\n hue: identity?.profile?.data?.hue,\n emoji: identity?.profile?.data?.emoji,\n status: status.swarm === ConnectionState.OFFLINE ? 'error' : 'active',\n },\n nodes: [\n Node.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 Node.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 Node.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 Node.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 Node.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 Node.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 }).pipe(Effect.orDie),\n });\n\n return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);\n }),\n);\n"],
5
+ "mappings": "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",
6
+ "names": ["Effect", "Capability", "AppCapabilities", "Operation", "CreateAtom", "GraphBuilder", "Node", "NodeMatcher", "ConnectionState", "meta", "ClientOperation", "Account", "ClientCapabilities", "makeModule", "fnUntraced", "extensions", "createExtension", "id", "match", "whenRoot", "actions", "succeed", "data", "invoke", "ShareIdentity", "properties", "label", "ns", "profile", "key", "icon", "disposition", "keyBinding", "macos", "windows", "linux", "connector", "node", "get", "gen", "client", "Client", "identity", "fromObservable", "halo", "status", "mesh", "networkStatus", "make", "type", "testId", "userId", "identityKey", "toHex", "hue", "emoji", "swarm", "OFFLINE", "nodes", "Profile", "Devices", "Security", "Invitations", "Usage", "pipe", "orDie", "contributes", "AppGraphBuilder"]
7
+ }
@@ -5,18 +5,18 @@ import { Capability as Capability2 } from "@dxos/app-framework";
5
5
 
6
6
  // src/capabilities/navigation-handler/index.ts
7
7
  import { Capability } from "@dxos/app-framework";
8
- var NavigationHandler = Capability.lazy("NavigationHandler", () => import("../navigation-handler-LU26CDFR.mjs"));
8
+ var NavigationHandler = Capability.lazy("NavigationHandler", () => import("../navigation-handler-MQ6MZXLX.mjs"));
9
9
 
10
10
  // src/capabilities/index.ts
11
- var AccountCache = Capability2.lazy("AccountCache", () => import("../account-cache-4EKGEUJI.mjs"));
12
- var AppGraphBuilder = Capability2.lazy("AppGraphBuilder", () => import("../app-graph-builder-A74W7C36.mjs"));
11
+ var AccountCache = Capability2.lazy("AccountCache", () => import("../account-cache-YVQKLNV2.mjs"));
12
+ var AppGraphBuilder = Capability2.lazy("AppGraphBuilder", () => import("../app-graph-builder-RVXTD6OE.mjs"));
13
13
  var HubHttpClient = Capability2.lazy("HubHttpClient", () => import("../hub-http-client-WOJUCDKV.mjs"));
14
14
  var Client = Capability2.lazy("Client", () => import("../client-7I5Y5SOA.mjs"));
15
- var LayerSpecs = Capability2.lazy("LayerSpecs", () => import("../layer-specs-CQLXQBQJ.mjs"));
15
+ var LayerSpecs = Capability2.lazy("LayerSpecs", () => import("../layer-specs-YI7BVWKZ.mjs"));
16
16
  var Migrations = Capability2.lazy("Migrations", () => import("../migrations-7FTW55ER.mjs"));
17
17
  var OperationHandler = Capability2.lazy("OperationHandler", () => import("../operation-handler-E3HB7E2T.mjs"));
18
- var ReactContext = Capability2.lazy("ReactContext", () => import("../react-context-B5LXMHVM.mjs"));
19
- var ReactSurface = Capability2.lazy("ReactSurface", () => import("../react-surface-DEKGWTCD.mjs"));
18
+ var ReactContext = Capability2.lazy("ReactContext", () => import("../react-context-V74T6JOJ.mjs"));
19
+ var ReactSurface = Capability2.lazy("ReactSurface", () => import("../react-surface-HPXRA65U.mjs"));
20
20
  var SchemaDefs = Capability2.lazy("SchemaDefs", () => import("../schema-defs-IHBCKTMM.mjs"));
21
21
  export {
22
22
  AccountCache,
@@ -2,11 +2,11 @@ import "../chunk-J5LGTIGS.mjs";
2
2
 
3
3
  // src/capabilities/node.ts
4
4
  import { Capability } from "@dxos/app-framework";
5
- var AppGraphBuilder = Capability.lazy("AppGraphBuilder", () => import("../app-graph-builder-A74W7C36.mjs"));
5
+ var AppGraphBuilder = Capability.lazy("AppGraphBuilder", () => import("../app-graph-builder-RVXTD6OE.mjs"));
6
6
  var Client = Capability.lazy("Client", () => import("../client-7I5Y5SOA.mjs"));
7
- var LayerSpecs = Capability.lazy("LayerSpecs", () => import("../layer-specs-CQLXQBQJ.mjs"));
7
+ var LayerSpecs = Capability.lazy("LayerSpecs", () => import("../layer-specs-YI7BVWKZ.mjs"));
8
8
  var Migrations = Capability.lazy("Migrations", () => import("../migrations-7FTW55ER.mjs"));
9
- var NavigationHandler = Capability.lazy("NavigationHandler", () => import("../navigation-handler-LU26CDFR.mjs"));
9
+ var NavigationHandler = Capability.lazy("NavigationHandler", () => import("../navigation-handler-MQ6MZXLX.mjs"));
10
10
  var OperationHandler = Capability.lazy("OperationHandler", () => import("../operation-handler-E3HB7E2T.mjs"));
11
11
  var SchemaDefs = Capability.lazy("SchemaDefs", () => import("../schema-defs-IHBCKTMM.mjs"));
12
12
  export {