@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.
Files changed (102) hide show
  1. package/README.md +101 -11
  2. package/dist/assistant-config.d.ts +16 -0
  3. package/dist/assistant-config.d.ts.map +1 -1
  4. package/dist/assistant-config.js +22 -0
  5. package/dist/assistant-config.js.map +1 -1
  6. package/dist/channels/bluesky/account.d.ts +18 -0
  7. package/dist/channels/bluesky/account.d.ts.map +1 -0
  8. package/dist/channels/bluesky/account.js +25 -0
  9. package/dist/channels/bluesky/account.js.map +1 -0
  10. package/dist/channels/bluesky/channel.d.ts +89 -0
  11. package/dist/channels/bluesky/channel.d.ts.map +1 -0
  12. package/dist/channels/bluesky/channel.js +427 -0
  13. package/dist/channels/bluesky/channel.js.map +1 -0
  14. package/dist/channels/bluesky/config.d.ts +16 -0
  15. package/dist/channels/bluesky/config.d.ts.map +1 -0
  16. package/dist/channels/bluesky/config.js +2 -0
  17. package/dist/channels/bluesky/config.js.map +1 -0
  18. package/dist/channels/bluesky/connection.d.ts +40 -0
  19. package/dist/channels/bluesky/connection.d.ts.map +1 -0
  20. package/dist/channels/bluesky/connection.js +159 -0
  21. package/dist/channels/bluesky/connection.js.map +1 -0
  22. package/dist/channels/bluesky/feed.d.ts +59 -0
  23. package/dist/channels/bluesky/feed.d.ts.map +1 -0
  24. package/dist/channels/bluesky/feed.js +324 -0
  25. package/dist/channels/bluesky/feed.js.map +1 -0
  26. package/dist/channels/bluesky/index.d.ts +5 -0
  27. package/dist/channels/bluesky/index.d.ts.map +1 -0
  28. package/dist/channels/bluesky/index.js +4 -0
  29. package/dist/channels/bluesky/index.js.map +1 -0
  30. package/dist/channels/threads/account.d.ts +42 -0
  31. package/dist/channels/threads/account.d.ts.map +1 -0
  32. package/dist/channels/threads/account.js +64 -0
  33. package/dist/channels/threads/account.js.map +1 -0
  34. package/dist/channels/threads/channel.d.ts +119 -0
  35. package/dist/channels/threads/channel.d.ts.map +1 -0
  36. package/dist/channels/threads/channel.js +405 -0
  37. package/dist/channels/threads/channel.js.map +1 -0
  38. package/dist/channels/threads/client.d.ts +42 -0
  39. package/dist/channels/threads/client.d.ts.map +1 -0
  40. package/dist/channels/threads/client.js +102 -0
  41. package/dist/channels/threads/client.js.map +1 -0
  42. package/dist/channels/threads/feed.d.ts +79 -0
  43. package/dist/channels/threads/feed.d.ts.map +1 -0
  44. package/dist/channels/threads/feed.js +396 -0
  45. package/dist/channels/threads/feed.js.map +1 -0
  46. package/dist/channels/threads/index.d.ts +6 -0
  47. package/dist/channels/threads/index.d.ts.map +1 -0
  48. package/dist/channels/threads/index.js +6 -0
  49. package/dist/channels/threads/index.js.map +1 -0
  50. package/dist/channels/threads/token.d.ts +51 -0
  51. package/dist/channels/threads/token.d.ts.map +1 -0
  52. package/dist/channels/threads/token.js +128 -0
  53. package/dist/channels/threads/token.js.map +1 -0
  54. package/dist/feeds/attachments.d.ts +15 -0
  55. package/dist/feeds/attachments.d.ts.map +1 -0
  56. package/dist/feeds/attachments.js +85 -0
  57. package/dist/feeds/attachments.js.map +1 -0
  58. package/dist/feeds/errors.d.ts +42 -0
  59. package/dist/feeds/errors.d.ts.map +1 -0
  60. package/dist/feeds/errors.js +66 -0
  61. package/dist/feeds/errors.js.map +1 -0
  62. package/dist/feeds/index.d.ts +8 -0
  63. package/dist/feeds/index.d.ts.map +1 -0
  64. package/dist/feeds/index.js +6 -0
  65. package/dist/feeds/index.js.map +1 -0
  66. package/dist/feeds/publish-store.d.ts +148 -0
  67. package/dist/feeds/publish-store.d.ts.map +1 -0
  68. package/dist/feeds/publish-store.js +345 -0
  69. package/dist/feeds/publish-store.js.map +1 -0
  70. package/dist/feeds/publisher.d.ts +118 -0
  71. package/dist/feeds/publisher.d.ts.map +1 -0
  72. package/dist/feeds/publisher.js +308 -0
  73. package/dist/feeds/publisher.js.map +1 -0
  74. package/dist/feeds/storage.d.ts +33 -0
  75. package/dist/feeds/storage.d.ts.map +1 -0
  76. package/dist/feeds/storage.js +61 -0
  77. package/dist/feeds/storage.js.map +1 -0
  78. package/dist/feeds/text.d.ts +26 -0
  79. package/dist/feeds/text.d.ts.map +1 -0
  80. package/dist/feeds/text.js +126 -0
  81. package/dist/feeds/text.js.map +1 -0
  82. package/dist/feeds/token-store.d.ts +45 -0
  83. package/dist/feeds/token-store.d.ts.map +1 -0
  84. package/dist/feeds/token-store.js +128 -0
  85. package/dist/feeds/token-store.js.map +1 -0
  86. package/dist/formatters/markdown.d.ts.map +1 -1
  87. package/dist/formatters/markdown.js +6 -0
  88. package/dist/formatters/markdown.js.map +1 -1
  89. package/dist/formatters/plain-text.d.ts +7 -0
  90. package/dist/formatters/plain-text.d.ts.map +1 -0
  91. package/dist/formatters/plain-text.js +38 -0
  92. package/dist/formatters/plain-text.js.map +1 -0
  93. package/dist/gateway.js +1 -1
  94. package/dist/gateway.js.map +1 -1
  95. package/dist/index.d.ts +5 -1
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +4 -0
  98. package/dist/index.js.map +1 -1
  99. package/dist/runtime-builder.d.ts.map +1 -1
  100. package/dist/runtime-builder.js +54 -0
  101. package/dist/runtime-builder.js.map +1 -1
  102. package/package.json +23 -15
@@ -0,0 +1,159 @@
1
+ import { FeedError, feedErrorCode } from '../../feeds/errors.js';
2
+ import { MemoryTokenStore } from '../../feeds/token-store.js';
3
+ let atproto;
4
+ /** `@atproto/api`, loaded on first use since it is an optional peer dependency. */
5
+ export function loadAtproto() {
6
+ atproto ??= import('@atproto/api').catch((error) => {
7
+ atproto = undefined;
8
+ throw new Error('@atproto/api is required for Bluesky support. Install it: pnpm add @atproto/api', { cause: error });
9
+ });
10
+ return atproto;
11
+ }
12
+ const XRPC_CODES = {
13
+ AuthenticationRequired: 'auth',
14
+ AuthFactorTokenRequired: 'auth',
15
+ AccountTakedown: 'auth',
16
+ InvalidToken: 'auth',
17
+ ExpiredToken: 'token_expired',
18
+ RateLimitExceeded: 'rate_limited',
19
+ InvalidRequest: 'invalid_post',
20
+ BlobTooLarge: 'invalid_post',
21
+ NotFound: 'not_found',
22
+ RecordNotFound: 'not_found',
23
+ XRPCNotSupported: 'auth',
24
+ };
25
+ /** A failure of the Bluesky API as a `FeedError`, keeping the wait a rate limit asks for. */
26
+ export function blueskyError(error, action) {
27
+ if (error instanceof FeedError)
28
+ return error;
29
+ if (typeof error === 'object' && error !== null && 'status' in error && 'error' in error) {
30
+ const status = Number(error.status);
31
+ const name = typeof error.error === 'string' ? error.error : '';
32
+ const headers = 'headers' in error && typeof error.headers === 'object' && error.headers !== null
33
+ ? error.headers
34
+ : {};
35
+ const reset = Number(headers['ratelimit-reset']);
36
+ const message = error instanceof Error ? error.message : name;
37
+ const code = XRPC_CODES[name] ?? (status > 1 ? feedErrorCode(status) : 'unavailable');
38
+ const hint = name === 'XRPCNotSupported'
39
+ ? ': direct messages need an app password created with "Allow access to your direct messages"'
40
+ : '';
41
+ return new FeedError('bluesky', code, `${action} failed: ${message}${hint}`, {
42
+ ...(status > 1 ? { status } : {}),
43
+ ...(Number.isFinite(reset) && reset > 0
44
+ ? { retryAfter: Math.max(0, reset * 1000 - Date.now()) }
45
+ : {}),
46
+ cause: error,
47
+ });
48
+ }
49
+ const message = error instanceof Error ? error.message : String(error);
50
+ return new FeedError('bluesky', 'unavailable', `${action} failed: ${message}`, { cause: error });
51
+ }
52
+ /**
53
+ * A signed-in Bluesky account, shared by the feed and the chat channel of
54
+ * one account. The session is resumed from the store when it holds one and
55
+ * kept there as it is refreshed. A session that cannot be resumed, or that
56
+ * expires because its refresh token was used up (by another process sharing
57
+ * the store, say), is replaced by a new sign-in with the app password.
58
+ */
59
+ export class BlueskyConnection {
60
+ config;
61
+ store;
62
+ key;
63
+ connecting;
64
+ session;
65
+ constructor(config) {
66
+ if (!config.identifier)
67
+ throw new Error('Bluesky needs the account handle or DID');
68
+ if (!config.appPassword)
69
+ throw new Error('Bluesky needs an app password');
70
+ this.config = config;
71
+ this.store = config.store ?? new MemoryTokenStore();
72
+ this.key = config.storeKey ?? `bluesky:${config.identifier}`;
73
+ }
74
+ /** The signed-in agent, signing in on first use. */
75
+ agent() {
76
+ this.connecting ??= this.connect().catch((error) => {
77
+ this.connecting = undefined;
78
+ throw blueskyError(error, 'Signing in to Bluesky');
79
+ });
80
+ return this.connecting;
81
+ }
82
+ /**
83
+ * Runs `action` with the signed-in agent, and once more after signing in
84
+ * again when the session expired while it ran.
85
+ */
86
+ async use(action) {
87
+ const agent = await this.agent();
88
+ const session = this.session;
89
+ try {
90
+ return await action(agent);
91
+ }
92
+ catch (error) {
93
+ if (this.session === session && this.connecting)
94
+ throw error;
95
+ return action(await this.agent());
96
+ }
97
+ }
98
+ /** The DID of the signed-in account. */
99
+ async did() {
100
+ const agent = await this.agent();
101
+ if (!agent.did)
102
+ throw new FeedError('bluesky', 'auth', 'The Bluesky session has no DID');
103
+ return agent.did;
104
+ }
105
+ async connect() {
106
+ const { Agent: AgentClass, CredentialSession: SessionClass } = await loadAtproto();
107
+ const session = new SessionClass(new URL(this.config.service ?? 'https://bsky.social'), this.config.fetch, (event, data) => this.persist(session, event, data));
108
+ const agent = new AgentClass(session);
109
+ const stored = await this.store.get(this.key);
110
+ let resumed = false;
111
+ if (stored) {
112
+ try {
113
+ await session.resumeSession(JSON.parse(stored.value));
114
+ resumed = true;
115
+ }
116
+ catch {
117
+ await this.store.delete(this.key);
118
+ }
119
+ }
120
+ if (!resumed) {
121
+ await session.login({
122
+ identifier: this.config.identifier,
123
+ password: this.config.appPassword,
124
+ });
125
+ }
126
+ this.session = session;
127
+ return agent;
128
+ }
129
+ async persist(session, event, data) {
130
+ if (event === 'expired' && this.session === session) {
131
+ this.session = undefined;
132
+ this.connecting = undefined;
133
+ }
134
+ try {
135
+ if ((event === 'create' || event === 'update') && data) {
136
+ await this.store.set(this.key, { value: JSON.stringify(data), issuedAt: Date.now() });
137
+ }
138
+ else if (event === 'expired' || event === 'create-failed') {
139
+ await this.store.delete(this.key);
140
+ }
141
+ }
142
+ catch (error) {
143
+ console.error('[bluesky] Could not save the session:', error);
144
+ }
145
+ }
146
+ }
147
+ const connections = new WeakMap();
148
+ /** Ties an account object to its connection. */
149
+ export function register(account, connection) {
150
+ connections.set(account, connection);
151
+ }
152
+ /** The connection behind an account, for the feed and channel of this package. */
153
+ export function connectionOf(account) {
154
+ const connection = connections.get(account);
155
+ if (!connection)
156
+ throw new Error('Not a BlueskyAccount');
157
+ return connection;
158
+ }
159
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../../src/channels/bluesky/connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import type { FeedChannel, FeedLimits, FeedPost, FeedPublishOptions, PublishedPost } from '@cogitator-ai/types';
2
+ import { type BlueskyAccount } from './account.js';
3
+ import type { BlueskyConnectionConfig } from './config.js';
4
+ /** A Bluesky feed config: an account to share with a `BlueskyChannel`, or its credentials. */
5
+ export type BlueskyFeedConfig = ({
6
+ account: BlueskyAccount;
7
+ } | BlueskyConnectionConfig) & {
8
+ /** The fetch for downloading images given by URL. */
9
+ fetch?: typeof fetch;
10
+ };
11
+ /** What a post record accepts, from the `app.bsky.feed.post` lexicon. */
12
+ export declare const BLUESKY_LIMITS: FeedLimits & {
13
+ maxBytes: number;
14
+ maxThumbBytes: number;
15
+ maxTagLength: number;
16
+ };
17
+ /** The public URL of a post from its `at://` URI. */
18
+ export declare function blueskyPostUrl(uri: string): string;
19
+ /**
20
+ * Publishes posts to a Bluesky account: text with its links, mentions and
21
+ * hashtags as facets, a link card with an uploaded preview or up to four
22
+ * images with alt text, extra tags, languages, and replies placed in their
23
+ * thread. With an idempotency key the post gets that key as its record key,
24
+ * so a second attempt finds the post the first one made.
25
+ */
26
+ export declare class BlueskyFeed implements FeedChannel {
27
+ readonly type = "bluesky";
28
+ readonly limits: FeedLimits;
29
+ readonly account: BlueskyAccount;
30
+ private readonly fetchImpl?;
31
+ private readonly refs;
32
+ constructor(config: BlueskyFeedConfig);
33
+ measure(text: string): number;
34
+ connect(): Promise<void>;
35
+ /** A new record key in the TID format, which `publish` gives the post. */
36
+ idempotencyKey(): string;
37
+ publish(post: FeedPost, options?: FeedPublishOptions): Promise<PublishedPost>;
38
+ delete(id: string): Promise<void>;
39
+ close(): Promise<void>;
40
+ private validate;
41
+ private upload;
42
+ private embed;
43
+ /** The post record for `post`: text with facets, embed, reply, tags and languages. */
44
+ private record;
45
+ /** The account's post under `rkey`, from its own PDS, which knows a post as soon as it exists. */
46
+ private findRecord;
47
+ /**
48
+ * Where a reply to `uri` goes: from the posts this feed published, from the
49
+ * account's own PDS for its other posts, otherwise from the AppView. A post
50
+ * published a moment ago is not on the AppView yet, so a thread of replies
51
+ * never waits for it.
52
+ */
53
+ private replyRef;
54
+ /** Keeps where a published post sits, so replies to it need no lookup. */
55
+ private remember;
56
+ }
57
+ /** A Bluesky feed. */
58
+ export declare function blueskyFeed(config: BlueskyFeedConfig): BlueskyFeed;
59
+ //# sourceMappingURL=feed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feed.d.ts","sourceRoot":"","sources":["../../../src/channels/bluesky/feed.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,kBAAkB,EAClB,aAAa,EACd,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAGxD,8FAA8F;AAC9F,MAAM,MAAM,iBAAiB,GAAG,CAAC;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,GAAG,uBAAuB,CAAC,GAAG;IACxF,qDAAqD;IACrD,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,cAAc,EAAE,UAAU,GAAG;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CAStB,CAAC;AAkCF,qDAAqD;AACrD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED;;;;;;GAMG;AACH,qBAAa,WAAY,YAAW,WAAW;IAC7C,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAkB;IAC7C,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAe;IAC1C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAuD;gBAEhE,MAAM,EAAE,iBAAiB;IAKrC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B,0EAA0E;IAC1E,cAAc,IAAI,MAAM;IAIlB,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,aAAa,CAAC;IA8CjF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAE5B,OAAO,CAAC,QAAQ;YAqCF,MAAM;YASN,KAAK;IA0CnB,sFAAsF;YACxE,MAAM;IA+BpB,kGAAkG;YACpF,UAAU;IA0BxB;;;;;OAKG;YACW,QAAQ;IAsBtB,0EAA0E;IAC1E,OAAO,CAAC,QAAQ;CAOjB;AA8BD,sBAAsB;AACtB,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,WAAW,CAElE"}
@@ -0,0 +1,324 @@
1
+ import { assertImage, attachmentBytes } from '../../feeds/attachments.js';
2
+ import { FeedError } from '../../feeds/errors.js';
3
+ import { graphemeLength } from '../../feeds/text.js';
4
+ import { accountOf } from './account.js';
5
+ import { blueskyError, connectionOf, loadAtproto } from './connection.js';
6
+ /** What a post record accepts, from the `app.bsky.feed.post` lexicon. */
7
+ export const BLUESKY_LIMITS = {
8
+ maxLength: 300,
9
+ maxBytes: 3000,
10
+ maxImages: 4,
11
+ maxImageBytes: 2_000_000,
12
+ maxThumbBytes: 1_000_000,
13
+ maxTags: 8,
14
+ maxTagLength: 64,
15
+ };
16
+ const encoder = new TextEncoder();
17
+ const POST_COLLECTION = 'app.bsky.feed.post';
18
+ const TID_CHARS = '234567abcdefghijklmnopqrstuvwxyz';
19
+ const TID_PATTERN = /^[234567abcdefghij][234567abcdefghijklmnopqrstuvwxyz]{12}$/;
20
+ const MAX_REFS = 500;
21
+ let lastTidMicros = 0;
22
+ /**
23
+ * A new record key in the TID format of the AT Protocol: the time in
24
+ * microseconds and a random clock id, in sortable base32.
25
+ */
26
+ function nextTid() {
27
+ lastTidMicros = Math.max(Date.now() * 1000, lastTidMicros + 1);
28
+ let value = (BigInt(lastTidMicros) << 10n) | BigInt(Math.floor(Math.random() * 1024));
29
+ let tid = '';
30
+ for (let index = 0; index < 13; index++) {
31
+ tid = TID_CHARS.charAt(Number(value & 31n)) + tid;
32
+ value >>= 5n;
33
+ }
34
+ return tid;
35
+ }
36
+ /** The public URL of a post from its `at://` URI. */
37
+ export function blueskyPostUrl(uri) {
38
+ const match = /^at:\/\/([^/]+)\/app\.bsky\.feed\.post\/([^/]+)$/.exec(uri);
39
+ if (!match)
40
+ throw new FeedError('bluesky', 'invalid_post', `Not a Bluesky post URI: ${uri}`);
41
+ return `https://bsky.app/profile/${match[1]}/post/${match[2]}`;
42
+ }
43
+ /**
44
+ * Publishes posts to a Bluesky account: text with its links, mentions and
45
+ * hashtags as facets, a link card with an uploaded preview or up to four
46
+ * images with alt text, extra tags, languages, and replies placed in their
47
+ * thread. With an idempotency key the post gets that key as its record key,
48
+ * so a second attempt finds the post the first one made.
49
+ */
50
+ export class BlueskyFeed {
51
+ type = 'bluesky';
52
+ limits = BLUESKY_LIMITS;
53
+ account;
54
+ fetchImpl;
55
+ refs = new Map();
56
+ constructor(config) {
57
+ this.account = accountOf(config);
58
+ if (config.fetch)
59
+ this.fetchImpl = config.fetch;
60
+ }
61
+ measure(text) {
62
+ return graphemeLength(text);
63
+ }
64
+ async connect() {
65
+ await this.account.connect();
66
+ }
67
+ /** A new record key in the TID format, which `publish` gives the post. */
68
+ idempotencyKey() {
69
+ return nextTid();
70
+ }
71
+ async publish(post, options = {}) {
72
+ this.validate(post);
73
+ const { signal, idempotencyKey: rkey, retry = true } = options;
74
+ if (rkey !== undefined && !TID_PATTERN.test(rkey)) {
75
+ throw new FeedError('bluesky', 'invalid_post', `"${rkey}" is not a key from BlueskyFeed.idempotencyKey()`);
76
+ }
77
+ signal?.throwIfAborted();
78
+ const connection = connectionOf(this.account);
79
+ const created = await connection.use(async (agent) => {
80
+ const did = agent.did;
81
+ if (!did)
82
+ throw new FeedError('bluesky', 'auth', 'The Bluesky session has no DID');
83
+ if (rkey && retry) {
84
+ const existing = await this.findRecord(agent, did, rkey);
85
+ if (existing)
86
+ return existing;
87
+ }
88
+ const { record, reply } = await this.record(agent, post);
89
+ signal?.throwIfAborted();
90
+ try {
91
+ const response = await agent.com.atproto.repo.createRecord({
92
+ repo: did,
93
+ collection: POST_COLLECTION,
94
+ ...(rkey && { rkey }),
95
+ record: { ...record, createdAt: new Date().toISOString() },
96
+ });
97
+ return {
98
+ uri: response.data.uri,
99
+ cid: response.data.cid,
100
+ ...(reply && { reply }),
101
+ };
102
+ }
103
+ catch (error) {
104
+ throw blueskyError(error, 'Publishing the post');
105
+ }
106
+ });
107
+ this.remember(created.uri, created.cid, created.reply?.root);
108
+ return {
109
+ feed: this.type,
110
+ id: created.uri,
111
+ url: blueskyPostUrl(created.uri),
112
+ publishedAt: new Date(),
113
+ };
114
+ }
115
+ async delete(id) {
116
+ await connectionOf(this.account).use(async (agent) => {
117
+ try {
118
+ await agent.deletePost(id);
119
+ }
120
+ catch (error) {
121
+ throw blueskyError(error, 'Deleting the post');
122
+ }
123
+ });
124
+ this.refs.delete(id);
125
+ }
126
+ async close() { }
127
+ validate(post) {
128
+ const invalid = (message) => new FeedError('bluesky', 'invalid_post', message);
129
+ const length = graphemeLength(post.text);
130
+ if (length > BLUESKY_LIMITS.maxLength) {
131
+ throw invalid(`The text is ${length} graphemes, Bluesky takes ${BLUESKY_LIMITS.maxLength}`);
132
+ }
133
+ const bytes = encoder.encode(post.text).length;
134
+ if (bytes > BLUESKY_LIMITS.maxBytes) {
135
+ throw invalid(`The text is ${bytes} bytes, Bluesky takes ${BLUESKY_LIMITS.maxBytes}`);
136
+ }
137
+ const images = post.images ?? [];
138
+ if (images.length > BLUESKY_LIMITS.maxImages) {
139
+ throw invalid(`The post has ${images.length} images, Bluesky takes ${BLUESKY_LIMITS.maxImages}`);
140
+ }
141
+ if (images.length > 0 && post.link) {
142
+ throw invalid('Bluesky shows either images or a link card: put the link in the text');
143
+ }
144
+ if (!post.text.trim() && images.length === 0 && !post.link) {
145
+ throw invalid('The post is empty');
146
+ }
147
+ for (const [index, image] of images.entries()) {
148
+ assertImage('bluesky', image.image, `Image ${index + 1}`);
149
+ }
150
+ if (post.link?.image)
151
+ assertImage('bluesky', post.link.image, 'The link preview');
152
+ const tags = post.tags ?? [];
153
+ if (tags.length > BLUESKY_LIMITS.maxTags) {
154
+ throw invalid(`The post has ${tags.length} tags, Bluesky takes ${BLUESKY_LIMITS.maxTags}`);
155
+ }
156
+ for (const tag of tags) {
157
+ if (graphemeLength(tag.replace(/^#/, '')) > BLUESKY_LIMITS.maxTagLength) {
158
+ throw invalid(`The tag "${tag}" is longer than ${BLUESKY_LIMITS.maxTagLength} graphemes`);
159
+ }
160
+ }
161
+ }
162
+ async upload(agent, bytes, mimeType) {
163
+ try {
164
+ const response = await agent.uploadBlob(bytes, { encoding: mimeType });
165
+ return response.data.blob;
166
+ }
167
+ catch (error) {
168
+ throw blueskyError(error, 'Uploading an image');
169
+ }
170
+ }
171
+ async embed(agent, post) {
172
+ if (post.images?.length) {
173
+ const images = await Promise.all(post.images.map(async (image, index) => ({
174
+ image: await this.upload(agent, await attachmentBytes('bluesky', image.image, {
175
+ maxBytes: BLUESKY_LIMITS.maxImageBytes,
176
+ what: `Image ${index + 1}`,
177
+ ...(this.fetchImpl && { fetch: this.fetchImpl }),
178
+ }), image.image.mimeType),
179
+ alt: image.alt ?? '',
180
+ ...(image.aspectRatio ? { aspectRatio: image.aspectRatio } : {}),
181
+ })));
182
+ return { $type: 'app.bsky.embed.images', images };
183
+ }
184
+ if (!post.link)
185
+ return undefined;
186
+ const thumb = post.link.image
187
+ ? await this.upload(agent, await attachmentBytes('bluesky', post.link.image, {
188
+ maxBytes: BLUESKY_LIMITS.maxThumbBytes,
189
+ what: 'The link preview',
190
+ ...(this.fetchImpl && { fetch: this.fetchImpl }),
191
+ }), post.link.image.mimeType)
192
+ : undefined;
193
+ return {
194
+ $type: 'app.bsky.embed.external',
195
+ external: {
196
+ uri: post.link.url,
197
+ title: post.link.title ?? '',
198
+ description: post.link.description ?? '',
199
+ ...(thumb ? { thumb } : {}),
200
+ },
201
+ };
202
+ }
203
+ /** The post record for `post`: text with facets, embed, reply, tags and languages. */
204
+ async record(agent, post) {
205
+ const { RichText } = await loadAtproto();
206
+ const rich = new RichText({ text: post.text });
207
+ try {
208
+ await rich.detectFacets(agent);
209
+ }
210
+ catch (error) {
211
+ throw blueskyError(error, 'Resolving the mentions of the post');
212
+ }
213
+ const embed = await this.embed(agent, post);
214
+ const reply = post.replyTo ? await this.replyRef(agent, post.replyTo) : undefined;
215
+ const tags = (post.tags ?? []).map((tag) => tag.replace(/^#/, '')).filter(Boolean);
216
+ return {
217
+ record: {
218
+ $type: POST_COLLECTION,
219
+ text: rich.text,
220
+ ...(rich.facets?.length ? { facets: rich.facets } : {}),
221
+ ...(post.langs?.length ? { langs: post.langs } : {}),
222
+ ...(tags.length ? { tags } : {}),
223
+ ...(embed ? { embed } : {}),
224
+ ...(reply ? { reply } : {}),
225
+ },
226
+ ...(reply && { reply }),
227
+ };
228
+ }
229
+ /** The account's post under `rkey`, from its own PDS, which knows a post as soon as it exists. */
230
+ async findRecord(agent, did, rkey) {
231
+ try {
232
+ const response = await agent.com.atproto.repo.getRecord({
233
+ repo: did,
234
+ collection: POST_COLLECTION,
235
+ rkey,
236
+ });
237
+ if (!response.data.cid)
238
+ return undefined;
239
+ const root = replyRootOf(response.data.value);
240
+ const parent = replyParentOf(response.data.value);
241
+ return {
242
+ uri: response.data.uri,
243
+ cid: response.data.cid,
244
+ ...(root && parent && { reply: { root, parent } }),
245
+ };
246
+ }
247
+ catch (error) {
248
+ const failure = blueskyError(error, 'Looking for the post of an earlier attempt');
249
+ if (failure.code === 'not_found')
250
+ return undefined;
251
+ throw failure;
252
+ }
253
+ }
254
+ /**
255
+ * Where a reply to `uri` goes: from the posts this feed published, from the
256
+ * account's own PDS for its other posts, otherwise from the AppView. A post
257
+ * published a moment ago is not on the AppView yet, so a thread of replies
258
+ * never waits for it.
259
+ */
260
+ async replyRef(agent, uri) {
261
+ const known = this.refs.get(uri);
262
+ if (known)
263
+ return { root: known.root, parent: { uri, cid: known.cid } };
264
+ const match = /^at:\/\/([^/]+)\/app\.bsky\.feed\.post\/([^/]+)$/.exec(uri);
265
+ if (match?.[1] && match[2] && match[1] === agent.did) {
266
+ const own = await this.findRecord(agent, match[1], match[2]);
267
+ if (!own)
268
+ throw new FeedError('bluesky', 'not_found', `No post ${uri} to reply to`);
269
+ const parent = { uri: own.uri, cid: own.cid };
270
+ return { root: own.reply?.root ?? parent, parent };
271
+ }
272
+ let parent;
273
+ try {
274
+ const response = await agent.getPosts({ uris: [uri] });
275
+ parent = response.data.posts[0];
276
+ }
277
+ catch (error) {
278
+ throw blueskyError(error, 'Loading the post to reply to');
279
+ }
280
+ if (!parent)
281
+ throw new FeedError('bluesky', 'not_found', `No post ${uri} to reply to`);
282
+ const root = replyRootOf(parent.record) ?? { uri: parent.uri, cid: parent.cid };
283
+ return { root, parent: { uri: parent.uri, cid: parent.cid } };
284
+ }
285
+ /** Keeps where a published post sits, so replies to it need no lookup. */
286
+ remember(uri, cid, root) {
287
+ this.refs.set(uri, { cid, root: root ?? { uri, cid } });
288
+ if (this.refs.size > MAX_REFS) {
289
+ const oldest = this.refs.keys().next().value;
290
+ if (oldest !== undefined)
291
+ this.refs.delete(oldest);
292
+ }
293
+ }
294
+ }
295
+ function strongRefAt(record, field) {
296
+ if (typeof record !== 'object' || record === null || !('reply' in record))
297
+ return undefined;
298
+ const reply = record.reply;
299
+ if (typeof reply !== 'object' || reply === null || !(field in reply))
300
+ return undefined;
301
+ const ref = reply[field];
302
+ if (typeof ref === 'object' &&
303
+ ref !== null &&
304
+ 'uri' in ref &&
305
+ 'cid' in ref &&
306
+ typeof ref.uri === 'string' &&
307
+ typeof ref.cid === 'string') {
308
+ return { uri: ref.uri, cid: ref.cid };
309
+ }
310
+ return undefined;
311
+ }
312
+ /** The root a post record replies under, where it is a reply. */
313
+ function replyRootOf(record) {
314
+ return strongRefAt(record, 'root');
315
+ }
316
+ /** The post a post record answers, where it is a reply. */
317
+ function replyParentOf(record) {
318
+ return strongRefAt(record, 'parent');
319
+ }
320
+ /** A Bluesky feed. */
321
+ export function blueskyFeed(config) {
322
+ return new BlueskyFeed(config);
323
+ }
324
+ //# sourceMappingURL=feed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feed.js","sourceRoot":"","sources":["../../../src/channels/bluesky/feed.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { BlueskyAccount } from './account.js';
2
+ export type { BlueskyConnectionConfig } from './config.js';
3
+ export { BLUESKY_LIMITS, BlueskyFeed, blueskyFeed, blueskyPostUrl, type BlueskyFeedConfig, } from './feed.js';
4
+ export { BlueskyChannel, blueskyChannel, type BlueskyChannelConfig } from './channel.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/channels/bluesky/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,YAAY,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EACL,cAAc,EACd,WAAW,EACX,WAAW,EACX,cAAc,EACd,KAAK,iBAAiB,GACvB,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { BlueskyAccount } from './account.js';
2
+ export { BLUESKY_LIMITS, BlueskyFeed, blueskyFeed, blueskyPostUrl, } from './feed.js';
3
+ export { BlueskyChannel, blueskyChannel } from './channel.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/channels/bluesky/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,EACL,cAAc,EACd,WAAW,EACX,WAAW,EACX,cAAc,GAEf,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,cAAc,EAAE,cAAc,EAA6B,MAAM,WAAW,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { type ThreadsParams } from './client.js';
2
+ import { type ThreadsTokenOptions } from './token.js';
3
+ export interface ThreadsAccountConfig extends ThreadsTokenOptions {
4
+ /** The Threads user id the token belongs to (default `me`). */
5
+ userId?: string;
6
+ /** The Graph API base (default `https://graph.threads.net/v1.0`). */
7
+ apiBase?: string;
8
+ /** The fetch the client uses, for tests and proxies. */
9
+ fetch?: typeof fetch;
10
+ }
11
+ /**
12
+ * One Threads account: its API client and its long-lived token, kept fresh.
13
+ * Share it between `ThreadsFeed` and `ThreadsChannel` so they renew one
14
+ * token.
15
+ */
16
+ export declare class ThreadsAccount {
17
+ readonly userId: string;
18
+ private readonly client;
19
+ private readonly tokens;
20
+ private readonly holders;
21
+ constructor(config: ThreadsAccountConfig);
22
+ /**
23
+ * Loads the token, renewing it if due, and checks it daily while anyone
24
+ * holds the account. `holder` is who holds it, the caller unless said: a
25
+ * feed and a channel sharing the account each hold it.
26
+ */
27
+ connect(holder?: object): Promise<void>;
28
+ /** Lets `holder` go. The daily token check stops once no one holds the account. */
29
+ close(holder?: object): void;
30
+ /** Renews the token now, whatever its age. */
31
+ renewToken(): Promise<void>;
32
+ get<T>(path: string, params?: ThreadsParams, signal?: AbortSignal): Promise<T>;
33
+ /** The items of a listing, page by page, following its cursors for `maxPages` at most. */
34
+ pages<T>(path: string, params: ThreadsParams, maxPages: number, signal?: AbortSignal): AsyncGenerator<T[]>;
35
+ post<T>(path: string, params?: ThreadsParams, signal?: AbortSignal): Promise<T>;
36
+ delete<T>(path: string, signal?: AbortSignal): Promise<T>;
37
+ }
38
+ /** The account a feed or channel config names, or a new one for its token. */
39
+ export declare function threadsAccountOf(config: {
40
+ account: ThreadsAccount;
41
+ } | ThreadsAccountConfig): ThreadsAccount;
42
+ //# sourceMappingURL=account.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../../src/channels/threads/account.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9F,OAAO,EAAuB,KAAK,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAExE,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED;;;;GAIG;AACH,qBAAa,cAAc;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEjC,MAAM,EAAE,oBAAoB;IASxC;;;;OAIG;IACG,OAAO,CAAC,MAAM,GAAE,MAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnD,mFAAmF;IACnF,KAAK,CAAC,MAAM,GAAE,MAAa,GAAG,IAAI;IAKlC,8CAA8C;IACxC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IAIpF,0FAA0F;IACnF,KAAK,CAAC,CAAC,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,WAAW,GACnB,cAAc,CAAC,CAAC,EAAE,CAAC;IAShB,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IAI/E,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;CAGhE;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,GAAG,oBAAoB,GACzD,cAAc,CAEhB"}