@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.
- package/README.md +129 -23
- package/dist/assistant-config.d.ts +78 -0
- package/dist/assistant-config.d.ts.map +1 -1
- package/dist/assistant-config.js +127 -0
- package/dist/assistant-config.js.map +1 -1
- package/dist/channels/bluesky/channel.d.ts.map +1 -1
- package/dist/channels/bluesky/channel.js +1 -0
- package/dist/channels/bluesky/channel.js.map +1 -1
- package/dist/channels/email/address.d.ts +44 -0
- package/dist/channels/email/address.d.ts.map +1 -0
- package/dist/channels/email/address.js +211 -0
- package/dist/channels/email/address.js.map +1 -0
- package/dist/channels/email/auth.d.ts +59 -0
- package/dist/channels/email/auth.d.ts.map +1 -0
- package/dist/channels/email/auth.js +212 -0
- package/dist/channels/email/auth.js.map +1 -0
- package/dist/channels/email/channel.d.ts +256 -0
- package/dist/channels/email/channel.d.ts.map +1 -0
- package/dist/channels/email/channel.js +701 -0
- package/dist/channels/email/channel.js.map +1 -0
- package/dist/channels/email/errors.d.ts +11 -0
- package/dist/channels/email/errors.d.ts.map +1 -0
- package/dist/channels/email/errors.js +13 -0
- package/dist/channels/email/errors.js.map +1 -0
- package/dist/channels/email/imap.d.ts +125 -0
- package/dist/channels/email/imap.d.ts.map +1 -0
- package/dist/channels/email/imap.js +309 -0
- package/dist/channels/email/imap.js.map +1 -0
- package/dist/channels/email/index.d.ts +7 -0
- package/dist/channels/email/index.d.ts.map +1 -0
- package/dist/channels/email/index.js +3 -0
- package/dist/channels/email/index.js.map +1 -0
- package/dist/channels/email/mime.d.ts +71 -0
- package/dist/channels/email/mime.d.ts.map +1 -0
- package/dist/channels/email/mime.js +83 -0
- package/dist/channels/email/mime.js.map +1 -0
- package/dist/channels/email/multipart.d.ts +28 -0
- package/dist/channels/email/multipart.d.ts.map +1 -0
- package/dist/channels/email/multipart.js +102 -0
- package/dist/channels/email/multipart.js.map +1 -0
- package/dist/channels/email/providers.d.ts +49 -0
- package/dist/channels/email/providers.d.ts.map +1 -0
- package/dist/channels/email/providers.js +292 -0
- package/dist/channels/email/providers.js.map +1 -0
- package/dist/channels/email/reply.d.ts +9 -0
- package/dist/channels/email/reply.d.ts.map +1 -0
- package/dist/channels/email/reply.js +122 -0
- package/dist/channels/email/reply.js.map +1 -0
- package/dist/channels/github/channel.d.ts +222 -0
- package/dist/channels/github/channel.d.ts.map +1 -0
- package/dist/channels/github/channel.js +736 -0
- package/dist/channels/github/channel.js.map +1 -0
- package/dist/channels/github/client.d.ts +45 -0
- package/dist/channels/github/client.d.ts.map +1 -0
- package/dist/channels/github/client.js +119 -0
- package/dist/channels/github/client.js.map +1 -0
- package/dist/channels/github/events.d.ts +49 -0
- package/dist/channels/github/events.d.ts.map +1 -0
- package/dist/channels/github/events.js +147 -0
- package/dist/channels/github/events.js.map +1 -0
- package/dist/channels/github/index.d.ts +4 -0
- package/dist/channels/github/index.d.ts.map +1 -0
- package/dist/channels/github/index.js +4 -0
- package/dist/channels/github/index.js.map +1 -0
- package/dist/channels/slack.d.ts.map +1 -1
- package/dist/channels/slack.js +2 -1
- package/dist/channels/slack.js.map +1 -1
- package/dist/channels/telegram.d.ts.map +1 -1
- package/dist/channels/telegram.js +14 -6
- package/dist/channels/telegram.js.map +1 -1
- package/dist/channels/threads/channel.d.ts.map +1 -1
- package/dist/channels/threads/channel.js +1 -0
- package/dist/channels/threads/channel.js.map +1 -1
- package/dist/channels/webchat.d.ts +8 -0
- package/dist/channels/webchat.d.ts.map +1 -1
- package/dist/channels/webchat.js +54 -15
- package/dist/channels/webchat.js.map +1 -1
- package/dist/channels/whatsapp.d.ts.map +1 -1
- package/dist/channels/whatsapp.js +13 -0
- package/dist/channels/whatsapp.js.map +1 -1
- package/dist/formatters/html.d.ts +16 -0
- package/dist/formatters/html.d.ts.map +1 -0
- package/dist/formatters/html.js +535 -0
- package/dist/formatters/html.js.map +1 -0
- package/dist/formatters/markdown.d.ts.map +1 -1
- package/dist/formatters/markdown.js +2 -0
- package/dist/formatters/markdown.js.map +1 -1
- package/dist/gateway.d.ts +91 -1
- package/dist/gateway.d.ts.map +1 -1
- package/dist/gateway.js +345 -46
- package/dist/gateway.js.map +1 -1
- package/dist/heartbeat.d.ts +5 -1
- package/dist/heartbeat.d.ts.map +1 -1
- package/dist/heartbeat.js +13 -3
- package/dist/heartbeat.js.map +1 -1
- package/dist/inbound-debounce.d.ts +4 -1
- package/dist/inbound-debounce.d.ts.map +1 -1
- package/dist/inbound-debounce.js +4 -2
- package/dist/inbound-debounce.js.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/merge-messages.d.ts +3 -2
- package/dist/merge-messages.d.ts.map +1 -1
- package/dist/merge-messages.js +4 -2
- package/dist/merge-messages.js.map +1 -1
- package/dist/message-queue.d.ts +14 -4
- package/dist/message-queue.d.ts.map +1 -1
- package/dist/message-queue.js +36 -35
- package/dist/message-queue.js.map +1 -1
- package/dist/runtime-builder.d.ts +9 -0
- package/dist/runtime-builder.d.ts.map +1 -1
- package/dist/runtime-builder.js +149 -5
- package/dist/runtime-builder.js.map +1 -1
- package/dist/thread-key.d.ts +50 -0
- package/dist/thread-key.d.ts.map +1 -0
- package/dist/thread-key.js +82 -0
- package/dist/thread-key.js.map +1 -0
- package/package.json +26 -8
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/** The longest line read as an attribution: longer ones are text, whatever they say. */
|
|
2
|
+
const MAX_ATTRIBUTION = 500;
|
|
3
|
+
/**
|
|
4
|
+
* Lines that introduce a quoted message, as mail clients write them in several languages: how
|
|
5
|
+
* they start and the word that names the writing. Checked as two linear tests, not one pattern.
|
|
6
|
+
*/
|
|
7
|
+
const ATTRIBUTIONS = [
|
|
8
|
+
[/^On\b/i, /\bwrote:$/i],
|
|
9
|
+
[/^Le\b/i, /\ba écrit\s?:$/i],
|
|
10
|
+
[/^Am\b/i, /\bschrieb\b/i],
|
|
11
|
+
[/^El\b/i, /\bescribió:$/i],
|
|
12
|
+
[/^Em\b/i, /\bescreveu:$/i],
|
|
13
|
+
[/^Op\b/i, /\bschreef\b/i],
|
|
14
|
+
[/^Il\b/i, /\bha scritto:$/i],
|
|
15
|
+
];
|
|
16
|
+
function isAttribution(line) {
|
|
17
|
+
if (line.length > MAX_ATTRIBUTION || !line.endsWith(':'))
|
|
18
|
+
return false;
|
|
19
|
+
return ATTRIBUTIONS.some(([start, word]) => start.test(line) && word.test(line));
|
|
20
|
+
}
|
|
21
|
+
const ADDRESS_TOKEN = /^<?[^\s@<>]+@[^\s@<>.]+(?:\.[^\s@<>.]+)+>?,?$/;
|
|
22
|
+
const WROTE = /^(пишет|написал\(а\)|написала?|wrote)$/i;
|
|
23
|
+
/**
|
|
24
|
+
* A line that ends with an address and a colon, as Gmail and Yandex write in Russian
|
|
25
|
+
* (`пн, 19 окт. 2026 г. в 10:00, Иван <ivan@example.ru>:`), read token by token.
|
|
26
|
+
*/
|
|
27
|
+
function isAddressAttribution(line) {
|
|
28
|
+
if (line.length > MAX_ATTRIBUTION || !line.endsWith(':'))
|
|
29
|
+
return false;
|
|
30
|
+
const words = line.slice(0, -1).trim().split(/\s+/);
|
|
31
|
+
let last = words.pop() ?? '';
|
|
32
|
+
if (WROTE.test(last))
|
|
33
|
+
last = words.pop() ?? '';
|
|
34
|
+
return ADDRESS_TOKEN.test(last);
|
|
35
|
+
}
|
|
36
|
+
const FORWARD_HEADER = /^(-{2,}\s*(Original Message|Ursprüngliche Nachricht|Исходное сообщение|Message d'origine)\s*-{2,}|_{10,})$/i;
|
|
37
|
+
const OUTLOOK_FROM = /^\*?(From|De|Von|От|Van|Da):\*?\s/i;
|
|
38
|
+
const OUTLOOK_FIELD = /^\*?(Sent|Date|To|Subject|Cc|Envoyé|Gesendet|Отправлено|Дата|Кому|Тема|Verzonden|Inviato|Enviado|Objet|Betreff|À|An|Aan|A|Para):\*?\s/i;
|
|
39
|
+
const MOBILE_SIGNATURE = /^(Sent from my \S+|Sent from (Mail|Outlook|Yahoo Mail) for \S+|Get Outlook for \S+|Отправлено с \S+)/i;
|
|
40
|
+
function isQuoted(line) {
|
|
41
|
+
return /^\s*>/.test(line);
|
|
42
|
+
}
|
|
43
|
+
function linesBelow(lines) {
|
|
44
|
+
const nextContent = new Array(lines.length + 1);
|
|
45
|
+
const onlyQuotes = new Array(lines.length + 1);
|
|
46
|
+
nextContent[lines.length] = lines.length;
|
|
47
|
+
onlyQuotes[lines.length] = false;
|
|
48
|
+
let clean = true;
|
|
49
|
+
let quoted = false;
|
|
50
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
51
|
+
const blank = !lines[i].trim();
|
|
52
|
+
nextContent[i] = blank ? nextContent[i + 1] : i;
|
|
53
|
+
if (!blank) {
|
|
54
|
+
if (isQuoted(lines[i]))
|
|
55
|
+
quoted = true;
|
|
56
|
+
else
|
|
57
|
+
clean = false;
|
|
58
|
+
}
|
|
59
|
+
onlyQuotes[i] = clean && quoted;
|
|
60
|
+
}
|
|
61
|
+
return { nextContent, onlyQuotes };
|
|
62
|
+
}
|
|
63
|
+
/** Where a quoted message starts, if it starts at line `i`: its attribution or separator. */
|
|
64
|
+
function quoteStartsAt(lines, i, below) {
|
|
65
|
+
const line = lines[i].trim();
|
|
66
|
+
if (!line)
|
|
67
|
+
return false;
|
|
68
|
+
if (FORWARD_HEADER.test(line))
|
|
69
|
+
return true;
|
|
70
|
+
const wrapped = i + 1 < lines.length && line.length <= MAX_ATTRIBUTION;
|
|
71
|
+
const joined = wrapped ? `${line} ${lines[i + 1].trim()}` : line;
|
|
72
|
+
const single = isAttribution(line);
|
|
73
|
+
if (single || (wrapped && isAttribution(joined))) {
|
|
74
|
+
const next = below.nextContent[single ? i + 1 : i + 2] ?? lines.length;
|
|
75
|
+
return next >= lines.length || isQuoted(lines[next]) || OUTLOOK_FROM.test(lines[next]);
|
|
76
|
+
}
|
|
77
|
+
if (isAddressAttribution(line)) {
|
|
78
|
+
const next = below.nextContent[i + 1];
|
|
79
|
+
return next < lines.length && below.onlyQuotes[next];
|
|
80
|
+
}
|
|
81
|
+
if (OUTLOOK_FROM.test(line)) {
|
|
82
|
+
let fields = 0;
|
|
83
|
+
for (let j = i + 1; j < Math.min(lines.length, i + 6); j++) {
|
|
84
|
+
if (OUTLOOK_FIELD.test(lines[j].trim()))
|
|
85
|
+
fields++;
|
|
86
|
+
}
|
|
87
|
+
return fields >= 2;
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The new text of a reply, without what it quotes: the history after an attribution line
|
|
93
|
+
* (`On ... wrote:` and its translations, `-----Original Message-----`, an Outlook `From:` and
|
|
94
|
+
* `Sent:` block), a trailing block of `>` quotes, the signature after a `-- ` line and a
|
|
95
|
+
* `Sent from my ...` line. Quotes the writer answers between are kept, as they say what each
|
|
96
|
+
* answer is about. Returns the text unchanged when stripping would leave nothing.
|
|
97
|
+
*/
|
|
98
|
+
export function stripQuotedReply(text) {
|
|
99
|
+
const lines = text.replace(/\r\n?/g, '\n').split('\n');
|
|
100
|
+
const below = linesBelow(lines);
|
|
101
|
+
let end = lines.length;
|
|
102
|
+
for (let i = 0; i < lines.length; i++) {
|
|
103
|
+
if (lines[i] === '-- ' || lines[i] === '--') {
|
|
104
|
+
end = i;
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
if (quoteStartsAt(lines, i, below)) {
|
|
108
|
+
end = i;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
let kept = lines.slice(0, end);
|
|
113
|
+
while (kept.length > 0 && (!kept[kept.length - 1].trim() || isQuoted(kept[kept.length - 1]))) {
|
|
114
|
+
kept.pop();
|
|
115
|
+
}
|
|
116
|
+
const last = kept.length - 1;
|
|
117
|
+
if (last >= 0 && MOBILE_SIGNATURE.test(kept[last].trim()))
|
|
118
|
+
kept = kept.slice(0, last);
|
|
119
|
+
const stripped = kept.join('\n').trim();
|
|
120
|
+
return stripped || text.trim();
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=reply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reply.js","sourceRoot":"","sources":["../../../src/channels/email/reply.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { type RequestListener } from 'node:http';
|
|
2
|
+
import type { Attachment, Channel, ChannelMessage, SendOptions } from '@cogitator-ai/types';
|
|
3
|
+
import { type GitHubToken } from './client.js';
|
|
4
|
+
/** The longest comment GitHub takes, in characters. */
|
|
5
|
+
export declare const GITHUB_COMMENT_LIMIT = 65536;
|
|
6
|
+
/** The shortest time between two edits of one comment, under GitHub's limit on content changes. */
|
|
7
|
+
export declare const GITHUB_MIN_EDIT_INTERVAL = 3000;
|
|
8
|
+
/** How an author is related to a repository, as GitHub's `author_association` says it. */
|
|
9
|
+
export type GitHubAssociation = 'OWNER' | 'MEMBER' | 'COLLABORATOR' | 'CONTRIBUTOR' | 'FIRST_TIME_CONTRIBUTOR' | 'FIRST_TIMER' | 'MANNEQUIN' | 'NONE';
|
|
10
|
+
/** The authors the bot answers by default: the repository's owner, the organization's members and collaborators. */
|
|
11
|
+
export declare const GITHUB_TRUSTED_ASSOCIATIONS: readonly GitHubAssociation[];
|
|
12
|
+
export interface GitHubWebhookConfig {
|
|
13
|
+
/** The secret set on the webhook, which signs every delivery. Required. */
|
|
14
|
+
secret: string;
|
|
15
|
+
/**
|
|
16
|
+
* Run an HTTP server of the channel's own on this port. Without it, mount
|
|
17
|
+
* `handleWebhook` or `webhookListener()` in a server of yours.
|
|
18
|
+
*/
|
|
19
|
+
port?: number;
|
|
20
|
+
/** The path of the channel's own server (default `/github/webhook`). */
|
|
21
|
+
path?: string;
|
|
22
|
+
host?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface GitHubChannelConfig {
|
|
25
|
+
/**
|
|
26
|
+
* A personal access token, a GitHub App installation token, or a function
|
|
27
|
+
* that returns a fresh one before every request. It needs to read and write
|
|
28
|
+
* issues and pull requests of the repositories the bot answers in.
|
|
29
|
+
*/
|
|
30
|
+
token: GitHubToken;
|
|
31
|
+
/** Where deliveries come from: GitHub only pushes events, so the webhook is required. */
|
|
32
|
+
webhook: GitHubWebhookConfig;
|
|
33
|
+
/**
|
|
34
|
+
* The bot's login, for skipping its own comments and finding mentions of it.
|
|
35
|
+
* Loaded with `GET /user` when not set, which a GitHub App installation
|
|
36
|
+
* token cannot do: an app sets it to `<app-slug>[bot]`.
|
|
37
|
+
*/
|
|
38
|
+
login?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Which events the bot answers: `mention` (default) answers only those
|
|
41
|
+
* that mention `@login`, `all` every new issue, pull request, comment and
|
|
42
|
+
* review in the allowed repositories. Once the bot answered someone in a
|
|
43
|
+
* conversation, their next comment there reaches it without a mention (an
|
|
44
|
+
* answer to an approval prompt, a follow-up), and so does every comment in
|
|
45
|
+
* a review thread it replied in.
|
|
46
|
+
*/
|
|
47
|
+
trigger?: 'mention' | 'all';
|
|
48
|
+
/**
|
|
49
|
+
* The repositories to answer in, as `owner/repo` or `owner/*` for every
|
|
50
|
+
* repository of an owner. Default: every repository that sends events,
|
|
51
|
+
* which `start()` warns about.
|
|
52
|
+
*/
|
|
53
|
+
repositories?: string[];
|
|
54
|
+
/**
|
|
55
|
+
* Whose events the bot answers, by their relation to the repository
|
|
56
|
+
* (`author_association`). Default `OWNER`, `MEMBER` and `COLLABORATOR`,
|
|
57
|
+
* since what people write steers an agent that holds the token. `'any'`
|
|
58
|
+
* answers everyone, for a public bot whose agent has nothing to leak.
|
|
59
|
+
*/
|
|
60
|
+
associations?: readonly GitHubAssociation[] | 'any';
|
|
61
|
+
/** Logins the bot answers whatever their association, such as private members of an organization. */
|
|
62
|
+
authors?: string[];
|
|
63
|
+
/** Answer other bots and apps too (default false, so two bots cannot answer each other forever). */
|
|
64
|
+
allowBots?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Stream answers into a comment that is edited as the text grows (default
|
|
67
|
+
* false). GitHub notifies subscribers of a comment once, with its first
|
|
68
|
+
* text, and limits how often content may be changed, so answers are sent
|
|
69
|
+
* once finished unless this is on. Edits of one comment are at least
|
|
70
|
+
* `GITHUB_MIN_EDIT_INTERVAL` (3 s) apart, the latest text winning.
|
|
71
|
+
*/
|
|
72
|
+
stream?: boolean;
|
|
73
|
+
/** The REST API root, `https://<host>/api/v3` on GitHub Enterprise Server. */
|
|
74
|
+
apiUrl?: string;
|
|
75
|
+
fetch?: typeof fetch;
|
|
76
|
+
}
|
|
77
|
+
/** A webhook delivery, as any HTTP server hands it over. */
|
|
78
|
+
export interface GitHubWebhookRequest {
|
|
79
|
+
method: string;
|
|
80
|
+
headers: Record<string, string | string[] | undefined>;
|
|
81
|
+
/** The body exactly as received, which the signature covers. */
|
|
82
|
+
rawBody?: string | Uint8Array;
|
|
83
|
+
}
|
|
84
|
+
export interface GitHubWebhookResponse {
|
|
85
|
+
status: number;
|
|
86
|
+
body: string;
|
|
87
|
+
}
|
|
88
|
+
/** Whether `signature` (`sha256=<hex>`) is the HMAC SHA-256 of `body` with `secret`. */
|
|
89
|
+
export declare function verifyGitHubSignature(body: string | Uint8Array, signature: string | undefined, secret: string): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* A GitHub channel: an agent answers issues, pull requests, their comments
|
|
92
|
+
* and reviews, in the repositories a webhook sends events from. Each issue or
|
|
93
|
+
* pull request is one conversation, `channelId` `owner/repo#number`, and
|
|
94
|
+
* answers are comments on it. A comment on a line of a pull request is
|
|
95
|
+
* answered in its review thread, which is the message's `topicId` (the id of
|
|
96
|
+
* the thread's first comment), so every review thread is a conversation of
|
|
97
|
+
* its own. Deliveries are checked against the webhook secret, answered at
|
|
98
|
+
* once and handled after.
|
|
99
|
+
*/
|
|
100
|
+
export declare class GitHubChannel implements Channel {
|
|
101
|
+
readonly type = "github";
|
|
102
|
+
readonly editable: boolean;
|
|
103
|
+
readonly nativeMarkdown = true;
|
|
104
|
+
readonly maxMessageChars = 65536;
|
|
105
|
+
private readonly config;
|
|
106
|
+
private readonly client;
|
|
107
|
+
private handler;
|
|
108
|
+
private readonly deliveries;
|
|
109
|
+
private readonly handled;
|
|
110
|
+
private readonly reactions;
|
|
111
|
+
private readonly reacting;
|
|
112
|
+
private readonly edits;
|
|
113
|
+
/** People who wrote to the bot in a conversation and were not answered yet, by conversation. */
|
|
114
|
+
private readonly waiting;
|
|
115
|
+
/** The conversation and author of each message handed to the agent, by `channelId|messageId`. */
|
|
116
|
+
private readonly askers;
|
|
117
|
+
private readonly engaged;
|
|
118
|
+
private server?;
|
|
119
|
+
private identity?;
|
|
120
|
+
private botLogin?;
|
|
121
|
+
private running;
|
|
122
|
+
private stopped;
|
|
123
|
+
constructor(config: GitHubChannelConfig);
|
|
124
|
+
/** The bot's login, once known: as configured, or loaded by `start()` or the first delivery. */
|
|
125
|
+
get login(): string | undefined;
|
|
126
|
+
onMessage(handler: (msg: ChannelMessage) => Promise<void>): void;
|
|
127
|
+
start(): Promise<void>;
|
|
128
|
+
stop(): Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* Answers a webhook delivery: checks its signature, answers at once and
|
|
131
|
+
* hands the event to the agent after. Mount it in any HTTP server, with the
|
|
132
|
+
* raw body unparsed. It works before `start()` too, and answers `503` once
|
|
133
|
+
* the channel is stopped. A delivery GitHub sends again is handled once:
|
|
134
|
+
* by its `X-GitHub-Delivery` and by the comment, issue or review it
|
|
135
|
+
* carries, which the signature covers. Both are remembered in memory only,
|
|
136
|
+
* for the latest 1000, so a delivery sent again after a restart is
|
|
137
|
+
* handled again.
|
|
138
|
+
*/
|
|
139
|
+
handleWebhook(request: GitHubWebhookRequest): Promise<GitHubWebhookResponse>;
|
|
140
|
+
/**
|
|
141
|
+
* A Node request listener that answers webhook deliveries on any path it
|
|
142
|
+
* is mounted at, such as a route of a server that serves other things too.
|
|
143
|
+
* Bodies over 1 MB are refused with `413`.
|
|
144
|
+
*/
|
|
145
|
+
webhookListener(): RequestListener;
|
|
146
|
+
/**
|
|
147
|
+
* Comments on the issue or pull request of `channelId`, as several
|
|
148
|
+
* comments when the text is longer than GitHub takes. With a `topicId`, or
|
|
149
|
+
* a `replyTo` of a review comment, the comments are replies in that review
|
|
150
|
+
* thread. Resolves with the first comment's id.
|
|
151
|
+
*/
|
|
152
|
+
sendText(channelId: string, text: string, options?: SendOptions): Promise<string>;
|
|
153
|
+
/**
|
|
154
|
+
* Replaces the text of a comment the bot made (`comment:<id>` or
|
|
155
|
+
* `review_comment:<id>`). Edits of one comment go out at least
|
|
156
|
+
* `GITHUB_MIN_EDIT_INTERVAL` apart: an edit made sooner waits, and edits
|
|
157
|
+
* made while it waits are folded into it, the latest text winning.
|
|
158
|
+
*/
|
|
159
|
+
editText(channelId: string, messageId: string, text: string): Promise<void>;
|
|
160
|
+
/** Sends the latest text of an edit once the comment's last edit is far enough back. */
|
|
161
|
+
private flushEdit;
|
|
162
|
+
/**
|
|
163
|
+
* GitHub has no API to upload files to comments, so a file with a public
|
|
164
|
+
* `url` is sent as a comment that links it (an image shows inline), and a
|
|
165
|
+
* file that only has a `buffer` is refused.
|
|
166
|
+
*/
|
|
167
|
+
sendFile(channelId: string, file: Attachment, options?: SendOptions): Promise<string>;
|
|
168
|
+
sendTyping(): Promise<void>;
|
|
169
|
+
/** Deletes a comment the bot made. */
|
|
170
|
+
deleteMessage(channelId: string, messageId: string): Promise<void>;
|
|
171
|
+
/**
|
|
172
|
+
* Reacts to an issue, pull request or comment, replacing the bot's earlier
|
|
173
|
+
* reaction on it. GitHub has eight reactions (+1, -1, laugh, confused,
|
|
174
|
+
* heart, hooray, rocket, eyes), named or as their emoji, and the status
|
|
175
|
+
* emojis of thinking, a tool and an error become eyes, rocket and
|
|
176
|
+
* confused. Other emojis are skipped, and so are reviews, which take no
|
|
177
|
+
* reactions. Reactions to one message are set one after another, so the
|
|
178
|
+
* last one called is the one that stays.
|
|
179
|
+
*/
|
|
180
|
+
setReaction(channelId: string, messageId: string, emoji: string): Promise<void>;
|
|
181
|
+
private react;
|
|
182
|
+
private comment;
|
|
183
|
+
private commentPath;
|
|
184
|
+
private reactionsPath;
|
|
185
|
+
/**
|
|
186
|
+
* Notes that the bot answered in a conversation. The person the answer is
|
|
187
|
+
* for (its `replyTo`, or everyone waiting there when it names no message
|
|
188
|
+
* the bot was asked in) may write on without a mention, and in a review
|
|
189
|
+
* thread everyone may.
|
|
190
|
+
*/
|
|
191
|
+
private answered;
|
|
192
|
+
private remember;
|
|
193
|
+
/** Whether a message reaches the bot without a mention: in a conversation it answered. */
|
|
194
|
+
private takesWithoutMention;
|
|
195
|
+
/**
|
|
196
|
+
* Hands a delivery's event to the agent when it is one to answer. Resolves
|
|
197
|
+
* false when the event was dropped because the bot's login could not be
|
|
198
|
+
* loaded or the channel stopped, so the delivery may be sent again.
|
|
199
|
+
*/
|
|
200
|
+
private receive;
|
|
201
|
+
/**
|
|
202
|
+
* The bot's login for a delivery: loaded when it is not known yet, and
|
|
203
|
+
* tried again a few times, since GitHub does not send a delivery again by
|
|
204
|
+
* itself. The delivery is dropped, with an error logged, when it cannot be
|
|
205
|
+
* loaded.
|
|
206
|
+
*/
|
|
207
|
+
private loginForDelivery;
|
|
208
|
+
/** Loads the bot's login once, unless it is configured. */
|
|
209
|
+
private identify;
|
|
210
|
+
private allowsRepository;
|
|
211
|
+
/** Whether the author may talk to the bot: by their association, or named in `authors`. */
|
|
212
|
+
private trusts;
|
|
213
|
+
private isOwnOrBot;
|
|
214
|
+
/** The name people mention the bot by: its login, without `[bot]` for an app. */
|
|
215
|
+
private mentionName;
|
|
216
|
+
private mentionsBot;
|
|
217
|
+
private stripMention;
|
|
218
|
+
private listen;
|
|
219
|
+
}
|
|
220
|
+
/** A GitHub channel that answers issues, pull requests, comments and reviews. */
|
|
221
|
+
export declare function githubChannel(config: GitHubChannelConfig): GitHubChannel;
|
|
222
|
+
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/channels/github/channel.ts"],"names":[],"mappings":"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"}
|