@locusai/locus-telegram 0.21.6 → 0.21.8

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/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
1
+ # @locusai/locus-telegram
2
+
3
+ ## 0.21.8
4
+
5
+ ### Patch Changes
6
+
7
+ - Continious learning improvements
8
+ Fix Telegram package installation issue
9
+ - Updated dependencies
10
+ - @locusai/sdk@0.21.8
11
+
12
+ ## 0.21.7
13
+
14
+ ### Patch Changes
15
+
16
+ - Initial telegram package
17
+ - Updated dependencies
18
+ - @locusai/sdk@0.21.7
package/dist/bot.js CHANGED
@@ -2,14 +2,14 @@
2
2
  * Bot instance — sets up grammy bot, registers middleware, commands,
3
3
  * and callback query handlers.
4
4
  */
5
- import { Bot } from "grammy";
6
5
  import { createLogger } from "@locusai/sdk";
6
+ import { Bot } from "grammy";
7
+ import { handleBranch, handleCheckout, handleCommit, handleDiff, handleGitStatus, handlePR, handleStage, handleStash, } from "./commands/git.js";
7
8
  import { handleLocusCommand } from "./commands/locus.js";
8
- import { handleGitStatus, handleStage, handleCommit, handleStash, handleBranch, handleCheckout, handleDiff, handlePR, } from "./commands/git.js";
9
9
  import { handleService } from "./commands/service.js";
10
+ import { formatInfo, formatSuccess } from "./ui/format.js";
10
11
  import { CB } from "./ui/keyboards.js";
11
12
  import { welcomeMessage } from "./ui/messages.js";
12
- import { formatSuccess, formatInfo } from "./ui/format.js";
13
13
  const logger = createLogger("telegram");
14
14
  // ─── Bot Factory ────────────────────────────────────────────────────────────
15
15
  export function createBot(config) {
@@ -5,7 +5,7 @@
5
5
  * PR creation uses `gh` CLI (same as the locus CLI does).
6
6
  */
7
7
  import { execSync } from "node:child_process";
8
- import { codeBlock, formatError, formatSuccess, bold, escapeHtml } from "../ui/format.js";
8
+ import { bold, codeBlock, escapeHtml, formatError, formatSuccess, } from "../ui/format.js";
9
9
  import { stashKeyboard } from "../ui/keyboards.js";
10
10
  import { gitBranchCreatedMessage, gitCheckoutMessage, gitCommitMessage, gitStashMessage, prCreatedMessage, } from "../ui/messages.js";
11
11
  // ─── Git Helper ─────────────────────────────────────────────────────────────
@@ -39,7 +39,9 @@ export async function handleGitStatus(ctx) {
39
39
  await ctx.reply(`${bold("Branch:")} ${escapeHtml(branch)}\n\n${codeBlock(status)}`, { parse_mode: "HTML" });
40
40
  }
41
41
  catch (error) {
42
- await ctx.reply(formatError("Failed to get git status", String(error)), { parse_mode: "HTML" });
42
+ await ctx.reply(formatError("Failed to get git status", String(error)), {
43
+ parse_mode: "HTML",
44
+ });
43
45
  }
44
46
  }
45
47
  /** /stage [files|.] — stage files for commit */
@@ -204,11 +206,15 @@ export async function handleDiff(ctx) {
204
206
  });
205
207
  }
206
208
  else {
207
- await ctx.reply(`${bold("Staged changes:")}\n\n${codeBlock(staged)}`, { parse_mode: "HTML" });
209
+ await ctx.reply(`${bold("Staged changes:")}\n\n${codeBlock(staged)}`, {
210
+ parse_mode: "HTML",
211
+ });
208
212
  }
209
213
  }
210
214
  else {
211
- await ctx.reply(`${bold("Unstaged changes:")}\n\n${codeBlock(diff)}`, { parse_mode: "HTML" });
215
+ await ctx.reply(`${bold("Unstaged changes:")}\n\n${codeBlock(diff)}`, {
216
+ parse_mode: "HTML",
217
+ });
212
218
  }
213
219
  }
214
220
  catch (error) {
@@ -6,9 +6,9 @@
6
6
  * in place at regular intervals.
7
7
  */
8
8
  import { invokeLocusStream } from "@locusai/sdk";
9
- import { formatCommandResult, formatStreamingMessage, } from "../ui/format.js";
9
+ import { formatCommandResult, formatStreamingMessage } from "../ui/format.js";
10
10
  import { planKeyboard, reviewKeyboard, runCompleteKeyboard, statusKeyboard, } from "../ui/keyboards.js";
11
- import { reviewStartedMessage, runStartedMessage, } from "../ui/messages.js";
11
+ import { reviewStartedMessage, runStartedMessage } from "../ui/messages.js";
12
12
  // ─── Command Map ────────────────────────────────────────────────────────────
13
13
  /** Maps Telegram command names to locus CLI arguments. */
14
14
  const COMMAND_MAP = {
@@ -114,7 +114,9 @@ async function handleStreamingCommand(ctx, displayCmd, fullArgs, command, args)
114
114
  // Send keyboard for post-command actions
115
115
  const keyboard = getPostCommandKeyboard(command, args, exitCode ?? 0);
116
116
  if (keyboard) {
117
- await ctx.reply(exitCode === 0 ? "What would you like to do next?" : "Command failed.", { reply_markup: keyboard });
117
+ await ctx.reply(exitCode === 0
118
+ ? "What would you like to do next?"
119
+ : "Command failed.", { reply_markup: keyboard });
118
120
  }
119
121
  resolve();
120
122
  });
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Service management commands — PM2 lifecycle control via Telegram.
3
3
  */
4
- import { formatError, formatSuccess, codeBlock } from "../ui/format.js";
5
- import { pm2Start, pm2Stop, pm2Restart, pm2Delete, pm2Status, pm2Logs, } from "../pm2.js";
6
- import { serviceStatusMessage, serviceNotRunningMessage } from "../ui/messages.js";
4
+ import { pm2Delete, pm2Logs, pm2Restart, pm2Start, pm2Status, pm2Stop, } from "../pm2.js";
5
+ import { codeBlock, formatError, formatSuccess } from "../ui/format.js";
6
+ import { serviceNotRunningMessage, serviceStatusMessage, } from "../ui/messages.js";
7
7
  /** /service <subcommand> — manage the bot process */
8
8
  export async function handleService(ctx, args) {
9
9
  const subcommand = args[0] ?? "status";
@@ -53,6 +53,8 @@ export async function handleService(ctx, args) {
53
53
  }
54
54
  }
55
55
  catch (error) {
56
- await ctx.reply(formatError("Service command failed", String(error)), { parse_mode: "HTML" });
56
+ await ctx.reply(formatError("Service command failed", String(error)), {
57
+ parse_mode: "HTML",
58
+ });
57
59
  }
58
60
  }
package/dist/config.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Environment configuration for the Telegram bot.
2
+ * Configuration for the Telegram bot, read from the Locus config system.
3
3
  *
4
- * Required env vars:
5
- * LOCUS_TELEGRAM_BOT_TOKEN — Telegram Bot API token from @BotFather
6
- * LOCUS_TELEGRAM_CHAT_ID — Comma-separated list of allowed chat IDs
4
+ * Users configure via:
5
+ * locus config packages.telegram.botToken "123456:ABC..."
6
+ * locus config packages.telegram.chatIds "12345678,87654321"
7
7
  */
8
8
  export interface TelegramConfig {
9
9
  botToken: string;
package/dist/config.js CHANGED
@@ -1,32 +1,54 @@
1
1
  /**
2
- * Environment configuration for the Telegram bot.
2
+ * Configuration for the Telegram bot, read from the Locus config system.
3
3
  *
4
- * Required env vars:
5
- * LOCUS_TELEGRAM_BOT_TOKEN — Telegram Bot API token from @BotFather
6
- * LOCUS_TELEGRAM_CHAT_ID — Comma-separated list of allowed chat IDs
4
+ * Users configure via:
5
+ * locus config packages.telegram.botToken "123456:ABC..."
6
+ * locus config packages.telegram.chatIds "12345678,87654321"
7
7
  */
8
+ import { readLocusConfig } from "@locusai/sdk";
8
9
  export function loadTelegramConfig() {
9
- const botToken = process.env.LOCUS_TELEGRAM_BOT_TOKEN;
10
- if (!botToken) {
11
- throw new Error("LOCUS_TELEGRAM_BOT_TOKEN is required. Get one from @BotFather on Telegram.");
10
+ const locusConfig = readLocusConfig();
11
+ const pkg = locusConfig.packages?.telegram;
12
+ const botToken = pkg?.botToken;
13
+ if (!botToken || typeof botToken !== "string") {
14
+ throw new Error('Telegram bot token not configured. Run:\n locus config packages.telegram.botToken "<your-token>"\n\nGet a token from @BotFather on Telegram.');
12
15
  }
13
- const chatIdRaw = process.env.LOCUS_TELEGRAM_CHAT_ID;
14
- if (!chatIdRaw) {
15
- throw new Error("LOCUS_TELEGRAM_CHAT_ID is required. Send /start to your bot and use the chat ID.");
16
+ const chatIdsRaw = pkg?.chatIds;
17
+ if (!chatIdsRaw) {
18
+ throw new Error('Telegram chat IDs not configured. Run:\n locus config packages.telegram.chatIds "12345678"\n\nSend /start to your bot, then use the chat ID from the Telegram API.');
16
19
  }
17
- const allowedChatIds = chatIdRaw
18
- .split(",")
19
- .map((id) => id.trim())
20
- .filter((id) => id.length > 0)
21
- .map((id) => {
22
- const parsed = Number.parseInt(id, 10);
23
- if (Number.isNaN(parsed)) {
24
- throw new Error(`Invalid chat ID: "${id}". Must be a number.`);
25
- }
26
- return parsed;
27
- });
20
+ const allowedChatIds = parseChatIds(chatIdsRaw);
28
21
  if (allowedChatIds.length === 0) {
29
- throw new Error("LOCUS_TELEGRAM_CHAT_ID must contain at least one chat ID.");
22
+ throw new Error("packages.telegram.chatIds must contain at least one chat ID.");
30
23
  }
31
24
  return { botToken, allowedChatIds };
32
25
  }
26
+ function parseChatIds(raw) {
27
+ // Support both array of numbers and comma-separated string
28
+ if (Array.isArray(raw)) {
29
+ return raw.map((id) => {
30
+ const parsed = Number(id);
31
+ if (Number.isNaN(parsed)) {
32
+ throw new Error(`Invalid chat ID: "${id}". Must be a number.`);
33
+ }
34
+ return parsed;
35
+ });
36
+ }
37
+ if (typeof raw === "string") {
38
+ return raw
39
+ .split(",")
40
+ .map((id) => id.trim())
41
+ .filter((id) => id.length > 0)
42
+ .map((id) => {
43
+ const parsed = Number.parseInt(id, 10);
44
+ if (Number.isNaN(parsed)) {
45
+ throw new Error(`Invalid chat ID: "${id}". Must be a number.`);
46
+ }
47
+ return parsed;
48
+ });
49
+ }
50
+ if (typeof raw === "number") {
51
+ return [raw];
52
+ }
53
+ throw new Error("Invalid chatIds format. Expected a number, array of numbers, or comma-separated string.");
54
+ }
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@
16
16
  import { createLogger } from "@locusai/sdk";
17
17
  import { createBot } from "./bot.js";
18
18
  import { loadTelegramConfig } from "./config.js";
19
- import { pm2Start, pm2Stop, pm2Restart, pm2Delete, pm2Status, pm2Logs, } from "./pm2.js";
19
+ import { pm2Delete, pm2Logs, pm2Restart, pm2Start, pm2Status, pm2Stop, } from "./pm2.js";
20
20
  const logger = createLogger("telegram");
21
21
  export async function main(args) {
22
22
  const command = args[0] ?? "help";
@@ -126,19 +126,16 @@ function printHelp() {
126
126
  bot Run the bot directly (foreground)
127
127
  help Show this help message
128
128
 
129
- Environment Variables:
130
- LOCUS_TELEGRAM_BOT_TOKEN Telegram Bot API token (from @BotFather)
131
- LOCUS_TELEGRAM_CHAT_ID Comma-separated list of allowed chat IDs
129
+ Configuration (via locus config):
130
+ packages.telegram.botToken Telegram Bot API token (from @BotFather)
131
+ packages.telegram.chatIds Comma-separated chat IDs or JSON array
132
132
 
133
- Examples:
134
- # Set up environment
135
- export LOCUS_TELEGRAM_BOT_TOKEN="123456:ABC-DEF..."
136
- export LOCUS_TELEGRAM_CHAT_ID="12345678"
137
-
138
- # Start in background
139
- locus pkg telegram start
133
+ Setup:
134
+ locus config packages.telegram.botToken "123456:ABC-DEF..."
135
+ locus config packages.telegram.chatIds "12345678"
140
136
 
141
- # Run in foreground (for development)
142
- locus pkg telegram bot
137
+ Examples:
138
+ locus pkg telegram start # Start in background
139
+ locus pkg telegram bot # Run in foreground (development)
143
140
  `);
144
141
  }
package/dist/pm2.js CHANGED
@@ -4,8 +4,8 @@
4
4
  * Uses pm2 package API to start/stop/restart/status/logs the bot.
5
5
  */
6
6
  import { execSync } from "node:child_process";
7
- import { fileURLToPath } from "node:url";
8
7
  import { dirname, join } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
9
  const PROCESS_NAME = "locus-telegram";
10
10
  function getPm2Bin() {
11
11
  // Try local node_modules first, then global
@@ -45,11 +45,6 @@ function getBotScriptPath() {
45
45
  export function pm2Start() {
46
46
  const script = getBotScriptPath();
47
47
  const pm2 = getPm2Bin();
48
- // Pass env vars through to the PM2 process
49
- const envArgs = [];
50
- if (process.env.LOCUS_TELEGRAM_BOT_TOKEN) {
51
- envArgs.push("--env", `LOCUS_TELEGRAM_BOT_TOKEN=${process.env.LOCUS_TELEGRAM_BOT_TOKEN}`);
52
- }
53
48
  try {
54
49
  // Check if already running
55
50
  const list = pm2Exec("jlist");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@locusai/locus-telegram",
3
- "version": "0.21.6",
3
+ "version": "0.21.8",
4
4
  "description": "Remote-control Locus via Telegram with full CLI mapping, git operations, and PM2 management",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,7 +21,7 @@
21
21
  "format": "biome format --write ."
22
22
  },
23
23
  "dependencies": {
24
- "@locusai/sdk": "0.21.6",
24
+ "@locusai/sdk": "^0.21.8",
25
25
  "grammy": "^1.35.0",
26
26
  "pm2": "^6.0.5"
27
27
  },
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env node
2
- import { main } from "../dist/index.js";
3
-
4
- main(process.argv.slice(2)).catch((err) => {
5
- console.error(err.message || err);
6
- process.exit(1);
7
- });