feat: better config
CI / verify (pull_request) Successful in 9s

This commit is contained in:
2026-09-19 13:12:03 +02:00
parent a183975b8a
commit 80728e7d75
6 changed files with 277 additions and 65 deletions
+176 -28
View File
@@ -9,7 +9,7 @@ import type { Info, ToolContext, ToolEditor } from "@opencode/plugin/promise/too
import type { JsonValue, ModelInfo, SessionGetInput } from "@opencode/client";
import type { SessionContext } from "@opencode/plugin/promise/session";
import { z } from "zod";
import { gptAgents } from "../src/config.js";
import { gptAgents, settings, workerNames } from "../src/config.js";
import { basePlugin as plugin } from "../src/index.js";
import { playwrightMcpCommand } from "../src/playwright.js";
import { bindingKey } from "../src/multi-work.js";
@@ -27,7 +27,31 @@ function reasoningModel(id: string): ModelInfo {
})),
};
}
function providerModel(provider: string, id: string): ModelInfo {
return {
...reasoningModel(id),
providerID: Provider.ID.make(provider),
};
}
const allModels = ["gpt-5.6-luna", "gpt-5.6-sol", "gpt-6-astra"].map(reasoningModel);
type CustomAssignment = {
model: string;
effort: "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
};
const customAssignments = (provider = "test") => {
const assignment = (name: (typeof workerNames)[number]): CustomAssignment => ({
...gptAgents[name],
model: `${provider}/${gptAgents[name].model}`,
});
return {
"fast-lo": assignment("fast-lo"),
"fast-hi": assignment("fast-hi"),
"good-lo": assignment("good-lo"),
"good-hi": assignment("good-hi"),
"deep-lo": assignment("deep-lo"),
"deep-hi": assignment("deep-hi"),
};
};
const cleanups: Plugin.Cleanup[] = [];
afterEach(async () => {
for (const cleanup of cleanups.splice(0)) await cleanup();
@@ -352,15 +376,20 @@ test("orchestration inherits deep-lo and falls back to good-lo with available wo
expect((await host(allModels.slice(1))).agents.has("coordinate")).toBe(false);
const customAgents = {
...gptAgents,
"good-lo": { model: "custom-good", effort: "high" as const },
"deep-lo": { model: "custom-deep", effort: "medium" as const },
...customAssignments(),
"good-lo": {
model: "test/custom-good",
effort: "high" as const,
},
"deep-lo": {
model: "test/custom-deep",
effort: "medium" as const,
},
};
const custom = await host(
[...allModels, reasoningModel("custom-good"), reasoningModel("custom-deep")],
{
mode: "custom",
provider: "test",
agents: customAgents,
},
);
@@ -370,7 +399,6 @@ test("orchestration inherits deep-lo and falls back to good-lo with available wo
});
const customFallback = await host([...allModels, reasoningModel("custom-good")], {
mode: "custom",
provider: "test",
agents: customAgents,
});
expect(customFallback.agents.get("coordinate")?.model).toMatchObject({
@@ -382,13 +410,106 @@ test("orchestration inherits deep-lo and falls back to good-lo with available wo
(
await host(allModels, {
mode: "custom",
provider: "test",
agents: customAgents,
})
).agents.has("coordinate"),
).toBe(false);
});
test("custom assignments resolve duplicate model IDs by provider and refresh provider-aware fallback", async () => {
const agents = customAssignments("alpha");
agents["fast-lo"] = { ...agents["fast-lo"], model: "beta/shared" };
agents["fast-hi"] = { ...agents["fast-hi"], model: "alpha/shared" };
agents["deep-lo"] = { ...agents["deep-lo"], model: "beta/deep" };
agents["deep-hi"] = { ...agents["deep-hi"], model: "beta/deep" };
const base = [
providerModel("alpha", "shared"),
providerModel("beta", "shared"),
providerModel("alpha", "gpt-5.6-sol"),
providerModel("alpha", "gpt-6-astra"),
];
const result = await host(base, { mode: "custom", agents });
expect(String(result.agents.get("fast-lo")?.model?.providerID)).toBe("beta");
expect(String(result.agents.get("fast-hi")?.model?.providerID)).toBe("alpha");
expect(String(result.agents.get("coordinate")?.model?.id)).toBe("gpt-5.6-sol");
expect(result.agents.has("deep-lo")).toBe(false);
await result.refresh([...base, providerModel("beta", "deep")]);
expect(result.agents.get("coordinate")?.model).toMatchObject({
providerID: "beta",
id: "deep",
});
expect(result.agents.has("deep-lo")).toBe(true);
const nested = customAssignments("alpha");
nested["fast-lo"] = { ...nested["fast-lo"], model: "alpha/group/shared" };
const nestedResult = await host(
[...base, providerModel("alpha", "gpt-5.6-luna"), providerModel("alpha", "group/shared")],
{ mode: "custom", agents: nested },
);
expect(String(nestedResult.agents.get("fast-lo")?.model?.id)).toBe("group/shared");
});
test("custom configuration requires qualified models and rejects obsolete fields", () => {
expect(() => settings.parse({ mode: "custom", agents: customAssignments() })).not.toThrow();
for (const model of ["bare", "/model", "provider/"])
expect(() =>
settings.parse({
mode: "custom",
agents: {
...customAssignments(),
"fast-lo": { model, effort: "low" },
},
}),
).toThrow();
const nested = customAssignments();
nested["fast-lo"] = { model: "provider/group/model", effort: "low" };
expect(() => settings.parse({ mode: "custom", agents: nested })).not.toThrow();
expect(() =>
settings.parse({ mode: "custom", provider: "test", agents: customAssignments() }),
).toThrow();
expect(() =>
settings.parse({ mode: "custom", lunaPriority: false, agents: customAssignments() }),
).toThrow();
expect(() =>
settings.parse({
mode: "custom",
agents: {
...customAssignments(),
"fast-lo": { ...customAssignments()["fast-lo"], provider: "test" },
},
}),
).toThrow();
expect(() =>
settings.parse({
mode: "custom",
agents: {
...customAssignments(),
"fast-lo": { ...customAssignments()["fast-lo"], lunaPriority: true },
},
}),
).toThrow();
expect(() =>
settings.parse({
mode: "custom",
agents: { ...customAssignments(), coordinate: customAssignments()["deep-lo"] },
}),
).not.toThrow();
for (const obsolete of [{ provider: "test" }, { lunaPriority: true }])
expect(() =>
settings.parse({
mode: "custom",
agents: {
...customAssignments(),
coordinate: {
...customAssignments()["deep-lo"],
...obsolete,
},
},
}),
).toThrow();
});
test("worker inheritance and coordinator isolation preserve build and default", async () => {
const result = await host();
expect(result.defaultAgent).toBe("build");
@@ -689,33 +810,58 @@ test("coordinate prompt admission requires owned ready placement; local and move
test("reasoning settings and Luna priority use native advertised or official support", async () => {
const luna = {
...model("gpt-5.6-luna"),
...providerModel("openai", "gpt-5.6-luna"),
package: "@opencode/ai/providers/openai",
settings: { baseURL: "https://api.openai.com/v1" },
};
const ordinary = await host();
const openaiModels = [
luna,
providerModel("openai", "gpt-5.6-sol"),
providerModel("openai", "gpt-6-astra"),
];
const ordinary = await host(
[providerModel("openai", "gpt-5.6-luna"), ...openaiModels.slice(1)],
{ provider: "openai" },
);
expect(ordinary.agents.get("fast-lo")?.request.settings).toEqual({});
expect(String(ordinary.agents.get("fast-lo")?.model?.variant)).toBe("low");
const official = await host([luna, ...allModels.slice(1)]);
expect(official.agents.get("fast-hi")?.request.settings).toEqual({
reasoningEffort: "high",
serviceTier: "priority",
});
const proxy = await host([
{ ...luna, settings: { baseURL: "https://proxy.example/v1" } },
...allModels.slice(1),
]);
expect(proxy.agents.get("fast-lo")?.request.settings).toEqual({ reasoningEffort: "low" });
const advertised = await host([
{ ...luna, package: "custom", settings: { serviceTier: "fast" } },
...allModels.slice(1),
]);
const official = await host(openaiModels, { provider: "openai" });
expect(official.agents.get("fast-hi")?.request.settings).toEqual({ serviceTier: "priority" });
const proxy = await host(
[{ ...luna, settings: { baseURL: "https://proxy.example/v1" } }, ...openaiModels.slice(1)],
{ provider: "openai" },
);
expect(proxy.agents.get("fast-lo")?.request.settings).toEqual({});
const advertised = await host(
[
{ ...luna, package: "custom", settings: { serviceTier: "fast" } },
...openaiModels.slice(1),
],
{ provider: "openai" },
);
expect(advertised.agents.get("fast-lo")?.request.settings.serviceTier).toBe("fast");
const disabled = await host([luna, ...allModels.slice(1)], {
provider: "test",
const sdkAlias = await host(
[{ ...luna, package: "@ai-sdk/openai" }, ...openaiModels.slice(1)],
{ provider: "openai" },
);
expect(sdkAlias.agents.get("fast-lo")?.request.settings.serviceTier).toBe("priority");
const disabled = await host(openaiModels, {
provider: "openai",
lunaPriority: false,
});
expect(disabled.agents.get("fast-lo")?.request.settings).toEqual({ reasoningEffort: "low" });
expect(disabled.agents.get("fast-lo")?.request.settings).toEqual({});
const custom = customAssignments("openai");
const customResult = await host(openaiModels, {
mode: "custom",
agents: custom,
});
expect(customResult.agents.get("fast-lo")?.request.settings.serviceTier).toBeUndefined();
expect(customResult.agents.get("fast-hi")?.request.settings.serviceTier).toBeUndefined();
const other = await host(allModels, { provider: "test" });
expect(other.agents.get("fast-lo")?.request.settings.serviceTier).toBeUndefined();
expect(() => settings.parse({ mode: "gpt", provider: "test", lunaPriority: true })).toThrow();
});
test("coordinator uses inherited effort and ignores the legacy custom assignment", async () => {
@@ -737,8 +883,10 @@ test("coordinator uses inherited effort and ignores the legacy custom assignment
const custom = await host([...allModels, model("local")], {
mode: "custom",
provider: "test",
agents: { ...gptAgents, coordinate: { model: "local", effort: "xhigh" } },
agents: {
...customAssignments(),
coordinate: { model: "test/local", effort: "xhigh" },
},
});
expect(custom.agents.get("coordinate")?.model).toMatchObject({
id: "gpt-6-astra",