hiloop-sdk 0.1.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.
@@ -0,0 +1,113 @@
1
+ /** E2E encryption for the Hiloop SDK using tweetnacl (X25519 + XSalsa20-Poly1305). */
2
+ export interface KeyPair {
3
+ publicKey: string;
4
+ secretKey: string;
5
+ }
6
+ /** Generate an X25519 keypair. */
7
+ export declare function generateKeyPair(): KeyPair;
8
+ /** Encrypt plaintext for a recipient using NaCl box. Returns base64 ciphertext. */
9
+ export declare function encrypt(plaintext: string, senderSecretKeyB64: string, recipientPublicKeyB64: string): string;
10
+ /** Decrypt base64 ciphertext. Returns plaintext. */
11
+ export declare function decrypt(ciphertextB64: string, recipientSecretKeyB64: string, senderPublicKeyB64: string): string;
12
+ export interface ContentWrapping {
13
+ scope: string;
14
+ recipientKeyId: string;
15
+ encryptedSymmetricKey: string;
16
+ nonce: string;
17
+ }
18
+ export interface WrappedContent {
19
+ ciphertext: string;
20
+ wrappings: ContentWrapping[];
21
+ }
22
+ /** Content wrapping result for ECDH + HKDF + AES-GCM scheme (session titles). */
23
+ export interface ContentWrappingResult {
24
+ ciphertext: string;
25
+ wrappings: Array<{
26
+ scope: string;
27
+ recipientKeyId: string;
28
+ wrappedContentKey: string;
29
+ }>;
30
+ }
31
+ /**
32
+ * Derive a symmetric wrapping key from an X25519 shared secret using HKDF-SHA256.
33
+ * Compatible with the frontend's deriveWrappingKey function.
34
+ */
35
+ export declare function deriveWrappingKey(sharedSecretB64: string, context: string): Promise<string>;
36
+ /** Encrypt content with AES-256-GCM and wrap the content key for a recipient via NaCl box. */
37
+ export declare function encryptContent(plaintext: string, recipientPublicKeyB64: string, recipientKeyId: string, senderSecretKeyB64: string, scope?: string): WrappedContent;
38
+ /** Decrypt wrapped content using the sender's public key and recipient's secret key. */
39
+ export declare function decryptContent(wrapped: WrappedContent, recipientKeyId: string, recipientSecretKeyB64: string, senderPublicKeyB64: string): string;
40
+ /** Manages encryption/decryption context for SDK operations. */
41
+ export declare class CryptoContext {
42
+ private secretKeyB64;
43
+ private publicKeyB64;
44
+ private recipientPublicKeyB64;
45
+ private recipientKeyId;
46
+ private serverKeyId?;
47
+ constructor(secretKeyB64: string, publicKeyB64: string, recipientPublicKeyB64: string, recipientKeyId: string, serverKeyId?: string | undefined);
48
+ /** Compute X25519 ECDH shared secret with the recipient (space) public key. */
49
+ getSharedSecret(): string;
50
+ /** Get the agent's public key (base64). */
51
+ getPublicKey(): string;
52
+ /** Get the space key ID. */
53
+ getSpaceKeyId(): string;
54
+ encryptField(plaintext: string): WrappedContent;
55
+ decryptField(wrapped: WrappedContent, senderPublicKeyB64: string): string;
56
+ /** Encrypt a plaintext field, returning the ciphertext and wrappings separately. */
57
+ encryptForApi(plaintext: string): {
58
+ ciphertext: string;
59
+ wrappings: ContentWrapping[];
60
+ };
61
+ /**
62
+ * Decrypt content encrypted with encryptWithWrapping (ECDH + HKDF + AES-GCM).
63
+ * Finds the wrapping matching this context's space key, unwraps the content key,
64
+ * then decrypts the ciphertext. Returns null on any failure.
65
+ */
66
+ decryptWrappedContent(ciphertext: string, wrappings: Array<{
67
+ recipientKeyId?: string;
68
+ wrappedContentKey?: string;
69
+ }>): Promise<string | null>;
70
+ /**
71
+ * Derive the session message key for encrypting/decrypting conv session messages.
72
+ * Session messages use the format `{agentPubBase64}:{AES-GCM ciphertext}`.
73
+ */
74
+ getSessionMessageKey(): Promise<string>;
75
+ /**
76
+ * Encrypt a conv session message: `{agentPubBase64}:{AES-256-GCM ciphertext}`.
77
+ */
78
+ encryptSessionMessage(content: string): Promise<string>;
79
+ /**
80
+ * Decrypt a conv session message. Handles both `{pubKey}:{ciphertext}` format
81
+ * and raw AES-GCM ciphertext. Returns null on failure.
82
+ */
83
+ decryptSessionMessage(encryptedContent: string): Promise<string | null>;
84
+ /**
85
+ * Encrypt content using the content wrapping scheme (ECDH + HKDF + AES-GCM).
86
+ * Compatible with the frontend's decryptContent function.
87
+ *
88
+ * This generates a random content key, encrypts the plaintext with AES-256-GCM,
89
+ * then wraps (encrypts) the content key using a wrapping key derived from
90
+ * ECDH(agentSecretKey, spacePublicKey) + HKDF.
91
+ *
92
+ * @param plaintext - Text to encrypt
93
+ * @param spaceKeyId - ID of the space public key (used as recipientKeyId in wrapping)
94
+ */
95
+ encryptWithWrapping(plaintext: string, spaceKeyId?: string): Promise<ContentWrappingResult>;
96
+ }
97
+ /**
98
+ * Encrypt plaintext using AES-256-GCM.
99
+ * Returns base64(12-byte nonce || ciphertext || 16-byte auth tag).
100
+ * Compatible with the Hiloop frontend's session message encryption.
101
+ *
102
+ * @param plaintext - The text to encrypt
103
+ * @param keyBase64 - Base64-encoded 32-byte AES-256 key
104
+ */
105
+ export declare function encryptAes(plaintext: string, keyBase64: string): Promise<string>;
106
+ /**
107
+ * Decrypt AES-256-GCM ciphertext.
108
+ * Expects base64(12-byte nonce || ciphertext || 16-byte auth tag).
109
+ *
110
+ * @param ciphertextBase64 - Base64-encoded ciphertext
111
+ * @param keyBase64 - Base64-encoded 32-byte AES-256 key
112
+ */
113
+ export declare function decryptAes(ciphertextBase64: string, keyBase64: string): Promise<string>;
package/dist/crypto.js ADDED
@@ -0,0 +1,278 @@
1
+ /** E2E encryption for the Hiloop SDK using tweetnacl (X25519 + XSalsa20-Poly1305). */
2
+ import nacl from "tweetnacl";
3
+ import util from "tweetnacl-util";
4
+ /** Generate an X25519 keypair. */
5
+ export function generateKeyPair() {
6
+ const kp = nacl.box.keyPair();
7
+ return {
8
+ publicKey: util.encodeBase64(kp.publicKey),
9
+ secretKey: util.encodeBase64(kp.secretKey),
10
+ };
11
+ }
12
+ /** Encrypt plaintext for a recipient using NaCl box. Returns base64 ciphertext. */
13
+ export function encrypt(plaintext, senderSecretKeyB64, recipientPublicKeyB64) {
14
+ const sk = util.decodeBase64(senderSecretKeyB64);
15
+ const pk = util.decodeBase64(recipientPublicKeyB64);
16
+ const nonce = nacl.randomBytes(nacl.box.nonceLength);
17
+ const msg = util.decodeUTF8(plaintext);
18
+ const ct = nacl.box(msg, nonce, pk, sk);
19
+ if (ct === null)
20
+ throw new Error("Encryption failed");
21
+ // Combine nonce + ciphertext
22
+ const combined = new Uint8Array(nonce.length + ct.length);
23
+ combined.set(nonce);
24
+ combined.set(ct, nonce.length);
25
+ return util.encodeBase64(combined);
26
+ }
27
+ /** Decrypt base64 ciphertext. Returns plaintext. */
28
+ export function decrypt(ciphertextB64, recipientSecretKeyB64, senderPublicKeyB64) {
29
+ const sk = util.decodeBase64(recipientSecretKeyB64);
30
+ const pk = util.decodeBase64(senderPublicKeyB64);
31
+ const combined = util.decodeBase64(ciphertextB64);
32
+ const nonce = combined.slice(0, nacl.box.nonceLength);
33
+ const ct = combined.slice(nacl.box.nonceLength);
34
+ const pt = nacl.box.open(ct, nonce, pk, sk);
35
+ if (pt === null)
36
+ throw new Error("Decryption failed");
37
+ return util.encodeUTF8(pt);
38
+ }
39
+ /**
40
+ * Derive a symmetric wrapping key from an X25519 shared secret using HKDF-SHA256.
41
+ * Compatible with the frontend's deriveWrappingKey function.
42
+ */
43
+ export async function deriveWrappingKey(sharedSecretB64, context) {
44
+ const sharedSecret = util.decodeBase64(sharedSecretB64);
45
+ const keyMaterial = await crypto.subtle.importKey("raw", sharedSecret.buffer.slice(sharedSecret.byteOffset, sharedSecret.byteOffset + sharedSecret.byteLength), "HKDF", false, ["deriveBits"]);
46
+ const derivedBits = await crypto.subtle.deriveBits({
47
+ name: "HKDF",
48
+ hash: "SHA-256",
49
+ salt: new Uint8Array(32),
50
+ info: new TextEncoder().encode(context),
51
+ }, keyMaterial, 256);
52
+ return util.encodeBase64(new Uint8Array(derivedBits));
53
+ }
54
+ /** Encrypt content with AES-256-GCM and wrap the content key for a recipient via NaCl box. */
55
+ export function encryptContent(plaintext, recipientPublicKeyB64, recipientKeyId, senderSecretKeyB64, scope = "space") {
56
+ // Generate random 32-byte content key
57
+ const contentKey = nacl.randomBytes(32);
58
+ // Encrypt content with the content key using XSalsa20-Poly1305 (NaCl secretbox)
59
+ const contentNonce = nacl.randomBytes(nacl.secretbox.nonceLength);
60
+ const contentBytes = util.decodeUTF8(plaintext);
61
+ const encrypted = nacl.secretbox(contentBytes, contentNonce, contentKey);
62
+ // Combine nonce + ciphertext for the content
63
+ const combined = new Uint8Array(contentNonce.length + encrypted.length);
64
+ combined.set(contentNonce);
65
+ combined.set(encrypted, contentNonce.length);
66
+ const ciphertext = util.encodeBase64(combined);
67
+ // Wrap content key for the recipient using NaCl box
68
+ const wrapNonce = nacl.randomBytes(nacl.box.nonceLength);
69
+ const sk = util.decodeBase64(senderSecretKeyB64);
70
+ const pk = util.decodeBase64(recipientPublicKeyB64);
71
+ const wrappedKey = nacl.box(contentKey, wrapNonce, pk, sk);
72
+ if (wrappedKey === null)
73
+ throw new Error("Failed to wrap content key");
74
+ return {
75
+ ciphertext,
76
+ wrappings: [{
77
+ scope,
78
+ recipientKeyId,
79
+ encryptedSymmetricKey: util.encodeBase64(wrappedKey),
80
+ nonce: util.encodeBase64(wrapNonce),
81
+ }],
82
+ };
83
+ }
84
+ /** Decrypt wrapped content using the sender's public key and recipient's secret key. */
85
+ export function decryptContent(wrapped, recipientKeyId, recipientSecretKeyB64, senderPublicKeyB64) {
86
+ const wrapping = wrapped.wrappings.find((w) => w.recipientKeyId === recipientKeyId);
87
+ if (wrapping === undefined) {
88
+ throw new Error("No matching wrapping found for the provided key ID");
89
+ }
90
+ // Unwrap content key
91
+ const sk = util.decodeBase64(recipientSecretKeyB64);
92
+ const pk = util.decodeBase64(senderPublicKeyB64);
93
+ const wrapNonce = util.decodeBase64(wrapping.nonce);
94
+ const wrappedKey = util.decodeBase64(wrapping.encryptedSymmetricKey);
95
+ const contentKey = nacl.box.open(wrappedKey, wrapNonce, pk, sk);
96
+ if (contentKey === null)
97
+ throw new Error("Failed to unwrap content key");
98
+ // Decrypt content
99
+ const combined = util.decodeBase64(wrapped.ciphertext);
100
+ const contentNonce = combined.slice(0, nacl.secretbox.nonceLength);
101
+ const ct = combined.slice(nacl.secretbox.nonceLength);
102
+ const plaintext = nacl.secretbox.open(ct, contentNonce, contentKey);
103
+ if (plaintext === null)
104
+ throw new Error("Decryption failed");
105
+ return util.encodeUTF8(plaintext);
106
+ }
107
+ /** Manages encryption/decryption context for SDK operations. */
108
+ export class CryptoContext {
109
+ constructor(secretKeyB64, publicKeyB64, recipientPublicKeyB64, recipientKeyId, serverKeyId) {
110
+ this.secretKeyB64 = secretKeyB64;
111
+ this.publicKeyB64 = publicKeyB64;
112
+ this.recipientPublicKeyB64 = recipientPublicKeyB64;
113
+ this.recipientKeyId = recipientKeyId;
114
+ this.serverKeyId = serverKeyId;
115
+ }
116
+ /** Compute X25519 ECDH shared secret with the recipient (space) public key. */
117
+ getSharedSecret() {
118
+ const sk = util.decodeBase64(this.secretKeyB64);
119
+ const pk = util.decodeBase64(this.recipientPublicKeyB64);
120
+ return util.encodeBase64(nacl.scalarMult(sk, pk));
121
+ }
122
+ /** Get the agent's public key (base64). */
123
+ getPublicKey() {
124
+ return this.publicKeyB64;
125
+ }
126
+ /** Get the space key ID. */
127
+ getSpaceKeyId() {
128
+ return this.recipientKeyId;
129
+ }
130
+ encryptField(plaintext) {
131
+ return encryptContent(plaintext, this.recipientPublicKeyB64, this.recipientKeyId, this.secretKeyB64);
132
+ }
133
+ decryptField(wrapped, senderPublicKeyB64) {
134
+ return decryptContent(wrapped, this.recipientKeyId, this.secretKeyB64, senderPublicKeyB64);
135
+ }
136
+ /** Encrypt a plaintext field, returning the ciphertext and wrappings separately. */
137
+ encryptForApi(plaintext) {
138
+ const wrapped = this.encryptField(plaintext);
139
+ return { ciphertext: wrapped.ciphertext, wrappings: wrapped.wrappings };
140
+ }
141
+ /**
142
+ * Decrypt content encrypted with encryptWithWrapping (ECDH + HKDF + AES-GCM).
143
+ * Finds the wrapping matching this context's space key, unwraps the content key,
144
+ * then decrypts the ciphertext. Returns null on any failure.
145
+ */
146
+ async decryptWrappedContent(ciphertext, wrappings) {
147
+ if (!wrappings?.length)
148
+ return null;
149
+ try {
150
+ const wrapping = wrappings.find((w) => w.recipientKeyId === this.recipientKeyId);
151
+ if (!wrapping?.wrappedContentKey)
152
+ return null;
153
+ const sharedSecret = this.getSharedSecret();
154
+ const wrappingKey = await deriveWrappingKey(sharedSecret, "space");
155
+ const contentKey = await decryptAes(wrapping.wrappedContentKey, wrappingKey);
156
+ return await decryptAes(ciphertext, contentKey);
157
+ }
158
+ catch {
159
+ return null;
160
+ }
161
+ }
162
+ /**
163
+ * Derive the session message key for encrypting/decrypting conv session messages.
164
+ * Session messages use the format `{agentPubBase64}:{AES-GCM ciphertext}`.
165
+ */
166
+ async getSessionMessageKey() {
167
+ const sharedSecret = this.getSharedSecret();
168
+ return deriveWrappingKey(sharedSecret, "session-message");
169
+ }
170
+ /**
171
+ * Encrypt a conv session message: `{agentPubBase64}:{AES-256-GCM ciphertext}`.
172
+ */
173
+ async encryptSessionMessage(content) {
174
+ const key = await this.getSessionMessageKey();
175
+ const ciphertext = await encryptAes(content, key);
176
+ return `${this.publicKeyB64}:${ciphertext}`;
177
+ }
178
+ /**
179
+ * Decrypt a conv session message. Handles both `{pubKey}:{ciphertext}` format
180
+ * and raw AES-GCM ciphertext. Returns null on failure.
181
+ */
182
+ async decryptSessionMessage(encryptedContent) {
183
+ const key = await this.getSessionMessageKey();
184
+ const colonIdx = encryptedContent.indexOf(":");
185
+ if (colonIdx <= 0) {
186
+ try {
187
+ return await decryptAes(encryptedContent, key);
188
+ }
189
+ catch {
190
+ return null;
191
+ }
192
+ }
193
+ const prefix = encryptedContent.slice(0, colonIdx);
194
+ const ciphertext = encryptedContent.slice(colonIdx + 1);
195
+ // Base64 public keys are 44 chars and don't contain hyphens
196
+ if (prefix.length === 44 && !prefix.includes("-")) {
197
+ try {
198
+ return await decryptAes(ciphertext, key);
199
+ }
200
+ catch {
201
+ return null;
202
+ }
203
+ }
204
+ return null;
205
+ }
206
+ /**
207
+ * Encrypt content using the content wrapping scheme (ECDH + HKDF + AES-GCM).
208
+ * Compatible with the frontend's decryptContent function.
209
+ *
210
+ * This generates a random content key, encrypts the plaintext with AES-256-GCM,
211
+ * then wraps (encrypts) the content key using a wrapping key derived from
212
+ * ECDH(agentSecretKey, spacePublicKey) + HKDF.
213
+ *
214
+ * @param plaintext - Text to encrypt
215
+ * @param spaceKeyId - ID of the space public key (used as recipientKeyId in wrapping)
216
+ */
217
+ async encryptWithWrapping(plaintext, spaceKeyId) {
218
+ if (this.recipientPublicKeyB64 === undefined) {
219
+ return { ciphertext: plaintext, wrappings: [] };
220
+ }
221
+ const keyId = spaceKeyId ?? this.recipientKeyId;
222
+ // 1. Compute raw X25519 shared secret
223
+ const sk = util.decodeBase64(this.secretKeyB64);
224
+ const pk = util.decodeBase64(this.recipientPublicKeyB64);
225
+ const rawSharedSecret = nacl.scalarMult(sk, pk);
226
+ const sharedSecretB64 = util.encodeBase64(rawSharedSecret);
227
+ // 2. Derive wrapping key via HKDF-SHA256 (same as frontend)
228
+ const wrappingKey = await deriveWrappingKey(sharedSecretB64, "space");
229
+ // 3. Generate random content key
230
+ const contentKeyBytes = crypto.getRandomValues(new Uint8Array(32));
231
+ const contentKeyB64 = util.encodeBase64(contentKeyBytes);
232
+ // 4. Encrypt plaintext with AES-256-GCM using content key
233
+ const ciphertext = await encryptAes(plaintext, contentKeyB64);
234
+ // 5. Wrap (encrypt) content key with AES-256-GCM using wrapping key
235
+ const wrappedContentKey = await encryptAes(contentKeyB64, wrappingKey);
236
+ return {
237
+ ciphertext,
238
+ wrappings: [{ scope: "space", recipientKeyId: keyId, wrappedContentKey }],
239
+ };
240
+ }
241
+ }
242
+ // -- AES-256-GCM utilities (for conv session messages) ----------------------
243
+ /**
244
+ * Encrypt plaintext using AES-256-GCM.
245
+ * Returns base64(12-byte nonce || ciphertext || 16-byte auth tag).
246
+ * Compatible with the Hiloop frontend's session message encryption.
247
+ *
248
+ * @param plaintext - The text to encrypt
249
+ * @param keyBase64 - Base64-encoded 32-byte AES-256 key
250
+ */
251
+ export async function encryptAes(plaintext, keyBase64) {
252
+ const keyBytes = util.decodeBase64(keyBase64);
253
+ const key = await crypto.subtle.importKey("raw", keyBytes.buffer.slice(keyBytes.byteOffset, keyBytes.byteOffset + keyBytes.byteLength), "AES-GCM", false, ["encrypt"]);
254
+ const nonce = crypto.getRandomValues(new Uint8Array(12));
255
+ const encoded = new TextEncoder().encode(plaintext);
256
+ const ct = await crypto.subtle.encrypt({ name: "AES-GCM", iv: nonce, tagLength: 128 }, key, encoded);
257
+ const buf = new Uint8Array(12 + ct.byteLength);
258
+ buf.set(nonce);
259
+ buf.set(new Uint8Array(ct), 12);
260
+ return util.encodeBase64(buf);
261
+ }
262
+ /**
263
+ * Decrypt AES-256-GCM ciphertext.
264
+ * Expects base64(12-byte nonce || ciphertext || 16-byte auth tag).
265
+ *
266
+ * @param ciphertextBase64 - Base64-encoded ciphertext
267
+ * @param keyBase64 - Base64-encoded 32-byte AES-256 key
268
+ */
269
+ export async function decryptAes(ciphertextBase64, keyBase64) {
270
+ const keyBytes = util.decodeBase64(keyBase64);
271
+ const key = await crypto.subtle.importKey("raw", keyBytes.buffer.slice(keyBytes.byteOffset, keyBytes.byteOffset + keyBytes.byteLength), "AES-GCM", false, ["decrypt"]);
272
+ const buf = util.decodeBase64(ciphertextBase64);
273
+ const nonce = buf.slice(0, 12);
274
+ const ct = buf.slice(12);
275
+ const ctBuf = ct.buffer.slice(ct.byteOffset, ct.byteOffset + ct.byteLength);
276
+ const pt = await crypto.subtle.decrypt({ name: "AES-GCM", iv: nonce, tagLength: 128 }, key, ctBuf);
277
+ return new TextDecoder().decode(pt);
278
+ }
@@ -0,0 +1,6 @@
1
+ export { HiloopClient, HiloopError } from "./client.js";
2
+ export type { HiloopClientOptions } from "./client.js";
3
+ export { generateKeyPair, encrypt, decrypt, encryptAes, decryptAes, deriveWrappingKey, CryptoContext } from "./crypto.js";
4
+ export type { KeyPair, ContentWrappingResult } from "./crypto.js";
5
+ export type { Interaction, InteractionType, InteractionStatus, Priority, Message, PaginatedResult, CreateInteractionOptions, ConvSession, ConvSessionType, ConvSessionStatus, ConvSessionRole, ConvSessionParticipant, ConvSessionMessage, GuestToken, CreateConvSessionOptions, Channel, ChannelStatus, ChannelMessage, ChannelParticipant, CreateChannelOptions, FileChangeStatus, CommandInvocationStatus, AgentCommand, CommandInvocation, } from "./types.js";
6
+ export { parseInteraction, parseMessage, parseConvSession, parseConvSessionMessage, parseGuestToken, parseChannel, parseChannelMessage, parseChannelParticipant, } from "./types.js";
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { HiloopClient, HiloopError } from "./client.js";
2
+ export { generateKeyPair, encrypt, decrypt, encryptAes, decryptAes, deriveWrappingKey, CryptoContext } from "./crypto.js";
3
+ export { parseInteraction, parseMessage, parseConvSession, parseConvSessionMessage, parseGuestToken, parseChannel, parseChannelMessage, parseChannelParticipant, } from "./types.js";
@@ -0,0 +1,204 @@
1
+ /** Core types for the Hiloop SDK. */
2
+ export type InteractionType = "approval" | "review" | "payment" | "form" | "notification" | "report" | "question" | "activity";
3
+ export type InteractionStatus = "created" | "pending" | "viewed" | "responded" | "completed" | "expired" | "escalated" | "cancelled";
4
+ export type Priority = "critical" | "high" | "normal" | "low";
5
+ export interface Interaction {
6
+ id: string;
7
+ type: InteractionType;
8
+ status: InteractionStatus;
9
+ priority: Priority;
10
+ title: string;
11
+ description?: string;
12
+ options?: string;
13
+ context?: string;
14
+ formSchema?: string;
15
+ response?: string;
16
+ comment?: string;
17
+ routeToUser?: string;
18
+ routeToTeam?: string;
19
+ deadlineAt?: string;
20
+ createdAt: string;
21
+ updatedAt: string;
22
+ assignedAt?: string;
23
+ viewedAt?: string;
24
+ respondedAt?: string;
25
+ completedAt?: string;
26
+ raw: Record<string, unknown>;
27
+ }
28
+ export interface Message {
29
+ id: string;
30
+ senderType: string;
31
+ content: string;
32
+ createdAt: string;
33
+ raw: Record<string, unknown>;
34
+ }
35
+ export interface PaginatedResult<T> {
36
+ items: T[];
37
+ total: number;
38
+ page: number;
39
+ pageSize: number;
40
+ }
41
+ export interface CreateInteractionOptions {
42
+ type: string;
43
+ title: string;
44
+ description?: string;
45
+ options?: string;
46
+ context?: string;
47
+ formSchema?: string;
48
+ priority?: string;
49
+ presentation?: string;
50
+ routeToUser?: string;
51
+ routeToTeam?: string;
52
+ deadlineMinutes?: number;
53
+ callbackUrl?: string;
54
+ convSessionId?: string;
55
+ }
56
+ export type ConvSessionType = "direct" | "group" | "public";
57
+ export type ConvSessionStatus = "open" | "closed" | "archived";
58
+ export type ConvSessionRole = "owner" | "admin" | "member" | "viewer" | "guest";
59
+ export interface ConvSession {
60
+ id: string;
61
+ sessionType: ConvSessionType;
62
+ status: ConvSessionStatus;
63
+ isPublic: boolean;
64
+ /** Encrypted title (base64). Use decryptAes to decrypt. */
65
+ encryptedTitle: string | null;
66
+ agentId: string | null;
67
+ createdByUserId: string;
68
+ participantCount?: number;
69
+ createdAt: string;
70
+ updatedAt: string;
71
+ raw: Record<string, unknown>;
72
+ }
73
+ export interface ConvSessionParticipant {
74
+ id: string;
75
+ sessionId: string;
76
+ userId: string;
77
+ role: ConvSessionRole;
78
+ addedAt: string;
79
+ raw: Record<string, unknown>;
80
+ }
81
+ export interface ConvSessionMessage {
82
+ id: string;
83
+ sessionId: string;
84
+ senderType: "agent" | "user" | "guest";
85
+ senderAgentId: string | null;
86
+ senderUserId: string | null;
87
+ /** Encrypted content (base64). */
88
+ encryptedContent: string;
89
+ /** Decrypted content (populated when decryption succeeds). */
90
+ content?: string;
91
+ editedAt: string | null;
92
+ deletedAt: string | null;
93
+ createdAt: string;
94
+ raw: Record<string, unknown>;
95
+ }
96
+ export interface GuestToken {
97
+ id: string;
98
+ sessionId: string;
99
+ token: string;
100
+ displayName: string | null;
101
+ expiresAt: string | null;
102
+ createdAt: string;
103
+ }
104
+ export interface CreateConvSessionOptions {
105
+ sessionType?: ConvSessionType;
106
+ isPublic?: boolean;
107
+ publicMode?: "private" | "shared";
108
+ /** Plaintext title -- auto-encrypted via content wrapping when crypto is configured. */
109
+ title?: string;
110
+ /** Space key ID for content wrapping. Auto-fetched via getEncryptionInfo() if not provided. */
111
+ spaceKeyId?: string;
112
+ /** @deprecated Pre-encrypted title (base64). Use `title` instead for automatic content wrapping. */
113
+ encryptedTitle?: string;
114
+ /** @deprecated Content wrappings for pre-encrypted title. Use `title` instead. */
115
+ titleContentWrappings?: Array<{
116
+ scope: string;
117
+ recipientKeyId: string;
118
+ wrappedContentKey: string;
119
+ }>;
120
+ maxGuests?: number;
121
+ participantIds?: string[];
122
+ }
123
+ export declare function parseConvSession(data: Record<string, unknown>): ConvSession;
124
+ export declare function parseConvSessionMessage(data: Record<string, unknown>): ConvSessionMessage;
125
+ export declare function parseGuestToken(data: Record<string, unknown>): GuestToken;
126
+ export type ChannelStatus = "open" | "closed";
127
+ export interface Channel {
128
+ id: string;
129
+ spaceId: string;
130
+ externalId: string | null;
131
+ encryptedName: string | null;
132
+ encryptedDescription: string | null;
133
+ status: ChannelStatus;
134
+ createdByAgentId: string;
135
+ lastMessageAt: string | null;
136
+ closedAt: string | null;
137
+ createdAt: string;
138
+ updatedAt: string;
139
+ raw: Record<string, unknown>;
140
+ }
141
+ export interface ChannelMessage {
142
+ id: string;
143
+ channelId: string;
144
+ senderAgentId: string;
145
+ encryptedContent: string;
146
+ /** Decrypted content (populated when decryption succeeds). */
147
+ content?: string;
148
+ createdAt: string;
149
+ raw: Record<string, unknown>;
150
+ }
151
+ export interface ChannelParticipant {
152
+ id: string;
153
+ channelId: string;
154
+ agentId: string;
155
+ joinedAt: string;
156
+ leftAt: string | null;
157
+ raw: Record<string, unknown>;
158
+ }
159
+ export interface CreateChannelOptions {
160
+ name?: string;
161
+ description?: string;
162
+ externalId?: string;
163
+ participantAgentIds?: string[];
164
+ }
165
+ export declare function parseChannel(data: Record<string, unknown>): Channel;
166
+ export declare function parseChannelMessage(data: Record<string, unknown>): ChannelMessage;
167
+ export declare function parseChannelParticipant(data: Record<string, unknown>): ChannelParticipant;
168
+ type DecryptFn = (text: string) => string;
169
+ export declare function parseInteraction(data: Record<string, unknown>, decrypt?: DecryptFn): Interaction;
170
+ export declare function parseMessage(data: Record<string, unknown>, decrypt?: DecryptFn): Message;
171
+ export type FileChangeStatus = "modified" | "added" | "deleted" | "renamed";
172
+ export type CommandInvocationStatus = "pending" | "running" | "completed" | "failed" | "cancelled";
173
+ export interface AgentCommand {
174
+ id: string;
175
+ name: string;
176
+ encryptedDescription: string | null;
177
+ encryptedArgumentHint: string | null;
178
+ encryptedParameters: string | null;
179
+ annotations: {
180
+ destructive?: boolean;
181
+ longRunning?: boolean;
182
+ } | null;
183
+ agentId: string;
184
+ agentName?: string;
185
+ agentAvatarUrl?: string | null;
186
+ createdAt: string;
187
+ updatedAt: string;
188
+ }
189
+ export interface CommandInvocation {
190
+ id: string;
191
+ commandName: string;
192
+ agentId: string;
193
+ spaceId: string;
194
+ convSessionId: string;
195
+ invokedBy: string;
196
+ status: CommandInvocationStatus;
197
+ encryptedArguments: string | null;
198
+ encryptedResult: string | null;
199
+ createdAt: string;
200
+ ackedAt: string | null;
201
+ completedAt: string | null;
202
+ updatedAt: string;
203
+ }
204
+ export {};