toledgram-bot-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.
Files changed (68) hide show
  1. package/dist/bot.d.ts +66 -0
  2. package/dist/bot.d.ts.map +1 -0
  3. package/dist/bot.js +282 -0
  4. package/dist/bot.js.map +1 -0
  5. package/dist/client/convex.d.ts +35 -0
  6. package/dist/client/convex.d.ts.map +1 -0
  7. package/dist/client/convex.js +96 -0
  8. package/dist/client/convex.js.map +1 -0
  9. package/dist/client/sender.d.ts +50 -0
  10. package/dist/client/sender.d.ts.map +1 -0
  11. package/dist/client/sender.js +161 -0
  12. package/dist/client/sender.js.map +1 -0
  13. package/dist/client/sync.d.ts +31 -0
  14. package/dist/client/sync.d.ts.map +1 -0
  15. package/dist/client/sync.js +175 -0
  16. package/dist/client/sync.js.map +1 -0
  17. package/dist/crypto/aes.d.ts +27 -0
  18. package/dist/crypto/aes.d.ts.map +1 -0
  19. package/dist/crypto/aes.js +54 -0
  20. package/dist/crypto/aes.js.map +1 -0
  21. package/dist/crypto/bip39.d.ts +27 -0
  22. package/dist/crypto/bip39.d.ts.map +1 -0
  23. package/dist/crypto/bip39.js +126 -0
  24. package/dist/crypto/bip39.js.map +1 -0
  25. package/dist/crypto/ecies.d.ts +32 -0
  26. package/dist/crypto/ecies.d.ts.map +1 -0
  27. package/dist/crypto/ecies.js +100 -0
  28. package/dist/crypto/ecies.js.map +1 -0
  29. package/dist/crypto/envelope.d.ts +21 -0
  30. package/dist/crypto/envelope.d.ts.map +1 -0
  31. package/dist/crypto/envelope.js +70 -0
  32. package/dist/crypto/envelope.js.map +1 -0
  33. package/dist/crypto/p256.d.ts +32 -0
  34. package/dist/crypto/p256.d.ts.map +1 -0
  35. package/dist/crypto/p256.js +54 -0
  36. package/dist/crypto/p256.js.map +1 -0
  37. package/dist/crypto/wordlist.d.ts +3 -0
  38. package/dist/crypto/wordlist.d.ts.map +1 -0
  39. package/dist/crypto/wordlist.js +260 -0
  40. package/dist/crypto/wordlist.js.map +1 -0
  41. package/dist/index.d.ts +9 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +9 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/storage/conversations.d.ts +20 -0
  46. package/dist/storage/conversations.d.ts.map +1 -0
  47. package/dist/storage/conversations.js +31 -0
  48. package/dist/storage/conversations.js.map +1 -0
  49. package/dist/storage/database.d.ts +13 -0
  50. package/dist/storage/database.d.ts.map +1 -0
  51. package/dist/storage/database.js +85 -0
  52. package/dist/storage/database.js.map +1 -0
  53. package/dist/storage/files.d.ts +21 -0
  54. package/dist/storage/files.d.ts.map +1 -0
  55. package/dist/storage/files.js +74 -0
  56. package/dist/storage/files.js.map +1 -0
  57. package/dist/storage/messages.d.ts +39 -0
  58. package/dist/storage/messages.d.ts.map +1 -0
  59. package/dist/storage/messages.js +71 -0
  60. package/dist/storage/messages.js.map +1 -0
  61. package/dist/types.d.ts +104 -0
  62. package/dist/types.d.ts.map +1 -0
  63. package/dist/types.js +3 -0
  64. package/dist/types.js.map +1 -0
  65. package/examples/ai-bot.ts +78 -0
  66. package/examples/echo-bot.ts +39 -0
  67. package/examples/image-bot.ts +76 -0
  68. package/package.json +54 -0
package/dist/bot.d.ts ADDED
@@ -0,0 +1,66 @@
1
+ /**
2
+ * ToledgramBot — main entry point for bot developers
3
+ *
4
+ * Usage:
5
+ * const bot = new ToledgramBot({ mnemonic, backendUrl, dataDir })
6
+ * bot.on('message', async (msg) => { await msg.reply('Hello!') })
7
+ * await bot.start()
8
+ */
9
+ import { type LocalMessage } from "./storage/messages.js";
10
+ import type { BotConfig, MessageHandler, FileHandler, ErrorHandler, ContentType, Conversation } from "./types.js";
11
+ export declare class ToledgramBot {
12
+ private config;
13
+ private connection;
14
+ private db;
15
+ private messageStore;
16
+ private conversationStore;
17
+ private fileStore;
18
+ private syncService;
19
+ private sender;
20
+ private privateKey;
21
+ private publicKeyBase64;
22
+ private messageHandler;
23
+ private fileHandler;
24
+ private errorHandler;
25
+ private activeConversations;
26
+ private conversationPollInterval;
27
+ private startedAt;
28
+ constructor(config: BotConfig);
29
+ /** Register an event handler */
30
+ on(event: "message", handler: MessageHandler): void;
31
+ on(event: "file", handler: FileHandler): void;
32
+ on(event: "error", handler: ErrorHandler): void;
33
+ /** Start the bot — authenticate and begin syncing */
34
+ start(): Promise<void>;
35
+ /** Stop the bot */
36
+ stop(): Promise<void>;
37
+ /** The bot's persona ID (available after start) */
38
+ get personaId(): string;
39
+ /** The bot's username (available after start) */
40
+ get username(): string;
41
+ /** Get messages from local DB (already decrypted) */
42
+ getMessages(conversationId: string, opts?: {
43
+ limit?: number;
44
+ }): LocalMessage[];
45
+ /** Send a text message */
46
+ sendText(conversationId: string, text: string): Promise<void>;
47
+ /** Send a file from disk */
48
+ sendFile(conversationId: string, filePath: string, opts?: {
49
+ type?: ContentType;
50
+ filename?: string;
51
+ }): Promise<void>;
52
+ /** Send in-memory data as a file (no disk write needed) */
53
+ sendBuffer(conversationId: string, data: Uint8Array, opts: {
54
+ type?: ContentType;
55
+ filename: string;
56
+ mimeType?: string;
57
+ }): Promise<void>;
58
+ /** Get the list of conversations */
59
+ getConversations(): Promise<Conversation[]>;
60
+ private discoverAndSync;
61
+ private handleNewMessage;
62
+ private localToMessage;
63
+ private downloadMessageFile;
64
+ private getRecipientPublicKey;
65
+ }
66
+ //# sourceMappingURL=bot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAOxE,OAAO,KAAK,EACV,SAAS,EAET,cAAc,EACd,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EAEb,MAAM,YAAY,CAAC;AAGpB,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,eAAe,CAAS;IAGhC,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,YAAY,CAA6B;IAGjD,OAAO,CAAC,mBAAmB,CAA0B;IACrD,OAAO,CAAC,wBAAwB,CACzB;IACP,OAAO,CAAC,SAAS,CAAa;gBAElB,MAAM,EAAE,SAAS;IAc7B,gCAAgC;IAChC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI;IACnD,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI;IAC7C,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAe/C,qDAAqD;IAC/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoD5B,mBAAmB;IACb,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,mDAAmD;IACnD,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,iDAAiD;IACjD,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,qDAAqD;IACrD,WAAW,CACT,cAAc,EAAE,MAAM,EACtB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GACxB,YAAY,EAAE;IAIjB,0BAA0B;IACpB,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnE,4BAA4B;IACtB,QAAQ,CACZ,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/C,OAAO,CAAC,IAAI,CAAC;IAShB,2DAA2D;IACrD,UAAU,CACd,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,WAAW,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAChE,OAAO,CAAC,IAAI,CAAC;IAShB,oCAAoC;IAC9B,gBAAgB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YA6BnC,eAAe;IAsB7B,OAAO,CAAC,gBAAgB;IAuBxB,OAAO,CAAC,cAAc;YAkCR,mBAAmB;YAiDnB,qBAAqB;CA4BpC"}
package/dist/bot.js ADDED
@@ -0,0 +1,282 @@
1
+ /**
2
+ * ToledgramBot — main entry point for bot developers
3
+ *
4
+ * Usage:
5
+ * const bot = new ToledgramBot({ mnemonic, backendUrl, dataDir })
6
+ * bot.on('message', async (msg) => { await msg.reply('Hello!') })
7
+ * await bot.start()
8
+ */
9
+ import { ConvexConnection } from "./client/convex.js";
10
+ import { SyncService } from "./client/sync.js";
11
+ import { MessageSender } from "./client/sender.js";
12
+ import { LocalDatabase } from "./storage/database.js";
13
+ import { MessageStore } from "./storage/messages.js";
14
+ import { ConversationStore } from "./storage/conversations.js";
15
+ import { FileStore } from "./storage/files.js";
16
+ import { mnemonicToPrivateKey } from "./crypto/bip39.js";
17
+ import { derivePublicKey } from "./crypto/p256.js";
18
+ export class ToledgramBot {
19
+ config;
20
+ connection;
21
+ db;
22
+ messageStore;
23
+ conversationStore;
24
+ fileStore;
25
+ syncService = null;
26
+ sender = null;
27
+ privateKey;
28
+ publicKeyBase64;
29
+ // Event handlers
30
+ messageHandler = null;
31
+ fileHandler = null;
32
+ errorHandler = null;
33
+ // Active conversation tracking
34
+ activeConversations = new Set();
35
+ conversationPollInterval = null;
36
+ startedAt = 0;
37
+ constructor(config) {
38
+ this.config = config;
39
+ this.connection = new ConvexConnection(config.backendUrl);
40
+ this.db = new LocalDatabase(config.dataDir);
41
+ this.messageStore = new MessageStore(this.db.raw);
42
+ this.conversationStore = new ConversationStore(this.db.raw);
43
+ this.fileStore = new FileStore(this.db.raw, config.dataDir);
44
+ // Derive keys from mnemonic
45
+ this.privateKey = mnemonicToPrivateKey(config.mnemonic);
46
+ const publicKey = derivePublicKey(this.privateKey);
47
+ this.publicKeyBase64 = Buffer.from(publicKey).toString("base64");
48
+ }
49
+ on(event, handler) {
50
+ switch (event) {
51
+ case "message":
52
+ this.messageHandler = handler;
53
+ break;
54
+ case "file":
55
+ this.fileHandler = handler;
56
+ break;
57
+ case "error":
58
+ this.errorHandler = handler;
59
+ break;
60
+ }
61
+ }
62
+ /** Start the bot — authenticate and begin syncing */
63
+ async start() {
64
+ console.log("[Bot] Starting...");
65
+ this.startedAt = Date.now();
66
+ // 1. Authenticate
67
+ const auth = await this.connection.authenticate(this.config.mnemonic, this.config.username);
68
+ console.log(`[Bot] Authenticated as @${auth.username} (${auth.personaId})`);
69
+ // 2. Initialize sender
70
+ this.sender = new MessageSender(this.connection.httpClient, this.privateKey, auth.personaId, this.publicKeyBase64, auth.token, auth.username);
71
+ // 3. Initialize sync service
72
+ this.syncService = new SyncService(this.connection.httpClient, this.privateKey, auth.personaId, auth.token, this.messageStore, this.conversationStore);
73
+ // Wire up new message callback
74
+ this.syncService.onMessage((localMsg) => {
75
+ this.handleNewMessage(localMsg);
76
+ });
77
+ // 4. Discover conversations and start syncing
78
+ await this.discoverAndSync();
79
+ // 5. Poll for new conversations periodically
80
+ this.conversationPollInterval = setInterval(async () => {
81
+ try {
82
+ await this.discoverAndSync();
83
+ }
84
+ catch (e) {
85
+ this.errorHandler?.(e instanceof Error ? e : new Error(String(e)));
86
+ }
87
+ }, 10000);
88
+ console.log("[Bot] Ready and listening for messages");
89
+ }
90
+ /** Stop the bot */
91
+ async stop() {
92
+ console.log("[Bot] Stopping...");
93
+ if (this.conversationPollInterval) {
94
+ clearInterval(this.conversationPollInterval);
95
+ }
96
+ this.syncService?.stopAll();
97
+ this.connection.close();
98
+ this.db.close();
99
+ console.log("[Bot] Stopped");
100
+ }
101
+ // ==================== Public API ====================
102
+ /** The bot's persona ID (available after start) */
103
+ get personaId() {
104
+ return this.connection.personaId;
105
+ }
106
+ /** The bot's username (available after start) */
107
+ get username() {
108
+ return this.connection.username;
109
+ }
110
+ /** Get messages from local DB (already decrypted) */
111
+ getMessages(conversationId, opts) {
112
+ return this.messageStore.list(conversationId, opts?.limit ?? 50);
113
+ }
114
+ /** Send a text message */
115
+ async sendText(conversationId, text) {
116
+ if (!this.sender)
117
+ throw new Error("Bot not started");
118
+ // Get recipient public key
119
+ const recipientPubKey = await this.getRecipientPublicKey(conversationId);
120
+ await this.sender.sendText(conversationId, text, recipientPubKey);
121
+ }
122
+ /** Send a file from disk */
123
+ async sendFile(conversationId, filePath, opts) {
124
+ if (!this.sender)
125
+ throw new Error("Bot not started");
126
+ const recipientPubKey = await this.getRecipientPublicKey(conversationId);
127
+ await this.sender.sendFile(conversationId, filePath, recipientPubKey, opts);
128
+ }
129
+ /** Send in-memory data as a file (no disk write needed) */
130
+ async sendBuffer(conversationId, data, opts) {
131
+ if (!this.sender)
132
+ throw new Error("Bot not started");
133
+ const recipientPubKey = await this.getRecipientPublicKey(conversationId);
134
+ await this.sender.sendBuffer(conversationId, data, recipientPubKey, opts);
135
+ }
136
+ /** Get the list of conversations */
137
+ async getConversations() {
138
+ const convos = (await this.connection.httpClient.query("conversations:list", {
139
+ token: this.connection.token,
140
+ personaId: this.connection.personaId,
141
+ }));
142
+ return convos.map((c) => ({
143
+ id: c.id,
144
+ type: c.type,
145
+ name: c.name,
146
+ members: (c.members ?? []).map((m) => ({
147
+ personaId: m.personaId,
148
+ username: m.username,
149
+ displayName: m.displayName,
150
+ publicKey: m.publicKey,
151
+ role: m.role,
152
+ isOnline: m.isOnline,
153
+ isBot: m.isBot ?? false,
154
+ })),
155
+ lastMessageAt: c.lastMessageAt,
156
+ reactionSalt: c.reactionSalt,
157
+ }));
158
+ }
159
+ // ==================== Internal ====================
160
+ async discoverAndSync() {
161
+ const conversations = await this.getConversations();
162
+ for (const convo of conversations) {
163
+ // Skip saved messages conversations — bots don't need them
164
+ if (convo.type === "saved")
165
+ continue;
166
+ if (!this.activeConversations.has(convo.id)) {
167
+ this.activeConversations.add(convo.id);
168
+ this.conversationStore.upsert({
169
+ id: convo.id,
170
+ type: convo.type,
171
+ name: convo.name ?? null,
172
+ lastMessageAt: convo.lastMessageAt ?? null,
173
+ reactionSalt: convo.reactionSalt ?? null,
174
+ metadata: JSON.stringify({ members: convo.members }),
175
+ });
176
+ this.syncService.startSync(convo.id);
177
+ }
178
+ }
179
+ }
180
+ handleNewMessage(localMsg) {
181
+ // Skip messages from before the bot started (avoids replaying old history)
182
+ if (localMsg.createdAt < this.startedAt)
183
+ return;
184
+ const msg = this.localToMessage(localMsg);
185
+ if (localMsg.contentType !== "text" && this.fileHandler) {
186
+ try {
187
+ this.fileHandler(msg);
188
+ }
189
+ catch (e) {
190
+ this.errorHandler?.(e instanceof Error ? e : new Error(String(e)));
191
+ }
192
+ }
193
+ if (this.messageHandler) {
194
+ try {
195
+ this.messageHandler(msg);
196
+ }
197
+ catch (e) {
198
+ this.errorHandler?.(e instanceof Error ? e : new Error(String(e)));
199
+ }
200
+ }
201
+ }
202
+ localToMessage(local) {
203
+ return {
204
+ id: local.id,
205
+ conversationId: local.conversationId,
206
+ senderPersonaId: local.senderPersonaId,
207
+ senderName: local.senderName ?? "Unknown",
208
+ senderDisplayName: local.senderDisplayName ?? undefined,
209
+ content: local.content ?? "",
210
+ contentType: local.contentType,
211
+ createdAt: local.createdAt,
212
+ replyToMessageId: local.replyToMessageId ?? undefined,
213
+ replyToPreview: local.replyToPreview ?? undefined,
214
+ keyMaterial: local.keyMaterial ? JSON.parse(local.keyMaterial) : undefined,
215
+ hasFile: !!local.encryptedFileStorageId,
216
+ encryptedFileStorageId: local.encryptedFileStorageId ?? undefined,
217
+ reply: async (text) => {
218
+ await this.sendText(local.conversationId, text);
219
+ },
220
+ replyWithFile: async (filePath, opts) => {
221
+ await this.sendFile(local.conversationId, filePath, opts);
222
+ },
223
+ replyWithBuffer: async (data, opts) => {
224
+ await this.sendBuffer(local.conversationId, data, opts);
225
+ },
226
+ downloadFile: async () => {
227
+ return this.downloadMessageFile(local);
228
+ },
229
+ };
230
+ }
231
+ async downloadMessageFile(local) {
232
+ // Check cache first
233
+ const cached = this.fileStore.getCachedPath(local.id);
234
+ if (cached)
235
+ return cached;
236
+ if (!local.encryptedFileStorageId || !local.keyMaterial) {
237
+ throw new Error("Message has no file attachment");
238
+ }
239
+ // Parse key material (SDK uses "fileKey", iOS uses "key")
240
+ const km = JSON.parse(local.keyMaterial);
241
+ const fileKeyBase64 = (km.fileKey ?? km.key);
242
+ if (!fileKeyBase64) {
243
+ throw new Error("No file key in key material");
244
+ }
245
+ // iOS stores keyMaterial as key(32) + nonce(12) = 44 bytes
246
+ // The nonce is also embedded in the encrypted file (combined format)
247
+ // so we only need the first 32 bytes as the AES key
248
+ let fileKeyBytes = new Uint8Array(Buffer.from(fileKeyBase64, "base64"));
249
+ if (fileKeyBytes.length === 44) {
250
+ fileKeyBytes = fileKeyBytes.slice(0, 32);
251
+ }
252
+ // Download encrypted file from Convex storage
253
+ const url = await this.connection.httpClient.mutation("storage:getFileUrl", {
254
+ token: this.connection.token,
255
+ storageId: local.encryptedFileStorageId,
256
+ });
257
+ if (!url) {
258
+ throw new Error("File not found in storage");
259
+ }
260
+ const response = await fetch(url);
261
+ const encryptedData = new Uint8Array(await response.arrayBuffer());
262
+ return this.fileStore.saveDecryptedFile(local.id, encryptedData, fileKeyBytes, km.filename, km.mimeType);
263
+ }
264
+ async getRecipientPublicKey(conversationId) {
265
+ // Get conversation details with member public keys
266
+ const convo = (await this.connection.httpClient.query("conversations:get", {
267
+ token: this.connection.token,
268
+ personaId: this.connection.personaId,
269
+ conversationId,
270
+ }));
271
+ if (!convo) {
272
+ throw new Error("Conversation not found");
273
+ }
274
+ // Find the other member's public key (for direct messages)
275
+ const otherMember = convo.members.find((m) => m.personaId !== this.connection.personaId);
276
+ if (!otherMember?.publicKey) {
277
+ throw new Error("Recipient public key not found");
278
+ }
279
+ return otherMember.publicKey;
280
+ }
281
+ }
282
+ //# sourceMappingURL=bot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bot.js","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Convex client connection and authentication
3
+ * Handles login with mnemonic-derived public key
4
+ */
5
+ import { ConvexHttpClient } from "convex/browser";
6
+ export interface AuthResult {
7
+ token: string;
8
+ personaId: string;
9
+ userId: string;
10
+ username: string;
11
+ displayName?: string;
12
+ }
13
+ export declare class ConvexConnection {
14
+ readonly httpClient: ConvexHttpClient;
15
+ private _token;
16
+ private _personaId;
17
+ private _userId;
18
+ private _username;
19
+ private _publicKeyBase64;
20
+ constructor(backendUrl: string);
21
+ get token(): string;
22
+ get personaId(): string;
23
+ get userId(): string;
24
+ get username(): string;
25
+ get publicKeyBase64(): string;
26
+ get isAuthenticated(): boolean;
27
+ /**
28
+ * Authenticate with the backend using a mnemonic
29
+ * Derives public key from mnemonic, then logs in
30
+ */
31
+ authenticate(mnemonic: string, preferredUsername?: string): Promise<AuthResult>;
32
+ /** Close the connection */
33
+ close(): void;
34
+ }
35
+ //# sourceMappingURL=convex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convex.d.ts","sourceRoot":"","sources":["../../src/client/convex.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIlD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,gBAAgB;IAC3B,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,gBAAgB,CAAuB;gBAEnC,UAAU,EAAE,MAAM;IAI9B,IAAI,KAAK,IAAI,MAAM,CAGlB;IAED,IAAI,SAAS,IAAI,MAAM,CAGtB;IAED,IAAI,MAAM,IAAI,MAAM,CAGnB;IAED,IAAI,QAAQ,IAAI,MAAM,CAGrB;IAED,IAAI,eAAe,IAAI,MAAM,CAG5B;IAED,IAAI,eAAe,IAAI,OAAO,CAE7B;IAED;;;OAGG;IACG,YAAY,CAChB,QAAQ,EAAE,MAAM,EAChB,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,CAAC,UAAU,CAAC;IA4DtB,2BAA2B;IAC3B,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Convex client connection and authentication
3
+ * Handles login with mnemonic-derived public key
4
+ */
5
+ import { ConvexHttpClient } from "convex/browser";
6
+ import { mnemonicToPrivateKey } from "../crypto/bip39.js";
7
+ import { derivePublicKey } from "../crypto/p256.js";
8
+ export class ConvexConnection {
9
+ httpClient;
10
+ _token = null;
11
+ _personaId = null;
12
+ _userId = null;
13
+ _username = null;
14
+ _publicKeyBase64 = null;
15
+ constructor(backendUrl) {
16
+ this.httpClient = new ConvexHttpClient(backendUrl);
17
+ }
18
+ get token() {
19
+ if (!this._token)
20
+ throw new Error("Not authenticated");
21
+ return this._token;
22
+ }
23
+ get personaId() {
24
+ if (!this._personaId)
25
+ throw new Error("Not authenticated");
26
+ return this._personaId;
27
+ }
28
+ get userId() {
29
+ if (!this._userId)
30
+ throw new Error("Not authenticated");
31
+ return this._userId;
32
+ }
33
+ get username() {
34
+ if (!this._username)
35
+ throw new Error("Not authenticated");
36
+ return this._username;
37
+ }
38
+ get publicKeyBase64() {
39
+ if (!this._publicKeyBase64)
40
+ throw new Error("Not authenticated");
41
+ return this._publicKeyBase64;
42
+ }
43
+ get isAuthenticated() {
44
+ return this._token !== null;
45
+ }
46
+ /**
47
+ * Authenticate with the backend using a mnemonic
48
+ * Derives public key from mnemonic, then logs in
49
+ */
50
+ async authenticate(mnemonic, preferredUsername) {
51
+ // Derive keys from mnemonic
52
+ const privateKey = mnemonicToPrivateKey(mnemonic);
53
+ const publicKey = derivePublicKey(privateKey);
54
+ const publicKeyBase64 = Buffer.from(publicKey).toString("base64");
55
+ this._publicKeyBase64 = publicKeyBase64;
56
+ // Try login first
57
+ const loginResult = await this.httpClient.mutation("auth:loginWithPublicKey", {
58
+ publicKey: publicKeyBase64,
59
+ deviceId: `bot-${Date.now()}`,
60
+ });
61
+ if (loginResult) {
62
+ const result = loginResult;
63
+ this._token = result.token;
64
+ this._userId = result.userId;
65
+ // Find matching persona
66
+ const personas = result.personas;
67
+ let persona = preferredUsername
68
+ ? personas.find((p) => p.username === preferredUsername.toLowerCase())
69
+ : personas[0];
70
+ if (!persona) {
71
+ persona = personas[0];
72
+ }
73
+ this._personaId = persona._id;
74
+ this._username = persona.username;
75
+ // Always switch to ensure session has correct active persona
76
+ await this.httpClient.mutation("auth:switchPersona", {
77
+ token: this._token,
78
+ personaId: persona._id,
79
+ });
80
+ return {
81
+ token: this._token,
82
+ personaId: this._personaId,
83
+ userId: this._userId,
84
+ username: this._username,
85
+ displayName: persona.displayName,
86
+ };
87
+ }
88
+ throw new Error("Login failed — no account found for this mnemonic. " +
89
+ "Create the bot persona in the iOS app first, then use the same mnemonic here.");
90
+ }
91
+ /** Close the connection */
92
+ close() {
93
+ // ConvexHttpClient doesn't need explicit cleanup
94
+ }
95
+ }
96
+ //# sourceMappingURL=convex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convex.js","sourceRoot":"","sources":["../../src/client/convex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Message sender — encrypt and send to Convex
3
+ * Port of iOS MessageService.swift send flow
4
+ */
5
+ import type { ConvexHttpClient } from "convex/browser";
6
+ import type { ContentType } from "../types.js";
7
+ export declare class MessageSender {
8
+ private httpClient;
9
+ private privateKey;
10
+ private myPersonaId;
11
+ private myPublicKeyBase64;
12
+ private token;
13
+ private username;
14
+ constructor(httpClient: ConvexHttpClient, privateKey: Uint8Array, myPersonaId: string, myPublicKeyBase64: string, token: string, username: string);
15
+ /**
16
+ * Send a text message to a direct conversation
17
+ */
18
+ sendText(conversationId: string, text: string, recipientPublicKeyBase64: string, opts?: {
19
+ replyToMessageId?: string;
20
+ }): Promise<{
21
+ messageId: string;
22
+ createdAt: number;
23
+ }>;
24
+ /**
25
+ * Send a file/media message to a direct conversation
26
+ */
27
+ sendFile(conversationId: string, filePath: string, recipientPublicKeyBase64: string, opts?: {
28
+ type?: ContentType;
29
+ filename?: string;
30
+ replyToMessageId?: string;
31
+ }): Promise<{
32
+ messageId: string;
33
+ createdAt: number;
34
+ }>;
35
+ /**
36
+ * Send in-memory data as a file (no disk I/O needed)
37
+ */
38
+ sendBuffer(conversationId: string, data: Uint8Array, recipientPublicKeyBase64: string, opts: {
39
+ type?: ContentType;
40
+ filename: string;
41
+ mimeType?: string;
42
+ replyToMessageId?: string;
43
+ }): Promise<{
44
+ messageId: string;
45
+ createdAt: number;
46
+ }>;
47
+ /** Upload raw bytes to Convex storage, returns storage ID */
48
+ private uploadToStorage;
49
+ }
50
+ //# sourceMappingURL=sender.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sender.d.ts","sourceRoot":"","sources":["../../src/client/sender.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIvD,OAAO,KAAK,EAAE,WAAW,EAAgB,MAAM,aAAa,CAAC;AAI7D,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAS;gBAGvB,UAAU,EAAE,gBAAgB,EAC5B,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,MAAM,EACzB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM;IAUlB;;OAEG;IACG,QAAQ,CACZ,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,EACZ,wBAAwB,EAAE,MAAM,EAChC,IAAI,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,GACnC,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAiCpD;;OAEG;IACG,QAAQ,CACZ,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,EAChB,wBAAwB,EAAE,MAAM,EAChC,IAAI,CAAC,EAAE;QACL,IAAI,CAAC,EAAE,WAAW,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,GACA,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAuDpD;;OAEG;IACG,UAAU,CACd,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,UAAU,EAChB,wBAAwB,EAAE,MAAM,EAChC,IAAI,EAAE;QACJ,IAAI,CAAC,EAAE,WAAW,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,GACA,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAqDpD,6DAA6D;YAC/C,eAAe;CAqB9B"}