@openacp/cli 0.2.28 → 0.2.30

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 (42) hide show
  1. package/dist/{autostart-YBYXQA77.js → autostart-N4HIL6C3.js} +3 -3
  2. package/dist/{chunk-CQMS5U7Z.js → chunk-2QSUSMBI.js} +3 -3
  3. package/dist/{chunk-PQRVTUNH.js → chunk-5E6ZXCNN.js} +2 -2
  4. package/dist/{chunk-4BN7NSKB.js → chunk-7VEHVMVM.js} +4 -4
  5. package/dist/{chunk-S6O7SM6A.js → chunk-CEAIK37M.js} +2 -2
  6. package/dist/{chunk-FGXG3H3F.js → chunk-GP66XLS6.js} +2 -2
  7. package/dist/{chunk-MNJDYDGH.js → chunk-JOSJGZGF.js} +19 -15
  8. package/dist/chunk-JOSJGZGF.js.map +1 -0
  9. package/dist/{chunk-WXS6ONOD.js → chunk-RBDPCHGD.js} +2 -2
  10. package/dist/{chunk-6HORD4FS.js → chunk-WKHCVK5P.js} +247 -146
  11. package/dist/chunk-WKHCVK5P.js.map +1 -0
  12. package/dist/{chunk-QWUJIKTX.js → chunk-ZMNBZAXN.js} +4 -4
  13. package/dist/cli.js +18 -18
  14. package/dist/{config-2XALNLAA.js → config-3EDZ3IMJ.js} +3 -3
  15. package/dist/config-editor-KCD6FFC3.js +11 -0
  16. package/dist/{daemon-3E5OMLT3.js → daemon-TNQKCKTB.js} +4 -4
  17. package/dist/index.d.ts +5 -1
  18. package/dist/index.js +8 -8
  19. package/dist/install-cloudflared-LMM7MFQX.js +8 -0
  20. package/dist/{main-XAUS3VZW.js → main-CW4GRPSX.js} +13 -13
  21. package/dist/{setup-FTNJACSC.js → setup-JRNMPTIT.js} +4 -4
  22. package/dist/{tunnel-service-YQ4RG652.js → tunnel-service-4GISQZNP.js} +3 -3
  23. package/package.json +2 -2
  24. package/dist/chunk-6HORD4FS.js.map +0 -1
  25. package/dist/chunk-MNJDYDGH.js.map +0 -1
  26. package/dist/config-editor-56B6YU7B.js +0 -11
  27. package/dist/install-cloudflared-57NRTI4E.js +0 -8
  28. /package/dist/{autostart-YBYXQA77.js.map → autostart-N4HIL6C3.js.map} +0 -0
  29. /package/dist/{chunk-CQMS5U7Z.js.map → chunk-2QSUSMBI.js.map} +0 -0
  30. /package/dist/{chunk-PQRVTUNH.js.map → chunk-5E6ZXCNN.js.map} +0 -0
  31. /package/dist/{chunk-4BN7NSKB.js.map → chunk-7VEHVMVM.js.map} +0 -0
  32. /package/dist/{chunk-S6O7SM6A.js.map → chunk-CEAIK37M.js.map} +0 -0
  33. /package/dist/{chunk-FGXG3H3F.js.map → chunk-GP66XLS6.js.map} +0 -0
  34. /package/dist/{chunk-WXS6ONOD.js.map → chunk-RBDPCHGD.js.map} +0 -0
  35. /package/dist/{chunk-QWUJIKTX.js.map → chunk-ZMNBZAXN.js.map} +0 -0
  36. /package/dist/{config-2XALNLAA.js.map → config-3EDZ3IMJ.js.map} +0 -0
  37. /package/dist/{config-editor-56B6YU7B.js.map → config-editor-KCD6FFC3.js.map} +0 -0
  38. /package/dist/{daemon-3E5OMLT3.js.map → daemon-TNQKCKTB.js.map} +0 -0
  39. /package/dist/{install-cloudflared-57NRTI4E.js.map → install-cloudflared-LMM7MFQX.js.map} +0 -0
  40. /package/dist/{main-XAUS3VZW.js.map → main-CW4GRPSX.js.map} +0 -0
  41. /package/dist/{setup-FTNJACSC.js.map → setup-JRNMPTIT.js.map} +0 -0
  42. /package/dist/{tunnel-service-YQ4RG652.js.map → tunnel-service-4GISQZNP.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createChildLogger,
3
3
  createSessionLogger
4
- } from "./chunk-MNJDYDGH.js";
4
+ } from "./chunk-JOSJGZGF.js";
5
5
 
6
6
  // src/core/streams.ts
7
7
  function nodeToWebWritable(nodeStream) {
@@ -304,6 +304,8 @@ ${stderr}`
304
304
  event = {
305
305
  type: "tool_update",
306
306
  id: update.toolCallId,
307
+ name: update.title ?? void 0,
308
+ kind: update.kind ?? void 0,
307
309
  status: update.status ?? "pending",
308
310
  content: update.content ?? void 0,
309
311
  rawInput: update.rawInput ?? void 0,
@@ -691,6 +693,16 @@ var SessionManager = class {
691
693
  await this.store.save({ ...record, status });
692
694
  }
693
695
  }
696
+ async updateSessionName(sessionId, name) {
697
+ if (!this.store) return;
698
+ const record = this.store.get(sessionId);
699
+ if (record) {
700
+ await this.store.save({ ...record, name });
701
+ }
702
+ }
703
+ getSessionRecord(sessionId) {
704
+ return this.store?.get(sessionId);
705
+ }
694
706
  async cancelSession(sessionId) {
695
707
  const session = this.sessions.get(sessionId);
696
708
  if (session) {
@@ -871,17 +883,21 @@ function extractFileInfo(name, kind, content, rawInput, meta) {
871
883
  let info = null;
872
884
  if (meta) {
873
885
  const m = meta;
874
- const file = m?.claudeCode?.toolResponse?.file;
886
+ const tr = m?.claudeCode?.toolResponse;
887
+ const file = tr?.file;
875
888
  if (file?.filePath && file?.content) {
876
889
  info = { filePath: file.filePath, content: file.content };
877
890
  }
891
+ if (!info && tr?.filePath && tr?.content) {
892
+ info = { filePath: tr.filePath, content: tr.content };
893
+ }
878
894
  }
879
895
  if (!info && rawInput) {
880
896
  const ri = rawInput;
881
897
  const filePath = ri?.file_path || ri?.filePath || ri?.path;
882
898
  if (typeof filePath === "string") {
883
899
  const parsed = content ? parseContent(content) : null;
884
- info = { filePath, content: parsed?.content || ri?.content };
900
+ info = { filePath, content: parsed?.content || ri?.content, oldContent: parsed?.oldContent };
885
901
  }
886
902
  }
887
903
  if (!info && content) {
@@ -1144,6 +1160,7 @@ var OpenACPCore = class {
1144
1160
  case "tool_call": {
1145
1161
  const metadata = {
1146
1162
  id: event.id,
1163
+ name: event.name,
1147
1164
  kind: event.kind,
1148
1165
  status: event.status,
1149
1166
  content: event.content,
@@ -1155,6 +1172,8 @@ var OpenACPCore = class {
1155
1172
  case "tool_update": {
1156
1173
  const metadata = {
1157
1174
  id: event.id,
1175
+ name: event.name,
1176
+ kind: event.kind,
1158
1177
  status: event.status,
1159
1178
  content: event.content
1160
1179
  };
@@ -1538,6 +1557,7 @@ function extractContentText(content, depth = 0) {
1538
1557
  if (c.type === "text" && typeof c.text === "string") return c.text;
1539
1558
  if (typeof c.text === "string") return c.text;
1540
1559
  if (typeof c.content === "string") return c.content;
1560
+ if (c.content && typeof c.content === "object") return extractContentText(c.content, depth + 1);
1541
1561
  if (c.input) return extractContentText(c.input, depth + 1);
1542
1562
  if (c.output) return extractContentText(c.output, depth + 1);
1543
1563
  const keys = Object.keys(c).filter((k) => k !== "type");
@@ -1554,12 +1574,14 @@ function formatToolCall(tool) {
1554
1574
  const si = STATUS_ICON[tool.status || ""] || "\u{1F527}";
1555
1575
  const ki = KIND_ICON[tool.kind || ""] || "\u{1F6E0}\uFE0F";
1556
1576
  let text = `${si} ${ki} <b>${escapeHtml(tool.name || "Tool")}</b>`;
1557
- const details = extractContentText(tool.content);
1558
- if (details) {
1559
- text += `
1577
+ text += formatViewerLinks(tool.viewerLinks, tool.viewerFilePath);
1578
+ if (!tool.viewerLinks) {
1579
+ const details = extractContentText(tool.content);
1580
+ if (details) {
1581
+ text += `
1560
1582
  <pre>${escapeHtml(truncateContent(details))}</pre>`;
1583
+ }
1561
1584
  }
1562
- text += formatViewerLinks(tool.viewerLinks, tool.viewerFilePath);
1563
1585
  return text;
1564
1586
  }
1565
1587
  function formatToolUpdate(update) {
@@ -1567,12 +1589,14 @@ function formatToolUpdate(update) {
1567
1589
  const ki = KIND_ICON[update.kind || ""] || "\u{1F6E0}\uFE0F";
1568
1590
  const name = update.name || "Tool";
1569
1591
  let text = `${si} ${ki} <b>${escapeHtml(name)}</b>`;
1570
- const details = extractContentText(update.content);
1571
- if (details) {
1572
- text += `
1592
+ text += formatViewerLinks(update.viewerLinks, update.viewerFilePath);
1593
+ if (!update.viewerLinks) {
1594
+ const details = extractContentText(update.content);
1595
+ if (details) {
1596
+ text += `
1573
1597
  <pre>${escapeHtml(truncateContent(details))}</pre>`;
1598
+ }
1574
1599
  }
1575
- text += formatViewerLinks(update.viewerLinks, update.viewerFilePath);
1576
1600
  return text;
1577
1601
  }
1578
1602
  function formatViewerLinks(links, filePath) {
@@ -1623,95 +1647,69 @@ function splitMessage(text, maxLength = 4096) {
1623
1647
  }
1624
1648
 
1625
1649
  // src/adapters/telegram/streaming.ts
1626
- var nextDraftId = 1;
1650
+ var FLUSH_INTERVAL = 5e3;
1627
1651
  var MessageDraft = class {
1628
- // Only set in fallback mode (sendMessageDraft returns true, not Message)
1629
- constructor(bot, chatId, threadId, throttleMs = 200, sendQueue) {
1652
+ constructor(bot, chatId, threadId, sendQueue, sessionId) {
1630
1653
  this.bot = bot;
1631
1654
  this.chatId = chatId;
1632
1655
  this.threadId = threadId;
1633
1656
  this.sendQueue = sendQueue;
1634
- this.draftId = nextDraftId++;
1635
- this.minInterval = throttleMs;
1657
+ this.sessionId = sessionId;
1636
1658
  }
1637
- draftId;
1638
1659
  buffer = "";
1639
- lastFlush = 0;
1660
+ messageId;
1661
+ firstFlushPending = false;
1640
1662
  flushTimer;
1641
1663
  flushPromise = Promise.resolve();
1642
- minInterval;
1643
- useFallback = false;
1644
- messageId;
1664
+ lastSentBuffer = "";
1645
1665
  append(text) {
1646
1666
  this.buffer += text;
1647
1667
  this.scheduleFlush();
1648
1668
  }
1649
1669
  scheduleFlush() {
1650
- const now = Date.now();
1651
- const elapsed = now - this.lastFlush;
1652
- if (elapsed >= this.minInterval) {
1670
+ if (this.flushTimer) return;
1671
+ this.flushTimer = setTimeout(() => {
1672
+ this.flushTimer = void 0;
1653
1673
  this.flushPromise = this.flushPromise.then(() => this.flush()).catch(() => {
1654
1674
  });
1655
- } else if (!this.flushTimer) {
1656
- this.flushTimer = setTimeout(() => {
1657
- this.flushTimer = void 0;
1658
- this.flushPromise = this.flushPromise.then(() => this.flush()).catch(() => {
1659
- });
1660
- }, this.minInterval - elapsed);
1661
- }
1675
+ }, FLUSH_INTERVAL);
1662
1676
  }
1663
1677
  async flush() {
1664
1678
  if (!this.buffer) return;
1665
- this.lastFlush = Date.now();
1679
+ if (this.firstFlushPending) return;
1666
1680
  const html = markdownToTelegramHtml(this.buffer);
1667
1681
  const truncated = html.length > 4096 ? html.slice(0, 4090) + "\n..." : html;
1668
1682
  if (!truncated) return;
1669
- if (this.useFallback) {
1670
- await this.flushFallback(truncated);
1671
- return;
1672
- }
1673
- try {
1674
- await this.bot.api.sendMessageDraft(this.chatId, this.draftId, truncated, {
1675
- message_thread_id: this.threadId,
1676
- parse_mode: "HTML"
1677
- });
1678
- } catch {
1679
- this.useFallback = true;
1680
- this.minInterval = 1e3;
1681
- await this.flushFallback(truncated);
1682
- }
1683
- }
1684
- async flushFallback(html) {
1685
- const exec = this.sendQueue ? (fn) => this.sendQueue.enqueue(fn) : (fn) => fn();
1686
- try {
1687
- if (!this.messageId) {
1688
- const msg = await exec(
1689
- () => this.bot.api.sendMessage(this.chatId, html, {
1683
+ if (!this.messageId) {
1684
+ this.firstFlushPending = true;
1685
+ try {
1686
+ const result = await this.sendQueue.enqueue(
1687
+ () => this.bot.api.sendMessage(this.chatId, truncated, {
1690
1688
  message_thread_id: this.threadId,
1691
1689
  parse_mode: "HTML",
1692
1690
  disable_notification: true
1693
- })
1694
- );
1695
- this.messageId = msg.message_id;
1696
- } else {
1697
- await exec(
1698
- () => this.bot.api.editMessageText(this.chatId, this.messageId, html, {
1699
- parse_mode: "HTML"
1700
- })
1691
+ }),
1692
+ { type: "other" }
1701
1693
  );
1694
+ if (result) {
1695
+ this.messageId = result.message_id;
1696
+ this.lastSentBuffer = this.buffer;
1697
+ }
1698
+ } catch {
1699
+ } finally {
1700
+ this.firstFlushPending = false;
1702
1701
  }
1703
- } catch {
1702
+ } else {
1704
1703
  try {
1705
- if (!this.messageId) {
1706
- const msg = await exec(
1707
- () => this.bot.api.sendMessage(this.chatId, this.buffer.slice(0, 4096), {
1708
- message_thread_id: this.threadId,
1709
- disable_notification: true
1710
- })
1711
- );
1712
- this.messageId = msg.message_id;
1713
- }
1704
+ await this.sendQueue.enqueue(
1705
+ () => this.bot.api.editMessageText(this.chatId, this.messageId, truncated, {
1706
+ parse_mode: "HTML"
1707
+ }),
1708
+ { type: "text", key: this.sessionId }
1709
+ );
1710
+ this.lastSentBuffer = this.buffer;
1714
1711
  } catch {
1712
+ this.messageId = void 0;
1715
1713
  }
1716
1714
  }
1717
1715
  }
@@ -1722,31 +1720,47 @@ var MessageDraft = class {
1722
1720
  }
1723
1721
  await this.flushPromise;
1724
1722
  if (!this.buffer) return this.messageId;
1723
+ if (this.messageId && this.buffer === this.lastSentBuffer) {
1724
+ return this.messageId;
1725
+ }
1725
1726
  const html = markdownToTelegramHtml(this.buffer);
1726
1727
  const chunks = splitMessage(html);
1727
1728
  try {
1728
1729
  for (let i = 0; i < chunks.length; i++) {
1729
1730
  const chunk = chunks[i];
1730
1731
  if (i === 0 && this.messageId) {
1731
- await this.bot.api.editMessageText(this.chatId, this.messageId, chunk, {
1732
- parse_mode: "HTML"
1733
- });
1732
+ await this.sendQueue.enqueue(
1733
+ () => this.bot.api.editMessageText(this.chatId, this.messageId, chunk, {
1734
+ parse_mode: "HTML"
1735
+ }),
1736
+ { type: "other" }
1737
+ );
1734
1738
  } else {
1735
- const msg = await this.bot.api.sendMessage(this.chatId, chunk, {
1736
- message_thread_id: this.threadId,
1737
- parse_mode: "HTML",
1738
- disable_notification: true
1739
- });
1740
- this.messageId = msg.message_id;
1739
+ const msg = await this.sendQueue.enqueue(
1740
+ () => this.bot.api.sendMessage(this.chatId, chunk, {
1741
+ message_thread_id: this.threadId,
1742
+ parse_mode: "HTML",
1743
+ disable_notification: true
1744
+ }),
1745
+ { type: "other" }
1746
+ );
1747
+ if (msg) {
1748
+ this.messageId = msg.message_id;
1749
+ }
1741
1750
  }
1742
1751
  }
1743
1752
  } catch {
1744
- try {
1745
- await this.bot.api.sendMessage(this.chatId, this.buffer.slice(0, 4096), {
1746
- message_thread_id: this.threadId,
1747
- disable_notification: true
1748
- });
1749
- } catch {
1753
+ if (this.buffer !== this.lastSentBuffer) {
1754
+ try {
1755
+ await this.sendQueue.enqueue(
1756
+ () => this.bot.api.sendMessage(this.chatId, this.buffer.slice(0, 4096), {
1757
+ message_thread_id: this.threadId,
1758
+ disable_notification: true
1759
+ }),
1760
+ { type: "other" }
1761
+ );
1762
+ } catch {
1763
+ }
1750
1764
  }
1751
1765
  }
1752
1766
  return this.messageId;
@@ -2155,7 +2169,7 @@ ${escapeHtml(request.description)}`,
2155
2169
  }
2156
2170
  );
2157
2171
  const deepLink = buildDeepLink(this.chatId, msg.message_id);
2158
- await this.sendNotification({
2172
+ void this.sendNotification({
2159
2173
  sessionId: session.id,
2160
2174
  sessionName: session.name,
2161
2175
  type: "permission",
@@ -2248,34 +2262,67 @@ function redirectToAssistant(chatId, assistantTopicId) {
2248
2262
 
2249
2263
  // src/adapters/telegram/send-queue.ts
2250
2264
  var TelegramSendQueue = class {
2251
- queue = Promise.resolve();
2265
+ items = [];
2266
+ processing = false;
2252
2267
  lastExec = 0;
2253
2268
  minInterval;
2254
- constructor(minInterval = 100) {
2269
+ constructor(minInterval = 3e3) {
2255
2270
  this.minInterval = minInterval;
2256
2271
  }
2257
- enqueue(fn) {
2258
- let resolve;
2259
- let reject;
2260
- const resultPromise = new Promise((res, rej) => {
2261
- resolve = res;
2262
- reject = rej;
2263
- });
2264
- this.queue = this.queue.then(async () => {
2265
- const elapsed = Date.now() - this.lastExec;
2266
- if (elapsed < this.minInterval) {
2267
- await new Promise((r) => setTimeout(r, this.minInterval - elapsed));
2268
- }
2269
- try {
2270
- const result = await fn();
2271
- resolve(result);
2272
- } catch (err) {
2273
- reject(err);
2274
- } finally {
2275
- this.lastExec = Date.now();
2272
+ enqueue(fn, opts) {
2273
+ const type = opts?.type ?? "other";
2274
+ const key = opts?.key;
2275
+ return new Promise((resolve, reject) => {
2276
+ if (type === "text" && key) {
2277
+ const idx = this.items.findIndex(
2278
+ (item) => item.type === "text" && item.key === key
2279
+ );
2280
+ if (idx !== -1) {
2281
+ this.items[idx].resolve(void 0);
2282
+ this.items[idx] = { fn, type, key, resolve, reject };
2283
+ this.scheduleProcess();
2284
+ return;
2285
+ }
2276
2286
  }
2287
+ this.items.push({ fn, type, key, resolve, reject });
2288
+ this.scheduleProcess();
2277
2289
  });
2278
- return resultPromise;
2290
+ }
2291
+ onRateLimited() {
2292
+ const remaining = [];
2293
+ for (const item of this.items) {
2294
+ if (item.type === "text") {
2295
+ item.resolve(void 0);
2296
+ } else {
2297
+ remaining.push(item);
2298
+ }
2299
+ }
2300
+ this.items = remaining;
2301
+ }
2302
+ scheduleProcess() {
2303
+ if (this.processing) return;
2304
+ if (this.items.length === 0) return;
2305
+ const elapsed = Date.now() - this.lastExec;
2306
+ const delay = Math.max(0, this.minInterval - elapsed);
2307
+ this.processing = true;
2308
+ setTimeout(() => void this.processNext(), delay);
2309
+ }
2310
+ async processNext() {
2311
+ const item = this.items.shift();
2312
+ if (!item) {
2313
+ this.processing = false;
2314
+ return;
2315
+ }
2316
+ try {
2317
+ const result = await item.fn();
2318
+ item.resolve(result);
2319
+ } catch (err) {
2320
+ item.reject(err);
2321
+ } finally {
2322
+ this.lastExec = Date.now();
2323
+ this.processing = false;
2324
+ this.scheduleProcess();
2325
+ }
2279
2326
  }
2280
2327
  };
2281
2328
 
@@ -2284,8 +2331,8 @@ import { nanoid as nanoid4 } from "nanoid";
2284
2331
  import { InlineKeyboard as InlineKeyboard3 } from "grammy";
2285
2332
  var CMD_NEW_RE = /\/new(?:\s+([^\s\u0080-\uFFFF]+)(?:\s+([^\s\u0080-\uFFFF]+))?)?/;
2286
2333
  var CMD_CANCEL_RE = /\/cancel\b/;
2287
- var KW_NEW_RE = /(?:tao|tạo|create|new)\s+session/i;
2288
- var KW_CANCEL_RE = /(?:huy|huỷ|cancel|dung|dừng)\s+session/i;
2334
+ var KW_NEW_RE = /(?:create|new)\s+session/i;
2335
+ var KW_CANCEL_RE = /(?:cancel|stop)\s+session/i;
2289
2336
  function detectAction(text) {
2290
2337
  if (!text) return null;
2291
2338
  const cancelCmd = CMD_CANCEL_RE.exec(text);
@@ -2330,11 +2377,11 @@ function removeAction(id) {
2330
2377
  function buildActionKeyboard(actionId, action) {
2331
2378
  const keyboard = new InlineKeyboard3();
2332
2379
  if (action.action === "new_session") {
2333
- keyboard.text("\u2705 T\u1EA1o session", `a:${actionId}`);
2334
- keyboard.text("\u274C Hu\u1EF7", `a:dismiss:${actionId}`);
2380
+ keyboard.text("\u2705 Create session", `a:${actionId}`);
2381
+ keyboard.text("\u274C Cancel", `a:dismiss:${actionId}`);
2335
2382
  } else {
2336
- keyboard.text("\u26D4 Hu\u1EF7 session", `a:${actionId}`);
2337
- keyboard.text("\u274C Kh\xF4ng", `a:dismiss:${actionId}`);
2383
+ keyboard.text("\u26D4 Cancel session", `a:${actionId}`);
2384
+ keyboard.text("\u274C No", `a:dismiss:${actionId}`);
2338
2385
  }
2339
2386
  return keyboard;
2340
2387
  }
@@ -2348,19 +2395,19 @@ function setupActionCallbacks(bot, core, chatId, getAssistantSessionId) {
2348
2395
  });
2349
2396
  } catch {
2350
2397
  }
2351
- await ctx.answerCallbackQuery({ text: "\u0110\xE3 hu\u1EF7" });
2398
+ await ctx.answerCallbackQuery({ text: "Dismissed" });
2352
2399
  });
2353
2400
  bot.callbackQuery(/^a:(?!dismiss)/, async (ctx) => {
2354
2401
  const actionId = ctx.callbackQuery.data.replace("a:", "");
2355
2402
  const action = getAction(actionId);
2356
2403
  if (!action) {
2357
- await ctx.answerCallbackQuery({ text: "Action \u0111\xE3 h\u1EBFt h\u1EA1n" });
2404
+ await ctx.answerCallbackQuery({ text: "Action expired" });
2358
2405
  return;
2359
2406
  }
2360
2407
  removeAction(actionId);
2361
2408
  try {
2362
2409
  if (action.action === "new_session") {
2363
- await ctx.answerCallbackQuery({ text: "\u23F3 \u0110ang t\u1EA1o session..." });
2410
+ await ctx.answerCallbackQuery({ text: "\u23F3 Creating session..." });
2364
2411
  const { threadId } = await executeNewSession(
2365
2412
  bot,
2366
2413
  core,
@@ -2386,13 +2433,13 @@ function setupActionCallbacks(bot, core, chatId, getAssistantSessionId) {
2386
2433
  const assistantId = getAssistantSessionId();
2387
2434
  const cancelled = await executeCancelSession(core, assistantId);
2388
2435
  if (cancelled) {
2389
- await ctx.answerCallbackQuery({ text: "\u26D4 Session \u0111\xE3 hu\u1EF7" });
2436
+ await ctx.answerCallbackQuery({ text: "\u26D4 Session cancelled" });
2390
2437
  const originalText = ctx.callbackQuery.message?.text ?? "";
2391
2438
  try {
2392
2439
  await ctx.editMessageText(
2393
2440
  originalText + `
2394
2441
 
2395
- \u26D4 Session "${cancelled.name ?? cancelled.id}" \u0111\xE3 hu\u1EF7`,
2442
+ \u26D4 Session "${cancelled.name ?? cancelled.id}" cancelled`,
2396
2443
  { parse_mode: "HTML" }
2397
2444
  );
2398
2445
  } catch {
@@ -2402,7 +2449,7 @@ function setupActionCallbacks(bot, core, chatId, getAssistantSessionId) {
2402
2449
  }
2403
2450
  } else {
2404
2451
  await ctx.answerCallbackQuery({
2405
- text: "Kh\xF4ng c\xF3 session n\xE0o \u0111ang ch\u1EA1y"
2452
+ text: "No active session"
2406
2453
  });
2407
2454
  try {
2408
2455
  await ctx.editMessageReplyMarkup({
@@ -2413,7 +2460,7 @@ function setupActionCallbacks(bot, core, chatId, getAssistantSessionId) {
2413
2460
  }
2414
2461
  }
2415
2462
  } catch {
2416
- await ctx.answerCallbackQuery({ text: "\u274C L\u1ED7i, th\u1EED l\u1EA1i sau" });
2463
+ await ctx.answerCallbackQuery({ text: "\u274C Error, try again later" });
2417
2464
  try {
2418
2465
  await ctx.editMessageReplyMarkup({
2419
2466
  reply_markup: { inline_keyboard: [] }
@@ -2452,7 +2499,7 @@ var TelegramAdapter = class extends ChannelAdapter {
2452
2499
  assistantTopicId;
2453
2500
  skillMessages = /* @__PURE__ */ new Map();
2454
2501
  // sessionId → pinned messageId
2455
- sendQueue = new TelegramSendQueue();
2502
+ sendQueue = new TelegramSendQueue(3e3);
2456
2503
  constructor(core, config) {
2457
2504
  super(core, config);
2458
2505
  this.telegramConfig = config;
@@ -2471,6 +2518,10 @@ var TelegramAdapter = class extends ChannelAdapter {
2471
2518
  return result;
2472
2519
  }
2473
2520
  const retryAfter = (result.parameters?.retry_after ?? 5) + 1;
2521
+ const rateLimitedMethods = ["sendMessage", "editMessageText", "editMessageReplyMarkup"];
2522
+ if (rateLimitedMethods.includes(method)) {
2523
+ this.sendQueue.onRateLimited();
2524
+ }
2474
2525
  log8.warn(
2475
2526
  { method, retryAfter, attempt: attempt + 1 },
2476
2527
  "Rate limited by Telegram, retrying"
@@ -2596,6 +2647,7 @@ Workspace: <code>${workspace}</code>
2596
2647
  }
2597
2648
  if (threadId === this.notificationTopicId) return;
2598
2649
  if (threadId === this.assistantTopicId) {
2650
+ await this.finalizeDraft(this.assistantSession.id);
2599
2651
  ctx.replyWithChatAction("typing").catch(() => {
2600
2652
  });
2601
2653
  handleAssistantMessage(this.assistantSession, ctx.message.text).catch(
@@ -2603,6 +2655,8 @@ Workspace: <code>${workspace}</code>
2603
2655
  );
2604
2656
  return;
2605
2657
  }
2658
+ const sessionId = this.core.sessionManager.getSessionByThread("telegram", String(threadId))?.id;
2659
+ if (sessionId) await this.finalizeDraft(sessionId);
2606
2660
  ctx.replyWithChatAction("typing").catch(() => {
2607
2661
  });
2608
2662
  this.core.handleMessage({
@@ -2631,8 +2685,8 @@ Workspace: <code>${workspace}</code>
2631
2685
  this.bot,
2632
2686
  this.telegramConfig.chatId,
2633
2687
  threadId,
2634
- this.telegramConfig.streamThrottleMs,
2635
- this.sendQueue
2688
+ this.sendQueue,
2689
+ sessionId
2636
2690
  );
2637
2691
  this.sessionDrafts.set(sessionId, draft);
2638
2692
  }
@@ -2646,6 +2700,21 @@ Workspace: <code>${workspace}</code>
2646
2700
  case "tool_call": {
2647
2701
  await this.finalizeDraft(sessionId);
2648
2702
  const meta = content.metadata;
2703
+ if (!this.toolCallMessages.has(sessionId)) {
2704
+ this.toolCallMessages.set(sessionId, /* @__PURE__ */ new Map());
2705
+ }
2706
+ let resolveReady;
2707
+ const ready = new Promise((r) => {
2708
+ resolveReady = r;
2709
+ });
2710
+ this.toolCallMessages.get(sessionId).set(meta.id, {
2711
+ msgId: 0,
2712
+ name: meta.name,
2713
+ kind: meta.kind,
2714
+ viewerLinks: meta.viewerLinks,
2715
+ viewerFilePath: content.metadata?.viewerFilePath,
2716
+ ready
2717
+ });
2649
2718
  const msg = await this.sendQueue.enqueue(
2650
2719
  () => this.bot.api.sendMessage(
2651
2720
  this.telegramConfig.chatId,
@@ -2657,43 +2726,52 @@ Workspace: <code>${workspace}</code>
2657
2726
  }
2658
2727
  )
2659
2728
  );
2660
- if (!this.toolCallMessages.has(sessionId)) {
2661
- this.toolCallMessages.set(sessionId, /* @__PURE__ */ new Map());
2662
- }
2663
- this.toolCallMessages.get(sessionId).set(meta.id, {
2664
- msgId: msg.message_id,
2665
- name: meta.name,
2666
- kind: meta.kind,
2667
- viewerLinks: meta.viewerLinks,
2668
- viewerFilePath: content.metadata?.viewerFilePath
2669
- });
2729
+ const toolEntry = this.toolCallMessages.get(sessionId).get(meta.id);
2730
+ toolEntry.msgId = msg.message_id;
2731
+ resolveReady();
2670
2732
  break;
2671
2733
  }
2672
2734
  case "tool_update": {
2673
2735
  const meta = content.metadata;
2674
2736
  const toolState = this.toolCallMessages.get(sessionId)?.get(meta.id);
2675
2737
  if (toolState) {
2676
- const viewerLinks = meta.viewerLinks || toolState.viewerLinks;
2677
- const viewerFilePath = content.metadata?.viewerFilePath || toolState.viewerFilePath;
2678
- if (meta.viewerLinks) toolState.viewerLinks = meta.viewerLinks;
2738
+ if (meta.viewerLinks) {
2739
+ toolState.viewerLinks = meta.viewerLinks;
2740
+ log8.debug({ toolId: meta.id, viewerLinks: meta.viewerLinks }, "Accumulated viewerLinks");
2741
+ }
2742
+ const viewerFilePath = content.metadata?.viewerFilePath;
2679
2743
  if (viewerFilePath) toolState.viewerFilePath = viewerFilePath;
2744
+ if (meta.name) toolState.name = meta.name;
2745
+ if (meta.kind) toolState.kind = meta.kind;
2746
+ const isTerminal = meta.status === "completed" || meta.status === "failed";
2747
+ if (!isTerminal && !meta.viewerLinks) break;
2748
+ await toolState.ready;
2749
+ log8.debug(
2750
+ { toolId: meta.id, status: meta.status, hasViewerLinks: !!toolState.viewerLinks, viewerLinks: toolState.viewerLinks, name: toolState.name, msgId: toolState.msgId },
2751
+ "Tool completed, preparing edit"
2752
+ );
2680
2753
  const merged = {
2681
2754
  ...meta,
2682
- name: meta.name || toolState.name,
2683
- kind: meta.kind || toolState.kind,
2684
- viewerLinks,
2685
- viewerFilePath
2755
+ name: toolState.name,
2756
+ kind: toolState.kind,
2757
+ viewerLinks: toolState.viewerLinks,
2758
+ viewerFilePath: toolState.viewerFilePath
2686
2759
  };
2760
+ const formattedText = formatToolUpdate(merged);
2687
2761
  try {
2688
2762
  await this.sendQueue.enqueue(
2689
2763
  () => this.bot.api.editMessageText(
2690
2764
  this.telegramConfig.chatId,
2691
2765
  toolState.msgId,
2692
- formatToolUpdate(merged),
2766
+ formattedText,
2693
2767
  { parse_mode: "HTML" }
2694
2768
  )
2695
2769
  );
2696
- } catch {
2770
+ } catch (err) {
2771
+ log8.warn(
2772
+ { err, msgId: toolState.msgId, textLen: formattedText.length, hasViewerLinks: !!merged.viewerLinks },
2773
+ "Tool update edit failed"
2774
+ );
2697
2775
  }
2698
2776
  }
2699
2777
  break;
@@ -2789,7 +2867,7 @@ Workspace: <code>${workspace}</code>
2789
2867
  permission: "\u{1F510}",
2790
2868
  input_required: "\u{1F4AC}"
2791
2869
  };
2792
- let text = `${emoji[notification.type] || "\u2139\uFE0F"} <b>${escapeHtml(notification.sessionName || notification.sessionId)}</b>
2870
+ let text = `${emoji[notification.type] || "\u2139\uFE0F"} <b>${escapeHtml(notification.sessionName || "New session")}</b>
2793
2871
  `;
2794
2872
  text += escapeHtml(notification.summary);
2795
2873
  if (notification.deepLink) {
@@ -2822,6 +2900,10 @@ Workspace: <code>${workspace}</code>
2822
2900
  Number(session.threadId),
2823
2901
  newName
2824
2902
  );
2903
+ await this.core.sessionManager.updateSessionName(
2904
+ sessionId,
2905
+ newName
2906
+ );
2825
2907
  }
2826
2908
  async sendSkillCommands(sessionId, commands) {
2827
2909
  const session = this.core.sessionManager.getSession(
@@ -2830,6 +2912,13 @@ Workspace: <code>${workspace}</code>
2830
2912
  if (!session) return;
2831
2913
  const threadId = Number(session.threadId);
2832
2914
  if (!threadId) return;
2915
+ if (!this.skillMessages.has(sessionId)) {
2916
+ const record = this.core.sessionManager.getSessionRecord(sessionId);
2917
+ const platform = record?.platform;
2918
+ if (platform?.skillMsgId) {
2919
+ this.skillMessages.set(sessionId, platform.skillMsgId);
2920
+ }
2921
+ }
2833
2922
  if (commands.length === 0) {
2834
2923
  await this.cleanupSkillCommands(sessionId);
2835
2924
  return;
@@ -2864,6 +2953,13 @@ Workspace: <code>${workspace}</code>
2864
2953
  )
2865
2954
  );
2866
2955
  this.skillMessages.set(sessionId, msg.message_id);
2956
+ const record = this.core.sessionManager.getSessionRecord(sessionId);
2957
+ if (record) {
2958
+ await this.core.sessionManager.updateSessionPlatform(
2959
+ sessionId,
2960
+ { ...record.platform, skillMsgId: msg.message_id }
2961
+ );
2962
+ }
2867
2963
  await this.bot.api.pinChatMessage(
2868
2964
  this.telegramConfig.chatId,
2869
2965
  msg.message_id,
@@ -2891,6 +2987,11 @@ Workspace: <code>${workspace}</code>
2891
2987
  }
2892
2988
  this.skillMessages.delete(sessionId);
2893
2989
  clearSkillCallbacks(sessionId);
2990
+ const record = this.core.sessionManager.getSessionRecord(sessionId);
2991
+ if (record) {
2992
+ const { skillMsgId: _removed, ...rest } = record.platform;
2993
+ await this.core.sessionManager.updateSessionPlatform(sessionId, rest);
2994
+ }
2894
2995
  }
2895
2996
  async updateCommandAutocomplete(agentName, skillCommands) {
2896
2997
  const prefix = `[${agentName}] `;
@@ -2957,4 +3058,4 @@ export {
2957
3058
  ApiServer,
2958
3059
  TelegramAdapter
2959
3060
  };
2960
- //# sourceMappingURL=chunk-6HORD4FS.js.map
3061
+ //# sourceMappingURL=chunk-WKHCVK5P.js.map