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.
- package/.claude-plugin/marketplace.json +11 -0
- package/.claude-plugin/plugin.json +35 -0
- package/LICENSE +1 -1
- package/README.md +64 -104
- package/commands/ethagent.md +40 -0
- package/package.json +16 -16
- package/src/app/keybindings/KeybindingProvider.tsx +1 -6
- package/src/app/keybindings/types.ts +1 -6
- package/src/cli/ResetConfirmView.tsx +54 -53
- package/src/cli/demo.ts +86 -0
- package/src/cli/hookIo.ts +45 -0
- package/src/cli/main.tsx +94 -123
- package/src/cli/memoryGuard.ts +49 -0
- package/src/cli/reset.ts +28 -70
- package/src/cli/sessionStart.ts +33 -0
- package/src/cli/status.ts +46 -0
- package/src/cli/sync.ts +167 -0
- package/src/cli/syncAdapters/claude-code.ts +86 -0
- package/src/cli/syncAdapters/codex.ts +66 -0
- package/src/cli/syncAdapters/index.ts +45 -0
- package/src/cli/syncAdapters/managedBlock.ts +175 -0
- package/src/cli/syncAdapters/shared.ts +63 -0
- package/src/identity/continuity/envelopeParse.ts +20 -1
- package/src/identity/continuity/publicSkills.ts +3 -1
- package/src/identity/continuity/skills/publicSkillsSync.ts +2 -1
- package/src/identity/continuity/skills/scaffold.ts +5 -2
- package/src/identity/continuity/snapshots.ts +12 -5
- package/src/identity/continuity/storage/defaults.ts +20 -19
- package/src/identity/continuity/storage/status.ts +1 -1
- package/src/identity/ens/ensLookup/constants.ts +1 -1
- package/src/identity/manager/IdentityManager.tsx +33 -0
- package/src/identity/{hub → manager}/OperationalRoutes.tsx +37 -18
- package/src/identity/{hub → manager}/Routes.tsx +48 -34
- package/src/identity/{hub → manager}/continuity/ContinuityDashboardScreen.tsx +9 -19
- package/src/identity/{hub → manager}/continuity/RebackupStorageScreen.tsx +3 -3
- package/src/identity/manager/continuity/RecoveryConfirmScreen.tsx +102 -0
- package/src/identity/{hub → manager}/continuity/SavePromptScreen.tsx +2 -3
- package/src/identity/{hub → manager}/continuity/completion.ts +1 -1
- package/src/identity/{hub → manager}/continuity/effects.ts +1 -1
- package/src/identity/{hub → manager}/continuity/skills/DeleteSkillConfirmScreen.tsx +2 -2
- package/src/identity/{hub → manager}/continuity/skills/NewSkillScreen.tsx +0 -5
- package/src/identity/{hub → manager}/continuity/skills/NewSkillVisibilityScreen.tsx +4 -4
- package/src/identity/{hub → manager}/continuity/skills/SkillActionsScreen.tsx +6 -22
- package/src/identity/{hub → manager}/continuity/skills/SkillsTreeScreen.tsx +5 -17
- package/src/identity/{hub → manager}/continuity/snapshot.ts +1 -1
- package/src/identity/{hub → manager}/continuity/vault.ts +1 -1
- package/src/identity/{hub → manager}/create/CreateFlow.tsx +59 -32
- package/src/identity/{hub → manager}/create/effects.ts +19 -10
- package/src/identity/manager/create/importScan.ts +122 -0
- package/src/identity/{hub → manager}/custody/CustodyEditFlow.tsx +17 -61
- package/src/identity/{hub → manager}/custody/actions.ts +1 -15
- package/src/identity/{hub → manager}/custody/routes.tsx +20 -40
- package/src/identity/{hub → manager}/custody/transactions.ts +1 -0
- package/src/identity/{hub → manager}/custody/types.ts +1 -2
- package/src/identity/{hub → manager}/custody/useCustodyEffects.ts +1 -1
- package/src/identity/{hub → manager}/ens/EnsEditAdvancedScreens.tsx +2 -2
- package/src/identity/{hub → manager}/ens/EnsEditMaintenanceScreens.tsx +12 -23
- package/src/identity/{hub → manager}/ens/EnsEditReviewScreens.tsx +18 -42
- package/src/identity/{hub → manager}/ens/EnsEditRunners.tsx +1 -1
- package/src/identity/{hub → manager}/ens/EnsEditShared.tsx +0 -2
- package/src/identity/{hub → manager}/ens/EnsEditSimpleScreens.tsx +10 -19
- package/src/identity/{hub → manager}/ens/EnsFlow.tsx +133 -41
- package/src/identity/{hub → manager}/ens/EnsOperatorWalletsScreen.tsx +14 -19
- package/src/identity/{hub → manager}/ens/editCopy.ts +1 -14
- package/src/identity/{hub → manager}/profile/EditProfileFlow.tsx +99 -66
- package/src/identity/{hub → manager}/profile/effects.ts +1 -3
- package/src/identity/{hub → manager}/profile/operatorSave.ts +1 -1
- package/src/identity/{hub → manager}/profile/state.ts +1 -1
- package/src/identity/{hub/identityHubReducer.ts → manager/reducer.ts} +25 -26
- package/src/identity/{hub → manager}/restore/RestoreFlow.tsx +16 -24
- package/src/identity/{hub → manager}/restore/apply.ts +1 -1
- package/src/identity/{hub → manager}/restore/auth.ts +1 -1
- package/src/identity/{hub → manager}/restore/discover.ts +1 -1
- package/src/identity/{hub → manager}/restore/fetch.ts +1 -1
- package/src/identity/{hub → manager}/restore/restoreAdmin.ts +1 -1
- package/src/identity/{hub → manager}/restore/useRestoreEffects.ts +2 -9
- package/src/identity/{hub → manager}/settings/StorageCredentialScreen.tsx +10 -25
- package/src/identity/{hub → manager}/shared/components/DetailsScreen.tsx +5 -7
- package/src/identity/{hub → manager}/shared/components/ErrorScreen.tsx +6 -10
- package/src/identity/{hub → manager}/shared/components/FlowTimeline.tsx +4 -3
- package/src/identity/{hub → manager}/shared/components/IdentitySummary.tsx +19 -59
- package/src/identity/manager/shared/components/LazyMenu.tsx +147 -0
- package/src/identity/manager/shared/components/MenuScreen.tsx +220 -0
- package/src/identity/manager/shared/components/OperationCompleteScreen.tsx +28 -0
- package/src/identity/{hub → manager}/shared/components/UnlinkedIdentityScreen.tsx +9 -10
- package/src/identity/{hub → manager}/shared/components/WalletApprovalScreen.tsx +1 -2
- package/src/identity/manager/shared/components/Wordmark.tsx +54 -0
- package/src/identity/{hub → manager}/shared/components/menuFlagsFromReconciliation.ts +39 -15
- package/src/identity/{hub → manager}/shared/effects/profilePrep.ts +1 -1
- package/src/identity/manager/shared/effects/types.ts +30 -0
- package/src/identity/{hub → manager}/shared/model/copy.ts +0 -4
- package/src/identity/{hub → manager}/shared/model/errors.ts +32 -3
- package/src/identity/{hub → manager}/shared/model/network.ts +2 -2
- package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/hook.ts +5 -0
- package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/run.ts +1 -1
- package/src/identity/{hub/shared/reconciliation/useAgentReconciliation.ts → manager/shared/reconciliation/index.ts} +6 -0
- package/src/identity/{hub → manager}/shared/utils.ts +6 -10
- package/src/identity/{hub → manager}/transfer/TokenTransferFlow.tsx +3 -3
- package/src/identity/{hub → manager}/transfer/TokenTransferScreens.tsx +4 -10
- package/src/identity/{hub → manager}/transfer/effects.ts +1 -1
- package/src/identity/{hub → manager}/types.ts +5 -6
- package/src/identity/{hub/useIdentityHubContinuity.ts → manager/useContinuity.ts} +59 -27
- package/src/identity/{hub/useIdentityHubController.ts → manager/useController.ts} +38 -35
- package/src/identity/{hub/useIdentityHubSideEffects.ts → manager/useSideEffects.ts} +40 -4
- package/src/identity/registry/erc8004/discovery.ts +3 -17
- package/src/identity/registry/erc8004/utils.ts +1 -1
- package/src/identity/storage/ipfs.ts +21 -1
- package/src/identity/wallet/browserWallet/html.ts +10 -2
- package/src/identity/wallet/browserWallet/http.ts +18 -0
- package/src/identity/wallet/browserWallet/requestServer.ts +5 -1
- package/src/identity/wallet/browserWallet/requests.ts +10 -28
- package/src/identity/wallet/browserWallet/session.ts +26 -33
- package/src/identity/wallet/browserWallet/validation.ts +14 -0
- package/src/identity/wallet/browserWallet/walletPageSource.ts +22 -40
- package/src/identity/wallet/page/boot.ts +43 -0
- package/src/identity/wallet/page/config.ts +59 -0
- package/src/identity/wallet/page/constants.ts +12 -0
- package/src/identity/wallet/page/copy.ts +47 -68
- package/src/identity/wallet/page/css.ts +638 -0
- package/src/identity/wallet/page/{errorView.ts → errors.ts} +5 -14
- package/src/identity/wallet/page/{controller.ts → flow.ts} +4 -71
- package/src/identity/wallet/page/markup.ts +44 -34
- package/src/identity/wallet/page/{walletProvider.ts → provider.ts} +0 -3
- package/src/identity/wallet/page/resize.ts +95 -0
- package/src/identity/wallet/page/state.ts +135 -8
- package/src/identity/wallet/page/timeline.ts +161 -0
- package/src/identity/wallet/page/view.ts +22 -302
- package/src/storage/config.ts +30 -80
- package/src/storage/reset.ts +31 -0
- package/src/storage/secrets.ts +1 -16
- package/src/ui/Select.tsx +27 -5
- package/src/ui/Spinner.tsx +16 -15
- package/src/ui/Surface.tsx +21 -17
- package/src/ui/TextArea.tsx +173 -0
- package/src/ui/TextInput.tsx +31 -133
- package/src/ui/theme.ts +22 -13
- package/src/utils/clipboard.ts +0 -140
- package/src/app/FirstRun.tsx +0 -577
- package/src/app/FirstRunTimeline.tsx +0 -51
- package/src/app/firstRunConfig.ts +0 -26
- package/src/app/hooks/useCancelRequest.ts +0 -22
- package/src/app/hooks/useDoublePress.ts +0 -46
- package/src/app/hooks/useExitOnCtrlC.ts +0 -36
- package/src/auth/openaiOAuth/credentials.ts +0 -47
- package/src/auth/openaiOAuth/crypto.ts +0 -23
- package/src/auth/openaiOAuth/index.ts +0 -238
- package/src/auth/openaiOAuth/landingPage.ts +0 -116
- package/src/auth/openaiOAuth/listener.ts +0 -151
- package/src/auth/openaiOAuth/refresh.ts +0 -70
- package/src/auth/openaiOAuth/shared.ts +0 -115
- package/src/chat/ChatBottomPane.tsx +0 -296
- package/src/chat/ChatScreen.tsx +0 -1685
- package/src/chat/ConversationStack.tsx +0 -56
- package/src/chat/MessageList.tsx +0 -638
- package/src/chat/SessionStatus.tsx +0 -53
- package/src/chat/chatEnvironment.ts +0 -16
- package/src/chat/chatScreenUtils.ts +0 -194
- package/src/chat/chatSessionState.ts +0 -146
- package/src/chat/chatTurnContext.ts +0 -50
- package/src/chat/chatTurnOrchestrator.ts +0 -603
- package/src/chat/chatTurnRows.ts +0 -64
- package/src/chat/commands.ts +0 -494
- package/src/chat/continuityEditReview.ts +0 -42
- package/src/chat/display/DiffView.tsx +0 -193
- package/src/chat/display/SyntaxText.tsx +0 -192
- package/src/chat/display/toolCallDisplay.ts +0 -103
- package/src/chat/display/toolResultDisplay.ts +0 -19
- package/src/chat/input/ChatInput.tsx +0 -625
- package/src/chat/input/chatInputHelpers.ts +0 -62
- package/src/chat/input/chatInputState.ts +0 -247
- package/src/chat/input/chatPaste.ts +0 -49
- package/src/chat/input/imageRefs.ts +0 -30
- package/src/chat/input/inputRendering.tsx +0 -93
- package/src/chat/input/textCursor.ts +0 -212
- package/src/chat/messageMarkdown.ts +0 -220
- package/src/chat/messageRows.ts +0 -43
- package/src/chat/planImplementation.ts +0 -62
- package/src/chat/slashCommandHandlers.ts +0 -122
- package/src/chat/slashCommandViews.ts +0 -120
- package/src/chat/transcript/TranscriptView.tsx +0 -184
- package/src/chat/transcript/transcriptViewport.ts +0 -295
- package/src/chat/views/ContextLimitView.tsx +0 -95
- package/src/chat/views/ContinuityEditReviewView.tsx +0 -50
- package/src/chat/views/CopyPicker.tsx +0 -50
- package/src/chat/views/PermissionPrompt.tsx +0 -156
- package/src/chat/views/PermissionsView.tsx +0 -165
- package/src/chat/views/PlanApprovalView.tsx +0 -91
- package/src/chat/views/ResumeView.tsx +0 -273
- package/src/chat/views/RewindView.tsx +0 -412
- package/src/cli/preview.tsx +0 -14
- package/src/cli/updateNotice.ts +0 -54
- package/src/identity/continuity/privateEdit/apply.ts +0 -170
- package/src/identity/continuity/privateEdit/diff.ts +0 -6
- package/src/identity/continuity/privateEdit/files.ts +0 -23
- package/src/identity/continuity/privateEdit/types.ts +0 -28
- package/src/identity/continuity/privateEdit.ts +0 -46
- package/src/identity/hub/IdentityHub.tsx +0 -14
- package/src/identity/hub/continuity/RecoveryConfirmScreen.tsx +0 -104
- package/src/identity/hub/ens/effects.ts +0 -218
- package/src/identity/hub/shared/components/MenuScreen.tsx +0 -241
- package/src/identity/hub/shared/effects/types.ts +0 -53
- package/src/identity/hub/shared/reconciliation/index.ts +0 -14
- package/src/identity/wallet/page/grainient.ts +0 -278
- package/src/identity/wallet/page/html.ts +0 -28
- package/src/identity/wallet/page/styles/base.ts +0 -259
- package/src/identity/wallet/page/styles/components.ts +0 -262
- package/src/identity/wallet/page/styles/index.ts +0 -5
- package/src/identity/wallet/page/styles/responsive.ts +0 -247
- package/src/identity/wallet/page.tsx +0 -38
- package/src/mcp/approvals.ts +0 -113
- package/src/mcp/config.ts +0 -235
- package/src/mcp/manager.ts +0 -482
- package/src/mcp/managerHelpers.ts +0 -70
- package/src/mcp/names.ts +0 -19
- package/src/mcp/output.ts +0 -96
- package/src/models/ModelPicker.tsx +0 -1009
- package/src/models/catalog.ts +0 -327
- package/src/models/huggingface.ts +0 -712
- package/src/models/huggingfaceStorage.ts +0 -136
- package/src/models/llamacpp.ts +0 -848
- package/src/models/llamacppCommands.ts +0 -44
- package/src/models/llamacppConfig.ts +0 -34
- package/src/models/llamacppDiscovery.ts +0 -176
- package/src/models/llamacppOutput.ts +0 -65
- package/src/models/llamacppPreflight.ts +0 -158
- package/src/models/modelDisplay.ts +0 -180
- package/src/models/modelPickerCatalogFlow.ts +0 -56
- package/src/models/modelPickerCredentials.ts +0 -166
- package/src/models/modelPickerData.ts +0 -41
- package/src/models/modelPickerDisplay.tsx +0 -132
- package/src/models/modelPickerHfFlow.ts +0 -192
- package/src/models/modelPickerLocalRunnerFlow.ts +0 -115
- package/src/models/modelPickerOptions.ts +0 -457
- package/src/models/modelPickerTypes.ts +0 -69
- package/src/models/modelPickerUninstallFlow.ts +0 -48
- package/src/models/modelPickerViewHelpers.ts +0 -174
- package/src/models/modelRecommendation.ts +0 -139
- package/src/models/providerDisplay.ts +0 -16
- package/src/models/runtimeDetection.ts +0 -81
- package/src/models/uncensoredCatalog.ts +0 -86
- package/src/providers/anthropic.ts +0 -290
- package/src/providers/contracts.ts +0 -71
- package/src/providers/errors.ts +0 -80
- package/src/providers/gemini.ts +0 -391
- package/src/providers/openai-chat.ts +0 -474
- package/src/providers/openai-responses-format.ts +0 -177
- package/src/providers/openai-responses.ts +0 -306
- package/src/providers/openaiChatWire.ts +0 -124
- package/src/providers/registry.ts +0 -120
- package/src/providers/retry.ts +0 -58
- package/src/providers/sse.ts +0 -93
- package/src/runtime/compaction.ts +0 -395
- package/src/runtime/cwd.ts +0 -43
- package/src/runtime/providerTurn.ts +0 -38
- package/src/runtime/sessionMode.ts +0 -55
- package/src/runtime/systemPrompt.ts +0 -213
- package/src/runtime/textToolParser.ts +0 -161
- package/src/runtime/toolClaimGuards.ts +0 -143
- package/src/runtime/toolExecution.ts +0 -304
- package/src/runtime/toolIntent.ts +0 -143
- package/src/runtime/turn.ts +0 -369
- package/src/runtime/turnNudges.ts +0 -223
- package/src/runtime/turnTypes.ts +0 -86
- package/src/storage/factoryReset.ts +0 -127
- package/src/storage/history.ts +0 -58
- package/src/storage/permissions.ts +0 -76
- package/src/storage/rewind.ts +0 -266
- package/src/storage/sessionExport.ts +0 -49
- package/src/storage/sessions.ts +0 -495
- package/src/tools/bashSafety.ts +0 -186
- package/src/tools/bashTool.ts +0 -140
- package/src/tools/changeDirectoryTool.ts +0 -213
- package/src/tools/contracts.ts +0 -192
- package/src/tools/deleteFileTool.ts +0 -116
- package/src/tools/editTool.ts +0 -165
- package/src/tools/editUtils.ts +0 -170
- package/src/tools/fileDiff.ts +0 -261
- package/src/tools/listDirectoryTool.ts +0 -55
- package/src/tools/listSkillFilesTool.ts +0 -77
- package/src/tools/listSkillsTool.ts +0 -68
- package/src/tools/mcpResourceTools.ts +0 -95
- package/src/tools/permissionRules.ts +0 -85
- package/src/tools/privateContinuityEditTool.ts +0 -187
- package/src/tools/privateContinuityReadTool.ts +0 -106
- package/src/tools/readSkillTool.ts +0 -107
- package/src/tools/readTool.ts +0 -85
- package/src/tools/registry.ts +0 -103
- package/src/tools/writeFileTool.ts +0 -167
- package/src/ui/BrandSplash.tsx +0 -133
- package/src/ui/terminalTitle.ts +0 -30
- package/src/utils/images.ts +0 -140
- package/src/utils/markdownSegments.ts +0 -51
- package/src/utils/messages.ts +0 -37
- package/src/utils/withRetry.ts +0 -324
- /package/src/identity/{hub → manager}/continuity/state.ts +0 -0
- /package/src/identity/{hub → manager}/custody/helpers.ts +0 -0
- /package/src/identity/{hub → manager}/custody/preflight.ts +0 -0
- /package/src/identity/{hub → manager}/custody/state.ts +0 -0
- /package/src/identity/{hub → manager}/custody/useCustodyFlow.tsx +0 -0
- /package/src/identity/{hub → manager}/ens/EnsEditFlow.tsx +0 -0
- /package/src/identity/{hub → manager}/ens/advancedEnsValidation.ts +0 -0
- /package/src/identity/{hub → manager}/ens/state.ts +0 -0
- /package/src/identity/{hub → manager}/ens/transactions.ts +0 -0
- /package/src/identity/{hub → manager}/ens/types.ts +0 -0
- /package/src/identity/{hub → manager}/profile/identity.ts +0 -0
- /package/src/identity/{hub → manager}/restore/envelopes.ts +0 -0
- /package/src/identity/{hub → manager}/restore/helpers.ts +0 -0
- /package/src/identity/{hub → manager}/restore/recovery.ts +0 -0
- /package/src/identity/{hub → manager}/restore/resolve.ts +0 -0
- /package/src/identity/{hub → manager}/shared/components/BusyScreen.tsx +0 -0
- /package/src/identity/{hub → manager}/shared/components/NetworkScreen.tsx +0 -0
- /package/src/identity/{hub → manager}/shared/components/PinataJwtInput.tsx +0 -0
- /package/src/identity/{hub → manager}/shared/effects/receipts.ts +0 -0
- /package/src/identity/{hub → manager}/shared/effects/sync.ts +0 -0
- /package/src/identity/{hub → manager}/shared/model/format.ts +0 -0
- /package/src/identity/{hub → manager}/shared/operatorWallets.ts +0 -0
- /package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/ownership.ts +0 -0
- /package/src/identity/{hub → manager}/shared/reconciliation/agentReconciliation/types.ts +0 -0
- /package/src/identity/{hub → manager}/shared/reconciliation/walletSetup.ts +0 -0
- /package/src/identity/{hub → manager}/shared/txGuard.ts +0 -0
- /package/src/identity/{hub → manager}/transfer/progress.ts +0 -0
- /package/src/identity/{hub → manager}/transfer/state.ts +0 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Box, Text } from 'ink'
|
|
3
|
+
import { theme } from '../../../../ui/theme.js'
|
|
4
|
+
import { isDemoMode } from '../../../../cli/demo.js'
|
|
5
|
+
import type { EthagentConfig, EthagentIdentity } from '../../../../storage/config.js'
|
|
6
|
+
import { identityPerspective } from '../../custody/state.js'
|
|
7
|
+
import { transferSnapshotView } from '../../transfer/state.js'
|
|
8
|
+
import type { AgentReconciliation } from '../reconciliation/index.js'
|
|
9
|
+
import { menuFlagsFromReconciliation } from './menuFlagsFromReconciliation.js'
|
|
10
|
+
import { localChangeStatusView } from '../../continuity/state.js'
|
|
11
|
+
import { LazyMenu, type LazyMenuRow } from './LazyMenu.js'
|
|
12
|
+
|
|
13
|
+
import type { ContinuityWorkingTreeStatus } from '../../../continuity/storage.js'
|
|
14
|
+
|
|
15
|
+
type MenuScreenProps = {
|
|
16
|
+
config?: EthagentConfig
|
|
17
|
+
identity?: EthagentIdentity
|
|
18
|
+
canRebackup: boolean
|
|
19
|
+
reconciliation?: AgentReconciliation
|
|
20
|
+
workingStatus?: ContinuityWorkingTreeStatus | null
|
|
21
|
+
onCreate: () => void
|
|
22
|
+
onLoad: () => void
|
|
23
|
+
onBackupNow: () => void
|
|
24
|
+
onRefetchLatest: () => void
|
|
25
|
+
onPublicProfile: () => void
|
|
26
|
+
onEnsName: () => void
|
|
27
|
+
onWalletSetup: () => void
|
|
28
|
+
onContinuity: () => void
|
|
29
|
+
onSkillsTree: () => void
|
|
30
|
+
onIdentityValues: () => void
|
|
31
|
+
onPrepareTransfer: () => void
|
|
32
|
+
onStorage: () => void
|
|
33
|
+
onCancel: () => void
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type Action =
|
|
37
|
+
| 'public-profile'
|
|
38
|
+
| 'ens-name'
|
|
39
|
+
| 'wallet-setup'
|
|
40
|
+
| 'continuity'
|
|
41
|
+
| 'skills-tree'
|
|
42
|
+
| 'backup'
|
|
43
|
+
| 'refetch'
|
|
44
|
+
| 'identity-values'
|
|
45
|
+
| 'prepare-transfer'
|
|
46
|
+
| 'storage'
|
|
47
|
+
| 'create'
|
|
48
|
+
| 'load'
|
|
49
|
+
| 'cancel'
|
|
50
|
+
|
|
51
|
+
function shortAddress(addr: string | undefined): string {
|
|
52
|
+
if (!addr) return ''
|
|
53
|
+
return addr.slice(0, 6) + '…' + addr.slice(-4)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function networkLabel(config?: EthagentConfig, identity?: EthagentIdentity): string | null {
|
|
57
|
+
const chainId = identity?.chainId ?? config?.erc8004?.chainId
|
|
58
|
+
if (chainId === 1) return 'mainnet'
|
|
59
|
+
if (chainId === 8453) return 'base'
|
|
60
|
+
return config?.selectedNetwork ?? null
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const MenuScreen: React.FC<MenuScreenProps> = ({
|
|
64
|
+
config,
|
|
65
|
+
identity,
|
|
66
|
+
reconciliation,
|
|
67
|
+
workingStatus,
|
|
68
|
+
canRebackup,
|
|
69
|
+
onCreate,
|
|
70
|
+
onLoad,
|
|
71
|
+
onBackupNow,
|
|
72
|
+
onRefetchLatest,
|
|
73
|
+
onPublicProfile,
|
|
74
|
+
onEnsName,
|
|
75
|
+
onWalletSetup,
|
|
76
|
+
onContinuity,
|
|
77
|
+
onSkillsTree,
|
|
78
|
+
onIdentityValues,
|
|
79
|
+
onPrepareTransfer,
|
|
80
|
+
onStorage,
|
|
81
|
+
onCancel,
|
|
82
|
+
}) => {
|
|
83
|
+
const canRefetch = Boolean(canRebackup && identity?.backup?.cid)
|
|
84
|
+
|
|
85
|
+
const perspective = identityPerspective(identity)
|
|
86
|
+
const flags = reconciliation
|
|
87
|
+
? menuFlagsFromReconciliation(reconciliation, perspective)
|
|
88
|
+
: (perspective === 'operator'
|
|
89
|
+
? menuFlagsFromReconciliation({
|
|
90
|
+
token: 'unknown', custody: 'unknown', agentUri: 'unknown',
|
|
91
|
+
vault: 'unknown', workingTree: 'unknown', rpc: 'reachable', driftCount: 0, lastCheckedAt: '',
|
|
92
|
+
}, perspective)
|
|
93
|
+
: null)
|
|
94
|
+
|
|
95
|
+
const backupEnabled = canRebackup && !(flags?.saveSnapshotDisabled ?? false)
|
|
96
|
+
const localChangeStatus = localChangeStatusView(workingStatus)
|
|
97
|
+
|
|
98
|
+
const rows: Array<LazyMenuRow<Action>> = identity
|
|
99
|
+
? [
|
|
100
|
+
{ value: 'public-profile', label: 'Public Profile', shortcut: 'p' },
|
|
101
|
+
{ value: 'continuity', label: 'Soul & Memory', shortcut: 'm' },
|
|
102
|
+
{ value: 'skills-tree', label: 'Skills', shortcut: 's' },
|
|
103
|
+
{ value: 'backup', label: 'Save Snapshot', shortcut: 'a', disabled: !canRebackup || (flags?.saveSnapshotDisabled ?? false), hint: flags?.saveSnapshotHint, ...(localChangeStatus.hasLocalChanges && backupEnabled ? { inlineNote: localChangeStatus.files.length > 0 ? localChangeStatus.files.join(', ') : 'unsaved changes', inlineNoteColor: theme.accentError } : {}) },
|
|
104
|
+
{ value: 'refetch', label: 'Refetch Latest', shortcut: 'r', disabled: !canRefetch || (flags?.refetchLatestDisabled ?? false), hint: flags?.refetchHint },
|
|
105
|
+
{ value: 'ens-name', label: 'ENS Name', shortcut: 'e', disabled: flags?.ensNameDisabled ?? false, hint: flags?.ensNameHint },
|
|
106
|
+
{ value: 'identity-values', label: 'Token Values', shortcut: 'v', ...(flags?.tokenValuesUnlinkedNote ? { note: flags.tokenValuesUnlinkedNote } : {}) },
|
|
107
|
+
{ value: 'wallet-setup', label: 'Custody Mode', shortcut: 'c', disabled: !identity.agentId || (flags?.custodyModeDisabled ?? false), hint: flags?.custodyModeHint ?? flags?.custodyHint },
|
|
108
|
+
...(flags?.prepareTransferHidden ? [] : [{ value: 'prepare-transfer' as Action, label: 'Prepare Transfer', shortcut: 't', disabled: flags?.prepareTransferDisabled ?? false, hint: flags?.prepareTransferHint }]),
|
|
109
|
+
{ value: 'load', label: 'Switch Agent', shortcut: 'w' },
|
|
110
|
+
{ value: 'create', label: 'New Agent', shortcut: 'n' },
|
|
111
|
+
{ value: 'storage', label: 'IPFS Storage', shortcut: 'i' },
|
|
112
|
+
{ value: 'cancel', label: 'Quit', shortcut: 'q' },
|
|
113
|
+
]
|
|
114
|
+
: [
|
|
115
|
+
{ value: 'create', label: 'Create New Agent' },
|
|
116
|
+
{ value: 'load', label: 'Load Existing' },
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
const reconciliationBanner = identity && reconciliation
|
|
120
|
+
? renderReconciliationBanner(reconciliation, identity)
|
|
121
|
+
: null
|
|
122
|
+
|
|
123
|
+
const network = networkLabel(config, identity)
|
|
124
|
+
const statusBits: string[] = []
|
|
125
|
+
if (identity?.agentId) statusBits.push(`#${identity.agentId}`)
|
|
126
|
+
const displayAddress = perspective === 'operator' ? identity?.connectedWallet : identity?.ownerAddress
|
|
127
|
+
if (displayAddress) statusBits.push(shortAddress(displayAddress))
|
|
128
|
+
if (network) statusBits.push(network)
|
|
129
|
+
if (perspective === 'operator') statusBits.push('operator')
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<Box flexDirection="column" alignItems="center" paddingY={1}>
|
|
133
|
+
<Box flexDirection="column" alignItems="center">
|
|
134
|
+
{reconciliationBanner ? (
|
|
135
|
+
<Box marginBottom={1} flexDirection="column" alignItems="center">
|
|
136
|
+
{reconciliationBanner}
|
|
137
|
+
</Box>
|
|
138
|
+
) : null}
|
|
139
|
+
{!identity ? (
|
|
140
|
+
<Box marginBottom={1}>
|
|
141
|
+
<Text color={theme.textSubtle}>Create or link an agent identity to get started.</Text>
|
|
142
|
+
</Box>
|
|
143
|
+
) : null}
|
|
144
|
+
<LazyMenu<Action>
|
|
145
|
+
rows={rows}
|
|
146
|
+
onSubmit={choice => {
|
|
147
|
+
if (choice === 'cancel') return onCancel()
|
|
148
|
+
if (choice === 'public-profile') return onPublicProfile()
|
|
149
|
+
if (choice === 'ens-name') return onEnsName()
|
|
150
|
+
if (choice === 'wallet-setup') return onWalletSetup()
|
|
151
|
+
if (choice === 'continuity') return onContinuity()
|
|
152
|
+
if (choice === 'skills-tree') return onSkillsTree()
|
|
153
|
+
if (choice === 'backup') return onBackupNow()
|
|
154
|
+
if (choice === 'refetch') return onRefetchLatest()
|
|
155
|
+
if (choice === 'identity-values') return onIdentityValues()
|
|
156
|
+
if (choice === 'prepare-transfer') return onPrepareTransfer()
|
|
157
|
+
if (choice === 'storage') return onStorage()
|
|
158
|
+
if (choice === 'load') return onLoad()
|
|
159
|
+
if (choice === 'create') return onCreate()
|
|
160
|
+
}}
|
|
161
|
+
onCancel={onCancel}
|
|
162
|
+
/>
|
|
163
|
+
{!identity ? (
|
|
164
|
+
<Box marginTop={1}>
|
|
165
|
+
<Text color={theme.dim}>esc to quit</Text>
|
|
166
|
+
</Box>
|
|
167
|
+
) : null}
|
|
168
|
+
</Box>
|
|
169
|
+
{statusBits.length > 0 ? (
|
|
170
|
+
<Box marginTop={2}>
|
|
171
|
+
{isDemoMode() ? (
|
|
172
|
+
<Text>
|
|
173
|
+
<Text color={theme.accentHighlight}>demo </Text>
|
|
174
|
+
<Text color={theme.menuStatus}>· {statusBits.join(' · ')}</Text>
|
|
175
|
+
</Text>
|
|
176
|
+
) : (
|
|
177
|
+
<Text color={theme.menuStatus}>{statusBits.join(' · ')}</Text>
|
|
178
|
+
)}
|
|
179
|
+
</Box>
|
|
180
|
+
) : null}
|
|
181
|
+
</Box>
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function renderReconciliationBanner(r: AgentReconciliation, identity: EthagentIdentity): React.ReactNode {
|
|
186
|
+
if (r.token === 'no-agent') return null
|
|
187
|
+
if (r.token === 'unlinked') {
|
|
188
|
+
const tokenLabel = r.tokenAgentId ? `Token #${r.tokenAgentId}` : 'Token'
|
|
189
|
+
const transferSnapshot = transferSnapshotView(identity)
|
|
190
|
+
if (transferSnapshot) {
|
|
191
|
+
return (
|
|
192
|
+
<>
|
|
193
|
+
<Text color={theme.accentError} bold>Agent Unlinked</Text>
|
|
194
|
+
<Text color={theme.textSubtle}>{tokenLabel} was transferred. Local SOUL.md, MEMORY.md, and skills remain.</Text>
|
|
195
|
+
</>
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
return (
|
|
199
|
+
<>
|
|
200
|
+
<Text color={theme.accentError} bold>Agent Unlinked</Text>
|
|
201
|
+
<Text color={theme.textSubtle}>{tokenLabel} left without Prepare Transfer.</Text>
|
|
202
|
+
</>
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
if (r.token === 'unknown') {
|
|
206
|
+
return <Text color={theme.dim}>Ownership check failed (RPC?)</Text>
|
|
207
|
+
}
|
|
208
|
+
const lines: string[] = []
|
|
209
|
+
if (r.custody === 'mid-flow-uri-pending') lines.push('Advanced setup pending')
|
|
210
|
+
if (r.custody !== 'mid-flow-uri-pending' && r.agentUri === 'local-newer') lines.push('Local newer than onchain')
|
|
211
|
+
if (r.custody !== 'mid-flow-uri-pending' && r.agentUri === 'chain-newer') lines.push('Onchain newer than local')
|
|
212
|
+
if (r.vault === 'missing') lines.push('Vault contract missing')
|
|
213
|
+
if (lines.length === 0) return null
|
|
214
|
+
return (
|
|
215
|
+
<>
|
|
216
|
+
<Text color={theme.accentPeriwinkle} bold>{lines.length} item{lines.length === 1 ? '' : 's'} need attention</Text>
|
|
217
|
+
{lines.map((line, i) => <Text key={i} color={theme.textSubtle}>· {line}</Text>)}
|
|
218
|
+
</>
|
|
219
|
+
)
|
|
220
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react'
|
|
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
|
+
|
|
7
|
+
type OperationCompleteScreenProps = {
|
|
8
|
+
message: string
|
|
9
|
+
onReturn: () => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const OperationCompleteScreen: React.FC<OperationCompleteScreenProps> = ({ message, onReturn }) => (
|
|
13
|
+
<Surface
|
|
14
|
+
title="Done"
|
|
15
|
+
footer={<Text color={theme.dim}>enter returns to menu</Text>}
|
|
16
|
+
>
|
|
17
|
+
<Box flexDirection="column">
|
|
18
|
+
<Text color={theme.text}>{message}</Text>
|
|
19
|
+
<Box marginTop={1}>
|
|
20
|
+
<Select<'menu'>
|
|
21
|
+
options={[{ value: 'menu', label: 'Return to Menu' }]}
|
|
22
|
+
onSubmit={onReturn}
|
|
23
|
+
onCancel={onReturn}
|
|
24
|
+
/>
|
|
25
|
+
</Box>
|
|
26
|
+
</Box>
|
|
27
|
+
</Surface>
|
|
28
|
+
)
|
|
@@ -27,13 +27,13 @@ export const UnlinkedIdentityScreen: React.FC<UnlinkedIdentityScreenProps> = ({
|
|
|
27
27
|
}) => {
|
|
28
28
|
const options: Array<{ value: Action; label: string; hint?: string; role?: 'section' | 'utility' }> = [
|
|
29
29
|
{ value: 'load-agent', role: 'section', label: 'Switch Agent' },
|
|
30
|
-
{ value: 'load-agent', label: 'Switch Agent', hint: 'Reconnect
|
|
31
|
-
{ value: 'open-menu', role: 'section', label: 'Identity
|
|
32
|
-
{ value: 'open-menu', label: 'Open Identity
|
|
30
|
+
{ value: 'load-agent', label: 'Switch Agent', hint: 'Reconnect or switch wallet' },
|
|
31
|
+
{ value: 'open-menu', role: 'section', label: 'Identity' },
|
|
32
|
+
{ value: 'open-menu', label: 'Open Identity', hint: 'Browse without reconnecting' },
|
|
33
33
|
]
|
|
34
34
|
if (onRetry) {
|
|
35
35
|
options.push({ value: 'retry', role: 'section', label: 'Recheck' })
|
|
36
|
-
options.push({ value: 'retry', label: 'Retry Ownership Check', hint: '
|
|
36
|
+
options.push({ value: 'retry', label: 'Retry Ownership Check', hint: 'Recheck owner onchain', role: 'utility' })
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
const tokenLabel = agentId ? `Token #${agentId}` : 'Token'
|
|
@@ -47,15 +47,14 @@ export const UnlinkedIdentityScreen: React.FC<UnlinkedIdentityScreenProps> = ({
|
|
|
47
47
|
>
|
|
48
48
|
<Box flexDirection="column">
|
|
49
49
|
{transferSnapshot ? (
|
|
50
|
-
|
|
51
|
-
{tokenLabel} was transferred
|
|
52
|
-
|
|
50
|
+
<>
|
|
51
|
+
<Text color={theme.textSubtle}>{tokenLabel} was transferred.</Text>
|
|
52
|
+
<Text color={theme.textSubtle}>Local files remain. Back them up before reuse.</Text>
|
|
53
|
+
</>
|
|
53
54
|
) : (
|
|
54
55
|
<>
|
|
55
56
|
<Text color={theme.accentPeriwinkle}>{tokenLabel} left this wallet without Prepare Transfer, so the new holder has no continuity handoff.</Text>
|
|
56
|
-
<Text color={theme.textSubtle}>
|
|
57
|
-
Local SOUL.md, MEMORY.md, and skills remain. Back them up before this directory is reused.
|
|
58
|
-
</Text>
|
|
57
|
+
<Text color={theme.textSubtle}>Local files remain. Back them up before reuse.</Text>
|
|
59
58
|
</>
|
|
60
59
|
)}
|
|
61
60
|
</Box>
|
|
@@ -16,7 +16,6 @@ type WalletApprovalScreenProps = {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export const OPEN_BROWSER_HINT = 'Press enter to open in browser...'
|
|
19
|
-
const PREPARING_WALLET_REQUEST_LABEL = 'preparing wallet request...'
|
|
20
19
|
|
|
21
20
|
export const WalletApprovalScreen: React.FC<WalletApprovalScreenProps> = ({ title, subtitle, walletSession, label, onCancel }) => {
|
|
22
21
|
useAppInput((_input, key) => {
|
|
@@ -37,7 +36,7 @@ export const WalletApprovalScreen: React.FC<WalletApprovalScreenProps> = ({ titl
|
|
|
37
36
|
</Box>
|
|
38
37
|
</Box>
|
|
39
38
|
) : (
|
|
40
|
-
<Spinner label={
|
|
39
|
+
<Spinner label={label} />
|
|
41
40
|
)}
|
|
42
41
|
</Surface>
|
|
43
42
|
)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Box, Text } from 'ink'
|
|
3
|
+
import { theme, gradientColor } from '../../../../ui/theme.js'
|
|
4
|
+
|
|
5
|
+
export const LINES = [
|
|
6
|
+
'░░░░░░░╗░░░░░░░░╗░░╗ ░░╗ █████╗ ██████╗ ███████╗███╗ ██╗████████╗',
|
|
7
|
+
'░░╔════╝╚══░░╔══╝░░║ ░░║██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝',
|
|
8
|
+
'░░░░░╗ ░░║ ░░░░░░░║███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ',
|
|
9
|
+
'░░╔══╝ ░░║ ░░╔══░░║██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ',
|
|
10
|
+
'░░░░░░░╗ ░░║ ░░║ ░░║██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ',
|
|
11
|
+
'╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ',
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
export const SPLIT = 25
|
|
15
|
+
|
|
16
|
+
export const LEFT_DECOR = [
|
|
17
|
+
' ✦ ',
|
|
18
|
+
' ⊹ ',
|
|
19
|
+
' ',
|
|
20
|
+
' . ',
|
|
21
|
+
' ',
|
|
22
|
+
' ฅ^•ﻌ•マ ',
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
export const RIGHT_DECOR = [
|
|
26
|
+
' ˖ 𐰁 ',
|
|
27
|
+
' ',
|
|
28
|
+
' 𝗓 ',
|
|
29
|
+
' ⊹ ',
|
|
30
|
+
' ᶻ ',
|
|
31
|
+
' ',
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
export const Wordmark: React.FC = () => (
|
|
35
|
+
<Box flexDirection="row">
|
|
36
|
+
<Text color={theme.wordmarkEth}>{LEFT_DECOR.join('\n')}</Text>
|
|
37
|
+
<Box flexDirection="column">
|
|
38
|
+
{LINES.map((line, i) => {
|
|
39
|
+
const eth = line.slice(0, SPLIT)
|
|
40
|
+
const agent = line.slice(SPLIT)
|
|
41
|
+
const maxAgent = Math.max(1, agent.length - 1)
|
|
42
|
+
return (
|
|
43
|
+
<Text key={i}>
|
|
44
|
+
<Text color={theme.wordmarkEth}>{eth}</Text>
|
|
45
|
+
{[...agent].map((ch, j) => (
|
|
46
|
+
<Text key={j} color={gradientColor(j / maxAgent)}>{ch}</Text>
|
|
47
|
+
))}
|
|
48
|
+
</Text>
|
|
49
|
+
)
|
|
50
|
+
})}
|
|
51
|
+
</Box>
|
|
52
|
+
<Text color={theme.wordmarkEth}>{RIGHT_DECOR.join('\n')}</Text>
|
|
53
|
+
</Box>
|
|
54
|
+
)
|
|
@@ -3,19 +3,22 @@ import type { IdentityPerspective } from '../../custody/state.js'
|
|
|
3
3
|
|
|
4
4
|
type MenuFlags = {
|
|
5
5
|
prepareTransferDisabled: boolean
|
|
6
|
-
|
|
6
|
+
prepareTransferHint?: string
|
|
7
|
+
prepareTransferHidden: boolean
|
|
7
8
|
custodyModeDisabled: boolean
|
|
8
|
-
|
|
9
|
+
custodyModeHint?: string
|
|
9
10
|
ensNameDisabled: boolean
|
|
10
|
-
|
|
11
|
+
ensNameHint?: string
|
|
11
12
|
saveSnapshotDisabled: boolean
|
|
12
13
|
refetchLatestDisabled: boolean
|
|
14
|
+
refetchHint?: string
|
|
13
15
|
tokenValuesUnlinkedNote?: string
|
|
14
16
|
|
|
15
17
|
custodyAsterisk: boolean
|
|
16
18
|
custodyHint?: string
|
|
17
19
|
saveSnapshotAsterisk: boolean
|
|
18
20
|
saveSnapshotHint?: string
|
|
21
|
+
workingTreeDirty: boolean
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
export function menuFlagsFromReconciliation(r: AgentReconciliation, perspective: IdentityPerspective = 'unknown'): MenuFlags {
|
|
@@ -23,11 +26,21 @@ export function menuFlagsFromReconciliation(r: AgentReconciliation, perspective:
|
|
|
23
26
|
const inVault = r.custody === 'advanced' || r.custody === 'mid-flow-uri-pending'
|
|
24
27
|
const isOperator = perspective === 'operator'
|
|
25
28
|
|
|
26
|
-
let
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
} else if (
|
|
30
|
-
|
|
29
|
+
let prepareTransferHint: string | undefined
|
|
30
|
+
if (unlinked) {
|
|
31
|
+
prepareTransferHint = 'Token unlinked'
|
|
32
|
+
} else if (inVault) {
|
|
33
|
+
prepareTransferHint = 'Token is in the Vault'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let custodyModeHint: string | undefined
|
|
37
|
+
if (unlinked) {
|
|
38
|
+
custodyModeHint = 'Token unlinked'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let ensNameHint: string | undefined
|
|
42
|
+
if (unlinked) {
|
|
43
|
+
ensNameHint = 'Token unlinked'
|
|
31
44
|
}
|
|
32
45
|
|
|
33
46
|
const custodyAsterisk = r.custody === 'mid-flow-uri-pending' || r.vault === 'missing'
|
|
@@ -40,23 +53,34 @@ export function menuFlagsFromReconciliation(r: AgentReconciliation, perspective:
|
|
|
40
53
|
custodyHint = 'Vault missing, open to redeploy'
|
|
41
54
|
}
|
|
42
55
|
|
|
43
|
-
const
|
|
44
|
-
|
|
56
|
+
const agentUriLocalNewer = r.agentUri === 'local-newer' && r.custody !== 'mid-flow-uri-pending'
|
|
57
|
+
|
|
58
|
+
let saveSnapshotHint: string | undefined
|
|
59
|
+
if (unlinked) {
|
|
60
|
+
saveSnapshotHint = 'Token unlinked'
|
|
61
|
+
} else if (agentUriLocalNewer) {
|
|
62
|
+
saveSnapshotHint = 'Local newer than onchain'
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const refetchHint: string | undefined = unlinked ? 'Token unlinked' : undefined
|
|
45
66
|
|
|
46
67
|
return {
|
|
47
68
|
prepareTransferDisabled: unlinked || inVault || isOperator,
|
|
48
|
-
...(
|
|
69
|
+
...(prepareTransferHint ? { prepareTransferHint } : {}),
|
|
70
|
+
prepareTransferHidden: inVault,
|
|
49
71
|
custodyModeDisabled: unlinked || isOperator,
|
|
50
|
-
...(
|
|
72
|
+
...(custodyModeHint ? { custodyModeHint } : {}),
|
|
51
73
|
ensNameDisabled: unlinked || isOperator,
|
|
52
|
-
...(
|
|
74
|
+
...(ensNameHint ? { ensNameHint } : {}),
|
|
53
75
|
saveSnapshotDisabled: unlinked,
|
|
54
76
|
refetchLatestDisabled: unlinked,
|
|
77
|
+
...(refetchHint ? { refetchHint } : {}),
|
|
55
78
|
...(unlinked ? { tokenValuesUnlinkedNote: 'Unlinked, retained for reference' } : {}),
|
|
56
79
|
|
|
57
80
|
custodyAsterisk: custodyAsterisk && !isOperator,
|
|
58
81
|
...(custodyHint ? { custodyHint } : {}),
|
|
59
|
-
saveSnapshotAsterisk: r.
|
|
60
|
-
...(
|
|
82
|
+
saveSnapshotAsterisk: agentUriLocalNewer || r.workingTree === 'dirty',
|
|
83
|
+
...(saveSnapshotHint ? { saveSnapshotHint } : {}),
|
|
84
|
+
workingTreeDirty: r.workingTree === 'dirty',
|
|
61
85
|
}
|
|
62
86
|
}
|
|
@@ -3,7 +3,7 @@ import os from 'node:os'
|
|
|
3
3
|
import path from 'node:path'
|
|
4
4
|
import { getAddress, type Address } from 'viem'
|
|
5
5
|
import type { EthagentIdentity } from '../../../../storage/config.js'
|
|
6
|
-
import type { ProfileUpdates } from '../../
|
|
6
|
+
import type { ProfileUpdates } from '../../reducer.js'
|
|
7
7
|
import type { Erc8004RegistryConfig } from '../../../registry/erc8004.js'
|
|
8
8
|
import { addFileToIpfs, DEFAULT_IPFS_API_URL, type IpfsAddResult } from '../../../storage/ipfs.js'
|
|
9
9
|
import { agentIconContentType, isAgentIconUrl, validateAgentIconReference } from '../../../profile/agentIcon.js'
|
|
@@ -0,0 +1,30 @@
|
|
|
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 '../../reducer.js'
|
|
5
|
+
|
|
6
|
+
export type IdentityCompletionSource = 'create' | 'restore' | 'update'
|
|
7
|
+
|
|
8
|
+
export type EffectCallbacks = {
|
|
9
|
+
onStep: (step: Step) => void
|
|
10
|
+
onWalletReady: (session: BrowserWalletReady | null) => void
|
|
11
|
+
onIdentityComplete: (identity: EthagentIdentity, message: string, source?: IdentityCompletionSource) => Promise<void>
|
|
12
|
+
onRestoreProgress?: (progress: RestoreProgress | null) => void
|
|
13
|
+
onTokenTransferProgress?: (progress: TokenTransferProgress | null) => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type RestoreProgress = {
|
|
17
|
+
phase: 'decrypting' | 'writing' | 'finishing'
|
|
18
|
+
label: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type TokenTransferProgress = {
|
|
22
|
+
phase: 'sender-sign' | 'target-sign' | 'pinning' | 'sender-transaction' | 'confirming'
|
|
23
|
+
walletRole: 'sender' | 'receiver' | 'none'
|
|
24
|
+
title: string
|
|
25
|
+
detail: string
|
|
26
|
+
label: string
|
|
27
|
+
expectedAddress?: Address
|
|
28
|
+
walletAction?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
@@ -27,7 +27,3 @@ export function copyableIdentityFields(identity?: EthagentIdentity, config?: Eth
|
|
|
27
27
|
if (activeOperator) fields.push({ label: 'Operator Wallet', value: activeOperator })
|
|
28
28
|
return fields
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
export function identityValuesCopyHint(_identity?: EthagentIdentity): string {
|
|
32
|
-
return 'Copy token and pointers'
|
|
33
|
-
}
|
|
@@ -10,16 +10,17 @@ import {
|
|
|
10
10
|
formatVaultBytecodeMismatchDetail,
|
|
11
11
|
} from '../../../registry/vault.js'
|
|
12
12
|
import { BrowserWalletError } from '../../../wallet/browserWallet.js'
|
|
13
|
+
import { PinataUploadError } from '../../../storage/ipfs.js'
|
|
13
14
|
import { TxGuardBusyError } from '../txGuard.js'
|
|
14
15
|
import { shortAddress } from './format.js'
|
|
15
16
|
|
|
16
|
-
export type
|
|
17
|
+
export type IdentityManagerErrorView = {
|
|
17
18
|
title: string
|
|
18
19
|
detail?: string
|
|
19
20
|
hint?: string
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
export function
|
|
23
|
+
export function identityManagerErrorView(err: unknown): IdentityManagerErrorView {
|
|
23
24
|
if (err instanceof ZodError) {
|
|
24
25
|
const issue = err.issues[0]
|
|
25
26
|
const path = issue?.path.join('.') ?? ''
|
|
@@ -88,6 +89,34 @@ export function identityHubErrorView(err: unknown): IdentityHubErrorView {
|
|
|
88
89
|
hint: 'Switch to the expected wallet, confirm you have funds, then retry. If the wallet keeps reporting an internal RPC error, change the RPC endpoint in your wallet settings.',
|
|
89
90
|
}
|
|
90
91
|
}
|
|
92
|
+
if (err instanceof PinataUploadError) {
|
|
93
|
+
if (err.status === 403) {
|
|
94
|
+
return {
|
|
95
|
+
title: 'Pinata Storage Limit Reached',
|
|
96
|
+
detail: 'Pinata refused the upload (403). Your account is likely at its file or storage limit; the free plan caps at 500 files.',
|
|
97
|
+
hint: 'Check your usage at https://app.pinata.cloud, remove old pins or upgrade your plan, then try again.',
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (err.status === 401) {
|
|
101
|
+
return {
|
|
102
|
+
title: 'Pinata Rejected the Credential',
|
|
103
|
+
detail: 'Pinata rejected the upload (401). Your Pinata JWT is invalid or expired.',
|
|
104
|
+
hint: 'Update your Pinata JWT in Storage settings, then try again.',
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (err.status === 429) {
|
|
108
|
+
return {
|
|
109
|
+
title: 'Pinata Rate Limited',
|
|
110
|
+
detail: 'Pinata is throttling uploads (429): too many requests in a short window.',
|
|
111
|
+
hint: 'Wait a moment, then try again.',
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
title: 'Pinata Upload Failed',
|
|
116
|
+
detail: err.message,
|
|
117
|
+
hint: 'Check your Pinata account status at https://app.pinata.cloud, then try again.',
|
|
118
|
+
}
|
|
119
|
+
}
|
|
91
120
|
const message = err instanceof Error ? err.message : String(err)
|
|
92
121
|
if (/^owner wallet required:/i.test(message)) {
|
|
93
122
|
return {
|
|
@@ -124,7 +153,7 @@ export function identityHubErrorView(err: unknown): IdentityHubErrorView {
|
|
|
124
153
|
}
|
|
125
154
|
|
|
126
155
|
export function pinataErrorText(err: unknown): string {
|
|
127
|
-
const view =
|
|
156
|
+
const view = identityManagerErrorView(err)
|
|
128
157
|
return view.detail ?? view.title
|
|
129
158
|
}
|
|
130
159
|
|
|
@@ -12,8 +12,8 @@ export function networkLabel(network: SelectableNetwork): string {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
const NETWORK_SUBTITLES: Record<SelectableNetwork, string> = {
|
|
15
|
-
mainnet: 'Best for
|
|
16
|
-
base: 'Best for lower-cost
|
|
15
|
+
mainnet: 'Best for security',
|
|
16
|
+
base: 'Best for lower-cost use',
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export function networkSubtitle(network: SelectableNetwork): string {
|
|
@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'
|
|
|
2
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
|
+
import { isDemoMode, synthDemoReconciliation } from '../../../../../cli/demo.js'
|
|
5
6
|
|
|
6
7
|
export function useAgentReconciliation(
|
|
7
8
|
config: EthagentConfig | null,
|
|
@@ -19,6 +20,10 @@ export function useAgentReconciliation(
|
|
|
19
20
|
const [refreshKey, setRefreshKey] = useState(0)
|
|
20
21
|
|
|
21
22
|
useEffect(() => {
|
|
23
|
+
if (isDemoMode()) {
|
|
24
|
+
setReconciliation(synthDemoReconciliation())
|
|
25
|
+
return
|
|
26
|
+
}
|
|
22
27
|
if (!config?.identity || !config.identity.agentId || !config.identity.chainId || !config.identity.identityRegistryAddress) {
|
|
23
28
|
setReconciliation(emptyReconciliation())
|
|
24
29
|
return
|
|
@@ -262,7 +262,7 @@ function computeDriftCount(r: AgentReconciliation): number {
|
|
|
262
262
|
let n = 0
|
|
263
263
|
if (r.token === 'unlinked') n++
|
|
264
264
|
if (r.custody === 'mid-flow-uri-pending') n++
|
|
265
|
-
if (r.agentUri === 'local-newer' || r.agentUri === 'chain-newer') n++
|
|
265
|
+
if ((r.agentUri === 'local-newer' || r.agentUri === 'chain-newer') && r.custody !== 'mid-flow-uri-pending') n++
|
|
266
266
|
if (r.vault === 'missing') n++
|
|
267
267
|
if (r.workingTree === 'dirty') n++
|
|
268
268
|
return n
|