@locusai/cli 0.7.0 → 0.7.3

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.
@@ -17065,7 +17065,15 @@ var colors = {
17065
17065
  brightBlue: `${ESC}94m`,
17066
17066
  brightMagenta: `${ESC}95m`,
17067
17067
  brightCyan: `${ESC}96m`,
17068
- brightWhite: `${ESC}97m`
17068
+ brightWhite: `${ESC}97m`,
17069
+ bgBlack: `${ESC}40m`,
17070
+ bgRed: `${ESC}41m`,
17071
+ bgGreen: `${ESC}42m`,
17072
+ bgYellow: `${ESC}43m`,
17073
+ bgBlue: `${ESC}44m`,
17074
+ bgMagenta: `${ESC}45m`,
17075
+ bgCyan: `${ESC}46m`,
17076
+ bgWhite: `${ESC}47m`
17069
17077
  };
17070
17078
  var c = {
17071
17079
  text: (text, ...colorNames) => {
@@ -17081,11 +17089,17 @@ var c = {
17081
17089
  magenta: (t) => c.text(t, "magenta"),
17082
17090
  cyan: (t) => c.text(t, "cyan"),
17083
17091
  gray: (t) => c.text(t, "gray"),
17092
+ white: (t) => c.text(t, "white"),
17093
+ brightBlue: (t) => c.text(t, "brightBlue"),
17094
+ bgBlue: (t) => c.text(t, "bgBlue", "white", "bold"),
17084
17095
  success: (t) => c.text(t, "green", "bold"),
17085
17096
  error: (t) => c.text(t, "red", "bold"),
17086
17097
  warning: (t) => c.text(t, "yellow", "bold"),
17087
17098
  info: (t) => c.text(t, "cyan", "bold"),
17088
17099
  primary: (t) => c.text(t, "blue", "bold"),
17100
+ secondary: (t) => c.text(t, "magenta", "bold"),
17101
+ header: (t) => c.text(` ${t} `, "bgBlue", "white", "bold"),
17102
+ step: (t) => c.text(` ${t} `, "bgCyan", "black", "bold"),
17089
17103
  underline: (t) => c.text(t, "underline")
17090
17104
  };
17091
17105
 
@@ -17213,7 +17227,6 @@ class ClaudeRunner {
17213
17227
  if (type === "content_block_start" && content_block) {
17214
17228
  if (content_block.type === "tool_use" && content_block.name) {
17215
17229
  this.log?.(`
17216
-
17217
17230
  ${c.primary("[Claude]")} ${c.bold(`Running ${content_block.name}...`)}
17218
17231
  `, "info");
17219
17232
  }
@@ -20814,6 +20827,13 @@ class AIModule extends BaseModule {
20814
20827
  async deleteSession(workspaceId, sessionId) {
20815
20828
  await this.api.delete(`/ai/${workspaceId}/session/${sessionId}`);
20816
20829
  }
20830
+ async shareSession(workspaceId, sessionId, body) {
20831
+ await this.api.post(`/ai/${workspaceId}/session/${sessionId}/share`, body);
20832
+ }
20833
+ async getSharedSession(sessionId) {
20834
+ const { data } = await this.api.get(`/ai/shared/${sessionId}`);
20835
+ return data;
20836
+ }
20817
20837
  }
20818
20838
 
20819
20839
  // ../sdk/src/modules/auth.ts
@@ -34834,6 +34854,9 @@ var ChatResponseSchema = exports_external.object({
34834
34854
  sessionId: exports_external.string(),
34835
34855
  history: exports_external.array(AIMessageSchema).optional()
34836
34856
  });
34857
+ var ShareChatRequestSchema = exports_external.object({
34858
+ isShared: exports_external.boolean()
34859
+ });
34837
34860
  // ../shared/src/models/user.ts
34838
34861
  var UserSchema = BaseEntitySchema.extend({
34839
34862
  email: exports_external.string().email(),
@@ -36110,13 +36133,10 @@ class CodebaseIndexer {
36110
36133
  `);
36111
36134
  const newTreeHash = this.hashTree(treeString);
36112
36135
  const existingIndex = this.loadIndex();
36113
- if (!force && existingIndex?.treeHash === newTreeHash) {
36114
- onProgress?.("No file changes detected, skipping reindex");
36115
- return null;
36116
- }
36117
36136
  const currentHashes = this.computeFileHashes(currentFiles);
36118
36137
  const existingHashes = existingIndex?.fileHashes;
36119
- const canIncremental = !force && existingIndex && existingHashes;
36138
+ const hasExistingContent = existingIndex && (Object.keys(existingIndex.symbols).length > 0 || Object.keys(existingIndex.responsibilities).length > 0);
36139
+ const canIncremental = !force && existingIndex && existingHashes && hasExistingContent;
36120
36140
  if (canIncremental) {
36121
36141
  onProgress?.("Performing incremental update");
36122
36142
  const { added, deleted, modified } = this.diffFiles(currentHashes, existingHashes);
@@ -36149,8 +36169,12 @@ class CodebaseIndexer {
36149
36169
  }
36150
36170
  }
36151
36171
  onProgress?.("AI is analyzing codebase structure...");
36152
- const index = await treeSummarizer(treeString);
36153
- return this.applyIndexMetadata(index, currentHashes, newTreeHash);
36172
+ try {
36173
+ const index = await treeSummarizer(treeString);
36174
+ return this.applyIndexMetadata(index, currentHashes, newTreeHash);
36175
+ } catch (error48) {
36176
+ throw new Error(`AI analysis failed: ${error48 instanceof Error ? error48.message : String(error48)}`);
36177
+ }
36154
36178
  }
36155
36179
  async getFileTree() {
36156
36180
  const gitmodulesPath = join4(this.projectPath, ".gitmodules");
@@ -36501,6 +36525,76 @@ ${comment.text}
36501
36525
  2. **Artifact Management**: If you create any high-level documentation (PRDs, technical drafts, architecture docs), you MUST save them in \`.locus/artifacts/\`. Do NOT create them in the root directory.
36502
36526
  3. **Paths**: Use relative paths from the project root at all times. Do NOT use absolute local paths (e.g., /Users/...).
36503
36527
  4. When finished successfully, output: <promise>COMPLETE</promise>
36528
+ `;
36529
+ return prompt;
36530
+ }
36531
+ async buildGenericPrompt(query) {
36532
+ let prompt = `# Direct Execution
36533
+
36534
+ `;
36535
+ prompt += `## Prompt
36536
+ ${query}
36537
+
36538
+ `;
36539
+ const projectConfig = this.getProjectConfig();
36540
+ if (projectConfig) {
36541
+ prompt += `## Project Metadata
36542
+ `;
36543
+ prompt += `- Version: ${projectConfig.version || "Unknown"}
36544
+ `;
36545
+ prompt += `- Created At: ${projectConfig.createdAt || "Unknown"}
36546
+
36547
+ `;
36548
+ }
36549
+ const contextPath = getLocusPath(this.projectPath, "contextFile");
36550
+ let hasLocalContext = false;
36551
+ if (existsSync4(contextPath)) {
36552
+ try {
36553
+ const context = readFileSync4(contextPath, "utf-8");
36554
+ if (context.trim().length > 20) {
36555
+ prompt += `## Project Context (Local)
36556
+ ${context}
36557
+
36558
+ `;
36559
+ hasLocalContext = true;
36560
+ }
36561
+ } catch (err) {
36562
+ console.warn(`Warning: Could not read context file: ${err}`);
36563
+ }
36564
+ }
36565
+ if (!hasLocalContext) {
36566
+ const fallback = this.getFallbackContext();
36567
+ if (fallback) {
36568
+ prompt += `## Project Context (README Fallback)
36569
+ ${fallback}
36570
+
36571
+ `;
36572
+ }
36573
+ }
36574
+ prompt += this.getProjectStructure();
36575
+ prompt += this.getSkillsInfo();
36576
+ prompt += `## Project Knowledge Base
36577
+ `;
36578
+ prompt += `You have access to the following documentation directories for context:
36579
+ `;
36580
+ prompt += `- Artifacts: \`.locus/artifacts\`
36581
+ `;
36582
+ prompt += `- Documents: \`.locus/documents\`
36583
+ `;
36584
+ prompt += `If you need more information about the project strategies, plans, or architecture, please read files in these directories.
36585
+
36586
+ `;
36587
+ const indexPath = getLocusPath(this.projectPath, "indexFile");
36588
+ if (existsSync4(indexPath)) {
36589
+ prompt += `## Codebase Overview
36590
+ There is an index file in the .locus/codebase-index.json and if you need you can check it.
36591
+
36592
+ `;
36593
+ }
36594
+ prompt += `## Instructions
36595
+ 1. Execute the prompt based on the provided project context.
36596
+ 2. **Paths**: Use relative paths from the project root at all times. Do NOT use absolute local paths (e.g., /Users/...).
36597
+ 3. When finished successfully, output: <promise>COMPLETE</promise>
36504
36598
  `;
36505
36599
  return prompt;
36506
36600
  }
@@ -36642,16 +36736,12 @@ class TaskExecutor {
36642
36736
  });
36643
36737
  try {
36644
36738
  let plan = null;
36645
- if (this.deps.skipPlanning) {
36646
- this.deps.log("Skipping Phase 1: Planning (CLI)...", "info");
36647
- } else {
36648
- this.deps.log("Phase 1: Planning (CLI)...", "info");
36649
- const planningPrompt = `${basePrompt}
36739
+ this.deps.log("Phase 1: Planning (CLI)...", "info");
36740
+ const planningPrompt = `${basePrompt}
36650
36741
 
36651
36742
  ## Phase 1: Planning
36652
36743
  Analyze and create a detailed plan for THIS SPECIFIC TASK. Do NOT execute changes yet.`;
36653
- plan = await this.deps.aiRunner.run(planningPrompt, true);
36654
- }
36744
+ plan = await this.deps.aiRunner.run(planningPrompt, true);
36655
36745
  this.deps.log("Starting Execution...", "info");
36656
36746
  let executionPrompt = basePrompt;
36657
36747
  if (plan != null) {
@@ -36740,7 +36830,6 @@ class AgentWorker {
36740
36830
  this.taskExecutor = new TaskExecutor({
36741
36831
  aiRunner: this.aiRunner,
36742
36832
  projectPath,
36743
- skipPlanning: config2.skipPlanning,
36744
36833
  log
36745
36834
  });
36746
36835
  const providerLabel = provider === "codex" ? "Codex" : "Claude";
@@ -36871,8 +36960,7 @@ if (process.argv[1]?.includes("agent-worker") || process.argv[1]?.includes("work
36871
36960
  if (value && !value.startsWith("--"))
36872
36961
  i++;
36873
36962
  config2.provider = resolveProvider(value);
36874
- } else if (arg === "--skip-planning")
36875
- config2.skipPlanning = true;
36963
+ }
36876
36964
  }
36877
36965
  if (!config2.agentId || !config2.workspaceId || !config2.apiBase || !config2.apiKey || !config2.projectPath) {
36878
36966
  console.error("Missing required arguments");
package/bin/locus.js CHANGED
@@ -30874,6 +30874,9 @@ var ChatResponseSchema = exports_external.object({
30874
30874
  sessionId: exports_external.string(),
30875
30875
  history: exports_external.array(AIMessageSchema).optional()
30876
30876
  });
30877
+ var ShareChatRequestSchema = exports_external.object({
30878
+ isShared: exports_external.boolean()
30879
+ });
30877
30880
  // ../shared/src/models/user.ts
30878
30881
  var UserSchema = BaseEntitySchema.extend({
30879
30882
  email: exports_external.string().email(),
@@ -31961,13 +31964,10 @@ class CodebaseIndexer {
31961
31964
  `);
31962
31965
  const newTreeHash = this.hashTree(treeString);
31963
31966
  const existingIndex = this.loadIndex();
31964
- if (!force && existingIndex?.treeHash === newTreeHash) {
31965
- onProgress?.("No file changes detected, skipping reindex");
31966
- return null;
31967
- }
31968
31967
  const currentHashes = this.computeFileHashes(currentFiles);
31969
31968
  const existingHashes = existingIndex?.fileHashes;
31970
- const canIncremental = !force && existingIndex && existingHashes;
31969
+ const hasExistingContent = existingIndex && (Object.keys(existingIndex.symbols).length > 0 || Object.keys(existingIndex.responsibilities).length > 0);
31970
+ const canIncremental = !force && existingIndex && existingHashes && hasExistingContent;
31971
31971
  if (canIncremental) {
31972
31972
  onProgress?.("Performing incremental update");
31973
31973
  const { added, deleted, modified } = this.diffFiles(currentHashes, existingHashes);
@@ -32000,8 +32000,12 @@ class CodebaseIndexer {
32000
32000
  }
32001
32001
  }
32002
32002
  onProgress?.("AI is analyzing codebase structure...");
32003
- const index = await treeSummarizer(treeString);
32004
- return this.applyIndexMetadata(index, currentHashes, newTreeHash);
32003
+ try {
32004
+ const index = await treeSummarizer(treeString);
32005
+ return this.applyIndexMetadata(index, currentHashes, newTreeHash);
32006
+ } catch (error48) {
32007
+ throw new Error(`AI analysis failed: ${error48 instanceof Error ? error48.message : String(error48)}`);
32008
+ }
32005
32009
  }
32006
32010
  async getFileTree() {
32007
32011
  const gitmodulesPath = join3(this.projectPath, ".gitmodules");
@@ -32351,6 +32355,76 @@ ${comment.text}
32351
32355
  2. **Artifact Management**: If you create any high-level documentation (PRDs, technical drafts, architecture docs), you MUST save them in \`.locus/artifacts/\`. Do NOT create them in the root directory.
32352
32356
  3. **Paths**: Use relative paths from the project root at all times. Do NOT use absolute local paths (e.g., /Users/...).
32353
32357
  4. When finished successfully, output: <promise>COMPLETE</promise>
32358
+ `;
32359
+ return prompt;
32360
+ }
32361
+ async buildGenericPrompt(query) {
32362
+ let prompt = `# Direct Execution
32363
+
32364
+ `;
32365
+ prompt += `## Prompt
32366
+ ${query}
32367
+
32368
+ `;
32369
+ const projectConfig = this.getProjectConfig();
32370
+ if (projectConfig) {
32371
+ prompt += `## Project Metadata
32372
+ `;
32373
+ prompt += `- Version: ${projectConfig.version || "Unknown"}
32374
+ `;
32375
+ prompt += `- Created At: ${projectConfig.createdAt || "Unknown"}
32376
+
32377
+ `;
32378
+ }
32379
+ const contextPath = getLocusPath(this.projectPath, "contextFile");
32380
+ let hasLocalContext = false;
32381
+ if (existsSync3(contextPath)) {
32382
+ try {
32383
+ const context = readFileSync3(contextPath, "utf-8");
32384
+ if (context.trim().length > 20) {
32385
+ prompt += `## Project Context (Local)
32386
+ ${context}
32387
+
32388
+ `;
32389
+ hasLocalContext = true;
32390
+ }
32391
+ } catch (err) {
32392
+ console.warn(`Warning: Could not read context file: ${err}`);
32393
+ }
32394
+ }
32395
+ if (!hasLocalContext) {
32396
+ const fallback = this.getFallbackContext();
32397
+ if (fallback) {
32398
+ prompt += `## Project Context (README Fallback)
32399
+ ${fallback}
32400
+
32401
+ `;
32402
+ }
32403
+ }
32404
+ prompt += this.getProjectStructure();
32405
+ prompt += this.getSkillsInfo();
32406
+ prompt += `## Project Knowledge Base
32407
+ `;
32408
+ prompt += `You have access to the following documentation directories for context:
32409
+ `;
32410
+ prompt += `- Artifacts: \`.locus/artifacts\`
32411
+ `;
32412
+ prompt += `- Documents: \`.locus/documents\`
32413
+ `;
32414
+ prompt += `If you need more information about the project strategies, plans, or architecture, please read files in these directories.
32415
+
32416
+ `;
32417
+ const indexPath = getLocusPath(this.projectPath, "indexFile");
32418
+ if (existsSync3(indexPath)) {
32419
+ prompt += `## Codebase Overview
32420
+ There is an index file in the .locus/codebase-index.json and if you need you can check it.
32421
+
32422
+ `;
32423
+ }
32424
+ prompt += `## Instructions
32425
+ 1. Execute the prompt based on the provided project context.
32426
+ 2. **Paths**: Use relative paths from the project root at all times. Do NOT use absolute local paths (e.g., /Users/...).
32427
+ 3. When finished successfully, output: <promise>COMPLETE</promise>
32354
32428
  `;
32355
32429
  return prompt;
32356
32430
  }
@@ -32492,16 +32566,12 @@ class TaskExecutor {
32492
32566
  });
32493
32567
  try {
32494
32568
  let plan = null;
32495
- if (this.deps.skipPlanning) {
32496
- this.deps.log("Skipping Phase 1: Planning (CLI)...", "info");
32497
- } else {
32498
- this.deps.log("Phase 1: Planning (CLI)...", "info");
32499
- const planningPrompt = `${basePrompt}
32569
+ this.deps.log("Phase 1: Planning (CLI)...", "info");
32570
+ const planningPrompt = `${basePrompt}
32500
32571
 
32501
32572
  ## Phase 1: Planning
32502
32573
  Analyze and create a detailed plan for THIS SPECIFIC TASK. Do NOT execute changes yet.`;
32503
- plan = await this.deps.aiRunner.run(planningPrompt, true);
32504
- }
32574
+ plan = await this.deps.aiRunner.run(planningPrompt, true);
32505
32575
  this.deps.log("Starting Execution...", "info");
32506
32576
  let executionPrompt = basePrompt;
32507
32577
  if (plan != null) {
@@ -32559,7 +32629,15 @@ var colors = {
32559
32629
  brightBlue: `${ESC}94m`,
32560
32630
  brightMagenta: `${ESC}95m`,
32561
32631
  brightCyan: `${ESC}96m`,
32562
- brightWhite: `${ESC}97m`
32632
+ brightWhite: `${ESC}97m`,
32633
+ bgBlack: `${ESC}40m`,
32634
+ bgRed: `${ESC}41m`,
32635
+ bgGreen: `${ESC}42m`,
32636
+ bgYellow: `${ESC}43m`,
32637
+ bgBlue: `${ESC}44m`,
32638
+ bgMagenta: `${ESC}45m`,
32639
+ bgCyan: `${ESC}46m`,
32640
+ bgWhite: `${ESC}47m`
32563
32641
  };
32564
32642
  var c = {
32565
32643
  text: (text, ...colorNames) => {
@@ -32575,11 +32653,17 @@ var c = {
32575
32653
  magenta: (t) => c.text(t, "magenta"),
32576
32654
  cyan: (t) => c.text(t, "cyan"),
32577
32655
  gray: (t) => c.text(t, "gray"),
32656
+ white: (t) => c.text(t, "white"),
32657
+ brightBlue: (t) => c.text(t, "brightBlue"),
32658
+ bgBlue: (t) => c.text(t, "bgBlue", "white", "bold"),
32578
32659
  success: (t) => c.text(t, "green", "bold"),
32579
32660
  error: (t) => c.text(t, "red", "bold"),
32580
32661
  warning: (t) => c.text(t, "yellow", "bold"),
32581
32662
  info: (t) => c.text(t, "cyan", "bold"),
32582
32663
  primary: (t) => c.text(t, "blue", "bold"),
32664
+ secondary: (t) => c.text(t, "magenta", "bold"),
32665
+ header: (t) => c.text(` ${t} `, "bgBlue", "white", "bold"),
32666
+ step: (t) => c.text(` ${t} `, "bgCyan", "black", "bold"),
32583
32667
  underline: (t) => c.text(t, "underline")
32584
32668
  };
32585
32669
 
@@ -32707,7 +32791,6 @@ class ClaudeRunner {
32707
32791
  if (type === "content_block_start" && content_block) {
32708
32792
  if (content_block.type === "tool_use" && content_block.name) {
32709
32793
  this.log?.(`
32710
-
32711
32794
  ${c.primary("[Claude]")} ${c.bold(`Running ${content_block.name}...`)}
32712
32795
  `, "info");
32713
32796
  }
@@ -36308,6 +36391,13 @@ class AIModule extends BaseModule {
36308
36391
  async deleteSession(workspaceId, sessionId) {
36309
36392
  await this.api.delete(`/ai/${workspaceId}/session/${sessionId}`);
36310
36393
  }
36394
+ async shareSession(workspaceId, sessionId, body) {
36395
+ await this.api.post(`/ai/${workspaceId}/session/${sessionId}/share`, body);
36396
+ }
36397
+ async getSharedSession(sessionId) {
36398
+ const { data } = await this.api.get(`/ai/shared/${sessionId}`);
36399
+ return data;
36400
+ }
36311
36401
  }
36312
36402
 
36313
36403
  // ../sdk/src/modules/auth.ts
@@ -36746,7 +36836,6 @@ class AgentWorker {
36746
36836
  this.taskExecutor = new TaskExecutor({
36747
36837
  aiRunner: this.aiRunner,
36748
36838
  projectPath,
36749
- skipPlanning: config2.skipPlanning,
36750
36839
  log
36751
36840
  });
36752
36841
  const providerLabel = provider === "codex" ? "Codex" : "Claude";
@@ -36877,8 +36966,7 @@ if (process.argv[1]?.includes("agent-worker") || process.argv[1]?.includes("work
36877
36966
  if (value && !value.startsWith("--"))
36878
36967
  i++;
36879
36968
  config2.provider = resolveProvider(value);
36880
- } else if (arg === "--skip-planning")
36881
- config2.skipPlanning = true;
36969
+ }
36882
36970
  }
36883
36971
  if (!config2.agentId || !config2.workspaceId || !config2.apiBase || !config2.apiKey || !config2.projectPath) {
36884
36972
  console.error("Missing required arguments");
@@ -37012,9 +37100,6 @@ ${c.success("✅ Orchestrator finished")}`);
37012
37100
  if (this.config.provider) {
37013
37101
  workerArgs.push("--provider", this.config.provider);
37014
37102
  }
37015
- if (this.config.skipPlanning) {
37016
- workerArgs.push("--skip-planning");
37017
- }
37018
37103
  if (this.resolvedSprintId) {
37019
37104
  workerArgs.push("--sprint-id", this.resolvedSprintId);
37020
37105
  }
@@ -37613,12 +37698,12 @@ function getVersion() {
37613
37698
  var VERSION2 = getVersion();
37614
37699
  function printBanner() {
37615
37700
  console.log(c.primary(`
37616
- ## ###### ###### ## ## ######
37617
- ## ## ## ## ## ## ##
37618
- ## ## ## ## ## ## ######
37619
- ## ## ## ## ## ## ##
37620
- ####### ###### ###### ###### ###### v${VERSION2}
37621
- `));
37701
+ _ ____ ____ _ _ ____
37702
+ | | / __ \\ / ___| | | |/ ___|
37703
+ | | | | | | | | | | |\\___ \\
37704
+ | |___| |__| | |___| |_| |___) |
37705
+ |_____|\\____/ \\____|\\___/|____/ ${c.dim(`v${VERSION2}`)}
37706
+ `));
37622
37707
  }
37623
37708
  function isProjectInitialized(projectPath) {
37624
37709
  const locusDir = join8(projectPath, LOCUS_CONFIG.dir);
@@ -37628,14 +37713,14 @@ function isProjectInitialized(projectPath) {
37628
37713
  function requireInitialization(projectPath, command) {
37629
37714
  if (!isProjectInitialized(projectPath)) {
37630
37715
  console.error(`
37631
- ${c.error(" Error: Locus is not initialized in this directory.")}
37716
+ ${c.error(" Error")} ${c.red(`Locus is not initialized in this directory.`)}
37632
37717
 
37633
- The '${c.bold(command)}' command requires a Locus project to be initialized.
37718
+ The '${c.bold(command)}' command requires a Locus project to be initialized.
37634
37719
 
37635
- To initialize Locus in this directory, run:
37636
- ${c.primary("locus init")}
37720
+ To initialize Locus in this directory, run:
37721
+ ${c.primary("locus init")}
37637
37722
 
37638
- This will create a .locus directory with the necessary configuration.
37723
+ This will create a ${c.dim(".locus")} directory with the necessary configuration.
37639
37724
  `);
37640
37725
  process.exit(1);
37641
37726
  }
@@ -37696,12 +37781,11 @@ async function runCommand(args) {
37696
37781
  apiBase,
37697
37782
  maxIterations: 100,
37698
37783
  projectPath,
37699
- apiKey,
37700
- skipPlanning: Boolean(values["skip-planning"])
37784
+ apiKey
37701
37785
  });
37702
- orchestrator.on("task:assigned", (data) => console.log(`ℹ [CLAIMED] ${data.title}`));
37703
- orchestrator.on("task:completed", (data) => console.log(`✓ [COMPLETED] ${data.taskId}`));
37704
- orchestrator.on("task:failed", (data) => console.log(`✗ [FAILED] ${data.taskId}: ${data.error}`));
37786
+ orchestrator.on("task:assigned", (data) => console.log(` ${c.info("●")} ${c.bold("Claimed:")} ${data.title}`));
37787
+ orchestrator.on("task:completed", (data) => console.log(` ${c.success("✔")} ${c.success("Completed:")} ${c.dim(data.taskId)}`));
37788
+ orchestrator.on("task:failed", (data) => console.log(` ${c.error("✖")} ${c.error("Failed:")} ${c.bold(data.taskId)}: ${data.error}`));
37705
37789
  const handleSignal = async (signal) => {
37706
37790
  console.log(`
37707
37791
  ${c.info(`Received ${signal}. Stopping agents...`)}`);
@@ -37710,7 +37794,8 @@ ${c.info(`Received ${signal}. Stopping agents...`)}`);
37710
37794
  };
37711
37795
  process.on("SIGINT", () => handleSignal("SIGINT"));
37712
37796
  process.on("SIGTERM", () => handleSignal("SIGTERM"));
37713
- console.log(`${c.primary("\uD83D\uDE80 Starting agent in")} ${c.bold(projectPath)}...`);
37797
+ console.log(`
37798
+ ${c.primary("\uD83D\uDE80")} ${c.bold("Starting Locus agent in")} ${c.primary(projectPath)}...`);
37714
37799
  await orchestrator.start();
37715
37800
  }
37716
37801
  async function indexCommand(args) {
@@ -37734,12 +37819,63 @@ async function indexCommand(args) {
37734
37819
  });
37735
37820
  const summarizer = new TreeSummarizer(aiRunner);
37736
37821
  const indexer = new CodebaseIndexer(projectPath);
37737
- console.log(`${c.primary("\uD83D\uDD0D Indexing codebase in")} ${c.bold(projectPath)}...`);
37738
- const index = await indexer.index((msg) => console.log(` ${c.dim(msg)}`), (tree) => summarizer.summarize(tree));
37739
- if (index) {
37740
- indexer.saveIndex(index);
37822
+ console.log(`
37823
+ ${c.step(" INDEX ")} ${c.primary("Analyzing codebase in")} ${c.bold(projectPath)}...`);
37824
+ try {
37825
+ const index = await indexer.index((msg) => console.log(` ${c.dim(msg)}`), (tree) => summarizer.summarize(tree));
37826
+ if (index) {
37827
+ indexer.saveIndex(index);
37828
+ }
37829
+ } catch (error48) {
37830
+ console.error(`
37831
+ ${c.error("✖")} ${c.error("Indexing failed:")} ${c.red(error48 instanceof Error ? error48.message : String(error48))}`);
37832
+ console.error(c.dim(` The agent might have limited context until indexing succeeds.
37833
+ `));
37834
+ }
37835
+ console.log(`
37836
+ ${c.success("✔")} ${c.success("Indexing complete!")}
37837
+ `);
37838
+ }
37839
+ async function execCommand(args) {
37840
+ const { values, positionals } = parseArgs({
37841
+ args,
37842
+ options: {
37843
+ model: { type: "string" },
37844
+ provider: { type: "string" },
37845
+ dir: { type: "string" }
37846
+ },
37847
+ strict: false
37848
+ });
37849
+ const promptInput = positionals.join(" ");
37850
+ if (!promptInput) {
37851
+ console.error(c.error('Error: Prompt is required. Usage: locus exec "your prompt"'));
37852
+ process.exit(1);
37853
+ }
37854
+ const projectPath = values.dir || process.cwd();
37855
+ requireInitialization(projectPath, "exec");
37856
+ const provider = resolveProvider2(values.provider);
37857
+ const model = values.model || DEFAULT_MODEL[provider];
37858
+ const aiRunner = createAiRunner(provider, {
37859
+ projectPath,
37860
+ model
37861
+ });
37862
+ const builder = new PromptBuilder(projectPath);
37863
+ const fullPrompt = await builder.buildGenericPrompt(promptInput);
37864
+ console.log(`
37865
+ ${c.primary("\uD83D\uDE80")} ${c.bold("Executing prompt with repository context...")}
37866
+ `);
37867
+ try {
37868
+ const result = await aiRunner.run(fullPrompt);
37869
+ console.log(result);
37870
+ console.log(`
37871
+ ${c.success("✔")} ${c.success("Execution finished!")}
37872
+ `);
37873
+ } catch (error48) {
37874
+ console.error(`
37875
+ ${c.error("✖")} ${c.error("Execution failed:")} ${c.red(error48 instanceof Error ? error48.message : String(error48))}
37876
+ `);
37877
+ process.exit(1);
37741
37878
  }
37742
- console.log(c.success("✅ Indexing complete!"));
37743
37879
  }
37744
37880
  async function initCommand() {
37745
37881
  const projectPath = process.cwd();
@@ -37755,19 +37891,19 @@ If you want to reinitialize, please remove the .locus directory first.
37755
37891
  }
37756
37892
  await new ConfigManager(projectPath).init(VERSION2);
37757
37893
  console.log(`
37758
- ${c.success("✨ Locus initialized successfully!")}
37894
+ ${c.success("✨ Locus initialized successfully!")}
37759
37895
 
37760
- Created:
37761
- \uD83D\uDCC1 ${c.dim(".locus/")} - Locus configuration directory
37762
- \uD83D\uDCC4 ${c.dim(".locus/config.json")} - Project configuration
37763
- \uD83D\uDCDD ${c.dim("CLAUDE.md")} - AI context file
37764
- \uD83D\uDCC1 ${c.dim(".agent/skills/")} - Agent skills (Frontend, Backend, DevOps, etc.)
37896
+ ${c.bold("Created:")}
37897
+ ${c.primary("\uD83D\uDCC1")} ${c.bold(".locus/")} ${c.dim("Configuration directory")}
37898
+ ${c.primary("\uD83D\uDCC4")} ${c.bold(".locus/config.json")} ${c.dim("Project settings")}
37899
+ ${c.primary("\uD83D\uDCDD")} ${c.bold("CLAUDE.md")} ${c.dim("AI instructions & context")}
37900
+ ${c.primary("\uD83D\uDCC1")} ${c.bold(".agent/skills/")} ${c.dim("Domain-specific agent skills")}
37765
37901
 
37766
- Next steps:
37767
- 1. Run '${c.primary("locus index")}' to index your codebase
37768
- 2. Run '${c.primary("locus run")}' to start an agent (requires --api-key)
37902
+ ${c.bold("Next steps:")}
37903
+ 1. Run '${c.primary("locus index")}' to index your codebase
37904
+ 2. Run '${c.primary("locus run")}' to start an agent (requires --api-key)
37769
37905
 
37770
- For more information, visit: ${c.underline("https://locusai.dev/docs")}
37906
+ For more information, visit: ${c.underline("https://locusai.dev/docs")}
37771
37907
  `);
37772
37908
  }
37773
37909
  async function main() {
@@ -37784,30 +37920,35 @@ async function main() {
37784
37920
  case "init":
37785
37921
  await initCommand();
37786
37922
  break;
37923
+ case "exec":
37924
+ await execCommand(args);
37925
+ break;
37787
37926
  default:
37788
37927
  console.log(`
37789
- Usage: locus <command>
37928
+ ${c.header(" USAGE ")}
37929
+ ${c.primary("locus")} ${c.dim("<command> [options]")}
37790
37930
 
37791
- Commands:
37792
- init Initialize Locus in the current directory
37793
- index Index the codebase for AI context
37794
- run Start an agent to work on tasks
37931
+ ${c.header(" COMMANDS ")}
37932
+ ${c.success("init")} Initialize Locus in the current directory
37933
+ ${c.success("index")} Index the codebase for AI context
37934
+ ${c.success("run")} Start an agent to work on tasks
37935
+ ${c.success("exec")} Run a prompt with repository context
37795
37936
 
37796
- Options:
37797
- --help Show this help message
37798
- --provider <name> AI provider: claude or codex (default: claude)
37799
- --skip-planning Skip the planning phase (CLI planning)
37937
+ ${c.header(" OPTIONS ")}
37938
+ ${c.secondary("--help")} Show this help message
37939
+ ${c.secondary("--provider")} <name> AI provider: ${c.dim("claude")} or ${c.dim("codex")} (default: ${c.dim("claude")})
37800
37940
 
37801
- Examples:
37802
- locus init
37803
- locus index
37804
- locus run --api-key YOUR_KEY
37941
+ ${c.header(" EXAMPLES ")}
37942
+ ${c.dim("$")} ${c.primary("locus init")}
37943
+ ${c.dim("$")} ${c.primary("locus index")}
37944
+ ${c.dim("$")} ${c.primary("locus run --api-key YOUR_KEY")}
37805
37945
 
37806
- For more information, visit: https://locusai.dev/docs
37946
+ For more information, visit: ${c.underline("https://locusai.dev/docs")}
37807
37947
  `);
37808
37948
  }
37809
37949
  }
37810
37950
  main().catch((err) => {
37811
- console.error(`Fatal error: ${err.message}`);
37951
+ console.error(`
37952
+ ${c.error("✖ Fatal Error")} ${c.red(err.message)}`);
37812
37953
  process.exit(1);
37813
37954
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@locusai/cli",
3
- "version": "0.7.0",
3
+ "version": "0.7.3",
4
4
  "description": "CLI for Locus - AI-native project management platform",
5
5
  "type": "module",
6
6
  "bin": {
@@ -32,7 +32,7 @@
32
32
  "author": "",
33
33
  "license": "MIT",
34
34
  "dependencies": {
35
- "@locusai/sdk": "^0.7.0"
35
+ "@locusai/sdk": "^0.7.3"
36
36
  },
37
37
  "devDependencies": {}
38
38
  }