ethagent 2.0.1 → 2.0.2

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/README.md CHANGED
@@ -15,7 +15,7 @@ ethagent binds an AI agent to a wallet-owned ERC-8004 token. Soul and memory sta
15
15
  | --- | --- |
16
16
  | Owner Wallet | Holds and controls the ERC-8004 agent token. Signs custody changes and, in Simple custody, every URI rotation. |
17
17
  | Operator Wallet | Additional wallet authorized to rotate the onchain URI on behalf of the owner. Used in Advanced custody. Never receives token approval. |
18
- | Operator Delegation Vault | Immutable contract deployed per agent token in Advanced custody. Each new vault holds at most one ERC-8004 token. |
18
+ | OperatorVault | Immutable per-agent custody contract used in Advanced custody. Holds at most one ERC-8004 token. |
19
19
  | Snapshot | Encrypted bundle of SOUL.md, MEMORY.md, and session state. Pinned to IPFS; decrypts only against the owner wallet's signature. |
20
20
  | Agent URI | IPFS URI stored in the ERC-8004 `tokenURI`. Resolves to the agent's published metadata. |
21
21
  | Agent Card | Public JSON describing the agent: name, description, capabilities, and skills. Other agents fetch it for discovery. |
@@ -50,7 +50,7 @@ The Identity Hub manages everything portable about the agent:
50
50
 
51
51
  - **Public Profile** edits name, description, icon, and the Agent Card.
52
52
  - **ENS Name** links the agent to a subdomain and authorizes operator wallets to write the subdomain's records.
53
- - **Custody Mode** switches between Simple and Advanced by depositing the token into its agent vault or unwrapping it back out.
53
+ - **Custody Mode** switches between Simple and Advanced by depositing the token into its OperatorVault or unwrapping it back out.
54
54
  - **Prepare Transfer** stages a dual-wallet snapshot before sending the token externally.
55
55
  - **Refetch Latest** pulls the most recent published snapshot back to local files.
56
56
  - **Load Agent** accepts either an ENS name or a bare token ID, and loads any agent owned by or linked to the connected wallet.
@@ -81,7 +81,7 @@ Custody comes in two modes. Switch between them anytime from **Custody Mode**.
81
81
 
82
82
  **Advanced** splits an owner wallet from one or more operator wallets. The **owner wallet** owns this agent's dedicated OperatorVault; one or more **operator wallets** handle routine URI rotations through that vault. Use Advanced when routine saves should not require an owner signature.
83
83
 
84
- Granting an operator wallet ERC-721 approval would let it rotate the URI, but that same approval also lets it transfer the token away. The agent vault holds the token instead and exposes only a URI-rotation lane for that agent. Operators never receive token approval or transfer rights, cannot touch ENS, and cannot grant rights to other operators. The owner still signs to authorize or revoke operators for the agent, withdraw the token, or transfer the agent.
84
+ Granting an operator wallet ERC-721 approval would let it rotate the URI, but that same approval also lets it transfer the token away. The OperatorVault holds the token instead and exposes only a URI-rotation lane for that agent. Operators never receive token approval or transfer rights, cannot touch ENS, and cannot grant rights to other operators. The owner still signs to authorize or revoke operators for the agent, withdraw the token, or transfer the agent.
85
85
 
86
86
  The vault is an immutable Foundry contract at `contracts/src/OperatorVault.sol`. New vault deployments are dedicated per agent token and reject any other token.
87
87
 
@@ -95,7 +95,7 @@ Save the token ID + network somewhere safe. ENS records can be cleared and rebui
95
95
 
96
96
  ## Token Transfers
97
97
 
98
- **Prepare Token Transfer** runs before any ERC-8004 token transfer, and only when the token sits directly in your wallet. An agent in Advanced custody has to switch to Simple first from Custody Mode, which unwraps the token from its agent vault back to the owner wallet.
98
+ **Prepare Token Transfer** runs before any ERC-8004 token transfer, and only when the token sits directly in your wallet. An agent in Advanced custody has to switch to Simple first from Custody Mode, which unwraps the token from its OperatorVault back to the owner wallet.
99
99
 
100
100
  - sender signs snapshot access, receiver signs restore access.
101
101
  - Sender publishes the snapshot pointer to the agent URI.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ethagent",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "A privacy-first AI agent with a portable Ethereum identity",
5
5
  "type": "module",
6
6
  "main": "bin/ethagent.js",
@@ -88,7 +88,7 @@ export const IdentitySummary: React.FC<IdentitySummaryProps> = ({ identity, conf
88
88
  if (!vaultAddress) return null
89
89
  return (
90
90
  <Text>
91
- <Text color={theme.dim}>{'Agent Vault'.padEnd(12)}</Text>
91
+ <Text color={theme.dim}>{'OperatorVault'.padEnd(12)}</Text>
92
92
  <Text color={theme.text}>{shortAddress(vaultAddress)}</Text>
93
93
  </Text>
94
94
  )
@@ -91,7 +91,7 @@ export const MenuScreen: React.FC<MenuScreenProps> = ({
91
91
  : null)
92
92
 
93
93
  const walletSetupBaseHint = custodyMode === 'advanced'
94
- ? 'Advanced. Owner wallet, agent vault, authorized operator wallets'
94
+ ? 'Advanced. Owner wallet, OperatorVault, authorized operator wallets'
95
95
  : 'Simple. Switch to Advanced to delegate URI rotation through a dedicated OperatorVault'
96
96
 
97
97
  const walletSetupLabel = flags?.custodyAsterisk ? 'Custody Mode *' : 'Custody Mode'
@@ -435,7 +435,7 @@ async function runOperatorWalletVaultPublicProfileSave(args: {
435
435
 
436
436
  await callbacks.onIdentityComplete(
437
437
  nextIdentity,
438
- 'Profile updated. ERC-8004 metadata published through the operator delegation vault.',
438
+ 'Profile updated. ERC-8004 metadata published through the OperatorVault.',
439
439
  'update',
440
440
  )
441
441
  } finally {
@@ -616,10 +616,10 @@ async function assertVaultSignerCanRotateAgentUri(args: {
616
616
  args: [registryAddress, args.agentId],
617
617
  }) as Address)
618
618
  } catch (err: unknown) {
619
- throw new Error(`Could not verify operator delegation vault custody for agent #${args.agentId.toString()}: ${err instanceof Error ? err.message : String(err)}`)
619
+ throw new Error(`Could not verify OperatorVault custody for agent #${args.agentId.toString()}: ${err instanceof Error ? err.message : String(err)}`)
620
620
  }
621
621
  if (vaultOwner === '0x0000000000000000000000000000000000000000') {
622
- throw new Error(`Operator delegation vault ${vaultAddress} does not currently hold agent token #${args.agentId.toString()}. Connect the owner wallet and run "Fix Records" or return the token to the vault before retrying.`)
622
+ throw new Error(`OperatorVault ${vaultAddress} does not currently hold agent token #${args.agentId.toString()}. Connect the owner wallet and run "Fix Records" or return the token to the vault before retrying.`)
623
623
  }
624
624
  if (vaultOwner.toLowerCase() === signer.toLowerCase()) return
625
625
 
@@ -632,7 +632,7 @@ async function assertVaultSignerCanRotateAgentUri(args: {
632
632
  if (isOperator) return
633
633
 
634
634
  throw new Error(
635
- `Operator wallet ${signer} is not yet authorized on the operator delegation vault to rotate this agent's URI. Connect the owner wallet and run "Fix Records" or re-add this operator to grant the permission.`,
635
+ `Operator wallet ${signer} is not yet authorized on the OperatorVault to rotate this agent's URI. Connect the owner wallet and run "Fix Records" or re-add this operator to grant the permission.`,
636
636
  )
637
637
  }
638
638
 
@@ -220,7 +220,7 @@ async function runOperatorWalletVaultPublish(args: {
220
220
  }) as boolean
221
221
  if (!isOperator) {
222
222
  throw new Error(
223
- `Operator wallet ${expectedSigner} is not yet authorized on the operator delegation vault to rotate this agent's URI. Connect the owner wallet and run "Fix Records" or re-add this operator to grant the permission.`,
223
+ `Operator wallet ${expectedSigner} is not yet authorized on the OperatorVault to rotate this agent's URI. Connect the owner wallet and run "Fix Records" or re-add this operator to grant the permission.`,
224
224
  )
225
225
  }
226
226
 
@@ -344,8 +344,8 @@ async function runOperatorWalletVaultPublish(args: {
344
344
  }
345
345
 
346
346
  const completionMessage = nextEnsName !== undefined && nextEnsName !== ((step.identity.state as Record<string, unknown> | undefined)?.ensName as string | undefined)
347
- ? 'Snapshot published onchain through the operator delegation vault. ENS records remain owner-signed, switch to the owner wallet to update them.'
348
- : 'Snapshot published onchain through the operator delegation vault.'
347
+ ? 'Snapshot published onchain through the OperatorVault. ENS records remain owner-signed, switch to the owner wallet to update them.'
348
+ : 'Snapshot published onchain through the OperatorVault.'
349
349
 
350
350
  return {
351
351
  to: vaultCall.to,
@@ -7,14 +7,14 @@ import { readCustodyMode } from '../../model/custody.js'
7
7
 
8
8
  export class OperatorVaultUnavailableError extends Error {
9
9
  constructor(chainId: number) {
10
- super(`Operator delegation vault is not deployed for chainId ${chainId}. Switching custody mode is unavailable until a deployment is recorded.`)
10
+ super(`OperatorVault is not deployed for chainId ${chainId}. Switching custody mode is unavailable until a deployment is recorded.`)
11
11
  this.name = 'OperatorVaultUnavailableError'
12
12
  }
13
13
  }
14
14
 
15
15
  export class TokenInVaultError extends Error {
16
16
  constructor(public vaultAddress: Address) {
17
- super('Token is in the operator delegation vault. Withdraw it first to prepare a transfer.')
17
+ super('Token is in the OperatorVault. Withdraw it first to prepare a transfer.')
18
18
  this.name = 'TokenInVaultError'
19
19
  }
20
20
  }
@@ -128,7 +128,7 @@ export const CreateFlow: React.FC<CreateFlowProps> = ({
128
128
  { value: 'simple', role: 'section', label: 'Simple (Recommended)' },
129
129
  { value: 'simple', label: 'Simple', hint: 'One wallet owns the token, signs every save, and rotates the URI directly' },
130
130
  { value: 'advanced', role: 'section', label: 'Advanced' },
131
- { value: 'advanced', label: 'Advanced', hint: 'Operator delegation vault holds the token; owner wallet controls vault, operator wallets get URI-rotation permission' },
131
+ { value: 'advanced', label: 'Advanced', hint: 'OperatorVault holds the token; owner wallet controls vault, operator wallets get URI-rotation permission' },
132
132
  ]}
133
133
  hintLayout="inline"
134
134
  onSubmit={onCustodySubmit}
@@ -182,7 +182,7 @@ export const CreateFlow: React.FC<CreateFlowProps> = ({
182
182
  title={isAdvanced ? 'Connect Owner Wallet' : 'Sign in Wallet'}
183
183
  subtitle={
184
184
  isAdvanced
185
- ? 'This wallet will own the agent token and control the delegation vault. Operator wallets are configured after minting.'
185
+ ? 'This wallet will own the agent token and control the OperatorVault. Operator wallets are configured after minting.'
186
186
  : 'One browser flow signs, saves the IPFS backup, and submits the token transaction.'
187
187
  }
188
188
  walletSession={walletSession}
@@ -95,7 +95,7 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
95
95
  const isAdvanced = onChainCustody === 'advanced' || midFlow || custodyMode === 'advanced'
96
96
  const vaultHolds = onChainCustody === 'advanced' || midFlow
97
97
  const subtitle = midFlow
98
- ? 'Advanced setup pending. This agent vault holds your token. Finish by publishing the first onchain update.'
98
+ ? 'Advanced setup pending. This OperatorVault holds your token. Finish by publishing the first onchain update.'
99
99
  : isAdvanced
100
100
  ? 'Advanced is active. Authorized operator wallets publish updates for this agent without an owner signature each time.'
101
101
  : 'Simple is active. One wallet owns the token and signs every update.'
@@ -106,7 +106,7 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
106
106
  options.push({
107
107
  value: 'resume-advanced',
108
108
  label: 'Resume Advanced Setup',
109
- hint: 'Sign once to publish onchain and finish the agent-vault switch.',
109
+ hint: 'Sign once to publish onchain and finish the OperatorVault switch.',
110
110
  })
111
111
  options.push({
112
112
  value: 'cancel-advanced',
@@ -139,7 +139,7 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
139
139
  options.push({
140
140
  value: 'return-to-vault',
141
141
  label: 'Return Token to Vault',
142
- hint: 'Redeposit this token to its agent vault. No redeploy, no operator re-add.',
142
+ hint: 'Redeposit this token to its OperatorVault. No redeploy, no operator re-add.',
143
143
  })
144
144
  }
145
145
  options.push({ value: 'manage-operator-wallets', role: 'section', label: 'Operators' })
@@ -184,7 +184,7 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
184
184
  })()}
185
185
  <Row label="Custody" value={modeLabel} />
186
186
  <Row label="Owner" value={shortAddress(ownerAddress || tokenOwner)} />
187
- {isAdvanced && vaultAddress ? <Row label="Agent Vault" value={shortAddress(vaultAddress)} /> : null}
187
+ {isAdvanced && vaultAddress ? <Row label="OperatorVault" value={shortAddress(vaultAddress)} /> : null}
188
188
  {isAdvanced ? (
189
189
  <Row
190
190
  label="Operators"
@@ -271,7 +271,7 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
271
271
  <Select<Action>
272
272
  options={[
273
273
  { value: 'confirm', role: 'section', label: 'Confirm' },
274
- { value: 'confirm', label: 'Yes, Switch to Advanced', hint: `Sign with ${shortAddress(ownerAddress || tokenOwner)} to deposit this token into its agent vault` },
274
+ { value: 'confirm', label: 'Yes, Switch to Advanced', hint: `Sign with ${shortAddress(ownerAddress || tokenOwner)} to deposit this token into its OperatorVault` },
275
275
  { value: 'transfer', role: 'section', label: 'Move Token First' },
276
276
  { value: 'transfer', label: 'Prepare Token Transfer', hint: 'Move the token to a different wallet first, with snapshot handoff' },
277
277
  { value: 'back', role: 'section', label: 'Cancel' },
@@ -300,7 +300,7 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
300
300
  return (
301
301
  <Surface
302
302
  title="Switch to Simple"
303
- subtitle="Unwraps this ERC-8004 token from its agent vault and returns it directly to the owner wallet."
303
+ subtitle="Unwraps this ERC-8004 token from its OperatorVault and returns it directly to the owner wallet."
304
304
  footer={footerHint('enter confirm · esc back')}
305
305
  >
306
306
  <Box flexDirection="column">
@@ -309,13 +309,13 @@ export const CustodyEditFlow: React.FC<CustodyEditFlowProps> = ({
309
309
  <Text> </Text>
310
310
  <Text color={theme.accentBlue}>Operators lose decrypt access on future snapshots immediately.</Text>
311
311
  <Text color={theme.textSubtle}>Operator approvals are cleared from local state for future snapshots. Revoke onchain via Manage Operators first if needed.</Text>
312
- <Text color={theme.textSubtle}>This switch calls the agent vault's unwrap function for this token, so the owner wallet must sign the transaction.</Text>
312
+ <Text color={theme.textSubtle}>This switch calls the OperatorVault unwrap function for this token, so the owner wallet must sign the transaction.</Text>
313
313
  </Box>
314
314
  <Box marginTop={1}>
315
315
  <Select<Action>
316
316
  options={[
317
317
  { value: 'confirm', role: 'section', label: 'Confirm' },
318
- { value: 'confirm', label: 'Yes, Switch to Simple', hint: `Sign with the owner wallet to unwrap ${tokenLabel} from its agent vault` },
318
+ { value: 'confirm', label: 'Yes, Switch to Simple', hint: `Sign with the owner wallet to unwrap ${tokenLabel} from its OperatorVault` },
319
319
  { value: 'back', role: 'section', label: 'Cancel' },
320
320
  { value: 'back', label: 'No, Go Back', hint: 'Return without changing custody', role: 'utility' },
321
321
  ]}
@@ -86,9 +86,9 @@ async function runVaultDeployTransactionInner(args: {
86
86
  })
87
87
  args.callbacks.onWalletReady(null)
88
88
  const client = args.publicClient ?? createErc8004PublicClient(args.registry)
89
- const receipt = await awaitConfirmedReceipt(client, result.txHash, 'Operator delegation vault deploy', { kind: 'vault-deploy', chainId: args.registry.chainId })
89
+ const receipt = await awaitConfirmedReceipt(client, result.txHash, 'OperatorVault deploy', { kind: 'vault-deploy', chainId: args.registry.chainId })
90
90
  if (!receipt.contractAddress) {
91
- throw new Error('Operator delegation vault deploy receipt is missing contractAddress; the transaction was not a contract creation')
91
+ throw new Error('OperatorVault deploy receipt is missing contractAddress; the transaction was not a contract creation')
92
92
  }
93
93
  const vaultAddress = getAddress(receipt.contractAddress)
94
94
  await assertVaultBytecode(client, vaultAddress, result.txHash)
@@ -114,7 +114,7 @@ async function runVaultDepositTransactionInner(args: {
114
114
  }): Promise<{ txHash: string }> {
115
115
  const { identity, registry, vaultAddress } = args
116
116
  if (!identity.agentId) {
117
- throw new Error('Cannot deposit token to operator delegation vault: agent token ID is missing')
117
+ throw new Error('Cannot deposit token to OperatorVault: agent token ID is missing')
118
118
  }
119
119
  const tokenOwner = getAddress(identity.ownerAddress ?? identity.address)
120
120
  await assertVaultCanAcceptAgent({
@@ -152,7 +152,7 @@ async function runVaultDepositTransactionInner(args: {
152
152
  await awaitConfirmedReceipt(
153
153
  depositClient,
154
154
  result.txHash as Hex,
155
- 'Operator delegation vault deposit',
155
+ 'OperatorVault deposit',
156
156
  { kind: 'vault-deposit', chainId: registry.chainId },
157
157
  )
158
158
  return { txHash: result.txHash }
@@ -179,9 +179,9 @@ async function assertVaultCanAcceptAgent(args: {
179
179
  const expectedRegistry = getAddress(args.registry.identityRegistryAddress)
180
180
  const sameAgent = heldRegistry.toLowerCase() === expectedRegistry.toLowerCase() && heldAgentId === args.agentId
181
181
  if (sameAgent) {
182
- throw new Error(`Agent vault ${getAddress(args.vaultAddress)} already holds ERC-8004 token #${args.agentId.toString()}. Publish the pending update instead of depositing again.`)
182
+ throw new Error(`OperatorVault ${getAddress(args.vaultAddress)} already holds ERC-8004 token #${args.agentId.toString()}. Publish the pending update instead of depositing again.`)
183
183
  }
184
- throw new Error(`Agent vault ${getAddress(args.vaultAddress)} already holds ERC-8004 token #${heldAgentId.toString()} for registry ${getAddress(heldRegistry)}. Deploy a fresh vault for this agent.`)
184
+ throw new Error(`OperatorVault ${getAddress(args.vaultAddress)} already holds ERC-8004 token #${heldAgentId.toString()} for registry ${getAddress(heldRegistry)}. Deploy a fresh vault for this agent.`)
185
185
  }
186
186
 
187
187
  export async function runVaultUnwrapTransaction(args: {
@@ -206,7 +206,7 @@ async function runVaultUnwrapTransactionInner(args: {
206
206
  const { identity, registry, vaultAddress } = args
207
207
  const targetAgentId = args.agentId ?? (identity.agentId ? BigInt(identity.agentId) : undefined)
208
208
  if (targetAgentId === undefined) {
209
- throw new Error('Cannot unwrap token from operator delegation vault: agent token ID is missing')
209
+ throw new Error('Cannot unwrap token from OperatorVault: agent token ID is missing')
210
210
  }
211
211
  const baseState = (identity.state ?? {}) as Record<string, unknown>
212
212
  const ownerAddressRaw = readOwnerAddressField(baseState)
@@ -240,7 +240,7 @@ async function runVaultUnwrapTransactionInner(args: {
240
240
  await awaitConfirmedReceipt(
241
241
  publicClient,
242
242
  result.txHash as Hex,
243
- 'Operator delegation vault unwrap',
243
+ 'OperatorVault unwrap',
244
244
  { kind: 'vault-unwrap', chainId: registry.chainId },
245
245
  )
246
246
  await confirmAgentWithdrawnFromVault({
@@ -307,7 +307,7 @@ async function runVaultWithdrawTransactionInner(args: {
307
307
  await awaitConfirmedReceipt(
308
308
  publicClient,
309
309
  result.txHash as Hex,
310
- 'Operator delegation vault withdraw',
310
+ 'OperatorVault withdraw',
311
311
  { kind: 'vault-withdraw', chainId: registry.chainId },
312
312
  )
313
313
  await confirmAgentWithdrawnFromVault({
@@ -49,7 +49,7 @@ export function createCustodyFlowActions({
49
49
  }
50
50
  if (status.inVault) {
51
51
  handleStepError(
52
- new Error(`Recovered operator delegation vault ${recoveredVault} holds the token, but the vault-level depositor is ${status.ownerAddress ?? 'unknown'}, not your wallet ${expectedOwnerForDiscovery}. Mid-flow recovery requires the original depositor's wallet to call vault.unwrap.`),
52
+ new Error(`Recovered OperatorVault ${recoveredVault} holds the token, but the vault-level depositor is ${status.ownerAddress ?? 'unknown'}, not your wallet ${expectedOwnerForDiscovery}. Mid-flow recovery requires the original depositor's wallet to call vault.unwrap.`),
53
53
  { kind: 'custody-model', identity: currentStep.identity, registry, returnTo },
54
54
  )
55
55
  return
@@ -95,7 +95,7 @@ export function createCustodyFlowActions({
95
95
  }
96
96
  if (status.inVault) {
97
97
  handleStepError(
98
- new Error(`Token is held by the operator delegation vault, but the vault-level owner is ${status.ownerAddress ?? 'unknown'}, not your wallet ${expectedOwner}. Recovery requires that wallet to call vault.unwrap.`),
98
+ new Error(`Token is held by the OperatorVault, but the vault-level owner is ${status.ownerAddress ?? 'unknown'}, not your wallet ${expectedOwner}. Recovery requires that wallet to call vault.unwrap.`),
99
99
  { kind: 'custody-model', identity: currentStep.identity, registry, returnTo },
100
100
  )
101
101
  return
@@ -127,7 +127,7 @@ export function createCustodyFlowActions({
127
127
  const vaultAddress = resolveOperatorVaultAddress(currentStep.identity, config?.erc8004?.operatorVaults)
128
128
  if (!vaultAddress) {
129
129
  handleStepError(
130
- new Error('No agent vault is recorded for this identity. There is nothing to withdraw.'),
130
+ new Error('No OperatorVault is recorded for this identity. There is nothing to withdraw.'),
131
131
  { kind: 'custody-model', identity: currentStep.identity, registry: currentStep.registry, returnTo },
132
132
  )
133
133
  return
@@ -160,7 +160,7 @@ export function createCustodyFlowActions({
160
160
  if (status.inVault) {
161
161
  if (status.ownerAddress && status.ownerAddress.toLowerCase() !== depositor.toLowerCase()) {
162
162
  handleStepError(
163
- new Error(`Agent vault holds token #${activeAgentId} but recorded the depositor as ${status.ownerAddress}, not your wallet ${depositor}. Only the original depositor can withdraw.`),
163
+ new Error(`OperatorVault holds token #${activeAgentId} but recorded the depositor as ${status.ownerAddress}, not your wallet ${depositor}. Only the original depositor can withdraw.`),
164
164
  { kind: 'custody-model', identity: currentStep.identity, registry: currentStep.registry, returnTo },
165
165
  )
166
166
  return
@@ -176,7 +176,7 @@ export function createCustodyFlowActions({
176
176
  return
177
177
  }
178
178
  handleStepError(
179
- new Error(`Token #${activeAgentId} is not currently in the agent vault. There is nothing to withdraw; the token is already with the owner wallet.`),
179
+ new Error(`Token #${activeAgentId} is not currently in the OperatorVault. There is nothing to withdraw; the token is already with the owner wallet.`),
180
180
  { kind: 'custody-model', identity: currentStep.identity, registry: currentStep.registry, returnTo },
181
181
  )
182
182
  } catch (err: unknown) {
@@ -25,7 +25,7 @@ export function useCustodyTransactionEffects({
25
25
  let cancelled = false
26
26
  if (!step.identity.agentId) {
27
27
  handleStepError(
28
- new Error('Cannot deploy agent vault: agent token ID is missing'),
28
+ new Error('Cannot deploy OperatorVault: agent token ID is missing'),
29
29
  { kind: 'custody-model', identity: step.identity, registry: step.registry, returnTo: step.returnTo },
30
30
  )
31
31
  return () => { cancelled = true }
@@ -24,7 +24,7 @@ export function renderCustodyStep({
24
24
  if (step.kind === 'custody-vault-deploy-tx') {
25
25
  return (
26
26
  <WalletApprovalScreen
27
- title="Deploy Operator Delegation Vault"
27
+ title="Deploy OperatorVault"
28
28
  subtitle={`Deploying a dedicated OperatorVault for this ERC-8004 token on ${chainLabel(step.registry.chainId)}.`}
29
29
  walletSession={walletSession}
30
30
  label="waiting for owner wallet transaction..."
@@ -35,8 +35,8 @@ export function renderCustodyStep({
35
35
  if (step.kind === 'custody-vault-deposit-tx') {
36
36
  return (
37
37
  <WalletApprovalScreen
38
- title="Deposit Token Into Operator Delegation Vault"
39
- subtitle={`Sign one ${chainLabel(step.registry.chainId)} transaction. Sends ERC-8004 token #${step.identity.agentId ?? ''} to its agent vault.`}
38
+ title="Deposit Token Into OperatorVault"
39
+ subtitle={`Sign one ${chainLabel(step.registry.chainId)} transaction. Sends ERC-8004 token #${step.identity.agentId ?? ''} to its OperatorVault.`}
40
40
  walletSession={walletSession}
41
41
  label="waiting for token-owner wallet transaction..."
42
42
  onCancel={() => setStep({ kind: 'custody-model', identity: step.identity, registry: step.registry, returnTo: step.returnTo })}
@@ -49,8 +49,8 @@ export function renderCustodyStep({
49
49
  <Surface
50
50
  title="Checking Vault"
51
51
  subtitle={targetAgentId
52
- ? `Confirming the agent vault holds ERC-8004 token #${targetAgentId} on ${chainLabel(step.registry.chainId)}.`
53
- : `Checking this identity's recorded agent vault on ${chainLabel(step.registry.chainId)}.`}
52
+ ? `Confirming the OperatorVault holds ERC-8004 token #${targetAgentId} on ${chainLabel(step.registry.chainId)}.`
53
+ : `Checking this identity's recorded OperatorVault on ${chainLabel(step.registry.chainId)}.`}
54
54
  footer={<Text color={theme.dim}>esc cancel</Text>}
55
55
  >
56
56
  <Box marginTop={1}>
@@ -64,7 +64,7 @@ export function renderCustodyStep({
64
64
  return (
65
65
  <WalletApprovalScreen
66
66
  title="Withdraw Token"
67
- subtitle={`Unwraps ERC-8004 token #${targetAgentId} from its agent vault to your owner wallet on ${chainLabel(step.registry.chainId)}.`}
67
+ subtitle={`Unwraps ERC-8004 token #${targetAgentId} from its OperatorVault to your owner wallet on ${chainLabel(step.registry.chainId)}.`}
68
68
  walletSession={walletSession}
69
69
  label="waiting for owner wallet transaction..."
70
70
  onCancel={() => setStep({ kind: 'custody-model', identity: step.identity, registry: step.registry, returnTo: step.returnTo })}
@@ -135,7 +135,7 @@ export function renderCustodyStep({
135
135
  return (
136
136
  <Surface
137
137
  title="Token Returned to Owner Wallet"
138
- subtitle={`Token returned to ${shortAddress(step.recipient)} on ${chainLabel(step.registry.chainId)}. The agent vault can be reused for this token.`}
138
+ subtitle={`Token returned to ${shortAddress(step.recipient)} on ${chainLabel(step.registry.chainId)}. The OperatorVault can be reused for this token.`}
139
139
  footer={<Text color={theme.dim}>enter select · esc back</Text>}
140
140
  >
141
141
  <Box flexDirection="column">
@@ -149,7 +149,7 @@ export function renderCustodyStep({
149
149
  <Select<'return-to-vault' | 'keep-out'>
150
150
  options={[
151
151
  { value: 'return-to-vault', role: 'section', label: 'Resume Advanced Custody' },
152
- { value: 'return-to-vault', label: 'Return Token to Vault', hint: 'Redeposit to this agent vault. No redeploy, no operator re-add' },
152
+ { value: 'return-to-vault', label: 'Return Token to Vault', hint: 'Redeposit to this OperatorVault. No redeploy, no operator re-add' },
153
153
  { value: 'keep-out', role: 'section', label: 'Later' },
154
154
  { value: 'keep-out', label: 'Keep Out For Now', hint: 'Token stays with the owner wallet; redeposit any time from Custody Mode', role: 'utility' },
155
155
  ]}
@@ -167,8 +167,8 @@ export function renderCustodyStep({
167
167
  if (step.kind === 'custody-vault-unwrap-tx') {
168
168
  return (
169
169
  <WalletApprovalScreen
170
- title="Unwrap Token From Agent Vault"
171
- subtitle={`Sign one ${chainLabel(step.registry.chainId)} transaction. Calls the agent vault's unwrap function to return ERC-8004 token #${step.identity.agentId ?? ''} to the owner wallet.`}
170
+ title="Unwrap Token From OperatorVault"
171
+ subtitle={`Sign one ${chainLabel(step.registry.chainId)} transaction. Calls the OperatorVault unwrap function to return ERC-8004 token #${step.identity.agentId ?? ''} to the owner wallet.`}
172
172
  walletSession={walletSession}
173
173
  label="waiting for owner wallet transaction..."
174
174
  onCancel={() => setStep({ kind: 'custody-model', identity: step.identity, registry: step.registry, returnTo: step.returnTo })}
@@ -186,7 +186,7 @@ export function renderCustodyStep({
186
186
  footer={<Text color={theme.dim}>enter continues</Text>}
187
187
  >
188
188
  <Box flexDirection="column">
189
- {step.vaultAddress ? <Row label="Agent Vault" value={shortAddress(step.vaultAddress)} /> : null}
189
+ {step.vaultAddress ? <Row label="OperatorVault" value={shortAddress(step.vaultAddress)} /> : null}
190
190
  <Row label="Owner Wallet" value={shortAddress(ownerWallet)} />
191
191
  <Row label="Operator Wallets" value={operatorCount === 1 ? '1 approved' : `${operatorCount} approved`} />
192
192
  <Box marginTop={1}>
@@ -235,5 +235,5 @@ export function renderRebackupSubtitle(
235
235
  vaultRouted: boolean,
236
236
  ): React.ReactNode {
237
237
  if (!vaultRouted) return defaultSubtitle
238
- return <Text color={theme.textSubtle}>{defaultSubtitle} Routed through this token's agent vault.</Text>
238
+ return <Text color={theme.textSubtle}>{defaultSubtitle} Routed through this token's OperatorVault.</Text>
239
239
  }
@@ -89,7 +89,7 @@ export function renderAdvancedEnsPhase({
89
89
  <Box marginTop={1} flexDirection="column">
90
90
  <EnsSetupRow label="Owner wallet" value={`Holds ERC-8004 token #${agentId ?? 'unknown'} and signs ENS records.`} />
91
91
  <EnsSetupRow label="Operator wallet" value="Restores snapshots; never controls the token." />
92
- <EnsSetupRow label="Token moves" value="If the token is in the operator delegation vault, withdraw it first from Custody Mode." />
92
+ <EnsSetupRow label="Token moves" value="If the token is in the OperatorVault, withdraw it first from Custody Mode." />
93
93
  </Box>
94
94
  </Box>
95
95
  <Box marginTop={1}>
@@ -217,7 +217,7 @@ export function renderAdvancedEnsPhase({
217
217
  <Box flexDirection="column">
218
218
  <Text color={theme.dim}>Agent ENS: <Text color={theme.text}>{label}.{rootName}</Text></Text>
219
219
  {phase.registryAction ? <Text color={theme.dim}>{advancedSubdomainStatusText(phase.registryAction)}</Text> : null}
220
- <Text color={theme.dim}>Choose the operator wallet for snapshot restore access and onchain ERC-8004 URI rotation via the operator delegation vault.</Text>
220
+ <Text color={theme.dim}>Choose the operator wallet for snapshot restore access and onchain ERC-8004 URI rotation via the OperatorVault.</Text>
221
221
  <Text color={theme.dim}>The operator wallet has no authority over this ENS subdomain or any token transfer; the owner wallet is the sole signer for both.</Text>
222
222
  <Text color={theme.dim}>We only read the operator's address here so it can be added to the snapshot envelope and vault operator list later.</Text>
223
223
  {savedOperator ? <Text color={theme.dim}>Saved operator wallet: <Text color={theme.text}>{shortAddress(savedOperator)}</Text></Text> : null}
@@ -218,9 +218,9 @@ export const EnsSetupBlockedScreen: React.FC<EnsSetupBlockedScreenProps> = ({
218
218
  ? (
219
219
  <>
220
220
  <Box marginTop={1} flexDirection="column">
221
- <Text color={theme.text}>To proceed: the owner wallet signs ENS records and must hold this token at setup time. Once setup is done you can deposit the token into the operator delegation vault while the ENS subdomain stays with the owner wallet.</Text>
221
+ <Text color={theme.text}>To proceed: the owner wallet signs ENS records and must hold this token at setup time. Once setup is done you can deposit the token into the OperatorVault while the ENS subdomain stays with the owner wallet.</Text>
222
222
  </Box>
223
- <Text color={theme.dim}>Operator wallets have no authority on this name; they only rotate the onchain ERC-8004 URI via the operator delegation vault.</Text>
223
+ <Text color={theme.dim}>Operator wallets have no authority on this name; they only rotate the onchain ERC-8004 URI via the OperatorVault.</Text>
224
224
  </>
225
225
  )
226
226
  : null}
@@ -21,7 +21,7 @@ export function copyableIdentityFields(identity?: EthagentIdentity, config?: Eth
21
21
  const custodyMode = readCustodyMode(identity.state)
22
22
  if (custodyMode === 'advanced') {
23
23
  const vaultAddress = readIdentityStateString(identity.state, 'operatorVaultAddress')
24
- if (vaultAddress) fields.push({ label: 'Agent Vault', value: vaultAddress })
24
+ if (vaultAddress) fields.push({ label: 'OperatorVault', value: vaultAddress })
25
25
  }
26
26
  const activeOperator = readIdentityStateString(identity.state, 'activeOperatorAddress')
27
27
  if (activeOperator) fields.push({ label: 'Operator Wallet', value: activeOperator })
@@ -85,7 +85,7 @@ async function runOwnershipPreflight(args: {
85
85
  return {
86
86
  ok: false,
87
87
  reason: 'not-owned',
88
- detail: `Token is held by the operator delegation vault (${directOwner.owner}). Withdraw it first.`,
88
+ detail: `Token is held by the OperatorVault (${directOwner.owner}). Withdraw it first.`,
89
89
  onChainOwner: directOwner.owner,
90
90
  }
91
91
  }
@@ -54,7 +54,7 @@ export async function validateErc8004TokenOwner(args: Erc8004RegistryConfig & {
54
54
  return {
55
55
  ok: false,
56
56
  reason: 'token-owner-lookup-failed',
57
- detail: `ERC-8004 token #${args.agentId.toString()} is still reported at the operator delegation vault, but that vault record is empty. Ownership is still settling; retry shortly.`,
57
+ detail: `ERC-8004 token #${args.agentId.toString()} is still reported at the OperatorVault, but that vault record is empty. Ownership is still settling; retry shortly.`,
58
58
  }
59
59
  }
60
60
  if (vaultOwnerResult.kind === 'error') {
@@ -73,7 +73,7 @@ export async function validateErc8004TokenOwner(args: Erc8004RegistryConfig & {
73
73
  ok: false,
74
74
  reason: 'token-owner-mismatch',
75
75
  ownerAddress: vaultOwner,
76
- detail: `ERC-8004 token #${args.agentId.toString()} is held by the operator delegation vault for ${vaultOwner}`,
76
+ detail: `ERC-8004 token #${args.agentId.toString()} is held by the OperatorVault for ${vaultOwner}`,
77
77
  }
78
78
  }
79
79
  return {
@@ -15,7 +15,7 @@ export class OperatorVaultBytecodeMismatchError extends Error {
15
15
  txHash?: Hex,
16
16
  ) {
17
17
  super(
18
- 'Deployed contract bytecode does not match the expected operator delegation vault. The deploy transaction may have been intercepted.',
18
+ 'Deployed contract bytecode does not match the expected OperatorVault. The deploy transaction may have been intercepted.',
19
19
  )
20
20
  this.name = 'OperatorVaultBytecodeMismatchError'
21
21
  this.vaultAddress = vaultAddress
@@ -97,7 +97,7 @@ export async function confirmAgentInVault(
97
97
  }
98
98
  if (lastErr) throw lastErr
99
99
  throw new Error(
100
- `Operator delegation vault ${getAddress(args.vaultAddress)} does not hold agent token #${args.agentId.toString()} for registry ${getAddress(args.registry)} after the deposit-confirmation budget was exhausted. The deposit transaction may have been re-orged or applied to the wrong vault. Re-run the switch.`,
100
+ `OperatorVault ${getAddress(args.vaultAddress)} does not hold agent token #${args.agentId.toString()} for registry ${getAddress(args.registry)} after the deposit-confirmation budget was exhausted. The deposit transaction may have been re-orged or applied to the wrong vault. Re-run the switch.`,
101
101
  )
102
102
  }
103
103
 
@@ -135,7 +135,7 @@ export async function confirmAgentWithdrawnFromVault(
135
135
  }
136
136
  if (lastErr) throw lastErr
137
137
  throw new Error(
138
- `Operator delegation vault ${getAddress(args.vaultAddress)} did not release agent token #${args.agentId.toString()} to ${recipient} after the withdraw-confirmation budget was exhausted. Last observed: ${lastObserved ?? 'unknown'}.`,
138
+ `OperatorVault ${getAddress(args.vaultAddress)} did not release agent token #${args.agentId.toString()} to ${recipient} after the withdraw-confirmation budget was exhausted. Last observed: ${lastObserved ?? 'unknown'}.`,
139
139
  )
140
140
  }
141
141
 
@@ -93,7 +93,7 @@ export const PURPOSE_COPY: Record<string, PurposeCopyEntry> = {
93
93
  flowTitle: "Operator Wallet Save",
94
94
  sign: { text: "Sign With Operator Wallet", hint: "Signs the encrypted snapshot for restore access." },
95
95
  prepare: { text: "Saving Snapshot...", hint: "Keep this page open." },
96
- transaction: { text: "Use Operator Wallet", hint: "Rotates the ERC-8004 token URI through the operator delegation vault." },
96
+ transaction: { text: "Use Operator Wallet", hint: "Rotates the ERC-8004 token URI through the OperatorVault." },
97
97
  },
98
98
  "update-snapshot-connected": {
99
99
  flowTitle: "Save Snapshot",
@@ -196,7 +196,7 @@ export const PURPOSE_COPY: Record<string, PurposeCopyEntry> = {
196
196
  "sync-operator-vault": {
197
197
  flowTitle: "Owner Wallet Required",
198
198
  prepare: { text: "Preparing Vault Operator Update...", hint: "Keep this page open." },
199
- transaction: { text: "Use Owner Wallet", hint: "Updates the operator delegation vault's metadata-operator list so authorized operator wallets can rotate the agent URI." },
199
+ transaction: { text: "Use Owner Wallet", hint: "Updates the OperatorVault metadata-operator list so authorized operator wallets can rotate the agent URI." },
200
200
  },
201
201
  "refetch-snapshot": {
202
202
  flowTitle: "Refetch Latest Snapshot",
@@ -219,39 +219,39 @@ export const PURPOSE_COPY: Record<string, PurposeCopyEntry> = {
219
219
  transaction: { text: "Use Sender Wallet", hint: "Submits one transaction to publish the transfer snapshot to the ERC-8004 token URI." },
220
220
  },
221
221
  "deploy-agent-vault": {
222
- flowTitle: "Deploy Operator Delegation Vault",
222
+ flowTitle: "Deploy OperatorVault",
223
223
  prepare: { text: "Preparing Vault Deploy...", hint: "Keep this page open." },
224
- transaction: { text: "Use Owner Wallet", hint: "Deploys the operator delegation vault contract onchain. One-time setup per agent." },
225
- errorContext: "While submitting the operator delegation vault deploy",
224
+ transaction: { text: "Use Owner Wallet", hint: "Deploys the OperatorVault contract onchain. One-time setup per agent." },
225
+ errorContext: "While submitting the OperatorVault deploy",
226
226
  },
227
227
  "deposit-agent-vault": {
228
228
  flowTitle: "Deposit Token Into Vault",
229
229
  prepare: { text: "Preparing Vault Deposit...", hint: "Keep this page open." },
230
- transaction: { text: "Use Owner Wallet", hint: "Sends the agent token to the operator delegation vault so the vault can save updates on your behalf." },
231
- errorContext: "While submitting the operator delegation vault deposit",
230
+ transaction: { text: "Use Owner Wallet", hint: "Sends the agent token to the OperatorVault so the vault can save updates on your behalf." },
231
+ errorContext: "While submitting the OperatorVault deposit",
232
232
  },
233
233
  "unwrap-agent-vault": {
234
234
  flowTitle: "Unwrap Token From Vault",
235
235
  prepare: { text: "Preparing Vault Unwrap...", hint: "Keep this page open." },
236
- transaction: { text: "Use Owner Wallet", hint: "Returns the agent token from the operator delegation vault to your owner wallet." },
236
+ transaction: { text: "Use Owner Wallet", hint: "Returns the agent token from the OperatorVault to your owner wallet." },
237
237
  },
238
238
  "rotate-agent-uri-vault-owner": {
239
239
  flowTitle: "Save Update Through Vault",
240
240
  sign: { text: "Sign With Owner Wallet", hint: "Approves the new snapshot before saving onchain. No token approval." },
241
241
  prepare: { text: "Preparing Update...", hint: "Keep this page open." },
242
- transaction: { text: "Use Owner Wallet", hint: "Saves your update onchain through the operator delegation vault. The vault holds your token, so updates go through it." },
242
+ transaction: { text: "Use Owner Wallet", hint: "Saves your update onchain through the OperatorVault. The vault holds your token, so updates go through it." },
243
243
  },
244
244
  "rotate-agent-uri-vault-operator": {
245
245
  flowTitle: "Save Update Through Vault",
246
246
  sign: { text: "Sign With Operator Wallet", hint: "Approves the new snapshot before saving onchain. No token approval." },
247
247
  prepare: { text: "Preparing Update...", hint: "Keep this page open." },
248
- transaction: { text: "Use Operator Wallet", hint: "Rotates the ERC-8004 token URI through the operator delegation vault. The vault holds your token, so the operator wallet calls the vault to publish." },
248
+ transaction: { text: "Use Operator Wallet", hint: "Rotates the ERC-8004 token URI through the OperatorVault. The vault holds your token, so the operator wallet calls the vault to publish." },
249
249
  },
250
250
  "withdraw-vault": {
251
251
  flowTitle: "Withdraw Token From Vault",
252
252
  prepare: { text: "Preparing Token Withdrawal...", hint: "Keep this page open." },
253
253
  transaction: { text: "Use Owner Wallet", hint: "Temporarily returns the agent token from the vault to your owner wallet. Vault stays configured so you can redeposit later." },
254
- errorContext: "While submitting the operator delegation vault withdraw",
254
+ errorContext: "While submitting the OperatorVault withdraw",
255
255
  },
256
256
  "register-root-commit": {
257
257
  flowTitle: "Commit ENS Name",
@@ -229,7 +229,7 @@ export function setConfiguredOperatorVaultAddress(
229
229
  vaultAddress: string,
230
230
  ): EthagentConfig {
231
231
  if (!config.erc8004) {
232
- throw new Error('Cannot record operator delegation vault address: erc8004 registry config is not set')
232
+ throw new Error('Cannot record OperatorVault address: erc8004 registry config is not set')
233
233
  }
234
234
  return {
235
235
  ...config,