import { createRequire } from "node:module";
import { chunkByNewline, chunkMarkdownText, chunkMarkdownTextWithMode, chunkText, chunkTextWithMode, resolveChunkMode, resolveTextChunkLimit, } from "../../auto-reply/chunk.js";
import { hasControlCommand, isControlCommandMessage, shouldComputeCommandAuthorized, } from "../../auto-reply/command-detection.js";
import { shouldHandleTextCommands } from "../../auto-reply/commands-registry.js";
import { createInboundDebouncer, resolveInboundDebounceMs, } from "../../auto-reply/inbound-debounce.js";
import { formatAgentEnvelope, formatInboundEnvelope, resolveEnvelopeFormatOptions, } from "../../auto-reply/envelope.js";
import { dispatchReplyFromConfig } from "../../auto-reply/reply/dispatch-from-config.js";
import { buildMentionRegexes, matchesMentionPatterns, matchesMentionWithExplicit, } from "../../auto-reply/reply/mentions.js";
import { dispatchReplyWithBufferedBlockDispatcher } from "../../auto-reply/reply/provider-dispatcher.js";
import { createReplyDispatcherWithTyping } from "../../auto-reply/reply/reply-dispatcher.js";
import { finalizeInboundContext } from "../../auto-reply/reply/inbound-context.js";
import { resolveEffectiveMessagesConfig, resolveHumanDelayConfig } from "../../agents/identity.js";
import { createMemoryGetTool, createMemorySearchTool } from "../../agents/tools/memory-tool.js";
import { handleSlackAction } from "../../agents/tools/slack-actions.js";
import { handleWhatsAppAction } from "../../agents/tools/whatsapp-actions.js";
import { removeAckReactionAfterReply, shouldAckReaction } from "../../channels/ack-reactions.js";
import { resolveCommandAuthorizedFromAuthorizers } from "../../channels/command-gating.js";
import { recordInboundSession } from "../../channels/session.js";
import { discordMessageActions } from "../../channels/plugins/actions/discord.js";
import { signalMessageActions } from "../../channels/plugins/actions/signal.js";
import { telegramMessageActions } from "../../channels/plugins/actions/telegram.js";
import { createWhatsAppLoginTool } from "../../channels/plugins/agent-tools/whatsapp-login.js";
import { monitorWebChannel } from "../../channels/web/index.js";
import { resolveChannelGroupPolicy, resolveChannelGroupRequireMention, } from "../../config/group-policy.js";
import { resolveMarkdownTableMode } from "../../config/markdown-tables.js";
import { resolveStateDir } from "../../config/paths.js";
import { loadConfig, writeConfigFile } from "../../config/config.js";
import { readSessionUpdatedAt, recordSessionMetaFromInbound, resolveStorePath, updateLastRoute, } from "../../config/sessions.js";
import { auditDiscordChannelPermissions } from "../../discord/audit.js";
import { listDiscordDirectoryGroupsLive, listDiscordDirectoryPeersLive, } from "../../discord/directory-live.js";
import { monitorDiscordProvider } from "../../discord/monitor.js";
import { probeDiscord } from "../../discord/probe.js";
import { resolveDiscordChannelAllowlist } from "../../discord/resolve-channels.js";
import { resolveDiscordUserAllowlist } from "../../discord/resolve-users.js";
import { sendMessageDiscord, sendPollDiscord } from "../../discord/send.js";
import { getChannelActivity, recordChannelActivity } from "../../infra/channel-activity.js";
import { enqueueSystemEvent } from "../../infra/system-events.js";
import { monitorIMessageProvider } from "../../imessage/monitor.js";
import { probeIMessage } from "../../imessage/probe.js";
import { sendMessageIMessage } from "../../imessage/send.js";
import { shouldLogVerbose } from "../../globals.js";
import { convertMarkdownTables } from "../../markdown/tables.js";
import { getChildLogger } from "../../logging.js";
import { normalizeLogLevel } from "../../logging/levels.js";
import { isVoiceCompatibleAudio } from "../../media/audio.js";
import { mediaKindFromMime } from "../../media/constants.js";
import { fetchRemoteMedia } from "../../media/fetch.js";
import { getImageMetadata, resizeToJpeg } from "../../media/image-ops.js";
import { detectMime } from "../../media/mime.js";
import { saveMediaBuffer } from "../../media/store.js";
import { buildPairingReply } from "../../pairing/pairing-messages.js";
import { readChannelAllowFromStore, upsertChannelPairingRequest, } from "../../pairing/pairing-store.js";
import { resolveAgentRoute } from "../../routing/resolve-route.js";
import { monitorSignalProvider } from "../../signal/index.js";
import { probeSignal } from "../../signal/probe.js";
import { sendMessageSignal } from "../../signal/send.js";
import { monitorSlackProvider } from "../../slack/index.js";
import { listSlackDirectoryGroupsLive, listSlackDirectoryPeersLive, } from "../../slack/directory-live.js";
import { probeSlack } from "../../slack/probe.js";
import { resolveSlackChannelAllowlist } from "../../slack/resolve-channels.js";
import { resolveSlackUserAllowlist } from "../../slack/resolve-users.js";
import { sendMessageSlack } from "../../slack/send.js";
import { auditTelegramGroupMembership, collectTelegramUnmentionedGroupIds, } from "../../telegram/audit.js";
import { monitorTelegramProvider } from "../../telegram/monitor.js";
import { probeTelegram } from "../../telegram/probe.js";
import { sendMessageTelegram } from "../../telegram/send.js";
import { resolveTelegramToken } from "../../telegram/token.js";
import { loadWebMedia } from "../../web/media.js";
import { getActiveWebListener } from "../../web/active-listener.js";
import { getWebAuthAgeMs, logoutWeb, logWebSelfId, readWebSelfId, webAuthExists, } from "../../web/auth-store.js";
import { loginWeb } from "../../web/login.js";
import { startWebLoginWithQr, waitForWebLogin } from "../../web/login-qr.js";
import { sendMessageWhatsApp, sendPollWhatsApp } from "../../web/outbound.js";
import { registerMemoryCli } from "../../cli/memory-cli.js";
import { formatNativeDependencyHint } from "./native-deps.js";
import { textToSpeechTelephony } from "../../tts/tts.js";
import { listLineAccountIds, normalizeAccountId as normalizeLineAccountId, resolveDefaultLineAccountId, resolveLineAccount, } from "../../line/accounts.js";
import { probeLineBot } from "../../line/probe.js";
import { createQuickReplyItems, pushMessageLine, pushMessagesLine, pushFlexMessage, pushTemplateMessage, pushLocationMessage, pushTextMessageWithQuickReplies, sendMessageLine, } from "../../line/send.js";
import { monitorLineProvider } from "../../line/monitor.js";
import { buildTemplateMessageFromPayload } from "../../line/template-messages.js";
let cachedVersion = null;
function resolveVersion() {
    if (cachedVersion)
        return cachedVersion;
    try {
        const require = createRequire(import.meta.url);
        const pkg = require("../../../package.json");
        // Prefer openclawVersion (upstream-compatible date-based version)
        // so third-party plugins that check host compatibility pass.
        cachedVersion = pkg.openclawVersion ?? pkg.version ?? "unknown";
        return cachedVersion;
    }
    catch {
        cachedVersion = "unknown";
        return cachedVersion;
    }
}
const runtimeCommandExecutionDisabled = async () => {
    throw new Error("runtime.system.runCommandWithTimeout 已因安全加固被禁用。请使用专用的 runtime API 代替。 ");
};
export function createPluginRuntime() {
    return {
        version: resolveVersion(),
        config: {
            loadConfig,
            writeConfigFile,
        },
        system: {
            enqueueSystemEvent,
            runCommandWithTimeout: runtimeCommandExecutionDisabled,
            formatNativeDependencyHint,
        },
        media: {
            loadWebMedia,
            detectMime,
            mediaKindFromMime,
            isVoiceCompatibleAudio,
            getImageMetadata,
            resizeToJpeg,
        },
        tts: {
            textToSpeechTelephony,
        },
        tools: {
            createMemoryGetTool,
            createMemorySearchTool,
            registerMemoryCli,
        },
        channel: {
            text: {
                chunkByNewline,
                chunkMarkdownText,
                chunkMarkdownTextWithMode,
                chunkText,
                chunkTextWithMode,
                resolveChunkMode,
                resolveTextChunkLimit,
                hasControlCommand,
                resolveMarkdownTableMode,
                convertMarkdownTables,
            },
            reply: {
                dispatchReplyWithBufferedBlockDispatcher,
                createReplyDispatcherWithTyping,
                resolveEffectiveMessagesConfig,
                resolveHumanDelayConfig,
                dispatchReplyFromConfig,
                finalizeInboundContext,
                formatAgentEnvelope,
                formatInboundEnvelope,
                resolveEnvelopeFormatOptions,
                withReplyDispatcher: async ({ dispatcher, run }) => {
                    try {
                        await run();
                    }
                    finally {
                        await dispatcher.waitForIdle();
                    }
                },
            },
            routing: {
                resolveAgentRoute,
            },
            pairing: {
                buildPairingReply,
                // Official plugins call readAllowFromStore({ channel, accountId? }) — an object.
                // The underlying readChannelAllowFromStore signature is (channel, env, accountId?)
                // so we wrap it here to accept the object form used by extension plugins.
                readAllowFromStore: ({ channel, accountId, env, }) => readChannelAllowFromStore(channel, env ?? process.env, accountId),
                upsertPairingRequest: upsertChannelPairingRequest,
            },
            media: {
                fetchRemoteMedia,
                saveMediaBuffer,
            },
            activity: {
                record: recordChannelActivity,
                get: getChannelActivity,
            },
            session: {
                resolveStorePath,
                readSessionUpdatedAt,
                recordSessionMetaFromInbound,
                recordInboundSession,
                updateLastRoute,
            },
            mentions: {
                buildMentionRegexes,
                matchesMentionPatterns,
                matchesMentionWithExplicit,
            },
            reactions: {
                shouldAckReaction,
                removeAckReactionAfterReply,
            },
            groups: {
                resolveGroupPolicy: resolveChannelGroupPolicy,
                resolveRequireMention: resolveChannelGroupRequireMention,
            },
            debounce: {
                createInboundDebouncer,
                resolveInboundDebounceMs,
            },
            commands: {
                resolveCommandAuthorizedFromAuthorizers,
                isControlCommandMessage,
                shouldComputeCommandAuthorized,
                shouldHandleTextCommands,
            },
            discord: {
                messageActions: discordMessageActions,
                auditChannelPermissions: auditDiscordChannelPermissions,
                listDirectoryGroupsLive: listDiscordDirectoryGroupsLive,
                listDirectoryPeersLive: listDiscordDirectoryPeersLive,
                probeDiscord,
                resolveChannelAllowlist: resolveDiscordChannelAllowlist,
                resolveUserAllowlist: resolveDiscordUserAllowlist,
                sendMessageDiscord,
                sendPollDiscord,
                monitorDiscordProvider,
            },
            slack: {
                listDirectoryGroupsLive: listSlackDirectoryGroupsLive,
                listDirectoryPeersLive: listSlackDirectoryPeersLive,
                probeSlack,
                resolveChannelAllowlist: resolveSlackChannelAllowlist,
                resolveUserAllowlist: resolveSlackUserAllowlist,
                sendMessageSlack,
                monitorSlackProvider,
                handleSlackAction,
            },
            telegram: {
                auditGroupMembership: auditTelegramGroupMembership,
                collectUnmentionedGroupIds: collectTelegramUnmentionedGroupIds,
                probeTelegram,
                resolveTelegramToken,
                sendMessageTelegram,
                monitorTelegramProvider,
                messageActions: telegramMessageActions,
            },
            signal: {
                probeSignal,
                sendMessageSignal,
                monitorSignalProvider,
                messageActions: signalMessageActions,
            },
            imessage: {
                monitorIMessageProvider,
                probeIMessage,
                sendMessageIMessage,
            },
            whatsapp: {
                getActiveWebListener,
                getWebAuthAgeMs,
                logoutWeb,
                logWebSelfId,
                readWebSelfId,
                webAuthExists,
                sendMessageWhatsApp,
                sendPollWhatsApp,
                loginWeb,
                startWebLoginWithQr,
                waitForWebLogin,
                monitorWebChannel,
                handleWhatsAppAction,
                createLoginTool: createWhatsAppLoginTool,
            },
            line: {
                listLineAccountIds,
                resolveDefaultLineAccountId,
                resolveLineAccount,
                normalizeAccountId: normalizeLineAccountId,
                probeLineBot,
                sendMessageLine,
                pushMessageLine,
                pushMessagesLine,
                pushFlexMessage,
                pushTemplateMessage,
                pushLocationMessage,
                pushTextMessageWithQuickReplies,
                createQuickReplyItems,
                buildTemplateMessageFromPayload,
                monitorLineProvider,
            },
        },
        logging: {
            shouldLogVerbose,
            getChildLogger: (bindings, opts) => {
                const logger = getChildLogger(bindings, {
                    level: opts?.level ? normalizeLogLevel(opts.level) : undefined,
                });
                return {
                    debug: (message) => logger.debug?.(message),
                    info: (message) => logger.info(message),
                    warn: (message) => logger.warn(message),
                    error: (message) => logger.error(message),
                };
            },
        },
        state: {
            resolveStateDir,
        },
    };
}
