@cotal-ai/cli 0.11.0 → 0.11.2
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/dist/command.d.ts.map +1 -1
- package/dist/command.js +14 -3
- package/dist/command.js.map +1 -1
- package/dist/commands/clean.d.ts +40 -0
- package/dist/commands/clean.d.ts.map +1 -0
- package/dist/commands/clean.js +138 -0
- package/dist/commands/clean.js.map +1 -0
- package/dist/commands/down.d.ts +15 -5
- package/dist/commands/down.d.ts.map +1 -1
- package/dist/commands/down.js +201 -66
- package/dist/commands/down.js.map +1 -1
- package/dist/commands/endpoints.d.ts +5 -0
- package/dist/commands/endpoints.d.ts.map +1 -0
- package/dist/commands/endpoints.js +42 -0
- package/dist/commands/endpoints.js.map +1 -0
- package/dist/commands/ext.d.ts +4 -4
- package/dist/commands/ext.d.ts.map +1 -1
- package/dist/commands/ext.js +327 -90
- package/dist/commands/ext.js.map +1 -1
- package/dist/commands/history.d.ts +3 -2
- package/dist/commands/history.d.ts.map +1 -1
- package/dist/commands/history.js +6 -21
- package/dist/commands/history.js.map +1 -1
- package/dist/commands/setup.js +2 -2
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/spawn-manifest.d.ts.map +1 -1
- package/dist/commands/spawn-manifest.js +23 -10
- package/dist/commands/spawn-manifest.js.map +1 -1
- package/dist/commands/spawn.d.ts +1 -1
- package/dist/commands/spawn.d.ts.map +1 -1
- package/dist/commands/spawn.js +3 -2
- package/dist/commands/spawn.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +25 -26
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/up.d.ts.map +1 -1
- package/dist/commands/up.js +7 -5
- package/dist/commands/up.js.map +1 -1
- package/dist/ext-loader.d.ts +12 -1
- package/dist/ext-loader.d.ts.map +1 -1
- package/dist/ext-loader.js +92 -8
- package/dist/ext-loader.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +70 -7
- package/dist/index.js.map +1 -1
- package/dist/lib/control.d.ts.map +1 -1
- package/dist/lib/control.js +8 -2
- package/dist/lib/control.js.map +1 -1
- package/dist/lib/manifest/model.d.ts +1 -1
- package/dist/lib/manifest/model.d.ts.map +1 -1
- package/dist/lib/manifest/schema.d.ts +1 -5
- package/dist/lib/manifest/schema.d.ts.map +1 -1
- package/dist/lib/manifest/schema.js +2 -1
- package/dist/lib/manifest/schema.js.map +1 -1
- package/dist/ui.d.ts +5 -0
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +12 -0
- package/dist/ui.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"down.js","sourceRoot":"","sources":["../../src/commands/down.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"down.js","sourceRoot":"","sources":["../../src/commands/down.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ParsedArgs, Presence } from "@cotal-ai/core";
|
|
2
|
+
/** List the mesh presence roster, including infrastructure endpoints such as the manager. */
|
|
3
|
+
export declare function endpoints(args: ParsedArgs): Promise<void>;
|
|
4
|
+
export declare function printEndpoints(roster: Presence[], space: string): void;
|
|
5
|
+
//# sourceMappingURL=endpoints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoints.d.ts","sourceRoot":"","sources":["../../src/commands/endpoints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAI3D,6FAA6F;AAC7F,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ/D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CA4BtE"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { openTransient } from "../lib/transient.js";
|
|
2
|
+
import { c, statusBadge } from "../ui.js";
|
|
3
|
+
/** List the mesh presence roster, including infrastructure endpoints such as the manager. */
|
|
4
|
+
export async function endpoints(args) {
|
|
5
|
+
const { ep, space } = await openTransient(args.values, "endpoints");
|
|
6
|
+
try {
|
|
7
|
+
await ep.waitForPresenceSnapshot();
|
|
8
|
+
printEndpoints(ep.getRoster(), space);
|
|
9
|
+
}
|
|
10
|
+
finally {
|
|
11
|
+
await ep.stop();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function printEndpoints(roster, space) {
|
|
15
|
+
if (!roster.length) {
|
|
16
|
+
console.log(c.dim(`(no endpoints present in "${space}")`));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const counts = new Map();
|
|
20
|
+
for (const presence of roster) {
|
|
21
|
+
const name = presence.card.name.toLowerCase();
|
|
22
|
+
counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
23
|
+
}
|
|
24
|
+
const rows = roster
|
|
25
|
+
.map((presence) => {
|
|
26
|
+
const role = presence.card.role ? `/${presence.card.role}` : "";
|
|
27
|
+
const duplicate = (counts.get(presence.card.name.toLowerCase()) ?? 0) > 1;
|
|
28
|
+
return {
|
|
29
|
+
presence,
|
|
30
|
+
label: `${presence.card.name}${role}${duplicate ? ` [${presence.card.id}]` : ""}`,
|
|
31
|
+
kind: presence.card.kind ?? "endpoint",
|
|
32
|
+
};
|
|
33
|
+
})
|
|
34
|
+
.sort((a, b) => a.label.localeCompare(b.label));
|
|
35
|
+
const labelWidth = Math.max(...rows.map((row) => row.label.length));
|
|
36
|
+
const kindWidth = Math.max(...rows.map((row) => row.kind.length));
|
|
37
|
+
for (const row of rows) {
|
|
38
|
+
const activity = row.presence.activity ? ` ${c.dim(row.presence.activity)}` : "";
|
|
39
|
+
console.log(`${c.bold(row.label.padEnd(labelWidth))} ${c.dim(row.kind.padEnd(kindWidth))} ${statusBadge(row.presence.status)}${activity}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=endpoints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoints.js","sourceRoot":"","sources":["../../src/commands/endpoints.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/ext.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { type ParsedArgs } from "@cotal-ai/core";
|
|
2
2
|
/**
|
|
3
|
-
* `cotal ext` — operator-installed
|
|
3
|
+
* `cotal ext` — operator-installed extensions. `add` installs an npm package into the
|
|
4
4
|
* cotal-owned prefix (never the user's project), imports it ONCE so it self-registers into the
|
|
5
|
-
* live `Registry`, verifies the registration actually landed, and caches
|
|
6
|
-
*
|
|
7
|
-
* dispatch imports the package lazily
|
|
5
|
+
* live `Registry`, verifies the registration actually landed, and caches every contributed key
|
|
6
|
+
* plus command display metadata. From then on, help and <TAB> read the cache (no import), and
|
|
7
|
+
* dispatch/provider resolution imports the package lazily with live objects.
|
|
8
8
|
*
|
|
9
9
|
* Add-time guarantees (design-review conditions — each converts a silent failure into a loud one):
|
|
10
10
|
* - shared `@cotal-ai/*` packages must be PEER dependencies of the extension; each is linked to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ext.d.ts","sourceRoot":"","sources":["../../src/commands/ext.ts"],"names":[],"mappings":"AAIA,OAAO,EAA0B,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"ext.d.ts","sourceRoot":"","sources":["../../src/commands/ext.ts"],"names":[],"mappings":"AAIA,OAAO,EAA0B,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AA0BzE;;;;;;;;;;;;;;GAcG;AAEH,wBAAsB,GAAG,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAOzD"}
|
package/dist/commands/ext.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
|
-
import { existsSync, mkdirSync, readFileSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { closeSync, cpSync, existsSync, mkdirSync, mkdtempSync, openSync, readFileSync, renameSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
5
|
import { registry } from "@cotal-ai/core";
|
|
6
|
-
import { cacheCommand, extensionPackageDir, extensionsDir, extensionsManifestPath, installedExtensionVersion, loadExtensionsManifest, provenance, saveExtensionsManifest, } from "@cotal-ai/workspace";
|
|
6
|
+
import { cacheCommand, cacheExtension, cacheLocalProcess, extensionPackageDir, extensionLocalProcesses, extensionMutationLockPath, extensionMutationLockState, extensionProvides, extensionsDir, extensionsManifestPath, loadMeshes, localProcessPath, installedExtensionVersion, loadExtensionsManifest, provenance, saveExtensionsManifest, } from "@cotal-ai/workspace";
|
|
7
7
|
import { c } from "../ui.js";
|
|
8
|
+
import { cotalRoot } from "../lib/paths.js";
|
|
9
|
+
import { resolveSpace } from "../lib/status.js";
|
|
8
10
|
/**
|
|
9
|
-
* `cotal ext` — operator-installed
|
|
11
|
+
* `cotal ext` — operator-installed extensions. `add` installs an npm package into the
|
|
10
12
|
* cotal-owned prefix (never the user's project), imports it ONCE so it self-registers into the
|
|
11
|
-
* live `Registry`, verifies the registration actually landed, and caches
|
|
12
|
-
*
|
|
13
|
-
* dispatch imports the package lazily
|
|
13
|
+
* live `Registry`, verifies the registration actually landed, and caches every contributed key
|
|
14
|
+
* plus command display metadata. From then on, help and <TAB> read the cache (no import), and
|
|
15
|
+
* dispatch/provider resolution imports the package lazily with live objects.
|
|
14
16
|
*
|
|
15
17
|
* Add-time guarantees (design-review conditions — each converts a silent failure into a loud one):
|
|
16
18
|
* - shared `@cotal-ai/*` packages must be PEER dependencies of the extension; each is linked to
|
|
@@ -72,6 +74,77 @@ async function importExtension(pkg) {
|
|
|
72
74
|
entry = meta.exports;
|
|
73
75
|
await import(pathToFileURL(join(dir, entry)).href);
|
|
74
76
|
}
|
|
77
|
+
/** Rebuild each installed package's private links after npm mutates the shared prefix. Keeping the
|
|
78
|
+
* links inside the owning package prevents a later sibling add/remove from pruning its peers. */
|
|
79
|
+
function linkExtensionPeers(packages, operationPkg) {
|
|
80
|
+
for (const owner of packages) {
|
|
81
|
+
let meta;
|
|
82
|
+
try {
|
|
83
|
+
meta = JSON.parse(readFileSync(join(extensionPackageDir(owner), "package.json"), "utf8"));
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
throw new Error(`${operationPkg} cannot preserve installed extension ${owner}'s shared peers: ${e.message}`);
|
|
87
|
+
}
|
|
88
|
+
for (const peer of Object.keys(meta.peerDependencies ?? {}).filter((name) => name.startsWith("@cotal-ai/"))) {
|
|
89
|
+
let src;
|
|
90
|
+
try {
|
|
91
|
+
src = ourPackageDir(peer);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
throw new Error(`${operationPkg}: ${owner} peer-depends on ${peer}, which this cotal binary does not carry - the peer can't be linked`);
|
|
95
|
+
}
|
|
96
|
+
const dest = join(extensionPackageDir(owner), "node_modules", ...peer.split("/"));
|
|
97
|
+
try {
|
|
98
|
+
rmSync(dest, { recursive: true, force: true });
|
|
99
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
100
|
+
symlinkSync(src, dest, "junction");
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
throw new Error(`${operationPkg} could not link ${peer} for ${owner}: ${e.message}`);
|
|
104
|
+
}
|
|
105
|
+
provenance.wrote(`${peer} link (${owner} → this CLI's copy)`, dest);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** Serialize prefix mutations. A dead owner's lock is reclaimed; a live owner fails loud. */
|
|
110
|
+
function claimExtensionMutation() {
|
|
111
|
+
const lock = extensionMutationLockPath();
|
|
112
|
+
mkdirSync(dirname(lock), { recursive: true });
|
|
113
|
+
for (;;) {
|
|
114
|
+
let fd;
|
|
115
|
+
try {
|
|
116
|
+
fd = openSync(lock, "wx", 0o600);
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
if (e.code !== "EEXIST")
|
|
120
|
+
throw e;
|
|
121
|
+
const status = extensionMutationLockState();
|
|
122
|
+
if (status.state === "absent")
|
|
123
|
+
continue; // raced with the owner's cleanup
|
|
124
|
+
if (status.state === "active")
|
|
125
|
+
throw new Error(`another \`cotal ext\` mutation is in progress (pid ${status.owner})`);
|
|
126
|
+
rmSync(lock, { force: true });
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
writeFileSync(fd, String(process.pid));
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
closeSync(fd);
|
|
134
|
+
}
|
|
135
|
+
let released = false;
|
|
136
|
+
return () => {
|
|
137
|
+
if (released)
|
|
138
|
+
return;
|
|
139
|
+
released = true;
|
|
140
|
+
try {
|
|
141
|
+
if (readFileSync(lock, "utf8").trim() === String(process.pid))
|
|
142
|
+
rmSync(lock, { force: true });
|
|
143
|
+
}
|
|
144
|
+
catch { /* already reclaimed/removed */ }
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
75
148
|
async function add(spec) {
|
|
76
149
|
const dir = extensionsDir();
|
|
77
150
|
mkdirSync(dir, { recursive: true });
|
|
@@ -86,84 +159,161 @@ async function add(spec) {
|
|
|
86
159
|
// dependencies (a heuristic that binds to the wrong key if the prefix ever drifted, and that made
|
|
87
160
|
// re-adding an installed extension impossible).
|
|
88
161
|
const pkg = packageNameFromSpec(resolved, isPath);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// --install-links: a file:/path spec is COPIED into the prefix, not symlinked — a symlink's
|
|
93
|
-
// realpath would escape the prefix and Node could no longer resolve the linked core from it.
|
|
94
|
-
const r = npm(["install", "--save", "--no-audit", "--no-fund", "--legacy-peer-deps", "--install-links", resolved], dir);
|
|
95
|
-
if (r.status !== 0) {
|
|
96
|
-
console.error(c.red(`✗ npm install failed:\n${r.output.split("\n").slice(-8).join("\n")}`));
|
|
97
|
-
process.exit(1);
|
|
162
|
+
const releaseMutation = claimExtensionMutation();
|
|
163
|
+
try {
|
|
164
|
+
await addTransaction();
|
|
98
165
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (!deps[pkg]) {
|
|
102
|
-
console.error(c.red(`✗ npm install succeeded but "${pkg}" is not among the prefix dependencies - remove and retry`));
|
|
103
|
-
process.exit(1);
|
|
166
|
+
finally {
|
|
167
|
+
releaseMutation();
|
|
104
168
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
169
|
+
async function addTransaction() {
|
|
170
|
+
// Validate/read workstation state before npm can mutate the prefix; this snapshot also drives the
|
|
171
|
+
// final replacement entry so the manifest and installed tree commit as one logical transaction.
|
|
172
|
+
const manifest = loadExtensionsManifest();
|
|
173
|
+
// npm installs in-place and may replace the package plus shared dependency/lock state before we
|
|
174
|
+
// can validate it. A failed update must restore the previously working prefix byte-for-byte.
|
|
175
|
+
const updating = manifest.extensions.some((entry) => entry.pkg === pkg) || existsSync(extensionPackageDir(pkg));
|
|
176
|
+
const rollbackRoot = updating ? mkdtempSync(join(dirname(dir), ".extensions.rollback-")) : undefined;
|
|
177
|
+
const rollbackDir = rollbackRoot ? join(rollbackRoot, "extensions") : undefined;
|
|
178
|
+
if (rollbackDir) {
|
|
179
|
+
// Snapshot beside the prefix (same filesystem), preserving npm's relative symlinks verbatim.
|
|
180
|
+
// npm mutates the live tree; rollback removes it and atomically renames this snapshot back.
|
|
181
|
+
cpSync(dir, rollbackDir, { recursive: true, verbatimSymlinks: true });
|
|
182
|
+
// npm otherwise treats a same-spec/same-version re-add as already current, even when the
|
|
183
|
+
// installed files are stale or damaged. Remove only the disposable copy's package so install
|
|
184
|
+
// must materialize it again; the untouched snapshot remains the rollback source.
|
|
185
|
+
rmSync(extensionPackageDir(pkg), { recursive: true, force: true });
|
|
186
|
+
}
|
|
187
|
+
let committed = false;
|
|
188
|
+
let restored = false;
|
|
189
|
+
const restore = () => {
|
|
190
|
+
if (restored || committed)
|
|
191
|
+
return;
|
|
192
|
+
restored = true;
|
|
193
|
+
if (rollbackDir) {
|
|
194
|
+
rmSync(dir, { recursive: true, force: true });
|
|
195
|
+
renameSync(rollbackDir, dir);
|
|
196
|
+
rmSync(rollbackRoot, { recursive: true, force: true });
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
npm(["remove", "--no-audit", "--no-fund", pkg], dir);
|
|
200
|
+
linkExtensionPeers(manifest.extensions.map((entry) => entry.pkg), pkg);
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
const interrupted = () => {
|
|
204
|
+
restore();
|
|
205
|
+
releaseMutation();
|
|
206
|
+
process.exit(130);
|
|
207
|
+
};
|
|
208
|
+
process.once("SIGINT", interrupted);
|
|
209
|
+
process.once("SIGTERM", interrupted);
|
|
123
210
|
try {
|
|
124
|
-
|
|
211
|
+
await installCandidate();
|
|
212
|
+
committed = true;
|
|
213
|
+
if (rollbackRoot)
|
|
214
|
+
rmSync(rollbackRoot, { recursive: true, force: true });
|
|
125
215
|
}
|
|
126
|
-
catch {
|
|
127
|
-
|
|
216
|
+
catch (e) {
|
|
217
|
+
restore();
|
|
218
|
+
throw e;
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
process.removeListener("SIGINT", interrupted);
|
|
222
|
+
process.removeListener("SIGTERM", interrupted);
|
|
223
|
+
}
|
|
224
|
+
async function installCandidate() {
|
|
225
|
+
console.error(c.dim(`installing ${resolved} into ${dir} …`));
|
|
226
|
+
// --legacy-peer-deps: never auto-install the peer'd core from the registry — the add ALWAYS
|
|
227
|
+
// links the running binary's copy below (one core instance is the whole point).
|
|
228
|
+
// --install-links: a file:/path spec is COPIED into the prefix, not symlinked — a symlink's
|
|
229
|
+
// realpath would escape the prefix and Node could no longer resolve the linked core from it.
|
|
230
|
+
const r = npm(["install", "--save", "--no-audit", "--no-fund", "--legacy-peer-deps", "--install-links", resolved], dir);
|
|
231
|
+
if (r.status !== 0) {
|
|
232
|
+
fail(pkg, `npm install failed:\n${r.output.split("\n").slice(-8).join("\n")}`);
|
|
233
|
+
}
|
|
234
|
+
// The spec's package must now be a prefix dependency — anything else is a failed install.
|
|
235
|
+
let deps;
|
|
236
|
+
try {
|
|
237
|
+
deps = JSON.parse(readFileSync(join(dir, "package.json"), "utf8")).dependencies ?? {};
|
|
238
|
+
}
|
|
239
|
+
catch (e) {
|
|
240
|
+
fail(pkg, `left unreadable prefix metadata: ${e.message}`);
|
|
241
|
+
}
|
|
242
|
+
if (!deps[pkg]) {
|
|
243
|
+
fail(pkg, `npm install succeeded but it is not among the prefix dependencies - remove and retry`);
|
|
244
|
+
}
|
|
245
|
+
const pkgDir = extensionPackageDir(pkg);
|
|
246
|
+
let pkgMeta;
|
|
247
|
+
try {
|
|
248
|
+
pkgMeta = JSON.parse(readFileSync(join(pkgDir, "package.json"), "utf8"));
|
|
249
|
+
}
|
|
250
|
+
catch (e) {
|
|
251
|
+
fail(pkg, `has unreadable package metadata: ${e.message}`);
|
|
252
|
+
}
|
|
253
|
+
// Shared @cotal-ai/* packages must be PEER dependencies — a regular dependency vendors a second
|
|
254
|
+
// copy: core's would swallow the extension's registrations into its own registry singleton, and
|
|
255
|
+
// any other shared package would silently drift from the binary's. Fail with the exact reason.
|
|
256
|
+
const vendored = Object.keys(pkgMeta.dependencies ?? {}).filter((d) => d.startsWith("@cotal-ai/"));
|
|
257
|
+
if (vendored.length) {
|
|
258
|
+
fail(pkg, `declares ${vendored.join(", ")} as a regular dependency - shared @cotal-ai/* packages must be peerDependencies, or the extension runs its own copy (core's would swallow its command registrations; any other's drifts from this CLI's)`);
|
|
259
|
+
}
|
|
260
|
+
if (!pkgMeta.peerDependencies?.["@cotal-ai/core"]) {
|
|
261
|
+
fail(pkg, `does not declare @cotal-ai/core as a peerDependency - a cotal CLI extension must (its extension objects register into core's registry)`);
|
|
262
|
+
}
|
|
263
|
+
// npm mutates the shared prefix, so restore every package's private shared-peer links, not only
|
|
264
|
+
// the candidate's. All extensions resolve the exact same host package instances.
|
|
265
|
+
try {
|
|
266
|
+
linkExtensionPeers([...manifest.extensions.filter((entry) => entry.pkg !== pkg).map((entry) => entry.pkg), pkg], pkg);
|
|
267
|
+
}
|
|
268
|
+
catch (e) {
|
|
269
|
+
fail(pkg, e.message);
|
|
270
|
+
}
|
|
271
|
+
// Import once; every registration must LAND IN OUR REGISTRY. Runtime-only and other provider
|
|
272
|
+
// packages are first-class extensions too; commands are only the display/dispatch subset.
|
|
273
|
+
const before = new Set(registry.all().map((ext) => `${ext.kind}:${ext.name}`));
|
|
274
|
+
try {
|
|
275
|
+
await importExtension(pkg);
|
|
276
|
+
}
|
|
277
|
+
catch (e) {
|
|
278
|
+
fail(pkg, `failed to import: ${e.message}`);
|
|
279
|
+
}
|
|
280
|
+
const contributed = registry.all().filter((ext) => !before.has(`${ext.kind}:${ext.name}`));
|
|
281
|
+
if (!contributed.length) {
|
|
282
|
+
fail(pkg, `imported cleanly but registered no extensions in THIS CLI's registry - if it bundles its own @cotal-ai/core, make core a peerDependency`);
|
|
283
|
+
}
|
|
284
|
+
// Builtin collisions can't happen here (registry.register throws on a duplicate, surfacing as
|
|
285
|
+
// failed-to-import above, naming the extension). OTHER installed extensions are invisible to the
|
|
286
|
+
// registry during this add (they aren't imported), so their CACHED names are checked explicitly —
|
|
287
|
+
// a duplicate fails the add under the same contract, naming both sides.
|
|
288
|
+
for (const provided of contributed) {
|
|
289
|
+
const other = manifest.extensions.find((e) => e.pkg !== pkg && extensionProvides(e).some((ref) => ref.kind === provided.kind && ref.name === provided.name));
|
|
290
|
+
if (other) {
|
|
291
|
+
fail(pkg, `contributes ${provided.kind} "${provided.name}", already provided by installed extension ${other.pkg}@${other.version} - two extensions cannot claim one registry key; \`cotal ext remove ${other.pkg}\` first if you want this one`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const commands = contributed.filter((ext) => ext.kind === "command");
|
|
295
|
+
const localProcesses = contributed.filter((ext) => ext.kind === "local-process");
|
|
296
|
+
const version = pkgMeta.version ?? "0.0.0";
|
|
297
|
+
const entry = {
|
|
298
|
+
pkg,
|
|
299
|
+
version,
|
|
300
|
+
spec: resolved,
|
|
301
|
+
provides: contributed.map(cacheExtension),
|
|
302
|
+
commands: commands.map(cacheCommand),
|
|
303
|
+
localProcesses: localProcesses.map(cacheLocalProcess),
|
|
304
|
+
};
|
|
305
|
+
try {
|
|
306
|
+
saveExtensionsManifest({ extensions: [...manifest.extensions.filter((e) => e.pkg !== pkg), entry] });
|
|
307
|
+
}
|
|
308
|
+
catch (e) {
|
|
309
|
+
fail(pkg, `could not update the extensions manifest: ${e.message}`);
|
|
310
|
+
}
|
|
311
|
+
provenance.wrote(`extensions manifest (+${pkg}@${version})`, extensionsManifestPath());
|
|
312
|
+
console.log(c.green(`✓ added ${pkg}@${version}`) + c.dim(` - provides: ${contributed.map((ext) => `${ext.kind}:${ext.name}`).join(", ")}`));
|
|
313
|
+
}
|
|
314
|
+
function fail(p, why) {
|
|
315
|
+
throw new Error(`${p} ${why}`);
|
|
128
316
|
}
|
|
129
|
-
const dest = join(dir, "node_modules", ...peer.split("/"));
|
|
130
|
-
rmSync(dest, { recursive: true, force: true });
|
|
131
|
-
mkdirSync(dirname(dest), { recursive: true });
|
|
132
|
-
symlinkSync(src, dest, "junction");
|
|
133
|
-
provenance.wrote(`${peer} link (extension → this CLI's copy)`, dest);
|
|
134
|
-
}
|
|
135
|
-
// Import once; the registration must LAND IN OUR REGISTRY — zero new commands is a failed add.
|
|
136
|
-
const before = new Set(registry.all("command").map((cm) => cm.name));
|
|
137
|
-
try {
|
|
138
|
-
await importExtension(pkg);
|
|
139
|
-
}
|
|
140
|
-
catch (e) {
|
|
141
|
-
fail(pkg, `failed to import: ${e.message}`);
|
|
142
|
-
}
|
|
143
|
-
const contributed = registry.all("command").filter((cm) => !before.has(cm.name));
|
|
144
|
-
if (!contributed.length) {
|
|
145
|
-
fail(pkg, `imported cleanly but registered no commands in THIS CLI's registry - if it bundles its own @cotal-ai/core, make core a peerDependency`);
|
|
146
|
-
}
|
|
147
|
-
// Builtin collisions can't happen here (registry.register throws on a duplicate, surfacing as
|
|
148
|
-
// failed-to-import above, naming the extension). OTHER installed extensions are invisible to the
|
|
149
|
-
// registry during this add (they aren't imported), so their CACHED names are checked explicitly —
|
|
150
|
-
// a duplicate fails the add under the same contract, naming both sides.
|
|
151
|
-
const manifest = loadExtensionsManifest();
|
|
152
|
-
for (const cm of contributed) {
|
|
153
|
-
const other = manifest.extensions.find((e) => e.pkg !== pkg && e.commands.some((oc) => oc.name === cm.name));
|
|
154
|
-
if (other) {
|
|
155
|
-
fail(pkg, `contributes "${cm.name}", already provided by installed extension ${other.pkg}@${other.version} - two extensions cannot claim one command; \`cotal ext remove ${other.pkg}\` first if you want this one`);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
const version = pkgMeta.version ?? "0.0.0";
|
|
159
|
-
const entry = { pkg, version, spec: resolved, commands: contributed.map(cacheCommand) };
|
|
160
|
-
saveExtensionsManifest({ extensions: [...manifest.extensions.filter((e) => e.pkg !== pkg), entry] });
|
|
161
|
-
provenance.wrote(`extensions manifest (+${pkg}@${version})`, extensionsManifestPath());
|
|
162
|
-
console.log(c.green(`✓ added ${pkg}@${version}`) + c.dim(` - commands: ${contributed.map((cm) => cm.name).join(", ")}`));
|
|
163
|
-
function fail(p, why) {
|
|
164
|
-
npm(["remove", "--no-audit", "--no-fund", p], dir); // roll the prefix back
|
|
165
|
-
console.error(c.red(`✗ ${p} ${why}`));
|
|
166
|
-
process.exit(1);
|
|
167
317
|
}
|
|
168
318
|
}
|
|
169
319
|
/** The package NAME a spec installs, known BEFORE npm runs: a path spec reads its package.json;
|
|
@@ -192,20 +342,107 @@ function packageNameFromSpec(resolved, isPath) {
|
|
|
192
342
|
process.exit(1);
|
|
193
343
|
}
|
|
194
344
|
async function remove(pkg) {
|
|
345
|
+
const releaseMutation = claimExtensionMutation();
|
|
346
|
+
try {
|
|
347
|
+
await removeUnlocked(pkg);
|
|
348
|
+
}
|
|
349
|
+
finally {
|
|
350
|
+
releaseMutation();
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
async function removeUnlocked(pkg) {
|
|
195
354
|
const manifest = loadExtensionsManifest();
|
|
196
355
|
const entry = manifest.extensions.find((e) => e.pkg === pkg);
|
|
197
|
-
if (!entry)
|
|
198
|
-
|
|
199
|
-
|
|
356
|
+
if (!entry)
|
|
357
|
+
throw new Error(`no installed extension "${pkg}" - see \`cotal ext list\``);
|
|
358
|
+
const processes = await extensionProcesses(entry);
|
|
359
|
+
const recorded = processes.filter(({ pidPath }) => existsSync(pidPath));
|
|
360
|
+
if (recorded.length)
|
|
361
|
+
throw new Error(`${pkg} still owns recorded local processes:\n${recorded.map(describeProcess).map((item) => ` ${item}`).join("\n")}\nStop or clean them from the listed mesh roots before removing the extension.`);
|
|
362
|
+
// Reserve every provider pidfile through uninstall. A concurrent extension startup then loses
|
|
363
|
+
// its own atomic pid claim instead of coming online after the liveness scan but before removal.
|
|
364
|
+
const reservations = [];
|
|
365
|
+
try {
|
|
366
|
+
for (const { context, pidPath } of processes) {
|
|
367
|
+
// Only real mesh roots participate, but reserve nested provider state directories even when
|
|
368
|
+
// the process has never run so startup cannot create-and-claim them during npm removal.
|
|
369
|
+
if (!existsSync(join(context.root, ".cotal")))
|
|
370
|
+
continue;
|
|
371
|
+
mkdirSync(dirname(pidPath), { recursive: true });
|
|
372
|
+
let fd;
|
|
373
|
+
try {
|
|
374
|
+
fd = openSync(pidPath, "wx", 0o600);
|
|
375
|
+
}
|
|
376
|
+
catch (e) {
|
|
377
|
+
if (e.code === "EEXIST")
|
|
378
|
+
throw new Error(`${pkg} acquired process state while removal was starting - stop it and retry`);
|
|
379
|
+
throw e;
|
|
380
|
+
}
|
|
381
|
+
try {
|
|
382
|
+
writeFileSync(fd, `removing:${process.pid}`);
|
|
383
|
+
}
|
|
384
|
+
finally {
|
|
385
|
+
closeSync(fd);
|
|
386
|
+
}
|
|
387
|
+
reservations.push(pidPath);
|
|
388
|
+
}
|
|
389
|
+
const r = npm(["remove", "--no-audit", "--no-fund", pkg], extensionsDir());
|
|
390
|
+
if (r.status !== 0)
|
|
391
|
+
throw new Error(`npm remove failed:\n${r.output.split("\n").slice(-6).join("\n")}`);
|
|
392
|
+
const remaining = manifest.extensions.filter((e) => e.pkg !== pkg);
|
|
393
|
+
linkExtensionPeers(remaining.map((entry) => entry.pkg), pkg);
|
|
394
|
+
saveExtensionsManifest({ extensions: remaining });
|
|
395
|
+
provenance.wrote(`extensions manifest (−${pkg})`, extensionsManifestPath());
|
|
396
|
+
console.log(c.green(`✓ removed ${pkg}`) + c.dim(` - removed: ${extensionProvides(entry).map((ref) => `${ref.kind}:${ref.name}`).join(", ")}`));
|
|
200
397
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
398
|
+
finally {
|
|
399
|
+
for (const pidPath of reservations) {
|
|
400
|
+
try {
|
|
401
|
+
if (readFileSync(pidPath, "utf8").trim() === `removing:${process.pid}`)
|
|
402
|
+
rmSync(pidPath, { force: true });
|
|
403
|
+
}
|
|
404
|
+
catch {
|
|
405
|
+
// A failed/racing startup may already have cleaned the reservation.
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
/** Resolve every mesh-local pidfile owned by this extension. */
|
|
411
|
+
async function extensionProcesses(entry) {
|
|
412
|
+
const refs = extensionProvides(entry).filter((ref) => ref.kind === "local-process");
|
|
413
|
+
if (!refs.length)
|
|
414
|
+
return [];
|
|
415
|
+
const providers = [...extensionLocalProcesses(entry)];
|
|
416
|
+
const missing = refs.map((ref) => ref.name).filter((name) => !providers.some((provider) => provider.name === name));
|
|
417
|
+
if (missing.length)
|
|
418
|
+
throw new Error(`${entry.pkg} predates cached local-process metadata for ${missing.join(", ")} - re-add it before removal: \`cotal ext add ${entry.spec}\``);
|
|
419
|
+
const currentRoot = cotalRoot();
|
|
420
|
+
const contexts = new Map();
|
|
421
|
+
contexts.set(currentRoot, { root: currentRoot, space: resolveSpace(currentRoot) });
|
|
422
|
+
for (const mesh of loadMeshes())
|
|
423
|
+
contexts.set(mesh.root, { root: mesh.root, space: mesh.space });
|
|
424
|
+
const processes = [];
|
|
425
|
+
for (const context of contexts.values()) {
|
|
426
|
+
for (const provider of providers) {
|
|
427
|
+
processes.push({ provider, context, pidPath: localProcessPath(provider.pidFile, context) });
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
return processes;
|
|
431
|
+
}
|
|
432
|
+
function describeProcess({ provider, context, pidPath }) {
|
|
433
|
+
const raw = readFileSync(pidPath, "utf8").trim();
|
|
434
|
+
if (raw.startsWith("removing:"))
|
|
435
|
+
return `${provider.name} (extension-removal reservation) in ${context.root} - clean ${pidPath} if its owner is gone`;
|
|
436
|
+
const pid = Number(raw);
|
|
437
|
+
let state = "stale pidfile";
|
|
438
|
+
if (Number.isInteger(pid) && pid > 0) {
|
|
439
|
+
try {
|
|
440
|
+
process.kill(pid, 0);
|
|
441
|
+
state = `pid ${pid}`;
|
|
442
|
+
}
|
|
443
|
+
catch { /* stale */ }
|
|
205
444
|
}
|
|
206
|
-
|
|
207
|
-
provenance.wrote(`extensions manifest (−${pkg})`, extensionsManifestPath());
|
|
208
|
-
console.log(c.green(`✓ removed ${pkg}`) + c.dim(` - commands gone: ${entry.commands.map((cm) => cm.name).join(", ")}`));
|
|
445
|
+
return `${provider.name} (${state}) in ${context.root} - run there: cotal down ${provider.name}`;
|
|
209
446
|
}
|
|
210
447
|
function list() {
|
|
211
448
|
const { extensions } = loadExtensionsManifest();
|
|
@@ -214,7 +451,7 @@ function list() {
|
|
|
214
451
|
return;
|
|
215
452
|
}
|
|
216
453
|
for (const e of extensions) {
|
|
217
|
-
console.log(`${c.bold(e.pkg)}@${e.version} ${c.dim(e.
|
|
454
|
+
console.log(`${c.bold(e.pkg)}@${e.version} ${c.dim(extensionProvides(e).map((ref) => `${ref.kind}:${ref.name}`).join(", "))}`);
|
|
218
455
|
}
|
|
219
456
|
}
|
|
220
457
|
//# sourceMappingURL=ext.js.map
|