@hybridaione/hybridclaw 0.2.1 → 0.2.2
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/CHANGELOG.md +23 -0
- package/README.md +47 -15
- package/container/package-lock.json +2 -2
- package/container/package.json +1 -1
- package/container/src/browser-tools.ts +1 -1
- package/container/src/index.ts +243 -14
- package/container/src/token-usage.ts +18 -2
- package/container/src/tools.ts +339 -1
- package/container/src/types.ts +28 -2
- package/dist/agent.d.ts +2 -2
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +2 -2
- package/dist/agent.js.map +1 -1
- package/dist/channels/discord/attachments.d.ts +9 -0
- package/dist/channels/discord/attachments.d.ts.map +1 -0
- package/dist/channels/discord/attachments.js +245 -0
- package/dist/channels/discord/attachments.js.map +1 -0
- package/dist/channels/discord/delivery.d.ts +31 -0
- package/dist/channels/discord/delivery.d.ts.map +1 -0
- package/dist/channels/discord/delivery.js +60 -0
- package/dist/channels/discord/delivery.js.map +1 -0
- package/dist/channels/discord/inbound.d.ts +20 -0
- package/dist/channels/discord/inbound.d.ts.map +1 -0
- package/dist/channels/discord/inbound.js +44 -0
- package/dist/channels/discord/inbound.js.map +1 -0
- package/dist/channels/discord/mentions.d.ts +14 -0
- package/dist/channels/discord/mentions.d.ts.map +1 -0
- package/dist/channels/discord/mentions.js +118 -0
- package/dist/channels/discord/mentions.js.map +1 -0
- package/dist/channels/discord/runtime.d.ts +22 -0
- package/dist/channels/discord/runtime.d.ts.map +1 -0
- package/dist/channels/discord/runtime.js +972 -0
- package/dist/channels/discord/runtime.js.map +1 -0
- package/dist/channels/discord/stream.d.ts +32 -0
- package/dist/channels/discord/stream.d.ts.map +1 -0
- package/dist/channels/discord/stream.js +196 -0
- package/dist/channels/discord/stream.js.map +1 -0
- package/dist/channels/discord/tool-actions.d.ts +31 -0
- package/dist/channels/discord/tool-actions.d.ts.map +1 -0
- package/dist/channels/discord/tool-actions.js +268 -0
- package/dist/channels/discord/tool-actions.js.map +1 -0
- package/dist/container-runner.d.ts +2 -2
- package/dist/container-runner.d.ts.map +1 -1
- package/dist/container-runner.js +12 -2
- package/dist/container-runner.js.map +1 -1
- package/dist/discord.basic.test.d.ts +2 -0
- package/dist/discord.basic.test.d.ts.map +1 -0
- package/dist/discord.basic.test.js +38 -0
- package/dist/discord.basic.test.js.map +1 -0
- package/dist/discord.d.ts +5 -44
- package/dist/discord.d.ts.map +1 -1
- package/dist/discord.js +3 -1468
- package/dist/discord.js.map +1 -1
- package/dist/gateway-service.d.ts +7 -1
- package/dist/gateway-service.d.ts.map +1 -1
- package/dist/gateway-service.js +111 -2
- package/dist/gateway-service.js.map +1 -1
- package/dist/gateway-service.media-routing.test.d.ts +2 -0
- package/dist/gateway-service.media-routing.test.d.ts.map +1 -0
- package/dist/gateway-service.media-routing.test.js +29 -0
- package/dist/gateway-service.media-routing.test.js.map +1 -0
- package/dist/gateway-types.d.ts +8 -0
- package/dist/gateway-types.d.ts.map +1 -1
- package/dist/gateway-types.js.map +1 -1
- package/dist/gateway.js +5 -2
- package/dist/gateway.js.map +1 -1
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js +1 -1
- package/dist/health.js.map +1 -1
- package/dist/heartbeat.d.ts.map +1 -1
- package/dist/heartbeat.js +2 -0
- package/dist/heartbeat.js.map +1 -1
- package/dist/token-efficiency.basic.test.d.ts +2 -0
- package/dist/token-efficiency.basic.test.d.ts.map +1 -0
- package/dist/token-efficiency.basic.test.js +29 -0
- package/dist/token-efficiency.basic.test.js.map +1 -0
- package/dist/token-efficiency.d.ts.map +1 -1
- package/dist/token-efficiency.js +18 -1
- package/dist/token-efficiency.js.map +1 -1
- package/dist/types.d.ts +23 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +10 -2
- package/src/agent.ts +11 -1
- package/src/channels/discord/attachments.ts +282 -0
- package/src/channels/discord/delivery.ts +99 -0
- package/src/channels/discord/inbound.ts +72 -0
- package/src/channels/discord/mentions.ts +130 -0
- package/src/{discord.ts → channels/discord/runtime.ts} +77 -615
- package/src/{discord-stream.ts → channels/discord/stream.ts} +2 -2
- package/src/channels/discord/tool-actions.ts +332 -0
- package/src/container-runner.ts +24 -1
- package/src/gateway-service.ts +125 -1
- package/src/gateway-types.ts +8 -0
- package/src/gateway.ts +5 -5
- package/src/health.ts +2 -1
- package/src/heartbeat.ts +2 -0
- package/src/token-efficiency.ts +17 -1
- package/src/types.ts +27 -1
- package/tests/discord.basic.test.ts +43 -0
- package/tests/gateway-service.media-routing.test.ts +33 -0
- package/tests/token-efficiency.basic.test.ts +32 -0
- package/vitest.e2e.config.ts +15 -0
- package/vitest.integration.config.ts +15 -0
- package/vitest.live.config.ts +16 -0
- package/vitest.unit.config.ts +15 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { randomUUID } from 'crypto';
|
|
4
|
+
import { DATA_DIR } from '../../config.js';
|
|
5
|
+
import { logger } from '../../logger.js';
|
|
6
|
+
const MAX_ATTACHMENT_BYTES = 10 * 1024 * 1024;
|
|
7
|
+
const MAX_ATTACHMENT_CONTEXT_CHARS = 16_000;
|
|
8
|
+
const MAX_SINGLE_ATTACHMENT_CHARS = 8_000;
|
|
9
|
+
const DISCORD_MEDIA_CACHE_DIR = path.resolve(path.join(DATA_DIR, 'discord-media-cache'));
|
|
10
|
+
const CONTAINER_DISCORD_MEDIA_CACHE_DIR = '/discord-media-cache';
|
|
11
|
+
const DISCORD_ATTACHMENT_FETCH_TIMEOUT_MS = 12_000;
|
|
12
|
+
const DISCORD_CDN_HOST_PATTERNS = [
|
|
13
|
+
/^cdn\.discordapp\.com$/i,
|
|
14
|
+
/^media\.discordapp\.net$/i,
|
|
15
|
+
/^cdn\.discordapp\.net$/i,
|
|
16
|
+
/^images-ext-\d+\.discordapp\.net$/i,
|
|
17
|
+
];
|
|
18
|
+
export function looksLikeTextAttachment(name, contentType) {
|
|
19
|
+
if (contentType.startsWith('text/'))
|
|
20
|
+
return true;
|
|
21
|
+
if (contentType.includes('json') || contentType.includes('xml') || contentType.includes('yaml'))
|
|
22
|
+
return true;
|
|
23
|
+
return /\.(txt|md|markdown|json|ya?ml|js|jsx|ts|tsx|py|rb|go|rs|java|c|cpp|h|hpp|cs|php|html?|css|scss|sql|log|csv)$/i.test(name);
|
|
24
|
+
}
|
|
25
|
+
function looksLikeImageAttachment(name, contentType) {
|
|
26
|
+
if (contentType.startsWith('image/'))
|
|
27
|
+
return true;
|
|
28
|
+
return /\.(png|jpe?g|gif|webp|bmp|svg|heic|heif|tiff?)$/i.test(name);
|
|
29
|
+
}
|
|
30
|
+
function sanitizeAttachmentFilename(name) {
|
|
31
|
+
const base = name.trim().replace(/[^\w.\-]+/g, '-').replace(/-+/g, '-').replace(/^-+|-+$/g, '');
|
|
32
|
+
const bounded = base.slice(0, 96);
|
|
33
|
+
return bounded || 'attachment';
|
|
34
|
+
}
|
|
35
|
+
function normalizeAttachmentPathForContainer(hostPath) {
|
|
36
|
+
const relative = path.relative(DISCORD_MEDIA_CACHE_DIR, hostPath);
|
|
37
|
+
if (!relative || relative.startsWith('..') || path.isAbsolute(relative))
|
|
38
|
+
return null;
|
|
39
|
+
return `${CONTAINER_DISCORD_MEDIA_CACHE_DIR}/${relative.replace(/\\/g, '/')}`;
|
|
40
|
+
}
|
|
41
|
+
function isAllowedDiscordAttachmentUrl(rawUrl) {
|
|
42
|
+
let parsed;
|
|
43
|
+
try {
|
|
44
|
+
parsed = new URL(rawUrl);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
if (parsed.protocol !== 'https:')
|
|
50
|
+
return false;
|
|
51
|
+
return DISCORD_CDN_HOST_PATTERNS.some((pattern) => pattern.test(parsed.hostname));
|
|
52
|
+
}
|
|
53
|
+
async function fetchAttachmentText(url, maxChars) {
|
|
54
|
+
try {
|
|
55
|
+
const response = await fetch(url);
|
|
56
|
+
if (!response.ok)
|
|
57
|
+
return null;
|
|
58
|
+
const text = await response.text();
|
|
59
|
+
if (!text)
|
|
60
|
+
return null;
|
|
61
|
+
if (text.length <= maxChars)
|
|
62
|
+
return text;
|
|
63
|
+
return `${text.slice(0, Math.max(1_000, maxChars - 32))}\n...[truncated]`;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function cacheDiscordImageAttachment(params) {
|
|
70
|
+
const { attachment, messageId, order, fallbackMimeType } = params;
|
|
71
|
+
const attachmentName = attachment.name || 'image';
|
|
72
|
+
const sourceCandidates = [attachment.url, attachment.proxyURL]
|
|
73
|
+
.map((value) => String(value || '').trim())
|
|
74
|
+
.filter(Boolean);
|
|
75
|
+
await fs.promises.mkdir(DISCORD_MEDIA_CACHE_DIR, { recursive: true });
|
|
76
|
+
const fetchErrors = [];
|
|
77
|
+
for (const candidateUrl of sourceCandidates) {
|
|
78
|
+
if (!isAllowedDiscordAttachmentUrl(candidateUrl)) {
|
|
79
|
+
fetchErrors.push(`blocked_url:${candidateUrl}`);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const controller = new AbortController();
|
|
83
|
+
const timer = setTimeout(() => controller.abort(), DISCORD_ATTACHMENT_FETCH_TIMEOUT_MS);
|
|
84
|
+
try {
|
|
85
|
+
const response = await fetch(candidateUrl, { signal: controller.signal });
|
|
86
|
+
if (!response.ok) {
|
|
87
|
+
fetchErrors.push(`http_${response.status}@${candidateUrl}`);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const resolvedMime = String(response.headers.get('content-type') || fallbackMimeType || '')
|
|
91
|
+
.split(';')[0]
|
|
92
|
+
.trim()
|
|
93
|
+
.toLowerCase();
|
|
94
|
+
if (!resolvedMime.startsWith('image/')) {
|
|
95
|
+
fetchErrors.push(`invalid_type:${resolvedMime || 'unknown'}@${candidateUrl}`);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const contentLength = Number.parseInt(response.headers.get('content-length') || '', 10);
|
|
99
|
+
if (Number.isFinite(contentLength) && contentLength > MAX_ATTACHMENT_BYTES) {
|
|
100
|
+
fetchErrors.push(`too_large_header:${contentLength}@${candidateUrl}`);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
104
|
+
if (buffer.length > MAX_ATTACHMENT_BYTES) {
|
|
105
|
+
fetchErrors.push(`too_large_body:${buffer.length}@${candidateUrl}`);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const unique = randomUUID().slice(0, 8);
|
|
109
|
+
const datePrefix = new Date().toISOString().slice(0, 10);
|
|
110
|
+
const fileName = `${Date.now()}-${messageId}-${String(order).padStart(3, '0')}-${unique}-${sanitizeAttachmentFilename(attachmentName)}`;
|
|
111
|
+
const hostPath = path.join(DISCORD_MEDIA_CACHE_DIR, datePrefix, fileName);
|
|
112
|
+
await fs.promises.mkdir(path.dirname(hostPath), { recursive: true });
|
|
113
|
+
await fs.promises.writeFile(hostPath, buffer);
|
|
114
|
+
const containerPath = normalizeAttachmentPathForContainer(hostPath);
|
|
115
|
+
if (!containerPath) {
|
|
116
|
+
fetchErrors.push(`cache_path_error:${hostPath}`);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
path: containerPath,
|
|
121
|
+
sourceUrl: candidateUrl,
|
|
122
|
+
mimeType: resolvedMime,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
127
|
+
fetchErrors.push(`fetch_error:${detail}@${candidateUrl}`);
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
clearTimeout(timer);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const fallbackUrl = sourceCandidates.find((url) => isAllowedDiscordAttachmentUrl(url))
|
|
134
|
+
|| sourceCandidates[0]
|
|
135
|
+
|| '';
|
|
136
|
+
return {
|
|
137
|
+
path: null,
|
|
138
|
+
sourceUrl: fallbackUrl,
|
|
139
|
+
mimeType: fallbackMimeType,
|
|
140
|
+
cacheError: fetchErrors.length > 0 ? fetchErrors.join(' | ') : 'cache_failed',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
export async function buildAttachmentContext(messages) {
|
|
144
|
+
const lines = [];
|
|
145
|
+
const media = [];
|
|
146
|
+
let remainingChars = MAX_ATTACHMENT_CONTEXT_CHARS;
|
|
147
|
+
let mediaOrder = 0;
|
|
148
|
+
for (const msg of messages) {
|
|
149
|
+
if (!msg.attachments || msg.attachments.size === 0)
|
|
150
|
+
continue;
|
|
151
|
+
for (const attachment of msg.attachments.values()) {
|
|
152
|
+
const name = attachment.name || 'unnamed';
|
|
153
|
+
const size = attachment.size || 0;
|
|
154
|
+
const contentType = (attachment.contentType || '').toLowerCase();
|
|
155
|
+
if (size > MAX_ATTACHMENT_BYTES) {
|
|
156
|
+
lines.push(`- ${name}: skipped (size ${size} bytes exceeds 10MB limit)`);
|
|
157
|
+
if (looksLikeImageAttachment(name, contentType)) {
|
|
158
|
+
mediaOrder += 1;
|
|
159
|
+
media.push({
|
|
160
|
+
path: null,
|
|
161
|
+
url: attachment.url,
|
|
162
|
+
originalUrl: attachment.url,
|
|
163
|
+
mimeType: contentType || null,
|
|
164
|
+
sizeBytes: size,
|
|
165
|
+
filename: name,
|
|
166
|
+
});
|
|
167
|
+
logger.warn({
|
|
168
|
+
messageId: msg.id,
|
|
169
|
+
attachmentId: attachment.id,
|
|
170
|
+
name,
|
|
171
|
+
sizeBytes: size,
|
|
172
|
+
}, 'Discord image attachment skipped by size limit');
|
|
173
|
+
}
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (looksLikeImageAttachment(name, contentType)) {
|
|
177
|
+
mediaOrder += 1;
|
|
178
|
+
const cached = await cacheDiscordImageAttachment({
|
|
179
|
+
attachment,
|
|
180
|
+
messageId: msg.id,
|
|
181
|
+
order: mediaOrder,
|
|
182
|
+
fallbackMimeType: contentType || null,
|
|
183
|
+
});
|
|
184
|
+
media.push({
|
|
185
|
+
path: cached.path,
|
|
186
|
+
url: cached.sourceUrl || attachment.url,
|
|
187
|
+
originalUrl: attachment.url,
|
|
188
|
+
mimeType: cached.mimeType || contentType || null,
|
|
189
|
+
sizeBytes: size,
|
|
190
|
+
filename: name,
|
|
191
|
+
});
|
|
192
|
+
if (cached.path) {
|
|
193
|
+
lines.push(`- ${name}: image attachment cached (${size} bytes, ${cached.mimeType || contentType || 'unknown type'})`);
|
|
194
|
+
logger.info({
|
|
195
|
+
messageId: msg.id,
|
|
196
|
+
attachmentId: attachment.id,
|
|
197
|
+
name,
|
|
198
|
+
sizeBytes: size,
|
|
199
|
+
mimeType: cached.mimeType || contentType || null,
|
|
200
|
+
localPath: cached.path,
|
|
201
|
+
}, 'Discord image attachment cached successfully');
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
lines.push(`- ${name}: image attachment (cache failed, using URL fallback)`);
|
|
205
|
+
logger.warn({
|
|
206
|
+
messageId: msg.id,
|
|
207
|
+
attachmentId: attachment.id,
|
|
208
|
+
name,
|
|
209
|
+
sizeBytes: size,
|
|
210
|
+
mimeType: contentType || null,
|
|
211
|
+
cacheError: cached.cacheError || 'unknown',
|
|
212
|
+
}, 'Discord image attachment cache failed; using CDN fallback');
|
|
213
|
+
}
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
if (looksLikeTextAttachment(name, contentType)) {
|
|
217
|
+
const maxChars = Math.min(MAX_SINGLE_ATTACHMENT_CHARS, Math.max(500, remainingChars));
|
|
218
|
+
const text = await fetchAttachmentText(attachment.url, maxChars);
|
|
219
|
+
if (!text) {
|
|
220
|
+
lines.push(`- ${name}: text attachment (failed to read content)`);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
const block = `- ${name} (text attachment):\n\`\`\`\n${text}\n\`\`\``;
|
|
224
|
+
remainingChars -= block.length;
|
|
225
|
+
lines.push(block);
|
|
226
|
+
if (remainingChars <= 0) {
|
|
227
|
+
lines.push('- Additional attachment content omitted (context budget reached).');
|
|
228
|
+
return {
|
|
229
|
+
context: `[Attachments]\n${lines.join('\n')}\n\n`,
|
|
230
|
+
media,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
lines.push(`- ${name}: attachment (${size} bytes, ${contentType || 'unknown type'})`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (lines.length === 0)
|
|
239
|
+
return { context: '', media };
|
|
240
|
+
return {
|
|
241
|
+
context: `[Attachments]\n${lines.join('\n')}\n\n`,
|
|
242
|
+
media,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=attachments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../../src/channels/discord/attachments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AttachmentBuilder, type ChatInputCommandInteraction, type Message as DiscordMessage } from 'discord.js';
|
|
2
|
+
import { type MentionLookup } from './mentions.js';
|
|
3
|
+
export type DiscordRetryFn = <T>(label: string, fn: () => Promise<T>) => Promise<T>;
|
|
4
|
+
export declare function buildResponseText(text: string, toolsUsed?: string[]): string;
|
|
5
|
+
export declare function formatInfo(title: string, body: string): string;
|
|
6
|
+
export declare function formatError(title: string, detail: string): string;
|
|
7
|
+
export declare function prepareChunkedPayloads(text: string, files?: AttachmentBuilder[], mentionLookup?: MentionLookup): {
|
|
8
|
+
content: string;
|
|
9
|
+
files?: AttachmentBuilder[];
|
|
10
|
+
}[];
|
|
11
|
+
export declare function sendChunkedReply(params: {
|
|
12
|
+
msg: DiscordMessage;
|
|
13
|
+
text: string;
|
|
14
|
+
withRetry: DiscordRetryFn;
|
|
15
|
+
files?: AttachmentBuilder[];
|
|
16
|
+
mentionLookup?: MentionLookup;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
export declare function sendChunkedDirectReply(params: {
|
|
19
|
+
msg: DiscordMessage;
|
|
20
|
+
text: string;
|
|
21
|
+
withRetry: DiscordRetryFn;
|
|
22
|
+
files?: AttachmentBuilder[];
|
|
23
|
+
mentionLookup?: MentionLookup;
|
|
24
|
+
}): Promise<void>;
|
|
25
|
+
export declare function sendChunkedInteractionReply(params: {
|
|
26
|
+
interaction: ChatInputCommandInteraction;
|
|
27
|
+
text: string;
|
|
28
|
+
withRetry: DiscordRetryFn;
|
|
29
|
+
files?: AttachmentBuilder[];
|
|
30
|
+
}): Promise<void>;
|
|
31
|
+
//# sourceMappingURL=delivery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../../src/channels/discord/delivery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,2BAA2B,EAAE,KAAK,OAAO,IAAI,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjH,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAExE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAEpF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAO5E;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,iBAAiB,EAAE,EAC3B,aAAa,CAAC,EAAE,aAAa,GAC5B;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAA;CAAE,EAAE,CAQpD;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,GAAG,EAAE,cAAc,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC5B,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B,GAAG,OAAO,CAAC,IAAI,CAAC,CAehB;AAED,wBAAsB,sBAAsB,CAAC,MAAM,EAAE;IACnD,GAAG,EAAE,cAAc,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC5B,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB;AAED,wBAAsB,2BAA2B,CAAC,MAAM,EAAE;IACxD,WAAW,EAAE,2BAA2B,CAAC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAC7B,GAAG,OAAO,CAAC,IAAI,CAAC,CAchB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { chunkMessage } from '../../chunk.js';
|
|
2
|
+
import { rewriteUserMentions } from './mentions.js';
|
|
3
|
+
export function buildResponseText(text, toolsUsed) {
|
|
4
|
+
let body = text;
|
|
5
|
+
if (toolsUsed && toolsUsed.length > 0) {
|
|
6
|
+
const toolsLine = `\n*Tools: ${toolsUsed.join(', ')}*`;
|
|
7
|
+
body = `${text}${toolsLine}`;
|
|
8
|
+
}
|
|
9
|
+
return body;
|
|
10
|
+
}
|
|
11
|
+
export function formatInfo(title, body) {
|
|
12
|
+
return `**${title}**\n${body}`;
|
|
13
|
+
}
|
|
14
|
+
export function formatError(title, detail) {
|
|
15
|
+
return `**${title}:** ${detail}`;
|
|
16
|
+
}
|
|
17
|
+
export function prepareChunkedPayloads(text, files, mentionLookup) {
|
|
18
|
+
const prepared = mentionLookup ? rewriteUserMentions(text, mentionLookup) : text;
|
|
19
|
+
const chunks = chunkMessage(prepared, { maxChars: 1_900, maxLines: 20 });
|
|
20
|
+
const safeChunks = chunks.length > 0 ? chunks : ['(no content)'];
|
|
21
|
+
return safeChunks.map((content, i) => ({
|
|
22
|
+
content,
|
|
23
|
+
...(i === safeChunks.length - 1 && files && files.length > 0 ? { files } : {}),
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
export async function sendChunkedReply(params) {
|
|
27
|
+
const payloads = prepareChunkedPayloads(params.text, params.files, params.mentionLookup);
|
|
28
|
+
for (let i = 0; i < payloads.length; i += 1) {
|
|
29
|
+
if (i === 0) {
|
|
30
|
+
await params.withRetry('reply', () => params.msg.reply(payloads[i]));
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
await params.withRetry('send', () => params.msg.channel.send(payloads[i]));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export async function sendChunkedDirectReply(params) {
|
|
38
|
+
const payloads = prepareChunkedPayloads(params.text, params.files, params.mentionLookup);
|
|
39
|
+
const dm = await params.withRetry('dm-open', () => params.msg.author.createDM());
|
|
40
|
+
for (const payload of payloads) {
|
|
41
|
+
await params.withRetry('dm-send', () => dm.send(payload));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export async function sendChunkedInteractionReply(params) {
|
|
45
|
+
const payloads = prepareChunkedPayloads(params.text, params.files);
|
|
46
|
+
for (let i = 0; i < payloads.length; i += 1) {
|
|
47
|
+
const payload = { ...payloads[i], ephemeral: true };
|
|
48
|
+
if (i === 0) {
|
|
49
|
+
if (params.interaction.replied || params.interaction.deferred) {
|
|
50
|
+
await params.withRetry('interaction-followup', () => params.interaction.followUp(payload));
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
await params.withRetry('interaction-reply', () => params.interaction.reply(payload));
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
await params.withRetry('interaction-followup', () => params.interaction.followUp(payload));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=delivery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delivery.js","sourceRoot":"","sources":["../../../src/channels/discord/delivery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface ParsedCommand {
|
|
2
|
+
isCommand: boolean;
|
|
3
|
+
command: string;
|
|
4
|
+
args: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare function stripBotMentions(text: string, botMentionRegex: RegExp | null): string;
|
|
7
|
+
export declare function cleanIncomingContent(content: string, botMentionRegex: RegExp | null, prefix: string): string;
|
|
8
|
+
export declare function hasPrefixInvocation(content: string, botMentionRegex: RegExp | null, prefix: string): boolean;
|
|
9
|
+
export declare function buildSessionIdFromContext(guildId: string | null, channelId: string, userId: string): string;
|
|
10
|
+
export declare function parseCommand(content: string, botMentionRegex: RegExp | null, prefix: string): ParsedCommand;
|
|
11
|
+
export declare function isTrigger(params: {
|
|
12
|
+
content: string;
|
|
13
|
+
isDm: boolean;
|
|
14
|
+
commandsOnly: boolean;
|
|
15
|
+
respondToAllMessages: boolean;
|
|
16
|
+
prefix: string;
|
|
17
|
+
botMentionRegex: RegExp | null;
|
|
18
|
+
hasBotMention: boolean;
|
|
19
|
+
}): boolean;
|
|
20
|
+
//# sourceMappingURL=inbound.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../../../src/channels/discord/inbound.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAGrF;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GAAG,IAAI,EAC9B,MAAM,EAAE,MAAM,GACb,MAAM,CAMR;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GAAG,IAAI,EAC9B,MAAM,EAAE,MAAM,GACb,OAAO,CAGT;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3G;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GAAG,IAAI,EAC9B,MAAM,EAAE,MAAM,GACb,aAAa,CAaf;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,OAAO,CAAC;IACtB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,OAAO,CAAC;CACxB,GAAG,OAAO,CAQV"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function stripBotMentions(text, botMentionRegex) {
|
|
2
|
+
if (!botMentionRegex)
|
|
3
|
+
return text;
|
|
4
|
+
return text.replace(botMentionRegex, '').trim();
|
|
5
|
+
}
|
|
6
|
+
export function cleanIncomingContent(content, botMentionRegex, prefix) {
|
|
7
|
+
let text = stripBotMentions(content, botMentionRegex);
|
|
8
|
+
if (text.startsWith(prefix)) {
|
|
9
|
+
text = text.slice(prefix.length).trim();
|
|
10
|
+
}
|
|
11
|
+
return text;
|
|
12
|
+
}
|
|
13
|
+
export function hasPrefixInvocation(content, botMentionRegex, prefix) {
|
|
14
|
+
const text = stripBotMentions(content, botMentionRegex);
|
|
15
|
+
return text.startsWith(prefix);
|
|
16
|
+
}
|
|
17
|
+
export function buildSessionIdFromContext(guildId, channelId, userId) {
|
|
18
|
+
return guildId ? `${guildId}:${channelId}` : `dm:${userId}`;
|
|
19
|
+
}
|
|
20
|
+
export function parseCommand(content, botMentionRegex, prefix) {
|
|
21
|
+
let text = stripBotMentions(content, botMentionRegex);
|
|
22
|
+
if (text.startsWith(prefix)) {
|
|
23
|
+
text = text.slice(prefix.length).trim();
|
|
24
|
+
}
|
|
25
|
+
const parts = text.split(/\s+/);
|
|
26
|
+
const subcommands = ['bot', 'rag', 'model', 'sessions', 'audit', 'schedule', 'clear', 'help'];
|
|
27
|
+
if (parts.length > 0 && subcommands.includes(parts[0].toLowerCase())) {
|
|
28
|
+
return { isCommand: true, command: parts[0].toLowerCase(), args: parts.slice(1) };
|
|
29
|
+
}
|
|
30
|
+
return { isCommand: false, command: '', args: [] };
|
|
31
|
+
}
|
|
32
|
+
export function isTrigger(params) {
|
|
33
|
+
if (params.commandsOnly) {
|
|
34
|
+
return hasPrefixInvocation(params.content, params.botMentionRegex, params.prefix);
|
|
35
|
+
}
|
|
36
|
+
if (params.isDm)
|
|
37
|
+
return true;
|
|
38
|
+
if (params.respondToAllMessages)
|
|
39
|
+
return true;
|
|
40
|
+
if (params.hasBotMention)
|
|
41
|
+
return true;
|
|
42
|
+
return params.content.startsWith(params.prefix);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=inbound.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound.js","sourceRoot":"","sources":["../../../src/channels/discord/inbound.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,eAA8B;IAC3E,IAAI,CAAC,eAAe;QAAE,OAAO,IAAI,CAAC;IAClC,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,OAAe,EACf,eAA8B,EAC9B,MAAc;IAEd,IAAI,IAAI,GAAG,gBAAgB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACtD,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAAe,EACf,eAA8B,EAC9B,MAAc;IAEd,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACxD,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,OAAsB,EAAE,SAAiB,EAAE,MAAc;IACjG,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,OAAe,EACf,eAA8B,EAC9B,MAAc;IAEd,IAAI,IAAI,GAAG,gBAAgB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACtD,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9F,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QACrE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACpF,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAQzB;IACC,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,OAAO,mBAAmB,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACpF,CAAC;IACD,IAAI,MAAM,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAC7B,IAAI,MAAM,CAAC,oBAAoB;QAAE,OAAO,IAAI,CAAC;IAC7C,IAAI,MAAM,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Message as DiscordMessage } from 'discord.js';
|
|
2
|
+
export interface MentionLookup {
|
|
3
|
+
byAlias: Map<string, Set<string>>;
|
|
4
|
+
}
|
|
5
|
+
export interface MentionAliasHint {
|
|
6
|
+
alias: string;
|
|
7
|
+
userId: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function normalizeMentionAlias(raw: string | null | undefined): string;
|
|
10
|
+
export declare function addMentionAlias(lookup: MentionLookup, rawAlias: string | null | undefined, userId: string): void;
|
|
11
|
+
export declare function extractMentionAliasHints(text: string): MentionAliasHint[];
|
|
12
|
+
export declare function rewriteUserMentions(text: string, lookup: MentionLookup): string;
|
|
13
|
+
export declare function rewriteUserMentionsForMessage(text: string, msg: DiscordMessage, lookup: MentionLookup): Promise<string>;
|
|
14
|
+
//# sourceMappingURL=mentions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mentions.d.ts","sourceRoot":"","sources":["../../../src/channels/discord/mentions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,YAAY,CAAC;AAI5D,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAQ5E;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAShH;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAyBzE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,CAY/E;AA8CD,wBAAsB,6BAA6B,CACjD,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,CAAC,CAMjB"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { logger } from '../../logger.js';
|
|
2
|
+
export function normalizeMentionAlias(raw) {
|
|
3
|
+
if (!raw)
|
|
4
|
+
return '';
|
|
5
|
+
const trimmed = raw.trim().replace(/^@+/, '');
|
|
6
|
+
if (!trimmed)
|
|
7
|
+
return '';
|
|
8
|
+
const lowered = trimmed.toLowerCase();
|
|
9
|
+
if (lowered === 'everyone' || lowered === 'here')
|
|
10
|
+
return '';
|
|
11
|
+
if (!/^[\p{L}\p{N}._-]{2,32}$/u.test(trimmed))
|
|
12
|
+
return '';
|
|
13
|
+
return lowered;
|
|
14
|
+
}
|
|
15
|
+
export function addMentionAlias(lookup, rawAlias, userId) {
|
|
16
|
+
const alias = normalizeMentionAlias(rawAlias);
|
|
17
|
+
if (!alias)
|
|
18
|
+
return;
|
|
19
|
+
let ids = lookup.byAlias.get(alias);
|
|
20
|
+
if (!ids) {
|
|
21
|
+
ids = new Set();
|
|
22
|
+
lookup.byAlias.set(alias, ids);
|
|
23
|
+
}
|
|
24
|
+
ids.add(userId);
|
|
25
|
+
}
|
|
26
|
+
export function extractMentionAliasHints(text) {
|
|
27
|
+
if (!text)
|
|
28
|
+
return [];
|
|
29
|
+
const hints = new Map();
|
|
30
|
+
const collect = (rawAlias, rawUserId) => {
|
|
31
|
+
const userId = (rawUserId || '').trim();
|
|
32
|
+
if (!/^\d{16,22}$/.test(userId))
|
|
33
|
+
return;
|
|
34
|
+
const alias = normalizeMentionAlias(rawAlias);
|
|
35
|
+
if (!alias)
|
|
36
|
+
return;
|
|
37
|
+
const key = `${alias}:${userId}`;
|
|
38
|
+
if (!hints.has(key))
|
|
39
|
+
hints.set(key, { alias, userId });
|
|
40
|
+
};
|
|
41
|
+
const aliasToId = /(^|[\s,;:.!?])@?([\p{L}\p{N}._-]{2,32})\s*(?:ist|is|=|->|=>|means|heißt)\s*(?:<@!?(\d{16,22})>|(\d{16,22}))/giu;
|
|
42
|
+
let match;
|
|
43
|
+
while ((match = aliasToId.exec(text)) !== null) {
|
|
44
|
+
collect(match[2], match[3] || match[4]);
|
|
45
|
+
}
|
|
46
|
+
const idToAlias = /(?:<@!?(\d{16,22})>|(\d{16,22}))\s*(?:ist|is|=|->|=>|means|heißt)\s*@?([\p{L}\p{N}._-]{2,32})/giu;
|
|
47
|
+
while ((match = idToAlias.exec(text)) !== null) {
|
|
48
|
+
collect(match[3], match[1] || match[2]);
|
|
49
|
+
}
|
|
50
|
+
return Array.from(hints.values());
|
|
51
|
+
}
|
|
52
|
+
export function rewriteUserMentions(text, lookup) {
|
|
53
|
+
if (!text)
|
|
54
|
+
return text;
|
|
55
|
+
if (!lookup.byAlias.size)
|
|
56
|
+
return text;
|
|
57
|
+
return text.replace(/(^|[\s([{:>])@([\p{L}\p{N}._-]{2,32})\b/gu, (full, prefix, rawAlias) => {
|
|
58
|
+
const alias = normalizeMentionAlias(rawAlias);
|
|
59
|
+
if (!alias)
|
|
60
|
+
return full;
|
|
61
|
+
const ids = lookup.byAlias.get(alias);
|
|
62
|
+
if (!ids || ids.size !== 1)
|
|
63
|
+
return full;
|
|
64
|
+
const [id] = Array.from(ids);
|
|
65
|
+
if (!id)
|
|
66
|
+
return full;
|
|
67
|
+
return `${prefix}<@${id}>`;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function extractMentionAliases(text) {
|
|
71
|
+
if (!text)
|
|
72
|
+
return [];
|
|
73
|
+
const aliases = new Set();
|
|
74
|
+
const re = /(^|[\s([{:>])@([\p{L}\p{N}._-]{2,32})\b/gu;
|
|
75
|
+
let match;
|
|
76
|
+
while ((match = re.exec(text)) !== null) {
|
|
77
|
+
const alias = normalizeMentionAlias(match[2]);
|
|
78
|
+
if (!alias)
|
|
79
|
+
continue;
|
|
80
|
+
aliases.add(alias);
|
|
81
|
+
if (aliases.size >= 8)
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
return Array.from(aliases);
|
|
85
|
+
}
|
|
86
|
+
async function enrichMentionLookupFromGuild(msg, lookup, aliases) {
|
|
87
|
+
if (!msg.guild || aliases.length === 0)
|
|
88
|
+
return;
|
|
89
|
+
for (const alias of aliases) {
|
|
90
|
+
if (lookup.byAlias.has(alias))
|
|
91
|
+
continue;
|
|
92
|
+
try {
|
|
93
|
+
const members = await msg.guild.members.search({ query: alias, limit: 5 });
|
|
94
|
+
const exactMatches = Array.from(members.values()).filter((member) => {
|
|
95
|
+
const username = normalizeMentionAlias(member.user?.username || '');
|
|
96
|
+
const displayName = normalizeMentionAlias(member.displayName || '');
|
|
97
|
+
return username === alias || displayName === alias;
|
|
98
|
+
});
|
|
99
|
+
if (exactMatches.length !== 1)
|
|
100
|
+
continue;
|
|
101
|
+
const match = exactMatches[0];
|
|
102
|
+
addMentionAlias(lookup, alias, match.id);
|
|
103
|
+
addMentionAlias(lookup, match.user?.username || '', match.id);
|
|
104
|
+
addMentionAlias(lookup, match.displayName || '', match.id);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
logger.debug({ error, guildId: msg.guild.id, alias }, 'Failed to resolve guild member alias for mention rewrite');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export async function rewriteUserMentionsForMessage(text, msg, lookup) {
|
|
112
|
+
const aliases = extractMentionAliases(text);
|
|
113
|
+
if (aliases.length > 0) {
|
|
114
|
+
await enrichMentionLookupFromGuild(msg, lookup, aliases);
|
|
115
|
+
}
|
|
116
|
+
return rewriteUserMentions(text, lookup);
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=mentions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mentions.js","sourceRoot":"","sources":["../../../src/channels/discord/mentions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { AttachmentBuilder, Client, type Message as DiscordMessage } from 'discord.js';
|
|
2
|
+
import { type MentionLookup } from './mentions.js';
|
|
3
|
+
import { type DiscordToolActionRequest } from './tool-actions.js';
|
|
4
|
+
import { DiscordStreamManager } from './stream.js';
|
|
5
|
+
import type { MediaContextItem } from '../../types.js';
|
|
6
|
+
export type ReplyFn = (content: string, files?: AttachmentBuilder[]) => Promise<void>;
|
|
7
|
+
export interface MessageRunContext {
|
|
8
|
+
sourceMessage: DiscordMessage;
|
|
9
|
+
batchedMessages: DiscordMessage[];
|
|
10
|
+
abortSignal: AbortSignal;
|
|
11
|
+
stream: DiscordStreamManager;
|
|
12
|
+
mentionLookup: MentionLookup;
|
|
13
|
+
}
|
|
14
|
+
export type MessageHandler = (sessionId: string, guildId: string | null, channelId: string, userId: string, username: string, content: string, media: MediaContextItem[], reply: ReplyFn, context: MessageRunContext) => Promise<void>;
|
|
15
|
+
export type CommandHandler = (sessionId: string, guildId: string | null, channelId: string, args: string[], reply: ReplyFn) => Promise<void>;
|
|
16
|
+
export declare function runDiscordToolAction(request: DiscordToolActionRequest): Promise<Record<string, unknown>>;
|
|
17
|
+
export declare function initDiscord(onMessage: MessageHandler, onCommand: CommandHandler): Client;
|
|
18
|
+
/**
|
|
19
|
+
* Send a message to a channel by ID (used by scheduler).
|
|
20
|
+
*/
|
|
21
|
+
export declare function sendToChannel(channelId: string, text: string, files?: AttachmentBuilder[]): Promise<void>;
|
|
22
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/channels/discord/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,EACjB,MAAM,EAEN,KAAK,OAAO,IAAI,cAAc,EAE/B,MAAM,YAAY,CAAC;AAoBpB,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AAQvB,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,iBAAiB,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAiBtF,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,cAAc,CAAC;IAC9B,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,aAAa,EAAE,aAAa,CAAC;CAC9B;AAED,MAAM,MAAM,cAAc,GAAG,CAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,gBAAgB,EAAE,EACzB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,iBAAiB,KACvB,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,MAAM,MAAM,cAAc,GAAG,CAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,EAAE,OAAO,KACX,OAAO,CAAC,IAAI,CAAC,CAAC;AA+TnB,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAElC;AAoRD,wBAAgB,WAAW,CAAC,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,cAAc,GAAG,MAAM,CAmexF;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/G"}
|