ethagent 1.0.2 → 1.0.3
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/package.json
CHANGED
|
@@ -24,9 +24,6 @@ import {
|
|
|
24
24
|
runRebackupPreflight,
|
|
25
25
|
runRebackupSigning,
|
|
26
26
|
runRebackupStorageSubmit,
|
|
27
|
-
runPublicProfilePreflight,
|
|
28
|
-
runPublicProfileSigning,
|
|
29
|
-
runPublicProfileStorageSubmit,
|
|
30
27
|
runRecoveryRefetch,
|
|
31
28
|
isAgentTokenIdRequiredError,
|
|
32
29
|
type EffectCallbacks,
|
|
@@ -190,16 +187,7 @@ export const IdentityHub: React.FC<IdentityHubProps> = ({ mode, config, initialA
|
|
|
190
187
|
.catch((err: unknown) => errorStep(err, backStep))
|
|
191
188
|
}
|
|
192
189
|
|
|
193
|
-
|
|
194
|
-
if (!identity) return
|
|
195
|
-
const registry = resolveRegistryForIdentity(identity)
|
|
196
|
-
if (!registry) {
|
|
197
|
-
errorStep(new Error('no agent registry configured for this identity'), backStep)
|
|
198
|
-
return
|
|
199
|
-
}
|
|
200
|
-
runPublicProfilePreflight(identity, registry, callbacks, profileUpdates, backStep)
|
|
201
|
-
.catch((err: unknown) => errorStep(err, backStep))
|
|
202
|
-
}
|
|
190
|
+
|
|
203
191
|
|
|
204
192
|
useEffect(() => {
|
|
205
193
|
if (step.kind !== 'rebackup-start') return
|
|
@@ -639,7 +627,7 @@ export const IdentityHub: React.FC<IdentityHubProps> = ({ mode, config, initialA
|
|
|
639
627
|
footer={footer}
|
|
640
628
|
onEditProfile={() => openPublicProfileEdit({ kind: 'continuity-public' })}
|
|
641
629
|
onOpenSkills={() => { void openContinuityFile('skills') }}
|
|
642
|
-
onPublish={() =>
|
|
630
|
+
onPublish={() => triggerRebackup({ kind: 'continuity-public' })}
|
|
643
631
|
onBack={back}
|
|
644
632
|
/>
|
|
645
633
|
)
|
|
@@ -689,8 +677,7 @@ export const IdentityHub: React.FC<IdentityHubProps> = ({ mode, config, initialA
|
|
|
689
677
|
onImageSubmit={imagePath => {
|
|
690
678
|
if (step.kind !== 'edit-profile-image') return
|
|
691
679
|
const updates: ProfileUpdates = { name: step.name, description: step.description, ...(imagePath ? { imagePath } : {}) }
|
|
692
|
-
|
|
693
|
-
.catch((err: unknown) => errorStep(err, step.returnTo ?? { kind: 'continuity-public' }))
|
|
680
|
+
triggerRebackup(step.returnTo ?? { kind: 'continuity-public' }, updates)
|
|
694
681
|
}}
|
|
695
682
|
onImagePick={() => {
|
|
696
683
|
if (step.kind !== 'edit-profile-image') return
|
|
@@ -702,8 +689,7 @@ export const IdentityHub: React.FC<IdentityHubProps> = ({ mode, config, initialA
|
|
|
702
689
|
return
|
|
703
690
|
}
|
|
704
691
|
const updates: ProfileUpdates = { name: imageStep.name, description: imageStep.description, imagePath: result.file }
|
|
705
|
-
|
|
706
|
-
.catch((err: unknown) => errorStep(err, imageStep.returnTo ?? { kind: 'continuity-public' }))
|
|
692
|
+
triggerRebackup(imageStep.returnTo ?? { kind: 'continuity-public' }, updates)
|
|
707
693
|
})
|
|
708
694
|
.catch((err: unknown) => {
|
|
709
695
|
setStep({ ...imageStep, error: `${(err as Error).message}. enter a path manually if needed.` })
|
|
@@ -727,17 +713,7 @@ export const IdentityHub: React.FC<IdentityHubProps> = ({ mode, config, initialA
|
|
|
727
713
|
)
|
|
728
714
|
}
|
|
729
715
|
|
|
730
|
-
|
|
731
|
-
return (
|
|
732
|
-
<WalletApprovalScreen
|
|
733
|
-
title="Approve Public Profile"
|
|
734
|
-
subtitle="Pins skills.json and the Agent Card, then updates tokenURI. Private files are not read."
|
|
735
|
-
walletSession={walletSession}
|
|
736
|
-
label="waiting for wallet approval..."
|
|
737
|
-
onCancel={() => setStep(step.returnTo ?? { kind: 'continuity-public' })}
|
|
738
|
-
/>
|
|
739
|
-
)
|
|
740
|
-
}
|
|
716
|
+
|
|
741
717
|
|
|
742
718
|
if (step.kind === 'rebackup-start') {
|
|
743
719
|
return (
|
|
@@ -752,18 +728,14 @@ export const IdentityHub: React.FC<IdentityHubProps> = ({ mode, config, initialA
|
|
|
752
728
|
|
|
753
729
|
|
|
754
730
|
|
|
755
|
-
if (step.kind === 'rebackup-storage'
|
|
731
|
+
if (step.kind === 'rebackup-storage') {
|
|
756
732
|
return (
|
|
757
733
|
<RebackupStorageScreen
|
|
758
734
|
step={step}
|
|
759
735
|
footer={footer}
|
|
760
736
|
onSubmit={async input => {
|
|
761
737
|
try {
|
|
762
|
-
|
|
763
|
-
await runRebackupStorageSubmit(input, step, callbacks)
|
|
764
|
-
} else {
|
|
765
|
-
await runPublicProfileStorageSubmit(input, step, callbacks)
|
|
766
|
-
}
|
|
738
|
+
await runRebackupStorageSubmit(input, step, callbacks)
|
|
767
739
|
} catch (err: unknown) {
|
|
768
740
|
setStep({ ...step, error: (err as Error).message })
|
|
769
741
|
}
|
|
@@ -751,85 +751,7 @@ export async function runRebackupStorageSubmit(
|
|
|
751
751
|
callbacks.onStep({ kind: 'rebackup-signing', identity: step.identity, registry: step.registry, pinataJwt, profileUpdates: step.profileUpdates, returnTo: step.returnTo })
|
|
752
752
|
}
|
|
753
753
|
|
|
754
|
-
export async function runPublicProfilePreflight(
|
|
755
|
-
identity: EthagentIdentity,
|
|
756
|
-
registry: Erc8004RegistryConfig,
|
|
757
|
-
callbacks: EffectCallbacks,
|
|
758
|
-
profileUpdates?: ProfileUpdates,
|
|
759
|
-
returnTo: Step = { kind: 'continuity-public' },
|
|
760
|
-
): Promise<void> {
|
|
761
|
-
const apiUrl = DEFAULT_IPFS_API_URL
|
|
762
|
-
let jwt: string | undefined
|
|
763
|
-
try {
|
|
764
|
-
jwt = isPinataUploadUrl(apiUrl) ? await resolveValidatedPinataJwt() : undefined
|
|
765
|
-
} catch (err: unknown) {
|
|
766
|
-
callbacks.onStep({ kind: 'public-profile-storage', identity, registry, error: (err as Error).message, profileUpdates, returnTo })
|
|
767
|
-
return
|
|
768
|
-
}
|
|
769
|
-
if (isPinataUploadUrl(apiUrl) && !jwt) {
|
|
770
|
-
callbacks.onStep({ kind: 'public-profile-storage', identity, registry, profileUpdates, returnTo })
|
|
771
|
-
return
|
|
772
|
-
}
|
|
773
|
-
callbacks.onStep({ kind: 'public-profile-signing', identity, registry, pinataJwt: jwt, profileUpdates, returnTo })
|
|
774
|
-
}
|
|
775
754
|
|
|
776
|
-
export async function runPublicProfileSigning(
|
|
777
|
-
step: Extract<Step, { kind: 'public-profile-signing' }>,
|
|
778
|
-
callbacks: EffectCallbacks,
|
|
779
|
-
): Promise<void> {
|
|
780
|
-
const expectedOwner = getAddress(step.identity.ownerAddress ?? step.identity.address)
|
|
781
|
-
if (!step.identity.agentId) throw new Error('cannot publish public profile: identity is missing an agent token id')
|
|
782
|
-
|
|
783
|
-
const prepared = await preparePublicProfileTransaction(step, expectedOwner)
|
|
784
|
-
const agentId = BigInt(step.identity.agentId)
|
|
785
|
-
await preflightSetAgentUri({
|
|
786
|
-
...step.registry,
|
|
787
|
-
account: expectedOwner,
|
|
788
|
-
agentId,
|
|
789
|
-
newUri: prepared.agentUri,
|
|
790
|
-
})
|
|
791
|
-
|
|
792
|
-
const tx = await sendBrowserWalletTransaction({
|
|
793
|
-
chainId: step.registry.chainId,
|
|
794
|
-
expectedAccount: expectedOwner,
|
|
795
|
-
to: step.registry.identityRegistryAddress,
|
|
796
|
-
data: encodeSetAgentUri({ agentId, newUri: prepared.agentUri }),
|
|
797
|
-
onReady: callbacks.onWalletReady,
|
|
798
|
-
})
|
|
799
|
-
const client = createErc8004PublicClient(step.registry)
|
|
800
|
-
await client.waitForTransactionReceipt({ hash: tx.txHash })
|
|
801
|
-
|
|
802
|
-
const nextIdentity: EthagentIdentity = {
|
|
803
|
-
...prepared.identity,
|
|
804
|
-
source: 'erc8004',
|
|
805
|
-
address: getAddress(prepared.ownerAddress),
|
|
806
|
-
ownerAddress: getAddress(prepared.ownerAddress),
|
|
807
|
-
chainId: step.registry.chainId,
|
|
808
|
-
rpcUrl: step.registry.rpcUrl,
|
|
809
|
-
identityRegistryAddress: step.registry.identityRegistryAddress,
|
|
810
|
-
agentUri: prepared.agentUri,
|
|
811
|
-
metadataCid: prepared.metadataCid,
|
|
812
|
-
publicSkills: prepared.publicSkills,
|
|
813
|
-
}
|
|
814
|
-
await writePublicSkillsFile(nextIdentity, prepared.publicSkillsJson)
|
|
815
|
-
await callbacks.onIdentityComplete(nextIdentity, step.profileUpdates ? 'public profile updated' : 'public profile published')
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
export async function runPublicProfileStorageSubmit(
|
|
819
|
-
input: string,
|
|
820
|
-
step: Extract<Step, { kind: 'public-profile-storage' }>,
|
|
821
|
-
callbacks: EffectCallbacks,
|
|
822
|
-
): Promise<void> {
|
|
823
|
-
const { jwt: pinataJwt } = await savePinataJwt(input)
|
|
824
|
-
callbacks.onStep({
|
|
825
|
-
kind: 'public-profile-signing',
|
|
826
|
-
identity: step.identity,
|
|
827
|
-
registry: step.registry,
|
|
828
|
-
pinataJwt,
|
|
829
|
-
profileUpdates: step.profileUpdates,
|
|
830
|
-
returnTo: step.returnTo,
|
|
831
|
-
})
|
|
832
|
-
}
|
|
833
755
|
|
|
834
756
|
|
|
835
757
|
export async function runRecoveryRefetch(
|
|
@@ -915,92 +837,7 @@ export async function runRecoveryRefetch(
|
|
|
915
837
|
}
|
|
916
838
|
|
|
917
839
|
|
|
918
|
-
|
|
919
|
-
step: Extract<Step, { kind: 'public-profile-signing' }>,
|
|
920
|
-
ownerAddress: Address,
|
|
921
|
-
): Promise<PublicProfilePreparedTransaction> {
|
|
922
|
-
const baseState = (step.identity.state ?? {}) as Record<string, unknown>
|
|
923
|
-
const profile = step.profileUpdates ?? {}
|
|
924
|
-
const nextName = typeof profile.name === 'string' && profile.name.trim()
|
|
925
|
-
? profile.name.trim()
|
|
926
|
-
: (typeof baseState.name === 'string' && baseState.name.trim() ? baseState.name.trim() : deriveAgentName(step.identity))
|
|
927
|
-
const nextDescription = profile.description !== undefined
|
|
928
|
-
? profile.description.trim()
|
|
929
|
-
: (typeof baseState.description === 'string' ? baseState.description : '')
|
|
930
|
-
const uploadedImageUri = profile.imagePath === 'delete'
|
|
931
|
-
? ''
|
|
932
|
-
: profile.imagePath
|
|
933
|
-
? await uploadAgentImage(profile.imagePath, step.pinataJwt)
|
|
934
|
-
: typeof baseState.imageUrl === 'string' && baseState.imageUrl.trim()
|
|
935
|
-
? baseState.imageUrl.trim()
|
|
936
|
-
: undefined
|
|
937
|
-
const updatedAt = new Date().toISOString()
|
|
938
|
-
const state: Record<string, unknown> = {
|
|
939
|
-
...baseState,
|
|
940
|
-
name: nextName,
|
|
941
|
-
description: nextDescription,
|
|
942
|
-
publicProfileUpdatedAt: updatedAt,
|
|
943
|
-
}
|
|
944
|
-
if (uploadedImageUri === '') {
|
|
945
|
-
delete state.imageUrl
|
|
946
|
-
} else if (uploadedImageUri) {
|
|
947
|
-
state.imageUrl = uploadedImageUri
|
|
948
|
-
}
|
|
949
|
-
const nextIdentityForFiles: EthagentIdentity = { ...step.identity, state }
|
|
950
|
-
const publicSkillsJson = step.profileUpdates
|
|
951
|
-
? await prepareSyncedPublicSkillsJson(nextIdentityForFiles)
|
|
952
|
-
: await ensurePublicSkillsFile(nextIdentityForFiles)
|
|
953
|
-
const publicSkillsPin = await addToIpfs(DEFAULT_IPFS_API_URL, publicSkillsJson, fetch, { pinataJwt: step.pinataJwt })
|
|
954
|
-
assertVerifiedPin(publicSkillsPin)
|
|
955
|
-
const agentCardPin = await addToIpfs(
|
|
956
|
-
DEFAULT_IPFS_API_URL,
|
|
957
|
-
serializeAgentCard(createAgentCard(defaultPublicSkillsProfile(nextIdentityForFiles))),
|
|
958
|
-
fetch,
|
|
959
|
-
{ pinataJwt: step.pinataJwt },
|
|
960
|
-
)
|
|
961
|
-
assertVerifiedPin(agentCardPin)
|
|
962
|
-
const publicSkills: PublicSkillsMetadata = {
|
|
963
|
-
cid: publicSkillsPin.cid,
|
|
964
|
-
agentCardCid: agentCardPin.cid,
|
|
965
|
-
updatedAt,
|
|
966
|
-
status: 'pinned',
|
|
967
|
-
}
|
|
968
|
-
const backup = step.identity.backup
|
|
969
|
-
const registration = withEthagentPointers({
|
|
970
|
-
type: 'https://eips.ethereum.org/EIPS/eip-8004#registration-v1',
|
|
971
|
-
name: nextName,
|
|
972
|
-
...(nextDescription ? { description: nextDescription } : {}),
|
|
973
|
-
...(uploadedImageUri ? { image: uploadedImageUri } : {}),
|
|
974
|
-
}, {
|
|
975
|
-
...(backup ? {
|
|
976
|
-
backup: {
|
|
977
|
-
cid: backup.cid,
|
|
978
|
-
envelopeVersion: backup.envelopeVersion,
|
|
979
|
-
createdAt: backup.createdAt,
|
|
980
|
-
},
|
|
981
|
-
} : {}),
|
|
982
|
-
publicDiscovery: {
|
|
983
|
-
skillsCid: publicSkills.cid,
|
|
984
|
-
agentCardCid: publicSkills.agentCardCid,
|
|
985
|
-
updatedAt,
|
|
986
|
-
},
|
|
987
|
-
registration: {
|
|
988
|
-
chainId: step.registry.chainId,
|
|
989
|
-
identityRegistryAddress: step.registry.identityRegistryAddress,
|
|
990
|
-
agentId: step.identity.agentId,
|
|
991
|
-
},
|
|
992
|
-
})
|
|
993
|
-
const metadataPin = await addToIpfs(DEFAULT_IPFS_API_URL, JSON.stringify(registration, null, 2), fetch, { pinataJwt: step.pinataJwt })
|
|
994
|
-
assertVerifiedPin(metadataPin)
|
|
995
|
-
return {
|
|
996
|
-
ownerAddress,
|
|
997
|
-
agentUri: `ipfs://${metadataPin.cid}`,
|
|
998
|
-
metadataCid: metadataPin.cid,
|
|
999
|
-
publicSkills,
|
|
1000
|
-
identity: { ...step.identity, state },
|
|
1001
|
-
publicSkillsJson,
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
840
|
+
|
|
1004
841
|
|
|
1005
842
|
function deriveAgentName(identity: EthagentIdentity): string {
|
|
1006
843
|
const state = (identity.state ?? {}) as Record<string, unknown>
|
|
@@ -45,8 +45,8 @@ export const PrivateContinuityScreen: React.FC<CommonProps & {
|
|
|
45
45
|
{ value: 'soul', role: 'section', prefix: '--', label: 'Open local files' },
|
|
46
46
|
{ value: 'soul', label: 'open SOUL.md', hint: 'edit persona and operating preferences', disabled: !ready },
|
|
47
47
|
{ value: 'memory', label: 'open MEMORY.md', hint: 'edit private working memory for this agent', disabled: !ready },
|
|
48
|
-
{ value: 'backup', role: 'section', prefix: '--', label: '
|
|
49
|
-
{ value: 'backup', label: '
|
|
48
|
+
{ value: 'backup', role: 'section', prefix: '--', label: 'Recovery' },
|
|
49
|
+
{ value: 'backup', label: 'publish snapshot now', hint: 'publishes SOUL.md, MEMORY.md, skills.json, and metadata', disabled: !ready || !canBackup },
|
|
50
50
|
{ value: 'back', role: 'section', prefix: '--', label: 'Navigation' },
|
|
51
51
|
{ value: 'back', label: 'back to identity hub', hint: 'return without changing private files', role: 'utility' },
|
|
52
52
|
]}
|
|
@@ -69,7 +69,7 @@ export const PublicSkillsScreen: React.FC<CommonProps & {
|
|
|
69
69
|
onOpenSkills: () => void
|
|
70
70
|
onPublish: () => void
|
|
71
71
|
}> = ({ identity, config, notice, footer, canPublish, onEditProfile, onOpenSkills, onPublish, onBack }) => (
|
|
72
|
-
<Surface title="Public Profile" subtitle={notice ?? '
|
|
72
|
+
<Surface title="Public Profile" subtitle={notice ?? 'Manage public metadata, skills.json, and the agent card.'} footer={footer}>
|
|
73
73
|
<IdentitySummary identity={identity} config={config} compact />
|
|
74
74
|
<PublicProfileRows identity={identity} />
|
|
75
75
|
<Box marginTop={1}>
|
|
@@ -79,8 +79,8 @@ export const PublicSkillsScreen: React.FC<CommonProps & {
|
|
|
79
79
|
{ value: 'edit', label: 'edit name, description, image', hint: 'upload a local image to IPFS automatically' },
|
|
80
80
|
{ value: 'skills', role: 'section', prefix: '--', label: 'Capabilities' },
|
|
81
81
|
{ value: 'skills', label: 'open skills.json', hint: 'edit public capabilities and notes' },
|
|
82
|
-
{ value: 'publish', role: 'section', prefix: '--', label: '
|
|
83
|
-
{ value: 'publish', label: 'publish
|
|
82
|
+
{ value: 'publish', role: 'section', prefix: '--', label: 'Recovery' },
|
|
83
|
+
{ value: 'publish', label: 'publish snapshot now', hint: 'publishes SOUL.md, MEMORY.md, skills.json, and metadata', disabled: !canPublish },
|
|
84
84
|
{ value: 'back', role: 'section', prefix: '--', label: 'Navigation' },
|
|
85
85
|
{ value: 'back', label: 'back to identity hub', hint: 'return without changing public metadata', role: 'utility' },
|
|
86
86
|
]}
|
|
@@ -69,7 +69,7 @@ export const MenuScreen: React.FC<MenuScreenProps> = ({
|
|
|
69
69
|
{ value: 'private-memory', role: 'section', prefix: '--', label: 'Private local files' },
|
|
70
70
|
{ value: 'private-memory', label: 'memory and persona', hint: 'SOUL.md and MEMORY.md only on this device' },
|
|
71
71
|
{ value: 'backup', role: 'section', prefix: '--', label: 'Recovery' },
|
|
72
|
-
{ value: 'backup', label: 'publish snapshot now', hint: '
|
|
72
|
+
{ value: 'backup', label: 'publish snapshot now', hint: 'publishes SOUL.md, MEMORY.md, skills.json, and metadata', disabled: !canRebackup },
|
|
73
73
|
{ value: 'refetch', label: 'refetch latest snapshot', hint: 'restore local files from the latest published snapshot', disabled: !canRefetch },
|
|
74
74
|
{ value: 'storage-credential', role: 'section', prefix: '--', label: 'Storage' },
|
|
75
75
|
{ value: 'storage-credential', label: 'IPFS credential', hint: 'save, replace, or forget Pinata JWT' },
|