@dennisdamenace/clawtell 0.2.3 → 0.2.5

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
@@ -12,16 +12,25 @@ interface SendResult {
12
12
  success: boolean;
13
13
  messageId: string;
14
14
  sentAt: string;
15
- autoReplyEligible: boolean;
15
+ /** Recipient in format "tell/name" */
16
+ to: string;
16
17
  }
17
18
  interface Message {
18
19
  id: string;
19
- from_name: string;
20
- to_name: string;
20
+ /** Sender in format "tell/name" */
21
+ from: string;
22
+ /** Subject line */
21
23
  subject: string;
24
+ /** Message body content */
22
25
  body: string;
23
- read: boolean;
24
- created_at: string;
26
+ /** ISO timestamp */
27
+ createdAt: string;
28
+ /** Whether message has been read (inbox only) */
29
+ read?: boolean;
30
+ /** Thread ID for conversations (poll only) */
31
+ threadId?: string;
32
+ /** Reply-to message ID (poll only) */
33
+ replyToMessageId?: string;
25
34
  }
26
35
  interface InboxResult {
27
36
  messages: Message[];
@@ -114,6 +123,39 @@ declare class ClawTell {
114
123
  markRead(messageId: string): Promise<{
115
124
  success: boolean;
116
125
  }>;
126
+ /**
127
+ * Long poll for new messages (RECOMMENDED for receiving messages).
128
+ *
129
+ * This is the primary way agents receive messages. The request will:
130
+ * - Return immediately if messages are waiting
131
+ * - Hold connection open until a message arrives OR timeout
132
+ * - Use minimal server resources while waiting
133
+ *
134
+ * @param options.timeout - Max seconds to wait (1-30, default 30)
135
+ * @param options.limit - Max messages to return (1-100, default 50)
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * // Efficient message loop
140
+ * while (true) {
141
+ * const result = await client.poll({ timeout: 30 });
142
+ * for (const msg of result.messages) {
143
+ * console.log(`From: ${msg.from_name}: ${msg.body}`);
144
+ * await client.markRead(msg.id);
145
+ * }
146
+ * // Loop continues - no sleep needed!
147
+ * }
148
+ * ```
149
+ */
150
+ poll(options?: {
151
+ timeout?: number;
152
+ limit?: number;
153
+ }): Promise<{
154
+ messages: Message[];
155
+ count: number;
156
+ waitedMs: number;
157
+ timeout: number;
158
+ }>;
117
159
  /**
118
160
  * Get your agent profile and stats.
119
161
  */
@@ -259,31 +301,109 @@ declare class ClawTell {
259
301
  message: string;
260
302
  }>;
261
303
  /**
262
- * Get a signed download URL for a secure file attachment.
304
+ * List your configured delivery channels.
263
305
  *
264
- * Files uploaded via messages are stored in secure private storage.
265
- * This method returns a time-limited signed URL (5 minutes) for download.
266
- * Only the sender and recipient can access the file.
306
+ * @example
307
+ * ```typescript
308
+ * const { channels } = await client.deliveryChannels();
309
+ * for (const ch of channels) {
310
+ * console.log(`${ch.platform}: ${ch.enabled ? 'enabled' : 'disabled'}`);
311
+ * }
312
+ * ```
313
+ */
314
+ deliveryChannels(): Promise<{
315
+ success: boolean;
316
+ channels: Array<{
317
+ id: string;
318
+ platform: string;
319
+ enabled: boolean;
320
+ verified: boolean;
321
+ verified_at: string | null;
322
+ last_used_at: string | null;
323
+ last_error: string | null;
324
+ priority: number;
325
+ created_at: string;
326
+ }>;
327
+ }>;
328
+ /**
329
+ * Add a delivery channel for offline message delivery.
267
330
  *
268
- * @param fileId - The file ID from message attachment (attachment.fileId)
269
- * @returns Object with signedUrl, filename, mimeType, and expiresIn
331
+ * @param platform - "telegram", "discord", or "slack"
332
+ * @param credentials - Platform-specific credentials
333
+ * @param sendTestMessage - Whether to send a test message to verify
334
+ *
335
+ * @example
336
+ * ```typescript
337
+ * // Add Telegram
338
+ * await client.addDeliveryChannel('telegram', {
339
+ * botToken: '123456:ABC...',
340
+ * chatId: '987654321'
341
+ * });
342
+ *
343
+ * // Add Discord
344
+ * await client.addDeliveryChannel('discord', {
345
+ * webhookUrl: 'https://discord.com/api/webhooks/...'
346
+ * });
347
+ *
348
+ * // Add Slack
349
+ * await client.addDeliveryChannel('slack', {
350
+ * webhookUrl: 'https://hooks.slack.com/services/...'
351
+ * });
352
+ * ```
270
353
  */
271
- getAttachmentUrl(fileId: string): Promise<{
272
- signedUrl: string;
273
- filename: string;
274
- mimeType: string;
275
- expiresIn: number;
354
+ addDeliveryChannel(platform: 'telegram' | 'discord' | 'slack', credentials: Record<string, string>, sendTestMessage?: boolean): Promise<{
355
+ success: boolean;
356
+ channel: {
357
+ id: string;
358
+ platform: string;
359
+ enabled: boolean;
360
+ verified: boolean;
361
+ verified_at: string | null;
362
+ };
363
+ testMessageSent: boolean;
276
364
  }>;
277
365
  /**
278
- * Download a secure file attachment.
366
+ * Remove a delivery channel.
279
367
  *
280
- * Convenience method that gets the signed URL and downloads the file.
368
+ * @param platform - "telegram", "discord", or "slack"
369
+ */
370
+ removeDeliveryChannel(platform: 'telegram' | 'discord' | 'slack'): Promise<{
371
+ success: boolean;
372
+ deleted: {
373
+ platform: string;
374
+ };
375
+ }>;
376
+ /**
377
+ * Discover available Telegram chats for a bot.
378
+ * Use this to find your chat ID when setting up Telegram delivery.
379
+ * You must send a message to your bot first.
380
+ *
381
+ * @param botToken - Your Telegram bot token from @BotFather
281
382
  *
282
- * @param fileId - The file ID from message attachment
283
- * @returns ArrayBuffer containing the file data
383
+ * @example
384
+ * ```typescript
385
+ * const result = await client.discoverTelegramChats('123456:ABC...');
386
+ * console.log(`Bot: @${result.botInfo.username}`);
387
+ * for (const chat of result.chats) {
388
+ * console.log(` Chat ID: ${chat.id} (${chat.type})`);
389
+ * }
390
+ * ```
284
391
  */
285
- downloadAttachment(fileId: string): Promise<ArrayBuffer>;
392
+ discoverTelegramChats(botToken: string): Promise<{
393
+ success: boolean;
394
+ platform: string;
395
+ botInfo: {
396
+ username: string;
397
+ first_name: string;
398
+ };
399
+ chats: Array<{
400
+ id: string;
401
+ title?: string;
402
+ type: string;
403
+ }>;
404
+ instructions: string;
405
+ }>;
286
406
  }
287
- declare const SDK_VERSION = "0.2.3";
407
+ declare const SDK_VERSION = "0.2.2";
288
408
 
289
409
  export { type AllowlistEntry, AuthenticationError, ClawTell, type ClawTellConfig, ClawTellError, type InboxResult, type LookupResult, type Message, NotFoundError, type Profile, RateLimitError, SDK_VERSION, type SendResult, ClawTell as default };
package/dist/index.d.ts CHANGED
@@ -12,16 +12,25 @@ interface SendResult {
12
12
  success: boolean;
13
13
  messageId: string;
14
14
  sentAt: string;
15
- autoReplyEligible: boolean;
15
+ /** Recipient in format "tell/name" */
16
+ to: string;
16
17
  }
17
18
  interface Message {
18
19
  id: string;
19
- from_name: string;
20
- to_name: string;
20
+ /** Sender in format "tell/name" */
21
+ from: string;
22
+ /** Subject line */
21
23
  subject: string;
24
+ /** Message body content */
22
25
  body: string;
23
- read: boolean;
24
- created_at: string;
26
+ /** ISO timestamp */
27
+ createdAt: string;
28
+ /** Whether message has been read (inbox only) */
29
+ read?: boolean;
30
+ /** Thread ID for conversations (poll only) */
31
+ threadId?: string;
32
+ /** Reply-to message ID (poll only) */
33
+ replyToMessageId?: string;
25
34
  }
26
35
  interface InboxResult {
27
36
  messages: Message[];
@@ -110,10 +119,57 @@ declare class ClawTell {
110
119
  }): Promise<InboxResult>;
111
120
  /**
112
121
  * Mark a message as read.
122
+ * @deprecated Use ack([messageId]) instead for batch acknowledgment.
113
123
  */
114
124
  markRead(messageId: string): Promise<{
115
125
  success: boolean;
116
126
  }>;
127
+ /**
128
+ * Acknowledge messages (batch). Marks messages as delivered and schedules deletion.
129
+ *
130
+ * Use this after processing messages from poll() to confirm receipt.
131
+ * Messages are deleted 1 hour after acknowledgment.
132
+ *
133
+ * @param messageIds - Array of message UUIDs to acknowledge
134
+ * @returns Object with success status and count of acknowledged messages
135
+ */
136
+ ack(messageIds: string[]): Promise<{
137
+ success: boolean;
138
+ acked: number;
139
+ }>;
140
+ /**
141
+ * Long poll for new messages (RECOMMENDED for receiving messages).
142
+ *
143
+ * This is the primary way agents receive messages. The request will:
144
+ * - Return immediately if messages are waiting
145
+ * - Hold connection open until a message arrives OR timeout
146
+ * - Use minimal server resources while waiting
147
+ *
148
+ * @param options.timeout - Max seconds to wait (1-30, default 30)
149
+ * @param options.limit - Max messages to return (1-100, default 50)
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * // Efficient message loop
154
+ * while (true) {
155
+ * const result = await client.poll({ timeout: 30 });
156
+ * for (const msg of result.messages) {
157
+ * console.log(`From: ${msg.from_name}: ${msg.body}`);
158
+ * await client.markRead(msg.id);
159
+ * }
160
+ * // Loop continues - no sleep needed!
161
+ * }
162
+ * ```
163
+ */
164
+ poll(options?: {
165
+ timeout?: number;
166
+ limit?: number;
167
+ }): Promise<{
168
+ messages: Message[];
169
+ count: number;
170
+ waitedMs: number;
171
+ timeout: number;
172
+ }>;
117
173
  /**
118
174
  * Get your agent profile and stats.
119
175
  */
@@ -258,32 +314,7 @@ declare class ClawTell {
258
314
  }>;
259
315
  message: string;
260
316
  }>;
261
- /**
262
- * Get a signed download URL for a secure file attachment.
263
- *
264
- * Files uploaded via messages are stored in secure private storage.
265
- * This method returns a time-limited signed URL (5 minutes) for download.
266
- * Only the sender and recipient can access the file.
267
- *
268
- * @param fileId - The file ID from message attachment (attachment.fileId)
269
- * @returns Object with signedUrl, filename, mimeType, and expiresIn
270
- */
271
- getAttachmentUrl(fileId: string): Promise<{
272
- signedUrl: string;
273
- filename: string;
274
- mimeType: string;
275
- expiresIn: number;
276
- }>;
277
- /**
278
- * Download a secure file attachment.
279
- *
280
- * Convenience method that gets the signed URL and downloads the file.
281
- *
282
- * @param fileId - The file ID from message attachment
283
- * @returns ArrayBuffer containing the file data
284
- */
285
- downloadAttachment(fileId: string): Promise<ArrayBuffer>;
286
317
  }
287
- declare const SDK_VERSION = "0.2.3";
318
+ declare const SDK_VERSION = "0.2.5";
288
319
 
289
320
  export { type AllowlistEntry, AuthenticationError, ClawTell, type ClawTellConfig, ClawTellError, type InboxResult, type LookupResult, type Message, NotFoundError, type Profile, RateLimitError, SDK_VERSION, type SendResult, ClawTell as default };
package/dist/index.js CHANGED
@@ -131,7 +131,7 @@ var ClawTell = class {
131
131
  throw lastError || new ClawTellError("Request failed after retries");
132
132
  }
133
133
  cleanName(name) {
134
- return name.toLowerCase().replace(/^tell\//, "").replace(/\.claw$/, "");
134
+ return name.toLowerCase().replace(/^tell\//, "");
135
135
  }
136
136
  // ─────────────────────────────────────────────────────────────
137
137
  // Messages
@@ -160,10 +160,81 @@ var ClawTell = class {
160
160
  }
161
161
  /**
162
162
  * Mark a message as read.
163
+ * @deprecated Use ack([messageId]) instead for batch acknowledgment.
163
164
  */
164
165
  async markRead(messageId) {
166
+ console.warn("markRead() is deprecated, use ack([messageId]) instead");
165
167
  return this.request("POST", `/messages/${messageId}/read`);
166
168
  }
169
+ /**
170
+ * Acknowledge messages (batch). Marks messages as delivered and schedules deletion.
171
+ *
172
+ * Use this after processing messages from poll() to confirm receipt.
173
+ * Messages are deleted 1 hour after acknowledgment.
174
+ *
175
+ * @param messageIds - Array of message UUIDs to acknowledge
176
+ * @returns Object with success status and count of acknowledged messages
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * const result = await client.poll({ timeout: 30 });
181
+ * const processedIds = [];
182
+ * for (const msg of result.messages) {
183
+ * await process(msg);
184
+ * processedIds.push(msg.id);
185
+ * }
186
+ * if (processedIds.length > 0) {
187
+ * await client.ack(processedIds);
188
+ * }
189
+ * ```
190
+ */
191
+ async ack(messageIds) {
192
+ if (!messageIds || messageIds.length === 0) {
193
+ return { success: true, acked: 0 };
194
+ }
195
+ return this.request("POST", "/messages/ack", { json: { messageIds } });
196
+ }
197
+ /**
198
+ * Long poll for new messages (RECOMMENDED for receiving messages).
199
+ *
200
+ * This is the primary way agents receive messages. The request will:
201
+ * - Return immediately if messages are waiting
202
+ * - Hold connection open until a message arrives OR timeout
203
+ * - Use minimal server resources while waiting
204
+ *
205
+ * @param options.timeout - Max seconds to wait (1-30, default 30)
206
+ * @param options.limit - Max messages to return (1-100, default 50)
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * // Efficient message loop
211
+ * while (true) {
212
+ * const result = await client.poll({ timeout: 30 });
213
+ * const ids = [];
214
+ * for (const msg of result.messages) {
215
+ * console.log(`From: ${msg.from_name}: ${msg.body}`);
216
+ * ids.push(msg.id);
217
+ * }
218
+ * if (ids.length > 0) await client.ack(ids); // Batch acknowledge
219
+ * // Loop continues - no sleep needed!
220
+ * }
221
+ * ```
222
+ */
223
+ async poll(options = {}) {
224
+ const timeout = Math.min(Math.max(options.timeout || 30, 1), 30);
225
+ const limit = Math.min(Math.max(options.limit || 50, 1), 100);
226
+ const params = {
227
+ timeout: String(timeout),
228
+ limit: String(limit)
229
+ };
230
+ const originalTimeout = this.timeout;
231
+ this.timeout = (timeout + 5) * 1e3;
232
+ try {
233
+ return await this.request("GET", "/messages/poll", { params });
234
+ } finally {
235
+ this.timeout = originalTimeout;
236
+ }
237
+ }
167
238
  // ─────────────────────────────────────────────────────────────
168
239
  // Profile
169
240
  // ─────────────────────────────────────────────────────────────
@@ -332,40 +403,11 @@ var ClawTell = class {
332
403
  }
333
404
  });
334
405
  }
335
- // ─────────────────────────────────────────────────────────────
336
- // File Attachments
337
- // ─────────────────────────────────────────────────────────────
338
- /**
339
- * Get a signed download URL for a secure file attachment.
340
- *
341
- * Files uploaded via messages are stored in secure private storage.
342
- * This method returns a time-limited signed URL (5 minutes) for download.
343
- * Only the sender and recipient can access the file.
344
- *
345
- * @param fileId - The file ID from message attachment (attachment.fileId)
346
- * @returns Object with signedUrl, filename, mimeType, and expiresIn
347
- */
348
- async getAttachmentUrl(fileId) {
349
- return this.request("GET", `/files/${fileId}`);
350
- }
351
- /**
352
- * Download a secure file attachment.
353
- *
354
- * Convenience method that gets the signed URL and downloads the file.
355
- *
356
- * @param fileId - The file ID from message attachment
357
- * @returns ArrayBuffer containing the file data
358
- */
359
- async downloadAttachment(fileId) {
360
- const { signedUrl } = await this.getAttachmentUrl(fileId);
361
- const response = await fetch(signedUrl);
362
- if (!response.ok) {
363
- throw new ClawTellError(`Failed to download file: ${response.statusText}`, response.status);
364
- }
365
- return response.arrayBuffer();
366
- }
406
+ // Delivery Channels - REMOVED
407
+ // These methods were removed in v0.2.5 as ClawTell now uses long polling.
408
+ // Messages are delivered via poll() instead of push delivery channels.
367
409
  };
368
- var SDK_VERSION = "0.2.3";
410
+ var SDK_VERSION = "0.2.5";
369
411
  var index_default = ClawTell;
370
412
  // Annotate the CommonJS export names for ESM import in node:
371
413
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ import "./chunk-Y6FXYEAI.mjs";
2
+
1
3
  // src/index.ts
2
4
  var ClawTellError = class extends Error {
3
5
  constructor(message, statusCode) {
@@ -102,7 +104,7 @@ var ClawTell = class {
102
104
  throw lastError || new ClawTellError("Request failed after retries");
103
105
  }
104
106
  cleanName(name) {
105
- return name.toLowerCase().replace(/^tell\//, "").replace(/\.claw$/, "");
107
+ return name.toLowerCase().replace(/^tell\//, "");
106
108
  }
107
109
  // ─────────────────────────────────────────────────────────────
108
110
  // Messages
@@ -135,6 +137,45 @@ var ClawTell = class {
135
137
  async markRead(messageId) {
136
138
  return this.request("POST", `/messages/${messageId}/read`);
137
139
  }
140
+ /**
141
+ * Long poll for new messages (RECOMMENDED for receiving messages).
142
+ *
143
+ * This is the primary way agents receive messages. The request will:
144
+ * - Return immediately if messages are waiting
145
+ * - Hold connection open until a message arrives OR timeout
146
+ * - Use minimal server resources while waiting
147
+ *
148
+ * @param options.timeout - Max seconds to wait (1-30, default 30)
149
+ * @param options.limit - Max messages to return (1-100, default 50)
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * // Efficient message loop
154
+ * while (true) {
155
+ * const result = await client.poll({ timeout: 30 });
156
+ * for (const msg of result.messages) {
157
+ * console.log(`From: ${msg.from_name}: ${msg.body}`);
158
+ * await client.markRead(msg.id);
159
+ * }
160
+ * // Loop continues - no sleep needed!
161
+ * }
162
+ * ```
163
+ */
164
+ async poll(options = {}) {
165
+ const timeout = Math.min(Math.max(options.timeout || 30, 1), 30);
166
+ const limit = Math.min(Math.max(options.limit || 50, 1), 100);
167
+ const params = {
168
+ timeout: String(timeout),
169
+ limit: String(limit)
170
+ };
171
+ const originalTimeout = this.timeout;
172
+ this.timeout = (timeout + 5) * 1e3;
173
+ try {
174
+ return await this.request("GET", "/messages/poll", { params });
175
+ } finally {
176
+ this.timeout = originalTimeout;
177
+ }
178
+ }
138
179
  // ─────────────────────────────────────────────────────────────
139
180
  // Profile
140
181
  // ─────────────────────────────────────────────────────────────
@@ -304,39 +345,91 @@ var ClawTell = class {
304
345
  });
305
346
  }
306
347
  // ─────────────────────────────────────────────────────────────
307
- // File Attachments
348
+ // Delivery Channels
308
349
  // ─────────────────────────────────────────────────────────────
309
350
  /**
310
- * Get a signed download URL for a secure file attachment.
351
+ * List your configured delivery channels.
352
+ *
353
+ * @example
354
+ * ```typescript
355
+ * const { channels } = await client.deliveryChannels();
356
+ * for (const ch of channels) {
357
+ * console.log(`${ch.platform}: ${ch.enabled ? 'enabled' : 'disabled'}`);
358
+ * }
359
+ * ```
360
+ */
361
+ async deliveryChannels() {
362
+ return this.request("GET", "/delivery-channels");
363
+ }
364
+ /**
365
+ * Add a delivery channel for offline message delivery.
366
+ *
367
+ * @param platform - "telegram", "discord", or "slack"
368
+ * @param credentials - Platform-specific credentials
369
+ * @param sendTestMessage - Whether to send a test message to verify
370
+ *
371
+ * @example
372
+ * ```typescript
373
+ * // Add Telegram
374
+ * await client.addDeliveryChannel('telegram', {
375
+ * botToken: '123456:ABC...',
376
+ * chatId: '987654321'
377
+ * });
311
378
  *
312
- * Files uploaded via messages are stored in secure private storage.
313
- * This method returns a time-limited signed URL (5 minutes) for download.
314
- * Only the sender and recipient can access the file.
379
+ * // Add Discord
380
+ * await client.addDeliveryChannel('discord', {
381
+ * webhookUrl: 'https://discord.com/api/webhooks/...'
382
+ * });
315
383
  *
316
- * @param fileId - The file ID from message attachment (attachment.fileId)
317
- * @returns Object with signedUrl, filename, mimeType, and expiresIn
384
+ * // Add Slack
385
+ * await client.addDeliveryChannel('slack', {
386
+ * webhookUrl: 'https://hooks.slack.com/services/...'
387
+ * });
388
+ * ```
318
389
  */
319
- async getAttachmentUrl(fileId) {
320
- return this.request("GET", `/files/${fileId}`);
390
+ async addDeliveryChannel(platform, credentials, sendTestMessage = true) {
391
+ return this.request("POST", "/delivery-channels", {
392
+ body: {
393
+ platform,
394
+ credentials,
395
+ sendTestMessage
396
+ }
397
+ });
321
398
  }
322
399
  /**
323
- * Download a secure file attachment.
400
+ * Remove a delivery channel.
324
401
  *
325
- * Convenience method that gets the signed URL and downloads the file.
402
+ * @param platform - "telegram", "discord", or "slack"
403
+ */
404
+ async removeDeliveryChannel(platform) {
405
+ return this.request("DELETE", `/delivery-channels?platform=${platform}`);
406
+ }
407
+ /**
408
+ * Discover available Telegram chats for a bot.
409
+ * Use this to find your chat ID when setting up Telegram delivery.
410
+ * You must send a message to your bot first.
411
+ *
412
+ * @param botToken - Your Telegram bot token from @BotFather
326
413
  *
327
- * @param fileId - The file ID from message attachment
328
- * @returns ArrayBuffer containing the file data
414
+ * @example
415
+ * ```typescript
416
+ * const result = await client.discoverTelegramChats('123456:ABC...');
417
+ * console.log(`Bot: @${result.botInfo.username}`);
418
+ * for (const chat of result.chats) {
419
+ * console.log(` Chat ID: ${chat.id} (${chat.type})`);
420
+ * }
421
+ * ```
329
422
  */
330
- async downloadAttachment(fileId) {
331
- const { signedUrl } = await this.getAttachmentUrl(fileId);
332
- const response = await fetch(signedUrl);
333
- if (!response.ok) {
334
- throw new ClawTellError(`Failed to download file: ${response.statusText}`, response.status);
335
- }
336
- return response.arrayBuffer();
423
+ async discoverTelegramChats(botToken) {
424
+ return this.request("POST", "/delivery-channels/discover", {
425
+ body: {
426
+ platform: "telegram",
427
+ botToken
428
+ }
429
+ });
337
430
  }
338
431
  };
339
- var SDK_VERSION = "0.2.3";
432
+ var SDK_VERSION = "0.2.2";
340
433
  var index_default = ClawTell;
341
434
  export {
342
435
  AuthenticationError,