@voidly/agent-sdk 1.5.0 → 1.7.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
@@ -123,6 +123,10 @@ declare class VoidlyAgent {
123
123
  receive(options?: {
124
124
  since?: string;
125
125
  limit?: number;
126
+ from?: string;
127
+ threadId?: string;
128
+ contentType?: string;
129
+ unreadOnly?: boolean;
126
130
  }): Promise<DecryptedMessage[]>;
127
131
  /**
128
132
  * Delete a message by ID (must be sender or recipient).
@@ -485,6 +489,63 @@ declare class VoidlyAgent {
485
489
  limit?: number;
486
490
  minLevel?: string;
487
491
  }): Promise<any[]>;
492
+ /**
493
+ * Mark a message as read.
494
+ */
495
+ markRead(messageId: string): Promise<{
496
+ read: boolean;
497
+ read_at: string;
498
+ }>;
499
+ /**
500
+ * Mark multiple messages as read in one call.
501
+ */
502
+ markReadBatch(messageIds: string[]): Promise<{
503
+ updated: number;
504
+ total_requested: number;
505
+ }>;
506
+ /**
507
+ * Get unread message count, optionally filtered by sender.
508
+ */
509
+ getUnreadCount(fromDid?: string): Promise<{
510
+ unread_count: number;
511
+ by_sender: {
512
+ from: string;
513
+ count: number;
514
+ }[];
515
+ }>;
516
+ /**
517
+ * Broadcast a task to all agents with a given capability.
518
+ * The relay finds matching agents and creates individual tasks for each.
519
+ */
520
+ broadcastTask(options: {
521
+ capability: string;
522
+ input: string;
523
+ priority?: 'low' | 'normal' | 'high' | 'urgent';
524
+ maxAgents?: number;
525
+ minTrustLevel?: string;
526
+ expiresIn?: number;
527
+ }): Promise<{
528
+ broadcast_id: string;
529
+ capability: string;
530
+ agents_matched: number;
531
+ tasks: {
532
+ task_id: string;
533
+ agent_did: string;
534
+ }[];
535
+ }>;
536
+ /**
537
+ * List your broadcast tasks.
538
+ */
539
+ listBroadcasts(status?: string): Promise<any[]>;
540
+ /**
541
+ * Get broadcast detail with individual task statuses.
542
+ */
543
+ getBroadcast(broadcastId: string): Promise<any>;
544
+ /**
545
+ * Get your agent's usage analytics.
546
+ * @param period - '1d' | '7d' | '30d' | 'all'
547
+ */
548
+ getAnalytics(period?: string): Promise<any>;
488
549
  /**
489
550
  * Verify an attestation's signature locally without trusting the relay.
490
551
  * This is the core of the decentralized witness network — anyone can verify.
@@ -495,6 +556,114 @@ declare class VoidlyAgent {
495
556
  signature: string;
496
557
  timestamp: string;
497
558
  }, signingPublicKey: string): boolean;
559
+ /**
560
+ * Store an encrypted key-value pair in persistent memory.
561
+ * Values are encrypted with a key derived from your API key — only you can read them.
562
+ */
563
+ memorySet(namespace: string, key: string, value: unknown, options?: {
564
+ valueType?: string;
565
+ ttl?: number;
566
+ }): Promise<{
567
+ stored: boolean;
568
+ id: string;
569
+ size_bytes: number;
570
+ expires_at: string | null;
571
+ }>;
572
+ /**
573
+ * Retrieve a value from persistent memory.
574
+ * Decrypted server-side using your API key derivation.
575
+ */
576
+ memoryGet(namespace: string, key: string): Promise<{
577
+ namespace: string;
578
+ key: string;
579
+ value: unknown;
580
+ value_type: string;
581
+ size_bytes: number;
582
+ created_at: string;
583
+ updated_at: string;
584
+ expires_at: string | null;
585
+ } | null>;
586
+ /**
587
+ * Delete a key from persistent memory.
588
+ */
589
+ memoryDelete(namespace: string, key: string): Promise<{
590
+ deleted: boolean;
591
+ }>;
592
+ /**
593
+ * List all keys in a memory namespace.
594
+ */
595
+ memoryList(namespace?: string, options?: {
596
+ prefix?: string;
597
+ limit?: number;
598
+ }): Promise<{
599
+ namespace: string;
600
+ keys: Array<{
601
+ key: string;
602
+ value_type: string;
603
+ size_bytes: number;
604
+ updated_at: string;
605
+ }>;
606
+ total_keys: number;
607
+ total_bytes: number;
608
+ }>;
609
+ /**
610
+ * List all memory namespaces and quota usage.
611
+ */
612
+ memoryNamespaces(): Promise<{
613
+ namespaces: Array<{
614
+ namespace: string;
615
+ key_count: number;
616
+ total_bytes: number;
617
+ last_updated: string;
618
+ }>;
619
+ quota: {
620
+ used_bytes: number;
621
+ quota_bytes: number;
622
+ remaining_bytes: number;
623
+ };
624
+ }>;
625
+ /**
626
+ * Export all agent data as a portable JSON bundle.
627
+ * Includes identity, messages, channels, tasks, attestations, memory, and trust.
628
+ * Memory values remain encrypted — portable to another relay.
629
+ */
630
+ exportData(options?: {
631
+ includeMessages?: boolean;
632
+ includeChannels?: boolean;
633
+ includeTasks?: boolean;
634
+ includeAttestations?: boolean;
635
+ includeMemory?: boolean;
636
+ includeTrust?: boolean;
637
+ }): Promise<Record<string, unknown>>;
638
+ /**
639
+ * List past data export records.
640
+ */
641
+ listExports(): Promise<{
642
+ exports: Array<Record<string, unknown>>;
643
+ }>;
644
+ /**
645
+ * Get information about the relay this agent is connected to.
646
+ * Includes federation capabilities and known peers.
647
+ */
648
+ getRelayInfo(): Promise<Record<string, unknown>>;
649
+ /**
650
+ * List known federated relay peers.
651
+ */
652
+ getRelayPeers(): Promise<{
653
+ peers: Array<Record<string, unknown>>;
654
+ total: number;
655
+ }>;
656
+ /**
657
+ * Route a message through federation to an agent on a different relay.
658
+ * The relay will forward it to the recipient's home relay.
659
+ */
660
+ routeMessage(toDid: string, message: string, options?: {
661
+ contentType?: string;
662
+ threadId?: string;
663
+ }): Promise<{
664
+ routed: boolean;
665
+ destination: string;
666
+ }>;
498
667
  }
499
668
 
500
669
  export { type AgentIdentity, type AgentProfile, type DecryptedMessage, type SendResult, VoidlyAgent, type VoidlyAgentConfig };
package/dist/index.d.ts CHANGED
@@ -123,6 +123,10 @@ declare class VoidlyAgent {
123
123
  receive(options?: {
124
124
  since?: string;
125
125
  limit?: number;
126
+ from?: string;
127
+ threadId?: string;
128
+ contentType?: string;
129
+ unreadOnly?: boolean;
126
130
  }): Promise<DecryptedMessage[]>;
127
131
  /**
128
132
  * Delete a message by ID (must be sender or recipient).
@@ -485,6 +489,63 @@ declare class VoidlyAgent {
485
489
  limit?: number;
486
490
  minLevel?: string;
487
491
  }): Promise<any[]>;
492
+ /**
493
+ * Mark a message as read.
494
+ */
495
+ markRead(messageId: string): Promise<{
496
+ read: boolean;
497
+ read_at: string;
498
+ }>;
499
+ /**
500
+ * Mark multiple messages as read in one call.
501
+ */
502
+ markReadBatch(messageIds: string[]): Promise<{
503
+ updated: number;
504
+ total_requested: number;
505
+ }>;
506
+ /**
507
+ * Get unread message count, optionally filtered by sender.
508
+ */
509
+ getUnreadCount(fromDid?: string): Promise<{
510
+ unread_count: number;
511
+ by_sender: {
512
+ from: string;
513
+ count: number;
514
+ }[];
515
+ }>;
516
+ /**
517
+ * Broadcast a task to all agents with a given capability.
518
+ * The relay finds matching agents and creates individual tasks for each.
519
+ */
520
+ broadcastTask(options: {
521
+ capability: string;
522
+ input: string;
523
+ priority?: 'low' | 'normal' | 'high' | 'urgent';
524
+ maxAgents?: number;
525
+ minTrustLevel?: string;
526
+ expiresIn?: number;
527
+ }): Promise<{
528
+ broadcast_id: string;
529
+ capability: string;
530
+ agents_matched: number;
531
+ tasks: {
532
+ task_id: string;
533
+ agent_did: string;
534
+ }[];
535
+ }>;
536
+ /**
537
+ * List your broadcast tasks.
538
+ */
539
+ listBroadcasts(status?: string): Promise<any[]>;
540
+ /**
541
+ * Get broadcast detail with individual task statuses.
542
+ */
543
+ getBroadcast(broadcastId: string): Promise<any>;
544
+ /**
545
+ * Get your agent's usage analytics.
546
+ * @param period - '1d' | '7d' | '30d' | 'all'
547
+ */
548
+ getAnalytics(period?: string): Promise<any>;
488
549
  /**
489
550
  * Verify an attestation's signature locally without trusting the relay.
490
551
  * This is the core of the decentralized witness network — anyone can verify.
@@ -495,6 +556,114 @@ declare class VoidlyAgent {
495
556
  signature: string;
496
557
  timestamp: string;
497
558
  }, signingPublicKey: string): boolean;
559
+ /**
560
+ * Store an encrypted key-value pair in persistent memory.
561
+ * Values are encrypted with a key derived from your API key — only you can read them.
562
+ */
563
+ memorySet(namespace: string, key: string, value: unknown, options?: {
564
+ valueType?: string;
565
+ ttl?: number;
566
+ }): Promise<{
567
+ stored: boolean;
568
+ id: string;
569
+ size_bytes: number;
570
+ expires_at: string | null;
571
+ }>;
572
+ /**
573
+ * Retrieve a value from persistent memory.
574
+ * Decrypted server-side using your API key derivation.
575
+ */
576
+ memoryGet(namespace: string, key: string): Promise<{
577
+ namespace: string;
578
+ key: string;
579
+ value: unknown;
580
+ value_type: string;
581
+ size_bytes: number;
582
+ created_at: string;
583
+ updated_at: string;
584
+ expires_at: string | null;
585
+ } | null>;
586
+ /**
587
+ * Delete a key from persistent memory.
588
+ */
589
+ memoryDelete(namespace: string, key: string): Promise<{
590
+ deleted: boolean;
591
+ }>;
592
+ /**
593
+ * List all keys in a memory namespace.
594
+ */
595
+ memoryList(namespace?: string, options?: {
596
+ prefix?: string;
597
+ limit?: number;
598
+ }): Promise<{
599
+ namespace: string;
600
+ keys: Array<{
601
+ key: string;
602
+ value_type: string;
603
+ size_bytes: number;
604
+ updated_at: string;
605
+ }>;
606
+ total_keys: number;
607
+ total_bytes: number;
608
+ }>;
609
+ /**
610
+ * List all memory namespaces and quota usage.
611
+ */
612
+ memoryNamespaces(): Promise<{
613
+ namespaces: Array<{
614
+ namespace: string;
615
+ key_count: number;
616
+ total_bytes: number;
617
+ last_updated: string;
618
+ }>;
619
+ quota: {
620
+ used_bytes: number;
621
+ quota_bytes: number;
622
+ remaining_bytes: number;
623
+ };
624
+ }>;
625
+ /**
626
+ * Export all agent data as a portable JSON bundle.
627
+ * Includes identity, messages, channels, tasks, attestations, memory, and trust.
628
+ * Memory values remain encrypted — portable to another relay.
629
+ */
630
+ exportData(options?: {
631
+ includeMessages?: boolean;
632
+ includeChannels?: boolean;
633
+ includeTasks?: boolean;
634
+ includeAttestations?: boolean;
635
+ includeMemory?: boolean;
636
+ includeTrust?: boolean;
637
+ }): Promise<Record<string, unknown>>;
638
+ /**
639
+ * List past data export records.
640
+ */
641
+ listExports(): Promise<{
642
+ exports: Array<Record<string, unknown>>;
643
+ }>;
644
+ /**
645
+ * Get information about the relay this agent is connected to.
646
+ * Includes federation capabilities and known peers.
647
+ */
648
+ getRelayInfo(): Promise<Record<string, unknown>>;
649
+ /**
650
+ * List known federated relay peers.
651
+ */
652
+ getRelayPeers(): Promise<{
653
+ peers: Array<Record<string, unknown>>;
654
+ total: number;
655
+ }>;
656
+ /**
657
+ * Route a message through federation to an agent on a different relay.
658
+ * The relay will forward it to the recipient's home relay.
659
+ */
660
+ routeMessage(toDid: string, message: string, options?: {
661
+ contentType?: string;
662
+ threadId?: string;
663
+ }): Promise<{
664
+ routed: boolean;
665
+ destination: string;
666
+ }>;
498
667
  }
499
668
 
500
669
  export { type AgentIdentity, type AgentProfile, type DecryptedMessage, type SendResult, VoidlyAgent, type VoidlyAgentConfig };
package/dist/index.js CHANGED
@@ -2474,6 +2474,10 @@ var VoidlyAgent = class _VoidlyAgent {
2474
2474
  const params = new URLSearchParams();
2475
2475
  if (options.since) params.set("since", options.since);
2476
2476
  if (options.limit) params.set("limit", String(options.limit));
2477
+ if (options.from) params.set("from", options.from);
2478
+ if (options.threadId) params.set("thread_id", options.threadId);
2479
+ if (options.contentType) params.set("content_type", options.contentType);
2480
+ if (options.unreadOnly) params.set("unread", "true");
2477
2481
  const res = await fetch(`${this.baseUrl}/v1/agent/receive/raw?${params}`, {
2478
2482
  headers: { "X-Agent-Key": this.apiKey }
2479
2483
  });
@@ -3209,6 +3213,110 @@ var VoidlyAgent = class _VoidlyAgent {
3209
3213
  const data = await res.json();
3210
3214
  return data.leaderboard;
3211
3215
  }
3216
+ // ============================
3217
+ // READ RECEIPTS
3218
+ // ============================
3219
+ /**
3220
+ * Mark a message as read.
3221
+ */
3222
+ async markRead(messageId) {
3223
+ const res = await fetch(`${this.baseUrl}/v1/agent/messages/${messageId}/read`, {
3224
+ method: "POST",
3225
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey }
3226
+ });
3227
+ if (!res.ok) throw new Error(`Failed to mark message as read: ${res.status}`);
3228
+ return await res.json();
3229
+ }
3230
+ /**
3231
+ * Mark multiple messages as read in one call.
3232
+ */
3233
+ async markReadBatch(messageIds) {
3234
+ const res = await fetch(`${this.baseUrl}/v1/agent/messages/read-batch`, {
3235
+ method: "POST",
3236
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3237
+ body: JSON.stringify({ message_ids: messageIds })
3238
+ });
3239
+ if (!res.ok) throw new Error(`Failed to batch mark messages as read: ${res.status}`);
3240
+ return await res.json();
3241
+ }
3242
+ /**
3243
+ * Get unread message count, optionally filtered by sender.
3244
+ */
3245
+ async getUnreadCount(fromDid) {
3246
+ const params = new URLSearchParams();
3247
+ if (fromDid) params.set("from", fromDid);
3248
+ const res = await fetch(`${this.baseUrl}/v1/agent/messages/unread-count?${params}`, {
3249
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey }
3250
+ });
3251
+ if (!res.ok) throw new Error(`Failed to get unread count: ${res.status}`);
3252
+ return await res.json();
3253
+ }
3254
+ // ============================
3255
+ // BROADCAST TASKS
3256
+ // ============================
3257
+ /**
3258
+ * Broadcast a task to all agents with a given capability.
3259
+ * The relay finds matching agents and creates individual tasks for each.
3260
+ */
3261
+ async broadcastTask(options) {
3262
+ const res = await fetch(`${this.baseUrl}/v1/agent/tasks/broadcast`, {
3263
+ method: "POST",
3264
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3265
+ body: JSON.stringify({
3266
+ capability: options.capability,
3267
+ encrypted_input: (0, import_tweetnacl_util.encodeBase64)((0, import_tweetnacl_util.decodeUTF8)(options.input)),
3268
+ input_nonce: (0, import_tweetnacl_util.encodeBase64)(import_tweetnacl.default.randomBytes(24)),
3269
+ priority: options.priority,
3270
+ max_agents: options.maxAgents,
3271
+ min_trust_level: options.minTrustLevel,
3272
+ expires_in: options.expiresIn
3273
+ })
3274
+ });
3275
+ if (!res.ok) {
3276
+ const err = await res.json().catch(() => ({}));
3277
+ throw new Error(err.error || `Broadcast failed: ${res.status}`);
3278
+ }
3279
+ return await res.json();
3280
+ }
3281
+ /**
3282
+ * List your broadcast tasks.
3283
+ */
3284
+ async listBroadcasts(status) {
3285
+ const params = new URLSearchParams();
3286
+ if (status) params.set("status", status);
3287
+ const res = await fetch(`${this.baseUrl}/v1/agent/tasks/broadcasts?${params}`, {
3288
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey }
3289
+ });
3290
+ if (!res.ok) return [];
3291
+ const data = await res.json();
3292
+ return data.broadcasts;
3293
+ }
3294
+ /**
3295
+ * Get broadcast detail with individual task statuses.
3296
+ */
3297
+ async getBroadcast(broadcastId) {
3298
+ const res = await fetch(`${this.baseUrl}/v1/agent/tasks/broadcasts/${broadcastId}`, {
3299
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey }
3300
+ });
3301
+ if (!res.ok) throw new Error(`Failed to get broadcast: ${res.status}`);
3302
+ return await res.json();
3303
+ }
3304
+ // ============================
3305
+ // ANALYTICS
3306
+ // ============================
3307
+ /**
3308
+ * Get your agent's usage analytics.
3309
+ * @param period - '1d' | '7d' | '30d' | 'all'
3310
+ */
3311
+ async getAnalytics(period) {
3312
+ const params = new URLSearchParams();
3313
+ if (period) params.set("period", period);
3314
+ const res = await fetch(`${this.baseUrl}/v1/agent/analytics?${params}`, {
3315
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey }
3316
+ });
3317
+ if (!res.ok) throw new Error(`Failed to get analytics: ${res.status}`);
3318
+ return await res.json();
3319
+ }
3212
3320
  /**
3213
3321
  * Verify an attestation's signature locally without trusting the relay.
3214
3322
  * This is the core of the decentralized witness network — anyone can verify.
@@ -3224,6 +3332,155 @@ var VoidlyAgent = class _VoidlyAgent {
3224
3332
  return false;
3225
3333
  }
3226
3334
  }
3335
+ // ─── Memory Store ──────────────────────────────────────────────────────────
3336
+ /**
3337
+ * Store an encrypted key-value pair in persistent memory.
3338
+ * Values are encrypted with a key derived from your API key — only you can read them.
3339
+ */
3340
+ async memorySet(namespace, key, value, options) {
3341
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(namespace)}/${encodeURIComponent(key)}`, {
3342
+ method: "PUT",
3343
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3344
+ body: JSON.stringify({
3345
+ value,
3346
+ value_type: options?.valueType || (typeof value === "object" ? "json" : typeof value),
3347
+ ttl: options?.ttl
3348
+ })
3349
+ });
3350
+ if (!res.ok) throw new Error(`Memory set failed: ${res.status} ${await res.text()}`);
3351
+ return res.json();
3352
+ }
3353
+ /**
3354
+ * Retrieve a value from persistent memory.
3355
+ * Decrypted server-side using your API key derivation.
3356
+ */
3357
+ async memoryGet(namespace, key) {
3358
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(namespace)}/${encodeURIComponent(key)}`, {
3359
+ headers: { "X-Agent-Key": this.apiKey }
3360
+ });
3361
+ if (res.status === 404) return null;
3362
+ if (!res.ok) throw new Error(`Memory get failed: ${res.status} ${await res.text()}`);
3363
+ return res.json();
3364
+ }
3365
+ /**
3366
+ * Delete a key from persistent memory.
3367
+ */
3368
+ async memoryDelete(namespace, key) {
3369
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(namespace)}/${encodeURIComponent(key)}`, {
3370
+ method: "DELETE",
3371
+ headers: { "X-Agent-Key": this.apiKey }
3372
+ });
3373
+ if (!res.ok) throw new Error(`Memory delete failed: ${res.status} ${await res.text()}`);
3374
+ return res.json();
3375
+ }
3376
+ /**
3377
+ * List all keys in a memory namespace.
3378
+ */
3379
+ async memoryList(namespace, options) {
3380
+ const ns = namespace || "default";
3381
+ const params = new URLSearchParams();
3382
+ if (options?.prefix) params.set("prefix", options.prefix);
3383
+ if (options?.limit) params.set("limit", String(options.limit));
3384
+ const qs = params.toString() ? `?${params.toString()}` : "";
3385
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(ns)}${qs}`, {
3386
+ headers: { "X-Agent-Key": this.apiKey }
3387
+ });
3388
+ if (!res.ok) throw new Error(`Memory list failed: ${res.status} ${await res.text()}`);
3389
+ return res.json();
3390
+ }
3391
+ /**
3392
+ * List all memory namespaces and quota usage.
3393
+ */
3394
+ async memoryNamespaces() {
3395
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory`, {
3396
+ headers: { "X-Agent-Key": this.apiKey }
3397
+ });
3398
+ if (!res.ok) throw new Error(`Memory namespaces failed: ${res.status} ${await res.text()}`);
3399
+ return res.json();
3400
+ }
3401
+ // ─── Data Export ───────────────────────────────────────────────────────────
3402
+ /**
3403
+ * Export all agent data as a portable JSON bundle.
3404
+ * Includes identity, messages, channels, tasks, attestations, memory, and trust.
3405
+ * Memory values remain encrypted — portable to another relay.
3406
+ */
3407
+ async exportData(options) {
3408
+ const res = await fetch(`${this.baseUrl}/v1/agent/export`, {
3409
+ method: "POST",
3410
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3411
+ body: JSON.stringify({
3412
+ include_messages: options?.includeMessages,
3413
+ include_channels: options?.includeChannels,
3414
+ include_tasks: options?.includeTasks,
3415
+ include_attestations: options?.includeAttestations,
3416
+ include_memory: options?.includeMemory,
3417
+ include_trust: options?.includeTrust
3418
+ })
3419
+ });
3420
+ if (!res.ok) throw new Error(`Export failed: ${res.status} ${await res.text()}`);
3421
+ return res.json();
3422
+ }
3423
+ /**
3424
+ * List past data export records.
3425
+ */
3426
+ async listExports() {
3427
+ const res = await fetch(`${this.baseUrl}/v1/agent/exports`, {
3428
+ headers: { "X-Agent-Key": this.apiKey }
3429
+ });
3430
+ if (!res.ok) throw new Error(`List exports failed: ${res.status} ${await res.text()}`);
3431
+ return res.json();
3432
+ }
3433
+ // ─── Relay Federation ─────────────────────────────────────────────────────
3434
+ /**
3435
+ * Get information about the relay this agent is connected to.
3436
+ * Includes federation capabilities and known peers.
3437
+ */
3438
+ async getRelayInfo() {
3439
+ const res = await fetch(`${this.baseUrl}/v1/relay/info`);
3440
+ if (!res.ok) throw new Error(`Relay info failed: ${res.status} ${await res.text()}`);
3441
+ return res.json();
3442
+ }
3443
+ /**
3444
+ * List known federated relay peers.
3445
+ */
3446
+ async getRelayPeers() {
3447
+ const res = await fetch(`${this.baseUrl}/v1/relay/peers`);
3448
+ if (!res.ok) throw new Error(`Relay peers failed: ${res.status} ${await res.text()}`);
3449
+ return res.json();
3450
+ }
3451
+ /**
3452
+ * Route a message through federation to an agent on a different relay.
3453
+ * The relay will forward it to the recipient's home relay.
3454
+ */
3455
+ async routeMessage(toDid, message, options) {
3456
+ const profile = await this.getIdentity(toDid);
3457
+ if (!profile) throw new Error(`Recipient ${toDid} not found`);
3458
+ const recipientPub = (0, import_tweetnacl_util.decodeBase64)(profile.encryption_public_key);
3459
+ const nonce = import_tweetnacl.default.randomBytes(import_tweetnacl.default.box.nonceLength);
3460
+ const encrypted = import_tweetnacl.default.box((0, import_tweetnacl_util.decodeUTF8)(message), nonce, recipientPub, this.encryptionKeyPair.secretKey);
3461
+ if (!encrypted) throw new Error("Encryption failed");
3462
+ const signaturePayload = (0, import_tweetnacl_util.decodeUTF8)(JSON.stringify({
3463
+ from: this.did,
3464
+ to: toDid,
3465
+ nonce: (0, import_tweetnacl_util.encodeBase64)(nonce),
3466
+ ciphertext_hash: await sha256((0, import_tweetnacl_util.encodeBase64)(encrypted))
3467
+ }));
3468
+ const signature = import_tweetnacl.default.sign.detached(signaturePayload, this.signingKeyPair.secretKey);
3469
+ const res = await fetch(`${this.baseUrl}/v1/relay/route`, {
3470
+ method: "POST",
3471
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3472
+ body: JSON.stringify({
3473
+ to: toDid,
3474
+ ciphertext: (0, import_tweetnacl_util.encodeBase64)(encrypted),
3475
+ nonce: (0, import_tweetnacl_util.encodeBase64)(nonce),
3476
+ signature: (0, import_tweetnacl_util.encodeBase64)(signature),
3477
+ content_type: options?.contentType || "text/plain",
3478
+ thread_id: options?.threadId
3479
+ })
3480
+ });
3481
+ if (!res.ok) throw new Error(`Route failed: ${res.status} ${await res.text()}`);
3482
+ return res.json();
3483
+ }
3227
3484
  };
3228
3485
  // Annotate the CommonJS export names for ESM import in node:
3229
3486
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -2464,6 +2464,10 @@ var VoidlyAgent = class _VoidlyAgent {
2464
2464
  const params = new URLSearchParams();
2465
2465
  if (options.since) params.set("since", options.since);
2466
2466
  if (options.limit) params.set("limit", String(options.limit));
2467
+ if (options.from) params.set("from", options.from);
2468
+ if (options.threadId) params.set("thread_id", options.threadId);
2469
+ if (options.contentType) params.set("content_type", options.contentType);
2470
+ if (options.unreadOnly) params.set("unread", "true");
2467
2471
  const res = await fetch(`${this.baseUrl}/v1/agent/receive/raw?${params}`, {
2468
2472
  headers: { "X-Agent-Key": this.apiKey }
2469
2473
  });
@@ -3199,6 +3203,110 @@ var VoidlyAgent = class _VoidlyAgent {
3199
3203
  const data = await res.json();
3200
3204
  return data.leaderboard;
3201
3205
  }
3206
+ // ============================
3207
+ // READ RECEIPTS
3208
+ // ============================
3209
+ /**
3210
+ * Mark a message as read.
3211
+ */
3212
+ async markRead(messageId) {
3213
+ const res = await fetch(`${this.baseUrl}/v1/agent/messages/${messageId}/read`, {
3214
+ method: "POST",
3215
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey }
3216
+ });
3217
+ if (!res.ok) throw new Error(`Failed to mark message as read: ${res.status}`);
3218
+ return await res.json();
3219
+ }
3220
+ /**
3221
+ * Mark multiple messages as read in one call.
3222
+ */
3223
+ async markReadBatch(messageIds) {
3224
+ const res = await fetch(`${this.baseUrl}/v1/agent/messages/read-batch`, {
3225
+ method: "POST",
3226
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3227
+ body: JSON.stringify({ message_ids: messageIds })
3228
+ });
3229
+ if (!res.ok) throw new Error(`Failed to batch mark messages as read: ${res.status}`);
3230
+ return await res.json();
3231
+ }
3232
+ /**
3233
+ * Get unread message count, optionally filtered by sender.
3234
+ */
3235
+ async getUnreadCount(fromDid) {
3236
+ const params = new URLSearchParams();
3237
+ if (fromDid) params.set("from", fromDid);
3238
+ const res = await fetch(`${this.baseUrl}/v1/agent/messages/unread-count?${params}`, {
3239
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey }
3240
+ });
3241
+ if (!res.ok) throw new Error(`Failed to get unread count: ${res.status}`);
3242
+ return await res.json();
3243
+ }
3244
+ // ============================
3245
+ // BROADCAST TASKS
3246
+ // ============================
3247
+ /**
3248
+ * Broadcast a task to all agents with a given capability.
3249
+ * The relay finds matching agents and creates individual tasks for each.
3250
+ */
3251
+ async broadcastTask(options) {
3252
+ const res = await fetch(`${this.baseUrl}/v1/agent/tasks/broadcast`, {
3253
+ method: "POST",
3254
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3255
+ body: JSON.stringify({
3256
+ capability: options.capability,
3257
+ encrypted_input: (0, import_tweetnacl_util.encodeBase64)((0, import_tweetnacl_util.decodeUTF8)(options.input)),
3258
+ input_nonce: (0, import_tweetnacl_util.encodeBase64)(import_tweetnacl.default.randomBytes(24)),
3259
+ priority: options.priority,
3260
+ max_agents: options.maxAgents,
3261
+ min_trust_level: options.minTrustLevel,
3262
+ expires_in: options.expiresIn
3263
+ })
3264
+ });
3265
+ if (!res.ok) {
3266
+ const err = await res.json().catch(() => ({}));
3267
+ throw new Error(err.error || `Broadcast failed: ${res.status}`);
3268
+ }
3269
+ return await res.json();
3270
+ }
3271
+ /**
3272
+ * List your broadcast tasks.
3273
+ */
3274
+ async listBroadcasts(status) {
3275
+ const params = new URLSearchParams();
3276
+ if (status) params.set("status", status);
3277
+ const res = await fetch(`${this.baseUrl}/v1/agent/tasks/broadcasts?${params}`, {
3278
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey }
3279
+ });
3280
+ if (!res.ok) return [];
3281
+ const data = await res.json();
3282
+ return data.broadcasts;
3283
+ }
3284
+ /**
3285
+ * Get broadcast detail with individual task statuses.
3286
+ */
3287
+ async getBroadcast(broadcastId) {
3288
+ const res = await fetch(`${this.baseUrl}/v1/agent/tasks/broadcasts/${broadcastId}`, {
3289
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey }
3290
+ });
3291
+ if (!res.ok) throw new Error(`Failed to get broadcast: ${res.status}`);
3292
+ return await res.json();
3293
+ }
3294
+ // ============================
3295
+ // ANALYTICS
3296
+ // ============================
3297
+ /**
3298
+ * Get your agent's usage analytics.
3299
+ * @param period - '1d' | '7d' | '30d' | 'all'
3300
+ */
3301
+ async getAnalytics(period) {
3302
+ const params = new URLSearchParams();
3303
+ if (period) params.set("period", period);
3304
+ const res = await fetch(`${this.baseUrl}/v1/agent/analytics?${params}`, {
3305
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey }
3306
+ });
3307
+ if (!res.ok) throw new Error(`Failed to get analytics: ${res.status}`);
3308
+ return await res.json();
3309
+ }
3202
3310
  /**
3203
3311
  * Verify an attestation's signature locally without trusting the relay.
3204
3312
  * This is the core of the decentralized witness network — anyone can verify.
@@ -3214,6 +3322,155 @@ var VoidlyAgent = class _VoidlyAgent {
3214
3322
  return false;
3215
3323
  }
3216
3324
  }
3325
+ // ─── Memory Store ──────────────────────────────────────────────────────────
3326
+ /**
3327
+ * Store an encrypted key-value pair in persistent memory.
3328
+ * Values are encrypted with a key derived from your API key — only you can read them.
3329
+ */
3330
+ async memorySet(namespace, key, value, options) {
3331
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(namespace)}/${encodeURIComponent(key)}`, {
3332
+ method: "PUT",
3333
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3334
+ body: JSON.stringify({
3335
+ value,
3336
+ value_type: options?.valueType || (typeof value === "object" ? "json" : typeof value),
3337
+ ttl: options?.ttl
3338
+ })
3339
+ });
3340
+ if (!res.ok) throw new Error(`Memory set failed: ${res.status} ${await res.text()}`);
3341
+ return res.json();
3342
+ }
3343
+ /**
3344
+ * Retrieve a value from persistent memory.
3345
+ * Decrypted server-side using your API key derivation.
3346
+ */
3347
+ async memoryGet(namespace, key) {
3348
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(namespace)}/${encodeURIComponent(key)}`, {
3349
+ headers: { "X-Agent-Key": this.apiKey }
3350
+ });
3351
+ if (res.status === 404) return null;
3352
+ if (!res.ok) throw new Error(`Memory get failed: ${res.status} ${await res.text()}`);
3353
+ return res.json();
3354
+ }
3355
+ /**
3356
+ * Delete a key from persistent memory.
3357
+ */
3358
+ async memoryDelete(namespace, key) {
3359
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(namespace)}/${encodeURIComponent(key)}`, {
3360
+ method: "DELETE",
3361
+ headers: { "X-Agent-Key": this.apiKey }
3362
+ });
3363
+ if (!res.ok) throw new Error(`Memory delete failed: ${res.status} ${await res.text()}`);
3364
+ return res.json();
3365
+ }
3366
+ /**
3367
+ * List all keys in a memory namespace.
3368
+ */
3369
+ async memoryList(namespace, options) {
3370
+ const ns = namespace || "default";
3371
+ const params = new URLSearchParams();
3372
+ if (options?.prefix) params.set("prefix", options.prefix);
3373
+ if (options?.limit) params.set("limit", String(options.limit));
3374
+ const qs = params.toString() ? `?${params.toString()}` : "";
3375
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory/${encodeURIComponent(ns)}${qs}`, {
3376
+ headers: { "X-Agent-Key": this.apiKey }
3377
+ });
3378
+ if (!res.ok) throw new Error(`Memory list failed: ${res.status} ${await res.text()}`);
3379
+ return res.json();
3380
+ }
3381
+ /**
3382
+ * List all memory namespaces and quota usage.
3383
+ */
3384
+ async memoryNamespaces() {
3385
+ const res = await fetch(`${this.baseUrl}/v1/agent/memory`, {
3386
+ headers: { "X-Agent-Key": this.apiKey }
3387
+ });
3388
+ if (!res.ok) throw new Error(`Memory namespaces failed: ${res.status} ${await res.text()}`);
3389
+ return res.json();
3390
+ }
3391
+ // ─── Data Export ───────────────────────────────────────────────────────────
3392
+ /**
3393
+ * Export all agent data as a portable JSON bundle.
3394
+ * Includes identity, messages, channels, tasks, attestations, memory, and trust.
3395
+ * Memory values remain encrypted — portable to another relay.
3396
+ */
3397
+ async exportData(options) {
3398
+ const res = await fetch(`${this.baseUrl}/v1/agent/export`, {
3399
+ method: "POST",
3400
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3401
+ body: JSON.stringify({
3402
+ include_messages: options?.includeMessages,
3403
+ include_channels: options?.includeChannels,
3404
+ include_tasks: options?.includeTasks,
3405
+ include_attestations: options?.includeAttestations,
3406
+ include_memory: options?.includeMemory,
3407
+ include_trust: options?.includeTrust
3408
+ })
3409
+ });
3410
+ if (!res.ok) throw new Error(`Export failed: ${res.status} ${await res.text()}`);
3411
+ return res.json();
3412
+ }
3413
+ /**
3414
+ * List past data export records.
3415
+ */
3416
+ async listExports() {
3417
+ const res = await fetch(`${this.baseUrl}/v1/agent/exports`, {
3418
+ headers: { "X-Agent-Key": this.apiKey }
3419
+ });
3420
+ if (!res.ok) throw new Error(`List exports failed: ${res.status} ${await res.text()}`);
3421
+ return res.json();
3422
+ }
3423
+ // ─── Relay Federation ─────────────────────────────────────────────────────
3424
+ /**
3425
+ * Get information about the relay this agent is connected to.
3426
+ * Includes federation capabilities and known peers.
3427
+ */
3428
+ async getRelayInfo() {
3429
+ const res = await fetch(`${this.baseUrl}/v1/relay/info`);
3430
+ if (!res.ok) throw new Error(`Relay info failed: ${res.status} ${await res.text()}`);
3431
+ return res.json();
3432
+ }
3433
+ /**
3434
+ * List known federated relay peers.
3435
+ */
3436
+ async getRelayPeers() {
3437
+ const res = await fetch(`${this.baseUrl}/v1/relay/peers`);
3438
+ if (!res.ok) throw new Error(`Relay peers failed: ${res.status} ${await res.text()}`);
3439
+ return res.json();
3440
+ }
3441
+ /**
3442
+ * Route a message through federation to an agent on a different relay.
3443
+ * The relay will forward it to the recipient's home relay.
3444
+ */
3445
+ async routeMessage(toDid, message, options) {
3446
+ const profile = await this.getIdentity(toDid);
3447
+ if (!profile) throw new Error(`Recipient ${toDid} not found`);
3448
+ const recipientPub = (0, import_tweetnacl_util.decodeBase64)(profile.encryption_public_key);
3449
+ const nonce = import_tweetnacl.default.randomBytes(import_tweetnacl.default.box.nonceLength);
3450
+ const encrypted = import_tweetnacl.default.box((0, import_tweetnacl_util.decodeUTF8)(message), nonce, recipientPub, this.encryptionKeyPair.secretKey);
3451
+ if (!encrypted) throw new Error("Encryption failed");
3452
+ const signaturePayload = (0, import_tweetnacl_util.decodeUTF8)(JSON.stringify({
3453
+ from: this.did,
3454
+ to: toDid,
3455
+ nonce: (0, import_tweetnacl_util.encodeBase64)(nonce),
3456
+ ciphertext_hash: await sha256((0, import_tweetnacl_util.encodeBase64)(encrypted))
3457
+ }));
3458
+ const signature = import_tweetnacl.default.sign.detached(signaturePayload, this.signingKeyPair.secretKey);
3459
+ const res = await fetch(`${this.baseUrl}/v1/relay/route`, {
3460
+ method: "POST",
3461
+ headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
3462
+ body: JSON.stringify({
3463
+ to: toDid,
3464
+ ciphertext: (0, import_tweetnacl_util.encodeBase64)(encrypted),
3465
+ nonce: (0, import_tweetnacl_util.encodeBase64)(nonce),
3466
+ signature: (0, import_tweetnacl_util.encodeBase64)(signature),
3467
+ content_type: options?.contentType || "text/plain",
3468
+ thread_id: options?.threadId
3469
+ })
3470
+ });
3471
+ if (!res.ok) throw new Error(`Route failed: ${res.status} ${await res.text()}`);
3472
+ return res.json();
3473
+ }
3217
3474
  };
3218
3475
  var export_decodeBase64 = import_tweetnacl_util.decodeBase64;
3219
3476
  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.5.0",
3
+ "version": "1.7.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",