omnius 1.0.43 → 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 +10 -3
- package/dist/index.js +1092 -36
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
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"],
|
|
@@ -582247,6 +582250,10 @@ function formatTelegramJsonResult(value2) {
|
|
|
582247
582250
|
if (value2 === null || value2 === void 0) return "No data returned.";
|
|
582248
582251
|
return JSON.stringify(value2, null, 2).slice(0, 3900);
|
|
582249
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
|
+
}
|
|
582250
582257
|
async function runSudoScript(ctx3, script) {
|
|
582251
582258
|
const stdinAny = process.stdin;
|
|
582252
582259
|
const hadRaw = !!(stdinAny && stdinAny.isTTY && stdinAny.isRaw);
|
|
@@ -582740,11 +582747,11 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
582740
582747
|
}
|
|
582741
582748
|
if (action === "new") {
|
|
582742
582749
|
try {
|
|
582743
|
-
const { randomBytes:
|
|
582750
|
+
const { randomBytes: randomBytes27 } = await import("node:crypto");
|
|
582744
582751
|
const { homedir: homedir48 } = await import("node:os");
|
|
582745
582752
|
const { mkdirSync: mkdirSync79, writeFileSync: writeFileSync71 } = await import("node:fs");
|
|
582746
582753
|
const { join: join144 } = await import("node:path");
|
|
582747
|
-
const newKey =
|
|
582754
|
+
const newKey = randomBytes27(16).toString("hex");
|
|
582748
582755
|
process.env["OMNIUS_API_KEY"] = newKey;
|
|
582749
582756
|
const dir = join144(homedir48(), ".omnius");
|
|
582750
582757
|
mkdirSync79(dir, { recursive: true });
|
|
@@ -583001,8 +583008,8 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
583001
583008
|
}
|
|
583002
583009
|
process.env["OMNIUS_ACCESS"] = val2;
|
|
583003
583010
|
if (val2 === "any" && !process.env["OMNIUS_API_KEY"]) {
|
|
583004
|
-
const { randomBytes:
|
|
583005
|
-
const apiKey =
|
|
583011
|
+
const { randomBytes: randomBytes27 } = await import("node:crypto");
|
|
583012
|
+
const apiKey = randomBytes27(16).toString("hex");
|
|
583006
583013
|
process.env["OMNIUS_API_KEY"] = apiKey;
|
|
583007
583014
|
renderInfo(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
|
|
583008
583015
|
renderInfo(
|
|
@@ -583121,8 +583128,8 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
583121
583128
|
}
|
|
583122
583129
|
process.env["OMNIUS_ACCESS"] = val;
|
|
583123
583130
|
if (val === "any" && !process.env["OMNIUS_API_KEY"]) {
|
|
583124
|
-
const { randomBytes:
|
|
583125
|
-
const apiKey =
|
|
583131
|
+
const { randomBytes: randomBytes27 } = await import("node:crypto");
|
|
583132
|
+
const apiKey = randomBytes27(16).toString("hex");
|
|
583126
583133
|
process.env["OMNIUS_API_KEY"] = apiKey;
|
|
583127
583134
|
renderInfo(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
|
|
583128
583135
|
renderInfo(
|
|
@@ -587367,6 +587374,73 @@ sleep 1
|
|
|
587367
587374
|
}
|
|
587368
587375
|
return "handled";
|
|
587369
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
|
+
}
|
|
587370
587444
|
if (parts[0] === "delete-reaction") {
|
|
587371
587445
|
const chatId = parseTelegramChatTarget(parts[1]);
|
|
587372
587446
|
const messageId = Number(parts[2]);
|
|
@@ -587477,6 +587551,9 @@ sleep 1
|
|
|
587477
587551
|
renderInfo(" /telegram admins <chat> [--bots] List chat admins");
|
|
587478
587552
|
renderInfo(" /telegram personal <user_id> <limit> Fetch profile personal chat messages");
|
|
587479
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");
|
|
587480
587557
|
renderInfo(" /telegram delete-reaction <chat> <msg> --user <id> Delete a reaction");
|
|
587481
587558
|
renderInfo(" /telegram delete-reactions <chat> --user <id> Delete recent reactions");
|
|
587482
587559
|
renderInfo(" Add --local to scope settings to this project only");
|
|
@@ -593681,11 +593758,11 @@ var init_commands = __esm({
|
|
|
593681
593758
|
process.env["OMNIUS_ACCESS"] = val;
|
|
593682
593759
|
if (val === "any" && !process.env["OMNIUS_API_KEY"]) {
|
|
593683
593760
|
try {
|
|
593684
|
-
const { randomBytes:
|
|
593761
|
+
const { randomBytes: randomBytes27 } = await import("node:crypto");
|
|
593685
593762
|
const { homedir: homedir48 } = await import("node:os");
|
|
593686
593763
|
const { mkdirSync: mkdirSync79, writeFileSync: writeFileSync71 } = await import("node:fs");
|
|
593687
593764
|
const { join: join144 } = await import("node:path");
|
|
593688
|
-
const apiKey =
|
|
593765
|
+
const apiKey = randomBytes27(16).toString("hex");
|
|
593689
593766
|
process.env["OMNIUS_API_KEY"] = apiKey;
|
|
593690
593767
|
const dir = join144(homedir48(), ".omnius");
|
|
593691
593768
|
mkdirSync79(dir, { recursive: true });
|
|
@@ -600540,6 +600617,7 @@ var init_tool_policy = __esm({
|
|
|
600540
600617
|
"reminders",
|
|
600541
600618
|
"explore_tools",
|
|
600542
600619
|
"telegram_media_recent",
|
|
600620
|
+
"telegram",
|
|
600543
600621
|
"generate_image",
|
|
600544
600622
|
"generate_audio",
|
|
600545
600623
|
"generate_tts",
|
|
@@ -600572,6 +600650,7 @@ var init_tool_policy = __esm({
|
|
|
600572
600650
|
"reminders",
|
|
600573
600651
|
"explore_tools",
|
|
600574
600652
|
"telegram_media_recent",
|
|
600653
|
+
"telegram",
|
|
600575
600654
|
"generate_image",
|
|
600576
600655
|
"generate_audio",
|
|
600577
600656
|
"generate_tts",
|
|
@@ -602825,7 +602904,7 @@ var init_vision_ingress = __esm({
|
|
|
602825
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";
|
|
602826
602905
|
import { join as join123, resolve as resolve41, basename as basename27, relative as relative13, isAbsolute as isAbsolute7, extname as extname16 } from "node:path";
|
|
602827
602906
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
602828
|
-
import { createHash as createHash23, randomInt } from "node:crypto";
|
|
602907
|
+
import { createHash as createHash23, randomBytes as randomBytes22, randomInt } from "node:crypto";
|
|
602829
602908
|
function parseTelegramInteractionDecision(text, forcedRoute, options2 = {}) {
|
|
602830
602909
|
const cleaned = stripTelegramHiddenThinking(text).replace(/```(?:json)?/gi, "").replace(/```/g, "").trim();
|
|
602831
602910
|
const jsonText = cleaned.startsWith("{") ? cleaned : cleaned.match(/\{[\s\S]*\}/)?.[0] ?? "";
|
|
@@ -603809,6 +603888,23 @@ function normalizeTelegramUpdate(update2) {
|
|
|
603809
603888
|
sourceUpdateType
|
|
603810
603889
|
};
|
|
603811
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
|
+
}
|
|
603812
603908
|
function adaptTool5(tool, todoSessionId) {
|
|
603813
603909
|
return {
|
|
603814
603910
|
name: tool.name,
|
|
@@ -603951,7 +604047,7 @@ function renderTelegramSubAgentError(username, error) {
|
|
|
603951
604047
|
process.stdout.write(` ${c3.dim("⎿")} ${c3.red("✘")} @${username}: ${c3.dim(preview)}
|
|
603952
604048
|
`);
|
|
603953
604049
|
}
|
|
603954
|
-
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;
|
|
603955
604051
|
var init_telegram_bridge = __esm({
|
|
603956
604052
|
"packages/cli/src/tui/telegram-bridge.ts"() {
|
|
603957
604053
|
"use strict";
|
|
@@ -603971,6 +604067,90 @@ var init_telegram_bridge = __esm({
|
|
|
603971
604067
|
init_telegram_channel_dmn();
|
|
603972
604068
|
init_telegram_reflection_corpus();
|
|
603973
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
|
+
};
|
|
603974
604154
|
TELEGRAM_SAFETY_PROMPT = `
|
|
603975
604155
|
CRITICAL SAFETY NOTICE — PUBLIC TELEGRAM CHANNEL
|
|
603976
604156
|
|
|
@@ -604168,8 +604348,10 @@ Telegram response contract:
|
|
|
604168
604348
|
this.agentConfig = agentConfig;
|
|
604169
604349
|
this.repoRoot = repoRoot;
|
|
604170
604350
|
this.toolPolicyConfig = toolPolicyConfig;
|
|
604351
|
+
this.telegramToolPolicy = resolveSettings(repoRoot || ".").telegramToolPolicy ?? {};
|
|
604171
604352
|
this.mediaCacheDir = resolve41(repoRoot || ".", ".omnius", "telegram-media-cache");
|
|
604172
604353
|
this.telegramConversationDir = resolve41(repoRoot || ".", ".omnius", "telegram-conversations");
|
|
604354
|
+
this.telegramToolButtonDir = resolve41(repoRoot || ".", ".omnius", "telegram-tool-buttons");
|
|
604173
604355
|
}
|
|
604174
604356
|
botToken;
|
|
604175
604357
|
onMessage;
|
|
@@ -604212,6 +604394,14 @@ Telegram response contract:
|
|
|
604212
604394
|
onSubAgentEvent = null;
|
|
604213
604395
|
/** Tool policy config — user overrides from config */
|
|
604214
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;
|
|
604215
604405
|
/** Command handler for admin DM slash commands (wired from interactive.ts) */
|
|
604216
604406
|
commandHandler = null;
|
|
604217
604407
|
/** Callback fired after a Telegram user completes the TUI-only admin auth challenge */
|
|
@@ -604277,6 +604467,12 @@ Telegram response contract:
|
|
|
604277
604467
|
setToolPolicyConfig(config) {
|
|
604278
604468
|
this.toolPolicyConfig = config;
|
|
604279
604469
|
}
|
|
604470
|
+
setTelegramToolPolicy(policy) {
|
|
604471
|
+
this.telegramToolPolicy = policy ?? {};
|
|
604472
|
+
}
|
|
604473
|
+
getTelegramToolPolicy() {
|
|
604474
|
+
return this.cloneTelegramToolPolicy(this.telegramToolPolicy);
|
|
604475
|
+
}
|
|
604280
604476
|
/**
|
|
604281
604477
|
* Set a command handler for admin DM slash commands.
|
|
604282
604478
|
* When an admin sends a /command in DM, it gets routed through the TUI's
|
|
@@ -606079,6 +606275,7 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
606079
606275
|
messagesSent: 0,
|
|
606080
606276
|
activeSubAgents: 0
|
|
606081
606277
|
};
|
|
606278
|
+
this.botUserId = typeof me.result?.id === "number" ? me.result.id : this.botUserId;
|
|
606082
606279
|
this.polling = true;
|
|
606083
606280
|
this.abortController = new AbortController();
|
|
606084
606281
|
try {
|
|
@@ -606251,6 +606448,20 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`);
|
|
|
606251
606448
|
await this.handleTelegramReflectionSlash(msg, normalizedCommandText);
|
|
606252
606449
|
return;
|
|
606253
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
|
+
}
|
|
606254
606465
|
if (!this.agentConfig || !this.repoRoot) {
|
|
606255
606466
|
this.onMessage(msg);
|
|
606256
606467
|
return;
|
|
@@ -607465,6 +607676,7 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
607465
607676
|
new SkillListTool(repoRoot),
|
|
607466
607677
|
sharedSkillExtractTool,
|
|
607467
607678
|
this.buildTelegramMediaRecentTool(chatId, msg),
|
|
607679
|
+
this.buildTelegramTool(context2, repoRoot, chatId, msg),
|
|
607468
607680
|
...this.buildTelegramReminderTools(context2, repoRoot, chatId, msg)
|
|
607469
607681
|
];
|
|
607470
607682
|
const adminTools = [
|
|
@@ -607527,6 +607739,7 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
607527
607739
|
new SkillListTool(repoRoot),
|
|
607528
607740
|
new SkillExecuteTool(repoRoot),
|
|
607529
607741
|
adminSkillExtractTool,
|
|
607742
|
+
this.buildTelegramTool(context2, repoRoot, chatId, msg),
|
|
607530
607743
|
...this.buildTelegramReminderTools(context2, repoRoot, chatId, msg),
|
|
607531
607744
|
fullSubAgentTool,
|
|
607532
607745
|
this.buildTelegramSendFileTool(context2, repoRoot, chatId, msg)
|
|
@@ -607573,6 +607786,811 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
607573
607786
|
]);
|
|
607574
607787
|
return tools.filter((tool) => !blocked.has(tool.name));
|
|
607575
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
|
+
}
|
|
607576
608594
|
buildTelegramReminderTool(context2, repoRoot, chatId, currentMsg) {
|
|
607577
608595
|
const rawChatId = String(chatId ?? currentMsg?.chatId ?? "unknown");
|
|
607578
608596
|
const isPrivate2 = currentMsg?.chatType === "private";
|
|
@@ -607744,6 +608762,10 @@ Scoped workspace: ${scopedRoot}`,
|
|
|
607744
608762
|
if (!target.ok) {
|
|
607745
608763
|
return { success: false, output: "", error: target.error, durationMs: performance.now() - start2 };
|
|
607746
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
|
+
}
|
|
607747
608769
|
const file = bridge.resolveTelegramFilePath(rawPath, repoRoot, scopedRoot);
|
|
607748
608770
|
if (!file.ok) {
|
|
607749
608771
|
return { success: false, output: "", error: file.error, durationMs: performance.now() - start2 };
|
|
@@ -608652,11 +609674,16 @@ ${caption}\r
|
|
|
608652
609674
|
const result = await this.apiCall("getUpdates", {
|
|
608653
609675
|
offset: this.lastUpdateId + 1,
|
|
608654
609676
|
timeout: 30,
|
|
608655
|
-
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"]
|
|
608656
609678
|
});
|
|
608657
609679
|
if (result.ok && Array.isArray(result.result)) {
|
|
608658
609680
|
for (const update2 of result.result) {
|
|
608659
609681
|
this.lastUpdateId = update2.update_id;
|
|
609682
|
+
const callback = normalizeTelegramCallbackQuery(update2);
|
|
609683
|
+
if (callback) {
|
|
609684
|
+
await this.handleTelegramCallbackQuery(callback);
|
|
609685
|
+
continue;
|
|
609686
|
+
}
|
|
608660
609687
|
const msg = normalizeTelegramUpdate(update2);
|
|
608661
609688
|
if (!msg) continue;
|
|
608662
609689
|
const isAdmin = this.adminUserId ? String(msg.fromUserId) === this.adminUserId || msg.username === this.adminUserId : false;
|
|
@@ -612366,7 +613393,7 @@ __export(runtime_keys_exports, {
|
|
|
612366
613393
|
import { existsSync as existsSync115, readFileSync as readFileSync94, writeFileSync as writeFileSync61, mkdirSync as mkdirSync69, chmodSync } from "node:fs";
|
|
612367
613394
|
import { join as join129 } from "node:path";
|
|
612368
613395
|
import { homedir as homedir40 } from "node:os";
|
|
612369
|
-
import { randomBytes as
|
|
613396
|
+
import { randomBytes as randomBytes23 } from "node:crypto";
|
|
612370
613397
|
function ensureDir2() {
|
|
612371
613398
|
const dir = join129(homedir40(), ".omnius");
|
|
612372
613399
|
if (!existsSync115(dir)) mkdirSync69(dir, { recursive: true });
|
|
@@ -612392,7 +613419,7 @@ function persistAll(records) {
|
|
|
612392
613419
|
}
|
|
612393
613420
|
function mintKey(args) {
|
|
612394
613421
|
const records = loadAll();
|
|
612395
|
-
const key = `omnius_${
|
|
613422
|
+
const key = `omnius_${randomBytes23(32).toString("hex")}`;
|
|
612396
613423
|
const record = {
|
|
612397
613424
|
key,
|
|
612398
613425
|
scope: args.scope,
|
|
@@ -615510,11 +616537,11 @@ async function handleAimsIncidentPost(ctx3) {
|
|
|
615510
616537
|
}));
|
|
615511
616538
|
return true;
|
|
615512
616539
|
}
|
|
615513
|
-
const { randomBytes:
|
|
616540
|
+
const { randomBytes: randomBytes27 } = await import("node:crypto");
|
|
615514
616541
|
const record = await withAimsLock("incidents.json", () => {
|
|
615515
616542
|
const existing = readAimsFile("incidents.json", []);
|
|
615516
616543
|
const rec = {
|
|
615517
|
-
id: `INC-${Date.now()}-${
|
|
616544
|
+
id: `INC-${Date.now()}-${randomBytes27(4).toString("hex")}`,
|
|
615518
616545
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
615519
616546
|
raised_by: user ?? "anonymous",
|
|
615520
616547
|
status: "open",
|
|
@@ -624969,7 +625996,7 @@ var init_usage_tracker = __esm({
|
|
|
624969
625996
|
import { existsSync as existsSync120, readFileSync as readFileSync98, writeFileSync as writeFileSync64, mkdirSync as mkdirSync72, readdirSync as readdirSync41, unlinkSync as unlinkSync24 } from "node:fs";
|
|
624970
625997
|
import { join as join134 } from "node:path";
|
|
624971
625998
|
import { homedir as homedir43 } from "node:os";
|
|
624972
|
-
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";
|
|
624973
626000
|
function globalProfileDir() {
|
|
624974
626001
|
return join134(homedir43(), ".omnius", "profiles");
|
|
624975
626002
|
}
|
|
@@ -625053,9 +626080,9 @@ function deleteProfile(name10, scope = "global", projectDir2) {
|
|
|
625053
626080
|
return false;
|
|
625054
626081
|
}
|
|
625055
626082
|
function encryptProfile(profile, password) {
|
|
625056
|
-
const salt =
|
|
626083
|
+
const salt = randomBytes24(32);
|
|
625057
626084
|
const key = scryptSync3(password, salt, 32);
|
|
625058
|
-
const iv =
|
|
626085
|
+
const iv = randomBytes24(16);
|
|
625059
626086
|
const cipher = createCipheriv5("aes-256-gcm", key, iv);
|
|
625060
626087
|
const plaintext = JSON.stringify(profile);
|
|
625061
626088
|
const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
@@ -625708,7 +626735,7 @@ import { dirname as dirname37, join as join137, resolve as resolve45 } from "nod
|
|
|
625708
626735
|
import { homedir as homedir45 } from "node:os";
|
|
625709
626736
|
import { spawn as spawn29, execSync as execSync57 } from "node:child_process";
|
|
625710
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";
|
|
625711
|
-
import { randomBytes as
|
|
626738
|
+
import { randomBytes as randomBytes25, randomUUID as randomUUID16 } from "node:crypto";
|
|
625712
626739
|
import { createHash as createHash27 } from "node:crypto";
|
|
625713
626740
|
function memoryDbPaths3(baseDir = process.cwd()) {
|
|
625714
626741
|
const dir = join137(baseDir, ".omnius");
|
|
@@ -627384,7 +628411,7 @@ ${messages2[firstSystemIdx].content}`
|
|
|
627384
628411
|
messages2.unshift({ role: "system", content: SYSTEM_FACTUAL_FIRST });
|
|
627385
628412
|
}
|
|
627386
628413
|
}
|
|
627387
|
-
const chatId = `chatcmpl-${
|
|
628414
|
+
const chatId = `chatcmpl-${randomBytes25(12).toString("hex")}`;
|
|
627388
628415
|
const turnsLog = [];
|
|
627389
628416
|
for (let turn = 1; turn <= maxTurns; turn++) {
|
|
627390
628417
|
if (Date.now() > totalDeadline) {
|
|
@@ -627650,7 +628677,7 @@ async function handleV1ChatCompletions(req2, res, ollamaUrl) {
|
|
|
627650
628677
|
"Cache-Control": "no-cache",
|
|
627651
628678
|
"Connection": "keep-alive"
|
|
627652
628679
|
});
|
|
627653
|
-
const chatId = `chatcmpl-${
|
|
628680
|
+
const chatId = `chatcmpl-${randomBytes25(12).toString("hex")}`;
|
|
627654
628681
|
let buffer2 = "";
|
|
627655
628682
|
ollamaStream(
|
|
627656
628683
|
targetUrl,
|
|
@@ -627692,7 +628719,7 @@ async function handleV1ChatCompletions(req2, res, ollamaUrl) {
|
|
|
627692
628719
|
if (ollamaChunk.message.content) delta.content = ollamaChunk.message.content;
|
|
627693
628720
|
if (ollamaChunk.message.tool_calls) {
|
|
627694
628721
|
delta.tool_calls = ollamaChunk.message.tool_calls.map((tc, idx) => ({
|
|
627695
|
-
id: tc.id || `call_${
|
|
628722
|
+
id: tc.id || `call_${randomBytes25(8).toString("hex")}`,
|
|
627696
628723
|
type: "function",
|
|
627697
628724
|
function: {
|
|
627698
628725
|
name: tc?.function?.name ?? tc?.name ?? "",
|
|
@@ -627772,14 +628799,14 @@ async function handleV1ChatCompletions(req2, res, ollamaUrl) {
|
|
|
627772
628799
|
if (ollamaResp.eval_count) metrics.totalTokensOut += ollamaResp.eval_count;
|
|
627773
628800
|
if (ollamaResp.prompt_eval_count) metrics.totalTokensIn += ollamaResp.prompt_eval_count;
|
|
627774
628801
|
trackTokens("local", ollamaResp.prompt_eval_count ?? 0, ollamaResp.eval_count ?? 0);
|
|
627775
|
-
const chatId = `chatcmpl-${
|
|
628802
|
+
const chatId = `chatcmpl-${randomBytes25(12).toString("hex")}`;
|
|
627776
628803
|
const responseMessage = {
|
|
627777
628804
|
role: ollamaResp.message?.role ?? "assistant",
|
|
627778
628805
|
content: ollamaResp.message?.content ?? ""
|
|
627779
628806
|
};
|
|
627780
628807
|
if (ollamaResp.message?.tool_calls && ollamaResp.message.tool_calls.length > 0) {
|
|
627781
628808
|
responseMessage.tool_calls = ollamaResp.message.tool_calls.map((tc, idx) => ({
|
|
627782
|
-
id: tc.id || `call_${
|
|
628809
|
+
id: tc.id || `call_${randomBytes25(8).toString("hex")}`,
|
|
627783
628810
|
type: "function",
|
|
627784
628811
|
function: {
|
|
627785
628812
|
name: tc?.function?.name ?? tc?.name ?? "",
|
|
@@ -628564,7 +629591,7 @@ async function handleV1Run(req2, res) {
|
|
|
628564
629591
|
return;
|
|
628565
629592
|
}
|
|
628566
629593
|
}
|
|
628567
|
-
const id = `job-${
|
|
629594
|
+
const id = `job-${randomBytes25(8).toString("hex")}`;
|
|
628568
629595
|
const dir = jobsDir();
|
|
628569
629596
|
const workingDir = requestBody["working_directory"] || req2.headers["x-working-directory"];
|
|
628570
629597
|
const isolate = requestBody["isolate"] === true;
|
|
@@ -639256,6 +640283,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
639256
640283
|
telegramBridge.setContextWindowSize(resolvedContextWindowSize);
|
|
639257
640284
|
}
|
|
639258
640285
|
telegramBridge.setInteractionMode(savedSettings.telegramMode ?? "auto");
|
|
640286
|
+
telegramBridge.setTelegramToolPolicy(savedSettings.telegramToolPolicy);
|
|
639259
640287
|
if (adminId) {
|
|
639260
640288
|
telegramBridge.setAdmin(adminId);
|
|
639261
640289
|
}
|
|
@@ -639469,6 +640497,34 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
639469
640497
|
if (!telegramBridge?.isActive) throw new Error("Telegram bridge not active.");
|
|
639470
640498
|
return telegramBridge.deleteAllMessageReactions(chatId, options2);
|
|
639471
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
|
+
},
|
|
639472
640528
|
async telegramGetChatAdministrators(chatId, returnBots) {
|
|
639473
640529
|
if (!telegramBridge?.isActive) throw new Error("Telegram bridge not active.");
|
|
639474
640530
|
return telegramBridge.getChatAdministrators(chatId, returnBots);
|
|
@@ -642285,7 +643341,7 @@ __export(run_exports, {
|
|
|
642285
643341
|
import { resolve as resolve47 } from "node:path";
|
|
642286
643342
|
import { spawn as spawn30 } from "node:child_process";
|
|
642287
643343
|
import { mkdirSync as mkdirSync77, writeFileSync as writeFileSync69, readFileSync as readFileSync102, readdirSync as readdirSync44, existsSync as existsSync124 } from "node:fs";
|
|
642288
|
-
import { randomBytes as
|
|
643344
|
+
import { randomBytes as randomBytes26 } from "node:crypto";
|
|
642289
643345
|
import { join as join140 } from "node:path";
|
|
642290
643346
|
function jobsDir2(repoPath) {
|
|
642291
643347
|
const root = resolve47(repoPath ?? process.cwd());
|
|
@@ -642383,7 +643439,7 @@ function extractSummary(captured) {
|
|
|
642383
643439
|
return lines.slice(-3).join(" ").slice(0, 200);
|
|
642384
643440
|
}
|
|
642385
643441
|
async function runBackground(task, config, opts) {
|
|
642386
|
-
const id = `job-${
|
|
643442
|
+
const id = `job-${randomBytes26(3).toString("hex")}`;
|
|
642387
643443
|
const dir = jobsDir2(opts.repoPath);
|
|
642388
643444
|
const repoRoot = resolve47(opts.repoPath ?? process.cwd());
|
|
642389
643445
|
const job = {
|