@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,117 @@
1
+ /**
2
+ * @fileoverview Twitter / X Channel Adapter for AgentOS.
3
+ *
4
+ * Wraps the Twitter API v2 to allow agents to post tweets, send DMs,
5
+ * and interact with the Twitter platform. Uses the `twitter-api-v2`
6
+ * npm package via dynamic import.
7
+ *
8
+ * **Rate limiting** is a critical concern for Twitter. The adapter
9
+ * tracks remaining rate-limit budget from response headers and will
10
+ * queue or reject requests when the budget is exhausted. A sliding
11
+ * window ensures the agent does not trip 429 responses.
12
+ *
13
+ * **Dependencies**: Requires `twitter-api-v2` to be installed.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const twitter = new TwitterChannelAdapter();
18
+ * await twitter.initialize({
19
+ * platform: 'twitter',
20
+ * credential: '<bearer_token>',
21
+ * params: {
22
+ * apiKey: 'consumer-key',
23
+ * apiSecret: 'consumer-secret',
24
+ * accessToken: 'user-access-token',
25
+ * accessSecret: 'user-access-token-secret',
26
+ * },
27
+ * });
28
+ * ```
29
+ *
30
+ * @module @framers/agentos/channels/adapters/TwitterChannelAdapter
31
+ */
32
+ import type { ChannelAuthConfig, ChannelCapability, ChannelPlatform, ChannelSendResult, MessageContent } from '../types.js';
33
+ import { BaseChannelAdapter } from './BaseChannelAdapter.js';
34
+ /** Platform-specific authentication parameters for Twitter API v2. */
35
+ export interface TwitterAuthParams extends Record<string, string | undefined> {
36
+ /** Consumer / API key. */
37
+ apiKey: string;
38
+ /** Consumer / API secret. */
39
+ apiSecret: string;
40
+ /** User-level access token for read/write operations. */
41
+ accessToken: string;
42
+ /** User-level access token secret. */
43
+ accessSecret: string;
44
+ }
45
+ /**
46
+ * Channel adapter for Twitter / X.
47
+ *
48
+ * Uses the `twitter-api-v2` package via dynamic import so the
49
+ * dependency is optional -- it is only loaded at connection time.
50
+ *
51
+ * Capabilities: `text`, `images`, `video`, `hashtags`, `mentions`,
52
+ * `threads`, `reactions`, `polls`.
53
+ */
54
+ export declare class TwitterChannelAdapter extends BaseChannelAdapter<TwitterAuthParams> {
55
+ readonly platform: ChannelPlatform;
56
+ readonly displayName = "Twitter / X";
57
+ readonly capabilities: readonly ChannelCapability[];
58
+ private client;
59
+ private rwClient;
60
+ /** Authenticated user info. */
61
+ private authenticatedUser;
62
+ /** Rate-limit tracking per endpoint group. */
63
+ private rateLimits;
64
+ /** Polling interval for mentions/DMs (ms). */
65
+ private pollTimer;
66
+ private lastMentionId;
67
+ private lastDmEventId;
68
+ protected doConnect(auth: ChannelAuthConfig & {
69
+ params?: TwitterAuthParams;
70
+ }): Promise<void>;
71
+ protected doSendMessage(conversationId: string, content: MessageContent): Promise<ChannelSendResult>;
72
+ protected doShutdown(): Promise<void>;
73
+ /**
74
+ * Post a tweet (public timeline post).
75
+ *
76
+ * @param content - Message content to tweet.
77
+ * @param replyToTweetId - If provided, the tweet will be a reply in a thread.
78
+ */
79
+ postTweet(content: MessageContent, replyToTweetId?: string): Promise<ChannelSendResult>;
80
+ /**
81
+ * Post a thread (sequence of connected tweets).
82
+ */
83
+ postThread(tweets: MessageContent[]): Promise<ChannelSendResult[]>;
84
+ /**
85
+ * Like (favorite) a tweet.
86
+ */
87
+ likeTweet(tweetId: string): Promise<void>;
88
+ /**
89
+ * Retweet a tweet.
90
+ */
91
+ retweet(tweetId: string): Promise<void>;
92
+ /**
93
+ * Get the authenticated user information.
94
+ */
95
+ getAuthenticatedUser(): {
96
+ id: string;
97
+ username: string;
98
+ name: string;
99
+ } | undefined;
100
+ private sendDirectMessage;
101
+ private uploadMediaFromBlocks;
102
+ private extractText;
103
+ private hasMediaBlocks;
104
+ /**
105
+ * Truncate text to fit Twitter's character limit.
106
+ * If truncation is needed, append an ellipsis.
107
+ */
108
+ private truncateToLimit;
109
+ private checkRateLimit;
110
+ private updateRateLimit;
111
+ private handleApiError;
112
+ private startPolling;
113
+ private stopPolling;
114
+ private pollMentions;
115
+ private pollDirectMessages;
116
+ }
117
+ //# sourceMappingURL=TwitterChannelAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TwitterChannelAdapter.d.ts","sourceRoot":"","sources":["../../../src/channels/adapters/TwitterChannelAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;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,sEAAsE;AACtE,MAAM,WAAW,iBAAkB,SAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3E,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;CACtB;AAkBD;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,SAAQ,kBAAkB,CAAC,iBAAiB,CAAC;IAC9E,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAa;IAC/C,QAAQ,CAAC,WAAW,iBAAiB;IACrC,QAAQ,CAAC,YAAY,EAAE,SAAS,iBAAiB,EAAE,CASxC;IAGX,OAAO,CAAC,MAAM,CAAkB;IAEhC,OAAO,CAAC,QAAQ,CAAkB;IAElC,+BAA+B;IAC/B,OAAO,CAAC,iBAAiB,CAA6D;IAEtF,8CAA8C;IAC9C,OAAO,CAAC,UAAU,CAA2C;IAE7D,8CAA8C;IAC9C,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,aAAa,CAAqB;cAI1B,SAAS,CACvB,IAAI,EAAE,iBAAiB,GAAG;QAAE,MAAM,CAAC,EAAE,iBAAiB,CAAA;KAAE,GACvD,OAAO,CAAC,IAAI,CAAC;cA2DA,aAAa,CAC3B,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,iBAAiB,CAAC;cAgBb,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3C;;;;;OAKG;IACG,SAAS,CACb,OAAO,EAAE,cAAc,EACvB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,iBAAiB,CAAC;IAmD7B;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAgBxE;;OAEG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe/C;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe7C;;OAEG;IACH,oBAAoB,IAAI;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;YAMpE,iBAAiB;YAuCjB,qBAAqB;IAqBnC,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,cAAc;IAItB;;;OAGG;IACH,OAAO,CAAC,eAAe;YAOT,cAAc;IAyB5B,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,cAAc;IAgBtB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,WAAW;YAOL,YAAY;YAyEZ,kBAAkB;CAqDjC"}
@@ -0,0 +1,489 @@
1
+ /**
2
+ * @fileoverview Twitter / X Channel Adapter for AgentOS.
3
+ *
4
+ * Wraps the Twitter API v2 to allow agents to post tweets, send DMs,
5
+ * and interact with the Twitter platform. Uses the `twitter-api-v2`
6
+ * npm package via dynamic import.
7
+ *
8
+ * **Rate limiting** is a critical concern for Twitter. The adapter
9
+ * tracks remaining rate-limit budget from response headers and will
10
+ * queue or reject requests when the budget is exhausted. A sliding
11
+ * window ensures the agent does not trip 429 responses.
12
+ *
13
+ * **Dependencies**: Requires `twitter-api-v2` to be installed.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const twitter = new TwitterChannelAdapter();
18
+ * await twitter.initialize({
19
+ * platform: 'twitter',
20
+ * credential: '<bearer_token>',
21
+ * params: {
22
+ * apiKey: 'consumer-key',
23
+ * apiSecret: 'consumer-secret',
24
+ * accessToken: 'user-access-token',
25
+ * accessSecret: 'user-access-token-secret',
26
+ * },
27
+ * });
28
+ * ```
29
+ *
30
+ * @module @framers/agentos/channels/adapters/TwitterChannelAdapter
31
+ */
32
+ import { BaseChannelAdapter } from './BaseChannelAdapter.js';
33
+ // ============================================================================
34
+ // TwitterChannelAdapter
35
+ // ============================================================================
36
+ /**
37
+ * Channel adapter for Twitter / X.
38
+ *
39
+ * Uses the `twitter-api-v2` package via dynamic import so the
40
+ * dependency is optional -- it is only loaded at connection time.
41
+ *
42
+ * Capabilities: `text`, `images`, `video`, `hashtags`, `mentions`,
43
+ * `threads`, `reactions`, `polls`.
44
+ */
45
+ export class TwitterChannelAdapter extends BaseChannelAdapter {
46
+ constructor() {
47
+ super(...arguments);
48
+ this.platform = 'twitter';
49
+ this.displayName = 'Twitter / X';
50
+ this.capabilities = [
51
+ 'text',
52
+ 'images',
53
+ 'video',
54
+ 'hashtags',
55
+ 'mentions',
56
+ 'threads',
57
+ 'reactions',
58
+ 'polls',
59
+ ];
60
+ /** Rate-limit tracking per endpoint group. */
61
+ this.rateLimits = new Map();
62
+ }
63
+ // ── Abstract hook implementations ──
64
+ async doConnect(auth) {
65
+ // Dynamic import
66
+ let TwitterApi; // eslint-disable-line @typescript-eslint/no-explicit-any
67
+ try {
68
+ const mod = await import('twitter-api-v2');
69
+ TwitterApi = mod.TwitterApi ?? mod.default?.TwitterApi ?? mod.default;
70
+ }
71
+ catch {
72
+ throw new Error('The "twitter-api-v2" package is required for the Twitter adapter. ' +
73
+ 'Install it with: npm install twitter-api-v2');
74
+ }
75
+ const params = auth.params ?? {};
76
+ if (!params.apiKey || !params.apiSecret) {
77
+ throw new Error('Twitter auth params must include "apiKey" and "apiSecret".');
78
+ }
79
+ if (!params.accessToken || !params.accessSecret) {
80
+ throw new Error('Twitter auth params must include "accessToken" and "accessSecret".');
81
+ }
82
+ // Create the client with user-context OAuth 1.0a credentials
83
+ this.client = new TwitterApi({
84
+ appKey: params.apiKey,
85
+ appSecret: params.apiSecret,
86
+ accessToken: params.accessToken,
87
+ accessSecret: params.accessSecret,
88
+ });
89
+ // Get the read-write client
90
+ this.rwClient = this.client.readWrite;
91
+ // Verify credentials by fetching the authenticated user
92
+ try {
93
+ const me = await this.rwClient.v2.me({
94
+ 'user.fields': ['id', 'username', 'name', 'profile_image_url'],
95
+ });
96
+ this.authenticatedUser = {
97
+ id: me.data.id,
98
+ username: me.data.username,
99
+ name: me.data.name,
100
+ };
101
+ }
102
+ catch (err) {
103
+ const message = err instanceof Error ? err.message : String(err);
104
+ throw new Error(`Twitter credential verification failed: ${message}`);
105
+ }
106
+ // Populate platform info
107
+ this.platformInfo = {
108
+ userId: this.authenticatedUser.id,
109
+ username: this.authenticatedUser.username,
110
+ displayName: this.authenticatedUser.name,
111
+ };
112
+ // Start polling for mentions and DMs
113
+ this.startPolling();
114
+ }
115
+ async doSendMessage(conversationId, content) {
116
+ if (!this.rwClient) {
117
+ throw new Error('[Twitter] Client is not connected.');
118
+ }
119
+ // Determine if this is a DM or a tweet
120
+ // Convention: conversationId starting with "dm:" indicates a DM target user ID
121
+ const isDm = conversationId.startsWith('dm:');
122
+ if (isDm) {
123
+ return this.sendDirectMessage(conversationId.slice(3), content);
124
+ }
125
+ return this.postTweet(content, conversationId);
126
+ }
127
+ async doShutdown() {
128
+ this.stopPolling();
129
+ this.client = undefined;
130
+ this.rwClient = undefined;
131
+ this.authenticatedUser = undefined;
132
+ this.rateLimits.clear();
133
+ this.lastMentionId = undefined;
134
+ this.lastDmEventId = undefined;
135
+ }
136
+ // ── Twitter-specific public methods ──
137
+ /**
138
+ * Post a tweet (public timeline post).
139
+ *
140
+ * @param content - Message content to tweet.
141
+ * @param replyToTweetId - If provided, the tweet will be a reply in a thread.
142
+ */
143
+ async postTweet(content, replyToTweetId) {
144
+ await this.checkRateLimit('tweets');
145
+ const text = this.extractText(content.blocks);
146
+ if (!text && !this.hasMediaBlocks(content.blocks)) {
147
+ throw new Error('[Twitter] Cannot post empty tweet.');
148
+ }
149
+ // Build tweet payload
150
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
151
+ const tweetPayload = {};
152
+ if (text) {
153
+ tweetPayload.text = this.truncateToLimit(text, 280);
154
+ }
155
+ // Handle reply threading
156
+ const replyTo = replyToTweetId || content.replyToMessageId;
157
+ if (replyTo) {
158
+ tweetPayload.reply = { in_reply_to_tweet_id: replyTo };
159
+ }
160
+ // Handle poll content blocks
161
+ const pollBlock = content.blocks.find((b) => b.type === 'poll');
162
+ if (pollBlock && pollBlock.type === 'poll') {
163
+ tweetPayload.poll = {
164
+ options: pollBlock.options.slice(0, 4), // Twitter max 4 options
165
+ duration_minutes: (pollBlock.durationHours ?? 24) * 60,
166
+ };
167
+ }
168
+ // Upload media if present
169
+ const mediaIds = await this.uploadMediaFromBlocks(content.blocks);
170
+ if (mediaIds.length > 0) {
171
+ tweetPayload.media = { media_ids: mediaIds.slice(0, 4) }; // Max 4 media per tweet
172
+ }
173
+ try {
174
+ const result = await this.rwClient.v2.tweet(tweetPayload);
175
+ this.updateRateLimit('tweets', result);
176
+ return {
177
+ messageId: result.data.id,
178
+ timestamp: new Date().toISOString(),
179
+ };
180
+ }
181
+ catch (err) {
182
+ this.handleApiError(err, 'tweet');
183
+ throw err; // re-throw after handling
184
+ }
185
+ }
186
+ /**
187
+ * Post a thread (sequence of connected tweets).
188
+ */
189
+ async postThread(tweets) {
190
+ const results = [];
191
+ let lastTweetId;
192
+ for (const tweet of tweets) {
193
+ if (lastTweetId) {
194
+ tweet.replyToMessageId = lastTweetId;
195
+ }
196
+ const result = await this.postTweet(tweet, lastTweetId);
197
+ results.push(result);
198
+ lastTweetId = result.messageId;
199
+ }
200
+ return results;
201
+ }
202
+ /**
203
+ * Like (favorite) a tweet.
204
+ */
205
+ async likeTweet(tweetId) {
206
+ if (!this.rwClient || !this.authenticatedUser) {
207
+ throw new Error('[Twitter] Client is not connected.');
208
+ }
209
+ await this.checkRateLimit('likes');
210
+ try {
211
+ await this.rwClient.v2.like(this.authenticatedUser.id, tweetId);
212
+ }
213
+ catch (err) {
214
+ this.handleApiError(err, 'like');
215
+ throw err;
216
+ }
217
+ }
218
+ /**
219
+ * Retweet a tweet.
220
+ */
221
+ async retweet(tweetId) {
222
+ if (!this.rwClient || !this.authenticatedUser) {
223
+ throw new Error('[Twitter] Client is not connected.');
224
+ }
225
+ await this.checkRateLimit('retweets');
226
+ try {
227
+ await this.rwClient.v2.retweet(this.authenticatedUser.id, tweetId);
228
+ }
229
+ catch (err) {
230
+ this.handleApiError(err, 'retweet');
231
+ throw err;
232
+ }
233
+ }
234
+ /**
235
+ * Get the authenticated user information.
236
+ */
237
+ getAuthenticatedUser() {
238
+ return this.authenticatedUser ? { ...this.authenticatedUser } : undefined;
239
+ }
240
+ // ── Private helpers ──
241
+ async sendDirectMessage(recipientUserId, content) {
242
+ await this.checkRateLimit('dm');
243
+ const text = this.extractText(content.blocks);
244
+ if (!text) {
245
+ throw new Error('[Twitter] DM text content is required.');
246
+ }
247
+ try {
248
+ const result = await this.rwClient.v2.sendDmInConversation(recipientUserId, { text });
249
+ return {
250
+ messageId: result.data?.dm_event_id ?? `dm-${Date.now()}`,
251
+ timestamp: new Date().toISOString(),
252
+ };
253
+ }
254
+ catch (err) {
255
+ // Fallback: try creating a new DM conversation
256
+ try {
257
+ const result = await this.rwClient.v2.sendDmToParticipant(recipientUserId, { text });
258
+ return {
259
+ messageId: result.data?.dm_event_id ?? `dm-${Date.now()}`,
260
+ timestamp: new Date().toISOString(),
261
+ };
262
+ }
263
+ catch (innerErr) {
264
+ this.handleApiError(innerErr, 'dm');
265
+ throw innerErr;
266
+ }
267
+ }
268
+ }
269
+ async uploadMediaFromBlocks(blocks) {
270
+ const mediaIds = [];
271
+ for (const block of blocks) {
272
+ if (block.type === 'image' || block.type === 'video') {
273
+ try {
274
+ // twitter-api-v2 supports uploading from URL via v1.1 media upload
275
+ const mediaId = await this.rwClient.v1.uploadMedia(block.url, {
276
+ mimeType: block.mimeType,
277
+ });
278
+ mediaIds.push(mediaId);
279
+ }
280
+ catch (err) {
281
+ console.warn(`[Twitter] Failed to upload media: ${err}`);
282
+ // Non-fatal: skip this media block
283
+ }
284
+ }
285
+ }
286
+ return mediaIds;
287
+ }
288
+ extractText(blocks) {
289
+ const textParts = [];
290
+ for (const block of blocks) {
291
+ if (block.type === 'text') {
292
+ textParts.push(block.text);
293
+ }
294
+ }
295
+ return textParts.join('\n');
296
+ }
297
+ hasMediaBlocks(blocks) {
298
+ return blocks.some((b) => b.type === 'image' || b.type === 'video');
299
+ }
300
+ /**
301
+ * Truncate text to fit Twitter's character limit.
302
+ * If truncation is needed, append an ellipsis.
303
+ */
304
+ truncateToLimit(text, limit) {
305
+ if (text.length <= limit)
306
+ return text;
307
+ return text.slice(0, limit - 1) + '\u2026';
308
+ }
309
+ // ── Rate limiting ──
310
+ async checkRateLimit(bucket) {
311
+ const limit = this.rateLimits.get(bucket);
312
+ if (!limit)
313
+ return; // No data yet — allow the request
314
+ const now = Math.floor(Date.now() / 1000);
315
+ if (limit.remaining <= 0 && now < limit.resetAt) {
316
+ const waitMs = (limit.resetAt - now) * 1000 + 1000; // +1s buffer
317
+ console.warn(`[Twitter] Rate limit exhausted for "${bucket}". ` +
318
+ `Waiting ${Math.round(waitMs / 1000)}s until reset.`);
319
+ if (waitMs > 60000) {
320
+ throw new Error(`[Twitter] Rate limit for "${bucket}" resets in ${Math.round(waitMs / 1000)}s. ` +
321
+ 'Request rejected to avoid excessive wait.');
322
+ }
323
+ await new Promise((resolve) => setTimeout(resolve, waitMs));
324
+ }
325
+ }
326
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
327
+ updateRateLimit(bucket, apiResponse) {
328
+ // twitter-api-v2 includes rate limit info in the response headers
329
+ // when available. The shape depends on the endpoint.
330
+ try {
331
+ const rateLimit = apiResponse?.rateLimit;
332
+ if (rateLimit) {
333
+ this.rateLimits.set(bucket, {
334
+ remaining: rateLimit.remaining ?? 0,
335
+ resetAt: rateLimit.reset ?? Math.floor(Date.now() / 1000) + 900,
336
+ });
337
+ }
338
+ }
339
+ catch {
340
+ // Non-fatal — rate limit tracking is best-effort
341
+ }
342
+ }
343
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
344
+ handleApiError(err, operation) {
345
+ // Check for rate limit errors (HTTP 429)
346
+ if (err?.code === 429 || err?.rateLimitError) {
347
+ const resetAt = err?.rateLimit?.reset ?? Math.floor(Date.now() / 1000) + 900;
348
+ this.rateLimits.set(operation, { remaining: 0, resetAt });
349
+ console.error(`[Twitter] Rate limited on "${operation}". Resets at ${new Date(resetAt * 1000).toISOString()}.`);
350
+ }
351
+ else {
352
+ const message = err instanceof Error ? err.message : String(err);
353
+ console.error(`[Twitter] API error during "${operation}": ${message}`);
354
+ }
355
+ }
356
+ // ── Polling for inbound events ──
357
+ startPolling() {
358
+ // Poll every 60 seconds for mentions and DMs
359
+ // Twitter API v2 free tier has very limited polling budget
360
+ this.pollTimer = setInterval(() => {
361
+ this.pollMentions().catch((err) => {
362
+ console.warn('[Twitter] Mention poll error:', err);
363
+ });
364
+ this.pollDirectMessages().catch((err) => {
365
+ console.warn('[Twitter] DM poll error:', err);
366
+ });
367
+ }, 60000);
368
+ }
369
+ stopPolling() {
370
+ if (this.pollTimer) {
371
+ clearInterval(this.pollTimer);
372
+ this.pollTimer = undefined;
373
+ }
374
+ }
375
+ async pollMentions() {
376
+ if (!this.rwClient || !this.authenticatedUser)
377
+ return;
378
+ try {
379
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
380
+ const params = {
381
+ 'tweet.fields': ['created_at', 'author_id', 'conversation_id', 'in_reply_to_user_id'],
382
+ 'user.fields': ['username', 'name', 'profile_image_url'],
383
+ expansions: ['author_id'],
384
+ max_results: 10,
385
+ };
386
+ if (this.lastMentionId) {
387
+ params.since_id = this.lastMentionId;
388
+ }
389
+ const mentions = await this.rwClient.v2.userMentionTimeline(this.authenticatedUser.id, params);
390
+ if (!mentions?.data?.data)
391
+ return;
392
+ // Build a user lookup from includes
393
+ const usersMap = new Map();
394
+ if (mentions.data.includes?.users) {
395
+ for (const u of mentions.data.includes.users) {
396
+ usersMap.set(u.id, { username: u.username, name: u.name });
397
+ }
398
+ }
399
+ for (const tweet of mentions.data.data) {
400
+ const user = usersMap.get(tweet.author_id) ?? {
401
+ username: 'unknown',
402
+ name: 'Unknown',
403
+ };
404
+ const message = {
405
+ messageId: tweet.id,
406
+ platform: 'twitter',
407
+ conversationId: tweet.conversation_id ?? tweet.id,
408
+ conversationType: 'channel', // Public timeline
409
+ sender: {
410
+ id: tweet.author_id,
411
+ displayName: user.name,
412
+ username: user.username,
413
+ },
414
+ content: [{ type: 'text', text: tweet.text }],
415
+ text: tweet.text,
416
+ timestamp: tweet.created_at ?? new Date().toISOString(),
417
+ replyToMessageId: tweet.in_reply_to_user_id ? tweet.conversation_id : undefined,
418
+ rawEvent: tweet,
419
+ };
420
+ this.emit({
421
+ type: 'message',
422
+ platform: 'twitter',
423
+ conversationId: message.conversationId,
424
+ timestamp: message.timestamp,
425
+ data: message,
426
+ });
427
+ // Track the latest mention ID for pagination
428
+ if (!this.lastMentionId || tweet.id > this.lastMentionId) {
429
+ this.lastMentionId = tweet.id;
430
+ }
431
+ }
432
+ }
433
+ catch (err) {
434
+ // Non-fatal — will retry on next poll
435
+ this.handleApiError(err, 'mentions_poll');
436
+ }
437
+ }
438
+ async pollDirectMessages() {
439
+ if (!this.rwClient || !this.authenticatedUser)
440
+ return;
441
+ try {
442
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
443
+ const params = {
444
+ 'dm_event.fields': ['created_at', 'sender_id', 'dm_conversation_id', 'text', 'attachments'],
445
+ max_results: 10,
446
+ };
447
+ const events = await this.rwClient.v2.listDmEvents(params);
448
+ if (!events?.data?.data)
449
+ return;
450
+ for (const dmEvent of events.data.data) {
451
+ // Skip our own messages
452
+ if (dmEvent.sender_id === this.authenticatedUser?.id)
453
+ continue;
454
+ // Skip already-processed events
455
+ if (this.lastDmEventId && dmEvent.id <= this.lastDmEventId)
456
+ continue;
457
+ const message = {
458
+ messageId: dmEvent.id,
459
+ platform: 'twitter',
460
+ conversationId: `dm:${dmEvent.dm_conversation_id ?? dmEvent.sender_id}`,
461
+ conversationType: 'direct',
462
+ sender: {
463
+ id: dmEvent.sender_id,
464
+ username: dmEvent.sender_id, // Would need a user lookup for username
465
+ },
466
+ content: [{ type: 'text', text: dmEvent.text ?? '' }],
467
+ text: dmEvent.text ?? '',
468
+ timestamp: dmEvent.created_at ?? new Date().toISOString(),
469
+ rawEvent: dmEvent,
470
+ };
471
+ this.emit({
472
+ type: 'message',
473
+ platform: 'twitter',
474
+ conversationId: message.conversationId,
475
+ timestamp: message.timestamp,
476
+ data: message,
477
+ });
478
+ if (!this.lastDmEventId || dmEvent.id > this.lastDmEventId) {
479
+ this.lastDmEventId = dmEvent.id;
480
+ }
481
+ }
482
+ }
483
+ catch (err) {
484
+ // Non-fatal — will retry on next poll
485
+ this.handleApiError(err, 'dm_poll');
486
+ }
487
+ }
488
+ }
489
+ //# sourceMappingURL=TwitterChannelAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TwitterChannelAdapter.js","sourceRoot":"","sources":["../../../src/channels/adapters/TwitterChannelAdapter.ts"],"names":[],"mappings":"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"}