@cogitator-ai/channels 0.15.12 → 0.17.0

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 (120) hide show
  1. package/README.md +129 -23
  2. package/dist/assistant-config.d.ts +78 -0
  3. package/dist/assistant-config.d.ts.map +1 -1
  4. package/dist/assistant-config.js +127 -0
  5. package/dist/assistant-config.js.map +1 -1
  6. package/dist/channels/bluesky/channel.d.ts.map +1 -1
  7. package/dist/channels/bluesky/channel.js +1 -0
  8. package/dist/channels/bluesky/channel.js.map +1 -1
  9. package/dist/channels/email/address.d.ts +44 -0
  10. package/dist/channels/email/address.d.ts.map +1 -0
  11. package/dist/channels/email/address.js +211 -0
  12. package/dist/channels/email/address.js.map +1 -0
  13. package/dist/channels/email/auth.d.ts +59 -0
  14. package/dist/channels/email/auth.d.ts.map +1 -0
  15. package/dist/channels/email/auth.js +212 -0
  16. package/dist/channels/email/auth.js.map +1 -0
  17. package/dist/channels/email/channel.d.ts +256 -0
  18. package/dist/channels/email/channel.d.ts.map +1 -0
  19. package/dist/channels/email/channel.js +701 -0
  20. package/dist/channels/email/channel.js.map +1 -0
  21. package/dist/channels/email/errors.d.ts +11 -0
  22. package/dist/channels/email/errors.d.ts.map +1 -0
  23. package/dist/channels/email/errors.js +13 -0
  24. package/dist/channels/email/errors.js.map +1 -0
  25. package/dist/channels/email/imap.d.ts +125 -0
  26. package/dist/channels/email/imap.d.ts.map +1 -0
  27. package/dist/channels/email/imap.js +309 -0
  28. package/dist/channels/email/imap.js.map +1 -0
  29. package/dist/channels/email/index.d.ts +7 -0
  30. package/dist/channels/email/index.d.ts.map +1 -0
  31. package/dist/channels/email/index.js +3 -0
  32. package/dist/channels/email/index.js.map +1 -0
  33. package/dist/channels/email/mime.d.ts +71 -0
  34. package/dist/channels/email/mime.d.ts.map +1 -0
  35. package/dist/channels/email/mime.js +83 -0
  36. package/dist/channels/email/mime.js.map +1 -0
  37. package/dist/channels/email/multipart.d.ts +28 -0
  38. package/dist/channels/email/multipart.d.ts.map +1 -0
  39. package/dist/channels/email/multipart.js +102 -0
  40. package/dist/channels/email/multipart.js.map +1 -0
  41. package/dist/channels/email/providers.d.ts +49 -0
  42. package/dist/channels/email/providers.d.ts.map +1 -0
  43. package/dist/channels/email/providers.js +292 -0
  44. package/dist/channels/email/providers.js.map +1 -0
  45. package/dist/channels/email/reply.d.ts +9 -0
  46. package/dist/channels/email/reply.d.ts.map +1 -0
  47. package/dist/channels/email/reply.js +122 -0
  48. package/dist/channels/email/reply.js.map +1 -0
  49. package/dist/channels/github/channel.d.ts +222 -0
  50. package/dist/channels/github/channel.d.ts.map +1 -0
  51. package/dist/channels/github/channel.js +736 -0
  52. package/dist/channels/github/channel.js.map +1 -0
  53. package/dist/channels/github/client.d.ts +45 -0
  54. package/dist/channels/github/client.d.ts.map +1 -0
  55. package/dist/channels/github/client.js +119 -0
  56. package/dist/channels/github/client.js.map +1 -0
  57. package/dist/channels/github/events.d.ts +49 -0
  58. package/dist/channels/github/events.d.ts.map +1 -0
  59. package/dist/channels/github/events.js +147 -0
  60. package/dist/channels/github/events.js.map +1 -0
  61. package/dist/channels/github/index.d.ts +4 -0
  62. package/dist/channels/github/index.d.ts.map +1 -0
  63. package/dist/channels/github/index.js +4 -0
  64. package/dist/channels/github/index.js.map +1 -0
  65. package/dist/channels/slack.d.ts.map +1 -1
  66. package/dist/channels/slack.js +2 -1
  67. package/dist/channels/slack.js.map +1 -1
  68. package/dist/channels/telegram.d.ts.map +1 -1
  69. package/dist/channels/telegram.js +14 -6
  70. package/dist/channels/telegram.js.map +1 -1
  71. package/dist/channels/threads/channel.d.ts.map +1 -1
  72. package/dist/channels/threads/channel.js +1 -0
  73. package/dist/channels/threads/channel.js.map +1 -1
  74. package/dist/channels/webchat.d.ts +8 -0
  75. package/dist/channels/webchat.d.ts.map +1 -1
  76. package/dist/channels/webchat.js +54 -15
  77. package/dist/channels/webchat.js.map +1 -1
  78. package/dist/channels/whatsapp.d.ts.map +1 -1
  79. package/dist/channels/whatsapp.js +13 -0
  80. package/dist/channels/whatsapp.js.map +1 -1
  81. package/dist/formatters/html.d.ts +16 -0
  82. package/dist/formatters/html.d.ts.map +1 -0
  83. package/dist/formatters/html.js +535 -0
  84. package/dist/formatters/html.js.map +1 -0
  85. package/dist/formatters/markdown.d.ts.map +1 -1
  86. package/dist/formatters/markdown.js +2 -0
  87. package/dist/formatters/markdown.js.map +1 -1
  88. package/dist/gateway.d.ts +91 -1
  89. package/dist/gateway.d.ts.map +1 -1
  90. package/dist/gateway.js +345 -46
  91. package/dist/gateway.js.map +1 -1
  92. package/dist/heartbeat.d.ts +5 -1
  93. package/dist/heartbeat.d.ts.map +1 -1
  94. package/dist/heartbeat.js +13 -3
  95. package/dist/heartbeat.js.map +1 -1
  96. package/dist/inbound-debounce.d.ts +4 -1
  97. package/dist/inbound-debounce.d.ts.map +1 -1
  98. package/dist/inbound-debounce.js +4 -2
  99. package/dist/inbound-debounce.js.map +1 -1
  100. package/dist/index.d.ts +8 -2
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +6 -2
  103. package/dist/index.js.map +1 -1
  104. package/dist/merge-messages.d.ts +3 -2
  105. package/dist/merge-messages.d.ts.map +1 -1
  106. package/dist/merge-messages.js +4 -2
  107. package/dist/merge-messages.js.map +1 -1
  108. package/dist/message-queue.d.ts +14 -4
  109. package/dist/message-queue.d.ts.map +1 -1
  110. package/dist/message-queue.js +36 -35
  111. package/dist/message-queue.js.map +1 -1
  112. package/dist/runtime-builder.d.ts +9 -0
  113. package/dist/runtime-builder.d.ts.map +1 -1
  114. package/dist/runtime-builder.js +149 -5
  115. package/dist/runtime-builder.js.map +1 -1
  116. package/dist/thread-key.d.ts +50 -0
  117. package/dist/thread-key.d.ts.map +1 -0
  118. package/dist/thread-key.js +82 -0
  119. package/dist/thread-key.js.map +1 -0
  120. package/package.json +26 -8
package/README.md CHANGED
@@ -15,7 +15,8 @@ pnpm add discord.js # Discord
15
15
  pnpm add @slack/bolt # Slack
16
16
  pnpm add @whiskeysockets/baileys # WhatsApp, 6.x or 7.x (+ qrcode-terminal to print the pairing QR)
17
17
  pnpm add ws # WebChat
18
- pnpm add @atproto/api # Bluesky (Threads needs no SDK)
18
+ pnpm add @atproto/api # Bluesky (Threads and GitHub need no SDK)
19
+ pnpm add nodemailer imapflow postal-mime # Email: SMTP, IMAP and MIME parsing (webhooks need nodemailer, plus postal-mime for raw MIME)
19
20
 
20
21
  # RuntimeBuilder (`cogitator up`)
21
22
  pnpm add better-sqlite3 # SQLite memory, knowledge graph and core facts (always needed)
@@ -134,7 +135,7 @@ slackChannel({
134
135
  });
135
136
  ```
136
137
 
137
- Supports: DMs, channel messages (via @mention, the mention is stripped from the text), threads (replies go to the thread root), file shares, Socket Mode (no public URL), streaming via chat.update, reactions. Set `mentionOnly: true` to ignore channel messages that do not mention the bot when the app also subscribes to `message.channels`. In `RuntimeBuilder`, Socket Mode is on when `SLACK_APP_TOKEN` is set; otherwise Slack runs in HTTP mode on `SLACK_PORT` (default 3000). Docs: [Slack](https://cogitator.app/docs/channels/slack).
138
+ Supports: DMs, channel messages (via @mention, the mention is stripped from the text, answered in a new Slack thread that is a conversation of its own without earlier history, `topicId` is the thread's `ts`), threads (replies go to the thread root and continue its conversation), file shares, Socket Mode (no public URL), streaming via chat.update, reactions. Set `mentionOnly: true` to ignore channel messages that do not mention the bot when the app also subscribes to `message.channels`. In `RuntimeBuilder`, Socket Mode is on when `SLACK_APP_TOKEN` is set; otherwise Slack runs in HTTP mode on `SLACK_PORT` (default 3000). Docs: [Slack](https://cogitator.app/docs/channels/slack).
138
139
 
139
140
  ### WhatsApp
140
141
 
@@ -167,6 +168,7 @@ webchatChannel({
167
168
  path: '/ws',
168
169
  auth: (token) => token === process.env.WEBCHAT_TOKEN,
169
170
  maxPayload: 1024 * 1024, // bytes per incoming frame (default 1 MiB)
171
+ // routes: { '/github/webhook': github.webhookListener() }, // plain HTTP routes on the same port
170
172
  });
171
173
  ```
172
174
 
@@ -224,17 +226,60 @@ const threads = threadsChannel({
224
226
 
225
227
  The agent answers replies to the bot's posts and mentions of it, from Meta's webhooks (verification and `X-Hub-Signature-256` checked) or, without `webhook`, by polling, which skips replies people make to each other. Answers go out finished, as a chain of 500-character replies when long. The Threads API has no direct messages. Docs: [Threads](https://cogitator.app/docs/channels/threads).
226
228
 
229
+ ### GitHub
230
+
231
+ ```typescript
232
+ import { githubChannel } from '@cogitator-ai/channels';
233
+
234
+ const github = githubChannel({
235
+ token: process.env.GITHUB_CHANNEL_TOKEN!, // a bot account's fine-grained token, or () => an App installation token
236
+ webhook: {
237
+ secret: process.env.GITHUB_WEBHOOK_SECRET!, // checked against X-Hub-Signature-256
238
+ port: 8787, // its own server at /github/webhook, or mount github.handleWebhook / webhookListener()
239
+ },
240
+ trigger: 'mention', // or 'all'
241
+ repositories: ['acme/*'], // default: every repository that sends events, with a warning
242
+ associations: ['OWNER', 'MEMBER', 'COLLABORATOR'], // the default, or 'any'
243
+ });
244
+ ```
245
+
246
+ The agent answers new issues and pull requests, comments on them, reviews with a body and comments on lines of a diff, from a repository or organization webhook. Each issue or pull request is a conversation, `channelId` `owner/repo#number`, and answers are comments on it. A comment on a line is answered in its review thread, which is the message's `topicId`, so each review thread is a conversation of its own. Deliveries are answered at once and handled after, each once by its `X-GitHub-Delivery` and the comment it carries (remembered in memory). It answers only the repository's owner, members and collaborators unless `associations` or `authors` say otherwise, since what people write steers an agent that holds the token, so give the bot an account and a token of its own scoped to its repositories. The bot skips its own comments and other bots (`allowBots` lets them in), and by default answers only mentions of `@login`, outside code and quotes, plus the next comment of someone it answered and comments in review threads it replied in. Answers go out finished (GitHub notifies people of a comment's first text, `stream: true` edits a comment as it grows, at most every 3 seconds), as several comments past 65536 characters. Reactions use GitHub's eight. GitHub has no upload API for comments, so `sendFile` links a file with a public `url` and refuses a buffer. A GitHub App installation token cannot read `GET /user`: set `login` to `<app-slug>[bot]`. Docs: [GitHub](https://cogitator.app/docs/channels/github).
247
+
248
+ ### Email
249
+
250
+ ```typescript
251
+ import { emailChannel } from '@cogitator-ai/channels';
252
+
253
+ const email = emailChannel({
254
+ address: 'assistant@example.com', // sends from it, never answers it
255
+ allowFrom: ['example.com', 'ann@partner.org'], // default: nobody, with a warning
256
+ imap: {
257
+ host: 'imap.gmail.com',
258
+ auth: { user: 'assistant@example.com', pass: process.env.EMAIL_IMAP_PASSWORD! },
259
+ },
260
+ smtp: {
261
+ host: 'smtp.gmail.com',
262
+ port: 587,
263
+ auth: { user: 'assistant@example.com', pass: process.env.EMAIL_SMTP_PASSWORD! },
264
+ }, // or { transport } for any nodemailer transport
265
+ // or instead of imap, a provider's inbound webhook:
266
+ // webhook: { provider: 'mailgun', signingKey: process.env.EMAIL_MAILGUN_SIGNING_KEY!, port: 8788 },
267
+ });
268
+ ```
269
+
270
+ The agent answers mail in its thread. Mail comes from a mailbox over IMAP (IDLE reports new mail at once, a poll every minute catches the rest, a message is marked read once the Gateway took it, so a restart reads only new mail, a refused or dropped one stays or becomes unread again, mail over 25 MB is skipped, a dropped connection is opened again with a wait that doubles up to a minute) or from the inbound webhook of Mailgun (HMAC of timestamp and token, refused after 5 minutes and handled once), Postmark or SendGrid (neither signs, so the URL carries basic auth or a `token`), answered `503` when the Gateway does not take the mail, so the provider retries. Answers go out over SMTP with `nodemailer`, as HTML rendered from the Markdown with a plain text alternative, a `Re:` subject and `In-Reply-To` and `References` set, so mail clients keep the thread. A sender is a conversation partner: `channelId` and `userId` are the address in lower case, and `topicId` is the thread's first `Message-ID`, so each email thread is a conversation of its own. The agent reads the plain text part (or the HTML as text) without the quoted history and the signature, with the subject on a thread's first mail, and attachments up to 10 MB. Mail from the bot itself, mail with the `X-Cogitator` header it puts on what it sends, auto-replies, bounces and bulk mail are skipped, and each `Message-ID` is handled once. Email is spoofable: the bot answers only `allowFrom` and `owners` (the address outside the quotes of `From`), drops mail whose DKIM, SPF or DMARC results fail for the `From` domain (`senderAuth: 'required'` also drops mail without results), and gives owner mail to the agent only with a passing result. It trusts only results the receiving side wrote: Mailgun's and SendGrid's, Postmark's spam tests, and over IMAP the `Authentication-Results` of `trustedAuthservIds` (such as `mx.google.com`), without which IMAP mail has no sender authentication. Answers cannot be edited. Docs: [Email](https://cogitator.app/docs/channels/email).
271
+
227
272
  ## Platform Comparison
228
273
 
229
- | Feature | Telegram | Discord | Slack | WhatsApp | WebChat | Bluesky | Threads |
230
- | ------------------ | ------------ | ------- | --------- | -------- | --------- | ------------------ | ------------------ |
231
- | Streaming (edit) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ (sent finished) | ❌ (sent finished) |
232
- | Reactions | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
233
- | Typing indicator | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ |
234
- | Photos → vision | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
235
- | Voice → STT | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
236
- | Max message length | 4096 | 2000 | 40000 | 65536 | unlimited | 300 per post | 500 per post |
237
- | Public URL needed | webhook only | no | HTTP only | no | no | no | webhooks only |
274
+ | Feature | Telegram | Discord | Slack | WhatsApp | WebChat | Bluesky | Threads | GitHub | Email |
275
+ | ------------------ | ------------ | ------- | --------- | -------- | --------- | ------------------ | ------------------ | ------------------- | ------------------ |
276
+ | Streaming (edit) | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ (sent finished) | ❌ (sent finished) | with `stream: true` | ❌ (sent finished) |
277
+ | Reactions | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ (8 kinds) | ❌ |
278
+ | Typing indicator | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
279
+ | Photos → vision | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ (attachments) |
280
+ | Voice → STT | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ (attachments) |
281
+ | Max message length | 4096 | 2000 | 40000 | 65536 | unlimited | 300 per post | 500 per post | 65536 per comment | unlimited |
282
+ | Public URL needed | webhook only | no | HTTP only | no | no | no | webhooks only | yes (webhook) | webhooks only |
238
283
 
239
284
  Outbound calls (`sendText`, `editText`, `sendFile`, `deleteMessage`) throw when the channel is not started, the target chat is unavailable or the platform rejects the request — wrap direct calls in `try/catch`. WebChat is the exception: only `sendText` throws for a disconnected client, the other calls are dropped. `sendText` returns the platform message id (for Discord, the id of the first chunk; continuation chunks are edited and deleted with it).
240
285
 
@@ -287,6 +332,7 @@ Docs: [Social Feeds](https://cogitator.app/docs/channels/feeds).
287
332
 
288
333
  Routes incoming messages to your agent. Handles:
289
334
 
335
+ - Conversation threads: one per user per conversation (chat, forum topic, Slack thread, Bluesky or Threads post thread, GitHub issue, pull request or review thread, email thread), answered one message at a time
290
336
  - Session management (per-user, per-channel) with an optional custom `sessionManager`
291
337
  - History compaction, hierarchical into a handoff of grounded atoms or with LLM-written summaries
292
338
  - Streaming with `StreamBuffer` when `stream` is set (message editing, splits at the platform limit without losing text); without `stream` the full answer is sent once the run finishes
@@ -305,7 +351,8 @@ const gateway = new Gateway({
305
351
  channels,
306
352
  memory, // MemoryAdapter — enables sessions and history
307
353
  session: {
308
- threadKey: (msg) => `${msg.channelType}:${msg.userId}`,
354
+ // default: `${channelType}:${conversation}:${userId}`, see Conversation threads below
355
+ threadKey: (msg) => `${msg.channelType}:${msg.channelId}`, // one thread per chat, shared by its members
309
356
  // compact once a conversation holds 50 messages (or `threshold` tokens), keep about 4000 tokens of the newest turns verbatim
310
357
  compaction: {
311
358
  strategy: 'hierarchical',
@@ -319,15 +366,43 @@ const gateway = new Gateway({
319
366
  });
320
367
 
321
368
  gateway.stats; // { uptime, activeSessions, totalSessions, messagesToday, connectedChannels }
322
- gateway.getSessions(); // [{ threadId, userName, messageCount, lastActiveAt, active }]
323
- await gateway.compactThread('telegram:42'); // force compaction of one conversation
369
+ gateway.getSessions(); // [{ threadId: 'telegram:42:42', userName, messageCount, lastActiveAt, active }], one per conversation
370
+ await gateway.compactThread('telegram:42:42'); // force compaction of one conversation
324
371
  await gateway.compactAll(); // every thread served since start and of every stored session: "Compacted 2 of 3 threads"
325
- await gateway.injectMessage(msg); // feed a synthetic message (used by the scheduler)
326
- await gateway.stop();
372
+ await gateway.injectMessage(msg); // feed a synthetic message and wait for its answer (used by the scheduler)
373
+ await gateway.idle(); // wait until every queued message is answered
374
+ await gateway.stop(); // answers what is queued first, up to drainTimeout (30 s), then aborts the rest
327
375
  ```
328
376
 
329
377
  `GatewayConfig.owner` is deprecated and never read: set owners on `ownerCommands({ ownerIds })` and `dmPolicy({ ownerIds })` (see [Middleware](#middleware)).
330
378
 
379
+ ### Conversation threads
380
+
381
+ A thread is the conversation memory and the queue of one user in one conversation. The default key is `channelType:conversation:userId`, where the conversation is the message's `conversationId` if it has one, else its `channelId` plus `:topicId` when it has a topic (`defaultThreadKey` computes it):
382
+
383
+ | Channel | Conversation | Example thread |
384
+ | ---------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------- |
385
+ | Telegram | chat, plus the forum topic | `telegram:-100123:7:42` |
386
+ | Slack | DM, or the Slack thread of a channel message (`topicId`, the thread's `ts`) | `slack:C123:1712.5:U1` |
387
+ | Discord | channel, a thread is a channel of its own | `discord:98765:1234` |
388
+ | Bluesky, Threads | the post thread's root (`conversationId`), not the reply post | `bluesky:thread:at://did:plc:a/app.bsky.feed.post/1:did:plc:b` |
389
+ | GitHub | issue or pull request, plus the review thread (`topicId`) | `github:acme/app#12:583231`, `github:acme/app#12:1840022:583231` |
390
+ | Email | sender, plus the email thread (`topicId`, its first `Message-ID`) | `email:ann@example.com:<a1@example.com>:ann@example.com` |
391
+ | WhatsApp | chat, a chat addressed by LID by the phone-number jid | `whatsapp:15550001111@s.whatsapp.net:15550001111` |
392
+ | WebChat | client | `webchat:c7f2:c7f2` |
393
+
394
+ So a user keeps a separate thread in their private chat, in each group and in each topic, and every reply in a Bluesky or Threads post thread lands in the same one. In a Slack channel each top-level message is answered in a new Slack thread, a conversation of its own without the history of earlier ones, and its follow-ups in that thread continue it, while a DM is one conversation. On GitHub each issue or pull request is a conversation, and each review thread another one. By email each thread is a conversation, however its subject changes. A WhatsApp chat that reaches a person by LID gets their phone-number jid as its `conversationId` when WhatsApp shares it, so it stays one thread with the chat addressed by phone number.
395
+
396
+ The gateway keeps the conversations of each user in their session's metadata (`conversations`, up to 50, most recent first), and `compactAll()` finds their threads there after a restart. A run gets the `topicId` and `conversationId` of its message, and its tools see them in their context, so `schedule_task` stores them with the task and `HeartbeatScheduler` fires it into the same topic and thread, even when the user has moved on to another one. A task without them is answered in the topic and thread of the user's most recent conversation in its chat. With a custom `threadKey` the gateway keeps no conversations and leaves stored sessions out of `compactAll()`, except with `legacyThreadKey`, whose thread of each stored session it still finds.
397
+
398
+ Up to 0.15 the key was `channelType:userId`, one thread per user per channel type. Threads stored under it are not found by the new key. To keep them, pass `legacyThreadKey`:
399
+
400
+ ```typescript
401
+ import { legacyThreadKey } from '@cogitator-ai/channels';
402
+
403
+ new Gateway({ ...config, session: { threadKey: legacyThreadKey } });
404
+ ```
405
+
331
406
  `session.compaction` is a `CompactionConfig`. With `strategy: 'hierarchical'` the older messages become a handoff of grounded atoms (facts, tasks, decisions, constraints, errors, files, open questions) and the newest `keepRecentTokens` stay verbatim, see [Hierarchical Compaction](https://cogitator.app/docs/memory#hierarchical-compaction). The gateway's summarizer asks the model and prompt each call names, falling back to `summaryModel` and `summaryPrompt`, then to the agent's model and a default prompt. `compactAll()` goes one thread at a time, past those that fail, and lists them after the count.
332
407
 
333
408
  `brief(msg)` returns notes for the run of each message, passed as `RunOptions.brief`: they go with the input, after what memory recalls for it, and are not saved to the thread. Put what changes from message to message there, such as the current time, rather than in the agent's instructions, so the instructions stay the same and the prompt cache keeps serving them.
@@ -434,20 +509,22 @@ const gateway = new Gateway({
434
509
 
435
510
  ## Queue Modes
436
511
 
437
- Control concurrent message handling per user:
512
+ Control how the messages of one thread wait for each other. Different threads always run side by side.
438
513
 
439
514
  ```typescript
440
515
  const gateway = new Gateway({
441
516
  // ...
442
- queueMode: 'sequential', // 'parallel' | 'sequential' | 'interrupt' | 'collect'
517
+ queueMode: 'sequential', // the default, or 'parallel' | 'interrupt' | 'collect'
443
518
  });
444
519
  ```
445
520
 
446
- - **parallel** — default, all messages processed immediately
447
- - **sequential** — FIFO per thread, wait for current to finish
448
- - **interrupt** — abort the current run (its signal is passed to `cogitator.run`), start the new message
521
+ - **sequential** - default, FIFO per thread: a message waits until the one before it is answered
522
+ - **parallel** - every message runs at once, also in the same thread (the default up to 0.15)
523
+ - **interrupt** - abort the current run (its signal is passed to `cogitator.run`), start the new message
449
524
  - **collect** - buffer during processing, merge per chat and topic on idle
450
525
 
526
+ With a queue, a channel's message handler returns once the message is queued, so a channel that reads its updates one by one (Telegram long polling, the Bluesky and Threads polls) goes on to other chats, button presses and stop buttons while a thread is busy. `injectMessage` still resolves once the message is answered, and `idle()` waits for every queued message. Since the channel has confirmed a queued message to its platform already, `stop()` drains the queues before it stops the channels: it waits up to `drainTimeout` (default 30000 ms) for the queued messages and the runs in progress, then aborts the runs still going and drops what still waits. Messages that come in while it stops are dropped and reported to `onError`, a second `stop()` returns the same promise, and `injectMessage` rejects when its message was not answered (failed run, aborted or dropped by `stop()`).
527
+
451
528
  ## Formatting Pipeline
452
529
 
453
530
  Platform-specific markdown conversion applied automatically (code spans and fences are never touched):
@@ -588,7 +665,7 @@ const scheduler = new HeartbeatScheduler(store, {
588
665
  scheduler.start();
589
666
  ```
590
667
 
591
- Schedule types: `cron` (recurring, next fire computed with `cron-parser`, honors `timezone`), `recurring` (interval), `fixed` (one-shot). Consecutive failures are carried across reschedules; after `maxRetries` the job is skipped until `enableJob()`. A fired job reaches `onFire` as a message on the `channel` / `channelId` / `userId` stored in its `metadata`, and `staggerMs` adds a random delay before the first poll. Docs: [Scheduler](https://cogitator.app/docs/channels/scheduler).
668
+ Schedule types: `cron` (recurring, next fire computed with `cron-parser`, honors `timezone`), `recurring` (interval), `fixed` (one-shot). Consecutive failures are carried across reschedules, and a one-shot job whose `onFire` throws stays pending to fire again (unless `bestEffort`). After `maxRetries` the job is skipped until `enableJob()`. A fired job reaches `onFire` as a message on the `channel` / `channelId` / `userId` / `topicId` / `conversationId` stored in its `metadata`, and `staggerMs` adds a random delay before the first poll. Docs: [Scheduler](https://cogitator.app/docs/channels/scheduler).
592
669
 
593
670
  With a store that claims timers (`claimTtl` / `renew` / `release`, e.g. the Redis/Postgres timer stores of `@cogitator-ai/workflows`), the claim is renewed right before a task fires and every `claimTtl / 3` while it runs; `onClaimLost(entry)` reports a claim that is gone (the task is skipped before firing, or another worker may fire it too). Claims are released for disabled tasks, tasks over `maxRetries` and overdue tasks not reached before `stop()`.
594
671
 
@@ -628,9 +705,17 @@ await runtime.cleanup();
628
705
 
629
706
  `hooks` and `approvals` are passed to the gateway; `approvals` is merged over the config's `approvals` block (`approveWords`, `denyWords`, `notAllowedMessage`) and wins, so use it for what YAML cannot hold, such as a custom `format`.
630
707
 
708
+ The gateway of a `RuntimeBuilder` uses the defaults: a thread per user per conversation, answered one message at a time. The `session` block of `cogitator.yml` changes them: `threadKey: legacy` keeps the threads stored up to 0.15 (`legacyThreadKey`), and `queueMode` takes any [queue mode](#queue-modes).
709
+
710
+ ```yaml
711
+ session:
712
+ threadKey: legacy # or conversation (default)
713
+ queueMode: parallel # sequential (default), interrupt, collect
714
+ ```
715
+
631
716
  For a parsed YAML file, validate it first with `new RuntimeBuilder(AssistantConfigSchema.parse(yamlObject), process.env)` (the schema is exported, along with the `AssistantConfigInput` / `AssistantConfigOutput` types).
632
717
 
633
- - **Channels:** the terminal REPL plus `channels.telegram` (`TG_TOKEN` or `TELEGRAM_TOKEN`), `channels.discord` (`DISCORD_TOKEN`) and `channels.slack` (`SLACK_BOT_TOKEN`, `SLACK_SIGNING_SECRET`, optional `SLACK_APP_TOKEN` / `SLACK_PORT`). A configured channel without its token is skipped with a warning. `channels.whatsapp` (`{ ownerIds?, sessionPath? }`, owner ids are phone numbers without `@s.whatsapp.net`, the session defaults to `~/.cogitator/whatsapp-session`) needs `@whiskeysockets/baileys`. `channels.webchat` (`{ port?, path? }`, default `8080` and `/ws`, no `ownerIds`) needs `ws` and starts only with `WEBCHAT_TOKEN` set, and clients connect with `?token=<WEBCHAT_TOKEN>`. `channels.bluesky` (`{ ownerIds?, posts?, directMessages?, pollInterval?, tokenPath? }`, owner ids are DIDs) needs `@atproto/api` and starts with `BLUESKY_HANDLE` and `BLUESKY_APP_PASSWORD`. `channels.threads` (`{ ownerIds?, webhook?: { port, path? }, pollInterval?, tokenPath? }`, owner ids are usernames) starts with `THREADS_ACCESS_TOKEN`, and with `THREADS_APP_SECRET` and `THREADS_VERIFY_TOKEN` for webhooks. Both keep their session or token in `tokenPath` (default `~/.cogitator/tokens.json`).
718
+ - **Channels:** the terminal REPL plus `channels.telegram` (`TG_TOKEN` or `TELEGRAM_TOKEN`), `channels.discord` (`DISCORD_TOKEN`) and `channels.slack` (`SLACK_BOT_TOKEN`, `SLACK_SIGNING_SECRET`, optional `SLACK_APP_TOKEN` / `SLACK_PORT`). A configured channel without its token is skipped with a warning. `channels.whatsapp` (`{ ownerIds?, sessionPath? }`, owner ids are phone numbers without `@s.whatsapp.net`, the session defaults to `~/.cogitator/whatsapp-session`) needs `@whiskeysockets/baileys`. `channels.webchat` (`{ port?, path? }`, default `8080` and `/ws`, no `ownerIds`) needs `ws` and starts only with `WEBCHAT_TOKEN` set, and clients connect with `?token=<WEBCHAT_TOKEN>`. `channels.bluesky` (`{ ownerIds?, posts?, directMessages?, pollInterval?, tokenPath? }`, owner ids are DIDs) needs `@atproto/api` and starts with `BLUESKY_HANDLE` and `BLUESKY_APP_PASSWORD`. `channels.threads` (`{ ownerIds?, webhook?: { port, path? }, pollInterval?, tokenPath? }`, owner ids are usernames) starts with `THREADS_ACCESS_TOKEN`, and with `THREADS_APP_SECRET` and `THREADS_VERIFY_TOKEN` for webhooks. Both keep their session or token in `tokenPath` (default `~/.cogitator/tokens.json`). `channels.github` (`{ ownerIds?, webhook?: { port?, path? }, trigger?, repositories?, associations?, authors?, login?, allowBots?, stream? }`, owner ids are numeric user ids, the webhook server defaults to port `8787` at `/github/webhook`) starts with `GITHUB_CHANNEL_TOKEN` (falling back to `GITHUB_TOKEN` with a warning) and `GITHUB_WEBHOOK_SECRET`, and calls `GITHUB_API_URL` when set (GitHub Enterprise Server). `channels.email` (`{ ownerIds?, address?, name?, aliases?, allowFrom?, senderAuth?, trustedAuthservIds?, subject?, imap?: { host?, port?, secure?, mailbox?, pollInterval?, lookbackDays? }, smtp?: { host?, port?, secure? }, webhook?: { provider, port?, path? } }`, owner ids are addresses, allowed and given owner rights with a passing sender authentication, the webhook server defaults to port `8788` at `/email/webhook`) needs `nodemailer`, plus `imapflow` and `postal-mime` for IMAP. It takes the address, hosts and ports from the file or `EMAIL_ADDRESS`, `EMAIL_IMAP_HOST`, `EMAIL_IMAP_PORT`, `EMAIL_SMTP_HOST` and `EMAIL_SMTP_PORT`, the passwords from `EMAIL_IMAP_PASSWORD` and `EMAIL_SMTP_PASSWORD` (users `EMAIL_IMAP_USER` and `EMAIL_SMTP_USER`, default the address), and reads over IMAP when `imap` is set or `EMAIL_IMAP_HOST` is. A Mailgun webhook needs `EMAIL_MAILGUN_SIGNING_KEY`, Postmark and SendGrid `EMAIL_WEBHOOK_TOKEN` (`?token=` in the URL) or `EMAIL_WEBHOOK_USER` and `EMAIL_WEBHOOK_PASSWORD` (basic auth).
634
719
 
635
720
  - **Memory:** `memory.adapter: sqlite` (default, `memory.path`, default `~/.cogitator/memory.db`) or `postgres` (`memory.connectionString`, `DATABASE_URL` or `POSTGRES_URL`, requires `pg`). Core facts always live in the SQLite file, as memory items with their history. The knowledge graph (`memory.knowledgeGraph`) and auto-extraction (`memory.autoExtract`) are on by default, and the memory tools keep memory items in the memory store too: `remember` keeps a fact as the user's (an `active` item, a core fact) only when its `quote` is in one of the run user's own messages on the thread's active branch, else as a suggestion, `recall` searches the items of the user and the thread, and `forget` lets go only the run's own that hold the query as whole words (a run without a user keeps its facts in the thread's memory). The assistant's agent id is its `name`, the same across restarts. `memory.compaction.threshold` enables history compaction, hierarchical, keeping about 4000 tokens of the newest turns verbatim.
636
721
  - **Fresh context:** the gateway builds an agent per message: instructions (with known user facts) and the `/model` override are resolved each time. The current date and time go to each run as its `brief`, with the input, so they do not change the instructions and their prompt cache. `runtime.agent` is the base agent.
@@ -674,6 +759,27 @@ THREADS_ACCESS_TOKEN=... # a long-lived token
674
759
  THREADS_APP_SECRET=... # webhooks only
675
760
  THREADS_VERIFY_TOKEN=... # webhooks only
676
761
 
762
+ # GitHub (a webhook delivers to port 8787 at /github/webhook)
763
+ GITHUB_CHANNEL_TOKEN=github_pat_... # a separate bot account's token, scoped to the repositories it answers in
764
+ GITHUB_TOKEN=ghp_... # capabilities.github, and the channel's fallback (with a warning)
765
+ GITHUB_WEBHOOK_SECRET=... # the secret set on the webhook
766
+ GITHUB_API_URL=... # GitHub Enterprise Server only, https://<host>/api/v3
767
+
768
+ # Email (channels.email, hosts and ports may be in cogitator.yml instead)
769
+ EMAIL_ADDRESS=assistant@example.com
770
+ EMAIL_IMAP_HOST=imap.gmail.com # reading over IMAP
771
+ EMAIL_IMAP_PORT=993
772
+ EMAIL_IMAP_USER=... # default EMAIL_ADDRESS
773
+ EMAIL_IMAP_PASSWORD=... # an app password for Gmail and Outlook
774
+ EMAIL_SMTP_HOST=smtp.gmail.com
775
+ EMAIL_SMTP_PORT=587 # 465 for TLS from the start
776
+ EMAIL_SMTP_USER=... # default EMAIL_ADDRESS
777
+ EMAIL_SMTP_PASSWORD=...
778
+ EMAIL_MAILGUN_SIGNING_KEY=... # webhook.provider: mailgun
779
+ EMAIL_WEBHOOK_TOKEN=... # webhook.provider: postmark or sendgrid, ?token= in the URL
780
+ EMAIL_WEBHOOK_USER=... # or basic auth in the URL, https://user:password@host/email/webhook
781
+ EMAIL_WEBHOOK_PASSWORD=...
782
+
677
783
  # STT (optional, for voice messages — pick one)
678
784
  DEEPGRAM_API_KEY=... # highest priority
679
785
  GROQ_API_KEY=... # free tier
@@ -1,4 +1,8 @@
1
1
  import { z } from 'zod';
2
+ /** An email address, as `channels.email` takes them */
3
+ export declare const EMAIL_ADDRESS_PATTERN: RegExp;
4
+ /** An entry of `channels.email.allowFrom`: an address, a domain, `*.domain`, `@domain` or `*` */
5
+ export declare const EMAIL_ALLOW_FROM_PATTERN: RegExp;
2
6
  export declare const AssistantConfigSchema: z.ZodObject<{
3
7
  name: z.ZodString;
4
8
  personality: z.ZodString;
@@ -45,6 +49,68 @@ export declare const AssistantConfigSchema: z.ZodObject<{
45
49
  pollInterval: z.ZodOptional<z.ZodNumber>;
46
50
  tokenPath: z.ZodOptional<z.ZodString>;
47
51
  }, z.core.$strip>>;
52
+ github: z.ZodOptional<z.ZodObject<{
53
+ ownerIds: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodPipe<z.ZodNumber, z.ZodTransform<string, number>>]>>>;
54
+ webhook: z.ZodDefault<z.ZodObject<{
55
+ port: z.ZodDefault<z.ZodNumber>;
56
+ path: z.ZodOptional<z.ZodString>;
57
+ }, z.core.$strip>>;
58
+ trigger: z.ZodOptional<z.ZodEnum<{
59
+ mention: "mention";
60
+ all: "all";
61
+ }>>;
62
+ repositories: z.ZodOptional<z.ZodArray<z.ZodString>>;
63
+ associations: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodEnum<{
64
+ OWNER: "OWNER";
65
+ MEMBER: "MEMBER";
66
+ COLLABORATOR: "COLLABORATOR";
67
+ CONTRIBUTOR: "CONTRIBUTOR";
68
+ FIRST_TIME_CONTRIBUTOR: "FIRST_TIME_CONTRIBUTOR";
69
+ FIRST_TIMER: "FIRST_TIMER";
70
+ MANNEQUIN: "MANNEQUIN";
71
+ NONE: "NONE";
72
+ }>>, z.ZodLiteral<"any">]>>;
73
+ authors: z.ZodOptional<z.ZodArray<z.ZodString>>;
74
+ login: z.ZodOptional<z.ZodString>;
75
+ allowBots: z.ZodOptional<z.ZodBoolean>;
76
+ stream: z.ZodOptional<z.ZodBoolean>;
77
+ }, z.core.$strip>>;
78
+ email: z.ZodOptional<z.ZodObject<{
79
+ ownerIds: z.ZodOptional<z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
80
+ address: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
81
+ name: z.ZodOptional<z.ZodString>;
82
+ aliases: z.ZodOptional<z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
83
+ allowFrom: z.ZodOptional<z.ZodArray<z.ZodString>>;
84
+ senderAuth: z.ZodOptional<z.ZodEnum<{
85
+ required: "required";
86
+ "when-reported": "when-reported";
87
+ off: "off";
88
+ }>>;
89
+ trustedAuthservIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
90
+ subject: z.ZodOptional<z.ZodString>;
91
+ imap: z.ZodOptional<z.ZodObject<{
92
+ host: z.ZodOptional<z.ZodString>;
93
+ port: z.ZodOptional<z.ZodNumber>;
94
+ secure: z.ZodOptional<z.ZodBoolean>;
95
+ mailbox: z.ZodOptional<z.ZodString>;
96
+ pollInterval: z.ZodOptional<z.ZodNumber>;
97
+ lookbackDays: z.ZodOptional<z.ZodNumber>;
98
+ }, z.core.$strip>>;
99
+ smtp: z.ZodOptional<z.ZodObject<{
100
+ host: z.ZodOptional<z.ZodString>;
101
+ port: z.ZodOptional<z.ZodNumber>;
102
+ secure: z.ZodOptional<z.ZodBoolean>;
103
+ }, z.core.$strip>>;
104
+ webhook: z.ZodOptional<z.ZodObject<{
105
+ provider: z.ZodEnum<{
106
+ mailgun: "mailgun";
107
+ postmark: "postmark";
108
+ sendgrid: "sendgrid";
109
+ }>;
110
+ port: z.ZodDefault<z.ZodNumber>;
111
+ path: z.ZodOptional<z.ZodString>;
112
+ }, z.core.$strip>>;
113
+ }, z.core.$strip>>;
48
114
  }, z.core.$strip>>>;
49
115
  capabilities: z.ZodDefault<z.ZodOptional<z.ZodObject<{
50
116
  webSearch: z.ZodOptional<z.ZodBoolean>;
@@ -110,6 +176,18 @@ export declare const AssistantConfigSchema: z.ZodObject<{
110
176
  denyWords: z.ZodOptional<z.ZodArray<z.ZodString>>;
111
177
  notAllowedMessage: z.ZodOptional<z.ZodString>;
112
178
  }, z.core.$strip>>;
179
+ session: z.ZodOptional<z.ZodObject<{
180
+ queueMode: z.ZodOptional<z.ZodEnum<{
181
+ parallel: "parallel";
182
+ sequential: "sequential";
183
+ interrupt: "interrupt";
184
+ collect: "collect";
185
+ }>>;
186
+ threadKey: z.ZodOptional<z.ZodEnum<{
187
+ conversation: "conversation";
188
+ legacy: "legacy";
189
+ }>>;
190
+ }, z.core.$strip>>;
113
191
  stream: z.ZodOptional<z.ZodObject<{
114
192
  flushInterval: z.ZodDefault<z.ZodNumber>;
115
193
  minChunkSize: z.ZodDefault<z.ZodNumber>;
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-config.d.ts","sourceRoot":"","sources":["../src/assistant-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsHxB,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4BhC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACzE,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
1
+ {"version":3,"file":"assistant-config.d.ts","sourceRoot":"","sources":["../src/assistant-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAexB,uDAAuD;AACvD,eAAO,MAAM,qBAAqB,QAA4C,CAAC;AAE/E,iGAAiG;AACjG,eAAO,MAAM,wBAAwB,QACwC,CAAC;AA4O9E,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6BhC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACzE,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -10,6 +10,15 @@ const McpServerSchema = z.object({
10
10
  requiresApproval: z.boolean().optional(),
11
11
  });
12
12
  const OwnerIdsSchema = z.array(z.string()).optional();
13
+ /** An email address, as `channels.email` takes them */
14
+ export const EMAIL_ADDRESS_PATTERN = /^[^\s@<>]+@[^\s@<>.]+(?:\.[^\s@<>.]+)+$/;
15
+ /** An entry of `channels.email.allowFrom`: an address, a domain, `*.domain`, `@domain` or `*` */
16
+ export const EMAIL_ALLOW_FROM_PATTERN = /^(\*|(\*\.|@)?[^\s@*.]+(?:\.[^\s@*.]+)+|[^\s@]+@[^\s@.]+(?:\.[^\s@.]+)+)$/;
17
+ const EmailAddressSchema = z
18
+ .string()
19
+ .trim()
20
+ .regex(EMAIL_ADDRESS_PATTERN, 'Not an email address')
21
+ .transform((address) => address.toLowerCase());
13
22
  const AssistantChannelsSchema = z.object({
14
23
  telegram: z.object({ ownerIds: OwnerIdsSchema }).optional(),
15
24
  discord: z.object({ ownerIds: OwnerIdsSchema }).optional(),
@@ -48,6 +57,113 @@ const AssistantChannelsSchema = z.object({
48
57
  tokenPath: z.string().optional(),
49
58
  })
50
59
  .optional(),
60
+ github: z
61
+ .object({
62
+ /**
63
+ * GitHub user ids (numbers, as `https://api.github.com/users/<login>` shows them), written
64
+ * as strings or numbers
65
+ */
66
+ ownerIds: z
67
+ .array(z.union([z.string(), z.number().int().nonnegative().transform(String)]))
68
+ .optional(),
69
+ /** The server GitHub's webhook delivers to (default port 8787, path `/github/webhook`) */
70
+ webhook: z
71
+ .object({
72
+ port: z.number().int().positive().default(8787),
73
+ path: z
74
+ .string()
75
+ .regex(/^\//, 'The webhook path starts with /, such as /github/webhook')
76
+ .optional(),
77
+ })
78
+ .default({ port: 8787 }),
79
+ /** `mention` (default) answers only when `@login` is mentioned, `all` every new event */
80
+ trigger: z.enum(['mention', 'all']).optional(),
81
+ /** The repositories to answer in, `owner/repo` or `owner/*` (default every one) */
82
+ repositories: z
83
+ .array(z.string().regex(/^[^/\s]+\/([^/\s]+|\*)$/, 'A repository is owner/repo or owner/*'))
84
+ .optional(),
85
+ /** Whose events to answer by `author_association` (default OWNER, MEMBER, COLLABORATOR), or `any` */
86
+ associations: z
87
+ .union([
88
+ z.array(z.enum([
89
+ 'OWNER',
90
+ 'MEMBER',
91
+ 'COLLABORATOR',
92
+ 'CONTRIBUTOR',
93
+ 'FIRST_TIME_CONTRIBUTOR',
94
+ 'FIRST_TIMER',
95
+ 'MANNEQUIN',
96
+ 'NONE',
97
+ ])),
98
+ z.literal('any'),
99
+ ])
100
+ .optional(),
101
+ /** Logins answered whatever their association */
102
+ authors: z.array(z.string()).optional(),
103
+ /** The bot's login, needed for a GitHub App installation token (`<app-slug>[bot]`) */
104
+ login: z.string().optional(),
105
+ allowBots: z.boolean().optional(),
106
+ /** Stream answers into a comment it edits, at most every 3 seconds (default false) */
107
+ stream: z.boolean().optional(),
108
+ })
109
+ .optional(),
110
+ email: z
111
+ .object({
112
+ /**
113
+ * Owner addresses, also answered whatever `allowFrom` says, but only when their sender
114
+ * authentication passes (unless `senderAuth` is `off`), since a `From` can be forged
115
+ */
116
+ ownerIds: z.array(EmailAddressSchema).optional(),
117
+ /** The bot's address (default `EMAIL_ADDRESS` from the env) */
118
+ address: EmailAddressSchema.optional(),
119
+ /** The display name of the mail it sends */
120
+ name: z.string().optional(),
121
+ /** Other addresses of the bot, never answered */
122
+ aliases: z.array(EmailAddressSchema).optional(),
123
+ /** Who it answers: addresses, domains, `*.domain` or `*` (default nobody but the owners) */
124
+ allowFrom: z
125
+ .array(z
126
+ .string()
127
+ .regex(EMAIL_ALLOW_FROM_PATTERN, 'An allowFrom entry is an address, a domain, *.domain or *'))
128
+ .optional(),
129
+ /** `when-reported` (default), `required` or `off`: how DKIM, SPF and DMARC results are used */
130
+ senderAuth: z.enum(['required', 'when-reported', 'off']).optional(),
131
+ /** The authserv-ids whose Authentication-Results count (default the topmost header) */
132
+ trustedAuthservIds: z.array(z.string()).optional(),
133
+ /** The subject of mail that starts a conversation */
134
+ subject: z.string().optional(),
135
+ /** Read mail over IMAP, host, port, user and password may also come from EMAIL_IMAP_* */
136
+ imap: z
137
+ .object({
138
+ host: z.string().optional(),
139
+ port: z.number().int().positive().optional(),
140
+ secure: z.boolean().optional(),
141
+ mailbox: z.string().optional(),
142
+ pollInterval: z.number().int().positive().optional(),
143
+ lookbackDays: z.number().positive().optional(),
144
+ })
145
+ .optional(),
146
+ /** Send over SMTP, host, port, user and password may also come from EMAIL_SMTP_* */
147
+ smtp: z
148
+ .object({
149
+ host: z.string().optional(),
150
+ port: z.number().int().positive().optional(),
151
+ secure: z.boolean().optional(),
152
+ })
153
+ .optional(),
154
+ /** Take mail from a provider's inbound webhook, on its own server (default port 8788) */
155
+ webhook: z
156
+ .object({
157
+ provider: z.enum(['mailgun', 'postmark', 'sendgrid']),
158
+ port: z.number().int().positive().default(8788),
159
+ path: z
160
+ .string()
161
+ .regex(/^\//, 'The webhook path starts with /, such as /email/webhook')
162
+ .optional(),
163
+ })
164
+ .optional(),
165
+ })
166
+ .optional(),
51
167
  });
52
168
  const ApprovalsSchema = z
53
169
  .object({
@@ -91,6 +207,16 @@ const AssistantMemorySchema = z.object({
91
207
  /** `threshold` counts messages: the thread is compacted once it holds that many */
92
208
  compaction: z.object({ threshold: z.number() }).optional(),
93
209
  });
210
+ /** How the gateway names and orders conversation threads */
211
+ const AssistantSessionSchema = z.object({
212
+ /** `sequential` (default) answers a thread's messages one at a time, `parallel` all at once */
213
+ queueMode: z.enum(['parallel', 'sequential', 'interrupt', 'collect']).optional(),
214
+ /**
215
+ * `conversation` (default): a thread per user per chat, topic or post thread. `legacy`: a thread
216
+ * per user per channel, as before, to keep the threads stored by earlier versions
217
+ */
218
+ threadKey: z.enum(['conversation', 'legacy']).optional(),
219
+ });
94
220
  const CommandAccessSchema = z
95
221
  .object({
96
222
  authorized: z.array(z.string()).optional(),
@@ -124,6 +250,7 @@ export const AssistantConfigSchema = z.object({
124
250
  }),
125
251
  security: SecuritySchema,
126
252
  approvals: ApprovalsSchema,
253
+ session: AssistantSessionSchema.optional(),
127
254
  stream: z
128
255
  .object({
129
256
  flushInterval: z.number().default(600),
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-config.js","sourceRoot":"","sources":["../src/assistant-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"assistant-config.js","sourceRoot":"","sources":["../src/assistant-config.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/channels/bluesky/channel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE5F,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAWxD,MAAM,MAAM,oBAAoB,GAAG,CAAC;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,GAAG,uBAAuB,CAAC,GAAG;IAC3F,oFAAoF;IACpF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gGAAgG;IAChG,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AA2BF;;;;;;;;;GASG;AACH,qBAAa,cAAe,YAAW,OAAO;IAC5C,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,QAAQ,SAAS;IAC1B,QAAQ,CAAC,cAAc,SAAS;IAChC,QAAQ,CAAC,eAAe,SAAY;IACpC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,OAAO,CAAyD;IACxE,OAAO,CAAC,KAAK,CAAC,CAAiC;IAC/C,OAAO,CAAC,OAAO,CAAC,CAAgB;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA2B;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,MAAM,CAAC,CAAgC;IAC/C,OAAO,CAAC,OAAO,CAAC,CAAsC;IACtD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAG1B;IACJ,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,oBAAoB;IASxC,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAUtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,yFAAyF;IACzF,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAcf,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAevF,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAInB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAcrF,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAE3B,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcxE,qFAAqF;YACvE,IAAI;IAQlB,OAAO,CAAC,QAAQ;YAUF,WAAW;IAWzB;;;;;;OAMG;YACW,SAAS;IAiDvB,OAAO,CAAC,WAAW;YAkBL,YAAY;IAsB1B;;;;;;;OAOG;YACW,gBAAgB;YAwEhB,YAAY;YA+BZ,OAAO;CAQtB;AAmDD,wCAAwC;AACxC,wBAAgB,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,cAAc,CAE3E"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/channels/bluesky/channel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE5F,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAWxD,MAAM,MAAM,oBAAoB,GAAG,CAAC;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,GAAG,uBAAuB,CAAC,GAAG;IAC3F,oFAAoF;IACpF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gGAAgG;IAChG,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AA2BF;;;;;;;;;GASG;AACH,qBAAa,cAAe,YAAW,OAAO;IAC5C,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,QAAQ,SAAS;IAC1B,QAAQ,CAAC,cAAc,SAAS;IAChC,QAAQ,CAAC,eAAe,SAAY;IACpC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,OAAO,CAAyD;IACxE,OAAO,CAAC,KAAK,CAAC,CAAiC;IAC/C,OAAO,CAAC,OAAO,CAAC,CAAgB;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA2B;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,MAAM,CAAC,CAAgC;IAC/C,OAAO,CAAC,OAAO,CAAC,CAAsC;IACtD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAG1B;IACJ,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,oBAAoB;IASxC,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAUtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,yFAAyF;IACzF,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAcf,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAevF,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAInB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAcrF,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAE3B,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcxE,qFAAqF;YACvE,IAAI;IAQlB,OAAO,CAAC,QAAQ;YAUF,WAAW;IAWzB;;;;;;OAMG;YACW,SAAS;IAiDvB,OAAO,CAAC,WAAW;YAmBL,YAAY;IAsB1B;;;;;;;OAOG;YACW,gBAAgB;YAwEhB,YAAY;YA+BZ,OAAO;CAQtB;AAmDD,wCAAwC;AACxC,wBAAgB,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,cAAc,CAE3E"}
@@ -231,6 +231,7 @@ export class BlueskyChannel {
231
231
  userId: notification.author.did,
232
232
  userName: notification.author.displayName || notification.author.handle,
233
233
  groupId: `thread:${root}`,
234
+ conversationId: `thread:${root}`,
234
235
  text: stripMention(text, this.account.identifier),
235
236
  ...(parent && { replyTo: parent }),
236
237
  raw: notification,