mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
refactor(extensions): burn down Discord and Slack dead exports (#106017)
* refactor(discord): trim dead internal exports * refactor(slack): trim dead internal exports * test(discord): cover inherited streaming migration * chore(tooling): ratchet reduced extension LOC * refactor(discord): remove stale approval helper import * chore(deadcode): remove reintroduced transcript baseline
This commit is contained in:
@@ -8,8 +8,6 @@ import {
|
||||
createDiscordMessagingActionContext,
|
||||
type DiscordMessagingActionOptions,
|
||||
} from "./runtime.messaging.shared.js";
|
||||
export { discordMessagingActionRuntime } from "./runtime.messaging.runtime.js";
|
||||
|
||||
export async function handleDiscordMessagingAction(
|
||||
action: string,
|
||||
params: Record<string, unknown>,
|
||||
|
||||
@@ -8,10 +8,8 @@ import { clearPresences, setPresence } from "../monitor/presence-cache.js";
|
||||
import { DiscordThreadInitialMessageError } from "../send.js";
|
||||
import { discordGuildActionRuntime, handleDiscordGuildAction } from "./runtime.guild.js";
|
||||
import { handleDiscordAction } from "./runtime.js";
|
||||
import {
|
||||
discordMessagingActionRuntime,
|
||||
handleDiscordMessagingAction,
|
||||
} from "./runtime.messaging.js";
|
||||
import { handleDiscordMessagingAction } from "./runtime.messaging.js";
|
||||
import { discordMessagingActionRuntime } from "./runtime.messaging.runtime.js";
|
||||
import {
|
||||
discordModerationActionRuntime,
|
||||
handleDiscordModerationAction,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { buildApprovalResolutionRef } from "openclaw/plugin-sdk/approval-referen
|
||||
import type { MessagePresentationAction } from "openclaw/plugin-sdk/interactive-runtime";
|
||||
import type { ComponentData } from "./internal/discord.js";
|
||||
|
||||
export type DiscordApprovalAction = Extract<MessagePresentationAction, { type: "approval" }>;
|
||||
type DiscordApprovalAction = Extract<MessagePresentationAction, { type: "approval" }>;
|
||||
|
||||
const DISCORD_APPROVAL_CUSTOM_ID_MAX_CHARS = 100;
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
createDiscordNativeApprovalAdapter,
|
||||
getDiscordApprovalCapability,
|
||||
shouldHandleDiscordApprovalRequest,
|
||||
} from "./approval-native.js";
|
||||
import { shouldHandleDiscordApprovalRequest } from "./approval-shared.js";
|
||||
|
||||
const STORE_PATH = path.join(os.tmpdir(), "openclaw-discord-approval-native-test.json");
|
||||
const NATIVE_APPROVAL_CFG = {
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
normalizeLowercaseStringOrEmpty,
|
||||
normalizeOptionalString,
|
||||
} from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
export { shouldHandleDiscordApprovalRequest } from "./approval-shared.js";
|
||||
import { listDiscordAccountIds, resolveDiscordAccount } from "./accounts.js";
|
||||
import {
|
||||
createChannelApproverDmTargetResolver,
|
||||
@@ -23,16 +22,6 @@ import {
|
||||
isDiscordExecApprovalClientEnabled,
|
||||
} from "./exec-approvals.js";
|
||||
|
||||
// Legacy export kept for monitor test/support surfaces; native routing now uses
|
||||
// the shared session-conversation fallback helper instead.
|
||||
export function extractDiscordChannelId(sessionKey?: string | null): string | null {
|
||||
if (!sessionKey) {
|
||||
return null;
|
||||
}
|
||||
const match = sessionKey.match(/discord:(?:channel|group):(\d+)/);
|
||||
return match?.[1] ?? null;
|
||||
}
|
||||
|
||||
function extractDiscordSessionKind(sessionKey?: string | null): "channel" | "group" | "dm" | null {
|
||||
if (!sessionKey) {
|
||||
return null;
|
||||
|
||||
@@ -64,11 +64,18 @@ describe("discord doctor", () => {
|
||||
work: {
|
||||
streaming: {
|
||||
mode: "off",
|
||||
chunkMode: "newline",
|
||||
block: {
|
||||
enabled: true,
|
||||
coalesce: {
|
||||
idleMs: 250,
|
||||
},
|
||||
},
|
||||
preview: {
|
||||
chunk: {
|
||||
minChars: 120,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -80,6 +87,7 @@ describe("discord doctor", () => {
|
||||
"Moved channels.discord.draftChunk → channels.discord.streaming.preview.chunk.",
|
||||
"Moved channels.discord.accounts.work.streaming (boolean) → channels.discord.accounts.work.streaming.mode (off).",
|
||||
"Moved channels.discord.accounts.work.blockStreamingCoalesce → channels.discord.accounts.work.streaming.block.coalesce.",
|
||||
"Copied flat channels.discord delivery keys into channels.discord.accounts.work.streaming to keep inherited settings while migrating flat streaming keys.",
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -25,15 +25,6 @@ export async function editWebhookMessage(
|
||||
: await rest.patch(Routes.webhookMessage(applicationId, token, messageId), data);
|
||||
}
|
||||
|
||||
export async function deleteWebhookMessage(
|
||||
rest: RequestClient,
|
||||
applicationId: string,
|
||||
token: string,
|
||||
messageId: string,
|
||||
): Promise<unknown> {
|
||||
return await rest.delete(Routes.webhookMessage(applicationId, token, messageId));
|
||||
}
|
||||
|
||||
export async function getWebhookMessage(
|
||||
rest: RequestClient,
|
||||
applicationId: string,
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
createUserDmChannel,
|
||||
deleteChannelMessage,
|
||||
deleteOwnMessageReaction,
|
||||
deleteWebhookMessage,
|
||||
editApplicationCommand,
|
||||
editWebhookMessage,
|
||||
getCurrentUser,
|
||||
@@ -207,13 +206,7 @@ describe("Discord REST API helpers", () => {
|
||||
});
|
||||
|
||||
it("routes interaction webhook helpers through the typed REST client", async () => {
|
||||
const rest = createFakeRestClient([
|
||||
{ ok: true },
|
||||
{ id: "m1" },
|
||||
{ id: "m2" },
|
||||
{ id: "m3" },
|
||||
undefined,
|
||||
]);
|
||||
const rest = createFakeRestClient([{ ok: true }, { id: "m1" }, { id: "m2" }, { id: "m3" }]);
|
||||
const query = { wait: "true" };
|
||||
|
||||
await expect(createInteractionCallback(rest, "i1", "itoken", { type: 5 })).resolves.toEqual({
|
||||
@@ -226,8 +219,6 @@ describe("Discord REST API helpers", () => {
|
||||
await expect(
|
||||
editWebhookMessage(rest, "app1", "wtoken", "m1", { body: { content: "updated" } }),
|
||||
).resolves.toEqual({ id: "m3" });
|
||||
await deleteWebhookMessage(rest, "app1", "wtoken", "m1");
|
||||
|
||||
expect(rest.calls).toEqual([
|
||||
{
|
||||
method: "POST",
|
||||
@@ -246,7 +237,6 @@ describe("Discord REST API helpers", () => {
|
||||
path: Routes.webhookMessage("app1", "wtoken", "m1"),
|
||||
data: { body: { content: "updated" } },
|
||||
},
|
||||
{ method: "DELETE", path: Routes.webhookMessage("app1", "wtoken", "m1") },
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ export {
|
||||
export {
|
||||
createInteractionCallback,
|
||||
createWebhookMessage,
|
||||
deleteWebhookMessage,
|
||||
editWebhookMessage,
|
||||
getWebhookMessage,
|
||||
} from "./api.interactions.js";
|
||||
|
||||
@@ -10,7 +10,7 @@ import { dispatchInteraction } from "./interaction-dispatch.js";
|
||||
import { RequestClient, type RequestClientOptions } from "./rest.js";
|
||||
import type { Guild, GuildMember, Message, User } from "./structures.js";
|
||||
|
||||
export interface Route {
|
||||
interface Route {
|
||||
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
||||
path: `/${string}`;
|
||||
handler(req: Request, ctx?: Context): Response | Promise<Response>;
|
||||
@@ -18,7 +18,7 @@ export interface Route {
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export interface Context {
|
||||
interface Context {
|
||||
waitUntil?(promise: Promise<unknown>): void;
|
||||
env?: unknown;
|
||||
}
|
||||
|
||||
@@ -451,4 +451,3 @@ function stableCommandSetHash(commands: SerializedCommand[]): string {
|
||||
);
|
||||
return createHash("sha256").update(JSON.stringify(stable)).digest("hex");
|
||||
}
|
||||
export { testing as __testing };
|
||||
|
||||
@@ -9,7 +9,7 @@ import type { BaseMessageInteractiveComponent } from "./components.js";
|
||||
import type { AutocompleteInteraction, CommandInteraction } from "./interactions.js";
|
||||
|
||||
type ConditionalCommandOption = (interaction: unknown) => boolean;
|
||||
export type CommandOption = Record<string, unknown> & {
|
||||
type CommandOption = Record<string, unknown> & {
|
||||
name: string;
|
||||
description?: string;
|
||||
type: ApplicationCommandOptionType;
|
||||
|
||||
@@ -11,7 +11,7 @@ export type ComponentData<
|
||||
> = {
|
||||
[K in T]: ComponentParserResult["data"][K];
|
||||
};
|
||||
export type ConditionalComponentOption = (interaction: BaseComponentInteraction) => boolean;
|
||||
type ConditionalComponentOption = (interaction: BaseComponentInteraction) => boolean;
|
||||
|
||||
export function parseCustomId(id: string): ComponentParserResult {
|
||||
const [rawKeyValue, ...parts] = id.split(";");
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
// Discord plugin module implements components behavior.
|
||||
export {
|
||||
BaseComponent,
|
||||
BaseMessageInteractiveComponent,
|
||||
BaseModalComponent,
|
||||
clean,
|
||||
colorToNumber,
|
||||
parseCustomId,
|
||||
type ComponentData,
|
||||
type ComponentParserResult,
|
||||
type ConditionalComponentOption,
|
||||
} from "./components.base.js";
|
||||
export {
|
||||
AnySelectMenu,
|
||||
Button,
|
||||
ChannelSelectMenu,
|
||||
Container,
|
||||
|
||||
@@ -37,9 +37,6 @@ import {
|
||||
type StructureClient,
|
||||
} from "./structures.js";
|
||||
|
||||
export { OptionsHandler } from "./interaction-options.js";
|
||||
export { ModalFields } from "./modal-fields.js";
|
||||
|
||||
type InteractionClient = StructureClient & {
|
||||
options: { clientId: string };
|
||||
componentHandler: {
|
||||
|
||||
@@ -26,7 +26,7 @@ import { isDiscordRateLimitBody } from "./schemas.js";
|
||||
export { DiscordError, isUnknownDiscordVoiceStateError, RateLimitError } from "./rest-errors.js";
|
||||
|
||||
type RuntimeProfile = "serverless" | "persistent";
|
||||
export type RequestPriority = RestRequestPriority;
|
||||
type RequestPriority = RestRequestPriority;
|
||||
type RequestSchedulerOptions = {
|
||||
lanes?: Partial<
|
||||
Record<RequestPriority, { maxQueueSize?: number; staleAfterMs?: number; weight?: number }>
|
||||
|
||||
@@ -2,12 +2,7 @@
|
||||
export const AGENT_BUTTON_KEY = "agent";
|
||||
export const AGENT_SELECT_KEY = "agentsel";
|
||||
|
||||
export {
|
||||
ackComponentInteraction,
|
||||
resolveAgentComponentRoute,
|
||||
resolveComponentInteractionContext,
|
||||
resolveDiscordChannelContext,
|
||||
} from "./agent-components-context.js";
|
||||
export { ackComponentInteraction, resolveAgentComponentRoute } from "./agent-components-context.js";
|
||||
export {
|
||||
ensureAgentComponentInteractionAllowed,
|
||||
ensureComponentUserAllowed,
|
||||
|
||||
@@ -114,7 +114,7 @@ async function runAgentSystemControlInteraction(params: AgentSystemControlParams
|
||||
});
|
||||
}
|
||||
|
||||
export class AgentComponentButton extends Button {
|
||||
class AgentComponentButton extends Button {
|
||||
override label = AGENT_BUTTON_KEY;
|
||||
customId = `${AGENT_BUTTON_KEY}:seed=1`;
|
||||
override style = ButtonStyle.Primary;
|
||||
@@ -142,7 +142,7 @@ export class AgentComponentButton extends Button {
|
||||
}
|
||||
}
|
||||
|
||||
export class AgentSelectMenu extends StringSelectMenu {
|
||||
class AgentSelectMenu extends StringSelectMenu {
|
||||
customId = `${AGENT_SELECT_KEY}:seed=1`;
|
||||
options: APIStringSelectComponent["options"] = [];
|
||||
private ctx: AgentComponentContext;
|
||||
|
||||
@@ -17,14 +17,6 @@ import {
|
||||
type DiscordComponentControlHandlers,
|
||||
} from "./agent-components.wildcard-controls.js";
|
||||
|
||||
export { resolveDiscordComponentOriginatingTo } from "./agent-components.dispatch.js";
|
||||
export {
|
||||
AgentComponentButton,
|
||||
AgentSelectMenu,
|
||||
createAgentComponentButton,
|
||||
createAgentSelectMenu,
|
||||
} from "./agent-components.system-controls.js";
|
||||
|
||||
type ComponentFactory = (ctx: AgentComponentContext) => BaseMessageInteractiveComponent;
|
||||
|
||||
function bindDiscordComponentControl<T extends BaseMessageInteractiveComponent>(
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import type { ApprovalResolveResult } from "openclaw/plugin-sdk/approval-gateway-runtime";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { buildExecApprovalCustomId, parseExecApprovalData } from "../approval-custom-id.js";
|
||||
import { parseCustomId, type ButtonInteraction, type ComponentData } from "../internal/discord.js";
|
||||
|
||||
const resolveApprovalOverGatewayMock = vi.hoisted(() => vi.fn());
|
||||
@@ -15,13 +16,7 @@ vi.mock("openclaw/plugin-sdk/approval-gateway-runtime", async (importOriginal) =
|
||||
};
|
||||
});
|
||||
|
||||
import {
|
||||
ExecApprovalButton,
|
||||
buildExecApprovalCustomId,
|
||||
createDiscordExecApprovalButtonContext,
|
||||
extractDiscordChannelId,
|
||||
parseExecApprovalData,
|
||||
} from "./exec-approvals.js";
|
||||
import { ExecApprovalButton, createDiscordExecApprovalButtonContext } from "./exec-approvals.js";
|
||||
|
||||
function buildConfig(
|
||||
execApprovals?: NonNullable<NonNullable<OpenClawConfig["channels"]>["discord"]>["execApprovals"],
|
||||
@@ -93,13 +88,6 @@ describe("discord exec approval monitor helpers", () => {
|
||||
expect(parseExecApprovalData({ kind: "plugin", action: "deny" } as ComponentData)).toBeNull();
|
||||
});
|
||||
|
||||
it("extracts discord channel ids from session keys", () => {
|
||||
expect(extractDiscordChannelId("agent:main:discord:channel:123456789")).toBe("123456789");
|
||||
expect(extractDiscordChannelId("agent:main:discord:group:222333444")).toBe("222333444");
|
||||
expect(extractDiscordChannelId("agent:main:telegram:channel:123456789")).toBeNull();
|
||||
expect(extractDiscordChannelId("")).toBeNull();
|
||||
});
|
||||
|
||||
it("rejects invalid approval button payloads", async () => {
|
||||
const interaction = createInteraction();
|
||||
const button = new ExecApprovalButton({
|
||||
|
||||
@@ -10,7 +10,7 @@ import type {
|
||||
DiscordExecApprovalConfig,
|
||||
OpenClawConfig,
|
||||
} from "openclaw/plugin-sdk/config-contracts";
|
||||
import { buildExecApprovalCustomId, parseExecApprovalData } from "../approval-custom-id.js";
|
||||
import { parseExecApprovalData } from "../approval-custom-id.js";
|
||||
import {
|
||||
DISCORD_APPROVAL_ALLOWED_MENTIONS,
|
||||
formatDiscordApprovalDisplayValue,
|
||||
@@ -26,9 +26,6 @@ import {
|
||||
type MessagePayloadObject,
|
||||
} from "../internal/discord.js";
|
||||
|
||||
export { buildExecApprovalCustomId, parseExecApprovalData };
|
||||
export { extractDiscordChannelId } from "../approval-native.js";
|
||||
|
||||
type ExecApprovalButtonContext = {
|
||||
getApprovers: () => string[];
|
||||
resolveApproval: (
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
import { EventEmitter } from "node:events";
|
||||
import { beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import { DISCORD_GATEWAY_TRANSPORT_ACTIVITY_EVENT } from "./gateway-handle.js";
|
||||
import {
|
||||
parseDiscordGatewayInfoBody,
|
||||
resolveDiscordGatewayInfoTimeoutMs,
|
||||
} from "./gateway-metadata.js";
|
||||
|
||||
const { GatewayIntents, GatewayPlugin } = vi.hoisted(() => {
|
||||
const GatewayIntentsLocal = {
|
||||
@@ -73,17 +77,11 @@ vi.mock("openclaw/plugin-sdk/runtime-env", () => ({
|
||||
|
||||
describe("createDiscordGatewayPlugin", () => {
|
||||
let createDiscordGatewayPlugin: typeof import("./gateway-plugin.js").createDiscordGatewayPlugin;
|
||||
let parseDiscordGatewayInfoBody: typeof import("./gateway-plugin.js").parseDiscordGatewayInfoBody;
|
||||
let resolveDiscordGatewayIntents: typeof import("./gateway-plugin.js").resolveDiscordGatewayIntents;
|
||||
let resolveDiscordGatewayInfoTimeoutMs: typeof import("./gateway-plugin.js").resolveDiscordGatewayInfoTimeoutMs;
|
||||
|
||||
beforeAll(async () => {
|
||||
({
|
||||
createDiscordGatewayPlugin,
|
||||
parseDiscordGatewayInfoBody,
|
||||
resolveDiscordGatewayIntents,
|
||||
resolveDiscordGatewayInfoTimeoutMs,
|
||||
} = await import("./gateway-plugin.js"));
|
||||
({ createDiscordGatewayPlugin, resolveDiscordGatewayIntents } =
|
||||
await import("./gateway-plugin.js"));
|
||||
});
|
||||
|
||||
function createPlugin(
|
||||
|
||||
@@ -27,11 +27,6 @@ import {
|
||||
type DiscordGatewayFetchInit,
|
||||
} from "./gateway-metadata.js";
|
||||
|
||||
export {
|
||||
parseDiscordGatewayInfoBody,
|
||||
resolveDiscordGatewayInfoTimeoutMs,
|
||||
} from "./gateway-metadata.js";
|
||||
|
||||
const DISCORD_GATEWAY_HANDSHAKE_TIMEOUT_MS = 30_000;
|
||||
const DISCORD_GATEWAY_POLICY_VIOLATION_CLOSE_CODE = 1008;
|
||||
const DISCORD_GATEWAY_WS_RECEIVER_LIMIT_CODE = "WS_ERR_TOO_MANY_BUFFERED_PARTS";
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { APIAttachment, APIStickerItem } from "discord-api-types/v10";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import type { Message } from "../internal/discord.js";
|
||||
|
||||
export type DiscordSnapshotAuthor = {
|
||||
type DiscordSnapshotAuthor = {
|
||||
id?: string | null;
|
||||
username?: string | null;
|
||||
discriminator?: string | null;
|
||||
@@ -21,13 +21,13 @@ export type DiscordSnapshotMessage = {
|
||||
author?: DiscordSnapshotAuthor | null;
|
||||
};
|
||||
|
||||
export type DiscordMessageSnapshot = {
|
||||
type DiscordMessageSnapshot = {
|
||||
message?: DiscordSnapshotMessage | null;
|
||||
};
|
||||
|
||||
const FORWARD_MESSAGE_REFERENCE_TYPE = 1;
|
||||
|
||||
export function normalizeDiscordStickerItems(value: unknown): APIStickerItem[] {
|
||||
function normalizeDiscordStickerItems(value: unknown): APIStickerItem[] {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ export type DiscordMediaInfo = {
|
||||
placeholder: string;
|
||||
};
|
||||
|
||||
export type DiscordMediaResolveOptions = {
|
||||
type DiscordMediaResolveOptions = {
|
||||
fetchImpl?: FetchLike;
|
||||
ssrfPolicy?: SsrFPolicy;
|
||||
readIdleTimeoutMs?: number;
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
} from "discord-api-types/v10";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { ChannelType, type Client, type Message } from "../internal/discord.js";
|
||||
import { resetDiscordChannelInfoCacheForTest } from "./message-channel-info.js";
|
||||
|
||||
const readRemoteMediaBuffer = vi.fn();
|
||||
const saveMediaBuffer = vi.fn();
|
||||
@@ -46,7 +47,6 @@ vi.mock("openclaw/plugin-sdk/runtime-env", async () => {
|
||||
};
|
||||
});
|
||||
|
||||
let resetDiscordChannelInfoCacheForTest: typeof import("./message-utils.js").resetDiscordChannelInfoCacheForTest;
|
||||
let resolveDiscordChannelInfo: typeof import("./message-utils.js").resolveDiscordChannelInfo;
|
||||
let resolveDiscordMessageChannelId: typeof import("./message-utils.js").resolveDiscordMessageChannelId;
|
||||
let resolveDiscordMessageText: typeof import("./message-utils.js").resolveDiscordMessageText;
|
||||
@@ -56,7 +56,6 @@ let resolveReferencedReplyMediaList: typeof import("./message-utils.js").resolve
|
||||
|
||||
beforeAll(async () => {
|
||||
({
|
||||
resetDiscordChannelInfoCacheForTest,
|
||||
resolveDiscordChannelInfo,
|
||||
resolveDiscordMessageChannelId,
|
||||
resolveDiscordMessageText,
|
||||
|
||||
@@ -1,32 +1,17 @@
|
||||
// Discord helper module supports message utils behavior.
|
||||
export {
|
||||
resetDiscordChannelInfoCacheForTest,
|
||||
resolveDiscordChannelInfo,
|
||||
resolveDiscordMessageChannelId,
|
||||
type DiscordChannelInfo,
|
||||
type DiscordChannelInfoClient,
|
||||
} from "./message-channel-info.js";
|
||||
export {
|
||||
hasDiscordMessageStickers,
|
||||
normalizeDiscordMessageSnapshots,
|
||||
normalizeDiscordStickerItems,
|
||||
resolveDiscordMessageSnapshots,
|
||||
resolveDiscordMessageStickers,
|
||||
resolveDiscordReferencedForwardMessage,
|
||||
resolveDiscordReferencedReplyMessage,
|
||||
resolveDiscordSnapshotStickers,
|
||||
type DiscordMessageSnapshot,
|
||||
type DiscordSnapshotAuthor,
|
||||
type DiscordSnapshotMessage,
|
||||
} from "./message-forwarded.js";
|
||||
export { hasDiscordMessageStickers } from "./message-forwarded.js";
|
||||
export {
|
||||
buildDiscordMediaPayload,
|
||||
buildDiscordMediaPlaceholder,
|
||||
resolveForwardedMediaList,
|
||||
resolveMediaList,
|
||||
resolveReferencedReplyMediaList,
|
||||
type DiscordMediaInfo,
|
||||
type DiscordMediaResolveOptions,
|
||||
} from "./message-media.js";
|
||||
export {
|
||||
resolveDiscordEmbedText,
|
||||
|
||||
@@ -73,7 +73,7 @@ export type DiscordModelPickerState = {
|
||||
* select cap. Below this threshold the user gets the existing flat list +
|
||||
* prev/next behavior unchanged.
|
||||
*/
|
||||
export const DISCORD_MODEL_PICKER_BUCKET_THRESHOLD = DISCORD_COMPONENT_MAX_SELECT_OPTIONS;
|
||||
const DISCORD_MODEL_PICKER_BUCKET_THRESHOLD = DISCORD_COMPONENT_MAX_SELECT_OPTIONS;
|
||||
|
||||
/** Target items per alpha bucket. Discord caps selects at 25 options. */
|
||||
export const DISCORD_MODEL_PICKER_BUCKET_TARGET_SIZE = 20;
|
||||
|
||||
@@ -63,13 +63,13 @@ type DiscordModelPickerRenderShellParams = {
|
||||
trailingRows?: DiscordModelPickerRow[];
|
||||
};
|
||||
|
||||
export type DiscordModelPickerRenderedView = {
|
||||
type DiscordModelPickerRenderedView = {
|
||||
layout: DiscordModelPickerLayout;
|
||||
content?: string;
|
||||
components: TopLevelComponents[];
|
||||
};
|
||||
|
||||
export type DiscordModelPickerProviderViewParams = {
|
||||
type DiscordModelPickerProviderViewParams = {
|
||||
command: DiscordModelPickerCommandContext;
|
||||
userId: string;
|
||||
data: ModelsProviderData;
|
||||
@@ -79,7 +79,7 @@ export type DiscordModelPickerProviderViewParams = {
|
||||
layout?: DiscordModelPickerLayout;
|
||||
};
|
||||
|
||||
export type DiscordModelPickerModelViewParams = {
|
||||
type DiscordModelPickerModelViewParams = {
|
||||
command: DiscordModelPickerCommandContext;
|
||||
userId: string;
|
||||
data: ModelsProviderData;
|
||||
@@ -877,7 +877,7 @@ export function renderDiscordModelPickerModelsView(
|
||||
});
|
||||
}
|
||||
|
||||
export type DiscordModelPickerRecentsViewParams = {
|
||||
type DiscordModelPickerRecentsViewParams = {
|
||||
command: DiscordModelPickerCommandContext;
|
||||
userId: string;
|
||||
data: ModelsProviderData;
|
||||
|
||||
@@ -16,12 +16,12 @@ import {
|
||||
resetDiscordComponentRuntimeMocks,
|
||||
upsertPairingRequestMock,
|
||||
} from "../test-support/component-runtime.js";
|
||||
import { resolveComponentInteractionContext } from "./agent-components-helpers.js";
|
||||
import { resolveComponentInteractionContext } from "./agent-components-context.js";
|
||||
import { resolveDiscordComponentOriginatingTo } from "./agent-components.dispatch.js";
|
||||
import {
|
||||
createAgentComponentButton,
|
||||
createAgentSelectMenu,
|
||||
resolveDiscordComponentOriginatingTo,
|
||||
} from "./agent-components.js";
|
||||
} from "./agent-components.system-controls.js";
|
||||
|
||||
describe("agent components", () => {
|
||||
const defaultDmSessionKey = buildAgentSessionKey({
|
||||
|
||||
@@ -34,7 +34,7 @@ function createCommandArgsWithValue(params: { argName: string; value: string }):
|
||||
return { values };
|
||||
}
|
||||
|
||||
export function buildDiscordCommandArgCustomId(params: {
|
||||
function buildDiscordCommandArgCustomId(params: {
|
||||
command: string;
|
||||
arg: string;
|
||||
value: string;
|
||||
@@ -71,7 +71,7 @@ function parseDiscordCommandArgData(
|
||||
};
|
||||
}
|
||||
|
||||
export async function handleDiscordCommandArgInteraction(params: {
|
||||
async function handleDiscordCommandArgInteraction(params: {
|
||||
interaction: ButtonInteraction;
|
||||
data: ComponentData;
|
||||
ctx: DiscordCommandArgContext;
|
||||
|
||||
@@ -11,7 +11,7 @@ import type { ThreadBindingManager } from "./thread-bindings.js";
|
||||
|
||||
type DiscordConfig = NonNullable<OpenClawConfig["channels"]>["discord"];
|
||||
|
||||
export type DispatchDiscordCommandInteractionParams = {
|
||||
type DispatchDiscordCommandInteractionParams = {
|
||||
interaction: CommandInteraction | ButtonInteraction | StringSelectMenuInteraction;
|
||||
prompt: string;
|
||||
command: ChatCommandDefinition;
|
||||
|
||||
@@ -302,7 +302,7 @@ function resolveDiscordModelPickerSubmissionRuntime(params: {
|
||||
);
|
||||
}
|
||||
|
||||
export async function handleDiscordModelPickerInteraction(params: {
|
||||
async function handleDiscordModelPickerInteraction(params: {
|
||||
interaction: ButtonInteraction | StringSelectMenuInteraction;
|
||||
data: ComponentData;
|
||||
ctx: DiscordModelPickerContext;
|
||||
|
||||
@@ -1,27 +1,19 @@
|
||||
// Discord plugin module implements native command ui behavior.
|
||||
export {
|
||||
buildDiscordCommandArgCustomId,
|
||||
buildDiscordCommandArgMenu,
|
||||
createDiscordCommandArgFallbackButton,
|
||||
handleDiscordCommandArgInteraction,
|
||||
} from "./native-command-arg-ui.js";
|
||||
export {
|
||||
createDiscordModelPickerFallbackButton,
|
||||
createDiscordModelPickerFallbackSelect,
|
||||
handleDiscordModelPickerInteraction,
|
||||
} from "./native-command-model-picker-interaction.js";
|
||||
export {
|
||||
replyWithDiscordModelPickerProviders,
|
||||
resolveDiscordNativeChoiceContext,
|
||||
shouldOpenDiscordModelPickerFromCommand,
|
||||
} from "./native-command-model-picker-ui.js";
|
||||
export type {
|
||||
DispatchDiscordCommandInteraction,
|
||||
DispatchDiscordCommandInteractionParams,
|
||||
DispatchDiscordCommandInteractionResult,
|
||||
} from "./native-command-dispatch.js";
|
||||
export type { DispatchDiscordCommandInteraction } from "./native-command-dispatch.js";
|
||||
export type {
|
||||
DiscordCommandArgContext,
|
||||
DiscordModelPickerContext,
|
||||
SafeDiscordInteractionCall,
|
||||
} from "./native-command-ui.types.js";
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
import * as commandTextModule from "openclaw/plugin-sdk/text-utility-runtime";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { defineThrowingDiscordChannelGetter } from "../test-support/partial-channel.js";
|
||||
import { resolveDiscordChannelContext } from "./agent-components-helpers.js";
|
||||
import { resolveDiscordChannelContext } from "./agent-components-context.js";
|
||||
import * as modelPickerPreferencesModule from "./model-picker-preferences.js";
|
||||
import * as modelPickerModule from "./model-picker.state.js";
|
||||
import { createModelsProviderData as createBaseModelsProviderData } from "./model-picker.test-utils.js";
|
||||
|
||||
@@ -56,4 +56,3 @@ export const testing = {
|
||||
return previous;
|
||||
},
|
||||
};
|
||||
export { testing as __testing };
|
||||
|
||||
@@ -85,7 +85,7 @@ import { resolveDiscordSenderIdentity } from "./sender-identity.js";
|
||||
import type { ThreadBindingManager } from "./thread-bindings.js";
|
||||
|
||||
const log = createSubsystemLogger("discord/native-command");
|
||||
export { testing, testing as __testing } from "./native-command.runtime.js";
|
||||
export { testing } from "./native-command.runtime.js";
|
||||
|
||||
export function createDiscordNativeCommand(params: {
|
||||
command: NativeCommandSpec;
|
||||
|
||||
@@ -688,4 +688,3 @@ export const testing = {
|
||||
};
|
||||
|
||||
export const resolveDiscordRuntimeGroupPolicy = resolveOpenProviderRuntimeGroupPolicy;
|
||||
export { testing as __testing };
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { ChannelType } from "../internal/discord.js";
|
||||
import { createPartialDiscordChannelWithThrowingGetters } from "../test-support/partial-channel.js";
|
||||
import { resetDiscordChannelInfoCacheForTest } from "./message-utils.js";
|
||||
import { resetDiscordChannelInfoCacheForTest } from "./message-channel-info.js";
|
||||
import { resolveDiscordThreadParentInfo } from "./threading.js";
|
||||
|
||||
describe("resolveDiscordThreadParentInfo", () => {
|
||||
|
||||
@@ -13,8 +13,7 @@ const DISCORD_MESSAGE_COMPONENT_LIMIT = 40;
|
||||
const DISCORD_TEXT_DISPLAY_LIMIT = 2000;
|
||||
const DISCORD_CONTEXT_PREFIX_LENGTH = Array.from("-# ").length;
|
||||
|
||||
export const DISCORD_PRESENTATION_TEXT_LIMIT =
|
||||
DISCORD_TEXT_DISPLAY_LIMIT - DISCORD_CONTEXT_PREFIX_LENGTH;
|
||||
const DISCORD_PRESENTATION_TEXT_LIMIT = DISCORD_TEXT_DISPLAY_LIMIT - DISCORD_CONTEXT_PREFIX_LENGTH;
|
||||
|
||||
export const DISCORD_PRESENTATION_CAPABILITIES = {
|
||||
supported: true,
|
||||
|
||||
@@ -47,7 +47,7 @@ const DISCORD_PRECONNECT_ERROR_CODES = new Set([
|
||||
]);
|
||||
const log = createSubsystemLogger("discord/retry");
|
||||
|
||||
export type DiscordRetrySafety = "idempotent" | "nonce-protected-create" | "non-idempotent-create";
|
||||
type DiscordRetrySafety = "idempotent" | "nonce-protected-create" | "non-idempotent-create";
|
||||
|
||||
export type DiscordRetryRunner = <T>(
|
||||
fn: () => Promise<T>,
|
||||
|
||||
@@ -9,10 +9,10 @@ import {
|
||||
type TopLevelComponents,
|
||||
} from "./internal/discord.js";
|
||||
|
||||
export const SUPPRESS_EMBEDS_FLAG = MessageFlags.SuppressEmbeds;
|
||||
const SUPPRESS_EMBEDS_FLAG = MessageFlags.SuppressEmbeds;
|
||||
export const SUPPRESS_NOTIFICATIONS_FLAG = MessageFlags.SuppressNotifications;
|
||||
|
||||
export type DiscordSendComponentFactory = (text: string) => TopLevelComponents[];
|
||||
type DiscordSendComponentFactory = (text: string) => TopLevelComponents[];
|
||||
export type DiscordSendComponents = TopLevelComponents[] | DiscordSendComponentFactory;
|
||||
export type DiscordSendEmbeds = Array<APIEmbed | Embed>;
|
||||
export type DiscordAllowedMentions = APIAllowedMentions;
|
||||
@@ -51,7 +51,7 @@ export function resolveDiscordSendEmbeds(params: {
|
||||
return normalizeDiscordEmbeds(params.embeds);
|
||||
}
|
||||
|
||||
export function buildDiscordMessagePayload(params: {
|
||||
function buildDiscordMessagePayload(params: {
|
||||
text: string;
|
||||
components?: TopLevelComponents[];
|
||||
embeds?: Embed[];
|
||||
|
||||
@@ -45,16 +45,13 @@ const DISCORD_UPLOAD_TOO_LARGE_NOTICE =
|
||||
type DiscordRequest = DiscordRetryRunner;
|
||||
|
||||
export {
|
||||
buildDiscordMessagePayload,
|
||||
buildDiscordMessageRequest,
|
||||
createDiscordMessageNonce,
|
||||
resolveDiscordMessageFlags,
|
||||
resolveDiscordSendComponents,
|
||||
resolveDiscordSendEmbeds,
|
||||
stripUndefinedFields,
|
||||
SUPPRESS_EMBEDS_FLAG,
|
||||
SUPPRESS_NOTIFICATIONS_FLAG,
|
||||
type DiscordSendComponentFactory,
|
||||
type DiscordAllowedMentions,
|
||||
type DiscordSendComponents,
|
||||
type DiscordSendEmbeds,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Slack tests cover approval auth plugin behavior.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { isSlackApprovalAuthorizedSender, slackApprovalAuth } from "./approval-auth.js";
|
||||
import { isSlackApprovalAuthorizedSender } from "./approval-auth.js";
|
||||
|
||||
describe("slackApprovalAuth", () => {
|
||||
describe("isSlackApprovalAuthorizedSender", () => {
|
||||
it("authorizes general Slack approvers from allowFrom and defaultTo", () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
@@ -15,65 +15,12 @@ describe("slackApprovalAuth", () => {
|
||||
},
|
||||
};
|
||||
|
||||
expect(
|
||||
slackApprovalAuth.authorizeActorAction({
|
||||
cfg,
|
||||
senderId: "U123OWNER",
|
||||
action: "approve",
|
||||
approvalKind: "exec",
|
||||
}),
|
||||
).toEqual({ authorized: true });
|
||||
|
||||
expect(
|
||||
slackApprovalAuth.authorizeActorAction({
|
||||
cfg,
|
||||
senderId: "u123owner",
|
||||
action: "approve",
|
||||
approvalKind: "plugin",
|
||||
}),
|
||||
).toEqual({ authorized: true });
|
||||
|
||||
expect(
|
||||
slackApprovalAuth.authorizeActorAction({
|
||||
cfg,
|
||||
senderId: "U345DEFAULT",
|
||||
action: "approve",
|
||||
approvalKind: "plugin",
|
||||
}),
|
||||
).toEqual({ authorized: true });
|
||||
|
||||
expect(
|
||||
slackApprovalAuth.authorizeActorAction({
|
||||
cfg,
|
||||
senderId: "u345default",
|
||||
action: "approve",
|
||||
approvalKind: "plugin",
|
||||
}),
|
||||
).toEqual({ authorized: true });
|
||||
|
||||
expect(
|
||||
slackApprovalAuth.authorizeActorAction({
|
||||
cfg,
|
||||
senderId: "U999EXEC",
|
||||
action: "approve",
|
||||
approvalKind: "plugin",
|
||||
}),
|
||||
).toEqual({
|
||||
authorized: false,
|
||||
reason: "❌ You are not authorized to approve plugin requests on Slack.",
|
||||
});
|
||||
|
||||
expect(
|
||||
slackApprovalAuth.authorizeActorAction({
|
||||
cfg,
|
||||
senderId: "U999ATTACKER",
|
||||
action: "approve",
|
||||
approvalKind: "exec",
|
||||
}),
|
||||
).toEqual({
|
||||
authorized: false,
|
||||
reason: "❌ You are not authorized to approve exec requests on Slack.",
|
||||
});
|
||||
for (const senderId of ["U123OWNER", "u123owner", "U345DEFAULT", "u345default"]) {
|
||||
expect(isSlackApprovalAuthorizedSender({ cfg, senderId })).toBe(true);
|
||||
}
|
||||
for (const senderId of ["U999EXEC", "U999ATTACKER"]) {
|
||||
expect(isSlackApprovalAuthorizedSender({ cfg, senderId })).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
it("canonicalizes configured plugin approver ids before matching uppercase senders", () => {
|
||||
@@ -87,14 +34,7 @@ describe("slackApprovalAuth", () => {
|
||||
};
|
||||
|
||||
for (const senderId of ["U123OWNER", "U345DEFAULT"]) {
|
||||
expect(
|
||||
slackApprovalAuth.authorizeActorAction({
|
||||
cfg,
|
||||
senderId,
|
||||
action: "approve",
|
||||
approvalKind: "plugin",
|
||||
}),
|
||||
).toEqual({ authorized: true });
|
||||
expect(isSlackApprovalAuthorizedSender({ cfg, senderId })).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -107,14 +47,6 @@ describe("slackApprovalAuth", () => {
|
||||
},
|
||||
};
|
||||
|
||||
expect(
|
||||
slackApprovalAuth.authorizeActorAction({
|
||||
cfg,
|
||||
senderId: "U123OWNER",
|
||||
action: "approve",
|
||||
approvalKind: "plugin",
|
||||
}),
|
||||
).toEqual({ authorized: true });
|
||||
expect(
|
||||
isSlackApprovalAuthorizedSender({
|
||||
cfg,
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// Slack plugin module implements approval auth behavior.
|
||||
import {
|
||||
createResolvedApproverActionAuthAdapter,
|
||||
resolveApprovalApprovers,
|
||||
} from "openclaw/plugin-sdk/approval-auth-runtime";
|
||||
import { resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
|
||||
import { resolveSlackAccount, resolveSlackAccountAllowFrom } from "./accounts.js";
|
||||
import { normalizeSlackApproverId } from "./exec-approvals.js";
|
||||
@@ -35,9 +32,3 @@ export function isSlackApprovalAuthorizedSender(params: {
|
||||
}
|
||||
return (resolveSlackAccountAllowFrom(params) ?? []).some((entry) => entry.trim() === "*");
|
||||
}
|
||||
|
||||
export const slackApprovalAuth = createResolvedApproverActionAuthAdapter({
|
||||
channelLabel: "Slack",
|
||||
resolveApprovers: ({ cfg, accountId }) => getSlackApprovalApprovers({ cfg, accountId }),
|
||||
normalizeSenderId: (value) => normalizeSlackApproverId(value),
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
} from "./data-visualization.js";
|
||||
import { escapeSlackMrkdwn } from "./monitor/mrkdwn.js";
|
||||
|
||||
export type SlackNativeDataFallbackFormat = "plain" | "mrkdwn-safe";
|
||||
type SlackNativeDataFallbackFormat = "plain" | "mrkdwn-safe";
|
||||
|
||||
type RenderSlackBlockFallbackOptions = {
|
||||
nativeDataFormat?: SlackNativeDataFallbackFormat;
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildSlackBlocksFallbackText, renderSlackBlockFallbackText } from "./blocks-fallback.js";
|
||||
import { parseSlackBlocksInput } from "./blocks-input.js";
|
||||
import {
|
||||
encodeSlackModalPrivateMetadata,
|
||||
parseSlackModalPrivateMetadata,
|
||||
} from "./modal-metadata.js";
|
||||
import { parseSlackModalPrivateMetadata } from "./modal-metadata.js";
|
||||
|
||||
describe("buildSlackBlocksFallbackText", () => {
|
||||
it("prefers header text", () => {
|
||||
@@ -280,32 +277,3 @@ describe("parseSlackModalPrivateMetadata", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("encodeSlackModalPrivateMetadata", () => {
|
||||
it("encodes only known non-empty fields", () => {
|
||||
expect(
|
||||
JSON.parse(
|
||||
encodeSlackModalPrivateMetadata({
|
||||
sessionKey: "agent:main:slack:channel:C1",
|
||||
channelId: "",
|
||||
channelType: "im",
|
||||
userId: "U123",
|
||||
pluginInteractiveData: "dean.contract:confirm",
|
||||
}),
|
||||
),
|
||||
).toEqual({
|
||||
sessionKey: "agent:main:slack:channel:C1",
|
||||
channelType: "im",
|
||||
userId: "U123",
|
||||
pluginInteractiveData: "dean.contract:confirm",
|
||||
});
|
||||
});
|
||||
|
||||
it("throws when encoded payload exceeds Slack metadata limit", () => {
|
||||
expect(() =>
|
||||
encodeSlackModalPrivateMetadata({
|
||||
sessionKey: `agent:main:${"x".repeat(4000)}`,
|
||||
}),
|
||||
).toThrow(/cannot exceed 3000 chars/i);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
import { escapeSlackMrkdwn } from "./monitor/mrkdwn.js";
|
||||
import { renderSlackMessagePresentationTableFallbackText } from "./presentation-fallback.js";
|
||||
|
||||
export const SLACK_DATA_TABLE_COLUMNS_MAX = 20;
|
||||
export const SLACK_DATA_TABLE_ROWS_MAX = 100;
|
||||
const SLACK_DATA_TABLE_COLUMNS_MAX = 20;
|
||||
const SLACK_DATA_TABLE_ROWS_MAX = 100;
|
||||
export const SLACK_DATA_TABLE_CELL_CHARACTERS_MAX = 10_000;
|
||||
|
||||
type SlackDataTableRawTextCell = {
|
||||
@@ -22,9 +22,9 @@ type SlackDataTableRawNumberCell = {
|
||||
text: string;
|
||||
};
|
||||
|
||||
export type SlackDataTableCell = SlackDataTableRawTextCell | SlackDataTableRawNumberCell;
|
||||
type SlackDataTableCell = SlackDataTableRawTextCell | SlackDataTableRawNumberCell;
|
||||
|
||||
export type SlackDataTableBlock = Block & {
|
||||
type SlackDataTableBlock = Block & {
|
||||
type: "data_table";
|
||||
caption: string;
|
||||
rows: SlackDataTableCell[][];
|
||||
|
||||
@@ -8,11 +8,11 @@ import {
|
||||
import { escapeSlackMrkdwn } from "./monitor/mrkdwn.js";
|
||||
import { renderSlackMessagePresentationChartFallbackText } from "./presentation-fallback.js";
|
||||
|
||||
export const SLACK_CHART_TITLE_MAX = 50;
|
||||
export const SLACK_CHART_LABEL_MAX = 20;
|
||||
export const SLACK_CHART_AXIS_LABEL_MAX = 50;
|
||||
export const SLACK_CHART_SERIES_MAX = 12;
|
||||
export const SLACK_CHART_DATA_POINTS_MAX = 20;
|
||||
const SLACK_CHART_TITLE_MAX = 50;
|
||||
const SLACK_CHART_LABEL_MAX = 20;
|
||||
const SLACK_CHART_AXIS_LABEL_MAX = 50;
|
||||
const SLACK_CHART_SERIES_MAX = 12;
|
||||
const SLACK_CHART_DATA_POINTS_MAX = 20;
|
||||
// Slack's API rejects a third data_visualization block even though its public
|
||||
// reference does not currently document this per-message subtype limit.
|
||||
export const SLACK_DATA_VISUALIZATION_BLOCKS_MAX = 2;
|
||||
@@ -34,7 +34,7 @@ type SlackSeriesChart = {
|
||||
};
|
||||
};
|
||||
|
||||
export type SlackDataVisualizationBlock = Block & {
|
||||
type SlackDataVisualizationBlock = Block & {
|
||||
type: "data_visualization";
|
||||
title: string;
|
||||
chart: SlackPieChart | SlackSeriesChart;
|
||||
|
||||
@@ -9,8 +9,6 @@ type SlackModalPrivateMetadata = {
|
||||
pluginInteractiveData?: string;
|
||||
};
|
||||
|
||||
const SLACK_PRIVATE_METADATA_MAX = 3000;
|
||||
|
||||
export function parseSlackModalPrivateMetadata(raw: unknown): SlackModalPrivateMetadata {
|
||||
if (typeof raw !== "string" || raw.trim().length === 0) {
|
||||
return {};
|
||||
@@ -28,20 +26,3 @@ export function parseSlackModalPrivateMetadata(raw: unknown): SlackModalPrivateM
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
export function encodeSlackModalPrivateMetadata(input: SlackModalPrivateMetadata): string {
|
||||
const payload: SlackModalPrivateMetadata = {
|
||||
...(input.sessionKey ? { sessionKey: input.sessionKey } : {}),
|
||||
...(input.channelId ? { channelId: input.channelId } : {}),
|
||||
...(input.channelType ? { channelType: input.channelType } : {}),
|
||||
...(input.userId ? { userId: input.userId } : {}),
|
||||
...(input.pluginInteractiveData ? { pluginInteractiveData: input.pluginInteractiveData } : {}),
|
||||
};
|
||||
const encoded = JSON.stringify(payload);
|
||||
if (encoded.length > SLACK_PRIVATE_METADATA_MAX) {
|
||||
throw new Error(
|
||||
`Slack modal private_metadata cannot exceed ${SLACK_PRIVATE_METADATA_MAX} chars`,
|
||||
);
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export type SlackEventScope = {
|
||||
uploadCompletionClient?: WebClient;
|
||||
};
|
||||
|
||||
export type SlackEventScopeResolution =
|
||||
type SlackEventScopeResolution =
|
||||
| { ok: true; scope?: SlackEventScope }
|
||||
| {
|
||||
ok: false;
|
||||
|
||||
@@ -7,8 +7,8 @@ import type { SlackMessageEvent } from "../../types.js";
|
||||
import type { SlackMediaResult } from "../media-types.js";
|
||||
import {
|
||||
discardSlackPreflightMedia,
|
||||
findCaptionlessSlackAudioFile,
|
||||
formatSlackAudioTranscriptForAgent,
|
||||
hasCaptionlessSlackAudio,
|
||||
resolveSlackPreflightAudioTranscript,
|
||||
sendSlackPreflightAudioTranscriptEcho,
|
||||
} from "./preflight-audio.js";
|
||||
@@ -68,15 +68,15 @@ describe("Slack captionless audio preflight", () => {
|
||||
],
|
||||
});
|
||||
|
||||
expect(hasCaptionlessSlackAudio(voiceClip)).toBe(true);
|
||||
expect(hasCaptionlessSlackAudio({ ...voiceClip, text: "typed caption" })).toBe(false);
|
||||
expect(findCaptionlessSlackAudioFile(voiceClip)).toEqual(voiceClip.files?.[0]);
|
||||
expect(findCaptionlessSlackAudioFile({ ...voiceClip, text: "typed caption" })).toBeUndefined();
|
||||
expect(
|
||||
hasCaptionlessSlackAudio(
|
||||
findCaptionlessSlackAudioFile(
|
||||
createSlackMessage({
|
||||
files: [{ id: "F2", name: "screen.mp4", mimetype: "video/mp4" }],
|
||||
}),
|
||||
),
|
||||
).toBe(false);
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("frames machine transcripts as untrusted input without replacing the file placeholder", () => {
|
||||
|
||||
@@ -31,10 +31,6 @@ export function findCaptionlessSlackAudioFile(message: SlackMessageEvent): Slack
|
||||
return message.files?.slice(0, MAX_SLACK_MEDIA_FILES).find(isSlackAudioFile);
|
||||
}
|
||||
|
||||
export function hasCaptionlessSlackAudio(message: SlackMessageEvent): boolean {
|
||||
return Boolean(findCaptionlessSlackAudioFile(message));
|
||||
}
|
||||
|
||||
export function formatSlackAudioTranscriptForAgent(params: {
|
||||
transcript: string;
|
||||
rawBody: string;
|
||||
|
||||
@@ -337,4 +337,3 @@ export function resolveSlackRoutingContext(params: {
|
||||
export const testing = {
|
||||
normalizeSlackRouteBindingConfig,
|
||||
};
|
||||
export { testing as __testing };
|
||||
|
||||
@@ -202,4 +202,3 @@ export const testing = {
|
||||
didSlackPreviewEditApplyAfterError,
|
||||
readSlackMessageAfterEditError,
|
||||
};
|
||||
export { testing as __testing };
|
||||
|
||||
@@ -778,8 +778,6 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
export { isNonRecoverableSlackAuthError } from "./reconnect-policy.js";
|
||||
|
||||
export const resolveSlackRuntimeGroupPolicy = resolveOpenProviderRuntimeGroupPolicy;
|
||||
|
||||
export const testing = {
|
||||
@@ -798,4 +796,3 @@ export const testing = {
|
||||
getSocketEmitter,
|
||||
waitForSlackSocketDisconnect,
|
||||
};
|
||||
export { testing as __testing };
|
||||
|
||||
@@ -276,14 +276,14 @@ export async function deliverReplies(params: {
|
||||
return latestResult;
|
||||
}
|
||||
|
||||
export type SlackRespondFn = (payload: {
|
||||
type SlackRespondFn = (payload: {
|
||||
text: string;
|
||||
blocks?: (Block | KnownBlock)[];
|
||||
mrkdwn?: false;
|
||||
response_type?: "ephemeral" | "in_channel";
|
||||
}) => Promise<unknown>;
|
||||
|
||||
export type SlackResponseUrlBudget = ResponseUrlBudget<Parameters<SlackRespondFn>[0]>;
|
||||
type SlackResponseUrlBudget = ResponseUrlBudget<Parameters<SlackRespondFn>[0]>;
|
||||
|
||||
/**
|
||||
* Compute effective threadTs for a Slack reply based on replyToMode.
|
||||
|
||||
@@ -4,7 +4,7 @@ export type SlackResponseUrlBudget<TPayload> = {
|
||||
remaining: () => number | undefined;
|
||||
};
|
||||
|
||||
export const SLACK_RESPONSE_URL_MAX_CALLS = 5;
|
||||
const SLACK_RESPONSE_URL_MAX_CALLS = 5;
|
||||
|
||||
export class SlackResponseAlreadyReportedError extends Error {}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ export type SlackFormattingDisabledMessage = {
|
||||
mrkdwn: false;
|
||||
};
|
||||
|
||||
export type SlackNativeDataDeliveryPlan = {
|
||||
type SlackNativeDataDeliveryPlan = {
|
||||
accessibilityText: string;
|
||||
fallbackMessages: SlackFormattingDisabledMessage[];
|
||||
skipOriginalBlocks: boolean;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Slack tests cover shared plugin behavior.
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { createSlackPluginBase, setSlackChannelAllowlist, slackConfigAdapter } from "./shared.js";
|
||||
import { setSlackChannelAllowlist } from "./setup-shared.js";
|
||||
import { createSlackPluginBase, slackConfigAdapter } from "./shared.js";
|
||||
|
||||
describe("createSlackPluginBase", () => {
|
||||
it("owns Slack native command name overrides", () => {
|
||||
|
||||
@@ -23,7 +23,7 @@ import { collectRuntimeConfigAssignments, secretTargetRegistryEntries } from "./
|
||||
import { slackSecurityAdapter } from "./security.js";
|
||||
import { SLACK_CHANNEL } from "./setup-shared.js";
|
||||
|
||||
export { setSlackChannelAllowlist, SLACK_CHANNEL } from "./setup-shared.js";
|
||||
export { SLACK_CHANNEL } from "./setup-shared.js";
|
||||
|
||||
export { isSlackPluginAccountConfigured };
|
||||
|
||||
|
||||
@@ -233,7 +233,7 @@ export async function appendSlackStream(params: AppendSlackStreamParams): Promis
|
||||
}
|
||||
|
||||
/** Result of {@link stopSlackStream}. */
|
||||
export type StopSlackStreamResult = {
|
||||
type StopSlackStreamResult = {
|
||||
/**
|
||||
* The Slack `ts` of the finalized streamed message, when `chat.stopStream`
|
||||
* reports it. Used to populate `MessageSentEvent.messageId` for the
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
// Slack tests cover targets plugin behavior.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { canonicalizeSlackApiTargetId } from "./target-parsing.js";
|
||||
import { canonicalizeSlackApiTargetId, slackTargetsMatch } from "./target-parsing.js";
|
||||
import {
|
||||
normalizeSlackMessagingTarget,
|
||||
parseSlackTarget,
|
||||
resolveSlackChannelId,
|
||||
slackContextTargetsMatch,
|
||||
slackTargetsMatch,
|
||||
} from "./targets.js";
|
||||
|
||||
describe("parseSlackTarget", () => {
|
||||
|
||||
@@ -34,5 +34,4 @@ export {
|
||||
parseSlackTarget,
|
||||
resolveSlackChannelId,
|
||||
} from "./target-parsing.js";
|
||||
export { slackTargetsMatch };
|
||||
export type { SlackTarget, SlackTargetKind, SlackTargetParseOptions } from "./target-parsing.js";
|
||||
|
||||
@@ -53,136 +53,59 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
|
||||
"extensions/diffs/src/viewer-assets.ts: resolveViewerRuntimeFileUrl",
|
||||
"extensions/diffs/src/viewer-assets.ts: VIEWER_LOADER_PATH",
|
||||
"extensions/discord/src/actions/runtime.guild.ts: discordGuildActionRuntime",
|
||||
"extensions/discord/src/actions/runtime.messaging.ts: discordMessagingActionRuntime",
|
||||
"extensions/discord/src/actions/runtime.moderation.ts: discordModerationActionRuntime",
|
||||
"extensions/discord/src/approval-custom-id.ts: DiscordApprovalAction",
|
||||
"extensions/discord/src/approval-native.ts: createDiscordNativeApprovalAdapter",
|
||||
"extensions/discord/src/approval-native.ts: extractDiscordChannelId",
|
||||
"extensions/discord/src/approval-native.ts: shouldHandleDiscordApprovalRequest",
|
||||
"extensions/discord/src/audit-core.ts: collectDiscordAuditChannelIdsForGuilds",
|
||||
"extensions/discord/src/chunk.ts: chunkDiscordText",
|
||||
"extensions/discord/src/components-registry.ts: clearDiscordComponentEntries",
|
||||
"extensions/discord/src/components-registry.ts: resolveDiscordComponentEntry",
|
||||
"extensions/discord/src/components-registry.ts: resolveDiscordModalEntry",
|
||||
"extensions/discord/src/directory-cache.ts: resetDiscordDirectoryCacheForTest",
|
||||
"extensions/discord/src/internal/api.interactions.ts: deleteWebhookMessage",
|
||||
"extensions/discord/src/internal/api.ts: deleteWebhookMessage",
|
||||
"extensions/discord/src/internal/client.ts: AnyListener",
|
||||
"extensions/discord/src/internal/client.ts: ClientOptions",
|
||||
"extensions/discord/src/internal/client.ts: ComponentRegistry",
|
||||
"extensions/discord/src/internal/client.ts: Context",
|
||||
"extensions/discord/src/internal/client.ts: Route",
|
||||
"extensions/discord/src/internal/command-deploy.ts: __testing",
|
||||
"extensions/discord/src/internal/command-deploy.ts: testing",
|
||||
"extensions/discord/src/internal/commands.ts: CommandOption",
|
||||
"extensions/discord/src/internal/components.base.ts: ConditionalComponentOption",
|
||||
"extensions/discord/src/internal/components.ts: AnySelectMenu",
|
||||
"extensions/discord/src/internal/components.ts: BaseComponent",
|
||||
"extensions/discord/src/internal/components.ts: BaseModalComponent",
|
||||
"extensions/discord/src/internal/components.ts: clean",
|
||||
"extensions/discord/src/internal/components.ts: colorToNumber",
|
||||
"extensions/discord/src/internal/components.ts: ConditionalComponentOption",
|
||||
"extensions/discord/src/internal/interactions.ts: BaseInteraction",
|
||||
"extensions/discord/src/internal/interactions.ts: ModalFields",
|
||||
"extensions/discord/src/internal/interactions.ts: OptionsHandler",
|
||||
"extensions/discord/src/internal/rest-scheduler.ts: RestSchedulerOptions",
|
||||
"extensions/discord/src/internal/rest.ts: QueuedRequest",
|
||||
"extensions/discord/src/internal/rest.ts: RequestPriority",
|
||||
"extensions/discord/src/mentions.ts: discordTextHasTargetedMention",
|
||||
"extensions/discord/src/monitor.gateway.ts: WaitForDiscordGatewayStopParams",
|
||||
"extensions/discord/src/monitor/agent-components-helpers.ts: resolveComponentInteractionContext",
|
||||
"extensions/discord/src/monitor/agent-components-helpers.ts: resolveDiscordChannelContext",
|
||||
"extensions/discord/src/monitor/agent-components.dispatch.ts: resolveDiscordComponentOriginatingTo",
|
||||
"extensions/discord/src/monitor/agent-components.system-controls.ts: AgentComponentButton",
|
||||
"extensions/discord/src/monitor/agent-components.system-controls.ts: AgentSelectMenu",
|
||||
"extensions/discord/src/monitor/agent-components.ts: AgentComponentButton",
|
||||
"extensions/discord/src/monitor/agent-components.ts: AgentSelectMenu",
|
||||
"extensions/discord/src/monitor/agent-components.ts: createAgentComponentButton",
|
||||
"extensions/discord/src/monitor/agent-components.ts: createAgentSelectMenu",
|
||||
"extensions/discord/src/monitor/agent-components.ts: createDiscordComponentButton",
|
||||
"extensions/discord/src/monitor/agent-components.ts: createDiscordComponentChannelSelect",
|
||||
"extensions/discord/src/monitor/agent-components.ts: createDiscordComponentMentionableSelect",
|
||||
"extensions/discord/src/monitor/agent-components.ts: createDiscordComponentRoleSelect",
|
||||
"extensions/discord/src/monitor/agent-components.ts: createDiscordComponentStringSelect",
|
||||
"extensions/discord/src/monitor/agent-components.ts: createDiscordComponentUserSelect",
|
||||
"extensions/discord/src/monitor/agent-components.ts: resolveDiscordComponentOriginatingTo",
|
||||
"extensions/discord/src/monitor/allow-list.ts: resolveDiscordRoleAllowed",
|
||||
"extensions/discord/src/monitor/auto-presence.ts: resolveDiscordAutoPresenceDecision",
|
||||
"extensions/discord/src/monitor/channel-access.ts: resolveDiscordChannelOwnerIdSafe",
|
||||
"extensions/discord/src/monitor/exec-approvals.ts: buildExecApprovalCustomId",
|
||||
"extensions/discord/src/monitor/exec-approvals.ts: ExecApprovalButton",
|
||||
"extensions/discord/src/monitor/exec-approvals.ts: extractDiscordChannelId",
|
||||
"extensions/discord/src/monitor/exec-approvals.ts: parseExecApprovalData",
|
||||
"extensions/discord/src/monitor/gateway-metadata.ts: fetchDiscordGatewayInfo",
|
||||
"extensions/discord/src/monitor/gateway-metadata.ts: parseDiscordGatewayInfoBody",
|
||||
"extensions/discord/src/monitor/gateway-plugin.ts: parseDiscordGatewayInfoBody",
|
||||
"extensions/discord/src/monitor/gateway-plugin.ts: resolveDiscordGatewayInfoTimeoutMs",
|
||||
"extensions/discord/src/monitor/gateway-supervisor.ts: classifyDiscordGatewayEvent",
|
||||
"extensions/discord/src/monitor/inbound-context.ts: buildDiscordUntrustedContext",
|
||||
"extensions/discord/src/monitor/message-channel-info.ts: resetDiscordChannelInfoCacheForTest",
|
||||
"extensions/discord/src/monitor/message-forwarded.ts: DiscordMessageSnapshot",
|
||||
"extensions/discord/src/monitor/message-forwarded.ts: DiscordSnapshotAuthor",
|
||||
"extensions/discord/src/monitor/message-forwarded.ts: normalizeDiscordStickerItems",
|
||||
"extensions/discord/src/monitor/message-media.ts: DiscordMediaResolveOptions",
|
||||
"extensions/discord/src/monitor/message-utils.ts: buildDiscordMediaPlaceholder",
|
||||
"extensions/discord/src/monitor/message-utils.ts: DiscordMediaResolveOptions",
|
||||
"extensions/discord/src/monitor/message-utils.ts: DiscordMessageSnapshot",
|
||||
"extensions/discord/src/monitor/message-utils.ts: DiscordSnapshotAuthor",
|
||||
"extensions/discord/src/monitor/message-utils.ts: DiscordSnapshotMessage",
|
||||
"extensions/discord/src/monitor/message-utils.ts: normalizeDiscordMessageSnapshots",
|
||||
"extensions/discord/src/monitor/message-utils.ts: normalizeDiscordStickerItems",
|
||||
"extensions/discord/src/monitor/message-utils.ts: resetDiscordChannelInfoCacheForTest",
|
||||
"extensions/discord/src/monitor/message-utils.ts: resolveDiscordMessageSnapshots",
|
||||
"extensions/discord/src/monitor/message-utils.ts: resolveDiscordMessageStickers",
|
||||
"extensions/discord/src/monitor/message-utils.ts: resolveDiscordReferencedForwardMessage",
|
||||
"extensions/discord/src/monitor/message-utils.ts: resolveDiscordReferencedReplyMessage",
|
||||
"extensions/discord/src/monitor/message-utils.ts: resolveDiscordSnapshotStickers",
|
||||
"extensions/discord/src/monitor/model-picker-preferences.ts: buildDiscordModelPickerPreferenceKey",
|
||||
"extensions/discord/src/monitor/model-picker.state.ts: computeAlphaBuckets",
|
||||
"extensions/discord/src/monitor/model-picker.state.ts: DISCORD_CUSTOM_ID_MAX_CHARS",
|
||||
"extensions/discord/src/monitor/model-picker.state.ts: DISCORD_MODEL_PICKER_BUCKET_TARGET_SIZE",
|
||||
"extensions/discord/src/monitor/model-picker.state.ts: DISCORD_MODEL_PICKER_BUCKET_THRESHOLD",
|
||||
"extensions/discord/src/monitor/model-picker.state.ts: DISCORD_MODEL_PICKER_MODEL_PAGE_SIZE",
|
||||
"extensions/discord/src/monitor/model-picker.state.ts: DISCORD_MODEL_PICKER_PROVIDER_PAGE_SIZE",
|
||||
"extensions/discord/src/monitor/model-picker.state.ts: DISCORD_MODEL_PICKER_PROVIDER_SINGLE_PAGE_MAX",
|
||||
"extensions/discord/src/monitor/model-picker.state.ts: parseDiscordModelPickerCustomId",
|
||||
"extensions/discord/src/monitor/model-picker.view.ts: DiscordModelPickerModelViewParams",
|
||||
"extensions/discord/src/monitor/model-picker.view.ts: DiscordModelPickerProviderViewParams",
|
||||
"extensions/discord/src/monitor/model-picker.view.ts: DiscordModelPickerRecentsViewParams",
|
||||
"extensions/discord/src/monitor/model-picker.view.ts: DiscordModelPickerRenderedView",
|
||||
"extensions/discord/src/monitor/native-command-arg-ui.ts: buildDiscordCommandArgCustomId",
|
||||
"extensions/discord/src/monitor/native-command-arg-ui.ts: handleDiscordCommandArgInteraction",
|
||||
"extensions/discord/src/monitor/native-command-dispatch.ts: DispatchDiscordCommandInteractionParams",
|
||||
"extensions/discord/src/monitor/native-command-model-picker-interaction.ts: handleDiscordModelPickerInteraction",
|
||||
"extensions/discord/src/monitor/native-command-ui.ts: buildDiscordCommandArgCustomId",
|
||||
"extensions/discord/src/monitor/native-command-ui.ts: DispatchDiscordCommandInteraction",
|
||||
"extensions/discord/src/monitor/native-command-ui.ts: DispatchDiscordCommandInteractionParams",
|
||||
"extensions/discord/src/monitor/native-command-ui.ts: DispatchDiscordCommandInteractionResult",
|
||||
"extensions/discord/src/monitor/native-command-ui.ts: handleDiscordCommandArgInteraction",
|
||||
"extensions/discord/src/monitor/native-command-ui.ts: handleDiscordModelPickerInteraction",
|
||||
"extensions/discord/src/monitor/native-command-ui.ts: SafeDiscordInteractionCall",
|
||||
"extensions/discord/src/monitor/native-command.runtime.ts: __testing",
|
||||
"extensions/discord/src/monitor/native-command.runtime.ts: testing",
|
||||
"extensions/discord/src/monitor/native-command.ts: __testing",
|
||||
"extensions/discord/src/monitor/native-command.ts: testing",
|
||||
"extensions/discord/src/monitor/provider.lifecycle.ts: resolveDiscordGatewayReadyTimeoutMs",
|
||||
"extensions/discord/src/monitor/provider.lifecycle.ts: resolveDiscordGatewayRuntimeReadyTimeoutMs",
|
||||
"extensions/discord/src/monitor/provider.ts: __testing",
|
||||
"extensions/discord/src/monitor/provider.ts: resolveDiscordRuntimeGroupPolicy",
|
||||
"extensions/discord/src/monitor/provider.ts: testing",
|
||||
"extensions/discord/src/monitor/thread-title.ts: normalizeGeneratedThreadTitle",
|
||||
"extensions/discord/src/outbound-components.ts: DISCORD_PRESENTATION_TEXT_LIMIT",
|
||||
"extensions/discord/src/resolve-allowlist-common.ts: findDiscordGuildByName",
|
||||
"extensions/discord/src/retry.ts: DiscordRetrySafety",
|
||||
"extensions/discord/src/retry.ts: isRetryableDiscordPreConnectError",
|
||||
"extensions/discord/src/retry.ts: isRetryableDiscordTransientError",
|
||||
"extensions/discord/src/runtime.ts: DiscordRuntime",
|
||||
"extensions/discord/src/send.message-request.ts: buildDiscordMessagePayload",
|
||||
"extensions/discord/src/send.message-request.ts: DiscordSendComponentFactory",
|
||||
"extensions/discord/src/send.message-request.ts: SUPPRESS_EMBEDS_FLAG",
|
||||
"extensions/discord/src/send.shared.ts: buildDiscordMessagePayload",
|
||||
"extensions/discord/src/send.shared.ts: DiscordSendComponentFactory",
|
||||
"extensions/discord/src/send.shared.ts: SUPPRESS_EMBEDS_FLAG",
|
||||
"extensions/discord/src/voice-message.ts: VoiceMessageMetadata",
|
||||
"extensions/discord/src/voice/prompt.ts: DISCORD_VOICE_SPOKEN_OUTPUT_CONTRACT",
|
||||
"extensions/duckduckgo/src/config.ts: DEFAULT_DDG_SAFE_SEARCH",
|
||||
@@ -938,29 +861,15 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
|
||||
"extensions/signal/src/runtime.ts: clearSignalRuntime",
|
||||
"extensions/signal/src/runtime.ts: getSignalRuntime",
|
||||
"extensions/signal/src/setup-core.ts: parseSignalAllowFromEntries",
|
||||
"extensions/slack/src/approval-auth.ts: slackApprovalAuth",
|
||||
"extensions/slack/src/approval-native-gates.ts: resolveSlackApprovalKind",
|
||||
"extensions/slack/src/approval-native.ts: testing",
|
||||
"extensions/slack/src/blocks-fallback.ts: SlackNativeDataFallbackFormat",
|
||||
"extensions/slack/src/channel-migration.ts: migrateSlackChannelsInPlace",
|
||||
"extensions/slack/src/data-table.ts: canRenderSlackDataTable",
|
||||
"extensions/slack/src/data-table.ts: SLACK_DATA_TABLE_COLUMNS_MAX",
|
||||
"extensions/slack/src/data-table.ts: SLACK_DATA_TABLE_ROWS_MAX",
|
||||
"extensions/slack/src/data-table.ts: SlackDataTableBlock",
|
||||
"extensions/slack/src/data-table.ts: SlackDataTableCell",
|
||||
"extensions/slack/src/data-visualization.ts: SLACK_CHART_AXIS_LABEL_MAX",
|
||||
"extensions/slack/src/data-visualization.ts: SLACK_CHART_DATA_POINTS_MAX",
|
||||
"extensions/slack/src/data-visualization.ts: SLACK_CHART_LABEL_MAX",
|
||||
"extensions/slack/src/data-visualization.ts: SLACK_CHART_SERIES_MAX",
|
||||
"extensions/slack/src/data-visualization.ts: SLACK_CHART_TITLE_MAX",
|
||||
"extensions/slack/src/data-visualization.ts: SlackDataVisualizationBlock",
|
||||
"extensions/slack/src/exec-approvals.ts: isSlackExecApprovalApprover",
|
||||
"extensions/slack/src/exec-approvals.ts: isSlackExecApprovalTargetRecipient",
|
||||
"extensions/slack/src/exec-approvals.ts: shouldHandleSlackExecApprovalRequest",
|
||||
"extensions/slack/src/format.ts: markdownToSlackMrkdwn",
|
||||
"extensions/slack/src/modal-metadata.ts: encodeSlackModalPrivateMetadata",
|
||||
"extensions/slack/src/monitor/auth.ts: clearSlackAllowFromCacheForTest",
|
||||
"extensions/slack/src/monitor/event-scope.ts: SlackEventScopeResolution",
|
||||
"extensions/slack/src/monitor/events/home.ts: buildSlackHomeView",
|
||||
"extensions/slack/src/monitor/events/messages.ts: formatSlackInboundLogLine",
|
||||
"extensions/slack/src/monitor/inbound-delivery-state.ts: clearSlackInboundDeliveryStateForTest",
|
||||
@@ -977,39 +886,27 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
|
||||
"extensions/slack/src/monitor/message-handler/dispatch.ts: resolveSlackStreamRecipientTeamId",
|
||||
"extensions/slack/src/monitor/message-handler/dispatch.ts: shouldEnableSlackPreviewStreaming",
|
||||
"extensions/slack/src/monitor/message-handler/dispatch.ts: shouldInitializeSlackDraftStream",
|
||||
"extensions/slack/src/monitor/message-handler/preflight-audio.ts: hasCaptionlessSlackAudio",
|
||||
"extensions/slack/src/monitor/message-handler/prepare-routing.ts: __testing",
|
||||
"extensions/slack/src/monitor/message-handler/prepare-routing.ts: SlackRoutingContextDeps",
|
||||
"extensions/slack/src/monitor/message-handler/prepare-routing.ts: testing",
|
||||
"extensions/slack/src/monitor/message-handler/prepare-thread-context-root.ts: SlackThreadRootCandidate",
|
||||
"extensions/slack/src/monitor/message-handler/preview-finalize.ts: __testing",
|
||||
"extensions/slack/src/monitor/message-handler/preview-finalize.ts: testing",
|
||||
"extensions/slack/src/monitor/message-handler/subteam-mentions.ts: clearSlackSubteamMentionCacheForTest",
|
||||
"extensions/slack/src/monitor/message-handler/subteam-mentions.ts: extractSlackSubteamMentionIds",
|
||||
"extensions/slack/src/monitor/provider-support.ts: createSlackSocketModeLogger",
|
||||
"extensions/slack/src/monitor/provider-support.ts: shouldSkipOpenClawSlackSelfEvent",
|
||||
"extensions/slack/src/monitor/provider.ts: __testing",
|
||||
"extensions/slack/src/monitor/provider.ts: formatSlackSocketReconnectMessage",
|
||||
"extensions/slack/src/monitor/provider.ts: formatSlackSocketStartRetryMessage",
|
||||
"extensions/slack/src/monitor/provider.ts: isNonRecoverableSlackAuthError",
|
||||
"extensions/slack/src/monitor/provider.ts: testing",
|
||||
"extensions/slack/src/monitor/replies.ts: SlackRespondFn",
|
||||
"extensions/slack/src/monitor/replies.ts: SlackResponseUrlBudget",
|
||||
"extensions/slack/src/monitor/reply.runtime.ts: createReplyDispatcherWithTyping",
|
||||
"extensions/slack/src/monitor/reply.runtime.ts: dispatchInboundMessage",
|
||||
"extensions/slack/src/monitor/reply.runtime.ts: settleReplyDispatcher",
|
||||
"extensions/slack/src/monitor/response-url-budget.ts: SLACK_RESPONSE_URL_MAX_CALLS",
|
||||
"extensions/slack/src/native-data-blocks.ts: renderSlackNativeDataFallbackText",
|
||||
"extensions/slack/src/native-data-fallback.ts: SlackNativeDataDeliveryPlan",
|
||||
"extensions/slack/src/reply-blocks.ts: resolveSlackReplyText",
|
||||
"extensions/slack/src/runtime.ts: clearSlackRuntime",
|
||||
"extensions/slack/src/send.ts: clearSlackDefaultSendIdentitiesForTest",
|
||||
"extensions/slack/src/send.ts: clearSlackDmChannelCache",
|
||||
"extensions/slack/src/shared.ts: setSlackChannelAllowlist",
|
||||
"extensions/slack/src/streaming.ts: extractSlackErrorCode",
|
||||
"extensions/slack/src/streaming.ts: isBenignSlackFinalizeError",
|
||||
"extensions/slack/src/streaming.ts: StopSlackStreamResult",
|
||||
"extensions/slack/src/targets.ts: slackTargetsMatch",
|
||||
"extensions/sms/src/channel.ts: resolveSmsTextChunkLimit",
|
||||
"extensions/sms/src/config-schema.ts: SmsConfigSchema",
|
||||
"extensions/sms/src/gateway.ts: registerSmsWebhookRoute",
|
||||
|
||||
@@ -106,11 +106,11 @@
|
||||
"extensions/discord/src/monitor/native-command-model-picker-interaction.ts": 782,
|
||||
"extensions/discord/src/monitor/native-command.ts": 736,
|
||||
"extensions/discord/src/monitor/provider.lifecycle.ts": 583,
|
||||
"extensions/discord/src/monitor/provider.ts": 691,
|
||||
"extensions/discord/src/monitor/provider.ts": 690,
|
||||
"extensions/discord/src/monitor/thread-bindings.manager.ts": 556,
|
||||
"extensions/discord/src/monitor/thread-bindings.state.ts": 563,
|
||||
"extensions/discord/src/send.outbound.ts": 515,
|
||||
"extensions/discord/src/send.shared.ts": 557,
|
||||
"extensions/discord/src/send.shared.ts": 554,
|
||||
"extensions/discord/src/voice/manager.ts": 1917,
|
||||
"extensions/discord/src/voice/realtime.ts": 1815,
|
||||
"extensions/elevenlabs/speech-provider.ts": 596,
|
||||
@@ -337,7 +337,7 @@
|
||||
"extensions/slack/src/monitor/message-handler/dispatch.ts": 2232,
|
||||
"extensions/slack/src/monitor/message-handler/prepare.ts": 1715,
|
||||
"extensions/slack/src/monitor/provider-support.ts": 510,
|
||||
"extensions/slack/src/monitor/provider.ts": 801,
|
||||
"extensions/slack/src/monitor/provider.ts": 798,
|
||||
"extensions/slack/src/monitor/replies.ts": 623,
|
||||
"extensions/slack/src/monitor/slash.ts": 1098,
|
||||
"extensions/slack/src/reply-blocks.ts": 505,
|
||||
|
||||
Reference in New Issue
Block a user