@polderlabs/bizar-plugin 0.6.0 → 0.6.1
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 +60 -3
- package/package.json +1 -1
- package/src/background-state.ts +41 -0
- package/src/background.ts +147 -11
- package/src/commands-impl.ts +4 -4
- package/src/commands.ts +278 -101
- package/src/reasoning-clean.ts +360 -0
- package/src/serve.ts +12 -3
- package/src/tools/bg-spawn.ts +21 -1
- package/tests/attach-handler-bug.test.ts +5 -3
- package/tests/background-state.test.ts +1 -1
- package/tests/background.test.ts +1 -1
- package/tests/block.test.ts +3 -1
- package/tests/canonical-key-order.test.ts +11 -7
- package/tests/event.test.ts +1 -1
- package/tests/fingerprint.test.ts +22 -21
- package/tests/http-client.test.ts +5 -3
- package/tests/options.test.ts +10 -8
- package/tests/settings.test.ts +2 -2
- package/tests/stall-think.test.ts +13 -12
- package/tests/state.test.ts +2 -1
- package/tests/tools/bg-spawn.test.ts +12 -12
- package/tests/update-deadlock.test.ts +1 -1
|
@@ -8,10 +8,11 @@ import { describe, test, expect } from "bun:test";
|
|
|
8
8
|
import { fingerprint } from "../src/fingerprint";
|
|
9
9
|
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
10
10
|
import path from "node:path";
|
|
11
|
+
import os from "node:os";
|
|
11
12
|
|
|
12
13
|
/** Use a real temp directory as the worktree for path normalization tests */
|
|
13
|
-
const WORKTREE = "
|
|
14
|
-
const OUTSIDE_TREE = "
|
|
14
|
+
const WORKTREE = path.join(os.tmpdir(), "bizar-fingerprint-test-worktree");
|
|
15
|
+
const OUTSIDE_TREE = path.join(os.tmpdir(), "bizar-outside-worktree");
|
|
15
16
|
|
|
16
17
|
function setupWorktree() {
|
|
17
18
|
try {
|
|
@@ -33,22 +34,22 @@ setupWorktree();
|
|
|
33
34
|
|
|
34
35
|
describe("fingerprint — stable hash", () => {
|
|
35
36
|
test("same args produce the same fingerprint", () => {
|
|
36
|
-
|
|
37
|
+
const args = { path: path.join(os.tmpdir(), "foo.ts"), recursive: false };
|
|
37
38
|
const a = fingerprint("read", args, WORKTREE);
|
|
38
39
|
const b = fingerprint("read", args, WORKTREE);
|
|
39
40
|
expect(a).toBe(b);
|
|
40
41
|
});
|
|
41
42
|
|
|
42
43
|
test("different tool name produces different fingerprint", () => {
|
|
43
|
-
|
|
44
|
+
const args = { path: path.join(os.tmpdir(), "foo.ts") };
|
|
44
45
|
const a = fingerprint("read", args, WORKTREE);
|
|
45
46
|
const b = fingerprint("edit", args, WORKTREE);
|
|
46
47
|
expect(a).not.toBe(b);
|
|
47
48
|
});
|
|
48
49
|
|
|
49
50
|
test("different args produce different fingerprint", () => {
|
|
50
|
-
const a = fingerprint("read", { path: "
|
|
51
|
-
const b = fingerprint("read", { path: "
|
|
51
|
+
const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts") }, WORKTREE);
|
|
52
|
+
const b = fingerprint("read", { path: path.join(os.tmpdir(), "bar.ts") }, WORKTREE);
|
|
52
53
|
expect(a).not.toBe(b);
|
|
53
54
|
});
|
|
54
55
|
|
|
@@ -74,7 +75,7 @@ describe("fingerprint — path normalization", () => {
|
|
|
74
75
|
const fp2 = fingerprint("read", { path: outside }, WORKTREE);
|
|
75
76
|
expect(fp1).toBe(fp2);
|
|
76
77
|
// Must NOT collide with a different outside path
|
|
77
|
-
const different = "
|
|
78
|
+
const different = path.join(os.tmpdir(), "different/path/file.txt");
|
|
78
79
|
const fp3 = fingerprint("read", { path: different }, WORKTREE);
|
|
79
80
|
expect(fp1).not.toBe(fp3);
|
|
80
81
|
});
|
|
@@ -90,38 +91,38 @@ describe("fingerprint — path normalization", () => {
|
|
|
90
91
|
|
|
91
92
|
describe("fingerprint — noise field stripping", () => {
|
|
92
93
|
test("strips timestamp fields", () => {
|
|
93
|
-
const a = fingerprint("read", { path: "
|
|
94
|
-
const b = fingerprint("read", { path: "
|
|
94
|
+
const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), createdAt: 1234567890 }, WORKTREE);
|
|
95
|
+
const b = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), createdAt: 9999999999 }, WORKTREE);
|
|
95
96
|
expect(a).toBe(b);
|
|
96
97
|
});
|
|
97
98
|
|
|
98
99
|
test("strips updatedAt timestamp fields", () => {
|
|
99
|
-
const a = fingerprint("read", { path: "
|
|
100
|
-
const b = fingerprint("read", { path: "
|
|
100
|
+
const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), updatedAt: "2024-01-01T00:00:00Z" }, WORKTREE);
|
|
101
|
+
const b = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), updatedAt: "2025-12-31T23:59:59Z" }, WORKTREE);
|
|
101
102
|
expect(a).toBe(b);
|
|
102
103
|
});
|
|
103
104
|
|
|
104
105
|
test("strips id field", () => {
|
|
105
|
-
const a = fingerprint("read", { path: "
|
|
106
|
-
const b = fingerprint("read", { path: "
|
|
106
|
+
const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), id: "abc123" }, WORKTREE);
|
|
107
|
+
const b = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), id: "xyz789" }, WORKTREE);
|
|
107
108
|
expect(a).toBe(b);
|
|
108
109
|
});
|
|
109
110
|
|
|
110
111
|
test("strips uuid field", () => {
|
|
111
|
-
const a = fingerprint("read", { path: "
|
|
112
|
-
const b = fingerprint("read", { path: "
|
|
112
|
+
const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), uuid: "550e8400-e29b-41d4-a716-446655440000" }, WORKTREE);
|
|
113
|
+
const b = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), uuid: "6ba7b810-9dad-11d1-80b4-00c04fd430c8" }, WORKTREE);
|
|
113
114
|
expect(a).toBe(b);
|
|
114
115
|
});
|
|
115
116
|
|
|
116
117
|
test("strips nonce field", () => {
|
|
117
|
-
const a = fingerprint("read", { path: "
|
|
118
|
-
const b = fingerprint("read", { path: "
|
|
118
|
+
const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), nonce: "random1" }, WORKTREE);
|
|
119
|
+
const b = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), nonce: "random2" }, WORKTREE);
|
|
119
120
|
expect(a).toBe(b);
|
|
120
121
|
});
|
|
121
122
|
|
|
122
123
|
test("strips cwd field entirely", () => {
|
|
123
|
-
const a = fingerprint("read", { path: "
|
|
124
|
-
const b = fingerprint("read", { path: "
|
|
124
|
+
const a = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), cwd: "/home/user" }, WORKTREE);
|
|
125
|
+
const b = fingerprint("read", { path: path.join(os.tmpdir(), "foo.ts"), cwd: "/completely/different" }, WORKTREE);
|
|
125
126
|
expect(a).toBe(b);
|
|
126
127
|
});
|
|
127
128
|
});
|
|
@@ -130,10 +131,10 @@ describe("fingerprint — nested objects", () => {
|
|
|
130
131
|
test("nested objects are normalized recursively", () => {
|
|
131
132
|
const a = fingerprint("edit", {
|
|
132
133
|
meta: { author: "Alice", timestamp: 1000 },
|
|
133
|
-
path: "
|
|
134
|
+
path: path.join(os.tmpdir(), "foo.ts"),
|
|
134
135
|
}, WORKTREE);
|
|
135
136
|
const b = fingerprint("edit", {
|
|
136
|
-
path: "
|
|
137
|
+
path: path.join(os.tmpdir(), "foo.ts"),
|
|
137
138
|
meta: { timestamp: 9999, author: "Alice" },
|
|
138
139
|
}, WORKTREE);
|
|
139
140
|
expect(a).toBe(b);
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { describe, it, expect } from "bun:test";
|
|
9
|
+
import os from "node:os";
|
|
10
|
+
import path from "node:path";
|
|
9
11
|
|
|
10
12
|
// ---------------------------------------------------------------------------
|
|
11
13
|
// Types that mirror the expected HttpClient API from §1 / §2
|
|
@@ -126,12 +128,12 @@ describe("HttpClient.createSession", () => {
|
|
|
126
128
|
parentID: "parent_sess",
|
|
127
129
|
title: "bgr:mimir:bgr_01",
|
|
128
130
|
agent: "mimir",
|
|
129
|
-
directory: "
|
|
131
|
+
directory: path.join(os.tmpdir(), "worktree"),
|
|
130
132
|
});
|
|
131
133
|
|
|
132
134
|
expect(session.id).toBeTruthy();
|
|
133
135
|
expect(session.projectID).toBe("proj_test");
|
|
134
|
-
expect(session.directory).toBe("
|
|
136
|
+
expect(session.directory).toBe(path.join(os.tmpdir(), "worktree"));
|
|
135
137
|
expect(session.parentID).toBe("parent_sess");
|
|
136
138
|
expect(session.title).toBe("bgr:mimir:bgr_01");
|
|
137
139
|
});
|
|
@@ -260,7 +262,7 @@ describe("HttpClient.sendPrompt", () => {
|
|
|
260
262
|
messageID: "msg_model_test",
|
|
261
263
|
prompt: "Use a specific model",
|
|
262
264
|
agent: "mimir",
|
|
263
|
-
model: { providerID: "
|
|
265
|
+
model: { providerID: "openrouter", modelID: "minimax-m3" },
|
|
264
266
|
directory: "/tmp",
|
|
265
267
|
});
|
|
266
268
|
|
package/tests/options.test.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
2
4
|
import {
|
|
3
5
|
DEFAULT_OPTIONS,
|
|
4
6
|
expandHome,
|
|
@@ -126,9 +128,9 @@ describe("normalizeOptions", () => {
|
|
|
126
128
|
});
|
|
127
129
|
|
|
128
130
|
test("custom logDir and stateDir are preserved", () => {
|
|
129
|
-
const { options } = normalizeOptions({ logDir: "
|
|
130
|
-
expect(options.logDir).toBe("
|
|
131
|
-
expect(options.stateDir).toBe("
|
|
131
|
+
const { options } = normalizeOptions({ logDir: path.join(os.tmpdir(), "my-logs"), stateDir: path.join(os.tmpdir(), "my-state") });
|
|
132
|
+
expect(options.logDir).toBe(path.join(os.tmpdir(), "my-logs"));
|
|
133
|
+
expect(options.stateDir).toBe(path.join(os.tmpdir(), "my-state"));
|
|
132
134
|
});
|
|
133
135
|
});
|
|
134
136
|
|
|
@@ -138,7 +140,7 @@ describe("findSecretDirMatch", () => {
|
|
|
138
140
|
const home = process.env.HOME ?? "/home/test";
|
|
139
141
|
|
|
140
142
|
test("returns null for safe paths", () => {
|
|
141
|
-
expect(findSecretDirMatch("
|
|
143
|
+
expect(findSecretDirMatch(path.join(os.tmpdir(), "foo"))).toBeNull();
|
|
142
144
|
expect(findSecretDirMatch("/home/user/project")).toBeNull();
|
|
143
145
|
});
|
|
144
146
|
|
|
@@ -181,8 +183,8 @@ describe("findOffendingPath", () => {
|
|
|
181
183
|
test("returns null when both paths are safe", () => {
|
|
182
184
|
const opts: NormalizedOptions = {
|
|
183
185
|
...D,
|
|
184
|
-
logDir: "
|
|
185
|
-
stateDir: "
|
|
186
|
+
logDir: path.join(os.tmpdir(), "bizar-logs"),
|
|
187
|
+
stateDir: path.join(os.tmpdir(), "bizar-state"),
|
|
186
188
|
};
|
|
187
189
|
expect(findOffendingPath(opts)).toBeNull();
|
|
188
190
|
});
|
|
@@ -192,7 +194,7 @@ describe("findOffendingPath", () => {
|
|
|
192
194
|
const opts: NormalizedOptions = {
|
|
193
195
|
...D,
|
|
194
196
|
logDir: `${home}/.ssh/evil`,
|
|
195
|
-
stateDir: "
|
|
197
|
+
stateDir: path.join(os.tmpdir(), "bizar-state"),
|
|
196
198
|
};
|
|
197
199
|
const result = findOffendingPath(opts);
|
|
198
200
|
expect(result).not.toBeNull();
|
|
@@ -204,7 +206,7 @@ describe("findOffendingPath", () => {
|
|
|
204
206
|
const home = process.env.HOME ?? "/home/test";
|
|
205
207
|
const opts: NormalizedOptions = {
|
|
206
208
|
...D,
|
|
207
|
-
logDir: "
|
|
209
|
+
logDir: path.join(os.tmpdir(), "bizar-logs"),
|
|
208
210
|
stateDir: `${home}/.aws/creds`,
|
|
209
211
|
};
|
|
210
212
|
const result = findOffendingPath(opts);
|
package/tests/settings.test.ts
CHANGED
|
@@ -44,7 +44,7 @@ class MockLogger {
|
|
|
44
44
|
error(m: string) { this.messages.push({ level: "error", message: m }); }
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
const TEST_DIR = "
|
|
47
|
+
const TEST_DIR = path.join(os.tmpdir(), "bizar-settings-test");
|
|
48
48
|
|
|
49
49
|
beforeEach(() => {
|
|
50
50
|
try { rmSync(TEST_DIR, { recursive: true, force: true }); } catch { /* ok */ }
|
|
@@ -252,7 +252,7 @@ describe("SettingsStore — file path", () => {
|
|
|
252
252
|
});
|
|
253
253
|
|
|
254
254
|
test("settings written with ~ path land in the expanded location", async () => {
|
|
255
|
-
const tmp = "
|
|
255
|
+
const tmp = path.join(os.tmpdir(), "bizar-settings-expansion-test");
|
|
256
256
|
rmSync(tmp, { recursive: true, force: true });
|
|
257
257
|
try {
|
|
258
258
|
const logger = makeLogger();
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import { describe, it, expect, beforeEach, afterEach } from "bun:test";
|
|
17
17
|
import { writeFileSync, mkdirSync, unlinkSync, rmSync } from "node:fs";
|
|
18
18
|
import path from "node:path";
|
|
19
|
+
import os from "node:os";
|
|
19
20
|
|
|
20
21
|
// ---------------------------------------------------------------------------
|
|
21
22
|
// Group 1 — researchInterventionPrompt
|
|
@@ -130,7 +131,7 @@ const silentLogger = {
|
|
|
130
131
|
};
|
|
131
132
|
|
|
132
133
|
function makeTempDir(prefix: string): string {
|
|
133
|
-
const dir =
|
|
134
|
+
const dir = path.join(os.tmpdir(), `bizar-stall-test-${prefix}-${process.pid}`);
|
|
134
135
|
mkdirSync(dir, { recursive: true });
|
|
135
136
|
return dir;
|
|
136
137
|
}
|
|
@@ -161,11 +162,11 @@ describe("BackgroundState schema backfill", () => {
|
|
|
161
162
|
agent: "mimir",
|
|
162
163
|
status: "running",
|
|
163
164
|
startedAt,
|
|
164
|
-
model: "minimax
|
|
165
|
+
model: "openrouter/minimax-m3",
|
|
165
166
|
promptPreview: "Do the thing",
|
|
166
167
|
toolCallCount: 0,
|
|
167
168
|
parentAgent: "odin",
|
|
168
|
-
logPath: "
|
|
169
|
+
logPath: path.join(os.tmpdir(), "test.log"),
|
|
169
170
|
timeoutMs: 300_000,
|
|
170
171
|
// lastEventAt is intentionally absent
|
|
171
172
|
lastToolOrTextAt: startedAt,
|
|
@@ -188,11 +189,11 @@ describe("BackgroundState schema backfill", () => {
|
|
|
188
189
|
agent: "mimir",
|
|
189
190
|
status: "running",
|
|
190
191
|
startedAt,
|
|
191
|
-
model: "minimax
|
|
192
|
+
model: "openrouter/minimax-m3",
|
|
192
193
|
promptPreview: "Do the thing",
|
|
193
194
|
toolCallCount: 0,
|
|
194
195
|
parentAgent: "odin",
|
|
195
|
-
logPath: "
|
|
196
|
+
logPath: path.join(os.tmpdir(), "test.log"),
|
|
196
197
|
timeoutMs: 300_000,
|
|
197
198
|
lastEventAt: startedAt,
|
|
198
199
|
// lastToolOrTextAt is intentionally absent
|
|
@@ -215,11 +216,11 @@ describe("BackgroundState schema backfill", () => {
|
|
|
215
216
|
agent: "mimir",
|
|
216
217
|
status: "running",
|
|
217
218
|
startedAt,
|
|
218
|
-
model: "minimax
|
|
219
|
+
model: "openrouter/minimax-m3",
|
|
219
220
|
promptPreview: "Do the thing",
|
|
220
221
|
toolCallCount: 0,
|
|
221
222
|
parentAgent: "odin",
|
|
222
|
-
logPath: "
|
|
223
|
+
logPath: path.join(os.tmpdir(), "test.log"),
|
|
223
224
|
timeoutMs: 300_000,
|
|
224
225
|
lastEventAt: startedAt,
|
|
225
226
|
lastToolOrTextAt: startedAt,
|
|
@@ -436,7 +437,7 @@ function makeBgState(overrides: Partial<BackgroundState> = {}): BackgroundState
|
|
|
436
437
|
agent: "mimir",
|
|
437
438
|
status: "running",
|
|
438
439
|
startedAt: now,
|
|
439
|
-
model: "minimax
|
|
440
|
+
model: "openrouter/minimax-m3",
|
|
440
441
|
promptPreview: "Do the thing",
|
|
441
442
|
resultPreview: undefined,
|
|
442
443
|
resultMessageIds: [],
|
|
@@ -699,11 +700,11 @@ describe("bg-status toView — v0.3.0 fields", () => {
|
|
|
699
700
|
agent: "mimir",
|
|
700
701
|
status: "running",
|
|
701
702
|
startedAt: now - 600_000,
|
|
702
|
-
model: "minimax
|
|
703
|
+
model: "openrouter/minimax-m3",
|
|
703
704
|
promptPreview: "Research X",
|
|
704
705
|
toolCallCount: 0,
|
|
705
706
|
parentAgent: "odin",
|
|
706
|
-
logPath: "
|
|
707
|
+
logPath: path.join(os.tmpdir(), "test.log"),
|
|
707
708
|
timeoutMs: 300_000,
|
|
708
709
|
lastEventAt: now - 60_000,
|
|
709
710
|
lastToolOrTextAt: now - 60_000,
|
|
@@ -728,11 +729,11 @@ describe("bg-status toView — v0.3.0 fields", () => {
|
|
|
728
729
|
agent: "mimir",
|
|
729
730
|
status: "running",
|
|
730
731
|
startedAt: now,
|
|
731
|
-
model: "minimax
|
|
732
|
+
model: "openrouter/minimax-m3",
|
|
732
733
|
promptPreview: "Research Y",
|
|
733
734
|
toolCallCount: 0,
|
|
734
735
|
parentAgent: "odin",
|
|
735
|
-
logPath: "
|
|
736
|
+
logPath: path.join(os.tmpdir(), "test.log"),
|
|
736
737
|
timeoutMs: 300_000,
|
|
737
738
|
// v0.3.0 fields are absent (no intervention yet)
|
|
738
739
|
};
|
package/tests/state.test.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { describe, test, expect, beforeEach, afterEach } from "bun:test";
|
|
|
9
9
|
import { StateStore, SessionState, EMPTY_STATE } from "../src/state";
|
|
10
10
|
import { mkdirSync, rmSync, writeFileSync, existsSync, utimesSync } from "node:fs";
|
|
11
11
|
import path from "node:path";
|
|
12
|
+
import os from "node:os";
|
|
12
13
|
|
|
13
14
|
// Minimal mock logger that collects all messages
|
|
14
15
|
class MockLogger {
|
|
@@ -18,7 +19,7 @@ class MockLogger {
|
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
const TEST_DIR = "
|
|
22
|
+
const TEST_DIR = path.join(os.tmpdir(), "bizar-state-test");
|
|
22
23
|
const TEST_SESSION_A = "session-a-123";
|
|
23
24
|
const TEST_SESSION_B = "session-b-456";
|
|
24
25
|
|
|
@@ -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. "minimax
|
|
30
|
+
`model must be in "providerID/modelID" format (e.g. "openrouter/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. "minimax
|
|
36
|
+
`model must be in "providerID/modelID" format (e.g. "openrouter/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('"minimax
|
|
136
|
-
const result = parseModel("minimax
|
|
137
|
-
expect(result).toEqual({ providerID: "
|
|
135
|
+
it('"openrouter/minimax-m3" parses to { providerID: "openrouter", modelID: "minimax-m3" }', () => {
|
|
136
|
+
const result = parseModel("openrouter/minimax-m3");
|
|
137
|
+
expect(result).toEqual({ providerID: "openrouter", modelID: "minimax-m3" });
|
|
138
138
|
});
|
|
139
139
|
|
|
140
140
|
it('"opencode/deepseek-v4-flash-free" parses correctly', () => {
|
|
@@ -142,20 +142,20 @@ describe("bizar_spawn_background — model parsing (HIGH-3, LOW-34)", () => {
|
|
|
142
142
|
expect(result).toEqual({ providerID: "opencode", modelID: "deepseek-v4-flash-free" });
|
|
143
143
|
});
|
|
144
144
|
|
|
145
|
-
it('"
|
|
146
|
-
expect(() => parseModel("
|
|
145
|
+
it('"minimax-m3" (no /) is rejected', () => {
|
|
146
|
+
expect(() => parseModel("minimax-m3")).toThrow();
|
|
147
147
|
});
|
|
148
148
|
|
|
149
149
|
it('"a/b/c" (multiple /) is rejected', () => {
|
|
150
150
|
expect(() => parseModel("a/b/c")).toThrow();
|
|
151
151
|
});
|
|
152
152
|
|
|
153
|
-
it('"
|
|
154
|
-
expect(() => parseModel("
|
|
153
|
+
it('"openrouter/" (empty modelID) is rejected', () => {
|
|
154
|
+
expect(() => parseModel("openrouter/")).toThrow();
|
|
155
155
|
});
|
|
156
156
|
|
|
157
|
-
it('"/
|
|
158
|
-
expect(() => parseModel("/
|
|
157
|
+
it('"/minimax-m3" (empty providerID) is rejected', () => {
|
|
158
|
+
expect(() => parseModel("/minimax-m3")).toThrow();
|
|
159
159
|
});
|
|
160
160
|
|
|
161
161
|
it("undefined model returns undefined (agent uses its default)", () => {
|
|
@@ -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: "minimax
|
|
171
|
+
{ agent: "mimir", prompt: "Do X", model: "openrouter/minimax-m3" },
|
|
172
172
|
{ agent: "odin", sessionID: "sess_parent", worktree: "/tmp" },
|
|
173
173
|
);
|
|
174
174
|
expect(result).not.toHaveProperty("error");
|
|
@@ -52,7 +52,7 @@ function makeDraft(overrides: Partial<AddDraft> = {}): AddDraft {
|
|
|
52
52
|
error: undefined,
|
|
53
53
|
parentAgent: "odin",
|
|
54
54
|
parentInstanceId: undefined,
|
|
55
|
-
logPath: "
|
|
55
|
+
logPath: path.join(os.tmpdir(), "bgr_deadlock_test.log"),
|
|
56
56
|
timeoutMs: 30_000,
|
|
57
57
|
toolCallCount: 0,
|
|
58
58
|
loopGuardTool: undefined,
|