@voidly/agent-sdk 1.6.0 → 1.8.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/index.d.mts CHANGED
@@ -115,6 +115,7 @@ declare class VoidlyAgent {
115
115
  threadId?: string;
116
116
  replyTo?: string;
117
117
  ttl?: number;
118
+ messageType?: string;
118
119
  }): Promise<SendResult>;
119
120
  /**
120
121
  * Receive and decrypt messages. Decryption happens locally.
@@ -556,6 +557,153 @@ declare class VoidlyAgent {
556
557
  signature: string;
557
558
  timestamp: string;
558
559
  }, signingPublicKey: string): boolean;
560
+ /**
561
+ * Store an encrypted key-value pair in persistent memory.
562
+ * Values are encrypted with a key derived from your API key — only you can read them.
563
+ */
564
+ memorySet(namespace: string, key: string, value: unknown, options?: {
565
+ valueType?: string;
566
+ ttl?: number;
567
+ }): Promise<{
568
+ stored: boolean;
569
+ id: string;
570
+ size_bytes: number;
571
+ expires_at: string | null;
572
+ }>;
573
+ /**
574
+ * Retrieve a value from persistent memory.
575
+ * Decrypted server-side using your API key derivation.
576
+ */
577
+ memoryGet(namespace: string, key: string): Promise<{
578
+ namespace: string;
579
+ key: string;
580
+ value: unknown;
581
+ value_type: string;
582
+ size_bytes: number;
583
+ created_at: string;
584
+ updated_at: string;
585
+ expires_at: string | null;
586
+ } | null>;
587
+ /**
588
+ * Delete a key from persistent memory.
589
+ */
590
+ memoryDelete(namespace: string, key: string): Promise<{
591
+ deleted: boolean;
592
+ }>;
593
+ /**
594
+ * List all keys in a memory namespace.
595
+ */
596
+ memoryList(namespace?: string, options?: {
597
+ prefix?: string;
598
+ limit?: number;
599
+ }): Promise<{
600
+ namespace: string;
601
+ keys: Array<{
602
+ key: string;
603
+ value_type: string;
604
+ size_bytes: number;
605
+ updated_at: string;
606
+ }>;
607
+ total_keys: number;
608
+ total_bytes: number;
609
+ }>;
610
+ /**
611
+ * List all memory namespaces and quota usage.
612
+ */
613
+ memoryNamespaces(): Promise<{
614
+ namespaces: Array<{
615
+ namespace: string;
616
+ key_count: number;
617
+ total_bytes: number;
618
+ last_updated: string;
619
+ }>;
620
+ quota: {
621
+ used_bytes: number;
622
+ quota_bytes: number;
623
+ remaining_bytes: number;
624
+ };
625
+ }>;
626
+ /**
627
+ * Export all agent data as a portable JSON bundle.
628
+ * Includes identity, messages, channels, tasks, attestations, memory, and trust.
629
+ * Memory values remain encrypted — portable to another relay.
630
+ */
631
+ exportData(options?: {
632
+ includeMessages?: boolean;
633
+ includeChannels?: boolean;
634
+ includeTasks?: boolean;
635
+ includeAttestations?: boolean;
636
+ includeMemory?: boolean;
637
+ includeTrust?: boolean;
638
+ }): Promise<Record<string, unknown>>;
639
+ /**
640
+ * List past data export records.
641
+ */
642
+ listExports(): Promise<{
643
+ exports: Array<Record<string, unknown>>;
644
+ }>;
645
+ /**
646
+ * Get information about the relay this agent is connected to.
647
+ * Includes federation capabilities and known peers.
648
+ */
649
+ getRelayInfo(): Promise<Record<string, unknown>>;
650
+ /**
651
+ * List known federated relay peers.
652
+ */
653
+ getRelayPeers(): Promise<{
654
+ peers: Array<Record<string, unknown>>;
655
+ total: number;
656
+ }>;
657
+ /**
658
+ * Route a message through federation to an agent on a different relay.
659
+ * The relay will forward it to the recipient's home relay.
660
+ */
661
+ routeMessage(toDid: string, message: string, options?: {
662
+ contentType?: string;
663
+ threadId?: string;
664
+ }): Promise<{
665
+ routed: boolean;
666
+ destination: string;
667
+ }>;
668
+ /** Send heartbeat — signals agent is alive, updates last_seen */
669
+ ping(): Promise<{
670
+ pong: boolean;
671
+ did: string;
672
+ status: string;
673
+ uptime: {
674
+ days: number;
675
+ hours: number;
676
+ };
677
+ }>;
678
+ /** Check if another agent is online (public) */
679
+ checkOnline(did: string): Promise<{
680
+ did: string;
681
+ online_status: 'online' | 'idle' | 'offline';
682
+ last_seen: string;
683
+ minutes_since_seen: number | null;
684
+ }>;
685
+ /** Pin another agent's public keys (Trust On First Use). Returns warning if keys changed since last pin. */
686
+ pinKeys(did: string): Promise<{
687
+ pinned: boolean;
688
+ key_changed: boolean;
689
+ status: string;
690
+ warning?: string;
691
+ }>;
692
+ /** List all pinned keys */
693
+ listPinnedKeys(options?: {
694
+ status?: string;
695
+ }): Promise<{
696
+ pins: any[];
697
+ total: number;
698
+ }>;
699
+ /** Verify an agent's keys against your pinned copy. Detects key changes (potential MitM). */
700
+ verifyKeys(did: string): Promise<{
701
+ did: string;
702
+ pinned: boolean;
703
+ verified?: boolean;
704
+ status: string;
705
+ warning?: string;
706
+ }>;
559
707
  }
560
708
 
561
709
  export { type AgentIdentity, type AgentProfile, type DecryptedMessage, type SendResult, VoidlyAgent, type VoidlyAgentConfig };
package/dist/index.d.ts CHANGED
@@ -115,6 +115,7 @@ declare class VoidlyAgent {
115
115
  threadId?: string;
116
116
  replyTo?: string;
117
117
  ttl?: number;
118
+ messageType?: string;
118
119
  }): Promise<SendResult>;
119
120
  /**
120
121
  * Receive and decrypt messages. Decryption happens locally.
@@ -556,6 +557,153 @@ declare class VoidlyAgent {
556
557
  signature: string;
557
558
  timestamp: string;
558
559
  }, signingPublicKey: string): boolean;
560
+ /**
561
+ * Store an encrypted key-value pair in persistent memory.
562
+ * Values are encrypted with a key derived from your API key — only you can read them.
563
+ */
564
+ memorySet(namespace: string, key: string, value: unknown, options?: {
565
+ valueType?: string;
566
+ ttl?: number;
567
+ }): Promise<{
568
+ stored: boolean;
569
+ id: string;
570
+ size_bytes: number;
571
+ expires_at: string | null;
572
+ }>;
573
+ /**
574
+ * Retrieve a value from persistent memory.
575
+ * Decrypted server-side using your API key derivation.
576
+ */
577
+ memoryGet(namespace: string, key: string): Promise<{
578
+ namespace: string;
579
+ key: string;
580
+ value: unknown;
581
+ value_type: string;
582
+ size_bytes: number;
583
+ created_at: string;
584
+ updated_at: string;
585
+ expires_at: string | null;
586
+ } | null>;
587
+ /**
588
+ * Delete a key from persistent memory.
589
+ */
590
+ memoryDelete(namespace: string, key: string): Promise<{
591
+ deleted: boolean;
592
+ }>;
593
+ /**
594
+ * List all keys in a memory namespace.
595
+ */
596
+ memoryList(namespace?: string, options?: {
597
+ prefix?: string;
598
+ limit?: number;
599
+ }): Promise<{
600
+ namespace: string;
601
+ keys: Array<{
602
+ key: string;
603
+ value_type: string;
604
+ size_bytes: number;
605
+ updated_at: string;
606
+ }>;
607
+ total_keys: number;
608
+ total_bytes: number;
609
+ }>;
610
+ /**
611
+ * List all memory namespaces and quota usage.
612
+ */
613
+ memoryNamespaces(): Promise<{
614
+ namespaces: Array<{
615
+ namespace: string;
616
+ key_count: number;
617
+ total_bytes: number;
618
+ last_updated: string;
619
+ }>;
620
+ quota: {
621
+ used_bytes: number;
622
+ quota_bytes: number;
623
+ remaining_bytes: number;
624
+ };
625
+ }>;
626
+ /**
627
+ * Export all agent data as a portable JSON bundle.
628
+ * Includes identity, messages, channels, tasks, attestations, memory, and trust.
629
+ * Memory values remain encrypted — portable to another relay.
630
+ */
631
+ exportData(options?: {
632
+ includeMessages?: boolean;
633
+ includeChannels?: boolean;
634
+ includeTasks?: boolean;
635
+ includeAttestations?: boolean;
636
+ includeMemory?: boolean;
637
+ includeTrust?: boolean;
638
+ }): Promise<Record<string, unknown>>;
639
+ /**
640
+ * List past data export records.
641
+ */
642
+ listExports(): Promise<{
643
+ exports: Array<Record<string, unknown>>;
644
+ }>;
645
+ /**
646
+ * Get information about the relay this agent is connected to.
647
+ * Includes federation capabilities and known peers.
648
+ */
649
+ getRelayInfo(): Promise<Record<string, unknown>>;
650
+ /**
651
+ * List known federated relay peers.
652
+ */
653
+ getRelayPeers(): Promise<{
654
+ peers: Array<Record<string, unknown>>;
655
+ total: number;
656
+ }>;
657
+ /**
658
+ * Route a message through federation to an agent on a different relay.
659
+ * The relay will forward it to the recipient's home relay.
660
+ */
661
+ routeMessage(toDid: string, message: string, options?: {
662
+ contentType?: string;
663
+ threadId?: string;
664
+ }): Promise<{
665
+ routed: boolean;
666
+ destination: string;
667
+ }>;
668
+ /** Send heartbeat — signals agent is alive, updates last_seen */
669
+ ping(): Promise<{
670
+ pong: boolean;
671
+ did: string;
672
+ status: string;
673
+ uptime: {
674
+ days: number;
675
+ hours: number;
676
+ };
677
+ }>;
678
+ /** Check if another agent is online (public) */
679
+ checkOnline(did: string): Promise<{
680
+ did: string;
681
+ online_status: 'online' | 'idle' | 'offline';
682
+ last_seen: string;
683
+ minutes_since_seen: number | null;
684
+ }>;
685
+ /** Pin another agent's public keys (Trust On First Use). Returns warning if keys changed since last pin. */
686
+ pinKeys(did: string): Promise<{
687
+ pinned: boolean;
688
+ key_changed: boolean;
689
+ status: string;
690
+ warning?: string;
691
+ }>;
692
+ /** List all pinned keys */
693
+ listPinnedKeys(options?: {
694
+ status?: string;
695
+ }): Promise<{
696
+ pins: any[];
697
+ total: number;
698
+ }>;
699
+ /** Verify an agent's keys against your pinned copy. Detects key changes (potential MitM). */
700
+ verifyKeys(did: string): Promise<{
701
+ did: string;
702
+ pinned: boolean;
703
+ verified?: boolean;
704
+ status: string;
705
+ warning?: string;
706
+ }>;
559
707
  }
560
708
 
561
709
  export { type AgentIdentity, type AgentProfile, type DecryptedMessage, type SendResult, VoidlyAgent, type VoidlyAgentConfig };
package/dist/index.js CHANGED
@@ -2455,6 +2455,7 @@ var VoidlyAgent = class _VoidlyAgent {
2455
2455
  envelope: envelopeData,
2456
2456
  // Pass signed envelope so receiver can verify
2457
2457
  content_type: options.contentType || "text/plain",
2458
+ message_type: options.messageType || "text",
2458
2459
  thread_id: options.threadId,
2459
2460
  reply_to: options.replyTo,
2460
2461
  ttl: options.ttl
@@ -3332,6 +3333,201 @@ var VoidlyAgent = class _VoidlyAgent {
3332
3333
  return false;
3333
3334
  }
3334
3335
  }
3336
+ // ─── Memory Store ──────────────────────────────────────────────────────────
3337
+ /**
3338
+ * Store an encrypted key-value pair in persistent memory.
3339
+ * Values are encrypted with a key derived from your API key — only you can read them.
3340
+ */
3341
+ async memorySet(namespace, key, value, options) {
3342
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(namespace)}/${encodeURIComponent(key)}`, {
3343
+ method: "PUT",
3344
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3345
+ body: JSON.stringify({
3346
+ value,
3347
+ value_type: options?.valueType || (typeof value === "object" ? "json" : typeof value),
3348
+ ttl: options?.ttl
3349
+ })
3350
+ });
3351
+ if (!res.ok) throw new Error(`Memory set failed: ${res.status} ${await res.text()}`);
3352
+ return res.json();
3353
+ }
3354
+ /**
3355
+ * Retrieve a value from persistent memory.
3356
+ * Decrypted server-side using your API key derivation.
3357
+ */
3358
+ async memoryGet(namespace, key) {
3359
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(namespace)}/${encodeURIComponent(key)}`, {
3360
+ headers: { "X-Agent-Key": this.apiKey }
3361
+ });
3362
+ if (res.status === 404) return null;
3363
+ if (!res.ok) throw new Error(`Memory get failed: ${res.status} ${await res.text()}`);
3364
+ return res.json();
3365
+ }
3366
+ /**
3367
+ * Delete a key from persistent memory.
3368
+ */
3369
+ async memoryDelete(namespace, key) {
3370
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(namespace)}/${encodeURIComponent(key)}`, {
3371
+ method: "DELETE",
3372
+ headers: { "X-Agent-Key": this.apiKey }
3373
+ });
3374
+ if (!res.ok) throw new Error(`Memory delete failed: ${res.status} ${await res.text()}`);
3375
+ return res.json();
3376
+ }
3377
+ /**
3378
+ * List all keys in a memory namespace.
3379
+ */
3380
+ async memoryList(namespace, options) {
3381
+ const ns = namespace || "default";
3382
+ const params = new URLSearchParams();
3383
+ if (options?.prefix) params.set("prefix", options.prefix);
3384
+ if (options?.limit) params.set("limit", String(options.limit));
3385
+ const qs = params.toString() ? `?${params.toString()}` : "";
3386
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(ns)}${qs}`, {
3387
+ headers: { "X-Agent-Key": this.apiKey }
3388
+ });
3389
+ if (!res.ok) throw new Error(`Memory list failed: ${res.status} ${await res.text()}`);
3390
+ return res.json();
3391
+ }
3392
+ /**
3393
+ * List all memory namespaces and quota usage.
3394
+ */
3395
+ async memoryNamespaces() {
3396
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory`, {
3397
+ headers: { "X-Agent-Key": this.apiKey }
3398
+ });
3399
+ if (!res.ok) throw new Error(`Memory namespaces failed: ${res.status} ${await res.text()}`);
3400
+ return res.json();
3401
+ }
3402
+ // ─── Data Export ───────────────────────────────────────────────────────────
3403
+ /**
3404
+ * Export all agent data as a portable JSON bundle.
3405
+ * Includes identity, messages, channels, tasks, attestations, memory, and trust.
3406
+ * Memory values remain encrypted — portable to another relay.
3407
+ */
3408
+ async exportData(options) {
3409
+ const res = await fetch(`${this.baseUrl}/v1/agent/export`, {
3410
+ method: "POST",
3411
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3412
+ body: JSON.stringify({
3413
+ include_messages: options?.includeMessages,
3414
+ include_channels: options?.includeChannels,
3415
+ include_tasks: options?.includeTasks,
3416
+ include_attestations: options?.includeAttestations,
3417
+ include_memory: options?.includeMemory,
3418
+ include_trust: options?.includeTrust
3419
+ })
3420
+ });
3421
+ if (!res.ok) throw new Error(`Export failed: ${res.status} ${await res.text()}`);
3422
+ return res.json();
3423
+ }
3424
+ /**
3425
+ * List past data export records.
3426
+ */
3427
+ async listExports() {
3428
+ const res = await fetch(`${this.baseUrl}/v1/agent/exports`, {
3429
+ headers: { "X-Agent-Key": this.apiKey }
3430
+ });
3431
+ if (!res.ok) throw new Error(`List exports failed: ${res.status} ${await res.text()}`);
3432
+ return res.json();
3433
+ }
3434
+ // ─── Relay Federation ─────────────────────────────────────────────────────
3435
+ /**
3436
+ * Get information about the relay this agent is connected to.
3437
+ * Includes federation capabilities and known peers.
3438
+ */
3439
+ async getRelayInfo() {
3440
+ const res = await fetch(`${this.baseUrl}/v1/relay/info`);
3441
+ if (!res.ok) throw new Error(`Relay info failed: ${res.status} ${await res.text()}`);
3442
+ return res.json();
3443
+ }
3444
+ /**
3445
+ * List known federated relay peers.
3446
+ */
3447
+ async getRelayPeers() {
3448
+ const res = await fetch(`${this.baseUrl}/v1/relay/peers`);
3449
+ if (!res.ok) throw new Error(`Relay peers failed: ${res.status} ${await res.text()}`);
3450
+ return res.json();
3451
+ }
3452
+ /**
3453
+ * Route a message through federation to an agent on a different relay.
3454
+ * The relay will forward it to the recipient's home relay.
3455
+ */
3456
+ async routeMessage(toDid, message, options) {
3457
+ const profile = await this.getIdentity(toDid);
3458
+ if (!profile) throw new Error(`Recipient ${toDid} not found`);
3459
+ const recipientPub = (0, import_tweetnacl_util.decodeBase64)(profile.encryption_public_key);
3460
+ const nonce = import_tweetnacl.default.randomBytes(import_tweetnacl.default.box.nonceLength);
3461
+ const encrypted = import_tweetnacl.default.box((0, import_tweetnacl_util.decodeUTF8)(message), nonce, recipientPub, this.encryptionKeyPair.secretKey);
3462
+ if (!encrypted) throw new Error("Encryption failed");
3463
+ const signaturePayload = (0, import_tweetnacl_util.decodeUTF8)(JSON.stringify({
3464
+ from: this.did,
3465
+ to: toDid,
3466
+ nonce: (0, import_tweetnacl_util.encodeBase64)(nonce),
3467
+ ciphertext_hash: await sha256((0, import_tweetnacl_util.encodeBase64)(encrypted))
3468
+ }));
3469
+ const signature = import_tweetnacl.default.sign.detached(signaturePayload, this.signingKeyPair.secretKey);
3470
+ const res = await fetch(`${this.baseUrl}/v1/relay/route`, {
3471
+ method: "POST",
3472
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3473
+ body: JSON.stringify({
3474
+ to: toDid,
3475
+ ciphertext: (0, import_tweetnacl_util.encodeBase64)(encrypted),
3476
+ nonce: (0, import_tweetnacl_util.encodeBase64)(nonce),
3477
+ signature: (0, import_tweetnacl_util.encodeBase64)(signature),
3478
+ content_type: options?.contentType || "text/plain",
3479
+ thread_id: options?.threadId
3480
+ })
3481
+ });
3482
+ if (!res.ok) throw new Error(`Route failed: ${res.status} ${await res.text()}`);
3483
+ return res.json();
3484
+ }
3485
+ // ── Heartbeat ──────────────────────────────────────────────────────────────
3486
+ /** Send heartbeat — signals agent is alive, updates last_seen */
3487
+ async ping() {
3488
+ const res = await fetch(`${this.baseUrl}/v1/agent/ping`, {
3489
+ method: "POST",
3490
+ headers: { "X-Agent-Key": this.apiKey }
3491
+ });
3492
+ if (!res.ok) throw new Error(`Ping failed: ${res.status}`);
3493
+ return res.json();
3494
+ }
3495
+ /** Check if another agent is online (public) */
3496
+ async checkOnline(did) {
3497
+ const res = await fetch(`${this.baseUrl}/v1/agent/ping/${encodeURIComponent(did)}`);
3498
+ if (!res.ok) throw new Error(`Ping check failed: ${res.status}`);
3499
+ return res.json();
3500
+ }
3501
+ // ── Key Pinning (TOFU) ────────────────────────────────────────────────────
3502
+ /** Pin another agent's public keys (Trust On First Use). Returns warning if keys changed since last pin. */
3503
+ async pinKeys(did) {
3504
+ const res = await fetch(`${this.baseUrl}/v1/agent/keys/pin`, {
3505
+ method: "POST",
3506
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3507
+ body: JSON.stringify({ did })
3508
+ });
3509
+ if (!res.ok) throw new Error(`Key pin failed: ${res.status}`);
3510
+ return res.json();
3511
+ }
3512
+ /** List all pinned keys */
3513
+ async listPinnedKeys(options) {
3514
+ const params = new URLSearchParams();
3515
+ if (options?.status) params.set("status", options.status);
3516
+ const qs = params.toString() ? `?${params.toString()}` : "";
3517
+ const res = await fetch(`${this.baseUrl}/v1/agent/keys/pins${qs}`, {
3518
+ headers: { "X-Agent-Key": this.apiKey }
3519
+ });
3520
+ if (!res.ok) throw new Error(`List pins failed: ${res.status}`);
3521
+ return res.json();
3522
+ }
3523
+ /** Verify an agent's keys against your pinned copy. Detects key changes (potential MitM). */
3524
+ async verifyKeys(did) {
3525
+ const res = await fetch(`${this.baseUrl}/v1/agent/keys/verify/${encodeURIComponent(did)}`, {
3526
+ headers: { "X-Agent-Key": this.apiKey }
3527
+ });
3528
+ if (!res.ok) throw new Error(`Key verify failed: ${res.status}`);
3529
+ return res.json();
3530
+ }
3335
3531
  };
3336
3532
  // Annotate the CommonJS export names for ESM import in node:
3337
3533
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -2445,6 +2445,7 @@ var VoidlyAgent = class _VoidlyAgent {
2445
2445
  envelope: envelopeData,
2446
2446
  // Pass signed envelope so receiver can verify
2447
2447
  content_type: options.contentType || "text/plain",
2448
+ message_type: options.messageType || "text",
2448
2449
  thread_id: options.threadId,
2449
2450
  reply_to: options.replyTo,
2450
2451
  ttl: options.ttl
@@ -3322,6 +3323,201 @@ var VoidlyAgent = class _VoidlyAgent {
3322
3323
  return false;
3323
3324
  }
3324
3325
  }
3326
+ // ─── Memory Store ──────────────────────────────────────────────────────────
3327
+ /**
3328
+ * Store an encrypted key-value pair in persistent memory.
3329
+ * Values are encrypted with a key derived from your API key — only you can read them.
3330
+ */
3331
+ async memorySet(namespace, key, value, options) {
3332
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(namespace)}/${encodeURIComponent(key)}`, {
3333
+ method: "PUT",
3334
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3335
+ body: JSON.stringify({
3336
+ value,
3337
+ value_type: options?.valueType || (typeof value === "object" ? "json" : typeof value),
3338
+ ttl: options?.ttl
3339
+ })
3340
+ });
3341
+ if (!res.ok) throw new Error(`Memory set failed: ${res.status} ${await res.text()}`);
3342
+ return res.json();
3343
+ }
3344
+ /**
3345
+ * Retrieve a value from persistent memory.
3346
+ * Decrypted server-side using your API key derivation.
3347
+ */
3348
+ async memoryGet(namespace, key) {
3349
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(namespace)}/${encodeURIComponent(key)}`, {
3350
+ headers: { "X-Agent-Key": this.apiKey }
3351
+ });
3352
+ if (res.status === 404) return null;
3353
+ if (!res.ok) throw new Error(`Memory get failed: ${res.status} ${await res.text()}`);
3354
+ return res.json();
3355
+ }
3356
+ /**
3357
+ * Delete a key from persistent memory.
3358
+ */
3359
+ async memoryDelete(namespace, key) {
3360
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(namespace)}/${encodeURIComponent(key)}`, {
3361
+ method: "DELETE",
3362
+ headers: { "X-Agent-Key": this.apiKey }
3363
+ });
3364
+ if (!res.ok) throw new Error(`Memory delete failed: ${res.status} ${await res.text()}`);
3365
+ return res.json();
3366
+ }
3367
+ /**
3368
+ * List all keys in a memory namespace.
3369
+ */
3370
+ async memoryList(namespace, options) {
3371
+ const ns = namespace || "default";
3372
+ const params = new URLSearchParams();
3373
+ if (options?.prefix) params.set("prefix", options.prefix);
3374
+ if (options?.limit) params.set("limit", String(options.limit));
3375
+ const qs = params.toString() ? `?${params.toString()}` : "";
3376
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(ns)}${qs}`, {
3377
+ headers: { "X-Agent-Key": this.apiKey }
3378
+ });
3379
+ if (!res.ok) throw new Error(`Memory list failed: ${res.status} ${await res.text()}`);
3380
+ return res.json();
3381
+ }
3382
+ /**
3383
+ * List all memory namespaces and quota usage.
3384
+ */
3385
+ async memoryNamespaces() {
3386
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory`, {
3387
+ headers: { "X-Agent-Key": this.apiKey }
3388
+ });
3389
+ if (!res.ok) throw new Error(`Memory namespaces failed: ${res.status} ${await res.text()}`);
3390
+ return res.json();
3391
+ }
3392
+ // ─── Data Export ───────────────────────────────────────────────────────────
3393
+ /**
3394
+ * Export all agent data as a portable JSON bundle.
3395
+ * Includes identity, messages, channels, tasks, attestations, memory, and trust.
3396
+ * Memory values remain encrypted — portable to another relay.
3397
+ */
3398
+ async exportData(options) {
3399
+ const res = await fetch(`${this.baseUrl}/v1/agent/export`, {
3400
+ method: "POST",
3401
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3402
+ body: JSON.stringify({
3403
+ include_messages: options?.includeMessages,
3404
+ include_channels: options?.includeChannels,
3405
+ include_tasks: options?.includeTasks,
3406
+ include_attestations: options?.includeAttestations,
3407
+ include_memory: options?.includeMemory,
3408
+ include_trust: options?.includeTrust
3409
+ })
3410
+ });
3411
+ if (!res.ok) throw new Error(`Export failed: ${res.status} ${await res.text()}`);
3412
+ return res.json();
3413
+ }
3414
+ /**
3415
+ * List past data export records.
3416
+ */
3417
+ async listExports() {
3418
+ const res = await fetch(`${this.baseUrl}/v1/agent/exports`, {
3419
+ headers: { "X-Agent-Key": this.apiKey }
3420
+ });
3421
+ if (!res.ok) throw new Error(`List exports failed: ${res.status} ${await res.text()}`);
3422
+ return res.json();
3423
+ }
3424
+ // ─── Relay Federation ─────────────────────────────────────────────────────
3425
+ /**
3426
+ * Get information about the relay this agent is connected to.
3427
+ * Includes federation capabilities and known peers.
3428
+ */
3429
+ async getRelayInfo() {
3430
+ const res = await fetch(`${this.baseUrl}/v1/relay/info`);
3431
+ if (!res.ok) throw new Error(`Relay info failed: ${res.status} ${await res.text()}`);
3432
+ return res.json();
3433
+ }
3434
+ /**
3435
+ * List known federated relay peers.
3436
+ */
3437
+ async getRelayPeers() {
3438
+ const res = await fetch(`${this.baseUrl}/v1/relay/peers`);
3439
+ if (!res.ok) throw new Error(`Relay peers failed: ${res.status} ${await res.text()}`);
3440
+ return res.json();
3441
+ }
3442
+ /**
3443
+ * Route a message through federation to an agent on a different relay.
3444
+ * The relay will forward it to the recipient's home relay.
3445
+ */
3446
+ async routeMessage(toDid, message, options) {
3447
+ const profile = await this.getIdentity(toDid);
3448
+ if (!profile) throw new Error(`Recipient ${toDid} not found`);
3449
+ const recipientPub = (0, import_tweetnacl_util.decodeBase64)(profile.encryption_public_key);
3450
+ const nonce = import_tweetnacl.default.randomBytes(import_tweetnacl.default.box.nonceLength);
3451
+ const encrypted = import_tweetnacl.default.box((0, import_tweetnacl_util.decodeUTF8)(message), nonce, recipientPub, this.encryptionKeyPair.secretKey);
3452
+ if (!encrypted) throw new Error("Encryption failed");
3453
+ const signaturePayload = (0, import_tweetnacl_util.decodeUTF8)(JSON.stringify({
3454
+ from: this.did,
3455
+ to: toDid,
3456
+ nonce: (0, import_tweetnacl_util.encodeBase64)(nonce),
3457
+ ciphertext_hash: await sha256((0, import_tweetnacl_util.encodeBase64)(encrypted))
3458
+ }));
3459
+ const signature = import_tweetnacl.default.sign.detached(signaturePayload, this.signingKeyPair.secretKey);
3460
+ const res = await fetch(`${this.baseUrl}/v1/relay/route`, {
3461
+ method: "POST",
3462
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3463
+ body: JSON.stringify({
3464
+ to: toDid,
3465
+ ciphertext: (0, import_tweetnacl_util.encodeBase64)(encrypted),
3466
+ nonce: (0, import_tweetnacl_util.encodeBase64)(nonce),
3467
+ signature: (0, import_tweetnacl_util.encodeBase64)(signature),
3468
+ content_type: options?.contentType || "text/plain",
3469
+ thread_id: options?.threadId
3470
+ })
3471
+ });
3472
+ if (!res.ok) throw new Error(`Route failed: ${res.status} ${await res.text()}`);
3473
+ return res.json();
3474
+ }
3475
+ // ── Heartbeat ──────────────────────────────────────────────────────────────
3476
+ /** Send heartbeat — signals agent is alive, updates last_seen */
3477
+ async ping() {
3478
+ const res = await fetch(`${this.baseUrl}/v1/agent/ping`, {
3479
+ method: "POST",
3480
+ headers: { "X-Agent-Key": this.apiKey }
3481
+ });
3482
+ if (!res.ok) throw new Error(`Ping failed: ${res.status}`);
3483
+ return res.json();
3484
+ }
3485
+ /** Check if another agent is online (public) */
3486
+ async checkOnline(did) {
3487
+ const res = await fetch(`${this.baseUrl}/v1/agent/ping/${encodeURIComponent(did)}`);
3488
+ if (!res.ok) throw new Error(`Ping check failed: ${res.status}`);
3489
+ return res.json();
3490
+ }
3491
+ // ── Key Pinning (TOFU) ────────────────────────────────────────────────────
3492
+ /** Pin another agent's public keys (Trust On First Use). Returns warning if keys changed since last pin. */
3493
+ async pinKeys(did) {
3494
+ const res = await fetch(`${this.baseUrl}/v1/agent/keys/pin`, {
3495
+ method: "POST",
3496
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3497
+ body: JSON.stringify({ did })
3498
+ });
3499
+ if (!res.ok) throw new Error(`Key pin failed: ${res.status}`);
3500
+ return res.json();
3501
+ }
3502
+ /** List all pinned keys */
3503
+ async listPinnedKeys(options) {
3504
+ const params = new URLSearchParams();
3505
+ if (options?.status) params.set("status", options.status);
3506
+ const qs = params.toString() ? `?${params.toString()}` : "";
3507
+ const res = await fetch(`${this.baseUrl}/v1/agent/keys/pins${qs}`, {
3508
+ headers: { "X-Agent-Key": this.apiKey }
3509
+ });
3510
+ if (!res.ok) throw new Error(`List pins failed: ${res.status}`);
3511
+ return res.json();
3512
+ }
3513
+ /** Verify an agent's keys against your pinned copy. Detects key changes (potential MitM). */
3514
+ async verifyKeys(did) {
3515
+ const res = await fetch(`${this.baseUrl}/v1/agent/keys/verify/${encodeURIComponent(did)}`, {
3516
+ headers: { "X-Agent-Key": this.apiKey }
3517
+ });
3518
+ if (!res.ok) throw new Error(`Key verify failed: ${res.status}`);
3519
+ return res.json();
3520
+ }
3325
3521
  };
3326
3522
  var export_decodeBase64 = import_tweetnacl_util.decodeBase64;
3327
3523
  var export_decodeUTF8 = import_tweetnacl_util.decodeUTF8;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voidly/agent-sdk",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
4
4
  "description": "E2E encrypted agent-to-agent communication SDK — true client-side encryption",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",