refactor: move bundled channel deps to plugin packages

This commit is contained in:
Peter Steinberger
2026-03-19 00:24:38 +00:00
parent 9a9db87952
commit 62b7b350c9
8 changed files with 632 additions and 74 deletions

View File

@@ -193,7 +193,8 @@ enablement via `plugins.entries.<id>.enabled` or
Bundled plugin runtime dependencies are owned by each plugin package. Packaged
builds stage opted-in bundled dependencies under
`dist/extensions/<id>/node_modules` instead of requiring mirrored copies in the
root package.
root package. npm artifacts ship the built `dist/extensions/*` tree; source
`extensions/*` directories stay in source checkouts only.
Installed plugins are enabled by default, but can be disabled the same way.

View File

@@ -7,6 +7,7 @@
"@buape/carbon": "0.0.0-beta-20260216184201",
"@discordjs/voice": "^0.19.2",
"discord-api-types": "^0.38.42",
"https-proxy-agent": "^8.0.0",
"opusscript": "^0.1.1"
},
"openclaw": {

View File

@@ -4,6 +4,10 @@
"private": true,
"description": "OpenClaw Slack channel plugin",
"type": "module",
"dependencies": {
"@slack/bolt": "^4.6.0",
"@slack/web-api": "^7.15.0"
},
"openclaw": {
"extensions": [
"./index.ts"
@@ -18,6 +22,9 @@
"docsLabel": "slack",
"blurb": "supported (Socket Mode).",
"systemImage": "number"
},
"bundle": {
"stageRuntimeDependencies": true
}
}
}

View File

@@ -4,6 +4,11 @@
"private": true,
"description": "OpenClaw Telegram channel plugin",
"type": "module",
"dependencies": {
"@grammyjs/runner": "^2.0.3",
"@grammyjs/transformer-throttler": "^1.2.1",
"grammy": "^1.41.1"
},
"openclaw": {
"extensions": [
"./index.ts"
@@ -18,6 +23,9 @@
"docsLabel": "telegram",
"blurb": "simplest way to get started — register a bot with @BotFather and get going.",
"systemImage": "paperplane"
},
"bundle": {
"stageRuntimeDependencies": true
}
}
}

View File

@@ -31,7 +31,6 @@
"docs/",
"!docs/.generated/**",
"!docs/.i18n/zh-CN.tm.jsonl",
"extensions/",
"skills/"
],
"type": "module",
@@ -608,8 +607,6 @@
"@agentclientprotocol/sdk": "0.16.1",
"@aws-sdk/client-bedrock": "^3.1011.0",
"@clack/prompts": "^1.1.0",
"@grammyjs/runner": "^2.0.3",
"@grammyjs/transformer-throttler": "^1.2.1",
"@homebridge/ciao": "^1.3.5",
"@lancedb/lancedb": "^0.27.0",
"@line/bot-sdk": "^10.6.0",
@@ -621,8 +618,6 @@
"@modelcontextprotocol/sdk": "1.27.1",
"@mozilla/readability": "^0.6.0",
"@sinclair/typebox": "0.34.48",
"@slack/bolt": "^4.6.0",
"@slack/web-api": "^7.15.0",
"@whiskeysockets/baileys": "7.0.0-rc.9",
"ajv": "^8.18.0",
"chalk": "^5.6.2",
@@ -634,9 +629,7 @@
"express": "^5.2.1",
"file-type": "21.3.3",
"gaxios": "7.1.4",
"grammy": "^1.41.1",
"hono": "4.12.8",
"https-proxy-agent": "^8.0.0",
"ipaddr.js": "^2.3.0",
"jiti": "^2.6.1",
"json5": "^2.2.3",

643
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,3 @@
import { HttpsProxyAgent } from "https-proxy-agent";
import { ProxyAgent } from "undici";
import { afterEach, describe, expect, it, vi } from "vitest";
@@ -82,7 +81,7 @@ describe("gaxios fetch compat", () => {
}
});
it("translates proxy agents into undici dispatchers for native fetch", async () => {
it("translates proxy-agent-like inputs into undici dispatchers for native fetch", async () => {
const fetchMock = vi.fn<FetchLike>(async () => {
return new Response("ok", {
headers: { "content-type": "text/plain" },
@@ -93,7 +92,7 @@ describe("gaxios fetch compat", () => {
const compatFetch = createGaxiosCompatFetch(fetchMock);
await compatFetch("https://example.com", {
agent: new HttpsProxyAgent("http://proxy.example:8080"),
agent: { proxy: new URL("http://proxy.example:8080") },
} as RequestInit);
expect(fetchMock).toHaveBeenCalledOnce();

View File

@@ -12,14 +12,18 @@ function readJson<T>(relativePath: string): T {
}
describe("bundled plugin runtime dependencies", () => {
it("keeps bundled Feishu runtime deps plugin-local instead of mirroring them into the root package", () => {
function expectPluginOwnsRuntimeDep(pluginPath: string, dependencyName: string) {
const rootManifest = readJson<PackageManifest>("package.json");
const feishuManifest = readJson<PackageManifest>("extensions/feishu/package.json");
const feishuSpec = feishuManifest.dependencies?.["@larksuiteoapi/node-sdk"];
const rootSpec = rootManifest.dependencies?.["@larksuiteoapi/node-sdk"];
const pluginManifest = readJson<PackageManifest>(pluginPath);
const pluginSpec = pluginManifest.dependencies?.[dependencyName];
const rootSpec = rootManifest.dependencies?.[dependencyName];
expect(feishuSpec).toBeTruthy();
expect(pluginSpec).toBeTruthy();
expect(rootSpec).toBeUndefined();
}
it("keeps bundled Feishu runtime deps plugin-local instead of mirroring them into the root package", () => {
expectPluginOwnsRuntimeDep("extensions/feishu/package.json", "@larksuiteoapi/node-sdk");
});
it("keeps bundled memory-lancedb runtime deps available from the root package while its native runtime stays bundled", () => {
@@ -33,12 +37,18 @@ describe("bundled plugin runtime dependencies", () => {
});
it("keeps bundled Discord runtime deps plugin-local instead of mirroring them into the root package", () => {
const rootManifest = readJson<PackageManifest>("package.json");
const discordManifest = readJson<PackageManifest>("extensions/discord/package.json");
const discordSpec = discordManifest.dependencies?.["@buape/carbon"];
const rootSpec = rootManifest.dependencies?.["@buape/carbon"];
expectPluginOwnsRuntimeDep("extensions/discord/package.json", "@buape/carbon");
});
expect(discordSpec).toBeTruthy();
expect(rootSpec).toBeUndefined();
it("keeps bundled Slack runtime deps plugin-local instead of mirroring them into the root package", () => {
expectPluginOwnsRuntimeDep("extensions/slack/package.json", "@slack/bolt");
});
it("keeps bundled Telegram runtime deps plugin-local instead of mirroring them into the root package", () => {
expectPluginOwnsRuntimeDep("extensions/telegram/package.json", "grammy");
});
it("keeps bundled proxy-agent deps plugin-local instead of mirroring them into the root package", () => {
expectPluginOwnsRuntimeDep("extensions/discord/package.json", "https-proxy-agent");
});
});