@dxos/shell 0.3.11-main.ec7a2b3 → 0.3.11-main.ee2b64c

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 (85) hide show
  1. package/dist/bundle/shell.mjs +15272 -13589
  2. package/dist/bundle/shell.mjs.map +1 -1
  3. package/dist/bundle/shell.umd.js +81 -75
  4. package/dist/bundle/shell.umd.js.map +1 -1
  5. package/dist/bundle/style.css +1 -1
  6. package/dist/lib/browser/meta.json +1 -1
  7. package/dist/lib/browser/react.mjs +190 -174
  8. package/dist/lib/browser/react.mjs.map +4 -4
  9. package/dist/lib/browser/testing/index.mjs +35 -14
  10. package/dist/lib/browser/testing/index.mjs.map +3 -3
  11. package/dist/types/src/components/IdentityList/SpaceMemberList.js +1 -1
  12. package/dist/types/src/components/IdentityList/SpaceMemberList.js.map +1 -1
  13. package/dist/types/src/components/Panel/Action.d.ts.map +1 -1
  14. package/dist/types/src/components/Panel/Action.js +3 -18
  15. package/dist/types/src/components/Panel/Action.js.map +1 -1
  16. package/dist/types/src/panels/IdentityPanel/IdentityPanel.d.ts.map +1 -1
  17. package/dist/types/src/panels/IdentityPanel/IdentityPanel.js +6 -2
  18. package/dist/types/src/panels/IdentityPanel/IdentityPanel.js.map +1 -1
  19. package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts +9 -1
  20. package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts.map +1 -1
  21. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.d.ts +3 -0
  22. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.d.ts.map +1 -0
  23. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.js +26 -0
  24. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.js.map +1 -0
  25. package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.d.ts.map +1 -1
  26. package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js +1 -1
  27. package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js.map +1 -1
  28. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.js +2 -2
  29. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.js.map +1 -1
  30. package/dist/types/src/panels/IdentityPanel/steps/index.d.ts +1 -1
  31. package/dist/types/src/panels/IdentityPanel/steps/index.d.ts.map +1 -1
  32. package/dist/types/src/panels/IdentityPanel/steps/index.js +1 -1
  33. package/dist/types/src/panels/IdentityPanel/steps/index.js.map +1 -1
  34. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.d.ts +15 -0
  35. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.d.ts.map +1 -0
  36. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.js +78 -0
  37. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.js.map +1 -0
  38. package/dist/types/src/panels/JoinPanel/joinMachine.d.ts +1 -1
  39. package/dist/types/src/panels/JoinPanel/joinMachine.d.ts.map +1 -1
  40. package/dist/types/src/panels/JoinPanel/joinMachine.js +14 -17
  41. package/dist/types/src/panels/JoinPanel/joinMachine.js.map +1 -1
  42. package/dist/types/src/panels/JoinPanel/steps/AdditionMethodChooser.js +3 -3
  43. package/dist/types/src/panels/JoinPanel/steps/AdditionMethodChooser.js.map +1 -1
  44. package/dist/types/src/panels/JoinPanel/steps/InvitationInput.d.ts.map +1 -1
  45. package/dist/types/src/panels/JoinPanel/steps/InvitationInput.js +13 -6
  46. package/dist/types/src/panels/JoinPanel/steps/InvitationInput.js.map +1 -1
  47. package/dist/types/src/panels/JoinPanel/steps/InvitationRescuer.js.map +1 -1
  48. package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.js +1 -1
  49. package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.js.map +1 -1
  50. package/dist/types/src/playwright/invitations-manager.d.ts +1 -0
  51. package/dist/types/src/playwright/invitations-manager.d.ts.map +1 -1
  52. package/dist/types/src/playwright/invitations-manager.js +4 -1
  53. package/dist/types/src/playwright/invitations-manager.js.map +1 -1
  54. package/dist/types/src/playwright/invitations.spec.js +15 -0
  55. package/dist/types/src/playwright/invitations.spec.js.map +1 -1
  56. package/dist/types/src/styles/invitationStatusStyles.d.ts.map +1 -1
  57. package/dist/types/src/styles/invitationStatusStyles.js.map +1 -1
  58. package/dist/types/src/testing/shell-manager.d.ts +5 -4
  59. package/dist/types/src/testing/shell-manager.d.ts.map +1 -1
  60. package/dist/types/src/testing/shell-manager.js +36 -12
  61. package/dist/types/src/testing/shell-manager.js.map +1 -1
  62. package/package.json +22 -22
  63. package/src/components/IdentityList/SpaceMemberList.tsx +1 -1
  64. package/src/components/Panel/Action.tsx +4 -19
  65. package/src/panels/IdentityPanel/IdentityPanel.tsx +7 -3
  66. package/src/panels/IdentityPanel/IdentityPanelProps.ts +11 -1
  67. package/src/panels/IdentityPanel/steps/AgentForm.tsx +61 -0
  68. package/src/panels/IdentityPanel/steps/IdentityActionChooser.tsx +5 -1
  69. package/src/panels/IdentityPanel/steps/SignOutChooser.tsx +2 -0
  70. package/src/panels/IdentityPanel/steps/index.ts +1 -1
  71. package/src/panels/IdentityPanel/useAgentHandlers.ts +88 -0
  72. package/src/panels/JoinPanel/joinMachine.ts +15 -18
  73. package/src/panels/JoinPanel/steps/AdditionMethodChooser.tsx +3 -3
  74. package/src/panels/JoinPanel/steps/InvitationInput.tsx +7 -1
  75. package/src/panels/JoinPanel/steps/InvitationRescuer.tsx +2 -2
  76. package/src/panels/JoinPanel/steps/ResetIdentity.tsx +1 -1
  77. package/src/playwright/invitations-manager.ts +5 -1
  78. package/src/playwright/invitations.spec.ts +19 -0
  79. package/src/styles/invitationStatusStyles.ts +6 -6
  80. package/src/testing/shell-manager.ts +40 -13
  81. package/dist/types/src/panels/IdentityPanel/steps/AgentPanel.d.ts +0 -19
  82. package/dist/types/src/panels/IdentityPanel/steps/AgentPanel.d.ts.map +0 -1
  83. package/dist/types/src/panels/IdentityPanel/steps/AgentPanel.js +0 -122
  84. package/dist/types/src/panels/IdentityPanel/steps/AgentPanel.js.map +0 -1
  85. package/src/panels/IdentityPanel/steps/AgentPanel.tsx +0 -165
@@ -220,7 +220,8 @@ var SpaceMemberListImpl = ({ members, onSelect }) => {
220
220
  const { t } = useTranslation3("os");
221
221
  const visibleMembers = members.filter((member) => member.identity);
222
222
  return visibleMembers.length > 0 ? /* @__PURE__ */ React6.createElement(List2, {
223
- classNames: "flex flex-col gap-2"
223
+ classNames: "flex flex-col gap-2",
224
+ "data-testid": "space-members-list"
224
225
  }, visibleMembers.map((member) => {
225
226
  return /* @__PURE__ */ React6.createElement(IdentityListItem, {
226
227
  key: member.identity.identityKey.toHex(),
@@ -521,12 +522,6 @@ import { useControllableState } from "@radix-ui/react-use-controllable-state";
521
522
  import React11, { forwardRef as forwardRef2 } from "react";
522
523
  import { Button as Button3, DropdownMenu, useTranslation as useTranslation5 } from "@dxos/react-ui";
523
524
  import { descriptionText as descriptionText4, getSize as getSize3, mx as mx9 } from "@dxos/react-ui-theme";
524
- var buttonColorFragment = (props) => {
525
- const resolvedVariant = props.variant ?? "default";
526
- return [
527
- !props.disabled ? resolvedVariant === "default" ? "bg-neutral-25 hover:bg-white hover:text-primary-500 active:bg-neutral-25 dark:active:bg-neutral-800" : resolvedVariant === "ghost" ? "active:bg-neutral-125 dark:active:bg-neutral-800" : resolvedVariant === "primary" ? "active:bg-primary-700 dark:active:bg-primary-500" : "" : ""
528
- ];
529
- };
530
525
  var defaultActions = {
531
526
  noopAction: {
532
527
  label: "No-op",
@@ -552,8 +547,7 @@ var BifurcatedAction = /* @__PURE__ */ forwardRef2((props, forwardedRef) => {
552
547
  ...rest,
553
548
  classNames: [
554
549
  "bs-11 flex-1 min-is-0 flex gap-2 rounded-ie-none",
555
- classNames,
556
- ...buttonColorFragment(props)
550
+ classNames
557
551
  ],
558
552
  ref: forwardedRef,
559
553
  variant,
@@ -563,8 +557,7 @@ var BifurcatedAction = /* @__PURE__ */ forwardRef2((props, forwardedRef) => {
563
557
  }, /* @__PURE__ */ React11.createElement(Button3, {
564
558
  classNames: [
565
559
  "bs-11 flex-none rounded-is-none",
566
- classNames,
567
- ...buttonColorFragment(props)
560
+ classNames
568
561
  ]
569
562
  }, /* @__PURE__ */ React11.createElement("span", {
570
563
  className: "sr-only"
@@ -598,7 +591,6 @@ var Action = /* @__PURE__ */ forwardRef2((props, forwardedRef) => {
598
591
  classNames: [
599
592
  isFull && "is-full",
600
593
  "bs-11 flex gap-2 mbs-2",
601
- ...buttonColorFragment(props),
602
594
  classNames
603
595
  ],
604
596
  ref: forwardedRef,
@@ -820,8 +812,8 @@ import { Dialog, useId as useId9 } from "@dxos/react-ui";
820
812
  import React27, { useEffect as useEffect3, useMemo as useMemo3 } from "react";
821
813
  import { generateName as generateName2 } from "@dxos/display-name";
822
814
  import { log as log3 } from "@dxos/log";
823
- import { useClient as useClient4 } from "@dxos/react-client";
824
- import { useIdentity, useDevices } from "@dxos/react-client/halo";
815
+ import { useClient as useClient3 } from "@dxos/react-client";
816
+ import { useIdentity, useDevices, useHaloInvitations as useHaloInvitations2 } from "@dxos/react-client/halo";
825
817
  import { useInvitationStatus as useInvitationStatus2 } from "@dxos/react-client/invitations";
826
818
  import { Avatar as Avatar4, DensityProvider as DensityProvider2, useId as useId5, useJdenticonHref as useJdenticonHref3, useTranslation as useTranslation13 } from "@dxos/react-ui";
827
819
 
@@ -951,106 +943,10 @@ var useIdentityMachine = (client, options) => {
951
943
  });
952
944
  };
953
945
 
954
- // packages/sdk/shell/src/panels/IdentityPanel/steps/AgentPanel.tsx
955
- import React21, { useState as useState3, useCallback as useCallback4, useEffect as useEffect2 } from "react";
956
- import { invariant } from "@dxos/invariant";
957
- import { useClient as useClient2, useAgentHostingProviderClient } from "@dxos/react-client";
958
- import { useHaloInvitations } from "@dxos/react-client/halo";
959
- import { Invitation as Invitation3, InvitationEncoder } from "@dxos/react-client/invitations";
946
+ // packages/sdk/shell/src/panels/IdentityPanel/steps/AgentForm.tsx
947
+ import React21 from "react";
960
948
  import { useTranslation as useTranslation7 } from "@dxos/react-ui";
961
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/steps/AgentPanel.tsx";
962
949
  var AgentForm = (props) => {
963
- const { identity } = props;
964
- const [validationMessage, setValidationMessage] = useState3("");
965
- const [agentStatus, setAgentStatus] = useState3("");
966
- const [agentActive, setAgentActive] = useState3(false);
967
- const client = useClient2();
968
- const invitations = useHaloInvitations();
969
- const agentHostingProviderClient = useAgentHostingProviderClient(client.config);
970
- useEffect2(() => {
971
- const fetchAgentStatus = async () => {
972
- if (agentHostingProviderClient) {
973
- const agentStatus2 = await agentHostingProviderClient?.getAgent(identity?.identityKey.truncate() ?? "foo");
974
- if (agentStatus2) {
975
- setAgentActive(true);
976
- setAgentStatus(agentStatus2);
977
- } else {
978
- setAgentActive(false);
979
- setValidationMessage("No agent deployed via provider.");
980
- }
981
- } else {
982
- setValidationMessage("No agent provider configured.");
983
- }
984
- };
985
- void fetchAgentStatus();
986
- }, []);
987
- const onAgentCreateEvent = useCallback4(async (invitation) => {
988
- const invitationCode = InvitationEncoder.encode(invitation);
989
- if (invitation.state === Invitation3.State.CONNECTING) {
990
- console.log(JSON.stringify({
991
- invitationCode,
992
- authCode: invitation.authCode
993
- }));
994
- invariant(identity, "Identity not found", {
995
- F: __dxlog_file2,
996
- L: 65,
997
- S: void 0,
998
- A: [
999
- "identity",
1000
- "'Identity not found'"
1001
- ]
1002
- });
1003
- if (agentHostingProviderClient) {
1004
- try {
1005
- const res = await agentHostingProviderClient?.createAgent(invitationCode, identity.identityKey.truncate());
1006
- setAgentStatus(res);
1007
- setAgentActive(true);
1008
- setValidationMessage("");
1009
- } catch (err) {
1010
- setValidationMessage(`error creating agent: ${err.message}`);
1011
- }
1012
- }
1013
- }
1014
- }, []);
1015
- const handleAgentCreate = async () => {
1016
- invitations.forEach((invitation2) => invitation2.cancel());
1017
- const invitation = client.halo.share({
1018
- type: Invitation3.Type.MULTIUSE,
1019
- authMethod: Invitation3.AuthMethod.NONE
1020
- });
1021
- invitation.subscribe(onAgentCreateEvent);
1022
- };
1023
- const handleAgentDestroy = async () => {
1024
- const identity2 = client.halo.identity.get();
1025
- invariant(identity2, "Identity not found", {
1026
- F: __dxlog_file2,
1027
- L: 91,
1028
- S: void 0,
1029
- A: [
1030
- "identity",
1031
- "'Identity not found'"
1032
- ]
1033
- });
1034
- try {
1035
- await agentHostingProviderClient?.destroyAgent(identity2.identityKey.truncate());
1036
- setValidationMessage("No agent deployed via provider.");
1037
- setAgentStatus("");
1038
- setAgentActive(false);
1039
- } catch (err) {
1040
- setValidationMessage(`error destroying agent: ${err.message}`);
1041
- }
1042
- };
1043
- return /* @__PURE__ */ React21.createElement(AgentFormImpl, {
1044
- ...props,
1045
- onAgentCreate: handleAgentCreate,
1046
- onAgentDestroy: handleAgentDestroy,
1047
- validationMessage,
1048
- agentStatus,
1049
- agentActive,
1050
- agentProviderDisabled: !agentHostingProviderClient
1051
- });
1052
- };
1053
- var AgentFormImpl = (props) => {
1054
950
  const { active, onAgentCreate, onAgentDestroy, send, validationMessage, agentStatus, agentActive, agentProviderDisabled } = props;
1055
951
  const disabled = !active;
1056
952
  const { t } = useTranslation7("os");
@@ -1103,19 +999,19 @@ var DeviceManager = ({ devices, active, send }) => {
1103
999
 
1104
1000
  // packages/sdk/shell/src/panels/IdentityPanel/steps/IdentityActionChooser.tsx
1105
1001
  import { CaretRight, Devices, Plus, Power, UserGear, HardDrive } from "@phosphor-icons/react";
1106
- import React23, { useCallback as useCallback5 } from "react";
1107
- import { useClient as useClient3 } from "@dxos/react-client";
1108
- import { useHaloInvitations as useHaloInvitations2 } from "@dxos/react-client/halo";
1109
- import { Invitation as Invitation4, InvitationEncoder as InvitationEncoder2 } from "@dxos/react-client/invitations";
1002
+ import React23, { useCallback as useCallback4 } from "react";
1003
+ import { useClient as useClient2 } from "@dxos/react-client";
1004
+ import { useHaloInvitations } from "@dxos/react-client/halo";
1005
+ import { Invitation as Invitation3, InvitationEncoder } from "@dxos/react-client/invitations";
1110
1006
  import { DensityProvider, useTranslation as useTranslation9 } from "@dxos/react-ui";
1111
1007
  import { getSize as getSize6 } from "@dxos/react-ui-theme";
1112
1008
  var IdentityActionChooser = (props) => {
1113
1009
  const { send } = props;
1114
- const client = useClient3();
1115
- const invitations = useHaloInvitations2();
1116
- const onInvitationEvent = useCallback5((invitation) => {
1117
- const invitationCode = InvitationEncoder2.encode(invitation);
1118
- if (invitation.state === Invitation4.State.CONNECTING) {
1010
+ const client = useClient2();
1011
+ const invitations = useHaloInvitations();
1012
+ const onInvitationEvent = useCallback4((invitation) => {
1013
+ const invitationCode = InvitationEncoder.encode(invitation);
1014
+ if (invitation.state === Invitation3.State.CONNECTING) {
1119
1015
  console.log(JSON.stringify({
1120
1016
  invitationCode,
1121
1017
  authCode: invitation.authCode
@@ -1126,8 +1022,8 @@ var IdentityActionChooser = (props) => {
1126
1022
  const testing = e.altKey && e.shiftKey;
1127
1023
  invitations.forEach((invitation2) => invitation2.cancel());
1128
1024
  const invitation = client.halo.share(testing ? {
1129
- type: Invitation4.Type.MULTIUSE,
1130
- authMethod: Invitation4.AuthMethod.NONE
1025
+ type: Invitation3.Type.MULTIUSE,
1026
+ authMethod: Invitation3.AuthMethod.NONE
1131
1027
  } : void 0);
1132
1028
  if (true) {
1133
1029
  invitation.subscribe(onInvitationEvent);
@@ -1203,7 +1099,7 @@ var IdentityActionChooserImpl = ({ onCreateInvitationClick, active, send, onDone
1203
1099
  weight: "bold",
1204
1100
  className: getSize6(4)
1205
1101
  })), /* @__PURE__ */ React23.createElement(Action, {
1206
- "data-testid": "sign-out",
1102
+ "data-testid": "devices-panel.sign-out",
1207
1103
  onClick: () => send?.({
1208
1104
  type: "chooseSignOut"
1209
1105
  }),
@@ -1219,18 +1115,18 @@ var IdentityActionChooserImpl = ({ onCreateInvitationClick, active, send, onDone
1219
1115
  };
1220
1116
 
1221
1117
  // packages/sdk/shell/src/panels/IdentityPanel/steps/ProfileForm.tsx
1222
- import React24, { useState as useState4 } from "react";
1118
+ import React24, { useState as useState3 } from "react";
1223
1119
  import { log as log2 } from "@dxos/log";
1224
1120
  import { useTranslation as useTranslation10 } from "@dxos/react-ui";
1225
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/steps/ProfileForm.tsx";
1121
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/steps/ProfileForm.tsx";
1226
1122
  var ProfileForm = (props) => {
1227
1123
  const { onUpdateProfile } = props;
1228
1124
  const { t } = useTranslation10("os");
1229
- const [validationMessage, setValidationMessage] = useState4("");
1125
+ const [validationMessage, setValidationMessage] = useState3("");
1230
1126
  const handleUpdateProfile = async (profile) => {
1231
1127
  await onUpdateProfile?.(profile).catch((error) => {
1232
1128
  log2.catch(error, void 0, {
1233
- F: __dxlog_file3,
1129
+ F: __dxlog_file2,
1234
1130
  L: 32,
1235
1131
  S: void 0,
1236
1132
  C: (f, a) => f(...a)
@@ -1248,7 +1144,7 @@ var ProfileFormImpl = (props) => {
1248
1144
  const { active, profile, send, onUpdateProfile, validationMessage } = props;
1249
1145
  const disabled = !active;
1250
1146
  const { t } = useTranslation10("os");
1251
- const [inputValue, setInputValue] = useState4(profile?.displayName ?? "");
1147
+ const [inputValue, setInputValue] = useState3(profile?.displayName ?? "");
1252
1148
  return /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement("div", {
1253
1149
  role: "none",
1254
1150
  className: "grow flex flex-col justify-center"
@@ -1315,17 +1211,112 @@ var SignOutChooserImpl = ({ disabled, onResetDevice, onJoinNewIdentity, onBack }
1315
1211
  onClick: onBack
1316
1212
  }, t("back label")), /* @__PURE__ */ React25.createElement(Action, {
1317
1213
  variant: "primary",
1214
+ "data-testid": "sign-out.join-new-identity",
1318
1215
  classNames: "!bg-error-500 hover:!bg-error-550",
1319
1216
  disabled,
1320
1217
  onClick: onJoinNewIdentity
1321
1218
  }, t("join new identity label")), /* @__PURE__ */ React25.createElement(Action, {
1322
1219
  variant: "primary",
1220
+ "data-testid": "sign-out.reset-device",
1323
1221
  classNames: "!bg-error-500 hover:!bg-error-550",
1324
1222
  disabled,
1325
1223
  onClick: onResetDevice
1326
1224
  }, t("reset device label"))));
1327
1225
  };
1328
1226
 
1227
+ // packages/sdk/shell/src/panels/IdentityPanel/useAgentHandlers.ts
1228
+ import { useCallback as useCallback5, useEffect as useEffect2, useState as useState4 } from "react";
1229
+ import { invariant } from "@dxos/invariant";
1230
+ import { useAgentHostingProviderClient } from "@dxos/react-client";
1231
+ import { Invitation as Invitation4, InvitationEncoder as InvitationEncoder2 } from "@dxos/react-client/invitations";
1232
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/useAgentHandlers.ts";
1233
+ var useAgentHandlers = ({ client, invitations, identity }) => {
1234
+ const [validationMessage, setValidationMessage] = useState4("");
1235
+ const [agentStatus, setAgentStatus] = useState4("");
1236
+ const [agentActive, setAgentActive] = useState4(false);
1237
+ const agentHostingProviderClient = useAgentHostingProviderClient(client.config);
1238
+ useEffect2(() => {
1239
+ const fetchAgentStatus = async () => {
1240
+ if (agentHostingProviderClient) {
1241
+ const agentStatus2 = await agentHostingProviderClient?.getAgent(identity?.identityKey.truncate() ?? "foo");
1242
+ if (agentStatus2) {
1243
+ setAgentActive(true);
1244
+ setAgentStatus(agentStatus2);
1245
+ } else {
1246
+ setAgentActive(false);
1247
+ setValidationMessage("No agent deployed via provider.");
1248
+ }
1249
+ } else {
1250
+ setValidationMessage("No agent provider configured.");
1251
+ }
1252
+ };
1253
+ void fetchAgentStatus();
1254
+ }, []);
1255
+ const handleAgentCreate = useCallback5(async (invitation) => {
1256
+ const invitationCode = InvitationEncoder2.encode(invitation);
1257
+ if (invitation.state === Invitation4.State.CONNECTING) {
1258
+ console.log(JSON.stringify({
1259
+ invitationCode,
1260
+ authCode: invitation.authCode
1261
+ }));
1262
+ invariant(identity, "Identity not found", {
1263
+ F: __dxlog_file3,
1264
+ L: 50,
1265
+ S: void 0,
1266
+ A: [
1267
+ "identity",
1268
+ "'Identity not found'"
1269
+ ]
1270
+ });
1271
+ if (agentHostingProviderClient) {
1272
+ try {
1273
+ const res = await agentHostingProviderClient?.createAgent(invitationCode, identity.identityKey.truncate());
1274
+ setAgentStatus(res);
1275
+ setAgentActive(true);
1276
+ setValidationMessage("");
1277
+ } catch (err) {
1278
+ setValidationMessage(`error creating agent: ${err.message}`);
1279
+ }
1280
+ }
1281
+ }
1282
+ }, []);
1283
+ const onAgentCreate = async () => {
1284
+ invitations.forEach((invitation2) => invitation2.cancel());
1285
+ const invitation = client.halo.share({
1286
+ type: Invitation4.Type.MULTIUSE,
1287
+ authMethod: Invitation4.AuthMethod.NONE
1288
+ });
1289
+ invitation.subscribe(handleAgentCreate);
1290
+ };
1291
+ const onAgentDestroy = async () => {
1292
+ const identity2 = client.halo.identity.get();
1293
+ invariant(identity2, "Identity not found", {
1294
+ F: __dxlog_file3,
1295
+ L: 76,
1296
+ S: void 0,
1297
+ A: [
1298
+ "identity",
1299
+ "'Identity not found'"
1300
+ ]
1301
+ });
1302
+ try {
1303
+ await agentHostingProviderClient?.destroyAgent(identity2.identityKey.truncate());
1304
+ setValidationMessage("No agent deployed via provider.");
1305
+ setAgentStatus("");
1306
+ setAgentActive(false);
1307
+ } catch (err) {
1308
+ setValidationMessage(`error destroying agent: ${err.message}`);
1309
+ }
1310
+ };
1311
+ return {
1312
+ onAgentCreate,
1313
+ onAgentDestroy,
1314
+ validationMessage,
1315
+ agentStatus,
1316
+ agentActive
1317
+ };
1318
+ };
1319
+
1329
1320
  // packages/sdk/shell/src/steps/InvitationManager.tsx
1330
1321
  import { Check as Check3, X as X3 } from "@phosphor-icons/react";
1331
1322
  import React26, { useMemo as useMemo2 } from "react";
@@ -1429,7 +1420,8 @@ var IdentityHeading = ({ titleId, title, identity, onDone }) => {
1429
1420
  }, /* @__PURE__ */ React27.createElement(Avatar4.Fallback, {
1430
1421
  href: fallbackHref
1431
1422
  })), /* @__PURE__ */ React27.createElement(Avatar4.Label, {
1432
- classNames: "block text-center font-light text-xl"
1423
+ classNames: "block text-center font-light text-xl",
1424
+ "data-testid": "identityHeading.displayName"
1433
1425
  }, identity.profile?.displayName ?? generateName2(identity.identityKey.toHex()))));
1434
1426
  };
1435
1427
  var IdentityPanelImpl = (props) => {
@@ -1498,7 +1490,7 @@ var IdentityPanelImpl = (props) => {
1498
1490
  }, /* @__PURE__ */ React27.createElement(AgentForm, {
1499
1491
  send: rest.send,
1500
1492
  active: activeView === "agent manager",
1501
- identity
1493
+ ...rest
1502
1494
  })))));
1503
1495
  };
1504
1496
  var IdentityPanelWithInvitationImpl = ({ invitation, ...props }) => {
@@ -1510,9 +1502,15 @@ var IdentityPanelWithInvitationImpl = ({ invitation, ...props }) => {
1510
1502
  };
1511
1503
  var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => code, ...props }) => {
1512
1504
  const titleId = useId5("identityPanel__heading", propsTitleId);
1513
- const client = useClient4();
1505
+ const client = useClient3();
1514
1506
  const devices = useDevices();
1515
1507
  const identity = useIdentity();
1508
+ const invitations = useHaloInvitations2();
1509
+ const agentProps = useAgentHandlers({
1510
+ client,
1511
+ identity,
1512
+ invitations
1513
+ });
1516
1514
  if (!identity) {
1517
1515
  console.error("IdentityPanel rendered with no active identity.");
1518
1516
  return null;
@@ -1522,7 +1520,7 @@ var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => co
1522
1520
  const subscription = identityService.subscribe((state) => {
1523
1521
  log3("[state]", state, {
1524
1522
  F: __dxlog_file4,
1525
- L: 135,
1523
+ L: 138,
1526
1524
  S: void 0,
1527
1525
  C: (f, a) => f(...a)
1528
1526
  });
@@ -1579,7 +1577,8 @@ var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => co
1579
1577
  send: identitySend,
1580
1578
  titleId,
1581
1579
  createInvitationUrl,
1582
- onUpdateProfile
1580
+ onUpdateProfile,
1581
+ ...agentProps
1583
1582
  };
1584
1583
  return identityState.context.invitation ? /* @__PURE__ */ React27.createElement(IdentityPanelWithInvitationImpl, {
1585
1584
  ...implProps,
@@ -1590,7 +1589,7 @@ var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => co
1590
1589
  // packages/sdk/shell/src/panels/JoinPanel/JoinPanel.tsx
1591
1590
  import React37, { useCallback as useCallback7, useEffect as useEffect5, useMemo as useMemo4 } from "react";
1592
1591
  import { log as log8 } from "@dxos/log";
1593
- import { useClient as useClient7, useMulticastObservable } from "@dxos/react-client";
1592
+ import { useClient as useClient6, useMulticastObservable } from "@dxos/react-client";
1594
1593
  import { useIdentity as useIdentity2 } from "@dxos/react-client/halo";
1595
1594
  import { DensityProvider as DensityProvider3, useId as useId7, useThemeContext as useThemeContext3 } from "@dxos/react-ui";
1596
1595
 
@@ -1632,6 +1631,7 @@ import { useMachine as useMachine2 } from "@xstate/react";
1632
1631
  import { useCallback as useCallback6 } from "react";
1633
1632
  import { assign as assign2, createMachine as createMachine2 } from "xstate";
1634
1633
  import { log as log4 } from "@dxos/log";
1634
+ import { AlreadyJoinedError } from "@dxos/react-client";
1635
1635
  import { Invitation as Invitation6, InvitationEncoder as InvitationEncoder3 } from "@dxos/react-client/invitations";
1636
1636
  var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/joinMachine.ts";
1637
1637
  var getInvitationSubscribable = (Kind, invitation) => {
@@ -1750,12 +1750,28 @@ var getInvitationSubscribable = (Kind, invitation) => {
1750
1750
  }
1751
1751
  }
1752
1752
  }, (error) => {
1753
+ if (error instanceof AlreadyJoinedError) {
1754
+ log4("[already joined]", {
1755
+ Kind,
1756
+ error
1757
+ }, {
1758
+ F: __dxlog_file5,
1759
+ L: 137,
1760
+ S: void 0,
1761
+ C: (f, a) => f(...a)
1762
+ });
1763
+ next({
1764
+ type: `success${Kind}Invitation`,
1765
+ invitation: invitation.get()
1766
+ });
1767
+ return complete?.();
1768
+ }
1753
1769
  log4.error("[invitation errored]", {
1754
1770
  Kind,
1755
1771
  error
1756
1772
  }, {
1757
1773
  F: __dxlog_file5,
1758
- L: 136,
1774
+ L: 142,
1759
1775
  S: void 0,
1760
1776
  C: (f, a) => f(...a)
1761
1777
  });
@@ -2080,7 +2096,7 @@ var joinMachine = createMachine2({
2080
2096
  spaceInvitation: context.space.invitation
2081
2097
  }, {
2082
2098
  F: __dxlog_file5,
2083
- L: 400,
2099
+ L: 406,
2084
2100
  S: void 0,
2085
2101
  C: (f, a) => f(...a)
2086
2102
  });
@@ -2094,7 +2110,7 @@ var defaultCodeFromUrl = (invitationType, text) => {
2094
2110
  } catch (err) {
2095
2111
  log4.catch(err, void 0, {
2096
2112
  F: __dxlog_file5,
2097
- L: 427,
2113
+ L: 433,
2098
2114
  S: void 0,
2099
2115
  C: (f, a) => f(...a)
2100
2116
  });
@@ -2105,7 +2121,8 @@ var useJoinMachine = (client, options) => {
2105
2121
  const redeemHaloInvitationCode = useCallback6(({ halo }) => {
2106
2122
  if (halo.unredeemedCode) {
2107
2123
  try {
2108
- const invitationObservable = client.halo.join(InvitationEncoder3.decode(defaultCodeFromUrl("halo", halo.unredeemedCode)));
2124
+ const invitation = InvitationEncoder3.decode(defaultCodeFromUrl("halo", halo.unredeemedCode));
2125
+ const invitationObservable = client.halo.join(invitation);
2109
2126
  return {
2110
2127
  ...halo,
2111
2128
  invitationObservable,
@@ -2114,7 +2131,7 @@ var useJoinMachine = (client, options) => {
2114
2131
  } catch (err) {
2115
2132
  log4.error("Could not redeem device invitation code", err, {
2116
2133
  F: __dxlog_file5,
2117
- L: 449,
2134
+ L: 454,
2118
2135
  S: void 0,
2119
2136
  C: (f, a) => f(...a)
2120
2137
  });
@@ -2130,23 +2147,16 @@ var useJoinMachine = (client, options) => {
2130
2147
  if (space.unredeemedCode) {
2131
2148
  try {
2132
2149
  const invitation = InvitationEncoder3.decode(defaultCodeFromUrl("space", space.unredeemedCode));
2133
- if (space.succeededKeys?.has(invitation.spaceKey?.toHex() ?? "never")) {
2134
- return {
2135
- ...space,
2136
- invitation
2137
- };
2138
- } else {
2139
- const invitationObservable = client.spaces.join(invitation);
2140
- return {
2141
- ...space,
2142
- invitationObservable,
2143
- invitationSubscribable: getInvitationSubscribable("Space", invitationObservable)
2144
- };
2145
- }
2150
+ const invitationObservable = client.spaces.join(invitation);
2151
+ return {
2152
+ ...space,
2153
+ invitationObservable,
2154
+ invitationSubscribable: getInvitationSubscribable("Space", invitationObservable)
2155
+ };
2146
2156
  } catch (err) {
2147
2157
  log4.error("Could not redeem space invitation code", err, {
2148
2158
  F: __dxlog_file5,
2149
- L: 479,
2159
+ L: 476,
2150
2160
  S: void 0,
2151
2161
  C: (f, a) => f(...a)
2152
2162
  });
@@ -2238,7 +2248,7 @@ var AdditionMethodChooser = (viewStateProps) => {
2238
2248
  type: "createIdentity"
2239
2249
  }),
2240
2250
  "data-autofocus": "choosingAuthMethod",
2241
- "data-testid": "create-identity"
2251
+ "data-testid": "identity-chooser.create-identity"
2242
2252
  }, t("create identity label")), /* @__PURE__ */ React29.createElement(CompoundButton, {
2243
2253
  ...sharedButtonProps,
2244
2254
  description: t("join identity description"),
@@ -2248,7 +2258,7 @@ var AdditionMethodChooser = (viewStateProps) => {
2248
2258
  onClick: () => send({
2249
2259
  type: "acceptHaloInvitation"
2250
2260
  }),
2251
- "data-testid": "join-identity"
2261
+ "data-testid": "identity-chooser.join-identity"
2252
2262
  }, t("join identity label")), /* @__PURE__ */ React29.createElement(CompoundButton, {
2253
2263
  ...sharedButtonProps,
2254
2264
  // TODO(mykola): Implement recover.
@@ -2260,7 +2270,7 @@ var AdditionMethodChooser = (viewStateProps) => {
2260
2270
  onClick: () => send({
2261
2271
  type: "recoverIdentity"
2262
2272
  }),
2263
- "data-testid": "recover-identity"
2273
+ "data-testid": "identity-chooser.recover-identity"
2264
2274
  }, t("recover identity label"))));
2265
2275
  };
2266
2276
 
@@ -2309,13 +2319,13 @@ var IdentityAdded = (props) => {
2309
2319
  // packages/sdk/shell/src/panels/JoinPanel/steps/IdentityInput.tsx
2310
2320
  import React31, { useState as useState5 } from "react";
2311
2321
  import { log as log5 } from "@dxos/log";
2312
- import { useClient as useClient5 } from "@dxos/react-client";
2322
+ import { useClient as useClient4 } from "@dxos/react-client";
2313
2323
  import { useTranslation as useTranslation17 } from "@dxos/react-ui";
2314
2324
  var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/steps/IdentityInput.tsx";
2315
2325
  var IdentityInput = (props) => {
2316
2326
  const { send, method } = props;
2317
2327
  const isRecover = method === "recover identity";
2318
- const client = useClient5();
2328
+ const client = useClient4();
2319
2329
  const { t } = useTranslation17("os");
2320
2330
  const [validationMessage, setValidationMessage] = useState5("");
2321
2331
  const createIdentity = (displayName) => {
@@ -2425,13 +2435,18 @@ var InvitationInput = (props) => {
2425
2435
  }, [
2426
2436
  unredeemedCode
2427
2437
  ]);
2428
- const handleNext = () => send({
2429
- type: `set${Kind}InvitationCode`,
2430
- code: invitationCodeFromUrl(inputValue),
2431
- ...Kind === "Space" && {
2432
- succeededKeys
2438
+ const handleNext = () => {
2439
+ if (inputValue.trim().length === 0) {
2440
+ return;
2433
2441
  }
2434
- });
2442
+ send({
2443
+ type: `set${Kind}InvitationCode`,
2444
+ code: invitationCodeFromUrl(inputValue),
2445
+ ...Kind === "Space" && {
2446
+ succeededKeys
2447
+ }
2448
+ });
2449
+ };
2435
2450
  const exitAction = /* @__PURE__ */ React33.createElement(Action, {
2436
2451
  variant: "ghost",
2437
2452
  disabled,
@@ -2447,6 +2462,7 @@ var InvitationInput = (props) => {
2447
2462
  className: "grow flex flex-col justify-center"
2448
2463
  }, /* @__PURE__ */ React33.createElement(Input, {
2449
2464
  label: /* @__PURE__ */ React33.createElement(StepHeading, null, t("invitation input label")),
2465
+ // TODO(burdon): Translation.
2450
2466
  placeholder: "Type an invitation code",
2451
2467
  disabled,
2452
2468
  value: inputValue,
@@ -2585,11 +2601,11 @@ var InvitationAuthenticator = ({ failed, Kind, active, pending, invitationId, on
2585
2601
  // packages/sdk/shell/src/panels/JoinPanel/steps/ResetIdentity.tsx
2586
2602
  import React36, { useState as useState8 } from "react";
2587
2603
  import { log as log7 } from "@dxos/log";
2588
- import { useClient as useClient6 } from "@dxos/react-client";
2604
+ import { useClient as useClient5 } from "@dxos/react-client";
2589
2605
  import { useTranslation as useTranslation22 } from "@dxos/react-ui";
2590
2606
  var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/steps/ResetIdentity.tsx";
2591
2607
  var ResetIdentity = ({ send, active }) => {
2592
- const client = useClient6();
2608
+ const client = useClient5();
2593
2609
  const { t } = useTranslation22("os");
2594
2610
  const [validationMessage, setValidationMessage] = useState8("");
2595
2611
  const resetIdentity = () => {
@@ -2624,7 +2640,7 @@ var ResetIdentityImpl = ({ disabled, validationMessage, onConfirm }) => {
2624
2640
  confirmationValue
2625
2641
  })),
2626
2642
  disabled,
2627
- "data-testid": "identity-input",
2643
+ "data-testid": "reset-identity-input",
2628
2644
  placeholder: confirmationValue,
2629
2645
  onChange: ({ target: { value } }) => setInputValue(value)
2630
2646
  })), /* @__PURE__ */ React36.createElement(Actions, null, /* @__PURE__ */ React36.createElement(Action, {
@@ -2803,7 +2819,7 @@ var JoinPanelImpl = (props) => {
2803
2819
  })))));
2804
2820
  };
2805
2821
  var JoinPanel = ({ titleId: propsTitleId, mode = "default", initialInvitationCode, exitActionParent, onExit, doneActionParent, onDone: propsOnDone }) => {
2806
- const client = useClient7();
2822
+ const client = useClient6();
2807
2823
  const identity = useIdentity2();
2808
2824
  const { hasIosKeyboard } = useThemeContext3();
2809
2825
  const titleId = useId7("joinPanel__heading", propsTitleId);
@@ -3419,7 +3435,7 @@ import { createIFramePort } from "@dxos/rpc-tunnel";
3419
3435
  // packages/sdk/shell/src/composites/Shell/Shell.tsx
3420
3436
  import React43, { useEffect as useEffect7, useState as useState10 } from "react";
3421
3437
  import { log as log11 } from "@dxos/log";
3422
- import { ShellDisplay, ShellLayout, useClient as useClient8 } from "@dxos/react-client";
3438
+ import { ShellDisplay, ShellLayout, useClient as useClient7 } from "@dxos/react-client";
3423
3439
  import { useSpace as useSpace2 } from "@dxos/react-client/echo";
3424
3440
 
3425
3441
  // packages/sdk/shell/src/composites/SpaceDialog/SpaceDialog.tsx
@@ -3450,7 +3466,7 @@ var Shell = ({ runtime, origin }) => {
3450
3466
  spaceKey: runtime.spaceKey,
3451
3467
  target: runtime.target
3452
3468
  });
3453
- const client = useClient8();
3469
+ const client = useClient7();
3454
3470
  const space = useSpace2(spaceKey);
3455
3471
  useEffect7(() => {
3456
3472
  return runtime.layoutUpdate.on((request) => setLayout(request));
@@ -3707,7 +3723,7 @@ var runShell = async (config = new Config()) => {
3707
3723
 
3708
3724
  // packages/sdk/shell/src/composites/Shell/ShellContext.tsx
3709
3725
  import React45, { createContext as createContext2, useCallback as useCallback9, useContext as useContext2, useEffect as useEffect8, useMemo as useMemo6, useState as useState11 } from "react";
3710
- import { ShellDisplay as ShellDisplay2, ShellLayout as ShellLayout3, useClient as useClient9 } from "@dxos/react-client";
3726
+ import { ShellDisplay as ShellDisplay2, ShellLayout as ShellLayout3, useClient as useClient8 } from "@dxos/react-client";
3711
3727
  import { useIdentity as useIdentity3 } from "@dxos/react-client/halo";
3712
3728
  import { mx as mx23 } from "@dxos/react-ui-theme";
3713
3729
 
@@ -3745,7 +3761,7 @@ var MemoryShellRuntime = class {
3745
3761
  // packages/sdk/shell/src/composites/Shell/ShellContext.tsx
3746
3762
  var ShellContext = /* @__PURE__ */ createContext2({});
3747
3763
  var useShell = () => {
3748
- const client = useClient9();
3764
+ const client = useClient8();
3749
3765
  const { runtime, setDisplay } = useContext2(ShellContext);
3750
3766
  const setLayout = async (layout, options) => {
3751
3767
  if (runtime) {
@@ -3766,7 +3782,7 @@ var useShell = () => {
3766
3782
  };
3767
3783
  };
3768
3784
  var ShellProvider = ({ space, deviceInvitationCode, spaceInvitationCode, onJoinedSpace, children }) => {
3769
- const client = useClient9();
3785
+ const client = useClient8();
3770
3786
  const identity = useIdentity3();
3771
3787
  const [display, setDisplay] = useState11(!identity || spaceInvitationCode || deviceInvitationCode ? ShellDisplay2.FULLSCREEN : ShellDisplay2.NONE);
3772
3788
  const shellRuntime = useMemo6(() => {