mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 21:07:01 -06:00
fix(anthropic): forward selected profiles to Claude CLI (#112458)
* fix(anthropic): forward Claude CLI auth profiles * fix(system-agent): inject CLI auth route stores * fix(claude-cli): pass profile credentials by descriptor * fix(anthropic): repair selected profile CI coverage * fix(anthropic): preserve profile owner validation * test(system-agent): preserve selected profile fixtures * test(system-agent): narrow selected profile fixture * test(system-agent): resolve profile store merge * fix(anthropic): forward profiles to node Claude runs * fix(system-agent): reconcile profile route projection * test(system-agent): thread profile store through projection * fix(anthropic): make selected profile authoritative * fix(system-agent): type auth setup failures * fix(system-agent): type setup auth failures * style: format Claude profile maintenance * fix(anthropic): keep gateway credentials off nodes * fix(anthropic): clear ambient auth for selected profiles * fix(anthropic): secure paired-node Claude auth * fix(node-host): type Claude fd spawn streams * style(node-host): satisfy Claude spawn lint * fix(process): capture exit before secret delivery * fix(anthropic): preserve node-native Claude auth
This commit is contained in:
@@ -517,14 +517,22 @@ describe("runCliAgent spawn path", () => {
|
||||
],
|
||||
forkArg: "--fork-session",
|
||||
liveSession: "claude-stdio",
|
||||
env: { ANTHROPIC_API_KEY: "configured-backend-key" },
|
||||
clearEnv: ["ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN"],
|
||||
systemPromptWhen: "always",
|
||||
},
|
||||
preparedEnv: { CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR: "3" },
|
||||
resolveExecutionArgs: (execution) => {
|
||||
toolAvailability = execution.toolAvailability;
|
||||
return [...execution.baseArgs];
|
||||
},
|
||||
cliToolAvailability: { native: [], mcp: ["mcp__openclaw__message"] },
|
||||
});
|
||||
context.preparedBackend.secretInput = {
|
||||
fd: 3,
|
||||
fingerprint: "selected-node-token-fingerprint",
|
||||
createData: () => Buffer.from("selected-node-token"),
|
||||
};
|
||||
context.openClawHistoryPrompt = "gateway transcript reseed";
|
||||
context.claudeSkillsPluginArgs = ["--plugin-dir", "/tmp/gateway-skills"];
|
||||
context.params.forkCliSessionOnResume = true;
|
||||
@@ -546,8 +554,14 @@ describe("runCliAgent spawn path", () => {
|
||||
stdin: "current turn",
|
||||
argv: expect.arrayContaining(["--resume", "source-node-session", "--fork-session"]),
|
||||
systemPrompt: "You are a helpful assistant.",
|
||||
env: { CLAUDE_CODE_OAUTH_TOKEN: "selected-node-token" },
|
||||
clearEnv: ["ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN"],
|
||||
}),
|
||||
);
|
||||
expect(invokeNode.mock.calls[0]?.[0].env).not.toHaveProperty("ANTHROPIC_API_KEY");
|
||||
expect(invokeNode.mock.calls[0]?.[0].env).not.toHaveProperty(
|
||||
"CLAUDE_CODE_SUBPROCESS_ENV_SCRUB",
|
||||
);
|
||||
const argv = invokeNode.mock.calls[0]?.[0].argv ?? [];
|
||||
expect(argv).not.toContain("--mcp-config");
|
||||
expect(argv).not.toContain("--permission-mode");
|
||||
@@ -591,6 +605,7 @@ describe("runCliAgent spawn path", () => {
|
||||
resumeArgs: ["-p", "--output-format", "stream-json", "--resume", "{sessionId}"],
|
||||
forkArg: "--fork-session",
|
||||
liveSession: "claude-stdio",
|
||||
env: { ANTHROPIC_API_KEY: "gateway-backend-key" },
|
||||
systemPromptWhen: "always",
|
||||
},
|
||||
});
|
||||
@@ -598,6 +613,8 @@ describe("runCliAgent spawn path", () => {
|
||||
await expect(executePreparedCliRun(context, undefined)).rejects.toThrow(
|
||||
/truncated the Claude CLI stream before the terminal result/,
|
||||
);
|
||||
expect(invokeNode.mock.calls[0]?.[0].env).toBeUndefined();
|
||||
expect(invokeNode.mock.calls[0]?.[0].clearEnv).toBeUndefined();
|
||||
});
|
||||
|
||||
it("cancels a node-placed Claude process when the run aborts", async () => {
|
||||
@@ -5851,6 +5868,34 @@ ${JSON.stringify({
|
||||
expect(input.env?.SAFE_OVERRIDE).toBe("from-override");
|
||||
});
|
||||
|
||||
it("keeps selected Claude auth authoritative over ambient and configured credentials", async () => {
|
||||
vi.stubEnv("OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV", '["ANTHROPIC_API_KEY"]');
|
||||
vi.stubEnv("ANTHROPIC_API_KEY", "ambient-api-key");
|
||||
mockSuccessfulClaudeJsonlRun();
|
||||
|
||||
await executePreparedCliRun(
|
||||
buildPreparedCliRunContext({
|
||||
provider: "claude-cli",
|
||||
model: "claude-sonnet-4-6",
|
||||
runId: "run-claude-selected-auth-authority",
|
||||
preparedEnv: {
|
||||
CLAUDE_CODE_OAUTH_TOKEN: "selected-oauth-token",
|
||||
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB: "1",
|
||||
},
|
||||
backend: {
|
||||
env: { ANTHROPIC_API_KEY: "configured-api-key" },
|
||||
clearEnv: ["ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN"],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const input = mockCallArg(supervisorSpawnMock) as {
|
||||
env?: Record<string, string | undefined>;
|
||||
};
|
||||
expect(input.env?.ANTHROPIC_API_KEY).toBeUndefined();
|
||||
expect(input.env?.CLAUDE_CODE_OAUTH_TOKEN).toBe("selected-oauth-token");
|
||||
});
|
||||
|
||||
it("clears claude-cli provider-routing, auth, telemetry, compaction, and host-managed env", async () => {
|
||||
vi.stubEnv("ANTHROPIC_BASE_URL", "https://proxy.example.com/v1");
|
||||
vi.stubEnv("ANTHROPIC_API_TOKEN", "env-api-token");
|
||||
|
||||
Reference in New Issue
Block a user