ethagent 2.1.1 → 2.3.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 (177) hide show
  1. package/package.json +2 -1
  2. package/src/app/FirstRun.tsx +1 -7
  3. package/src/app/FirstRunTimeline.tsx +1 -1
  4. package/src/auth/openaiOAuth/credentials.ts +47 -0
  5. package/src/auth/openaiOAuth/crypto.ts +23 -0
  6. package/src/auth/openaiOAuth/index.ts +238 -0
  7. package/src/auth/openaiOAuth/landingPage.ts +125 -0
  8. package/src/auth/openaiOAuth/listener.ts +151 -0
  9. package/src/auth/openaiOAuth/refresh.ts +70 -0
  10. package/src/auth/openaiOAuth/shared.ts +115 -0
  11. package/src/chat/ChatBottomPane.tsx +20 -11
  12. package/src/chat/ChatScreen.tsx +160 -35
  13. package/src/chat/ConversationStack.tsx +1 -1
  14. package/src/chat/MessageList.tsx +185 -72
  15. package/src/chat/SessionStatus.tsx +3 -1
  16. package/src/chat/chatScreenUtils.ts +11 -15
  17. package/src/chat/chatSessionState.ts +3 -2
  18. package/src/chat/chatTurnOrchestrator.ts +1 -7
  19. package/src/chat/commands.ts +28 -27
  20. package/src/chat/display/DiffView.tsx +193 -0
  21. package/src/chat/display/SyntaxText.tsx +192 -0
  22. package/src/chat/display/toolCallDisplay.ts +103 -0
  23. package/src/chat/display/toolResultDisplay.ts +19 -0
  24. package/src/chat/{ChatInput.tsx → input/ChatInput.tsx} +36 -23
  25. package/src/chat/{TranscriptView.tsx → transcript/TranscriptView.tsx} +24 -50
  26. package/src/chat/{transcriptViewport.ts → transcript/transcriptViewport.ts} +12 -30
  27. package/src/chat/{ContextLimitView.tsx → views/ContextLimitView.tsx} +3 -3
  28. package/src/chat/{ContinuityEditReviewView.tsx → views/ContinuityEditReviewView.tsx} +11 -3
  29. package/src/chat/{CopyPicker.tsx → views/CopyPicker.tsx} +4 -5
  30. package/src/chat/{PermissionPrompt.tsx → views/PermissionPrompt.tsx} +16 -17
  31. package/src/chat/{PermissionsView.tsx → views/PermissionsView.tsx} +6 -6
  32. package/src/chat/{PlanApprovalView.tsx → views/PlanApprovalView.tsx} +4 -4
  33. package/src/chat/{ResumeView.tsx → views/ResumeView.tsx} +35 -35
  34. package/src/chat/views/RewindView.tsx +410 -0
  35. package/src/identity/continuity/privateEdit/diff.ts +2 -78
  36. package/src/identity/ens/agentRecords.ts +5 -19
  37. package/src/identity/ens/ensAutomation/setup.ts +0 -1
  38. package/src/identity/ens/ensAutomation/types.ts +0 -1
  39. package/src/identity/hub/OperationalRoutes.tsx +23 -32
  40. package/src/identity/hub/Routes.tsx +13 -13
  41. package/src/identity/hub/{flows/continuity → continuity}/ContinuityDashboardScreen.tsx +9 -9
  42. package/src/identity/hub/{flows/continuity → continuity}/RebackupStorageScreen.tsx +2 -2
  43. package/src/identity/hub/{flows/continuity → continuity}/RecoveryConfirmScreen.tsx +5 -5
  44. package/src/identity/hub/{flows/continuity → continuity}/SavePromptScreen.tsx +5 -5
  45. package/src/identity/hub/{effects/rebackup/runRebackup.ts → continuity/effects.ts} +19 -19
  46. package/src/identity/hub/{effects/rebackup → continuity}/index.ts +1 -1
  47. package/src/identity/hub/{effects/shared → continuity}/snapshot.ts +8 -8
  48. package/src/identity/hub/{effects/rebackup → continuity}/vault.ts +15 -15
  49. package/src/identity/hub/{flows/create → create}/CreateFlow.tsx +13 -13
  50. package/src/identity/hub/{effects/create.ts → create/effects.ts} +4 -4
  51. package/src/identity/hub/{flows/custody → custody}/CustodyEditFlow.tsx +10 -48
  52. package/src/identity/hub/{flows/custody/custodyFlowActions.ts → custody/actions.ts} +11 -9
  53. package/src/identity/hub/{flows/custody/custodyFlowHelpers.ts → custody/helpers.ts} +4 -4
  54. package/src/identity/hub/{effects/vault → custody}/preflight.ts +5 -5
  55. package/src/identity/hub/{flows/custody/custodyFlowRoutes.tsx → custody/routes.tsx} +8 -8
  56. package/src/identity/hub/{flows/custody/custodyEffects.ts → custody/transactions.ts} +9 -9
  57. package/src/identity/hub/{flows/custody/custodyFlowTypes.ts → custody/types.ts} +6 -6
  58. package/src/identity/hub/{flows/custody/custodyFlowEffects.ts → custody/useCustodyEffects.ts} +7 -7
  59. package/src/identity/hub/{flows/custody → custody}/useCustodyFlow.tsx +5 -5
  60. package/src/identity/hub/ens/EnsEditAdvancedScreens.tsx +241 -0
  61. package/src/identity/hub/{flows/ens → ens}/EnsEditFlow.tsx +27 -82
  62. package/src/identity/hub/{flows/ens → ens}/EnsEditMaintenanceScreens.tsx +25 -65
  63. package/src/identity/hub/{flows/ens → ens}/EnsEditReviewScreens.tsx +12 -30
  64. package/src/identity/hub/ens/EnsEditRunners.tsx +62 -0
  65. package/src/identity/hub/{flows/ens → ens}/EnsEditShared.tsx +15 -14
  66. package/src/identity/hub/{flows/ens → ens}/EnsEditSimpleScreens.tsx +68 -217
  67. package/src/identity/hub/{flows/ens/IdentityHubEnsFlow.tsx → ens/EnsFlow.tsx} +18 -11
  68. package/src/identity/hub/{flows/ens/OperatorWalletsScreen.tsx → ens/EnsOperatorWalletsScreen.tsx} +17 -48
  69. package/src/identity/hub/{advancedEnsValidation.ts → ens/advancedEnsValidation.ts} +2 -2
  70. package/src/identity/hub/{flows/ens/ensEditCopy.ts → ens/editCopy.ts} +4 -4
  71. package/src/identity/hub/{effects/ens/flows.ts → ens/effects.ts} +7 -7
  72. package/src/identity/hub/{effects/ens → ens}/index.ts +1 -1
  73. package/src/identity/hub/{model/ens.ts → ens/state.ts} +1 -1
  74. package/src/identity/hub/{effects/ens → ens}/transactions.ts +232 -232
  75. package/src/identity/hub/{flows/ens/ensEditTypes.ts → ens/types.ts} +12 -26
  76. package/src/identity/hub/identityHubReducer.ts +3 -3
  77. package/src/identity/hub/{flows/profile → profile}/EditProfileFlow.tsx +17 -10
  78. package/src/identity/hub/{effects/publicProfile/runPublicProfileSave.ts → profile/effects.ts} +55 -177
  79. package/src/identity/hub/{model → profile}/identity.ts +3 -3
  80. package/src/identity/hub/{effects/profile/profileState.ts → profile/state.ts} +181 -173
  81. package/src/identity/hub/{flows/restore → restore}/RestoreFlow.tsx +21 -21
  82. package/src/identity/hub/{effects/restore → restore}/apply.ts +10 -10
  83. package/src/identity/hub/{effects/restore → restore}/auth.ts +7 -7
  84. package/src/identity/hub/{effects/restore → restore}/discover.ts +6 -6
  85. package/src/identity/hub/{effects/restore → restore}/envelopes.ts +2 -2
  86. package/src/identity/hub/{effects/restore → restore}/fetch.ts +3 -3
  87. package/src/identity/hub/{effects/restore/shared.ts → restore/helpers.ts} +6 -6
  88. package/src/identity/hub/{effects/restore → restore}/recovery.ts +10 -10
  89. package/src/identity/hub/{effects/restore → restore}/resolve.ts +4 -4
  90. package/src/identity/hub/restore/restoreAdmin.ts +34 -0
  91. package/src/identity/hub/{flows/restore/useRestoreFlowEffects.ts → restore/useRestoreEffects.ts} +5 -5
  92. package/src/identity/hub/{flows/settings → settings}/StorageCredentialScreen.tsx +5 -5
  93. package/src/identity/hub/{components → shared/components}/BusyScreen.tsx +4 -4
  94. package/src/identity/hub/{components → shared/components}/DetailsScreen.tsx +4 -4
  95. package/src/identity/hub/{components → shared/components}/ErrorScreen.tsx +4 -4
  96. package/src/identity/hub/{components → shared/components}/FlowTimeline.tsx +1 -1
  97. package/src/identity/hub/{components → shared/components}/IdentitySummary.tsx +16 -11
  98. package/src/identity/hub/{components → shared/components}/MenuScreen.tsx +8 -9
  99. package/src/identity/hub/{components → shared/components}/NetworkScreen.tsx +4 -4
  100. package/src/identity/hub/{components → shared/components}/PinataJwtInput.tsx +4 -4
  101. package/src/identity/hub/{components → shared/components}/UnlinkedIdentityScreen.tsx +5 -5
  102. package/src/identity/hub/{components → shared/components}/WalletApprovalScreen.tsx +6 -6
  103. package/src/identity/hub/{components → shared/components}/menuFlagsFromReconciliation.ts +2 -4
  104. package/src/identity/hub/{effects/shared → shared/effects}/profilePrep.ts +1 -1
  105. package/src/identity/hub/{effects → shared/effects}/receipts.ts +2 -2
  106. package/src/identity/hub/{effects/shared → shared/effects}/sync.ts +6 -47
  107. package/src/identity/hub/{effects → shared/effects}/types.ts +3 -3
  108. package/src/identity/hub/{model → shared/model}/copy.ts +2 -2
  109. package/src/identity/hub/{model → shared/model}/errors.ts +5 -5
  110. package/src/identity/hub/{model → shared/model}/network.ts +3 -3
  111. package/src/identity/hub/{operatorWallets.ts → shared/operatorWallets.ts} +1 -1
  112. package/src/identity/hub/{reconciliation → shared/reconciliation}/agentReconciliation/hook.ts +1 -2
  113. package/src/identity/hub/{reconciliation → shared/reconciliation}/agentReconciliation/ownership.ts +2 -2
  114. package/src/identity/hub/{reconciliation → shared/reconciliation}/agentReconciliation/run.ts +7 -40
  115. package/src/identity/hub/{reconciliation → shared/reconciliation}/agentReconciliation/types.ts +0 -4
  116. package/src/identity/hub/{reconciliation → shared/reconciliation}/index.ts +0 -7
  117. package/src/identity/hub/shared/reconciliation/walletSetup.ts +27 -0
  118. package/src/identity/hub/{utils.ts → shared/utils.ts} +5 -5
  119. package/src/identity/hub/{flows/token-transfer/IdentityHubTokenTransferFlow.tsx → transfer/TokenTransferFlow.tsx} +8 -8
  120. package/src/identity/hub/{flows/token-transfer → transfer}/TokenTransferScreens.tsx +14 -14
  121. package/src/identity/hub/{effects/token-transfer/runTokenTransfer.ts → transfer/effects.ts} +16 -16
  122. package/src/identity/hub/{effects/token-transfer → transfer}/progress.ts +1 -1
  123. package/src/identity/hub/useIdentityHubController.ts +11 -11
  124. package/src/identity/hub/useIdentityHubSideEffects.ts +11 -11
  125. package/src/identity/wallet/browserWallet/types.ts +0 -5
  126. package/src/identity/wallet/page/copy.ts +1 -31
  127. package/src/identity/wallet/walletPurposeCompat.ts +0 -2
  128. package/src/models/ModelPicker.tsx +248 -8
  129. package/src/models/catalog.ts +29 -1
  130. package/src/models/modelPickerOptions.ts +12 -10
  131. package/src/models/providerDisplay.ts +16 -0
  132. package/src/providers/errors.ts +6 -4
  133. package/src/providers/openai-chat.ts +2 -1
  134. package/src/providers/openai-responses-format.ts +156 -0
  135. package/src/providers/openai-responses.ts +276 -0
  136. package/src/providers/registry.ts +85 -8
  137. package/src/runtime/sessionMode.ts +1 -1
  138. package/src/runtime/systemPrompt.ts +4 -2
  139. package/src/runtime/toolExecution.ts +9 -6
  140. package/src/runtime/turn.ts +29 -1
  141. package/src/storage/rewind.ts +20 -0
  142. package/src/storage/secrets.ts +4 -1
  143. package/src/storage/sessions.ts +2 -1
  144. package/src/tools/bashSafety.ts +7 -3
  145. package/src/tools/bashTool.ts +1 -1
  146. package/src/tools/contracts.ts +3 -0
  147. package/src/tools/deleteFileTool.ts +8 -3
  148. package/src/tools/editTool.ts +10 -5
  149. package/src/tools/fileDiff.ts +261 -0
  150. package/src/tools/privateContinuityEditTool.ts +11 -1
  151. package/src/tools/writeFileTool.ts +8 -3
  152. package/src/ui/Spinner.tsx +25 -3
  153. package/src/ui/TextInput.tsx +2 -2
  154. package/src/ui/theme.ts +17 -0
  155. package/src/utils/clipboard.ts +10 -7
  156. package/src/utils/openExternal.ts +20 -10
  157. package/src/chat/RewindView.tsx +0 -386
  158. package/src/chat/toolResultDisplay.ts +0 -8
  159. package/src/identity/ens/ensRegistration.ts +0 -199
  160. package/src/identity/hub/effects/index.ts +0 -74
  161. package/src/identity/hub/effects/publicProfile/index.ts +0 -5
  162. package/src/identity/hub/effects/restore/restoreEffects.ts +0 -22
  163. package/src/identity/hub/effects/restoreAdmin.ts +0 -93
  164. package/src/identity/hub/effects/token-transfer/index.ts +0 -6
  165. package/src/identity/hub/flows/ens/EnsEditAdvancedScreens.tsx +0 -336
  166. package/src/identity/hub/flows/ens/EnsEditRunners.tsx +0 -198
  167. package/src/identity/hub/reconciliation/walletSetup.ts +0 -220
  168. /package/src/chat/{chatInputState.ts → input/chatInputState.ts} +0 -0
  169. /package/src/chat/{chatPaste.ts → input/chatPaste.ts} +0 -0
  170. /package/src/chat/{textCursor.ts → input/textCursor.ts} +0 -0
  171. /package/src/identity/hub/{model/continuity.ts → continuity/state.ts} +0 -0
  172. /package/src/identity/hub/{model/custody.ts → custody/state.ts} +0 -0
  173. /package/src/identity/hub/{effects/restore → restore}/index.ts +0 -0
  174. /package/src/identity/hub/{model → shared/model}/format.ts +0 -0
  175. /package/src/identity/hub/{reconciliation → shared/reconciliation}/useAgentReconciliation.ts +0 -0
  176. /package/src/identity/hub/{txGuard.ts → shared/txGuard.ts} +0 -0
  177. /package/src/identity/hub/{model/transfer.ts → transfer/state.ts} +0 -0
@@ -0,0 +1,34 @@
1
+ import type { EthagentConfig } from '../../../storage/config.js'
2
+ import { saveConfig } from '../../../storage/config.js'
3
+ import { normalizeErc8004RegistryConfig } from '../../registry/erc8004.js'
4
+ import { registryConfigFromConfig } from '../../registry/registryConfig.js'
5
+ import type { Step } from '../identityHubReducer.js'
6
+ import type { EffectCallbacks } from '../shared/effects/types.js'
7
+
8
+ export async function runRestoreRegistrySubmit(
9
+ value: string,
10
+ step: Extract<Step, { kind: 'restore-registry' }>,
11
+ config: EthagentConfig | undefined,
12
+ onConfigChange: ((config: EthagentConfig) => void) | undefined,
13
+ callbacks: EffectCallbacks,
14
+ ): Promise<void> {
15
+ const resolution = registryConfigFromConfig(config)
16
+ const registry = normalizeErc8004RegistryConfig({
17
+ chainId: resolution.chainId,
18
+ rpcUrl: resolution.config?.rpcUrl ?? resolution.defaultRpcUrl,
19
+ identityRegistryAddress: value.trim(),
20
+ })
21
+ if (config && onConfigChange) {
22
+ const next: EthagentConfig = {
23
+ ...config,
24
+ erc8004: {
25
+ chainId: registry.chainId,
26
+ rpcUrl: registry.rpcUrl,
27
+ identityRegistryAddress: registry.identityRegistryAddress,
28
+ },
29
+ }
30
+ await saveConfig(next)
31
+ onConfigChange(next)
32
+ }
33
+ callbacks.onStep({ kind: 'restore-discovering', ownerHandle: step.ownerHandle, registry, purpose: step.purpose })
34
+ }
@@ -1,13 +1,13 @@
1
1
  import { useEffect } from 'react'
2
- import type { EthagentConfig } from '../../../../storage/config.js'
2
+ import type { EthagentConfig } from '../../../storage/config.js'
3
3
  import {
4
4
  runRestoreAuthorize,
5
5
  runRestoreConnectWallet,
6
6
  runRestoreDiscover,
7
7
  runRestoreFetch,
8
- } from '../../effects/restore/index.js'
9
- import type { EffectCallbacks } from '../../effects/types.js'
10
- import type { Step } from '../../identityHubReducer.js'
8
+ } from './index.js'
9
+ import type { EffectCallbacks } from '../shared/effects/types.js'
10
+ import type { Step } from '../identityHubReducer.js'
11
11
 
12
12
  const MIN_BUSY_ERROR_MS = 2000
13
13
 
@@ -24,7 +24,7 @@ type RestoreFlowEffectsArgs = {
24
24
  handleStepError: (err: unknown, backStep: Step, softCancel?: Step) => void
25
25
  }
26
26
 
27
- export function useRestoreFlowEffects(args: RestoreFlowEffectsArgs): void {
27
+ export function useRestoreEffects(args: RestoreFlowEffectsArgs): void {
28
28
  const { step, config, callbacks, handleStepError } = args
29
29
 
30
30
  useEffect(() => {
@@ -1,10 +1,10 @@
1
1
  import React from 'react'
2
2
  import { Box, Text } from 'ink'
3
- import { Surface } from '../../../../ui/Surface.js'
4
- import { Select } from '../../../../ui/Select.js'
5
- import { theme } from '../../../../ui/theme.js'
6
- import { PinataJwtInput } from '../../components/PinataJwtInput.js'
7
- import type { Step } from '../../identityHubReducer.js'
3
+ import { Surface } from '../../../ui/Surface.js'
4
+ import { Select } from '../../../ui/Select.js'
5
+ import { theme } from '../../../ui/theme.js'
6
+ import { PinataJwtInput } from '../shared/components/PinataJwtInput.js'
7
+ import type { Step } from '../identityHubReducer.js'
8
8
 
9
9
  type StorageCredentialAction = 'edit' | 'forget' | 'back'
10
10
 
@@ -1,9 +1,9 @@
1
1
  import React from 'react'
2
2
  import { Text } from 'ink'
3
- import { Surface } from '../../../ui/Surface.js'
4
- import { Spinner } from '../../../ui/Spinner.js'
5
- import { theme } from '../../../ui/theme.js'
6
- import { useAppInput } from '../../../app/input/AppInputProvider.js'
3
+ import { Surface } from '../../../../ui/Surface.js'
4
+ import { Spinner } from '../../../../ui/Spinner.js'
5
+ import { theme } from '../../../../ui/theme.js'
6
+ import { useAppInput } from '../../../../app/input/AppInputProvider.js'
7
7
 
8
8
  type BusyScreenProps = {
9
9
  title: string
@@ -1,9 +1,9 @@
1
1
  import React from 'react'
2
2
  import { Box, Text } from 'ink'
3
- import { theme } from '../../../ui/theme.js'
4
- import { Surface } from '../../../ui/Surface.js'
5
- import { Select, type SelectOption } from '../../../ui/Select.js'
6
- import type { EthagentConfig, EthagentIdentity } from '../../../storage/config.js'
3
+ import { theme } from '../../../../ui/theme.js'
4
+ import { Surface } from '../../../../ui/Surface.js'
5
+ import { Select, type SelectOption } from '../../../../ui/Select.js'
6
+ import type { EthagentConfig, EthagentIdentity } from '../../../../storage/config.js'
7
7
  import { copyableIdentityFields, identityValuesCopyHint } from '../model/copy.js'
8
8
  import { IdentitySummary } from './IdentitySummary.js'
9
9
 
@@ -1,10 +1,10 @@
1
1
  import React from 'react'
2
2
  import { Text } from 'ink'
3
- import { Surface } from '../../../ui/Surface.js'
4
- import { Select } from '../../../ui/Select.js'
5
- import { theme } from '../../../ui/theme.js'
3
+ import { Surface } from '../../../../ui/Surface.js'
4
+ import { Select } from '../../../../ui/Select.js'
5
+ import { theme } from '../../../../ui/theme.js'
6
6
  import type { IdentityHubErrorView } from '../model/errors.js'
7
- import type { Step } from '../identityHubReducer.js'
7
+ import type { Step } from '../../identityHubReducer.js'
8
8
 
9
9
  type ErrorScreenProps = {
10
10
  error: IdentityHubErrorView
@@ -1,6 +1,6 @@
1
1
  import React from 'react'
2
2
  import { Text } from 'ink'
3
- import { theme } from '../../../ui/theme.js'
3
+ import { theme } from '../../../../ui/theme.js'
4
4
 
5
5
  type FlowTimelineProps = {
6
6
  steps: string[]
@@ -1,35 +1,36 @@
1
1
  import React from 'react'
2
2
  import { Box, Text } from 'ink'
3
- import { theme } from '../../../ui/theme.js'
4
- import type { EthagentConfig, EthagentIdentity } from '../../../storage/config.js'
3
+ import { theme } from '../../../../ui/theme.js'
4
+ import type { EthagentConfig, EthagentIdentity } from '../../../../storage/config.js'
5
5
  import {
6
6
  displayCustodyMode,
7
7
  identityOwnerAddress,
8
8
  readCustodyMode,
9
9
  readIdentityStateString,
10
- } from '../model/custody.js'
10
+ } from '../../custody/state.js'
11
11
  import {
12
12
  hasPendingPublish,
13
13
  localChangeStatusView,
14
14
  type LocalChangeStatusView,
15
- } from '../model/continuity.js'
16
- import { ensValidationReasonText, selectEnsStatus } from '../model/ens.js'
15
+ } from '../../continuity/state.js'
16
+ import { ensValidationReasonText, selectEnsStatus } from '../../ens/state.js'
17
17
  import { shortAddress } from '../model/format.js'
18
- import { identitySummaryRows, lastBackupLabel } from '../model/identity.js'
19
- import { transferSnapshotView, type TransferSnapshotView } from '../model/transfer.js'
18
+ import { identitySummaryRows, lastBackupLabel } from '../../profile/identity.js'
19
+ import { transferSnapshotView, type TransferSnapshotView } from '../../transfer/state.js'
20
20
 
21
- import type { ContinuityWorkingTreeStatus } from '../../continuity/storage.js'
21
+ import type { ContinuityWorkingTreeStatus } from '../../../continuity/storage.js'
22
22
 
23
23
  interface IdentitySummaryProps {
24
24
  identity?: EthagentIdentity
25
25
  config?: EthagentConfig
26
26
  workingStatus?: ContinuityWorkingTreeStatus | null
27
27
  hideLocalChanges?: boolean
28
+ hideHeader?: boolean
28
29
  tokenLinked?: boolean
29
30
  onchainOwner?: string
30
31
  }
31
32
 
32
- export const IdentitySummary: React.FC<IdentitySummaryProps> = ({ identity, config, workingStatus, hideLocalChanges = false, tokenLinked = true, onchainOwner }) => {
33
+ export const IdentitySummary: React.FC<IdentitySummaryProps> = ({ identity, config, workingStatus, hideLocalChanges = false, hideHeader = false, tokenLinked = true, onchainOwner }) => {
33
34
  if (!identity) {
34
35
  return (
35
36
  <Text color={theme.dim}>No agent yet. Create or load one.</Text>
@@ -60,8 +61,12 @@ export const IdentitySummary: React.FC<IdentitySummaryProps> = ({ identity, conf
60
61
 
61
62
  return (
62
63
  <Box flexDirection="column">
63
- <Text color={theme.accentPeriwinkle} bold>{stateName || 'Active Agent'}</Text>
64
- <Text color={identity.agentId ? theme.text : theme.dim} bold={Boolean(identity.agentId)}>{tokenLine}</Text>
64
+ {hideHeader ? null : (
65
+ <>
66
+ <Text color={theme.accentPeriwinkle} bold>{stateName || 'Active Agent'}</Text>
67
+ <Text color={identity.agentId ? theme.text : theme.dim} bold={Boolean(identity.agentId)}>{tokenLine}</Text>
68
+ </>
69
+ )}
65
70
  <Text>
66
71
  <Text color={theme.dim}>{'ENS'.padEnd(12)}</Text>
67
72
  {ensStatus.kind === 'linked'
@@ -1,13 +1,13 @@
1
1
  import React from 'react'
2
2
  import { Box, Text } from 'ink'
3
- import { Surface } from '../../../ui/Surface.js'
4
- import { Select, type SelectOption } from '../../../ui/Select.js'
5
- import { theme } from '../../../ui/theme.js'
6
- import type { EthagentConfig, EthagentIdentity } from '../../../storage/config.js'
7
- import type { ContinuityWorkingTreeStatus } from '../../continuity/storage.js'
8
- import { identityPerspective, readCustodyMode } from '../model/custody.js'
3
+ import { Surface } from '../../../../ui/Surface.js'
4
+ import { Select, type SelectOption } from '../../../../ui/Select.js'
5
+ import { theme } from '../../../../ui/theme.js'
6
+ import type { EthagentConfig, EthagentIdentity } from '../../../../storage/config.js'
7
+ import type { ContinuityWorkingTreeStatus } from '../../../continuity/storage.js'
8
+ import { identityPerspective, readCustodyMode } from '../../custody/state.js'
9
9
  import { identityValuesCopyHint } from '../model/copy.js'
10
- import { transferSnapshotView } from '../model/transfer.js'
10
+ import { transferSnapshotView } from '../../transfer/state.js'
11
11
  import { IdentitySummary } from './IdentitySummary.js'
12
12
  import type { AgentReconciliation } from '../reconciliation/index.js'
13
13
  import { menuFlagsFromReconciliation } from './menuFlagsFromReconciliation.js'
@@ -85,7 +85,7 @@ export const MenuScreen: React.FC<MenuScreenProps> = ({
85
85
  ? menuFlagsFromReconciliation(reconciliation, perspective)
86
86
  : (perspective === 'operator'
87
87
  ? menuFlagsFromReconciliation({
88
- token: 'unknown', custody: 'unknown', agentUri: 'unknown', ensRecords: 'unknown',
88
+ token: 'unknown', custody: 'unknown', agentUri: 'unknown',
89
89
  vault: 'unknown', workingTree: 'unknown', rpc: 'reachable', driftCount: 0, lastCheckedAt: '',
90
90
  }, perspective)
91
91
  : null)
@@ -223,7 +223,6 @@ function renderReconciliationBanner(r: AgentReconciliation, identity: EthagentId
223
223
  if (r.custody === 'mid-flow-uri-pending') lines.push('Advanced setup pending. Open Custody Mode to finish.')
224
224
  if (r.agentUri === 'local-newer') lines.push('Local state newer than chain. Save Snapshot Now to publish.')
225
225
  if (r.agentUri === 'chain-newer') lines.push('Onchain agentURI is newer than local. Refetch Latest.')
226
- if (r.ensRecords === 'drift') lines.push('ENS records out of sync. Open Custody Mode to Fix Records.')
227
226
  if (r.vault === 'missing') lines.push('Recorded vault address has no contract at it. Open Custody Mode to redeploy.')
228
227
  if (r.workingTree === 'dirty') lines.push('Local edits pending. Save Snapshot Now to publish.')
229
228
  return (
@@ -1,8 +1,8 @@
1
1
  import React from 'react'
2
- import { Surface } from '../../../ui/Surface.js'
3
- import { Select, type SelectOption } from '../../../ui/Select.js'
4
- import type { SelectableNetwork } from '../../../storage/config.js'
5
- import { SELECTABLE_NETWORKS } from '../../../storage/config.js'
2
+ import { Surface } from '../../../../ui/Surface.js'
3
+ import { Select, type SelectOption } from '../../../../ui/Select.js'
4
+ import type { SelectableNetwork } from '../../../../storage/config.js'
5
+ import { SELECTABLE_NETWORKS } from '../../../../storage/config.js'
6
6
  import { networkLabel, networkSubtitle } from '../model/network.js'
7
7
 
8
8
  type NetworkScreenProps = {
@@ -1,9 +1,9 @@
1
1
  import React from 'react'
2
2
  import { Text } from 'ink'
3
- import { Surface } from '../../../ui/Surface.js'
4
- import { TextInput } from '../../../ui/TextInput.js'
5
- import { theme } from '../../../ui/theme.js'
6
- import { extractPinataJwt } from '../../storage/ipfs.js'
3
+ import { Surface } from '../../../../ui/Surface.js'
4
+ import { TextInput } from '../../../../ui/TextInput.js'
5
+ import { theme } from '../../../../ui/theme.js'
6
+ import { extractPinataJwt } from '../../../storage/ipfs.js'
7
7
 
8
8
  const PINATA_API_KEYS_URL = 'https://app.pinata.cloud/developers/api-keys'
9
9
 
@@ -1,10 +1,10 @@
1
1
  import React from 'react'
2
2
  import { Box, Text } from 'ink'
3
- import { Surface } from '../../../ui/Surface.js'
4
- import { Select } from '../../../ui/Select.js'
5
- import { theme } from '../../../ui/theme.js'
6
- import { transferSnapshotView } from '../model/transfer.js'
7
- import type { EthagentIdentity } from '../../../storage/config.js'
3
+ import { Surface } from '../../../../ui/Surface.js'
4
+ import { Select } from '../../../../ui/Select.js'
5
+ import { theme } from '../../../../ui/theme.js'
6
+ import { transferSnapshotView } from '../../transfer/state.js'
7
+ import type { EthagentIdentity } from '../../../../storage/config.js'
8
8
 
9
9
  type UnlinkedIdentityScreenProps = {
10
10
  identity?: EthagentIdentity
@@ -1,11 +1,11 @@
1
1
  import React from 'react'
2
2
  import { Box, Text } from 'ink'
3
- import { Surface } from '../../../ui/Surface.js'
4
- import { Spinner } from '../../../ui/Spinner.js'
5
- import { theme } from '../../../ui/theme.js'
6
- import { useAppInput } from '../../../app/input/AppInputProvider.js'
7
- import { openExternalUrl } from '../../../utils/openExternal.js'
8
- import type { BrowserWalletReady } from '../../wallet/browserWallet.js'
3
+ import { Surface } from '../../../../ui/Surface.js'
4
+ import { Spinner } from '../../../../ui/Spinner.js'
5
+ import { theme } from '../../../../ui/theme.js'
6
+ import { useAppInput } from '../../../../app/input/AppInputProvider.js'
7
+ import { openExternalUrl } from '../../../../utils/openExternal.js'
8
+ import type { BrowserWalletReady } from '../../../wallet/browserWallet.js'
9
9
 
10
10
  type WalletApprovalScreenProps = {
11
11
  title: string
@@ -1,5 +1,5 @@
1
1
  import type { AgentReconciliation } from '../reconciliation/index.js'
2
- import type { IdentityPerspective } from '../model/custody.js'
2
+ import type { IdentityPerspective } from '../../custody/state.js'
3
3
 
4
4
  type MenuFlags = {
5
5
  prepareTransferDisabled: boolean
@@ -30,7 +30,7 @@ export function menuFlagsFromReconciliation(r: AgentReconciliation, perspective:
30
30
  prepareTransferReason = 'Token is in the vault. Withdraw it first in Custody Mode.'
31
31
  }
32
32
 
33
- const custodyAsterisk = r.custody === 'mid-flow-uri-pending' || r.ensRecords === 'drift' || r.vault === 'missing'
33
+ const custodyAsterisk = r.custody === 'mid-flow-uri-pending' || r.vault === 'missing'
34
34
  let custodyHint: string | undefined
35
35
  if (isOperator) {
36
36
  custodyHint = undefined
@@ -38,8 +38,6 @@ export function menuFlagsFromReconciliation(r: AgentReconciliation, perspective:
38
38
  custodyHint = 'Advanced setup pending. Open to finish.'
39
39
  } else if (r.vault === 'missing') {
40
40
  custodyHint = 'Vault contract not found. Open to redeploy.'
41
- } else if (r.ensRecords === 'drift') {
42
- custodyHint = 'ENS records out of sync. Open to fix.'
43
41
  }
44
42
 
45
43
  const custodyModeReason = isOperator
@@ -11,7 +11,7 @@ import {
11
11
  applyEnsValidationState,
12
12
  applyOperatorProfileState,
13
13
  validateEnsForProfileUpdate,
14
- } from '../profile/profileState.js'
14
+ } from '../../profile/state.js'
15
15
 
16
16
  type PreparedProfileState = {
17
17
  state: Record<string, unknown>
@@ -1,6 +1,6 @@
1
1
  import type { Hex, PublicClient } from 'viem'
2
- import type { PendingTxKind } from '../../../storage/config.js'
3
- import { clearPendingTx, recordPendingTx } from '../../../storage/config.js'
2
+ import type { PendingTxKind } from '../../../../storage/config.js'
3
+ import { clearPendingTx, recordPendingTx } from '../../../../storage/config.js'
4
4
 
5
5
  export async function awaitConfirmedReceipt(
6
6
  client: Pick<PublicClient, 'waitForTransactionReceipt'>,
@@ -9,23 +9,17 @@ import {
9
9
  encodeSetMetadataOperator,
10
10
  readMetadataOperators,
11
11
  } from '../../../registry/vault.js'
12
- import {
13
- sendBrowserWalletTransaction,
14
- type WalletPurpose,
15
- } from '../../../wallet/browserWallet.js'
12
+ import { sendBrowserWalletTransaction } from '../../../wallet/browserWallet.js'
16
13
  import {
17
14
  computeApprovalDiff,
18
- encodeResolverApprovalChanges,
19
- verifyResolverApprovalsLanded,
20
15
  type ApprovalDiff,
21
- } from '../../reconciliation/index.js'
22
- import { normalizeApprovedOperatorWallets } from '../../operatorWallets.js'
16
+ } from '../reconciliation/index.js'
17
+ import { normalizeApprovedOperatorWallets } from '../operatorWallets.js'
23
18
  import { readOwnerAddressField } from '../../../identityCompat.js'
24
19
  import { localContinuitySnapshotContentHashes } from '../../../continuity/storage.js'
25
20
  import { updatePublishedContinuitySnapshotContentHashes } from '../../../continuity/snapshots.js'
26
- import type { EffectCallbacks } from '../types.js'
27
- import { awaitConfirmedReceipt, awaitOptionalReceipt } from '../receipts.js'
28
- import { createMainnetEnsPublicClient } from '../ens/transactions.js'
21
+ import type { EffectCallbacks } from './types.js'
22
+ import { awaitConfirmedReceipt } from './receipts.js'
29
23
 
30
24
  export function resolverSyncWarningMessage(err: unknown): string {
31
25
  return err instanceof Error ? err.message : String(err)
@@ -36,7 +30,7 @@ export function appendResolverSyncWarning(message: string, warning: string | nul
36
30
  return `${message}\n\nWarning: ${warning}`
37
31
  }
38
32
 
39
- export async function syncResolverApprovalsAfterOwnerSave(args: {
33
+ export async function syncVaultOperatorsAfterOwnerSave(args: {
40
34
  beforeIdentity: EthagentIdentity
41
35
  afterIdentity: EthagentIdentity
42
36
  registry: Erc8004RegistryConfig
@@ -45,7 +39,6 @@ export async function syncResolverApprovalsAfterOwnerSave(args: {
45
39
  }): Promise<void> {
46
40
  const beforeState = (args.beforeIdentity.state ?? {}) as Record<string, unknown>
47
41
  const afterState = (args.afterIdentity.state ?? {}) as Record<string, unknown>
48
- const ensName = typeof afterState.ensName === 'string' ? afterState.ensName.trim() : ''
49
42
  const before = normalizeApprovedOperatorWallets(beforeState.approvedOperatorWallets)
50
43
  const after = normalizeApprovedOperatorWallets(afterState.approvedOperatorWallets)
51
44
  const diff = computeApprovalDiff(before, after)
@@ -54,40 +47,6 @@ export async function syncResolverApprovalsAfterOwnerSave(args: {
54
47
  const ownerAddressRaw = readOwnerAddressField(afterState) ?? args.afterIdentity.ownerAddress ?? args.afterIdentity.address
55
48
  const ownerAddress = getAddress(ownerAddressRaw)
56
49
 
57
- if (ensName) {
58
- let encoded
59
- try {
60
- encoded = await encodeResolverApprovalChanges({ ensName, diff })
61
- } catch {
62
- encoded = null
63
- }
64
- if (encoded) {
65
- const purpose: WalletPurpose = diff.removed.length > 0 && diff.added.length === 0
66
- ? 'revoke-operator-wallet-resolver'
67
- : 'authorize-operator-wallet-resolver'
68
-
69
- const tx = await sendBrowserWalletTransaction({
70
- chainId: 1,
71
- expectedAccount: ownerAddress,
72
- to: encoded.resolverAddress,
73
- data: encoded.data,
74
- onReady: args.callbacks.onWalletReady,
75
- purpose,
76
- })
77
- args.callbacks.onWalletReady(null)
78
- const client = createMainnetEnsPublicClient()
79
- await awaitOptionalReceipt(client, tx.txHash, 'Resolver delegation sync')
80
- await verifyResolverApprovalsLanded({
81
- ensName,
82
- ownerAddress: ownerAddress,
83
- resolverAddress: encoded.resolverAddress,
84
- added: encoded.added,
85
- removed: encoded.removed,
86
- client,
87
- })
88
- }
89
- }
90
-
91
50
  await syncVaultMetadataOperatorsAfterOwnerSave({
92
51
  afterIdentity: args.afterIdentity,
93
52
  registry: args.registry,
@@ -1,7 +1,7 @@
1
1
  import type { Address } from 'viem'
2
- import type { EthagentIdentity } from '../../../storage/config.js'
3
- import type { BrowserWalletReady } from '../../wallet/browserWallet.js'
4
- import type { Step } from '../identityHubReducer.js'
2
+ import type { EthagentIdentity } from '../../../../storage/config.js'
3
+ import type { BrowserWalletReady } from '../../../wallet/browserWallet.js'
4
+ import type { Step } from '../../identityHubReducer.js'
5
5
 
6
6
  export type IdentityCompletionSource = 'create' | 'restore' | 'update'
7
7
 
@@ -1,5 +1,5 @@
1
- import type { EthagentConfig, EthagentIdentity } from '../../../storage/config.js'
2
- import { readCustodyMode, readIdentityStateString } from './custody.js'
1
+ import type { EthagentConfig, EthagentIdentity } from '../../../../storage/config.js'
2
+ import { readCustodyMode, readIdentityStateString } from '../../custody/state.js'
3
3
 
4
4
  type CopyableField = {
5
5
  label: string
@@ -1,15 +1,15 @@
1
1
  import { ZodError } from 'zod'
2
- import { RegisterAgentPreflightError } from '../../registry/erc8004.js'
3
- import { AgentStateOwnerMismatchError } from '../../crypto/backupEnvelope.js'
2
+ import { RegisterAgentPreflightError } from '../../../registry/erc8004.js'
3
+ import { AgentStateOwnerMismatchError } from '../../../crypto/backupEnvelope.js'
4
4
  import {
5
5
  ContinuitySnapshotOwnerMismatchError,
6
6
  ContinuityTransferSnapshotTargetMismatchError,
7
- } from '../../continuity/envelope.js'
7
+ } from '../../../continuity/envelope.js'
8
8
  import {
9
9
  VaultBytecodeMismatchError,
10
10
  formatVaultBytecodeMismatchDetail,
11
- } from '../../registry/vault.js'
12
- import { BrowserWalletError } from '../../wallet/browserWallet.js'
11
+ } from '../../../registry/vault.js'
12
+ import { BrowserWalletError } from '../../../wallet/browserWallet.js'
13
13
  import { TxGuardBusyError } from '../txGuard.js'
14
14
  import { shortAddress } from './format.js'
15
15
 
@@ -1,6 +1,6 @@
1
- import type { EthagentConfig, EthagentIdentity, SelectableNetwork } from '../../../storage/config.js'
2
- import { supportedErc8004ChainForId } from '../../registry/erc8004.js'
3
- import { resolveSelectedNetwork } from '../../registry/registryConfig.js'
1
+ import type { EthagentConfig, EthagentIdentity, SelectableNetwork } from '../../../../storage/config.js'
2
+ import { supportedErc8004ChainForId } from '../../../registry/erc8004.js'
3
+ import { resolveSelectedNetwork } from '../../../registry/registryConfig.js'
4
4
 
5
5
  const NETWORK_LABELS: Record<SelectableNetwork, string> = {
6
6
  mainnet: 'ethereum mainnet',
@@ -1,5 +1,5 @@
1
1
  import { getAddress, isAddress, type Address } from 'viem'
2
- import type { WalletContinuityRestoreAccessKey } from '../continuity/envelope.js'
2
+ import type { WalletContinuityRestoreAccessKey } from '../../continuity/envelope.js'
3
3
 
4
4
  export type ApprovedOperatorWalletRecord = {
5
5
  address: Address
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useState } from 'react'
2
- import type { EthagentConfig } from '../../../../storage/config.js'
2
+ import type { EthagentConfig } from '../../../../../storage/config.js'
3
3
  import { emptyReconciliation, runReconciliation } from './run.js'
4
4
  import type { AgentReconciliation } from './types.js'
5
5
 
@@ -10,7 +10,6 @@ export function useAgentReconciliation(
10
10
  token: 'no-agent',
11
11
  custody: 'unknown',
12
12
  agentUri: 'unknown',
13
- ensRecords: 'unset',
14
13
  vault: 'unset',
15
14
  workingTree: 'unknown',
16
15
  rpc: 'reachable',
@@ -3,8 +3,8 @@ import {
3
3
  createErc8004PublicClient,
4
4
  validateErc8004TokenOwner,
5
5
  type Erc8004RegistryConfig,
6
- } from '../../../registry/erc8004.js'
7
- import type { EthagentIdentity } from '../../../../storage/config.js'
6
+ } from '../../../../registry/erc8004.js'
7
+ import type { EthagentIdentity } from '../../../../../storage/config.js'
8
8
 
9
9
  export type OwnershipRole = 'token-holder' | 'vault-level-owner'
10
10