@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
@@ -1,29 +1,25 @@
1
- import {
2
- DoctorEngine
3
- } from "./chunk-3DIPXFZJ.js";
4
- import {
5
- getAgentCapabilities
6
- } from "./chunk-VA2M52CM.js";
7
1
  import {
8
2
  buildMenuKeyboard,
9
3
  buildSkillMessages,
10
- escapeHtml,
11
- formatToolCall,
12
- formatToolUpdate,
13
- formatUsage,
14
- handleAgents,
15
4
  handleClear,
16
5
  handleHelp,
17
- handleMenu,
18
- markdownToTelegramHtml,
19
- splitMessage
20
- } from "./chunk-BGKQHQB4.js";
6
+ handleMenu
7
+ } from "./chunk-UG6X672R.js";
8
+ import {
9
+ AgentCatalog
10
+ } from "./chunk-S3DRLJPM.js";
11
+ import {
12
+ getAgentCapabilities
13
+ } from "./chunk-XJJ7LPXP.js";
14
+ import {
15
+ DoctorEngine
16
+ } from "./chunk-IRGYTNLP.js";
21
17
  import {
22
18
  getConfigValue,
23
19
  getSafeFields,
24
20
  isHotReloadable,
25
21
  resolveOptions
26
- } from "./chunk-C33LTDZV.js";
22
+ } from "./chunk-Z46LGZ7R.js";
27
23
  import {
28
24
  createChildLogger,
29
25
  createSessionLogger
@@ -72,7 +68,7 @@ var StderrCapture = class {
72
68
  };
73
69
 
74
70
  // src/core/agent-instance.ts
75
- import { spawn, execSync } from "child_process";
71
+ import { spawn, execFileSync } from "child_process";
76
72
  import { Transform } from "stream";
77
73
  import fs from "fs";
78
74
  import path from "path";
@@ -123,7 +119,7 @@ function resolveAgentCommand(cmd) {
123
119
  }
124
120
  }
125
121
  try {
126
- const fullPath = execSync(`which ${cmd}`, { encoding: "utf-8" }).trim();
122
+ const fullPath = execFileSync("which", [cmd], { encoding: "utf-8" }).trim();
127
123
  if (fullPath) {
128
124
  const content = fs.readFileSync(fullPath, "utf-8");
129
125
  if (content.startsWith("#!/usr/bin/env node")) {
@@ -501,31 +497,29 @@ ${stderr}`
501
497
 
502
498
  // src/core/agent-manager.ts
503
499
  var AgentManager = class {
504
- constructor(config) {
505
- this.config = config;
500
+ constructor(catalog) {
501
+ this.catalog = catalog;
506
502
  }
507
503
  getAvailableAgents() {
508
- return Object.entries(this.config.agents).map(([name, cfg]) => ({
509
- name,
510
- command: cfg.command,
511
- args: cfg.args,
512
- workingDirectory: cfg.workingDirectory,
513
- env: cfg.env
504
+ const installed = this.catalog.getInstalledEntries();
505
+ return Object.entries(installed).map(([key, agent]) => ({
506
+ name: key,
507
+ command: agent.command,
508
+ args: agent.args,
509
+ env: agent.env
514
510
  }));
515
511
  }
516
512
  getAgent(name) {
517
- const cfg = this.config.agents[name];
518
- if (!cfg) return void 0;
519
- return { name, ...cfg };
513
+ return this.catalog.resolve(name);
520
514
  }
521
515
  async spawn(agentName, workingDirectory) {
522
516
  const agentDef = this.getAgent(agentName);
523
- if (!agentDef) throw new Error(`Agent "${agentName}" not found in config`);
517
+ if (!agentDef) throw new Error(`Agent "${agentName}" is not installed. Run "openacp agents install ${agentName}" to add it.`);
524
518
  return AgentInstance.spawn(agentDef, workingDirectory);
525
519
  }
526
520
  async resume(agentName, workingDirectory, agentSessionId) {
527
521
  const agentDef = this.getAgent(agentName);
528
- if (!agentDef) throw new Error(`Agent "${agentName}" not found in config`);
522
+ if (!agentDef) throw new Error(`Agent "${agentName}" is not installed. Run "openacp agents install ${agentName}" to add it.`);
529
523
  return AgentInstance.resume(agentDef, workingDirectory, agentSessionId);
530
524
  }
531
525
  };
@@ -652,28 +646,40 @@ var PromptQueue = class {
652
646
  };
653
647
 
654
648
  // src/core/permission-gate.ts
649
+ var DEFAULT_TIMEOUT_MS = 10 * 60 * 1e3;
655
650
  var PermissionGate = class {
656
651
  request;
657
652
  resolveFn;
658
653
  rejectFn;
659
654
  settled = false;
655
+ timeoutTimer;
656
+ timeoutMs;
657
+ constructor(timeoutMs) {
658
+ this.timeoutMs = timeoutMs ?? DEFAULT_TIMEOUT_MS;
659
+ }
660
660
  setPending(request) {
661
661
  this.request = request;
662
662
  this.settled = false;
663
+ this.clearTimeout();
663
664
  return new Promise((resolve2, reject) => {
664
665
  this.resolveFn = resolve2;
665
666
  this.rejectFn = reject;
667
+ this.timeoutTimer = setTimeout(() => {
668
+ this.reject("Permission request timed out (no response received)");
669
+ }, this.timeoutMs);
666
670
  });
667
671
  }
668
672
  resolve(optionId) {
669
673
  if (this.settled || !this.resolveFn) return;
670
674
  this.settled = true;
675
+ this.clearTimeout();
671
676
  this.resolveFn(optionId);
672
677
  this.cleanup();
673
678
  }
674
679
  reject(reason) {
675
680
  if (this.settled || !this.rejectFn) return;
676
681
  this.settled = true;
682
+ this.clearTimeout();
677
683
  this.rejectFn(new Error(reason ?? "Permission rejected"));
678
684
  this.cleanup();
679
685
  }
@@ -687,6 +693,12 @@ var PermissionGate = class {
687
693
  get requestId() {
688
694
  return this.request?.id;
689
695
  }
696
+ clearTimeout() {
697
+ if (this.timeoutTimer) {
698
+ clearTimeout(this.timeoutTimer);
699
+ this.timeoutTimer = void 0;
700
+ }
701
+ }
690
702
  cleanup() {
691
703
  this.request = void 0;
692
704
  this.resolveFn = void 0;
@@ -1453,6 +1465,7 @@ var JsonFileSessionStore = class {
1453
1465
  var log5 = createChildLogger({ module: "core" });
1454
1466
  var OpenACPCore = class {
1455
1467
  configManager;
1468
+ agentCatalog;
1456
1469
  agentManager;
1457
1470
  sessionManager;
1458
1471
  notificationManager;
@@ -1466,7 +1479,9 @@ var OpenACPCore = class {
1466
1479
  constructor(configManager) {
1467
1480
  this.configManager = configManager;
1468
1481
  const config = configManager.get();
1469
- this.agentManager = new AgentManager(config);
1482
+ this.agentCatalog = new AgentCatalog();
1483
+ this.agentCatalog.load();
1484
+ this.agentManager = new AgentManager(this.agentCatalog);
1470
1485
  const storePath = path3.join(os.homedir(), ".openacp", "sessions.json");
1471
1486
  this.sessionStore = new JsonFileSessionStore(
1472
1487
  storePath,
@@ -1494,6 +1509,9 @@ var OpenACPCore = class {
1494
1509
  this.adapters.set(name, adapter);
1495
1510
  }
1496
1511
  async start() {
1512
+ this.agentCatalog.refreshRegistryIfStale().catch((err) => {
1513
+ log5.warn({ err }, "Background registry refresh failed");
1514
+ });
1497
1515
  for (const adapter of this.adapters.values()) {
1498
1516
  await adapter.start();
1499
1517
  }
@@ -1631,8 +1649,9 @@ var OpenACPCore = class {
1631
1649
  const config = this.configManager.get();
1632
1650
  const resolvedAgent = agentName || config.defaultAgent;
1633
1651
  log5.info({ channelId, agentName: resolvedAgent }, "New session request");
1652
+ const agentDef = this.agentCatalog.resolve(resolvedAgent);
1634
1653
  const resolvedWorkspace = this.configManager.resolveWorkspace(
1635
- workspacePath || config.agents[resolvedAgent]?.workingDirectory
1654
+ workspacePath || agentDef?.workingDirectory
1636
1655
  );
1637
1656
  return this.createSession({
1638
1657
  channelId,
@@ -2128,7 +2147,7 @@ var ApiServer = class {
2128
2147
  this.sendJson(res, 200, { version: getVersion() });
2129
2148
  }
2130
2149
  async handleGetEditableConfig(res) {
2131
- const { getSafeFields: getSafeFields2, resolveOptions: resolveOptions2, getConfigValue: getConfigValue2 } = await import("./config-registry-OGX4YM2U.js");
2150
+ const { getSafeFields: getSafeFields2, resolveOptions: resolveOptions2, getConfigValue: getConfigValue2 } = await import("./config-registry-SNKA2EH2.js");
2132
2151
  const config = this.core.configManager.get();
2133
2152
  const safeFields = getSafeFields2();
2134
2153
  const fields = safeFields.map((def) => ({
@@ -2182,7 +2201,7 @@ var ApiServer = class {
2182
2201
  return;
2183
2202
  }
2184
2203
  target[lastKey] = value;
2185
- const { ConfigSchema } = await import("./config-XURP6B3S.js");
2204
+ const { ConfigSchema } = await import("./config-PCPIBPUA.js");
2186
2205
  const result = ConfigSchema.safeParse(cloned);
2187
2206
  if (!result.success) {
2188
2207
  this.sendJson(res, 400, {
@@ -2199,7 +2218,7 @@ var ApiServer = class {
2199
2218
  }
2200
2219
  updateTarget[lastKey] = value;
2201
2220
  await this.core.configManager.save(updates, configPath);
2202
- const { isHotReloadable: isHotReloadable2 } = await import("./config-registry-OGX4YM2U.js");
2221
+ const { isHotReloadable: isHotReloadable2 } = await import("./config-registry-SNKA2EH2.js");
2203
2222
  const needsRestart = !isHotReloadable2(configPath);
2204
2223
  this.sendJson(res, 200, {
2205
2224
  ok: true,
@@ -2485,6 +2504,169 @@ function buildDeepLink(chatId, messageId) {
2485
2504
  // src/adapters/telegram/commands/new-session.ts
2486
2505
  import { InlineKeyboard as InlineKeyboard2 } from "grammy";
2487
2506
 
2507
+ // src/adapters/telegram/formatting.ts
2508
+ function escapeHtml(text) {
2509
+ if (!text) return "";
2510
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
2511
+ }
2512
+ function markdownToTelegramHtml(md) {
2513
+ const codeBlocks = [];
2514
+ const inlineCodes = [];
2515
+ let text = md.replace(/```(\w*)\n?([\s\S]*?)```/g, (_match, lang, code) => {
2516
+ const index = codeBlocks.length;
2517
+ const escapedCode = escapeHtml(code);
2518
+ const langAttr = lang ? ` class="language-${escapeHtml(lang)}"` : "";
2519
+ codeBlocks.push(`<pre><code${langAttr}>${escapedCode}</code></pre>`);
2520
+ return `\0CODE_BLOCK_${index}\0`;
2521
+ });
2522
+ text = text.replace(/`([^`]+)`/g, (_match, code) => {
2523
+ const index = inlineCodes.length;
2524
+ inlineCodes.push(`<code>${escapeHtml(code)}</code>`);
2525
+ return `\0INLINE_CODE_${index}\0`;
2526
+ });
2527
+ text = escapeHtml(text);
2528
+ text = text.replace(/\*\*(.+?)\*\*/g, "<b>$1</b>");
2529
+ text = text.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "<i>$1</i>");
2530
+ text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
2531
+ text = text.replace(/\x00CODE_BLOCK_(\d+)\x00/g, (_match, idx) => {
2532
+ return codeBlocks[parseInt(idx, 10)];
2533
+ });
2534
+ text = text.replace(/\x00INLINE_CODE_(\d+)\x00/g, (_match, idx) => {
2535
+ return inlineCodes[parseInt(idx, 10)];
2536
+ });
2537
+ return text;
2538
+ }
2539
+ var STATUS_ICON = {
2540
+ pending: "\u23F3",
2541
+ in_progress: "\u{1F504}",
2542
+ completed: "\u2705",
2543
+ failed: "\u274C"
2544
+ };
2545
+ var KIND_ICON = {
2546
+ read: "\u{1F4D6}",
2547
+ edit: "\u270F\uFE0F",
2548
+ delete: "\u{1F5D1}\uFE0F",
2549
+ execute: "\u25B6\uFE0F",
2550
+ search: "\u{1F50D}",
2551
+ fetch: "\u{1F310}",
2552
+ think: "\u{1F9E0}",
2553
+ move: "\u{1F4E6}",
2554
+ other: "\u{1F6E0}\uFE0F"
2555
+ };
2556
+ function extractContentText(content, depth = 0) {
2557
+ if (!content || depth > 5) return "";
2558
+ if (typeof content === "string") return content;
2559
+ if (Array.isArray(content)) {
2560
+ return content.map((c) => extractContentText(c, depth + 1)).filter(Boolean).join("\n");
2561
+ }
2562
+ if (typeof content === "object" && content !== null) {
2563
+ const c = content;
2564
+ if (c.type === "text" && typeof c.text === "string") return c.text;
2565
+ if (typeof c.text === "string") return c.text;
2566
+ if (typeof c.content === "string") return c.content;
2567
+ if (c.content && typeof c.content === "object") return extractContentText(c.content, depth + 1);
2568
+ if (c.input) return extractContentText(c.input, depth + 1);
2569
+ if (c.output) return extractContentText(c.output, depth + 1);
2570
+ const keys = Object.keys(c).filter((k) => k !== "type");
2571
+ if (keys.length === 0) return "";
2572
+ return JSON.stringify(c, null, 2);
2573
+ }
2574
+ return String(content);
2575
+ }
2576
+ function truncateContent(text, maxLen = 3800) {
2577
+ if (text.length <= maxLen) return text;
2578
+ return text.slice(0, maxLen) + "\n\u2026 (truncated)";
2579
+ }
2580
+ function formatToolCall(tool) {
2581
+ const si = STATUS_ICON[tool.status || ""] || "\u{1F527}";
2582
+ const ki = KIND_ICON[tool.kind || ""] || "\u{1F6E0}\uFE0F";
2583
+ let text = `${si} ${ki} <b>${escapeHtml(tool.name || "Tool")}</b>`;
2584
+ text += formatViewerLinks(tool.viewerLinks, tool.viewerFilePath);
2585
+ if (!tool.viewerLinks) {
2586
+ const details = extractContentText(tool.content);
2587
+ if (details) {
2588
+ text += `
2589
+ <pre>${escapeHtml(truncateContent(details))}</pre>`;
2590
+ }
2591
+ }
2592
+ return text;
2593
+ }
2594
+ function formatToolUpdate(update) {
2595
+ const si = STATUS_ICON[update.status] || "\u{1F527}";
2596
+ const ki = KIND_ICON[update.kind || ""] || "\u{1F6E0}\uFE0F";
2597
+ const name = update.name || "Tool";
2598
+ let text = `${si} ${ki} <b>${escapeHtml(name)}</b>`;
2599
+ text += formatViewerLinks(update.viewerLinks, update.viewerFilePath);
2600
+ if (!update.viewerLinks) {
2601
+ const details = extractContentText(update.content);
2602
+ if (details) {
2603
+ text += `
2604
+ <pre>${escapeHtml(truncateContent(details))}</pre>`;
2605
+ }
2606
+ }
2607
+ return text;
2608
+ }
2609
+ function formatViewerLinks(links, filePath) {
2610
+ if (!links) return "";
2611
+ const fileName = filePath ? filePath.split("/").pop() || filePath : "";
2612
+ let text = "\n";
2613
+ if (links.file) text += `
2614
+ \u{1F4C4} <a href="${escapeHtml(links.file)}">View ${escapeHtml(fileName || "file")}</a>`;
2615
+ if (links.diff) text += `
2616
+ \u{1F4DD} <a href="${escapeHtml(links.diff)}">View diff${fileName ? ` \u2014 ${escapeHtml(fileName)}` : ""}</a>`;
2617
+ return text;
2618
+ }
2619
+ function formatTokens(n) {
2620
+ return n >= 1e3 ? `${Math.round(n / 1e3)}k` : String(n);
2621
+ }
2622
+ function progressBar(ratio) {
2623
+ const filled = Math.round(Math.min(ratio, 1) * 10);
2624
+ return "\u2593".repeat(filled) + "\u2591".repeat(10 - filled);
2625
+ }
2626
+ function formatUsage(usage) {
2627
+ const { tokensUsed, contextSize } = usage;
2628
+ if (tokensUsed == null) return "\u{1F4CA} Usage data unavailable";
2629
+ if (contextSize == null) return `\u{1F4CA} ${formatTokens(tokensUsed)} tokens`;
2630
+ const ratio = tokensUsed / contextSize;
2631
+ const pct = Math.round(ratio * 100);
2632
+ const bar = progressBar(ratio);
2633
+ const emoji = pct >= 85 ? "\u26A0\uFE0F" : "\u{1F4CA}";
2634
+ return `${emoji} ${formatTokens(tokensUsed)} / ${formatTokens(contextSize)} tokens
2635
+ ${bar} ${pct}%`;
2636
+ }
2637
+ function splitMessage(text, maxLength = 3800) {
2638
+ if (text.length <= maxLength) return [text];
2639
+ const chunks = [];
2640
+ let remaining = text;
2641
+ while (remaining.length > 0) {
2642
+ if (remaining.length <= maxLength) {
2643
+ chunks.push(remaining);
2644
+ break;
2645
+ }
2646
+ const wouldLeaveSmall = remaining.length < maxLength * 1.3;
2647
+ const searchLimit = wouldLeaveSmall ? Math.floor(remaining.length / 2) + 300 : maxLength;
2648
+ let splitAt = remaining.lastIndexOf("\n\n", searchLimit);
2649
+ if (splitAt === -1 || splitAt < searchLimit * 0.2) {
2650
+ splitAt = remaining.lastIndexOf("\n", searchLimit);
2651
+ }
2652
+ if (splitAt === -1 || splitAt < searchLimit * 0.2) {
2653
+ splitAt = searchLimit;
2654
+ }
2655
+ const candidate = remaining.slice(0, splitAt);
2656
+ const fences = candidate.match(/```/g);
2657
+ if (fences && fences.length % 2 !== 0) {
2658
+ const closingFence = remaining.indexOf("```", splitAt);
2659
+ if (closingFence !== -1) {
2660
+ const afterFence = remaining.indexOf("\n", closingFence + 3);
2661
+ splitAt = afterFence !== -1 ? afterFence + 1 : closingFence + 3;
2662
+ }
2663
+ }
2664
+ chunks.push(remaining.slice(0, splitAt));
2665
+ remaining = remaining.slice(splitAt).replace(/^\n+/, "");
2666
+ }
2667
+ return chunks;
2668
+ }
2669
+
2488
2670
  // src/adapters/telegram/commands/admin.ts
2489
2671
  import { InlineKeyboard } from "grammy";
2490
2672
  var log9 = createChildLogger({ module: "telegram-cmd-admin" });
@@ -2688,37 +2870,12 @@ async function handleNew(ctx, core, chatId, assistant) {
2688
2870
  return;
2689
2871
  }
2690
2872
  }
2691
- const userId = ctx.from?.id;
2692
- if (!userId) return;
2693
- const agents = core.agentManager.getAvailableAgents();
2694
- const config = core.configManager.get();
2695
- if (agentName || agents.length === 1) {
2696
- const selectedAgent = agentName || config.defaultAgent;
2697
- await startWorkspaceStep(ctx, core, chatId, userId, selectedAgent);
2698
- return;
2699
- }
2700
- const keyboard = new InlineKeyboard2();
2701
- for (const agent of agents) {
2702
- const label = agent.name === config.defaultAgent ? `${agent.name} (default)` : agent.name;
2703
- keyboard.text(label, `m:new:agent:${agent.name}`).row();
2704
- }
2705
- keyboard.text("\u274C Cancel", "m:new:cancel");
2706
- const msg = await ctx.reply(
2707
- `\u{1F916} <b>Choose an agent:</b>`,
2708
- { parse_mode: "HTML", reply_markup: keyboard }
2709
- );
2710
- cleanupPending(userId);
2711
- pendingNewSessions.set(userId, {
2712
- step: "agent",
2713
- messageId: msg.message_id,
2714
- threadId: currentThreadId,
2715
- timer: setTimeout(() => pendingNewSessions.delete(userId), PENDING_TIMEOUT_MS)
2716
- });
2873
+ await showAgentPicker(ctx, core, chatId, agentName);
2717
2874
  }
2718
2875
  async function startWorkspaceStep(ctx, core, chatId, userId, agentName) {
2719
2876
  const config = core.configManager.get();
2720
2877
  const baseDir = config.workspace.baseDir;
2721
- const keyboard = new InlineKeyboard2().text(`\u{1F4C1} Use ${baseDir}`, "m:new:ws:default").row().text("\u270F\uFE0F Enter project path", "m:new:ws:custom").row().text("\u274C Cancel", "m:new:cancel");
2878
+ const keyboard = new InlineKeyboard2().text(`\u{1F4C1} Use ${baseDir}`, "m:new:ws:default").row().text("\u270F\uFE0F Enter project path", "m:new:ws:custom");
2722
2879
  const text = `\u{1F4C1} <b>Where should ${escapeHtml(agentName)} work?</b>
2723
2880
 
2724
2881
  Enter the path to your project folder \u2014 the agent will read, write, and run code there.
@@ -2953,30 +3110,35 @@ async function handlePendingWorkspaceInput(ctx, core, chatId, assistantTopicId)
2953
3110
  return true;
2954
3111
  }
2955
3112
  async function startInteractiveNewSession(ctx, core, chatId, agentName) {
3113
+ await showAgentPicker(ctx, core, chatId, agentName);
3114
+ }
3115
+ async function showAgentPicker(ctx, core, chatId, agentName) {
2956
3116
  const userId = ctx.from?.id;
2957
3117
  if (!userId) return;
2958
- const agents = core.agentManager.getAvailableAgents();
3118
+ const installedEntries = core.agentCatalog.getInstalledEntries();
3119
+ const agentKeys = Object.keys(installedEntries);
2959
3120
  const config = core.configManager.get();
2960
- if (agentName || agents.length === 1) {
3121
+ if (agentName || agentKeys.length === 1) {
2961
3122
  const selectedAgent = agentName || config.defaultAgent;
2962
3123
  await startWorkspaceStep(ctx, core, chatId, userId, selectedAgent);
2963
3124
  return;
2964
3125
  }
2965
3126
  const keyboard = new InlineKeyboard2();
2966
- for (const agent of agents) {
2967
- const label = agent.name === config.defaultAgent ? `${agent.name} (default)` : agent.name;
2968
- keyboard.text(label, `m:new:agent:${agent.name}`).row();
3127
+ for (const key of agentKeys) {
3128
+ const agent = installedEntries[key];
3129
+ const label = key === config.defaultAgent ? `${agent.name} (default)` : agent.name;
3130
+ keyboard.text(label, `m:new:agent:${key}`).row();
2969
3131
  }
2970
- keyboard.text("\u274C Cancel", "m:new:cancel");
2971
3132
  const msg = await ctx.reply(
2972
3133
  `\u{1F916} <b>Choose an agent:</b>`,
2973
3134
  { parse_mode: "HTML", reply_markup: keyboard }
2974
3135
  );
2975
3136
  cleanupPending(userId);
3137
+ const threadId = ctx.message?.message_thread_id ?? ctx.callbackQuery?.message?.message_thread_id;
2976
3138
  pendingNewSessions.set(userId, {
2977
3139
  step: "agent",
2978
3140
  messageId: msg.message_id,
2979
- threadId: ctx.callbackQuery?.message?.message_thread_id,
3141
+ threadId,
2980
3142
  timer: setTimeout(() => pendingNewSessions.delete(userId), PENDING_TIMEOUT_MS)
2981
3143
  });
2982
3144
  }
@@ -3350,12 +3512,221 @@ function setupSessionCallbacks(bot, core, chatId, systemTopicIds) {
3350
3512
  });
3351
3513
  }
3352
3514
 
3353
- // src/adapters/telegram/commands/integrate.ts
3515
+ // src/adapters/telegram/commands/agents.ts
3354
3516
  import { InlineKeyboard as InlineKeyboard4 } from "grammy";
3517
+ var AGENTS_PER_PAGE = 6;
3518
+ async function handleAgents(ctx, core, page = 0) {
3519
+ const catalog = core.agentCatalog;
3520
+ const items = catalog.getAvailable();
3521
+ const installed = items.filter((i) => i.installed);
3522
+ const available = items.filter((i) => !i.installed);
3523
+ let text = "<b>\u{1F916} Agents</b>\n\n";
3524
+ if (installed.length > 0) {
3525
+ text += "<b>Installed:</b>\n";
3526
+ for (const item of installed) {
3527
+ text += `\u2705 <b>${escapeHtml(item.name)}</b>`;
3528
+ if (item.description) {
3529
+ text += ` \u2014 <i>${escapeHtml(truncate(item.description, 50))}</i>`;
3530
+ }
3531
+ text += "\n";
3532
+ }
3533
+ text += "\n";
3534
+ }
3535
+ if (available.length > 0) {
3536
+ const totalPages = Math.ceil(available.length / AGENTS_PER_PAGE);
3537
+ const safePage = Math.max(0, Math.min(page, totalPages - 1));
3538
+ const pageItems = available.slice(safePage * AGENTS_PER_PAGE, (safePage + 1) * AGENTS_PER_PAGE);
3539
+ text += `<b>Available to install:</b>`;
3540
+ if (totalPages > 1) {
3541
+ text += ` (${safePage + 1}/${totalPages})`;
3542
+ }
3543
+ text += "\n";
3544
+ for (const item of pageItems) {
3545
+ if (item.available) {
3546
+ text += `\u2B07\uFE0F <b>${escapeHtml(item.name)}</b>`;
3547
+ } else {
3548
+ const deps = item.missingDeps?.join(", ") ?? "requirements not met";
3549
+ text += `\u26A0\uFE0F <b>${escapeHtml(item.name)}</b> <i>(needs: ${escapeHtml(deps)})</i>`;
3550
+ }
3551
+ if (item.description) {
3552
+ text += `
3553
+ <i>${escapeHtml(truncate(item.description, 60))}</i>`;
3554
+ }
3555
+ text += "\n";
3556
+ }
3557
+ const keyboard = new InlineKeyboard4();
3558
+ const installable = pageItems.filter((i) => i.available);
3559
+ for (let i = 0; i < installable.length; i += 2) {
3560
+ const row = installable.slice(i, i + 2);
3561
+ for (const item of row) {
3562
+ keyboard.text(`\u2B07\uFE0F ${item.name}`, `ag:install:${item.key}`);
3563
+ }
3564
+ keyboard.row();
3565
+ }
3566
+ if (totalPages > 1) {
3567
+ if (safePage > 0) {
3568
+ keyboard.text("\u25C0\uFE0F Prev", `ag:page:${safePage - 1}`);
3569
+ }
3570
+ if (safePage < totalPages - 1) {
3571
+ keyboard.text("Next \u25B6\uFE0F", `ag:page:${safePage + 1}`);
3572
+ }
3573
+ keyboard.row();
3574
+ }
3575
+ if (available.some((i) => !i.available)) {
3576
+ text += "\n\u{1F4A1} <i>Agents marked \u26A0\uFE0F need additional setup. Use</i> <code>openacp agents info &lt;name&gt;</code> <i>for details.</i>\n";
3577
+ }
3578
+ await ctx.reply(text, { parse_mode: "HTML", reply_markup: keyboard });
3579
+ } else {
3580
+ text += "<i>All agents are already installed!</i>";
3581
+ await ctx.reply(text, { parse_mode: "HTML" });
3582
+ }
3583
+ }
3584
+ async function handleInstall(ctx, core) {
3585
+ const text = (ctx.message?.text ?? "").trim();
3586
+ const parts = text.split(/\s+/);
3587
+ const nameOrId = parts[1];
3588
+ if (!nameOrId) {
3589
+ await ctx.reply(
3590
+ "\u{1F4E6} <b>Install an agent</b>\n\nUsage: <code>/install &lt;agent-name&gt;</code>\nExample: <code>/install gemini</code>\n\nUse /agents to browse available agents.",
3591
+ { parse_mode: "HTML" }
3592
+ );
3593
+ return;
3594
+ }
3595
+ await installAgentWithProgress(ctx, core, nameOrId);
3596
+ }
3597
+ async function handleAgentCallback(ctx, core) {
3598
+ const data = ctx.callbackQuery?.data ?? "";
3599
+ await ctx.answerCallbackQuery();
3600
+ if (data.startsWith("ag:install:")) {
3601
+ const nameOrId = data.replace("ag:install:", "");
3602
+ await installAgentWithProgress(ctx, core, nameOrId);
3603
+ return;
3604
+ }
3605
+ if (data.startsWith("ag:page:")) {
3606
+ const page = parseInt(data.replace("ag:page:", ""), 10);
3607
+ try {
3608
+ const catalog = core.agentCatalog;
3609
+ const items = catalog.getAvailable();
3610
+ const installed = items.filter((i) => i.installed);
3611
+ const available = items.filter((i) => !i.installed);
3612
+ let text = "<b>\u{1F916} Agents</b>\n\n";
3613
+ if (installed.length > 0) {
3614
+ text += "<b>Installed:</b>\n";
3615
+ for (const item of installed) {
3616
+ text += `\u2705 <b>${escapeHtml(item.name)}</b>`;
3617
+ if (item.description) {
3618
+ text += ` \u2014 <i>${escapeHtml(truncate(item.description, 50))}</i>`;
3619
+ }
3620
+ text += "\n";
3621
+ }
3622
+ text += "\n";
3623
+ }
3624
+ const totalPages = Math.ceil(available.length / AGENTS_PER_PAGE);
3625
+ const safePage = Math.max(0, Math.min(page, totalPages - 1));
3626
+ const pageItems = available.slice(safePage * AGENTS_PER_PAGE, (safePage + 1) * AGENTS_PER_PAGE);
3627
+ text += `<b>Available to install:</b>`;
3628
+ if (totalPages > 1) {
3629
+ text += ` (${safePage + 1}/${totalPages})`;
3630
+ }
3631
+ text += "\n";
3632
+ for (const item of pageItems) {
3633
+ if (item.available) {
3634
+ text += `\u2B07\uFE0F <b>${escapeHtml(item.name)}</b>`;
3635
+ } else {
3636
+ const deps = item.missingDeps?.join(", ") ?? "requirements not met";
3637
+ text += `\u26A0\uFE0F <b>${escapeHtml(item.name)}</b> <i>(needs: ${escapeHtml(deps)})</i>`;
3638
+ }
3639
+ if (item.description) {
3640
+ text += `
3641
+ <i>${escapeHtml(truncate(item.description, 60))}</i>`;
3642
+ }
3643
+ text += "\n";
3644
+ }
3645
+ const keyboard = new InlineKeyboard4();
3646
+ const installable = pageItems.filter((i) => i.available);
3647
+ for (let i = 0; i < installable.length; i += 2) {
3648
+ const row = installable.slice(i, i + 2);
3649
+ for (const item of row) {
3650
+ keyboard.text(`\u2B07\uFE0F ${item.name}`, `ag:install:${item.key}`);
3651
+ }
3652
+ keyboard.row();
3653
+ }
3654
+ if (totalPages > 1) {
3655
+ if (safePage > 0) {
3656
+ keyboard.text("\u25C0\uFE0F Prev", `ag:page:${safePage - 1}`);
3657
+ }
3658
+ if (safePage < totalPages - 1) {
3659
+ keyboard.text("Next \u25B6\uFE0F", `ag:page:${safePage + 1}`);
3660
+ }
3661
+ keyboard.row();
3662
+ }
3663
+ await ctx.editMessageText(text, { parse_mode: "HTML", reply_markup: keyboard });
3664
+ } catch {
3665
+ }
3666
+ }
3667
+ }
3668
+ async function installAgentWithProgress(ctx, core, nameOrId) {
3669
+ const catalog = core.agentCatalog;
3670
+ const msg = await ctx.reply(`\u23F3 Installing <b>${escapeHtml(nameOrId)}</b>...`, { parse_mode: "HTML" });
3671
+ let lastEdit = 0;
3672
+ const EDIT_THROTTLE_MS = 1500;
3673
+ const progress = {
3674
+ onStart(_id, _name) {
3675
+ },
3676
+ async onStep(step) {
3677
+ const now = Date.now();
3678
+ if (now - lastEdit > EDIT_THROTTLE_MS) {
3679
+ lastEdit = now;
3680
+ try {
3681
+ await ctx.api.editMessageText(msg.chat.id, msg.message_id, `\u23F3 <b>${escapeHtml(nameOrId)}</b>: ${escapeHtml(step)}`, { parse_mode: "HTML" });
3682
+ } catch {
3683
+ }
3684
+ }
3685
+ },
3686
+ async onDownloadProgress(percent) {
3687
+ const now = Date.now();
3688
+ if (now - lastEdit > EDIT_THROTTLE_MS) {
3689
+ lastEdit = now;
3690
+ try {
3691
+ const bar = buildProgressBar(percent);
3692
+ await ctx.api.editMessageText(msg.chat.id, msg.message_id, `\u23F3 <b>${escapeHtml(nameOrId)}</b>
3693
+ Downloading... ${bar} ${percent}%`, { parse_mode: "HTML" });
3694
+ } catch {
3695
+ }
3696
+ }
3697
+ },
3698
+ async onSuccess(name) {
3699
+ try {
3700
+ const keyboard = new InlineKeyboard4().text(`\u{1F680} Start session with ${name}`, `na:${nameOrId}`);
3701
+ await ctx.api.editMessageText(msg.chat.id, msg.message_id, `\u2705 <b>${escapeHtml(name)}</b> installed!`, { parse_mode: "HTML", reply_markup: keyboard });
3702
+ } catch {
3703
+ }
3704
+ },
3705
+ async onError(error) {
3706
+ try {
3707
+ await ctx.api.editMessageText(msg.chat.id, msg.message_id, `\u274C ${escapeHtml(error)}`, { parse_mode: "HTML" });
3708
+ } catch {
3709
+ }
3710
+ }
3711
+ };
3712
+ await catalog.install(nameOrId, progress);
3713
+ }
3714
+ function truncate(text, maxLen) {
3715
+ if (text.length <= maxLen) return text;
3716
+ return text.slice(0, maxLen - 1) + "\u2026";
3717
+ }
3718
+ function buildProgressBar(percent) {
3719
+ const filled = Math.round(percent / 10);
3720
+ const empty = 10 - filled;
3721
+ return "\u2588".repeat(filled) + "\u2591".repeat(empty);
3722
+ }
3723
+
3724
+ // src/adapters/telegram/commands/integrate.ts
3725
+ import { InlineKeyboard as InlineKeyboard5 } from "grammy";
3355
3726
  async function handleIntegrate(ctx, _core) {
3356
3727
  const { listIntegrations } = await import("./integrate-WUPLRJD3.js");
3357
3728
  const agents = listIntegrations();
3358
- const keyboard = new InlineKeyboard4();
3729
+ const keyboard = new InlineKeyboard5();
3359
3730
  for (const agent of agents) {
3360
3731
  keyboard.text(`\u{1F916} ${agent}`, `i:agent:${agent}`).row();
3361
3732
  }
@@ -3367,7 +3738,7 @@ Select an agent to manage its integrations.`,
3367
3738
  );
3368
3739
  }
3369
3740
  function buildAgentItemsKeyboard(agentName, items) {
3370
- const keyboard = new InlineKeyboard4();
3741
+ const keyboard = new InlineKeyboard5();
3371
3742
  for (const item of items) {
3372
3743
  const installed = item.isInstalled();
3373
3744
  keyboard.text(
@@ -3388,7 +3759,7 @@ function setupIntegrateCallbacks(bot, core) {
3388
3759
  if (data === "i:back") {
3389
3760
  const { listIntegrations } = await import("./integrate-WUPLRJD3.js");
3390
3761
  const agents = listIntegrations();
3391
- const keyboard2 = new InlineKeyboard4();
3762
+ const keyboard2 = new InlineKeyboard5();
3392
3763
  for (const agent of agents) {
3393
3764
  keyboard2.text(`\u{1F916} ${agent}`, `i:agent:${agent}`).row();
3394
3765
  }
@@ -3469,12 +3840,12 @@ ${resultText}`,
3469
3840
  }
3470
3841
 
3471
3842
  // src/adapters/telegram/commands/settings.ts
3472
- import { InlineKeyboard as InlineKeyboard5 } from "grammy";
3843
+ import { InlineKeyboard as InlineKeyboard6 } from "grammy";
3473
3844
  var log12 = createChildLogger({ module: "telegram-settings" });
3474
3845
  function buildSettingsKeyboard(core) {
3475
3846
  const config = core.configManager.get();
3476
3847
  const fields = getSafeFields();
3477
- const kb = new InlineKeyboard5();
3848
+ const kb = new InlineKeyboard6();
3478
3849
  for (const field of fields) {
3479
3850
  const value = getConfigValue(config, field.path);
3480
3851
  const label = formatFieldLabel(field, value);
@@ -3545,7 +3916,7 @@ function setupSettingsCallbacks(bot, core, getAssistantSession) {
3545
3916
  if (!fieldDef) return;
3546
3917
  const options = resolveOptions(fieldDef, config) ?? [];
3547
3918
  const currentValue = getConfigValue(config, fieldPath);
3548
- const kb = new InlineKeyboard5();
3919
+ const kb = new InlineKeyboard6();
3549
3920
  for (const opt of options) {
3550
3921
  const marker = opt === String(currentValue) ? " \u2713" : "";
3551
3922
  kb.text(`${opt}${marker}`, `s:pick:${fieldPath}:${opt}`).row();
@@ -3617,7 +3988,7 @@ Tap to change:`, {
3617
3988
  await ctx.answerCallbackQuery();
3618
3989
  } catch {
3619
3990
  }
3620
- const { buildMenuKeyboard: buildMenuKeyboard3 } = await import("./menu-CARRTW2F.js");
3991
+ const { buildMenuKeyboard: buildMenuKeyboard3 } = await import("./menu-6RCPBVGQ.js");
3621
3992
  try {
3622
3993
  await ctx.editMessageText(`<b>OpenACP Menu</b>
3623
3994
  Choose an action:`, {
@@ -3655,7 +4026,7 @@ function buildNestedUpdate(dotPath, value) {
3655
4026
  }
3656
4027
 
3657
4028
  // src/adapters/telegram/commands/doctor.ts
3658
- import { InlineKeyboard as InlineKeyboard6 } from "grammy";
4029
+ import { InlineKeyboard as InlineKeyboard7 } from "grammy";
3659
4030
  var log13 = createChildLogger({ module: "telegram-cmd-doctor" });
3660
4031
  var pendingFixesStore = /* @__PURE__ */ new Map();
3661
4032
  function renderReport(report) {
@@ -3673,7 +4044,7 @@ function renderReport(report) {
3673
4044
  lines.push(`<b>Result:</b> ${passed} passed, ${warnings} warnings, ${failed} failed${fixedStr}`);
3674
4045
  let keyboard;
3675
4046
  if (report.pendingFixes.length > 0) {
3676
- keyboard = new InlineKeyboard6();
4047
+ keyboard = new InlineKeyboard7();
3677
4048
  for (let i = 0; i < report.pendingFixes.length; i++) {
3678
4049
  const label = `\u{1F527} Fix: ${report.pendingFixes[i].message.slice(0, 30)}`;
3679
4050
  keyboard.text(label, `m:doctor:fix:${i}`).row();
@@ -3768,6 +4139,7 @@ function setupCommands(bot, core, chatId, assistant) {
3768
4139
  bot.command("status", (ctx) => handleStatus(ctx, core));
3769
4140
  bot.command("sessions", (ctx) => handleTopics(ctx, core));
3770
4141
  bot.command("agents", (ctx) => handleAgents(ctx, core));
4142
+ bot.command("install", (ctx) => handleInstall(ctx, core));
3771
4143
  bot.command("help", (ctx) => handleHelp(ctx));
3772
4144
  bot.command("menu", (ctx) => handleMenu(ctx));
3773
4145
  bot.command("enable_dangerous", (ctx) => handleEnableDangerous(ctx, core));
@@ -3783,6 +4155,12 @@ function setupAllCallbacks(bot, core, chatId, systemTopicIds, getAssistantSessio
3783
4155
  setupSessionCallbacks(bot, core, chatId, systemTopicIds);
3784
4156
  setupSettingsCallbacks(bot, core, getAssistantSession ?? (() => void 0));
3785
4157
  setupDoctorCallbacks(bot);
4158
+ bot.callbackQuery(/^ag:/, (ctx) => handleAgentCallback(ctx, core));
4159
+ bot.callbackQuery(/^na:/, async (ctx) => {
4160
+ const agentKey = ctx.callbackQuery.data.replace("na:", "");
4161
+ await ctx.answerCallbackQuery();
4162
+ await createSessionDirect(ctx, core, chatId, agentKey, core.configManager.get().workspace.baseDir);
4163
+ });
3786
4164
  bot.callbackQuery(/^m:/, async (ctx) => {
3787
4165
  const data = ctx.callbackQuery.data;
3788
4166
  try {
@@ -3827,6 +4205,7 @@ var STATIC_COMMANDS = [
3827
4205
  { command: "status", description: "Show status" },
3828
4206
  { command: "sessions", description: "List all sessions" },
3829
4207
  { command: "agents", description: "List available agents" },
4208
+ { command: "install", description: "Install a new agent" },
3830
4209
  { command: "help", description: "Help" },
3831
4210
  { command: "menu", description: "Show menu" },
3832
4211
  { command: "enable_dangerous", description: "Auto-approve all permission requests (session only)" },
@@ -3840,7 +4219,7 @@ var STATIC_COMMANDS = [
3840
4219
  ];
3841
4220
 
3842
4221
  // src/adapters/telegram/permissions.ts
3843
- import { InlineKeyboard as InlineKeyboard7 } from "grammy";
4222
+ import { InlineKeyboard as InlineKeyboard8 } from "grammy";
3844
4223
  import { nanoid as nanoid2 } from "nanoid";
3845
4224
  var log14 = createChildLogger({ module: "telegram-permissions" });
3846
4225
  var PermissionHandler = class {
@@ -3859,7 +4238,7 @@ var PermissionHandler = class {
3859
4238
  requestId: request.id,
3860
4239
  options: request.options.map((o) => ({ id: o.id, isAllow: o.isAllow }))
3861
4240
  });
3862
- const keyboard = new InlineKeyboard7();
4241
+ const keyboard = new InlineKeyboard8();
3863
4242
  for (const option of request.options) {
3864
4243
  const emoji = option.isAllow ? "\u2705" : "\u274C";
3865
4244
  keyboard.text(`${emoji} ${option.label}`, `p:${callbackKey}:${option.id}`);
@@ -4801,7 +5180,7 @@ var TelegramSendQueue = class {
4801
5180
 
4802
5181
  // src/adapters/telegram/action-detect.ts
4803
5182
  import { nanoid as nanoid3 } from "nanoid";
4804
- import { InlineKeyboard as InlineKeyboard8 } from "grammy";
5183
+ import { InlineKeyboard as InlineKeyboard9 } from "grammy";
4805
5184
  var CMD_NEW_RE = /\/new(?:\s+([^\s\u0080-\uFFFF]+)(?:\s+([^\s\u0080-\uFFFF]+))?)?/;
4806
5185
  var CMD_CANCEL_RE = /\/cancel\b/;
4807
5186
  var KW_NEW_RE = /(?:create|new)\s+session/i;
@@ -4848,7 +5227,7 @@ function removeAction(id) {
4848
5227
  actionMap.delete(id);
4849
5228
  }
4850
5229
  function buildActionKeyboard(actionId, action) {
4851
- const keyboard = new InlineKeyboard8();
5230
+ const keyboard = new InlineKeyboard9();
4852
5231
  if (action.action === "new_session") {
4853
5232
  keyboard.text("\u2705 Create session", `a:${actionId}`);
4854
5233
  keyboard.text("\u274C Cancel", `a:dismiss:${actionId}`);
@@ -5577,7 +5956,7 @@ var TelegramAdapter = class extends ChannelAdapter {
5577
5956
  });
5578
5957
  return;
5579
5958
  }
5580
- const { getAgentCapabilities: getAgentCapabilities2 } = await import("./agent-registry-7HC6D4CH.js");
5959
+ const { getAgentCapabilities: getAgentCapabilities2 } = await import("./agent-registry-B5YAMA4T.js");
5581
5960
  const caps = getAgentCapabilities2(agentName);
5582
5961
  if (!caps.supportsResume || !caps.resumeCommand) {
5583
5962
  await ctx.reply("This agent does not support session transfer.", {
@@ -5953,4 +6332,4 @@ export {
5953
6332
  TopicManager,
5954
6333
  TelegramAdapter
5955
6334
  };
5956
- //# sourceMappingURL=chunk-66RVSUAR.js.map
6335
+ //# sourceMappingURL=chunk-FWN3UIRT.js.map