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
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { EthagentIdentity } from '../../../storage/config.js'
|
|
2
|
-
import type { PrivateContinuityFile } from '../storage.js'
|
|
3
|
-
|
|
4
|
-
export type PrivateContinuityEditInput = {
|
|
5
|
-
file: PrivateContinuityFile
|
|
6
|
-
oldText?: string
|
|
7
|
-
newText?: string
|
|
8
|
-
appendToSection?: string
|
|
9
|
-
appendText?: string
|
|
10
|
-
replaceAll?: boolean
|
|
11
|
-
replaceWholeFile?: boolean
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export type PreparedPrivateContinuityEdit = {
|
|
15
|
-
identity: EthagentIdentity
|
|
16
|
-
file: PrivateContinuityFile
|
|
17
|
-
fullPath: string
|
|
18
|
-
relativePath: string
|
|
19
|
-
directoryPath: string
|
|
20
|
-
existedBefore: boolean
|
|
21
|
-
previousContent: string
|
|
22
|
-
before: string
|
|
23
|
-
after: string
|
|
24
|
-
previewBefore: string
|
|
25
|
-
previewAfter: string
|
|
26
|
-
changeSummary: string
|
|
27
|
-
diff: string
|
|
28
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
import { atomicWriteText } from '../../storage/atomicWrite.js'
|
|
3
|
-
import type { EthagentConfig } from '../../storage/config.js'
|
|
4
|
-
import { ensureContinuityVault } from './storage.js'
|
|
5
|
-
import { ensureTrailingNewline } from './storage/files.js'
|
|
6
|
-
import { applyPrivateContinuityEdit } from './privateEdit/apply.js'
|
|
7
|
-
import { renderPrivateContinuityDiff } from './privateEdit/diff.js'
|
|
8
|
-
import { privateContinuityPath, readPrivateContinuityFile } from './privateEdit/files.js'
|
|
9
|
-
import type { PreparedPrivateContinuityEdit, PrivateContinuityEditInput } from './privateEdit/types.js'
|
|
10
|
-
|
|
11
|
-
export type { PreparedPrivateContinuityEdit, PrivateContinuityEditInput } from './privateEdit/types.js'
|
|
12
|
-
|
|
13
|
-
export async function preparePrivateContinuityEdit(
|
|
14
|
-
input: PrivateContinuityEditInput,
|
|
15
|
-
config: EthagentConfig | undefined,
|
|
16
|
-
): Promise<PreparedPrivateContinuityEdit> {
|
|
17
|
-
const identity = config?.identity
|
|
18
|
-
if (!identity) {
|
|
19
|
-
throw new Error('No active identity; create or load an identity before proposing private continuity edits')
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const fullPath = privateContinuityPath(identity, input.file)
|
|
23
|
-
const existing = await readPrivateContinuityFile(identity, input.file, fullPath)
|
|
24
|
-
const applied = applyPrivateContinuityEdit(input, existing.content, identity)
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
identity,
|
|
28
|
-
file: input.file,
|
|
29
|
-
fullPath,
|
|
30
|
-
relativePath: 'identity-vault/' + input.file,
|
|
31
|
-
directoryPath: path.dirname(fullPath),
|
|
32
|
-
existedBefore: existing.existedBefore,
|
|
33
|
-
previousContent: existing.existedBefore ? existing.content : '',
|
|
34
|
-
before: existing.content,
|
|
35
|
-
after: applied.after,
|
|
36
|
-
previewBefore: applied.previewBefore,
|
|
37
|
-
previewAfter: applied.previewAfter,
|
|
38
|
-
changeSummary: applied.summary,
|
|
39
|
-
diff: renderPrivateContinuityDiff(input.file, applied.before, applied.after),
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export async function writePreparedPrivateContinuityEdit(edit: PreparedPrivateContinuityEdit): Promise<void> {
|
|
44
|
-
await ensureContinuityVault(edit.identity)
|
|
45
|
-
await atomicWriteText(edit.fullPath, ensureTrailingNewline(edit.after), { mode: 0o600 })
|
|
46
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { IdentityHubRoutes } from './Routes.js'
|
|
3
|
-
import type { IdentityHubProps } from './types.js'
|
|
4
|
-
import { useIdentityHubController } from './useIdentityHubController.js'
|
|
5
|
-
|
|
6
|
-
export type {
|
|
7
|
-
IdentityHubInitialAction,
|
|
8
|
-
IdentityHubResult,
|
|
9
|
-
} from './types.js'
|
|
10
|
-
|
|
11
|
-
export const IdentityHub: React.FC<IdentityHubProps> = props => {
|
|
12
|
-
const controller = useIdentityHubController(props)
|
|
13
|
-
return <IdentityHubRoutes controller={controller} />
|
|
14
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
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
|
-
import { localChangeStatusView, type LocalChangeStatusView } from './state.js'
|
|
7
|
-
|
|
8
|
-
import type { ContinuityWorkingTreeStatus } from '../../continuity/storage.js'
|
|
9
|
-
|
|
10
|
-
type RecoveryConfirmMode = 'publish' | 'refetch'
|
|
11
|
-
|
|
12
|
-
interface RecoveryConfirmScreenProps {
|
|
13
|
-
mode: RecoveryConfirmMode
|
|
14
|
-
workingStatus?: ContinuityWorkingTreeStatus | null
|
|
15
|
-
pendingPublish?: boolean
|
|
16
|
-
footer: React.ReactNode
|
|
17
|
-
onConfirm: () => void
|
|
18
|
-
onBack: () => void
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const RecoveryConfirmScreen: React.FC<RecoveryConfirmScreenProps> = ({ mode, workingStatus, pendingPublish, footer, onConfirm, onBack }) => {
|
|
22
|
-
const isPublish = mode === 'publish'
|
|
23
|
-
const title = isPublish ? 'Save Snapshot?' : 'Refetch Latest From Onchain?'
|
|
24
|
-
const subtitle = isPublish
|
|
25
|
-
? 'Saves SOUL.md, MEMORY.md, skills, and profile changes.'
|
|
26
|
-
: 'This overwrites local files with the onchain version.'
|
|
27
|
-
|
|
28
|
-
const headlineColor = theme.accentPeriwinkle
|
|
29
|
-
const headline = isPublish
|
|
30
|
-
? 'Saving updates the onchain pointer for this agent.'
|
|
31
|
-
: 'Refetching replaces SOUL.md, MEMORY.md, and skills with what is onchain.'
|
|
32
|
-
const detail = isPublish
|
|
33
|
-
? 'Your local continuity files and profile edits become the saved state. The previous snapshot pointer is overwritten.'
|
|
34
|
-
: 'Unsaved local edits will be lost. Use this when local files are missing or out of sync with the latest saved snapshot.'
|
|
35
|
-
|
|
36
|
-
const localChangeStatus = localChangeStatusView(workingStatus)
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<Surface title={title} subtitle={subtitle} footer={footer} tone="primary">
|
|
40
|
-
<Box flexDirection="column">
|
|
41
|
-
<Text color={headlineColor}>{headline}</Text>
|
|
42
|
-
<Text color={theme.textSubtle}>{detail}</Text>
|
|
43
|
-
{isPublish && (
|
|
44
|
-
<Box marginTop={1}>
|
|
45
|
-
<SaveSnapshotStatusLine status={localChangeStatus} />
|
|
46
|
-
</Box>
|
|
47
|
-
)}
|
|
48
|
-
{!isPublish && pendingPublish ? (
|
|
49
|
-
<Box marginTop={1} flexDirection="column">
|
|
50
|
-
<Text color={theme.accentError} bold>Local snapshot is ahead of onchain.</Text>
|
|
51
|
-
<Text color={theme.textSubtle}>Local edits have not yet been rotated to the onchain pointer. Refetching discards them and reverts to the last published snapshot.</Text>
|
|
52
|
-
</Box>
|
|
53
|
-
) : null}
|
|
54
|
-
{!isPublish && (
|
|
55
|
-
<Box marginTop={1}>
|
|
56
|
-
<Text color={theme.accentPeriwinkle}>Overwrite your local files?</Text>
|
|
57
|
-
</Box>
|
|
58
|
-
)}
|
|
59
|
-
</Box>
|
|
60
|
-
<Box marginTop={1}>
|
|
61
|
-
<Select<'confirm' | 'back'>
|
|
62
|
-
options={[
|
|
63
|
-
{ value: 'confirm', role: 'section', label: isPublish ? 'Save' : 'Refetch' },
|
|
64
|
-
{
|
|
65
|
-
value: 'confirm',
|
|
66
|
-
label: isPublish ? 'Yes, Save Snapshot Now' : 'Yes, Refetch From Onchain',
|
|
67
|
-
hint: isPublish ? 'Sign and save the encrypted snapshot' : 'Wallet decrypts and overwrites local files',
|
|
68
|
-
},
|
|
69
|
-
{ value: 'back', role: 'section', label: 'Navigation' },
|
|
70
|
-
{
|
|
71
|
-
value: 'back',
|
|
72
|
-
label: 'No, Go Back',
|
|
73
|
-
hint: isPublish ? 'Return without saving anything' : 'Return without changing anything',
|
|
74
|
-
role: 'utility',
|
|
75
|
-
},
|
|
76
|
-
]}
|
|
77
|
-
hintLayout="inline"
|
|
78
|
-
onSubmit={choice => {
|
|
79
|
-
if (choice === 'confirm') return onConfirm()
|
|
80
|
-
return onBack()
|
|
81
|
-
}}
|
|
82
|
-
onCancel={onBack}
|
|
83
|
-
/>
|
|
84
|
-
</Box>
|
|
85
|
-
</Surface>
|
|
86
|
-
)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const SaveSnapshotStatusLine: React.FC<{ status: LocalChangeStatusView }> = ({ status }) => {
|
|
90
|
-
if (status.hasLocalChanges) {
|
|
91
|
-
return (
|
|
92
|
-
<Text>
|
|
93
|
-
<Text color={theme.textSubtle}>Local changes detected: </Text>
|
|
94
|
-
<Text color={theme.accentError} bold>{status.files.length > 0 ? status.files.join(', ') : 'local files differ from saved snapshot'}</Text>
|
|
95
|
-
</Text>
|
|
96
|
-
)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (!status.detail) return null
|
|
100
|
-
|
|
101
|
-
const color = status.tone === 'ok' || status.tone === 'warn' ? theme.accentPeriwinkle : theme.dim
|
|
102
|
-
const label = status.detail === 'None detected' ? 'No local changes detected.' : status.detail
|
|
103
|
-
return <Text color={color}>{label}</Text>
|
|
104
|
-
}
|
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
import type { Address, PublicClient } from 'viem'
|
|
2
|
-
import type { EthagentIdentity } from '../../../storage/config.js'
|
|
3
|
-
import type { AgentEnsRecordState, AgentEnsRecords } from '../../ens/agentRecords.js'
|
|
4
|
-
import type { Erc8004RegistryConfig } from '../../registry/erc8004.js'
|
|
5
|
-
import {
|
|
6
|
-
openBrowserWalletSession,
|
|
7
|
-
type WalletPurpose,
|
|
8
|
-
} from '../../wallet/browserWallet.js'
|
|
9
|
-
import type { ProfileUpdates, Step } from '../identityHubReducer.js'
|
|
10
|
-
import type { EffectCallbacks, EnsClearProgress, EnsLinkProgress, EnsUpdateProgress } from '../shared/effects/types.js'
|
|
11
|
-
import {
|
|
12
|
-
runEnsSetupRecordsTransaction,
|
|
13
|
-
runEnsSetupRegistryTransaction,
|
|
14
|
-
runUpdateEnsRecords,
|
|
15
|
-
} from './transactions.js'
|
|
16
|
-
import { runRebackupSigningInSession } from '../continuity/effects.js'
|
|
17
|
-
|
|
18
|
-
type EnsRecordsFlowArgs = {
|
|
19
|
-
identity: EthagentIdentity
|
|
20
|
-
registry: Erc8004RegistryConfig
|
|
21
|
-
fullName: string
|
|
22
|
-
ownerAddress: Address
|
|
23
|
-
records: AgentEnsRecords
|
|
24
|
-
currentRecords?: AgentEnsRecordState
|
|
25
|
-
pinataJwt?: string
|
|
26
|
-
publicClient?: PublicClient
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async function runEnsRecordsThenSnapshot(args: {
|
|
30
|
-
flowId: 'ens-clear' | 'ens-update' | 'ens-link'
|
|
31
|
-
flow: EnsRecordsFlowArgs
|
|
32
|
-
clearRecords: boolean
|
|
33
|
-
recordsPurpose: WalletPurpose
|
|
34
|
-
callbacks: EffectCallbacks
|
|
35
|
-
reportProgress: (phase: 'records-tx' | 'records-confirming' | 'snapshot-sign' | 'snapshot-tx' | 'snapshot-confirming') => void
|
|
36
|
-
preRecordsSteps?: number
|
|
37
|
-
totalSteps: number
|
|
38
|
-
}): Promise<void> {
|
|
39
|
-
const { flow } = args
|
|
40
|
-
const session = await openBrowserWalletSession({ onReady: args.callbacks.onWalletReady })
|
|
41
|
-
try {
|
|
42
|
-
args.reportProgress('records-tx')
|
|
43
|
-
const recordsStepIndex = (args.preRecordsSteps ?? 0) + 1
|
|
44
|
-
await runUpdateEnsRecords({
|
|
45
|
-
fullName: flow.fullName,
|
|
46
|
-
ownerAddress: flow.ownerAddress,
|
|
47
|
-
records: flow.records,
|
|
48
|
-
...(flow.currentRecords ? { currentRecords: flow.currentRecords } : {}),
|
|
49
|
-
callbacks: args.callbacks,
|
|
50
|
-
purpose: args.recordsPurpose,
|
|
51
|
-
clearRecords: args.clearRecords,
|
|
52
|
-
...(flow.publicClient ? { publicClient: flow.publicClient } : {}),
|
|
53
|
-
tokenChainId: flow.registry.chainId,
|
|
54
|
-
session,
|
|
55
|
-
flowId: args.flowId,
|
|
56
|
-
flowStep: recordsStepIndex,
|
|
57
|
-
})
|
|
58
|
-
args.reportProgress('records-confirming')
|
|
59
|
-
args.reportProgress('snapshot-sign')
|
|
60
|
-
const snapshotStepIndex = recordsStepIndex + 1
|
|
61
|
-
const nextEnsName = args.clearRecords ? '' : flow.fullName
|
|
62
|
-
const profileUpdates: ProfileUpdates = { ensName: nextEnsName }
|
|
63
|
-
const rebackupStep: Extract<Step, { kind: 'rebackup-signing' }> = {
|
|
64
|
-
kind: 'rebackup-signing',
|
|
65
|
-
identity: flow.identity,
|
|
66
|
-
registry: flow.registry,
|
|
67
|
-
profileUpdates,
|
|
68
|
-
...(flow.pinataJwt ? { pinataJwt: flow.pinataJwt } : {}),
|
|
69
|
-
}
|
|
70
|
-
args.reportProgress('snapshot-tx')
|
|
71
|
-
await runRebackupSigningInSession(rebackupStep, args.callbacks, session, {
|
|
72
|
-
flowId: args.flowId,
|
|
73
|
-
flowStep: snapshotStepIndex,
|
|
74
|
-
})
|
|
75
|
-
args.reportProgress('snapshot-confirming')
|
|
76
|
-
} finally {
|
|
77
|
-
await session.close().catch(() => null)
|
|
78
|
-
args.callbacks.onWalletReady(null)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export async function runEnsUnlinkFlow(
|
|
83
|
-
step: Extract<Step, { kind: 'ens-clear-flow-running' }>,
|
|
84
|
-
callbacks: EffectCallbacks,
|
|
85
|
-
): Promise<void> {
|
|
86
|
-
await runEnsRecordsThenSnapshot({
|
|
87
|
-
flowId: 'ens-clear',
|
|
88
|
-
clearRecords: true,
|
|
89
|
-
recordsPurpose: 'clear-ens-records',
|
|
90
|
-
flow: {
|
|
91
|
-
identity: step.identity,
|
|
92
|
-
registry: step.registry,
|
|
93
|
-
fullName: step.fullName,
|
|
94
|
-
ownerAddress: step.ownerAddress,
|
|
95
|
-
records: step.records,
|
|
96
|
-
...(step.currentRecords ? { currentRecords: step.currentRecords } : {}),
|
|
97
|
-
...(step.pinataJwt ? { pinataJwt: step.pinataJwt } : {}),
|
|
98
|
-
},
|
|
99
|
-
callbacks,
|
|
100
|
-
reportProgress: phase => callbacks.onEnsClearProgress?.({ phase, label: ensClearLabelFor(phase) }),
|
|
101
|
-
totalSteps: 2,
|
|
102
|
-
})
|
|
103
|
-
callbacks.onEnsClearProgress?.(null)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export async function runEnsUpdateFlow(
|
|
107
|
-
step: Extract<Step, { kind: 'ens-update-flow-running' }>,
|
|
108
|
-
callbacks: EffectCallbacks,
|
|
109
|
-
): Promise<void> {
|
|
110
|
-
await runEnsRecordsThenSnapshot({
|
|
111
|
-
flowId: 'ens-update',
|
|
112
|
-
clearRecords: false,
|
|
113
|
-
recordsPurpose: 'update-ens-records',
|
|
114
|
-
flow: {
|
|
115
|
-
identity: step.identity,
|
|
116
|
-
registry: step.registry,
|
|
117
|
-
fullName: step.fullName,
|
|
118
|
-
ownerAddress: step.ownerAddress,
|
|
119
|
-
records: step.records,
|
|
120
|
-
...(step.currentRecords ? { currentRecords: step.currentRecords } : {}),
|
|
121
|
-
...(step.pinataJwt ? { pinataJwt: step.pinataJwt } : {}),
|
|
122
|
-
},
|
|
123
|
-
callbacks,
|
|
124
|
-
reportProgress: phase => callbacks.onEnsUpdateProgress?.({ phase, label: ensUpdateLabelFor(phase) }),
|
|
125
|
-
totalSteps: 2,
|
|
126
|
-
})
|
|
127
|
-
callbacks.onEnsUpdateProgress?.(null)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function ensClearLabelFor(phase: EnsClearProgress['phase']): string {
|
|
131
|
-
switch (phase) {
|
|
132
|
-
case 'records-tx': return 'Clearing ENS records on Ethereum Mainnet...'
|
|
133
|
-
case 'records-confirming': return 'Waiting for ENS clear confirmation...'
|
|
134
|
-
case 'snapshot-sign': return 'Sign to save the cleared snapshot...'
|
|
135
|
-
case 'snapshot-tx': return 'Publishing cleared snapshot to the agent token URI...'
|
|
136
|
-
case 'snapshot-confirming': return 'Waiting for snapshot publish confirmation...'
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function ensUpdateLabelFor(phase: EnsUpdateProgress['phase']): string {
|
|
141
|
-
switch (phase) {
|
|
142
|
-
case 'records-tx': return 'Updating ENS records on Ethereum Mainnet...'
|
|
143
|
-
case 'records-confirming': return 'Waiting for ENS records confirmation...'
|
|
144
|
-
case 'snapshot-sign': return 'Sign to save the updated snapshot...'
|
|
145
|
-
case 'snapshot-tx': return 'Publishing updated snapshot to the agent token URI...'
|
|
146
|
-
case 'snapshot-confirming': return 'Waiting for snapshot publish confirmation...'
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function ensLinkLabelFor(phase: EnsLinkProgress['phase']): string {
|
|
151
|
-
switch (phase) {
|
|
152
|
-
case 'registry-tx': return 'Creating ENS subdomain on Ethereum Mainnet...'
|
|
153
|
-
case 'registry-confirming': return 'Waiting for subdomain creation confirmation...'
|
|
154
|
-
case 'records-tx': return 'Setting ENS records on Ethereum Mainnet...'
|
|
155
|
-
case 'records-confirming': return 'Waiting for ENS records confirmation...'
|
|
156
|
-
case 'snapshot-sign': return 'Sign to save the linked snapshot...'
|
|
157
|
-
case 'snapshot-tx': return 'Publishing linked snapshot to the agent token URI...'
|
|
158
|
-
case 'snapshot-confirming': return 'Waiting for snapshot publish confirmation...'
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export async function runEnsLinkFlow(
|
|
163
|
-
step: Extract<Step, { kind: 'ens-link-flow-running' }>,
|
|
164
|
-
callbacks: EffectCallbacks,
|
|
165
|
-
): Promise<void> {
|
|
166
|
-
const session = await openBrowserWalletSession({ onReady: callbacks.onWalletReady })
|
|
167
|
-
const report = (phase: EnsLinkProgress['phase']): void => {
|
|
168
|
-
callbacks.onEnsLinkProgress?.({ phase, label: ensLinkLabelFor(phase) })
|
|
169
|
-
}
|
|
170
|
-
try {
|
|
171
|
-
let stepIndex = 0
|
|
172
|
-
const willRunRegistry = step.setup.registryAction !== 'none'
|
|
173
|
-
if (willRunRegistry) {
|
|
174
|
-
stepIndex += 1
|
|
175
|
-
report('registry-tx')
|
|
176
|
-
await runEnsSetupRegistryTransaction({
|
|
177
|
-
setup: step.setup,
|
|
178
|
-
callbacks,
|
|
179
|
-
tokenChainId: step.registry.chainId,
|
|
180
|
-
session,
|
|
181
|
-
flowId: 'ens-link',
|
|
182
|
-
flowStep: stepIndex,
|
|
183
|
-
})
|
|
184
|
-
report('registry-confirming')
|
|
185
|
-
}
|
|
186
|
-
stepIndex += 1
|
|
187
|
-
report('records-tx')
|
|
188
|
-
await runEnsSetupRecordsTransaction({
|
|
189
|
-
setup: step.setup,
|
|
190
|
-
callbacks,
|
|
191
|
-
tokenChainId: step.registry.chainId,
|
|
192
|
-
session,
|
|
193
|
-
flowId: 'ens-link',
|
|
194
|
-
flowStep: stepIndex,
|
|
195
|
-
})
|
|
196
|
-
report('records-confirming')
|
|
197
|
-
stepIndex += 1
|
|
198
|
-
report('snapshot-sign')
|
|
199
|
-
const profileUpdates: ProfileUpdates = { ensName: step.setup.fullName }
|
|
200
|
-
const rebackupStep: Extract<Step, { kind: 'rebackup-signing' }> = {
|
|
201
|
-
kind: 'rebackup-signing',
|
|
202
|
-
identity: step.identity,
|
|
203
|
-
registry: step.registry,
|
|
204
|
-
profileUpdates,
|
|
205
|
-
...(step.pinataJwt ? { pinataJwt: step.pinataJwt } : {}),
|
|
206
|
-
}
|
|
207
|
-
report('snapshot-tx')
|
|
208
|
-
await runRebackupSigningInSession(rebackupStep, callbacks, session, {
|
|
209
|
-
flowId: 'ens-link',
|
|
210
|
-
flowStep: stepIndex,
|
|
211
|
-
})
|
|
212
|
-
report('snapshot-confirming')
|
|
213
|
-
} finally {
|
|
214
|
-
await session.close().catch(() => null)
|
|
215
|
-
callbacks.onWalletReady(null)
|
|
216
|
-
callbacks.onEnsLinkProgress?.(null)
|
|
217
|
-
}
|
|
218
|
-
}
|
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
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 { FirstRunTimeline } from '../../../../app/FirstRunTimeline.js'
|
|
7
|
-
import type { EthagentConfig, EthagentIdentity } from '../../../../storage/config.js'
|
|
8
|
-
import type { ContinuityWorkingTreeStatus } from '../../../continuity/storage.js'
|
|
9
|
-
import { identityPerspective, readCustodyMode } from '../../custody/state.js'
|
|
10
|
-
import { identityValuesCopyHint } from '../model/copy.js'
|
|
11
|
-
import { transferSnapshotView } from '../../transfer/state.js'
|
|
12
|
-
import { IdentitySummary } from './IdentitySummary.js'
|
|
13
|
-
import type { AgentReconciliation } from '../reconciliation/index.js'
|
|
14
|
-
import { menuFlagsFromReconciliation } from './menuFlagsFromReconciliation.js'
|
|
15
|
-
|
|
16
|
-
type MenuScreenProps = {
|
|
17
|
-
mode: 'first-run' | 'manage'
|
|
18
|
-
config?: EthagentConfig
|
|
19
|
-
identity?: EthagentIdentity
|
|
20
|
-
workingStatus?: ContinuityWorkingTreeStatus | null
|
|
21
|
-
canRebackup: boolean
|
|
22
|
-
reconciliation?: AgentReconciliation
|
|
23
|
-
footer: React.ReactNode
|
|
24
|
-
onCreate: () => void
|
|
25
|
-
onLoad: () => void
|
|
26
|
-
onBackupNow: () => void
|
|
27
|
-
onRefetchLatest: () => void
|
|
28
|
-
onPublicProfile: () => void
|
|
29
|
-
onEnsName: () => void
|
|
30
|
-
onWalletSetup: () => void
|
|
31
|
-
onContinuity: () => void
|
|
32
|
-
onSkillsTree: () => void
|
|
33
|
-
onIdentityValues: () => void
|
|
34
|
-
onPrepareTransfer: () => void
|
|
35
|
-
onStorage: () => void
|
|
36
|
-
onSkip: () => void
|
|
37
|
-
onCancel: () => void
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
type Action =
|
|
41
|
-
| 'public-profile'
|
|
42
|
-
| 'ens-name'
|
|
43
|
-
| 'wallet-setup'
|
|
44
|
-
| 'continuity'
|
|
45
|
-
| 'skills-tree'
|
|
46
|
-
| 'backup'
|
|
47
|
-
| 'refetch'
|
|
48
|
-
| 'identity-values'
|
|
49
|
-
| 'prepare-transfer'
|
|
50
|
-
| 'storage'
|
|
51
|
-
| 'create'
|
|
52
|
-
| 'load'
|
|
53
|
-
| 'skip'
|
|
54
|
-
| 'cancel'
|
|
55
|
-
|
|
56
|
-
export const MenuScreen: React.FC<MenuScreenProps> = ({
|
|
57
|
-
mode,
|
|
58
|
-
config,
|
|
59
|
-
identity,
|
|
60
|
-
workingStatus,
|
|
61
|
-
canRebackup,
|
|
62
|
-
reconciliation,
|
|
63
|
-
footer,
|
|
64
|
-
onCreate,
|
|
65
|
-
onLoad,
|
|
66
|
-
onBackupNow,
|
|
67
|
-
onRefetchLatest,
|
|
68
|
-
onPublicProfile,
|
|
69
|
-
onEnsName,
|
|
70
|
-
onWalletSetup,
|
|
71
|
-
onContinuity,
|
|
72
|
-
onSkillsTree,
|
|
73
|
-
onIdentityValues,
|
|
74
|
-
onPrepareTransfer,
|
|
75
|
-
onStorage,
|
|
76
|
-
onSkip,
|
|
77
|
-
onCancel,
|
|
78
|
-
}) => {
|
|
79
|
-
const isFirstRun = mode === 'first-run'
|
|
80
|
-
const title = isFirstRun ? 'Set Up Agent Identity' : 'Identity Hub'
|
|
81
|
-
const subtitle: React.ReactNode = isFirstRun
|
|
82
|
-
? <FirstRunTimeline current={2} />
|
|
83
|
-
: 'Manage agent identity, custody, encrypted continuity, and recovery.'
|
|
84
|
-
|
|
85
|
-
const canRefetch = Boolean(canRebackup && identity?.backup?.cid)
|
|
86
|
-
const custodyMode = identity ? readCustodyMode(identity.state) : undefined
|
|
87
|
-
|
|
88
|
-
const perspective = identityPerspective(identity)
|
|
89
|
-
const flags = reconciliation
|
|
90
|
-
? menuFlagsFromReconciliation(reconciliation, perspective)
|
|
91
|
-
: (perspective === 'operator'
|
|
92
|
-
? menuFlagsFromReconciliation({
|
|
93
|
-
token: 'unknown', custody: 'unknown', agentUri: 'unknown',
|
|
94
|
-
vault: 'unknown', workingTree: 'unknown', rpc: 'reachable', driftCount: 0, lastCheckedAt: '',
|
|
95
|
-
}, perspective)
|
|
96
|
-
: null)
|
|
97
|
-
|
|
98
|
-
const walletSetupBaseHint = custodyMode === 'advanced'
|
|
99
|
-
? 'Owner wallet, vault, operators'
|
|
100
|
-
: 'Simple mode, switch for vault delegation'
|
|
101
|
-
|
|
102
|
-
const walletSetupLabel = flags?.custodyAsterisk ? 'Custody Mode *' : 'Custody Mode'
|
|
103
|
-
const walletSetupHint = flags?.custodyModeReason ?? flags?.custodyHint ?? walletSetupBaseHint
|
|
104
|
-
|
|
105
|
-
const saveSnapshotLabel = flags?.saveSnapshotAsterisk ? 'Save Snapshot *' : 'Save Snapshot'
|
|
106
|
-
const saveSnapshotHint = flags?.saveSnapshotHint ?? 'Publish encrypted snapshot'
|
|
107
|
-
|
|
108
|
-
const ensNameHint = flags?.ensNameReason ?? 'Public name or subdomain'
|
|
109
|
-
|
|
110
|
-
const prepareTransferHint = flags?.prepareTransferReason ?? 'Hand off this agent'
|
|
111
|
-
|
|
112
|
-
const tokenValuesHint = flags?.tokenValuesUnlinkedNote ?? identityValuesCopyHint(identity)
|
|
113
|
-
|
|
114
|
-
const options: Array<SelectOption<Action>> = identity
|
|
115
|
-
? [
|
|
116
|
-
{ value: 'public-profile', role: 'section', label: 'Public Identity' },
|
|
117
|
-
{ value: 'public-profile', label: 'Public Profile', hint: 'Agent card and profile fields' },
|
|
118
|
-
{ value: 'ens-name', label: 'ENS Name', hint: ensNameHint, disabled: flags?.ensNameDisabled ?? false },
|
|
119
|
-
{ value: 'continuity', role: 'section', label: 'Continuity' },
|
|
120
|
-
{ value: 'continuity', label: 'Soul & Memory', hint: 'Edit SOUL.md and MEMORY.md' },
|
|
121
|
-
{ value: 'skills-tree', label: 'Skills', hint: 'Browse and edit SKILL.md files' },
|
|
122
|
-
{ value: 'backup', label: saveSnapshotLabel, hint: saveSnapshotHint, disabled: !canRebackup || (flags?.saveSnapshotDisabled ?? false) },
|
|
123
|
-
{ value: 'refetch', label: 'Refetch Snapshot', hint: 'Restore latest snapshot', disabled: !canRefetch || (flags?.refetchLatestDisabled ?? false) },
|
|
124
|
-
{ value: 'wallet-setup', role: 'section', label: 'Custody' },
|
|
125
|
-
{ value: 'wallet-setup', label: walletSetupLabel, hint: walletSetupHint, disabled: !identity.agentId || (flags?.custodyModeDisabled ?? false) },
|
|
126
|
-
{ value: 'prepare-transfer', label: 'Prepare Transfer', hint: prepareTransferHint, disabled: flags?.prepareTransferDisabled ?? false },
|
|
127
|
-
{ value: 'identity-values', role: 'section', label: 'Token' },
|
|
128
|
-
{ value: 'identity-values', label: 'Token Values', hint: tokenValuesHint },
|
|
129
|
-
{ value: 'load', label: 'Switch Agent', hint: 'Switch agent or wallet' },
|
|
130
|
-
{ value: 'create', label: 'New Agent', hint: 'Mint another agent' },
|
|
131
|
-
{ value: 'storage', label: 'IPFS Storage', hint: 'Publishing credentials' },
|
|
132
|
-
{ value: 'cancel', role: 'section', label: 'Exit' },
|
|
133
|
-
{ value: 'cancel', label: 'Close Identity Hub', hint: 'Return to chat', role: 'utility' },
|
|
134
|
-
]
|
|
135
|
-
: [
|
|
136
|
-
{ value: 'create', role: 'section', label: 'Setup' },
|
|
137
|
-
{ value: 'create', label: 'Create New Agent', hint: 'Mint a wallet-owned token for this machine' },
|
|
138
|
-
{ value: 'load', label: 'Load Existing Agent', hint: 'Find a token owned by this wallet or linked to it' },
|
|
139
|
-
...(mode === 'first-run'
|
|
140
|
-
? [
|
|
141
|
-
{ value: 'skip' as Action, label: 'Skip For Now', hint: 'Continue now, use /identity later', role: 'utility' as const },
|
|
142
|
-
]
|
|
143
|
-
: [
|
|
144
|
-
{ value: 'cancel' as Action, label: 'Close Identity Hub', hint: 'Return to chat without changing identity', role: 'utility' as const },
|
|
145
|
-
]),
|
|
146
|
-
]
|
|
147
|
-
|
|
148
|
-
const reconciliationBanner = identity && reconciliation
|
|
149
|
-
? renderReconciliationBanner(reconciliation, identity)
|
|
150
|
-
: null
|
|
151
|
-
|
|
152
|
-
return (
|
|
153
|
-
<Surface title={title} subtitle={subtitle} footer={footer}>
|
|
154
|
-
<IdentitySummary
|
|
155
|
-
identity={identity}
|
|
156
|
-
config={config}
|
|
157
|
-
workingStatus={workingStatus}
|
|
158
|
-
tokenLinked={reconciliation ? reconciliation.token === 'linked' : true}
|
|
159
|
-
{...(reconciliation?.onChainOwner ? { onchainOwner: reconciliation.onChainOwner } : {})}
|
|
160
|
-
/>
|
|
161
|
-
{reconciliationBanner ? (
|
|
162
|
-
<Box marginTop={1} flexDirection="column">
|
|
163
|
-
{reconciliationBanner}
|
|
164
|
-
</Box>
|
|
165
|
-
) : null}
|
|
166
|
-
<Box marginTop={1}>
|
|
167
|
-
<Select<Action>
|
|
168
|
-
options={options}
|
|
169
|
-
hintLayout="inline"
|
|
170
|
-
onSubmit={choice => {
|
|
171
|
-
if (choice === 'skip') return onSkip()
|
|
172
|
-
if (choice === 'cancel') return onCancel()
|
|
173
|
-
if (choice === 'public-profile') return onPublicProfile()
|
|
174
|
-
if (choice === 'ens-name') return onEnsName()
|
|
175
|
-
if (choice === 'wallet-setup') return onWalletSetup()
|
|
176
|
-
if (choice === 'continuity') return onContinuity()
|
|
177
|
-
if (choice === 'skills-tree') return onSkillsTree()
|
|
178
|
-
if (choice === 'backup') return onBackupNow()
|
|
179
|
-
if (choice === 'refetch') return onRefetchLatest()
|
|
180
|
-
if (choice === 'identity-values') return onIdentityValues()
|
|
181
|
-
if (choice === 'prepare-transfer') return onPrepareTransfer()
|
|
182
|
-
if (choice === 'storage') return onStorage()
|
|
183
|
-
if (choice === 'load') return onLoad()
|
|
184
|
-
if (choice === 'create') return onCreate()
|
|
185
|
-
}}
|
|
186
|
-
onCancel={mode === 'first-run' ? undefined : onCancel}
|
|
187
|
-
/>
|
|
188
|
-
</Box>
|
|
189
|
-
</Surface>
|
|
190
|
-
)
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function renderReconciliationBanner(r: AgentReconciliation, identity: EthagentIdentity): React.ReactNode {
|
|
194
|
-
if (r.token === 'no-agent') return null
|
|
195
|
-
if (r.token === 'unlinked') {
|
|
196
|
-
const tokenLabel = r.tokenAgentId ? `Token #${r.tokenAgentId}` : 'Token'
|
|
197
|
-
const transferSnapshot = transferSnapshotView(identity)
|
|
198
|
-
if (transferSnapshot) {
|
|
199
|
-
return (
|
|
200
|
-
<>
|
|
201
|
-
<Text color={theme.accentError} bold>Agent Unlinked</Text>
|
|
202
|
-
<Text color={theme.textSubtle}>{tokenLabel} was transferred. Local SOUL.md, MEMORY.md, and skills remain. Back them up before this directory is reused.</Text>
|
|
203
|
-
<Text color={theme.textSubtle}>Use Switch Agent or New Agent to re-enable disabled actions.</Text>
|
|
204
|
-
</>
|
|
205
|
-
)
|
|
206
|
-
}
|
|
207
|
-
return (
|
|
208
|
-
<>
|
|
209
|
-
<Text color={theme.accentError} bold>Agent Unlinked</Text>
|
|
210
|
-
<Text color={theme.textSubtle}>{tokenLabel} left without Prepare Transfer. Back up local SOUL.md, MEMORY.md, and skills before loading another agent.</Text>
|
|
211
|
-
<Text color={theme.textSubtle}>For continuity handoff: ask the new holder to return the token, then run Prepare Transfer before re-sending.</Text>
|
|
212
|
-
<Text color={theme.textSubtle}>Use Switch Agent or New Agent to re-enable disabled actions.</Text>
|
|
213
|
-
</>
|
|
214
|
-
)
|
|
215
|
-
}
|
|
216
|
-
if (r.token === 'unknown') {
|
|
217
|
-
return (
|
|
218
|
-
<>
|
|
219
|
-
<Text color={theme.dim}>Ownership Check Failed (RPC?)</Text>
|
|
220
|
-
{r.tokenDetail ? <Text color={theme.dim}>{r.tokenDetail}</Text> : null}
|
|
221
|
-
</>
|
|
222
|
-
)
|
|
223
|
-
}
|
|
224
|
-
if (r.driftCount === 0) {
|
|
225
|
-
return null
|
|
226
|
-
}
|
|
227
|
-
const lines: string[] = []
|
|
228
|
-
if (r.custody === 'mid-flow-uri-pending') lines.push('Advanced setup pending. Open Custody Mode to finish.')
|
|
229
|
-
if (r.agentUri === 'local-newer') lines.push('Local state newer than onchain. Save Snapshot Now to publish.')
|
|
230
|
-
if (r.agentUri === 'chain-newer') lines.push('Onchain agentURI is newer than local. Refetch Latest.')
|
|
231
|
-
if (r.vault === 'missing') lines.push('Recorded vault address has no contract at it. Open Custody Mode to redeploy.')
|
|
232
|
-
if (r.workingTree === 'dirty') lines.push('Local edits pending. Save Snapshot Now to publish.')
|
|
233
|
-
return (
|
|
234
|
-
<>
|
|
235
|
-
<Text color={theme.accentPeriwinkle} bold>Agent Linked. {lines.length} item{lines.length === 1 ? '' : 's'} need attention</Text>
|
|
236
|
-
{lines.map((line, i) => (
|
|
237
|
-
<Text key={i} color={theme.textSubtle}>· {line}</Text>
|
|
238
|
-
))}
|
|
239
|
-
</>
|
|
240
|
-
)
|
|
241
|
-
}
|