mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:30:42 +00:00
fix: use declarative channel configured-state probes
This commit is contained in:
@@ -44,6 +44,11 @@
|
||||
"nativeSkillsAutoEnabled": true
|
||||
},
|
||||
"configuredState": {
|
||||
"env": {
|
||||
"allOf": [
|
||||
"DISCORD_BOT_TOKEN"
|
||||
]
|
||||
},
|
||||
"specifier": "./configured-state",
|
||||
"exportName": "hasDiscordConfiguredState"
|
||||
}
|
||||
|
||||
@@ -27,6 +27,12 @@
|
||||
],
|
||||
"systemImage": "network",
|
||||
"configuredState": {
|
||||
"env": {
|
||||
"allOf": [
|
||||
"IRC_HOST",
|
||||
"IRC_NICK"
|
||||
]
|
||||
},
|
||||
"specifier": "./configured-state",
|
||||
"exportName": "hasIrcConfiguredState"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,13 @@
|
||||
"nativeSkillsAutoEnabled": false
|
||||
},
|
||||
"configuredState": {
|
||||
"env": {
|
||||
"anyOf": [
|
||||
"SLACK_APP_TOKEN",
|
||||
"SLACK_BOT_TOKEN",
|
||||
"SLACK_USER_TOKEN"
|
||||
]
|
||||
},
|
||||
"specifier": "./configured-state",
|
||||
"exportName": "hasSlackConfiguredState"
|
||||
}
|
||||
|
||||
@@ -43,6 +43,11 @@
|
||||
"nativeSkillsAutoEnabled": true
|
||||
},
|
||||
"configuredState": {
|
||||
"env": {
|
||||
"allOf": [
|
||||
"TELEGRAM_BOT_TOKEN"
|
||||
]
|
||||
},
|
||||
"specifier": "./configured-state",
|
||||
"exportName": "hasTelegramConfiguredState"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { createRequire } from "node:module";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
hasBundledChannelConfiguredState,
|
||||
listBundledChannelIdsWithConfiguredState,
|
||||
} from "./configured-state.js";
|
||||
|
||||
const nodeRequire = createRequire(import.meta.url);
|
||||
|
||||
describe("bundled channel configured-state metadata", () => {
|
||||
it("lists the shipped metadata-first configured-state channels", () => {
|
||||
expect(listBundledChannelIdsWithConfiguredState()).toEqual(
|
||||
@@ -41,4 +44,22 @@ describe("bundled channel configured-state metadata", () => {
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("uses declarative env metadata without a TypeScript source require hook", () => {
|
||||
const previousTsHook = nodeRequire.extensions[".ts"];
|
||||
delete nodeRequire.extensions[".ts"];
|
||||
try {
|
||||
expect(
|
||||
hasBundledChannelConfiguredState({
|
||||
channelId: "discord",
|
||||
cfg: {},
|
||||
env: { DISCORD_BOT_TOKEN: "token" },
|
||||
}),
|
||||
).toBe(true);
|
||||
} finally {
|
||||
if (previousTsHook) {
|
||||
nodeRequire.extensions[".ts"] = previousTsHook;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,12 +16,29 @@ type ChannelPackageStateChecker = (params: {
|
||||
type ChannelPackageStateMetadata = {
|
||||
specifier?: string;
|
||||
exportName?: string;
|
||||
env?: {
|
||||
allOf?: readonly string[];
|
||||
anyOf?: readonly string[];
|
||||
};
|
||||
};
|
||||
|
||||
export type ChannelPackageStateMetadataKey = "configuredState" | "persistedAuthState";
|
||||
|
||||
const log = createSubsystemLogger("channels");
|
||||
|
||||
function normalizeStringList(value: unknown): string[] {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
return value
|
||||
.map((entry) => normalizeOptionalString(entry))
|
||||
.filter((entry): entry is string => Boolean(entry));
|
||||
}
|
||||
|
||||
function hasNonEmptyEnvValue(env: NodeJS.ProcessEnv | undefined, key: string): boolean {
|
||||
return typeof env?.[key] === "string" && env[key].trim().length > 0;
|
||||
}
|
||||
|
||||
function resolveChannelPackageStateMetadata(
|
||||
entry: PluginChannelCatalogEntry,
|
||||
metadataKey: ChannelPackageStateMetadataKey,
|
||||
@@ -32,10 +49,17 @@ function resolveChannelPackageStateMetadata(
|
||||
}
|
||||
const specifier = normalizeOptionalString(metadata.specifier) ?? "";
|
||||
const exportName = normalizeOptionalString(metadata.exportName) ?? "";
|
||||
if (!specifier || !exportName) {
|
||||
const allOf = normalizeStringList(metadata.env?.allOf);
|
||||
const anyOf = normalizeStringList(metadata.env?.anyOf);
|
||||
const env = allOf.length > 0 || anyOf.length > 0 ? { allOf, anyOf } : undefined;
|
||||
if ((!specifier || !exportName) && !env) {
|
||||
return null;
|
||||
}
|
||||
return { specifier, exportName };
|
||||
return {
|
||||
...(specifier ? { specifier } : {}),
|
||||
...(exportName ? { exportName } : {}),
|
||||
...(env ? { env } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
function listChannelPackageStateCatalog(
|
||||
@@ -55,6 +79,17 @@ function resolveChannelPackageStateChecker(params: {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (metadata.env) {
|
||||
return ({ env }) => {
|
||||
const allOf = metadata.env?.allOf ?? [];
|
||||
const anyOf = metadata.env?.anyOf ?? [];
|
||||
return (
|
||||
(allOf.length === 0 || allOf.every((key) => hasNonEmptyEnvValue(env, key))) &&
|
||||
(anyOf.length === 0 || anyOf.some((key) => hasNonEmptyEnvValue(env, key)))
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const moduleExport = loadChannelPluginModule({
|
||||
modulePath: resolveExistingPluginModulePath(params.entry.rootDir, metadata.specifier!),
|
||||
|
||||
@@ -325,6 +325,9 @@ describe("bundled plugin metadata", () => {
|
||||
{
|
||||
dir: "discord",
|
||||
configuredState: {
|
||||
env: {
|
||||
allOf: ["DISCORD_BOT_TOKEN"],
|
||||
},
|
||||
specifier: "./configured-state",
|
||||
exportName: "hasDiscordConfiguredState",
|
||||
},
|
||||
@@ -332,6 +335,9 @@ describe("bundled plugin metadata", () => {
|
||||
{
|
||||
dir: "irc",
|
||||
configuredState: {
|
||||
env: {
|
||||
allOf: ["IRC_HOST", "IRC_NICK"],
|
||||
},
|
||||
specifier: "./configured-state",
|
||||
exportName: "hasIrcConfiguredState",
|
||||
},
|
||||
@@ -339,6 +345,9 @@ describe("bundled plugin metadata", () => {
|
||||
{
|
||||
dir: "slack",
|
||||
configuredState: {
|
||||
env: {
|
||||
anyOf: ["SLACK_APP_TOKEN", "SLACK_BOT_TOKEN", "SLACK_USER_TOKEN"],
|
||||
},
|
||||
specifier: "./configured-state",
|
||||
exportName: "hasSlackConfiguredState",
|
||||
},
|
||||
@@ -346,6 +355,9 @@ describe("bundled plugin metadata", () => {
|
||||
{
|
||||
dir: "telegram",
|
||||
configuredState: {
|
||||
env: {
|
||||
allOf: ["TELEGRAM_BOT_TOKEN"],
|
||||
},
|
||||
specifier: "./configured-state",
|
||||
exportName: "hasTelegramConfiguredState",
|
||||
},
|
||||
|
||||
@@ -1481,6 +1481,10 @@ export type PluginPackageChannel = {
|
||||
configuredState?: {
|
||||
specifier?: string;
|
||||
exportName?: string;
|
||||
env?: {
|
||||
allOf?: readonly string[];
|
||||
anyOf?: readonly string[];
|
||||
};
|
||||
};
|
||||
persistedAuthState?: {
|
||||
specifier?: string;
|
||||
|
||||
Reference in New Issue
Block a user