@cogitator-ai/channels 0.9.3 → 0.10.1
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/README.md +101 -11
- package/dist/assistant-config.d.ts +16 -0
- package/dist/assistant-config.d.ts.map +1 -1
- package/dist/assistant-config.js +22 -0
- package/dist/assistant-config.js.map +1 -1
- package/dist/channels/bluesky/account.d.ts +18 -0
- package/dist/channels/bluesky/account.d.ts.map +1 -0
- package/dist/channels/bluesky/account.js +25 -0
- package/dist/channels/bluesky/account.js.map +1 -0
- package/dist/channels/bluesky/channel.d.ts +89 -0
- package/dist/channels/bluesky/channel.d.ts.map +1 -0
- package/dist/channels/bluesky/channel.js +427 -0
- package/dist/channels/bluesky/channel.js.map +1 -0
- package/dist/channels/bluesky/config.d.ts +16 -0
- package/dist/channels/bluesky/config.d.ts.map +1 -0
- package/dist/channels/bluesky/config.js +2 -0
- package/dist/channels/bluesky/config.js.map +1 -0
- package/dist/channels/bluesky/connection.d.ts +40 -0
- package/dist/channels/bluesky/connection.d.ts.map +1 -0
- package/dist/channels/bluesky/connection.js +159 -0
- package/dist/channels/bluesky/connection.js.map +1 -0
- package/dist/channels/bluesky/feed.d.ts +59 -0
- package/dist/channels/bluesky/feed.d.ts.map +1 -0
- package/dist/channels/bluesky/feed.js +324 -0
- package/dist/channels/bluesky/feed.js.map +1 -0
- package/dist/channels/bluesky/index.d.ts +5 -0
- package/dist/channels/bluesky/index.d.ts.map +1 -0
- package/dist/channels/bluesky/index.js +4 -0
- package/dist/channels/bluesky/index.js.map +1 -0
- package/dist/channels/threads/account.d.ts +42 -0
- package/dist/channels/threads/account.d.ts.map +1 -0
- package/dist/channels/threads/account.js +64 -0
- package/dist/channels/threads/account.js.map +1 -0
- package/dist/channels/threads/channel.d.ts +119 -0
- package/dist/channels/threads/channel.d.ts.map +1 -0
- package/dist/channels/threads/channel.js +405 -0
- package/dist/channels/threads/channel.js.map +1 -0
- package/dist/channels/threads/client.d.ts +42 -0
- package/dist/channels/threads/client.d.ts.map +1 -0
- package/dist/channels/threads/client.js +102 -0
- package/dist/channels/threads/client.js.map +1 -0
- package/dist/channels/threads/feed.d.ts +79 -0
- package/dist/channels/threads/feed.d.ts.map +1 -0
- package/dist/channels/threads/feed.js +396 -0
- package/dist/channels/threads/feed.js.map +1 -0
- package/dist/channels/threads/index.d.ts +6 -0
- package/dist/channels/threads/index.d.ts.map +1 -0
- package/dist/channels/threads/index.js +6 -0
- package/dist/channels/threads/index.js.map +1 -0
- package/dist/channels/threads/token.d.ts +51 -0
- package/dist/channels/threads/token.d.ts.map +1 -0
- package/dist/channels/threads/token.js +128 -0
- package/dist/channels/threads/token.js.map +1 -0
- package/dist/feeds/attachments.d.ts +15 -0
- package/dist/feeds/attachments.d.ts.map +1 -0
- package/dist/feeds/attachments.js +85 -0
- package/dist/feeds/attachments.js.map +1 -0
- package/dist/feeds/errors.d.ts +42 -0
- package/dist/feeds/errors.d.ts.map +1 -0
- package/dist/feeds/errors.js +66 -0
- package/dist/feeds/errors.js.map +1 -0
- package/dist/feeds/index.d.ts +8 -0
- package/dist/feeds/index.d.ts.map +1 -0
- package/dist/feeds/index.js +6 -0
- package/dist/feeds/index.js.map +1 -0
- package/dist/feeds/publish-store.d.ts +148 -0
- package/dist/feeds/publish-store.d.ts.map +1 -0
- package/dist/feeds/publish-store.js +345 -0
- package/dist/feeds/publish-store.js.map +1 -0
- package/dist/feeds/publisher.d.ts +118 -0
- package/dist/feeds/publisher.d.ts.map +1 -0
- package/dist/feeds/publisher.js +308 -0
- package/dist/feeds/publisher.js.map +1 -0
- package/dist/feeds/storage.d.ts +33 -0
- package/dist/feeds/storage.d.ts.map +1 -0
- package/dist/feeds/storage.js +61 -0
- package/dist/feeds/storage.js.map +1 -0
- package/dist/feeds/text.d.ts +26 -0
- package/dist/feeds/text.d.ts.map +1 -0
- package/dist/feeds/text.js +126 -0
- package/dist/feeds/text.js.map +1 -0
- package/dist/feeds/token-store.d.ts +45 -0
- package/dist/feeds/token-store.d.ts.map +1 -0
- package/dist/feeds/token-store.js +128 -0
- package/dist/feeds/token-store.js.map +1 -0
- package/dist/formatters/markdown.d.ts.map +1 -1
- package/dist/formatters/markdown.js +6 -0
- package/dist/formatters/markdown.js.map +1 -1
- package/dist/formatters/plain-text.d.ts +7 -0
- package/dist/formatters/plain-text.d.ts.map +1 -0
- package/dist/formatters/plain-text.js +38 -0
- package/dist/formatters/plain-text.js.map +1 -0
- package/dist/gateway.js +1 -1
- package/dist/gateway.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/runtime-builder.d.ts.map +1 -1
- package/dist/runtime-builder.js +54 -0
- package/dist/runtime-builder.js.map +1 -1
- package/package.json +23 -15
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
import { graphemeLength, splitText } from '../../feeds/text.js';
|
|
2
|
+
import { accountOf } from './account.js';
|
|
3
|
+
import { blueskyError, connectionOf, loadAtproto } from './connection.js';
|
|
4
|
+
import { BlueskyFeed } from './feed.js';
|
|
5
|
+
const CHAT_SERVICE = 'did:web:api.bsky.chat';
|
|
6
|
+
const MAX_TRACKED = 1000;
|
|
7
|
+
const POST_LIMIT = 300;
|
|
8
|
+
const MESSAGE_LIMIT = 1000;
|
|
9
|
+
const MAX_NOTIFICATION_PAGES = 10;
|
|
10
|
+
const MAX_MESSAGE_PAGES = 5;
|
|
11
|
+
/**
|
|
12
|
+
* A conversational Bluesky channel: an agent answers mentions, replies and
|
|
13
|
+
* quotes of its posts in their threads, and direct messages in their
|
|
14
|
+
* conversation. It polls, and keeps what it has seen on Bluesky itself (the
|
|
15
|
+
* notifications' seen time, each conversation's read state), so it needs no
|
|
16
|
+
* state of its own across restarts. Bluesky cannot edit posts, so answers
|
|
17
|
+
* are sent once finished, as a thread of posts or several messages when
|
|
18
|
+
* long. A message's `channelId` is `post:<uri>` to answer under that post,
|
|
19
|
+
* `dm:<convoId>` for a conversation, or `feed` for a new post.
|
|
20
|
+
*/
|
|
21
|
+
export class BlueskyChannel {
|
|
22
|
+
type = 'bluesky';
|
|
23
|
+
editable = false;
|
|
24
|
+
nativeMarkdown = false;
|
|
25
|
+
maxMessageChars = Infinity;
|
|
26
|
+
account;
|
|
27
|
+
feed;
|
|
28
|
+
interval;
|
|
29
|
+
posts;
|
|
30
|
+
directMessages;
|
|
31
|
+
catchUp;
|
|
32
|
+
handler = null;
|
|
33
|
+
timer;
|
|
34
|
+
polling;
|
|
35
|
+
seen = new Map();
|
|
36
|
+
requests = new Set();
|
|
37
|
+
chatOf;
|
|
38
|
+
backlog;
|
|
39
|
+
conversations = new Map();
|
|
40
|
+
ownDid;
|
|
41
|
+
running = false;
|
|
42
|
+
constructor(config) {
|
|
43
|
+
this.account = accountOf(config);
|
|
44
|
+
this.feed = new BlueskyFeed({ account: this.account });
|
|
45
|
+
this.interval = config.pollInterval ?? 15_000;
|
|
46
|
+
this.posts = config.posts ?? true;
|
|
47
|
+
this.directMessages = config.directMessages ?? true;
|
|
48
|
+
this.catchUp = config.catchUp ?? true;
|
|
49
|
+
}
|
|
50
|
+
onMessage(handler) {
|
|
51
|
+
this.handler = handler;
|
|
52
|
+
}
|
|
53
|
+
async start() {
|
|
54
|
+
if (this.running)
|
|
55
|
+
return;
|
|
56
|
+
const agent = await connectionOf(this.account).agent();
|
|
57
|
+
this.ownDid = await this.account.did();
|
|
58
|
+
if (!this.catchUp)
|
|
59
|
+
await this.skipBacklog(agent);
|
|
60
|
+
this.running = true;
|
|
61
|
+
this.timer = setInterval(() => void this.poll(), this.interval);
|
|
62
|
+
await this.poll();
|
|
63
|
+
}
|
|
64
|
+
async stop() {
|
|
65
|
+
this.running = false;
|
|
66
|
+
if (this.timer)
|
|
67
|
+
clearInterval(this.timer);
|
|
68
|
+
this.timer = undefined;
|
|
69
|
+
await this.polling;
|
|
70
|
+
}
|
|
71
|
+
/** Looks for new mentions, replies and messages once. `start()` does this on a timer. */
|
|
72
|
+
poll() {
|
|
73
|
+
this.polling ??= (async () => {
|
|
74
|
+
try {
|
|
75
|
+
if (this.posts)
|
|
76
|
+
await this.pollPosts();
|
|
77
|
+
if (this.directMessages)
|
|
78
|
+
await this.pollMessages();
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
console.error('[bluesky] Polling failed:', error);
|
|
82
|
+
}
|
|
83
|
+
})().finally(() => {
|
|
84
|
+
this.polling = undefined;
|
|
85
|
+
});
|
|
86
|
+
return this.polling;
|
|
87
|
+
}
|
|
88
|
+
async sendText(channelId, text, options) {
|
|
89
|
+
const target = parseTarget(channelId);
|
|
90
|
+
if (target.kind === 'dm')
|
|
91
|
+
return this.sendMessages(target.id, text);
|
|
92
|
+
const parts = splitText(text, POST_LIMIT, graphemeLength);
|
|
93
|
+
if (parts.length === 0)
|
|
94
|
+
throw new Error('[bluesky] Nothing to send');
|
|
95
|
+
let replyTo = options?.replyTo ?? (target.kind === 'post' ? target.id : undefined);
|
|
96
|
+
let first;
|
|
97
|
+
for (const part of parts) {
|
|
98
|
+
const published = await this.feed.publish({ text: part, ...(replyTo && { replyTo }) });
|
|
99
|
+
first ??= published.id;
|
|
100
|
+
replyTo = published.id;
|
|
101
|
+
}
|
|
102
|
+
return first ?? '';
|
|
103
|
+
}
|
|
104
|
+
editText() {
|
|
105
|
+
return Promise.reject(new Error('[bluesky] Bluesky posts and messages cannot be edited'));
|
|
106
|
+
}
|
|
107
|
+
async sendFile(channelId, file, options) {
|
|
108
|
+
const target = parseTarget(channelId);
|
|
109
|
+
if (target.kind === 'dm') {
|
|
110
|
+
throw new Error('[bluesky] Direct messages cannot carry files: send a link instead');
|
|
111
|
+
}
|
|
112
|
+
const replyTo = options?.replyTo ?? (target.kind === 'post' ? target.id : undefined);
|
|
113
|
+
const published = await this.feed.publish({
|
|
114
|
+
text: file.caption ?? '',
|
|
115
|
+
images: [{ image: file }],
|
|
116
|
+
...(replyTo && { replyTo }),
|
|
117
|
+
});
|
|
118
|
+
return published.id;
|
|
119
|
+
}
|
|
120
|
+
async sendTyping() { }
|
|
121
|
+
async deleteMessage(channelId, messageId) {
|
|
122
|
+
const target = parseTarget(channelId);
|
|
123
|
+
if (target.kind === 'dm') {
|
|
124
|
+
const chat = await this.chat();
|
|
125
|
+
try {
|
|
126
|
+
await chat.chat.bsky.convo.deleteMessageForSelf({ convoId: target.id, messageId });
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
throw blueskyError(error, 'Deleting the message');
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
await this.feed.delete(messageId);
|
|
134
|
+
}
|
|
135
|
+
/** The chat service agent of the current session, made again after a new sign-in. */
|
|
136
|
+
async chat() {
|
|
137
|
+
const agent = await connectionOf(this.account).agent();
|
|
138
|
+
if (this.chatOf?.agent !== agent) {
|
|
139
|
+
this.chatOf = { agent, chat: agent.withProxy('bsky_chat', CHAT_SERVICE) };
|
|
140
|
+
}
|
|
141
|
+
return this.chatOf.chat;
|
|
142
|
+
}
|
|
143
|
+
remember(id) {
|
|
144
|
+
if (this.seen.has(id))
|
|
145
|
+
return false;
|
|
146
|
+
this.seen.set(id, true);
|
|
147
|
+
if (this.seen.size > MAX_TRACKED) {
|
|
148
|
+
const oldest = this.seen.keys().next().value;
|
|
149
|
+
if (oldest !== undefined)
|
|
150
|
+
this.seen.delete(oldest);
|
|
151
|
+
}
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
async skipBacklog(agent) {
|
|
155
|
+
try {
|
|
156
|
+
if (this.posts) {
|
|
157
|
+
await agent.app.bsky.notification.updateSeen({ seenAt: new Date().toISOString() });
|
|
158
|
+
}
|
|
159
|
+
if (this.directMessages)
|
|
160
|
+
await (await this.chat()).chat.bsky.convo.updateAllRead({});
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
throw blueskyError(error, 'Skipping what arrived before the start');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Answers the unread mentions, replies and quotes, oldest first of each
|
|
168
|
+
* batch, paging back to the first one already seen, then marks them seen.
|
|
169
|
+
* A backlog longer than one poll reads is carried on from where the last
|
|
170
|
+
* poll stopped, and nothing is marked seen until it is read to the end,
|
|
171
|
+
* since marking a time seen also marks everything older.
|
|
172
|
+
*/
|
|
173
|
+
async pollPosts() {
|
|
174
|
+
const agent = await connectionOf(this.account).agent();
|
|
175
|
+
const unread = [];
|
|
176
|
+
let cursor = this.backlog?.cursor;
|
|
177
|
+
let reachedSeen = false;
|
|
178
|
+
try {
|
|
179
|
+
for (let page = 0; page < MAX_NOTIFICATION_PAGES; page++) {
|
|
180
|
+
const response = await agent.app.bsky.notification.listNotifications({
|
|
181
|
+
reasons: ['mention', 'reply', 'quote'],
|
|
182
|
+
limit: 100,
|
|
183
|
+
...(cursor && { cursor }),
|
|
184
|
+
});
|
|
185
|
+
const notifications = response.data.notifications;
|
|
186
|
+
unread.push(...notifications.filter((notification) => !notification.isRead));
|
|
187
|
+
cursor = response.data.cursor;
|
|
188
|
+
if (!cursor || notifications.length === 0 || notifications.some((item) => item.isRead)) {
|
|
189
|
+
reachedSeen = true;
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
throw blueskyError(error, 'Listing notifications');
|
|
196
|
+
}
|
|
197
|
+
const newest = [this.backlog?.newest, ...unread.map((notification) => notification.indexedAt)]
|
|
198
|
+
.filter((time) => time !== undefined)
|
|
199
|
+
.sort()
|
|
200
|
+
.at(-1);
|
|
201
|
+
this.backlog = reachedSeen || !cursor ? undefined : { cursor, ...(newest && { newest }) };
|
|
202
|
+
if (this.backlog) {
|
|
203
|
+
console.warn(`[bluesky] More than ${MAX_NOTIFICATION_PAGES * 100} unread notifications: the next poll reads on`);
|
|
204
|
+
}
|
|
205
|
+
const fresh = unread
|
|
206
|
+
.filter((notification) => notification.author.did !== this.ownDid)
|
|
207
|
+
.sort((a, b) => a.indexedAt.localeCompare(b.indexedAt));
|
|
208
|
+
for (const notification of fresh) {
|
|
209
|
+
if (!this.remember(notification.uri))
|
|
210
|
+
continue;
|
|
211
|
+
await this.deliver(this.postMessage(notification));
|
|
212
|
+
}
|
|
213
|
+
if (newest && !this.backlog) {
|
|
214
|
+
try {
|
|
215
|
+
await agent.app.bsky.notification.updateSeen({ seenAt: newest });
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
console.error('[bluesky] Could not mark notifications seen:', error);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
postMessage(notification) {
|
|
223
|
+
const record = notification.record;
|
|
224
|
+
const text = typeof record.text === 'string' ? record.text : '';
|
|
225
|
+
const parent = replyParent(record);
|
|
226
|
+
const root = replyRoot(record) ?? notification.uri;
|
|
227
|
+
return {
|
|
228
|
+
id: notification.uri,
|
|
229
|
+
channelType: this.type,
|
|
230
|
+
channelId: `post:${notification.uri}`,
|
|
231
|
+
userId: notification.author.did,
|
|
232
|
+
userName: notification.author.displayName || notification.author.handle,
|
|
233
|
+
groupId: `thread:${root}`,
|
|
234
|
+
text: stripMention(text, this.account.identifier),
|
|
235
|
+
...(parent && { replyTo: parent }),
|
|
236
|
+
raw: notification,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
async pollMessages() {
|
|
240
|
+
const chat = await this.chat();
|
|
241
|
+
let convos;
|
|
242
|
+
try {
|
|
243
|
+
const [unread, requests] = await Promise.all([
|
|
244
|
+
chat.chat.bsky.convo.listConvos({ readState: 'unread', limit: 50 }),
|
|
245
|
+
chat.chat.bsky.convo.listConvoRequests({ limit: 50 }),
|
|
246
|
+
]);
|
|
247
|
+
const pending = requests.data.requests.filter((convo) => typeof convo.id === 'string' && convo.unreadCount > 0);
|
|
248
|
+
for (const convo of pending)
|
|
249
|
+
this.requests.add(convo.id);
|
|
250
|
+
convos = [...unread.data.convos, ...pending];
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
throw blueskyError(error, 'Listing conversations');
|
|
254
|
+
}
|
|
255
|
+
for (const convo of convos) {
|
|
256
|
+
if (convo.unreadCount <= 0)
|
|
257
|
+
continue;
|
|
258
|
+
await this.readConversation(chat, convo);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Answers a conversation's unread messages, then marks it read. History
|
|
263
|
+
* runs newest first and holds the bot's own, deleted and system messages
|
|
264
|
+
* too, so it is read back until as many messages from others as are
|
|
265
|
+
* unread were found. A conversation with more than one poll reads is
|
|
266
|
+
* carried on by the next poll from where this one stopped, and marked
|
|
267
|
+
* read only at the end, since marking a message read marks all before it.
|
|
268
|
+
*/
|
|
269
|
+
async readConversation(chat, convo) {
|
|
270
|
+
const backlog = this.conversations.get(convo.id);
|
|
271
|
+
const fromOthers = [];
|
|
272
|
+
let newest = backlog?.newest;
|
|
273
|
+
let cursor = backlog?.cursor;
|
|
274
|
+
let found = backlog?.found ?? 0;
|
|
275
|
+
try {
|
|
276
|
+
for (let page = 0; page < MAX_MESSAGE_PAGES; page++) {
|
|
277
|
+
const response = await chat.chat.bsky.convo.getMessages({
|
|
278
|
+
convoId: convo.id,
|
|
279
|
+
limit: 100,
|
|
280
|
+
...(cursor && { cursor }),
|
|
281
|
+
});
|
|
282
|
+
const messages = response.data.messages;
|
|
283
|
+
for (const message of messages) {
|
|
284
|
+
if (message.sentAt !== undefined && (!newest || message.sentAt > newest.sentAt)) {
|
|
285
|
+
newest = { id: message.id, sentAt: message.sentAt };
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const deliverable = messages
|
|
289
|
+
.filter((message) => typeof message.text === 'string' &&
|
|
290
|
+
message.sender !== undefined &&
|
|
291
|
+
message.sender.did !== this.ownDid)
|
|
292
|
+
.slice(0, Math.max(0, convo.unreadCount - found));
|
|
293
|
+
fromOthers.push(...deliverable);
|
|
294
|
+
found += deliverable.length;
|
|
295
|
+
cursor = messages.length > 0 ? response.data.cursor : undefined;
|
|
296
|
+
if (!cursor || found >= convo.unreadCount) {
|
|
297
|
+
cursor = undefined;
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
console.error(`[bluesky] Could not read conversation ${convo.id}:`, error);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (cursor) {
|
|
307
|
+
this.conversations.set(convo.id, { cursor, found, ...(newest && { newest }) });
|
|
308
|
+
console.warn(`[bluesky] Conversation ${convo.id} has more unread messages than one poll reads: the next poll reads on`);
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
this.conversations.delete(convo.id);
|
|
312
|
+
}
|
|
313
|
+
const incoming = fromOthers.sort((a, b) => (a.sentAt ?? '').localeCompare(b.sentAt ?? ''));
|
|
314
|
+
for (const message of incoming) {
|
|
315
|
+
if (!this.remember(`${convo.id}:${message.id}`))
|
|
316
|
+
continue;
|
|
317
|
+
const sender = convo.members.find((member) => member.did === message.sender?.did);
|
|
318
|
+
await this.deliver({
|
|
319
|
+
id: message.id,
|
|
320
|
+
channelType: this.type,
|
|
321
|
+
channelId: `dm:${convo.id}`,
|
|
322
|
+
userId: message.sender?.did ?? '',
|
|
323
|
+
...(sender && { userName: sender.displayName || sender.handle }),
|
|
324
|
+
text: message.text ?? '',
|
|
325
|
+
raw: { convo, message },
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
if (cursor)
|
|
329
|
+
return;
|
|
330
|
+
try {
|
|
331
|
+
await chat.chat.bsky.convo.updateRead({
|
|
332
|
+
convoId: convo.id,
|
|
333
|
+
...(newest && { messageId: newest.id }),
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
console.error(`[bluesky] Could not mark conversation ${convo.id} read:`, error);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
async sendMessages(convoId, text) {
|
|
341
|
+
const chat = await this.chat();
|
|
342
|
+
const parts = splitText(text, MESSAGE_LIMIT, graphemeLength);
|
|
343
|
+
if (parts.length === 0)
|
|
344
|
+
throw new Error('[bluesky] Nothing to send');
|
|
345
|
+
if (this.requests.has(convoId)) {
|
|
346
|
+
try {
|
|
347
|
+
await chat.chat.bsky.convo.acceptConvo({ convoId });
|
|
348
|
+
this.requests.delete(convoId);
|
|
349
|
+
}
|
|
350
|
+
catch (error) {
|
|
351
|
+
throw blueskyError(error, 'Accepting the conversation');
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
const { RichText } = await loadAtproto();
|
|
355
|
+
const agent = await connectionOf(this.account).agent();
|
|
356
|
+
let first;
|
|
357
|
+
for (const part of parts) {
|
|
358
|
+
const rich = new RichText({ text: part });
|
|
359
|
+
try {
|
|
360
|
+
await rich.detectFacets(agent);
|
|
361
|
+
const sent = await chat.chat.bsky.convo.sendMessage({
|
|
362
|
+
convoId,
|
|
363
|
+
message: { text: rich.text, ...(rich.facets?.length ? { facets: rich.facets } : {}) },
|
|
364
|
+
});
|
|
365
|
+
first ??= sent.data.id;
|
|
366
|
+
}
|
|
367
|
+
catch (error) {
|
|
368
|
+
throw blueskyError(error, 'Sending the message');
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return first ?? '';
|
|
372
|
+
}
|
|
373
|
+
async deliver(message) {
|
|
374
|
+
if (!this.handler || !message.text.trim())
|
|
375
|
+
return;
|
|
376
|
+
try {
|
|
377
|
+
await this.handler(message);
|
|
378
|
+
}
|
|
379
|
+
catch (error) {
|
|
380
|
+
console.error('[bluesky] Message handler error:', error);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
/** What a `channelId` points at: a post to answer, a conversation, or the account's feed. */
|
|
385
|
+
function parseTarget(channelId) {
|
|
386
|
+
if (channelId === 'feed')
|
|
387
|
+
return { kind: 'feed' };
|
|
388
|
+
if (channelId.startsWith('post:'))
|
|
389
|
+
return { kind: 'post', id: channelId.slice(5) };
|
|
390
|
+
if (channelId.startsWith('dm:'))
|
|
391
|
+
return { kind: 'dm', id: channelId.slice(3) };
|
|
392
|
+
if (channelId.startsWith('at://'))
|
|
393
|
+
return { kind: 'post', id: channelId };
|
|
394
|
+
throw new Error(`[bluesky] Unknown channel id "${channelId}": use post:<at-uri>, dm:<convoId> or feed`);
|
|
395
|
+
}
|
|
396
|
+
function strongRefUri(value) {
|
|
397
|
+
return typeof value === 'object' &&
|
|
398
|
+
value !== null &&
|
|
399
|
+
'uri' in value &&
|
|
400
|
+
typeof value.uri === 'string'
|
|
401
|
+
? value.uri
|
|
402
|
+
: undefined;
|
|
403
|
+
}
|
|
404
|
+
function replyParent(record) {
|
|
405
|
+
const reply = record.reply;
|
|
406
|
+
return typeof reply === 'object' && reply !== null && 'parent' in reply
|
|
407
|
+
? strongRefUri(reply.parent)
|
|
408
|
+
: undefined;
|
|
409
|
+
}
|
|
410
|
+
function replyRoot(record) {
|
|
411
|
+
const reply = record.reply;
|
|
412
|
+
return typeof reply === 'object' && reply !== null && 'root' in reply
|
|
413
|
+
? strongRefUri(reply.root)
|
|
414
|
+
: undefined;
|
|
415
|
+
}
|
|
416
|
+
/** The text without the account's own mention in front, as the agent should read it. */
|
|
417
|
+
function stripMention(text, identifier) {
|
|
418
|
+
const handle = identifier.replace(/^@/, '').toLowerCase();
|
|
419
|
+
return (text
|
|
420
|
+
.replace(new RegExp(`^\\s*@${handle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b[\\s,:]*`, 'i'), '')
|
|
421
|
+
.trim() || text.trim());
|
|
422
|
+
}
|
|
423
|
+
/** A conversational Bluesky channel. */
|
|
424
|
+
export function blueskyChannel(config) {
|
|
425
|
+
return new BlueskyChannel(config);
|
|
426
|
+
}
|
|
427
|
+
//# sourceMappingURL=channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../../../src/channels/bluesky/channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TokenStore } from '@cogitator-ai/types';
|
|
2
|
+
export interface BlueskyConnectionConfig {
|
|
3
|
+
/** The account's handle (`mybot.bsky.social`) or DID. */
|
|
4
|
+
identifier: string;
|
|
5
|
+
/** An app password from Settings → Privacy and security → App passwords, not the account password. */
|
|
6
|
+
appPassword: string;
|
|
7
|
+
/** The PDS to sign in to (default `https://bsky.social`). */
|
|
8
|
+
service?: string;
|
|
9
|
+
/** Where the session is kept so a restart does not sign in again (default in memory). */
|
|
10
|
+
store?: TokenStore;
|
|
11
|
+
/** The session's key in the store (default `bluesky:<identifier>`). */
|
|
12
|
+
storeKey?: string;
|
|
13
|
+
/** The fetch the client uses, for tests and proxies. */
|
|
14
|
+
fetch?: typeof fetch;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/channels/bluesky/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,WAAW,uBAAuB;IACtC,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,sGAAsG;IACtG,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yFAAyF;IACzF,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/channels/bluesky/config.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Agent } from '@atproto/api';
|
|
2
|
+
import type { BlueskyConnectionConfig } from './config.js';
|
|
3
|
+
import { FeedError } from '../../feeds/errors.js';
|
|
4
|
+
type AtprotoModule = typeof import('@atproto/api');
|
|
5
|
+
/** `@atproto/api`, loaded on first use since it is an optional peer dependency. */
|
|
6
|
+
export declare function loadAtproto(): Promise<AtprotoModule>;
|
|
7
|
+
/** A failure of the Bluesky API as a `FeedError`, keeping the wait a rate limit asks for. */
|
|
8
|
+
export declare function blueskyError(error: unknown, action: string): FeedError;
|
|
9
|
+
/**
|
|
10
|
+
* A signed-in Bluesky account, shared by the feed and the chat channel of
|
|
11
|
+
* one account. The session is resumed from the store when it holds one and
|
|
12
|
+
* kept there as it is refreshed. A session that cannot be resumed, or that
|
|
13
|
+
* expires because its refresh token was used up (by another process sharing
|
|
14
|
+
* the store, say), is replaced by a new sign-in with the app password.
|
|
15
|
+
*/
|
|
16
|
+
export declare class BlueskyConnection {
|
|
17
|
+
readonly config: BlueskyConnectionConfig;
|
|
18
|
+
private readonly store;
|
|
19
|
+
private readonly key;
|
|
20
|
+
private connecting?;
|
|
21
|
+
private session?;
|
|
22
|
+
constructor(config: BlueskyConnectionConfig);
|
|
23
|
+
/** The signed-in agent, signing in on first use. */
|
|
24
|
+
agent(): Promise<Agent>;
|
|
25
|
+
/**
|
|
26
|
+
* Runs `action` with the signed-in agent, and once more after signing in
|
|
27
|
+
* again when the session expired while it ran.
|
|
28
|
+
*/
|
|
29
|
+
use<T>(action: (agent: Agent) => Promise<T>): Promise<T>;
|
|
30
|
+
/** The DID of the signed-in account. */
|
|
31
|
+
did(): Promise<string>;
|
|
32
|
+
private connect;
|
|
33
|
+
private persist;
|
|
34
|
+
}
|
|
35
|
+
/** Ties an account object to its connection. */
|
|
36
|
+
export declare function register(account: object, connection: BlueskyConnection): void;
|
|
37
|
+
/** The connection behind an account, for the feed and channel of this package. */
|
|
38
|
+
export declare function connectionOf(account: object): BlueskyConnection;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/channels/bluesky/connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAsD,MAAM,cAAc,CAAC;AAE9F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,SAAS,EAAqC,MAAM,oBAAoB,CAAC;AAGlF,KAAK,aAAa,GAAG,cAAc,cAAc,CAAC,CAAC;AAInD,mFAAmF;AACnF,wBAAgB,WAAW,IAAI,OAAO,CAAC,aAAa,CAAC,CASpD;AAgBD,6FAA6F;AAC7F,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CA2BtE;AAED;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,UAAU,CAAC,CAAiB;IACpC,OAAO,CAAC,OAAO,CAAC,CAAoB;gBAExB,MAAM,EAAE,uBAAuB;IAQ3C,oDAAoD;IACpD,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC;IAQvB;;;OAGG;IACG,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAW9D,wCAAwC;IAClC,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;YAMd,OAAO;YA4BP,OAAO;CAmBtB;AAID,gDAAgD;AAChD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAE7E;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAI/D"}
|