@openacp/cli 2026.327.5 → 2026.328.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 (178) hide show
  1. package/README.md +13 -13
  2. package/dist/adapter-HGJENQCN.js +13 -0
  3. package/dist/agent-catalog-SZQQERV7.js +10 -0
  4. package/dist/{agent-dependencies-WS7Z2DFW.js → agent-dependencies-ED2ZTUHG.js} +1 -2
  5. package/dist/{agent-registry-5LZT7CUB.js → agent-registry-YOGP656W.js} +1 -2
  6. package/dist/agent-store-5UHZH2XI.js +8 -0
  7. package/dist/{api-client-AQPNKXI2.js → api-client-XTLRRFPX.js} +1 -2
  8. package/dist/api-server-DSUW637I.js +7 -0
  9. package/dist/api-server-WFB5K6FP.js +10 -0
  10. package/dist/{autostart-6JS565RY.js → autostart-CUPZMKKC.js} +3 -4
  11. package/dist/{chunk-WIIZNPCR.js → chunk-2KT6TROD.js} +12 -33
  12. package/dist/chunk-2KT6TROD.js.map +1 -0
  13. package/dist/{chunk-PPSMUECX.js → chunk-2R5XM3ES.js} +2 -2
  14. package/dist/{chunk-SNPYTMPR.js → chunk-3EWTPOF7.js} +2 -2
  15. package/dist/{chunk-YEULD3SG.js → chunk-3NAFXVQM.js} +7 -2
  16. package/dist/{chunk-YEULD3SG.js.map → chunk-3NAFXVQM.js.map} +1 -1
  17. package/dist/{chunk-QAQDGPB4.js → chunk-43JVXFYP.js} +3 -3
  18. package/dist/{chunk-KMMEFXIE.js → chunk-4B6PCWQP.js} +37 -9
  19. package/dist/chunk-4B6PCWQP.js.map +1 -0
  20. package/dist/{chunk-A6Y4GZM3.js → chunk-566W6INH.js} +2 -2
  21. package/dist/{chunk-ODUM3D6X.js → chunk-5HKQCYOI.js} +1 -39
  22. package/dist/chunk-5HKQCYOI.js.map +1 -0
  23. package/dist/{chunk-P2G275VD.js → chunk-5TCXYDLR.js} +3 -3
  24. package/dist/{chunk-XIBG7LSL.js → chunk-6VR4GWOO.js} +238 -108
  25. package/dist/chunk-6VR4GWOO.js.map +1 -0
  26. package/dist/{chunk-WXVT3AOY.js → chunk-7ZCQF6QM.js} +8 -3
  27. package/dist/chunk-7ZCQF6QM.js.map +1 -0
  28. package/dist/{chunk-S3ZGPPXY.js → chunk-E2SLHZAC.js} +8 -12
  29. package/dist/{chunk-S3ZGPPXY.js.map → chunk-E2SLHZAC.js.map} +1 -1
  30. package/dist/{chunk-RBYBSSGO.js → chunk-FCTC7KDT.js} +2 -2
  31. package/dist/{plugin-installer-QVJP6VKV.js → chunk-I53NEV3S.js} +6 -3
  32. package/dist/chunk-I53NEV3S.js.map +1 -0
  33. package/dist/{chunk-2YCW3QDV.js → chunk-IXMIC4GQ.js} +8 -7
  34. package/dist/chunk-IXMIC4GQ.js.map +1 -0
  35. package/dist/{chunk-BLQUXO7S.js → chunk-IZ5UEZF7.js} +27 -2
  36. package/dist/chunk-IZ5UEZF7.js.map +1 -0
  37. package/dist/{chunk-QVMEF6FB.js → chunk-JOMDPFQ2.js} +10 -24
  38. package/dist/chunk-JOMDPFQ2.js.map +1 -0
  39. package/dist/{chunk-4GMLGCF2.js → chunk-JUFN4XMB.js} +2 -2
  40. package/dist/{chunk-AD3X6DGK.js → chunk-NT6FYV27.js} +75 -13
  41. package/dist/chunk-NT6FYV27.js.map +1 -0
  42. package/dist/{chunk-HRKAXFWR.js → chunk-QBEQJFGL.js} +9 -9
  43. package/dist/{chunk-XMMAGAT4.js → chunk-R6KZYF7D.js} +8 -1
  44. package/dist/{chunk-XMMAGAT4.js.map → chunk-R6KZYF7D.js.map} +1 -1
  45. package/dist/{chunk-XWDW3XBE.js → chunk-RXMWJHWH.js} +687 -99
  46. package/dist/chunk-RXMWJHWH.js.map +1 -0
  47. package/dist/{chunk-SHTGQGAU.js → chunk-V2YZWYXT.js} +3 -3
  48. package/dist/{chunk-BQ6FR32N.js → chunk-VD3QSMVY.js} +2 -2
  49. package/dist/cli.js +103 -97
  50. package/dist/cli.js.map +1 -1
  51. package/dist/{config-I4FMCJGZ.js → config-UCAFCS5W.js} +3 -4
  52. package/dist/config-editor-OU6PUY66.js +10 -0
  53. package/dist/{config-registry-CUMNXFGK.js → config-registry-ZXAIJNYB.js} +2 -3
  54. package/dist/{context-XM6E22LM.js → context-7MPU7RL5.js} +1 -2
  55. package/dist/core-plugins-R2EVZAJV.js +22 -0
  56. package/dist/{daemon-PXO5QPCR.js → daemon-DTA6KYYY.js} +4 -5
  57. package/dist/{dev-loader-DRU3R7ZM.js → dev-loader-7P3HZCIA.js} +1 -3
  58. package/dist/{dev-loader-DRU3R7ZM.js.map → dev-loader-7P3HZCIA.js.map} +1 -1
  59. package/dist/doctor-D723IB2I.js +9 -0
  60. package/dist/file-service-HHB3JQIO.js +8 -0
  61. package/dist/index.d.ts +37 -145
  62. package/dist/index.js +32 -28
  63. package/dist/index.js.map +1 -1
  64. package/dist/{install-cloudflared-AN24L4DP.js → install-cloudflared-JRJ4BSOM.js} +3 -4
  65. package/dist/{install-cloudflared-AN24L4DP.js.map → install-cloudflared-JRJ4BSOM.js.map} +1 -1
  66. package/dist/{install-context-XPWTFT3J.js → install-context-EHYV5WRY.js} +2 -3
  67. package/dist/{install-context-XPWTFT3J.js.map → install-context-EHYV5WRY.js.map} +1 -1
  68. package/dist/{install-jq-CRVDJGF3.js → install-jq-ISTGT263.js} +3 -4
  69. package/dist/{install-jq-CRVDJGF3.js.map → install-jq-ISTGT263.js.map} +1 -1
  70. package/dist/{integrate-G6CVXTGT.js → integrate-JIEZYDOR.js} +1 -2
  71. package/dist/{integrate-G6CVXTGT.js.map → integrate-JIEZYDOR.js.map} +1 -1
  72. package/dist/{log-LZ7FTRKG.js → log-YZ243M5G.js} +4 -3
  73. package/dist/{main-3GF3EQTE.js → main-RRSX5SRL.js} +117 -40
  74. package/dist/main-RRSX5SRL.js.map +1 -0
  75. package/dist/{menu-YDQ2LWAR.js → menu-ALFN37IR.js} +1 -2
  76. package/dist/notifications-MO23S7S3.js +8 -0
  77. package/dist/{plugin-create-5HQRF2ID.js → plugin-create-EHL76ZZG.js} +1 -2
  78. package/dist/{plugin-create-5HQRF2ID.js.map → plugin-create-EHL76ZZG.js.map} +1 -1
  79. package/dist/plugin-installer-5XHORMLS.js +9 -0
  80. package/dist/{plugin-registry-WB3DR67H.js → plugin-registry-6J3YSFHF.js} +1 -2
  81. package/dist/{plugin-search-HQ4WQKOF.js → plugin-search-MGKAL5JM.js} +1 -2
  82. package/dist/{plugin-search-HQ4WQKOF.js.map → plugin-search-MGKAL5JM.js.map} +1 -1
  83. package/dist/{post-upgrade-3ADZRMYJ.js → post-upgrade-Y26S2ZQ7.js} +6 -7
  84. package/dist/{post-upgrade-3ADZRMYJ.js.map → post-upgrade-Y26S2ZQ7.js.map} +1 -1
  85. package/dist/{read-text-file-IRZM3QLM.js → read-text-file-DJBTITIB.js} +1 -2
  86. package/dist/{registry-client-AVGRE4CF.js → registry-client-GTBWLXYU.js} +1 -2
  87. package/dist/{security-YNRBW6S7.js → security-2BA265LN.js} +1 -2
  88. package/dist/{settings-manager-MD2U4ZV2.js → settings-manager-B4UN2LAC.js} +1 -2
  89. package/dist/{setup-A7VPW46C.js → setup-OI6A3OXW.js} +109 -82
  90. package/dist/setup-OI6A3OXW.js.map +1 -0
  91. package/dist/speech-GB7PHVQZ.js +9 -0
  92. package/dist/{suggest-7D6B542M.js → suggest-RST5VOHB.js} +1 -3
  93. package/dist/{suggest-7D6B542M.js.map → suggest-RST5VOHB.js.map} +1 -1
  94. package/dist/telegram-UVIAXADE.js +7 -0
  95. package/dist/tunnel-4WNFC7GO.js +7 -0
  96. package/dist/{tunnel-service-QJPUYEKU.js → tunnel-service-I2NFUX3V.js} +3 -4
  97. package/dist/{tunnel-service-QJPUYEKU.js.map → tunnel-service-I2NFUX3V.js.map} +1 -1
  98. package/dist/{validators-WSTBNKRW.js → validators-GITLOFXC.js} +1 -2
  99. package/dist/{version-NQZBM5M7.js → version-AXXV6IV2.js} +1 -2
  100. package/package.json +1 -3
  101. package/dist/adapter-JQFQ3JAO.js +0 -15
  102. package/dist/adapter-UORRGHNH.js +0 -1030
  103. package/dist/adapter-UORRGHNH.js.map +0 -1
  104. package/dist/agent-catalog-YHBFERYO.js +0 -11
  105. package/dist/agent-store-VSHNY5GT.js +0 -9
  106. package/dist/api-server-7G3ZUZRM.js +0 -8
  107. package/dist/api-server-CAYNPUF2.js +0 -11
  108. package/dist/chunk-2YCW3QDV.js.map +0 -1
  109. package/dist/chunk-32LVIEPW.js +0 -477
  110. package/dist/chunk-32LVIEPW.js.map +0 -1
  111. package/dist/chunk-AD3X6DGK.js.map +0 -1
  112. package/dist/chunk-BLQUXO7S.js.map +0 -1
  113. package/dist/chunk-KMMEFXIE.js.map +0 -1
  114. package/dist/chunk-ODUM3D6X.js.map +0 -1
  115. package/dist/chunk-QVMEF6FB.js.map +0 -1
  116. package/dist/chunk-VUNV25KB.js +0 -16
  117. package/dist/chunk-WIIZNPCR.js.map +0 -1
  118. package/dist/chunk-WXVT3AOY.js.map +0 -1
  119. package/dist/chunk-XIBG7LSL.js.map +0 -1
  120. package/dist/chunk-XWDW3XBE.js.map +0 -1
  121. package/dist/chunk-ZNSO2QVC.js +0 -124
  122. package/dist/chunk-ZNSO2QVC.js.map +0 -1
  123. package/dist/config-editor-7PKW42GZ.js +0 -11
  124. package/dist/core-plugins-Y5US6RED.js +0 -23
  125. package/dist/dist-UHQK5CXN.js +0 -21151
  126. package/dist/dist-UHQK5CXN.js.map +0 -1
  127. package/dist/doctor-QZQAP46W.js +0 -10
  128. package/dist/file-service-EUODJAIT.js +0 -9
  129. package/dist/main-3GF3EQTE.js.map +0 -1
  130. package/dist/notifications-D5BRDNSU.js +0 -9
  131. package/dist/plugin-installer-QVJP6VKV.js.map +0 -1
  132. package/dist/setup-A7VPW46C.js.map +0 -1
  133. package/dist/slack-2XNWBOWH.js +0 -8
  134. package/dist/speech-2GHQNRIO.js +0 -9
  135. package/dist/telegram-E65IWFBW.js +0 -8
  136. package/dist/tunnel-45HA72MB.js +0 -8
  137. package/dist/version-NQZBM5M7.js.map +0 -1
  138. /package/dist/{adapter-JQFQ3JAO.js.map → adapter-HGJENQCN.js.map} +0 -0
  139. /package/dist/{agent-catalog-YHBFERYO.js.map → agent-catalog-SZQQERV7.js.map} +0 -0
  140. /package/dist/{agent-dependencies-WS7Z2DFW.js.map → agent-dependencies-ED2ZTUHG.js.map} +0 -0
  141. /package/dist/{agent-registry-5LZT7CUB.js.map → agent-registry-YOGP656W.js.map} +0 -0
  142. /package/dist/{agent-store-VSHNY5GT.js.map → agent-store-5UHZH2XI.js.map} +0 -0
  143. /package/dist/{api-client-AQPNKXI2.js.map → api-client-XTLRRFPX.js.map} +0 -0
  144. /package/dist/{api-server-7G3ZUZRM.js.map → api-server-DSUW637I.js.map} +0 -0
  145. /package/dist/{api-server-CAYNPUF2.js.map → api-server-WFB5K6FP.js.map} +0 -0
  146. /package/dist/{autostart-6JS565RY.js.map → autostart-CUPZMKKC.js.map} +0 -0
  147. /package/dist/{chunk-PPSMUECX.js.map → chunk-2R5XM3ES.js.map} +0 -0
  148. /package/dist/{chunk-SNPYTMPR.js.map → chunk-3EWTPOF7.js.map} +0 -0
  149. /package/dist/{chunk-QAQDGPB4.js.map → chunk-43JVXFYP.js.map} +0 -0
  150. /package/dist/{chunk-A6Y4GZM3.js.map → chunk-566W6INH.js.map} +0 -0
  151. /package/dist/{chunk-P2G275VD.js.map → chunk-5TCXYDLR.js.map} +0 -0
  152. /package/dist/{chunk-RBYBSSGO.js.map → chunk-FCTC7KDT.js.map} +0 -0
  153. /package/dist/{chunk-4GMLGCF2.js.map → chunk-JUFN4XMB.js.map} +0 -0
  154. /package/dist/{chunk-HRKAXFWR.js.map → chunk-QBEQJFGL.js.map} +0 -0
  155. /package/dist/{chunk-SHTGQGAU.js.map → chunk-V2YZWYXT.js.map} +0 -0
  156. /package/dist/{chunk-BQ6FR32N.js.map → chunk-VD3QSMVY.js.map} +0 -0
  157. /package/dist/{chunk-VUNV25KB.js.map → config-UCAFCS5W.js.map} +0 -0
  158. /package/dist/{config-I4FMCJGZ.js.map → config-editor-OU6PUY66.js.map} +0 -0
  159. /package/dist/{config-editor-7PKW42GZ.js.map → config-registry-ZXAIJNYB.js.map} +0 -0
  160. /package/dist/{config-registry-CUMNXFGK.js.map → context-7MPU7RL5.js.map} +0 -0
  161. /package/dist/{context-XM6E22LM.js.map → core-plugins-R2EVZAJV.js.map} +0 -0
  162. /package/dist/{core-plugins-Y5US6RED.js.map → daemon-DTA6KYYY.js.map} +0 -0
  163. /package/dist/{daemon-PXO5QPCR.js.map → doctor-D723IB2I.js.map} +0 -0
  164. /package/dist/{doctor-QZQAP46W.js.map → file-service-HHB3JQIO.js.map} +0 -0
  165. /package/dist/{file-service-EUODJAIT.js.map → log-YZ243M5G.js.map} +0 -0
  166. /package/dist/{log-LZ7FTRKG.js.map → menu-ALFN37IR.js.map} +0 -0
  167. /package/dist/{menu-YDQ2LWAR.js.map → notifications-MO23S7S3.js.map} +0 -0
  168. /package/dist/{notifications-D5BRDNSU.js.map → plugin-installer-5XHORMLS.js.map} +0 -0
  169. /package/dist/{plugin-registry-WB3DR67H.js.map → plugin-registry-6J3YSFHF.js.map} +0 -0
  170. /package/dist/{read-text-file-IRZM3QLM.js.map → read-text-file-DJBTITIB.js.map} +0 -0
  171. /package/dist/{registry-client-AVGRE4CF.js.map → registry-client-GTBWLXYU.js.map} +0 -0
  172. /package/dist/{security-YNRBW6S7.js.map → security-2BA265LN.js.map} +0 -0
  173. /package/dist/{settings-manager-MD2U4ZV2.js.map → settings-manager-B4UN2LAC.js.map} +0 -0
  174. /package/dist/{slack-2XNWBOWH.js.map → speech-GB7PHVQZ.js.map} +0 -0
  175. /package/dist/{speech-2GHQNRIO.js.map → telegram-UVIAXADE.js.map} +0 -0
  176. /package/dist/{telegram-E65IWFBW.js.map → tunnel-4WNFC7GO.js.map} +0 -0
  177. /package/dist/{tunnel-45HA72MB.js.map → validators-GITLOFXC.js.map} +0 -0
  178. /package/dist/{validators-WSTBNKRW.js.map → version-AXXV6IV2.js.map} +0 -0
@@ -7,21 +7,7 @@ import {
7
7
  } from "./chunk-AFKX424Q.js";
8
8
  import {
9
9
  DoctorEngine
10
- } from "./chunk-QAQDGPB4.js";
11
- import {
12
- BaseRenderer,
13
- MessagingAdapter,
14
- evaluateNoise,
15
- extractContentText,
16
- formatTokens,
17
- formatToolSummary,
18
- formatToolTitle,
19
- progressBar,
20
- resolveToolIcon,
21
- splitMessage,
22
- stripCodeFences,
23
- truncateContent
24
- } from "./chunk-32LVIEPW.js";
10
+ } from "./chunk-43JVXFYP.js";
25
11
  import {
26
12
  CheckpointReader,
27
13
  DEFAULT_MAX_TOKENS
@@ -31,10 +17,10 @@ import {
31
17
  getSafeFields,
32
18
  isHotReloadable,
33
19
  resolveOptions
34
- } from "./chunk-ODUM3D6X.js";
20
+ } from "./chunk-5HKQCYOI.js";
35
21
  import {
36
22
  createChildLogger
37
- } from "./chunk-XMMAGAT4.js";
23
+ } from "./chunk-R6KZYF7D.js";
38
24
 
39
25
  // src/plugins/telegram/adapter.ts
40
26
  import { Bot, InputFile } from "grammy";
@@ -79,6 +65,249 @@ function buildDeepLink(chatId, threadId, messageId) {
79
65
  // src/plugins/telegram/commands/new-session.ts
80
66
  import { InlineKeyboard as InlineKeyboard2 } from "grammy";
81
67
 
68
+ // src/core/adapter-primitives/format-utils.ts
69
+ function progressBar(ratio, length = 10) {
70
+ const filled = Math.round(Math.min(ratio, 1) * length);
71
+ return "\u2593".repeat(filled) + "\u2591".repeat(length - filled);
72
+ }
73
+ function formatTokens(n) {
74
+ if (n >= 1e6) {
75
+ const m = n / 1e6;
76
+ return m % 1 === 0 ? `${m}M` : `${parseFloat(m.toFixed(1))}M`;
77
+ }
78
+ if (n >= 1e3) {
79
+ const k = n / 1e3;
80
+ return k % 1 === 0 ? `${k}k` : `${parseFloat(k.toFixed(1))}k`;
81
+ }
82
+ return String(n);
83
+ }
84
+ function stripCodeFences(text) {
85
+ return text.replace(/```\w*\n?/g, "").replace(/```$/gm, "").trim();
86
+ }
87
+ function truncateContent(text, maxLen) {
88
+ if (text.length <= maxLen) return text;
89
+ return text.slice(0, maxLen) + "\n\u2026 (truncated)";
90
+ }
91
+ function splitMessage(text, maxLength) {
92
+ if (text.length <= maxLength) return [text];
93
+ const chunks = [];
94
+ let remaining = text;
95
+ while (remaining.length > 0) {
96
+ if (remaining.length <= maxLength) {
97
+ chunks.push(remaining);
98
+ break;
99
+ }
100
+ const wouldLeaveSmall = remaining.length < maxLength * 1.3;
101
+ const searchLimit = wouldLeaveSmall ? Math.floor(remaining.length / 2) + 300 : maxLength;
102
+ const threshold = maxLength * 0.2;
103
+ let splitAt = remaining.lastIndexOf("\n\n", searchLimit);
104
+ if (splitAt === -1 || splitAt < threshold) {
105
+ splitAt = remaining.lastIndexOf("\n", searchLimit);
106
+ }
107
+ if (splitAt === -1 || splitAt < threshold) {
108
+ splitAt = searchLimit;
109
+ }
110
+ const candidate = remaining.slice(0, splitAt);
111
+ const fences = candidate.match(/```/g);
112
+ if (fences && fences.length % 2 !== 0) {
113
+ const closingFence = remaining.indexOf("```", splitAt);
114
+ if (closingFence !== -1) {
115
+ const afterFence = remaining.indexOf("\n", closingFence + 3);
116
+ const fenceSplit = afterFence !== -1 ? afterFence + 1 : closingFence + 3;
117
+ if (fenceSplit <= maxLength * 2) {
118
+ splitAt = fenceSplit;
119
+ }
120
+ }
121
+ }
122
+ chunks.push(remaining.slice(0, splitAt));
123
+ remaining = remaining.slice(splitAt).replace(/^\n+/, "");
124
+ }
125
+ return chunks;
126
+ }
127
+
128
+ // src/core/adapter-primitives/format-types.ts
129
+ var STATUS_ICONS = {
130
+ pending: "\u23F3",
131
+ in_progress: "\u{1F504}",
132
+ completed: "\u2705",
133
+ failed: "\u274C",
134
+ cancelled: "\u{1F6AB}",
135
+ running: "\u{1F504}",
136
+ done: "\u2705",
137
+ error: "\u274C"
138
+ };
139
+ var KIND_ICONS = {
140
+ read: "\u{1F4D6}",
141
+ edit: "\u270F\uFE0F",
142
+ write: "\u270F\uFE0F",
143
+ delete: "\u{1F5D1}\uFE0F",
144
+ execute: "\u25B6\uFE0F",
145
+ command: "\u25B6\uFE0F",
146
+ bash: "\u25B6\uFE0F",
147
+ terminal: "\u25B6\uFE0F",
148
+ search: "\u{1F50D}",
149
+ web: "\u{1F310}",
150
+ fetch: "\u{1F310}",
151
+ agent: "\u{1F9E0}",
152
+ think: "\u{1F9E0}",
153
+ install: "\u{1F4E6}",
154
+ move: "\u{1F4E6}",
155
+ other: "\u{1F6E0}\uFE0F"
156
+ };
157
+
158
+ // src/core/adapter-primitives/message-formatter.ts
159
+ function extractContentText(content, depth = 0) {
160
+ if (!content || depth > 5) return "";
161
+ if (typeof content === "string") return content;
162
+ if (Array.isArray(content)) {
163
+ return content.map((c) => extractContentText(c, depth + 1)).filter(Boolean).join("\n");
164
+ }
165
+ if (typeof content !== "object") return String(content);
166
+ const obj = content;
167
+ if (obj.text && typeof obj.text === "string") return obj.text;
168
+ if (obj.content) {
169
+ if (typeof obj.content === "string") return obj.content;
170
+ if (Array.isArray(obj.content)) {
171
+ return obj.content.map((c) => extractContentText(c, depth + 1)).filter(Boolean).join("\n");
172
+ }
173
+ return extractContentText(obj.content, depth + 1);
174
+ }
175
+ if (obj.input) return extractContentText(obj.input, depth + 1);
176
+ if (obj.output) return extractContentText(obj.output, depth + 1);
177
+ const keys = Object.keys(obj).filter((k) => k !== "type");
178
+ if (keys.length === 0) return "";
179
+ try {
180
+ return JSON.stringify(obj, null, 2);
181
+ } catch {
182
+ return "";
183
+ }
184
+ }
185
+ function parseRawInput(rawInput) {
186
+ try {
187
+ if (typeof rawInput === "string") {
188
+ return JSON.parse(rawInput);
189
+ }
190
+ if (typeof rawInput === "object" && rawInput !== null) {
191
+ return rawInput;
192
+ }
193
+ } catch {
194
+ }
195
+ return {};
196
+ }
197
+ function formatToolSummary(name, rawInput, displaySummary) {
198
+ if (displaySummary && typeof displaySummary === "string") {
199
+ return displaySummary;
200
+ }
201
+ const args = parseRawInput(rawInput);
202
+ const lowerName = name.toLowerCase();
203
+ if (lowerName === "read") {
204
+ const fp = args.file_path ?? args.filePath ?? "";
205
+ const limit = args.limit ? ` (${args.limit} lines)` : "";
206
+ return fp ? `\u{1F4D6} Read ${fp}${limit}` : `\u{1F527} ${name}`;
207
+ }
208
+ if (lowerName === "edit") {
209
+ const fp = args.file_path ?? args.filePath ?? "";
210
+ return fp ? `\u270F\uFE0F Edit ${fp}` : `\u{1F527} ${name}`;
211
+ }
212
+ if (lowerName === "write") {
213
+ const fp = args.file_path ?? args.filePath ?? "";
214
+ return fp ? `\u{1F4DD} Write ${fp}` : `\u{1F527} ${name}`;
215
+ }
216
+ if (lowerName === "bash" || lowerName === "terminal") {
217
+ const cmd = String(args.command ?? args.cmd ?? "").slice(0, 60);
218
+ return cmd ? `\u25B6\uFE0F Run: ${cmd}` : `\u25B6\uFE0F Terminal`;
219
+ }
220
+ if (lowerName === "grep") {
221
+ const pattern = args.pattern ?? "";
222
+ const path2 = args.path ?? "";
223
+ return pattern ? `\u{1F50D} Grep "${pattern}"${path2 ? ` in ${path2}` : ""}` : `\u{1F527} ${name}`;
224
+ }
225
+ if (lowerName === "glob") {
226
+ const pattern = args.pattern ?? "";
227
+ return pattern ? `\u{1F50D} Glob ${pattern}` : `\u{1F527} ${name}`;
228
+ }
229
+ if (lowerName === "agent") {
230
+ const desc = String(args.description ?? "").slice(0, 60);
231
+ return desc ? `\u{1F9E0} Agent: ${desc}` : `\u{1F527} ${name}`;
232
+ }
233
+ if (lowerName === "webfetch" || lowerName === "web_fetch") {
234
+ const url = String(args.url ?? "").slice(0, 60);
235
+ return url ? `\u{1F310} Fetch ${url}` : `\u{1F527} ${name}`;
236
+ }
237
+ if (lowerName === "websearch" || lowerName === "web_search") {
238
+ const query = String(args.query ?? "").slice(0, 60);
239
+ return query ? `\u{1F310} Search "${query}"` : `\u{1F527} ${name}`;
240
+ }
241
+ return `\u{1F527} ${name}`;
242
+ }
243
+ function formatToolTitle(name, rawInput, displayTitle) {
244
+ if (displayTitle && typeof displayTitle === "string") {
245
+ return displayTitle;
246
+ }
247
+ const args = parseRawInput(rawInput);
248
+ const lowerName = name.toLowerCase();
249
+ if (["read", "edit", "write"].includes(lowerName)) {
250
+ return String(args.file_path ?? args.filePath ?? name);
251
+ }
252
+ if (lowerName === "bash" || lowerName === "terminal") {
253
+ return String(args.command ?? args.cmd ?? name).slice(0, 60);
254
+ }
255
+ if (lowerName === "grep") {
256
+ const pattern = args.pattern ?? "";
257
+ const path2 = args.path ?? "";
258
+ return pattern ? `"${pattern}"${path2 ? ` in ${path2}` : ""}` : name;
259
+ }
260
+ if (lowerName === "glob") {
261
+ return String(args.pattern ?? name);
262
+ }
263
+ if (lowerName === "agent") {
264
+ return String(args.description ?? name).slice(0, 60);
265
+ }
266
+ if (["webfetch", "web_fetch"].includes(lowerName)) {
267
+ return String(args.url ?? name).slice(0, 60);
268
+ }
269
+ if (["websearch", "web_search"].includes(lowerName)) {
270
+ return String(args.query ?? name).slice(0, 60);
271
+ }
272
+ return name;
273
+ }
274
+ function resolveToolIcon(tool) {
275
+ const statusIcon = STATUS_ICONS[tool.status || ""];
276
+ if (statusIcon) return statusIcon;
277
+ const kind = tool.displayKind ?? tool.kind;
278
+ if (kind && KIND_ICONS[kind]) return KIND_ICONS[kind];
279
+ return "\u{1F527}";
280
+ }
281
+ var NOISE_RULES = [
282
+ {
283
+ match: (name) => name.toLowerCase() === "ls",
284
+ action: "hide"
285
+ },
286
+ {
287
+ match: (_name, kind, rawInput) => {
288
+ if (kind !== "read") return false;
289
+ const args = parseRawInput(rawInput);
290
+ const p = String(args.file_path ?? args.filePath ?? args.path ?? "");
291
+ return p.endsWith("/");
292
+ },
293
+ action: "hide"
294
+ },
295
+ {
296
+ match: (name) => name.toLowerCase() === "glob",
297
+ action: "hide"
298
+ },
299
+ {
300
+ match: (name) => name.toLowerCase() === "grep",
301
+ action: "hide"
302
+ }
303
+ ];
304
+ function evaluateNoise(name, kind, rawInput) {
305
+ for (const rule of NOISE_RULES) {
306
+ if (rule.match(name, kind, rawInput)) return rule.action;
307
+ }
308
+ return null;
309
+ }
310
+
82
311
  // src/plugins/telegram/formatting.ts
83
312
  function escapeHtml(text) {
84
313
  if (!text) return "";
@@ -171,23 +400,16 @@ function formatPlan(plan) {
171
400
  return `<b>Plan:</b>
172
401
  ${lines.join("\n")}`;
173
402
  }
174
- function formatUsage(usage, verbosity = "medium") {
175
- const { tokensUsed, contextSize, cost } = usage;
403
+ function formatUsage(usage, _verbosity = "medium") {
404
+ const { tokensUsed, contextSize } = usage;
176
405
  if (tokensUsed == null) return "\u{1F4CA} Usage data unavailable";
177
- if (verbosity === "medium") {
178
- const costStr = cost != null ? ` \xB7 $${cost.toFixed(2)}` : "";
179
- return `\u{1F4CA} ${formatTokens(tokensUsed)} tokens${costStr}`;
180
- }
181
406
  if (contextSize == null) return `\u{1F4CA} ${formatTokens(tokensUsed)} tokens`;
182
407
  const ratio = tokensUsed / contextSize;
183
408
  const pct = Math.round(ratio * 100);
184
409
  const bar = progressBar(ratio);
185
410
  const emoji = pct >= 85 ? "\u26A0\uFE0F" : "\u{1F4CA}";
186
- let text = `${emoji} ${formatTokens(tokensUsed)} / ${formatTokens(contextSize)} tokens
411
+ return `${emoji} ${formatTokens(tokensUsed)} / ${formatTokens(contextSize)} tokens
187
412
  ${bar} ${pct}%`;
188
- if (cost != null) text += `
189
- \u{1F4B0} $${cost.toFixed(2)}`;
190
- return text;
191
413
  }
192
414
  function splitMessage2(text, maxLength = 3800) {
193
415
  return splitMessage(text, maxLength);
@@ -215,14 +437,14 @@ function renderToolCard(snap) {
215
437
  const fileName = entry.viewerFilePath?.split("/").pop() ?? "";
216
438
  if (entry.viewerLinks.file)
217
439
  links.push(
218
- `\u{1F4C4} <a href="${escapeHtml(entry.viewerLinks.file)}">View ${escapeHtml(fileName || "file")}</a>`
440
+ `<a href="${escapeHtml(entry.viewerLinks.file)}">View ${escapeHtml(fileName || "file")}</a>`
219
441
  );
220
442
  if (entry.viewerLinks.diff)
221
443
  links.push(
222
- `\u{1F4DD} <a href="${escapeHtml(entry.viewerLinks.diff)}">View diff</a>`
444
+ `<a href="${escapeHtml(entry.viewerLinks.diff)}">View diff</a>`
223
445
  );
224
446
  if (links.length > 0) line += `
225
- ${links.join(" \xB7 ")}`;
447
+ ${links.join(" \xB7 ")}`;
226
448
  }
227
449
  sections.push(line);
228
450
  }
@@ -247,11 +469,27 @@ function renderToolCard(snap) {
247
469
  for (const entry of running) {
248
470
  sections.push(`${entry.icon} ${escapeHtml(entry.label)}`);
249
471
  }
250
- if (snap.usage?.tokensUsed != null) {
251
- if (sections.length > 0) sections.push("\u2500\u2500\u2500");
252
- sections.push(formatUsage(snap.usage, snap.verbosity));
472
+ return sections.join("\n\n");
473
+ }
474
+ var TELEGRAM_MAX_LENGTH = 4096;
475
+ function splitToolCardText(text) {
476
+ if (text.length <= TELEGRAM_MAX_LENGTH) return [text];
477
+ const sections = text.split("\n\n");
478
+ const chunks = [];
479
+ let current = "";
480
+ for (const section of sections) {
481
+ const candidate = current ? `${current}
482
+
483
+ ${section}` : section;
484
+ if (candidate.length > TELEGRAM_MAX_LENGTH && current) {
485
+ chunks.push(current);
486
+ current = section;
487
+ } else {
488
+ current = candidate;
489
+ }
253
490
  }
254
- return sections.join("\n");
491
+ if (current) chunks.push(current);
492
+ return chunks;
255
493
  }
256
494
 
257
495
  // src/plugins/telegram/commands/admin.ts
@@ -440,6 +678,15 @@ function setupTTSCallbacks(bot, core) {
440
678
  }
441
679
  return;
442
680
  }
681
+ if (session.voiceMode !== "on" && !core.speechService?.isTTSAvailable()) {
682
+ try {
683
+ await ctx.answerCallbackQuery({
684
+ text: "\u26A0\uFE0F TTS provider not installed. Use /tts install to set up."
685
+ });
686
+ } catch {
687
+ }
688
+ return;
689
+ }
443
690
  const newMode = session.voiceMode === "on" ? "off" : "on";
444
691
  session.setVoiceMode(newMode);
445
692
  const toastText = newMode === "on" ? "\u{1F50A} Text to Speech enabled" : "\u{1F507} Text to Speech disabled";
@@ -476,6 +723,15 @@ async function handleTTS(ctx, core) {
476
723
  }
477
724
  const args = ctx.message?.text?.split(/\s+/).slice(1) ?? [];
478
725
  const arg = args[0]?.toLowerCase();
726
+ if (arg === "on" || !arg) {
727
+ if (!core.speechService?.isTTSAvailable()) {
728
+ await ctx.reply(
729
+ "\u26A0\uFE0F TTS provider not installed.\n\nUse <code>/tts install</code> to install Edge TTS plugin.",
730
+ { parse_mode: "HTML" }
731
+ );
732
+ return;
733
+ }
734
+ }
479
735
  if (arg === "on") {
480
736
  session.setVoiceMode("on");
481
737
  await ctx.reply("\u{1F50A} Text to Speech enabled for this session.", {
@@ -546,7 +802,7 @@ async function handleUpdate(ctx, core) {
546
802
  );
547
803
  return;
548
804
  }
549
- const { getCurrentVersion, getLatestVersion, compareVersions, runUpdate } = await import("./version-NQZBM5M7.js");
805
+ const { getCurrentVersion, getLatestVersion, compareVersions, runUpdate } = await import("./version-AXXV6IV2.js");
550
806
  const current = getCurrentVersion();
551
807
  const statusMsg = await ctx.reply(
552
808
  `\u{1F50D} Checking for updates... (current: v${escapeHtml(current)})`,
@@ -1290,9 +1546,22 @@ async function handleArchive(ctx, core) {
1290
1546
  if (!threadId) return;
1291
1547
  const session = core.sessionManager.getSessionByThread("telegram", String(threadId));
1292
1548
  const record = !session ? core.sessionManager.getRecordByThread("telegram", String(threadId)) : void 0;
1293
- const identifier = session?.id ?? record?.sessionId ?? `topic:${threadId}`;
1549
+ if (!session && !record) {
1550
+ await ctx.reply("This topic is not linked to a session.", { parse_mode: "HTML" });
1551
+ return;
1552
+ }
1553
+ const identifier = session?.id ?? record?.sessionId;
1554
+ if (!identifier) {
1555
+ await ctx.reply("Could not determine session for this topic.", { parse_mode: "HTML" });
1556
+ return;
1557
+ }
1558
+ const status = session?.status ?? record?.status;
1559
+ if (status === "initializing") {
1560
+ await ctx.reply("Cannot archive a session that is still initializing. Wait for it to become active.", { parse_mode: "HTML" });
1561
+ return;
1562
+ }
1294
1563
  await ctx.reply(
1295
- "\u26A0\uFE0F <b>Archive this session?</b>\n\nThis will:\n\u2022 Delete this topic and all messages\n\u2022 Stop the agent session (if running)\n\u2022 Remove the session record\n\n<i>This action cannot be undone.</i>",
1564
+ "\u26A0\uFE0F <b>Archive this session?</b>\n\nThis will:\n\u2022 Delete this topic and recreate it (clearing chat history)\n\u2022 The agent session will keep running\n\n<i>Chat history cannot be recovered.</i>",
1296
1565
  {
1297
1566
  parse_mode: "HTML",
1298
1567
  reply_markup: new InlineKeyboard3().text("\u{1F5D1} Yes, archive", `ar:yes:${identifier}`).text("\u274C Cancel", `ar:no:${identifier}`)
@@ -1312,37 +1581,21 @@ async function handleArchiveConfirm(ctx, core, chatId) {
1312
1581
  await ctx.editMessageText("Archive cancelled.", { parse_mode: "HTML" });
1313
1582
  return;
1314
1583
  }
1315
- await ctx.editMessageText("\u{1F504} Archiving...", { parse_mode: "HTML" });
1316
- if (identifier.startsWith("topic:")) {
1317
- const topicId = Number(identifier.slice("topic:".length));
1318
- try {
1319
- await ctx.api.deleteForumTopic(chatId, topicId);
1320
- core.notificationManager.notifyAll({
1321
- sessionId: "system",
1322
- sessionName: `Orphan topic #${topicId}`,
1323
- type: "completed",
1324
- summary: `Orphan topic #${topicId} archived and deleted.`
1325
- });
1326
- } catch (err) {
1327
- core.notificationManager.notifyAll({
1328
- sessionId: "system",
1329
- sessionName: `Orphan topic #${topicId}`,
1330
- type: "error",
1331
- summary: `Failed to delete orphan topic #${topicId}: ${err.message}`
1332
- });
1333
- }
1334
- return;
1335
- }
1336
1584
  const result = await core.archiveSession(identifier);
1337
1585
  if (result.ok) {
1338
- core.notificationManager.notifyAll({
1339
- sessionId: identifier,
1340
- type: "completed",
1341
- summary: `Session archived and deleted.`
1342
- });
1586
+ const adapter = core.adapters.get("telegram");
1587
+ if (adapter) {
1588
+ try {
1589
+ await adapter.sendMessage(identifier, {
1590
+ type: "text",
1591
+ text: "Chat history cleared. Session is still active \u2014 send a message to continue."
1592
+ });
1593
+ } catch {
1594
+ }
1595
+ }
1343
1596
  } else {
1344
1597
  try {
1345
- await ctx.editMessageText(`\u274C Failed to archive: <code>${escapeHtml(result.error)}</code>`, { parse_mode: "HTML" });
1598
+ await ctx.editMessageText(`Failed to archive: <code>${escapeHtml(result.error)}</code>`, { parse_mode: "HTML" });
1346
1599
  } catch {
1347
1600
  core.notificationManager.notifyAll({
1348
1601
  sessionId: identifier,
@@ -1552,10 +1805,10 @@ Downloading... ${bar} ${percent}%`, { parse_mode: "HTML" });
1552
1805
  };
1553
1806
  const result = await catalog.install(nameOrId, progress);
1554
1807
  if (result.ok) {
1555
- const { getAgentCapabilities } = await import("./agent-dependencies-WS7Z2DFW.js");
1808
+ const { getAgentCapabilities } = await import("./agent-dependencies-ED2ZTUHG.js");
1556
1809
  const caps = getAgentCapabilities(result.agentKey);
1557
1810
  if (caps.integration) {
1558
- const { installIntegration } = await import("./integrate-G6CVXTGT.js");
1811
+ const { installIntegration } = await import("./integrate-JIEZYDOR.js");
1559
1812
  const intResult = await installIntegration(result.agentKey, caps.integration);
1560
1813
  if (intResult.success) {
1561
1814
  try {
@@ -1625,7 +1878,7 @@ function buildProgressBar(percent) {
1625
1878
  // src/plugins/telegram/commands/integrate.ts
1626
1879
  import { InlineKeyboard as InlineKeyboard5 } from "grammy";
1627
1880
  async function handleIntegrate(ctx, _core) {
1628
- const { listIntegrations } = await import("./integrate-G6CVXTGT.js");
1881
+ const { listIntegrations } = await import("./integrate-JIEZYDOR.js");
1629
1882
  const agents = listIntegrations();
1630
1883
  const keyboard = new InlineKeyboard5();
1631
1884
  for (const agent of agents) {
@@ -1658,7 +1911,7 @@ function setupIntegrateCallbacks(bot, core) {
1658
1911
  } catch {
1659
1912
  }
1660
1913
  if (data === "i:back") {
1661
- const { listIntegrations } = await import("./integrate-G6CVXTGT.js");
1914
+ const { listIntegrations } = await import("./integrate-JIEZYDOR.js");
1662
1915
  const agents = listIntegrations();
1663
1916
  const keyboard2 = new InlineKeyboard5();
1664
1917
  for (const agent of agents) {
@@ -1678,7 +1931,7 @@ Select an agent to manage its integrations.`,
1678
1931
  const agentMatch = data.match(/^i:agent:(.+)$/);
1679
1932
  if (agentMatch) {
1680
1933
  const agentName2 = agentMatch[1];
1681
- const { getIntegration: getIntegration2 } = await import("./integrate-G6CVXTGT.js");
1934
+ const { getIntegration: getIntegration2 } = await import("./integrate-JIEZYDOR.js");
1682
1935
  const integration2 = getIntegration2(agentName2);
1683
1936
  if (!integration2) {
1684
1937
  await ctx.reply(`\u274C No integration available for '${escapeHtml(agentName2)}'.`, { parse_mode: "HTML" });
@@ -1705,7 +1958,7 @@ ${integration2.items.map((i) => `\u2022 <b>${escapeHtml(i.name)}</b> \u2014 ${es
1705
1958
  const action = actionMatch[1];
1706
1959
  const agentName = actionMatch[2];
1707
1960
  const itemId = actionMatch[3];
1708
- const { getIntegration } = await import("./integrate-G6CVXTGT.js");
1961
+ const { getIntegration } = await import("./integrate-JIEZYDOR.js");
1709
1962
  const integration = getIntegration(agentName);
1710
1963
  if (!integration) return;
1711
1964
  const item = integration.items.find((i) => i.id === itemId);
@@ -2189,7 +2442,7 @@ Tap to change:`, {
2189
2442
  await ctx.answerCallbackQuery();
2190
2443
  } catch {
2191
2444
  }
2192
- const { buildMenuKeyboard: buildMenuKeyboard3 } = await import("./menu-YDQ2LWAR.js");
2445
+ const { buildMenuKeyboard: buildMenuKeyboard3 } = await import("./menu-ALFN37IR.js");
2193
2446
  try {
2194
2447
  await ctx.editMessageText(`<b>OpenACP Menu</b>
2195
2448
  Choose an action:`, {
@@ -3361,7 +3614,7 @@ var ToolCardState = class {
3361
3614
  appendUsage(usage) {
3362
3615
  if (this.finalized) return;
3363
3616
  this.usage = usage;
3364
- this.flush();
3617
+ this.scheduleFlush();
3365
3618
  }
3366
3619
  finalize() {
3367
3620
  if (this.finalized) return;
@@ -3440,9 +3693,16 @@ var ThinkingIndicator = class {
3440
3693
  disable_notification: true
3441
3694
  })
3442
3695
  );
3443
- if (result && !this.dismissed) {
3444
- this.msgId = result.message_id;
3445
- this.startRefreshTimer();
3696
+ if (result) {
3697
+ if (this.dismissed) {
3698
+ try {
3699
+ await this.api.deleteMessage(this.chatId, result.message_id);
3700
+ } catch {
3701
+ }
3702
+ } else {
3703
+ this.msgId = result.message_id;
3704
+ this.startRefreshTimer();
3705
+ }
3446
3706
  }
3447
3707
  } catch (err) {
3448
3708
  log10.warn({ err }, "ThinkingIndicator.show() failed");
@@ -3450,11 +3710,19 @@ var ThinkingIndicator = class {
3450
3710
  this.sending = false;
3451
3711
  }
3452
3712
  }
3453
- /** Clear state stops refresh timer, no Telegram API call */
3454
- dismiss() {
3713
+ /** Dismiss indicator: stops refresh timer and deletes the Telegram message */
3714
+ async dismiss() {
3715
+ if (this.dismissed) return;
3455
3716
  this.dismissed = true;
3456
- this.msgId = void 0;
3457
3717
  this.stopRefreshTimer();
3718
+ const msgId = this.msgId;
3719
+ this.msgId = void 0;
3720
+ if (msgId) {
3721
+ try {
3722
+ await this.api.deleteMessage(this.chatId, msgId);
3723
+ } catch {
3724
+ }
3725
+ }
3458
3726
  }
3459
3727
  /** Reset for a new prompt cycle */
3460
3728
  reset() {
@@ -3506,6 +3774,7 @@ var ToolCard = class {
3506
3774
  msgId;
3507
3775
  lastSentText;
3508
3776
  flushPromise = Promise.resolve();
3777
+ overflowCount = 0;
3509
3778
  addTool(meta, kind, rawInput) {
3510
3779
  this.state.addTool(meta, kind, rawInput);
3511
3780
  }
@@ -3532,20 +3801,22 @@ var ToolCard = class {
3532
3801
  return this.msgId;
3533
3802
  }
3534
3803
  async _sendOrEdit(snapshot) {
3535
- const text = renderToolCard(snapshot);
3536
- if (!text) return;
3537
- if (this.msgId && text === this.lastSentText) return;
3538
- this.lastSentText = text;
3804
+ const fullText = renderToolCard(snapshot);
3805
+ if (!fullText) return;
3806
+ if (this.msgId && fullText === this.lastSentText) return;
3807
+ this.lastSentText = fullText;
3808
+ const chunks = splitToolCardText(fullText);
3539
3809
  try {
3810
+ const firstChunk = chunks[0];
3540
3811
  if (this.msgId) {
3541
3812
  await this.sendQueue.enqueue(
3542
- () => this.api.editMessageText(this.chatId, this.msgId, text, {
3813
+ () => this.api.editMessageText(this.chatId, this.msgId, firstChunk, {
3543
3814
  parse_mode: "HTML"
3544
3815
  })
3545
3816
  );
3546
3817
  } else {
3547
3818
  const result = await this.sendQueue.enqueue(
3548
- () => this.api.sendMessage(this.chatId, text, {
3819
+ () => this.api.sendMessage(this.chatId, firstChunk, {
3549
3820
  message_thread_id: this.threadId,
3550
3821
  parse_mode: "HTML",
3551
3822
  disable_notification: true
@@ -3553,6 +3824,18 @@ var ToolCard = class {
3553
3824
  );
3554
3825
  if (result) this.msgId = result.message_id;
3555
3826
  }
3827
+ for (let i = 1; i < chunks.length; i++) {
3828
+ if (i > this.overflowCount) {
3829
+ await this.sendQueue.enqueue(
3830
+ () => this.api.sendMessage(this.chatId, chunks[i], {
3831
+ message_thread_id: this.threadId,
3832
+ parse_mode: "HTML",
3833
+ disable_notification: true
3834
+ })
3835
+ );
3836
+ this.overflowCount = i;
3837
+ }
3838
+ }
3556
3839
  } catch (err) {
3557
3840
  log10.warn({ err }, "[ToolCard] send/edit failed");
3558
3841
  }
@@ -3564,52 +3847,76 @@ var ActivityTracker = class {
3564
3847
  this.chatId = chatId;
3565
3848
  this.threadId = threadId;
3566
3849
  this.sendQueue = sendQueue;
3850
+ this.verbosity = verbosity;
3567
3851
  this.thinking = new ThinkingIndicator(api, chatId, threadId, sendQueue);
3568
3852
  this.toolCard = new ToolCard(api, chatId, threadId, sendQueue, verbosity);
3569
3853
  }
3570
3854
  isFirstEvent = true;
3571
3855
  thinking;
3572
3856
  toolCard;
3857
+ verbosity;
3573
3858
  async onNewPrompt() {
3574
3859
  this.isFirstEvent = true;
3575
- this.thinking.dismiss();
3860
+ await this.thinking.dismiss();
3576
3861
  this.thinking.reset();
3862
+ await this.toolCard.finalize();
3863
+ this.toolCard = new ToolCard(
3864
+ this.api,
3865
+ this.chatId,
3866
+ this.threadId,
3867
+ this.sendQueue,
3868
+ this.verbosity
3869
+ );
3577
3870
  }
3578
3871
  async onThought() {
3579
3872
  this.isFirstEvent = false;
3873
+ await this.sealToolCardIfNeeded();
3580
3874
  await this.thinking.show();
3581
3875
  }
3582
3876
  async onTextStart() {
3583
3877
  this.isFirstEvent = false;
3584
- this.thinking.dismiss();
3878
+ await this.thinking.dismiss();
3879
+ await this.sealToolCardIfNeeded();
3585
3880
  }
3586
3881
  async onToolCall(meta, kind, rawInput) {
3587
3882
  this.isFirstEvent = false;
3588
- this.thinking.dismiss();
3883
+ await this.thinking.dismiss();
3589
3884
  this.thinking.reset();
3590
3885
  this.toolCard.addTool(meta, kind, rawInput);
3591
3886
  }
3887
+ /** Finalize current tool card and create a fresh one (when interrupted by text/thought) */
3888
+ async sealToolCardIfNeeded() {
3889
+ if (!this.toolCard.hasContent()) return;
3890
+ await this.toolCard.finalize();
3891
+ this.toolCard = new ToolCard(
3892
+ this.api,
3893
+ this.chatId,
3894
+ this.threadId,
3895
+ this.sendQueue,
3896
+ this.verbosity
3897
+ );
3898
+ }
3592
3899
  async onToolUpdate(id, status, viewerLinks, viewerFilePath) {
3593
3900
  this.toolCard.updateTool(id, status, viewerLinks, viewerFilePath);
3594
3901
  }
3595
3902
  async onPlan(entries) {
3596
3903
  this.isFirstEvent = false;
3597
- this.thinking.dismiss();
3904
+ await this.thinking.dismiss();
3598
3905
  this.toolCard.updatePlan(entries);
3599
3906
  }
3600
- async sendUsage(usage) {
3601
- this.toolCard.appendUsage(usage);
3907
+ /** @deprecated Usage is now sent as a separate message by the adapter */
3908
+ async sendUsage(_usage) {
3602
3909
  }
3603
- getUsageMsgId() {
3910
+ getToolCardMsgId() {
3604
3911
  return this.toolCard.getMsgId();
3605
3912
  }
3606
3913
  async cleanup() {
3607
- this.thinking.dismiss();
3914
+ await this.thinking.dismiss();
3608
3915
  await this.toolCard.finalize();
3609
3916
  this.toolCard.destroy();
3610
3917
  }
3611
3918
  destroy() {
3612
- this.thinking.dismiss();
3919
+ void this.thinking.dismiss();
3613
3920
  this.toolCard.destroy();
3614
3921
  }
3615
3922
  };
@@ -4060,6 +4367,7 @@ var DraftManager = class {
4060
4367
  }
4061
4368
  drafts = /* @__PURE__ */ new Map();
4062
4369
  textBuffers = /* @__PURE__ */ new Map();
4370
+ finalizedDrafts = /* @__PURE__ */ new Map();
4063
4371
  getOrCreate(sessionId, threadId) {
4064
4372
  let draft = this.drafts.get(sessionId);
4065
4373
  if (!draft) {
@@ -4095,6 +4403,9 @@ var DraftManager = class {
4095
4403
  if (!draft) return;
4096
4404
  this.drafts.delete(sessionId);
4097
4405
  const finalMsgId = await draft.finalize();
4406
+ if (finalMsgId) {
4407
+ this.finalizedDrafts.set(sessionId, { messageId: finalMsgId, draft });
4408
+ }
4098
4409
  if (assistantSessionId && sessionId === assistantSessionId) {
4099
4410
  const fullText = this.textBuffers.get(sessionId);
4100
4411
  this.textBuffers.delete(sessionId);
@@ -4117,9 +4428,25 @@ var DraftManager = class {
4117
4428
  this.textBuffers.delete(sessionId);
4118
4429
  }
4119
4430
  }
4431
+ /**
4432
+ * Strip a regex pattern from the active or finalized draft for a session.
4433
+ * Used by tts_strip to remove [TTS]...[/TTS] blocks after TTS audio is sent.
4434
+ */
4435
+ async stripPattern(sessionId, pattern) {
4436
+ const draft = this.drafts.get(sessionId);
4437
+ if (draft) {
4438
+ await draft.stripPattern(pattern);
4439
+ return;
4440
+ }
4441
+ const finalized = this.finalizedDrafts.get(sessionId);
4442
+ if (finalized) {
4443
+ await finalized.draft.stripPattern(pattern);
4444
+ }
4445
+ }
4120
4446
  cleanup(sessionId) {
4121
4447
  this.drafts.delete(sessionId);
4122
4448
  this.textBuffers.delete(sessionId);
4449
+ this.finalizedDrafts.delete(sessionId);
4123
4450
  }
4124
4451
  };
4125
4452
 
@@ -4218,6 +4545,231 @@ var SkillCommandManager = class {
4218
4545
  }
4219
4546
  };
4220
4547
 
4548
+ // src/core/adapter-primitives/messaging-adapter.ts
4549
+ var HIDDEN_ON_LOW = /* @__PURE__ */ new Set(["thought", "usage"]);
4550
+ var MessagingAdapter = class {
4551
+ constructor(context, adapterConfig) {
4552
+ this.context = context;
4553
+ this.adapterConfig = adapterConfig;
4554
+ }
4555
+ // === Message dispatch flow ===
4556
+ async sendMessage(sessionId, content) {
4557
+ const verbosity = this.getVerbosity();
4558
+ if (!this.shouldDisplay(content, verbosity)) return;
4559
+ await this.dispatchMessage(sessionId, content, verbosity);
4560
+ }
4561
+ async dispatchMessage(sessionId, content, verbosity) {
4562
+ switch (content.type) {
4563
+ case "text":
4564
+ return this.handleText(sessionId, content);
4565
+ case "thought":
4566
+ return this.handleThought(sessionId, content, verbosity);
4567
+ case "tool_call":
4568
+ return this.handleToolCall(sessionId, content, verbosity);
4569
+ case "tool_update":
4570
+ return this.handleToolUpdate(sessionId, content, verbosity);
4571
+ case "plan":
4572
+ return this.handlePlan(sessionId, content, verbosity);
4573
+ case "usage":
4574
+ return this.handleUsage(sessionId, content, verbosity);
4575
+ case "error":
4576
+ return this.handleError(sessionId, content);
4577
+ case "attachment":
4578
+ return this.handleAttachment(sessionId, content);
4579
+ case "system_message":
4580
+ return this.handleSystem(sessionId, content);
4581
+ case "session_end":
4582
+ return this.handleSessionEnd(sessionId, content);
4583
+ case "mode_change":
4584
+ return this.handleModeChange(sessionId, content);
4585
+ case "config_update":
4586
+ return this.handleConfigUpdate(sessionId, content);
4587
+ case "model_update":
4588
+ return this.handleModelUpdate(sessionId, content);
4589
+ case "user_replay":
4590
+ return this.handleUserReplay(sessionId, content);
4591
+ case "resource":
4592
+ return this.handleResource(sessionId, content);
4593
+ case "resource_link":
4594
+ return this.handleResourceLink(sessionId, content);
4595
+ }
4596
+ }
4597
+ // === Default handlers — all protected, all overridable ===
4598
+ async handleText(_sessionId, _content) {
4599
+ }
4600
+ async handleThought(_sessionId, _content, _verbosity) {
4601
+ }
4602
+ async handleToolCall(_sessionId, _content, _verbosity) {
4603
+ }
4604
+ async handleToolUpdate(_sessionId, _content, _verbosity) {
4605
+ }
4606
+ async handlePlan(_sessionId, _content, _verbosity) {
4607
+ }
4608
+ async handleUsage(_sessionId, _content, _verbosity) {
4609
+ }
4610
+ async handleError(_sessionId, _content) {
4611
+ }
4612
+ async handleAttachment(_sessionId, _content) {
4613
+ }
4614
+ async handleSystem(_sessionId, _content) {
4615
+ }
4616
+ async handleSessionEnd(_sessionId, _content) {
4617
+ }
4618
+ async handleModeChange(_sessionId, _content) {
4619
+ }
4620
+ async handleConfigUpdate(_sessionId, _content) {
4621
+ }
4622
+ async handleModelUpdate(_sessionId, _content) {
4623
+ }
4624
+ async handleUserReplay(_sessionId, _content) {
4625
+ }
4626
+ async handleResource(_sessionId, _content) {
4627
+ }
4628
+ async handleResourceLink(_sessionId, _content) {
4629
+ }
4630
+ // === Helpers ===
4631
+ getVerbosity() {
4632
+ const config = this.context.configManager.get();
4633
+ const channelConfig = config.channels;
4634
+ const v = channelConfig?.[this.name]?.displayVerbosity ?? this.adapterConfig.displayVerbosity;
4635
+ if (v === "low" || v === "high") return v;
4636
+ return "medium";
4637
+ }
4638
+ shouldDisplay(content, verbosity) {
4639
+ if (verbosity === "low" && HIDDEN_ON_LOW.has(content.type)) return false;
4640
+ if (content.type === "tool_call") {
4641
+ const meta = content.metadata ?? {};
4642
+ const toolName = meta.name ?? content.text ?? "";
4643
+ const toolKind = String(meta.kind ?? "other");
4644
+ const noiseAction = evaluateNoise(toolName, toolKind, meta.rawInput);
4645
+ if (noiseAction === "hide" && verbosity !== "high") return false;
4646
+ if (noiseAction === "collapse" && verbosity === "low") return false;
4647
+ }
4648
+ return true;
4649
+ }
4650
+ };
4651
+
4652
+ // src/core/adapter-primitives/rendering/renderer.ts
4653
+ var BaseRenderer = class {
4654
+ renderText(content) {
4655
+ return { body: content.text, format: "plain" };
4656
+ }
4657
+ renderToolCall(content, verbosity) {
4658
+ const meta = content.metadata ?? {};
4659
+ const name = meta.name ?? content.text ?? "Tool";
4660
+ const icon = resolveToolIcon(meta);
4661
+ const label = verbosity === "low" ? formatToolTitle(
4662
+ name,
4663
+ meta.rawInput,
4664
+ meta.displayTitle
4665
+ ) : formatToolSummary(
4666
+ name,
4667
+ meta.rawInput,
4668
+ meta.displaySummary
4669
+ );
4670
+ return { body: `${icon} ${label}`, format: "plain" };
4671
+ }
4672
+ renderToolUpdate(content, verbosity) {
4673
+ const meta = content.metadata ?? {};
4674
+ const name = meta.name ?? content.text ?? "Tool";
4675
+ const icon = resolveToolIcon(meta);
4676
+ const label = verbosity === "low" ? formatToolTitle(
4677
+ name,
4678
+ meta.rawInput,
4679
+ meta.displayTitle
4680
+ ) : formatToolSummary(
4681
+ name,
4682
+ meta.rawInput,
4683
+ meta.displaySummary
4684
+ );
4685
+ return { body: `${icon} ${label}`, format: "plain" };
4686
+ }
4687
+ renderPlan(content) {
4688
+ const entries = content.metadata?.entries ?? [];
4689
+ const lines = entries.map((e, i) => {
4690
+ const icon = e.status === "completed" ? "\u2705" : e.status === "in_progress" ? "\u{1F504}" : "\u2B1C";
4691
+ return `${icon} ${i + 1}. ${e.content}`;
4692
+ });
4693
+ return { body: `\u{1F4CB} Plan
4694
+ ${lines.join("\n")}`, format: "plain" };
4695
+ }
4696
+ renderUsage(content, verbosity) {
4697
+ const meta = content.metadata;
4698
+ if (!meta?.tokensUsed)
4699
+ return { body: "\u{1F4CA} Usage data unavailable", format: "plain" };
4700
+ const costStr = meta.cost != null ? ` \xB7 $${meta.cost.toFixed(2)}` : "";
4701
+ if (verbosity === "medium") {
4702
+ return {
4703
+ body: `\u{1F4CA} ${formatTokens(meta.tokensUsed)} tokens${costStr}`,
4704
+ format: "plain"
4705
+ };
4706
+ }
4707
+ if (!meta.contextSize)
4708
+ return {
4709
+ body: `\u{1F4CA} ${formatTokens(meta.tokensUsed)} tokens`,
4710
+ format: "plain"
4711
+ };
4712
+ const ratio = meta.tokensUsed / meta.contextSize;
4713
+ const pct = Math.round(ratio * 100);
4714
+ const bar = progressBar(ratio);
4715
+ let text = `\u{1F4CA} ${formatTokens(meta.tokensUsed)} / ${formatTokens(meta.contextSize)} tokens
4716
+ ${bar} ${pct}%`;
4717
+ if (meta.cost != null) text += `
4718
+ \u{1F4B0} $${meta.cost.toFixed(2)}`;
4719
+ return { body: text, format: "plain" };
4720
+ }
4721
+ renderPermission(request) {
4722
+ return {
4723
+ body: request.description,
4724
+ format: "plain",
4725
+ actions: request.options.map((o) => ({
4726
+ id: o.id,
4727
+ label: o.label,
4728
+ isAllow: o.isAllow
4729
+ }))
4730
+ };
4731
+ }
4732
+ renderError(content) {
4733
+ return { body: `\u274C Error: ${content.text}`, format: "plain" };
4734
+ }
4735
+ renderNotification(notification) {
4736
+ const emoji = {
4737
+ completed: "\u2705",
4738
+ error: "\u274C",
4739
+ permission: "\u{1F510}",
4740
+ input_required: "\u{1F4AC}",
4741
+ budget_warning: "\u26A0\uFE0F"
4742
+ };
4743
+ return {
4744
+ body: `${emoji[notification.type] || "\u2139\uFE0F"} ${notification.sessionName || "Session"}
4745
+ ${notification.summary}`,
4746
+ format: "plain"
4747
+ };
4748
+ }
4749
+ renderSystemMessage(content) {
4750
+ return { body: content.text, format: "plain" };
4751
+ }
4752
+ renderModeChange(content) {
4753
+ const modeId = content.metadata?.modeId ?? "";
4754
+ return { body: `\u{1F504} Mode: ${modeId}`, format: "plain" };
4755
+ }
4756
+ renderConfigUpdate() {
4757
+ return { body: "\u2699\uFE0F Config updated", format: "plain" };
4758
+ }
4759
+ renderModelUpdate(content) {
4760
+ const modelId = content.metadata?.modelId ?? "";
4761
+ return { body: `\u{1F916} Model: ${modelId}`, format: "plain" };
4762
+ }
4763
+ renderResource(content) {
4764
+ const uri = content.metadata?.uri ?? "";
4765
+ return { body: `\u{1F4C4} Resource: ${content.text} (${uri})`, format: "plain" };
4766
+ }
4767
+ renderResourceLink(content) {
4768
+ const uri = content.metadata?.uri ?? "";
4769
+ return { body: `\u{1F517} ${content.text}: ${uri}`, format: "plain" };
4770
+ }
4771
+ };
4772
+
4221
4773
  // src/plugins/telegram/renderer.ts
4222
4774
  var TelegramRenderer = class extends BaseRenderer {
4223
4775
  renderToolCall(content, verbosity) {
@@ -4600,7 +5152,7 @@ var TelegramAdapter = class extends MessagingAdapter {
4600
5152
  });
4601
5153
  return;
4602
5154
  }
4603
- const { getAgentCapabilities } = await import("./agent-registry-5LZT7CUB.js");
5155
+ const { getAgentCapabilities } = await import("./agent-registry-YOGP656W.js");
4604
5156
  const caps = getAgentCapabilities(agentName);
4605
5157
  if (!caps.supportsResume || !caps.resumeCommand) {
4606
5158
  await ctx.reply("This agent does not support session transfer.", {
@@ -4681,6 +5233,11 @@ var TelegramAdapter = class extends MessagingAdapter {
4681
5233
  }
4682
5234
  }
4683
5235
  async stop() {
5236
+ for (const tracker of this.sessionTrackers.values()) {
5237
+ tracker.destroy();
5238
+ }
5239
+ this.sessionTrackers.clear();
5240
+ this.sendQueue.clear();
4684
5241
  if (this.assistantSession) {
4685
5242
  await this.assistantSession.destroy();
4686
5243
  }
@@ -4993,14 +5550,25 @@ ${lines.join("\n")}`;
4993
5550
  const threadId = this.getThreadId(sessionId);
4994
5551
  const meta = content.metadata;
4995
5552
  await this.draftManager.finalize(sessionId, this.assistantSession?.id);
4996
- const tracker = this.getOrCreateTracker(sessionId, threadId, verbosity);
4997
- await tracker.sendUsage(meta ?? {});
5553
+ const usageText = formatUsage(meta ?? {}, verbosity);
5554
+ let usageMsgId;
5555
+ try {
5556
+ const result = await this.sendQueue.enqueue(
5557
+ () => this.bot.api.sendMessage(this.telegramConfig.chatId, usageText, {
5558
+ message_thread_id: threadId,
5559
+ parse_mode: "HTML",
5560
+ disable_notification: true
5561
+ })
5562
+ );
5563
+ usageMsgId = result?.message_id;
5564
+ } catch (err) {
5565
+ log12.warn({ err, sessionId }, "Failed to send usage message");
5566
+ }
4998
5567
  if (this.notificationTopicId && sessionId !== this.assistantSession?.id) {
4999
5568
  const sess = this.core.sessionManager.getSession(sessionId);
5000
5569
  const sessionName = sess?.name || "Session";
5001
5570
  const chatIdStr = String(this.telegramConfig.chatId);
5002
5571
  const numericId = chatIdStr.startsWith("-100") ? chatIdStr.slice(4) : chatIdStr.replace("-", "");
5003
- const usageMsgId = tracker.getUsageMsgId();
5004
5572
  const deepLink = usageMsgId ? `https://t.me/c/${numericId}/${threadId}/${usageMsgId}` : `https://t.me/c/${numericId}/${threadId}`;
5005
5573
  const text = `\u2705 <b>${escapeHtml(sessionName)}</b>
5006
5574
  Task completed.
@@ -5283,10 +5851,13 @@ Task completed.
5283
5851
  async cleanupSkillCommands(sessionId) {
5284
5852
  await this.skillManager.cleanup(sessionId);
5285
5853
  }
5854
+ async stripTTSBlock(sessionId) {
5855
+ await this.draftManager.stripPattern(sessionId, /\[TTS\][\s\S]*?\[\/TTS\]/g);
5856
+ }
5286
5857
  async archiveSessionTopic(sessionId) {
5287
5858
  const core = this.core;
5288
5859
  const session = core.sessionManager.getSession(sessionId);
5289
- if (!session) return;
5860
+ if (!session) throw new Error("Session not found");
5290
5861
  const chatId = this.telegramConfig.chatId;
5291
5862
  const oldTopicId = Number(session.threadId);
5292
5863
  session.archiving = true;
@@ -5299,12 +5870,29 @@ Task completed.
5299
5870
  this.sessionTrackers.delete(session.id);
5300
5871
  }
5301
5872
  await deleteSessionTopic(this.bot, chatId, oldTopicId);
5873
+ const topicName = session.name ?? `Session ${session.id.slice(0, 6)}`;
5874
+ const newTopicId = await createSessionTopic(this.bot, chatId, topicName);
5875
+ session.archiving = false;
5876
+ return String(newTopicId);
5302
5877
  }
5303
5878
  };
5304
5879
 
5305
5880
  export {
5881
+ progressBar,
5882
+ formatTokens,
5883
+ stripCodeFences,
5884
+ truncateContent,
5885
+ splitMessage,
5886
+ STATUS_ICONS,
5887
+ KIND_ICONS,
5888
+ extractContentText,
5889
+ formatToolSummary,
5890
+ formatToolTitle,
5891
+ resolveToolIcon,
5306
5892
  PRODUCT_GUIDE,
5307
5893
  SendQueue,
5894
+ MessagingAdapter,
5895
+ BaseRenderer,
5308
5896
  TelegramAdapter
5309
5897
  };
5310
- //# sourceMappingURL=chunk-XWDW3XBE.js.map
5898
+ //# sourceMappingURL=chunk-RXMWJHWH.js.map