create-egregore 0.19.23 → 0.19.24
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 +50 -7
- package/assets/egregore-launcher.sh +10 -2
- package/bin/cli.js +21 -3
- package/lib/codex-runtime.js +25 -3
- package/lib/connect-runtime.js +329 -0
- package/lib/pi-runtime.js +23 -3
- package/lib/setup.js +13 -0
- package/package.json +3 -3
- package/runtime/codex/.codex/skills/handoff/SKILL.md +35 -11
- package/runtime/codex/.codex/skills/save/SKILL.md +39 -4
- package/runtime/codex/.codex/spec-manifest.json +2 -2
- package/runtime/codex/AGENTS.md +18 -1
- package/runtime/codex/bin/agent.sh +28 -14
- package/runtime/codex/bin/attendant.sh +169 -6
- package/runtime/codex/bin/codex-render-spec.mjs +18 -1
- package/runtime/codex/bin/codex-session-start.sh +13 -0
- package/runtime/codex/bin/codex-sync-skills.sh +1 -0
- package/runtime/codex/bin/graph.sh +21 -1
- package/runtime/codex/bin/handoff-run.sh +25 -5
- package/runtime/codex/bin/lib/context.sh +220 -172
- package/runtime/codex/bin/lib/dashboard-artifact.sh +113 -13
- package/runtime/codex/bin/lib/git-sync.sh +44 -8
- package/runtime/codex/bin/lib/greeting.sh +34 -11
- package/runtime/codex/bin/lib/identity.sh +32 -14
- package/runtime/codex/bin/person.py +20 -0
- package/runtime/codex/manifest.json +3 -72
- package/runtime/pi/.codex/skills/handoff/SKILL.md +35 -11
- package/runtime/pi/.codex/skills/save/SKILL.md +39 -4
- package/runtime/pi/.codex/spec-manifest.json +2 -2
- package/runtime/pi/.pi/APPEND_SYSTEM.md +18 -1
- package/runtime/pi/.pi/spec-manifest.json +2 -2
- package/runtime/pi/AGENTS.md +18 -1
- package/runtime/pi/bin/agent.sh +28 -14
- package/runtime/pi/bin/attendant.sh +169 -6
- package/runtime/pi/bin/codex-render-spec.mjs +18 -1
- package/runtime/pi/bin/codex-session-start.sh +13 -0
- package/runtime/pi/bin/codex-sync-skills.sh +1 -0
- package/runtime/pi/bin/graph.sh +21 -1
- package/runtime/pi/bin/handoff-run.sh +25 -5
- package/runtime/pi/bin/lib/context.sh +220 -172
- package/runtime/pi/bin/lib/dashboard-artifact.sh +113 -13
- package/runtime/pi/bin/lib/git-sync.sh +44 -8
- package/runtime/pi/bin/lib/greeting.sh +34 -11
- package/runtime/pi/bin/lib/identity.sh +32 -14
- package/runtime/pi/bin/person.py +20 -0
- package/runtime/pi/bin/pi-product-workflows.mjs +5 -1
- package/runtime/pi/manifest.json +3 -72
- package/runtime/codex/.codex/skills/add/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/answer/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/ask/SKILL.md +0 -67
- package/runtime/codex/.codex/skills/audit/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/autosave/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/branch/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/commit/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/demo-mode/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/deploy-bridge/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/design/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/egregore-voice/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/emissary/SKILL.md +0 -45
- package/runtime/codex/.codex/skills/env/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/ingest-google/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/minion/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/mock/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/pr/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/product-voice/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/project/SKILL.md +0 -45
- package/runtime/codex/.codex/skills/pull/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/push/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/quest-suggest/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/review-pr/SKILL.md +0 -45
- package/runtime/codex/.codex/skills/scroll/SKILL.md +0 -288
- package/runtime/codex/.codex/skills/scroll/agents/openai.yaml +0 -4
- package/runtime/codex/.codex/skills/scroll/assets/shell.html +0 -871
- package/runtime/codex/.codex/skills/search/SKILL.md +0 -79
- package/runtime/codex/.codex/skills/session-view/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/setup/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/summon/SKILL.md +0 -45
- package/runtime/codex/.codex/skills/task/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/teams-connect/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/telegram-connect/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/the-spiral/SKILL.md +0 -84
- package/runtime/codex/.codex/skills/thread/SKILL.md +0 -29
- package/runtime/codex/.codex/skills/todo/SKILL.md +0 -45
- package/runtime/pi/.codex/skills/add/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/answer/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/ask/SKILL.md +0 -67
- package/runtime/pi/.codex/skills/audit/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/autosave/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/branch/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/commit/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/demo-mode/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/deploy-bridge/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/design/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/egregore-voice/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/emissary/SKILL.md +0 -45
- package/runtime/pi/.codex/skills/env/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/ingest-google/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/minion/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/mock/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/pr/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/product-voice/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/project/SKILL.md +0 -45
- package/runtime/pi/.codex/skills/pull/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/push/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/quest-suggest/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/review-pr/SKILL.md +0 -45
- package/runtime/pi/.codex/skills/scroll/SKILL.md +0 -288
- package/runtime/pi/.codex/skills/scroll/agents/openai.yaml +0 -4
- package/runtime/pi/.codex/skills/scroll/assets/shell.html +0 -871
- package/runtime/pi/.codex/skills/search/SKILL.md +0 -79
- package/runtime/pi/.codex/skills/session-view/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/setup/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/summon/SKILL.md +0 -45
- package/runtime/pi/.codex/skills/task/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/teams-connect/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/telegram-connect/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/the-spiral/SKILL.md +0 -84
- package/runtime/pi/.codex/skills/thread/SKILL.md +0 -29
- package/runtime/pi/.codex/skills/todo/SKILL.md +0 -45
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// egregore-launcher-version: 0.19.
|
|
2
|
+
// egregore-launcher-version: 0.19.24
|
|
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.19.
|
|
36
|
+
const VERSION = "0.19.24";
|
|
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");
|
|
@@ -670,6 +670,27 @@ async function renderCodexStartupCard(egregoreDir) {
|
|
|
670
670
|
return false;
|
|
671
671
|
}
|
|
672
672
|
|
|
673
|
+
function renderClaudeGreetingCard(egregoreDir) {
|
|
674
|
+
// Claude Code counterpart of renderCodexStartupCard: prints the card the
|
|
675
|
+
// previous boot cached (bin/greeting-card.sh) instead of re-rendering —
|
|
676
|
+
// must stay instant. Never fatal: a miss (first boot, stale cache, old
|
|
677
|
+
// core) just means the session renders the full greeting itself.
|
|
678
|
+
const script = path.join(egregoreDir, "bin", "greeting-card.sh");
|
|
679
|
+
if (!fs.existsSync(script)) return false;
|
|
680
|
+
try {
|
|
681
|
+
const result = spawnSync("bash", [script], {
|
|
682
|
+
cwd: egregoreDir,
|
|
683
|
+
encoding: "utf8",
|
|
684
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
685
|
+
});
|
|
686
|
+
if (result.status === 0 && result.stdout) {
|
|
687
|
+
process.stdout.write(result.stdout);
|
|
688
|
+
return true;
|
|
689
|
+
}
|
|
690
|
+
} catch {}
|
|
691
|
+
return false;
|
|
692
|
+
}
|
|
693
|
+
|
|
673
694
|
function codexSupportMessage(egregoreDir) {
|
|
674
695
|
return [
|
|
675
696
|
"Codex harness support is missing from this Egregore checkout.",
|
|
@@ -802,16 +823,22 @@ async function launch(inst, runtimeOverride) {
|
|
|
802
823
|
} else if (runtime === "pi") {
|
|
803
824
|
if (!hasPiCoreSupport(inst.path)) die(piSupportMessage(inst.path));
|
|
804
825
|
}
|
|
826
|
+
// Print the cached greeting card for Claude Code (instant; at most one
|
|
827
|
+
// session stale) and tell the session to skip the in-chat re-render.
|
|
828
|
+
const claudeCardShown =
|
|
829
|
+
runtime === "claude-code" && renderClaudeGreetingCard(inst.path);
|
|
805
830
|
// Replace the current process with the selected assistant in the instance dir.
|
|
806
831
|
// spawn + detached + exit-on-exit replicates exec() in Node.
|
|
832
|
+
const launchEnv = {
|
|
833
|
+
...process.env,
|
|
834
|
+
EGREGORE_RUNTIME: runtime,
|
|
835
|
+
EGREGORE_CODEX_TRUSTED: runtime === "codex" ? "1" : process.env.EGREGORE_CODEX_TRUSTED,
|
|
836
|
+
};
|
|
837
|
+
if (claudeCardShown) launchEnv.EGREGORE_CARD_SHOWN = "1";
|
|
807
838
|
const child = spawn(binary, runtimeLaunchArgs(runtime, inst.path), {
|
|
808
839
|
cwd: inst.path,
|
|
809
840
|
stdio: "inherit",
|
|
810
|
-
env:
|
|
811
|
-
...process.env,
|
|
812
|
-
EGREGORE_RUNTIME: runtime,
|
|
813
|
-
EGREGORE_CODEX_TRUSTED: runtime === "codex" ? "1" : process.env.EGREGORE_CODEX_TRUSTED,
|
|
814
|
-
},
|
|
841
|
+
env: launchEnv,
|
|
815
842
|
});
|
|
816
843
|
child.on("exit", (code, signal) => {
|
|
817
844
|
process.exit(signal ? 1 : (code ?? 0));
|
|
@@ -1608,6 +1635,22 @@ async function cmdConnect(args) {
|
|
|
1608
1635
|
for (const line of backfillSummaryLines(backfillSummary)) {
|
|
1609
1636
|
console.log(` ${DIM}${line}${RESET}`);
|
|
1610
1637
|
}
|
|
1638
|
+
const runtimeRefresh = spawnSync(
|
|
1639
|
+
"npx",
|
|
1640
|
+
["-y", `${PUBLIC_NPX_PACKAGE}@latest`, "--refresh-launcher"],
|
|
1641
|
+
{
|
|
1642
|
+
cwd: inst.path,
|
|
1643
|
+
encoding: "utf-8",
|
|
1644
|
+
stdio: "pipe",
|
|
1645
|
+
timeout: 3 * 60 * 1000,
|
|
1646
|
+
},
|
|
1647
|
+
);
|
|
1648
|
+
if (runtimeRefresh.status === 0) {
|
|
1649
|
+
console.log(` ${GREEN}✓${RESET} Connect features installed`);
|
|
1650
|
+
} else {
|
|
1651
|
+
console.log(` ${YELLOW}!${RESET} Connect features will retry on the next update`);
|
|
1652
|
+
console.log(` ${DIM}npx -y ${PUBLIC_NPX_PACKAGE}@latest --refresh-launcher${RESET}`);
|
|
1653
|
+
}
|
|
1611
1654
|
console.log("");
|
|
1612
1655
|
console.log(` ${GREEN}✓${RESET} ${BOLD}${inst.slug}${RESET} is connected. Local files remain the source of truth.`);
|
|
1613
1656
|
console.log("");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# egregore-launcher-version: 0.4.
|
|
2
|
+
# egregore-launcher-version: 0.4.11
|
|
3
3
|
# egregore — launch an Egregore instance in Claude Code.
|
|
4
4
|
# Reads ~/.egregore/instances.json for the registry of installed egregores.
|
|
5
5
|
#
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
set -u
|
|
24
24
|
|
|
25
|
-
VERSION="0.4.
|
|
25
|
+
VERSION="0.4.11"
|
|
26
26
|
REGISTRY="${HOME}/.egregore/instances.json"
|
|
27
27
|
DEFAULT_FILE="${HOME}/.egregore/default"
|
|
28
28
|
|
|
@@ -97,6 +97,14 @@ launch() {
|
|
|
97
97
|
if [ -d "$target_path/memory" ]; then
|
|
98
98
|
claude_args+=("--add-dir" "$target_path/memory")
|
|
99
99
|
fi
|
|
100
|
+
# Print the cached greeting card (instant; at most one session stale) and
|
|
101
|
+
# tell the session to skip the in-chat re-render. greeting-card.sh exits
|
|
102
|
+
# non-zero silently on a miss (first boot, stale cache, old core) — the
|
|
103
|
+
# session then renders the full greeting itself, exactly as before.
|
|
104
|
+
if [ -f "$target_path/bin/greeting-card.sh" ] \
|
|
105
|
+
&& bash "$target_path/bin/greeting-card.sh" 2>/dev/null; then
|
|
106
|
+
export EGREGORE_CARD_SHOWN=1
|
|
107
|
+
fi
|
|
100
108
|
exec claude "${claude_args[@]}"
|
|
101
109
|
}
|
|
102
110
|
|
package/bin/cli.js
CHANGED
|
@@ -35,6 +35,12 @@ const {
|
|
|
35
35
|
installPiRuntime,
|
|
36
36
|
reportPiRuntimeSummary,
|
|
37
37
|
} = require("../lib/pi-runtime");
|
|
38
|
+
const {
|
|
39
|
+
connectEligibility,
|
|
40
|
+
fetchConnectRuntimePack,
|
|
41
|
+
installConnectRuntime,
|
|
42
|
+
reportConnectRuntimeSummary,
|
|
43
|
+
} = require("../lib/connect-runtime");
|
|
38
44
|
const {
|
|
39
45
|
install,
|
|
40
46
|
ghApi,
|
|
@@ -108,10 +114,17 @@ function assistantLabel(runtime) {
|
|
|
108
114
|
return "Claude Code";
|
|
109
115
|
}
|
|
110
116
|
|
|
111
|
-
function upgradePortableRuntimesForExisting(instances) {
|
|
117
|
+
async function upgradePortableRuntimesForExisting(instances) {
|
|
112
118
|
for (const inst of instances) {
|
|
113
119
|
if (!inst || !inst.path || !fs.existsSync(inst.path)) continue;
|
|
114
120
|
try {
|
|
121
|
+
// Fetch and validate the private overlay before pruning the old public
|
|
122
|
+
// bundle. During the one-time ownership migration, an API outage must
|
|
123
|
+
// leave an existing Connect installation untouched.
|
|
124
|
+
const eligibility = connectEligibility(inst.path);
|
|
125
|
+
const connectPack = eligibility.eligible
|
|
126
|
+
? await fetchConnectRuntimePack(inst.path)
|
|
127
|
+
: null;
|
|
115
128
|
const summary = installCodexRuntime(inst.path);
|
|
116
129
|
const ready = hasCodexRuntimeSupport(inst.path);
|
|
117
130
|
reportCodexRuntimeSummary(summary, ui, {
|
|
@@ -124,6 +137,10 @@ function upgradePortableRuntimesForExisting(instances) {
|
|
|
124
137
|
label: `Pi meta-harness for ${inst.slug || inst.name || path.basename(inst.path)}`,
|
|
125
138
|
includeConflicts: !piReady,
|
|
126
139
|
});
|
|
140
|
+
const connectSummary = await installConnectRuntime(inst.path, { validatedPack: connectPack });
|
|
141
|
+
reportConnectRuntimeSummary(connectSummary, ui, {
|
|
142
|
+
label: `Connect features for ${inst.slug || inst.name || path.basename(inst.path)}`,
|
|
143
|
+
});
|
|
127
144
|
} catch (err) {
|
|
128
145
|
ui.warn(`Could not refresh shell-runtime support for ${inst.path}: ${err.message}`);
|
|
129
146
|
}
|
|
@@ -169,7 +186,7 @@ async function chooseRuntime(args) {
|
|
|
169
186
|
}
|
|
170
187
|
|
|
171
188
|
async function upgradeLauncherFromExisting(instances) {
|
|
172
|
-
upgradePortableRuntimesForExisting(instances);
|
|
189
|
+
await upgradePortableRuntimesForExisting(instances);
|
|
173
190
|
const inst = instances.find((entry) => entry && entry.path && fs.existsSync(entry.path));
|
|
174
191
|
if (!inst) return null;
|
|
175
192
|
try {
|
|
@@ -398,7 +415,7 @@ function showHelp() {
|
|
|
398
415
|
ui.info(" --force Skip the in-repo detection check");
|
|
399
416
|
ui.info(" --no-autolaunch Don't launch the harness at the end (for CI)");
|
|
400
417
|
ui.info(" --no-screens Skip the full-screen welcome/ready bookends");
|
|
401
|
-
ui.info(" --refresh-launcher Refresh
|
|
418
|
+
ui.info(" --refresh-launcher Refresh the Egregore CLI and runtime packs, then exit");
|
|
402
419
|
ui.info(" -h, --help Show this help");
|
|
403
420
|
ui.info("");
|
|
404
421
|
}
|
|
@@ -451,6 +468,7 @@ async function main() {
|
|
|
451
468
|
ui.error("No installed Egregore instance was found. Run create-egregore without --refresh-launcher.");
|
|
452
469
|
process.exit(1);
|
|
453
470
|
}
|
|
471
|
+
await upgradePortableRuntimesForExisting(instances);
|
|
454
472
|
const alias = await installLauncherBinary(instances[0].path, ui);
|
|
455
473
|
if (!alias || !alias.binaryPath) {
|
|
456
474
|
ui.error("Could not refresh the Egregore CLI.");
|
package/lib/codex-runtime.js
CHANGED
|
@@ -151,6 +151,7 @@ function installCodexRuntime(egregoreDir) {
|
|
|
151
151
|
const summary = {
|
|
152
152
|
installed: 0,
|
|
153
153
|
updated: 0,
|
|
154
|
+
removed: 0,
|
|
154
155
|
skipped: 0,
|
|
155
156
|
conflicted: 0,
|
|
156
157
|
conflicts: [],
|
|
@@ -172,8 +173,29 @@ function installCodexRuntime(egregoreDir) {
|
|
|
172
173
|
files: {},
|
|
173
174
|
};
|
|
174
175
|
const previousFiles = previous.files || {};
|
|
176
|
+
const currentBundleFiles = bundleFiles();
|
|
177
|
+
const currentBundleSet = new Set(currentBundleFiles);
|
|
175
178
|
|
|
176
|
-
|
|
179
|
+
// Remove installer-owned files that moved to queued, Connect, or internal.
|
|
180
|
+
// Preserve anything the user modified and keep its ownership record.
|
|
181
|
+
for (const [rel, record] of Object.entries(previousFiles)) {
|
|
182
|
+
if (currentBundleSet.has(rel)) continue;
|
|
183
|
+
const dest = path.join(egregoreDir, rel);
|
|
184
|
+
if (!pathExistsOrSymlink(dest)) continue;
|
|
185
|
+
let stat;
|
|
186
|
+
try { stat = fs.lstatSync(dest); } catch { continue; }
|
|
187
|
+
if (stat.isFile() && hashBuffer(fs.readFileSync(dest)) === record.hash) {
|
|
188
|
+
fs.unlinkSync(dest);
|
|
189
|
+
try { fs.rmdirSync(path.dirname(dest)); } catch {}
|
|
190
|
+
summary.removed += 1;
|
|
191
|
+
} else {
|
|
192
|
+
summary.conflicted += 1;
|
|
193
|
+
summary.conflicts.push(rel);
|
|
194
|
+
next.files[rel] = { hash: record.hash };
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
for (const rel of currentBundleFiles) {
|
|
177
199
|
const src = path.join(BUNDLE_DIR, rel);
|
|
178
200
|
const dest = path.join(egregoreDir, rel);
|
|
179
201
|
const sourceBuffer = fs.readFileSync(src);
|
|
@@ -240,10 +262,10 @@ function reportCodexRuntimeSummary(summary, ui, opts = {}) {
|
|
|
240
262
|
if (!summary || !ui) return;
|
|
241
263
|
const label = opts.label || "Codex runtime";
|
|
242
264
|
const includeConflicts = opts.includeConflicts !== false;
|
|
243
|
-
const changed = summary.installed + summary.updated;
|
|
265
|
+
const changed = summary.installed + summary.updated + (summary.removed || 0);
|
|
244
266
|
if (changed > 0) {
|
|
245
267
|
ui.success(
|
|
246
|
-
`${label} ready (${summary.installed} installed, ${summary.updated} updated, ${summary.skipped} unchanged)`,
|
|
268
|
+
`${label} ready (${summary.installed} installed, ${summary.updated} updated, ${summary.removed || 0} removed, ${summary.skipped} unchanged)`,
|
|
247
269
|
);
|
|
248
270
|
}
|
|
249
271
|
if (includeConflicts && summary.conflicted > 0) {
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const crypto = require("node:crypto");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const http = require("node:http");
|
|
6
|
+
const https = require("node:https");
|
|
7
|
+
const path = require("node:path");
|
|
8
|
+
const { URL } = require("node:url");
|
|
9
|
+
|
|
10
|
+
const PACKAGE = require("../package.json");
|
|
11
|
+
const LOCAL_MANIFEST = path.join(".egregore", "connect-runtime-manifest.json");
|
|
12
|
+
const PACK_PATH = "/api/runtime/connect-pack";
|
|
13
|
+
const MAX_PACK_BYTES = 12 * 1024 * 1024;
|
|
14
|
+
const MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
15
|
+
const MAX_FILES = 500;
|
|
16
|
+
|
|
17
|
+
function hashBuffer(buffer) {
|
|
18
|
+
return crypto.createHash("sha256").update(buffer).digest("hex");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function readJson(file, fallback) {
|
|
22
|
+
try { return JSON.parse(fs.readFileSync(file, "utf8")); }
|
|
23
|
+
catch { return fallback; }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function pathExists(file) {
|
|
27
|
+
try { fs.lstatSync(file); return true; }
|
|
28
|
+
catch { return false; }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function gitDirFor(egregoreDir) {
|
|
32
|
+
const gitPath = path.join(egregoreDir, ".git");
|
|
33
|
+
try {
|
|
34
|
+
const stat = fs.lstatSync(gitPath);
|
|
35
|
+
if (stat.isDirectory()) return gitPath;
|
|
36
|
+
if (stat.isFile()) {
|
|
37
|
+
const match = fs.readFileSync(gitPath, "utf8").trim().match(/^gitdir:\s*(.+)$/);
|
|
38
|
+
if (match) return path.isAbsolute(match[1]) ? match[1] : path.resolve(egregoreDir, match[1]);
|
|
39
|
+
}
|
|
40
|
+
} catch {}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function installManifestPath(egregoreDir) {
|
|
45
|
+
const gitDir = gitDirFor(egregoreDir);
|
|
46
|
+
return gitDir
|
|
47
|
+
? path.join(gitDir, "info", "egregore-connect-runtime.json")
|
|
48
|
+
: path.join(egregoreDir, LOCAL_MANIFEST);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function readApiKey(egregoreDir) {
|
|
52
|
+
try {
|
|
53
|
+
const env = fs.readFileSync(path.join(egregoreDir, ".env"), "utf8");
|
|
54
|
+
const match = env.match(/^EGREGORE_API_KEY=(.*)$/m);
|
|
55
|
+
return match && match[1].trim() ? match[1].trim() : "";
|
|
56
|
+
} catch { return ""; }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function connectCredentials(egregoreDir) {
|
|
60
|
+
const config = readJson(path.join(egregoreDir, "egregore.json"), null);
|
|
61
|
+
if (!config || config.mode !== "connected" || !config.api_url) {
|
|
62
|
+
return { eligible: false, reason: "not-connected" };
|
|
63
|
+
}
|
|
64
|
+
const apiKey = readApiKey(egregoreDir);
|
|
65
|
+
if (!apiKey) return { eligible: false, reason: "missing-api-key" };
|
|
66
|
+
return {
|
|
67
|
+
eligible: true,
|
|
68
|
+
reason: "connected",
|
|
69
|
+
apiUrl: String(config.api_url).replace(/\/$/, ""),
|
|
70
|
+
apiKey,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function connectEligibility(egregoreDir) {
|
|
75
|
+
const { eligible, reason } = connectCredentials(egregoreDir);
|
|
76
|
+
return { eligible, reason };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function validateConnectPack(pack) {
|
|
80
|
+
if (!pack || typeof pack !== "object" || Array.isArray(pack)) {
|
|
81
|
+
throw new Error("Connect API returned an invalid runtime pack");
|
|
82
|
+
}
|
|
83
|
+
if (pack.schemaVersion !== 1 || pack.availability !== "connect") {
|
|
84
|
+
throw new Error(`Unsupported Connect runtime pack schema: ${pack.schemaVersion}`);
|
|
85
|
+
}
|
|
86
|
+
if (!Array.isArray(pack.skills) || pack.skills.length === 0) {
|
|
87
|
+
throw new Error("Connect runtime pack has no skill inventory");
|
|
88
|
+
}
|
|
89
|
+
const skills = [...new Set(pack.skills)];
|
|
90
|
+
if (skills.length !== pack.skills.length || skills.some((name) => !/^[a-z0-9-]+$/.test(name))) {
|
|
91
|
+
throw new Error("Connect runtime pack has an invalid skill inventory");
|
|
92
|
+
}
|
|
93
|
+
if (!Array.isArray(pack.files) || pack.files.length === 0 || pack.files.length > MAX_FILES) {
|
|
94
|
+
throw new Error("Connect runtime pack has an invalid file inventory");
|
|
95
|
+
}
|
|
96
|
+
if (!/^[a-f0-9]{64}$/.test(pack.packVersion || "")) {
|
|
97
|
+
throw new Error("Connect runtime pack has an invalid version");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const skillSet = new Set(skills);
|
|
101
|
+
const seen = new Set();
|
|
102
|
+
let totalBytes = 0;
|
|
103
|
+
const files = pack.files.map((entry) => {
|
|
104
|
+
if (!entry || typeof entry !== "object" || typeof entry.path !== "string") {
|
|
105
|
+
throw new Error("Connect runtime pack contains an invalid file record");
|
|
106
|
+
}
|
|
107
|
+
const rel = entry.path;
|
|
108
|
+
const match = rel.match(/^\.(claude|codex)\/skills\/([^/]+)\/(.+)$/);
|
|
109
|
+
if (!match || !skillSet.has(match[2]) || rel.includes("\\") || path.posix.normalize(rel) !== rel || seen.has(rel)) {
|
|
110
|
+
throw new Error(`Connect runtime pack contains an unsafe path: ${rel}`);
|
|
111
|
+
}
|
|
112
|
+
seen.add(rel);
|
|
113
|
+
if (!Number.isInteger(entry.mode) || entry.mode < 0 || entry.mode > 0o777) {
|
|
114
|
+
throw new Error(`Connect runtime pack contains an invalid mode: ${rel}`);
|
|
115
|
+
}
|
|
116
|
+
if (typeof entry.content !== "string" || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(entry.content)) {
|
|
117
|
+
throw new Error(`Connect runtime pack contains invalid content: ${rel}`);
|
|
118
|
+
}
|
|
119
|
+
const buffer = Buffer.from(entry.content, "base64");
|
|
120
|
+
if (buffer.length > MAX_FILE_BYTES || buffer.toString("base64") !== entry.content) {
|
|
121
|
+
throw new Error(`Connect runtime pack file exceeds safety limits: ${rel}`);
|
|
122
|
+
}
|
|
123
|
+
totalBytes += buffer.length;
|
|
124
|
+
if (totalBytes > MAX_PACK_BYTES) throw new Error("Connect runtime pack exceeds safety limits");
|
|
125
|
+
if (!/^[a-f0-9]{64}$/.test(entry.sha256 || "") || hashBuffer(buffer) !== entry.sha256) {
|
|
126
|
+
throw new Error(`Connect runtime pack failed integrity validation: ${rel}`);
|
|
127
|
+
}
|
|
128
|
+
return { path: rel, mode: entry.mode, sha256: entry.sha256, buffer };
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
for (const skill of skills) {
|
|
132
|
+
for (const runtime of ["claude", "codex"]) {
|
|
133
|
+
if (!seen.has(`.${runtime}/skills/${skill}/SKILL.md`)) {
|
|
134
|
+
throw new Error(`Connect runtime pack is incomplete for ${skill}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const unsigned = {
|
|
139
|
+
schemaVersion: pack.schemaVersion,
|
|
140
|
+
availability: pack.availability,
|
|
141
|
+
skills: pack.skills,
|
|
142
|
+
files: pack.files,
|
|
143
|
+
};
|
|
144
|
+
if (hashBuffer(Buffer.from(JSON.stringify(unsigned))) !== pack.packVersion) {
|
|
145
|
+
throw new Error("Connect runtime pack version does not match its contents");
|
|
146
|
+
}
|
|
147
|
+
return { schemaVersion: pack.schemaVersion, availability: pack.availability, packVersion: pack.packVersion, skills, files };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function requestConnectPack(apiUrl, apiKey, timeout = 30000) {
|
|
151
|
+
return new Promise((resolve, reject) => {
|
|
152
|
+
let parsed;
|
|
153
|
+
try { parsed = new URL(`${apiUrl}${PACK_PATH}`); }
|
|
154
|
+
catch { reject(new Error("Connected instance has an invalid API URL")); return; }
|
|
155
|
+
const transport = parsed.protocol === "http:" ? http : https;
|
|
156
|
+
const request = transport.request(parsed, {
|
|
157
|
+
method: "GET",
|
|
158
|
+
headers: {
|
|
159
|
+
Accept: "application/json",
|
|
160
|
+
Authorization: `Bearer ${apiKey}`,
|
|
161
|
+
"User-Agent": `${PACKAGE.name}/${PACKAGE.version}`,
|
|
162
|
+
},
|
|
163
|
+
timeout,
|
|
164
|
+
}, (response) => {
|
|
165
|
+
const chunks = [];
|
|
166
|
+
let size = 0;
|
|
167
|
+
response.on("error", reject);
|
|
168
|
+
response.on("data", (chunk) => {
|
|
169
|
+
size += chunk.length;
|
|
170
|
+
if (size > MAX_PACK_BYTES * 2) {
|
|
171
|
+
response.destroy(new Error("Connect runtime response exceeds safety limits"));
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
chunks.push(chunk);
|
|
175
|
+
});
|
|
176
|
+
response.on("end", () => {
|
|
177
|
+
const body = Buffer.concat(chunks).toString("utf8");
|
|
178
|
+
if (response.statusCode !== 200) {
|
|
179
|
+
reject(new Error(`Connect runtime download failed (HTTP ${response.statusCode})`));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
try { resolve(JSON.parse(body)); }
|
|
183
|
+
catch { reject(new Error("Connect API returned an invalid runtime response")); }
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
request.on("error", reject);
|
|
187
|
+
request.on("timeout", () => request.destroy(new Error("Connect runtime download timed out")));
|
|
188
|
+
request.end();
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async function fetchConnectRuntimePack(egregoreDir, opts = {}) {
|
|
193
|
+
const credentials = connectCredentials(egregoreDir);
|
|
194
|
+
if (!credentials.eligible) return null;
|
|
195
|
+
const raw = opts.pack || await (opts.requestPack || requestConnectPack)(
|
|
196
|
+
credentials.apiUrl, credentials.apiKey, opts.timeout,
|
|
197
|
+
);
|
|
198
|
+
return validateConnectPack(raw);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function copyPackFile(file, dest) {
|
|
202
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
203
|
+
fs.writeFileSync(dest, file.buffer, { mode: file.mode });
|
|
204
|
+
try { fs.chmodSync(dest, file.mode); } catch {}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function recordGitExcludes(egregoreDir, skills) {
|
|
208
|
+
const gitDir = gitDirFor(egregoreDir);
|
|
209
|
+
if (!gitDir) return;
|
|
210
|
+
const excludePath = path.join(gitDir, "info", "exclude");
|
|
211
|
+
fs.mkdirSync(path.dirname(excludePath), { recursive: true });
|
|
212
|
+
const current = fs.existsSync(excludePath) ? fs.readFileSync(excludePath, "utf8") : "";
|
|
213
|
+
const wanted = [];
|
|
214
|
+
for (const skill of skills) wanted.push(`/.claude/skills/${skill}/`, `/.codex/skills/${skill}/`);
|
|
215
|
+
const lines = current.split(/\r?\n/);
|
|
216
|
+
const missing = wanted.filter((line) => !lines.includes(line));
|
|
217
|
+
if (!missing.length) return;
|
|
218
|
+
const prefix = current && !current.endsWith("\n") ? "\n" : "";
|
|
219
|
+
const header = current.includes("# Egregore Connect feature pack")
|
|
220
|
+
? ""
|
|
221
|
+
: "# Egregore Connect feature pack (authenticated local overlay)\n";
|
|
222
|
+
fs.appendFileSync(excludePath, `${prefix}${header}${missing.join("\n")}\n`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async function installConnectRuntime(egregoreDir, opts = {}) {
|
|
226
|
+
const eligibility = connectEligibility(egregoreDir);
|
|
227
|
+
const summary = {
|
|
228
|
+
...eligibility, installed: 0, updated: 0, removed: 0, skipped: 0,
|
|
229
|
+
conflicted: 0, conflicts: [], files: [], bundleSkills: [], bundleSkillCount: 0, packVersion: null,
|
|
230
|
+
};
|
|
231
|
+
if (!eligibility.eligible) return summary;
|
|
232
|
+
|
|
233
|
+
// Validate the complete response before touching the checkout. A failed
|
|
234
|
+
// refresh leaves the last known-good Connect overlay intact.
|
|
235
|
+
const pack = opts.validatedPack || await fetchConnectRuntimePack(egregoreDir, opts);
|
|
236
|
+
summary.bundleSkills = pack.skills;
|
|
237
|
+
summary.bundleSkillCount = pack.skills.length;
|
|
238
|
+
summary.packVersion = pack.packVersion;
|
|
239
|
+
|
|
240
|
+
const manifestPath = installManifestPath(egregoreDir);
|
|
241
|
+
const previous = readJson(manifestPath, { files: {} });
|
|
242
|
+
const previousFiles = previous.files || {};
|
|
243
|
+
const currentSet = new Set(pack.files.map((file) => file.path));
|
|
244
|
+
const next = {
|
|
245
|
+
package: PACKAGE.name, version: PACKAGE.version, schemaVersion: pack.schemaVersion,
|
|
246
|
+
packVersion: pack.packVersion, installedAt: new Date().toISOString(), skills: pack.skills, files: {},
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
for (const [rel, record] of Object.entries(previousFiles)) {
|
|
250
|
+
if (currentSet.has(rel)) continue;
|
|
251
|
+
const dest = path.join(egregoreDir, rel);
|
|
252
|
+
if (!pathExists(dest)) continue;
|
|
253
|
+
let stat;
|
|
254
|
+
try { stat = fs.lstatSync(dest); } catch { continue; }
|
|
255
|
+
if (stat.isFile() && hashBuffer(fs.readFileSync(dest)) === record.hash) {
|
|
256
|
+
fs.unlinkSync(dest);
|
|
257
|
+
try { fs.rmdirSync(path.dirname(dest)); } catch {}
|
|
258
|
+
summary.removed += 1;
|
|
259
|
+
} else {
|
|
260
|
+
summary.conflicted += 1;
|
|
261
|
+
summary.conflicts.push(rel);
|
|
262
|
+
next.files[rel] = { hash: record.hash };
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
for (const file of pack.files) {
|
|
267
|
+
const rel = file.path;
|
|
268
|
+
const dest = path.join(egregoreDir, rel);
|
|
269
|
+
const previousHash = previousFiles[rel] && previousFiles[rel].hash;
|
|
270
|
+
const record = () => {
|
|
271
|
+
next.files[rel] = { hash: file.sha256 };
|
|
272
|
+
summary.files.push(rel);
|
|
273
|
+
};
|
|
274
|
+
if (!pathExists(dest)) {
|
|
275
|
+
copyPackFile(file, dest);
|
|
276
|
+
summary.installed += 1;
|
|
277
|
+
record();
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
let stat;
|
|
281
|
+
try { stat = fs.lstatSync(dest); } catch { stat = null; }
|
|
282
|
+
if (!stat || !stat.isFile()) {
|
|
283
|
+
summary.conflicted += 1;
|
|
284
|
+
summary.conflicts.push(rel);
|
|
285
|
+
if (previousHash) next.files[rel] = { hash: previousHash };
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const currentHash = hashBuffer(fs.readFileSync(dest));
|
|
289
|
+
if (currentHash === file.sha256) {
|
|
290
|
+
try { fs.chmodSync(dest, file.mode); } catch {}
|
|
291
|
+
summary.skipped += 1;
|
|
292
|
+
record();
|
|
293
|
+
} else if (previousHash && currentHash === previousHash) {
|
|
294
|
+
copyPackFile(file, dest);
|
|
295
|
+
summary.updated += 1;
|
|
296
|
+
record();
|
|
297
|
+
} else {
|
|
298
|
+
summary.conflicted += 1;
|
|
299
|
+
summary.conflicts.push(rel);
|
|
300
|
+
if (previousHash) next.files[rel] = { hash: previousHash };
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
304
|
+
fs.writeFileSync(manifestPath, `${JSON.stringify(next, null, 2)}\n`);
|
|
305
|
+
recordGitExcludes(egregoreDir, pack.skills);
|
|
306
|
+
return summary;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function reportConnectRuntimeSummary(summary, ui, opts = {}) {
|
|
310
|
+
if (!summary || !ui || !summary.eligible) return;
|
|
311
|
+
const label = opts.label || "Connect features";
|
|
312
|
+
const changed = summary.installed + summary.updated + summary.removed;
|
|
313
|
+
if (changed > 0) {
|
|
314
|
+
ui.success(`${label} ready (${summary.installed} installed, ${summary.updated} updated, ${summary.removed} removed)`);
|
|
315
|
+
}
|
|
316
|
+
if (summary.conflicted > 0) {
|
|
317
|
+
ui.warn(`${label}: kept ${summary.conflicted} locally modified file${summary.conflicted === 1 ? "" : "s"}.`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
module.exports = {
|
|
322
|
+
connectEligibility,
|
|
323
|
+
fetchConnectRuntimePack,
|
|
324
|
+
installConnectRuntime,
|
|
325
|
+
installManifestPath,
|
|
326
|
+
reportConnectRuntimeSummary,
|
|
327
|
+
requestConnectPack,
|
|
328
|
+
validateConnectPack,
|
|
329
|
+
};
|
package/lib/pi-runtime.js
CHANGED
|
@@ -101,6 +101,7 @@ function installPiRuntime(egregoreDir) {
|
|
|
101
101
|
const summary = {
|
|
102
102
|
installed: 0,
|
|
103
103
|
updated: 0,
|
|
104
|
+
removed: 0,
|
|
104
105
|
skipped: 0,
|
|
105
106
|
conflicted: 0,
|
|
106
107
|
conflicts: [],
|
|
@@ -108,8 +109,27 @@ function installPiRuntime(egregoreDir) {
|
|
|
108
109
|
bundleSkills: bundleManifest().skills || [],
|
|
109
110
|
bundleSkillCount: bundleManifest().skillCount || 0,
|
|
110
111
|
};
|
|
112
|
+
const currentBundleFiles = bundleFiles();
|
|
113
|
+
const currentBundleSet = new Set(currentBundleFiles);
|
|
111
114
|
|
|
112
|
-
for (const rel of
|
|
115
|
+
for (const [rel, record] of Object.entries(previousFiles)) {
|
|
116
|
+
if (currentBundleSet.has(rel)) continue;
|
|
117
|
+
const dest = path.join(egregoreDir, rel);
|
|
118
|
+
if (!pathExists(dest)) continue;
|
|
119
|
+
let stat;
|
|
120
|
+
try { stat = fs.lstatSync(dest); } catch { continue; }
|
|
121
|
+
if (stat.isFile() && hashBuffer(fs.readFileSync(dest)) === record.hash) {
|
|
122
|
+
fs.unlinkSync(dest);
|
|
123
|
+
try { fs.rmdirSync(path.dirname(dest)); } catch {}
|
|
124
|
+
summary.removed += 1;
|
|
125
|
+
} else {
|
|
126
|
+
summary.conflicted += 1;
|
|
127
|
+
summary.conflicts.push(rel);
|
|
128
|
+
next.files[rel] = { hash: record.hash };
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
for (const rel of currentBundleFiles) {
|
|
113
133
|
const src = path.join(BUNDLE_DIR, rel);
|
|
114
134
|
const dest = path.join(egregoreDir, rel);
|
|
115
135
|
const sourceHash = hashBuffer(fs.readFileSync(src));
|
|
@@ -163,9 +183,9 @@ function hasPiRuntimeSupport(egregoreDir) {
|
|
|
163
183
|
function reportPiRuntimeSummary(summary, ui, opts = {}) {
|
|
164
184
|
if (!summary || !ui) return;
|
|
165
185
|
const label = opts.label || "Pi meta-harness";
|
|
166
|
-
const changed = summary.installed + summary.updated;
|
|
186
|
+
const changed = summary.installed + summary.updated + (summary.removed || 0);
|
|
167
187
|
if (changed > 0) {
|
|
168
|
-
ui.success(`${label} ready (${summary.installed} installed, ${summary.updated} updated, ${summary.skipped} unchanged)`);
|
|
188
|
+
ui.success(`${label} ready (${summary.installed} installed, ${summary.updated} updated, ${summary.removed || 0} removed, ${summary.skipped} unchanged)`);
|
|
169
189
|
}
|
|
170
190
|
if (opts.includeConflicts !== false && summary.conflicted > 0) {
|
|
171
191
|
const count = summary.conflicted;
|
package/lib/setup.js
CHANGED
|
@@ -17,6 +17,10 @@ const {
|
|
|
17
17
|
installPiRuntime,
|
|
18
18
|
reportPiRuntimeSummary,
|
|
19
19
|
} = require("./pi-runtime");
|
|
20
|
+
const {
|
|
21
|
+
installConnectRuntime,
|
|
22
|
+
reportConnectRuntimeSummary,
|
|
23
|
+
} = require("./connect-runtime");
|
|
20
24
|
const { commandExists } = require("./path-lookup");
|
|
21
25
|
|
|
22
26
|
const https = require("node:https");
|
|
@@ -522,6 +526,15 @@ async function install(data, ui, targetDir, opts = {}) {
|
|
|
522
526
|
reportPiRuntimeSummary(piRuntime, ui);
|
|
523
527
|
}
|
|
524
528
|
|
|
529
|
+
// Connect is an authenticated additive overlay on the exact OSS runtime.
|
|
530
|
+
// Local instances return immediately; network failure never breaks setup.
|
|
531
|
+
try {
|
|
532
|
+
const connectRuntime = await installConnectRuntime(egregoreDir);
|
|
533
|
+
reportConnectRuntimeSummary(connectRuntime, ui);
|
|
534
|
+
} catch (err) {
|
|
535
|
+
ui.warn(`Connect features were not refreshed: ${err.message}`);
|
|
536
|
+
}
|
|
537
|
+
|
|
525
538
|
// Reconcile the installer-captured identity through the same portable writer
|
|
526
539
|
// used by /me and onboarding. Failure is recoverable: the state + person
|
|
527
540
|
// profile already exist and the next session retries `bin/person.sh sync`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-egregore",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.24",
|
|
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": {
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"node": ">=18"
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build:runtime": "node scripts/build-runtime-bundle.mjs && node scripts/build-pi-runtime-bundle.mjs",
|
|
13
|
+
"build:runtime": "node ../../bin/capability-distribution.mjs generate-skill-view --root ../.. && node scripts/build-runtime-bundle.mjs && node scripts/build-pi-runtime-bundle.mjs && node ../../api/scripts/build-connect-runtime-pack.mjs",
|
|
14
14
|
"build:pi-runtime": "node scripts/build-pi-runtime-bundle.mjs",
|
|
15
|
-
"test": "node scripts/build-runtime-bundle.mjs --check && node scripts/build-pi-runtime-bundle.mjs --check && node --test test/context.test.js test/path-lookup.test.js test/nixos-portability.test.js test/parse-join-target.test.js test/skip-repos.test.js test/install-origin-guard.test.js test/onboarding-shortcircuit.test.js test/welcome-screen.test.js test/runtime-selection.test.js test/command-generation.test.js test/auth-gh.test.js test/gauntlet-fixes.test.js test/codex-runtime.test.js test/pi-runtime.test.js test/pi-product-workflows.test.js test/installer-runtime-source.test.js test/scroll-repro.test.js test/launcher-refocus-redraw.test.js test/multiselect-remote-search.test.js test/back-navigation.test.js test/manifest-form.test.js test/launcher-delete.test.js test/launcher-connect.test.js test/launcher-connected-status.test.js test/launcher-permissions.test.js test/launcher-update.test.js test/connected-config.test.js",
|
|
15
|
+
"test": "node ../../bin/capability-distribution.mjs validate --root ../.. && node scripts/build-runtime-bundle.mjs --check && node scripts/build-pi-runtime-bundle.mjs --check && node ../../api/scripts/build-connect-runtime-pack.mjs --check && node --test test/capability-distribution.test.js test/connect-runtime.test.js test/context.test.js test/path-lookup.test.js test/nixos-portability.test.js test/parse-join-target.test.js test/skip-repos.test.js test/install-origin-guard.test.js test/onboarding-shortcircuit.test.js test/welcome-screen.test.js test/runtime-selection.test.js test/command-generation.test.js test/auth-gh.test.js test/gauntlet-fixes.test.js test/codex-runtime.test.js test/pi-runtime.test.js test/pi-product-workflows.test.js test/installer-runtime-source.test.js test/scroll-repro.test.js test/launcher-refocus-redraw.test.js test/multiselect-remote-search.test.js test/back-navigation.test.js test/manifest-form.test.js test/launcher-delete.test.js test/launcher-connect.test.js test/launcher-connected-status.test.js test/launcher-permissions.test.js test/launcher-update.test.js test/connected-config.test.js",
|
|
16
16
|
"test:e2e": "node --test test/e2e-local.test.js",
|
|
17
17
|
"test:all": "node scripts/build-runtime-bundle.mjs --check && node scripts/build-pi-runtime-bundle.mjs --check && node --test test/"
|
|
18
18
|
},
|