@locusai/sdk 0.9.3 → 0.9.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/dist/agent/worker.js +110 -71
- package/dist/ai/claude-runner.d.ts.map +1 -1
- package/dist/ai/codex-runner.d.ts.map +1 -1
- package/dist/index-node.js +179 -140
- package/dist/utils/resolve-bin.d.ts +12 -0
- package/dist/utils/resolve-bin.d.ts.map +1 -0
- package/package.json +2 -2
package/dist/agent/worker.js
CHANGED
|
@@ -547,7 +547,7 @@ function getAgentArtifactsPath(projectPath, agentId) {
|
|
|
547
547
|
|
|
548
548
|
// src/ai/claude-runner.ts
|
|
549
549
|
var import_node_child_process = require("node:child_process");
|
|
550
|
-
var
|
|
550
|
+
var import_node_path3 = require("node:path");
|
|
551
551
|
|
|
552
552
|
// src/utils/colors.ts
|
|
553
553
|
var ESC = "\x1B[";
|
|
@@ -611,6 +611,47 @@ var c = {
|
|
|
611
611
|
underline: (t) => c.text(t, "underline")
|
|
612
612
|
};
|
|
613
613
|
|
|
614
|
+
// src/utils/resolve-bin.ts
|
|
615
|
+
var import_node_fs = require("node:fs");
|
|
616
|
+
var import_node_os = require("node:os");
|
|
617
|
+
var import_node_path2 = require("node:path");
|
|
618
|
+
var EXTRA_BIN_DIRS = [
|
|
619
|
+
import_node_path2.join(import_node_os.homedir(), ".local", "bin"),
|
|
620
|
+
import_node_path2.join(import_node_os.homedir(), ".npm", "bin"),
|
|
621
|
+
import_node_path2.join(import_node_os.homedir(), ".npm-global", "bin"),
|
|
622
|
+
import_node_path2.join(import_node_os.homedir(), ".yarn", "bin"),
|
|
623
|
+
"/usr/local/bin"
|
|
624
|
+
];
|
|
625
|
+
function getNodeManagerDirs() {
|
|
626
|
+
const dirs = [];
|
|
627
|
+
const nvmDir = process.env.NVM_DIR || import_node_path2.join(import_node_os.homedir(), ".nvm");
|
|
628
|
+
const nvmCurrent = import_node_path2.join(nvmDir, "current", "bin");
|
|
629
|
+
if (import_node_fs.existsSync(nvmCurrent)) {
|
|
630
|
+
dirs.push(nvmCurrent);
|
|
631
|
+
}
|
|
632
|
+
const fnmDir = process.env.FNM_DIR || import_node_path2.join(import_node_os.homedir(), ".fnm");
|
|
633
|
+
const fnmCurrent = import_node_path2.join(fnmDir, "current", "bin");
|
|
634
|
+
if (import_node_fs.existsSync(fnmCurrent)) {
|
|
635
|
+
dirs.push(fnmCurrent);
|
|
636
|
+
}
|
|
637
|
+
return dirs;
|
|
638
|
+
}
|
|
639
|
+
function getAugmentedPath() {
|
|
640
|
+
const currentPath = process.env.PATH || "";
|
|
641
|
+
const currentDirs = new Set(currentPath.split(import_node_path2.delimiter));
|
|
642
|
+
const extra = [...EXTRA_BIN_DIRS, ...getNodeManagerDirs()].filter((dir) => !currentDirs.has(dir) && import_node_fs.existsSync(dir));
|
|
643
|
+
if (extra.length === 0)
|
|
644
|
+
return currentPath;
|
|
645
|
+
return currentPath + import_node_path2.delimiter + extra.join(import_node_path2.delimiter);
|
|
646
|
+
}
|
|
647
|
+
function getAugmentedEnv(overrides = {}) {
|
|
648
|
+
return {
|
|
649
|
+
...process.env,
|
|
650
|
+
...overrides,
|
|
651
|
+
PATH: getAugmentedPath()
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
|
|
614
655
|
// src/ai/claude-runner.ts
|
|
615
656
|
var SANDBOX_SETTINGS = JSON.stringify({
|
|
616
657
|
sandbox: {
|
|
@@ -631,7 +672,7 @@ class ClaudeRunner {
|
|
|
631
672
|
constructor(projectPath, model = DEFAULT_MODEL[PROVIDER.CLAUDE], log) {
|
|
632
673
|
this.model = model;
|
|
633
674
|
this.log = log;
|
|
634
|
-
this.projectPath =
|
|
675
|
+
this.projectPath = import_node_path3.resolve(projectPath);
|
|
635
676
|
}
|
|
636
677
|
setEventEmitter(emitter) {
|
|
637
678
|
this.eventEmitter = emitter;
|
|
@@ -674,11 +715,10 @@ class ClaudeRunner {
|
|
|
674
715
|
"--settings",
|
|
675
716
|
SANDBOX_SETTINGS
|
|
676
717
|
];
|
|
677
|
-
const env = {
|
|
678
|
-
...process.env,
|
|
718
|
+
const env = getAugmentedEnv({
|
|
679
719
|
FORCE_COLOR: "1",
|
|
680
720
|
TERM: "xterm-256color"
|
|
681
|
-
};
|
|
721
|
+
});
|
|
682
722
|
this.eventEmitter?.emitSessionStarted({
|
|
683
723
|
model: this.model,
|
|
684
724
|
provider: "claude"
|
|
@@ -919,11 +959,10 @@ class ClaudeRunner {
|
|
|
919
959
|
"--settings",
|
|
920
960
|
SANDBOX_SETTINGS
|
|
921
961
|
];
|
|
922
|
-
const env = {
|
|
923
|
-
...process.env,
|
|
962
|
+
const env = getAugmentedEnv({
|
|
924
963
|
FORCE_COLOR: "1",
|
|
925
964
|
TERM: "xterm-256color"
|
|
926
|
-
};
|
|
965
|
+
});
|
|
927
966
|
const claude = import_node_child_process.spawn("claude", args, {
|
|
928
967
|
cwd: this.projectPath,
|
|
929
968
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -1023,9 +1062,9 @@ ${c.primary("[Claude]")} ${c.bold(`Running ${content_block.name}...`)}
|
|
|
1023
1062
|
// src/ai/codex-runner.ts
|
|
1024
1063
|
var import_node_child_process2 = require("node:child_process");
|
|
1025
1064
|
var import_node_crypto = require("node:crypto");
|
|
1026
|
-
var
|
|
1027
|
-
var
|
|
1028
|
-
var
|
|
1065
|
+
var import_node_fs2 = require("node:fs");
|
|
1066
|
+
var import_node_os2 = require("node:os");
|
|
1067
|
+
var import_node_path4 = require("node:path");
|
|
1029
1068
|
class CodexRunner {
|
|
1030
1069
|
projectPath;
|
|
1031
1070
|
model;
|
|
@@ -1060,12 +1099,12 @@ class CodexRunner {
|
|
|
1060
1099
|
throw lastError || new Error("Codex CLI failed after multiple attempts");
|
|
1061
1100
|
}
|
|
1062
1101
|
async* runStream(prompt) {
|
|
1063
|
-
const outputPath =
|
|
1102
|
+
const outputPath = import_node_path4.join(import_node_os2.tmpdir(), `locus-codex-${import_node_crypto.randomUUID()}.txt`);
|
|
1064
1103
|
const args = this.buildArgs(outputPath);
|
|
1065
1104
|
const codex = import_node_child_process2.spawn("codex", args, {
|
|
1066
1105
|
cwd: this.projectPath,
|
|
1067
1106
|
stdio: ["pipe", "pipe", "pipe"],
|
|
1068
|
-
env:
|
|
1107
|
+
env: getAugmentedEnv(),
|
|
1069
1108
|
shell: false
|
|
1070
1109
|
});
|
|
1071
1110
|
this.activeProcess = codex;
|
|
@@ -1156,12 +1195,12 @@ class CodexRunner {
|
|
|
1156
1195
|
}
|
|
1157
1196
|
executeRun(prompt) {
|
|
1158
1197
|
return new Promise((resolve2, reject) => {
|
|
1159
|
-
const outputPath =
|
|
1198
|
+
const outputPath = import_node_path4.join(import_node_os2.tmpdir(), `locus-codex-${import_node_crypto.randomUUID()}.txt`);
|
|
1160
1199
|
const args = this.buildArgs(outputPath);
|
|
1161
1200
|
const codex = import_node_child_process2.spawn("codex", args, {
|
|
1162
1201
|
cwd: this.projectPath,
|
|
1163
1202
|
stdio: ["pipe", "pipe", "pipe"],
|
|
1164
|
-
env:
|
|
1203
|
+
env: getAugmentedEnv(),
|
|
1165
1204
|
shell: false
|
|
1166
1205
|
});
|
|
1167
1206
|
this.activeProcess = codex;
|
|
@@ -1228,9 +1267,9 @@ class CodexRunner {
|
|
|
1228
1267
|
].some((pattern) => pattern.test(line));
|
|
1229
1268
|
}
|
|
1230
1269
|
readOutput(outputPath, fallback) {
|
|
1231
|
-
if (
|
|
1270
|
+
if (import_node_fs2.existsSync(outputPath)) {
|
|
1232
1271
|
try {
|
|
1233
|
-
const text =
|
|
1272
|
+
const text = import_node_fs2.readFileSync(outputPath, "utf-8").trim();
|
|
1234
1273
|
if (text)
|
|
1235
1274
|
return text;
|
|
1236
1275
|
} catch {}
|
|
@@ -1244,8 +1283,8 @@ class CodexRunner {
|
|
|
1244
1283
|
}
|
|
1245
1284
|
cleanupTempFile(path) {
|
|
1246
1285
|
try {
|
|
1247
|
-
if (
|
|
1248
|
-
|
|
1286
|
+
if (import_node_fs2.existsSync(path))
|
|
1287
|
+
import_node_fs2.unlinkSync(path);
|
|
1249
1288
|
} catch {}
|
|
1250
1289
|
}
|
|
1251
1290
|
sleep(ms) {
|
|
@@ -1591,8 +1630,8 @@ class PrService {
|
|
|
1591
1630
|
}
|
|
1592
1631
|
|
|
1593
1632
|
// src/project/knowledge-base.ts
|
|
1594
|
-
var
|
|
1595
|
-
var
|
|
1633
|
+
var import_node_fs3 = require("node:fs");
|
|
1634
|
+
var import_node_path5 = require("node:path");
|
|
1596
1635
|
class KnowledgeBase {
|
|
1597
1636
|
contextPath;
|
|
1598
1637
|
progressPath;
|
|
@@ -1601,20 +1640,20 @@ class KnowledgeBase {
|
|
|
1601
1640
|
this.progressPath = getLocusPath(projectPath, "projectProgressFile");
|
|
1602
1641
|
}
|
|
1603
1642
|
readContext() {
|
|
1604
|
-
if (!
|
|
1643
|
+
if (!import_node_fs3.existsSync(this.contextPath)) {
|
|
1605
1644
|
return "";
|
|
1606
1645
|
}
|
|
1607
|
-
return
|
|
1646
|
+
return import_node_fs3.readFileSync(this.contextPath, "utf-8");
|
|
1608
1647
|
}
|
|
1609
1648
|
readProgress() {
|
|
1610
|
-
if (!
|
|
1649
|
+
if (!import_node_fs3.existsSync(this.progressPath)) {
|
|
1611
1650
|
return "";
|
|
1612
1651
|
}
|
|
1613
|
-
return
|
|
1652
|
+
return import_node_fs3.readFileSync(this.progressPath, "utf-8");
|
|
1614
1653
|
}
|
|
1615
1654
|
updateContext(content) {
|
|
1616
1655
|
this.ensureDir(this.contextPath);
|
|
1617
|
-
|
|
1656
|
+
import_node_fs3.writeFileSync(this.contextPath, content);
|
|
1618
1657
|
}
|
|
1619
1658
|
updateProgress(event) {
|
|
1620
1659
|
this.ensureDir(this.progressPath);
|
|
@@ -1660,7 +1699,7 @@ class KnowledgeBase {
|
|
|
1660
1699
|
${entry}` : `# Project Progress
|
|
1661
1700
|
|
|
1662
1701
|
${entry}`;
|
|
1663
|
-
|
|
1702
|
+
import_node_fs3.writeFileSync(this.progressPath, updated);
|
|
1664
1703
|
}
|
|
1665
1704
|
getFullContext() {
|
|
1666
1705
|
const context = this.readContext();
|
|
@@ -1704,24 +1743,24 @@ ${techStackList}
|
|
|
1704
1743
|
|
|
1705
1744
|
No sprints started yet.
|
|
1706
1745
|
`;
|
|
1707
|
-
|
|
1708
|
-
|
|
1746
|
+
import_node_fs3.writeFileSync(this.contextPath, contextContent);
|
|
1747
|
+
import_node_fs3.writeFileSync(this.progressPath, progressContent);
|
|
1709
1748
|
}
|
|
1710
1749
|
get exists() {
|
|
1711
|
-
return
|
|
1750
|
+
return import_node_fs3.existsSync(this.contextPath) || import_node_fs3.existsSync(this.progressPath);
|
|
1712
1751
|
}
|
|
1713
1752
|
ensureDir(filePath) {
|
|
1714
|
-
const dir =
|
|
1715
|
-
if (!
|
|
1716
|
-
|
|
1753
|
+
const dir = import_node_path5.dirname(filePath);
|
|
1754
|
+
if (!import_node_fs3.existsSync(dir)) {
|
|
1755
|
+
import_node_fs3.mkdirSync(dir, { recursive: true });
|
|
1717
1756
|
}
|
|
1718
1757
|
}
|
|
1719
1758
|
}
|
|
1720
1759
|
|
|
1721
1760
|
// src/worktree/worktree-manager.ts
|
|
1722
1761
|
var import_node_child_process5 = require("node:child_process");
|
|
1723
|
-
var
|
|
1724
|
-
var
|
|
1762
|
+
var import_node_fs4 = require("node:fs");
|
|
1763
|
+
var import_node_path6 = require("node:path");
|
|
1725
1764
|
|
|
1726
1765
|
// src/worktree/worktree-config.ts
|
|
1727
1766
|
var WORKTREE_ROOT_DIR = ".locus-worktrees";
|
|
@@ -1738,14 +1777,14 @@ class WorktreeManager {
|
|
|
1738
1777
|
projectPath;
|
|
1739
1778
|
log;
|
|
1740
1779
|
constructor(projectPath, config, log) {
|
|
1741
|
-
this.projectPath =
|
|
1780
|
+
this.projectPath = import_node_path6.resolve(projectPath);
|
|
1742
1781
|
this.config = { ...DEFAULT_WORKTREE_CONFIG, ...config };
|
|
1743
1782
|
this.log = log ?? ((_msg) => {
|
|
1744
1783
|
return;
|
|
1745
1784
|
});
|
|
1746
1785
|
}
|
|
1747
1786
|
get rootPath() {
|
|
1748
|
-
return
|
|
1787
|
+
return import_node_path6.join(this.projectPath, this.config.rootDir);
|
|
1749
1788
|
}
|
|
1750
1789
|
buildBranchName(taskId, taskSlug) {
|
|
1751
1790
|
const sanitized = taskSlug.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 50);
|
|
@@ -1754,16 +1793,16 @@ class WorktreeManager {
|
|
|
1754
1793
|
create(options) {
|
|
1755
1794
|
const branch = this.buildBranchName(options.taskId, options.taskSlug);
|
|
1756
1795
|
const worktreeDir = `${options.agentId}-${options.taskId}`;
|
|
1757
|
-
const worktreePath =
|
|
1796
|
+
const worktreePath = import_node_path6.join(this.rootPath, worktreeDir);
|
|
1758
1797
|
this.ensureDirectory(this.rootPath, "Worktree root");
|
|
1759
1798
|
const baseBranch = options.baseBranch ?? this.config.baseBranch ?? this.getCurrentBranch();
|
|
1760
1799
|
this.log(`Creating worktree: ${worktreeDir} (branch: ${branch}, base: ${baseBranch})`, "info");
|
|
1761
|
-
if (
|
|
1800
|
+
if (import_node_fs4.existsSync(worktreePath)) {
|
|
1762
1801
|
this.log(`Removing stale worktree directory: ${worktreePath}`, "warn");
|
|
1763
1802
|
try {
|
|
1764
1803
|
this.git(`worktree remove "${worktreePath}" --force`, this.projectPath);
|
|
1765
1804
|
} catch {
|
|
1766
|
-
|
|
1805
|
+
import_node_fs4.rmSync(worktreePath, { recursive: true, force: true });
|
|
1767
1806
|
this.git("worktree prune", this.projectPath);
|
|
1768
1807
|
}
|
|
1769
1808
|
}
|
|
@@ -1771,7 +1810,7 @@ class WorktreeManager {
|
|
|
1771
1810
|
this.log(`Deleting existing branch: ${branch}`, "warn");
|
|
1772
1811
|
const branchWorktrees = this.list().filter((wt) => wt.branch === branch);
|
|
1773
1812
|
for (const wt of branchWorktrees) {
|
|
1774
|
-
const worktreePath2 =
|
|
1813
|
+
const worktreePath2 = import_node_path6.resolve(wt.path);
|
|
1775
1814
|
if (wt.isMain || !this.isManagedWorktreePath(worktreePath2)) {
|
|
1776
1815
|
throw new Error(`Branch "${branch}" is checked out at "${worktreePath2}". Remove or detach that worktree before retrying.`);
|
|
1777
1816
|
}
|
|
@@ -1831,7 +1870,7 @@ class WorktreeManager {
|
|
|
1831
1870
|
branch = "(detached)";
|
|
1832
1871
|
}
|
|
1833
1872
|
}
|
|
1834
|
-
if (
|
|
1873
|
+
if (import_node_path6.resolve(path) === this.projectPath) {
|
|
1835
1874
|
isMain = true;
|
|
1836
1875
|
}
|
|
1837
1876
|
if (path) {
|
|
@@ -1844,16 +1883,16 @@ class WorktreeManager {
|
|
|
1844
1883
|
return this.list().filter((wt) => !wt.isMain);
|
|
1845
1884
|
}
|
|
1846
1885
|
remove(worktreePath, deleteBranch = true) {
|
|
1847
|
-
const absolutePath =
|
|
1886
|
+
const absolutePath = import_node_path6.resolve(worktreePath);
|
|
1848
1887
|
const worktrees = this.list();
|
|
1849
|
-
const worktree = worktrees.find((wt) =>
|
|
1888
|
+
const worktree = worktrees.find((wt) => import_node_path6.resolve(wt.path) === absolutePath);
|
|
1850
1889
|
const branchToDelete = worktree?.branch;
|
|
1851
1890
|
this.log(`Removing worktree: ${absolutePath}`, "info");
|
|
1852
1891
|
try {
|
|
1853
1892
|
this.git(`worktree remove "${absolutePath}" --force`, this.projectPath);
|
|
1854
1893
|
} catch {
|
|
1855
|
-
if (
|
|
1856
|
-
|
|
1894
|
+
if (import_node_fs4.existsSync(absolutePath)) {
|
|
1895
|
+
import_node_fs4.rmSync(absolutePath, { recursive: true, force: true });
|
|
1857
1896
|
}
|
|
1858
1897
|
this.git("worktree prune", this.projectPath);
|
|
1859
1898
|
}
|
|
@@ -1888,9 +1927,9 @@ class WorktreeManager {
|
|
|
1888
1927
|
this.log(`Failed to remove worktree: ${wt.path}`, "warn");
|
|
1889
1928
|
}
|
|
1890
1929
|
}
|
|
1891
|
-
if (
|
|
1930
|
+
if (import_node_fs4.existsSync(this.rootPath)) {
|
|
1892
1931
|
try {
|
|
1893
|
-
|
|
1932
|
+
import_node_fs4.rmSync(this.rootPath, { recursive: true, force: true });
|
|
1894
1933
|
} catch {}
|
|
1895
1934
|
}
|
|
1896
1935
|
return removed;
|
|
@@ -1948,19 +1987,19 @@ class WorktreeManager {
|
|
|
1948
1987
|
return this.git("rev-parse --abbrev-ref HEAD", this.projectPath).trim();
|
|
1949
1988
|
}
|
|
1950
1989
|
isManagedWorktreePath(worktreePath) {
|
|
1951
|
-
const rootPath =
|
|
1952
|
-
const candidate =
|
|
1953
|
-
const rootWithSep = rootPath.endsWith(
|
|
1990
|
+
const rootPath = import_node_path6.resolve(this.rootPath);
|
|
1991
|
+
const candidate = import_node_path6.resolve(worktreePath);
|
|
1992
|
+
const rootWithSep = rootPath.endsWith(import_node_path6.sep) ? rootPath : `${rootPath}${import_node_path6.sep}`;
|
|
1954
1993
|
return candidate.startsWith(rootWithSep);
|
|
1955
1994
|
}
|
|
1956
1995
|
ensureDirectory(dirPath, label) {
|
|
1957
|
-
if (
|
|
1958
|
-
if (!
|
|
1996
|
+
if (import_node_fs4.existsSync(dirPath)) {
|
|
1997
|
+
if (!import_node_fs4.statSync(dirPath).isDirectory()) {
|
|
1959
1998
|
throw new Error(`${label} exists but is not a directory: ${dirPath}`);
|
|
1960
1999
|
}
|
|
1961
2000
|
return;
|
|
1962
2001
|
}
|
|
1963
|
-
|
|
2002
|
+
import_node_fs4.mkdirSync(dirPath, { recursive: true });
|
|
1964
2003
|
}
|
|
1965
2004
|
isMissingDirectoryError(error) {
|
|
1966
2005
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1970,8 +2009,8 @@ class WorktreeManager {
|
|
|
1970
2009
|
try {
|
|
1971
2010
|
this.git(`worktree remove "${worktreePath}" --force`, this.projectPath);
|
|
1972
2011
|
} catch {}
|
|
1973
|
-
if (
|
|
1974
|
-
|
|
2012
|
+
if (import_node_fs4.existsSync(worktreePath)) {
|
|
2013
|
+
import_node_fs4.rmSync(worktreePath, { recursive: true, force: true });
|
|
1975
2014
|
}
|
|
1976
2015
|
try {
|
|
1977
2016
|
this.git("worktree prune", this.projectPath);
|
|
@@ -2003,8 +2042,8 @@ class WorktreeManager {
|
|
|
2003
2042
|
}
|
|
2004
2043
|
|
|
2005
2044
|
// src/core/prompt-builder.ts
|
|
2006
|
-
var
|
|
2007
|
-
var
|
|
2045
|
+
var import_node_fs5 = require("node:fs");
|
|
2046
|
+
var import_node_path7 = require("node:path");
|
|
2008
2047
|
var import_shared2 = require("@locusai/shared");
|
|
2009
2048
|
class PromptBuilder {
|
|
2010
2049
|
projectPath;
|
|
@@ -2046,9 +2085,9 @@ ${task.description || "No description provided."}
|
|
|
2046
2085
|
}
|
|
2047
2086
|
const contextPath = getLocusPath(this.projectPath, "contextFile");
|
|
2048
2087
|
let hasLocalContext = false;
|
|
2049
|
-
if (
|
|
2088
|
+
if (import_node_fs5.existsSync(contextPath)) {
|
|
2050
2089
|
try {
|
|
2051
|
-
const context =
|
|
2090
|
+
const context = import_node_fs5.readFileSync(contextPath, "utf-8");
|
|
2052
2091
|
if (context.trim().length > 20) {
|
|
2053
2092
|
prompt += `## Project Context (Local)
|
|
2054
2093
|
${context}
|
|
@@ -2102,7 +2141,7 @@ ${serverContext.context}
|
|
|
2102
2141
|
|
|
2103
2142
|
`;
|
|
2104
2143
|
const indexPath = getLocusPath(this.projectPath, "indexFile");
|
|
2105
|
-
if (
|
|
2144
|
+
if (import_node_fs5.existsSync(indexPath)) {
|
|
2106
2145
|
prompt += `## Codebase Overview
|
|
2107
2146
|
There is an index file in the .locus/codebase-index.json and if you need you can check it.
|
|
2108
2147
|
|
|
@@ -2177,9 +2216,9 @@ ${query}
|
|
|
2177
2216
|
}
|
|
2178
2217
|
const contextPath = getLocusPath(this.projectPath, "contextFile");
|
|
2179
2218
|
let hasLocalContext = false;
|
|
2180
|
-
if (
|
|
2219
|
+
if (import_node_fs5.existsSync(contextPath)) {
|
|
2181
2220
|
try {
|
|
2182
|
-
const context =
|
|
2221
|
+
const context = import_node_fs5.readFileSync(contextPath, "utf-8");
|
|
2183
2222
|
if (context.trim().length > 20) {
|
|
2184
2223
|
prompt += `## Project Context (Local)
|
|
2185
2224
|
${context}
|
|
@@ -2213,7 +2252,7 @@ ${fallback}
|
|
|
2213
2252
|
|
|
2214
2253
|
`;
|
|
2215
2254
|
const indexPath = getLocusPath(this.projectPath, "indexFile");
|
|
2216
|
-
if (
|
|
2255
|
+
if (import_node_fs5.existsSync(indexPath)) {
|
|
2217
2256
|
prompt += `## Codebase Overview
|
|
2218
2257
|
There is an index file in the .locus/codebase-index.json and if you need you can check it.
|
|
2219
2258
|
|
|
@@ -2226,9 +2265,9 @@ There is an index file in the .locus/codebase-index.json and if you need you can
|
|
|
2226
2265
|
}
|
|
2227
2266
|
getProjectConfig() {
|
|
2228
2267
|
const configPath = getLocusPath(this.projectPath, "configFile");
|
|
2229
|
-
if (
|
|
2268
|
+
if (import_node_fs5.existsSync(configPath)) {
|
|
2230
2269
|
try {
|
|
2231
|
-
return JSON.parse(
|
|
2270
|
+
return JSON.parse(import_node_fs5.readFileSync(configPath, "utf-8"));
|
|
2232
2271
|
} catch {
|
|
2233
2272
|
return null;
|
|
2234
2273
|
}
|
|
@@ -2236,10 +2275,10 @@ There is an index file in the .locus/codebase-index.json and if you need you can
|
|
|
2236
2275
|
return null;
|
|
2237
2276
|
}
|
|
2238
2277
|
getFallbackContext() {
|
|
2239
|
-
const readmePath =
|
|
2240
|
-
if (
|
|
2278
|
+
const readmePath = import_node_path7.join(this.projectPath, "README.md");
|
|
2279
|
+
if (import_node_fs5.existsSync(readmePath)) {
|
|
2241
2280
|
try {
|
|
2242
|
-
const content =
|
|
2281
|
+
const content = import_node_fs5.readFileSync(readmePath, "utf-8");
|
|
2243
2282
|
const limit = 1000;
|
|
2244
2283
|
return content.slice(0, limit) + (content.length > limit ? `
|
|
2245
2284
|
...(truncated)...` : "");
|
|
@@ -2251,12 +2290,12 @@ There is an index file in the .locus/codebase-index.json and if you need you can
|
|
|
2251
2290
|
}
|
|
2252
2291
|
getProjectStructure() {
|
|
2253
2292
|
try {
|
|
2254
|
-
const entries =
|
|
2293
|
+
const entries = import_node_fs5.readdirSync(this.projectPath);
|
|
2255
2294
|
const folders = entries.filter((e) => {
|
|
2256
2295
|
if (e.startsWith(".") || e === "node_modules")
|
|
2257
2296
|
return false;
|
|
2258
2297
|
try {
|
|
2259
|
-
return
|
|
2298
|
+
return import_node_fs5.statSync(import_node_path7.join(this.projectPath, e)).isDirectory();
|
|
2260
2299
|
} catch {
|
|
2261
2300
|
return false;
|
|
2262
2301
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-runner.d.ts","sourceRoot":"","sources":["../../src/ai/claude-runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-runner.d.ts","sourceRoot":"","sources":["../../src/ai/claude-runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,kBAAkB,CAAC;AAGhE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAwC5C,qBAAa,YAAa,YAAW,QAAQ;IASzC,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,GAAG,CAAC;IATd,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAC,CAAmB;IACxC,OAAO,CAAC,eAAe,CAAC,CAAS;IACjC,OAAO,CAAC,WAAW,CAA+C;IAClE,OAAO,CAAC,aAAa,CAA6B;gBAGhD,WAAW,EAAE,MAAM,EACX,KAAK,GAAE,MAAuC,EAC9C,GAAG,CAAC,EAAE,KAAK,YAAA;IAKrB;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAIhD;;OAEG;IACH,KAAK,IAAI,IAAI;IAOP,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAyBnC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC;IA0K5E;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiCzB,OAAO,CAAC,sBAAsB;IAW9B,OAAO,CAAC,wBAAwB;IAYhC,OAAO,CAAC,kBAAkB;IAwE1B,OAAO,CAAC,UAAU;IAuFlB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,oBAAoB;CAO7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-runner.d.ts","sourceRoot":"","sources":["../../src/ai/codex-runner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"codex-runner.d.ts","sourceRoot":"","sources":["../../src/ai/codex-runner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,qBAAa,WAAY,YAAW,QAAQ;IAIxC,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,GAAG,CAAC;IALd,OAAO,CAAC,aAAa,CAA6B;gBAGxC,WAAW,EAAE,MAAM,EACnB,KAAK,GAAE,MAAsC,EAC7C,GAAG,CAAC,EAAE,KAAK,YAAA;IAGrB;;OAEG;IACH,KAAK,IAAI,IAAI;IAOP,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAuBnC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC;IAgH5E,OAAO,CAAC,UAAU;IAuDlB,OAAO,CAAC,SAAS;IAkBjB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,KAAK;CAGd"}
|
package/dist/index-node.js
CHANGED
|
@@ -547,7 +547,7 @@ function getAgentArtifactsPath(projectPath, agentId) {
|
|
|
547
547
|
|
|
548
548
|
// src/ai/claude-runner.ts
|
|
549
549
|
var import_node_child_process = require("node:child_process");
|
|
550
|
-
var
|
|
550
|
+
var import_node_path3 = require("node:path");
|
|
551
551
|
|
|
552
552
|
// src/utils/colors.ts
|
|
553
553
|
var ESC = "\x1B[";
|
|
@@ -611,6 +611,47 @@ var c = {
|
|
|
611
611
|
underline: (t) => c.text(t, "underline")
|
|
612
612
|
};
|
|
613
613
|
|
|
614
|
+
// src/utils/resolve-bin.ts
|
|
615
|
+
var import_node_fs = require("node:fs");
|
|
616
|
+
var import_node_os = require("node:os");
|
|
617
|
+
var import_node_path2 = require("node:path");
|
|
618
|
+
var EXTRA_BIN_DIRS = [
|
|
619
|
+
import_node_path2.join(import_node_os.homedir(), ".local", "bin"),
|
|
620
|
+
import_node_path2.join(import_node_os.homedir(), ".npm", "bin"),
|
|
621
|
+
import_node_path2.join(import_node_os.homedir(), ".npm-global", "bin"),
|
|
622
|
+
import_node_path2.join(import_node_os.homedir(), ".yarn", "bin"),
|
|
623
|
+
"/usr/local/bin"
|
|
624
|
+
];
|
|
625
|
+
function getNodeManagerDirs() {
|
|
626
|
+
const dirs = [];
|
|
627
|
+
const nvmDir = process.env.NVM_DIR || import_node_path2.join(import_node_os.homedir(), ".nvm");
|
|
628
|
+
const nvmCurrent = import_node_path2.join(nvmDir, "current", "bin");
|
|
629
|
+
if (import_node_fs.existsSync(nvmCurrent)) {
|
|
630
|
+
dirs.push(nvmCurrent);
|
|
631
|
+
}
|
|
632
|
+
const fnmDir = process.env.FNM_DIR || import_node_path2.join(import_node_os.homedir(), ".fnm");
|
|
633
|
+
const fnmCurrent = import_node_path2.join(fnmDir, "current", "bin");
|
|
634
|
+
if (import_node_fs.existsSync(fnmCurrent)) {
|
|
635
|
+
dirs.push(fnmCurrent);
|
|
636
|
+
}
|
|
637
|
+
return dirs;
|
|
638
|
+
}
|
|
639
|
+
function getAugmentedPath() {
|
|
640
|
+
const currentPath = process.env.PATH || "";
|
|
641
|
+
const currentDirs = new Set(currentPath.split(import_node_path2.delimiter));
|
|
642
|
+
const extra = [...EXTRA_BIN_DIRS, ...getNodeManagerDirs()].filter((dir) => !currentDirs.has(dir) && import_node_fs.existsSync(dir));
|
|
643
|
+
if (extra.length === 0)
|
|
644
|
+
return currentPath;
|
|
645
|
+
return currentPath + import_node_path2.delimiter + extra.join(import_node_path2.delimiter);
|
|
646
|
+
}
|
|
647
|
+
function getAugmentedEnv(overrides = {}) {
|
|
648
|
+
return {
|
|
649
|
+
...process.env,
|
|
650
|
+
...overrides,
|
|
651
|
+
PATH: getAugmentedPath()
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
|
|
614
655
|
// src/ai/claude-runner.ts
|
|
615
656
|
var SANDBOX_SETTINGS = JSON.stringify({
|
|
616
657
|
sandbox: {
|
|
@@ -631,7 +672,7 @@ class ClaudeRunner {
|
|
|
631
672
|
constructor(projectPath, model = DEFAULT_MODEL[PROVIDER.CLAUDE], log) {
|
|
632
673
|
this.model = model;
|
|
633
674
|
this.log = log;
|
|
634
|
-
this.projectPath =
|
|
675
|
+
this.projectPath = import_node_path3.resolve(projectPath);
|
|
635
676
|
}
|
|
636
677
|
setEventEmitter(emitter) {
|
|
637
678
|
this.eventEmitter = emitter;
|
|
@@ -674,11 +715,10 @@ class ClaudeRunner {
|
|
|
674
715
|
"--settings",
|
|
675
716
|
SANDBOX_SETTINGS
|
|
676
717
|
];
|
|
677
|
-
const env = {
|
|
678
|
-
...process.env,
|
|
718
|
+
const env = getAugmentedEnv({
|
|
679
719
|
FORCE_COLOR: "1",
|
|
680
720
|
TERM: "xterm-256color"
|
|
681
|
-
};
|
|
721
|
+
});
|
|
682
722
|
this.eventEmitter?.emitSessionStarted({
|
|
683
723
|
model: this.model,
|
|
684
724
|
provider: "claude"
|
|
@@ -919,11 +959,10 @@ class ClaudeRunner {
|
|
|
919
959
|
"--settings",
|
|
920
960
|
SANDBOX_SETTINGS
|
|
921
961
|
];
|
|
922
|
-
const env = {
|
|
923
|
-
...process.env,
|
|
962
|
+
const env = getAugmentedEnv({
|
|
924
963
|
FORCE_COLOR: "1",
|
|
925
964
|
TERM: "xterm-256color"
|
|
926
|
-
};
|
|
965
|
+
});
|
|
927
966
|
const claude = import_node_child_process.spawn("claude", args, {
|
|
928
967
|
cwd: this.projectPath,
|
|
929
968
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -1023,9 +1062,9 @@ ${c.primary("[Claude]")} ${c.bold(`Running ${content_block.name}...`)}
|
|
|
1023
1062
|
// src/ai/codex-runner.ts
|
|
1024
1063
|
var import_node_child_process2 = require("node:child_process");
|
|
1025
1064
|
var import_node_crypto = require("node:crypto");
|
|
1026
|
-
var
|
|
1027
|
-
var
|
|
1028
|
-
var
|
|
1065
|
+
var import_node_fs2 = require("node:fs");
|
|
1066
|
+
var import_node_os2 = require("node:os");
|
|
1067
|
+
var import_node_path4 = require("node:path");
|
|
1029
1068
|
class CodexRunner {
|
|
1030
1069
|
projectPath;
|
|
1031
1070
|
model;
|
|
@@ -1060,12 +1099,12 @@ class CodexRunner {
|
|
|
1060
1099
|
throw lastError || new Error("Codex CLI failed after multiple attempts");
|
|
1061
1100
|
}
|
|
1062
1101
|
async* runStream(prompt) {
|
|
1063
|
-
const outputPath =
|
|
1102
|
+
const outputPath = import_node_path4.join(import_node_os2.tmpdir(), `locus-codex-${import_node_crypto.randomUUID()}.txt`);
|
|
1064
1103
|
const args = this.buildArgs(outputPath);
|
|
1065
1104
|
const codex = import_node_child_process2.spawn("codex", args, {
|
|
1066
1105
|
cwd: this.projectPath,
|
|
1067
1106
|
stdio: ["pipe", "pipe", "pipe"],
|
|
1068
|
-
env:
|
|
1107
|
+
env: getAugmentedEnv(),
|
|
1069
1108
|
shell: false
|
|
1070
1109
|
});
|
|
1071
1110
|
this.activeProcess = codex;
|
|
@@ -1156,12 +1195,12 @@ class CodexRunner {
|
|
|
1156
1195
|
}
|
|
1157
1196
|
executeRun(prompt) {
|
|
1158
1197
|
return new Promise((resolve2, reject) => {
|
|
1159
|
-
const outputPath =
|
|
1198
|
+
const outputPath = import_node_path4.join(import_node_os2.tmpdir(), `locus-codex-${import_node_crypto.randomUUID()}.txt`);
|
|
1160
1199
|
const args = this.buildArgs(outputPath);
|
|
1161
1200
|
const codex = import_node_child_process2.spawn("codex", args, {
|
|
1162
1201
|
cwd: this.projectPath,
|
|
1163
1202
|
stdio: ["pipe", "pipe", "pipe"],
|
|
1164
|
-
env:
|
|
1203
|
+
env: getAugmentedEnv(),
|
|
1165
1204
|
shell: false
|
|
1166
1205
|
});
|
|
1167
1206
|
this.activeProcess = codex;
|
|
@@ -1228,9 +1267,9 @@ class CodexRunner {
|
|
|
1228
1267
|
].some((pattern) => pattern.test(line));
|
|
1229
1268
|
}
|
|
1230
1269
|
readOutput(outputPath, fallback) {
|
|
1231
|
-
if (
|
|
1270
|
+
if (import_node_fs2.existsSync(outputPath)) {
|
|
1232
1271
|
try {
|
|
1233
|
-
const text =
|
|
1272
|
+
const text = import_node_fs2.readFileSync(outputPath, "utf-8").trim();
|
|
1234
1273
|
if (text)
|
|
1235
1274
|
return text;
|
|
1236
1275
|
} catch {}
|
|
@@ -1244,8 +1283,8 @@ class CodexRunner {
|
|
|
1244
1283
|
}
|
|
1245
1284
|
cleanupTempFile(path) {
|
|
1246
1285
|
try {
|
|
1247
|
-
if (
|
|
1248
|
-
|
|
1286
|
+
if (import_node_fs2.existsSync(path))
|
|
1287
|
+
import_node_fs2.unlinkSync(path);
|
|
1249
1288
|
} catch {}
|
|
1250
1289
|
}
|
|
1251
1290
|
sleep(ms) {
|
|
@@ -1591,8 +1630,8 @@ class PrService {
|
|
|
1591
1630
|
}
|
|
1592
1631
|
|
|
1593
1632
|
// src/project/knowledge-base.ts
|
|
1594
|
-
var
|
|
1595
|
-
var
|
|
1633
|
+
var import_node_fs3 = require("node:fs");
|
|
1634
|
+
var import_node_path5 = require("node:path");
|
|
1596
1635
|
class KnowledgeBase {
|
|
1597
1636
|
contextPath;
|
|
1598
1637
|
progressPath;
|
|
@@ -1601,20 +1640,20 @@ class KnowledgeBase {
|
|
|
1601
1640
|
this.progressPath = getLocusPath(projectPath, "projectProgressFile");
|
|
1602
1641
|
}
|
|
1603
1642
|
readContext() {
|
|
1604
|
-
if (!
|
|
1643
|
+
if (!import_node_fs3.existsSync(this.contextPath)) {
|
|
1605
1644
|
return "";
|
|
1606
1645
|
}
|
|
1607
|
-
return
|
|
1646
|
+
return import_node_fs3.readFileSync(this.contextPath, "utf-8");
|
|
1608
1647
|
}
|
|
1609
1648
|
readProgress() {
|
|
1610
|
-
if (!
|
|
1649
|
+
if (!import_node_fs3.existsSync(this.progressPath)) {
|
|
1611
1650
|
return "";
|
|
1612
1651
|
}
|
|
1613
|
-
return
|
|
1652
|
+
return import_node_fs3.readFileSync(this.progressPath, "utf-8");
|
|
1614
1653
|
}
|
|
1615
1654
|
updateContext(content) {
|
|
1616
1655
|
this.ensureDir(this.contextPath);
|
|
1617
|
-
|
|
1656
|
+
import_node_fs3.writeFileSync(this.contextPath, content);
|
|
1618
1657
|
}
|
|
1619
1658
|
updateProgress(event) {
|
|
1620
1659
|
this.ensureDir(this.progressPath);
|
|
@@ -1660,7 +1699,7 @@ class KnowledgeBase {
|
|
|
1660
1699
|
${entry}` : `# Project Progress
|
|
1661
1700
|
|
|
1662
1701
|
${entry}`;
|
|
1663
|
-
|
|
1702
|
+
import_node_fs3.writeFileSync(this.progressPath, updated);
|
|
1664
1703
|
}
|
|
1665
1704
|
getFullContext() {
|
|
1666
1705
|
const context = this.readContext();
|
|
@@ -1704,24 +1743,24 @@ ${techStackList}
|
|
|
1704
1743
|
|
|
1705
1744
|
No sprints started yet.
|
|
1706
1745
|
`;
|
|
1707
|
-
|
|
1708
|
-
|
|
1746
|
+
import_node_fs3.writeFileSync(this.contextPath, contextContent);
|
|
1747
|
+
import_node_fs3.writeFileSync(this.progressPath, progressContent);
|
|
1709
1748
|
}
|
|
1710
1749
|
get exists() {
|
|
1711
|
-
return
|
|
1750
|
+
return import_node_fs3.existsSync(this.contextPath) || import_node_fs3.existsSync(this.progressPath);
|
|
1712
1751
|
}
|
|
1713
1752
|
ensureDir(filePath) {
|
|
1714
|
-
const dir =
|
|
1715
|
-
if (!
|
|
1716
|
-
|
|
1753
|
+
const dir = import_node_path5.dirname(filePath);
|
|
1754
|
+
if (!import_node_fs3.existsSync(dir)) {
|
|
1755
|
+
import_node_fs3.mkdirSync(dir, { recursive: true });
|
|
1717
1756
|
}
|
|
1718
1757
|
}
|
|
1719
1758
|
}
|
|
1720
1759
|
|
|
1721
1760
|
// src/worktree/worktree-manager.ts
|
|
1722
1761
|
var import_node_child_process5 = require("node:child_process");
|
|
1723
|
-
var
|
|
1724
|
-
var
|
|
1762
|
+
var import_node_fs4 = require("node:fs");
|
|
1763
|
+
var import_node_path6 = require("node:path");
|
|
1725
1764
|
|
|
1726
1765
|
// src/worktree/worktree-config.ts
|
|
1727
1766
|
var WORKTREE_ROOT_DIR = ".locus-worktrees";
|
|
@@ -1738,14 +1777,14 @@ class WorktreeManager {
|
|
|
1738
1777
|
projectPath;
|
|
1739
1778
|
log;
|
|
1740
1779
|
constructor(projectPath, config, log) {
|
|
1741
|
-
this.projectPath =
|
|
1780
|
+
this.projectPath = import_node_path6.resolve(projectPath);
|
|
1742
1781
|
this.config = { ...DEFAULT_WORKTREE_CONFIG, ...config };
|
|
1743
1782
|
this.log = log ?? ((_msg) => {
|
|
1744
1783
|
return;
|
|
1745
1784
|
});
|
|
1746
1785
|
}
|
|
1747
1786
|
get rootPath() {
|
|
1748
|
-
return
|
|
1787
|
+
return import_node_path6.join(this.projectPath, this.config.rootDir);
|
|
1749
1788
|
}
|
|
1750
1789
|
buildBranchName(taskId, taskSlug) {
|
|
1751
1790
|
const sanitized = taskSlug.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 50);
|
|
@@ -1754,16 +1793,16 @@ class WorktreeManager {
|
|
|
1754
1793
|
create(options) {
|
|
1755
1794
|
const branch = this.buildBranchName(options.taskId, options.taskSlug);
|
|
1756
1795
|
const worktreeDir = `${options.agentId}-${options.taskId}`;
|
|
1757
|
-
const worktreePath =
|
|
1796
|
+
const worktreePath = import_node_path6.join(this.rootPath, worktreeDir);
|
|
1758
1797
|
this.ensureDirectory(this.rootPath, "Worktree root");
|
|
1759
1798
|
const baseBranch = options.baseBranch ?? this.config.baseBranch ?? this.getCurrentBranch();
|
|
1760
1799
|
this.log(`Creating worktree: ${worktreeDir} (branch: ${branch}, base: ${baseBranch})`, "info");
|
|
1761
|
-
if (
|
|
1800
|
+
if (import_node_fs4.existsSync(worktreePath)) {
|
|
1762
1801
|
this.log(`Removing stale worktree directory: ${worktreePath}`, "warn");
|
|
1763
1802
|
try {
|
|
1764
1803
|
this.git(`worktree remove "${worktreePath}" --force`, this.projectPath);
|
|
1765
1804
|
} catch {
|
|
1766
|
-
|
|
1805
|
+
import_node_fs4.rmSync(worktreePath, { recursive: true, force: true });
|
|
1767
1806
|
this.git("worktree prune", this.projectPath);
|
|
1768
1807
|
}
|
|
1769
1808
|
}
|
|
@@ -1771,7 +1810,7 @@ class WorktreeManager {
|
|
|
1771
1810
|
this.log(`Deleting existing branch: ${branch}`, "warn");
|
|
1772
1811
|
const branchWorktrees = this.list().filter((wt) => wt.branch === branch);
|
|
1773
1812
|
for (const wt of branchWorktrees) {
|
|
1774
|
-
const worktreePath2 =
|
|
1813
|
+
const worktreePath2 = import_node_path6.resolve(wt.path);
|
|
1775
1814
|
if (wt.isMain || !this.isManagedWorktreePath(worktreePath2)) {
|
|
1776
1815
|
throw new Error(`Branch "${branch}" is checked out at "${worktreePath2}". Remove or detach that worktree before retrying.`);
|
|
1777
1816
|
}
|
|
@@ -1831,7 +1870,7 @@ class WorktreeManager {
|
|
|
1831
1870
|
branch = "(detached)";
|
|
1832
1871
|
}
|
|
1833
1872
|
}
|
|
1834
|
-
if (
|
|
1873
|
+
if (import_node_path6.resolve(path) === this.projectPath) {
|
|
1835
1874
|
isMain = true;
|
|
1836
1875
|
}
|
|
1837
1876
|
if (path) {
|
|
@@ -1844,16 +1883,16 @@ class WorktreeManager {
|
|
|
1844
1883
|
return this.list().filter((wt) => !wt.isMain);
|
|
1845
1884
|
}
|
|
1846
1885
|
remove(worktreePath, deleteBranch = true) {
|
|
1847
|
-
const absolutePath =
|
|
1886
|
+
const absolutePath = import_node_path6.resolve(worktreePath);
|
|
1848
1887
|
const worktrees = this.list();
|
|
1849
|
-
const worktree = worktrees.find((wt) =>
|
|
1888
|
+
const worktree = worktrees.find((wt) => import_node_path6.resolve(wt.path) === absolutePath);
|
|
1850
1889
|
const branchToDelete = worktree?.branch;
|
|
1851
1890
|
this.log(`Removing worktree: ${absolutePath}`, "info");
|
|
1852
1891
|
try {
|
|
1853
1892
|
this.git(`worktree remove "${absolutePath}" --force`, this.projectPath);
|
|
1854
1893
|
} catch {
|
|
1855
|
-
if (
|
|
1856
|
-
|
|
1894
|
+
if (import_node_fs4.existsSync(absolutePath)) {
|
|
1895
|
+
import_node_fs4.rmSync(absolutePath, { recursive: true, force: true });
|
|
1857
1896
|
}
|
|
1858
1897
|
this.git("worktree prune", this.projectPath);
|
|
1859
1898
|
}
|
|
@@ -1888,9 +1927,9 @@ class WorktreeManager {
|
|
|
1888
1927
|
this.log(`Failed to remove worktree: ${wt.path}`, "warn");
|
|
1889
1928
|
}
|
|
1890
1929
|
}
|
|
1891
|
-
if (
|
|
1930
|
+
if (import_node_fs4.existsSync(this.rootPath)) {
|
|
1892
1931
|
try {
|
|
1893
|
-
|
|
1932
|
+
import_node_fs4.rmSync(this.rootPath, { recursive: true, force: true });
|
|
1894
1933
|
} catch {}
|
|
1895
1934
|
}
|
|
1896
1935
|
return removed;
|
|
@@ -1948,19 +1987,19 @@ class WorktreeManager {
|
|
|
1948
1987
|
return this.git("rev-parse --abbrev-ref HEAD", this.projectPath).trim();
|
|
1949
1988
|
}
|
|
1950
1989
|
isManagedWorktreePath(worktreePath) {
|
|
1951
|
-
const rootPath =
|
|
1952
|
-
const candidate =
|
|
1953
|
-
const rootWithSep = rootPath.endsWith(
|
|
1990
|
+
const rootPath = import_node_path6.resolve(this.rootPath);
|
|
1991
|
+
const candidate = import_node_path6.resolve(worktreePath);
|
|
1992
|
+
const rootWithSep = rootPath.endsWith(import_node_path6.sep) ? rootPath : `${rootPath}${import_node_path6.sep}`;
|
|
1954
1993
|
return candidate.startsWith(rootWithSep);
|
|
1955
1994
|
}
|
|
1956
1995
|
ensureDirectory(dirPath, label) {
|
|
1957
|
-
if (
|
|
1958
|
-
if (!
|
|
1996
|
+
if (import_node_fs4.existsSync(dirPath)) {
|
|
1997
|
+
if (!import_node_fs4.statSync(dirPath).isDirectory()) {
|
|
1959
1998
|
throw new Error(`${label} exists but is not a directory: ${dirPath}`);
|
|
1960
1999
|
}
|
|
1961
2000
|
return;
|
|
1962
2001
|
}
|
|
1963
|
-
|
|
2002
|
+
import_node_fs4.mkdirSync(dirPath, { recursive: true });
|
|
1964
2003
|
}
|
|
1965
2004
|
isMissingDirectoryError(error) {
|
|
1966
2005
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1970,8 +2009,8 @@ class WorktreeManager {
|
|
|
1970
2009
|
try {
|
|
1971
2010
|
this.git(`worktree remove "${worktreePath}" --force`, this.projectPath);
|
|
1972
2011
|
} catch {}
|
|
1973
|
-
if (
|
|
1974
|
-
|
|
2012
|
+
if (import_node_fs4.existsSync(worktreePath)) {
|
|
2013
|
+
import_node_fs4.rmSync(worktreePath, { recursive: true, force: true });
|
|
1975
2014
|
}
|
|
1976
2015
|
try {
|
|
1977
2016
|
this.git("worktree prune", this.projectPath);
|
|
@@ -2003,8 +2042,8 @@ class WorktreeManager {
|
|
|
2003
2042
|
}
|
|
2004
2043
|
|
|
2005
2044
|
// src/core/prompt-builder.ts
|
|
2006
|
-
var
|
|
2007
|
-
var
|
|
2045
|
+
var import_node_fs5 = require("node:fs");
|
|
2046
|
+
var import_node_path7 = require("node:path");
|
|
2008
2047
|
var import_shared2 = require("@locusai/shared");
|
|
2009
2048
|
class PromptBuilder {
|
|
2010
2049
|
projectPath;
|
|
@@ -2046,9 +2085,9 @@ ${task.description || "No description provided."}
|
|
|
2046
2085
|
}
|
|
2047
2086
|
const contextPath = getLocusPath(this.projectPath, "contextFile");
|
|
2048
2087
|
let hasLocalContext = false;
|
|
2049
|
-
if (
|
|
2088
|
+
if (import_node_fs5.existsSync(contextPath)) {
|
|
2050
2089
|
try {
|
|
2051
|
-
const context =
|
|
2090
|
+
const context = import_node_fs5.readFileSync(contextPath, "utf-8");
|
|
2052
2091
|
if (context.trim().length > 20) {
|
|
2053
2092
|
prompt += `## Project Context (Local)
|
|
2054
2093
|
${context}
|
|
@@ -2102,7 +2141,7 @@ ${serverContext.context}
|
|
|
2102
2141
|
|
|
2103
2142
|
`;
|
|
2104
2143
|
const indexPath = getLocusPath(this.projectPath, "indexFile");
|
|
2105
|
-
if (
|
|
2144
|
+
if (import_node_fs5.existsSync(indexPath)) {
|
|
2106
2145
|
prompt += `## Codebase Overview
|
|
2107
2146
|
There is an index file in the .locus/codebase-index.json and if you need you can check it.
|
|
2108
2147
|
|
|
@@ -2177,9 +2216,9 @@ ${query}
|
|
|
2177
2216
|
}
|
|
2178
2217
|
const contextPath = getLocusPath(this.projectPath, "contextFile");
|
|
2179
2218
|
let hasLocalContext = false;
|
|
2180
|
-
if (
|
|
2219
|
+
if (import_node_fs5.existsSync(contextPath)) {
|
|
2181
2220
|
try {
|
|
2182
|
-
const context =
|
|
2221
|
+
const context = import_node_fs5.readFileSync(contextPath, "utf-8");
|
|
2183
2222
|
if (context.trim().length > 20) {
|
|
2184
2223
|
prompt += `## Project Context (Local)
|
|
2185
2224
|
${context}
|
|
@@ -2213,7 +2252,7 @@ ${fallback}
|
|
|
2213
2252
|
|
|
2214
2253
|
`;
|
|
2215
2254
|
const indexPath = getLocusPath(this.projectPath, "indexFile");
|
|
2216
|
-
if (
|
|
2255
|
+
if (import_node_fs5.existsSync(indexPath)) {
|
|
2217
2256
|
prompt += `## Codebase Overview
|
|
2218
2257
|
There is an index file in the .locus/codebase-index.json and if you need you can check it.
|
|
2219
2258
|
|
|
@@ -2226,9 +2265,9 @@ There is an index file in the .locus/codebase-index.json and if you need you can
|
|
|
2226
2265
|
}
|
|
2227
2266
|
getProjectConfig() {
|
|
2228
2267
|
const configPath = getLocusPath(this.projectPath, "configFile");
|
|
2229
|
-
if (
|
|
2268
|
+
if (import_node_fs5.existsSync(configPath)) {
|
|
2230
2269
|
try {
|
|
2231
|
-
return JSON.parse(
|
|
2270
|
+
return JSON.parse(import_node_fs5.readFileSync(configPath, "utf-8"));
|
|
2232
2271
|
} catch {
|
|
2233
2272
|
return null;
|
|
2234
2273
|
}
|
|
@@ -2236,10 +2275,10 @@ There is an index file in the .locus/codebase-index.json and if you need you can
|
|
|
2236
2275
|
return null;
|
|
2237
2276
|
}
|
|
2238
2277
|
getFallbackContext() {
|
|
2239
|
-
const readmePath =
|
|
2240
|
-
if (
|
|
2278
|
+
const readmePath = import_node_path7.join(this.projectPath, "README.md");
|
|
2279
|
+
if (import_node_fs5.existsSync(readmePath)) {
|
|
2241
2280
|
try {
|
|
2242
|
-
const content =
|
|
2281
|
+
const content = import_node_fs5.readFileSync(readmePath, "utf-8");
|
|
2243
2282
|
const limit = 1000;
|
|
2244
2283
|
return content.slice(0, limit) + (content.length > limit ? `
|
|
2245
2284
|
...(truncated)...` : "");
|
|
@@ -2251,12 +2290,12 @@ There is an index file in the .locus/codebase-index.json and if you need you can
|
|
|
2251
2290
|
}
|
|
2252
2291
|
getProjectStructure() {
|
|
2253
2292
|
try {
|
|
2254
|
-
const entries =
|
|
2293
|
+
const entries = import_node_fs5.readdirSync(this.projectPath);
|
|
2255
2294
|
const folders = entries.filter((e) => {
|
|
2256
2295
|
if (e.startsWith(".") || e === "node_modules")
|
|
2257
2296
|
return false;
|
|
2258
2297
|
try {
|
|
2259
|
-
return
|
|
2298
|
+
return import_node_fs5.statSync(import_node_path7.join(this.projectPath, e)).isDirectory();
|
|
2260
2299
|
} catch {
|
|
2261
2300
|
return false;
|
|
2262
2301
|
}
|
|
@@ -2866,8 +2905,8 @@ module.exports = __toCommonJS(exports_index_node);
|
|
|
2866
2905
|
|
|
2867
2906
|
// src/core/indexer.ts
|
|
2868
2907
|
var import_node_crypto2 = require("node:crypto");
|
|
2869
|
-
var
|
|
2870
|
-
var
|
|
2908
|
+
var import_node_fs6 = require("node:fs");
|
|
2909
|
+
var import_node_path8 = require("node:path");
|
|
2871
2910
|
var import_globby = require("globby");
|
|
2872
2911
|
|
|
2873
2912
|
class CodebaseIndexer {
|
|
@@ -2876,7 +2915,7 @@ class CodebaseIndexer {
|
|
|
2876
2915
|
fullReindexRatioThreshold = 0.2;
|
|
2877
2916
|
constructor(projectPath) {
|
|
2878
2917
|
this.projectPath = projectPath;
|
|
2879
|
-
this.indexPath =
|
|
2918
|
+
this.indexPath = import_node_path8.join(projectPath, ".locus", "codebase-index.json");
|
|
2880
2919
|
}
|
|
2881
2920
|
async index(onProgress, treeSummarizer, force = false) {
|
|
2882
2921
|
if (!treeSummarizer) {
|
|
@@ -2932,11 +2971,11 @@ class CodebaseIndexer {
|
|
|
2932
2971
|
}
|
|
2933
2972
|
}
|
|
2934
2973
|
async getFileTree() {
|
|
2935
|
-
const gitmodulesPath =
|
|
2974
|
+
const gitmodulesPath = import_node_path8.join(this.projectPath, ".gitmodules");
|
|
2936
2975
|
const submoduleIgnores = [];
|
|
2937
|
-
if (
|
|
2976
|
+
if (import_node_fs6.existsSync(gitmodulesPath)) {
|
|
2938
2977
|
try {
|
|
2939
|
-
const content =
|
|
2978
|
+
const content = import_node_fs6.readFileSync(gitmodulesPath, "utf-8");
|
|
2940
2979
|
const lines = content.split(`
|
|
2941
2980
|
`);
|
|
2942
2981
|
for (const line of lines) {
|
|
@@ -2992,9 +3031,9 @@ class CodebaseIndexer {
|
|
|
2992
3031
|
});
|
|
2993
3032
|
}
|
|
2994
3033
|
loadIndex() {
|
|
2995
|
-
if (
|
|
3034
|
+
if (import_node_fs6.existsSync(this.indexPath)) {
|
|
2996
3035
|
try {
|
|
2997
|
-
return JSON.parse(
|
|
3036
|
+
return JSON.parse(import_node_fs6.readFileSync(this.indexPath, "utf-8"));
|
|
2998
3037
|
} catch {
|
|
2999
3038
|
return null;
|
|
3000
3039
|
}
|
|
@@ -3002,11 +3041,11 @@ class CodebaseIndexer {
|
|
|
3002
3041
|
return null;
|
|
3003
3042
|
}
|
|
3004
3043
|
saveIndex(index) {
|
|
3005
|
-
const dir =
|
|
3006
|
-
if (!
|
|
3007
|
-
|
|
3044
|
+
const dir = import_node_path8.dirname(this.indexPath);
|
|
3045
|
+
if (!import_node_fs6.existsSync(dir)) {
|
|
3046
|
+
import_node_fs6.mkdirSync(dir, { recursive: true });
|
|
3008
3047
|
}
|
|
3009
|
-
|
|
3048
|
+
import_node_fs6.writeFileSync(this.indexPath, JSON.stringify(index, null, 2));
|
|
3010
3049
|
}
|
|
3011
3050
|
cloneIndex(index) {
|
|
3012
3051
|
return JSON.parse(JSON.stringify(index));
|
|
@@ -3022,7 +3061,7 @@ class CodebaseIndexer {
|
|
|
3022
3061
|
}
|
|
3023
3062
|
hashFile(filePath) {
|
|
3024
3063
|
try {
|
|
3025
|
-
const content =
|
|
3064
|
+
const content = import_node_fs6.readFileSync(import_node_path8.join(this.projectPath, filePath), "utf-8");
|
|
3026
3065
|
return import_node_crypto2.createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
3027
3066
|
} catch {
|
|
3028
3067
|
return null;
|
|
@@ -3126,8 +3165,8 @@ Return ONLY valid JSON, no markdown formatting.`;
|
|
|
3126
3165
|
}
|
|
3127
3166
|
}
|
|
3128
3167
|
// src/agent/document-fetcher.ts
|
|
3129
|
-
var
|
|
3130
|
-
var
|
|
3168
|
+
var import_node_fs7 = require("node:fs");
|
|
3169
|
+
var import_node_path9 = require("node:path");
|
|
3131
3170
|
class DocumentFetcher {
|
|
3132
3171
|
deps;
|
|
3133
3172
|
constructor(deps) {
|
|
@@ -3135,8 +3174,8 @@ class DocumentFetcher {
|
|
|
3135
3174
|
}
|
|
3136
3175
|
async fetch() {
|
|
3137
3176
|
const documentsDir = getLocusPath(this.deps.projectPath, "documentsDir");
|
|
3138
|
-
if (!
|
|
3139
|
-
|
|
3177
|
+
if (!import_node_fs7.existsSync(documentsDir)) {
|
|
3178
|
+
import_node_fs7.mkdirSync(documentsDir, { recursive: true });
|
|
3140
3179
|
}
|
|
3141
3180
|
try {
|
|
3142
3181
|
const groups = await this.deps.client.docs.listGroups(this.deps.workspaceId);
|
|
@@ -3149,14 +3188,14 @@ class DocumentFetcher {
|
|
|
3149
3188
|
continue;
|
|
3150
3189
|
}
|
|
3151
3190
|
const groupName = groupMap.get(doc.groupId || "") || "General";
|
|
3152
|
-
const groupDir =
|
|
3153
|
-
if (!
|
|
3154
|
-
|
|
3191
|
+
const groupDir = import_node_path9.join(documentsDir, groupName);
|
|
3192
|
+
if (!import_node_fs7.existsSync(groupDir)) {
|
|
3193
|
+
import_node_fs7.mkdirSync(groupDir, { recursive: true });
|
|
3155
3194
|
}
|
|
3156
3195
|
const fileName = `${doc.title}.md`;
|
|
3157
|
-
const filePath =
|
|
3158
|
-
if (!
|
|
3159
|
-
|
|
3196
|
+
const filePath = import_node_path9.join(groupDir, fileName);
|
|
3197
|
+
if (!import_node_fs7.existsSync(filePath) || import_node_fs7.readFileSync(filePath, "utf-8") !== doc.content) {
|
|
3198
|
+
import_node_fs7.writeFileSync(filePath, doc.content || "");
|
|
3160
3199
|
fetchedCount++;
|
|
3161
3200
|
}
|
|
3162
3201
|
}
|
|
@@ -3853,8 +3892,8 @@ class ExecEventEmitter {
|
|
|
3853
3892
|
}
|
|
3854
3893
|
}
|
|
3855
3894
|
// src/exec/history-manager.ts
|
|
3856
|
-
var
|
|
3857
|
-
var
|
|
3895
|
+
var import_node_fs8 = require("node:fs");
|
|
3896
|
+
var import_node_path10 = require("node:path");
|
|
3858
3897
|
var DEFAULT_MAX_SESSIONS = 30;
|
|
3859
3898
|
function generateSessionId2() {
|
|
3860
3899
|
const timestamp = Date.now().toString(36);
|
|
@@ -3866,30 +3905,30 @@ class HistoryManager {
|
|
|
3866
3905
|
historyDir;
|
|
3867
3906
|
maxSessions;
|
|
3868
3907
|
constructor(projectPath, options) {
|
|
3869
|
-
this.historyDir = options?.historyDir ??
|
|
3908
|
+
this.historyDir = options?.historyDir ?? import_node_path10.join(projectPath, LOCUS_CONFIG.dir, LOCUS_CONFIG.sessionsDir);
|
|
3870
3909
|
this.maxSessions = options?.maxSessions ?? DEFAULT_MAX_SESSIONS;
|
|
3871
3910
|
this.ensureHistoryDir();
|
|
3872
3911
|
}
|
|
3873
3912
|
ensureHistoryDir() {
|
|
3874
|
-
if (!
|
|
3875
|
-
|
|
3913
|
+
if (!import_node_fs8.existsSync(this.historyDir)) {
|
|
3914
|
+
import_node_fs8.mkdirSync(this.historyDir, { recursive: true });
|
|
3876
3915
|
}
|
|
3877
3916
|
}
|
|
3878
3917
|
getSessionPath(sessionId) {
|
|
3879
|
-
return
|
|
3918
|
+
return import_node_path10.join(this.historyDir, `${sessionId}.json`);
|
|
3880
3919
|
}
|
|
3881
3920
|
saveSession(session) {
|
|
3882
3921
|
const filePath = this.getSessionPath(session.id);
|
|
3883
3922
|
session.updatedAt = Date.now();
|
|
3884
|
-
|
|
3923
|
+
import_node_fs8.writeFileSync(filePath, JSON.stringify(session, null, 2), "utf-8");
|
|
3885
3924
|
}
|
|
3886
3925
|
loadSession(sessionId) {
|
|
3887
3926
|
const filePath = this.getSessionPath(sessionId);
|
|
3888
|
-
if (!
|
|
3927
|
+
if (!import_node_fs8.existsSync(filePath)) {
|
|
3889
3928
|
return null;
|
|
3890
3929
|
}
|
|
3891
3930
|
try {
|
|
3892
|
-
const content =
|
|
3931
|
+
const content = import_node_fs8.readFileSync(filePath, "utf-8");
|
|
3893
3932
|
return JSON.parse(content);
|
|
3894
3933
|
} catch {
|
|
3895
3934
|
return null;
|
|
@@ -3897,18 +3936,18 @@ class HistoryManager {
|
|
|
3897
3936
|
}
|
|
3898
3937
|
deleteSession(sessionId) {
|
|
3899
3938
|
const filePath = this.getSessionPath(sessionId);
|
|
3900
|
-
if (!
|
|
3939
|
+
if (!import_node_fs8.existsSync(filePath)) {
|
|
3901
3940
|
return false;
|
|
3902
3941
|
}
|
|
3903
3942
|
try {
|
|
3904
|
-
|
|
3943
|
+
import_node_fs8.rmSync(filePath);
|
|
3905
3944
|
return true;
|
|
3906
3945
|
} catch {
|
|
3907
3946
|
return false;
|
|
3908
3947
|
}
|
|
3909
3948
|
}
|
|
3910
3949
|
listSessions(options) {
|
|
3911
|
-
const files =
|
|
3950
|
+
const files = import_node_fs8.readdirSync(this.historyDir);
|
|
3912
3951
|
let sessions = [];
|
|
3913
3952
|
for (const file of files) {
|
|
3914
3953
|
if (file.endsWith(".json")) {
|
|
@@ -3981,11 +4020,11 @@ class HistoryManager {
|
|
|
3981
4020
|
return deleted;
|
|
3982
4021
|
}
|
|
3983
4022
|
getSessionCount() {
|
|
3984
|
-
const files =
|
|
4023
|
+
const files = import_node_fs8.readdirSync(this.historyDir);
|
|
3985
4024
|
return files.filter((f) => f.endsWith(".json")).length;
|
|
3986
4025
|
}
|
|
3987
4026
|
sessionExists(sessionId) {
|
|
3988
|
-
return
|
|
4027
|
+
return import_node_fs8.existsSync(this.getSessionPath(sessionId));
|
|
3989
4028
|
}
|
|
3990
4029
|
findSessionByPartialId(partialId) {
|
|
3991
4030
|
const sessions = this.listSessions();
|
|
@@ -3999,12 +4038,12 @@ class HistoryManager {
|
|
|
3999
4038
|
return this.historyDir;
|
|
4000
4039
|
}
|
|
4001
4040
|
clearAllSessions() {
|
|
4002
|
-
const files =
|
|
4041
|
+
const files = import_node_fs8.readdirSync(this.historyDir);
|
|
4003
4042
|
let deleted = 0;
|
|
4004
4043
|
for (const file of files) {
|
|
4005
4044
|
if (file.endsWith(".json")) {
|
|
4006
4045
|
try {
|
|
4007
|
-
|
|
4046
|
+
import_node_fs8.rmSync(import_node_path10.join(this.historyDir, file));
|
|
4008
4047
|
deleted++;
|
|
4009
4048
|
} catch {}
|
|
4010
4049
|
}
|
|
@@ -4270,8 +4309,8 @@ ${currentPrompt}`);
|
|
|
4270
4309
|
}
|
|
4271
4310
|
// src/orchestrator.ts
|
|
4272
4311
|
var import_node_child_process7 = require("node:child_process");
|
|
4273
|
-
var
|
|
4274
|
-
var
|
|
4312
|
+
var import_node_fs9 = require("node:fs");
|
|
4313
|
+
var import_node_path11 = require("node:path");
|
|
4275
4314
|
var import_node_url = require("node:url");
|
|
4276
4315
|
var import_shared4 = require("@locusai/shared");
|
|
4277
4316
|
var import_events4 = require("events");
|
|
@@ -4482,13 +4521,13 @@ ${agentId} finished (exit code: ${code})`);
|
|
|
4482
4521
|
}
|
|
4483
4522
|
resolveWorkerPath() {
|
|
4484
4523
|
const currentModulePath = import_node_url.fileURLToPath("file:///home/runner/work/locusai/locusai/packages/sdk/src/orchestrator.ts");
|
|
4485
|
-
const currentModuleDir =
|
|
4524
|
+
const currentModuleDir = import_node_path11.dirname(currentModulePath);
|
|
4486
4525
|
const potentialPaths = [
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4526
|
+
import_node_path11.join(currentModuleDir, "agent", "worker.js"),
|
|
4527
|
+
import_node_path11.join(currentModuleDir, "worker.js"),
|
|
4528
|
+
import_node_path11.join(currentModuleDir, "agent", "worker.ts")
|
|
4490
4529
|
];
|
|
4491
|
-
return potentialPaths.find((p) =>
|
|
4530
|
+
return potentialPaths.find((p) => import_node_fs9.existsSync(p));
|
|
4492
4531
|
}
|
|
4493
4532
|
startHeartbeatMonitor() {
|
|
4494
4533
|
this.heartbeatInterval = setInterval(() => {
|
|
@@ -4663,8 +4702,8 @@ ${summary}`
|
|
|
4663
4702
|
}
|
|
4664
4703
|
}
|
|
4665
4704
|
// src/planning/plan-manager.ts
|
|
4666
|
-
var
|
|
4667
|
-
var
|
|
4705
|
+
var import_node_fs10 = require("node:fs");
|
|
4706
|
+
var import_node_path12 = require("node:path");
|
|
4668
4707
|
|
|
4669
4708
|
// src/planning/sprint-plan.ts
|
|
4670
4709
|
var import_shared5 = require("@locusai/shared");
|
|
@@ -4787,19 +4826,19 @@ class PlanManager {
|
|
|
4787
4826
|
save(plan) {
|
|
4788
4827
|
this.ensurePlansDir();
|
|
4789
4828
|
const slug = this.slugify(plan.name);
|
|
4790
|
-
const jsonPath =
|
|
4791
|
-
const mdPath =
|
|
4792
|
-
|
|
4793
|
-
|
|
4829
|
+
const jsonPath = import_node_path12.join(this.plansDir, `${slug}.json`);
|
|
4830
|
+
const mdPath = import_node_path12.join(this.plansDir, `sprint-${slug}.md`);
|
|
4831
|
+
import_node_fs10.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf-8");
|
|
4832
|
+
import_node_fs10.writeFileSync(mdPath, sprintPlanToMarkdown(plan), "utf-8");
|
|
4794
4833
|
return plan.id;
|
|
4795
4834
|
}
|
|
4796
4835
|
load(idOrSlug) {
|
|
4797
4836
|
this.ensurePlansDir();
|
|
4798
|
-
const files =
|
|
4837
|
+
const files = import_node_fs10.readdirSync(this.plansDir).filter((f) => f.endsWith(".json"));
|
|
4799
4838
|
for (const file of files) {
|
|
4800
|
-
const filePath =
|
|
4839
|
+
const filePath = import_node_path12.join(this.plansDir, file);
|
|
4801
4840
|
try {
|
|
4802
|
-
const plan = JSON.parse(
|
|
4841
|
+
const plan = JSON.parse(import_node_fs10.readFileSync(filePath, "utf-8"));
|
|
4803
4842
|
if (plan.id === idOrSlug || this.slugify(plan.name) === idOrSlug) {
|
|
4804
4843
|
return plan;
|
|
4805
4844
|
}
|
|
@@ -4809,11 +4848,11 @@ class PlanManager {
|
|
|
4809
4848
|
}
|
|
4810
4849
|
list(status) {
|
|
4811
4850
|
this.ensurePlansDir();
|
|
4812
|
-
const files =
|
|
4851
|
+
const files = import_node_fs10.readdirSync(this.plansDir).filter((f) => f.endsWith(".json"));
|
|
4813
4852
|
const plans = [];
|
|
4814
4853
|
for (const file of files) {
|
|
4815
4854
|
try {
|
|
4816
|
-
const plan = JSON.parse(
|
|
4855
|
+
const plan = JSON.parse(import_node_fs10.readFileSync(import_node_path12.join(this.plansDir, file), "utf-8"));
|
|
4817
4856
|
if (!status || plan.status === status) {
|
|
4818
4857
|
plans.push(plan);
|
|
4819
4858
|
}
|
|
@@ -4876,18 +4915,18 @@ class PlanManager {
|
|
|
4876
4915
|
}
|
|
4877
4916
|
delete(idOrSlug) {
|
|
4878
4917
|
this.ensurePlansDir();
|
|
4879
|
-
const files =
|
|
4918
|
+
const files = import_node_fs10.readdirSync(this.plansDir);
|
|
4880
4919
|
for (const file of files) {
|
|
4881
|
-
const filePath =
|
|
4920
|
+
const filePath = import_node_path12.join(this.plansDir, file);
|
|
4882
4921
|
if (!file.endsWith(".json"))
|
|
4883
4922
|
continue;
|
|
4884
4923
|
try {
|
|
4885
|
-
const plan = JSON.parse(
|
|
4924
|
+
const plan = JSON.parse(import_node_fs10.readFileSync(filePath, "utf-8"));
|
|
4886
4925
|
if (plan.id === idOrSlug || this.slugify(plan.name) === idOrSlug) {
|
|
4887
|
-
|
|
4888
|
-
const mdPath =
|
|
4889
|
-
if (
|
|
4890
|
-
|
|
4926
|
+
import_node_fs10.unlinkSync(filePath);
|
|
4927
|
+
const mdPath = import_node_path12.join(this.plansDir, `sprint-${this.slugify(plan.name)}.md`);
|
|
4928
|
+
if (import_node_fs10.existsSync(mdPath)) {
|
|
4929
|
+
import_node_fs10.unlinkSync(mdPath);
|
|
4891
4930
|
}
|
|
4892
4931
|
return;
|
|
4893
4932
|
}
|
|
@@ -4901,8 +4940,8 @@ class PlanManager {
|
|
|
4901
4940
|
return sprintPlanToMarkdown(plan);
|
|
4902
4941
|
}
|
|
4903
4942
|
ensurePlansDir() {
|
|
4904
|
-
if (!
|
|
4905
|
-
|
|
4943
|
+
if (!import_node_fs10.existsSync(this.plansDir)) {
|
|
4944
|
+
import_node_fs10.mkdirSync(this.plansDir, { recursive: true });
|
|
4906
4945
|
}
|
|
4907
4946
|
}
|
|
4908
4947
|
slugify(name) {
|
|
@@ -4910,7 +4949,7 @@ class PlanManager {
|
|
|
4910
4949
|
}
|
|
4911
4950
|
}
|
|
4912
4951
|
// src/planning/planning-meeting.ts
|
|
4913
|
-
var
|
|
4952
|
+
var import_node_fs11 = require("node:fs");
|
|
4914
4953
|
|
|
4915
4954
|
// src/planning/agents/architect.ts
|
|
4916
4955
|
function buildArchitectPrompt(input) {
|
|
@@ -5164,11 +5203,11 @@ class PlanningMeeting {
|
|
|
5164
5203
|
}
|
|
5165
5204
|
getCodebaseIndex() {
|
|
5166
5205
|
const indexPath = getLocusPath(this.projectPath, "indexFile");
|
|
5167
|
-
if (!
|
|
5206
|
+
if (!import_node_fs11.existsSync(indexPath)) {
|
|
5168
5207
|
return "";
|
|
5169
5208
|
}
|
|
5170
5209
|
try {
|
|
5171
|
-
const raw =
|
|
5210
|
+
const raw = import_node_fs11.readFileSync(indexPath, "utf-8");
|
|
5172
5211
|
const index = JSON.parse(raw);
|
|
5173
5212
|
const parts = [];
|
|
5174
5213
|
if (index.responsibilities) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a PATH string that includes common CLI binary directories
|
|
3
|
+
* in addition to the current process PATH. Existing entries take priority.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getAugmentedPath(): string;
|
|
6
|
+
/**
|
|
7
|
+
* Returns a copy of the current process.env with an augmented PATH.
|
|
8
|
+
* Use this when spawning CLI tools (claude, codex) to ensure they
|
|
9
|
+
* can be found even when running from restricted environments.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getAugmentedEnv(overrides?: Record<string, string>): NodeJS.ProcessEnv;
|
|
12
|
+
//# sourceMappingURL=resolve-bin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-bin.d.ts","sourceRoot":"","sources":["../../src/utils/resolve-bin.ts"],"names":[],"mappings":"AAuCA;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAUzC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACrC,MAAM,CAAC,UAAU,CAMnB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@locusai/sdk",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"clean": "rm -rf node_modules"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@locusai/shared": "^0.9.
|
|
33
|
+
"@locusai/shared": "^0.9.5",
|
|
34
34
|
"axios": "^1.13.2",
|
|
35
35
|
"events": "^3.3.0",
|
|
36
36
|
"globby": "^14.0.2"
|