@locusai/cli 0.23.3 → 0.23.5
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 +232 -19
- package/package.json +2 -2
package/bin/locus.js
CHANGED
|
@@ -11282,6 +11282,7 @@ var exports_status = {};
|
|
|
11282
11282
|
__export(exports_status, {
|
|
11283
11283
|
statusCommand: () => statusCommand
|
|
11284
11284
|
});
|
|
11285
|
+
import { execSync as execSync18 } from "node:child_process";
|
|
11285
11286
|
async function statusCommand(projectRoot) {
|
|
11286
11287
|
const config = loadConfig(projectRoot);
|
|
11287
11288
|
const spinner = new Spinner;
|
|
@@ -11362,12 +11363,223 @@ async function statusCommand(projectRoot) {
|
|
|
11362
11363
|
}
|
|
11363
11364
|
}
|
|
11364
11365
|
} catch {}
|
|
11366
|
+
const agents = getActiveAgents(config.sandbox);
|
|
11367
|
+
if (agents.length > 0) {
|
|
11368
|
+
lines.push("");
|
|
11369
|
+
lines.push(` ${bold2("Agents:")}`);
|
|
11370
|
+
for (const agent of agents) {
|
|
11371
|
+
const icon = agent.status === "running" ? green("●") : dim2("○");
|
|
11372
|
+
const details = [agent.provider];
|
|
11373
|
+
if (agent.sandbox)
|
|
11374
|
+
details.push(dim2(`sandbox:${agent.sandbox}`));
|
|
11375
|
+
if (agent.pid)
|
|
11376
|
+
details.push(dim2(`pid:${agent.pid}`));
|
|
11377
|
+
if (agent.uptime)
|
|
11378
|
+
details.push(dim2(agent.uptime));
|
|
11379
|
+
if (agent.memory)
|
|
11380
|
+
details.push(dim2(agent.memory));
|
|
11381
|
+
lines.push(` ${icon} ${cyan2(agent.provider)} ${details.slice(1).join(" ")}`);
|
|
11382
|
+
if (agent.sandboxProcesses && agent.sandboxProcesses.length > 0) {
|
|
11383
|
+
for (const proc of agent.sandboxProcesses) {
|
|
11384
|
+
lines.push(` ${dim2("└")} ${yellow2(proc.name)} ${dim2(`pid:${proc.pid}`)}`);
|
|
11385
|
+
}
|
|
11386
|
+
} else if (agent.sandbox && agent.status === "running") {
|
|
11387
|
+
lines.push(` ${dim2("└ no agent processes detected")}`);
|
|
11388
|
+
}
|
|
11389
|
+
}
|
|
11390
|
+
}
|
|
11391
|
+
const registry = loadRegistry();
|
|
11392
|
+
const entries = Object.values(registry.packages);
|
|
11393
|
+
if (entries.length > 0) {
|
|
11394
|
+
const pm2Processes = getPm2Processes();
|
|
11395
|
+
lines.push("");
|
|
11396
|
+
lines.push(` ${bold2("Packages:")}`);
|
|
11397
|
+
for (const entry of entries) {
|
|
11398
|
+
const shortName = extractShortName(entry.name);
|
|
11399
|
+
const processName = `locus-${shortName}`;
|
|
11400
|
+
const proc = pm2Processes.find((p) => p.name === processName);
|
|
11401
|
+
const statusStr = proc ? proc.status === "online" ? green("online") : proc.status === "stopped" ? dim2("stopped") : yellow2(proc.status) : dim2("not running");
|
|
11402
|
+
const details = [`v${entry.version}`, statusStr];
|
|
11403
|
+
if (proc?.pid) {
|
|
11404
|
+
details.push(dim2(`pid:${proc.pid}`));
|
|
11405
|
+
}
|
|
11406
|
+
if (proc?.uptime) {
|
|
11407
|
+
details.push(dim2(formatUptime(proc.uptime)));
|
|
11408
|
+
}
|
|
11409
|
+
if (proc?.memory) {
|
|
11410
|
+
details.push(dim2(`${(proc.memory / (1024 * 1024)).toFixed(0)}MB`));
|
|
11411
|
+
}
|
|
11412
|
+
lines.push(` ${proc?.status === "online" ? green("●") : dim2("○")} ${cyan2(shortName)} ${details.join(" ")}`);
|
|
11413
|
+
}
|
|
11414
|
+
}
|
|
11365
11415
|
spinner.stop();
|
|
11366
11416
|
lines.push("");
|
|
11367
11417
|
process.stderr.write(`
|
|
11368
11418
|
${drawBox(lines, { title: "Locus Status" })}
|
|
11369
11419
|
`);
|
|
11370
11420
|
}
|
|
11421
|
+
function getPm2Processes() {
|
|
11422
|
+
try {
|
|
11423
|
+
const output = execSync18("npx pm2 jlist", {
|
|
11424
|
+
encoding: "utf-8",
|
|
11425
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
11426
|
+
timeout: 5000
|
|
11427
|
+
});
|
|
11428
|
+
const processes = JSON.parse(output);
|
|
11429
|
+
return processes.map((p) => ({
|
|
11430
|
+
name: p.name,
|
|
11431
|
+
status: p.pm2_env?.status ?? "unknown",
|
|
11432
|
+
pid: p.pid ?? null,
|
|
11433
|
+
uptime: p.pm2_env?.pm_uptime ?? null,
|
|
11434
|
+
memory: p.monit?.memory ?? null
|
|
11435
|
+
}));
|
|
11436
|
+
} catch {
|
|
11437
|
+
return [];
|
|
11438
|
+
}
|
|
11439
|
+
}
|
|
11440
|
+
function getActiveAgents(sandboxConfig) {
|
|
11441
|
+
const agents = [];
|
|
11442
|
+
if (sandboxConfig.enabled) {
|
|
11443
|
+
const sandboxes = getSandboxProcesses();
|
|
11444
|
+
for (const [provider, name] of Object.entries(sandboxConfig.providers)) {
|
|
11445
|
+
if (!name)
|
|
11446
|
+
continue;
|
|
11447
|
+
const sb = sandboxes.find((s) => s.name === name);
|
|
11448
|
+
const isRunning = !!sb && sb.status === "running";
|
|
11449
|
+
let sandboxProcesses;
|
|
11450
|
+
if (isRunning) {
|
|
11451
|
+
sandboxProcesses = getProcessesInsideSandbox(name);
|
|
11452
|
+
}
|
|
11453
|
+
agents.push({
|
|
11454
|
+
provider,
|
|
11455
|
+
status: isRunning ? "running" : "stopped",
|
|
11456
|
+
sandbox: name,
|
|
11457
|
+
sandboxProcesses
|
|
11458
|
+
});
|
|
11459
|
+
}
|
|
11460
|
+
} else {
|
|
11461
|
+
const procs = getAgentProcesses();
|
|
11462
|
+
agents.push(...procs);
|
|
11463
|
+
}
|
|
11464
|
+
return agents;
|
|
11465
|
+
}
|
|
11466
|
+
function getSandboxProcesses() {
|
|
11467
|
+
try {
|
|
11468
|
+
const output = execSync18("docker sandbox ls", {
|
|
11469
|
+
encoding: "utf-8",
|
|
11470
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
11471
|
+
timeout: 5000
|
|
11472
|
+
});
|
|
11473
|
+
const lines = output.trim().split(`
|
|
11474
|
+
`);
|
|
11475
|
+
if (lines.length < 2)
|
|
11476
|
+
return [];
|
|
11477
|
+
const header = lines[0];
|
|
11478
|
+
const statusIdx = header.search(/\bSTATUS\b/i);
|
|
11479
|
+
return lines.slice(1).map((line) => {
|
|
11480
|
+
const parts = line.trim().split(/\s+/);
|
|
11481
|
+
const name = parts[0] ?? "";
|
|
11482
|
+
let status = "";
|
|
11483
|
+
if (statusIdx >= 0 && line.length > statusIdx) {
|
|
11484
|
+
const rest = line.substring(statusIdx).trim();
|
|
11485
|
+
status = (rest.split(/\s+/)[0] ?? "").toLowerCase();
|
|
11486
|
+
} else {
|
|
11487
|
+
status = (parts[parts.length - 2] ?? parts[1] ?? "").toLowerCase();
|
|
11488
|
+
}
|
|
11489
|
+
return { name, status };
|
|
11490
|
+
}).filter((s) => s.name.length > 0);
|
|
11491
|
+
} catch {
|
|
11492
|
+
return [];
|
|
11493
|
+
}
|
|
11494
|
+
}
|
|
11495
|
+
function getProcessesInsideSandbox(sandboxName) {
|
|
11496
|
+
try {
|
|
11497
|
+
const output = execSync18(`docker sandbox exec ${sandboxName} sh -c "ps -eo pid,pcpu,pmem,args"`, {
|
|
11498
|
+
encoding: "utf-8",
|
|
11499
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
11500
|
+
timeout: 1e4
|
|
11501
|
+
});
|
|
11502
|
+
const lines = output.trim().split(`
|
|
11503
|
+
`).slice(1);
|
|
11504
|
+
const processes = [];
|
|
11505
|
+
for (const line of lines) {
|
|
11506
|
+
const lower = line.toLowerCase();
|
|
11507
|
+
let agentName;
|
|
11508
|
+
if (lower.includes("claude"))
|
|
11509
|
+
agentName = "claude";
|
|
11510
|
+
else if (lower.includes("codex"))
|
|
11511
|
+
agentName = "codex";
|
|
11512
|
+
if (!agentName)
|
|
11513
|
+
continue;
|
|
11514
|
+
const pidMatch = line.trim().match(/^(\d+)/);
|
|
11515
|
+
if (!pidMatch)
|
|
11516
|
+
continue;
|
|
11517
|
+
processes.push({
|
|
11518
|
+
name: agentName,
|
|
11519
|
+
pid: pidMatch[1],
|
|
11520
|
+
command: ""
|
|
11521
|
+
});
|
|
11522
|
+
}
|
|
11523
|
+
return processes;
|
|
11524
|
+
} catch {
|
|
11525
|
+
return [];
|
|
11526
|
+
}
|
|
11527
|
+
}
|
|
11528
|
+
function getAgentProcesses() {
|
|
11529
|
+
const agents = [];
|
|
11530
|
+
try {
|
|
11531
|
+
const output = execSync18("ps -eo pid,pcpu,pmem,args", {
|
|
11532
|
+
encoding: "utf-8",
|
|
11533
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
11534
|
+
timeout: 5000
|
|
11535
|
+
});
|
|
11536
|
+
const lines = output.trim().split(`
|
|
11537
|
+
`).slice(1);
|
|
11538
|
+
const providerMatches = {};
|
|
11539
|
+
for (const line of lines) {
|
|
11540
|
+
const trimmed = line.trim();
|
|
11541
|
+
if (!trimmed)
|
|
11542
|
+
continue;
|
|
11543
|
+
const match = trimmed.match(/^(\d+)\s+([\d.]+)\s+([\d.]+)\s+(.+)$/);
|
|
11544
|
+
if (!match)
|
|
11545
|
+
continue;
|
|
11546
|
+
const [, pid, cpu, mem, command] = match;
|
|
11547
|
+
const cmdLower = command.toLowerCase();
|
|
11548
|
+
if (cmdLower.includes("ps -eo") || cmdLower.includes("grep") || cmdLower.includes("locus status") || cmdLower.includes("locus-cli"))
|
|
11549
|
+
continue;
|
|
11550
|
+
for (const provider of ["claude", "codex"]) {
|
|
11551
|
+
if (providerMatches[provider])
|
|
11552
|
+
continue;
|
|
11553
|
+
const binPattern = new RegExp(`(^|/)${provider}(\\s|$|-)`);
|
|
11554
|
+
if (binPattern.test(command)) {
|
|
11555
|
+
providerMatches[provider] = { pid, cpu, mem, command };
|
|
11556
|
+
}
|
|
11557
|
+
}
|
|
11558
|
+
}
|
|
11559
|
+
for (const [provider, info] of Object.entries(providerMatches)) {
|
|
11560
|
+
agents.push({
|
|
11561
|
+
provider,
|
|
11562
|
+
status: "running",
|
|
11563
|
+
pid: info.pid,
|
|
11564
|
+
memory: info.mem !== "0.0" ? `${info.mem}%` : undefined
|
|
11565
|
+
});
|
|
11566
|
+
}
|
|
11567
|
+
} catch {}
|
|
11568
|
+
return agents;
|
|
11569
|
+
}
|
|
11570
|
+
function formatUptime(pmUptime) {
|
|
11571
|
+
const seconds = Math.floor((Date.now() - pmUptime) / 1000);
|
|
11572
|
+
if (seconds < 60)
|
|
11573
|
+
return `${seconds}s`;
|
|
11574
|
+
const minutes = Math.floor(seconds / 60);
|
|
11575
|
+
if (minutes < 60)
|
|
11576
|
+
return `${minutes}m`;
|
|
11577
|
+
const hours = Math.floor(minutes / 60);
|
|
11578
|
+
if (hours < 24)
|
|
11579
|
+
return `${hours}h ${minutes % 60}m`;
|
|
11580
|
+
const days = Math.floor(hours / 24);
|
|
11581
|
+
return `${days}d ${hours % 24}h`;
|
|
11582
|
+
}
|
|
11371
11583
|
var init_status = __esm(() => {
|
|
11372
11584
|
init_config();
|
|
11373
11585
|
init_github();
|
|
@@ -11375,6 +11587,7 @@ var init_status = __esm(() => {
|
|
|
11375
11587
|
init_worktree();
|
|
11376
11588
|
init_progress();
|
|
11377
11589
|
init_terminal();
|
|
11590
|
+
init_registry();
|
|
11378
11591
|
});
|
|
11379
11592
|
|
|
11380
11593
|
// src/commands/plan.ts
|
|
@@ -12039,7 +12252,7 @@ var exports_review = {};
|
|
|
12039
12252
|
__export(exports_review, {
|
|
12040
12253
|
reviewCommand: () => reviewCommand
|
|
12041
12254
|
});
|
|
12042
|
-
import { execFileSync as execFileSync2, execSync as
|
|
12255
|
+
import { execFileSync as execFileSync2, execSync as execSync19 } from "node:child_process";
|
|
12043
12256
|
import { existsSync as existsSync23, readFileSync as readFileSync14 } from "node:fs";
|
|
12044
12257
|
import { join as join23 } from "node:path";
|
|
12045
12258
|
function printHelp3() {
|
|
@@ -12125,7 +12338,7 @@ ${bold2("Review complete:")} ${green(`✓ ${reviewed}`)}${failed > 0 ? ` ${red2(
|
|
|
12125
12338
|
async function reviewSinglePR(projectRoot, config, prNumber, focus, flags) {
|
|
12126
12339
|
let prInfo;
|
|
12127
12340
|
try {
|
|
12128
|
-
const result =
|
|
12341
|
+
const result = execSync19(`gh pr view ${prNumber} --json number,title,body,state,headRefName,baseRefName,labels,url,createdAt`, { cwd: projectRoot, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
12129
12342
|
const raw = JSON.parse(result);
|
|
12130
12343
|
prInfo = {
|
|
12131
12344
|
number: raw.number,
|
|
@@ -12273,7 +12486,7 @@ var exports_iterate = {};
|
|
|
12273
12486
|
__export(exports_iterate, {
|
|
12274
12487
|
iterateCommand: () => iterateCommand
|
|
12275
12488
|
});
|
|
12276
|
-
import { execSync as
|
|
12489
|
+
import { execSync as execSync20 } from "node:child_process";
|
|
12277
12490
|
function printHelp4() {
|
|
12278
12491
|
process.stderr.write(`
|
|
12279
12492
|
${bold2("locus iterate")} — Re-execute tasks with PR feedback
|
|
@@ -12491,12 +12704,12 @@ ${bold2("Summary:")} ${green(`✓ ${succeeded}`)}${failed > 0 ? ` ${red2(`✗ ${
|
|
|
12491
12704
|
}
|
|
12492
12705
|
function findPRForIssue(projectRoot, issueNumber) {
|
|
12493
12706
|
try {
|
|
12494
|
-
const result =
|
|
12707
|
+
const result = execSync20(`gh pr list --search "Closes #${issueNumber}" --json number --state open`, { cwd: projectRoot, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
12495
12708
|
const parsed = JSON.parse(result);
|
|
12496
12709
|
if (parsed.length > 0) {
|
|
12497
12710
|
return parsed[0].number;
|
|
12498
12711
|
}
|
|
12499
|
-
const branchResult =
|
|
12712
|
+
const branchResult = execSync20(`gh pr list --head "locus/issue-${issueNumber}" --json number --state open`, { cwd: projectRoot, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
12500
12713
|
const branchParsed = JSON.parse(branchResult);
|
|
12501
12714
|
if (branchParsed.length > 0) {
|
|
12502
12715
|
return branchParsed[0].number;
|
|
@@ -13125,7 +13338,7 @@ var exports_commit = {};
|
|
|
13125
13338
|
__export(exports_commit, {
|
|
13126
13339
|
commitCommand: () => commitCommand
|
|
13127
13340
|
});
|
|
13128
|
-
import { execSync as
|
|
13341
|
+
import { execSync as execSync21 } from "node:child_process";
|
|
13129
13342
|
function printCommitHelp() {
|
|
13130
13343
|
process.stderr.write(`
|
|
13131
13344
|
${bold2("locus commit")} — AI-powered commit message generation
|
|
@@ -13159,7 +13372,7 @@ async function commitCommand(projectRoot, args, flags = {}) {
|
|
|
13159
13372
|
const config = loadConfig(projectRoot);
|
|
13160
13373
|
let stagedDiff;
|
|
13161
13374
|
try {
|
|
13162
|
-
stagedDiff =
|
|
13375
|
+
stagedDiff = execSync21("git diff --cached", {
|
|
13163
13376
|
cwd: projectRoot,
|
|
13164
13377
|
encoding: "utf-8",
|
|
13165
13378
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -13176,7 +13389,7 @@ async function commitCommand(projectRoot, args, flags = {}) {
|
|
|
13176
13389
|
}
|
|
13177
13390
|
let stagedStat;
|
|
13178
13391
|
try {
|
|
13179
|
-
stagedStat =
|
|
13392
|
+
stagedStat = execSync21("git diff --cached --stat", {
|
|
13180
13393
|
cwd: projectRoot,
|
|
13181
13394
|
encoding: "utf-8",
|
|
13182
13395
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -13186,7 +13399,7 @@ async function commitCommand(projectRoot, args, flags = {}) {
|
|
|
13186
13399
|
}
|
|
13187
13400
|
let recentCommits;
|
|
13188
13401
|
try {
|
|
13189
|
-
recentCommits =
|
|
13402
|
+
recentCommits = execSync21("git log --oneline -10", {
|
|
13190
13403
|
cwd: projectRoot,
|
|
13191
13404
|
encoding: "utf-8",
|
|
13192
13405
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -13246,7 +13459,7 @@ Co-Authored-By: LocusAgent <agent@locusai.team>`;
|
|
|
13246
13459
|
return;
|
|
13247
13460
|
}
|
|
13248
13461
|
try {
|
|
13249
|
-
|
|
13462
|
+
execSync21("git commit -F -", {
|
|
13250
13463
|
input: fullMessage,
|
|
13251
13464
|
cwd: projectRoot,
|
|
13252
13465
|
encoding: "utf-8",
|
|
@@ -13317,7 +13530,7 @@ __export(exports_sandbox2, {
|
|
|
13317
13530
|
parseSandboxLogsArgs: () => parseSandboxLogsArgs,
|
|
13318
13531
|
parseSandboxInstallArgs: () => parseSandboxInstallArgs
|
|
13319
13532
|
});
|
|
13320
|
-
import { execSync as
|
|
13533
|
+
import { execSync as execSync22, spawn as spawn7 } from "node:child_process";
|
|
13321
13534
|
import { createHash } from "node:crypto";
|
|
13322
13535
|
import { existsSync as existsSync26, readFileSync as readFileSync17 } from "node:fs";
|
|
13323
13536
|
import { basename as basename4, join as join26 } from "node:path";
|
|
@@ -13562,7 +13775,7 @@ function handleRemove(projectRoot) {
|
|
|
13562
13775
|
process.stderr.write(`Removing sandbox ${bold2(sandboxName)}...
|
|
13563
13776
|
`);
|
|
13564
13777
|
try {
|
|
13565
|
-
|
|
13778
|
+
execSync22(`docker sandbox rm ${sandboxName}`, {
|
|
13566
13779
|
encoding: "utf-8",
|
|
13567
13780
|
stdio: ["pipe", "pipe", "pipe"],
|
|
13568
13781
|
timeout: 15000
|
|
@@ -13885,7 +14098,7 @@ function getInstallCommand(pm) {
|
|
|
13885
14098
|
function verifyBinEntries(sandboxName, workdir) {
|
|
13886
14099
|
try {
|
|
13887
14100
|
const binDir = `${workdir}/node_modules/.bin/`;
|
|
13888
|
-
const result =
|
|
14101
|
+
const result = execSync22(`docker sandbox exec --privileged ${sandboxName} sh -c ${JSON.stringify(`ls ${JSON.stringify(binDir)} 2>/dev/null | head -20`)}`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 5000 }).trim();
|
|
13889
14102
|
if (!result) {
|
|
13890
14103
|
process.stderr.write(`${yellow2("⚠")} node_modules/.bin is empty — binaries like biome may not be available.
|
|
13891
14104
|
`);
|
|
@@ -14059,7 +14272,7 @@ function runInteractiveCommand(command, args) {
|
|
|
14059
14272
|
}
|
|
14060
14273
|
async function createProviderSandbox(provider, sandboxName, projectRoot) {
|
|
14061
14274
|
try {
|
|
14062
|
-
|
|
14275
|
+
execSync22(`docker sandbox create --name ${sandboxName} claude ${projectRoot}`, {
|
|
14063
14276
|
stdio: ["pipe", "pipe", "pipe"],
|
|
14064
14277
|
timeout: 120000
|
|
14065
14278
|
});
|
|
@@ -14074,7 +14287,7 @@ async function createProviderSandbox(provider, sandboxName, projectRoot) {
|
|
|
14074
14287
|
}
|
|
14075
14288
|
async function ensurePackageManagerInSandbox(sandboxName, pm) {
|
|
14076
14289
|
try {
|
|
14077
|
-
|
|
14290
|
+
execSync22(`docker sandbox exec --privileged ${sandboxName} which ${pm}`, {
|
|
14078
14291
|
stdio: ["pipe", "pipe", "pipe"],
|
|
14079
14292
|
timeout: 5000
|
|
14080
14293
|
});
|
|
@@ -14083,7 +14296,7 @@ async function ensurePackageManagerInSandbox(sandboxName, pm) {
|
|
|
14083
14296
|
process.stderr.write(`Installing ${bold2(pm)} in sandbox...
|
|
14084
14297
|
`);
|
|
14085
14298
|
try {
|
|
14086
|
-
|
|
14299
|
+
execSync22(`docker sandbox exec --privileged ${sandboxName} npm install -g ${npmPkg}`, {
|
|
14087
14300
|
stdio: "inherit",
|
|
14088
14301
|
timeout: 120000
|
|
14089
14302
|
});
|
|
@@ -14095,7 +14308,7 @@ async function ensurePackageManagerInSandbox(sandboxName, pm) {
|
|
|
14095
14308
|
}
|
|
14096
14309
|
async function ensureCodexInSandbox(sandboxName) {
|
|
14097
14310
|
try {
|
|
14098
|
-
|
|
14311
|
+
execSync22(`docker sandbox exec --privileged ${sandboxName} which codex`, {
|
|
14099
14312
|
stdio: ["pipe", "pipe", "pipe"],
|
|
14100
14313
|
timeout: 5000
|
|
14101
14314
|
});
|
|
@@ -14103,7 +14316,7 @@ async function ensureCodexInSandbox(sandboxName) {
|
|
|
14103
14316
|
process.stderr.write(`Installing codex in sandbox...
|
|
14104
14317
|
`);
|
|
14105
14318
|
try {
|
|
14106
|
-
|
|
14319
|
+
execSync22(`docker sandbox exec --privileged ${sandboxName} npm install -g @openai/codex`, { stdio: "inherit", timeout: 120000 });
|
|
14107
14320
|
} catch {
|
|
14108
14321
|
process.stderr.write(`${red2("✗")} Failed to install codex in sandbox.
|
|
14109
14322
|
`);
|
|
@@ -14112,7 +14325,7 @@ async function ensureCodexInSandbox(sandboxName) {
|
|
|
14112
14325
|
}
|
|
14113
14326
|
function isSandboxAlive(name) {
|
|
14114
14327
|
try {
|
|
14115
|
-
const output =
|
|
14328
|
+
const output = execSync22("docker sandbox ls", {
|
|
14116
14329
|
encoding: "utf-8",
|
|
14117
14330
|
stdio: ["pipe", "pipe", "pipe"],
|
|
14118
14331
|
timeout: 5000
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@locusai/cli",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.5",
|
|
4
4
|
"description": "GitHub-native AI engineering assistant",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"license": "MIT",
|
|
37
37
|
"dependencies": {},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@locusai/sdk": "^0.23.
|
|
39
|
+
"@locusai/sdk": "^0.23.5",
|
|
40
40
|
"@types/bun": "latest",
|
|
41
41
|
"typescript": "^5.8.3"
|
|
42
42
|
},
|