@spinabot/brigade 1.6.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/agent-loop.d.ts.map +1 -1
- package/dist/agents/agent-loop.js +51 -1
- package/dist/agents/agent-loop.js.map +1 -1
- package/dist/agents/channels/bundled-channel-metas.d.ts +2 -0
- package/dist/agents/channels/bundled-channel-metas.d.ts.map +1 -1
- package/dist/agents/channels/bundled-channel-metas.js +11 -0
- package/dist/agents/channels/bundled-channel-metas.js.map +1 -1
- package/dist/agents/channels/discord/account-config.d.ts +117 -0
- package/dist/agents/channels/discord/account-config.d.ts.map +1 -0
- package/dist/agents/channels/discord/account-config.js +260 -0
- package/dist/agents/channels/discord/account-config.js.map +1 -0
- package/dist/agents/channels/discord/adapter.d.ts +56 -0
- package/dist/agents/channels/discord/adapter.d.ts.map +1 -0
- package/dist/agents/channels/discord/adapter.js +526 -0
- package/dist/agents/channels/discord/adapter.js.map +1 -0
- package/dist/agents/channels/discord/approval-authorize.d.ts +43 -0
- package/dist/agents/channels/discord/approval-authorize.d.ts.map +1 -0
- package/dist/agents/channels/discord/approval-authorize.js +71 -0
- package/dist/agents/channels/discord/approval-authorize.js.map +1 -0
- package/dist/agents/channels/discord/approval-native.d.ts +68 -0
- package/dist/agents/channels/discord/approval-native.d.ts.map +1 -0
- package/dist/agents/channels/discord/approval-native.js +81 -0
- package/dist/agents/channels/discord/approval-native.js.map +1 -0
- package/dist/agents/channels/discord/command-menu.d.ts +49 -0
- package/dist/agents/channels/discord/command-menu.d.ts.map +1 -0
- package/dist/agents/channels/discord/command-menu.js +73 -0
- package/dist/agents/channels/discord/command-menu.js.map +1 -0
- package/dist/agents/channels/discord/components.d.ts +97 -0
- package/dist/agents/channels/discord/components.d.ts.map +1 -0
- package/dist/agents/channels/discord/components.js +131 -0
- package/dist/agents/channels/discord/components.js.map +1 -0
- package/dist/agents/channels/discord/connection.d.ts +387 -0
- package/dist/agents/channels/discord/connection.d.ts.map +1 -0
- package/dist/agents/channels/discord/connection.js +786 -0
- package/dist/agents/channels/discord/connection.js.map +1 -0
- package/dist/agents/channels/discord/draft-stream.d.ts +92 -0
- package/dist/agents/channels/discord/draft-stream.d.ts.map +1 -0
- package/dist/agents/channels/discord/draft-stream.js +213 -0
- package/dist/agents/channels/discord/draft-stream.js.map +1 -0
- package/dist/agents/channels/discord/format.d.ts +55 -0
- package/dist/agents/channels/discord/format.d.ts.map +1 -0
- package/dist/agents/channels/discord/format.js +247 -0
- package/dist/agents/channels/discord/format.js.map +1 -0
- package/dist/agents/channels/discord/inbound-extras.d.ts +220 -0
- package/dist/agents/channels/discord/inbound-extras.d.ts.map +1 -0
- package/dist/agents/channels/discord/inbound-extras.js +351 -0
- package/dist/agents/channels/discord/inbound-extras.js.map +1 -0
- package/dist/agents/channels/discord/index.d.ts +14 -0
- package/dist/agents/channels/discord/index.d.ts.map +1 -0
- package/dist/agents/channels/discord/index.js +14 -0
- package/dist/agents/channels/discord/index.js.map +1 -0
- package/dist/agents/channels/discord/media.d.ts +85 -0
- package/dist/agents/channels/discord/media.d.ts.map +1 -0
- package/dist/agents/channels/discord/media.js +242 -0
- package/dist/agents/channels/discord/media.js.map +1 -0
- package/dist/agents/channels/discord/module.d.ts +15 -0
- package/dist/agents/channels/discord/module.d.ts.map +1 -0
- package/dist/agents/channels/discord/module.js +22 -0
- package/dist/agents/channels/discord/module.js.map +1 -0
- package/dist/agents/channels/discord/plugin.d.ts +73 -0
- package/dist/agents/channels/discord/plugin.d.ts.map +1 -0
- package/dist/agents/channels/discord/plugin.js +303 -0
- package/dist/agents/channels/discord/plugin.js.map +1 -0
- package/dist/agents/channels/discord/probe.d.ts +93 -0
- package/dist/agents/channels/discord/probe.d.ts.map +1 -0
- package/dist/agents/channels/discord/probe.js +158 -0
- package/dist/agents/channels/discord/probe.js.map +1 -0
- package/dist/agents/channels/discord/reasoning-lane.d.ts +42 -0
- package/dist/agents/channels/discord/reasoning-lane.d.ts.map +1 -0
- package/dist/agents/channels/discord/reasoning-lane.js +68 -0
- package/dist/agents/channels/discord/reasoning-lane.js.map +1 -0
- package/dist/agents/channels/inbound-pipeline.d.ts.map +1 -1
- package/dist/agents/channels/inbound-pipeline.js +65 -7
- package/dist/agents/channels/inbound-pipeline.js.map +1 -1
- package/dist/agents/channels/sdk.d.ts +2 -0
- package/dist/agents/channels/sdk.d.ts.map +1 -1
- package/dist/agents/channels/sdk.js +2 -0
- package/dist/agents/channels/sdk.js.map +1 -1
- package/dist/agents/extensions/modules/index.d.ts.map +1 -1
- package/dist/agents/extensions/modules/index.js +5 -0
- package/dist/agents/extensions/modules/index.js.map +1 -1
- package/dist/agents/tools/cron-tool.d.ts.map +1 -1
- package/dist/agents/tools/cron-tool.js +4 -1
- package/dist/agents/tools/cron-tool.js.map +1 -1
- package/dist/buildstamp.json +1 -1
- package/dist/core/auth-bridge.d.ts +1 -0
- package/dist/core/auth-bridge.d.ts.map +1 -1
- package/dist/core/auth-bridge.js +46 -1
- package/dist/core/auth-bridge.js.map +1 -1
- package/dist/core/server.d.ts.map +1 -1
- package/dist/core/server.js +18 -2
- package/dist/core/server.js.map +1 -1
- package/dist/cron/isolated-agent/run-executor.d.ts +11 -0
- package/dist/cron/isolated-agent/run-executor.d.ts.map +1 -1
- package/dist/cron/isolated-agent/run-executor.js +20 -4
- package/dist/cron/isolated-agent/run-executor.js.map +1 -1
- package/dist/cron/types.d.ts +8 -0
- package/dist/cron/types.d.ts.map +1 -1
- package/dist/system-prompt/assembler.d.ts.map +1 -1
- package/dist/system-prompt/assembler.js +4 -2
- package/dist/system-prompt/assembler.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert agent-style markdown (Brigade agents output this by default) into
|
|
3
|
+
* Discord's message markup.
|
|
4
|
+
*
|
|
5
|
+
* Discord renders a near-CommonMark dialect natively, so — unlike Slack's
|
|
6
|
+
* `mrkdwn` (single-asterisk bold) or Telegram's strict HTML — most agent
|
|
7
|
+
* markdown passes through UNCHANGED:
|
|
8
|
+
* - **bold** / __underline__ → kept (Discord: `**bold**`, `__underline__`)
|
|
9
|
+
* - *italic* / _italic_ → kept
|
|
10
|
+
* - ~~strike~~ → kept
|
|
11
|
+
* - `code` → kept (interior verbatim)
|
|
12
|
+
* - ```fenced``` → kept (interior verbatim, language tag kept)
|
|
13
|
+
* - > quote → kept
|
|
14
|
+
* - `-`/`*`/`+` bullets → kept
|
|
15
|
+
* - 1. numbered lists → kept
|
|
16
|
+
* - # headings → kept (Discord renders `#`/`##`/`###` headers)
|
|
17
|
+
*
|
|
18
|
+
* The ONE load-bearing transform: a markdown link `[label](url)` renders
|
|
19
|
+
* LITERALLY in a normal Discord message (Discord only auto-links bare URLs and
|
|
20
|
+
* honours `[label](url)` in embeds, not plain content). So a plain-message link
|
|
21
|
+
* is rewritten to `label (url)` — the same readable fallback Slack/Telegram use
|
|
22
|
+
* when a link can't be a native token. A bare URL is left as-is (Discord
|
|
23
|
+
* auto-links it).
|
|
24
|
+
*
|
|
25
|
+
* MENTION PASSTHROUGH (critical): an agent that authored a Discord mention token
|
|
26
|
+
* means it to PING. Discord's tokens are `<@123>` (user), `<@!123>` (member
|
|
27
|
+
* nickname), `<@&123>` (role), `<#123>` (channel), `<:name:123>` / `<a:name:123>`
|
|
28
|
+
* (custom / animated emoji), and the literal `@everyone` / `@here`. Those are
|
|
29
|
+
* passed through VERBATIM so the mention actually resolves; everything else is
|
|
30
|
+
* left as Discord-native markdown. We do NOT entity-escape (Discord has no HTML
|
|
31
|
+
* entities) — we only neutralize a STRAY markdown link.
|
|
32
|
+
*
|
|
33
|
+
* Pure / deterministic — no I/O, no globals. Models the SHAPE of
|
|
34
|
+
* `slack/format.ts` (markdown in → channel-native formatting out) but emits
|
|
35
|
+
* Discord markup.
|
|
36
|
+
*/
|
|
37
|
+
/** Discord's hard per-message content limit (chars). Sends chunk under this. */
|
|
38
|
+
export const DISCORD_MESSAGE_LIMIT = 2000;
|
|
39
|
+
/**
|
|
40
|
+
* A pre-formed Discord token that must pass through verbatim so it resolves:
|
|
41
|
+
* - `<@123>` / `<@!123>` user / member mention
|
|
42
|
+
* - `<@&123>` role mention
|
|
43
|
+
* - `<#123>` channel mention
|
|
44
|
+
* - `<:name:123>` / `<a:name:123>` custom / animated emoji
|
|
45
|
+
* - `<t:123>` / `<t:123:R>` timestamp
|
|
46
|
+
* Anchored at the `<` the scanner is sitting on. Returns the matched token
|
|
47
|
+
* length, or 0 when the `<…>` isn't a recognised Discord token.
|
|
48
|
+
*/
|
|
49
|
+
function matchDiscordToken(text, start) {
|
|
50
|
+
// Find the closing `>` for this `<`.
|
|
51
|
+
const close = text.indexOf(">", start + 1);
|
|
52
|
+
if (close === -1)
|
|
53
|
+
return 0;
|
|
54
|
+
const inner = text.slice(start + 1, close);
|
|
55
|
+
// user / member: @123 or @!123 ; role: @&123 ; channel: #123
|
|
56
|
+
if (/^@!?\d+$/.test(inner))
|
|
57
|
+
return close - start + 1;
|
|
58
|
+
if (/^@&\d+$/.test(inner))
|
|
59
|
+
return close - start + 1;
|
|
60
|
+
if (/^#\d+$/.test(inner))
|
|
61
|
+
return close - start + 1;
|
|
62
|
+
// custom / animated emoji: :name:123 or a:name:123
|
|
63
|
+
if (/^a?:[A-Za-z0-9_]{2,32}:\d+$/.test(inner))
|
|
64
|
+
return close - start + 1;
|
|
65
|
+
// timestamp: t:123 or t:123:R
|
|
66
|
+
if (/^t:\d+(?::[tTdDfFR])?$/.test(inner))
|
|
67
|
+
return close - start + 1;
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
/** Try to match a `[label](url)` link starting at `start` (the `[`). */
|
|
71
|
+
function matchMarkdownLink(text, start) {
|
|
72
|
+
const labelEnd = text.indexOf("]", start + 1);
|
|
73
|
+
if (labelEnd === -1)
|
|
74
|
+
return null;
|
|
75
|
+
if (text[labelEnd + 1] !== "(")
|
|
76
|
+
return null;
|
|
77
|
+
// Balanced-paren scan from just after the opening `(` so a URL that itself
|
|
78
|
+
// contains parentheses (e.g. `…/Mercury_(planet)`) keeps its closing `)`. A
|
|
79
|
+
// plain `indexOf(")")` would truncate at the FIRST `)`, dropping the rest.
|
|
80
|
+
let depth = 1;
|
|
81
|
+
let urlEnd = -1;
|
|
82
|
+
for (let j = labelEnd + 2; j < text.length; j++) {
|
|
83
|
+
const c = text[j];
|
|
84
|
+
if (c === "(")
|
|
85
|
+
depth += 1;
|
|
86
|
+
else if (c === ")") {
|
|
87
|
+
depth -= 1;
|
|
88
|
+
if (depth === 0) {
|
|
89
|
+
urlEnd = j;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (urlEnd === -1)
|
|
95
|
+
return null;
|
|
96
|
+
const label = text.slice(start + 1, labelEnd);
|
|
97
|
+
const url = text.slice(labelEnd + 2, urlEnd).trim();
|
|
98
|
+
// Only honour http/https/mailto/tel links — anything else stays literal so we
|
|
99
|
+
// never linkify a path / fragment that wasn't a real URL.
|
|
100
|
+
if (!/^(https?:\/\/|mailto:|tel:)/i.test(url))
|
|
101
|
+
return null;
|
|
102
|
+
if (!label)
|
|
103
|
+
return null;
|
|
104
|
+
return { label, url, end: urlEnd + 1 };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Render the INLINE span markup of one already-newline-free run into Discord
|
|
108
|
+
* markup. Inline code is preserved verbatim (its interior is never rewritten),
|
|
109
|
+
* Discord mention/emoji tokens pass through verbatim, and a markdown link is
|
|
110
|
+
* rewritten to the readable `label (url)` fallback. Everything else is passed
|
|
111
|
+
* through unchanged (Discord renders **bold** / *italic* / ~~strike~~ natively).
|
|
112
|
+
*/
|
|
113
|
+
function renderInlineSpans(text) {
|
|
114
|
+
const out = [];
|
|
115
|
+
let i = 0;
|
|
116
|
+
const n = text.length;
|
|
117
|
+
while (i < n) {
|
|
118
|
+
const ch = text[i];
|
|
119
|
+
// Inline code: `…` — interior is verbatim (no link rewrite inside code).
|
|
120
|
+
if (ch === "`") {
|
|
121
|
+
// Support a run of backticks (`` `x` `` / ``` ``y`` ``` ) — match the
|
|
122
|
+
// same-length closing fence so an interior backtick doesn't close early.
|
|
123
|
+
const fenceMatch = /^`+/.exec(text.slice(i));
|
|
124
|
+
const fence = fenceMatch ? fenceMatch[0] : "`";
|
|
125
|
+
const close = text.indexOf(fence, i + fence.length);
|
|
126
|
+
if (close !== -1) {
|
|
127
|
+
out.push(text.slice(i, close + fence.length));
|
|
128
|
+
i = close + fence.length;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Pre-formed Discord token (mention / channel / role / emoji / timestamp) —
|
|
133
|
+
// pass through verbatim so it actually resolves on Discord.
|
|
134
|
+
if (ch === "<") {
|
|
135
|
+
const len = matchDiscordToken(text, i);
|
|
136
|
+
if (len > 0) {
|
|
137
|
+
out.push(text.slice(i, i + len));
|
|
138
|
+
i += len;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Markdown link: [label](url) → "label (url)" (a plain Discord message
|
|
143
|
+
// renders the markdown-link form literally, so we degrade to readable text).
|
|
144
|
+
if (ch === "[") {
|
|
145
|
+
const link = matchMarkdownLink(text, i);
|
|
146
|
+
if (link) {
|
|
147
|
+
// When the label already equals the url, just emit the bare url
|
|
148
|
+
// (Discord auto-links it) to avoid the noisy "url (url)".
|
|
149
|
+
out.push(link.label === link.url ? link.url : `${link.label} (${link.url})`);
|
|
150
|
+
i = link.end;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
out.push(ch ?? "");
|
|
155
|
+
i += 1;
|
|
156
|
+
}
|
|
157
|
+
return out.join("");
|
|
158
|
+
}
|
|
159
|
+
/** Render a markdown pipe-table block as flat "cell | cell" lines. */
|
|
160
|
+
function renderTableBlock(block) {
|
|
161
|
+
const rows = [];
|
|
162
|
+
for (const row of block) {
|
|
163
|
+
// Drop the separator row (`| --- | :--: |`).
|
|
164
|
+
if (/^\s*\|?[\s|:-]+\|?\s*$/.test(row))
|
|
165
|
+
continue;
|
|
166
|
+
const cells = row
|
|
167
|
+
.trim()
|
|
168
|
+
.replace(/^\||\|$/g, "")
|
|
169
|
+
.split("|")
|
|
170
|
+
.map((c) => c.trim())
|
|
171
|
+
.filter(Boolean);
|
|
172
|
+
if (cells.length)
|
|
173
|
+
rows.push(cells.map((c) => renderInlineSpans(c)).join(" | "));
|
|
174
|
+
}
|
|
175
|
+
return rows.join("\n");
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Convert agent-style markdown into Discord markup. Block structure (fenced code,
|
|
179
|
+
* tables) is handled line-by-line so a link inside a code fence is never
|
|
180
|
+
* rewritten; inline markup (links, mentions, code) is handled per-line by
|
|
181
|
+
* {@link renderInlineSpans}. Headings / bullets / numbered lists / blockquotes
|
|
182
|
+
* render natively on Discord, so they pass through with only their inline spans
|
|
183
|
+
* rewritten.
|
|
184
|
+
*/
|
|
185
|
+
export function markdownToDiscord(markdown) {
|
|
186
|
+
if (!markdown)
|
|
187
|
+
return "";
|
|
188
|
+
const lines = markdown.split("\n");
|
|
189
|
+
const out = [];
|
|
190
|
+
let i = 0;
|
|
191
|
+
const n = lines.length;
|
|
192
|
+
while (i < n) {
|
|
193
|
+
const line = lines[i] ?? "";
|
|
194
|
+
// Fenced code block: ```lang … ``` — kept VERBATIM (language tag + interior),
|
|
195
|
+
// Discord renders it natively and a link inside must not be rewritten.
|
|
196
|
+
const fenceOpen = /^\s*```/.exec(line);
|
|
197
|
+
if (fenceOpen) {
|
|
198
|
+
out.push(line);
|
|
199
|
+
i += 1;
|
|
200
|
+
while (i < n) {
|
|
201
|
+
const inner = lines[i] ?? "";
|
|
202
|
+
out.push(inner);
|
|
203
|
+
i += 1;
|
|
204
|
+
if (/^\s*```\s*$/.test(inner))
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
// Pipe-table block: ≥2 contiguous lines that start+end with `|`. Discord has
|
|
210
|
+
// no table rendering, so flatten to "cell | cell" lines (parity w/ Slack).
|
|
211
|
+
if (/^\s*\|.*\|\s*$/.test(line)) {
|
|
212
|
+
const start = i;
|
|
213
|
+
while (i < n && /^\s*\|.*\|\s*$/.test(lines[i] ?? ""))
|
|
214
|
+
i += 1;
|
|
215
|
+
if (i - start >= 2) {
|
|
216
|
+
out.push(renderTableBlock(lines.slice(start, i)));
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
i = start;
|
|
220
|
+
}
|
|
221
|
+
// Plain / heading / bullet / quote line — render inline spans; the block
|
|
222
|
+
// markers (`#`, `-`, `>`, `1.`) are left in place for Discord to render.
|
|
223
|
+
out.push(renderInlineSpans(line));
|
|
224
|
+
i += 1;
|
|
225
|
+
}
|
|
226
|
+
return out.join("\n");
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* True when the rendered Discord text carries no visible content — only
|
|
230
|
+
* whitespace and/or markdown markers. Discord rejects an empty message body, so
|
|
231
|
+
* the send path falls back / skips when this returns true. Mirrors
|
|
232
|
+
* `slackMrkdwnIsEmpty` intent.
|
|
233
|
+
*/
|
|
234
|
+
export function discordTextIsEmpty(text) {
|
|
235
|
+
if (!text)
|
|
236
|
+
return true;
|
|
237
|
+
const stripped = text
|
|
238
|
+
// Mentions / channels / roles / emoji ARE content.
|
|
239
|
+
.replace(/<a?:[A-Za-z0-9_]+:\d+>/g, "x")
|
|
240
|
+
.replace(/<@[!&]?\d+>/g, "x")
|
|
241
|
+
.replace(/<#\d+>/g, "x")
|
|
242
|
+
.replace(/<t:\d+(?::[tTdDfFR])?>/g, "x")
|
|
243
|
+
.replace(/[*_~`>#|.\-\s]/g, "")
|
|
244
|
+
.trim();
|
|
245
|
+
return stripped.length === 0;
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../../src/agents/channels/discord/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure extractors that turn a discord.js message / reaction / interaction into
|
|
3
|
+
* the normalized fields Brigade's `InboundMessage` carries. No network, no side
|
|
4
|
+
* effects — every function here is deterministic over its argument so they're
|
|
5
|
+
* trivial to unit-test without a live gateway.
|
|
6
|
+
*
|
|
7
|
+
* Discord's wire shape (rich discord.js objects, not raw JSON like Slack's
|
|
8
|
+
* Events API) differs from Slack/Telegram in load-bearing ways, so the logic is
|
|
9
|
+
* a Brigade-native re-implementation that models the SHAPE of
|
|
10
|
+
* `slack/inbound-extras.ts` (raw payload → normalized signals) while speaking
|
|
11
|
+
* Discord semantics:
|
|
12
|
+
*
|
|
13
|
+
* - Text arrives as `message.content` peppered with Discord TOKENS: `<@123>`
|
|
14
|
+
* / `<@!123>` (user/member), `<@&456>` (role), `<#789>` (channel),
|
|
15
|
+
* `<:name:111>` / `<a:name:111>` (custom emoji). {@link extractDiscordText}
|
|
16
|
+
* expands user/channel/role mentions into readable plain text the agent can
|
|
17
|
+
* parse (`@alex`, `#general`), resolving names via an injected cache when one
|
|
18
|
+
* is supplied (the cached guild/client primes them in the background).
|
|
19
|
+
* - The bot is "addressed" when its own user id appears as a `<@123>` mention.
|
|
20
|
+
* {@link extractDiscordMentions} surfaces the bot's id when addressed so the
|
|
21
|
+
* central group ACL admits the message — exactly as Slack surfaces the bot's
|
|
22
|
+
* id. Every OTHER user mention is surfaced too.
|
|
23
|
+
* - Channel kind: a DM channel → `direct`; a guild text channel / thread →
|
|
24
|
+
* `group` (see {@link discordChannelType}).
|
|
25
|
+
* - Threads ride on the channel being a thread (`threadId` = the thread
|
|
26
|
+
* channel id); the parent text channel is the conversation root.
|
|
27
|
+
* - Reply context rides on `message.reference.messageId`.
|
|
28
|
+
* - Attachments arrive as `message.attachments` (each a CDN `url` + metadata);
|
|
29
|
+
* the connection layer DEFERS the byte download until the access gate admits
|
|
30
|
+
* the sender (mirrors Slack/Telegram's deferred-media discipline).
|
|
31
|
+
*
|
|
32
|
+
* Brigade's CENTRAL inbound pipeline owns the actual ACL / mention / routing
|
|
33
|
+
* decision — these helpers only surface the raw signals it reads.
|
|
34
|
+
*/
|
|
35
|
+
import type { InboundReplyContext } from "../sdk.js";
|
|
36
|
+
/** One attachment discord.js exposes on a message (the subset we read). */
|
|
37
|
+
export interface DiscordAttachmentLike {
|
|
38
|
+
id?: string;
|
|
39
|
+
name?: string | null;
|
|
40
|
+
/** CDN download URL (cdn.discordapp.com / media.discordapp.net). */
|
|
41
|
+
url?: string;
|
|
42
|
+
proxyURL?: string;
|
|
43
|
+
contentType?: string | null;
|
|
44
|
+
size?: number;
|
|
45
|
+
/** Discord marks voice messages with this flag-bit set; we treat them as voice. */
|
|
46
|
+
flags?: {
|
|
47
|
+
has?: (bit: unknown) => boolean;
|
|
48
|
+
} | number;
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
}
|
|
51
|
+
/** A discord.js channel (the subset Brigade reads). `isThread()`/`isDMBased()` may be absent on a fake. */
|
|
52
|
+
export interface DiscordChannelLike {
|
|
53
|
+
id?: string;
|
|
54
|
+
/** Discord channel type enum value (0 = guild text, 1 = DM, 11/12 = thread, …). */
|
|
55
|
+
type?: number;
|
|
56
|
+
isThread?: () => boolean;
|
|
57
|
+
isDMBased?: () => boolean;
|
|
58
|
+
/** Parent text-channel id when this channel is a thread. */
|
|
59
|
+
parentId?: string | null;
|
|
60
|
+
[key: string]: unknown;
|
|
61
|
+
}
|
|
62
|
+
/** A discord.js guild (the subset Brigade reads). */
|
|
63
|
+
export interface DiscordGuildLike {
|
|
64
|
+
id?: string;
|
|
65
|
+
[key: string]: unknown;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The member's roles as Brigade reads them. On a live message discord.js hands
|
|
69
|
+
* a `GuildMemberRoleManager` whose `.cache` is a Collection (a Map subclass)
|
|
70
|
+
* keyed by role id; a fake / partial may pass a plain array of role ids. Both
|
|
71
|
+
* shapes (and an absent value) are honoured by {@link extractDiscordMemberRoleIds}.
|
|
72
|
+
*/
|
|
73
|
+
export type DiscordMemberRolesLike = {
|
|
74
|
+
cache?: Map<string, unknown> | Iterable<[string, unknown]> | Iterable<{
|
|
75
|
+
id?: string;
|
|
76
|
+
}>;
|
|
77
|
+
} | Iterable<string> | string[] | null | undefined;
|
|
78
|
+
/** A discord.js user / author (the subset Brigade reads). */
|
|
79
|
+
export interface DiscordUserLike {
|
|
80
|
+
id?: string;
|
|
81
|
+
bot?: boolean;
|
|
82
|
+
username?: string;
|
|
83
|
+
globalName?: string | null;
|
|
84
|
+
/** Cached member display name (guild nickname), when discord.js resolved one. */
|
|
85
|
+
displayName?: string;
|
|
86
|
+
[key: string]: unknown;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A discord.js Message (the subset Brigade consumes). Only the fields used are
|
|
90
|
+
* typed; the live object carries far more.
|
|
91
|
+
*/
|
|
92
|
+
export interface DiscordMessageLike {
|
|
93
|
+
id?: string;
|
|
94
|
+
content?: string;
|
|
95
|
+
author?: DiscordUserLike;
|
|
96
|
+
/**
|
|
97
|
+
* The member who sent it (guild nickname lives here). `roles` is discord.js's
|
|
98
|
+
* `GuildMemberRoleManager` (a `.cache` Collection keyed by role id) on a live
|
|
99
|
+
* message; a fake / partial may instead carry a plain array of role ids.
|
|
100
|
+
*/
|
|
101
|
+
member?: {
|
|
102
|
+
nickname?: string | null;
|
|
103
|
+
displayName?: string;
|
|
104
|
+
roles?: DiscordMemberRolesLike;
|
|
105
|
+
} | null;
|
|
106
|
+
channelId?: string;
|
|
107
|
+
channel?: DiscordChannelLike;
|
|
108
|
+
guildId?: string | null;
|
|
109
|
+
guild?: DiscordGuildLike | null;
|
|
110
|
+
/** Epoch ms the message was created. */
|
|
111
|
+
createdTimestamp?: number;
|
|
112
|
+
/** Set when the message was edited (epoch ms), else null. */
|
|
113
|
+
editedTimestamp?: number | null;
|
|
114
|
+
/** Reply pointer — `messageId` is the message being replied to. */
|
|
115
|
+
reference?: {
|
|
116
|
+
messageId?: string | null;
|
|
117
|
+
channelId?: string | null;
|
|
118
|
+
guildId?: string | null;
|
|
119
|
+
} | null;
|
|
120
|
+
attachments?: Iterable<DiscordAttachmentLike> | Map<string, DiscordAttachmentLike> | DiscordAttachmentLike[];
|
|
121
|
+
/** A resolved Collection of mentioned users, or a plain array on a fake. */
|
|
122
|
+
mentions?: {
|
|
123
|
+
users?: Iterable<DiscordUserLike> | Map<string, DiscordUserLike> | DiscordUserLike[];
|
|
124
|
+
};
|
|
125
|
+
[key: string]: unknown;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Expand the Discord message TOKENS in a run of text into readable plain text:
|
|
129
|
+
* - `<@123>` / `<@!123>` → `@alex` (resolved name) or `@123`
|
|
130
|
+
* - `<@&456>` → `@role` (resolved) or `@&456`
|
|
131
|
+
* - `<#789>` → `#general` (resolved) or `#789`
|
|
132
|
+
* - `<:name:111>` / `<a:name:111>` → `:name:` (the readable emoji shortcode)
|
|
133
|
+
*
|
|
134
|
+
* Names resolve via the injected lookups (the connection primes them from the
|
|
135
|
+
* cached guild/client); without a resolver the bare id is surfaced. Pure +
|
|
136
|
+
* deterministic.
|
|
137
|
+
*/
|
|
138
|
+
export declare function expandDiscordTokens(text: string, resolve?: {
|
|
139
|
+
user?: (id: string) => string | undefined;
|
|
140
|
+
role?: (id: string) => string | undefined;
|
|
141
|
+
channel?: (id: string) => string | undefined;
|
|
142
|
+
}): string;
|
|
143
|
+
/**
|
|
144
|
+
* The agent-facing plain text of a Discord message. Token-expanded (mentions /
|
|
145
|
+
* channels / roles / emoji → readable text). Binary blobs are dropped to "".
|
|
146
|
+
*/
|
|
147
|
+
export declare function extractDiscordText(message: Pick<DiscordMessageLike, "content">, resolve?: Parameters<typeof expandDiscordTokens>[1]): string;
|
|
148
|
+
/** True when a discord.js channel is a thread (uses `isThread()` when present, else the type enum). */
|
|
149
|
+
export declare function isThreadChannel(channel: DiscordChannelLike | undefined | null): boolean;
|
|
150
|
+
/** True when a discord.js channel is a DM (uses `isDMBased()` when present, else the type enum). */
|
|
151
|
+
export declare function isDmChannel(channel: DiscordChannelLike | undefined | null): boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Discord channel → Brigade chat type. A 1:1 DM → `direct`; a guild text channel
|
|
154
|
+
* or a thread → `group`. A group DM (rare for bots) → `group`. When no channel
|
|
155
|
+
* object is available, a missing `guildId` implies a DM.
|
|
156
|
+
*/
|
|
157
|
+
export declare function discordChannelType(message: Pick<DiscordMessageLike, "channel" | "guildId">): "direct" | "group";
|
|
158
|
+
/**
|
|
159
|
+
* The thread channel id when the message landed in a thread, else undefined. The
|
|
160
|
+
* thread's own channel id is the thread id (Discord threads ARE channels).
|
|
161
|
+
*/
|
|
162
|
+
export declare function discordThreadId(message: Pick<DiscordMessageLike, "channel" | "channelId">): string | undefined;
|
|
163
|
+
/**
|
|
164
|
+
* Reply-context (what message this inbound quotes), when it's a reply. Discord
|
|
165
|
+
* carries `message.reference.messageId` (the replied-to message id) but does NOT
|
|
166
|
+
* inline that message's text — so the context surfaces the parent message id and
|
|
167
|
+
* leaves `body` undefined (the connection can fetch the parent if it needs the
|
|
168
|
+
* excerpt). Returns undefined for a non-reply.
|
|
169
|
+
*/
|
|
170
|
+
export declare function extractDiscordReplyContext(message: Pick<DiscordMessageLike, "reference">): InboundReplyContext | undefined;
|
|
171
|
+
/**
|
|
172
|
+
* Channel-native ids of users addressed in this message. Brigade's central group
|
|
173
|
+
* ACL treats a group message as "addressed to the bot" when the bot's own id
|
|
174
|
+
* appears in `mentions`; without this a group message never reaches the agent.
|
|
175
|
+
* So when the bot's own `<@id>` mention appears in the text we surface the bot's
|
|
176
|
+
* id (passed in). Every OTHER user mention is surfaced too so the pipeline sees
|
|
177
|
+
* who else was tagged.
|
|
178
|
+
*
|
|
179
|
+
* We scan BOTH the resolved `message.mentions.users` collection (when present)
|
|
180
|
+
* AND the raw `<@id>` / `<@!id>` tokens in the content, unioned + deduped — the
|
|
181
|
+
* collection is authoritative on a live message, the token scan is the fallback
|
|
182
|
+
* for a fake / a partial.
|
|
183
|
+
*
|
|
184
|
+
* @param botUserId the bot's own user id, surfaced when the bot is mentioned so
|
|
185
|
+
* the ACL admits the group message.
|
|
186
|
+
*/
|
|
187
|
+
export declare function extractDiscordMentions(message: DiscordMessageLike, botUserId?: string): string[];
|
|
188
|
+
/**
|
|
189
|
+
* The guild-role ids the sending member holds, surfaced so the 8-tier route
|
|
190
|
+
* resolver's `binding.guild+roles` tier can match. Role NAMES are never used —
|
|
191
|
+
* only ids. Returns `[]` for a DM (no member) or when no roles resolve.
|
|
192
|
+
*
|
|
193
|
+
* Handles the three shapes the `member.roles` value can take:
|
|
194
|
+
* - discord.js `GuildMemberRoleManager` — a `.cache` Collection (Map subclass)
|
|
195
|
+
* keyed by role id; we read the keys (the role ids).
|
|
196
|
+
* - a plain array / iterable of role-id strings (a fake / partial).
|
|
197
|
+
* - absent / null (a DM, or a message with no resolved member) → `[]`.
|
|
198
|
+
*
|
|
199
|
+
* Pure + deterministic; deduped, with the `@everyone` role (whose id equals the
|
|
200
|
+
* guild id and is implicit for everyone) left in as-is — the resolver only
|
|
201
|
+
* matches ids a binding explicitly lists, so a stray everyone id is harmless.
|
|
202
|
+
*/
|
|
203
|
+
export declare function extractDiscordMemberRoleIds(message: Pick<DiscordMessageLike, "member">): string[];
|
|
204
|
+
/**
|
|
205
|
+
* A short display name for the sender. A guild nickname wins (most specific),
|
|
206
|
+
* then the member/global display name, then the username, then the raw id.
|
|
207
|
+
*/
|
|
208
|
+
export declare function buildDiscordSenderName(message: DiscordMessageLike): string | undefined;
|
|
209
|
+
/**
|
|
210
|
+
* Cheap presence probe — does this message carry a downloadable attachment?
|
|
211
|
+
* Walks `message.attachments` but never touches the network, so the connection
|
|
212
|
+
* layer can DEFER the actual download until AFTER the central access gate admits
|
|
213
|
+
* the sender (mirrors Slack/Telegram). Mirrors `hasInboundMedia`.
|
|
214
|
+
*/
|
|
215
|
+
export declare function hasInboundMedia(message: Pick<DiscordMessageLike, "attachments">): boolean;
|
|
216
|
+
/** The list of downloadable attachments on a message. */
|
|
217
|
+
export declare function resolveInboundAttachments(message: Pick<DiscordMessageLike, "attachments">): DiscordAttachmentLike[];
|
|
218
|
+
/** The Brigade media-kind of a Discord attachment, from its contentType / filename / voice flag. */
|
|
219
|
+
export declare function resolveDiscordAttachmentKind(a: DiscordAttachmentLike): "image" | "video" | "audio" | "voice" | "document";
|
|
220
|
+
//# sourceMappingURL=inbound-extras.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound-extras.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/discord/inbound-extras.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAIrD,2EAA2E;AAC3E,MAAM,WAAW,qBAAqB;IACrC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,KAAK,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAA;KAAE,GAAG,MAAM,CAAC;IACrD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED,2GAA2G;AAC3G,MAAM,WAAW,kBAAkB;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,mFAAmF;IACnF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;IAC1B,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED,qDAAqD;AACrD,MAAM,WAAW,gBAAgB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAC/B;IAAE,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,QAAQ,CAAC;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAC1F,QAAQ,CAAC,MAAM,CAAC,GAChB,MAAM,EAAE,GACR,IAAI,GACJ,SAAS,CAAC;AAEb,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;;OAIG;IACH,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,sBAAsB,CAAA;KAAE,GAAG,IAAI,CAAC;IACnG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAChC,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6DAA6D;IAC7D,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mEAAmE;IACnE,SAAS,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IACrG,WAAW,CAAC,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,GAAG,qBAAqB,EAAE,CAAC;IAC7G,4EAA4E;IAC5E,QAAQ,CAAC,EAAE;QACV,KAAK,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,eAAe,EAAE,CAAC;KACrF,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AA+BD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IACT,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC1C,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC1C,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC7C,GACC,MAAM,CAkBR;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC,EAC5C,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,GACjD,MAAM,CAIR;AASD,uGAAuG;AACvG,wBAAgB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAIvF;AAED,oGAAoG;AACpG,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAInF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,SAAS,CAAC,GAAG,QAAQ,GAAG,OAAO,CAQ/G;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,WAAW,CAAC,GAAG,MAAM,GAAG,SAAS,CAM9G;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,WAAW,CAAC,GAAG,mBAAmB,GAAG,SAAS,CAK1H;AAID;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,kBAAkB,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CA4BhG;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GAAG,MAAM,EAAE,CA2CjG;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAWtF;AAYD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,GAAG,OAAO,CAEzF;AAED,yDAAyD;AACzD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,GAAG,qBAAqB,EAAE,CAEnH;AAgBD,oGAAoG;AACpG,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,qBAAqB,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,CAWzH"}
|