@polderlabs/bizar-plugin 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/index.ts +106 -10
- package/package.json +2 -2
- package/src/background.ts +195 -76
- package/src/opencode-runner.ts +47 -19
- package/src/reasoning-clean.ts +120 -26
- package/tests/attach-handler-bug.test.ts +2 -1
- package/tests/background-state.test.ts +1 -1
- package/tests/background.test.ts +1 -1
- package/tests/reasoning-clean.test.ts +422 -0
- package/tests/stall-think.test.ts +6 -6
- package/tests/tools/bg-spawn.test.ts +6 -6
- package/tests/tools/opencode-runner.test.ts +115 -0
- package/tests/update-deadlock.test.ts +1 -0
|
@@ -162,7 +162,7 @@ describe("BackgroundState schema backfill", () => {
|
|
|
162
162
|
agent: "mimir",
|
|
163
163
|
status: "running",
|
|
164
164
|
startedAt,
|
|
165
|
-
model: "
|
|
165
|
+
model: "minimax/minimax-m3",
|
|
166
166
|
promptPreview: "Do the thing",
|
|
167
167
|
toolCallCount: 0,
|
|
168
168
|
parentAgent: "odin",
|
|
@@ -189,7 +189,7 @@ describe("BackgroundState schema backfill", () => {
|
|
|
189
189
|
agent: "mimir",
|
|
190
190
|
status: "running",
|
|
191
191
|
startedAt,
|
|
192
|
-
model: "
|
|
192
|
+
model: "minimax/minimax-m3",
|
|
193
193
|
promptPreview: "Do the thing",
|
|
194
194
|
toolCallCount: 0,
|
|
195
195
|
parentAgent: "odin",
|
|
@@ -216,7 +216,7 @@ describe("BackgroundState schema backfill", () => {
|
|
|
216
216
|
agent: "mimir",
|
|
217
217
|
status: "running",
|
|
218
218
|
startedAt,
|
|
219
|
-
model: "
|
|
219
|
+
model: "minimax/minimax-m3",
|
|
220
220
|
promptPreview: "Do the thing",
|
|
221
221
|
toolCallCount: 0,
|
|
222
222
|
parentAgent: "odin",
|
|
@@ -437,7 +437,7 @@ function makeBgState(overrides: Partial<BackgroundState> = {}): BackgroundState
|
|
|
437
437
|
agent: "mimir",
|
|
438
438
|
status: "running",
|
|
439
439
|
startedAt: now,
|
|
440
|
-
model: "
|
|
440
|
+
model: "minimax/minimax-m3",
|
|
441
441
|
promptPreview: "Do the thing",
|
|
442
442
|
resultPreview: undefined,
|
|
443
443
|
resultMessageIds: [],
|
|
@@ -700,7 +700,7 @@ describe("bg-status toView — v0.3.0 fields", () => {
|
|
|
700
700
|
agent: "mimir",
|
|
701
701
|
status: "running",
|
|
702
702
|
startedAt: now - 600_000,
|
|
703
|
-
model: "
|
|
703
|
+
model: "minimax/minimax-m3",
|
|
704
704
|
promptPreview: "Research X",
|
|
705
705
|
toolCallCount: 0,
|
|
706
706
|
parentAgent: "odin",
|
|
@@ -729,7 +729,7 @@ describe("bg-status toView — v0.3.0 fields", () => {
|
|
|
729
729
|
agent: "mimir",
|
|
730
730
|
status: "running",
|
|
731
731
|
startedAt: now,
|
|
732
|
-
model: "
|
|
732
|
+
model: "minimax/minimax-m3",
|
|
733
733
|
promptPreview: "Research Y",
|
|
734
734
|
toolCallCount: 0,
|
|
735
735
|
parentAgent: "odin",
|
|
@@ -27,13 +27,13 @@ function parseModel(model: string | undefined): { providerID: string; modelID: s
|
|
|
27
27
|
const parts = model.split("/");
|
|
28
28
|
if (parts.length !== 2) {
|
|
29
29
|
throw new Error(
|
|
30
|
-
`model must be in "providerID/modelID" format (e.g. "
|
|
30
|
+
`model must be in "providerID/modelID" format (e.g. "minimax/minimax-m3"). Omit to use the agent's default.`,
|
|
31
31
|
);
|
|
32
32
|
}
|
|
33
33
|
const [providerID, modelID] = parts;
|
|
34
34
|
if (!providerID || !modelID) {
|
|
35
35
|
throw new Error(
|
|
36
|
-
`model must be in "providerID/modelID" format (e.g. "
|
|
36
|
+
`model must be in "providerID/modelID" format (e.g. "minimax/minimax-m3"). Omit to use the agent's default.`,
|
|
37
37
|
);
|
|
38
38
|
}
|
|
39
39
|
return { providerID, modelID };
|
|
@@ -132,9 +132,9 @@ describe("bizar_spawn_background — Odin-only", () => {
|
|
|
132
132
|
// ---------------------------------------------------------------------------
|
|
133
133
|
|
|
134
134
|
describe("bizar_spawn_background — model parsing (HIGH-3, LOW-34)", () => {
|
|
135
|
-
it('"
|
|
136
|
-
const result = parseModel("
|
|
137
|
-
expect(result).toEqual({ providerID: "
|
|
135
|
+
it('"minimax/minimax-m3" parses to { providerID: "minimax", modelID: "minimax-m3" }', () => {
|
|
136
|
+
const result = parseModel("minimax/minimax-m3");
|
|
137
|
+
expect(result).toEqual({ providerID: "minimax", modelID: "minimax-m3" });
|
|
138
138
|
});
|
|
139
139
|
|
|
140
140
|
it('"opencode/deepseek-v4-flash-free" parses correctly', () => {
|
|
@@ -168,7 +168,7 @@ describe("bizar_spawn_background — model parsing (HIGH-3, LOW-34)", () => {
|
|
|
168
168
|
|
|
169
169
|
it("spawn tool includes parsed model in POST /session body", () => {
|
|
170
170
|
const result = bizarre_spawn_background(
|
|
171
|
-
{ agent: "mimir", prompt: "Do X", model: "
|
|
171
|
+
{ agent: "mimir", prompt: "Do X", model: "minimax/minimax-m3" },
|
|
172
172
|
{ agent: "odin", sessionID: "sess_parent", worktree: "/tmp" },
|
|
173
173
|
);
|
|
174
174
|
expect(result).not.toHaveProperty("error");
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* plugins/bizar/tests/tools/opencode-runner.test.ts
|
|
3
|
+
*
|
|
4
|
+
* Unit tests for `buildOpencodeRunArgs` — the pure helper extracted
|
|
5
|
+
* from `plugins/bizar/src/opencode-runner.ts` so the argv passed to
|
|
6
|
+
* `Bun.spawn(["opencode", "run", ...])` can be asserted without
|
|
7
|
+
* spawning a real process.
|
|
8
|
+
*
|
|
9
|
+
* These tests pin the two regressions that motivated the extraction:
|
|
10
|
+
*
|
|
11
|
+
* 1. Bug 1 (HIGH): the `--agent` flag was missing from the args list,
|
|
12
|
+
* so `opencode run` silently fell back to the opencode default
|
|
13
|
+
* agent and broke session attribution.
|
|
14
|
+
*
|
|
15
|
+
* 2. Bug 2 (HIGH): the OpenRouter model IDs were renamed. Tests assert
|
|
16
|
+
* the new `minimax/minimax-m3` / `minimax/minimax-m2.7` format so
|
|
17
|
+
* a stale `openrouter/minimax-m3` reference is caught immediately.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { describe, it, expect } from "bun:test";
|
|
21
|
+
import {
|
|
22
|
+
buildOpencodeRunArgs,
|
|
23
|
+
type SpawnAgentOptions,
|
|
24
|
+
} from "../../src/opencode-runner";
|
|
25
|
+
|
|
26
|
+
function baseOpts(overrides: Partial<SpawnAgentOptions> = {}): SpawnAgentOptions {
|
|
27
|
+
return {
|
|
28
|
+
agent: "thor",
|
|
29
|
+
prompt: "Investigate the auth module",
|
|
30
|
+
worktree: "/tmp/worktree",
|
|
31
|
+
logPath: "/tmp/worktree/.bgr/log.log",
|
|
32
|
+
...overrides,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe("buildOpencodeRunArgs — Bug 1 regression: --agent flag", () => {
|
|
37
|
+
it("argv contains the --agent flag followed by the agent name", () => {
|
|
38
|
+
const args = buildOpencodeRunArgs(baseOpts({ agent: "thor" }));
|
|
39
|
+
const i = args.indexOf("--agent");
|
|
40
|
+
expect(i).toBeGreaterThanOrEqual(0);
|
|
41
|
+
expect(args[i + 1]).toBe("thor");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("--agent value matches opts.agent exactly (no default fallback)", () => {
|
|
45
|
+
for (const agent of ["mimir", "thor", "tyr", "heimdall", "hermod"]) {
|
|
46
|
+
const args = buildOpencodeRunArgs(baseOpts({ agent }));
|
|
47
|
+
expect(args[args.indexOf("--agent") + 1]).toBe(agent);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("throws a clear error when opts.agent is empty", () => {
|
|
52
|
+
expect(() => buildOpencodeRunArgs(baseOpts({ agent: "" }))).toThrow(
|
|
53
|
+
/agent is required/,
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe("buildOpencodeRunArgs — Bug 2 regression: migrated model ID", () => {
|
|
59
|
+
it("emits --model with the migrated 'minimax/minimax-m3' ID", () => {
|
|
60
|
+
const args = buildOpencodeRunArgs(
|
|
61
|
+
baseOpts({
|
|
62
|
+
model: { providerID: "minimax", modelID: "minimax-m3" },
|
|
63
|
+
}),
|
|
64
|
+
);
|
|
65
|
+
const i = args.indexOf("--model");
|
|
66
|
+
expect(i).toBeGreaterThanOrEqual(0);
|
|
67
|
+
expect(args[i + 1]).toBe("minimax/minimax-m3");
|
|
68
|
+
// The full flag pair proves the migration target — the OLD ID would
|
|
69
|
+
// be 'openrouter/minimax-m3'; the NEW ID is 'minimax/minimax-m3'.
|
|
70
|
+
expect(args[i + 1]).not.toBe("openrouter/minimax-m3");
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("emits --model with the migrated 'minimax/minimax-m2.7' ID", () => {
|
|
74
|
+
const args = buildOpencodeRunArgs(
|
|
75
|
+
baseOpts({
|
|
76
|
+
model: { providerID: "minimax", modelID: "minimax-m2.7" },
|
|
77
|
+
}),
|
|
78
|
+
);
|
|
79
|
+
expect(args[args.indexOf("--model") + 1]).toBe("minimax/minimax-m2.7");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("omits --model entirely when opts.model is not provided", () => {
|
|
83
|
+
const args = buildOpencodeRunArgs(baseOpts({ model: undefined }));
|
|
84
|
+
expect(args).not.toContain("--model");
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe("buildOpencodeRunArgs — arg layout", () => {
|
|
89
|
+
it("starts with 'opencode' 'run'", () => {
|
|
90
|
+
const args = buildOpencodeRunArgs(baseOpts());
|
|
91
|
+
expect(args[0]).toBe("opencode");
|
|
92
|
+
expect(args[1]).toBe("run");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("appends prompt after the -- separator", () => {
|
|
96
|
+
const args = buildOpencodeRunArgs(baseOpts({ prompt: "do the thing" }));
|
|
97
|
+
const sep = args.indexOf("--");
|
|
98
|
+
expect(sep).toBeGreaterThanOrEqual(0);
|
|
99
|
+
expect(args[sep + 1]).toBe("do the thing");
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("uses opts.title when provided, else defaults to bgr:<agent>:<ts>", () => {
|
|
103
|
+
const a = buildOpencodeRunArgs(baseOpts({ title: "custom title" }));
|
|
104
|
+
expect(a[a.indexOf("--title") + 1]).toBe("custom title");
|
|
105
|
+
|
|
106
|
+
const b = buildOpencodeRunArgs(baseOpts({ agent: "mimir" }));
|
|
107
|
+
expect(b[b.indexOf("--title") + 1]).toMatch(/^bgr:mimir:\d+$/);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("wires --dir to opts.worktree and --log-level to INFO", () => {
|
|
111
|
+
const args = buildOpencodeRunArgs(baseOpts({ worktree: "/srv/repo" }));
|
|
112
|
+
expect(args[args.indexOf("--dir") + 1]).toBe("/srv/repo");
|
|
113
|
+
expect(args[args.indexOf("--log-level") + 1]).toBe("INFO");
|
|
114
|
+
});
|
|
115
|
+
});
|