create-egregore 0.21.0-runtime-mvp.4 → 0.21.0-runtime-mvp.6
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 +109 -14
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// egregore-launcher-version: 0.21.0-runtime-mvp.
|
|
2
|
+
// egregore-launcher-version: 0.21.0-runtime-mvp.6
|
|
3
3
|
//
|
|
4
4
|
// egregore — launch and browse Egregore instances from your terminal.
|
|
5
5
|
// Installed by create-egregore. Reads ~/.egregore/instances.json.
|
|
@@ -35,7 +35,7 @@ const crypto = require("node:crypto");
|
|
|
35
35
|
const { spawnSync, spawn } = require("node:child_process");
|
|
36
36
|
const readline = require("node:readline");
|
|
37
37
|
|
|
38
|
-
const VERSION = "0.21.0-runtime-mvp.
|
|
38
|
+
const VERSION = "0.21.0-runtime-mvp.6";
|
|
39
39
|
const REGISTRY = path.join(os.homedir(), ".egregore", "instances.json");
|
|
40
40
|
const DEFAULT_FILE = path.join(os.homedir(), ".egregore", "default");
|
|
41
41
|
const UPDATE_CACHE_FILE = path.join(os.homedir(), ".egregore", "update-check.json");
|
|
@@ -2564,6 +2564,54 @@ async function fetchRuntimeMvpCandidate() {
|
|
|
2564
2564
|
}
|
|
2565
2565
|
}
|
|
2566
2566
|
|
|
2567
|
+
// Fetch the published candidate tarball from the npm registry and verify its
|
|
2568
|
+
// integrity before staging. The first-timer path: `p prepare` with nothing
|
|
2569
|
+
// staged must not dead-end into a CLI instruction referencing a tarball the
|
|
2570
|
+
// user does not have — the registry has it, digest-verified.
|
|
2571
|
+
function fetchCandidateTarball(version, cb) {
|
|
2572
|
+
const metaUrl = new URL(`https://registry.npmjs.org/${PUBLIC_NPX_PACKAGE}/${version}`);
|
|
2573
|
+
requestJson({
|
|
2574
|
+
hostname: metaUrl.hostname,
|
|
2575
|
+
path: metaUrl.pathname,
|
|
2576
|
+
method: "GET",
|
|
2577
|
+
protocol: metaUrl.protocol,
|
|
2578
|
+
timeoutMs: 10000,
|
|
2579
|
+
headers: { Accept: "application/json" },
|
|
2580
|
+
}).then((meta) => {
|
|
2581
|
+
const dist = meta && meta.status === 200 && meta.data && meta.data.dist;
|
|
2582
|
+
if (!dist || !dist.tarball) return cb(new Error(`candidate ${version} not found on the registry`));
|
|
2583
|
+
const dest = path.join(os.tmpdir(), `egregore-candidate-${version}.tgz`);
|
|
2584
|
+
const fetchTarball = (url, redirects) => {
|
|
2585
|
+
https.get(url, { headers: { "User-Agent": "egregore-launcher" } }, (res) => {
|
|
2586
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location && redirects > 0) {
|
|
2587
|
+
res.resume();
|
|
2588
|
+
return fetchTarball(res.headers.location, redirects - 1);
|
|
2589
|
+
}
|
|
2590
|
+
if (res.statusCode !== 200) {
|
|
2591
|
+
res.resume();
|
|
2592
|
+
return cb(new Error(`tarball download failed (HTTP ${res.statusCode})`));
|
|
2593
|
+
}
|
|
2594
|
+
const hash = crypto.createHash("sha512");
|
|
2595
|
+
const out = fs.createWriteStream(dest);
|
|
2596
|
+
res.on("data", (d) => hash.update(d));
|
|
2597
|
+
res.pipe(out);
|
|
2598
|
+
out.on("finish", () => {
|
|
2599
|
+
out.close(() => {
|
|
2600
|
+
const digest = `sha512-${hash.digest("base64")}`;
|
|
2601
|
+
if (dist.integrity && digest !== dist.integrity) {
|
|
2602
|
+
fs.rmSync(dest, { force: true });
|
|
2603
|
+
return cb(new Error("candidate integrity mismatch — refusing to stage"));
|
|
2604
|
+
}
|
|
2605
|
+
cb(null, dest);
|
|
2606
|
+
});
|
|
2607
|
+
});
|
|
2608
|
+
out.on("error", (err) => cb(err));
|
|
2609
|
+
}).on("error", (err) => cb(err));
|
|
2610
|
+
};
|
|
2611
|
+
fetchTarball(dist.tarball, 3);
|
|
2612
|
+
}).catch((err) => cb(err));
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2567
2615
|
const UPGRADE_STATUS_LABEL = {
|
|
2568
2616
|
none: "no update staged",
|
|
2569
2617
|
pending: "staged, not started",
|
|
@@ -2576,6 +2624,26 @@ const UPGRADE_STATUS_LABEL = {
|
|
|
2576
2624
|
"rolled-back": "rolled back",
|
|
2577
2625
|
};
|
|
2578
2626
|
|
|
2627
|
+
// Settings-row truth for the Runtime update line. The row must say outright
|
|
2628
|
+
// whether this egregore runs the new Runtime — "no update staged" is
|
|
2629
|
+
// transaction state, not the condition the user needs to see.
|
|
2630
|
+
function runtimeUpdateRowValue(st, candidate) {
|
|
2631
|
+
if (st === undefined) return `${DIM}checking…${RESET}`;
|
|
2632
|
+
if (st === null) return `${DIM}unavailable${RESET}`;
|
|
2633
|
+
if (st.status === "active") {
|
|
2634
|
+
const v = st.active_version || "?";
|
|
2635
|
+
if (candidate && candidate !== v) return `${v} active ${YELLOW}· update available ${candidate}${RESET}`;
|
|
2636
|
+
return `${GREEN}${v} active${RESET}${candidate ? `${DIM} · up to date${RESET}` : ""}`;
|
|
2637
|
+
}
|
|
2638
|
+
if (st.status === "ready-to-activate") return `${GREEN}${upgradeSummary(st)}${RESET}`;
|
|
2639
|
+
if (st.status === "failed" || st.status === "interrupted") return `${YELLOW}${upgradeSummary(st)}${RESET}`;
|
|
2640
|
+
if (st.status === "preparing" || st.status === "pending") return `${DIM}${upgradeSummary(st)}${RESET}`;
|
|
2641
|
+
// No activation record (or cancelled/rolled back): this egregore is not on
|
|
2642
|
+
// the new Runtime. Say so, and name the candidate when we know it.
|
|
2643
|
+
const base = `${YELLOW}not updated to the new Runtime${RESET}`;
|
|
2644
|
+
return candidate ? `${base}${DIM} · ${candidate} available${RESET}` : base;
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2579
2647
|
function upgradeSummary(st) {
|
|
2580
2648
|
// "none" means no activation record — a first-time state, not freshness.
|
|
2581
2649
|
if (!st || st.status === "none") return "no update staged";
|
|
@@ -3086,7 +3154,7 @@ function renderUpgradePanel({ inst, data, candidate, retrieval, mode, notice, wi
|
|
|
3086
3154
|
return lines;
|
|
3087
3155
|
}
|
|
3088
3156
|
|
|
3089
|
-
function renderSettingsPanel({ inst, data, cursor, view, domain, items, listCursor, mode, input, notice, width, upgrade, retrieval }) {
|
|
3157
|
+
function renderSettingsPanel({ inst, data, cursor, view, domain, items, listCursor, mode, input, notice, width, upgrade, retrieval, candidate }) {
|
|
3090
3158
|
const title = inst.slug || inst.name || path.basename(inst.path);
|
|
3091
3159
|
const outerWidth = Math.min(Math.max(50, width - 2), 126);
|
|
3092
3160
|
const innerWidth = Math.max(48, outerWidth - 2);
|
|
@@ -3231,15 +3299,7 @@ function renderSettingsPanel({ inst, data, cursor, view, domain, items, listCurs
|
|
|
3231
3299
|
lines.push(boxLine(`${DIM}↑↓ nav · ${RESET}${BOLD}a${RESET}${DIM} add · ${RESET}${BOLD}d${RESET}${DIM} delete · ← back · q quit${RESET}`, innerWidth, margin));
|
|
3232
3300
|
}
|
|
3233
3301
|
} else {
|
|
3234
|
-
const upgradeValue = upgrade
|
|
3235
|
-
? `${DIM}checking…${RESET}`
|
|
3236
|
-
: upgrade === null
|
|
3237
|
-
? `${DIM}unavailable${RESET}`
|
|
3238
|
-
: upgrade.status === "ready-to-activate"
|
|
3239
|
-
? `${GREEN}${upgradeSummary(upgrade)}${RESET}`
|
|
3240
|
-
: upgrade.status === "failed" || upgrade.status === "interrupted"
|
|
3241
|
-
? `${YELLOW}${upgradeSummary(upgrade)}${RESET}`
|
|
3242
|
-
: `${DIM}${upgradeSummary(upgrade)}${RESET}`;
|
|
3302
|
+
const upgradeValue = runtimeUpdateRowValue(upgrade, candidate);
|
|
3243
3303
|
const rows = [
|
|
3244
3304
|
{
|
|
3245
3305
|
name: "Runtime update",
|
|
@@ -3427,6 +3487,7 @@ async function browser(args = {}) {
|
|
|
3427
3487
|
width: w,
|
|
3428
3488
|
upgrade: state.settingsUpgrade,
|
|
3429
3489
|
retrieval: state.settingsRetrieval,
|
|
3490
|
+
candidate: state.upgradeCandidate,
|
|
3430
3491
|
});
|
|
3431
3492
|
for (const line of settingsLines) out.push(line + ANSI.clearLine + "\n");
|
|
3432
3493
|
const remainingRows = Math.max(0, h - settingsLines.length - 1);
|
|
@@ -3771,8 +3832,36 @@ async function browser(args = {}) {
|
|
|
3771
3832
|
&& !["none", "cancelled", "rolled-back"].includes(status)
|
|
3772
3833
|
&& state.upgradeData.candidate_version;
|
|
3773
3834
|
if (!staged) {
|
|
3774
|
-
|
|
3775
|
-
|
|
3835
|
+
const candidate = state.upgradeCandidate;
|
|
3836
|
+
if (!candidate) {
|
|
3837
|
+
state.upgradeNotice = `${DIM}No published candidate found. Stage one manually: egregore settings ${state.upgradeInst.slug} runtime init --candidate <version> --tarball <candidate.tgz>${RESET}`;
|
|
3838
|
+
render(); return;
|
|
3839
|
+
}
|
|
3840
|
+
if (state.upgradeFetching) { render(); return; }
|
|
3841
|
+
state.upgradeFetching = true;
|
|
3842
|
+
const inst = state.upgradeInst;
|
|
3843
|
+
state.upgradeNotice = `${DIM}Downloading ${candidate} from npm…${RESET}`;
|
|
3844
|
+
render();
|
|
3845
|
+
fetchCandidateTarball(candidate, (err, tgz) => {
|
|
3846
|
+
state.upgradeFetching = false;
|
|
3847
|
+
if (!state.upgradeInst || state.upgradeInst !== inst) return;
|
|
3848
|
+
if (err) {
|
|
3849
|
+
state.upgradeNotice = `${YELLOW}${err.message}${RESET}`;
|
|
3850
|
+
render(); return;
|
|
3851
|
+
}
|
|
3852
|
+
const r = runUpgrade(inst, ["init", "--candidate", candidate, "--tarball", tgz]);
|
|
3853
|
+
if (r === null || r.status !== 0) {
|
|
3854
|
+
const detail = ((r && (r.stderr || r.stdout)) || "staging failed").trim().split("\n")[0];
|
|
3855
|
+
state.upgradeNotice = `${YELLOW}${detail}${RESET}`;
|
|
3856
|
+
render(); return;
|
|
3857
|
+
}
|
|
3858
|
+
refreshUpgrade();
|
|
3859
|
+
state.upgradeData = upgradeStatus(inst) || state.upgradeData;
|
|
3860
|
+
state.upgradeNotice = "";
|
|
3861
|
+
state.upgradeMode = "confirm-prepare";
|
|
3862
|
+
render();
|
|
3863
|
+
});
|
|
3864
|
+
return;
|
|
3776
3865
|
}
|
|
3777
3866
|
state.upgradeMode = "confirm-prepare"; render(); return;
|
|
3778
3867
|
}
|
|
@@ -4256,6 +4345,12 @@ async function browser(args = {}) {
|
|
|
4256
4345
|
state.settingsRetrieval = health;
|
|
4257
4346
|
if (state.settingsInst === pick && !state.upgradeInst) render();
|
|
4258
4347
|
});
|
|
4348
|
+
if (!state.upgradeCandidate) {
|
|
4349
|
+
fetchRuntimeMvpCandidate().then((v) => {
|
|
4350
|
+
state.upgradeCandidate = v || "";
|
|
4351
|
+
if (state.settingsInst === pick && !state.upgradeInst) render();
|
|
4352
|
+
});
|
|
4353
|
+
}
|
|
4259
4354
|
state.settingsNotice = "";
|
|
4260
4355
|
render();
|
|
4261
4356
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-egregore",
|
|
3
|
-
"version": "0.21.0-runtime-mvp.
|
|
3
|
+
"version": "0.21.0-runtime-mvp.6",
|
|
4
4
|
"description": "Set up Egregore for your team in one command — installs the egregore launcher and your choice of Claude Code, Codex, or Pi.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|