create-egregore 0.19.33 → 0.20.0
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/assets/egregore-launcher.js +118 -13
- package/bin/cli.js +19 -3
- package/lib/connect-runtime.js +4 -2
- package/lib/local.js +15 -1
- package/lib/prime-runtime.js +208 -0
- package/lib/setup.js +45 -3
- package/package.json +4 -3
- package/runtime/codex/.codex/skills/ingest-notion/SKILL.md +29 -0
- package/runtime/codex/.codex/skills/notion-connect/SKILL.md +29 -0
- package/runtime/codex/.codex/skills/teams-connect/SKILL.md +29 -0
- package/runtime/codex/.codex/spec-manifest.json +3 -3
- package/runtime/codex/AGENTS.md +11 -4
- package/runtime/codex/bin/activity-data.sh +4 -8
- package/runtime/codex/bin/attendant.sh +13 -0
- package/runtime/codex/bin/autosave.sh +27 -1
- package/runtime/codex/bin/codex-render-spec.mjs +6 -0
- package/runtime/codex/bin/codex-session-start.sh +3 -1
- package/runtime/codex/bin/graph-batch.sh +25 -6
- package/runtime/codex/bin/graph-op.sh +5 -4
- package/runtime/codex/bin/graph.sh +31 -5
- package/runtime/codex/bin/ingest.py +81 -5
- package/runtime/codex/bin/lib/context.sh +26 -1
- package/runtime/codex/bin/lib/greeting.sh +4 -1
- package/runtime/codex/bin/lib/worktree-links.sh +25 -0
- package/runtime/codex/manifest.json +7 -1
- package/runtime/pi/.codex/skills/ingest-notion/SKILL.md +29 -0
- package/runtime/pi/.codex/skills/notion-connect/SKILL.md +29 -0
- package/runtime/pi/.codex/skills/teams-connect/SKILL.md +29 -0
- package/runtime/pi/.codex/spec-manifest.json +3 -3
- package/runtime/pi/.pi/APPEND_SYSTEM.md +3 -2
- package/runtime/pi/.pi/extensions/egregore.ts +17 -6
- package/runtime/pi/.pi/spec-manifest.json +2 -2
- package/runtime/pi/AGENTS.md +11 -4
- package/runtime/pi/bin/activity-data.sh +4 -8
- package/runtime/pi/bin/attendant.sh +13 -0
- package/runtime/pi/bin/autosave.sh +27 -1
- package/runtime/pi/bin/codex-render-spec.mjs +6 -0
- package/runtime/pi/bin/codex-session-start.sh +3 -1
- package/runtime/pi/bin/graph-batch.sh +25 -6
- package/runtime/pi/bin/graph-op.sh +5 -4
- package/runtime/pi/bin/graph.sh +31 -5
- package/runtime/pi/bin/ingest.py +81 -5
- package/runtime/pi/bin/lib/context.sh +26 -1
- package/runtime/pi/bin/lib/greeting.sh +4 -1
- package/runtime/pi/bin/lib/worktree-links.sh +25 -0
- package/runtime/pi/bin/pi-branch-policy.mjs +138 -1
- package/runtime/pi/bin/pi-product-workflows.mjs +35 -7
- package/runtime/pi/manifest.json +7 -1
- package/runtime/prime/.claude/context/notification-consent.md +66 -0
- package/runtime/prime/.codex/config.toml +17 -0
- package/runtime/prime/.codex/hooks/branch-guard.js +461 -0
- package/runtime/prime/.codex/hooks/search-hint.js +67 -0
- package/runtime/prime/.codex/hooks.json +30 -0
- package/runtime/prime/.codex/skills/activity/SKILL.md +82 -0
- package/runtime/prime/.codex/skills/announce/SKILL.md +67 -0
- package/runtime/prime/.codex/skills/archive/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/branch/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/checkup/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/commit/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/contribute/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/create-skill/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/dark-mode/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/dashboard/SKILL.md +59 -0
- package/runtime/prime/.codex/skills/deep-reflect/SKILL.md +109 -0
- package/runtime/prime/.codex/skills/delete-user/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/emissary/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/handoff/SKILL.md +166 -0
- package/runtime/prime/.codex/skills/harvest/QUESTION_PALETTE.md +76 -0
- package/runtime/prime/.codex/skills/harvest/SKILL.md +131 -0
- package/runtime/prime/.codex/skills/ingest/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/ingest-notion/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/ingest-user-interview/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/invite/SKILL.md +44 -0
- package/runtime/prime/.codex/skills/issue/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/me/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/meeting/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/note/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/notion-connect/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/onboarding/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/pr/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/pull/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/push/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/quest/SKILL.md +80 -0
- package/runtime/prime/.codex/skills/reflect/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/review-pr/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/save/SKILL.md +125 -0
- package/runtime/prime/.codex/skills/slack-connect/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/summon/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/sync-repos/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/teams-connect/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/telegram-connect/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/telemetry/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/test/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/the-spiral/SKILL.md +84 -0
- package/runtime/prime/.codex/skills/tui-design/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/tutorial/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/update/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/view/SKILL.md +156 -0
- package/runtime/prime/.codex/skills/view/agents/openai.yaml +4 -0
- package/runtime/prime/.codex/skills/view/assets/compose-scaffold.html +221 -0
- package/runtime/prime/.codex/skills/visual-explain/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/wrap/SKILL.md +58 -0
- package/runtime/prime/.codex/spec-manifest.json +132 -0
- package/runtime/prime/.prime/agent/APPEND_SYSTEM.md +393 -0
- package/runtime/prime/.prime/agent/extensions/egregore.ts +460 -0
- package/runtime/prime/.prime/agent/settings.json +4 -0
- package/runtime/prime/.prime/agent/skills/egregore/SKILL.md +34 -0
- package/runtime/prime/.prime/agent/skills/egregore/pyproject.toml +13 -0
- package/runtime/prime/.prime/agent/skills/egregore/src/egregore/__init__.py +156 -0
- package/runtime/prime/.prime/agent/spec-manifest.json +12 -0
- package/runtime/prime/AGENTS.md +489 -0
- package/runtime/prime/bin/activity-data.sh +238 -0
- package/runtime/prime/bin/agent.sh +775 -0
- package/runtime/prime/bin/attendant.sh +707 -0
- package/runtime/prime/bin/autosave.sh +112 -0
- package/runtime/prime/bin/capture-reconcile.sh +69 -0
- package/runtime/prime/bin/capture-run.sh +341 -0
- package/runtime/prime/bin/codex-install-skills.sh +78 -0
- package/runtime/prime/bin/codex-render-spec.mjs +440 -0
- package/runtime/prime/bin/codex-session-start.sh +265 -0
- package/runtime/prime/bin/codex-skill-render.mjs +347 -0
- package/runtime/prime/bin/codex-sync-skills.sh +232 -0
- package/runtime/prime/bin/connect-refresh.sh +33 -0
- package/runtime/prime/bin/dashboard-data.sh +178 -0
- package/runtime/prime/bin/graph-batch.sh +79 -0
- package/runtime/prime/bin/graph-op.sh +1102 -0
- package/runtime/prime/bin/graph-wal.sh +229 -0
- package/runtime/prime/bin/graph.sh +223 -0
- package/runtime/prime/bin/handoff-pr-backfill.sh +86 -0
- package/runtime/prime/bin/handoff-run.sh +671 -0
- package/runtime/prime/bin/handoff-save-egregore.sh +212 -0
- package/runtime/prime/bin/index-handoff.sh +322 -0
- package/runtime/prime/bin/ingest-graph.sh +80 -0
- package/runtime/prime/bin/ingest-surface.html +495 -0
- package/runtime/prime/bin/ingest.py +756 -0
- package/runtime/prime/bin/ingest.sh +279 -0
- package/runtime/prime/bin/ingest_graph.py +856 -0
- package/runtime/prime/bin/ingest_surface.py +544 -0
- package/runtime/prime/bin/lib/artifact-id.sh +46 -0
- package/runtime/prime/bin/lib/config.sh +116 -0
- package/runtime/prime/bin/lib/context.sh +621 -0
- package/runtime/prime/bin/lib/dashboard-artifact.sh +242 -0
- package/runtime/prime/bin/lib/ensure-develop.sh +183 -0
- package/runtime/prime/bin/lib/git-sync.sh +406 -0
- package/runtime/prime/bin/lib/greeting.sh +519 -0
- package/runtime/prime/bin/lib/hash.sh +13 -0
- package/runtime/prime/bin/lib/identity.sh +213 -0
- package/runtime/prime/bin/lib/metrics.sh +374 -0
- package/runtime/prime/bin/lib/noncode.sh +31 -0
- package/runtime/prime/bin/lib/permissions.sh +106 -0
- package/runtime/prime/bin/lib/time.sh +56 -0
- package/runtime/prime/bin/lib/worktree-links.sh +79 -0
- package/runtime/prime/bin/notify.sh +636 -0
- package/runtime/prime/bin/person.py +630 -0
- package/runtime/prime/bin/person.sh +448 -0
- package/runtime/prime/bin/pi-branch-policy.mjs +312 -0
- package/runtime/prime/bin/pi-product-workflows.mjs +394 -0
- package/runtime/prime/bin/prime-render-spec.mjs +123 -0
- package/runtime/prime/bin/prime-session-start.sh +24 -0
- package/runtime/prime/bin/publish-artifact.sh +271 -0
- package/runtime/prime/bin/publish-references.sh +144 -0
- package/runtime/prime/bin/repo-state.sh +96 -0
- package/runtime/prime/bin/search.sh +240 -0
- package/runtime/prime/bin/session-autosave.sh +209 -0
- package/runtime/prime/bin/session-log.sh +199 -0
- package/runtime/prime/bin/settings.sh +304 -0
- package/runtime/prime/bin/telemetry.sh +391 -0
- package/runtime/prime/bin/worktree-create.sh +128 -0
- package/runtime/prime/bin/worktree-remove.sh +50 -0
- package/runtime/prime/bin/worktree.sh +198 -0
- package/runtime/prime/manifest.json +178 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// egregore-launcher-version: 0.
|
|
2
|
+
// egregore-launcher-version: 0.20.0
|
|
3
3
|
//
|
|
4
4
|
// egregore — launch and browse Egregore instances from your terminal.
|
|
5
5
|
// Installed by create-egregore. Reads ~/.egregore/instances.json.
|
|
@@ -33,7 +33,7 @@ const crypto = require("node:crypto");
|
|
|
33
33
|
const { spawnSync, spawn } = require("node:child_process");
|
|
34
34
|
const readline = require("node:readline");
|
|
35
35
|
|
|
36
|
-
const VERSION = "0.
|
|
36
|
+
const VERSION = "0.20.0";
|
|
37
37
|
const REGISTRY = path.join(os.homedir(), ".egregore", "instances.json");
|
|
38
38
|
const DEFAULT_FILE = path.join(os.homedir(), ".egregore", "default");
|
|
39
39
|
const UPDATE_CACHE_FILE = path.join(os.homedir(), ".egregore", "update-check.json");
|
|
@@ -368,6 +368,7 @@ function normalizeRuntime(raw) {
|
|
|
368
368
|
if (value === "claude" || value === "claude-code" || value === "claude_code") return "claude-code";
|
|
369
369
|
if (value === "codex" || value === "openai-codex" || value === "openai_codex") return "codex";
|
|
370
370
|
if (value === "pi" || value === "pi-coding-agent" || value === "pi_coding_agent") return "pi";
|
|
371
|
+
if (value === "prime" || value === "prime-agent" || value === "prime_agent") return "prime";
|
|
371
372
|
return null;
|
|
372
373
|
}
|
|
373
374
|
|
|
@@ -380,6 +381,8 @@ function parseRuntimeFlags(argv) {
|
|
|
380
381
|
runtimeOverride = "codex";
|
|
381
382
|
} else if (arg === "--pi") {
|
|
382
383
|
runtimeOverride = "pi";
|
|
384
|
+
} else if (arg === "--prime") {
|
|
385
|
+
runtimeOverride = "prime";
|
|
383
386
|
} else if (arg === "--claude" || arg === "--claude-code") {
|
|
384
387
|
runtimeOverride = "claude-code";
|
|
385
388
|
} else if (arg === "--runtime") {
|
|
@@ -393,7 +396,7 @@ function parseRuntimeFlags(argv) {
|
|
|
393
396
|
}
|
|
394
397
|
}
|
|
395
398
|
const normalized = runtimeOverride ? normalizeRuntime(runtimeOverride) : null;
|
|
396
|
-
if (runtimeOverride && !normalized) die(`unknown runtime: ${runtimeOverride}\n expected claude-code, codex, or
|
|
399
|
+
if (runtimeOverride && !normalized) die(`unknown runtime: ${runtimeOverride}\n expected claude-code, codex, pi, or prime`);
|
|
397
400
|
return { args: rest, runtimeOverride: normalized };
|
|
398
401
|
}
|
|
399
402
|
|
|
@@ -412,20 +415,23 @@ function runtimeFor(inst, runtimeOverride) {
|
|
|
412
415
|
function runtimeLabel(runtime) {
|
|
413
416
|
if (runtime === "codex") return "Codex";
|
|
414
417
|
if (runtime === "pi") return "Pi";
|
|
418
|
+
if (runtime === "prime") return "Prime Agent";
|
|
415
419
|
return "Claude Code";
|
|
416
420
|
}
|
|
417
421
|
|
|
418
422
|
function runtimeShort(runtime) {
|
|
419
|
-
return runtime === "codex" ? "codex" : runtime === "pi" ? "pi" : "claude-code";
|
|
423
|
+
return runtime === "codex" ? "codex" : runtime === "pi" ? "pi" : runtime === "prime" ? "prime" : "claude-code";
|
|
420
424
|
}
|
|
421
425
|
|
|
422
426
|
function runtimeBinary(runtime) {
|
|
423
|
-
return runtime === "codex" ? "codex" : runtime === "pi" ? "pi" : "claude";
|
|
427
|
+
return runtime === "codex" ? "codex" : runtime === "pi" ? "pi" : runtime === "prime" ? "prime-agent" : "claude";
|
|
424
428
|
}
|
|
425
429
|
|
|
426
430
|
function assistantInstallCommand(runtime) {
|
|
427
431
|
if (runtime === "codex") return "npm install -g @openai/codex";
|
|
428
432
|
if (runtime === "pi") return "npm install -g --ignore-scripts @earendil-works/pi-coding-agent";
|
|
433
|
+
// Prime Agent is not on the public npm registry — install via its own script.
|
|
434
|
+
if (runtime === "prime") return "curl -fsSL https://app.primeintellect.ai/prime-agent/install.sh | sh";
|
|
429
435
|
return "npm install -g @anthropic-ai/claude-code";
|
|
430
436
|
}
|
|
431
437
|
|
|
@@ -438,6 +444,15 @@ function piTrustArgs() {
|
|
|
438
444
|
}
|
|
439
445
|
}
|
|
440
446
|
|
|
447
|
+
function primeTrustArgs() {
|
|
448
|
+
try {
|
|
449
|
+
const help = spawnSync("prime-agent", ["--help"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
450
|
+
return `${help.stdout || ""}\n${help.stderr || ""}`.includes("--approve") ? ["--approve"] : [];
|
|
451
|
+
} catch {
|
|
452
|
+
return [];
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
441
456
|
function commandExists(bin) {
|
|
442
457
|
if (typeof bin !== "string" || bin.length === 0) return false;
|
|
443
458
|
const pathValue = process.env.PATH || process.env.Path || process.env.path || "";
|
|
@@ -477,7 +492,7 @@ function runtimeChoiceDescription(runtime, inst, stored) {
|
|
|
477
492
|
bits.push("installed");
|
|
478
493
|
if (runtime === stored) bits.push("saved default");
|
|
479
494
|
if (runtime === "codex") bits.push("portable agent protocol");
|
|
480
|
-
else if (runtime === "pi") bits.push("project-local meta-harness");
|
|
495
|
+
else if (runtime === "pi" || runtime === "prime") bits.push("project-local meta-harness");
|
|
481
496
|
else bits.push("Claude Code integration");
|
|
482
497
|
return bits.join(" · ");
|
|
483
498
|
}
|
|
@@ -590,7 +605,7 @@ function runtimeChoicesFor(inst, runtimeOverride) {
|
|
|
590
605
|
const override = normalizeRuntime(runtimeOverride);
|
|
591
606
|
if (override) return [override];
|
|
592
607
|
const stored = storedRuntimeFor(inst);
|
|
593
|
-
const choices = [stored, ...["claude-code", "codex", "pi"].filter((runtime) => runtime !== stored)];
|
|
608
|
+
const choices = [stored, ...["claude-code", "codex", "pi", "prime"].filter((runtime) => runtime !== stored)];
|
|
594
609
|
return choices.sort((a, b) => Number(commandExists(runtimeBinary(b))) - Number(commandExists(runtimeBinary(a))));
|
|
595
610
|
}
|
|
596
611
|
|
|
@@ -722,6 +737,75 @@ function piSupportMessage(egregoreDir) {
|
|
|
722
737
|
].join("\n");
|
|
723
738
|
}
|
|
724
739
|
|
|
740
|
+
function hasPrimeCoreSupport(egregoreDir) {
|
|
741
|
+
return (
|
|
742
|
+
fs.existsSync(path.join(egregoreDir, "bin", "prime-session-start.sh")) &&
|
|
743
|
+
fs.existsSync(path.join(egregoreDir, ".prime", "agent", "APPEND_SYSTEM.md")) &&
|
|
744
|
+
fs.existsSync(path.join(egregoreDir, ".prime", "agent", "settings.json")) &&
|
|
745
|
+
fs.existsSync(path.join(egregoreDir, ".prime", "agent", "extensions", "egregore.ts")) &&
|
|
746
|
+
fs.existsSync(path.join(egregoreDir, ".codex", "skills"))
|
|
747
|
+
);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
function primeSupportMessage(egregoreDir) {
|
|
751
|
+
return [
|
|
752
|
+
"Prime Agent runtime support is missing from this Egregore checkout.",
|
|
753
|
+
` path: ${egregoreDir}`,
|
|
754
|
+
"",
|
|
755
|
+
"Run npx -y create-egregore@latest to install the packaged Prime Agent runtime, then rerun egregore.",
|
|
756
|
+
].join("\n");
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// Minimal y/N line prompt for pre-launch decisions (the TUI select machinery
|
|
760
|
+
// is torn down by the time launch() runs).
|
|
761
|
+
function confirmLine(question) {
|
|
762
|
+
return new Promise((resolve) => {
|
|
763
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
764
|
+
rl.question(` ${question} [Y/n] `, (answer) => {
|
|
765
|
+
rl.close();
|
|
766
|
+
resolve(!/^n/i.test(String(answer).trim()));
|
|
767
|
+
});
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// Guided install: never leave the user alone with a curl one-liner. Runs the
|
|
772
|
+
// official installer with full output visible, then re-checks the binary.
|
|
773
|
+
async function offerPrimeInstall() {
|
|
774
|
+
const command = assistantInstallCommand("prime");
|
|
775
|
+
process.stdout.write([
|
|
776
|
+
"",
|
|
777
|
+
` ${BOLD}Prime Agent isn't installed.${RESET}`,
|
|
778
|
+
` ${DIM}Egregore can run the official installer now:${RESET}`,
|
|
779
|
+
` ${command}`,
|
|
780
|
+
"",
|
|
781
|
+
].join("\n"));
|
|
782
|
+
const yes = await confirmLine("Install Prime Agent now?");
|
|
783
|
+
if (!yes) return false;
|
|
784
|
+
const result = spawnSync("sh", ["-c", command], { stdio: "inherit" });
|
|
785
|
+
if (result.status !== 0 || !commandExists(runtimeBinary("prime"))) {
|
|
786
|
+
process.stdout.write(`\n ${DIM}Installer did not complete — run it manually, then: egregore${RESET}\n`);
|
|
787
|
+
return false;
|
|
788
|
+
}
|
|
789
|
+
process.stdout.write(`\n ${CYAN}✓${RESET} Prime Agent installed\n`);
|
|
790
|
+
return true;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// Auth stays harness-owned; the launcher only removes the dead end of a first
|
|
794
|
+
// session with no model account connected.
|
|
795
|
+
function primeAuthHint() {
|
|
796
|
+
const agentDir = process.env.PRIME_AGENT_CODING_AGENT_DIR ||
|
|
797
|
+
path.join(os.homedir(), ".prime", "agent");
|
|
798
|
+
try {
|
|
799
|
+
const auth = JSON.parse(fs.readFileSync(path.join(agentDir, "auth.json"), "utf-8"));
|
|
800
|
+
if (auth && Object.keys(auth).length > 0) return;
|
|
801
|
+
} catch {}
|
|
802
|
+
process.stdout.write(
|
|
803
|
+
`\n ${DIM}First run: connect a model account inside Prime Agent — type ${RESET}/login${DIM}` +
|
|
804
|
+
` (Claude Pro/Max subscription or an API key). Heads-up: subscription usage in` +
|
|
805
|
+
` third-party harnesses bills per token as extra usage.${RESET}\n\n`,
|
|
806
|
+
);
|
|
807
|
+
}
|
|
808
|
+
|
|
725
809
|
function installCodexSkills(egregoreDir) {
|
|
726
810
|
const script = path.join(egregoreDir, "bin", "codex-install-skills.sh");
|
|
727
811
|
if (!fs.existsSync(script)) return false;
|
|
@@ -766,6 +850,7 @@ function runtimeLaunchArgs(runtime, egregoreDir) {
|
|
|
766
850
|
];
|
|
767
851
|
}
|
|
768
852
|
if (runtime === "pi") return piTrustArgs();
|
|
853
|
+
if (runtime === "prime") return primeTrustArgs();
|
|
769
854
|
return claudeLaunchArgs(egregoreDir);
|
|
770
855
|
}
|
|
771
856
|
|
|
@@ -792,7 +877,12 @@ async function launch(inst, runtimeOverride) {
|
|
|
792
877
|
}
|
|
793
878
|
const binary = runtimeBinary(runtime);
|
|
794
879
|
if (!commandExists(binary)) {
|
|
795
|
-
|
|
880
|
+
// Never run a curl|sh installer off non-interactive stdin: piped or
|
|
881
|
+
// closed input must fall through to the printed install command.
|
|
882
|
+
const installed = runtime === "prime" && canPrompt() && await offerPrimeInstall();
|
|
883
|
+
if (!installed) {
|
|
884
|
+
die(`${runtimeLabel(runtime)} is not installed.\n Install it with:\n ${assistantInstallCommand(runtime)}\n Then run: egregore`);
|
|
885
|
+
}
|
|
796
886
|
}
|
|
797
887
|
if (runtime === "codex") {
|
|
798
888
|
if (!hasCodexCoreSupport(inst.path)) {
|
|
@@ -806,6 +896,20 @@ async function launch(inst, runtimeOverride) {
|
|
|
806
896
|
} else if (runtime === "pi") {
|
|
807
897
|
if (!hasPiCoreSupport(inst.path)) die(piSupportMessage(inst.path));
|
|
808
898
|
}
|
|
899
|
+
let launchArgs = null;
|
|
900
|
+
if (runtime === "prime") {
|
|
901
|
+
// Cover the gap between choosing the harness and Prime's first paint:
|
|
902
|
+
// the loader runs through the launcher-side pre-flight (core-support
|
|
903
|
+
// check + the trust-flag probe, which shells out to the binary), then a
|
|
904
|
+
// single handoff line explains the remaining in-harness startup.
|
|
905
|
+
const stopLoader = startSpinner("Starting Prime Agent");
|
|
906
|
+
const coreOk = hasPrimeCoreSupport(inst.path);
|
|
907
|
+
launchArgs = coreOk ? runtimeLaunchArgs(runtime, inst.path) : null;
|
|
908
|
+
stopLoader();
|
|
909
|
+
if (!coreOk) die(primeSupportMessage(inst.path));
|
|
910
|
+
primeAuthHint();
|
|
911
|
+
process.stdout.write(` ${CYAN}◆${RESET} ${BOLD}Prime Agent starting${RESET}${DIM} — the Egregore greeting loads inside in a few seconds${RESET}\n`);
|
|
912
|
+
}
|
|
809
913
|
// Claude Code renders the greeting in-chat — no pre-launch card. Claude Code
|
|
810
914
|
// ≥2.1.89 boots into the alternate screen buffer, which hides anything
|
|
811
915
|
// printed here; the launcher-card fast path is parked in PR #1493.
|
|
@@ -816,7 +920,7 @@ async function launch(inst, runtimeOverride) {
|
|
|
816
920
|
EGREGORE_RUNTIME: runtime,
|
|
817
921
|
EGREGORE_CODEX_TRUSTED: runtime === "codex" ? "1" : process.env.EGREGORE_CODEX_TRUSTED,
|
|
818
922
|
};
|
|
819
|
-
const child = spawn(binary, runtimeLaunchArgs(runtime, inst.path), {
|
|
923
|
+
const child = spawn(binary, launchArgs || runtimeLaunchArgs(runtime, inst.path), {
|
|
820
924
|
cwd: inst.path,
|
|
821
925
|
stdio: "inherit",
|
|
822
926
|
env: launchEnv,
|
|
@@ -940,7 +1044,7 @@ function cmdHelp() {
|
|
|
940
1044
|
` ${CYAN}egregore${RESET} pick an instance, then pick a harness`,
|
|
941
1045
|
` ${CYAN}egregore${RESET} ${DIM}<slug|name>${RESET} pick a harness for the matching instance`,
|
|
942
1046
|
` ${CYAN}egregore --runtime${RESET} ${DIM}<name> <slug>${RESET} advanced harness override`,
|
|
943
|
-
` ${DIM}names: claude-code · codex · pi${RESET}`,
|
|
1047
|
+
` ${DIM}names: claude-code · codex · pi · prime${RESET}`,
|
|
944
1048
|
` ${CYAN}egregore browse${RESET} force the full-screen browser`,
|
|
945
1049
|
` ${CYAN}egregore ls${RESET} ${DIM}| list${RESET} list installed instances`,
|
|
946
1050
|
` ${CYAN}egregore use${RESET} ${DIM}<slug>${RESET} set the default for bare ${BOLD}egregore${RESET}`,
|
|
@@ -2176,6 +2280,7 @@ function renderHeroPanel({ selected, pv, width, height, countSuffix, filter, fil
|
|
|
2176
2280
|
`${DIM}claude-code${RESET}: ${commandExists("claude") ? "installed" : "not installed"}`,
|
|
2177
2281
|
`${DIM}codex${RESET}: ${commandExists("codex") ? "installed" : "not installed"}`,
|
|
2178
2282
|
`${DIM}pi${RESET}: ${commandExists("pi") ? "installed" : "not installed"}`,
|
|
2283
|
+
`${DIM}prime${RESET}: ${commandExists("prime-agent") ? "installed" : "not installed"}`,
|
|
2179
2284
|
`${DIM}Hermes — Coming Soon${RESET}`,
|
|
2180
2285
|
];
|
|
2181
2286
|
const rows = Math.max(EGREGORE_SIGIL.length + 2, right.length);
|
|
@@ -2188,11 +2293,11 @@ function renderHeroPanel({ selected, pv, width, height, countSuffix, filter, fil
|
|
|
2188
2293
|
lines.push(boxLine(`${BOLD}Available Skills${RESET}`, innerWidth, margin));
|
|
2189
2294
|
for (const group of skillGroups) lines.push(boxLine(group, innerWidth, margin));
|
|
2190
2295
|
lines.push(emptyBoxLine(innerWidth, margin));
|
|
2191
|
-
lines.push(boxLine(`${BOLD}Harnesses${RESET} ${DIM}claude-code${RESET} ${commandExists("claude") ? "installed" : "missing"} · ${DIM}codex${RESET} ${commandExists("codex") ? "installed" : "missing"} · ${DIM}pi${RESET} ${commandExists("pi") ? "installed" : "missing"} · ${DIM}Hermes — Coming Soon${RESET}`, innerWidth, margin));
|
|
2296
|
+
lines.push(boxLine(`${BOLD}Harnesses${RESET} ${DIM}claude-code${RESET} ${commandExists("claude") ? "installed" : "missing"} · ${DIM}codex${RESET} ${commandExists("codex") ? "installed" : "missing"} · ${DIM}pi${RESET} ${commandExists("pi") ? "installed" : "missing"} · ${DIM}prime${RESET} ${commandExists("prime-agent") ? "installed" : "missing"} · ${DIM}Hermes — Coming Soon${RESET}`, innerWidth, margin));
|
|
2192
2297
|
}
|
|
2193
2298
|
|
|
2194
2299
|
lines.push(emptyBoxLine(innerWidth, margin));
|
|
2195
|
-
lines.push(boxLine(`${DIM}enter selects an instance, then choose Claude Code, Codex, or
|
|
2300
|
+
lines.push(boxLine(`${DIM}enter selects an instance, then choose Claude Code, Codex, Pi, or Prime Agent without leaving this screen${RESET}`, innerWidth, margin));
|
|
2196
2301
|
lines.push(bottom);
|
|
2197
2302
|
return lines;
|
|
2198
2303
|
}
|
|
@@ -2555,7 +2660,7 @@ async function browser(args = {}) {
|
|
|
2555
2660
|
const label = (k) => `${DIM}${pad(k, 10)}${RESET}`;
|
|
2556
2661
|
previewLines.push(` ${label("action")} ${BOLD}Set up a new Egregore${RESET}`);
|
|
2557
2662
|
previewLines.push(` ${label("flow")} guided install, Telegram, invite, ready/start`);
|
|
2558
|
-
previewLines.push(` ${label("harness")} choose Claude Code, Codex, or
|
|
2663
|
+
previewLines.push(` ${label("harness")} choose Claude Code, Codex, Pi, or Prime Agent during setup`);
|
|
2559
2664
|
previewLines.push(` ${label("start")} press enter to begin`);
|
|
2560
2665
|
} else if (!selected) {
|
|
2561
2666
|
previewLines.push(`${DIM} (no selection)${RESET}`);
|
package/bin/cli.js
CHANGED
|
@@ -35,6 +35,11 @@ const {
|
|
|
35
35
|
installPiRuntime,
|
|
36
36
|
reportPiRuntimeSummary,
|
|
37
37
|
} = require("../lib/pi-runtime");
|
|
38
|
+
const {
|
|
39
|
+
hasPrimeRuntimeSupport,
|
|
40
|
+
installPrimeRuntime,
|
|
41
|
+
reportPrimeRuntimeSummary,
|
|
42
|
+
} = require("../lib/prime-runtime");
|
|
38
43
|
const {
|
|
39
44
|
connectEligibility,
|
|
40
45
|
fetchConnectRuntimePack,
|
|
@@ -111,6 +116,7 @@ function assistantLabel(runtime) {
|
|
|
111
116
|
const normalized = normalizeRuntime(runtime);
|
|
112
117
|
if (normalized === "codex") return "Codex";
|
|
113
118
|
if (normalized === "pi") return "Pi";
|
|
119
|
+
if (normalized === "prime") return "Prime Agent";
|
|
114
120
|
return "Claude Code";
|
|
115
121
|
}
|
|
116
122
|
|
|
@@ -137,6 +143,12 @@ async function upgradePortableRuntimesForExisting(instances) {
|
|
|
137
143
|
label: `Pi meta-harness for ${inst.slug || inst.name || path.basename(inst.path)}`,
|
|
138
144
|
includeConflicts: !piReady,
|
|
139
145
|
});
|
|
146
|
+
const primeSummary = installPrimeRuntime(inst.path);
|
|
147
|
+
const primeReady = hasPrimeRuntimeSupport(inst.path);
|
|
148
|
+
reportPrimeRuntimeSummary(primeSummary, ui, {
|
|
149
|
+
label: `Prime Agent runtime for ${inst.slug || inst.name || path.basename(inst.path)}`,
|
|
150
|
+
includeConflicts: !primeReady,
|
|
151
|
+
});
|
|
140
152
|
const connectSummary = await installConnectRuntime(inst.path, { validatedPack: connectPack });
|
|
141
153
|
reportConnectRuntimeSummary(connectSummary, ui, {
|
|
142
154
|
label: `Connect features for ${inst.slug || inst.name || path.basename(inst.path)}`,
|
|
@@ -163,9 +175,10 @@ async function chooseRuntime(args) {
|
|
|
163
175
|
"claude-code": binaryOnPath("claude"),
|
|
164
176
|
codex: binaryOnPath("codex"),
|
|
165
177
|
pi: binaryOnPath("pi"),
|
|
178
|
+
prime: binaryOnPath("prime-agent"),
|
|
166
179
|
};
|
|
167
180
|
const recommended = Object.keys(installedByRuntime).find((runtime) => installedByRuntime[runtime]) || "claude-code";
|
|
168
|
-
const choices = ["claude-code", "codex", "pi"]
|
|
181
|
+
const choices = ["claude-code", "codex", "pi", "prime"]
|
|
169
182
|
.map((runtime) => {
|
|
170
183
|
const installed = installedByRuntime[runtime];
|
|
171
184
|
const label = assistantLabel(runtime);
|
|
@@ -173,7 +186,7 @@ async function chooseRuntime(args) {
|
|
|
173
186
|
return {
|
|
174
187
|
label: `${label}${installed ? "" : " (not installed)"}${recommended === runtime ? " (recommended)" : ""}`,
|
|
175
188
|
description: installed
|
|
176
|
-
? (runtime === "claude-code" ? "Installed · Claude Code integration" : runtime === "pi" ? "Installed · project-local meta-harness" : "Installed · portable agent protocol")
|
|
189
|
+
? (runtime === "claude-code" ? "Installed · Claude Code integration" : runtime === "pi" || runtime === "prime" ? "Installed · project-local meta-harness" : "Installed · portable agent protocol")
|
|
177
190
|
: missingCopy,
|
|
178
191
|
runtime,
|
|
179
192
|
installed,
|
|
@@ -249,6 +262,8 @@ function parseArgs(argv) {
|
|
|
249
262
|
args.runtime = "codex";
|
|
250
263
|
} else if (argv[i] === "--pi") {
|
|
251
264
|
args.runtime = "pi";
|
|
265
|
+
} else if (argv[i] === "--prime") {
|
|
266
|
+
args.runtime = "prime";
|
|
252
267
|
} else if (argv[i] === "--claude" || argv[i] === "--claude-code") {
|
|
253
268
|
args.runtime = "claude-code";
|
|
254
269
|
} else if (argv[i] === "--runtime" && argv[i + 1]) {
|
|
@@ -412,8 +427,9 @@ function showHelp() {
|
|
|
412
427
|
ui.info(" --api <url> Use connected API setup with this URL");
|
|
413
428
|
ui.info(" --codex Prefer Codex for this local install");
|
|
414
429
|
ui.info(" --pi Prefer Pi for this local install");
|
|
430
|
+
ui.info(" --prime Prefer Prime Agent for this local install");
|
|
415
431
|
ui.info(" --claude Prefer Claude Code for this local install");
|
|
416
|
-
ui.info(" --runtime <name> Harness override: claude-code, codex, or
|
|
432
|
+
ui.info(" --runtime <name> Harness override: claude-code, codex, pi, or prime");
|
|
417
433
|
ui.info(" --force Skip the in-repo detection check");
|
|
418
434
|
ui.info(" --no-autolaunch Don't launch the harness at the end (for CI)");
|
|
419
435
|
ui.info(" --no-screens Skip the full-screen welcome/ready bookends");
|
package/lib/connect-runtime.js
CHANGED
|
@@ -83,14 +83,16 @@ function validateConnectPack(pack) {
|
|
|
83
83
|
if (pack.schemaVersion !== 1 || pack.availability !== "connect") {
|
|
84
84
|
throw new Error(`Unsupported Connect runtime pack schema: ${pack.schemaVersion}`);
|
|
85
85
|
}
|
|
86
|
-
if (!Array.isArray(pack.skills)
|
|
86
|
+
if (!Array.isArray(pack.skills)) {
|
|
87
87
|
throw new Error("Connect runtime pack has no skill inventory");
|
|
88
88
|
}
|
|
89
|
+
// An empty inventory is valid: every gated connector skill can ship in the
|
|
90
|
+
// OSS base, leaving the overlay with nothing to add for now.
|
|
89
91
|
const skills = [...new Set(pack.skills)];
|
|
90
92
|
if (skills.length !== pack.skills.length || skills.some((name) => !/^[a-z0-9-]+$/.test(name))) {
|
|
91
93
|
throw new Error("Connect runtime pack has an invalid skill inventory");
|
|
92
94
|
}
|
|
93
|
-
if (!Array.isArray(pack.files) || pack.files.length
|
|
95
|
+
if (!Array.isArray(pack.files) || pack.files.length > MAX_FILES) {
|
|
94
96
|
throw new Error("Connect runtime pack has an invalid file inventory");
|
|
95
97
|
}
|
|
96
98
|
if (!/^[a-f0-9]{64}$/.test(pack.packVersion || "")) {
|
package/lib/local.js
CHANGED
|
@@ -17,6 +17,7 @@ const {
|
|
|
17
17
|
} = require("./auth");
|
|
18
18
|
const { installCodexRuntime, reportCodexRuntimeSummary } = require("./codex-runtime");
|
|
19
19
|
const { installPiRuntime, reportPiRuntimeSummary } = require("./pi-runtime");
|
|
20
|
+
const { installPrimeRuntime, reportPrimeRuntimeSummary } = require("./prime-runtime");
|
|
20
21
|
const {
|
|
21
22
|
install,
|
|
22
23
|
ghApi,
|
|
@@ -1398,6 +1399,17 @@ async function localFounderFlow(ui, ctx = {}) {
|
|
|
1398
1399
|
run("git push", { cwd: egregoreDir });
|
|
1399
1400
|
}
|
|
1400
1401
|
} catch {}
|
|
1402
|
+
} else if (preferredRuntime === "prime") {
|
|
1403
|
+
const primeRuntime = installPrimeRuntime(egregoreDir);
|
|
1404
|
+
reportPrimeRuntimeSummary(primeRuntime, ui);
|
|
1405
|
+
try {
|
|
1406
|
+
const toCommit = Array.isArray(primeRuntime.files) ? [...primeRuntime.files] : [];
|
|
1407
|
+
if (toCommit.length) {
|
|
1408
|
+
execFileSync("git", ["add", "--", ...toCommit], { cwd: egregoreDir, stdio: "pipe" });
|
|
1409
|
+
run('git commit -m "Add Prime Agent meta-harness runtime"', { cwd: egregoreDir });
|
|
1410
|
+
run("git push", { cwd: egregoreDir });
|
|
1411
|
+
}
|
|
1412
|
+
} catch {}
|
|
1401
1413
|
} else {
|
|
1402
1414
|
stripCodexRuntimeForClaude(egregoreDir, ui);
|
|
1403
1415
|
}
|
|
@@ -1570,7 +1582,9 @@ async function localFounderFlow(ui, ctx = {}) {
|
|
|
1570
1582
|
? "Codex"
|
|
1571
1583
|
: preferredRuntime === "pi"
|
|
1572
1584
|
? "Pi"
|
|
1573
|
-
:
|
|
1585
|
+
: preferredRuntime === "prime"
|
|
1586
|
+
? "Prime Agent"
|
|
1587
|
+
: "Claude Code";
|
|
1574
1588
|
const setupSummary = {
|
|
1575
1589
|
workspace: "created",
|
|
1576
1590
|
invite: invitedUsers.length
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const crypto = require("node:crypto");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
|
|
7
|
+
const PACKAGE = require("../package.json");
|
|
8
|
+
|
|
9
|
+
const BUNDLE_DIR = path.join(__dirname, "..", "runtime", "prime");
|
|
10
|
+
const BUNDLE_MANIFEST = path.join(BUNDLE_DIR, "manifest.json");
|
|
11
|
+
const LOCAL_MANIFEST = path.join(".egregore", "prime-runtime-manifest.json");
|
|
12
|
+
|
|
13
|
+
const REQUIRED_RUNTIME_PATHS = [
|
|
14
|
+
"AGENTS.md",
|
|
15
|
+
".prime/agent/APPEND_SYSTEM.md",
|
|
16
|
+
".prime/agent/settings.json",
|
|
17
|
+
".prime/agent/extensions/egregore.ts",
|
|
18
|
+
".prime/agent/skills/egregore/SKILL.md",
|
|
19
|
+
".codex/skills",
|
|
20
|
+
"bin/agent.sh",
|
|
21
|
+
"bin/pi-branch-policy.mjs",
|
|
22
|
+
"bin/pi-product-workflows.mjs",
|
|
23
|
+
"bin/prime-session-start.sh",
|
|
24
|
+
"bin/codex-session-start.sh",
|
|
25
|
+
"bin/codex-skill-render.mjs",
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
function hashBuffer(buffer) {
|
|
29
|
+
return crypto.createHash("sha256").update(buffer).digest("hex");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function readJson(file, fallback) {
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
35
|
+
} catch {
|
|
36
|
+
return fallback;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function listFiles(dir, prefix = "") {
|
|
41
|
+
if (!fs.existsSync(dir)) return [];
|
|
42
|
+
const result = [];
|
|
43
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
44
|
+
const rel = prefix ? path.join(prefix, entry.name) : entry.name;
|
|
45
|
+
const full = path.join(dir, entry.name);
|
|
46
|
+
if (entry.isDirectory()) result.push(...listFiles(full, rel));
|
|
47
|
+
else if (entry.isFile()) result.push(rel);
|
|
48
|
+
}
|
|
49
|
+
return result.sort();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function bundleManifest() {
|
|
53
|
+
return readJson(BUNDLE_MANIFEST, { files: [], skills: [], skillCount: 0 });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function bundleFiles() {
|
|
57
|
+
return listFiles(BUNDLE_DIR).filter((rel) => rel !== "manifest.json");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function installManifestPath(egregoreDir) {
|
|
61
|
+
const gitPath = path.join(egregoreDir, ".git");
|
|
62
|
+
try {
|
|
63
|
+
const stat = fs.lstatSync(gitPath);
|
|
64
|
+
if (stat.isDirectory()) return path.join(gitPath, "info", "egregore-prime-runtime.json");
|
|
65
|
+
if (stat.isFile()) {
|
|
66
|
+
const match = fs.readFileSync(gitPath, "utf8").trim().match(/^gitdir:\s*(.+)$/);
|
|
67
|
+
if (match) {
|
|
68
|
+
const gitDir = path.isAbsolute(match[1]) ? match[1] : path.resolve(egregoreDir, match[1]);
|
|
69
|
+
return path.join(gitDir, "info", "egregore-prime-runtime.json");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} catch {}
|
|
73
|
+
return path.join(egregoreDir, LOCAL_MANIFEST);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function pathExists(file) {
|
|
77
|
+
try {
|
|
78
|
+
fs.lstatSync(file);
|
|
79
|
+
return true;
|
|
80
|
+
} catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function copyFile(src, dest) {
|
|
86
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
87
|
+
fs.copyFileSync(src, dest);
|
|
88
|
+
try { fs.chmodSync(dest, fs.statSync(src).mode & 0o777); } catch {}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function installPrimeRuntime(egregoreDir) {
|
|
92
|
+
if (!fs.existsSync(BUNDLE_DIR)) throw new Error(`Prime runtime bundle missing: ${BUNDLE_DIR}`);
|
|
93
|
+
|
|
94
|
+
const previousPath = installManifestPath(egregoreDir);
|
|
95
|
+
const previous = readJson(previousPath, { files: {} });
|
|
96
|
+
const previousFiles = previous.files || {};
|
|
97
|
+
const next = {
|
|
98
|
+
package: PACKAGE.name,
|
|
99
|
+
version: PACKAGE.version,
|
|
100
|
+
installedAt: new Date().toISOString(),
|
|
101
|
+
files: {},
|
|
102
|
+
};
|
|
103
|
+
const summary = {
|
|
104
|
+
installed: 0,
|
|
105
|
+
updated: 0,
|
|
106
|
+
removed: 0,
|
|
107
|
+
skipped: 0,
|
|
108
|
+
conflicted: 0,
|
|
109
|
+
conflicts: [],
|
|
110
|
+
files: [],
|
|
111
|
+
bundleSkills: bundleManifest().skills || [],
|
|
112
|
+
bundleSkillCount: bundleManifest().skillCount || 0,
|
|
113
|
+
};
|
|
114
|
+
const currentBundleFiles = bundleFiles();
|
|
115
|
+
const currentBundleSet = new Set(currentBundleFiles);
|
|
116
|
+
|
|
117
|
+
for (const [rel, record] of Object.entries(previousFiles)) {
|
|
118
|
+
if (currentBundleSet.has(rel)) continue;
|
|
119
|
+
const dest = path.join(egregoreDir, rel);
|
|
120
|
+
if (!pathExists(dest)) continue;
|
|
121
|
+
let stat;
|
|
122
|
+
try { stat = fs.lstatSync(dest); } catch { continue; }
|
|
123
|
+
if (stat.isFile() && hashBuffer(fs.readFileSync(dest)) === record.hash) {
|
|
124
|
+
fs.unlinkSync(dest);
|
|
125
|
+
try { fs.rmdirSync(path.dirname(dest)); } catch {}
|
|
126
|
+
summary.removed += 1;
|
|
127
|
+
} else {
|
|
128
|
+
summary.conflicted += 1;
|
|
129
|
+
summary.conflicts.push(rel);
|
|
130
|
+
next.files[rel] = { hash: record.hash };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
for (const rel of currentBundleFiles) {
|
|
135
|
+
const src = path.join(BUNDLE_DIR, rel);
|
|
136
|
+
const dest = path.join(egregoreDir, rel);
|
|
137
|
+
const sourceHash = hashBuffer(fs.readFileSync(src));
|
|
138
|
+
const previousHash = previousFiles[rel]?.hash;
|
|
139
|
+
const record = () => {
|
|
140
|
+
next.files[rel] = { hash: sourceHash };
|
|
141
|
+
summary.files.push(rel);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
if (!pathExists(dest)) {
|
|
145
|
+
copyFile(src, dest);
|
|
146
|
+
summary.installed += 1;
|
|
147
|
+
record();
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let stat;
|
|
152
|
+
try { stat = fs.lstatSync(dest); } catch {}
|
|
153
|
+
if (!stat?.isFile()) {
|
|
154
|
+
summary.conflicted += 1;
|
|
155
|
+
summary.conflicts.push(rel);
|
|
156
|
+
if (previousHash) next.files[rel] = { hash: previousHash };
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const currentHash = hashBuffer(fs.readFileSync(dest));
|
|
161
|
+
if (currentHash === sourceHash) {
|
|
162
|
+
try { fs.chmodSync(dest, fs.statSync(src).mode & 0o777); } catch {}
|
|
163
|
+
summary.skipped += 1;
|
|
164
|
+
record();
|
|
165
|
+
} else if (previousHash && currentHash === previousHash) {
|
|
166
|
+
copyFile(src, dest);
|
|
167
|
+
summary.updated += 1;
|
|
168
|
+
record();
|
|
169
|
+
} else {
|
|
170
|
+
summary.conflicted += 1;
|
|
171
|
+
summary.conflicts.push(rel);
|
|
172
|
+
if (previousHash) next.files[rel] = { hash: previousHash };
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
fs.mkdirSync(path.dirname(previousPath), { recursive: true });
|
|
177
|
+
fs.writeFileSync(previousPath, JSON.stringify(next, null, 2) + "\n");
|
|
178
|
+
return summary;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function hasPrimeRuntimeSupport(egregoreDir) {
|
|
182
|
+
return REQUIRED_RUNTIME_PATHS.every((rel) => fs.existsSync(path.join(egregoreDir, rel)));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function reportPrimeRuntimeSummary(summary, ui, opts = {}) {
|
|
186
|
+
if (!summary || !ui) return;
|
|
187
|
+
const label = opts.label || "Prime Agent runtime";
|
|
188
|
+
const changed = summary.installed + summary.updated + (summary.removed || 0);
|
|
189
|
+
if (changed > 0) {
|
|
190
|
+
ui.success(`${label} ready (${summary.installed} installed, ${summary.updated} updated, ${summary.removed || 0} removed, ${summary.skipped} unchanged)`);
|
|
191
|
+
}
|
|
192
|
+
if (opts.includeConflicts !== false && summary.conflicted > 0) {
|
|
193
|
+
const count = summary.conflicted;
|
|
194
|
+
ui.info(ui.dim
|
|
195
|
+
? ui.dim(`${label}: kept ${count} framework file${count === 1 ? "" : "s"} this Egregore already manages.`)
|
|
196
|
+
: `${label}: kept ${count} framework file${count === 1 ? "" : "s"} this Egregore already manages.`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
module.exports = {
|
|
201
|
+
BUNDLE_DIR,
|
|
202
|
+
bundleFiles,
|
|
203
|
+
bundleManifest,
|
|
204
|
+
hasPrimeRuntimeSupport,
|
|
205
|
+
installManifestPath,
|
|
206
|
+
installPrimeRuntime,
|
|
207
|
+
reportPrimeRuntimeSummary,
|
|
208
|
+
};
|