@integrity-labs/agt-cli 0.28.739 → 0.28.741
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.
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
safeWriteJsonAtomic,
|
|
58
58
|
setConfigHash,
|
|
59
59
|
tripClass
|
|
60
|
-
} from "../chunk-
|
|
60
|
+
} from "../chunk-2HGXCU4Y.js";
|
|
61
61
|
import {
|
|
62
62
|
getProjectDir as getProjectDir2,
|
|
63
63
|
getReadyTasks,
|
|
@@ -13154,7 +13154,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
13154
13154
|
var lastVersionCheckAt = 0;
|
|
13155
13155
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
13156
13156
|
var lastResponsivenessProbeAt = 0;
|
|
13157
|
-
var agtCliVersion = true ? "0.28.
|
|
13157
|
+
var agtCliVersion = true ? "0.28.741" : "dev";
|
|
13158
13158
|
function resolveBrewPath(execFileSync3) {
|
|
13159
13159
|
try {
|
|
13160
13160
|
const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -39055,9 +39055,55 @@ var TELEGRAM_EGRESS_TOOLS = /* @__PURE__ */ new Set([
|
|
|
39055
39055
|
"telegram.react",
|
|
39056
39056
|
"telegram.upload_file",
|
|
39057
39057
|
"telegram.consume",
|
|
39058
|
+
// ENG-9677: leaving a chat is delivery-state mutation of the bluntest kind -
|
|
39059
|
+
// after it, nothing from that chat can ever arrive. An impersonating operator
|
|
39060
|
+
// must not be able to cut an agent off from a customer's group.
|
|
39061
|
+
"telegram.leave_chat",
|
|
39058
39062
|
"channel_request_input"
|
|
39059
39063
|
]);
|
|
39060
39064
|
|
|
39065
|
+
// src/telegram-leave-chat-policy.ts
|
|
39066
|
+
function validateLeaveChatArgs(args) {
|
|
39067
|
+
const { chat_id, reason } = args ?? {};
|
|
39068
|
+
if (typeof chat_id !== "string" || !chat_id.trim()) {
|
|
39069
|
+
return {
|
|
39070
|
+
ok: false,
|
|
39071
|
+
message: "telegram.leave_chat requires chat_id (from the <channel> tag)."
|
|
39072
|
+
};
|
|
39073
|
+
}
|
|
39074
|
+
if (typeof reason !== "string" || !reason.trim()) {
|
|
39075
|
+
return {
|
|
39076
|
+
ok: false,
|
|
39077
|
+
message: "telegram.leave_chat requires a reason (a non-empty string). It is logged, not sent to the chat."
|
|
39078
|
+
};
|
|
39079
|
+
}
|
|
39080
|
+
return { ok: true, chatId: chat_id.trim(), reason: reason.trim() };
|
|
39081
|
+
}
|
|
39082
|
+
function isGroupShapedChatId(chatId) {
|
|
39083
|
+
return /^-\d+$/.test(chatId.trim());
|
|
39084
|
+
}
|
|
39085
|
+
function decideLeaveChat(input) {
|
|
39086
|
+
const chatId = input.chatId.trim();
|
|
39087
|
+
if (input.allowedChats.size > 0 && !input.allowedChats.has(chatId)) {
|
|
39088
|
+
return { allowed: true, because: "not-on-the-allowlist" };
|
|
39089
|
+
}
|
|
39090
|
+
if (input.allowedChats.has(chatId)) {
|
|
39091
|
+
return {
|
|
39092
|
+
allowed: false,
|
|
39093
|
+
because: "operator-only",
|
|
39094
|
+
detail: "this chat is on the agent's allowed_chats list, so leaving it is an operator decision"
|
|
39095
|
+
};
|
|
39096
|
+
}
|
|
39097
|
+
if (input.privateChatsOnly && isGroupShapedChatId(chatId)) {
|
|
39098
|
+
return { allowed: true, because: "group-chat-under-private-chats-only" };
|
|
39099
|
+
}
|
|
39100
|
+
return {
|
|
39101
|
+
allowed: false,
|
|
39102
|
+
because: "operator-only",
|
|
39103
|
+
detail: input.allowedChats.size > 0 ? "this chat is on the agent's allowed_chats list, so leaving it is an operator decision" : input.privateChatsOnly ? "this chat is not a group, so private-chats-only does not bar the agent from it" : "no chat policy is configured for this agent, so nothing marks this chat as one it should not be in"
|
|
39104
|
+
};
|
|
39105
|
+
}
|
|
39106
|
+
|
|
39061
39107
|
// src/telegram-upload.ts
|
|
39062
39108
|
var TELEGRAM_PHOTO_MAX_BYTES = 10 * 1024 * 1024;
|
|
39063
39109
|
var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
|
|
@@ -41428,6 +41474,14 @@ async function computeTelegramOwnChannelLiveStatus() {
|
|
|
41428
41474
|
try {
|
|
41429
41475
|
const resp = await telegramApiCall("getMe", {}, 5e3);
|
|
41430
41476
|
if (resp.ok) {
|
|
41477
|
+
const canJoinGroups = resp.result?.can_join_groups;
|
|
41478
|
+
if (PRIVATE_CHATS_ONLY && canJoinGroups === true) {
|
|
41479
|
+
return {
|
|
41480
|
+
level: "ok",
|
|
41481
|
+
checked_at,
|
|
41482
|
+
reason: "getMe ok \u2014 but this bot can still be ADDED to groups. private_chats_only makes the agent ignore group traffic; it does not close the door. Only the bot owner can: @BotFather \u2192 /mybots \u2192 this bot \u2192 Bot Settings \u2192 Allow Groups? \u2192 Turn off."
|
|
41483
|
+
};
|
|
41484
|
+
}
|
|
41431
41485
|
return { level: "ok", checked_at, reason: "getMe ok" };
|
|
41432
41486
|
}
|
|
41433
41487
|
return { level: "error", checked_at, reason: `getMe rejected: ${resp.description ?? "unknown"}` };
|
|
@@ -41937,6 +41991,14 @@ async function refreshBotIdentity() {
|
|
|
41937
41991
|
if (typeof result.id === "number") {
|
|
41938
41992
|
cachedBotId = result.id;
|
|
41939
41993
|
}
|
|
41994
|
+
if (typeof result.can_join_groups === "boolean") {
|
|
41995
|
+
if (result.can_join_groups && PRIVATE_CHATS_ONLY) {
|
|
41996
|
+
process.stderr.write(
|
|
41997
|
+
`telegram-channel(${AGENT_CODE_NAME}): WARNING private_chats_only is set but this bot's can_join_groups is TRUE, so it can still be added to groups. Only the bot owner can change that: message @BotFather -> /mybots -> select this bot -> Bot Settings -> Group Privacy / Allow Groups? -> Turn off.
|
|
41998
|
+
`
|
|
41999
|
+
);
|
|
42000
|
+
}
|
|
42001
|
+
}
|
|
41940
42002
|
if (cachedBotUsername !== null && cachedBotId !== null) return;
|
|
41941
42003
|
}
|
|
41942
42004
|
process.stderr.write(
|
|
@@ -43109,6 +43171,24 @@ mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
43109
43171
|
required: ["chat_id"]
|
|
43110
43172
|
}
|
|
43111
43173
|
},
|
|
43174
|
+
{
|
|
43175
|
+
name: "telegram.leave_chat",
|
|
43176
|
+
description: "Remove this agent's bot from a Telegram group, supergroup or channel it should not be in. Pass the chat_id from the <channel> tag and a short reason. ONLY works for a chat the agent is already barred from engaging with - one outside its allowed_chats, or a group while private_chats_only is set. Leaving a chat the agent is permitted to be in is an operator decision and this tool will refuse it, deliberately: an agent that can be talked into leaving any chat is a denial-of-service primitive. Leaving does NOT stop anyone re-adding the bot - that is a BotFather setting the owner has to change.",
|
|
43177
|
+
inputSchema: {
|
|
43178
|
+
type: "object",
|
|
43179
|
+
properties: {
|
|
43180
|
+
chat_id: {
|
|
43181
|
+
type: "string",
|
|
43182
|
+
description: "Telegram chat ID to leave (from the chat_id attribute in the <channel> tag)"
|
|
43183
|
+
},
|
|
43184
|
+
reason: {
|
|
43185
|
+
type: "string",
|
|
43186
|
+
description: "Why the bot is leaving. Required, logged, and not sent to the chat. Leaving a chat with no recorded reason is indistinguishable from a mistake when someone reads it back."
|
|
43187
|
+
}
|
|
43188
|
+
},
|
|
43189
|
+
required: ["chat_id", "reason"]
|
|
43190
|
+
}
|
|
43191
|
+
},
|
|
43112
43192
|
{
|
|
43113
43193
|
name: "telegram.send_message",
|
|
43114
43194
|
description: "Send a new Telegram message to an arbitrary chat (agent-initiated, not a reply)",
|
|
@@ -43321,6 +43401,75 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
43321
43401
|
return { content: [{ type: "text", text: `Telegram ${method} error: ${err.message}` }], isError: true };
|
|
43322
43402
|
}
|
|
43323
43403
|
}
|
|
43404
|
+
if (name === "telegram.leave_chat") {
|
|
43405
|
+
const parsed = validateLeaveChatArgs(args);
|
|
43406
|
+
if (!parsed.ok) {
|
|
43407
|
+
return { content: [{ type: "text", text: parsed.message }], isError: true };
|
|
43408
|
+
}
|
|
43409
|
+
const { chatId: chat_id, reason } = parsed;
|
|
43410
|
+
const decision = decideLeaveChat({
|
|
43411
|
+
chatId: chat_id,
|
|
43412
|
+
allowedChats: ALLOWED_CHATS,
|
|
43413
|
+
privateChatsOnly: PRIVATE_CHATS_ONLY
|
|
43414
|
+
});
|
|
43415
|
+
if (!decision.allowed) {
|
|
43416
|
+
process.stderr.write(
|
|
43417
|
+
`telegram-channel(${AGENT_CODE_NAME}): leave_chat REFUSED chat=${redactId(chat_id)} why=${decision.because} detail=${JSON.stringify(decision.detail)}
|
|
43418
|
+
`
|
|
43419
|
+
);
|
|
43420
|
+
return {
|
|
43421
|
+
content: [
|
|
43422
|
+
{
|
|
43423
|
+
type: "text",
|
|
43424
|
+
text: `Not leaving ${chat_id}: ${decision.detail}. This tool only removes the bot from chats the agent is already barred from engaging with, so that an instruction to leave cannot be used to cut the owner off from a chat they wanted. An operator can do it from the console.`
|
|
43425
|
+
}
|
|
43426
|
+
],
|
|
43427
|
+
isError: true
|
|
43428
|
+
};
|
|
43429
|
+
}
|
|
43430
|
+
let resp;
|
|
43431
|
+
try {
|
|
43432
|
+
resp = await telegramApiCall("leaveChat", { chat_id }, 1e4);
|
|
43433
|
+
} catch (err) {
|
|
43434
|
+
const detail = err.message;
|
|
43435
|
+
process.stderr.write(
|
|
43436
|
+
`telegram-channel(${AGENT_CODE_NAME}): leave_chat chat=${redactId(chat_id)} allowed_because=${decision.because} ok=false transport_error=${JSON.stringify(detail)} reason=${JSON.stringify(reason)}
|
|
43437
|
+
`
|
|
43438
|
+
);
|
|
43439
|
+
return {
|
|
43440
|
+
content: [
|
|
43441
|
+
{
|
|
43442
|
+
type: "text",
|
|
43443
|
+
text: `Could not reach Telegram to leave ${chat_id}: ${detail}. The bot is still in the chat \u2014 nothing changed, so this is safe to retry.`
|
|
43444
|
+
}
|
|
43445
|
+
],
|
|
43446
|
+
isError: true
|
|
43447
|
+
};
|
|
43448
|
+
}
|
|
43449
|
+
process.stderr.write(
|
|
43450
|
+
`telegram-channel(${AGENT_CODE_NAME}): leave_chat chat=${redactId(chat_id)} allowed_because=${decision.because} ok=${resp.ok} reason=${JSON.stringify(reason)}${resp.ok ? "" : ` error=${resp.description ?? "unknown"}`}
|
|
43451
|
+
`
|
|
43452
|
+
);
|
|
43453
|
+
if (!resp.ok) {
|
|
43454
|
+
return {
|
|
43455
|
+
content: [
|
|
43456
|
+
{
|
|
43457
|
+
type: "text",
|
|
43458
|
+
text: `Telegram refused the leave for ${chat_id}: ${resp.description ?? "unknown error"}.`
|
|
43459
|
+
}
|
|
43460
|
+
],
|
|
43461
|
+
isError: true
|
|
43462
|
+
};
|
|
43463
|
+
}
|
|
43464
|
+
return {
|
|
43465
|
+
content: [
|
|
43466
|
+
{
|
|
43467
|
+
type: "text",
|
|
43468
|
+
text: `Left ${chat_id}. Note this does NOT stop anyone adding the bot back: whether it can be added to groups at all is a BotFather setting (/setjoingroups), which only the bot owner can change.`
|
|
43469
|
+
}
|
|
43470
|
+
]
|
|
43471
|
+
};
|
|
43472
|
+
}
|
|
43324
43473
|
if (name === "telegram.consume") {
|
|
43325
43474
|
const { chat_id, reason } = args;
|
|
43326
43475
|
if (!chat_id) {
|