ethagent 3.3.3 → 4.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 (322) hide show
  1. package/.claude-plugin/marketplace.json +11 -0
  2. package/.claude-plugin/plugin.json +35 -0
  3. package/LICENSE +1 -1
  4. package/README.md +64 -104
  5. package/commands/ethagent.md +40 -0
  6. package/package.json +16 -16
  7. package/src/app/keybindings/KeybindingProvider.tsx +1 -6
  8. package/src/app/keybindings/types.ts +1 -6
  9. package/src/cli/ResetConfirmView.tsx +54 -53
  10. package/src/cli/demo.ts +86 -0
  11. package/src/cli/hookIo.ts +45 -0
  12. package/src/cli/main.tsx +94 -123
  13. package/src/cli/memoryGuard.ts +49 -0
  14. package/src/cli/reset.ts +28 -70
  15. package/src/cli/sessionStart.ts +33 -0
  16. package/src/cli/status.ts +46 -0
  17. package/src/cli/sync.ts +167 -0
  18. package/src/cli/syncAdapters/claude-code.ts +86 -0
  19. package/src/cli/syncAdapters/codex.ts +66 -0
  20. package/src/cli/syncAdapters/index.ts +45 -0
  21. package/src/cli/syncAdapters/managedBlock.ts +175 -0
  22. package/src/cli/syncAdapters/shared.ts +63 -0
  23. package/src/identity/continuity/envelopeParse.ts +20 -1
  24. package/src/identity/continuity/publicSkills.ts +3 -1
  25. package/src/identity/continuity/skills/publicSkillsSync.ts +2 -1
  26. package/src/identity/continuity/skills/scaffold.ts +5 -2
  27. package/src/identity/continuity/snapshots.ts +12 -5
  28. package/src/identity/continuity/storage/defaults.ts +20 -19
  29. package/src/identity/continuity/storage/status.ts +1 -1
  30. package/src/identity/ens/ensLookup/constants.ts +1 -1
  31. package/src/identity/manager/IdentityManager.tsx +33 -0
  32. package/src/identity/{hub → manager}/OperationalRoutes.tsx +37 -18
  33. package/src/identity/{hub → manager}/Routes.tsx +48 -34
  34. package/src/identity/{hub → manager}/continuity/ContinuityDashboardScreen.tsx +9 -19
  35. package/src/identity/{hub → manager}/continuity/RebackupStorageScreen.tsx +3 -3
  36. package/src/identity/manager/continuity/RecoveryConfirmScreen.tsx +102 -0
  37. package/src/identity/{hub → manager}/continuity/SavePromptScreen.tsx +2 -3
  38. package/src/identity/{hub → manager}/continuity/completion.ts +1 -1
  39. package/src/identity/{hub → manager}/continuity/effects.ts +1 -1
  40. package/src/identity/{hub → manager}/continuity/skills/DeleteSkillConfirmScreen.tsx +2 -2
  41. package/src/identity/{hub → manager}/continuity/skills/NewSkillScreen.tsx +0 -5
  42. package/src/identity/{hub → manager}/continuity/skills/NewSkillVisibilityScreen.tsx +4 -4
  43. package/src/identity/{hub → manager}/continuity/skills/SkillActionsScreen.tsx +6 -22
  44. package/src/identity/{hub → manager}/continuity/skills/SkillsTreeScreen.tsx +5 -17
  45. package/src/identity/{hub → manager}/continuity/snapshot.ts +1 -1
  46. package/src/identity/{hub → manager}/continuity/vault.ts +1 -1
  47. package/src/identity/{hub → manager}/create/CreateFlow.tsx +59 -32
  48. package/src/identity/{hub → manager}/create/effects.ts +19 -10
  49. package/src/identity/manager/create/importScan.ts +122 -0
  50. package/src/identity/{hub → manager}/custody/CustodyEditFlow.tsx +17 -61
  51. package/src/identity/{hub → manager}/custody/actions.ts +1 -15
  52. package/src/identity/{hub → manager}/custody/routes.tsx +20 -40
  53. package/src/identity/{hub → manager}/custody/transactions.ts +1 -0
  54. package/src/identity/{hub → manager}/custody/types.ts +1 -2
  55. package/src/identity/{hub → manager}/custody/useCustodyEffects.ts +1 -1
  56. package/src/identity/{hub → manager}/ens/EnsEditAdvancedScreens.tsx +2 -2
  57. package/src/identity/{hub → manager}/ens/EnsEditMaintenanceScreens.tsx +12 -23
  58. package/src/identity/{hub → manager}/ens/EnsEditReviewScreens.tsx +18 -42
  59. package/src/identity/{hub → manager}/ens/EnsEditRunners.tsx +1 -1
  60. package/src/identity/{hub → manager}/ens/EnsEditShared.tsx +0 -2
  61. package/src/identity/{hub → manager}/ens/EnsEditSimpleScreens.tsx +10 -19
  62. package/src/identity/{hub → manager}/ens/EnsFlow.tsx +133 -41
  63. package/src/identity/{hub → manager}/ens/EnsOperatorWalletsScreen.tsx +14 -19
  64. package/src/identity/{hub → manager}/ens/editCopy.ts +1 -14
  65. package/src/identity/{hub → manager}/profile/EditProfileFlow.tsx +99 -66
  66. package/src/identity/{hub → manager}/profile/effects.ts +1 -3
  67. package/src/identity/{hub → manager}/profile/operatorSave.ts +1 -1
  68. package/src/identity/{hub → manager}/profile/state.ts +1 -1
  69. package/src/identity/{hub/identityHubReducer.ts → manager/reducer.ts} +25 -26
  70. package/src/identity/{hub → manager}/restore/RestoreFlow.tsx +16 -24
  71. package/src/identity/{hub → manager}/restore/apply.ts +1 -1
  72. package/src/identity/{hub → manager}/restore/auth.ts +1 -1
  73. package/src/identity/{hub → manager}/restore/discover.ts +1 -1
  74. package/src/identity/{hub → manager}/restore/fetch.ts +1 -1
  75. package/src/identity/{hub → manager}/restore/restoreAdmin.ts +1 -1
  76. package/src/identity/{hub → manager}/restore/useRestoreEffects.ts +2 -9
  77. package/src/identity/{hub → manager}/settings/StorageCredentialScreen.tsx +10 -25
  78. package/src/identity/{hub → manager}/shared/components/DetailsScreen.tsx +5 -7
  79. package/src/identity/{hub → manager}/shared/components/ErrorScreen.tsx +6 -10
  80. package/src/identity/{hub → manager}/shared/components/FlowTimeline.tsx +4 -3
  81. package/src/identity/{hub → manager}/shared/components/IdentitySummary.tsx +19 -59
  82. package/src/identity/manager/shared/components/LazyMenu.tsx +147 -0
  83. package/src/identity/manager/shared/components/MenuScreen.tsx +220 -0
  84. package/src/identity/manager/shared/components/OperationCompleteScreen.tsx +28 -0
  85. package/src/identity/{hub → manager}/shared/components/UnlinkedIdentityScreen.tsx +9 -10
  86. package/src/identity/{hub → manager}/shared/components/WalletApprovalScreen.tsx +1 -2
  87. package/src/identity/manager/shared/components/Wordmark.tsx +54 -0
  88. package/src/identity/{hub → manager}/shared/components/menuFlagsFromReconciliation.ts +39 -15
  89. package/src/identity/{hub → manager}/shared/effects/profilePrep.ts +1 -1
  90. package/src/identity/manager/shared/effects/types.ts +30 -0
  91. package/src/identity/{hub → manager}/shared/model/copy.ts +0 -4
  92. package/src/identity/{hub → manager}/shared/model/errors.ts +32 -3
  93. package/src/identity/{hub → manager}/shared/model/network.ts +2 -2
  94. package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/hook.ts +5 -0
  95. package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/run.ts +1 -1
  96. package/src/identity/{hub/shared/reconciliation/useAgentReconciliation.ts → manager/shared/reconciliation/index.ts} +6 -0
  97. package/src/identity/{hub → manager}/shared/utils.ts +6 -10
  98. package/src/identity/{hub → manager}/transfer/TokenTransferFlow.tsx +3 -3
  99. package/src/identity/{hub → manager}/transfer/TokenTransferScreens.tsx +4 -10
  100. package/src/identity/{hub → manager}/transfer/effects.ts +1 -1
  101. package/src/identity/{hub → manager}/types.ts +5 -6
  102. package/src/identity/{hub/useIdentityHubContinuity.ts → manager/useContinuity.ts} +59 -27
  103. package/src/identity/{hub/useIdentityHubController.ts → manager/useController.ts} +38 -35
  104. package/src/identity/{hub/useIdentityHubSideEffects.ts → manager/useSideEffects.ts} +40 -4
  105. package/src/identity/registry/erc8004/discovery.ts +3 -17
  106. package/src/identity/registry/erc8004/utils.ts +1 -1
  107. package/src/identity/storage/ipfs.ts +21 -1
  108. package/src/identity/wallet/browserWallet/html.ts +10 -2
  109. package/src/identity/wallet/browserWallet/http.ts +18 -0
  110. package/src/identity/wallet/browserWallet/requestServer.ts +5 -1
  111. package/src/identity/wallet/browserWallet/requests.ts +10 -28
  112. package/src/identity/wallet/browserWallet/session.ts +26 -33
  113. package/src/identity/wallet/browserWallet/validation.ts +14 -0
  114. package/src/identity/wallet/browserWallet/walletPageSource.ts +22 -40
  115. package/src/identity/wallet/page/boot.ts +43 -0
  116. package/src/identity/wallet/page/config.ts +59 -0
  117. package/src/identity/wallet/page/constants.ts +12 -0
  118. package/src/identity/wallet/page/copy.ts +47 -68
  119. package/src/identity/wallet/page/css.ts +638 -0
  120. package/src/identity/wallet/page/{errorView.ts → errors.ts} +5 -14
  121. package/src/identity/wallet/page/{controller.ts → flow.ts} +4 -71
  122. package/src/identity/wallet/page/markup.ts +44 -34
  123. package/src/identity/wallet/page/{walletProvider.ts → provider.ts} +0 -3
  124. package/src/identity/wallet/page/resize.ts +95 -0
  125. package/src/identity/wallet/page/state.ts +135 -8
  126. package/src/identity/wallet/page/timeline.ts +161 -0
  127. package/src/identity/wallet/page/view.ts +22 -302
  128. package/src/storage/config.ts +30 -80
  129. package/src/storage/reset.ts +31 -0
  130. package/src/storage/secrets.ts +1 -16
  131. package/src/ui/Select.tsx +27 -5
  132. package/src/ui/Spinner.tsx +16 -15
  133. package/src/ui/Surface.tsx +21 -17
  134. package/src/ui/TextArea.tsx +173 -0
  135. package/src/ui/TextInput.tsx +31 -133
  136. package/src/ui/theme.ts +22 -13
  137. package/src/utils/clipboard.ts +0 -140
  138. package/src/app/FirstRun.tsx +0 -577
  139. package/src/app/FirstRunTimeline.tsx +0 -51
  140. package/src/app/firstRunConfig.ts +0 -26
  141. package/src/app/hooks/useCancelRequest.ts +0 -22
  142. package/src/app/hooks/useDoublePress.ts +0 -46
  143. package/src/app/hooks/useExitOnCtrlC.ts +0 -36
  144. package/src/auth/openaiOAuth/credentials.ts +0 -47
  145. package/src/auth/openaiOAuth/crypto.ts +0 -23
  146. package/src/auth/openaiOAuth/index.ts +0 -238
  147. package/src/auth/openaiOAuth/landingPage.ts +0 -116
  148. package/src/auth/openaiOAuth/listener.ts +0 -151
  149. package/src/auth/openaiOAuth/refresh.ts +0 -70
  150. package/src/auth/openaiOAuth/shared.ts +0 -115
  151. package/src/chat/ChatBottomPane.tsx +0 -296
  152. package/src/chat/ChatScreen.tsx +0 -1685
  153. package/src/chat/ConversationStack.tsx +0 -56
  154. package/src/chat/MessageList.tsx +0 -638
  155. package/src/chat/SessionStatus.tsx +0 -53
  156. package/src/chat/chatEnvironment.ts +0 -16
  157. package/src/chat/chatScreenUtils.ts +0 -194
  158. package/src/chat/chatSessionState.ts +0 -146
  159. package/src/chat/chatTurnContext.ts +0 -50
  160. package/src/chat/chatTurnOrchestrator.ts +0 -603
  161. package/src/chat/chatTurnRows.ts +0 -64
  162. package/src/chat/commands.ts +0 -494
  163. package/src/chat/continuityEditReview.ts +0 -42
  164. package/src/chat/display/DiffView.tsx +0 -193
  165. package/src/chat/display/SyntaxText.tsx +0 -192
  166. package/src/chat/display/toolCallDisplay.ts +0 -103
  167. package/src/chat/display/toolResultDisplay.ts +0 -19
  168. package/src/chat/input/ChatInput.tsx +0 -625
  169. package/src/chat/input/chatInputHelpers.ts +0 -62
  170. package/src/chat/input/chatInputState.ts +0 -247
  171. package/src/chat/input/chatPaste.ts +0 -49
  172. package/src/chat/input/imageRefs.ts +0 -30
  173. package/src/chat/input/inputRendering.tsx +0 -93
  174. package/src/chat/input/textCursor.ts +0 -212
  175. package/src/chat/messageMarkdown.ts +0 -220
  176. package/src/chat/messageRows.ts +0 -43
  177. package/src/chat/planImplementation.ts +0 -62
  178. package/src/chat/slashCommandHandlers.ts +0 -122
  179. package/src/chat/slashCommandViews.ts +0 -120
  180. package/src/chat/transcript/TranscriptView.tsx +0 -184
  181. package/src/chat/transcript/transcriptViewport.ts +0 -295
  182. package/src/chat/views/ContextLimitView.tsx +0 -95
  183. package/src/chat/views/ContinuityEditReviewView.tsx +0 -50
  184. package/src/chat/views/CopyPicker.tsx +0 -50
  185. package/src/chat/views/PermissionPrompt.tsx +0 -156
  186. package/src/chat/views/PermissionsView.tsx +0 -165
  187. package/src/chat/views/PlanApprovalView.tsx +0 -91
  188. package/src/chat/views/ResumeView.tsx +0 -273
  189. package/src/chat/views/RewindView.tsx +0 -412
  190. package/src/cli/preview.tsx +0 -14
  191. package/src/cli/updateNotice.ts +0 -54
  192. package/src/identity/continuity/privateEdit/apply.ts +0 -170
  193. package/src/identity/continuity/privateEdit/diff.ts +0 -6
  194. package/src/identity/continuity/privateEdit/files.ts +0 -23
  195. package/src/identity/continuity/privateEdit/types.ts +0 -28
  196. package/src/identity/continuity/privateEdit.ts +0 -46
  197. package/src/identity/hub/IdentityHub.tsx +0 -14
  198. package/src/identity/hub/continuity/RecoveryConfirmScreen.tsx +0 -104
  199. package/src/identity/hub/ens/effects.ts +0 -218
  200. package/src/identity/hub/shared/components/MenuScreen.tsx +0 -241
  201. package/src/identity/hub/shared/effects/types.ts +0 -53
  202. package/src/identity/hub/shared/reconciliation/index.ts +0 -14
  203. package/src/identity/wallet/page/grainient.ts +0 -278
  204. package/src/identity/wallet/page/html.ts +0 -28
  205. package/src/identity/wallet/page/styles/base.ts +0 -259
  206. package/src/identity/wallet/page/styles/components.ts +0 -262
  207. package/src/identity/wallet/page/styles/index.ts +0 -5
  208. package/src/identity/wallet/page/styles/responsive.ts +0 -247
  209. package/src/identity/wallet/page.tsx +0 -38
  210. package/src/mcp/approvals.ts +0 -113
  211. package/src/mcp/config.ts +0 -235
  212. package/src/mcp/manager.ts +0 -482
  213. package/src/mcp/managerHelpers.ts +0 -70
  214. package/src/mcp/names.ts +0 -19
  215. package/src/mcp/output.ts +0 -96
  216. package/src/models/ModelPicker.tsx +0 -1009
  217. package/src/models/catalog.ts +0 -327
  218. package/src/models/huggingface.ts +0 -712
  219. package/src/models/huggingfaceStorage.ts +0 -136
  220. package/src/models/llamacpp.ts +0 -848
  221. package/src/models/llamacppCommands.ts +0 -44
  222. package/src/models/llamacppConfig.ts +0 -34
  223. package/src/models/llamacppDiscovery.ts +0 -176
  224. package/src/models/llamacppOutput.ts +0 -65
  225. package/src/models/llamacppPreflight.ts +0 -158
  226. package/src/models/modelDisplay.ts +0 -180
  227. package/src/models/modelPickerCatalogFlow.ts +0 -56
  228. package/src/models/modelPickerCredentials.ts +0 -166
  229. package/src/models/modelPickerData.ts +0 -41
  230. package/src/models/modelPickerDisplay.tsx +0 -132
  231. package/src/models/modelPickerHfFlow.ts +0 -192
  232. package/src/models/modelPickerLocalRunnerFlow.ts +0 -115
  233. package/src/models/modelPickerOptions.ts +0 -457
  234. package/src/models/modelPickerTypes.ts +0 -69
  235. package/src/models/modelPickerUninstallFlow.ts +0 -48
  236. package/src/models/modelPickerViewHelpers.ts +0 -174
  237. package/src/models/modelRecommendation.ts +0 -139
  238. package/src/models/providerDisplay.ts +0 -16
  239. package/src/models/runtimeDetection.ts +0 -81
  240. package/src/models/uncensoredCatalog.ts +0 -86
  241. package/src/providers/anthropic.ts +0 -290
  242. package/src/providers/contracts.ts +0 -71
  243. package/src/providers/errors.ts +0 -80
  244. package/src/providers/gemini.ts +0 -391
  245. package/src/providers/openai-chat.ts +0 -474
  246. package/src/providers/openai-responses-format.ts +0 -177
  247. package/src/providers/openai-responses.ts +0 -306
  248. package/src/providers/openaiChatWire.ts +0 -124
  249. package/src/providers/registry.ts +0 -120
  250. package/src/providers/retry.ts +0 -58
  251. package/src/providers/sse.ts +0 -93
  252. package/src/runtime/compaction.ts +0 -395
  253. package/src/runtime/cwd.ts +0 -43
  254. package/src/runtime/providerTurn.ts +0 -38
  255. package/src/runtime/sessionMode.ts +0 -55
  256. package/src/runtime/systemPrompt.ts +0 -213
  257. package/src/runtime/textToolParser.ts +0 -161
  258. package/src/runtime/toolClaimGuards.ts +0 -143
  259. package/src/runtime/toolExecution.ts +0 -304
  260. package/src/runtime/toolIntent.ts +0 -143
  261. package/src/runtime/turn.ts +0 -369
  262. package/src/runtime/turnNudges.ts +0 -223
  263. package/src/runtime/turnTypes.ts +0 -86
  264. package/src/storage/factoryReset.ts +0 -127
  265. package/src/storage/history.ts +0 -58
  266. package/src/storage/permissions.ts +0 -76
  267. package/src/storage/rewind.ts +0 -266
  268. package/src/storage/sessionExport.ts +0 -49
  269. package/src/storage/sessions.ts +0 -495
  270. package/src/tools/bashSafety.ts +0 -186
  271. package/src/tools/bashTool.ts +0 -140
  272. package/src/tools/changeDirectoryTool.ts +0 -213
  273. package/src/tools/contracts.ts +0 -192
  274. package/src/tools/deleteFileTool.ts +0 -116
  275. package/src/tools/editTool.ts +0 -165
  276. package/src/tools/editUtils.ts +0 -170
  277. package/src/tools/fileDiff.ts +0 -261
  278. package/src/tools/listDirectoryTool.ts +0 -55
  279. package/src/tools/listSkillFilesTool.ts +0 -77
  280. package/src/tools/listSkillsTool.ts +0 -68
  281. package/src/tools/mcpResourceTools.ts +0 -95
  282. package/src/tools/permissionRules.ts +0 -85
  283. package/src/tools/privateContinuityEditTool.ts +0 -187
  284. package/src/tools/privateContinuityReadTool.ts +0 -106
  285. package/src/tools/readSkillTool.ts +0 -107
  286. package/src/tools/readTool.ts +0 -85
  287. package/src/tools/registry.ts +0 -103
  288. package/src/tools/writeFileTool.ts +0 -167
  289. package/src/ui/BrandSplash.tsx +0 -133
  290. package/src/ui/terminalTitle.ts +0 -30
  291. package/src/utils/images.ts +0 -140
  292. package/src/utils/markdownSegments.ts +0 -51
  293. package/src/utils/messages.ts +0 -37
  294. package/src/utils/withRetry.ts +0 -324
  295. /package/src/identity/{hub → manager}/continuity/state.ts +0 -0
  296. /package/src/identity/{hub → manager}/custody/helpers.ts +0 -0
  297. /package/src/identity/{hub → manager}/custody/preflight.ts +0 -0
  298. /package/src/identity/{hub → manager}/custody/state.ts +0 -0
  299. /package/src/identity/{hub → manager}/custody/useCustodyFlow.tsx +0 -0
  300. /package/src/identity/{hub → manager}/ens/EnsEditFlow.tsx +0 -0
  301. /package/src/identity/{hub → manager}/ens/advancedEnsValidation.ts +0 -0
  302. /package/src/identity/{hub → manager}/ens/state.ts +0 -0
  303. /package/src/identity/{hub → manager}/ens/transactions.ts +0 -0
  304. /package/src/identity/{hub → manager}/ens/types.ts +0 -0
  305. /package/src/identity/{hub → manager}/profile/identity.ts +0 -0
  306. /package/src/identity/{hub → manager}/restore/envelopes.ts +0 -0
  307. /package/src/identity/{hub → manager}/restore/helpers.ts +0 -0
  308. /package/src/identity/{hub → manager}/restore/recovery.ts +0 -0
  309. /package/src/identity/{hub → manager}/restore/resolve.ts +0 -0
  310. /package/src/identity/{hub → manager}/shared/components/BusyScreen.tsx +0 -0
  311. /package/src/identity/{hub → manager}/shared/components/NetworkScreen.tsx +0 -0
  312. /package/src/identity/{hub → manager}/shared/components/PinataJwtInput.tsx +0 -0
  313. /package/src/identity/{hub → manager}/shared/effects/receipts.ts +0 -0
  314. /package/src/identity/{hub → manager}/shared/effects/sync.ts +0 -0
  315. /package/src/identity/{hub → manager}/shared/model/format.ts +0 -0
  316. /package/src/identity/{hub → manager}/shared/operatorWallets.ts +0 -0
  317. /package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/ownership.ts +0 -0
  318. /package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/types.ts +0 -0
  319. /package/src/identity/{hub → manager}/shared/reconciliation/walletSetup.ts +0 -0
  320. /package/src/identity/{hub → manager}/shared/txGuard.ts +0 -0
  321. /package/src/identity/{hub → manager}/transfer/progress.ts +0 -0
  322. /package/src/identity/{hub → manager}/transfer/state.ts +0 -0
@@ -19,7 +19,7 @@ import { FlowTimeline } from '../shared/components/FlowTimeline.js'
19
19
  import { OPEN_BROWSER_HINT } from '../shared/components/WalletApprovalScreen.js'
20
20
  import { readCustodyMode } from '../custody/state.js'
21
21
  import { shortAddress } from '../shared/model/format.js'
22
- import type { ProfileUpdates } from '../identityHubReducer.js'
22
+ import type { ProfileUpdates } from '../reducer.js'
23
23
  import {
24
24
  normalizeApprovedOperatorWallets,
25
25
  removeApprovedOperatorWallet,
@@ -150,19 +150,17 @@ export const OperatorWalletsScreen: React.FC<OperatorWalletsScreenProps> = ({
150
150
  return (
151
151
  <Surface
152
152
  title="Operator Wallets"
153
- subtitle="Advanced custody must be set up before operator wallets can be managed."
153
+ subtitle="Set up Advanced custody first."
154
154
  footer={footerHint('enter select · esc back')}
155
155
  >
156
156
  <Box flexDirection="column">
157
- <Text color={theme.dim}>Switch to Advanced custody from the Custody Mode menu to capture an owner wallet.</Text>
158
- <Text color={theme.dim}>Operator wallets can be changed later and never receive token control.</Text>
159
157
  {phase.kind === 'main' && phase.error ? <Text color={theme.accentError}>{phase.error}</Text> : null}
160
158
  </Box>
161
159
  <Box marginTop={1}>
162
160
  <Select<'back'>
163
161
  options={[
164
162
  { value: 'back', role: 'section', label: 'Navigation' },
165
- { value: 'back', label: 'Back', hint: 'Return to the previous screen', role: 'utility' },
163
+ { value: 'back', label: 'Back', role: 'utility' },
166
164
  ]}
167
165
  hintLayout="inline"
168
166
  onSubmit={() => onBack()}
@@ -180,7 +178,6 @@ export const OperatorWalletsScreen: React.FC<OperatorWalletsScreenProps> = ({
180
178
  subtitle={
181
179
  <Box flexDirection="column">
182
180
  <FlowTimeline steps={['Verify Operator', 'Sign Backup', 'Publish Snapshot', 'Approve ENS', 'Approve Vault']} current={1} />
183
- <Text color={theme.dim}>Operator wallet signs restore access. Owner wallet then re-attests the backup, publishes the new snapshot, and authorizes the operator onchain (ENS + vault).</Text>
184
181
  </Box>
185
182
  }
186
183
  walletSession={walletSession}
@@ -202,7 +199,7 @@ export const OperatorWalletsScreen: React.FC<OperatorWalletsScreenProps> = ({
202
199
  return (
203
200
  <Surface
204
201
  title="Operator Wallets"
205
- subtitle="Owner wallet controls this list. The active operator wallet signs frequent updates; others stay authorized."
202
+ subtitle="Owner wallet controls this list."
206
203
  footer={footerHint('enter select · esc back')}
207
204
  >
208
205
  <Box flexDirection="column">
@@ -284,7 +281,7 @@ function operatorOptions(args: {
284
281
  }): Array<SelectOption<OperatorAction>> {
285
282
  const options: Array<SelectOption<OperatorAction>> = [
286
283
  { value: 'add-browser', role: 'section', label: 'Operator Wallets' },
287
- { value: 'add-browser', label: 'Add Wallet', hint: 'Connect wallet to sign restore access' },
284
+ { value: 'add-browser', label: 'Add Wallet' },
288
285
  ]
289
286
  if (args.records[0]) options.push({ value: `remove:${args.records[0].address}`, role: 'section', label: 'Operator Wallets' })
290
287
  for (const record of args.records) {
@@ -293,27 +290,23 @@ function operatorOptions(args: {
293
290
  options.push({
294
291
  value: `activate:${record.address}`,
295
292
  label: `Set Active: ${shortAddress(record.address)}`,
296
- hint: 'Make this the active operator wallet (owner wallet signs)',
297
293
  })
298
294
  }
299
295
  options.push({
300
296
  value: `remove:${record.address}`,
301
297
  label: `Unlink ${shortAddress(record.address)}${active ? ' (active)' : ''}`,
302
- hint: active
303
- ? 'Active operator wallet. Unlinking clears the active slot; pick a new active from the list.'
304
- : 'Remove this wallet from the approved list (owner wallet signs)',
298
+ ...(active ? {} : { hint: 'Remove' }),
305
299
  })
306
300
  }
307
301
  if (args.records.length > 1) {
308
302
  options.push({
309
303
  value: 'remove-all',
310
304
  label: 'Unlink All Operator Wallets',
311
- hint: 'Remove every approved operator wallet (owner wallet signs)',
312
305
  })
313
306
  }
314
307
  options.push(
315
308
  { value: 'back', role: 'section', label: 'Navigation' },
316
- { value: 'back', label: 'Back', hint: 'Return to the previous screen', role: 'utility' },
309
+ { value: 'back', label: 'Back', role: 'utility' },
317
310
  )
318
311
  return options
319
312
  }
@@ -332,15 +325,17 @@ const WalletWaitSurface: React.FC<{
332
325
  })
333
326
  return (
334
327
  <Surface title={title} subtitle={subtitle} footer={footerHint('esc cancels')}>
335
- <Box marginTop={1}>
336
- <Spinner label={walletSession ? 'waiting for wallet signature...' : 'opening wallet request...'} />
337
- </Box>
338
328
  {walletSession ? (
339
329
  <Box flexDirection="column">
340
- <Text color={theme.accentPeriwinkle} underline>{walletSession.url}</Text>
330
+ <Text color={theme.accentBlue} underline>{walletSession.url}</Text>
341
331
  <Text color={theme.dim}>{OPEN_BROWSER_HINT}</Text>
332
+ <Box marginTop={1}>
333
+ <Spinner label="waiting for operator wallet signature..." />
334
+ </Box>
342
335
  </Box>
343
- ) : null}
336
+ ) : (
337
+ <Spinner label="opening wallet request..." />
338
+ )}
344
339
  </Surface>
345
340
  )
346
341
  }
@@ -1,6 +1,6 @@
1
1
  import { getAddress, type Address } from 'viem'
2
2
  import type { AgentEnsRecords, AgentRecordDiff } from '../../ens/agentRecords.js'
3
- import type { EnsRegistryAction, EnsSetupBlockedPlan } from '../../ens/ensAutomation.js'
3
+ import type { EnsSetupBlockedPlan } from '../../ens/ensAutomation.js'
4
4
  import type { CustodyMode } from '../custody/state.js'
5
5
 
6
6
  export function abbreviateHexBlobs(input: string): string {
@@ -52,19 +52,6 @@ export function modeSwitchHeading(
52
52
  return 'Automation'
53
53
  }
54
54
 
55
- export function advancedSubdomainStatusText(action: EnsRegistryAction): string {
56
- switch (action) {
57
- case 'create-subdomain':
58
- case 'create-wrapped-subdomain':
59
- return 'Subdomain check: the owner wallet can create this agent ENS name during setup.'
60
- case 'set-resolver':
61
- case 'set-wrapped-resolver':
62
- return 'Subdomain check: the owner wallet can prepare this ENS name during setup.'
63
- case 'none':
64
- return 'Subdomain check: this ENS name is ready.'
65
- }
66
- }
67
-
68
55
  export function networkLabelForChainId(chainId: number): string {
69
56
  switch (chainId) {
70
57
  case 1: return 'Ethereum Mainnet'
@@ -3,19 +3,29 @@ import { Box, Text } from 'ink'
3
3
  import { Surface } from '../../../ui/Surface.js'
4
4
  import { Select } from '../../../ui/Select.js'
5
5
  import { TextInput } from '../../../ui/TextInput.js'
6
+ import { TextArea } from '../../../ui/TextArea.js'
6
7
  import { theme } from '../../../ui/theme.js'
7
8
  import type { AgentEnsRecordState, AgentEnsRecords } from '../../ens/agentRecords.js'
8
9
  import type { EnsSetupPlan } from '../../ens/ensAutomation.js'
9
- import type { Step } from '../identityHubReducer.js'
10
+ import type { Step } from '../reducer.js'
10
11
  import { readIdentityStateString } from '../custody/state.js'
11
- import { FlowTimeline } from '../shared/components/FlowTimeline.js'
12
12
  import { validateAgentIconReference } from '../../profile/agentIcon.js'
13
13
  import { EnsEditFlow, type EnsLinkOptions } from '../ens/EnsEditFlow.js'
14
14
  import type { AgentReconciliation } from '../shared/reconciliation/index.js'
15
15
 
16
+ type EditProfileStepKind =
17
+ | 'edit-profile-menu'
18
+ | 'edit-profile-name'
19
+ | 'edit-profile-description'
20
+ | 'edit-profile-image'
21
+ | 'edit-profile-review'
22
+ | 'edit-profile-ens'
23
+
16
24
  type EditProfileFlowProps = {
17
- step: Extract<Step, { kind: 'edit-profile-name' | 'edit-profile-description' | 'edit-profile-image' | 'edit-profile-review' | 'edit-profile-ens' }>
25
+ step: Extract<Step, { kind: EditProfileStepKind }>
18
26
  reconciliation: AgentReconciliation
27
+ onSelectField: (field: 'name' | 'description' | 'image') => void
28
+ onSaveProfile: () => void
19
29
  onNameSubmit: (name: string) => void
20
30
  onDescriptionSubmit: (description: string) => void
21
31
  onIconSubmit: (iconPath?: string) => void
@@ -28,16 +38,16 @@ type EditProfileFlowProps = {
28
38
  onManageOperatorWalletAccess: () => void
29
39
  onBack: () => void
30
40
  onMenu: () => void
41
+ onBackToEditMenu: () => void
31
42
  }
32
43
 
33
- const footerHint = (hint: string) => <Text color={theme.dim}>{hint}</Text>
34
- export const EDIT_PROFILE_STEPS = ['Name', 'Description', 'Icon', 'Review', 'Save']
35
- const EDIT_NEXT_FOOTER = 'enter next · esc back'
36
- const EDIT_DESCRIPTION_FOOTER = 'enter next · shift+enter newline · esc back'
44
+ const footerHint = (hint: string) => <Text color={theme.menuStatus}>{hint}</Text>
37
45
 
38
46
  export const EditProfileFlow: React.FC<EditProfileFlowProps> = ({
39
47
  step,
40
48
  reconciliation,
49
+ onSelectField,
50
+ onSaveProfile,
41
51
  onNameSubmit,
42
52
  onDescriptionSubmit,
43
53
  onIconSubmit,
@@ -50,16 +60,17 @@ export const EditProfileFlow: React.FC<EditProfileFlowProps> = ({
50
60
  onManageOperatorWalletAccess,
51
61
  onBack,
52
62
  onMenu,
63
+ onBackToEditMenu,
53
64
  }) => {
65
+ if (step.kind === 'edit-profile-menu') {
66
+ return <EditProfileMenuStep step={step} onSelectField={onSelectField} onSaveProfile={onSaveProfile} onBack={onBack} />
67
+ }
68
+
54
69
  if (step.kind === 'edit-profile-name') {
55
70
  const currentName = step.name ?? readIdentityStateString(step.identity.state, 'name')
56
71
  return (
57
- <Surface
58
- title="Edit Profile"
59
- subtitle={<FlowTimeline steps={EDIT_PROFILE_STEPS} current={1} />}
60
- footer={footerHint(EDIT_NEXT_FOOTER)}
61
- >
62
- <Text color={theme.dim}>Saved: {readIdentityStateString(step.identity.state, 'name') || '(unnamed)'}</Text>
72
+ <Surface title="Edit Name" footer={footerHint('enter save · esc back')}>
73
+ <Text color={theme.menuStatus}>Saved: {readIdentityStateString(step.identity.state, 'name') || '(unnamed)'}</Text>
63
74
  <Box marginTop={1}>
64
75
  <TextInput
65
76
  key="edit-profile-name"
@@ -67,7 +78,7 @@ export const EditProfileFlow: React.FC<EditProfileFlowProps> = ({
67
78
  placeholder="agent name"
68
79
  validate={value => value.trim().length >= 2 ? null : 'name must be at least 2 characters'}
69
80
  onSubmit={value => onNameSubmit(value.trim())}
70
- onCancel={onMenu}
81
+ onCancel={onBackToEditMenu}
71
82
  />
72
83
  </Box>
73
84
  </Surface>
@@ -75,17 +86,11 @@ export const EditProfileFlow: React.FC<EditProfileFlowProps> = ({
75
86
  }
76
87
 
77
88
  if (step.kind === 'edit-profile-image') {
78
- return <AgentIconStep step={step} onIconSubmit={onIconSubmit} onIconPick={onIconPick} onBack={onBack} />
89
+ return <AgentIconStep step={step} onIconSubmit={onIconSubmit} onIconPick={onIconPick} onBack={onBack} onMenu={onBackToEditMenu} />
79
90
  }
80
91
 
81
92
  if (step.kind === 'edit-profile-review') {
82
- return (
83
- <EditProfileReviewStep
84
- step={step}
85
- onSave={onReviewSave}
86
- onBack={onBack}
87
- />
88
- )
93
+ return <EditProfileReviewStep step={step} onSave={onReviewSave} onBack={onBackToEditMenu} />
89
94
  }
90
95
 
91
96
  if (step.kind === 'edit-profile-ens') {
@@ -108,52 +113,92 @@ export const EditProfileFlow: React.FC<EditProfileFlowProps> = ({
108
113
  const currentDescription = readIdentityStateString(step.identity.state, 'description')
109
114
  const draftDescription = step.description ?? currentDescription
110
115
  return (
111
- <Surface
112
- title="Edit Profile"
113
- subtitle={<FlowTimeline steps={EDIT_PROFILE_STEPS} current={2} />}
114
- footer={footerHint(EDIT_DESCRIPTION_FOOTER)}
115
- >
116
- <Text color={theme.dim}>Saved: {currentDescription || '(no description)'}</Text>
116
+ <Surface title="Edit Description">
117
+ <Text color={theme.menuStatus}>Saved: {currentDescription || '(no description)'}</Text>
117
118
  <Box marginTop={1}>
118
- <TextInput
119
+ <TextArea
119
120
  key="edit-profile-description"
120
121
  initialValue={draftDescription}
121
- placeholder="description"
122
- allowEmpty
123
- multiline
122
+ placeholder="describe this agent"
124
123
  onSubmit={value => onDescriptionSubmit(value.trim())}
125
- onCancel={onBack}
124
+ onCancel={onBackToEditMenu}
126
125
  />
127
126
  </Box>
128
127
  </Surface>
129
128
  )
130
129
  }
131
130
 
131
+ const EditProfileMenuStep: React.FC<{
132
+ step: Extract<Step, { kind: 'edit-profile-menu' }>
133
+ onSelectField: (field: 'name' | 'description' | 'image') => void
134
+ onSaveProfile: () => void
135
+ onBack: () => void
136
+ }> = ({ step, onSelectField, onSaveProfile, onBack }) => {
137
+ const savedName = readIdentityStateString(step.identity.state, 'name')
138
+ const savedDescription = readIdentityStateString(step.identity.state, 'description')
139
+ const savedIcon = readIdentityStateString(step.identity.state, 'imageUrl')
140
+
141
+ const draftName = step.name ?? savedName
142
+ const draftDescription = step.description ?? savedDescription
143
+ const draftIcon = describeDraftIcon(step.imagePath, savedIcon)
144
+
145
+ const nameHint = draftName || '(unnamed)'
146
+ const descriptionHint = draftDescription || '(no description)'
147
+ const iconHint = step.imagePath !== undefined
148
+ ? `${draftIcon} (draft)`
149
+ : savedIcon
150
+ ? draftIcon
151
+ : '(no icon)'
152
+
153
+ const dirty = step.name !== undefined || step.description !== undefined || step.imagePath !== undefined
154
+ const saveHint = dirty ? 'Publish public profile and update the token URI' : 'No changes to save'
155
+
156
+ return (
157
+ <Surface title="Edit Profile" subtitle="Save publishes all fields together." footer={footerHint('enter select · esc back')}>
158
+ <Select<'name' | 'description' | 'image' | 'save' | 'back'>
159
+ options={[
160
+ { value: 'name', label: 'Name', hint: nameHint },
161
+ { value: 'description', label: 'Description', hint: descriptionHint },
162
+ { value: 'image', label: 'Icon', hint: iconHint },
163
+ { value: 'save', label: 'Save Profile', hint: saveHint, disabled: !dirty },
164
+ { value: 'back', label: 'Back', role: 'utility' },
165
+ ]}
166
+ hintLayout="inline"
167
+ onSubmit={choice => {
168
+ if (choice === 'name') return onSelectField('name')
169
+ if (choice === 'description') return onSelectField('description')
170
+ if (choice === 'image') return onSelectField('image')
171
+ if (choice === 'save') return onSaveProfile()
172
+ return onBack()
173
+ }}
174
+ onCancel={onBack}
175
+ />
176
+ </Surface>
177
+ )
178
+ }
179
+
132
180
  const AgentIconStep: React.FC<{
133
181
  step: Extract<Step, { kind: 'edit-profile-image' }>
134
182
  onIconSubmit: (iconPath?: string) => void
135
183
  onIconPick: () => void
136
184
  onBack: () => void
137
- }> = ({ step, onIconSubmit, onIconPick, onBack }) => {
185
+ onMenu: () => void
186
+ }> = ({ step, onIconSubmit, onIconPick, onBack, onMenu }) => {
138
187
  const [entryMode, setEntryMode] = React.useState(false)
139
188
  const currentIcon = readIdentityStateString(step.identity.state, 'imageUrl')
140
189
  const selectedIcon = describeDraftIcon(step.imagePath, currentIcon)
141
190
 
142
191
  if (entryMode) {
143
192
  return (
144
- <Surface
145
- title="Edit Profile"
146
- subtitle={<FlowTimeline steps={EDIT_PROFILE_STEPS} current={3} />}
147
- footer={footerHint(EDIT_NEXT_FOOTER)}
148
- >
149
- <Text color={theme.dim}>Current: {currentIcon ? shortIconReference(currentIcon) : '(no icon)'}</Text>
193
+ <Surface title="Edit Icon" footer={footerHint('enter save · esc back')}>
194
+ <Text color={theme.menuStatus}>Current: {currentIcon ? shortIconReference(currentIcon) : '(no icon)'}</Text>
150
195
  <Box marginTop={1}>
151
196
  <TextInput
152
197
  key="edit-profile-icon-entry"
153
198
  placeholder="https://.../icon.png or C:\\path\\icon.png"
154
199
  validate={validateAgentIconReference}
155
200
  onSubmit={value => onIconSubmit(value.trim())}
156
- onCancel={onBack}
201
+ onCancel={() => setEntryMode(false)}
157
202
  />
158
203
  </Box>
159
204
  </Surface>
@@ -161,26 +206,19 @@ const AgentIconStep: React.FC<{
161
206
  }
162
207
 
163
208
  return (
164
- <Surface
165
- title="Edit Profile"
166
- subtitle={<FlowTimeline steps={EDIT_PROFILE_STEPS} current={3} />}
167
- footer={footerHint('enter select · esc back')}
168
- >
209
+ <Surface title="Edit Icon" footer={footerHint('enter select · esc back')}>
169
210
  <Box flexDirection="column">
170
- <Text color={theme.dim}>Agent Icon: {selectedIcon}</Text>
211
+ <Text color={theme.menuStatus}>Agent Icon: {selectedIcon}</Text>
171
212
  {step.error ? <Text color={theme.accentError}>{step.error}</Text> : null}
172
213
  </Box>
173
214
  <Box marginTop={1}>
174
215
  <Select<'choose' | 'enter' | 'skip' | 'delete' | 'back'>
175
216
  options={[
176
- { value: 'choose', role: 'section', label: 'Icon Source' },
177
- { value: 'choose', label: 'Choose Local File', hint: 'Open the operating system file picker' },
178
- { value: 'enter', label: 'Enter URL Or Path', hint: 'Use https, ipfs, or a local media path' },
179
- { value: 'skip', role: 'section', label: 'Current Icon' },
180
- { value: 'skip', label: currentIcon ? 'Keep Current Icon' : 'No Icon', hint: 'Continue without changing the icon' },
181
- { value: 'delete', label: 'Remove Agent Icon', hint: 'Clear the public profile icon', disabled: !currentIcon },
182
- { value: 'back', role: 'section', label: 'Navigation' },
183
- { value: 'back', label: 'Back', hint: 'Return to description', role: 'utility' },
217
+ { value: 'choose', label: 'Choose Local File', hint: 'Open the file picker' },
218
+ { value: 'enter', label: 'Enter URL Or Path', hint: 'https, ipfs, or local path' },
219
+ { value: 'skip', label: currentIcon ? 'Keep Current Icon' : 'No Icon' },
220
+ { value: 'delete', label: 'Remove Agent Icon', disabled: !currentIcon },
221
+ { value: 'back', label: 'Back', role: 'utility' },
184
222
  ]}
185
223
  hintLayout="inline"
186
224
  onSubmit={choice => {
@@ -188,9 +226,9 @@ const AgentIconStep: React.FC<{
188
226
  if (choice === 'enter') { setEntryMode(true); return }
189
227
  if (choice === 'delete') return onIconSubmit('delete')
190
228
  if (choice === 'skip') return onIconSubmit(undefined)
191
- return onBack()
229
+ return onMenu()
192
230
  }}
193
- onCancel={onBack}
231
+ onCancel={onMenu}
194
232
  />
195
233
  </Box>
196
234
  </Surface>
@@ -204,11 +242,7 @@ const EditProfileReviewStep: React.FC<{
204
242
  }> = ({ step, onSave, onBack }) => {
205
243
  const currentIcon = readIdentityStateString(step.identity.state, 'imageUrl')
206
244
  return (
207
- <Surface
208
- title="Edit Profile"
209
- subtitle={<FlowTimeline steps={EDIT_PROFILE_STEPS} current={4} />}
210
- footer={footerHint('enter save · esc back')}
211
- >
245
+ <Surface title="Review Public Profile" footer={footerHint('enter save · esc back')}>
212
246
  <Box flexDirection="column">
213
247
  <ReviewRow label="Name" value={step.name || '(unnamed)'} />
214
248
  <ReviewRow label="Description" value={step.description || '(no description)'} />
@@ -217,9 +251,8 @@ const EditProfileReviewStep: React.FC<{
217
251
  <Box marginTop={1}>
218
252
  <Select<'save' | 'back'>
219
253
  options={[
220
- { value: 'save', label: 'Save Public Profile', hint: 'Publish public profile and update the token URI' },
221
- { value: 'back', role: 'section', label: 'Navigation' },
222
- { value: 'back', label: 'Back', hint: 'Return to Agent Icon', role: 'utility' },
254
+ { value: 'save', label: 'Save Profile', hint: 'Publish and update URI' },
255
+ { value: 'back', label: 'Back', role: 'utility' },
223
256
  ]}
224
257
  hintLayout="inline"
225
258
  onSubmit={choice => choice === 'save' ? onSave() : onBack()}
@@ -235,7 +268,7 @@ const ReviewRow: React.FC<{ label: string; value: string }> = ({ label, value })
235
268
  return (
236
269
  <Box flexDirection="row">
237
270
  <Box width={13} flexShrink={0}>
238
- <Text color={theme.dim}>{label}</Text>
271
+ <Text color={theme.menuStatus}>{label}</Text>
239
272
  </Box>
240
273
  <Box flexDirection="column" flexGrow={1}>
241
274
  {lines.map((line, i) => (
@@ -2,7 +2,6 @@ import { getAddress, type Address } from 'viem'
2
2
  import type { EthagentIdentity } from '../../../storage/config.js'
3
3
  import {
4
4
  createWalletRestoreAccessChallenge,
5
- serializeContinuitySnapshotEnvelope,
6
5
  type WalletChallengePurpose,
7
6
  } from '../../continuity/envelope.js'
8
7
  import {
@@ -23,10 +22,9 @@ import { resolveValidatedPinataJwt, savePinataJwt } from '../../storage/pinataJw
23
22
  import {
24
23
  openBrowserWalletSession,
25
24
  requestBrowserWalletSignatureAndTransaction,
26
- type BrowserWalletSignature,
27
25
  type WalletPurpose,
28
26
  } from '../../wallet/browserWallet.js'
29
- import type { ProfileUpdates, Step } from '../identityHubReducer.js'
27
+ import type { ProfileUpdates, Step } from '../reducer.js'
30
28
  import { acquireTxGuard, releaseTxGuard } from '../shared/txGuard.js'
31
29
  import type { EffectCallbacks } from '../shared/effects/types.js'
32
30
  import { awaitConfirmedReceipt } from '../shared/effects/receipts.js'
@@ -20,7 +20,7 @@ import {
20
20
  } from '../../registry/erc8004.js'
21
21
  import { VAULT_ABI } from '../../registry/vault.js'
22
22
  import type { BrowserWalletSignature } from '../../wallet/browserWallet.js'
23
- import type { Step } from '../identityHubReducer.js'
23
+ import type { Step } from '../reducer.js'
24
24
  import {
25
25
  assertVerifiedPin,
26
26
  deriveAgentName,
@@ -6,7 +6,7 @@ import { clearOwnerAddressField, clearVaultAddressField, readOwnerAddressField,
6
6
  import { validateAdvancedEnsRelationship } from '../ens/advancedEnsValidation.js'
7
7
  import { readCustodyMode } from '../custody/state.js'
8
8
  import { ensValidationReasonText } from '../ens/state.js'
9
- import type { ProfileUpdates } from '../identityHubReducer.js'
9
+ import type { ProfileUpdates } from '../reducer.js'
10
10
  import {
11
11
  assertActiveOperatorIsApproved,
12
12
  mergeApprovedOperatorWallets,
@@ -7,9 +7,10 @@ import type { ContinuitySnapshotEnvelope } from '../continuity/envelope.js'
7
7
  import type { AgentEnsRecordState, AgentEnsRecords } from '../ens/agentRecords.js'
8
8
  import type { EnsSetupPlan } from '../ens/ensAutomation.js'
9
9
  import type { WalletPurpose } from '../wallet/browserWallet.js'
10
- import type { IdentityHubErrorView } from './shared/model/errors.js'
10
+ import type { IdentityManagerErrorView } from './shared/model/errors.js'
11
11
  import type { ApprovedOperatorWalletInput } from './shared/operatorWallets.js'
12
12
  import type { CustodyMode } from './custody/state.js'
13
+ import type { ImportCandidate } from './create/importScan.js'
13
14
 
14
15
  export type RestorePurpose = 'restore' | 'switch'
15
16
  type RestoreNotFoundReason = 'no-owner-or-operator' | 'search-incomplete' | 'cancelled'
@@ -29,19 +30,22 @@ export type ProfileUpdates = {
29
30
  }
30
31
 
31
32
  type RestorableBackupEnvelope = AgentStateBackupEnvelope | ContinuitySnapshotEnvelope
33
+ type RestoreFetchingStep = { kind: 'restore-fetching'; cid: string; apiUrl: string; candidate: Erc8004AgentCandidate; requesterAddress?: string; purpose?: RestorePurpose }
32
34
 
33
35
  export type Step =
34
36
  | { kind: 'menu' }
37
+ | { kind: 'operation-complete'; message: string }
35
38
  | { kind: 'replace-confirm'; next: 'create' | 'restore' }
36
39
  | { kind: 'create-name'; name?: string; error?: string }
37
40
  | { kind: 'create-description'; name: string; description?: string }
38
41
  | { kind: 'create-network'; name: string; description: string }
39
42
  | { kind: 'create-custody'; name: string; description: string; network?: SelectableNetwork }
40
- | { kind: 'create-preflight'; name: string; description: string; network?: SelectableNetwork; custodyMode: CustodyMode }
41
- | { kind: 'create-registry'; name: string; description: string; resolution: RegistryResolution; custodyMode: CustodyMode; error?: string }
42
- | { kind: 'create-signing'; name: string; description: string; registry: Erc8004RegistryConfig; custodyMode: CustodyMode; pinataJwt?: string }
43
- | { kind: 'create-storage'; name: string; description: string; registry: Erc8004RegistryConfig; custodyMode: CustodyMode; error?: string; pinataJwt?: string }
44
- | { kind: 'first-run-ens-prompt'; identity: EthagentIdentity; registry: Erc8004RegistryConfig }
43
+ | { kind: 'create-import'; name: string; description: string; network?: SelectableNetwork; custodyMode: CustodyMode; candidates?: ImportCandidate[] }
44
+ | { kind: 'create-preflight'; name: string; description: string; network?: SelectableNetwork; custodyMode: CustodyMode; importNotes?: ImportCandidate[] }
45
+ | { kind: 'create-registry'; name: string; description: string; resolution: RegistryResolution; custodyMode: CustodyMode; error?: string; importNotes?: ImportCandidate[] }
46
+ | { kind: 'create-signing'; name: string; description: string; registry: Erc8004RegistryConfig; custodyMode: CustodyMode; pinataJwt?: string; importNotes?: ImportCandidate[] }
47
+ | { kind: 'create-storage'; name: string; description: string; registry: Erc8004RegistryConfig; custodyMode: CustodyMode; error?: string; pinataJwt?: string; importNotes?: ImportCandidate[] }
48
+ | { kind: 'first-run-ens-prompt'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; origin?: 'create' | 'restore' }
45
49
  | { kind: 'restore-wallet'; purpose?: RestorePurpose }
46
50
  | { kind: 'restore-network'; ownerHandle: string; purpose?: RestorePurpose }
47
51
  | { kind: 'restore-registry'; ownerHandle: string; error?: string; purpose?: RestorePurpose }
@@ -51,7 +55,7 @@ export type Step =
51
55
  | { kind: 'restore-token-id-input'; ownerHandle: string; registry: Erc8004RegistryConfig; purpose?: RestorePurpose; busy?: boolean; error?: string }
52
56
  | { kind: 'restore-not-found'; ownerHandle: string; registry: Erc8004RegistryConfig; requesterAddress?: string; reason: RestoreNotFoundReason; purpose?: RestorePurpose }
53
57
  | { kind: 'restore-select-token'; ownerHandle: string; registry: Erc8004RegistryConfig; candidates: Erc8004AgentCandidate[]; requesterAddress?: string; purpose?: RestorePurpose }
54
- | { kind: 'restore-fetching'; cid: string; apiUrl: string; candidate: Erc8004AgentCandidate; requesterAddress?: string; purpose?: RestorePurpose }
58
+ | RestoreFetchingStep
55
59
  | { kind: 'restore-authorizing'; cid: string; apiUrl: string; envelope: RestorableBackupEnvelope; candidate: Erc8004AgentCandidate; requesterAddress?: string; purpose?: RestorePurpose }
56
60
  | { kind: 'rebackup-signing'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; pinataJwt?: string; profileUpdates?: ProfileUpdates; returnTo?: Step; walletPurpose?: WalletPurpose; vaultAddress?: `0x${string}` }
57
61
  | { kind: 'rebackup-storage'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; error?: string; pinataJwt?: string; profileUpdates?: ProfileUpdates; returnTo?: Step; walletPurpose?: WalletPurpose; vaultAddress?: `0x${string}` }
@@ -67,18 +71,17 @@ export type Step =
67
71
  | { kind: 'rebackup-confirm'; back: Step }
68
72
  | { kind: 'recovery-refetch-confirm'; back: Step }
69
73
  | { kind: 'recovery-refetching'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; back: Step }
74
+ | { kind: 'continuity-overwrite-confirm'; action: 'restore'; next: RestoreFetchingStep; back: Step }
70
75
  | { kind: 'rebackup-start'; back: Step }
76
+ | { kind: 'edit-profile-menu'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; name?: string; description?: string; imagePath?: string; returnTo?: Step }
71
77
  | { kind: 'edit-profile-name'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; name?: string; description?: string; imagePath?: string; returnTo?: Step }
72
- | { kind: 'edit-profile-description'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; name: string; description?: string; imagePath?: string; returnTo?: Step }
73
- | { kind: 'edit-profile-image'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; name: string; description: string; imagePath?: string; error?: string; returnTo?: Step }
78
+ | { kind: 'edit-profile-description'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; name?: string; description?: string; imagePath?: string; returnTo?: Step }
79
+ | { kind: 'edit-profile-image'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; name?: string; description?: string; imagePath?: string; error?: string; returnTo?: Step }
74
80
  | { kind: 'edit-profile-review'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; name: string; description: string; imagePath?: string; returnTo?: Step }
75
81
  | { kind: 'edit-profile-ens'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; returnTo?: Step; initialView?: 'advanced' }
76
82
  | { kind: 'ens-records-tx'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; fullName: string; records: AgentEnsRecords; currentRecords?: AgentEnsRecordState; ownerAddress?: string; returnTo?: Step; clearRecords?: boolean }
77
83
  | { kind: 'ens-setup-registry-tx'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; setup: EnsSetupPlan; returnTo?: Step }
78
84
  | { kind: 'ens-setup-records-tx'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; setup: EnsSetupPlan; returnTo?: Step; registryTxHash?: string }
79
- | { kind: 'ens-clear-flow-running'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; fullName: string; ownerAddress: `0x${string}`; records: AgentEnsRecords; currentRecords?: AgentEnsRecordState; pinataJwt?: string; returnTo?: Step }
80
- | { kind: 'ens-update-flow-running'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; fullName: string; ownerAddress: `0x${string}`; records: AgentEnsRecords; currentRecords?: AgentEnsRecordState; pinataJwt?: string; returnTo?: Step }
81
- | { kind: 'ens-link-flow-running'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; setup: EnsSetupPlan; pinataJwt?: string; returnTo?: Step }
82
85
  | { kind: 'manage-ens-operators'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; returnTo?: Step; notice?: string; error?: string }
83
86
  | { kind: 'custody-model'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; returnTo?: Step; notice?: string }
84
87
  | { kind: 'custody-advanced-confirm'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; returnTo?: Step }
@@ -103,14 +106,14 @@ export type Step =
103
106
  | { kind: 'details' }
104
107
  | { kind: 'save-prompt'; back: Step }
105
108
  | { kind: 'busy'; label: string }
106
- | { kind: 'error'; error: IdentityHubErrorView; back: Step }
109
+ | { kind: 'error'; error: IdentityManagerErrorView; back: Step }
107
110
  | { kind: 'identity-unlinked'; identity: EthagentIdentity; registry: Erc8004RegistryConfig; onChainOwner?: string; back: Step }
108
111
 
109
112
  export type Action =
110
113
  | { type: 'setStep'; step: Step }
111
114
  | { type: 'back'; from: Step }
112
115
 
113
- export function identityHubReducer(state: Step, action: Action): Step {
116
+ export function identityManagerReducer(state: Step, action: Action): Step {
114
117
  switch (action.type) {
115
118
  case 'setStep':
116
119
  return action.step
@@ -131,6 +134,8 @@ function backStep(from: Step): Step {
131
134
  return { kind: 'create-description', name: from.name, description: from.description }
132
135
  case 'create-custody':
133
136
  return { kind: 'create-network', name: from.name, description: from.description }
137
+ case 'create-import':
138
+ return { kind: 'create-custody', name: from.name, description: from.description, ...(from.network ? { network: from.network } : {}) }
134
139
  case 'create-preflight':
135
140
  return { kind: 'create-custody', name: from.name, description: from.description, ...(from.network ? { network: from.network } : {}) }
136
141
  case 'create-registry':
@@ -192,8 +197,12 @@ function backStep(from: Step): Step {
192
197
  case 'recovery-refetch-confirm':
193
198
  case 'recovery-refetching':
194
199
  return { kind: 'menu' }
195
- case 'edit-profile-name':
200
+ case 'continuity-overwrite-confirm':
201
+ return from.back
202
+ case 'edit-profile-menu':
196
203
  return from.returnTo ?? { kind: 'continuity-public' }
204
+ case 'edit-profile-name':
205
+ return { kind: 'edit-profile-menu', identity: from.identity, registry: from.registry, name: from.name, description: from.description, imagePath: from.imagePath, returnTo: from.returnTo }
197
206
  case 'edit-profile-description':
198
207
  return { kind: 'edit-profile-name', identity: from.identity, registry: from.registry, name: from.name, description: from.description, imagePath: from.imagePath, returnTo: from.returnTo }
199
208
  case 'edit-profile-image':
@@ -213,17 +222,6 @@ function backStep(from: Step): Step {
213
222
  returnTo: from.returnTo,
214
223
  ...(from.setup.mode === 'advanced' ? { initialView: 'advanced' as const } : {}),
215
224
  }
216
- case 'ens-clear-flow-running':
217
- case 'ens-update-flow-running':
218
- return { kind: 'edit-profile-ens', identity: from.identity, registry: from.registry, returnTo: from.returnTo }
219
- case 'ens-link-flow-running':
220
- return {
221
- kind: 'edit-profile-ens',
222
- identity: from.identity,
223
- registry: from.registry,
224
- returnTo: from.returnTo,
225
- ...(from.setup.mode === 'advanced' ? { initialView: 'advanced' as const } : {}),
226
- }
227
225
  case 'manage-ens-operators':
228
226
  return from.returnTo ?? { kind: 'menu' }
229
227
  case 'custody-model':
@@ -276,6 +274,7 @@ export function createStepNumber(step: Step): number {
276
274
  return 3
277
275
  case 'create-custody':
278
276
  return 4
277
+ case 'create-import':
279
278
  case 'create-preflight':
280
279
  case 'create-storage':
281
280
  case 'create-registry':