refactor: untangle remaining plugin sdk boundaries

This commit is contained in:
Peter Steinberger 2026-03-16 21:13:56 -07:00
parent afc0172cb1
commit 9ebe38b6e3
No known key found for this signature in database
492 changed files with 5657 additions and 2877 deletions

View File

@ -1,7 +1,7 @@
import fs from "node:fs";
import { chmod, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import path from "node:path";
import { resolvePreferredOpenClawTmpDir } from "../../../../src/infra/tmp-openclaw-dir.js";
import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/infra-runtime";
import type { ResolvedAcpxPluginConfig } from "../config.js";
import { ACPX_PINNED_VERSION } from "../config.js";
import { AcpxRuntime } from "../runtime.js";

View File

@ -1,3 +1,5 @@
import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
import { parseDurationMs } from "openclaw/plugin-sdk/cli-runtime";
import {
emptyPluginConfigSchema,
type OpenClawPluginApi,
@ -7,26 +9,25 @@ import {
} from "openclaw/plugin-sdk/core";
import {
CLAUDE_CLI_PROFILE_ID,
applyAuthProfileConfig,
buildTokenProfileId,
createProviderApiKeyAuthMethod,
ensureApiKeyFromOptionEnvOrPrompt,
listProfilesForProvider,
upsertAuthProfile,
} from "../../src/agents/auth-profiles.js";
import { suggestOAuthProfileIdForLegacyDefault } from "../../src/agents/auth-profiles/repair.js";
import type { AuthProfileStore } from "../../src/agents/auth-profiles/types.js";
import { normalizeModelCompat } from "../../src/agents/model-compat.js";
import { formatCliCommand } from "../../src/cli/command-format.js";
import { parseDurationMs } from "../../src/cli/parse-duration.js";
import {
normalizeApiKeyInput,
suggestOAuthProfileIdForLegacyDefault,
type AuthProfileStore,
type ProviderAuthResult,
normalizeSecretInput,
normalizeSecretInputModeInput,
promptSecretRefForSetup,
resolveSecretInputModeForEnvSelection,
} from "../../src/commands/auth-choice.apply-helpers.js";
import { buildTokenProfileId, validateAnthropicSetupToken } from "../../src/commands/auth-token.js";
import { applyAuthProfileConfig } from "../../src/commands/onboard-auth.js";
import { fetchClaudeUsage } from "../../src/infra/provider-usage.fetch.js";
import { createProviderApiKeyAuthMethod } from "../../src/plugins/provider-api-key-auth.js";
import type { ProviderAuthResult } from "../../src/plugins/types.js";
import { normalizeSecretInput } from "../../src/utils/normalize-secret-input.js";
import { anthropicMediaUnderstandingProvider } from "./media-understanding-provider.js";
upsertAuthProfile,
validateAnthropicSetupToken,
validateApiKeyInput,
} from "openclaw/plugin-sdk/provider-auth";
import { normalizeModelCompat } from "openclaw/plugin-sdk/provider-models";
import { fetchClaudeUsage } from "openclaw/plugin-sdk/provider-usage";
const PROVIDER_ID = "anthropic";
const DEFAULT_ANTHROPIC_MODEL = "anthropic/claude-sonnet-4-6";
@ -395,7 +396,6 @@ const anthropicPlugin = {
profileId: ctx.profileId,
}),
});
api.registerMediaUnderstandingProvider(anthropicMediaUnderstandingProvider);
},
};

View File

@ -1,10 +1,9 @@
import { emptyPluginConfigSchema, type OpenClawPluginApi } from "openclaw/plugin-sdk/core";
import {
createPluginBackedWebSearchProvider,
getTopLevelCredentialValue,
setTopLevelCredentialValue,
} from "../../src/agents/tools/web-search-plugin-factory.js";
import { emptyPluginConfigSchema } from "../../src/plugins/config-schema.js";
import type { OpenClawPluginApi } from "../../src/plugins/types.js";
} from "openclaw/plugin-sdk/provider-web-search";
const bravePlugin = {
id: "brave",

View File

@ -1,7 +1,6 @@
import { emptyPluginConfigSchema, type OpenClawPluginApi } from "openclaw/plugin-sdk/core";
import { ensureModelAllowlistEntry } from "../../src/commands/model-allowlist.js";
import { createProviderApiKeyAuthMethod } from "../../src/plugins/provider-api-key-auth.js";
import { buildPairedProviderApiKeyCatalog } from "../../src/plugins/provider-catalog.js";
import { createProviderApiKeyAuthMethod } from "openclaw/plugin-sdk/provider-auth";
import { ensureModelAllowlistEntry } from "openclaw/plugin-sdk/provider-onboard";
import { buildBytePlusCodingProvider, buildBytePlusProvider } from "./provider-catalog.js";
const PROVIDER_ID = "byteplus";
@ -46,15 +45,18 @@ const byteplusPlugin = {
],
catalog: {
order: "paired",
run: (ctx) =>
buildPairedProviderApiKeyCatalog({
ctx,
providerId: PROVIDER_ID,
buildProviders: () => ({
byteplus: buildBytePlusProvider(),
"byteplus-plan": buildBytePlusCodingProvider(),
}),
}),
run: async (ctx) => {
const apiKey = ctx.resolveProviderApiKey(PROVIDER_ID).apiKey;
if (!apiKey) {
return null;
}
return {
providers: {
byteplus: { ...buildBytePlusProvider(), apiKey },
"byteplus-plan": { ...buildBytePlusCodingProvider(), apiKey },
},
};
},
},
});
},

View File

@ -4,8 +4,8 @@ import {
BYTEPLUS_CODING_BASE_URL,
BYTEPLUS_CODING_MODEL_CATALOG,
BYTEPLUS_MODEL_CATALOG,
} from "../../src/agents/byteplus-models.js";
import type { ModelProviderConfig } from "../../src/config/types.models.js";
type ModelProviderConfig,
} from "openclaw/plugin-sdk/provider-models";
export function buildBytePlusProvider(): ModelProviderConfig {
return {

View File

@ -1,21 +1,22 @@
import { emptyPluginConfigSchema, type OpenClawPluginApi } from "openclaw/plugin-sdk/core";
import { upsertAuthProfile } from "../../src/agents/auth-profiles.js";
import { ensureAuthProfileStore, listProfilesForProvider } from "../../src/agents/auth-profiles.js";
import {
applyAuthProfileConfig,
buildApiKeyCredential,
coerceSecretRef,
ensureApiKeyFromOptionEnvOrPrompt,
ensureAuthProfileStore,
listProfilesForProvider,
normalizeApiKeyInput,
normalizeOptionalSecretInput,
resolveNonEnvSecretRefApiKeyMarker,
type SecretInput,
upsertAuthProfile,
validateApiKeyInput,
} from "openclaw/plugin-sdk/provider-auth";
import {
buildCloudflareAiGatewayModelDefinition,
resolveCloudflareAiGatewayBaseUrl,
} from "../../src/agents/cloudflare-ai-gateway.js";
import { resolveNonEnvSecretRefApiKeyMarker } from "../../src/agents/model-auth-markers.js";
import {
normalizeApiKeyInput,
validateApiKeyInput,
} from "../../src/commands/auth-choice.api-key.js";
import { ensureApiKeyFromOptionEnvOrPrompt } from "../../src/commands/auth-choice.apply-helpers.js";
import { buildApiKeyCredential } from "../../src/commands/auth-credentials.js";
import { applyAuthProfileConfig } from "../../src/commands/onboard-auth.js";
import type { SecretInput } from "../../src/config/types.secrets.js";
import { coerceSecretRef } from "../../src/config/types.secrets.js";
import { normalizeOptionalSecretInput } from "../../src/utils/normalize-secret-input.js";
} from "openclaw/plugin-sdk/provider-models";
import {
applyCloudflareAiGatewayConfig,
buildCloudflareAiGatewayConfigPatch,

View File

@ -2,12 +2,12 @@ import {
buildCloudflareAiGatewayModelDefinition,
CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF,
resolveCloudflareAiGatewayBaseUrl,
} from "../../src/agents/cloudflare-ai-gateway.js";
} from "openclaw/plugin-sdk/provider-models";
import {
applyAgentDefaultModelPrimary,
applyProviderConfigWithDefaultModel,
} from "../../src/commands/onboard-auth.config-shared.js";
import type { OpenClawConfig } from "../../src/config/config.js";
type OpenClawConfig,
} from "openclaw/plugin-sdk/provider-onboard";
export { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF };

View File

@ -1,13 +1,13 @@
import {
hasConfiguredSecretInput,
normalizeSecretInputString,
} from "../../../src/config/types.secrets.js";
} from "openclaw/plugin-sdk/config-runtime";
import {
DEFAULT_ACCOUNT_ID,
normalizeAccountId,
type OpenClawConfig,
type DiscordAccountConfig,
} from "../../../src/plugin-sdk-internal/discord.js";
} from "openclaw/plugin-sdk/discord";
import {
mergeDiscordAccountConfig,
resolveDefaultDiscordAccountId,

View File

@ -3,12 +3,12 @@ import {
createAccountListHelpers,
normalizeAccountId,
resolveAccountEntry,
} from "../../../src/plugin-sdk-internal/accounts.js";
} from "openclaw/plugin-sdk/account-resolution";
import type {
OpenClawConfig,
DiscordAccountConfig,
DiscordActionConfig,
} from "../../../src/plugin-sdk-internal/discord.js";
OpenClawConfig,
} from "openclaw/plugin-sdk/discord";
import { resolveDiscordToken } from "./token.js";
export type ResolvedDiscordAccount = {

View File

@ -4,13 +4,13 @@ import {
readNumberParam,
readStringArrayParam,
readStringParam,
} from "../../../../src/agents/tools/common.js";
} from "openclaw/plugin-sdk/agent-runtime";
import {
isDiscordModerationAction,
readDiscordModerationCommand,
} from "../../../../src/agents/tools/discord-actions-moderation-shared.js";
import { handleDiscordAction } from "../../../../src/agents/tools/discord-actions.js";
import type { ChannelMessageActionContext } from "../../../../src/channels/plugins/types.js";
} from "openclaw/plugin-sdk/agent-runtime";
import { handleDiscordAction } from "openclaw/plugin-sdk/agent-runtime";
import type { ChannelMessageActionContext } from "openclaw/plugin-sdk/channel-runtime";
type Ctx = Pick<
ChannelMessageActionContext,

View File

@ -1,15 +1,15 @@
import type { AgentToolResult } from "@mariozechner/pi-agent-core";
import { readBooleanParam } from "openclaw/plugin-sdk/boolean-param";
import {
readNumberParam,
readStringArrayParam,
readStringParam,
} from "../../../../src/agents/tools/common.js";
import { readDiscordParentIdParam } from "../../../../src/agents/tools/discord-actions-shared.js";
import { handleDiscordAction } from "../../../../src/agents/tools/discord-actions.js";
import { resolveReactionMessageId } from "../../../../src/channels/plugins/actions/reaction-message-id.js";
import type { ChannelMessageActionContext } from "../../../../src/channels/plugins/types.js";
import { normalizeInteractiveReply } from "../../../../src/interactive/payload.js";
} from "openclaw/plugin-sdk/agent-runtime";
import { readDiscordParentIdParam } from "openclaw/plugin-sdk/agent-runtime";
import { handleDiscordAction } from "openclaw/plugin-sdk/agent-runtime";
import { readBooleanParam } from "openclaw/plugin-sdk/boolean-param";
import { resolveReactionMessageId } from "openclaw/plugin-sdk/channel-runtime";
import type { ChannelMessageActionContext } from "openclaw/plugin-sdk/channel-runtime";
import { normalizeInteractiveReply } from "openclaw/plugin-sdk/channel-runtime";
import { buildDiscordInteractiveComponents } from "../shared-interactive.js";
import { resolveDiscordChannelId } from "../targets.js";
import { tryHandleDiscordMessageActionGuildAdmin } from "./handle-action.guild-admin.js";

View File

@ -1,5 +1,9 @@
import { resolveFetch } from "../../../src/infra/fetch.js";
import { resolveRetryConfig, retryAsync, type RetryConfig } from "../../../src/infra/retry.js";
import { resolveFetch } from "openclaw/plugin-sdk/infra-runtime";
import {
resolveRetryConfig,
retryAsync,
type RetryConfig,
} from "openclaw/plugin-sdk/infra-runtime";
const DISCORD_API_BASE = "https://discord.com/api/v10";
const DISCORD_API_RETRY_DEFAULTS = {

View File

@ -1,6 +1,9 @@
import type { OpenClawConfig } from "../../../src/config/config.js";
import type { DiscordGuildChannelConfig, DiscordGuildEntry } from "../../../src/config/types.js";
import { isRecord } from "../../../src/utils.js";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import type {
DiscordGuildChannelConfig,
DiscordGuildEntry,
} from "openclaw/plugin-sdk/config-runtime";
import { isRecord } from "openclaw/plugin-sdk/text-runtime";
import { inspectDiscordAccount } from "./account-inspect.js";
import { fetchChannelPermissionsDiscord } from "./send.js";

View File

@ -1,12 +1,12 @@
import {
createUnionActionGate,
listTokenSourcedAccounts,
} from "../../../src/channels/plugins/actions/shared.js";
} from "openclaw/plugin-sdk/channel-runtime";
import type {
ChannelMessageActionAdapter,
ChannelMessageActionName,
} from "../../../src/channels/plugins/types.js";
import type { DiscordActionConfig } from "../../../src/config/types.discord.js";
} from "openclaw/plugin-sdk/channel-runtime";
import type { DiscordActionConfig } from "openclaw/plugin-sdk/config-runtime";
import { createDiscordActionGate, listEnabledDiscordAccounts } from "./accounts.js";
import { handleDiscordMessageAction } from "./actions/handle-action.js";

View File

@ -1,8 +1,43 @@
import type { ChannelPlugin } from "openclaw/plugin-sdk/discord";
import type { ResolvedDiscordAccount } from "./accounts.js";
import {
buildChannelConfigSchema,
DiscordConfigSchema,
getChatChannelMeta,
type ChannelPlugin,
} from "openclaw/plugin-sdk/discord";
import { type ResolvedDiscordAccount } from "./accounts.js";
import { discordConfigAccessors, discordConfigBase, discordSetupWizard } from "./plugin-shared.js";
import { discordSetupAdapter } from "./setup-core.js";
import { createDiscordPluginBase } from "./shared.js";
export const discordSetupPlugin: ChannelPlugin<ResolvedDiscordAccount> = createDiscordPluginBase({
export const discordSetupPlugin: ChannelPlugin<ResolvedDiscordAccount> = {
id: "discord",
meta: {
...getChatChannelMeta("discord"),
},
setupWizard: discordSetupWizard,
capabilities: {
chatTypes: ["direct", "channel", "thread"],
polls: true,
reactions: true,
threads: true,
media: true,
nativeCommands: true,
},
streaming: {
blockStreamingCoalesceDefaults: { minChars: 1500, idleMs: 1000 },
},
reload: { configPrefixes: ["channels.discord"] },
configSchema: buildChannelConfigSchema(DiscordConfigSchema),
config: {
...discordConfigBase,
isConfigured: (account) => Boolean(account.token?.trim()),
describeAccount: (account) => ({
accountId: account.accountId,
name: account.name,
enabled: account.enabled,
configured: Boolean(account.token?.trim()),
tokenSource: account.tokenSource,
}),
...discordConfigAccessors,
},
setup: discordSetupAdapter,
});
};

View File

@ -1,10 +1,12 @@
import { Separator, TextDisplay } from "@buape/carbon";
import { buildAccountScopedAllowlistConfigEditor } from "openclaw/plugin-sdk/allowlist-config-edit";
import {
buildAccountScopedAllowlistConfigEditor,
buildAccountScopedDmSecurityPolicy,
collectOpenProviderGroupPolicyWarnings,
collectOpenGroupPolicyConfiguredRouteWarnings,
} from "openclaw/plugin-sdk/compat";
collectOpenProviderGroupPolicyWarnings,
} from "openclaw/plugin-sdk/channel-config-helpers";
import { resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-runtime";
import { normalizeMessageChannel } from "openclaw/plugin-sdk/channel-runtime";
import {
buildAgentSessionKey,
resolveThreadSessionKeys,
@ -12,8 +14,11 @@ import {
} from "openclaw/plugin-sdk/core";
import {
buildComputedAccountStatusSnapshot,
buildChannelConfigSchema,
buildTokenChannelStatusSummary,
DEFAULT_ACCOUNT_ID,
DiscordConfigSchema,
getChatChannelMeta,
listDiscordDirectoryGroupsFromConfig,
listDiscordDirectoryPeersFromConfig,
PAIRING_APPROVED_MESSAGE,
@ -25,9 +30,6 @@ import {
type ChannelPlugin,
type OpenClawConfig,
} from "openclaw/plugin-sdk/discord";
import { resolveOutboundSendDep } from "../../../src/infra/outbound/send-deps.js";
import { normalizeOutboundThreadId } from "../../../src/infra/outbound/thread-id.js";
import { normalizeMessageChannel } from "../../../src/utils/message-channel.js";
import {
listDiscordAccountIds,
resolveDiscordAccount,
@ -43,12 +45,12 @@ import {
normalizeDiscordMessagingTarget,
normalizeDiscordOutboundTarget,
} from "./normalize.js";
import { discordConfigAccessors, discordConfigBase, discordSetupWizard } from "./plugin-shared.js";
import type { DiscordProbe } from "./probe.js";
import { resolveDiscordUserAllowlist } from "./resolve-users.js";
import { getDiscordRuntime } from "./runtime.js";
import { fetchChannelPermissionsDiscord } from "./send.js";
import { discordSetupAdapter } from "./setup-core.js";
import { createDiscordPluginBase, discordConfigAccessors } from "./shared.js";
import { collectDiscordStatusIssues } from "./status-issues.js";
import { parseDiscordTarget } from "./targets.js";
import { DiscordUiContainer } from "./ui.js";
@ -57,6 +59,7 @@ type DiscordSendFn = ReturnType<
typeof getDiscordRuntime
>["channel"]["discord"]["sendMessageDiscord"];
const meta = getChatChannelMeta("discord");
const REQUIRED_DISCORD_PERMISSIONS = ["ViewChannel", "SendMessages"] as const;
function formatDiscordIntents(intents?: {
@ -197,6 +200,20 @@ function parseDiscordExplicitTarget(raw: string) {
}
}
function normalizeOutboundThreadId(value?: string | number | null): string | undefined {
if (value == null) {
return undefined;
}
if (typeof value === "number") {
if (!Number.isFinite(value)) {
return undefined;
}
return String(Math.trunc(value));
}
const trimmed = value.trim();
return trimmed ? trimmed : undefined;
}
function buildDiscordBaseSessionKey(params: {
cfg: OpenClawConfig;
agentId: string;
@ -280,9 +297,11 @@ function resolveDiscordOutboundSessionRoute(params: {
}
export const discordPlugin: ChannelPlugin<ResolvedDiscordAccount> = {
...createDiscordPluginBase({
setup: discordSetupAdapter,
}),
id: "discord",
meta: {
...meta,
},
setupWizard: discordSetupWizard,
pairing: {
idLabel: "discordUserId",
normalizeAllowEntry: (entry) => entry.replace(/^(discord|user):/i, ""),
@ -293,6 +312,31 @@ export const discordPlugin: ChannelPlugin<ResolvedDiscordAccount> = {
);
},
},
capabilities: {
chatTypes: ["direct", "channel", "thread"],
polls: true,
reactions: true,
threads: true,
media: true,
nativeCommands: true,
},
streaming: {
blockStreamingCoalesceDefaults: { minChars: 1500, idleMs: 1000 },
},
reload: { configPrefixes: ["channels.discord"] },
configSchema: buildChannelConfigSchema(DiscordConfigSchema),
config: {
...discordConfigBase,
isConfigured: (account) => Boolean(account.token?.trim()),
describeAccount: (account) => ({
accountId: account.accountId,
name: account.name,
enabled: account.enabled,
configured: Boolean(account.token?.trim()),
tokenSource: account.tokenSource,
}),
...discordConfigAccessors,
},
allowlist: {
supportsScope: ({ scope }) => scope === "dm",
readConfig: ({ cfg, accountId }) =>

View File

@ -1,4 +1,4 @@
import { chunkMarkdownTextWithMode, type ChunkMode } from "../../../src/auto-reply/chunk.js";
import { chunkMarkdownTextWithMode, type ChunkMode } from "openclaw/plugin-sdk/reply-runtime";
export type ChunkDiscordTextOpts = {
/** Max characters per Discord message. Default: 2000. */

View File

@ -1,8 +1,8 @@
import { RequestClient } from "@buape/carbon";
import { loadConfig } from "../../../src/config/config.js";
import { createDiscordRetryRunner, type RetryRunner } from "../../../src/infra/retry-policy.js";
import type { RetryConfig } from "../../../src/infra/retry.js";
import { normalizeAccountId } from "../../../src/routing/session-key.js";
import { loadConfig } from "openclaw/plugin-sdk/config-runtime";
import { createDiscordRetryRunner, type RetryRunner } from "openclaw/plugin-sdk/infra-runtime";
import type { RetryConfig } from "openclaw/plugin-sdk/infra-runtime";
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
import {
mergeDiscordAccountConfig,
resolveDiscordAccount,

View File

@ -1,4 +1,4 @@
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../../src/routing/account-id.js";
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/routing";
const DISCORD_DIRECTORY_CACHE_MAX_ENTRIES = 4000;
const DISCORD_DISCRIMINATOR_SUFFIX = /#\d{4}$/;

View File

@ -1,5 +1,5 @@
import type { DirectoryConfigParams } from "../../../src/channels/plugins/directory-config.js";
import type { ChannelDirectoryEntry } from "../../../src/channels/plugins/types.js";
import type { DirectoryConfigParams } from "openclaw/plugin-sdk/channel-runtime";
import type { ChannelDirectoryEntry } from "openclaw/plugin-sdk/channel-runtime";
import { resolveDiscordAccount } from "./accounts.js";
import { fetchDiscord } from "./api.js";
import { rememberDiscordDirectoryUser } from "./directory-cache.js";

View File

@ -1,7 +1,7 @@
import { resolveTextChunkLimit } from "../../../src/auto-reply/chunk.js";
import { type OpenClawConfig } from "../../../src/config/config.js";
import { resolveAccountEntry } from "../../../src/routing/account-lookup.js";
import { normalizeAccountId } from "../../../src/routing/session-key.js";
import { type OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-runtime";
import { resolveAccountEntry } from "openclaw/plugin-sdk/routing";
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
import { DISCORD_TEXT_CHUNK_LIMIT } from "./outbound-adapter.js";
const DEFAULT_DISCORD_DRAFT_STREAM_MIN = 200;

View File

@ -1,6 +1,6 @@
import type { RequestClient } from "@buape/carbon";
import { Routes } from "discord-api-types/v10";
import { createFinalizableDraftLifecycle } from "../../../src/channels/draft-stream-controls.js";
import { createFinalizableDraftLifecycle } from "openclaw/plugin-sdk/channel-runtime";
/** Discord messages cap at 2000 characters. */
const DISCORD_STREAM_MAX_CHARS = 2000;

View File

@ -1,6 +1,6 @@
import type { ReplyPayload } from "../../../src/auto-reply/types.js";
import type { OpenClawConfig } from "../../../src/config/config.js";
import { getExecApprovalReplyMetadata } from "../../../src/infra/exec-approval-reply.js";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { getExecApprovalReplyMetadata } from "openclaw/plugin-sdk/infra-runtime";
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
import { resolveDiscordAccount } from "./accounts.js";
export function isDiscordExecApprovalClientEnabled(params: {

View File

@ -1,6 +1,6 @@
import type { EventEmitter } from "node:events";
import { logVerbose } from "../../../src/globals.js";
import type { RuntimeEnv } from "../../../src/runtime.js";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
type GatewayEmitter = Pick<EventEmitter, "on" | "removeListener">;

View File

@ -1,5 +1,5 @@
import type { MockFn } from "openclaw/plugin-sdk/test-utils";
import { vi } from "vitest";
import type { MockFn } from "../../../src/test-utils/vitest-mock-fn.js";
export const sendMock: MockFn = vi.fn();
export const reactMock: MockFn = vi.fn();
@ -15,8 +15,8 @@ vi.mock("./send.js", () => ({
},
}));
vi.mock("../../../src/auto-reply/dispatch.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("../../../src/auto-reply/dispatch.js")>();
vi.mock("openclaw/plugin-sdk/reply-runtime", async (importOriginal) => {
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/reply-runtime")>();
return {
...actual,
dispatchInboundMessage: (...args: unknown[]) => dispatchMock(...args),
@ -36,10 +36,10 @@ function createPairingStoreMocks() {
};
}
vi.mock("../../../src/pairing/pairing-store.js", () => createPairingStoreMocks());
vi.mock("openclaw/plugin-sdk/conversation-runtime", () => createPairingStoreMocks());
vi.mock("../../../src/config/sessions.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("../../../src/config/sessions.js")>();
vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => {
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
return {
...actual,
resolveStorePath: vi.fn(() => "/tmp/openclaw-sessions.json"),

View File

@ -18,41 +18,41 @@ import {
} from "@buape/carbon";
import type { APIStringSelectComponent } from "discord-api-types/v10";
import { ButtonStyle, ChannelType } from "discord-api-types/v10";
import { resolveHumanDelayConfig } from "../../../../src/agents/identity.js";
import { resolveChunkMode, resolveTextChunkLimit } from "../../../../src/auto-reply/chunk.js";
import {
formatInboundEnvelope,
resolveEnvelopeFormatOptions,
} from "../../../../src/auto-reply/envelope.js";
import { finalizeInboundContext } from "../../../../src/auto-reply/reply/inbound-context.js";
import { dispatchReplyWithBufferedBlockDispatcher } from "../../../../src/auto-reply/reply/provider-dispatcher.js";
import { createReplyReferencePlanner } from "../../../../src/auto-reply/reply/reply-reference.js";
import { resolveCommandAuthorizedFromAuthorizers } from "../../../../src/channels/command-gating.js";
import { createReplyPrefixOptions } from "../../../../src/channels/reply-prefix.js";
import { recordInboundSession } from "../../../../src/channels/session.js";
import type { OpenClawConfig } from "../../../../src/config/config.js";
import { isDangerousNameMatchingEnabled } from "../../../../src/config/dangerous-name-matching.js";
import { resolveMarkdownTableMode } from "../../../../src/config/markdown-tables.js";
import { readSessionUpdatedAt, resolveStorePath } from "../../../../src/config/sessions.js";
import type { DiscordAccountConfig } from "../../../../src/config/types.discord.js";
import { logVerbose } from "../../../../src/globals.js";
import { enqueueSystemEvent } from "../../../../src/infra/system-events.js";
import { logDebug, logError } from "../../../../src/logger.js";
import { getAgentScopedMediaLocalRoots } from "../../../../src/media/local-roots.js";
import { issuePairingChallenge } from "../../../../src/pairing/pairing-challenge.js";
import { upsertChannelPairingRequest } from "../../../../src/pairing/pairing-store.js";
import { resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
import { resolveCommandAuthorizedFromAuthorizers } from "openclaw/plugin-sdk/channel-runtime";
import { createReplyPrefixOptions } from "openclaw/plugin-sdk/channel-runtime";
import { recordInboundSession } from "openclaw/plugin-sdk/channel-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/config-runtime";
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/config-runtime";
import { readSessionUpdatedAt, resolveStorePath } from "openclaw/plugin-sdk/config-runtime";
import type { DiscordAccountConfig } from "openclaw/plugin-sdk/config-runtime";
import { issuePairingChallenge } from "openclaw/plugin-sdk/conversation-runtime";
import { upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
import {
buildPluginBindingResolvedText,
parsePluginBindingApprovalCustomId,
resolvePluginConversationBindingApproval,
} from "../../../../src/plugins/conversation-binding.js";
import { dispatchPluginInteractiveHandler } from "../../../../src/plugins/interactive.js";
import { resolveAgentRoute } from "../../../../src/routing/resolve-route.js";
import { createNonExitingRuntime, type RuntimeEnv } from "../../../../src/runtime.js";
} from "openclaw/plugin-sdk/conversation-runtime";
import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
import { dispatchPluginInteractiveHandler } from "openclaw/plugin-sdk/plugin-runtime";
import { resolveChunkMode, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-runtime";
import {
formatInboundEnvelope,
resolveEnvelopeFormatOptions,
} from "openclaw/plugin-sdk/reply-runtime";
import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-runtime";
import { dispatchReplyWithBufferedBlockDispatcher } from "openclaw/plugin-sdk/reply-runtime";
import { createReplyReferencePlanner } from "openclaw/plugin-sdk/reply-runtime";
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
import { createNonExitingRuntime, type RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
import {
readStoreAllowFromForDmPolicy,
resolvePinnedMainDmOwnerFromAllowlist,
} from "../../../../src/security/dm-policy-shared.js";
} from "openclaw/plugin-sdk/security-runtime";
import { logDebug, logError } from "openclaw/plugin-sdk/text-runtime";
import { resolveDiscordMaxLinesPerMessage } from "../accounts.js";
import { resolveDiscordComponentEntry, resolveDiscordModalEntry } from "../components-registry.js";
import {

View File

@ -1,12 +1,12 @@
import type { Guild, User } from "@buape/carbon";
import { evaluateGroupRouteAccessForPolicy } from "openclaw/plugin-sdk/group-access";
import type { AllowlistMatch } from "../../../../src/channels/allowlist-match.js";
import type { AllowlistMatch } from "openclaw/plugin-sdk/channel-runtime";
import {
buildChannelKeyCandidates,
resolveChannelEntryMatchWithFallback,
resolveChannelMatchConfig,
type ChannelMatchSource,
} from "../../../../src/channels/channel-config.js";
} from "openclaw/plugin-sdk/channel-runtime";
import { evaluateGroupRouteAccessForPolicy } from "openclaw/plugin-sdk/group-access";
import { formatDiscordUserTag } from "./format.js";
export type DiscordAllowList = {

View File

@ -6,12 +6,12 @@ import {
resolveProfilesUnavailableReason,
type AuthProfileFailureReason,
type AuthProfileStore,
} from "../../../../src/agents/auth-profiles.js";
} from "openclaw/plugin-sdk/agent-runtime";
import type {
DiscordAccountConfig,
DiscordAutoPresenceConfig,
} from "../../../../src/config/config.js";
import { warn } from "../../../../src/globals.js";
} from "openclaw/plugin-sdk/config-runtime";
import { warn } from "openclaw/plugin-sdk/runtime-env";
import { resolveDiscordPresenceUpdate } from "./presence.js";
const DEFAULT_CUSTOM_ACTIVITY_TYPE = 4;

View File

@ -1,4 +1,4 @@
import type { DiscordSlashCommandConfig } from "../../../../src/config/types.discord.js";
import type { DiscordSlashCommandConfig } from "openclaw/plugin-sdk/config-runtime";
export function resolveDiscordSlashCommandConfig(
raw?: DiscordSlashCommandConfig,

View File

@ -1,9 +1,9 @@
import { resolveCommandAuthorizedFromAuthorizers } from "../../../../src/channels/command-gating.js";
import { resolveCommandAuthorizedFromAuthorizers } from "openclaw/plugin-sdk/channel-runtime";
import {
readStoreAllowFromForDmPolicy,
resolveDmGroupAccessWithLists,
type DmGroupAccessDecision,
} from "../../../../src/security/dm-policy-shared.js";
} from "openclaw/plugin-sdk/security-runtime";
import { normalizeDiscordAllowList, resolveDiscordAllowListMatch } from "./allow-list.js";
const DISCORD_ALLOW_LIST_PREFIXES = ["discord:", "user:", "pk:"];

View File

@ -1,5 +1,5 @@
import { issuePairingChallenge } from "../../../../src/pairing/pairing-challenge.js";
import { upsertChannelPairingRequest } from "../../../../src/pairing/pairing-store.js";
import { issuePairingChallenge } from "openclaw/plugin-sdk/conversation-runtime";
import { upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
import type { DiscordDmCommandAccess } from "./dm-command-auth.js";
export async function handleDiscordDmCommandDecision(params: {

View File

@ -10,30 +10,24 @@ import {
type TopLevelComponents,
} from "@buape/carbon";
import { ButtonStyle, Routes } from "discord-api-types/v10";
import type { OpenClawConfig } from "../../../../src/config/config.js";
import { loadSessionStore, resolveStorePath } from "../../../../src/config/sessions.js";
import type { DiscordExecApprovalConfig } from "../../../../src/config/types.discord.js";
import { GatewayClient } from "../../../../src/gateway/client.js";
import { createOperatorApprovalsGatewayClient } from "../../../../src/gateway/operator-approvals-client.js";
import type { EventFrame } from "../../../../src/gateway/protocol/index.js";
import { resolveExecApprovalCommandDisplay } from "../../../../src/infra/exec-approval-command-display.js";
import { getExecApprovalApproverDmNoticeText } from "../../../../src/infra/exec-approval-reply.js";
import { normalizeMessageChannel } from "openclaw/plugin-sdk/channel-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { loadSessionStore, resolveStorePath } from "openclaw/plugin-sdk/config-runtime";
import type { DiscordExecApprovalConfig } from "openclaw/plugin-sdk/config-runtime";
import { GatewayClient } from "openclaw/plugin-sdk/gateway-runtime";
import { createOperatorApprovalsGatewayClient } from "openclaw/plugin-sdk/gateway-runtime";
import type { EventFrame } from "openclaw/plugin-sdk/gateway-runtime";
import { resolveExecApprovalCommandDisplay } from "openclaw/plugin-sdk/infra-runtime";
import { getExecApprovalApproverDmNoticeText } from "openclaw/plugin-sdk/infra-runtime";
import type {
ExecApprovalDecision,
ExecApprovalRequest,
ExecApprovalResolved,
} from "../../../../src/infra/exec-approvals.js";
import { logDebug, logError } from "../../../../src/logger.js";
import {
normalizeAccountId,
resolveAgentIdFromSessionKey,
} from "../../../../src/routing/session-key.js";
import type { RuntimeEnv } from "../../../../src/runtime.js";
import {
compileSafeRegex,
testRegexWithBoundedInput,
} from "../../../../src/security/safe-regex.js";
import { normalizeMessageChannel } from "../../../../src/utils/message-channel.js";
} from "openclaw/plugin-sdk/infra-runtime";
import { normalizeAccountId, resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing";
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
import { compileSafeRegex, testRegexWithBoundedInput } from "openclaw/plugin-sdk/security-runtime";
import { logDebug, logError } from "openclaw/plugin-sdk/text-runtime";
import { createDiscordClient, stripUndefinedFields } from "../send.shared.js";
import { DiscordUiContainer } from "../ui.js";

View File

@ -1,11 +1,11 @@
import { GatewayIntents, GatewayPlugin } from "@buape/carbon/gateway";
import type { APIGatewayBotInfo } from "discord-api-types/v10";
import { HttpsProxyAgent } from "https-proxy-agent";
import type { DiscordAccountConfig } from "openclaw/plugin-sdk/config-runtime";
import { danger } from "openclaw/plugin-sdk/runtime-env";
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
import { ProxyAgent, fetch as undiciFetch } from "undici";
import WebSocket from "ws";
import type { DiscordAccountConfig } from "../../../../src/config/types.js";
import { danger } from "../../../../src/globals.js";
import type { RuntimeEnv } from "../../../../src/runtime.js";
const DISCORD_GATEWAY_BOT_URL = "https://discord.com/api/v10/gateway/bot";
const DEFAULT_DISCORD_GATEWAY_URL = "wss://gateway.discord.gg/";
@ -20,7 +20,7 @@ type DiscordGatewayFetch = (
) => Promise<DiscordGatewayMetadataResponse>;
export function resolveDiscordGatewayIntents(
intentsConfig?: import("../../../../src/config/types.discord.js").DiscordIntentsConfig,
intentsConfig?: import("openclaw/plugin-sdk/config-runtime").DiscordIntentsConfig,
): number {
let intents =
GatewayIntents.Guilds |

View File

@ -1,4 +1,4 @@
import { buildUntrustedChannelMetadata } from "../../../../src/security/channel-metadata.js";
import { buildUntrustedChannelMetadata } from "openclaw/plugin-sdk/security-runtime";
import {
resolveDiscordOwnerAllowFrom,
type DiscordChannelConfigResolved,

View File

@ -1,7 +1,7 @@
import { createRunStateMachine } from "openclaw/plugin-sdk/channel-runtime";
import { formatDurationSeconds } from "openclaw/plugin-sdk/infra-runtime";
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
import { createRunStateMachine } from "../../../../src/channels/run-state-machine.js";
import { danger } from "../../../../src/globals.js";
import { formatDurationSeconds } from "../../../../src/infra/format-time/format-duration.ts";
import { danger } from "openclaw/plugin-sdk/runtime-env";
import { materializeDiscordInboundJob, type DiscordInboundJob } from "./inbound-job.js";
import type { RuntimeEnv } from "./message-handler.preflight.types.js";
import { processDiscordMessage } from "./message-handler.process.js";

View File

@ -8,16 +8,16 @@ import {
ThreadUpdateListener,
type User,
} from "@buape/carbon";
import type { OpenClawConfig } from "../../../../src/config/config.js";
import { danger, logVerbose } from "../../../../src/globals.js";
import { formatDurationSeconds } from "../../../../src/infra/format-time/format-duration.ts";
import { enqueueSystemEvent } from "../../../../src/infra/system-events.js";
import { createSubsystemLogger } from "../../../../src/logging/subsystem.js";
import { resolveAgentRoute } from "../../../../src/routing/resolve-route.js";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { formatDurationSeconds } from "openclaw/plugin-sdk/infra-runtime";
import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
import { danger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
import {
readStoreAllowFromForDmPolicy,
resolveDmGroupAccessWithLists,
} from "../../../../src/security/dm-policy-shared.js";
} from "openclaw/plugin-sdk/security-runtime";
import {
isDiscordGroupAllowedByPolicy,
normalizeDiscordAllowList,
@ -36,11 +36,9 @@ import { isThreadArchived } from "./thread-bindings.discord-api.js";
import { closeDiscordThreadSessions } from "./thread-session-close.js";
import { normalizeDiscordListenerTimeoutMs, runDiscordTaskWithTimeout } from "./timeouts.js";
type LoadedConfig = ReturnType<typeof import("../../../../src/config/config.js").loadConfig>;
type RuntimeEnv = import("../../../../src/runtime.js").RuntimeEnv;
type Logger = ReturnType<
typeof import("../../../../src/logging/subsystem.js").createSubsystemLogger
>;
type LoadedConfig = ReturnType<typeof import("openclaw/plugin-sdk/config-runtime").loadConfig>;
type RuntimeEnv = import("openclaw/plugin-sdk/runtime-env").RuntimeEnv;
type Logger = ReturnType<typeof import("openclaw/plugin-sdk/runtime-env").createSubsystemLogger>;
export type DiscordMessageEvent = Parameters<MessageCreateListener["handle"]>[0];

View File

@ -1,5 +1,5 @@
import type { MockFn } from "openclaw/plugin-sdk/test-utils";
import { vi } from "vitest";
import type { MockFn } from "../../../../src/test-utils/vitest-mock-fn.js";
export const preflightDiscordMessageMock: MockFn = vi.fn();
export const processDiscordMessageMock: MockFn = vi.fn();

View File

@ -1,5 +1,5 @@
import { ChannelType } from "@buape/carbon";
import type { OpenClawConfig } from "../../../../src/config/config.js";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import type { preflightDiscordMessage } from "./message-handler.preflight.js";
import { createNoopThreadBindingManager } from "./thread-bindings.js";
@ -90,7 +90,7 @@ export function createDiscordPreflightArgs(params: {
discordConfig: params.discordConfig,
accountId: "default",
token: "token",
runtime: {} as import("../../../../src/runtime.js").RuntimeEnv,
runtime: {} as import("openclaw/plugin-sdk/runtime-env").RuntimeEnv,
botUserId: params.botUserId ?? "openclaw-bot",
guildHistories: new Map(),
historyLimit: 0,

View File

@ -1,36 +1,33 @@
import { ChannelType, MessageType, type User } from "@buape/carbon";
import { formatAllowlistMatchMeta } from "openclaw/plugin-sdk/channel-runtime";
import { resolveControlCommandGate } from "openclaw/plugin-sdk/channel-runtime";
import { logInboundDrop } from "openclaw/plugin-sdk/channel-runtime";
import { resolveMentionGatingWithBypass } from "openclaw/plugin-sdk/channel-runtime";
import { loadConfig } from "openclaw/plugin-sdk/config-runtime";
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/config-runtime";
import {
ensureConfiguredAcpRouteReady,
resolveConfiguredAcpRoute,
} from "../../../../src/acp/persistent-bindings.route.js";
import { hasControlCommand } from "../../../../src/auto-reply/command-detection.js";
import { shouldHandleTextCommands } from "../../../../src/auto-reply/commands-registry.js";
import {
recordPendingHistoryEntryIfEnabled,
type HistoryEntry,
} from "../../../../src/auto-reply/reply/history.js";
import {
buildMentionRegexes,
matchesMentionWithExplicit,
} from "../../../../src/auto-reply/reply/mentions.js";
import { formatAllowlistMatchMeta } from "../../../../src/channels/allowlist-match.js";
import { resolveControlCommandGate } from "../../../../src/channels/command-gating.js";
import { logInboundDrop } from "../../../../src/channels/logging.js";
import { resolveMentionGatingWithBypass } from "../../../../src/channels/mention-gating.js";
import { loadConfig } from "../../../../src/config/config.js";
import { isDangerousNameMatchingEnabled } from "../../../../src/config/dangerous-name-matching.js";
import { logVerbose, shouldLogVerbose } from "../../../../src/globals.js";
import { recordChannelActivity } from "../../../../src/infra/channel-activity.js";
} from "openclaw/plugin-sdk/conversation-runtime";
import {
getSessionBindingService,
type SessionBindingRecord,
} from "../../../../src/infra/outbound/session-binding-service.js";
import { enqueueSystemEvent } from "../../../../src/infra/system-events.js";
import { logDebug } from "../../../../src/logger.js";
import { getChildLogger } from "../../../../src/logging.js";
import { buildPairingReply } from "../../../../src/pairing/pairing-messages.js";
import { isPluginOwnedSessionBindingRecord } from "../../../../src/plugins/conversation-binding.js";
import { DEFAULT_ACCOUNT_ID } from "../../../../src/routing/session-key.js";
} from "openclaw/plugin-sdk/conversation-runtime";
import { buildPairingReply } from "openclaw/plugin-sdk/conversation-runtime";
import { isPluginOwnedSessionBindingRecord } from "openclaw/plugin-sdk/conversation-runtime";
import { recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime";
import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
import { hasControlCommand } from "openclaw/plugin-sdk/reply-runtime";
import { shouldHandleTextCommands } from "openclaw/plugin-sdk/reply-runtime";
import {
recordPendingHistoryEntryIfEnabled,
type HistoryEntry,
} from "openclaw/plugin-sdk/reply-runtime";
import { buildMentionRegexes, matchesMentionWithExplicit } from "openclaw/plugin-sdk/reply-runtime";
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/routing";
import { logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
import { getChildLogger } from "openclaw/plugin-sdk/runtime-env";
import { logDebug } from "openclaw/plugin-sdk/text-runtime";
import { fetchPluralKitMessageInfo } from "../pluralkit.js";
import { sendMessageDiscord } from "../send.js";
import {

View File

@ -1,8 +1,8 @@
import type { ChannelType, Client, User } from "@buape/carbon";
import type { HistoryEntry } from "../../../../src/auto-reply/reply/history.js";
import type { ReplyToMode } from "../../../../src/config/config.js";
import type { SessionBindingRecord } from "../../../../src/infra/outbound/session-binding-service.js";
import type { resolveAgentRoute } from "../../../../src/routing/resolve-route.js";
import type { ReplyToMode } from "openclaw/plugin-sdk/config-runtime";
import type { SessionBindingRecord } from "openclaw/plugin-sdk/conversation-runtime";
import type { HistoryEntry } from "openclaw/plugin-sdk/reply-runtime";
import type { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
import type { DiscordChannelConfigResolved, DiscordGuildEntryResolved } from "./allow-list.js";
import type { DiscordChannelInfo } from "./message-utils.js";
import type { DiscordThreadBindingLookup } from "./reply-delivery.js";
@ -11,15 +11,17 @@ import type { DiscordSenderIdentity } from "./sender-identity.js";
export type { DiscordSenderIdentity } from "./sender-identity.js";
import type { DiscordThreadChannel } from "./threading.js";
export type LoadedConfig = ReturnType<typeof import("../../../../src/config/config.js").loadConfig>;
export type RuntimeEnv = import("../../../../src/runtime.js").RuntimeEnv;
export type LoadedConfig = ReturnType<
typeof import("openclaw/plugin-sdk/config-runtime").loadConfig
>;
export type RuntimeEnv = import("openclaw/plugin-sdk/runtime-env").RuntimeEnv;
export type DiscordMessageEvent = import("./listeners.js").DiscordMessageEvent;
type DiscordMessagePreflightSharedFields = {
cfg: LoadedConfig;
discordConfig: NonNullable<
import("../../../../src/config/config.js").OpenClawConfig["channels"]
import("openclaw/plugin-sdk/config-runtime").OpenClawConfig["channels"]
>["discord"];
accountId: string;
token: string;

View File

@ -1,40 +1,40 @@
import { ChannelType, type RequestClient } from "@buape/carbon";
import { resolveAckReaction, resolveHumanDelayConfig } from "../../../../src/agents/identity.js";
import { EmbeddedBlockChunker } from "../../../../src/agents/pi-embedded-block-chunker.js";
import { resolveChunkMode } from "../../../../src/auto-reply/chunk.js";
import { dispatchInboundMessage } from "../../../../src/auto-reply/dispatch.js";
import {
formatInboundEnvelope,
resolveEnvelopeFormatOptions,
} from "../../../../src/auto-reply/envelope.js";
import {
buildPendingHistoryContextFromMap,
clearHistoryEntriesIfEnabled,
} from "../../../../src/auto-reply/reply/history.js";
import { finalizeInboundContext } from "../../../../src/auto-reply/reply/inbound-context.js";
import { createReplyDispatcherWithTyping } from "../../../../src/auto-reply/reply/reply-dispatcher.js";
import type { ReplyPayload } from "../../../../src/auto-reply/types.js";
import { shouldAckReaction as shouldAckReactionGate } from "../../../../src/channels/ack-reactions.js";
import { logTypingFailure, logAckFailure } from "../../../../src/channels/logging.js";
import { createReplyPrefixOptions } from "../../../../src/channels/reply-prefix.js";
import { recordInboundSession } from "../../../../src/channels/session.js";
import { resolveAckReaction, resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
import { EmbeddedBlockChunker } from "openclaw/plugin-sdk/agent-runtime";
import { shouldAckReaction as shouldAckReactionGate } from "openclaw/plugin-sdk/channel-runtime";
import { logTypingFailure, logAckFailure } from "openclaw/plugin-sdk/channel-runtime";
import { createReplyPrefixOptions } from "openclaw/plugin-sdk/channel-runtime";
import { recordInboundSession } from "openclaw/plugin-sdk/channel-runtime";
import {
createStatusReactionController,
DEFAULT_TIMING,
type StatusReactionAdapter,
} from "../../../../src/channels/status-reactions.js";
import { createTypingCallbacks } from "../../../../src/channels/typing.js";
import { isDangerousNameMatchingEnabled } from "../../../../src/config/dangerous-name-matching.js";
import { resolveDiscordPreviewStreamMode } from "../../../../src/config/discord-preview-streaming.js";
import { resolveMarkdownTableMode } from "../../../../src/config/markdown-tables.js";
import { readSessionUpdatedAt, resolveStorePath } from "../../../../src/config/sessions.js";
import { danger, logVerbose, shouldLogVerbose } from "../../../../src/globals.js";
import { convertMarkdownTables } from "../../../../src/markdown/tables.js";
import { getAgentScopedMediaLocalRoots } from "../../../../src/media/local-roots.js";
import { buildAgentSessionKey } from "../../../../src/routing/resolve-route.js";
import { resolveThreadSessionKeys } from "../../../../src/routing/session-key.js";
import { stripReasoningTagsFromText } from "../../../../src/shared/text/reasoning-tags.js";
import { truncateUtf16Safe } from "../../../../src/utils.js";
} from "openclaw/plugin-sdk/channel-runtime";
import { createTypingCallbacks } from "openclaw/plugin-sdk/channel-runtime";
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/config-runtime";
import { resolveDiscordPreviewStreamMode } from "openclaw/plugin-sdk/config-runtime";
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/config-runtime";
import { readSessionUpdatedAt, resolveStorePath } from "openclaw/plugin-sdk/config-runtime";
import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
import { resolveChunkMode } from "openclaw/plugin-sdk/reply-runtime";
import { dispatchInboundMessage } from "openclaw/plugin-sdk/reply-runtime";
import {
formatInboundEnvelope,
resolveEnvelopeFormatOptions,
} from "openclaw/plugin-sdk/reply-runtime";
import {
buildPendingHistoryContextFromMap,
clearHistoryEntriesIfEnabled,
} from "openclaw/plugin-sdk/reply-runtime";
import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-runtime";
import { createReplyDispatcherWithTyping } from "openclaw/plugin-sdk/reply-runtime";
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
import { buildAgentSessionKey } from "openclaw/plugin-sdk/routing";
import { resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
import { danger, logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
import { convertMarkdownTables } from "openclaw/plugin-sdk/text-runtime";
import { stripReasoningTagsFromText } from "openclaw/plugin-sdk/text-runtime";
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-runtime";
import { resolveDiscordMaxLinesPerMessage } from "../accounts.js";
import { chunkDiscordTextWithMode } from "../chunk.js";
import { resolveDiscordDraftStreamingChunking } from "../draft-chunking.js";

View File

@ -1,5 +1,5 @@
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { vi } from "vitest";
import type { OpenClawConfig } from "../../../../src/config/types.js";
import type { createDiscordMessageHandler } from "./message-handler.js";
import { createNoopThreadBindingManager } from "./thread-bindings.js";

View File

@ -2,9 +2,9 @@ import type { Client } from "@buape/carbon";
import {
createChannelInboundDebouncer,
shouldDebounceTextInbound,
} from "../../../../src/channels/inbound-debounce-policy.js";
import { resolveOpenProviderRuntimeGroupPolicy } from "../../../../src/config/runtime-group-policy.js";
import { danger } from "../../../../src/globals.js";
} from "openclaw/plugin-sdk/channel-runtime";
import { resolveOpenProviderRuntimeGroupPolicy } from "openclaw/plugin-sdk/config-runtime";
import { danger } from "openclaw/plugin-sdk/runtime-env";
import { buildDiscordInboundJob } from "./inbound-job.js";
import { createDiscordInboundWorker } from "./inbound-worker.js";
import type { DiscordMessageEvent, DiscordMessageHandler } from "./listeners.js";

View File

@ -1,10 +1,10 @@
import type { ChannelType, Client, Message } from "@buape/carbon";
import { StickerFormatType, type APIAttachment, type APIStickerItem } from "discord-api-types/v10";
import { buildMediaPayload } from "../../../../src/channels/plugins/media-payload.js";
import { logVerbose } from "../../../../src/globals.js";
import type { SsrFPolicy } from "../../../../src/infra/net/ssrf.js";
import { fetchRemoteMedia, type FetchLike } from "../../../../src/media/fetch.js";
import { saveMediaBuffer } from "../../../../src/media/store.js";
import { buildMediaPayload } from "openclaw/plugin-sdk/channel-runtime";
import type { SsrFPolicy } from "openclaw/plugin-sdk/infra-runtime";
import { fetchRemoteMedia, type FetchLike } from "openclaw/plugin-sdk/media-runtime";
import { saveMediaBuffer } from "openclaw/plugin-sdk/media-runtime";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
const DISCORD_CDN_HOSTNAMES = [
"cdn.discordapp.com",

View File

@ -1,11 +1,11 @@
import os from "node:os";
import path from "node:path";
import { normalizeAccountId as normalizeSharedAccountId } from "openclaw/plugin-sdk/account-id";
import { normalizeProviderId } from "openclaw/plugin-sdk/agent-runtime";
import { withFileLock } from "openclaw/plugin-sdk/infra-runtime";
import { resolveRequiredHomeDir } from "openclaw/plugin-sdk/infra-runtime";
import { readJsonFileWithFallback, writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
import { normalizeProviderId } from "../../../../src/agents/model-selection.js";
import { resolveStateDir } from "../../../../src/config/paths.js";
import { withFileLock } from "../../../../src/infra/file-lock.js";
import { resolveRequiredHomeDir } from "../../../../src/infra/home-dir.js";
import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
const MODEL_PICKER_PREFERENCES_LOCK_OPTIONS = {
retries: {

View File

@ -1,4 +1,4 @@
import type { ModelsProviderData } from "../../../../src/auto-reply/reply/commands-models.js";
import type { ModelsProviderData } from "openclaw/plugin-sdk/reply-runtime";
export function createModelsProviderData(
entries: Record<string, string[]>,

View File

@ -11,12 +11,12 @@ import {
} from "@buape/carbon";
import type { APISelectMenuOption } from "discord-api-types/v10";
import { ButtonStyle } from "discord-api-types/v10";
import { normalizeProviderId } from "../../../../src/agents/model-selection.js";
import { normalizeProviderId } from "openclaw/plugin-sdk/agent-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import {
buildModelsProviderData,
type ModelsProviderData,
} from "../../../../src/auto-reply/reply/commands-models.js";
import type { OpenClawConfig } from "../../../../src/config/config.js";
} from "openclaw/plugin-sdk/reply-runtime";
export const DISCORD_MODEL_PICKER_CUSTOM_ID_KEY = "mdlpk";
export const DISCORD_CUSTOM_ID_MAX_CHARS = 100;

View File

@ -1,5 +1,5 @@
import type { CommandArgs } from "../../../../src/auto-reply/commands-registry.js";
import { finalizeInboundContext } from "../../../../src/auto-reply/reply/inbound-context.js";
import type { CommandArgs } from "openclaw/plugin-sdk/reply-runtime";
import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-runtime";
import { type DiscordChannelConfigResolved, type DiscordGuildEntryResolved } from "./allow-list.js";
import { buildDiscordInboundAccessContext } from "./inbound-context.js";

View File

@ -15,19 +15,29 @@ import {
type StringSelectMenuInteraction,
} from "@buape/carbon";
import { ApplicationCommandOptionType, ButtonStyle } from "discord-api-types/v10";
import { resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
import { resolveCommandAuthorizedFromAuthorizers } from "openclaw/plugin-sdk/channel-runtime";
import { resolveNativeCommandSessionTargets } from "openclaw/plugin-sdk/channel-runtime";
import { createReplyPrefixOptions } from "openclaw/plugin-sdk/channel-runtime";
import type { OpenClawConfig, loadConfig } from "openclaw/plugin-sdk/config-runtime";
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/config-runtime";
import { resolveOpenProviderRuntimeGroupPolicy } from "openclaw/plugin-sdk/config-runtime";
import { loadSessionStore, resolveStorePath } from "openclaw/plugin-sdk/config-runtime";
import {
ensureConfiguredAcpRouteReady,
resolveConfiguredAcpRoute,
} from "../../../../src/acp/persistent-bindings.route.js";
import { resolveHumanDelayConfig } from "../../../../src/agents/identity.js";
import { resolveChunkMode, resolveTextChunkLimit } from "../../../../src/auto-reply/chunk.js";
} from "openclaw/plugin-sdk/conversation-runtime";
import { buildPairingReply } from "openclaw/plugin-sdk/conversation-runtime";
import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
import { executePluginCommand, matchPluginCommand } from "openclaw/plugin-sdk/plugin-runtime";
import { resolveChunkMode, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-runtime";
import type {
ChatCommandDefinition,
CommandArgDefinition,
CommandArgValues,
CommandArgs,
NativeCommandSpec,
} from "../../../../src/auto-reply/commands-registry.js";
} from "openclaw/plugin-sdk/reply-runtime";
import {
buildCommandTextFromArgs,
findCommandByNativeName,
@ -36,25 +46,15 @@ import {
resolveCommandArgChoices,
resolveCommandArgMenu,
serializeCommandArgs,
} from "../../../../src/auto-reply/commands-registry.js";
import { resolveStoredModelOverride } from "../../../../src/auto-reply/reply/model-selection.js";
import { dispatchReplyWithDispatcher } from "../../../../src/auto-reply/reply/provider-dispatcher.js";
import type { ReplyPayload } from "../../../../src/auto-reply/types.js";
import { resolveCommandAuthorizedFromAuthorizers } from "../../../../src/channels/command-gating.js";
import { resolveNativeCommandSessionTargets } from "../../../../src/channels/native-command-session-targets.js";
import { createReplyPrefixOptions } from "../../../../src/channels/reply-prefix.js";
import type { OpenClawConfig, loadConfig } from "../../../../src/config/config.js";
import { isDangerousNameMatchingEnabled } from "../../../../src/config/dangerous-name-matching.js";
import { resolveOpenProviderRuntimeGroupPolicy } from "../../../../src/config/runtime-group-policy.js";
import { loadSessionStore, resolveStorePath } from "../../../../src/config/sessions.js";
import { logVerbose } from "../../../../src/globals.js";
import { createSubsystemLogger } from "../../../../src/logging/subsystem.js";
import { getAgentScopedMediaLocalRoots } from "../../../../src/media/local-roots.js";
import { buildPairingReply } from "../../../../src/pairing/pairing-messages.js";
import { executePluginCommand, matchPluginCommand } from "../../../../src/plugins/commands.js";
import type { ResolvedAgentRoute } from "../../../../src/routing/resolve-route.js";
import { chunkItems } from "../../../../src/utils/chunk-items.js";
import { withTimeout } from "../../../../src/utils/with-timeout.js";
} from "openclaw/plugin-sdk/reply-runtime";
import { resolveStoredModelOverride } from "openclaw/plugin-sdk/reply-runtime";
import { dispatchReplyWithDispatcher } from "openclaw/plugin-sdk/reply-runtime";
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
import type { ResolvedAgentRoute } from "openclaw/plugin-sdk/routing";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
import { chunkItems } from "openclaw/plugin-sdk/text-runtime";
import { withTimeout } from "openclaw/plugin-sdk/text-runtime";
import { loadWebMedia } from "../../../whatsapp/src/media.js";
import { resolveDiscordMaxLinesPerMessage } from "../accounts.js";
import { chunkDiscordTextWithMode } from "../chunk.js";

View File

@ -1,5 +1,5 @@
import type { OpenClawConfig } from "../../../../src/config/config.js";
import { logVerbose } from "../../../../src/globals.js";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
type DiscordAudioAttachment = {
content_type?: string;
@ -50,8 +50,7 @@ export async function resolveDiscordPreflightAudioMentionContext(params: {
};
}
try {
const { transcribeFirstAudio } =
await import("../../../../src/media-understanding/audio-preflight.js");
const { transcribeFirstAudio } = await import("openclaw/plugin-sdk/media-runtime");
if (params.abortSignal?.aborted) {
return {
hasAudioAttachment,

View File

@ -1,5 +1,5 @@
import type { Activity, UpdatePresenceData } from "@buape/carbon/gateway";
import type { DiscordAccountConfig } from "../../../../src/config/config.js";
import type { DiscordAccountConfig } from "openclaw/plugin-sdk/config-runtime";
const DEFAULT_CUSTOM_ACTIVITY_TYPE = 4;
const CUSTOM_STATUS_NAME = "Custom Status";

View File

@ -4,11 +4,11 @@ import {
canonicalizeAllowlistWithResolvedIds,
patchAllowlistUsersInConfigEntries,
summarizeMapping,
} from "../../../../src/channels/allowlists/resolve-utils.js";
import type { DiscordGuildEntry } from "../../../../src/config/types.discord.js";
import { formatErrorMessage } from "../../../../src/infra/errors.js";
import type { RuntimeEnv } from "../../../../src/runtime.js";
import { normalizeStringEntries } from "../../../../src/shared/string-normalization.js";
} from "openclaw/plugin-sdk/channel-runtime";
import type { DiscordGuildEntry } from "openclaw/plugin-sdk/config-runtime";
import { formatErrorMessage } from "openclaw/plugin-sdk/infra-runtime";
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
import { normalizeStringEntries } from "openclaw/plugin-sdk/text-runtime";
import { resolveDiscordChannelAllowlist } from "../resolve-channels.js";
import { resolveDiscordUserAllowlist } from "../resolve-users.js";

View File

@ -1,9 +1,9 @@
import type { Client } from "@buape/carbon";
import type { GatewayPlugin } from "@buape/carbon/gateway";
import { createArmableStallWatchdog } from "../../../../src/channels/transport/stall-watchdog.js";
import { createConnectedChannelStatusPatch } from "../../../../src/gateway/channel-status-patches.js";
import { danger } from "../../../../src/globals.js";
import type { RuntimeEnv } from "../../../../src/runtime.js";
import { createArmableStallWatchdog } from "openclaw/plugin-sdk/channel-runtime";
import { createConnectedChannelStatusPatch } from "openclaw/plugin-sdk/gateway-runtime";
import { danger } from "openclaw/plugin-sdk/runtime-env";
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
import { attachDiscordGatewayLogging } from "../gateway-logging.js";
import { getDiscordGatewayEmitter, waitForDiscordGatewayStop } from "../monitor.gateway.js";
import type { DiscordVoiceManager } from "../voice/manager.js";

View File

@ -11,39 +11,45 @@ import {
import { GatewayCloseCodes, type GatewayPlugin } from "@buape/carbon/gateway";
import { VoicePlugin } from "@buape/carbon/voice";
import { Routes } from "discord-api-types/v10";
import { getAcpSessionManager } from "../../../../src/acp/control-plane/manager.js";
import { isAcpRuntimeError } from "../../../../src/acp/runtime/errors.js";
import { resolveTextChunkLimit } from "../../../../src/auto-reply/chunk.js";
import type { NativeCommandSpec } from "../../../../src/auto-reply/commands-registry.js";
import { listNativeCommandSpecsForConfig } from "../../../../src/auto-reply/commands-registry.js";
import type { HistoryEntry } from "../../../../src/auto-reply/reply/history.js";
import { listSkillCommandsForAgents } from "../../../../src/auto-reply/skill-commands.js";
import { getAcpSessionManager } from "openclaw/plugin-sdk/acp-runtime";
import { isAcpRuntimeError } from "openclaw/plugin-sdk/acp-runtime";
import {
resolveThreadBindingIdleTimeoutMs,
resolveThreadBindingMaxAgeMs,
resolveThreadBindingsEnabled,
} from "../../../../src/channels/thread-bindings-policy.js";
} from "openclaw/plugin-sdk/channel-runtime";
import {
isNativeCommandsExplicitlyDisabled,
resolveNativeCommandsEnabled,
resolveNativeSkillsEnabled,
} from "../../../../src/config/commands.js";
import type { OpenClawConfig, ReplyToMode } from "../../../../src/config/config.js";
import { loadConfig } from "../../../../src/config/config.js";
import { isDangerousNameMatchingEnabled } from "../../../../src/config/dangerous-name-matching.js";
} from "openclaw/plugin-sdk/config-runtime";
import type { OpenClawConfig, ReplyToMode } from "openclaw/plugin-sdk/config-runtime";
import { loadConfig } from "openclaw/plugin-sdk/config-runtime";
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/config-runtime";
import {
GROUP_POLICY_BLOCKED_LABEL,
resolveOpenProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
warnMissingProviderGroupPolicyFallbackOnce,
} from "../../../../src/config/runtime-group-policy.js";
import { createConnectedChannelStatusPatch } from "../../../../src/gateway/channel-status-patches.js";
import { danger, isVerbose, logVerbose, shouldLogVerbose, warn } from "../../../../src/globals.js";
import { formatErrorMessage } from "../../../../src/infra/errors.js";
import { createSubsystemLogger } from "../../../../src/logging/subsystem.js";
import { getPluginCommandSpecs } from "../../../../src/plugins/commands.js";
import { createNonExitingRuntime, type RuntimeEnv } from "../../../../src/runtime.js";
import { summarizeStringEntries } from "../../../../src/shared/string-sample.js";
} from "openclaw/plugin-sdk/config-runtime";
import { createConnectedChannelStatusPatch } from "openclaw/plugin-sdk/gateway-runtime";
import { formatErrorMessage } from "openclaw/plugin-sdk/infra-runtime";
import { getPluginCommandSpecs } from "openclaw/plugin-sdk/plugin-runtime";
import { resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-runtime";
import type { NativeCommandSpec } from "openclaw/plugin-sdk/reply-runtime";
import { listNativeCommandSpecsForConfig } from "openclaw/plugin-sdk/reply-runtime";
import type { HistoryEntry } from "openclaw/plugin-sdk/reply-runtime";
import { listSkillCommandsForAgents } from "openclaw/plugin-sdk/reply-runtime";
import {
danger,
isVerbose,
logVerbose,
shouldLogVerbose,
warn,
} from "openclaw/plugin-sdk/runtime-env";
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
import { createNonExitingRuntime, type RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
import { summarizeStringEntries } from "openclaw/plugin-sdk/text-runtime";
import { resolveDiscordAccount } from "../accounts.js";
import { getDiscordGatewayEmitter } from "../monitor.gateway.js";
import { fetchDiscordApplicationId } from "../probe.js";

View File

@ -1,13 +1,17 @@
import type { RequestClient } from "@buape/carbon";
import { resolveAgentAvatar } from "../../../../src/agents/identity-avatar.js";
import type { ChunkMode } from "../../../../src/auto-reply/chunk.js";
import type { ReplyPayload } from "../../../../src/auto-reply/types.js";
import type { OpenClawConfig } from "../../../../src/config/config.js";
import type { MarkdownTableMode, ReplyToMode } from "../../../../src/config/types.base.js";
import { createDiscordRetryRunner, type RetryRunner } from "../../../../src/infra/retry-policy.js";
import { resolveRetryConfig, retryAsync, type RetryConfig } from "../../../../src/infra/retry.js";
import { convertMarkdownTables } from "../../../../src/markdown/tables.js";
import type { RuntimeEnv } from "../../../../src/runtime.js";
import { resolveAgentAvatar } from "openclaw/plugin-sdk/agent-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import type { MarkdownTableMode, ReplyToMode } from "openclaw/plugin-sdk/config-runtime";
import { createDiscordRetryRunner, type RetryRunner } from "openclaw/plugin-sdk/infra-runtime";
import {
resolveRetryConfig,
retryAsync,
type RetryConfig,
} from "openclaw/plugin-sdk/infra-runtime";
import type { ChunkMode } from "openclaw/plugin-sdk/reply-runtime";
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
import { convertMarkdownTables } from "openclaw/plugin-sdk/text-runtime";
import { resolveDiscordAccount } from "../accounts.js";
import { chunkDiscordTextWithMode } from "../chunk.js";
import { sendMessageDiscord, sendVoiceMessageDiscord, sendWebhookMessageDiscord } from "../send.js";

View File

@ -1,7 +1,7 @@
import { wrapFetchWithAbortSignal } from "openclaw/plugin-sdk/infra-runtime";
import { danger } from "openclaw/plugin-sdk/runtime-env";
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
import { ProxyAgent, fetch as undiciFetch } from "undici";
import { danger } from "../../../../src/globals.js";
import { wrapFetchWithAbortSignal } from "../../../../src/infra/fetch.js";
import type { RuntimeEnv } from "../../../../src/runtime.js";
export function resolveDiscordRestFetch(
proxyUrl: string | undefined,

View File

@ -1,11 +1,11 @@
import type { OpenClawConfig } from "../../../../src/config/config.js";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import {
deriveLastRoutePolicy,
resolveAgentRoute,
type ResolvedAgentRoute,
type RoutePeer,
} from "../../../../src/routing/resolve-route.js";
import { resolveAgentIdFromSessionKey } from "../../../../src/routing/session-key.js";
} from "openclaw/plugin-sdk/routing";
import { resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing";
export function buildDiscordRoutePeer(params: {
isDirectMessage: boolean;

View File

@ -2,9 +2,9 @@ import {
resolveThreadBindingIdleTimeoutMs,
resolveThreadBindingMaxAgeMs,
resolveThreadBindingsEnabled,
} from "../../../../src/channels/thread-bindings-policy.js";
import type { OpenClawConfig } from "../../../../src/config/config.js";
import { normalizeAccountId } from "../../../../src/routing/session-key.js";
} from "openclaw/plugin-sdk/channel-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
export {
resolveThreadBindingIdleTimeoutMs,

View File

@ -1,6 +1,6 @@
import { ChannelType, Routes } from "discord-api-types/v10";
import type { OpenClawConfig } from "../../../../src/config/config.js";
import { logVerbose } from "../../../../src/globals.js";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
import { createDiscordRestClient } from "../client.js";
import { sendMessageDiscord, sendWebhookMessageDiscord } from "../send.js";
import { createThreadDiscord } from "../send.messages.js";

View File

@ -1,9 +1,6 @@
import {
readAcpSessionEntry,
type AcpSessionStoreEntry,
} from "../../../../src/acp/runtime/session-meta.js";
import type { OpenClawConfig } from "../../../../src/config/config.js";
import { normalizeAccountId } from "../../../../src/routing/session-key.js";
import { readAcpSessionEntry, type AcpSessionStoreEntry } from "openclaw/plugin-sdk/acp-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
import { parseDiscordTarget } from "../targets.js";
import { resolveChannelIdForBinding } from "./thread-bindings.discord-api.js";
import { getThreadBindingManager } from "./thread-bindings.manager.js";

View File

@ -1,17 +1,14 @@
import { Routes } from "discord-api-types/v10";
import { resolveThreadBindingConversationIdFromBindingId } from "../../../../src/channels/thread-binding-id.js";
import { getRuntimeConfigSnapshot, type OpenClawConfig } from "../../../../src/config/config.js";
import { logVerbose } from "../../../../src/globals.js";
import { resolveThreadBindingConversationIdFromBindingId } from "openclaw/plugin-sdk/channel-runtime";
import { getRuntimeConfigSnapshot, type OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import {
registerSessionBindingAdapter,
unregisterSessionBindingAdapter,
type BindingTargetKind,
type SessionBindingRecord,
} from "../../../../src/infra/outbound/session-binding-service.js";
import {
normalizeAccountId,
resolveAgentIdFromSessionKey,
} from "../../../../src/routing/session-key.js";
} from "openclaw/plugin-sdk/conversation-runtime";
import { normalizeAccountId, resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
import { createDiscordRestClient } from "../client.js";
import {
createThreadForBinding,

View File

@ -3,4 +3,4 @@ export {
resolveThreadBindingFarewellText,
resolveThreadBindingIntroText,
resolveThreadBindingThreadName,
} from "../../../../src/channels/thread-bindings-messages.js";
} from "openclaw/plugin-sdk/channel-runtime";

View File

@ -1,4 +1,4 @@
import { SYSTEM_MARK } from "../../../../src/infra/system-message.js";
import { SYSTEM_MARK } from "openclaw/plugin-sdk/infra-runtime";
import type { ThreadBindingRecord } from "./thread-bindings.types.js";
const THREAD_BINDING_PERSONA_MAX_CHARS = 80;

View File

@ -1,11 +1,8 @@
import fs from "node:fs";
import path from "node:path";
import { resolveStateDir } from "../../../../src/config/paths.js";
import { loadJsonFile, saveJsonFile } from "../../../../src/infra/json-file.js";
import {
normalizeAccountId,
resolveAgentIdFromSessionKey,
} from "../../../../src/routing/session-key.js";
import { loadJsonFile, saveJsonFile } from "openclaw/plugin-sdk/json-store";
import { normalizeAccountId, resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing";
import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
import {
DEFAULT_THREAD_BINDING_IDLE_TIMEOUT_MS,
DEFAULT_THREAD_BINDING_MAX_AGE_MS,

View File

@ -1,5 +1,5 @@
import type { OpenClawConfig } from "../../../../src/config/config.js";
import { resolveStorePath, updateSessionStore } from "../../../../src/config/sessions.js";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { resolveStorePath, updateSessionStore } from "openclaw/plugin-sdk/config-runtime";
/**
* Marks every session entry in the store whose key contains {@link threadId}

View File

@ -1,10 +1,10 @@
import { ChannelType, type Client } from "@buape/carbon";
import { Routes } from "discord-api-types/v10";
import { createReplyReferencePlanner } from "../../../../src/auto-reply/reply/reply-reference.js";
import type { ReplyToMode } from "../../../../src/config/config.js";
import { logVerbose } from "../../../../src/globals.js";
import { buildAgentSessionKey } from "../../../../src/routing/resolve-route.js";
import { truncateUtf16Safe } from "../../../../src/utils.js";
import type { ReplyToMode } from "openclaw/plugin-sdk/config-runtime";
import { createReplyReferencePlanner } from "openclaw/plugin-sdk/reply-runtime";
import { buildAgentSessionKey } from "openclaw/plugin-sdk/routing";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-runtime";
import type { DiscordChannelConfigResolved } from "./allow-list.js";
import type { DiscordMessageEvent } from "./listeners.js";
import {

View File

@ -2,11 +2,11 @@ import {
resolvePayloadMediaUrls,
sendPayloadMediaSequence,
sendTextMediaPayload,
} from "../../../src/channels/plugins/outbound/direct-text-media.js";
import type { ChannelOutboundAdapter } from "../../../src/channels/plugins/types.js";
import type { OpenClawConfig } from "../../../src/config/config.js";
import type { OutboundIdentity } from "../../../src/infra/outbound/identity.js";
import { resolveOutboundSendDep } from "../../../src/infra/outbound/send-deps.js";
} from "openclaw/plugin-sdk/channel-runtime";
import type { ChannelOutboundAdapter } from "openclaw/plugin-sdk/channel-runtime";
import { resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import type { OutboundIdentity } from "openclaw/plugin-sdk/infra-runtime";
import type { DiscordComponentMessageSpec } from "./components.js";
import { getThreadBindingManager, type ThreadBindingRecord } from "./monitor/thread-bindings.js";
import { normalizeDiscordOutboundTarget } from "./normalize.js";

View File

@ -1,9 +1,9 @@
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
import {
createScopedAccountConfigAccessors,
createScopedChannelConfigBase,
formatAllowFromLowercase,
} from "../../../src/plugin-sdk-internal/channel-config.js";
import { type OpenClawConfig } from "../../../src/plugin-sdk-internal/discord.js";
} from "openclaw/plugin-sdk/channel-config-helpers";
import type { OpenClawConfig } from "openclaw/plugin-sdk/discord";
import { inspectDiscordAccount } from "./account-inspect.js";
import {
listDiscordAccountIds,

View File

@ -1,4 +1,4 @@
import { resolveFetch } from "../../../src/infra/fetch.js";
import { resolveFetch } from "openclaw/plugin-sdk/infra-runtime";
const PLURALKIT_API_BASE = "https://api.pluralkit.me/v2";

View File

@ -1,6 +1,6 @@
import type { BaseProbeResult } from "../../../src/channels/plugins/types.js";
import { resolveFetch } from "../../../src/infra/fetch.js";
import { fetchWithTimeout } from "../../../src/utils/fetch-timeout.js";
import type { BaseProbeResult } from "openclaw/plugin-sdk/channel-runtime";
import { resolveFetch } from "openclaw/plugin-sdk/infra-runtime";
import { fetchWithTimeout } from "openclaw/plugin-sdk/text-runtime";
import { normalizeDiscordToken } from "./token.js";
const DISCORD_API_BASE = "https://discord.com/api/v10";

View File

@ -1,7 +1,5 @@
import {
createPluginRuntimeStore,
type PluginRuntime,
} from "../../../src/plugin-sdk-internal/core.js";
import type { PluginRuntime } from "openclaw/plugin-sdk/core";
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
const { setRuntime: setDiscordRuntime, getRuntime: getDiscordRuntime } =
createPluginRuntimeStore<PluginRuntime>("Discord runtime not initialized");

View File

@ -5,8 +5,8 @@ import {
type RequestClient,
} from "@buape/carbon";
import { ChannelType, Routes } from "discord-api-types/v10";
import { loadConfig, type OpenClawConfig } from "../../../src/config/config.js";
import { recordChannelActivity } from "../../../src/infra/channel-activity.js";
import { loadConfig, type OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime";
import { loadWebMedia } from "../../whatsapp/src/media.js";
import { resolveDiscordAccount } from "./accounts.js";
import { registerDiscordComponentEntries } from "./components-registry.js";

View File

@ -3,17 +3,17 @@ import fs from "node:fs/promises";
import path from "node:path";
import { serializePayload, type MessagePayloadObject, type RequestClient } from "@buape/carbon";
import { ChannelType, Routes } from "discord-api-types/v10";
import { resolveChunkMode } from "../../../src/auto-reply/chunk.js";
import { loadConfig, type OpenClawConfig } from "../../../src/config/config.js";
import { resolveMarkdownTableMode } from "../../../src/config/markdown-tables.js";
import { recordChannelActivity } from "../../../src/infra/channel-activity.js";
import type { RetryConfig } from "../../../src/infra/retry.js";
import { resolvePreferredOpenClawTmpDir } from "../../../src/infra/tmp-openclaw-dir.js";
import { convertMarkdownTables } from "../../../src/markdown/tables.js";
import { maxBytesForKind } from "../../../src/media/constants.js";
import { extensionForMime } from "../../../src/media/mime.js";
import { unlinkIfExists } from "../../../src/media/temp-files.js";
import type { PollInput } from "../../../src/polls.js";
import { loadConfig, type OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/config-runtime";
import { recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime";
import type { RetryConfig } from "openclaw/plugin-sdk/infra-runtime";
import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/infra-runtime";
import { maxBytesForKind } from "openclaw/plugin-sdk/media-runtime";
import { extensionForMime } from "openclaw/plugin-sdk/media-runtime";
import { unlinkIfExists } from "openclaw/plugin-sdk/media-runtime";
import type { PollInput } from "openclaw/plugin-sdk/media-runtime";
import { resolveChunkMode } from "openclaw/plugin-sdk/reply-runtime";
import { convertMarkdownTables } from "openclaw/plugin-sdk/text-runtime";
import { loadWebMediaRaw } from "../../whatsapp/src/media.js";
import { resolveDiscordAccount } from "./accounts.js";
import { rewriteDiscordKnownMentions } from "./mentions.js";

View File

@ -1,5 +1,5 @@
import { Routes } from "discord-api-types/v10";
import { loadConfig } from "../../../src/config/config.js";
import { loadConfig } from "openclaw/plugin-sdk/config-runtime";
import {
buildReactionIdentifier,
createDiscordClient,

View File

@ -9,15 +9,15 @@ import {
import { PollLayoutType } from "discord-api-types/payloads/v10";
import type { RESTAPIPoll } from "discord-api-types/rest/v10";
import { Routes, type APIChannel, type APIEmbed } from "discord-api-types/v10";
import type { ChunkMode } from "../../../src/auto-reply/chunk.js";
import { loadConfig, type OpenClawConfig } from "../../../src/config/config.js";
import type { RetryRunner } from "../../../src/infra/retry-policy.js";
import { buildOutboundMediaLoadOptions } from "../../../src/media/load-options.js";
import { loadConfig, type OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import type { RetryRunner } from "openclaw/plugin-sdk/infra-runtime";
import { buildOutboundMediaLoadOptions } from "openclaw/plugin-sdk/media-runtime";
import {
normalizePollDurationHours,
normalizePollInput,
type PollInput,
} from "../../../src/polls.js";
} from "openclaw/plugin-sdk/media-runtime";
import type { ChunkMode } from "openclaw/plugin-sdk/reply-runtime";
import { loadWebMedia } from "../../whatsapp/src/media.js";
import { resolveDiscordAccount } from "./accounts.js";
import { chunkDiscordTextWithMode } from "./chunk.js";

View File

@ -1,5 +1,5 @@
import type { MockFn } from "openclaw/plugin-sdk/test-utils";
import { vi } from "vitest";
import type { MockFn } from "../../../src/test-utils/vitest-mock-fn.js";
type DiscordWebMediaMockFactoryResult = {
loadWebMedia: MockFn;

View File

@ -1,6 +1,6 @@
import type { RequestClient } from "@buape/carbon";
import type { OpenClawConfig } from "../../../src/config/config.js";
import type { RetryConfig } from "../../../src/infra/retry.js";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import type { RetryConfig } from "openclaw/plugin-sdk/infra-runtime";
export class DiscordSendError extends Error {
kind?: "missing-permissions" | "dm-blocked";

View File

@ -1,5 +1,5 @@
import type { MsgContext } from "../../../src/auto-reply/templating.js";
import { normalizeChatType } from "../../../src/channels/chat-type.js";
import { normalizeChatType } from "openclaw/plugin-sdk/channel-runtime";
import type { MsgContext } from "openclaw/plugin-sdk/reply-runtime";
export function normalizeExplicitDiscordSessionKey(
sessionKey: string,

View File

@ -1,7 +1,10 @@
import { createPatchedAccountSetupAdapter } from "../../../src/channels/plugins/setup-helpers.js";
import type { DiscordGuildEntry } from "../../../src/config/types.discord.js";
import type { DiscordGuildEntry } from "openclaw/plugin-sdk/config-runtime";
import {
applyAccountNameToChannelSection,
DEFAULT_ACCOUNT_ID,
formatDocsLink,
migrateBaseNameToDefaultAccount,
normalizeAccountId,
noteChannelLookupFailure,
noteChannelLookupSummary,
parseMentionOrPrefixedId,
@ -9,13 +12,12 @@ import {
setLegacyChannelDmPolicyWithAllowFrom,
setSetupChannelEnabled,
type OpenClawConfig,
} from "../../../src/plugin-sdk-internal/setup.js";
} from "openclaw/plugin-sdk/setup";
import {
type ChannelSetupAdapter,
type ChannelSetupDmPolicy,
type ChannelSetupWizard,
} from "../../../src/plugin-sdk-internal/setup.js";
import { formatDocsLink } from "../../../src/terminal/links.js";
} from "openclaw/plugin-sdk/setup";
import { inspectDiscordAccount } from "./account-inspect.js";
import { listDiscordAccountIds, resolveDiscordAccount } from "./accounts.js";
@ -70,8 +72,15 @@ export function parseDiscordAllowFromId(value: string): string | null {
});
}
export const discordSetupAdapter: ChannelSetupAdapter = createPatchedAccountSetupAdapter({
channelKey: channel,
export const discordSetupAdapter: ChannelSetupAdapter = {
resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
applyAccountName: ({ cfg, accountId, name }) =>
applyAccountNameToChannelSection({
cfg,
channelKey: channel,
accountId,
name,
}),
validateInput: ({ accountId, input }) => {
if (input.useEnv && accountId !== DEFAULT_ACCOUNT_ID) {
return "DISCORD_BOT_TOKEN can only be used for the default account.";
@ -81,46 +90,57 @@ export const discordSetupAdapter: ChannelSetupAdapter = createPatchedAccountSetu
}
return null;
},
buildPatch: (input) => (input.useEnv ? {} : input.token ? { token: input.token } : {}),
});
type DiscordAllowFromResolverParams = {
cfg: OpenClawConfig;
accountId: string;
credentialValues: { token?: string };
entries: string[];
applyAccountConfig: ({ cfg, accountId, input }) => {
const namedConfig = applyAccountNameToChannelSection({
cfg,
channelKey: channel,
accountId,
name: input.name,
});
const next =
accountId !== DEFAULT_ACCOUNT_ID
? migrateBaseNameToDefaultAccount({
cfg: namedConfig,
channelKey: channel,
})
: namedConfig;
if (accountId === DEFAULT_ACCOUNT_ID) {
return {
...next,
channels: {
...next.channels,
discord: {
...next.channels?.discord,
enabled: true,
...(input.useEnv ? {} : input.token ? { token: input.token } : {}),
},
},
};
}
return {
...next,
channels: {
...next.channels,
discord: {
...next.channels?.discord,
enabled: true,
accounts: {
...next.channels?.discord?.accounts,
[accountId]: {
...next.channels?.discord?.accounts?.[accountId],
enabled: true,
...(input.token ? { token: input.token } : {}),
},
},
},
},
};
},
};
type DiscordGroupAllowlistResolverParams = DiscordAllowFromResolverParams & {
prompter: { note: (message: string, title?: string) => Promise<void> };
};
type DiscordGroupAllowlistResolution = Array<{
input: string;
resolved: boolean;
}>;
type DiscordSetupWizardHandlers = {
promptAllowFrom: (params: {
cfg: OpenClawConfig;
prompter: import("../../../src/plugin-sdk-internal/setup.js").WizardPrompter;
accountId?: string;
}) => Promise<OpenClawConfig>;
resolveAllowFromEntries: (params: DiscordAllowFromResolverParams) => Promise<
Array<{
input: string;
resolved: boolean;
id: string | null;
}>
>;
resolveGroupAllowlist: (
params: DiscordGroupAllowlistResolverParams,
) => Promise<DiscordGroupAllowlistResolution>;
};
export function createDiscordSetupWizardBase(
handlers: DiscordSetupWizardHandlers,
): ChannelSetupWizard {
export function createDiscordSetupWizardProxy(
loadWizard: () => Promise<{ discordSetupWizard: ChannelSetupWizard }>,
) {
const discordDmPolicy: ChannelSetupDmPolicy = {
label: "Discord",
channel,
@ -134,7 +154,13 @@ export function createDiscordSetupWizardBase(
channel,
dmPolicy: policy,
}),
promptAllowFrom: handlers.promptAllowFrom,
promptAllowFrom: async ({ cfg, prompter, accountId }) => {
const wizard = (await loadWizard()).discordSetupWizard;
if (!wizard.dmPolicy?.promptAllowFrom) {
return cfg;
}
return await wizard.dmPolicy.promptAllowFrom({ cfg, prompter, accountId });
},
};
return {
@ -212,22 +238,44 @@ export function createDiscordSetupWizardBase(
accountId,
patch: { groupPolicy: policy },
}),
resolveAllowlist: async (params: DiscordGroupAllowlistResolverParams) => {
resolveAllowlist: async ({
cfg,
accountId,
credentialValues,
entries,
prompter,
}: {
cfg: OpenClawConfig;
accountId: string;
credentialValues: { token?: string };
entries: string[];
prompter: { note: (message: string, title?: string) => Promise<void> };
}) => {
const wizard = (await loadWizard()).discordSetupWizard;
if (!wizard.groupAccess?.resolveAllowlist) {
return entries.map((input) => ({ input, resolved: false }));
}
try {
return await handlers.resolveGroupAllowlist(params);
return await wizard.groupAccess.resolveAllowlist({
cfg,
accountId,
credentialValues,
entries,
prompter,
});
} catch (error) {
await noteChannelLookupFailure({
prompter: params.prompter,
prompter,
label: "Discord channels",
error,
});
await noteChannelLookupSummary({
prompter: params.prompter,
prompter,
label: "Discord channels",
resolvedSections: [],
unresolved: params.entries,
unresolved: entries,
});
return params.entries.map((input) => ({ input, resolved: false }));
return entries.map((input) => ({ input, resolved: false }));
}
},
applyAllowlist: ({
@ -257,7 +305,28 @@ export function createDiscordSetupWizardBase(
invalidWithoutCredentialNote:
"Bot token missing; use numeric user ids (or mention form) only.",
parseId: parseDiscordAllowFromId,
resolveEntries: handlers.resolveAllowFromEntries,
resolveEntries: async ({
cfg,
accountId,
credentialValues,
entries,
}: {
cfg: OpenClawConfig;
accountId: string;
credentialValues: { token?: string };
entries: string[];
}) => {
const wizard = (await loadWizard()).discordSetupWizard;
if (!wizard.allowFrom) {
return entries.map((input) => ({ input, resolved: false, id: null }));
}
return await wizard.allowFrom.resolveEntries({
cfg,
accountId,
credentialValues,
entries,
});
},
apply: async ({
cfg,
accountId,
@ -278,42 +347,3 @@ export function createDiscordSetupWizardBase(
disable: (cfg: OpenClawConfig) => setSetupChannelEnabled(cfg, channel, false),
} satisfies ChannelSetupWizard;
}
export function createDiscordSetupWizardProxy(
loadWizard: () => Promise<{ discordSetupWizard: ChannelSetupWizard }>,
) {
return createDiscordSetupWizardBase({
promptAllowFrom: async ({ cfg, prompter, accountId }) => {
const wizard = (await loadWizard()).discordSetupWizard;
if (!wizard.dmPolicy?.promptAllowFrom) {
return cfg;
}
return await wizard.dmPolicy.promptAllowFrom({ cfg, prompter, accountId });
},
resolveAllowFromEntries: async ({ cfg, accountId, credentialValues, entries }) => {
const wizard = (await loadWizard()).discordSetupWizard;
if (!wizard.allowFrom) {
return entries.map((input) => ({ input, resolved: false, id: null }));
}
return await wizard.allowFrom.resolveEntries({
cfg,
accountId,
credentialValues,
entries,
});
},
resolveGroupAllowlist: async ({ cfg, accountId, credentialValues, entries, prompter }) => {
const wizard = (await loadWizard()).discordSetupWizard;
if (!wizard.groupAccess?.resolveAllowlist) {
return entries.map((input) => ({ input, resolved: false }));
}
return (await wizard.groupAccess.resolveAllowlist({
cfg,
accountId,
credentialValues,
entries,
prompter,
})) as DiscordGroupAllowlistResolution;
},
});
}

View File

@ -1,14 +1,24 @@
import {
DEFAULT_ACCOUNT_ID,
formatDocsLink,
noteChannelLookupFailure,
noteChannelLookupSummary,
type OpenClawConfig,
parseMentionOrPrefixedId,
patchChannelConfigForAccount,
promptLegacyChannelAllowFrom,
resolveSetupAccountId,
setLegacyChannelDmPolicyWithAllowFrom,
setSetupChannelEnabled,
type WizardPrompter,
} from "../../../src/plugin-sdk-internal/setup.js";
import { type ChannelSetupWizard } from "../../../src/plugin-sdk-internal/setup.js";
import { formatDocsLink } from "../../../src/terminal/links.js";
import { resolveDefaultDiscordAccountId, resolveDiscordAccount } from "./accounts.js";
} from "openclaw/plugin-sdk/setup";
import { type ChannelSetupDmPolicy, type ChannelSetupWizard } from "openclaw/plugin-sdk/setup";
import { inspectDiscordAccount } from "./account-inspect.js";
import {
listDiscordAccountIds,
resolveDefaultDiscordAccountId,
resolveDiscordAccount,
} from "./accounts.js";
import { normalizeDiscordSlug } from "./monitor/allow-list.js";
import {
resolveDiscordChannelAllowlist,
@ -16,7 +26,6 @@ import {
} from "./resolve-channels.js";
import { resolveDiscordUserAllowlist } from "./resolve-users.js";
import {
createDiscordSetupWizardBase,
discordSetupAdapter,
DISCORD_TOKEN_HELP_LINES,
parseDiscordAllowFromId,
@ -82,62 +91,186 @@ async function promptDiscordAllowFrom(params: {
});
}
export const discordSetupWizard: ChannelSetupWizard = createDiscordSetupWizardBase({
promptAllowFrom: promptDiscordAllowFrom,
resolveAllowFromEntries: async ({ cfg, accountId, credentialValues, entries }) =>
await resolveDiscordAllowFromEntries({
token:
resolveDiscordAccount({ cfg, accountId }).token ||
(typeof credentialValues.token === "string" ? credentialValues.token : ""),
entries,
const discordDmPolicy: ChannelSetupDmPolicy = {
label: "Discord",
channel,
policyKey: "channels.discord.dmPolicy",
allowFromKey: "channels.discord.allowFrom",
getCurrent: (cfg) =>
cfg.channels?.discord?.dmPolicy ?? cfg.channels?.discord?.dm?.policy ?? "pairing",
setPolicy: (cfg, policy) =>
setLegacyChannelDmPolicyWithAllowFrom({
cfg,
channel,
dmPolicy: policy,
}),
resolveGroupAllowlist: async ({ cfg, accountId, credentialValues, entries, prompter }) => {
const token =
resolveDiscordAccount({ cfg, accountId }).token ||
(typeof credentialValues.token === "string" ? credentialValues.token : "");
let resolved: DiscordChannelResolution[] = entries.map((input) => ({
input,
resolved: false,
}));
if (!token || entries.length === 0) {
return resolved;
}
try {
resolved = await resolveDiscordChannelAllowlist({
token,
entries,
});
const resolvedChannels = resolved.filter((entry) => entry.resolved && entry.channelId);
const resolvedGuilds = resolved.filter(
(entry) => entry.resolved && entry.guildId && !entry.channelId,
);
const unresolved = resolved.filter((entry) => !entry.resolved).map((entry) => entry.input);
await noteChannelLookupSummary({
prompter,
label: "Discord channels",
resolvedSections: [
{
title: "Resolved channels",
values: resolvedChannels
.map((entry) => entry.channelId)
.filter((value): value is string => Boolean(value)),
},
{
title: "Resolved guilds",
values: resolvedGuilds
.map((entry) => entry.guildId)
.filter((value): value is string => Boolean(value)),
},
],
unresolved,
});
} catch (error) {
await noteChannelLookupFailure({
prompter,
label: "Discord channels",
error,
});
}
return resolved;
promptAllowFrom: promptDiscordAllowFrom,
};
export const discordSetupWizard: ChannelSetupWizard = {
channel,
status: {
configuredLabel: "configured",
unconfiguredLabel: "needs token",
configuredHint: "configured",
unconfiguredHint: "needs token",
configuredScore: 2,
unconfiguredScore: 1,
resolveConfigured: ({ cfg }) =>
listDiscordAccountIds(cfg).some(
(accountId) => inspectDiscordAccount({ cfg, accountId }).configured,
),
},
});
credentials: [
{
inputKey: "token",
providerHint: channel,
credentialLabel: "Discord bot token",
preferredEnvVar: "DISCORD_BOT_TOKEN",
helpTitle: "Discord bot token",
helpLines: DISCORD_TOKEN_HELP_LINES,
envPrompt: "DISCORD_BOT_TOKEN detected. Use env var?",
keepPrompt: "Discord token already configured. Keep it?",
inputPrompt: "Enter Discord bot token",
allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID,
inspect: ({ cfg, accountId }) => {
const account = inspectDiscordAccount({ cfg, accountId });
return {
accountConfigured: account.configured,
hasConfiguredValue: account.tokenStatus !== "missing",
resolvedValue: account.token?.trim() || undefined,
envValue:
accountId === DEFAULT_ACCOUNT_ID
? process.env.DISCORD_BOT_TOKEN?.trim() || undefined
: undefined,
};
},
},
],
groupAccess: {
label: "Discord channels",
placeholder: "My Server/#general, guildId/channelId, #support",
currentPolicy: ({ cfg, accountId }) =>
resolveDiscordAccount({ cfg, accountId }).config.groupPolicy ?? "allowlist",
currentEntries: ({ cfg, accountId }) =>
Object.entries(resolveDiscordAccount({ cfg, accountId }).config.guilds ?? {}).flatMap(
([guildKey, value]) => {
const channels = value?.channels ?? {};
const channelKeys = Object.keys(channels);
if (channelKeys.length === 0) {
const input = /^\d+$/.test(guildKey) ? `guild:${guildKey}` : guildKey;
return [input];
}
return channelKeys.map((channelKey) => `${guildKey}/${channelKey}`);
},
),
updatePrompt: ({ cfg, accountId }) =>
Boolean(resolveDiscordAccount({ cfg, accountId }).config.guilds),
setPolicy: ({ cfg, accountId, policy }) =>
patchChannelConfigForAccount({
cfg,
channel,
accountId,
patch: { groupPolicy: policy },
}),
resolveAllowlist: async ({ cfg, accountId, credentialValues, entries, prompter }) => {
const token =
resolveDiscordAccount({ cfg, accountId }).token ||
(typeof credentialValues.token === "string" ? credentialValues.token : "");
let resolved: DiscordChannelResolution[] = entries.map((input) => ({
input,
resolved: false,
}));
if (!token || entries.length === 0) {
return resolved;
}
try {
resolved = await resolveDiscordChannelAllowlist({
token,
entries,
});
const resolvedChannels = resolved.filter((entry) => entry.resolved && entry.channelId);
const resolvedGuilds = resolved.filter(
(entry) => entry.resolved && entry.guildId && !entry.channelId,
);
const unresolved = resolved.filter((entry) => !entry.resolved).map((entry) => entry.input);
await noteChannelLookupSummary({
prompter,
label: "Discord channels",
resolvedSections: [
{
title: "Resolved channels",
values: resolvedChannels
.map((entry) => entry.channelId)
.filter((value): value is string => Boolean(value)),
},
{
title: "Resolved guilds",
values: resolvedGuilds
.map((entry) => entry.guildId)
.filter((value): value is string => Boolean(value)),
},
],
unresolved,
});
} catch (error) {
await noteChannelLookupFailure({
prompter,
label: "Discord channels",
error,
});
}
return resolved;
},
applyAllowlist: ({ cfg, accountId, resolved }) => {
const allowlistEntries: Array<{ guildKey: string; channelKey?: string }> = [];
for (const entry of resolved as DiscordChannelResolution[]) {
const guildKey =
entry.guildId ??
(entry.guildName ? normalizeDiscordSlug(entry.guildName) : undefined) ??
"*";
const channelKey =
entry.channelId ??
(entry.channelName ? normalizeDiscordSlug(entry.channelName) : undefined);
if (!channelKey && guildKey === "*") {
continue;
}
allowlistEntries.push({ guildKey, ...(channelKey ? { channelKey } : {}) });
}
return setDiscordGuildChannelAllowlist(cfg, accountId, allowlistEntries);
},
},
allowFrom: {
credentialInputKey: "token",
helpTitle: "Discord allowlist",
helpLines: [
"Allowlist Discord DMs by username (we resolve to user ids).",
"Examples:",
"- 123456789012345678",
"- @alice",
"- alice#1234",
"Multiple entries: comma-separated.",
`Docs: ${formatDocsLink("/discord", "discord")}`,
],
message: "Discord allowFrom (usernames or ids)",
placeholder: "@alice, 123456789012345678",
invalidWithoutCredentialNote: "Bot token missing; use numeric user ids (or mention form) only.",
parseId: parseDiscordAllowFromId,
resolveEntries: async ({ cfg, accountId, credentialValues, entries }) =>
await resolveDiscordAllowFromEntries({
token:
resolveDiscordAccount({ cfg, accountId }).token ||
(typeof credentialValues.token === "string" ? credentialValues.token : ""),
entries,
}),
apply: async ({ cfg, accountId, allowFrom }) =>
patchChannelConfigForAccount({
cfg,
channel,
accountId,
patch: { dmPolicy: "allowlist", allowFrom },
}),
},
dmPolicy: discordDmPolicy,
disable: (cfg) => setSetupChannelEnabled(cfg, channel, false),
};

View File

@ -1,5 +1,5 @@
import { reduceInteractiveReply } from "../../../src/channels/plugins/outbound/interactive.js";
import type { InteractiveButtonStyle, InteractiveReply } from "../../../src/interactive/payload.js";
import { reduceInteractiveReply } from "openclaw/plugin-sdk/channel-runtime";
import type { InteractiveButtonStyle, InteractiveReply } from "openclaw/plugin-sdk/channel-runtime";
import type { DiscordComponentButtonStyle, DiscordComponentMessageSpec } from "./components.js";
function resolveDiscordInteractiveButtonStyle(

View File

@ -3,11 +3,11 @@ import {
asString,
isRecord,
resolveEnabledConfiguredAccountId,
} from "../../../src/channels/plugins/status-issues/shared.js";
} from "openclaw/plugin-sdk/channel-runtime";
import type {
ChannelAccountSnapshot,
ChannelStatusIssue,
} from "../../../src/channels/plugins/types.js";
} from "openclaw/plugin-sdk/channel-runtime";
type DiscordIntentSummary = {
messageContent?: "enabled" | "limited" | "disabled";

View File

@ -1,4 +1,4 @@
import type { OpenClawPluginApi } from "../../../src/plugin-sdk-internal/core.js";
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
import { resolveDiscordAccount } from "./accounts.js";
import {
autoBindSpawnedDiscordSubagent,

View File

@ -1,4 +1,4 @@
import type { DirectoryConfigParams } from "../../../src/channels/plugins/directory-config.js";
import type { DirectoryConfigParams } from "openclaw/plugin-sdk/channel-runtime";
import {
buildMessagingTarget,
parseMentionPrefixOrAtUserTarget,
@ -6,7 +6,7 @@ import {
type MessagingTarget,
type MessagingTargetKind,
type MessagingTargetParseOptions,
} from "../../../src/channels/targets.js";
} from "openclaw/plugin-sdk/channel-runtime";
import { rememberDiscordDirectoryUser } from "./directory-cache.js";
import { listDiscordDirectoryPeersLive } from "./directory-live.js";

View File

@ -1,7 +1,7 @@
import type { BaseTokenResolution } from "../../../src/channels/plugins/types.core.js";
import type { OpenClawConfig } from "../../../src/config/config.js";
import { normalizeResolvedSecretInputString } from "../../../src/config/types.secrets.js";
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../../src/routing/session-key.js";
import type { BaseTokenResolution } from "openclaw/plugin-sdk/channel-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/config-runtime";
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/routing";
export type DiscordTokenSource = "env" | "config" | "none";

View File

@ -1,5 +1,5 @@
import { Container } from "@buape/carbon";
import type { OpenClawConfig } from "../../../src/config/config.js";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { inspectDiscordAccount } from "./account-inspect.js";
const DEFAULT_DISCORD_ACCENT_COLOR = "#5865F2";

View File

@ -14,15 +14,15 @@ import crypto from "node:crypto";
import fs from "node:fs/promises";
import path from "node:path";
import { RateLimitError, type RequestClient } from "@buape/carbon";
import type { RetryRunner } from "../../../src/infra/retry-policy.js";
import { resolvePreferredOpenClawTmpDir } from "../../../src/infra/tmp-openclaw-dir.js";
import type { RetryRunner } from "openclaw/plugin-sdk/infra-runtime";
import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/infra-runtime";
import {
parseFfprobeCodecAndSampleRate,
runFfmpeg,
runFfprobe,
} from "../../../src/media/ffmpeg-exec.js";
import { MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS } from "../../../src/media/ffmpeg-limits.js";
import { unlinkIfExists } from "../../../src/media/temp-files.js";
} from "openclaw/plugin-sdk/media-runtime";
import { MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS } from "openclaw/plugin-sdk/media-runtime";
import { unlinkIfExists } from "openclaw/plugin-sdk/media-runtime";
const DISCORD_VOICE_MESSAGE_FLAG = 1 << 13;
const SUPPRESS_NOTIFICATIONS_FLAG = 1 << 12;

View File

@ -10,10 +10,10 @@ import {
ChannelType as DiscordChannelType,
type APIApplicationCommandChannelOption,
} from "discord-api-types/v10";
import { resolveCommandAuthorizedFromAuthorizers } from "../../../../src/channels/command-gating.js";
import type { OpenClawConfig } from "../../../../src/config/config.js";
import { isDangerousNameMatchingEnabled } from "../../../../src/config/dangerous-name-matching.js";
import type { DiscordAccountConfig } from "../../../../src/config/types.js";
import { resolveCommandAuthorizedFromAuthorizers } from "openclaw/plugin-sdk/channel-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/config-runtime";
import type { DiscordAccountConfig } from "openclaw/plugin-sdk/config-runtime";
import { formatMention } from "../mentions.js";
import {
isDiscordGroupAllowedByPolicy,

View File

@ -16,20 +16,30 @@ import {
type AudioPlayer,
type VoiceConnection,
} from "@discordjs/voice";
import { resolveAgentDir } from "../../../../src/agents/agent-scope.js";
import { agentCommandFromIngress } from "../../../../src/commands/agent.js";
import type { OpenClawConfig } from "../../../../src/config/config.js";
import { isDangerousNameMatchingEnabled } from "../../../../src/config/dangerous-name-matching.js";
import type { DiscordAccountConfig, TtsConfig } from "../../../../src/config/types.js";
import { logVerbose, shouldLogVerbose } from "../../../../src/globals.js";
import { formatErrorMessage } from "../../../../src/infra/errors.js";
import { resolvePreferredOpenClawTmpDir } from "../../../../src/infra/tmp-openclaw-dir.js";
import { createSubsystemLogger } from "../../../../src/logging/subsystem.js";
import { transcribeAudioFile } from "../../../../src/media-understanding/runtime.js";
import { resolveAgentRoute } from "../../../../src/routing/resolve-route.js";
import type { RuntimeEnv } from "../../../../src/runtime.js";
import { parseTtsDirectives } from "../../../../src/tts/tts-core.js";
import { resolveTtsConfig, textToSpeech, type ResolvedTtsConfig } from "../../../../src/tts/tts.js";
import { resolveAgentDir } from "openclaw/plugin-sdk/agent-runtime";
import { agentCommandFromIngress } from "openclaw/plugin-sdk/agent-runtime";
import {
resolveTtsConfig,
textToSpeech,
type ResolvedTtsConfig,
} from "openclaw/plugin-sdk/agent-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/config-runtime";
import type { DiscordAccountConfig, TtsConfig } from "openclaw/plugin-sdk/config-runtime";
import { formatErrorMessage } from "openclaw/plugin-sdk/infra-runtime";
import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/infra-runtime";
import {
buildProviderRegistry,
createMediaAttachmentCache,
normalizeMediaAttachments,
runCapability,
} from "openclaw/plugin-sdk/media-runtime";
import type { MsgContext } from "openclaw/plugin-sdk/reply-runtime";
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
import { logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
import { parseTtsDirectives } from "openclaw/plugin-sdk/speech";
import { formatMention } from "../mentions.js";
import { resolveDiscordOwnerAccess } from "../monitor/allow-list.js";
import { formatDiscordUserTag } from "../monitor/format.js";
@ -230,13 +240,33 @@ async function transcribeAudio(params: {
agentId: string;
filePath: string;
}): Promise<string | undefined> {
const result = await transcribeAudioFile({
cfg: params.cfg,
filePath: params.filePath,
mime: "audio/wav",
agentDir: resolveAgentDir(params.cfg, params.agentId),
});
return result.text?.trim() || undefined;
const ctx: MsgContext = {
MediaPath: params.filePath,
MediaType: "audio/wav",
};
const attachments = normalizeMediaAttachments(ctx);
if (attachments.length === 0) {
return undefined;
}
const cache = createMediaAttachmentCache(attachments);
const providerRegistry = buildProviderRegistry();
try {
const result = await runCapability({
capability: "audio",
cfg: params.cfg,
ctx,
attachments: cache,
media: attachments,
agentDir: resolveAgentDir(params.cfg, params.agentId),
providerRegistry,
config: params.cfg.tools?.media?.audio,
});
const output = result.outputs.find((entry) => entry.kind === "audio.transcription");
const text = output?.text?.trim();
return text || undefined;
} finally {
await cache.cleanup();
}
}
export class DiscordVoiceManager {

View File

@ -1,5 +1,5 @@
import { emptyPluginConfigSchema, type OpenClawPluginApi } from "openclaw/plugin-sdk/core";
import { buildElevenLabsSpeechProvider } from "../../src/tts/providers/elevenlabs.js";
import { buildElevenLabsSpeechProvider } from "openclaw/plugin-sdk/speech";
const elevenLabsPlugin = {
id: "elevenlabs",

View File

@ -1,3 +1,8 @@
import {
ensureConfiguredAcpRouteReady,
resolveConfiguredAcpRoute,
} from "openclaw/plugin-sdk/conversation-runtime";
import { getSessionBindingService } from "openclaw/plugin-sdk/conversation-runtime";
import type { ClawdbotConfig, RuntimeEnv } from "openclaw/plugin-sdk/feishu";
import {
buildAgentMediaPayload,
@ -14,13 +19,8 @@ import {
resolveDefaultGroupPolicy,
warnMissingProviderGroupPolicyFallbackOnce,
} from "openclaw/plugin-sdk/feishu";
import {
ensureConfiguredAcpRouteReady,
resolveConfiguredAcpRoute,
} from "../../../src/acp/persistent-bindings.route.js";
import { getSessionBindingService } from "../../../src/infra/outbound/session-binding-service.js";
import { deriveLastRoutePolicy } from "../../../src/routing/resolve-route.js";
import { resolveAgentIdFromSessionKey } from "../../../src/routing/session-key.js";
import { deriveLastRoutePolicy } from "openclaw/plugin-sdk/routing";
import { resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing";
import { resolveFeishuAccount } from "./accounts.js";
import { createFeishuClient } from "./client.js";
import { buildFeishuConversationId } from "./conversation-id.js";

View File

@ -2,7 +2,7 @@ import fs from "fs";
import path from "path";
import { Readable } from "stream";
import { withTempDownloadPath, type ClawdbotConfig } from "openclaw/plugin-sdk/feishu";
import { mediaKindFromMime } from "../../../src/media/constants.js";
import { mediaKindFromMime } from "openclaw/plugin-sdk/media-runtime";
import { resolveFeishuAccount } from "./accounts.js";
import { createFeishuClient } from "./client.js";
import { normalizeFeishuExternalKey } from "./external-keys.js";

View File

@ -1,20 +1,17 @@
import { resolveThreadBindingConversationIdFromBindingId } from "../../../src/channels/thread-binding-id.js";
import { resolveThreadBindingConversationIdFromBindingId } from "openclaw/plugin-sdk/channel-runtime";
import {
resolveThreadBindingIdleTimeoutMsForChannel,
resolveThreadBindingMaxAgeMsForChannel,
} from "../../../src/channels/thread-bindings-policy.js";
import type { OpenClawConfig } from "../../../src/config/config.js";
} from "openclaw/plugin-sdk/channel-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import {
registerSessionBindingAdapter,
unregisterSessionBindingAdapter,
type BindingTargetKind,
type SessionBindingRecord,
} from "../../../src/infra/outbound/session-binding-service.js";
import {
normalizeAccountId,
resolveAgentIdFromSessionKey,
} from "../../../src/routing/session-key.js";
import { resolveGlobalSingleton } from "../../../src/shared/global-singleton.js";
} from "openclaw/plugin-sdk/conversation-runtime";
import { normalizeAccountId, resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing";
import { resolveGlobalSingleton } from "openclaw/plugin-sdk/text-runtime";
type FeishuBindingTargetKind = "subagent" | "acp";

View File

@ -1,6 +1,8 @@
import type { AnyAgentTool } from "../../src/agents/tools/common.js";
import { emptyPluginConfigSchema } from "../../src/plugins/config-schema.js";
import type { OpenClawPluginApi } from "../../src/plugins/types.js";
import {
emptyPluginConfigSchema,
type AnyAgentTool,
type OpenClawPluginApi,
} from "openclaw/plugin-sdk/core";
import { createFirecrawlScrapeTool } from "./src/firecrawl-scrape-tool.js";
import { createFirecrawlWebSearchProvider } from "./src/firecrawl-search-provider.js";
import { createFirecrawlSearchTool } from "./src/firecrawl-search-tool.js";

View File

@ -1,6 +1,6 @@
import type { OpenClawConfig } from "../../../src/config/config.js";
import { normalizeResolvedSecretInputString } from "../../../src/config/types.secrets.js";
import { normalizeSecretInput } from "../../../src/utils/normalize-secret-input.js";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/config-runtime";
import { normalizeSecretInput } from "openclaw/plugin-sdk/provider-auth";
export const DEFAULT_FIRECRAWL_BASE_URL = "https://api.firecrawl.dev";
export const DEFAULT_FIRECRAWL_SEARCH_TIMEOUT_SECONDS = 30;

View File

@ -1,5 +1,6 @@
import { markdownToText, truncateText } from "../../../src/agents/tools/web-fetch-utils.js";
import { withTrustedWebToolsEndpoint } from "../../../src/agents/tools/web-guarded-fetch.js";
import { markdownToText, truncateText } from "openclaw/plugin-sdk/agent-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { withTrustedWebToolsEndpoint } from "openclaw/plugin-sdk/provider-web-search";
import {
DEFAULT_CACHE_TTL_MINUTES,
normalizeCacheKey,
@ -7,9 +8,8 @@ import {
readResponseText,
resolveCacheTtlMs,
writeCache,
} from "../../../src/agents/tools/web-shared.js";
import type { OpenClawConfig } from "../../../src/config/config.js";
import { wrapExternalContent, wrapWebContent } from "../../../src/security/external-content.js";
} from "openclaw/plugin-sdk/provider-web-search";
import { wrapExternalContent, wrapWebContent } from "openclaw/plugin-sdk/security-runtime";
import {
resolveFirecrawlApiKey,
resolveFirecrawlBaseUrl,

View File

@ -1,7 +1,7 @@
import { Type } from "@sinclair/typebox";
import { optionalStringEnum } from "../../../src/agents/schema/typebox.js";
import { jsonResult, readNumberParam, readStringParam } from "../../../src/agents/tools/common.js";
import type { OpenClawPluginApi } from "../../../src/plugins/types.js";
import { optionalStringEnum } from "openclaw/plugin-sdk/agent-runtime";
import { jsonResult, readNumberParam, readStringParam } from "openclaw/plugin-sdk/agent-runtime";
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-runtime";
import { runFirecrawlScrape } from "./firecrawl-client.js";
const FirecrawlScrapeToolSchema = Type.Object(

View File

@ -1,5 +1,5 @@
import { Type } from "@sinclair/typebox";
import type { WebSearchProviderPlugin } from "../../../src/plugins/types.js";
import type { WebSearchProviderPlugin } from "openclaw/plugin-sdk/plugin-runtime";
import { runFirecrawlSearch } from "./firecrawl-client.js";
const GenericFirecrawlSearchSchema = Type.Object(

View File

@ -4,8 +4,8 @@ import {
readNumberParam,
readStringArrayParam,
readStringParam,
} from "../../../src/agents/tools/common.js";
import type { OpenClawPluginApi } from "../../../src/plugins/types.js";
} from "openclaw/plugin-sdk/agent-runtime";
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-runtime";
import { runFirecrawlSearch } from "./firecrawl-client.js";
const FirecrawlSearchToolSchema = Type.Object(

View File

@ -5,11 +5,13 @@ import {
type ProviderResolveDynamicModelContext,
type ProviderRuntimeModel,
} from "openclaw/plugin-sdk/core";
import { listProfilesForProvider } from "../../src/agents/auth-profiles/profiles.js";
import { ensureAuthProfileStore } from "../../src/agents/auth-profiles/store.js";
import { normalizeModelCompat } from "../../src/agents/model-compat.js";
import { coerceSecretRef } from "../../src/config/types.secrets.js";
import { githubCopilotLoginCommand } from "../../src/providers/github-copilot-auth.js";
import {
coerceSecretRef,
ensureAuthProfileStore,
githubCopilotLoginCommand,
listProfilesForProvider,
} from "openclaw/plugin-sdk/provider-auth";
import { normalizeModelCompat } from "openclaw/plugin-sdk/provider-models";
import { DEFAULT_COPILOT_API_BASE_URL, resolveCopilotApiToken } from "./token.js";
import { fetchCopilotUsage } from "./usage.js";

Some files were not shown because too many files have changed in this diff Show More