@openacp/cli 2026.326.4 → 2026.327.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/README.md +2 -2
  2. package/dist/{adapter-6ANPBSVU.js → adapter-LC2QSDAS.js} +4 -5
  3. package/dist/{adapter-PQGHVG4K.js → adapter-Y55NXX6I.js} +2 -2
  4. package/dist/{api-server-3PYLRBCN.js → api-server-7G3ZUZRM.js} +2 -2
  5. package/dist/{api-server-CHVSUDBX.js → api-server-CAYNPUF2.js} +2 -2
  6. package/dist/{chunk-UNJUWWQO.js → chunk-2YCW3QDV.js} +21 -14
  7. package/dist/chunk-2YCW3QDV.js.map +1 -0
  8. package/dist/{chunk-Y64XWMJ4.js → chunk-36YQ44D7.js} +2 -2
  9. package/dist/{chunk-UB2QB6DE.js → chunk-3ASUU6WW.js} +2 -2
  10. package/dist/{chunk-V5JT5TPD.js → chunk-4GMLGCF2.js} +2 -2
  11. package/dist/chunk-CDAUYTVP.js +41 -0
  12. package/dist/chunk-CDAUYTVP.js.map +1 -0
  13. package/dist/{chunk-Q6ZXJTZB.js → chunk-HUWOFP2H.js} +9 -17
  14. package/dist/chunk-HUWOFP2H.js.map +1 -0
  15. package/dist/{chunk-P4SNGQNI.js → chunk-KMMEFXIE.js} +2 -2
  16. package/dist/{chunk-RKB2ZK6S.js → chunk-LP45RCA4.js} +579 -153
  17. package/dist/chunk-LP45RCA4.js.map +1 -0
  18. package/dist/{chunk-L7YNNBI5.js → chunk-QAQDGPB4.js} +1 -75
  19. package/dist/chunk-QAQDGPB4.js.map +1 -0
  20. package/dist/{chunk-V2M243KZ.js → chunk-TRXBJEZ5.js} +55 -53
  21. package/dist/chunk-TRXBJEZ5.js.map +1 -0
  22. package/dist/{chunk-NBFIBGAT.js → chunk-UMT7RU77.js} +45 -118
  23. package/dist/chunk-UMT7RU77.js.map +1 -0
  24. package/dist/{chunk-FQEBWOZR.js → chunk-XIBG7LSL.js} +181 -128
  25. package/dist/chunk-XIBG7LSL.js.map +1 -0
  26. package/dist/cli.js +155 -49
  27. package/dist/cli.js.map +1 -1
  28. package/dist/{config-editor-HNEKXRLQ.js → config-editor-3IKBPZA7.js} +2 -2
  29. package/dist/{core-plugins-VEUNFTMB.js → core-plugins-ROU4GPLT.js} +8 -12
  30. package/dist/{dev-loader-RDC5E2CW.js → dev-loader-DRU3R7ZM.js} +7 -18
  31. package/dist/dev-loader-DRU3R7ZM.js.map +1 -0
  32. package/dist/{doctor-H72BZOPA.js → doctor-QZQAP46W.js} +2 -2
  33. package/dist/index.d.ts +128 -66
  34. package/dist/index.js +41 -20
  35. package/dist/index.js.map +1 -1
  36. package/dist/{integrate-5C6KSU6D.js → integrate-G6CVXTGT.js} +3 -4
  37. package/dist/integrate-G6CVXTGT.js.map +1 -0
  38. package/dist/{main-T5WVCCFN.js → main-UVTZ46WP.js} +39 -185
  39. package/dist/main-UVTZ46WP.js.map +1 -0
  40. package/dist/plugin-create-5HQRF2ID.js +967 -0
  41. package/dist/plugin-create-5HQRF2ID.js.map +1 -0
  42. package/dist/plugin-installer-GQ2P3Q3E.js +23 -0
  43. package/dist/plugin-installer-GQ2P3Q3E.js.map +1 -0
  44. package/dist/plugin-search-HQ4WQKOF.js +40 -0
  45. package/dist/plugin-search-HQ4WQKOF.js.map +1 -0
  46. package/dist/{post-upgrade-XLHZ6ZB7.js → post-upgrade-3ADZRMYJ.js} +2 -2
  47. package/dist/registry-client-AVGRE4CF.js +8 -0
  48. package/dist/{setup-BAI2F24H.js → setup-EYAFK2WI.js} +77 -50
  49. package/dist/setup-EYAFK2WI.js.map +1 -0
  50. package/dist/{slack-KH7E3VBS.js → slack-37ZWBDUI.js} +2 -2
  51. package/dist/{telegram-ZDC3JQF2.js → telegram-2ZCCCZIY.js} +2 -2
  52. package/dist/{tunnel-M47I7H4B.js → tunnel-45HA72MB.js} +2 -2
  53. package/dist/{tunnel-service-WADYHREX.js → tunnel-service-QJPUYEKU.js} +11 -3
  54. package/dist/tunnel-service-QJPUYEKU.js.map +1 -0
  55. package/package.json +2 -3
  56. package/dist/action-detect-QPA775HB.js +0 -16
  57. package/dist/adapter-77ZCVABT.js +0 -2394
  58. package/dist/adapter-77ZCVABT.js.map +0 -1
  59. package/dist/admin-GBPZFFAU.js +0 -23
  60. package/dist/agents-BWU4MRRD.js +0 -15
  61. package/dist/chunk-2CX4IEEC.js +0 -124
  62. package/dist/chunk-2CX4IEEC.js.map +0 -1
  63. package/dist/chunk-4KGLKKQK.js +0 -298
  64. package/dist/chunk-4KGLKKQK.js.map +0 -1
  65. package/dist/chunk-5ZOFBTOR.js +0 -553
  66. package/dist/chunk-5ZOFBTOR.js.map +0 -1
  67. package/dist/chunk-6RXVEXF3.js +0 -23
  68. package/dist/chunk-6RXVEXF3.js.map +0 -1
  69. package/dist/chunk-FQEBWOZR.js.map +0 -1
  70. package/dist/chunk-GJOY37U7.js +0 -265
  71. package/dist/chunk-GJOY37U7.js.map +0 -1
  72. package/dist/chunk-HVBNCPAY.js +0 -71
  73. package/dist/chunk-HVBNCPAY.js.map +0 -1
  74. package/dist/chunk-I3CGU5W7.js +0 -134
  75. package/dist/chunk-I3CGU5W7.js.map +0 -1
  76. package/dist/chunk-L7YNNBI5.js.map +0 -1
  77. package/dist/chunk-MTSDOSXS.js +0 -219
  78. package/dist/chunk-MTSDOSXS.js.map +0 -1
  79. package/dist/chunk-NAM4ERUW.js +0 -203
  80. package/dist/chunk-NAM4ERUW.js.map +0 -1
  81. package/dist/chunk-NBFIBGAT.js.map +0 -1
  82. package/dist/chunk-O5RG4YZY.js +0 -122
  83. package/dist/chunk-O5RG4YZY.js.map +0 -1
  84. package/dist/chunk-Q6ZXJTZB.js.map +0 -1
  85. package/dist/chunk-QSDZDHNS.js +0 -145
  86. package/dist/chunk-QSDZDHNS.js.map +0 -1
  87. package/dist/chunk-RKB2ZK6S.js.map +0 -1
  88. package/dist/chunk-UNJUWWQO.js.map +0 -1
  89. package/dist/chunk-V2M243KZ.js.map +0 -1
  90. package/dist/chunk-WAAD23KY.js +0 -222
  91. package/dist/chunk-WAAD23KY.js.map +0 -1
  92. package/dist/chunk-WVLDNYOJ.js +0 -150
  93. package/dist/chunk-WVLDNYOJ.js.map +0 -1
  94. package/dist/dev-loader-RDC5E2CW.js.map +0 -1
  95. package/dist/discord-NOJQ5PZO.js +0 -8
  96. package/dist/doctor-RF6BHMCC.js +0 -15
  97. package/dist/doctor-RF6BHMCC.js.map +0 -1
  98. package/dist/integrate-5C6KSU6D.js.map +0 -1
  99. package/dist/main-T5WVCCFN.js.map +0 -1
  100. package/dist/new-session-AVQCNXRG.js +0 -17
  101. package/dist/new-session-AVQCNXRG.js.map +0 -1
  102. package/dist/plugin-create-AQ3B22BZ.js +0 -334
  103. package/dist/plugin-create-AQ3B22BZ.js.map +0 -1
  104. package/dist/session-KZFA6Z26.js +0 -20
  105. package/dist/session-KZFA6Z26.js.map +0 -1
  106. package/dist/settings-MFYM7CZO.js +0 -14
  107. package/dist/settings-MFYM7CZO.js.map +0 -1
  108. package/dist/setup-BAI2F24H.js.map +0 -1
  109. package/dist/slack-KH7E3VBS.js.map +0 -1
  110. package/dist/telegram-ZDC3JQF2.js.map +0 -1
  111. package/dist/tunnel-M47I7H4B.js.map +0 -1
  112. package/dist/tunnel-service-WADYHREX.js.map +0 -1
  113. package/dist/usage-WYNK6ZC5.js +0 -10
  114. package/dist/usage-WYNK6ZC5.js.map +0 -1
  115. package/dist/validators-6CLEZUBD.js +0 -8
  116. package/dist/validators-6CLEZUBD.js.map +0 -1
  117. /package/dist/{action-detect-QPA775HB.js.map → adapter-LC2QSDAS.js.map} +0 -0
  118. /package/dist/{adapter-PQGHVG4K.js.map → adapter-Y55NXX6I.js.map} +0 -0
  119. /package/dist/{adapter-6ANPBSVU.js.map → api-server-7G3ZUZRM.js.map} +0 -0
  120. /package/dist/{admin-GBPZFFAU.js.map → api-server-CAYNPUF2.js.map} +0 -0
  121. /package/dist/{chunk-Y64XWMJ4.js.map → chunk-36YQ44D7.js.map} +0 -0
  122. /package/dist/{chunk-UB2QB6DE.js.map → chunk-3ASUU6WW.js.map} +0 -0
  123. /package/dist/{chunk-V5JT5TPD.js.map → chunk-4GMLGCF2.js.map} +0 -0
  124. /package/dist/{chunk-P4SNGQNI.js.map → chunk-KMMEFXIE.js.map} +0 -0
  125. /package/dist/{agents-BWU4MRRD.js.map → config-editor-3IKBPZA7.js.map} +0 -0
  126. /package/dist/{api-server-3PYLRBCN.js.map → core-plugins-ROU4GPLT.js.map} +0 -0
  127. /package/dist/{api-server-CHVSUDBX.js.map → doctor-QZQAP46W.js.map} +0 -0
  128. /package/dist/{post-upgrade-XLHZ6ZB7.js.map → post-upgrade-3ADZRMYJ.js.map} +0 -0
  129. /package/dist/{config-editor-HNEKXRLQ.js.map → registry-client-AVGRE4CF.js.map} +0 -0
  130. /package/dist/{core-plugins-VEUNFTMB.js.map → slack-37ZWBDUI.js.map} +0 -0
  131. /package/dist/{discord-NOJQ5PZO.js.map → telegram-2ZCCCZIY.js.map} +0 -0
  132. /package/dist/{doctor-H72BZOPA.js.map → tunnel-45HA72MB.js.map} +0 -0
@@ -1,8 +1,13 @@
1
1
  import {
2
- PRODUCT_GUIDE,
3
- SendQueue,
4
- ToolCallTracker
5
- } from "./chunk-5ZOFBTOR.js";
2
+ buildMenuKeyboard,
3
+ buildSkillMessages,
4
+ handleClear,
5
+ handleHelp,
6
+ handleMenu
7
+ } from "./chunk-AFKX424Q.js";
8
+ import {
9
+ DoctorEngine
10
+ } from "./chunk-QAQDGPB4.js";
6
11
  import {
7
12
  BaseRenderer,
8
13
  MessagingAdapter,
@@ -15,17 +20,7 @@ import {
15
20
  splitMessage,
16
21
  stripCodeFences,
17
22
  truncateContent
18
- } from "./chunk-V2M243KZ.js";
19
- import {
20
- buildMenuKeyboard,
21
- buildSkillMessages,
22
- handleClear,
23
- handleHelp,
24
- handleMenu
25
- } from "./chunk-AFKX424Q.js";
26
- import {
27
- DoctorEngine
28
- } from "./chunk-L7YNNBI5.js";
23
+ } from "./chunk-TRXBJEZ5.js";
29
24
  import {
30
25
  CheckpointReader,
31
26
  DEFAULT_MAX_TOKENS
@@ -205,43 +200,6 @@ ${bar} ${pct}%`;
205
200
  \u{1F4B0} $${cost.toFixed(2)}`;
206
201
  return text;
207
202
  }
208
- var PERIOD_LABEL = {
209
- today: "Today",
210
- week: "This Week",
211
- month: "This Month",
212
- all: "All Time"
213
- };
214
- function formatUsageReport(summaries, budgetStatus) {
215
- const hasData = summaries.some((s) => s.recordCount > 0);
216
- if (!hasData) {
217
- return "\u{1F4CA} <b>Usage Report</b>\n\nNo usage data yet.";
218
- }
219
- const formatCost = (n) => `$${n.toFixed(2)}`;
220
- const lines = ["\u{1F4CA} <b>Usage Report</b>"];
221
- for (const summary of summaries) {
222
- lines.push("");
223
- lines.push(
224
- `\u2500\u2500 <b>${PERIOD_LABEL[summary.period] ?? summary.period}</b> \u2500\u2500`
225
- );
226
- lines.push(
227
- `\u{1F4B0} ${formatCost(summary.totalCost)} \xB7 \u{1F524} ${formatTokens(summary.totalTokens)} tokens \xB7 \u{1F4CB} ${summary.sessionCount} sessions`
228
- );
229
- if (summary.period === "month" && budgetStatus.budget > 0) {
230
- const bar = progressBar(budgetStatus.used / budgetStatus.budget);
231
- lines.push(
232
- `Budget: ${formatCost(budgetStatus.used)} / ${formatCost(budgetStatus.budget)} (${budgetStatus.percent}%)`
233
- );
234
- lines.push(`${bar} ${budgetStatus.percent}%`);
235
- }
236
- }
237
- return lines.join("\n");
238
- }
239
- function formatSummary(summary, sessionName) {
240
- const header = sessionName ? `\u{1F4CB} <b>Summary \u2014 ${escapeHtml(sessionName)}</b>` : "\u{1F4CB} <b>Session Summary</b>";
241
- return `${header}
242
-
243
- ${escapeHtml(summary)}`;
244
- }
245
203
  function splitMessage2(text, maxLength = 3800) {
246
204
  return splitMessage(text, maxLength);
247
205
  }
@@ -1277,27 +1235,6 @@ function setupSessionCallbacks(bot, core, chatId, systemTopicIds) {
1277
1235
  }
1278
1236
  });
1279
1237
  }
1280
- async function handleUsage(ctx, core) {
1281
- if (!core.usageStore) {
1282
- await ctx.reply("\u{1F4CA} Usage tracking is disabled.", { parse_mode: "HTML" });
1283
- return;
1284
- }
1285
- const rawMatch = ctx.match;
1286
- const period = typeof rawMatch === "string" ? rawMatch.trim().toLowerCase() : "";
1287
- let summaries;
1288
- if (period === "today" || period === "week" || period === "month") {
1289
- summaries = [core.usageStore.query(period)];
1290
- } else {
1291
- summaries = [
1292
- core.usageStore.query("month"),
1293
- core.usageStore.query("week"),
1294
- core.usageStore.query("today")
1295
- ];
1296
- }
1297
- const budgetStatus = core.usageBudget ? core.usageBudget.getStatus() : { status: "ok", used: 0, budget: 0, percent: 0 };
1298
- const text = formatUsageReport(summaries, budgetStatus);
1299
- await ctx.reply(text, { parse_mode: "HTML" });
1300
- }
1301
1238
  async function handleArchive(ctx, core) {
1302
1239
  const threadId = ctx.message?.message_thread_id;
1303
1240
  if (!threadId) return;
@@ -1365,57 +1302,6 @@ async function handleArchiveConfirm(ctx, core, chatId) {
1365
1302
  }
1366
1303
  }
1367
1304
  }
1368
- async function handleSummary(ctx, core) {
1369
- const threadId = ctx.message?.message_thread_id;
1370
- if (!threadId) return;
1371
- const session = core.sessionManager.getSessionByThread("telegram", String(threadId));
1372
- const record = !session ? core.sessionManager.getRecordByThread("telegram", String(threadId)) : void 0;
1373
- const sessionId = session?.id ?? record?.sessionId;
1374
- if (!sessionId) {
1375
- await ctx.reply(
1376
- "\u2139\uFE0F <b>/summary</b> works in session topics \u2014 it asks the agent to summarize the session.\n\nGo to a session topic and type /summary there.",
1377
- { parse_mode: "HTML" }
1378
- );
1379
- return;
1380
- }
1381
- await ctx.replyWithChatAction("typing");
1382
- const result = await core.summarizeSession(sessionId);
1383
- if (result.ok) {
1384
- await ctx.reply(formatSummary(result.summary, session?.name ?? record?.name), { parse_mode: "HTML" });
1385
- } else {
1386
- await ctx.reply(`\u26A0\uFE0F ${escapeHtml(result.error)}`, { parse_mode: "HTML" });
1387
- }
1388
- }
1389
- async function handleSummaryCallback(ctx, core, chatId) {
1390
- const data = ctx.callbackQuery?.data;
1391
- if (!data) return;
1392
- const sessionId = data.replace("sm:summary:", "");
1393
- try {
1394
- await ctx.answerCallbackQuery();
1395
- } catch {
1396
- }
1397
- const session = core.sessionManager.getSession(sessionId);
1398
- const record = !session ? core.sessionManager.getSessionRecord(sessionId) : void 0;
1399
- const threadId = session ? Number(session.threadId) : record?.platform?.topicId ?? 0;
1400
- if (!threadId) return;
1401
- await ctx.api.sendMessage(chatId, "\u{1F4CB} Generating summary...", {
1402
- message_thread_id: threadId,
1403
- parse_mode: "HTML"
1404
- });
1405
- const result = await core.summarizeSession(sessionId);
1406
- const sessionName = session?.name ?? record?.name;
1407
- if (result.ok) {
1408
- await ctx.api.sendMessage(chatId, formatSummary(result.summary, sessionName), {
1409
- message_thread_id: threadId,
1410
- parse_mode: "HTML"
1411
- });
1412
- } else {
1413
- await ctx.api.sendMessage(chatId, `\u26A0\uFE0F ${escapeHtml(result.error)}`, {
1414
- message_thread_id: threadId,
1415
- parse_mode: "HTML"
1416
- });
1417
- }
1418
- }
1419
1305
 
1420
1306
  // src/plugins/telegram/commands/agents.ts
1421
1307
  import { InlineKeyboard as InlineKeyboard4 } from "grammy";
@@ -1619,7 +1505,7 @@ Downloading... ${bar} ${percent}%`, { parse_mode: "HTML" });
1619
1505
  const { getAgentCapabilities } = await import("./agent-dependencies-WS7Z2DFW.js");
1620
1506
  const caps = getAgentCapabilities(result.agentKey);
1621
1507
  if (caps.integration) {
1622
- const { installIntegration } = await import("./integrate-5C6KSU6D.js");
1508
+ const { installIntegration } = await import("./integrate-G6CVXTGT.js");
1623
1509
  const intResult = await installIntegration(result.agentKey, caps.integration);
1624
1510
  if (intResult.success) {
1625
1511
  try {
@@ -1689,7 +1575,7 @@ function buildProgressBar(percent) {
1689
1575
  // src/plugins/telegram/commands/integrate.ts
1690
1576
  import { InlineKeyboard as InlineKeyboard5 } from "grammy";
1691
1577
  async function handleIntegrate(ctx, _core) {
1692
- const { listIntegrations } = await import("./integrate-5C6KSU6D.js");
1578
+ const { listIntegrations } = await import("./integrate-G6CVXTGT.js");
1693
1579
  const agents = listIntegrations();
1694
1580
  const keyboard = new InlineKeyboard5();
1695
1581
  for (const agent of agents) {
@@ -1722,7 +1608,7 @@ function setupIntegrateCallbacks(bot, core) {
1722
1608
  } catch {
1723
1609
  }
1724
1610
  if (data === "i:back") {
1725
- const { listIntegrations } = await import("./integrate-5C6KSU6D.js");
1611
+ const { listIntegrations } = await import("./integrate-G6CVXTGT.js");
1726
1612
  const agents = listIntegrations();
1727
1613
  const keyboard2 = new InlineKeyboard5();
1728
1614
  for (const agent of agents) {
@@ -1742,7 +1628,7 @@ Select an agent to manage its integrations.`,
1742
1628
  const agentMatch = data.match(/^i:agent:(.+)$/);
1743
1629
  if (agentMatch) {
1744
1630
  const agentName2 = agentMatch[1];
1745
- const { getIntegration: getIntegration2 } = await import("./integrate-5C6KSU6D.js");
1631
+ const { getIntegration: getIntegration2 } = await import("./integrate-G6CVXTGT.js");
1746
1632
  const integration2 = getIntegration2(agentName2);
1747
1633
  if (!integration2) {
1748
1634
  await ctx.reply(`\u274C No integration available for '${escapeHtml(agentName2)}'.`, { parse_mode: "HTML" });
@@ -1769,7 +1655,7 @@ ${integration2.items.map((i) => `\u2022 <b>${escapeHtml(i.name)}</b> \u2014 ${es
1769
1655
  const action = actionMatch[1];
1770
1656
  const agentName = actionMatch[2];
1771
1657
  const itemId = actionMatch[3];
1772
- const { getIntegration } = await import("./integrate-5C6KSU6D.js");
1658
+ const { getIntegration } = await import("./integrate-G6CVXTGT.js");
1773
1659
  const integration = getIntegration(agentName);
1774
1660
  if (!integration) return;
1775
1661
  const item = integration.items.find((i) => i.id === itemId);
@@ -2570,11 +2456,9 @@ function setupCommands(bot, core, chatId, assistant) {
2570
2456
  bot.command("integrate", (ctx) => handleIntegrate(ctx, core));
2571
2457
  bot.command("clear", (ctx) => handleClear(ctx, assistant));
2572
2458
  bot.command("doctor", (ctx) => handleDoctor(ctx));
2573
- bot.command("usage", (ctx) => handleUsage(ctx, core));
2574
2459
  bot.command("tunnel", (ctx) => handleTunnel(ctx, core));
2575
2460
  bot.command("tunnels", (ctx) => handleTunnels(ctx, core));
2576
2461
  bot.command("archive", (ctx) => handleArchive(ctx, core));
2577
- bot.command("summary", (ctx) => handleSummary(ctx, core));
2578
2462
  bot.command("text_to_speech", (ctx) => handleTTS(ctx, core));
2579
2463
  bot.command("verbosity", (ctx) => handleVerbosity(ctx, core));
2580
2464
  bot.command("resume", (ctx) => handleResume(ctx, core, chatId, assistant));
@@ -2599,7 +2483,6 @@ function setupAllCallbacks(bot, core, chatId, systemTopicIds, getAssistantSessio
2599
2483
  );
2600
2484
  });
2601
2485
  bot.callbackQuery(/^ar:/, (ctx) => handleArchiveConfirm(ctx, core, chatId));
2602
- bot.callbackQuery(/^sm:/, (ctx) => handleSummaryCallback(ctx, core, chatId));
2603
2486
  bot.callbackQuery(/^m:/, async (ctx) => {
2604
2487
  const data = ctx.callbackQuery.data;
2605
2488
  try {
@@ -2661,11 +2544,9 @@ var STATIC_COMMANDS = [
2661
2544
  { command: "restart", description: "Restart OpenACP" },
2662
2545
  { command: "update", description: "Update to latest version and restart" },
2663
2546
  { command: "doctor", description: "Run system diagnostics" },
2664
- { command: "usage", description: "View token usage and cost report" },
2665
2547
  { command: "tunnel", description: "Create/stop tunnel for a local port" },
2666
2548
  { command: "tunnels", description: "List active tunnels" },
2667
2549
  { command: "archive", description: "Archive session topic (recreate with clean history)" },
2668
- { command: "summary", description: "Get AI summary of current session" },
2669
2550
  { command: "text_to_speech", description: "Toggle Text to Speech (/text_to_speech on, /text_to_speech off)" },
2670
2551
  { command: "verbosity", description: "Set display verbosity (/verbosity low|medium|high)" },
2671
2552
  { command: "resume", description: "Resume with conversation history from Entire checkpoints" }
@@ -2751,6 +2632,424 @@ ${escapeHtml(request.description)}`,
2751
2632
  }
2752
2633
  };
2753
2634
 
2635
+ // src/data/product-guide.ts
2636
+ var PRODUCT_GUIDE = `
2637
+ # OpenACP \u2014 Product Guide
2638
+
2639
+ OpenACP lets you chat with AI coding agents (like Claude Code) through messaging platforms (Telegram, Discord).
2640
+ You type messages in your chat platform, the agent reads/writes/runs code in your project folder, and results stream back in real time.
2641
+
2642
+ ---
2643
+
2644
+ ## Quick Start
2645
+
2646
+ 1. Start OpenACP: \`openacp\` (or \`openacp start\` for background daemon)
2647
+ 2. Open your messaging platform (Telegram group or Discord server) \u2014 you'll see the Assistant topic/thread
2648
+ 3. Tap/click \u{1F195} New Session or type /new
2649
+ 4. Pick an agent and a project folder
2650
+ 5. Chat in the session topic/thread \u2014 the agent works on your code
2651
+
2652
+ ---
2653
+
2654
+ ## Core Concepts
2655
+
2656
+ ### Sessions
2657
+ A session = one conversation with one AI agent working in one project folder.
2658
+ Each session gets its own topic (Telegram) or forum thread (Discord). Chat there to give instructions to the agent.
2659
+
2660
+ ### Agents
2661
+ An agent is an AI coding tool (e.g., Claude Code, Gemini, Cursor, Codex, etc.).
2662
+ OpenACP supports 28+ agents from the official ACP Registry (agentclientprotocol.com).
2663
+ You can install multiple agents and choose which one to use per session.
2664
+ The default agent is used when you don't specify one.
2665
+
2666
+ ### Agent Management
2667
+ - Browse agents: \`/agents\` in your chat platform or \`openacp agents\` in CLI
2668
+ - Install: tap the install button in /agents, or \`openacp agents install <name>\`
2669
+ - Uninstall: \`openacp agents uninstall <name>\`
2670
+ - Setup/login: \`openacp agents run <name> -- <args>\` (e.g., \`openacp agents run gemini -- auth login\`)
2671
+ - Details: \`openacp agents info <name>\` shows version, dependencies, and setup steps
2672
+
2673
+ Some agents need additional setup before they can be used:
2674
+ - Claude: requires \`claude login\`
2675
+ - Gemini: requires \`openacp agents run gemini -- auth login\`
2676
+ - Codex: requires setting \`OPENAI_API_KEY\` environment variable
2677
+ - GitHub Copilot: requires \`openacp agents run copilot -- auth login\`
2678
+
2679
+ Agents are installed in three ways depending on the agent:
2680
+ - **npx** \u2014 Node.js agents, downloaded automatically on first use
2681
+ - **uvx** \u2014 Python agents, downloaded automatically on first use
2682
+ - **binary** \u2014 Platform-specific binaries, downloaded to \`~/.openacp/agents/\`
2683
+
2684
+ ### Project Folder (Workspace)
2685
+ The directory where the agent reads, writes, and runs code.
2686
+ When creating a session, you choose which folder the agent works in.
2687
+ You can type a full path like \`~/code/my-project\` or just a name like \`my-project\` (it becomes \`<base-dir>/my-project\`).
2688
+
2689
+ ### System Topics
2690
+ - **Assistant** \u2014 Always-on helper that can answer questions, create sessions, check status, troubleshoot
2691
+ - **Notifications** \u2014 System alerts (permission requests, session errors, completions)
2692
+
2693
+ ---
2694
+
2695
+ ## Creating Sessions
2696
+
2697
+ ### From menu
2698
+ Tap \u{1F195} New Session \u2192 choose agent (if multiple) \u2192 choose project folder \u2192 confirm
2699
+
2700
+ ### From command
2701
+ - \`/new\` \u2014 Interactive flow (asks agent + folder)
2702
+ - \`/new claude ~/code/my-project\` \u2014 Create directly with specific agent and folder
2703
+
2704
+ ### From Assistant topic
2705
+ Just ask: "Create a session for my-project with claude" \u2014 the assistant handles it
2706
+
2707
+ ### Quick new chat
2708
+ \`/newchat\` in a session topic \u2014 creates new session with same agent and folder as current one
2709
+
2710
+ ---
2711
+
2712
+ ## Working with Sessions
2713
+
2714
+ ### Chat
2715
+ Type messages in the session topic. The agent responds with code changes, explanations, tool outputs.
2716
+
2717
+ ### What you see while the agent works
2718
+ - **\u{1F4AD} Thinking indicator** \u2014 Shows when the agent is reasoning, with elapsed time
2719
+ - **Text responses** \u2014 Streamed in real time, updated every few seconds
2720
+ - **Tool calls** \u2014 When the agent runs commands or edits files, you see tool name, input, status, and output
2721
+ - **\u{1F4CB} Plan card** \u2014 Visual task progress with completed/in-progress/pending items and progress bar
2722
+ - **"View File" / "View Diff" buttons** \u2014 Opens in browser with Monaco editor (requires tunnel)
2723
+
2724
+ ### Session lifecycle
2725
+ 1. **Creating** \u2014 Topic created, agent spawning
2726
+ 2. **Warming up** \u2014 Agent primes its cache (happens automatically, invisible to you)
2727
+ 3. **Active** \u2014 Ready for your messages
2728
+ 4. **Auto-naming** \u2014 After your first message, the session gets a descriptive name (agent summarizes in ~5 words). The topic title updates automatically.
2729
+ 5. **Finished/Error** \u2014 Session completed or hit an error
2730
+
2731
+ ### Agent skills
2732
+ Some agents provide slash commands (e.g., /compact, /review). Available skills are pinned in the session topic.
2733
+
2734
+ ### Permission requests
2735
+ When the agent wants to run a command, it asks for permission.
2736
+ You see buttons: \u2705 Allow, \u274C Reject (and sometimes "Always Allow").
2737
+ A notification also appears in the Notifications topic with a link to the request.
2738
+
2739
+ ### Dangerous mode
2740
+ Auto-approves ALL permission requests \u2014 the agent runs any command without asking.
2741
+ - Enable: \`/enable_dangerous\` or tap the \u2620\uFE0F button in the session
2742
+ - Disable: \`/disable_dangerous\` or tap the \u{1F510} button
2743
+ - \u26A0\uFE0F Use with caution \u2014 the agent can execute anything
2744
+
2745
+ ### Session timeout
2746
+ Idle sessions are automatically cancelled after a configurable timeout (default: 60 minutes).
2747
+ Configure via \`security.sessionTimeoutMinutes\` in config.
2748
+
2749
+ ---
2750
+
2751
+ ## Session Transfer (Handoff)
2752
+
2753
+ ### Chat \u2192 Terminal
2754
+ 1. Type \`/handoff\` in a session topic/thread
2755
+ 2. You get a command like \`claude --resume <SESSION_ID>\`
2756
+ 3. Copy and run it in your terminal \u2014 the session continues there with full conversation history
2757
+
2758
+ ### Terminal \u2192 Chat
2759
+ 1. First time: run \`openacp integrate claude\` to install the handoff skill (one-time setup)
2760
+ 2. In Claude Code, use the /openacp:handoff slash command
2761
+ 3. The session appears as a new topic/thread and you can continue chatting there
2762
+
2763
+ ### How it works
2764
+ - The agent session ID is shared between platforms
2765
+ - Conversation history is preserved \u2014 pick up where you left off
2766
+ - The agent that supports resume (e.g., Claude with \`--resume\`) handles the actual transfer
2767
+
2768
+ ---
2769
+
2770
+ ## Managing Sessions
2771
+
2772
+ ### Status
2773
+ - \`/status\` \u2014 Shows active sessions count and details
2774
+ - Ask the Assistant: "What sessions are running?"
2775
+
2776
+ ### List all sessions
2777
+ - \`/sessions\` \u2014 Shows all sessions with status (active, finished, error)
2778
+
2779
+ ### Cancel
2780
+ - \`/cancel\` in a session topic \u2014 cancels that session
2781
+ - Ask the Assistant: "Cancel the stuck session"
2782
+
2783
+ ### Cleanup
2784
+ - From \`/sessions\` \u2192 tap cleanup buttons (finished, errors, all)
2785
+ - Ask the Assistant: "Clean up old sessions"
2786
+
2787
+ ---
2788
+
2789
+ ## Assistant Topic
2790
+
2791
+ The Assistant is an always-on AI helper in its own topic. It can:
2792
+ - Answer questions about OpenACP
2793
+ - Create sessions for you
2794
+ - Check status and health
2795
+ - Cancel sessions
2796
+ - Clean up old sessions
2797
+ - Troubleshoot issues
2798
+ - Manage configuration
2799
+
2800
+ Just chat naturally: "How do I create a session?", "What's the status?", "Something is stuck"
2801
+
2802
+ ### Clear history
2803
+ \`/clear\` in the Assistant topic \u2014 resets the conversation
2804
+
2805
+ ---
2806
+
2807
+ ## System Commands
2808
+
2809
+ | Command | Where | What it does |
2810
+ |---------|-------|-------------|
2811
+ | \`/new [agent] [path]\` | Anywhere | Create new session |
2812
+ | \`/newchat\` | Session topic | New session, same agent + folder |
2813
+ | \`/cancel\` | Session topic | Cancel current session |
2814
+ | \`/status\` | Anywhere | Show status |
2815
+ | \`/sessions\` | Anywhere | List all sessions |
2816
+ | \`/agents\` | Anywhere | Browse & install agents from ACP Registry |
2817
+ | \`/install <name>\` | Anywhere | Install an agent |
2818
+ | \`/enable_dangerous\` | Session topic | Auto-approve all permissions |
2819
+ | \`/disable_dangerous\` | Session topic | Restore permission prompts |
2820
+ | \`/handoff\` | Session topic | Transfer session to terminal |
2821
+ | \`/clear\` | Assistant topic | Clear assistant history |
2822
+ | \`/menu\` | Anywhere | Show action menu |
2823
+ | \`/help\` | Anywhere | Show help |
2824
+ | \`/restart\` | Anywhere | Restart OpenACP |
2825
+ | \`/update\` | Anywhere | Update to latest version |
2826
+ | \`/integrate\` | Anywhere | Manage agent integrations |
2827
+
2828
+ ---
2829
+
2830
+ ## Menu Buttons
2831
+
2832
+ | Button | Action |
2833
+ |--------|--------|
2834
+ | \u{1F195} New Session | Create new session (interactive) |
2835
+ | \u{1F4CB} Sessions | List all sessions with cleanup options |
2836
+ | \u{1F4CA} Status | Show active/total session count |
2837
+ | \u{1F916} Agents | List available agents |
2838
+ | \u{1F517} Integrate | Manage agent integrations |
2839
+ | \u2753 Help | Show help text |
2840
+ | \u{1F504} Restart | Restart OpenACP |
2841
+ | \u2B06\uFE0F Update | Check and install updates |
2842
+
2843
+ ---
2844
+
2845
+ ## CLI Commands
2846
+
2847
+ ### Server
2848
+ - \`openacp\` \u2014 Start (uses configured mode: foreground or daemon)
2849
+ - \`openacp start\` \u2014 Start as background daemon
2850
+ - \`openacp stop\` \u2014 Stop daemon
2851
+ - \`openacp status\` \u2014 Show daemon status
2852
+ - \`openacp logs\` \u2014 Tail daemon logs
2853
+ - \`openacp --foreground\` \u2014 Force foreground mode (useful for debugging or containers)
2854
+
2855
+ ### Auto-start (run on boot)
2856
+ - macOS: installs a LaunchAgent in \`~/Library/LaunchAgents/\`
2857
+ - Linux: installs a systemd user service in \`~/.config/systemd/user/\`
2858
+ - Enabled automatically when you start the daemon. Remove with \`openacp stop\`.
2859
+
2860
+ ### Configuration
2861
+ - \`openacp config\` \u2014 Interactive config editor
2862
+ - \`openacp reset\` \u2014 Delete all data and start fresh
2863
+
2864
+ ### Agent Management (CLI)
2865
+ - \`openacp agents\` \u2014 List all agents (installed + available from ACP Registry)
2866
+ - \`openacp agents install <name>\` \u2014 Install an agent
2867
+ - \`openacp agents uninstall <name>\` \u2014 Remove an agent
2868
+ - \`openacp agents info <name>\` \u2014 Show details, dependencies, and setup guide
2869
+ - \`openacp agents run <name> [-- args]\` \u2014 Run agent CLI directly (for login, config, etc.)
2870
+ - \`openacp agents refresh\` \u2014 Force-refresh registry cache
2871
+
2872
+ ### Plugins
2873
+ - \`openacp install <package>\` \u2014 Install adapter plugin
2874
+ - \`openacp uninstall <package>\` \u2014 Remove adapter plugin
2875
+ - \`openacp plugins\` \u2014 List installed plugins
2876
+
2877
+ ### Integration
2878
+ - \`openacp integrate <agent>\` \u2014 Install agent integration (e.g., Claude handoff skill)
2879
+ - \`openacp integrate <agent> --uninstall\` \u2014 Remove integration
2880
+
2881
+ ### API (requires running daemon)
2882
+ \`openacp api <command>\` \u2014 Interact with running daemon:
2883
+
2884
+ | Command | Description |
2885
+ |---------|-------------|
2886
+ | \`status\` | List active sessions |
2887
+ | \`session <id>\` | Session details |
2888
+ | \`new <agent> <path>\` | Create session |
2889
+ | \`send <id> "text"\` | Send prompt |
2890
+ | \`cancel <id>\` | Cancel session |
2891
+ | \`dangerous <id> on/off\` | Toggle dangerous mode |
2892
+ | \`topics [--status x,y]\` | List topics |
2893
+ | \`delete-topic <id> [--force]\` | Delete topic |
2894
+ | \`cleanup [--status x,y]\` | Cleanup old topics |
2895
+ | \`agents\` | List agents |
2896
+ | \`health\` | System health |
2897
+ | \`config\` | Show config |
2898
+ | \`config set <key> <value>\` | Update config |
2899
+ | \`adapters\` | List adapters |
2900
+ | \`tunnel\` | Tunnel status |
2901
+ | \`notify "message"\` | Send notification |
2902
+ | \`version\` | Daemon version |
2903
+ | \`restart\` | Restart daemon |
2904
+
2905
+ ---
2906
+
2907
+ ## File Viewer (Tunnel)
2908
+
2909
+ When tunnel is enabled, file edits and diffs get "View" buttons that open in your browser:
2910
+ - **Monaco Editor** \u2014 Full VS Code editor with syntax highlighting
2911
+ - **Diff viewer** \u2014 Side-by-side or inline comparison
2912
+ - **Line highlighting** \u2014 Click lines to highlight
2913
+ - Dark/light theme toggle
2914
+
2915
+ ### Setup
2916
+ Enable in config: set \`tunnel.enabled\` to \`true\`.
2917
+ Providers: Cloudflare (default, free), ngrok, bore, Tailscale Funnel.
2918
+
2919
+ ### Port Tunneling
2920
+
2921
+ Expose any local port (dev servers, APIs, etc.) to the internet:
2922
+
2923
+ **CLI commands** (agent can call these directly):
2924
+ - \`openacp tunnel add <port> --label <name>\` \u2014 Create tunnel to a local port
2925
+ - \`openacp tunnel list\` \u2014 List active tunnels
2926
+ - \`openacp tunnel stop <port>\` \u2014 Stop a tunnel
2927
+ - \`openacp tunnel stop-all\` \u2014 Stop all user tunnels
2928
+
2929
+ **Telegram commands**:
2930
+ - \`/tunnel <port> [label]\` \u2014 Create tunnel
2931
+ - \`/tunnels\` \u2014 List active tunnels
2932
+ - \`/tunnel stop <port>\` \u2014 Stop tunnel
2933
+
2934
+ Example: after starting a dev server on port 3000, run \`openacp tunnel add 3000 --label my-app\` to get a public URL.
2935
+
2936
+ ---
2937
+
2938
+ ## Configuration
2939
+
2940
+ Config file: \`~/.openacp/config.json\`
2941
+
2942
+ ### Channels
2943
+ - **channels.telegram.botToken** \u2014 Your Telegram bot token
2944
+ - **channels.telegram.chatId** \u2014 Your Telegram supergroup ID
2945
+ - **channels.discord.botToken** \u2014 Your Discord bot token
2946
+ - **channels.discord.guildId** \u2014 Your Discord server (guild) ID
2947
+
2948
+ ### Agents
2949
+ - **defaultAgent** \u2014 Which agent to use by default
2950
+ - Agents are managed via \`/agents\` (Telegram) or \`openacp agents\` (CLI)
2951
+ - Installed agents are stored in \`~/.openacp/agents.json\`
2952
+ - Agent list is fetched from the ACP Registry CDN and cached locally (24h)
2953
+
2954
+ ### Workspace
2955
+ - **workspace.baseDir** \u2014 Base directory for project folders (default: \`~/openacp-workspace\`)
2956
+
2957
+ ### Security
2958
+ - **security.allowedUserIds** \u2014 Restrict who can use the bot (empty = everyone)
2959
+ - **security.maxConcurrentSessions** \u2014 Max parallel sessions (default: 5)
2960
+ - **security.sessionTimeoutMinutes** \u2014 Auto-cancel idle sessions (default: 60)
2961
+
2962
+ ### Tunnel / File Viewer
2963
+ - **tunnel.enabled** \u2014 Enable file viewer tunnel
2964
+ - **tunnel.provider** \u2014 Tunnel provider: cloudflare (default, free), ngrok, bore, tailscale
2965
+ - **tunnel.port** \u2014 Local port for tunnel server (default: 3100)
2966
+ - **tunnel.auth.enabled** \u2014 Enable authentication for tunnel URLs
2967
+ - **tunnel.auth.token** \u2014 Auth token for tunnel access
2968
+ - **tunnel.storeTtlMinutes** \u2014 How long viewer links stay cached (default: 60)
2969
+
2970
+ ### Logging
2971
+ - **logging.level** \u2014 Log level: silent, debug, info, warn, error, fatal (default: info)
2972
+ - **logging.logDir** \u2014 Log directory (default: \`~/.openacp/logs\`)
2973
+ - **logging.maxFileSize** \u2014 Max log file size before rotation
2974
+ - **logging.maxFiles** \u2014 Max number of rotated log files
2975
+ - **logging.sessionLogRetentionDays** \u2014 Auto-delete old session logs (default: 30)
2976
+
2977
+ ### Data Retention
2978
+ - **sessionStore.ttlDays** \u2014 How long session records persist (default: 30). Old records are cleaned up automatically.
2979
+
2980
+ ### Environment variables
2981
+ Override config with env vars:
2982
+ - \`OPENACP_TELEGRAM_BOT_TOKEN\`
2983
+ - \`OPENACP_TELEGRAM_CHAT_ID\`
2984
+ - \`OPENACP_DISCORD_BOT_TOKEN\`
2985
+ - \`OPENACP_DISCORD_GUILD_ID\`
2986
+ - \`OPENACP_DEFAULT_AGENT\`
2987
+ - \`OPENACP_RUN_MODE\` \u2014 foreground or daemon
2988
+ - \`OPENACP_API_PORT\` \u2014 API server port (default: 21420)
2989
+ - \`OPENACP_TUNNEL_ENABLED\`
2990
+ - \`OPENACP_TUNNEL_PORT\`
2991
+ - \`OPENACP_TUNNEL_PROVIDER\`
2992
+ - \`OPENACP_LOG_LEVEL\`
2993
+ - \`OPENACP_LOG_DIR\`
2994
+ - \`OPENACP_DEBUG\` \u2014 Sets log level to debug
2995
+
2996
+ ---
2997
+
2998
+ ## Troubleshooting
2999
+
3000
+ ### Session stuck / not responding
3001
+ - Check status: ask Assistant "Is anything stuck?"
3002
+ - Cancel and create new: \`/cancel\` then \`/new\`
3003
+ - Check system health: Assistant can run health check
3004
+
3005
+ ### Agent not found
3006
+ - Check available agents: \`/agents\` or \`openacp agents\`
3007
+ - Install missing agent: \`openacp agents install <name>\`
3008
+ - Some agents need login first: \`openacp agents info <name>\` to see setup steps
3009
+ - Run agent CLI for setup: \`openacp agents run <name> -- <args>\`
3010
+
3011
+ ### Permission request not showing
3012
+ - Check Notifications topic for the alert
3013
+ - Try \`/enable_dangerous\` to auto-approve (if you trust the agent)
3014
+
3015
+ ### Session disappeared after restart
3016
+ - Sessions persist across restarts
3017
+ - Send a message in the old topic \u2014 it auto-resumes
3018
+ - If topic was deleted, the session record may still exist in status
3019
+
3020
+ ### Bot not responding at all
3021
+ - Check daemon: \`openacp status\`
3022
+ - Check logs: \`openacp logs\`
3023
+ - Restart: \`openacp start\` or \`/restart\`
3024
+
3025
+ ### Messages going to wrong topic
3026
+ - Each session is bound to a specific topic/thread
3027
+ - If you see messages appearing in the Assistant topic instead of the session topic, try creating a new session
3028
+
3029
+ ### Viewing logs
3030
+ - Session-specific logs: \`~/.openacp/logs/sessions/\`
3031
+ - System logs: \`openacp logs\` to tail live
3032
+ - Set \`OPENACP_DEBUG=true\` for verbose output
3033
+
3034
+ ---
3035
+
3036
+ ## Data & Storage
3037
+
3038
+ All data is stored in \`~/.openacp/\`:
3039
+ - \`config.json\` \u2014 Configuration
3040
+ - \`agents.json\` \u2014 Installed agents (managed by AgentCatalog)
3041
+ - \`registry-cache.json\` \u2014 Cached ACP Registry data (refreshes every 24h)
3042
+ - \`agents/\` \u2014 Downloaded binary agents
3043
+ - \`sessions/\` \u2014 Session records and state
3044
+ - \`topics/\` \u2014 Topic-to-session mappings
3045
+ - \`logs/\` \u2014 System and session logs
3046
+ - \`plugins/\` \u2014 Installed adapter plugins
3047
+ - \`openacp.pid\` \u2014 Daemon PID file
3048
+
3049
+ Session records auto-cleanup: 30 days (configurable via \`sessionStore.ttlDays\`).
3050
+ Session logs auto-cleanup: 30 days (configurable via \`logging.sessionLogRetentionDays\`).
3051
+ `;
3052
+
2754
3053
  // src/plugins/telegram/assistant.ts
2755
3054
  var log9 = createChildLogger({ module: "telegram-assistant" });
2756
3055
  async function spawnAssistant(core, adapter, assistantTopicId) {
@@ -2834,7 +3133,7 @@ function buildAssistantSystemPrompt(ctx) {
2834
3133
  - Ask which agent to use (if multiple are installed). Show installed: ${agentNames}
2835
3134
  - Ask which project directory to use as workspace. Suggest \`${config.workspace.baseDir}\` as the base, but explain the user can provide any path.
2836
3135
  - Confirm before creating: show agent name + full workspace path.
2837
- - Create via: \`openacp api new <agent> <workspace>\`
3136
+ - Create via: \`openacp api new <agent> <workspace> --channel telegram\`
2838
3137
 
2839
3138
  ### Browse & Install Agents
2840
3139
  - Guide users to /agents command to see all available agents (installed + from ACP Registry)
@@ -2896,7 +3195,7 @@ function buildAssistantSystemPrompt(ctx) {
2896
3195
  # Session management
2897
3196
  openacp api status # List active sessions
2898
3197
  openacp api session <id> # Session detail
2899
- openacp api new <agent> <workspace> # Create new session
3198
+ openacp api new <agent> <workspace> --channel telegram # Create new session
2900
3199
  openacp api send <id> "prompt text" # Send prompt to session
2901
3200
  openacp api cancel <id> # Cancel session
2902
3201
  openacp api dangerous <id> on|off # Toggle dangerous mode
@@ -2937,7 +3236,7 @@ openacp api restart # Restart daemon
2937
3236
  - Respond in the same language the user uses.
2938
3237
  - Format responses for Telegram: use <b>bold</b>, <code>code</code>, keep it concise.
2939
3238
  - When you don't know something, check with the relevant \`openacp api\` command first before answering.
2940
- - Talk to users like a helpful assistant, not a CLI manual. Example: "B\u1EA1n c\xF3 2 session \u0111ang ch\u1EA1y. Mu\u1ED1n xem chi ti\u1EBFt kh\xF4ng?" instead of listing commands.
3239
+ - Talk to users like a helpful assistant, not a CLI manual. Example: "You have 2 sessions running. Want to see details?" instead of listing commands.
2941
3240
 
2942
3241
  ## Product Reference
2943
3242
  ${PRODUCT_GUIDE}`;
@@ -3250,6 +3549,104 @@ var ActivityTracker = class {
3250
3549
  }
3251
3550
  };
3252
3551
 
3552
+ // src/core/adapter-primitives/primitives/send-queue.ts
3553
+ var SendQueue = class {
3554
+ constructor(config) {
3555
+ this.config = config;
3556
+ }
3557
+ items = [];
3558
+ processing = false;
3559
+ lastExec = 0;
3560
+ lastCategoryExec = /* @__PURE__ */ new Map();
3561
+ get pending() {
3562
+ return this.items.length;
3563
+ }
3564
+ enqueue(fn, opts) {
3565
+ const type = opts?.type ?? "other";
3566
+ const key = opts?.key;
3567
+ const category = opts?.category;
3568
+ let resolve;
3569
+ let reject;
3570
+ const promise = new Promise((res, rej) => {
3571
+ resolve = res;
3572
+ reject = rej;
3573
+ });
3574
+ promise.catch(() => {
3575
+ });
3576
+ if (type === "text" && key) {
3577
+ const idx = this.items.findIndex(
3578
+ (item) => item.type === "text" && item.key === key
3579
+ );
3580
+ if (idx !== -1) {
3581
+ this.items[idx].resolve(void 0);
3582
+ this.items[idx] = { fn, type, key, category, resolve, reject, promise };
3583
+ this.scheduleProcess();
3584
+ return promise;
3585
+ }
3586
+ }
3587
+ this.items.push({ fn, type, key, category, resolve, reject, promise });
3588
+ this.scheduleProcess();
3589
+ return promise;
3590
+ }
3591
+ onRateLimited() {
3592
+ this.config.onRateLimited?.();
3593
+ const remaining = [];
3594
+ for (const item of this.items) {
3595
+ if (item.type === "text") {
3596
+ item.resolve(void 0);
3597
+ } else {
3598
+ remaining.push(item);
3599
+ }
3600
+ }
3601
+ this.items = remaining;
3602
+ }
3603
+ clear() {
3604
+ for (const item of this.items) {
3605
+ item.resolve(void 0);
3606
+ }
3607
+ this.items = [];
3608
+ }
3609
+ scheduleProcess() {
3610
+ if (this.processing) return;
3611
+ if (this.items.length === 0) return;
3612
+ const item = this.items[0];
3613
+ const interval = this.getInterval(item.category);
3614
+ const lastExec = item.category ? this.lastCategoryExec.get(item.category) ?? 0 : this.lastExec;
3615
+ const elapsed = Date.now() - lastExec;
3616
+ const delay = Math.max(0, interval - elapsed);
3617
+ this.processing = true;
3618
+ setTimeout(() => void this.processNext(), delay);
3619
+ }
3620
+ getInterval(category) {
3621
+ if (category && this.config.categoryIntervals?.[category] != null) {
3622
+ return this.config.categoryIntervals[category];
3623
+ }
3624
+ return this.config.minInterval;
3625
+ }
3626
+ async processNext() {
3627
+ const item = this.items.shift();
3628
+ if (!item) {
3629
+ this.processing = false;
3630
+ return;
3631
+ }
3632
+ try {
3633
+ const result = await item.fn();
3634
+ item.resolve(result);
3635
+ } catch (err) {
3636
+ this.config.onError?.(err instanceof Error ? err : new Error(String(err)));
3637
+ item.reject(err);
3638
+ } finally {
3639
+ const now = Date.now();
3640
+ this.lastExec = now;
3641
+ if (item.category) {
3642
+ this.lastCategoryExec.set(item.category, now);
3643
+ }
3644
+ this.processing = false;
3645
+ this.scheduleProcess();
3646
+ }
3647
+ }
3648
+ };
3649
+
3253
3650
  // src/plugins/telegram/action-detect.ts
3254
3651
  import { nanoid as nanoid2 } from "nanoid";
3255
3652
  import { InlineKeyboard as InlineKeyboard11 } from "grammy";
@@ -3407,6 +3804,37 @@ function setupActionCallbacks(bot, core, chatId, getAssistantSessionId) {
3407
3804
  });
3408
3805
  }
3409
3806
 
3807
+ // src/core/adapter-primitives/primitives/tool-call-tracker.ts
3808
+ var ToolCallTracker = class {
3809
+ sessions = /* @__PURE__ */ new Map();
3810
+ track(sessionId, meta, messageId) {
3811
+ if (!this.sessions.has(sessionId)) {
3812
+ this.sessions.set(sessionId, /* @__PURE__ */ new Map());
3813
+ }
3814
+ this.sessions.get(sessionId).set(meta.id, { ...meta, messageId });
3815
+ }
3816
+ update(sessionId, toolId, status, patch) {
3817
+ const tool = this.sessions.get(sessionId)?.get(toolId);
3818
+ if (!tool) return null;
3819
+ tool.status = status;
3820
+ if (patch?.viewerLinks) tool.viewerLinks = patch.viewerLinks;
3821
+ if (patch?.viewerFilePath) tool.viewerFilePath = patch.viewerFilePath;
3822
+ if (patch?.name) tool.name = patch.name;
3823
+ if (patch?.kind) tool.kind = patch.kind;
3824
+ return tool;
3825
+ }
3826
+ getActive(sessionId) {
3827
+ const session = this.sessions.get(sessionId);
3828
+ return session ? [...session.values()] : [];
3829
+ }
3830
+ clear(sessionId) {
3831
+ this.sessions.delete(sessionId);
3832
+ }
3833
+ clearAll() {
3834
+ this.sessions.clear();
3835
+ }
3836
+ };
3837
+
3410
3838
  // src/plugins/telegram/tool-call-tracker.ts
3411
3839
  var log11 = createChildLogger({ module: "tool-call-tracker" });
3412
3840
  var TelegramToolCallTracker = class {
@@ -4077,7 +4505,12 @@ var TelegramAdapter = class extends MessagingAdapter {
4077
4505
  if (!text?.startsWith("/")) return next();
4078
4506
  const registry = this.core.lifecycleManager?.serviceRegistry?.get("command-registry");
4079
4507
  if (!registry) return next();
4080
- const commandName = text.split(" ")[0].slice(1).split("@")[0];
4508
+ const rawCommand = text.split(" ")[0].slice(1);
4509
+ const atIdx = rawCommand.indexOf("@");
4510
+ if (atIdx !== -1 && rawCommand.slice(atIdx + 1).toLowerCase() !== ctx.me.username.toLowerCase()) {
4511
+ return next();
4512
+ }
4513
+ const commandName = atIdx === -1 ? rawCommand : rawCommand.slice(0, atIdx);
4081
4514
  const def = registry.get(commandName);
4082
4515
  if (!def) return next();
4083
4516
  const chatId = ctx.chat.id;
@@ -4097,9 +4530,10 @@ var TelegramAdapter = class extends MessagingAdapter {
4097
4530
  }
4098
4531
  }
4099
4532
  });
4100
- if (response.type !== "silent") {
4101
- await this.renderCommandResponse(response, chatId, topicId);
4533
+ if (response.type === "silent") {
4534
+ return next();
4102
4535
  }
4536
+ await this.renderCommandResponse(response, chatId, topicId);
4103
4537
  } catch (err) {
4104
4538
  await ctx.reply(`\u26A0\uFE0F Command failed: ${String(err)}`);
4105
4539
  }
@@ -4803,22 +5237,11 @@ Task completed.
4803
5237
 
4804
5238
  <a href="${deepLink}">\u2192 Go to topic</a>`;
4805
5239
  }
4806
- const replyMarkup = notification.type === "completed" ? {
4807
- inline_keyboard: [
4808
- [
4809
- {
4810
- text: "\u{1F4CB} Summary",
4811
- callback_data: `sm:summary:${notification.sessionId}`
4812
- }
4813
- ]
4814
- ]
4815
- } : void 0;
4816
5240
  await this.sendQueue.enqueue(
4817
5241
  () => this.bot.api.sendMessage(this.telegramConfig.chatId, text, {
4818
5242
  message_thread_id: this.notificationTopicId,
4819
5243
  parse_mode: "HTML",
4820
- disable_notification: false,
4821
- reply_markup: replyMarkup
5244
+ disable_notification: false
4822
5245
  })
4823
5246
  );
4824
5247
  }
@@ -4955,6 +5378,9 @@ Task completed.
4955
5378
  };
4956
5379
 
4957
5380
  export {
5381
+ PRODUCT_GUIDE,
5382
+ SendQueue,
5383
+ ToolCallTracker,
4958
5384
  TelegramAdapter
4959
5385
  };
4960
- //# sourceMappingURL=chunk-RKB2ZK6S.js.map
5386
+ //# sourceMappingURL=chunk-LP45RCA4.js.map