ethagent 2.1.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/package.json +2 -1
  2. package/src/app/FirstRun.tsx +1 -7
  3. package/src/app/FirstRunTimeline.tsx +1 -1
  4. package/src/auth/openaiOAuth/credentials.ts +47 -0
  5. package/src/auth/openaiOAuth/crypto.ts +23 -0
  6. package/src/auth/openaiOAuth/index.ts +238 -0
  7. package/src/auth/openaiOAuth/landingPage.ts +125 -0
  8. package/src/auth/openaiOAuth/listener.ts +151 -0
  9. package/src/auth/openaiOAuth/refresh.ts +70 -0
  10. package/src/auth/openaiOAuth/shared.ts +115 -0
  11. package/src/chat/ChatBottomPane.tsx +20 -11
  12. package/src/chat/ChatScreen.tsx +160 -35
  13. package/src/chat/ConversationStack.tsx +1 -1
  14. package/src/chat/MessageList.tsx +185 -72
  15. package/src/chat/SessionStatus.tsx +3 -1
  16. package/src/chat/chatScreenUtils.ts +11 -15
  17. package/src/chat/chatSessionState.ts +3 -2
  18. package/src/chat/chatTurnOrchestrator.ts +1 -7
  19. package/src/chat/commands.ts +28 -27
  20. package/src/chat/display/DiffView.tsx +193 -0
  21. package/src/chat/display/SyntaxText.tsx +192 -0
  22. package/src/chat/display/toolCallDisplay.ts +103 -0
  23. package/src/chat/display/toolResultDisplay.ts +19 -0
  24. package/src/chat/{ChatInput.tsx → input/ChatInput.tsx} +36 -23
  25. package/src/chat/{TranscriptView.tsx → transcript/TranscriptView.tsx} +24 -50
  26. package/src/chat/{transcriptViewport.ts → transcript/transcriptViewport.ts} +12 -30
  27. package/src/chat/{ContextLimitView.tsx → views/ContextLimitView.tsx} +3 -3
  28. package/src/chat/{ContinuityEditReviewView.tsx → views/ContinuityEditReviewView.tsx} +11 -3
  29. package/src/chat/{CopyPicker.tsx → views/CopyPicker.tsx} +4 -5
  30. package/src/chat/{PermissionPrompt.tsx → views/PermissionPrompt.tsx} +16 -17
  31. package/src/chat/{PermissionsView.tsx → views/PermissionsView.tsx} +6 -6
  32. package/src/chat/{PlanApprovalView.tsx → views/PlanApprovalView.tsx} +4 -4
  33. package/src/chat/{ResumeView.tsx → views/ResumeView.tsx} +35 -35
  34. package/src/chat/views/RewindView.tsx +410 -0
  35. package/src/identity/continuity/privateEdit/diff.ts +2 -78
  36. package/src/identity/ens/agentRecords.ts +5 -19
  37. package/src/identity/ens/ensAutomation/setup.ts +0 -1
  38. package/src/identity/ens/ensAutomation/types.ts +0 -1
  39. package/src/identity/hub/OperationalRoutes.tsx +23 -32
  40. package/src/identity/hub/Routes.tsx +13 -13
  41. package/src/identity/hub/{flows/continuity → continuity}/ContinuityDashboardScreen.tsx +9 -9
  42. package/src/identity/hub/{flows/continuity → continuity}/RebackupStorageScreen.tsx +2 -2
  43. package/src/identity/hub/{flows/continuity → continuity}/RecoveryConfirmScreen.tsx +5 -5
  44. package/src/identity/hub/{flows/continuity → continuity}/SavePromptScreen.tsx +5 -5
  45. package/src/identity/hub/{effects/rebackup/runRebackup.ts → continuity/effects.ts} +19 -19
  46. package/src/identity/hub/{effects/rebackup → continuity}/index.ts +1 -1
  47. package/src/identity/hub/{effects/shared → continuity}/snapshot.ts +8 -8
  48. package/src/identity/hub/{effects/rebackup → continuity}/vault.ts +15 -15
  49. package/src/identity/hub/{flows/create → create}/CreateFlow.tsx +13 -13
  50. package/src/identity/hub/{effects/create.ts → create/effects.ts} +4 -4
  51. package/src/identity/hub/{flows/custody → custody}/CustodyEditFlow.tsx +10 -48
  52. package/src/identity/hub/{flows/custody/custodyFlowActions.ts → custody/actions.ts} +11 -9
  53. package/src/identity/hub/{flows/custody/custodyFlowHelpers.ts → custody/helpers.ts} +4 -4
  54. package/src/identity/hub/{effects/vault → custody}/preflight.ts +5 -5
  55. package/src/identity/hub/{flows/custody/custodyFlowRoutes.tsx → custody/routes.tsx} +8 -8
  56. package/src/identity/hub/{flows/custody/custodyEffects.ts → custody/transactions.ts} +9 -9
  57. package/src/identity/hub/{flows/custody/custodyFlowTypes.ts → custody/types.ts} +6 -6
  58. package/src/identity/hub/{flows/custody/custodyFlowEffects.ts → custody/useCustodyEffects.ts} +7 -7
  59. package/src/identity/hub/{flows/custody → custody}/useCustodyFlow.tsx +5 -5
  60. package/src/identity/hub/ens/EnsEditAdvancedScreens.tsx +241 -0
  61. package/src/identity/hub/{flows/ens → ens}/EnsEditFlow.tsx +27 -82
  62. package/src/identity/hub/{flows/ens → ens}/EnsEditMaintenanceScreens.tsx +25 -65
  63. package/src/identity/hub/{flows/ens → ens}/EnsEditReviewScreens.tsx +12 -30
  64. package/src/identity/hub/ens/EnsEditRunners.tsx +62 -0
  65. package/src/identity/hub/{flows/ens → ens}/EnsEditShared.tsx +15 -14
  66. package/src/identity/hub/{flows/ens → ens}/EnsEditSimpleScreens.tsx +68 -217
  67. package/src/identity/hub/{flows/ens/IdentityHubEnsFlow.tsx → ens/EnsFlow.tsx} +18 -11
  68. package/src/identity/hub/{flows/ens/OperatorWalletsScreen.tsx → ens/EnsOperatorWalletsScreen.tsx} +17 -48
  69. package/src/identity/hub/{advancedEnsValidation.ts → ens/advancedEnsValidation.ts} +2 -2
  70. package/src/identity/hub/{flows/ens/ensEditCopy.ts → ens/editCopy.ts} +4 -4
  71. package/src/identity/hub/{effects/ens/flows.ts → ens/effects.ts} +7 -7
  72. package/src/identity/hub/{effects/ens → ens}/index.ts +1 -1
  73. package/src/identity/hub/{model/ens.ts → ens/state.ts} +1 -1
  74. package/src/identity/hub/{effects/ens → ens}/transactions.ts +232 -232
  75. package/src/identity/hub/{flows/ens/ensEditTypes.ts → ens/types.ts} +12 -26
  76. package/src/identity/hub/identityHubReducer.ts +3 -3
  77. package/src/identity/hub/{flows/profile → profile}/EditProfileFlow.tsx +17 -10
  78. package/src/identity/hub/{effects/publicProfile/runPublicProfileSave.ts → profile/effects.ts} +55 -177
  79. package/src/identity/hub/{model → profile}/identity.ts +3 -3
  80. package/src/identity/hub/{effects/profile/profileState.ts → profile/state.ts} +181 -173
  81. package/src/identity/hub/{flows/restore → restore}/RestoreFlow.tsx +21 -21
  82. package/src/identity/hub/{effects/restore → restore}/apply.ts +10 -10
  83. package/src/identity/hub/{effects/restore → restore}/auth.ts +7 -7
  84. package/src/identity/hub/{effects/restore → restore}/discover.ts +6 -6
  85. package/src/identity/hub/{effects/restore → restore}/envelopes.ts +2 -2
  86. package/src/identity/hub/{effects/restore → restore}/fetch.ts +3 -3
  87. package/src/identity/hub/{effects/restore/shared.ts → restore/helpers.ts} +6 -6
  88. package/src/identity/hub/{effects/restore → restore}/recovery.ts +10 -10
  89. package/src/identity/hub/{effects/restore → restore}/resolve.ts +4 -4
  90. package/src/identity/hub/restore/restoreAdmin.ts +34 -0
  91. package/src/identity/hub/{flows/restore/useRestoreFlowEffects.ts → restore/useRestoreEffects.ts} +5 -5
  92. package/src/identity/hub/{flows/settings → settings}/StorageCredentialScreen.tsx +5 -5
  93. package/src/identity/hub/{components → shared/components}/BusyScreen.tsx +4 -4
  94. package/src/identity/hub/{components → shared/components}/DetailsScreen.tsx +4 -4
  95. package/src/identity/hub/{components → shared/components}/ErrorScreen.tsx +4 -4
  96. package/src/identity/hub/{components → shared/components}/FlowTimeline.tsx +1 -1
  97. package/src/identity/hub/{components → shared/components}/IdentitySummary.tsx +16 -11
  98. package/src/identity/hub/{components → shared/components}/MenuScreen.tsx +8 -9
  99. package/src/identity/hub/{components → shared/components}/NetworkScreen.tsx +4 -4
  100. package/src/identity/hub/{components → shared/components}/PinataJwtInput.tsx +4 -4
  101. package/src/identity/hub/{components → shared/components}/UnlinkedIdentityScreen.tsx +5 -5
  102. package/src/identity/hub/{components → shared/components}/WalletApprovalScreen.tsx +6 -6
  103. package/src/identity/hub/{components → shared/components}/menuFlagsFromReconciliation.ts +2 -4
  104. package/src/identity/hub/{effects/shared → shared/effects}/profilePrep.ts +1 -1
  105. package/src/identity/hub/{effects → shared/effects}/receipts.ts +2 -2
  106. package/src/identity/hub/{effects/shared → shared/effects}/sync.ts +6 -47
  107. package/src/identity/hub/{effects → shared/effects}/types.ts +3 -3
  108. package/src/identity/hub/{model → shared/model}/copy.ts +2 -2
  109. package/src/identity/hub/{model → shared/model}/errors.ts +5 -5
  110. package/src/identity/hub/{model → shared/model}/network.ts +3 -3
  111. package/src/identity/hub/{operatorWallets.ts → shared/operatorWallets.ts} +1 -1
  112. package/src/identity/hub/{reconciliation → shared/reconciliation}/agentReconciliation/hook.ts +1 -2
  113. package/src/identity/hub/{reconciliation → shared/reconciliation}/agentReconciliation/ownership.ts +2 -2
  114. package/src/identity/hub/{reconciliation → shared/reconciliation}/agentReconciliation/run.ts +7 -40
  115. package/src/identity/hub/{reconciliation → shared/reconciliation}/agentReconciliation/types.ts +0 -4
  116. package/src/identity/hub/{reconciliation → shared/reconciliation}/index.ts +0 -7
  117. package/src/identity/hub/shared/reconciliation/walletSetup.ts +27 -0
  118. package/src/identity/hub/{utils.ts → shared/utils.ts} +5 -5
  119. package/src/identity/hub/{flows/token-transfer/IdentityHubTokenTransferFlow.tsx → transfer/TokenTransferFlow.tsx} +8 -8
  120. package/src/identity/hub/{flows/token-transfer → transfer}/TokenTransferScreens.tsx +14 -14
  121. package/src/identity/hub/{effects/token-transfer/runTokenTransfer.ts → transfer/effects.ts} +16 -16
  122. package/src/identity/hub/{effects/token-transfer → transfer}/progress.ts +1 -1
  123. package/src/identity/hub/useIdentityHubController.ts +11 -11
  124. package/src/identity/hub/useIdentityHubSideEffects.ts +11 -11
  125. package/src/identity/wallet/browserWallet/types.ts +0 -5
  126. package/src/identity/wallet/page/copy.ts +1 -31
  127. package/src/identity/wallet/walletPurposeCompat.ts +0 -2
  128. package/src/models/ModelPicker.tsx +248 -8
  129. package/src/models/catalog.ts +29 -1
  130. package/src/models/modelPickerOptions.ts +12 -10
  131. package/src/models/providerDisplay.ts +16 -0
  132. package/src/providers/errors.ts +6 -4
  133. package/src/providers/openai-chat.ts +2 -1
  134. package/src/providers/openai-responses-format.ts +156 -0
  135. package/src/providers/openai-responses.ts +276 -0
  136. package/src/providers/registry.ts +85 -8
  137. package/src/runtime/sessionMode.ts +1 -1
  138. package/src/runtime/systemPrompt.ts +4 -2
  139. package/src/runtime/toolExecution.ts +9 -6
  140. package/src/runtime/turn.ts +29 -1
  141. package/src/storage/rewind.ts +20 -0
  142. package/src/storage/secrets.ts +4 -1
  143. package/src/storage/sessions.ts +2 -1
  144. package/src/tools/bashSafety.ts +7 -3
  145. package/src/tools/bashTool.ts +1 -1
  146. package/src/tools/contracts.ts +3 -0
  147. package/src/tools/deleteFileTool.ts +8 -3
  148. package/src/tools/editTool.ts +10 -5
  149. package/src/tools/fileDiff.ts +261 -0
  150. package/src/tools/privateContinuityEditTool.ts +11 -1
  151. package/src/tools/writeFileTool.ts +8 -3
  152. package/src/ui/Spinner.tsx +25 -3
  153. package/src/ui/TextInput.tsx +2 -2
  154. package/src/ui/theme.ts +17 -0
  155. package/src/utils/clipboard.ts +10 -7
  156. package/src/utils/openExternal.ts +20 -10
  157. package/src/chat/RewindView.tsx +0 -386
  158. package/src/chat/toolResultDisplay.ts +0 -8
  159. package/src/identity/ens/ensRegistration.ts +0 -199
  160. package/src/identity/hub/effects/index.ts +0 -74
  161. package/src/identity/hub/effects/publicProfile/index.ts +0 -5
  162. package/src/identity/hub/effects/restore/restoreEffects.ts +0 -22
  163. package/src/identity/hub/effects/restoreAdmin.ts +0 -93
  164. package/src/identity/hub/effects/token-transfer/index.ts +0 -6
  165. package/src/identity/hub/flows/ens/EnsEditAdvancedScreens.tsx +0 -336
  166. package/src/identity/hub/flows/ens/EnsEditRunners.tsx +0 -198
  167. package/src/identity/hub/reconciliation/walletSetup.ts +0 -220
  168. /package/src/chat/{chatInputState.ts → input/chatInputState.ts} +0 -0
  169. /package/src/chat/{chatPaste.ts → input/chatPaste.ts} +0 -0
  170. /package/src/chat/{textCursor.ts → input/textCursor.ts} +0 -0
  171. /package/src/identity/hub/{model/continuity.ts → continuity/state.ts} +0 -0
  172. /package/src/identity/hub/{model/custody.ts → custody/state.ts} +0 -0
  173. /package/src/identity/hub/{effects/restore → restore}/index.ts +0 -0
  174. /package/src/identity/hub/{model → shared/model}/format.ts +0 -0
  175. /package/src/identity/hub/{reconciliation → shared/reconciliation}/useAgentReconciliation.ts +0 -0
  176. /package/src/identity/hub/{txGuard.ts → shared/txGuard.ts} +0 -0
  177. /package/src/identity/hub/{model/transfer.ts → transfer/state.ts} +0 -0
@@ -1,62 +1,56 @@
1
- import { getAddress, type Address, type Hex } from 'viem'
2
- import type { EthagentIdentity } from '../../../../storage/config.js'
1
+ import { getAddress, type Address } from 'viem'
2
+ import type { EthagentIdentity } from '../../../storage/config.js'
3
3
  import {
4
4
  createWalletRestoreAccessChallenge,
5
5
  serializeContinuitySnapshotEnvelope,
6
6
  type WalletChallengePurpose,
7
- } from '../../../continuity/envelope.js'
7
+ } from '../../continuity/envelope.js'
8
8
  import {
9
9
  prepareSyncedPublicSkillsJson,
10
10
  readContinuityFiles,
11
11
  writePublicSkillsFile,
12
- } from '../../../continuity/storage.js'
12
+ } from '../../continuity/storage.js'
13
13
  import {
14
14
  createAgentCard,
15
15
  defaultPublicSkillsProfile,
16
16
  serializeAgentCard,
17
- } from '../../../continuity/publicSkills.js'
18
- import { recordPublishedContinuitySnapshot } from '../../../continuity/snapshots.js'
19
- import { addToIpfs, DEFAULT_IPFS_API_URL, isPinataUploadUrl } from '../../../storage/ipfs.js'
17
+ } from '../../continuity/publicSkills.js'
18
+ import { recordPublishedContinuitySnapshot } from '../../continuity/snapshots.js'
19
+ import { addToIpfs, DEFAULT_IPFS_API_URL, isPinataUploadUrl } from '../../storage/ipfs.js'
20
20
  import {
21
21
  createErc8004PublicClient,
22
22
  encodeSetAgentUri,
23
23
  preflightSetAgentUri,
24
24
  withEthagentPointers,
25
25
  type Erc8004RegistryConfig,
26
- } from '../../../registry/erc8004.js'
26
+ } from '../../registry/erc8004.js'
27
27
  import {
28
28
  VAULT_ABI,
29
29
  encodeRotateAgentURI,
30
- } from '../../../registry/vault.js'
31
- import { resolveValidatedPinataJwt, savePinataJwt } from '../../../storage/pinataJwt.js'
30
+ } from '../../registry/vault.js'
31
+ import { resolveValidatedPinataJwt, savePinataJwt } from '../../storage/pinataJwt.js'
32
32
  import {
33
33
  openBrowserWalletSession,
34
34
  requestBrowserWalletSignatureAndTransaction,
35
- type BrowserWalletSession,
36
35
  type BrowserWalletSignature,
37
36
  type WalletPurpose,
38
- } from '../../../wallet/browserWallet.js'
39
- import type { ProfileUpdates, Step } from '../../identityHubReducer.js'
40
- import { reconcileWalletSetup } from '../../reconciliation/index.js'
41
- import { acquireTxGuard, releaseTxGuard } from '../../txGuard.js'
42
- import type { EffectCallbacks } from '../types.js'
43
- import { awaitConfirmedReceipt } from '../receipts.js'
44
- import {
45
- createMainnetEnsPublicClient,
46
- runUpdateEnsRecords,
47
- } from '../ens/transactions.js'
37
+ } from '../../wallet/browserWallet.js'
38
+ import type { ProfileUpdates, Step } from '../identityHubReducer.js'
39
+ import { acquireTxGuard, releaseTxGuard } from '../shared/txGuard.js'
40
+ import type { EffectCallbacks } from '../shared/effects/types.js'
41
+ import { awaitConfirmedReceipt } from '../shared/effects/receipts.js'
48
42
  import {
49
43
  assertVerifiedPin,
50
44
  deriveAgentName,
51
45
  prepareProfileStateForSave,
52
46
  readEnsOkFromState,
53
- } from '../shared/profilePrep.js'
47
+ } from '../shared/effects/profilePrep.js'
54
48
  import {
55
49
  appendResolverSyncWarning,
56
50
  markCurrentContinuityFilesPublished,
57
51
  resolverSyncWarningMessage,
58
- syncResolverApprovalsAfterOwnerSave,
59
- } from '../shared/sync.js'
52
+ syncVaultOperatorsAfterOwnerSave,
53
+ } from '../shared/effects/sync.js'
60
54
  import {
61
55
  assertSnapshotSaveSignerAuthorized,
62
56
  createContinuityEnvelopeForSave,
@@ -65,8 +59,8 @@ import {
65
59
  ownerAddressForSnapshotSave,
66
60
  snapshotSaveWalletRole,
67
61
  walletRestoreAccessContext,
68
- } from '../shared/snapshot.js'
69
- import { rebackupCompletionMessage } from '../rebackup/runRebackup.js'
62
+ } from '../continuity/snapshot.js'
63
+ import { rebackupCompletionMessage } from '../continuity/effects.js'
70
64
 
71
65
  type BackupMetadata = NonNullable<EthagentIdentity['backup']>
72
66
  type PublicSkillsMetadata = NonNullable<EthagentIdentity['publicSkills']>
@@ -241,7 +235,7 @@ async function runPublicProfileSigningInner(
241
235
  }
242
236
  await writePublicSkillsFile(nextIdentity, result.prepared.publicSkillsJson)
243
237
  await markCurrentContinuityFilesPublished(nextIdentity)
244
- const resolverSyncWarning = await syncResolverApprovalsAfterOwnerSave({
238
+ const resolverSyncWarning = await syncVaultOperatorsAfterOwnerSave({
245
239
  beforeIdentity: step.identity,
246
240
  afterIdentity: nextIdentity,
247
241
  registry: step.registry,
@@ -263,92 +257,21 @@ async function runOperatorWalletPublicProfileSave(
263
257
  callbacks: EffectCallbacks,
264
258
  ): Promise<void> {
265
259
  if (!step.identity.agentId) throw new Error('Cannot update public profile: identity is missing an agent token ID')
266
- const baseState = (step.identity.state ?? {}) as Record<string, unknown>
267
- const ensName = typeof baseState.ensName === 'string' ? baseState.ensName.trim() : ''
268
- if (!ensName) {
269
- throw new Error('Operator wallet profile updates require an ENS subdomain, connect the owner wallet to set one up first')
260
+ if (!step.vaultAddress) {
261
+ throw new Error('Operator-wallet profile updates require a Vault. Set one up via Advanced Mode, or connect the owner wallet to update the profile.')
270
262
  }
271
263
  const snapshotOwner = ownerAddressForSnapshotSave(step.identity, step.profileUpdates)
272
264
  const walletAccess = walletRestoreAccessContext(step.identity, step.registry, step.profileUpdates, snapshotOwner)
273
265
  if (!walletAccess) throw new Error('Operator-wallet profile updates require wallet restore access context')
274
266
  const challengePurpose: WalletChallengePurpose = 'restore-operator'
275
- if (step.vaultAddress) {
276
- await runOperatorWalletVaultPublicProfileSave({
277
- step,
278
- callbacks,
279
- snapshotOwner,
280
- walletAccess,
281
- challengePurpose,
282
- vaultAddress: step.vaultAddress,
283
- })
284
- return
285
- }
286
-
287
- const reconcileBaseState = (step.identity.state ?? {}) as Record<string, unknown>
288
- const activeOperator = typeof reconcileBaseState.activeOperatorAddress === 'string'
289
- ? reconcileBaseState.activeOperatorAddress.trim()
290
- : ''
291
- if (activeOperator) {
292
- const fixPlan = await reconcileWalletSetup({ identity: step.identity, registry: step.registry })
293
- const stale = fixPlan.items.find(
294
- (item): item is Extract<typeof item, { kind: 'missing-approval' }> =>
295
- item.kind === 'missing-approval'
296
- && item.address.toLowerCase() === activeOperator.toLowerCase(),
297
- )
298
- if (stale) {
299
- throw new Error(
300
- `Operator wallet ${stale.address} is no longer approved as a resolver delegate for this agent's ENS subdomain. Connect the owner wallet and run "Fix Records" to restore the approval before retrying.`,
301
- )
302
- }
303
- }
304
-
305
- const session = await openBrowserWalletSession({ onReady: callbacks.onWalletReady })
306
- try {
307
- const wallet = await session.requestSignature({
308
- chainId: step.registry.chainId,
309
- messageForAccount: account => createWalletRestoreAccessChallenge({
310
- token: walletAccess.token,
311
- ownerAddress: snapshotOwner,
312
- walletAddress: account,
313
- accessEpoch: walletAccess.accessEpoch,
314
- purpose: challengePurpose,
315
- }),
316
- purpose: 'update-profile-operator',
317
- })
318
- assertSnapshotSaveSignerAuthorized(step.identity, step.profileUpdates, wallet.account, snapshotOwner, walletAccess)
319
- const prepared = await prepareOperatorProfileArtifacts({
320
- step,
321
- wallet,
322
- snapshotOwner,
323
- walletAccess,
324
- challengePurpose,
325
- includeMetadata: false,
326
- })
327
- await publishOperatorProfileEnsRecord({
328
- ensName,
329
- signer: wallet.account,
330
- registry: step.registry,
331
- agentCardUri: prepared.agentCardUri,
332
- callbacks,
333
- session,
334
- })
335
-
336
- await writePublicSkillsFile(prepared.nextIdentity, prepared.publicSkillsJson)
337
- await markCurrentContinuityFilesPublished(prepared.nextIdentity).catch(() => null)
338
- await recordPublishedContinuitySnapshot({
339
- identity: prepared.nextIdentity,
340
- label: 'operator-wallet ENS profile update',
341
- }).catch(() => null)
342
-
343
- await callbacks.onIdentityComplete(
344
- prepared.nextIdentity,
345
- 'Profile pointer published to ENS records (org.ethagent.profile). ERC-8004 metadata stays put until owner wallet next signs.',
346
- 'update',
347
- )
348
- } finally {
349
- await session.close().catch(() => null)
350
- callbacks.onWalletReady(null)
351
- }
267
+ await runOperatorWalletVaultPublicProfileSave({
268
+ step,
269
+ callbacks,
270
+ snapshotOwner,
271
+ walletAccess,
272
+ challengePurpose,
273
+ vaultAddress: step.vaultAddress,
274
+ })
352
275
  }
353
276
 
354
277
  type WalletAccessContext = NonNullable<ReturnType<typeof walletRestoreAccessContext>>
@@ -391,11 +314,7 @@ async function runOperatorWalletVaultPublicProfileSave(args: {
391
314
  snapshotOwner,
392
315
  walletAccess,
393
316
  challengePurpose,
394
- includeMetadata: true,
395
317
  })
396
- if (!prepared.agentUri || !prepared.metadataCid) {
397
- throw new Error('Vault profile update did not prepare ERC-8004 metadata')
398
- }
399
318
 
400
319
  const vaultCall = encodeRotateAgentURI({
401
320
  registry: getAddress(step.registry.identityRegistryAddress),
@@ -447,9 +366,8 @@ async function runOperatorWalletVaultPublicProfileSave(args: {
447
366
  type OperatorProfileArtifacts = {
448
367
  nextIdentity: EthagentIdentity
449
368
  publicSkillsJson: string
450
- agentCardUri: string
451
- agentUri?: string
452
- metadataCid?: string
369
+ agentUri: string
370
+ metadataCid: string
453
371
  }
454
372
 
455
373
  async function prepareOperatorProfileArtifacts(args: {
@@ -458,7 +376,6 @@ async function prepareOperatorProfileArtifacts(args: {
458
376
  snapshotOwner: Address
459
377
  walletAccess: WalletAccessContext
460
378
  challengePurpose: WalletChallengePurpose
461
- includeMetadata: boolean
462
379
  }): Promise<OperatorProfileArtifacts> {
463
380
  const { step, wallet, snapshotOwner, walletAccess, challengePurpose } = args
464
381
  const {
@@ -523,80 +440,41 @@ async function prepareOperatorProfileArtifacts(args: {
523
440
  agentId: step.identity.agentId!,
524
441
  }
525
442
 
526
- let metadataCid: string | undefined
527
- let agentUri: string | undefined
528
- if (args.includeMetadata) {
529
- const registration = withEthagentPointers({
530
- type: 'https://eips.ethereum.org/EIPS/eip-8004#registration-v1',
531
- name: nextName ?? deriveAgentName(step.identity),
532
- ...(nextDescription ? { description: nextDescription } : {}),
533
- ...(uploadedImageUri ? { image: uploadedImageUri } : {}),
534
- }, {
535
- backup: { cid: statePin.cid, envelopeVersion: envelope.envelopeVersion, createdAt: envelope.createdAt },
536
- publicDiscovery: { skillsCid: publicSkills.cid, agentCardCid: publicSkills.agentCardCid, updatedAt: publicSkills.updatedAt },
537
- registration: { chainId: step.registry.chainId, identityRegistryAddress: step.registry.identityRegistryAddress, agentId: step.identity.agentId },
538
- ensName: nextEnsName,
539
- operators: operatorsPointerFromState(state, nextEnsName),
540
- ownerAddress: snapshotOwner,
541
- })
542
- const metadataPin = await addToIpfs(DEFAULT_IPFS_API_URL, JSON.stringify(registration, null, 2), fetch, { pinataJwt: step.pinataJwt })
543
- assertVerifiedPin(metadataPin)
544
- metadataCid = metadataPin.cid
545
- agentUri = `ipfs://${metadataCid}`
546
- }
443
+ const registration = withEthagentPointers({
444
+ type: 'https://eips.ethereum.org/EIPS/eip-8004#registration-v1',
445
+ name: nextName ?? deriveAgentName(step.identity),
446
+ ...(nextDescription ? { description: nextDescription } : {}),
447
+ ...(uploadedImageUri ? { image: uploadedImageUri } : {}),
448
+ }, {
449
+ backup: { cid: statePin.cid, envelopeVersion: envelope.envelopeVersion, createdAt: envelope.createdAt },
450
+ publicDiscovery: { skillsCid: publicSkills.cid, agentCardCid: publicSkills.agentCardCid, updatedAt: publicSkills.updatedAt },
451
+ registration: { chainId: step.registry.chainId, identityRegistryAddress: step.registry.identityRegistryAddress, agentId: step.identity.agentId },
452
+ ensName: nextEnsName,
453
+ operators: operatorsPointerFromState(state, nextEnsName),
454
+ ownerAddress: snapshotOwner,
455
+ })
456
+ const metadataPin = await addToIpfs(DEFAULT_IPFS_API_URL, JSON.stringify(registration, null, 2), fetch, { pinataJwt: step.pinataJwt })
457
+ assertVerifiedPin(metadataPin)
458
+ const metadataCid = metadataPin.cid
459
+ const agentUri = `ipfs://${metadataCid}`
547
460
 
548
- const nextBackup = agentUri && metadataCid
549
- ? { ...backup, metadataCid, agentUri }
550
- : backup
551
461
  const nextIdentity: EthagentIdentity = {
552
462
  ...step.identity,
553
463
  state,
554
- backup: nextBackup,
464
+ backup: { ...backup, metadataCid, agentUri },
555
465
  publicSkills,
556
- ...(agentUri ? { agentUri } : {}),
557
- ...(metadataCid ? { metadataCid } : {}),
466
+ agentUri,
467
+ metadataCid,
558
468
  }
559
469
 
560
470
  return {
561
471
  nextIdentity,
562
472
  publicSkillsJson,
563
- agentCardUri: `ipfs://${agentCardPin.cid}`,
564
- ...(agentUri ? { agentUri } : {}),
565
- ...(metadataCid ? { metadataCid } : {}),
473
+ agentUri,
474
+ metadataCid,
566
475
  }
567
476
  }
568
477
 
569
- async function publishOperatorProfileEnsRecord(args: {
570
- ensName: string
571
- signer: Address
572
- registry: Erc8004RegistryConfig
573
- agentCardUri: string
574
- callbacks: EffectCallbacks
575
- session: BrowserWalletSession
576
- flowId?: string
577
- flowStep?: number
578
- }): Promise<void> {
579
- const ensClient = createMainnetEnsPublicClient()
580
- const tx = await runUpdateEnsRecords({
581
- fullName: args.ensName,
582
- ownerAddress: args.signer,
583
- records: { profile: args.agentCardUri },
584
- callbacks: args.callbacks,
585
- purpose: 'update-profile-operator',
586
- tokenChainId: args.registry.chainId,
587
- session: args.session,
588
- publicClient: ensClient,
589
- ...(args.flowId ? { flowId: args.flowId } : {}),
590
- ...(typeof args.flowStep === 'number' ? { flowStep: args.flowStep } : {}),
591
- })
592
- await awaitConfirmedReceipt(
593
- ensClient,
594
- tx.txHash as Hex,
595
- 'Public profile ENS record update',
596
- { kind: 'public-profile', chainId: 1 },
597
- )
598
- }
599
-
600
478
  async function assertVaultSignerCanRotateAgentUri(args: {
601
479
  registry: Erc8004RegistryConfig
602
480
  vaultAddress: Address
@@ -1,8 +1,8 @@
1
1
  import type { EthagentConfig, EthagentIdentity } from '../../../storage/config.js'
2
2
  import { supportedErc8004ChainForId, type Erc8004AgentCandidate } from '../../registry/erc8004.js'
3
- import { readCustodyMode, type CustodyMode } from './custody.js'
4
- import { formatDate, shortAddress, shortCid } from './format.js'
5
- import { chainSummaryRow, networkLabel } from './network.js'
3
+ import { readCustodyMode, type CustodyMode } from '../custody/state.js'
4
+ import { formatDate, shortAddress, shortCid } from '../shared/model/format.js'
5
+ import { chainSummaryRow, networkLabel } from '../shared/model/network.js'
6
6
 
7
7
  export const PREFLIGHT_AGENT_URI = 'ipfs://bafybeigdyrztma2dbfczw7q6ooozbxlqzyw5r7w4f3qw2axvvxqg3w6y7q'
8
8