@openacp/cli 2026.327.3 → 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.
- package/README.md +13 -13
- package/dist/adapter-HGJENQCN.js +13 -0
- package/dist/agent-catalog-SZQQERV7.js +10 -0
- package/dist/{agent-dependencies-WS7Z2DFW.js → agent-dependencies-ED2ZTUHG.js} +1 -2
- package/dist/{agent-registry-5LZT7CUB.js → agent-registry-YOGP656W.js} +1 -2
- package/dist/agent-store-5UHZH2XI.js +8 -0
- package/dist/{api-client-AQPNKXI2.js → api-client-XTLRRFPX.js} +1 -2
- package/dist/api-server-DSUW637I.js +7 -0
- package/dist/api-server-WFB5K6FP.js +10 -0
- package/dist/{autostart-6JS565RY.js → autostart-CUPZMKKC.js} +3 -4
- package/dist/{chunk-WIIZNPCR.js → chunk-2KT6TROD.js} +12 -33
- package/dist/chunk-2KT6TROD.js.map +1 -0
- package/dist/{chunk-PPSMUECX.js → chunk-2R5XM3ES.js} +2 -2
- package/dist/{chunk-SNPYTMPR.js → chunk-3EWTPOF7.js} +2 -2
- package/dist/{chunk-YEULD3SG.js → chunk-3NAFXVQM.js} +7 -2
- package/dist/{chunk-YEULD3SG.js.map → chunk-3NAFXVQM.js.map} +1 -1
- package/dist/{chunk-QAQDGPB4.js → chunk-43JVXFYP.js} +3 -3
- package/dist/{chunk-KMMEFXIE.js → chunk-4B6PCWQP.js} +37 -9
- package/dist/chunk-4B6PCWQP.js.map +1 -0
- package/dist/{chunk-A6Y4GZM3.js → chunk-566W6INH.js} +2 -2
- package/dist/{chunk-ODUM3D6X.js → chunk-5HKQCYOI.js} +1 -39
- package/dist/chunk-5HKQCYOI.js.map +1 -0
- package/dist/{chunk-36YQ44D7.js → chunk-5TCXYDLR.js} +3 -3
- package/dist/{chunk-XIBG7LSL.js → chunk-6VR4GWOO.js} +238 -108
- package/dist/chunk-6VR4GWOO.js.map +1 -0
- package/dist/{chunk-WXVT3AOY.js → chunk-7ZCQF6QM.js} +8 -3
- package/dist/chunk-7ZCQF6QM.js.map +1 -0
- package/dist/{chunk-HUWOFP2H.js → chunk-E2SLHZAC.js} +8 -12
- package/dist/{chunk-HUWOFP2H.js.map → chunk-E2SLHZAC.js.map} +1 -1
- package/dist/{chunk-RBYBSSGO.js → chunk-FCTC7KDT.js} +2 -2
- package/dist/chunk-I53NEV3S.js +45 -0
- package/dist/chunk-I53NEV3S.js.map +1 -0
- package/dist/{chunk-2YCW3QDV.js → chunk-IXMIC4GQ.js} +8 -7
- package/dist/chunk-IXMIC4GQ.js.map +1 -0
- package/dist/{chunk-BLQUXO7S.js → chunk-IZ5UEZF7.js} +27 -2
- package/dist/chunk-IZ5UEZF7.js.map +1 -0
- package/dist/{chunk-QVMEF6FB.js → chunk-JOMDPFQ2.js} +10 -24
- package/dist/chunk-JOMDPFQ2.js.map +1 -0
- package/dist/{chunk-4GMLGCF2.js → chunk-JUFN4XMB.js} +2 -2
- package/dist/{chunk-AD3X6DGK.js → chunk-NT6FYV27.js} +75 -13
- package/dist/chunk-NT6FYV27.js.map +1 -0
- package/dist/{chunk-UMT7RU77.js → chunk-QBEQJFGL.js} +9 -9
- package/dist/{chunk-XMMAGAT4.js → chunk-R6KZYF7D.js} +8 -1
- package/dist/{chunk-XMMAGAT4.js.map → chunk-R6KZYF7D.js.map} +1 -1
- package/dist/{chunk-LP45RCA4.js → chunk-RXMWJHWH.js} +1007 -495
- package/dist/chunk-RXMWJHWH.js.map +1 -0
- package/dist/{chunk-SHTGQGAU.js → chunk-V2YZWYXT.js} +3 -3
- package/dist/{chunk-BQ6FR32N.js → chunk-VD3QSMVY.js} +2 -2
- package/dist/cli.js +141 -115
- package/dist/cli.js.map +1 -1
- package/dist/{config-I4FMCJGZ.js → config-UCAFCS5W.js} +3 -4
- package/dist/config-editor-OU6PUY66.js +10 -0
- package/dist/{config-registry-CUMNXFGK.js → config-registry-ZXAIJNYB.js} +2 -3
- package/dist/{context-XM6E22LM.js → context-7MPU7RL5.js} +1 -2
- package/dist/core-plugins-R2EVZAJV.js +22 -0
- package/dist/{daemon-PXO5QPCR.js → daemon-DTA6KYYY.js} +4 -5
- package/dist/{dev-loader-DRU3R7ZM.js → dev-loader-7P3HZCIA.js} +1 -3
- package/dist/{dev-loader-DRU3R7ZM.js.map → dev-loader-7P3HZCIA.js.map} +1 -1
- package/dist/doctor-D723IB2I.js +9 -0
- package/dist/file-service-HHB3JQIO.js +8 -0
- package/dist/index.d.ts +41 -150
- package/dist/index.js +63 -29
- package/dist/index.js.map +1 -1
- package/dist/{install-cloudflared-AN24L4DP.js → install-cloudflared-JRJ4BSOM.js} +3 -4
- package/dist/{install-cloudflared-AN24L4DP.js.map → install-cloudflared-JRJ4BSOM.js.map} +1 -1
- package/dist/{install-context-XPWTFT3J.js → install-context-EHYV5WRY.js} +2 -3
- package/dist/{install-context-XPWTFT3J.js.map → install-context-EHYV5WRY.js.map} +1 -1
- package/dist/{install-jq-CRVDJGF3.js → install-jq-ISTGT263.js} +3 -4
- package/dist/{install-jq-CRVDJGF3.js.map → install-jq-ISTGT263.js.map} +1 -1
- package/dist/{integrate-G6CVXTGT.js → integrate-JIEZYDOR.js} +1 -2
- package/dist/{integrate-G6CVXTGT.js.map → integrate-JIEZYDOR.js.map} +1 -1
- package/dist/{log-LZ7FTRKG.js → log-YZ243M5G.js} +4 -3
- package/dist/{main-UVTZ46WP.js → main-RRSX5SRL.js} +117 -40
- package/dist/main-RRSX5SRL.js.map +1 -0
- package/dist/{menu-YDQ2LWAR.js → menu-ALFN37IR.js} +1 -2
- package/dist/notifications-MO23S7S3.js +8 -0
- package/dist/{plugin-create-5HQRF2ID.js → plugin-create-EHL76ZZG.js} +1 -2
- package/dist/{plugin-create-5HQRF2ID.js.map → plugin-create-EHL76ZZG.js.map} +1 -1
- package/dist/plugin-installer-5XHORMLS.js +9 -0
- package/dist/{plugin-registry-WB3DR67H.js → plugin-registry-6J3YSFHF.js} +1 -2
- package/dist/{plugin-search-HQ4WQKOF.js → plugin-search-MGKAL5JM.js} +1 -2
- package/dist/{plugin-search-HQ4WQKOF.js.map → plugin-search-MGKAL5JM.js.map} +1 -1
- package/dist/{post-upgrade-3ADZRMYJ.js → post-upgrade-Y26S2ZQ7.js} +6 -7
- package/dist/{post-upgrade-3ADZRMYJ.js.map → post-upgrade-Y26S2ZQ7.js.map} +1 -1
- package/dist/{read-text-file-IRZM3QLM.js → read-text-file-DJBTITIB.js} +1 -2
- package/dist/{registry-client-AVGRE4CF.js → registry-client-GTBWLXYU.js} +1 -2
- package/dist/{security-YNRBW6S7.js → security-2BA265LN.js} +1 -2
- package/dist/{settings-manager-MD2U4ZV2.js → settings-manager-B4UN2LAC.js} +1 -2
- package/dist/{setup-EYAFK2WI.js → setup-OI6A3OXW.js} +109 -80
- package/dist/setup-OI6A3OXW.js.map +1 -0
- package/dist/speech-GB7PHVQZ.js +9 -0
- package/dist/{suggest-7D6B542M.js → suggest-RST5VOHB.js} +1 -3
- package/dist/{suggest-7D6B542M.js.map → suggest-RST5VOHB.js.map} +1 -1
- package/dist/telegram-UVIAXADE.js +7 -0
- package/dist/tunnel-4WNFC7GO.js +7 -0
- package/dist/{tunnel-service-QJPUYEKU.js → tunnel-service-I2NFUX3V.js} +3 -4
- package/dist/{tunnel-service-QJPUYEKU.js.map → tunnel-service-I2NFUX3V.js.map} +1 -1
- package/dist/{validators-WSTBNKRW.js → validators-GITLOFXC.js} +1 -2
- package/dist/{version-NQZBM5M7.js → version-AXXV6IV2.js} +1 -2
- package/package.json +1 -3
- package/dist/adapter-LC2QSDAS.js +0 -15
- package/dist/adapter-Y55NXX6I.js +0 -1006
- package/dist/adapter-Y55NXX6I.js.map +0 -1
- package/dist/agent-catalog-YHBFERYO.js +0 -11
- package/dist/agent-store-VSHNY5GT.js +0 -9
- package/dist/api-server-7G3ZUZRM.js +0 -8
- package/dist/api-server-CAYNPUF2.js +0 -11
- package/dist/chunk-2YCW3QDV.js.map +0 -1
- package/dist/chunk-3ASUU6WW.js +0 -124
- package/dist/chunk-3ASUU6WW.js.map +0 -1
- package/dist/chunk-AD3X6DGK.js.map +0 -1
- package/dist/chunk-BLQUXO7S.js.map +0 -1
- package/dist/chunk-KMMEFXIE.js.map +0 -1
- package/dist/chunk-LP45RCA4.js.map +0 -1
- package/dist/chunk-ODUM3D6X.js.map +0 -1
- package/dist/chunk-QVMEF6FB.js.map +0 -1
- package/dist/chunk-TRXBJEZ5.js +0 -447
- package/dist/chunk-TRXBJEZ5.js.map +0 -1
- package/dist/chunk-VUNV25KB.js +0 -16
- package/dist/chunk-WIIZNPCR.js.map +0 -1
- package/dist/chunk-WXVT3AOY.js.map +0 -1
- package/dist/chunk-XIBG7LSL.js.map +0 -1
- package/dist/config-editor-3IKBPZA7.js +0 -11
- package/dist/core-plugins-ROU4GPLT.js +0 -23
- package/dist/dist-UHQK5CXN.js +0 -21151
- package/dist/dist-UHQK5CXN.js.map +0 -1
- package/dist/doctor-QZQAP46W.js +0 -10
- package/dist/file-service-EUODJAIT.js +0 -9
- package/dist/main-UVTZ46WP.js.map +0 -1
- package/dist/notifications-D5BRDNSU.js +0 -9
- package/dist/plugin-installer-GQ2P3Q3E.js +0 -23
- package/dist/plugin-installer-GQ2P3Q3E.js.map +0 -1
- package/dist/setup-EYAFK2WI.js.map +0 -1
- package/dist/slack-37ZWBDUI.js +0 -8
- package/dist/speech-2GHQNRIO.js +0 -9
- package/dist/telegram-2ZCCCZIY.js +0 -8
- package/dist/tunnel-45HA72MB.js +0 -8
- package/dist/version-NQZBM5M7.js.map +0 -1
- /package/dist/{adapter-LC2QSDAS.js.map → adapter-HGJENQCN.js.map} +0 -0
- /package/dist/{agent-catalog-YHBFERYO.js.map → agent-catalog-SZQQERV7.js.map} +0 -0
- /package/dist/{agent-dependencies-WS7Z2DFW.js.map → agent-dependencies-ED2ZTUHG.js.map} +0 -0
- /package/dist/{agent-registry-5LZT7CUB.js.map → agent-registry-YOGP656W.js.map} +0 -0
- /package/dist/{agent-store-VSHNY5GT.js.map → agent-store-5UHZH2XI.js.map} +0 -0
- /package/dist/{api-client-AQPNKXI2.js.map → api-client-XTLRRFPX.js.map} +0 -0
- /package/dist/{api-server-7G3ZUZRM.js.map → api-server-DSUW637I.js.map} +0 -0
- /package/dist/{api-server-CAYNPUF2.js.map → api-server-WFB5K6FP.js.map} +0 -0
- /package/dist/{autostart-6JS565RY.js.map → autostart-CUPZMKKC.js.map} +0 -0
- /package/dist/{chunk-PPSMUECX.js.map → chunk-2R5XM3ES.js.map} +0 -0
- /package/dist/{chunk-SNPYTMPR.js.map → chunk-3EWTPOF7.js.map} +0 -0
- /package/dist/{chunk-QAQDGPB4.js.map → chunk-43JVXFYP.js.map} +0 -0
- /package/dist/{chunk-A6Y4GZM3.js.map → chunk-566W6INH.js.map} +0 -0
- /package/dist/{chunk-36YQ44D7.js.map → chunk-5TCXYDLR.js.map} +0 -0
- /package/dist/{chunk-RBYBSSGO.js.map → chunk-FCTC7KDT.js.map} +0 -0
- /package/dist/{chunk-4GMLGCF2.js.map → chunk-JUFN4XMB.js.map} +0 -0
- /package/dist/{chunk-UMT7RU77.js.map → chunk-QBEQJFGL.js.map} +0 -0
- /package/dist/{chunk-SHTGQGAU.js.map → chunk-V2YZWYXT.js.map} +0 -0
- /package/dist/{chunk-BQ6FR32N.js.map → chunk-VD3QSMVY.js.map} +0 -0
- /package/dist/{chunk-VUNV25KB.js.map → config-UCAFCS5W.js.map} +0 -0
- /package/dist/{config-I4FMCJGZ.js.map → config-editor-OU6PUY66.js.map} +0 -0
- /package/dist/{config-editor-3IKBPZA7.js.map → config-registry-ZXAIJNYB.js.map} +0 -0
- /package/dist/{config-registry-CUMNXFGK.js.map → context-7MPU7RL5.js.map} +0 -0
- /package/dist/{context-XM6E22LM.js.map → core-plugins-R2EVZAJV.js.map} +0 -0
- /package/dist/{core-plugins-ROU4GPLT.js.map → daemon-DTA6KYYY.js.map} +0 -0
- /package/dist/{daemon-PXO5QPCR.js.map → doctor-D723IB2I.js.map} +0 -0
- /package/dist/{doctor-QZQAP46W.js.map → file-service-HHB3JQIO.js.map} +0 -0
- /package/dist/{file-service-EUODJAIT.js.map → log-YZ243M5G.js.map} +0 -0
- /package/dist/{log-LZ7FTRKG.js.map → menu-ALFN37IR.js.map} +0 -0
- /package/dist/{menu-YDQ2LWAR.js.map → notifications-MO23S7S3.js.map} +0 -0
- /package/dist/{notifications-D5BRDNSU.js.map → plugin-installer-5XHORMLS.js.map} +0 -0
- /package/dist/{plugin-registry-WB3DR67H.js.map → plugin-registry-6J3YSFHF.js.map} +0 -0
- /package/dist/{read-text-file-IRZM3QLM.js.map → read-text-file-DJBTITIB.js.map} +0 -0
- /package/dist/{registry-client-AVGRE4CF.js.map → registry-client-GTBWLXYU.js.map} +0 -0
- /package/dist/{security-YNRBW6S7.js.map → security-2BA265LN.js.map} +0 -0
- /package/dist/{settings-manager-MD2U4ZV2.js.map → settings-manager-B4UN2LAC.js.map} +0 -0
- /package/dist/{slack-37ZWBDUI.js.map → speech-GB7PHVQZ.js.map} +0 -0
- /package/dist/{speech-2GHQNRIO.js.map → telegram-UVIAXADE.js.map} +0 -0
- /package/dist/{telegram-2ZCCCZIY.js.map → tunnel-4WNFC7GO.js.map} +0 -0
- /package/dist/{tunnel-45HA72MB.js.map → validators-GITLOFXC.js.map} +0 -0
- /package/dist/{validators-WSTBNKRW.js.map → version-AXXV6IV2.js.map} +0 -0
|
@@ -7,20 +7,7 @@ import {
|
|
|
7
7
|
} from "./chunk-AFKX424Q.js";
|
|
8
8
|
import {
|
|
9
9
|
DoctorEngine
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import {
|
|
12
|
-
BaseRenderer,
|
|
13
|
-
MessagingAdapter,
|
|
14
|
-
extractContentText,
|
|
15
|
-
formatTokens,
|
|
16
|
-
formatToolSummary,
|
|
17
|
-
formatToolTitle,
|
|
18
|
-
progressBar,
|
|
19
|
-
resolveToolIcon,
|
|
20
|
-
splitMessage,
|
|
21
|
-
stripCodeFences,
|
|
22
|
-
truncateContent
|
|
23
|
-
} from "./chunk-TRXBJEZ5.js";
|
|
10
|
+
} from "./chunk-43JVXFYP.js";
|
|
24
11
|
import {
|
|
25
12
|
CheckpointReader,
|
|
26
13
|
DEFAULT_MAX_TOKENS
|
|
@@ -30,10 +17,10 @@ import {
|
|
|
30
17
|
getSafeFields,
|
|
31
18
|
isHotReloadable,
|
|
32
19
|
resolveOptions
|
|
33
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-5HKQCYOI.js";
|
|
34
21
|
import {
|
|
35
22
|
createChildLogger
|
|
36
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-R6KZYF7D.js";
|
|
37
24
|
|
|
38
25
|
// src/plugins/telegram/adapter.ts
|
|
39
26
|
import { Bot, InputFile } from "grammy";
|
|
@@ -78,6 +65,249 @@ function buildDeepLink(chatId, threadId, messageId) {
|
|
|
78
65
|
// src/plugins/telegram/commands/new-session.ts
|
|
79
66
|
import { InlineKeyboard as InlineKeyboard2 } from "grammy";
|
|
80
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
|
+
|
|
81
311
|
// src/plugins/telegram/formatting.ts
|
|
82
312
|
function escapeHtml(text) {
|
|
83
313
|
if (!text) return "";
|
|
@@ -125,15 +355,7 @@ function formatToolCall(tool, verbosity = "medium") {
|
|
|
125
355
|
return text;
|
|
126
356
|
}
|
|
127
357
|
function formatToolUpdate(update, verbosity = "medium") {
|
|
128
|
-
|
|
129
|
-
const name = update.name || "Tool";
|
|
130
|
-
const label = verbosity === "low" ? formatToolTitle(name, update.rawInput, update.displayTitle) : formatToolSummary(name, update.rawInput, update.displaySummary);
|
|
131
|
-
let text = `${si} <b>${escapeHtml(label)}</b>`;
|
|
132
|
-
text += formatViewerLinks(update.viewerLinks, update.viewerFilePath);
|
|
133
|
-
if (verbosity === "high") {
|
|
134
|
-
text += formatHighDetails(update.rawInput, update.content, 3800);
|
|
135
|
-
}
|
|
136
|
-
return text;
|
|
358
|
+
return formatToolCall(update, verbosity);
|
|
137
359
|
}
|
|
138
360
|
function formatHighDetails(rawInput, content, maxLen) {
|
|
139
361
|
let text = "";
|
|
@@ -165,12 +387,8 @@ function formatViewerLinks(links, filePath) {
|
|
|
165
387
|
\u{1F4DD} <a href="${escapeHtml(links.diff)}">View diff${fileName ? ` \u2014 ${escapeHtml(fileName)}` : ""}</a>`;
|
|
166
388
|
return text;
|
|
167
389
|
}
|
|
168
|
-
function formatPlan(plan
|
|
390
|
+
function formatPlan(plan) {
|
|
169
391
|
const { entries } = plan;
|
|
170
|
-
if (verbosity === "medium") {
|
|
171
|
-
const done = entries.filter((e) => e.status === "completed").length;
|
|
172
|
-
return `\u{1F4CB} <b>Plan:</b> ${done}/${entries.length} steps completed`;
|
|
173
|
-
}
|
|
174
392
|
const statusIcon = {
|
|
175
393
|
pending: "\u2B1C",
|
|
176
394
|
in_progress: "\u{1F504}",
|
|
@@ -182,27 +400,97 @@ function formatPlan(plan, verbosity = "medium") {
|
|
|
182
400
|
return `<b>Plan:</b>
|
|
183
401
|
${lines.join("\n")}`;
|
|
184
402
|
}
|
|
185
|
-
function formatUsage(usage,
|
|
186
|
-
const { tokensUsed, contextSize
|
|
403
|
+
function formatUsage(usage, _verbosity = "medium") {
|
|
404
|
+
const { tokensUsed, contextSize } = usage;
|
|
187
405
|
if (tokensUsed == null) return "\u{1F4CA} Usage data unavailable";
|
|
188
|
-
if (verbosity === "medium") {
|
|
189
|
-
const costStr = cost != null ? ` \xB7 $${cost.toFixed(2)}` : "";
|
|
190
|
-
return `\u{1F4CA} ${formatTokens(tokensUsed)} tokens${costStr}`;
|
|
191
|
-
}
|
|
192
406
|
if (contextSize == null) return `\u{1F4CA} ${formatTokens(tokensUsed)} tokens`;
|
|
193
407
|
const ratio = tokensUsed / contextSize;
|
|
194
408
|
const pct = Math.round(ratio * 100);
|
|
195
409
|
const bar = progressBar(ratio);
|
|
196
410
|
const emoji = pct >= 85 ? "\u26A0\uFE0F" : "\u{1F4CA}";
|
|
197
|
-
|
|
411
|
+
return `${emoji} ${formatTokens(tokensUsed)} / ${formatTokens(contextSize)} tokens
|
|
198
412
|
${bar} ${pct}%`;
|
|
199
|
-
if (cost != null) text += `
|
|
200
|
-
\u{1F4B0} $${cost.toFixed(2)}`;
|
|
201
|
-
return text;
|
|
202
413
|
}
|
|
203
414
|
function splitMessage2(text, maxLength = 3800) {
|
|
204
415
|
return splitMessage(text, maxLength);
|
|
205
416
|
}
|
|
417
|
+
function renderToolCard(snap) {
|
|
418
|
+
const sections = [];
|
|
419
|
+
const { totalVisible, completedVisible, allComplete } = snap;
|
|
420
|
+
const headerCheck = allComplete ? " \u2705" : "";
|
|
421
|
+
if (totalVisible > 0) {
|
|
422
|
+
sections.push(
|
|
423
|
+
`<b>\u{1F4CB} Tools (${completedVisible}/${totalVisible})</b>${headerCheck}`
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
const visible = snap.entries.filter((e) => !e.hidden);
|
|
427
|
+
const completed = visible.filter(
|
|
428
|
+
(e) => e.status === "completed" || e.status === "done" || e.status === "failed"
|
|
429
|
+
);
|
|
430
|
+
const running = visible.filter(
|
|
431
|
+
(e) => e.status !== "completed" && e.status !== "done" && e.status !== "failed"
|
|
432
|
+
);
|
|
433
|
+
for (const entry of completed) {
|
|
434
|
+
let line = `${entry.icon} ${escapeHtml(entry.label)}`;
|
|
435
|
+
if (entry.viewerLinks) {
|
|
436
|
+
const links = [];
|
|
437
|
+
const fileName = entry.viewerFilePath?.split("/").pop() ?? "";
|
|
438
|
+
if (entry.viewerLinks.file)
|
|
439
|
+
links.push(
|
|
440
|
+
`<a href="${escapeHtml(entry.viewerLinks.file)}">View ${escapeHtml(fileName || "file")}</a>`
|
|
441
|
+
);
|
|
442
|
+
if (entry.viewerLinks.diff)
|
|
443
|
+
links.push(
|
|
444
|
+
`<a href="${escapeHtml(entry.viewerLinks.diff)}">View diff</a>`
|
|
445
|
+
);
|
|
446
|
+
if (links.length > 0) line += `
|
|
447
|
+
${links.join(" \xB7 ")}`;
|
|
448
|
+
}
|
|
449
|
+
sections.push(line);
|
|
450
|
+
}
|
|
451
|
+
if (snap.planEntries && snap.planEntries.length > 0) {
|
|
452
|
+
const planDone = snap.planEntries.filter(
|
|
453
|
+
(e) => e.status === "completed"
|
|
454
|
+
).length;
|
|
455
|
+
const planTotal = snap.planEntries.length;
|
|
456
|
+
sections.push(`\u2500\u2500 Plan: ${planDone}/${planTotal} \u2500\u2500`);
|
|
457
|
+
const statusIcon = {
|
|
458
|
+
completed: "\u2705",
|
|
459
|
+
in_progress: "\u{1F504}",
|
|
460
|
+
pending: "\u2B1C"
|
|
461
|
+
};
|
|
462
|
+
for (let i = 0; i < snap.planEntries.length; i++) {
|
|
463
|
+
const e = snap.planEntries[i];
|
|
464
|
+
const icon = statusIcon[e.status] ?? "\u2B1C";
|
|
465
|
+
sections.push(`${icon} ${i + 1}. ${escapeHtml(e.content)}`);
|
|
466
|
+
}
|
|
467
|
+
sections.push("\u2500\u2500\u2500\u2500");
|
|
468
|
+
}
|
|
469
|
+
for (const entry of running) {
|
|
470
|
+
sections.push(`${entry.icon} ${escapeHtml(entry.label)}`);
|
|
471
|
+
}
|
|
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
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (current) chunks.push(current);
|
|
492
|
+
return chunks;
|
|
493
|
+
}
|
|
206
494
|
|
|
207
495
|
// src/plugins/telegram/commands/admin.ts
|
|
208
496
|
import { InlineKeyboard } from "grammy";
|
|
@@ -390,6 +678,15 @@ function setupTTSCallbacks(bot, core) {
|
|
|
390
678
|
}
|
|
391
679
|
return;
|
|
392
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
|
+
}
|
|
393
690
|
const newMode = session.voiceMode === "on" ? "off" : "on";
|
|
394
691
|
session.setVoiceMode(newMode);
|
|
395
692
|
const toastText = newMode === "on" ? "\u{1F50A} Text to Speech enabled" : "\u{1F507} Text to Speech disabled";
|
|
@@ -426,6 +723,15 @@ async function handleTTS(ctx, core) {
|
|
|
426
723
|
}
|
|
427
724
|
const args = ctx.message?.text?.split(/\s+/).slice(1) ?? [];
|
|
428
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
|
+
}
|
|
429
735
|
if (arg === "on") {
|
|
430
736
|
session.setVoiceMode("on");
|
|
431
737
|
await ctx.reply("\u{1F50A} Text to Speech enabled for this session.", {
|
|
@@ -496,7 +802,7 @@ async function handleUpdate(ctx, core) {
|
|
|
496
802
|
);
|
|
497
803
|
return;
|
|
498
804
|
}
|
|
499
|
-
const { getCurrentVersion, getLatestVersion, compareVersions, runUpdate } = await import("./version-
|
|
805
|
+
const { getCurrentVersion, getLatestVersion, compareVersions, runUpdate } = await import("./version-AXXV6IV2.js");
|
|
500
806
|
const current = getCurrentVersion();
|
|
501
807
|
const statusMsg = await ctx.reply(
|
|
502
808
|
`\u{1F50D} Checking for updates... (current: v${escapeHtml(current)})`,
|
|
@@ -1240,9 +1546,22 @@ async function handleArchive(ctx, core) {
|
|
|
1240
1546
|
if (!threadId) return;
|
|
1241
1547
|
const session = core.sessionManager.getSessionByThread("telegram", String(threadId));
|
|
1242
1548
|
const record = !session ? core.sessionManager.getRecordByThread("telegram", String(threadId)) : void 0;
|
|
1243
|
-
|
|
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
|
+
}
|
|
1244
1563
|
await ctx.reply(
|
|
1245
|
-
"\u26A0\uFE0F <b>Archive this session?</b>\n\nThis will:\n\u2022 Delete this topic and
|
|
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>",
|
|
1246
1565
|
{
|
|
1247
1566
|
parse_mode: "HTML",
|
|
1248
1567
|
reply_markup: new InlineKeyboard3().text("\u{1F5D1} Yes, archive", `ar:yes:${identifier}`).text("\u274C Cancel", `ar:no:${identifier}`)
|
|
@@ -1262,37 +1581,21 @@ async function handleArchiveConfirm(ctx, core, chatId) {
|
|
|
1262
1581
|
await ctx.editMessageText("Archive cancelled.", { parse_mode: "HTML" });
|
|
1263
1582
|
return;
|
|
1264
1583
|
}
|
|
1265
|
-
await ctx.editMessageText("\u{1F504} Archiving...", { parse_mode: "HTML" });
|
|
1266
|
-
if (identifier.startsWith("topic:")) {
|
|
1267
|
-
const topicId = Number(identifier.slice("topic:".length));
|
|
1268
|
-
try {
|
|
1269
|
-
await ctx.api.deleteForumTopic(chatId, topicId);
|
|
1270
|
-
core.notificationManager.notifyAll({
|
|
1271
|
-
sessionId: "system",
|
|
1272
|
-
sessionName: `Orphan topic #${topicId}`,
|
|
1273
|
-
type: "completed",
|
|
1274
|
-
summary: `Orphan topic #${topicId} archived and deleted.`
|
|
1275
|
-
});
|
|
1276
|
-
} catch (err) {
|
|
1277
|
-
core.notificationManager.notifyAll({
|
|
1278
|
-
sessionId: "system",
|
|
1279
|
-
sessionName: `Orphan topic #${topicId}`,
|
|
1280
|
-
type: "error",
|
|
1281
|
-
summary: `Failed to delete orphan topic #${topicId}: ${err.message}`
|
|
1282
|
-
});
|
|
1283
|
-
}
|
|
1284
|
-
return;
|
|
1285
|
-
}
|
|
1286
1584
|
const result = await core.archiveSession(identifier);
|
|
1287
1585
|
if (result.ok) {
|
|
1288
|
-
core.
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
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
|
+
}
|
|
1293
1596
|
} else {
|
|
1294
1597
|
try {
|
|
1295
|
-
await ctx.editMessageText(
|
|
1598
|
+
await ctx.editMessageText(`Failed to archive: <code>${escapeHtml(result.error)}</code>`, { parse_mode: "HTML" });
|
|
1296
1599
|
} catch {
|
|
1297
1600
|
core.notificationManager.notifyAll({
|
|
1298
1601
|
sessionId: identifier,
|
|
@@ -1502,10 +1805,10 @@ Downloading... ${bar} ${percent}%`, { parse_mode: "HTML" });
|
|
|
1502
1805
|
};
|
|
1503
1806
|
const result = await catalog.install(nameOrId, progress);
|
|
1504
1807
|
if (result.ok) {
|
|
1505
|
-
const { getAgentCapabilities } = await import("./agent-dependencies-
|
|
1808
|
+
const { getAgentCapabilities } = await import("./agent-dependencies-ED2ZTUHG.js");
|
|
1506
1809
|
const caps = getAgentCapabilities(result.agentKey);
|
|
1507
1810
|
if (caps.integration) {
|
|
1508
|
-
const { installIntegration } = await import("./integrate-
|
|
1811
|
+
const { installIntegration } = await import("./integrate-JIEZYDOR.js");
|
|
1509
1812
|
const intResult = await installIntegration(result.agentKey, caps.integration);
|
|
1510
1813
|
if (intResult.success) {
|
|
1511
1814
|
try {
|
|
@@ -1575,7 +1878,7 @@ function buildProgressBar(percent) {
|
|
|
1575
1878
|
// src/plugins/telegram/commands/integrate.ts
|
|
1576
1879
|
import { InlineKeyboard as InlineKeyboard5 } from "grammy";
|
|
1577
1880
|
async function handleIntegrate(ctx, _core) {
|
|
1578
|
-
const { listIntegrations } = await import("./integrate-
|
|
1881
|
+
const { listIntegrations } = await import("./integrate-JIEZYDOR.js");
|
|
1579
1882
|
const agents = listIntegrations();
|
|
1580
1883
|
const keyboard = new InlineKeyboard5();
|
|
1581
1884
|
for (const agent of agents) {
|
|
@@ -1608,7 +1911,7 @@ function setupIntegrateCallbacks(bot, core) {
|
|
|
1608
1911
|
} catch {
|
|
1609
1912
|
}
|
|
1610
1913
|
if (data === "i:back") {
|
|
1611
|
-
const { listIntegrations } = await import("./integrate-
|
|
1914
|
+
const { listIntegrations } = await import("./integrate-JIEZYDOR.js");
|
|
1612
1915
|
const agents = listIntegrations();
|
|
1613
1916
|
const keyboard2 = new InlineKeyboard5();
|
|
1614
1917
|
for (const agent of agents) {
|
|
@@ -1628,7 +1931,7 @@ Select an agent to manage its integrations.`,
|
|
|
1628
1931
|
const agentMatch = data.match(/^i:agent:(.+)$/);
|
|
1629
1932
|
if (agentMatch) {
|
|
1630
1933
|
const agentName2 = agentMatch[1];
|
|
1631
|
-
const { getIntegration: getIntegration2 } = await import("./integrate-
|
|
1934
|
+
const { getIntegration: getIntegration2 } = await import("./integrate-JIEZYDOR.js");
|
|
1632
1935
|
const integration2 = getIntegration2(agentName2);
|
|
1633
1936
|
if (!integration2) {
|
|
1634
1937
|
await ctx.reply(`\u274C No integration available for '${escapeHtml(agentName2)}'.`, { parse_mode: "HTML" });
|
|
@@ -1655,7 +1958,7 @@ ${integration2.items.map((i) => `\u2022 <b>${escapeHtml(i.name)}</b> \u2014 ${es
|
|
|
1655
1958
|
const action = actionMatch[1];
|
|
1656
1959
|
const agentName = actionMatch[2];
|
|
1657
1960
|
const itemId = actionMatch[3];
|
|
1658
|
-
const { getIntegration } = await import("./integrate-
|
|
1961
|
+
const { getIntegration } = await import("./integrate-JIEZYDOR.js");
|
|
1659
1962
|
const integration = getIntegration(agentName);
|
|
1660
1963
|
if (!integration) return;
|
|
1661
1964
|
const item = integration.items.find((i) => i.id === itemId);
|
|
@@ -2139,7 +2442,7 @@ Tap to change:`, {
|
|
|
2139
2442
|
await ctx.answerCallbackQuery();
|
|
2140
2443
|
} catch {
|
|
2141
2444
|
}
|
|
2142
|
-
const { buildMenuKeyboard: buildMenuKeyboard3 } = await import("./menu-
|
|
2445
|
+
const { buildMenuKeyboard: buildMenuKeyboard3 } = await import("./menu-ALFN37IR.js");
|
|
2143
2446
|
try {
|
|
2144
2447
|
await ctx.editMessageText(`<b>OpenACP Menu</b>
|
|
2145
2448
|
Choose an action:`, {
|
|
@@ -3251,6 +3554,117 @@ function redirectToAssistant(chatId, assistantTopicId) {
|
|
|
3251
3554
|
return `\u{1F4AC} Please use the <a href="${link}">\u{1F916} Assistant</a> topic to chat with OpenACP.`;
|
|
3252
3555
|
}
|
|
3253
3556
|
|
|
3557
|
+
// src/core/adapter-primitives/primitives/tool-card-state.ts
|
|
3558
|
+
var DEBOUNCE_MS = 500;
|
|
3559
|
+
var ToolCardState = class {
|
|
3560
|
+
entries = [];
|
|
3561
|
+
planEntries;
|
|
3562
|
+
usage;
|
|
3563
|
+
finalized = false;
|
|
3564
|
+
isFirstFlush = true;
|
|
3565
|
+
debounceTimer;
|
|
3566
|
+
verbosity;
|
|
3567
|
+
onFlush;
|
|
3568
|
+
constructor(config) {
|
|
3569
|
+
this.verbosity = config.verbosity;
|
|
3570
|
+
this.onFlush = config.onFlush;
|
|
3571
|
+
}
|
|
3572
|
+
addTool(meta, kind, rawInput) {
|
|
3573
|
+
if (this.finalized) return;
|
|
3574
|
+
const hidden = this.verbosity !== "high" && evaluateNoise(meta.name, kind, rawInput) !== null;
|
|
3575
|
+
const entry = {
|
|
3576
|
+
id: meta.id,
|
|
3577
|
+
name: meta.name,
|
|
3578
|
+
kind,
|
|
3579
|
+
status: meta.status ?? "running",
|
|
3580
|
+
icon: resolveToolIcon({ status: meta.status ?? "running", kind }),
|
|
3581
|
+
label: formatToolSummary(meta.name, rawInput, meta.displaySummary),
|
|
3582
|
+
viewerLinks: meta.viewerLinks,
|
|
3583
|
+
viewerFilePath: meta.viewerFilePath,
|
|
3584
|
+
hidden
|
|
3585
|
+
};
|
|
3586
|
+
this.entries.push(entry);
|
|
3587
|
+
if (this.isFirstFlush) {
|
|
3588
|
+
this.isFirstFlush = false;
|
|
3589
|
+
this.flush();
|
|
3590
|
+
} else {
|
|
3591
|
+
this.scheduleFlush();
|
|
3592
|
+
}
|
|
3593
|
+
}
|
|
3594
|
+
updateTool(id, status, viewerLinks, viewerFilePath) {
|
|
3595
|
+
if (this.finalized) return;
|
|
3596
|
+
const entry = this.entries.find((e) => e.id === id);
|
|
3597
|
+
if (!entry) return;
|
|
3598
|
+
entry.status = status;
|
|
3599
|
+
entry.icon = resolveToolIcon({ status, kind: entry.kind });
|
|
3600
|
+
if (viewerLinks) entry.viewerLinks = viewerLinks;
|
|
3601
|
+
if (viewerFilePath) entry.viewerFilePath = viewerFilePath;
|
|
3602
|
+
this.scheduleFlush();
|
|
3603
|
+
}
|
|
3604
|
+
updatePlan(entries) {
|
|
3605
|
+
if (this.finalized) return;
|
|
3606
|
+
this.planEntries = entries;
|
|
3607
|
+
if (this.entries.length === 0 && this.isFirstFlush) {
|
|
3608
|
+
this.isFirstFlush = false;
|
|
3609
|
+
this.flush();
|
|
3610
|
+
} else {
|
|
3611
|
+
this.scheduleFlush();
|
|
3612
|
+
}
|
|
3613
|
+
}
|
|
3614
|
+
appendUsage(usage) {
|
|
3615
|
+
if (this.finalized) return;
|
|
3616
|
+
this.usage = usage;
|
|
3617
|
+
this.scheduleFlush();
|
|
3618
|
+
}
|
|
3619
|
+
finalize() {
|
|
3620
|
+
if (this.finalized) return;
|
|
3621
|
+
this.finalized = true;
|
|
3622
|
+
this.clearDebounce();
|
|
3623
|
+
this.flush();
|
|
3624
|
+
}
|
|
3625
|
+
destroy() {
|
|
3626
|
+
this.finalized = true;
|
|
3627
|
+
this.clearDebounce();
|
|
3628
|
+
}
|
|
3629
|
+
hasContent() {
|
|
3630
|
+
return this.entries.length > 0 || this.planEntries !== void 0;
|
|
3631
|
+
}
|
|
3632
|
+
snapshot() {
|
|
3633
|
+
const visible = this.entries.filter((e) => !e.hidden);
|
|
3634
|
+
const completedVisible = visible.filter(
|
|
3635
|
+
(e) => e.status === "completed" || e.status === "done"
|
|
3636
|
+
).length;
|
|
3637
|
+
const allComplete = visible.length > 0 && completedVisible === visible.length;
|
|
3638
|
+
return {
|
|
3639
|
+
entries: this.entries,
|
|
3640
|
+
planEntries: this.planEntries,
|
|
3641
|
+
usage: this.usage,
|
|
3642
|
+
visibleCount: visible.length,
|
|
3643
|
+
totalVisible: visible.length,
|
|
3644
|
+
completedVisible,
|
|
3645
|
+
allComplete,
|
|
3646
|
+
verbosity: this.verbosity
|
|
3647
|
+
};
|
|
3648
|
+
}
|
|
3649
|
+
flush() {
|
|
3650
|
+
this.clearDebounce();
|
|
3651
|
+
this.onFlush(this.snapshot());
|
|
3652
|
+
}
|
|
3653
|
+
scheduleFlush() {
|
|
3654
|
+
this.clearDebounce();
|
|
3655
|
+
this.debounceTimer = setTimeout(() => {
|
|
3656
|
+
this.debounceTimer = void 0;
|
|
3657
|
+
this.flush();
|
|
3658
|
+
}, DEBOUNCE_MS);
|
|
3659
|
+
}
|
|
3660
|
+
clearDebounce() {
|
|
3661
|
+
if (this.debounceTimer) {
|
|
3662
|
+
clearTimeout(this.debounceTimer);
|
|
3663
|
+
this.debounceTimer = void 0;
|
|
3664
|
+
}
|
|
3665
|
+
}
|
|
3666
|
+
};
|
|
3667
|
+
|
|
3254
3668
|
// src/plugins/telegram/activity.ts
|
|
3255
3669
|
var log10 = createChildLogger({ module: "telegram:activity" });
|
|
3256
3670
|
var THINKING_REFRESH_MS = 15e3;
|
|
@@ -3279,9 +3693,16 @@ var ThinkingIndicator = class {
|
|
|
3279
3693
|
disable_notification: true
|
|
3280
3694
|
})
|
|
3281
3695
|
);
|
|
3282
|
-
if (result
|
|
3283
|
-
this.
|
|
3284
|
-
|
|
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
|
+
}
|
|
3285
3706
|
}
|
|
3286
3707
|
} catch (err) {
|
|
3287
3708
|
log10.warn({ err }, "ThinkingIndicator.show() failed");
|
|
@@ -3289,11 +3710,19 @@ var ThinkingIndicator = class {
|
|
|
3289
3710
|
this.sending = false;
|
|
3290
3711
|
}
|
|
3291
3712
|
}
|
|
3292
|
-
/**
|
|
3293
|
-
dismiss() {
|
|
3713
|
+
/** Dismiss indicator: stops refresh timer and deletes the Telegram message */
|
|
3714
|
+
async dismiss() {
|
|
3715
|
+
if (this.dismissed) return;
|
|
3294
3716
|
this.dismissed = true;
|
|
3295
|
-
this.msgId = void 0;
|
|
3296
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
|
+
}
|
|
3297
3726
|
}
|
|
3298
3727
|
/** Reset for a new prompt cycle */
|
|
3299
3728
|
reset() {
|
|
@@ -3308,20 +3737,14 @@ var ThinkingIndicator = class {
|
|
|
3308
3737
|
}
|
|
3309
3738
|
const elapsed = Math.round((Date.now() - this.showTime) / 1e3);
|
|
3310
3739
|
this.sendQueue.enqueue(() => {
|
|
3311
|
-
if (this.dismissed) return Promise.resolve(void 0);
|
|
3312
|
-
return this.api.
|
|
3740
|
+
if (this.dismissed || !this.msgId) return Promise.resolve(void 0);
|
|
3741
|
+
return this.api.editMessageText(
|
|
3313
3742
|
this.chatId,
|
|
3743
|
+
this.msgId,
|
|
3314
3744
|
`\u{1F4AD} <i>Still thinking... (${elapsed}s)</i>`,
|
|
3315
|
-
{
|
|
3316
|
-
message_thread_id: this.threadId,
|
|
3317
|
-
parse_mode: "HTML",
|
|
3318
|
-
disable_notification: true
|
|
3319
|
-
}
|
|
3745
|
+
{ parse_mode: "HTML" }
|
|
3320
3746
|
);
|
|
3321
|
-
}).then((
|
|
3322
|
-
if (result && !this.dismissed) {
|
|
3323
|
-
this.msgId = result.message_id;
|
|
3324
|
-
}
|
|
3747
|
+
}).then(() => {
|
|
3325
3748
|
}).catch(() => {
|
|
3326
3749
|
});
|
|
3327
3750
|
}, THINKING_REFRESH_MS);
|
|
@@ -3333,135 +3756,67 @@ var ThinkingIndicator = class {
|
|
|
3333
3756
|
}
|
|
3334
3757
|
}
|
|
3335
3758
|
};
|
|
3336
|
-
var
|
|
3337
|
-
constructor(api, chatId, threadId, sendQueue) {
|
|
3759
|
+
var ToolCard = class {
|
|
3760
|
+
constructor(api, chatId, threadId, sendQueue, verbosity) {
|
|
3338
3761
|
this.api = api;
|
|
3339
3762
|
this.chatId = chatId;
|
|
3340
3763
|
this.threadId = threadId;
|
|
3341
3764
|
this.sendQueue = sendQueue;
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
if (this.msgId) {
|
|
3348
|
-
await this.sendQueue.enqueue(
|
|
3349
|
-
() => this.api.editMessageText(this.chatId, this.msgId, text, {
|
|
3350
|
-
parse_mode: "HTML"
|
|
3351
|
-
})
|
|
3352
|
-
);
|
|
3353
|
-
} else {
|
|
3354
|
-
const result = await this.sendQueue.enqueue(
|
|
3355
|
-
() => this.api.sendMessage(this.chatId, text, {
|
|
3356
|
-
message_thread_id: this.threadId,
|
|
3357
|
-
parse_mode: "HTML",
|
|
3358
|
-
disable_notification: true
|
|
3359
|
-
})
|
|
3360
|
-
);
|
|
3361
|
-
if (result) this.msgId = result.message_id;
|
|
3765
|
+
this.state = new ToolCardState({
|
|
3766
|
+
verbosity,
|
|
3767
|
+
onFlush: (snapshot) => {
|
|
3768
|
+
this.flushPromise = this.flushPromise.then(() => this._sendOrEdit(snapshot)).catch(() => {
|
|
3769
|
+
});
|
|
3362
3770
|
}
|
|
3363
|
-
}
|
|
3364
|
-
log10.warn({ err }, "UsageMessage.send() failed");
|
|
3365
|
-
}
|
|
3366
|
-
}
|
|
3367
|
-
getMsgId() {
|
|
3368
|
-
return this.msgId;
|
|
3369
|
-
}
|
|
3370
|
-
async delete() {
|
|
3371
|
-
if (!this.msgId) return;
|
|
3372
|
-
const id = this.msgId;
|
|
3373
|
-
this.msgId = void 0;
|
|
3374
|
-
try {
|
|
3375
|
-
await this.sendQueue.enqueue(
|
|
3376
|
-
() => this.api.deleteMessage(this.chatId, id)
|
|
3377
|
-
);
|
|
3378
|
-
} catch (err) {
|
|
3379
|
-
log10.warn({ err }, "UsageMessage.delete() failed");
|
|
3380
|
-
}
|
|
3381
|
-
}
|
|
3382
|
-
};
|
|
3383
|
-
function formatPlanCard(entries, verbosity = "medium") {
|
|
3384
|
-
if (verbosity === "medium") {
|
|
3385
|
-
const done2 = entries.filter((e) => e.status === "completed").length;
|
|
3386
|
-
return `\u{1F4CB} <b>Plan:</b> ${done2}/${entries.length} steps completed`;
|
|
3387
|
-
}
|
|
3388
|
-
const statusIcon = {
|
|
3389
|
-
completed: "\u2705",
|
|
3390
|
-
in_progress: "\u{1F504}",
|
|
3391
|
-
pending: "\u2B1C",
|
|
3392
|
-
failed: "\u274C"
|
|
3393
|
-
};
|
|
3394
|
-
const total = entries.length;
|
|
3395
|
-
const done = entries.filter((e) => e.status === "completed").length;
|
|
3396
|
-
const ratio = total > 0 ? done / total : 0;
|
|
3397
|
-
const filled = Math.round(ratio * 10);
|
|
3398
|
-
const bar = "\u2593".repeat(filled) + "\u2591".repeat(10 - filled);
|
|
3399
|
-
const pct = Math.round(ratio * 100);
|
|
3400
|
-
const header = `\u{1F4CB} <b>Plan</b>
|
|
3401
|
-
${bar} ${pct}% \xB7 ${done}/${total}`;
|
|
3402
|
-
const lines = entries.map((e, i) => {
|
|
3403
|
-
const icon = statusIcon[e.status] ?? "\u2B1C";
|
|
3404
|
-
return `${icon} ${i + 1}. ${e.content}`;
|
|
3405
|
-
});
|
|
3406
|
-
return [header, ...lines].join("\n");
|
|
3407
|
-
}
|
|
3408
|
-
var PlanCard = class {
|
|
3409
|
-
constructor(api, chatId, threadId, sendQueue) {
|
|
3410
|
-
this.api = api;
|
|
3411
|
-
this.chatId = chatId;
|
|
3412
|
-
this.threadId = threadId;
|
|
3413
|
-
this.sendQueue = sendQueue;
|
|
3771
|
+
});
|
|
3414
3772
|
}
|
|
3773
|
+
state;
|
|
3415
3774
|
msgId;
|
|
3416
|
-
flushPromise = Promise.resolve();
|
|
3417
|
-
latestEntries;
|
|
3418
3775
|
lastSentText;
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
this.
|
|
3776
|
+
flushPromise = Promise.resolve();
|
|
3777
|
+
overflowCount = 0;
|
|
3778
|
+
addTool(meta, kind, rawInput) {
|
|
3779
|
+
this.state.addTool(meta, kind, rawInput);
|
|
3423
3780
|
}
|
|
3424
|
-
|
|
3425
|
-
this.
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3781
|
+
updateTool(id, status, viewerLinks, viewerFilePath) {
|
|
3782
|
+
this.state.updateTool(id, status, viewerLinks, viewerFilePath);
|
|
3783
|
+
}
|
|
3784
|
+
updatePlan(entries) {
|
|
3785
|
+
this.state.updatePlan(entries);
|
|
3786
|
+
}
|
|
3787
|
+
appendUsage(usage) {
|
|
3788
|
+
this.state.appendUsage(usage);
|
|
3432
3789
|
}
|
|
3433
3790
|
async finalize() {
|
|
3434
|
-
|
|
3435
|
-
if (this.flushTimer) {
|
|
3436
|
-
clearTimeout(this.flushTimer);
|
|
3437
|
-
this.flushTimer = void 0;
|
|
3438
|
-
}
|
|
3439
|
-
await this.flushPromise;
|
|
3440
|
-
this.flushPromise = this.flushPromise.then(() => this._flush()).catch(() => {
|
|
3441
|
-
});
|
|
3791
|
+
this.state.finalize();
|
|
3442
3792
|
await this.flushPromise;
|
|
3443
3793
|
}
|
|
3444
3794
|
destroy() {
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3795
|
+
this.state.destroy();
|
|
3796
|
+
}
|
|
3797
|
+
hasContent() {
|
|
3798
|
+
return this.state.hasContent();
|
|
3449
3799
|
}
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3800
|
+
getMsgId() {
|
|
3801
|
+
return this.msgId;
|
|
3802
|
+
}
|
|
3803
|
+
async _sendOrEdit(snapshot) {
|
|
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);
|
|
3455
3809
|
try {
|
|
3810
|
+
const firstChunk = chunks[0];
|
|
3456
3811
|
if (this.msgId) {
|
|
3457
3812
|
await this.sendQueue.enqueue(
|
|
3458
|
-
() => this.api.editMessageText(this.chatId, this.msgId,
|
|
3813
|
+
() => this.api.editMessageText(this.chatId, this.msgId, firstChunk, {
|
|
3459
3814
|
parse_mode: "HTML"
|
|
3460
3815
|
})
|
|
3461
3816
|
);
|
|
3462
3817
|
} else {
|
|
3463
3818
|
const result = await this.sendQueue.enqueue(
|
|
3464
|
-
() => this.api.sendMessage(this.chatId,
|
|
3819
|
+
() => this.api.sendMessage(this.chatId, firstChunk, {
|
|
3465
3820
|
message_thread_id: this.threadId,
|
|
3466
3821
|
parse_mode: "HTML",
|
|
3467
3822
|
disable_notification: true
|
|
@@ -3469,83 +3824,100 @@ var PlanCard = class {
|
|
|
3469
3824
|
);
|
|
3470
3825
|
if (result) this.msgId = result.message_id;
|
|
3471
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
|
+
}
|
|
3472
3839
|
} catch (err) {
|
|
3473
|
-
log10.warn({ err }, "
|
|
3840
|
+
log10.warn({ err }, "[ToolCard] send/edit failed");
|
|
3474
3841
|
}
|
|
3475
3842
|
}
|
|
3476
3843
|
};
|
|
3477
3844
|
var ActivityTracker = class {
|
|
3478
|
-
constructor(api, chatId, threadId, sendQueue) {
|
|
3845
|
+
constructor(api, chatId, threadId, sendQueue, verbosity = "medium") {
|
|
3479
3846
|
this.api = api;
|
|
3480
3847
|
this.chatId = chatId;
|
|
3481
3848
|
this.threadId = threadId;
|
|
3482
3849
|
this.sendQueue = sendQueue;
|
|
3850
|
+
this.verbosity = verbosity;
|
|
3483
3851
|
this.thinking = new ThinkingIndicator(api, chatId, threadId, sendQueue);
|
|
3484
|
-
this.
|
|
3485
|
-
this.usage = new UsageMessage(api, chatId, threadId, sendQueue);
|
|
3852
|
+
this.toolCard = new ToolCard(api, chatId, threadId, sendQueue, verbosity);
|
|
3486
3853
|
}
|
|
3487
3854
|
isFirstEvent = true;
|
|
3488
|
-
hasPlanCard = false;
|
|
3489
3855
|
thinking;
|
|
3490
|
-
|
|
3491
|
-
|
|
3856
|
+
toolCard;
|
|
3857
|
+
verbosity;
|
|
3492
3858
|
async onNewPrompt() {
|
|
3493
3859
|
this.isFirstEvent = true;
|
|
3494
|
-
this.
|
|
3495
|
-
this.thinking.dismiss();
|
|
3860
|
+
await this.thinking.dismiss();
|
|
3496
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
|
+
);
|
|
3497
3870
|
}
|
|
3498
3871
|
async onThought() {
|
|
3499
|
-
|
|
3872
|
+
this.isFirstEvent = false;
|
|
3873
|
+
await this.sealToolCardIfNeeded();
|
|
3500
3874
|
await this.thinking.show();
|
|
3501
3875
|
}
|
|
3502
|
-
async
|
|
3503
|
-
|
|
3504
|
-
this.thinking.dismiss();
|
|
3505
|
-
this.
|
|
3506
|
-
if (verbosity) this.planCard.setVerbosity(verbosity);
|
|
3507
|
-
this.planCard.update(entries);
|
|
3876
|
+
async onTextStart() {
|
|
3877
|
+
this.isFirstEvent = false;
|
|
3878
|
+
await this.thinking.dismiss();
|
|
3879
|
+
await this.sealToolCardIfNeeded();
|
|
3508
3880
|
}
|
|
3509
|
-
async onToolCall() {
|
|
3510
|
-
|
|
3511
|
-
this.thinking.dismiss();
|
|
3881
|
+
async onToolCall(meta, kind, rawInput) {
|
|
3882
|
+
this.isFirstEvent = false;
|
|
3883
|
+
await this.thinking.dismiss();
|
|
3512
3884
|
this.thinking.reset();
|
|
3885
|
+
this.toolCard.addTool(meta, kind, rawInput);
|
|
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
|
+
);
|
|
3513
3898
|
}
|
|
3514
|
-
async
|
|
3515
|
-
|
|
3516
|
-
this.thinking.dismiss();
|
|
3899
|
+
async onToolUpdate(id, status, viewerLinks, viewerFilePath) {
|
|
3900
|
+
this.toolCard.updateTool(id, status, viewerLinks, viewerFilePath);
|
|
3517
3901
|
}
|
|
3518
|
-
async
|
|
3519
|
-
|
|
3902
|
+
async onPlan(entries) {
|
|
3903
|
+
this.isFirstEvent = false;
|
|
3904
|
+
await this.thinking.dismiss();
|
|
3905
|
+
this.toolCard.updatePlan(entries);
|
|
3520
3906
|
}
|
|
3521
|
-
|
|
3522
|
-
|
|
3907
|
+
/** @deprecated Usage is now sent as a separate message by the adapter */
|
|
3908
|
+
async sendUsage(_usage) {
|
|
3523
3909
|
}
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
await this.planCard.finalize();
|
|
3527
|
-
} else {
|
|
3528
|
-
try {
|
|
3529
|
-
await this.sendQueue.enqueue(
|
|
3530
|
-
() => this.api.sendMessage(this.chatId, "\u2705 <b>Done</b>", {
|
|
3531
|
-
message_thread_id: this.threadId,
|
|
3532
|
-
parse_mode: "HTML",
|
|
3533
|
-
disable_notification: true
|
|
3534
|
-
})
|
|
3535
|
-
);
|
|
3536
|
-
} catch (err) {
|
|
3537
|
-
log10.warn({ err }, "ActivityTracker.onComplete() Done send failed");
|
|
3538
|
-
}
|
|
3539
|
-
}
|
|
3910
|
+
getToolCardMsgId() {
|
|
3911
|
+
return this.toolCard.getMsgId();
|
|
3540
3912
|
}
|
|
3541
|
-
|
|
3542
|
-
this.thinking.dismiss();
|
|
3543
|
-
this.
|
|
3913
|
+
async cleanup() {
|
|
3914
|
+
await this.thinking.dismiss();
|
|
3915
|
+
await this.toolCard.finalize();
|
|
3916
|
+
this.toolCard.destroy();
|
|
3544
3917
|
}
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
this.
|
|
3548
|
-
await this.usage.delete();
|
|
3918
|
+
destroy() {
|
|
3919
|
+
void this.thinking.dismiss();
|
|
3920
|
+
this.toolCard.destroy();
|
|
3549
3921
|
}
|
|
3550
3922
|
};
|
|
3551
3923
|
|
|
@@ -3804,143 +4176,6 @@ function setupActionCallbacks(bot, core, chatId, getAssistantSessionId) {
|
|
|
3804
4176
|
});
|
|
3805
4177
|
}
|
|
3806
4178
|
|
|
3807
|
-
// src/core/adapter-primitives/primitives/tool-call-tracker.ts
|
|
3808
|
-
var ToolCallTracker = class {
|
|
3809
|
-
sessions = /* @__PURE__ */ new Map();
|
|
3810
|
-
track(sessionId, meta, messageId) {
|
|
3811
|
-
if (!this.sessions.has(sessionId)) {
|
|
3812
|
-
this.sessions.set(sessionId, /* @__PURE__ */ new Map());
|
|
3813
|
-
}
|
|
3814
|
-
this.sessions.get(sessionId).set(meta.id, { ...meta, messageId });
|
|
3815
|
-
}
|
|
3816
|
-
update(sessionId, toolId, status, patch) {
|
|
3817
|
-
const tool = this.sessions.get(sessionId)?.get(toolId);
|
|
3818
|
-
if (!tool) return null;
|
|
3819
|
-
tool.status = status;
|
|
3820
|
-
if (patch?.viewerLinks) tool.viewerLinks = patch.viewerLinks;
|
|
3821
|
-
if (patch?.viewerFilePath) tool.viewerFilePath = patch.viewerFilePath;
|
|
3822
|
-
if (patch?.name) tool.name = patch.name;
|
|
3823
|
-
if (patch?.kind) tool.kind = patch.kind;
|
|
3824
|
-
return tool;
|
|
3825
|
-
}
|
|
3826
|
-
getActive(sessionId) {
|
|
3827
|
-
const session = this.sessions.get(sessionId);
|
|
3828
|
-
return session ? [...session.values()] : [];
|
|
3829
|
-
}
|
|
3830
|
-
clear(sessionId) {
|
|
3831
|
-
this.sessions.delete(sessionId);
|
|
3832
|
-
}
|
|
3833
|
-
clearAll() {
|
|
3834
|
-
this.sessions.clear();
|
|
3835
|
-
}
|
|
3836
|
-
};
|
|
3837
|
-
|
|
3838
|
-
// src/plugins/telegram/tool-call-tracker.ts
|
|
3839
|
-
var log11 = createChildLogger({ module: "tool-call-tracker" });
|
|
3840
|
-
var TelegramToolCallTracker = class {
|
|
3841
|
-
constructor(bot, chatId, sendQueue) {
|
|
3842
|
-
this.bot = bot;
|
|
3843
|
-
this.chatId = chatId;
|
|
3844
|
-
this.sendQueue = sendQueue;
|
|
3845
|
-
}
|
|
3846
|
-
tracker = new ToolCallTracker();
|
|
3847
|
-
/** Platform-specific ready-promise per tool call, keyed by `${sessionId}:${toolId}`. */
|
|
3848
|
-
readyMap = /* @__PURE__ */ new Map();
|
|
3849
|
-
async trackNewCall(sessionId, threadId, meta, verbosity = "medium") {
|
|
3850
|
-
let resolveReady;
|
|
3851
|
-
const ready = new Promise((r) => {
|
|
3852
|
-
resolveReady = r;
|
|
3853
|
-
});
|
|
3854
|
-
const key = `${sessionId}:${meta.id}`;
|
|
3855
|
-
this.readyMap.set(key, { ready });
|
|
3856
|
-
this.tracker.track(sessionId, meta, "0");
|
|
3857
|
-
try {
|
|
3858
|
-
const msg = await this.sendQueue.enqueue(
|
|
3859
|
-
() => this.bot.api.sendMessage(this.chatId, formatToolCall(meta, verbosity), {
|
|
3860
|
-
message_thread_id: threadId,
|
|
3861
|
-
parse_mode: "HTML",
|
|
3862
|
-
disable_notification: true
|
|
3863
|
-
})
|
|
3864
|
-
);
|
|
3865
|
-
const tracked = this.tracker.update(sessionId, meta.id, meta.status ?? "running");
|
|
3866
|
-
if (tracked) {
|
|
3867
|
-
tracked.messageId = String(msg.message_id);
|
|
3868
|
-
}
|
|
3869
|
-
} finally {
|
|
3870
|
-
resolveReady();
|
|
3871
|
-
}
|
|
3872
|
-
}
|
|
3873
|
-
async updateCall(sessionId, meta, verbosity = "medium") {
|
|
3874
|
-
const key = `${sessionId}:${meta.id}`;
|
|
3875
|
-
const readyState = this.readyMap.get(key);
|
|
3876
|
-
const tracked = this.tracker.update(sessionId, meta.id, meta.status, {
|
|
3877
|
-
viewerLinks: meta.viewerLinks,
|
|
3878
|
-
viewerFilePath: meta.viewerFilePath,
|
|
3879
|
-
name: meta.name,
|
|
3880
|
-
kind: meta.kind
|
|
3881
|
-
});
|
|
3882
|
-
if (!tracked) return;
|
|
3883
|
-
const isTerminal = meta.status === "completed" || meta.status === "failed";
|
|
3884
|
-
if (!isTerminal) return;
|
|
3885
|
-
if (readyState) {
|
|
3886
|
-
await readyState.ready;
|
|
3887
|
-
}
|
|
3888
|
-
const msgId = Number(tracked.messageId);
|
|
3889
|
-
log11.debug(
|
|
3890
|
-
{
|
|
3891
|
-
toolId: meta.id,
|
|
3892
|
-
status: meta.status,
|
|
3893
|
-
hasViewerLinks: !!tracked.viewerLinks,
|
|
3894
|
-
viewerLinks: tracked.viewerLinks,
|
|
3895
|
-
name: tracked.name,
|
|
3896
|
-
msgId
|
|
3897
|
-
},
|
|
3898
|
-
"Tool completed, preparing edit"
|
|
3899
|
-
);
|
|
3900
|
-
const merged = {
|
|
3901
|
-
id: meta.id,
|
|
3902
|
-
name: tracked.name,
|
|
3903
|
-
kind: tracked.kind,
|
|
3904
|
-
rawInput: tracked.rawInput,
|
|
3905
|
-
viewerLinks: tracked.viewerLinks,
|
|
3906
|
-
viewerFilePath: tracked.viewerFilePath,
|
|
3907
|
-
displaySummary: tracked.displaySummary,
|
|
3908
|
-
displayTitle: tracked.displayTitle,
|
|
3909
|
-
displayKind: tracked.displayKind,
|
|
3910
|
-
status: meta.status,
|
|
3911
|
-
content: meta.content
|
|
3912
|
-
};
|
|
3913
|
-
const formattedText = formatToolUpdate(merged, verbosity);
|
|
3914
|
-
try {
|
|
3915
|
-
await this.sendQueue.enqueue(
|
|
3916
|
-
() => this.bot.api.editMessageText(
|
|
3917
|
-
this.chatId,
|
|
3918
|
-
msgId,
|
|
3919
|
-
formattedText,
|
|
3920
|
-
{ parse_mode: "HTML" }
|
|
3921
|
-
)
|
|
3922
|
-
);
|
|
3923
|
-
} catch (err) {
|
|
3924
|
-
log11.warn(
|
|
3925
|
-
{
|
|
3926
|
-
err,
|
|
3927
|
-
msgId,
|
|
3928
|
-
textLen: formattedText.length,
|
|
3929
|
-
hasViewerLinks: !!merged.viewerLinks
|
|
3930
|
-
},
|
|
3931
|
-
"Tool update edit failed"
|
|
3932
|
-
);
|
|
3933
|
-
}
|
|
3934
|
-
}
|
|
3935
|
-
cleanup(sessionId) {
|
|
3936
|
-
const active = this.tracker.getActive(sessionId);
|
|
3937
|
-
for (const tool of active) {
|
|
3938
|
-
this.readyMap.delete(`${sessionId}:${tool.id}`);
|
|
3939
|
-
}
|
|
3940
|
-
this.tracker.clear(sessionId);
|
|
3941
|
-
}
|
|
3942
|
-
};
|
|
3943
|
-
|
|
3944
4179
|
// src/plugins/telegram/streaming.ts
|
|
3945
4180
|
var FLUSH_INTERVAL = 5e3;
|
|
3946
4181
|
var MessageDraft = class {
|
|
@@ -4132,6 +4367,7 @@ var DraftManager = class {
|
|
|
4132
4367
|
}
|
|
4133
4368
|
drafts = /* @__PURE__ */ new Map();
|
|
4134
4369
|
textBuffers = /* @__PURE__ */ new Map();
|
|
4370
|
+
finalizedDrafts = /* @__PURE__ */ new Map();
|
|
4135
4371
|
getOrCreate(sessionId, threadId) {
|
|
4136
4372
|
let draft = this.drafts.get(sessionId);
|
|
4137
4373
|
if (!draft) {
|
|
@@ -4167,6 +4403,9 @@ var DraftManager = class {
|
|
|
4167
4403
|
if (!draft) return;
|
|
4168
4404
|
this.drafts.delete(sessionId);
|
|
4169
4405
|
const finalMsgId = await draft.finalize();
|
|
4406
|
+
if (finalMsgId) {
|
|
4407
|
+
this.finalizedDrafts.set(sessionId, { messageId: finalMsgId, draft });
|
|
4408
|
+
}
|
|
4170
4409
|
if (assistantSessionId && sessionId === assistantSessionId) {
|
|
4171
4410
|
const fullText = this.textBuffers.get(sessionId);
|
|
4172
4411
|
this.textBuffers.delete(sessionId);
|
|
@@ -4189,14 +4428,30 @@ var DraftManager = class {
|
|
|
4189
4428
|
this.textBuffers.delete(sessionId);
|
|
4190
4429
|
}
|
|
4191
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
|
+
}
|
|
4192
4446
|
cleanup(sessionId) {
|
|
4193
4447
|
this.drafts.delete(sessionId);
|
|
4194
4448
|
this.textBuffers.delete(sessionId);
|
|
4449
|
+
this.finalizedDrafts.delete(sessionId);
|
|
4195
4450
|
}
|
|
4196
4451
|
};
|
|
4197
4452
|
|
|
4198
4453
|
// src/plugins/telegram/skill-command-manager.ts
|
|
4199
|
-
var
|
|
4454
|
+
var log11 = createChildLogger({ module: "skill-commands" });
|
|
4200
4455
|
var SkillCommandManager = class {
|
|
4201
4456
|
// sessionId → pinned msgId
|
|
4202
4457
|
constructor(bot, chatId, sendQueue, sessionManager) {
|
|
@@ -4262,7 +4517,7 @@ var SkillCommandManager = class {
|
|
|
4262
4517
|
disable_notification: true
|
|
4263
4518
|
});
|
|
4264
4519
|
} catch (err) {
|
|
4265
|
-
|
|
4520
|
+
log11.error({ err, sessionId }, "Failed to send skill commands");
|
|
4266
4521
|
}
|
|
4267
4522
|
}
|
|
4268
4523
|
async cleanup(sessionId) {
|
|
@@ -4290,26 +4545,263 @@ var SkillCommandManager = class {
|
|
|
4290
4545
|
}
|
|
4291
4546
|
};
|
|
4292
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
|
+
|
|
4293
4773
|
// src/plugins/telegram/renderer.ts
|
|
4294
4774
|
var TelegramRenderer = class extends BaseRenderer {
|
|
4295
4775
|
renderToolCall(content, verbosity) {
|
|
4296
4776
|
const meta = content.metadata ?? {};
|
|
4297
|
-
return {
|
|
4777
|
+
return {
|
|
4778
|
+
body: formatToolCall(meta, verbosity),
|
|
4779
|
+
format: "html"
|
|
4780
|
+
};
|
|
4298
4781
|
}
|
|
4299
4782
|
renderToolUpdate(content, verbosity) {
|
|
4300
4783
|
const meta = content.metadata ?? {};
|
|
4301
|
-
return {
|
|
4784
|
+
return {
|
|
4785
|
+
body: formatToolUpdate(meta, verbosity),
|
|
4786
|
+
format: "html"
|
|
4787
|
+
};
|
|
4302
4788
|
}
|
|
4303
|
-
renderPlan(content
|
|
4789
|
+
renderPlan(content) {
|
|
4304
4790
|
const meta = content.metadata;
|
|
4305
|
-
return {
|
|
4791
|
+
return {
|
|
4792
|
+
body: formatPlan({ entries: meta?.entries ?? [] }),
|
|
4793
|
+
format: "html"
|
|
4794
|
+
};
|
|
4306
4795
|
}
|
|
4307
4796
|
renderUsage(content, verbosity) {
|
|
4308
4797
|
const meta = content.metadata;
|
|
4309
4798
|
return { body: formatUsage(meta ?? {}, verbosity), format: "html" };
|
|
4310
4799
|
}
|
|
4311
4800
|
renderError(content) {
|
|
4312
|
-
return {
|
|
4801
|
+
return {
|
|
4802
|
+
body: `\u274C <b>Error:</b> ${escapeHtml(content.text)}`,
|
|
4803
|
+
format: "html"
|
|
4804
|
+
};
|
|
4313
4805
|
}
|
|
4314
4806
|
renderNotification(notification) {
|
|
4315
4807
|
const emoji = {
|
|
@@ -4329,19 +4821,25 @@ var TelegramRenderer = class extends BaseRenderer {
|
|
|
4329
4821
|
}
|
|
4330
4822
|
renderModeChange(content) {
|
|
4331
4823
|
const modeId = content.metadata?.modeId ?? "";
|
|
4332
|
-
return {
|
|
4824
|
+
return {
|
|
4825
|
+
body: `\u{1F504} <b>Mode:</b> ${escapeHtml(String(modeId))}`,
|
|
4826
|
+
format: "html"
|
|
4827
|
+
};
|
|
4333
4828
|
}
|
|
4334
4829
|
renderConfigUpdate() {
|
|
4335
4830
|
return { body: "\u2699\uFE0F <b>Config updated</b>", format: "html" };
|
|
4336
4831
|
}
|
|
4337
4832
|
renderModelUpdate(content) {
|
|
4338
4833
|
const modelId = content.metadata?.modelId ?? "";
|
|
4339
|
-
return {
|
|
4834
|
+
return {
|
|
4835
|
+
body: `\u{1F916} <b>Model:</b> ${escapeHtml(String(modelId))}`,
|
|
4836
|
+
format: "html"
|
|
4837
|
+
};
|
|
4340
4838
|
}
|
|
4341
4839
|
};
|
|
4342
4840
|
|
|
4343
4841
|
// src/plugins/telegram/adapter.ts
|
|
4344
|
-
var
|
|
4842
|
+
var log12 = createChildLogger({ module: "telegram" });
|
|
4345
4843
|
function patchedFetch(input, init) {
|
|
4346
4844
|
if (init?.signal && !(init.signal instanceof AbortSignal)) {
|
|
4347
4845
|
const nativeController = new AbortController();
|
|
@@ -4377,7 +4875,6 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4377
4875
|
sendQueue = new SendQueue({ minInterval: 3e3 });
|
|
4378
4876
|
_sessionThreadIds = /* @__PURE__ */ new Map();
|
|
4379
4877
|
// Extracted managers
|
|
4380
|
-
toolTracker;
|
|
4381
4878
|
draftManager;
|
|
4382
4879
|
skillManager;
|
|
4383
4880
|
fileService;
|
|
@@ -4391,24 +4888,26 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4391
4888
|
}
|
|
4392
4889
|
return threadId;
|
|
4393
4890
|
}
|
|
4394
|
-
getOrCreateTracker(sessionId, threadId) {
|
|
4891
|
+
getOrCreateTracker(sessionId, threadId, verbosity = "medium") {
|
|
4395
4892
|
let tracker = this.sessionTrackers.get(sessionId);
|
|
4396
4893
|
if (!tracker) {
|
|
4397
4894
|
tracker = new ActivityTracker(
|
|
4398
4895
|
this.bot.api,
|
|
4399
4896
|
this.telegramConfig.chatId,
|
|
4400
4897
|
threadId,
|
|
4401
|
-
this.sendQueue
|
|
4898
|
+
this.sendQueue,
|
|
4899
|
+
verbosity
|
|
4402
4900
|
);
|
|
4403
4901
|
this.sessionTrackers.set(sessionId, tracker);
|
|
4404
4902
|
}
|
|
4405
4903
|
return tracker;
|
|
4406
4904
|
}
|
|
4407
4905
|
constructor(core, config) {
|
|
4408
|
-
super(
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4906
|
+
super({ configManager: core.configManager }, {
|
|
4907
|
+
...config,
|
|
4908
|
+
maxMessageLength: 4096,
|
|
4909
|
+
enabled: config.enabled ?? true
|
|
4910
|
+
});
|
|
4412
4911
|
this.core = core;
|
|
4413
4912
|
this.telegramConfig = config;
|
|
4414
4913
|
}
|
|
@@ -4420,11 +4919,6 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4420
4919
|
}
|
|
4421
4920
|
});
|
|
4422
4921
|
this.fileService = this.core.fileService;
|
|
4423
|
-
this.toolTracker = new TelegramToolCallTracker(
|
|
4424
|
-
this.bot,
|
|
4425
|
-
this.telegramConfig.chatId,
|
|
4426
|
-
this.sendQueue
|
|
4427
|
-
);
|
|
4428
4922
|
this.draftManager = new DraftManager(
|
|
4429
4923
|
this.bot,
|
|
4430
4924
|
this.telegramConfig.chatId,
|
|
@@ -4438,7 +4932,7 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4438
4932
|
);
|
|
4439
4933
|
this.bot.catch((err) => {
|
|
4440
4934
|
const rootCause = err.error instanceof Error ? err.error : err;
|
|
4441
|
-
|
|
4935
|
+
log12.error({ err: rootCause }, "Telegram bot error");
|
|
4442
4936
|
});
|
|
4443
4937
|
this.bot.api.config.use(async (prev, method, payload, signal) => {
|
|
4444
4938
|
const maxRetries = 3;
|
|
@@ -4456,7 +4950,7 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4456
4950
|
if (rateLimitedMethods.includes(method)) {
|
|
4457
4951
|
this.sendQueue.onRateLimited();
|
|
4458
4952
|
}
|
|
4459
|
-
|
|
4953
|
+
log12.warn(
|
|
4460
4954
|
{ method, retryAfter, attempt: attempt + 1 },
|
|
4461
4955
|
"Rate limited by Telegram, retrying"
|
|
4462
4956
|
);
|
|
@@ -4503,7 +4997,9 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4503
4997
|
this.bot.on("message:text", async (ctx, next) => {
|
|
4504
4998
|
const text = ctx.message?.text;
|
|
4505
4999
|
if (!text?.startsWith("/")) return next();
|
|
4506
|
-
const registry = this.core.lifecycleManager?.serviceRegistry?.get(
|
|
5000
|
+
const registry = this.core.lifecycleManager?.serviceRegistry?.get(
|
|
5001
|
+
"command-registry"
|
|
5002
|
+
);
|
|
4507
5003
|
if (!registry) return next();
|
|
4508
5004
|
const rawCommand = text.split(" ")[0].slice(1);
|
|
4509
5005
|
const atIdx = rawCommand.indexOf("@");
|
|
@@ -4516,7 +5012,10 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4516
5012
|
const chatId = ctx.chat.id;
|
|
4517
5013
|
const topicId = ctx.message.message_thread_id;
|
|
4518
5014
|
try {
|
|
4519
|
-
const sessionId = topicId != null ? this.core.sessionManager.getSessionByThread(
|
|
5015
|
+
const sessionId = topicId != null ? this.core.sessionManager.getSessionByThread(
|
|
5016
|
+
"telegram",
|
|
5017
|
+
String(topicId)
|
|
5018
|
+
)?.id ?? null : null;
|
|
4520
5019
|
const response = await registry.execute(text, {
|
|
4521
5020
|
raw: "",
|
|
4522
5021
|
sessionId,
|
|
@@ -4526,7 +5025,11 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4526
5025
|
if (typeof content === "string") {
|
|
4527
5026
|
await ctx.reply(content);
|
|
4528
5027
|
} else if (typeof content === "object" && content !== null && "type" in content) {
|
|
4529
|
-
await this.renderCommandResponse(
|
|
5028
|
+
await this.renderCommandResponse(
|
|
5029
|
+
content,
|
|
5030
|
+
chatId,
|
|
5031
|
+
topicId
|
|
5032
|
+
);
|
|
4530
5033
|
}
|
|
4531
5034
|
}
|
|
4532
5035
|
});
|
|
@@ -4541,12 +5044,17 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4541
5044
|
this.bot.callbackQuery(/^c\//, async (ctx) => {
|
|
4542
5045
|
const data = ctx.callbackQuery.data;
|
|
4543
5046
|
const command = this.fromCallbackData(data);
|
|
4544
|
-
const registry = this.core.lifecycleManager?.serviceRegistry?.get(
|
|
5047
|
+
const registry = this.core.lifecycleManager?.serviceRegistry?.get(
|
|
5048
|
+
"command-registry"
|
|
5049
|
+
);
|
|
4545
5050
|
if (!registry) return;
|
|
4546
5051
|
const chatId = ctx.chat.id;
|
|
4547
5052
|
const topicId = ctx.callbackQuery.message?.message_thread_id;
|
|
4548
5053
|
try {
|
|
4549
|
-
const sessionId = topicId != null ? this.core.sessionManager.getSessionByThread(
|
|
5054
|
+
const sessionId = topicId != null ? this.core.sessionManager.getSessionByThread(
|
|
5055
|
+
"telegram",
|
|
5056
|
+
String(topicId)
|
|
5057
|
+
)?.id ?? null : null;
|
|
4550
5058
|
const response = await registry.execute(command, {
|
|
4551
5059
|
raw: "",
|
|
4552
5060
|
sessionId,
|
|
@@ -4644,7 +5152,7 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4644
5152
|
});
|
|
4645
5153
|
return;
|
|
4646
5154
|
}
|
|
4647
|
-
const { getAgentCapabilities } = await import("./agent-registry-
|
|
5155
|
+
const { getAgentCapabilities } = await import("./agent-registry-YOGP656W.js");
|
|
4648
5156
|
const caps = getAgentCapabilities(agentName);
|
|
4649
5157
|
if (!caps.supportsResume || !caps.resumeCommand) {
|
|
4650
5158
|
await ctx.reply("This agent does not support session transfer.", {
|
|
@@ -4666,7 +5174,7 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4666
5174
|
this.setupRoutes();
|
|
4667
5175
|
this.bot.start({
|
|
4668
5176
|
allowed_updates: ["message", "callback_query"],
|
|
4669
|
-
onStart: () =>
|
|
5177
|
+
onStart: () => log12.info(
|
|
4670
5178
|
{ chatId: this.telegramConfig.chatId },
|
|
4671
5179
|
"Telegram bot started"
|
|
4672
5180
|
)
|
|
@@ -4690,10 +5198,10 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4690
5198
|
reply_markup: buildMenuKeyboard()
|
|
4691
5199
|
});
|
|
4692
5200
|
} catch (err) {
|
|
4693
|
-
|
|
5201
|
+
log12.warn({ err }, "Failed to send welcome message");
|
|
4694
5202
|
}
|
|
4695
5203
|
try {
|
|
4696
|
-
|
|
5204
|
+
log12.info("Spawning assistant session...");
|
|
4697
5205
|
const { session, ready } = await spawnAssistant(
|
|
4698
5206
|
this.core,
|
|
4699
5207
|
this,
|
|
@@ -4701,19 +5209,19 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4701
5209
|
);
|
|
4702
5210
|
this.assistantSession = session;
|
|
4703
5211
|
this.assistantInitializing = true;
|
|
4704
|
-
|
|
5212
|
+
log12.info(
|
|
4705
5213
|
{ sessionId: session.id },
|
|
4706
5214
|
"Assistant session ready, system prompt running in background"
|
|
4707
5215
|
);
|
|
4708
5216
|
ready.then(() => {
|
|
4709
5217
|
this.assistantInitializing = false;
|
|
4710
|
-
|
|
5218
|
+
log12.info(
|
|
4711
5219
|
{ sessionId: session.id },
|
|
4712
5220
|
"Assistant ready for user messages"
|
|
4713
5221
|
);
|
|
4714
5222
|
});
|
|
4715
5223
|
} catch (err) {
|
|
4716
|
-
|
|
5224
|
+
log12.error({ err }, "Failed to spawn assistant");
|
|
4717
5225
|
this.bot.api.sendMessage(
|
|
4718
5226
|
this.telegramConfig.chatId,
|
|
4719
5227
|
`\u26A0\uFE0F <b>Failed to start assistant session.</b>
|
|
@@ -4725,11 +5233,16 @@ var TelegramAdapter = class extends MessagingAdapter {
|
|
|
4725
5233
|
}
|
|
4726
5234
|
}
|
|
4727
5235
|
async stop() {
|
|
5236
|
+
for (const tracker of this.sessionTrackers.values()) {
|
|
5237
|
+
tracker.destroy();
|
|
5238
|
+
}
|
|
5239
|
+
this.sessionTrackers.clear();
|
|
5240
|
+
this.sendQueue.clear();
|
|
4728
5241
|
if (this.assistantSession) {
|
|
4729
5242
|
await this.assistantSession.destroy();
|
|
4730
5243
|
}
|
|
4731
5244
|
await this.bot.stop();
|
|
4732
|
-
|
|
5245
|
+
log12.info("Telegram bot stopped");
|
|
4733
5246
|
}
|
|
4734
5247
|
// --- CommandRegistry response rendering ---
|
|
4735
5248
|
async renderCommandResponse(response, chatId, topicId) {
|
|
@@ -4857,7 +5370,7 @@ ${lines.join("\n")}`;
|
|
|
4857
5370
|
ctx.replyWithChatAction("typing").catch(() => {
|
|
4858
5371
|
});
|
|
4859
5372
|
handleAssistantMessage(this.assistantSession, forwardText).catch(
|
|
4860
|
-
(err) =>
|
|
5373
|
+
(err) => log12.error({ err }, "Assistant error")
|
|
4861
5374
|
);
|
|
4862
5375
|
return;
|
|
4863
5376
|
}
|
|
@@ -4878,7 +5391,7 @@ ${lines.join("\n")}`;
|
|
|
4878
5391
|
threadId: String(threadId),
|
|
4879
5392
|
userId: String(ctx.from.id),
|
|
4880
5393
|
text: forwardText
|
|
4881
|
-
}).catch((err) =>
|
|
5394
|
+
}).catch((err) => log12.error({ err }, "handleMessage error"));
|
|
4882
5395
|
});
|
|
4883
5396
|
this.bot.on("message:photo", async (ctx) => {
|
|
4884
5397
|
const threadId = ctx.message.message_thread_id;
|
|
@@ -4957,7 +5470,7 @@ ${lines.join("\n")}`;
|
|
|
4957
5470
|
if (session.archiving) return;
|
|
4958
5471
|
const threadId = Number(session.threadId);
|
|
4959
5472
|
if (!threadId || isNaN(threadId)) {
|
|
4960
|
-
|
|
5473
|
+
log12.warn(
|
|
4961
5474
|
{ sessionId, threadId: session.threadId },
|
|
4962
5475
|
"Session has no valid threadId, skipping message"
|
|
4963
5476
|
);
|
|
@@ -4989,15 +5502,9 @@ ${lines.join("\n")}`;
|
|
|
4989
5502
|
async handleToolCall(sessionId, content, verbosity) {
|
|
4990
5503
|
const threadId = this.getThreadId(sessionId);
|
|
4991
5504
|
const meta = content.metadata ?? {};
|
|
4992
|
-
const tracker = this.getOrCreateTracker(sessionId, threadId);
|
|
4993
|
-
await
|
|
4994
|
-
await
|
|
4995
|
-
sessionId,
|
|
4996
|
-
this.assistantSession?.id
|
|
4997
|
-
);
|
|
4998
|
-
await this.toolTracker.trackNewCall(
|
|
4999
|
-
sessionId,
|
|
5000
|
-
threadId,
|
|
5505
|
+
const tracker = this.getOrCreateTracker(sessionId, threadId, verbosity);
|
|
5506
|
+
await this.draftManager.finalize(sessionId, this.assistantSession?.id);
|
|
5507
|
+
await tracker.onToolCall(
|
|
5001
5508
|
{
|
|
5002
5509
|
id: meta.id ?? "",
|
|
5003
5510
|
name: meta.name ?? content.text ?? "Tool",
|
|
@@ -5011,58 +5518,57 @@ ${lines.join("\n")}`;
|
|
|
5011
5518
|
displayTitle: meta.displayTitle,
|
|
5012
5519
|
displayKind: meta.displayKind
|
|
5013
5520
|
},
|
|
5014
|
-
|
|
5521
|
+
String(meta.kind ?? ""),
|
|
5522
|
+
meta.rawInput
|
|
5015
5523
|
);
|
|
5016
5524
|
}
|
|
5017
5525
|
async handleToolUpdate(sessionId, content, verbosity) {
|
|
5526
|
+
const threadId = this.getThreadId(sessionId);
|
|
5018
5527
|
const meta = content.metadata ?? {};
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
status: meta.status ?? "completed",
|
|
5026
|
-
content: meta.content,
|
|
5027
|
-
rawInput: meta.rawInput,
|
|
5028
|
-
viewerLinks: meta.viewerLinks,
|
|
5029
|
-
viewerFilePath: meta.viewerFilePath,
|
|
5030
|
-
displaySummary: meta.displaySummary,
|
|
5031
|
-
displayTitle: meta.displayTitle,
|
|
5032
|
-
displayKind: meta.displayKind
|
|
5033
|
-
},
|
|
5034
|
-
verbosity
|
|
5528
|
+
const tracker = this.getOrCreateTracker(sessionId, threadId, verbosity);
|
|
5529
|
+
await tracker.onToolUpdate(
|
|
5530
|
+
meta.id ?? "",
|
|
5531
|
+
meta.status ?? "completed",
|
|
5532
|
+
meta.viewerLinks,
|
|
5533
|
+
meta.viewerFilePath
|
|
5035
5534
|
);
|
|
5036
5535
|
}
|
|
5037
5536
|
async handlePlan(sessionId, content, verbosity) {
|
|
5038
5537
|
const threadId = this.getThreadId(sessionId);
|
|
5039
5538
|
const meta = content.metadata ?? {};
|
|
5040
5539
|
const entries = meta.entries ?? [];
|
|
5041
|
-
const tracker = this.getOrCreateTracker(sessionId, threadId);
|
|
5540
|
+
const tracker = this.getOrCreateTracker(sessionId, threadId, verbosity);
|
|
5042
5541
|
await tracker.onPlan(
|
|
5043
5542
|
entries.map((e) => ({
|
|
5044
5543
|
content: e.content,
|
|
5045
5544
|
status: e.status,
|
|
5046
5545
|
priority: e.priority ?? "medium"
|
|
5047
|
-
}))
|
|
5048
|
-
verbosity
|
|
5546
|
+
}))
|
|
5049
5547
|
);
|
|
5050
5548
|
}
|
|
5051
5549
|
async handleUsage(sessionId, content, verbosity) {
|
|
5052
5550
|
const threadId = this.getThreadId(sessionId);
|
|
5053
5551
|
const meta = content.metadata;
|
|
5054
|
-
await this.draftManager.finalize(
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5552
|
+
await this.draftManager.finalize(sessionId, this.assistantSession?.id);
|
|
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
|
+
}
|
|
5060
5567
|
if (this.notificationTopicId && sessionId !== this.assistantSession?.id) {
|
|
5061
5568
|
const sess = this.core.sessionManager.getSession(sessionId);
|
|
5062
5569
|
const sessionName = sess?.name || "Session";
|
|
5063
5570
|
const chatIdStr = String(this.telegramConfig.chatId);
|
|
5064
5571
|
const numericId = chatIdStr.startsWith("-100") ? chatIdStr.slice(4) : chatIdStr.replace("-", "");
|
|
5065
|
-
const usageMsgId = tracker.getUsageMsgId();
|
|
5066
5572
|
const deepLink = usageMsgId ? `https://t.me/c/${numericId}/${threadId}/${usageMsgId}` : `https://t.me/c/${numericId}/${threadId}`;
|
|
5067
5573
|
const text = `\u2705 <b>${escapeHtml(sessionName)}</b>
|
|
5068
5574
|
Task completed.
|
|
@@ -5083,7 +5589,7 @@ Task completed.
|
|
|
5083
5589
|
if (!content.attachment) return;
|
|
5084
5590
|
const { attachment } = content;
|
|
5085
5591
|
if (attachment.size > 50 * 1024 * 1024) {
|
|
5086
|
-
|
|
5592
|
+
log12.warn(
|
|
5087
5593
|
{
|
|
5088
5594
|
sessionId,
|
|
5089
5595
|
fileName: attachment.fileName,
|
|
@@ -5127,7 +5633,7 @@ Task completed.
|
|
|
5127
5633
|
);
|
|
5128
5634
|
}
|
|
5129
5635
|
} catch (err) {
|
|
5130
|
-
|
|
5636
|
+
log12.error(
|
|
5131
5637
|
{ err, sessionId, fileName: attachment.fileName },
|
|
5132
5638
|
"Failed to send attachment"
|
|
5133
5639
|
);
|
|
@@ -5135,38 +5641,26 @@ Task completed.
|
|
|
5135
5641
|
}
|
|
5136
5642
|
async handleSessionEnd(sessionId, _content) {
|
|
5137
5643
|
const threadId = this.getThreadId(sessionId);
|
|
5138
|
-
await this.draftManager.finalize(
|
|
5139
|
-
sessionId,
|
|
5140
|
-
this.assistantSession?.id
|
|
5141
|
-
);
|
|
5644
|
+
await this.draftManager.finalize(sessionId, this.assistantSession?.id);
|
|
5142
5645
|
this.draftManager.cleanup(sessionId);
|
|
5143
|
-
this.toolTracker.cleanup(sessionId);
|
|
5144
5646
|
await this.skillManager.cleanup(sessionId);
|
|
5145
5647
|
const tracker = this.sessionTrackers.get(sessionId);
|
|
5146
5648
|
if (tracker) {
|
|
5147
|
-
await tracker.
|
|
5148
|
-
tracker.destroy();
|
|
5649
|
+
await tracker.cleanup();
|
|
5149
5650
|
this.sessionTrackers.delete(sessionId);
|
|
5150
5651
|
} else {
|
|
5151
5652
|
await this.sendQueue.enqueue(
|
|
5152
|
-
() => this.bot.api.sendMessage(
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
parse_mode: "HTML",
|
|
5158
|
-
disable_notification: true
|
|
5159
|
-
}
|
|
5160
|
-
)
|
|
5653
|
+
() => this.bot.api.sendMessage(this.telegramConfig.chatId, `\u2705 <b>Done</b>`, {
|
|
5654
|
+
message_thread_id: threadId,
|
|
5655
|
+
parse_mode: "HTML",
|
|
5656
|
+
disable_notification: true
|
|
5657
|
+
})
|
|
5161
5658
|
);
|
|
5162
5659
|
}
|
|
5163
5660
|
}
|
|
5164
5661
|
async handleError(sessionId, content) {
|
|
5165
5662
|
const threadId = this.getThreadId(sessionId);
|
|
5166
|
-
await this.draftManager.finalize(
|
|
5167
|
-
sessionId,
|
|
5168
|
-
this.assistantSession?.id
|
|
5169
|
-
);
|
|
5663
|
+
await this.draftManager.finalize(sessionId, this.assistantSession?.id);
|
|
5170
5664
|
const tracker = this.sessionTrackers.get(sessionId);
|
|
5171
5665
|
if (tracker) {
|
|
5172
5666
|
tracker.destroy();
|
|
@@ -5199,7 +5693,7 @@ Task completed.
|
|
|
5199
5693
|
);
|
|
5200
5694
|
}
|
|
5201
5695
|
async sendPermissionRequest(sessionId, request) {
|
|
5202
|
-
|
|
5696
|
+
log12.info({ sessionId, requestId: request.id }, "Permission request sent");
|
|
5203
5697
|
const session = this.core.sessionManager.getSession(sessionId);
|
|
5204
5698
|
if (!session) return;
|
|
5205
5699
|
await this.sendQueue.enqueue(
|
|
@@ -5208,7 +5702,7 @@ Task completed.
|
|
|
5208
5702
|
}
|
|
5209
5703
|
async sendNotification(notification) {
|
|
5210
5704
|
if (notification.sessionId === this.assistantSession?.id) return;
|
|
5211
|
-
|
|
5705
|
+
log12.info(
|
|
5212
5706
|
{ sessionId: notification.sessionId, type: notification.type },
|
|
5213
5707
|
"Notification sent"
|
|
5214
5708
|
);
|
|
@@ -5246,7 +5740,7 @@ Task completed.
|
|
|
5246
5740
|
);
|
|
5247
5741
|
}
|
|
5248
5742
|
async createSessionThread(sessionId, name) {
|
|
5249
|
-
|
|
5743
|
+
log12.info({ sessionId, name }, "Session topic created");
|
|
5250
5744
|
return String(
|
|
5251
5745
|
await createSessionTopic(this.bot, this.telegramConfig.chatId, name)
|
|
5252
5746
|
);
|
|
@@ -5270,7 +5764,7 @@ Task completed.
|
|
|
5270
5764
|
try {
|
|
5271
5765
|
await this.bot.api.deleteForumTopic(this.telegramConfig.chatId, topicId);
|
|
5272
5766
|
} catch (err) {
|
|
5273
|
-
|
|
5767
|
+
log12.warn(
|
|
5274
5768
|
{ err, sessionId, topicId },
|
|
5275
5769
|
"Failed to delete forum topic (may already be deleted)"
|
|
5276
5770
|
);
|
|
@@ -5300,7 +5794,7 @@ Task completed.
|
|
|
5300
5794
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
5301
5795
|
return { buffer, filePath: file.file_path };
|
|
5302
5796
|
} catch (err) {
|
|
5303
|
-
|
|
5797
|
+
log12.error({ err }, "Failed to download file from Telegram");
|
|
5304
5798
|
return null;
|
|
5305
5799
|
}
|
|
5306
5800
|
}
|
|
@@ -5321,7 +5815,7 @@ Task completed.
|
|
|
5321
5815
|
try {
|
|
5322
5816
|
buffer = await this.fileService.convertOggToWav(buffer);
|
|
5323
5817
|
} catch (err) {
|
|
5324
|
-
|
|
5818
|
+
log12.warn({ err }, "OGG\u2192WAV conversion failed, saving original OGG");
|
|
5325
5819
|
fileName = "voice.ogg";
|
|
5326
5820
|
mimeType = "audio/ogg";
|
|
5327
5821
|
originalFilePath = void 0;
|
|
@@ -5352,21 +5846,23 @@ Task completed.
|
|
|
5352
5846
|
userId: String(userId),
|
|
5353
5847
|
text,
|
|
5354
5848
|
attachments: [att]
|
|
5355
|
-
}).catch((err) =>
|
|
5849
|
+
}).catch((err) => log12.error({ err }, "handleMessage error"));
|
|
5356
5850
|
}
|
|
5357
5851
|
async cleanupSkillCommands(sessionId) {
|
|
5358
5852
|
await this.skillManager.cleanup(sessionId);
|
|
5359
5853
|
}
|
|
5854
|
+
async stripTTSBlock(sessionId) {
|
|
5855
|
+
await this.draftManager.stripPattern(sessionId, /\[TTS\][\s\S]*?\[\/TTS\]/g);
|
|
5856
|
+
}
|
|
5360
5857
|
async archiveSessionTopic(sessionId) {
|
|
5361
5858
|
const core = this.core;
|
|
5362
5859
|
const session = core.sessionManager.getSession(sessionId);
|
|
5363
|
-
if (!session)
|
|
5860
|
+
if (!session) throw new Error("Session not found");
|
|
5364
5861
|
const chatId = this.telegramConfig.chatId;
|
|
5365
5862
|
const oldTopicId = Number(session.threadId);
|
|
5366
5863
|
session.archiving = true;
|
|
5367
5864
|
await this.draftManager.finalize(session.id, this.assistantSession?.id);
|
|
5368
5865
|
this.draftManager.cleanup(session.id);
|
|
5369
|
-
this.toolTracker.cleanup(session.id);
|
|
5370
5866
|
await this.skillManager.cleanup(session.id);
|
|
5371
5867
|
const tracker = this.sessionTrackers.get(session.id);
|
|
5372
5868
|
if (tracker) {
|
|
@@ -5374,13 +5870,29 @@ Task completed.
|
|
|
5374
5870
|
this.sessionTrackers.delete(session.id);
|
|
5375
5871
|
}
|
|
5376
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);
|
|
5377
5877
|
}
|
|
5378
5878
|
};
|
|
5379
5879
|
|
|
5380
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,
|
|
5381
5892
|
PRODUCT_GUIDE,
|
|
5382
5893
|
SendQueue,
|
|
5383
|
-
|
|
5894
|
+
MessagingAdapter,
|
|
5895
|
+
BaseRenderer,
|
|
5384
5896
|
TelegramAdapter
|
|
5385
5897
|
};
|
|
5386
|
-
//# sourceMappingURL=chunk-
|
|
5898
|
+
//# sourceMappingURL=chunk-RXMWJHWH.js.map
|