@locusai/cli 0.6.0 → 0.7.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.
@@ -17143,6 +17143,7 @@ class ClaudeRunner {
17143
17143
  let finalResult = "";
17144
17144
  let errorOutput = "";
17145
17145
  let buffer = "";
17146
+ let stderrBuffer = "";
17146
17147
  claude.stdout.on("data", (data) => {
17147
17148
  buffer += data.toString();
17148
17149
  const lines = buffer.split(`
@@ -17155,14 +17156,27 @@ class ClaudeRunner {
17155
17156
  }
17156
17157
  });
17157
17158
  claude.stderr.on("data", (data) => {
17158
- const msg = data.toString();
17159
- errorOutput += msg;
17160
- process.stderr.write(msg);
17159
+ const chunk = data.toString();
17160
+ errorOutput += chunk;
17161
+ stderrBuffer += chunk;
17162
+ const lines = stderrBuffer.split(`
17163
+ `);
17164
+ stderrBuffer = lines.pop() || "";
17165
+ for (const line of lines) {
17166
+ if (!this.shouldSuppressLine(line)) {
17167
+ process.stderr.write(`${line}
17168
+ `);
17169
+ }
17170
+ }
17161
17171
  });
17162
17172
  claude.on("error", (err) => {
17163
17173
  reject(new Error(`Failed to start Claude CLI: ${err.message}. Please ensure the 'claude' command is available in your PATH.`));
17164
17174
  });
17165
17175
  claude.on("close", (code) => {
17176
+ if (stderrBuffer && !this.shouldSuppressLine(stderrBuffer)) {
17177
+ process.stderr.write(`${stderrBuffer}
17178
+ `);
17179
+ }
17166
17180
  process.stdout.write(`
17167
17181
  `);
17168
17182
  if (code === 0) {
@@ -17205,6 +17219,10 @@ ${c.primary("[Claude]")} ${c.bold(`Running ${content_block.name}...`)}
17205
17219
  }
17206
17220
  }
17207
17221
  }
17222
+ shouldSuppressLine(line) {
17223
+ const infoLogRegex = /^\[\d{2}:\d{2}:\d{2}\]\s\[.*?\]\sℹ\s*$/;
17224
+ return infoLogRegex.test(line.trim());
17225
+ }
17208
17226
  createExecutionError(code, detail) {
17209
17227
  const errorMsg = detail.trim();
17210
17228
  const message = errorMsg ? `Claude CLI error (exit code ${code}): ${errorMsg}` : `Claude CLI exited with code ${code}. Please ensure the Claude CLI is installed and you are logged in.`;
@@ -20771,7 +20789,15 @@ class BaseModule {
20771
20789
  // ../sdk/src/modules/ai.ts
20772
20790
  class AIModule extends BaseModule {
20773
20791
  async chat(workspaceId, body) {
20774
- const { data } = await this.api.post(`/ai/${workspaceId}/chat`, body);
20792
+ const { data } = await this.api.post(`/ai/${workspaceId}/chat`, body, { timeout: 300000 });
20793
+ return data;
20794
+ }
20795
+ async detectIntent(workspaceId, body) {
20796
+ const { data } = await this.api.post(`/ai/${workspaceId}/chat/intent`, body, { timeout: 300000 });
20797
+ return data;
20798
+ }
20799
+ async executeIntent(workspaceId, body) {
20800
+ const { data } = await this.api.post(`/ai/${workspaceId}/chat/execute`, body, { timeout: 300000 });
20775
20801
  return data;
20776
20802
  }
20777
20803
  async listSessions(workspaceId) {
@@ -20792,10 +20818,14 @@ class AIModule extends BaseModule {
20792
20818
 
20793
20819
  // ../sdk/src/modules/auth.ts
20794
20820
  class AuthModule extends BaseModule {
20795
- async getMe() {
20821
+ async getProfile() {
20796
20822
  const { data } = await this.api.get("/auth/me");
20797
20823
  return data;
20798
20824
  }
20825
+ async getApiKeyInfo() {
20826
+ const { data } = await this.api.get("/auth/api-key");
20827
+ return data;
20828
+ }
20799
20829
  async requestRegisterOtp(email) {
20800
20830
  const { data } = await this.api.post("/auth/register-otp", { email });
20801
20831
  return data;
@@ -34841,9 +34871,10 @@ var JwtAuthUserSchema = exports_external.object({
34841
34871
  });
34842
34872
  var ApiKeyAuthUserSchema = exports_external.object({
34843
34873
  authType: exports_external.literal("api_key"),
34844
- apiKeyId: exports_external.uuid(),
34874
+ apiKeyId: exports_external.string(),
34845
34875
  apiKeyName: exports_external.string(),
34846
- orgId: exports_external.uuid()
34876
+ orgId: exports_external.string().optional(),
34877
+ workspaceId: exports_external.string().optional()
34847
34878
  });
34848
34879
  var AuthenticatedUserSchema = exports_external.discriminatedUnion("authType", [
34849
34880
  JwtAuthUserSchema,
@@ -35344,6 +35375,17 @@ class WorkspacesModule extends BaseModule {
35344
35375
  const { data } = await this.api.post(`/workspaces/${id}/dispatch`, { workerId, sprintId });
35345
35376
  return data.task;
35346
35377
  }
35378
+ async listApiKeys(workspaceId) {
35379
+ const { data } = await this.api.get(`/workspaces/${workspaceId}/api-keys`);
35380
+ return data.apiKeys;
35381
+ }
35382
+ async createApiKey(workspaceId, name) {
35383
+ const { data } = await this.api.post(`/workspaces/${workspaceId}/api-keys`, { name });
35384
+ return data.apiKey;
35385
+ }
35386
+ async deleteApiKey(workspaceId, keyId) {
35387
+ await this.api.delete(`/workspaces/${workspaceId}/api-keys/${keyId}`);
35388
+ }
35347
35389
  }
35348
35390
 
35349
35391
  // ../sdk/src/index.ts
package/bin/locus.js CHANGED
@@ -30911,9 +30911,10 @@ var JwtAuthUserSchema = exports_external.object({
30911
30911
  });
30912
30912
  var ApiKeyAuthUserSchema = exports_external.object({
30913
30913
  authType: exports_external.literal("api_key"),
30914
- apiKeyId: exports_external.uuid(),
30914
+ apiKeyId: exports_external.string(),
30915
30915
  apiKeyName: exports_external.string(),
30916
- orgId: exports_external.uuid()
30916
+ orgId: exports_external.string().optional(),
30917
+ workspaceId: exports_external.string().optional()
30917
30918
  });
30918
30919
  var AuthenticatedUserSchema = exports_external.discriminatedUnion("authType", [
30919
30920
  JwtAuthUserSchema,
@@ -32636,6 +32637,7 @@ class ClaudeRunner {
32636
32637
  let finalResult = "";
32637
32638
  let errorOutput = "";
32638
32639
  let buffer = "";
32640
+ let stderrBuffer = "";
32639
32641
  claude.stdout.on("data", (data) => {
32640
32642
  buffer += data.toString();
32641
32643
  const lines = buffer.split(`
@@ -32648,14 +32650,27 @@ class ClaudeRunner {
32648
32650
  }
32649
32651
  });
32650
32652
  claude.stderr.on("data", (data) => {
32651
- const msg = data.toString();
32652
- errorOutput += msg;
32653
- process.stderr.write(msg);
32653
+ const chunk = data.toString();
32654
+ errorOutput += chunk;
32655
+ stderrBuffer += chunk;
32656
+ const lines = stderrBuffer.split(`
32657
+ `);
32658
+ stderrBuffer = lines.pop() || "";
32659
+ for (const line of lines) {
32660
+ if (!this.shouldSuppressLine(line)) {
32661
+ process.stderr.write(`${line}
32662
+ `);
32663
+ }
32664
+ }
32654
32665
  });
32655
32666
  claude.on("error", (err) => {
32656
32667
  reject(new Error(`Failed to start Claude CLI: ${err.message}. Please ensure the 'claude' command is available in your PATH.`));
32657
32668
  });
32658
32669
  claude.on("close", (code) => {
32670
+ if (stderrBuffer && !this.shouldSuppressLine(stderrBuffer)) {
32671
+ process.stderr.write(`${stderrBuffer}
32672
+ `);
32673
+ }
32659
32674
  process.stdout.write(`
32660
32675
  `);
32661
32676
  if (code === 0) {
@@ -32698,6 +32713,10 @@ ${c.primary("[Claude]")} ${c.bold(`Running ${content_block.name}...`)}
32698
32713
  }
32699
32714
  }
32700
32715
  }
32716
+ shouldSuppressLine(line) {
32717
+ const infoLogRegex = /^\[\d{2}:\d{2}:\d{2}\]\s\[.*?\]\sℹ\s*$/;
32718
+ return infoLogRegex.test(line.trim());
32719
+ }
32701
32720
  createExecutionError(code, detail) {
32702
32721
  const errorMsg = detail.trim();
32703
32722
  const message = errorMsg ? `Claude CLI error (exit code ${code}): ${errorMsg}` : `Claude CLI exited with code ${code}. Please ensure the Claude CLI is installed and you are logged in.`;
@@ -36264,7 +36283,15 @@ class BaseModule {
36264
36283
  // ../sdk/src/modules/ai.ts
36265
36284
  class AIModule extends BaseModule {
36266
36285
  async chat(workspaceId, body) {
36267
- const { data } = await this.api.post(`/ai/${workspaceId}/chat`, body);
36286
+ const { data } = await this.api.post(`/ai/${workspaceId}/chat`, body, { timeout: 300000 });
36287
+ return data;
36288
+ }
36289
+ async detectIntent(workspaceId, body) {
36290
+ const { data } = await this.api.post(`/ai/${workspaceId}/chat/intent`, body, { timeout: 300000 });
36291
+ return data;
36292
+ }
36293
+ async executeIntent(workspaceId, body) {
36294
+ const { data } = await this.api.post(`/ai/${workspaceId}/chat/execute`, body, { timeout: 300000 });
36268
36295
  return data;
36269
36296
  }
36270
36297
  async listSessions(workspaceId) {
@@ -36285,10 +36312,14 @@ class AIModule extends BaseModule {
36285
36312
 
36286
36313
  // ../sdk/src/modules/auth.ts
36287
36314
  class AuthModule extends BaseModule {
36288
- async getMe() {
36315
+ async getProfile() {
36289
36316
  const { data } = await this.api.get("/auth/me");
36290
36317
  return data;
36291
36318
  }
36319
+ async getApiKeyInfo() {
36320
+ const { data } = await this.api.get("/auth/api-key");
36321
+ return data;
36322
+ }
36292
36323
  async requestRegisterOtp(email3) {
36293
36324
  const { data } = await this.api.post("/auth/register-otp", { email: email3 });
36294
36325
  return data;
@@ -36551,6 +36582,17 @@ class WorkspacesModule extends BaseModule {
36551
36582
  const { data } = await this.api.post(`/workspaces/${id}/dispatch`, { workerId, sprintId });
36552
36583
  return data.task;
36553
36584
  }
36585
+ async listApiKeys(workspaceId) {
36586
+ const { data } = await this.api.get(`/workspaces/${workspaceId}/api-keys`);
36587
+ return data.apiKeys;
36588
+ }
36589
+ async createApiKey(workspaceId, name) {
36590
+ const { data } = await this.api.post(`/workspaces/${workspaceId}/api-keys`, { name });
36591
+ return data.apiKey;
36592
+ }
36593
+ async deleteApiKey(workspaceId, keyId) {
36594
+ await this.api.delete(`/workspaces/${workspaceId}/api-keys/${keyId}`);
36595
+ }
36554
36596
  }
36555
36597
 
36556
36598
  // ../sdk/src/index.ts
@@ -37477,10 +37519,23 @@ class ConfigManager {
37477
37519
  const config2 = this.loadConfig();
37478
37520
  if (config2 && config2.version !== version2) {
37479
37521
  config2.version = version2;
37480
- const path2 = getLocusPath(this.projectPath, "configFile");
37481
- writeFileSync3(path2, JSON.stringify(config2, null, 2));
37522
+ this.saveConfig(config2);
37523
+ }
37524
+ }
37525
+ getWorkspaceId() {
37526
+ return this.loadConfig()?.workspaceId;
37527
+ }
37528
+ setWorkspaceId(workspaceId) {
37529
+ const config2 = this.loadConfig();
37530
+ if (config2) {
37531
+ config2.workspaceId = workspaceId;
37532
+ this.saveConfig(config2);
37482
37533
  }
37483
37534
  }
37535
+ saveConfig(config2) {
37536
+ const path2 = getLocusPath(this.projectPath, "configFile");
37537
+ writeFileSync3(path2, JSON.stringify(config2, null, 2));
37538
+ }
37484
37539
  }
37485
37540
 
37486
37541
  // src/tree-summarizer.ts
@@ -37507,6 +37562,41 @@ ${tree}`;
37507
37562
  }
37508
37563
  }
37509
37564
 
37565
+ // src/workspace-resolver.ts
37566
+ class WorkspaceResolver {
37567
+ configManager;
37568
+ options;
37569
+ constructor(configManager, options) {
37570
+ this.configManager = configManager;
37571
+ this.options = options;
37572
+ }
37573
+ async resolve() {
37574
+ if (this.options.workspaceId) {
37575
+ return this.options.workspaceId;
37576
+ }
37577
+ const persistedId = this.configManager.getWorkspaceId();
37578
+ if (persistedId) {
37579
+ return persistedId;
37580
+ }
37581
+ try {
37582
+ console.log(c.dim("ℹ Resolving workspace from API key..."));
37583
+ const client = new LocusClient({
37584
+ baseUrl: this.options.apiBase,
37585
+ token: this.options.apiKey
37586
+ });
37587
+ const info = await client.auth.getApiKeyInfo();
37588
+ if (info.workspaceId) {
37589
+ this.configManager.setWorkspaceId(info.workspaceId);
37590
+ console.log(c.success(`✓ Resolved workspace: ${info.workspaceId}`));
37591
+ return info.workspaceId;
37592
+ }
37593
+ throw new Error("API key is not associated with a workspace. Please specify --workspace.");
37594
+ } catch (error48) {
37595
+ throw new Error(`Error resolving workspace: ${error48 instanceof Error ? error48.message : String(error48)}`);
37596
+ }
37597
+ }
37598
+ }
37599
+
37510
37600
  // src/cli.ts
37511
37601
  function getVersion() {
37512
37602
  try {
@@ -37575,13 +37665,27 @@ async function runCommand(args) {
37575
37665
  });
37576
37666
  const projectPath = values.dir || process.cwd();
37577
37667
  requireInitialization(projectPath, "run");
37578
- new ConfigManager(projectPath).updateVersion(VERSION2);
37668
+ const configManager = new ConfigManager(projectPath);
37669
+ configManager.updateVersion(VERSION2);
37579
37670
  const apiKey = values["api-key"];
37580
- const workspaceId = values.workspace;
37671
+ let workspaceId = values.workspace;
37581
37672
  const provider = resolveProvider2(values.provider);
37582
37673
  const model = values.model || DEFAULT_MODEL[provider];
37583
- if (!apiKey || !workspaceId) {
37584
- console.error(c.error("Error: --api-key and --workspace are required"));
37674
+ const apiBase = values["api-url"] || "https://api.locusai.dev/api";
37675
+ if (!apiKey) {
37676
+ console.error(c.error("Error: --api-key is required"));
37677
+ console.error(c.dim("You can create an API key in Workspace Settings > API Keys"));
37678
+ process.exit(1);
37679
+ }
37680
+ try {
37681
+ const resolver = new WorkspaceResolver(configManager, {
37682
+ apiKey,
37683
+ apiBase,
37684
+ workspaceId: values.workspace
37685
+ });
37686
+ workspaceId = await resolver.resolve();
37687
+ } catch (error48) {
37688
+ console.error(c.error(error48 instanceof Error ? error48.message : String(error48)));
37585
37689
  process.exit(1);
37586
37690
  }
37587
37691
  const orchestrator = new AgentOrchestrator({
@@ -37589,7 +37693,7 @@ async function runCommand(args) {
37589
37693
  sprintId: values.sprint || "",
37590
37694
  model,
37591
37695
  provider,
37592
- apiBase: values["api-url"] || "https://api.locusai.dev/api",
37696
+ apiBase,
37593
37697
  maxIterations: 100,
37594
37698
  projectPath,
37595
37699
  apiKey,
@@ -37661,7 +37765,7 @@ Created:
37661
37765
 
37662
37766
  Next steps:
37663
37767
  1. Run '${c.primary("locus index")}' to index your codebase
37664
- 2. Run '${c.primary("locus run")}' to start an agent (requires --api-key and --workspace)
37768
+ 2. Run '${c.primary("locus run")}' to start an agent (requires --api-key)
37665
37769
 
37666
37770
  For more information, visit: ${c.underline("https://locusai.dev/docs")}
37667
37771
  `);
@@ -37697,7 +37801,7 @@ Options:
37697
37801
  Examples:
37698
37802
  locus init
37699
37803
  locus index
37700
- locus run --api-key YOUR_KEY --workspace WORKSPACE_ID
37804
+ locus run --api-key YOUR_KEY
37701
37805
 
37702
37806
  For more information, visit: https://locusai.dev/docs
37703
37807
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@locusai/cli",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
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.6.0"
35
+ "@locusai/sdk": "^0.7.0"
36
36
  },
37
37
  "devDependencies": {}
38
38
  }