@polderlabs/bizar 4.4.10 → 4.4.12
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/dist/assets/{main-Nq8Dq3VR.css → main-BKXEqU1w.css} +1 -1
- package/bizar-dash/dist/assets/main-EK_fzXn_.js +352 -0
- package/bizar-dash/dist/assets/main-EK_fzXn_.js.map +1 -0
- package/bizar-dash/dist/assets/mobile-Dl1q7Cyq.js.map +1 -1
- package/bizar-dash/dist/index.html +2 -2
- package/bizar-dash/src/server/api.mjs +2 -0
- package/bizar-dash/src/server/minimax.mjs +352 -0
- package/bizar-dash/src/server/mods-loader.mjs +169 -1
- package/bizar-dash/src/server/routes/_shared.mjs +15 -0
- package/bizar-dash/src/server/routes/minimax.mjs +140 -0
- package/bizar-dash/src/web/App.tsx +2 -0
- package/bizar-dash/src/web/components/Topbar.tsx +2 -0
- package/bizar-dash/src/web/lib/types.ts +12 -0
- package/bizar-dash/src/web/main.tsx +1 -0
- package/bizar-dash/src/web/styles/minimax-usage.css +371 -0
- package/bizar-dash/src/web/views/MiniMaxUsage.tsx +543 -0
- package/cli/bin.mjs +39 -6
- package/cli/provision.mjs +182 -2
- package/package.json +1 -1
- package/bizar-dash/dist/assets/main-CEazNxxy.js +0 -347
- package/bizar-dash/dist/assets/main-CEazNxxy.js.map +0 -1
package/cli/provision.mjs
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
import chalk from 'chalk';
|
|
40
40
|
import { execSync, spawn, spawnSync } from 'node:child_process';
|
|
41
|
-
import { existsSync, readFileSync, rmSync, writeFileSync, mkdirSync, statSync } from 'node:fs';
|
|
41
|
+
import { existsSync, readFileSync, readdirSync, rmSync, writeFileSync, mkdirSync, statSync } from 'node:fs';
|
|
42
42
|
import { homedir } from 'node:os';
|
|
43
43
|
import { join, dirname } from 'node:path';
|
|
44
44
|
import { fileURLToPath } from 'node:url';
|
|
@@ -272,6 +272,13 @@ export function detectState({ cwd = process.cwd() } = {}) {
|
|
|
272
272
|
// ── Git checkout? ─────────────────────────────────────────────────
|
|
273
273
|
const gitRepo = existsSync(join(REPO_ROOT, '.git'));
|
|
274
274
|
|
|
275
|
+
// ── Installed mods ─────────────────────────────────────────────────
|
|
276
|
+
// v4.4.11 — `bizar install` and `bizar update` never install or
|
|
277
|
+
// upgrade mods. The list below is informational only. Use
|
|
278
|
+
// `bizar mod install <id>` to add a mod explicitly.
|
|
279
|
+
const MODS_DIR = join(BIZAR_HOME, 'mods');
|
|
280
|
+
const installedMods = listInstalledMods(MODS_DIR);
|
|
281
|
+
|
|
275
282
|
return {
|
|
276
283
|
pkgRoot,
|
|
277
284
|
pkgVersion,
|
|
@@ -302,9 +309,52 @@ export function detectState({ cwd = process.cwd() } = {}) {
|
|
|
302
309
|
opencodeCli,
|
|
303
310
|
headsUpState,
|
|
304
311
|
gitRepo,
|
|
312
|
+
installedMods,
|
|
305
313
|
};
|
|
306
314
|
}
|
|
307
315
|
|
|
316
|
+
/**
|
|
317
|
+
* v4.4.11 — Lightweight read-only scan of `~/.config/bizar/mods/`.
|
|
318
|
+
* Returns one entry per mod folder with the id + enabled flag parsed
|
|
319
|
+
* from mod.json. Never throws; mods with a missing or invalid mod.json
|
|
320
|
+
* are reported as `{id, error}` so the provisioner can surface them.
|
|
321
|
+
*/
|
|
322
|
+
function listInstalledMods(modsDir) {
|
|
323
|
+
const out = [];
|
|
324
|
+
if (!existsSync(modsDir)) return out;
|
|
325
|
+
let entries;
|
|
326
|
+
try {
|
|
327
|
+
entries = readdirSync(modsDir, { withFileTypes: true });
|
|
328
|
+
} catch {
|
|
329
|
+
return out;
|
|
330
|
+
}
|
|
331
|
+
for (const entry of entries) {
|
|
332
|
+
if (!entry.isDirectory()) continue;
|
|
333
|
+
const dir = join(modsDir, entry.name);
|
|
334
|
+
const manifestPath = join(dir, 'mod.json');
|
|
335
|
+
if (!existsSync(manifestPath)) {
|
|
336
|
+
out.push({ id: entry.name, error: 'missing mod.json' });
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
let manifest;
|
|
340
|
+
try {
|
|
341
|
+
manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
342
|
+
} catch {
|
|
343
|
+
out.push({ id: entry.name, error: 'invalid mod.json' });
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
out.push({
|
|
347
|
+
id: manifest.id || entry.name,
|
|
348
|
+
name: manifest.name || entry.name,
|
|
349
|
+
version: manifest.version || '?',
|
|
350
|
+
enabled: manifest.enabled !== false,
|
|
351
|
+
installedAt: manifest.installedAt || null,
|
|
352
|
+
path: dir,
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
return out;
|
|
356
|
+
}
|
|
357
|
+
|
|
308
358
|
/**
|
|
309
359
|
* Lightweight CommonJS-ish require for ESM contexts. Used to detect the
|
|
310
360
|
* service-controller + heads-up modules without paying the static-import
|
|
@@ -681,6 +731,125 @@ export async function runDoctor({ silent = false } = {}) {
|
|
|
681
731
|
}
|
|
682
732
|
}
|
|
683
733
|
|
|
734
|
+
/**
|
|
735
|
+
* v4.4.11 — The mods step. By default, NEVER install or upgrade mods
|
|
736
|
+
* during `bizar install` or `bizar update`. The step just reports the
|
|
737
|
+
* current mod list so the user can see what's installed.
|
|
738
|
+
*
|
|
739
|
+
* To install a mod as part of the run, the user must opt in by:
|
|
740
|
+
* - passing `--with-mods <id1,id2>` to `bizar install` / `bizar update`
|
|
741
|
+
* - or setting the env var `BIZAR_MODS_AUTO_INSTALL=allow`
|
|
742
|
+
*
|
|
743
|
+
* When opted in, we shell to the running dashboard's `/api/mods`
|
|
744
|
+
* endpoint (which already validates the mod) — we don't duplicate the
|
|
745
|
+
* install logic here.
|
|
746
|
+
*/
|
|
747
|
+
export async function runModsStep({ mode, dryRun, force, withMods, state }) {
|
|
748
|
+
// List the current mods (from the state we already detected).
|
|
749
|
+
const installed = state?.installedMods ?? [];
|
|
750
|
+
if (installed.length === 0) {
|
|
751
|
+
console.log(chalk.dim(' Mods: 0 installed.'));
|
|
752
|
+
return { ok: true, message: 'no mods installed', touched: false };
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
const enabled = installed.filter((m) => m.enabled).length;
|
|
756
|
+
const disabled = installed.length - enabled;
|
|
757
|
+
const summary = `${installed.length} installed (${enabled} enabled${disabled ? `, ${disabled} disabled` : ''})`;
|
|
758
|
+
|
|
759
|
+
// Resolve which mods the user asked us to install. The CLI parses
|
|
760
|
+
// `--with-mods a,b,c` into a string array; the provisioner accepts
|
|
761
|
+
// the same. We also accept a single env var as a comma-separated list.
|
|
762
|
+
const envList = (process.env.BIZAR_MODS_AUTO_INSTALL || '')
|
|
763
|
+
.split(',')
|
|
764
|
+
.map((s) => s.trim())
|
|
765
|
+
.filter(Boolean);
|
|
766
|
+
const wantedMods = Array.isArray(withMods) && withMods.length > 0
|
|
767
|
+
? withMods
|
|
768
|
+
: (process.env.BIZAR_MODS_AUTO_INSTALL === 'allow' ? [] : envList);
|
|
769
|
+
|
|
770
|
+
// Default behavior: no install. Just print the list.
|
|
771
|
+
if (!wantedMods || wantedMods.length === 0) {
|
|
772
|
+
console.log(chalk.dim(` Mods: ${summary}. Not modified (use \`bizar mod install <id>\` to add one).`));
|
|
773
|
+
// Surface mods with errors so the user knows they need attention.
|
|
774
|
+
const broken = installed.filter((m) => m.error);
|
|
775
|
+
for (const m of broken) {
|
|
776
|
+
console.log(chalk.yellow(` ⚠ ${m.id}: ${m.error}`));
|
|
777
|
+
}
|
|
778
|
+
return { ok: true, message: `${summary}, not modified`, touched: false };
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// Opt-in install path. Talk to the dashboard over HTTP — the
|
|
782
|
+
// dashboard's `POST /api/mods` endpoint already does the actual
|
|
783
|
+
// install + validation. If the dashboard isn't reachable, the
|
|
784
|
+
// install fails loudly.
|
|
785
|
+
console.log(chalk.cyan(` Installing ${wantedMods.length} mod(s) via dashboard API: ${wantedMods.join(', ')}`));
|
|
786
|
+
const errors = [];
|
|
787
|
+
for (const id of wantedMods) {
|
|
788
|
+
try {
|
|
789
|
+
const result = await installModViaDashboard(id, { dryRun });
|
|
790
|
+
if (result.ok) {
|
|
791
|
+
console.log(chalk.green(` ✓ ${id}: ${result.message}`));
|
|
792
|
+
} else {
|
|
793
|
+
console.log(chalk.red(` ✗ ${id}: ${result.message}`));
|
|
794
|
+
errors.push(`${id}: ${result.message}`);
|
|
795
|
+
}
|
|
796
|
+
} catch (err) {
|
|
797
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
798
|
+
console.log(chalk.red(` ✗ ${id}: ${msg}`));
|
|
799
|
+
errors.push(`${id}: ${msg}`);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
if (errors.length > 0) {
|
|
803
|
+
return {
|
|
804
|
+
ok: false,
|
|
805
|
+
message: `mod install failed for ${errors.length} mod(s): ${errors.join('; ')}`,
|
|
806
|
+
touched: true,
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
return { ok: true, message: `${wantedMods.length} mod(s) installed`, touched: true };
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* v4.4.11 — POST to the dashboard's /api/mods endpoint to install a mod.
|
|
814
|
+
* We re-use the dashboard's own validation pipeline (mod-loader.mjs
|
|
815
|
+
* runs the same manifest + route.mjs + permissions checks) so we
|
|
816
|
+
* don't have to duplicate them here.
|
|
817
|
+
*/
|
|
818
|
+
async function installModViaDashboard(id, { dryRun }) {
|
|
819
|
+
if (dryRun) {
|
|
820
|
+
return { ok: true, message: '[dry-run] would install via dashboard' };
|
|
821
|
+
}
|
|
822
|
+
// Find the dashboard's port from BIZAR_HOME/dashboard.port.
|
|
823
|
+
const portFile = join(BIZAR_HOME, 'dashboard.port');
|
|
824
|
+
let port = 4321;
|
|
825
|
+
try {
|
|
826
|
+
if (existsSync(portFile)) {
|
|
827
|
+
const parsed = parseInt(readTextSafe(portFile, '4321').trim(), 10);
|
|
828
|
+
if (Number.isFinite(parsed) && parsed > 0) port = parsed;
|
|
829
|
+
}
|
|
830
|
+
} catch { /* ignore */ }
|
|
831
|
+
// We need an auth token. The dashboard's install endpoint is under
|
|
832
|
+
// /api/* which is auth-gated. Fetch the auth status + token via
|
|
833
|
+
// /api/auth/status (skipped from auth via the skipPaths list in
|
|
834
|
+
// server.mjs). If the dashboard has auth enabled, the user needs to
|
|
835
|
+
// supply a token via BIZAR_DASHBOARD_TOKEN.
|
|
836
|
+
const headers = { 'content-type': 'application/json' };
|
|
837
|
+
const token = process.env.BIZAR_DASHBOARD_TOKEN;
|
|
838
|
+
if (token) headers['authorization'] = `Basic ${Buffer.from(`opencode:${token}`).toString('base64')}`;
|
|
839
|
+
const url = `http://127.0.0.1:${port}/api/mods`;
|
|
840
|
+
const res = await fetch(url, {
|
|
841
|
+
method: 'POST',
|
|
842
|
+
headers,
|
|
843
|
+
body: JSON.stringify({ id }),
|
|
844
|
+
});
|
|
845
|
+
if (!res.ok) {
|
|
846
|
+
const text = await res.text().catch(() => '');
|
|
847
|
+
return { ok: false, message: `dashboard returned ${res.status}: ${text.slice(0, 200) || '(no body)'}` };
|
|
848
|
+
}
|
|
849
|
+
const data = await res.json().catch(() => ({}));
|
|
850
|
+
return { ok: true, message: data?.name ? `installed ${data.name}@${data.version}` : 'installed' };
|
|
851
|
+
}
|
|
852
|
+
|
|
684
853
|
// ─── Top-level orchestration ──────────────────────────────────────────────────
|
|
685
854
|
|
|
686
855
|
/**
|
|
@@ -785,6 +954,7 @@ export async function runProvision(opts = {}) {
|
|
|
785
954
|
skipSystemDeps = false,
|
|
786
955
|
skipHeadsUps = false,
|
|
787
956
|
yes = false,
|
|
957
|
+
withMods = null, // string[] — opt-in mod install. Default null = don't touch mods.
|
|
788
958
|
} = opts;
|
|
789
959
|
|
|
790
960
|
const banner = mode === 'update'
|
|
@@ -897,7 +1067,17 @@ export async function runProvision(opts = {}) {
|
|
|
897
1067
|
stepResults.push({ label: 'dashboard-restart', ...r });
|
|
898
1068
|
}
|
|
899
1069
|
|
|
900
|
-
// ── 11.
|
|
1070
|
+
// ── 11. Mods (opt-in only) ─────────────────────────────────────────
|
|
1071
|
+
// v4.4.11 — `bizar install` and `bizar update` never install or
|
|
1072
|
+
// upgrade mods by default. The provisioner reports the current mod
|
|
1073
|
+
// list so the user can see what's installed, then exits the mod step
|
|
1074
|
+
// without touching anything. To install a mod, pass
|
|
1075
|
+
// `--with-mods <id1,id2>` or set `BIZAR_MODS_AUTO_INSTALL=allow`.
|
|
1076
|
+
console.log('');
|
|
1077
|
+
const modsStep = await runModsStep({ mode, dryRun, force, withMods, state });
|
|
1078
|
+
stepResults.push({ label: 'mods', ...modsStep });
|
|
1079
|
+
|
|
1080
|
+
// ── 12. Doctor health check ───────────────────────────────────────
|
|
901
1081
|
console.log('');
|
|
902
1082
|
const doctor = await runDoctor({ silent: true });
|
|
903
1083
|
if (doctor.failed > 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polderlabs/bizar",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.12",
|
|
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": {
|