@gakr-gakr/discord 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/account-inspect-api.ts +6 -0
- package/action-runtime-api.ts +1 -0
- package/api.ts +130 -0
- package/autobot.plugin.json +15 -0
- package/channel-config-api.ts +1 -0
- package/channel-plugin-api.ts +3 -0
- package/config-api.ts +4 -0
- package/configured-state.ts +6 -0
- package/contract-api.ts +21 -0
- package/directory-contract-api.ts +4 -0
- package/doctor-contract-api.ts +1 -0
- package/index.ts +24 -0
- package/package.json +79 -0
- package/runtime-api.actions.ts +15 -0
- package/runtime-api.lookup.ts +22 -0
- package/runtime-api.monitor.ts +50 -0
- package/runtime-api.send.ts +79 -0
- package/runtime-api.threads.ts +31 -0
- package/runtime-api.ts +181 -0
- package/runtime-setter-api.ts +3 -0
- package/secret-contract-api.ts +4 -0
- package/security-audit-contract-api.ts +1 -0
- package/security-contract-api.ts +4 -0
- package/session-key-api.ts +1 -0
- package/setup-entry.ts +9 -0
- package/setup-plugin-api.ts +3 -0
- package/src/account-inspect.ts +131 -0
- package/src/accounts.ts +205 -0
- package/src/actions/handle-action.guild-admin.ts +421 -0
- package/src/actions/handle-action.ts +402 -0
- package/src/actions/runtime.guild.ts +446 -0
- package/src/actions/runtime.messaging.messages.ts +226 -0
- package/src/actions/runtime.messaging.reactions.ts +67 -0
- package/src/actions/runtime.messaging.runtime.ts +73 -0
- package/src/actions/runtime.messaging.send.ts +336 -0
- package/src/actions/runtime.messaging.shared.ts +97 -0
- package/src/actions/runtime.messaging.ts +37 -0
- package/src/actions/runtime.moderation-shared.ts +48 -0
- package/src/actions/runtime.moderation.ts +116 -0
- package/src/actions/runtime.presence.ts +117 -0
- package/src/actions/runtime.shared.ts +86 -0
- package/src/actions/runtime.ts +87 -0
- package/src/api.ts +219 -0
- package/src/approval-handler.runtime.ts +636 -0
- package/src/approval-native.ts +219 -0
- package/src/approval-runtime.ts +14 -0
- package/src/approval-shared.ts +56 -0
- package/src/audit-core.ts +178 -0
- package/src/audit.ts +32 -0
- package/src/channel-actions.runtime.ts +1 -0
- package/src/channel-actions.ts +254 -0
- package/src/channel-api.ts +29 -0
- package/src/channel.conversation.ts +159 -0
- package/src/channel.loaders.ts +50 -0
- package/src/channel.runtime.ts +1 -0
- package/src/channel.setup.ts +12 -0
- package/src/channel.ts +728 -0
- package/src/chunk.ts +321 -0
- package/src/client.ts +143 -0
- package/src/component-custom-id.ts +72 -0
- package/src/components-registry.ts +356 -0
- package/src/components.builders.ts +410 -0
- package/src/components.modal.ts +124 -0
- package/src/components.parse.ts +407 -0
- package/src/components.ts +54 -0
- package/src/components.types.ts +187 -0
- package/src/config-schema.ts +6 -0
- package/src/config-ui-hints.ts +354 -0
- package/src/conversation-identity.ts +58 -0
- package/src/delivery-retry.ts +56 -0
- package/src/directory-cache.ts +116 -0
- package/src/directory-config.ts +58 -0
- package/src/directory-live.ts +135 -0
- package/src/doctor-contract.ts +477 -0
- package/src/doctor-shared.ts +5 -0
- package/src/doctor.ts +340 -0
- package/src/draft-chunking.ts +43 -0
- package/src/draft-stream.ts +162 -0
- package/src/error-body.ts +38 -0
- package/src/exec-approvals.ts +110 -0
- package/src/gateway-logging.ts +67 -0
- package/src/group-policy.ts +113 -0
- package/src/guilds.ts +29 -0
- package/src/inbound-event-delivery.ts +135 -0
- package/src/interactive-dispatch.ts +104 -0
- package/src/internal/api.commands.ts +51 -0
- package/src/internal/api.guild.ts +164 -0
- package/src/internal/api.interactions.ts +53 -0
- package/src/internal/api.messages.ts +113 -0
- package/src/internal/api.reactions.ts +38 -0
- package/src/internal/api.ts +61 -0
- package/src/internal/api.users.ts +19 -0
- package/src/internal/api.webhooks.ts +13 -0
- package/src/internal/client.ts +310 -0
- package/src/internal/command-deploy.ts +352 -0
- package/src/internal/commands.ts +188 -0
- package/src/internal/components.base.ts +65 -0
- package/src/internal/components.message.ts +279 -0
- package/src/internal/components.modal.ts +95 -0
- package/src/internal/components.ts +31 -0
- package/src/internal/discord.ts +11 -0
- package/src/internal/embeds.ts +35 -0
- package/src/internal/entity-cache.ts +98 -0
- package/src/internal/event-queue.ts +185 -0
- package/src/internal/gateway-close-codes.ts +25 -0
- package/src/internal/gateway-dispatch.ts +96 -0
- package/src/internal/gateway-identify-limiter.ts +26 -0
- package/src/internal/gateway-lifecycle.ts +75 -0
- package/src/internal/gateway-rate-limit.ts +104 -0
- package/src/internal/gateway.ts +479 -0
- package/src/internal/interaction-dispatch.ts +162 -0
- package/src/internal/interaction-options.ts +98 -0
- package/src/internal/interaction-response.ts +53 -0
- package/src/internal/interactions.ts +378 -0
- package/src/internal/listeners.ts +91 -0
- package/src/internal/modal-fields.ts +95 -0
- package/src/internal/payload.ts +69 -0
- package/src/internal/rest-body.ts +115 -0
- package/src/internal/rest-errors.ts +88 -0
- package/src/internal/rest-routes.ts +50 -0
- package/src/internal/rest-scheduler.ts +557 -0
- package/src/internal/rest.ts +322 -0
- package/src/internal/schemas.ts +36 -0
- package/src/internal/structures.ts +280 -0
- package/src/internal/test-builders.test-support.ts +167 -0
- package/src/internal/voice.ts +49 -0
- package/src/media-detection.ts +28 -0
- package/src/mentions.ts +147 -0
- package/src/monitor/ack-reactions.ts +70 -0
- package/src/monitor/agent-components-auth.ts +7 -0
- package/src/monitor/agent-components-context.ts +154 -0
- package/src/monitor/agent-components-data.ts +224 -0
- package/src/monitor/agent-components-dm-auth.ts +177 -0
- package/src/monitor/agent-components-guild-auth.ts +322 -0
- package/src/monitor/agent-components-helpers.runtime.ts +3 -0
- package/src/monitor/agent-components-helpers.ts +34 -0
- package/src/monitor/agent-components-reply.ts +10 -0
- package/src/monitor/agent-components.deps.runtime.ts +2 -0
- package/src/monitor/agent-components.dispatch.ts +359 -0
- package/src/monitor/agent-components.handlers.ts +303 -0
- package/src/monitor/agent-components.modal.ts +160 -0
- package/src/monitor/agent-components.plugin-interactive.ts +187 -0
- package/src/monitor/agent-components.runtime.ts +14 -0
- package/src/monitor/agent-components.system-controls.ts +215 -0
- package/src/monitor/agent-components.ts +70 -0
- package/src/monitor/agent-components.types.ts +58 -0
- package/src/monitor/agent-components.wildcard-controls.ts +171 -0
- package/src/monitor/allow-list.ts +631 -0
- package/src/monitor/auto-presence.ts +356 -0
- package/src/monitor/channel-access.ts +102 -0
- package/src/monitor/commands.ts +9 -0
- package/src/monitor/dm-command-auth.ts +259 -0
- package/src/monitor/dm-command-decision.ts +49 -0
- package/src/monitor/exec-approvals.ts +161 -0
- package/src/monitor/format.ts +45 -0
- package/src/monitor/gateway-handle.ts +34 -0
- package/src/monitor/gateway-metadata.ts +298 -0
- package/src/monitor/gateway-plugin.ts +302 -0
- package/src/monitor/gateway-registry.ts +37 -0
- package/src/monitor/gateway-supervisor.ts +206 -0
- package/src/monitor/inbound-context.ts +95 -0
- package/src/monitor/inbound-dedupe.ts +79 -0
- package/src/monitor/inbound-job.ts +118 -0
- package/src/monitor/listeners.queue.ts +91 -0
- package/src/monitor/listeners.reactions.ts +594 -0
- package/src/monitor/listeners.ts +150 -0
- package/src/monitor/message-channel-info.ts +96 -0
- package/src/monitor/message-forwarded.ts +114 -0
- package/src/monitor/message-handler.batch-gate.ts +19 -0
- package/src/monitor/message-handler.context.ts +492 -0
- package/src/monitor/message-handler.dm-preflight.ts +119 -0
- package/src/monitor/message-handler.draft-preview.ts +436 -0
- package/src/monitor/message-handler.hydration.ts +198 -0
- package/src/monitor/message-handler.module-test-helpers.ts +31 -0
- package/src/monitor/message-handler.preflight-channel-access.ts +86 -0
- package/src/monitor/message-handler.preflight-channel-context.ts +58 -0
- package/src/monitor/message-handler.preflight-context.ts +54 -0
- package/src/monitor/message-handler.preflight-helpers.ts +164 -0
- package/src/monitor/message-handler.preflight-history.ts +23 -0
- package/src/monitor/message-handler.preflight-logging.ts +36 -0
- package/src/monitor/message-handler.preflight-pluralkit.ts +28 -0
- package/src/monitor/message-handler.preflight-runtime.ts +28 -0
- package/src/monitor/message-handler.preflight-thread.ts +49 -0
- package/src/monitor/message-handler.preflight.ts +822 -0
- package/src/monitor/message-handler.preflight.types.ts +115 -0
- package/src/monitor/message-handler.process.ts +1033 -0
- package/src/monitor/message-handler.routing-preflight.ts +112 -0
- package/src/monitor/message-handler.ts +309 -0
- package/src/monitor/message-media.ts +536 -0
- package/src/monitor/message-run-queue.ts +101 -0
- package/src/monitor/message-text.ts +171 -0
- package/src/monitor/message-utils.ts +34 -0
- package/src/monitor/model-picker-preferences.ts +184 -0
- package/src/monitor/model-picker.state.ts +364 -0
- package/src/monitor/model-picker.test-utils.ts +26 -0
- package/src/monitor/model-picker.ts +38 -0
- package/src/monitor/model-picker.view.ts +722 -0
- package/src/monitor/native-command-agent-reply.ts +125 -0
- package/src/monitor/native-command-arg-ui.ts +233 -0
- package/src/monitor/native-command-auth.ts +309 -0
- package/src/monitor/native-command-bypass.ts +13 -0
- package/src/monitor/native-command-context.ts +109 -0
- package/src/monitor/native-command-dispatch.ts +35 -0
- package/src/monitor/native-command-model-picker-apply.ts +209 -0
- package/src/monitor/native-command-model-picker-interaction.ts +516 -0
- package/src/monitor/native-command-model-picker-ui.ts +357 -0
- package/src/monitor/native-command-reply.ts +185 -0
- package/src/monitor/native-command-route.ts +91 -0
- package/src/monitor/native-command-status.ts +76 -0
- package/src/monitor/native-command-ui.ts +26 -0
- package/src/monitor/native-command-ui.types.ts +20 -0
- package/src/monitor/native-command.args.ts +45 -0
- package/src/monitor/native-command.options.ts +153 -0
- package/src/monitor/native-command.runtime.ts +51 -0
- package/src/monitor/native-command.ts +747 -0
- package/src/monitor/native-command.types.ts +9 -0
- package/src/monitor/native-interaction-channel-context.ts +50 -0
- package/src/monitor/preflight-audio.runtime.ts +9 -0
- package/src/monitor/preflight-audio.ts +130 -0
- package/src/monitor/presence-cache.ts +61 -0
- package/src/monitor/presence.ts +50 -0
- package/src/monitor/provider-session.runtime.ts +12 -0
- package/src/monitor/provider.acp.ts +89 -0
- package/src/monitor/provider.allowlist.ts +398 -0
- package/src/monitor/provider.cleanup.ts +41 -0
- package/src/monitor/provider.commands.ts +129 -0
- package/src/monitor/provider.config-log.ts +45 -0
- package/src/monitor/provider.deploy-errors.ts +362 -0
- package/src/monitor/provider.deploy.ts +221 -0
- package/src/monitor/provider.interactions.ts +160 -0
- package/src/monitor/provider.lifecycle.ts +562 -0
- package/src/monitor/provider.runtime.ts +1 -0
- package/src/monitor/provider.startup-log.ts +32 -0
- package/src/monitor/provider.startup.ts +323 -0
- package/src/monitor/provider.ts +688 -0
- package/src/monitor/reply-context.ts +64 -0
- package/src/monitor/reply-delivery.ts +216 -0
- package/src/monitor/reply-safety.ts +96 -0
- package/src/monitor/rest-fetch.ts +97 -0
- package/src/monitor/route-resolution.ts +140 -0
- package/src/monitor/sender-identity.ts +81 -0
- package/src/monitor/startup-status.ts +10 -0
- package/src/monitor/status.ts +22 -0
- package/src/monitor/system-events.ts +55 -0
- package/src/monitor/thread-bindings.config.ts +35 -0
- package/src/monitor/thread-bindings.discord-api.ts +310 -0
- package/src/monitor/thread-bindings.lifecycle.ts +354 -0
- package/src/monitor/thread-bindings.manager.ts +554 -0
- package/src/monitor/thread-bindings.messages.ts +6 -0
- package/src/monitor/thread-bindings.persona.ts +25 -0
- package/src/monitor/thread-bindings.session-adapter.ts +229 -0
- package/src/monitor/thread-bindings.session-shared.ts +59 -0
- package/src/monitor/thread-bindings.session-updates.ts +35 -0
- package/src/monitor/thread-bindings.state.ts +540 -0
- package/src/monitor/thread-bindings.ts +48 -0
- package/src/monitor/thread-bindings.types.ts +83 -0
- package/src/monitor/thread-channel-context.ts +112 -0
- package/src/monitor/thread-session-close.ts +63 -0
- package/src/monitor/thread-title.ts +181 -0
- package/src/monitor/threading.auto-thread.ts +287 -0
- package/src/monitor/threading.cache.ts +45 -0
- package/src/monitor/threading.starter.ts +288 -0
- package/src/monitor/threading.ts +20 -0
- package/src/monitor/threading.types.ts +102 -0
- package/src/monitor/timeouts.ts +84 -0
- package/src/monitor/typing.ts +17 -0
- package/src/monitor.gateway.ts +75 -0
- package/src/monitor.ts +28 -0
- package/src/network-config.ts +79 -0
- package/src/normalize.ts +86 -0
- package/src/outbound-adapter.ts +327 -0
- package/src/outbound-approval.ts +29 -0
- package/src/outbound-components.ts +86 -0
- package/src/outbound-payload.ts +208 -0
- package/src/outbound-send-context.ts +92 -0
- package/src/outbound-session-route.ts +72 -0
- package/src/pluralkit.ts +58 -0
- package/src/preview-streaming.ts +18 -0
- package/src/probe.runtime.ts +1 -0
- package/src/probe.ts +237 -0
- package/src/proxy-fetch.ts +92 -0
- package/src/proxy-request-client.ts +21 -0
- package/src/recipient-resolution.ts +39 -0
- package/src/resolve-allowlist-common.ts +39 -0
- package/src/resolve-channels.ts +369 -0
- package/src/resolve-users.ts +184 -0
- package/src/retry.ts +98 -0
- package/src/runtime-api.ts +64 -0
- package/src/runtime-config.ts +16 -0
- package/src/runtime.ts +23 -0
- package/src/secret-config-contract.ts +140 -0
- package/src/security-audit.runtime.ts +1 -0
- package/src/security-audit.ts +208 -0
- package/src/security-contract.ts +47 -0
- package/src/security-doctor.ts +20 -0
- package/src/security.ts +60 -0
- package/src/send-target-parsing.ts +14 -0
- package/src/send.channels.ts +139 -0
- package/src/send.components.ts +391 -0
- package/src/send.emojis-stickers.ts +57 -0
- package/src/send.guild.ts +170 -0
- package/src/send.message-request.ts +112 -0
- package/src/send.messages.ts +229 -0
- package/src/send.outbound.ts +459 -0
- package/src/send.permissions.ts +283 -0
- package/src/send.reactions.ts +155 -0
- package/src/send.receipt.ts +69 -0
- package/src/send.shared.ts +469 -0
- package/src/send.ts +82 -0
- package/src/send.types.ts +191 -0
- package/src/send.typing.ts +9 -0
- package/src/send.voice.ts +140 -0
- package/src/send.webhook.ts +137 -0
- package/src/session-contract.ts +3 -0
- package/src/session-key-normalization.ts +47 -0
- package/src/setup-account-state.ts +144 -0
- package/src/setup-adapter.ts +14 -0
- package/src/setup-core.ts +215 -0
- package/src/setup-runtime-helpers.ts +10 -0
- package/src/setup-surface.ts +132 -0
- package/src/shared-interactive.ts +167 -0
- package/src/shared.ts +197 -0
- package/src/status-issues.ts +201 -0
- package/src/subagent-hooks.ts +232 -0
- package/src/target-parsing.ts +70 -0
- package/src/target-resolver.ts +129 -0
- package/src/targets.ts +12 -0
- package/src/token.ts +107 -0
- package/src/ui-colors.ts +27 -0
- package/src/ui.ts +20 -0
- package/src/voice/access.ts +126 -0
- package/src/voice/audio.ts +249 -0
- package/src/voice/capture-state.ts +120 -0
- package/src/voice/command.ts +284 -0
- package/src/voice/config.ts +8 -0
- package/src/voice/ingress.ts +164 -0
- package/src/voice/manager.runtime.ts +14 -0
- package/src/voice/manager.ts +1155 -0
- package/src/voice/prompt.ts +22 -0
- package/src/voice/realtime.ts +1370 -0
- package/src/voice/receive-recovery.ts +159 -0
- package/src/voice/sanitize.ts +29 -0
- package/src/voice/sdk-runtime.ts +14 -0
- package/src/voice/segment.ts +160 -0
- package/src/voice/session.ts +81 -0
- package/src/voice/speaker-context.ts +127 -0
- package/src/voice/tts.ts +151 -0
- package/src/voice-message.ts +474 -0
- package/subagent-hooks-api.ts +27 -0
- package/test-api.ts +4 -0
- package/thread-binding-api.ts +1 -0
- package/timeouts.ts +6 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addAllowlistUserEntriesFromConfigEntry,
|
|
3
|
+
buildAllowlistResolutionSummary,
|
|
4
|
+
canonicalizeAllowlistWithResolvedIds,
|
|
5
|
+
patchAllowlistUsersInConfigEntries,
|
|
6
|
+
summarizeMapping,
|
|
7
|
+
} from "autobot/plugin-sdk/allow-from";
|
|
8
|
+
import type { DiscordAccountConfig, DiscordGuildEntry } from "autobot/plugin-sdk/config-contracts";
|
|
9
|
+
import { isDangerousNameMatchingEnabled } from "autobot/plugin-sdk/dangerous-name-runtime";
|
|
10
|
+
import type { RuntimeEnv } from "autobot/plugin-sdk/runtime-env";
|
|
11
|
+
import { formatErrorMessage } from "autobot/plugin-sdk/ssrf-runtime";
|
|
12
|
+
import { normalizeStringEntries } from "autobot/plugin-sdk/string-coerce-runtime";
|
|
13
|
+
import { resolveDiscordChannelAllowlist } from "../resolve-channels.js";
|
|
14
|
+
import { resolveDiscordUserAllowlist } from "../resolve-users.js";
|
|
15
|
+
|
|
16
|
+
type GuildEntries = Record<string, DiscordGuildEntry>;
|
|
17
|
+
type ChannelResolutionInput = { input: string; guildKey: string; channelKey?: string };
|
|
18
|
+
type DiscordChannelLogEntry = {
|
|
19
|
+
input: string;
|
|
20
|
+
guildId?: string;
|
|
21
|
+
guildName?: string;
|
|
22
|
+
channelId?: string;
|
|
23
|
+
channelName?: string;
|
|
24
|
+
note?: string;
|
|
25
|
+
};
|
|
26
|
+
type DiscordChannelResolvedGroup = {
|
|
27
|
+
target: string;
|
|
28
|
+
aliases: string[];
|
|
29
|
+
guildName?: string;
|
|
30
|
+
channelName?: string;
|
|
31
|
+
note?: string;
|
|
32
|
+
};
|
|
33
|
+
type DiscordUserLogEntry = {
|
|
34
|
+
input: string;
|
|
35
|
+
id?: string;
|
|
36
|
+
name?: string;
|
|
37
|
+
guildName?: string;
|
|
38
|
+
note?: string;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
function formatResolutionLogDetails(base: string, details: Array<string | undefined>): string {
|
|
42
|
+
const nonEmpty = details
|
|
43
|
+
.map((value) => value?.trim())
|
|
44
|
+
.filter((value): value is string => Boolean(value));
|
|
45
|
+
return nonEmpty.length > 0 ? `${base} (${nonEmpty.join("; ")})` : base;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function formatResolvedBase(input: string, target: string | undefined): string {
|
|
49
|
+
if (!target) {
|
|
50
|
+
return input;
|
|
51
|
+
}
|
|
52
|
+
return input === target ? input : `${input}→${target}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function formatAliasSummary(aliases: string[]): string | undefined {
|
|
56
|
+
if (aliases.length === 0) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
const preview = aliases.slice(0, 3).join(", ");
|
|
60
|
+
if (aliases.length <= 3) {
|
|
61
|
+
return preview;
|
|
62
|
+
}
|
|
63
|
+
return `${preview}, +${aliases.length - 3} more`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function formatDiscordChannelResolvedGroup(entry: DiscordChannelResolvedGroup): string {
|
|
67
|
+
const aliasSummary = formatAliasSummary(entry.aliases);
|
|
68
|
+
return formatResolutionLogDetails(entry.target, [
|
|
69
|
+
entry.guildName ? `guild:${entry.guildName}` : undefined,
|
|
70
|
+
entry.channelName ? `channel:${entry.channelName}` : undefined,
|
|
71
|
+
entry.note,
|
|
72
|
+
aliasSummary ? `aliases:${aliasSummary}` : undefined,
|
|
73
|
+
]);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function formatDiscordChannelUnresolved(entry: DiscordChannelLogEntry): string {
|
|
77
|
+
return formatResolutionLogDetails(entry.input, [
|
|
78
|
+
entry.guildName
|
|
79
|
+
? `guild:${entry.guildName}`
|
|
80
|
+
: entry.guildId
|
|
81
|
+
? `guildId:${entry.guildId}`
|
|
82
|
+
: undefined,
|
|
83
|
+
entry.channelName
|
|
84
|
+
? `channel:${entry.channelName}`
|
|
85
|
+
: entry.channelId
|
|
86
|
+
? `channelId:${entry.channelId}`
|
|
87
|
+
: undefined,
|
|
88
|
+
entry.note,
|
|
89
|
+
]);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function formatDiscordUserResolved(entry: DiscordUserLogEntry): string {
|
|
93
|
+
const displayName = entry.name?.trim();
|
|
94
|
+
const target = displayName || entry.id;
|
|
95
|
+
const base = formatResolvedBase(entry.input, target);
|
|
96
|
+
return formatResolutionLogDetails(base, [
|
|
97
|
+
displayName && entry.id ? `id:${entry.id}` : undefined,
|
|
98
|
+
entry.guildName ? `guild:${entry.guildName}` : undefined,
|
|
99
|
+
entry.note,
|
|
100
|
+
]);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function formatDiscordUserUnresolved(entry: DiscordUserLogEntry): string {
|
|
104
|
+
return formatResolutionLogDetails(entry.input, [
|
|
105
|
+
entry.name ? `name:${entry.name}` : undefined,
|
|
106
|
+
entry.guildName ? `guild:${entry.guildName}` : undefined,
|
|
107
|
+
entry.note,
|
|
108
|
+
]);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function toGuildEntries(value: unknown): GuildEntries {
|
|
112
|
+
if (!value || typeof value !== "object") {
|
|
113
|
+
return {};
|
|
114
|
+
}
|
|
115
|
+
const out: GuildEntries = {};
|
|
116
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
117
|
+
if (!entry || typeof entry !== "object") {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
out[key] = entry as DiscordGuildEntry;
|
|
121
|
+
}
|
|
122
|
+
return out;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function toAllowlistEntries(value: unknown): string[] | undefined {
|
|
126
|
+
if (!Array.isArray(value)) {
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
return normalizeStringEntries(value);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function hasGuildEntries(value: GuildEntries): boolean {
|
|
133
|
+
return Object.keys(value).length > 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function collectChannelResolutionInputs(guildEntries: GuildEntries): ChannelResolutionInput[] {
|
|
137
|
+
const entries: ChannelResolutionInput[] = [];
|
|
138
|
+
for (const [guildKey, guildCfg] of Object.entries(guildEntries)) {
|
|
139
|
+
if (guildKey === "*") {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const channels = guildCfg?.channels ?? {};
|
|
143
|
+
const channelKeys = Object.keys(channels).filter((key) => key !== "*");
|
|
144
|
+
if (channelKeys.length === 0) {
|
|
145
|
+
const input = /^\d+$/.test(guildKey) ? `guild:${guildKey}` : guildKey;
|
|
146
|
+
entries.push({ input, guildKey });
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
for (const channelKey of channelKeys) {
|
|
150
|
+
entries.push({
|
|
151
|
+
input: `${guildKey}/${channelKey}`,
|
|
152
|
+
guildKey,
|
|
153
|
+
channelKey,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return entries;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function resolveGuildEntriesByChannelAllowlist(params: {
|
|
161
|
+
token: string;
|
|
162
|
+
guildEntries: GuildEntries;
|
|
163
|
+
fetcher: typeof fetch;
|
|
164
|
+
runtime: RuntimeEnv;
|
|
165
|
+
}): Promise<GuildEntries> {
|
|
166
|
+
const entries = collectChannelResolutionInputs(params.guildEntries);
|
|
167
|
+
if (entries.length === 0) {
|
|
168
|
+
return params.guildEntries;
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
const resolved = await resolveDiscordChannelAllowlist({
|
|
172
|
+
token: params.token,
|
|
173
|
+
entries: entries.map((entry) => entry.input),
|
|
174
|
+
fetcher: params.fetcher,
|
|
175
|
+
});
|
|
176
|
+
const sourceByInput = new Map(entries.map((entry) => [entry.input, entry]));
|
|
177
|
+
const nextGuilds = { ...params.guildEntries };
|
|
178
|
+
const mappingByTarget = new Map<string, DiscordChannelResolvedGroup>();
|
|
179
|
+
const unresolved: string[] = [];
|
|
180
|
+
for (const entry of resolved) {
|
|
181
|
+
const source = sourceByInput.get(entry.input);
|
|
182
|
+
if (!source) {
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
const sourceGuild = params.guildEntries[source.guildKey] ?? {};
|
|
186
|
+
if (!entry.resolved || !entry.guildId) {
|
|
187
|
+
unresolved.push(formatDiscordChannelUnresolved(entry));
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
const target = entry.channelId ? `${entry.guildId}/${entry.channelId}` : entry.guildId;
|
|
191
|
+
const existingGroup =
|
|
192
|
+
mappingByTarget.get(target) ??
|
|
193
|
+
({
|
|
194
|
+
target,
|
|
195
|
+
aliases: [],
|
|
196
|
+
guildName: entry.guildName,
|
|
197
|
+
channelName: entry.channelName,
|
|
198
|
+
note: entry.note,
|
|
199
|
+
} satisfies DiscordChannelResolvedGroup);
|
|
200
|
+
if (entry.input !== target && !existingGroup.aliases.includes(entry.input)) {
|
|
201
|
+
existingGroup.aliases.push(entry.input);
|
|
202
|
+
}
|
|
203
|
+
if (!existingGroup.guildName && entry.guildName) {
|
|
204
|
+
existingGroup.guildName = entry.guildName;
|
|
205
|
+
}
|
|
206
|
+
if (!existingGroup.channelName && entry.channelName) {
|
|
207
|
+
existingGroup.channelName = entry.channelName;
|
|
208
|
+
}
|
|
209
|
+
if (!existingGroup.note && entry.note) {
|
|
210
|
+
existingGroup.note = entry.note;
|
|
211
|
+
}
|
|
212
|
+
mappingByTarget.set(target, existingGroup);
|
|
213
|
+
const existing = nextGuilds[entry.guildId] ?? {};
|
|
214
|
+
const mergedChannels = {
|
|
215
|
+
...sourceGuild.channels,
|
|
216
|
+
...existing.channels,
|
|
217
|
+
};
|
|
218
|
+
const mergedGuild: DiscordGuildEntry = {
|
|
219
|
+
...sourceGuild,
|
|
220
|
+
...existing,
|
|
221
|
+
channels: mergedChannels,
|
|
222
|
+
};
|
|
223
|
+
nextGuilds[entry.guildId] = mergedGuild;
|
|
224
|
+
|
|
225
|
+
if (source.channelKey && entry.channelId) {
|
|
226
|
+
const sourceChannel = sourceGuild.channels?.[source.channelKey];
|
|
227
|
+
if (sourceChannel) {
|
|
228
|
+
nextGuilds[entry.guildId] = {
|
|
229
|
+
...mergedGuild,
|
|
230
|
+
channels: {
|
|
231
|
+
...mergedChannels,
|
|
232
|
+
[entry.channelId]: {
|
|
233
|
+
...sourceChannel,
|
|
234
|
+
...mergedChannels[entry.channelId],
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const mapping = [...mappingByTarget.values()].map((group) =>
|
|
242
|
+
formatDiscordChannelResolvedGroup(group),
|
|
243
|
+
);
|
|
244
|
+
summarizeMapping("discord channels", mapping, unresolved, params.runtime);
|
|
245
|
+
return nextGuilds;
|
|
246
|
+
} catch (err) {
|
|
247
|
+
params.runtime.log?.(
|
|
248
|
+
`discord channel resolve failed; using config entries. ${formatErrorMessage(err)}`,
|
|
249
|
+
);
|
|
250
|
+
return params.guildEntries;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async function resolveAllowFromByUserAllowlist(params: {
|
|
255
|
+
token: string;
|
|
256
|
+
allowFrom: string[] | undefined;
|
|
257
|
+
fetcher: typeof fetch;
|
|
258
|
+
runtime: RuntimeEnv;
|
|
259
|
+
}): Promise<string[] | undefined> {
|
|
260
|
+
const allowEntries = normalizeStringEntries(params.allowFrom).filter((entry) => entry !== "*");
|
|
261
|
+
if (allowEntries.length === 0) {
|
|
262
|
+
return params.allowFrom;
|
|
263
|
+
}
|
|
264
|
+
try {
|
|
265
|
+
const resolvedUsers = await resolveDiscordUserAllowlist({
|
|
266
|
+
token: params.token,
|
|
267
|
+
entries: allowEntries,
|
|
268
|
+
fetcher: params.fetcher,
|
|
269
|
+
});
|
|
270
|
+
const { resolvedMap, mapping, unresolved } = buildAllowlistResolutionSummary(resolvedUsers, {
|
|
271
|
+
formatResolved: formatDiscordUserResolved,
|
|
272
|
+
formatUnresolved: formatDiscordUserUnresolved,
|
|
273
|
+
});
|
|
274
|
+
const allowFrom = canonicalizeAllowlistWithResolvedIds({
|
|
275
|
+
existing: params.allowFrom,
|
|
276
|
+
resolvedMap,
|
|
277
|
+
});
|
|
278
|
+
summarizeMapping("discord users", mapping, unresolved, params.runtime);
|
|
279
|
+
return allowFrom;
|
|
280
|
+
} catch (err) {
|
|
281
|
+
params.runtime.log?.(
|
|
282
|
+
`discord user resolve failed; using config entries. ${formatErrorMessage(err)}`,
|
|
283
|
+
);
|
|
284
|
+
return params.allowFrom;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function collectGuildUserEntries(guildEntries: GuildEntries): Set<string> {
|
|
289
|
+
const userEntries = new Set<string>();
|
|
290
|
+
for (const guild of Object.values(guildEntries)) {
|
|
291
|
+
if (!guild || typeof guild !== "object") {
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
addAllowlistUserEntriesFromConfigEntry(userEntries, guild);
|
|
295
|
+
const channels = (guild as { channels?: Record<string, unknown> }).channels ?? {};
|
|
296
|
+
for (const channel of Object.values(channels)) {
|
|
297
|
+
addAllowlistUserEntriesFromConfigEntry(userEntries, channel);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return userEntries;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async function resolveGuildEntriesByUserAllowlist(params: {
|
|
304
|
+
token: string;
|
|
305
|
+
guildEntries: GuildEntries;
|
|
306
|
+
fetcher: typeof fetch;
|
|
307
|
+
runtime: RuntimeEnv;
|
|
308
|
+
}): Promise<GuildEntries> {
|
|
309
|
+
const userEntries = collectGuildUserEntries(params.guildEntries);
|
|
310
|
+
if (userEntries.size === 0) {
|
|
311
|
+
return params.guildEntries;
|
|
312
|
+
}
|
|
313
|
+
try {
|
|
314
|
+
const resolvedUsers = await resolveDiscordUserAllowlist({
|
|
315
|
+
token: params.token,
|
|
316
|
+
entries: Array.from(userEntries),
|
|
317
|
+
fetcher: params.fetcher,
|
|
318
|
+
});
|
|
319
|
+
const { resolvedMap, mapping, unresolved } = buildAllowlistResolutionSummary(resolvedUsers, {
|
|
320
|
+
formatResolved: formatDiscordUserResolved,
|
|
321
|
+
formatUnresolved: formatDiscordUserUnresolved,
|
|
322
|
+
});
|
|
323
|
+
const nextGuilds = { ...params.guildEntries };
|
|
324
|
+
for (const [guildKey, guildConfig] of Object.entries(params.guildEntries)) {
|
|
325
|
+
if (!guildConfig || typeof guildConfig !== "object") {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
const nextGuild = { ...guildConfig } as Record<string, unknown>;
|
|
329
|
+
const users = (guildConfig as { users?: string[] }).users;
|
|
330
|
+
if (Array.isArray(users) && users.length > 0) {
|
|
331
|
+
nextGuild.users = canonicalizeAllowlistWithResolvedIds({
|
|
332
|
+
existing: users,
|
|
333
|
+
resolvedMap,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
const channels = (guildConfig as { channels?: Record<string, unknown> }).channels ?? {};
|
|
337
|
+
if (channels && typeof channels === "object") {
|
|
338
|
+
nextGuild.channels = patchAllowlistUsersInConfigEntries({
|
|
339
|
+
entries: channels,
|
|
340
|
+
resolvedMap,
|
|
341
|
+
strategy: "canonicalize",
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
nextGuilds[guildKey] = nextGuild as DiscordGuildEntry;
|
|
345
|
+
}
|
|
346
|
+
summarizeMapping("discord channel users", mapping, unresolved, params.runtime);
|
|
347
|
+
return nextGuilds;
|
|
348
|
+
} catch (err) {
|
|
349
|
+
params.runtime.log?.(
|
|
350
|
+
`discord channel user resolve failed; using config entries. ${formatErrorMessage(err)}`,
|
|
351
|
+
);
|
|
352
|
+
return params.guildEntries;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export async function resolveDiscordAllowlistConfig(params: {
|
|
357
|
+
token: string;
|
|
358
|
+
guildEntries: unknown;
|
|
359
|
+
allowFrom: unknown;
|
|
360
|
+
discordConfig: DiscordAccountConfig;
|
|
361
|
+
fetcher: typeof fetch;
|
|
362
|
+
runtime: RuntimeEnv;
|
|
363
|
+
}): Promise<{ guildEntries: GuildEntries | undefined; allowFrom: string[] | undefined }> {
|
|
364
|
+
let guildEntries = toGuildEntries(params.guildEntries);
|
|
365
|
+
let allowFrom = toAllowlistEntries(params.allowFrom);
|
|
366
|
+
|
|
367
|
+
if (hasGuildEntries(guildEntries)) {
|
|
368
|
+
guildEntries = await resolveGuildEntriesByChannelAllowlist({
|
|
369
|
+
token: params.token,
|
|
370
|
+
guildEntries,
|
|
371
|
+
fetcher: params.fetcher,
|
|
372
|
+
runtime: params.runtime,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (isDangerousNameMatchingEnabled(params.discordConfig)) {
|
|
377
|
+
allowFrom = await resolveAllowFromByUserAllowlist({
|
|
378
|
+
token: params.token,
|
|
379
|
+
allowFrom,
|
|
380
|
+
fetcher: params.fetcher,
|
|
381
|
+
runtime: params.runtime,
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
if (hasGuildEntries(guildEntries)) {
|
|
385
|
+
guildEntries = await resolveGuildEntriesByUserAllowlist({
|
|
386
|
+
token: params.token,
|
|
387
|
+
guildEntries,
|
|
388
|
+
fetcher: params.fetcher,
|
|
389
|
+
runtime: params.runtime,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return {
|
|
395
|
+
guildEntries: hasGuildEntries(guildEntries) ? guildEntries : undefined,
|
|
396
|
+
allowFrom,
|
|
397
|
+
};
|
|
398
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { danger, type RuntimeEnv } from "autobot/plugin-sdk/runtime-env";
|
|
2
|
+
import type { MutableDiscordGateway } from "./gateway-handle.js";
|
|
3
|
+
import type { DiscordMonitorStatusSink } from "./status.js";
|
|
4
|
+
import type { ThreadBindingManager } from "./thread-bindings.js";
|
|
5
|
+
|
|
6
|
+
type EventEmitterLike = {
|
|
7
|
+
removeListener(event: string, listener: (...args: unknown[]) => void): unknown;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function cleanupDiscordProviderStartup(params: {
|
|
11
|
+
deactivateMessageHandler?: () => void;
|
|
12
|
+
autoPresenceController?: { stop: () => void } | null;
|
|
13
|
+
setStatus?: DiscordMonitorStatusSink;
|
|
14
|
+
onEarlyGatewayDebug?: ((msg: unknown) => void) | undefined;
|
|
15
|
+
earlyGatewayEmitter?: EventEmitterLike | undefined;
|
|
16
|
+
lifecycleStarted: boolean;
|
|
17
|
+
lifecycleGateway?: MutableDiscordGateway;
|
|
18
|
+
gatewaySupervisor?: { dispose: () => void };
|
|
19
|
+
threadBindings: ThreadBindingManager;
|
|
20
|
+
runtime: RuntimeEnv;
|
|
21
|
+
}) {
|
|
22
|
+
params.deactivateMessageHandler?.();
|
|
23
|
+
params.autoPresenceController?.stop();
|
|
24
|
+
params.setStatus?.({ connected: false });
|
|
25
|
+
if (params.onEarlyGatewayDebug) {
|
|
26
|
+
params.earlyGatewayEmitter?.removeListener("debug", params.onEarlyGatewayDebug);
|
|
27
|
+
}
|
|
28
|
+
if (!params.lifecycleStarted) {
|
|
29
|
+
try {
|
|
30
|
+
params.lifecycleGateway?.disconnect();
|
|
31
|
+
} catch (err) {
|
|
32
|
+
params.runtime.error?.(
|
|
33
|
+
danger(`discord: failed to disconnect gateway during startup cleanup: ${String(err)}`),
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
params.gatewaySupervisor?.dispose();
|
|
38
|
+
if (!params.lifecycleStarted) {
|
|
39
|
+
params.threadBindings.stop();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import {
|
|
2
|
+
listNativeCommandSpecsForConfig,
|
|
3
|
+
listSkillCommandsForAgents,
|
|
4
|
+
type NativeCommandSpec,
|
|
5
|
+
} from "autobot/plugin-sdk/command-auth-native";
|
|
6
|
+
import type { AutoBotConfig } from "autobot/plugin-sdk/config-contracts";
|
|
7
|
+
import { danger, warn, type RuntimeEnv } from "autobot/plugin-sdk/runtime-env";
|
|
8
|
+
import { normalizeLowercaseStringOrEmpty } from "autobot/plugin-sdk/string-coerce-runtime";
|
|
9
|
+
|
|
10
|
+
export type GetPluginCommandSpecs =
|
|
11
|
+
typeof import("autobot/plugin-sdk/plugin-runtime").getPluginCommandSpecs;
|
|
12
|
+
|
|
13
|
+
let pluginRuntimePromise: Promise<typeof import("autobot/plugin-sdk/plugin-runtime")> | undefined;
|
|
14
|
+
|
|
15
|
+
async function loadPluginRuntime() {
|
|
16
|
+
const promise = pluginRuntimePromise ?? import("autobot/plugin-sdk/plugin-runtime");
|
|
17
|
+
pluginRuntimePromise = promise;
|
|
18
|
+
try {
|
|
19
|
+
return await promise;
|
|
20
|
+
} catch (error) {
|
|
21
|
+
if (pluginRuntimePromise === promise) {
|
|
22
|
+
pluginRuntimePromise = undefined;
|
|
23
|
+
}
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function appendPluginCommandSpecs(params: {
|
|
29
|
+
commandSpecs: NativeCommandSpec[];
|
|
30
|
+
runtime: RuntimeEnv;
|
|
31
|
+
cfg: AutoBotConfig;
|
|
32
|
+
getPluginCommandSpecs?: GetPluginCommandSpecs;
|
|
33
|
+
}): Promise<NativeCommandSpec[]> {
|
|
34
|
+
const merged = [...params.commandSpecs];
|
|
35
|
+
const existingNames = new Set(
|
|
36
|
+
merged.map((spec) => normalizeLowercaseStringOrEmpty(spec.name)).filter(Boolean),
|
|
37
|
+
);
|
|
38
|
+
const getPluginCommandSpecs =
|
|
39
|
+
params.getPluginCommandSpecs ?? (await loadPluginRuntime()).getPluginCommandSpecs;
|
|
40
|
+
for (const pluginCommand of getPluginCommandSpecs("discord", { config: params.cfg })) {
|
|
41
|
+
const normalizedName = normalizeLowercaseStringOrEmpty(pluginCommand.name);
|
|
42
|
+
if (!normalizedName) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (existingNames.has(normalizedName)) {
|
|
46
|
+
params.runtime.error?.(
|
|
47
|
+
danger(
|
|
48
|
+
`discord: plugin command "/${normalizedName}" duplicates an existing native command. Skipping.`,
|
|
49
|
+
),
|
|
50
|
+
);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
existingNames.add(normalizedName);
|
|
54
|
+
merged.push({
|
|
55
|
+
name: pluginCommand.name,
|
|
56
|
+
description: pluginCommand.description,
|
|
57
|
+
acceptsArgs: pluginCommand.acceptsArgs,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return merged;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function resolveDiscordProviderCommandSpecs(params: {
|
|
64
|
+
cfg: AutoBotConfig;
|
|
65
|
+
runtime: RuntimeEnv;
|
|
66
|
+
nativeEnabled: boolean;
|
|
67
|
+
nativeSkillsEnabled: boolean;
|
|
68
|
+
maxDiscordCommands?: number;
|
|
69
|
+
listSkillCommandsForAgents?: typeof listSkillCommandsForAgents;
|
|
70
|
+
listNativeCommandSpecsForConfig?: typeof listNativeCommandSpecsForConfig;
|
|
71
|
+
getPluginCommandSpecs?: GetPluginCommandSpecs;
|
|
72
|
+
}): Promise<{
|
|
73
|
+
skillCommands: ReturnType<typeof listSkillCommandsForAgents>;
|
|
74
|
+
commandSpecs: NativeCommandSpec[];
|
|
75
|
+
}> {
|
|
76
|
+
const listSkillCommands = params.listSkillCommandsForAgents ?? listSkillCommandsForAgents;
|
|
77
|
+
const listNativeCommandSpecs =
|
|
78
|
+
params.listNativeCommandSpecsForConfig ?? listNativeCommandSpecsForConfig;
|
|
79
|
+
const maxDiscordCommands = params.maxDiscordCommands ?? 100;
|
|
80
|
+
let skillCommands =
|
|
81
|
+
params.nativeEnabled && params.nativeSkillsEnabled
|
|
82
|
+
? listSkillCommands({ cfg: params.cfg })
|
|
83
|
+
: [];
|
|
84
|
+
let commandSpecs = params.nativeEnabled
|
|
85
|
+
? listNativeCommandSpecs(params.cfg, {
|
|
86
|
+
skillCommands,
|
|
87
|
+
provider: "discord",
|
|
88
|
+
})
|
|
89
|
+
: [];
|
|
90
|
+
if (params.nativeEnabled) {
|
|
91
|
+
commandSpecs = await appendPluginCommandSpecs({
|
|
92
|
+
commandSpecs,
|
|
93
|
+
runtime: params.runtime,
|
|
94
|
+
cfg: params.cfg,
|
|
95
|
+
getPluginCommandSpecs: params.getPluginCommandSpecs,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const initialCommandCount = commandSpecs.length;
|
|
99
|
+
if (
|
|
100
|
+
params.nativeEnabled &&
|
|
101
|
+
params.nativeSkillsEnabled &&
|
|
102
|
+
commandSpecs.length > maxDiscordCommands
|
|
103
|
+
) {
|
|
104
|
+
skillCommands = [];
|
|
105
|
+
commandSpecs = listNativeCommandSpecs(params.cfg, {
|
|
106
|
+
skillCommands: [],
|
|
107
|
+
provider: "discord",
|
|
108
|
+
});
|
|
109
|
+
commandSpecs = await appendPluginCommandSpecs({
|
|
110
|
+
commandSpecs,
|
|
111
|
+
runtime: params.runtime,
|
|
112
|
+
cfg: params.cfg,
|
|
113
|
+
getPluginCommandSpecs: params.getPluginCommandSpecs,
|
|
114
|
+
});
|
|
115
|
+
params.runtime.log?.(
|
|
116
|
+
warn(
|
|
117
|
+
`discord: ${initialCommandCount} commands exceeds limit; removing per-skill commands and keeping /skill.`,
|
|
118
|
+
),
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
if (params.nativeEnabled && commandSpecs.length > maxDiscordCommands) {
|
|
122
|
+
params.runtime.log?.(
|
|
123
|
+
warn(
|
|
124
|
+
`discord: ${commandSpecs.length} commands exceeds limit; some commands may fail to deploy.`,
|
|
125
|
+
),
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return { skillCommands, commandSpecs };
|
|
129
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { logVerbose } from "autobot/plugin-sdk/runtime-env";
|
|
2
|
+
import { summarizeStringEntries } from "autobot/plugin-sdk/string-coerce-runtime";
|
|
3
|
+
import { formatThreadBindingDurationLabel } from "./thread-bindings.messages.js";
|
|
4
|
+
|
|
5
|
+
function formatThreadBindingDurationForConfigLabel(durationMs: number): string {
|
|
6
|
+
const label = formatThreadBindingDurationLabel(durationMs);
|
|
7
|
+
return label === "disabled" ? "off" : label;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function logDiscordResolvedConfig(params: {
|
|
11
|
+
dmEnabled: boolean;
|
|
12
|
+
dmPolicy: string;
|
|
13
|
+
allowFrom?: string[];
|
|
14
|
+
groupDmEnabled: boolean;
|
|
15
|
+
groupDmChannels?: string[];
|
|
16
|
+
groupPolicy: string;
|
|
17
|
+
guildEntries?: Record<string, unknown>;
|
|
18
|
+
historyLimit: number;
|
|
19
|
+
mediaMaxBytes: number;
|
|
20
|
+
nativeEnabled: boolean;
|
|
21
|
+
nativeSkillsEnabled: boolean;
|
|
22
|
+
useAccessGroups: boolean;
|
|
23
|
+
threadBindingsEnabled: boolean;
|
|
24
|
+
threadBindingIdleTimeoutMs: number;
|
|
25
|
+
threadBindingMaxAgeMs: number;
|
|
26
|
+
}): void {
|
|
27
|
+
const allowFromSummary = summarizeStringEntries({
|
|
28
|
+
entries: params.allowFrom ?? [],
|
|
29
|
+
limit: 4,
|
|
30
|
+
emptyText: "any",
|
|
31
|
+
});
|
|
32
|
+
const groupDmChannelSummary = summarizeStringEntries({
|
|
33
|
+
entries: params.groupDmChannels ?? [],
|
|
34
|
+
limit: 4,
|
|
35
|
+
emptyText: "any",
|
|
36
|
+
});
|
|
37
|
+
const guildSummary = summarizeStringEntries({
|
|
38
|
+
entries: Object.keys(params.guildEntries ?? {}),
|
|
39
|
+
limit: 4,
|
|
40
|
+
emptyText: "any",
|
|
41
|
+
});
|
|
42
|
+
logVerbose(
|
|
43
|
+
`discord: config dm=${params.dmEnabled ? "on" : "off"} dmPolicy=${params.dmPolicy} allowFrom=${allowFromSummary} groupDm=${params.groupDmEnabled ? "on" : "off"} groupDmChannels=${groupDmChannelSummary} groupPolicy=${params.groupPolicy} guilds=${guildSummary} historyLimit=${params.historyLimit} mediaMaxMb=${Math.round(params.mediaMaxBytes / (1024 * 1024))} native=${params.nativeEnabled ? "on" : "off"} nativeSkills=${params.nativeSkillsEnabled ? "on" : "off"} accessGroups=${params.useAccessGroups ? "on" : "off"} threadBindings=${params.threadBindingsEnabled ? "on" : "off"} threadIdleTimeout=${formatThreadBindingDurationForConfigLabel(params.threadBindingIdleTimeoutMs)} threadMaxAge=${formatThreadBindingDurationForConfigLabel(params.threadBindingMaxAgeMs)}`,
|
|
44
|
+
);
|
|
45
|
+
}
|