@polderlabs/bizar 4.4.3 → 4.4.5

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.
@@ -29,10 +29,10 @@
29
29
  }
30
30
  })();
31
31
  </script>
32
- <script type="module" crossorigin src="/assets/main-B3RgW6FS.js"></script>
33
- <link rel="modulepreload" crossorigin href="/assets/mobile-Dvq2d53Y.js">
32
+ <script type="module" crossorigin src="/assets/main-C4Dq4wTz.js"></script>
33
+ <link rel="modulepreload" crossorigin href="/assets/mobile-CaZ0gEeJ.js">
34
34
  <link rel="stylesheet" crossorigin href="/assets/mobile-CsZQAswA.css">
35
- <link rel="stylesheet" crossorigin href="/assets/main-DlJ8wgLR.css">
35
+ <link rel="stylesheet" crossorigin href="/assets/main-Nq8Dq3VR.css">
36
36
  </head>
37
37
  <body>
38
38
  <div id="root"></div>
@@ -12,8 +12,8 @@
12
12
  <link rel="preconnect" href="https://fonts.googleapis.com" />
13
13
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
14
14
  <link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
15
- <script type="module" crossorigin src="/assets/mobile-DbxIw8BG.js"></script>
16
- <link rel="modulepreload" crossorigin href="/assets/mobile-Dvq2d53Y.js">
15
+ <script type="module" crossorigin src="/assets/mobile-CQTXbuHq.js"></script>
16
+ <link rel="modulepreload" crossorigin href="/assets/mobile-CaZ0gEeJ.js">
17
17
  <link rel="stylesheet" crossorigin href="/assets/mobile-CsZQAswA.css">
18
18
  </head>
19
19
  <body>
package/cli/install.mjs CHANGED
@@ -26,15 +26,12 @@ const AGENT_FILES = [
26
26
  ];
27
27
 
28
28
  /**
29
- * Install the Bizar opencode plugin from the separate global npm package
30
- * `@polderlabs/bizar-plugin`. The main `@polderlabs/bizar` package
31
- * no longer ships `plugins/bizar/` — the plugin lives in its own scoped package
32
- * so it can be versioned and published independently.
29
+ * Install the Bizar opencode plugin from this package's own
30
+ * `plugins/bizar/` directory into `~/.config/opencode/plugins/bizar/`.
33
31
  *
34
- * If the plugin package is globally installed, copies its contents into
35
- * `~/.config/opencode/plugins/bizar/` (or the platform-equivalent path via
36
- * `opencodeConfigDir()`). Otherwise, prints a hint directing the user to run
37
- * `npm install -g @polderlabs/bizar-plugin`.
32
+ * v4.0.0 consolidated everything into one npm package, so the plugin
33
+ * source ships with `@polderlabs/bizar` itself no separate
34
+ * `@polderlabs/bizar-plugin` package, no git clone, no fresh checkout.
38
35
  *
39
36
  * Symlink guard (v3.12.2): if the dest is a symlink (e.g. created by
40
37
  * `bizar dev-link`), do NOT overwrite it. The copy below would otherwise
@@ -43,26 +40,22 @@ const AGENT_FILES = [
43
40
  * confirming the user really wants the deployed copy back).
44
41
  *
45
42
  * node_modules copy: the plugin imports `@polderlabs/bizar-sdk`, a
46
- * workspace-internal package not on the public registry. The npm source
47
- * bundles the SDK into its own `node_modules/`. After copying the plugin
48
- * files, this function ALSO copies the source's `node_modules/` to the
49
- * deployed `node_modules/` so Bun can resolve the import when the plugin
50
- * is loaded from `~/.config/opencode/plugins/bizar/`. Without this, the
51
- * plugin silently fails to load.
43
+ * workspace-internal package not on the public registry. After copying
44
+ * the plugin files, this function ALSO copies the source's `node_modules/`
45
+ * to the deployed `node_modules/` so Bun can resolve the import when the
46
+ * plugin is loaded from `~/.config/opencode/plugins/bizar/`. Without
47
+ * this, the plugin silently fails to load.
52
48
  *
53
49
  * Pass `{ silent: true }` to suppress the warning prints; the function
54
50
  * still returns `true` if the dest is already in the desired state.
55
51
  *
56
- * Pass `{ sourceDir: '/path/to/fake' }` (test seam) to bypass the
57
- * `npm root -g` lookup and use a caller-supplied source path. Used by
58
- * cli/install.test.mjs to drive the function against a controlled
59
- * filesystem without touching the real global npm root.
52
+ * Pass `{ sourceDir: '/path/to/fake' }` (test seam) to drive the function
53
+ * against a controlled filesystem without touching the real install.
60
54
  *
61
55
  * Returns `true` if the plugin was installed (or already in place),
62
56
  * `false` otherwise. Never throws.
63
57
  */
64
58
  export async function installPluginFromGlobal(opts = {}) {
65
- const { execSync } = await import('node:child_process');
66
59
  const { mkdir, readdir, copyFile } = await import('node:fs/promises');
67
60
  const { join } = await import('node:path');
68
61
 
@@ -87,7 +80,7 @@ export async function installPluginFromGlobal(opts = {}) {
87
80
  }
88
81
  console.log(
89
82
  chalk.yellow(
90
- ' ⚠ ~/.config/opencode/plugins/bizar is a dev symlink — skipping npm copy.',
83
+ ' ⚠ ~/.config/opencode/plugins/bizar is a dev symlink — skipping copy.',
91
84
  ),
92
85
  );
93
86
  console.log(
@@ -100,26 +93,19 @@ export async function installPluginFromGlobal(opts = {}) {
100
93
  }
101
94
 
102
95
  // ── Resolve source path ─────────────────────────────────────────────────────
103
- // Production: `npm root -g` + `@polderlabs/bizar-plugin`. Tests can pass
104
- // `opts.sourceDir` to bypass the lookup entirely.
96
+ // v4.4.5 the plugin ships inside this package at <pkg>/plugins/bizar/.
97
+ // No separate npm package, no git clone.
105
98
  let pluginPath;
106
99
  if (opts.sourceDir) {
107
100
  pluginPath = opts.sourceDir;
108
101
  } else {
109
- let globalRoot;
110
- try {
111
- globalRoot = execSync('npm root -g', { stdio: ['ignore', 'pipe', 'ignore'] })
112
- .toString()
113
- .trim();
114
- } catch {
115
- console.log(chalk.yellow(' ⚠ Could not determine npm global root — skipping plugin install'));
116
- return false;
117
- }
118
- pluginPath = join(globalRoot, '@polderlabs', 'bizar-plugin');
102
+ // __dirname is `<pkg>/cli/`, so ../plugins/bizar is the canonical source.
103
+ pluginPath = join(__dirname, '..', 'plugins', 'bizar');
119
104
  }
120
105
  if (!existsSync(pluginPath)) {
121
- console.log(chalk.dim(' Bizar plugin not installed globally. To install it:'));
122
- console.log(chalk.dim(' npm install -g @polderlabs/bizar-plugin'));
106
+ console.log(chalk.red(` Plugin source not found at ${pluginPath}`));
107
+ console.log(chalk.dim(' This package appears to be missing plugins/bizar/. Reinstall:'));
108
+ console.log(chalk.dim(' npm install -g @polderlabs/bizar --force'));
123
109
  return false;
124
110
  }
125
111
 
@@ -311,42 +297,30 @@ async function isPackageInstalled(name) {
311
297
  }
312
298
 
313
299
  async function promptAndInstallOptional() {
314
- // Plugin
315
- const pluginInstalled = await isPackageInstalled('@polderlabs/bizar-plugin');
316
- if (!pluginInstalled) {
317
- console.log('');
318
- console.log(' The Bizar opencode plugin is required for the /bizar command and agent integration.');
319
- const install = await promptYesNo(
320
- 'Install @polderlabs/bizar-plugin?',
321
- true,
322
- );
323
- if (install) {
324
- try {
325
- console.log(' Installing @polderlabs/bizar-plugin...');
326
- execSync('npm install -g @polderlabs/bizar-plugin', { stdio: 'inherit' });
327
- console.log(' ✓ @polderlabs/bizar-plugin installed');
328
- } catch (err) {
329
- console.log(` ✗ Failed to install @polderlabs/bizar-plugin: ${err.message}`);
330
- console.log(' You can install it later with: npm install -g @polderlabs/bizar-plugin');
331
- }
332
- } else {
333
- console.log(' Skipped. Install later with: npm install -g @polderlabs/bizar-plugin');
334
- }
300
+ // v4.4.5 — Plugin and dashboard are both shipped inside this package.
301
+ // No separate npm install step is required for either. The plugin
302
+ // copy happens via installPluginFromGlobal() in runInstaller(); the
303
+ // dashboard is loaded directly from this package's bizar-dash/src/.
304
+ // We just verify they're present here and warn loudly if not.
305
+ const pluginPath = join(__dirname, '..', 'plugins', 'bizar');
306
+ if (!existsSync(pluginPath)) {
307
+ console.error('');
308
+ console.error(' ✗ Plugin source not found at plugins/bizar/.');
309
+ console.error(' This package is missing the plugin source. Reinstall:');
310
+ console.error(' npm install -g @polderlabs/bizar --force');
335
311
  } else {
336
- console.log(' ✓ @polderlabs/bizar-plugin already installed');
312
+ console.log(' ✓ Plugin source present (plugins/bizar/)');
337
313
  }
338
314
 
339
- // Dashboard — v4.0.0: ships inside this package at <repo>/bizar-dash/
340
- // Verify the directory is present; it's a corrupted install if missing.
341
315
  const dashDir = join(__dirname, '..', 'bizar-dash');
342
316
  const dashPkgJson = join(dashDir, 'package.json');
343
317
  if (!existsSync(dashPkgJson)) {
344
318
  console.error('');
345
- console.error(' ✗ Dashboard directory not found at bizar-dash/.');
346
- console.error(' This looks like a corrupted install.');
347
- console.error(' Please report at: github.com/DrB0rk/BizarHarness/issues');
319
+ console.error(' ✗ Dashboard source not found at bizar-dash/.');
320
+ console.error(' This package is missing the dashboard source. Reinstall:');
321
+ console.error(' npm install -g @polderlabs/bizar --force');
348
322
  } else {
349
- console.log(' ✓ Dashboard directory present (bizar-dash/)');
323
+ console.log(' ✓ Dashboard source present (bizar-dash/)');
350
324
  }
351
325
  }
352
326
 
package/cli/update.mjs CHANGED
@@ -47,12 +47,13 @@ const __filename = fileURLToPath(import.meta.url);
47
47
  const __dirname = dirname(__filename);
48
48
  const REPO_ROOT = join(__dirname, '..');
49
49
 
50
+ // v4.4.5 — The plugin and dashboard are both shipped inside @polderlabs/bizar.
51
+ // No separate @polderlabs/bizar-plugin or @polderlabs/bizar-dash packages.
52
+ // Updating the main package updates everything.
50
53
  const PKG_MAIN = '@polderlabs/bizar';
51
- const PKG_DASH = '@polderlabs/bizar-dash';
52
- const PKG_PLUGIN = '@polderlabs/bizar-plugin';
53
54
 
54
55
  // All known components, in the order they should be prompted + updated.
55
- const COMPONENTS = ['opencode', 'bizar', 'dash', 'plugin'];
56
+ const COMPONENTS = ['opencode', 'bizar'];
56
57
 
57
58
  // ---------------------------------------------------------------------------
58
59
  // Config paths (mirror the dashboard + service for consistency)
@@ -431,11 +432,13 @@ function spawnFreshDashboard({ port } = {}) {
431
432
  } catch {
432
433
  return { ok: false, message: 'could not locate npm global root' };
433
434
  }
434
- const dashBin = join(globalRoot, ...PKG_DASH.split('/'), 'src', 'cli.mjs');
435
+ // v4.4.5 Dashboard ships inside @polderlabs/bizar (no separate
436
+ // @polderlabs/bizar-dash). Resolve the main package's cli.mjs.
437
+ const dashBin = join(globalRoot, '@polderlabs', 'bizar', 'cli', 'bin.mjs');
435
438
  if (!existsSync(dashBin)) {
436
439
  return {
437
440
  ok: false,
438
- message: `dashboard binary not found at ${dashBin} (was @polderlabs/bizar-dash installed?)`,
441
+ message: `dashboard binary not found at ${dashBin} (was @polderlabs/bizar installed?)`,
439
442
  };
440
443
  }
441
444
  try {
@@ -536,59 +539,6 @@ async function installSkills({ dryRun = false } = {}) {
536
539
  return results;
537
540
  }
538
541
 
539
- /**
540
- * Rebuild the bizar-dash frontend with Vite.
541
- */
542
- function rebuildDashboard({ dryRun = false } = {}) {
543
- const dashDir = join(REPO_ROOT, 'bizar-dash');
544
- const pkgJson = join(dashDir, 'package.json');
545
- if (!existsSync(pkgJson)) {
546
- return { ok: false, message: 'bizar-dash/package.json not found — is the dashboard cloned?' };
547
- }
548
- if (dryRun) {
549
- console.log(chalk.dim(' [dry-run] would run: npx vite build (in bizar-dash/)'));
550
- return { ok: true, message: '[dry-run] dashboard rebuild' };
551
- }
552
- console.log(chalk.dim('\n Rebuilding dashboard...'));
553
- const r = spawnSync('npx', ['vite', 'build'], {
554
- stdio: 'inherit', cwd: dashDir, timeout: 120000,
555
- });
556
- if (r.status === 0) {
557
- return { ok: true, message: 'dashboard rebuilt' };
558
- }
559
- return { ok: false, message: 'dashboard rebuild failed (try: cd bizar-dash && npx vite build)' };
560
- }
561
-
562
- /**
563
- * Detect and run the project's test suite. Checks for common test runners
564
- * (npm test, pytest, cargo test, go test) and runs the first one found.
565
- */
566
- function runTestGate({ dryRun = false } = {}) {
567
- if (dryRun) {
568
- console.log(chalk.dim(' [dry-run] would detect and run local test suite'));
569
- return { ok: true, message: '[dry-run] test gate' };
570
- }
571
- const cwd = process.cwd();
572
- const suites = [
573
- { cmd: 'npm test', check: 'package.json' },
574
- { cmd: 'pytest', check: 'pyproject.toml' },
575
- { cmd: 'cargo test', check: 'Cargo.toml' },
576
- { cmd: 'go test ./...', check: 'go.mod' },
577
- ];
578
- for (const suite of suites) {
579
- try {
580
- if (existsSync(join(cwd, suite.check))) {
581
- console.log(chalk.dim(`\n Running test suite: ${suite.cmd}...`));
582
- execSync(suite.cmd, { stdio: 'inherit', timeout: 120000, cwd });
583
- return { ok: true, message: `test gate passed (${suite.cmd})` };
584
- }
585
- } catch {
586
- return { ok: false, message: `test gate failed (${suite.cmd})` };
587
- }
588
- }
589
- return { ok: true, message: 'no test suite detected (skipped)' };
590
- }
591
-
592
542
  // ---------------------------------------------------------------------------
593
543
  // Prompt helpers
594
544
  // ---------------------------------------------------------------------------
@@ -603,9 +553,7 @@ async function promptForUpdates(forceAll) {
603
553
  message: 'Which components do you want to update?',
604
554
  choices: [
605
555
  { name: 'opencode (the opencode CLI itself)', value: 'opencode', checked: true },
606
- { name: `bizar (${PKG_MAIN})`, value: 'bizar', checked: true },
607
- { name: `bizar dash (${PKG_DASH}) — web dashboard`, value: 'dash', checked: true },
608
- { name: `plugin (${PKG_PLUGIN})`, value: 'plugin', checked: true },
556
+ { name: `bizar (${PKG_MAIN}) — includes plugin + dashboard`, value: 'bizar', checked: true },
609
557
  ],
610
558
  },
611
559
  ]);
@@ -717,24 +665,16 @@ export async function runUpdate(subargs = []) {
717
665
  const cur = {
718
666
  opencode: currentVersion('opencode-ai'),
719
667
  bizar: currentVersion(PKG_MAIN),
720
- dash: currentVersion(PKG_DASH),
721
- plugin: currentVersion(PKG_PLUGIN),
722
668
  };
723
669
  const latest = {
724
670
  opencode: latestVersion('opencode-ai'),
725
671
  bizar: latestVersion(PKG_MAIN),
726
- dash: latestVersion(PKG_DASH),
727
- plugin: latestVersion(PKG_PLUGIN),
728
672
  };
729
673
 
730
674
  console.log('');
731
675
  console.log(' Installed vs. latest:');
732
676
  for (const k of COMPONENTS) {
733
- const label =
734
- k === 'plugin' ? PKG_PLUGIN :
735
- k === 'dash' ? PKG_DASH :
736
- k === 'bizar' ? PKG_MAIN :
737
- 'opencode-ai';
677
+ const label = k === 'bizar' ? PKG_MAIN : 'opencode-ai';
738
678
  const c = cur[k] ?? '(not installed)';
739
679
  const l = latest[k] ?? '(unknown)';
740
680
  const same = c === l;
@@ -824,23 +764,15 @@ export async function runUpdate(subargs = []) {
824
764
  console.log(chalk.bold(` → ${PKG_MAIN}`));
825
765
  results.push(['bizar', updatePackage(PKG_MAIN, { dryRun })]);
826
766
  }
827
- if (selected.has('dash')) {
828
- console.log(chalk.bold(` → ${PKG_DASH}`));
829
- results.push(['dash', updatePackage(PKG_DASH, { dryRun })]);
830
- }
831
- if (selected.has('plugin')) {
832
- console.log(chalk.bold(` → ${PKG_PLUGIN}`));
833
- results.push(['plugin', updatePackage(PKG_PLUGIN, { dryRun })]);
834
- }
835
767
 
836
768
  // 4. Re-run the install script if anything relevant changed.
837
769
  const anySuccess = results.some(([, r]) => r.ok);
838
- if (anySuccess && (selected.has('bizar') || selected.has('plugin'))) {
770
+ if (anySuccess && selected.has('bizar')) {
839
771
  console.log('');
840
772
  if (dryRun) {
841
773
  console.log(
842
774
  chalk.dim(
843
- ' [dry-run] would re-run install script (bin.mjs --setup or install.sh)',
775
+ ' [dry-run] would re-run install.sh to refresh agent files + plugin copy',
844
776
  ),
845
777
  );
846
778
  } else {
@@ -849,7 +781,7 @@ export async function runUpdate(subargs = []) {
849
781
  console.log(chalk.green(`\n ✓ ${rerun.message}`));
850
782
  } else {
851
783
  console.log(chalk.yellow(`\n ⚠ ${rerun.message}`));
852
- console.log(chalk.dim(' Run `bash install.sh` from the Bizar repo manually.'));
784
+ console.log(chalk.dim(' Run `bizar install` to refresh agent files + plugin copy.'));
853
785
  }
854
786
  }
855
787
  }
@@ -859,27 +791,15 @@ export async function runUpdate(subargs = []) {
859
791
  const skillResults = await installSkills({ dryRun });
860
792
  const skillOk = skillResults.length === 0 || skillResults.every((r) => r.ok);
861
793
 
862
- // ── Rebuild dashboard ───────────────────────────────────────────────
863
- console.log(chalk.bold('\n → Rebuilding dashboard...'));
864
- const dashRebuild = rebuildDashboard({ dryRun });
865
- if (dashRebuild.ok) {
866
- console.log(chalk.green(` ${dashRebuild.message}`));
867
- } else {
868
- console.log(chalk.yellow(` ⚠ ${dashRebuild.message}`));
869
- }
870
-
871
- // ── Test gate ───────────────────────────────────────────────────────
872
- console.log(chalk.bold('\n → Running test gate...'));
873
- const testResult = runTestGate({ dryRun });
874
- if (testResult.ok) {
875
- console.log(chalk.green(` ✓ ${testResult.message}`));
876
- } else {
877
- console.log(chalk.red(` ✗ ${testResult.message}`));
878
- }
794
+ // v4.4.5 Dashboard dist ships prebuilt inside the npm package. No
795
+ // rebuild step is needed (and we can't run `vite build` from the
796
+ // installed package anyway node_modules/vite lives outside the
797
+ // plugin's runtime context). The next launch picks up the new dist
798
+ // when `bizar dash start --bg` runs.
879
799
 
880
800
  // ── Restart dashboard ─────────────────────────────────────────────
881
- // Restart if it was running before, or if the dashboard was just rebuilt.
882
- if (restartAfter && (instances.dashboard || dashRebuild.ok)) {
801
+ // Restart if it was running before.
802
+ if (restartAfter && instances.dashboard) {
883
803
  if (dryRun) {
884
804
  console.log('');
885
805
  console.log(chalk.dim(' [dry-run] would restart dashboard with the new code'));
@@ -908,17 +828,10 @@ export async function runUpdate(subargs = []) {
908
828
  const marker = sr.ok ? chalk.green('✓') : chalk.red('✗');
909
829
  console.log(` ${marker} ${'skill/skills'.padEnd(10)} ${sr.ok ? 'installed' : `failed: ${sr.skill}`}`);
910
830
  }
911
- if (!dashRebuild.ok) {
912
- console.log(` ${chalk.yellow('⚠')} ${'dash'.padEnd(10)} ${dashRebuild.message}`);
913
- }
914
- const testMarker = testResult.ok ? chalk.green('✓') : chalk.red('✗');
915
- console.log(` ${testMarker} ${'test-gate'.padEnd(10)} ${testResult.message}`);
916
831
 
917
832
  const allResults = [
918
833
  ...results.map(([, r]) => r),
919
834
  ...skillResults,
920
- dashRebuild,
921
- testResult,
922
835
  ];
923
836
  const anyFail = allResults.some((r) => !r.ok);
924
837
  if (anyFail) {
package/install.sh CHANGED
@@ -215,61 +215,97 @@ ensure_node() {
215
215
  note "Node.js installed: $(node --version)"
216
216
  }
217
217
 
218
- # ── git operations (clone or update) ───────────────────────────────────────────
218
+ # ── Standalone installer (no git clone) ─────────────────────────────────────────
219
+ # v4.4.5 — The plugin, agents, commands, hooks, and dashboard ALL ship inside
220
+ # this package. No separate npm install, no git clone, no separate package
221
+ # lookup. install.sh runs entirely against its own `$REPO_DIR` (which is the
222
+ # installed package directory — `<npm root -g>/@polderlabs/bizar/`).
219
223
 
220
224
  ensure_repo() {
221
- if $UPDATE_MODE; then
222
- section "Updating BizarHarness repository"
223
- action "Pulling latest via git pull --ff-only..."
224
- dry git -C "$REPO_DIR" pull --ff-only
225
- note "repository updated"
226
- return
225
+ # v4.4.5 — No-op. Everything ships with the package. We still log a note
226
+ # so users upgrading from older versions see that the git-clone step is
227
+ # intentionally gone.
228
+ if [ -d "$REPO_DIR/plugins/bizar" ] && [ -d "$REPO_DIR/bizar-dash" ]; then
229
+ note "using bundled plugin + dashboard from $REPO_DIR"
230
+ else
231
+ err "package missing required files (plugins/bizar or bizar-dash)"
232
+ err "this looks like a corrupted install — try: npm install -g @polderlabs/bizar --force"
233
+ exit 1
227
234
  fi
228
235
 
229
- # If we're already inside the repo, skip clone.
230
- if [ -d "$REPO_DIR/.git" ]; then
231
- note "repository already present at $REPO_DIR"
232
- if $FORCE || $UPDATE_MODE; then
233
- dry git -C "$REPO_DIR" pull --ff-only
236
+ # Clean up any stale separate-repo clone left over from v3.x installs.
237
+ local stale_clone="$(dirname "$REPO_DIR")/BizarHarness"
238
+ if [ -d "$stale_clone" ] && [ "$stale_clone" != "$REPO_DIR" ]; then
239
+ if $DRY_RUN; then
240
+ dim " would remove stale v3.x clone at $stale_clone"
241
+ else
242
+ action "Removing stale v3.x repo clone at $stale_clone..."
243
+ rm -rf "$stale_clone" 2>/dev/null && note "removed" || dim " (could not remove; harmless)"
234
244
  fi
235
- return
236
- fi
237
-
238
- section "Cloning BizarHarness repository"
239
- local target
240
- target="$(dirname "$REPO_DIR")/BizarHarness"
241
- if [ ! -d "$target" ]; then
242
- action "Cloning into $target..."
243
- dry git clone https://github.com/DrB0rk/BizarHarness.git "$target"
244
- note "cloned"
245
- else
246
- note "already cloned at $target"
247
245
  fi
248
246
  }
249
247
 
250
- # ── Install agent/config files via cli/install.mjs ──────────────────────────────
248
+ # ── Copy agent / config / dashboard files ──────────────────────────────────────
251
249
 
252
250
  install_config() {
253
251
  section "Installing BizarHarness config files"
254
252
 
255
253
  if $DRY_RUN; then
256
- dim " would run: node \"$REPO_DIR/cli/install.mjs\" --non-interactive"
254
+ dim " would copy agents/, commands/, hooks/, skills/ to ~/.config/opencode/"
257
255
  return
258
256
  fi
259
257
 
260
- if [ -f "$REPO_DIR/cli/install.mjs" ]; then
261
- action "Running cli/install.mjs (agent files, skills, plugin)..."
258
+ local dst="${XDG_CONFIG_HOME:-$HOME/.config}/opencode"
259
+ mkdir -p "$dst/agents" "$dst/agents/_shared" "$dst/command" "$dst/commands" "$dst/skill" "$dst/skills" 2>/dev/null
260
+
261
+ # Agents
262
+ if [ -d "$REPO_DIR/config/agents" ]; then
263
+ action "Copying agent files..."
264
+ cp -R "$REPO_DIR/config/agents/." "$dst/agents/" 2>/dev/null && note "agents synced" || warn "agent copy incomplete"
265
+ fi
266
+
267
+ # Slash commands
268
+ if [ -d "$REPO_DIR/config/command" ]; then
269
+ cp -R "$REPO_DIR/config/command/." "$dst/command/" 2>/dev/null
270
+ fi
271
+ if [ -d "$REPO_DIR/config/commands" ]; then
272
+ cp -R "$REPO_DIR/config/commands/." "$dst/commands/" 2>/dev/null
273
+ fi
274
+
275
+ # Skills (bundled)
276
+ for skill in obsidian glyph read-the-damn-docs; do
277
+ if [ -d "$REPO_DIR/config/skills/$skill" ]; then
278
+ cp -R "$REPO_DIR/config/skills/$skill" "$dst/skill/" 2>/dev/null
279
+ cp -R "$REPO_DIR/config/skills/$skill" "$dst/skills/" 2>/dev/null
280
+ fi
281
+ done
282
+ note "skills installed"
283
+
284
+ # AGENTS.md
285
+ if [ -f "$REPO_DIR/AGENTS.md" ]; then
286
+ cp "$REPO_DIR/AGENTS.md" "$dst/AGENTS.md" 2>/dev/null && note "AGENTS.md synced" || true
287
+ fi
262
288
 
263
- # cli/install.mjs runInstaller() spawns bash install.sh — we need to pass
264
- # the flags through. Use the canonical entry point with environment hints.
265
- # The installer automatically copies agents, commands, hooks, skills, plugin.
266
- if node "$REPO_DIR/cli/install.mjs" --non-interactive 2>&1; then
267
- note "config files installed"
289
+ # Plugin (copy from <pkg>/plugins/bizar/ to ~/.config/opencode/plugins/bizar/)
290
+ local dst_plugin="$dst/plugins/bizar"
291
+ if [ -d "$REPO_DIR/plugins/bizar" ]; then
292
+ mkdir -p "$dst_plugin"
293
+ # Skip node_modules + dist to keep the deploy dir small; the plugin's
294
+ # package.json declares its deps and Bun resolves them from the user's
295
+ # global node_modules at load time.
296
+ if command -v rsync >/dev/null 2>&1; then
297
+ rsync -a --exclude='node_modules' --exclude='dist' --exclude='.DS_Store' \
298
+ "$REPO_DIR/plugins/bizar/" "$dst_plugin/" 2>/dev/null && note "plugin copied to $dst_plugin" \
299
+ || warn "plugin copy incomplete"
268
300
  else
269
- warn "cli/install.mjs exited non-zerosome config may be incomplete"
301
+ # Fallback: shell glob + cp mirrors rsync's exclude behaviour by
302
+ # pruning after copy.
303
+ cp -R "$REPO_DIR/plugins/bizar/." "$dst_plugin/" 2>/dev/null
304
+ rm -rf "$dst_plugin/node_modules" "$dst_plugin/dist" 2>/dev/null
305
+ note "plugin copied to $dst_plugin (cp fallback)"
270
306
  fi
271
307
  else
272
- warn "cli/install.mjs not found config files not auto-installed"
308
+ warn "plugin source not found at $REPO_DIR/plugins/bizar/"
273
309
  fi
274
310
  }
275
311
 
@@ -370,7 +406,7 @@ install_service() {
370
406
 
371
407
  if [ "$ok" = "yes" ]; then
372
408
  if [ "$skipped" = "yes" ]; then
373
- dim " (service-controller not yet available will be completed when Stream A lands)"
409
+ dim " (service registration deferredre-run \`bizar service install\` to retry)"
374
410
  fi
375
411
  note "service registration complete"
376
412
  else
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polderlabs/bizar",
3
- "version": "4.4.3",
3
+ "version": "4.4.5",
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": {
@@ -19,10 +19,12 @@
19
19
  "scripts": {
20
20
  "typecheck": "tsc --noEmit",
21
21
  "build:sdk": "tsc -p packages/sdk/tsconfig.json",
22
+ "build:dash": "vite build",
22
23
  "test:sdk": "node_modules/.bin/vitest run --root packages/sdk",
23
24
  "test:sdk:watch": "node_modules/.bin/vitest --root packages/sdk",
24
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
- "build": "npm run build:sdk"
26
+ "build": "npm run build:sdk && npm run build:dash",
27
+ "prepublishOnly": "npm run build"
26
28
  },
27
29
  "keywords": [
28
30
  "opencode",