@polderlabs/bizar 4.5.1 → 4.5.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.
Files changed (48) hide show
  1. package/bizar-dash/dist/assets/__vite-browser-external-BIHI7g3E.js +0 -1
  2. package/bizar-dash/dist/assets/main-B4OfGAwz.js +361 -0
  3. package/bizar-dash/dist/assets/main-B4OfGAwz.js.map +1 -0
  4. package/bizar-dash/dist/assets/main-DAlLdW8I.css +1 -0
  5. package/bizar-dash/dist/assets/{mobile-DQLFCjwJ.js → mobile-BRhoDOUz.js} +1 -2
  6. package/bizar-dash/dist/assets/{mobile-DQLFCjwJ.js.map → mobile-BRhoDOUz.js.map} +1 -1
  7. package/bizar-dash/dist/assets/{mobile-O6ANdD4W.js → mobile-lbH6szyX.js} +2 -3
  8. package/bizar-dash/dist/assets/mobile-lbH6szyX.js.map +1 -0
  9. package/bizar-dash/dist/index.html +3 -3
  10. package/bizar-dash/dist/mobile.html +2 -2
  11. package/bizar-dash/src/server/headroom.mjs +37 -35
  12. package/bizar-dash/src/server/memory-lightrag.mjs +39 -31
  13. package/bizar-dash/src/server/mods-loader.mjs +13 -5
  14. package/bizar-dash/src/server/providers-store.mjs +73 -1
  15. package/bizar-dash/src/server/routes/chat.mjs +38 -0
  16. package/bizar-dash/src/server/routes/lightrag.mjs +6 -2
  17. package/bizar-dash/src/server/routes/memory.mjs +12 -4
  18. package/bizar-dash/src/server/schedules-runner.mjs +4 -4
  19. package/bizar-dash/src/server/server.mjs +39 -37
  20. package/bizar-dash/src/server/watcher.mjs +2 -2
  21. package/bizar-dash/src/web/App.tsx +40 -6
  22. package/bizar-dash/src/web/components/Toast.tsx +1 -1
  23. package/bizar-dash/src/web/components/Topbar.tsx +1 -1
  24. package/bizar-dash/src/web/lib/api.ts +12 -11
  25. package/bizar-dash/src/web/styles/chat.css +2 -0
  26. package/bizar-dash/src/web/styles/main.css +52 -23
  27. package/bizar-dash/src/web/styles/tasks.css +2 -0
  28. package/bizar-dash/src/web/views/Memory.tsx +4 -3
  29. package/bizar-dash/src/web/views/MiniMaxUsage.tsx +3 -2
  30. package/bizar-dash/src/web/views/Overview.tsx +4 -2
  31. package/bizar-dash/src/web/views/Settings.tsx +2 -1
  32. package/bizar-dash/src/web/views/Skills.tsx +3 -2
  33. package/bizar-dash/src/web/views/Tasks.tsx +4 -3
  34. package/bizar-dash/src/web/views/memory/MemoryOverview.tsx +8 -6
  35. package/bizar-dash/tests/cli-bugfixes.test.mjs +151 -0
  36. package/bizar-dash/tests/frontend-bugfixes.test.mjs +151 -0
  37. package/bizar-dash/tests/server-bugfixes.test.mjs +318 -0
  38. package/cli/artifact.mjs +11 -4
  39. package/cli/bin.mjs +46 -12
  40. package/cli/doctor.mjs +5 -3
  41. package/cli/memory.mjs +65 -21
  42. package/cli/provision.mjs +8 -2
  43. package/install.sh +1 -2
  44. package/package.json +3 -3
  45. package/bizar-dash/dist/assets/main-eWZ4NlCL.css +0 -1
  46. package/bizar-dash/dist/assets/main-usWhlPWa.js +0 -362
  47. package/bizar-dash/dist/assets/main-usWhlPWa.js.map +0 -1
  48. package/bizar-dash/dist/assets/mobile-O6ANdD4W.js.map +0 -1
package/cli/bin.mjs CHANGED
@@ -22,6 +22,13 @@ import { fileURLToPath } from 'node:url';
22
22
 
23
23
  const HOME = homedir();
24
24
  const BIZAR_HOME = join(HOME, '.config', 'bizar');
25
+
26
+ // Exit codes
27
+ const EXIT_OK = 0;
28
+ const EXIT_ERROR = 1;
29
+ const EXIT_USAGE = 2;
30
+ const EXIT_MISSING_DEP = 3;
31
+ const EXIT_TIMEOUT = 4;
25
32
  import chalk from 'chalk';
26
33
  import { runInstaller } from './install.mjs';
27
34
  import { runAudit } from './audit.mjs';
@@ -35,6 +42,17 @@ import { ensureSetup, checkSetupStatus } from './bootstrap.mjs';
35
42
  const args = process.argv.slice(2);
36
43
  const isHelpRequest = args.includes('--help') || args.includes('-h');
37
44
  const isVersionRequest = args.includes('--version') || args.includes('-v');
45
+ const wantJson = args.includes('--json');
46
+ const wantDebug = args.includes('--debug');
47
+
48
+ if (wantDebug) {
49
+ process.env.DEBUG = 'bizar:*';
50
+ process.env.BIZAR_DEBUG = '1';
51
+ }
52
+
53
+ function dbg(...msg) {
54
+ if (wantDebug) console.error('[DEBUG]', ...msg);
55
+ }
38
56
 
39
57
  // ── Bootstrap ─────────────────────────────────────────────────────────────────
40
58
  // Every bin command checks setup status on first invocation.
@@ -759,7 +777,7 @@ function showUsageHelp() {
759
777
  `);
760
778
  }
761
779
 
762
- async function runUsageCommand(args) {
780
+ async function runUsageCommand(args, wantJson = false) {
763
781
  const range = (args[0] && ['24h', '7d', '30d'].includes(args[0])) ? args[0] : '24h';
764
782
  const { port, secret } = readDashboardConn();
765
783
  const url = `http://127.0.0.1:${port}/api/usage?range=${range}`;
@@ -774,6 +792,10 @@ async function runUsageCommand(args) {
774
792
  console.error(chalk.red(` ✗ Failed to load usage data: ${data?.message ?? resp.statusText}`));
775
793
  process.exit(1);
776
794
  }
795
+ if (wantJson) {
796
+ process.stdout.write(JSON.stringify(data) + '\n');
797
+ return;
798
+ }
777
799
  const t = data.totals;
778
800
  console.log('');
779
801
  console.log(chalk.bold(` Usage summary — ${range} (from JSONL store)`));
@@ -1083,11 +1105,15 @@ function parseFlag(name) {
1083
1105
  * Returns `null` if the flag isn't present (the provisioner's
1084
1106
  * "don't touch mods" default), or a string[] of mod ids if it is.
1085
1107
  */
1086
- function parseWithModsFlag(subargs) {
1108
+ export function parseWithModsFlag(subargs) {
1087
1109
  const idx = subargs.indexOf('--with-mods');
1088
1110
  if (idx === -1) return null;
1089
1111
  const raw = subargs[idx + 1];
1090
- if (!raw || raw.startsWith('--')) return [];
1112
+ if (!raw || raw.startsWith('--')) {
1113
+ console.error('bizar: --with-mods requires a value (e.g. --with-mods a,b,c)');
1114
+ console.error('Usage: bizar install --with-mods <mod-id,mod-id>');
1115
+ process.exit(2);
1116
+ }
1091
1117
  return raw
1092
1118
  .split(',')
1093
1119
  .map((s) => s.trim())
@@ -1181,7 +1207,7 @@ async function main() {
1181
1207
  if (isHelpRequest && !args[1]) showMemoryHelp();
1182
1208
  else {
1183
1209
  const { runMemory } = await import('./memory.mjs');
1184
- await runMemory(args[1], args.slice(2));
1210
+ await runMemory(args[1], args.slice(2), { wantJson });
1185
1211
  }
1186
1212
  } else if (args[0] === 'headroom') {
1187
1213
  await runHeadroomCommand(args.slice(1));
@@ -1229,8 +1255,11 @@ async function main() {
1229
1255
  if (isHelpRequest) showDoctorHelp();
1230
1256
  else {
1231
1257
  const { runDoctor } = await import('./doctor.mjs');
1232
- const result = await runDoctor();
1233
- if (result.failed > 0) process.exit(1);
1258
+ const result = await runDoctor({ silent: wantJson, json: wantJson });
1259
+ if (wantJson) {
1260
+ process.stdout.write(JSON.stringify(result) + '\n');
1261
+ }
1262
+ if (result.failed > 0) process.exit(EXIT_ERROR);
1234
1263
  }
1235
1264
  } else if (args[0] === 'repair') {
1236
1265
  // v4.4.3 — One-shot repair for stale `bizar` bin symlinks.
@@ -1328,11 +1357,11 @@ async function main() {
1328
1357
  await runMinimaxCommand(args.slice(1));
1329
1358
  } else if (args[0] === 'usage') {
1330
1359
  // v4.6.0 — Compact usage analytics summary from the JSONL store.
1331
- await runUsageCommand(args.slice(1));
1360
+ await runUsageCommand(args.slice(1), wantJson);
1332
1361
  } else if (args[0] === 'dash' || args[0] === 'dashboard') {
1333
1362
  // `bizar dashboard` is a deprecated alias for `bizar dash`
1334
1363
  if (args[0] === 'dashboard') {
1335
- console.warn(chalk.yellow(' ⚠ `bizar dashboard` is deprecated, use `bizar dash` instead.'));
1364
+ process.stdout.write(chalk.yellow(' ⚠ `bizar dashboard` is deprecated, use `bizar dash` instead.\n'));
1336
1365
  }
1337
1366
  const dashArgs = args.slice(1); // everything after 'dash' or 'dashboard'
1338
1367
  if (dashArgs.length === 0 || isHelpRequest) {
@@ -1458,7 +1487,12 @@ async function runDash(dashArgs) {
1458
1487
 
1459
1488
  // ── Main ──────────────────────────────────────────────────────────────────────
1460
1489
 
1461
- await main().catch((err) => {
1462
- console.error(chalk.red(`bizar: ${err && err.message ? err.message : String(err)}`));
1463
- process.exit(1);
1464
- });
1490
+ // Only run main() when bin.mjs is executed directly (not imported as a module in tests)
1491
+ const thisFile = fileURLToPath(import.meta.url);
1492
+ const isMainModule = process.argv[1] === thisFile;
1493
+ if (isMainModule) {
1494
+ await main().catch((err) => {
1495
+ console.error(chalk.red(`bizar: ${err && err.message ? err.message : String(err)}`));
1496
+ process.exit(1);
1497
+ });
1498
+ }
package/cli/doctor.mjs CHANGED
@@ -269,10 +269,12 @@ const CHECKS = [
269
269
 
270
270
  /**
271
271
  * Run all health checks. Prints per-check output unless `opts.silent`.
272
- * Always prints a final summary line. Returns `{ passed, failed, results }`.
272
+ * Prints a final summary line unless `opts.json` is true.
273
+ * Returns `{ passed, failed, results }`.
273
274
  */
274
275
  export async function runDoctor(opts = {}) {
275
276
  const silent = !!opts.silent;
277
+ const jsonMode = !!opts.json;
276
278
  const results = [];
277
279
  for (const [name, fn] of CHECKS) {
278
280
  const r = await runCheck(name, fn);
@@ -288,8 +290,8 @@ export async function runDoctor(opts = {}) {
288
290
  const passed = results.filter((r) => r.ok).length;
289
291
  const failed = results.length - passed;
290
292
 
291
- // Always print a summary line if there were failures, or if not silent.
292
- if (failed > 0 || !silent) {
293
+ // Print summary line only when not in JSON mode
294
+ if (!jsonMode && (failed > 0 || !silent)) {
293
295
  console.log('');
294
296
  if (failed === 0) {
295
297
  console.log(
package/cli/memory.mjs CHANGED
@@ -755,7 +755,8 @@ function printSetupResult({ mode, remote, vaultPath }) {
755
755
  /**
756
756
  * `bizar memory status`
757
757
  */
758
- async function cmdStatus(_args) {
758
+ async function cmdStatus(_args, opts = {}) {
759
+ const { wantJson = false } = opts;
759
760
  const projectRoot = getProjectRoot();
760
761
  const { loadConfig, resolveVault, initVault, listNotes } = memoryStore;
761
762
  const { isGitInstalled, status: gitStatus } = memoryGit;
@@ -768,19 +769,15 @@ async function cmdStatus(_args) {
768
769
 
769
770
  const { vaultRoot, mode, projectId, branch } = resolveVault(projectRoot);
770
771
 
771
- console.log(chalk.bold('\n Bizar Memory Status'));
772
- console.log(' ─────────────────────────────');
773
- kv('mode', mode);
774
- kv('projectId', projectId);
775
- kv('vault', vaultRoot);
776
- kv('branch', branch);
772
+ const out = { mode, projectId, vault: vaultRoot, branch };
777
773
 
778
774
  // Ensure vault exists
779
775
  if (!existsSync(vaultRoot)) {
780
- warn(`vault directory does not exist — run \`bizar memory init\` or \`bizar memory sync\``);
776
+ out.vaultExists = false;
781
777
  } else {
778
+ out.vaultExists = true;
782
779
  const notes = listNotes(projectRoot);
783
- kv('noteCount', String(notes.length));
780
+ out.noteCount = notes.length;
784
781
  }
785
782
 
786
783
  // Git status if managed
@@ -788,14 +785,14 @@ async function cmdStatus(_args) {
788
785
  if (isGitInstalled()) {
789
786
  const gs = gitStatus(vaultRoot);
790
787
  if (gs.ok) {
791
- kv('git', `${gs.branch} (${gs.clean ? chalk.green('clean') : chalk.red('dirty')})`);
792
- if (gs.ahead > 0) kv('ahead', String(gs.ahead));
793
- if (gs.behind > 0) kv('behind', String(gs.behind));
788
+ out.git = { branch: gs.branch, clean: gs.clean };
789
+ if (gs.ahead > 0) out.git.ahead = gs.ahead;
790
+ if (gs.behind > 0) out.git.behind = gs.behind;
794
791
  } else {
795
- kv('git', chalk.yellow(`not a git repo`));
792
+ out.git = { error: 'not a git repo' };
796
793
  }
797
794
  } else {
798
- kv('git', chalk.yellow(`git not installed`));
795
+ out.git = { error: 'git not installed' };
799
796
  }
800
797
  }
801
798
 
@@ -804,15 +801,15 @@ async function cmdStatus(_args) {
804
801
  const { isLightRAGRunning, isLightRAGInstalled, resolveLightRAGConfig } = memoryStore;
805
802
  const cfg = resolveLightRAGConfig(projectRoot);
806
803
  if (!cfg.enabled) {
807
- kv('lightrag', chalk.gray('disabled'));
804
+ out.lightrag = { enabled: false };
808
805
  } else if (!(await isLightRAGInstalled())) {
809
- kv('lightrag', chalk.yellow('not installed `uv tool install "lightrag-hku[api]"`'));
806
+ out.lightrag = { enabled: true, installed: false };
810
807
  } else {
811
808
  const running = await isLightRAGRunning(cfg);
812
- kv('lightrag', running ? chalk.green(`${cfg.host}:${cfg.port} (running)`) : chalk.yellow(`${cfg.host}:${cfg.port} (not running — run \`bizar memory reindex\`)`));
809
+ out.lightrag = { enabled: true, installed: true, running, host: cfg.host, port: cfg.port };
813
810
  }
814
811
  } catch (err) {
815
- kv('lightrag', chalk.gray(`status unavailable (${err.message})`));
812
+ out.lightrag = { error: err.message };
816
813
  }
817
814
 
818
815
  // Last reindex attempt
@@ -820,10 +817,55 @@ async function cmdStatus(_args) {
820
817
  if (existsSync(reindexMarker)) {
821
818
  try {
822
819
  const { finishedAt, ok, inserted, failed, noteCount } = JSON.parse(readFileSync(reindexMarker, 'utf8'));
823
- kv('lastReindex', `${new Date(finishedAt).toLocaleString()} — ${ok ? chalk.green(`${inserted}/${noteCount} ok`) : chalk.red(`${failed} failed`)}`);
820
+ out.lastReindex = { finishedAt, ok, inserted, failed, noteCount };
824
821
  } catch { /* ignore */ }
825
822
  }
826
823
 
824
+ if (wantJson) {
825
+ process.stdout.write(JSON.stringify(out) + '\n');
826
+ return;
827
+ }
828
+
829
+ console.log(chalk.bold('\n Bizar Memory Status'));
830
+ console.log(' ─────────────────────────────');
831
+ kv('mode', mode);
832
+ kv('projectId', projectId);
833
+ kv('vault', vaultRoot);
834
+ kv('branch', branch);
835
+ if (!out.vaultExists) {
836
+ warn(`vault directory does not exist — run \`bizar memory init\` or \`bizar memory sync\``);
837
+ } else {
838
+ kv('noteCount', String(out.noteCount));
839
+ }
840
+ if (out.git) {
841
+ if (out.git.error) {
842
+ kv('git', chalk.yellow(out.git.error));
843
+ } else {
844
+ const cleanStr = out.git.clean ? chalk.green('clean') : chalk.red('dirty');
845
+ kv('git', `${out.git.branch} (${cleanStr})`);
846
+ if (out.git.ahead) kv('ahead', String(out.git.ahead));
847
+ if (out.git.behind) kv('behind', String(out.git.behind));
848
+ }
849
+ }
850
+ if (out.lightrag) {
851
+ if (out.lightrag.error) {
852
+ kv('lightrag', chalk.gray(`status unavailable (${out.lightrag.error})`));
853
+ } else if (!out.lightrag.enabled) {
854
+ kv('lightrag', chalk.gray('disabled'));
855
+ } else if (!out.lightrag.installed) {
856
+ kv('lightrag', chalk.yellow('not installed — `uv tool install "lightrag-hku[api]"`'));
857
+ } else {
858
+ const runningStr = out.lightrag.running
859
+ ? chalk.green(`${out.lightrag.host}:${out.lightrag.port} (running)`)
860
+ : chalk.yellow(`${out.lightrag.host}:${out.lightrag.port} (not running)`);
861
+ kv('lightrag', runningStr);
862
+ }
863
+ }
864
+ if (out.lastReindex) {
865
+ const lr = out.lastReindex;
866
+ const lrStr = `${new Date(lr.finishedAt).toLocaleString()} — ${lr.ok ? chalk.green(`${lr.inserted}/${lr.noteCount} ok`) : chalk.red(`${lr.failed} failed`)}`;
867
+ kv('lastReindex', lrStr);
868
+ }
827
869
  console.log();
828
870
  }
829
871
 
@@ -1606,8 +1648,10 @@ async function cmdDelete(args) {
1606
1648
  /**
1607
1649
  * @param {string} subcommand
1608
1650
  * @param {string[]} args
1651
+ * @param {{ wantJson?: boolean }} opts
1609
1652
  */
1610
- export async function runMemory(subcommand, args) {
1653
+ export async function runMemory(subcommand, args, opts = {}) {
1654
+ const { wantJson = false } = opts;
1611
1655
  switch (subcommand) {
1612
1656
  case 'init':
1613
1657
  await cmdInit(args);
@@ -1616,7 +1660,7 @@ export async function runMemory(subcommand, args) {
1616
1660
  await cmdSetup(args);
1617
1661
  break;
1618
1662
  case 'status':
1619
- await cmdStatus(args);
1663
+ await cmdStatus(args, { wantJson });
1620
1664
  break;
1621
1665
  case 'link':
1622
1666
  await cmdLink(args);
package/cli/provision.mjs CHANGED
@@ -446,7 +446,10 @@ export async function ensureNpmPackage(pkg, { mode, dryRun, force }) {
446
446
  // processes are reading files inside the npm-global install dir. We
447
447
  // can't replace those files atomically while they're open. The caller
448
448
  // is expected to have already killed them via ensureInstancesKilled().
449
- const r = spawnSync('npm', ['install', '-g', `${pkg}@latest`], { stdio: 'inherit' });
449
+ const r = spawnSync('npm', ['install', '-g', `${pkg}@latest`], { stdio: 'inherit', timeout: 600000 });
450
+ if (r.status === null && r.error?.code === 'ETIMEDOUT') {
451
+ return { ok: false, message: `${pkg} install timed out after 10 minutes`, installed: current };
452
+ }
450
453
  if (r.status !== 0) {
451
454
  return { ok: false, message: `${pkg} install failed`, installed: current };
452
455
  }
@@ -471,7 +474,10 @@ export async function updateOpencodeCli({ dryRun, force }) {
471
474
  return { ok: true, message: 'opencode updated via `opencode upgrade`' };
472
475
  }
473
476
  console.log(chalk.dim(' opencode upgrade not available; falling back to npm'));
474
- const r2 = spawnSync('npm', ['install', '-g', 'opencode-ai@latest'], { stdio: 'inherit' });
477
+ const r2 = spawnSync('npm', ['install', '-g', 'opencode-ai@latest'], { stdio: 'inherit', timeout: 600000 });
478
+ if (r2.status === null && r2.error?.code === 'ETIMEDOUT') {
479
+ return { ok: false, message: 'opencode install timed out after 10 minutes' };
480
+ }
475
481
  if (r2.status === 0) {
476
482
  return { ok: true, message: 'opencode updated via npm' };
477
483
  }
package/install.sh CHANGED
@@ -322,8 +322,6 @@ main() {
322
322
  ;;
323
323
  esac
324
324
 
325
- print_banner
326
-
327
325
  # ── Hand off to the unified provisioner (Node) ─────────────────────────
328
326
  # All cross-OS work (agent files, plugin copy, opencode.json patching,
329
327
  # skills install, doctor check) lives in `cli/provision.mjs:runProvision`.
@@ -350,6 +348,7 @@ main() {
350
348
  warn "provisioner exited with code $rc"
351
349
  exit "$rc"
352
350
  fi
351
+ print_banner
353
352
  else
354
353
  warn "cli/provision.mjs not found — agent files / plugin / opencode.json"
355
354
  warn " were NOT synced. Run \`bizar install\` from a checkout to fix."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polderlabs/bizar",
3
- "version": "4.5.1",
3
+ "version": "4.5.2",
4
4
  "description": "Norse-pantheon multi-agent system for opencode — 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, opencode plugin, and typed SDK.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,7 +22,7 @@
22
22
  "build:dash": "vite build",
23
23
  "test:sdk": "node_modules/.bin/vitest run --root packages/sdk",
24
24
  "test:sdk:watch": "node_modules/.bin/vitest --root packages/sdk",
25
- "test": "npm run typecheck && npm run test:sdk && bun test plugins/bizar/tests/loop.test.ts plugins/bizar/tests/block.test.ts plugins/bizar/tests/stall-think.test.ts plugins/bizar/tests/tools/bg-get-comments.test.ts plugins/bizar/tests/tools/bg-spawn-delegation.test.ts plugins/bizar/tests/tools/opencode-runner.test.ts plugins/bizar/tests/settings.test.ts plugins/bizar/tests/commands.test.ts plugins/bizar/tests/commands-impl.test.ts plugins/bizar/tests/tools/plan-action.test.ts plugins/bizar/tests/tools/wait-for-feedback.test.ts plugins/bizar/tests/tools/read-glyph-feedback.test.ts plugins/bizar/tests/reasoning-clean.test.ts plugins/bizar/tests/key-rotation.test.ts && node bizar-dash/tests/smoke-v2.mjs && node --test bizar-dash/tests/path-safe.test.mjs bizar-dash/tests/tmux-wrap.test.mjs bizar-dash/tests/opencode-sessions-detail.test.mjs bizar-dash/tests/opencode-runner.test.mjs bizar-dash/tests/mod-instructions.node.test.mjs bizar-dash/tests/mod-upgrade.node.test.mjs bizar-dash/tests/graphify-mod-spawn.node.test.mjs bizar-dash/tests/no-agent-browser.node.test.mjs bizar-dash/tests/providers-store-backup-keys.node.test.mjs bizar-dash/tests/dashboard-ports.test.mjs bizar-dash/tests/submit-feedback.test.mjs bizar-dash/tests/yaml.test.mjs bizar-dash/tests/memory-store.test.mjs bizar-dash/tests/memory-schema.test.mjs bizar-dash/tests/memory-secrets.test.mjs bizar-dash/tests/memory-git.test.mjs bizar-dash/tests/memory-sync.test.mjs bizar-dash/tests/obsidian-back-compat.test.mjs bizar-dash/tests/memory-lightrag.test.mjs bizar-dash/tests/memory-config.test.mjs bizar-dash/tests/memory-cli.test.mjs bizar-dash/tests/memory-cli-readlistdelete.test.mjs bizar-dash/tests/memory-cli-setup.test.mjs bizar-dash/tests/memory-conflicts.test.mjs bizar-dash/tests/memory-namespace.test.mjs bizar-dash/tests/memory-path-safety.test.mjs bizar-dash/tests/memory-protocol-drift.test.mjs bizar-dash/tests/memory-roundtrip.test.mjs",
25
+ "test": "npm run typecheck && npm run test:sdk && bun test plugins/bizar/tests/loop.test.ts plugins/bizar/tests/block.test.ts plugins/bizar/tests/stall-think.test.ts plugins/bizar/tests/tools/bg-get-comments.test.ts plugins/bizar/tests/tools/bg-spawn-delegation.test.ts plugins/bizar/tests/tools/opencode-runner.test.ts plugins/bizar/tests/settings.test.ts plugins/bizar/tests/commands.test.ts plugins/bizar/tests/commands-impl.test.ts plugins/bizar/tests/tools/plan-action.test.ts plugins/bizar/tests/tools/wait-for-feedback.test.ts plugins/bizar/tests/tools/read-glyph-feedback.test.ts plugins/bizar/tests/reasoning-clean.test.ts plugins/bizar/tests/key-rotation.test.ts && node bizar-dash/tests/smoke-v2.mjs && node --test bizar-dash/tests/path-safe.test.mjs bizar-dash/tests/tmux-wrap.test.mjs bizar-dash/tests/opencode-sessions-detail.test.mjs bizar-dash/tests/opencode-runner.test.mjs bizar-dash/tests/mod-instructions.node.test.mjs bizar-dash/tests/mod-upgrade.node.test.mjs bizar-dash/tests/graphify-mod-spawn.node.test.mjs bizar-dash/tests/no-agent-browser.node.test.mjs bizar-dash/tests/providers-store-backup-keys.node.test.mjs bizar-dash/tests/dashboard-ports.test.mjs bizar-dash/tests/submit-feedback.test.mjs bizar-dash/tests/yaml.test.mjs bizar-dash/tests/memory-store.test.mjs bizar-dash/tests/memory-schema.test.mjs bizar-dash/tests/memory-secrets.test.mjs bizar-dash/tests/memory-git.test.mjs bizar-dash/tests/memory-sync.test.mjs bizar-dash/tests/obsidian-back-compat.test.mjs bizar-dash/tests/memory-lightrag.test.mjs bizar-dash/tests/memory-config.test.mjs bizar-dash/tests/memory-cli.test.mjs bizar-dash/tests/memory-cli-readlistdelete.test.mjs bizar-dash/tests/memory-cli-setup.test.mjs bizar-dash/tests/memory-conflicts.test.mjs bizar-dash/tests/memory-namespace.test.mjs bizar-dash/tests/memory-path-safety.test.mjs bizar-dash/tests/memory-protocol-drift.test.mjs bizar-dash/tests/memory-roundtrip.test.mjs bizar-dash/tests/cli-bugfixes.test.mjs bizar-dash/tests/server-bugfixes.test.mjs bizar-dash/tests/frontend-bugfixes.test.mjs",
26
26
  "build": "npm run build:sdk && npm run build:dash",
27
27
  "prepublishOnly": "npm run build"
28
28
  },
@@ -85,7 +85,7 @@
85
85
  "@vitejs/plugin-react": "^4.3.0",
86
86
  "typescript": "^5.6.0",
87
87
  "vite": "^5.0.0",
88
- "vitest": "^2.1.0"
88
+ "vitest": "^4.1.9"
89
89
  },
90
90
  "allowScripts": {
91
91
  "better-sqlite3@12.11.1": true