create-egregore 0.21.0-runtime-mvp.5 → 0.21.0-runtime-mvp.7
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 +148 -7
- 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.7
|
|
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.7";
|
|
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",
|
|
@@ -3121,6 +3169,40 @@ function renderSettingsPanel({ inst, data, cursor, view, domain, items, listCurs
|
|
|
3121
3169
|
emptyBoxLine(innerWidth, margin),
|
|
3122
3170
|
];
|
|
3123
3171
|
|
|
3172
|
+
if (view === "workflow") {
|
|
3173
|
+
const current = (d.workflow === "simple" || d.workflow === "staged") ? d.workflow : "custom";
|
|
3174
|
+
lines.push(boxLine(`${BOLD}Git workflow${RESET}`, innerWidth, margin));
|
|
3175
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3176
|
+
const options = [
|
|
3177
|
+
{ key: "simple", name: "Simple", detail: "pull requests target main — one branch, no release staging" },
|
|
3178
|
+
{ key: "staged", name: "Staged", detail: "pull requests target develop; releases promote to main" },
|
|
3179
|
+
];
|
|
3180
|
+
options.forEach((option, i) => {
|
|
3181
|
+
const sel = i === listCursor;
|
|
3182
|
+
const marker = sel ? `${CYAN}❯${RESET}` : " ";
|
|
3183
|
+
const active = option.key === current ? ` ${GREEN}● current${RESET}` : "";
|
|
3184
|
+
lines.push(boxLine(`${marker} ${sel ? BOLD : ""}${option.name}${RESET}${active}`, innerWidth, margin));
|
|
3185
|
+
lines.push(boxLine(` ${DIM}${option.detail}${RESET}`, innerWidth, margin));
|
|
3186
|
+
});
|
|
3187
|
+
if (current === "custom") {
|
|
3188
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3189
|
+
lines.push(boxLine(`${YELLOW}● current: CUSTOM${RESET} ${DIM}— pull requests target ${d.base_branch || "?"}${RESET}`, innerWidth, margin));
|
|
3190
|
+
lines.push(boxLine(` ${DIM}selecting an option above replaces this for the whole org${RESET}`, innerWidth, margin));
|
|
3191
|
+
}
|
|
3192
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3193
|
+
if (mode === "confirm") {
|
|
3194
|
+
const target = listCursor === 0 ? "SIMPLE — pull requests target main" : "STAGED — pull requests target develop";
|
|
3195
|
+
lines.push(boxLine(`${YELLOW}Switch ${BOLD}${title}${RESET}${YELLOW} to ${target}?${RESET}`, innerWidth, margin));
|
|
3196
|
+
lines.push(boxLine(`${DIM}This edits the org's committed egregore.json for everyone.${RESET} ${DIM}y / N${RESET}`, innerWidth, margin));
|
|
3197
|
+
} else {
|
|
3198
|
+
if (notice) lines.push(boxLine(notice, innerWidth, margin));
|
|
3199
|
+
lines.push(boxLine(`${DIM}↑↓ nav · ${RESET}${BOLD}enter${RESET}${DIM} select · ← back · q quit${RESET}`, innerWidth, margin));
|
|
3200
|
+
}
|
|
3201
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3202
|
+
lines.push(`${margin}${DIM}└${"─".repeat(innerWidth)}┘${RESET}`);
|
|
3203
|
+
return lines;
|
|
3204
|
+
}
|
|
3205
|
+
|
|
3124
3206
|
if (view === "privacy" || view === "telemetry") {
|
|
3125
3207
|
lines.push(boxLine(`${BOLD}${view === "privacy" ? "Privacy & access" : "Telemetry"}${RESET}`, innerWidth, margin));
|
|
3126
3208
|
lines.push(emptyBoxLine(innerWidth, margin));
|
|
@@ -3282,7 +3364,7 @@ function renderSettingsPanel({ inst, data, cursor, view, domain, items, listCurs
|
|
|
3282
3364
|
});
|
|
3283
3365
|
lines.push(emptyBoxLine(innerWidth, margin));
|
|
3284
3366
|
if (notice) lines.push(boxLine(notice, innerWidth, margin));
|
|
3285
|
-
lines.push(boxLine(`${DIM}↑↓ nav · ${RESET}${BOLD}enter${RESET}${DIM} ${cursor === 3
|
|
3367
|
+
lines.push(boxLine(`${DIM}↑↓ nav · ${RESET}${BOLD}enter${RESET}${DIM} ${cursor === 3 ? "toggle" : "open"} · ← back · q quit${RESET}`, innerWidth, margin));
|
|
3286
3368
|
}
|
|
3287
3369
|
|
|
3288
3370
|
lines.push(emptyBoxLine(innerWidth, margin));
|
|
@@ -3784,8 +3866,36 @@ async function browser(args = {}) {
|
|
|
3784
3866
|
&& !["none", "cancelled", "rolled-back"].includes(status)
|
|
3785
3867
|
&& state.upgradeData.candidate_version;
|
|
3786
3868
|
if (!staged) {
|
|
3787
|
-
|
|
3788
|
-
|
|
3869
|
+
const candidate = state.upgradeCandidate;
|
|
3870
|
+
if (!candidate) {
|
|
3871
|
+
state.upgradeNotice = `${DIM}No published candidate found. Stage one manually: egregore settings ${state.upgradeInst.slug} runtime init --candidate <version> --tarball <candidate.tgz>${RESET}`;
|
|
3872
|
+
render(); return;
|
|
3873
|
+
}
|
|
3874
|
+
if (state.upgradeFetching) { render(); return; }
|
|
3875
|
+
state.upgradeFetching = true;
|
|
3876
|
+
const inst = state.upgradeInst;
|
|
3877
|
+
state.upgradeNotice = `${DIM}Downloading ${candidate} from npm…${RESET}`;
|
|
3878
|
+
render();
|
|
3879
|
+
fetchCandidateTarball(candidate, (err, tgz) => {
|
|
3880
|
+
state.upgradeFetching = false;
|
|
3881
|
+
if (!state.upgradeInst || state.upgradeInst !== inst) return;
|
|
3882
|
+
if (err) {
|
|
3883
|
+
state.upgradeNotice = `${YELLOW}${err.message}${RESET}`;
|
|
3884
|
+
render(); return;
|
|
3885
|
+
}
|
|
3886
|
+
const r = runUpgrade(inst, ["init", "--candidate", candidate, "--tarball", tgz]);
|
|
3887
|
+
if (r === null || r.status !== 0) {
|
|
3888
|
+
const detail = ((r && (r.stderr || r.stdout)) || "staging failed").trim().split("\n")[0];
|
|
3889
|
+
state.upgradeNotice = `${YELLOW}${detail}${RESET}`;
|
|
3890
|
+
render(); return;
|
|
3891
|
+
}
|
|
3892
|
+
refreshUpgrade();
|
|
3893
|
+
state.upgradeData = upgradeStatus(inst) || state.upgradeData;
|
|
3894
|
+
state.upgradeNotice = "";
|
|
3895
|
+
state.upgradeMode = "confirm-prepare";
|
|
3896
|
+
render();
|
|
3897
|
+
});
|
|
3898
|
+
return;
|
|
3789
3899
|
}
|
|
3790
3900
|
state.upgradeMode = "confirm-prepare"; render(); return;
|
|
3791
3901
|
}
|
|
@@ -3800,6 +3910,36 @@ async function browser(args = {}) {
|
|
|
3800
3910
|
if (key.ctrl && key.name === "c") { cleanup(); process.exit(130); }
|
|
3801
3911
|
if (key.name === "q") { cleanup(); resolve(); return; }
|
|
3802
3912
|
|
|
3913
|
+
if (S.settingsView === "workflow") {
|
|
3914
|
+
if (S.settingsMode === "confirm") {
|
|
3915
|
+
if (chunk === "y" || chunk === "Y") {
|
|
3916
|
+
settingsRunVerb(["workflow", S.settingsListCursor === 0 ? "simple" : "staged"]);
|
|
3917
|
+
S.settingsMode = "browse";
|
|
3918
|
+
S.settingsView = "menu";
|
|
3919
|
+
render(); return;
|
|
3920
|
+
}
|
|
3921
|
+
if (key.name === "escape" || chunk === "n" || chunk === "N" || key.name === "return") {
|
|
3922
|
+
S.settingsMode = "browse"; render(); return;
|
|
3923
|
+
}
|
|
3924
|
+
return;
|
|
3925
|
+
}
|
|
3926
|
+
if (key.name === "escape" || key.name === "left") {
|
|
3927
|
+
S.settingsView = "menu"; S.settingsNotice = ""; render(); return;
|
|
3928
|
+
}
|
|
3929
|
+
if (key.name === "up" || key.name === "k") { S.settingsListCursor = (S.settingsListCursor + 1) % 2; render(); return; }
|
|
3930
|
+
if (key.name === "down" || key.name === "j") { S.settingsListCursor = (S.settingsListCursor + 1) % 2; render(); return; }
|
|
3931
|
+
if (key.name === "return") {
|
|
3932
|
+
const chosen = S.settingsListCursor === 0 ? "simple" : "staged";
|
|
3933
|
+
const current = (S.settingsData && S.settingsData.workflow) || "custom";
|
|
3934
|
+
if (chosen === current) {
|
|
3935
|
+
S.settingsNotice = `${DIM}already on ${chosen.toUpperCase()}${RESET}`;
|
|
3936
|
+
render(); return;
|
|
3937
|
+
}
|
|
3938
|
+
S.settingsMode = "confirm"; render(); return;
|
|
3939
|
+
}
|
|
3940
|
+
return;
|
|
3941
|
+
}
|
|
3942
|
+
|
|
3803
3943
|
if (S.settingsView === "privacy" || S.settingsView === "telemetry") {
|
|
3804
3944
|
const backToMenu = () => {
|
|
3805
3945
|
S.settingsView = "menu"; S.settingsMode = "browse"; S.settingsInput = ""; S.settingsNotice = ""; render();
|
|
@@ -3996,8 +4136,9 @@ async function browser(args = {}) {
|
|
|
3996
4136
|
settingsRunVerb(["hosting", on ? "off" : "on"]);
|
|
3997
4137
|
render();
|
|
3998
4138
|
} else if (S.settingsCursor === 4) {
|
|
3999
|
-
|
|
4000
|
-
|
|
4139
|
+
S.settingsView = "workflow"; S.settingsMode = "browse";
|
|
4140
|
+
S.settingsListCursor = (S.settingsData && S.settingsData.workflow) === "simple" ? 0 : 1;
|
|
4141
|
+
S.settingsNotice = "";
|
|
4001
4142
|
render();
|
|
4002
4143
|
} else {
|
|
4003
4144
|
const domain = S.settingsCursor === 5 ? "repo" : S.settingsCursor === 6 ? "admin" : "people";
|
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.7",
|
|
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": {
|