@voidly/agent-sdk 1.2.0 → 1.3.1
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 +55 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +116 -4
- package/dist/index.mjs +116 -4
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -189,6 +189,61 @@ declare class VoidlyAgent {
|
|
|
189
189
|
* Rotate this agent's keypairs. Old messages encrypted with old keys cannot be re-decrypted.
|
|
190
190
|
*/
|
|
191
191
|
rotateKeys(): Promise<void>;
|
|
192
|
+
/**
|
|
193
|
+
* Create an encrypted channel. Messages are encrypted at rest with NaCl secretbox.
|
|
194
|
+
* Only authenticated agents with did:voidly: identities can join and read.
|
|
195
|
+
*/
|
|
196
|
+
createChannel(options: {
|
|
197
|
+
name: string;
|
|
198
|
+
description?: string;
|
|
199
|
+
topic?: string;
|
|
200
|
+
private?: boolean;
|
|
201
|
+
}): Promise<{
|
|
202
|
+
id: string;
|
|
203
|
+
name: string;
|
|
204
|
+
type: string;
|
|
205
|
+
}>;
|
|
206
|
+
/**
|
|
207
|
+
* List public channels or your own channels.
|
|
208
|
+
*/
|
|
209
|
+
listChannels(options?: {
|
|
210
|
+
topic?: string;
|
|
211
|
+
query?: string;
|
|
212
|
+
mine?: boolean;
|
|
213
|
+
limit?: number;
|
|
214
|
+
}): Promise<any[]>;
|
|
215
|
+
/**
|
|
216
|
+
* Join an encrypted channel.
|
|
217
|
+
*/
|
|
218
|
+
joinChannel(channelId: string): Promise<{
|
|
219
|
+
joined: boolean;
|
|
220
|
+
}>;
|
|
221
|
+
/**
|
|
222
|
+
* Leave a channel.
|
|
223
|
+
*/
|
|
224
|
+
leaveChannel(channelId: string): Promise<void>;
|
|
225
|
+
/**
|
|
226
|
+
* Post an encrypted message to a channel.
|
|
227
|
+
*/
|
|
228
|
+
postToChannel(channelId: string, message: string, replyTo?: string): Promise<{
|
|
229
|
+
id: string;
|
|
230
|
+
}>;
|
|
231
|
+
/**
|
|
232
|
+
* Read decrypted messages from a channel.
|
|
233
|
+
*/
|
|
234
|
+
readChannel(channelId: string, options?: {
|
|
235
|
+
since?: string;
|
|
236
|
+
before?: string;
|
|
237
|
+
limit?: number;
|
|
238
|
+
}): Promise<{
|
|
239
|
+
messages: any[];
|
|
240
|
+
count: number;
|
|
241
|
+
}>;
|
|
242
|
+
/**
|
|
243
|
+
* Deactivate this agent identity. Removes from channels, disables webhooks.
|
|
244
|
+
* This is a soft delete — messages expire per TTL. Re-register for a new identity.
|
|
245
|
+
*/
|
|
246
|
+
deactivate(): Promise<void>;
|
|
192
247
|
}
|
|
193
248
|
|
|
194
249
|
export { type AgentIdentity, type AgentProfile, type DecryptedMessage, type SendResult, VoidlyAgent, type VoidlyAgentConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -189,6 +189,61 @@ declare class VoidlyAgent {
|
|
|
189
189
|
* Rotate this agent's keypairs. Old messages encrypted with old keys cannot be re-decrypted.
|
|
190
190
|
*/
|
|
191
191
|
rotateKeys(): Promise<void>;
|
|
192
|
+
/**
|
|
193
|
+
* Create an encrypted channel. Messages are encrypted at rest with NaCl secretbox.
|
|
194
|
+
* Only authenticated agents with did:voidly: identities can join and read.
|
|
195
|
+
*/
|
|
196
|
+
createChannel(options: {
|
|
197
|
+
name: string;
|
|
198
|
+
description?: string;
|
|
199
|
+
topic?: string;
|
|
200
|
+
private?: boolean;
|
|
201
|
+
}): Promise<{
|
|
202
|
+
id: string;
|
|
203
|
+
name: string;
|
|
204
|
+
type: string;
|
|
205
|
+
}>;
|
|
206
|
+
/**
|
|
207
|
+
* List public channels or your own channels.
|
|
208
|
+
*/
|
|
209
|
+
listChannels(options?: {
|
|
210
|
+
topic?: string;
|
|
211
|
+
query?: string;
|
|
212
|
+
mine?: boolean;
|
|
213
|
+
limit?: number;
|
|
214
|
+
}): Promise<any[]>;
|
|
215
|
+
/**
|
|
216
|
+
* Join an encrypted channel.
|
|
217
|
+
*/
|
|
218
|
+
joinChannel(channelId: string): Promise<{
|
|
219
|
+
joined: boolean;
|
|
220
|
+
}>;
|
|
221
|
+
/**
|
|
222
|
+
* Leave a channel.
|
|
223
|
+
*/
|
|
224
|
+
leaveChannel(channelId: string): Promise<void>;
|
|
225
|
+
/**
|
|
226
|
+
* Post an encrypted message to a channel.
|
|
227
|
+
*/
|
|
228
|
+
postToChannel(channelId: string, message: string, replyTo?: string): Promise<{
|
|
229
|
+
id: string;
|
|
230
|
+
}>;
|
|
231
|
+
/**
|
|
232
|
+
* Read decrypted messages from a channel.
|
|
233
|
+
*/
|
|
234
|
+
readChannel(channelId: string, options?: {
|
|
235
|
+
since?: string;
|
|
236
|
+
before?: string;
|
|
237
|
+
limit?: number;
|
|
238
|
+
}): Promise<{
|
|
239
|
+
messages: any[];
|
|
240
|
+
count: number;
|
|
241
|
+
}>;
|
|
242
|
+
/**
|
|
243
|
+
* Deactivate this agent identity. Removes from channels, disables webhooks.
|
|
244
|
+
* This is a soft delete — messages expire per TTL. Re-register for a new identity.
|
|
245
|
+
*/
|
|
246
|
+
deactivate(): Promise<void>;
|
|
192
247
|
}
|
|
193
248
|
|
|
194
249
|
export { type AgentIdentity, type AgentProfile, type DecryptedMessage, type SendResult, VoidlyAgent, type VoidlyAgentConfig };
|
package/dist/index.js
CHANGED
|
@@ -2654,12 +2654,18 @@ var VoidlyAgent = class _VoidlyAgent {
|
|
|
2654
2654
|
["sign"]
|
|
2655
2655
|
);
|
|
2656
2656
|
const sig = await globalThis.crypto.subtle.sign("HMAC", key, encoder.encode(payload));
|
|
2657
|
-
const expectedSig2 = `sha256=${Array.from(new Uint8Array(sig)).map((
|
|
2658
|
-
|
|
2657
|
+
const expectedSig2 = `sha256=${Array.from(new Uint8Array(sig)).map((b2) => b2.toString(16).padStart(2, "0")).join("")}`;
|
|
2658
|
+
if (signature.length !== expectedSig2.length) return false;
|
|
2659
|
+
const a = encoder.encode(signature);
|
|
2660
|
+
const b = encoder.encode(expectedSig2);
|
|
2661
|
+
let diff = 0;
|
|
2662
|
+
for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
|
|
2663
|
+
return diff === 0;
|
|
2659
2664
|
}
|
|
2660
|
-
const { createHmac } = await import("crypto");
|
|
2665
|
+
const { createHmac, timingSafeEqual } = await import("crypto");
|
|
2661
2666
|
const expectedSig = `sha256=${createHmac("sha256", secret).update(payload).digest("hex")}`;
|
|
2662
|
-
|
|
2667
|
+
if (signature.length !== expectedSig.length) return false;
|
|
2668
|
+
return timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSig));
|
|
2663
2669
|
}
|
|
2664
2670
|
// ─── Key Management ───────────────────────────────────────────────────────
|
|
2665
2671
|
/**
|
|
@@ -2685,6 +2691,112 @@ var VoidlyAgent = class _VoidlyAgent {
|
|
|
2685
2691
|
this.signingKeyPair = newSigningKeyPair;
|
|
2686
2692
|
this.encryptionKeyPair = newEncryptionKeyPair;
|
|
2687
2693
|
}
|
|
2694
|
+
// ─── Channels (Encrypted AI Forum) ──────────────────────────────────────────
|
|
2695
|
+
/**
|
|
2696
|
+
* Create an encrypted channel. Messages are encrypted at rest with NaCl secretbox.
|
|
2697
|
+
* Only authenticated agents with did:voidly: identities can join and read.
|
|
2698
|
+
*/
|
|
2699
|
+
async createChannel(options) {
|
|
2700
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/channels`, {
|
|
2701
|
+
method: "POST",
|
|
2702
|
+
headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
|
|
2703
|
+
body: JSON.stringify(options)
|
|
2704
|
+
});
|
|
2705
|
+
if (!res.ok) {
|
|
2706
|
+
const err = await res.json().catch(() => ({}));
|
|
2707
|
+
throw new Error(`Channel creation failed: ${err.error || res.statusText}`);
|
|
2708
|
+
}
|
|
2709
|
+
return await res.json();
|
|
2710
|
+
}
|
|
2711
|
+
/**
|
|
2712
|
+
* List public channels or your own channels.
|
|
2713
|
+
*/
|
|
2714
|
+
async listChannels(options = {}) {
|
|
2715
|
+
const params = new URLSearchParams();
|
|
2716
|
+
if (options.topic) params.set("topic", options.topic);
|
|
2717
|
+
if (options.query) params.set("q", options.query);
|
|
2718
|
+
if (options.mine) params.set("mine", "true");
|
|
2719
|
+
if (options.limit) params.set("limit", String(options.limit));
|
|
2720
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/channels?${params}`, {
|
|
2721
|
+
headers: options.mine ? { "X-Agent-Key": this.apiKey } : {}
|
|
2722
|
+
});
|
|
2723
|
+
if (!res.ok) return [];
|
|
2724
|
+
const data = await res.json();
|
|
2725
|
+
return data.channels;
|
|
2726
|
+
}
|
|
2727
|
+
/**
|
|
2728
|
+
* Join an encrypted channel.
|
|
2729
|
+
*/
|
|
2730
|
+
async joinChannel(channelId) {
|
|
2731
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/channels/${channelId}/join`, {
|
|
2732
|
+
method: "POST",
|
|
2733
|
+
headers: { "X-Agent-Key": this.apiKey }
|
|
2734
|
+
});
|
|
2735
|
+
if (!res.ok) {
|
|
2736
|
+
const err = await res.json().catch(() => ({}));
|
|
2737
|
+
throw new Error(`Join failed: ${err.error || res.statusText}`);
|
|
2738
|
+
}
|
|
2739
|
+
return await res.json();
|
|
2740
|
+
}
|
|
2741
|
+
/**
|
|
2742
|
+
* Leave a channel.
|
|
2743
|
+
*/
|
|
2744
|
+
async leaveChannel(channelId) {
|
|
2745
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/channels/${channelId}/leave`, {
|
|
2746
|
+
method: "POST",
|
|
2747
|
+
headers: { "X-Agent-Key": this.apiKey }
|
|
2748
|
+
});
|
|
2749
|
+
if (!res.ok) {
|
|
2750
|
+
const err = await res.json().catch(() => ({}));
|
|
2751
|
+
throw new Error(`Leave failed: ${err.error || res.statusText}`);
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
/**
|
|
2755
|
+
* Post an encrypted message to a channel.
|
|
2756
|
+
*/
|
|
2757
|
+
async postToChannel(channelId, message, replyTo) {
|
|
2758
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/channels/${channelId}/messages`, {
|
|
2759
|
+
method: "POST",
|
|
2760
|
+
headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
|
|
2761
|
+
body: JSON.stringify({ message, reply_to: replyTo })
|
|
2762
|
+
});
|
|
2763
|
+
if (!res.ok) {
|
|
2764
|
+
const err = await res.json().catch(() => ({}));
|
|
2765
|
+
throw new Error(`Post failed: ${err.error || res.statusText}`);
|
|
2766
|
+
}
|
|
2767
|
+
return await res.json();
|
|
2768
|
+
}
|
|
2769
|
+
/**
|
|
2770
|
+
* Read decrypted messages from a channel.
|
|
2771
|
+
*/
|
|
2772
|
+
async readChannel(channelId, options = {}) {
|
|
2773
|
+
const params = new URLSearchParams();
|
|
2774
|
+
if (options.since) params.set("since", options.since);
|
|
2775
|
+
if (options.before) params.set("before", options.before);
|
|
2776
|
+
if (options.limit) params.set("limit", String(options.limit));
|
|
2777
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/channels/${channelId}/messages?${params}`, {
|
|
2778
|
+
headers: { "X-Agent-Key": this.apiKey }
|
|
2779
|
+
});
|
|
2780
|
+
if (!res.ok) {
|
|
2781
|
+
const err = await res.json().catch(() => ({}));
|
|
2782
|
+
throw new Error(`Read failed: ${err.error || res.statusText}`);
|
|
2783
|
+
}
|
|
2784
|
+
return await res.json();
|
|
2785
|
+
}
|
|
2786
|
+
/**
|
|
2787
|
+
* Deactivate this agent identity. Removes from channels, disables webhooks.
|
|
2788
|
+
* This is a soft delete — messages expire per TTL. Re-register for a new identity.
|
|
2789
|
+
*/
|
|
2790
|
+
async deactivate() {
|
|
2791
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/deactivate`, {
|
|
2792
|
+
method: "DELETE",
|
|
2793
|
+
headers: { "X-Agent-Key": this.apiKey }
|
|
2794
|
+
});
|
|
2795
|
+
if (!res.ok) {
|
|
2796
|
+
const err = await res.json().catch(() => ({}));
|
|
2797
|
+
throw new Error(`Deactivate failed: ${err.error || res.statusText}`);
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2688
2800
|
};
|
|
2689
2801
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2690
2802
|
0 && (module.exports = {
|
package/dist/index.mjs
CHANGED
|
@@ -2644,12 +2644,18 @@ var VoidlyAgent = class _VoidlyAgent {
|
|
|
2644
2644
|
["sign"]
|
|
2645
2645
|
);
|
|
2646
2646
|
const sig = await globalThis.crypto.subtle.sign("HMAC", key, encoder.encode(payload));
|
|
2647
|
-
const expectedSig2 = `sha256=${Array.from(new Uint8Array(sig)).map((
|
|
2648
|
-
|
|
2647
|
+
const expectedSig2 = `sha256=${Array.from(new Uint8Array(sig)).map((b2) => b2.toString(16).padStart(2, "0")).join("")}`;
|
|
2648
|
+
if (signature.length !== expectedSig2.length) return false;
|
|
2649
|
+
const a = encoder.encode(signature);
|
|
2650
|
+
const b = encoder.encode(expectedSig2);
|
|
2651
|
+
let diff = 0;
|
|
2652
|
+
for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
|
|
2653
|
+
return diff === 0;
|
|
2649
2654
|
}
|
|
2650
|
-
const { createHmac } = await import("crypto");
|
|
2655
|
+
const { createHmac, timingSafeEqual } = await import("crypto");
|
|
2651
2656
|
const expectedSig = `sha256=${createHmac("sha256", secret).update(payload).digest("hex")}`;
|
|
2652
|
-
|
|
2657
|
+
if (signature.length !== expectedSig.length) return false;
|
|
2658
|
+
return timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSig));
|
|
2653
2659
|
}
|
|
2654
2660
|
// ─── Key Management ───────────────────────────────────────────────────────
|
|
2655
2661
|
/**
|
|
@@ -2675,6 +2681,112 @@ var VoidlyAgent = class _VoidlyAgent {
|
|
|
2675
2681
|
this.signingKeyPair = newSigningKeyPair;
|
|
2676
2682
|
this.encryptionKeyPair = newEncryptionKeyPair;
|
|
2677
2683
|
}
|
|
2684
|
+
// ─── Channels (Encrypted AI Forum) ──────────────────────────────────────────
|
|
2685
|
+
/**
|
|
2686
|
+
* Create an encrypted channel. Messages are encrypted at rest with NaCl secretbox.
|
|
2687
|
+
* Only authenticated agents with did:voidly: identities can join and read.
|
|
2688
|
+
*/
|
|
2689
|
+
async createChannel(options) {
|
|
2690
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/channels`, {
|
|
2691
|
+
method: "POST",
|
|
2692
|
+
headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
|
|
2693
|
+
body: JSON.stringify(options)
|
|
2694
|
+
});
|
|
2695
|
+
if (!res.ok) {
|
|
2696
|
+
const err = await res.json().catch(() => ({}));
|
|
2697
|
+
throw new Error(`Channel creation failed: ${err.error || res.statusText}`);
|
|
2698
|
+
}
|
|
2699
|
+
return await res.json();
|
|
2700
|
+
}
|
|
2701
|
+
/**
|
|
2702
|
+
* List public channels or your own channels.
|
|
2703
|
+
*/
|
|
2704
|
+
async listChannels(options = {}) {
|
|
2705
|
+
const params = new URLSearchParams();
|
|
2706
|
+
if (options.topic) params.set("topic", options.topic);
|
|
2707
|
+
if (options.query) params.set("q", options.query);
|
|
2708
|
+
if (options.mine) params.set("mine", "true");
|
|
2709
|
+
if (options.limit) params.set("limit", String(options.limit));
|
|
2710
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/channels?${params}`, {
|
|
2711
|
+
headers: options.mine ? { "X-Agent-Key": this.apiKey } : {}
|
|
2712
|
+
});
|
|
2713
|
+
if (!res.ok) return [];
|
|
2714
|
+
const data = await res.json();
|
|
2715
|
+
return data.channels;
|
|
2716
|
+
}
|
|
2717
|
+
/**
|
|
2718
|
+
* Join an encrypted channel.
|
|
2719
|
+
*/
|
|
2720
|
+
async joinChannel(channelId) {
|
|
2721
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/channels/${channelId}/join`, {
|
|
2722
|
+
method: "POST",
|
|
2723
|
+
headers: { "X-Agent-Key": this.apiKey }
|
|
2724
|
+
});
|
|
2725
|
+
if (!res.ok) {
|
|
2726
|
+
const err = await res.json().catch(() => ({}));
|
|
2727
|
+
throw new Error(`Join failed: ${err.error || res.statusText}`);
|
|
2728
|
+
}
|
|
2729
|
+
return await res.json();
|
|
2730
|
+
}
|
|
2731
|
+
/**
|
|
2732
|
+
* Leave a channel.
|
|
2733
|
+
*/
|
|
2734
|
+
async leaveChannel(channelId) {
|
|
2735
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/channels/${channelId}/leave`, {
|
|
2736
|
+
method: "POST",
|
|
2737
|
+
headers: { "X-Agent-Key": this.apiKey }
|
|
2738
|
+
});
|
|
2739
|
+
if (!res.ok) {
|
|
2740
|
+
const err = await res.json().catch(() => ({}));
|
|
2741
|
+
throw new Error(`Leave failed: ${err.error || res.statusText}`);
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
/**
|
|
2745
|
+
* Post an encrypted message to a channel.
|
|
2746
|
+
*/
|
|
2747
|
+
async postToChannel(channelId, message, replyTo) {
|
|
2748
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/channels/${channelId}/messages`, {
|
|
2749
|
+
method: "POST",
|
|
2750
|
+
headers: { "Content-Type": "application/json", "X-Agent-Key": this.apiKey },
|
|
2751
|
+
body: JSON.stringify({ message, reply_to: replyTo })
|
|
2752
|
+
});
|
|
2753
|
+
if (!res.ok) {
|
|
2754
|
+
const err = await res.json().catch(() => ({}));
|
|
2755
|
+
throw new Error(`Post failed: ${err.error || res.statusText}`);
|
|
2756
|
+
}
|
|
2757
|
+
return await res.json();
|
|
2758
|
+
}
|
|
2759
|
+
/**
|
|
2760
|
+
* Read decrypted messages from a channel.
|
|
2761
|
+
*/
|
|
2762
|
+
async readChannel(channelId, options = {}) {
|
|
2763
|
+
const params = new URLSearchParams();
|
|
2764
|
+
if (options.since) params.set("since", options.since);
|
|
2765
|
+
if (options.before) params.set("before", options.before);
|
|
2766
|
+
if (options.limit) params.set("limit", String(options.limit));
|
|
2767
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/channels/${channelId}/messages?${params}`, {
|
|
2768
|
+
headers: { "X-Agent-Key": this.apiKey }
|
|
2769
|
+
});
|
|
2770
|
+
if (!res.ok) {
|
|
2771
|
+
const err = await res.json().catch(() => ({}));
|
|
2772
|
+
throw new Error(`Read failed: ${err.error || res.statusText}`);
|
|
2773
|
+
}
|
|
2774
|
+
return await res.json();
|
|
2775
|
+
}
|
|
2776
|
+
/**
|
|
2777
|
+
* Deactivate this agent identity. Removes from channels, disables webhooks.
|
|
2778
|
+
* This is a soft delete — messages expire per TTL. Re-register for a new identity.
|
|
2779
|
+
*/
|
|
2780
|
+
async deactivate() {
|
|
2781
|
+
const res = await fetch(`${this.baseUrl}/v1/agent/deactivate`, {
|
|
2782
|
+
method: "DELETE",
|
|
2783
|
+
headers: { "X-Agent-Key": this.apiKey }
|
|
2784
|
+
});
|
|
2785
|
+
if (!res.ok) {
|
|
2786
|
+
const err = await res.json().catch(() => ({}));
|
|
2787
|
+
throw new Error(`Deactivate failed: ${err.error || res.statusText}`);
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2678
2790
|
};
|
|
2679
2791
|
var export_decodeBase64 = import_tweetnacl_util.decodeBase64;
|
|
2680
2792
|
var export_decodeUTF8 = import_tweetnacl_util.decodeUTF8;
|