mirror of
https://github.com/bendtherules/opencode-multi-model.git
synced 2026-08-18 13:42:21 +00:00
fix: update model references from gpt-4o to gpt-5-2 in utils and tests
This commit is contained in:
+2
-2
@@ -309,8 +309,8 @@ export function getSessionPath(sessionName: string): string {
|
|||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* getWorktreePath("my-session", "gpt-4o");
|
* getWorktreePath("my-session", "gpt-5-2");
|
||||||
* // "/home/user/.local/share/opencode/multi-model/my-session/gpt-4o"
|
* // "/home/user/.local/share/opencode/multi-model/my-session/gpt-5-2"
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function getWorktreePath(safeSession: string, windowName: string): string {
|
export function getWorktreePath(safeSession: string, windowName: string): string {
|
||||||
|
|||||||
+43
-43
@@ -70,7 +70,7 @@ describe("multi-model launch", () => {
|
|||||||
"command -v opencode": { ok: true, stdout: "/usr/bin/opencode", stderr: "" },
|
"command -v opencode": { ok: true, stdout: "/usr/bin/opencode", stderr: "" },
|
||||||
"opencode models": { ok: true, stdout: "openai/gpt-5.2\nanthropic/claude-3-5-sonnet", stderr: "" },
|
"opencode models": { ok: true, stdout: "openai/gpt-5.2\nanthropic/claude-3-5-sonnet", stderr: "" },
|
||||||
"tmux has-session -t test-session": { ok: false, stdout: "", stderr: "session not found" },
|
"tmux has-session -t test-session": { ok: false, stdout: "", stderr: "session not found" },
|
||||||
"git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-4o": { ok: false, stdout: "", stderr: "" },
|
"git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-5-2": { ok: false, stdout: "", stderr: "" },
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -200,8 +200,8 @@ describe("multi-model launch", () => {
|
|||||||
|
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
expect(result.instructions).toContain("Use `tmux attach -t test-session` to join session");
|
expect(result.instructions).toContain("Use `tmux attach -t test-session` to join session");
|
||||||
expect(executedCommands.some(c => c.startsWith("tmux new-session -d -s test-session -n gpt-4o"))).toBe(true);
|
expect(executedCommands.some(c => c.startsWith("tmux new-session -d -s test-session -n gpt-5-2"))).toBe(true);
|
||||||
expect(executedCommands.some(c => c.startsWith("tmux send-keys -t test-session:gpt-4o"))).toBe(true);
|
expect(executedCommands.some(c => c.startsWith("tmux send-keys -t test-session:gpt-5-2"))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("successfully launches multiple models", async () => {
|
test("successfully launches multiple models", async () => {
|
||||||
@@ -214,13 +214,13 @@ describe("multi-model launch", () => {
|
|||||||
|
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
expect(result.instructions).toContain("Use `tmux attach -t test-session` to join session");
|
expect(result.instructions).toContain("Use `tmux attach -t test-session` to join session");
|
||||||
expect(executedCommands.some(c => c.startsWith("tmux new-session -d -s test-session -n gpt-4o"))).toBe(true);
|
expect(executedCommands.some(c => c.startsWith("tmux new-session -d -s test-session -n gpt-5-2"))).toBe(true);
|
||||||
expect(executedCommands.some(c => c.startsWith("tmux new-window -d -t test-session -n claude-3-5-sonnet"))).toBe(true);
|
expect(executedCommands.some(c => c.startsWith("tmux new-window -d -t test-session -n claude-3-5-sonnet"))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("sanitizes session name", async () => {
|
test("sanitizes session name", async () => {
|
||||||
mockCommandResponses["tmux has-session -t test session!"] = { ok: false, stdout: "", stderr: "" };
|
mockCommandResponses["tmux has-session -t test session!"] = { ok: false, stdout: "", stderr: "" };
|
||||||
mockCommandResponses["git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-4o"] = { ok: false, stdout: "", stderr: "" };
|
mockCommandResponses["git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-5-2"] = { ok: false, stdout: "", stderr: "" };
|
||||||
|
|
||||||
const result = await launchMultiModel({
|
const result = await launchMultiModel({
|
||||||
sessionName: "test session!",
|
sessionName: "test session!",
|
||||||
@@ -229,13 +229,13 @@ describe("multi-model launch", () => {
|
|||||||
|
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
expect(result.instructions).toContain("Use `tmux attach -t test session!` to join session");
|
expect(result.instructions).toContain("Use `tmux attach -t test session!` to join session");
|
||||||
expect(executedCommands.some(c => c.startsWith("git worktree add -b opencode/test-session/gpt-4o"))).toBe(true);
|
expect(executedCommands.some(c => c.startsWith("git worktree add -b opencode/test-session/gpt-5-2"))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("fails if tmux new-session fails for the first model and triggers undo", async () => {
|
test("fails if tmux new-session fails for the first model and triggers undo", async () => {
|
||||||
mockCommandResponses["tmux new-session -d -s test-session -n gpt-4o -c /mock/home/.local/share/opencode/multi-model/test-session/gpt-4o"] = { ok: false, stdout: "", stderr: "tmux error" };
|
mockCommandResponses["tmux new-session -d -s test-session -n gpt-5-2 -c /mock/home/.local/share/opencode/multi-model/test-session/gpt-5-2"] = { ok: false, stdout: "", stderr: "tmux error" };
|
||||||
mockCommandResponses["git worktree remove -f /mock/home/.local/share/opencode/multi-model/test-session/gpt-4o"] = { ok: true, stdout: "", stderr: "" };
|
mockCommandResponses["git worktree remove -f /mock/home/.local/share/opencode/multi-model/test-session/gpt-5-2"] = { ok: true, stdout: "", stderr: "" };
|
||||||
mockCommandResponses["git branch -D opencode/test-session/gpt-4o"] = { ok: true, stdout: "", stderr: "" };
|
mockCommandResponses["git branch -D opencode/test-session/gpt-5-2"] = { ok: true, stdout: "", stderr: "" };
|
||||||
|
|
||||||
const result = await launchMultiModel({
|
const result = await launchMultiModel({
|
||||||
sessionName: "test-session",
|
sessionName: "test-session",
|
||||||
@@ -250,17 +250,17 @@ describe("multi-model launch", () => {
|
|||||||
"command -v opencode",
|
"command -v opencode",
|
||||||
"opencode models",
|
"opencode models",
|
||||||
"tmux has-session -t test-session",
|
"tmux has-session -t test-session",
|
||||||
"git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-4o",
|
"git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-5-2",
|
||||||
"git worktree add -b opencode/test-session/gpt-4o /mock/home/.local/share/opencode/multi-model/test-session/gpt-4o",
|
"git worktree add -b opencode/test-session/gpt-5-2 /mock/home/.local/share/opencode/multi-model/test-session/gpt-5-2",
|
||||||
"tmux new-session -d -s test-session -n gpt-4o -c /mock/home/.local/share/opencode/multi-model/test-session/gpt-4o",
|
"tmux new-session -d -s test-session -n gpt-5-2 -c /mock/home/.local/share/opencode/multi-model/test-session/gpt-5-2",
|
||||||
"git worktree remove -f /mock/home/.local/share/opencode/multi-model/test-session/gpt-4o",
|
"git worktree remove -f /mock/home/.local/share/opencode/multi-model/test-session/gpt-5-2",
|
||||||
"git branch -D opencode/test-session/gpt-4o"
|
"git branch -D opencode/test-session/gpt-5-2"
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("fails if worktree path exists for first model", async () => {
|
test("fails if worktree path exists for first model", async () => {
|
||||||
existsSyncMock.mockImplementation((path: string) => {
|
existsSyncMock.mockImplementation((path: string) => {
|
||||||
return path.includes("test-session/gpt-4o");
|
return path.includes("test-session/gpt-5-2");
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = await launchMultiModel({
|
const result = await launchMultiModel({
|
||||||
@@ -280,7 +280,7 @@ describe("multi-model launch", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("fails if git branch exists for first model", async () => {
|
test("fails if git branch exists for first model", async () => {
|
||||||
mockCommandResponses["git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-4o"] = { ok: true, stdout: "", stderr: "" };
|
mockCommandResponses["git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-5-2"] = { ok: true, stdout: "", stderr: "" };
|
||||||
|
|
||||||
const result = await launchMultiModel({
|
const result = await launchMultiModel({
|
||||||
sessionName: "test-session",
|
sessionName: "test-session",
|
||||||
@@ -288,19 +288,19 @@ describe("multi-model launch", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(result.success).toBe(false);
|
expect(result.success).toBe(false);
|
||||||
expect(result.error).toContain("Branch 'opencode/test-session/gpt-4o' already exists");
|
expect(result.error).toContain("Branch 'opencode/test-session/gpt-5-2' already exists");
|
||||||
expect(executedCommands).toEqual([
|
expect(executedCommands).toEqual([
|
||||||
"git rev-parse --is-inside-work-tree",
|
"git rev-parse --is-inside-work-tree",
|
||||||
"command -v tmux",
|
"command -v tmux",
|
||||||
"command -v opencode",
|
"command -v opencode",
|
||||||
"opencode models",
|
"opencode models",
|
||||||
"tmux has-session -t test-session",
|
"tmux has-session -t test-session",
|
||||||
"git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-4o"
|
"git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-5-2"
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("fails if git worktree add fails for first model", async () => {
|
test("fails if git worktree add fails for first model", async () => {
|
||||||
mockCommandResponses["git worktree add -b opencode/test-session/gpt-4o /mock/home/.local/share/opencode/multi-model/test-session/gpt-4o"] = { ok: false, stdout: "", stderr: "git error" };
|
mockCommandResponses["git worktree add -b opencode/test-session/gpt-5-2 /mock/home/.local/share/opencode/multi-model/test-session/gpt-5-2"] = { ok: false, stdout: "", stderr: "git error" };
|
||||||
|
|
||||||
const result = await launchMultiModel({
|
const result = await launchMultiModel({
|
||||||
sessionName: "test-session",
|
sessionName: "test-session",
|
||||||
@@ -315,25 +315,25 @@ describe("multi-model launch", () => {
|
|||||||
"command -v opencode",
|
"command -v opencode",
|
||||||
"opencode models",
|
"opencode models",
|
||||||
"tmux has-session -t test-session",
|
"tmux has-session -t test-session",
|
||||||
"git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-4o",
|
"git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-5-2",
|
||||||
"git worktree add -b opencode/test-session/gpt-4o /mock/home/.local/share/opencode/multi-model/test-session/gpt-4o"
|
"git worktree add -b opencode/test-session/gpt-5-2 /mock/home/.local/share/opencode/multi-model/test-session/gpt-5-2"
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("model name collision creates unique window names", async () => {
|
test("model name collision creates unique window names", async () => {
|
||||||
mockCommandResponses["opencode models"] = { ok: true, stdout: "openai/gpt-5.2\nanthropic/gpt-4o", stderr: "" };
|
mockCommandResponses["opencode models"] = { ok: true, stdout: "openai/gpt-5.2\nanthropic/gpt-5.2", stderr: "" };
|
||||||
mockCommandResponses["git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-4o"] = { ok: false, stdout: "", stderr: "" };
|
mockCommandResponses["git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-5-2"] = { ok: false, stdout: "", stderr: "" };
|
||||||
mockCommandResponses["git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-4o-2"] = { ok: false, stdout: "", stderr: "" };
|
mockCommandResponses["git show-ref --verify --quiet refs/heads/opencode/test-session/gpt-5-2-2"] = { ok: false, stdout: "", stderr: "" };
|
||||||
|
|
||||||
const result = await launchMultiModel({
|
const result = await launchMultiModel({
|
||||||
sessionName: "test-session",
|
sessionName: "test-session",
|
||||||
models: ["openai/gpt-5.2", "anthropic/gpt-4o"],
|
models: ["openai/gpt-5.2", "anthropic/gpt-5.2"],
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
expect(result.instructions).toContain("Use `tmux attach -t test-session` to join session");
|
expect(result.instructions).toContain("Use `tmux attach -t test-session` to join session");
|
||||||
expect(executedCommands.some(c => c.startsWith("tmux new-session -d -s test-session -n gpt-4o"))).toBe(true);
|
expect(executedCommands.some(c => c.startsWith("tmux new-session -d -s test-session -n gpt-5-2"))).toBe(true);
|
||||||
expect(executedCommands.some(c => c.startsWith("tmux new-window -d -t test-session -n gpt-4o-2"))).toBe(true);
|
expect(executedCommands.some(c => c.startsWith("tmux new-window -d -t test-session -n gpt-5-2-2"))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("long model name is truncated in window name", async () => {
|
test("long model name is truncated in window name", async () => {
|
||||||
@@ -431,7 +431,7 @@ describe("core utils", () => {
|
|||||||
|
|
||||||
describe("createWindowBaseName", () => {
|
describe("createWindowBaseName", () => {
|
||||||
test("normal model name without slashes", () => {
|
test("normal model name without slashes", () => {
|
||||||
expect(createWindowBaseName("gpt-4o")).toBe("gpt-4o");
|
expect(createWindowBaseName("gpt-5-2")).toBe("gpt-5-2");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("model with slashes", () => {
|
test("model with slashes", () => {
|
||||||
@@ -454,13 +454,13 @@ describe("core utils", () => {
|
|||||||
|
|
||||||
describe("createWindowPlans", () => {
|
describe("createWindowPlans", () => {
|
||||||
test("single model", () => {
|
test("single model", () => {
|
||||||
expect(createWindowPlans(["openai/gpt-5.2"])).toEqual([{ model: "openai/gpt-5.2", windowName: "gpt-4o" }]);
|
expect(createWindowPlans(["openai/gpt-5-2"])).toEqual([{ model: "openai/gpt-5-2", windowName: "gpt-5-2" }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("two models with the same base name", () => {
|
test("two models with the same base name", () => {
|
||||||
expect(createWindowPlans(["openai/gpt-5.2", "anthropic/gpt-4o"])).toEqual([
|
expect(createWindowPlans(["openai/gpt-5-2", "anthropic/gpt-5-2"])).toEqual([
|
||||||
{ model: "openai/gpt-5.2", windowName: "gpt-4o" },
|
{ model: "openai/gpt-5-2", windowName: "gpt-5-2" },
|
||||||
{ model: "anthropic/gpt-4o", windowName: "gpt-4o-2" }
|
{ model: "anthropic/gpt-5-2", windowName: "gpt-5-2-2" }
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -510,8 +510,8 @@ describe("core utils", () => {
|
|||||||
|
|
||||||
describe("suggestModels", () => {
|
describe("suggestModels", () => {
|
||||||
test("exact match", () => {
|
test("exact match", () => {
|
||||||
const result = suggestModels("gpt-4o", ["gpt-4o", "gpt-4o-mini"]);
|
const result = suggestModels("gpt-5.2", ["gpt-5.2", "gpt-5.2-mini"]);
|
||||||
expect(result[0]).toBe("gpt-4o");
|
expect(result[0]).toBe("gpt-5.2");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("fuzzy match/typo", () => {
|
test("fuzzy match/typo", () => {
|
||||||
@@ -519,12 +519,12 @@ describe("core utils", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("fuzzy match with contains boost", () => {
|
test("fuzzy match with contains boost", () => {
|
||||||
const suggestions = suggestModels("gpt4o", ["gpt-4o", "gpt-4o-mini"]);
|
const suggestions = suggestModels("gpt4o", ["gpt-5.2", "gpt-5.2-mini"]);
|
||||||
expect(suggestions[0]).toBe("gpt-4o");
|
expect(suggestions[0]).toBe("gpt-5.2");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("maximum of 3 suggestions", () => {
|
test("maximum of 3 suggestions", () => {
|
||||||
const allowlist = ["gpt-4o", "gpt-4o-mini", "gpt-4o-pro", "gpt-4o-ultra"];
|
const allowlist = ["gpt-5.2", "gpt-5.2-mini", "gpt-5.2-pro", "gpt-5.2-ultra"];
|
||||||
expect(suggestModels("gpt4o", allowlist).length).toBe(3);
|
expect(suggestModels("gpt4o", allowlist).length).toBe(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -536,7 +536,7 @@ describe("core utils", () => {
|
|||||||
|
|
||||||
describe("formatInvalidModelError", () => {
|
describe("formatInvalidModelError", () => {
|
||||||
test("single invalid model with available suggestions", () => {
|
test("single invalid model with available suggestions", () => {
|
||||||
const error = formatInvalidModelError(["gpt5.4"], ["gpt-5.4", "gpt-4o"]);
|
const error = formatInvalidModelError(["gpt5.4"], ["gpt-5.4", "gpt-5.2"]);
|
||||||
expect(error).toContain("Model name 'gpt5.4' not found");
|
expect(error).toContain("Model name 'gpt5.4' not found");
|
||||||
expect(error).toContain("Did you mean");
|
expect(error).toContain("Did you mean");
|
||||||
});
|
});
|
||||||
@@ -593,8 +593,8 @@ describe("core utils", () => {
|
|||||||
describe("getWorktreePath", () => {
|
describe("getWorktreePath", () => {
|
||||||
test("returns correct worktree path", () => {
|
test("returns correct worktree path", () => {
|
||||||
spyOn(os, "homedir").mockReturnValue("/home/user");
|
spyOn(os, "homedir").mockReturnValue("/home/user");
|
||||||
const result = getWorktreePath("my-session", "gpt-4o");
|
const result = getWorktreePath("my-session", "gpt-5.2");
|
||||||
expect(result).toBe("/home/user/.local/share/opencode/multi-model/my-session/gpt-4o");
|
expect(result).toBe("/home/user/.local/share/opencode/multi-model/my-session/gpt-5.2");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("handles nested session names", () => {
|
test("handles nested session names", () => {
|
||||||
@@ -671,14 +671,14 @@ describe("core utils", () => {
|
|||||||
spyOn(os, "homedir").mockReturnValue("/home/user");
|
spyOn(os, "homedir").mockReturnValue("/home/user");
|
||||||
mockCommandResponses["git worktree list --porcelain"] = {
|
mockCommandResponses["git worktree list --porcelain"] = {
|
||||||
ok: true,
|
ok: true,
|
||||||
stdout: "worktree /home/user/.local/share/opencode/multi-model/my-session/gpt-4o\nbranch refs/heads/opencode/my-session/gpt-4o\n\nworktree /home/user/other-repo\nbranch refs/heads/main",
|
stdout: "worktree /home/user/.local/share/opencode/multi-model/my-session/gpt-5.2\nbranch refs/heads/opencode/my-session/gpt-5.2\n\nworktree /home/user/other-repo\nbranch refs/heads/main",
|
||||||
stderr: "",
|
stderr: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
const worktrees = await getWorktreesForSession("my-session");
|
const worktrees = await getWorktreesForSession("my-session");
|
||||||
expect(worktrees.length).toBe(1);
|
expect(worktrees.length).toBe(1);
|
||||||
expect(worktrees[0]?.path).toBe("/home/user/.local/share/opencode/multi-model/my-session/gpt-4o");
|
expect(worktrees[0]?.path).toBe("/home/user/.local/share/opencode/multi-model/my-session/gpt-5.2");
|
||||||
expect(worktrees[0]?.branch).toBe("opencode/my-session/gpt-4o");
|
expect(worktrees[0]?.branch).toBe("opencode/my-session/gpt-5.2");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("returns empty array when no matching worktrees", async () => {
|
test("returns empty array when no matching worktrees", async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user