mirror of
https://github.com/bendtherules/opencode-multi-model.git
synced 2026-08-18 13:42:21 +00:00
build: add biome formatter and linter
This commit is contained in:
+470
-167
@@ -1,10 +1,21 @@
|
||||
import { expect, test, mock, beforeEach, afterEach, describe, spyOn } from "bun:test";
|
||||
import * as os from "node:os";
|
||||
import {
|
||||
afterEach,
|
||||
beforeEach,
|
||||
describe,
|
||||
expect,
|
||||
mock,
|
||||
spyOn,
|
||||
test,
|
||||
} from "bun:test";
|
||||
import * as fs from "node:fs";
|
||||
import * as os from "node:os";
|
||||
import { openMultiModel } from "../src/core/open";
|
||||
|
||||
let originalBun$: typeof Bun.$ = (globalThis as any).Bun?.$;
|
||||
let mockCommandResponses: Record<string, { ok: boolean; stdout: string; stderr: string }> = {};
|
||||
const originalBun$: typeof Bun.$ = (globalThis as any).Bun?.$;
|
||||
let mockCommandResponses: Record<
|
||||
string,
|
||||
{ ok: boolean; stdout: string; stderr: string }
|
||||
> = {};
|
||||
let executedCommands: string[] = [];
|
||||
|
||||
function setupMockBun$() {
|
||||
@@ -12,7 +23,11 @@ function setupMockBun$() {
|
||||
const parts = values[0] as string[];
|
||||
const cmd = parts.join(" ");
|
||||
executedCommands.push(cmd);
|
||||
const response = mockCommandResponses[cmd] ?? { ok: true, stdout: "", stderr: "" };
|
||||
const response = mockCommandResponses[cmd] ?? {
|
||||
ok: true,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
return {
|
||||
quiet: () => ({
|
||||
nothrow: async () => ({
|
||||
@@ -44,193 +59,481 @@ describe("openMultiModel error paths", () => {
|
||||
|
||||
test("fails when model list command fails", async () => {
|
||||
const session = "sess";
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = { ok: true, stdout: "true", stderr: "" };
|
||||
mockCommandResponses["command -v tmux"] = { ok: true, stdout: "tmux", stderr: "" };
|
||||
mockCommandResponses["command -v opencode"] = { ok: true, stdout: "opencode", stderr: "" };
|
||||
mockCommandResponses["opencode models"] = { ok: false, stdout: "", stderr: "model error" };
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = {
|
||||
ok: true,
|
||||
stdout: "true",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v tmux"] = {
|
||||
ok: true,
|
||||
stdout: "tmux",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v opencode"] = {
|
||||
ok: true,
|
||||
stdout: "opencode",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["opencode models"] = {
|
||||
ok: false,
|
||||
stdout: "",
|
||||
stderr: "model error",
|
||||
};
|
||||
|
||||
const result = await openMultiModel({ sessionName: session, models: ["openai/gpt-5.2"], binaryName: "opencode", mode: "cli" });
|
||||
const result = await openMultiModel({
|
||||
sessionName: session,
|
||||
models: ["openai/gpt-5.2"],
|
||||
binaryName: "opencode",
|
||||
mode: "cli",
|
||||
});
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toContain("Failed to load valid models");
|
||||
});
|
||||
|
||||
test("fails when duplicate models provided", async () => {
|
||||
const session = "dup";
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = { ok: true, stdout: "true", stderr: "" };
|
||||
mockCommandResponses["command -v tmux"] = { ok: true, stdout: "tmux", stderr: "" };
|
||||
mockCommandResponses["command -v opencode"] = { ok: true, stdout: "opencode", stderr: "" };
|
||||
mockCommandResponses["opencode models"] = { ok: true, stdout: "openai/gpt-5.2", stderr: "" };
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = {
|
||||
ok: true,
|
||||
stdout: "true",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v tmux"] = {
|
||||
ok: true,
|
||||
stdout: "tmux",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v opencode"] = {
|
||||
ok: true,
|
||||
stdout: "opencode",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["opencode models"] = {
|
||||
ok: true,
|
||||
stdout: "openai/gpt-5.2",
|
||||
stderr: "",
|
||||
};
|
||||
|
||||
const result = await openMultiModel({ sessionName: session, models: ["openai/gpt-5.2", "openai/gpt-5.2"], binaryName: "opencode", mode: "cli" });
|
||||
const result = await openMultiModel({
|
||||
sessionName: session,
|
||||
models: ["openai/gpt-5.2", "openai/gpt-5.2"],
|
||||
binaryName: "opencode",
|
||||
mode: "cli",
|
||||
});
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toContain("Duplicate model names are not allowed");
|
||||
});
|
||||
|
||||
test("fails when session already exists", async () => {
|
||||
const session = "existing";
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = { ok: true, stdout: "true", stderr: "" };
|
||||
mockCommandResponses["command -v tmux"] = { ok: true, stdout: "tmux", stderr: "" };
|
||||
mockCommandResponses["command -v opencode"] = { ok: true, stdout: "opencode", stderr: "" };
|
||||
mockCommandResponses["opencode models"] = { ok: true, stdout: "openai/gpt-5.2", stderr: "" };
|
||||
mockCommandResponses[`tmux has-session -t ${session}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = {
|
||||
ok: true,
|
||||
stdout: "true",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v tmux"] = {
|
||||
ok: true,
|
||||
stdout: "tmux",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v opencode"] = {
|
||||
ok: true,
|
||||
stdout: "opencode",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["opencode models"] = {
|
||||
ok: true,
|
||||
stdout: "openai/gpt-5.2",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[`tmux has-session -t ${session}`] = {
|
||||
ok: true,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
|
||||
const result = await openMultiModel({ sessionName: session, models: ["openai/gpt-5.2"], binaryName: "opencode", mode: "cli" });
|
||||
const result = await openMultiModel({
|
||||
sessionName: session,
|
||||
models: ["openai/gpt-5.2"],
|
||||
binaryName: "opencode",
|
||||
mode: "cli",
|
||||
});
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toContain("Session already exists");
|
||||
});
|
||||
|
||||
test("second model fails because branch already exists", async () => {
|
||||
const session = "sess-add";
|
||||
const binary = "opencode";
|
||||
const models = ["openai/gpt-5.2", "anthropic/gpt-5-2"];
|
||||
// common mocks
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = { ok: true, stdout: "true", stderr: "" };
|
||||
mockCommandResponses["command -v tmux"] = { ok: true, stdout: "tmux", stderr: "" };
|
||||
mockCommandResponses["command -v opencode"] = { ok: true, stdout: "opencode", stderr: "" };
|
||||
mockCommandResponses["opencode models"] = { ok: true, stdout: models.join("\n"), stderr: "" };
|
||||
mockCommandResponses[`tmux has-session -t ${session}`] = { ok: false, stdout: "", stderr: "" };
|
||||
// first model success
|
||||
const firstBranch = `opencode/${session}/gpt-5-2`;
|
||||
const firstPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2`;
|
||||
mockCommandResponses[`git show-ref --verify --quiet refs/heads/${firstBranch}`] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${firstBranch} ${firstPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`tmux new-session -d -s ${session} -n gpt-5-2 -c ${firstPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`tmux send-keys -t ${session}:gpt-5-2 ${binary} --model 'openai/gpt-5.2' C-m`] = { ok: true, stdout: "", stderr: "" };
|
||||
// second model branch exists
|
||||
const secondBranch = `opencode/${session}/gpt-5-2-2`;
|
||||
mockCommandResponses[`git show-ref --verify --quiet refs/heads/${secondBranch}`] = { ok: true, stdout: "", stderr: "" };
|
||||
const result = await openMultiModel({ sessionName: session, models, binaryName: binary, mode: "cli" });
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.instructions).toContain("Failed: anthropic/gpt-5-2 (Branch");
|
||||
expect(result.windows).toContain("gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2-2");
|
||||
test("second model fails because branch already exists", async () => {
|
||||
const session = "sess-add";
|
||||
const binary = "opencode";
|
||||
const models = ["openai/gpt-5.2", "anthropic/gpt-5-2"];
|
||||
// common mocks
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = {
|
||||
ok: true,
|
||||
stdout: "true",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v tmux"] = {
|
||||
ok: true,
|
||||
stdout: "tmux",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v opencode"] = {
|
||||
ok: true,
|
||||
stdout: "opencode",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["opencode models"] = {
|
||||
ok: true,
|
||||
stdout: models.join("\n"),
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[`tmux has-session -t ${session}`] = {
|
||||
ok: false,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
// first model success
|
||||
const firstBranch = `opencode/${session}/gpt-5-2`;
|
||||
const firstPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2`;
|
||||
mockCommandResponses[
|
||||
`git show-ref --verify --quiet refs/heads/${firstBranch}`
|
||||
] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${firstBranch} ${firstPath}`] = {
|
||||
ok: true,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[
|
||||
`tmux new-session -d -s ${session} -n gpt-5-2 -c ${firstPath}`
|
||||
] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[
|
||||
`tmux send-keys -t ${session}:gpt-5-2 ${binary} --model 'openai/gpt-5.2' C-m`
|
||||
] = { ok: true, stdout: "", stderr: "" };
|
||||
// second model branch exists
|
||||
const secondBranch = `opencode/${session}/gpt-5-2-2`;
|
||||
mockCommandResponses[
|
||||
`git show-ref --verify --quiet refs/heads/${secondBranch}`
|
||||
] = { ok: true, stdout: "", stderr: "" };
|
||||
const result = await openMultiModel({
|
||||
sessionName: session,
|
||||
models,
|
||||
binaryName: binary,
|
||||
mode: "cli",
|
||||
});
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.instructions).toContain("Failed: anthropic/gpt-5-2 (Branch");
|
||||
expect(result.windows).toContain("gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2-2");
|
||||
});
|
||||
|
||||
test("second model worktree creation fails", async () => {
|
||||
const session = "sess-wt";
|
||||
const binary = "opencode";
|
||||
const models = ["openai/gpt-5.2", "anthropic/gpt-5-2"];
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = {
|
||||
ok: true,
|
||||
stdout: "true",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v tmux"] = {
|
||||
ok: true,
|
||||
stdout: "tmux",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v opencode"] = {
|
||||
ok: true,
|
||||
stdout: "opencode",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["opencode models"] = {
|
||||
ok: true,
|
||||
stdout: models.join("\n"),
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[`tmux has-session -t ${session}`] = {
|
||||
ok: false,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
// first model success
|
||||
const firstBranch = `opencode/${session}/gpt-5-2`;
|
||||
const firstPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2`;
|
||||
mockCommandResponses[
|
||||
`git show-ref --verify --quiet refs/heads/${firstBranch}`
|
||||
] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${firstBranch} ${firstPath}`] = {
|
||||
ok: true,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[
|
||||
`tmux new-session -d -s ${session} -n gpt-5-2 -c ${firstPath}`
|
||||
] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[
|
||||
`tmux send-keys -t ${session}:gpt-5-2 ${binary} --model 'openai/gpt-5.2' C-m`
|
||||
] = { ok: true, stdout: "", stderr: "" };
|
||||
// second model fails worktree
|
||||
const secondBranch = `opencode/${session}/gpt-5-2-2`;
|
||||
const secondPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2-2`;
|
||||
mockCommandResponses[
|
||||
`git show-ref --verify --quiet refs/heads/${secondBranch}`
|
||||
] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${secondBranch} ${secondPath}`] =
|
||||
{ ok: false, stdout: "", stderr: "wt error" };
|
||||
mockCommandResponses[`git worktree remove -f ${secondPath}`] = {
|
||||
ok: true,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[`git branch -D ${secondBranch}`] = {
|
||||
ok: true,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
const result = await openMultiModel({
|
||||
sessionName: session,
|
||||
models,
|
||||
binaryName: binary,
|
||||
mode: "cli",
|
||||
});
|
||||
|
||||
test("second model worktree creation fails", async () => {
|
||||
const session = "sess-wt";
|
||||
const binary = "opencode";
|
||||
const models = ["openai/gpt-5.2", "anthropic/gpt-5-2"];
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = { ok: true, stdout: "true", stderr: "" };
|
||||
mockCommandResponses["command -v tmux"] = { ok: true, stdout: "tmux", stderr: "" };
|
||||
mockCommandResponses["command -v opencode"] = { ok: true, stdout: "opencode", stderr: "" };
|
||||
mockCommandResponses["opencode models"] = { ok: true, stdout: models.join("\n"), stderr: "" };
|
||||
mockCommandResponses[`tmux has-session -t ${session}`] = { ok: false, stdout: "", stderr: "" };
|
||||
// first model success
|
||||
const firstBranch = `opencode/${session}/gpt-5-2`;
|
||||
const firstPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2`;
|
||||
mockCommandResponses[`git show-ref --verify --quiet refs/heads/${firstBranch}`] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${firstBranch} ${firstPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`tmux new-session -d -s ${session} -n gpt-5-2 -c ${firstPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`tmux send-keys -t ${session}:gpt-5-2 ${binary} --model 'openai/gpt-5.2' C-m`] = { ok: true, stdout: "", stderr: "" };
|
||||
// second model fails worktree
|
||||
const secondBranch = `opencode/${session}/gpt-5-2-2`;
|
||||
const secondPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2-2`;
|
||||
mockCommandResponses[`git show-ref --verify --quiet refs/heads/${secondBranch}`] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${secondBranch} ${secondPath}`] = { ok: false, stdout: "", stderr: "wt error" };
|
||||
mockCommandResponses[`git worktree remove -f ${secondPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git branch -D ${secondBranch}`] = { ok: true, stdout: "", stderr: "" };
|
||||
const result = await openMultiModel({ sessionName: session, models, binaryName: binary, mode: "cli" });
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.instructions).toContain("Error: Created tmux session");
|
||||
expect(result.instructions).toContain("Failed: anthropic/gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2-2");
|
||||
});
|
||||
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.instructions).toContain("Error: Created tmux session"); expect(result.instructions).toContain("Failed: anthropic/gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2-2");
|
||||
test("second model window creation fails", async () => {
|
||||
const session = "sess-win";
|
||||
const binary = "opencode";
|
||||
const models = ["openai/gpt-5.2", "anthropic/gpt-5-2"];
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = {
|
||||
ok: true,
|
||||
stdout: "true",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v tmux"] = {
|
||||
ok: true,
|
||||
stdout: "tmux",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v opencode"] = {
|
||||
ok: true,
|
||||
stdout: "opencode",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["opencode models"] = {
|
||||
ok: true,
|
||||
stdout: models.join("\n"),
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[`tmux has-session -t ${session}`] = {
|
||||
ok: false,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
// first model success
|
||||
const firstBranch = `opencode/${session}/gpt-5-2`;
|
||||
const firstPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2`;
|
||||
mockCommandResponses[
|
||||
`git show-ref --verify --quiet refs/heads/${firstBranch}`
|
||||
] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${firstBranch} ${firstPath}`] = {
|
||||
ok: true,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[
|
||||
`tmux new-session -d -s ${session} -n gpt-5-2 -c ${firstPath}`
|
||||
] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[
|
||||
`tmux send-keys -t ${session}:gpt-5-2 ${binary} --model 'openai/gpt-5.2' C-m`
|
||||
] = { ok: true, stdout: "", stderr: "" };
|
||||
// second model window failure
|
||||
const secondBranch = `opencode/${session}/gpt-5-2-2`;
|
||||
const secondPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2-2`;
|
||||
mockCommandResponses[
|
||||
`git show-ref --verify --quiet refs/heads/${secondBranch}`
|
||||
] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${secondBranch} ${secondPath}`] =
|
||||
{ ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[
|
||||
`tmux new-window -d -t ${session} -n gpt-5-2-2 -c ${secondPath}`
|
||||
] = { ok: false, stdout: "", stderr: "win err" };
|
||||
mockCommandResponses[`git worktree remove -f ${secondPath}`] = {
|
||||
ok: true,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[`git branch -D ${secondBranch}`] = {
|
||||
ok: true,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
const result = await openMultiModel({
|
||||
sessionName: session,
|
||||
models,
|
||||
binaryName: binary,
|
||||
mode: "cli",
|
||||
});
|
||||
|
||||
test("second model window creation fails", async () => {
|
||||
const session = "sess-win";
|
||||
const binary = "opencode";
|
||||
const models = ["openai/gpt-5.2", "anthropic/gpt-5-2"];
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = { ok: true, stdout: "true", stderr: "" };
|
||||
mockCommandResponses["command -v tmux"] = { ok: true, stdout: "tmux", stderr: "" };
|
||||
mockCommandResponses["command -v opencode"] = { ok: true, stdout: "opencode", stderr: "" };
|
||||
mockCommandResponses["opencode models"] = { ok: true, stdout: models.join("\n"), stderr: "" };
|
||||
mockCommandResponses[`tmux has-session -t ${session}`] = { ok: false, stdout: "", stderr: "" };
|
||||
// first model success
|
||||
const firstBranch = `opencode/${session}/gpt-5-2`;
|
||||
const firstPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2`;
|
||||
mockCommandResponses[`git show-ref --verify --quiet refs/heads/${firstBranch}`] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${firstBranch} ${firstPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`tmux new-session -d -s ${session} -n gpt-5-2 -c ${firstPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`tmux send-keys -t ${session}:gpt-5-2 ${binary} --model 'openai/gpt-5.2' C-m`] = { ok: true, stdout: "", stderr: "" };
|
||||
// second model window failure
|
||||
const secondBranch = `opencode/${session}/gpt-5-2-2`;
|
||||
const secondPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2-2`;
|
||||
mockCommandResponses[`git show-ref --verify --quiet refs/heads/${secondBranch}`] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${secondBranch} ${secondPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`tmux new-window -d -t ${session} -n gpt-5-2-2 -c ${secondPath}`] = { ok: false, stdout: "", stderr: "win err" };
|
||||
mockCommandResponses[`git worktree remove -f ${secondPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git branch -D ${secondBranch}`] = { ok: true, stdout: "", stderr: "" };
|
||||
const result = await openMultiModel({ sessionName: session, models, binaryName: binary, mode: "cli" });
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.instructions).toContain("Error: Created tmux session");
|
||||
expect(result.instructions).toContain("Failed: anthropic/gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2-2");
|
||||
});
|
||||
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.instructions).toContain("Error: Created tmux session"); expect(result.instructions).toContain("Failed: anthropic/gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2-2");
|
||||
});
|
||||
|
||||
test("second model launch command fails", async () => {
|
||||
const session = "sess-launch";
|
||||
const binary = "opencode";
|
||||
const models = ["openai/gpt-5.2", "anthropic/gpt-5-2"];
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = { ok: true, stdout: "true", stderr: "" };
|
||||
mockCommandResponses["command -v tmux"] = { ok: true, stdout: "tmux", stderr: "" };
|
||||
mockCommandResponses["command -v opencode"] = { ok: true, stdout: "opencode", stderr: "" };
|
||||
mockCommandResponses["opencode models"] = { ok: true, stdout: models.join("\n"), stderr: "" };
|
||||
mockCommandResponses[`tmux has-session -t ${session}`] = { ok: false, stdout: "", stderr: "" };
|
||||
// first model success
|
||||
const firstBranch = `opencode/${session}/gpt-5-2`;
|
||||
const firstPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2`;
|
||||
mockCommandResponses[`git show-ref --verify --quiet refs/heads/${firstBranch}`] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${firstBranch} ${firstPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`tmux new-session -d -s ${session} -n gpt-5-2 -c ${firstPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`tmux send-keys -t ${session}:gpt-5-2 ${binary} --model 'openai/gpt-5.2' C-m`] = { ok: true, stdout: "", stderr: "" };
|
||||
// second model launch fails
|
||||
const secondBranch = `opencode/${session}/gpt-5-2-2`;
|
||||
const secondPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2-2`;
|
||||
mockCommandResponses[`git show-ref --verify --quiet refs/heads/${secondBranch}`] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${secondBranch} ${secondPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`tmux new-window -d -t ${session} -n gpt-5-2-2 -c ${secondPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`tmux send-keys -t ${session}:gpt-5-2-2 ${binary} --model 'anthropic/gpt-5-2' C-m`] = { ok: false, stdout: "", stderr: "launch err" };
|
||||
mockCommandResponses[`git worktree remove -f ${secondPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git branch -D ${secondBranch}`] = { ok: true, stdout: "", stderr: "" };
|
||||
const result = await openMultiModel({ sessionName: session, models, binaryName: binary, mode: "cli" });
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.instructions).toContain("Failed: anthropic/gpt-5-2 (launch err");
|
||||
expect(result.windows).toContain("gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2-2");
|
||||
});
|
||||
|
||||
test("second model worktree path already exists", async () => {
|
||||
const session = "sess-wtpath";
|
||||
const binary = "opencode";
|
||||
const models = ["openai/gpt-5.2", "anthropic/gpt-5-2"];
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = { ok: true, stdout: "true", stderr: "" };
|
||||
mockCommandResponses["command -v tmux"] = { ok: true, stdout: "tmux", stderr: "" };
|
||||
mockCommandResponses["command -v opencode"] = { ok: true, stdout: "opencode", stderr: "" };
|
||||
mockCommandResponses["opencode models"] = { ok: true, stdout: models.join("\n"), stderr: "" };
|
||||
mockCommandResponses[`tmux has-session -t ${session}`] = { ok: false, stdout: "", stderr: "" };
|
||||
// first model success
|
||||
const firstBranch = `opencode/${session}/gpt-5-2`;
|
||||
const firstPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2`;
|
||||
mockCommandResponses[`git show-ref --verify --quiet refs/heads/${firstBranch}`] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${firstBranch} ${firstPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`tmux new-session -d -s ${session} -n gpt-5-2 -c ${firstPath}`] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`tmux send-keys -t ${session}:gpt-5-2 ${binary} --model 'openai/gpt-5.2' C-m`] = { ok: true, stdout: "", stderr: "" };
|
||||
// second model path exists
|
||||
const secondBranch = `opencode/${session}/gpt-5-2-2`;
|
||||
const secondPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2-2`;
|
||||
mockCommandResponses[`git show-ref --verify --quiet refs/heads/${secondBranch}`] = { ok: false, stdout: "", stderr: "" };
|
||||
// mock fs existsSync to return true for secondPath
|
||||
spyOn(fs, "existsSync").mockImplementation((p) => p === secondPath);
|
||||
const result = await openMultiModel({ sessionName: session, models, binaryName: binary, mode: "cli" });
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.instructions).toContain("Error: Created tmux session");
|
||||
expect(result.instructions).toContain("Failed: anthropic/gpt-5-2 (Worktree path already exists at");
|
||||
expect(result.windows).toContain("gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2-2");
|
||||
test("second model launch command fails", async () => {
|
||||
const session = "sess-launch";
|
||||
const binary = "opencode";
|
||||
const models = ["openai/gpt-5.2", "anthropic/gpt-5-2"];
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = {
|
||||
ok: true,
|
||||
stdout: "true",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v tmux"] = {
|
||||
ok: true,
|
||||
stdout: "tmux",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v opencode"] = {
|
||||
ok: true,
|
||||
stdout: "opencode",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["opencode models"] = {
|
||||
ok: true,
|
||||
stdout: models.join("\n"),
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[`tmux has-session -t ${session}`] = {
|
||||
ok: false,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
// first model success
|
||||
const firstBranch = `opencode/${session}/gpt-5-2`;
|
||||
const firstPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2`;
|
||||
mockCommandResponses[
|
||||
`git show-ref --verify --quiet refs/heads/${firstBranch}`
|
||||
] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${firstBranch} ${firstPath}`] = {
|
||||
ok: true,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[
|
||||
`tmux new-session -d -s ${session} -n gpt-5-2 -c ${firstPath}`
|
||||
] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[
|
||||
`tmux send-keys -t ${session}:gpt-5-2 ${binary} --model 'openai/gpt-5.2' C-m`
|
||||
] = { ok: true, stdout: "", stderr: "" };
|
||||
// second model launch fails
|
||||
const secondBranch = `opencode/${session}/gpt-5-2-2`;
|
||||
const secondPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2-2`;
|
||||
mockCommandResponses[
|
||||
`git show-ref --verify --quiet refs/heads/${secondBranch}`
|
||||
] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${secondBranch} ${secondPath}`] =
|
||||
{ ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[
|
||||
`tmux new-window -d -t ${session} -n gpt-5-2-2 -c ${secondPath}`
|
||||
] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[
|
||||
`tmux send-keys -t ${session}:gpt-5-2-2 ${binary} --model 'anthropic/gpt-5-2' C-m`
|
||||
] = { ok: false, stdout: "", stderr: "launch err" };
|
||||
mockCommandResponses[`git worktree remove -f ${secondPath}`] = {
|
||||
ok: true,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[`git branch -D ${secondBranch}`] = {
|
||||
ok: true,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
const result = await openMultiModel({
|
||||
sessionName: session,
|
||||
models,
|
||||
binaryName: binary,
|
||||
mode: "cli",
|
||||
});
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.instructions).toContain(
|
||||
"Failed: anthropic/gpt-5-2 (launch err",
|
||||
);
|
||||
expect(result.windows).toContain("gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2-2");
|
||||
});
|
||||
|
||||
test("second model worktree path already exists", async () => {
|
||||
const session = "sess-wtpath";
|
||||
const binary = "opencode";
|
||||
const models = ["openai/gpt-5.2", "anthropic/gpt-5-2"];
|
||||
mockCommandResponses["git rev-parse --is-inside-work-tree"] = {
|
||||
ok: true,
|
||||
stdout: "true",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v tmux"] = {
|
||||
ok: true,
|
||||
stdout: "tmux",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["command -v opencode"] = {
|
||||
ok: true,
|
||||
stdout: "opencode",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses["opencode models"] = {
|
||||
ok: true,
|
||||
stdout: models.join("\n"),
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[`tmux has-session -t ${session}`] = {
|
||||
ok: false,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
// first model success
|
||||
const firstBranch = `opencode/${session}/gpt-5-2`;
|
||||
const firstPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2`;
|
||||
mockCommandResponses[
|
||||
`git show-ref --verify --quiet refs/heads/${firstBranch}`
|
||||
] = { ok: false, stdout: "", stderr: "" };
|
||||
mockCommandResponses[`git worktree add -b ${firstBranch} ${firstPath}`] = {
|
||||
ok: true,
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
};
|
||||
mockCommandResponses[
|
||||
`tmux new-session -d -s ${session} -n gpt-5-2 -c ${firstPath}`
|
||||
] = { ok: true, stdout: "", stderr: "" };
|
||||
mockCommandResponses[
|
||||
`tmux send-keys -t ${session}:gpt-5-2 ${binary} --model 'openai/gpt-5.2' C-m`
|
||||
] = { ok: true, stdout: "", stderr: "" };
|
||||
// second model path exists
|
||||
const secondBranch = `opencode/${session}/gpt-5-2-2`;
|
||||
const secondPath = `/mock/home/.local/share/opencode/multi-model/${session}/gpt-5-2-2`;
|
||||
mockCommandResponses[
|
||||
`git show-ref --verify --quiet refs/heads/${secondBranch}`
|
||||
] = { ok: false, stdout: "", stderr: "" };
|
||||
// mock fs existsSync to return true for secondPath
|
||||
spyOn(fs, "existsSync").mockImplementation((p) => p === secondPath);
|
||||
const result = await openMultiModel({
|
||||
sessionName: session,
|
||||
models,
|
||||
binaryName: binary,
|
||||
mode: "cli",
|
||||
});
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.instructions).toContain("Error: Created tmux session");
|
||||
expect(result.instructions).toContain(
|
||||
"Failed: anthropic/gpt-5-2 (Worktree path already exists at",
|
||||
);
|
||||
expect(result.windows).toContain("gpt-5-2");
|
||||
expect(result.windows).toContain("gpt-5-2-2");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user