@locusai/cli 0.15.5 → 0.16.1

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.js CHANGED
@@ -7055,7 +7055,6 @@ var init_resolve_bin = __esm(() => {
7055
7055
  join4(homedir(), ".local", "bin"),
7056
7056
  join4(homedir(), ".npm", "bin"),
7057
7057
  join4(homedir(), ".npm-global", "bin"),
7058
- join4(homedir(), ".npm-packages", "bin"),
7059
7058
  join4(homedir(), ".yarn", "bin"),
7060
7059
  join4(homedir(), ".bun", "bin"),
7061
7060
  join4(homedir(), "Library", "pnpm"),
@@ -23353,29 +23352,6 @@ var init_sprints = __esm(() => {
23353
23352
  };
23354
23353
  });
23355
23354
 
23356
- // ../sdk/src/modules/suggestions.ts
23357
- var SuggestionsModule;
23358
- var init_suggestions = __esm(() => {
23359
- SuggestionsModule = class SuggestionsModule extends BaseModule {
23360
- async create(workspaceId, data) {
23361
- const { data: res } = await this.api.post(`/workspaces/${workspaceId}/suggestions`, data);
23362
- return res.suggestion;
23363
- }
23364
- async list(workspaceId, params) {
23365
- const { data } = await this.api.get(`/workspaces/${workspaceId}/suggestions`, { params });
23366
- return data.suggestions;
23367
- }
23368
- async get(workspaceId, id) {
23369
- const { data } = await this.api.get(`/workspaces/${workspaceId}/suggestions/${id}`);
23370
- return data.suggestion;
23371
- }
23372
- async updateStatus(workspaceId, id, status) {
23373
- const { data } = await this.api.patch(`/workspaces/${workspaceId}/suggestions/${id}/status`, status);
23374
- return data.suggestion;
23375
- }
23376
- };
23377
- });
23378
-
23379
23355
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/core.js
23380
23356
  function $constructor(name, initializer, params) {
23381
23357
  function init(inst, def) {
@@ -37691,75 +37667,6 @@ var init_auth2 = __esm(() => {
37691
37667
  });
37692
37668
  });
37693
37669
 
37694
- // ../shared/src/models/autonomy.ts
37695
- var RiskLevel, ChangeCategory, AutonomyRuleSchema, DEFAULT_AUTONOMY_RULES;
37696
- var init_autonomy = __esm(() => {
37697
- init_zod();
37698
- ((RiskLevel2) => {
37699
- RiskLevel2["LOW"] = "LOW";
37700
- RiskLevel2["HIGH"] = "HIGH";
37701
- })(RiskLevel ||= {});
37702
- ((ChangeCategory2) => {
37703
- ChangeCategory2["FIX"] = "FIX";
37704
- ChangeCategory2["REFACTOR"] = "REFACTOR";
37705
- ChangeCategory2["STYLE"] = "STYLE";
37706
- ChangeCategory2["DEPENDENCY"] = "DEPENDENCY";
37707
- ChangeCategory2["FEATURE"] = "FEATURE";
37708
- ChangeCategory2["ARCHITECTURE"] = "ARCHITECTURE";
37709
- ChangeCategory2["DATABASE"] = "DATABASE";
37710
- ChangeCategory2["AUTH"] = "AUTH";
37711
- ChangeCategory2["API"] = "API";
37712
- })(ChangeCategory ||= {});
37713
- AutonomyRuleSchema = exports_external.object({
37714
- category: exports_external.enum(ChangeCategory),
37715
- riskLevel: exports_external.enum(RiskLevel),
37716
- autoExecute: exports_external.boolean()
37717
- });
37718
- DEFAULT_AUTONOMY_RULES = [
37719
- { category: "FIX" /* FIX */, riskLevel: "LOW" /* LOW */, autoExecute: true },
37720
- {
37721
- category: "REFACTOR" /* REFACTOR */,
37722
- riskLevel: "LOW" /* LOW */,
37723
- autoExecute: true
37724
- },
37725
- {
37726
- category: "STYLE" /* STYLE */,
37727
- riskLevel: "LOW" /* LOW */,
37728
- autoExecute: true
37729
- },
37730
- {
37731
- category: "DEPENDENCY" /* DEPENDENCY */,
37732
- riskLevel: "LOW" /* LOW */,
37733
- autoExecute: true
37734
- },
37735
- {
37736
- category: "FEATURE" /* FEATURE */,
37737
- riskLevel: "HIGH" /* HIGH */,
37738
- autoExecute: false
37739
- },
37740
- {
37741
- category: "ARCHITECTURE" /* ARCHITECTURE */,
37742
- riskLevel: "HIGH" /* HIGH */,
37743
- autoExecute: false
37744
- },
37745
- {
37746
- category: "DATABASE" /* DATABASE */,
37747
- riskLevel: "HIGH" /* HIGH */,
37748
- autoExecute: false
37749
- },
37750
- {
37751
- category: "AUTH" /* AUTH */,
37752
- riskLevel: "HIGH" /* HIGH */,
37753
- autoExecute: false
37754
- },
37755
- {
37756
- category: "API" /* API */,
37757
- riskLevel: "HIGH" /* HIGH */,
37758
- autoExecute: false
37759
- }
37760
- ];
37761
- });
37762
-
37763
37670
  // ../shared/src/models/aws-instance.ts
37764
37671
  var InstanceAction, AwsCredentialsSchema, IntegrationSchema, AwsInstanceSchema, CreateAwsInstanceSchema, UpdateAwsInstanceSchema, SaveAwsCredentialsSchema, ProvisionAwsInstanceSchema, InstanceActionBodySchema, InstanceIdParamSchema, CIDR_REGEX, UpdateSecurityRulesSchema;
37765
37672
  var init_aws_instance = __esm(() => {
@@ -38078,49 +37985,6 @@ var init_sprint = __esm(() => {
38078
37985
  });
38079
37986
  });
38080
37987
 
38081
- // ../shared/src/models/suggestion.ts
38082
- var SuggestionStatus, SuggestionType, SuggestionSchema, CreateSuggestionSchema, UpdateSuggestionStatusSchema;
38083
- var init_suggestion = __esm(() => {
38084
- init_zod();
38085
- ((SuggestionStatus2) => {
38086
- SuggestionStatus2["NEW"] = "NEW";
38087
- SuggestionStatus2["NOTIFIED"] = "NOTIFIED";
38088
- SuggestionStatus2["ACTED_ON"] = "ACTED_ON";
38089
- SuggestionStatus2["SKIPPED"] = "SKIPPED";
38090
- SuggestionStatus2["EXPIRED"] = "EXPIRED";
38091
- })(SuggestionStatus ||= {});
38092
- ((SuggestionType2) => {
38093
- SuggestionType2["CODE_FIX"] = "CODE_FIX";
38094
- SuggestionType2["DEPENDENCY_UPDATE"] = "DEPENDENCY_UPDATE";
38095
- SuggestionType2["NEXT_STEP"] = "NEXT_STEP";
38096
- SuggestionType2["REFACTOR"] = "REFACTOR";
38097
- SuggestionType2["TEST_FIX"] = "TEST_FIX";
38098
- })(SuggestionType ||= {});
38099
- SuggestionSchema = exports_external.object({
38100
- id: exports_external.string(),
38101
- type: exports_external.enum(SuggestionType),
38102
- status: exports_external.enum(SuggestionStatus),
38103
- title: exports_external.string(),
38104
- description: exports_external.string(),
38105
- jobRunId: exports_external.string().optional(),
38106
- workspaceId: exports_external.string(),
38107
- createdAt: exports_external.string(),
38108
- expiresAt: exports_external.string(),
38109
- metadata: exports_external.record(exports_external.string(), exports_external.any()).optional()
38110
- });
38111
- CreateSuggestionSchema = exports_external.object({
38112
- type: exports_external.enum(SuggestionType),
38113
- title: exports_external.string().min(1, "Title is required"),
38114
- description: exports_external.string().min(1, "Description is required"),
38115
- jobRunId: exports_external.string().uuid().optional(),
38116
- metadata: exports_external.record(exports_external.string(), exports_external.any()).optional(),
38117
- expiresAt: exports_external.string().optional()
38118
- });
38119
- UpdateSuggestionStatusSchema = exports_external.object({
38120
- status: exports_external.enum(SuggestionStatus)
38121
- });
38122
- });
38123
-
38124
37988
  // ../shared/src/models/task.ts
38125
37989
  var AcceptanceItemSchema, TaskSchema, CreateTaskSchema, UpdateTaskSchema, AddCommentSchema, DispatchTaskSchema, TaskIdParamSchema, TaskQuerySchema, TaskResponseSchema, TasksResponseSchema;
38126
37990
  var init_task = __esm(() => {
@@ -38260,7 +38124,6 @@ var init_models = __esm(() => {
38260
38124
  init_activity();
38261
38125
  init_agent();
38262
38126
  init_auth2();
38263
- init_autonomy();
38264
38127
  init_aws_instance();
38265
38128
  init_ci2();
38266
38129
  init_doc();
@@ -38268,7 +38131,6 @@ var init_models = __esm(() => {
38268
38131
  init_invitation();
38269
38132
  init_organization();
38270
38133
  init_sprint();
38271
- init_suggestion();
38272
38134
  init_task();
38273
38135
  init_user();
38274
38136
  init_workspace();
@@ -38991,7 +38853,6 @@ class LocusClient {
38991
38853
  docs;
38992
38854
  ci;
38993
38855
  instances;
38994
- suggestions;
38995
38856
  constructor(config2) {
38996
38857
  this.emitter = new LocusEmitter;
38997
38858
  this.api = axios_default.create({
@@ -39012,7 +38873,6 @@ class LocusClient {
39012
38873
  this.docs = new DocsModule(this.api, this.emitter);
39013
38874
  this.ci = new CiModule(this.api, this.emitter);
39014
38875
  this.instances = new InstancesModule(this.api, this.emitter);
39015
- this.suggestions = new SuggestionsModule(this.api, this.emitter);
39016
38876
  if (config2.retryOptions) {
39017
38877
  this.setupRetryInterceptor(config2.retryOptions);
39018
38878
  }
@@ -39082,7 +38942,6 @@ var init_src2 = __esm(() => {
39082
38942
  init_invitations();
39083
38943
  init_organizations();
39084
38944
  init_sprints();
39085
- init_suggestions();
39086
38945
  init_tasks();
39087
38946
  init_workspaces();
39088
38947
  init_discussion_types();
@@ -39094,7 +38953,6 @@ var init_src2 = __esm(() => {
39094
38953
  init_invitations();
39095
38954
  init_organizations();
39096
38955
  init_sprints();
39097
- init_suggestions();
39098
38956
  init_tasks();
39099
38957
  init_workspaces();
39100
38958
  });
@@ -42037,22 +41895,6 @@ var init_planning = __esm(() => {
42037
41895
  init_sprint_plan();
42038
41896
  });
42039
41897
 
42040
- // ../sdk/src/proposals/context-gatherer.ts
42041
- var init_context_gatherer = () => {};
42042
-
42043
- // ../sdk/src/proposals/proposal-engine.ts
42044
- var init_proposal_engine = __esm(() => {
42045
- init_src();
42046
- init_factory();
42047
- init_context_gatherer();
42048
- });
42049
-
42050
- // ../sdk/src/proposals/index.ts
42051
- var init_proposals = __esm(() => {
42052
- init_context_gatherer();
42053
- init_proposal_engine();
42054
- });
42055
-
42056
41898
  // ../sdk/src/index-node.ts
42057
41899
  var init_index_node = __esm(() => {
42058
41900
  init_prompt_builder();
@@ -42067,7 +41909,6 @@ var init_index_node = __esm(() => {
42067
41909
  init_git();
42068
41910
  init_src2();
42069
41911
  init_planning();
42070
- init_proposals();
42071
41912
  });
42072
41913
 
42073
41914
  // src/utils/version.ts
@@ -42506,22 +42347,9 @@ class SettingsManager {
42506
42347
  exists() {
42507
42348
  return existsSync15(getSettingsPath(this.projectPath));
42508
42349
  }
42509
- getAutonomyRules() {
42510
- const settings = this.load();
42511
- const userRules = settings.autonomy?.rules ?? [];
42512
- if (userRules.length === 0) {
42513
- return DEFAULT_AUTONOMY_RULES;
42514
- }
42515
- const ruleMap = new Map(DEFAULT_AUTONOMY_RULES.map((r) => [r.category, r]));
42516
- for (const rule of userRules) {
42517
- ruleMap.set(rule.category, rule);
42518
- }
42519
- return Array.from(ruleMap.values());
42520
- }
42521
42350
  }
42522
42351
  var init_settings_manager = __esm(() => {
42523
42352
  init_index_node();
42524
- init_src();
42525
42353
  });
42526
42354
 
42527
42355
  // src/workspace-resolver.ts
@@ -43126,19 +42954,31 @@ class ProgressRenderer {
43126
42954
  toolDisplay = new ToolDisplay;
43127
42955
  toolDisplayShown = false;
43128
42956
  thinkingShown = false;
42957
+ animated;
43129
42958
  spinnerInterval = null;
43130
42959
  spinnerFrameIndex = 0;
43131
42960
  thinkingStartTime = null;
43132
42961
  isInTextBlock = false;
43133
42962
  textBuffer = "";
42963
+ constructor(options = {}) {
42964
+ this.animated = options.animated ?? false;
42965
+ }
43134
42966
  showThinkingStarted() {
43135
42967
  if (this.isThinking)
43136
42968
  return;
43137
42969
  this.isThinking = true;
43138
42970
  this.thinkingStartTime = Date.now();
43139
- if (!this.thinkingShown) {
43140
- this.thinkingShown = true;
43141
- this.startThinkingAnimation();
42971
+ if (this.animated) {
42972
+ if (!this.thinkingShown) {
42973
+ this.thinkingShown = true;
42974
+ this.startThinkingAnimation();
42975
+ }
42976
+ } else {
42977
+ if (!this.thinkingShown) {
42978
+ console.log(c.dim(`\uD83E\uDD14 Thinking...
42979
+ `));
42980
+ this.thinkingShown = true;
42981
+ }
43142
42982
  }
43143
42983
  }
43144
42984
  showThinkingStopped() {
@@ -43169,7 +43009,7 @@ class ProgressRenderer {
43169
43009
  clearInterval(this.spinnerInterval);
43170
43010
  this.spinnerInterval = null;
43171
43011
  }
43172
- if (this.thinkingShown && this.isThinking) {
43012
+ if (this.animated && this.thinkingShown && this.isThinking) {
43173
43013
  process.stdout.write(`${ANSI.MOVE_TO_START}${ANSI.CLEAR_LINE}
43174
43014
  `);
43175
43015
  }
@@ -43451,9 +43291,9 @@ var init_progress_renderer = __esm(() => {
43451
43291
  });
43452
43292
 
43453
43293
  // src/repl/image-detect.ts
43454
- import { copyFileSync, existsSync as existsSync20, mkdirSync as mkdirSync9 } from "node:fs";
43455
- import { homedir as homedir4, tmpdir as tmpdir2 } from "node:os";
43456
- import { basename as basename2, join as join20 } from "node:path";
43294
+ import { copyFileSync, existsSync as existsSync18, mkdirSync as mkdirSync8 } from "node:fs";
43295
+ import { homedir as homedir2, tmpdir as tmpdir2 } from "node:os";
43296
+ import { basename as basename2, join as join18 } from "node:path";
43457
43297
  function hasImageExtension(p) {
43458
43298
  const dot = p.lastIndexOf(".");
43459
43299
  if (dot === -1)
@@ -43466,16 +43306,16 @@ function resolvePath(raw) {
43466
43306
  p = p.slice(1, -1);
43467
43307
  }
43468
43308
  if (p.startsWith("~/")) {
43469
- p = homedir4() + p.slice(1);
43309
+ p = homedir2() + p.slice(1);
43470
43310
  }
43471
43311
  return p;
43472
43312
  }
43473
43313
  function copyToStable(srcPath) {
43474
43314
  try {
43475
- mkdirSync9(STABLE_IMAGE_DIR, { recursive: true });
43315
+ mkdirSync8(STABLE_IMAGE_DIR, { recursive: true });
43476
43316
  const ts = Date.now();
43477
43317
  const name = `${ts}-${basename2(srcPath)}`;
43478
- const destPath = join20(STABLE_IMAGE_DIR, name);
43318
+ const destPath = join18(STABLE_IMAGE_DIR, name);
43479
43319
  copyFileSync(srcPath, destPath);
43480
43320
  return destPath;
43481
43321
  } catch {
@@ -43495,7 +43335,7 @@ function detectImages(input) {
43495
43335
  let exists = false;
43496
43336
  let stablePath = normalized;
43497
43337
  try {
43498
- exists = existsSync20(normalized);
43338
+ exists = existsSync18(normalized);
43499
43339
  } catch {}
43500
43340
  if (exists) {
43501
43341
  const copied = copyToStable(normalized);
@@ -43569,7 +43409,7 @@ var init_image_detect = __esm(() => {
43569
43409
  ".tif",
43570
43410
  ".tiff"
43571
43411
  ]);
43572
- STABLE_IMAGE_DIR = join20(tmpdir2(), "locus-images");
43412
+ STABLE_IMAGE_DIR = join18(tmpdir2(), "locus-images");
43573
43413
  });
43574
43414
 
43575
43415
  // src/repl/input-handler.ts
@@ -44112,7 +43952,7 @@ class InteractiveSession {
44112
43952
  model: options.model
44113
43953
  });
44114
43954
  this.promptBuilder = new PromptBuilder(options.projectPath);
44115
- this.renderer = new ProgressRenderer;
43955
+ this.renderer = new ProgressRenderer({ animated: true });
44116
43956
  this.historyManager = new HistoryManager(options.projectPath);
44117
43957
  this.projectPath = options.projectPath;
44118
43958
  this.model = options.model;
@@ -44783,533 +44623,6 @@ async function configCommand(args) {
44783
44623
  showConfigHelp();
44784
44624
  }
44785
44625
  }
44786
- // src/commands/daemon.ts
44787
- init_index_node();
44788
- init_settings_manager();
44789
- init_utils3();
44790
- import { existsSync as existsSync19, mkdirSync as mkdirSync8, unlinkSync as unlinkSync6, writeFileSync as writeFileSync8 } from "node:fs";
44791
- import { homedir as homedir3 } from "node:os";
44792
- import { join as join19 } from "node:path";
44793
-
44794
- // src/utils/process.ts
44795
- import { spawn as spawn4 } from "node:child_process";
44796
- import { existsSync as existsSync18, readdirSync as readdirSync6, readFileSync as readFileSync15 } from "node:fs";
44797
- import { homedir as homedir2 } from "node:os";
44798
- import { dirname as dirname4, join as join18 } from "node:path";
44799
- function runShell(cmd, args) {
44800
- return new Promise((resolve2) => {
44801
- const proc = spawn4(cmd, args, { stdio: ["pipe", "pipe", "pipe"] });
44802
- let stdout = "";
44803
- let stderr = "";
44804
- proc.stdout?.on("data", (d) => {
44805
- stdout += d.toString();
44806
- });
44807
- proc.stderr?.on("data", (d) => {
44808
- stderr += d.toString();
44809
- });
44810
- proc.on("close", (exitCode) => resolve2({ exitCode, stdout, stderr }));
44811
- proc.on("error", (err) => resolve2({ exitCode: 1, stdout, stderr: err.message }));
44812
- });
44813
- }
44814
- async function findTelegramBinary() {
44815
- const result = await runShell("which", ["locus-telegram"]);
44816
- const p = result.stdout.trim();
44817
- return p?.startsWith?.("/") ? p : null;
44818
- }
44819
- async function findBinDir(binary) {
44820
- const result = await runShell("which", [binary]);
44821
- const p = result.stdout.trim();
44822
- if (p?.startsWith?.("/"))
44823
- return dirname4(p);
44824
- return null;
44825
- }
44826
- function resolveNvmBinDir() {
44827
- const nvmDir = process.env.NVM_DIR || join18(homedir2(), ".nvm");
44828
- const versionsDir = join18(nvmDir, "versions", "node");
44829
- if (!existsSync18(versionsDir))
44830
- return null;
44831
- let versions2;
44832
- try {
44833
- versions2 = readdirSync6(versionsDir).filter((d) => d.startsWith("v"));
44834
- } catch {
44835
- return null;
44836
- }
44837
- if (versions2.length === 0)
44838
- return null;
44839
- const currentNodeVersion = `v${process.versions.node}`;
44840
- const currentBin = join18(versionsDir, currentNodeVersion, "bin");
44841
- if (versions2.includes(currentNodeVersion) && existsSync18(currentBin)) {
44842
- return currentBin;
44843
- }
44844
- const aliasPath = join18(nvmDir, "alias", "default");
44845
- if (existsSync18(aliasPath)) {
44846
- try {
44847
- const alias = readFileSync15(aliasPath, "utf-8").trim();
44848
- const match = versions2.find((v) => v === `v${alias}` || v.startsWith(`v${alias}.`));
44849
- if (match) {
44850
- const bin2 = join18(versionsDir, match, "bin");
44851
- if (existsSync18(bin2))
44852
- return bin2;
44853
- }
44854
- } catch {}
44855
- }
44856
- const sorted = versions2.sort((a, b) => {
44857
- const pa = a.slice(1).split(".").map(Number);
44858
- const pb = b.slice(1).split(".").map(Number);
44859
- for (let i = 0;i < 3; i++) {
44860
- if ((pa[i] || 0) !== (pb[i] || 0))
44861
- return (pb[i] || 0) - (pa[i] || 0);
44862
- }
44863
- return 0;
44864
- });
44865
- const bin = join18(versionsDir, sorted[0], "bin");
44866
- return existsSync18(bin) ? bin : null;
44867
- }
44868
- async function buildServicePath() {
44869
- const home = homedir2();
44870
- const dirs = new Set;
44871
- dirs.add("/usr/local/bin");
44872
- dirs.add("/usr/bin");
44873
- dirs.add("/bin");
44874
- const candidates = [
44875
- join18(home, ".bun", "bin"),
44876
- join18(home, ".local", "bin"),
44877
- join18(home, ".npm", "bin"),
44878
- join18(home, ".npm-global", "bin"),
44879
- join18(home, ".yarn", "bin")
44880
- ];
44881
- for (const d of candidates) {
44882
- if (existsSync18(d))
44883
- dirs.add(d);
44884
- }
44885
- const nvmBin = resolveNvmBinDir();
44886
- if (nvmBin)
44887
- dirs.add(nvmBin);
44888
- const fnmCurrent = join18(home, ".fnm", "current", "bin");
44889
- if (existsSync18(fnmCurrent))
44890
- dirs.add(fnmCurrent);
44891
- for (const bin of ["claude", "codex"]) {
44892
- const dir = await findBinDir(bin);
44893
- if (dir)
44894
- dirs.add(dir);
44895
- }
44896
- return Array.from(dirs).join(":");
44897
- }
44898
- var SERVICE_NAME = "locus";
44899
- var SYSTEMD_UNIT_PATH = `/etc/systemd/system/${SERVICE_NAME}.service`;
44900
- var PLIST_LABEL = "com.locus.agent";
44901
- function getPlistPath() {
44902
- return join18(homedir2(), "Library/LaunchAgents", `${PLIST_LABEL}.plist`);
44903
- }
44904
- function getPlatform() {
44905
- if (process.platform === "linux")
44906
- return "linux";
44907
- if (process.platform === "darwin")
44908
- return "darwin";
44909
- return null;
44910
- }
44911
- async function killOrphanedProcesses() {
44912
- const result = await runShell("pgrep", ["-f", "locus-telegram"]);
44913
- const pids = result.stdout.trim().split(`
44914
- `).filter((p) => p.length > 0);
44915
- if (pids.length === 0)
44916
- return;
44917
- console.log(` Killing ${pids.length} orphaned locus-telegram process${pids.length > 1 ? "es" : ""}...`);
44918
- await runShell("pkill", ["-f", "locus-telegram"]);
44919
- await new Promise((resolve2) => setTimeout(resolve2, 2000));
44920
- const check2 = await runShell("pgrep", ["-f", "locus-telegram"]);
44921
- if (check2.stdout.trim().length > 0) {
44922
- await runShell("pkill", ["-9", "-f", "locus-telegram"]);
44923
- }
44924
- }
44925
- async function isDaemonRunning() {
44926
- const platform = getPlatform();
44927
- if (platform === "linux") {
44928
- const result = await runShell("systemctl", ["is-active", SERVICE_NAME]);
44929
- return result.stdout.trim() === "active";
44930
- }
44931
- if (platform === "darwin") {
44932
- const plistPath = getPlistPath();
44933
- if (!existsSync18(plistPath))
44934
- return false;
44935
- const result = await runShell("launchctl", ["list"]);
44936
- const match = result.stdout.split(`
44937
- `).find((l) => l.includes(PLIST_LABEL));
44938
- if (!match)
44939
- return false;
44940
- const pid = match.trim().split(/\s+/)[0];
44941
- return pid !== "-";
44942
- }
44943
- return false;
44944
- }
44945
- async function restartDaemonIfRunning() {
44946
- const platform = getPlatform();
44947
- if (!platform)
44948
- return false;
44949
- const running = await isDaemonRunning();
44950
- if (!running)
44951
- return false;
44952
- if (platform === "linux") {
44953
- const result = await runShell("systemctl", ["restart", SERVICE_NAME]);
44954
- return result.exitCode === 0;
44955
- }
44956
- if (platform === "darwin") {
44957
- const plistPath = getPlistPath();
44958
- await runShell("launchctl", ["unload", plistPath]);
44959
- const result = await runShell("launchctl", ["load", plistPath]);
44960
- return result.exitCode === 0;
44961
- }
44962
- return false;
44963
- }
44964
-
44965
- // src/commands/daemon.ts
44966
- function showDaemonHelp() {
44967
- console.log(`
44968
- ${c.header(" DAEMON ")}
44969
- ${c.primary("locus daemon")} ${c.dim("<subcommand>")}
44970
-
44971
- ${c.header(" SUBCOMMANDS ")}
44972
- ${c.success("start")} Install and start Locus as a background service
44973
- ${c.dim("Sets up systemd (Linux) or launchd (macOS)")}
44974
- ${c.success("stop")} Stop and remove the background service
44975
- ${c.success("restart")} Restart the background service
44976
- ${c.success("status")} Check if the service is running
44977
-
44978
- ${c.header(" EXAMPLES ")}
44979
- ${c.dim("$")} ${c.primary("locus daemon start")}
44980
- ${c.dim("$")} ${c.primary("locus daemon status")}
44981
- ${c.dim("$")} ${c.primary("locus daemon restart")}
44982
- ${c.dim("$")} ${c.primary("locus daemon stop")}
44983
- `);
44984
- }
44985
- async function resolveBinaries() {
44986
- const binaryPath = await findTelegramBinary();
44987
- if (!binaryPath) {
44988
- console.error(`
44989
- ${c.error("✖")} ${c.bold("Could not find locus-telegram binary.")}
44990
- ` + ` Install with: ${c.primary("npm install -g @locusai/telegram")}
44991
- `);
44992
- process.exit(1);
44993
- }
44994
- for (const bin of ["claude", "codex"]) {
44995
- if (!await findBinDir(bin)) {
44996
- console.warn(`
44997
- ${c.secondary("⚠")} ${c.bold(`Could not find '${bin}' CLI in PATH.`)}
44998
- ` + ` The service may need it to execute tasks.
44999
- `);
45000
- }
45001
- }
45002
- const servicePath = await buildServicePath();
45003
- return { binaryPath, servicePath };
45004
- }
45005
- function requirePlatform() {
45006
- const platform = getPlatform();
45007
- if (!platform) {
45008
- console.error(`
45009
- ${c.error("✖")} ${c.bold(`Unsupported platform: ${process.platform}`)}
45010
- ` + ` Daemon management is supported on Linux (systemd) and macOS (launchd).
45011
- `);
45012
- process.exit(1);
45013
- }
45014
- return platform;
45015
- }
45016
- function validateConfig(projectPath) {
45017
- const manager = new SettingsManager(projectPath);
45018
- const settings = manager.load();
45019
- if (!settings.telegram?.botToken || !settings.telegram?.chatId) {
45020
- console.error(`
45021
- ${c.error("✖")} ${c.bold("Telegram is not configured.")}
45022
- ` + ` Run ${c.primary("locus telegram setup")} first.
45023
- `);
45024
- process.exit(1);
45025
- }
45026
- if (!settings.apiKey) {
45027
- console.error(`
45028
- ${c.error("✖")} ${c.bold("API key is not configured.")}
45029
- ` + ` Run ${c.primary("locus config setup --api-key <key>")} first.
45030
- `);
45031
- process.exit(1);
45032
- }
45033
- }
45034
- function generateSystemdUnit(projectPath, user2, bins) {
45035
- return `[Unit]
45036
- Description=Locus AI Agent (Telegram bot + proposal scheduler)
45037
- After=network-online.target
45038
- Wants=network-online.target
45039
-
45040
- [Service]
45041
- Type=simple
45042
- User=${user2}
45043
- WorkingDirectory=${projectPath}
45044
- ExecStart=${bins.binaryPath}
45045
- Restart=on-failure
45046
- RestartSec=10
45047
- Environment=PATH=${bins.servicePath}
45048
- Environment=HOME=${homedir3()}
45049
-
45050
- [Install]
45051
- WantedBy=multi-user.target
45052
- `;
45053
- }
45054
- async function startSystemd(projectPath, bins) {
45055
- const user2 = process.env.USER || "root";
45056
- const unit = generateSystemdUnit(projectPath, user2, bins);
45057
- console.log(`
45058
- ${c.info("▶")} Writing systemd unit to ${c.dim(SYSTEMD_UNIT_PATH)}`);
45059
- writeFileSync8(SYSTEMD_UNIT_PATH, unit, "utf-8");
45060
- console.log(` ${c.info("▶")} Reloading systemd daemon...`);
45061
- await runShell("systemctl", ["daemon-reload"]);
45062
- console.log(` ${c.info("▶")} Enabling and starting ${SERVICE_NAME}...`);
45063
- await runShell("systemctl", ["enable", SERVICE_NAME]);
45064
- const result = await runShell("systemctl", ["start", SERVICE_NAME]);
45065
- if (result.exitCode !== 0) {
45066
- console.error(`
45067
- ${c.error("✖")} Failed to start service: ${result.stderr.trim()}`);
45068
- console.error(` ${c.dim("Check logs with:")} ${c.primary(`journalctl -u ${SERVICE_NAME} -f`)}`);
45069
- return;
45070
- }
45071
- console.log(`
45072
- ${c.success("✔")} ${c.bold("Locus daemon started!")}
45073
-
45074
- ${c.bold("Service:")} ${SERVICE_NAME}
45075
- ${c.bold("Unit file:")} ${SYSTEMD_UNIT_PATH}
45076
-
45077
- ${c.bold("Useful commands:")}
45078
- ${c.dim("$")} ${c.primary(`sudo systemctl status ${SERVICE_NAME}`)}
45079
- ${c.dim("$")} ${c.primary(`journalctl -u ${SERVICE_NAME} -f`)}
45080
- `);
45081
- }
45082
- async function stopSystemd() {
45083
- if (!existsSync19(SYSTEMD_UNIT_PATH)) {
45084
- console.log(`
45085
- ${c.dim("No systemd service found. Nothing to stop.")}
45086
- `);
45087
- await killOrphanedProcesses();
45088
- return;
45089
- }
45090
- console.log(` ${c.info("▶")} Stopping and disabling ${SERVICE_NAME}...`);
45091
- await runShell("systemctl", ["stop", SERVICE_NAME]);
45092
- await runShell("systemctl", ["disable", SERVICE_NAME]);
45093
- unlinkSync6(SYSTEMD_UNIT_PATH);
45094
- await runShell("systemctl", ["daemon-reload"]);
45095
- await killOrphanedProcesses();
45096
- console.log(`
45097
- ${c.success("✔")} ${c.bold("Locus daemon stopped.")}
45098
- `);
45099
- }
45100
- async function restartSystemd() {
45101
- if (!existsSync19(SYSTEMD_UNIT_PATH)) {
45102
- console.log(`
45103
- ${c.dim("No systemd service found. Use")} ${c.primary("locus daemon start")} ${c.dim("first.")}
45104
- `);
45105
- return;
45106
- }
45107
- console.log(` ${c.info("▶")} Restarting ${SERVICE_NAME}...`);
45108
- const result = await runShell("systemctl", ["restart", SERVICE_NAME]);
45109
- if (result.exitCode !== 0) {
45110
- console.error(`
45111
- ${c.error("✖")} Failed to restart: ${result.stderr.trim()}
45112
- `);
45113
- return;
45114
- }
45115
- console.log(`
45116
- ${c.success("✔")} ${c.bold("Locus daemon restarted.")}
45117
- `);
45118
- }
45119
- async function statusSystemd() {
45120
- const result = await runShell("systemctl", ["is-active", SERVICE_NAME]);
45121
- const state = result.stdout.trim();
45122
- if (state === "active") {
45123
- console.log(`
45124
- ${c.success("●")} ${c.bold("Locus daemon is running")} ${c.dim("(systemd)")}
45125
- `);
45126
- } else if (existsSync19(SYSTEMD_UNIT_PATH)) {
45127
- console.log(`
45128
- ${c.secondary("●")} ${c.bold(`Locus daemon is ${state}`)} ${c.dim("(systemd)")}
45129
- `);
45130
- console.log(` ${c.dim("Start with:")} ${c.primary("locus daemon start")}
45131
- `);
45132
- } else {
45133
- console.log(`
45134
- ${c.secondary("●")} ${c.bold("Locus daemon is not installed")}
45135
- `);
45136
- console.log(` ${c.dim("Start with:")} ${c.primary("locus daemon start")}
45137
- `);
45138
- }
45139
- }
45140
- function generatePlist(projectPath, bins) {
45141
- const logDir = join19(homedir3(), "Library/Logs/Locus");
45142
- return `<?xml version="1.0" encoding="UTF-8"?>
45143
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
45144
- <plist version="1.0">
45145
- <dict>
45146
- <key>Label</key>
45147
- <string>${PLIST_LABEL}</string>
45148
- <key>ProgramArguments</key>
45149
- <array>
45150
- <string>${bins.binaryPath}</string>
45151
- </array>
45152
- <key>WorkingDirectory</key>
45153
- <string>${projectPath}</string>
45154
- <key>RunAtLoad</key>
45155
- <true/>
45156
- <key>KeepAlive</key>
45157
- <true/>
45158
- <key>StandardOutPath</key>
45159
- <string>${join19(logDir, "locus.log")}</string>
45160
- <key>StandardErrorPath</key>
45161
- <string>${join19(logDir, "locus-error.log")}</string>
45162
- <key>EnvironmentVariables</key>
45163
- <dict>
45164
- <key>PATH</key>
45165
- <string>${bins.servicePath}</string>
45166
- </dict>
45167
- </dict>
45168
- </plist>
45169
- `;
45170
- }
45171
- async function startLaunchd(projectPath, bins) {
45172
- const plistPath = getPlistPath();
45173
- if (existsSync19(plistPath)) {
45174
- await runShell("launchctl", ["unload", plistPath]);
45175
- }
45176
- const logDir = join19(homedir3(), "Library/Logs/Locus");
45177
- mkdirSync8(logDir, { recursive: true });
45178
- mkdirSync8(join19(homedir3(), "Library/LaunchAgents"), { recursive: true });
45179
- const plist = generatePlist(projectPath, bins);
45180
- console.log(`
45181
- ${c.info("▶")} Writing plist to ${c.dim(plistPath)}`);
45182
- writeFileSync8(plistPath, plist, "utf-8");
45183
- console.log(` ${c.info("▶")} Loading service...`);
45184
- const result = await runShell("launchctl", ["load", plistPath]);
45185
- if (result.exitCode !== 0) {
45186
- console.error(`
45187
- ${c.error("✖")} Failed to load service: ${result.stderr.trim()}`);
45188
- return;
45189
- }
45190
- const logPath = join19(logDir, "locus.log");
45191
- console.log(`
45192
- ${c.success("✔")} ${c.bold("Locus daemon started!")}
45193
-
45194
- ${c.bold("Plist:")} ${plistPath}
45195
- ${c.bold("Logs:")} ${logPath}
45196
-
45197
- ${c.bold("Useful commands:")}
45198
- ${c.dim("$")} ${c.primary(`launchctl list | grep ${PLIST_LABEL}`)}
45199
- ${c.dim("$")} ${c.primary(`tail -f ${logPath}`)}
45200
- `);
45201
- }
45202
- async function stopLaunchd() {
45203
- const plistPath = getPlistPath();
45204
- if (!existsSync19(plistPath)) {
45205
- console.log(`
45206
- ${c.dim("No launchd service found. Nothing to stop.")}
45207
- `);
45208
- await killOrphanedProcesses();
45209
- return;
45210
- }
45211
- console.log(` ${c.info("▶")} Unloading service...`);
45212
- await runShell("launchctl", ["unload", plistPath]);
45213
- unlinkSync6(plistPath);
45214
- await killOrphanedProcesses();
45215
- console.log(`
45216
- ${c.success("✔")} ${c.bold("Locus daemon stopped.")}
45217
- `);
45218
- }
45219
- async function restartLaunchd() {
45220
- const plistPath = getPlistPath();
45221
- if (!existsSync19(plistPath)) {
45222
- console.log(`
45223
- ${c.dim("No launchd service found. Use")} ${c.primary("locus daemon start")} ${c.dim("first.")}
45224
- `);
45225
- return;
45226
- }
45227
- console.log(` ${c.info("▶")} Restarting service...`);
45228
- await runShell("launchctl", ["unload", plistPath]);
45229
- const result = await runShell("launchctl", ["load", plistPath]);
45230
- if (result.exitCode !== 0) {
45231
- console.error(`
45232
- ${c.error("✖")} Failed to restart: ${result.stderr.trim()}
45233
- `);
45234
- return;
45235
- }
45236
- console.log(`
45237
- ${c.success("✔")} ${c.bold("Locus daemon restarted.")}
45238
- `);
45239
- }
45240
- async function statusLaunchd() {
45241
- const plistPath = getPlistPath();
45242
- if (!existsSync19(plistPath)) {
45243
- console.log(`
45244
- ${c.secondary("●")} ${c.bold("Locus daemon is not installed")}
45245
- `);
45246
- console.log(` ${c.dim("Start with:")} ${c.primary("locus daemon start")}
45247
- `);
45248
- return;
45249
- }
45250
- const result = await runShell("launchctl", ["list"]);
45251
- const match = result.stdout.split(`
45252
- `).find((l) => l.includes(PLIST_LABEL));
45253
- if (match) {
45254
- const parts = match.trim().split(/\s+/);
45255
- const pid = parts[0] === "-" ? null : parts[0];
45256
- if (pid) {
45257
- console.log(`
45258
- ${c.success("●")} ${c.bold("Locus daemon is running")} ${c.dim(`(PID ${pid}, launchd)`)}
45259
- `);
45260
- } else {
45261
- console.log(`
45262
- ${c.secondary("●")} ${c.bold("Locus daemon is stopped")} ${c.dim("(launchd)")}
45263
- `);
45264
- console.log(` ${c.dim("Start with:")} ${c.primary("locus daemon start")}
45265
- `);
45266
- }
45267
- } else {
45268
- console.log(`
45269
- ${c.secondary("●")} ${c.bold("Locus daemon is not loaded")} ${c.dim("(plist exists but not loaded)")}
45270
- `);
45271
- console.log(` ${c.dim("Start with:")} ${c.primary("locus daemon start")}
45272
- `);
45273
- }
45274
- }
45275
- async function daemonCommand(args) {
45276
- const projectPath = process.cwd();
45277
- requireInitialization(projectPath, "daemon");
45278
- const subcommand = args[0];
45279
- const platform = subcommand ? requirePlatform() : null;
45280
- const isLinux = platform === "linux";
45281
- switch (subcommand) {
45282
- case "start": {
45283
- validateConfig(projectPath);
45284
- const bins = await resolveBinaries();
45285
- if (isLinux)
45286
- await startSystemd(projectPath, bins);
45287
- else
45288
- await startLaunchd(projectPath, bins);
45289
- break;
45290
- }
45291
- case "stop":
45292
- if (isLinux)
45293
- await stopSystemd();
45294
- else
45295
- await stopLaunchd();
45296
- break;
45297
- case "restart":
45298
- if (isLinux)
45299
- await restartSystemd();
45300
- else
45301
- await restartLaunchd();
45302
- break;
45303
- case "status":
45304
- if (isLinux)
45305
- await statusSystemd();
45306
- else
45307
- await statusLaunchd();
45308
- break;
45309
- default:
45310
- showDaemonHelp();
45311
- }
45312
- }
45313
44626
  // src/commands/discuss.ts
45314
44627
  init_index_node();
45315
44628
  init_progress_renderer();
@@ -45381,7 +44694,7 @@ async function discussCommand(args) {
45381
44694
  console.log(` ${c.dim("Topic:")} ${c.bold(topic)}`);
45382
44695
  console.log(` ${c.dim("Model:")} ${c.dim(`${model} (${provider})`)}
45383
44696
  `);
45384
- const renderer = new ProgressRenderer;
44697
+ const renderer = new ProgressRenderer({ animated: true });
45385
44698
  let discussionId;
45386
44699
  try {
45387
44700
  renderer.showThinkingStarted();
@@ -45445,7 +44758,7 @@ async function discussCommand(args) {
45445
44758
  }
45446
44759
  if (lowerInput === "summary") {
45447
44760
  isProcessing = true;
45448
- const summaryRenderer = new ProgressRenderer;
44761
+ const summaryRenderer = new ProgressRenderer({ animated: true });
45449
44762
  try {
45450
44763
  summaryRenderer.showThinkingStarted();
45451
44764
  const summary = await facilitator.summarizeDiscussion(discussionId);
@@ -45489,7 +44802,7 @@ async function discussCommand(args) {
45489
44802
  const cleanedInput = stripImagePaths(trimmed, images);
45490
44803
  const effectiveInput = cleanedInput + buildImageContext(images);
45491
44804
  isProcessing = true;
45492
- const chunkRenderer = new ProgressRenderer;
44805
+ const chunkRenderer = new ProgressRenderer({ animated: true });
45493
44806
  try {
45494
44807
  chunkRenderer.showThinkingStarted();
45495
44808
  const stream4 = facilitator.continueDiscussionStream(discussionId, effectiveInput);
@@ -46358,17 +45671,11 @@ function showHelp2() {
46358
45671
  ${c.dim("sync Sync docs from API to .locus/documents")}
46359
45672
  ${c.success("review")} Review open Locus PRs on GitHub with AI
46360
45673
  ${c.dim("local Review staged changes locally (no GitHub)")}
46361
- ${c.success("telegram")} Manage the Telegram bot
46362
- ${c.dim("start Start the Telegram bot")}
45674
+ ${c.success("telegram")} Configure the Telegram bot
46363
45675
  ${c.dim("setup Interactive bot token and chat ID setup")}
46364
45676
  ${c.dim("config Show current configuration")}
46365
45677
  ${c.dim("set <k> <v> Update a config value")}
46366
45678
  ${c.dim("remove Remove Telegram configuration")}
46367
- ${c.success("daemon")} Manage the Locus background service
46368
- ${c.dim("start Install and start the daemon")}
46369
- ${c.dim("stop Stop and remove the daemon")}
46370
- ${c.dim("restart Restart the daemon")}
46371
- ${c.dim("status Check if the daemon is running")}
46372
45679
  ${c.success("exec")} Run a prompt with repository context
46373
45680
  ${c.dim("--interactive, -i Start interactive REPL mode")}
46374
45681
  ${c.dim("--session, -s <id> Resume a previous session")}
@@ -46391,19 +45698,17 @@ function showHelp2() {
46391
45698
  ${c.header(" GETTING STARTED ")}
46392
45699
  ${c.dim("$")} ${c.primary("locus init")}
46393
45700
  ${c.dim("$")} ${c.primary("locus config setup")}
46394
- ${c.dim("$")} ${c.primary("locus telegram setup")}
46395
- ${c.dim("$")} ${c.primary("locus daemon start")}
45701
+ ${c.dim("$")} ${c.primary("locus run")}
46396
45702
 
46397
45703
  ${c.header(" EXAMPLES ")}
46398
45704
  ${c.dim("$")} ${c.primary("locus run")}
46399
45705
  ${c.dim("$")} ${c.primary("locus docs sync")}
46400
45706
  ${c.dim("$")} ${c.primary("locus review")}
46401
45707
  ${c.dim("$")} ${c.primary("locus review local")}
46402
- ${c.dim("$")} ${c.primary("locus telegram start")}
45708
+ ${c.dim("$")} ${c.primary("locus telegram setup")}
46403
45709
  ${c.dim("$")} ${c.primary('locus discuss "how should we design the auth system?"')}
46404
45710
  ${c.dim("$")} ${c.primary("locus exec sessions list")}
46405
45711
  ${c.dim("$")} ${c.primary("locus artifacts")}
46406
- ${c.dim("$")} ${c.primary("locus daemon start")}
46407
45712
 
46408
45713
  For more information, visit: ${c.underline("https://docs.locusai.dev")}
46409
45714
  `);
@@ -46548,8 +45853,8 @@ init_config_manager();
46548
45853
  init_settings_manager();
46549
45854
  init_utils3();
46550
45855
  init_workspace_resolver();
46551
- import { existsSync as existsSync21, mkdirSync as mkdirSync10, writeFileSync as writeFileSync9 } from "node:fs";
46552
- import { join as join21 } from "node:path";
45856
+ import { existsSync as existsSync19, mkdirSync as mkdirSync9, writeFileSync as writeFileSync8 } from "node:fs";
45857
+ import { join as join19 } from "node:path";
46553
45858
  import { parseArgs as parseArgs7 } from "node:util";
46554
45859
  async function reviewCommand(args) {
46555
45860
  const subcommand = args[0];
@@ -46688,13 +45993,13 @@ async function reviewLocalCommand(args) {
46688
45993
  `);
46689
45994
  return;
46690
45995
  }
46691
- const reviewsDir = join21(projectPath, LOCUS_CONFIG.dir, LOCUS_CONFIG.reviewsDir);
46692
- if (!existsSync21(reviewsDir)) {
46693
- mkdirSync10(reviewsDir, { recursive: true });
45996
+ const reviewsDir = join19(projectPath, LOCUS_CONFIG.dir, LOCUS_CONFIG.reviewsDir);
45997
+ if (!existsSync19(reviewsDir)) {
45998
+ mkdirSync9(reviewsDir, { recursive: true });
46694
45999
  }
46695
46000
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
46696
- const reportPath = join21(reviewsDir, `review-${timestamp}.md`);
46697
- writeFileSync9(reportPath, report, "utf-8");
46001
+ const reportPath = join19(reviewsDir, `review-${timestamp}.md`);
46002
+ writeFileSync8(reportPath, report, "utf-8");
46698
46003
  console.log(`
46699
46004
  ${c.success("✔")} ${c.success("Review complete!")}`);
46700
46005
  console.log(` ${c.dim("Report saved to:")} ${c.primary(reportPath)}
@@ -46787,30 +46092,12 @@ ${c.info(`Received ${signal}. Stopping agent and cleaning up...`)}`);
46787
46092
  console.log(` ${c.dim("A PR will be opened when all tasks are done")}`);
46788
46093
  await orchestrator.start();
46789
46094
  }
46790
- // src/commands/service.ts
46791
- init_index_node();
46792
- async function serviceCommand(args) {
46793
- const subcommand = args[0];
46794
- const mapping = {
46795
- install: "start",
46796
- uninstall: "stop",
46797
- status: "status"
46798
- };
46799
- const mapped = subcommand ? mapping[subcommand] : undefined;
46800
- if (mapped) {
46801
- console.log(` ${c.dim(`Hint: 'locus service ${subcommand}' is now 'locus daemon ${mapped}'`)}
46802
- `);
46803
- await daemonCommand([mapped, ...args.slice(1)]);
46804
- } else {
46805
- await daemonCommand(args);
46806
- }
46807
- }
46808
46095
  // src/commands/telegram.ts
46809
46096
  init_index_node();
46810
46097
  init_settings_manager();
46811
- import { spawn as spawn5 } from "node:child_process";
46812
- import { existsSync as existsSync22 } from "node:fs";
46813
- import { join as join22 } from "node:path";
46098
+ import { spawn as spawn4 } from "node:child_process";
46099
+ import { existsSync as existsSync20 } from "node:fs";
46100
+ import { join as join20 } from "node:path";
46814
46101
  import { createInterface as createInterface2 } from "node:readline";
46815
46102
  function ask2(question) {
46816
46103
  const rl = createInterface2({
@@ -46836,7 +46123,7 @@ function showTelegramHelp() {
46836
46123
  ${c.primary("locus telegram")} ${c.dim("<subcommand> [options]")}
46837
46124
 
46838
46125
  ${c.header(" SUBCOMMANDS ")}
46839
- ${c.success("start")} Start the Telegram bot
46126
+ ${c.success("run")} Start the Telegram bot
46840
46127
  ${c.success("setup")} Interactive Telegram bot setup (or pass flags below)
46841
46128
  ${c.success("config")} Show current Telegram configuration
46842
46129
  ${c.success("set")} Set a config value
@@ -46845,7 +46132,7 @@ function showTelegramHelp() {
46845
46132
  ${c.success("remove")} Remove Telegram configuration
46846
46133
 
46847
46134
  ${c.header(" EXAMPLES ")}
46848
- ${c.dim("$")} ${c.primary("locus telegram start")}
46135
+ ${c.dim("$")} ${c.primary("locus telegram run")}
46849
46136
  ${c.dim("$")} ${c.primary('locus telegram setup --token "123:ABC" --chat-id 987654')}
46850
46137
  ${c.dim("$")} ${c.primary("locus telegram config")}
46851
46138
  ${c.dim("$")} ${c.primary("locus telegram remove")}
@@ -46856,7 +46143,7 @@ function showTelegramHelp() {
46856
46143
  ${c.primary("locus config set <key> <value>")}
46857
46144
  `);
46858
46145
  }
46859
- async function setup(args, projectPath) {
46146
+ async function setupCommand2(args, projectPath) {
46860
46147
  let token;
46861
46148
  let chatId;
46862
46149
  for (let i = 0;i < args.length; i++) {
@@ -46928,11 +46215,10 @@ async function setup(args, projectPath) {
46928
46215
  ${c.primary("Chat ID:")} ${parsedChatId}
46929
46216
 
46930
46217
  ${c.bold("Next steps:")}
46931
- Start as daemon: ${c.primary("locus daemon start")}
46932
- Or run manually: ${c.primary("locus telegram start")}
46218
+ Start the bot with: ${c.primary("locus telegram run")}
46933
46219
  `);
46934
46220
  }
46935
- function showConfig(projectPath) {
46221
+ function configCommand2(projectPath) {
46936
46222
  const manager = new SettingsManager(projectPath);
46937
46223
  const settings = manager.load();
46938
46224
  const tg = settings.telegram;
@@ -46948,28 +46234,36 @@ function showConfig(projectPath) {
46948
46234
  console.log(` ${c.dim("File: .locus/settings.json (telegram section)")}
46949
46235
  `);
46950
46236
  const entries = [];
46951
- if (tg.botToken)
46237
+ if (tg.botToken) {
46952
46238
  entries.push(["botToken", maskToken(tg.botToken)]);
46953
- if (tg.chatId)
46239
+ }
46240
+ if (tg.chatId) {
46954
46241
  entries.push(["chatId", String(tg.chatId)]);
46955
- if (tg.testMode !== undefined)
46242
+ }
46243
+ if (tg.testMode !== undefined) {
46956
46244
  entries.push(["testMode", String(tg.testMode)]);
46957
- if (settings.apiKey)
46245
+ }
46246
+ if (settings.apiKey) {
46958
46247
  entries.push(["apiKey (shared)", maskToken(settings.apiKey)]);
46959
- if (settings.apiUrl)
46248
+ }
46249
+ if (settings.apiUrl) {
46960
46250
  entries.push(["apiUrl (shared)", settings.apiUrl]);
46961
- if (settings.provider)
46251
+ }
46252
+ if (settings.provider) {
46962
46253
  entries.push(["provider (shared)", settings.provider]);
46963
- if (settings.model)
46254
+ }
46255
+ if (settings.model) {
46964
46256
  entries.push(["model (shared)", settings.model]);
46965
- if (settings.workspaceId)
46257
+ }
46258
+ if (settings.workspaceId) {
46966
46259
  entries.push(["workspaceId (shared)", settings.workspaceId]);
46260
+ }
46967
46261
  for (const [key, value] of entries) {
46968
46262
  console.log(` ${c.primary(`${key}:`)} ${value}`);
46969
46263
  }
46970
46264
  console.log("");
46971
46265
  }
46972
- function setValue(args, projectPath) {
46266
+ function setCommand2(args, projectPath) {
46973
46267
  const key = args[0]?.trim();
46974
46268
  const value = args.slice(1).join(" ").trim();
46975
46269
  if (!key || !value) {
@@ -47012,7 +46306,7 @@ function setValue(args, projectPath) {
47012
46306
  ${c.success("✔")} Set ${c.primary(key)} = ${displayValue}
47013
46307
  `);
47014
46308
  }
47015
- function removeConfig(projectPath) {
46309
+ function removeCommand2(projectPath) {
47016
46310
  const manager = new SettingsManager(projectPath);
47017
46311
  const settings = manager.load();
47018
46312
  if (!settings.telegram) {
@@ -47027,7 +46321,7 @@ function removeConfig(projectPath) {
47027
46321
  ${c.success("✔")} ${c.bold("Telegram configuration removed.")}
47028
46322
  `);
47029
46323
  }
47030
- function startBot(projectPath) {
46324
+ function runBotCommand(projectPath) {
47031
46325
  const manager = new SettingsManager(projectPath);
47032
46326
  const settings = manager.load();
47033
46327
  if (!settings.telegram?.botToken || !settings.telegram?.chatId) {
@@ -47037,14 +46331,22 @@ function startBot(projectPath) {
47037
46331
  `);
47038
46332
  process.exit(1);
47039
46333
  }
47040
- const monorepoEntry = join22(projectPath, "packages/telegram/src/index.ts");
47041
- const isMonorepo = existsSync22(monorepoEntry);
47042
- const cmd = isMonorepo ? "bun" : "locus-telegram";
47043
- const cmdArgs = isMonorepo ? ["run", monorepoEntry] : [];
47044
- const child = spawn5(cmd, cmdArgs, {
46334
+ const monorepoTelegramEntry = join20(projectPath, "packages/telegram/src/index.ts");
46335
+ const isMonorepo = existsSync20(monorepoTelegramEntry);
46336
+ let cmd;
46337
+ let args;
46338
+ if (isMonorepo) {
46339
+ cmd = "bun";
46340
+ args = ["run", monorepoTelegramEntry];
46341
+ } else {
46342
+ cmd = "locus-telegram";
46343
+ args = [];
46344
+ }
46345
+ const env = { ...process.env };
46346
+ const child = spawn4(cmd, args, {
47045
46347
  cwd: projectPath,
47046
46348
  stdio: "inherit",
47047
- env: { ...process.env }
46349
+ env
47048
46350
  });
47049
46351
  child.on("error", (err) => {
47050
46352
  if (err.code === "ENOENT" && !isMonorepo) {
@@ -47065,23 +46367,22 @@ function startBot(projectPath) {
47065
46367
  }
47066
46368
  async function telegramCommand(args) {
47067
46369
  const projectPath = process.cwd();
47068
- const [subcommand, ...subArgs] = args;
46370
+ const subcommand = args[0];
47069
46371
  switch (subcommand) {
47070
- case "start":
47071
46372
  case "run":
47072
- startBot(projectPath);
46373
+ runBotCommand(projectPath);
47073
46374
  break;
47074
46375
  case "setup":
47075
- await setup(subArgs, projectPath);
46376
+ await setupCommand2(args, projectPath);
47076
46377
  break;
47077
46378
  case "config":
47078
- showConfig(projectPath);
46379
+ configCommand2(projectPath);
47079
46380
  break;
47080
46381
  case "set":
47081
- setValue(subArgs, projectPath);
46382
+ setCommand2(args, projectPath);
47082
46383
  break;
47083
46384
  case "remove":
47084
- removeConfig(projectPath);
46385
+ removeCommand2(projectPath);
47085
46386
  break;
47086
46387
  default:
47087
46388
  showTelegramHelp();
@@ -47117,7 +46418,6 @@ async function upgradeCommand() {
47117
46418
  console.log(`
47118
46419
  ${c.header(" UPGRADE ")}
47119
46420
  `);
47120
- const daemonWasRunning = await isDaemonRunning();
47121
46421
  try {
47122
46422
  console.log(` ${c.dim("◌")} Cleaning npm cache...`);
47123
46423
  execSync3("npm cache clean --force", {
@@ -47129,7 +46429,6 @@ async function upgradeCommand() {
47129
46429
  console.log(` ${c.dim("⚠")} Could not clean npm cache, continuing...
47130
46430
  `);
47131
46431
  }
47132
- let anyUpdated = false;
47133
46432
  for (const pkg of PACKAGES) {
47134
46433
  const current = getInstalledVersion(pkg);
47135
46434
  const latest = getLatestVersion(pkg);
@@ -47152,27 +46451,12 @@ async function upgradeCommand() {
47152
46451
  });
47153
46452
  console.log(` ${c.success("✔")} ${c.bold(pkg)} updated to ${c.primary(`v${latest}`)}
47154
46453
  `);
47155
- anyUpdated = true;
47156
46454
  } catch {
47157
46455
  console.error(` ${c.error("✖")} Failed to update ${c.bold(pkg)}. Try manually:
47158
46456
  ` + ` ${c.primary(`npm install -g ${pkg}@latest`)}
47159
46457
  `);
47160
46458
  }
47161
46459
  }
47162
- if (daemonWasRunning && anyUpdated) {
47163
- console.log(` ${c.info("▶")} Restarting locus daemon...`);
47164
- const restarted = await restartDaemonIfRunning();
47165
- if (restarted) {
47166
- console.log(` ${c.success("✔")} Locus daemon restarted
47167
- `);
47168
- } else {
47169
- console.log(` ${c.dim("⚠")} Could not restart daemon (may need sudo)
47170
- `);
47171
- }
47172
- } else if (daemonWasRunning && !anyUpdated) {
47173
- console.log(` ${c.dim("No updates — daemon left running")}
47174
- `);
47175
- }
47176
46460
  console.log("");
47177
46461
  }
47178
46462
  // src/commands/version.ts
@@ -47244,12 +46528,6 @@ async function main() {
47244
46528
  case "config":
47245
46529
  await configCommand(args);
47246
46530
  break;
47247
- case "daemon":
47248
- await daemonCommand(args);
47249
- break;
47250
- case "service":
47251
- await serviceCommand(args);
47252
- break;
47253
46531
  case "docs":
47254
46532
  await docsCommand(args);
47255
46533
  break;
@@ -47278,11 +46556,3 @@ main().catch((err) => {
47278
46556
  ${c.error("✖ Fatal Error")} ${c.red(err.message)}`);
47279
46557
  process.exit(1);
47280
46558
  });
47281
-
47282
- // index.ts
47283
- var _emit = process.emit;
47284
- process.emit = function(name, data, ...args) {
47285
- if (name === "warning" && data?.code === "DEP0040")
47286
- return false;
47287
- return _emit.apply(process, [name, data, ...args]);
47288
- };