mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-23 22:55:24 +00:00
refactor: clean bundled channel bootstrap boundaries
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
export { bluebubblesPlugin } from "./src/channel.js";
|
||||
export { bluebubblesSetupPlugin } from "./src/channel.setup.js";
|
||||
export * from "./src/conversation-id.js";
|
||||
export * from "./src/conversation-bindings.js";
|
||||
export { collectBlueBubblesStatusIssues } from "./src/status-issues.js";
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { bluebubblesPlugin } from "./src/channel.js";
|
||||
import { setBlueBubblesRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { bluebubblesPlugin } from "./src/channel.js";
|
||||
export { setBlueBubblesRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "bluebubbles",
|
||||
name: "BlueBubbles",
|
||||
description: "BlueBubbles channel plugin (macOS app)",
|
||||
plugin: bluebubblesPlugin,
|
||||
setRuntime: setBlueBubblesRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "bluebubblesPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setBlueBubblesRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,3 +2,4 @@ export {
|
||||
resolveBlueBubblesGroupRequireMention,
|
||||
resolveBlueBubblesGroupToolPolicy,
|
||||
} from "./src/group-policy.js";
|
||||
export { setBlueBubblesRuntime } from "./src/runtime.js";
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { bluebubblesSetupPlugin } from "./src/channel.setup.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { bluebubblesSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default defineSetupPluginEntry(bluebubblesSetupPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "bluebubblesSetupPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
export { discordPlugin } from "./src/channel.js";
|
||||
export { discordSetupPlugin } from "./src/channel.setup.js";
|
||||
export {
|
||||
handleDiscordSubagentDeliveryTarget,
|
||||
handleDiscordSubagentEnded,
|
||||
handleDiscordSubagentSpawning,
|
||||
} from "./src/subagent-hooks.js";
|
||||
export * from "./src/account-inspect.js";
|
||||
export * from "./src/accounts.js";
|
||||
export * from "./src/actions/handle-action.guild-admin.js";
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { discordPlugin } from "./src/channel.js";
|
||||
import { setDiscordRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { discordPlugin } from "./src/channel.js";
|
||||
export { setDiscordRuntime } from "./src/runtime.js";
|
||||
|
||||
type DiscordSubagentHooksModule = typeof import("./src/subagent-hooks.js");
|
||||
type DiscordSubagentHooksModule = typeof import("./api.js");
|
||||
|
||||
let discordSubagentHooksPromise: Promise<DiscordSubagentHooksModule> | null = null;
|
||||
|
||||
function loadDiscordSubagentHooksModule() {
|
||||
discordSubagentHooksPromise ??= import("./src/subagent-hooks.js");
|
||||
discordSubagentHooksPromise ??= import("./api.js");
|
||||
return discordSubagentHooksPromise;
|
||||
}
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "discord",
|
||||
name: "Discord",
|
||||
description: "Discord channel plugin",
|
||||
plugin: discordPlugin,
|
||||
setRuntime: setDiscordRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "discordPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setDiscordRuntime",
|
||||
},
|
||||
registerFull(api) {
|
||||
api.on("subagent_spawning", async (event) => {
|
||||
const { handleDiscordSubagentSpawning } = await loadDiscordSubagentHooksModule();
|
||||
|
||||
@@ -17,3 +17,4 @@ export * from "./src/resolve-users.js";
|
||||
export * from "./src/outbound-session-route.js";
|
||||
export * from "./src/send.js";
|
||||
export * from "./src/send.components.js";
|
||||
export { setDiscordRuntime } from "./src/runtime.js";
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { discordSetupPlugin } from "./src/channel.setup.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { discordSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default defineSetupPluginEntry(discordSetupPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "discordSetupPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
export { feishuPlugin } from "./src/channel.js";
|
||||
export { registerFeishuDocTools } from "./src/docx.js";
|
||||
export { registerFeishuChatTools } from "./src/chat.js";
|
||||
export { registerFeishuWikiTools } from "./src/wiki.js";
|
||||
export { registerFeishuDriveTools } from "./src/drive.js";
|
||||
export { registerFeishuPermTools } from "./src/perm.js";
|
||||
export { registerFeishuBitableTools } from "./src/bitable.js";
|
||||
export {
|
||||
handleFeishuSubagentDeliveryTarget,
|
||||
handleFeishuSubagentEnded,
|
||||
handleFeishuSubagentSpawning,
|
||||
} from "./src/subagent-hooks.js";
|
||||
export * from "./src/conversation-id.js";
|
||||
export * from "./src/setup-core.js";
|
||||
export * from "./src/setup-surface.js";
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { feishuPlugin } from "./src/channel.js";
|
||||
import { setFeishuRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { feishuPlugin } from "./src/channel.js";
|
||||
export { setFeishuRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "feishu",
|
||||
name: "Feishu",
|
||||
description: "Feishu/Lark channel plugin",
|
||||
plugin: feishuPlugin,
|
||||
setRuntime: setFeishuRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "feishuPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setFeishuRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,78 +1,79 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { registerFeishuBitableTools } from "./src/bitable.js";
|
||||
import { feishuPlugin } from "./src/channel.js";
|
||||
import { registerFeishuChatTools } from "./src/chat.js";
|
||||
import { registerFeishuDocTools } from "./src/docx.js";
|
||||
import { registerFeishuDriveTools } from "./src/drive.js";
|
||||
import { registerFeishuPermTools } from "./src/perm.js";
|
||||
import { setFeishuRuntime } from "./src/runtime.js";
|
||||
import { registerFeishuWikiTools } from "./src/wiki.js";
|
||||
import {
|
||||
defineBundledChannelEntry,
|
||||
loadBundledEntryExportSync,
|
||||
} from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { feishuPlugin } from "./src/channel.js";
|
||||
export { setFeishuRuntime } from "./src/runtime.js";
|
||||
export {
|
||||
sendMessageFeishu,
|
||||
sendCardFeishu,
|
||||
updateCardFeishu,
|
||||
editMessageFeishu,
|
||||
getMessageFeishu,
|
||||
} from "./src/send.js";
|
||||
export {
|
||||
uploadImageFeishu,
|
||||
uploadFileFeishu,
|
||||
sendImageFeishu,
|
||||
sendFileFeishu,
|
||||
sendMediaFeishu,
|
||||
} from "./src/media.js";
|
||||
export { probeFeishu } from "./src/probe.js";
|
||||
export {
|
||||
addReactionFeishu,
|
||||
removeReactionFeishu,
|
||||
listReactionsFeishu,
|
||||
FeishuEmoji,
|
||||
} from "./src/reactions.js";
|
||||
export {
|
||||
extractMentionTargets,
|
||||
extractMessageBody,
|
||||
isMentionForwardRequest,
|
||||
formatMentionForText,
|
||||
formatMentionForCard,
|
||||
formatMentionAllForText,
|
||||
formatMentionAllForCard,
|
||||
buildMentionedMessage,
|
||||
buildMentionedCardContent,
|
||||
type MentionTarget,
|
||||
} from "./src/mention.js";
|
||||
type FeishuSubagentHooksModule = typeof import("./api.js");
|
||||
|
||||
type MonitorFeishuProvider = typeof import("./src/monitor.js").monitorFeishuProvider;
|
||||
type FeishuSubagentHooksModule = typeof import("./src/subagent-hooks.js");
|
||||
|
||||
let feishuMonitorPromise: Promise<typeof import("./src/monitor.js")> | null = null;
|
||||
let feishuSubagentHooksPromise: Promise<FeishuSubagentHooksModule> | null = null;
|
||||
|
||||
function loadFeishuMonitorModule() {
|
||||
feishuMonitorPromise ??= import("./src/monitor.js");
|
||||
return feishuMonitorPromise;
|
||||
}
|
||||
|
||||
function loadFeishuSubagentHooksModule() {
|
||||
feishuSubagentHooksPromise ??= import("./src/subagent-hooks.js");
|
||||
feishuSubagentHooksPromise ??= import("./api.js");
|
||||
return feishuSubagentHooksPromise;
|
||||
}
|
||||
|
||||
export async function monitorFeishuProvider(
|
||||
...args: Parameters<MonitorFeishuProvider>
|
||||
): ReturnType<MonitorFeishuProvider> {
|
||||
const { monitorFeishuProvider } = await loadFeishuMonitorModule();
|
||||
return await monitorFeishuProvider(...args);
|
||||
function registerFeishuDocTools(api: OpenClawPluginApi) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerFeishuDocTools",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
function registerFeishuChatTools(api: OpenClawPluginApi) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerFeishuChatTools",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
function registerFeishuWikiTools(api: OpenClawPluginApi) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerFeishuWikiTools",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
function registerFeishuDriveTools(api: OpenClawPluginApi) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerFeishuDriveTools",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
function registerFeishuPermTools(api: OpenClawPluginApi) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerFeishuPermTools",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
function registerFeishuBitableTools(api: OpenClawPluginApi) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerFeishuBitableTools",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
export default defineBundledChannelEntry({
|
||||
id: "feishu",
|
||||
name: "Feishu",
|
||||
description: "Feishu/Lark channel plugin",
|
||||
plugin: feishuPlugin,
|
||||
setRuntime: setFeishuRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "feishuPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setFeishuRuntime",
|
||||
},
|
||||
registerFull(api) {
|
||||
api.on("subagent_spawning", async (event, ctx) => {
|
||||
const { handleFeishuSubagentSpawning } = await loadFeishuSubagentHooksModule();
|
||||
|
||||
@@ -49,3 +49,4 @@ export {
|
||||
readRequestBodyWithLimit,
|
||||
requestBodyErrorToText,
|
||||
} from "openclaw/plugin-sdk/webhook-ingress";
|
||||
export { setFeishuRuntime } from "./src/runtime.js";
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { feishuPlugin } from "./src/channel.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export default defineSetupPluginEntry(feishuPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "feishuPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export { googlechatPlugin } from "./src/channel.js";
|
||||
export * from "./src/setup-core.js";
|
||||
export * from "./src/setup-surface.js";
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import type { ChannelPlugin } from "openclaw/plugin-sdk/channel-core";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { googlechatPlugin } from "./src/channel.js";
|
||||
import { setGoogleChatRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { googlechatPlugin } from "./src/channel.js";
|
||||
export { setGoogleChatRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "googlechat",
|
||||
name: "Google Chat",
|
||||
description: "OpenClaw Google Chat channel plugin",
|
||||
plugin: googlechatPlugin as ChannelPlugin,
|
||||
setRuntime: setGoogleChatRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "googlechatPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setGoogleChatRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -60,3 +60,4 @@ export {
|
||||
readJsonWebhookBodyOrReject,
|
||||
type WebhookInFlightLimiter,
|
||||
} from "openclaw/plugin-sdk/webhook-request-guards";
|
||||
export { setGoogleChatRuntime } from "./src/runtime.js";
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { googlechatPlugin } from "./src/channel.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export default defineSetupPluginEntry(googlechatPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "googlechatPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export { imessagePlugin } from "./src/channel.js";
|
||||
export { imessageSetupPlugin } from "./src/channel.setup.js";
|
||||
export * from "./src/accounts.js";
|
||||
export * from "./src/conversation-bindings.js";
|
||||
export * from "./src/conversation-id.js";
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { imessagePlugin } from "./src/channel.js";
|
||||
import { setIMessageRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { imessagePlugin } from "./src/channel.js";
|
||||
export { setIMessageRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "imessage",
|
||||
name: "iMessage",
|
||||
description: "iMessage channel plugin",
|
||||
plugin: imessagePlugin,
|
||||
setRuntime: setIMessageRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "imessagePlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setIMessageRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -29,6 +29,7 @@ export type { MonitorIMessageOpts } from "./src/monitor.js";
|
||||
export { probeIMessage } from "./src/probe.js";
|
||||
export type { IMessageProbe } from "./src/probe.js";
|
||||
export { sendMessageIMessage } from "./src/send.js";
|
||||
export { setIMessageRuntime } from "./src/runtime.js";
|
||||
export { chunkTextForOutbound } from "./src/channel-api.js";
|
||||
|
||||
export type IMessageAccountConfig = Omit<
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { imessageSetupPlugin } from "./src/channel.setup.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { imessageSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default defineSetupPluginEntry(imessageSetupPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "imessageSetupPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
export { ircPlugin } from "./src/channel.js";
|
||||
export { setIrcRuntime } from "./src/runtime.js";
|
||||
export * from "./src/accounts.js";
|
||||
export * from "./src/setup-surface.js";
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import type { ChannelPlugin } from "openclaw/plugin-sdk/channel-core";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { ircPlugin } from "./src/channel.js";
|
||||
import { setIrcRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { ircPlugin } from "./src/channel.js";
|
||||
export { setIrcRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "irc",
|
||||
name: "IRC",
|
||||
description: "IRC channel plugin",
|
||||
plugin: ircPlugin as ChannelPlugin,
|
||||
setRuntime: setIrcRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "ircPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./api.js",
|
||||
exportName: "setIrcRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { ircPlugin } from "./src/channel.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export default defineSetupPluginEntry(ircPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "ircPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -40,5 +40,8 @@ export {
|
||||
setSetupChannelEnabled,
|
||||
splitSetupEntries,
|
||||
} from "./runtime-api.js";
|
||||
export { linePlugin } from "./src/channel.js";
|
||||
export { lineSetupPlugin } from "./src/channel.setup.js";
|
||||
export { registerLineCardCommand } from "./src/card-command.js";
|
||||
export * from "./runtime-api.js";
|
||||
export * from "./setup-api.js";
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { defineChannelPluginEntry, type OpenClawPluginApi } from "openclaw/plugin-sdk/channel-core";
|
||||
import { linePlugin } from "./src/channel.js";
|
||||
import { setLineRuntime } from "./src/runtime.js";
|
||||
|
||||
export { linePlugin } from "./src/channel.js";
|
||||
export { setLineRuntime } from "./src/runtime.js";
|
||||
import {
|
||||
defineBundledChannelEntry,
|
||||
type OpenClawPluginApi,
|
||||
} from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
type RegisteredLineCardCommand = Parameters<OpenClawPluginApi["registerCommand"]>[0];
|
||||
|
||||
@@ -12,7 +10,7 @@ let lineCardCommandPromise: Promise<RegisteredLineCardCommand> | null = null;
|
||||
async function loadLineCardCommand(api: OpenClawPluginApi): Promise<RegisteredLineCardCommand> {
|
||||
lineCardCommandPromise ??= (async () => {
|
||||
let registered: RegisteredLineCardCommand | null = null;
|
||||
const { registerLineCardCommand } = await import("./src/card-command.js");
|
||||
const { registerLineCardCommand } = await import("./api.js");
|
||||
registerLineCardCommand({
|
||||
...api,
|
||||
registerCommand(command: RegisteredLineCardCommand) {
|
||||
@@ -27,12 +25,19 @@ async function loadLineCardCommand(api: OpenClawPluginApi): Promise<RegisteredLi
|
||||
return await lineCardCommandPromise;
|
||||
}
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "line",
|
||||
name: "LINE",
|
||||
description: "LINE Messaging API channel plugin",
|
||||
plugin: linePlugin,
|
||||
setRuntime: setLineRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "linePlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setLineRuntime",
|
||||
},
|
||||
registerFull(api) {
|
||||
api.registerCommand({
|
||||
name: "card",
|
||||
|
||||
@@ -26,6 +26,7 @@ export {
|
||||
setSetupChannelEnabled,
|
||||
splitSetupEntries,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
export { setLineRuntime } from "./src/runtime.js";
|
||||
// Keep named exports explicit here so the runtime barrel stays self-contained
|
||||
// and plugin-sdk can re-export this file directly without reaching into
|
||||
// extension internals.
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { lineSetupPlugin } from "./src/channel.setup.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { lineSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default defineSetupPluginEntry(lineSetupPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "lineSetupPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export { matrixPlugin } from "./src/channel.js";
|
||||
export * from "./src/setup-core.js";
|
||||
export * from "./src/setup-surface.js";
|
||||
export * from "./src/account-selection.js";
|
||||
|
||||
@@ -1,20 +1,33 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { matrixPlugin } from "./src/channel.js";
|
||||
import { registerMatrixCliMetadata } from "./src/cli-metadata.js";
|
||||
import { setMatrixRuntime } from "./src/runtime.js";
|
||||
import {
|
||||
defineBundledChannelEntry,
|
||||
loadBundledEntryExportSync,
|
||||
} from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { matrixPlugin } from "./src/channel.js";
|
||||
export { setMatrixRuntime } from "./src/runtime.js";
|
||||
function registerMatrixCliMetadata(api: OpenClawPluginApi) {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./cli-metadata.js",
|
||||
exportName: "registerMatrixCliMetadata",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "matrix",
|
||||
name: "Matrix",
|
||||
description: "Matrix channel plugin (matrix-js-sdk)",
|
||||
plugin: matrixPlugin,
|
||||
setRuntime: setMatrixRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "matrixPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setMatrixRuntime",
|
||||
},
|
||||
registerCliMetadata: registerMatrixCliMetadata,
|
||||
registerFull(api) {
|
||||
void import("./src/plugin-entry.runtime.js")
|
||||
void import("./plugin-entry.handlers.runtime.js")
|
||||
.then(({ ensureMatrixCryptoRuntime }) =>
|
||||
ensureMatrixCryptoRuntime({ log: api.logger.info }).catch((err: unknown) => {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
@@ -27,17 +40,17 @@ export default defineChannelPluginEntry({
|
||||
});
|
||||
|
||||
api.registerGatewayMethod("matrix.verify.recoveryKey", async (ctx) => {
|
||||
const { handleVerifyRecoveryKey } = await import("./src/plugin-entry.runtime.js");
|
||||
const { handleVerifyRecoveryKey } = await import("./plugin-entry.handlers.runtime.js");
|
||||
await handleVerifyRecoveryKey(ctx);
|
||||
});
|
||||
|
||||
api.registerGatewayMethod("matrix.verify.bootstrap", async (ctx) => {
|
||||
const { handleVerificationBootstrap } = await import("./src/plugin-entry.runtime.js");
|
||||
const { handleVerificationBootstrap } = await import("./plugin-entry.handlers.runtime.js");
|
||||
await handleVerificationBootstrap(ctx);
|
||||
});
|
||||
|
||||
api.registerGatewayMethod("matrix.verify.status", async (ctx) => {
|
||||
const { handleVerificationStatus } = await import("./src/plugin-entry.runtime.js");
|
||||
const { handleVerificationStatus } = await import("./plugin-entry.handlers.runtime.js");
|
||||
await handleVerificationStatus(ctx);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { matrixPlugin } from "./src/channel.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export default defineSetupPluginEntry(matrixPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "matrixPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,17 +1,30 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { mattermostPlugin } from "./src/channel.js";
|
||||
import { registerSlashCommandRoute } from "./src/mattermost/slash-state.js";
|
||||
import { setMattermostRuntime } from "./src/runtime.js";
|
||||
import {
|
||||
defineBundledChannelEntry,
|
||||
loadBundledEntryExportSync,
|
||||
} from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { mattermostPlugin } from "./src/channel.js";
|
||||
export { setMattermostRuntime } from "./src/runtime.js";
|
||||
function registerSlashCommandRoute(api: OpenClawPluginApi): void {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "registerSlashCommandRoute",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "mattermost",
|
||||
name: "Mattermost",
|
||||
description: "Mattermost channel plugin",
|
||||
plugin: mattermostPlugin,
|
||||
setRuntime: setMattermostRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "mattermostPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setMattermostRuntime",
|
||||
},
|
||||
registerFull(api) {
|
||||
// Actual slash-command registration happens after the monitor connects and
|
||||
// knows the team id; the route itself can be wired here.
|
||||
|
||||
@@ -57,6 +57,7 @@ export {
|
||||
resolveDmGroupAccessWithLists,
|
||||
resolveEffectiveAllowFromLists,
|
||||
} from "openclaw/plugin-sdk/channel-policy";
|
||||
export { mattermostPlugin } from "./src/channel.js";
|
||||
export { evaluateSenderGroupAccessForPolicy } from "openclaw/plugin-sdk/group-access";
|
||||
export { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline";
|
||||
export { logTypingFailure } from "openclaw/plugin-sdk/channel-feedback";
|
||||
@@ -86,3 +87,5 @@ export {
|
||||
resolveChannelMediaMaxBytes,
|
||||
} from "openclaw/plugin-sdk/media-runtime";
|
||||
export { normalizeProviderId } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
export { registerSlashCommandRoute } from "./src/mattermost/slash-state.js";
|
||||
export { setMattermostRuntime } from "./src/runtime.js";
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { mattermostPlugin } from "./src/channel.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export default defineSetupPluginEntry(mattermostPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "mattermostPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export { msteamsPlugin } from "./src/channel.js";
|
||||
export * from "./src/setup-core.js";
|
||||
export * from "./src/setup-surface.js";
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { msteamsPlugin } from "./src/channel.js";
|
||||
import { setMSTeamsRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { msteamsPlugin } from "./src/channel.js";
|
||||
export { setMSTeamsRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "msteams",
|
||||
name: "Microsoft Teams",
|
||||
description: "Microsoft Teams channel plugin (Bot Framework)",
|
||||
plugin: msteamsPlugin,
|
||||
setRuntime: setMSTeamsRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "msteamsPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setMSTeamsRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
// Keep this barrel thin and aligned with the local extension surface.
|
||||
|
||||
export * from "openclaw/plugin-sdk/msteams";
|
||||
export { setMSTeamsRuntime } from "./src/runtime.js";
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { msteamsPlugin } from "./src/channel.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export default defineSetupPluginEntry(msteamsPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "msteamsPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { nextcloudTalkPlugin } from "./src/channel.js";
|
||||
import { setNextcloudTalkRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { nextcloudTalkPlugin } from "./src/channel.js";
|
||||
export { setNextcloudTalkRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "nextcloud-talk",
|
||||
name: "Nextcloud Talk",
|
||||
description: "Nextcloud Talk channel plugin",
|
||||
plugin: nextcloudTalkPlugin,
|
||||
setRuntime: setNextcloudTalkRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "nextcloudTalkPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setNextcloudTalkRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
// Keep this barrel thin and aligned with the local extension surface.
|
||||
|
||||
export * from "openclaw/plugin-sdk/nextcloud-talk";
|
||||
export { setNextcloudTalkRuntime } from "./src/runtime.js";
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { nextcloudTalkPlugin } from "./src/channel.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export default defineSetupPluginEntry(nextcloudTalkPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "nextcloudTalkPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
export * from "./runtime-api.js";
|
||||
export { nostrPlugin } from "./src/channel.js";
|
||||
export { createNostrProfileHttpHandler } from "./src/nostr-profile-http.js";
|
||||
export { getNostrRuntime, setNostrRuntime } from "./src/runtime.js";
|
||||
export { resolveNostrAccount } from "./src/types.js";
|
||||
|
||||
@@ -1,28 +1,56 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { nostrPlugin } from "./src/channel.js";
|
||||
import type { NostrProfile } from "./src/config-schema.js";
|
||||
import { createNostrProfileHttpHandler } from "./src/nostr-profile-http.js";
|
||||
import { getNostrRuntime, setNostrRuntime } from "./src/runtime.js";
|
||||
import { resolveNostrAccount } from "./src/types.js";
|
||||
import {
|
||||
defineBundledChannelEntry,
|
||||
loadBundledEntryExportSync,
|
||||
} from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { nostrPlugin } from "./src/channel.js";
|
||||
export { setNostrRuntime } from "./src/runtime.js";
|
||||
function createNostrProfileHttpHandler() {
|
||||
return loadBundledEntryExportSync<
|
||||
(params: Record<string, unknown>) => (ctx: unknown) => Promise<void> | void
|
||||
>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "createNostrProfileHttpHandler",
|
||||
});
|
||||
}
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
function getNostrRuntime() {
|
||||
return loadBundledEntryExportSync<() => any>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "getNostrRuntime",
|
||||
})();
|
||||
}
|
||||
|
||||
function resolveNostrAccount(params: { cfg: unknown; accountId: string }) {
|
||||
return loadBundledEntryExportSync<(params: { cfg: unknown; accountId: string }) => any>(
|
||||
import.meta.url,
|
||||
{
|
||||
specifier: "./api.js",
|
||||
exportName: "resolveNostrAccount",
|
||||
},
|
||||
)(params);
|
||||
}
|
||||
|
||||
export default defineBundledChannelEntry({
|
||||
id: "nostr",
|
||||
name: "Nostr",
|
||||
description: "Nostr DM channel plugin via NIP-04",
|
||||
plugin: nostrPlugin,
|
||||
setRuntime: setNostrRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "nostrPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./api.js",
|
||||
exportName: "setNostrRuntime",
|
||||
},
|
||||
registerFull(api) {
|
||||
const httpHandler = createNostrProfileHttpHandler({
|
||||
const httpHandler = createNostrProfileHttpHandler()({
|
||||
getConfigProfile: (accountId: string) => {
|
||||
const runtime = getNostrRuntime();
|
||||
const cfg = runtime.config.loadConfig();
|
||||
const account = resolveNostrAccount({ cfg, accountId });
|
||||
return account.profile;
|
||||
},
|
||||
updateConfigProfile: async (accountId: string, profile: NostrProfile) => {
|
||||
updateConfigProfile: async (accountId: string, profile: unknown) => {
|
||||
const runtime = getNostrRuntime();
|
||||
const cfg = runtime.config.loadConfig();
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { nostrPlugin } from "./src/channel.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export default defineSetupPluginEntry(nostrPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "nostrPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
export { qqbotPlugin } from "./src/channel.js";
|
||||
export { qqbotSetupPlugin } from "./src/channel.setup.js";
|
||||
export { getFrameworkCommands } from "./src/slash-commands.js";
|
||||
export { registerChannelTool } from "./src/tools/channel.js";
|
||||
export { registerRemindTool } from "./src/tools/remind.js";
|
||||
export * from "./src/types.js";
|
||||
export * from "./src/config.js";
|
||||
export * from "./src/outbound.js";
|
||||
|
||||
@@ -1,26 +1,96 @@
|
||||
import type {
|
||||
ChannelPlugin,
|
||||
OpenClawPluginApi,
|
||||
PluginCommandContext,
|
||||
} from "openclaw/plugin-sdk/channel-core";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { qqbotPlugin } from "./src/channel.js";
|
||||
import { resolveQQBotAccount } from "./src/config.js";
|
||||
import { sendDocument, type MediaTargetContext } from "./src/outbound.js";
|
||||
import { setQQBotRuntime } from "./src/runtime.js";
|
||||
import { getFrameworkCommands } from "./src/slash-commands.js";
|
||||
import { registerChannelTool } from "./src/tools/channel.js";
|
||||
import { registerRemindTool } from "./src/tools/remind.js";
|
||||
import {
|
||||
defineBundledChannelEntry,
|
||||
loadBundledEntryExportSync,
|
||||
type OpenClawPluginApi,
|
||||
type PluginCommandContext,
|
||||
} from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { qqbotPlugin } from "./src/channel.js";
|
||||
export { setQQBotRuntime, getQQBotRuntime } from "./src/runtime.js";
|
||||
type QQBotAccount = {
|
||||
accountId: string;
|
||||
appId: string;
|
||||
config: unknown;
|
||||
};
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
type MediaTargetContext = {
|
||||
targetType: "c2c" | "group" | "channel" | "dm";
|
||||
targetId: string;
|
||||
account: QQBotAccount;
|
||||
logPrefix: string;
|
||||
};
|
||||
|
||||
type QQBotFrameworkCommandResult =
|
||||
| string
|
||||
| {
|
||||
text: string;
|
||||
filePath?: string;
|
||||
}
|
||||
| null
|
||||
| undefined;
|
||||
|
||||
type QQBotFrameworkCommand = {
|
||||
name: string;
|
||||
description: string;
|
||||
handler: (ctx: Record<string, unknown>) => Promise<QQBotFrameworkCommandResult>;
|
||||
};
|
||||
|
||||
function resolveQQBotAccount(config: unknown, accountId?: string): QQBotAccount {
|
||||
const resolve = loadBundledEntryExportSync<(config: unknown, accountId?: string) => QQBotAccount>(
|
||||
import.meta.url,
|
||||
{
|
||||
specifier: "./api.js",
|
||||
exportName: "resolveQQBotAccount",
|
||||
},
|
||||
);
|
||||
return resolve(config, accountId);
|
||||
}
|
||||
|
||||
function sendDocument(context: MediaTargetContext, filePath: string) {
|
||||
const send = loadBundledEntryExportSync<
|
||||
(context: MediaTargetContext, filePath: string) => Promise<unknown>
|
||||
>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "sendDocument",
|
||||
});
|
||||
return send(context, filePath);
|
||||
}
|
||||
|
||||
function getFrameworkCommands(): QQBotFrameworkCommand[] {
|
||||
const getCommands = loadBundledEntryExportSync<() => QQBotFrameworkCommand[]>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "getFrameworkCommands",
|
||||
});
|
||||
return getCommands();
|
||||
}
|
||||
|
||||
function registerChannelTool(api: OpenClawPluginApi): void {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerChannelTool",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
function registerRemindTool(api: OpenClawPluginApi): void {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./api.js",
|
||||
exportName: "registerRemindTool",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
export default defineBundledChannelEntry({
|
||||
id: "qqbot",
|
||||
name: "QQ Bot",
|
||||
description: "QQ Bot channel plugin",
|
||||
plugin: qqbotPlugin as ChannelPlugin,
|
||||
setRuntime: setQQBotRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "qqbotPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setQQBotRuntime",
|
||||
},
|
||||
registerFull(api: OpenClawPluginApi) {
|
||||
registerChannelTool(api);
|
||||
registerRemindTool(api);
|
||||
@@ -95,7 +165,7 @@ export default defineChannelPluginEntry({
|
||||
}
|
||||
|
||||
// File result: send the file attachment via QQ API, return text summary.
|
||||
if (result && "filePath" in result) {
|
||||
if (result && typeof result === "object" && "filePath" in result) {
|
||||
try {
|
||||
const mediaCtx: MediaTargetContext = {
|
||||
targetType,
|
||||
@@ -103,14 +173,22 @@ export default defineChannelPluginEntry({
|
||||
account,
|
||||
logPrefix: `[qqbot:${account.accountId}]`,
|
||||
};
|
||||
await sendDocument(mediaCtx, result.filePath);
|
||||
await sendDocument(mediaCtx, String(result.filePath));
|
||||
} catch {
|
||||
// File send failed; the text summary is still returned below.
|
||||
}
|
||||
return { text: result.text };
|
||||
return { text: String(result.text) };
|
||||
}
|
||||
|
||||
return { text: "⚠️ 命令返回了意外结果。" };
|
||||
return {
|
||||
text:
|
||||
result &&
|
||||
typeof result === "object" &&
|
||||
"text" in result &&
|
||||
typeof result.text === "string"
|
||||
? result.text
|
||||
: "⚠️ 命令返回了意外结果。",
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { qqbotSetupPlugin } from "./src/channel.setup.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { qqbotSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default defineSetupPluginEntry(qqbotSetupPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "qqbotSetupPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export { signalPlugin } from "./src/channel.js";
|
||||
export { signalSetupPlugin } from "./src/channel.setup.js";
|
||||
export * from "./src/accounts.js";
|
||||
export * from "./src/format.js";
|
||||
export * from "./src/identity.js";
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { signalPlugin } from "./src/channel.js";
|
||||
import { setSignalRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { signalPlugin } from "./src/channel.js";
|
||||
export { setSignalRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "signal",
|
||||
name: "Signal",
|
||||
description: "Signal channel plugin",
|
||||
plugin: signalPlugin,
|
||||
setRuntime: setSignalRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "signalPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setSignalRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { signalPlugin } from "./src/channel.js";
|
||||
import { setSignalRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { signalPlugin } from "./src/channel.js";
|
||||
export { setSignalRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "signal",
|
||||
name: "Signal",
|
||||
description: "Signal channel plugin",
|
||||
plugin: signalPlugin,
|
||||
setRuntime: setSignalRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "signalPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setSignalRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export * from "./src/runtime-api.js";
|
||||
export { setSignalRuntime } from "./src/runtime.js";
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { signalSetupPlugin } from "./src/channel.setup.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { signalSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default defineSetupPluginEntry(signalSetupPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "signalSetupPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export { slackPlugin } from "./src/channel.js";
|
||||
export { slackSetupPlugin } from "./src/channel.setup.js";
|
||||
export * from "./src/account-inspect.js";
|
||||
export * from "./src/accounts.js";
|
||||
export * from "./src/action-threading.js";
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { slackPlugin } from "./src/channel.js";
|
||||
import { setSlackRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { slackPlugin } from "./src/channel.js";
|
||||
export { setSlackRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "slack",
|
||||
name: "Slack",
|
||||
description: "Slack channel plugin",
|
||||
plugin: slackPlugin,
|
||||
setRuntime: setSlackRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "slackPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setSlackRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,16 +1,29 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { slackPlugin } from "./src/channel.js";
|
||||
import { registerSlackPluginHttpRoutes } from "./src/http/plugin-routes.js";
|
||||
import { setSlackRuntime } from "./src/runtime.js";
|
||||
import {
|
||||
defineBundledChannelEntry,
|
||||
loadBundledEntryExportSync,
|
||||
} from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { slackPlugin } from "./src/channel.js";
|
||||
export { setSlackRuntime } from "./src/runtime.js";
|
||||
function registerSlackPluginHttpRoutes(api: OpenClawPluginApi): void {
|
||||
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "registerSlackPluginHttpRoutes",
|
||||
});
|
||||
register(api);
|
||||
}
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "slack",
|
||||
name: "Slack",
|
||||
description: "Slack channel plugin",
|
||||
plugin: slackPlugin,
|
||||
setRuntime: setSlackRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "slackPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setSlackRuntime",
|
||||
},
|
||||
registerFull: registerSlackPluginHttpRoutes,
|
||||
});
|
||||
|
||||
@@ -3,3 +3,5 @@ export * from "./src/directory-live.js";
|
||||
export * from "./src/index.js";
|
||||
export * from "./src/resolve-channels.js";
|
||||
export * from "./src/resolve-users.js";
|
||||
export { registerSlackPluginHttpRoutes } from "./src/http/plugin-routes.js";
|
||||
export { setSlackRuntime } from "./src/runtime.js";
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { slackSetupPlugin } from "./src/channel.setup.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { slackSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default defineSetupPluginEntry(slackSetupPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "slackSetupPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export { synologyChatPlugin } from "./src/channel.js";
|
||||
export { setSynologyRuntime } from "./src/runtime.js";
|
||||
export * from "./src/security-audit.js";
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { synologyChatPlugin } from "./src/channel.js";
|
||||
import { setSynologyRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { synologyChatPlugin } from "./src/channel.js";
|
||||
export { setSynologyRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "synology-chat",
|
||||
name: "Synology Chat",
|
||||
description: "Native Synology Chat channel plugin for OpenClaw",
|
||||
plugin: synologyChatPlugin,
|
||||
setRuntime: setSynologyRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "synologyChatPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./api.js",
|
||||
exportName: "setSynologyRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { synologyChatPlugin } from "./src/channel.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export default defineSetupPluginEntry(synologyChatPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "synologyChatPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export { telegramPlugin } from "./src/channel.js";
|
||||
export { telegramSetupPlugin } from "./src/channel.setup.js";
|
||||
export * from "./src/account-inspect.js";
|
||||
export * from "./src/accounts.js";
|
||||
export * from "./src/action-threading.js";
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import type { ChannelPlugin } from "openclaw/plugin-sdk/channel-core";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { telegramPlugin } from "./src/channel.js";
|
||||
import { setTelegramRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { telegramPlugin } from "./src/channel.js";
|
||||
export { setTelegramRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "telegram",
|
||||
name: "Telegram",
|
||||
description: "Telegram channel plugin",
|
||||
plugin: telegramPlugin as ChannelPlugin,
|
||||
setRuntime: setTelegramRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "telegramPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setTelegramRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -83,6 +83,7 @@ export {
|
||||
setTelegramThreadBindingMaxAgeBySessionKey,
|
||||
} from "./src/thread-bindings.js";
|
||||
export { resolveTelegramToken } from "./src/token.js";
|
||||
export { setTelegramRuntime } from "./src/runtime.js";
|
||||
export type { ChannelPlugin } from "openclaw/plugin-sdk/core";
|
||||
export type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
export type TelegramAccountConfig = NonNullable<
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { telegramSetupPlugin } from "./src/channel.setup.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { telegramSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default defineSetupPluginEntry(telegramSetupPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "telegramSetupPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export * from "./runtime-api.js";
|
||||
export { tlonPlugin } from "./src/channel.js";
|
||||
export { setTlonRuntime } from "./src/runtime.js";
|
||||
|
||||
@@ -2,12 +2,7 @@ import { spawn } from "node:child_process";
|
||||
import { existsSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { tlonPlugin } from "./src/channel.js";
|
||||
import { setTlonRuntime } from "./src/runtime.js";
|
||||
|
||||
export { tlonPlugin } from "./src/channel.js";
|
||||
export { setTlonRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
@@ -117,12 +112,19 @@ function runTlonCommand(binary: string, args: string[]): Promise<string> {
|
||||
});
|
||||
}
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "tlon",
|
||||
name: "Tlon",
|
||||
description: "Tlon/Urbit channel plugin",
|
||||
plugin: tlonPlugin,
|
||||
setRuntime: setTlonRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "tlonPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./api.js",
|
||||
exportName: "setTlonRuntime",
|
||||
},
|
||||
registerFull(api) {
|
||||
api.logger.debug?.("[tlon] Registering tlon tool");
|
||||
api.registerTool({
|
||||
@@ -164,9 +166,14 @@ export default defineChannelPluginEntry({
|
||||
content: [{ type: "text" as const, text: output }],
|
||||
details: undefined,
|
||||
};
|
||||
} catch (error: any) {
|
||||
} catch (error: unknown) {
|
||||
return {
|
||||
content: [{ type: "text" as const, text: `Error: ${error.message}` }],
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
||||
},
|
||||
],
|
||||
details: { error: true },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { tlonPlugin } from "./src/channel.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export default defineSetupPluginEntry(tlonPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "tlonPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export * from "./runtime-api.js";
|
||||
export { twitchPlugin } from "./src/plugin.js";
|
||||
export { setTwitchRuntime } from "./src/runtime.js";
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { twitchPlugin } from "./src/plugin.js";
|
||||
import { setTwitchRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { monitorTwitchProvider } from "./src/monitor.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "twitch",
|
||||
name: "Twitch",
|
||||
description: "Twitch chat channel plugin",
|
||||
plugin: twitchPlugin,
|
||||
setRuntime: setTwitchRuntime,
|
||||
description: "Twitch IRC chat channel plugin",
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "twitchPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./api.js",
|
||||
exportName: "setTwitchRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export { whatsappPlugin } from "./src/channel.js";
|
||||
export { whatsappSetupPlugin } from "./src/channel.setup.js";
|
||||
export * from "./src/accounts.js";
|
||||
export * from "./src/auto-reply/constants.js";
|
||||
export { whatsappCommandPolicy } from "./src/command-policy.js";
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { whatsappPlugin } from "./src/channel.js";
|
||||
import { setWhatsAppRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { whatsappPlugin } from "./src/channel.js";
|
||||
export { setWhatsAppRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "whatsapp",
|
||||
name: "WhatsApp",
|
||||
description: "WhatsApp channel plugin",
|
||||
plugin: whatsappPlugin,
|
||||
setRuntime: setWhatsAppRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "whatsappPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setWhatsAppRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ export * from "./src/login.js";
|
||||
export * from "./src/media.js";
|
||||
export * from "./src/send.js";
|
||||
export * from "./src/session.js";
|
||||
export { setWhatsAppRuntime } from "./src/runtime.js";
|
||||
|
||||
type StartWebLoginWithQr = typeof import("./src/login-qr.js").startWebLoginWithQr;
|
||||
type WaitForWebLogin = typeof import("./src/login-qr.js").waitForWebLogin;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { whatsappSetupPlugin } from "./src/channel.setup.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { whatsappSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default defineSetupPluginEntry(whatsappSetupPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "whatsappSetupPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
export * from "./src/setup-core.js";
|
||||
export * from "./src/setup-surface.js";
|
||||
export { evaluateZaloGroupAccess, resolveZaloRuntimeGroupPolicy } from "./src/group-access.js";
|
||||
export * from "./setup-api.js";
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { zaloPlugin } from "./src/channel.js";
|
||||
import { setZaloRuntime } from "./src/runtime.js";
|
||||
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { zaloPlugin } from "./src/channel.js";
|
||||
export { setZaloRuntime } from "./src/runtime.js";
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "zalo",
|
||||
name: "Zalo",
|
||||
description: "Zalo channel plugin",
|
||||
plugin: zaloPlugin,
|
||||
setRuntime: setZaloRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "zaloPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setZaloRuntime",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Private runtime barrel for the bundled Zalo extension.
|
||||
// Keep this barrel thin and aligned with the local extension surface.
|
||||
|
||||
export { zaloPlugin } from "./src/channel.js";
|
||||
export * from "./api.js";
|
||||
export type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
|
||||
export type { OpenClawConfig, GroupPolicy } from "openclaw/plugin-sdk/config-runtime";
|
||||
@@ -92,3 +93,4 @@ export type {
|
||||
RegisterWebhookPluginRouteOptions,
|
||||
RegisterWebhookTargetOptions,
|
||||
} from "openclaw/plugin-sdk/webhook-ingress";
|
||||
export { setZaloRuntime } from "./src/runtime.js";
|
||||
|
||||
34
extensions/zalo/setup-api.ts
Normal file
34
extensions/zalo/setup-api.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { loadBundledEntryExportSync } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
type SetupSurfaceModule = typeof import("./src/setup-surface.js");
|
||||
|
||||
function createLazyObjectValue<T extends object>(load: () => T): T {
|
||||
return new Proxy({} as T, {
|
||||
get(_target, property, receiver) {
|
||||
return Reflect.get(load(), property, receiver);
|
||||
},
|
||||
has(_target, property) {
|
||||
return property in load();
|
||||
},
|
||||
ownKeys() {
|
||||
return Reflect.ownKeys(load());
|
||||
},
|
||||
getOwnPropertyDescriptor(_target, property) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(load(), property);
|
||||
return descriptor ? { ...descriptor, configurable: true } : undefined;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function loadSetupSurfaceModule(): SetupSurfaceModule {
|
||||
return loadBundledEntryExportSync<SetupSurfaceModule>(import.meta.url, {
|
||||
specifier: "./src/setup-surface.js",
|
||||
});
|
||||
}
|
||||
|
||||
export { zaloDmPolicy, zaloSetupAdapter, createZaloSetupWizardProxy } from "./src/setup-core.js";
|
||||
export { evaluateZaloGroupAccess, resolveZaloRuntimeGroupPolicy } from "./src/group-access.js";
|
||||
|
||||
export const zaloSetupWizard: SetupSurfaceModule["zaloSetupWizard"] = createLazyObjectValue(
|
||||
() => loadSetupSurfaceModule().zaloSetupWizard as object,
|
||||
) as SetupSurfaceModule["zaloSetupWizard"];
|
||||
@@ -1,4 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { zaloPlugin } from "./src/channel.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export default defineSetupPluginEntry(zaloPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "zaloPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
export { zalouserPlugin } from "./src/channel.js";
|
||||
export { zalouserSetupPlugin } from "./src/channel.setup.js";
|
||||
export { createZalouserTool } from "./src/tool.js";
|
||||
export * from "./src/setup-core.js";
|
||||
export * from "./src/setup-surface.js";
|
||||
export * from "./src/security-audit.js";
|
||||
|
||||
@@ -1,17 +1,33 @@
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { zalouserPlugin } from "./src/channel.js";
|
||||
import { setZalouserRuntime } from "./src/runtime.js";
|
||||
import { createZalouserTool } from "./src/tool.js";
|
||||
import {
|
||||
type AnyAgentTool,
|
||||
defineBundledChannelEntry,
|
||||
loadBundledEntryExportSync,
|
||||
} from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { zalouserPlugin } from "./src/channel.js";
|
||||
export { setZalouserRuntime } from "./src/runtime.js";
|
||||
function createZalouserTool(context?: unknown): AnyAgentTool {
|
||||
const createTool = loadBundledEntryExportSync<(context?: unknown) => AnyAgentTool>(
|
||||
import.meta.url,
|
||||
{
|
||||
specifier: "./api.js",
|
||||
exportName: "createZalouserTool",
|
||||
},
|
||||
);
|
||||
return createTool(context);
|
||||
}
|
||||
|
||||
export default defineChannelPluginEntry({
|
||||
export default defineBundledChannelEntry({
|
||||
id: "zalouser",
|
||||
name: "Zalo Personal",
|
||||
description: "Zalo personal account messaging via native zca-js integration",
|
||||
plugin: zalouserPlugin,
|
||||
setRuntime: setZalouserRuntime,
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "zalouserPlugin",
|
||||
},
|
||||
runtime: {
|
||||
specifier: "./runtime-api.js",
|
||||
exportName: "setZalouserRuntime",
|
||||
},
|
||||
registerFull(api) {
|
||||
api.registerTool((ctx) => createZalouserTool(ctx), { name: "zalouser" });
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Keep this barrel thin and aligned with the local extension surface.
|
||||
|
||||
export * from "./api.js";
|
||||
export { setZalouserRuntime } from "./src/runtime.js";
|
||||
export type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
|
||||
export type {
|
||||
BaseProbeResult,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
|
||||
import { zalouserSetupPlugin } from "./src/channel.setup.js";
|
||||
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
||||
|
||||
export { zalouserSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default defineSetupPluginEntry(zalouserSetupPlugin);
|
||||
export default defineBundledChannelSetupEntry({
|
||||
importMetaUrl: import.meta.url,
|
||||
plugin: {
|
||||
specifier: "./api.js",
|
||||
exportName: "zalouserSetupPlugin",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -459,6 +459,10 @@
|
||||
"types": "./dist/plugin-sdk/channel-core.d.ts",
|
||||
"default": "./dist/plugin-sdk/channel-core.js"
|
||||
},
|
||||
"./plugin-sdk/channel-entry-contract": {
|
||||
"types": "./dist/plugin-sdk/channel-entry-contract.d.ts",
|
||||
"default": "./dist/plugin-sdk/channel-entry-contract.js"
|
||||
},
|
||||
"./plugin-sdk/channel-contract": {
|
||||
"types": "./dist/plugin-sdk/channel-contract.d.ts",
|
||||
"default": "./dist/plugin-sdk/channel-contract.js"
|
||||
|
||||
@@ -104,6 +104,7 @@
|
||||
"channel-actions",
|
||||
"channel-plugin-common",
|
||||
"channel-core",
|
||||
"channel-entry-contract",
|
||||
"channel-contract",
|
||||
"channel-feedback",
|
||||
"channel-inbound",
|
||||
|
||||
@@ -34,7 +34,7 @@ describe("bundled channel entry shape guards", () => {
|
||||
expect(bundled.listBundledChannelPlugins()).toEqual([]);
|
||||
expect(bundled.listBundledChannelSetupPlugins()).toEqual([]);
|
||||
});
|
||||
it("keeps channel entrypoints on the narrow channel-core SDK surface", () => {
|
||||
it("keeps channel entrypoints on the dedicated entry-contract SDK surface", () => {
|
||||
const extensionRoot = path.resolve("extensions");
|
||||
const offenders: string[] = [];
|
||||
|
||||
@@ -43,18 +43,53 @@ describe("bundled channel entry shape guards", () => {
|
||||
if (!fs.statSync(extensionDir).isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
for (const relativePath of ["index.ts", "setup-entry.ts"]) {
|
||||
for (const relativePath of ["index.ts", "channel-entry.ts", "setup-entry.ts"]) {
|
||||
const filePath = path.join(extensionDir, relativePath);
|
||||
if (!fs.existsSync(filePath)) {
|
||||
continue;
|
||||
}
|
||||
const source = fs.readFileSync(filePath, "utf8");
|
||||
const usesEntryHelpers =
|
||||
source.includes("defineChannelPluginEntry") || source.includes("defineSetupPluginEntry");
|
||||
source.includes("defineBundledChannelEntry") ||
|
||||
source.includes("defineBundledChannelSetupEntry");
|
||||
if (!usesEntryHelpers) {
|
||||
continue;
|
||||
}
|
||||
if (source.includes('from "openclaw/plugin-sdk/core"')) {
|
||||
if (
|
||||
!source.includes('from "openclaw/plugin-sdk/channel-entry-contract"') ||
|
||||
source.includes('from "openclaw/plugin-sdk/core"') ||
|
||||
source.includes('from "openclaw/plugin-sdk/channel-core"')
|
||||
) {
|
||||
offenders.push(path.relative(process.cwd(), filePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expect(offenders).toEqual([]);
|
||||
});
|
||||
|
||||
it("keeps bundled channel entrypoints free of static src imports", () => {
|
||||
const extensionRoot = path.resolve("extensions");
|
||||
const offenders: string[] = [];
|
||||
|
||||
for (const extensionId of fs.readdirSync(extensionRoot)) {
|
||||
const extensionDir = path.join(extensionRoot, extensionId);
|
||||
if (!fs.statSync(extensionDir).isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
for (const relativePath of ["index.ts", "channel-entry.ts", "setup-entry.ts"]) {
|
||||
const filePath = path.join(extensionDir, relativePath);
|
||||
if (!fs.existsSync(filePath)) {
|
||||
continue;
|
||||
}
|
||||
const source = fs.readFileSync(filePath, "utf8");
|
||||
const usesEntryHelpers =
|
||||
source.includes("defineBundledChannelEntry") ||
|
||||
source.includes("defineBundledChannelSetupEntry");
|
||||
if (!usesEntryHelpers) {
|
||||
continue;
|
||||
}
|
||||
if (/^(?:import|export)\s.+["']\.\/src\//mu.test(source)) {
|
||||
offenders.push(path.relative(process.cwd(), filePath));
|
||||
}
|
||||
}
|
||||
@@ -199,11 +234,19 @@ describe("bundled channel entry shape guards", () => {
|
||||
}
|
||||
return {
|
||||
default: {
|
||||
channelPlugin: {
|
||||
id: "alpha",
|
||||
meta: {},
|
||||
capabilities: {},
|
||||
config: {},
|
||||
kind: "bundled-channel-entry",
|
||||
id: "alpha",
|
||||
name: "Alpha",
|
||||
description: "Alpha",
|
||||
configSchema: {},
|
||||
register() {},
|
||||
loadChannelPlugin() {
|
||||
return {
|
||||
id: "alpha",
|
||||
meta: {},
|
||||
capabilities: {},
|
||||
config: {},
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4,6 +4,10 @@ import path from "node:path";
|
||||
import { createJiti } from "jiti";
|
||||
import { openBoundaryFileSync } from "../../infra/boundary-file-read.js";
|
||||
import { createSubsystemLogger } from "../../logging/subsystem.js";
|
||||
import type {
|
||||
BundledChannelEntryContract,
|
||||
BundledChannelSetupEntryContract,
|
||||
} from "../../plugin-sdk/channel-entry-contract.js";
|
||||
import { discoverOpenClawPlugins } from "../../plugins/discovery.js";
|
||||
import { loadPluginManifestRegistry } from "../../plugins/manifest-registry.js";
|
||||
import type { PluginRuntime } from "../../plugins/runtime/types.js";
|
||||
@@ -16,13 +20,8 @@ import type { ChannelId, ChannelPlugin } from "./types.js";
|
||||
|
||||
type GeneratedBundledChannelEntry = {
|
||||
id: string;
|
||||
entry: {
|
||||
channelPlugin: ChannelPlugin;
|
||||
setChannelRuntime?: (runtime: PluginRuntime) => void;
|
||||
};
|
||||
setupEntry?: {
|
||||
plugin: ChannelPlugin;
|
||||
};
|
||||
entry: BundledChannelEntryContract;
|
||||
setupEntry?: BundledChannelSetupEntryContract;
|
||||
};
|
||||
|
||||
type BundledChannelDiscoveryCandidate = {
|
||||
@@ -44,38 +43,7 @@ const nodeRequire = createRequire(import.meta.url);
|
||||
|
||||
function resolveChannelPluginModuleEntry(
|
||||
moduleExport: unknown,
|
||||
): GeneratedBundledChannelEntry["entry"] | null {
|
||||
const resolveNamedFallback = (value: unknown): GeneratedBundledChannelEntry["entry"] | null => {
|
||||
if (!value || typeof value !== "object") {
|
||||
return null;
|
||||
}
|
||||
const entries = Object.entries(value as Record<string, unknown>).filter(
|
||||
([key]) => key !== "default",
|
||||
);
|
||||
const pluginCandidates = entries.filter(
|
||||
([key, candidate]) =>
|
||||
key.endsWith("Plugin") &&
|
||||
!!candidate &&
|
||||
typeof candidate === "object" &&
|
||||
"id" in (candidate as Record<string, unknown>),
|
||||
);
|
||||
if (pluginCandidates.length !== 1) {
|
||||
return null;
|
||||
}
|
||||
const runtimeCandidates = entries.filter(
|
||||
([key, candidate]) =>
|
||||
key.startsWith("set") && key.endsWith("Runtime") && typeof candidate === "function",
|
||||
);
|
||||
return {
|
||||
channelPlugin: pluginCandidates[0][1] as ChannelPlugin,
|
||||
...(runtimeCandidates.length === 1
|
||||
? {
|
||||
setChannelRuntime: runtimeCandidates[0][1] as (runtime: PluginRuntime) => void,
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
};
|
||||
|
||||
): BundledChannelEntryContract | null {
|
||||
const resolved =
|
||||
moduleExport &&
|
||||
typeof moduleExport === "object" &&
|
||||
@@ -85,24 +53,25 @@ function resolveChannelPluginModuleEntry(
|
||||
if (!resolved || typeof resolved !== "object") {
|
||||
return null;
|
||||
}
|
||||
const record = resolved as {
|
||||
channelPlugin?: unknown;
|
||||
setChannelRuntime?: unknown;
|
||||
};
|
||||
if (!record.channelPlugin || typeof record.channelPlugin !== "object") {
|
||||
return resolveNamedFallback(resolved) ?? resolveNamedFallback(moduleExport);
|
||||
const record = resolved as Partial<BundledChannelEntryContract>;
|
||||
if (record.kind !== "bundled-channel-entry") {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
channelPlugin: record.channelPlugin as ChannelPlugin,
|
||||
...(typeof record.setChannelRuntime === "function"
|
||||
? { setChannelRuntime: record.setChannelRuntime as (runtime: PluginRuntime) => void }
|
||||
: {}),
|
||||
};
|
||||
if (
|
||||
typeof record.id !== "string" ||
|
||||
typeof record.name !== "string" ||
|
||||
typeof record.description !== "string" ||
|
||||
typeof record.register !== "function" ||
|
||||
typeof record.loadChannelPlugin !== "function"
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return record as BundledChannelEntryContract;
|
||||
}
|
||||
|
||||
function resolveChannelSetupModuleEntry(
|
||||
moduleExport: unknown,
|
||||
): GeneratedBundledChannelEntry["setupEntry"] | null {
|
||||
): BundledChannelSetupEntryContract | null {
|
||||
const resolved =
|
||||
moduleExport &&
|
||||
typeof moduleExport === "object" &&
|
||||
@@ -112,15 +81,14 @@ function resolveChannelSetupModuleEntry(
|
||||
if (!resolved || typeof resolved !== "object") {
|
||||
return null;
|
||||
}
|
||||
const record = resolved as {
|
||||
plugin?: unknown;
|
||||
};
|
||||
if (!record.plugin || typeof record.plugin !== "object") {
|
||||
const record = resolved as Partial<BundledChannelSetupEntryContract>;
|
||||
if (record.kind !== "bundled-channel-setup-entry") {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
plugin: record.plugin as ChannelPlugin,
|
||||
};
|
||||
if (typeof record.loadSetupPlugin !== "function") {
|
||||
return null;
|
||||
}
|
||||
return record as BundledChannelSetupEntryContract;
|
||||
}
|
||||
|
||||
function createModuleLoader() {
|
||||
@@ -237,7 +205,7 @@ function loadGeneratedBundledChannelEntries(): readonly GeneratedBundledChannelE
|
||||
);
|
||||
if (!entry) {
|
||||
log.warn(
|
||||
`[channels] bundled channel entry ${manifest.id} missing channelPlugin export from ${sourcePath}; skipping`,
|
||||
`[channels] bundled channel entry ${manifest.id} missing bundled-channel-entry contract from ${sourcePath}; skipping`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -281,10 +249,7 @@ type BundledChannelState = {
|
||||
plugins: readonly ChannelPlugin[];
|
||||
setupPlugins: readonly ChannelPlugin[];
|
||||
pluginsById: Map<ChannelId, ChannelPlugin>;
|
||||
runtimeSettersById: Map<
|
||||
ChannelId,
|
||||
NonNullable<GeneratedBundledChannelEntry["entry"]["setChannelRuntime"]>
|
||||
>;
|
||||
runtimeSettersById: Map<ChannelId, NonNullable<BundledChannelEntryContract["setChannelRuntime"]>>;
|
||||
};
|
||||
|
||||
const EMPTY_BUNDLED_CHANNEL_STATE: BundledChannelState = {
|
||||
@@ -307,18 +272,18 @@ function getBundledChannelState(): BundledChannelState {
|
||||
}
|
||||
bundledChannelStateLoadInProgress = true;
|
||||
const entries = loadGeneratedBundledChannelEntries();
|
||||
const plugins = entries.map(({ entry }) => entry.channelPlugin);
|
||||
const plugins = entries.map(({ entry }) => entry.loadChannelPlugin());
|
||||
const setupPlugins = entries.flatMap(({ setupEntry }) => {
|
||||
const plugin = setupEntry?.plugin;
|
||||
const plugin = setupEntry?.loadSetupPlugin();
|
||||
return plugin ? [plugin] : [];
|
||||
});
|
||||
const runtimeSettersById = new Map<
|
||||
ChannelId,
|
||||
NonNullable<GeneratedBundledChannelEntry["entry"]["setChannelRuntime"]>
|
||||
NonNullable<BundledChannelEntryContract["setChannelRuntime"]>
|
||||
>();
|
||||
for (const { entry } of entries) {
|
||||
if (entry.setChannelRuntime) {
|
||||
runtimeSettersById.set(entry.channelPlugin.id, entry.setChannelRuntime);
|
||||
runtimeSettersById.set(entry.id, entry.setChannelRuntime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
227
src/plugin-sdk/channel-entry-contract.ts
Normal file
227
src/plugin-sdk/channel-entry-contract.ts
Normal file
@@ -0,0 +1,227 @@
|
||||
import fs from "node:fs";
|
||||
import { createRequire } from "node:module";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { createJiti } from "jiti";
|
||||
import { emptyChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
||||
import type { ChannelConfigSchema, ChannelPlugin } from "../channels/plugins/types.plugin.js";
|
||||
import { openBoundaryFileSync } from "../infra/boundary-file-read.js";
|
||||
import type { PluginRuntime } from "../plugins/runtime/types.js";
|
||||
import {
|
||||
buildPluginLoaderAliasMap,
|
||||
buildPluginLoaderJitiOptions,
|
||||
shouldPreferNativeJiti,
|
||||
} from "../plugins/sdk-alias.js";
|
||||
import type { AnyAgentTool, OpenClawPluginApi, PluginCommandContext } from "../plugins/types.js";
|
||||
|
||||
export type { AnyAgentTool, OpenClawPluginApi, PluginCommandContext };
|
||||
|
||||
type ChannelEntryConfigSchema<TPlugin> =
|
||||
TPlugin extends ChannelPlugin<unknown>
|
||||
? NonNullable<TPlugin["configSchema"]>
|
||||
: ChannelConfigSchema;
|
||||
|
||||
type BundledEntryModuleRef = {
|
||||
specifier: string;
|
||||
exportName?: string;
|
||||
};
|
||||
|
||||
type DefineBundledChannelEntryOptions<TPlugin = ChannelPlugin> = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
importMetaUrl: string;
|
||||
plugin: BundledEntryModuleRef;
|
||||
configSchema?: ChannelEntryConfigSchema<TPlugin> | (() => ChannelEntryConfigSchema<TPlugin>);
|
||||
runtime?: BundledEntryModuleRef;
|
||||
registerCliMetadata?: (api: OpenClawPluginApi) => void;
|
||||
registerFull?: (api: OpenClawPluginApi) => void;
|
||||
};
|
||||
|
||||
type DefineBundledChannelSetupEntryOptions = {
|
||||
importMetaUrl: string;
|
||||
plugin: BundledEntryModuleRef;
|
||||
};
|
||||
|
||||
export type BundledChannelEntryContract<TPlugin = ChannelPlugin> = {
|
||||
kind: "bundled-channel-entry";
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
configSchema: ChannelEntryConfigSchema<TPlugin>;
|
||||
register: (api: OpenClawPluginApi) => void;
|
||||
loadChannelPlugin: () => TPlugin;
|
||||
setChannelRuntime?: (runtime: PluginRuntime) => void;
|
||||
};
|
||||
|
||||
export type BundledChannelSetupEntryContract<TPlugin = ChannelPlugin> = {
|
||||
kind: "bundled-channel-setup-entry";
|
||||
loadSetupPlugin: () => TPlugin;
|
||||
};
|
||||
|
||||
const nodeRequire = createRequire(import.meta.url);
|
||||
const jitiLoaders = new Map<string, ReturnType<typeof createJiti>>();
|
||||
const loadedModuleExports = new Map<string, unknown>();
|
||||
|
||||
function resolveSpecifierCandidates(modulePath: string): string[] {
|
||||
const ext = path.extname(modulePath).toLowerCase();
|
||||
if (ext === ".js") {
|
||||
return [modulePath, modulePath.slice(0, -3) + ".ts"];
|
||||
}
|
||||
if (ext === ".mjs") {
|
||||
return [modulePath, modulePath.slice(0, -4) + ".mts"];
|
||||
}
|
||||
if (ext === ".cjs") {
|
||||
return [modulePath, modulePath.slice(0, -4) + ".cts"];
|
||||
}
|
||||
return [modulePath];
|
||||
}
|
||||
|
||||
function resolveEntryBoundaryRoot(importMetaUrl: string): string {
|
||||
return path.dirname(fileURLToPath(importMetaUrl));
|
||||
}
|
||||
|
||||
function resolveBundledEntryModulePath(importMetaUrl: string, specifier: string): string {
|
||||
const importerPath = fileURLToPath(importMetaUrl);
|
||||
const resolved = path.resolve(path.dirname(importerPath), specifier);
|
||||
const boundaryRoot = resolveEntryBoundaryRoot(importMetaUrl);
|
||||
const candidate =
|
||||
resolveSpecifierCandidates(resolved).find((entry) => fs.existsSync(entry)) ?? resolved;
|
||||
const opened = openBoundaryFileSync({
|
||||
absolutePath: candidate,
|
||||
rootPath: boundaryRoot,
|
||||
boundaryLabel: "plugin root",
|
||||
rejectHardlinks: false,
|
||||
skipLexicalRootCheck: true,
|
||||
});
|
||||
if (!opened.ok) {
|
||||
throw new Error(`plugin entry path escapes plugin root: ${specifier}`);
|
||||
}
|
||||
fs.closeSync(opened.fd);
|
||||
return opened.path;
|
||||
}
|
||||
|
||||
function getJiti(modulePath: string) {
|
||||
const tryNative =
|
||||
shouldPreferNativeJiti(modulePath) || modulePath.includes(`${path.sep}dist${path.sep}`);
|
||||
const aliasMap = buildPluginLoaderAliasMap(modulePath, process.argv[1], import.meta.url);
|
||||
const cacheKey = JSON.stringify({
|
||||
tryNative,
|
||||
aliasMap: Object.entries(aliasMap).toSorted(([left], [right]) => left.localeCompare(right)),
|
||||
});
|
||||
const cached = jitiLoaders.get(cacheKey);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
const loader = createJiti(import.meta.url, {
|
||||
...buildPluginLoaderJitiOptions(aliasMap),
|
||||
tryNative,
|
||||
});
|
||||
jitiLoaders.set(cacheKey, loader);
|
||||
return loader;
|
||||
}
|
||||
|
||||
function loadBundledEntryModuleSync(importMetaUrl: string, specifier: string): unknown {
|
||||
const modulePath = resolveBundledEntryModulePath(importMetaUrl, specifier);
|
||||
const cached = loadedModuleExports.get(modulePath);
|
||||
if (cached !== undefined) {
|
||||
return cached;
|
||||
}
|
||||
let loaded: unknown;
|
||||
if (
|
||||
process.platform === "win32" &&
|
||||
modulePath.includes(`${path.sep}dist${path.sep}`) &&
|
||||
[".js", ".mjs", ".cjs"].includes(path.extname(modulePath).toLowerCase())
|
||||
) {
|
||||
try {
|
||||
loaded = nodeRequire(modulePath);
|
||||
} catch {
|
||||
loaded = getJiti(modulePath)(modulePath);
|
||||
}
|
||||
} else {
|
||||
loaded = getJiti(modulePath)(modulePath);
|
||||
}
|
||||
loadedModuleExports.set(modulePath, loaded);
|
||||
return loaded;
|
||||
}
|
||||
|
||||
export function loadBundledEntryExportSync<T>(
|
||||
importMetaUrl: string,
|
||||
reference: BundledEntryModuleRef,
|
||||
): T {
|
||||
const loaded = loadBundledEntryModuleSync(importMetaUrl, reference.specifier);
|
||||
const resolved =
|
||||
loaded && typeof loaded === "object" && "default" in (loaded as Record<string, unknown>)
|
||||
? (loaded as { default: unknown }).default
|
||||
: loaded;
|
||||
if (!reference.exportName) {
|
||||
return resolved as T;
|
||||
}
|
||||
const record = (resolved ?? loaded) as Record<string, unknown> | undefined;
|
||||
if (!record || !(reference.exportName in record)) {
|
||||
throw new Error(
|
||||
`missing export "${reference.exportName}" from bundled entry module ${reference.specifier}`,
|
||||
);
|
||||
}
|
||||
return record[reference.exportName] as T;
|
||||
}
|
||||
|
||||
export function defineBundledChannelEntry<TPlugin = ChannelPlugin>({
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
importMetaUrl,
|
||||
plugin,
|
||||
configSchema,
|
||||
runtime,
|
||||
registerCliMetadata,
|
||||
registerFull,
|
||||
}: DefineBundledChannelEntryOptions<TPlugin>): BundledChannelEntryContract<TPlugin> {
|
||||
const resolvedConfigSchema: ChannelEntryConfigSchema<TPlugin> =
|
||||
typeof configSchema === "function"
|
||||
? configSchema()
|
||||
: ((configSchema ?? emptyChannelConfigSchema()) as ChannelEntryConfigSchema<TPlugin>);
|
||||
const loadChannelPlugin = () => loadBundledEntryExportSync<TPlugin>(importMetaUrl, plugin);
|
||||
const setChannelRuntime = runtime
|
||||
? (pluginRuntime: PluginRuntime) => {
|
||||
const setter = loadBundledEntryExportSync<(runtime: PluginRuntime) => void>(
|
||||
importMetaUrl,
|
||||
runtime,
|
||||
);
|
||||
setter(pluginRuntime);
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
kind: "bundled-channel-entry",
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
configSchema: resolvedConfigSchema,
|
||||
register(api: OpenClawPluginApi) {
|
||||
if (api.registrationMode === "cli-metadata") {
|
||||
registerCliMetadata?.(api);
|
||||
return;
|
||||
}
|
||||
setChannelRuntime?.(api.runtime);
|
||||
api.registerChannel({ plugin: loadChannelPlugin() as ChannelPlugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
registerCliMetadata?.(api);
|
||||
registerFull?.(api);
|
||||
},
|
||||
loadChannelPlugin,
|
||||
...(setChannelRuntime ? { setChannelRuntime } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
export function defineBundledChannelSetupEntry<TPlugin = ChannelPlugin>({
|
||||
importMetaUrl,
|
||||
plugin,
|
||||
}: DefineBundledChannelSetupEntryOptions): BundledChannelSetupEntryContract<TPlugin> {
|
||||
return {
|
||||
kind: "bundled-channel-setup-entry",
|
||||
loadSetupPlugin: () => loadBundledEntryExportSync<TPlugin>(importMetaUrl, plugin),
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// Manual facade. Keep loader boundary explicit.
|
||||
type FacadeModule = typeof import("@openclaw/zalo/api.js");
|
||||
type FacadeModule = typeof import("@openclaw/zalo/setup-api.js");
|
||||
import {
|
||||
createLazyFacadeObjectValue,
|
||||
loadBundledPluginPublicSurfaceModuleSync,
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
function loadFacadeModule(): FacadeModule {
|
||||
return loadBundledPluginPublicSurfaceModuleSync<FacadeModule>({
|
||||
dirName: "zalo",
|
||||
artifactBasename: "api.js",
|
||||
artifactBasename: "setup-api.js",
|
||||
});
|
||||
}
|
||||
export const evaluateZaloGroupAccess: FacadeModule["evaluateZaloGroupAccess"] = ((...args) =>
|
||||
|
||||
Reference in New Issue
Block a user