@openacp/cli 0.6.9 → 2026.41.1
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/README.md +116 -152
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +27740 -415
- package/dist/cli.js.map +1 -1
- package/dist/data/registry-snapshot.json +1 -1
- package/dist/index.d.ts +1944 -463
- package/dist/index.js +17365 -102
- package/dist/index.js.map +1 -1
- package/package.json +13 -7
- package/dist/action-detect-P7ZE4NEM.js +0 -16
- package/dist/action-detect-P7ZE4NEM.js.map +0 -1
- package/dist/adapter-LNEGLMOE.js +0 -799
- package/dist/adapter-LNEGLMOE.js.map +0 -1
- package/dist/admin-6SYB6XCZ.js +0 -23
- package/dist/admin-6SYB6XCZ.js.map +0 -1
- package/dist/agent-catalog-FC3HGDEQ.js +0 -11
- package/dist/agent-catalog-FC3HGDEQ.js.map +0 -1
- package/dist/agent-dependencies-4OWBMZWZ.js +0 -24
- package/dist/agent-dependencies-4OWBMZWZ.js.map +0 -1
- package/dist/agent-registry-WT4NXPYG.js +0 -9
- package/dist/agent-registry-WT4NXPYG.js.map +0 -1
- package/dist/agent-store-VZLFPTZU.js +0 -9
- package/dist/agent-store-VZLFPTZU.js.map +0 -1
- package/dist/agents-QO7DKARJ.js +0 -15
- package/dist/agents-QO7DKARJ.js.map +0 -1
- package/dist/api-client-CFQT5U7D.js +0 -14
- package/dist/api-client-CFQT5U7D.js.map +0 -1
- package/dist/autostart-X33OGMX6.js +0 -23
- package/dist/autostart-X33OGMX6.js.map +0 -1
- package/dist/chunk-2CJ46J3C.js +0 -154
- package/dist/chunk-2CJ46J3C.js.map +0 -1
- package/dist/chunk-2HMQOC7N.js +0 -134
- package/dist/chunk-2HMQOC7N.js.map +0 -1
- package/dist/chunk-33RP6K2O.js +0 -435
- package/dist/chunk-33RP6K2O.js.map +0 -1
- package/dist/chunk-34M4OS5P.js +0 -83
- package/dist/chunk-34M4OS5P.js.map +0 -1
- package/dist/chunk-4CTX774K.js +0 -265
- package/dist/chunk-4CTX774K.js.map +0 -1
- package/dist/chunk-7QJS2XBD.js +0 -92
- package/dist/chunk-7QJS2XBD.js.map +0 -1
- package/dist/chunk-BDYVCIBH.js +0 -735
- package/dist/chunk-BDYVCIBH.js.map +0 -1
- package/dist/chunk-BN3X7UXB.js +0 -738
- package/dist/chunk-BN3X7UXB.js.map +0 -1
- package/dist/chunk-BNLGTZ34.js +0 -122
- package/dist/chunk-BNLGTZ34.js.map +0 -1
- package/dist/chunk-GAK6PIBW.js +0 -224
- package/dist/chunk-GAK6PIBW.js.map +0 -1
- package/dist/chunk-H5P2C6H4.js +0 -4740
- package/dist/chunk-H5P2C6H4.js.map +0 -1
- package/dist/chunk-I7WC6E5S.js +0 -71
- package/dist/chunk-I7WC6E5S.js.map +0 -1
- package/dist/chunk-J4SJTKIK.js +0 -203
- package/dist/chunk-J4SJTKIK.js.map +0 -1
- package/dist/chunk-JHYXKVV2.js +0 -183
- package/dist/chunk-JHYXKVV2.js.map +0 -1
- package/dist/chunk-JKBFUAJK.js +0 -282
- package/dist/chunk-JKBFUAJK.js.map +0 -1
- package/dist/chunk-JUYDFUSN.js +0 -673
- package/dist/chunk-JUYDFUSN.js.map +0 -1
- package/dist/chunk-KIRH7TUJ.js +0 -219
- package/dist/chunk-KIRH7TUJ.js.map +0 -1
- package/dist/chunk-LBIKITQT.js +0 -22
- package/dist/chunk-LBIKITQT.js.map +0 -1
- package/dist/chunk-LGP2YGRL.js +0 -4880
- package/dist/chunk-LGP2YGRL.js.map +0 -1
- package/dist/chunk-NAMYZIS5.js +0 -1
- package/dist/chunk-NAMYZIS5.js.map +0 -1
- package/dist/chunk-NVPG6JCL.js +0 -724
- package/dist/chunk-NVPG6JCL.js.map +0 -1
- package/dist/chunk-O7CPGUAI.js +0 -298
- package/dist/chunk-O7CPGUAI.js.map +0 -1
- package/dist/chunk-S64CB6J3.js +0 -98
- package/dist/chunk-S64CB6J3.js.map +0 -1
- package/dist/chunk-UKT3G5IA.js +0 -484
- package/dist/chunk-UKT3G5IA.js.map +0 -1
- package/dist/chunk-V5GZQEIY.js +0 -101
- package/dist/chunk-V5GZQEIY.js.map +0 -1
- package/dist/chunk-VOIJ6OY4.js +0 -63
- package/dist/chunk-VOIJ6OY4.js.map +0 -1
- package/dist/chunk-VUNV25KB.js +0 -16
- package/dist/chunk-VUNV25KB.js.map +0 -1
- package/dist/chunk-W3EYKZNQ.js +0 -45
- package/dist/chunk-W3EYKZNQ.js.map +0 -1
- package/dist/chunk-WTZDAYZX.js +0 -172
- package/dist/chunk-WTZDAYZX.js.map +0 -1
- package/dist/chunk-XANPHG7W.js +0 -145
- package/dist/chunk-XANPHG7W.js.map +0 -1
- package/dist/config-6S355X75.js +0 -15
- package/dist/config-6S355X75.js.map +0 -1
- package/dist/config-editor-RVLWZLVB.js +0 -13
- package/dist/config-editor-RVLWZLVB.js.map +0 -1
- package/dist/config-registry-AHYI4MYL.js +0 -18
- package/dist/config-registry-AHYI4MYL.js.map +0 -1
- package/dist/daemon-4CS6HMB5.js +0 -30
- package/dist/daemon-4CS6HMB5.js.map +0 -1
- package/dist/discord-7IVQKB2H.js +0 -2083
- package/dist/discord-7IVQKB2H.js.map +0 -1
- package/dist/dist-UHQK5CXN.js +0 -21151
- package/dist/dist-UHQK5CXN.js.map +0 -1
- package/dist/doctor-HZZ5BSHB.js +0 -10
- package/dist/doctor-HZZ5BSHB.js.map +0 -1
- package/dist/doctor-OLYBO3V3.js +0 -15
- package/dist/doctor-OLYBO3V3.js.map +0 -1
- package/dist/install-cloudflared-Z7VCGOVG.js +0 -33
- package/dist/install-cloudflared-Z7VCGOVG.js.map +0 -1
- package/dist/install-jq-HUYSQWKR.js +0 -32
- package/dist/install-jq-HUYSQWKR.js.map +0 -1
- package/dist/integrate-PNEHRY2I.js +0 -373
- package/dist/integrate-PNEHRY2I.js.map +0 -1
- package/dist/log-NXABYJTT.js +0 -24
- package/dist/log-NXABYJTT.js.map +0 -1
- package/dist/main-ZK4MPMBG.js +0 -238
- package/dist/main-ZK4MPMBG.js.map +0 -1
- package/dist/menu-YY5MKHEK.js +0 -16
- package/dist/menu-YY5MKHEK.js.map +0 -1
- package/dist/new-session-FEO4J4VU.js +0 -17
- package/dist/new-session-FEO4J4VU.js.map +0 -1
- package/dist/post-upgrade-CJG5I7M2.js +0 -80
- package/dist/post-upgrade-CJG5I7M2.js.map +0 -1
- package/dist/session-IUSI7P5S.js +0 -20
- package/dist/session-IUSI7P5S.js.map +0 -1
- package/dist/settings-RQPAM4KC.js +0 -14
- package/dist/settings-RQPAM4KC.js.map +0 -1
- package/dist/setup-3GQSYBE4.js +0 -35
- package/dist/setup-3GQSYBE4.js.map +0 -1
- package/dist/suggest-7D6B542M.js +0 -38
- package/dist/suggest-7D6B542M.js.map +0 -1
- package/dist/tunnel-service-CJLUH6SZ.js +0 -1174
- package/dist/tunnel-service-CJLUH6SZ.js.map +0 -1
- package/dist/version-NQZBM5M7.js +0 -16
- package/dist/version-NQZBM5M7.js.map +0 -1
package/dist/chunk-UKT3G5IA.js
DELETED
|
@@ -1,484 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AgentStore
|
|
3
|
-
} from "./chunk-34M4OS5P.js";
|
|
4
|
-
import {
|
|
5
|
-
checkDependencies,
|
|
6
|
-
checkRuntimeAvailable,
|
|
7
|
-
getAgentAlias,
|
|
8
|
-
getAgentSetup
|
|
9
|
-
} from "./chunk-JKBFUAJK.js";
|
|
10
|
-
import {
|
|
11
|
-
createChildLogger
|
|
12
|
-
} from "./chunk-GAK6PIBW.js";
|
|
13
|
-
|
|
14
|
-
// src/core/agent-catalog.ts
|
|
15
|
-
import * as fs2 from "fs";
|
|
16
|
-
import * as path2 from "path";
|
|
17
|
-
import * as os2 from "os";
|
|
18
|
-
|
|
19
|
-
// src/core/agent-installer.ts
|
|
20
|
-
import * as fs from "fs";
|
|
21
|
-
import * as path from "path";
|
|
22
|
-
import * as os from "os";
|
|
23
|
-
var log = createChildLogger({ module: "agent-installer" });
|
|
24
|
-
var AGENTS_DIR = path.join(os.homedir(), ".openacp", "agents");
|
|
25
|
-
var ARCH_MAP = {
|
|
26
|
-
arm64: "aarch64",
|
|
27
|
-
x64: "x86_64"
|
|
28
|
-
};
|
|
29
|
-
var PLATFORM_MAP = {
|
|
30
|
-
darwin: "darwin",
|
|
31
|
-
linux: "linux",
|
|
32
|
-
win32: "windows"
|
|
33
|
-
};
|
|
34
|
-
function getPlatformKey() {
|
|
35
|
-
const platform = PLATFORM_MAP[process.platform] ?? process.platform;
|
|
36
|
-
const arch = ARCH_MAP[process.arch] ?? process.arch;
|
|
37
|
-
return `${platform}-${arch}`;
|
|
38
|
-
}
|
|
39
|
-
function resolveDistribution(agent) {
|
|
40
|
-
const dist = agent.distribution;
|
|
41
|
-
if (dist.npx) {
|
|
42
|
-
return { type: "npx", package: dist.npx.package, args: dist.npx.args ?? [], env: dist.npx.env };
|
|
43
|
-
}
|
|
44
|
-
if (dist.uvx) {
|
|
45
|
-
return { type: "uvx", package: dist.uvx.package, args: dist.uvx.args ?? [], env: dist.uvx.env };
|
|
46
|
-
}
|
|
47
|
-
if (dist.binary) {
|
|
48
|
-
const platformKey = getPlatformKey();
|
|
49
|
-
const target = dist.binary[platformKey];
|
|
50
|
-
if (!target) return null;
|
|
51
|
-
return { type: "binary", archive: target.archive, cmd: target.cmd, args: target.args ?? [], env: target.env };
|
|
52
|
-
}
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
function buildInstalledAgent(registryId, name, version, dist, binaryPath) {
|
|
56
|
-
if (dist.type === "npx") {
|
|
57
|
-
const npxPackage = stripPackageVersion(dist.package);
|
|
58
|
-
return {
|
|
59
|
-
registryId,
|
|
60
|
-
name,
|
|
61
|
-
version,
|
|
62
|
-
distribution: "npx",
|
|
63
|
-
command: "npx",
|
|
64
|
-
args: [npxPackage, ...dist.args],
|
|
65
|
-
env: dist.env ?? {},
|
|
66
|
-
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
67
|
-
binaryPath: null
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
if (dist.type === "uvx") {
|
|
71
|
-
const uvxPackage = stripPythonPackageVersion(dist.package);
|
|
72
|
-
return {
|
|
73
|
-
registryId,
|
|
74
|
-
name,
|
|
75
|
-
version,
|
|
76
|
-
distribution: "uvx",
|
|
77
|
-
command: "uvx",
|
|
78
|
-
args: [uvxPackage, ...dist.args],
|
|
79
|
-
env: dist.env ?? {},
|
|
80
|
-
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
81
|
-
binaryPath: null
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
const absCmd = path.resolve(binaryPath, dist.cmd);
|
|
85
|
-
return {
|
|
86
|
-
registryId,
|
|
87
|
-
name,
|
|
88
|
-
version,
|
|
89
|
-
distribution: "binary",
|
|
90
|
-
command: absCmd,
|
|
91
|
-
args: dist.args,
|
|
92
|
-
env: dist.env ?? {},
|
|
93
|
-
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
94
|
-
binaryPath
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
function stripPackageVersion(pkg) {
|
|
98
|
-
if (pkg.startsWith("@")) {
|
|
99
|
-
const afterScope = pkg.indexOf("/");
|
|
100
|
-
if (afterScope === -1) return pkg;
|
|
101
|
-
const versionAt = pkg.indexOf("@", afterScope + 1);
|
|
102
|
-
return versionAt === -1 ? pkg : pkg.slice(0, versionAt);
|
|
103
|
-
}
|
|
104
|
-
const at = pkg.indexOf("@");
|
|
105
|
-
return at === -1 ? pkg : pkg.slice(0, at);
|
|
106
|
-
}
|
|
107
|
-
function stripPythonPackageVersion(pkg) {
|
|
108
|
-
const pyMatch = pkg.match(/^([^=@><!]+)/);
|
|
109
|
-
if (pyMatch && pkg.includes("==")) return pyMatch[1];
|
|
110
|
-
const at = pkg.indexOf("@");
|
|
111
|
-
return at === -1 ? pkg : pkg.slice(0, at);
|
|
112
|
-
}
|
|
113
|
-
async function installAgent(agent, store, progress) {
|
|
114
|
-
const agentKey = getAgentAlias(agent.id);
|
|
115
|
-
await progress?.onStart(agent.id, agent.name);
|
|
116
|
-
await progress?.onStep("Checking requirements...");
|
|
117
|
-
const depResult = checkDependencies(agent.id);
|
|
118
|
-
if (!depResult.available) {
|
|
119
|
-
const hints = depResult.missing.map((m) => ` ${m.label}: ${m.installHint}`).join("\n");
|
|
120
|
-
const msg = `${agent.name} needs some tools installed first:
|
|
121
|
-
${hints}`;
|
|
122
|
-
await progress?.onError(msg);
|
|
123
|
-
return { ok: false, agentKey, error: msg };
|
|
124
|
-
}
|
|
125
|
-
const dist = resolveDistribution(agent);
|
|
126
|
-
if (!dist) {
|
|
127
|
-
const platformKey = getPlatformKey();
|
|
128
|
-
const msg = `${agent.name} is not available for your system (${platformKey}). Check their website for other install options.`;
|
|
129
|
-
await progress?.onError(msg);
|
|
130
|
-
return { ok: false, agentKey, error: msg };
|
|
131
|
-
}
|
|
132
|
-
if (dist.type === "uvx" && !checkRuntimeAvailable("uvx")) {
|
|
133
|
-
const msg = `${agent.name} requires Python's uvx tool.
|
|
134
|
-
Install it with: pip install uv`;
|
|
135
|
-
await progress?.onError(msg, "pip install uv");
|
|
136
|
-
return { ok: false, agentKey, error: msg, hint: "pip install uv" };
|
|
137
|
-
}
|
|
138
|
-
let binaryPath;
|
|
139
|
-
if (dist.type === "binary") {
|
|
140
|
-
try {
|
|
141
|
-
binaryPath = await downloadAndExtract(agent.id, dist.archive, progress);
|
|
142
|
-
} catch (err) {
|
|
143
|
-
const msg = `Failed to download ${agent.name}. Please try again or install manually.`;
|
|
144
|
-
await progress?.onError(msg);
|
|
145
|
-
return { ok: false, agentKey, error: msg };
|
|
146
|
-
}
|
|
147
|
-
} else {
|
|
148
|
-
await progress?.onStep("Setting up... (will download on first use)");
|
|
149
|
-
}
|
|
150
|
-
const installed = buildInstalledAgent(agent.id, agent.name, agent.version, dist, binaryPath);
|
|
151
|
-
store.addAgent(agentKey, installed);
|
|
152
|
-
const setup = getAgentSetup(agent.id);
|
|
153
|
-
await progress?.onSuccess(agent.name);
|
|
154
|
-
return { ok: true, agentKey, setupSteps: setup?.setupSteps };
|
|
155
|
-
}
|
|
156
|
-
async function downloadAndExtract(agentId, archiveUrl, progress) {
|
|
157
|
-
const destDir = path.join(AGENTS_DIR, agentId);
|
|
158
|
-
fs.mkdirSync(destDir, { recursive: true });
|
|
159
|
-
await progress?.onStep("Downloading...");
|
|
160
|
-
log.info({ agentId, url: archiveUrl }, "Downloading agent binary");
|
|
161
|
-
const response = await fetch(archiveUrl);
|
|
162
|
-
if (!response.ok) {
|
|
163
|
-
throw new Error(`Download failed: ${response.status} ${response.statusText}`);
|
|
164
|
-
}
|
|
165
|
-
const contentLength = Number(response.headers.get("content-length") || 0);
|
|
166
|
-
const buffer = await readResponseWithProgress(response, contentLength, progress);
|
|
167
|
-
await progress?.onStep("Extracting...");
|
|
168
|
-
if (archiveUrl.endsWith(".zip")) {
|
|
169
|
-
await extractZip(buffer, destDir);
|
|
170
|
-
} else {
|
|
171
|
-
await extractTarGz(buffer, destDir);
|
|
172
|
-
}
|
|
173
|
-
await progress?.onStep("Ready!");
|
|
174
|
-
return destDir;
|
|
175
|
-
}
|
|
176
|
-
async function readResponseWithProgress(response, contentLength, progress) {
|
|
177
|
-
if (!response.body || contentLength === 0) {
|
|
178
|
-
const arrayBuffer = await response.arrayBuffer();
|
|
179
|
-
return Buffer.from(arrayBuffer);
|
|
180
|
-
}
|
|
181
|
-
const reader = response.body.getReader();
|
|
182
|
-
const chunks = [];
|
|
183
|
-
let received = 0;
|
|
184
|
-
while (true) {
|
|
185
|
-
const { done, value } = await reader.read();
|
|
186
|
-
if (done) break;
|
|
187
|
-
chunks.push(value);
|
|
188
|
-
received += value.length;
|
|
189
|
-
if (contentLength > 0) {
|
|
190
|
-
await progress?.onDownloadProgress(Math.round(received / contentLength * 100));
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return Buffer.concat(chunks);
|
|
194
|
-
}
|
|
195
|
-
function validateExtractedPaths(destDir) {
|
|
196
|
-
const realDest = fs.realpathSync(destDir);
|
|
197
|
-
const entries = fs.readdirSync(destDir, { recursive: true, withFileTypes: true });
|
|
198
|
-
for (const entry of entries) {
|
|
199
|
-
const dirent = entry;
|
|
200
|
-
const parentPath = dirent.parentPath ?? dirent.path ?? destDir;
|
|
201
|
-
const fullPath = path.join(parentPath, entry.name);
|
|
202
|
-
let realPath;
|
|
203
|
-
try {
|
|
204
|
-
realPath = fs.realpathSync(fullPath);
|
|
205
|
-
} catch {
|
|
206
|
-
const linkTarget = fs.readlinkSync(fullPath);
|
|
207
|
-
realPath = path.resolve(path.dirname(fullPath), linkTarget);
|
|
208
|
-
}
|
|
209
|
-
if (!realPath.startsWith(realDest + path.sep) && realPath !== realDest) {
|
|
210
|
-
fs.rmSync(destDir, { recursive: true, force: true });
|
|
211
|
-
throw new Error(`Archive contains unsafe path: ${entry.name}`);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
async function extractTarGz(buffer, destDir) {
|
|
216
|
-
const { execFileSync } = await import("child_process");
|
|
217
|
-
const tmpFile = path.join(destDir, "_archive.tar.gz");
|
|
218
|
-
fs.writeFileSync(tmpFile, buffer);
|
|
219
|
-
try {
|
|
220
|
-
execFileSync("tar", ["xzf", tmpFile, "-C", destDir], { stdio: "pipe" });
|
|
221
|
-
} finally {
|
|
222
|
-
fs.unlinkSync(tmpFile);
|
|
223
|
-
}
|
|
224
|
-
validateExtractedPaths(destDir);
|
|
225
|
-
}
|
|
226
|
-
async function extractZip(buffer, destDir) {
|
|
227
|
-
const { execFileSync } = await import("child_process");
|
|
228
|
-
const tmpFile = path.join(destDir, "_archive.zip");
|
|
229
|
-
fs.writeFileSync(tmpFile, buffer);
|
|
230
|
-
try {
|
|
231
|
-
execFileSync("unzip", ["-o", tmpFile, "-d", destDir], { stdio: "pipe" });
|
|
232
|
-
} finally {
|
|
233
|
-
fs.unlinkSync(tmpFile);
|
|
234
|
-
}
|
|
235
|
-
validateExtractedPaths(destDir);
|
|
236
|
-
}
|
|
237
|
-
async function uninstallAgent(agentKey, store) {
|
|
238
|
-
const agent = store.getAgent(agentKey);
|
|
239
|
-
if (!agent) return;
|
|
240
|
-
if (agent.binaryPath && fs.existsSync(agent.binaryPath)) {
|
|
241
|
-
fs.rmSync(agent.binaryPath, { recursive: true, force: true });
|
|
242
|
-
log.info({ agentKey, binaryPath: agent.binaryPath }, "Deleted agent binary");
|
|
243
|
-
}
|
|
244
|
-
store.removeAgent(agentKey);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// src/core/agent-catalog.ts
|
|
248
|
-
var log2 = createChildLogger({ module: "agent-catalog" });
|
|
249
|
-
var REGISTRY_URL = "https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json";
|
|
250
|
-
var CACHE_PATH = path2.join(os2.homedir(), ".openacp", "registry-cache.json");
|
|
251
|
-
var DEFAULT_TTL_HOURS = 24;
|
|
252
|
-
var AgentCatalog = class {
|
|
253
|
-
store;
|
|
254
|
-
registryAgents = [];
|
|
255
|
-
constructor(store) {
|
|
256
|
-
this.store = store ?? new AgentStore();
|
|
257
|
-
}
|
|
258
|
-
load() {
|
|
259
|
-
this.store.load();
|
|
260
|
-
this.loadRegistryFromCacheOrSnapshot();
|
|
261
|
-
this.enrichInstalledFromRegistry();
|
|
262
|
-
}
|
|
263
|
-
// --- Registry ---
|
|
264
|
-
async fetchRegistry() {
|
|
265
|
-
try {
|
|
266
|
-
log2.info("Fetching agent registry from CDN...");
|
|
267
|
-
const response = await fetch(REGISTRY_URL);
|
|
268
|
-
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
269
|
-
const data = await response.json();
|
|
270
|
-
this.registryAgents = data.agents ?? [];
|
|
271
|
-
const cache = {
|
|
272
|
-
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
273
|
-
ttlHours: DEFAULT_TTL_HOURS,
|
|
274
|
-
data
|
|
275
|
-
};
|
|
276
|
-
fs2.mkdirSync(path2.dirname(CACHE_PATH), { recursive: true });
|
|
277
|
-
fs2.writeFileSync(CACHE_PATH, JSON.stringify(cache, null, 2));
|
|
278
|
-
log2.info({ count: this.registryAgents.length }, "Registry updated");
|
|
279
|
-
} catch (err) {
|
|
280
|
-
log2.warn({ err }, "Failed to fetch registry, using cached data");
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
async refreshRegistryIfStale() {
|
|
284
|
-
if (this.isCacheStale()) {
|
|
285
|
-
await this.fetchRegistry();
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
getRegistryAgents() {
|
|
289
|
-
return this.registryAgents;
|
|
290
|
-
}
|
|
291
|
-
getRegistryAgent(registryId) {
|
|
292
|
-
return this.registryAgents.find((a) => a.id === registryId);
|
|
293
|
-
}
|
|
294
|
-
findRegistryAgent(keyOrId) {
|
|
295
|
-
const byId = this.registryAgents.find((a) => a.id === keyOrId);
|
|
296
|
-
if (byId) return byId;
|
|
297
|
-
return this.registryAgents.find((a) => getAgentAlias(a.id) === keyOrId);
|
|
298
|
-
}
|
|
299
|
-
// --- Installed ---
|
|
300
|
-
getInstalled() {
|
|
301
|
-
return Object.values(this.store.getInstalled());
|
|
302
|
-
}
|
|
303
|
-
getInstalledEntries() {
|
|
304
|
-
return this.store.getInstalled();
|
|
305
|
-
}
|
|
306
|
-
getInstalledAgent(key) {
|
|
307
|
-
return this.store.getAgent(key);
|
|
308
|
-
}
|
|
309
|
-
// --- Discovery ---
|
|
310
|
-
getAvailable() {
|
|
311
|
-
const installed = this.store.getInstalled();
|
|
312
|
-
const items = [];
|
|
313
|
-
const seenKeys = /* @__PURE__ */ new Set();
|
|
314
|
-
for (const [key, agent] of Object.entries(installed)) {
|
|
315
|
-
seenKeys.add(key);
|
|
316
|
-
const availability = agent.registryId ? checkDependencies(agent.registryId) : { available: true };
|
|
317
|
-
const registryEntry = agent.registryId ? this.registryAgents.find((a) => a.id === agent.registryId) : void 0;
|
|
318
|
-
items.push({
|
|
319
|
-
key,
|
|
320
|
-
registryId: agent.registryId ?? key,
|
|
321
|
-
name: agent.name,
|
|
322
|
-
version: agent.version,
|
|
323
|
-
description: registryEntry?.description,
|
|
324
|
-
distribution: agent.distribution,
|
|
325
|
-
installed: true,
|
|
326
|
-
available: availability.available,
|
|
327
|
-
missingDeps: availability.missing?.map((m) => m.label)
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
for (const agent of this.registryAgents) {
|
|
331
|
-
const alias = getAgentAlias(agent.id);
|
|
332
|
-
if (seenKeys.has(alias)) continue;
|
|
333
|
-
seenKeys.add(alias);
|
|
334
|
-
const dist = resolveDistribution(agent);
|
|
335
|
-
const availability = checkDependencies(agent.id);
|
|
336
|
-
items.push({
|
|
337
|
-
key: alias,
|
|
338
|
-
registryId: agent.id,
|
|
339
|
-
name: agent.name,
|
|
340
|
-
version: agent.version,
|
|
341
|
-
description: agent.description,
|
|
342
|
-
distribution: dist?.type ?? "binary",
|
|
343
|
-
installed: false,
|
|
344
|
-
available: dist !== null && availability.available,
|
|
345
|
-
missingDeps: availability.missing?.map((m) => m.label)
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
return items;
|
|
349
|
-
}
|
|
350
|
-
checkAvailability(keyOrId) {
|
|
351
|
-
const agent = this.findRegistryAgent(keyOrId);
|
|
352
|
-
if (!agent) return { available: false, reason: "Not found in the agent registry." };
|
|
353
|
-
const dist = resolveDistribution(agent);
|
|
354
|
-
if (!dist) {
|
|
355
|
-
return { available: false, reason: `Not available for your system. Check ${agent.website ?? agent.repository ?? "their website"} for other options.` };
|
|
356
|
-
}
|
|
357
|
-
return checkDependencies(agent.id);
|
|
358
|
-
}
|
|
359
|
-
// --- Install/Uninstall ---
|
|
360
|
-
async install(keyOrId, progress, force) {
|
|
361
|
-
const agent = this.findRegistryAgent(keyOrId);
|
|
362
|
-
if (!agent) {
|
|
363
|
-
const msg = `"${keyOrId}" was not found in the agent registry. Run "openacp agents" to see what's available.`;
|
|
364
|
-
await progress?.onError(msg);
|
|
365
|
-
return { ok: false, agentKey: keyOrId, error: msg };
|
|
366
|
-
}
|
|
367
|
-
const agentKey = getAgentAlias(agent.id);
|
|
368
|
-
if (this.store.hasAgent(agentKey) && !force) {
|
|
369
|
-
const existing = this.store.getAgent(agentKey);
|
|
370
|
-
const msg = `${agent.name} is already installed (v${existing.version}). Use --force to reinstall.`;
|
|
371
|
-
await progress?.onError(msg);
|
|
372
|
-
return { ok: false, agentKey, error: msg };
|
|
373
|
-
}
|
|
374
|
-
return installAgent(agent, this.store, progress);
|
|
375
|
-
}
|
|
376
|
-
async uninstall(key) {
|
|
377
|
-
if (!this.store.hasAgent(key)) {
|
|
378
|
-
return { ok: false, error: `"${key}" is not installed.` };
|
|
379
|
-
}
|
|
380
|
-
await uninstallAgent(key, this.store);
|
|
381
|
-
return { ok: true };
|
|
382
|
-
}
|
|
383
|
-
// --- Resolution (for AgentManager) ---
|
|
384
|
-
resolve(key) {
|
|
385
|
-
const agent = this.store.getAgent(key);
|
|
386
|
-
if (!agent) return void 0;
|
|
387
|
-
return {
|
|
388
|
-
name: key,
|
|
389
|
-
command: agent.command,
|
|
390
|
-
args: agent.args,
|
|
391
|
-
workingDirectory: agent.workingDirectory,
|
|
392
|
-
env: agent.env
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
// --- Internal ---
|
|
396
|
-
/**
|
|
397
|
-
* Enrich installed agents (especially migrated ones) with registry data.
|
|
398
|
-
* Fixes agents that were migrated with version:"unknown", distribution:"custom",
|
|
399
|
-
* or generic names by matching them to registry entries.
|
|
400
|
-
*/
|
|
401
|
-
enrichInstalledFromRegistry() {
|
|
402
|
-
const installed = this.store.getInstalled();
|
|
403
|
-
let changed = false;
|
|
404
|
-
for (const [key, agent] of Object.entries(installed)) {
|
|
405
|
-
const regAgent = agent.registryId ? this.registryAgents.find((a) => a.id === agent.registryId) : this.registryAgents.find((a) => getAgentAlias(a.id) === key);
|
|
406
|
-
if (!regAgent) continue;
|
|
407
|
-
let updated = false;
|
|
408
|
-
if (agent.name !== regAgent.name) {
|
|
409
|
-
agent.name = regAgent.name;
|
|
410
|
-
updated = true;
|
|
411
|
-
}
|
|
412
|
-
if (agent.version === "unknown") {
|
|
413
|
-
agent.version = regAgent.version;
|
|
414
|
-
updated = true;
|
|
415
|
-
}
|
|
416
|
-
if (!agent.registryId) {
|
|
417
|
-
agent.registryId = regAgent.id;
|
|
418
|
-
updated = true;
|
|
419
|
-
}
|
|
420
|
-
if (agent.distribution === "custom") {
|
|
421
|
-
const dist = resolveDistribution(regAgent);
|
|
422
|
-
if (dist) {
|
|
423
|
-
agent.distribution = dist.type;
|
|
424
|
-
updated = true;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
if (updated) {
|
|
428
|
-
this.store.addAgent(key, agent);
|
|
429
|
-
changed = true;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
if (changed) {
|
|
433
|
-
log2.info("Enriched installed agents with registry data");
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
isCacheStale() {
|
|
437
|
-
if (!fs2.existsSync(CACHE_PATH)) return true;
|
|
438
|
-
try {
|
|
439
|
-
const raw = JSON.parse(fs2.readFileSync(CACHE_PATH, "utf-8"));
|
|
440
|
-
const fetchedAt = new Date(raw.fetchedAt).getTime();
|
|
441
|
-
const ttlMs = (raw.ttlHours ?? DEFAULT_TTL_HOURS) * 60 * 60 * 1e3;
|
|
442
|
-
return Date.now() - fetchedAt > ttlMs;
|
|
443
|
-
} catch {
|
|
444
|
-
return true;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
loadRegistryFromCacheOrSnapshot() {
|
|
448
|
-
if (fs2.existsSync(CACHE_PATH)) {
|
|
449
|
-
try {
|
|
450
|
-
const raw = JSON.parse(fs2.readFileSync(CACHE_PATH, "utf-8"));
|
|
451
|
-
if (raw.data?.agents) {
|
|
452
|
-
this.registryAgents = raw.data.agents;
|
|
453
|
-
log2.debug({ count: this.registryAgents.length }, "Loaded registry from cache");
|
|
454
|
-
return;
|
|
455
|
-
}
|
|
456
|
-
} catch {
|
|
457
|
-
log2.warn("Failed to load registry cache");
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
try {
|
|
461
|
-
const candidates = [
|
|
462
|
-
path2.join(import.meta.dirname, "data", "registry-snapshot.json"),
|
|
463
|
-
path2.join(import.meta.dirname, "..", "data", "registry-snapshot.json"),
|
|
464
|
-
path2.join(import.meta.dirname, "..", "..", "data", "registry-snapshot.json")
|
|
465
|
-
];
|
|
466
|
-
for (const candidate of candidates) {
|
|
467
|
-
if (fs2.existsSync(candidate)) {
|
|
468
|
-
const raw = JSON.parse(fs2.readFileSync(candidate, "utf-8"));
|
|
469
|
-
this.registryAgents = raw.agents ?? [];
|
|
470
|
-
log2.debug({ count: this.registryAgents.length }, "Loaded registry from bundled snapshot");
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
log2.warn("No registry data available (no cache, no snapshot)");
|
|
475
|
-
} catch {
|
|
476
|
-
log2.warn("Failed to load bundled registry snapshot");
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
};
|
|
480
|
-
|
|
481
|
-
export {
|
|
482
|
-
AgentCatalog
|
|
483
|
-
};
|
|
484
|
-
//# sourceMappingURL=chunk-UKT3G5IA.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/agent-catalog.ts","../../src/core/agent-installer.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { AgentStore } from \"./agent-store.js\";\nimport { installAgent, uninstallAgent, resolveDistribution } from \"./agent-installer.js\";\nimport { getAgentAlias, checkDependencies } from \"./agent-dependencies.js\";\nimport type {\n AgentDefinition,\n RegistryAgent,\n AgentListItem,\n AvailabilityResult,\n InstallProgress,\n InstallResult,\n InstalledAgent,\n} from \"./types.js\";\nimport { createChildLogger } from \"./log.js\";\n\nconst log = createChildLogger({ module: \"agent-catalog\" });\n\nconst REGISTRY_URL = \"https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json\";\nconst CACHE_PATH = path.join(os.homedir(), \".openacp\", \"registry-cache.json\");\nconst DEFAULT_TTL_HOURS = 24;\n\ninterface RegistryCache {\n fetchedAt: string;\n ttlHours: number;\n data: { agents: RegistryAgent[] };\n}\n\nexport class AgentCatalog {\n private store: AgentStore;\n private registryAgents: RegistryAgent[] = [];\n\n constructor(store?: AgentStore) {\n this.store = store ?? new AgentStore();\n }\n\n load(): void {\n this.store.load();\n this.loadRegistryFromCacheOrSnapshot();\n this.enrichInstalledFromRegistry();\n }\n\n // --- Registry ---\n\n async fetchRegistry(): Promise<void> {\n try {\n log.info(\"Fetching agent registry from CDN...\");\n const response = await fetch(REGISTRY_URL);\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n const data = await response.json() as { agents: RegistryAgent[] };\n this.registryAgents = data.agents ?? [];\n\n const cache: RegistryCache = {\n fetchedAt: new Date().toISOString(),\n ttlHours: DEFAULT_TTL_HOURS,\n data,\n };\n fs.mkdirSync(path.dirname(CACHE_PATH), { recursive: true });\n fs.writeFileSync(CACHE_PATH, JSON.stringify(cache, null, 2));\n log.info({ count: this.registryAgents.length }, \"Registry updated\");\n } catch (err) {\n log.warn({ err }, \"Failed to fetch registry, using cached data\");\n }\n }\n\n async refreshRegistryIfStale(): Promise<void> {\n if (this.isCacheStale()) {\n await this.fetchRegistry();\n }\n }\n\n getRegistryAgents(): RegistryAgent[] {\n return this.registryAgents;\n }\n\n getRegistryAgent(registryId: string): RegistryAgent | undefined {\n return this.registryAgents.find((a) => a.id === registryId);\n }\n\n findRegistryAgent(keyOrId: string): RegistryAgent | undefined {\n const byId = this.registryAgents.find((a) => a.id === keyOrId);\n if (byId) return byId;\n return this.registryAgents.find((a) => getAgentAlias(a.id) === keyOrId);\n }\n\n // --- Installed ---\n\n getInstalled(): InstalledAgent[] {\n return Object.values(this.store.getInstalled());\n }\n\n getInstalledEntries(): Record<string, InstalledAgent> {\n return this.store.getInstalled();\n }\n\n getInstalledAgent(key: string): InstalledAgent | undefined {\n return this.store.getAgent(key);\n }\n\n // --- Discovery ---\n\n getAvailable(): AgentListItem[] {\n const installed = this.store.getInstalled();\n const items: AgentListItem[] = [];\n const seenKeys = new Set<string>();\n\n for (const [key, agent] of Object.entries(installed)) {\n seenKeys.add(key);\n const availability = agent.registryId\n ? checkDependencies(agent.registryId)\n : { available: true };\n const registryEntry = agent.registryId\n ? this.registryAgents.find((a) => a.id === agent.registryId)\n : undefined;\n items.push({\n key,\n registryId: agent.registryId ?? key,\n name: agent.name,\n version: agent.version,\n description: registryEntry?.description,\n distribution: agent.distribution,\n installed: true,\n available: availability.available,\n missingDeps: availability.missing?.map((m) => m.label),\n });\n }\n\n for (const agent of this.registryAgents) {\n const alias = getAgentAlias(agent.id);\n if (seenKeys.has(alias)) continue;\n seenKeys.add(alias);\n\n const dist = resolveDistribution(agent);\n const availability = checkDependencies(agent.id);\n\n items.push({\n key: alias,\n registryId: agent.id,\n name: agent.name,\n version: agent.version,\n description: agent.description,\n distribution: dist?.type ?? \"binary\",\n installed: false,\n available: dist !== null && availability.available,\n missingDeps: availability.missing?.map((m) => m.label),\n });\n }\n\n return items;\n }\n\n checkAvailability(keyOrId: string): AvailabilityResult {\n const agent = this.findRegistryAgent(keyOrId);\n if (!agent) return { available: false, reason: \"Not found in the agent registry.\" };\n\n const dist = resolveDistribution(agent);\n if (!dist) {\n return { available: false, reason: `Not available for your system. Check ${agent.website ?? agent.repository ?? \"their website\"} for other options.` };\n }\n\n return checkDependencies(agent.id);\n }\n\n // --- Install/Uninstall ---\n\n async install(keyOrId: string, progress?: InstallProgress, force?: boolean): Promise<InstallResult> {\n const agent = this.findRegistryAgent(keyOrId);\n if (!agent) {\n const msg = `\"${keyOrId}\" was not found in the agent registry. Run \"openacp agents\" to see what's available.`;\n await progress?.onError(msg);\n return { ok: false, agentKey: keyOrId, error: msg };\n }\n\n const agentKey = getAgentAlias(agent.id);\n if (this.store.hasAgent(agentKey) && !force) {\n const existing = this.store.getAgent(agentKey)!;\n const msg = `${agent.name} is already installed (v${existing.version}). Use --force to reinstall.`;\n await progress?.onError(msg);\n return { ok: false, agentKey, error: msg };\n }\n\n return installAgent(agent, this.store, progress);\n }\n\n async uninstall(key: string): Promise<{ ok: boolean; error?: string }> {\n if (!this.store.hasAgent(key)) {\n return { ok: false, error: `\"${key}\" is not installed.` };\n }\n await uninstallAgent(key, this.store);\n return { ok: true };\n }\n\n // --- Resolution (for AgentManager) ---\n\n resolve(key: string): AgentDefinition | undefined {\n const agent = this.store.getAgent(key);\n if (!agent) return undefined;\n return {\n name: key,\n command: agent.command,\n args: agent.args,\n workingDirectory: agent.workingDirectory,\n env: agent.env,\n };\n }\n\n // --- Internal ---\n\n /**\n * Enrich installed agents (especially migrated ones) with registry data.\n * Fixes agents that were migrated with version:\"unknown\", distribution:\"custom\",\n * or generic names by matching them to registry entries.\n */\n private enrichInstalledFromRegistry(): void {\n const installed = this.store.getInstalled();\n let changed = false;\n\n for (const [key, agent] of Object.entries(installed)) {\n const regAgent = agent.registryId\n ? this.registryAgents.find((a) => a.id === agent.registryId)\n : this.registryAgents.find((a) => getAgentAlias(a.id) === key);\n\n if (!regAgent) continue;\n\n let updated = false;\n\n // Enrich name if it's a generic capitalized key (e.g. \"Claude\" from migration)\n if (agent.name !== regAgent.name) {\n agent.name = regAgent.name;\n updated = true;\n }\n\n // Enrich version if unknown\n if (agent.version === \"unknown\") {\n agent.version = regAgent.version;\n updated = true;\n }\n\n // Enrich registryId if missing\n if (!agent.registryId) {\n agent.registryId = regAgent.id;\n updated = true;\n }\n\n // Enrich distribution from \"custom\" to actual type\n if (agent.distribution === \"custom\") {\n const dist = resolveDistribution(regAgent);\n if (dist) {\n agent.distribution = dist.type;\n updated = true;\n }\n }\n\n if (updated) {\n this.store.addAgent(key, agent);\n changed = true;\n }\n }\n\n if (changed) {\n log.info(\"Enriched installed agents with registry data\");\n }\n }\n\n private isCacheStale(): boolean {\n if (!fs.existsSync(CACHE_PATH)) return true;\n try {\n const raw = JSON.parse(fs.readFileSync(CACHE_PATH, \"utf-8\") as string) as RegistryCache;\n const fetchedAt = new Date(raw.fetchedAt).getTime();\n const ttlMs = (raw.ttlHours ?? DEFAULT_TTL_HOURS) * 60 * 60 * 1000;\n return Date.now() - fetchedAt > ttlMs;\n } catch {\n return true;\n }\n }\n\n private loadRegistryFromCacheOrSnapshot(): void {\n // Try cache first\n if (fs.existsSync(CACHE_PATH)) {\n try {\n const raw = JSON.parse(fs.readFileSync(CACHE_PATH, \"utf-8\") as string) as RegistryCache;\n if (raw.data?.agents) {\n this.registryAgents = raw.data.agents;\n log.debug({ count: this.registryAgents.length }, \"Loaded registry from cache\");\n return;\n }\n } catch {\n log.warn(\"Failed to load registry cache\");\n }\n }\n\n // Fallback: bundled snapshot\n try {\n // Try multiple paths for tsc and tsup builds\n const candidates = [\n path.join(import.meta.dirname, \"data\", \"registry-snapshot.json\"),\n path.join(import.meta.dirname, \"..\", \"data\", \"registry-snapshot.json\"),\n path.join(import.meta.dirname, \"..\", \"..\", \"data\", \"registry-snapshot.json\"),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n const raw = JSON.parse(fs.readFileSync(candidate, \"utf-8\") as string);\n this.registryAgents = raw.agents ?? [];\n log.debug({ count: this.registryAgents.length }, \"Loaded registry from bundled snapshot\");\n return;\n }\n }\n\n log.warn(\"No registry data available (no cache, no snapshot)\");\n } catch {\n log.warn(\"Failed to load bundled registry snapshot\");\n }\n }\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { createChildLogger } from \"./log.js\";\nimport type { InstalledAgent, RegistryAgent, InstallProgress, InstallResult } from \"./types.js\";\nimport { getAgentAlias, checkDependencies, checkRuntimeAvailable, getAgentSetup } from \"./agent-dependencies.js\";\nimport { AgentStore } from \"./agent-store.js\";\n\nconst log = createChildLogger({ module: \"agent-installer\" });\n\nconst AGENTS_DIR = path.join(os.homedir(), \".openacp\", \"agents\");\n\nconst ARCH_MAP: Record<string, string> = {\n arm64: \"aarch64\",\n x64: \"x86_64\",\n};\n\nconst PLATFORM_MAP: Record<string, string> = {\n darwin: \"darwin\",\n linux: \"linux\",\n win32: \"windows\",\n};\n\nexport function getPlatformKey(): string {\n const platform = PLATFORM_MAP[process.platform] ?? process.platform;\n const arch = ARCH_MAP[process.arch] ?? process.arch;\n return `${platform}-${arch}`;\n}\n\nexport type ResolvedDistribution =\n | { type: \"npx\"; package: string; args: string[]; env?: Record<string, string> }\n | { type: \"uvx\"; package: string; args: string[]; env?: Record<string, string> }\n | { type: \"binary\"; archive: string; cmd: string; args: string[]; env?: Record<string, string> };\n\nexport function resolveDistribution(agent: RegistryAgent): ResolvedDistribution | null {\n const dist = agent.distribution;\n\n if (dist.npx) {\n return { type: \"npx\", package: dist.npx.package, args: dist.npx.args ?? [], env: dist.npx.env };\n }\n if (dist.uvx) {\n return { type: \"uvx\", package: dist.uvx.package, args: dist.uvx.args ?? [], env: dist.uvx.env };\n }\n if (dist.binary) {\n const platformKey = getPlatformKey();\n const target = dist.binary[platformKey];\n if (!target) return null;\n return { type: \"binary\", archive: target.archive, cmd: target.cmd, args: target.args ?? [], env: target.env };\n }\n return null;\n}\n\nexport function buildInstalledAgent(\n registryId: string,\n name: string,\n version: string,\n dist: ResolvedDistribution,\n binaryPath?: string,\n): InstalledAgent {\n if (dist.type === \"npx\") {\n // Use latest version: strip pinned version from package name (e.g. @google/gemini-cli@0.34.0 → @google/gemini-cli)\n const npxPackage = stripPackageVersion(dist.package);\n return {\n registryId, name, version, distribution: \"npx\",\n command: \"npx\", args: [npxPackage, ...dist.args],\n env: dist.env ?? {}, installedAt: new Date().toISOString(), binaryPath: null,\n };\n }\n if (dist.type === \"uvx\") {\n // Strip pinned version: \"fast-agent-acp==0.6.6\" → \"fast-agent-acp\", \"minion-code@0.1.44\" → \"minion-code\"\n const uvxPackage = stripPythonPackageVersion(dist.package);\n return {\n registryId, name, version, distribution: \"uvx\",\n command: \"uvx\", args: [uvxPackage, ...dist.args],\n env: dist.env ?? {}, installedAt: new Date().toISOString(), binaryPath: null,\n };\n }\n // binary\n const absCmd = path.resolve(binaryPath!, dist.cmd);\n return {\n registryId, name, version, distribution: \"binary\",\n command: absCmd, args: dist.args,\n env: dist.env ?? {}, installedAt: new Date().toISOString(), binaryPath: binaryPath!,\n };\n}\n\n/**\n * Strip pinned version from npm package name so npx always uses latest.\n * e.g. \"@google/gemini-cli@0.34.0\" → \"@google/gemini-cli\"\n * \"cline@2.9.0\" → \"cline\"\n * \"@scope/pkg\" → \"@scope/pkg\" (no version, unchanged)\n */\nfunction stripPackageVersion(pkg: string): string {\n // Scoped: @scope/name@version → find the second @\n if (pkg.startsWith(\"@\")) {\n const afterScope = pkg.indexOf(\"/\");\n if (afterScope === -1) return pkg;\n const versionAt = pkg.indexOf(\"@\", afterScope + 1);\n return versionAt === -1 ? pkg : pkg.slice(0, versionAt);\n }\n // Unscoped: name@version\n const at = pkg.indexOf(\"@\");\n return at === -1 ? pkg : pkg.slice(0, at);\n}\n\n/**\n * Strip pinned version from Python package name so uvx always uses latest.\n * e.g. \"fast-agent-acp==0.6.6\" → \"fast-agent-acp\"\n * \"minion-code@0.1.44\" → \"minion-code\"\n * \"crow-cli\" → \"crow-cli\" (no version, unchanged)\n */\nfunction stripPythonPackageVersion(pkg: string): string {\n // Python-style: name==version or name>=version\n const pyMatch = pkg.match(/^([^=@><!]+)/);\n if (pyMatch && pkg.includes(\"==\")) return pyMatch[1]!;\n // npm-style @ used in some uvx packages\n const at = pkg.indexOf(\"@\");\n return at === -1 ? pkg : pkg.slice(0, at);\n}\n\nexport async function installAgent(\n agent: RegistryAgent,\n store: AgentStore,\n progress?: InstallProgress,\n): Promise<InstallResult> {\n const agentKey = getAgentAlias(agent.id);\n await progress?.onStart(agent.id, agent.name);\n\n // 1. Check dependencies\n await progress?.onStep(\"Checking requirements...\");\n const depResult = checkDependencies(agent.id);\n if (!depResult.available) {\n const hints = depResult.missing!.map((m) => ` ${m.label}: ${m.installHint}`).join(\"\\n\");\n const msg = `${agent.name} needs some tools installed first:\\n${hints}`;\n await progress?.onError(msg);\n return { ok: false, agentKey, error: msg };\n }\n\n // 2. Resolve distribution\n const dist = resolveDistribution(agent);\n if (!dist) {\n const platformKey = getPlatformKey();\n const msg = `${agent.name} is not available for your system (${platformKey}). Check their website for other install options.`;\n await progress?.onError(msg);\n return { ok: false, agentKey, error: msg };\n }\n\n // 3. Check runtime\n if (dist.type === \"uvx\" && !checkRuntimeAvailable(\"uvx\")) {\n const msg = `${agent.name} requires Python's uvx tool.\\nInstall it with: pip install uv`;\n await progress?.onError(msg, \"pip install uv\");\n return { ok: false, agentKey, error: msg, hint: \"pip install uv\" };\n }\n\n // 4. Install based on type\n let binaryPath: string | undefined;\n\n if (dist.type === \"binary\") {\n try {\n binaryPath = await downloadAndExtract(agent.id, dist.archive, progress);\n } catch (err) {\n const msg = `Failed to download ${agent.name}. Please try again or install manually.`;\n await progress?.onError(msg);\n return { ok: false, agentKey, error: msg };\n }\n } else {\n await progress?.onStep(\"Setting up... (will download on first use)\");\n }\n\n // 5. Save to store\n const installed = buildInstalledAgent(agent.id, agent.name, agent.version, dist, binaryPath);\n store.addAgent(agentKey, installed);\n\n const setup = getAgentSetup(agent.id);\n await progress?.onSuccess(agent.name);\n return { ok: true, agentKey, setupSteps: setup?.setupSteps };\n}\n\nasync function downloadAndExtract(\n agentId: string,\n archiveUrl: string,\n progress?: InstallProgress,\n): Promise<string> {\n const destDir = path.join(AGENTS_DIR, agentId);\n fs.mkdirSync(destDir, { recursive: true });\n\n await progress?.onStep(\"Downloading...\");\n log.info({ agentId, url: archiveUrl }, \"Downloading agent binary\");\n\n const response = await fetch(archiveUrl);\n if (!response.ok) {\n throw new Error(`Download failed: ${response.status} ${response.statusText}`);\n }\n\n const contentLength = Number(response.headers.get(\"content-length\") || 0);\n const buffer = await readResponseWithProgress(response, contentLength, progress);\n\n await progress?.onStep(\"Extracting...\");\n\n if (archiveUrl.endsWith(\".zip\")) {\n await extractZip(buffer, destDir);\n } else {\n await extractTarGz(buffer, destDir);\n }\n\n await progress?.onStep(\"Ready!\");\n return destDir;\n}\n\nasync function readResponseWithProgress(\n response: Response,\n contentLength: number,\n progress?: InstallProgress,\n): Promise<Buffer> {\n if (!response.body || contentLength === 0) {\n const arrayBuffer = await response.arrayBuffer();\n return Buffer.from(arrayBuffer);\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let received = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n received += value.length;\n if (contentLength > 0) {\n await progress?.onDownloadProgress(Math.round((received / contentLength) * 100));\n }\n }\n\n return Buffer.concat(chunks);\n}\n\nfunction validateExtractedPaths(destDir: string): void {\n const realDest = fs.realpathSync(destDir);\n const entries = fs.readdirSync(destDir, { recursive: true, withFileTypes: true });\n for (const entry of entries) {\n // Node <20.12 uses `path`, >=20.12 uses `parentPath` on Dirent with recursive readdir\n const dirent = entry as fs.Dirent & { parentPath?: string; path?: string };\n const parentPath = dirent.parentPath ?? dirent.path ?? destDir;\n const fullPath = path.join(parentPath, entry.name);\n let realPath: string;\n try {\n realPath = fs.realpathSync(fullPath);\n } catch {\n // Broken symlink — check where it points\n const linkTarget = fs.readlinkSync(fullPath);\n realPath = path.resolve(path.dirname(fullPath), linkTarget);\n }\n if (!realPath.startsWith(realDest + path.sep) && realPath !== realDest) {\n fs.rmSync(destDir, { recursive: true, force: true });\n throw new Error(`Archive contains unsafe path: ${entry.name}`);\n }\n }\n}\n\nasync function extractTarGz(buffer: Buffer, destDir: string): Promise<void> {\n const { execFileSync } = await import(\"node:child_process\");\n const tmpFile = path.join(destDir, \"_archive.tar.gz\");\n fs.writeFileSync(tmpFile, buffer);\n try {\n execFileSync(\"tar\", [\"xzf\", tmpFile, \"-C\", destDir], { stdio: \"pipe\" });\n } finally {\n fs.unlinkSync(tmpFile);\n }\n validateExtractedPaths(destDir);\n}\n\nasync function extractZip(buffer: Buffer, destDir: string): Promise<void> {\n const { execFileSync } = await import(\"node:child_process\");\n const tmpFile = path.join(destDir, \"_archive.zip\");\n fs.writeFileSync(tmpFile, buffer);\n try {\n execFileSync(\"unzip\", [\"-o\", tmpFile, \"-d\", destDir], { stdio: \"pipe\" });\n } finally {\n fs.unlinkSync(tmpFile);\n }\n validateExtractedPaths(destDir);\n}\n\nexport async function uninstallAgent(\n agentKey: string,\n store: AgentStore,\n): Promise<void> {\n const agent = store.getAgent(agentKey);\n if (!agent) return;\n\n if (agent.binaryPath && fs.existsSync(agent.binaryPath)) {\n fs.rmSync(agent.binaryPath, { recursive: true, force: true });\n log.info({ agentKey, binaryPath: agent.binaryPath }, \"Deleted agent binary\");\n }\n\n store.removeAgent(agentKey);\n}\n"],"mappings":"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","names":["fs","path","os","log"]}
|
package/dist/chunk-V5GZQEIY.js
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
commandExists
|
|
3
|
-
} from "./chunk-JKBFUAJK.js";
|
|
4
|
-
import {
|
|
5
|
-
createChildLogger
|
|
6
|
-
} from "./chunk-GAK6PIBW.js";
|
|
7
|
-
|
|
8
|
-
// src/core/install-binary.ts
|
|
9
|
-
import fs from "fs";
|
|
10
|
-
import path from "path";
|
|
11
|
-
import https from "https";
|
|
12
|
-
import os from "os";
|
|
13
|
-
import { execSync } from "child_process";
|
|
14
|
-
var log = createChildLogger({ module: "binary-installer" });
|
|
15
|
-
var BIN_DIR = path.join(os.homedir(), ".openacp", "bin");
|
|
16
|
-
var IS_WINDOWS = os.platform() === "win32";
|
|
17
|
-
function downloadFile(url, dest) {
|
|
18
|
-
return new Promise((resolve, reject) => {
|
|
19
|
-
const file = fs.createWriteStream(dest);
|
|
20
|
-
const cleanup = () => {
|
|
21
|
-
try {
|
|
22
|
-
if (fs.existsSync(dest)) fs.unlinkSync(dest);
|
|
23
|
-
} catch {
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
https.get(url, (response) => {
|
|
27
|
-
if (response.statusCode === 301 || response.statusCode === 302) {
|
|
28
|
-
file.close(() => {
|
|
29
|
-
cleanup();
|
|
30
|
-
downloadFile(response.headers.location, dest).then(resolve).catch(reject);
|
|
31
|
-
});
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
if (response.statusCode !== 200) {
|
|
35
|
-
file.close(() => {
|
|
36
|
-
cleanup();
|
|
37
|
-
reject(new Error(`Download failed with status ${response.statusCode}`));
|
|
38
|
-
});
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
response.pipe(file);
|
|
42
|
-
file.on("finish", () => file.close(() => resolve(dest)));
|
|
43
|
-
file.on("error", (err) => {
|
|
44
|
-
file.close(() => {
|
|
45
|
-
cleanup();
|
|
46
|
-
reject(err);
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
}).on("error", (err) => {
|
|
50
|
-
file.close(() => {
|
|
51
|
-
cleanup();
|
|
52
|
-
reject(err);
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
function getDownloadUrl(spec) {
|
|
58
|
-
const platform = os.platform();
|
|
59
|
-
const arch = os.arch();
|
|
60
|
-
const mapping = spec.platforms[platform];
|
|
61
|
-
if (!mapping) throw new Error(`${spec.name}: unsupported platform ${platform}`);
|
|
62
|
-
const binary = mapping[arch];
|
|
63
|
-
if (!binary) throw new Error(`${spec.name}: unsupported architecture ${arch} for ${platform}`);
|
|
64
|
-
return `${spec.githubBaseUrl}/${binary}`;
|
|
65
|
-
}
|
|
66
|
-
async function ensureBinary(spec) {
|
|
67
|
-
const binName = IS_WINDOWS ? `${spec.name}.exe` : spec.name;
|
|
68
|
-
const binPath = path.join(BIN_DIR, binName);
|
|
69
|
-
if (commandExists(spec.name)) {
|
|
70
|
-
log.debug({ name: spec.name }, "Found in PATH");
|
|
71
|
-
return spec.name;
|
|
72
|
-
}
|
|
73
|
-
if (fs.existsSync(binPath)) {
|
|
74
|
-
if (!IS_WINDOWS) fs.chmodSync(binPath, "755");
|
|
75
|
-
log.debug({ name: spec.name, path: binPath }, "Found in ~/.openacp/bin");
|
|
76
|
-
return binPath;
|
|
77
|
-
}
|
|
78
|
-
log.info({ name: spec.name }, "Not found, downloading from GitHub...");
|
|
79
|
-
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
80
|
-
const url = getDownloadUrl(spec);
|
|
81
|
-
const isArchive = spec.isArchive?.(url) ?? false;
|
|
82
|
-
const downloadDest = isArchive ? path.join(BIN_DIR, `${spec.name}.tgz`) : binPath;
|
|
83
|
-
await downloadFile(url, downloadDest);
|
|
84
|
-
if (isArchive) {
|
|
85
|
-
execSync(`tar -xzf "${downloadDest}" -C "${BIN_DIR}"`, { stdio: "pipe" });
|
|
86
|
-
try {
|
|
87
|
-
fs.unlinkSync(downloadDest);
|
|
88
|
-
} catch {
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
if (!IS_WINDOWS) {
|
|
92
|
-
fs.chmodSync(binPath, "755");
|
|
93
|
-
}
|
|
94
|
-
log.info({ name: spec.name, path: binPath }, "Installed successfully");
|
|
95
|
-
return binPath;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export {
|
|
99
|
-
ensureBinary
|
|
100
|
-
};
|
|
101
|
-
//# sourceMappingURL=chunk-V5GZQEIY.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/install-binary.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport https from 'node:https'\nimport os from 'node:os'\nimport { execSync } from 'node:child_process'\nimport { createChildLogger } from './log.js'\nimport { commandExists } from './agent-dependencies.js'\n\nconst log = createChildLogger({ module: 'binary-installer' })\n\nconst BIN_DIR = path.join(os.homedir(), '.openacp', 'bin')\nconst IS_WINDOWS = os.platform() === 'win32'\n\nexport interface BinarySpec {\n name: string\n /** GitHub base URL for releases, e.g. \"https://github.com/jqlang/jq/releases/latest/download\" */\n githubBaseUrl: string\n /** Platform → arch → filename mapping */\n platforms: Record<string, Record<string, string>>\n /** If true, downloaded file is a .tgz archive that needs extraction */\n isArchive?: (url: string) => boolean\n}\n\nfunction downloadFile(url: string, dest: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const file = fs.createWriteStream(dest)\n\n const cleanup = () => {\n try { if (fs.existsSync(dest)) fs.unlinkSync(dest) } catch { /* ignore */ }\n }\n\n https.get(url, (response) => {\n if (response.statusCode === 301 || response.statusCode === 302) {\n file.close(() => {\n cleanup()\n downloadFile(response.headers.location!, dest).then(resolve).catch(reject)\n })\n return\n }\n\n if (response.statusCode !== 200) {\n file.close(() => {\n cleanup()\n reject(new Error(`Download failed with status ${response.statusCode}`))\n })\n return\n }\n\n response.pipe(file)\n file.on('finish', () => file.close(() => resolve(dest)))\n file.on('error', (err) => {\n file.close(() => {\n cleanup()\n reject(err)\n })\n })\n }).on('error', (err) => {\n file.close(() => {\n cleanup()\n reject(err)\n })\n })\n })\n}\n\nfunction getDownloadUrl(spec: BinarySpec): string {\n const platform = os.platform()\n const arch = os.arch()\n const mapping = spec.platforms[platform]\n if (!mapping) throw new Error(`${spec.name}: unsupported platform ${platform}`)\n const binary = mapping[arch]\n if (!binary) throw new Error(`${spec.name}: unsupported architecture ${arch} for ${platform}`)\n return `${spec.githubBaseUrl}/${binary}`\n}\n\n/**\n * Ensure a binary is available.\n * 1. Check PATH first (respects user's system install)\n * 2. Check ~/.openacp/bin/\n * 3. Download from GitHub releases\n */\nexport async function ensureBinary(spec: BinarySpec): Promise<string> {\n const binName = IS_WINDOWS ? `${spec.name}.exe` : spec.name\n const binPath = path.join(BIN_DIR, binName)\n\n // 1. Check PATH first\n if (commandExists(spec.name)) {\n log.debug({ name: spec.name }, 'Found in PATH')\n return spec.name\n }\n\n // 2. Check our bin directory\n if (fs.existsSync(binPath)) {\n if (!IS_WINDOWS) fs.chmodSync(binPath, '755')\n log.debug({ name: spec.name, path: binPath }, 'Found in ~/.openacp/bin')\n return binPath\n }\n\n // 3. Download\n log.info({ name: spec.name }, 'Not found, downloading from GitHub...')\n fs.mkdirSync(BIN_DIR, { recursive: true })\n\n const url = getDownloadUrl(spec)\n const isArchive = spec.isArchive?.(url) ?? false\n const downloadDest = isArchive ? path.join(BIN_DIR, `${spec.name}.tgz`) : binPath\n\n await downloadFile(url, downloadDest)\n\n if (isArchive) {\n execSync(`tar -xzf \"${downloadDest}\" -C \"${BIN_DIR}\"`, { stdio: 'pipe' })\n try { fs.unlinkSync(downloadDest) } catch { /* ignore */ }\n }\n\n if (!IS_WINDOWS) {\n fs.chmodSync(binPath, '755')\n }\n\n log.info({ name: spec.name, path: binPath }, 'Installed successfully')\n return binPath\n}\n"],"mappings":"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","names":[]}
|