@openacp/cli 0.4.11 → 0.5.0

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.
Files changed (66) hide show
  1. package/README.md +40 -2
  2. package/dist/agent-catalog-4IAJ7HEG.js +10 -0
  3. package/dist/agent-registry-B5YAMA4T.js +8 -0
  4. package/dist/agent-store-ZBXGOFPH.js +8 -0
  5. package/dist/chunk-5HGXUCMX.js +83 -0
  6. package/dist/chunk-5HGXUCMX.js.map +1 -0
  7. package/dist/{chunk-W7QQA6CW.js → chunk-D73LCTPF.js} +73 -35
  8. package/dist/chunk-D73LCTPF.js.map +1 -0
  9. package/dist/{chunk-66RVSUAR.js → chunk-FWN3UIRT.js} +465 -86
  10. package/dist/chunk-FWN3UIRT.js.map +1 -0
  11. package/dist/{chunk-3DIPXFZJ.js → chunk-IRGYTNLP.js} +2 -2
  12. package/dist/{chunk-WYZFGHHI.js → chunk-JRF4G4X7.js} +60 -24
  13. package/dist/chunk-JRF4G4X7.js.map +1 -0
  14. package/dist/{chunk-FKOARMAE.js → chunk-LAFKARV3.js} +3 -3
  15. package/dist/chunk-NAMYZIS5.js +1 -0
  16. package/dist/{chunk-ZW444AQY.js → chunk-NDR5JCS7.js} +2 -2
  17. package/dist/chunk-S3DRLJPM.js +422 -0
  18. package/dist/chunk-S3DRLJPM.js.map +1 -0
  19. package/dist/chunk-UG6X672R.js +90 -0
  20. package/dist/chunk-UG6X672R.js.map +1 -0
  21. package/dist/{chunk-YRJEZD7R.js → chunk-VBEWSWVL.js} +2 -2
  22. package/dist/chunk-XJJ7LPXP.js +85 -0
  23. package/dist/chunk-XJJ7LPXP.js.map +1 -0
  24. package/dist/{chunk-C33LTDZV.js → chunk-Z46LGZ7R.js} +21 -8
  25. package/dist/chunk-Z46LGZ7R.js.map +1 -0
  26. package/dist/cli.js +190 -18
  27. package/dist/cli.js.map +1 -1
  28. package/dist/{config-XURP6B3S.js → config-PCPIBPUA.js} +2 -2
  29. package/dist/config-editor-5L7AJ5AF.js +12 -0
  30. package/dist/{config-registry-OGX4YM2U.js → config-registry-SNKA2EH2.js} +2 -2
  31. package/dist/{daemon-GWJM2S4A.js → daemon-JZLFRUW6.js} +3 -3
  32. package/dist/data/registry-snapshot.json +876 -0
  33. package/dist/doctor-N2HKKUUQ.js +9 -0
  34. package/dist/doctor-N2HKKUUQ.js.map +1 -0
  35. package/dist/index.d.ts +137 -17
  36. package/dist/index.js +19 -10
  37. package/dist/{main-2QKD2EI2.js → main-37GLOJ7G.js} +18 -15
  38. package/dist/{main-2QKD2EI2.js.map → main-37GLOJ7G.js.map} +1 -1
  39. package/dist/{menu-CARRTW2F.js → menu-6RCPBVGQ.js} +2 -4
  40. package/dist/menu-6RCPBVGQ.js.map +1 -0
  41. package/dist/{setup-TTOL7XAN.js → setup-QAS3QW3M.js} +4 -3
  42. package/dist/setup-QAS3QW3M.js.map +1 -0
  43. package/package.json +10 -2
  44. package/dist/agent-registry-7HC6D4CH.js +0 -7
  45. package/dist/chunk-66RVSUAR.js.map +0 -1
  46. package/dist/chunk-BGKQHQB4.js +0 -276
  47. package/dist/chunk-BGKQHQB4.js.map +0 -1
  48. package/dist/chunk-C33LTDZV.js.map +0 -1
  49. package/dist/chunk-VA2M52CM.js +0 -15
  50. package/dist/chunk-VA2M52CM.js.map +0 -1
  51. package/dist/chunk-W7QQA6CW.js.map +0 -1
  52. package/dist/chunk-WYZFGHHI.js.map +0 -1
  53. package/dist/config-editor-AALY3URF.js +0 -11
  54. package/dist/doctor-X477CVZN.js +0 -9
  55. /package/dist/{agent-registry-7HC6D4CH.js.map → agent-catalog-4IAJ7HEG.js.map} +0 -0
  56. /package/dist/{config-XURP6B3S.js.map → agent-registry-B5YAMA4T.js.map} +0 -0
  57. /package/dist/{config-editor-AALY3URF.js.map → agent-store-ZBXGOFPH.js.map} +0 -0
  58. /package/dist/{chunk-3DIPXFZJ.js.map → chunk-IRGYTNLP.js.map} +0 -0
  59. /package/dist/{chunk-FKOARMAE.js.map → chunk-LAFKARV3.js.map} +0 -0
  60. /package/dist/{config-registry-OGX4YM2U.js.map → chunk-NAMYZIS5.js.map} +0 -0
  61. /package/dist/{chunk-ZW444AQY.js.map → chunk-NDR5JCS7.js.map} +0 -0
  62. /package/dist/{chunk-YRJEZD7R.js.map → chunk-VBEWSWVL.js.map} +0 -0
  63. /package/dist/{daemon-GWJM2S4A.js.map → config-PCPIBPUA.js.map} +0 -0
  64. /package/dist/{doctor-X477CVZN.js.map → config-editor-5L7AJ5AF.js.map} +0 -0
  65. /package/dist/{menu-CARRTW2F.js.map → config-registry-SNKA2EH2.js.map} +0 -0
  66. /package/dist/{setup-TTOL7XAN.js.map → daemon-JZLFRUW6.js.map} +0 -0
@@ -0,0 +1,422 @@
1
+ import {
2
+ AgentStore
3
+ } from "./chunk-5HGXUCMX.js";
4
+ import {
5
+ checkDependencies,
6
+ checkRuntimeAvailable,
7
+ getAgentAlias
8
+ } from "./chunk-XJJ7LPXP.js";
9
+ import {
10
+ createChildLogger
11
+ } from "./chunk-ESOPMQAY.js";
12
+
13
+ // src/core/agent-catalog.ts
14
+ import * as fs2 from "fs";
15
+ import * as path2 from "path";
16
+ import * as os2 from "os";
17
+
18
+ // src/core/agent-installer.ts
19
+ import * as fs from "fs";
20
+ import * as path from "path";
21
+ import * as os from "os";
22
+ var log = createChildLogger({ module: "agent-installer" });
23
+ var AGENTS_DIR = path.join(os.homedir(), ".openacp", "agents");
24
+ var ARCH_MAP = {
25
+ arm64: "aarch64",
26
+ x64: "x86_64"
27
+ };
28
+ var PLATFORM_MAP = {
29
+ darwin: "darwin",
30
+ linux: "linux",
31
+ win32: "windows"
32
+ };
33
+ function getPlatformKey() {
34
+ const platform = PLATFORM_MAP[process.platform] ?? process.platform;
35
+ const arch = ARCH_MAP[process.arch] ?? process.arch;
36
+ return `${platform}-${arch}`;
37
+ }
38
+ function resolveDistribution(agent) {
39
+ const dist = agent.distribution;
40
+ if (dist.npx) {
41
+ return { type: "npx", package: dist.npx.package, args: dist.npx.args ?? [], env: dist.npx.env };
42
+ }
43
+ if (dist.uvx) {
44
+ return { type: "uvx", package: dist.uvx.package, args: dist.uvx.args ?? [], env: dist.uvx.env };
45
+ }
46
+ if (dist.binary) {
47
+ const platformKey = getPlatformKey();
48
+ const target = dist.binary[platformKey];
49
+ if (!target) return null;
50
+ return { type: "binary", archive: target.archive, cmd: target.cmd, args: target.args ?? [], env: target.env };
51
+ }
52
+ return null;
53
+ }
54
+ function buildInstalledAgent(registryId, name, version, dist, binaryPath) {
55
+ if (dist.type === "npx") {
56
+ return {
57
+ registryId,
58
+ name,
59
+ version,
60
+ distribution: "npx",
61
+ command: "npx",
62
+ args: [dist.package, ...dist.args],
63
+ env: dist.env ?? {},
64
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
65
+ binaryPath: null
66
+ };
67
+ }
68
+ if (dist.type === "uvx") {
69
+ return {
70
+ registryId,
71
+ name,
72
+ version,
73
+ distribution: "uvx",
74
+ command: "uvx",
75
+ args: [dist.package, ...dist.args],
76
+ env: dist.env ?? {},
77
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
78
+ binaryPath: null
79
+ };
80
+ }
81
+ const absCmd = path.resolve(binaryPath, dist.cmd);
82
+ return {
83
+ registryId,
84
+ name,
85
+ version,
86
+ distribution: "binary",
87
+ command: absCmd,
88
+ args: dist.args,
89
+ env: dist.env ?? {},
90
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
91
+ binaryPath
92
+ };
93
+ }
94
+ async function installAgent(agent, store, progress) {
95
+ const agentKey = getAgentAlias(agent.id);
96
+ await progress?.onStart(agent.id, agent.name);
97
+ await progress?.onStep("Checking requirements...");
98
+ const depResult = checkDependencies(agent.id);
99
+ if (!depResult.available) {
100
+ const hints = depResult.missing.map((m) => ` ${m.label}: ${m.installHint}`).join("\n");
101
+ const msg = `${agent.name} needs some tools installed first:
102
+ ${hints}`;
103
+ await progress?.onError(msg);
104
+ return { ok: false, agentKey, error: msg };
105
+ }
106
+ const dist = resolveDistribution(agent);
107
+ if (!dist) {
108
+ const platformKey = getPlatformKey();
109
+ const msg = `${agent.name} is not available for your system (${platformKey}). Check their website for other install options.`;
110
+ await progress?.onError(msg);
111
+ return { ok: false, agentKey, error: msg };
112
+ }
113
+ if (dist.type === "uvx" && !checkRuntimeAvailable("uvx")) {
114
+ const msg = `${agent.name} requires Python's uvx tool.
115
+ Install it with: pip install uv`;
116
+ await progress?.onError(msg, "pip install uv");
117
+ return { ok: false, agentKey, error: msg, hint: "pip install uv" };
118
+ }
119
+ let binaryPath;
120
+ if (dist.type === "binary") {
121
+ try {
122
+ binaryPath = await downloadAndExtract(agent.id, dist.archive, progress);
123
+ } catch (err) {
124
+ const msg = `Failed to download ${agent.name}. Please try again or install manually.`;
125
+ await progress?.onError(msg);
126
+ return { ok: false, agentKey, error: msg };
127
+ }
128
+ } else {
129
+ await progress?.onStep("Setting up... (will download on first use)");
130
+ }
131
+ const installed = buildInstalledAgent(agent.id, agent.name, agent.version, dist, binaryPath);
132
+ store.addAgent(agentKey, installed);
133
+ await progress?.onSuccess(agent.name);
134
+ return { ok: true, agentKey };
135
+ }
136
+ async function downloadAndExtract(agentId, archiveUrl, progress) {
137
+ const destDir = path.join(AGENTS_DIR, agentId);
138
+ fs.mkdirSync(destDir, { recursive: true });
139
+ await progress?.onStep("Downloading...");
140
+ log.info({ agentId, url: archiveUrl }, "Downloading agent binary");
141
+ const response = await fetch(archiveUrl);
142
+ if (!response.ok) {
143
+ throw new Error(`Download failed: ${response.status} ${response.statusText}`);
144
+ }
145
+ const contentLength = Number(response.headers.get("content-length") || 0);
146
+ const buffer = await readResponseWithProgress(response, contentLength, progress);
147
+ await progress?.onStep("Extracting...");
148
+ if (archiveUrl.endsWith(".zip")) {
149
+ await extractZip(buffer, destDir);
150
+ } else {
151
+ await extractTarGz(buffer, destDir);
152
+ }
153
+ await progress?.onStep("Ready!");
154
+ return destDir;
155
+ }
156
+ async function readResponseWithProgress(response, contentLength, progress) {
157
+ if (!response.body || contentLength === 0) {
158
+ const arrayBuffer = await response.arrayBuffer();
159
+ return Buffer.from(arrayBuffer);
160
+ }
161
+ const reader = response.body.getReader();
162
+ const chunks = [];
163
+ let received = 0;
164
+ while (true) {
165
+ const { done, value } = await reader.read();
166
+ if (done) break;
167
+ chunks.push(value);
168
+ received += value.length;
169
+ if (contentLength > 0) {
170
+ await progress?.onDownloadProgress(Math.round(received / contentLength * 100));
171
+ }
172
+ }
173
+ return Buffer.concat(chunks);
174
+ }
175
+ function validateExtractedPaths(destDir) {
176
+ const realDest = fs.realpathSync(destDir);
177
+ const entries = fs.readdirSync(destDir, { recursive: true, withFileTypes: true });
178
+ for (const entry of entries) {
179
+ const parentPath = entry.parentPath ?? entry.path;
180
+ const fullPath = path.join(parentPath, entry.name);
181
+ let realPath;
182
+ try {
183
+ realPath = fs.realpathSync(fullPath);
184
+ } catch {
185
+ const linkTarget = fs.readlinkSync(fullPath);
186
+ realPath = path.resolve(path.dirname(fullPath), linkTarget);
187
+ }
188
+ if (!realPath.startsWith(realDest + path.sep) && realPath !== realDest) {
189
+ fs.rmSync(destDir, { recursive: true, force: true });
190
+ throw new Error(`Archive contains unsafe path: ${entry.name}`);
191
+ }
192
+ }
193
+ }
194
+ async function extractTarGz(buffer, destDir) {
195
+ const { execFileSync } = await import("child_process");
196
+ const tmpFile = path.join(destDir, "_archive.tar.gz");
197
+ fs.writeFileSync(tmpFile, buffer);
198
+ try {
199
+ execFileSync("tar", ["xzf", tmpFile, "-C", destDir], { stdio: "pipe" });
200
+ } finally {
201
+ fs.unlinkSync(tmpFile);
202
+ }
203
+ validateExtractedPaths(destDir);
204
+ }
205
+ async function extractZip(buffer, destDir) {
206
+ const { execFileSync } = await import("child_process");
207
+ const tmpFile = path.join(destDir, "_archive.zip");
208
+ fs.writeFileSync(tmpFile, buffer);
209
+ try {
210
+ execFileSync("unzip", ["-o", tmpFile, "-d", destDir], { stdio: "pipe" });
211
+ } finally {
212
+ fs.unlinkSync(tmpFile);
213
+ }
214
+ validateExtractedPaths(destDir);
215
+ }
216
+ async function uninstallAgent(agentKey, store) {
217
+ const agent = store.getAgent(agentKey);
218
+ if (!agent) return;
219
+ if (agent.binaryPath && fs.existsSync(agent.binaryPath)) {
220
+ fs.rmSync(agent.binaryPath, { recursive: true, force: true });
221
+ log.info({ agentKey, binaryPath: agent.binaryPath }, "Deleted agent binary");
222
+ }
223
+ store.removeAgent(agentKey);
224
+ }
225
+
226
+ // src/core/agent-catalog.ts
227
+ var log2 = createChildLogger({ module: "agent-catalog" });
228
+ var REGISTRY_URL = "https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json";
229
+ var CACHE_PATH = path2.join(os2.homedir(), ".openacp", "registry-cache.json");
230
+ var DEFAULT_TTL_HOURS = 24;
231
+ var AgentCatalog = class {
232
+ store;
233
+ registryAgents = [];
234
+ constructor(store) {
235
+ this.store = store ?? new AgentStore();
236
+ }
237
+ load() {
238
+ this.store.load();
239
+ this.loadRegistryFromCacheOrSnapshot();
240
+ }
241
+ // --- Registry ---
242
+ async fetchRegistry() {
243
+ try {
244
+ log2.info("Fetching agent registry from CDN...");
245
+ const response = await fetch(REGISTRY_URL);
246
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
247
+ const data = await response.json();
248
+ this.registryAgents = data.agents ?? [];
249
+ const cache = {
250
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
251
+ ttlHours: DEFAULT_TTL_HOURS,
252
+ data
253
+ };
254
+ fs2.mkdirSync(path2.dirname(CACHE_PATH), { recursive: true });
255
+ fs2.writeFileSync(CACHE_PATH, JSON.stringify(cache, null, 2));
256
+ log2.info({ count: this.registryAgents.length }, "Registry updated");
257
+ } catch (err) {
258
+ log2.warn({ err }, "Failed to fetch registry, using cached data");
259
+ }
260
+ }
261
+ async refreshRegistryIfStale() {
262
+ if (this.isCacheStale()) {
263
+ await this.fetchRegistry();
264
+ }
265
+ }
266
+ getRegistryAgents() {
267
+ return this.registryAgents;
268
+ }
269
+ getRegistryAgent(registryId) {
270
+ return this.registryAgents.find((a) => a.id === registryId);
271
+ }
272
+ findRegistryAgent(keyOrId) {
273
+ const byId = this.registryAgents.find((a) => a.id === keyOrId);
274
+ if (byId) return byId;
275
+ return this.registryAgents.find((a) => getAgentAlias(a.id) === keyOrId);
276
+ }
277
+ // --- Installed ---
278
+ getInstalled() {
279
+ return Object.values(this.store.getInstalled());
280
+ }
281
+ getInstalledEntries() {
282
+ return this.store.getInstalled();
283
+ }
284
+ getInstalledAgent(key) {
285
+ return this.store.getAgent(key);
286
+ }
287
+ // --- Discovery ---
288
+ getAvailable() {
289
+ const installed = this.store.getInstalled();
290
+ const items = [];
291
+ const seenKeys = /* @__PURE__ */ new Set();
292
+ for (const [key, agent] of Object.entries(installed)) {
293
+ seenKeys.add(key);
294
+ const availability = agent.registryId ? checkDependencies(agent.registryId) : { available: true };
295
+ const registryEntry = agent.registryId ? this.registryAgents.find((a) => a.id === agent.registryId) : void 0;
296
+ items.push({
297
+ key,
298
+ registryId: agent.registryId ?? key,
299
+ name: agent.name,
300
+ version: agent.version,
301
+ description: registryEntry?.description,
302
+ distribution: agent.distribution,
303
+ installed: true,
304
+ available: availability.available,
305
+ missingDeps: availability.missing?.map((m) => m.label)
306
+ });
307
+ }
308
+ for (const agent of this.registryAgents) {
309
+ const alias = getAgentAlias(agent.id);
310
+ if (seenKeys.has(alias)) continue;
311
+ seenKeys.add(alias);
312
+ const dist = resolveDistribution(agent);
313
+ const availability = checkDependencies(agent.id);
314
+ items.push({
315
+ key: alias,
316
+ registryId: agent.id,
317
+ name: agent.name,
318
+ version: agent.version,
319
+ description: agent.description,
320
+ distribution: dist?.type ?? "binary",
321
+ installed: false,
322
+ available: dist !== null && availability.available,
323
+ missingDeps: availability.missing?.map((m) => m.label)
324
+ });
325
+ }
326
+ return items;
327
+ }
328
+ checkAvailability(keyOrId) {
329
+ const agent = this.findRegistryAgent(keyOrId);
330
+ if (!agent) return { available: false, reason: "Not found in the agent registry." };
331
+ const dist = resolveDistribution(agent);
332
+ if (!dist) {
333
+ return { available: false, reason: `Not available for your system. Check ${agent.website ?? agent.repository ?? "their website"} for other options.` };
334
+ }
335
+ return checkDependencies(agent.id);
336
+ }
337
+ // --- Install/Uninstall ---
338
+ async install(keyOrId, progress, force) {
339
+ const agent = this.findRegistryAgent(keyOrId);
340
+ if (!agent) {
341
+ const msg = `"${keyOrId}" was not found in the agent registry. Run "openacp agents" to see what's available.`;
342
+ await progress?.onError(msg);
343
+ return { ok: false, agentKey: keyOrId, error: msg };
344
+ }
345
+ const agentKey = getAgentAlias(agent.id);
346
+ if (this.store.hasAgent(agentKey) && !force) {
347
+ const existing = this.store.getAgent(agentKey);
348
+ const msg = `${agent.name} is already installed (v${existing.version}). Use --force to reinstall.`;
349
+ await progress?.onError(msg);
350
+ return { ok: false, agentKey, error: msg };
351
+ }
352
+ return installAgent(agent, this.store, progress);
353
+ }
354
+ async uninstall(key) {
355
+ if (!this.store.hasAgent(key)) {
356
+ return { ok: false, error: `"${key}" is not installed.` };
357
+ }
358
+ await uninstallAgent(key, this.store);
359
+ return { ok: true };
360
+ }
361
+ // --- Resolution (for AgentManager) ---
362
+ resolve(key) {
363
+ const agent = this.store.getAgent(key);
364
+ if (!agent) return void 0;
365
+ return {
366
+ name: key,
367
+ command: agent.command,
368
+ args: agent.args,
369
+ workingDirectory: agent.workingDirectory,
370
+ env: agent.env
371
+ };
372
+ }
373
+ // --- Internal ---
374
+ isCacheStale() {
375
+ if (!fs2.existsSync(CACHE_PATH)) return true;
376
+ try {
377
+ const raw = JSON.parse(fs2.readFileSync(CACHE_PATH, "utf-8"));
378
+ const fetchedAt = new Date(raw.fetchedAt).getTime();
379
+ const ttlMs = (raw.ttlHours ?? DEFAULT_TTL_HOURS) * 60 * 60 * 1e3;
380
+ return Date.now() - fetchedAt > ttlMs;
381
+ } catch {
382
+ return true;
383
+ }
384
+ }
385
+ loadRegistryFromCacheOrSnapshot() {
386
+ if (fs2.existsSync(CACHE_PATH)) {
387
+ try {
388
+ const raw = JSON.parse(fs2.readFileSync(CACHE_PATH, "utf-8"));
389
+ if (raw.data?.agents) {
390
+ this.registryAgents = raw.data.agents;
391
+ log2.debug({ count: this.registryAgents.length }, "Loaded registry from cache");
392
+ return;
393
+ }
394
+ } catch {
395
+ log2.warn("Failed to load registry cache");
396
+ }
397
+ }
398
+ try {
399
+ const candidates = [
400
+ path2.join(import.meta.dirname, "data", "registry-snapshot.json"),
401
+ path2.join(import.meta.dirname, "..", "data", "registry-snapshot.json"),
402
+ path2.join(import.meta.dirname, "..", "..", "data", "registry-snapshot.json")
403
+ ];
404
+ for (const candidate of candidates) {
405
+ if (fs2.existsSync(candidate)) {
406
+ const raw = JSON.parse(fs2.readFileSync(candidate, "utf-8"));
407
+ this.registryAgents = raw.agents ?? [];
408
+ log2.debug({ count: this.registryAgents.length }, "Loaded registry from bundled snapshot");
409
+ return;
410
+ }
411
+ }
412
+ log2.warn("No registry data available (no cache, no snapshot)");
413
+ } catch {
414
+ log2.warn("Failed to load bundled registry snapshot");
415
+ }
416
+ }
417
+ };
418
+
419
+ export {
420
+ AgentCatalog
421
+ };
422
+ //# sourceMappingURL=chunk-S3DRLJPM.js.map
@@ -0,0 +1 @@
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 }\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 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 } 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 return {\n registryId, name, version, distribution: \"npx\",\n command: \"npx\", args: [dist.package, ...dist.args],\n env: dist.env ?? {}, installedAt: new Date().toISOString(), binaryPath: null,\n };\n }\n if (dist.type === \"uvx\") {\n return {\n registryId, name, version, distribution: \"uvx\",\n command: \"uvx\", args: [dist.package, ...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\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 await progress?.onSuccess(agent.name);\n return { ok: true, agentKey };\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 const parentPath = (entry as unknown as { parentPath?: string; path?: string }).parentPath ?? (entry as unknown as { path: string }).path;\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"]}
@@ -0,0 +1,90 @@
1
+ // src/adapters/telegram/commands/menu.ts
2
+ import { InlineKeyboard } from "grammy";
3
+ function buildMenuKeyboard() {
4
+ return new InlineKeyboard().text("\u{1F195} New Session", "m:new").text("\u{1F4CB} Sessions", "m:topics").row().text("\u{1F4CA} Status", "m:status").text("\u{1F916} Agents", "m:agents").row().text("\u2699\uFE0F Settings", "m:settings").text("\u{1F517} Integrate", "m:integrate").row().text("\u{1F504} Restart", "m:restart").text("\u2B06\uFE0F Update", "m:update").row().text("\u2753 Help", "m:help").text("\u{1FA7A} Doctor", "m:doctor");
5
+ }
6
+ async function handleMenu(ctx) {
7
+ await ctx.reply(`<b>OpenACP Menu</b>
8
+ Choose an action:`, {
9
+ parse_mode: "HTML",
10
+ reply_markup: buildMenuKeyboard()
11
+ });
12
+ }
13
+ async function handleHelp(ctx) {
14
+ await ctx.reply(
15
+ `\u{1F4D6} <b>OpenACP Help</b>
16
+
17
+ \u{1F680} <b>Getting Started</b>
18
+ Tap \u{1F195} New Session to start coding with AI.
19
+ Each session gets its own topic \u2014 chat there to work with the agent.
20
+
21
+ \u{1F4A1} <b>Common Tasks</b>
22
+ /new [agent] [workspace] \u2014 Create new session
23
+ /cancel \u2014 Cancel session (in session topic)
24
+ /status \u2014 Show session or system status
25
+ /sessions \u2014 List all sessions
26
+ /agents \u2014 List available agents
27
+
28
+ \u2699\uFE0F <b>System</b>
29
+ /restart \u2014 Restart OpenACP
30
+ /update \u2014 Update to latest version
31
+ /integrate \u2014 Manage agent integrations
32
+ /menu \u2014 Show action menu
33
+
34
+ \u{1F512} <b>Session Options</b>
35
+ /enable_dangerous \u2014 Auto-approve permissions
36
+ /disable_dangerous \u2014 Restore permission prompts
37
+ /handoff \u2014 Continue session in terminal
38
+ /clear \u2014 Clear assistant history
39
+
40
+ \u{1F4AC} Need help? Just ask me in this topic!`,
41
+ { parse_mode: "HTML" }
42
+ );
43
+ }
44
+ async function handleClear(ctx, assistant) {
45
+ if (!assistant) {
46
+ await ctx.reply("\u26A0\uFE0F Assistant is not available.", { parse_mode: "HTML" });
47
+ return;
48
+ }
49
+ const threadId = ctx.message?.message_thread_id;
50
+ if (threadId !== assistant.topicId) {
51
+ await ctx.reply("\u2139\uFE0F /clear only works in the Assistant topic.", { parse_mode: "HTML" });
52
+ return;
53
+ }
54
+ await ctx.reply("\u{1F504} Clearing assistant history...", { parse_mode: "HTML" });
55
+ try {
56
+ await assistant.respawn();
57
+ await ctx.reply("\u2705 Assistant history cleared.", { parse_mode: "HTML" });
58
+ } catch (err) {
59
+ const message = err instanceof Error ? err.message : String(err);
60
+ await ctx.reply(`\u274C Failed to clear: <code>${message}</code>`, { parse_mode: "HTML" });
61
+ }
62
+ }
63
+ var TELEGRAM_MSG_LIMIT = 4096;
64
+ function buildSkillMessages(commands) {
65
+ const sorted = [...commands].sort((a, b) => a.name.localeCompare(b.name));
66
+ const header = "\u{1F6E0} <b>Available Skills</b>\n";
67
+ const lines = sorted.map((c) => `<code>/${c.name}</code>`);
68
+ const messages = [];
69
+ let current = header;
70
+ for (const line of lines) {
71
+ const candidate = current + "\n" + line;
72
+ if (candidate.length > TELEGRAM_MSG_LIMIT) {
73
+ messages.push(current);
74
+ current = line;
75
+ } else {
76
+ current = candidate;
77
+ }
78
+ }
79
+ if (current) messages.push(current);
80
+ return messages;
81
+ }
82
+
83
+ export {
84
+ buildMenuKeyboard,
85
+ handleMenu,
86
+ handleHelp,
87
+ handleClear,
88
+ buildSkillMessages
89
+ };
90
+ //# sourceMappingURL=chunk-UG6X672R.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/telegram/commands/menu.ts"],"sourcesContent":["import type { Context } from \"grammy\";\nimport { InlineKeyboard } from \"grammy\";\nimport type { AgentCommand } from \"../../../core/index.js\";\nimport type { CommandsAssistantContext } from \"../types.js\";\n\nexport function buildMenuKeyboard(): InlineKeyboard {\n return new InlineKeyboard()\n .text(\"🆕 New Session\", \"m:new\")\n .text(\"📋 Sessions\", \"m:topics\")\n .row()\n .text(\"📊 Status\", \"m:status\")\n .text(\"🤖 Agents\", \"m:agents\")\n .row()\n .text(\"⚙️ Settings\", \"m:settings\")\n .text(\"🔗 Integrate\", \"m:integrate\")\n .row()\n .text(\"🔄 Restart\", \"m:restart\")\n .text(\"⬆️ Update\", \"m:update\")\n .row()\n .text(\"❓ Help\", \"m:help\")\n .text(\"🩺 Doctor\", \"m:doctor\");\n}\n\nexport async function handleMenu(ctx: Context): Promise<void> {\n await ctx.reply(`<b>OpenACP Menu</b>\\nChoose an action:`, {\n parse_mode: \"HTML\",\n reply_markup: buildMenuKeyboard(),\n });\n}\n\nexport async function handleHelp(ctx: Context): Promise<void> {\n await ctx.reply(\n `📖 <b>OpenACP Help</b>\\n\\n` +\n `🚀 <b>Getting Started</b>\\n` +\n `Tap 🆕 New Session to start coding with AI.\\n` +\n `Each session gets its own topic — chat there to work with the agent.\\n\\n` +\n `💡 <b>Common Tasks</b>\\n` +\n `/new [agent] [workspace] — Create new session\\n` +\n `/cancel — Cancel session (in session topic)\\n` +\n `/status — Show session or system status\\n` +\n `/sessions — List all sessions\\n` +\n `/agents — List available agents\\n\\n` +\n `⚙️ <b>System</b>\\n` +\n `/restart — Restart OpenACP\\n` +\n `/update — Update to latest version\\n` +\n `/integrate — Manage agent integrations\\n` +\n `/menu — Show action menu\\n\\n` +\n `🔒 <b>Session Options</b>\\n` +\n `/enable_dangerous — Auto-approve permissions\\n` +\n `/disable_dangerous — Restore permission prompts\\n` +\n `/handoff — Continue session in terminal\\n` +\n `/clear — Clear assistant history\\n\\n` +\n `💬 Need help? Just ask me in this topic!`,\n { parse_mode: \"HTML\" },\n );\n}\n\nexport async function handleClear(ctx: Context, assistant?: CommandsAssistantContext): Promise<void> {\n if (!assistant) {\n await ctx.reply(\"⚠️ Assistant is not available.\", { parse_mode: \"HTML\" });\n return;\n }\n\n const threadId = ctx.message?.message_thread_id;\n if (threadId !== assistant.topicId) {\n await ctx.reply(\"ℹ️ /clear only works in the Assistant topic.\", { parse_mode: \"HTML\" });\n return;\n }\n\n await ctx.reply(\"🔄 Clearing assistant history...\", { parse_mode: \"HTML\" });\n\n try {\n await assistant.respawn();\n await ctx.reply(\"✅ Assistant history cleared.\", { parse_mode: \"HTML\" });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n await ctx.reply(`❌ Failed to clear: <code>${message}</code>`, { parse_mode: \"HTML\" });\n }\n}\n\nconst TELEGRAM_MSG_LIMIT = 4096;\n\n/**\n * Build plain-text skill command messages. Each command is on its own line\n * wrapped in <code> for tap-to-copy. If the list exceeds Telegram's message\n * limit, it is split into multiple messages (cut at line boundaries).\n */\nexport function buildSkillMessages(commands: AgentCommand[]): string[] {\n const sorted = [...commands].sort((a, b) => a.name.localeCompare(b.name));\n const header = \"🛠 <b>Available Skills</b>\\n\";\n const lines = sorted.map((c) => `<code>/${c.name}</code>`);\n\n const messages: string[] = [];\n let current = header;\n\n for (const line of lines) {\n const candidate = current + \"\\n\" + line;\n if (candidate.length > TELEGRAM_MSG_LIMIT) {\n messages.push(current);\n current = line;\n } else {\n current = candidate;\n }\n }\n if (current) messages.push(current);\n return messages;\n}\n"],"mappings":";AACA,SAAS,sBAAsB;AAIxB,SAAS,oBAAoC;AAClD,SAAO,IAAI,eAAe,EACvB,KAAK,yBAAkB,OAAO,EAC9B,KAAK,sBAAe,UAAU,EAC9B,IAAI,EACJ,KAAK,oBAAa,UAAU,EAC5B,KAAK,oBAAa,UAAU,EAC5B,IAAI,EACJ,KAAK,yBAAe,YAAY,EAChC,KAAK,uBAAgB,aAAa,EAClC,IAAI,EACJ,KAAK,qBAAc,WAAW,EAC9B,KAAK,uBAAa,UAAU,EAC5B,IAAI,EACJ,KAAK,eAAU,QAAQ,EACvB,KAAK,oBAAa,UAAU;AACjC;AAEA,eAAsB,WAAW,KAA6B;AAC5D,QAAM,IAAI,MAAM;AAAA,oBAA0C;AAAA,IACxD,YAAY;AAAA,IACZ,cAAc,kBAAkB;AAAA,EAClC,CAAC;AACH;AAEA,eAAsB,WAAW,KAA6B;AAC5D,QAAM,IAAI;AAAA,IACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAqBA,EAAE,YAAY,OAAO;AAAA,EACvB;AACF;AAEA,eAAsB,YAAY,KAAc,WAAqD;AACnG,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,4CAAkC,EAAE,YAAY,OAAO,CAAC;AACxE;AAAA,EACF;AAEA,QAAM,WAAW,IAAI,SAAS;AAC9B,MAAI,aAAa,UAAU,SAAS;AAClC,UAAM,IAAI,MAAM,0DAAgD,EAAE,YAAY,OAAO,CAAC;AACtF;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,2CAAoC,EAAE,YAAY,OAAO,CAAC;AAE1E,MAAI;AACF,UAAM,UAAU,QAAQ;AACxB,UAAM,IAAI,MAAM,qCAAgC,EAAE,YAAY,OAAO,CAAC;AAAA,EACxE,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,UAAM,IAAI,MAAM,iCAA4B,OAAO,WAAW,EAAE,YAAY,OAAO,CAAC;AAAA,EACtF;AACF;AAEA,IAAM,qBAAqB;AAOpB,SAAS,mBAAmB,UAAoC;AACrE,QAAM,SAAS,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AACxE,QAAM,SAAS;AACf,QAAM,QAAQ,OAAO,IAAI,CAAC,MAAM,UAAU,EAAE,IAAI,SAAS;AAEzD,QAAM,WAAqB,CAAC;AAC5B,MAAI,UAAU;AAEd,aAAW,QAAQ,OAAO;AACxB,UAAM,YAAY,UAAU,OAAO;AACnC,QAAI,UAAU,SAAS,oBAAoB;AACzC,eAAS,KAAK,OAAO;AACrB,gBAAU;AAAA,IACZ,OAAO;AACL,gBAAU;AAAA,IACZ;AAAA,EACF;AACA,MAAI,QAAS,UAAS,KAAK,OAAO;AAClC,SAAO;AACT;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  expandHome
3
- } from "./chunk-WYZFGHHI.js";
3
+ } from "./chunk-JRF4G4X7.js";
4
4
 
5
5
  // src/core/daemon.ts
6
6
  import { spawn } from "child_process";
@@ -126,4 +126,4 @@ export {
126
126
  clearRunning,
127
127
  shouldAutoStart
128
128
  };
129
- //# sourceMappingURL=chunk-YRJEZD7R.js.map
129
+ //# sourceMappingURL=chunk-VBEWSWVL.js.map