edge-book 0.2.4 → 0.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/dist/edge-book.js +303 -9
- package/package.json +1 -1
package/dist/edge-book.js
CHANGED
|
@@ -42,6 +42,11 @@ var POSTS_FILE = "posts.json";
|
|
|
42
42
|
var FEED_FILE = "feed-items.json";
|
|
43
43
|
var APPROVALS_FILE = "approvals.json";
|
|
44
44
|
var CONTACT_MUTES_FILE = "contact-mutes.json";
|
|
45
|
+
var ATTESTATIONS_FILE = "attestations.json";
|
|
46
|
+
var ENDORSEMENTS_FILE = "endorsements.json";
|
|
47
|
+
var SIGNALS_FILE = "signals.json";
|
|
48
|
+
var CAPABILITIES_FILE = "capabilities.json";
|
|
49
|
+
var DEFAULT_SIGNAL_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
45
50
|
function resolveHome(home) {
|
|
46
51
|
if (home?.trim()) return path.resolve(home.trim());
|
|
47
52
|
if (process.env.EDGE_BOOK_HOME?.trim()) return path.resolve(process.env.EDGE_BOOK_HOME.trim());
|
|
@@ -57,6 +62,9 @@ function stableIdFromPublicKey(publicKeyPem) {
|
|
|
57
62
|
const digest = crypto.createHash("sha256").update(publicKeyPem).digest("base64url").slice(0, 32);
|
|
58
63
|
return `did:openclaw:${digest}`;
|
|
59
64
|
}
|
|
65
|
+
function contentHash(value) {
|
|
66
|
+
return crypto.createHash("sha256").update(canonicalize(value)).digest("base64url");
|
|
67
|
+
}
|
|
60
68
|
function canonicalize(value) {
|
|
61
69
|
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
62
70
|
if (Array.isArray(value)) return `[${value.map(canonicalize).join(",")}]`;
|
|
@@ -186,6 +194,7 @@ var EdgeBookStore = class {
|
|
|
186
194
|
const identity = await this.identity();
|
|
187
195
|
if (input.displayName !== void 0 && input.displayName !== "") identity.display_name = input.displayName;
|
|
188
196
|
if (input.ownerLabel !== void 0) identity.owner_label = input.ownerLabel;
|
|
197
|
+
if (input.shareOwnerLabel !== void 0) identity.share_owner_label = input.shareOwnerLabel;
|
|
189
198
|
identity.updated_at = now();
|
|
190
199
|
await writeJson(this.file(IDENTITY_FILE), identity, 384);
|
|
191
200
|
await this.writeCard();
|
|
@@ -214,6 +223,8 @@ var EdgeBookStore = class {
|
|
|
214
223
|
agent_id: identity.agent_id,
|
|
215
224
|
handle: identity.handle,
|
|
216
225
|
display_name: identity.display_name,
|
|
226
|
+
// Opt-in only: include the human owner name when the owner enabled sharing.
|
|
227
|
+
...identity.share_owner_label && identity.owner_label ? { owner_label: identity.owner_label } : {},
|
|
217
228
|
card_url: cardUrl || `file://${this.file(CARD_FILE)}`,
|
|
218
229
|
card_version: 1,
|
|
219
230
|
public_keys: [{ id: `${identity.agent_id}#main`, type: "ed25519", public_key_pem: identity.public_key_pem }],
|
|
@@ -296,6 +307,9 @@ var EdgeBookStore = class {
|
|
|
296
307
|
peer_agent_id: card.agent_id,
|
|
297
308
|
aliases: Array.from(new Set([...existing?.aliases ?? [], card.handle].filter(Boolean))),
|
|
298
309
|
display_name: card.display_name,
|
|
310
|
+
// Carry the peer's shared human name (undefined if they didn't opt in, or
|
|
311
|
+
// dropped on refresh if they turned sharing off).
|
|
312
|
+
owner_label: card.owner_label,
|
|
299
313
|
card_url: card.card_url,
|
|
300
314
|
known_endpoints: card.transports,
|
|
301
315
|
public_keys: card.public_keys,
|
|
@@ -532,6 +546,209 @@ var EdgeBookStore = class {
|
|
|
532
546
|
await this.audit("object.create", identity.agent_id, { object_id, has_attachment: Boolean(attachment) });
|
|
533
547
|
return object;
|
|
534
548
|
}
|
|
549
|
+
// ─── spec-0021 post-type store methods ──────────────────────────────────
|
|
550
|
+
// Class 4: Result Attestation — content-addressed, write-once (R6)
|
|
551
|
+
async attestations() {
|
|
552
|
+
return readJson(this.file(ATTESTATIONS_FILE), {});
|
|
553
|
+
}
|
|
554
|
+
async saveAttestations(attestations) {
|
|
555
|
+
await writeJson(this.file(ATTESTATIONS_FILE), attestations);
|
|
556
|
+
}
|
|
557
|
+
async saveEndorsements(endorsements) {
|
|
558
|
+
await writeJson(this.file(ENDORSEMENTS_FILE), endorsements);
|
|
559
|
+
}
|
|
560
|
+
async saveSignals(signals) {
|
|
561
|
+
await writeJson(this.file(SIGNALS_FILE), signals);
|
|
562
|
+
}
|
|
563
|
+
async saveCapabilities(capabilities) {
|
|
564
|
+
await writeJson(this.file(CAPABILITIES_FILE), capabilities);
|
|
565
|
+
}
|
|
566
|
+
async createAttestation(input) {
|
|
567
|
+
const identity = await this.identity();
|
|
568
|
+
const content = {
|
|
569
|
+
post_type: "result_attestation",
|
|
570
|
+
schema: "edge-book/result-attestation/0.1",
|
|
571
|
+
attestor_agent_id: identity.agent_id,
|
|
572
|
+
subject_agent_id: input.subject_agent_id,
|
|
573
|
+
task_ref: input.task_ref,
|
|
574
|
+
outcome: input.outcome,
|
|
575
|
+
summary: input.summary,
|
|
576
|
+
evidence: input.evidence ?? {},
|
|
577
|
+
created_at: input.created_at ?? now()
|
|
578
|
+
};
|
|
579
|
+
const attestation_id = contentHash(content);
|
|
580
|
+
const attestation = {
|
|
581
|
+
...content,
|
|
582
|
+
attestation_id,
|
|
583
|
+
signature: signPayload({ ...content, attestation_id }, identity.private_key_pem)
|
|
584
|
+
};
|
|
585
|
+
const all = await this.attestations();
|
|
586
|
+
if (!all[attestation_id]) {
|
|
587
|
+
all[attestation_id] = attestation;
|
|
588
|
+
await this.saveAttestations(all);
|
|
589
|
+
await this.audit("attestation.create", input.subject_agent_id, { attestation_id, task_ref: input.task_ref });
|
|
590
|
+
}
|
|
591
|
+
return all[attestation_id];
|
|
592
|
+
}
|
|
593
|
+
async verifyAttestation(att) {
|
|
594
|
+
const identity = await this.identity();
|
|
595
|
+
let pub = identity.agent_id === att.attestor_agent_id ? identity.public_key_pem : void 0;
|
|
596
|
+
if (!pub) {
|
|
597
|
+
const c = (await this.contacts())[att.attestor_agent_id];
|
|
598
|
+
pub = c?.public_keys?.[0]?.public_key_pem;
|
|
599
|
+
}
|
|
600
|
+
if (!pub) return false;
|
|
601
|
+
const { signature, ...signedPayload } = att;
|
|
602
|
+
const { attestation_id, ...content } = signedPayload;
|
|
603
|
+
if (contentHash(content) !== attestation_id) return false;
|
|
604
|
+
return verifyPayload(signedPayload, signature, pub);
|
|
605
|
+
}
|
|
606
|
+
async verifyCapability(cap) {
|
|
607
|
+
const identity = await this.identity();
|
|
608
|
+
let pub = identity.agent_id === cap.agent_id ? identity.public_key_pem : void 0;
|
|
609
|
+
if (!pub) {
|
|
610
|
+
const c = (await this.contacts())[cap.agent_id];
|
|
611
|
+
pub = c?.public_keys?.[0]?.public_key_pem;
|
|
612
|
+
}
|
|
613
|
+
if (!pub) return false;
|
|
614
|
+
const { signature, ...rest } = cap;
|
|
615
|
+
return verifyPayload(rest, signature, pub);
|
|
616
|
+
}
|
|
617
|
+
// Class 3: Endorse — actor-owned reified edge, strongRef parent, evidence link (R5, R8)
|
|
618
|
+
async endorsements() {
|
|
619
|
+
return readJson(this.file(ENDORSEMENTS_FILE), {});
|
|
620
|
+
}
|
|
621
|
+
async createEndorsement(input) {
|
|
622
|
+
if (!input.evidence_ref && !input.evidence_task_id) {
|
|
623
|
+
throw new EdgeBookError("missing_evidence", "Endorse requires an evidence link (Result Attestation ref or task id) \u2014 R8");
|
|
624
|
+
}
|
|
625
|
+
if (!input.parent?.uri || !input.parent?.hash) {
|
|
626
|
+
throw new EdgeBookError("missing_parent", "Endorse requires a strongRef parent (uri + hash) \u2014 R5");
|
|
627
|
+
}
|
|
628
|
+
const identity = await this.identity();
|
|
629
|
+
const endorse_id = randomId("end");
|
|
630
|
+
const stamp = now();
|
|
631
|
+
const unsigned = {
|
|
632
|
+
endorse_id,
|
|
633
|
+
post_type: "endorse",
|
|
634
|
+
schema: "edge-book/endorse/0.1",
|
|
635
|
+
endorser_agent_id: identity.agent_id,
|
|
636
|
+
// actor-owned (R5)
|
|
637
|
+
subject_agent_id: input.subject_agent_id,
|
|
638
|
+
parent: input.parent,
|
|
639
|
+
...input.evidence_ref ? { evidence_ref: input.evidence_ref } : {},
|
|
640
|
+
...input.evidence_task_id ? { evidence_task_id: input.evidence_task_id } : {},
|
|
641
|
+
statement: input.statement,
|
|
642
|
+
created_at: stamp
|
|
643
|
+
};
|
|
644
|
+
const endorsement = { ...unsigned, signature: signPayload(unsigned, identity.private_key_pem) };
|
|
645
|
+
const all = await this.endorsements();
|
|
646
|
+
all[endorse_id] = endorsement;
|
|
647
|
+
await this.saveEndorsements(all);
|
|
648
|
+
await this.audit("endorse.create", input.subject_agent_id, { endorse_id, parent: input.parent.uri });
|
|
649
|
+
return endorsement;
|
|
650
|
+
}
|
|
651
|
+
// Class 2: Signal — ephemeral, lifecycle + TTL (R4)
|
|
652
|
+
signalLifecycle(sig) {
|
|
653
|
+
if (sig.lifecycle === "expired") return "expired";
|
|
654
|
+
return Date.parse(sig.expires_at) <= Date.now() ? "stale" : "active";
|
|
655
|
+
}
|
|
656
|
+
async signals() {
|
|
657
|
+
const raw = await readJson(this.file(SIGNALS_FILE), {});
|
|
658
|
+
for (const id of Object.keys(raw)) raw[id].lifecycle = this.signalLifecycle(raw[id]);
|
|
659
|
+
return raw;
|
|
660
|
+
}
|
|
661
|
+
async createSignal(input) {
|
|
662
|
+
const identity = await this.identity();
|
|
663
|
+
const signal_id = randomId("sig");
|
|
664
|
+
const created = now();
|
|
665
|
+
const expires_at = new Date(Date.now() + (input.ttlMs ?? DEFAULT_SIGNAL_TTL_MS)).toISOString();
|
|
666
|
+
const unsigned = {
|
|
667
|
+
signal_id,
|
|
668
|
+
post_type: "signal",
|
|
669
|
+
schema: "edge-book/signal/0.1",
|
|
670
|
+
from_agent: identity.agent_id,
|
|
671
|
+
body: input.body,
|
|
672
|
+
lifecycle: "active",
|
|
673
|
+
created_at: created,
|
|
674
|
+
expires_at
|
|
675
|
+
};
|
|
676
|
+
const signal = { ...unsigned, signature: signPayload(unsigned, identity.private_key_pem) };
|
|
677
|
+
const all = await this.signals();
|
|
678
|
+
all[signal_id] = signal;
|
|
679
|
+
await this.saveSignals(all);
|
|
680
|
+
await this.audit("signal.create", identity.agent_id, { signal_id });
|
|
681
|
+
return signal;
|
|
682
|
+
}
|
|
683
|
+
async expireSignals() {
|
|
684
|
+
const all = await readJson(this.file(SIGNALS_FILE), {});
|
|
685
|
+
let changed = false;
|
|
686
|
+
for (const id of Object.keys(all)) {
|
|
687
|
+
if (all[id].lifecycle !== "expired" && Date.parse(all[id].expires_at) <= Date.now()) {
|
|
688
|
+
all[id].lifecycle = "expired";
|
|
689
|
+
changed = true;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
if (changed) await this.saveSignals(all);
|
|
693
|
+
}
|
|
694
|
+
// Class 1: Capability Advertisement — versioned, deprecate-not-delete (R3)
|
|
695
|
+
async capabilities() {
|
|
696
|
+
return readJson(this.file(CAPABILITIES_FILE), {});
|
|
697
|
+
}
|
|
698
|
+
async advertiseCapability(input) {
|
|
699
|
+
const identity = await this.identity();
|
|
700
|
+
const capability_id = randomId("cap");
|
|
701
|
+
const stamp = now();
|
|
702
|
+
const unsigned = {
|
|
703
|
+
capability_id,
|
|
704
|
+
post_type: "capability_advertisement",
|
|
705
|
+
schema: "edge-book/capability/0.1",
|
|
706
|
+
agent_id: identity.agent_id,
|
|
707
|
+
name: input.name,
|
|
708
|
+
version: input.version,
|
|
709
|
+
summary: input.summary,
|
|
710
|
+
status: "active",
|
|
711
|
+
created_at: stamp,
|
|
712
|
+
updated_at: stamp
|
|
713
|
+
};
|
|
714
|
+
const cap = { ...unsigned, signature: signPayload(unsigned, identity.private_key_pem) };
|
|
715
|
+
const all = await this.capabilities();
|
|
716
|
+
all[capability_id] = cap;
|
|
717
|
+
await this.saveCapabilities(all);
|
|
718
|
+
await this.audit("capability.advertise", identity.agent_id, { capability_id, name: input.name });
|
|
719
|
+
return cap;
|
|
720
|
+
}
|
|
721
|
+
async deprecateCapability(capabilityId) {
|
|
722
|
+
const identity = await this.identity();
|
|
723
|
+
const all = await this.capabilities();
|
|
724
|
+
const cap = all[capabilityId];
|
|
725
|
+
if (!cap) throw new EdgeBookError("not_found", `No capability ${capabilityId}`);
|
|
726
|
+
cap.status = "deprecated";
|
|
727
|
+
cap.updated_at = now();
|
|
728
|
+
const { signature: _sig, ...rest } = cap;
|
|
729
|
+
cap.signature = signPayload(rest, identity.private_key_pem);
|
|
730
|
+
await this.saveCapabilities(all);
|
|
731
|
+
await this.audit("capability.deprecate", identity.agent_id, { capability_id: capabilityId });
|
|
732
|
+
return cap;
|
|
733
|
+
}
|
|
734
|
+
// R7 cascade: deprecate Class 1, terminate open Class 2, RETAIN Class 3 + Class 4.
|
|
735
|
+
async deregister() {
|
|
736
|
+
const identity = await this.identity();
|
|
737
|
+
const caps = await this.capabilities();
|
|
738
|
+
for (const id of Object.keys(caps)) {
|
|
739
|
+
if (caps[id].status === "active") {
|
|
740
|
+
caps[id].status = "deprecated";
|
|
741
|
+
caps[id].updated_at = now();
|
|
742
|
+
const { signature: _sig, ...rest } = caps[id];
|
|
743
|
+
caps[id].signature = signPayload(rest, identity.private_key_pem);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
await this.saveCapabilities(caps);
|
|
747
|
+
const sigs = await readJson(this.file(SIGNALS_FILE), {});
|
|
748
|
+
for (const id of Object.keys(sigs)) sigs[id].lifecycle = "expired";
|
|
749
|
+
await this.saveSignals(sigs);
|
|
750
|
+
await this.audit("agent.deregister", (await this.identity()).agent_id, {});
|
|
751
|
+
}
|
|
535
752
|
// Issue an `object.read` grant binding ONE object to ONE subject (revocable).
|
|
536
753
|
async issueObjectGrant(subjectAgentId, objectId, expiresAt = "") {
|
|
537
754
|
const identity = await this.identity();
|
|
@@ -1334,6 +1551,22 @@ async function handleOwnerApi(req, res, url, adapters) {
|
|
|
1334
1551
|
sendJson(res, 200, { contacts: await store.contacts(), mutes: await store.contactMutes() });
|
|
1335
1552
|
return true;
|
|
1336
1553
|
}
|
|
1554
|
+
if (req.method === "GET" && url.pathname === "/api/signals") {
|
|
1555
|
+
sendJson(res, 200, { signals: await store.signals() });
|
|
1556
|
+
return true;
|
|
1557
|
+
}
|
|
1558
|
+
if (req.method === "GET" && url.pathname === "/api/attestations") {
|
|
1559
|
+
sendJson(res, 200, { attestations: await store.attestations() });
|
|
1560
|
+
return true;
|
|
1561
|
+
}
|
|
1562
|
+
if (req.method === "GET" && url.pathname === "/api/endorsements") {
|
|
1563
|
+
sendJson(res, 200, { endorsements: await store.endorsements() });
|
|
1564
|
+
return true;
|
|
1565
|
+
}
|
|
1566
|
+
if (req.method === "GET" && url.pathname === "/api/capabilities") {
|
|
1567
|
+
sendJson(res, 200, { capabilities: await store.capabilities() });
|
|
1568
|
+
return true;
|
|
1569
|
+
}
|
|
1337
1570
|
if (req.method === "GET" && url.pathname === "/api/shared-objects") {
|
|
1338
1571
|
const objects = await store.sharedObjectsFor();
|
|
1339
1572
|
sendJson(res, 200, { objects: objects.map((object) => ({ ...object, grant_scope: "object.read" })) });
|
|
@@ -3160,7 +3393,8 @@ function usage() {
|
|
|
3160
3393
|
Usage:
|
|
3161
3394
|
edge-book init [--home <dir>] [--handle <handle>] [--name <agent name>] [--owner <human owner>]
|
|
3162
3395
|
edge-book profile show [--home <dir>]
|
|
3163
|
-
edge-book profile set [--name <agent name>] [--owner <human owner>] [--home <dir>]
|
|
3396
|
+
edge-book profile set [--name <agent name>] [--owner <human owner>] [--share-owner | --no-share-owner] [--home <dir>]
|
|
3397
|
+
# owner name is private by default; --share-owner exposes it on your card
|
|
3164
3398
|
|
|
3165
3399
|
Hosted reader:
|
|
3166
3400
|
edge-book dialout [--host <ws-url>] [--home <dir>]
|
|
@@ -3192,7 +3426,15 @@ Local agent:
|
|
|
3192
3426
|
edge-book inbox pull --relay <url> [--home <dir>]
|
|
3193
3427
|
edge-book serve --host <host> --port <port> [--home <dir>]
|
|
3194
3428
|
edge-book relay serve --host <host> --port <port> --store <dir>
|
|
3195
|
-
edge-book harness two-agent
|
|
3429
|
+
edge-book harness two-agent
|
|
3430
|
+
|
|
3431
|
+
Post taxonomy (spec-0021):
|
|
3432
|
+
edge-book attest --subject <id> --task <ref> --outcome <success|failure|partial> --summary <s>
|
|
3433
|
+
edge-book endorse <subject-agent-id> --parent-uri <uri> --parent-hash <h> (--evidence-attestation <id> | --evidence-task <id>) --statement <s>
|
|
3434
|
+
edge-book signal --body <s> [--ttl-ms <ms>]
|
|
3435
|
+
edge-book capability advertise --name <n> --version <v> --summary <s>
|
|
3436
|
+
edge-book capability deprecate <capability-id>
|
|
3437
|
+
edge-book capability list`;
|
|
3196
3438
|
}
|
|
3197
3439
|
function takeFlag(args, name) {
|
|
3198
3440
|
const idx = args.indexOf(name);
|
|
@@ -3262,22 +3504,27 @@ async function handleCli(inputArgs, ctx = {}) {
|
|
|
3262
3504
|
const action = args.shift() || "show";
|
|
3263
3505
|
if (action === "show") {
|
|
3264
3506
|
const id = await store.identity();
|
|
3507
|
+
const shared = id.share_owner_label ? "shared with contacts" : "private (default)";
|
|
3265
3508
|
return {
|
|
3266
3509
|
text: `display_name: ${id.display_name}
|
|
3267
|
-
owner_label: ${id.owner_label || "(unset)"}
|
|
3268
|
-
|
|
3510
|
+
owner_label: ${id.owner_label || "(unset)"}
|
|
3511
|
+
share_owner_label: ${id.share_owner_label ? "true" : "false"} (${shared})`,
|
|
3512
|
+
json: { agent_id: id.agent_id, display_name: id.display_name, owner_label: id.owner_label, share_owner_label: Boolean(id.share_owner_label) }
|
|
3269
3513
|
};
|
|
3270
3514
|
}
|
|
3271
3515
|
if (action === "set") {
|
|
3272
3516
|
const displayName = takeFlag(args, "--name");
|
|
3273
3517
|
const ownerLabel = takeFlag(args, "--owner");
|
|
3274
|
-
|
|
3275
|
-
|
|
3518
|
+
const shareOwner = takeBoolFlag(args, "--share-owner");
|
|
3519
|
+
const noShareOwner = takeBoolFlag(args, "--no-share-owner");
|
|
3520
|
+
const shareOwnerLabel = shareOwner ? true : noShareOwner ? false : void 0;
|
|
3521
|
+
if (displayName === void 0 && ownerLabel === void 0 && shareOwnerLabel === void 0) {
|
|
3522
|
+
throw new EdgeBookError("missing_arg", "profile set needs --name (agent name), --owner (human owner), and/or --share-owner|--no-share-owner");
|
|
3276
3523
|
}
|
|
3277
|
-
const id = await store.setProfile({ displayName, ownerLabel });
|
|
3524
|
+
const id = await store.setProfile({ displayName, ownerLabel, shareOwnerLabel });
|
|
3278
3525
|
return {
|
|
3279
|
-
text: `Updated profile: display_name=${id.display_name} owner_label=${id.owner_label || "(unset)"}`,
|
|
3280
|
-
json: { agent_id: id.agent_id, display_name: id.display_name, owner_label: id.owner_label }
|
|
3526
|
+
text: `Updated profile: display_name=${id.display_name} owner_label=${id.owner_label || "(unset)"} share_owner_label=${id.share_owner_label ? "true" : "false"}`,
|
|
3527
|
+
json: { agent_id: id.agent_id, display_name: id.display_name, owner_label: id.owner_label, share_owner_label: Boolean(id.share_owner_label) }
|
|
3281
3528
|
};
|
|
3282
3529
|
}
|
|
3283
3530
|
throw new EdgeBookError("unknown_action", `Unknown profile action: ${action} (use "show" or "set")`);
|
|
@@ -3531,6 +3778,53 @@ Expires in: ${registration.frame.ttl_ms}ms`, json: registration };
|
|
|
3531
3778
|
${JSON.stringify(result, null, 2)}`, json: result };
|
|
3532
3779
|
}
|
|
3533
3780
|
}
|
|
3781
|
+
if (command === "attest") {
|
|
3782
|
+
const id = await store.createAttestation({
|
|
3783
|
+
subject_agent_id: requireArg(takeFlag(args, "--subject"), "--subject"),
|
|
3784
|
+
task_ref: requireArg(takeFlag(args, "--task"), "--task"),
|
|
3785
|
+
outcome: takeFlag(args, "--outcome") ?? "success",
|
|
3786
|
+
summary: requireArg(takeFlag(args, "--summary"), "--summary")
|
|
3787
|
+
});
|
|
3788
|
+
return { text: `Attestation ${id.attestation_id}`, json: id };
|
|
3789
|
+
}
|
|
3790
|
+
if (command === "endorse") {
|
|
3791
|
+
const subject = requireArg(args.shift(), "<subject-agent-id>");
|
|
3792
|
+
const evAtt = takeFlag(args, "--evidence-attestation");
|
|
3793
|
+
const evTask = takeFlag(args, "--evidence-task");
|
|
3794
|
+
const id = await store.createEndorsement({
|
|
3795
|
+
subject_agent_id: subject,
|
|
3796
|
+
parent: { uri: requireArg(takeFlag(args, "--parent-uri"), "--parent-uri"), hash: requireArg(takeFlag(args, "--parent-hash"), "--parent-hash") },
|
|
3797
|
+
...evAtt ? { evidence_ref: { uri: `edgebook:attestation:${evAtt}`, hash: evAtt } } : {},
|
|
3798
|
+
...evTask ? { evidence_task_id: evTask } : {},
|
|
3799
|
+
statement: requireArg(takeFlag(args, "--statement"), "--statement")
|
|
3800
|
+
});
|
|
3801
|
+
return { text: `Endorsement ${id.endorse_id}`, json: id };
|
|
3802
|
+
}
|
|
3803
|
+
if (command === "signal") {
|
|
3804
|
+
const ttl = takeFlag(args, "--ttl-ms");
|
|
3805
|
+
const id = await store.createSignal({ body: requireArg(takeFlag(args, "--body"), "--body"), ttlMs: ttl ? Number(ttl) : void 0 });
|
|
3806
|
+
return { text: `Signal ${id.signal_id}`, json: id };
|
|
3807
|
+
}
|
|
3808
|
+
if (command === "capability") {
|
|
3809
|
+
const action = args.shift() || "list";
|
|
3810
|
+
if (action === "advertise") {
|
|
3811
|
+
const id = await store.advertiseCapability({
|
|
3812
|
+
name: requireArg(takeFlag(args, "--name"), "--name"),
|
|
3813
|
+
version: requireArg(takeFlag(args, "--version"), "--version"),
|
|
3814
|
+
summary: requireArg(takeFlag(args, "--summary"), "--summary")
|
|
3815
|
+
});
|
|
3816
|
+
return { text: `Capability ${id.capability_id}`, json: id };
|
|
3817
|
+
}
|
|
3818
|
+
if (action === "deprecate") {
|
|
3819
|
+
const id = await store.deprecateCapability(requireArg(args.shift(), "<capability-id>"));
|
|
3820
|
+
return { text: `Deprecated ${id.capability_id}`, json: id };
|
|
3821
|
+
}
|
|
3822
|
+
if (action === "list") {
|
|
3823
|
+
const all = await store.capabilities();
|
|
3824
|
+
return { text: JSON.stringify(all, null, 2), json: all };
|
|
3825
|
+
}
|
|
3826
|
+
throw new EdgeBookError("unknown_action", `Unknown capability action: ${action}`);
|
|
3827
|
+
}
|
|
3534
3828
|
throw new EdgeBookError("unknown_command", usage());
|
|
3535
3829
|
}
|
|
3536
3830
|
async function runCli(args) {
|