@locusai/telegram 0.13.3 → 0.14.0

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.
Files changed (2) hide show
  1. package/bin/telegram.js +266 -8
  2. package/package.json +3 -3
package/bin/telegram.js CHANGED
@@ -22719,7 +22719,7 @@ var init_constants = __esm(() => {
22719
22719
  });
22720
22720
 
22721
22721
  // ../shared/src/enums.ts
22722
- var UserRole, MembershipRole, TaskStatus, TaskPriority, AssigneeRole, SprintStatus, EventType;
22722
+ var UserRole, MembershipRole, TaskStatus, TaskPriority, AssigneeRole, SprintStatus, InstanceStatus, AwsRegion, EventType;
22723
22723
  var init_enums = __esm(() => {
22724
22724
  ((UserRole2) => {
22725
22725
  UserRole2["USER"] = "USER";
@@ -22756,6 +22756,16 @@ var init_enums = __esm(() => {
22756
22756
  SprintStatus2["ACTIVE"] = "ACTIVE";
22757
22757
  SprintStatus2["COMPLETED"] = "COMPLETED";
22758
22758
  })(SprintStatus ||= {});
22759
+ ((InstanceStatus2) => {
22760
+ InstanceStatus2["PROVISIONING"] = "PROVISIONING";
22761
+ InstanceStatus2["RUNNING"] = "RUNNING";
22762
+ InstanceStatus2["STOPPED"] = "STOPPED";
22763
+ InstanceStatus2["TERMINATED"] = "TERMINATED";
22764
+ InstanceStatus2["ERROR"] = "ERROR";
22765
+ })(InstanceStatus ||= {});
22766
+ ((AwsRegion2) => {
22767
+ AwsRegion2["US_EAST_1"] = "us-east-1";
22768
+ })(AwsRegion ||= {});
22759
22769
  ((EventType2) => {
22760
22770
  EventType2["TASK_CREATED"] = "TASK_CREATED";
22761
22771
  EventType2["TASK_UPDATED"] = "TASK_UPDATED";
@@ -23103,6 +23113,76 @@ var init_auth = __esm(() => {
23103
23113
  });
23104
23114
  });
23105
23115
 
23116
+ // ../shared/src/models/aws-instance.ts
23117
+ var InstanceAction, AwsCredentialsSchema, IntegrationSchema, AwsInstanceSchema, CreateAwsInstanceSchema, UpdateAwsInstanceSchema, SaveAwsCredentialsSchema, ProvisionAwsInstanceSchema, InstanceActionBodySchema, InstanceIdParamSchema, CIDR_REGEX, UpdateSecurityRulesSchema;
23118
+ var init_aws_instance = __esm(() => {
23119
+ init_zod();
23120
+ init_common();
23121
+ init_enums();
23122
+ ((InstanceAction2) => {
23123
+ InstanceAction2["START"] = "START";
23124
+ InstanceAction2["STOP"] = "STOP";
23125
+ InstanceAction2["TERMINATE"] = "TERMINATE";
23126
+ })(InstanceAction ||= {});
23127
+ AwsCredentialsSchema = exports_external.object({
23128
+ accessKeyId: exports_external.string().min(1),
23129
+ secretAccessKey: exports_external.string().min(1),
23130
+ region: exports_external.enum(AwsRegion).default("us-east-1" /* US_EAST_1 */)
23131
+ });
23132
+ IntegrationSchema = exports_external.object({
23133
+ name: exports_external.string(),
23134
+ config: exports_external.record(exports_external.string(), exports_external.string())
23135
+ });
23136
+ AwsInstanceSchema = BaseEntitySchema.extend({
23137
+ workspaceId: exports_external.uuid(),
23138
+ instanceId: exports_external.string(),
23139
+ status: exports_external.enum(InstanceStatus),
23140
+ instanceType: exports_external.enum(["t3.micro", "t3.small", "t3.medium"]),
23141
+ region: exports_external.enum(AwsRegion).default("us-east-1" /* US_EAST_1 */),
23142
+ publicIp: exports_external.string().nullable().optional(),
23143
+ launchTime: exports_external.union([exports_external.date(), exports_external.number()]).nullable().optional(),
23144
+ repoUrl: exports_external.string().nullable().optional(),
23145
+ integrations: exports_external.array(IntegrationSchema).default([])
23146
+ });
23147
+ CreateAwsInstanceSchema = exports_external.object({
23148
+ workspaceId: exports_external.uuid(),
23149
+ instanceType: exports_external.enum(["t3.micro", "t3.small", "t3.medium"]).default("t3.micro"),
23150
+ region: exports_external.enum(AwsRegion).default("us-east-1" /* US_EAST_1 */),
23151
+ repoUrl: exports_external.string().optional(),
23152
+ integrations: exports_external.array(IntegrationSchema).optional().default([])
23153
+ });
23154
+ UpdateAwsInstanceSchema = exports_external.object({
23155
+ status: exports_external.enum(InstanceStatus).optional(),
23156
+ instanceType: exports_external.enum(["t3.micro", "t3.small", "t3.medium"]).optional(),
23157
+ publicIp: exports_external.string().nullable().optional(),
23158
+ launchTime: exports_external.union([exports_external.date(), exports_external.number()]).nullable().optional(),
23159
+ repoUrl: exports_external.string().nullable().optional(),
23160
+ integrations: exports_external.array(IntegrationSchema).optional()
23161
+ });
23162
+ SaveAwsCredentialsSchema = exports_external.object({
23163
+ accessKeyId: exports_external.string().min(16),
23164
+ secretAccessKey: exports_external.string().min(1),
23165
+ region: exports_external.string().default("us-east-1")
23166
+ });
23167
+ ProvisionAwsInstanceSchema = exports_external.object({
23168
+ repoUrl: exports_external.string().min(1),
23169
+ githubToken: exports_external.string().min(1),
23170
+ instanceType: exports_external.enum(["t3.micro", "t3.small", "t3.medium"]).default("t3.small"),
23171
+ integrations: exports_external.array(IntegrationSchema).optional().default([])
23172
+ });
23173
+ InstanceActionBodySchema = exports_external.object({
23174
+ action: exports_external.nativeEnum(InstanceAction)
23175
+ });
23176
+ InstanceIdParamSchema = exports_external.object({
23177
+ workspaceId: exports_external.string().uuid("Invalid Workspace ID"),
23178
+ instanceId: exports_external.string().uuid("Invalid Instance ID")
23179
+ });
23180
+ CIDR_REGEX = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}$/;
23181
+ UpdateSecurityRulesSchema = exports_external.object({
23182
+ allowedIps: exports_external.array(exports_external.string().regex(CIDR_REGEX, "Invalid CIDR format (e.g. 1.2.3.4/32)"))
23183
+ });
23184
+ });
23185
+
23106
23186
  // ../shared/src/models/ci.ts
23107
23187
  var RecordCiSchema;
23108
23188
  var init_ci = __esm(() => {
@@ -23490,6 +23570,7 @@ var init_models = __esm(() => {
23490
23570
  init_activity();
23491
23571
  init_agent();
23492
23572
  init_auth();
23573
+ init_aws_instance();
23493
23574
  init_ci();
23494
23575
  init_doc();
23495
23576
  init_doc_group();
@@ -38388,6 +38469,49 @@ var init_docs = __esm(() => {
38388
38469
  };
38389
38470
  });
38390
38471
 
38472
+ // ../sdk/src/modules/instances.ts
38473
+ var InstancesModule;
38474
+ var init_instances = __esm(() => {
38475
+ InstancesModule = class InstancesModule extends BaseModule {
38476
+ async list(workspaceId) {
38477
+ const { data } = await this.api.get(`/workspaces/${workspaceId}/aws-instances`);
38478
+ return data.instances;
38479
+ }
38480
+ async get(workspaceId, instanceId) {
38481
+ const { data } = await this.api.get(`/workspaces/${workspaceId}/aws-instances/${instanceId}`);
38482
+ return data.instance;
38483
+ }
38484
+ async provision(workspaceId, body) {
38485
+ const { data } = await this.api.post(`/workspaces/${workspaceId}/aws-instances`, body);
38486
+ return data.instance;
38487
+ }
38488
+ async performAction(workspaceId, instanceId, action) {
38489
+ const { data } = await this.api.post(`/workspaces/${workspaceId}/aws-instances/${instanceId}/actions`, { action });
38490
+ return data.instance;
38491
+ }
38492
+ async sync(workspaceId, instanceId) {
38493
+ const { data } = await this.api.post(`/workspaces/${workspaceId}/aws-instances/${instanceId}/sync`);
38494
+ return data.instance;
38495
+ }
38496
+ async checkUpdates(workspaceId, instanceId) {
38497
+ const { data } = await this.api.get(`/workspaces/${workspaceId}/aws-instances/${instanceId}/updates`);
38498
+ return data.update;
38499
+ }
38500
+ async applyUpdate(workspaceId, instanceId) {
38501
+ const { data } = await this.api.post(`/workspaces/${workspaceId}/aws-instances/${instanceId}/updates`);
38502
+ return data.update;
38503
+ }
38504
+ async getSecurity(workspaceId, instanceId) {
38505
+ const { data } = await this.api.get(`/workspaces/${workspaceId}/aws-instances/${instanceId}/security`);
38506
+ return data.rules;
38507
+ }
38508
+ async updateSecurity(workspaceId, instanceId, body) {
38509
+ const { data } = await this.api.put(`/workspaces/${workspaceId}/aws-instances/${instanceId}/security`, body);
38510
+ return data.rules;
38511
+ }
38512
+ };
38513
+ });
38514
+
38391
38515
  // ../sdk/src/modules/invitations.ts
38392
38516
  var InvitationsModule;
38393
38517
  var init_invitations = __esm(() => {
@@ -38620,6 +38744,17 @@ var init_workspaces = __esm(() => {
38620
38744
  async deleteApiKey(workspaceId, keyId) {
38621
38745
  await this.api.delete(`/workspaces/${workspaceId}/api-keys/${keyId}`);
38622
38746
  }
38747
+ async getAwsCredentials(workspaceId) {
38748
+ const { data } = await this.api.get(`/workspaces/${workspaceId}/aws-credentials`);
38749
+ return data.credential;
38750
+ }
38751
+ async saveAwsCredentials(workspaceId, body) {
38752
+ const { data } = await this.api.put(`/workspaces/${workspaceId}/aws-credentials`, body);
38753
+ return data.credential;
38754
+ }
38755
+ async deleteAwsCredentials(workspaceId) {
38756
+ await this.api.delete(`/workspaces/${workspaceId}/aws-credentials`);
38757
+ }
38623
38758
  };
38624
38759
  });
38625
38760
 
@@ -38668,6 +38803,7 @@ class LocusClient {
38668
38803
  invitations;
38669
38804
  docs;
38670
38805
  ci;
38806
+ instances;
38671
38807
  constructor(config2) {
38672
38808
  this.emitter = new LocusEmitter;
38673
38809
  this.api = axios_default.create({
@@ -38687,6 +38823,7 @@ class LocusClient {
38687
38823
  this.invitations = new InvitationsModule(this.api, this.emitter);
38688
38824
  this.docs = new DocsModule(this.api, this.emitter);
38689
38825
  this.ci = new CiModule(this.api, this.emitter);
38826
+ this.instances = new InstancesModule(this.api, this.emitter);
38690
38827
  if (config2.retryOptions) {
38691
38828
  this.setupRetryInterceptor(config2.retryOptions);
38692
38829
  }
@@ -38752,6 +38889,7 @@ var init_src2 = __esm(() => {
38752
38889
  init_auth2();
38753
38890
  init_ci2();
38754
38891
  init_docs();
38892
+ init_instances();
38755
38893
  init_invitations();
38756
38894
  init_organizations();
38757
38895
  init_sprints();
@@ -38762,6 +38900,7 @@ var init_src2 = __esm(() => {
38762
38900
  init_auth2();
38763
38901
  init_ci2();
38764
38902
  init_docs();
38903
+ init_instances();
38765
38904
  init_invitations();
38766
38905
  init_organizations();
38767
38906
  init_sprints();
@@ -44423,6 +44562,7 @@ var PLAN_TIMEOUT = 3600000;
44423
44562
  var STREAMING_DEFAULT_TIMEOUT = 3600000;
44424
44563
  var GIT_TIMEOUT = 60000;
44425
44564
  var DEV_TIMEOUT = 600000;
44565
+ var UPGRADE_TIMEOUT = 300000;
44426
44566
 
44427
44567
  // src/commands/dev.ts
44428
44568
  var USAGE2 = `<b>Usage:</b> /dev &lt;command&gt;
@@ -44601,6 +44741,7 @@ var HELP_TEXT = `<b>Locus Bot — Command Center</b>
44601
44741
  /config set &lt;key&gt; &lt;value&gt; — Update a setting
44602
44742
  /config unset &lt;key&gt; — Remove a setting
44603
44743
  /model [name] — View or switch AI model
44744
+ /upgrade — Upgrade Locus CLI &amp; restart bot
44604
44745
  /help — Show this message`;
44605
44746
  async function startCommand(ctx) {
44606
44747
  console.log("[start] User started bot");
@@ -45266,6 +45407,121 @@ async function approveTaskCommand(ctx, config2) {
45266
45407
  await ctx.reply(formatError2(`Failed to approve task: ${err instanceof Error ? err.message : String(err)}`), { parse_mode: "HTML" });
45267
45408
  }
45268
45409
  }
45410
+ // src/commands/upgrade.ts
45411
+ import { spawn as spawn5 } from "node:child_process";
45412
+ import { homedir as homedir3 } from "node:os";
45413
+ import { join as join10 } from "node:path";
45414
+ function runCommand2(cmd, args, timeout) {
45415
+ return new Promise((resolve2) => {
45416
+ const proc = spawn5(cmd, args, {
45417
+ stdio: ["pipe", "pipe", "pipe"]
45418
+ });
45419
+ let stdout = "";
45420
+ let stderr = "";
45421
+ let killed = false;
45422
+ proc.stdout?.on("data", (data) => {
45423
+ stdout += data.toString();
45424
+ });
45425
+ proc.stderr?.on("data", (data) => {
45426
+ stderr += data.toString();
45427
+ });
45428
+ const timer = setTimeout(() => {
45429
+ killed = true;
45430
+ proc.kill("SIGTERM");
45431
+ }, timeout);
45432
+ proc.on("close", (exitCode) => {
45433
+ clearTimeout(timer);
45434
+ resolve2({ stdout, stderr, exitCode, killed });
45435
+ });
45436
+ proc.on("error", (err) => {
45437
+ clearTimeout(timer);
45438
+ resolve2({
45439
+ stdout,
45440
+ stderr: stderr || err.message,
45441
+ exitCode: 1,
45442
+ killed: false
45443
+ });
45444
+ });
45445
+ });
45446
+ }
45447
+ function getRestartInfo() {
45448
+ const platform = process.platform;
45449
+ if (platform === "linux") {
45450
+ return {
45451
+ label: "systemd (Linux)",
45452
+ commands: [
45453
+ { cmd: "sudo", args: ["systemctl", "restart", "locus-telegram"] }
45454
+ ]
45455
+ };
45456
+ }
45457
+ if (platform === "darwin") {
45458
+ const plistPath = join10(homedir3(), "Library/LaunchAgents/com.locus.telegram.plist");
45459
+ return {
45460
+ label: "launchctl (macOS)",
45461
+ commands: [
45462
+ { cmd: "launchctl", args: ["unload", plistPath] },
45463
+ { cmd: "launchctl", args: ["load", plistPath] }
45464
+ ]
45465
+ };
45466
+ }
45467
+ return null;
45468
+ }
45469
+ async function upgradeCommand(ctx) {
45470
+ console.log("[upgrade] Starting upgrade");
45471
+ const restartInfo = getRestartInfo();
45472
+ if (!restartInfo) {
45473
+ await ctx.reply(formatError2(`Unsupported platform: ${process.platform}. Upgrade is only supported on Linux (systemd) and macOS (launchctl).`), { parse_mode: "HTML" });
45474
+ return;
45475
+ }
45476
+ await ctx.reply(formatInfo("Running <code>sudo locus upgrade</code>..."), {
45477
+ parse_mode: "HTML"
45478
+ });
45479
+ const upgradeResult = await runCommand2("sudo", ["locus", "upgrade"], UPGRADE_TIMEOUT);
45480
+ const output = stripAnsi((upgradeResult.stdout + upgradeResult.stderr).trim());
45481
+ if (upgradeResult.killed) {
45482
+ await ctx.reply(formatError2("Upgrade command timed out and was killed."), {
45483
+ parse_mode: "HTML"
45484
+ });
45485
+ return;
45486
+ }
45487
+ if (upgradeResult.exitCode !== 0) {
45488
+ const truncated = truncateOutput(output, 3000);
45489
+ await ctx.reply(`${formatError2("Upgrade failed:")}
45490
+
45491
+ <pre>${escapeHtml(truncated)}</pre>`, { parse_mode: "HTML" });
45492
+ return;
45493
+ }
45494
+ if (output) {
45495
+ const truncated = truncateOutput(output, 3000);
45496
+ await ctx.reply(`${formatSuccess("Upgrade completed:")}
45497
+
45498
+ <pre>${escapeHtml(truncated)}</pre>`, { parse_mode: "HTML" });
45499
+ } else {
45500
+ await ctx.reply(formatSuccess("Upgrade completed."), {
45501
+ parse_mode: "HTML"
45502
+ });
45503
+ }
45504
+ await ctx.reply(formatInfo(`Restarting locus-telegram via ${restartInfo.label}... The bot will be back shortly.`), { parse_mode: "HTML" });
45505
+ for (const { cmd, args } of restartInfo.commands) {
45506
+ console.log(`[upgrade] Running: ${cmd} ${args.join(" ")}`);
45507
+ const result = await runCommand2(cmd, args, 30000);
45508
+ if (result.exitCode !== 0) {
45509
+ const errOutput = stripAnsi((result.stdout + result.stderr).trim());
45510
+ console.error(`[upgrade] Restart command failed: ${cmd} ${args.join(" ")} — ${errOutput}`);
45511
+ try {
45512
+ await ctx.reply(formatError2(`Restart failed: <code>${escapeHtml(`${cmd} ${args.join(" ")}`)}</code>
45513
+
45514
+ <pre>${escapeHtml(truncateOutput(errOutput, 2000))}</pre>`), { parse_mode: "HTML" });
45515
+ } catch {}
45516
+ return;
45517
+ }
45518
+ }
45519
+ try {
45520
+ await ctx.reply(formatSuccess("Bot restarted successfully."), {
45521
+ parse_mode: "HTML"
45522
+ });
45523
+ } catch {}
45524
+ }
45269
45525
  // src/commands/workspace.ts
45270
45526
  async function workspaceCommand(ctx, config2) {
45271
45527
  console.log("[workspace] Fetching workspace info");
@@ -45309,8 +45565,8 @@ async function workspaceCommand(ctx, config2) {
45309
45565
  }
45310
45566
  }
45311
45567
  // src/executor.ts
45312
- import { spawn as spawn5 } from "node:child_process";
45313
- import { join as join10 } from "node:path";
45568
+ import { spawn as spawn6 } from "node:child_process";
45569
+ import { join as join11 } from "node:path";
45314
45570
  function timestamp2() {
45315
45571
  return new Date().toLocaleTimeString("en-GB", { hour12: false });
45316
45572
  }
@@ -45326,7 +45582,7 @@ class CliExecutor {
45326
45582
  }
45327
45583
  resolveCommand(args) {
45328
45584
  if (this.config.testMode) {
45329
- const cliPath = join10(this.config.projectPath, "packages/cli/src/cli.ts");
45585
+ const cliPath = join11(this.config.projectPath, "packages/cli/src/cli.ts");
45330
45586
  return { cmd: "bun", cmdArgs: ["run", cliPath, ...args] };
45331
45587
  }
45332
45588
  return { cmd: "locus", cmdArgs: args };
@@ -45339,7 +45595,7 @@ class CliExecutor {
45339
45595
  const startTime = Date.now();
45340
45596
  log2(id, `Process started: ${fullCommand}`);
45341
45597
  return new Promise((resolve2) => {
45342
- const proc = spawn5(cmd, cmdArgs, {
45598
+ const proc = spawn6(cmd, cmdArgs, {
45343
45599
  cwd: this.config.projectPath,
45344
45600
  env: buildSpawnEnv(),
45345
45601
  stdio: ["pipe", "pipe", "pipe"]
@@ -45389,7 +45645,7 @@ class CliExecutor {
45389
45645
  const fullCommand = `${cmd} ${cmdArgs.join(" ")}`;
45390
45646
  const startTime = Date.now();
45391
45647
  log2(id, `Process started (streaming): ${fullCommand}`);
45392
- const proc = spawn5(cmd, cmdArgs, {
45648
+ const proc = spawn6(cmd, cmdArgs, {
45393
45649
  cwd: this.config.projectPath,
45394
45650
  env: buildSpawnEnv(),
45395
45651
  stdio: ["pipe", "pipe", "pipe"]
@@ -45535,6 +45791,7 @@ function createBot(config2) {
45535
45791
  bot.command("activity", (ctx) => activityCommand(ctx, config2));
45536
45792
  bot.command("workspace", (ctx) => workspaceCommand(ctx, config2));
45537
45793
  bot.command("status", (ctx) => statusCommand(ctx, executor));
45794
+ bot.command("upgrade", (ctx) => upgradeCommand(ctx));
45538
45795
  bot.on("text", (ctx) => {
45539
45796
  const text = ctx.message.text;
45540
45797
  const chatId = ctx.chat.id;
@@ -45581,6 +45838,7 @@ function createBot(config2) {
45581
45838
  { command: "config", description: "Show/update settings" },
45582
45839
  { command: "model", description: "View or switch AI model" },
45583
45840
  { command: "status", description: "Show running processes" },
45841
+ { command: "upgrade", description: "Upgrade Locus CLI & restart bot" },
45584
45842
  { command: "help", description: "Show all commands" }
45585
45843
  ]).catch((err) => console.error("Failed to set bot commands:", err));
45586
45844
  return bot;
@@ -45589,12 +45847,12 @@ function createBot(config2) {
45589
45847
  // src/config.ts
45590
45848
  var import_dotenv = __toESM(require_main(), 1);
45591
45849
  import { existsSync as existsSync9, readFileSync as readFileSync8 } from "node:fs";
45592
- import { join as join11 } from "node:path";
45850
+ import { join as join12 } from "node:path";
45593
45851
  import_dotenv.default.config();
45594
45852
  var SETTINGS_FILE2 = "settings.json";
45595
45853
  var CONFIG_DIR2 = ".locus";
45596
45854
  function loadSettings2(projectPath) {
45597
- const settingsPath = join11(projectPath, CONFIG_DIR2, SETTINGS_FILE2);
45855
+ const settingsPath = join12(projectPath, CONFIG_DIR2, SETTINGS_FILE2);
45598
45856
  if (!existsSync9(settingsPath)) {
45599
45857
  return null;
45600
45858
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@locusai/telegram",
3
- "version": "0.13.3",
3
+ "version": "0.14.0",
4
4
  "description": "Telegram bot for Locus - remote control your AI agents from Telegram",
5
5
  "type": "module",
6
6
  "bin": {
@@ -31,8 +31,8 @@
31
31
  "author": "",
32
32
  "license": "MIT",
33
33
  "dependencies": {
34
- "@locusai/sdk": "^0.13.3",
35
- "@locusai/shared": "^0.13.3",
34
+ "@locusai/sdk": "^0.14.0",
35
+ "@locusai/shared": "^0.14.0",
36
36
  "dotenv": "^16.4.7",
37
37
  "telegraf": "^4.16.3"
38
38
  },