
























@@ -356,6 +356,67 @@ describe("/model chat UX", () => {
356356expect(reply?.text).toContain("Switch: /model <provider/model>");
357357});
358358359+it("uses workspace-scoped auth evidence in /model list provider visibility", async () => {
360+const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-model-list-auth-label-"));
361+const workspaceDir = path.join(tempRoot, "workspace");
362+const pluginDir = path.join(workspaceDir, ".openclaw", "extensions", "workspace-model-list");
363+const bundledDir = path.join(tempRoot, "bundled");
364+const stateDir = path.join(tempRoot, "state");
365+const credentialPath = path.join(tempRoot, "credentials.json");
366+fs.mkdirSync(pluginDir, { recursive: true });
367+fs.mkdirSync(bundledDir, { recursive: true });
368+fs.mkdirSync(stateDir, { recursive: true });
369+fs.writeFileSync(path.join(pluginDir, "index.ts"), "export default {}\n", "utf8");
370+fs.writeFileSync(credentialPath, "{}", "utf8");
371+fs.writeFileSync(
372+path.join(pluginDir, "openclaw.plugin.json"),
373+JSON.stringify({
374+id: "workspace-model-list",
375+configSchema: { type: "object" },
376+setup: {
377+providers: [
378+{
379+id: "anthropic",
380+authEvidence: [
381+{
382+type: "local-file-with-env",
383+fileEnvVar: "WORKSPACE_MODEL_LIST_CREDENTIALS",
384+credentialMarker: "workspace-model-list-local-credentials",
385+source: "workspace model list credentials",
386+},
387+],
388+},
389+],
390+},
391+}),
392+"utf8",
393+);
394+395+try {
396+await withEnvAsync(
397+{
398+OPENCLAW_BUNDLED_PLUGINS_DIR: bundledDir,
399+OPENCLAW_STATE_DIR: stateDir,
400+WORKSPACE_MODEL_LIST_CREDENTIALS: credentialPath,
401+},
402+async () => {
403+const reply = await resolveModelInfoReply({
404+directives: parseInlineDirectives("/model list"),
405+ workspaceDir,
406+cfg: {
407+ ...baseConfig(),
408+plugins: { allow: ["workspace-model-list"] },
409+} as OpenClawConfig,
410+});
411+412+expect(reply?.text).toContain("- anthropic");
413+},
414+);
415+} finally {
416+fs.rmSync(tempRoot, { recursive: true, force: true });
417+}
418+});
419+359420it("shows active runtime model when different from selected model", async () => {
360421const reply = await resolveModelInfoReply({
361422provider: "fireworks",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。