@polderlabs/bizar 5.6.0-beta.8 → 5.6.0-beta.9
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/cli/agent-browser-up.sh +16 -0
- package/cli/bin.mjs +49 -3
- package/cli/cli-commands-validation.test.mjs +106 -0
- package/cli/commands/clip.mjs +18 -1
- package/cli/commands/eval.mjs +19 -1
- package/cli/commands/lightrag.mjs +0 -1
- package/cli/commands/ocr.mjs +18 -1
- package/cli/commands/usage.mjs +4 -0
- package/cli/commands/util.mjs +34 -0
- package/cli/digest.mjs +1 -1
- package/package.json +1 -1
- package/packages/sdk/package.json +1 -1
package/cli/agent-browser-up.sh
CHANGED
|
@@ -132,5 +132,21 @@ case "${1:-start}" in
|
|
|
132
132
|
status) ensure_binary; print_status ;;
|
|
133
133
|
doctor) ensure_binary; $AB_BIN doctor ;;
|
|
134
134
|
install) ensure_binary; ensure_chrome; $AB_BIN install ;;
|
|
135
|
+
help|--help|-h)
|
|
136
|
+
cat <<'AGENT_BROWSER_UP_HELP'
|
|
137
|
+
agent-browser-up -- start/stop the agent-browser daemon
|
|
138
|
+
|
|
139
|
+
Usage: cli/agent-browser-up.sh <command>
|
|
140
|
+
|
|
141
|
+
Commands:
|
|
142
|
+
start Start the daemon (idempotent)
|
|
143
|
+
stop Stop the daemon
|
|
144
|
+
restart Stop + start
|
|
145
|
+
status Print daemon status
|
|
146
|
+
doctor Run agent-browser doctor
|
|
147
|
+
install Install agent-browser + download Chrome
|
|
148
|
+
AGENT_BROWSER_UP_HELP
|
|
149
|
+
exit 0
|
|
150
|
+
;;
|
|
135
151
|
*) fail "unknown command: $1 (use start|stop|restart|status|doctor|install)" ;;
|
|
136
152
|
esac
|
package/cli/bin.mjs
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* Commands:
|
|
14
14
|
* install, audit, init, export, artifact, update, test-gate, service, dash,
|
|
15
15
|
* memory, headroom, minimax, usage, mod, doctor, repair, dev-link, dev-unlink,
|
|
16
|
-
* heads-up, bg, agent-browser, agent-browser-up, providers, deploy, plugin,
|
|
16
|
+
* heads-up, bg, agent-browser, agent-browser-up, providers, deploy, plugin,
|
|
17
|
+
* marketplace, plan, digest, backup, restore, clip, ocr, voice, workspace, eval
|
|
17
18
|
*/
|
|
18
19
|
import chalk from 'chalk';
|
|
19
20
|
import { existsSync, readFileSync } from 'node:fs';
|
|
@@ -120,6 +121,13 @@ function showHelp() {
|
|
|
120
121
|
providers detect Auto-detect provider API keys from env + cline.json
|
|
121
122
|
clip <subcommand> Manage web clipper saved clips (list/delete/configure)
|
|
122
123
|
ocr <subcommand> OCR operations on images (list/process/configure)
|
|
124
|
+
digest Manage weekly digests (list/view/generate)
|
|
125
|
+
backup Create / list / verify / delete backups of BizarHarness state
|
|
126
|
+
restore Restore BizarHarness from a backup
|
|
127
|
+
voice Manage voice notes (via the dashboard's HTTP API)
|
|
128
|
+
workspace Manage workspaces (via the dashboard's HTTP API)
|
|
129
|
+
eval Evaluate AI agent outputs against golden fixtures
|
|
130
|
+
plan [v6.0.0+] Reserved for future plan management
|
|
123
131
|
|
|
124
132
|
Examples:
|
|
125
133
|
bizar install
|
|
@@ -189,8 +197,30 @@ async function main() {
|
|
|
189
197
|
}
|
|
190
198
|
|
|
191
199
|
if (isHelpRequest && !cmd.startsWith('-')) {
|
|
192
|
-
// Pass --help to the command
|
|
193
|
-
|
|
200
|
+
// Pass --help to the command. Commands dispatched through util.mjs
|
|
201
|
+
// (audit, init, export, doctor, backup, restore, etc.) don't have
|
|
202
|
+
// their own cli/commands/<name>.mjs — they all live in util.mjs.
|
|
203
|
+
const UTIL_COMMANDS = new Set([
|
|
204
|
+
'audit', 'init', 'export', 'test-gate', 'dev-link', 'dev-unlink',
|
|
205
|
+
'doctor', 'repair', 'heads-up', 'bg', 'digest', 'backup', 'restore',
|
|
206
|
+
'agent-browser', 'update', 'providers', 'plan',
|
|
207
|
+
]);
|
|
208
|
+
const UTIL_ALIASES = new Set(['dashboard', 'agent-browser-up']);
|
|
209
|
+
let mod;
|
|
210
|
+
if (UTIL_COMMANDS.has(cmd)) {
|
|
211
|
+
// util-based commands: audit, init, etc.
|
|
212
|
+
mod = await importCommand('util');
|
|
213
|
+
} else if (UTIL_ALIASES.has(cmd)) {
|
|
214
|
+
// util aliases: dashboard → dash, agent-browser-up → bash script
|
|
215
|
+
if (cmd === 'dashboard') {
|
|
216
|
+
mod = await importCommand('dash');
|
|
217
|
+
} else if (cmd === 'agent-browser-up') {
|
|
218
|
+
// Run via util.mjs's `agent-browser-up` case
|
|
219
|
+
mod = await importCommand('util');
|
|
220
|
+
}
|
|
221
|
+
} else {
|
|
222
|
+
mod = await importCommand(cmd);
|
|
223
|
+
}
|
|
194
224
|
if (mod && typeof mod.run === 'function') {
|
|
195
225
|
await mod.run(cmd, cmdArgs, true);
|
|
196
226
|
return;
|
|
@@ -430,6 +460,8 @@ async function main() {
|
|
|
430
460
|
case 'heads-up':
|
|
431
461
|
case 'bg':
|
|
432
462
|
case 'digest':
|
|
463
|
+
case 'backup':
|
|
464
|
+
case 'restore':
|
|
433
465
|
case 'agent-browser':
|
|
434
466
|
case 'agent-browser-up':
|
|
435
467
|
case 'providers':
|
|
@@ -451,6 +483,20 @@ async function main() {
|
|
|
451
483
|
break;
|
|
452
484
|
}
|
|
453
485
|
|
|
486
|
+
case 'voice':
|
|
487
|
+
case 'workspace':
|
|
488
|
+
case 'eval': {
|
|
489
|
+
// Each of these has its own module file in cli/commands/.
|
|
490
|
+
const mod = await importCommand(cmd);
|
|
491
|
+
if (!mod) {
|
|
492
|
+
console.error(chalk.red(` ✗ Could not load ${cmd} command module`));
|
|
493
|
+
process.exit(EXIT_ERROR);
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
if (mod.run) await mod.run(cmd, cmdArgs, isHelpRequest);
|
|
497
|
+
break;
|
|
498
|
+
}
|
|
499
|
+
|
|
454
500
|
default: {
|
|
455
501
|
console.error(chalk.red(` ✗ Unknown command: ${cmd}`));
|
|
456
502
|
showHelp();
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* /tmp/test-cli-commands.mjs
|
|
4
|
+
* Comprehensive validation of every `bizar` CLI command.
|
|
5
|
+
*
|
|
6
|
+
* Tests:
|
|
7
|
+
* - All case branches in cli/bin.mjs respond to --help
|
|
8
|
+
* - All case branches in cli/commands/util.mjs respond to --help
|
|
9
|
+
* - Module exports are loadable
|
|
10
|
+
*
|
|
11
|
+
* Usage: node /tmp/test-cli-commands.mjs
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { spawnSync } from 'node:child_process';
|
|
15
|
+
|
|
16
|
+
const REPO = process.cwd();
|
|
17
|
+
const BIN = `${REPO}/cli/bin.mjs`;
|
|
18
|
+
|
|
19
|
+
const ALL_COMMANDS = [
|
|
20
|
+
// Util-based (live in cli/commands/util.mjs)
|
|
21
|
+
'audit', 'init', 'export', 'test-gate', 'dev-link', 'dev-unlink',
|
|
22
|
+
'doctor', 'repair', 'heads-up', 'bg', 'digest', 'backup', 'restore',
|
|
23
|
+
'agent-browser', 'agent-browser-up', 'providers',
|
|
24
|
+
// Own module
|
|
25
|
+
'install', 'update',
|
|
26
|
+
'service',
|
|
27
|
+
'dash', 'dashboard',
|
|
28
|
+
'minimax', 'tailscale', 'headroom', 'lightrag',
|
|
29
|
+
'mod', 'usage',
|
|
30
|
+
'deploy', 'plugin', 'marketplace',
|
|
31
|
+
'artifact',
|
|
32
|
+
'memory',
|
|
33
|
+
'memory',
|
|
34
|
+
'clip', 'ocr',
|
|
35
|
+
'voice', 'workspace', 'eval',
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const NON_OWN_MODULE = new Set([
|
|
39
|
+
'audit', 'init', 'export', 'test-gate', 'dev-link', 'dev-unlink',
|
|
40
|
+
'doctor', 'repair', 'heads-up', 'bg', 'digest', 'backup', 'restore',
|
|
41
|
+
'agent-browser', 'agent-browser-up', 'providers', 'install', 'update',
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
const seen = new Set();
|
|
45
|
+
const passed = [];
|
|
46
|
+
const failed = [];
|
|
47
|
+
|
|
48
|
+
for (const cmd of ALL_COMMANDS) {
|
|
49
|
+
if (seen.has(cmd)) continue;
|
|
50
|
+
seen.add(cmd);
|
|
51
|
+
|
|
52
|
+
// Run `node cli/bin.mjs <cmd> --help` and check exit code + that it prints help
|
|
53
|
+
const r = spawnSync('node', [BIN, cmd, '--help'], {
|
|
54
|
+
timeout: 15_000,
|
|
55
|
+
encoding: 'utf8',
|
|
56
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
57
|
+
});
|
|
58
|
+
const stdout = r.stdout || '';
|
|
59
|
+
const stderr = r.stderr || '';
|
|
60
|
+
const exitCode = r.status;
|
|
61
|
+
|
|
62
|
+
// Pass criteria:
|
|
63
|
+
// - Exit code 0 OR 2 (CLINE exit code for usage/help is 2 sometimes)
|
|
64
|
+
// - stdout mentions the command name or contains a recognizable help string
|
|
65
|
+
// - stderr is empty OR mentions the command name (not "module not found")
|
|
66
|
+
const hasModuleError = stderr.includes('Cannot find module') ||
|
|
67
|
+
stderr.includes('Failed to load command module');
|
|
68
|
+
const hasHelp = stdout.toLowerCase().includes(cmd) ||
|
|
69
|
+
stdout.includes('Usage:') ||
|
|
70
|
+
stdout.includes('Subcommands:') ||
|
|
71
|
+
stdout.includes('Description:');
|
|
72
|
+
|
|
73
|
+
if ((exitCode === 0 || exitCode === 2) && !hasModuleError && (hasHelp || stdout.length > 50)) {
|
|
74
|
+
passed.push({ cmd, exitCode, stdoutLines: stdout.split('\n').length });
|
|
75
|
+
} else {
|
|
76
|
+
failed.push({ cmd, exitCode, hasModuleError, hasHelp, stdout: stdout.slice(0, 200), stderr: stderr.slice(0, 200) });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log(`\n=== CLI command validation ===\n`);
|
|
81
|
+
console.log(`Passed: ${passed.length}/${seen.size}`);
|
|
82
|
+
console.log(`Failed: ${failed.length}\n`);
|
|
83
|
+
|
|
84
|
+
if (passed.length > 0) {
|
|
85
|
+
console.log('=== Passing commands ===');
|
|
86
|
+
for (const p of passed) {
|
|
87
|
+
console.log(` ✓ ${p.cmd.padEnd(20)} (exit ${p.exitCode}, ${p.stdoutLines} lines)`);
|
|
88
|
+
}
|
|
89
|
+
console.log();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (failed.length > 0) {
|
|
93
|
+
console.log('=== FAILING commands ===');
|
|
94
|
+
for (const f of failed) {
|
|
95
|
+
console.log(` ✗ ${f.cmd.padEnd(20)} exitCode=${f.exitCode} moduleErr=${f.hasModuleError} hasHelp=${f.hasHelp}`);
|
|
96
|
+
if (f.hasModuleError) {
|
|
97
|
+
console.log(` stderr: ${f.stderr.trim()}`);
|
|
98
|
+
} else if (f.exitCode !== 0 && f.exitCode !== 2) {
|
|
99
|
+
console.log(` stderr: ${f.stderr.trim().slice(0, 200)}`);
|
|
100
|
+
console.log(` stdout: ${f.stdout.trim().slice(0, 200)}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
console.log();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
process.exit(failed.length > 0 ? 1 : 0);
|
package/cli/commands/clip.mjs
CHANGED
|
@@ -10,7 +10,24 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import chalk from 'chalk';
|
|
13
|
-
|
|
13
|
+
// Mirror `readDashboardConn` from clip.mjs / minimax.mjs / usage.mjs.
|
|
14
|
+
function readDashboardConn() {
|
|
15
|
+
const cfgDir = process.env.XDG_CONFIG_HOME
|
|
16
|
+
? require_('node:path').join(process.env.XDG_CONFIG_HOME, 'bizar')
|
|
17
|
+
: require_('node:path').join(require_('node:os').homedir(), '.config', 'bizar');
|
|
18
|
+
const portPath = require_('node:path').join(cfgDir, 'dashboard.port');
|
|
19
|
+
const secretPath = require_('node:path').join(cfgDir, 'dashboard.secret');
|
|
20
|
+
const port = require_('node:fs').existsSync(portPath)
|
|
21
|
+
? parseInt(require_('node:fs').readFileSync(portPath, 'utf8').trim(), 10)
|
|
22
|
+
: 4321;
|
|
23
|
+
const secret = require_('node:fs').existsSync(secretPath)
|
|
24
|
+
? require_('node:fs').readFileSync(secretPath, 'utf8').trim()
|
|
25
|
+
: '';
|
|
26
|
+
return {
|
|
27
|
+
port: Number.isFinite(port) && port > 0 ? port : 4321,
|
|
28
|
+
secret,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
14
31
|
|
|
15
32
|
// ── API helpers ────────────────────────────────────────────────────────────────
|
|
16
33
|
|
package/cli/commands/eval.mjs
CHANGED
|
@@ -15,7 +15,25 @@ import chalk from 'chalk';
|
|
|
15
15
|
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
16
16
|
import { join, dirname } from 'node:path';
|
|
17
17
|
import { homedir } from 'node:os';
|
|
18
|
-
|
|
18
|
+
|
|
19
|
+
// Mirror `readDashboardConn` from clip.mjs / minimax.mjs / usage.mjs.
|
|
20
|
+
function readDashboardConn() {
|
|
21
|
+
const cfgDir = process.env.XDG_CONFIG_HOME
|
|
22
|
+
? join(process.env.XDG_CONFIG_HOME, 'bizar')
|
|
23
|
+
: join(homedir(), '.config', 'bizar');
|
|
24
|
+
const portPath = join(cfgDir, 'dashboard.port');
|
|
25
|
+
const secretPath = join(cfgDir, 'dashboard.secret');
|
|
26
|
+
const port = existsSync(portPath)
|
|
27
|
+
? parseInt(readFileSync(portPath, 'utf8').trim(), 10)
|
|
28
|
+
: 4321;
|
|
29
|
+
const secret = existsSync(secretPath)
|
|
30
|
+
? readFileSync(secretPath, 'utf8').trim()
|
|
31
|
+
: '';
|
|
32
|
+
return {
|
|
33
|
+
port: Number.isFinite(port) && port > 0 ? port : 4321,
|
|
34
|
+
secret,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
19
37
|
|
|
20
38
|
const HOME = homedir();
|
|
21
39
|
const TEMPLATES_DIR = join(HOME, '.config', 'bizar', 'templates', 'eval-fixtures');
|
package/cli/commands/ocr.mjs
CHANGED
|
@@ -11,7 +11,24 @@
|
|
|
11
11
|
|
|
12
12
|
import chalk from 'chalk';
|
|
13
13
|
import { readFileSync, existsSync } from 'node:fs';
|
|
14
|
-
|
|
14
|
+
// Mirror `readDashboardConn` from clip.mjs / minimax.mjs / usage.mjs.
|
|
15
|
+
function readDashboardConn() {
|
|
16
|
+
const cfgDir = process.env.XDG_CONFIG_HOME
|
|
17
|
+
? require_('node:path').join(process.env.XDG_CONFIG_HOME, 'bizar')
|
|
18
|
+
: require_('node:path').join(require_('node:os').homedir(), '.config', 'bizar');
|
|
19
|
+
const portPath = require_('node:path').join(cfgDir, 'dashboard.port');
|
|
20
|
+
const secretPath = require_('node:path').join(cfgDir, 'dashboard.secret');
|
|
21
|
+
const port = require_('node:fs').existsSync(portPath)
|
|
22
|
+
? parseInt(require_('node:fs').readFileSync(portPath, 'utf8').trim(), 10)
|
|
23
|
+
: 4321;
|
|
24
|
+
const secret = require_('node:fs').existsSync(secretPath)
|
|
25
|
+
? require_('node:fs').readFileSync(secretPath, 'utf8').trim()
|
|
26
|
+
: '';
|
|
27
|
+
return {
|
|
28
|
+
port: Number.isFinite(port) && port > 0 ? port : 4321,
|
|
29
|
+
secret,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
15
32
|
|
|
16
33
|
// ── API helpers ────────────────────────────────────────────────────────────────
|
|
17
34
|
|
package/cli/commands/usage.mjs
CHANGED
|
@@ -105,5 +105,9 @@ async function runUsageCommand(args, wantJson = false) {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
export async function run(name, args, isHelpRequest) {
|
|
108
|
+
if (isHelpRequest || args.length === 0) {
|
|
109
|
+
showUsageHelp();
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
108
112
|
await runUsageCommand(args, false);
|
|
109
113
|
}
|
package/cli/commands/util.mjs
CHANGED
|
@@ -154,6 +154,24 @@ export function showBackupHelp() {
|
|
|
154
154
|
`);
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
export function showProvidersHelp() {
|
|
158
|
+
console.log(`
|
|
159
|
+
bizar providers - Auto-detect provider API keys
|
|
160
|
+
|
|
161
|
+
Usage:
|
|
162
|
+
bizar providers detect Auto-detect provider API keys from env + cline.json
|
|
163
|
+
bizar providers --help Show this help
|
|
164
|
+
|
|
165
|
+
Description:
|
|
166
|
+
Scans process.env + ~/.config/cline/cline.json for known provider
|
|
167
|
+
API keys (OpenAI, Anthropic, OpenRouter, MiniMax, etc.) and reports
|
|
168
|
+
what's available. Useful before the first \`bizar install\` to verify
|
|
169
|
+
credentials are picked up.
|
|
170
|
+
|
|
171
|
+
No API keys are sent over the network - detection is local.
|
|
172
|
+
`);
|
|
173
|
+
}
|
|
174
|
+
|
|
157
175
|
export function showRestoreHelp() {
|
|
158
176
|
console.log(`
|
|
159
177
|
bizar restore — Restore BizarHarness from a backup
|
|
@@ -209,6 +227,18 @@ export async function runTestGate() {
|
|
|
209
227
|
|
|
210
228
|
export async function run(name, args, isHelpRequest) {
|
|
211
229
|
switch (name) {
|
|
230
|
+
case 'update':
|
|
231
|
+
// `bizar update` lives in commands/install.mjs (the install/update
|
|
232
|
+
// pair share a code path). Proxy to it.
|
|
233
|
+
if (isHelpRequest) {
|
|
234
|
+
const { showUpdateHelp } = await import('./install.mjs');
|
|
235
|
+
showUpdateHelp();
|
|
236
|
+
} else {
|
|
237
|
+
const { runUpdate } = await import('./install.mjs');
|
|
238
|
+
await runUpdate(args, {});
|
|
239
|
+
}
|
|
240
|
+
break;
|
|
241
|
+
|
|
212
242
|
case 'audit':
|
|
213
243
|
if (isHelpRequest) showAuditHelp();
|
|
214
244
|
else {
|
|
@@ -506,6 +536,10 @@ export async function run(name, args, isHelpRequest) {
|
|
|
506
536
|
}
|
|
507
537
|
|
|
508
538
|
case 'providers':
|
|
539
|
+
if (isHelpRequest || args.length === 0) {
|
|
540
|
+
showProvidersHelp();
|
|
541
|
+
break;
|
|
542
|
+
}
|
|
509
543
|
if (args[0] === 'detect') {
|
|
510
544
|
const { runProvidersDetect } = await import('../providers-detect.mjs');
|
|
511
545
|
await runProvidersDetect(args.slice(1));
|
package/cli/digest.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polderlabs/bizar",
|
|
3
|
-
"version": "5.6.0-beta.
|
|
3
|
+
"version": "5.6.0-beta.9",
|
|
4
4
|
"description": "Norse-pantheon multi-agent system for cline — 13 agents across 4 cost tiers with cost-aware routing, plans, and a configurable agent harness. v4 ships as a single npm package bundling the dashboard server, cline plugin, and typed SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|