omnius 1.0.42 → 1.0.44
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 +94 -30
- package/dist/index.js +1190 -53
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -25710,7 +25710,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
25710
25710
|
bits2int_modN: "function"
|
|
25711
25711
|
});
|
|
25712
25712
|
ecdsaOpts = Object.assign({}, ecdsaOpts);
|
|
25713
|
-
const
|
|
25713
|
+
const randomBytes27 = ecdsaOpts.randomBytes || randomBytes7;
|
|
25714
25714
|
const hmac2 = ecdsaOpts.hmac || ((key, msg) => hmac(hash, key, msg));
|
|
25715
25715
|
const { Fp, Fn } = Point;
|
|
25716
25716
|
const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn;
|
|
@@ -25852,7 +25852,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
25852
25852
|
throw new Error("invalid private key");
|
|
25853
25853
|
const seedArgs = [int2octets(d2), int2octets(h1int)];
|
|
25854
25854
|
if (extraEntropy != null && extraEntropy !== false) {
|
|
25855
|
-
const e2 = extraEntropy === true ?
|
|
25855
|
+
const e2 = extraEntropy === true ? randomBytes27(lengths.secretKey) : extraEntropy;
|
|
25856
25856
|
seedArgs.push(abytes(e2, void 0, "extraEntropy"));
|
|
25857
25857
|
}
|
|
25858
25858
|
const seed = concatBytes(...seedArgs);
|
|
@@ -62362,9 +62362,9 @@ var init_cookies = __esm({
|
|
|
62362
62362
|
|
|
62363
62363
|
// ../node_modules/@libp2p/http-peer-id-auth/dist/src/utils.js
|
|
62364
62364
|
function generateChallenge() {
|
|
62365
|
-
const
|
|
62366
|
-
crypto.getRandomValues(
|
|
62367
|
-
return toString2(
|
|
62365
|
+
const randomBytes27 = new Uint8Array(32);
|
|
62366
|
+
crypto.getRandomValues(randomBytes27);
|
|
62367
|
+
return toString2(randomBytes27, "base64urlpad");
|
|
62368
62368
|
}
|
|
62369
62369
|
function encodeAuthParams(params) {
|
|
62370
62370
|
const encodedParams = Object.entries(params).map(([key, value2]) => `${key}="${value2}"`).join(", ");
|
|
@@ -234560,7 +234560,7 @@ var require_websocket2 = __commonJS({
|
|
|
234560
234560
|
var http6 = __require("http");
|
|
234561
234561
|
var net5 = __require("net");
|
|
234562
234562
|
var tls2 = __require("tls");
|
|
234563
|
-
var { randomBytes:
|
|
234563
|
+
var { randomBytes: randomBytes27, createHash: createHash28 } = __require("crypto");
|
|
234564
234564
|
var { Duplex: Duplex3, Readable } = __require("stream");
|
|
234565
234565
|
var { URL: URL3 } = __require("url");
|
|
234566
234566
|
var PerMessageDeflate3 = require_permessage_deflate2();
|
|
@@ -235090,7 +235090,7 @@ var require_websocket2 = __commonJS({
|
|
|
235090
235090
|
}
|
|
235091
235091
|
}
|
|
235092
235092
|
const defaultPort = isSecure ? 443 : 80;
|
|
235093
|
-
const key =
|
|
235093
|
+
const key = randomBytes27(16).toString("base64");
|
|
235094
235094
|
const request = isSecure ? https4.request : http6.request;
|
|
235095
235095
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
235096
235096
|
let perMessageDeflate;
|
|
@@ -553818,7 +553818,7 @@ var require_websocket3 = __commonJS({
|
|
|
553818
553818
|
var http6 = __require("http");
|
|
553819
553819
|
var net5 = __require("net");
|
|
553820
553820
|
var tls2 = __require("tls");
|
|
553821
|
-
var { randomBytes:
|
|
553821
|
+
var { randomBytes: randomBytes27, createHash: createHash28 } = __require("crypto");
|
|
553822
553822
|
var { Duplex: Duplex3, Readable } = __require("stream");
|
|
553823
553823
|
var { URL: URL3 } = __require("url");
|
|
553824
553824
|
var PerMessageDeflate3 = require_permessage_deflate3();
|
|
@@ -554348,7 +554348,7 @@ var require_websocket3 = __commonJS({
|
|
|
554348
554348
|
}
|
|
554349
554349
|
}
|
|
554350
554350
|
const defaultPort = isSecure ? 443 : 80;
|
|
554351
|
-
const key =
|
|
554351
|
+
const key = randomBytes27(16).toString("base64");
|
|
554352
554352
|
const request = isSecure ? https4.request : http6.request;
|
|
554353
554353
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
554354
554354
|
let perMessageDeflate;
|
|
@@ -555836,6 +555836,9 @@ var init_command_registry = __esm({
|
|
|
555836
555836
|
["/telegram personal <user_id> <limit>", "Fetch last messages from a user's profile personal chat"],
|
|
555837
555837
|
["/telegram access get <managed_bot_user_id>", "Show managed-bot access restriction settings"],
|
|
555838
555838
|
["/telegram access set <managed_bot_user_id> <restricted|open> [added_user_ids]", "Set managed-bot access restrictions"],
|
|
555839
|
+
["/telegram tools [group <chat>|panel <chat> [policy_chat]]", "Show unified Telegram tool policy or send inline admin toggle buttons"],
|
|
555840
|
+
["/telegram delete-message <chat> <message> [reason]", "Delete one Telegram message after policy and Bot API rights checks"],
|
|
555841
|
+
["/telegram delete-messages <chat> <message,message> [reason]", "Delete multiple Telegram messages after policy and Bot API rights checks"],
|
|
555839
555842
|
["/telegram delete-reaction <chat> <message> [--user <id>|--actor <chat>]", "Delete a Telegram message reaction"],
|
|
555840
555843
|
["/telegram delete-reactions <chat> [--user <id>|--actor <chat>]", "Delete recent Telegram message reactions by user or chat"],
|
|
555841
555844
|
["/platforms", "Show gateway platform state"],
|
|
@@ -564917,7 +564920,7 @@ function setTerminalTitle(task, version4) {
|
|
|
564917
564920
|
const title = task ? `${task.slice(0, 60)} · ${ver}` : ver;
|
|
564918
564921
|
process.stdout.write(`\x1B]2;${title}\x07`);
|
|
564919
564922
|
}
|
|
564920
|
-
var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, _globalFooterLock, RESET2, CURSOR_BLINK_BLOCK, _isWindows, StatusBar;
|
|
564923
|
+
var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, NO_SUB_AGENTS_HEADER_LABEL, BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, _globalFooterLock, RESET2, CURSOR_BLINK_BLOCK, _isWindows, StatusBar;
|
|
564921
564924
|
var init_status_bar = __esm({
|
|
564922
564925
|
"packages/cli/src/tui/status-bar.ts"() {
|
|
564923
564926
|
"use strict";
|
|
@@ -565089,6 +565092,7 @@ var init_status_bar = __esm({
|
|
|
565089
565092
|
BOX_FG = tuiBoxFg();
|
|
565090
565093
|
TEXT_PRIMARY = tuiTextPrimary() < 0 ? 252 : tuiTextPrimary();
|
|
565091
565094
|
TEXT_DIM = tuiTextDim();
|
|
565095
|
+
NO_SUB_AGENTS_HEADER_LABEL = " no sub-agents ";
|
|
565092
565096
|
BOX_TL = "╭";
|
|
565093
565097
|
BOX_TR = "╮";
|
|
565094
565098
|
BOX_BL = "╰";
|
|
@@ -565538,8 +565542,8 @@ var init_status_bar = __esm({
|
|
|
565538
565542
|
}
|
|
565539
565543
|
} else {
|
|
565540
565544
|
sysItems.push({
|
|
565541
|
-
render: () => `\x1B[38;5;${TEXT_DIM}m
|
|
565542
|
-
w:
|
|
565545
|
+
render: () => `\x1B[38;5;${TEXT_DIM}m${NO_SUB_AGENTS_HEADER_LABEL}`,
|
|
565546
|
+
w: NO_SUB_AGENTS_HEADER_LABEL.length
|
|
565543
565547
|
});
|
|
565544
565548
|
}
|
|
565545
565549
|
const sysSeparatorOffset = sysItems.reduce((sum, item) => sum + item.w, 0);
|
|
@@ -565622,7 +565626,10 @@ var init_status_bar = __esm({
|
|
|
565622
565626
|
return identity3.separatorOffsets.map((offset) => chrome.contentStartCol + offset).filter((col) => col > 1 && col < termWidth);
|
|
565623
565627
|
}
|
|
565624
565628
|
if (panel.meta.kind === "system" && this._sysSeparatorOffset !== null) {
|
|
565625
|
-
const
|
|
565629
|
+
const rendered = stripAnsi(panel.render(chrome.innerWidth));
|
|
565630
|
+
const renderedOffset = Array.from(rendered).indexOf("│");
|
|
565631
|
+
const offset = renderedOffset >= 0 ? renderedOffset : this._sysSeparatorOffset;
|
|
565632
|
+
const col = chrome.contentStartCol + offset;
|
|
565626
565633
|
if (col > 1 && col < termWidth) return [col];
|
|
565627
565634
|
}
|
|
565628
565635
|
return [];
|
|
@@ -565703,7 +565710,7 @@ var init_status_bar = __esm({
|
|
|
565703
565710
|
zones.push({ w: base3.length + 1, id: view.id, render: () => "" });
|
|
565704
565711
|
}
|
|
565705
565712
|
} else {
|
|
565706
|
-
zones.push({ w:
|
|
565713
|
+
zones.push({ w: NO_SUB_AGENTS_HEADER_LABEL.length, render: () => "" });
|
|
565707
565714
|
}
|
|
565708
565715
|
zones.push({ w: 2, render: () => "" });
|
|
565709
565716
|
const voiceLabel = this._voiceActive ? ` ${this._voiceModelId || "voice"} ` : " voice ";
|
|
@@ -582243,6 +582250,10 @@ function formatTelegramJsonResult(value2) {
|
|
|
582243
582250
|
if (value2 === null || value2 === void 0) return "No data returned.";
|
|
582244
582251
|
return JSON.stringify(value2, null, 2).slice(0, 3900);
|
|
582245
582252
|
}
|
|
582253
|
+
function parseTelegramMessageIdList(value2) {
|
|
582254
|
+
if (!value2) return [];
|
|
582255
|
+
return [...new Set(value2.split(",").map((part) => Number(part.trim())).filter((num) => Number.isFinite(num)))];
|
|
582256
|
+
}
|
|
582246
582257
|
async function runSudoScript(ctx3, script) {
|
|
582247
582258
|
const stdinAny = process.stdin;
|
|
582248
582259
|
const hadRaw = !!(stdinAny && stdinAny.isTTY && stdinAny.isRaw);
|
|
@@ -582736,11 +582747,11 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
582736
582747
|
}
|
|
582737
582748
|
if (action === "new") {
|
|
582738
582749
|
try {
|
|
582739
|
-
const { randomBytes:
|
|
582750
|
+
const { randomBytes: randomBytes27 } = await import("node:crypto");
|
|
582740
582751
|
const { homedir: homedir48 } = await import("node:os");
|
|
582741
582752
|
const { mkdirSync: mkdirSync79, writeFileSync: writeFileSync71 } = await import("node:fs");
|
|
582742
582753
|
const { join: join144 } = await import("node:path");
|
|
582743
|
-
const newKey =
|
|
582754
|
+
const newKey = randomBytes27(16).toString("hex");
|
|
582744
582755
|
process.env["OMNIUS_API_KEY"] = newKey;
|
|
582745
582756
|
const dir = join144(homedir48(), ".omnius");
|
|
582746
582757
|
mkdirSync79(dir, { recursive: true });
|
|
@@ -582997,8 +583008,8 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
582997
583008
|
}
|
|
582998
583009
|
process.env["OMNIUS_ACCESS"] = val2;
|
|
582999
583010
|
if (val2 === "any" && !process.env["OMNIUS_API_KEY"]) {
|
|
583000
|
-
const { randomBytes:
|
|
583001
|
-
const apiKey =
|
|
583011
|
+
const { randomBytes: randomBytes27 } = await import("node:crypto");
|
|
583012
|
+
const apiKey = randomBytes27(16).toString("hex");
|
|
583002
583013
|
process.env["OMNIUS_API_KEY"] = apiKey;
|
|
583003
583014
|
renderInfo(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
|
|
583004
583015
|
renderInfo(
|
|
@@ -583117,8 +583128,8 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
583117
583128
|
}
|
|
583118
583129
|
process.env["OMNIUS_ACCESS"] = val;
|
|
583119
583130
|
if (val === "any" && !process.env["OMNIUS_API_KEY"]) {
|
|
583120
|
-
const { randomBytes:
|
|
583121
|
-
const apiKey =
|
|
583131
|
+
const { randomBytes: randomBytes27 } = await import("node:crypto");
|
|
583132
|
+
const apiKey = randomBytes27(16).toString("hex");
|
|
583122
583133
|
process.env["OMNIUS_API_KEY"] = apiKey;
|
|
583123
583134
|
renderInfo(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
|
|
583124
583135
|
renderInfo(
|
|
@@ -587363,6 +587374,73 @@ sleep 1
|
|
|
587363
587374
|
}
|
|
587364
587375
|
return "handled";
|
|
587365
587376
|
}
|
|
587377
|
+
if (parts[0] === "tools" || parts[0] === "tooling") {
|
|
587378
|
+
if (parts[1] === "group" || parts[1] === "chat") {
|
|
587379
|
+
const chatId = parseTelegramChatTarget(parts[2]);
|
|
587380
|
+
if (!chatId) {
|
|
587381
|
+
renderWarning("Usage: /telegram tools group <chat>");
|
|
587382
|
+
return "handled";
|
|
587383
|
+
}
|
|
587384
|
+
const policy2 = ctx3.telegramGetToolPolicy?.() ?? {};
|
|
587385
|
+
const override = policy2.chatOverrides?.[String(chatId)] ?? {};
|
|
587386
|
+
renderInfo(`Unified Telegram tool policy override for chat ${String(chatId)}:`);
|
|
587387
|
+
renderInfo(formatTelegramJsonResult(override));
|
|
587388
|
+
renderInfo("Use /telegram tools panel <admin_dm_chat_id> <policy_chat> to edit this scope with buttons.");
|
|
587389
|
+
return "handled";
|
|
587390
|
+
}
|
|
587391
|
+
if (parts[1] === "panel" || parts[1] === "buttons") {
|
|
587392
|
+
const panelChatId = parseTelegramChatTarget(parts[2]);
|
|
587393
|
+
const policyChatId = parts[3] && parts[3] !== "global" ? parseTelegramChatTarget(parts[3]) : void 0;
|
|
587394
|
+
if (!panelChatId) {
|
|
587395
|
+
renderWarning("Usage: /telegram tools panel <panel_chat> [policy_chat|global]");
|
|
587396
|
+
return "handled";
|
|
587397
|
+
}
|
|
587398
|
+
try {
|
|
587399
|
+
const result = await ctx3.telegramSendToolPanel?.(panelChatId, policyChatId ?? void 0);
|
|
587400
|
+
renderInfo(formatTelegramJsonResult(result));
|
|
587401
|
+
} catch (err) {
|
|
587402
|
+
renderError(`Telegram tools panel failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
587403
|
+
}
|
|
587404
|
+
return "handled";
|
|
587405
|
+
}
|
|
587406
|
+
const policy = ctx3.telegramGetToolPolicy?.();
|
|
587407
|
+
renderInfo("Unified Telegram tool policy:");
|
|
587408
|
+
renderInfo(formatTelegramJsonResult(policy ?? {}));
|
|
587409
|
+
renderInfo("Use /telegram tools panel <admin_dm_chat_id> [policy_chat] to send inline toggle buttons.");
|
|
587410
|
+
return "handled";
|
|
587411
|
+
}
|
|
587412
|
+
if (parts[0] === "delete-message") {
|
|
587413
|
+
const chatId = parseTelegramChatTarget(parts[1]);
|
|
587414
|
+
const messageId = Number(parts[2]);
|
|
587415
|
+
const reason = parts.slice(3).join(" ").trim() || "TUI admin delete-message command";
|
|
587416
|
+
if (!chatId || !Number.isFinite(messageId)) {
|
|
587417
|
+
renderWarning("Usage: /telegram delete-message <chat> <message_id> [reason]");
|
|
587418
|
+
return "handled";
|
|
587419
|
+
}
|
|
587420
|
+
try {
|
|
587421
|
+
const result = await ctx3.telegramDeleteMessage?.(chatId, messageId, reason);
|
|
587422
|
+
renderInfo(formatTelegramJsonResult(result));
|
|
587423
|
+
} catch (err) {
|
|
587424
|
+
renderError(`Telegram delete message failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
587425
|
+
}
|
|
587426
|
+
return "handled";
|
|
587427
|
+
}
|
|
587428
|
+
if (parts[0] === "delete-messages") {
|
|
587429
|
+
const chatId = parseTelegramChatTarget(parts[1]);
|
|
587430
|
+
const messageIds = parseTelegramMessageIdList(parts[2]);
|
|
587431
|
+
const reason = parts.slice(3).join(" ").trim() || "TUI admin delete-messages command";
|
|
587432
|
+
if (!chatId || messageIds.length === 0) {
|
|
587433
|
+
renderWarning("Usage: /telegram delete-messages <chat> <message_id,message_id> [reason]");
|
|
587434
|
+
return "handled";
|
|
587435
|
+
}
|
|
587436
|
+
try {
|
|
587437
|
+
const result = await ctx3.telegramDeleteMessages?.(chatId, messageIds, reason);
|
|
587438
|
+
renderInfo(formatTelegramJsonResult(result));
|
|
587439
|
+
} catch (err) {
|
|
587440
|
+
renderError(`Telegram delete messages failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
587441
|
+
}
|
|
587442
|
+
return "handled";
|
|
587443
|
+
}
|
|
587366
587444
|
if (parts[0] === "delete-reaction") {
|
|
587367
587445
|
const chatId = parseTelegramChatTarget(parts[1]);
|
|
587368
587446
|
const messageId = Number(parts[2]);
|
|
@@ -587473,6 +587551,9 @@ sleep 1
|
|
|
587473
587551
|
renderInfo(" /telegram admins <chat> [--bots] List chat admins");
|
|
587474
587552
|
renderInfo(" /telegram personal <user_id> <limit> Fetch profile personal chat messages");
|
|
587475
587553
|
renderInfo(" /telegram access get|set <managed_bot_user_id> ... Manage bot access restriction");
|
|
587554
|
+
renderInfo(" /telegram tools [group <chat>|panel <chat> [policy_chat]] Show/send unified tool policy buttons");
|
|
587555
|
+
renderInfo(" /telegram delete-message <chat> <msg> [reason] Delete one message");
|
|
587556
|
+
renderInfo(" /telegram delete-messages <chat> <msg,msg> [reason] Delete multiple messages");
|
|
587476
587557
|
renderInfo(" /telegram delete-reaction <chat> <msg> --user <id> Delete a reaction");
|
|
587477
587558
|
renderInfo(" /telegram delete-reactions <chat> --user <id> Delete recent reactions");
|
|
587478
587559
|
renderInfo(" Add --local to scope settings to this project only");
|
|
@@ -588338,7 +588419,9 @@ async function showPlatformOnboardingMenu(ctx3, id) {
|
|
|
588338
588419
|
} else if (result.key === "telegram-start") {
|
|
588339
588420
|
const settings = ctx3.getTelegramSettings?.() ?? {};
|
|
588340
588421
|
if (!settings.key) renderWarning("No Telegram bot token configured.");
|
|
588341
|
-
else
|
|
588422
|
+
else if (ctx3.isTelegramActive?.()) {
|
|
588423
|
+
renderWarning("Telegram bridge already active. Use /telegram stop before restarting.");
|
|
588424
|
+
} else await ctx3.telegramStart?.(settings.key, settings.admin);
|
|
588342
588425
|
} else if (result.key === "telegram-stop") {
|
|
588343
588426
|
ctx3.telegramStop?.();
|
|
588344
588427
|
}
|
|
@@ -593675,11 +593758,11 @@ var init_commands = __esm({
|
|
|
593675
593758
|
process.env["OMNIUS_ACCESS"] = val;
|
|
593676
593759
|
if (val === "any" && !process.env["OMNIUS_API_KEY"]) {
|
|
593677
593760
|
try {
|
|
593678
|
-
const { randomBytes:
|
|
593761
|
+
const { randomBytes: randomBytes27 } = await import("node:crypto");
|
|
593679
593762
|
const { homedir: homedir48 } = await import("node:os");
|
|
593680
593763
|
const { mkdirSync: mkdirSync79, writeFileSync: writeFileSync71 } = await import("node:fs");
|
|
593681
593764
|
const { join: join144 } = await import("node:path");
|
|
593682
|
-
const apiKey =
|
|
593765
|
+
const apiKey = randomBytes27(16).toString("hex");
|
|
593683
593766
|
process.env["OMNIUS_API_KEY"] = apiKey;
|
|
593684
593767
|
const dir = join144(homedir48(), ".omnius");
|
|
593685
593768
|
mkdirSync79(dir, { recursive: true });
|
|
@@ -600534,6 +600617,7 @@ var init_tool_policy = __esm({
|
|
|
600534
600617
|
"reminders",
|
|
600535
600618
|
"explore_tools",
|
|
600536
600619
|
"telegram_media_recent",
|
|
600620
|
+
"telegram",
|
|
600537
600621
|
"generate_image",
|
|
600538
600622
|
"generate_audio",
|
|
600539
600623
|
"generate_tts",
|
|
@@ -600566,6 +600650,7 @@ var init_tool_policy = __esm({
|
|
|
600566
600650
|
"reminders",
|
|
600567
600651
|
"explore_tools",
|
|
600568
600652
|
"telegram_media_recent",
|
|
600653
|
+
"telegram",
|
|
600569
600654
|
"generate_image",
|
|
600570
600655
|
"generate_audio",
|
|
600571
600656
|
"generate_tts",
|
|
@@ -602819,7 +602904,7 @@ var init_vision_ingress = __esm({
|
|
|
602819
602904
|
import { mkdirSync as mkdirSync63, existsSync as existsSync108, unlinkSync as unlinkSync21, readdirSync as readdirSync37, statSync as statSync36, statfsSync as statfsSync3, readFileSync as readFileSync88, writeFileSync as writeFileSync57 } from "node:fs";
|
|
602820
602905
|
import { join as join123, resolve as resolve41, basename as basename27, relative as relative13, isAbsolute as isAbsolute7, extname as extname16 } from "node:path";
|
|
602821
602906
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
602822
|
-
import { createHash as createHash23, randomInt } from "node:crypto";
|
|
602907
|
+
import { createHash as createHash23, randomBytes as randomBytes22, randomInt } from "node:crypto";
|
|
602823
602908
|
function parseTelegramInteractionDecision(text, forcedRoute, options2 = {}) {
|
|
602824
602909
|
const cleaned = stripTelegramHiddenThinking(text).replace(/```(?:json)?/gi, "").replace(/```/g, "").trim();
|
|
602825
602910
|
const jsonText = cleaned.startsWith("{") ? cleaned : cleaned.match(/\{[\s\S]*\}/)?.[0] ?? "";
|
|
@@ -603803,6 +603888,23 @@ function normalizeTelegramUpdate(update2) {
|
|
|
603803
603888
|
sourceUpdateType
|
|
603804
603889
|
};
|
|
603805
603890
|
}
|
|
603891
|
+
function normalizeTelegramCallbackQuery(update2) {
|
|
603892
|
+
const callback = update2.callback_query;
|
|
603893
|
+
if (!callback || typeof callback !== "object") return null;
|
|
603894
|
+
const from3 = callback.from && typeof callback.from === "object" ? callback.from : {};
|
|
603895
|
+
const message2 = callback.message && typeof callback.message === "object" ? callback.message : void 0;
|
|
603896
|
+
const data = typeof callback.data === "string" ? callback.data : "";
|
|
603897
|
+
if (!callback.id || !data) return null;
|
|
603898
|
+
return {
|
|
603899
|
+
id: String(callback.id),
|
|
603900
|
+
fromUserId: telegramOptionalNumber(from3.id) ?? 0,
|
|
603901
|
+
username: telegramOptionalString(from3.username) ?? "unknown",
|
|
603902
|
+
firstName: telegramOptionalString(from3.first_name),
|
|
603903
|
+
chatId: message2?.chat?.id !== void 0 ? normalizeTelegramChatId(message2.chat.id) : void 0,
|
|
603904
|
+
messageId: telegramOptionalNumber(message2?.message_id),
|
|
603905
|
+
data
|
|
603906
|
+
};
|
|
603907
|
+
}
|
|
603806
603908
|
function adaptTool5(tool, todoSessionId) {
|
|
603807
603909
|
return {
|
|
603808
603910
|
name: tool.name,
|
|
@@ -603945,7 +604047,7 @@ function renderTelegramSubAgentError(username, error) {
|
|
|
603945
604047
|
process.stdout.write(` ${c3.dim("⎿")} ${c3.red("✘")} @${username}: ${c3.dim(preview)}
|
|
603946
604048
|
`);
|
|
603947
604049
|
}
|
|
603948
|
-
var TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, TELEGRAM_PUBLIC_SOUL_PROFILE, TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT, TELEGRAM_PUBLIC_MEMORY_SCOPE_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_CHAT_HISTORY_LIMIT, TELEGRAM_CONTEXT_RECENT_DEFAULT, TELEGRAM_CONTEXT_LINE_LIMIT, TELEGRAM_CONTEXT_SAMPLE_LIMIT, TELEGRAM_MEMORY_CARD_LIMIT, TELEGRAM_MEMORY_NOTE_LIMIT, TELEGRAM_MEMORY_STOPWORDS, TELEGRAM_PUBLIC_HELP_COMMANDS, TELEGRAM_REMINDER_SLASH_COMMANDS, TELEGRAM_REFLECTION_SLASH_COMMANDS, TELEGRAM_IMAGE_EXTENSIONS, MEDIA_CACHE_TTL_MS, TELEGRAM_CHANNEL_DMN_SWEEP_MS, TELEGRAM_CHANNEL_DMN_IDLE_AFTER_MS, TELEGRAM_CHANNEL_DMN_MIN_INTERVAL_MS, TELEGRAM_CHANNEL_DMN_MIN_MESSAGES, TelegramBridge;
|
|
604050
|
+
var TELEGRAM_TOOL_ACTION_GROUPS, TELEGRAM_TOOL_ACTION_GROUP, TELEGRAM_TOOL_MUTATING_GROUPS, DEFAULT_TELEGRAM_TOOL_GROUP_POLICY, TELEGRAM_TOOL_BUTTON_LABELS, TELEGRAM_SAFETY_PROMPT, ADMIN_DM_PROMPT, ADMIN_GROUP_PROMPT, TELEGRAM_PUBLIC_SOUL_PROFILE, TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT, TELEGRAM_PUBLIC_MEMORY_SCOPE_CONTRACT, GROUP_REPLY_DISCRETION_PROMPT, TELEGRAM_CHAT_MODE_PROMPT, ADMIN_CHAT_PROFILE_PROMPT, TELEGRAM_ACTION_RESPONSE_CONTRACT, TELEGRAM_CHAT_HISTORY_LIMIT, TELEGRAM_CONTEXT_RECENT_DEFAULT, TELEGRAM_CONTEXT_LINE_LIMIT, TELEGRAM_CONTEXT_SAMPLE_LIMIT, TELEGRAM_MEMORY_CARD_LIMIT, TELEGRAM_MEMORY_NOTE_LIMIT, TELEGRAM_MEMORY_STOPWORDS, TELEGRAM_PUBLIC_HELP_COMMANDS, TELEGRAM_REMINDER_SLASH_COMMANDS, TELEGRAM_REFLECTION_SLASH_COMMANDS, TELEGRAM_IMAGE_EXTENSIONS, MEDIA_CACHE_TTL_MS, TELEGRAM_CHANNEL_DMN_SWEEP_MS, TELEGRAM_CHANNEL_DMN_IDLE_AFTER_MS, TELEGRAM_CHANNEL_DMN_MIN_INTERVAL_MS, TELEGRAM_CHANNEL_DMN_MIN_MESSAGES, TelegramBridge;
|
|
603949
604051
|
var init_telegram_bridge = __esm({
|
|
603950
604052
|
"packages/cli/src/tui/telegram-bridge.ts"() {
|
|
603951
604053
|
"use strict";
|
|
@@ -603965,6 +604067,90 @@ var init_telegram_bridge = __esm({
|
|
|
603965
604067
|
init_telegram_channel_dmn();
|
|
603966
604068
|
init_telegram_reflection_corpus();
|
|
603967
604069
|
init_telegram_reflection_extraction();
|
|
604070
|
+
TELEGRAM_TOOL_ACTION_GROUPS = [
|
|
604071
|
+
"read",
|
|
604072
|
+
"message",
|
|
604073
|
+
"media",
|
|
604074
|
+
"janitorial",
|
|
604075
|
+
"reaction",
|
|
604076
|
+
"moderation",
|
|
604077
|
+
"bot_admin",
|
|
604078
|
+
"policy"
|
|
604079
|
+
];
|
|
604080
|
+
TELEGRAM_TOOL_ACTION_GROUP = {
|
|
604081
|
+
scope_status: "read",
|
|
604082
|
+
get_tool_scope: "read",
|
|
604083
|
+
get_me: "read",
|
|
604084
|
+
get_chat: "read",
|
|
604085
|
+
get_chat_member: "read",
|
|
604086
|
+
get_chat_administrators: "read",
|
|
604087
|
+
get_message_context: "read",
|
|
604088
|
+
send_message: "message",
|
|
604089
|
+
edit_message_text: "message",
|
|
604090
|
+
edit_message_caption: "message",
|
|
604091
|
+
edit_message_reply_markup: "message",
|
|
604092
|
+
pin_message: "message",
|
|
604093
|
+
unpin_message: "message",
|
|
604094
|
+
unpin_all_messages: "message",
|
|
604095
|
+
delete_message: "janitorial",
|
|
604096
|
+
delete_messages: "janitorial",
|
|
604097
|
+
send_file: "media",
|
|
604098
|
+
send_photo: "media",
|
|
604099
|
+
send_document: "media",
|
|
604100
|
+
send_audio: "media",
|
|
604101
|
+
send_voice: "media",
|
|
604102
|
+
send_video: "media",
|
|
604103
|
+
set_message_reaction: "reaction",
|
|
604104
|
+
delete_message_reaction: "reaction",
|
|
604105
|
+
delete_all_message_reactions: "reaction",
|
|
604106
|
+
ban_chat_member: "moderation",
|
|
604107
|
+
unban_chat_member: "moderation",
|
|
604108
|
+
restrict_chat_member: "moderation",
|
|
604109
|
+
promote_chat_member: "moderation",
|
|
604110
|
+
set_chat_permissions: "moderation",
|
|
604111
|
+
approve_chat_join_request: "moderation",
|
|
604112
|
+
decline_chat_join_request: "moderation",
|
|
604113
|
+
set_my_commands: "bot_admin",
|
|
604114
|
+
get_my_commands: "bot_admin",
|
|
604115
|
+
set_chat_menu_button: "bot_admin",
|
|
604116
|
+
get_chat_menu_button: "bot_admin",
|
|
604117
|
+
set_my_description: "bot_admin",
|
|
604118
|
+
get_my_description: "bot_admin",
|
|
604119
|
+
enable_action: "policy",
|
|
604120
|
+
disable_action: "policy",
|
|
604121
|
+
enable_group: "policy",
|
|
604122
|
+
disable_group: "policy",
|
|
604123
|
+
render_admin_buttons: "policy"
|
|
604124
|
+
};
|
|
604125
|
+
TELEGRAM_TOOL_MUTATING_GROUPS = /* @__PURE__ */ new Set([
|
|
604126
|
+
"message",
|
|
604127
|
+
"media",
|
|
604128
|
+
"janitorial",
|
|
604129
|
+
"reaction",
|
|
604130
|
+
"moderation",
|
|
604131
|
+
"bot_admin",
|
|
604132
|
+
"policy"
|
|
604133
|
+
]);
|
|
604134
|
+
DEFAULT_TELEGRAM_TOOL_GROUP_POLICY = {
|
|
604135
|
+
read: true,
|
|
604136
|
+
message: false,
|
|
604137
|
+
media: true,
|
|
604138
|
+
janitorial: false,
|
|
604139
|
+
reaction: false,
|
|
604140
|
+
moderation: false,
|
|
604141
|
+
bot_admin: false,
|
|
604142
|
+
policy: true
|
|
604143
|
+
};
|
|
604144
|
+
TELEGRAM_TOOL_BUTTON_LABELS = {
|
|
604145
|
+
read: "Read",
|
|
604146
|
+
message: "Send/Edit",
|
|
604147
|
+
media: "Media",
|
|
604148
|
+
janitorial: "Delete",
|
|
604149
|
+
reaction: "Reactions",
|
|
604150
|
+
moderation: "Moderation",
|
|
604151
|
+
bot_admin: "Bot Admin",
|
|
604152
|
+
policy: "Policy"
|
|
604153
|
+
};
|
|
603968
604154
|
TELEGRAM_SAFETY_PROMPT = `
|
|
603969
604155
|
CRITICAL SAFETY NOTICE — PUBLIC TELEGRAM CHANNEL
|
|
603970
604156
|
|
|
@@ -604162,8 +604348,10 @@ Telegram response contract:
|
|
|
604162
604348
|
this.agentConfig = agentConfig;
|
|
604163
604349
|
this.repoRoot = repoRoot;
|
|
604164
604350
|
this.toolPolicyConfig = toolPolicyConfig;
|
|
604351
|
+
this.telegramToolPolicy = resolveSettings(repoRoot || ".").telegramToolPolicy ?? {};
|
|
604165
604352
|
this.mediaCacheDir = resolve41(repoRoot || ".", ".omnius", "telegram-media-cache");
|
|
604166
604353
|
this.telegramConversationDir = resolve41(repoRoot || ".", ".omnius", "telegram-conversations");
|
|
604354
|
+
this.telegramToolButtonDir = resolve41(repoRoot || ".", ".omnius", "telegram-tool-buttons");
|
|
604167
604355
|
}
|
|
604168
604356
|
botToken;
|
|
604169
604357
|
onMessage;
|
|
@@ -604206,6 +604394,14 @@ Telegram response contract:
|
|
|
604206
604394
|
onSubAgentEvent = null;
|
|
604207
604395
|
/** Tool policy config — user overrides from config */
|
|
604208
604396
|
toolPolicyConfig;
|
|
604397
|
+
/** Action-level policy for the unified Telegram tool */
|
|
604398
|
+
telegramToolPolicy;
|
|
604399
|
+
/** Cached bot id from getMe for permission checks */
|
|
604400
|
+
botUserId = null;
|
|
604401
|
+
/** Cached bot chat rights for mutation guard checks */
|
|
604402
|
+
telegramBotRightsCache = /* @__PURE__ */ new Map();
|
|
604403
|
+
/** Short-lived Telegram inline button state directory */
|
|
604404
|
+
telegramToolButtonDir;
|
|
604209
604405
|
/** Command handler for admin DM slash commands (wired from interactive.ts) */
|
|
604210
604406
|
commandHandler = null;
|
|
604211
604407
|
/** Callback fired after a Telegram user completes the TUI-only admin auth challenge */
|
|
@@ -604271,6 +604467,12 @@ Telegram response contract:
|
|
|
604271
604467
|
setToolPolicyConfig(config) {
|
|
604272
604468
|
this.toolPolicyConfig = config;
|
|
604273
604469
|
}
|
|
604470
|
+
setTelegramToolPolicy(policy) {
|
|
604471
|
+
this.telegramToolPolicy = policy ?? {};
|
|
604472
|
+
}
|
|
604473
|
+
getTelegramToolPolicy() {
|
|
604474
|
+
return this.cloneTelegramToolPolicy(this.telegramToolPolicy);
|
|
604475
|
+
}
|
|
604274
604476
|
/**
|
|
604275
604477
|
* Set a command handler for admin DM slash commands.
|
|
604276
604478
|
* When an admin sends a /command in DM, it gets routed through the TUI's
|
|
@@ -606073,6 +606275,7 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
606073
606275
|
messagesSent: 0,
|
|
606074
606276
|
activeSubAgents: 0
|
|
606075
606277
|
};
|
|
606278
|
+
this.botUserId = typeof me.result?.id === "number" ? me.result.id : this.botUserId;
|
|
606076
606279
|
this.polling = true;
|
|
606077
606280
|
this.abortController = new AbortController();
|
|
606078
606281
|
try {
|
|
@@ -606192,11 +606395,12 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
606192
606395
|
const chunks = splitTelegramMessageText(html, 3900);
|
|
606193
606396
|
if (chunks.length === 0) return null;
|
|
606194
606397
|
const replyToMessageId = msg.chatType !== "private" ? msg.messageId : void 0;
|
|
606398
|
+
const suppressMedia = this.deliveredArtifactMediaSuppressorForMessage(msg);
|
|
606195
606399
|
if (liveMessageId && !msg.guestQueryId) {
|
|
606196
606400
|
const edited = await this.editLiveMessage(msg.chatId, liveMessageId, chunks[0]);
|
|
606197
606401
|
if (edited) {
|
|
606198
606402
|
for (const chunk of chunks.slice(1)) {
|
|
606199
|
-
await this.sendMessageHTML(msg.chatId, chunk);
|
|
606403
|
+
await this.sendMessageHTML(msg.chatId, chunk, void 0, { suppressMedia });
|
|
606200
606404
|
}
|
|
606201
606405
|
return liveMessageId;
|
|
606202
606406
|
}
|
|
@@ -606207,7 +606411,12 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
606207
606411
|
}
|
|
606208
606412
|
let firstMessageId = null;
|
|
606209
606413
|
for (let idx = 0; idx < chunks.length; idx++) {
|
|
606210
|
-
const messageId = await this.sendMessageHTML(
|
|
606414
|
+
const messageId = await this.sendMessageHTML(
|
|
606415
|
+
msg.chatId,
|
|
606416
|
+
chunks[idx],
|
|
606417
|
+
idx === 0 ? replyToMessageId : void 0,
|
|
606418
|
+
{ suppressMedia }
|
|
606419
|
+
);
|
|
606211
606420
|
if (firstMessageId === null) firstMessageId = messageId;
|
|
606212
606421
|
}
|
|
606213
606422
|
return firstMessageId;
|
|
@@ -606239,6 +606448,20 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
606239
606448
|
await this.handleTelegramReflectionSlash(msg, normalizedCommandText);
|
|
606240
606449
|
return;
|
|
606241
606450
|
}
|
|
606451
|
+
if (msg.text.trim().startsWith("/") && (telegramSlash === "tools" || telegramSlash === "telegram_tools")) {
|
|
606452
|
+
if (!isAdmin) {
|
|
606453
|
+
await this.replyToTelegramMessage(msg, "Telegram tool controls require admin authentication.");
|
|
606454
|
+
return;
|
|
606455
|
+
}
|
|
606456
|
+
const parts = normalizedCommandText.trim().split(/\s+/).slice(1);
|
|
606457
|
+
const target = parts[0] === "chat" || parts[0] === "group" ? this.resolveTelegramFileTarget({ target: parts[1] }, msg.chatId, msg.chatType === "private", msg) : { ok: true, chatId: msg.chatType === "private" ? void 0 : msg.chatId };
|
|
606458
|
+
if (!target.ok) {
|
|
606459
|
+
await this.replyToTelegramMessage(msg, target.error);
|
|
606460
|
+
return;
|
|
606461
|
+
}
|
|
606462
|
+
await this.sendTelegramToolPanel(msg.chatId, target.chatId);
|
|
606463
|
+
return;
|
|
606464
|
+
}
|
|
606242
606465
|
if (!this.agentConfig || !this.repoRoot) {
|
|
606243
606466
|
this.onMessage(msg);
|
|
606244
606467
|
return;
|
|
@@ -606407,6 +606630,7 @@ Join: ${newUrl}`);
|
|
|
606407
606630
|
creativeWorkspaceRoot: this.creativeWorkspaceRootForMessage(msg, toolContext),
|
|
606408
606631
|
generatedArtifacts: [],
|
|
606409
606632
|
deliveredArtifacts: [],
|
|
606633
|
+
deliveredFileSends: /* @__PURE__ */ new Set(),
|
|
606410
606634
|
surfacedToolCallFingerprints: /* @__PURE__ */ new Set()
|
|
606411
606635
|
};
|
|
606412
606636
|
this.subAgents.set(sessionKey, subAgent);
|
|
@@ -606519,6 +606743,7 @@ Join: ${newUrl}`);
|
|
|
606519
606743
|
creativeWorkspaceRoot: this.creativeWorkspaceRootForMessage(msg, toolContext),
|
|
606520
606744
|
generatedArtifacts: [],
|
|
606521
606745
|
deliveredArtifacts: [],
|
|
606746
|
+
deliveredFileSends: /* @__PURE__ */ new Set(),
|
|
606522
606747
|
surfacedToolCallFingerprints: /* @__PURE__ */ new Set()
|
|
606523
606748
|
};
|
|
606524
606749
|
this.subAgents.set(sessionKey, subAgent);
|
|
@@ -607451,6 +607676,7 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
607451
607676
|
new SkillListTool(repoRoot),
|
|
607452
607677
|
sharedSkillExtractTool,
|
|
607453
607678
|
this.buildTelegramMediaRecentTool(chatId, msg),
|
|
607679
|
+
this.buildTelegramTool(context2, repoRoot, chatId, msg),
|
|
607454
607680
|
...this.buildTelegramReminderTools(context2, repoRoot, chatId, msg)
|
|
607455
607681
|
];
|
|
607456
607682
|
const adminTools = [
|
|
@@ -607513,6 +607739,7 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
607513
607739
|
new SkillListTool(repoRoot),
|
|
607514
607740
|
new SkillExecuteTool(repoRoot),
|
|
607515
607741
|
adminSkillExtractTool,
|
|
607742
|
+
this.buildTelegramTool(context2, repoRoot, chatId, msg),
|
|
607516
607743
|
...this.buildTelegramReminderTools(context2, repoRoot, chatId, msg),
|
|
607517
607744
|
fullSubAgentTool,
|
|
607518
607745
|
this.buildTelegramSendFileTool(context2, repoRoot, chatId, msg)
|
|
@@ -607559,6 +607786,811 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
607559
607786
|
]);
|
|
607560
607787
|
return tools.filter((tool) => !blocked.has(tool.name));
|
|
607561
607788
|
}
|
|
607789
|
+
buildTelegramTool(context2, repoRoot, chatId, currentMsg) {
|
|
607790
|
+
const bridge = this;
|
|
607791
|
+
const adminDm = context2 === "telegram-admin-dm";
|
|
607792
|
+
return {
|
|
607793
|
+
name: "telegram",
|
|
607794
|
+
description: [
|
|
607795
|
+
"Unified scoped Telegram tool. Use action to inspect chat state, send messages/files, delete messages, manage reactions, or manage Telegram tool policy.",
|
|
607796
|
+
"Deletion and moderation actions require authenticated admin context, Omnius Telegram tool policy enablement, current/known chat scoping, and Telegram bot rights.",
|
|
607797
|
+
"Use scope_status before risky actions when uncertain. Use render_admin_buttons to show clickable admin toggles."
|
|
607798
|
+
].join(" "),
|
|
607799
|
+
parameters: {
|
|
607800
|
+
type: "object",
|
|
607801
|
+
properties: {
|
|
607802
|
+
action: {
|
|
607803
|
+
type: "string",
|
|
607804
|
+
enum: Object.keys(TELEGRAM_TOOL_ACTION_GROUP),
|
|
607805
|
+
description: "Telegram action to perform."
|
|
607806
|
+
},
|
|
607807
|
+
target: {
|
|
607808
|
+
type: "string",
|
|
607809
|
+
description: adminDm ? "Optional target chat/user. Defaults to the current DM; known group chat ids are allowed." : "Current chat only for group/public contexts."
|
|
607810
|
+
},
|
|
607811
|
+
chat_id: { type: "string", description: "Alias for target." },
|
|
607812
|
+
message_id: { type: "number", description: "Telegram message id for single-message actions." },
|
|
607813
|
+
message_ids: {
|
|
607814
|
+
type: "array",
|
|
607815
|
+
items: { type: "number" },
|
|
607816
|
+
description: "Telegram message ids for batch actions."
|
|
607817
|
+
},
|
|
607818
|
+
user_id: { type: "number", description: "Telegram user id for member/moderation/reaction actions." },
|
|
607819
|
+
text: { type: "string", description: "Text for send/edit actions." },
|
|
607820
|
+
caption: { type: "string", description: "Caption for media or caption edit actions." },
|
|
607821
|
+
reply_markup: { type: "object", description: "Raw Telegram reply_markup object for edit_message_reply_markup." },
|
|
607822
|
+
permissions: { type: "object", description: "Raw Telegram ChatPermissions object for restriction or default chat permissions." },
|
|
607823
|
+
rights: { type: "object", description: "Raw Telegram admin-rights fields for promote_chat_member." },
|
|
607824
|
+
reaction: { type: "array", items: { type: "object" }, description: "ReactionType array for set_message_reaction." },
|
|
607825
|
+
commands: { type: "array", items: { type: "object" }, description: "Bot command objects for set_my_commands." },
|
|
607826
|
+
menu_button: { type: "object", description: "Raw MenuButton object for set_chat_menu_button." },
|
|
607827
|
+
description: { type: "string", description: "Bot description text for set_my_description." },
|
|
607828
|
+
language_code: { type: "string", description: "Optional Telegram language code for bot command/description actions." },
|
|
607829
|
+
until_date: { type: "number", description: "Unix timestamp for ban/restrict expiry." },
|
|
607830
|
+
path: { type: "string", description: "File path for send_file; same scoping as telegram_send_file." },
|
|
607831
|
+
kind: {
|
|
607832
|
+
type: "string",
|
|
607833
|
+
enum: ["auto", "image", "photo", "document", "audio", "voice", "video", "animation"],
|
|
607834
|
+
description: "Media kind for send_file."
|
|
607835
|
+
},
|
|
607836
|
+
group: {
|
|
607837
|
+
type: "string",
|
|
607838
|
+
enum: TELEGRAM_TOOL_ACTION_GROUPS,
|
|
607839
|
+
description: "Action group for enable_group/disable_group."
|
|
607840
|
+
},
|
|
607841
|
+
tool_action: { type: "string", description: "Action name for enable_action/disable_action." },
|
|
607842
|
+
scope: { type: "string", enum: ["global", "chat"], description: "Policy scope for enable/disable actions." },
|
|
607843
|
+
dry_run: { type: "boolean", description: "When true, validate and report without calling Telegram." },
|
|
607844
|
+
reason: { type: "string", description: "Short audit reason for risky Telegram actions." }
|
|
607845
|
+
},
|
|
607846
|
+
required: ["action"]
|
|
607847
|
+
},
|
|
607848
|
+
async execute(args) {
|
|
607849
|
+
const start2 = performance.now();
|
|
607850
|
+
const action = String(args["action"] || "").trim().toLowerCase();
|
|
607851
|
+
if (!action || !(action in TELEGRAM_TOOL_ACTION_GROUP)) {
|
|
607852
|
+
return { success: false, output: "", error: `Unsupported Telegram action: ${action || "(missing)"}`, durationMs: performance.now() - start2 };
|
|
607853
|
+
}
|
|
607854
|
+
try {
|
|
607855
|
+
const result = await bridge.executeTelegramToolAction(action, args, {
|
|
607856
|
+
context: context2,
|
|
607857
|
+
repoRoot,
|
|
607858
|
+
chatId,
|
|
607859
|
+
currentMsg
|
|
607860
|
+
});
|
|
607861
|
+
return {
|
|
607862
|
+
success: true,
|
|
607863
|
+
output: typeof result === "string" ? result : JSON.stringify(result, null, 2),
|
|
607864
|
+
llmContent: typeof result === "string" ? result : JSON.stringify(result),
|
|
607865
|
+
durationMs: performance.now() - start2,
|
|
607866
|
+
mutated: TELEGRAM_TOOL_MUTATING_GROUPS.has(TELEGRAM_TOOL_ACTION_GROUP[action]),
|
|
607867
|
+
mutatedFiles: []
|
|
607868
|
+
};
|
|
607869
|
+
} catch (err) {
|
|
607870
|
+
return {
|
|
607871
|
+
success: false,
|
|
607872
|
+
output: "",
|
|
607873
|
+
error: err instanceof Error ? err.message : String(err),
|
|
607874
|
+
durationMs: performance.now() - start2
|
|
607875
|
+
};
|
|
607876
|
+
}
|
|
607877
|
+
}
|
|
607878
|
+
};
|
|
607879
|
+
}
|
|
607880
|
+
async executeTelegramToolAction(action, args, env2) {
|
|
607881
|
+
const target = this.resolveTelegramFileTarget(args, env2.chatId, env2.context === "telegram-admin-dm", env2.currentMsg);
|
|
607882
|
+
if (!target.ok && this.telegramToolHasExplicitTarget(args)) throw new Error(target.error);
|
|
607883
|
+
const targetChatId = target.ok ? target.chatId : env2.chatId;
|
|
607884
|
+
const gate = this.assertTelegramToolActionAllowed(action, env2.context, env2.currentMsg, targetChatId, args);
|
|
607885
|
+
if (!gate.ok) throw new Error(gate.error);
|
|
607886
|
+
const dryRun = this.telegramToolDryRun(args, targetChatId);
|
|
607887
|
+
const messageId = this.telegramNumberArg(args["message_id"]);
|
|
607888
|
+
const messageIds = this.telegramMessageIdsArg(args["message_ids"] ?? args["message_id"]);
|
|
607889
|
+
const userId = this.telegramNumberArg(args["user_id"]);
|
|
607890
|
+
if (!dryRun) {
|
|
607891
|
+
await this.assertTelegramBotRightsForAction(action, targetChatId, messageIds, env2.currentMsg);
|
|
607892
|
+
}
|
|
607893
|
+
switch (action) {
|
|
607894
|
+
case "scope_status":
|
|
607895
|
+
case "get_tool_scope":
|
|
607896
|
+
return this.formatTelegramToolScopeStatus(env2.context, env2.currentMsg, targetChatId);
|
|
607897
|
+
case "get_me":
|
|
607898
|
+
return this.telegramApiResult("getMe", {});
|
|
607899
|
+
case "get_chat":
|
|
607900
|
+
if (targetChatId === void 0) throw new Error("target/chat_id is required for get_chat.");
|
|
607901
|
+
return this.telegramApiResult("getChat", { chat_id: targetChatId });
|
|
607902
|
+
case "get_chat_member":
|
|
607903
|
+
if (targetChatId === void 0 || userId === void 0) throw new Error("target/chat_id and user_id are required for get_chat_member.");
|
|
607904
|
+
return this.telegramApiResult("getChatMember", { chat_id: targetChatId, user_id: userId });
|
|
607905
|
+
case "get_chat_administrators":
|
|
607906
|
+
if (targetChatId === void 0) throw new Error("target/chat_id is required for get_chat_administrators.");
|
|
607907
|
+
return this.getChatAdministrators(targetChatId, args["return_bots"] === true);
|
|
607908
|
+
case "get_message_context":
|
|
607909
|
+
if (targetChatId === void 0) throw new Error("target/chat_id is required for get_message_context.");
|
|
607910
|
+
return this.telegramMessageContext(targetChatId, messageId);
|
|
607911
|
+
case "send_message": {
|
|
607912
|
+
if (targetChatId === void 0) throw new Error("target/chat_id is required for send_message.");
|
|
607913
|
+
const text = String(args["text"] || "").trim();
|
|
607914
|
+
if (!text) throw new Error("text is required for send_message.");
|
|
607915
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { text });
|
|
607916
|
+
const sent = await this.sendMessage(targetChatId, text);
|
|
607917
|
+
return { action, telegram_method: "sendMessage", ok: true, chat_id: targetChatId, message_id: sent };
|
|
607918
|
+
}
|
|
607919
|
+
case "edit_message_text": {
|
|
607920
|
+
if (targetChatId === void 0 || messageId === void 0) throw new Error("target/chat_id and message_id are required for edit_message_text.");
|
|
607921
|
+
const text = String(args["text"] || "").trim();
|
|
607922
|
+
if (!text) throw new Error("text is required for edit_message_text.");
|
|
607923
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { message_id: messageId, text });
|
|
607924
|
+
return this.telegramApiResult("editMessageText", { chat_id: targetChatId, message_id: messageId, text: convertMarkdownToTelegramHTML(text), parse_mode: "HTML" });
|
|
607925
|
+
}
|
|
607926
|
+
case "edit_message_caption": {
|
|
607927
|
+
if (targetChatId === void 0 || messageId === void 0) throw new Error("target/chat_id and message_id are required for edit_message_caption.");
|
|
607928
|
+
const caption = String(args["caption"] ?? args["text"] ?? "").trim();
|
|
607929
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { message_id: messageId, caption });
|
|
607930
|
+
return this.telegramApiResult("editMessageCaption", { chat_id: targetChatId, message_id: messageId, caption: convertMarkdownToTelegramHTML(caption), parse_mode: "HTML" });
|
|
607931
|
+
}
|
|
607932
|
+
case "edit_message_reply_markup": {
|
|
607933
|
+
if (targetChatId === void 0 || messageId === void 0) throw new Error("target/chat_id and message_id are required for edit_message_reply_markup.");
|
|
607934
|
+
const replyMarkup = this.telegramObjectArg(args["reply_markup"]);
|
|
607935
|
+
if (!replyMarkup) throw new Error("reply_markup object is required for edit_message_reply_markup.");
|
|
607936
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { message_id: messageId, reply_markup: replyMarkup });
|
|
607937
|
+
return this.telegramApiResult("editMessageReplyMarkup", { chat_id: targetChatId, message_id: messageId, reply_markup: replyMarkup });
|
|
607938
|
+
}
|
|
607939
|
+
case "delete_message": {
|
|
607940
|
+
if (targetChatId === void 0 || messageId === void 0) throw new Error("target/chat_id and message_id are required for delete_message.");
|
|
607941
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { message_id: messageId });
|
|
607942
|
+
return this.deleteTelegramMessage(targetChatId, messageId, env2.currentMsg);
|
|
607943
|
+
}
|
|
607944
|
+
case "delete_messages": {
|
|
607945
|
+
if (targetChatId === void 0 || messageIds.length === 0) throw new Error("target/chat_id and message_ids are required for delete_messages.");
|
|
607946
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { message_ids: messageIds });
|
|
607947
|
+
return this.deleteTelegramMessages(targetChatId, messageIds, env2.currentMsg);
|
|
607948
|
+
}
|
|
607949
|
+
case "pin_message":
|
|
607950
|
+
if (targetChatId === void 0 || messageId === void 0) throw new Error("target/chat_id and message_id are required for pin_message.");
|
|
607951
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { message_id: messageId });
|
|
607952
|
+
return this.telegramApiResult("pinChatMessage", { chat_id: targetChatId, message_id: messageId, disable_notification: args["disable_notification"] === true });
|
|
607953
|
+
case "unpin_message":
|
|
607954
|
+
if (targetChatId === void 0 || messageId === void 0) throw new Error("target/chat_id and message_id are required for unpin_message.");
|
|
607955
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { message_id: messageId });
|
|
607956
|
+
return this.telegramApiResult("unpinChatMessage", { chat_id: targetChatId, message_id: messageId });
|
|
607957
|
+
case "unpin_all_messages":
|
|
607958
|
+
if (targetChatId === void 0) throw new Error("target/chat_id is required for unpin_all_messages.");
|
|
607959
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, {});
|
|
607960
|
+
return this.telegramApiResult("unpinAllChatMessages", { chat_id: targetChatId });
|
|
607961
|
+
case "set_message_reaction":
|
|
607962
|
+
if (targetChatId === void 0 || messageId === void 0) throw new Error("target/chat_id and message_id are required for set_message_reaction.");
|
|
607963
|
+
if (!Array.isArray(args["reaction"])) throw new Error("reaction array is required for set_message_reaction.");
|
|
607964
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { message_id: messageId, reaction: args["reaction"] });
|
|
607965
|
+
return this.telegramApiResult("setMessageReaction", {
|
|
607966
|
+
chat_id: targetChatId,
|
|
607967
|
+
message_id: messageId,
|
|
607968
|
+
reaction: args["reaction"],
|
|
607969
|
+
is_big: args["is_big"] === true
|
|
607970
|
+
});
|
|
607971
|
+
case "delete_message_reaction":
|
|
607972
|
+
if (targetChatId === void 0 || messageId === void 0) throw new Error("target/chat_id and message_id are required for delete_message_reaction.");
|
|
607973
|
+
if (userId === void 0 && args["actor_chat_id"] === void 0) throw new Error("user_id or actor_chat_id is required for delete_message_reaction.");
|
|
607974
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { message_id: messageId, user_id: userId });
|
|
607975
|
+
return { action, ok: await this.deleteMessageReaction(targetChatId, messageId, { userId, actorChatId: args["actor_chat_id"] }) };
|
|
607976
|
+
case "delete_all_message_reactions":
|
|
607977
|
+
if (targetChatId === void 0) throw new Error("target/chat_id is required for delete_all_message_reactions.");
|
|
607978
|
+
if (userId === void 0 && args["actor_chat_id"] === void 0) throw new Error("user_id or actor_chat_id is required for delete_all_message_reactions.");
|
|
607979
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { user_id: userId });
|
|
607980
|
+
return { action, ok: await this.deleteAllMessageReactions(targetChatId, { userId, actorChatId: args["actor_chat_id"] }) };
|
|
607981
|
+
case "send_file": {
|
|
607982
|
+
const tool = this.buildTelegramSendFileTool(env2.context, env2.repoRoot, env2.chatId, env2.currentMsg);
|
|
607983
|
+
const result = await tool.execute(args);
|
|
607984
|
+
if (!result.success) throw new Error(result.error || result.output || "telegram send_file failed");
|
|
607985
|
+
return { action, ok: true, output: result.output };
|
|
607986
|
+
}
|
|
607987
|
+
case "send_photo":
|
|
607988
|
+
case "send_document":
|
|
607989
|
+
case "send_audio":
|
|
607990
|
+
case "send_voice":
|
|
607991
|
+
case "send_video": {
|
|
607992
|
+
const kind = action.slice("send_".length);
|
|
607993
|
+
const tool = this.buildTelegramSendFileTool(env2.context, env2.repoRoot, env2.chatId, env2.currentMsg);
|
|
607994
|
+
const result = await tool.execute({ ...args, kind });
|
|
607995
|
+
if (!result.success) throw new Error(result.error || result.output || `telegram ${action} failed`);
|
|
607996
|
+
return { action, ok: true, output: result.output };
|
|
607997
|
+
}
|
|
607998
|
+
case "ban_chat_member":
|
|
607999
|
+
if (targetChatId === void 0 || userId === void 0) throw new Error("target/chat_id and user_id are required for ban_chat_member.");
|
|
608000
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { user_id: userId });
|
|
608001
|
+
return this.telegramApiResult("banChatMember", {
|
|
608002
|
+
chat_id: targetChatId,
|
|
608003
|
+
user_id: userId,
|
|
608004
|
+
...args["until_date"] !== void 0 ? { until_date: this.telegramNumberArg(args["until_date"]) } : {},
|
|
608005
|
+
revoke_messages: args["revoke_messages"] === true
|
|
608006
|
+
});
|
|
608007
|
+
case "unban_chat_member":
|
|
608008
|
+
if (targetChatId === void 0 || userId === void 0) throw new Error("target/chat_id and user_id are required for unban_chat_member.");
|
|
608009
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { user_id: userId });
|
|
608010
|
+
return this.telegramApiResult("unbanChatMember", {
|
|
608011
|
+
chat_id: targetChatId,
|
|
608012
|
+
user_id: userId,
|
|
608013
|
+
only_if_banned: args["only_if_banned"] === true
|
|
608014
|
+
});
|
|
608015
|
+
case "restrict_chat_member": {
|
|
608016
|
+
if (targetChatId === void 0 || userId === void 0) throw new Error("target/chat_id, user_id, and permissions are required for restrict_chat_member.");
|
|
608017
|
+
const permissions = this.telegramObjectArg(args["permissions"]);
|
|
608018
|
+
if (!permissions) throw new Error("permissions object is required for restrict_chat_member.");
|
|
608019
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { user_id: userId, permissions });
|
|
608020
|
+
return this.telegramApiResult("restrictChatMember", {
|
|
608021
|
+
chat_id: targetChatId,
|
|
608022
|
+
user_id: userId,
|
|
608023
|
+
permissions,
|
|
608024
|
+
...args["until_date"] !== void 0 ? { until_date: this.telegramNumberArg(args["until_date"]) } : {},
|
|
608025
|
+
use_independent_chat_permissions: args["use_independent_chat_permissions"] === true
|
|
608026
|
+
});
|
|
608027
|
+
}
|
|
608028
|
+
case "promote_chat_member": {
|
|
608029
|
+
if (targetChatId === void 0 || userId === void 0) throw new Error("target/chat_id, user_id, and rights are required for promote_chat_member.");
|
|
608030
|
+
const rights = this.telegramObjectArg(args["rights"]);
|
|
608031
|
+
if (!rights) throw new Error("rights object is required for promote_chat_member.");
|
|
608032
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { user_id: userId, rights });
|
|
608033
|
+
return this.telegramApiResult("promoteChatMember", { chat_id: targetChatId, user_id: userId, ...rights });
|
|
608034
|
+
}
|
|
608035
|
+
case "set_chat_permissions": {
|
|
608036
|
+
if (targetChatId === void 0) throw new Error("target/chat_id and permissions are required for set_chat_permissions.");
|
|
608037
|
+
const permissions = this.telegramObjectArg(args["permissions"]);
|
|
608038
|
+
if (!permissions) throw new Error("permissions object is required for set_chat_permissions.");
|
|
608039
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { permissions });
|
|
608040
|
+
return this.telegramApiResult("setChatPermissions", {
|
|
608041
|
+
chat_id: targetChatId,
|
|
608042
|
+
permissions,
|
|
608043
|
+
use_independent_chat_permissions: args["use_independent_chat_permissions"] === true
|
|
608044
|
+
});
|
|
608045
|
+
}
|
|
608046
|
+
case "approve_chat_join_request":
|
|
608047
|
+
if (targetChatId === void 0 || userId === void 0) throw new Error("target/chat_id and user_id are required for approve_chat_join_request.");
|
|
608048
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { user_id: userId });
|
|
608049
|
+
return this.telegramApiResult("approveChatJoinRequest", { chat_id: targetChatId, user_id: userId });
|
|
608050
|
+
case "decline_chat_join_request":
|
|
608051
|
+
if (targetChatId === void 0 || userId === void 0) throw new Error("target/chat_id and user_id are required for decline_chat_join_request.");
|
|
608052
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId, { user_id: userId });
|
|
608053
|
+
return this.telegramApiResult("declineChatJoinRequest", { chat_id: targetChatId, user_id: userId });
|
|
608054
|
+
case "set_my_commands": {
|
|
608055
|
+
if (!Array.isArray(args["commands"])) throw new Error("commands array is required for set_my_commands.");
|
|
608056
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId ?? "bot", { commands: args["commands"] });
|
|
608057
|
+
return this.telegramApiResult("setMyCommands", {
|
|
608058
|
+
commands: args["commands"],
|
|
608059
|
+
...args["language_code"] ? { language_code: String(args["language_code"]) } : {}
|
|
608060
|
+
});
|
|
608061
|
+
}
|
|
608062
|
+
case "get_my_commands":
|
|
608063
|
+
return this.telegramApiResult("getMyCommands", args["language_code"] ? { language_code: String(args["language_code"]) } : {});
|
|
608064
|
+
case "set_chat_menu_button": {
|
|
608065
|
+
const menuButton = this.telegramObjectArg(args["menu_button"]);
|
|
608066
|
+
if (!menuButton) throw new Error("menu_button object is required for set_chat_menu_button.");
|
|
608067
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId ?? "bot", { menu_button: menuButton });
|
|
608068
|
+
return this.telegramApiResult("setChatMenuButton", {
|
|
608069
|
+
...targetChatId !== void 0 ? { chat_id: targetChatId } : {},
|
|
608070
|
+
menu_button: menuButton
|
|
608071
|
+
});
|
|
608072
|
+
}
|
|
608073
|
+
case "get_chat_menu_button":
|
|
608074
|
+
return this.telegramApiResult("getChatMenuButton", targetChatId !== void 0 ? { chat_id: targetChatId } : {});
|
|
608075
|
+
case "set_my_description": {
|
|
608076
|
+
const description = String(args["description"] ?? args["text"] ?? "");
|
|
608077
|
+
if (dryRun) return this.telegramDryRun(action, targetChatId ?? "bot", { description });
|
|
608078
|
+
return this.telegramApiResult("setMyDescription", {
|
|
608079
|
+
description,
|
|
608080
|
+
...args["language_code"] ? { language_code: String(args["language_code"]) } : {}
|
|
608081
|
+
});
|
|
608082
|
+
}
|
|
608083
|
+
case "get_my_description":
|
|
608084
|
+
return this.telegramApiResult("getMyDescription", args["language_code"] ? { language_code: String(args["language_code"]) } : {});
|
|
608085
|
+
case "enable_group":
|
|
608086
|
+
case "disable_group":
|
|
608087
|
+
return this.setTelegramToolGroupPolicy(args, action === "enable_group", targetChatId);
|
|
608088
|
+
case "enable_action":
|
|
608089
|
+
case "disable_action":
|
|
608090
|
+
return this.setTelegramToolActionPolicy(args, action === "enable_action", targetChatId);
|
|
608091
|
+
case "render_admin_buttons":
|
|
608092
|
+
if (!env2.currentMsg) throw new Error("render_admin_buttons requires a Telegram message context.");
|
|
608093
|
+
if (dryRun) return this.telegramDryRun(action, env2.currentMsg.chatId, {});
|
|
608094
|
+
return this.sendTelegramToolPanel(env2.currentMsg.chatId, String(args["scope"] || "").toLowerCase() === "chat" ? targetChatId : void 0);
|
|
608095
|
+
default:
|
|
608096
|
+
throw new Error(`Unsupported Telegram action: ${action}`);
|
|
608097
|
+
}
|
|
608098
|
+
}
|
|
608099
|
+
cloneTelegramToolPolicy(policy) {
|
|
608100
|
+
return JSON.parse(JSON.stringify(policy ?? {}));
|
|
608101
|
+
}
|
|
608102
|
+
telegramToolHasExplicitTarget(args) {
|
|
608103
|
+
return ["target", "chat_id", "target_chat_id", "username"].some((key) => {
|
|
608104
|
+
const value2 = args[key];
|
|
608105
|
+
return value2 !== void 0 && String(value2).trim() !== "";
|
|
608106
|
+
});
|
|
608107
|
+
}
|
|
608108
|
+
telegramObjectArg(value2) {
|
|
608109
|
+
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) return void 0;
|
|
608110
|
+
return value2;
|
|
608111
|
+
}
|
|
608112
|
+
telegramNumberArg(value2) {
|
|
608113
|
+
if (typeof value2 === "number" && Number.isFinite(value2)) return Math.trunc(value2);
|
|
608114
|
+
if (typeof value2 === "string" && /^-?\d+$/.test(value2.trim())) return Number(value2.trim());
|
|
608115
|
+
return void 0;
|
|
608116
|
+
}
|
|
608117
|
+
telegramMessageIdsArg(value2) {
|
|
608118
|
+
if (Array.isArray(value2)) {
|
|
608119
|
+
return [...new Set(value2.map((item) => this.telegramNumberArg(item)).filter((item) => item !== void 0))];
|
|
608120
|
+
}
|
|
608121
|
+
if (typeof value2 === "string" && value2.includes(",")) {
|
|
608122
|
+
return [...new Set(value2.split(",").map((item) => this.telegramNumberArg(item.trim())).filter((item) => item !== void 0))];
|
|
608123
|
+
}
|
|
608124
|
+
const single = this.telegramNumberArg(value2);
|
|
608125
|
+
return single === void 0 ? [] : [single];
|
|
608126
|
+
}
|
|
608127
|
+
effectiveTelegramToolPolicy(chatId) {
|
|
608128
|
+
const base3 = this.cloneTelegramToolPolicy(this.telegramToolPolicy);
|
|
608129
|
+
const override = chatId !== void 0 ? base3.chatOverrides?.[String(chatId)] : void 0;
|
|
608130
|
+
if (!override) return base3;
|
|
608131
|
+
return {
|
|
608132
|
+
...base3,
|
|
608133
|
+
enabledActionGroups: {
|
|
608134
|
+
...base3.enabledActionGroups ?? {},
|
|
608135
|
+
...override.enabledActionGroups ?? {}
|
|
608136
|
+
},
|
|
608137
|
+
enabledActions: {
|
|
608138
|
+
...base3.enabledActions ?? {},
|
|
608139
|
+
...override.enabledActions ?? {}
|
|
608140
|
+
},
|
|
608141
|
+
requireAdminForMutation: override.requireAdminForMutation ?? base3.requireAdminForMutation,
|
|
608142
|
+
dryRunByDefault: override.dryRunByDefault ?? base3.dryRunByDefault
|
|
608143
|
+
};
|
|
608144
|
+
}
|
|
608145
|
+
telegramToolActionEnabled(action, chatId) {
|
|
608146
|
+
const group = TELEGRAM_TOOL_ACTION_GROUP[action];
|
|
608147
|
+
if (!group) return false;
|
|
608148
|
+
const policy = this.effectiveTelegramToolPolicy(chatId);
|
|
608149
|
+
const actionOverride = policy.enabledActions?.[action];
|
|
608150
|
+
if (actionOverride !== void 0) return actionOverride;
|
|
608151
|
+
const groupOverride = policy.enabledActionGroups?.[group];
|
|
608152
|
+
if (groupOverride !== void 0) return groupOverride;
|
|
608153
|
+
return DEFAULT_TELEGRAM_TOOL_GROUP_POLICY[group];
|
|
608154
|
+
}
|
|
608155
|
+
telegramToolDryRun(args, chatId) {
|
|
608156
|
+
if (args["dry_run"] === true) return true;
|
|
608157
|
+
if (args["dry_run"] === false) return false;
|
|
608158
|
+
return this.effectiveTelegramToolPolicy(chatId).dryRunByDefault === true;
|
|
608159
|
+
}
|
|
608160
|
+
isAdminActor(userId, username) {
|
|
608161
|
+
if (!this.adminUserId) return false;
|
|
608162
|
+
if (userId !== void 0 && String(userId) === this.adminUserId) return true;
|
|
608163
|
+
return Boolean(username && username === this.adminUserId);
|
|
608164
|
+
}
|
|
608165
|
+
assertTelegramToolActionAllowed(action, context2, currentMsg, targetChatId, args) {
|
|
608166
|
+
const group = TELEGRAM_TOOL_ACTION_GROUP[action];
|
|
608167
|
+
if (!group) return { ok: false, error: `Unsupported Telegram action: ${action}` };
|
|
608168
|
+
const currentChatId = currentMsg?.chatId;
|
|
608169
|
+
const isCurrentChat = currentChatId === void 0 || targetChatId === void 0 || String(currentChatId) === String(targetChatId);
|
|
608170
|
+
const allowedPrivateSharedGroupMedia = group === "media" && currentMsg?.chatType === "private";
|
|
608171
|
+
if (context2 !== "telegram-admin-dm" && !isCurrentChat && !allowedPrivateSharedGroupMedia) {
|
|
608172
|
+
return { ok: false, error: "This Telegram context can only target the current chat." };
|
|
608173
|
+
}
|
|
608174
|
+
if (context2 === "telegram-public" && (group === "janitorial" || group === "reaction" || group === "moderation" || group === "bot_admin" || group === "policy" || group === "message")) {
|
|
608175
|
+
return { ok: false, error: `Telegram ${group} actions require authenticated admin context.` };
|
|
608176
|
+
}
|
|
608177
|
+
if ((group === "policy" || group === "bot_admin" || group === "moderation") && context2 !== "telegram-admin-dm" && context2 !== "telegram-admin-group") {
|
|
608178
|
+
return { ok: false, error: `Telegram ${group} actions require admin context.` };
|
|
608179
|
+
}
|
|
608180
|
+
const mutating = TELEGRAM_TOOL_MUTATING_GROUPS.has(group);
|
|
608181
|
+
const policy = this.effectiveTelegramToolPolicy(targetChatId);
|
|
608182
|
+
if (mutating && policy.requireAdminForMutation !== false && context2 === "telegram-public" && group !== "media") {
|
|
608183
|
+
return { ok: false, error: "Telegram mutation requires admin context by policy." };
|
|
608184
|
+
}
|
|
608185
|
+
if (!this.telegramToolActionEnabled(action, targetChatId)) {
|
|
608186
|
+
const scope = targetChatId !== void 0 && this.telegramToolPolicy.chatOverrides?.[String(targetChatId)] ? `chat ${String(targetChatId)}` : "global/default";
|
|
608187
|
+
return { ok: false, error: `Telegram action ${action} is disabled by ${scope} policy. Enable ${group} or ${action} first.` };
|
|
608188
|
+
}
|
|
608189
|
+
if ((action === "delete_messages" || group === "moderation") && !String(args["reason"] || "").trim()) {
|
|
608190
|
+
return { ok: false, error: `Telegram ${action} requires a short reason for the audit trail.` };
|
|
608191
|
+
}
|
|
608192
|
+
return { ok: true };
|
|
608193
|
+
}
|
|
608194
|
+
formatTelegramToolScopeStatus(context2, currentMsg, targetChatId) {
|
|
608195
|
+
const effective = this.effectiveTelegramToolPolicy(targetChatId);
|
|
608196
|
+
const groups = TELEGRAM_TOOL_ACTION_GROUPS.map((group) => ({
|
|
608197
|
+
group,
|
|
608198
|
+
enabled: effective.enabledActionGroups?.[group] ?? DEFAULT_TELEGRAM_TOOL_GROUP_POLICY[group],
|
|
608199
|
+
default: DEFAULT_TELEGRAM_TOOL_GROUP_POLICY[group]
|
|
608200
|
+
}));
|
|
608201
|
+
const knownTargets = context2 === "telegram-admin-dm" ? this.knownTelegramChatTargets().slice(0, 12).map((target) => ({
|
|
608202
|
+
chat_id: target.chatId,
|
|
608203
|
+
chat_type: target.chatType,
|
|
608204
|
+
title: target.title,
|
|
608205
|
+
session: target.sessionKey
|
|
608206
|
+
})) : [];
|
|
608207
|
+
return {
|
|
608208
|
+
context: context2,
|
|
608209
|
+
current_chat_id: currentMsg?.chatId,
|
|
608210
|
+
current_chat_type: currentMsg?.chatType,
|
|
608211
|
+
target_chat_id: targetChatId,
|
|
608212
|
+
bot_username: this.state.botUsername || void 0,
|
|
608213
|
+
admin_configured: Boolean(this.adminUserId),
|
|
608214
|
+
effective_policy: {
|
|
608215
|
+
groups,
|
|
608216
|
+
enabled_actions: effective.enabledActions ?? {},
|
|
608217
|
+
dry_run_by_default: effective.dryRunByDefault === true,
|
|
608218
|
+
require_admin_for_mutation: effective.requireAdminForMutation !== false
|
|
608219
|
+
},
|
|
608220
|
+
known_targets: knownTargets
|
|
608221
|
+
};
|
|
608222
|
+
}
|
|
608223
|
+
telegramMessageContext(chatId, messageId) {
|
|
608224
|
+
this.ensureAllTelegramConversationsLoaded();
|
|
608225
|
+
const sessionKey = `chat:${String(chatId)}`;
|
|
608226
|
+
const history = this.chatHistory.get(sessionKey) ?? [];
|
|
608227
|
+
if (messageId === void 0) {
|
|
608228
|
+
return {
|
|
608229
|
+
chat_id: chatId,
|
|
608230
|
+
recent: history.slice(-20)
|
|
608231
|
+
};
|
|
608232
|
+
}
|
|
608233
|
+
const index = history.findIndex((entry) => entry.messageId === messageId);
|
|
608234
|
+
if (index === -1) {
|
|
608235
|
+
return {
|
|
608236
|
+
chat_id: chatId,
|
|
608237
|
+
message_id: messageId,
|
|
608238
|
+
found: false,
|
|
608239
|
+
recent: history.slice(-10)
|
|
608240
|
+
};
|
|
608241
|
+
}
|
|
608242
|
+
return {
|
|
608243
|
+
chat_id: chatId,
|
|
608244
|
+
message_id: messageId,
|
|
608245
|
+
found: true,
|
|
608246
|
+
before: history.slice(Math.max(0, index - 5), index),
|
|
608247
|
+
message: history[index],
|
|
608248
|
+
after: history.slice(index + 1, index + 6)
|
|
608249
|
+
};
|
|
608250
|
+
}
|
|
608251
|
+
telegramDryRun(action, chatId, detail) {
|
|
608252
|
+
return {
|
|
608253
|
+
action,
|
|
608254
|
+
dry_run: true,
|
|
608255
|
+
ok: true,
|
|
608256
|
+
chat_id: chatId,
|
|
608257
|
+
would_call_telegram: true,
|
|
608258
|
+
detail,
|
|
608259
|
+
policy_scope: this.telegramToolPolicy.chatOverrides?.[String(chatId)] ? "chat" : "global/default"
|
|
608260
|
+
};
|
|
608261
|
+
}
|
|
608262
|
+
async telegramApiResult(method, body) {
|
|
608263
|
+
const result = await this.apiCall(method, body);
|
|
608264
|
+
if (!result.ok) throw new Error(String(result.description || `Telegram ${method} failed`));
|
|
608265
|
+
if (method.startsWith("send") || method === "copyMessage" || method === "forwardMessage") this.state.messagesSent++;
|
|
608266
|
+
return {
|
|
608267
|
+
telegram_method: method,
|
|
608268
|
+
ok: true,
|
|
608269
|
+
result: result.result ?? true
|
|
608270
|
+
};
|
|
608271
|
+
}
|
|
608272
|
+
async getTelegramBotUserId() {
|
|
608273
|
+
if (this.botUserId !== null) return this.botUserId;
|
|
608274
|
+
const result = await this.apiCall("getMe", {});
|
|
608275
|
+
if (!result.ok || typeof result.result?.id !== "number") {
|
|
608276
|
+
throw new Error(String(result.description || "Telegram getMe did not return a bot id."));
|
|
608277
|
+
}
|
|
608278
|
+
const botId = result.result.id;
|
|
608279
|
+
this.botUserId = botId;
|
|
608280
|
+
if (typeof result.result.username === "string") this.state.botUsername = result.result.username;
|
|
608281
|
+
return botId;
|
|
608282
|
+
}
|
|
608283
|
+
async getChatMember(chatId, userId) {
|
|
608284
|
+
const result = await this.apiCall("getChatMember", { chat_id: chatId, user_id: userId });
|
|
608285
|
+
if (!result.ok) return null;
|
|
608286
|
+
return result.result && typeof result.result === "object" ? result.result : null;
|
|
608287
|
+
}
|
|
608288
|
+
async getBotChatRights(chatId, force = false) {
|
|
608289
|
+
const key = String(chatId);
|
|
608290
|
+
const cached = this.telegramBotRightsCache.get(key);
|
|
608291
|
+
if (!force && cached && Date.now() - cached.checkedAt < 6e4) return cached;
|
|
608292
|
+
const botId = await this.getTelegramBotUserId();
|
|
608293
|
+
const member = await this.getChatMember(chatId, botId);
|
|
608294
|
+
if (!member) throw new Error(`Could not inspect Telegram bot rights for chat ${String(chatId)}.`);
|
|
608295
|
+
const status = String(member.status || "unknown");
|
|
608296
|
+
const rights = {
|
|
608297
|
+
chatId,
|
|
608298
|
+
status,
|
|
608299
|
+
isCreator: status === "creator",
|
|
608300
|
+
isAdministrator: status === "creator" || status === "administrator",
|
|
608301
|
+
canDeleteMessages: status === "creator" || member.can_delete_messages === true,
|
|
608302
|
+
canPinMessages: status === "creator" || member.can_pin_messages === true,
|
|
608303
|
+
canRestrictMembers: status === "creator" || member.can_restrict_members === true,
|
|
608304
|
+
canPromoteMembers: status === "creator" || member.can_promote_members === true,
|
|
608305
|
+
canManageChat: status === "creator" || member.can_manage_chat === true,
|
|
608306
|
+
canChangeInfo: status === "creator" || member.can_change_info === true,
|
|
608307
|
+
checkedAt: Date.now(),
|
|
608308
|
+
raw: member
|
|
608309
|
+
};
|
|
608310
|
+
this.telegramBotRightsCache.set(key, rights);
|
|
608311
|
+
return rights;
|
|
608312
|
+
}
|
|
608313
|
+
isKnownAssistantTelegramMessage(chatId, messageId) {
|
|
608314
|
+
this.ensureAllTelegramConversationsLoaded();
|
|
608315
|
+
for (const history of this.chatHistory.values()) {
|
|
608316
|
+
if (history.some((entry) => entry.role === "assistant" && String(entry.chatId) === String(chatId) && entry.messageId === messageId)) {
|
|
608317
|
+
return true;
|
|
608318
|
+
}
|
|
608319
|
+
}
|
|
608320
|
+
return false;
|
|
608321
|
+
}
|
|
608322
|
+
telegramTargetLooksPrivate(chatId, currentMsg) {
|
|
608323
|
+
if (currentMsg && String(currentMsg.chatId) === String(chatId) && currentMsg.chatType === "private") return true;
|
|
608324
|
+
return typeof chatId === "number" && chatId > 0;
|
|
608325
|
+
}
|
|
608326
|
+
async assertTelegramBotRightsForAction(action, chatId, messageIds, currentMsg) {
|
|
608327
|
+
if (chatId === void 0) return;
|
|
608328
|
+
const group = TELEGRAM_TOOL_ACTION_GROUP[action];
|
|
608329
|
+
if (!group || group === "read" || group === "media" || group === "policy" || group === "bot_admin") return;
|
|
608330
|
+
if (group === "message" && action !== "pin_message" && action !== "unpin_message" && action !== "unpin_all_messages") return;
|
|
608331
|
+
if (this.telegramTargetLooksPrivate(chatId, currentMsg)) return;
|
|
608332
|
+
if (action === "delete_message" || action === "delete_messages") {
|
|
608333
|
+
if (messageIds.length > 0 && messageIds.every((id) => this.isKnownAssistantTelegramMessage(chatId, id))) return;
|
|
608334
|
+
const rights2 = await this.getBotChatRights(chatId);
|
|
608335
|
+
if (!rights2.canDeleteMessages) {
|
|
608336
|
+
throw new Error(`Bot lacks can_delete_messages in chat ${String(chatId)}; Telegram status=${rights2.status}.`);
|
|
608337
|
+
}
|
|
608338
|
+
return;
|
|
608339
|
+
}
|
|
608340
|
+
const rights = await this.getBotChatRights(chatId);
|
|
608341
|
+
if ((action === "pin_message" || action === "unpin_message" || action === "unpin_all_messages") && !rights.canPinMessages && !rights.canManageChat) {
|
|
608342
|
+
throw new Error(`Bot lacks pin/manage rights in chat ${String(chatId)}; Telegram status=${rights.status}.`);
|
|
608343
|
+
}
|
|
608344
|
+
if ((action === "ban_chat_member" || action === "unban_chat_member" || action === "restrict_chat_member" || action === "set_chat_permissions" || action === "approve_chat_join_request" || action === "decline_chat_join_request") && !rights.canRestrictMembers) {
|
|
608345
|
+
throw new Error(`Bot lacks restrict/member management rights in chat ${String(chatId)}; Telegram status=${rights.status}.`);
|
|
608346
|
+
}
|
|
608347
|
+
if (action === "promote_chat_member" && !rights.canPromoteMembers) {
|
|
608348
|
+
throw new Error(`Bot lacks promote rights in chat ${String(chatId)}; Telegram status=${rights.status}.`);
|
|
608349
|
+
}
|
|
608350
|
+
}
|
|
608351
|
+
async deleteTelegramMessage(chatId, messageId, currentMsg) {
|
|
608352
|
+
await this.assertTelegramBotRightsForAction("delete_message", chatId, [messageId], currentMsg);
|
|
608353
|
+
const result = await this.apiCall("deleteMessage", { chat_id: chatId, message_id: messageId });
|
|
608354
|
+
if (!result.ok) throw new Error(String(result.description || "Telegram deleteMessage failed"));
|
|
608355
|
+
return {
|
|
608356
|
+
action: "delete_message",
|
|
608357
|
+
telegram_method: "deleteMessage",
|
|
608358
|
+
ok: true,
|
|
608359
|
+
chat_id: chatId,
|
|
608360
|
+
message_id: messageId,
|
|
608361
|
+
bot_rights_checked: !this.telegramTargetLooksPrivate(chatId, currentMsg) && !this.isKnownAssistantTelegramMessage(chatId, messageId),
|
|
608362
|
+
policy_scope: this.telegramToolPolicy.chatOverrides?.[String(chatId)] ? "chat" : "global/default"
|
|
608363
|
+
};
|
|
608364
|
+
}
|
|
608365
|
+
async deleteTelegramMessages(chatId, messageIds, currentMsg) {
|
|
608366
|
+
const unique = [...new Set(messageIds)].filter((id) => Number.isFinite(id));
|
|
608367
|
+
if (unique.length === 0) throw new Error("deleteTelegramMessages requires at least one message id.");
|
|
608368
|
+
await this.assertTelegramBotRightsForAction("delete_messages", chatId, unique, currentMsg);
|
|
608369
|
+
const chunks = [];
|
|
608370
|
+
for (let idx = 0; idx < unique.length; idx += 100) chunks.push(unique.slice(idx, idx + 100));
|
|
608371
|
+
const results = [];
|
|
608372
|
+
for (const chunk of chunks) {
|
|
608373
|
+
const result = await this.apiCall("deleteMessages", { chat_id: chatId, message_ids: chunk });
|
|
608374
|
+
if (!result.ok) throw new Error(String(result.description || "Telegram deleteMessages failed"));
|
|
608375
|
+
results.push({ message_ids: chunk, ok: true });
|
|
608376
|
+
}
|
|
608377
|
+
return {
|
|
608378
|
+
action: "delete_messages",
|
|
608379
|
+
telegram_method: "deleteMessages",
|
|
608380
|
+
ok: true,
|
|
608381
|
+
chat_id: chatId,
|
|
608382
|
+
message_ids: unique,
|
|
608383
|
+
batches: results,
|
|
608384
|
+
bot_rights_checked: !this.telegramTargetLooksPrivate(chatId, currentMsg) && !unique.every((id) => this.isKnownAssistantTelegramMessage(chatId, id)),
|
|
608385
|
+
policy_scope: this.telegramToolPolicy.chatOverrides?.[String(chatId)] ? "chat" : "global/default"
|
|
608386
|
+
};
|
|
608387
|
+
}
|
|
608388
|
+
telegramToolPolicyTarget(args, targetChatId) {
|
|
608389
|
+
const requested = String(args["scope"] || "").trim().toLowerCase();
|
|
608390
|
+
if (requested === "chat" || targetChatId !== void 0 && this.telegramToolHasExplicitTarget(args)) {
|
|
608391
|
+
if (targetChatId === void 0) throw new Error("scope=chat requires target/chat_id.");
|
|
608392
|
+
return { scope: "chat", chatId: targetChatId };
|
|
608393
|
+
}
|
|
608394
|
+
return { scope: "global" };
|
|
608395
|
+
}
|
|
608396
|
+
persistTelegramToolPolicy() {
|
|
608397
|
+
if (!this.repoRoot) return;
|
|
608398
|
+
saveProjectSettings(this.repoRoot, { telegramToolPolicy: this.cloneTelegramToolPolicy(this.telegramToolPolicy) });
|
|
608399
|
+
}
|
|
608400
|
+
setTelegramToolGroupPolicy(args, enabled2, targetChatId) {
|
|
608401
|
+
const group = String(args["group"] || "").trim().toLowerCase();
|
|
608402
|
+
if (!TELEGRAM_TOOL_ACTION_GROUPS.includes(group)) throw new Error(`Unknown Telegram action group: ${group || "(missing)"}`);
|
|
608403
|
+
const target = this.telegramToolPolicyTarget(args, targetChatId);
|
|
608404
|
+
if (target.scope === "chat") {
|
|
608405
|
+
const key = String(target.chatId);
|
|
608406
|
+
this.telegramToolPolicy.chatOverrides ??= {};
|
|
608407
|
+
const override = this.telegramToolPolicy.chatOverrides[key] ?? {};
|
|
608408
|
+
override.enabledActionGroups = { ...override.enabledActionGroups ?? {}, [group]: enabled2 };
|
|
608409
|
+
this.telegramToolPolicy.chatOverrides[key] = override;
|
|
608410
|
+
} else {
|
|
608411
|
+
this.telegramToolPolicy.enabledActionGroups = { ...this.telegramToolPolicy.enabledActionGroups ?? {}, [group]: enabled2 };
|
|
608412
|
+
}
|
|
608413
|
+
this.persistTelegramToolPolicy();
|
|
608414
|
+
return { ok: true, action: enabled2 ? "enable_group" : "disable_group", group, scope: target.scope, chat_id: target.chatId, enabled: enabled2 };
|
|
608415
|
+
}
|
|
608416
|
+
setTelegramToolActionPolicy(args, enabled2, targetChatId) {
|
|
608417
|
+
const toolAction = String(args["tool_action"] ?? args["telegram_action"] ?? "").trim().toLowerCase();
|
|
608418
|
+
if (!toolAction || !(toolAction in TELEGRAM_TOOL_ACTION_GROUP)) throw new Error(`Unknown Telegram action: ${toolAction || "(missing)"}`);
|
|
608419
|
+
const target = this.telegramToolPolicyTarget(args, targetChatId);
|
|
608420
|
+
if (target.scope === "chat") {
|
|
608421
|
+
const key = String(target.chatId);
|
|
608422
|
+
this.telegramToolPolicy.chatOverrides ??= {};
|
|
608423
|
+
const override = this.telegramToolPolicy.chatOverrides[key] ?? {};
|
|
608424
|
+
override.enabledActions = { ...override.enabledActions ?? {}, [toolAction]: enabled2 };
|
|
608425
|
+
this.telegramToolPolicy.chatOverrides[key] = override;
|
|
608426
|
+
} else {
|
|
608427
|
+
this.telegramToolPolicy.enabledActions = { ...this.telegramToolPolicy.enabledActions ?? {}, [toolAction]: enabled2 };
|
|
608428
|
+
}
|
|
608429
|
+
this.persistTelegramToolPolicy();
|
|
608430
|
+
return { ok: true, action: enabled2 ? "enable_action" : "disable_action", tool_action: toolAction, scope: target.scope, chat_id: target.chatId, enabled: enabled2 };
|
|
608431
|
+
}
|
|
608432
|
+
telegramToolButtonPath(nonce) {
|
|
608433
|
+
const safe = nonce.replace(/[^A-Za-z0-9_-]/g, "");
|
|
608434
|
+
return join123(this.telegramToolButtonDir, `${safe}.json`);
|
|
608435
|
+
}
|
|
608436
|
+
writeTelegramToolButtonState(state) {
|
|
608437
|
+
mkdirSync63(this.telegramToolButtonDir, { recursive: true });
|
|
608438
|
+
writeFileSync57(this.telegramToolButtonPath(state.nonce), JSON.stringify(state, null, 2) + "\n", "utf-8");
|
|
608439
|
+
}
|
|
608440
|
+
readTelegramToolButtonState(nonce) {
|
|
608441
|
+
try {
|
|
608442
|
+
const parsed = JSON.parse(readFileSync88(this.telegramToolButtonPath(nonce), "utf-8"));
|
|
608443
|
+
if (!parsed || parsed.expiresAt < Date.now()) return null;
|
|
608444
|
+
return parsed;
|
|
608445
|
+
} catch {
|
|
608446
|
+
return null;
|
|
608447
|
+
}
|
|
608448
|
+
}
|
|
608449
|
+
telegramToolPanelPayload(state) {
|
|
608450
|
+
const policyChatId = state.policyScope === "chat" ? state.policyChatId : void 0;
|
|
608451
|
+
const effective = this.effectiveTelegramToolPolicy(policyChatId);
|
|
608452
|
+
const rows = TELEGRAM_TOOL_ACTION_GROUPS.map((group) => {
|
|
608453
|
+
const enabled2 = effective.enabledActionGroups?.[group] ?? DEFAULT_TELEGRAM_TOOL_GROUP_POLICY[group];
|
|
608454
|
+
return {
|
|
608455
|
+
text: `${enabled2 ? "[x]" : "[ ]"} ${TELEGRAM_TOOL_BUTTON_LABELS[group]}`,
|
|
608456
|
+
callback_data: `omni:v1:tgtool:${state.nonce}:group:${group}`
|
|
608457
|
+
};
|
|
608458
|
+
});
|
|
608459
|
+
const dryRun = effective.dryRunByDefault === true;
|
|
608460
|
+
const requireAdmin = effective.requireAdminForMutation !== false;
|
|
608461
|
+
const keyboard = [];
|
|
608462
|
+
for (let idx = 0; idx < rows.length; idx += 2) keyboard.push(rows.slice(idx, idx + 2));
|
|
608463
|
+
keyboard.push([
|
|
608464
|
+
{ text: `${dryRun ? "[x]" : "[ ]"} Dry run`, callback_data: `omni:v1:tgtool:${state.nonce}:flag:dryrun` },
|
|
608465
|
+
{ text: `${requireAdmin ? "[x]" : "[ ]"} Admin mutations`, callback_data: `omni:v1:tgtool:${state.nonce}:flag:admin` }
|
|
608466
|
+
]);
|
|
608467
|
+
const scopeLabel = state.policyScope === "chat" ? `chat ${String(state.policyChatId)}` : "global";
|
|
608468
|
+
return {
|
|
608469
|
+
text: [
|
|
608470
|
+
"<b>Telegram tool controls</b>",
|
|
608471
|
+
`Scope: <code>${escapeTelegramHTML(scopeLabel)}</code>`,
|
|
608472
|
+
"Buttons toggle Omnius policy only. Telegram bot admin rights are still checked before privileged Bot API calls."
|
|
608473
|
+
].join("\n"),
|
|
608474
|
+
reply_markup: { inline_keyboard: keyboard }
|
|
608475
|
+
};
|
|
608476
|
+
}
|
|
608477
|
+
async sendTelegramToolPanel(panelChatId, policyChatId) {
|
|
608478
|
+
const state = {
|
|
608479
|
+
nonce: randomBytes22(8).toString("hex"),
|
|
608480
|
+
createdAt: Date.now(),
|
|
608481
|
+
expiresAt: Date.now() + 15 * 6e4,
|
|
608482
|
+
panelChatId,
|
|
608483
|
+
policyScope: policyChatId === void 0 ? "global" : "chat",
|
|
608484
|
+
policyChatId
|
|
608485
|
+
};
|
|
608486
|
+
const payload = this.telegramToolPanelPayload(state);
|
|
608487
|
+
const result = await this.apiCall("sendMessage", {
|
|
608488
|
+
chat_id: panelChatId,
|
|
608489
|
+
text: payload.text,
|
|
608490
|
+
parse_mode: "HTML",
|
|
608491
|
+
reply_markup: payload.reply_markup
|
|
608492
|
+
});
|
|
608493
|
+
if (!result.ok) throw new Error(String(result.description || "Telegram sendMessage failed"));
|
|
608494
|
+
this.state.messagesSent++;
|
|
608495
|
+
state.messageId = result.result?.message_id;
|
|
608496
|
+
this.writeTelegramToolButtonState(state);
|
|
608497
|
+
return {
|
|
608498
|
+
action: "render_admin_buttons",
|
|
608499
|
+
telegram_method: "sendMessage",
|
|
608500
|
+
ok: true,
|
|
608501
|
+
chat_id: panelChatId,
|
|
608502
|
+
message_id: state.messageId,
|
|
608503
|
+
policy_scope: state.policyScope,
|
|
608504
|
+
policy_chat_id: state.policyChatId
|
|
608505
|
+
};
|
|
608506
|
+
}
|
|
608507
|
+
async answerCallbackQuery(callbackQueryId, text, showAlert = false) {
|
|
608508
|
+
const result = await this.apiCall("answerCallbackQuery", {
|
|
608509
|
+
callback_query_id: callbackQueryId,
|
|
608510
|
+
...text ? { text } : {},
|
|
608511
|
+
show_alert: showAlert
|
|
608512
|
+
});
|
|
608513
|
+
return Boolean(result.ok);
|
|
608514
|
+
}
|
|
608515
|
+
async handleTelegramCallbackQuery(callback) {
|
|
608516
|
+
let answerText = "Updated.";
|
|
608517
|
+
let alert = false;
|
|
608518
|
+
try {
|
|
608519
|
+
if (!this.isAdminActor(callback.fromUserId, callback.username)) {
|
|
608520
|
+
answerText = "Only the configured Omnius Telegram admin can change tool policy.";
|
|
608521
|
+
alert = true;
|
|
608522
|
+
return;
|
|
608523
|
+
}
|
|
608524
|
+
const parts = callback.data.split(":");
|
|
608525
|
+
if (parts.length !== 6 || parts[0] !== "omni" || parts[1] !== "v1" || parts[2] !== "tgtool") {
|
|
608526
|
+
answerText = "Unknown Omnius Telegram control.";
|
|
608527
|
+
alert = true;
|
|
608528
|
+
return;
|
|
608529
|
+
}
|
|
608530
|
+
const state = this.readTelegramToolButtonState(parts[3] ?? "");
|
|
608531
|
+
if (!state) {
|
|
608532
|
+
answerText = "This Telegram tool panel expired. Open a new one with /telegram tools.";
|
|
608533
|
+
alert = true;
|
|
608534
|
+
return;
|
|
608535
|
+
}
|
|
608536
|
+
const kind = parts[4];
|
|
608537
|
+
const value2 = parts[5];
|
|
608538
|
+
if (kind === "group") {
|
|
608539
|
+
const group = value2;
|
|
608540
|
+
if (!TELEGRAM_TOOL_ACTION_GROUPS.includes(group)) throw new Error(`Unknown group: ${value2}`);
|
|
608541
|
+
const policy = this.effectiveTelegramToolPolicy(state.policyChatId);
|
|
608542
|
+
const enabled2 = !(policy.enabledActionGroups?.[group] ?? DEFAULT_TELEGRAM_TOOL_GROUP_POLICY[group]);
|
|
608543
|
+
this.setTelegramToolGroupPolicy(
|
|
608544
|
+
{ group, scope: state.policyScope, ...state.policyChatId !== void 0 ? { target: String(state.policyChatId) } : {} },
|
|
608545
|
+
enabled2,
|
|
608546
|
+
state.policyChatId
|
|
608547
|
+
);
|
|
608548
|
+
answerText = `${TELEGRAM_TOOL_BUTTON_LABELS[group]} ${enabled2 ? "enabled" : "disabled"}.`;
|
|
608549
|
+
} else if (kind === "flag" && value2 === "dryrun") {
|
|
608550
|
+
this.setTelegramToolBooleanPolicy(state, "dryRunByDefault", this.effectiveTelegramToolPolicy(state.policyChatId).dryRunByDefault !== true);
|
|
608551
|
+
answerText = "Dry-run default toggled.";
|
|
608552
|
+
} else if (kind === "flag" && value2 === "admin") {
|
|
608553
|
+
this.setTelegramToolBooleanPolicy(state, "requireAdminForMutation", this.effectiveTelegramToolPolicy(state.policyChatId).requireAdminForMutation === false);
|
|
608554
|
+
answerText = "Admin mutation requirement toggled.";
|
|
608555
|
+
} else {
|
|
608556
|
+
throw new Error("Unsupported Telegram tool panel action.");
|
|
608557
|
+
}
|
|
608558
|
+
const messageId = state.messageId ?? callback.messageId;
|
|
608559
|
+
if (messageId !== void 0) {
|
|
608560
|
+
const payload = this.telegramToolPanelPayload(state);
|
|
608561
|
+
await this.apiCall("editMessageText", {
|
|
608562
|
+
chat_id: state.panelChatId,
|
|
608563
|
+
message_id: messageId,
|
|
608564
|
+
text: payload.text,
|
|
608565
|
+
parse_mode: "HTML",
|
|
608566
|
+
reply_markup: payload.reply_markup
|
|
608567
|
+
});
|
|
608568
|
+
}
|
|
608569
|
+
} catch (err) {
|
|
608570
|
+
answerText = err instanceof Error ? err.message : String(err);
|
|
608571
|
+
alert = true;
|
|
608572
|
+
} finally {
|
|
608573
|
+
await this.answerCallbackQuery(callback.id, answerText.slice(0, 180), alert).catch(() => false);
|
|
608574
|
+
}
|
|
608575
|
+
}
|
|
608576
|
+
async runTelegramToolActionForAdmin(action, args) {
|
|
608577
|
+
return this.executeTelegramToolAction(action.trim().toLowerCase(), { ...args, action }, {
|
|
608578
|
+
context: "telegram-admin-dm",
|
|
608579
|
+
repoRoot: this.repoRoot ?? "."
|
|
608580
|
+
});
|
|
608581
|
+
}
|
|
608582
|
+
setTelegramToolBooleanPolicy(state, key, value2) {
|
|
608583
|
+
if (state.policyScope === "chat" && state.policyChatId !== void 0) {
|
|
608584
|
+
const chatKey = String(state.policyChatId);
|
|
608585
|
+
this.telegramToolPolicy.chatOverrides ??= {};
|
|
608586
|
+
const override = this.telegramToolPolicy.chatOverrides[chatKey] ?? {};
|
|
608587
|
+
override[key] = value2;
|
|
608588
|
+
this.telegramToolPolicy.chatOverrides[chatKey] = override;
|
|
608589
|
+
} else {
|
|
608590
|
+
this.telegramToolPolicy[key] = value2;
|
|
608591
|
+
}
|
|
608592
|
+
this.persistTelegramToolPolicy();
|
|
608593
|
+
}
|
|
607562
608594
|
buildTelegramReminderTool(context2, repoRoot, chatId, currentMsg) {
|
|
607563
608595
|
const rawChatId = String(chatId ?? currentMsg?.chatId ?? "unknown");
|
|
607564
608596
|
const isPrivate2 = currentMsg?.chatType === "private";
|
|
@@ -607730,6 +608762,10 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
607730
608762
|
if (!target.ok) {
|
|
607731
608763
|
return { success: false, output: "", error: target.error, durationMs: performance.now() - start2 };
|
|
607732
608764
|
}
|
|
608765
|
+
const gate = bridge.assertTelegramToolActionAllowed("send_file", context2, currentMsg, target.chatId, args);
|
|
608766
|
+
if (!gate.ok) {
|
|
608767
|
+
return { success: false, output: "", error: gate.error, durationMs: performance.now() - start2 };
|
|
608768
|
+
}
|
|
607733
608769
|
const file = bridge.resolveTelegramFilePath(rawPath, repoRoot, scopedRoot);
|
|
607734
608770
|
if (!file.ok) {
|
|
607735
608771
|
return { success: false, output: "", error: file.error, durationMs: performance.now() - start2 };
|
|
@@ -607737,13 +608773,33 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
607737
608773
|
const kind = normalizeTelegramSendKind(args["kind"], file.path);
|
|
607738
608774
|
const caption = typeof args["caption"] === "string" ? args["caption"].trim().slice(0, 1024) : void 0;
|
|
607739
608775
|
const replyTo = Number(args["reply_to_message_id"]);
|
|
608776
|
+
const replyToMessageId = Number.isFinite(replyTo) && replyTo > 0 ? Math.floor(replyTo) : void 0;
|
|
608777
|
+
const ledgerPath = file.logicalPath ?? file.path;
|
|
608778
|
+
const sendFingerprint = bridge.telegramFileSendFingerprint(
|
|
608779
|
+
target.chatId,
|
|
608780
|
+
ledgerPath,
|
|
608781
|
+
kind,
|
|
608782
|
+
caption,
|
|
608783
|
+
replyToMessageId
|
|
608784
|
+
);
|
|
608785
|
+
if (bridge.telegramFileSendAlreadyDeliveredForMessage(currentMsg, sendFingerprint)) {
|
|
608786
|
+
return {
|
|
608787
|
+
success: true,
|
|
608788
|
+
output: `Telegram file already sent in this turn: ${basename27(file.path)} as ${kind} to ${String(target.chatId)}`,
|
|
608789
|
+
llmContent: `Already sent ${basename27(file.path)} to Telegram as ${kind}; do not send it again.`,
|
|
608790
|
+
durationMs: performance.now() - start2,
|
|
608791
|
+
mutated: false,
|
|
608792
|
+
mutatedFiles: []
|
|
608793
|
+
};
|
|
608794
|
+
}
|
|
607740
608795
|
try {
|
|
607741
608796
|
const messageId = await bridge.sendTelegramFileToChat(target.chatId, file.path, {
|
|
607742
608797
|
kind,
|
|
607743
608798
|
caption: caption || void 0,
|
|
607744
|
-
replyToMessageId
|
|
608799
|
+
replyToMessageId
|
|
607745
608800
|
});
|
|
607746
|
-
bridge.
|
|
608801
|
+
bridge.rememberTelegramFileSendForMessage(currentMsg, sendFingerprint);
|
|
608802
|
+
bridge.rememberTelegramDeliveredArtifactForMessage(currentMsg, ledgerPath);
|
|
607747
608803
|
return {
|
|
607748
608804
|
success: true,
|
|
607749
608805
|
output: `Sent Telegram file: ${basename27(file.path)} as ${kind} to ${String(target.chatId)}${messageId ? ` (message_id ${messageId})` : ""}`,
|
|
@@ -607841,6 +608897,27 @@ ${knownList}` : "Private-user telegram_send_file target must be this DM or a kno
|
|
|
607841
608897
|
if (!subAgent) return;
|
|
607842
608898
|
this.rememberTelegramDeliveredArtifact(subAgent, path11);
|
|
607843
608899
|
}
|
|
608900
|
+
telegramFileSendFingerprint(chatId, path11, kind, caption, replyToMessageId) {
|
|
608901
|
+
return stableTelegramValueKey({
|
|
608902
|
+
chatId: String(chatId),
|
|
608903
|
+
path: resolve41(path11),
|
|
608904
|
+
kind,
|
|
608905
|
+
caption: caption ?? "",
|
|
608906
|
+
replyToMessageId: replyToMessageId ?? null
|
|
608907
|
+
});
|
|
608908
|
+
}
|
|
608909
|
+
telegramFileSendAlreadyDeliveredForMessage(msg, fingerprint) {
|
|
608910
|
+
if (!msg) return false;
|
|
608911
|
+
const subAgent = this.subAgents.get(this.sessionKeyForMessage(msg));
|
|
608912
|
+
return Boolean(subAgent?.deliveredFileSends?.has(fingerprint));
|
|
608913
|
+
}
|
|
608914
|
+
rememberTelegramFileSendForMessage(msg, fingerprint) {
|
|
608915
|
+
if (!msg) return;
|
|
608916
|
+
const subAgent = this.subAgents.get(this.sessionKeyForMessage(msg));
|
|
608917
|
+
if (!subAgent) return;
|
|
608918
|
+
subAgent.deliveredFileSends ??= /* @__PURE__ */ new Set();
|
|
608919
|
+
subAgent.deliveredFileSends.add(fingerprint);
|
|
608920
|
+
}
|
|
607844
608921
|
/** Check if a message is from the admin user (uses fromUserId, NOT chatId) */
|
|
607845
608922
|
isAdminUser(msg) {
|
|
607846
608923
|
if (!this.adminUserId) return false;
|
|
@@ -608057,23 +609134,25 @@ ${text}`.trim());
|
|
|
608057
609134
|
}
|
|
608058
609135
|
// ── Message sending ───────────────────────────────────────────────────
|
|
608059
609136
|
/** Send a response back to a Telegram chat (Markdown → HTML conversion) */
|
|
608060
|
-
async sendMessage(chatId, text, replyToMessageId) {
|
|
609137
|
+
async sendMessage(chatId, text, replyToMessageId, options2 = {}) {
|
|
608061
609138
|
const extracted = extractMediaReferences(text);
|
|
609139
|
+
const mediaRefs = this.filterTelegramMediaReferences(extracted.media, options2);
|
|
608062
609140
|
const html = convertMarkdownToTelegramHTML(extracted.text);
|
|
608063
|
-
const msgId = extracted.text.trim() ? await this.sendMessageHTML(chatId, html, replyToMessageId) : null;
|
|
608064
|
-
for (const media of
|
|
609141
|
+
const msgId = extracted.text.trim() ? await this.sendMessageHTML(chatId, html, replyToMessageId, options2) : null;
|
|
609142
|
+
for (const media of mediaRefs) {
|
|
608065
609143
|
await this.sendMediaReference(chatId, media, { replyToMessageId }).catch(() => null);
|
|
608066
609144
|
}
|
|
608067
609145
|
return msgId;
|
|
608068
609146
|
}
|
|
608069
609147
|
/** Send an HTML-formatted message to a Telegram chat */
|
|
608070
|
-
async sendMessageHTML(chatId, html, replyToMessageId) {
|
|
609148
|
+
async sendMessageHTML(chatId, html, replyToMessageId, options2 = {}) {
|
|
608071
609149
|
const extracted = extractMediaReferences(html);
|
|
609150
|
+
const mediaRefs = this.filterTelegramMediaReferences(extracted.media, options2);
|
|
608072
609151
|
const sendHtml = extracted.text || (extracted.media.length > 0 ? "" : html);
|
|
608073
609152
|
let sentId = null;
|
|
608074
609153
|
if (!sendHtml.trim()) {
|
|
608075
|
-
for (let idx = 0; idx <
|
|
608076
|
-
const media =
|
|
609154
|
+
for (let idx = 0; idx < mediaRefs.length; idx++) {
|
|
609155
|
+
const media = mediaRefs[idx];
|
|
608077
609156
|
const mediaId = await this.sendMediaReference(
|
|
608078
609157
|
chatId,
|
|
608079
609158
|
media,
|
|
@@ -608112,11 +609191,24 @@ ${text}`.trim());
|
|
|
608112
609191
|
}
|
|
608113
609192
|
}
|
|
608114
609193
|
}
|
|
608115
|
-
for (const media of
|
|
609194
|
+
for (const media of mediaRefs) {
|
|
608116
609195
|
await this.sendMediaReference(chatId, media).catch(() => null);
|
|
608117
609196
|
}
|
|
608118
609197
|
return sentId;
|
|
608119
609198
|
}
|
|
609199
|
+
filterTelegramMediaReferences(media, options2) {
|
|
609200
|
+
const suppress = options2.suppressMedia;
|
|
609201
|
+
if (!suppress) return media;
|
|
609202
|
+
return media.filter((ref) => !suppress(ref));
|
|
609203
|
+
}
|
|
609204
|
+
deliveredArtifactMediaSuppressorForMessage(msg) {
|
|
609205
|
+
const subAgent = this.subAgents.get(this.sessionKeyForMessage(msg));
|
|
609206
|
+
const delivered = new Set(
|
|
609207
|
+
(subAgent?.deliveredArtifacts ?? []).map((path11) => resolve41(path11))
|
|
609208
|
+
);
|
|
609209
|
+
if (delivered.size === 0) return void 0;
|
|
609210
|
+
return (media) => media.source === "file" && delivered.has(resolve41(media.value));
|
|
609211
|
+
}
|
|
608120
609212
|
async replyToTelegramMessage(msg, text, options2 = {}) {
|
|
608121
609213
|
if (msg.guestQueryId) {
|
|
608122
609214
|
return this.answerGuestQuery(msg.guestQueryId, text, {
|
|
@@ -608582,11 +609674,16 @@ ${caption}\r
|
|
|
608582
609674
|
const result = await this.apiCall("getUpdates", {
|
|
608583
609675
|
offset: this.lastUpdateId + 1,
|
|
608584
609676
|
timeout: 30,
|
|
608585
|
-
allowed_updates: ["message", "guest_message", "poll", "message_reaction", "message_reaction_count"]
|
|
609677
|
+
allowed_updates: ["message", "guest_message", "callback_query", "poll", "message_reaction", "message_reaction_count"]
|
|
608586
609678
|
});
|
|
608587
609679
|
if (result.ok && Array.isArray(result.result)) {
|
|
608588
609680
|
for (const update2 of result.result) {
|
|
608589
609681
|
this.lastUpdateId = update2.update_id;
|
|
609682
|
+
const callback = normalizeTelegramCallbackQuery(update2);
|
|
609683
|
+
if (callback) {
|
|
609684
|
+
await this.handleTelegramCallbackQuery(callback);
|
|
609685
|
+
continue;
|
|
609686
|
+
}
|
|
608590
609687
|
const msg = normalizeTelegramUpdate(update2);
|
|
608591
609688
|
if (!msg) continue;
|
|
608592
609689
|
const isAdmin = this.adminUserId ? String(msg.fromUserId) === this.adminUserId || msg.username === this.adminUserId : false;
|
|
@@ -612296,7 +613393,7 @@ __export(runtime_keys_exports, {
|
|
|
612296
613393
|
import { existsSync as existsSync115, readFileSync as readFileSync94, writeFileSync as writeFileSync61, mkdirSync as mkdirSync69, chmodSync } from "node:fs";
|
|
612297
613394
|
import { join as join129 } from "node:path";
|
|
612298
613395
|
import { homedir as homedir40 } from "node:os";
|
|
612299
|
-
import { randomBytes as
|
|
613396
|
+
import { randomBytes as randomBytes23 } from "node:crypto";
|
|
612300
613397
|
function ensureDir2() {
|
|
612301
613398
|
const dir = join129(homedir40(), ".omnius");
|
|
612302
613399
|
if (!existsSync115(dir)) mkdirSync69(dir, { recursive: true });
|
|
@@ -612322,7 +613419,7 @@ function persistAll(records) {
|
|
|
612322
613419
|
}
|
|
612323
613420
|
function mintKey(args) {
|
|
612324
613421
|
const records = loadAll();
|
|
612325
|
-
const key = `omnius_${
|
|
613422
|
+
const key = `omnius_${randomBytes23(32).toString("hex")}`;
|
|
612326
613423
|
const record = {
|
|
612327
613424
|
key,
|
|
612328
613425
|
scope: args.scope,
|
|
@@ -615440,11 +616537,11 @@ async function handleAimsIncidentPost(ctx3) {
|
|
|
615440
616537
|
}));
|
|
615441
616538
|
return true;
|
|
615442
616539
|
}
|
|
615443
|
-
const { randomBytes:
|
|
616540
|
+
const { randomBytes: randomBytes27 } = await import("node:crypto");
|
|
615444
616541
|
const record = await withAimsLock("incidents.json", () => {
|
|
615445
616542
|
const existing = readAimsFile("incidents.json", []);
|
|
615446
616543
|
const rec = {
|
|
615447
|
-
id: `INC-${Date.now()}-${
|
|
616544
|
+
id: `INC-${Date.now()}-${randomBytes27(4).toString("hex")}`,
|
|
615448
616545
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
615449
616546
|
raised_by: user ?? "anonymous",
|
|
615450
616547
|
status: "open",
|
|
@@ -624899,7 +625996,7 @@ var init_usage_tracker = __esm({
|
|
|
624899
625996
|
import { existsSync as existsSync120, readFileSync as readFileSync98, writeFileSync as writeFileSync64, mkdirSync as mkdirSync72, readdirSync as readdirSync41, unlinkSync as unlinkSync24 } from "node:fs";
|
|
624900
625997
|
import { join as join134 } from "node:path";
|
|
624901
625998
|
import { homedir as homedir43 } from "node:os";
|
|
624902
|
-
import { createCipheriv as createCipheriv5, createDecipheriv as createDecipheriv5, randomBytes as
|
|
625999
|
+
import { createCipheriv as createCipheriv5, createDecipheriv as createDecipheriv5, randomBytes as randomBytes24, scryptSync as scryptSync3 } from "node:crypto";
|
|
624903
626000
|
function globalProfileDir() {
|
|
624904
626001
|
return join134(homedir43(), ".omnius", "profiles");
|
|
624905
626002
|
}
|
|
@@ -624983,9 +626080,9 @@ function deleteProfile(name10, scope = "global", projectDir2) {
|
|
|
624983
626080
|
return false;
|
|
624984
626081
|
}
|
|
624985
626082
|
function encryptProfile(profile, password) {
|
|
624986
|
-
const salt =
|
|
626083
|
+
const salt = randomBytes24(32);
|
|
624987
626084
|
const key = scryptSync3(password, salt, 32);
|
|
624988
|
-
const iv =
|
|
626085
|
+
const iv = randomBytes24(16);
|
|
624989
626086
|
const cipher = createCipheriv5("aes-256-gcm", key, iv);
|
|
624990
626087
|
const plaintext = JSON.stringify(profile);
|
|
624991
626088
|
const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
@@ -625638,7 +626735,7 @@ import { dirname as dirname37, join as join137, resolve as resolve45 } from "nod
|
|
|
625638
626735
|
import { homedir as homedir45 } from "node:os";
|
|
625639
626736
|
import { spawn as spawn29, execSync as execSync57 } from "node:child_process";
|
|
625640
626737
|
import { mkdirSync as mkdirSync74, writeFileSync as writeFileSync66, readFileSync as readFileSync99, readdirSync as readdirSync42, existsSync as existsSync122, watch as fsWatch3, renameSync as renameSync8, unlinkSync as unlinkSync25 } from "node:fs";
|
|
625641
|
-
import { randomBytes as
|
|
626738
|
+
import { randomBytes as randomBytes25, randomUUID as randomUUID16 } from "node:crypto";
|
|
625642
626739
|
import { createHash as createHash27 } from "node:crypto";
|
|
625643
626740
|
function memoryDbPaths3(baseDir = process.cwd()) {
|
|
625644
626741
|
const dir = join137(baseDir, ".omnius");
|
|
@@ -627314,7 +628411,7 @@ ${messages2[firstSystemIdx].content}`
|
|
|
627314
628411
|
messages2.unshift({ role: "system", content: SYSTEM_FACTUAL_FIRST });
|
|
627315
628412
|
}
|
|
627316
628413
|
}
|
|
627317
|
-
const chatId = `chatcmpl-${
|
|
628414
|
+
const chatId = `chatcmpl-${randomBytes25(12).toString("hex")}`;
|
|
627318
628415
|
const turnsLog = [];
|
|
627319
628416
|
for (let turn = 1; turn <= maxTurns; turn++) {
|
|
627320
628417
|
if (Date.now() > totalDeadline) {
|
|
@@ -627580,7 +628677,7 @@ async function handleV1ChatCompletions(req2, res, ollamaUrl) {
|
|
|
627580
628677
|
"Cache-Control": "no-cache",
|
|
627581
628678
|
"Connection": "keep-alive"
|
|
627582
628679
|
});
|
|
627583
|
-
const chatId = `chatcmpl-${
|
|
628680
|
+
const chatId = `chatcmpl-${randomBytes25(12).toString("hex")}`;
|
|
627584
628681
|
let buffer2 = "";
|
|
627585
628682
|
ollamaStream(
|
|
627586
628683
|
targetUrl,
|
|
@@ -627622,7 +628719,7 @@ async function handleV1ChatCompletions(req2, res, ollamaUrl) {
|
|
|
627622
628719
|
if (ollamaChunk.message.content) delta.content = ollamaChunk.message.content;
|
|
627623
628720
|
if (ollamaChunk.message.tool_calls) {
|
|
627624
628721
|
delta.tool_calls = ollamaChunk.message.tool_calls.map((tc, idx) => ({
|
|
627625
|
-
id: tc.id || `call_${
|
|
628722
|
+
id: tc.id || `call_${randomBytes25(8).toString("hex")}`,
|
|
627626
628723
|
type: "function",
|
|
627627
628724
|
function: {
|
|
627628
628725
|
name: tc?.function?.name ?? tc?.name ?? "",
|
|
@@ -627702,14 +628799,14 @@ async function handleV1ChatCompletions(req2, res, ollamaUrl) {
|
|
|
627702
628799
|
if (ollamaResp.eval_count) metrics.totalTokensOut += ollamaResp.eval_count;
|
|
627703
628800
|
if (ollamaResp.prompt_eval_count) metrics.totalTokensIn += ollamaResp.prompt_eval_count;
|
|
627704
628801
|
trackTokens("local", ollamaResp.prompt_eval_count ?? 0, ollamaResp.eval_count ?? 0);
|
|
627705
|
-
const chatId = `chatcmpl-${
|
|
628802
|
+
const chatId = `chatcmpl-${randomBytes25(12).toString("hex")}`;
|
|
627706
628803
|
const responseMessage = {
|
|
627707
628804
|
role: ollamaResp.message?.role ?? "assistant",
|
|
627708
628805
|
content: ollamaResp.message?.content ?? ""
|
|
627709
628806
|
};
|
|
627710
628807
|
if (ollamaResp.message?.tool_calls && ollamaResp.message.tool_calls.length > 0) {
|
|
627711
628808
|
responseMessage.tool_calls = ollamaResp.message.tool_calls.map((tc, idx) => ({
|
|
627712
|
-
id: tc.id || `call_${
|
|
628809
|
+
id: tc.id || `call_${randomBytes25(8).toString("hex")}`,
|
|
627713
628810
|
type: "function",
|
|
627714
628811
|
function: {
|
|
627715
628812
|
name: tc?.function?.name ?? tc?.name ?? "",
|
|
@@ -628494,7 +629591,7 @@ async function handleV1Run(req2, res) {
|
|
|
628494
629591
|
return;
|
|
628495
629592
|
}
|
|
628496
629593
|
}
|
|
628497
|
-
const id = `job-${
|
|
629594
|
+
const id = `job-${randomBytes25(8).toString("hex")}`;
|
|
628498
629595
|
const dir = jobsDir();
|
|
628499
629596
|
const workingDir = requestBody["working_directory"] || req2.headers["x-working-directory"];
|
|
628500
629597
|
const isolate = requestBody["isolate"] === true;
|
|
@@ -639143,6 +640240,17 @@ The user pasted a clipboard image saved at ${relPath}. Use the OCR, vision analy
|
|
|
639143
640240
|
},
|
|
639144
640241
|
// Telegram bridge
|
|
639145
640242
|
async telegramStart(token, adminId) {
|
|
640243
|
+
if (telegramBridge?.isActive) {
|
|
640244
|
+
writeContent(
|
|
640245
|
+
() => renderWarning("Telegram bridge already active. Use /telegram stop before restarting.")
|
|
640246
|
+
);
|
|
640247
|
+
showPrompt();
|
|
640248
|
+
return;
|
|
640249
|
+
}
|
|
640250
|
+
if (telegramBridge) {
|
|
640251
|
+
telegramBridge.stop();
|
|
640252
|
+
telegramBridge = null;
|
|
640253
|
+
}
|
|
639146
640254
|
telegramBridge = new TelegramBridge(
|
|
639147
640255
|
token,
|
|
639148
640256
|
(msg) => {
|
|
@@ -639175,6 +640283,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
639175
640283
|
telegramBridge.setContextWindowSize(resolvedContextWindowSize);
|
|
639176
640284
|
}
|
|
639177
640285
|
telegramBridge.setInteractionMode(savedSettings.telegramMode ?? "auto");
|
|
640286
|
+
telegramBridge.setTelegramToolPolicy(savedSettings.telegramToolPolicy);
|
|
639178
640287
|
if (adminId) {
|
|
639179
640288
|
telegramBridge.setAdmin(adminId);
|
|
639180
640289
|
}
|
|
@@ -639388,6 +640497,34 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
639388
640497
|
if (!telegramBridge?.isActive) throw new Error("Telegram bridge not active.");
|
|
639389
640498
|
return telegramBridge.deleteAllMessageReactions(chatId, options2);
|
|
639390
640499
|
},
|
|
640500
|
+
async telegramDeleteMessage(chatId, messageId, reason) {
|
|
640501
|
+
if (!telegramBridge?.isActive) throw new Error("Telegram bridge not active.");
|
|
640502
|
+
return telegramBridge.runTelegramToolActionForAdmin("delete_message", {
|
|
640503
|
+
target: String(chatId),
|
|
640504
|
+
message_id: messageId,
|
|
640505
|
+
reason: reason || "TUI admin delete-message command"
|
|
640506
|
+
});
|
|
640507
|
+
},
|
|
640508
|
+
async telegramDeleteMessages(chatId, messageIds, reason) {
|
|
640509
|
+
if (!telegramBridge?.isActive) throw new Error("Telegram bridge not active.");
|
|
640510
|
+
return telegramBridge.runTelegramToolActionForAdmin("delete_messages", {
|
|
640511
|
+
target: String(chatId),
|
|
640512
|
+
message_ids: messageIds,
|
|
640513
|
+
reason: reason || "TUI admin delete-messages command"
|
|
640514
|
+
});
|
|
640515
|
+
},
|
|
640516
|
+
telegramGetToolPolicy() {
|
|
640517
|
+
return telegramBridge?.getTelegramToolPolicy() ?? savedSettings.telegramToolPolicy ?? {};
|
|
640518
|
+
},
|
|
640519
|
+
telegramSetToolPolicy(policy) {
|
|
640520
|
+
savedSettings.telegramToolPolicy = policy;
|
|
640521
|
+
saveProjectSettings(repoRoot, { telegramToolPolicy: policy });
|
|
640522
|
+
telegramBridge?.setTelegramToolPolicy(policy);
|
|
640523
|
+
},
|
|
640524
|
+
async telegramSendToolPanel(chatId, policyChatId) {
|
|
640525
|
+
if (!telegramBridge?.isActive) throw new Error("Telegram bridge not active.");
|
|
640526
|
+
return telegramBridge.sendTelegramToolPanel(chatId, policyChatId);
|
|
640527
|
+
},
|
|
639391
640528
|
async telegramGetChatAdministrators(chatId, returnBots) {
|
|
639392
640529
|
if (!telegramBridge?.isActive) throw new Error("Telegram bridge not active.");
|
|
639393
640530
|
return telegramBridge.getChatAdministrators(chatId, returnBots);
|
|
@@ -642204,7 +643341,7 @@ __export(run_exports, {
|
|
|
642204
643341
|
import { resolve as resolve47 } from "node:path";
|
|
642205
643342
|
import { spawn as spawn30 } from "node:child_process";
|
|
642206
643343
|
import { mkdirSync as mkdirSync77, writeFileSync as writeFileSync69, readFileSync as readFileSync102, readdirSync as readdirSync44, existsSync as existsSync124 } from "node:fs";
|
|
642207
|
-
import { randomBytes as
|
|
643344
|
+
import { randomBytes as randomBytes26 } from "node:crypto";
|
|
642208
643345
|
import { join as join140 } from "node:path";
|
|
642209
643346
|
function jobsDir2(repoPath) {
|
|
642210
643347
|
const root = resolve47(repoPath ?? process.cwd());
|
|
@@ -642302,7 +643439,7 @@ function extractSummary(captured) {
|
|
|
642302
643439
|
return lines.slice(-3).join(" ").slice(0, 200);
|
|
642303
643440
|
}
|
|
642304
643441
|
async function runBackground(task, config, opts) {
|
|
642305
|
-
const id = `job-${
|
|
643442
|
+
const id = `job-${randomBytes26(3).toString("hex")}`;
|
|
642306
643443
|
const dir = jobsDir2(opts.repoPath);
|
|
642307
643444
|
const repoRoot = resolve47(opts.repoPath ?? process.cwd());
|
|
642308
643445
|
const job = {
|