@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,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discord config-shape helpers (multi-ACCOUNT aware; mirrors Slack's
|
|
3
|
+
* `account-config.ts`).
|
|
4
|
+
*
|
|
5
|
+
* Discord needs ONE secret per account — the bot token (every Gateway login +
|
|
6
|
+
* REST call uses it). Unlike Slack (bot + app + signing tokens), there is no
|
|
7
|
+
* second credential: the Gateway opens a websocket with the bot token, and the
|
|
8
|
+
* same token drives the REST outbound. So this module is closer to Telegram's
|
|
9
|
+
* single-token shape than Slack's three-token one, but it keeps Slack's
|
|
10
|
+
* multi-account discovery so an operator can run >1 bot at once.
|
|
11
|
+
*
|
|
12
|
+
* Two config shapes are recognised so the surface lines up with WhatsApp /
|
|
13
|
+
* Telegram / Slack:
|
|
14
|
+
*
|
|
15
|
+
* Legacy (single-account):
|
|
16
|
+
* channels.discord = { enabled: true, botToken: "…" }
|
|
17
|
+
*
|
|
18
|
+
* Multi-account:
|
|
19
|
+
* channels.discord = {
|
|
20
|
+
* enabled: true,
|
|
21
|
+
* accounts: [
|
|
22
|
+
* { id: "main", botToken: "…AAA" },
|
|
23
|
+
* { id: "labs", botToken: "…BBB" },
|
|
24
|
+
* ],
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* A legacy config with no `accounts[]` reads as `[{ id: "default" }]`.
|
|
28
|
+
*
|
|
29
|
+
* Token resolution mirrors Slack/Telegram: a `${VAR}` ref expands against
|
|
30
|
+
* `process.env`; otherwise the literal passes through; then a DURABLE sealed
|
|
31
|
+
* token (written by `connect_channel`) is consulted so the channel survives a
|
|
32
|
+
* reboot; finally the per-secret env var `DISCORD_BOT_TOKEN` is the last-resort
|
|
33
|
+
* fallback. A leading `Bot ` prefix (Discord's REST scheme prefix) is stripped
|
|
34
|
+
* so an operator who pasted the whole `Authorization` header still works.
|
|
35
|
+
*/
|
|
36
|
+
import { readSealedChannelToken } from "../channel-secrets.js";
|
|
37
|
+
const CHANNEL_ID = "discord";
|
|
38
|
+
const DEFAULT_ACCOUNT_ID = "default";
|
|
39
|
+
/** Per-secret env var consulted as a last-resort fallback. */
|
|
40
|
+
const BOT_TOKEN_ENV_VAR = "DISCORD_BOT_TOKEN";
|
|
41
|
+
/**
|
|
42
|
+
* Standard proxy env vars consulted as a last-resort proxy fallback, in
|
|
43
|
+
* precedence order. Lower-case wins over upper-case (curl/undici convention),
|
|
44
|
+
* and a TLS-oriented `https_proxy` outranks the catch-all `ALL_PROXY`. Mirrors
|
|
45
|
+
* the keys Slack/Telegram honour.
|
|
46
|
+
*/
|
|
47
|
+
const PROXY_ENV_VARS = ["https_proxy", "HTTPS_PROXY", "all_proxy", "ALL_PROXY"];
|
|
48
|
+
/**
|
|
49
|
+
* Sealed-token key for the bot token (`channel:discord`) — the secret
|
|
50
|
+
* `connect_channel` seals. The bot token is the only Discord credential, so it
|
|
51
|
+
* is the one that gets the sealed-read fallback.
|
|
52
|
+
*/
|
|
53
|
+
const SEAL_KEY_BOT = CHANNEL_ID; // `channel:discord`
|
|
54
|
+
/** `${VAR}` secret-ref form — identical to `config/io.ts`'s SECRET_REF_PATTERN. */
|
|
55
|
+
const SECRET_REF_PATTERN = /^\$\{([A-Z_][A-Z0-9_]*)\}$/;
|
|
56
|
+
/** Read `channels.discord` loosely (schema keeps it open). */
|
|
57
|
+
function discordChannelConfig(cfg) {
|
|
58
|
+
return cfg.channels?.[CHANNEL_ID];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Resolve a single token-ish string: a `${VAR}` ref expands against
|
|
62
|
+
* `process.env`; any other non-empty string passes through verbatim; empty /
|
|
63
|
+
* missing returns "".
|
|
64
|
+
*/
|
|
65
|
+
function resolveTokenRef(raw, env) {
|
|
66
|
+
if (typeof raw !== "string")
|
|
67
|
+
return "";
|
|
68
|
+
const trimmed = raw.trim();
|
|
69
|
+
if (!trimmed)
|
|
70
|
+
return "";
|
|
71
|
+
const m = SECRET_REF_PATTERN.exec(trimmed);
|
|
72
|
+
if (m && m[1])
|
|
73
|
+
return (env[m[1]] ?? "").trim();
|
|
74
|
+
return trimmed;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Strip a leading `Bot ` scheme prefix from a Discord token. Discord's REST
|
|
78
|
+
* `Authorization` header is `Bot <token>`; an operator who pasted the whole
|
|
79
|
+
* header still gets a clean token. Idempotent + case-insensitive.
|
|
80
|
+
*/
|
|
81
|
+
export function stripBotPrefix(token) {
|
|
82
|
+
return token.replace(/^Bot\s+/i, "").trim();
|
|
83
|
+
}
|
|
84
|
+
/** Is the Discord channel switched on at all (any shape)? */
|
|
85
|
+
export function discordChannelEnabled(cfg) {
|
|
86
|
+
return discordChannelConfig(cfg)?.enabled === true;
|
|
87
|
+
}
|
|
88
|
+
/** List configured account ids. Legacy single-account configs surface `["default"]`. */
|
|
89
|
+
export function listDiscordAccountIds(cfg) {
|
|
90
|
+
const slot = discordChannelConfig(cfg);
|
|
91
|
+
if (!slot || slot.enabled !== true)
|
|
92
|
+
return [];
|
|
93
|
+
const accounts = Array.isArray(slot.accounts) ? slot.accounts : undefined;
|
|
94
|
+
if (!accounts || accounts.length === 0)
|
|
95
|
+
return [DEFAULT_ACCOUNT_ID];
|
|
96
|
+
const ids = [];
|
|
97
|
+
const seen = new Set();
|
|
98
|
+
for (const entry of accounts) {
|
|
99
|
+
const id = typeof entry?.id === "string" ? entry.id.trim() : "";
|
|
100
|
+
if (!id || seen.has(id))
|
|
101
|
+
continue;
|
|
102
|
+
seen.add(id);
|
|
103
|
+
ids.push(id);
|
|
104
|
+
}
|
|
105
|
+
// A half-typed `accounts:[]` still degrades to the default account so the
|
|
106
|
+
// channel isn't silently disabled.
|
|
107
|
+
return ids.length === 0 ? [DEFAULT_ACCOUNT_ID] : ids;
|
|
108
|
+
}
|
|
109
|
+
/** Look up the raw account entry from config (or null when missing). */
|
|
110
|
+
function findAccountEntry(cfg, accountId) {
|
|
111
|
+
const slot = discordChannelConfig(cfg);
|
|
112
|
+
if (!slot)
|
|
113
|
+
return null;
|
|
114
|
+
const accounts = Array.isArray(slot.accounts) ? slot.accounts : undefined;
|
|
115
|
+
if (!accounts)
|
|
116
|
+
return null;
|
|
117
|
+
for (const entry of accounts) {
|
|
118
|
+
const id = typeof entry?.id === "string" ? entry.id.trim() : "";
|
|
119
|
+
if (id === accountId)
|
|
120
|
+
return entry;
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Resolve the Discord bot token for an account. Precedence (mirrors Slack's
|
|
126
|
+
* token resolution): per-account config `${VAR}`/literal → top-level config →
|
|
127
|
+
* durable sealed token → per-secret env var. The `Bot ` scheme prefix is
|
|
128
|
+
* stripped from whichever source wins. Returns `""` when nothing resolves.
|
|
129
|
+
*/
|
|
130
|
+
export function resolveDiscordBotToken(cfg, accountId, env = process.env) {
|
|
131
|
+
const id = accountId?.trim() || DEFAULT_ACCOUNT_ID;
|
|
132
|
+
const slot = discordChannelConfig(cfg);
|
|
133
|
+
const entry = findAccountEntry(cfg, id);
|
|
134
|
+
const perAccount = resolveTokenRef(entry?.botToken, env);
|
|
135
|
+
if (perAccount)
|
|
136
|
+
return stripBotPrefix(perAccount);
|
|
137
|
+
const topLevel = resolveTokenRef(slot?.botToken, env);
|
|
138
|
+
if (topLevel)
|
|
139
|
+
return stripBotPrefix(topLevel);
|
|
140
|
+
const sealed = readSealedChannelToken(SEAL_KEY_BOT);
|
|
141
|
+
if (sealed)
|
|
142
|
+
return stripBotPrefix(sealed);
|
|
143
|
+
const fromEnv = (env[BOT_TOKEN_ENV_VAR] ?? "").trim();
|
|
144
|
+
if (fromEnv)
|
|
145
|
+
return stripBotPrefix(fromEnv);
|
|
146
|
+
return "";
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Resolve the proxy URL all Discord REST calls (+ the Gateway websocket) should
|
|
150
|
+
* route through. Precedence (mirrors Slack's `resolveSlackProxyUrl`):
|
|
151
|
+
* 1. The per-account `accounts[].proxy` (multi-account shape), `${VAR}`-resolved.
|
|
152
|
+
* 2. The top-level `channels.discord.proxy`, `${VAR}`-resolved.
|
|
153
|
+
* 3. The first set standard proxy env var (`https_proxy` / `HTTPS_PROXY` /
|
|
154
|
+
* `all_proxy` / `ALL_PROXY`) — last-resort fallback.
|
|
155
|
+
* Returns `""` when none is configured → a DIRECT connection (the default).
|
|
156
|
+
*
|
|
157
|
+
* `${VAR}` refs are resolved here the same way `botToken` is, so an operator can
|
|
158
|
+
* keep the proxy (which may carry `user:pass@` creds) out of the committed
|
|
159
|
+
* config as `channels.discord.proxy: "${DISCORD_PROXY}"`.
|
|
160
|
+
*/
|
|
161
|
+
export function resolveDiscordProxyUrl(cfg, accountId, env = process.env) {
|
|
162
|
+
const id = accountId?.trim() || DEFAULT_ACCOUNT_ID;
|
|
163
|
+
const slot = discordChannelConfig(cfg);
|
|
164
|
+
const entry = findAccountEntry(cfg, id);
|
|
165
|
+
const perAccount = resolveTokenRef(entry?.proxy, env);
|
|
166
|
+
if (perAccount)
|
|
167
|
+
return perAccount;
|
|
168
|
+
const topLevel = resolveTokenRef(slot?.proxy, env);
|
|
169
|
+
if (topLevel)
|
|
170
|
+
return topLevel;
|
|
171
|
+
for (const key of PROXY_ENV_VARS) {
|
|
172
|
+
const value = (env[key] ?? "").trim();
|
|
173
|
+
if (value)
|
|
174
|
+
return value;
|
|
175
|
+
}
|
|
176
|
+
return "";
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Mask a proxy URL down to `scheme://host:port` (creds + path dropped) so it is
|
|
180
|
+
* safe to log. A malformed URL is reduced to its scheme only; an empty input
|
|
181
|
+
* returns "". NEVER log a raw proxy URL — it may embed `user:pass@`.
|
|
182
|
+
*/
|
|
183
|
+
export function maskProxyUrl(proxyUrl) {
|
|
184
|
+
const raw = (proxyUrl ?? "").trim();
|
|
185
|
+
if (!raw)
|
|
186
|
+
return "";
|
|
187
|
+
try {
|
|
188
|
+
const u = new URL(raw);
|
|
189
|
+
return `${u.protocol}//${u.host}`; // host includes :port; userinfo + path/query dropped
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
const scheme = /^([a-z][a-z0-9+.-]*):\/\//i.exec(raw)?.[1];
|
|
193
|
+
return scheme ? `${scheme}://<masked>` : "<masked>";
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/** Resolve a per-account view of the config (defaults + token resolution filled in). */
|
|
197
|
+
export function resolveDiscordAccount(cfg, accountId, env = process.env) {
|
|
198
|
+
const slot = discordChannelConfig(cfg);
|
|
199
|
+
const id = accountId?.trim() || DEFAULT_ACCOUNT_ID;
|
|
200
|
+
const entry = findAccountEntry(cfg, id);
|
|
201
|
+
const enabled = entry?.enabled !== false && slot?.enabled === true;
|
|
202
|
+
return {
|
|
203
|
+
accountId: id,
|
|
204
|
+
enabled,
|
|
205
|
+
botToken: resolveDiscordBotToken(cfg, id, env),
|
|
206
|
+
proxyUrl: resolveDiscordProxyUrl(cfg, id, env),
|
|
207
|
+
verbose: slot?.verbose === true,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/* ───────────────────────── lifecycle / streaming config ───────────────────────── */
|
|
211
|
+
/**
|
|
212
|
+
* True when live reply-streaming is enabled (`channels.discord.liveStream`).
|
|
213
|
+
* Default OFF — the adapter delivers one final chunked message.
|
|
214
|
+
*/
|
|
215
|
+
export function discordLiveStreamEnabled(cfg) {
|
|
216
|
+
return discordChannelConfig(cfg)?.liveStream === true;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Resolve the streaming edit throttle in ms. Reads
|
|
220
|
+
* `channels.discord.streamThrottleMs`; falls back to 1000ms (floored at 250ms by
|
|
221
|
+
* the draft-stream).
|
|
222
|
+
*/
|
|
223
|
+
export function discordStreamThrottleMs(cfg) {
|
|
224
|
+
const raw = discordChannelConfig(cfg)?.streamThrottleMs;
|
|
225
|
+
return typeof raw === "number" && raw > 0 ? raw : 1000;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* True when reasoning surfacing is enabled (`channels.discord.surfaceReasoning`).
|
|
229
|
+
* Default OFF — `<think>` reasoning is stripped from channel replies as today.
|
|
230
|
+
*/
|
|
231
|
+
export function discordSurfaceReasoning(cfg) {
|
|
232
|
+
return discordChannelConfig(cfg)?.surfaceReasoning === true;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Resolve the idle-thread-session TTL in ms, or `null` when unset / disabled.
|
|
236
|
+
* Accepts a number (ms) or a duration string (`"6h"`, `"30m"`, …). The cron
|
|
237
|
+
* session-reaper uses this to age out idle Discord thread sessions.
|
|
238
|
+
*/
|
|
239
|
+
export function discordThreadIdleTtlMs(cfg) {
|
|
240
|
+
const raw = discordChannelConfig(cfg)?.threadIdleTtlMs;
|
|
241
|
+
if (typeof raw === "number")
|
|
242
|
+
return raw > 0 ? raw : null;
|
|
243
|
+
if (typeof raw !== "string")
|
|
244
|
+
return null;
|
|
245
|
+
const trimmed = raw.trim();
|
|
246
|
+
if (!trimmed)
|
|
247
|
+
return null;
|
|
248
|
+
const m = /^(\d+)\s*(s|m|h|d|w)?$/i.exec(trimmed);
|
|
249
|
+
if (!m)
|
|
250
|
+
return null;
|
|
251
|
+
const n = Number(m[1]);
|
|
252
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
253
|
+
return null;
|
|
254
|
+
const unit = (m[2] ?? "ms").toLowerCase();
|
|
255
|
+
const mult = { s: 1_000, m: 60_000, h: 3_600_000, d: 86_400_000, w: 604_800_000, ms: 1 };
|
|
256
|
+
const factor = mult[unit] ?? 1;
|
|
257
|
+
return n * factor;
|
|
258
|
+
}
|
|
259
|
+
export { CHANNEL_ID as DISCORD_CHANNEL_ID, DEFAULT_ACCOUNT_ID as DISCORD_DEFAULT_ACCOUNT_ID, BOT_TOKEN_ENV_VAR as DISCORD_BOT_TOKEN_ENV_VAR, };
|
|
260
|
+
//# sourceMappingURL=account-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-config.js","sourceRoot":"","sources":["../../../../src/agents/channels/discord/account-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discord channel adapter.
|
|
3
|
+
*
|
|
4
|
+
* Implements the Brigade `ChannelAdapter` contract on top of the discord.js
|
|
5
|
+
* Gateway + REST connection. Like Slack, Discord is TOKEN-based: the operator
|
|
6
|
+
* pastes a bot token from the Discord Developer Portal, so this adapter declares
|
|
7
|
+
* a `setup` wizard (one credential) and has NO QR/link flow. Enablement is
|
|
8
|
+
* explicit — `channels.discord.enabled: true` plus a resolvable bot token.
|
|
9
|
+
*
|
|
10
|
+
* Modeled directly on `slack/adapter.ts`: same health-flag mirroring, same
|
|
11
|
+
* deferred-media passthrough on inbound, same chunk-then-send outbound shape
|
|
12
|
+
* (chunk markdown ≤2000, convert each chunk to Discord markup, send). Discord
|
|
13
|
+
* markup never "fails to parse" the way Telegram HTML can, so the outbound path
|
|
14
|
+
* is simple — an empty rendered chunk falls back to the raw chunk.
|
|
15
|
+
*
|
|
16
|
+
* Capabilities: edit (message.edit), unsend (message.delete), reactions
|
|
17
|
+
* (message.react), reply (reply reference + threads), threads, media
|
|
18
|
+
* (AttachmentBuilder), buttons (ActionRow + Button), and NATIVE slash commands
|
|
19
|
+
* (registered via REST application commands on connect). Unlike Slack, Discord's
|
|
20
|
+
* command menu IS pushed programmatically — `nativeCommands: true`.
|
|
21
|
+
*/
|
|
22
|
+
import { type ChannelAdapter, type ChannelCapabilities } from "../sdk.js";
|
|
23
|
+
import { type ConnectDiscordArgs, type DiscordConnection } from "./connection.js";
|
|
24
|
+
/** Adapter construction options — all optional for back-compat. */
|
|
25
|
+
export interface CreateDiscordAdapterOptions {
|
|
26
|
+
/** Per-account scope. Defaults to `"default"` (single-account). */
|
|
27
|
+
accountId?: string;
|
|
28
|
+
/**
|
|
29
|
+
* TEST SEAM: override how the connection is built. Production leaves this
|
|
30
|
+
* undefined and `connectDiscord` lazy-loads discord.js. Tests inject a fake.
|
|
31
|
+
*/
|
|
32
|
+
connectImpl?: (args: ConnectDiscordArgs) => Promise<DiscordConnection>;
|
|
33
|
+
}
|
|
34
|
+
export declare function createDiscordAdapter(opts?: CreateDiscordAdapterOptions): ChannelAdapter;
|
|
35
|
+
/**
|
|
36
|
+
* Synthesise the agent-facing note for an inbound reaction. The reaction itself
|
|
37
|
+
* carries no text, so the note ("<who> reacted :emoji: to message <id>") is what
|
|
38
|
+
* the central pipeline routes through dispatchTurn so the agent has context.
|
|
39
|
+
*/
|
|
40
|
+
export declare function buildReactionNote(emojis: string[], targetMessageId: string, fromName?: string): string;
|
|
41
|
+
/** Static Discord capability flags (shared by the legacy adapter + plugin meta). */
|
|
42
|
+
export declare const DISCORD_CAPABILITIES: ChannelCapabilities;
|
|
43
|
+
/**
|
|
44
|
+
* The Discord adapter shape with its liveness extension. `createDiscordAdapter`
|
|
45
|
+
* returns a `ChannelAdapter`, but the concrete object ALSO carries `lastEventAt`
|
|
46
|
+
* (not in the base contract). Callers that need it cast through this type.
|
|
47
|
+
*/
|
|
48
|
+
export interface DiscordAdapter extends ChannelAdapter {
|
|
49
|
+
/**
|
|
50
|
+
* Epoch ms of the most recent inbound event (liveness diagnostic), or null
|
|
51
|
+
* before the first event / when not started. Observability only — never flips
|
|
52
|
+
* health to "down" (a quiet channel is legitimately idle).
|
|
53
|
+
*/
|
|
54
|
+
lastEventAt(): number | null;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/discord/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAOH,OAAO,EAGN,KAAK,cAAc,EAEnB,KAAK,mBAAmB,EAQxB,MAAM,WAAW,CAAC;AAgBnB,OAAO,EAAkB,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAQlG,mEAAmE;AACnE,MAAM,WAAW,2BAA2B;IAC3C,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACvE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,GAAE,2BAAgC,GAAG,cAAc,CA4c3F;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAKtG;AAED,oFAAoF;AACpF,eAAO,MAAM,oBAAoB,EAAE,mBASlC,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,cAAe,SAAQ,cAAc;IACrD;;;;OAIG;IACH,WAAW,IAAI,MAAM,GAAG,IAAI,CAAC;CAC7B"}
|