@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.
- package/dist/api/AgentOSOrchestrator.js +1 -1
- package/dist/api/AgentOSOrchestrator.js.map +1 -1
- package/dist/channels/ChannelRouter.d.ts.map +1 -1
- package/dist/channels/ChannelRouter.js +1 -1
- package/dist/channels/ChannelRouter.js.map +1 -1
- package/dist/channels/IChannelAdapter.d.ts.map +1 -1
- package/dist/channels/adapters/BaseChannelAdapter.d.ts +130 -0
- package/dist/channels/adapters/BaseChannelAdapter.d.ts.map +1 -0
- package/dist/channels/adapters/BaseChannelAdapter.js +257 -0
- package/dist/channels/adapters/BaseChannelAdapter.js.map +1 -0
- package/dist/channels/adapters/DiscordChannelAdapter.d.ts +86 -0
- package/dist/channels/adapters/DiscordChannelAdapter.d.ts.map +1 -0
- package/dist/channels/adapters/DiscordChannelAdapter.js +550 -0
- package/dist/channels/adapters/DiscordChannelAdapter.js.map +1 -0
- package/dist/channels/adapters/GoogleChatChannelAdapter.d.ts +117 -0
- package/dist/channels/adapters/GoogleChatChannelAdapter.d.ts.map +1 -0
- package/dist/channels/adapters/GoogleChatChannelAdapter.js +632 -0
- package/dist/channels/adapters/GoogleChatChannelAdapter.js.map +1 -0
- package/dist/channels/adapters/IRCChannelAdapter.d.ts +86 -0
- package/dist/channels/adapters/IRCChannelAdapter.d.ts.map +1 -0
- package/dist/channels/adapters/IRCChannelAdapter.js +253 -0
- package/dist/channels/adapters/IRCChannelAdapter.js.map +1 -0
- package/dist/channels/adapters/RedditChannelAdapter.d.ts +123 -0
- package/dist/channels/adapters/RedditChannelAdapter.d.ts.map +1 -0
- package/dist/channels/adapters/RedditChannelAdapter.js +516 -0
- package/dist/channels/adapters/RedditChannelAdapter.js.map +1 -0
- package/dist/channels/adapters/SignalChannelAdapter.d.ts +120 -0
- package/dist/channels/adapters/SignalChannelAdapter.d.ts.map +1 -0
- package/dist/channels/adapters/SignalChannelAdapter.js +521 -0
- package/dist/channels/adapters/SignalChannelAdapter.js.map +1 -0
- package/dist/channels/adapters/SlackChannelAdapter.d.ts +96 -0
- package/dist/channels/adapters/SlackChannelAdapter.d.ts.map +1 -0
- package/dist/channels/adapters/SlackChannelAdapter.js +535 -0
- package/dist/channels/adapters/SlackChannelAdapter.js.map +1 -0
- package/dist/channels/adapters/TeamsChannelAdapter.d.ts +138 -0
- package/dist/channels/adapters/TeamsChannelAdapter.d.ts.map +1 -0
- package/dist/channels/adapters/TeamsChannelAdapter.js +639 -0
- package/dist/channels/adapters/TeamsChannelAdapter.js.map +1 -0
- package/dist/channels/adapters/TelegramChannelAdapter.d.ts +83 -0
- package/dist/channels/adapters/TelegramChannelAdapter.d.ts.map +1 -0
- package/dist/channels/adapters/TelegramChannelAdapter.js +463 -0
- package/dist/channels/adapters/TelegramChannelAdapter.js.map +1 -0
- package/dist/channels/adapters/TwitterChannelAdapter.d.ts +117 -0
- package/dist/channels/adapters/TwitterChannelAdapter.d.ts.map +1 -0
- package/dist/channels/adapters/TwitterChannelAdapter.js +489 -0
- package/dist/channels/adapters/TwitterChannelAdapter.js.map +1 -0
- package/dist/channels/adapters/WebChatChannelAdapter.d.ts +141 -0
- package/dist/channels/adapters/WebChatChannelAdapter.d.ts.map +1 -0
- package/dist/channels/adapters/WebChatChannelAdapter.js +539 -0
- package/dist/channels/adapters/WebChatChannelAdapter.js.map +1 -0
- package/dist/channels/adapters/WhatsAppChannelAdapter.d.ts +122 -0
- package/dist/channels/adapters/WhatsAppChannelAdapter.d.ts.map +1 -0
- package/dist/channels/adapters/WhatsAppChannelAdapter.js +643 -0
- package/dist/channels/adapters/WhatsAppChannelAdapter.js.map +1 -0
- package/dist/channels/adapters/index.d.ts +34 -0
- package/dist/channels/adapters/index.d.ts.map +1 -0
- package/dist/channels/adapters/index.js +25 -0
- package/dist/channels/adapters/index.js.map +1 -0
- package/dist/channels/index.d.ts +24 -0
- package/dist/channels/index.d.ts.map +1 -1
- package/dist/channels/index.js +16 -0
- package/dist/channels/index.js.map +1 -1
- package/dist/cognitive_substrate/personas/metaprompt_presets.d.ts.map +1 -1
- package/dist/cognitive_substrate/personas/metaprompt_presets.js +0 -2
- package/dist/cognitive_substrate/personas/metaprompt_presets.js.map +1 -1
- package/dist/core/provenance/crypto/HashChain.d.ts.map +1 -1
- package/dist/core/provenance/enforcement/AutonomyGuard.d.ts.map +1 -1
- package/dist/core/provenance/enforcement/ProvenanceStorageHooks.d.ts.map +1 -1
- package/dist/core/provenance/enforcement/ProvenanceStorageHooks.js +2 -1
- package/dist/core/provenance/enforcement/ProvenanceStorageHooks.js.map +1 -1
- package/dist/core/provenance/ledger/EventTypes.d.ts.map +1 -1
- package/dist/core/safety/ToolExecutionGuard.d.ts.map +1 -1
- package/dist/core/safety/ToolExecutionGuard.js +0 -1
- package/dist/core/safety/ToolExecutionGuard.js.map +1 -1
- package/dist/extensions/ExtensionManager.d.ts.map +1 -1
- package/dist/extensions/ExtensionManager.js +3 -9
- package/dist/extensions/ExtensionManager.js.map +1 -1
- package/dist/rag/RetrievalAugmentor.js.map +1 -1
- 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"}
|