@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.
- package/bin/agent/worker.js +49 -7
- package/bin/locus.js +120 -16
- package/package.json +2 -2
package/bin/agent/worker.js
CHANGED
|
@@ -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
|
|
17159
|
-
errorOutput +=
|
|
17160
|
-
|
|
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
|
|
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.
|
|
34874
|
+
apiKeyId: exports_external.string(),
|
|
34845
34875
|
apiKeyName: exports_external.string(),
|
|
34846
|
-
orgId: exports_external.
|
|
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.
|
|
30914
|
+
apiKeyId: exports_external.string(),
|
|
30915
30915
|
apiKeyName: exports_external.string(),
|
|
30916
|
-
orgId: exports_external.
|
|
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
|
|
32652
|
-
errorOutput +=
|
|
32653
|
-
|
|
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
|
|
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
|
-
|
|
37481
|
-
|
|
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)
|
|
37668
|
+
const configManager = new ConfigManager(projectPath);
|
|
37669
|
+
configManager.updateVersion(VERSION2);
|
|
37579
37670
|
const apiKey = values["api-key"];
|
|
37580
|
-
|
|
37671
|
+
let workspaceId = values.workspace;
|
|
37581
37672
|
const provider = resolveProvider2(values.provider);
|
|
37582
37673
|
const model = values.model || DEFAULT_MODEL[provider];
|
|
37583
|
-
|
|
37584
|
-
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
35
|
+
"@locusai/sdk": "^0.7.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {}
|
|
38
38
|
}
|