@openacp/cli 0.6.5 → 0.6.6
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.
- package/dist/{adapter-YSEIZJBA.js → adapter-RKK7A5GI.js} +2 -2
- package/dist/{chunk-FW6HM4VU.js → chunk-AHPRT3RY.js} +349 -62
- package/dist/chunk-AHPRT3RY.js.map +1 -0
- package/dist/{chunk-FEWSQT3U.js → chunk-ZMVVW3BK.js} +888 -66
- package/dist/chunk-ZMVVW3BK.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +80 -1
- package/dist/index.js +6 -2
- package/dist/{main-TSZR4HPP.js → main-B5L3DD3Y.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-FEWSQT3U.js.map +0 -1
- package/dist/chunk-FW6HM4VU.js.map +0 -1
- /package/dist/{adapter-YSEIZJBA.js.map → adapter-RKK7A5GI.js.map} +0 -0
- /package/dist/{main-TSZR4HPP.js.map → main-B5L3DD3Y.js.map} +0 -0
|
@@ -12,6 +12,10 @@ import {
|
|
|
12
12
|
handleHelp,
|
|
13
13
|
handleMenu
|
|
14
14
|
} from "./chunk-7QJS2XBD.js";
|
|
15
|
+
import {
|
|
16
|
+
CheckpointReader,
|
|
17
|
+
DEFAULT_MAX_TOKENS
|
|
18
|
+
} from "./chunk-ZMVVW3BK.js";
|
|
15
19
|
import {
|
|
16
20
|
ChannelAdapter
|
|
17
21
|
} from "./chunk-4GQ3I65A.js";
|
|
@@ -1622,13 +1626,290 @@ ${resultText}`,
|
|
|
1622
1626
|
});
|
|
1623
1627
|
}
|
|
1624
1628
|
|
|
1625
|
-
// src/adapters/telegram/commands/
|
|
1629
|
+
// src/adapters/telegram/commands/resume.ts
|
|
1630
|
+
import * as fs from "fs";
|
|
1631
|
+
import * as path from "path";
|
|
1632
|
+
import * as os from "os";
|
|
1626
1633
|
import { InlineKeyboard as InlineKeyboard6 } from "grammy";
|
|
1627
|
-
var log4 = createChildLogger({ module: "telegram-
|
|
1634
|
+
var log4 = createChildLogger({ module: "telegram-cmd-resume" });
|
|
1635
|
+
var PENDING_TIMEOUT_MS2 = 5 * 60 * 1e3;
|
|
1636
|
+
function botFromCtx2(ctx) {
|
|
1637
|
+
return { api: ctx.api };
|
|
1638
|
+
}
|
|
1639
|
+
var pendingResumes = /* @__PURE__ */ new Map();
|
|
1640
|
+
function cleanupPending2(userId) {
|
|
1641
|
+
const pending = pendingResumes.get(userId);
|
|
1642
|
+
if (pending) {
|
|
1643
|
+
clearTimeout(pending.timer);
|
|
1644
|
+
pendingResumes.delete(userId);
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
function parseResumeArgs(matchStr) {
|
|
1648
|
+
const args = matchStr.split(" ").filter(Boolean);
|
|
1649
|
+
if (args.length === 0) return { query: { type: "latest", value: "5" } };
|
|
1650
|
+
const first = args[0];
|
|
1651
|
+
if (first === "pr") return args[1] ? { query: { type: "pr", value: args[1] } } : null;
|
|
1652
|
+
if (first === "branch") return args[1] ? { query: { type: "branch", value: args[1] } } : null;
|
|
1653
|
+
if (first === "commit") return args[1] ? { query: { type: "commit", value: args[1] } } : null;
|
|
1654
|
+
if (CheckpointReader.isCheckpointId(first)) return { query: { type: "checkpoint", value: first } };
|
|
1655
|
+
if (CheckpointReader.isSessionId(first)) return { query: { type: "session", value: first } };
|
|
1656
|
+
if (first.includes("/pull/")) {
|
|
1657
|
+
const prMatch = first.match(/\/pull\/(\d+)/);
|
|
1658
|
+
return prMatch ? { query: { type: "pr", value: prMatch[1] } } : null;
|
|
1659
|
+
}
|
|
1660
|
+
const ghCommitMatch = first.match(/github\.com\/[^/]+\/[^/]+\/commit\/([0-9a-f]+)/);
|
|
1661
|
+
if (ghCommitMatch) return { query: { type: "commit", value: ghCommitMatch[1] } };
|
|
1662
|
+
const ghBranchMatch = first.match(/github\.com\/[^/]+\/[^/]+\/tree\/(.+?)(?:\?|#|$)/);
|
|
1663
|
+
if (ghBranchMatch) return { query: { type: "branch", value: ghBranchMatch[1] } };
|
|
1664
|
+
const ghCompareMatch = first.match(/github\.com\/[^/]+\/[^/]+\/compare\/(?:[^.]+\.{2,3})(.+?)(?:\?|#|$)/);
|
|
1665
|
+
if (ghCompareMatch) return { query: { type: "branch", value: ghCompareMatch[1] } };
|
|
1666
|
+
if (first.match(/github\.com\/[^/]+\/[^/]+\/?$/) && !first.includes("/tree/") && !first.includes("/pull/") && !first.includes("/commit/") && !first.includes("/compare/")) {
|
|
1667
|
+
return { query: { type: "latest", value: "5" } };
|
|
1668
|
+
}
|
|
1669
|
+
const entireCheckpointMatch = first.match(/entire\.io\/gh\/[^/]+\/[^/]+\/checkpoints\/[^/]+\/([0-9a-f]{12})/);
|
|
1670
|
+
if (entireCheckpointMatch) return { query: { type: "checkpoint", value: entireCheckpointMatch[1] } };
|
|
1671
|
+
const entireCommitMatch = first.match(/entire\.io\/gh\/[^/]+\/[^/]+\/commit\/([0-9a-f]+)/);
|
|
1672
|
+
if (entireCommitMatch) return { query: { type: "commit", value: entireCommitMatch[1] } };
|
|
1673
|
+
return { query: { type: "latest", value: "5" } };
|
|
1674
|
+
}
|
|
1675
|
+
function looksLikePath(text) {
|
|
1676
|
+
return text.startsWith("/") || text.startsWith("~") || text.startsWith(".");
|
|
1677
|
+
}
|
|
1678
|
+
function listWorkspaceDirs(baseDir, maxItems = 10) {
|
|
1679
|
+
const resolved = baseDir.replace(/^~/, os.homedir());
|
|
1680
|
+
try {
|
|
1681
|
+
if (!fs.existsSync(resolved)) return [];
|
|
1682
|
+
return fs.readdirSync(resolved, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".")).map((d) => d.name).sort().slice(0, maxItems);
|
|
1683
|
+
} catch {
|
|
1684
|
+
return [];
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
async function showWorkspacePicker(ctx, core, chatId, userId, query) {
|
|
1688
|
+
const config = core.configManager.get();
|
|
1689
|
+
const baseDir = config.workspace.baseDir;
|
|
1690
|
+
const resolvedBase = baseDir.replace(/^~/, os.homedir());
|
|
1691
|
+
const subdirs = listWorkspaceDirs(baseDir);
|
|
1692
|
+
const keyboard = new InlineKeyboard6();
|
|
1693
|
+
for (const dir of subdirs) {
|
|
1694
|
+
const fullPath = path.join(resolvedBase, dir);
|
|
1695
|
+
keyboard.text(`\u{1F4C1} ${dir}`, `m:resume:ws:${dir}`).row();
|
|
1696
|
+
}
|
|
1697
|
+
keyboard.text(`\u{1F4C1} Use ${baseDir}`, "m:resume:ws:default").row();
|
|
1698
|
+
keyboard.text("\u270F\uFE0F Enter project path", "m:resume:ws:custom");
|
|
1699
|
+
const queryLabel = query.type === "latest" ? "latest sessions" : `${query.type}: ${query.value}`;
|
|
1700
|
+
const text = `\u{1F4C1} <b>Select project directory for resume</b>
|
|
1701
|
+
|
|
1702
|
+
Query: <code>${escapeHtml(queryLabel)}</code>
|
|
1703
|
+
|
|
1704
|
+
Choose the repo that has Entire checkpoints enabled:`;
|
|
1705
|
+
const msg = await ctx.reply(text, { parse_mode: "HTML", reply_markup: keyboard });
|
|
1706
|
+
cleanupPending2(userId);
|
|
1707
|
+
pendingResumes.set(userId, {
|
|
1708
|
+
query,
|
|
1709
|
+
step: "workspace",
|
|
1710
|
+
messageId: msg.message_id,
|
|
1711
|
+
threadId: ctx.message?.message_thread_id,
|
|
1712
|
+
timer: setTimeout(() => pendingResumes.delete(userId), PENDING_TIMEOUT_MS2)
|
|
1713
|
+
});
|
|
1714
|
+
}
|
|
1715
|
+
async function executeResume(ctx, core, chatId, query, repoPath) {
|
|
1716
|
+
const provider = await core.contextManager.getProvider(repoPath);
|
|
1717
|
+
if (!provider) {
|
|
1718
|
+
await ctx.reply(
|
|
1719
|
+
`\u26A0\uFE0F <b>Entire not enabled in <code>${escapeHtml(repoPath)}</code></b>
|
|
1720
|
+
|
|
1721
|
+
To enable conversation history tracking:
|
|
1722
|
+
<code>cd ${escapeHtml(repoPath)} && npx entire enable</code>
|
|
1723
|
+
|
|
1724
|
+
Learn more: https://docs.entire.io/getting-started`,
|
|
1725
|
+
{ parse_mode: "HTML" }
|
|
1726
|
+
);
|
|
1727
|
+
return;
|
|
1728
|
+
}
|
|
1729
|
+
const fullQuery = { ...query, repoPath };
|
|
1730
|
+
await ctx.reply(`\u{1F50D} Scanning ${query.type === "latest" ? "latest sessions" : `${query.type}: ${escapeHtml(query.value)}`}...`, { parse_mode: "HTML" });
|
|
1731
|
+
const listResult = await core.contextManager.listSessions(fullQuery);
|
|
1732
|
+
if (!listResult || listResult.sessions.length === 0) {
|
|
1733
|
+
await ctx.reply(
|
|
1734
|
+
`\u{1F50D} <b>No sessions found</b>
|
|
1735
|
+
|
|
1736
|
+
Query: <code>${escapeHtml(query.type)}: ${escapeHtml(query.value)}</code>
|
|
1737
|
+
Repo: <code>${escapeHtml(repoPath)}</code>`,
|
|
1738
|
+
{ parse_mode: "HTML" }
|
|
1739
|
+
);
|
|
1740
|
+
return;
|
|
1741
|
+
}
|
|
1742
|
+
const config = core.configManager.get();
|
|
1743
|
+
const agentName = config.defaultAgent;
|
|
1744
|
+
let threadId;
|
|
1745
|
+
try {
|
|
1746
|
+
const queryLabel = query.type === "latest" ? "latest" : `${query.type}: ${query.value.slice(0, 20)}`;
|
|
1747
|
+
const topicName = `\u{1F4DC} Resume \u2014 ${queryLabel}`;
|
|
1748
|
+
threadId = await createSessionTopic(botFromCtx2(ctx), chatId, topicName);
|
|
1749
|
+
await ctx.api.sendMessage(chatId, `\u23F3 Loading context and starting session...`, {
|
|
1750
|
+
message_thread_id: threadId,
|
|
1751
|
+
parse_mode: "HTML"
|
|
1752
|
+
});
|
|
1753
|
+
const { session, contextResult } = await core.createSessionWithContext({
|
|
1754
|
+
channelId: "telegram",
|
|
1755
|
+
agentName,
|
|
1756
|
+
workingDirectory: repoPath,
|
|
1757
|
+
contextQuery: fullQuery,
|
|
1758
|
+
contextOptions: { maxTokens: DEFAULT_MAX_TOKENS }
|
|
1759
|
+
});
|
|
1760
|
+
session.threadId = String(threadId);
|
|
1761
|
+
await core.sessionManager.patchRecord(session.id, { platform: { topicId: threadId } });
|
|
1762
|
+
const sessionCount = contextResult?.sessionCount ?? listResult.sessions.length;
|
|
1763
|
+
const mode = contextResult?.mode ?? "full";
|
|
1764
|
+
const tokens = contextResult?.tokenEstimate ?? listResult.estimatedTokens;
|
|
1765
|
+
const topicLink = buildDeepLink(chatId, threadId);
|
|
1766
|
+
const replyTarget = ctx.message?.message_thread_id;
|
|
1767
|
+
if (replyTarget !== threadId) {
|
|
1768
|
+
await ctx.reply(
|
|
1769
|
+
`\u2705 Session resumed \u2192 <a href="${topicLink}">Open topic</a>`,
|
|
1770
|
+
{ parse_mode: "HTML" }
|
|
1771
|
+
);
|
|
1772
|
+
}
|
|
1773
|
+
await ctx.api.sendMessage(
|
|
1774
|
+
chatId,
|
|
1775
|
+
`\u2705 <b>Session resumed with context</b>
|
|
1776
|
+
<b>Agent:</b> ${escapeHtml(session.agentName)}
|
|
1777
|
+
<b>Workspace:</b> <code>${escapeHtml(session.workingDirectory)}</code>
|
|
1778
|
+
<b>Sessions loaded:</b> ${sessionCount}
|
|
1779
|
+
<b>Mode:</b> ${escapeHtml(mode)}
|
|
1780
|
+
<b>~Tokens:</b> ${tokens.toLocaleString()}
|
|
1781
|
+
|
|
1782
|
+
Context is ready \u2014 chat here to continue working with the agent.`,
|
|
1783
|
+
{
|
|
1784
|
+
message_thread_id: threadId,
|
|
1785
|
+
parse_mode: "HTML",
|
|
1786
|
+
reply_markup: buildSessionControlKeyboard(session.id, false, false)
|
|
1787
|
+
}
|
|
1788
|
+
);
|
|
1789
|
+
session.warmup().catch((err) => log4.error({ err }, "Warm-up error"));
|
|
1790
|
+
} catch (err) {
|
|
1791
|
+
log4.error({ err }, "Resume session creation failed");
|
|
1792
|
+
if (threadId) {
|
|
1793
|
+
try {
|
|
1794
|
+
await ctx.api.deleteForumTopic(chatId, threadId);
|
|
1795
|
+
} catch {
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
const message = err instanceof Error ? err.message : typeof err === "object" ? JSON.stringify(err) : String(err);
|
|
1799
|
+
await ctx.reply(`\u274C ${escapeHtml(message)}`, { parse_mode: "HTML" });
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
async function handleResume(ctx, core, chatId, assistant) {
|
|
1803
|
+
const rawMatch = ctx.match;
|
|
1804
|
+
const matchStr = typeof rawMatch === "string" ? rawMatch : "";
|
|
1805
|
+
const parsed = parseResumeArgs(matchStr);
|
|
1806
|
+
if (!parsed) {
|
|
1807
|
+
await ctx.reply(
|
|
1808
|
+
`\u274C <b>Invalid arguments.</b>
|
|
1809
|
+
|
|
1810
|
+
Usage examples:
|
|
1811
|
+
\u2022 <code>/resume</code> \u2014 latest 5 sessions
|
|
1812
|
+
\u2022 <code>/resume pr 19</code>
|
|
1813
|
+
\u2022 <code>/resume branch main</code>
|
|
1814
|
+
\u2022 <code>/resume commit e0dd2fa4</code>
|
|
1815
|
+
\u2022 <code>/resume f634acf05138</code> \u2014 checkpoint ID
|
|
1816
|
+
\u2022 <code>/resume https://entire.io/gh/.../checkpoints/.../2e884e2c402a</code>
|
|
1817
|
+
\u2022 <code>/resume https://entire.io/gh/.../commit/e0dd2fa4...</code>`,
|
|
1818
|
+
{ parse_mode: "HTML" }
|
|
1819
|
+
);
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1822
|
+
const { query } = parsed;
|
|
1823
|
+
const userId = ctx.from?.id;
|
|
1824
|
+
if (!userId) return;
|
|
1825
|
+
await showWorkspacePicker(ctx, core, chatId, userId, query);
|
|
1826
|
+
}
|
|
1827
|
+
async function handlePendingResumeInput(ctx, core, chatId, assistantTopicId) {
|
|
1828
|
+
const userId = ctx.from?.id;
|
|
1829
|
+
if (!userId) return false;
|
|
1830
|
+
const pending = pendingResumes.get(userId);
|
|
1831
|
+
if (!pending || !ctx.message?.text) return false;
|
|
1832
|
+
if (pending.step !== "workspace_input" && pending.step !== "workspace") return false;
|
|
1833
|
+
const threadId = ctx.message.message_thread_id;
|
|
1834
|
+
if (threadId && threadId !== assistantTopicId) return false;
|
|
1835
|
+
if (pending.step === "workspace" && !looksLikePath(ctx.message.text.trim())) return false;
|
|
1836
|
+
let workspace = ctx.message.text.trim();
|
|
1837
|
+
if (!workspace) {
|
|
1838
|
+
await ctx.reply("\u26A0\uFE0F Please enter a valid directory path.", { parse_mode: "HTML" });
|
|
1839
|
+
return true;
|
|
1840
|
+
}
|
|
1841
|
+
if (!workspace.startsWith("/") && !workspace.startsWith("~")) {
|
|
1842
|
+
const baseDir = core.configManager.get().workspace.baseDir;
|
|
1843
|
+
workspace = `${baseDir.replace(/\/$/, "")}/${workspace}`;
|
|
1844
|
+
}
|
|
1845
|
+
const resolved = core.configManager.resolveWorkspace(workspace);
|
|
1846
|
+
cleanupPending2(userId);
|
|
1847
|
+
await executeResume(ctx, core, chatId, pending.query, resolved);
|
|
1848
|
+
return true;
|
|
1849
|
+
}
|
|
1850
|
+
function setupResumeCallbacks(bot, core, chatId) {
|
|
1851
|
+
bot.callbackQuery(/^m:resume:/, async (ctx) => {
|
|
1852
|
+
const data = ctx.callbackQuery.data;
|
|
1853
|
+
const userId = ctx.from?.id;
|
|
1854
|
+
if (!userId) return;
|
|
1855
|
+
try {
|
|
1856
|
+
await ctx.answerCallbackQuery();
|
|
1857
|
+
} catch {
|
|
1858
|
+
}
|
|
1859
|
+
const pending = pendingResumes.get(userId);
|
|
1860
|
+
if (!pending) return;
|
|
1861
|
+
if (data === "m:resume:ws:default") {
|
|
1862
|
+
const baseDir = core.configManager.get().workspace.baseDir;
|
|
1863
|
+
const resolved = core.configManager.resolveWorkspace(baseDir);
|
|
1864
|
+
cleanupPending2(userId);
|
|
1865
|
+
try {
|
|
1866
|
+
await ctx.api.editMessageText(chatId, pending.messageId, `\u23F3 Using <code>${escapeHtml(resolved)}</code>...`, { parse_mode: "HTML" });
|
|
1867
|
+
} catch {
|
|
1868
|
+
}
|
|
1869
|
+
await executeResume(ctx, core, chatId, pending.query, resolved);
|
|
1870
|
+
return;
|
|
1871
|
+
}
|
|
1872
|
+
if (data === "m:resume:ws:custom") {
|
|
1873
|
+
try {
|
|
1874
|
+
await ctx.api.editMessageText(
|
|
1875
|
+
chatId,
|
|
1876
|
+
pending.messageId,
|
|
1877
|
+
`\u270F\uFE0F <b>Enter project path:</b>
|
|
1878
|
+
|
|
1879
|
+
Full path like <code>~/code/my-project</code>
|
|
1880
|
+
Or just the folder name (will use workspace baseDir)`,
|
|
1881
|
+
{ parse_mode: "HTML" }
|
|
1882
|
+
);
|
|
1883
|
+
} catch {
|
|
1884
|
+
await ctx.reply(`\u270F\uFE0F <b>Enter project path:</b>`, { parse_mode: "HTML" });
|
|
1885
|
+
}
|
|
1886
|
+
clearTimeout(pending.timer);
|
|
1887
|
+
pending.step = "workspace_input";
|
|
1888
|
+
pending.timer = setTimeout(() => pendingResumes.delete(userId), PENDING_TIMEOUT_MS2);
|
|
1889
|
+
return;
|
|
1890
|
+
}
|
|
1891
|
+
if (data.startsWith("m:resume:ws:")) {
|
|
1892
|
+
const dirName = data.replace("m:resume:ws:", "");
|
|
1893
|
+
const baseDir = core.configManager.get().workspace.baseDir;
|
|
1894
|
+
const resolved = core.configManager.resolveWorkspace(path.join(baseDir.replace(/^~/, os.homedir()), dirName));
|
|
1895
|
+
cleanupPending2(userId);
|
|
1896
|
+
try {
|
|
1897
|
+
await ctx.api.editMessageText(chatId, pending.messageId, `\u23F3 Using <code>${escapeHtml(resolved)}</code>...`, { parse_mode: "HTML" });
|
|
1898
|
+
} catch {
|
|
1899
|
+
}
|
|
1900
|
+
await executeResume(ctx, core, chatId, pending.query, resolved);
|
|
1901
|
+
return;
|
|
1902
|
+
}
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
// src/adapters/telegram/commands/settings.ts
|
|
1907
|
+
import { InlineKeyboard as InlineKeyboard7 } from "grammy";
|
|
1908
|
+
var log5 = createChildLogger({ module: "telegram-settings" });
|
|
1628
1909
|
function buildSettingsKeyboard(core) {
|
|
1629
1910
|
const config = core.configManager.get();
|
|
1630
1911
|
const fields = getSafeFields();
|
|
1631
|
-
const kb = new
|
|
1912
|
+
const kb = new InlineKeyboard7();
|
|
1632
1913
|
for (const field of fields) {
|
|
1633
1914
|
const value = getConfigValue(config, field.path);
|
|
1634
1915
|
const label = formatFieldLabel(field, value);
|
|
@@ -1687,7 +1968,7 @@ function setupSettingsCallbacks(bot, core, getAssistantSession) {
|
|
|
1687
1968
|
} catch {
|
|
1688
1969
|
}
|
|
1689
1970
|
} catch (err) {
|
|
1690
|
-
|
|
1971
|
+
log5.error({ err, fieldPath }, "Failed to toggle config");
|
|
1691
1972
|
try {
|
|
1692
1973
|
await ctx.answerCallbackQuery({ text: "\u274C Failed to update" });
|
|
1693
1974
|
} catch {
|
|
@@ -1701,7 +1982,7 @@ function setupSettingsCallbacks(bot, core, getAssistantSession) {
|
|
|
1701
1982
|
if (!fieldDef) return;
|
|
1702
1983
|
const options = resolveOptions(fieldDef, config) ?? [];
|
|
1703
1984
|
const currentValue = getConfigValue(config, fieldPath);
|
|
1704
|
-
const kb = new
|
|
1985
|
+
const kb = new InlineKeyboard7();
|
|
1705
1986
|
for (const opt of options) {
|
|
1706
1987
|
const marker = opt === String(currentValue) ? " \u2713" : "";
|
|
1707
1988
|
kb.text(`${opt}${marker}`, `s:pick:${fieldPath}:${opt}`).row();
|
|
@@ -1761,7 +2042,7 @@ Tap to change:`, {
|
|
|
1761
2042
|
} catch {
|
|
1762
2043
|
}
|
|
1763
2044
|
} catch (err) {
|
|
1764
|
-
|
|
2045
|
+
log5.error({ err, fieldPath }, "Failed to set config");
|
|
1765
2046
|
try {
|
|
1766
2047
|
await ctx.answerCallbackQuery({ text: "\u274C Failed to update" });
|
|
1767
2048
|
} catch {
|
|
@@ -1832,8 +2113,8 @@ function buildNestedUpdate(dotPath, value) {
|
|
|
1832
2113
|
}
|
|
1833
2114
|
|
|
1834
2115
|
// src/adapters/telegram/commands/doctor.ts
|
|
1835
|
-
import { InlineKeyboard as
|
|
1836
|
-
var
|
|
2116
|
+
import { InlineKeyboard as InlineKeyboard8 } from "grammy";
|
|
2117
|
+
var log6 = createChildLogger({ module: "telegram-cmd-doctor" });
|
|
1837
2118
|
var pendingFixesStore = /* @__PURE__ */ new Map();
|
|
1838
2119
|
function renderReport(report) {
|
|
1839
2120
|
const icons = { pass: "\u2705", warn: "\u26A0\uFE0F", fail: "\u274C" };
|
|
@@ -1850,7 +2131,7 @@ function renderReport(report) {
|
|
|
1850
2131
|
lines.push(`<b>Result:</b> ${passed} passed, ${warnings} warnings, ${failed} failed${fixedStr}`);
|
|
1851
2132
|
let keyboard;
|
|
1852
2133
|
if (report.pendingFixes.length > 0) {
|
|
1853
|
-
keyboard = new
|
|
2134
|
+
keyboard = new InlineKeyboard8();
|
|
1854
2135
|
for (let i = 0; i < report.pendingFixes.length; i++) {
|
|
1855
2136
|
const label = `\u{1F527} Fix: ${report.pendingFixes[i].message.slice(0, 30)}`;
|
|
1856
2137
|
keyboard.text(label, `m:doctor:fix:${i}`).row();
|
|
@@ -1876,7 +2157,7 @@ async function handleDoctor(ctx) {
|
|
|
1876
2157
|
reply_markup: keyboard
|
|
1877
2158
|
});
|
|
1878
2159
|
} catch (err) {
|
|
1879
|
-
|
|
2160
|
+
log6.error({ err }, "Doctor command failed");
|
|
1880
2161
|
await ctx.api.editMessageText(
|
|
1881
2162
|
ctx.chat.id,
|
|
1882
2163
|
statusMsg.message_id,
|
|
@@ -1925,7 +2206,7 @@ function setupDoctorCallbacks(bot) {
|
|
|
1925
2206
|
}
|
|
1926
2207
|
}
|
|
1927
2208
|
} catch (err) {
|
|
1928
|
-
|
|
2209
|
+
log6.error({ err, index }, "Doctor fix callback failed");
|
|
1929
2210
|
}
|
|
1930
2211
|
});
|
|
1931
2212
|
bot.callbackQuery("m:doctor", async (ctx) => {
|
|
@@ -1938,8 +2219,8 @@ function setupDoctorCallbacks(bot) {
|
|
|
1938
2219
|
}
|
|
1939
2220
|
|
|
1940
2221
|
// src/adapters/telegram/commands/tunnel.ts
|
|
1941
|
-
import { InlineKeyboard as
|
|
1942
|
-
var
|
|
2222
|
+
import { InlineKeyboard as InlineKeyboard9 } from "grammy";
|
|
2223
|
+
var log7 = createChildLogger({ module: "telegram-cmd-tunnel" });
|
|
1943
2224
|
async function handleTunnel(ctx, core) {
|
|
1944
2225
|
if (!core.tunnelService) {
|
|
1945
2226
|
await ctx.reply("\u274C Tunnel service is not enabled.", { parse_mode: "HTML" });
|
|
@@ -2026,7 +2307,7 @@ async function handleTunnels(ctx, core) {
|
|
|
2026
2307
|
\u2192 <a href="${escapeHtml(e.publicUrl)}">${escapeHtml(e.publicUrl)}</a>` : "";
|
|
2027
2308
|
return `${status} Port <b>${e.port}</b>${label}${url}`;
|
|
2028
2309
|
});
|
|
2029
|
-
const keyboard = new
|
|
2310
|
+
const keyboard = new InlineKeyboard9();
|
|
2030
2311
|
for (const e of entries) {
|
|
2031
2312
|
keyboard.text(`\u{1F50C} Stop ${e.port}${e.label ? ` (${e.label})` : ""}`, `tn:stop:${e.port}`).row();
|
|
2032
2313
|
}
|
|
@@ -2066,7 +2347,7 @@ function setupTunnelCallbacks(bot, core) {
|
|
|
2066
2347
|
if (remaining.length === 0) {
|
|
2067
2348
|
await ctx.editMessageText("\u{1F50C} All tunnels stopped.", { parse_mode: "HTML" });
|
|
2068
2349
|
} else {
|
|
2069
|
-
const kb = new
|
|
2350
|
+
const kb = new InlineKeyboard9();
|
|
2070
2351
|
for (const e of remaining) {
|
|
2071
2352
|
kb.text(`\u{1F50C} Stop ${e.port}${e.label ? ` (${e.label})` : ""}`, `tn:stop:${e.port}`).row();
|
|
2072
2353
|
}
|
|
@@ -2116,9 +2397,11 @@ function setupCommands(bot, core, chatId, assistant) {
|
|
|
2116
2397
|
bot.command("tunnels", (ctx) => handleTunnels(ctx, core));
|
|
2117
2398
|
bot.command("archive", (ctx) => handleArchive(ctx, core));
|
|
2118
2399
|
bot.command("text_to_speech", (ctx) => handleTTS(ctx, core));
|
|
2400
|
+
bot.command("resume", (ctx) => handleResume(ctx, core, chatId, assistant));
|
|
2119
2401
|
}
|
|
2120
2402
|
function setupAllCallbacks(bot, core, chatId, systemTopicIds, getAssistantSession) {
|
|
2121
2403
|
setupNewSessionCallbacks(bot, core, chatId);
|
|
2404
|
+
setupResumeCallbacks(bot, core, chatId);
|
|
2122
2405
|
setupSessionCallbacks(bot, core, chatId, systemTopicIds);
|
|
2123
2406
|
setupSettingsCallbacks(bot, core, getAssistantSession ?? (() => void 0));
|
|
2124
2407
|
setupDoctorCallbacks(bot);
|
|
@@ -2189,13 +2472,14 @@ var STATIC_COMMANDS = [
|
|
|
2189
2472
|
{ command: "tunnel", description: "Create/stop tunnel for a local port" },
|
|
2190
2473
|
{ command: "tunnels", description: "List active tunnels" },
|
|
2191
2474
|
{ command: "archive", description: "Archive session topic (recreate with clean history)" },
|
|
2192
|
-
{ command: "text_to_speech", description: "Toggle Text to Speech (/text_to_speech on, /text_to_speech off)" }
|
|
2475
|
+
{ command: "text_to_speech", description: "Toggle Text to Speech (/text_to_speech on, /text_to_speech off)" },
|
|
2476
|
+
{ command: "resume", description: "Resume with conversation history from Entire checkpoints" }
|
|
2193
2477
|
];
|
|
2194
2478
|
|
|
2195
2479
|
// src/adapters/telegram/permissions.ts
|
|
2196
|
-
import { InlineKeyboard as
|
|
2480
|
+
import { InlineKeyboard as InlineKeyboard10 } from "grammy";
|
|
2197
2481
|
import { nanoid } from "nanoid";
|
|
2198
|
-
var
|
|
2482
|
+
var log8 = createChildLogger({ module: "telegram-permissions" });
|
|
2199
2483
|
var PermissionHandler = class {
|
|
2200
2484
|
constructor(bot, chatId, getSession, sendNotification) {
|
|
2201
2485
|
this.bot = bot;
|
|
@@ -2212,7 +2496,7 @@ var PermissionHandler = class {
|
|
|
2212
2496
|
requestId: request.id,
|
|
2213
2497
|
options: request.options.map((o) => ({ id: o.id, isAllow: o.isAllow }))
|
|
2214
2498
|
});
|
|
2215
|
-
const keyboard = new
|
|
2499
|
+
const keyboard = new InlineKeyboard10();
|
|
2216
2500
|
for (const option of request.options) {
|
|
2217
2501
|
const emoji = option.isAllow ? "\u2705" : "\u274C";
|
|
2218
2502
|
keyboard.text(`${emoji} ${option.label}`, `p:${callbackKey}:${option.id}`);
|
|
@@ -2255,7 +2539,7 @@ ${escapeHtml(request.description)}`,
|
|
|
2255
2539
|
}
|
|
2256
2540
|
const session = this.getSession(pending.sessionId);
|
|
2257
2541
|
const isAllow = pending.options.find((o) => o.id === optionId)?.isAllow ?? false;
|
|
2258
|
-
|
|
2542
|
+
log8.info({ requestId: pending.requestId, optionId, isAllow }, "Permission responded");
|
|
2259
2543
|
if (session?.permissionGate.requestId === pending.requestId) {
|
|
2260
2544
|
session.permissionGate.resolve(optionId);
|
|
2261
2545
|
}
|
|
@@ -2273,10 +2557,10 @@ ${escapeHtml(request.description)}`,
|
|
|
2273
2557
|
};
|
|
2274
2558
|
|
|
2275
2559
|
// src/adapters/telegram/assistant.ts
|
|
2276
|
-
var
|
|
2560
|
+
var log9 = createChildLogger({ module: "telegram-assistant" });
|
|
2277
2561
|
async function spawnAssistant(core, adapter, assistantTopicId) {
|
|
2278
2562
|
const config = core.configManager.get();
|
|
2279
|
-
|
|
2563
|
+
log9.info({ agent: config.defaultAgent }, "Creating assistant session...");
|
|
2280
2564
|
const session = await core.createSession({
|
|
2281
2565
|
channelId: "telegram",
|
|
2282
2566
|
agentName: config.defaultAgent,
|
|
@@ -2285,7 +2569,7 @@ async function spawnAssistant(core, adapter, assistantTopicId) {
|
|
|
2285
2569
|
// Prevent auto-naming from triggering after system prompt
|
|
2286
2570
|
});
|
|
2287
2571
|
session.threadId = String(assistantTopicId);
|
|
2288
|
-
|
|
2572
|
+
log9.info({ sessionId: session.id }, "Assistant agent spawned");
|
|
2289
2573
|
const allRecords = core.sessionManager.listRecords();
|
|
2290
2574
|
const activeCount = allRecords.filter((r) => r.status === "active" || r.status === "initializing").length;
|
|
2291
2575
|
const statusCounts = /* @__PURE__ */ new Map();
|
|
@@ -2306,9 +2590,9 @@ async function spawnAssistant(core, adapter, assistantTopicId) {
|
|
|
2306
2590
|
};
|
|
2307
2591
|
const systemPrompt = buildAssistantSystemPrompt(ctx);
|
|
2308
2592
|
const ready = session.enqueuePrompt(systemPrompt).then(() => {
|
|
2309
|
-
|
|
2593
|
+
log9.info({ sessionId: session.id }, "Assistant system prompt completed");
|
|
2310
2594
|
}).catch((err) => {
|
|
2311
|
-
|
|
2595
|
+
log9.warn({ err }, "Assistant system prompt failed");
|
|
2312
2596
|
});
|
|
2313
2597
|
return { session, ready };
|
|
2314
2598
|
}
|
|
@@ -2474,7 +2758,7 @@ function redirectToAssistant(chatId, assistantTopicId) {
|
|
|
2474
2758
|
}
|
|
2475
2759
|
|
|
2476
2760
|
// src/adapters/telegram/activity.ts
|
|
2477
|
-
var
|
|
2761
|
+
var log10 = createChildLogger({ module: "telegram:activity" });
|
|
2478
2762
|
var THINKING_REFRESH_MS = 15e3;
|
|
2479
2763
|
var THINKING_MAX_MS = 3 * 60 * 1e3;
|
|
2480
2764
|
var ThinkingIndicator = class {
|
|
@@ -2506,7 +2790,7 @@ var ThinkingIndicator = class {
|
|
|
2506
2790
|
this.startRefreshTimer();
|
|
2507
2791
|
}
|
|
2508
2792
|
} catch (err) {
|
|
2509
|
-
|
|
2793
|
+
log10.warn({ err }, "ThinkingIndicator.show() failed");
|
|
2510
2794
|
} finally {
|
|
2511
2795
|
this.sending = false;
|
|
2512
2796
|
}
|
|
@@ -2579,7 +2863,7 @@ var UsageMessage = class {
|
|
|
2579
2863
|
if (result) this.msgId = result.message_id;
|
|
2580
2864
|
}
|
|
2581
2865
|
} catch (err) {
|
|
2582
|
-
|
|
2866
|
+
log10.warn({ err }, "UsageMessage.send() failed");
|
|
2583
2867
|
}
|
|
2584
2868
|
}
|
|
2585
2869
|
getMsgId() {
|
|
@@ -2592,7 +2876,7 @@ var UsageMessage = class {
|
|
|
2592
2876
|
try {
|
|
2593
2877
|
await this.sendQueue.enqueue(() => this.api.deleteMessage(this.chatId, id));
|
|
2594
2878
|
} catch (err) {
|
|
2595
|
-
|
|
2879
|
+
log10.warn({ err }, "UsageMessage.delete() failed");
|
|
2596
2880
|
}
|
|
2597
2881
|
}
|
|
2598
2882
|
};
|
|
@@ -2678,7 +2962,7 @@ var PlanCard = class {
|
|
|
2678
2962
|
if (result) this.msgId = result.message_id;
|
|
2679
2963
|
}
|
|
2680
2964
|
} catch (err) {
|
|
2681
|
-
|
|
2965
|
+
log10.warn({ err }, "PlanCard flush failed");
|
|
2682
2966
|
}
|
|
2683
2967
|
}
|
|
2684
2968
|
};
|
|
@@ -2741,7 +3025,7 @@ var ActivityTracker = class {
|
|
|
2741
3025
|
})
|
|
2742
3026
|
);
|
|
2743
3027
|
} catch (err) {
|
|
2744
|
-
|
|
3028
|
+
log10.warn({ err }, "ActivityTracker.onComplete() Done send failed");
|
|
2745
3029
|
}
|
|
2746
3030
|
}
|
|
2747
3031
|
}
|
|
@@ -2824,7 +3108,7 @@ var TelegramSendQueue = class {
|
|
|
2824
3108
|
|
|
2825
3109
|
// src/adapters/telegram/action-detect.ts
|
|
2826
3110
|
import { nanoid as nanoid2 } from "nanoid";
|
|
2827
|
-
import { InlineKeyboard as
|
|
3111
|
+
import { InlineKeyboard as InlineKeyboard11 } from "grammy";
|
|
2828
3112
|
var CMD_NEW_RE = /\/new(?:\s+([^\s\u0080-\uFFFF]+)(?:\s+([^\s\u0080-\uFFFF]+))?)?/;
|
|
2829
3113
|
var CMD_CANCEL_RE = /\/cancel\b/;
|
|
2830
3114
|
var KW_NEW_RE = /(?:create|new)\s+session/i;
|
|
@@ -2871,7 +3155,7 @@ function removeAction(id) {
|
|
|
2871
3155
|
actionMap.delete(id);
|
|
2872
3156
|
}
|
|
2873
3157
|
function buildActionKeyboard(actionId, action) {
|
|
2874
|
-
const keyboard = new
|
|
3158
|
+
const keyboard = new InlineKeyboard11();
|
|
2875
3159
|
if (action.action === "new_session") {
|
|
2876
3160
|
keyboard.text("\u2705 Create session", `a:${actionId}`);
|
|
2877
3161
|
keyboard.text("\u274C Cancel", `a:dismiss:${actionId}`);
|
|
@@ -2980,7 +3264,7 @@ function setupActionCallbacks(bot, core, chatId, getAssistantSessionId) {
|
|
|
2980
3264
|
}
|
|
2981
3265
|
|
|
2982
3266
|
// src/adapters/telegram/tool-call-tracker.ts
|
|
2983
|
-
var
|
|
3267
|
+
var log11 = createChildLogger({ module: "tool-call-tracker" });
|
|
2984
3268
|
var ToolCallTracker = class {
|
|
2985
3269
|
constructor(bot, chatId, sendQueue) {
|
|
2986
3270
|
this.bot = bot;
|
|
@@ -3024,7 +3308,7 @@ var ToolCallTracker = class {
|
|
|
3024
3308
|
if (!toolState) return;
|
|
3025
3309
|
if (meta.viewerLinks) {
|
|
3026
3310
|
toolState.viewerLinks = meta.viewerLinks;
|
|
3027
|
-
|
|
3311
|
+
log11.debug({ toolId: meta.id, viewerLinks: meta.viewerLinks }, "Accumulated viewerLinks");
|
|
3028
3312
|
}
|
|
3029
3313
|
if (meta.viewerFilePath) toolState.viewerFilePath = meta.viewerFilePath;
|
|
3030
3314
|
if (meta.name) toolState.name = meta.name;
|
|
@@ -3032,7 +3316,7 @@ var ToolCallTracker = class {
|
|
|
3032
3316
|
const isTerminal = meta.status === "completed" || meta.status === "failed";
|
|
3033
3317
|
if (!isTerminal) return;
|
|
3034
3318
|
await toolState.ready;
|
|
3035
|
-
|
|
3319
|
+
log11.debug(
|
|
3036
3320
|
{
|
|
3037
3321
|
toolId: meta.id,
|
|
3038
3322
|
status: meta.status,
|
|
@@ -3061,7 +3345,7 @@ var ToolCallTracker = class {
|
|
|
3061
3345
|
)
|
|
3062
3346
|
);
|
|
3063
3347
|
} catch (err) {
|
|
3064
|
-
|
|
3348
|
+
log11.warn(
|
|
3065
3349
|
{
|
|
3066
3350
|
err,
|
|
3067
3351
|
msgId: toolState.msgId,
|
|
@@ -3332,7 +3616,7 @@ var DraftManager = class {
|
|
|
3332
3616
|
};
|
|
3333
3617
|
|
|
3334
3618
|
// src/adapters/telegram/skill-command-manager.ts
|
|
3335
|
-
var
|
|
3619
|
+
var log12 = createChildLogger({ module: "skill-commands" });
|
|
3336
3620
|
var SkillCommandManager = class {
|
|
3337
3621
|
// sessionId → pinned msgId
|
|
3338
3622
|
constructor(bot, chatId, sendQueue, sessionManager) {
|
|
@@ -3398,7 +3682,7 @@ var SkillCommandManager = class {
|
|
|
3398
3682
|
disable_notification: true
|
|
3399
3683
|
});
|
|
3400
3684
|
} catch (err) {
|
|
3401
|
-
|
|
3685
|
+
log12.error({ err, sessionId }, "Failed to send skill commands");
|
|
3402
3686
|
}
|
|
3403
3687
|
}
|
|
3404
3688
|
async cleanup(sessionId) {
|
|
@@ -3427,7 +3711,7 @@ var SkillCommandManager = class {
|
|
|
3427
3711
|
};
|
|
3428
3712
|
|
|
3429
3713
|
// src/adapters/telegram/adapter.ts
|
|
3430
|
-
var
|
|
3714
|
+
var log13 = createChildLogger({ module: "telegram" });
|
|
3431
3715
|
function patchedFetch(input, init) {
|
|
3432
3716
|
if (init?.signal && !(init.signal instanceof AbortSignal)) {
|
|
3433
3717
|
const nativeController = new AbortController();
|
|
@@ -3491,7 +3775,7 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
3491
3775
|
);
|
|
3492
3776
|
this.bot.catch((err) => {
|
|
3493
3777
|
const rootCause = err.error instanceof Error ? err.error : err;
|
|
3494
|
-
|
|
3778
|
+
log13.error({ err: rootCause }, "Telegram bot error");
|
|
3495
3779
|
});
|
|
3496
3780
|
this.bot.api.config.use(async (prev, method, payload, signal) => {
|
|
3497
3781
|
const maxRetries = 3;
|
|
@@ -3505,7 +3789,7 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
3505
3789
|
if (rateLimitedMethods.includes(method)) {
|
|
3506
3790
|
this.sendQueue.onRateLimited();
|
|
3507
3791
|
}
|
|
3508
|
-
|
|
3792
|
+
log13.warn(
|
|
3509
3793
|
{ method, retryAfter, attempt: attempt + 1 },
|
|
3510
3794
|
"Rate limited by Telegram, retrying"
|
|
3511
3795
|
);
|
|
@@ -3638,7 +3922,7 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
3638
3922
|
this.setupRoutes();
|
|
3639
3923
|
this.bot.start({
|
|
3640
3924
|
allowed_updates: ["message", "callback_query"],
|
|
3641
|
-
onStart: () =>
|
|
3925
|
+
onStart: () => log13.info(
|
|
3642
3926
|
{ chatId: this.telegramConfig.chatId },
|
|
3643
3927
|
"Telegram bot started"
|
|
3644
3928
|
)
|
|
@@ -3660,10 +3944,10 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
3660
3944
|
reply_markup: buildMenuKeyboard()
|
|
3661
3945
|
});
|
|
3662
3946
|
} catch (err) {
|
|
3663
|
-
|
|
3947
|
+
log13.warn({ err }, "Failed to send welcome message");
|
|
3664
3948
|
}
|
|
3665
3949
|
try {
|
|
3666
|
-
|
|
3950
|
+
log13.info("Spawning assistant session...");
|
|
3667
3951
|
const { session, ready } = await spawnAssistant(
|
|
3668
3952
|
this.core,
|
|
3669
3953
|
this,
|
|
@@ -3671,13 +3955,13 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
3671
3955
|
);
|
|
3672
3956
|
this.assistantSession = session;
|
|
3673
3957
|
this.assistantInitializing = true;
|
|
3674
|
-
|
|
3958
|
+
log13.info({ sessionId: session.id }, "Assistant session ready, system prompt running in background");
|
|
3675
3959
|
ready.then(() => {
|
|
3676
3960
|
this.assistantInitializing = false;
|
|
3677
|
-
|
|
3961
|
+
log13.info({ sessionId: session.id }, "Assistant ready for user messages");
|
|
3678
3962
|
});
|
|
3679
3963
|
} catch (err) {
|
|
3680
|
-
|
|
3964
|
+
log13.error({ err }, "Failed to spawn assistant");
|
|
3681
3965
|
this.bot.api.sendMessage(
|
|
3682
3966
|
this.telegramConfig.chatId,
|
|
3683
3967
|
`\u26A0\uFE0F <b>Failed to start assistant session.</b>
|
|
@@ -3693,7 +3977,7 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
3693
3977
|
await this.assistantSession.destroy();
|
|
3694
3978
|
}
|
|
3695
3979
|
await this.bot.stop();
|
|
3696
|
-
|
|
3980
|
+
log13.info("Telegram bot stopped");
|
|
3697
3981
|
}
|
|
3698
3982
|
setupRoutes() {
|
|
3699
3983
|
this.bot.on("message:text", async (ctx) => {
|
|
@@ -3702,6 +3986,9 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
3702
3986
|
if (await handlePendingWorkspaceInput(ctx, this.core, this.telegramConfig.chatId, this.assistantTopicId)) {
|
|
3703
3987
|
return;
|
|
3704
3988
|
}
|
|
3989
|
+
if (await handlePendingResumeInput(ctx, this.core, this.telegramConfig.chatId, this.assistantTopicId)) {
|
|
3990
|
+
return;
|
|
3991
|
+
}
|
|
3705
3992
|
if (!threadId) {
|
|
3706
3993
|
const html = redirectToAssistant(
|
|
3707
3994
|
this.telegramConfig.chatId,
|
|
@@ -3721,7 +4008,7 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
3721
4008
|
ctx.replyWithChatAction("typing").catch(() => {
|
|
3722
4009
|
});
|
|
3723
4010
|
handleAssistantMessage(this.assistantSession, forwardText).catch(
|
|
3724
|
-
(err) =>
|
|
4011
|
+
(err) => log13.error({ err }, "Assistant error")
|
|
3725
4012
|
);
|
|
3726
4013
|
return;
|
|
3727
4014
|
}
|
|
@@ -3738,7 +4025,7 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
3738
4025
|
threadId: String(threadId),
|
|
3739
4026
|
userId: String(ctx.from.id),
|
|
3740
4027
|
text: forwardText
|
|
3741
|
-
}).catch((err) =>
|
|
4028
|
+
}).catch((err) => log13.error({ err }, "handleMessage error"));
|
|
3742
4029
|
});
|
|
3743
4030
|
this.bot.on("message:photo", async (ctx) => {
|
|
3744
4031
|
const threadId = ctx.message.message_thread_id;
|
|
@@ -3880,7 +4167,7 @@ Task completed.
|
|
|
3880
4167
|
if (!content.attachment) return;
|
|
3881
4168
|
const { attachment } = content;
|
|
3882
4169
|
if (attachment.size > 50 * 1024 * 1024) {
|
|
3883
|
-
|
|
4170
|
+
log13.warn({ sessionId: ctx.sessionId, fileName: attachment.fileName, size: attachment.size }, "File too large for Telegram (>50MB)");
|
|
3884
4171
|
await this.sendQueue.enqueue(
|
|
3885
4172
|
() => this.bot.api.sendMessage(
|
|
3886
4173
|
this.telegramConfig.chatId,
|
|
@@ -3917,7 +4204,7 @@ Task completed.
|
|
|
3917
4204
|
);
|
|
3918
4205
|
}
|
|
3919
4206
|
} catch (err) {
|
|
3920
|
-
|
|
4207
|
+
log13.error({ err, sessionId: ctx.sessionId, fileName: attachment.fileName }, "Failed to send attachment");
|
|
3921
4208
|
}
|
|
3922
4209
|
},
|
|
3923
4210
|
onSessionEnd: async (ctx, _content) => {
|
|
@@ -3985,14 +4272,14 @@ Task completed.
|
|
|
3985
4272
|
if (session.archiving) return;
|
|
3986
4273
|
const threadId = Number(session.threadId);
|
|
3987
4274
|
if (!threadId || isNaN(threadId)) {
|
|
3988
|
-
|
|
4275
|
+
log13.warn({ sessionId, threadId: session.threadId }, "Session has no valid threadId, skipping message");
|
|
3989
4276
|
return;
|
|
3990
4277
|
}
|
|
3991
4278
|
const ctx = { sessionId, threadId };
|
|
3992
4279
|
await dispatchMessage(this.messageHandlers, ctx, content);
|
|
3993
4280
|
}
|
|
3994
4281
|
async sendPermissionRequest(sessionId, request) {
|
|
3995
|
-
|
|
4282
|
+
log13.info({ sessionId, requestId: request.id }, "Permission request sent");
|
|
3996
4283
|
const session = this.core.sessionManager.getSession(sessionId);
|
|
3997
4284
|
if (!session) return;
|
|
3998
4285
|
await this.sendQueue.enqueue(
|
|
@@ -4001,7 +4288,7 @@ Task completed.
|
|
|
4001
4288
|
}
|
|
4002
4289
|
async sendNotification(notification) {
|
|
4003
4290
|
if (notification.sessionId === this.assistantSession?.id) return;
|
|
4004
|
-
|
|
4291
|
+
log13.info(
|
|
4005
4292
|
{ sessionId: notification.sessionId, type: notification.type },
|
|
4006
4293
|
"Notification sent"
|
|
4007
4294
|
);
|
|
@@ -4037,7 +4324,7 @@ Task completed.
|
|
|
4037
4324
|
);
|
|
4038
4325
|
}
|
|
4039
4326
|
async createSessionThread(sessionId, name) {
|
|
4040
|
-
|
|
4327
|
+
log13.info({ sessionId, name }, "Session topic created");
|
|
4041
4328
|
return String(
|
|
4042
4329
|
await createSessionTopic(this.bot, this.telegramConfig.chatId, name)
|
|
4043
4330
|
);
|
|
@@ -4061,7 +4348,7 @@ Task completed.
|
|
|
4061
4348
|
try {
|
|
4062
4349
|
await this.bot.api.deleteForumTopic(this.telegramConfig.chatId, topicId);
|
|
4063
4350
|
} catch (err) {
|
|
4064
|
-
|
|
4351
|
+
log13.warn({ err, sessionId, topicId }, "Failed to delete forum topic (may already be deleted)");
|
|
4065
4352
|
}
|
|
4066
4353
|
}
|
|
4067
4354
|
async sendSkillCommands(sessionId, commands) {
|
|
@@ -4085,7 +4372,7 @@ Task completed.
|
|
|
4085
4372
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
4086
4373
|
return { buffer, filePath: file.file_path };
|
|
4087
4374
|
} catch (err) {
|
|
4088
|
-
|
|
4375
|
+
log13.error({ err }, "Failed to download file from Telegram");
|
|
4089
4376
|
return null;
|
|
4090
4377
|
}
|
|
4091
4378
|
}
|
|
@@ -4101,7 +4388,7 @@ Task completed.
|
|
|
4101
4388
|
try {
|
|
4102
4389
|
buffer = await this.fileService.convertOggToWav(buffer);
|
|
4103
4390
|
} catch (err) {
|
|
4104
|
-
|
|
4391
|
+
log13.warn({ err }, "OGG\u2192WAV conversion failed, saving original OGG");
|
|
4105
4392
|
fileName = "voice.ogg";
|
|
4106
4393
|
mimeType = "audio/ogg";
|
|
4107
4394
|
originalFilePath = void 0;
|
|
@@ -4127,7 +4414,7 @@ Task completed.
|
|
|
4127
4414
|
userId: String(userId),
|
|
4128
4415
|
text,
|
|
4129
4416
|
attachments: [att]
|
|
4130
|
-
}).catch((err) =>
|
|
4417
|
+
}).catch((err) => log13.error({ err }, "handleMessage error"));
|
|
4131
4418
|
}
|
|
4132
4419
|
async cleanupSkillCommands(sessionId) {
|
|
4133
4420
|
await this.skillManager.cleanup(sessionId);
|
|
@@ -4178,4 +4465,4 @@ Task completed.
|
|
|
4178
4465
|
export {
|
|
4179
4466
|
TelegramAdapter
|
|
4180
4467
|
};
|
|
4181
|
-
//# sourceMappingURL=chunk-
|
|
4468
|
+
//# sourceMappingURL=chunk-AHPRT3RY.js.map
|