@menteeai/menteeswe 0.1.12 → 0.1.13

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 +261 -154
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -194,6 +194,154 @@ var init_exec = __esm({
194
194
  }
195
195
  });
196
196
 
197
+ // src/tools/testing.ts
198
+ import fs4 from "fs";
199
+ import path4 from "path";
200
+ function readPackageJson(cwd) {
201
+ try {
202
+ return JSON.parse(fs4.readFileSync(path4.join(cwd, "package.json"), "utf8"));
203
+ } catch {
204
+ return null;
205
+ }
206
+ }
207
+ function readTextIfExists(cwd, file) {
208
+ try {
209
+ return fs4.readFileSync(path4.join(cwd, file), "utf8");
210
+ } catch {
211
+ return null;
212
+ }
213
+ }
214
+ function fileExists(cwd, file) {
215
+ try {
216
+ return fs4.existsSync(path4.join(cwd, file));
217
+ } catch {
218
+ return false;
219
+ }
220
+ }
221
+ function detectTestCommand(cwd) {
222
+ const pkg = readPackageJson(cwd);
223
+ const testScript = pkg && typeof pkg.scripts?.test === "string" ? pkg.scripts.test : null;
224
+ if (testScript && !/error|no test specified/i.test(testScript)) {
225
+ return "npm test";
226
+ }
227
+ if (fileExists(cwd, "pytest.ini") || fileExists(cwd, "tests")) return "pytest -q";
228
+ const pyproject = readTextIfExists(cwd, "pyproject.toml");
229
+ if (pyproject && /\[tool\.pytest/.test(pyproject)) return "pytest -q";
230
+ if (fileExists(cwd, "go.mod")) return "go test ./...";
231
+ if (fileExists(cwd, "Cargo.toml")) return "cargo test";
232
+ return null;
233
+ }
234
+ function detectLintCommand(cwd) {
235
+ if (fileExists(cwd, "eslint.config.js") || fileExists(cwd, "eslint.config.mjs") || fileExists(cwd, ".eslintrc.json") || fileExists(cwd, ".eslintrc.js")) {
236
+ return "npx --no-install eslint .";
237
+ }
238
+ if (fileExists(cwd, "biome.json")) return "npx --no-install biome check .";
239
+ if (fileExists(cwd, ".ruff.toml") || fileExists(cwd, "ruff.toml")) return "ruff check .";
240
+ const pyproject = readTextIfExists(cwd, "pyproject.toml");
241
+ if (pyproject && /\[tool\.ruff/.test(pyproject)) return "ruff check .";
242
+ return null;
243
+ }
244
+ function detectTypecheckCommand(cwd) {
245
+ if (fileExists(cwd, "tsconfig.json")) return "npx --no-install tsc --noEmit";
246
+ if (fileExists(cwd, "mypy.ini")) return "python -m mypy .";
247
+ const pyproject = readTextIfExists(cwd, "pyproject.toml");
248
+ if (pyproject && /\[tool\.mypy/.test(pyproject)) return "python -m mypy .";
249
+ if (fileExists(cwd, "go.mod")) return "go vet ./...";
250
+ if (fileExists(cwd, "Cargo.toml")) return "cargo check";
251
+ return null;
252
+ }
253
+ function makeRunnerTool(config) {
254
+ return {
255
+ name: config.name,
256
+ description: config.description,
257
+ risk: "safe",
258
+ timeoutMs: DEFAULT_TIMEOUT_MS2,
259
+ parameters: {
260
+ type: "object",
261
+ properties: {
262
+ command: {
263
+ type: "string",
264
+ description: "Exact command to run. If omitted, the project type is auto-detected."
265
+ },
266
+ timeout_ms: { type: "number", description: `Timeout in ms. Defaults to ${DEFAULT_TIMEOUT_MS2}.` }
267
+ }
268
+ },
269
+ async execute(args, ctx) {
270
+ let command = firstString(args, "command");
271
+ if (!command) {
272
+ command = config.detect(ctx.cwd) ?? void 0;
273
+ if (!command) {
274
+ return {
275
+ success: false,
276
+ output: `Could not auto-detect a command for this project. ${config.fallbackHint} Use the command argument to run one explicitly.`
277
+ };
278
+ }
279
+ }
280
+ const timeoutMs = Math.min(6e5, firstNumber(args, "timeout_ms") ?? DEFAULT_TIMEOUT_MS2);
281
+ const outcome = await runShellCommand(command, ctx.cwd, timeoutMs);
282
+ const formatted = formatOutcome(outcome);
283
+ return { success: formatted.success, output: formatted.output, truncated: formatted.truncated };
284
+ }
285
+ };
286
+ }
287
+ var DEFAULT_TIMEOUT_MS2, runTests, runLinter, runTypecheck, inspectEnv;
288
+ var init_testing = __esm({
289
+ "src/tools/testing.ts"() {
290
+ "use strict";
291
+ init_base();
292
+ init_exec();
293
+ DEFAULT_TIMEOUT_MS2 = 18e4;
294
+ runTests = makeRunnerTool({
295
+ name: "run_tests",
296
+ description: "Run the project test suite. Auto-detects npm test / pytest / go test / cargo test from the project files, or run an exact command. Use this to verify changes.",
297
+ detect: detectTestCommand,
298
+ fallbackHint: "No test runner found (looked for package.json scripts.test, pytest, go, cargo)."
299
+ });
300
+ runLinter = makeRunnerTool({
301
+ name: "run_linter",
302
+ description: "Run the project linter (eslint / biome / ruff auto-detected).",
303
+ detect: detectLintCommand,
304
+ fallbackHint: "No linter config found (looked for eslint, biome, ruff)."
305
+ });
306
+ runTypecheck = makeRunnerTool({
307
+ name: "run_typecheck",
308
+ description: "Run static type checking (tsc --noEmit / mypy / go vet / cargo check auto-detected).",
309
+ detect: detectTypecheckCommand,
310
+ fallbackHint: "No typechecker config found (looked for tsconfig.json, mypy, go, cargo)."
311
+ });
312
+ inspectEnv = {
313
+ name: "inspect_env",
314
+ description: "Inspect the environment: OS info, and which toolchains are installed with versions (node, npm, python, pip, git). Use this to adapt commands to the machine.",
315
+ risk: "safe",
316
+ parameters: { type: "object", properties: {} },
317
+ async execute(_args, ctx) {
318
+ const lines = [
319
+ `os: ${process.platform} ${process.version} ${process.arch}`,
320
+ `workspace: ${ctx.cwd}`
321
+ ];
322
+ const probes = [
323
+ ["node", "node --version"],
324
+ ["npm", "npm --version"],
325
+ ["npx", "npx --version"],
326
+ ["python", "python --version"],
327
+ ["pip", "pip --version"],
328
+ ["git", "git --version"],
329
+ ["docker", "docker --version"]
330
+ ];
331
+ const results = await Promise.all(
332
+ probes.map(async ([label, probe]) => {
333
+ const outcome = await runShellCommand(probe, ctx.cwd, 8e3);
334
+ const version2 = `${outcome.stdout} ${outcome.stderr}`.trim().split("\n")[0] ?? "";
335
+ return `${label}: ${outcome.exitCode === 0 ? version2 || "installed (version unknown)" : "not available"}`;
336
+ })
337
+ );
338
+ lines.push(...results);
339
+ return { success: true, output: lines.join("\n") };
340
+ }
341
+ };
342
+ }
343
+ });
344
+
197
345
  // src/events.ts
198
346
  var EventBus;
199
347
  var init_events = __esm({
@@ -635,6 +783,7 @@ function createAgentState(task, maxIterations) {
635
783
  sameErrorCount: 0,
636
784
  totalToolCalls: 0,
637
785
  readCount: 0,
786
+ verifyAttempts: 0,
638
787
  usage: { inputTokens: 0, outputTokens: 0, modelRequests: 0 },
639
788
  startedAt: Date.now()
640
789
  };
@@ -724,6 +873,31 @@ function trimOldToolResults(messages) {
724
873
  message.content = `\u27E8prior tool output trimmed: ${head}\u2026 (${content.length} chars)\u27E9`;
725
874
  }
726
875
  }
876
+ async function runVerification(tools, ctx, bus, state, cwd) {
877
+ const checks = [
878
+ { tool: tools.get("run_typecheck"), detect: detectTypecheckCommand },
879
+ { tool: tools.get("run_tests"), detect: detectTestCommand }
880
+ ];
881
+ let combined = "";
882
+ for (const { tool, detect } of checks) {
883
+ if (!tool) continue;
884
+ if (!detect(cwd)) continue;
885
+ bus.emit("tool_started", `verify \xB7 ${tool.name}`, { tool: tool.name });
886
+ const res = await tool.execute({}, ctx);
887
+ bus.emit("tool_completed", `verify \xB7 ${tool.name}`, {
888
+ tool: tool.name,
889
+ success: res.success,
890
+ output: res.output.slice(0, 2e3)
891
+ });
892
+ combined += `${tool.name}: ${res.output}
893
+ `;
894
+ if (!res.success) {
895
+ state.errors.push(res.output.slice(0, 500));
896
+ return { ok: false, output: combined };
897
+ }
898
+ }
899
+ return { ok: true, output: combined };
900
+ }
727
901
  async function runAgent(options) {
728
902
  const {
729
903
  task,
@@ -756,7 +930,12 @@ ${systemExtra}` : "");
756
930
  }
757
931
  };
758
932
  const messages = [{ role: "user", content: task }];
933
+ const setPhase = (p) => {
934
+ state.phase = p;
935
+ bus.emit("phase", p);
936
+ };
759
937
  bus.emit("task_started", task, { provider: provider.name, model: model ?? provider.defaultModel });
938
+ setPhase("EXPLORATION");
760
939
  let finalText = "";
761
940
  let sawFinish = false;
762
941
  while (state.iteration < maxIterations) {
@@ -828,6 +1007,27 @@ ${systemExtra}` : "");
828
1007
  if (response.toolCalls.length === 0) {
829
1008
  finalText = response.content ?? "";
830
1009
  sawFinish = true;
1010
+ if (state.modifiedFiles.length > 0 && state.verifyAttempts < MAX_VERIFY) {
1011
+ setPhase("VALIDATION");
1012
+ const verdict = await runVerification(tools, toolCtx, bus, state, cwd);
1013
+ if (!verdict.ok) {
1014
+ state.verifyAttempts += 1;
1015
+ if (state.verifyAttempts >= MAX_VERIFY) {
1016
+ bus.emit("warning", "Verification failed after multiple attempts; finishing with the issue reported.");
1017
+ break;
1018
+ }
1019
+ setPhase("DEBUGGING");
1020
+ messages.push({
1021
+ role: "user",
1022
+ content: `SYSTEM NOTE: Verification failed.
1023
+ ${verdict.output}
1024
+ Investigate the root cause, fix it, then finish with a final answer.`
1025
+ });
1026
+ sawFinish = false;
1027
+ continue;
1028
+ }
1029
+ setPhase("REVIEW");
1030
+ }
831
1031
  break;
832
1032
  }
833
1033
  messages.push({
@@ -859,6 +1059,7 @@ ${systemExtra}` : "");
859
1059
  });
860
1060
  continue;
861
1061
  }
1062
+ if (EDIT_TOOLS.has(tool.name) && state.phase === "EXPLORATION") setPhase("IMPLEMENTATION");
862
1063
  bus.emit("tool_started", toolCallPreview(call), { tool: tool.name, args });
863
1064
  const risk = tool.dynamicRisk ? tool.dynamicRisk(args) : tool.risk;
864
1065
  let approved = true;
@@ -969,7 +1170,7 @@ ${systemExtra}` : "");
969
1170
  });
970
1171
  return { success, finalText, state };
971
1172
  }
972
- var MAX_CONTEXT_CHARS, READ_BUDGET, RATE_LIMIT_MAX_ATTEMPTS, KEEP_RECENT_TOOL;
1173
+ var MAX_CONTEXT_CHARS, READ_BUDGET, RATE_LIMIT_MAX_ATTEMPTS, MAX_VERIFY, EDIT_TOOLS, KEEP_RECENT_TOOL;
973
1174
  var init_loop = __esm({
974
1175
  "src/agent/loop.ts"() {
975
1176
  "use strict";
@@ -977,9 +1178,12 @@ var init_loop = __esm({
977
1178
  init_conversation();
978
1179
  init_state();
979
1180
  init_base();
1181
+ init_testing();
980
1182
  MAX_CONTEXT_CHARS = 7e4;
981
1183
  READ_BUDGET = 6;
982
1184
  RATE_LIMIT_MAX_ATTEMPTS = 8;
1185
+ MAX_VERIFY = 3;
1186
+ EDIT_TOOLS = /* @__PURE__ */ new Set(["apply_patch", "write_file", "move_path"]);
983
1187
  KEEP_RECENT_TOOL = 4;
984
1188
  }
985
1189
  });
@@ -988,7 +1192,7 @@ var init_loop = __esm({
988
1192
  var version;
989
1193
  var init_package = __esm({
990
1194
  "package.json"() {
991
- version = "0.1.12";
1195
+ version = "0.1.13";
992
1196
  }
993
1197
  });
994
1198
 
@@ -1354,6 +1558,7 @@ function App(props) {
1354
1558
  const [showDetails, setShowDetails] = useState3(false);
1355
1559
  const [thinkingText, setThinkingText] = useState3("");
1356
1560
  const [currentEdit, setCurrentEdit] = useState3(null);
1561
+ const [phase, setPhase] = useState3("");
1357
1562
  const finalTextRef = useRef(null);
1358
1563
  const pendingTool = useRef(null);
1359
1564
  const counter = useRef(0);
@@ -1374,6 +1579,10 @@ function App(props) {
1374
1579
  if (delta) setThinkingText((prev) => (prev + delta).slice(-4e3));
1375
1580
  return;
1376
1581
  }
1582
+ if (event.type === "phase") {
1583
+ setPhase(event.message ?? "");
1584
+ return;
1585
+ }
1377
1586
  if (event.type === "model_request" || event.type === "task_completed") {
1378
1587
  setThinkingText("");
1379
1588
  }
@@ -1767,7 +1976,11 @@ function App(props) {
1767
1976
  SPINNER_FRAMES[frame],
1768
1977
  " "
1769
1978
  ] }),
1770
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "agent working... (Ctrl+C to exit)" })
1979
+ /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1980
+ "agent ",
1981
+ PHASE_LABEL[phase] ?? "working",
1982
+ "\u2026 (Ctrl+C to exit)"
1983
+ ] })
1771
1984
  ] }),
1772
1985
  thinkingText ? /* @__PURE__ */ jsxs6(Box6, { children: [
1773
1986
  /* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "\u{1F4AD} " }),
@@ -1789,7 +2002,7 @@ function App(props) {
1789
2002
  ] })
1790
2003
  ] });
1791
2004
  }
1792
- var SPINNER_FRAMES, PROVIDER_NAMES, PROVIDER_DESCRIPTIONS, BANNER;
2005
+ var SPINNER_FRAMES, PHASE_LABEL, PROVIDER_NAMES, PROVIDER_DESCRIPTIONS, BANNER;
1793
2006
  var init_App = __esm({
1794
2007
  "src/tui/App.tsx"() {
1795
2008
  "use strict";
@@ -1808,6 +2021,16 @@ var init_App = __esm({
1808
2021
  init_KeyDialog();
1809
2022
  init_package();
1810
2023
  SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
2024
+ PHASE_LABEL = {
2025
+ INITIALIZATION: "starting",
2026
+ EXPLORATION: "exploring",
2027
+ PLANNING: "planning",
2028
+ IMPLEMENTATION: "implementing",
2029
+ VALIDATION: "verifying",
2030
+ DEBUGGING: "debugging",
2031
+ REVIEW: "reviewing",
2032
+ COMPLETION: "finalizing"
2033
+ };
1811
2034
  PROVIDER_NAMES = ["kimi", "glm", "zai", "zai-coding", "openrouter", "nvidia", "mock"];
1812
2035
  PROVIDER_DESCRIPTIONS = {
1813
2036
  kimi: "Moonshot \xB7 api.moonshot.ai",
@@ -2324,20 +2547,43 @@ var applyPatch = {
2324
2547
  if (oldString === newString) {
2325
2548
  return { success: false, output: "old_string and new_string are identical; nothing to change." };
2326
2549
  }
2327
- const occurrences = content.split(oldString).length - 1;
2328
- if (occurrences === 0) {
2329
- return {
2330
- success: false,
2331
- output: "old_string not found in file. Read the file again and copy the exact text, including whitespace."
2332
- };
2550
+ const tryMatch = (c, o, n) => {
2551
+ const occ = c.split(o).length - 1;
2552
+ return occ === 1 ? c.replace(o, n) : null;
2553
+ };
2554
+ let updated = tryMatch(content, oldString, newString);
2555
+ let note = "";
2556
+ if (updated === null) {
2557
+ const lfContent = content.replace(/\r\n/g, "\n");
2558
+ const lfOld = oldString.replace(/\r\n/g, "\n");
2559
+ const lfNew = newString.replace(/\r\n/g, "\n");
2560
+ const lfUpdated = tryMatch(lfContent, lfOld, lfNew);
2561
+ if (lfUpdated !== null) {
2562
+ updated = lfUpdated;
2563
+ note = " (applied after normalizing CRLF \u2192 LF line endings)";
2564
+ }
2333
2565
  }
2334
- if (occurrences > 1) {
2566
+ if (updated === null) {
2567
+ const strip = (s) => s.split("\n").map((l) => l.replace(/\s+$/, "")).join("\n");
2568
+ const sUpdated = tryMatch(strip(content), strip(oldString), strip(newString));
2569
+ if (sUpdated !== null) {
2570
+ updated = sUpdated;
2571
+ note = " (applied after trimming trailing whitespace to match)";
2572
+ }
2573
+ }
2574
+ if (updated === null) {
2575
+ const occ = content.split(oldString).length - 1;
2576
+ if (occ === 0) {
2577
+ return {
2578
+ success: false,
2579
+ output: "old_string not found in file. Read the file again and copy the exact text, including whitespace."
2580
+ };
2581
+ }
2335
2582
  return {
2336
2583
  success: false,
2337
- output: `old_string occurs ${occurrences} times. Include more surrounding lines to make it unique.`
2584
+ output: `old_string occurs ${occ} times. Include more surrounding lines to make it unique.`
2338
2585
  };
2339
2586
  }
2340
- const updated = content.replace(oldString, newString);
2341
2587
  fs2.writeFileSync(filePath, updated, "utf8");
2342
2588
  const removed = oldString.split(/\r?\n/).length;
2343
2589
  const added = newString.split(/\r?\n/).length;
@@ -2901,147 +3147,8 @@ var executeCommand = {
2901
3147
  }
2902
3148
  };
2903
3149
 
2904
- // src/tools/testing.ts
2905
- init_base();
2906
- init_exec();
2907
- import fs4 from "fs";
2908
- import path4 from "path";
2909
- var DEFAULT_TIMEOUT_MS2 = 18e4;
2910
- function readPackageJson(cwd) {
2911
- try {
2912
- return JSON.parse(fs4.readFileSync(path4.join(cwd, "package.json"), "utf8"));
2913
- } catch {
2914
- return null;
2915
- }
2916
- }
2917
- function readTextIfExists(cwd, file) {
2918
- try {
2919
- return fs4.readFileSync(path4.join(cwd, file), "utf8");
2920
- } catch {
2921
- return null;
2922
- }
2923
- }
2924
- function fileExists(cwd, file) {
2925
- try {
2926
- return fs4.existsSync(path4.join(cwd, file));
2927
- } catch {
2928
- return false;
2929
- }
2930
- }
2931
- function detectTestCommand(cwd) {
2932
- const pkg = readPackageJson(cwd);
2933
- const testScript = pkg && typeof pkg.scripts?.test === "string" ? pkg.scripts.test : null;
2934
- if (testScript && !/error|no test specified/i.test(testScript)) {
2935
- return "npm test";
2936
- }
2937
- if (fileExists(cwd, "pytest.ini") || fileExists(cwd, "tests")) return "pytest -q";
2938
- const pyproject = readTextIfExists(cwd, "pyproject.toml");
2939
- if (pyproject && /\[tool\.pytest/.test(pyproject)) return "pytest -q";
2940
- if (fileExists(cwd, "go.mod")) return "go test ./...";
2941
- if (fileExists(cwd, "Cargo.toml")) return "cargo test";
2942
- return null;
2943
- }
2944
- function detectLintCommand(cwd) {
2945
- if (fileExists(cwd, "eslint.config.js") || fileExists(cwd, "eslint.config.mjs") || fileExists(cwd, ".eslintrc.json") || fileExists(cwd, ".eslintrc.js")) {
2946
- return "npx --no-install eslint .";
2947
- }
2948
- if (fileExists(cwd, "biome.json")) return "npx --no-install biome check .";
2949
- if (fileExists(cwd, ".ruff.toml") || fileExists(cwd, "ruff.toml")) return "ruff check .";
2950
- const pyproject = readTextIfExists(cwd, "pyproject.toml");
2951
- if (pyproject && /\[tool\.ruff/.test(pyproject)) return "ruff check .";
2952
- return null;
2953
- }
2954
- function detectTypecheckCommand(cwd) {
2955
- if (fileExists(cwd, "tsconfig.json")) return "npx --no-install tsc --noEmit";
2956
- if (fileExists(cwd, "mypy.ini")) return "python -m mypy .";
2957
- const pyproject = readTextIfExists(cwd, "pyproject.toml");
2958
- if (pyproject && /\[tool\.mypy/.test(pyproject)) return "python -m mypy .";
2959
- if (fileExists(cwd, "go.mod")) return "go vet ./...";
2960
- if (fileExists(cwd, "Cargo.toml")) return "cargo check";
2961
- return null;
2962
- }
2963
- function makeRunnerTool(config) {
2964
- return {
2965
- name: config.name,
2966
- description: config.description,
2967
- risk: "safe",
2968
- timeoutMs: DEFAULT_TIMEOUT_MS2,
2969
- parameters: {
2970
- type: "object",
2971
- properties: {
2972
- command: {
2973
- type: "string",
2974
- description: "Exact command to run. If omitted, the project type is auto-detected."
2975
- },
2976
- timeout_ms: { type: "number", description: `Timeout in ms. Defaults to ${DEFAULT_TIMEOUT_MS2}.` }
2977
- }
2978
- },
2979
- async execute(args, ctx) {
2980
- let command = firstString(args, "command");
2981
- if (!command) {
2982
- command = config.detect(ctx.cwd) ?? void 0;
2983
- if (!command) {
2984
- return {
2985
- success: false,
2986
- output: `Could not auto-detect a command for this project. ${config.fallbackHint} Use the command argument to run one explicitly.`
2987
- };
2988
- }
2989
- }
2990
- const timeoutMs = Math.min(6e5, firstNumber(args, "timeout_ms") ?? DEFAULT_TIMEOUT_MS2);
2991
- const outcome = await runShellCommand(command, ctx.cwd, timeoutMs);
2992
- const formatted = formatOutcome(outcome);
2993
- return { success: formatted.success, output: formatted.output, truncated: formatted.truncated };
2994
- }
2995
- };
2996
- }
2997
- var runTests = makeRunnerTool({
2998
- name: "run_tests",
2999
- description: "Run the project test suite. Auto-detects npm test / pytest / go test / cargo test from the project files, or run an exact command. Use this to verify changes.",
3000
- detect: detectTestCommand,
3001
- fallbackHint: "No test runner found (looked for package.json scripts.test, pytest, go, cargo)."
3002
- });
3003
- var runLinter = makeRunnerTool({
3004
- name: "run_linter",
3005
- description: "Run the project linter (eslint / biome / ruff auto-detected).",
3006
- detect: detectLintCommand,
3007
- fallbackHint: "No linter config found (looked for eslint, biome, ruff)."
3008
- });
3009
- var runTypecheck = makeRunnerTool({
3010
- name: "run_typecheck",
3011
- description: "Run static type checking (tsc --noEmit / mypy / go vet / cargo check auto-detected).",
3012
- detect: detectTypecheckCommand,
3013
- fallbackHint: "No typechecker config found (looked for tsconfig.json, mypy, go, cargo)."
3014
- });
3015
- var inspectEnv = {
3016
- name: "inspect_env",
3017
- description: "Inspect the environment: OS info, and which toolchains are installed with versions (node, npm, python, pip, git). Use this to adapt commands to the machine.",
3018
- risk: "safe",
3019
- parameters: { type: "object", properties: {} },
3020
- async execute(_args, ctx) {
3021
- const lines = [
3022
- `os: ${process.platform} ${process.version} ${process.arch}`,
3023
- `workspace: ${ctx.cwd}`
3024
- ];
3025
- const probes = [
3026
- ["node", "node --version"],
3027
- ["npm", "npm --version"],
3028
- ["npx", "npx --version"],
3029
- ["python", "python --version"],
3030
- ["pip", "pip --version"],
3031
- ["git", "git --version"],
3032
- ["docker", "docker --version"]
3033
- ];
3034
- const results = await Promise.all(
3035
- probes.map(async ([label, probe]) => {
3036
- const outcome = await runShellCommand(probe, ctx.cwd, 8e3);
3037
- const version2 = `${outcome.stdout} ${outcome.stderr}`.trim().split("\n")[0] ?? "";
3038
- return `${label}: ${outcome.exitCode === 0 ? version2 || "installed (version unknown)" : "not available"}`;
3039
- })
3040
- );
3041
- lines.push(...results);
3042
- return { success: true, output: lines.join("\n") };
3043
- }
3044
- };
3150
+ // src/tools/registry.ts
3151
+ init_testing();
3045
3152
 
3046
3153
  // src/tools/memory.ts
3047
3154
  init_config();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@menteeai/menteeswe",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
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",