@polderlabs/bizar 4.5.0 → 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.
- package/bizar-dash/dist/assets/__vite-browser-external-BIHI7g3E.js +1 -0
- package/bizar-dash/dist/assets/__vite-browser-external-BIHI7g3E.js.map +1 -0
- package/bizar-dash/dist/assets/main-B4OfGAwz.js +361 -0
- package/bizar-dash/dist/assets/main-B4OfGAwz.js.map +1 -0
- package/bizar-dash/dist/assets/main-DAlLdW8I.css +1 -0
- package/bizar-dash/dist/assets/{mobile--0FBIKX3.js → mobile-BRhoDOUz.js} +1 -2
- package/bizar-dash/dist/assets/{mobile--0FBIKX3.js.map → mobile-BRhoDOUz.js.map} +1 -1
- package/bizar-dash/dist/assets/{mobile-OgRp8VIb.js → mobile-lbH6szyX.js} +2 -3
- package/bizar-dash/dist/assets/mobile-lbH6szyX.js.map +1 -0
- package/bizar-dash/dist/index.html +3 -3
- package/bizar-dash/dist/mobile.html +2 -2
- package/bizar-dash/skills/bizar/SKILL.md +20 -0
- package/bizar-dash/skills/headroom/SKILL.md +94 -0
- package/bizar-dash/skills/lightrag/SKILL.md +11 -0
- package/bizar-dash/skills/obsidian/SKILL.md +13 -0
- package/bizar-dash/src/server/api.mjs +6 -0
- package/bizar-dash/src/server/headroom.mjs +647 -0
- package/bizar-dash/src/server/memory-lightrag.mjs +281 -6
- package/bizar-dash/src/server/memory-obsidian.mjs +230 -0
- package/bizar-dash/src/server/memory-store.mjs +151 -0
- package/bizar-dash/src/server/mods-loader.mjs +13 -5
- package/bizar-dash/src/server/providers-store.mjs +73 -1
- package/bizar-dash/src/server/routes/_shared.mjs +17 -0
- package/bizar-dash/src/server/routes/chat.mjs +38 -0
- package/bizar-dash/src/server/routes/headroom.mjs +126 -0
- package/bizar-dash/src/server/routes/lightrag.mjs +6 -2
- package/bizar-dash/src/server/routes/memory.mjs +439 -4
- package/bizar-dash/src/server/schedules-runner.mjs +4 -4
- package/bizar-dash/src/server/server.mjs +55 -37
- package/bizar-dash/src/server/watcher.mjs +2 -2
- package/bizar-dash/src/web/App.tsx +42 -6
- package/bizar-dash/src/web/components/HeadroomSettings.tsx +418 -0
- package/bizar-dash/src/web/components/HeadroomStatus.tsx +158 -0
- package/bizar-dash/src/web/components/Toast.tsx +1 -1
- package/bizar-dash/src/web/components/Topbar.tsx +3 -1
- package/bizar-dash/src/web/lib/api.ts +12 -11
- package/bizar-dash/src/web/lib/types.ts +16 -0
- package/bizar-dash/src/web/main.tsx +1 -0
- package/bizar-dash/src/web/styles/chat.css +2 -0
- package/bizar-dash/src/web/styles/main.css +52 -23
- package/bizar-dash/src/web/styles/memory.css +955 -0
- package/bizar-dash/src/web/styles/tasks.css +2 -0
- package/bizar-dash/src/web/views/Memory.tsx +141 -0
- package/bizar-dash/src/web/views/MiniMaxUsage.tsx +3 -2
- package/bizar-dash/src/web/views/Overview.tsx +7 -2
- package/bizar-dash/src/web/views/Settings.tsx +32 -1
- package/bizar-dash/src/web/views/Skills.tsx +3 -2
- package/bizar-dash/src/web/views/Tasks.tsx +4 -3
- package/bizar-dash/src/web/views/memory/ConfigPanel.tsx +289 -0
- package/bizar-dash/src/web/views/memory/GitSyncPanel.tsx +220 -0
- package/bizar-dash/src/web/views/memory/LightragPanel.tsx +307 -0
- package/bizar-dash/src/web/views/memory/MemoryOverview.tsx +356 -0
- package/bizar-dash/src/web/views/memory/MemoryStatusCard.tsx +160 -0
- package/bizar-dash/src/web/views/memory/ObsidianPanel.tsx +642 -0
- package/bizar-dash/src/web/views/memory/SemanticSearchPanel.tsx +194 -0
- package/bizar-dash/tests/cli-bugfixes.test.mjs +151 -0
- package/bizar-dash/tests/frontend-bugfixes.test.mjs +151 -0
- package/bizar-dash/tests/headroom-install.test.mjs +173 -0
- package/bizar-dash/tests/headroom-settings.test.mjs +126 -0
- package/bizar-dash/tests/headroom-status.test.mjs +117 -0
- package/bizar-dash/tests/memory-lightrag-extended.test.mjs +162 -0
- package/bizar-dash/tests/memory-obsidian.test.mjs +269 -0
- package/bizar-dash/tests/memory-tab.test.mjs +322 -0
- package/bizar-dash/tests/mod-upgrade.node.test.mjs +1 -1
- package/bizar-dash/tests/server-bugfixes.test.mjs +318 -0
- package/bizar-dash/tests/submit-feedback.test.mjs +6 -6
- package/cli/artifact.mjs +11 -4
- package/cli/bin.mjs +211 -12
- package/cli/doctor.mjs +5 -3
- package/cli/memory.mjs +65 -21
- package/cli/provision.mjs +8 -2
- package/install.sh +1 -2
- package/package.json +3 -3
- package/bizar-dash/dist/assets/main-CDFKHzBg.css +0 -1
- package/bizar-dash/dist/assets/main-NYFpS2wY.js +0 -312
- package/bizar-dash/dist/assets/main-NYFpS2wY.js.map +0 -1
- package/bizar-dash/dist/assets/mobile-OgRp8VIb.js.map +0 -1
|
@@ -46,7 +46,7 @@ function makeProjectRoot() {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
function seedArtifact(projectRoot, slug, { comments = [], answers = [], status = 'draft' } = {}) {
|
|
49
|
-
const dir = join(projectRoot, 'artifacts', slug);
|
|
49
|
+
const dir = join(projectRoot, '.bizar', 'artifacts', slug);
|
|
50
50
|
mkdirSync(dir, { recursive: true });
|
|
51
51
|
const meta = {
|
|
52
52
|
slug,
|
|
@@ -85,7 +85,7 @@ test('submitFeedback creates feedback.md', () => {
|
|
|
85
85
|
const result = artifactsStore.submitFeedback(slug, { answers: [] }, root);
|
|
86
86
|
assert.equal(result.ok, true);
|
|
87
87
|
assert.equal(result.slug, slug);
|
|
88
|
-
const feedbackPath = join(root, 'artifacts', slug, 'feedback.md');
|
|
88
|
+
const feedbackPath = join(root, '.bizar', 'artifacts', slug, 'feedback.md');
|
|
89
89
|
assert.ok(existsSync(feedbackPath), 'feedback.md should be created');
|
|
90
90
|
const content = readFileSync(feedbackPath, 'utf8');
|
|
91
91
|
assert.ok(content.includes('glyph: ' + slug), 'frontmatter glyph line');
|
|
@@ -107,7 +107,7 @@ test('submitFeedback updates meta.json status to "review"', () => {
|
|
|
107
107
|
seedArtifact(root, slug, { status: 'draft' });
|
|
108
108
|
const result = artifactsStore.submitFeedback(slug, { answers: [] }, root);
|
|
109
109
|
assert.equal(result.ok, true);
|
|
110
|
-
const meta = JSON.parse(readFileSync(join(root, 'artifacts', slug, 'meta.json'), 'utf8'));
|
|
110
|
+
const meta = JSON.parse(readFileSync(join(root, '.bizar', 'artifacts', slug, 'meta.json'), 'utf8'));
|
|
111
111
|
assert.equal(meta.status, 'review', 'meta.status should be "review"');
|
|
112
112
|
} finally {
|
|
113
113
|
rmSync(root, { recursive: true, force: true });
|
|
@@ -123,7 +123,7 @@ test('submitFeedback updates meta.json lastEdited', () => {
|
|
|
123
123
|
const result = artifactsStore.submitFeedback(slug, { answers: [] }, root);
|
|
124
124
|
const after = Date.now();
|
|
125
125
|
assert.equal(result.ok, true);
|
|
126
|
-
const meta = JSON.parse(readFileSync(join(root, 'artifacts', slug, 'meta.json'), 'utf8'));
|
|
126
|
+
const meta = JSON.parse(readFileSync(join(root, '.bizar', 'artifacts', slug, 'meta.json'), 'utf8'));
|
|
127
127
|
const ts = Date.parse(meta.lastEdited);
|
|
128
128
|
assert.ok(Number.isFinite(ts), 'lastEdited should be a parseable timestamp');
|
|
129
129
|
assert.ok(ts >= before && ts <= after, `lastEdited ${meta.lastEdited} should be in [${before}, ${after}]`);
|
|
@@ -208,7 +208,7 @@ test('submitFeedback falls back to comments.json when canvas has none', () => {
|
|
|
208
208
|
const slug = 'glyph-comments-json-fallback';
|
|
209
209
|
// Seed canvas with empty comments array, comments.json with one comment.
|
|
210
210
|
seedArtifact(root, slug);
|
|
211
|
-
const dir = join(root, 'artifacts', slug);
|
|
211
|
+
const dir = join(root, '.bizar', 'artifacts', slug);
|
|
212
212
|
// Replace plan.json with empty comments, populate comments.json.
|
|
213
213
|
const canvas = JSON.parse(readFileSync(join(dir, 'plan.json'), 'utf8'));
|
|
214
214
|
canvas.comments = [];
|
|
@@ -339,7 +339,7 @@ test('POST /api/artifacts/:slug/submit persists feedback.md on disk', async () =
|
|
|
339
339
|
body: JSON.stringify({ answers: [] }),
|
|
340
340
|
});
|
|
341
341
|
assert.equal(res.status, 200);
|
|
342
|
-
const feedbackPath = join(root, 'artifacts', slug, 'feedback.md');
|
|
342
|
+
const feedbackPath = join(root, '.bizar', 'artifacts', slug, 'feedback.md');
|
|
343
343
|
assert.ok(existsSync(feedbackPath), 'feedback.md should exist on disk');
|
|
344
344
|
const content = readFileSync(feedbackPath, 'utf8');
|
|
345
345
|
assert.ok(content.startsWith('---'), 'starts with YAML frontmatter');
|
package/cli/artifact.mjs
CHANGED
|
@@ -1885,13 +1885,22 @@ async function handleRequest(req, res, slug, planDir, serverPort) {
|
|
|
1885
1885
|
|
|
1886
1886
|
// ─── Browser opening ─────────────────────────────────────────────────────────
|
|
1887
1887
|
|
|
1888
|
+
function isWSL() {
|
|
1889
|
+
try {
|
|
1890
|
+
const version = readFileSync('/proc/version', 'utf8');
|
|
1891
|
+
if (version.toLowerCase().includes('microsoft')) return true;
|
|
1892
|
+
} catch { /* not WSL */ }
|
|
1893
|
+
return !!process.env.WSL_INTEROP;
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1888
1896
|
function openBrowser(url) {
|
|
1889
1897
|
const platform = process.platform;
|
|
1898
|
+
const wsl = isWSL();
|
|
1890
1899
|
let cmd, args;
|
|
1891
1900
|
if (platform === 'darwin') {
|
|
1892
1901
|
cmd = 'open';
|
|
1893
1902
|
args = [url];
|
|
1894
|
-
} else if (platform === 'win32') {
|
|
1903
|
+
} else if (platform === 'win32' || wsl) {
|
|
1895
1904
|
cmd = 'cmd';
|
|
1896
1905
|
args = ['/c', 'start', '""', url];
|
|
1897
1906
|
} else {
|
|
@@ -1900,9 +1909,7 @@ function openBrowser(url) {
|
|
|
1900
1909
|
}
|
|
1901
1910
|
|
|
1902
1911
|
// Check if the command exists
|
|
1903
|
-
const probe =
|
|
1904
|
-
? spawnSync('where', [cmd], { stdio: 'ignore' })
|
|
1905
|
-
: spawnSync('which', [cmd], { stdio: 'ignore' });
|
|
1912
|
+
const probe = spawnSync('which', [cmd], { stdio: 'ignore' });
|
|
1906
1913
|
if (probe.status !== 0) {
|
|
1907
1914
|
console.log(` ℹ Open ${url} in your browser (no ${cmd} available)`);
|
|
1908
1915
|
return false;
|
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.
|
|
@@ -91,6 +109,7 @@ function showHelp() {
|
|
|
91
109
|
service Manage the background service daemon
|
|
92
110
|
bg <subcommand> Manage background agents (list/view/kill/logs)
|
|
93
111
|
memory <subcommand> Manage project memory (Bizar Memory Service)
|
|
112
|
+
headroom <subcommand> Manage Headroom context compression
|
|
94
113
|
dash <subcommand> Manage the dashboard (start/stop/status/cleanup/tui)
|
|
95
114
|
browser-harness-up Start Chromium for browser-harness (start/stop/status/restart)
|
|
96
115
|
dev-link [src] Symlink the local plugin source into opencode's plugin dir
|
|
@@ -758,7 +777,7 @@ function showUsageHelp() {
|
|
|
758
777
|
`);
|
|
759
778
|
}
|
|
760
779
|
|
|
761
|
-
async function runUsageCommand(args) {
|
|
780
|
+
async function runUsageCommand(args, wantJson = false) {
|
|
762
781
|
const range = (args[0] && ['24h', '7d', '30d'].includes(args[0])) ? args[0] : '24h';
|
|
763
782
|
const { port, secret } = readDashboardConn();
|
|
764
783
|
const url = `http://127.0.0.1:${port}/api/usage?range=${range}`;
|
|
@@ -773,6 +792,10 @@ async function runUsageCommand(args) {
|
|
|
773
792
|
console.error(chalk.red(` ✗ Failed to load usage data: ${data?.message ?? resp.statusText}`));
|
|
774
793
|
process.exit(1);
|
|
775
794
|
}
|
|
795
|
+
if (wantJson) {
|
|
796
|
+
process.stdout.write(JSON.stringify(data) + '\n');
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
776
799
|
const t = data.totals;
|
|
777
800
|
console.log('');
|
|
778
801
|
console.log(chalk.bold(` Usage summary — ${range} (from JSONL store)`));
|
|
@@ -809,6 +832,168 @@ async function runUsageCommand(args) {
|
|
|
809
832
|
}
|
|
810
833
|
}
|
|
811
834
|
|
|
835
|
+
function showHeadroomHelp() {
|
|
836
|
+
console.log(`
|
|
837
|
+
bizar headroom — Manage Headroom context compression
|
|
838
|
+
|
|
839
|
+
Usage:
|
|
840
|
+
bizar headroom status Show live status (installed, proxy, wrapped)
|
|
841
|
+
bizar headroom stats Show compression stats for the last 24h
|
|
842
|
+
bizar headroom install Install headroom via pip or npm
|
|
843
|
+
bizar headroom wrap Wrap opencode to route through the proxy
|
|
844
|
+
bizar headroom unwrap Unwrap opencode
|
|
845
|
+
bizar headroom start Start the proxy server
|
|
846
|
+
bizar headroom stop Stop the proxy server
|
|
847
|
+
bizar headroom doctor Run headroom doctor health check
|
|
848
|
+
|
|
849
|
+
Examples:
|
|
850
|
+
bizar headroom status
|
|
851
|
+
bizar headroom stats
|
|
852
|
+
bizar headroom install
|
|
853
|
+
bizar headroom wrap
|
|
854
|
+
`);
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
async function runHeadroomCommand(headroomArgs) {
|
|
858
|
+
const sub = headroomArgs[0];
|
|
859
|
+
const flags = headroomArgs.slice(1).filter((a) => a.startsWith('-'));
|
|
860
|
+
const positional = headroomArgs.slice(1).filter((a) => !a.startsWith('-'));
|
|
861
|
+
|
|
862
|
+
if (!sub || sub === '--help' || sub === '-h' || flags.includes('--help') || flags.includes('-h')) {
|
|
863
|
+
showHeadroomHelp();
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// Delegate to dashboard API
|
|
868
|
+
const { port, secret } = readDashboardConn();
|
|
869
|
+
const baseUrl = `http://127.0.0.1:${port}`;
|
|
870
|
+
|
|
871
|
+
async function apiGet(path) {
|
|
872
|
+
const url = `${baseUrl}${path}`;
|
|
873
|
+
const headers = { accept: 'application/json' };
|
|
874
|
+
if (secret) headers.authorization = `Basic ${Buffer.from(`opencode:${secret}`).toString('base64')}`;
|
|
875
|
+
const res = await fetch(url, { method: 'GET', headers });
|
|
876
|
+
const text = await res.text();
|
|
877
|
+
let data = null;
|
|
878
|
+
try { data = text ? JSON.parse(text) : null; } catch { /* ignore */ }
|
|
879
|
+
if (!res.ok) throw new Error(`${path}: ${data?.message || data?.error || res.statusText}`);
|
|
880
|
+
return data;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
async function apiPost(path, body = {}) {
|
|
884
|
+
const url = `${baseUrl}${path}`;
|
|
885
|
+
const headers = { 'content-type': 'application/json', accept: 'application/json' };
|
|
886
|
+
if (secret) headers.authorization = `Basic ${Buffer.from(`opencode:${secret}`).toString('base64')}`;
|
|
887
|
+
const res = await fetch(url, { method: 'POST', headers, body: JSON.stringify(body) });
|
|
888
|
+
const text = await res.text();
|
|
889
|
+
let data = null;
|
|
890
|
+
try { data = text ? JSON.parse(text) : null; } catch { /* ignore */ }
|
|
891
|
+
if (!res.ok) throw new Error(`${path}: ${data?.message || data?.error || res.statusText}`);
|
|
892
|
+
return data;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
if (sub === 'status') {
|
|
896
|
+
const s = await apiGet('/api/headroom/status');
|
|
897
|
+
console.log('');
|
|
898
|
+
console.log(chalk.bold(' Headroom status'));
|
|
899
|
+
console.log('');
|
|
900
|
+
console.log(` ${chalk.dim('installed:')} ${s.installed ? chalk.green('yes') : chalk.red('no')} ${s.version || ''}`);
|
|
901
|
+
console.log(` ${chalk.dim('proxy:')} ${s.proxyRunning ? chalk.green('running') : chalk.yellow('stopped')} ${s.proxyPort ? `@ ${s.proxyPort}` : ''} ${s.proxyPid ? `(PID ${s.proxyPid})` : ''}`);
|
|
902
|
+
console.log(` ${chalk.dim('wrapped:')} ${s.wrapped ? chalk.green('yes') : chalk.yellow('no')}`);
|
|
903
|
+
console.log(` ${chalk.dim('healthy:')} ${s.healthy === 'ok' ? chalk.green('ok') : s.healthy === 'warn' ? chalk.yellow('warn') : chalk.red('fail')}`);
|
|
904
|
+
if (s.messages && s.messages.length > 0) {
|
|
905
|
+
console.log('');
|
|
906
|
+
for (const m of s.messages) {
|
|
907
|
+
console.log(` ${m}`);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
console.log('');
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
if (sub === 'stats') {
|
|
915
|
+
const hours = parseInt(positional[0], 10) || 24;
|
|
916
|
+
const st = await apiGet(`/api/headroom/stats?hours=${hours}`);
|
|
917
|
+
console.log('');
|
|
918
|
+
console.log(chalk.bold(` Headroom stats (${hours}h)`));
|
|
919
|
+
console.log('');
|
|
920
|
+
if (st.error) {
|
|
921
|
+
console.log(chalk.yellow(` ${st.error}`));
|
|
922
|
+
} else {
|
|
923
|
+
console.log(` ${chalk.dim('tokens saved:')} ${(st.tokensSaved || 0).toLocaleString()}`);
|
|
924
|
+
console.log(` ${chalk.dim('compression:')} ${st.compressionRatio ? `${Math.round(st.compressionRatio * 100)}%` : '—'}`);
|
|
925
|
+
console.log(` ${chalk.dim('cache hits:')} ${st.cacheHits ?? '—'}`);
|
|
926
|
+
console.log(` ${chalk.dim('transforms:')} ${st.transforms ?? '—'}`);
|
|
927
|
+
}
|
|
928
|
+
console.log('');
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
if (sub === 'install') {
|
|
933
|
+
const r = await apiPost('/api/headroom/install', { force: true });
|
|
934
|
+
if (r.installed) {
|
|
935
|
+
console.log(chalk.green(` ✓ Headroom installed via ${r.method}${r.version ? ` (${r.version})` : ''}`));
|
|
936
|
+
} else {
|
|
937
|
+
console.log(chalk.red(' ✗ Install failed. Try: pip install "headroom-ai[all]"'));
|
|
938
|
+
}
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
if (sub === 'wrap') {
|
|
943
|
+
const port = parseInt(positional[0], 10) || 8787;
|
|
944
|
+
const r = await apiPost('/api/headroom/wrap', { port });
|
|
945
|
+
if (r.ok) {
|
|
946
|
+
console.log(chalk.green(` ✓ opencode wrapped with Headroom on port ${port}`));
|
|
947
|
+
} else {
|
|
948
|
+
console.log(chalk.red(` ✗ Wrap failed: ${r.log || 'unknown error'}`));
|
|
949
|
+
}
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
if (sub === 'unwrap') {
|
|
954
|
+
const r = await apiPost('/api/headroom/unwrap');
|
|
955
|
+
if (r.ok) {
|
|
956
|
+
console.log(chalk.green(' ✓ opencode unwrapped from Headroom'));
|
|
957
|
+
} else {
|
|
958
|
+
console.log(chalk.red(' ✗ Unwrap failed'));
|
|
959
|
+
}
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
if (sub === 'start') {
|
|
964
|
+
const port = parseInt(positional[0], 10) || 8787;
|
|
965
|
+
const r = await apiPost('/api/headroom/proxy/start', { port, host: '127.0.0.1' });
|
|
966
|
+
if (r.ok) {
|
|
967
|
+
console.log(chalk.green(` ✓ Proxy started on 127.0.0.1:${port} (PID ${r.pid})`));
|
|
968
|
+
} else {
|
|
969
|
+
console.log(chalk.red(' ✗ Proxy start failed'));
|
|
970
|
+
}
|
|
971
|
+
return;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
if (sub === 'stop') {
|
|
975
|
+
const r = await apiPost('/api/headroom/proxy/stop');
|
|
976
|
+
if (r.ok) {
|
|
977
|
+
console.log(chalk.green(' ✓ Proxy stopped'));
|
|
978
|
+
} else {
|
|
979
|
+
console.log(chalk.red(' ✗ Proxy stop failed'));
|
|
980
|
+
}
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
if (sub === 'doctor') {
|
|
985
|
+
// Run `headroom doctor` locally
|
|
986
|
+
const { spawn } = await import('node:child_process');
|
|
987
|
+
const child = spawn('headroom', ['doctor'], { stdio: 'inherit' });
|
|
988
|
+
await new Promise((resolve) => child.on('close', resolve));
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
console.error(chalk.red(` ✗ Unknown headroom subcommand: ${sub}`));
|
|
993
|
+
showHeadroomHelp();
|
|
994
|
+
process.exit(1);
|
|
995
|
+
}
|
|
996
|
+
|
|
812
997
|
function showDashHelp() {
|
|
813
998
|
console.log(`
|
|
814
999
|
bizar dash — Manage the Bizar dashboard
|
|
@@ -920,11 +1105,15 @@ function parseFlag(name) {
|
|
|
920
1105
|
* Returns `null` if the flag isn't present (the provisioner's
|
|
921
1106
|
* "don't touch mods" default), or a string[] of mod ids if it is.
|
|
922
1107
|
*/
|
|
923
|
-
function parseWithModsFlag(subargs) {
|
|
1108
|
+
export function parseWithModsFlag(subargs) {
|
|
924
1109
|
const idx = subargs.indexOf('--with-mods');
|
|
925
1110
|
if (idx === -1) return null;
|
|
926
1111
|
const raw = subargs[idx + 1];
|
|
927
|
-
if (!raw || raw.startsWith('--'))
|
|
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
|
+
}
|
|
928
1117
|
return raw
|
|
929
1118
|
.split(',')
|
|
930
1119
|
.map((s) => s.trim())
|
|
@@ -1018,8 +1207,10 @@ async function main() {
|
|
|
1018
1207
|
if (isHelpRequest && !args[1]) showMemoryHelp();
|
|
1019
1208
|
else {
|
|
1020
1209
|
const { runMemory } = await import('./memory.mjs');
|
|
1021
|
-
await runMemory(args[1], args.slice(2));
|
|
1210
|
+
await runMemory(args[1], args.slice(2), { wantJson });
|
|
1022
1211
|
}
|
|
1212
|
+
} else if (args[0] === 'headroom') {
|
|
1213
|
+
await runHeadroomCommand(args.slice(1));
|
|
1023
1214
|
} else if (args[0] === 'export') {
|
|
1024
1215
|
if (isHelpRequest) showExportHelp();
|
|
1025
1216
|
else await runExport(parseFlag('--target'));
|
|
@@ -1064,8 +1255,11 @@ async function main() {
|
|
|
1064
1255
|
if (isHelpRequest) showDoctorHelp();
|
|
1065
1256
|
else {
|
|
1066
1257
|
const { runDoctor } = await import('./doctor.mjs');
|
|
1067
|
-
const result = await runDoctor();
|
|
1068
|
-
if (
|
|
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);
|
|
1069
1263
|
}
|
|
1070
1264
|
} else if (args[0] === 'repair') {
|
|
1071
1265
|
// v4.4.3 — One-shot repair for stale `bizar` bin symlinks.
|
|
@@ -1163,11 +1357,11 @@ async function main() {
|
|
|
1163
1357
|
await runMinimaxCommand(args.slice(1));
|
|
1164
1358
|
} else if (args[0] === 'usage') {
|
|
1165
1359
|
// v4.6.0 — Compact usage analytics summary from the JSONL store.
|
|
1166
|
-
await runUsageCommand(args.slice(1));
|
|
1360
|
+
await runUsageCommand(args.slice(1), wantJson);
|
|
1167
1361
|
} else if (args[0] === 'dash' || args[0] === 'dashboard') {
|
|
1168
1362
|
// `bizar dashboard` is a deprecated alias for `bizar dash`
|
|
1169
1363
|
if (args[0] === 'dashboard') {
|
|
1170
|
-
|
|
1364
|
+
process.stdout.write(chalk.yellow(' ⚠ `bizar dashboard` is deprecated, use `bizar dash` instead.\n'));
|
|
1171
1365
|
}
|
|
1172
1366
|
const dashArgs = args.slice(1); // everything after 'dash' or 'dashboard'
|
|
1173
1367
|
if (dashArgs.length === 0 || isHelpRequest) {
|
|
@@ -1293,7 +1487,12 @@ async function runDash(dashArgs) {
|
|
|
1293
1487
|
|
|
1294
1488
|
// ── Main ──────────────────────────────────────────────────────────────────────
|
|
1295
1489
|
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
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
|
-
*
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
776
|
+
out.vaultExists = false;
|
|
781
777
|
} else {
|
|
778
|
+
out.vaultExists = true;
|
|
782
779
|
const notes = listNotes(projectRoot);
|
|
783
|
-
|
|
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
|
-
|
|
792
|
-
if (gs.ahead > 0)
|
|
793
|
-
if (gs.behind > 0)
|
|
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
|
-
|
|
792
|
+
out.git = { error: 'not a git repo' };
|
|
796
793
|
}
|
|
797
794
|
} else {
|
|
798
|
-
|
|
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
|
-
|
|
804
|
+
out.lightrag = { enabled: false };
|
|
808
805
|
} else if (!(await isLightRAGInstalled())) {
|
|
809
|
-
|
|
806
|
+
out.lightrag = { enabled: true, installed: false };
|
|
810
807
|
} else {
|
|
811
808
|
const running = await isLightRAGRunning(cfg);
|
|
812
|
-
|
|
809
|
+
out.lightrag = { enabled: true, installed: true, running, host: cfg.host, port: cfg.port };
|
|
813
810
|
}
|
|
814
811
|
} catch (err) {
|
|
815
|
-
|
|
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
|
-
|
|
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.
|
|
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": "^
|
|
88
|
+
"vitest": "^4.1.9"
|
|
89
89
|
},
|
|
90
90
|
"allowScripts": {
|
|
91
91
|
"better-sqlite3@12.11.1": true
|