mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-05 07:10:23 +00:00
fix: unify live model auth gating
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { isLiveTestEnabled } from "./live-test-helpers.js";
|
||||
import { isLiveProfileKeyModeEnabled, isLiveTestEnabled } from "./live-test-helpers.js";
|
||||
|
||||
describe("isLiveTestEnabled", () => {
|
||||
it("treats LIVE and OPENCLAW_LIVE_TEST as shared live gates", () => {
|
||||
@@ -13,3 +13,11 @@ describe("isLiveTestEnabled", () => {
|
||||
expect(isLiveTestEnabled(["MINIMAX_LIVE_TEST"], { MINIMAX_LIVE_TEST: "0" })).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isLiveProfileKeyModeEnabled", () => {
|
||||
it("only enables profile-key mode for the dedicated flag", () => {
|
||||
expect(isLiveProfileKeyModeEnabled({ OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS: "1" })).toBe(true);
|
||||
expect(isLiveProfileKeyModeEnabled({ OPENCLAW_LIVE_TEST: "1" })).toBe(false);
|
||||
expect(isLiveProfileKeyModeEnabled({ LIVE: "1" })).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,6 +11,10 @@ export function isLiveTestEnabled(
|
||||
);
|
||||
}
|
||||
|
||||
export function isLiveProfileKeyModeEnabled(env: NodeJS.ProcessEnv = process.env): boolean {
|
||||
return isTruthyEnvValue(env.OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS);
|
||||
}
|
||||
|
||||
export function createSingleUserPromptMessage(content = LIVE_OK_PROMPT) {
|
||||
return [
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
isAnthropicRateLimitError,
|
||||
} from "./live-auth-keys.js";
|
||||
import { isModernModelRef } from "./live-model-filter.js";
|
||||
import { isLiveTestEnabled } from "./live-test-helpers.js";
|
||||
import { isLiveProfileKeyModeEnabled, isLiveTestEnabled } from "./live-test-helpers.js";
|
||||
import { getApiKeyForModel, requireApiKey } from "./model-auth.js";
|
||||
import { shouldSuppressBuiltInModel } from "./model-suppression.js";
|
||||
import { ensureOpenClawModelsJson } from "./models-config.js";
|
||||
@@ -18,7 +18,7 @@ import { discoverAuthStorage, discoverModels } from "./pi-model-discovery.js";
|
||||
|
||||
const LIVE = isLiveTestEnabled();
|
||||
const DIRECT_ENABLED = Boolean(process.env.OPENCLAW_LIVE_MODELS?.trim());
|
||||
const REQUIRE_PROFILE_KEYS = isLiveTestEnabled(["OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS"]);
|
||||
const REQUIRE_PROFILE_KEYS = isLiveProfileKeyModeEnabled();
|
||||
const LIVE_HEARTBEAT_MS = Math.max(1_000, toInt(process.env.OPENCLAW_LIVE_HEARTBEAT_MS, 30_000));
|
||||
|
||||
const describeLive = LIVE ? describe : describe.skip;
|
||||
|
||||
@@ -149,4 +149,31 @@ describe("discoverAuthStorage", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("includes env-backed provider auth when no auth profile exists", async () => {
|
||||
await withAgentDir(async (agentDir) => {
|
||||
const previous = process.env.MISTRAL_API_KEY;
|
||||
process.env.MISTRAL_API_KEY = "mistral-env-test-key";
|
||||
try {
|
||||
saveAuthProfileStore(
|
||||
{
|
||||
version: 1,
|
||||
profiles: {},
|
||||
},
|
||||
agentDir,
|
||||
);
|
||||
|
||||
const authStorage = discoverAuthStorage(agentDir);
|
||||
|
||||
expect(authStorage.hasAuth("mistral")).toBe(true);
|
||||
await expect(authStorage.getApiKey("mistral")).resolves.toBe("mistral-env-test-key");
|
||||
} finally {
|
||||
if (previous === undefined) {
|
||||
delete process.env.MISTRAL_API_KEY;
|
||||
} else {
|
||||
process.env.MISTRAL_API_KEY = previous;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,6 +6,8 @@ import type {
|
||||
ModelRegistry as PiModelRegistry,
|
||||
} from "@mariozechner/pi-coding-agent";
|
||||
import { ensureAuthProfileStore } from "./auth-profiles.js";
|
||||
import { PROVIDER_ENV_API_KEY_CANDIDATES } from "./model-auth-env-vars.js";
|
||||
import { resolveEnvApiKey } from "./model-auth-env.js";
|
||||
import { resolvePiCredentialMapFromStore, type PiCredentialMap } from "./pi-auth-credentials.js";
|
||||
|
||||
const PiAuthStorageClass = PiCodingAgent.AuthStorage;
|
||||
@@ -136,7 +138,24 @@ function createAuthStorage(AuthStorageLike: unknown, path: string, creds: PiCred
|
||||
|
||||
function resolvePiCredentials(agentDir: string): PiCredentialMap {
|
||||
const store = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false });
|
||||
return resolvePiCredentialMapFromStore(store);
|
||||
const credentials = resolvePiCredentialMapFromStore(store);
|
||||
// pi-coding-agent hides providers from its registry when auth storage lacks
|
||||
// a matching credential entry. Mirror env-backed provider auth here so
|
||||
// live/model discovery sees the same providers runtime auth can use.
|
||||
for (const provider of Object.keys(PROVIDER_ENV_API_KEY_CANDIDATES)) {
|
||||
if (credentials[provider]) {
|
||||
continue;
|
||||
}
|
||||
const resolved = resolveEnvApiKey(provider);
|
||||
if (!resolved?.apiKey) {
|
||||
continue;
|
||||
}
|
||||
credentials[provider] = {
|
||||
type: "api_key",
|
||||
key: resolved.apiKey,
|
||||
};
|
||||
}
|
||||
return credentials;
|
||||
}
|
||||
|
||||
// Compatibility helpers for pi-coding-agent 0.50+ (discover* helpers removed).
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
} from "../agents/live-auth-keys.js";
|
||||
import { isModelNotFoundErrorMessage } from "../agents/live-model-errors.js";
|
||||
import { isModernModelRef } from "../agents/live-model-filter.js";
|
||||
import { isLiveTestEnabled } from "../agents/live-test-helpers.js";
|
||||
import { isLiveProfileKeyModeEnabled, isLiveTestEnabled } from "../agents/live-test-helpers.js";
|
||||
import { getApiKeyForModel } from "../agents/model-auth.js";
|
||||
import { normalizeGoogleModelId } from "../agents/model-id-normalization.js";
|
||||
import { shouldSuppressBuiltInModel } from "../agents/model-suppression.js";
|
||||
@@ -44,7 +44,7 @@ import { startGatewayServer } from "./server.js";
|
||||
import { loadSessionEntry, readSessionMessages } from "./session-utils.js";
|
||||
|
||||
const ZAI_FALLBACK = isTruthyEnvValue(process.env.OPENCLAW_LIVE_GATEWAY_ZAI_FALLBACK);
|
||||
const REQUIRE_PROFILE_KEYS = isTruthyEnvValue(process.env.OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS);
|
||||
const REQUIRE_PROFILE_KEYS = isLiveProfileKeyModeEnabled();
|
||||
const PROVIDERS = parseFilter(process.env.OPENCLAW_LIVE_GATEWAY_PROVIDERS);
|
||||
const THINKING_LEVEL = "high";
|
||||
const THINKING_TAG_RE = /<\s*\/?\s*(?:think(?:ing)?|thought|antthinking)\s*>/i;
|
||||
|
||||
Reference in New Issue
Block a user