ethagent 3.1.2 → 3.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.
- package/README.md +15 -16
- package/package.json +1 -1
- package/src/chat/ChatScreen.tsx +25 -2
- package/src/chat/chatTurnOrchestrator.ts +17 -0
- package/src/identity/continuity/history.ts +8 -8
- package/src/identity/continuity/publicSkills.ts +3 -80
- package/src/identity/continuity/skills/frontmatter.ts +4 -1
- package/src/identity/continuity/skills/loadSkills.ts +73 -5
- package/src/identity/continuity/skills/publicSkillsSync.ts +9 -8
- package/src/identity/continuity/skills/scaffold.ts +1 -1
- package/src/identity/continuity/skills/types.ts +1 -1
- package/src/identity/continuity/snapshots.ts +3 -8
- package/src/identity/continuity/storage/defaults.ts +3 -3
- package/src/identity/continuity/storage/paths.ts +1 -1
- package/src/identity/continuity/storage/scaffold.ts +37 -25
- package/src/identity/continuity/storage/status.ts +11 -11
- package/src/identity/continuity/storage/types.ts +4 -4
- package/src/identity/continuity/storage.ts +4 -4
- package/src/identity/ens/agentRecords.ts +61 -45
- package/src/identity/ens/ensAutomation/read.ts +7 -10
- package/src/identity/ens/ensAutomation/setup.ts +10 -16
- package/src/identity/ens/ensAutomation/types.ts +0 -1
- package/src/identity/ens/ensAutomation.ts +1 -0
- package/src/identity/ens/ensLookup/records.ts +1 -1
- package/src/identity/ens/ensLookup.ts +1 -1
- package/src/identity/ens/erc7930.ts +48 -0
- package/src/identity/hub/OperationalRoutes.tsx +4 -1
- package/src/identity/hub/continuity/effects.ts +17 -39
- package/src/identity/hub/continuity/skills/NewSkillVisibilityScreen.tsx +3 -4
- package/src/identity/hub/continuity/skills/SkillActionsScreen.tsx +3 -4
- package/src/identity/hub/continuity/skills/SkillsTreeScreen.tsx +2 -1
- package/src/identity/hub/continuity/state.ts +1 -1
- package/src/identity/hub/continuity/vault.ts +16 -50
- package/src/identity/hub/create/effects.ts +12 -16
- package/src/identity/hub/ens/EnsEditFlow.tsx +19 -5
- package/src/identity/hub/ens/EnsEditReviewScreens.tsx +11 -11
- package/src/identity/hub/ens/EnsEditShared.tsx +2 -6
- package/src/identity/hub/ens/editCopy.ts +1 -3
- package/src/identity/hub/ens/transactions.ts +67 -18
- package/src/identity/hub/profile/effects.ts +15 -30
- package/src/identity/hub/profile/identity.ts +2 -4
- package/src/identity/hub/profile/operatorSave.ts +10 -30
- package/src/identity/hub/restore/RestoreFlow.tsx +9 -9
- package/src/identity/hub/restore/apply.ts +7 -8
- package/src/identity/hub/restore/helpers.ts +3 -3
- package/src/identity/hub/restore/recovery.ts +9 -10
- package/src/identity/hub/restore/resolve.ts +11 -9
- package/src/identity/hub/shared/components/MenuScreen.tsx +3 -3
- package/src/identity/hub/shared/components/UnlinkedIdentityScreen.tsx +2 -2
- package/src/identity/hub/shared/effects/sync.ts +1 -1
- package/src/identity/hub/transfer/TokenTransferScreens.tsx +1 -1
- package/src/identity/hub/transfer/effects.ts +10 -31
- package/src/identity/hub/useIdentityHubContinuity.ts +12 -12
- package/src/identity/hub/useIdentityHubController.ts +12 -3
- package/src/identity/registry/erc8004/metadata.ts +10 -27
- package/src/identity/registry/erc8004/types.ts +0 -1
- package/src/models/llamacpp.ts +61 -1
- package/src/models/llamacppPreflight.ts +5 -1
- package/src/runtime/compaction.ts +11 -5
- package/src/storage/config.ts +1 -2
- package/src/storage/identity.ts +3 -3
- package/src/storage/rewind.ts +1 -1
- package/src/tools/privateContinuityEditTool.ts +4 -4
- package/src/utils/messages.ts +1 -1
- package/src/utils/withRetry.ts +2 -2
|
@@ -6,17 +6,11 @@ import {
|
|
|
6
6
|
prepareSyncedIdentityMarkdownScaffold,
|
|
7
7
|
prepareSyncedSkillsTree,
|
|
8
8
|
readContinuityFiles,
|
|
9
|
-
readPublicSkillsFile,
|
|
10
9
|
writeIdentityMarkdownScaffold,
|
|
11
10
|
type IdentityMarkdownScaffold,
|
|
12
11
|
} from '../../continuity/storage.js'
|
|
13
12
|
import {
|
|
14
|
-
|
|
15
|
-
defaultPublicSkillsProfile as basePublicSkillsProfile,
|
|
16
|
-
} from '../../continuity/publicSkills.js'
|
|
17
|
-
import {
|
|
18
|
-
derivePublicSkillEntries,
|
|
19
|
-
syncPublicSkillsManifest,
|
|
13
|
+
syncAgentCardManifest,
|
|
20
14
|
} from '../../continuity/skills/publicSkillsSync.js'
|
|
21
15
|
import {
|
|
22
16
|
createWalletRestoreAccessChallenge,
|
|
@@ -25,12 +19,8 @@ import {
|
|
|
25
19
|
type ContinuitySkillsTree,
|
|
26
20
|
type WalletChallengePurpose,
|
|
27
21
|
} from '../../continuity/envelope.js'
|
|
28
|
-
import {
|
|
29
|
-
createAgentCard,
|
|
30
|
-
defaultPublicSkillsProfile,
|
|
31
|
-
serializeAgentCard,
|
|
32
|
-
} from '../../continuity/publicSkills.js'
|
|
33
22
|
import { recordPublishedContinuitySnapshot } from '../../continuity/snapshots.js'
|
|
23
|
+
import { readCustodyMode } from '../custody/state.js'
|
|
34
24
|
import { addToIpfs, DEFAULT_IPFS_API_URL, isPinataUploadUrl } from '../../storage/ipfs.js'
|
|
35
25
|
import {
|
|
36
26
|
createErc8004PublicClient,
|
|
@@ -83,19 +73,19 @@ import {
|
|
|
83
73
|
} from './completion.js'
|
|
84
74
|
|
|
85
75
|
type BackupMetadata = NonNullable<EthagentIdentity['backup']>
|
|
86
|
-
type
|
|
76
|
+
type AgentCardMetadata = NonNullable<EthagentIdentity['agentCard']>
|
|
87
77
|
|
|
88
78
|
type RebackupPreparedTransaction = {
|
|
89
79
|
ownerAddress: Address
|
|
90
80
|
agentUri: string
|
|
91
81
|
metadataCid: string
|
|
92
82
|
backup: BackupMetadata
|
|
93
|
-
|
|
83
|
+
agentCard: AgentCardMetadata
|
|
94
84
|
identity: EthagentIdentity
|
|
95
85
|
markdownScaffold?: IdentityMarkdownScaffold
|
|
96
86
|
publishedSources: {
|
|
97
87
|
privateFiles: ContinuityFiles
|
|
98
|
-
|
|
88
|
+
agentCard: string
|
|
99
89
|
skills: ContinuitySkillsTree
|
|
100
90
|
}
|
|
101
91
|
}
|
|
@@ -197,8 +187,9 @@ async function runRebackupSigningInner(
|
|
|
197
187
|
return
|
|
198
188
|
}
|
|
199
189
|
const snapshotOwner = ownerAddressForSnapshotSave(step.identity, step.profileUpdates)
|
|
190
|
+
const isAdvanced = readCustodyMode(step.identity.state as Record<string, unknown> | undefined) === 'advanced'
|
|
200
191
|
const purpose: WalletPurpose = step.walletPurpose
|
|
201
|
-
?? (step.vaultAddress ? 'rotate-agent-uri-vault-owner' : rebackupWalletPurpose(step.identity, step.profileUpdates))
|
|
192
|
+
?? (step.vaultAddress && isAdvanced ? 'rotate-agent-uri-vault-owner' : rebackupWalletPurpose(step.identity, step.profileUpdates))
|
|
202
193
|
const challengePurpose: WalletChallengePurpose = 'restore-owner'
|
|
203
194
|
const walletAccess = walletRestoreAccessContext(step.identity, step.registry, step.profileUpdates, snapshotOwner)
|
|
204
195
|
if (!walletAccess) throw new Error('Cannot back up: missing wallet restore access context')
|
|
@@ -244,20 +235,8 @@ async function runRebackupSigningInner(
|
|
|
244
235
|
const continuityFiles = markdownScaffold
|
|
245
236
|
? { 'SOUL.md': markdownScaffold['SOUL.md'], 'MEMORY.md': markdownScaffold['MEMORY.md'] }
|
|
246
237
|
: await readContinuityFiles(nextIdentityForFiles)
|
|
247
|
-
const
|
|
248
|
-
const
|
|
249
|
-
assertVerifiedPin(publicSkillsPin)
|
|
250
|
-
const publicSkillEntries = await derivePublicSkillEntries(nextIdentityForFiles)
|
|
251
|
-
const augmentedPublicProfile = appendPublicSkillEntries(
|
|
252
|
-
basePublicSkillsProfile(nextIdentityForFiles),
|
|
253
|
-
publicSkillEntries,
|
|
254
|
-
)
|
|
255
|
-
const agentCardPin = await addToIpfs(
|
|
256
|
-
DEFAULT_IPFS_API_URL,
|
|
257
|
-
serializeAgentCard(createAgentCard(augmentedPublicProfile)),
|
|
258
|
-
fetch,
|
|
259
|
-
{ pinataJwt: step.pinataJwt },
|
|
260
|
-
)
|
|
238
|
+
const agentCardJson = await syncAgentCardManifest(nextIdentityForFiles)
|
|
239
|
+
const agentCardPin = await addToIpfs(DEFAULT_IPFS_API_URL, agentCardJson, fetch, { pinataJwt: step.pinataJwt })
|
|
261
240
|
assertVerifiedPin(agentCardPin)
|
|
262
241
|
const skillsTree = await prepareSyncedSkillsTree(nextIdentityForFiles)
|
|
263
242
|
const envelope = createContinuityEnvelopeForSave({
|
|
@@ -287,9 +266,8 @@ async function runRebackupSigningInner(
|
|
|
287
266
|
identityRegistryAddress: step.registry.identityRegistryAddress,
|
|
288
267
|
agentId: sourceAgentId,
|
|
289
268
|
}
|
|
290
|
-
const
|
|
291
|
-
cid:
|
|
292
|
-
agentCardCid: agentCardPin.cid,
|
|
269
|
+
const agentCard: AgentCardMetadata = {
|
|
270
|
+
cid: agentCardPin.cid,
|
|
293
271
|
updatedAt: envelope.createdAt,
|
|
294
272
|
status: 'pinned',
|
|
295
273
|
}
|
|
@@ -300,7 +278,7 @@ async function runRebackupSigningInner(
|
|
|
300
278
|
...(uploadedImageUri ? { image: uploadedImageUri } : {}),
|
|
301
279
|
}, {
|
|
302
280
|
backup: { cid, envelopeVersion: envelope.envelopeVersion, createdAt: envelope.createdAt },
|
|
303
|
-
publicDiscovery: {
|
|
281
|
+
publicDiscovery: { agentCardCid: agentCard.cid, updatedAt: agentCard.updatedAt },
|
|
304
282
|
registration: { chainId: step.registry.chainId, identityRegistryAddress: step.registry.identityRegistryAddress, agentId: sourceAgentId },
|
|
305
283
|
ensName: nextEnsName,
|
|
306
284
|
operators: operatorsPointerFromState(state, nextEnsName),
|
|
@@ -332,12 +310,12 @@ async function runRebackupSigningInner(
|
|
|
332
310
|
agentUri,
|
|
333
311
|
metadataCid,
|
|
334
312
|
backup: { ...backup, metadataCid, agentUri },
|
|
335
|
-
|
|
313
|
+
agentCard,
|
|
336
314
|
identity: { ...step.identity, state },
|
|
337
315
|
...(markdownScaffold ? { markdownScaffold } : {}),
|
|
338
316
|
publishedSources: {
|
|
339
317
|
privateFiles: continuityFiles,
|
|
340
|
-
|
|
318
|
+
agentCard: agentCardJson,
|
|
341
319
|
skills: skillsTree,
|
|
342
320
|
},
|
|
343
321
|
},
|
|
@@ -357,12 +335,12 @@ async function runRebackupSigningInner(
|
|
|
357
335
|
agentUri,
|
|
358
336
|
metadataCid,
|
|
359
337
|
backup: { ...backup, metadataCid, agentUri },
|
|
360
|
-
|
|
338
|
+
agentCard,
|
|
361
339
|
identity: { ...step.identity, state },
|
|
362
340
|
...(markdownScaffold ? { markdownScaffold } : {}),
|
|
363
341
|
publishedSources: {
|
|
364
342
|
privateFiles: continuityFiles,
|
|
365
|
-
|
|
343
|
+
agentCard: agentCardJson,
|
|
366
344
|
skills: skillsTree,
|
|
367
345
|
},
|
|
368
346
|
},
|
|
@@ -388,7 +366,7 @@ async function runRebackupSigningInner(
|
|
|
388
366
|
agentUri: result.prepared.agentUri,
|
|
389
367
|
metadataCid: result.prepared.metadataCid,
|
|
390
368
|
backup: { ...result.prepared.backup, txHash: result.txHash },
|
|
391
|
-
|
|
369
|
+
agentCard: result.prepared.agentCard,
|
|
392
370
|
}
|
|
393
371
|
if (result.prepared.markdownScaffold) {
|
|
394
372
|
await writeIdentityMarkdownScaffold(nextIdentity, result.prepared.markdownScaffold)
|
|
@@ -22,7 +22,7 @@ export const NewSkillVisibilityScreen: React.FC<NewSkillVisibilityScreenProps> =
|
|
|
22
22
|
}) => (
|
|
23
23
|
<Surface
|
|
24
24
|
title={`Visibility · ${name}`}
|
|
25
|
-
subtitle="
|
|
25
|
+
subtitle="Public is the default. You can change it later from Change Visibility."
|
|
26
26
|
footer={footer}
|
|
27
27
|
>
|
|
28
28
|
{error && (
|
|
@@ -33,9 +33,8 @@ export const NewSkillVisibilityScreen: React.FC<NewSkillVisibilityScreenProps> =
|
|
|
33
33
|
<Box marginTop={1}>
|
|
34
34
|
<Select<SkillVisibility | 'back'>
|
|
35
35
|
options={[
|
|
36
|
-
{ value: 'private', label: 'Private', hint: 'Local-only. Not in
|
|
37
|
-
{ value: '
|
|
38
|
-
{ value: 'public', label: 'Public', hint: 'Indexed in skills.json and Agent Card.' },
|
|
36
|
+
{ value: 'private', label: 'Private', hint: 'Local-only. Not in the Agent Card.' },
|
|
37
|
+
{ value: 'public', label: 'Public', hint: 'Default. Listed in the Agent Card.' },
|
|
39
38
|
{ value: 'back', role: 'section', label: 'Navigation' },
|
|
40
39
|
{ value: 'back', label: 'Back', hint: 'Return to the name step', role: 'utility' },
|
|
41
40
|
]}
|
|
@@ -74,7 +74,6 @@ export const SkillActionsScreen: React.FC<SkillActionsScreenProps> = ({
|
|
|
74
74
|
|
|
75
75
|
options.push({ value: noop, role: 'section', label: 'Visibility' })
|
|
76
76
|
options.push(visibilityOption('private', visibility))
|
|
77
|
-
options.push(visibilityOption('discoverable', visibility))
|
|
78
77
|
options.push(visibilityOption('public', visibility))
|
|
79
78
|
|
|
80
79
|
options.push({ value: noop, role: 'section', label: 'Manage' })
|
|
@@ -83,6 +82,7 @@ export const SkillActionsScreen: React.FC<SkillActionsScreenProps> = ({
|
|
|
83
82
|
label: 'Delete',
|
|
84
83
|
hint: 'Remove this skill folder and its supporting files',
|
|
85
84
|
})
|
|
85
|
+
options.push({ value: noop, role: 'section', label: 'Return' })
|
|
86
86
|
options.push({
|
|
87
87
|
value: { kind: 'back' },
|
|
88
88
|
label: 'Back',
|
|
@@ -140,9 +140,8 @@ function visibilityOption(level: SkillVisibility, current?: SkillVisibility): Se
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
function visibilityHint(level: SkillVisibility): string {
|
|
143
|
-
if (level === 'private') return 'Local-only. Not in
|
|
144
|
-
|
|
145
|
-
return 'Indexed with description and Agent Card link.'
|
|
143
|
+
if (level === 'private') return 'Local-only. Not in the Agent Card.'
|
|
144
|
+
return 'Default. Listed in the Agent Card.'
|
|
146
145
|
}
|
|
147
146
|
|
|
148
147
|
function capitalize(value: string): string {
|
|
@@ -73,7 +73,7 @@ export const SkillsTreeScreen: React.FC<SkillsTreeScreenProps> = ({
|
|
|
73
73
|
}
|
|
74
74
|
}, [identity, editorOpened])
|
|
75
75
|
|
|
76
|
-
const subtitle = notice ?? '
|
|
76
|
+
const subtitle = notice ?? 'Select a skill to open, change visibility, or delete.'
|
|
77
77
|
const isLoading = tree === null
|
|
78
78
|
const skills = tree?.skills ?? []
|
|
79
79
|
const supportingCounts = tree?.supportingCounts ?? {}
|
|
@@ -145,6 +145,7 @@ function buildOptions(
|
|
|
145
145
|
const supportCount = supportingCounts[skill.name] ?? 0
|
|
146
146
|
const meta = [capitalize(skill.visibility)]
|
|
147
147
|
if (supportCount > 0) meta.push(`${supportCount + 1} files`)
|
|
148
|
+
meta.push('enter for actions')
|
|
148
149
|
rows.push({
|
|
149
150
|
value: { kind: 'skill', relativePath: skill.relativePath },
|
|
150
151
|
label: `${branch}${skill.name}/SKILL.md`,
|
|
@@ -27,7 +27,7 @@ export function changedContinuitySnapshotFiles(
|
|
|
27
27
|
const result: string[] = []
|
|
28
28
|
if (changed('SOUL.md')) result.push('SOUL.md')
|
|
29
29
|
if (changed('MEMORY.md')) result.push('MEMORY.md')
|
|
30
|
-
if (changed('
|
|
30
|
+
if (changed('agent-card.json') || changed('private-skills')) result.push('Skills')
|
|
31
31
|
return result
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
prepareSyncedIdentityMarkdownScaffold,
|
|
5
5
|
prepareSyncedSkillsTree,
|
|
6
6
|
readContinuityFiles,
|
|
7
|
-
readPublicSkillsFile,
|
|
8
7
|
writeIdentityMarkdownScaffold,
|
|
9
8
|
type IdentityMarkdownScaffold,
|
|
10
9
|
} from '../../continuity/storage.js'
|
|
@@ -16,14 +15,7 @@ import {
|
|
|
16
15
|
type WalletChallengePurpose,
|
|
17
16
|
} from '../../continuity/envelope.js'
|
|
18
17
|
import {
|
|
19
|
-
|
|
20
|
-
createAgentCard,
|
|
21
|
-
defaultPublicSkillsProfile,
|
|
22
|
-
serializeAgentCard,
|
|
23
|
-
} from '../../continuity/publicSkills.js'
|
|
24
|
-
import {
|
|
25
|
-
derivePublicSkillEntries,
|
|
26
|
-
syncPublicSkillsManifest,
|
|
18
|
+
syncAgentCardManifest,
|
|
27
19
|
} from '../../continuity/skills/publicSkillsSync.js'
|
|
28
20
|
import { recordPublishedContinuitySnapshot } from '../../continuity/snapshots.js'
|
|
29
21
|
import { addToIpfs, DEFAULT_IPFS_API_URL } from '../../storage/ipfs.js'
|
|
@@ -60,7 +52,7 @@ import {
|
|
|
60
52
|
import { markCurrentContinuityFilesPublished } from '../shared/effects/sync.js'
|
|
61
53
|
|
|
62
54
|
type BackupMetadata = NonNullable<EthagentIdentity['backup']>
|
|
63
|
-
type
|
|
55
|
+
type AgentCardMetadata = NonNullable<EthagentIdentity['agentCard']>
|
|
64
56
|
|
|
65
57
|
type VaultPublishPrepared = {
|
|
66
58
|
nextIdentity: EthagentIdentity
|
|
@@ -68,7 +60,7 @@ type VaultPublishPrepared = {
|
|
|
68
60
|
completionMessage: string
|
|
69
61
|
publishedSources: {
|
|
70
62
|
privateFiles: ContinuityFiles
|
|
71
|
-
|
|
63
|
+
agentCard: string
|
|
72
64
|
skills: ContinuitySkillsTree
|
|
73
65
|
}
|
|
74
66
|
}
|
|
@@ -142,20 +134,8 @@ export async function runOperatorWalletRebackup(args: {
|
|
|
142
134
|
const continuityFiles = markdownScaffold
|
|
143
135
|
? { 'SOUL.md': markdownScaffold['SOUL.md'], 'MEMORY.md': markdownScaffold['MEMORY.md'] }
|
|
144
136
|
: await readContinuityFiles(nextIdentityForFiles)
|
|
145
|
-
const
|
|
146
|
-
const
|
|
147
|
-
assertVerifiedPin(publicSkillsPin)
|
|
148
|
-
const publicSkillEntries = await derivePublicSkillEntries(nextIdentityForFiles)
|
|
149
|
-
const augmentedPublicProfile = appendPublicSkillEntries(
|
|
150
|
-
defaultPublicSkillsProfile(nextIdentityForFiles),
|
|
151
|
-
publicSkillEntries,
|
|
152
|
-
)
|
|
153
|
-
const agentCardPin = await addToIpfs(
|
|
154
|
-
DEFAULT_IPFS_API_URL,
|
|
155
|
-
serializeAgentCard(createAgentCard(augmentedPublicProfile)),
|
|
156
|
-
fetch,
|
|
157
|
-
{ pinataJwt: step.pinataJwt },
|
|
158
|
-
)
|
|
137
|
+
const agentCardJson = await syncAgentCardManifest(nextIdentityForFiles)
|
|
138
|
+
const agentCardPin = await addToIpfs(DEFAULT_IPFS_API_URL, agentCardJson, fetch, { pinataJwt: step.pinataJwt })
|
|
159
139
|
assertVerifiedPin(agentCardPin)
|
|
160
140
|
const skillsTree = await prepareSyncedSkillsTree(nextIdentityForFiles)
|
|
161
141
|
const envelope = createContinuityEnvelopeForSave({
|
|
@@ -185,9 +165,8 @@ export async function runOperatorWalletRebackup(args: {
|
|
|
185
165
|
identityRegistryAddress: step.registry.identityRegistryAddress,
|
|
186
166
|
agentId: sourceAgentId,
|
|
187
167
|
}
|
|
188
|
-
const
|
|
189
|
-
cid:
|
|
190
|
-
agentCardCid: agentCardPin.cid,
|
|
168
|
+
const agentCard: AgentCardMetadata = {
|
|
169
|
+
cid: agentCardPin.cid,
|
|
191
170
|
updatedAt: envelope.createdAt,
|
|
192
171
|
status: 'pinned',
|
|
193
172
|
}
|
|
@@ -196,7 +175,7 @@ export async function runOperatorWalletRebackup(args: {
|
|
|
196
175
|
...step.identity,
|
|
197
176
|
state,
|
|
198
177
|
backup,
|
|
199
|
-
|
|
178
|
+
agentCard,
|
|
200
179
|
}
|
|
201
180
|
|
|
202
181
|
if (markdownScaffold) {
|
|
@@ -205,7 +184,7 @@ export async function runOperatorWalletRebackup(args: {
|
|
|
205
184
|
await recordPublishedContinuitySnapshot({ identity: nextIdentity, label: 'local operator-wallet snapshot' }).catch(() => null)
|
|
206
185
|
await markCurrentContinuityFilesPublished(nextIdentity, {
|
|
207
186
|
privateFiles: continuityFiles,
|
|
208
|
-
|
|
187
|
+
agentCard: agentCardJson,
|
|
209
188
|
skills: skillsTree,
|
|
210
189
|
}).catch(() => null)
|
|
211
190
|
const completionMessage = nextEnsName !== undefined && nextEnsName !== ((step.identity.state as Record<string, unknown> | undefined)?.ensName as string | undefined)
|
|
@@ -284,20 +263,8 @@ async function runOperatorWalletVaultPublish(args: {
|
|
|
284
263
|
const continuityFiles = markdownScaffold
|
|
285
264
|
? { 'SOUL.md': markdownScaffold['SOUL.md'], 'MEMORY.md': markdownScaffold['MEMORY.md'] }
|
|
286
265
|
: await readContinuityFiles(nextIdentityForFiles)
|
|
287
|
-
const
|
|
288
|
-
const
|
|
289
|
-
assertVerifiedPin(publicSkillsPin)
|
|
290
|
-
const publicSkillEntries = await derivePublicSkillEntries(nextIdentityForFiles)
|
|
291
|
-
const augmentedPublicProfile = appendPublicSkillEntries(
|
|
292
|
-
defaultPublicSkillsProfile(nextIdentityForFiles),
|
|
293
|
-
publicSkillEntries,
|
|
294
|
-
)
|
|
295
|
-
const agentCardPin = await addToIpfs(
|
|
296
|
-
DEFAULT_IPFS_API_URL,
|
|
297
|
-
serializeAgentCard(createAgentCard(augmentedPublicProfile)),
|
|
298
|
-
fetch,
|
|
299
|
-
{ pinataJwt: step.pinataJwt },
|
|
300
|
-
)
|
|
266
|
+
const agentCardJson = await syncAgentCardManifest(nextIdentityForFiles)
|
|
267
|
+
const agentCardPin = await addToIpfs(DEFAULT_IPFS_API_URL, agentCardJson, fetch, { pinataJwt: step.pinataJwt })
|
|
301
268
|
assertVerifiedPin(agentCardPin)
|
|
302
269
|
const skillsTree = await prepareSyncedSkillsTree(nextIdentityForFiles)
|
|
303
270
|
const envelope = createContinuityEnvelopeForSave({
|
|
@@ -315,9 +282,8 @@ async function runOperatorWalletVaultPublish(args: {
|
|
|
315
282
|
const statePin = await addToIpfs(DEFAULT_IPFS_API_URL, serializeContinuitySnapshotEnvelope(envelope), fetch, { pinataJwt: step.pinataJwt })
|
|
316
283
|
assertVerifiedPin(statePin)
|
|
317
284
|
|
|
318
|
-
const
|
|
319
|
-
cid:
|
|
320
|
-
agentCardCid: agentCardPin.cid,
|
|
285
|
+
const agentCard: AgentCardMetadata = {
|
|
286
|
+
cid: agentCardPin.cid,
|
|
321
287
|
updatedAt: envelope.createdAt,
|
|
322
288
|
status: 'pinned',
|
|
323
289
|
}
|
|
@@ -329,7 +295,7 @@ async function runOperatorWalletVaultPublish(args: {
|
|
|
329
295
|
...(uploadedImageUri ? { image: uploadedImageUri } : {}),
|
|
330
296
|
}, {
|
|
331
297
|
backup: { cid: statePin.cid, envelopeVersion: envelope.envelopeVersion, createdAt: envelope.createdAt },
|
|
332
|
-
publicDiscovery: {
|
|
298
|
+
publicDiscovery: { agentCardCid: agentCard.cid, updatedAt: agentCard.updatedAt },
|
|
333
299
|
registration: { chainId: step.registry.chainId, identityRegistryAddress: step.registry.identityRegistryAddress, agentId: sourceAgentId },
|
|
334
300
|
ensName: nextEnsName,
|
|
335
301
|
operators: operatorsPointerFromState(state, nextEnsName),
|
|
@@ -365,7 +331,7 @@ async function runOperatorWalletVaultPublish(args: {
|
|
|
365
331
|
...step.identity,
|
|
366
332
|
state,
|
|
367
333
|
backup,
|
|
368
|
-
|
|
334
|
+
agentCard,
|
|
369
335
|
agentUri,
|
|
370
336
|
metadataCid,
|
|
371
337
|
}
|
|
@@ -383,7 +349,7 @@ async function runOperatorWalletVaultPublish(args: {
|
|
|
383
349
|
completionMessage,
|
|
384
350
|
publishedSources: {
|
|
385
351
|
privateFiles: continuityFiles,
|
|
386
|
-
|
|
352
|
+
agentCard: agentCardJson,
|
|
387
353
|
skills: skillsTree,
|
|
388
354
|
},
|
|
389
355
|
},
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
createAgentCard,
|
|
16
16
|
defaultPublicSkillsProfile,
|
|
17
|
-
renderPublicSkillsJson,
|
|
18
17
|
serializeAgentCard,
|
|
19
18
|
} from '../../continuity/publicSkills.js'
|
|
20
19
|
import { recordPublishedContinuitySnapshot } from '../../continuity/snapshots.js'
|
|
@@ -43,17 +42,17 @@ import { awaitConfirmedReceipt } from '../shared/effects/receipts.js'
|
|
|
43
42
|
import { assertVerifiedPin } from '../shared/effects/profilePrep.js'
|
|
44
43
|
|
|
45
44
|
type BackupMetadata = NonNullable<EthagentIdentity['backup']>
|
|
46
|
-
type
|
|
45
|
+
type AgentCardMetadata = NonNullable<EthagentIdentity['agentCard']>
|
|
47
46
|
|
|
48
47
|
type CreatePreparedTransaction = {
|
|
49
48
|
ownerAddress: Address
|
|
50
49
|
agentUri: string
|
|
51
50
|
metadataCid: string
|
|
52
51
|
backup: BackupMetadata
|
|
53
|
-
|
|
52
|
+
agentCard: AgentCardMetadata
|
|
54
53
|
state: Record<string, unknown>
|
|
55
54
|
continuityFiles: ReturnType<typeof defaultContinuityFiles>
|
|
56
|
-
|
|
55
|
+
agentCardJson: string
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
export async function runCreatePreflight(
|
|
@@ -139,10 +138,8 @@ export async function runCreateSigning(
|
|
|
139
138
|
})
|
|
140
139
|
const continuityFiles = defaultContinuityFiles(draftIdentity)
|
|
141
140
|
const publicProfile = defaultPublicSkillsProfile(draftIdentity)
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
assertVerifiedPin(publicSkillsPin)
|
|
145
|
-
const agentCardPin = await addToIpfs(DEFAULT_IPFS_API_URL, serializeAgentCard(createAgentCard(publicProfile)), fetch, { pinataJwt: step.pinataJwt })
|
|
141
|
+
const agentCardJson = serializeAgentCard(createAgentCard(publicProfile))
|
|
142
|
+
const agentCardPin = await addToIpfs(DEFAULT_IPFS_API_URL, agentCardJson, fetch, { pinataJwt: step.pinataJwt })
|
|
146
143
|
assertVerifiedPin(agentCardPin)
|
|
147
144
|
const envelope = createContinuitySnapshotEnvelope({
|
|
148
145
|
ownerAddress: wallet.account,
|
|
@@ -168,9 +165,8 @@ export async function runCreateSigning(
|
|
|
168
165
|
rpcUrl: step.registry.rpcUrl,
|
|
169
166
|
identityRegistryAddress: step.registry.identityRegistryAddress,
|
|
170
167
|
}
|
|
171
|
-
const
|
|
172
|
-
cid:
|
|
173
|
-
agentCardCid: agentCardPin.cid,
|
|
168
|
+
const agentCard: AgentCardMetadata = {
|
|
169
|
+
cid: agentCardPin.cid,
|
|
174
170
|
updatedAt: envelope.createdAt,
|
|
175
171
|
status: 'pinned',
|
|
176
172
|
}
|
|
@@ -181,7 +177,7 @@ export async function runCreateSigning(
|
|
|
181
177
|
...(typeof state.imageUrl === 'string' ? { image: state.imageUrl } : {}),
|
|
182
178
|
}, {
|
|
183
179
|
backup: { cid, envelopeVersion: envelope.envelopeVersion, createdAt: envelope.createdAt },
|
|
184
|
-
publicDiscovery: {
|
|
180
|
+
publicDiscovery: { agentCardCid: agentCard.cid, updatedAt: agentCard.updatedAt },
|
|
185
181
|
registration: { chainId: step.registry.chainId, identityRegistryAddress: step.registry.identityRegistryAddress },
|
|
186
182
|
ownerAddress: wallet.account,
|
|
187
183
|
})
|
|
@@ -197,10 +193,10 @@ export async function runCreateSigning(
|
|
|
197
193
|
agentUri,
|
|
198
194
|
metadataCid,
|
|
199
195
|
backup: { ...backup, metadataCid, agentUri },
|
|
200
|
-
|
|
196
|
+
agentCard,
|
|
201
197
|
state,
|
|
202
198
|
continuityFiles,
|
|
203
|
-
|
|
199
|
+
agentCardJson,
|
|
204
200
|
},
|
|
205
201
|
}
|
|
206
202
|
},
|
|
@@ -233,11 +229,11 @@ export async function runCreateSigning(
|
|
|
233
229
|
metadataCid: result.prepared.metadataCid,
|
|
234
230
|
state: result.prepared.state,
|
|
235
231
|
backup,
|
|
236
|
-
|
|
232
|
+
agentCard: result.prepared.agentCard,
|
|
237
233
|
}
|
|
238
234
|
await writeIdentityMarkdownScaffold(nextIdentity, {
|
|
239
235
|
...defaultContinuityFiles(nextIdentity),
|
|
240
|
-
'
|
|
236
|
+
'agent-card.json': result.prepared.agentCardJson,
|
|
241
237
|
})
|
|
242
238
|
await recordPublishedContinuitySnapshot({ identity: nextIdentity, label: 'initial published snapshot' }).catch(() => null)
|
|
243
239
|
await callbacks.onIdentityComplete(nextIdentity, `ERC-8004 agent registered · #${registered.agentId.toString()}`, 'create')
|
|
@@ -2,8 +2,8 @@ import React from 'react'
|
|
|
2
2
|
import { getAddress, type Address } from 'viem'
|
|
3
3
|
import type { BrowserWalletReady } from '../../wallet/browserWallet.js'
|
|
4
4
|
import {
|
|
5
|
-
AGENT_RECORD_READ_KEY_LIST,
|
|
6
5
|
buildAgentEnsRecords,
|
|
6
|
+
buildEnsip25Key,
|
|
7
7
|
diffRecords,
|
|
8
8
|
recordsFromTextMap,
|
|
9
9
|
} from '../../ens/agentRecords.js'
|
|
@@ -137,8 +137,15 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
137
137
|
setPhase({ kind: 'validating', fullName, mode, ownerAddress: phaseOwnerAddress, operatorWallet })
|
|
138
138
|
try {
|
|
139
139
|
const validation = await validateAgentEnsLink(fullName, ownerAddress)
|
|
140
|
-
const
|
|
141
|
-
?
|
|
140
|
+
const readKeys = identity.agentId
|
|
141
|
+
? [buildEnsip25Key({
|
|
142
|
+
chainId: registry.chainId,
|
|
143
|
+
identityRegistryAddress: registry.identityRegistryAddress,
|
|
144
|
+
agentId: identity.agentId,
|
|
145
|
+
})]
|
|
146
|
+
: []
|
|
147
|
+
const currentText = validation.ok && readKeys.length > 0
|
|
148
|
+
? await readEthagentTextRecords(fullName, readKeys)
|
|
142
149
|
: {}
|
|
143
150
|
const current = recordsFromTextMap(currentText)
|
|
144
151
|
const next = buildAgentEnsRecords({
|
|
@@ -252,7 +259,14 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
252
259
|
const runUnlinkEnsLoading = React.useCallback((fullName: string): void => {
|
|
253
260
|
setValidationError(null)
|
|
254
261
|
setPhase({ kind: 'unlink-loading', fullName })
|
|
255
|
-
|
|
262
|
+
const readKeys = identity.agentId
|
|
263
|
+
? [buildEnsip25Key({
|
|
264
|
+
chainId: registry.chainId,
|
|
265
|
+
identityRegistryAddress: registry.identityRegistryAddress,
|
|
266
|
+
agentId: identity.agentId,
|
|
267
|
+
})]
|
|
268
|
+
: []
|
|
269
|
+
readEthagentTextRecords(fullName, readKeys)
|
|
256
270
|
.then(currentText => {
|
|
257
271
|
const currentRecords = recordsFromTextMap(currentText)
|
|
258
272
|
setPhase({
|
|
@@ -266,7 +280,7 @@ export const EnsEditFlow: React.FC<EnsEditProps> = ({
|
|
|
266
280
|
setValidationError(err instanceof Error ? err.message : String(err))
|
|
267
281
|
setPhase({ kind: 'mode-select' })
|
|
268
282
|
})
|
|
269
|
-
}, [])
|
|
283
|
+
}, [identity.agentId, registry.chainId, registry.identityRegistryAddress])
|
|
270
284
|
|
|
271
285
|
const maintenanceScreen = renderEnsMaintenancePhase({
|
|
272
286
|
phase,
|
|
@@ -4,11 +4,9 @@ import { getAddress, type Address } from 'viem'
|
|
|
4
4
|
import { Surface } from '../../../ui/Surface.js'
|
|
5
5
|
import { Select, type SelectOption } from '../../../ui/Select.js'
|
|
6
6
|
import { theme } from '../../../ui/theme.js'
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
type AgentEnsRecords,
|
|
11
|
-
type AgentRecordDiff,
|
|
7
|
+
import type {
|
|
8
|
+
AgentEnsRecords,
|
|
9
|
+
AgentRecordDiff,
|
|
12
10
|
} from '../../ens/agentRecords.js'
|
|
13
11
|
import type { EnsValidation } from '../../ens/ensLookup.js'
|
|
14
12
|
import type {
|
|
@@ -194,7 +192,9 @@ export const EnsSetupBlockedScreen: React.FC<EnsSetupBlockedScreenProps> = ({
|
|
|
194
192
|
{isSimple
|
|
195
193
|
? <EnsSetupRow label="Wallet" value={fallback.ownerAddress ? shortAddress(fallback.ownerAddress) : shortAddress(fallback.operatorAddress)} />
|
|
196
194
|
: (fallback.ownerAddress ? <EnsSetupRow label="Owner wallet" value={shortAddress(fallback.ownerAddress)} /> : null)}
|
|
197
|
-
{fallback.nextRecords
|
|
195
|
+
{fallback.nextRecords && Object.keys(fallback.nextRecords).length > 0
|
|
196
|
+
? <EnsSetupRow label="Attestation" value="ENSIP-25 agent-registration record" />
|
|
197
|
+
: null}
|
|
198
198
|
<EnsSetupRow label="Address" value={`Set the subdomain address record to the ${isSimple ? 'connected wallet' : 'owner wallet'}.`} />
|
|
199
199
|
{!isSimple
|
|
200
200
|
? (
|
|
@@ -271,7 +271,7 @@ export const UnlinkEnsReviewScreen: React.FC<UnlinkEnsReviewScreenProps> = ({
|
|
|
271
271
|
{changedDiffs.map(diff => (
|
|
272
272
|
<Text key={diff.key}>
|
|
273
273
|
<Text color={theme.dim}>{` ${diff.key} `}</Text>
|
|
274
|
-
<Text color={theme.accentPeriwinkle}>{
|
|
274
|
+
<Text color={theme.accentPeriwinkle}>{diff.current}</Text>
|
|
275
275
|
</Text>
|
|
276
276
|
))}
|
|
277
277
|
</Box>
|
|
@@ -420,16 +420,16 @@ export const ReviewScreen: React.FC<ReviewScreenProps> = ({
|
|
|
420
420
|
: null}
|
|
421
421
|
{recordsDiff.map(diff => (
|
|
422
422
|
<Text key={diff.key}>
|
|
423
|
-
<Text color={theme.dim}>{`- ${
|
|
423
|
+
<Text color={theme.dim}>{`- ${diff.key}: `}</Text>
|
|
424
424
|
{diff.changed
|
|
425
425
|
? (
|
|
426
426
|
<>
|
|
427
|
-
{renderRecordValue(diff.
|
|
427
|
+
{renderRecordValue(diff.current)}
|
|
428
428
|
<Text color={theme.dim}>{' → '}</Text>
|
|
429
|
-
{renderRecordValue(diff.
|
|
429
|
+
{renderRecordValue(diff.next)}
|
|
430
430
|
</>
|
|
431
431
|
)
|
|
432
|
-
: renderRecordValue(diff.
|
|
432
|
+
: renderRecordValue(diff.next)}
|
|
433
433
|
</Text>
|
|
434
434
|
))}
|
|
435
435
|
{!hasRecordChanges
|
|
@@ -4,10 +4,6 @@ import type { Address } from 'viem'
|
|
|
4
4
|
import { Surface } from '../../../ui/Surface.js'
|
|
5
5
|
import { TextInput } from '../../../ui/TextInput.js'
|
|
6
6
|
import { theme } from '../../../ui/theme.js'
|
|
7
|
-
import {
|
|
8
|
-
formatRecordValue,
|
|
9
|
-
type AgentEnsRecordState,
|
|
10
|
-
} from '../../ens/agentRecords.js'
|
|
11
7
|
import {
|
|
12
8
|
isEthDomain,
|
|
13
9
|
sanitizeSubdomainPrefix,
|
|
@@ -24,9 +20,9 @@ import type { EnsEditProps } from './types.js'
|
|
|
24
20
|
|
|
25
21
|
export const footerHint = (hint: string) => <Text color={theme.dim}>{hint}</Text>
|
|
26
22
|
|
|
27
|
-
export const renderRecordValue = (
|
|
23
|
+
export const renderRecordValue = (value: string) =>
|
|
28
24
|
value
|
|
29
|
-
? <Text color={theme.accentPeriwinkle}>{
|
|
25
|
+
? <Text color={theme.accentPeriwinkle}>{value}</Text>
|
|
30
26
|
: <Text color={theme.dim}>Unset</Text>
|
|
31
27
|
|
|
32
28
|
export function rootErrorMessage(
|
|
@@ -18,7 +18,7 @@ export function recordsHaveCurrentValues(recordsDiff: AgentRecordDiff[]): boolea
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export function emptyAgentEnsRecords(): AgentEnsRecords {
|
|
21
|
-
return {
|
|
21
|
+
return {}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export function unlinkEnsLinkOptions(savedCustodyMode: CustodyMode | undefined, savedOwnerAddress: string): EnsLinkOptions {
|
|
@@ -84,8 +84,6 @@ export function manualReasonTitle(reason: EnsSetupBlockedPlan['reason']): string
|
|
|
84
84
|
case 'wrapped-parent':
|
|
85
85
|
case 'subdomain-wrapped':
|
|
86
86
|
return 'ENS NameWrapper ownership could not be verified'
|
|
87
|
-
case 'token-record-collision':
|
|
88
|
-
return 'Subdomain already points to another token'
|
|
89
87
|
case 'token-owner-mismatch':
|
|
90
88
|
return 'Owner wallet does not own this ERC-8004 token'
|
|
91
89
|
case 'token-owner-lookup-failed':
|