@locusai/locus-telegram 0.23.1 → 0.23.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/locus-telegram.js +64 -21
- package/package.json +4 -4
package/bin/locus-telegram.js
CHANGED
|
@@ -10250,8 +10250,14 @@ var init_cancel = __esm(() => {
|
|
|
10250
10250
|
});
|
|
10251
10251
|
|
|
10252
10252
|
// src/ui/keyboards.ts
|
|
10253
|
-
function planKeyboard() {
|
|
10254
|
-
return new import_grammy2.InlineKeyboard().text("✅ Approve Plan", CB.APPROVE_PLAN).text("❌ Reject Plan", CB.REJECT_PLAN)
|
|
10253
|
+
function planKeyboard(planId) {
|
|
10254
|
+
return new import_grammy2.InlineKeyboard().text("✅ Approve Plan", `${CB.APPROVE_PLAN}${planId}`).text("❌ Reject Plan", CB.REJECT_PLAN);
|
|
10255
|
+
}
|
|
10256
|
+
function sprintActiveKeyboard(sprintName) {
|
|
10257
|
+
return new import_grammy2.InlineKeyboard().text("\uD83D\uDE80 Activate Sprint", `${CB.SPRINT_ACTIVE}${sprintName}`);
|
|
10258
|
+
}
|
|
10259
|
+
function runKeyboard() {
|
|
10260
|
+
return new import_grammy2.InlineKeyboard().text("\uD83D\uDE80 Run", CB.RUN_START);
|
|
10255
10261
|
}
|
|
10256
10262
|
function runCompleteKeyboard(issueNumber) {
|
|
10257
10263
|
const kb = new import_grammy2.InlineKeyboard;
|
|
@@ -10274,9 +10280,10 @@ var import_grammy2, CB;
|
|
|
10274
10280
|
var init_keyboards = __esm(() => {
|
|
10275
10281
|
import_grammy2 = __toESM(require_mod(), 1);
|
|
10276
10282
|
CB = {
|
|
10277
|
-
APPROVE_PLAN: "plan:approve",
|
|
10283
|
+
APPROVE_PLAN: "plan:approve:",
|
|
10278
10284
|
REJECT_PLAN: "plan:reject",
|
|
10279
|
-
|
|
10285
|
+
SPRINT_ACTIVE: "sprint:active:",
|
|
10286
|
+
RUN_START: "run:start",
|
|
10280
10287
|
CONFIRM_ACTION: "confirm:yes",
|
|
10281
10288
|
CANCEL_ACTION: "confirm:no",
|
|
10282
10289
|
VIEW_PR: "pr:view:",
|
|
@@ -10706,7 +10713,7 @@ async function handleLocusCommand(ctx, command, args) {
|
|
|
10706
10713
|
if (isStreaming) {
|
|
10707
10714
|
await handleStreamingCommand(ctx, displayCmd, fullArgs, command, args);
|
|
10708
10715
|
} else {
|
|
10709
|
-
await handleBufferedCommand(ctx, displayCmd, fullArgs, command);
|
|
10716
|
+
await handleBufferedCommand(ctx, displayCmd, fullArgs, command, args);
|
|
10710
10717
|
}
|
|
10711
10718
|
}
|
|
10712
10719
|
async function handleStreamingCommand(ctx, displayCmd, fullArgs, command, args) {
|
|
@@ -10748,7 +10755,7 @@ async function handleStreamingCommand(ctx, displayCmd, fullArgs, command, args)
|
|
|
10748
10755
|
try {
|
|
10749
10756
|
await ctx.api.editMessageText(msg.chat.id, msg.message_id, formatStreamingMessage(displayCmd, output, true), { parse_mode: "HTML" });
|
|
10750
10757
|
} catch {}
|
|
10751
|
-
const keyboard = getPostCommandKeyboard(command, args, exitCode ?? 0);
|
|
10758
|
+
const keyboard = getPostCommandKeyboard(command, args, exitCode ?? 0, output);
|
|
10752
10759
|
if (keyboard) {
|
|
10753
10760
|
await ctx.reply(exitCode === 0 ? "What would you like to do next?" : "Command failed.", { reply_markup: keyboard });
|
|
10754
10761
|
}
|
|
@@ -10756,13 +10763,13 @@ async function handleStreamingCommand(ctx, displayCmd, fullArgs, command, args)
|
|
|
10756
10763
|
});
|
|
10757
10764
|
});
|
|
10758
10765
|
}
|
|
10759
|
-
async function handleBufferedCommand(ctx, displayCmd, fullArgs, command) {
|
|
10766
|
+
async function handleBufferedCommand(ctx, displayCmd, fullArgs, command, args) {
|
|
10760
10767
|
const chatId = ctx.chat?.id;
|
|
10761
10768
|
if (!chatId)
|
|
10762
10769
|
return;
|
|
10763
10770
|
const sessionId = String(chatId);
|
|
10764
10771
|
const child = invokeLocusStream(fullArgs);
|
|
10765
|
-
const trackingId = commandTracker.track(sessionId, command,
|
|
10772
|
+
const trackingId = commandTracker.track(sessionId, command, args, child);
|
|
10766
10773
|
let output = "";
|
|
10767
10774
|
child.stdout?.on("data", (chunk) => {
|
|
10768
10775
|
output += chunk.toString();
|
|
@@ -10774,7 +10781,7 @@ async function handleBufferedCommand(ctx, displayCmd, fullArgs, command) {
|
|
|
10774
10781
|
child.on("close", async (exitCode) => {
|
|
10775
10782
|
commandTracker.untrack(sessionId, trackingId);
|
|
10776
10783
|
const result = formatCommandResult(displayCmd, output, exitCode ?? 0);
|
|
10777
|
-
const keyboard = getPostCommandKeyboard(command,
|
|
10784
|
+
const keyboard = getPostCommandKeyboard(command, args, exitCode ?? 0, output);
|
|
10778
10785
|
await ctx.reply(result, {
|
|
10779
10786
|
parse_mode: "HTML",
|
|
10780
10787
|
reply_markup: keyboard ?? undefined
|
|
@@ -10783,12 +10790,43 @@ async function handleBufferedCommand(ctx, displayCmd, fullArgs, command) {
|
|
|
10783
10790
|
});
|
|
10784
10791
|
});
|
|
10785
10792
|
}
|
|
10786
|
-
function
|
|
10793
|
+
function stripAnsi(text) {
|
|
10794
|
+
return text.replace(/\x1B\[[0-9;]*m/g, "");
|
|
10795
|
+
}
|
|
10796
|
+
function extractPlanId(output) {
|
|
10797
|
+
const clean = stripAnsi(output);
|
|
10798
|
+
const match = clean.match(/Plan saved:\s*(\S+)/);
|
|
10799
|
+
return match?.[1] ?? null;
|
|
10800
|
+
}
|
|
10801
|
+
function extractSprintName(output) {
|
|
10802
|
+
const clean = stripAnsi(output);
|
|
10803
|
+
const match = clean.match(/Sprint:\s*(.+?)$/m);
|
|
10804
|
+
return match?.[1]?.trim() ?? null;
|
|
10805
|
+
}
|
|
10806
|
+
function getPostCommandKeyboard(command, args, exitCode, output = "") {
|
|
10787
10807
|
if (exitCode !== 0)
|
|
10788
10808
|
return null;
|
|
10789
10809
|
switch (command) {
|
|
10790
|
-
case "plan":
|
|
10791
|
-
|
|
10810
|
+
case "plan": {
|
|
10811
|
+
if (args[0] === "approve") {
|
|
10812
|
+
const sprint = extractSprintName(output);
|
|
10813
|
+
if (sprint)
|
|
10814
|
+
return sprintActiveKeyboard(sprint);
|
|
10815
|
+
return runKeyboard();
|
|
10816
|
+
}
|
|
10817
|
+
if (args[0] !== "list" && args[0] !== "show") {
|
|
10818
|
+
const planId = extractPlanId(output);
|
|
10819
|
+
if (planId)
|
|
10820
|
+
return planKeyboard(planId);
|
|
10821
|
+
}
|
|
10822
|
+
return null;
|
|
10823
|
+
}
|
|
10824
|
+
case "sprint": {
|
|
10825
|
+
if (args[0] === "active" && args.length > 1) {
|
|
10826
|
+
return runKeyboard();
|
|
10827
|
+
}
|
|
10828
|
+
return null;
|
|
10829
|
+
}
|
|
10792
10830
|
case "review":
|
|
10793
10831
|
if (args.length > 0) {
|
|
10794
10832
|
return reviewKeyboard(Number(args[0]));
|
|
@@ -10966,13 +11004,11 @@ function createBot(config) {
|
|
|
10966
11004
|
return bot;
|
|
10967
11005
|
}
|
|
10968
11006
|
function registerCallbackHandlers(bot) {
|
|
10969
|
-
bot.callbackQuery(
|
|
10970
|
-
|
|
11007
|
+
bot.callbackQuery(/^plan:approve:(.+)$/, async (ctx) => {
|
|
11008
|
+
const planId = ctx.match[1];
|
|
11009
|
+
await ctx.answerCallbackQuery({ text: "Approving plan..." });
|
|
10971
11010
|
await ctx.editMessageReplyMarkup({ reply_markup: undefined });
|
|
10972
|
-
await ctx
|
|
10973
|
-
parse_mode: "HTML"
|
|
10974
|
-
});
|
|
10975
|
-
await handleLocusCommand(ctx, "run", []);
|
|
11011
|
+
await handleLocusCommand(ctx, "plan", ["approve", planId]);
|
|
10976
11012
|
});
|
|
10977
11013
|
bot.callbackQuery(CB.REJECT_PLAN, async (ctx) => {
|
|
10978
11014
|
await ctx.answerCallbackQuery({ text: "Plan rejected." });
|
|
@@ -10981,9 +11017,16 @@ function registerCallbackHandlers(bot) {
|
|
|
10981
11017
|
parse_mode: "HTML"
|
|
10982
11018
|
});
|
|
10983
11019
|
});
|
|
10984
|
-
bot.callbackQuery(
|
|
10985
|
-
|
|
10986
|
-
await
|
|
11020
|
+
bot.callbackQuery(/^sprint:active:(.+)$/, async (ctx) => {
|
|
11021
|
+
const sprintName = ctx.match[1];
|
|
11022
|
+
await ctx.answerCallbackQuery({ text: "Activating sprint..." });
|
|
11023
|
+
await ctx.editMessageReplyMarkup({ reply_markup: undefined });
|
|
11024
|
+
await handleLocusCommand(ctx, "sprint", ["active", sprintName]);
|
|
11025
|
+
});
|
|
11026
|
+
bot.callbackQuery(CB.RUN_START, async (ctx) => {
|
|
11027
|
+
await ctx.answerCallbackQuery({ text: "Starting run..." });
|
|
11028
|
+
await ctx.editMessageReplyMarkup({ reply_markup: undefined });
|
|
11029
|
+
await handleLocusCommand(ctx, "run", []);
|
|
10987
11030
|
});
|
|
10988
11031
|
bot.callbackQuery(CB.VIEW_LOGS, async (ctx) => {
|
|
10989
11032
|
await ctx.answerCallbackQuery();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@locusai/locus-telegram",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.2",
|
|
4
4
|
"description": "Remote-control Locus via Telegram with full CLI mapping, git operations, and PM2 management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@grammyjs/runner": "^2.0.3",
|
|
30
|
-
"@locusai/locus-gateway": "^0.23.
|
|
31
|
-
"@locusai/locus-pm2": "^0.23.
|
|
32
|
-
"@locusai/sdk": "^0.23.
|
|
30
|
+
"@locusai/locus-gateway": "^0.23.2",
|
|
31
|
+
"@locusai/locus-pm2": "^0.23.2",
|
|
32
|
+
"@locusai/sdk": "^0.23.2",
|
|
33
33
|
"grammy": "^1.35.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|