mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-17 21:10:54 +00:00
refactor: dedupe channel entrypoints and test bridges
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { registerSingleProviderPlugin } from "../../src/test-utils/plugin-registration.js";
|
||||
import { registerSingleProviderPlugin } from "../test-utils/plugin-registration.js";
|
||||
import amazonBedrockPlugin from "./index.js";
|
||||
|
||||
describe("amazon-bedrock provider plugin", () => {
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/bluebubbles";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/bluebubbles";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { bluebubblesPlugin } from "./src/channel.js";
|
||||
import { setBlueBubblesRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "bluebubbles",
|
||||
name: "BlueBubbles",
|
||||
description: "BlueBubbles channel plugin (macOS app)",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setBlueBubblesRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: bluebubblesPlugin });
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
plugin: bluebubblesPlugin,
|
||||
setRuntime: setBlueBubblesRuntime,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { bluebubblesPlugin } from "./src/channel.js";
|
||||
|
||||
export default {
|
||||
plugin: bluebubblesPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(bluebubblesPlugin);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { IncomingMessage } from "node:http";
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/diffs";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { createMockServerResponse } from "../../src/test-utils/mock-http-response.js";
|
||||
import { createMockServerResponse } from "../test-utils/mock-http-response.js";
|
||||
import { createTestPluginApi } from "../test-utils/plugin-api.js";
|
||||
import plugin from "./index.js";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { IncomingMessage } from "node:http";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { createMockServerResponse } from "../../../src/test-utils/mock-http-response.js";
|
||||
import { createMockServerResponse } from "../../test-utils/mock-http-response.js";
|
||||
import { createDiffsHttpHandler } from "./http.js";
|
||||
import { DiffArtifactStore } from "./store.js";
|
||||
import { createDiffStoreHarness } from "./test-helpers.js";
|
||||
|
||||
@@ -1,22 +1,13 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { discordPlugin } from "./src/channel.js";
|
||||
import { setDiscordRuntime } from "./src/runtime.js";
|
||||
import { registerDiscordSubagentHooks } from "./src/subagent-hooks.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "discord",
|
||||
name: "Discord",
|
||||
description: "Discord channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setDiscordRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: discordPlugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
registerDiscordSubagentHooks(api);
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
plugin: discordPlugin,
|
||||
setRuntime: setDiscordRuntime,
|
||||
registerFull: registerDiscordSubagentHooks,
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { discordSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default { plugin: discordSetupPlugin };
|
||||
export default defineSetupPluginEntry(discordSetupPlugin);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { withFetchPreconnect } from "../../../src/test-utils/fetch-mock.js";
|
||||
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
|
||||
import { fetchDiscord } from "./api.js";
|
||||
import { jsonResponse } from "./test-http-helpers.js";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { countLines, hasBalancedFences } from "../../../src/test-utils/chunk-test-helpers.js";
|
||||
import { countLines, hasBalancedFences } from "../../test-utils/chunk-test-helpers.js";
|
||||
import { chunkDiscordText, chunkDiscordTextWithMode } from "./chunk.js";
|
||||
|
||||
describe("chunkDiscordText", () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ChannelType, type Guild } from "@buape/carbon";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { typedCases } from "../../../src/test-utils/typed-cases.js";
|
||||
import { typedCases } from "../../test-utils/typed-cases.js";
|
||||
import {
|
||||
allowListMatches,
|
||||
buildDiscordMediaPayload,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { withFetchPreconnect } from "../../../src/test-utils/fetch-mock.js";
|
||||
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
|
||||
import { resolveDiscordChannelAllowlist } from "./resolve-channels.js";
|
||||
import { jsonResponse, urlToString } from "./test-http-helpers.js";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { withFetchPreconnect } from "../../../src/test-utils/fetch-mock.js";
|
||||
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
|
||||
import { resolveDiscordUserAllowlist } from "./resolve-users.js";
|
||||
import { jsonResponse, urlToString } from "./test-http-helpers.js";
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/feishu";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/feishu";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { registerFeishuBitableTools } from "./src/bitable.js";
|
||||
import { feishuPlugin } from "./src/channel.js";
|
||||
import { registerFeishuChatTools } from "./src/chat.js";
|
||||
@@ -46,17 +45,13 @@ export {
|
||||
} from "./src/mention.js";
|
||||
export { feishuPlugin } from "./src/channel.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "feishu",
|
||||
name: "Feishu",
|
||||
description: "Feishu/Lark channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setFeishuRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: feishuPlugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
plugin: feishuPlugin,
|
||||
setRuntime: setFeishuRuntime,
|
||||
registerFull(api) {
|
||||
registerFeishuSubagentHooks(api);
|
||||
registerFeishuDocTools(api);
|
||||
registerFeishuChatTools(api);
|
||||
@@ -65,6 +60,4 @@ const plugin = {
|
||||
registerFeishuPermTools(api);
|
||||
registerFeishuBitableTools(api);
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { feishuPlugin } from "./src/channel.js";
|
||||
|
||||
export default {
|
||||
plugin: feishuPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(feishuPlugin);
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
createProviderUsageFetch,
|
||||
makeResponse,
|
||||
} from "../../src/test-utils/provider-usage-fetch.js";
|
||||
import { createProviderUsageFetch, makeResponse } from "../test-utils/provider-usage-fetch.js";
|
||||
import { fetchCopilotUsage } from "./usage.js";
|
||||
|
||||
describe("fetchCopilotUsage", () => {
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/googlechat";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/googlechat";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { googlechatPlugin } from "./src/channel.js";
|
||||
import { setGoogleChatRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "googlechat",
|
||||
name: "Google Chat",
|
||||
description: "OpenClaw Google Chat channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setGoogleChatRuntime(api.runtime);
|
||||
api.registerChannel(googlechatPlugin);
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
plugin: googlechatPlugin,
|
||||
setRuntime: setGoogleChatRuntime,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { googlechatPlugin } from "./src/channel.js";
|
||||
|
||||
export default {
|
||||
plugin: googlechatPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(googlechatPlugin);
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { OpenClawConfig, PluginRuntime } from "openclaw/plugin-sdk/googlech
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { createEmptyPluginRegistry } from "../../../src/plugins/registry.js";
|
||||
import { setActivePluginRegistry } from "../../../src/plugins/runtime.js";
|
||||
import { createMockServerResponse } from "../../../src/test-utils/mock-http-response.js";
|
||||
import { createMockServerResponse } from "../../test-utils/mock-http-response.js";
|
||||
import type { ResolvedGoogleChatAccount } from "./accounts.js";
|
||||
import { verifyGoogleChatRequest } from "./auth.js";
|
||||
import { handleGoogleChatWebhookRequest, registerGoogleChatWebhookTarget } from "./monitor.js";
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { imessagePlugin } from "./src/channel.js";
|
||||
import { setIMessageRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "imessage",
|
||||
name: "iMessage",
|
||||
description: "iMessage channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setIMessageRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: imessagePlugin });
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
plugin: imessagePlugin,
|
||||
setRuntime: setIMessageRuntime,
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { imessageSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default { plugin: imessageSetupPlugin };
|
||||
export default defineSetupPluginEntry(imessageSetupPlugin);
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
import type { ChannelPlugin, OpenClawPluginApi } from "openclaw/plugin-sdk/irc";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/irc";
|
||||
import type { ChannelPlugin } from "openclaw/plugin-sdk/core";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { ircPlugin } from "./src/channel.js";
|
||||
import { setIrcRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "irc",
|
||||
name: "IRC",
|
||||
description: "IRC channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setIrcRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: ircPlugin as ChannelPlugin });
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
plugin: ircPlugin as ChannelPlugin,
|
||||
setRuntime: setIrcRuntime,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { ircPlugin } from "./src/channel.js";
|
||||
|
||||
export default {
|
||||
plugin: ircPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(ircPlugin);
|
||||
|
||||
@@ -1,22 +1,13 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/line";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/line";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { registerLineCardCommand } from "./src/card-command.js";
|
||||
import { linePlugin } from "./src/channel.js";
|
||||
import { setLineRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "line",
|
||||
name: "LINE",
|
||||
description: "LINE Messaging API channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setLineRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: linePlugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
registerLineCardCommand(api);
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
plugin: linePlugin,
|
||||
setRuntime: setLineRuntime,
|
||||
registerFull: registerLineCardCommand,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { lineSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default {
|
||||
plugin: lineSetupPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(lineSetupPlugin);
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/matrix";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/matrix";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { matrixPlugin } from "./src/channel.js";
|
||||
import { setMatrixRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "matrix",
|
||||
name: "Matrix",
|
||||
description: "Matrix channel plugin (matrix-js-sdk)",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setMatrixRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: matrixPlugin });
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
description: "Matrix channel plugin",
|
||||
plugin: matrixPlugin,
|
||||
setRuntime: setMatrixRuntime,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { matrixPlugin } from "./src/channel.js";
|
||||
|
||||
export default {
|
||||
plugin: matrixPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(matrixPlugin);
|
||||
|
||||
@@ -1,26 +1,17 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/mattermost";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/mattermost";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { mattermostPlugin } from "./src/channel.js";
|
||||
import { getSlashCommandState, registerSlashCommandRoute } from "./src/mattermost/slash-state.js";
|
||||
import { registerSlashCommandRoute } from "./src/mattermost/slash-state.js";
|
||||
import { setMattermostRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "mattermost",
|
||||
name: "Mattermost",
|
||||
description: "Mattermost channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setMattermostRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: mattermostPlugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register the HTTP route for slash command callbacks.
|
||||
// The actual command registration with MM happens in the monitor
|
||||
// after the bot connects and we know the team ID.
|
||||
plugin: mattermostPlugin,
|
||||
setRuntime: setMattermostRuntime,
|
||||
registerFull(api) {
|
||||
// Actual slash-command registration happens after the monitor connects and
|
||||
// knows the team id; the route itself can be wired here.
|
||||
registerSlashCommandRoute(api);
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { mattermostPlugin } from "./src/channel.js";
|
||||
|
||||
export default {
|
||||
plugin: mattermostPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(mattermostPlugin);
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/msteams";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/msteams";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { msteamsPlugin } from "./src/channel.js";
|
||||
import { setMSTeamsRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "msteams",
|
||||
name: "Microsoft Teams",
|
||||
description: "Microsoft Teams channel plugin (Bot Framework)",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setMSTeamsRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: msteamsPlugin });
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
plugin: msteamsPlugin,
|
||||
setRuntime: setMSTeamsRuntime,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { msteamsPlugin } from "./src/channel.js";
|
||||
|
||||
export default {
|
||||
plugin: msteamsPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(msteamsPlugin);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { withFetchPreconnect } from "../../../src/test-utils/fetch-mock.js";
|
||||
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
|
||||
import { uploadToOneDrive, uploadToSharePoint } from "./graph-upload.js";
|
||||
|
||||
describe("graph upload helpers", () => {
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/nextcloud-talk";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/nextcloud-talk";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { nextcloudTalkPlugin } from "./src/channel.js";
|
||||
import { setNextcloudTalkRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "nextcloud-talk",
|
||||
name: "Nextcloud Talk",
|
||||
description: "Nextcloud Talk channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setNextcloudTalkRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: nextcloudTalkPlugin });
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
plugin: nextcloudTalkPlugin,
|
||||
setRuntime: setNextcloudTalkRuntime,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { nextcloudTalkPlugin } from "./src/channel.js";
|
||||
|
||||
export default {
|
||||
plugin: nextcloudTalkPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(nextcloudTalkPlugin);
|
||||
|
||||
@@ -1,24 +1,17 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/nostr";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/nostr";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { nostrPlugin } from "./src/channel.js";
|
||||
import type { NostrProfile } from "./src/config-schema.js";
|
||||
import { createNostrProfileHttpHandler } from "./src/nostr-profile-http.js";
|
||||
import { setNostrRuntime, getNostrRuntime } from "./src/runtime.js";
|
||||
import { getNostrRuntime, setNostrRuntime } from "./src/runtime.js";
|
||||
import { resolveNostrAccount } from "./src/types.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "nostr",
|
||||
name: "Nostr",
|
||||
description: "Nostr DM channel plugin via NIP-04",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setNostrRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: nostrPlugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register HTTP handler for profile management
|
||||
plugin: nostrPlugin,
|
||||
setRuntime: setNostrRuntime,
|
||||
registerFull(api) {
|
||||
const httpHandler = createNostrProfileHttpHandler({
|
||||
getConfigProfile: (accountId: string) => {
|
||||
const runtime = getNostrRuntime();
|
||||
@@ -30,23 +23,18 @@ const plugin = {
|
||||
const runtime = getNostrRuntime();
|
||||
const cfg = runtime.config.loadConfig();
|
||||
|
||||
// Build the config patch for channels.nostr.profile
|
||||
const channels = (cfg.channels ?? {}) as Record<string, unknown>;
|
||||
const nostrConfig = (channels.nostr ?? {}) as Record<string, unknown>;
|
||||
|
||||
const updatedNostrConfig = {
|
||||
...nostrConfig,
|
||||
profile,
|
||||
};
|
||||
|
||||
const updatedChannels = {
|
||||
...channels,
|
||||
nostr: updatedNostrConfig,
|
||||
};
|
||||
|
||||
await runtime.config.writeConfigFile({
|
||||
...cfg,
|
||||
channels: updatedChannels,
|
||||
channels: {
|
||||
...channels,
|
||||
nostr: {
|
||||
...nostrConfig,
|
||||
profile,
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
getAccountInfo: (accountId: string) => {
|
||||
@@ -71,6 +59,4 @@ const plugin = {
|
||||
handler: httpHandler,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { nostrPlugin } from "./src/channel.js";
|
||||
|
||||
export default {
|
||||
plugin: nostrPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(nostrPlugin);
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { signalPlugin } from "./src/channel.js";
|
||||
import { setSignalRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "signal",
|
||||
name: "Signal",
|
||||
description: "Signal channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setSignalRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: signalPlugin });
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
plugin: signalPlugin,
|
||||
setRuntime: setSignalRuntime,
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { signalSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default { plugin: signalSetupPlugin };
|
||||
export default defineSetupPluginEntry(signalSetupPlugin);
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { slackPlugin } from "./src/channel.js";
|
||||
import { setSlackRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "slack",
|
||||
name: "Slack",
|
||||
description: "Slack channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setSlackRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: slackPlugin });
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
plugin: slackPlugin,
|
||||
setRuntime: setSlackRuntime,
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { slackSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default { plugin: slackSetupPlugin };
|
||||
export default defineSetupPluginEntry(slackSetupPlugin);
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as mediaFetch from "../../../../src/media/fetch.js";
|
||||
import type { SavedMedia } from "../../../../src/media/store.js";
|
||||
import * as mediaStore from "../../../../src/media/store.js";
|
||||
import { mockPinnedHostnameResolution } from "../../../../src/test-helpers/ssrf.js";
|
||||
import { type FetchMock, withFetchPreconnect } from "../../../../src/test-utils/fetch-mock.js";
|
||||
import { type FetchMock, withFetchPreconnect } from "../../../test-utils/fetch-mock.js";
|
||||
import {
|
||||
fetchWithSlackAuth,
|
||||
resolveSlackAttachmentContent,
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/synology-chat";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/synology-chat";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { synologyChatPlugin } from "./src/channel.js";
|
||||
import { setSynologyRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "synology-chat",
|
||||
name: "Synology Chat",
|
||||
description: "Native Synology Chat channel plugin for OpenClaw",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setSynologyRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: synologyChatPlugin });
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
plugin: synologyChatPlugin,
|
||||
setRuntime: setSynologyRuntime,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { synologyChatPlugin } from "./src/channel.js";
|
||||
|
||||
export default {
|
||||
plugin: synologyChatPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(synologyChatPlugin);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawPluginCommandDefinition } from "../../src/plugins/types.js";
|
||||
import type { OpenClawPluginCommandDefinition } from "../test-utils/plugin-command.js";
|
||||
import { createPluginRuntimeMock } from "../test-utils/plugin-runtime-mock.js";
|
||||
import register from "./index.js";
|
||||
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
import type { ChannelPlugin, OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core";
|
||||
import type { ChannelPlugin } from "openclaw/plugin-sdk/core";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { telegramPlugin } from "./src/channel.js";
|
||||
import { setTelegramRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "telegram",
|
||||
name: "Telegram",
|
||||
description: "Telegram channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setTelegramRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: telegramPlugin as ChannelPlugin });
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
plugin: telegramPlugin as ChannelPlugin,
|
||||
setRuntime: setTelegramRuntime,
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { telegramSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default { plugin: telegramSetupPlugin };
|
||||
export default defineSetupPluginEntry(telegramSetupPlugin);
|
||||
|
||||
@@ -3,7 +3,7 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import { withEnv } from "../../../src/test-utils/env.js";
|
||||
import { withEnv } from "../../test-utils/env.js";
|
||||
import { inspectTelegramAccount } from "./account-inspect.js";
|
||||
|
||||
describe("inspectTelegramAccount SecretRef resolution", () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import * as subsystemModule from "../../../src/logging/subsystem.js";
|
||||
import { withEnv } from "../../../src/test-utils/env.js";
|
||||
import { withEnv } from "../../test-utils/env.js";
|
||||
import {
|
||||
listTelegramAccountIds,
|
||||
resetMissingDefaultWarnFlag,
|
||||
|
||||
@@ -2,9 +2,9 @@ import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import { withEnvAsync } from "../../../src/test-utils/env.js";
|
||||
import { useFrozenTime, useRealTime } from "../../../src/test-utils/frozen-time.js";
|
||||
import { escapeRegExp, formatEnvelopeTimestamp } from "../../../test/helpers/envelope-timestamp.js";
|
||||
import { withEnvAsync } from "../../test-utils/env.js";
|
||||
import { useFrozenTime, useRealTime } from "../../test-utils/frozen-time.js";
|
||||
import {
|
||||
answerCallbackQuerySpy,
|
||||
botCtorSpy,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { rm } from "node:fs/promises";
|
||||
import type { PluginInteractiveTelegramHandlerContext } from "openclaw/plugin-sdk/core";
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { expectChannelInboundContextContract as expectInboundContextContract } from "../../../src/channels/plugins/contracts/suites.js";
|
||||
import {
|
||||
clearPluginInteractiveHandlers,
|
||||
registerPluginInteractiveHandler,
|
||||
} from "../../../src/plugins/interactive.js";
|
||||
import type { PluginInteractiveTelegramHandlerContext } from "../../../src/plugins/types.js";
|
||||
import { escapeRegExp, formatEnvelopeTimestamp } from "../../../test/helpers/envelope-timestamp.js";
|
||||
import {
|
||||
answerCallbackQuerySpy,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { afterEach, type Mock, describe, expect, it, vi } from "vitest";
|
||||
import { withFetchPreconnect } from "../../../src/test-utils/fetch-mock.js";
|
||||
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
|
||||
import { probeTelegram, resetTelegramProbeFetcherCacheForTests } from "./probe.js";
|
||||
|
||||
const resolveTelegramFetch = vi.hoisted(() => vi.fn());
|
||||
|
||||
1
extensions/test-utils/chunk-test-helpers.ts
Normal file
1
extensions/test-utils/chunk-test-helpers.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { countLines, hasBalancedFences } from "../../src/test-utils/chunk-test-helpers.js";
|
||||
1
extensions/test-utils/env.ts
Normal file
1
extensions/test-utils/env.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { captureEnv, withEnv, withEnvAsync } from "../../src/test-utils/env.js";
|
||||
1
extensions/test-utils/fetch-mock.ts
Normal file
1
extensions/test-utils/fetch-mock.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { withFetchPreconnect, type FetchMock } from "../../src/test-utils/fetch-mock.js";
|
||||
1
extensions/test-utils/frozen-time.ts
Normal file
1
extensions/test-utils/frozen-time.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { useFrozenTime, useRealTime } from "../../src/test-utils/frozen-time.js";
|
||||
1
extensions/test-utils/mock-http-response.ts
Normal file
1
extensions/test-utils/mock-http-response.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { createMockServerResponse } from "../../src/test-utils/mock-http-response.js";
|
||||
1
extensions/test-utils/plugin-command.ts
Normal file
1
extensions/test-utils/plugin-command.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type { OpenClawPluginCommandDefinition } from "openclaw/plugin-sdk/core";
|
||||
1
extensions/test-utils/plugin-registration.ts
Normal file
1
extensions/test-utils/plugin-registration.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { registerSingleProviderPlugin } from "../../src/test-utils/plugin-registration.js";
|
||||
4
extensions/test-utils/provider-usage-fetch.ts
Normal file
4
extensions/test-utils/provider-usage-fetch.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export {
|
||||
createProviderUsageFetch,
|
||||
makeResponse,
|
||||
} from "../../src/test-utils/provider-usage-fetch.js";
|
||||
1
extensions/test-utils/temp-dir.ts
Normal file
1
extensions/test-utils/temp-dir.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { withTempDir } from "../../src/test-utils/temp-dir.js";
|
||||
1
extensions/test-utils/typed-cases.ts
Normal file
1
extensions/test-utils/typed-cases.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { typedCases } from "../../src/test-utils/typed-cases.js";
|
||||
@@ -2,14 +2,12 @@ import { spawn } from "node:child_process";
|
||||
import { existsSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/tlon";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/tlon";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { tlonPlugin } from "./src/channel.js";
|
||||
import { setTlonRuntime } from "./src/runtime.js";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
// Whitelist of allowed tlon subcommands
|
||||
const ALLOWED_TLON_COMMANDS = new Set([
|
||||
"activity",
|
||||
"channels",
|
||||
@@ -24,40 +22,29 @@ const ALLOWED_TLON_COMMANDS = new Set([
|
||||
"version",
|
||||
]);
|
||||
|
||||
/**
|
||||
* Find the tlon binary from the skill package
|
||||
*/
|
||||
let cachedTlonBinary: string | undefined;
|
||||
|
||||
function findTlonBinary(): string {
|
||||
if (cachedTlonBinary) {
|
||||
return cachedTlonBinary;
|
||||
}
|
||||
// Check in node_modules/.bin
|
||||
const skillBin = join(__dirname, "node_modules", ".bin", "tlon");
|
||||
if (existsSync(skillBin)) {
|
||||
cachedTlonBinary = skillBin;
|
||||
return skillBin;
|
||||
}
|
||||
|
||||
// Check for platform-specific binary directly
|
||||
const platform = process.platform;
|
||||
const arch = process.arch;
|
||||
const platformPkg = `@tloncorp/tlon-skill-${platform}-${arch}`;
|
||||
const platformPkg = `@tloncorp/tlon-skill-${process.platform}-${process.arch}`;
|
||||
const platformBin = join(__dirname, "node_modules", platformPkg, "tlon");
|
||||
if (existsSync(platformBin)) {
|
||||
cachedTlonBinary = platformBin;
|
||||
return platformBin;
|
||||
}
|
||||
|
||||
// Fallback to PATH
|
||||
cachedTlonBinary = "tlon";
|
||||
return cachedTlonBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shell-like argument splitter that respects quotes
|
||||
*/
|
||||
function shellSplit(str: string): string[] {
|
||||
const args: string[] = [];
|
||||
let cur = "";
|
||||
@@ -92,18 +79,15 @@ function shellSplit(str: string): string[] {
|
||||
}
|
||||
cur += ch;
|
||||
}
|
||||
if (cur) args.push(cur);
|
||||
if (cur) {
|
||||
args.push(cur);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the tlon command and return the result
|
||||
*/
|
||||
function runTlonCommand(binary: string, args: string[]): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = spawn(binary, args, {
|
||||
env: process.env,
|
||||
});
|
||||
const child = spawn(binary, args, { env: process.env });
|
||||
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
@@ -123,25 +107,20 @@ function runTlonCommand(binary: string, args: string[]): Promise<string> {
|
||||
child.on("close", (code) => {
|
||||
if (code !== 0) {
|
||||
reject(new Error(stderr || `tlon exited with code ${code}`));
|
||||
} else {
|
||||
resolve(stdout);
|
||||
return;
|
||||
}
|
||||
resolve(stdout);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "tlon",
|
||||
name: "Tlon",
|
||||
description: "Tlon/Urbit channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setTlonRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: tlonPlugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
|
||||
plugin: tlonPlugin,
|
||||
setRuntime: setTlonRuntime,
|
||||
registerFull(api) {
|
||||
api.logger.debug?.("[tlon] Registering tlon tool");
|
||||
api.registerTool({
|
||||
name: "tlon",
|
||||
@@ -164,9 +143,6 @@ const plugin = {
|
||||
async execute(_id: string, params: { command: string }) {
|
||||
try {
|
||||
const args = shellSplit(params.command);
|
||||
const tlonBinary = findTlonBinary();
|
||||
|
||||
// Validate first argument is a whitelisted tlon subcommand
|
||||
const subcommand = args[0];
|
||||
if (!ALLOWED_TLON_COMMANDS.has(subcommand)) {
|
||||
return {
|
||||
@@ -180,7 +156,7 @@ const plugin = {
|
||||
};
|
||||
}
|
||||
|
||||
const output = await runTlonCommand(tlonBinary, args);
|
||||
const output = await runTlonCommand(findTlonBinary(), args);
|
||||
return {
|
||||
content: [{ type: "text" as const, text: output }],
|
||||
details: undefined,
|
||||
@@ -194,6 +170,4 @@ const plugin = {
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { tlonPlugin } from "./src/channel.js";
|
||||
|
||||
export default {
|
||||
plugin: tlonPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(tlonPlugin);
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/twitch";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/twitch";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { twitchPlugin } from "./src/plugin.js";
|
||||
import { setTwitchRuntime } from "./src/runtime.js";
|
||||
|
||||
export { monitorTwitchProvider } from "./src/monitor.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "twitch",
|
||||
name: "Twitch",
|
||||
description: "Twitch channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setTwitchRuntime(api.runtime);
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
api.registerChannel({ plugin: twitchPlugin as any });
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
description: "Twitch chat channel plugin",
|
||||
plugin: twitchPlugin,
|
||||
setRuntime: setTwitchRuntime,
|
||||
});
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { whatsappPlugin } from "./src/channel.js";
|
||||
import { setWhatsAppRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "whatsapp",
|
||||
name: "WhatsApp",
|
||||
description: "WhatsApp channel plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setWhatsAppRuntime(api.runtime);
|
||||
api.registerChannel({ plugin: whatsappPlugin });
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
plugin: whatsappPlugin,
|
||||
setRuntime: setWhatsAppRuntime,
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { whatsappSetupPlugin } from "./src/channel.setup.js";
|
||||
|
||||
export default { plugin: whatsappSetupPlugin };
|
||||
export default defineSetupPluginEntry(whatsappSetupPlugin);
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { captureEnv } from "../../../src/test-utils/env.js";
|
||||
import { captureEnv } from "../../test-utils/env.js";
|
||||
import { hasAnyWhatsAppAuth, listWhatsAppAuthDirs } from "./accounts.js";
|
||||
|
||||
describe("hasAnyWhatsAppAuth", () => {
|
||||
|
||||
@@ -4,8 +4,8 @@ import fs from "node:fs/promises";
|
||||
import { beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import { setLoggerOverride } from "../../../src/logging.js";
|
||||
import { withEnvAsync } from "../../../src/test-utils/env.js";
|
||||
import { escapeRegExp, formatEnvelopeTimestamp } from "../../../test/helpers/envelope-timestamp.js";
|
||||
import { withEnvAsync } from "../../test-utils/env.js";
|
||||
import {
|
||||
createMockWebListener,
|
||||
createWebListenerFactoryCapture,
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { saveSessionStore } from "../../../../src/config/sessions.js";
|
||||
import { withTempDir } from "../../../../src/test-utils/temp-dir.js";
|
||||
import { withTempDir } from "../../../test-utils/temp-dir.js";
|
||||
import {
|
||||
debugMention,
|
||||
isBotMentionedFromTargets,
|
||||
|
||||
@@ -7,8 +7,8 @@ import { resolveStateDir } from "../../../src/config/paths.js";
|
||||
import { resolvePreferredOpenClawTmpDir } from "../../../src/infra/tmp-openclaw-dir.js";
|
||||
import { optimizeImageToPng } from "../../../src/media/image-ops.js";
|
||||
import { mockPinnedHostnameResolution } from "../../../src/test-helpers/ssrf.js";
|
||||
import { captureEnv } from "../../../src/test-utils/env.js";
|
||||
import { sendVoiceMessageDiscord } from "../../discord/src/send.js";
|
||||
import { captureEnv } from "../../test-utils/env.js";
|
||||
import {
|
||||
LocalMediaAccessError,
|
||||
loadWebMedia,
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/zalo";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/zalo";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { zaloPlugin } from "./src/channel.js";
|
||||
import { setZaloRuntime } from "./src/runtime.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "zalo",
|
||||
name: "Zalo",
|
||||
description: "Zalo channel plugin (Bot API)",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setZaloRuntime(api.runtime);
|
||||
api.registerChannel(zaloPlugin);
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
description: "Zalo channel plugin",
|
||||
plugin: zaloPlugin,
|
||||
setRuntime: setZaloRuntime,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { zaloPlugin } from "./src/channel.js";
|
||||
|
||||
export default {
|
||||
plugin: zaloPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(zaloPlugin);
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
import type { AnyAgentTool, OpenClawPluginApi } from "openclaw/plugin-sdk/zalouser";
|
||||
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/zalouser";
|
||||
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import type { AnyAgentTool } from "openclaw/plugin-sdk/zalouser";
|
||||
import { zalouserPlugin } from "./src/channel.js";
|
||||
import { setZalouserRuntime } from "./src/runtime.js";
|
||||
import { ZalouserToolSchema, executeZalouserTool } from "./src/tool.js";
|
||||
|
||||
const plugin = {
|
||||
export default defineChannelPluginEntry({
|
||||
id: "zalouser",
|
||||
name: "Zalo Personal",
|
||||
description: "Zalo personal account messaging via native zca-js integration",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setZalouserRuntime(api.runtime);
|
||||
api.registerChannel(zalouserPlugin);
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
|
||||
plugin: zalouserPlugin,
|
||||
setRuntime: setZalouserRuntime,
|
||||
registerFull(api) {
|
||||
api.registerTool({
|
||||
name: "zalouser",
|
||||
label: "Zalo Personal",
|
||||
@@ -27,6 +22,4 @@ const plugin = {
|
||||
execute: executeZalouserTool,
|
||||
} as AnyAgentTool);
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
|
||||
import { zalouserPlugin } from "./src/channel.js";
|
||||
|
||||
export default {
|
||||
plugin: zalouserPlugin,
|
||||
};
|
||||
export default defineSetupPluginEntry(zalouserPlugin);
|
||||
|
||||
@@ -443,7 +443,7 @@
|
||||
"build:plugin-sdk:dts": "tsc -p tsconfig.plugin-sdk.dts.json || true",
|
||||
"build:strict-smoke": "pnpm canvas:a2ui:bundle && node scripts/tsdown-build.mjs && node scripts/runtime-postbuild.mjs && pnpm build:plugin-sdk:dts",
|
||||
"canvas:a2ui:bundle": "bash scripts/bundle-a2ui.sh",
|
||||
"check": "pnpm check:host-env-policy:swift && pnpm format:check && pnpm tsgo && pnpm plugin-sdk:check-exports && pnpm lint && pnpm lint:tmp:no-random-messaging && pnpm lint:tmp:channel-agnostic-boundaries && pnpm lint:tmp:no-raw-channel-fetch && pnpm lint:agent:ingress-owner && pnpm lint:plugins:no-register-http-handler && pnpm lint:plugins:no-monolithic-plugin-sdk-entry-imports && pnpm lint:webhook:no-low-level-body-read && pnpm lint:auth:no-pairing-store-group && pnpm lint:auth:pairing-account-scope",
|
||||
"check": "pnpm check:host-env-policy:swift && pnpm format:check && pnpm tsgo && pnpm plugin-sdk:check-exports && pnpm lint && pnpm lint:tmp:no-random-messaging && pnpm lint:tmp:channel-agnostic-boundaries && pnpm lint:tmp:no-raw-channel-fetch && pnpm lint:agent:ingress-owner && pnpm lint:plugins:no-register-http-handler && pnpm lint:plugins:no-monolithic-plugin-sdk-entry-imports && pnpm lint:plugins:no-extension-test-core-imports && pnpm lint:webhook:no-low-level-body-read && pnpm lint:auth:no-pairing-store-group && pnpm lint:auth:pairing-account-scope",
|
||||
"check:docs": "pnpm format:docs:check && pnpm lint:docs && pnpm docs:check-i18n-glossary && pnpm docs:check-links",
|
||||
"check:host-env-policy:swift": "node scripts/generate-host-env-security-policy-swift.mjs --check",
|
||||
"check:loc": "node --import tsx scripts/check-ts-max-loc.ts --max 500",
|
||||
@@ -495,6 +495,7 @@
|
||||
"lint:docs": "pnpm dlx markdownlint-cli2",
|
||||
"lint:docs:fix": "pnpm dlx markdownlint-cli2 --fix",
|
||||
"lint:fix": "oxlint --type-aware --fix && pnpm format",
|
||||
"lint:plugins:no-extension-test-core-imports": "node --import tsx scripts/check-no-extension-test-core-imports.ts",
|
||||
"lint:plugins:no-monolithic-plugin-sdk-entry-imports": "node --import tsx scripts/check-no-monolithic-plugin-sdk-entry-imports.ts",
|
||||
"lint:plugins:no-register-http-handler": "node scripts/check-no-register-http-handler.mjs",
|
||||
"lint:swift": "swiftlint lint --config .swiftlint.yml && (cd apps/ios && swiftlint lint --config .swiftlint.yml)",
|
||||
|
||||
90
scripts/check-no-extension-test-core-imports.ts
Normal file
90
scripts/check-no-extension-test-core-imports.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const FORBIDDEN_PATTERNS: Array<{ pattern: RegExp; hint: string }> = [
|
||||
{
|
||||
pattern: /["']openclaw\/plugin-sdk["']/,
|
||||
hint: "Use openclaw/plugin-sdk/<subpath> instead of the monolithic root entry.",
|
||||
},
|
||||
{
|
||||
pattern: /["']openclaw\/plugin-sdk\/compat["']/,
|
||||
hint: "Use a focused public plugin-sdk subpath instead of compat.",
|
||||
},
|
||||
{
|
||||
pattern: /["'](?:\.\.\/)+(?:src\/test-utils\/)[^"']+["']/,
|
||||
hint: "Use extensions/test-utils/* bridges for shared extension test helpers.",
|
||||
},
|
||||
{
|
||||
pattern: /["'](?:\.\.\/)+(?:src\/plugins\/types\.js)["']/,
|
||||
hint: "Use public plugin-sdk/core types or extensions/test-utils bridges instead.",
|
||||
},
|
||||
];
|
||||
|
||||
function isExtensionTestFile(filePath: string): boolean {
|
||||
return /\.test\.[cm]?[jt]sx?$/u.test(filePath) || /\.e2e\.test\.[cm]?[jt]sx?$/u.test(filePath);
|
||||
}
|
||||
|
||||
function collectExtensionTestFiles(rootDir: string): string[] {
|
||||
const files: string[] = [];
|
||||
const stack = [rootDir];
|
||||
while (stack.length > 0) {
|
||||
const current = stack.pop();
|
||||
if (!current) {
|
||||
continue;
|
||||
}
|
||||
let entries: fs.Dirent[] = [];
|
||||
try {
|
||||
entries = fs.readdirSync(current, { withFileTypes: true });
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(current, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "coverage") {
|
||||
continue;
|
||||
}
|
||||
stack.push(fullPath);
|
||||
continue;
|
||||
}
|
||||
if (entry.isFile() && isExtensionTestFile(fullPath)) {
|
||||
files.push(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const extensionsDir = path.join(process.cwd(), "extensions");
|
||||
const files = collectExtensionTestFiles(extensionsDir);
|
||||
const offenders: Array<{ file: string; hint: string }> = [];
|
||||
|
||||
for (const file of files) {
|
||||
const content = fs.readFileSync(file, "utf8");
|
||||
for (const rule of FORBIDDEN_PATTERNS) {
|
||||
if (!rule.pattern.test(content)) {
|
||||
continue;
|
||||
}
|
||||
offenders.push({ file, hint: rule.hint });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (offenders.length > 0) {
|
||||
console.error(
|
||||
"Extension test files must stay on extension test bridges or public plugin-sdk seams.",
|
||||
);
|
||||
for (const offender of offenders.toSorted((a, b) => a.file.localeCompare(b.file))) {
|
||||
const relative = path.relative(process.cwd(), offender.file) || offender.file;
|
||||
console.error(`- ${relative}: ${offender.hint}`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(
|
||||
`OK: extension test files avoid direct core test/internal imports (${files.length} checked).`,
|
||||
);
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -1,3 +1,13 @@
|
||||
import type { ChannelPlugin } from "../channels/plugins/types.plugin.js";
|
||||
import { emptyPluginConfigSchema } from "../plugins/config-schema.js";
|
||||
import type { PluginRuntime } from "../plugins/runtime/types.js";
|
||||
import type {
|
||||
OpenClawPluginApi,
|
||||
OpenClawPluginCommandDefinition,
|
||||
OpenClawPluginConfigSchema,
|
||||
PluginInteractiveTelegramHandlerContext,
|
||||
} from "../plugins/types.js";
|
||||
|
||||
export type {
|
||||
AnyAgentTool,
|
||||
MediaUnderstandingProviderPlugin,
|
||||
@@ -31,6 +41,8 @@ export type {
|
||||
ProviderAuthMethodNonInteractiveContext,
|
||||
ProviderAuthMethod,
|
||||
ProviderAuthResult,
|
||||
OpenClawPluginCommandDefinition,
|
||||
PluginInteractiveTelegramHandlerContext,
|
||||
} from "../plugins/types.js";
|
||||
export type { OpenClawConfig } from "../config/config.js";
|
||||
export type { GatewayRequestHandlerOptions } from "../gateway/server-methods/types.js";
|
||||
@@ -70,3 +82,44 @@ export {
|
||||
export { buildOutboundBaseSessionKey } from "../infra/outbound/base-session-key.js";
|
||||
export { normalizeOutboundThreadId } from "../infra/outbound/thread-id.js";
|
||||
export { resolveThreadSessionKeys } from "../routing/session-key.js";
|
||||
|
||||
type DefineChannelPluginEntryOptions<TPlugin extends ChannelPlugin = ChannelPlugin> = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
plugin: TPlugin;
|
||||
configSchema?: () => OpenClawPluginConfigSchema;
|
||||
setRuntime?: (runtime: PluginRuntime) => void;
|
||||
registerFull?: (api: OpenClawPluginApi) => void;
|
||||
};
|
||||
|
||||
// Shared channel-plugin entry boilerplate for bundled and third-party channels.
|
||||
export function defineChannelPluginEntry<TPlugin extends ChannelPlugin>({
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
plugin,
|
||||
configSchema = emptyPluginConfigSchema,
|
||||
setRuntime,
|
||||
registerFull,
|
||||
}: DefineChannelPluginEntryOptions<TPlugin>) {
|
||||
return {
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
configSchema: configSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
setRuntime?.(api.runtime);
|
||||
api.registerChannel({ plugin });
|
||||
if (api.registrationMode !== "full") {
|
||||
return;
|
||||
}
|
||||
registerFull?.(api);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Shared setup-entry shape so bundled channels do not duplicate `{ plugin }`.
|
||||
export function defineSetupPluginEntry<TPlugin>(plugin: TPlugin) {
|
||||
return { plugin };
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@ describe("plugin-sdk subpath exports", () => {
|
||||
|
||||
it("keeps core focused on generic shared exports", () => {
|
||||
expect(typeof coreSdk.emptyPluginConfigSchema).toBe("function");
|
||||
expect(typeof coreSdk.defineChannelPluginEntry).toBe("function");
|
||||
expect(typeof coreSdk.defineSetupPluginEntry).toBe("function");
|
||||
expect("runPassiveAccountLifecycle" in asExports(coreSdk)).toBe(false);
|
||||
expect("createLoggerBackedRuntime" in asExports(coreSdk)).toBe(false);
|
||||
expect("registerSandboxBackend" in asExports(coreSdk)).toBe(false);
|
||||
|
||||
Reference in New Issue
Block a user