@openclaw/discord 2026.7.2-beta.7 → 2026.8.1-beta.3
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/{account-inspect-SXiCBCgP.js → account-inspect-D5xmUpnj.js} +49 -43
- package/dist/account-inspect-api.js +1 -1
- package/dist/accounts-DNl-oCEw.js +371 -0
- package/dist/action-runtime-api.js +1 -1
- package/dist/{active-turn-thread-route-MlKWp8RD.js → active-turn-thread-route-fmHl1HNd.js} +9 -11
- package/dist/{activities-api-DTKsuDxf.js → activities-api-KCBAmWxD.js} +133 -175
- package/dist/activities-api.js +1 -1
- package/dist/{allow-list-DzKrtfah.js → allow-list-BDMimASD.js} +2 -3
- package/dist/{api-DnrK9gML.js → api-DNVbJyEy.js} +7 -2
- package/dist/api.js +18 -18
- package/dist/{approval-handler.runtime-HymvFTYn.js → approval-handler.runtime-B12RCYr8.js} +6 -6
- package/dist/{approval-message-safety-DEyKVsAw.js → approval-message-safety-XGFPbDoI.js} +89 -3
- package/dist/{audit-CjsrabP8.js → audit-Yc7eZDd6.js} +5 -5
- package/dist/{channel-actions-uXFTJX3o.js → channel-actions-Dr2QI8Bf.js} +11 -7
- package/dist/{channel-actions.runtime-CIYU90sl.js → channel-actions.runtime-CODTvo7c.js} +99 -97
- package/dist/{channel-vKa-76xY.js → channel-cXYzGc4L.js} +102 -104
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-CmcwZ_qd.js → channel.setup-CSiwnMgs.js} +16 -54
- package/dist/{outbound-session-route-H-HoyH5U.js → components-ezGKo_Yh.js} +69 -142
- package/dist/{config-schema-WHRQcY19.js → config-schema-DC5kDtQ5.js} +42 -11
- package/dist/conversation-binding-route-D6rCQ5S0.js +43 -0
- package/dist/{directory-config-D_LojtCe.js → directory-config-XyCfoqLg.js} +2 -2
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-Bw5Ephzv.js → directory-live-Df0NbFJB.js} +7 -4
- package/dist/{doctor-Bc4S1qyd.js → doctor-DYY31GrO.js} +34 -13
- package/dist/{doctor-contract-CCFMIDk9.js → doctor-contract-DsWvKIXF.js} +2 -3
- package/dist/doctor-contract-api.js +147 -2
- package/dist/{handle-action.guild-admin-D6VRRW-C.js → handle-action.guild-admin-6Tvvinsa.js} +4 -7
- package/dist/{inbound-event-delivery-CEPlt2uz.js → inbound-event-delivery-De2qxTrP.js} +4 -25
- package/dist/index.js +5 -4
- package/dist/{message-handler-CeiSulIw.js → message-handler-B61q5MOF.js} +118 -33
- package/dist/{message-handler.preflight-DibgQFf2.js → message-handler.preflight-Bzg_Hawz.js} +75 -61
- package/dist/{message-handler.process-Dnc_oz9y.js → message-handler.process--4_712Ec.js} +236 -296
- package/dist/{message-utils-BgTwT_q7.js → message-utils-BXLLnFl6.js} +34 -35
- package/dist/{model-picker-preference-primitives-D25pnCOu.js → model-picker-preference-primitives-BHT1LkR_.js} +3 -3
- package/dist/{outbound-adapter-DtE-i2OJ.js → outbound-adapter-DxHTOqiN.js} +157 -68
- package/dist/{outbound-components-C7GVyfPh.js → outbound-components-B2PL0ooH.js} +3 -3
- package/dist/owner-access-Bg41VzAf.js +107 -0
- package/dist/{pluralkit-CD4B11JB.js → pluralkit-dUl4v1X3.js} +1 -1
- package/dist/{preflight-audio-BjnQZ5yS.js → preflight-audio-DrnqFA8U.js} +22 -28
- package/dist/{probe-BeWKhjqX.js → probe-BTdtVRwU.js} +37 -13
- package/dist/probe.runtime-Dq5-PRKT.js +2 -0
- package/dist/{provider-DfQJX3z5.js → provider-DlK_ynqt.js} +1131 -2021
- package/dist/{provider-session.runtime-Bo88k0pV.js → provider-session.runtime-CvvphHvs.js} +3 -3
- package/dist/provider.runtime-CzKGRiAF.js +2 -0
- package/dist/realtime-session.runtime-ysbMG8v7.js +1351 -0
- package/dist/{resolve-allowlist-common-DHERApxi.js → resolve-allowlist-common-DIVXbD1P.js} +3 -3
- package/dist/{resolve-channels-BjepAj8b.js → resolve-channels-CGeUoIqb.js} +4 -4
- package/dist/{resolve-users-Bc28htgt.js → resolve-users-BtKxLUZv.js} +3 -3
- package/dist/{chunk-DX4jpFQP.js → retry-DNsVTeTo.js} +308 -131
- package/dist/{runtime-BmW_j_hl.js → runtime-CQovMsH3.js} +12 -15
- package/dist/{runtime-_aRC6V2s.js → runtime-D71_VFLr.js} +49 -58
- package/dist/runtime-api.actions.js +2 -2
- package/dist/runtime-api.js +23 -23
- package/dist/runtime-api.lookup.js +5 -5
- package/dist/runtime-api.monitor-CzeTYF32.js +6 -0
- package/dist/runtime-api.monitor.js +6 -5
- package/dist/runtime-api.send.js +6 -6
- package/dist/runtime-api.threads.js +5 -6
- package/dist/sdk-runtime-37OU6_Yh.js +369 -0
- package/dist/{secret-config-contract-B1akrlyY.js → secret-config-contract-B3i6WxV5.js} +53 -25
- package/dist/secret-contract-api.js +1 -1
- package/dist/security-audit-contract-api.js +1 -1
- package/dist/{security-audit.runtime-CPN0xFYz.js → security-audit.runtime-BVKF9VtY.js} +1 -1
- package/dist/{send-CdkZ6zeW.js → send-rQIffSYu.js} +180 -91
- package/dist/{send.components-5uqwkjgE.js → send.components-ChK1wS7w.js} +32 -46
- package/dist/{send.outbound-D-80Ej-t.js → send.outbound-HIkgji_7.js} +57 -34
- package/dist/{send.reactions-CtlmGd_o.js → send.reactions-gmJ6yFPo.js} +14 -21
- package/dist/{send.receipt-CuwRrpFz.js → send.receipt-Cnhoautb.js} +29 -1
- package/dist/{send.shared-jpvAG_u6.js → send.shared-B3fpaLWJ.js} +112 -181
- package/dist/{sender-identity-mG_zsdox.js → sender-identity-BJtfyise.js} +1 -1
- package/dist/setup-entry.js +0 -5
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{shared-CXF1tup1.js → shared-CaAaoksy.js} +27 -23
- package/dist/subagent-hooks-CNT2ZJTJ.js +49 -0
- package/dist/subagent-hooks-api.js +2 -6
- package/dist/subagent-progress-FPLqBY1s.js +110 -0
- package/dist/{system-events-DdUqf91B.js → system-events-Nuwoq_au.js} +2 -2
- package/dist/{target-resolver-C3s_2m0t.js → target-resolver-DIXShHaZ.js} +3 -3
- package/dist/targets-B2pf49zc.js +3 -0
- package/dist/{thread-bindings-C-M-ly7P.js → thread-bindings-VlymUnbz.js} +29 -28
- package/dist/{thread-bindings.manager-DYvSlrva.js → thread-bindings.manager-CngsgErq.js} +258 -29
- package/dist/{thread-bindings.session-updates-DAIlp7Px.js → thread-bindings.session-updates-CJb-BpPL.js} +1 -1
- package/dist/{thread-bindings.state-Cgi5uRn-.js → thread-bindings.state-D8OMdk4O.js} +3 -16
- package/dist/threading-DU6pgeGm.js +456 -0
- package/dist/transcripts-source-DeIMNbRh.js +265 -0
- package/dist/transcripts-source-api.js +7 -2
- package/dist/{typing--Mzo2kM7.js → typing-oLiS5Z13.js} +1 -1
- package/dist/voice-runtime-CjNFaynA.js +2549 -0
- package/openclaw.plugin.json +215 -25
- package/package.json +15 -11
- package/skills/discord/SKILL.md +22 -115
- package/dist/accounts-DJTf1LtA.js +0 -219
- package/dist/channel-api-CAJ0wMoV.js +0 -21
- package/dist/legacy-state-migrations-api.js +0 -138
- package/dist/manager.runtime-Bjav3pfC.js +0 -3655
- package/dist/preflight-audio.runtime-CoCXMM8r.js +0 -7
- package/dist/probe.runtime-DqFGFMbZ.js +0 -2
- package/dist/provider.runtime-Cy7XZmyh.js +0 -2
- package/dist/runtime-api.monitor-CCRubd3-.js +0 -5
- package/dist/session-binding-contract-api.js +0 -2
- package/dist/subagent-hooks-Dxy7Fmnq.js +0 -120
- package/dist/subagent-progress-DI3sYLLo.js +0 -664
- package/dist/targets-Dv_RN7vT.js +0 -3
- package/dist/thread-bindings.discord-api-BoDNqamb.js +0 -246
- package/dist/transcripts-source-DIKGsTGT.js +0 -123
- package/node_modules/p-map/index.d.ts +0 -155
- package/node_modules/p-map/index.js +0 -285
- package/node_modules/p-map/license +0 -9
- package/node_modules/p-map/package.json +0 -57
- package/node_modules/p-map/readme.md +0 -190
- package/dist/{audit-core-xwjIczO0.js → audit-core-BCX8UeFH.js} +1 -1
- package/dist/{security-audit-jGnJF__m.js → security-audit-BfJhAXZp.js} +1 -1
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
import { St as editChannel, Tt as getChannelMessage, en as __exportAll, p as discord_exports, yt as createThread } from "./retry-DNsVTeTo.js";
|
|
2
|
+
import { d as resolveDiscordChannelParentSafe, l as resolveDiscordChannelNameSafe, s as resolveDiscordChannelIdSafe, u as resolveDiscordChannelParentIdSafe } from "./thread-bindings.manager-CngsgErq.js";
|
|
3
|
+
import { a as formatDiscordMediaText, f as resolveDiscordChannelInfo, n as resolveDiscordForwardedMessagesTextFromSnapshots, p as resolveDiscordMessageChannelId, t as resolveDiscordEmbedText } from "./message-utils-BXLLnFl6.js";
|
|
4
|
+
import { buildAgentSessionKey } from "openclaw/plugin-sdk/routing";
|
|
5
|
+
import { normalizeOptionalString, normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
|
+
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
7
|
+
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
8
|
+
import { createReplyReferencePlanner } from "openclaw/plugin-sdk/reply-reference";
|
|
9
|
+
import { resolveChannelModelOverride } from "openclaw/plugin-sdk/model-session-runtime";
|
|
10
|
+
import { generateConversationLabel } from "openclaw/plugin-sdk/reply-dispatch-runtime";
|
|
11
|
+
//#region extensions/discord/src/monitor/thread-title.ts
|
|
12
|
+
const DEFAULT_THREAD_TITLE_TIMEOUT_MS = 6e4;
|
|
13
|
+
const MAX_THREAD_TITLE_SOURCE_CHARS = 600;
|
|
14
|
+
const MAX_THREAD_TITLE_CHANNEL_NAME_CHARS = 120;
|
|
15
|
+
const MAX_THREAD_TITLE_CHANNEL_DESCRIPTION_CHARS = 320;
|
|
16
|
+
const DISCORD_THREAD_TITLE_SYSTEM_PROMPT = "Generate a concise Discord thread title (3-6 words) in sentence case: capitalize only the first word and words that are always capitalized. Return only the title. Use channel context when provided and avoid redundant channel-name words unless needed for clarity.";
|
|
17
|
+
async function generateThreadTitle(params) {
|
|
18
|
+
const sourceText = params.messageText.trim();
|
|
19
|
+
if (!sourceText) return null;
|
|
20
|
+
try {
|
|
21
|
+
const userMessage = buildThreadTitleCompletionUserMessage({
|
|
22
|
+
sourceText,
|
|
23
|
+
channelName: params.channelName,
|
|
24
|
+
channelDescription: params.channelDescription
|
|
25
|
+
});
|
|
26
|
+
const timeoutMs = resolveThreadTitleTimeoutMs(params.timeoutMs);
|
|
27
|
+
const generated = await generateConversationLabel({
|
|
28
|
+
cfg: params.cfg,
|
|
29
|
+
agentId: params.agentId,
|
|
30
|
+
userMessage,
|
|
31
|
+
prompt: DISCORD_THREAD_TITLE_SYSTEM_PROMPT,
|
|
32
|
+
...params.modelRef ? { modelRef: params.modelRef } : {},
|
|
33
|
+
timeoutMs,
|
|
34
|
+
maxLength: MAX_THREAD_TITLE_SOURCE_CHARS
|
|
35
|
+
});
|
|
36
|
+
return generated ? normalizeGeneratedThreadTitle(generated) : null;
|
|
37
|
+
} catch (err) {
|
|
38
|
+
logVerbose(`thread-title: title generation failed for agent ${params.agentId}: ${String(err)}`);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function buildThreadTitleCompletionUserMessage(params) {
|
|
43
|
+
const sourceText = truncateThreadTitleSourceText(params.sourceText);
|
|
44
|
+
const channelName = normalizeTitleContextField(params.channelName, MAX_THREAD_TITLE_CHANNEL_NAME_CHARS);
|
|
45
|
+
const channelDescription = normalizeTitleContextField(params.channelDescription, MAX_THREAD_TITLE_CHANNEL_DESCRIPTION_CHARS);
|
|
46
|
+
const messageLines = [];
|
|
47
|
+
if (channelName) messageLines.push(`Channel: ${channelName}`);
|
|
48
|
+
if (channelDescription) messageLines.push(`Channel description: ${channelDescription}`);
|
|
49
|
+
messageLines.push(`Message:\n${sourceText}`);
|
|
50
|
+
return messageLines.join("\n\n");
|
|
51
|
+
}
|
|
52
|
+
function truncateThreadTitleSourceText(sourceText) {
|
|
53
|
+
if (sourceText.length <= MAX_THREAD_TITLE_SOURCE_CHARS) return sourceText;
|
|
54
|
+
return `${truncateUtf16Safe(sourceText, MAX_THREAD_TITLE_SOURCE_CHARS)}...`;
|
|
55
|
+
}
|
|
56
|
+
function resolveThreadTitleTimeoutMs(timeoutMs) {
|
|
57
|
+
return Math.max(100, Math.floor(timeoutMs ?? DEFAULT_THREAD_TITLE_TIMEOUT_MS));
|
|
58
|
+
}
|
|
59
|
+
function normalizeGeneratedThreadTitle(raw) {
|
|
60
|
+
const lines = raw.replace(/\r/g, "").split("\n");
|
|
61
|
+
let firstLine = "";
|
|
62
|
+
for (const line of lines) {
|
|
63
|
+
const trimmed = line.trim();
|
|
64
|
+
if (!trimmed) continue;
|
|
65
|
+
if (!firstLine && trimmed.startsWith("```")) continue;
|
|
66
|
+
firstLine = trimmed;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
return stripThreadTitleWrappers(firstLine);
|
|
70
|
+
}
|
|
71
|
+
function stripThreadTitleWrappers(raw) {
|
|
72
|
+
let current = raw.trim();
|
|
73
|
+
let previous = "";
|
|
74
|
+
while (current && current !== previous) {
|
|
75
|
+
previous = current;
|
|
76
|
+
current = current.replace(/^["'`]+|["'`]+$/g, "").trim();
|
|
77
|
+
current = stripBalancedWrapper(current, "**");
|
|
78
|
+
current = stripBalancedWrapper(current, "__");
|
|
79
|
+
current = stripBalancedWrapper(current, "*");
|
|
80
|
+
current = stripBalancedWrapper(current, "_");
|
|
81
|
+
current = stripBalancedWrapper(current, "~~");
|
|
82
|
+
}
|
|
83
|
+
return current;
|
|
84
|
+
}
|
|
85
|
+
function stripBalancedWrapper(text, marker) {
|
|
86
|
+
if (text.length < marker.length * 2 + 1) return text;
|
|
87
|
+
if (!text.startsWith(marker) || !text.endsWith(marker)) return text;
|
|
88
|
+
const inner = text.slice(marker.length, text.length - marker.length);
|
|
89
|
+
if (!inner || inner.includes(marker)) return text;
|
|
90
|
+
return inner;
|
|
91
|
+
}
|
|
92
|
+
function normalizeTitleContextField(raw, maxChars) {
|
|
93
|
+
const value = raw?.trim();
|
|
94
|
+
if (!value) return;
|
|
95
|
+
const singleLine = value.replace(/\s+/g, " ");
|
|
96
|
+
if (singleLine.length <= maxChars) return singleLine;
|
|
97
|
+
return `${truncateUtf16Safe(singleLine, maxChars)}...`;
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region extensions/discord/src/monitor/threading.cache.ts
|
|
101
|
+
const DISCORD_THREAD_STARTER_CACHE_TTL_MS = 300 * 1e3;
|
|
102
|
+
const DISCORD_THREAD_STARTER_CACHE_MAX = 500;
|
|
103
|
+
const DISCORD_THREAD_STARTER_CACHE = /* @__PURE__ */ new Map();
|
|
104
|
+
function getCachedThreadStarter(key, now) {
|
|
105
|
+
const entry = DISCORD_THREAD_STARTER_CACHE.get(key);
|
|
106
|
+
if (!entry) return;
|
|
107
|
+
if (now - entry.updatedAt > DISCORD_THREAD_STARTER_CACHE_TTL_MS) {
|
|
108
|
+
DISCORD_THREAD_STARTER_CACHE.delete(key);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
DISCORD_THREAD_STARTER_CACHE.delete(key);
|
|
112
|
+
DISCORD_THREAD_STARTER_CACHE.set(key, {
|
|
113
|
+
...entry,
|
|
114
|
+
updatedAt: now
|
|
115
|
+
});
|
|
116
|
+
return entry.value;
|
|
117
|
+
}
|
|
118
|
+
function setCachedThreadStarter(key, value, now) {
|
|
119
|
+
DISCORD_THREAD_STARTER_CACHE.delete(key);
|
|
120
|
+
DISCORD_THREAD_STARTER_CACHE.set(key, {
|
|
121
|
+
value,
|
|
122
|
+
updatedAt: now
|
|
123
|
+
});
|
|
124
|
+
while (DISCORD_THREAD_STARTER_CACHE.size > DISCORD_THREAD_STARTER_CACHE_MAX) {
|
|
125
|
+
const iter = DISCORD_THREAD_STARTER_CACHE.keys().next();
|
|
126
|
+
if (iter.done) break;
|
|
127
|
+
DISCORD_THREAD_STARTER_CACHE.delete(iter.value);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region extensions/discord/src/monitor/threading.starter.ts
|
|
132
|
+
function isDiscordThreadType(type) {
|
|
133
|
+
return type === discord_exports.ChannelType.PublicThread || type === discord_exports.ChannelType.PrivateThread || type === discord_exports.ChannelType.AnnouncementThread;
|
|
134
|
+
}
|
|
135
|
+
function isDiscordForumParentType(parentType) {
|
|
136
|
+
return parentType === discord_exports.ChannelType.GuildForum || parentType === discord_exports.ChannelType.GuildMedia;
|
|
137
|
+
}
|
|
138
|
+
function resolveDiscordThreadChannel(params) {
|
|
139
|
+
if (!params.isGuildMessage) return null;
|
|
140
|
+
const { message, channelInfo } = params;
|
|
141
|
+
const channel = "channel" in message ? message.channel : void 0;
|
|
142
|
+
if (channel && typeof channel === "object" && "isThread" in channel && typeof channel.isThread === "function" && channel.isThread()) return channel;
|
|
143
|
+
if (!isDiscordThreadType(channelInfo?.type)) return null;
|
|
144
|
+
const messageChannelId = params.messageChannelId || resolveDiscordMessageChannelId({ message });
|
|
145
|
+
if (!messageChannelId) return null;
|
|
146
|
+
return {
|
|
147
|
+
id: messageChannelId,
|
|
148
|
+
name: channelInfo?.name ?? void 0,
|
|
149
|
+
parentId: channelInfo?.parentId ?? void 0,
|
|
150
|
+
parent: void 0,
|
|
151
|
+
ownerId: channelInfo?.ownerId ?? void 0
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
async function resolveDiscordThreadParentInfo(params) {
|
|
155
|
+
const { threadChannel, channelInfo, client } = params;
|
|
156
|
+
const parent = resolveDiscordChannelParentSafe(threadChannel);
|
|
157
|
+
let parentId = resolveDiscordChannelParentIdSafe(threadChannel) ?? resolveDiscordChannelIdSafe(parent) ?? channelInfo?.parentId ?? void 0;
|
|
158
|
+
if (!parentId && threadChannel.id) parentId = (await resolveDiscordChannelInfo(client, threadChannel.id))?.parentId ?? void 0;
|
|
159
|
+
if (!parentId) return {};
|
|
160
|
+
let parentName = resolveDiscordChannelNameSafe(parent);
|
|
161
|
+
const parentInfo = await resolveDiscordChannelInfo(client, parentId);
|
|
162
|
+
parentName = parentName ?? parentInfo?.name;
|
|
163
|
+
const parentType = parentInfo?.type;
|
|
164
|
+
return {
|
|
165
|
+
id: parentId,
|
|
166
|
+
name: parentName,
|
|
167
|
+
type: parentType
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
async function resolveDiscordThreadStarter(params) {
|
|
171
|
+
const cacheKey = params.channel.id;
|
|
172
|
+
const cached = getCachedThreadStarter(cacheKey, Date.now());
|
|
173
|
+
if (cached) return cached;
|
|
174
|
+
try {
|
|
175
|
+
const messageChannelId = resolveDiscordThreadStarterMessageChannelId(params);
|
|
176
|
+
if (!messageChannelId) return null;
|
|
177
|
+
const starter = await fetchDiscordThreadStarterMessage({
|
|
178
|
+
client: params.client,
|
|
179
|
+
messageChannelId,
|
|
180
|
+
threadId: params.channel.id
|
|
181
|
+
});
|
|
182
|
+
if (!starter) return null;
|
|
183
|
+
const payload = buildDiscordThreadStarterPayload({
|
|
184
|
+
starter,
|
|
185
|
+
resolveTimestampMs: params.resolveTimestampMs
|
|
186
|
+
});
|
|
187
|
+
if (!payload) return null;
|
|
188
|
+
setCachedThreadStarter(cacheKey, payload, Date.now());
|
|
189
|
+
return payload;
|
|
190
|
+
} catch {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function resolveDiscordThreadStarterMessageChannelId(params) {
|
|
195
|
+
return isDiscordForumParentType(params.parentType) ? params.channel.id : params.parentId;
|
|
196
|
+
}
|
|
197
|
+
async function fetchDiscordThreadStarterMessage(params) {
|
|
198
|
+
const starter = await getChannelMessage(params.client.rest, params.messageChannelId, params.threadId);
|
|
199
|
+
return starter ? starter : null;
|
|
200
|
+
}
|
|
201
|
+
function buildDiscordThreadStarterPayload(params) {
|
|
202
|
+
const text = resolveDiscordThreadStarterText(params.starter);
|
|
203
|
+
if (!text) return null;
|
|
204
|
+
return {
|
|
205
|
+
text,
|
|
206
|
+
...resolveDiscordThreadStarterIdentity(params.starter),
|
|
207
|
+
timestamp: params.resolveTimestampMs(params.starter.timestamp) ?? void 0
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function resolveDiscordThreadStarterText(starter) {
|
|
211
|
+
const content = normalizeOptionalString(starter.content) ?? "";
|
|
212
|
+
const embedText = resolveDiscordEmbedText(starter.embeds);
|
|
213
|
+
const forwardedText = resolveDiscordForwardedMessagesTextFromSnapshots(starter.message_snapshots);
|
|
214
|
+
return [content || embedText || forwardedText, formatDiscordMediaText({
|
|
215
|
+
attachments: starter.attachments ?? void 0,
|
|
216
|
+
stickers: starter.sticker_items ?? void 0
|
|
217
|
+
})].filter(Boolean).join("\n");
|
|
218
|
+
}
|
|
219
|
+
function resolveDiscordThreadStarterIdentity(starter) {
|
|
220
|
+
return {
|
|
221
|
+
author: resolveDiscordThreadStarterAuthor(starter),
|
|
222
|
+
authorId: starter.author?.id ?? void 0,
|
|
223
|
+
authorName: starter.author?.username ?? void 0,
|
|
224
|
+
authorTag: resolveDiscordThreadStarterAuthorTag(starter.author),
|
|
225
|
+
memberRoleIds: resolveDiscordThreadStarterRoleIds(starter.member)
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function resolveDiscordThreadStarterAuthor(starter) {
|
|
229
|
+
return starter.member?.nick ?? starter.member?.displayName ?? resolveDiscordThreadStarterAuthorTag(starter.author) ?? starter.author?.username ?? starter.author?.id ?? "Unknown";
|
|
230
|
+
}
|
|
231
|
+
function resolveDiscordThreadStarterAuthorTag(author) {
|
|
232
|
+
if (!author?.username || !author.discriminator) return;
|
|
233
|
+
if (author.discriminator !== "0") return `${author.username}#${author.discriminator}`;
|
|
234
|
+
return author.username;
|
|
235
|
+
}
|
|
236
|
+
function resolveDiscordThreadStarterRoleIds(member) {
|
|
237
|
+
return Array.isArray(member?.roles) ? member.roles : void 0;
|
|
238
|
+
}
|
|
239
|
+
function resolveDiscordReplyTarget(opts) {
|
|
240
|
+
if (opts.replyToMode === "off") return;
|
|
241
|
+
const replyToId = normalizeOptionalString(opts.replyToId);
|
|
242
|
+
if (!replyToId) return;
|
|
243
|
+
if (opts.replyToMode === "all") return replyToId;
|
|
244
|
+
return opts.hasReplied ? void 0 : replyToId;
|
|
245
|
+
}
|
|
246
|
+
function sanitizeDiscordThreadName(rawName, fallbackId) {
|
|
247
|
+
return truncateUtf16Safe(truncateUtf16Safe(rawName.replace(/<@!?\d+>/g, "").replace(/<@&\d+>/g, "").replace(/<#\d+>/g, "").replace(/\s+/g, " ").trim() || `Thread ${fallbackId}`, 80), 100) || `Thread ${fallbackId}`;
|
|
248
|
+
}
|
|
249
|
+
function resolveDiscordReplyDeliveryPlan(params) {
|
|
250
|
+
const originalReplyTarget = params.replyTarget;
|
|
251
|
+
let deliverTarget = originalReplyTarget;
|
|
252
|
+
let replyTarget = originalReplyTarget;
|
|
253
|
+
if (params.createdThreadId) {
|
|
254
|
+
deliverTarget = `channel:${params.createdThreadId}`;
|
|
255
|
+
replyTarget = deliverTarget;
|
|
256
|
+
}
|
|
257
|
+
const allowReference = deliverTarget === originalReplyTarget;
|
|
258
|
+
const replyReference = createReplyReferencePlanner({
|
|
259
|
+
replyToMode: allowReference ? params.replyToMode : "off",
|
|
260
|
+
existingId: params.threadChannel ? params.messageId : void 0,
|
|
261
|
+
startId: params.messageId,
|
|
262
|
+
allowReference
|
|
263
|
+
});
|
|
264
|
+
return {
|
|
265
|
+
deliverTarget,
|
|
266
|
+
replyTarget,
|
|
267
|
+
replyReference
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
//#endregion
|
|
271
|
+
//#region extensions/discord/src/monitor/threading.auto-thread.ts
|
|
272
|
+
function resolveTrimmedDiscordMessageChannelId(params) {
|
|
273
|
+
return (params.messageChannelId || resolveDiscordMessageChannelId({ message: params.message })).trim();
|
|
274
|
+
}
|
|
275
|
+
function resolveDiscordAutoThreadContext(params) {
|
|
276
|
+
const createdThreadId = normalizeOptionalStringifiedId(params.createdThreadId) ?? "";
|
|
277
|
+
if (!createdThreadId) return null;
|
|
278
|
+
const parentSessionKey = normalizeOptionalString(params.parentSessionKey) ?? "";
|
|
279
|
+
if (!parentSessionKey) return null;
|
|
280
|
+
const threadSessionKey = params.groupScope === "main" ? parentSessionKey : buildAgentSessionKey({
|
|
281
|
+
agentId: params.agentId,
|
|
282
|
+
channel: params.channel,
|
|
283
|
+
peer: {
|
|
284
|
+
kind: "channel",
|
|
285
|
+
id: createdThreadId
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
const inheritsDistinctParent = threadSessionKey !== parentSessionKey;
|
|
289
|
+
return {
|
|
290
|
+
createdThreadId,
|
|
291
|
+
From: `${params.channel}:channel:${createdThreadId}`,
|
|
292
|
+
To: `channel:${createdThreadId}`,
|
|
293
|
+
OriginatingTo: `channel:${createdThreadId}`,
|
|
294
|
+
SessionKey: threadSessionKey,
|
|
295
|
+
...inheritsDistinctParent ? { ModelParentSessionKey: parentSessionKey } : {},
|
|
296
|
+
...inheritsDistinctParent && params.parentInheritanceEnabled === true ? { ParentSessionKey: parentSessionKey } : {}
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
async function resolveDiscordAutoThreadReplyPlan(params) {
|
|
300
|
+
const messageChannelId = resolveTrimmedDiscordMessageChannelId(params);
|
|
301
|
+
const originalReplyTarget = `channel:${params.threadChannel?.id ?? (messageChannelId || "unknown")}`;
|
|
302
|
+
const createdThreadId = await maybeCreateDiscordAutoThread({
|
|
303
|
+
client: params.client,
|
|
304
|
+
message: params.message,
|
|
305
|
+
messageChannelId: messageChannelId || void 0,
|
|
306
|
+
channel: params.channel,
|
|
307
|
+
isGuildMessage: params.isGuildMessage,
|
|
308
|
+
channelConfig: params.channelConfig,
|
|
309
|
+
threadChannel: params.threadChannel,
|
|
310
|
+
channelType: params.channelType,
|
|
311
|
+
channelName: params.channelName,
|
|
312
|
+
channelDescription: params.channelDescription,
|
|
313
|
+
baseText: params.baseText,
|
|
314
|
+
combinedBody: params.combinedBody,
|
|
315
|
+
cfg: params.cfg,
|
|
316
|
+
agentId: params.agentId
|
|
317
|
+
});
|
|
318
|
+
const deliveryPlan = resolveDiscordReplyDeliveryPlan({
|
|
319
|
+
replyTarget: originalReplyTarget,
|
|
320
|
+
replyToMode: params.replyToMode,
|
|
321
|
+
messageId: params.message.id,
|
|
322
|
+
threadChannel: params.threadChannel,
|
|
323
|
+
createdThreadId
|
|
324
|
+
});
|
|
325
|
+
const autoThreadContext = params.isGuildMessage ? resolveDiscordAutoThreadContext({
|
|
326
|
+
agentId: params.agentId,
|
|
327
|
+
channel: params.channel,
|
|
328
|
+
parentSessionKey: params.parentSessionKey,
|
|
329
|
+
createdThreadId,
|
|
330
|
+
groupScope: params.groupScope,
|
|
331
|
+
parentInheritanceEnabled: params.threadParentInheritanceEnabled
|
|
332
|
+
}) : null;
|
|
333
|
+
return {
|
|
334
|
+
...deliveryPlan,
|
|
335
|
+
createdThreadId,
|
|
336
|
+
autoThreadContext
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
async function maybeCreateDiscordAutoThread(params) {
|
|
340
|
+
if (!params.isGuildMessage) return;
|
|
341
|
+
if (!params.channelConfig?.autoThread) return;
|
|
342
|
+
if (params.threadChannel) return;
|
|
343
|
+
if (params.channelType === discord_exports.ChannelType.GuildForum || params.channelType === discord_exports.ChannelType.GuildMedia || params.channelType === discord_exports.ChannelType.GuildVoice || params.channelType === discord_exports.ChannelType.GuildStageVoice) return;
|
|
344
|
+
const messageChannelId = resolveTrimmedDiscordMessageChannelId(params);
|
|
345
|
+
if (!messageChannelId) return;
|
|
346
|
+
try {
|
|
347
|
+
try {
|
|
348
|
+
const existingThreadId = (await getChannelMessage(params.client.rest, messageChannelId, params.message.id))?.thread?.id;
|
|
349
|
+
if (existingThreadId) {
|
|
350
|
+
logVerbose(`discord: autoThread reusing existing thread ${existingThreadId} on ${messageChannelId}/${params.message.id}`);
|
|
351
|
+
return existingThreadId;
|
|
352
|
+
}
|
|
353
|
+
} catch {}
|
|
354
|
+
if (params.message.author?.bot) {
|
|
355
|
+
logVerbose(`discord: autoThread skipped for bot-authored message ${messageChannelId}/${params.message.id}`);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
const rawThreadSource = params.baseText || params.combinedBody || "Thread";
|
|
359
|
+
const threadName = sanitizeDiscordThreadName(rawThreadSource, params.message.id);
|
|
360
|
+
const archiveDuration = params.channelConfig?.autoArchiveDuration ? Number(params.channelConfig.autoArchiveDuration) : 60;
|
|
361
|
+
const createdId = (await createThread(params.client.rest, messageChannelId, { body: {
|
|
362
|
+
name: threadName,
|
|
363
|
+
auto_archive_duration: archiveDuration
|
|
364
|
+
} }, params.message.id))?.id || "";
|
|
365
|
+
if (createdId && params.channelConfig?.autoThreadName === "generated" && params.cfg && params.agentId) {
|
|
366
|
+
const modelRef = resolveDiscordThreadTitleModelRef({
|
|
367
|
+
cfg: params.cfg,
|
|
368
|
+
channel: params.channel,
|
|
369
|
+
agentId: params.agentId,
|
|
370
|
+
threadId: createdId,
|
|
371
|
+
messageChannelId,
|
|
372
|
+
channelName: params.channelName
|
|
373
|
+
});
|
|
374
|
+
maybeRenameDiscordAutoThread({
|
|
375
|
+
client: params.client,
|
|
376
|
+
threadId: createdId,
|
|
377
|
+
currentName: threadName,
|
|
378
|
+
fallbackId: params.message.id,
|
|
379
|
+
sourceText: rawThreadSource,
|
|
380
|
+
modelRef,
|
|
381
|
+
channelName: params.channelName,
|
|
382
|
+
channelDescription: params.channelDescription,
|
|
383
|
+
cfg: params.cfg,
|
|
384
|
+
agentId: params.agentId
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
return createdId || void 0;
|
|
388
|
+
} catch (err) {
|
|
389
|
+
logVerbose(`discord: autoThread creation failed for ${messageChannelId}/${params.message.id}: ${String(err)}`);
|
|
390
|
+
try {
|
|
391
|
+
const existingThreadId = (await getChannelMessage(params.client.rest, messageChannelId, params.message.id))?.thread?.id || "";
|
|
392
|
+
if (existingThreadId) {
|
|
393
|
+
logVerbose(`discord: autoThread reusing existing thread ${existingThreadId} on ${messageChannelId}/${params.message.id}`);
|
|
394
|
+
return existingThreadId;
|
|
395
|
+
}
|
|
396
|
+
} catch {}
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
function resolveDiscordThreadTitleModelRef(params) {
|
|
401
|
+
const channel = params.channel?.trim();
|
|
402
|
+
if (!channel) return;
|
|
403
|
+
const parentSessionKey = buildAgentSessionKey({
|
|
404
|
+
agentId: params.agentId,
|
|
405
|
+
channel,
|
|
406
|
+
peer: {
|
|
407
|
+
kind: "channel",
|
|
408
|
+
id: params.messageChannelId
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
const channelLabel = params.channelName?.trim();
|
|
412
|
+
const groupChannel = channelLabel ? `#${channelLabel}` : void 0;
|
|
413
|
+
return resolveChannelModelOverride({
|
|
414
|
+
cfg: params.cfg,
|
|
415
|
+
channel,
|
|
416
|
+
groupId: params.threadId,
|
|
417
|
+
groupChatType: "channel",
|
|
418
|
+
groupChannel,
|
|
419
|
+
groupSubject: groupChannel,
|
|
420
|
+
parentSessionKey
|
|
421
|
+
})?.model;
|
|
422
|
+
}
|
|
423
|
+
async function maybeRenameDiscordAutoThread(params) {
|
|
424
|
+
try {
|
|
425
|
+
const fallbackName = sanitizeDiscordThreadName("", params.fallbackId);
|
|
426
|
+
const generated = await generateThreadTitle({
|
|
427
|
+
cfg: params.cfg,
|
|
428
|
+
agentId: params.agentId,
|
|
429
|
+
messageText: params.sourceText,
|
|
430
|
+
modelRef: params.modelRef,
|
|
431
|
+
channelName: params.channelName,
|
|
432
|
+
channelDescription: params.channelDescription
|
|
433
|
+
});
|
|
434
|
+
if (!generated) return;
|
|
435
|
+
const nextName = sanitizeDiscordThreadName(generated, params.fallbackId);
|
|
436
|
+
if (!nextName || nextName === params.currentName || nextName === fallbackName) return;
|
|
437
|
+
await editChannel(params.client.rest, params.threadId, { body: { name: nextName } });
|
|
438
|
+
} catch (err) {
|
|
439
|
+
logVerbose(`discord: autoThread rename failed for ${params.threadId}: ${String(err)}`);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
//#endregion
|
|
443
|
+
//#region extensions/discord/src/monitor/threading.ts
|
|
444
|
+
var threading_exports = /* @__PURE__ */ __exportAll({
|
|
445
|
+
maybeCreateDiscordAutoThread: () => maybeCreateDiscordAutoThread,
|
|
446
|
+
resolveDiscordAutoThreadContext: () => resolveDiscordAutoThreadContext,
|
|
447
|
+
resolveDiscordAutoThreadReplyPlan: () => resolveDiscordAutoThreadReplyPlan,
|
|
448
|
+
resolveDiscordReplyDeliveryPlan: () => resolveDiscordReplyDeliveryPlan,
|
|
449
|
+
resolveDiscordReplyTarget: () => resolveDiscordReplyTarget,
|
|
450
|
+
resolveDiscordThreadChannel: () => resolveDiscordThreadChannel,
|
|
451
|
+
resolveDiscordThreadParentInfo: () => resolveDiscordThreadParentInfo,
|
|
452
|
+
resolveDiscordThreadStarter: () => resolveDiscordThreadStarter,
|
|
453
|
+
sanitizeDiscordThreadName: () => sanitizeDiscordThreadName
|
|
454
|
+
});
|
|
455
|
+
//#endregion
|
|
456
|
+
export { resolveDiscordThreadStarter as a, resolveDiscordThreadParentInfo as i, resolveDiscordAutoThreadReplyPlan as n, sanitizeDiscordThreadName as o, resolveDiscordReplyTarget as r, threading_exports as t };
|