ethagent 1.1.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +126 -30
  3. package/package.json +7 -2
  4. package/src/app/FirstRun.tsx +190 -146
  5. package/src/app/FirstRunTimeline.tsx +47 -0
  6. package/src/app/input/AppInputProvider.tsx +1 -1
  7. package/src/app/keybindings/KeybindingProvider.tsx +1 -1
  8. package/src/chat/ChatBottomPane.tsx +0 -1
  9. package/src/chat/ChatInput.tsx +6 -6
  10. package/src/chat/ChatScreen.tsx +35 -15
  11. package/src/chat/ContextLimitView.tsx +4 -4
  12. package/src/chat/ContinuityEditReviewView.tsx +10 -22
  13. package/src/chat/CopyPicker.tsx +0 -1
  14. package/src/chat/MessageList.tsx +62 -45
  15. package/src/chat/PermissionPrompt.tsx +13 -9
  16. package/src/chat/PlanApprovalView.tsx +3 -3
  17. package/src/chat/ResumeView.tsx +1 -4
  18. package/src/chat/RewindView.tsx +2 -2
  19. package/src/chat/chatInputState.ts +1 -1
  20. package/src/chat/chatScreenUtils.ts +22 -11
  21. package/src/chat/chatSessionState.ts +2 -2
  22. package/src/chat/chatTurnOrchestrator.ts +16 -81
  23. package/src/chat/commands.ts +1 -1
  24. package/src/chat/textCursor.ts +1 -1
  25. package/src/chat/transcriptViewport.ts +2 -7
  26. package/src/cli/ResetConfirmView.tsx +1 -1
  27. package/src/cli/main.tsx +9 -3
  28. package/src/cli/preview.tsx +0 -5
  29. package/src/cli/updateNotice.ts +4 -2
  30. package/src/identity/continuity/editor.ts +7 -107
  31. package/src/identity/continuity/envelope.ts +1048 -40
  32. package/src/identity/continuity/history.ts +4 -4
  33. package/src/identity/continuity/localBackup.ts +249 -0
  34. package/src/identity/continuity/privateEdit/apply.ts +170 -0
  35. package/src/identity/continuity/privateEdit/diff.ts +82 -0
  36. package/src/identity/continuity/privateEdit/files.ts +23 -0
  37. package/src/identity/continuity/privateEdit/types.ts +28 -0
  38. package/src/identity/continuity/privateEdit.ts +10 -298
  39. package/src/identity/continuity/publicSkills.ts +8 -9
  40. package/src/identity/continuity/snapshots.ts +17 -6
  41. package/src/identity/continuity/storage/defaults.ts +111 -0
  42. package/src/identity/continuity/storage/files.ts +72 -0
  43. package/src/identity/continuity/storage/markdown.ts +81 -0
  44. package/src/identity/continuity/storage/paths.ts +24 -0
  45. package/src/identity/continuity/storage/scaffold.ts +124 -0
  46. package/src/identity/continuity/storage/status.ts +86 -0
  47. package/src/identity/continuity/storage/types.ts +27 -0
  48. package/src/identity/continuity/storage.ts +32 -507
  49. package/src/identity/continuity/zipWriter.ts +95 -0
  50. package/src/identity/crypto/backupEnvelope.ts +14 -247
  51. package/src/identity/crypto/eth.ts +7 -7
  52. package/src/identity/ens/agentRecords.ts +96 -0
  53. package/src/identity/ens/ensAutomation/contracts.ts +38 -0
  54. package/src/identity/ens/ensAutomation/delete.ts +80 -0
  55. package/src/identity/ens/ensAutomation/names.ts +14 -0
  56. package/src/identity/ens/ensAutomation/operators.ts +29 -0
  57. package/src/identity/ens/ensAutomation/read.ts +114 -0
  58. package/src/identity/ens/ensAutomation/root.ts +63 -0
  59. package/src/identity/ens/ensAutomation/setup.ts +284 -0
  60. package/src/identity/ens/ensAutomation/transactions.ts +107 -0
  61. package/src/identity/ens/ensAutomation/types.ts +126 -0
  62. package/src/identity/ens/ensAutomation.ts +29 -0
  63. package/src/identity/ens/ensLookup/client.ts +43 -0
  64. package/src/identity/ens/ensLookup/constants.ts +26 -0
  65. package/src/identity/ens/ensLookup/discovery.ts +70 -0
  66. package/src/identity/ens/ensLookup/names.ts +34 -0
  67. package/src/identity/ens/ensLookup/records.ts +45 -0
  68. package/src/identity/ens/ensLookup/resolve.ts +75 -0
  69. package/src/identity/ens/ensLookup/tokenReference.ts +17 -0
  70. package/src/identity/ens/ensLookup/types.ts +38 -0
  71. package/src/identity/ens/ensLookup/validation.ts +72 -0
  72. package/src/identity/ens/ensLookup.ts +19 -0
  73. package/src/identity/ens/ensRegistration.ts +199 -0
  74. package/src/identity/ens/resolverDelegation.ts +48 -0
  75. package/src/identity/hub/IdentityHub.tsx +13 -817
  76. package/src/identity/hub/OperationalRoutes.tsx +370 -0
  77. package/src/identity/hub/Routes.tsx +361 -0
  78. package/src/identity/hub/advancedEnsValidation.ts +45 -0
  79. package/src/identity/hub/{screens → components}/DetailsScreen.tsx +14 -8
  80. package/src/identity/hub/{screens → components}/ErrorScreen.tsx +15 -5
  81. package/src/identity/hub/components/FlowTimeline.tsx +27 -0
  82. package/src/identity/hub/components/IdentitySummary.tsx +190 -0
  83. package/src/identity/hub/components/MenuScreen.tsx +237 -0
  84. package/src/identity/hub/{screens → components}/NetworkScreen.tsx +3 -3
  85. package/src/identity/hub/{screens/RebackupStorageScreen.tsx → components/PinataJwtInput.tsx} +21 -18
  86. package/src/identity/hub/components/UnlinkedIdentityScreen.tsx +76 -0
  87. package/src/identity/hub/{screens → components}/WalletApprovalScreen.tsx +9 -8
  88. package/src/identity/hub/components/menuFlagsFromReconciliation.ts +68 -0
  89. package/src/identity/hub/effects/create.ts +310 -0
  90. package/src/identity/hub/effects/ens/flows.ts +218 -0
  91. package/src/identity/hub/effects/ens/index.ts +11 -0
  92. package/src/identity/hub/effects/ens/transactions.ts +239 -0
  93. package/src/identity/hub/effects/index.ts +74 -0
  94. package/src/identity/hub/effects/profile/profileState.ts +173 -0
  95. package/src/identity/hub/effects/publicProfile/index.ts +5 -0
  96. package/src/identity/hub/effects/publicProfile/runPublicProfileSave.ts +646 -0
  97. package/src/identity/hub/effects/rebackup/index.ts +7 -0
  98. package/src/identity/hub/effects/rebackup/operatorVault.ts +378 -0
  99. package/src/identity/hub/effects/rebackup/runRebackup.ts +451 -0
  100. package/src/identity/hub/effects/receipts.ts +46 -0
  101. package/src/identity/hub/effects/restore/apply.ts +112 -0
  102. package/src/identity/hub/effects/restore/auth.ts +159 -0
  103. package/src/identity/hub/effects/restore/discover.ts +86 -0
  104. package/src/identity/hub/effects/restore/envelopes.ts +21 -0
  105. package/src/identity/hub/effects/restore/fetch.ts +25 -0
  106. package/src/identity/hub/effects/restore/index.ts +22 -0
  107. package/src/identity/hub/effects/restore/recovery.ts +135 -0
  108. package/src/identity/hub/effects/restore/resolve.ts +102 -0
  109. package/src/identity/hub/effects/restore/restoreEffects.ts +22 -0
  110. package/src/identity/hub/effects/restore/shared.ts +91 -0
  111. package/src/identity/hub/effects/restoreAdmin.ts +93 -0
  112. package/src/identity/hub/effects/shared/profilePrep.ts +139 -0
  113. package/src/identity/hub/effects/shared/snapshot.ts +336 -0
  114. package/src/identity/hub/effects/shared/sync.ts +190 -0
  115. package/src/identity/hub/effects/token-transfer/index.ts +6 -0
  116. package/src/identity/hub/effects/token-transfer/progress.ts +59 -0
  117. package/src/identity/hub/effects/token-transfer/runTokenTransfer.ts +299 -0
  118. package/src/identity/hub/effects/types.ts +53 -0
  119. package/src/identity/hub/effects/vault/preflight.ts +50 -0
  120. package/src/identity/hub/flows/continuity/ContinuityDashboardScreen.tsx +170 -0
  121. package/src/identity/hub/flows/continuity/RebackupStorageScreen.tsx +28 -0
  122. package/src/identity/hub/{screens → flows/continuity}/RecoveryConfirmScreen.tsx +28 -19
  123. package/src/identity/hub/flows/continuity/SavePromptScreen.tsx +49 -0
  124. package/src/identity/hub/{screens → flows/create}/CreateFlow.tsx +61 -62
  125. package/src/identity/hub/flows/custody/CustodyEditFlow.tsx +347 -0
  126. package/src/identity/hub/flows/custody/custodyEffects.ts +321 -0
  127. package/src/identity/hub/flows/custody/custodyFlowActions.ts +236 -0
  128. package/src/identity/hub/flows/custody/custodyFlowEffects.ts +163 -0
  129. package/src/identity/hub/flows/custody/custodyFlowHelpers.ts +25 -0
  130. package/src/identity/hub/flows/custody/custodyFlowRoutes.tsx +239 -0
  131. package/src/identity/hub/flows/custody/custodyFlowTypes.ts +45 -0
  132. package/src/identity/hub/flows/custody/useCustodyFlow.tsx +25 -0
  133. package/src/identity/hub/flows/ens/EnsEditAdvancedScreens.tsx +336 -0
  134. package/src/identity/hub/flows/ens/EnsEditFlow.tsx +397 -0
  135. package/src/identity/hub/flows/ens/EnsEditMaintenanceScreens.tsx +332 -0
  136. package/src/identity/hub/flows/ens/EnsEditReviewScreens.tsx +471 -0
  137. package/src/identity/hub/flows/ens/EnsEditRunners.tsx +198 -0
  138. package/src/identity/hub/flows/ens/EnsEditShared.tsx +162 -0
  139. package/src/identity/hub/flows/ens/EnsEditSimpleScreens.tsx +518 -0
  140. package/src/identity/hub/flows/ens/IdentityHubEnsFlow.tsx +299 -0
  141. package/src/identity/hub/flows/ens/OperatorWalletsScreen.tsx +398 -0
  142. package/src/identity/hub/flows/ens/ensEditCopy.ts +117 -0
  143. package/src/identity/hub/flows/ens/ensEditTypes.ts +91 -0
  144. package/src/identity/hub/flows/profile/EditProfileFlow.tsx +271 -0
  145. package/src/identity/hub/flows/restore/RestoreFlow.tsx +324 -0
  146. package/src/identity/hub/flows/restore/useRestoreFlowEffects.ts +77 -0
  147. package/src/identity/hub/{screens → flows/settings}/StorageCredentialScreen.tsx +23 -44
  148. package/src/identity/hub/flows/token-transfer/IdentityHubTokenTransferFlow.tsx +162 -0
  149. package/src/identity/hub/flows/token-transfer/TokenTransferScreens.tsx +256 -0
  150. package/src/identity/hub/identityHubReducer.ts +164 -99
  151. package/src/identity/hub/model/continuity.ts +94 -0
  152. package/src/identity/hub/model/copy.ts +35 -0
  153. package/src/identity/hub/model/custody.ts +54 -0
  154. package/src/identity/hub/model/ens.ts +49 -0
  155. package/src/identity/hub/model/errors.ts +140 -0
  156. package/src/identity/hub/model/format.ts +15 -0
  157. package/src/identity/hub/model/identity.ts +94 -0
  158. package/src/identity/hub/model/network.ts +32 -0
  159. package/src/identity/hub/model/transfer.ts +57 -0
  160. package/src/identity/hub/operatorWallets.ts +131 -0
  161. package/src/identity/hub/reconciliation/agentReconciliation/hook.ts +46 -0
  162. package/src/identity/hub/reconciliation/agentReconciliation/ownership.ts +129 -0
  163. package/src/identity/hub/reconciliation/agentReconciliation/run.ts +302 -0
  164. package/src/identity/hub/reconciliation/agentReconciliation/types.ts +17 -0
  165. package/src/identity/hub/reconciliation/index.ts +21 -0
  166. package/src/identity/hub/reconciliation/useAgentReconciliation.ts +10 -0
  167. package/src/identity/hub/reconciliation/walletSetup.ts +220 -0
  168. package/src/identity/hub/txGuard.ts +51 -0
  169. package/src/identity/hub/types.ts +17 -0
  170. package/src/identity/hub/useIdentityHubContinuity.ts +136 -0
  171. package/src/identity/hub/useIdentityHubController.ts +396 -0
  172. package/src/identity/hub/useIdentityHubSideEffects.ts +309 -0
  173. package/src/identity/hub/utils.ts +79 -0
  174. package/src/identity/identityCompat.ts +34 -0
  175. package/src/identity/profile/agentIcon.ts +61 -0
  176. package/src/identity/profile/imagePicker.ts +12 -12
  177. package/src/identity/registry/erc8004/abi.ts +14 -0
  178. package/src/identity/registry/erc8004/chains.ts +150 -0
  179. package/src/identity/registry/erc8004/client.ts +11 -0
  180. package/src/identity/registry/erc8004/discovery.ts +511 -0
  181. package/src/identity/registry/erc8004/metadata.ts +335 -0
  182. package/src/identity/registry/erc8004/ownership.ts +121 -0
  183. package/src/identity/registry/erc8004/preflight.ts +123 -0
  184. package/src/identity/registry/erc8004/transactions.ts +77 -0
  185. package/src/identity/registry/erc8004/types.ts +88 -0
  186. package/src/identity/registry/erc8004/uri.ts +59 -0
  187. package/src/identity/registry/erc8004/utils.ts +58 -0
  188. package/src/identity/registry/erc8004.ts +53 -1106
  189. package/src/identity/registry/fieldParsers.ts +28 -0
  190. package/src/identity/registry/operatorVault/bytecode.ts +98 -0
  191. package/src/identity/registry/operatorVault/constants.ts +38 -0
  192. package/src/identity/registry/operatorVault/read.ts +246 -0
  193. package/src/identity/registry/operatorVault/transactions.ts +81 -0
  194. package/src/identity/registry/operatorVault.ts +44 -0
  195. package/src/identity/storage/ipfs.ts +26 -24
  196. package/src/identity/wallet/browserWallet/gas.ts +41 -0
  197. package/src/identity/wallet/browserWallet/html.ts +106 -0
  198. package/src/identity/wallet/browserWallet/http.ts +28 -0
  199. package/src/identity/wallet/browserWallet/requestServer.ts +106 -0
  200. package/src/identity/wallet/browserWallet/requests.ts +191 -0
  201. package/src/identity/wallet/browserWallet/session.ts +325 -0
  202. package/src/identity/wallet/browserWallet/types.ts +192 -0
  203. package/src/identity/wallet/browserWallet/validation.ts +74 -0
  204. package/src/identity/wallet/browserWallet.ts +30 -393
  205. package/src/identity/wallet/page/constants.ts +5 -0
  206. package/src/identity/wallet/page/controller.ts +251 -0
  207. package/src/identity/wallet/page/copy.ts +340 -0
  208. package/src/identity/wallet/page/grainient.ts +278 -0
  209. package/src/identity/wallet/page/html.ts +28 -0
  210. package/src/identity/wallet/page/markup.ts +50 -0
  211. package/src/identity/wallet/page/state.ts +9 -0
  212. package/src/identity/wallet/page/styles/base.ts +259 -0
  213. package/src/identity/wallet/page/styles/components.ts +262 -0
  214. package/src/identity/wallet/page/styles/index.ts +5 -0
  215. package/src/identity/wallet/page/styles/responsive.ts +247 -0
  216. package/src/identity/wallet/page/types.ts +47 -0
  217. package/src/identity/wallet/page/view.ts +535 -0
  218. package/src/identity/wallet/page/walletProvider.ts +70 -0
  219. package/src/identity/wallet/page.tsx +38 -0
  220. package/src/identity/wallet/walletPurposeCompat.ts +27 -0
  221. package/src/mcp/manager.ts +0 -1
  222. package/src/models/ModelPicker.tsx +36 -30
  223. package/src/models/catalog.ts +5 -2
  224. package/src/models/huggingface.ts +9 -9
  225. package/src/models/llamacpp.ts +13 -13
  226. package/src/models/modelDisplay.ts +75 -0
  227. package/src/models/modelPickerOptions.ts +16 -3
  228. package/src/models/modelRecommendation.ts +0 -1
  229. package/src/providers/errors.ts +16 -0
  230. package/src/providers/gemini.ts +252 -39
  231. package/src/providers/registry.ts +2 -2
  232. package/src/providers/retry.ts +1 -1
  233. package/src/runtime/sessionMode.ts +1 -1
  234. package/src/runtime/systemPrompt.ts +2 -0
  235. package/src/runtime/toolExecution.ts +18 -22
  236. package/src/runtime/toolIntent.ts +0 -20
  237. package/src/runtime/turn.ts +0 -92
  238. package/src/storage/atomicWrite.ts +4 -1
  239. package/src/storage/config.ts +181 -5
  240. package/src/storage/identity.ts +9 -3
  241. package/src/storage/secrets.ts +2 -2
  242. package/src/tools/bashSafety.ts +8 -0
  243. package/src/tools/changeDirectoryTool.ts +1 -1
  244. package/src/tools/deleteFileTool.ts +4 -4
  245. package/src/tools/editTool.ts +4 -4
  246. package/src/tools/editUtils.ts +5 -5
  247. package/src/tools/privateContinuityEditTool.ts +4 -5
  248. package/src/tools/privateContinuityReadTool.ts +1 -2
  249. package/src/tools/registry.ts +30 -0
  250. package/src/tools/writeFileTool.ts +5 -5
  251. package/src/ui/BrandSplash.tsx +20 -85
  252. package/src/ui/ProgressBar.tsx +3 -5
  253. package/src/ui/Select.tsx +20 -8
  254. package/src/ui/Spinner.tsx +38 -3
  255. package/src/ui/Surface.tsx +2 -2
  256. package/src/ui/TextInput.tsx +63 -20
  257. package/src/ui/theme.ts +7 -34
  258. package/src/utils/openExternal.ts +21 -0
  259. package/src/utils/withRetry.ts +47 -3
  260. package/src/identity/hub/identityHubEffects.ts +0 -937
  261. package/src/identity/hub/identityHubModel.ts +0 -371
  262. package/src/identity/hub/screens/ContinuityDashboardScreen.tsx +0 -156
  263. package/src/identity/hub/screens/EditProfileFlow.tsx +0 -146
  264. package/src/identity/hub/screens/IdentitySummary.tsx +0 -106
  265. package/src/identity/hub/screens/MenuScreen.tsx +0 -117
  266. package/src/identity/hub/screens/RestoreFlow.tsx +0 -206
  267. package/src/identity/wallet/wallet-page/wallet.html +0 -1202
  268. /package/src/identity/hub/{screens → components}/BusyScreen.tsx +0 -0
@@ -0,0 +1,332 @@
1
+ import React from 'react'
2
+ import { Box, Text } from 'ink'
3
+ import type { Address } from 'viem'
4
+ import { Surface } from '../../../../ui/Surface.js'
5
+ import { Select } from '../../../../ui/Select.js'
6
+ import { Spinner } from '../../../../ui/Spinner.js'
7
+ import { theme } from '../../../../ui/theme.js'
8
+ import type { BrowserWalletReady } from '../../../wallet/browserWallet.js'
9
+ import {
10
+ type CustodyMode,
11
+ } from '../../model/custody.js'
12
+ import { shortAddress } from '../../model/format.js'
13
+ import {
14
+ emptyAgentEnsRecords,
15
+ recordsHaveCurrentValues,
16
+ unlinkEnsLinkOptions,
17
+ } from './ensEditCopy.js'
18
+ import {
19
+ AssignEnsCurrentSetup,
20
+ EnsSetupRow,
21
+ footerHint,
22
+ } from './EnsEditShared.js'
23
+ import { UnlinkEnsReviewScreen } from './EnsEditReviewScreens.js'
24
+ import {
25
+ DeleteSubdomainTxRunner,
26
+ EscCancel,
27
+ } from './EnsEditRunners.js'
28
+ import type {
29
+ EnsEditProps,
30
+ EnsPhase,
31
+ } from './ensEditTypes.js'
32
+
33
+ type MaintenanceScreenProps = {
34
+ phase: EnsPhase
35
+ currentEnsName: string
36
+ currentEnsCanDelete: boolean
37
+ savedCustodyMode: CustodyMode | undefined
38
+ savedOwnerAddress: string
39
+ savedOperator: string
40
+ registryNetworkLabel: string
41
+ validationError: string | null
42
+ ownerAddress: Address
43
+ operatorWalletSession: BrowserWalletReady | null
44
+ setOperatorWalletSession: (session: BrowserWalletReady | null) => void
45
+ setPhase: (phase: EnsPhase) => void
46
+ runDiscovery: () => void
47
+ runUnlinkEnsLoading: (fullName: string) => void
48
+ runDeleteSubdomainPreflight: (fullName: string) => void
49
+ onBack: () => void
50
+ onEnsUnlink: EnsEditProps['onEnsUnlink']
51
+ onEnsRecordsUpdate: EnsEditProps['onEnsRecordsUpdate']
52
+ onManageOperatorWalletAccess: EnsEditProps['onManageOperatorWalletAccess']
53
+ }
54
+
55
+ export function renderEnsMaintenancePhase({
56
+ phase,
57
+ currentEnsName,
58
+ currentEnsCanDelete,
59
+ savedCustodyMode,
60
+ savedOwnerAddress,
61
+ savedOperator,
62
+ registryNetworkLabel,
63
+ validationError,
64
+ ownerAddress,
65
+ operatorWalletSession,
66
+ setOperatorWalletSession,
67
+ setPhase,
68
+ runDiscovery,
69
+ runUnlinkEnsLoading,
70
+ runDeleteSubdomainPreflight,
71
+ onBack,
72
+ onEnsUnlink,
73
+ onEnsRecordsUpdate,
74
+ onManageOperatorWalletAccess,
75
+ }: MaintenanceScreenProps): React.ReactNode | null {
76
+ if (phase.kind === 'mode-select') {
77
+ type EnsAction = 'link' | 'unlink' | 'delete-subdomain' | 'manage-operator-wallets' | 'back'
78
+ const isAdvanced = savedCustodyMode === 'advanced'
79
+ const multiNeedsCustodySetup = isAdvanced && !savedOwnerAddress
80
+ const subtitle = currentEnsName
81
+ ? `This agent resolves at ${currentEnsName}.`
82
+ : 'Link an ENS name so others can find this agent by name instead of token ID.'
83
+ const linkHint = multiNeedsCustodySetup
84
+ ? 'Set Advanced custody first via Custody Mode'
85
+ : isAdvanced
86
+ ? 'Walks you through Root, Name, Operator Wallet, Review, and Apply'
87
+ : 'Walks you through Root, Name, Review, and Apply'
88
+ const options: Array<{ value: EnsAction; role?: 'section' | 'utility'; label: string; hint?: string; disabled?: boolean }> = []
89
+ options.push({ value: 'link', role: 'section', label: 'Name' })
90
+ if (currentEnsName) {
91
+ options.push({ value: 'unlink', label: 'Unlink Name', hint: 'Removes this name from the token. Set up a different name afterward by linking again.' })
92
+ if (currentEnsCanDelete) {
93
+ options.push({
94
+ value: 'delete-subdomain',
95
+ label: 'Delete Subdomain',
96
+ hint: 'Clear the onchain subdomain entry at the parent name. The label is freed for reuse, and this token unlinks from it.',
97
+ })
98
+ }
99
+ } else {
100
+ options.push({
101
+ value: 'link',
102
+ label: 'Set Up Name',
103
+ hint: linkHint,
104
+ disabled: multiNeedsCustodySetup,
105
+ })
106
+ }
107
+ if (isAdvanced && savedOwnerAddress) {
108
+ options.push({ value: 'manage-operator-wallets', role: 'section', label: 'Operator Wallets' })
109
+ options.push({
110
+ value: 'manage-operator-wallets',
111
+ label: 'Manage Operator Wallets',
112
+ hint: "Authorize or revoke wallets that can update this name's token and profile text records on your behalf",
113
+ })
114
+ }
115
+ options.push({ value: 'back', role: 'section', label: 'Navigation' })
116
+ options.push({ value: 'back', label: 'Back', hint: 'Return to Identity Hub', role: 'utility' })
117
+ return (
118
+ <Surface
119
+ title="ENS Name"
120
+ subtitle={subtitle}
121
+ footer={footerHint('picking an action starts a stepped flow · enter select · esc back')}
122
+ >
123
+ <AssignEnsCurrentSetup
124
+ currentEnsName={currentEnsName}
125
+ currentMode={savedCustodyMode}
126
+ ownerAddress={savedOwnerAddress}
127
+ operatorAddress={savedOperator}
128
+ tokenNetworkLabel={registryNetworkLabel}
129
+ />
130
+ {!currentEnsName ? (
131
+ <Box marginTop={1}>
132
+ <Text color={theme.dim}>No subdomain linked yet. Discovery falls back to the token ID + network pair until one is set.</Text>
133
+ </Box>
134
+ ) : null}
135
+ {validationError ? <Text color={theme.accentError}>{validationError}</Text> : null}
136
+ <Box marginTop={1}>
137
+ <Select<EnsAction>
138
+ options={options}
139
+ hintLayout="inline"
140
+ onSubmit={choice => {
141
+ if (choice === 'back') return onBack()
142
+ if (choice === 'unlink' && currentEnsName) {
143
+ runUnlinkEnsLoading(currentEnsName)
144
+ return
145
+ }
146
+ if (choice === 'delete-subdomain' && currentEnsName && currentEnsCanDelete) {
147
+ runDeleteSubdomainPreflight(currentEnsName)
148
+ return
149
+ }
150
+ if (choice === 'manage-operator-wallets') {
151
+ onManageOperatorWalletAccess()
152
+ return
153
+ }
154
+ if (choice === 'link') {
155
+ if (multiNeedsCustodySetup) return
156
+ if (isAdvanced && savedOwnerAddress) {
157
+ setPhase({ kind: 'advanced-transfer-check' })
158
+ return
159
+ }
160
+ runDiscovery()
161
+ return
162
+ }
163
+ }}
164
+ onCancel={onBack}
165
+ />
166
+ </Box>
167
+ </Surface>
168
+ )
169
+ }
170
+
171
+ if (phase.kind === 'unlink-loading') {
172
+ return (
173
+ <Surface
174
+ title="Prepare ENS Unlink"
175
+ subtitle={`Reading ethagent records from ${phase.fullName}`}
176
+ footer={footerHint('esc back')}
177
+ >
178
+ <Box marginTop={1}>
179
+ <Spinner label="reading current ENS record values..." />
180
+ </Box>
181
+ <EscCancel onCancel={() => setPhase({ kind: 'mode-select' })} />
182
+ </Surface>
183
+ )
184
+ }
185
+
186
+ if (phase.kind === 'unlink-review') {
187
+ const options = unlinkEnsLinkOptions(savedCustodyMode, savedOwnerAddress)
188
+ return (
189
+ <UnlinkEnsReviewScreen
190
+ fullName={phase.fullName}
191
+ currentMode={savedCustodyMode}
192
+ registryNetworkLabel={registryNetworkLabel}
193
+ recordsDiff={phase.recordsDiff}
194
+ onUnlink={() => {
195
+ if (recordsHaveCurrentValues(phase.recordsDiff)) {
196
+ onEnsRecordsUpdate(phase.fullName, emptyAgentEnsRecords(), options, true, phase.currentRecords)
197
+ return
198
+ }
199
+ onEnsUnlink()
200
+ }}
201
+ onBack={() => setPhase({ kind: 'mode-select' })}
202
+ />
203
+ )
204
+ }
205
+
206
+ if (phase.kind === 'delete-subdomain-preflight') {
207
+ return (
208
+ <Surface
209
+ title="Prepare Subdomain Deletion"
210
+ subtitle={`Verifying the parent of ${phase.fullName} on Ethereum mainnet.`}
211
+ footer={footerHint('esc back')}
212
+ >
213
+ <Box marginTop={1}>
214
+ <Spinner label="reading parent owner from ENS..." />
215
+ </Box>
216
+ <EscCancel onCancel={() => setPhase({ kind: 'mode-select' })} />
217
+ </Surface>
218
+ )
219
+ }
220
+
221
+ if (phase.kind === 'delete-subdomain-blocked') {
222
+ return (
223
+ <Surface
224
+ title="Cannot Delete Subdomain"
225
+ subtitle={`Onchain check for ${phase.fullName} did not pass.`}
226
+ footer={footerHint('enter select · esc back')}
227
+ >
228
+ <Box flexDirection="column" marginTop={1}>
229
+ <Text color={theme.accentError}>{phase.reason}</Text>
230
+ </Box>
231
+ <Box marginTop={1}>
232
+ <Select<'back'>
233
+ options={[
234
+ { value: 'back', role: 'section', label: 'Navigation' },
235
+ { value: 'back', label: 'Back to ENS', hint: 'Return to ENS menu', role: 'utility' },
236
+ ]}
237
+ hintLayout="inline"
238
+ onSubmit={() => setPhase({ kind: 'mode-select' })}
239
+ onCancel={() => setPhase({ kind: 'mode-select' })}
240
+ />
241
+ </Box>
242
+ </Surface>
243
+ )
244
+ }
245
+
246
+ if (phase.kind === 'delete-subdomain-confirm') {
247
+ const plan = phase.plan
248
+ return (
249
+ <Surface
250
+ title="Delete ENS Subdomain"
251
+ subtitle={`Clear the onchain entry for ${plan.fullName} at ${plan.parentName}.`}
252
+ footer={footerHint('enter select · esc back')}
253
+ >
254
+ <Box flexDirection="column" marginTop={1}>
255
+ <EnsSetupRow label="Subdomain" value={plan.fullName} />
256
+ <EnsSetupRow label="Parent" value={plan.parentName} />
257
+ <EnsSetupRow label="Owner wallet" value={shortAddress(plan.parentOwnerAddress)} />
258
+ <EnsSetupRow
259
+ label="Path"
260
+ value={plan.parentWrapped ? 'NameWrapper.setSubnodeRecord' : 'Registry.setSubnodeRecord'}
261
+ />
262
+ <EnsSetupRow
263
+ label="What changes"
264
+ value="Onchain: subdomain owner and resolver set to 0. Locally: this token unlinks from the name."
265
+ />
266
+ </Box>
267
+ <Box marginTop={1}>
268
+ <Select<'delete' | 'back'>
269
+ options={[
270
+ { value: 'delete', role: 'section', label: 'Action' },
271
+ { value: 'delete', label: 'Delete Subdomain', hint: 'Sign with the owner wallet to clear the onchain entry' },
272
+ { value: 'back', role: 'section', label: 'Navigation' },
273
+ { value: 'back', label: 'Back', hint: 'Return to ENS menu', role: 'utility' },
274
+ ]}
275
+ hintLayout="inline"
276
+ onSubmit={choice => {
277
+ if (choice === 'delete') {
278
+ setPhase({ kind: 'delete-subdomain-tx', plan })
279
+ return
280
+ }
281
+ setPhase({ kind: 'mode-select' })
282
+ }}
283
+ onCancel={() => setPhase({ kind: 'mode-select' })}
284
+ />
285
+ </Box>
286
+ </Surface>
287
+ )
288
+ }
289
+
290
+ if (phase.kind === 'delete-subdomain-tx') {
291
+ return (
292
+ <DeleteSubdomainTxRunner
293
+ plan={phase.plan}
294
+ ownerAddress={ownerAddress}
295
+ walletSession={operatorWalletSession}
296
+ onWalletReady={setOperatorWalletSession}
297
+ onDeleted={() => {
298
+ onEnsUnlink()
299
+ setPhase({ kind: 'delete-subdomain-done', fullName: phase.plan.fullName })
300
+ }}
301
+ onError={msg => setPhase({ kind: 'delete-subdomain-blocked', fullName: phase.plan.fullName, reason: msg })}
302
+ />
303
+ )
304
+ }
305
+
306
+ if (phase.kind === 'delete-subdomain-done') {
307
+ return (
308
+ <Surface
309
+ title="Subdomain Deleted"
310
+ subtitle={`${phase.fullName} is cleared onchain and unlinked from this token.`}
311
+ footer={footerHint('enter select · esc back')}
312
+ >
313
+ <Box flexDirection="column" marginTop={1}>
314
+ <Text color={theme.text}>The label is freed for reuse on the parent name.</Text>
315
+ </Box>
316
+ <Box marginTop={1}>
317
+ <Select<'back'>
318
+ options={[
319
+ { value: 'back', role: 'section', label: 'Navigation' },
320
+ { value: 'back', label: 'Back to ENS', hint: 'Return to ENS menu', role: 'utility' },
321
+ ]}
322
+ hintLayout="inline"
323
+ onSubmit={() => setPhase({ kind: 'mode-select' })}
324
+ onCancel={() => setPhase({ kind: 'mode-select' })}
325
+ />
326
+ </Box>
327
+ </Surface>
328
+ )
329
+ }
330
+
331
+ return null
332
+ }