mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:20:43 +00:00
feat: add setup auth evidence metadata
This commit is contained in:
@@ -1129,6 +1129,17 @@ describe("loadPluginManifestRegistry", () => {
|
||||
id: "openai",
|
||||
authMethods: ["api-key"],
|
||||
envVars: ["OPENAI_API_KEY"],
|
||||
authEvidence: [
|
||||
{
|
||||
type: "local-file-with-env",
|
||||
fileEnvVar: "OPENAI_CREDENTIALS_FILE",
|
||||
fallbackPaths: ["${HOME}/.config/openai/credentials.json"],
|
||||
requiresAnyEnv: ["OPENAI_PROJECT", "OPENAI_ORG"],
|
||||
requiresAllEnv: ["OPENAI_REGION"],
|
||||
credentialMarker: "openai-local-credentials",
|
||||
source: "openai local credentials",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
cliBackends: ["openai-cli"],
|
||||
@@ -1158,6 +1169,17 @@ describe("loadPluginManifestRegistry", () => {
|
||||
id: "openai",
|
||||
authMethods: ["api-key"],
|
||||
envVars: ["OPENAI_API_KEY"],
|
||||
authEvidence: [
|
||||
{
|
||||
type: "local-file-with-env",
|
||||
fileEnvVar: "OPENAI_CREDENTIALS_FILE",
|
||||
fallbackPaths: ["${HOME}/.config/openai/credentials.json"],
|
||||
requiresAnyEnv: ["OPENAI_PROJECT", "OPENAI_ORG"],
|
||||
requiresAllEnv: ["OPENAI_REGION"],
|
||||
credentialMarker: "openai-local-credentials",
|
||||
source: "openai local credentials",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
cliBackends: ["openai-cli"],
|
||||
|
||||
@@ -188,6 +188,29 @@ export type PluginManifestSetupProvider = {
|
||||
authMethods?: string[];
|
||||
/** Environment variables that can satisfy setup without runtime loading. */
|
||||
envVars?: string[];
|
||||
/**
|
||||
* Cheap local evidence that a provider can authenticate without loading
|
||||
* runtime code. Evidence checks must not read secrets, shell out, or call
|
||||
* provider APIs.
|
||||
*/
|
||||
authEvidence?: PluginManifestSetupProviderAuthEvidence[];
|
||||
};
|
||||
|
||||
export type PluginManifestSetupProviderAuthEvidence = {
|
||||
/** Generic local file evidence gated by required environment metadata. */
|
||||
type: "local-file-with-env";
|
||||
/** Optional env var containing an explicit credential file path. */
|
||||
fileEnvVar?: string;
|
||||
/** Optional fallback credential file paths. Supports `${HOME}` only. */
|
||||
fallbackPaths?: string[];
|
||||
/** At least one of these env vars must be non-empty when provided. */
|
||||
requiresAnyEnv?: string[];
|
||||
/** Every env var listed here must be non-empty when provided. */
|
||||
requiresAllEnv?: string[];
|
||||
/** Non-secret marker returned when this evidence is present. */
|
||||
credentialMarker: string;
|
||||
/** Human-readable auth source label. */
|
||||
source?: string;
|
||||
};
|
||||
|
||||
export type PluginManifestSetup = {
|
||||
@@ -982,10 +1005,48 @@ function normalizeManifestSetupProviders(
|
||||
}
|
||||
const authMethods = normalizeTrimmedStringList(entry.authMethods);
|
||||
const envVars = normalizeTrimmedStringList(entry.envVars);
|
||||
const authEvidence = normalizeManifestSetupProviderAuthEvidence(entry.authEvidence);
|
||||
normalized.push({
|
||||
id,
|
||||
...(authMethods.length > 0 ? { authMethods } : {}),
|
||||
...(envVars.length > 0 ? { envVars } : {}),
|
||||
...(authEvidence ? { authEvidence } : {}),
|
||||
});
|
||||
}
|
||||
return normalized.length > 0 ? normalized : undefined;
|
||||
}
|
||||
|
||||
function normalizeManifestSetupProviderAuthEvidence(
|
||||
value: unknown,
|
||||
): PluginManifestSetupProviderAuthEvidence[] | undefined {
|
||||
if (!Array.isArray(value)) {
|
||||
return undefined;
|
||||
}
|
||||
const normalized: PluginManifestSetupProviderAuthEvidence[] = [];
|
||||
for (const entry of value) {
|
||||
if (!isRecord(entry) || entry.type !== "local-file-with-env") {
|
||||
continue;
|
||||
}
|
||||
const credentialMarker = normalizeOptionalString(entry.credentialMarker);
|
||||
if (!credentialMarker) {
|
||||
continue;
|
||||
}
|
||||
const fileEnvVar = normalizeOptionalString(entry.fileEnvVar);
|
||||
const fallbackPaths = normalizeTrimmedStringList(entry.fallbackPaths);
|
||||
if (!fileEnvVar && fallbackPaths.length === 0) {
|
||||
continue;
|
||||
}
|
||||
const requiresAnyEnv = normalizeTrimmedStringList(entry.requiresAnyEnv);
|
||||
const requiresAllEnv = normalizeTrimmedStringList(entry.requiresAllEnv);
|
||||
const source = normalizeOptionalString(entry.source);
|
||||
normalized.push({
|
||||
type: "local-file-with-env",
|
||||
...(fileEnvVar ? { fileEnvVar } : {}),
|
||||
...(fallbackPaths.length > 0 ? { fallbackPaths } : {}),
|
||||
...(requiresAnyEnv.length > 0 ? { requiresAnyEnv } : {}),
|
||||
...(requiresAllEnv.length > 0 ? { requiresAllEnv } : {}),
|
||||
credentialMarker,
|
||||
...(source ? { source } : {}),
|
||||
});
|
||||
}
|
||||
return normalized.length > 0 ? normalized : undefined;
|
||||
|
||||
Reference in New Issue
Block a user