
























@@ -10,6 +10,15 @@ import { requestHeartbeatNow } from "../../infra/heartbeat-wake.js";
1010import * as execModule from "../../process/exec.js";
1111import { onSessionTranscriptUpdate } from "../../sessions/transcript-events.js";
1212import { VERSION } from "../../version.js";
13+14+const runtimeModelAuthMocks = vi.hoisted(() => ({
15+getApiKeyForModel: vi.fn(),
16+getRuntimeAuthForModel: vi.fn(),
17+resolveApiKeyForProvider: vi.fn(),
18+}));
19+20+vi.mock("./runtime-model-auth.runtime.js", () => runtimeModelAuthMocks);
21+1322import {
1423clearGatewaySubagentRuntime,
1524createPluginRuntime,
@@ -107,6 +116,9 @@ function expectRunCommandOutcome(params: {
107116describe("plugin runtime command execution", () => {
108117beforeEach(() => {
109118vi.restoreAllMocks();
119+runtimeModelAuthMocks.getApiKeyForModel.mockReset();
120+runtimeModelAuthMocks.getRuntimeAuthForModel.mockReset();
121+runtimeModelAuthMocks.resolveApiKeyForProvider.mockReset();
110122resetConfigRuntimeState();
111123clearGatewaySubagentRuntime();
112124});
@@ -291,6 +303,57 @@ describe("plugin runtime command execution", () => {
291303expect(runtime.modelAuth.getApiKeyForModel).not.toBe(rawGetApiKey);
292304});
293305306+it("modelAuth wrappers preserve workspace scope while stripping credential steering", async () => {
307+const runtime = createPluginRuntime();
308+const model = {
309+id: "workspace-cloud/model",
310+provider: "workspace-cloud",
311+api: "openai-responses",
312+baseUrl: "https://workspace-cloud.example/v1",
313+};
314+const cfg = { plugins: { allow: ["workspace-cloud"] } } as OpenClawConfig;
315+runtimeModelAuthMocks.getApiKeyForModel.mockResolvedValue({
316+apiKey: "model-key",
317+source: "workspace cloud credentials",
318+mode: "api-key",
319+});
320+runtimeModelAuthMocks.resolveApiKeyForProvider.mockResolvedValue({
321+apiKey: "provider-key",
322+source: "workspace cloud credentials",
323+mode: "api-key",
324+});
325+326+await expect(
327+runtime.modelAuth.getApiKeyForModel({
328+model: model as never,
329+ cfg,
330+workspaceDir: "/tmp/workspace",
331+agentDir: "/tmp/agent",
332+store: { version: 1, profiles: {} },
333+} as never),
334+).resolves.toMatchObject({ apiKey: "model-key" });
335+await expect(
336+runtime.modelAuth.resolveApiKeyForProvider({
337+provider: "workspace-cloud",
338+ cfg,
339+workspaceDir: "/tmp/workspace",
340+agentDir: "/tmp/agent",
341+store: { version: 1, profiles: {} },
342+} as never),
343+).resolves.toMatchObject({ apiKey: "provider-key" });
344+345+expect(runtimeModelAuthMocks.getApiKeyForModel).toHaveBeenCalledWith({
346+ model,
347+ cfg,
348+workspaceDir: "/tmp/workspace",
349+});
350+expect(runtimeModelAuthMocks.resolveApiKeyForProvider).toHaveBeenCalledWith({
351+provider: "workspace-cloud",
352+ cfg,
353+workspaceDir: "/tmp/workspace",
354+});
355+});
356+294357it("keeps subagent unavailable by default even after gateway initialization", async () => {
295358const { runtime } = createGatewaySubagentRunFixture();
296359此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。