@locusai/cli 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/agent/worker.js +130 -323
- package/bin/locus.js +433 -827
- package/package.json +2 -2
package/bin/agent/worker.js
CHANGED
|
@@ -15249,9 +15249,6 @@ var init_src = __esm(() => {
|
|
|
15249
15249
|
// ../sdk/src/core/config.ts
|
|
15250
15250
|
import { join } from "node:path";
|
|
15251
15251
|
function getLocusPath(projectPath, fileName) {
|
|
15252
|
-
if (fileName === "projectContextFile" || fileName === "projectProgressFile") {
|
|
15253
|
-
return join(projectPath, LOCUS_CONFIG.dir, LOCUS_CONFIG.projectDir, LOCUS_CONFIG[fileName]);
|
|
15254
|
-
}
|
|
15255
15252
|
return join(projectPath, LOCUS_CONFIG.dir, LOCUS_CONFIG[fileName]);
|
|
15256
15253
|
}
|
|
15257
15254
|
var PROVIDER, DEFAULT_MODEL, LOCUS_SCHEMA_BASE_URL = "https://locusai.dev/schemas", LOCUS_SCHEMAS, LOCUS_CONFIG;
|
|
@@ -15274,14 +15271,12 @@ var init_config = __esm(() => {
|
|
|
15274
15271
|
settingsFile: "settings.json",
|
|
15275
15272
|
indexFile: "codebase-index.json",
|
|
15276
15273
|
contextFile: "LOCUS.md",
|
|
15274
|
+
learningsFile: "LEARNINGS.md",
|
|
15277
15275
|
artifactsDir: "artifacts",
|
|
15278
15276
|
documentsDir: "documents",
|
|
15279
15277
|
sessionsDir: "sessions",
|
|
15280
15278
|
reviewsDir: "reviews",
|
|
15281
|
-
plansDir: "plans"
|
|
15282
|
-
projectDir: "project",
|
|
15283
|
-
projectContextFile: "context.md",
|
|
15284
|
-
projectProgressFile: "progress.md"
|
|
15279
|
+
plansDir: "plans"
|
|
15285
15280
|
};
|
|
15286
15281
|
});
|
|
15287
15282
|
|
|
@@ -15523,17 +15518,22 @@ class ClaudeRunner {
|
|
|
15523
15518
|
});
|
|
15524
15519
|
});
|
|
15525
15520
|
}
|
|
15526
|
-
|
|
15521
|
+
buildCliArgs() {
|
|
15527
15522
|
const args = [
|
|
15528
|
-
"--dangerously-skip-permissions",
|
|
15529
15523
|
"--print",
|
|
15530
|
-
"--verbose",
|
|
15531
15524
|
"--output-format",
|
|
15532
15525
|
"stream-json",
|
|
15526
|
+
"--verbose",
|
|
15527
|
+
"--dangerously-skip-permissions",
|
|
15528
|
+
"--no-session-persistence",
|
|
15533
15529
|
"--include-partial-messages",
|
|
15534
15530
|
"--model",
|
|
15535
15531
|
this.model
|
|
15536
15532
|
];
|
|
15533
|
+
return args;
|
|
15534
|
+
}
|
|
15535
|
+
async* runStream(prompt) {
|
|
15536
|
+
const args = this.buildCliArgs();
|
|
15537
15537
|
const env = getAugmentedEnv({
|
|
15538
15538
|
FORCE_COLOR: "1",
|
|
15539
15539
|
TERM: "xterm-256color"
|
|
@@ -15773,16 +15773,7 @@ class ClaudeRunner {
|
|
|
15773
15773
|
}
|
|
15774
15774
|
executeRun(prompt) {
|
|
15775
15775
|
return new Promise((resolve2, reject) => {
|
|
15776
|
-
const args =
|
|
15777
|
-
"--dangerously-skip-permissions",
|
|
15778
|
-
"--print",
|
|
15779
|
-
"--verbose",
|
|
15780
|
-
"--output-format",
|
|
15781
|
-
"stream-json",
|
|
15782
|
-
"--include-partial-messages",
|
|
15783
|
-
"--model",
|
|
15784
|
-
this.model
|
|
15785
|
-
];
|
|
15776
|
+
const args = this.buildCliArgs();
|
|
15786
15777
|
const env = getAugmentedEnv({
|
|
15787
15778
|
FORCE_COLOR: "1",
|
|
15788
15779
|
TERM: "xterm-256color"
|
|
@@ -15907,7 +15898,7 @@ class CodexRunner {
|
|
|
15907
15898
|
eventEmitter;
|
|
15908
15899
|
currentToolName;
|
|
15909
15900
|
timeoutMs;
|
|
15910
|
-
constructor(projectPath, model = DEFAULT_MODEL[PROVIDER.CODEX], log,
|
|
15901
|
+
constructor(projectPath, model = DEFAULT_MODEL[PROVIDER.CODEX], log, reasoningEffort, timeoutMs) {
|
|
15911
15902
|
this.projectPath = projectPath;
|
|
15912
15903
|
this.model = model;
|
|
15913
15904
|
this.log = log;
|
|
@@ -16233,7 +16224,7 @@ function createAiRunner(provider, config2) {
|
|
|
16233
16224
|
const model = config2.model ?? DEFAULT_MODEL[resolvedProvider];
|
|
16234
16225
|
switch (resolvedProvider) {
|
|
16235
16226
|
case PROVIDER.CODEX:
|
|
16236
|
-
return new CodexRunner(config2.projectPath, model, config2.log, config2.
|
|
16227
|
+
return new CodexRunner(config2.projectPath, model, config2.log, config2.reasoningEffort ?? "high", config2.timeoutMs);
|
|
16237
16228
|
default:
|
|
16238
16229
|
return new ClaudeRunner(config2.projectPath, model, config2.log, config2.timeoutMs);
|
|
16239
16230
|
}
|
|
@@ -31771,102 +31762,6 @@ var init_src2 = __esm(() => {
|
|
|
31771
31762
|
init_workspaces();
|
|
31772
31763
|
});
|
|
31773
31764
|
|
|
31774
|
-
// ../sdk/src/project/knowledge-base.ts
|
|
31775
|
-
import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, writeFileSync } from "node:fs";
|
|
31776
|
-
import { dirname } from "node:path";
|
|
31777
|
-
|
|
31778
|
-
class KnowledgeBase {
|
|
31779
|
-
contextPath;
|
|
31780
|
-
progressPath;
|
|
31781
|
-
constructor(projectPath) {
|
|
31782
|
-
this.contextPath = getLocusPath(projectPath, "projectContextFile");
|
|
31783
|
-
this.progressPath = getLocusPath(projectPath, "projectProgressFile");
|
|
31784
|
-
}
|
|
31785
|
-
readContext() {
|
|
31786
|
-
if (!existsSync3(this.contextPath)) {
|
|
31787
|
-
return "";
|
|
31788
|
-
}
|
|
31789
|
-
return readFileSync3(this.contextPath, "utf-8");
|
|
31790
|
-
}
|
|
31791
|
-
readProgress() {
|
|
31792
|
-
if (!existsSync3(this.progressPath)) {
|
|
31793
|
-
return "";
|
|
31794
|
-
}
|
|
31795
|
-
return readFileSync3(this.progressPath, "utf-8");
|
|
31796
|
-
}
|
|
31797
|
-
updateContext(content) {
|
|
31798
|
-
this.ensureDir(this.contextPath);
|
|
31799
|
-
writeFileSync(this.contextPath, content);
|
|
31800
|
-
}
|
|
31801
|
-
updateProgress(entry) {
|
|
31802
|
-
this.ensureDir(this.progressPath);
|
|
31803
|
-
const existing = this.readProgress();
|
|
31804
|
-
const timestamp = (entry.timestamp ?? new Date).toISOString();
|
|
31805
|
-
const label = entry.role === "user" ? "User" : "Assistant";
|
|
31806
|
-
const line = `**${label}** (${timestamp}):
|
|
31807
|
-
${entry.content}`;
|
|
31808
|
-
const updated = existing ? `${existing}
|
|
31809
|
-
|
|
31810
|
-
---
|
|
31811
|
-
|
|
31812
|
-
${line}` : `# Conversation History
|
|
31813
|
-
|
|
31814
|
-
${line}`;
|
|
31815
|
-
writeFileSync(this.progressPath, updated);
|
|
31816
|
-
}
|
|
31817
|
-
getFullContext() {
|
|
31818
|
-
const context2 = this.readContext();
|
|
31819
|
-
const parts = [];
|
|
31820
|
-
if (context2.trim()) {
|
|
31821
|
-
parts.push(context2.trim());
|
|
31822
|
-
}
|
|
31823
|
-
return parts.join(`
|
|
31824
|
-
|
|
31825
|
-
---
|
|
31826
|
-
|
|
31827
|
-
`);
|
|
31828
|
-
}
|
|
31829
|
-
initialize(info) {
|
|
31830
|
-
this.ensureDir(this.contextPath);
|
|
31831
|
-
this.ensureDir(this.progressPath);
|
|
31832
|
-
const techStackList = info.techStack.map((t) => `- ${t}`).join(`
|
|
31833
|
-
`);
|
|
31834
|
-
const contextContent = `# Project: ${info.name}
|
|
31835
|
-
|
|
31836
|
-
## Mission
|
|
31837
|
-
${info.mission}
|
|
31838
|
-
|
|
31839
|
-
## Tech Stack
|
|
31840
|
-
${techStackList}
|
|
31841
|
-
|
|
31842
|
-
## Architecture
|
|
31843
|
-
<!-- Describe your high-level architecture here -->
|
|
31844
|
-
|
|
31845
|
-
## Key Decisions
|
|
31846
|
-
<!-- Document important technical decisions and their rationale -->
|
|
31847
|
-
|
|
31848
|
-
## Feature Areas
|
|
31849
|
-
<!-- List your main feature areas and their status -->
|
|
31850
|
-
`;
|
|
31851
|
-
const progressContent = `# Conversation History
|
|
31852
|
-
`;
|
|
31853
|
-
writeFileSync(this.contextPath, contextContent);
|
|
31854
|
-
writeFileSync(this.progressPath, progressContent);
|
|
31855
|
-
}
|
|
31856
|
-
get exists() {
|
|
31857
|
-
return existsSync3(this.contextPath) || existsSync3(this.progressPath);
|
|
31858
|
-
}
|
|
31859
|
-
ensureDir(filePath) {
|
|
31860
|
-
const dir = dirname(filePath);
|
|
31861
|
-
if (!existsSync3(dir)) {
|
|
31862
|
-
mkdirSync(dir, { recursive: true });
|
|
31863
|
-
}
|
|
31864
|
-
}
|
|
31865
|
-
}
|
|
31866
|
-
var init_knowledge_base = __esm(() => {
|
|
31867
|
-
init_config();
|
|
31868
|
-
});
|
|
31869
|
-
|
|
31870
31765
|
// ../sdk/src/agent/git-workflow.ts
|
|
31871
31766
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
31872
31767
|
|
|
@@ -32113,7 +32008,7 @@ var init_git_workflow = __esm(() => {
|
|
|
32113
32008
|
});
|
|
32114
32009
|
|
|
32115
32010
|
// ../sdk/src/core/prompt-builder.ts
|
|
32116
|
-
import { existsSync as
|
|
32011
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
|
|
32117
32012
|
import { join as join4 } from "node:path";
|
|
32118
32013
|
|
|
32119
32014
|
class PromptBuilder {
|
|
@@ -32121,223 +32016,157 @@ class PromptBuilder {
|
|
|
32121
32016
|
constructor(projectPath) {
|
|
32122
32017
|
this.projectPath = projectPath;
|
|
32123
32018
|
}
|
|
32124
|
-
async build(task2
|
|
32125
|
-
let prompt = `# Task: ${task2.title}
|
|
32126
|
-
|
|
32127
|
-
`;
|
|
32019
|
+
async build(task2) {
|
|
32128
32020
|
const roleText = this.roleToText(task2.assigneeRole);
|
|
32021
|
+
const description = task2.description || "No description provided.";
|
|
32022
|
+
const context2 = this.getProjectContext();
|
|
32023
|
+
const learnings = this.getLearningsContent();
|
|
32024
|
+
const knowledgeBase = this.getKnowledgeBaseSection();
|
|
32025
|
+
let sections = "";
|
|
32129
32026
|
if (roleText) {
|
|
32130
|
-
|
|
32027
|
+
sections += `
|
|
32028
|
+
<role>
|
|
32131
32029
|
You are acting as a ${roleText}.
|
|
32132
|
-
|
|
32030
|
+
</role>
|
|
32133
32031
|
`;
|
|
32134
32032
|
}
|
|
32135
|
-
|
|
32136
|
-
|
|
32137
|
-
|
|
32138
|
-
`;
|
|
32139
|
-
const projectConfig = this.getProjectConfig();
|
|
32140
|
-
if (projectConfig) {
|
|
32141
|
-
prompt += `## Project Metadata
|
|
32142
|
-
`;
|
|
32143
|
-
prompt += `- Version: ${projectConfig.version || "Unknown"}
|
|
32144
|
-
`;
|
|
32145
|
-
prompt += `- Created At: ${projectConfig.createdAt || "Unknown"}
|
|
32146
|
-
|
|
32147
|
-
`;
|
|
32148
|
-
}
|
|
32149
|
-
let serverContext = null;
|
|
32150
|
-
if (options.taskContext) {
|
|
32151
|
-
try {
|
|
32152
|
-
serverContext = JSON.parse(options.taskContext);
|
|
32153
|
-
} catch {
|
|
32154
|
-
serverContext = { context: options.taskContext };
|
|
32155
|
-
}
|
|
32156
|
-
}
|
|
32157
|
-
const contextPath = getLocusPath(this.projectPath, "contextFile");
|
|
32158
|
-
let hasLocalContext = false;
|
|
32159
|
-
if (existsSync4(contextPath)) {
|
|
32160
|
-
try {
|
|
32161
|
-
const context2 = readFileSync4(contextPath, "utf-8");
|
|
32162
|
-
if (context2.trim().length > 20) {
|
|
32163
|
-
prompt += `## Project Context (Local)
|
|
32033
|
+
if (context2) {
|
|
32034
|
+
sections += `
|
|
32035
|
+
<project_context>
|
|
32164
32036
|
${context2}
|
|
32165
|
-
|
|
32166
|
-
`;
|
|
32167
|
-
hasLocalContext = true;
|
|
32168
|
-
}
|
|
32169
|
-
} catch (err) {
|
|
32170
|
-
console.warn(`Warning: Could not read context file: ${err}`);
|
|
32171
|
-
}
|
|
32172
|
-
}
|
|
32173
|
-
if (!hasLocalContext) {
|
|
32174
|
-
const fallback = this.getFallbackContext();
|
|
32175
|
-
if (fallback) {
|
|
32176
|
-
prompt += `## Project Context (README Fallback)
|
|
32177
|
-
${fallback}
|
|
32178
|
-
|
|
32037
|
+
</project_context>
|
|
32179
32038
|
`;
|
|
32180
|
-
}
|
|
32181
32039
|
}
|
|
32182
|
-
|
|
32183
|
-
|
|
32184
|
-
|
|
32185
|
-
|
|
32186
|
-
if (project) {
|
|
32187
|
-
prompt += `- Project: ${project.name || "Unknown"}
|
|
32188
|
-
`;
|
|
32189
|
-
if (!hasLocalContext && project.techStack?.length) {
|
|
32190
|
-
prompt += `- Tech Stack: ${project.techStack.join(", ")}
|
|
32040
|
+
sections += `
|
|
32041
|
+
<knowledge_base>
|
|
32042
|
+
${knowledgeBase}
|
|
32043
|
+
</knowledge_base>
|
|
32191
32044
|
`;
|
|
32192
|
-
|
|
32193
|
-
|
|
32194
|
-
|
|
32195
|
-
|
|
32196
|
-
${
|
|
32197
|
-
|
|
32198
|
-
}
|
|
32199
|
-
prompt += `
|
|
32045
|
+
if (learnings) {
|
|
32046
|
+
sections += `
|
|
32047
|
+
<learnings>
|
|
32048
|
+
These are accumulated lessons from past tasks. Follow them to avoid repeating mistakes:
|
|
32049
|
+
${learnings}
|
|
32050
|
+
</learnings>
|
|
32200
32051
|
`;
|
|
32201
32052
|
}
|
|
32202
|
-
prompt += this.getProjectStructure();
|
|
32203
|
-
prompt += `## Project Knowledge Base
|
|
32204
|
-
`;
|
|
32205
|
-
prompt += `You have access to the following documentation directories for context:
|
|
32206
|
-
`;
|
|
32207
|
-
prompt += `- Artifacts: \`.locus/artifacts\`
|
|
32208
|
-
`;
|
|
32209
|
-
prompt += `- Documents: \`.locus/documents\`
|
|
32210
|
-
`;
|
|
32211
|
-
prompt += `If you need more information about the project strategies, plans, or architecture, please read files in these directories.
|
|
32212
|
-
|
|
32213
|
-
`;
|
|
32214
32053
|
if (task2.docs && task2.docs.length > 0) {
|
|
32215
|
-
|
|
32216
|
-
`;
|
|
32217
|
-
prompt += `> Full content available on server. Rely on Task Description for specific requirements.
|
|
32218
|
-
|
|
32219
|
-
`;
|
|
32054
|
+
let docsContent = "";
|
|
32220
32055
|
for (const doc3 of task2.docs) {
|
|
32221
32056
|
const content = doc3.content || "";
|
|
32222
32057
|
const limit = 800;
|
|
32223
32058
|
const preview = content.slice(0, limit);
|
|
32224
32059
|
const isTruncated = content.length > limit;
|
|
32225
|
-
|
|
32060
|
+
docsContent += `### ${doc3.title}
|
|
32226
32061
|
${preview}${isTruncated ? `
|
|
32227
32062
|
...(truncated)...` : ""}
|
|
32228
32063
|
|
|
32229
32064
|
`;
|
|
32230
32065
|
}
|
|
32066
|
+
sections += `
|
|
32067
|
+
<documents>
|
|
32068
|
+
${docsContent.trimEnd()}
|
|
32069
|
+
</documents>
|
|
32070
|
+
`;
|
|
32231
32071
|
}
|
|
32232
32072
|
if (task2.acceptanceChecklist && task2.acceptanceChecklist.length > 0) {
|
|
32233
|
-
|
|
32234
|
-
`;
|
|
32073
|
+
let criteria = "";
|
|
32235
32074
|
for (const item of task2.acceptanceChecklist) {
|
|
32236
|
-
|
|
32075
|
+
criteria += `- ${item.done ? "[x]" : "[ ]"} ${item.text}
|
|
32237
32076
|
`;
|
|
32238
32077
|
}
|
|
32239
|
-
|
|
32078
|
+
sections += `
|
|
32079
|
+
<acceptance_criteria>
|
|
32080
|
+
${criteria.trimEnd()}
|
|
32081
|
+
</acceptance_criteria>
|
|
32240
32082
|
`;
|
|
32241
32083
|
}
|
|
32242
32084
|
if (task2.comments && task2.comments.length > 0) {
|
|
32243
32085
|
const filteredComments = task2.comments.filter((comment) => comment.author !== "system");
|
|
32244
32086
|
const comments = filteredComments.slice(0, 3);
|
|
32245
|
-
|
|
32087
|
+
if (comments.length > 0) {
|
|
32088
|
+
let commentsContent = "";
|
|
32089
|
+
for (const comment of comments) {
|
|
32090
|
+
const date5 = new Date(comment.createdAt).toLocaleString();
|
|
32091
|
+
commentsContent += `- ${comment.author} (${date5}): ${comment.text}
|
|
32246
32092
|
`;
|
|
32247
|
-
|
|
32248
|
-
|
|
32249
|
-
|
|
32093
|
+
}
|
|
32094
|
+
sections += `
|
|
32095
|
+
<feedback>
|
|
32096
|
+
${commentsContent.trimEnd()}
|
|
32097
|
+
</feedback>
|
|
32250
32098
|
`;
|
|
32251
32099
|
}
|
|
32252
|
-
prompt += `
|
|
32253
|
-
`;
|
|
32254
32100
|
}
|
|
32255
|
-
|
|
32256
|
-
|
|
32257
|
-
|
|
32258
|
-
|
|
32259
|
-
|
|
32260
|
-
|
|
32261
|
-
|
|
32101
|
+
return `<task_execution>
|
|
32102
|
+
Complete this task: ${task2.title}
|
|
32103
|
+
|
|
32104
|
+
<description>
|
|
32105
|
+
${description}
|
|
32106
|
+
</description>
|
|
32107
|
+
${sections}
|
|
32108
|
+
<rules>
|
|
32109
|
+
- Complete the task as described
|
|
32110
|
+
- Save any high-level documentation (PRDs, technical drafts, architecture docs) in \`.locus/artifacts/\`
|
|
32111
|
+
- Use relative paths from the project root at all times — no absolute local paths
|
|
32112
|
+
- Do NOT run \`git add\`, \`git commit\`, \`git push\`, or create branches — Locus handles git automatically
|
|
32113
|
+
</rules>
|
|
32114
|
+
</task_execution>`;
|
|
32262
32115
|
}
|
|
32263
32116
|
async buildGenericPrompt(query) {
|
|
32264
|
-
|
|
32265
|
-
|
|
32266
|
-
|
|
32267
|
-
|
|
32268
|
-
|
|
32269
|
-
|
|
32117
|
+
const context2 = this.getProjectContext();
|
|
32118
|
+
const learnings = this.getLearningsContent();
|
|
32119
|
+
const knowledgeBase = this.getKnowledgeBaseSection();
|
|
32120
|
+
let sections = "";
|
|
32121
|
+
if (context2) {
|
|
32122
|
+
sections += `
|
|
32123
|
+
<project_context>
|
|
32124
|
+
${context2}
|
|
32125
|
+
</project_context>
|
|
32270
32126
|
`;
|
|
32271
|
-
|
|
32272
|
-
|
|
32273
|
-
|
|
32127
|
+
}
|
|
32128
|
+
sections += `
|
|
32129
|
+
<knowledge_base>
|
|
32130
|
+
${knowledgeBase}
|
|
32131
|
+
</knowledge_base>
|
|
32274
32132
|
`;
|
|
32275
|
-
|
|
32276
|
-
|
|
32277
|
-
|
|
32278
|
-
|
|
32133
|
+
if (learnings) {
|
|
32134
|
+
sections += `
|
|
32135
|
+
<learnings>
|
|
32136
|
+
These are accumulated lessons from past tasks. Follow them to avoid repeating mistakes:
|
|
32137
|
+
${learnings}
|
|
32138
|
+
</learnings>
|
|
32279
32139
|
`;
|
|
32280
32140
|
}
|
|
32141
|
+
return `<direct_execution>
|
|
32142
|
+
Execute this prompt: ${query}
|
|
32143
|
+
${sections}
|
|
32144
|
+
<rules>
|
|
32145
|
+
- Execute the prompt based on the provided project context
|
|
32146
|
+
- Use relative paths from the project root at all times — no absolute local paths
|
|
32147
|
+
- Do NOT run \`git add\`, \`git commit\`, \`git push\`, or create branches — Locus handles git automatically
|
|
32148
|
+
</rules>
|
|
32149
|
+
</direct_execution>`;
|
|
32150
|
+
}
|
|
32151
|
+
getProjectContext() {
|
|
32281
32152
|
const contextPath = getLocusPath(this.projectPath, "contextFile");
|
|
32282
|
-
|
|
32283
|
-
if (existsSync4(contextPath)) {
|
|
32153
|
+
if (existsSync3(contextPath)) {
|
|
32284
32154
|
try {
|
|
32285
|
-
const context2 =
|
|
32155
|
+
const context2 = readFileSync3(contextPath, "utf-8");
|
|
32286
32156
|
if (context2.trim().length > 20) {
|
|
32287
|
-
|
|
32288
|
-
${context2}
|
|
32289
|
-
|
|
32290
|
-
`;
|
|
32291
|
-
hasLocalContext = true;
|
|
32157
|
+
return context2;
|
|
32292
32158
|
}
|
|
32293
32159
|
} catch (err) {
|
|
32294
32160
|
console.warn(`Warning: Could not read context file: ${err}`);
|
|
32295
32161
|
}
|
|
32296
32162
|
}
|
|
32297
|
-
|
|
32298
|
-
const fallback = this.getFallbackContext();
|
|
32299
|
-
if (fallback) {
|
|
32300
|
-
prompt += `## Project Context (README Fallback)
|
|
32301
|
-
${fallback}
|
|
32302
|
-
|
|
32303
|
-
`;
|
|
32304
|
-
}
|
|
32305
|
-
}
|
|
32306
|
-
prompt += this.getProjectStructure();
|
|
32307
|
-
prompt += `## Project Knowledge Base
|
|
32308
|
-
`;
|
|
32309
|
-
prompt += `You have access to the following documentation directories for context:
|
|
32310
|
-
`;
|
|
32311
|
-
prompt += `- Artifacts: \`.locus/artifacts\` (local-only, not synced to cloud)
|
|
32312
|
-
`;
|
|
32313
|
-
prompt += `- Documents: \`.locus/documents\` (synced from cloud)
|
|
32314
|
-
`;
|
|
32315
|
-
prompt += `If you need more information about the project strategies, plans, or architecture, please read files in these directories.
|
|
32316
|
-
|
|
32317
|
-
`;
|
|
32318
|
-
prompt += `## Instructions
|
|
32319
|
-
1. Execute the prompt based on the provided project context.
|
|
32320
|
-
2. **Paths**: Use relative paths from the project root at all times. Do NOT use absolute local paths (e.g., /Users/...).
|
|
32321
|
-
3. **Git**: Do NOT run \`git add\`, \`git commit\`, \`git push\`, or create branches. The Locus system handles all git operations automatically after your execution completes.
|
|
32322
|
-
4. **Progress**: Do NOT modify \`.locus/project/progress.md\`. The system updates it automatically.`;
|
|
32323
|
-
return prompt;
|
|
32324
|
-
}
|
|
32325
|
-
getProjectConfig() {
|
|
32326
|
-
const configPath = getLocusPath(this.projectPath, "configFile");
|
|
32327
|
-
if (existsSync4(configPath)) {
|
|
32328
|
-
try {
|
|
32329
|
-
return JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
32330
|
-
} catch {
|
|
32331
|
-
return null;
|
|
32332
|
-
}
|
|
32333
|
-
}
|
|
32334
|
-
return null;
|
|
32163
|
+
return this.getFallbackContext() || null;
|
|
32335
32164
|
}
|
|
32336
32165
|
getFallbackContext() {
|
|
32337
32166
|
const readmePath = join4(this.projectPath, "README.md");
|
|
32338
|
-
if (
|
|
32167
|
+
if (existsSync3(readmePath)) {
|
|
32339
32168
|
try {
|
|
32340
|
-
const content =
|
|
32169
|
+
const content = readFileSync3(readmePath, "utf-8");
|
|
32341
32170
|
const limit = 1000;
|
|
32342
32171
|
return content.slice(0, limit) + (content.length > limit ? `
|
|
32343
32172
|
...(truncated)...` : "");
|
|
@@ -32347,32 +32176,28 @@ ${fallback}
|
|
|
32347
32176
|
}
|
|
32348
32177
|
return "";
|
|
32349
32178
|
}
|
|
32350
|
-
|
|
32179
|
+
getKnowledgeBaseSection() {
|
|
32180
|
+
return `You have access to the following documentation directories for context:
|
|
32181
|
+
- Artifacts: \`.locus/artifacts\` (local-only, not synced to cloud)
|
|
32182
|
+
- Documents: \`.locus/documents\` (synced from cloud)
|
|
32183
|
+
If you need more information about the project strategies, plans, or architecture, read files in these directories.`;
|
|
32184
|
+
}
|
|
32185
|
+
getLearningsContent() {
|
|
32186
|
+
const learningsPath = getLocusPath(this.projectPath, "learningsFile");
|
|
32187
|
+
if (!existsSync3(learningsPath)) {
|
|
32188
|
+
return null;
|
|
32189
|
+
}
|
|
32351
32190
|
try {
|
|
32352
|
-
const
|
|
32353
|
-
const
|
|
32354
|
-
|
|
32355
|
-
|
|
32356
|
-
|
|
32357
|
-
return statSync(join4(this.projectPath, e)).isDirectory();
|
|
32358
|
-
} catch {
|
|
32359
|
-
return false;
|
|
32360
|
-
}
|
|
32361
|
-
});
|
|
32362
|
-
if (folders.length === 0)
|
|
32363
|
-
return "";
|
|
32364
|
-
let structure = `## Project Structure
|
|
32365
|
-
`;
|
|
32366
|
-
structure += `Key directories in this project:
|
|
32367
|
-
`;
|
|
32368
|
-
for (const folder of folders) {
|
|
32369
|
-
structure += `- \`${folder}/\`
|
|
32370
|
-
`;
|
|
32191
|
+
const content = readFileSync3(learningsPath, "utf-8");
|
|
32192
|
+
const lines = content.split(`
|
|
32193
|
+
`).filter((l) => l.startsWith("- "));
|
|
32194
|
+
if (lines.length === 0) {
|
|
32195
|
+
return null;
|
|
32371
32196
|
}
|
|
32372
|
-
return
|
|
32373
|
-
|
|
32197
|
+
return lines.join(`
|
|
32198
|
+
`);
|
|
32374
32199
|
} catch {
|
|
32375
|
-
return
|
|
32200
|
+
return null;
|
|
32376
32201
|
}
|
|
32377
32202
|
}
|
|
32378
32203
|
roleToText(role) {
|
|
@@ -32508,7 +32333,6 @@ class AgentWorker {
|
|
|
32508
32333
|
client;
|
|
32509
32334
|
aiRunner;
|
|
32510
32335
|
taskExecutor;
|
|
32511
|
-
knowledgeBase;
|
|
32512
32336
|
gitWorkflow;
|
|
32513
32337
|
maxTasks = 50;
|
|
32514
32338
|
tasksCompleted = 0;
|
|
@@ -32548,7 +32372,6 @@ class AgentWorker {
|
|
|
32548
32372
|
projectPath,
|
|
32549
32373
|
log
|
|
32550
32374
|
});
|
|
32551
|
-
this.knowledgeBase = new KnowledgeBase(projectPath);
|
|
32552
32375
|
this.gitWorkflow = new GitWorkflow(config2, log);
|
|
32553
32376
|
const providerLabel = provider === "codex" ? "Codex" : "Claude";
|
|
32554
32377
|
this.log(`Using ${providerLabel} CLI for all phases`, "info");
|
|
@@ -32622,20 +32445,6 @@ class AgentWorker {
|
|
|
32622
32445
|
};
|
|
32623
32446
|
}
|
|
32624
32447
|
}
|
|
32625
|
-
updateProgress(task2, summary) {
|
|
32626
|
-
try {
|
|
32627
|
-
this.knowledgeBase.updateProgress({
|
|
32628
|
-
role: "user",
|
|
32629
|
-
content: task2.title
|
|
32630
|
-
});
|
|
32631
|
-
this.knowledgeBase.updateProgress({
|
|
32632
|
-
role: "assistant",
|
|
32633
|
-
content: summary
|
|
32634
|
-
});
|
|
32635
|
-
} catch (err) {
|
|
32636
|
-
this.log(`Failed to update progress: ${err instanceof Error ? err.message : String(err)}`, "warn");
|
|
32637
|
-
}
|
|
32638
|
-
}
|
|
32639
32448
|
startHeartbeat() {
|
|
32640
32449
|
this.sendHeartbeat();
|
|
32641
32450
|
this.heartbeatInterval = setInterval(() => this.sendHeartbeat(), 60000);
|
|
@@ -32710,7 +32519,6 @@ Branch: \`${result.branch}\`` : "";
|
|
|
32710
32519
|
this.tasksCompleted++;
|
|
32711
32520
|
this.completedTaskList.push({ title: task2.title, id: task2.id });
|
|
32712
32521
|
this.taskSummaries.push(result.summary);
|
|
32713
|
-
this.updateProgress(task2, result.summary);
|
|
32714
32522
|
}
|
|
32715
32523
|
} else {
|
|
32716
32524
|
this.log(`Failed: ${task2.title} - ${result.summary}`, "error");
|
|
@@ -32756,7 +32564,6 @@ var init_worker = __esm(() => {
|
|
|
32756
32564
|
init_config();
|
|
32757
32565
|
init_git_utils();
|
|
32758
32566
|
init_src2();
|
|
32759
|
-
init_knowledge_base();
|
|
32760
32567
|
init_colors();
|
|
32761
32568
|
init_git_workflow();
|
|
32762
32569
|
init_task_executor();
|