@menteeai/menteeswe 0.1.14 → 0.1.16

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.
Files changed (2) hide show
  1. package/dist/cli.js +53 -38
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -404,6 +404,13 @@ function formatEvent(event) {
404
404
  return "\n" + chalk.bold.magenta(`\u25B8 Task: ${event.message ?? ""}`);
405
405
  case "model_request":
406
406
  return chalk.gray("\u25CF thinking...");
407
+ case "tokens": {
408
+ const req = typeof event.data?.request === "number" ? event.data.request : 0;
409
+ const inTok = typeof event.data?.inputTokens === "number" ? event.data.inputTokens : 0;
410
+ const outTok = typeof event.data?.outputTokens === "number" ? event.data.outputTokens : 0;
411
+ const fmtK = (n) => n >= 1e3 ? `${(n / 1e3).toFixed(1)}k` : String(n);
412
+ return chalk.dim(` \u21C5 req #${req} \xB7 ctx ${fmtK(inTok)} tok \xB7 out ${fmtK(outTok)} tok`);
413
+ }
407
414
  case "info":
408
415
  return chalk.cyan.bold(`\u{1F4AD} ${event.message ?? ""}`);
409
416
  case "tool_started": {
@@ -483,8 +490,8 @@ var init_render = __esm({
483
490
  "use strict";
484
491
  TOOL_CATEGORY = {
485
492
  read_file: "filesystem",
486
- write_file: "filesystem",
487
- apply_patch: "filesystem",
493
+ write_file: "exec",
494
+ apply_patch: "testing",
488
495
  delete_file: "filesystem",
489
496
  move_path: "filesystem",
490
497
  search_code: "search",
@@ -646,7 +653,7 @@ ${branch ? `- Git branch: ${branch}` : "- Not a git repository"}
646
653
  ${tree}
647
654
 
648
655
  # How to work
649
- 1. UNDERSTAND before acting: list files, search code, and read the relevant files (with line ranges for large files) before proposing changes. Never modify a file you have not read.
656
+ 1. UNDERSTAND before acting: use search_code to locate the relevant files and symbols, then read only the 5-6 most important files as reference (with line ranges for large files) before proposing changes. Never modify a file you have not read.
650
657
  2. MINIMAL CHANGES: make the smallest change that correctly fulfils the task. Never refactor unrelated code, never reformat, never rename things that were not asked about.
651
658
  3. REALITY CHECK: do not invent APIs, packages, or file paths. If you are unsure a dependency or module exists, verify with search or by reading package.json / requirements files.
652
659
  4. VERIFY: after modifying code, run the project's own tests, build, or typecheck commands to prove the change works. If no obvious test command exists, at minimum execute the modified code or a syntax check.
@@ -662,8 +669,7 @@ ${tree}
662
669
 
663
670
  # Research strategy (IMPORTANT \u2014 HARD RULE)
664
671
  - The file tree above already shows the whole structure. Do NOT read files just to "see what's there".
665
- - When asked to "understand", "study", or "explore", read at most 5 files: typically README, package.json / pyproject, and 1-3 source files directly relevant to the question. Use search_code to locate symbols instead of opening files blindly.
666
- - The harness enforces a read budget. Once it warns you, STOP reading and answer or act.
672
+ - Before reading anything, use search_code to locate the symbols and files that matter. Then read ONLY the 5-6 most important files as reference (README, package.json / pyproject, and the few source files directly relevant to the task). Do not open many files \u2014 search first, read selectively.
667
673
  - For debugging or feature tasks, read only the files directly involved, then verify with tests. Never read the entire codebase.
668
674
 
669
675
  # Editing notes
@@ -998,6 +1004,13 @@ ${systemExtra}` : "");
998
1004
  if (response.usage) {
999
1005
  state.usage.inputTokens += response.usage.inputTokens;
1000
1006
  state.usage.outputTokens += response.usage.outputTokens;
1007
+ bus.emit("tokens", void 0, {
1008
+ request: state.usage.modelRequests,
1009
+ inputTokens: response.usage.inputTokens,
1010
+ outputTokens: response.usage.outputTokens,
1011
+ totalIn: state.usage.inputTokens,
1012
+ totalOut: state.usage.outputTokens
1013
+ });
1001
1014
  }
1002
1015
  if (response.finishReason === "length") {
1003
1016
  bus.emit("warning", "Model hit its output length limit.");
@@ -1085,19 +1098,6 @@ Investigate the root cause, fix it, then finish with a final answer.`
1085
1098
  }
1086
1099
  }
1087
1100
  state.totalToolCalls += 1;
1088
- if (tool.name === "read_file" && result.success) {
1089
- state.readCount += 1;
1090
- if (state.readCount === READ_BUDGET || state.readCount === READ_BUDGET * 2) {
1091
- bus.emit(
1092
- "warning",
1093
- `Read budget reached (${state.readCount} files). Stop exploring \u2014 either answer now or start acting on what you have.`
1094
- );
1095
- messages.push({
1096
- role: "user",
1097
- content: "SYSTEM NOTE: You have read " + state.readCount + " files. That is more than enough exploration. Do NOT call read_file again unless a later step absolutely requires it. Either answer the question now or begin making changes."
1098
- });
1099
- }
1100
- }
1101
1101
  if (tool.name === "apply_patch" || tool.name === "write_file") {
1102
1102
  const pathArg = firstString(args, "path");
1103
1103
  if (pathArg && result.success && !state.modifiedFiles.includes(pathArg)) {
@@ -1170,7 +1170,7 @@ Investigate the root cause, fix it, then finish with a final answer.`
1170
1170
  });
1171
1171
  return { success, finalText, state };
1172
1172
  }
1173
- var MAX_CONTEXT_CHARS, READ_BUDGET, RATE_LIMIT_MAX_ATTEMPTS, MAX_VERIFY, EDIT_TOOLS, KEEP_RECENT_TOOL;
1173
+ var MAX_CONTEXT_CHARS, RATE_LIMIT_MAX_ATTEMPTS, MAX_VERIFY, EDIT_TOOLS, KEEP_RECENT_TOOL;
1174
1174
  var init_loop = __esm({
1175
1175
  "src/agent/loop.ts"() {
1176
1176
  "use strict";
@@ -1180,7 +1180,6 @@ var init_loop = __esm({
1180
1180
  init_base();
1181
1181
  init_testing();
1182
1182
  MAX_CONTEXT_CHARS = 7e4;
1183
- READ_BUDGET = 6;
1184
1183
  RATE_LIMIT_MAX_ATTEMPTS = 8;
1185
1184
  MAX_VERIFY = 3;
1186
1185
  EDIT_TOOLS = /* @__PURE__ */ new Set(["apply_patch", "write_file", "move_path"]);
@@ -1192,7 +1191,7 @@ var init_loop = __esm({
1192
1191
  var version;
1193
1192
  var init_package = __esm({
1194
1193
  "package.json"() {
1195
- version = "0.1.14";
1194
+ version = "0.1.16";
1196
1195
  }
1197
1196
  });
1198
1197
 
@@ -1557,9 +1556,10 @@ function App(props) {
1557
1556
  const [detailsOpen, setDetailsOpen] = useState3(false);
1558
1557
  const [showDetails, setShowDetails] = useState3(false);
1559
1558
  const [thinkingText, setThinkingText] = useState3("");
1560
- const [currentEdit, setCurrentEdit] = useState3(null);
1561
1559
  const [phase, setPhase] = useState3("");
1562
1560
  const [showEdits, setShowEdits] = useState3(true);
1561
+ const [taskSummary, setTaskSummary] = useState3(null);
1562
+ const [tokenTotals, setTokenTotals] = useState3({ totalIn: 0, totalOut: 0 });
1563
1563
  const finalTextRef = useRef(null);
1564
1564
  const pendingTool = useRef(null);
1565
1565
  const counter = useRef(0);
@@ -1572,6 +1572,10 @@ function App(props) {
1572
1572
  const line = { id: counter.current, text, noise, kind };
1573
1573
  setLog((prev) => [...prev, line]);
1574
1574
  };
1575
+ const appendPatchEdit = (edit) => {
1576
+ counter.current += 1;
1577
+ setLog((prev) => [...prev, { id: counter.current, text: "", noise: false, kind: "patch", edit }]);
1578
+ };
1575
1579
  useEffect2(() => {
1576
1580
  const TOOL_NOISE = /* @__PURE__ */ new Set(["tool_started", "tool_completed", "model_request"]);
1577
1581
  const unsubscribeLog = bus.subscribe((event) => {
@@ -1591,7 +1595,25 @@ function App(props) {
1591
1595
  const filePath = typeof event.data?.path === "string" ? event.data.path : "file";
1592
1596
  const oldStr = typeof event.data?.old_string === "string" ? event.data.old_string : "";
1593
1597
  const newStr = typeof event.data?.new_string === "string" ? event.data.new_string : "";
1594
- setCurrentEdit({ path: filePath, old: oldStr, new: newStr });
1598
+ appendPatchEdit({ path: filePath, old: oldStr, new: newStr });
1599
+ return;
1600
+ }
1601
+ if (event.type === "tokens") {
1602
+ const totalIn = typeof event.data?.totalIn === "number" ? event.data.totalIn : 0;
1603
+ const totalOut = typeof event.data?.totalOut === "number" ? event.data.totalOut : 0;
1604
+ setTokenTotals({ totalIn, totalOut });
1605
+ }
1606
+ if (event.type === "task_completed") {
1607
+ setTaskSummary(formatEvent(event));
1608
+ const text = typeof event.data?.finalText === "string" ? event.data.finalText.trim() : "";
1609
+ if (text) {
1610
+ finalTextRef.current = text;
1611
+ setFinalPending(text);
1612
+ setTypedText("");
1613
+ setTyping(true);
1614
+ } else {
1615
+ finalTextRef.current = null;
1616
+ }
1595
1617
  return;
1596
1618
  }
1597
1619
  appendLog(formatEvent(event), TOOL_NOISE.has(event.type));
@@ -1608,16 +1630,6 @@ function App(props) {
1608
1630
  (prev) => [...prev, { name, target: rec?.target ?? "", args: rec?.args ?? "", output: output.slice(0, 4e3) }].slice(-40)
1609
1631
  );
1610
1632
  pendingTool.current = null;
1611
- } else if (event.type === "task_completed") {
1612
- const text = typeof event.data?.finalText === "string" ? event.data.finalText.trim() : "";
1613
- if (text) {
1614
- finalTextRef.current = text;
1615
- setFinalPending(text);
1616
- setTypedText("");
1617
- setTyping(true);
1618
- } else {
1619
- finalTextRef.current = null;
1620
- }
1621
1633
  }
1622
1634
  });
1623
1635
  const unsubscribeLog2 = bus.subscribe(createSessionLogger());
@@ -1802,7 +1814,8 @@ function App(props) {
1802
1814
  setInspectorIndex(null);
1803
1815
  setDetailsOpen(false);
1804
1816
  setRunning(true);
1805
- setCurrentEdit(null);
1817
+ setTaskSummary(null);
1818
+ setTokenTotals({ totalIn: 0, totalOut: 0 });
1806
1819
  const ac = new AbortController();
1807
1820
  abortRef.current = ac;
1808
1821
  try {
@@ -1900,14 +1913,14 @@ function App(props) {
1900
1913
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1901
1914
  /* @__PURE__ */ jsx6(Static, { items: [{ key: "header", text: header }], children: (item) => /* @__PURE__ */ jsx6(Box6, { children: item.text }, item.key) }),
1902
1915
  /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1903
- log.filter((l) => showDetails || !l.noise).map(
1904
- (line) => line.kind === "answer" ? /* @__PURE__ */ jsx6(AnswerBlock, { text: line.text }, line.id) : /* @__PURE__ */ jsx6(Text6, { children: line.text }, line.id)
1916
+ log.filter((l) => (showDetails || !l.noise) && (l.kind !== "patch" || showEdits)).map(
1917
+ (line) => line.kind === "answer" ? /* @__PURE__ */ jsx6(AnswerBlock, { text: line.text }, line.id) : line.kind === "patch" && line.edit ? /* @__PURE__ */ jsx6(CurrentEditBox, { edit: line.edit }, line.id) : /* @__PURE__ */ jsx6(Text6, { children: line.text }, line.id)
1905
1918
  ),
1906
1919
  finalPending !== null ? /* @__PURE__ */ jsx6(Box6, { marginTop: 1, flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, children: /* @__PURE__ */ jsxs6(Text6, { color: "green", children: [
1907
1920
  typedText,
1908
1921
  typing ? "\u258C" : ""
1909
1922
  ] }) }) : null,
1910
- showEdits && /* @__PURE__ */ jsx6(CurrentEditBox, { edit: currentEdit }),
1923
+ taskSummary ? /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { children: taskSummary }) }) : null,
1911
1924
  detailsOpen && inspectorIndex !== null && toolHistory[inspectorIndex] ? (() => {
1912
1925
  const rec = toolHistory[inspectorIndex];
1913
1926
  const outLines = rec.output.split("\n").slice(0, 24).join("\n");
@@ -1986,7 +1999,9 @@ function App(props) {
1986
1999
  /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1987
2000
  "agent ",
1988
2001
  PHASE_LABEL[phase] ?? "working",
1989
- "\u2026 (Ctrl+C to exit)"
2002
+ "\u2026",
2003
+ tokenTotals.totalIn + tokenTotals.totalOut > 0 ? ` \xB7 ${((tokenTotals.totalIn + tokenTotals.totalOut) / 1e3).toFixed(1)}k tok` : "",
2004
+ " (Ctrl+C to exit)"
1990
2005
  ] })
1991
2006
  ] }),
1992
2007
  thinkingText ? /* @__PURE__ */ jsxs6(Box6, { children: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@menteeai/menteeswe",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
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",