@framers/agentos 0.1.26 → 0.1.28

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 (79) hide show
  1. package/dist/api/AgentOSOrchestrator.js +1 -1
  2. package/dist/api/AgentOSOrchestrator.js.map +1 -1
  3. package/dist/channels/ChannelRouter.d.ts.map +1 -1
  4. package/dist/channels/ChannelRouter.js +1 -1
  5. package/dist/channels/ChannelRouter.js.map +1 -1
  6. package/dist/channels/IChannelAdapter.d.ts.map +1 -1
  7. package/dist/channels/adapters/BaseChannelAdapter.d.ts +130 -0
  8. package/dist/channels/adapters/BaseChannelAdapter.d.ts.map +1 -0
  9. package/dist/channels/adapters/BaseChannelAdapter.js +257 -0
  10. package/dist/channels/adapters/BaseChannelAdapter.js.map +1 -0
  11. package/dist/channels/adapters/DiscordChannelAdapter.d.ts +86 -0
  12. package/dist/channels/adapters/DiscordChannelAdapter.d.ts.map +1 -0
  13. package/dist/channels/adapters/DiscordChannelAdapter.js +550 -0
  14. package/dist/channels/adapters/DiscordChannelAdapter.js.map +1 -0
  15. package/dist/channels/adapters/GoogleChatChannelAdapter.d.ts +117 -0
  16. package/dist/channels/adapters/GoogleChatChannelAdapter.d.ts.map +1 -0
  17. package/dist/channels/adapters/GoogleChatChannelAdapter.js +632 -0
  18. package/dist/channels/adapters/GoogleChatChannelAdapter.js.map +1 -0
  19. package/dist/channels/adapters/IRCChannelAdapter.d.ts +86 -0
  20. package/dist/channels/adapters/IRCChannelAdapter.d.ts.map +1 -0
  21. package/dist/channels/adapters/IRCChannelAdapter.js +253 -0
  22. package/dist/channels/adapters/IRCChannelAdapter.js.map +1 -0
  23. package/dist/channels/adapters/RedditChannelAdapter.d.ts +123 -0
  24. package/dist/channels/adapters/RedditChannelAdapter.d.ts.map +1 -0
  25. package/dist/channels/adapters/RedditChannelAdapter.js +516 -0
  26. package/dist/channels/adapters/RedditChannelAdapter.js.map +1 -0
  27. package/dist/channels/adapters/SignalChannelAdapter.d.ts +120 -0
  28. package/dist/channels/adapters/SignalChannelAdapter.d.ts.map +1 -0
  29. package/dist/channels/adapters/SignalChannelAdapter.js +521 -0
  30. package/dist/channels/adapters/SignalChannelAdapter.js.map +1 -0
  31. package/dist/channels/adapters/SlackChannelAdapter.d.ts +96 -0
  32. package/dist/channels/adapters/SlackChannelAdapter.d.ts.map +1 -0
  33. package/dist/channels/adapters/SlackChannelAdapter.js +535 -0
  34. package/dist/channels/adapters/SlackChannelAdapter.js.map +1 -0
  35. package/dist/channels/adapters/TeamsChannelAdapter.d.ts +138 -0
  36. package/dist/channels/adapters/TeamsChannelAdapter.d.ts.map +1 -0
  37. package/dist/channels/adapters/TeamsChannelAdapter.js +639 -0
  38. package/dist/channels/adapters/TeamsChannelAdapter.js.map +1 -0
  39. package/dist/channels/adapters/TelegramChannelAdapter.d.ts +83 -0
  40. package/dist/channels/adapters/TelegramChannelAdapter.d.ts.map +1 -0
  41. package/dist/channels/adapters/TelegramChannelAdapter.js +463 -0
  42. package/dist/channels/adapters/TelegramChannelAdapter.js.map +1 -0
  43. package/dist/channels/adapters/TwitterChannelAdapter.d.ts +117 -0
  44. package/dist/channels/adapters/TwitterChannelAdapter.d.ts.map +1 -0
  45. package/dist/channels/adapters/TwitterChannelAdapter.js +489 -0
  46. package/dist/channels/adapters/TwitterChannelAdapter.js.map +1 -0
  47. package/dist/channels/adapters/WebChatChannelAdapter.d.ts +141 -0
  48. package/dist/channels/adapters/WebChatChannelAdapter.d.ts.map +1 -0
  49. package/dist/channels/adapters/WebChatChannelAdapter.js +539 -0
  50. package/dist/channels/adapters/WebChatChannelAdapter.js.map +1 -0
  51. package/dist/channels/adapters/WhatsAppChannelAdapter.d.ts +122 -0
  52. package/dist/channels/adapters/WhatsAppChannelAdapter.d.ts.map +1 -0
  53. package/dist/channels/adapters/WhatsAppChannelAdapter.js +643 -0
  54. package/dist/channels/adapters/WhatsAppChannelAdapter.js.map +1 -0
  55. package/dist/channels/adapters/index.d.ts +34 -0
  56. package/dist/channels/adapters/index.d.ts.map +1 -0
  57. package/dist/channels/adapters/index.js +25 -0
  58. package/dist/channels/adapters/index.js.map +1 -0
  59. package/dist/channels/index.d.ts +24 -0
  60. package/dist/channels/index.d.ts.map +1 -1
  61. package/dist/channels/index.js +16 -0
  62. package/dist/channels/index.js.map +1 -1
  63. package/dist/cognitive_substrate/personas/metaprompt_presets.d.ts.map +1 -1
  64. package/dist/cognitive_substrate/personas/metaprompt_presets.js +0 -2
  65. package/dist/cognitive_substrate/personas/metaprompt_presets.js.map +1 -1
  66. package/dist/core/provenance/crypto/HashChain.d.ts.map +1 -1
  67. package/dist/core/provenance/enforcement/AutonomyGuard.d.ts.map +1 -1
  68. package/dist/core/provenance/enforcement/ProvenanceStorageHooks.d.ts.map +1 -1
  69. package/dist/core/provenance/enforcement/ProvenanceStorageHooks.js +2 -1
  70. package/dist/core/provenance/enforcement/ProvenanceStorageHooks.js.map +1 -1
  71. package/dist/core/provenance/ledger/EventTypes.d.ts.map +1 -1
  72. package/dist/core/safety/ToolExecutionGuard.d.ts.map +1 -1
  73. package/dist/core/safety/ToolExecutionGuard.js +0 -1
  74. package/dist/core/safety/ToolExecutionGuard.js.map +1 -1
  75. package/dist/extensions/ExtensionManager.d.ts.map +1 -1
  76. package/dist/extensions/ExtensionManager.js +3 -9
  77. package/dist/extensions/ExtensionManager.js.map +1 -1
  78. package/dist/rag/RetrievalAugmentor.js.map +1 -1
  79. package/package.json +1 -1
@@ -0,0 +1,516 @@
1
+ /**
2
+ * @fileoverview Reddit Channel Adapter for AgentOS.
3
+ *
4
+ * Wraps the Reddit API (via `snoowrap`) to allow agents to submit
5
+ * posts, comments, and interact with subreddits. Uses dynamic import
6
+ * so that `snoowrap` is only loaded at connection time.
7
+ *
8
+ * Reddit's API has strict rate limits (60 requests per minute for
9
+ * OAuth apps). The adapter tracks and respects these limits with a
10
+ * request queue.
11
+ *
12
+ * **Dependencies**: Requires `snoowrap` to be installed.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const reddit = new RedditChannelAdapter();
17
+ * await reddit.initialize({
18
+ * platform: 'reddit',
19
+ * credential: '<client_id>',
20
+ * params: {
21
+ * clientSecret: 'your-client-secret',
22
+ * username: 'bot_username',
23
+ * password: 'bot_password',
24
+ * userAgent: 'agentos:v1.0 (by /u/your_username)',
25
+ * },
26
+ * });
27
+ * ```
28
+ *
29
+ * @module @framers/agentos/channels/adapters/RedditChannelAdapter
30
+ */
31
+ import { BaseChannelAdapter } from './BaseChannelAdapter.js';
32
+ // ============================================================================
33
+ // RedditChannelAdapter
34
+ // ============================================================================
35
+ /**
36
+ * Channel adapter for Reddit.
37
+ *
38
+ * Uses the `snoowrap` package via dynamic import so the dependency
39
+ * is optional. Falls back to raw `fetch` against the Reddit OAuth2
40
+ * API if snoowrap is unavailable.
41
+ *
42
+ * Capabilities: `text`, `rich_text`, `images`, `video`, `reactions`,
43
+ * `threads`, `group_chat`, `hashtags`, `polls`.
44
+ *
45
+ * Conversation ID mapping:
46
+ * - Subreddit post: `r/<subreddit>` or `post:<thing_id>`
47
+ * - Comment reply: `comment:<thing_id>`
48
+ * - Direct message: `dm:<username>`
49
+ */
50
+ export class RedditChannelAdapter extends BaseChannelAdapter {
51
+ constructor() {
52
+ super(...arguments);
53
+ this.platform = 'reddit';
54
+ this.displayName = 'Reddit';
55
+ this.capabilities = [
56
+ 'text',
57
+ 'rich_text',
58
+ 'images',
59
+ 'video',
60
+ 'reactions',
61
+ 'threads',
62
+ 'group_chat',
63
+ 'hashtags',
64
+ 'polls',
65
+ ];
66
+ /** Whether we're using snoowrap or raw fetch. */
67
+ this.usingSnoowrap = false;
68
+ this.tokenExpiresAt = 0;
69
+ /** Rate-limit: requests remaining in the current window. */
70
+ this.rateLimitRemaining = 60;
71
+ this.rateLimitResetAt = 0;
72
+ this.lastInboxTimestamp = 0;
73
+ }
74
+ // ── Abstract hook implementations ──
75
+ async doConnect(auth) {
76
+ const params = auth.params ?? {};
77
+ this.storedAuth = auth;
78
+ if (!auth.credential) {
79
+ throw new Error('Reddit auth credential (clientId) is required.');
80
+ }
81
+ if (!params.clientSecret) {
82
+ throw new Error('Reddit auth params must include "clientSecret".');
83
+ }
84
+ if (!params.username || !params.password) {
85
+ throw new Error('Reddit auth params must include "username" and "password".');
86
+ }
87
+ if (!params.userAgent) {
88
+ throw new Error('Reddit auth params must include "userAgent".');
89
+ }
90
+ // Attempt snoowrap first, fall back to raw fetch
91
+ try {
92
+ const snoowrap = await import('snoowrap');
93
+ const Snoowrap = snoowrap.default ?? snoowrap;
94
+ this.client = new Snoowrap({
95
+ userAgent: params.userAgent,
96
+ clientId: auth.credential,
97
+ clientSecret: params.clientSecret,
98
+ username: params.username,
99
+ password: params.password,
100
+ });
101
+ // Configure snoowrap rate limiting
102
+ this.client.config({
103
+ requestDelay: 1000, // 1 request per second baseline
104
+ continueAfterRatelimitError: true,
105
+ retryErrorCodes: [502, 503, 504, 522],
106
+ maxRetryAttempts: 3,
107
+ });
108
+ this.usingSnoowrap = true;
109
+ // Verify by fetching the authenticated user
110
+ const me = await this.client.getMe();
111
+ this.authenticatedUser = {
112
+ name: me.name,
113
+ id: me.id,
114
+ };
115
+ }
116
+ catch (importErr) {
117
+ // snoowrap not available — use raw Reddit API
118
+ console.warn('[Reddit] snoowrap not installed, using raw Reddit API. ' +
119
+ 'Install snoowrap for a richer experience: npm install snoowrap');
120
+ this.usingSnoowrap = false;
121
+ await this.authenticateRaw(auth.credential, params);
122
+ }
123
+ this.platformInfo = {
124
+ username: this.authenticatedUser?.name,
125
+ userId: this.authenticatedUser?.id,
126
+ usingSnoowrap: this.usingSnoowrap,
127
+ };
128
+ // Start polling for incoming messages
129
+ this.startPolling();
130
+ }
131
+ async doSendMessage(conversationId, content) {
132
+ // Determine what kind of interaction this is
133
+ if (conversationId.startsWith('r/')) {
134
+ return this.submitPost(conversationId.slice(2), content);
135
+ }
136
+ if (conversationId.startsWith('comment:')) {
137
+ return this.replyToComment(conversationId.slice(8), content);
138
+ }
139
+ if (conversationId.startsWith('post:')) {
140
+ return this.replyToPost(conversationId.slice(5), content);
141
+ }
142
+ if (conversationId.startsWith('dm:')) {
143
+ return this.sendPrivateMessage(conversationId.slice(3), content);
144
+ }
145
+ // Default: treat as subreddit name
146
+ return this.submitPost(conversationId, content);
147
+ }
148
+ async doShutdown() {
149
+ this.stopPolling();
150
+ this.client = undefined;
151
+ this.accessToken = undefined;
152
+ this.authenticatedUser = undefined;
153
+ this.storedAuth = undefined;
154
+ this.lastInboxTimestamp = 0;
155
+ }
156
+ // ── Reddit-specific public methods ──
157
+ /**
158
+ * Submit a new post to a subreddit.
159
+ */
160
+ async submitPost(subreddit, content) {
161
+ const text = this.extractText(content.blocks);
162
+ const title = this.extractTitle(text);
163
+ const body = this.extractBody(text);
164
+ const imageBlock = content.blocks.find((b) => b.type === 'image');
165
+ const pollBlock = content.blocks.find((b) => b.type === 'poll');
166
+ if (this.usingSnoowrap && this.client) {
167
+ return this.submitPostSnoowrap(subreddit, title, body, imageBlock, pollBlock);
168
+ }
169
+ return this.submitPostRaw(subreddit, title, body, imageBlock);
170
+ }
171
+ /**
172
+ * Upvote a post or comment.
173
+ */
174
+ async upvote(thingId) {
175
+ if (this.usingSnoowrap && this.client) {
176
+ await this.client.getSubmission(thingId).upvote();
177
+ }
178
+ else {
179
+ await this.redditApiRequest('POST', '/api/vote', {
180
+ id: thingId,
181
+ dir: 1,
182
+ });
183
+ }
184
+ }
185
+ /**
186
+ * Downvote a post or comment.
187
+ */
188
+ async downvote(thingId) {
189
+ if (this.usingSnoowrap && this.client) {
190
+ await this.client.getSubmission(thingId).downvote();
191
+ }
192
+ else {
193
+ await this.redditApiRequest('POST', '/api/vote', {
194
+ id: thingId,
195
+ dir: -1,
196
+ });
197
+ }
198
+ }
199
+ /**
200
+ * Get information about the authenticated user.
201
+ */
202
+ getAuthenticatedUser() {
203
+ return this.authenticatedUser ? { ...this.authenticatedUser } : undefined;
204
+ }
205
+ // ── Private: snoowrap methods ──
206
+ async submitPostSnoowrap(subreddit, title, body,
207
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
208
+ imageBlock,
209
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
210
+ pollBlock) {
211
+ let submission; // eslint-disable-line @typescript-eslint/no-explicit-any
212
+ if (imageBlock && imageBlock.type === 'image') {
213
+ // Link post with image URL
214
+ submission = await this.client
215
+ .getSubreddit(subreddit)
216
+ .submitLink({
217
+ title,
218
+ url: imageBlock.url,
219
+ });
220
+ }
221
+ else if (pollBlock && pollBlock.type === 'poll') {
222
+ // Polls require raw API call even with snoowrap
223
+ const result = await this.redditApiRequest('POST', '/api/submit_poll_post', {
224
+ sr: subreddit,
225
+ title,
226
+ selftext: body,
227
+ options: pollBlock.options,
228
+ duration: (pollBlock.durationHours ?? 24) * 60, // minutes
229
+ });
230
+ return {
231
+ messageId: result?.json?.data?.id ?? `reddit-${Date.now()}`,
232
+ timestamp: new Date().toISOString(),
233
+ };
234
+ }
235
+ else {
236
+ // Self (text) post
237
+ submission = await this.client
238
+ .getSubreddit(subreddit)
239
+ .submitSelfpost({
240
+ title,
241
+ text: body,
242
+ });
243
+ }
244
+ return {
245
+ messageId: submission?.name ?? submission?.id ?? `reddit-${Date.now()}`,
246
+ timestamp: new Date().toISOString(),
247
+ };
248
+ }
249
+ async replyToComment(commentId, content) {
250
+ const text = this.extractText(content.blocks);
251
+ if (!text) {
252
+ throw new Error('[Reddit] Cannot post empty comment.');
253
+ }
254
+ if (this.usingSnoowrap && this.client) {
255
+ const reply = await this.client.getComment(commentId).reply(text);
256
+ return {
257
+ messageId: reply?.name ?? reply?.id ?? `reddit-${Date.now()}`,
258
+ timestamp: new Date().toISOString(),
259
+ };
260
+ }
261
+ const result = await this.redditApiRequest('POST', '/api/comment', {
262
+ parent: commentId.startsWith('t1_') ? commentId : `t1_${commentId}`,
263
+ text,
264
+ });
265
+ return {
266
+ messageId: result?.json?.data?.things?.[0]?.data?.name ?? `reddit-${Date.now()}`,
267
+ timestamp: new Date().toISOString(),
268
+ };
269
+ }
270
+ async replyToPost(postId, content) {
271
+ const text = this.extractText(content.blocks);
272
+ if (!text) {
273
+ throw new Error('[Reddit] Cannot post empty comment.');
274
+ }
275
+ if (this.usingSnoowrap && this.client) {
276
+ const reply = await this.client.getSubmission(postId).reply(text);
277
+ return {
278
+ messageId: reply?.name ?? reply?.id ?? `reddit-${Date.now()}`,
279
+ timestamp: new Date().toISOString(),
280
+ };
281
+ }
282
+ const result = await this.redditApiRequest('POST', '/api/comment', {
283
+ parent: postId.startsWith('t3_') ? postId : `t3_${postId}`,
284
+ text,
285
+ });
286
+ return {
287
+ messageId: result?.json?.data?.things?.[0]?.data?.name ?? `reddit-${Date.now()}`,
288
+ timestamp: new Date().toISOString(),
289
+ };
290
+ }
291
+ async sendPrivateMessage(username, content) {
292
+ const text = this.extractText(content.blocks);
293
+ const title = this.extractTitle(text);
294
+ const body = this.extractBody(text);
295
+ if (this.usingSnoowrap && this.client) {
296
+ await this.client.composeMessage({
297
+ to: username,
298
+ subject: title || 'Message from AgentOS',
299
+ text: body || text,
300
+ });
301
+ }
302
+ else {
303
+ await this.redditApiRequest('POST', '/api/compose', {
304
+ to: username,
305
+ subject: title || 'Message from AgentOS',
306
+ text: body || text,
307
+ });
308
+ }
309
+ return {
310
+ messageId: `dm-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
311
+ timestamp: new Date().toISOString(),
312
+ };
313
+ }
314
+ // ── Private: raw Reddit API (fetch-based fallback) ──
315
+ async authenticateRaw(clientId, params) {
316
+ const basicAuth = Buffer.from(`${clientId}:${params.clientSecret}`).toString('base64');
317
+ const response = await fetch('https://www.reddit.com/api/v1/access_token', {
318
+ method: 'POST',
319
+ headers: {
320
+ 'Authorization': `Basic ${basicAuth}`,
321
+ 'Content-Type': 'application/x-www-form-urlencoded',
322
+ 'User-Agent': params.userAgent,
323
+ },
324
+ body: new URLSearchParams({
325
+ grant_type: 'password',
326
+ username: params.username,
327
+ password: params.password,
328
+ }),
329
+ });
330
+ if (!response.ok) {
331
+ throw new Error(`Reddit OAuth2 authentication failed: ${response.status} ${response.statusText}`);
332
+ }
333
+ const data = await response.json();
334
+ if (data.error) {
335
+ throw new Error(`Reddit OAuth2 error: ${data.error}`);
336
+ }
337
+ this.accessToken = data.access_token;
338
+ this.tokenExpiresAt = Date.now() + (data.expires_in ?? 3600) * 1000;
339
+ // Fetch authenticated user info
340
+ const meResponse = await this.redditApiRequest('GET', '/api/v1/me');
341
+ this.authenticatedUser = {
342
+ name: meResponse.name,
343
+ id: meResponse.id,
344
+ };
345
+ }
346
+ async ensureAccessToken() {
347
+ if (this.accessToken && Date.now() < this.tokenExpiresAt - 60000) {
348
+ return; // Token still valid (with 60s buffer)
349
+ }
350
+ if (!this.storedAuth) {
351
+ throw new Error('[Reddit] Cannot refresh token — no stored auth.');
352
+ }
353
+ const params = this.storedAuth.params ?? {};
354
+ await this.authenticateRaw(this.storedAuth.credential, params);
355
+ }
356
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
357
+ async redditApiRequest(method, path, body) {
358
+ if (!this.usingSnoowrap) {
359
+ await this.ensureAccessToken();
360
+ }
361
+ // Respect rate limits
362
+ const now = Date.now() / 1000;
363
+ if (this.rateLimitRemaining <= 1 && now < this.rateLimitResetAt) {
364
+ const waitMs = (this.rateLimitResetAt - now) * 1000 + 500;
365
+ console.warn(`[Reddit] Rate limit near exhaustion. Waiting ${Math.round(waitMs / 1000)}s.`);
366
+ await new Promise((resolve) => setTimeout(resolve, waitMs));
367
+ }
368
+ const url = `https://oauth.reddit.com${path}`;
369
+ const userAgent = this.storedAuth?.params?.userAgent ?? 'AgentOS Reddit Adapter';
370
+ const options = {
371
+ method,
372
+ headers: {
373
+ 'Authorization': `Bearer ${this.accessToken}`,
374
+ 'User-Agent': userAgent,
375
+ 'Content-Type': 'application/x-www-form-urlencoded',
376
+ },
377
+ };
378
+ if (body && method !== 'GET') {
379
+ options.body = new URLSearchParams(Object.entries(body).reduce((acc, [k, v]) => {
380
+ acc[k] = typeof v === 'string' ? v : JSON.stringify(v);
381
+ return acc;
382
+ }, {}));
383
+ }
384
+ const response = await fetch(url, options);
385
+ // Update rate limit tracking from headers
386
+ const remaining = response.headers.get('x-ratelimit-remaining');
387
+ const reset = response.headers.get('x-ratelimit-reset');
388
+ if (remaining !== null) {
389
+ this.rateLimitRemaining = parseFloat(remaining);
390
+ }
391
+ if (reset !== null) {
392
+ this.rateLimitResetAt = Date.now() / 1000 + parseFloat(reset);
393
+ }
394
+ if (!response.ok) {
395
+ const text = await response.text().catch(() => '');
396
+ throw new Error(`Reddit API error: ${response.status} ${response.statusText} — ${text}`);
397
+ }
398
+ return response.json();
399
+ }
400
+ // ── Private: submit post via raw API ──
401
+ async submitPostRaw(subreddit, title, body,
402
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
403
+ imageBlock) {
404
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
405
+ const payload = {
406
+ sr: subreddit,
407
+ title,
408
+ kind: imageBlock ? 'link' : 'self',
409
+ resubmit: 'true',
410
+ };
411
+ if (imageBlock && imageBlock.type === 'image') {
412
+ payload.url = imageBlock.url;
413
+ }
414
+ else {
415
+ payload.text = body;
416
+ }
417
+ const result = await this.redditApiRequest('POST', '/api/submit', payload);
418
+ return {
419
+ messageId: result?.json?.data?.name ?? result?.json?.data?.id ?? `reddit-${Date.now()}`,
420
+ timestamp: new Date().toISOString(),
421
+ };
422
+ }
423
+ // ── Polling for inbox messages ──
424
+ startPolling() {
425
+ // Poll inbox every 90 seconds (conservative for Reddit rate limits)
426
+ this.pollTimer = setInterval(() => {
427
+ this.pollInbox().catch((err) => {
428
+ console.warn('[Reddit] Inbox poll error:', err);
429
+ });
430
+ }, 90000);
431
+ }
432
+ stopPolling() {
433
+ if (this.pollTimer) {
434
+ clearInterval(this.pollTimer);
435
+ this.pollTimer = undefined;
436
+ }
437
+ }
438
+ async pollInbox() {
439
+ try {
440
+ let messages; // eslint-disable-line @typescript-eslint/no-explicit-any
441
+ if (this.usingSnoowrap && this.client) {
442
+ const inbox = await this.client.getUnreadMessages();
443
+ messages = Array.isArray(inbox) ? inbox : [];
444
+ }
445
+ else {
446
+ const result = await this.redditApiRequest('GET', '/message/unread?limit=25');
447
+ messages = result?.data?.children?.map((c) => c.data) ?? []; // eslint-disable-line @typescript-eslint/no-explicit-any
448
+ }
449
+ for (const msg of messages) {
450
+ const createdAt = (msg.created_utc ?? msg.created ?? 0) * 1000;
451
+ if (createdAt <= this.lastInboxTimestamp)
452
+ continue;
453
+ const isComment = msg.was_comment === true;
454
+ const conversationId = isComment
455
+ ? `comment:${msg.name ?? msg.id}`
456
+ : `dm:${msg.author ?? msg.dest ?? 'unknown'}`;
457
+ const channelMessage = {
458
+ messageId: msg.name ?? msg.id ?? `reddit-${Date.now()}`,
459
+ platform: 'reddit',
460
+ conversationId,
461
+ conversationType: isComment ? 'thread' : 'direct',
462
+ sender: {
463
+ id: msg.author ?? 'unknown',
464
+ username: msg.author,
465
+ displayName: msg.author,
466
+ },
467
+ content: [{ type: 'text', text: msg.body ?? '' }],
468
+ text: msg.body ?? '',
469
+ timestamp: new Date(createdAt).toISOString(),
470
+ rawEvent: msg,
471
+ };
472
+ this.emit({
473
+ type: 'message',
474
+ platform: 'reddit',
475
+ conversationId,
476
+ timestamp: channelMessage.timestamp,
477
+ data: channelMessage,
478
+ });
479
+ if (createdAt > this.lastInboxTimestamp) {
480
+ this.lastInboxTimestamp = createdAt;
481
+ }
482
+ }
483
+ }
484
+ catch {
485
+ // Non-fatal — will retry on next poll
486
+ }
487
+ }
488
+ // ── Text helpers ──
489
+ extractText(blocks) {
490
+ return blocks
491
+ .filter((b) => b.type === 'text')
492
+ .map((b) => b.text)
493
+ .join('\n');
494
+ }
495
+ /**
496
+ * Extract the first line as a title. Reddit requires titles for posts.
497
+ */
498
+ extractTitle(text) {
499
+ const firstLine = text.split('\n')[0]?.trim();
500
+ if (firstLine && firstLine.length <= 300)
501
+ return firstLine;
502
+ if (firstLine)
503
+ return firstLine.slice(0, 297) + '...';
504
+ return 'Post from AgentOS';
505
+ }
506
+ /**
507
+ * Extract everything after the first line as the body.
508
+ */
509
+ extractBody(text) {
510
+ const lines = text.split('\n');
511
+ if (lines.length <= 1)
512
+ return '';
513
+ return lines.slice(1).join('\n').trim();
514
+ }
515
+ }
516
+ //# sourceMappingURL=RedditChannelAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RedditChannelAdapter.js","sourceRoot":"","sources":["../../../src/channels/adapters/RedditChannelAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * @fileoverview Signal Channel Adapter for AgentOS.
3
+ *
4
+ * Integrates with the Signal messaging protocol via `signal-cli`, a
5
+ * command-line tool for Signal. The adapter invokes signal-cli as a
6
+ * subprocess for sending/receiving messages, providing end-to-end
7
+ * encrypted communication for agents.
8
+ *
9
+ * **Dependencies**: Requires `signal-cli` to be installed and
10
+ * configured on the system (either registered or linked to an
11
+ * existing device). See https://github.com/AsamK/signal-cli
12
+ *
13
+ * The adapter supports two operation modes:
14
+ * 1. **Subprocess mode** (default): Invokes signal-cli per command.
15
+ * 2. **JSON-RPC daemon mode**: Connects to a running signal-cli
16
+ * daemon for lower latency. Enabled when `daemonSocket` param
17
+ * is provided.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const signal = new SignalChannelAdapter();
22
+ * await signal.initialize({
23
+ * platform: 'signal',
24
+ * credential: '+1234567890', // registered phone number
25
+ * params: {
26
+ * signalCliPath: '/usr/local/bin/signal-cli',
27
+ * configDir: '/home/agent/.local/share/signal-cli',
28
+ * },
29
+ * });
30
+ * ```
31
+ *
32
+ * @module @framers/agentos/channels/adapters/SignalChannelAdapter
33
+ */
34
+ import type { ChannelAuthConfig, ChannelCapability, ChannelPlatform, ChannelSendResult, MessageContent } from '../types.js';
35
+ import { BaseChannelAdapter } from './BaseChannelAdapter.js';
36
+ /** Platform-specific authentication parameters for Signal. */
37
+ export interface SignalAuthParams extends Record<string, string | undefined> {
38
+ /** Path to the signal-cli binary. Default: 'signal-cli'. */
39
+ signalCliPath?: string;
40
+ /** Path to signal-cli config/data directory. */
41
+ configDir?: string;
42
+ /** Unix socket or TCP address of signal-cli JSON-RPC daemon. */
43
+ daemonSocket?: string;
44
+ /** Trust mode for new identities: 'always', 'on-first-use', 'never'. Default: 'on-first-use'. */
45
+ trustMode?: string;
46
+ }
47
+ /**
48
+ * Channel adapter for the Signal messaging protocol via signal-cli.
49
+ *
50
+ * Capabilities: `text`, `images`, `audio`, `voice_notes`,
51
+ * `documents`, `reactions`, `group_chat`.
52
+ *
53
+ * Conversation ID mapping:
54
+ * - Direct message: phone number (e.g., '+1234567890')
55
+ * - Group: group ID in base64 format, prefixed with 'group:'
56
+ */
57
+ export declare class SignalChannelAdapter extends BaseChannelAdapter<SignalAuthParams> {
58
+ readonly platform: ChannelPlatform;
59
+ readonly displayName = "Signal";
60
+ readonly capabilities: readonly ChannelCapability[];
61
+ /** Path to signal-cli binary. */
62
+ private signalCliPath;
63
+ /** Registered phone number (account identifier). */
64
+ private phoneNumber;
65
+ /** Config directory for signal-cli. */
66
+ private configDir;
67
+ /** Trust mode for unknown identities. */
68
+ private trustMode;
69
+ /** JSON-RPC daemon connection (if using daemon mode). */
70
+ private daemonSocket;
71
+ private daemonConnection;
72
+ /** Polling process for receiving messages. */
73
+ private receiveProcess;
74
+ private pollTimer;
75
+ protected doConnect(auth: ChannelAuthConfig & {
76
+ params?: SignalAuthParams;
77
+ }): Promise<void>;
78
+ protected doSendMessage(conversationId: string, content: MessageContent): Promise<ChannelSendResult>;
79
+ protected doShutdown(): Promise<void>;
80
+ /**
81
+ * Send a reaction to a message.
82
+ *
83
+ * @param conversationId - Target conversation (phone number or group:id).
84
+ * @param targetAuthor - Phone number of the message author being reacted to.
85
+ * @param targetTimestamp - Timestamp of the target message (Signal's message ID).
86
+ * @param emoji - The reaction emoji.
87
+ */
88
+ sendReaction(conversationId: string, targetAuthor: string, targetTimestamp: string, emoji: string): Promise<void>;
89
+ /**
90
+ * List groups the account is a member of.
91
+ */
92
+ listGroups(): Promise<Array<{
93
+ id: string;
94
+ name: string;
95
+ members: string[];
96
+ }>>;
97
+ /**
98
+ * Mark messages as read (send read receipt).
99
+ */
100
+ markAsRead(senderNumber: string, timestamps: string[]): Promise<void>;
101
+ private verifySignalCli;
102
+ private verifyAccount;
103
+ /**
104
+ * Execute a signal-cli command and return stdout.
105
+ */
106
+ private execSignalCli;
107
+ private connectDaemon;
108
+ private handleDaemonData;
109
+ private startReceivePolling;
110
+ private receiveMessages;
111
+ private processSignalEvent;
112
+ private extractText;
113
+ /**
114
+ * Extract file paths from attachment blocks. For Signal, URLs
115
+ * must be local file paths (signal-cli does not support remote URLs
116
+ * directly — the caller must download first).
117
+ */
118
+ private extractAttachmentPaths;
119
+ }
120
+ //# sourceMappingURL=SignalChannelAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SignalChannelAdapter.d.ts","sourceRoot":"","sources":["../../../src/channels/adapters/SignalChannelAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EAEjB,eAAe,EACf,iBAAiB,EACjB,cAAc,EAEf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAM7D,8DAA8D;AAC9D,MAAM,WAAW,gBAAiB,SAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1E,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;;;;;GASG;AACH,qBAAa,oBAAqB,SAAQ,kBAAkB,CAAC,gBAAgB,CAAC;IAC5E,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAY;IAC9C,QAAQ,CAAC,WAAW,YAAY;IAChC,QAAQ,CAAC,YAAY,EAAE,SAAS,iBAAiB,EAAE,CAQxC;IAEX,iCAAiC;IACjC,OAAO,CAAC,aAAa,CAAgB;IAErC,oDAAoD;IACpD,OAAO,CAAC,WAAW,CAAqB;IAExC,uCAAuC;IACvC,OAAO,CAAC,SAAS,CAAqB;IAEtC,yCAAyC;IACzC,OAAO,CAAC,SAAS,CAAuD;IAExE,yDAAyD;IACzD,OAAO,CAAC,YAAY,CAAqB;IAEzC,OAAO,CAAC,gBAAgB,CAAkB;IAE1C,8CAA8C;IAE9C,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,SAAS,CAA6C;cAI9C,SAAS,CACvB,IAAI,EAAE,iBAAiB,GAAG;QAAE,MAAM,CAAC,EAAE,gBAAgB,CAAA;KAAE,GACtD,OAAO,CAAC,IAAI,CAAC;cAyCA,aAAa,CAC3B,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,iBAAiB,CAAC;cA+Cb,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAkC3C;;;;;;;OAOG;IACG,YAAY,CAChB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC;IAoBhB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAkBnF;;OAEG;IACG,UAAU,CACd,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAAE,GACnB,OAAO,CAAC,IAAI,CAAC;YAWF,eAAe;YAaf,aAAa;IAkB3B;;OAEG;YACW,aAAa;YA+Cb,aAAa;IAuC3B,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,mBAAmB;YAYb,eAAe;IAoC7B,OAAO,CAAC,kBAAkB;IAkH1B,OAAO,CAAC,WAAW;IAOnB;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;CAyB/B"}