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
@@ -1,106 +0,0 @@
1
- import React from 'react'
2
- import { Box, Text } from 'ink'
3
- import { theme } from '../../../ui/theme.js'
4
- import type { EthagentConfig, EthagentIdentity } from '../../../storage/config.js'
5
- import {
6
- identitySummaryRows,
7
- lastBackupLabel,
8
- localChangeStatusView,
9
- type LocalChangeStatusView,
10
- } from '../identityHubModel.js'
11
-
12
- import type { ContinuityWorkingTreeStatus } from '../../continuity/storage.js'
13
-
14
- type SummaryRow = {
15
- label: string
16
- value: string
17
- tone: 'ok' | 'dim' | 'warn'
18
- highlight?: boolean
19
- }
20
-
21
- export const IdentitySummary: React.FC<{
22
- identity?: EthagentIdentity
23
- config?: EthagentConfig
24
- workingStatus?: ContinuityWorkingTreeStatus | null
25
- compact?: boolean
26
- }> = ({ identity, config, workingStatus, compact = false }) => {
27
- if (!identity) {
28
- return (
29
- <Text color={theme.dim}>No agent yet. Create or load one.</Text>
30
- )
31
- }
32
-
33
- const rows = identitySummaryRows(identity, config)
34
- const lastBackup = lastBackupLabel(identity)
35
- const stateName = typeof (identity.state as Record<string, unknown> | undefined)?.name === 'string'
36
- ? ((identity.state as Record<string, unknown>).name as string).trim()
37
- : ''
38
-
39
- const row = (label: string) => rows.find(item => item.label === label)
40
- const localChangeStatus = localChangeStatusView(workingStatus)
41
- const lastSavedRow: SummaryRow = { label: 'Last Saved', value: lastBackup, tone: lastBackup === 'never' ? 'dim' : 'ok' }
42
-
43
- const summaryRows: SummaryRow[] = [
44
- { label: 'Token', value: row('token')?.value ?? 'Not Created', tone: row('token')?.tone ?? 'dim', highlight: true },
45
- { label: 'Network', value: row('network')?.value ?? 'Unknown', tone: row('network')?.tone ?? 'dim' },
46
- { label: 'Owner', value: row('owner')?.value ?? 'Not Connected', tone: row('owner')?.tone ?? 'dim' },
47
- { label: 'Snapshot', value: row('state')?.value ?? 'Not Saved Yet', tone: row('state')?.tone ?? 'dim', highlight: true },
48
- lastSavedRow,
49
- { label: 'Skills', value: row('skills')?.value ?? 'Not Saved', tone: row('skills')?.tone ?? 'dim' },
50
- { label: 'Agent Card', value: row('card')?.value ?? 'Not Saved', tone: row('card')?.tone ?? 'dim' },
51
- { label: 'Image', value: row('image')?.value ?? 'Not Attached', tone: row('image')?.tone ?? 'dim' },
52
- ]
53
-
54
- return (
55
- <Box flexDirection="column">
56
- <Text color={theme.accentPrimary} bold>{stateName || 'Active Agent'}</Text>
57
- {summaryRows.map(row => {
58
- const valueColor = row.tone === 'warn' ? '#e87070' : (row.tone === 'ok' ? theme.text : theme.dim)
59
- return (
60
- <Text key={row.label}>
61
- <Text color={theme.dim}>{row.label.padEnd(12)}</Text>
62
- <Text color={valueColor} bold={row.highlight ?? false}>{displayValue(row.value)}</Text>
63
- </Text>
64
- )
65
- })}
66
- <Box marginTop={1}>
67
- <LocalChangeStatusLine status={localChangeStatus} />
68
- </Box>
69
- </Box>
70
- )
71
- }
72
-
73
- const LocalChangeStatusLine: React.FC<{ status: LocalChangeStatusView }> = ({ status }) => {
74
- if (status.hasLocalChanges) {
75
- return (
76
- <Text color="#e87070" bold>
77
- Local changes detected
78
- {status.files.length > 0 ? `: ${status.files.join(', ')}` : ''}
79
- </Text>
80
- )
81
- }
82
-
83
- const color = status.tone === 'ok' ? theme.accentMint : status.tone === 'warn' ? theme.accentPeach : theme.dim
84
- const label = status.detail === 'None detected' ? 'No local changes detected' : status.detail
85
- return <Text color={color}>{label}</Text>
86
- }
87
-
88
- function displayValue(value: string): string {
89
- const mapped = DISPLAY_VALUES[value]
90
- return mapped ?? value
91
- }
92
-
93
- const DISPLAY_VALUES: Record<string, string> = {
94
- 'not attached': 'Not Attached',
95
- 'not connected': 'Not Connected',
96
- 'not created': 'Not Created',
97
- 'not saved': 'Not Saved',
98
- 'not saved yet': 'Not Saved Yet',
99
- 'never': 'Never',
100
- 'unknown': 'Unknown',
101
- 'ethereum mainnet': 'Ethereum Mainnet',
102
- 'arbitrum one': 'Arbitrum One',
103
- 'base': 'Base',
104
- 'optimism': 'Optimism',
105
- 'polygon': 'Polygon',
106
- }
@@ -1,117 +0,0 @@
1
- import React from 'react'
2
- import { Box } from 'ink'
3
- import { Surface } from '../../../ui/Surface.js'
4
- import { Select, type SelectOption } from '../../../ui/Select.js'
5
- import type { EthagentConfig, EthagentIdentity } from '../../../storage/config.js'
6
- import type { ContinuityWorkingTreeStatus } from '../../continuity/storage.js'
7
- import { IdentitySummary } from './IdentitySummary.js'
8
-
9
- type MenuScreenProps = {
10
- mode: 'first-run' | 'manage'
11
- config?: EthagentConfig
12
- identity?: EthagentIdentity
13
- workingStatus?: ContinuityWorkingTreeStatus | null
14
- canRebackup: boolean
15
- footer: React.ReactNode
16
- onCreate: () => void
17
- onLoad: () => void
18
- onBackupNow: () => void
19
- onRefetchLatest: () => void
20
- onPublicProfile: () => void
21
- onPrivateMemory: () => void
22
- onCopyValues: () => void
23
- onStorageCredential: () => void
24
- onSkip: () => void
25
- onCancel: () => void
26
- }
27
-
28
- type Action =
29
- | 'public-profile'
30
- | 'private-memory'
31
- | 'backup'
32
- | 'refetch'
33
- | 'copy'
34
- | 'storage-credential'
35
- | 'create'
36
- | 'load'
37
- | 'skip'
38
- | 'cancel'
39
-
40
- export const MenuScreen: React.FC<MenuScreenProps> = ({
41
- mode,
42
- config,
43
- identity,
44
- workingStatus,
45
- canRebackup,
46
- footer,
47
- onCreate,
48
- onLoad,
49
- onBackupNow,
50
- onRefetchLatest,
51
- onPublicProfile,
52
- onPrivateMemory,
53
- onCopyValues,
54
- onStorageCredential,
55
- onSkip,
56
- onCancel,
57
- }) => {
58
- const title = mode === 'first-run' ? 'Set Up Agent Identity' : 'Identity Hub'
59
- const subtitle = mode === 'first-run'
60
- ? 'Create a portable agent or load one you already own.'
61
- : 'Public, private, recovery, storage, and device controls are separate.'
62
-
63
- const canRefetch = Boolean(canRebackup && identity?.backup?.cid)
64
-
65
- const options: Array<SelectOption<Action>> = identity
66
- ? [
67
- { value: 'public-profile', role: 'section', prefix: '--', label: 'Public Metadata' },
68
- { value: 'public-profile', label: 'Public Profile', hint: 'Name, image, skills.json, Agent Card' },
69
- { value: 'private-memory', role: 'section', prefix: '--', label: 'Private Local Files' },
70
- { value: 'private-memory', label: 'Memory and Persona', hint: 'SOUL.md and MEMORY.md only on this device' },
71
- { value: 'backup', role: 'section', prefix: '--', label: 'Recovery' },
72
- { value: 'backup', label: 'Save Snapshot Now', hint: 'Saves any local edits to SOUL.md, MEMORY.md, skills.json, and public profile', disabled: !canRebackup },
73
- { value: 'refetch', label: 'Refetch Latest Snapshot', hint: 'Restore local files from the latest saved snapshot', disabled: !canRefetch },
74
- { value: 'storage-credential', role: 'section', prefix: '--', label: 'Storage' },
75
- { value: 'storage-credential', label: 'IPFS Credential', hint: 'Save, replace, or forget Pinata JWT' },
76
- { value: 'copy', role: 'section', prefix: '--', label: 'Agent Token' },
77
- { value: 'copy', label: 'Copy Values', hint: 'Copy CIDs, token ID, URI, or owner' },
78
- { value: 'load', label: 'Switch Agent', hint: 'Load a different token owned by your wallet' },
79
- { value: 'create', label: 'New Agent', hint: 'Mint another token and make it active here' },
80
- { value: 'cancel', role: 'section', prefix: '--', label: 'Exit' },
81
- { value: 'cancel', label: 'Close Identity Hub', hint: 'Return to chat without changing identity', role: 'utility' },
82
- ]
83
- : [
84
- { value: 'create', role: 'section', prefix: '--', label: 'Setup' },
85
- { value: 'create', label: 'Create New Agent', hint: 'Mint a wallet-owned token for this machine' },
86
- { value: 'load', label: 'Load Existing Agent', hint: 'Find an agent token your wallet already owns' },
87
- { value: 'skip', role: 'section', prefix: '--', label: 'Exit' },
88
- ...(mode === 'first-run'
89
- ? [{ value: 'skip' as Action, label: 'Skip For Now', hint: 'Continue now; use /identity later', role: 'utility' as const }]
90
- : [{ value: 'cancel' as Action, label: 'Close Identity Hub', hint: 'Return to chat without changing identity', role: 'utility' as const }]),
91
- ]
92
-
93
- return (
94
- <Surface title={title} subtitle={subtitle} footer={footer}>
95
- <IdentitySummary identity={identity} config={config} workingStatus={workingStatus} compact={Boolean(identity)} />
96
- <Box marginTop={1}>
97
- <Select<Action>
98
- options={options}
99
- hintLayout="inline"
100
- onSubmit={choice => {
101
- if (choice === 'skip') return onSkip()
102
- if (choice === 'cancel') return onCancel()
103
- if (choice === 'public-profile') return onPublicProfile()
104
- if (choice === 'private-memory') return onPrivateMemory()
105
- if (choice === 'backup') return onBackupNow()
106
- if (choice === 'refetch') return onRefetchLatest()
107
- if (choice === 'copy') return onCopyValues()
108
- if (choice === 'storage-credential') return onStorageCredential()
109
- if (choice === 'load') return onLoad()
110
- if (choice === 'create') return onCreate()
111
- }}
112
- onCancel={() => mode === 'first-run' ? onSkip() : onCancel()}
113
- />
114
- </Box>
115
- </Surface>
116
- )
117
- }
@@ -1,206 +0,0 @@
1
- import React from 'react'
2
- import { Text } from 'ink'
3
- import { Surface } from '../../../ui/Surface.js'
4
- import { Select } from '../../../ui/Select.js'
5
- import { TextInput } from '../../../ui/TextInput.js'
6
- import { theme } from '../../../ui/theme.js'
7
- import { normalizeErc8004RegistryConfig } from '../../registry/erc8004.js'
8
- import {
9
- isCurrentAgentCandidate,
10
- networkLabel,
11
- tokenCandidateHint,
12
- tokenCandidateSelectLabel,
13
- } from '../identityHubModel.js'
14
- import { registryConfigFromConfig } from '../../registry/registryConfig.js'
15
- import type { Step } from '../identityHubReducer.js'
16
- import { WalletApprovalScreen } from './WalletApprovalScreen.js'
17
- import { BusyScreen } from './BusyScreen.js'
18
- import type { BrowserWalletReady } from '../../wallet/browserWallet.js'
19
- import type { EthagentConfig } from '../../../storage/config.js'
20
- import type { RestoreProgress } from '../identityHubEffects.js'
21
-
22
- type RestoreStep = Exclude<Extract<Step, { kind: `restore-${string}` }>, { kind: 'restore-wallet' | 'restore-network' }>
23
-
24
- type RestoreFlowProps = {
25
- step: RestoreStep
26
- config?: EthagentConfig
27
- walletSession: BrowserWalletReady | null
28
- restoreProgress: RestoreProgress | null
29
- onConnectWallet: () => void
30
- onRestoreRegistrySubmit: (value: string) => void
31
- onTokenIdSubmit: (value: string) => void
32
- onTokenSelect: (tokenId: string) => void
33
- onBack: () => void
34
- }
35
-
36
- const footerHint = (hint: string) => <Text color={theme.dim}>{hint}</Text>
37
-
38
- export const RestoreFlow: React.FC<RestoreFlowProps> = ({
39
- step,
40
- config,
41
- walletSession,
42
- restoreProgress,
43
- onConnectWallet,
44
- onRestoreRegistrySubmit,
45
- onTokenIdSubmit,
46
- onTokenSelect,
47
- onBack,
48
- }) => {
49
- const purpose = 'purpose' in step ? step.purpose ?? 'restore' : 'restore'
50
- const isSwitch = purpose === 'switch'
51
-
52
- if (step.kind === 'restore-owner') {
53
- return (
54
- <Surface
55
- title={isSwitch ? 'Switch Agent Identity' : 'Restore an Agent'}
56
- subtitle="Connect the wallet that owns the agent you want to load."
57
- footer={footerHint('enter select · esc back')}
58
- >
59
- <Select<'connect'>
60
- options={[
61
- { value: 'connect', role: 'section', prefix: '--', label: 'Wallet' },
62
- { value: 'connect', label: 'Connect Wallet', hint: 'Search tokens owned by browser wallet' },
63
- ]}
64
- hintLayout="inline"
65
- onSubmit={onConnectWallet}
66
- onCancel={onBack}
67
- />
68
- </Surface>
69
- )
70
- }
71
-
72
- if (step.kind === 'restore-registry') {
73
- const resolution = registryConfigFromConfig(config)
74
- return (
75
- <Surface
76
- title={`${resolution.network ? networkLabel(resolution.network).charAt(0).toUpperCase() + networkLabel(resolution.network).slice(1) : ''} Agent Registry`}
77
- subtitle={step.error ? `Lookup failed: ${step.error}` : 'Paste the agent registry address for this network.'}
78
- footer={footerHint('enter discover · esc back')}
79
- >
80
- <Text color={theme.dim}>RPC defaults to {resolution.defaultRpcUrl}</Text>
81
- <TextInput
82
- initialValue={config?.erc8004?.identityRegistryAddress ?? ''}
83
- placeholder="0x registry address"
84
- validate={value => {
85
- try {
86
- normalizeErc8004RegistryConfig({
87
- chainId: resolution.chainId,
88
- rpcUrl: resolution.config?.rpcUrl ?? resolution.defaultRpcUrl,
89
- identityRegistryAddress: value.trim(),
90
- })
91
- return null
92
- } catch (err: unknown) {
93
- return (err as Error).message
94
- }
95
- }}
96
- onSubmit={onRestoreRegistrySubmit}
97
- onCancel={onBack}
98
- />
99
- </Surface>
100
- )
101
- }
102
-
103
- if (step.kind === 'restore-discovering') {
104
- return (
105
- <BusyScreen
106
- title={isSwitch ? 'Finding Agent Identities' : 'Finding Agents'}
107
- subtitle={step.ownerHandle}
108
- label="searching this network..."
109
- onCancel={onBack}
110
- />
111
- )
112
- }
113
-
114
- if (step.kind === 'restore-token-id') {
115
- return (
116
- <Surface
117
- title="Enter Agent Token ID"
118
- subtitle={step.error ?? `${networkLabelForRegistry(step.registry)} lookup needs the token ID.`}
119
- footer={footerHint('enter continue · esc back')}
120
- >
121
- <TextInput
122
- placeholder="#45744"
123
- validate={value => parseTokenIdInput(value) ? null : 'enter a token id'}
124
- onSubmit={value => onTokenIdSubmit(value.trim())}
125
- onCancel={onBack}
126
- />
127
- </Surface>
128
- )
129
- }
130
-
131
- if (step.kind === 'restore-select-token') {
132
- return (
133
- <Surface
134
- title={isSwitch ? 'Switch to an Agent' : 'Choose Your Agent'}
135
- subtitle={step.ownerHandle}
136
- footer={footerHint('enter select · esc back')}
137
- >
138
- <Select<string>
139
- options={[
140
- { value: 'section:owned-agents', role: 'section', prefix: '--', label: 'Owned Agents' },
141
- ...step.candidates.map(candidate => {
142
- const current = isSwitch && isCurrentAgentCandidate(config?.identity, candidate)
143
- return {
144
- value: candidate.agentId.toString(),
145
- label: tokenCandidateSelectLabel(candidate, current),
146
- hint: tokenCandidateHint(candidate),
147
- }
148
- }),
149
- ]}
150
- hintLayout="inline"
151
- onSubmit={onTokenSelect}
152
- onCancel={onBack}
153
- />
154
- </Surface>
155
- )
156
- }
157
-
158
- if (step.kind === 'restore-fetching') {
159
- return (
160
- <BusyScreen
161
- title={isSwitch ? 'Switching Agent Identity' : 'Restoring Your Agent'}
162
- subtitle="IPFS"
163
- label="opening encrypted state from IPFS..."
164
- onCancel={onBack}
165
- />
166
- )
167
- }
168
-
169
- if (step.kind === 'restore-authorizing') {
170
- if (restoreProgress) {
171
- return (
172
- <BusyScreen
173
- title={isSwitch ? 'Switching Agent Identity' : 'Restoring Your Agent'}
174
- subtitle="Wallet Signature Received"
175
- label={restoreProgress.label}
176
- />
177
- )
178
- }
179
- return (
180
- <WalletApprovalScreen
181
- title={isSwitch ? 'Approve Switch' : 'Approve Restore'}
182
- subtitle={isSwitch ? 'Use the wallet that owns this agent to switch.' : 'Use the wallet that owns this agent.'}
183
- walletSession={walletSession}
184
- label="waiting for approval..."
185
- onCancel={onBack}
186
- />
187
- )
188
- }
189
-
190
- return null
191
- }
192
-
193
- function parseTokenIdInput(value: string): string | null {
194
- const normalized = value.trim().replace(/^#/, '')
195
- return /^\d+$/.test(normalized) ? normalized : null
196
- }
197
-
198
- function networkLabelForRegistry(registry: { chainId: number }): string {
199
- const network = registry.chainId === 1 ? 'mainnet'
200
- : registry.chainId === 42161 ? 'arbitrum'
201
- : registry.chainId === 8453 ? 'base'
202
- : registry.chainId === 10 ? 'optimism'
203
- : registry.chainId === 137 ? 'polygon'
204
- : undefined
205
- return network ? networkLabel(network) : `chain ${registry.chainId}`
206
- }