Build: isolate optional bundled plugin-sdk clusters
This commit is contained in:
parent
b4f16bad32
commit
891e2a3da8
@ -14,3 +14,17 @@ export const optionalBundledClusters = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const optionalBundledClusterSet = new Set(optionalBundledClusters);
|
export const optionalBundledClusterSet = new Set(optionalBundledClusters);
|
||||||
|
|
||||||
|
export const OPTIONAL_BUNDLED_BUILD_ENV = "OPENCLAW_INCLUDE_OPTIONAL_BUNDLED";
|
||||||
|
|
||||||
|
export function isOptionalBundledCluster(cluster) {
|
||||||
|
return optionalBundledClusterSet.has(cluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function shouldIncludeOptionalBundledClusters(env = process.env) {
|
||||||
|
return env[OPTIONAL_BUNDLED_BUILD_ENV] === "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function shouldBuildBundledCluster(cluster, env = process.env) {
|
||||||
|
return shouldIncludeOptionalBundledClusters(env) || !isOptionalBundledCluster(cluster);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
// Narrow plugin-sdk surface for the bundled googlechat plugin.
|
// Narrow plugin-sdk surface for the bundled googlechat plugin.
|
||||||
// Keep this list additive and scoped to symbols used under extensions/googlechat.
|
// Keep this list additive and scoped to symbols used under extensions/googlechat.
|
||||||
|
|
||||||
|
import { resolveChannelGroupRequireMention } from "./channel-policy.js";
|
||||||
|
import {
|
||||||
|
createOptionalChannelSetupAdapter,
|
||||||
|
createOptionalChannelSetupWizard,
|
||||||
|
} from "./optional-channel-setup.js";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
createActionGate,
|
createActionGate,
|
||||||
jsonResult,
|
jsonResult,
|
||||||
@ -20,7 +26,6 @@ export {
|
|||||||
export { buildComputedAccountStatusSnapshot } from "./status-helpers.js";
|
export { buildComputedAccountStatusSnapshot } from "./status-helpers.js";
|
||||||
export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
||||||
export { createAccountStatusSink, runPassiveAccountLifecycle } from "./channel-lifecycle.js";
|
export { createAccountStatusSink, runPassiveAccountLifecycle } from "./channel-lifecycle.js";
|
||||||
export { resolveGoogleChatGroupRequireMention } from "../../extensions/googlechat/src/group-policy.js";
|
|
||||||
export { formatPairingApproveHint } from "../channels/plugins/helpers.js";
|
export { formatPairingApproveHint } from "../channels/plugins/helpers.js";
|
||||||
export { resolveChannelMediaMaxBytes } from "../channels/plugins/media-limits.js";
|
export { resolveChannelMediaMaxBytes } from "../channels/plugins/media-limits.js";
|
||||||
export {
|
export {
|
||||||
@ -65,8 +70,6 @@ export { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.j
|
|||||||
export { resolveDmGroupAccessWithLists } from "../security/dm-policy-shared.js";
|
export { resolveDmGroupAccessWithLists } from "../security/dm-policy-shared.js";
|
||||||
export { formatDocsLink } from "../terminal/links.js";
|
export { formatDocsLink } from "../terminal/links.js";
|
||||||
export type { WizardPrompter } from "../wizard/prompts.js";
|
export type { WizardPrompter } from "../wizard/prompts.js";
|
||||||
export { googlechatSetupAdapter } from "../../extensions/googlechat/api.js";
|
|
||||||
export { googlechatSetupWizard } from "../../extensions/googlechat/api.js";
|
|
||||||
export { resolveInboundRouteEnvelopeBuilderWithRuntime } from "./inbound-envelope.js";
|
export { resolveInboundRouteEnvelopeBuilderWithRuntime } from "./inbound-envelope.js";
|
||||||
export { createScopedPairingAccess } from "./pairing-access.js";
|
export { createScopedPairingAccess } from "./pairing-access.js";
|
||||||
export { issuePairingChallenge } from "../pairing/pairing-challenge.js";
|
export { issuePairingChallenge } from "../pairing/pairing-challenge.js";
|
||||||
@ -88,3 +91,32 @@ export {
|
|||||||
resolveWebhookTargetWithAuthOrReject,
|
resolveWebhookTargetWithAuthOrReject,
|
||||||
withResolvedWebhookRequestPipeline,
|
withResolvedWebhookRequestPipeline,
|
||||||
} from "./webhook-targets.js";
|
} from "./webhook-targets.js";
|
||||||
|
|
||||||
|
type GoogleChatGroupContext = {
|
||||||
|
cfg: import("../config/config.js").OpenClawConfig;
|
||||||
|
accountId?: string | null;
|
||||||
|
groupId?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function resolveGoogleChatGroupRequireMention(params: GoogleChatGroupContext): boolean {
|
||||||
|
return resolveChannelGroupRequireMention({
|
||||||
|
cfg: params.cfg,
|
||||||
|
channel: "googlechat",
|
||||||
|
groupId: params.groupId,
|
||||||
|
accountId: params.accountId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const googlechatSetupAdapter = createOptionalChannelSetupAdapter({
|
||||||
|
channel: "googlechat",
|
||||||
|
label: "Google Chat",
|
||||||
|
npmSpec: "@openclaw/googlechat",
|
||||||
|
docsPath: "/channels/googlechat",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const googlechatSetupWizard = createOptionalChannelSetupWizard({
|
||||||
|
channel: "googlechat",
|
||||||
|
label: "Google Chat",
|
||||||
|
npmSpec: "@openclaw/googlechat",
|
||||||
|
docsPath: "/channels/googlechat",
|
||||||
|
});
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
// Narrow plugin-sdk surface for the bundled matrix plugin.
|
// Narrow plugin-sdk surface for the bundled matrix plugin.
|
||||||
// Keep this list additive and scoped to symbols used under extensions/matrix.
|
// Keep this list additive and scoped to symbols used under extensions/matrix.
|
||||||
|
|
||||||
|
import {
|
||||||
|
createOptionalChannelSetupAdapter,
|
||||||
|
createOptionalChannelSetupWizard,
|
||||||
|
} from "./optional-channel-setup.js";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
createActionGate,
|
createActionGate,
|
||||||
jsonResult,
|
jsonResult,
|
||||||
@ -108,5 +113,17 @@ export {
|
|||||||
buildProbeChannelStatusSummary,
|
buildProbeChannelStatusSummary,
|
||||||
collectStatusIssuesFromLastError,
|
collectStatusIssuesFromLastError,
|
||||||
} from "./status-helpers.js";
|
} from "./status-helpers.js";
|
||||||
export { matrixSetupWizard } from "../../extensions/matrix/api.js";
|
|
||||||
export { matrixSetupAdapter } from "../../extensions/matrix/api.js";
|
export const matrixSetupWizard = createOptionalChannelSetupWizard({
|
||||||
|
channel: "matrix",
|
||||||
|
label: "Matrix",
|
||||||
|
npmSpec: "@openclaw/matrix",
|
||||||
|
docsPath: "/channels/matrix",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const matrixSetupAdapter = createOptionalChannelSetupAdapter({
|
||||||
|
channel: "matrix",
|
||||||
|
label: "Matrix",
|
||||||
|
npmSpec: "@openclaw/matrix",
|
||||||
|
docsPath: "/channels/matrix",
|
||||||
|
});
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
// Narrow plugin-sdk surface for the bundled msteams plugin.
|
// Narrow plugin-sdk surface for the bundled msteams plugin.
|
||||||
// Keep this list additive and scoped to symbols used under extensions/msteams.
|
// Keep this list additive and scoped to symbols used under extensions/msteams.
|
||||||
|
|
||||||
|
import {
|
||||||
|
createOptionalChannelSetupAdapter,
|
||||||
|
createOptionalChannelSetupWizard,
|
||||||
|
} from "./optional-channel-setup.js";
|
||||||
|
|
||||||
export type { ChunkMode } from "../auto-reply/chunk.js";
|
export type { ChunkMode } from "../auto-reply/chunk.js";
|
||||||
export type { HistoryEntry } from "../auto-reply/reply/history.js";
|
export type { HistoryEntry } from "../auto-reply/reply/history.js";
|
||||||
export {
|
export {
|
||||||
@ -117,5 +122,17 @@ export {
|
|||||||
createDefaultChannelRuntimeState,
|
createDefaultChannelRuntimeState,
|
||||||
} from "./status-helpers.js";
|
} from "./status-helpers.js";
|
||||||
export { normalizeStringEntries } from "../shared/string-normalization.js";
|
export { normalizeStringEntries } from "../shared/string-normalization.js";
|
||||||
export { msteamsSetupWizard } from "../../extensions/msteams/api.js";
|
|
||||||
export { msteamsSetupAdapter } from "../../extensions/msteams/api.js";
|
export const msteamsSetupWizard = createOptionalChannelSetupWizard({
|
||||||
|
channel: "msteams",
|
||||||
|
label: "Microsoft Teams",
|
||||||
|
npmSpec: "@openclaw/msteams",
|
||||||
|
docsPath: "/channels/msteams",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const msteamsSetupAdapter = createOptionalChannelSetupAdapter({
|
||||||
|
channel: "msteams",
|
||||||
|
label: "Microsoft Teams",
|
||||||
|
npmSpec: "@openclaw/msteams",
|
||||||
|
docsPath: "/channels/msteams",
|
||||||
|
});
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
// Narrow plugin-sdk surface for the bundled nostr plugin.
|
// Narrow plugin-sdk surface for the bundled nostr plugin.
|
||||||
// Keep this list additive and scoped to symbols used under extensions/nostr.
|
// Keep this list additive and scoped to symbols used under extensions/nostr.
|
||||||
|
|
||||||
|
import {
|
||||||
|
createOptionalChannelSetupAdapter,
|
||||||
|
createOptionalChannelSetupWizard,
|
||||||
|
} from "./optional-channel-setup.js";
|
||||||
|
|
||||||
export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
||||||
export type { ChannelSetupAdapter } from "../channels/plugins/types.adapters.js";
|
export type { ChannelSetupAdapter } from "../channels/plugins/types.adapters.js";
|
||||||
export { formatPairingApproveHint } from "../channels/plugins/helpers.js";
|
export { formatPairingApproveHint } from "../channels/plugins/helpers.js";
|
||||||
@ -19,4 +24,17 @@ export {
|
|||||||
} from "./status-helpers.js";
|
} from "./status-helpers.js";
|
||||||
export { createFixedWindowRateLimiter } from "./webhook-memory-guards.js";
|
export { createFixedWindowRateLimiter } from "./webhook-memory-guards.js";
|
||||||
export { mapAllowFromEntries } from "./channel-config-helpers.js";
|
export { mapAllowFromEntries } from "./channel-config-helpers.js";
|
||||||
export { nostrSetupAdapter, nostrSetupWizard } from "../../extensions/nostr/setup-api.js";
|
|
||||||
|
export const nostrSetupAdapter = createOptionalChannelSetupAdapter({
|
||||||
|
channel: "nostr",
|
||||||
|
label: "Nostr",
|
||||||
|
npmSpec: "@openclaw/nostr",
|
||||||
|
docsPath: "/channels/nostr",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const nostrSetupWizard = createOptionalChannelSetupWizard({
|
||||||
|
channel: "nostr",
|
||||||
|
label: "Nostr",
|
||||||
|
npmSpec: "@openclaw/nostr",
|
||||||
|
docsPath: "/channels/nostr",
|
||||||
|
});
|
||||||
|
|||||||
56
src/plugin-sdk/optional-channel-setup.ts
Normal file
56
src/plugin-sdk/optional-channel-setup.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import type { ChannelSetupWizard } from "../channels/plugins/setup-wizard.js";
|
||||||
|
import type { ChannelSetupAdapter } from "../channels/plugins/types.adapters.js";
|
||||||
|
import { DEFAULT_ACCOUNT_ID } from "../routing/session-key.js";
|
||||||
|
import { formatDocsLink } from "../terminal/links.js";
|
||||||
|
|
||||||
|
type OptionalChannelSetupParams = {
|
||||||
|
channel: string;
|
||||||
|
label: string;
|
||||||
|
npmSpec?: string;
|
||||||
|
docsPath?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
function buildOptionalChannelSetupMessage(params: OptionalChannelSetupParams): string {
|
||||||
|
const installTarget = params.npmSpec ?? `the ${params.label} plugin`;
|
||||||
|
const message = [`${params.label} setup requires ${installTarget} to be installed.`];
|
||||||
|
if (params.docsPath) {
|
||||||
|
message.push(`Docs: ${formatDocsLink(params.docsPath, params.docsPath.replace(/^\/+/u, ""))}`);
|
||||||
|
}
|
||||||
|
return message.join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createOptionalChannelSetupAdapter(
|
||||||
|
params: OptionalChannelSetupParams,
|
||||||
|
): ChannelSetupAdapter {
|
||||||
|
const message = buildOptionalChannelSetupMessage(params);
|
||||||
|
return {
|
||||||
|
resolveAccountId: ({ accountId }) => accountId ?? DEFAULT_ACCOUNT_ID,
|
||||||
|
applyAccountConfig: () => {
|
||||||
|
throw new Error(message);
|
||||||
|
},
|
||||||
|
validateInput: () => message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createOptionalChannelSetupWizard(
|
||||||
|
params: OptionalChannelSetupParams,
|
||||||
|
): ChannelSetupWizard {
|
||||||
|
const message = buildOptionalChannelSetupMessage(params);
|
||||||
|
return {
|
||||||
|
channel: params.channel,
|
||||||
|
status: {
|
||||||
|
configuredLabel: `${params.label} plugin installed`,
|
||||||
|
unconfiguredLabel: `install ${params.label} plugin`,
|
||||||
|
configuredHint: message,
|
||||||
|
unconfiguredHint: message,
|
||||||
|
unconfiguredScore: 0,
|
||||||
|
resolveConfigured: () => false,
|
||||||
|
resolveStatusLines: () => [message],
|
||||||
|
resolveSelectionHint: () => message,
|
||||||
|
},
|
||||||
|
credentials: [],
|
||||||
|
finalize: async () => {
|
||||||
|
throw new Error(message);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,6 +1,11 @@
|
|||||||
// Narrow plugin-sdk surface for the bundled tlon plugin.
|
// Narrow plugin-sdk surface for the bundled tlon plugin.
|
||||||
// Keep this list additive and scoped to symbols used under extensions/tlon.
|
// Keep this list additive and scoped to symbols used under extensions/tlon.
|
||||||
|
|
||||||
|
import {
|
||||||
|
createOptionalChannelSetupAdapter,
|
||||||
|
createOptionalChannelSetupWizard,
|
||||||
|
} from "./optional-channel-setup.js";
|
||||||
|
|
||||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||||
export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
||||||
export {
|
export {
|
||||||
@ -27,4 +32,17 @@ export type { RuntimeEnv } from "../runtime.js";
|
|||||||
export { formatDocsLink } from "../terminal/links.js";
|
export { formatDocsLink } from "../terminal/links.js";
|
||||||
export type { WizardPrompter } from "../wizard/prompts.js";
|
export type { WizardPrompter } from "../wizard/prompts.js";
|
||||||
export { createLoggerBackedRuntime } from "./runtime.js";
|
export { createLoggerBackedRuntime } from "./runtime.js";
|
||||||
export { tlonSetupAdapter, tlonSetupWizard } from "../../extensions/tlon/setup-api.js";
|
|
||||||
|
export const tlonSetupAdapter = createOptionalChannelSetupAdapter({
|
||||||
|
channel: "tlon",
|
||||||
|
label: "Tlon",
|
||||||
|
npmSpec: "@openclaw/tlon",
|
||||||
|
docsPath: "/channels/tlon",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const tlonSetupWizard = createOptionalChannelSetupWizard({
|
||||||
|
channel: "tlon",
|
||||||
|
label: "Tlon",
|
||||||
|
npmSpec: "@openclaw/tlon",
|
||||||
|
docsPath: "/channels/tlon",
|
||||||
|
});
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
// Narrow plugin-sdk surface for the bundled twitch plugin.
|
// Narrow plugin-sdk surface for the bundled twitch plugin.
|
||||||
// Keep this list additive and scoped to symbols used under extensions/twitch.
|
// Keep this list additive and scoped to symbols used under extensions/twitch.
|
||||||
|
|
||||||
|
import {
|
||||||
|
createOptionalChannelSetupAdapter,
|
||||||
|
createOptionalChannelSetupWizard,
|
||||||
|
} from "./optional-channel-setup.js";
|
||||||
|
|
||||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||||
export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
|
||||||
export type {
|
export type {
|
||||||
@ -33,7 +38,15 @@ export type { OpenClawPluginApi } from "../plugins/types.js";
|
|||||||
export type { RuntimeEnv } from "../runtime.js";
|
export type { RuntimeEnv } from "../runtime.js";
|
||||||
export { formatDocsLink } from "../terminal/links.js";
|
export { formatDocsLink } from "../terminal/links.js";
|
||||||
export type { WizardPrompter } from "../wizard/prompts.js";
|
export type { WizardPrompter } from "../wizard/prompts.js";
|
||||||
export {
|
|
||||||
twitchSetupAdapter,
|
export const twitchSetupAdapter = createOptionalChannelSetupAdapter({
|
||||||
twitchSetupWizard,
|
channel: "twitch",
|
||||||
} from "../../extensions/twitch/src/setup-surface.js";
|
label: "Twitch",
|
||||||
|
npmSpec: "@openclaw/twitch",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const twitchSetupWizard = createOptionalChannelSetupWizard({
|
||||||
|
channel: "twitch",
|
||||||
|
label: "Twitch",
|
||||||
|
npmSpec: "@openclaw/twitch",
|
||||||
|
});
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
// Narrow plugin-sdk surface for the bundled zalouser plugin.
|
// Narrow plugin-sdk surface for the bundled zalouser plugin.
|
||||||
// Keep this list additive and scoped to symbols used under extensions/zalouser.
|
// Keep this list additive and scoped to symbols used under extensions/zalouser.
|
||||||
|
|
||||||
|
import {
|
||||||
|
createOptionalChannelSetupAdapter,
|
||||||
|
createOptionalChannelSetupWizard,
|
||||||
|
} from "./optional-channel-setup.js";
|
||||||
|
|
||||||
export type { ReplyPayload } from "../auto-reply/types.js";
|
export type { ReplyPayload } from "../auto-reply/types.js";
|
||||||
export { mergeAllowlist, summarizeMapping } from "../channels/allowlists/resolve-utils.js";
|
export { mergeAllowlist, summarizeMapping } from "../channels/allowlists/resolve-utils.js";
|
||||||
export { resolveMentionGatingWithBypass } from "../channels/mention-gating.js";
|
export { resolveMentionGatingWithBypass } from "../channels/mention-gating.js";
|
||||||
@ -53,8 +58,6 @@ export type { WizardPrompter } from "../wizard/prompts.js";
|
|||||||
export { formatAllowFromLowercase } from "./allow-from.js";
|
export { formatAllowFromLowercase } from "./allow-from.js";
|
||||||
export { resolveSenderCommandAuthorization } from "./command-auth.js";
|
export { resolveSenderCommandAuthorization } from "./command-auth.js";
|
||||||
export { resolveChannelAccountConfigBasePath } from "./config-paths.js";
|
export { resolveChannelAccountConfigBasePath } from "./config-paths.js";
|
||||||
export { zalouserSetupAdapter } from "../../extensions/zalouser/api.js";
|
|
||||||
export { zalouserSetupWizard } from "../../extensions/zalouser/api.js";
|
|
||||||
export {
|
export {
|
||||||
evaluateGroupRouteAccessForPolicy,
|
evaluateGroupRouteAccessForPolicy,
|
||||||
resolveSenderScopedGroupPolicy,
|
resolveSenderScopedGroupPolicy,
|
||||||
@ -73,3 +76,17 @@ export {
|
|||||||
export { formatResolvedUnresolvedNote } from "./resolution-notes.js";
|
export { formatResolvedUnresolvedNote } from "./resolution-notes.js";
|
||||||
export { buildBaseAccountStatusSnapshot } from "./status-helpers.js";
|
export { buildBaseAccountStatusSnapshot } from "./status-helpers.js";
|
||||||
export { chunkTextForOutbound } from "./text-chunking.js";
|
export { chunkTextForOutbound } from "./text-chunking.js";
|
||||||
|
|
||||||
|
export const zalouserSetupAdapter = createOptionalChannelSetupAdapter({
|
||||||
|
channel: "zalouser",
|
||||||
|
label: "Zalo Personal",
|
||||||
|
npmSpec: "@openclaw/zalouser",
|
||||||
|
docsPath: "/channels/zalouser",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const zalouserSetupWizard = createOptionalChannelSetupWizard({
|
||||||
|
channel: "zalouser",
|
||||||
|
label: "Zalo Personal",
|
||||||
|
npmSpec: "@openclaw/zalouser",
|
||||||
|
docsPath: "/channels/zalouser",
|
||||||
|
});
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { defineConfig, type UserConfig } from "tsdown";
|
import { defineConfig, type UserConfig } from "tsdown";
|
||||||
|
import { shouldBuildBundledCluster } from "./scripts/lib/optional-bundled-clusters.mjs";
|
||||||
import { buildPluginSdkEntrySources } from "./scripts/lib/plugin-sdk-entries.mjs";
|
import { buildPluginSdkEntrySources } from "./scripts/lib/plugin-sdk-entries.mjs";
|
||||||
|
|
||||||
type InputOptionsFactory = Extract<NonNullable<UserConfig["inputOptions"]>, Function>;
|
type InputOptionsFactory = Extract<NonNullable<UserConfig["inputOptions"]>, Function>;
|
||||||
@ -81,6 +82,9 @@ function listBundledPluginBuildEntries(): Record<string, string> {
|
|||||||
if (!dirent.isDirectory()) {
|
if (!dirent.isDirectory()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!shouldBuildBundledCluster(dirent.name, process.env)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const pluginDir = path.join(extensionsRoot, dirent.name);
|
const pluginDir = path.join(extensionsRoot, dirent.name);
|
||||||
const manifestPath = path.join(pluginDir, "openclaw.plugin.json");
|
const manifestPath = path.join(pluginDir, "openclaw.plugin.json");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user