@locusai/cli 0.25.2 → 0.25.4
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 +277 -88
- package/package.json +2 -2
package/bin/locus.js
CHANGED
|
@@ -3352,46 +3352,155 @@ var init_lock = __esm(() => {
|
|
|
3352
3352
|
});
|
|
3353
3353
|
|
|
3354
3354
|
// src/skills/installer.ts
|
|
3355
|
-
import {
|
|
3355
|
+
import {
|
|
3356
|
+
existsSync as existsSync11,
|
|
3357
|
+
mkdirSync as mkdirSync8,
|
|
3358
|
+
readFileSync as readFileSync8,
|
|
3359
|
+
renameSync as renameSync2,
|
|
3360
|
+
rmSync,
|
|
3361
|
+
writeFileSync as writeFileSync8
|
|
3362
|
+
} from "node:fs";
|
|
3363
|
+
import { tmpdir } from "node:os";
|
|
3356
3364
|
import { join as join11 } from "node:path";
|
|
3357
3365
|
async function installSkill(projectRoot, name, content, source) {
|
|
3358
3366
|
const claudeDir = join11(projectRoot, CLAUDE_SKILLS_DIR, name);
|
|
3359
3367
|
const agentsDir = join11(projectRoot, AGENTS_SKILLS_DIR, name);
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3368
|
+
const stagingDir = join11(tmpdir(), `locus-skill-${name}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
|
|
3369
|
+
const stagingClaudeDir = join11(stagingDir, "claude");
|
|
3370
|
+
const stagingAgentsDir = join11(stagingDir, "agents");
|
|
3371
|
+
let wroteClaudeDir = false;
|
|
3372
|
+
let wroteAgentsDir = false;
|
|
3373
|
+
try {
|
|
3374
|
+
try {
|
|
3375
|
+
mkdirSync8(stagingClaudeDir, { recursive: true });
|
|
3376
|
+
mkdirSync8(stagingAgentsDir, { recursive: true });
|
|
3377
|
+
writeFileSync8(join11(stagingClaudeDir, "SKILL.md"), content, "utf-8");
|
|
3378
|
+
writeFileSync8(join11(stagingAgentsDir, "SKILL.md"), content, "utf-8");
|
|
3379
|
+
} catch (err) {
|
|
3380
|
+
throw new SkillInstallError(name, "stage", err);
|
|
3381
|
+
}
|
|
3382
|
+
try {
|
|
3383
|
+
if (!content || content.trim().length === 0) {
|
|
3384
|
+
throw new Error("Skill content is empty");
|
|
3385
|
+
}
|
|
3386
|
+
const expectedHash = computeSkillHash(content);
|
|
3387
|
+
const stagedContent = readFileSync8(join11(stagingClaudeDir, "SKILL.md"), "utf-8");
|
|
3388
|
+
const stagedHash = computeSkillHash(stagedContent);
|
|
3389
|
+
if (stagedHash !== expectedHash) {
|
|
3390
|
+
throw new Error("Staged file hash does not match expected content");
|
|
3391
|
+
}
|
|
3392
|
+
} catch (err) {
|
|
3393
|
+
if (err instanceof SkillInstallError)
|
|
3394
|
+
throw err;
|
|
3395
|
+
throw new SkillInstallError(name, "validate", err);
|
|
3396
|
+
}
|
|
3397
|
+
try {
|
|
3398
|
+
mkdirSync8(join11(projectRoot, CLAUDE_SKILLS_DIR), { recursive: true });
|
|
3399
|
+
mkdirSync8(join11(projectRoot, AGENTS_SKILLS_DIR), { recursive: true });
|
|
3400
|
+
if (existsSync11(claudeDir)) {
|
|
3401
|
+
rmSync(claudeDir, { recursive: true, force: true });
|
|
3402
|
+
}
|
|
3403
|
+
if (existsSync11(agentsDir)) {
|
|
3404
|
+
rmSync(agentsDir, { recursive: true, force: true });
|
|
3405
|
+
}
|
|
3406
|
+
try {
|
|
3407
|
+
renameSync2(stagingClaudeDir, claudeDir);
|
|
3408
|
+
wroteClaudeDir = true;
|
|
3409
|
+
} catch {
|
|
3410
|
+
mkdirSync8(claudeDir, { recursive: true });
|
|
3411
|
+
writeFileSync8(join11(claudeDir, "SKILL.md"), content, "utf-8");
|
|
3412
|
+
wroteClaudeDir = true;
|
|
3413
|
+
}
|
|
3414
|
+
try {
|
|
3415
|
+
renameSync2(stagingAgentsDir, agentsDir);
|
|
3416
|
+
wroteAgentsDir = true;
|
|
3417
|
+
} catch {
|
|
3418
|
+
mkdirSync8(agentsDir, { recursive: true });
|
|
3419
|
+
writeFileSync8(join11(agentsDir, "SKILL.md"), content, "utf-8");
|
|
3420
|
+
wroteAgentsDir = true;
|
|
3421
|
+
}
|
|
3422
|
+
} catch (err) {
|
|
3423
|
+
if (err instanceof SkillInstallError)
|
|
3424
|
+
throw err;
|
|
3425
|
+
throw new SkillInstallError(name, "write", err);
|
|
3426
|
+
}
|
|
3427
|
+
try {
|
|
3428
|
+
const lock = readLockFile(projectRoot);
|
|
3429
|
+
lock.skills[name] = {
|
|
3430
|
+
source,
|
|
3431
|
+
sourceType: "github",
|
|
3432
|
+
computedHash: computeSkillHash(content)
|
|
3433
|
+
};
|
|
3434
|
+
writeLockFile(projectRoot, lock);
|
|
3435
|
+
} catch (err) {
|
|
3436
|
+
throw new SkillInstallError(name, "register", err);
|
|
3437
|
+
}
|
|
3438
|
+
} catch (err) {
|
|
3439
|
+
if (wroteClaudeDir && existsSync11(claudeDir)) {
|
|
3440
|
+
rmSync(claudeDir, { recursive: true, force: true });
|
|
3441
|
+
}
|
|
3442
|
+
if (wroteAgentsDir && existsSync11(agentsDir)) {
|
|
3443
|
+
rmSync(agentsDir, { recursive: true, force: true });
|
|
3444
|
+
}
|
|
3445
|
+
throw err;
|
|
3446
|
+
} finally {
|
|
3447
|
+
if (existsSync11(stagingDir)) {
|
|
3448
|
+
rmSync(stagingDir, { recursive: true, force: true });
|
|
3449
|
+
}
|
|
3450
|
+
}
|
|
3371
3451
|
}
|
|
3372
3452
|
async function removeSkill(projectRoot, name) {
|
|
3373
|
-
|
|
3453
|
+
const claudeDir = join11(projectRoot, CLAUDE_SKILLS_DIR, name);
|
|
3454
|
+
const agentsDir = join11(projectRoot, AGENTS_SKILLS_DIR, name);
|
|
3455
|
+
const lock = readLockFile(projectRoot);
|
|
3456
|
+
const inLockFile = name in lock.skills;
|
|
3457
|
+
const hasClaude = existsSync11(claudeDir);
|
|
3458
|
+
const hasAgents = existsSync11(agentsDir);
|
|
3459
|
+
if (!inLockFile && !hasClaude && !hasAgents) {
|
|
3374
3460
|
console.warn(`Skill "${name}" is not installed.`);
|
|
3375
3461
|
return;
|
|
3376
3462
|
}
|
|
3377
|
-
|
|
3378
|
-
const agentsDir = join11(projectRoot, AGENTS_SKILLS_DIR, name);
|
|
3379
|
-
if (existsSync11(claudeDir)) {
|
|
3463
|
+
if (hasClaude) {
|
|
3380
3464
|
rmSync(claudeDir, { recursive: true, force: true });
|
|
3381
3465
|
}
|
|
3382
|
-
if (
|
|
3466
|
+
if (hasAgents) {
|
|
3383
3467
|
rmSync(agentsDir, { recursive: true, force: true });
|
|
3384
3468
|
}
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3469
|
+
if (inLockFile) {
|
|
3470
|
+
delete lock.skills[name];
|
|
3471
|
+
writeLockFile(projectRoot, lock);
|
|
3472
|
+
}
|
|
3388
3473
|
}
|
|
3389
3474
|
function isSkillInstalled(projectRoot, name) {
|
|
3390
3475
|
const lock = readLockFile(projectRoot);
|
|
3391
3476
|
return name in lock.skills;
|
|
3392
3477
|
}
|
|
3478
|
+
function hasOrphanedSkillFiles(projectRoot, name) {
|
|
3479
|
+
const claudeDir = join11(projectRoot, CLAUDE_SKILLS_DIR, name);
|
|
3480
|
+
const agentsDir = join11(projectRoot, AGENTS_SKILLS_DIR, name);
|
|
3481
|
+
const inLockFile = isSkillInstalled(projectRoot, name);
|
|
3482
|
+
return !inLockFile && (existsSync11(claudeDir) || existsSync11(agentsDir));
|
|
3483
|
+
}
|
|
3484
|
+
var SkillInstallError;
|
|
3393
3485
|
var init_installer = __esm(() => {
|
|
3394
3486
|
init_lock();
|
|
3487
|
+
SkillInstallError = class SkillInstallError extends Error {
|
|
3488
|
+
skillName;
|
|
3489
|
+
step;
|
|
3490
|
+
constructor(skillName, step, cause) {
|
|
3491
|
+
const stepLabel = {
|
|
3492
|
+
stage: "staging files to temp directory",
|
|
3493
|
+
validate: "validating skill content",
|
|
3494
|
+
write: "writing skill files to project",
|
|
3495
|
+
register: "updating skills-lock.json"
|
|
3496
|
+
};
|
|
3497
|
+
const reason = cause instanceof Error ? cause.message : String(cause ?? "");
|
|
3498
|
+
super(`Failed to install '${skillName}' during ${stepLabel[step]}${reason ? `: ${reason}` : ""}`);
|
|
3499
|
+
this.skillName = skillName;
|
|
3500
|
+
this.step = step;
|
|
3501
|
+
this.name = "SkillInstallError";
|
|
3502
|
+
}
|
|
3503
|
+
};
|
|
3395
3504
|
});
|
|
3396
3505
|
|
|
3397
3506
|
// src/skills/registry.ts
|
|
@@ -3565,7 +3674,22 @@ async function installRemoteSkill(name) {
|
|
|
3565
3674
|
}
|
|
3566
3675
|
const cwd = process.cwd();
|
|
3567
3676
|
const source = `${REGISTRY_REPO}/${entry.path}`;
|
|
3568
|
-
|
|
3677
|
+
try {
|
|
3678
|
+
await installSkill(cwd, name, content, source);
|
|
3679
|
+
} catch (err) {
|
|
3680
|
+
if (err instanceof SkillInstallError) {
|
|
3681
|
+
process.stderr.write(`${red2("✗")} ${err.message}
|
|
3682
|
+
`);
|
|
3683
|
+
process.stderr.write(` To clean up and retry: ${bold2(`locus skills remove ${name}`)} then ${bold2(`locus skills install ${name}`)}
|
|
3684
|
+
`);
|
|
3685
|
+
} else {
|
|
3686
|
+
process.stderr.write(`${red2("✗")} Unexpected error installing skill '${name}'.
|
|
3687
|
+
`);
|
|
3688
|
+
process.stderr.write(` ${dim2(err.message)}
|
|
3689
|
+
`);
|
|
3690
|
+
}
|
|
3691
|
+
process.exit(1);
|
|
3692
|
+
}
|
|
3569
3693
|
process.stderr.write(`
|
|
3570
3694
|
${green("✓")} Installed skill '${bold2(name)}' from ${REGISTRY_REPO}
|
|
3571
3695
|
`);
|
|
@@ -3584,7 +3708,9 @@ async function removeInstalledSkill(name) {
|
|
|
3584
3708
|
process.exit(1);
|
|
3585
3709
|
}
|
|
3586
3710
|
const cwd = process.cwd();
|
|
3587
|
-
|
|
3711
|
+
const installed = isSkillInstalled(cwd, name);
|
|
3712
|
+
const orphaned = hasOrphanedSkillFiles(cwd, name);
|
|
3713
|
+
if (!installed && !orphaned) {
|
|
3588
3714
|
process.stderr.write(`${red2("✗")} Skill '${bold2(name)}' is not installed.
|
|
3589
3715
|
`);
|
|
3590
3716
|
process.stderr.write(` Run ${bold2("locus skills list --installed")} to see installed skills.
|
|
@@ -3592,8 +3718,13 @@ async function removeInstalledSkill(name) {
|
|
|
3592
3718
|
process.exit(1);
|
|
3593
3719
|
}
|
|
3594
3720
|
await removeSkill(cwd, name);
|
|
3595
|
-
|
|
3721
|
+
if (orphaned) {
|
|
3722
|
+
process.stderr.write(`${green("✓")} Cleaned up orphaned skill files for '${bold2(name)}'
|
|
3723
|
+
`);
|
|
3724
|
+
} else {
|
|
3725
|
+
process.stderr.write(`${green("✓")} Removed skill '${bold2(name)}'
|
|
3596
3726
|
`);
|
|
3727
|
+
}
|
|
3597
3728
|
}
|
|
3598
3729
|
async function updateSkills(name) {
|
|
3599
3730
|
const cwd = process.cwd();
|
|
@@ -3649,7 +3780,20 @@ async function updateSkills(name) {
|
|
|
3649
3780
|
continue;
|
|
3650
3781
|
}
|
|
3651
3782
|
const source = `${REGISTRY_REPO}/${entry.path}`;
|
|
3652
|
-
|
|
3783
|
+
try {
|
|
3784
|
+
await installSkill(cwd, skillName, content, source);
|
|
3785
|
+
} catch (err) {
|
|
3786
|
+
if (err instanceof SkillInstallError) {
|
|
3787
|
+
process.stderr.write(`${red2("✗")} ${err.message}
|
|
3788
|
+
`);
|
|
3789
|
+
process.stderr.write(` To clean up: ${bold2(`locus skills remove ${skillName}`)}
|
|
3790
|
+
`);
|
|
3791
|
+
} else {
|
|
3792
|
+
process.stderr.write(`${red2("✗")} Failed to update '${skillName}': ${dim2(err.message)}
|
|
3793
|
+
`);
|
|
3794
|
+
}
|
|
3795
|
+
continue;
|
|
3796
|
+
}
|
|
3653
3797
|
updatedCount++;
|
|
3654
3798
|
process.stderr.write(`${green("✓")} Updated '${bold2(skillName)}' (hash changed)
|
|
3655
3799
|
`);
|
|
@@ -3743,7 +3887,7 @@ ${bold2("Subcommands:")}
|
|
|
3743
3887
|
${cyan2("list")} List available skills from the registry
|
|
3744
3888
|
${cyan2("list")} ${dim2("--installed")} List locally installed skills
|
|
3745
3889
|
${cyan2("install")} ${dim2("<name>")} Install a skill from the registry
|
|
3746
|
-
${cyan2("remove")} ${dim2("<name>")} Remove an installed skill
|
|
3890
|
+
${cyan2("remove")} ${dim2("<name>")} Remove an installed skill (alias: ${cyan2("uninstall")})
|
|
3747
3891
|
${cyan2("update")} ${dim2("[name]")} Update installed skill(s) from registry
|
|
3748
3892
|
${cyan2("info")} ${dim2("<name>")} Show skill metadata and install status
|
|
3749
3893
|
|
|
@@ -3778,7 +3922,8 @@ async function skillsCommand(args, flags) {
|
|
|
3778
3922
|
await installRemoteSkill(skillName);
|
|
3779
3923
|
break;
|
|
3780
3924
|
}
|
|
3781
|
-
case "remove":
|
|
3925
|
+
case "remove":
|
|
3926
|
+
case "uninstall": {
|
|
3782
3927
|
const skillName = args[1];
|
|
3783
3928
|
await removeInstalledSkill(skillName);
|
|
3784
3929
|
break;
|
|
@@ -3796,7 +3941,7 @@ async function skillsCommand(args, flags) {
|
|
|
3796
3941
|
default:
|
|
3797
3942
|
process.stderr.write(`${red2("✗")} Unknown subcommand: ${bold2(subcommand)}
|
|
3798
3943
|
`);
|
|
3799
|
-
process.stderr.write(` Available: ${bold2("list")}, ${bold2("install")}, ${bold2("remove")}, ${bold2("update")}, ${bold2("info")}
|
|
3944
|
+
process.stderr.write(` Available: ${bold2("list")}, ${bold2("install")}, ${bold2("remove")} (${bold2("uninstall")}), ${bold2("update")}, ${bold2("info")}
|
|
3800
3945
|
`);
|
|
3801
3946
|
process.exit(1);
|
|
3802
3947
|
}
|
|
@@ -3947,7 +4092,7 @@ __export(exports_logs, {
|
|
|
3947
4092
|
import {
|
|
3948
4093
|
existsSync as existsSync12,
|
|
3949
4094
|
readdirSync as readdirSync2,
|
|
3950
|
-
readFileSync as
|
|
4095
|
+
readFileSync as readFileSync9,
|
|
3951
4096
|
statSync as statSync2,
|
|
3952
4097
|
unlinkSync as unlinkSync2
|
|
3953
4098
|
} from "node:fs";
|
|
@@ -3974,7 +4119,7 @@ async function logsCommand(cwd, options) {
|
|
|
3974
4119
|
return viewLog(logFiles[0], options.level, options.lines ?? 50);
|
|
3975
4120
|
}
|
|
3976
4121
|
function viewLog(logFile, levelFilter, maxLines) {
|
|
3977
|
-
const content =
|
|
4122
|
+
const content = readFileSync9(logFile, "utf-8");
|
|
3978
4123
|
const lines = content.trim().split(`
|
|
3979
4124
|
`).filter(Boolean);
|
|
3980
4125
|
process.stderr.write(`
|
|
@@ -4011,7 +4156,7 @@ async function tailLog(logFile, levelFilter) {
|
|
|
4011
4156
|
`);
|
|
4012
4157
|
let lastSize = existsSync12(logFile) ? statSync2(logFile).size : 0;
|
|
4013
4158
|
if (existsSync12(logFile)) {
|
|
4014
|
-
const content =
|
|
4159
|
+
const content = readFileSync9(logFile, "utf-8");
|
|
4015
4160
|
const lines = content.trim().split(`
|
|
4016
4161
|
`).filter(Boolean);
|
|
4017
4162
|
const recent = lines.slice(-10);
|
|
@@ -4034,7 +4179,7 @@ async function tailLog(logFile, levelFilter) {
|
|
|
4034
4179
|
const currentSize = statSync2(logFile).size;
|
|
4035
4180
|
if (currentSize <= lastSize)
|
|
4036
4181
|
return;
|
|
4037
|
-
const content =
|
|
4182
|
+
const content = readFileSync9(logFile, "utf-8");
|
|
4038
4183
|
const allLines = content.trim().split(`
|
|
4039
4184
|
`).filter(Boolean);
|
|
4040
4185
|
const oldContent = content.slice(0, lastSize);
|
|
@@ -4400,7 +4545,7 @@ var init_stream_renderer = __esm(() => {
|
|
|
4400
4545
|
// src/repl/clipboard.ts
|
|
4401
4546
|
import { execSync as execSync6 } from "node:child_process";
|
|
4402
4547
|
import { existsSync as existsSync13, mkdirSync as mkdirSync9 } from "node:fs";
|
|
4403
|
-
import { tmpdir } from "node:os";
|
|
4548
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
4404
4549
|
import { join as join13 } from "node:path";
|
|
4405
4550
|
function readClipboardImage() {
|
|
4406
4551
|
if (process.platform === "darwin") {
|
|
@@ -4466,12 +4611,12 @@ function readLinuxClipboardImage() {
|
|
|
4466
4611
|
}
|
|
4467
4612
|
var STABLE_DIR;
|
|
4468
4613
|
var init_clipboard = __esm(() => {
|
|
4469
|
-
STABLE_DIR = join13(
|
|
4614
|
+
STABLE_DIR = join13(tmpdir2(), "locus-images");
|
|
4470
4615
|
});
|
|
4471
4616
|
|
|
4472
4617
|
// src/repl/image-detect.ts
|
|
4473
4618
|
import { copyFileSync, existsSync as existsSync14, mkdirSync as mkdirSync10 } from "node:fs";
|
|
4474
|
-
import { homedir as homedir3, tmpdir as
|
|
4619
|
+
import { homedir as homedir3, tmpdir as tmpdir3 } from "node:os";
|
|
4475
4620
|
import { basename, extname, join as join14, resolve } from "node:path";
|
|
4476
4621
|
function detectImages(input) {
|
|
4477
4622
|
const detected = [];
|
|
@@ -4676,7 +4821,7 @@ var init_image_detect = __esm(() => {
|
|
|
4676
4821
|
".tif",
|
|
4677
4822
|
".tiff"
|
|
4678
4823
|
]);
|
|
4679
|
-
STABLE_DIR2 = join14(
|
|
4824
|
+
STABLE_DIR2 = join14(tmpdir3(), "locus-images");
|
|
4680
4825
|
PLACEHOLDER_ID_PATTERN = /\(locus:\/\/screenshot-(\d+)\)/g;
|
|
4681
4826
|
});
|
|
4682
4827
|
|
|
@@ -5689,17 +5834,17 @@ import {
|
|
|
5689
5834
|
mkdirSync as mkdirSync11,
|
|
5690
5835
|
mkdtempSync,
|
|
5691
5836
|
readdirSync as readdirSync3,
|
|
5692
|
-
readFileSync as
|
|
5837
|
+
readFileSync as readFileSync10,
|
|
5693
5838
|
rmSync as rmSync2,
|
|
5694
5839
|
statSync as statSync3
|
|
5695
5840
|
} from "node:fs";
|
|
5696
|
-
import { tmpdir as
|
|
5841
|
+
import { tmpdir as tmpdir4 } from "node:os";
|
|
5697
5842
|
import { dirname as dirname3, join as join15, relative } from "node:path";
|
|
5698
5843
|
import { promisify } from "node:util";
|
|
5699
5844
|
function parseIgnoreFile(filePath) {
|
|
5700
5845
|
if (!existsSync15(filePath))
|
|
5701
5846
|
return [];
|
|
5702
|
-
const content =
|
|
5847
|
+
const content = readFileSync10(filePath, "utf-8");
|
|
5703
5848
|
const rules = [];
|
|
5704
5849
|
for (const rawLine of content.split(`
|
|
5705
5850
|
`)) {
|
|
@@ -5810,7 +5955,7 @@ function backupIgnoredFiles(projectRoot) {
|
|
|
5810
5955
|
return NOOP_BACKUP;
|
|
5811
5956
|
let backupDir;
|
|
5812
5957
|
try {
|
|
5813
|
-
backupDir = mkdtempSync(join15(
|
|
5958
|
+
backupDir = mkdtempSync(join15(tmpdir4(), "locus-sandbox-backup-"));
|
|
5814
5959
|
} catch (err) {
|
|
5815
5960
|
log.debug("Failed to create sandbox backup dir", {
|
|
5816
5961
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -8028,7 +8173,7 @@ var init_sprint = __esm(() => {
|
|
|
8028
8173
|
|
|
8029
8174
|
// src/core/prompt-builder.ts
|
|
8030
8175
|
import { execSync as execSync9 } from "node:child_process";
|
|
8031
|
-
import { existsSync as existsSync16, readdirSync as readdirSync4, readFileSync as
|
|
8176
|
+
import { existsSync as existsSync16, readdirSync as readdirSync4, readFileSync as readFileSync11 } from "node:fs";
|
|
8032
8177
|
import { join as join16 } from "node:path";
|
|
8033
8178
|
function buildExecutionPrompt(ctx) {
|
|
8034
8179
|
const sections = [];
|
|
@@ -8256,7 +8401,7 @@ function readFileSafe(path) {
|
|
|
8256
8401
|
try {
|
|
8257
8402
|
if (!existsSync16(path))
|
|
8258
8403
|
return null;
|
|
8259
|
-
return
|
|
8404
|
+
return readFileSync11(path, "utf-8");
|
|
8260
8405
|
} catch {
|
|
8261
8406
|
return null;
|
|
8262
8407
|
}
|
|
@@ -8825,7 +8970,7 @@ class CombinedCompletion {
|
|
|
8825
8970
|
var init_completions = () => {};
|
|
8826
8971
|
|
|
8827
8972
|
// src/repl/input-history.ts
|
|
8828
|
-
import { existsSync as existsSync17, mkdirSync as mkdirSync12, readFileSync as
|
|
8973
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
|
|
8829
8974
|
import { dirname as dirname5, join as join18 } from "node:path";
|
|
8830
8975
|
|
|
8831
8976
|
class InputHistory {
|
|
@@ -8873,7 +9018,7 @@ class InputHistory {
|
|
|
8873
9018
|
try {
|
|
8874
9019
|
if (!existsSync17(this.filePath))
|
|
8875
9020
|
return;
|
|
8876
|
-
const content =
|
|
9021
|
+
const content = readFileSync12(this.filePath, "utf-8");
|
|
8877
9022
|
this.entries = content.split(`
|
|
8878
9023
|
`).map((line) => this.unescape(line)).filter(Boolean);
|
|
8879
9024
|
} catch {}
|
|
@@ -8915,7 +9060,7 @@ import {
|
|
|
8915
9060
|
existsSync as existsSync18,
|
|
8916
9061
|
mkdirSync as mkdirSync13,
|
|
8917
9062
|
readdirSync as readdirSync6,
|
|
8918
|
-
readFileSync as
|
|
9063
|
+
readFileSync as readFileSync13,
|
|
8919
9064
|
unlinkSync as unlinkSync3,
|
|
8920
9065
|
writeFileSync as writeFileSync10
|
|
8921
9066
|
} from "node:fs";
|
|
@@ -8958,7 +9103,7 @@ class SessionManager {
|
|
|
8958
9103
|
const exactPath = this.getSessionPath(idOrPrefix);
|
|
8959
9104
|
if (existsSync18(exactPath)) {
|
|
8960
9105
|
try {
|
|
8961
|
-
return JSON.parse(
|
|
9106
|
+
return JSON.parse(readFileSync13(exactPath, "utf-8"));
|
|
8962
9107
|
} catch {
|
|
8963
9108
|
return null;
|
|
8964
9109
|
}
|
|
@@ -8966,7 +9111,7 @@ class SessionManager {
|
|
|
8966
9111
|
const matches = files.filter((f) => basename3(f, ".json").startsWith(idOrPrefix));
|
|
8967
9112
|
if (matches.length === 1) {
|
|
8968
9113
|
try {
|
|
8969
|
-
return JSON.parse(
|
|
9114
|
+
return JSON.parse(readFileSync13(matches[0], "utf-8"));
|
|
8970
9115
|
} catch {
|
|
8971
9116
|
return null;
|
|
8972
9117
|
}
|
|
@@ -8991,7 +9136,7 @@ class SessionManager {
|
|
|
8991
9136
|
const sessions = [];
|
|
8992
9137
|
for (const file of files) {
|
|
8993
9138
|
try {
|
|
8994
|
-
const session = JSON.parse(
|
|
9139
|
+
const session = JSON.parse(readFileSync13(file, "utf-8"));
|
|
8995
9140
|
sessions.push({
|
|
8996
9141
|
id: session.id,
|
|
8997
9142
|
created: session.created,
|
|
@@ -9018,7 +9163,7 @@ class SessionManager {
|
|
|
9018
9163
|
let pruned = 0;
|
|
9019
9164
|
const withStats = files.map((f) => {
|
|
9020
9165
|
try {
|
|
9021
|
-
const session = JSON.parse(
|
|
9166
|
+
const session = JSON.parse(readFileSync13(f, "utf-8"));
|
|
9022
9167
|
return { path: f, updated: new Date(session.updated).getTime() };
|
|
9023
9168
|
} catch {
|
|
9024
9169
|
return { path: f, updated: 0 };
|
|
@@ -9072,7 +9217,7 @@ var init_session_manager = __esm(() => {
|
|
|
9072
9217
|
// src/repl/voice.ts
|
|
9073
9218
|
import { execSync as execSync11, spawn as spawn6 } from "node:child_process";
|
|
9074
9219
|
import { existsSync as existsSync19, mkdirSync as mkdirSync14, unlinkSync as unlinkSync4 } from "node:fs";
|
|
9075
|
-
import { cpus, homedir as homedir4, platform, tmpdir as
|
|
9220
|
+
import { cpus, homedir as homedir4, platform, tmpdir as tmpdir5 } from "node:os";
|
|
9076
9221
|
import { join as join20 } from "node:path";
|
|
9077
9222
|
function getWhisperModelPath() {
|
|
9078
9223
|
return join20(WHISPER_MODELS_DIR, `ggml-${WHISPER_MODEL}.bin`);
|
|
@@ -9284,7 +9429,7 @@ function ensureBuildDeps(pm) {
|
|
|
9284
9429
|
}
|
|
9285
9430
|
function buildWhisperFromSource(pm) {
|
|
9286
9431
|
const out = process.stderr;
|
|
9287
|
-
const buildDir = join20(
|
|
9432
|
+
const buildDir = join20(tmpdir5(), `locus-whisper-build-${process.pid}`);
|
|
9288
9433
|
if (!ensureBuildDeps(pm)) {
|
|
9289
9434
|
out.write(` ${red2("✗")} Could not install build tools (cmake, g++, git).
|
|
9290
9435
|
`);
|
|
@@ -9442,7 +9587,7 @@ class VoiceController {
|
|
|
9442
9587
|
onStateChange;
|
|
9443
9588
|
constructor(options) {
|
|
9444
9589
|
this.onStateChange = options.onStateChange;
|
|
9445
|
-
this.tempFile = join20(
|
|
9590
|
+
this.tempFile = join20(tmpdir5(), `locus-voice-${process.pid}.wav`);
|
|
9446
9591
|
this.deps = checkDependencies();
|
|
9447
9592
|
}
|
|
9448
9593
|
getState() {
|
|
@@ -10384,7 +10529,8 @@ ${green("✓")} Issue #${issueNumber} completed ${dim2(`(${timer.formatted()})`)
|
|
|
10384
10529
|
`);
|
|
10385
10530
|
let prNumber;
|
|
10386
10531
|
if (config.agent.autoPR && !options.skipPR) {
|
|
10387
|
-
|
|
10532
|
+
const workDir = options.worktreePath ?? projectRoot;
|
|
10533
|
+
prNumber = await createIssuePR(workDir, config, issue);
|
|
10388
10534
|
}
|
|
10389
10535
|
if (config.agent.autoLabel) {
|
|
10390
10536
|
try {
|
|
@@ -10465,29 +10611,56 @@ ${aiResult.success ? green("✓") : red2("✗")} Iteration ${aiResult.success ?
|
|
|
10465
10611
|
summary: extractSummary(aiResult.output)
|
|
10466
10612
|
};
|
|
10467
10613
|
}
|
|
10468
|
-
async function createIssuePR(
|
|
10614
|
+
async function createIssuePR(workDir, config, issue) {
|
|
10469
10615
|
try {
|
|
10616
|
+
try {
|
|
10617
|
+
commitDirtySubmodules(workDir, issue.number, issue.title);
|
|
10618
|
+
const status = execSync14("git status --porcelain", {
|
|
10619
|
+
cwd: workDir,
|
|
10620
|
+
encoding: "utf-8",
|
|
10621
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
10622
|
+
}).trim();
|
|
10623
|
+
if (status) {
|
|
10624
|
+
execSync14("git add -A", {
|
|
10625
|
+
cwd: workDir,
|
|
10626
|
+
encoding: "utf-8",
|
|
10627
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
10628
|
+
});
|
|
10629
|
+
const message = `chore: complete #${issue.number} - ${issue.title}
|
|
10630
|
+
|
|
10631
|
+
Co-Authored-By: LocusAgent <agent@locusai.team>`;
|
|
10632
|
+
execSync14("git commit -F -", {
|
|
10633
|
+
input: message,
|
|
10634
|
+
cwd: workDir,
|
|
10635
|
+
encoding: "utf-8",
|
|
10636
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
10637
|
+
});
|
|
10638
|
+
process.stderr.write(` ${dim2(`Committed uncommitted changes for #${issue.number}`)}
|
|
10639
|
+
`);
|
|
10640
|
+
}
|
|
10641
|
+
} catch {}
|
|
10470
10642
|
const currentBranch = execSync14("git rev-parse --abbrev-ref HEAD", {
|
|
10471
|
-
cwd:
|
|
10643
|
+
cwd: workDir,
|
|
10472
10644
|
encoding: "utf-8",
|
|
10473
10645
|
stdio: ["pipe", "pipe", "pipe"]
|
|
10474
10646
|
}).trim();
|
|
10475
10647
|
const diff = execSync14(`git diff origin/${config.agent.baseBranch}..HEAD --stat`, {
|
|
10476
|
-
cwd:
|
|
10648
|
+
cwd: workDir,
|
|
10477
10649
|
encoding: "utf-8",
|
|
10478
10650
|
stdio: ["pipe", "pipe", "pipe"]
|
|
10479
10651
|
}).trim();
|
|
10480
10652
|
if (!diff) {
|
|
10481
|
-
|
|
10653
|
+
process.stderr.write(` ${yellow2("⚠")} No changes detected — skipping PR creation
|
|
10654
|
+
`);
|
|
10482
10655
|
return;
|
|
10483
10656
|
}
|
|
10484
|
-
pushSubmoduleBranches(
|
|
10657
|
+
pushSubmoduleBranches(workDir);
|
|
10485
10658
|
execSync14(`git push -u origin ${currentBranch}`, {
|
|
10486
|
-
cwd:
|
|
10659
|
+
cwd: workDir,
|
|
10487
10660
|
encoding: "utf-8",
|
|
10488
10661
|
stdio: ["pipe", "pipe", "pipe"]
|
|
10489
10662
|
});
|
|
10490
|
-
const submoduleSummary = getSubmoduleChangeSummary(
|
|
10663
|
+
const submoduleSummary = getSubmoduleChangeSummary(workDir, config.agent.baseBranch);
|
|
10491
10664
|
let prBody = `Closes #${issue.number}`;
|
|
10492
10665
|
if (submoduleSummary) {
|
|
10493
10666
|
prBody += `
|
|
@@ -10502,7 +10675,7 @@ ${submoduleSummary}`;
|
|
|
10502
10675
|
const prTitle = `${issue.title} (#${issue.number})`;
|
|
10503
10676
|
let prNumber;
|
|
10504
10677
|
try {
|
|
10505
|
-
const existing = execSync14(`gh pr list --head ${currentBranch} --base ${config.agent.baseBranch} --json number --limit 1`, { cwd:
|
|
10678
|
+
const existing = execSync14(`gh pr list --head ${currentBranch} --base ${config.agent.baseBranch} --json number --limit 1`, { cwd: workDir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
10506
10679
|
const parsed = JSON.parse(existing);
|
|
10507
10680
|
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
10508
10681
|
prNumber = parsed[0].number;
|
|
@@ -10512,7 +10685,7 @@ ${submoduleSummary}`;
|
|
|
10512
10685
|
try {
|
|
10513
10686
|
execSync14(`gh pr edit ${prNumber} --title ${JSON.stringify(prTitle)} --body-file -`, {
|
|
10514
10687
|
input: prBody,
|
|
10515
|
-
cwd:
|
|
10688
|
+
cwd: workDir,
|
|
10516
10689
|
encoding: "utf-8",
|
|
10517
10690
|
stdio: ["pipe", "pipe", "pipe"]
|
|
10518
10691
|
});
|
|
@@ -10522,13 +10695,15 @@ ${submoduleSummary}`;
|
|
|
10522
10695
|
getLogger().warn(`Failed to update PR #${prNumber}: ${editErr}`);
|
|
10523
10696
|
}
|
|
10524
10697
|
} else {
|
|
10525
|
-
prNumber = createPR(prTitle, prBody, currentBranch, config.agent.baseBranch, { cwd:
|
|
10698
|
+
prNumber = createPR(prTitle, prBody, currentBranch, config.agent.baseBranch, { cwd: workDir });
|
|
10526
10699
|
process.stderr.write(` ${green("✓")} Created PR #${prNumber}
|
|
10527
10700
|
`);
|
|
10528
10701
|
}
|
|
10529
10702
|
return prNumber;
|
|
10530
10703
|
} catch (e) {
|
|
10531
|
-
|
|
10704
|
+
const errorMsg = e instanceof Error ? e.message : String(e);
|
|
10705
|
+
process.stderr.write(` ${red2("✗")} Failed to create PR: ${errorMsg}
|
|
10706
|
+
`);
|
|
10532
10707
|
return;
|
|
10533
10708
|
}
|
|
10534
10709
|
}
|
|
@@ -10693,7 +10868,7 @@ var init_conflict = __esm(() => {
|
|
|
10693
10868
|
import {
|
|
10694
10869
|
existsSync as existsSync21,
|
|
10695
10870
|
mkdirSync as mkdirSync15,
|
|
10696
|
-
readFileSync as
|
|
10871
|
+
readFileSync as readFileSync14,
|
|
10697
10872
|
unlinkSync as unlinkSync5,
|
|
10698
10873
|
writeFileSync as writeFileSync11
|
|
10699
10874
|
} from "node:fs";
|
|
@@ -10716,7 +10891,7 @@ function loadRunState(projectRoot, sprintName) {
|
|
|
10716
10891
|
if (!existsSync21(path))
|
|
10717
10892
|
return null;
|
|
10718
10893
|
try {
|
|
10719
|
-
return JSON.parse(
|
|
10894
|
+
return JSON.parse(readFileSync14(path, "utf-8"));
|
|
10720
10895
|
} catch {
|
|
10721
10896
|
getLogger().warn("Corrupted run state file, ignoring");
|
|
10722
10897
|
return null;
|
|
@@ -11508,7 +11683,7 @@ async function handleSingleIssue(projectRoot, config, issueNumber, flags, sandbo
|
|
|
11508
11683
|
${bold2("Running sprint issue")} ${cyan2(`#${issueNumber}`)} ${dim2("(sequential)")}
|
|
11509
11684
|
|
|
11510
11685
|
`);
|
|
11511
|
-
await executeIssue(projectRoot, {
|
|
11686
|
+
const result2 = await executeIssue(projectRoot, {
|
|
11512
11687
|
issueNumber,
|
|
11513
11688
|
provider: execution.provider,
|
|
11514
11689
|
model: execution.model,
|
|
@@ -11517,6 +11692,11 @@ ${bold2("Running sprint issue")} ${cyan2(`#${issueNumber}`)} ${dim2("(sequential
|
|
|
11517
11692
|
sandboxName: execution.sandboxName,
|
|
11518
11693
|
containerWorkdir: execution.containerWorkdir
|
|
11519
11694
|
});
|
|
11695
|
+
if (!result2.success) {
|
|
11696
|
+
process.stderr.write(`
|
|
11697
|
+
${red2("✗")} Issue #${issueNumber} execution failed${result2.error ? `: ${result2.error}` : ""}
|
|
11698
|
+
`);
|
|
11699
|
+
}
|
|
11520
11700
|
return;
|
|
11521
11701
|
}
|
|
11522
11702
|
const randomSuffix = Math.random().toString(36).slice(2, 8);
|
|
@@ -11559,6 +11739,15 @@ ${bold2("Running issue")} ${cyan2(`#${issueNumber}`)} ${dim2(`(branch: ${branchN
|
|
|
11559
11739
|
});
|
|
11560
11740
|
log.info(`Checked out ${config.agent.baseBranch}`);
|
|
11561
11741
|
} catch {}
|
|
11742
|
+
if (result.prNumber) {
|
|
11743
|
+
process.stderr.write(`
|
|
11744
|
+
${green("✓")} Issue #${issueNumber} done — PR #${result.prNumber} opened
|
|
11745
|
+
`);
|
|
11746
|
+
} else if (config.agent.autoPR) {
|
|
11747
|
+
process.stderr.write(`
|
|
11748
|
+
${yellow2("⚠")} Issue #${issueNumber} done — no PR was created (check errors above)
|
|
11749
|
+
`);
|
|
11750
|
+
}
|
|
11562
11751
|
} else {
|
|
11563
11752
|
process.stderr.write(` ${yellow2("⚠")} Branch ${dim2(branchName)} preserved for debugging.
|
|
11564
11753
|
`);
|
|
@@ -12302,7 +12491,7 @@ import {
|
|
|
12302
12491
|
existsSync as existsSync25,
|
|
12303
12492
|
mkdirSync as mkdirSync17,
|
|
12304
12493
|
readdirSync as readdirSync8,
|
|
12305
|
-
readFileSync as
|
|
12494
|
+
readFileSync as readFileSync15,
|
|
12306
12495
|
writeFileSync as writeFileSync12
|
|
12307
12496
|
} from "node:fs";
|
|
12308
12497
|
import { join as join26 } from "node:path";
|
|
@@ -12358,7 +12547,7 @@ function loadPlanFile(projectRoot, id) {
|
|
|
12358
12547
|
if (!match)
|
|
12359
12548
|
return null;
|
|
12360
12549
|
try {
|
|
12361
|
-
const content =
|
|
12550
|
+
const content = readFileSync15(join26(dir, match), "utf-8");
|
|
12362
12551
|
return JSON.parse(content);
|
|
12363
12552
|
} catch {
|
|
12364
12553
|
return null;
|
|
@@ -12443,7 +12632,7 @@ ${bold2("Saved Plans:")}
|
|
|
12443
12632
|
for (const file of files) {
|
|
12444
12633
|
const id = file.replace(".json", "");
|
|
12445
12634
|
try {
|
|
12446
|
-
const content =
|
|
12635
|
+
const content = readFileSync15(join26(dir, file), "utf-8");
|
|
12447
12636
|
const plan = JSON.parse(content);
|
|
12448
12637
|
const date = plan.createdAt ? plan.createdAt.slice(0, 10) : "";
|
|
12449
12638
|
const issueCount = Array.isArray(plan.issues) ? plan.issues.length : 0;
|
|
@@ -12558,7 +12747,7 @@ ${yellow2("⚠")} Plan file was not found at ${bold2(planPathRelative)}.
|
|
|
12558
12747
|
}
|
|
12559
12748
|
let updatedPlan;
|
|
12560
12749
|
try {
|
|
12561
|
-
const content =
|
|
12750
|
+
const content = readFileSync15(planPath, "utf-8");
|
|
12562
12751
|
updatedPlan = JSON.parse(content);
|
|
12563
12752
|
} catch {
|
|
12564
12753
|
process.stderr.write(`
|
|
@@ -12701,7 +12890,7 @@ ${yellow2("⚠")} Plan file was not created at ${bold2(planPathRelative)}.
|
|
|
12701
12890
|
}
|
|
12702
12891
|
let plan;
|
|
12703
12892
|
try {
|
|
12704
|
-
const content =
|
|
12893
|
+
const content = readFileSync15(planPath, "utf-8");
|
|
12705
12894
|
plan = JSON.parse(content);
|
|
12706
12895
|
} catch {
|
|
12707
12896
|
process.stderr.write(`
|
|
@@ -12875,14 +13064,14 @@ ${directive}${sprintName ? `
|
|
|
12875
13064
|
</directive>`);
|
|
12876
13065
|
const locusPath = join26(projectRoot, ".locus", "LOCUS.md");
|
|
12877
13066
|
if (existsSync25(locusPath)) {
|
|
12878
|
-
const content =
|
|
13067
|
+
const content = readFileSync15(locusPath, "utf-8");
|
|
12879
13068
|
parts.push(`<project-context>
|
|
12880
13069
|
${content.slice(0, 3000)}
|
|
12881
13070
|
</project-context>`);
|
|
12882
13071
|
}
|
|
12883
13072
|
const learningsPath = join26(projectRoot, ".locus", "LEARNINGS.md");
|
|
12884
13073
|
if (existsSync25(learningsPath)) {
|
|
12885
|
-
const content =
|
|
13074
|
+
const content = readFileSync15(learningsPath, "utf-8");
|
|
12886
13075
|
parts.push(`<past-learnings>
|
|
12887
13076
|
${content.slice(0, 2000)}
|
|
12888
13077
|
</past-learnings>`);
|
|
@@ -12936,7 +13125,7 @@ ${feedback}
|
|
|
12936
13125
|
</feedback>`);
|
|
12937
13126
|
const locusPath = join26(projectRoot, ".locus", "LOCUS.md");
|
|
12938
13127
|
if (existsSync25(locusPath)) {
|
|
12939
|
-
const content =
|
|
13128
|
+
const content = readFileSync15(locusPath, "utf-8");
|
|
12940
13129
|
parts.push(`<project-context>
|
|
12941
13130
|
${content.slice(0, 3000)}
|
|
12942
13131
|
</project-context>`);
|
|
@@ -13118,7 +13307,7 @@ __export(exports_review, {
|
|
|
13118
13307
|
reviewCommand: () => reviewCommand
|
|
13119
13308
|
});
|
|
13120
13309
|
import { execFileSync as execFileSync2, execSync as execSync19 } from "node:child_process";
|
|
13121
|
-
import { existsSync as existsSync26, readFileSync as
|
|
13310
|
+
import { existsSync as existsSync26, readFileSync as readFileSync16 } from "node:fs";
|
|
13122
13311
|
import { join as join27 } from "node:path";
|
|
13123
13312
|
function printHelp3() {
|
|
13124
13313
|
process.stderr.write(`
|
|
@@ -13290,7 +13479,7 @@ You are an expert code reviewer for the ${config.github.owner}/${config.github.r
|
|
|
13290
13479
|
</role>`);
|
|
13291
13480
|
const locusPath = join27(projectRoot, ".locus", "LOCUS.md");
|
|
13292
13481
|
if (existsSync26(locusPath)) {
|
|
13293
|
-
const content =
|
|
13482
|
+
const content = readFileSync16(locusPath, "utf-8");
|
|
13294
13483
|
parts.push(`<project-context>
|
|
13295
13484
|
${content.slice(0, 2000)}
|
|
13296
13485
|
</project-context>`);
|
|
@@ -13608,7 +13797,7 @@ import {
|
|
|
13608
13797
|
existsSync as existsSync27,
|
|
13609
13798
|
mkdirSync as mkdirSync18,
|
|
13610
13799
|
readdirSync as readdirSync9,
|
|
13611
|
-
readFileSync as
|
|
13800
|
+
readFileSync as readFileSync17,
|
|
13612
13801
|
unlinkSync as unlinkSync6,
|
|
13613
13802
|
writeFileSync as writeFileSync13
|
|
13614
13803
|
} from "node:fs";
|
|
@@ -13690,7 +13879,7 @@ ${bold2("Discussions:")}
|
|
|
13690
13879
|
`);
|
|
13691
13880
|
for (const file of files) {
|
|
13692
13881
|
const id = file.replace(".md", "");
|
|
13693
|
-
const content =
|
|
13882
|
+
const content = readFileSync17(join28(dir, file), "utf-8");
|
|
13694
13883
|
const titleMatch = content.match(/^#\s+(.+)/m);
|
|
13695
13884
|
const title = titleMatch ? titleMatch[1] : id;
|
|
13696
13885
|
const dateMatch = content.match(/\*\*Date:\*\*\s*(.+)/);
|
|
@@ -13720,7 +13909,7 @@ function showDiscussion(projectRoot, id) {
|
|
|
13720
13909
|
`);
|
|
13721
13910
|
return;
|
|
13722
13911
|
}
|
|
13723
|
-
const content =
|
|
13912
|
+
const content = readFileSync17(join28(dir, match), "utf-8");
|
|
13724
13913
|
process.stdout.write(`${content}
|
|
13725
13914
|
`);
|
|
13726
13915
|
}
|
|
@@ -13768,7 +13957,7 @@ async function convertDiscussionToPlan(projectRoot, id) {
|
|
|
13768
13957
|
`);
|
|
13769
13958
|
return;
|
|
13770
13959
|
}
|
|
13771
|
-
const content =
|
|
13960
|
+
const content = readFileSync17(join28(dir, match), "utf-8");
|
|
13772
13961
|
const titleMatch = content.match(/^#\s+(.+)/m);
|
|
13773
13962
|
const discussionTitle = titleMatch ? titleMatch[1].trim() : id;
|
|
13774
13963
|
await planCommand(projectRoot, [
|
|
@@ -13911,14 +14100,14 @@ You are a senior software architect and consultant for the ${config.github.owner
|
|
|
13911
14100
|
</role>`);
|
|
13912
14101
|
const locusPath = join28(projectRoot, ".locus", "LOCUS.md");
|
|
13913
14102
|
if (existsSync27(locusPath)) {
|
|
13914
|
-
const content =
|
|
14103
|
+
const content = readFileSync17(locusPath, "utf-8");
|
|
13915
14104
|
parts.push(`<project-context>
|
|
13916
14105
|
${content.slice(0, 3000)}
|
|
13917
14106
|
</project-context>`);
|
|
13918
14107
|
}
|
|
13919
14108
|
const learningsPath = join28(projectRoot, ".locus", "LEARNINGS.md");
|
|
13920
14109
|
if (existsSync27(learningsPath)) {
|
|
13921
|
-
const content =
|
|
14110
|
+
const content = readFileSync17(learningsPath, "utf-8");
|
|
13922
14111
|
parts.push(`<past-learnings>
|
|
13923
14112
|
${content.slice(0, 2000)}
|
|
13924
14113
|
</past-learnings>`);
|
|
@@ -13989,7 +14178,7 @@ __export(exports_artifacts, {
|
|
|
13989
14178
|
formatDate: () => formatDate2,
|
|
13990
14179
|
artifactsCommand: () => artifactsCommand
|
|
13991
14180
|
});
|
|
13992
|
-
import { existsSync as existsSync28, readdirSync as readdirSync10, readFileSync as
|
|
14181
|
+
import { existsSync as existsSync28, readdirSync as readdirSync10, readFileSync as readFileSync18, statSync as statSync5 } from "node:fs";
|
|
13993
14182
|
import { join as join29 } from "node:path";
|
|
13994
14183
|
function printHelp6() {
|
|
13995
14184
|
process.stderr.write(`
|
|
@@ -14035,7 +14224,7 @@ function readArtifact(projectRoot, name) {
|
|
|
14035
14224
|
return null;
|
|
14036
14225
|
const stat = statSync5(filePath);
|
|
14037
14226
|
return {
|
|
14038
|
-
content:
|
|
14227
|
+
content: readFileSync18(filePath, "utf-8"),
|
|
14039
14228
|
info: {
|
|
14040
14229
|
name: fileName.replace(/\.md$/, ""),
|
|
14041
14230
|
fileName,
|
|
@@ -14392,7 +14581,7 @@ __export(exports_sandbox2, {
|
|
|
14392
14581
|
});
|
|
14393
14582
|
import { execSync as execSync22, spawn as spawn7 } from "node:child_process";
|
|
14394
14583
|
import { createHash as createHash2 } from "node:crypto";
|
|
14395
|
-
import { existsSync as existsSync29, readFileSync as
|
|
14584
|
+
import { existsSync as existsSync29, readFileSync as readFileSync19 } from "node:fs";
|
|
14396
14585
|
import { basename as basename4, join as join30 } from "node:path";
|
|
14397
14586
|
import { createInterface as createInterface3 } from "node:readline";
|
|
14398
14587
|
function printSandboxHelp() {
|
|
@@ -14923,7 +15112,7 @@ async function handleLogs(projectRoot, args) {
|
|
|
14923
15112
|
}
|
|
14924
15113
|
function detectPackageManager2(projectRoot) {
|
|
14925
15114
|
try {
|
|
14926
|
-
const raw =
|
|
15115
|
+
const raw = readFileSync19(join30(projectRoot, "package.json"), "utf-8");
|
|
14927
15116
|
const pkgJson = JSON.parse(raw);
|
|
14928
15117
|
if (typeof pkgJson.packageManager === "string") {
|
|
14929
15118
|
const name = pkgJson.packageManager.split("@")[0];
|
|
@@ -15216,7 +15405,7 @@ init_context();
|
|
|
15216
15405
|
init_logger();
|
|
15217
15406
|
init_rate_limiter();
|
|
15218
15407
|
init_terminal();
|
|
15219
|
-
import { existsSync as existsSync30, readFileSync as
|
|
15408
|
+
import { existsSync as existsSync30, readFileSync as readFileSync20 } from "node:fs";
|
|
15220
15409
|
import { join as join31 } from "node:path";
|
|
15221
15410
|
import { fileURLToPath } from "node:url";
|
|
15222
15411
|
function getCliVersion() {
|
|
@@ -15226,7 +15415,7 @@ function getCliVersion() {
|
|
|
15226
15415
|
return fallbackVersion;
|
|
15227
15416
|
}
|
|
15228
15417
|
try {
|
|
15229
|
-
const parsed = JSON.parse(
|
|
15418
|
+
const parsed = JSON.parse(readFileSync20(packageJsonPath, "utf-8"));
|
|
15230
15419
|
return parsed.version ?? fallbackVersion;
|
|
15231
15420
|
} catch {
|
|
15232
15421
|
return fallbackVersion;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@locusai/cli",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.4",
|
|
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.25.
|
|
39
|
+
"@locusai/sdk": "^0.25.4",
|
|
40
40
|
"@types/bun": "latest",
|
|
41
41
|
"typescript": "^5.8.3"
|
|
42
42
|
},
|