mirror of https://github.com/openclaw/openclaw.git
Secrets: honor caller env during runtime validation
This commit is contained in:
parent
e5282e6bda
commit
467dae53cf
|
|
@ -3,14 +3,13 @@ import { resolveStateDir } from "../config/paths.js";
|
|||
import { DEFAULT_AGENT_ID } from "../routing/session-key.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
|
||||
export function resolveOpenClawAgentDir(): string {
|
||||
const override =
|
||||
process.env.OPENCLAW_AGENT_DIR?.trim() || process.env.PI_CODING_AGENT_DIR?.trim();
|
||||
export function resolveOpenClawAgentDir(env: NodeJS.ProcessEnv = process.env): string {
|
||||
const override = env.OPENCLAW_AGENT_DIR?.trim() || env.PI_CODING_AGENT_DIR?.trim();
|
||||
if (override) {
|
||||
return resolveUserPath(override);
|
||||
return resolveUserPath(override, env);
|
||||
}
|
||||
const defaultAgentDir = path.join(resolveStateDir(), "agents", DEFAULT_AGENT_ID, "agent");
|
||||
return resolveUserPath(defaultAgentDir);
|
||||
const defaultAgentDir = path.join(resolveStateDir(env), "agents", DEFAULT_AGENT_ID, "agent");
|
||||
return resolveUserPath(defaultAgentDir, env);
|
||||
}
|
||||
|
||||
export function ensureOpenClawAgentEnv(): string {
|
||||
|
|
|
|||
|
|
@ -327,12 +327,16 @@ export function resolveAgentIdByWorkspacePath(
|
|||
return resolveAgentIdsByWorkspacePath(cfg, workspacePath)[0];
|
||||
}
|
||||
|
||||
export function resolveAgentDir(cfg: OpenClawConfig, agentId: string) {
|
||||
export function resolveAgentDir(
|
||||
cfg: OpenClawConfig,
|
||||
agentId: string,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
) {
|
||||
const id = normalizeAgentId(agentId);
|
||||
const configured = resolveAgentConfig(cfg, id)?.agentDir?.trim();
|
||||
if (configured) {
|
||||
return resolveUserPath(configured);
|
||||
return resolveUserPath(configured, env);
|
||||
}
|
||||
const root = resolveStateDir(process.env);
|
||||
const root = resolveStateDir(env);
|
||||
return path.join(root, "agents", id, "agent");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import path from "node:path";
|
|||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { runSecretsApply } from "./apply.js";
|
||||
import type { SecretsApplyPlan } from "./plan.js";
|
||||
import { clearSecretsRuntimeSnapshot } from "./runtime.js";
|
||||
|
||||
const OPENAI_API_KEY_ENV_REF = {
|
||||
source: "env",
|
||||
|
|
@ -173,11 +174,13 @@ describe("secrets apply", () => {
|
|||
let fixture: ApplyFixture;
|
||||
|
||||
beforeEach(async () => {
|
||||
clearSecretsRuntimeSnapshot();
|
||||
fixture = await createApplyFixture();
|
||||
await seedDefaultApplyFixture(fixture);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
clearSecretsRuntimeSnapshot();
|
||||
await fs.rm(fixture.rootDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import * as webSearchProviders from "../plugins/web-search-providers.js";
|
||||
import * as secretResolve from "./resolve.js";
|
||||
import { createResolverContext } from "./runtime-shared.js";
|
||||
import { resolveRuntimeWebTools } from "./runtime-web-tools.js";
|
||||
|
|
@ -88,6 +89,32 @@ describe("runtime web tools resolution", () => {
|
|||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("skips loading web search providers when search config is absent", async () => {
|
||||
const providerSpy = vi.spyOn(webSearchProviders, "resolvePluginWebSearchProviders");
|
||||
|
||||
const { metadata } = await runRuntimeWebTools({
|
||||
config: asConfig({
|
||||
tools: {
|
||||
web: {
|
||||
fetch: {
|
||||
firecrawl: {
|
||||
apiKey: { source: "env", provider: "default", id: "FIRECRAWL_API_KEY_REF" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
env: {
|
||||
FIRECRAWL_API_KEY: "firecrawl-runtime-key", // pragma: allowlist secret
|
||||
},
|
||||
});
|
||||
|
||||
expect(providerSpy).not.toHaveBeenCalled();
|
||||
expect(metadata.search.providerSource).toBe("none");
|
||||
expect(metadata.fetch.firecrawl.active).toBe(true);
|
||||
expect(metadata.fetch.firecrawl.apiKeySource).toBe("env");
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
provider: "brave" as const,
|
||||
|
|
|
|||
|
|
@ -315,11 +315,13 @@ export async function resolveRuntimeWebTools(params: {
|
|||
const tools = isRecord(params.sourceConfig.tools) ? params.sourceConfig.tools : undefined;
|
||||
const web = isRecord(tools?.web) ? tools.web : undefined;
|
||||
const search = isRecord(web?.search) ? web.search : undefined;
|
||||
const providers = resolvePluginWebSearchProviders({
|
||||
config: params.sourceConfig,
|
||||
env: params.context.env,
|
||||
bundledAllowlistCompat: true,
|
||||
});
|
||||
const providers = search
|
||||
? resolvePluginWebSearchProviders({
|
||||
config: params.sourceConfig,
|
||||
env: params.context.env,
|
||||
bundledAllowlistCompat: true,
|
||||
})
|
||||
: [];
|
||||
|
||||
const searchMetadata: RuntimeWebSearchMetadata = {
|
||||
providerSource: "none",
|
||||
|
|
|
|||
|
|
@ -79,11 +79,14 @@ function clearActiveSecretsRuntimeState(): void {
|
|||
clearRuntimeAuthProfileStoreSnapshots();
|
||||
}
|
||||
|
||||
function collectCandidateAgentDirs(config: OpenClawConfig): string[] {
|
||||
function collectCandidateAgentDirs(
|
||||
config: OpenClawConfig,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): string[] {
|
||||
const dirs = new Set<string>();
|
||||
dirs.add(resolveUserPath(resolveOpenClawAgentDir()));
|
||||
dirs.add(resolveUserPath(resolveOpenClawAgentDir(env), env));
|
||||
for (const agentId of listAgentIds(config)) {
|
||||
dirs.add(resolveUserPath(resolveAgentDir(config, agentId)));
|
||||
dirs.add(resolveUserPath(resolveAgentDir(config, agentId, env), env));
|
||||
}
|
||||
return [...dirs];
|
||||
}
|
||||
|
|
@ -92,7 +95,7 @@ function resolveRefreshAgentDirs(
|
|||
config: OpenClawConfig,
|
||||
context: SecretsRuntimeRefreshContext,
|
||||
): string[] {
|
||||
const configDerived = collectCandidateAgentDirs(config);
|
||||
const configDerived = collectCandidateAgentDirs(config, context.env);
|
||||
if (!context.explicitAgentDirs || context.explicitAgentDirs.length === 0) {
|
||||
return configDerived;
|
||||
}
|
||||
|
|
@ -119,8 +122,12 @@ export async function prepareSecretsRuntimeSnapshot(params: {
|
|||
|
||||
const loadAuthStore = params.loadAuthStore ?? loadAuthProfileStoreForSecretsRuntime;
|
||||
const candidateDirs = params.agentDirs?.length
|
||||
? [...new Set(params.agentDirs.map((entry) => resolveUserPath(entry)))]
|
||||
: collectCandidateAgentDirs(resolvedConfig);
|
||||
? [
|
||||
...new Set(
|
||||
params.agentDirs.map((entry) => resolveUserPath(entry, params.env ?? process.env)),
|
||||
),
|
||||
]
|
||||
: collectCandidateAgentDirs(resolvedConfig, params.env ?? process.env);
|
||||
|
||||
const authStores: Array<{ agentDir: string; store: AuthProfileStore }> = [];
|
||||
for (const agentDir of candidateDirs) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue