@menteeai/menteeswe 0.1.18 → 0.1.19
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/cli.js +85 -13
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -694,7 +694,7 @@ var init_prompts = __esm({
|
|
|
694
694
|
// src/agent/conversation.ts
|
|
695
695
|
import fs9 from "fs";
|
|
696
696
|
import path8 from "path";
|
|
697
|
-
import
|
|
697
|
+
import crypto3 from "crypto";
|
|
698
698
|
import os3 from "os";
|
|
699
699
|
function sessionsDir() {
|
|
700
700
|
const dir = path8.join(os3.homedir(), ".mentee", "sessions");
|
|
@@ -702,7 +702,7 @@ function sessionsDir() {
|
|
|
702
702
|
return dir;
|
|
703
703
|
}
|
|
704
704
|
function sessionFile(cwd) {
|
|
705
|
-
const hash =
|
|
705
|
+
const hash = crypto3.createHash("sha1").update(cwd).digest("hex").slice(0, 16);
|
|
706
706
|
return path8.join(sessionsDir(), `${hash}.json`);
|
|
707
707
|
}
|
|
708
708
|
function loadConversation(cwd, limit = 12) {
|
|
@@ -747,6 +747,43 @@ Assistant: ${t.response.trim()}
|
|
|
747
747
|
}
|
|
748
748
|
return [header, ...blocks, ""].join("\n");
|
|
749
749
|
}
|
|
750
|
+
function recentFile(cwd) {
|
|
751
|
+
const hash = crypto3.createHash("sha1").update(cwd).digest("hex").slice(0, 16);
|
|
752
|
+
return path8.join(sessionsDir(), `${hash}.files.json`);
|
|
753
|
+
}
|
|
754
|
+
function saveRecentFiles(cwd, reads, writes) {
|
|
755
|
+
try {
|
|
756
|
+
let prev = { reads: [], writes: [] };
|
|
757
|
+
try {
|
|
758
|
+
const parsed = JSON.parse(fs9.readFileSync(recentFile(cwd), "utf8"));
|
|
759
|
+
if (parsed && Array.isArray(parsed.reads) && Array.isArray(parsed.writes)) prev = parsed;
|
|
760
|
+
} catch {
|
|
761
|
+
}
|
|
762
|
+
const merge = (known, fresh) => [.../* @__PURE__ */ new Set([...fresh, ...known])].slice(0, 15);
|
|
763
|
+
fs9.writeFileSync(
|
|
764
|
+
recentFile(cwd),
|
|
765
|
+
JSON.stringify({ reads: merge(prev.reads, reads), writes: merge(prev.writes, writes) }, null, 2)
|
|
766
|
+
);
|
|
767
|
+
} catch {
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
function formatRecentFiles(cwd) {
|
|
771
|
+
try {
|
|
772
|
+
const parsed = JSON.parse(fs9.readFileSync(recentFile(cwd), "utf8"));
|
|
773
|
+
const writes = (parsed.writes ?? []).slice(0, 10);
|
|
774
|
+
const reads = (parsed.reads ?? []).filter((f) => !writes.includes(f)).slice(0, 10);
|
|
775
|
+
if (reads.length === 0 && writes.length === 0) return "";
|
|
776
|
+
const lines = ["# Known files from earlier tasks in this project"];
|
|
777
|
+
if (writes.length > 0) lines.push(`Modified recently: ${writes.join(", ")}`);
|
|
778
|
+
if (reads.length > 0) lines.push(`Read recently: ${reads.join(", ")}`);
|
|
779
|
+
lines.push(
|
|
780
|
+
"Reuse this knowledge \u2014 do not re-search or re-read these files unless you suspect they changed. If you read a file earlier and it is unchanged, you may apply_patch directly."
|
|
781
|
+
);
|
|
782
|
+
return lines.join("\n");
|
|
783
|
+
} catch {
|
|
784
|
+
return "";
|
|
785
|
+
}
|
|
786
|
+
}
|
|
750
787
|
var init_conversation = __esm({
|
|
751
788
|
"src/agent/conversation.ts"() {
|
|
752
789
|
"use strict";
|
|
@@ -761,6 +798,7 @@ function createAgentState(task, maxIterations) {
|
|
|
761
798
|
iteration: 0,
|
|
762
799
|
maxIterations,
|
|
763
800
|
modifiedFiles: [],
|
|
801
|
+
readFiles: [],
|
|
764
802
|
commandsRun: [],
|
|
765
803
|
errors: [],
|
|
766
804
|
lastErrorSignature: null,
|
|
@@ -898,7 +936,10 @@ async function runAgent(options) {
|
|
|
898
936
|
} = options;
|
|
899
937
|
const state = createAgentState(task, maxIterations);
|
|
900
938
|
const prior = formatConversationContext(cwd);
|
|
901
|
-
const
|
|
939
|
+
const knownFiles = formatRecentFiles(cwd);
|
|
940
|
+
const system = buildSystemPrompt(cwd) + (knownFiles ? `
|
|
941
|
+
|
|
942
|
+
${knownFiles}` : "") + (prior ? `
|
|
902
943
|
|
|
903
944
|
${prior}
|
|
904
945
|
|
|
@@ -910,6 +951,7 @@ ${systemExtra}` : "");
|
|
|
910
951
|
const toolCtx = {
|
|
911
952
|
cwd,
|
|
912
953
|
approval,
|
|
954
|
+
fileState: /* @__PURE__ */ new Map(),
|
|
913
955
|
emit: (type, message, data) => {
|
|
914
956
|
bus.emit(type, message, data);
|
|
915
957
|
}
|
|
@@ -961,6 +1003,7 @@ ${systemExtra}` : "");
|
|
|
961
1003
|
bus.emit("error", message + hint);
|
|
962
1004
|
finalText = `Model request failed: ${message}`;
|
|
963
1005
|
appendTurn(cwd, task, finalText);
|
|
1006
|
+
saveRecentFiles(cwd, state.readFiles, state.modifiedFiles);
|
|
964
1007
|
bus.emit("task_completed", finalText.slice(0, 400), {
|
|
965
1008
|
success: false,
|
|
966
1009
|
finalText,
|
|
@@ -1121,7 +1164,10 @@ Investigate the root cause, fix it, then finish with a final answer.`
|
|
|
1121
1164
|
}
|
|
1122
1165
|
const readHeader = result.success && tool.name === "read_file" ? result.output.split("\n")[0] ?? "" : "";
|
|
1123
1166
|
const readRel = readHeader ? normalizeRel(readHeader.replace(/\s+\(\d+ lines\)\s*$/, "").trim()) : "";
|
|
1124
|
-
if (readRel)
|
|
1167
|
+
if (readRel) {
|
|
1168
|
+
readMsgIndex.set(readRel, messages.length);
|
|
1169
|
+
if (!state.readFiles.includes(readRel) && state.readFiles.length < 20) state.readFiles.push(readRel);
|
|
1170
|
+
}
|
|
1125
1171
|
if ((tool.name === "apply_patch" || tool.name === "write_file") && result.success) {
|
|
1126
1172
|
const patchedRel = normalizeRel(
|
|
1127
1173
|
typeof result.data?.path === "string" && result.data.path ? result.data.path : typeof args.path === "string" ? args.path : ""
|
|
@@ -1160,7 +1206,10 @@ Investigate the root cause, fix it, then finish with a final answer.`
|
|
|
1160
1206
|
bus.emit("warning", finalText);
|
|
1161
1207
|
}
|
|
1162
1208
|
const success = sawFinish && state.errors.length === 0;
|
|
1163
|
-
if (finalText && !signal?.aborted)
|
|
1209
|
+
if (finalText && !signal?.aborted) {
|
|
1210
|
+
appendTurn(cwd, task, finalText);
|
|
1211
|
+
saveRecentFiles(cwd, state.readFiles, state.modifiedFiles);
|
|
1212
|
+
}
|
|
1164
1213
|
bus.emit("task_completed", finalText.slice(0, 400), {
|
|
1165
1214
|
success,
|
|
1166
1215
|
finalText,
|
|
@@ -1195,7 +1244,7 @@ var init_loop = __esm({
|
|
|
1195
1244
|
var version;
|
|
1196
1245
|
var init_package = __esm({
|
|
1197
1246
|
"package.json"() {
|
|
1198
|
-
version = "0.1.
|
|
1247
|
+
version = "0.1.19";
|
|
1199
1248
|
}
|
|
1200
1249
|
});
|
|
1201
1250
|
|
|
@@ -1558,7 +1607,7 @@ function App(props) {
|
|
|
1558
1607
|
const [toolHistory, setToolHistory] = useState3([]);
|
|
1559
1608
|
const [inspectorIndex, setInspectorIndex] = useState3(null);
|
|
1560
1609
|
const [detailsOpen, setDetailsOpen] = useState3(false);
|
|
1561
|
-
const [showDetails, setShowDetails] = useState3(
|
|
1610
|
+
const [showDetails, setShowDetails] = useState3(true);
|
|
1562
1611
|
const [thinkingText, setThinkingText] = useState3("");
|
|
1563
1612
|
const [phase, setPhase] = useState3("");
|
|
1564
1613
|
const [showEdits, setShowEdits] = useState3(true);
|
|
@@ -2369,6 +2418,10 @@ function createProvider(provider, config, modelOverride) {
|
|
|
2369
2418
|
init_base();
|
|
2370
2419
|
import fs2 from "fs";
|
|
2371
2420
|
import path2 from "path";
|
|
2421
|
+
import crypto from "crypto";
|
|
2422
|
+
function contentHash(content) {
|
|
2423
|
+
return crypto.createHash("sha1").update(content).digest("hex").slice(0, 12);
|
|
2424
|
+
}
|
|
2372
2425
|
function resolveWithinWorkspace(cwd, target) {
|
|
2373
2426
|
const resolved = path2.resolve(cwd, target);
|
|
2374
2427
|
const normalizedCwd = path2.resolve(cwd);
|
|
@@ -2503,9 +2556,16 @@ var readFile = {
|
|
|
2503
2556
|
if (start > lines.length) {
|
|
2504
2557
|
return {
|
|
2505
2558
|
success: false,
|
|
2506
|
-
output: `start_line ${start} is beyond end of file (${lines.length} lines)
|
|
2559
|
+
output: `READ_RANGE_INVALID: start_line ${start} is beyond end of file (total_lines ${lines.length}). Valid range: 1-${lines.length}. Recovery: retry read_file with start_line <= ${Math.max(1, lines.length)} or omit the range.`
|
|
2560
|
+
};
|
|
2561
|
+
}
|
|
2562
|
+
if (Number.isNaN(end) || end < start) {
|
|
2563
|
+
return {
|
|
2564
|
+
success: false,
|
|
2565
|
+
output: `READ_RANGE_INVALID: end_line (${args.end_line}) is before start_line (${start}). Valid range: 1-${lines.length}. Recovery: retry with end_line >= start_line.`
|
|
2507
2566
|
};
|
|
2508
2567
|
}
|
|
2568
|
+
ctx.fileState?.set(filePath, contentHash(content));
|
|
2509
2569
|
const slice = lines.slice(start - 1, end).map((line, i) => `${start + i}: ${line}`);
|
|
2510
2570
|
const { text, truncated } = truncateOutput(slice.join("\n"), 12e3);
|
|
2511
2571
|
const note = end < lines.length ? `
|
|
@@ -2535,6 +2595,7 @@ var writeFile = {
|
|
|
2535
2595
|
const content = requireString(args, "content");
|
|
2536
2596
|
fs2.mkdirSync(path2.dirname(filePath), { recursive: true });
|
|
2537
2597
|
fs2.writeFileSync(filePath, content, "utf8");
|
|
2598
|
+
ctx.fileState?.set(filePath, contentHash(content));
|
|
2538
2599
|
return {
|
|
2539
2600
|
success: true,
|
|
2540
2601
|
output: `Wrote ${Buffer.byteLength(content, "utf8")} bytes to ${relativeToWorkspace(ctx.cwd, filePath)}`
|
|
@@ -2567,6 +2628,16 @@ var applyPatch = {
|
|
|
2567
2628
|
if (oldString === newString) {
|
|
2568
2629
|
return { success: false, output: "old_string and new_string are identical; nothing to change." };
|
|
2569
2630
|
}
|
|
2631
|
+
const relPath = relativeToWorkspace(ctx.cwd, filePath);
|
|
2632
|
+
const totalLines = content.split(/\r?\n/).length;
|
|
2633
|
+
const currentHash = contentHash(content);
|
|
2634
|
+
const knownHash = ctx.fileState?.get(filePath);
|
|
2635
|
+
if (knownHash && knownHash !== currentHash) {
|
|
2636
|
+
return {
|
|
2637
|
+
success: false,
|
|
2638
|
+
output: `FILE_CHANGED: ${relPath} changed since it was last read (expected hash ${knownHash}, current ${currentHash}, total_lines ${totalLines}). Recovery: read_file ${relPath} again, then retry apply_patch against the current text.`
|
|
2639
|
+
};
|
|
2640
|
+
}
|
|
2570
2641
|
const tryMatch = (c, o, n) => {
|
|
2571
2642
|
const occ = c.split(o).length - 1;
|
|
2572
2643
|
return occ === 1 ? c.replace(o, n) : null;
|
|
@@ -2596,15 +2667,16 @@ var applyPatch = {
|
|
|
2596
2667
|
if (occ === 0) {
|
|
2597
2668
|
return {
|
|
2598
2669
|
success: false,
|
|
2599
|
-
output:
|
|
2670
|
+
output: `PATCH_FAILED: old_string not found in ${relPath} (total_lines ${totalLines}, hash ${currentHash}). Recovery: read_file ${relPath} (or the relevant line range) and copy the exact text including whitespace, then retry. Do not guess.`
|
|
2600
2671
|
};
|
|
2601
2672
|
}
|
|
2602
2673
|
return {
|
|
2603
2674
|
success: false,
|
|
2604
|
-
output: `old_string occurs ${occ} times.
|
|
2675
|
+
output: `PATCH_FAILED: old_string occurs ${occ} times in ${relPath}. Recovery: include more surrounding lines to make it unique, then retry.`
|
|
2605
2676
|
};
|
|
2606
2677
|
}
|
|
2607
2678
|
fs2.writeFileSync(filePath, updated, "utf8");
|
|
2679
|
+
ctx.fileState?.set(filePath, contentHash(updated));
|
|
2608
2680
|
const removed = oldString.split(/\r?\n/).length;
|
|
2609
2681
|
const added = newString.split(/\r?\n/).length;
|
|
2610
2682
|
return {
|
|
@@ -3175,12 +3247,12 @@ init_config();
|
|
|
3175
3247
|
init_base();
|
|
3176
3248
|
import fs5 from "fs";
|
|
3177
3249
|
import path5 from "path";
|
|
3178
|
-
import
|
|
3250
|
+
import crypto2 from "crypto";
|
|
3179
3251
|
function memoryDir() {
|
|
3180
3252
|
return path5.join(configDir(), "memory");
|
|
3181
3253
|
}
|
|
3182
3254
|
function memoryFile(cwd) {
|
|
3183
|
-
const key =
|
|
3255
|
+
const key = crypto2.createHash("sha1").update(path5.resolve(cwd)).digest("hex").slice(0, 16);
|
|
3184
3256
|
return path5.join(memoryDir(), `${key}.json`);
|
|
3185
3257
|
}
|
|
3186
3258
|
function load(cwd) {
|
|
@@ -3222,7 +3294,7 @@ var memoryTool = {
|
|
|
3222
3294
|
}
|
|
3223
3295
|
const topic = firstString(args, "topic") ?? "";
|
|
3224
3296
|
const entry = {
|
|
3225
|
-
id:
|
|
3297
|
+
id: crypto2.randomBytes(4).toString("hex"),
|
|
3226
3298
|
topic,
|
|
3227
3299
|
content: content.trim(),
|
|
3228
3300
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@menteeai/menteeswe",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "MenteE SWE — a model-agnostic autonomous software-engineering agent CLI. Bring your own intelligence: Kimi, GLM/Z.ai, and more.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|