@polderlabs/bizar 5.6.0-beta.12 → 5.6.0-beta.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/provision.mjs +98 -8
- package/package.json +1 -1
- package/packages/sdk/package.json +1 -1
- package/plugins/bizar/package.json +25 -0
package/cli/provision.mjs
CHANGED
|
@@ -259,11 +259,40 @@ export function writeInstallMarker({ version, repoPath, serviceUnit }) {
|
|
|
259
259
|
*/
|
|
260
260
|
export function detectState({ cwd = process.cwd() } = {}) {
|
|
261
261
|
// ── npm-global package location ─────────────────────────────────────
|
|
262
|
+
// Try multiple strategies because `npm root -g` doesn't always
|
|
263
|
+
// respect NPM_CONFIG_PREFIX (notably when npm is installed by the
|
|
264
|
+
// system package manager on Debian/Ubuntu).
|
|
262
265
|
let globalRoot = null;
|
|
266
|
+
const npmRootCandidates = [];
|
|
267
|
+
|
|
268
|
+
// 1. Honour the user's explicit env override first.
|
|
269
|
+
if (process.env.NPM_CONFIG_PREFIX) {
|
|
270
|
+
npmRootCandidates.push(join(process.env.NPM_CONFIG_PREFIX, 'lib', 'node_modules'));
|
|
271
|
+
}
|
|
272
|
+
// 2. Honour NPM_CONFIG_GLOBAL_PREFIX (set by `npm -g`).
|
|
273
|
+
if (process.env.NPM_CONFIG_GLOBAL_PREFIX) {
|
|
274
|
+
npmRootCandidates.push(join(process.env.NPM_CONFIG_GLOBAL_PREFIX, 'lib', 'node_modules'));
|
|
275
|
+
}
|
|
276
|
+
// 3. The classic `npm root -g` query (works on most distros).
|
|
263
277
|
try {
|
|
264
|
-
|
|
278
|
+
const r = execSync('npm root -g', { stdio: ['ignore', 'pipe', 'ignore'] })
|
|
265
279
|
.toString().trim();
|
|
280
|
+
if (r) npmRootCandidates.push(r);
|
|
266
281
|
} catch { /* ignore */ }
|
|
282
|
+
// 4. Common distro defaults.
|
|
283
|
+
npmRootCandidates.push('/usr/local/lib/node_modules');
|
|
284
|
+
npmRootCandidates.push('/usr/lib/node_modules');
|
|
285
|
+
|
|
286
|
+
// Pick the first candidate that actually has @polderlabs/bizar.
|
|
287
|
+
for (const candidate of npmRootCandidates) {
|
|
288
|
+
if (existsSync(join(candidate, '@polderlabs', 'bizar'))) {
|
|
289
|
+
globalRoot = candidate;
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// Fall back to the first candidate (even if it doesn't have the
|
|
294
|
+
// package) so downstream code can produce a clean error message.
|
|
295
|
+
if (!globalRoot) globalRoot = npmRootCandidates[0] ?? null;
|
|
267
296
|
|
|
268
297
|
const pkgRoot = globalRoot ? join(globalRoot, '@polderlabs', 'bizar') : null;
|
|
269
298
|
const pkgVersion = globalRoot ? currentVersion(PKG_MAIN) : null;
|
|
@@ -515,7 +544,11 @@ export async function ensureNpmPackage(pkg, { mode, dryRun, force }) {
|
|
|
515
544
|
// processes are reading files inside the npm-global install dir. We
|
|
516
545
|
// can't replace those files atomically while they're open. The caller
|
|
517
546
|
// is expected to have already killed them via ensureInstancesKilled().
|
|
518
|
-
const
|
|
547
|
+
const npmArgs = ['install', '-g', `${pkg}@latest`];
|
|
548
|
+
if (process.env.NPM_CONFIG_PREFIX) {
|
|
549
|
+
npmArgs.push('--prefix', process.env.NPM_CONFIG_PREFIX);
|
|
550
|
+
}
|
|
551
|
+
const r = spawnSync('npm', npmArgs, { stdio: 'inherit', timeout: 600000 });
|
|
519
552
|
if (r.status === null && r.error?.code === 'ETIMEDOUT') {
|
|
520
553
|
return { ok: false, message: `${pkg} install timed out after 10 minutes`, installed: current };
|
|
521
554
|
}
|
|
@@ -543,7 +576,11 @@ export async function updateClineCli({ dryRun, force }) {
|
|
|
543
576
|
return { ok: true, message: 'cline updated via `cline upgrade`' };
|
|
544
577
|
}
|
|
545
578
|
console.log(chalk.dim(' cline upgrade not available; falling back to npm'));
|
|
546
|
-
const
|
|
579
|
+
const npm2Args = ['install', '-g', 'cline@latest'];
|
|
580
|
+
if (process.env.NPM_CONFIG_PREFIX) {
|
|
581
|
+
npm2Args.push('--prefix', process.env.NPM_CONFIG_PREFIX);
|
|
582
|
+
}
|
|
583
|
+
const r2 = spawnSync('npm', npm2Args, { stdio: 'inherit', timeout: 600000 });
|
|
547
584
|
if (r2.status === null && r2.error?.code === 'ETIMEDOUT') {
|
|
548
585
|
return { ok: false, message: 'cline install timed out after 10 minutes' };
|
|
549
586
|
}
|
|
@@ -583,6 +620,40 @@ export async function copyPluginToCline({ dryRun, force }) {
|
|
|
583
620
|
};
|
|
584
621
|
}
|
|
585
622
|
|
|
623
|
+
// v5.6.0-beta.14: require a package.json with a `cline` field before
|
|
624
|
+
// copying. Per https://docs.cline.bot/customization/plugins — without
|
|
625
|
+
// the `cline.plugins` manifest, Cline falls back to recursive
|
|
626
|
+
// auto-discovery and tries to load every .ts file in the plugin tree
|
|
627
|
+
// (including `src/tools/*.ts`, `tests/*.test.ts`) as a plugin module,
|
|
628
|
+
// which produces ~100 `Invalid plugin module` errors at startup.
|
|
629
|
+
// Refuse to copy a plugin that isn't actually a Cline plugin.
|
|
630
|
+
const pkgJsonPath = join(src, 'package.json');
|
|
631
|
+
if (!existsSync(pkgJsonPath)) {
|
|
632
|
+
return {
|
|
633
|
+
ok: false,
|
|
634
|
+
message:
|
|
635
|
+
`plugin source missing package.json at ${pkgJsonPath} — ` +
|
|
636
|
+
`rebuild @polderlabs/bizar (the plugin must ship a cline field)`,
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
try {
|
|
640
|
+
const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf8'));
|
|
641
|
+
if (!pkg.cline?.plugins?.length) {
|
|
642
|
+
return {
|
|
643
|
+
ok: false,
|
|
644
|
+
message:
|
|
645
|
+
`plugin package.json at ${pkgJsonPath} is missing the ` +
|
|
646
|
+
'cline.plugins manifest required by Cline — see ' +
|
|
647
|
+
'https://docs.cline.bot/customization/plugins',
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
} catch (err) {
|
|
651
|
+
return {
|
|
652
|
+
ok: false,
|
|
653
|
+
message: `plugin package.json at ${pkgJsonPath} is invalid JSON: ${err.message}`,
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
|
|
586
657
|
if (state.plugin.symlink && !force) {
|
|
587
658
|
return {
|
|
588
659
|
ok: true,
|
|
@@ -626,7 +697,19 @@ export async function copyPluginToCline({ dryRun, force }) {
|
|
|
626
697
|
// Filter against RELATIVE path segments, not absolute substrings. This
|
|
627
698
|
// is the v5.6.0-beta.12 fix: the old filter excluded the src dir itself
|
|
628
699
|
// because npm-global paths contain `node_modules`.
|
|
629
|
-
|
|
700
|
+
//
|
|
701
|
+
// v5.6.0-beta.14: also skip `tests/` and `scripts/` (test fixtures &
|
|
702
|
+
// helper scripts aren't part of the runtime plugin) and `coverage/`
|
|
703
|
+
// (jest artifacts). The runtime only needs `index.ts`, `src/`,
|
|
704
|
+
// `package.json`, and the static docs.
|
|
705
|
+
const skipDirs = new Set([
|
|
706
|
+
'node_modules',
|
|
707
|
+
'dist',
|
|
708
|
+
'tests',
|
|
709
|
+
'scripts',
|
|
710
|
+
'coverage',
|
|
711
|
+
'.DS_Store',
|
|
712
|
+
]);
|
|
630
713
|
await cp(src, dest, {
|
|
631
714
|
recursive: true,
|
|
632
715
|
filter: (p) => {
|
|
@@ -683,9 +766,9 @@ function pluginContentMatches(src, dest) {
|
|
|
683
766
|
if (!sEntries) return false;
|
|
684
767
|
// src should not have files missing from dest
|
|
685
768
|
for (const e of sEntries) {
|
|
686
|
-
if (skipDirs.has(e)) continue;
|
|
687
|
-
const sFull = join(s, e);
|
|
688
|
-
const dFull = join(d, e);
|
|
769
|
+
if (skipDirs.has(e.name)) continue;
|
|
770
|
+
const sFull = join(s, e.name);
|
|
771
|
+
const dFull = join(d, e.name);
|
|
689
772
|
try {
|
|
690
773
|
const sSt = statSync(sFull);
|
|
691
774
|
if (sSt.isDirectory()) {
|
|
@@ -780,7 +863,14 @@ export async function patchClineJson({ dryRun, force }) {
|
|
|
780
863
|
}
|
|
781
864
|
|
|
782
865
|
if (!hasEntry) {
|
|
783
|
-
|
|
866
|
+
// v5.6.0-beta.14: point at the plugin DIRECTORY (not a file inside
|
|
867
|
+
// it). Cline reads `package.json#cline.plugins` from there and loads
|
|
868
|
+
// the entry point declared in the manifest. Pointing at `index.ts`
|
|
869
|
+
// directly used to work, but with the new auto-discovery rules (see
|
|
870
|
+
// https://docs.cline.bot/customization/plugins) it can cause every
|
|
871
|
+
// .ts file under the plugin tree to be loaded as a separate plugin
|
|
872
|
+
// module — producing ~100 `Invalid plugin module` errors at startup.
|
|
873
|
+
plugins.push(['./plugins/bizar', {
|
|
784
874
|
loopThresholdWarn: 5,
|
|
785
875
|
loopThresholdEscalate: 8,
|
|
786
876
|
loopThresholdBlock: 12,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polderlabs/bizar",
|
|
3
|
-
"version": "5.6.0-beta.
|
|
3
|
+
"version": "5.6.0-beta.14",
|
|
4
4
|
"description": "Norse-pantheon multi-agent system for cline — 13 agents across 4 cost tiers with cost-aware routing, plans, and a configurable agent harness. v4 ships as a single npm package bundling the dashboard server, cline plugin, and typed SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@polderlabs/bizar-plugin",
|
|
3
|
+
"version": "5.6.0-beta.14",
|
|
4
|
+
"description": "Bizar Norse-pantheon multi-agent plugin for Cline — 14 agents across 4 cost tiers with cost-aware routing and plans.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.ts",
|
|
7
|
+
"cline": {
|
|
8
|
+
"plugins": [
|
|
9
|
+
{
|
|
10
|
+
"paths": ["./index.ts"],
|
|
11
|
+
"capabilities": ["tools", "hooks"]
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"@cline/sdk": "*",
|
|
17
|
+
"@cline/core": "*",
|
|
18
|
+
"@cline/shared": "*"
|
|
19
|
+
},
|
|
20
|
+
"peerDependenciesMeta": {
|
|
21
|
+
"@cline/sdk": { "optional": true },
|
|
22
|
+
"@cline/core": { "optional": true },
|
|
23
|
+
"@cline/shared": { "optional": true }
|
|
24
|
+
}
|
|
25
|
+
}
|