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,45 @@
1
+ import type React from 'react'
2
+ import type { Address } from 'viem'
3
+ import type { EthagentConfig, EthagentIdentity } from '../../../../storage/config.js'
4
+ import type { Erc8004RegistryConfig } from '../../../registry/erc8004.js'
5
+ import type { EffectCallbacks } from '../../effects/types.js'
6
+ import type { ProfileUpdates, Step } from '../../identityHubReducer.js'
7
+ import type { WalletApprovalScreen } from '../../components/WalletApprovalScreen.js'
8
+
9
+ export type GuardOwnership = (
10
+ identity: EthagentIdentity,
11
+ registry: Erc8004RegistryConfig,
12
+ role: 'token-holder' | 'vault-level-owner',
13
+ fallback: Step,
14
+ ) => Promise<boolean>
15
+
16
+ export type TriggerRebackup = (
17
+ back: Step,
18
+ profileUpdates?: ProfileUpdates,
19
+ options?: { vaultAddress?: `0x${string}`; useVault?: boolean },
20
+ ) => void
21
+
22
+ export interface CustodyFlowDeps {
23
+ config: EthagentConfig | undefined
24
+ step: Step
25
+ setStep: (step: Step) => void
26
+ callbacks: EffectCallbacks
27
+ walletSession: React.ComponentProps<typeof WalletApprovalScreen>['walletSession']
28
+ handleStepError: (err: unknown, fallback: Step) => void
29
+ guardOwnership: GuardOwnership
30
+ triggerRebackup: TriggerRebackup
31
+ refreshReconciliation: () => void
32
+ onConfigChange?: (config: EthagentConfig) => void
33
+ }
34
+
35
+ export interface CustodyFlow {
36
+ beginVaultDeposit: (currentStep: Step, returnTo: Step, profileUpdates: ProfileUpdates) => void
37
+ beginVaultUnwrap: (currentStep: Step, returnTo: Step, profileUpdates: ProfileUpdates) => void
38
+ beginWithdrawToken: (currentStep: Step, returnTo: Step) => void
39
+ beginReturnToVault: (currentStep: Step, returnTo: Step, vaultAddress: Address) => void
40
+ renderCustodyStep: () => React.ReactElement | null
41
+ renderRebackupSubtitle: (
42
+ defaultSubtitle: React.ReactNode,
43
+ vaultRouted: boolean,
44
+ ) => React.ReactNode
45
+ }
@@ -0,0 +1,25 @@
1
+ import type { CustodyFlow, CustodyFlowDeps } from './custodyFlowTypes.js'
2
+ import { createCustodyFlowActions } from './custodyFlowActions.js'
3
+ import { useCustodyTransactionEffects } from './custodyFlowEffects.js'
4
+ import {
5
+ renderCustodyStep,
6
+ renderRebackupSubtitle,
7
+ } from './custodyFlowRoutes.js'
8
+
9
+ export function useCustodyFlow(deps: CustodyFlowDeps): CustodyFlow {
10
+ useCustodyTransactionEffects(deps)
11
+ const actions = createCustodyFlowActions(deps)
12
+
13
+ return {
14
+ ...actions,
15
+ renderCustodyStep: () => renderCustodyStep(deps),
16
+ renderRebackupSubtitle,
17
+ }
18
+ }
19
+
20
+ export type {
21
+ CustodyFlow,
22
+ CustodyFlowDeps,
23
+ GuardOwnership,
24
+ TriggerRebackup,
25
+ } from './custodyFlowTypes.js'
@@ -0,0 +1,336 @@
1
+ import React from 'react'
2
+ import { Box, Text } from 'ink'
3
+ import { getAddress, type Address } from 'viem'
4
+ import { Surface } from '../../../../ui/Surface.js'
5
+ import { Select } from '../../../../ui/Select.js'
6
+ import { TextInput } from '../../../../ui/TextInput.js'
7
+ import { Spinner } from '../../../../ui/Spinner.js'
8
+ import { theme } from '../../../../ui/theme.js'
9
+ import {
10
+ normalizeEthDomain,
11
+ sanitizeSubdomainPrefix,
12
+ } from '../../../ens/ensLookup.js'
13
+ import { isRootEthName } from '../../../ens/ensAutomation.js'
14
+ import type { Erc8004RegistryConfig } from '../../../registry/erc8004.js'
15
+ import type { BrowserWalletReady } from '../../../wallet/browserWallet.js'
16
+ import {
17
+ type CustodyMode,
18
+ } from '../../model/custody.js'
19
+ import { shortAddress } from '../../model/format.js'
20
+ import { WalletApprovalScreen } from '../../components/WalletApprovalScreen.js'
21
+ import { advancedSubdomainStatusText } from './ensEditCopy.js'
22
+ import {
23
+ EnsSetupRow,
24
+ footerHint,
25
+ } from './EnsEditShared.js'
26
+ import {
27
+ EnsSetupBlockedScreen,
28
+ EnsSetupReviewScreen,
29
+ } from './EnsEditReviewScreens.js'
30
+ import { EscCancel } from './EnsEditRunners.js'
31
+ import type {
32
+ EnsEditProps,
33
+ EnsPhase,
34
+ } from './ensEditTypes.js'
35
+
36
+ type AdvancedScreenProps = {
37
+ phase: EnsPhase
38
+ ownerAddress: Address
39
+ agentId: EnsEditProps['identity']['agentId']
40
+ savedOwnerAddress: string
41
+ savedOperator: string
42
+ savedRootName: string
43
+ savedSubdomainLabel: string
44
+ agentNameSuggestion: string
45
+ currentEnsName: string
46
+ savedCustodyMode: CustodyMode | undefined
47
+ registry: Erc8004RegistryConfig
48
+ operatorWalletSession: BrowserWalletReady | null
49
+ setPhase: (phase: EnsPhase) => void
50
+ connectOperatorWallet: (rootName: string, label: string) => void
51
+ runAdvancedRootCheck: (rootName: string) => void
52
+ runAdvancedSubdomainCheck: (rootName: string, label: string) => void
53
+ runAdvancedPreflight: (rootName: string, label: string, operatorWallet: Address) => void
54
+ onEnsSetup: EnsEditProps['onEnsSetup']
55
+ onEnsLink: EnsEditProps['onEnsLink']
56
+ }
57
+
58
+ export function renderAdvancedEnsPhase({
59
+ phase,
60
+ ownerAddress,
61
+ agentId,
62
+ savedOwnerAddress,
63
+ savedOperator,
64
+ savedRootName,
65
+ savedSubdomainLabel,
66
+ agentNameSuggestion,
67
+ currentEnsName,
68
+ savedCustodyMode,
69
+ registry,
70
+ operatorWalletSession,
71
+ setPhase,
72
+ connectOperatorWallet,
73
+ runAdvancedRootCheck,
74
+ runAdvancedSubdomainCheck,
75
+ runAdvancedPreflight,
76
+ onEnsSetup,
77
+ onEnsLink,
78
+ }: AdvancedScreenProps): React.ReactNode | null {
79
+ if (phase.kind === 'advanced-transfer-check') {
80
+ type TransferCheckAction = 'skip' | 'back'
81
+ return (
82
+ <Surface
83
+ title="Token Custody Check"
84
+ subtitle="ENS setup continues only after the owner wallet holds this token."
85
+ footer={footerHint('enter select · esc back')}
86
+ >
87
+ <Box flexDirection="column">
88
+ <Text color={theme.dim}>Current token owner: <Text color={theme.text}>{shortAddress(ownerAddress)}</Text></Text>
89
+ <Box marginTop={1} flexDirection="column">
90
+ <EnsSetupRow label="Owner wallet" value={`Holds ERC-8004 token #${agentId ?? 'unknown'} and signs ENS records.`} />
91
+ <EnsSetupRow label="Operator wallet" value="Restores snapshots; never controls the token." />
92
+ <EnsSetupRow label="Token moves" value="If the token is in the operator delegation vault, withdraw it first from Custody Mode." />
93
+ </Box>
94
+ </Box>
95
+ <Box marginTop={1}>
96
+ <Select<TransferCheckAction>
97
+ options={[
98
+ { value: 'skip', role: 'section', label: 'Setup' },
99
+ { value: 'skip', label: 'Continue ENS Setup', hint: 'The connected wallet is already the owner wallet' },
100
+ { value: 'back', role: 'section', label: 'Navigation' },
101
+ { value: 'back', label: 'Back', hint: 'Return to setup type', role: 'utility' },
102
+ ]}
103
+ hintLayout="inline"
104
+ onSubmit={choice => {
105
+ if (choice === 'skip') return setPhase({ kind: 'advanced-root', rootName: savedRootName })
106
+ return setPhase({ kind: 'mode-select' })
107
+ }}
108
+ onCancel={() => setPhase({ kind: 'mode-select' })}
109
+ />
110
+ </Box>
111
+ </Surface>
112
+ )
113
+ }
114
+
115
+ if (phase.kind === 'advanced-root') {
116
+ return (
117
+ <Surface
118
+ title="Root ENS"
119
+ footer={footerHint('enter next · esc back')}
120
+ >
121
+ <Box flexDirection="column">
122
+ <Text color={theme.dim}>Enter the parent .eth name. The owner wallet must manage it and own this ERC-8004 token.</Text>
123
+ {savedOwnerAddress ? <Text color={theme.dim}>Saved owner wallet: <Text color={theme.text}>{shortAddress(savedOwnerAddress)}</Text></Text> : null}
124
+ {phase.error ? <Text color={theme.accentError}>{phase.error}</Text> : null}
125
+ </Box>
126
+ <Box marginTop={1}>
127
+ <TextInput
128
+ key="advanced-root"
129
+ initialValue={phase.rootName || savedRootName}
130
+ placeholder="name.eth"
131
+ validate={value => {
132
+ const root = normalizeEthDomain(value)
133
+ if (!root) return 'Enter a parent .eth name'
134
+ if (!isRootEthName(root)) return 'Enter the parent .eth name, e.g. name.eth'
135
+ return null
136
+ }}
137
+ onSubmit={value => runAdvancedRootCheck(normalizeEthDomain(value))}
138
+ onCancel={() => setPhase({ kind: 'mode-select' })}
139
+ />
140
+ </Box>
141
+ </Surface>
142
+ )
143
+ }
144
+
145
+ if (phase.kind === 'advanced-root-check') {
146
+ return (
147
+ <Surface
148
+ title="Checking ENS and Token Ownership"
149
+ subtitle={`Verifying the connected wallet manages ${phase.rootName} and owns the ERC-8004 token.`}
150
+ footer={footerHint('esc back')}
151
+ >
152
+ <Box marginTop={1}>
153
+ <Text color={theme.textSubtle}>Reading from Ethereum mainnet...</Text>
154
+ </Box>
155
+ </Surface>
156
+ )
157
+ }
158
+
159
+ if (phase.kind === 'advanced-subdomain') {
160
+ const rootName = phase.rootName
161
+ return (
162
+ <Surface
163
+ title="Agent Subdomain"
164
+ footer={footerHint('enter next · esc back')}
165
+ >
166
+ <Box flexDirection="column">
167
+ <Text color={theme.dim}>Create one subdomain for this agent only. Root .eth names stay parent names.</Text>
168
+ <Text color={theme.dim}>Parent: <Text color={theme.text}>{rootName}</Text></Text>
169
+ {phase.error ? <Text color={theme.accentError}>{phase.error}</Text> : null}
170
+ </Box>
171
+ <Box marginTop={1}>
172
+ <TextInput
173
+ key={`advanced-subdomain-${rootName}`}
174
+ initialValue={phase.label || savedSubdomainLabel || agentNameSuggestion}
175
+ placeholder="agent-name"
176
+ validate={value => {
177
+ const trimmed = value.trim()
178
+ const label = sanitizeSubdomainPrefix(trimmed)
179
+ if (!label) return 'Enter a subdomain label'
180
+ if (trimmed.includes('.')) return 'Enter only the subdomain label'
181
+ if (label !== trimmed.toLowerCase()) return 'Use lowercase letters, numbers, and hyphens only'
182
+ return null
183
+ }}
184
+ onSubmit={value => runAdvancedSubdomainCheck(rootName, sanitizeSubdomainPrefix(value))}
185
+ onCancel={() => setPhase({ kind: 'advanced-root', rootName })}
186
+ />
187
+ </Box>
188
+ </Surface>
189
+ )
190
+ }
191
+
192
+ if (phase.kind === 'advanced-subdomain-check') {
193
+ return (
194
+ <Surface
195
+ title="Check Agent Subdomain"
196
+ footer={footerHint('esc back')}
197
+ >
198
+ <Box flexDirection="column">
199
+ <Text color={theme.dim}>Agent ENS: <Text color={theme.text}>{phase.label}.{phase.rootName}</Text></Text>
200
+ <Text color={theme.dim}>Checking whether the subdomain is ready or needs the owner wallet to create it.</Text>
201
+ </Box>
202
+ <Box marginTop={1}>
203
+ <Spinner label="checking agent subdomain..." />
204
+ </Box>
205
+ <EscCancel onCancel={() => setPhase({ kind: 'advanced-subdomain', rootName: phase.rootName, label: phase.label })} />
206
+ </Surface>
207
+ )
208
+ }
209
+
210
+ if (phase.kind === 'advanced-operator-wallet') {
211
+ const { rootName, label } = phase
212
+ return (
213
+ <Surface
214
+ title="Operator Wallet"
215
+ footer={footerHint('enter select · esc back')}
216
+ >
217
+ <Box flexDirection="column">
218
+ <Text color={theme.dim}>Agent ENS: <Text color={theme.text}>{label}.{rootName}</Text></Text>
219
+ {phase.registryAction ? <Text color={theme.dim}>{advancedSubdomainStatusText(phase.registryAction)}</Text> : null}
220
+ <Text color={theme.dim}>Choose the operator wallet for snapshot restore access and onchain ERC-8004 URI rotation via the operator delegation vault.</Text>
221
+ <Text color={theme.dim}>The operator wallet has no authority over this ENS subdomain or any token transfer; the owner wallet is the sole signer for both.</Text>
222
+ <Text color={theme.dim}>We only read the operator's address here so it can be added to the snapshot envelope and vault operator list later.</Text>
223
+ {savedOperator ? <Text color={theme.dim}>Saved operator wallet: <Text color={theme.text}>{shortAddress(savedOperator)}</Text></Text> : null}
224
+ {phase.error ? <Text color={theme.accentError}>{phase.error}</Text> : null}
225
+ </Box>
226
+ <Box marginTop={1}>
227
+ <Select<'connect' | 'enter' | 'back'>
228
+ options={[
229
+ { value: 'connect', role: 'section', label: 'Operator Wallet' },
230
+ { value: 'connect', label: 'Connect Wallet', hint: 'Connect the wallet that will be the operator' },
231
+ { value: 'enter', label: 'Enter Wallet Address', hint: 'Paste the operator wallet address' },
232
+ { value: 'back', role: 'section', label: 'Navigation' },
233
+ { value: 'back', label: 'Back', hint: 'Return to subdomain', role: 'utility' },
234
+ ]}
235
+ hintLayout="inline"
236
+ onSubmit={choice => {
237
+ if (choice === 'connect') return connectOperatorWallet(rootName, label)
238
+ if (choice === 'enter') return setPhase({ kind: 'advanced-operator-wallet-manual', rootName, label })
239
+ return setPhase({ kind: 'advanced-subdomain', rootName, label })
240
+ }}
241
+ onCancel={() => setPhase({ kind: 'advanced-subdomain', rootName, label })}
242
+ />
243
+ </Box>
244
+ </Surface>
245
+ )
246
+ }
247
+
248
+ if (phase.kind === 'advanced-operator-wallet-manual') {
249
+ const { rootName, label } = phase
250
+ return (
251
+ <Surface
252
+ title="Operator Wallet"
253
+ footer={footerHint('enter next · esc back')}
254
+ >
255
+ <Box flexDirection="column">
256
+ <Text color={theme.dim}>The operator wallet is saved in ERC-8004 metadata for lookup and restore access.</Text>
257
+ <Text color={theme.dim}>It gets no token approval or transfer right.</Text>
258
+ <Text color={theme.dim}>Owner wallet signs the ENS and ERC-8004 transactions after this address is checked.</Text>
259
+ <Text color={theme.dim}>Any future token move still starts with Prepare Token Transfer.</Text>
260
+ {phase.error ? <Text color={theme.accentError}>{phase.error}</Text> : null}
261
+ </Box>
262
+ <Box marginTop={1}>
263
+ <TextInput
264
+ key="advanced-operator-wallet-manual"
265
+ initialValue={savedOperator}
266
+ placeholder="0x..."
267
+ validate={value => /^0x[0-9a-fA-F]{40}$/.test(value.trim()) ? null : 'enter a valid 0x address'}
268
+ onSubmit={value => runAdvancedPreflight(rootName, label, getAddress(value.trim()))}
269
+ onCancel={() => setPhase({ kind: 'advanced-operator-wallet', rootName, label })}
270
+ />
271
+ </Box>
272
+ </Surface>
273
+ )
274
+ }
275
+
276
+ if (phase.kind === 'advanced-operator-wallet-connecting') {
277
+ return (
278
+ <WalletApprovalScreen
279
+ title="Connect Wallet"
280
+ subtitle="Connect the operator wallet only to read its address for ERC-8004 metadata. It does not sign or submit a transaction."
281
+ walletSession={operatorWalletSession}
282
+ label="waiting for wallet connection..."
283
+ onCancel={() => setPhase({ kind: 'advanced-operator-wallet', rootName: phase.rootName, label: phase.label })}
284
+ />
285
+ )
286
+ }
287
+
288
+ if (phase.kind === 'advanced-preflight') {
289
+ return (
290
+ <Surface
291
+ title="Check ENS Setup"
292
+ footer={footerHint('esc back')}
293
+ >
294
+ <Box marginTop={1}>
295
+ <Spinner label="checking ens setup..." />
296
+ </Box>
297
+ <EscCancel onCancel={() => setPhase({ kind: 'advanced-operator-wallet', rootName: phase.rootName, label: phase.label })} />
298
+ </Surface>
299
+ )
300
+ }
301
+
302
+ if (phase.kind === 'advanced-review') {
303
+ return (
304
+ <EnsSetupReviewScreen
305
+ setup={phase.setup}
306
+ currentEnsName={currentEnsName}
307
+ currentMode={savedCustodyMode}
308
+ registry={registry}
309
+ onBegin={() => {
310
+ if (phase.setup.txCount > 0) {
311
+ onEnsSetup(phase.setup)
312
+ return
313
+ }
314
+ onEnsLink(phase.setup.fullName, {
315
+ mode: 'advanced',
316
+ ownerAddress: phase.setup.ownerAddress,
317
+ operatorWallet: phase.setup.operatorAddress,
318
+ })
319
+ }}
320
+ onBack={() => setPhase({ kind: 'advanced-operator-wallet', rootName: phase.setup.rootName, label: phase.setup.label })}
321
+ />
322
+ )
323
+ }
324
+
325
+ if (phase.kind === 'advanced-manual') {
326
+ return (
327
+ <EnsSetupBlockedScreen
328
+ fallback={phase.fallback}
329
+ onCheckAgain={() => runAdvancedPreflight(phase.fallback.rootName, phase.fallback.label, phase.fallback.operatorAddress)}
330
+ onBack={() => setPhase({ kind: 'advanced-operator-wallet', rootName: phase.fallback.rootName, label: phase.fallback.label })}
331
+ />
332
+ )
333
+ }
334
+
335
+ return null
336
+ }