@polderlabs/bizar 10.6.0 → 10.7.0
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/bizar-dash/tests/memory-protocol-drift.test.mjs +18 -11
- package/cli/__tests__/feature-list-bridge.test.mjs +42 -42
- package/cli/agent-browser-up.sh +35 -35
- package/cli/agent-browser-update.mjs +42 -42
- package/cli/agent-browser-update.test.mjs +7 -7
- package/cli/audit.mjs +3 -3
- package/cli/bin.mjs +10 -10
- package/cli/bootstrap.mjs +1 -1
- package/cli/cli-commands-validation.test.mjs +2 -2
- package/cli/commands/claim.mjs +3 -3
- package/cli/commands/claude-cmd.mjs +3 -3
- package/cli/commands/eval.mjs +6 -6
- package/cli/commands/util.mjs +18 -18
- package/cli/commands/validate.mjs +10 -10
- package/cli/init.mjs +1 -1
- package/cli/install/postinstall.mjs +4 -4
- package/cli/plow-through.test.mjs +7 -6
- package/cli/prompts.mjs +11 -11
- package/cli/provision.mjs +4 -16
- package/config/skills/bizar/SKILL.md +1 -1
- package/config/skills/skillopt/SKILL.md +129 -0
- package/config/skills/thinking-archetypes/SKILL.md +90 -0
- package/config/skills/thinking-bayesian/SKILL.md +267 -0
- package/config/skills/thinking-bounded-rationality/SKILL.md +406 -0
- package/config/skills/thinking-circle-of-competence/SKILL.md +216 -0
- package/config/skills/thinking-cynefin/SKILL.md +70 -0
- package/config/skills/thinking-debiasing/SKILL.md +192 -0
- package/config/skills/thinking-dual-process/SKILL.md +282 -0
- package/config/skills/thinking-effectuation/SKILL.md +366 -0
- package/config/skills/thinking-feedback-loops/SKILL.md +464 -0
- package/config/skills/thinking-fermi-estimation/SKILL.md +263 -0
- package/config/skills/thinking-first-principles/SKILL.md +167 -0
- package/config/skills/thinking-five-whys-plus/SKILL.md +139 -0
- package/config/skills/thinking-inversion/SKILL.md +195 -0
- package/config/skills/thinking-jobs-to-be-done/SKILL.md +363 -0
- package/config/skills/thinking-kepner-tregoe/SKILL.md +154 -0
- package/config/skills/thinking-leverage-points/SKILL.md +390 -0
- package/config/skills/thinking-lindy-effect/SKILL.md +331 -0
- package/config/skills/thinking-map-territory/SKILL.md +111 -0
- package/config/skills/thinking-margin-of-safety/SKILL.md +330 -0
- package/config/skills/thinking-model-combination/SKILL.md +406 -0
- package/config/skills/thinking-model-router/SKILL.md +360 -0
- package/config/skills/thinking-model-selection/SKILL.md +341 -0
- package/config/skills/thinking-occams-razor/SKILL.md +129 -0
- package/config/skills/thinking-ooda/SKILL.md +127 -0
- package/config/skills/thinking-opportunity-cost/SKILL.md +360 -0
- package/config/skills/thinking-pre-mortem/SKILL.md +170 -0
- package/config/skills/thinking-probabilistic/SKILL.md +324 -0
- package/config/skills/thinking-red-team/SKILL.md +142 -0
- package/config/skills/thinking-regret-minimization/SKILL.md +335 -0
- package/config/skills/thinking-reversibility/SKILL.md +326 -0
- package/config/skills/thinking-scientific-method/SKILL.md +162 -0
- package/config/skills/thinking-second-order/SKILL.md +184 -0
- package/config/skills/thinking-socratic/SKILL.md +198 -0
- package/config/skills/thinking-steel-manning/SKILL.md +332 -0
- package/config/skills/thinking-systems/SKILL.md +238 -0
- package/config/skills/thinking-theory-of-constraints/SKILL.md +338 -0
- package/config/skills/thinking-thought-experiment/SKILL.md +354 -0
- package/config/skills/thinking-triz/SKILL.md +171 -0
- package/config/skills/thinking-via-negativa/SKILL.md +358 -0
- package/package.json +2 -3
- package/packages/sdk/dist/consensus/index.js +4 -4
- package/packages/sdk/dist/router/agent-model-registry.js +2 -2
- package/packages/sdk/dist/router/index.d.ts +3 -3
- package/packages/sdk/dist/router/index.js +4 -4
- package/packages/sdk/dist/router/q-learning-router.d.ts +2 -2
- package/packages/sdk/dist/router/q-learning-router.js +18 -18
- package/scripts/bh-full-e2e.mjs +10 -8
- package/scripts/check-agents.mjs +27 -24
- package/scripts/mirror-claude-md.sh +0 -0
- package/scripts/sync-skills-mirror.mjs +113 -0
- package/scripts/verify-thinking-skills.mjs +135 -0
- package/config/agents/_shared/AGENT_BASELINE.md +0 -155
- package/config/agents/_shared/CLINE_TOOLS.md +0 -398
- package/config/agents/_shared/SKILLS.md +0 -109
- package/config/agents/agent-browser.md +0 -90
- package/config/agents/baldr.md +0 -60
- package/config/agents/forseti.md +0 -60
- package/config/agents/frigg.md +0 -52
- package/config/agents/heimdall.md +0 -44
- package/config/agents/hermod.md +0 -64
- package/config/agents/mimir.md +0 -60
- package/config/agents/odin.md +0 -310
- package/config/agents/quick.md +0 -47
- package/config/agents/semble-search.md +0 -59
- package/config/agents/thor.md +0 -64
- package/config/agents/tyr.md +0 -67
- package/config/agents/vidarr.md +0 -65
- package/config/agents/vor.md +0 -62
- package/config/commands/audit.md +0 -5
- package/config/commands/bizar.md +0 -22
- package/config/commands/explain.md +0 -5
- package/config/commands/init.md +0 -26
- package/config/commands/learn.md +0 -5
- package/config/commands/plan.md +0 -30
- package/config/commands/plow-through.md +0 -47
- package/config/commands/pr-review.md +0 -5
- package/config/commands/setup-provider.md +0 -95
- package/config/commands/tailscale-serve.md +0 -97
- package/config/commands/team.md +0 -124
- package/config/commands/test.md +0 -60
- package/config/commands/validate.md +0 -66
- package/config/commands/visual-plan.md +0 -19
- package/config/hooks/PostToolUse +0 -66
- package/config/hooks/PreToolUse +0 -82
- package/config/hooks/README.md +0 -68
- package/config/hooks/TaskResume +0 -48
- package/config/hooks/TaskStart +0 -47
- package/config/hooks/UserPromptSubmit +0 -55
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* cli/
|
|
2
|
+
* cli/kevin-update.mjs
|
|
3
3
|
*
|
|
4
|
-
* v6.0.0 — Install / update / verify the `
|
|
4
|
+
* v6.0.0 — Install / update / verify the `kevin` CLI.
|
|
5
5
|
*
|
|
6
|
-
* `
|
|
6
|
+
* `kevin` is a native Rust CLI from vercel-labs (~38K★) that
|
|
7
7
|
* gives Bizar agents a complete browser-automation surface:
|
|
8
8
|
* - 100+ typed CLI commands (open, snapshot, click, fill, screenshot, ...)
|
|
9
|
-
* - Native MCP stdio server (`
|
|
9
|
+
* - Native MCP stdio server (`kevin mcp`)
|
|
10
10
|
* - Self-healing snapshot-based element refs (`@e2`)
|
|
11
11
|
* - Plugin system (vault, recorder, ...)
|
|
12
12
|
* - Vercel AI SDK + AI Gateway integration
|
|
13
13
|
*
|
|
14
14
|
* This module is the single source of truth for installing and
|
|
15
|
-
* updating `
|
|
15
|
+
* updating `kevin`. It is used by:
|
|
16
16
|
* - cli/install.mjs (during `bizar install`)
|
|
17
17
|
* - cli/provision.mjs (during `bizar update`)
|
|
18
|
-
* - cli/
|
|
19
|
-
* run it shells to `npm install -g
|
|
18
|
+
* - cli/kevin-up.sh (the bash idempotent starter; on first
|
|
19
|
+
* run it shells to `npm install -g kevin` if the binary
|
|
20
20
|
* is missing — this module is the rich equivalent)
|
|
21
21
|
*
|
|
22
22
|
* Public API:
|
|
@@ -36,12 +36,12 @@ import { homedir } from 'node:os';
|
|
|
36
36
|
import chalk from 'chalk';
|
|
37
37
|
|
|
38
38
|
const DEFAULT_DAEMON_PORT = 9223;
|
|
39
|
-
const DEFAULT_PROFILE_DIR = join(homedir(), '.
|
|
39
|
+
const DEFAULT_PROFILE_DIR = join(homedir(), '.kevin', 'profile');
|
|
40
40
|
|
|
41
41
|
// ── detection ──────────────────────────────────────────────────────────
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* Probe the current
|
|
44
|
+
* Probe the current kevin install without modifying anything.
|
|
45
45
|
*
|
|
46
46
|
* Returns a structured state object:
|
|
47
47
|
* {
|
|
@@ -79,7 +79,7 @@ export function detectState() {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
// 3. Check Chrome for Testing
|
|
82
|
-
const chromeDir = join(homedir(), '.cache', '
|
|
82
|
+
const chromeDir = join(homedir(), '.cache', 'kevin', 'chrome');
|
|
83
83
|
if (existsSync(chromeDir)) state.chromeReady = true;
|
|
84
84
|
|
|
85
85
|
// 4. Check daemon (read env on every call so tests can override)
|
|
@@ -97,17 +97,17 @@ function findAgentBrowserBin() {
|
|
|
97
97
|
}
|
|
98
98
|
// 2. Well-known npm-global locations
|
|
99
99
|
const candidates = [
|
|
100
|
-
'/usr/local/bin/
|
|
101
|
-
'/opt/homebrew/bin/
|
|
102
|
-
join(homedir(), '.local', 'bin', '
|
|
103
|
-
join(homedir(), '.npm', 'bin', '
|
|
100
|
+
'/usr/local/bin/kevin',
|
|
101
|
+
'/opt/homebrew/bin/kevin',
|
|
102
|
+
join(homedir(), '.local', 'bin', 'kevin'),
|
|
103
|
+
join(homedir(), '.npm', 'bin', 'kevin'),
|
|
104
104
|
];
|
|
105
105
|
for (const c of candidates) {
|
|
106
106
|
if (existsSync(c)) return c;
|
|
107
107
|
}
|
|
108
108
|
// 3. PATH lookup
|
|
109
109
|
try {
|
|
110
|
-
const r = execSync('command -v
|
|
110
|
+
const r = execSync('command -v kevin', { encoding: 'utf8', timeout: 2_000 }).trim();
|
|
111
111
|
if (r && existsSync(r)) return r;
|
|
112
112
|
} catch {
|
|
113
113
|
// fall through
|
|
@@ -130,7 +130,7 @@ function isDaemonUp(port) {
|
|
|
130
130
|
// ── install / update ───────────────────────────────────────────────────
|
|
131
131
|
|
|
132
132
|
/**
|
|
133
|
-
* Install
|
|
133
|
+
* Install kevin. Idempotent: skips steps that are already
|
|
134
134
|
* complete. Returns the updated state.
|
|
135
135
|
*
|
|
136
136
|
* @param {object} opts
|
|
@@ -145,7 +145,7 @@ export function install(opts = {}) {
|
|
|
145
145
|
|
|
146
146
|
const before = detectState();
|
|
147
147
|
if (before.installed) {
|
|
148
|
-
log(`
|
|
148
|
+
log(`kevin ${before.version} already installed at ${before.bin}`);
|
|
149
149
|
if (startDaemon && !before.daemonRunning) {
|
|
150
150
|
log('daemon is down — bringing it up');
|
|
151
151
|
ensureRunning({ silent, dryRun });
|
|
@@ -153,28 +153,28 @@ export function install(opts = {}) {
|
|
|
153
153
|
return detectState();
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
log(`Installing
|
|
156
|
+
log(`Installing kevin from npm (channel: ${channel})...`);
|
|
157
157
|
if (dryRun) {
|
|
158
|
-
log(`[DRY RUN] would run: npm install -g
|
|
158
|
+
log(`[DRY RUN] would run: npm install -g kevin@${channel}`);
|
|
159
159
|
// In dry-run, the binary may not be on PATH. Just return the
|
|
160
160
|
// current state (which includes installed=false) without checking
|
|
161
161
|
// for the after-install state.
|
|
162
162
|
return detectState();
|
|
163
163
|
} else {
|
|
164
|
-
const r = spawnSync('npm', ['install', '-g', `
|
|
164
|
+
const r = spawnSync('npm', ['install', '-g', `kevin@${channel}`], {
|
|
165
165
|
stdio: silent ? 'ignore' : 'inherit',
|
|
166
166
|
timeout: 180_000,
|
|
167
167
|
});
|
|
168
168
|
if (r.status !== 0) {
|
|
169
|
-
throw new Error(`npm install -g
|
|
169
|
+
throw new Error(`npm install -g kevin@${channel} failed (exit ${r.status})`);
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
const after = detectState();
|
|
174
174
|
if (!after.installed) {
|
|
175
|
-
throw new Error('
|
|
175
|
+
throw new Error('kevin still not on PATH after install');
|
|
176
176
|
}
|
|
177
|
-
log(`
|
|
177
|
+
log(`kevin ${after.version} installed`);
|
|
178
178
|
|
|
179
179
|
log('Downloading Chrome for Testing...');
|
|
180
180
|
if (!dryRun) {
|
|
@@ -183,7 +183,7 @@ export function install(opts = {}) {
|
|
|
183
183
|
timeout: 300_000,
|
|
184
184
|
});
|
|
185
185
|
if (r.status !== 0) {
|
|
186
|
-
log(chalk.yellow('Chrome download failed — you can retry with `
|
|
186
|
+
log(chalk.yellow('Chrome download failed — you can retry with `kevin install`'));
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
189
|
|
|
@@ -194,9 +194,9 @@ export function install(opts = {}) {
|
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
/**
|
|
197
|
-
* Update
|
|
197
|
+
* Update kevin to the latest version. Idempotent.
|
|
198
198
|
*
|
|
199
|
-
* Same shape as install() but uses `
|
|
199
|
+
* Same shape as install() but uses `kevin upgrade` after the
|
|
200
200
|
* first install (which knows how to detect the install method and run
|
|
201
201
|
* the right update command).
|
|
202
202
|
*/
|
|
@@ -206,38 +206,38 @@ export function update(opts = {}) {
|
|
|
206
206
|
|
|
207
207
|
const before = detectState();
|
|
208
208
|
if (!before.installed) {
|
|
209
|
-
log('
|
|
209
|
+
log('kevin not installed — calling install()');
|
|
210
210
|
return install(opts);
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
log(`
|
|
213
|
+
log(`kevin ${before.version} is installed. Upgrading to ${channel}...`);
|
|
214
214
|
if (dryRun) {
|
|
215
|
-
log(`[DRY RUN] would run:
|
|
215
|
+
log(`[DRY RUN] would run: kevin upgrade`);
|
|
216
216
|
return detectState();
|
|
217
217
|
} else {
|
|
218
|
-
// First, try `
|
|
218
|
+
// First, try `kevin upgrade` (the self-updater). If it
|
|
219
219
|
// doesn't exist (older version), fall back to `npm update -g`.
|
|
220
220
|
const r = spawnSync(before.bin, ['upgrade'], {
|
|
221
221
|
stdio: silent ? 'ignore' : 'inherit',
|
|
222
222
|
timeout: 180_000,
|
|
223
223
|
});
|
|
224
224
|
if (r.status !== 0) {
|
|
225
|
-
log('`
|
|
226
|
-
const r2 = spawnSync('npm', ['update', '-g', `
|
|
225
|
+
log('`kevin upgrade` failed — falling back to `npm update -g`');
|
|
226
|
+
const r2 = spawnSync('npm', ['update', '-g', `kevin@${channel}`], {
|
|
227
227
|
stdio: silent ? 'ignore' : 'inherit',
|
|
228
228
|
timeout: 180_000,
|
|
229
229
|
});
|
|
230
230
|
if (r2.status !== 0) {
|
|
231
|
-
throw new Error(`npm update -g
|
|
231
|
+
throw new Error(`npm update -g kevin@${channel} failed (exit ${r2.status})`);
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
const after = detectState();
|
|
237
237
|
if (after.version === before.version) {
|
|
238
|
-
log(`
|
|
238
|
+
log(`kevin already at latest (${after.version})`);
|
|
239
239
|
} else {
|
|
240
|
-
log(`
|
|
240
|
+
log(`kevin updated: ${before.version} → ${after.version}`);
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
if (startDaemon && !after.daemonRunning) {
|
|
@@ -249,10 +249,10 @@ export function update(opts = {}) {
|
|
|
249
249
|
// ── daemon management ──────────────────────────────────────────────────
|
|
250
250
|
|
|
251
251
|
/**
|
|
252
|
-
* Bring the
|
|
252
|
+
* Bring the kevin daemon up if it's down. Idempotent.
|
|
253
253
|
*
|
|
254
254
|
* On macOS, Linux, and Windows, the daemon is started as a background
|
|
255
|
-
* process using `
|
|
255
|
+
* process using `kevin serve`. On success, the daemon listens
|
|
256
256
|
* on `http://127.0.0.1:<port>` and is reachable via the typed CLI
|
|
257
257
|
* and the MCP stdio server.
|
|
258
258
|
*/
|
|
@@ -262,7 +262,7 @@ export function ensureRunning(opts = {}) {
|
|
|
262
262
|
|
|
263
263
|
const state = detectState();
|
|
264
264
|
if (!state.installed) {
|
|
265
|
-
log('
|
|
265
|
+
log('kevin is not installed — call install() first');
|
|
266
266
|
return state;
|
|
267
267
|
}
|
|
268
268
|
if (state.daemonRunning) {
|
|
@@ -297,7 +297,7 @@ export function ensureRunning(opts = {}) {
|
|
|
297
297
|
}
|
|
298
298
|
spawnSync('sleep', ['0.1']);
|
|
299
299
|
}
|
|
300
|
-
log(chalk.yellow('daemon did not bind within 5s — check `
|
|
300
|
+
log(chalk.yellow('daemon did not bind within 5s — check `kevin doctor`'));
|
|
301
301
|
return detectState();
|
|
302
302
|
}
|
|
303
303
|
|
|
@@ -309,14 +309,14 @@ export function ensureRunning(opts = {}) {
|
|
|
309
309
|
export function printStatus() {
|
|
310
310
|
const s = detectState();
|
|
311
311
|
if (!s.installed) {
|
|
312
|
-
console.log(chalk.yellow('
|
|
313
|
-
console.log(chalk.dim(' Install with: npm install -g
|
|
312
|
+
console.log(chalk.yellow(' kevin: NOT INSTALLED'));
|
|
313
|
+
console.log(chalk.dim(' Install with: npm install -g kevin && kevin install'));
|
|
314
314
|
} else {
|
|
315
315
|
const daemonTxt = s.daemonRunning
|
|
316
316
|
? chalk.green('running')
|
|
317
317
|
: chalk.yellow('stopped');
|
|
318
318
|
const chromeTxt = s.chromeReady ? chalk.green('ready') : chalk.yellow('not installed');
|
|
319
|
-
console.log(`
|
|
319
|
+
console.log(` kevin ${chalk.cyan(s.version)} · daemon: ${daemonTxt} (port ${s.daemonPort}) · chrome: ${chromeTxt}`);
|
|
320
320
|
}
|
|
321
321
|
return s;
|
|
322
322
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* cli/
|
|
2
|
+
* cli/kevin-update.test.mjs
|
|
3
3
|
*
|
|
4
|
-
* Unit tests for the v6.0.0
|
|
4
|
+
* Unit tests for the v6.0.0 kevin install/update module.
|
|
5
5
|
* Uses node:test (no `expect` — uses `assert` instead).
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -14,9 +14,9 @@ const {
|
|
|
14
14
|
install,
|
|
15
15
|
update,
|
|
16
16
|
ensureRunning,
|
|
17
|
-
} = await import("./
|
|
17
|
+
} = await import("./kevin-update.mjs");
|
|
18
18
|
|
|
19
|
-
describe("
|
|
19
|
+
describe("kevin-update", () => {
|
|
20
20
|
it("exports the public API", () => {
|
|
21
21
|
assert.equal(typeof detectState, "function");
|
|
22
22
|
assert.equal(typeof printStatus, "function");
|
|
@@ -42,9 +42,9 @@ describe("agent-browser-update", () => {
|
|
|
42
42
|
}
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
it("detectState profileDir points to ~/.
|
|
45
|
+
it("detectState profileDir points to ~/.kevin/profile by default", () => {
|
|
46
46
|
const s = detectState();
|
|
47
|
-
assert.match(s.profileDir, /\.
|
|
47
|
+
assert.match(s.profileDir, /\.kevin\/profile$/);
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
it("detectState default daemon port is 9223", () => {
|
|
@@ -63,7 +63,7 @@ describe("agent-browser-update", () => {
|
|
|
63
63
|
console.log = origLog;
|
|
64
64
|
}
|
|
65
65
|
assert.ok(captured.length > 0);
|
|
66
|
-
assert.match(captured[0], /
|
|
66
|
+
assert.match(captured[0], /kevin/);
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
it("install with dryRun=true returns a state object", () => {
|
package/cli/audit.mjs
CHANGED
|
@@ -28,7 +28,7 @@ export async function runAudit() {
|
|
|
28
28
|
const lines = content.split('\n');
|
|
29
29
|
|
|
30
30
|
// Check 1: Dangerous bash permissions on review-only agents
|
|
31
|
-
if (file.includes('
|
|
31
|
+
if (file.includes('linda') || file.includes('oscar')) {
|
|
32
32
|
if (content.includes('bash: allow')) {
|
|
33
33
|
issues.push({ path, severity: 'HIGH', msg: 'Review-only agent has bash permission' });
|
|
34
34
|
}
|
|
@@ -38,7 +38,7 @@ export async function runAudit() {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
// Check 2: Frigg should never have edit/write
|
|
41
|
-
if (file.includes('
|
|
41
|
+
if (file.includes('susan')) {
|
|
42
42
|
if (content.includes('edit: allow')) {
|
|
43
43
|
issues.push({ path, severity: 'HIGH', msg: 'Read-only Q&A agent (Frigg) has edit permission' });
|
|
44
44
|
}
|
|
@@ -48,7 +48,7 @@ export async function runAudit() {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// Check 3: Odin should have minimal permissions
|
|
51
|
-
if (file.includes('
|
|
51
|
+
if (file.includes('mike')) {
|
|
52
52
|
const dangerousForOdin = ['bash', 'edit', 'write', 'glob', 'grep', 'question'];
|
|
53
53
|
for (const tool of dangerousForOdin) {
|
|
54
54
|
if (content.includes(`${tool}: allow`)) {
|
package/cli/bin.mjs
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* Commands:
|
|
14
14
|
* install, audit, init, export, artifact, update, test-gate, service, dash,
|
|
15
15
|
* memory, minimax, usage, mod, doctor, repair, dev-link, dev-unlink,
|
|
16
|
-
* heads-up, bg,
|
|
16
|
+
* heads-up, bg, kevin, kevin-up, providers, deploy, plugin,
|
|
17
17
|
* marketplace, plan, digest, backup, restore, clip, ocr, voice, workspace, eval
|
|
18
18
|
*/
|
|
19
19
|
import chalk from 'chalk';
|
|
@@ -148,8 +148,8 @@ function showHelp() {
|
|
|
148
148
|
deploy One-click deploy to Vercel, Cloudflare, Fly.io, or Docker
|
|
149
149
|
plugin <subcommand> Manage marketplace plugins (search/install/config/invoke)
|
|
150
150
|
marketplace <subcommand> Browse and install plugins from the public marketplace
|
|
151
|
-
|
|
152
|
-
|
|
151
|
+
kevin Install / update / verify the kevin CLI
|
|
152
|
+
kevin-up Start Chromium for kevin (start/stop/status)
|
|
153
153
|
providers detect Auto-detect provider API keys from env + ~/.claude/settings.json
|
|
154
154
|
clip <subcommand> Manage web clipper saved clips (list/delete/configure)
|
|
155
155
|
ocr <subcommand> OCR operations on images (list/process/configure)
|
|
@@ -245,21 +245,21 @@ async function main() {
|
|
|
245
245
|
const UTIL_COMMANDS = new Set([
|
|
246
246
|
'audit', 'init', 'export', 'test-gate', 'dev-link', 'dev-unlink',
|
|
247
247
|
'doctor', 'repair', 'heads-up', 'bg', 'digest', 'backup', 'restore',
|
|
248
|
-
'
|
|
248
|
+
'kevin', 'update', 'providers', 'plan', 'validate',
|
|
249
249
|
'setup-provider', 'config', 'history', 'hub', 'hook',
|
|
250
250
|
'team', 'subagent', 'rca',
|
|
251
251
|
]);
|
|
252
|
-
const UTIL_ALIASES = new Set(['dashboard', '
|
|
252
|
+
const UTIL_ALIASES = new Set(['dashboard', 'kevin-up']);
|
|
253
253
|
let mod;
|
|
254
254
|
if (UTIL_COMMANDS.has(cmd)) {
|
|
255
255
|
// util-based commands: audit, init, etc.
|
|
256
256
|
mod = await importCommand('util');
|
|
257
257
|
} else if (UTIL_ALIASES.has(cmd)) {
|
|
258
|
-
// util aliases: dashboard → dash,
|
|
258
|
+
// util aliases: dashboard → dash, kevin-up → bash script
|
|
259
259
|
if (cmd === 'dashboard') {
|
|
260
260
|
mod = await importCommand('dash');
|
|
261
|
-
} else if (cmd === '
|
|
262
|
-
// Run via util.mjs's `
|
|
261
|
+
} else if (cmd === 'kevin-up') {
|
|
262
|
+
// Run via util.mjs's `kevin-up` case
|
|
263
263
|
mod = await importCommand('util');
|
|
264
264
|
}
|
|
265
265
|
} else {
|
|
@@ -499,8 +499,8 @@ async function main() {
|
|
|
499
499
|
case 'digest':
|
|
500
500
|
case 'backup':
|
|
501
501
|
case 'restore':
|
|
502
|
-
case '
|
|
503
|
-
case '
|
|
502
|
+
case 'kevin':
|
|
503
|
+
case 'kevin-up':
|
|
504
504
|
case 'providers':
|
|
505
505
|
case 'plan': {
|
|
506
506
|
const mod = await importCommand('util');
|
package/cli/bootstrap.mjs
CHANGED
|
@@ -26,7 +26,7 @@ import { runPostInstall } from './install.mjs';
|
|
|
26
26
|
* If ANY are missing → setup is needed.
|
|
27
27
|
*/
|
|
28
28
|
const SETUP_MARKERS = [
|
|
29
|
-
join(clineAgentsDir(), '
|
|
29
|
+
join(clineAgentsDir(), 'mike.md'), // core agent installed
|
|
30
30
|
join(clineConfigDir(), 'plugins', 'bizar'), // plugin installed
|
|
31
31
|
];
|
|
32
32
|
|
|
@@ -20,7 +20,7 @@ const ALL_COMMANDS = [
|
|
|
20
20
|
// Util-based (live in cli/commands/util.mjs)
|
|
21
21
|
'audit', 'init', 'export', 'test-gate', 'dev-link', 'dev-unlink',
|
|
22
22
|
'doctor', 'repair', 'heads-up', 'bg', 'digest', 'backup', 'restore',
|
|
23
|
-
'
|
|
23
|
+
'kevin', 'kevin-up', 'providers',
|
|
24
24
|
// Own module
|
|
25
25
|
'install', 'update',
|
|
26
26
|
'service',
|
|
@@ -38,7 +38,7 @@ const ALL_COMMANDS = [
|
|
|
38
38
|
const NON_OWN_MODULE = new Set([
|
|
39
39
|
'audit', 'init', 'export', 'test-gate', 'dev-link', 'dev-unlink',
|
|
40
40
|
'doctor', 'repair', 'heads-up', 'bg', 'digest', 'backup', 'restore',
|
|
41
|
-
'
|
|
41
|
+
'kevin', 'kevin-up', 'providers', 'install', 'update',
|
|
42
42
|
]);
|
|
43
43
|
|
|
44
44
|
const seen = new Set();
|
package/cli/commands/claim.mjs
CHANGED
|
@@ -111,9 +111,9 @@ function showHelp() {
|
|
|
111
111
|
--help, -h Show this help
|
|
112
112
|
|
|
113
113
|
Examples:
|
|
114
|
-
bizar claim F-035 --who
|
|
115
|
-
bizar claim steal F-014 --by
|
|
116
|
-
bizar claim handoff F-035 --to
|
|
114
|
+
bizar claim F-035 --who mike --reason "porting MetaHarness from ruflo"
|
|
115
|
+
bizar claim steal F-014 --by steve --reason stale
|
|
116
|
+
bizar claim handoff F-035 --to karen --from mike
|
|
117
117
|
bizar claim list --status claimed --agent-only
|
|
118
118
|
`);
|
|
119
119
|
}
|
|
@@ -121,7 +121,7 @@ export function showClaudeCmdHelp() {
|
|
|
121
121
|
bizar config --json
|
|
122
122
|
bizar plugin list
|
|
123
123
|
bizar team auth-sprint "Plan and implement user auth with tests"
|
|
124
|
-
bizar subagent
|
|
124
|
+
bizar subagent greg "Find all places where the auth token is verified"
|
|
125
125
|
bizar run "fix the failing test in src/auth.test.ts"
|
|
126
126
|
|
|
127
127
|
Related:
|
|
@@ -262,7 +262,7 @@ export async function runClaudeTeam(args = []) {
|
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
/**
|
|
265
|
-
* `bizar subagent <agent> "task"` — spawn a
|
|
265
|
+
* `bizar subagent <agent> "task"` — spawn a pam read-only research
|
|
266
266
|
* subagent via `claude --agent <name> "..."`.
|
|
267
267
|
*
|
|
268
268
|
* Note: Claude Code's in-session subagent dispatch uses the `Agent`
|
|
@@ -272,7 +272,7 @@ export async function runClaudeTeam(args = []) {
|
|
|
272
272
|
*/
|
|
273
273
|
export async function runClaudeSubagent(args = []) {
|
|
274
274
|
if (args.length === 0) {
|
|
275
|
-
console.log(chalk.cyan(' bizar subagent — Spawn a
|
|
275
|
+
console.log(chalk.cyan(' bizar subagent — Spawn a pam read-only research subagent\n'));
|
|
276
276
|
console.log(chalk.dim(' Subagents are research agents. They run in parallel, '));
|
|
277
277
|
console.log(chalk.dim(' keep their own context window, and return a focused report.'));
|
|
278
278
|
console.log(chalk.dim(' Use them for broad codebase exploration without burning context.\n'));
|
package/cli/commands/eval.mjs
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Subcommands:
|
|
7
7
|
* bizar eval list [--limit N] List recent runs
|
|
8
|
-
* bizar eval run <suite-path> [--concurrency N] [--agent
|
|
8
|
+
* bizar eval run <suite-path> [--concurrency N] [--agent todd] Run a suite
|
|
9
9
|
* bizar eval show <run-id> Show run details
|
|
10
10
|
* bizar eval diff <run-id-1> <run-id-2> Compare two runs
|
|
11
11
|
* bizar eval init <path> Scaffold a new fixture template
|
|
@@ -76,7 +76,7 @@ export function showEvalHelp() {
|
|
|
76
76
|
|
|
77
77
|
Usage:
|
|
78
78
|
bizar eval list [--limit N] List recent runs (default limit 20)
|
|
79
|
-
bizar eval run <suite-path> [--concurrency N] [--agent
|
|
79
|
+
bizar eval run <suite-path> [--concurrency N] [--agent todd]
|
|
80
80
|
Run a fixture suite
|
|
81
81
|
bizar eval show <run-id> Show run details + results
|
|
82
82
|
bizar eval diff <run-id-1> <run-id-2> Diff two runs
|
|
@@ -118,12 +118,12 @@ async function runSuite(args) {
|
|
|
118
118
|
const suitePath = positional[0];
|
|
119
119
|
if (!suitePath) {
|
|
120
120
|
console.error(chalk.red(' Error: suite-path is required'));
|
|
121
|
-
console.error(' Usage: bizar eval run <suite-path> [--concurrency N] [--agent
|
|
121
|
+
console.error(' Usage: bizar eval run <suite-path> [--concurrency N] [--agent todd]');
|
|
122
122
|
process.exit(1);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
const concurrency = parseInt(args.find((a) => a.startsWith('--concurrency='))?.split('=')[1] || '5', 10);
|
|
126
|
-
const agent = args.find((a) => a.startsWith('--agent='))?.split('=')[1] || '
|
|
126
|
+
const agent = args.find((a) => a.startsWith('--agent='))?.split('=')[1] || 'todd';
|
|
127
127
|
|
|
128
128
|
console.log(chalk.bold(` Running eval suite: ${suitePath}`));
|
|
129
129
|
console.log(` Concurrency: ${concurrency} Agent: ${agent}`);
|
|
@@ -260,7 +260,7 @@ function initFixture(path) {
|
|
|
260
260
|
id: 'my-fixture-id',
|
|
261
261
|
name: 'My Fixture',
|
|
262
262
|
description: 'Describe what this fixture verifies',
|
|
263
|
-
agent: '
|
|
263
|
+
agent: 'todd',
|
|
264
264
|
prompt: 'What should the agent do?',
|
|
265
265
|
expected: {
|
|
266
266
|
contains: ['expected output fragment'],
|
|
@@ -286,7 +286,7 @@ function initFixture(path) {
|
|
|
286
286
|
- \`id\` — unique identifier
|
|
287
287
|
- \`name\` — human-readable name
|
|
288
288
|
- \`description\` — what the fixture verifies
|
|
289
|
-
- \`agent\` — agent to use (
|
|
289
|
+
- \`agent\` — agent to use (todd, karen, etc.)
|
|
290
290
|
- \`prompt\` — the prompt to send
|
|
291
291
|
- \`expected\` — validation rules (contains, notContains, regex, jsonSchema, maxTokens, maxLatencyMs)
|
|
292
292
|
- \`tags\` — optional tags for filtering
|
package/cli/commands/util.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Miscellaneous utility commands:
|
|
5
5
|
* audit, init, export, test-gate, dev-link, dev-unlink,
|
|
6
|
-
* doctor, repair, heads-up, bg,
|
|
6
|
+
* doctor, repair, heads-up, bg, kevin, kevin-up, providers detect,
|
|
7
7
|
* backup, restore
|
|
8
8
|
*/
|
|
9
9
|
import chalk from 'chalk';
|
|
@@ -119,7 +119,7 @@ export function showDoctorHelp() {
|
|
|
119
119
|
• the Bizar plugin is registered
|
|
120
120
|
• plugin path resolves
|
|
121
121
|
• @polderlabs/bizar-plugin is installed globally
|
|
122
|
-
• core agent files are installed (
|
|
122
|
+
• core agent files are installed (mike, pam, todd, karen)
|
|
123
123
|
• semble / skills on PATH (lenient — at least one)
|
|
124
124
|
• dashboard reachable (skipped if no port file)
|
|
125
125
|
• provider.minimax block + MiniMax model flags are sane
|
|
@@ -466,11 +466,11 @@ export async function run(name, args, isHelpRequest) {
|
|
|
466
466
|
}
|
|
467
467
|
break;
|
|
468
468
|
|
|
469
|
-
case '
|
|
469
|
+
case 'kevin-up': {
|
|
470
470
|
const { execFileSync } = await import('node:child_process');
|
|
471
471
|
const sub = args[0] || 'start';
|
|
472
472
|
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
473
|
-
const scriptPath = join(__dirname, '..', '
|
|
473
|
+
const scriptPath = join(__dirname, '..', 'kevin-up.sh');
|
|
474
474
|
try {
|
|
475
475
|
const out = execFileSync('bash', [scriptPath, sub], {
|
|
476
476
|
encoding: 'utf8',
|
|
@@ -478,18 +478,18 @@ export async function run(name, args, isHelpRequest) {
|
|
|
478
478
|
});
|
|
479
479
|
if (out) process.stdout.write(out);
|
|
480
480
|
} catch (err) {
|
|
481
|
-
console.error(chalk.red(` ✗
|
|
481
|
+
console.error(chalk.red(` ✗ kevin-up ${sub} failed (exit ${err.status ?? 1})`));
|
|
482
482
|
process.exit(err.status || 1);
|
|
483
483
|
}
|
|
484
484
|
break;
|
|
485
485
|
}
|
|
486
486
|
|
|
487
|
-
case '
|
|
488
|
-
// v6.0.0 — install / update / verify the
|
|
489
|
-
// (The '
|
|
487
|
+
case 'kevin': {
|
|
488
|
+
// v6.0.0 — install / update / verify the kevin CLI.
|
|
489
|
+
// (The 'kevin-up' sibling is the bash wrapper that just
|
|
490
490
|
// manages the daemon process; this is the rich installer + updater.)
|
|
491
491
|
const { install, update, detectState, ensureRunning, printStatus } =
|
|
492
|
-
await import('../
|
|
492
|
+
await import('../kevin-update.mjs');
|
|
493
493
|
const sub = args[0] || 'status';
|
|
494
494
|
switch (sub) {
|
|
495
495
|
case 'status':
|
|
@@ -497,7 +497,7 @@ export async function run(name, args, isHelpRequest) {
|
|
|
497
497
|
break;
|
|
498
498
|
case 'install': {
|
|
499
499
|
const s = install({ silent: false });
|
|
500
|
-
console.log(chalk.green('\n
|
|
500
|
+
console.log(chalk.green('\n kevin ready.'));
|
|
501
501
|
console.log(` version: ${s.version}`);
|
|
502
502
|
console.log(` daemon: ${s.daemonRunning ? 'running' : 'stopped'}`);
|
|
503
503
|
console.log(` profile: ${s.profileDir}`);
|
|
@@ -505,7 +505,7 @@ export async function run(name, args, isHelpRequest) {
|
|
|
505
505
|
}
|
|
506
506
|
case 'update': {
|
|
507
507
|
const s = update({ silent: false });
|
|
508
|
-
console.log(chalk.green('\n
|
|
508
|
+
console.log(chalk.green('\n kevin up-to-date.'));
|
|
509
509
|
console.log(` version: ${s.version}`);
|
|
510
510
|
console.log(` daemon: ${s.daemonRunning ? 'running' : 'stopped'}`);
|
|
511
511
|
break;
|
|
@@ -520,7 +520,7 @@ export async function run(name, args, isHelpRequest) {
|
|
|
520
520
|
break;
|
|
521
521
|
case 'stop': {
|
|
522
522
|
const { spawnSync } = await import('node:child_process');
|
|
523
|
-
const killed = spawnSync('pkill', ['-f', '
|
|
523
|
+
const killed = spawnSync('pkill', ['-f', 'kevin serve'], { stdio: 'ignore' });
|
|
524
524
|
if (killed.status === 0) {
|
|
525
525
|
console.log(chalk.green(' ✓ daemon stopped'));
|
|
526
526
|
} else {
|
|
@@ -529,21 +529,21 @@ export async function run(name, args, isHelpRequest) {
|
|
|
529
529
|
break;
|
|
530
530
|
}
|
|
531
531
|
default:
|
|
532
|
-
console.log(`bizar
|
|
532
|
+
console.log(`bizar kevin <sub>
|
|
533
533
|
|
|
534
534
|
Subcommands:
|
|
535
535
|
status one-line status (default)
|
|
536
|
-
install install
|
|
536
|
+
install install kevin + download Chrome
|
|
537
537
|
update upgrade to the latest version
|
|
538
538
|
detect JSON state (for scripts)
|
|
539
539
|
start start the daemon
|
|
540
540
|
stop stop the daemon
|
|
541
541
|
|
|
542
542
|
Examples:
|
|
543
|
-
bizar
|
|
544
|
-
bizar
|
|
545
|
-
bizar
|
|
546
|
-
bizar
|
|
543
|
+
bizar kevin status
|
|
544
|
+
bizar kevin install
|
|
545
|
+
bizar kevin update
|
|
546
|
+
bizar kevin start`);
|
|
547
547
|
}
|
|
548
548
|
break;
|
|
549
549
|
}
|
|
@@ -61,10 +61,10 @@ function bizarHome() {
|
|
|
61
61
|
const REPO_ROOT = process.env.BIZAR_REPO_ROOT || process.cwd();
|
|
62
62
|
|
|
63
63
|
const REQUIRED_AGENTS = [
|
|
64
|
-
'
|
|
65
|
-
'
|
|
66
|
-
'
|
|
67
|
-
'
|
|
64
|
+
'mike.md', 'janet.md', 'susan.md', 'pam.md',
|
|
65
|
+
'greg.md', 'brenda.md', 'steve.md', 'todd.md', 'brad.md',
|
|
66
|
+
'karen.md', 'carl.md', 'linda.md',
|
|
67
|
+
'oscar.md', 'kevin.md',
|
|
68
68
|
];
|
|
69
69
|
|
|
70
70
|
const REQUIRED_COMMANDS = [
|
|
@@ -244,16 +244,16 @@ const CHECKS = {
|
|
|
244
244
|
|
|
245
245
|
'agent-frontmatter-format': async () => {
|
|
246
246
|
// Claude Code reads agents via `.md` files with YAML frontmatter.
|
|
247
|
-
// Spot-check that at least the
|
|
247
|
+
// Spot-check that at least the mike.md agent has frontmatter.
|
|
248
248
|
const dir = join(claudeDir(), 'agents');
|
|
249
249
|
if (!existsSync(dir)) throw new Error('agents dir missing');
|
|
250
|
-
const
|
|
251
|
-
if (!existsSync(
|
|
252
|
-
const text = readFileSync(
|
|
250
|
+
const mike = join(dir, 'mike.md');
|
|
251
|
+
if (!existsSync(mike)) throw new Error('mike.md missing');
|
|
252
|
+
const text = readFileSync(mike, 'utf8');
|
|
253
253
|
if (!text.startsWith('---')) {
|
|
254
|
-
throw new Error('
|
|
254
|
+
throw new Error('mike.md has no YAML frontmatter — Claude Code may not load it');
|
|
255
255
|
}
|
|
256
|
-
return '
|
|
256
|
+
return 'mike.md has YAML frontmatter';
|
|
257
257
|
},
|
|
258
258
|
|
|
259
259
|
'slash-commands-installed': async () => {
|
package/cli/init.mjs
CHANGED
|
@@ -363,6 +363,6 @@ ${stack.runner ? `- Dev: \`${stack.runner}\`` : ''}
|
|
|
363
363
|
}
|
|
364
364
|
}
|
|
365
365
|
|
|
366
|
-
console.log(chalk.dim('\n Project initialized. Run `@
|
|
366
|
+
console.log(chalk.dim('\n Project initialized. Run `@susan` to ask questions about the codebase.\n'));
|
|
367
367
|
return true;
|
|
368
368
|
}
|