@integrity-labs/agt-cli 0.12.8 → 0.12.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/agt.js +2 -2
- package/mcp/index.js +3 -6
- package/mcp/telegram-channel.js +136 -4
- package/package.json +1 -1
package/dist/bin/agt.js
CHANGED
|
@@ -3717,7 +3717,7 @@ import { execFileSync, execSync } from "child_process";
|
|
|
3717
3717
|
import { existsSync as existsSync5, realpathSync } from "fs";
|
|
3718
3718
|
import chalk20 from "chalk";
|
|
3719
3719
|
import ora15 from "ora";
|
|
3720
|
-
var cliVersion = true ? "0.12.
|
|
3720
|
+
var cliVersion = true ? "0.12.9" : "dev";
|
|
3721
3721
|
async function fetchLatestVersion() {
|
|
3722
3722
|
const host2 = getHost();
|
|
3723
3723
|
if (!host2) return null;
|
|
@@ -4166,7 +4166,7 @@ function handleError(err) {
|
|
|
4166
4166
|
}
|
|
4167
4167
|
|
|
4168
4168
|
// src/bin/agt.ts
|
|
4169
|
-
var cliVersion2 = true ? "0.12.
|
|
4169
|
+
var cliVersion2 = true ? "0.12.9" : "dev";
|
|
4170
4170
|
var program = new Command();
|
|
4171
4171
|
program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
|
|
4172
4172
|
program.hook("preAction", (thisCommand) => {
|
package/mcp/index.js
CHANGED
|
@@ -21150,13 +21150,10 @@ server.tool(
|
|
|
21150
21150
|
}
|
|
21151
21151
|
]
|
|
21152
21152
|
});
|
|
21153
|
+
const first = data.added_items?.[0];
|
|
21154
|
+
const text = !data.ok ? "Failed to add item." : first ? `Added "${first.title}" to board (status: ${params.status ?? "today"}, id: ${first.id}). Board: ${first.url}` : `Added "${params.title}" to board (status: ${params.status ?? "today"}).`;
|
|
21153
21155
|
return {
|
|
21154
|
-
content: [
|
|
21155
|
-
{
|
|
21156
|
-
type: "text",
|
|
21157
|
-
text: data.ok ? `Added "${params.title}" to board (status: ${params.status ?? "today"}).` : "Failed to add item."
|
|
21158
|
-
}
|
|
21159
|
-
]
|
|
21156
|
+
content: [{ type: "text", text }]
|
|
21160
21157
|
};
|
|
21161
21158
|
}
|
|
21162
21159
|
);
|
package/mcp/telegram-channel.js
CHANGED
|
@@ -13863,6 +13863,10 @@ var StdioServerTransport = class {
|
|
|
13863
13863
|
|
|
13864
13864
|
// src/telegram-channel.ts
|
|
13865
13865
|
import https from "https";
|
|
13866
|
+
import { createHash } from "crypto";
|
|
13867
|
+
function redactId(id) {
|
|
13868
|
+
return createHash("sha256").update(String(id)).digest("hex").slice(0, 8);
|
|
13869
|
+
}
|
|
13866
13870
|
var BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
|
|
13867
13871
|
var AGENT_CODE_NAME = process.env.AGT_AGENT_CODE_NAME ?? "unknown";
|
|
13868
13872
|
var ALLOWED_CHATS = new Set(
|
|
@@ -13913,6 +13917,67 @@ function telegramApiCall(method, body, timeoutMs) {
|
|
|
13913
13917
|
req.end();
|
|
13914
13918
|
});
|
|
13915
13919
|
}
|
|
13920
|
+
var ACK_EMOJI = "\u{1F440}";
|
|
13921
|
+
var TIMEOUT_EMOJI = "\u{1F494}";
|
|
13922
|
+
var RESPONSE_TIMEOUT_MS = 12e4;
|
|
13923
|
+
async function setMessageReaction(chatId, messageId, emoji2) {
|
|
13924
|
+
try {
|
|
13925
|
+
const resp = await telegramApiCall(
|
|
13926
|
+
"setMessageReaction",
|
|
13927
|
+
{
|
|
13928
|
+
chat_id: chatId,
|
|
13929
|
+
message_id: Number(messageId),
|
|
13930
|
+
reaction: emoji2 ? [{ type: "emoji", emoji: emoji2 }] : []
|
|
13931
|
+
},
|
|
13932
|
+
1e4
|
|
13933
|
+
);
|
|
13934
|
+
if (!resp.ok) {
|
|
13935
|
+
process.stderr.write(
|
|
13936
|
+
`telegram-channel(${AGENT_CODE_NAME}): setMessageReaction failed (${emoji2 ?? "clear"}): ${resp.description ?? "unknown"}
|
|
13937
|
+
`
|
|
13938
|
+
);
|
|
13939
|
+
}
|
|
13940
|
+
} catch (err) {
|
|
13941
|
+
process.stderr.write(
|
|
13942
|
+
`telegram-channel(${AGENT_CODE_NAME}): setMessageReaction error: ${err.message}
|
|
13943
|
+
`
|
|
13944
|
+
);
|
|
13945
|
+
}
|
|
13946
|
+
}
|
|
13947
|
+
var pendingMessages = /* @__PURE__ */ new Map();
|
|
13948
|
+
function trackPendingMessage(chatId, messageId, chatType) {
|
|
13949
|
+
const key = `${chatId}:${messageId}`;
|
|
13950
|
+
const existing = pendingMessages.get(key);
|
|
13951
|
+
if (existing) clearTimeout(existing.timer);
|
|
13952
|
+
const timer = setTimeout(() => {
|
|
13953
|
+
pendingMessages.delete(key);
|
|
13954
|
+
void setMessageReaction(chatId, messageId, TIMEOUT_EMOJI);
|
|
13955
|
+
process.stderr.write(
|
|
13956
|
+
`telegram-channel(${AGENT_CODE_NAME}): response timeout for message ${redactId(messageId)} in chat ${redactId(chatId)}
|
|
13957
|
+
`
|
|
13958
|
+
);
|
|
13959
|
+
}, RESPONSE_TIMEOUT_MS);
|
|
13960
|
+
timer.unref?.();
|
|
13961
|
+
pendingMessages.set(key, { timer, chatType });
|
|
13962
|
+
}
|
|
13963
|
+
function clearPendingMessage(chatId, messageId) {
|
|
13964
|
+
if (messageId) {
|
|
13965
|
+
const key = `${chatId}:${messageId}`;
|
|
13966
|
+
const entry = pendingMessages.get(key);
|
|
13967
|
+
if (entry) {
|
|
13968
|
+
clearTimeout(entry.timer);
|
|
13969
|
+
pendingMessages.delete(key);
|
|
13970
|
+
}
|
|
13971
|
+
return;
|
|
13972
|
+
}
|
|
13973
|
+
const prefix = `${chatId}:`;
|
|
13974
|
+
for (const [key, entry] of pendingMessages) {
|
|
13975
|
+
if (!key.startsWith(prefix)) continue;
|
|
13976
|
+
if (entry.chatType !== "private") continue;
|
|
13977
|
+
clearTimeout(entry.timer);
|
|
13978
|
+
pendingMessages.delete(key);
|
|
13979
|
+
}
|
|
13980
|
+
}
|
|
13916
13981
|
var mcp = new Server(
|
|
13917
13982
|
{ name: "telegram", version: "0.1.0" },
|
|
13918
13983
|
{
|
|
@@ -13922,10 +13987,15 @@ var mcp = new Server(
|
|
|
13922
13987
|
},
|
|
13923
13988
|
instructions: [
|
|
13924
13989
|
'Messages from Telegram arrive as <channel source="telegram" chat_id="..." user="..." user_name="..." message_id="...">.',
|
|
13925
|
-
"
|
|
13990
|
+
"The user reads Telegram, not this session. The ONLY way to reach them is the telegram.reply tool \u2014 anything you put in session output is invisible to them.",
|
|
13991
|
+
`EVERY response to a Telegram message goes through telegram.reply, passing the chat_id from the tag. This includes clarifying questions, error messages, partial answers, "I don't understand", and status updates \u2014 no exceptions.`,
|
|
13992
|
+
'For work that will take more than ~30 seconds, follow the standard kanban flow from CLAUDE.md: call kanban.add to track the task, then IMMEDIATELY reply via telegram.reply with "On it \u2014 tracking here: <kanban URL>" including the created task title, move the task to in_progress, do the work, and reply via telegram.reply with the result.',
|
|
13993
|
+
"Simple lookups, one-line answers, and no-action acknowledgements do NOT need a kanban task \u2014 but still reply via telegram.reply every time.",
|
|
13994
|
+
"When a user mentions a time without a timezone, interpret it in your Timezone from the Identity section of CLAUDE.md. Do NOT ask the user which timezone they meant \u2014 resolve it yourself against your own identity.",
|
|
13926
13995
|
"Address users by their user_name when possible; user is their numeric Telegram ID.",
|
|
13927
|
-
"To reply
|
|
13928
|
-
"Telegram DMs are 1:1 \u2014 always reply
|
|
13996
|
+
"To quote-reply to a specific earlier message, pass its message_id as reply_to_message_id \u2014 otherwise omit it for a normal reply.",
|
|
13997
|
+
"Telegram DMs are 1:1 \u2014 always reply to every inbound message unless it is obviously not addressed to you.",
|
|
13998
|
+
'Every inbound message gets an automatic \u{1F440} reaction as a "seen, working on it" ack. Use the telegram.react tool to add your own reactions (e.g. \u270D while clarifying, \u{1FAE1} on task complete). Only free-tier emoji are available to bots \u2014 stick to: \u{1F44D} \u{1F44E} \u2764 \u{1F525} \u{1F389} \u{1F914} \u{1F92F} \u{1F64F} \u{1F44C} \u{1F440} \u{1F4AF} \u270D \u{1FAE1} \u{1F192} \u{1F973} and similar common reactions. Premium-only emoji fail silently.'
|
|
13929
13999
|
].join(" ")
|
|
13930
14000
|
}
|
|
13931
14001
|
);
|
|
@@ -13964,6 +14034,28 @@ mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
13964
14034
|
},
|
|
13965
14035
|
required: ["chat_id", "text"]
|
|
13966
14036
|
}
|
|
14037
|
+
},
|
|
14038
|
+
{
|
|
14039
|
+
name: "telegram.react",
|
|
14040
|
+
description: "Add an emoji reaction to a Telegram message. Only free-tier emoji reactions are available to bots (Premium-only emoji fail silently). Pass an empty string or omit emoji to clear the bot's reaction on that message.",
|
|
14041
|
+
inputSchema: {
|
|
14042
|
+
type: "object",
|
|
14043
|
+
properties: {
|
|
14044
|
+
chat_id: {
|
|
14045
|
+
type: "string",
|
|
14046
|
+
description: "Telegram chat ID (from the chat_id attribute in the <channel> tag)"
|
|
14047
|
+
},
|
|
14048
|
+
message_id: {
|
|
14049
|
+
type: "string",
|
|
14050
|
+
description: "Telegram message_id to react to (from the message_id attribute)"
|
|
14051
|
+
},
|
|
14052
|
+
emoji: {
|
|
14053
|
+
type: "string",
|
|
14054
|
+
description: `A single emoji from Telegram's free-tier reaction set (e.g. "\u{1F440}", "\u{1FAE1}", "\u270D", "\u{1F525}"). Pass "" to clear.`
|
|
14055
|
+
}
|
|
14056
|
+
},
|
|
14057
|
+
required: ["chat_id", "message_id"]
|
|
14058
|
+
}
|
|
13967
14059
|
}
|
|
13968
14060
|
]
|
|
13969
14061
|
}));
|
|
@@ -13987,6 +14079,9 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
13987
14079
|
isError: true
|
|
13988
14080
|
};
|
|
13989
14081
|
}
|
|
14082
|
+
if (name === "telegram.reply") {
|
|
14083
|
+
clearPendingMessage(chat_id, reply_to_message_id);
|
|
14084
|
+
}
|
|
13990
14085
|
return { content: [{ type: "text", text: "sent" }] };
|
|
13991
14086
|
} catch (err) {
|
|
13992
14087
|
return {
|
|
@@ -13995,6 +14090,38 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
13995
14090
|
};
|
|
13996
14091
|
}
|
|
13997
14092
|
}
|
|
14093
|
+
if (name === "telegram.react") {
|
|
14094
|
+
const { chat_id, message_id, emoji: emoji2 } = args;
|
|
14095
|
+
if (ALLOWED_CHATS.size > 0 && !ALLOWED_CHATS.has(chat_id)) {
|
|
14096
|
+
return {
|
|
14097
|
+
content: [{ type: "text", text: `Chat ${chat_id} is not in TELEGRAM_ALLOWED_CHATS` }],
|
|
14098
|
+
isError: true
|
|
14099
|
+
};
|
|
14100
|
+
}
|
|
14101
|
+
try {
|
|
14102
|
+
const data = await telegramApiCall(
|
|
14103
|
+
"setMessageReaction",
|
|
14104
|
+
{
|
|
14105
|
+
chat_id,
|
|
14106
|
+
message_id: Number(message_id),
|
|
14107
|
+
reaction: emoji2 ? [{ type: "emoji", emoji: emoji2 }] : []
|
|
14108
|
+
},
|
|
14109
|
+
1e4
|
|
14110
|
+
);
|
|
14111
|
+
if (!data.ok) {
|
|
14112
|
+
return {
|
|
14113
|
+
content: [{ type: "text", text: `Telegram error: ${data.description ?? "unknown"}` }],
|
|
14114
|
+
isError: true
|
|
14115
|
+
};
|
|
14116
|
+
}
|
|
14117
|
+
return { content: [{ type: "text", text: emoji2 ? "reacted" : "cleared" }] };
|
|
14118
|
+
} catch (err) {
|
|
14119
|
+
return {
|
|
14120
|
+
content: [{ type: "text", text: `Failed: ${err.message}` }],
|
|
14121
|
+
isError: true
|
|
14122
|
+
};
|
|
14123
|
+
}
|
|
14124
|
+
}
|
|
13998
14125
|
throw new Error(`Unknown tool: ${name}`);
|
|
13999
14126
|
});
|
|
14000
14127
|
await mcp.connect(new StdioServerTransport());
|
|
@@ -14031,6 +14158,9 @@ async function pollLoop() {
|
|
|
14031
14158
|
if (ALLOWED_CHATS.size > 0 && !ALLOWED_CHATS.has(chatId)) continue;
|
|
14032
14159
|
const userId = msg.from?.id != null ? String(msg.from.id) : "unknown";
|
|
14033
14160
|
const userName = msg.from?.username || [msg.from?.first_name, msg.from?.last_name].filter(Boolean).join(" ").trim() || userId;
|
|
14161
|
+
const messageId = String(msg.message_id);
|
|
14162
|
+
void setMessageReaction(chatId, messageId, ACK_EMOJI);
|
|
14163
|
+
trackPendingMessage(chatId, messageId, msg.chat.type);
|
|
14034
14164
|
await mcp.notification({
|
|
14035
14165
|
method: "notifications/claude/channel",
|
|
14036
14166
|
params: {
|
|
@@ -14039,7 +14169,7 @@ async function pollLoop() {
|
|
|
14039
14169
|
source: "telegram",
|
|
14040
14170
|
chat_id: chatId,
|
|
14041
14171
|
chat_type: msg.chat.type,
|
|
14042
|
-
message_id:
|
|
14172
|
+
message_id: messageId,
|
|
14043
14173
|
user: userId,
|
|
14044
14174
|
user_name: userName,
|
|
14045
14175
|
ts: String(msg.date)
|
|
@@ -14063,6 +14193,8 @@ function sleep(ms) {
|
|
|
14063
14193
|
function shutdown(reason) {
|
|
14064
14194
|
if (isShuttingDown) return;
|
|
14065
14195
|
isShuttingDown = true;
|
|
14196
|
+
for (const { timer } of pendingMessages.values()) clearTimeout(timer);
|
|
14197
|
+
pendingMessages.clear();
|
|
14066
14198
|
process.stderr.write(
|
|
14067
14199
|
`telegram-channel(${AGENT_CODE_NAME}): ${reason} \u2014 exiting
|
|
14068
14200
|
`
|