@menteeai/menteeswe 0.1.25 → 0.1.27

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 +103 -14
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1306,7 +1306,7 @@ var init_loop = __esm({
1306
1306
  var version;
1307
1307
  var init_package = __esm({
1308
1308
  "package.json"() {
1309
- version = "0.1.25";
1309
+ version = "0.1.27";
1310
1310
  }
1311
1311
  });
1312
1312
 
@@ -1709,13 +1709,18 @@ function App(props) {
1709
1709
  const stateRef = useRef({ running, approval, dialog, factoryResult, providerName, model });
1710
1710
  stateRef.current = { running, approval, dialog, factoryResult, providerName, model };
1711
1711
  const abortRef = useRef(null);
1712
+ const maxScrollRef = useRef(0);
1713
+ const scrollOffsetRef = useRef(0);
1714
+ scrollOffsetRef.current = scrollOffset;
1712
1715
  const appendLog = (text, noise = false, kind) => {
1713
1716
  if (!text) return;
1717
+ if (scrollOffsetRef.current > 0) setScrollOffset((o) => o + 1);
1714
1718
  counter.current += 1;
1715
1719
  const line = { id: counter.current, text, noise, kind };
1716
1720
  setLog((prev) => [...prev, line]);
1717
1721
  };
1718
1722
  const appendPatchEdit = (edit) => {
1723
+ if (scrollOffsetRef.current > 0) setScrollOffset((o) => o + 1);
1719
1724
  counter.current += 1;
1720
1725
  setLog((prev) => [...prev, { id: counter.current, text: "", noise: false, kind: "patch", edit }]);
1721
1726
  };
@@ -1806,6 +1811,17 @@ function App(props) {
1806
1811
  const timer = setInterval(() => setFrame((f) => (f + 1) % SPINNER_FRAMES.length), 80);
1807
1812
  return () => clearInterval(timer);
1808
1813
  }, [running]);
1814
+ useEffect2(() => {
1815
+ const onWheel = (dir) => {
1816
+ if (stateRef.current.dialog || stateRef.current.approval) return;
1817
+ if (dir === "up") setScrollOffset((o) => Math.min(o + 3, maxScrollRef.current));
1818
+ else if (dir === "down") setScrollOffset((o) => Math.max(0, o - 3));
1819
+ };
1820
+ props.scrollEvents.on("wheel", onWheel);
1821
+ return () => {
1822
+ props.scrollEvents.off("wheel", onWheel);
1823
+ };
1824
+ }, [props.scrollEvents]);
1809
1825
  useEffect2(() => {
1810
1826
  const turns = loadConversation(props.cwd);
1811
1827
  if (turns.length > 0) {
@@ -2047,13 +2063,21 @@ function App(props) {
2047
2063
  }
2048
2064
  if (!stateRef.current.dialog && !stateRef.current.approval) {
2049
2065
  if (key.pageUp) {
2050
- setScrollOffset((o) => o + 10);
2066
+ setScrollOffset((o) => Math.min(o + 10, maxScrollRef.current));
2051
2067
  return;
2052
2068
  }
2053
2069
  if (key.pageDown) {
2054
2070
  setScrollOffset((o) => Math.max(0, o - 10));
2055
2071
  return;
2056
2072
  }
2073
+ if (key.upArrow) {
2074
+ setScrollOffset((o) => Math.min(o + 3, maxScrollRef.current));
2075
+ return;
2076
+ }
2077
+ if (key.downArrow) {
2078
+ setScrollOffset((o) => Math.max(0, o - 3));
2079
+ return;
2080
+ }
2057
2081
  }
2058
2082
  if (stateRef.current.dialog || stateRef.current.approval || stateRef.current.running) return;
2059
2083
  if (key.meta && (input === "m" || input === "M")) openModelDialog();
@@ -2073,7 +2097,9 @@ function App(props) {
2073
2097
  const summaryH = taskSummary ? 1 + wrappedH(taskSummary, mainInnerW) : 0;
2074
2098
  const visible = useMemo2(() => {
2075
2099
  const filtered = log.filter((l) => (showDetails || !l.noise) && (l.kind !== "patch" || showEdits));
2076
- const sliceEnd = Math.max(0, filtered.length - scrollOffset);
2100
+ maxScrollRef.current = Math.max(0, filtered.length - 1);
2101
+ const offset = Math.min(scrollOffset, maxScrollRef.current);
2102
+ const sliceEnd = Math.max(0, filtered.length - offset);
2077
2103
  const budget = mainInnerH - answerH - summaryH - 2;
2078
2104
  let used = 0;
2079
2105
  let start = sliceEnd;
@@ -2094,13 +2120,27 @@ function App(props) {
2094
2120
  ] }, label);
2095
2121
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", height: rows, children: [
2096
2122
  /* @__PURE__ */ jsxs6(Box6, { flexDirection: "row", flexGrow: 1, children: [
2097
- /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", flexGrow: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: [
2098
- visible.map(renderLine),
2099
- finalPending !== null ? /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, children: /* @__PURE__ */ jsxs6(Text6, { color: "green", children: [
2100
- typedText,
2101
- typing ? "\u258C" : ""
2102
- ] }) }) : null,
2103
- taskSummary ? /* @__PURE__ */ jsx6(Text6, { children: taskSummary }) : null
2123
+ /* @__PURE__ */ jsxs6(Box6, { flexDirection: "row", flexGrow: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: [
2124
+ /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", flexGrow: 1, children: [
2125
+ visible.map(renderLine),
2126
+ finalPending !== null ? /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, children: /* @__PURE__ */ jsxs6(Text6, { color: "green", children: [
2127
+ typedText,
2128
+ typing ? "\u258C" : ""
2129
+ ] }) }) : null,
2130
+ taskSummary ? /* @__PURE__ */ jsx6(Text6, { children: taskSummary }) : null
2131
+ ] }),
2132
+ (() => {
2133
+ const total = maxScrollRef.current;
2134
+ if (total <= 0) return null;
2135
+ const H = Math.max(4, mainInnerH - 2);
2136
+ const offset = Math.min(scrollOffset, maxScrollRef.current);
2137
+ const frac = maxScrollRef.current > 0 ? offset / maxScrollRef.current : 0;
2138
+ const thumbLen = Math.max(1, Math.round(H * 0.25));
2139
+ const thumbStart = Math.round((1 - frac) * (H - thumbLen));
2140
+ const glyphs = [];
2141
+ for (let i = 0; i < H; i++) glyphs.push(i >= thumbStart && i < thumbStart + thumbLen ? "\u2588" : "\u2502");
2142
+ return /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", width: 1, children: glyphs.map((g, i) => /* @__PURE__ */ jsx6(Text6, { color: g === "\u2588" ? "magenta" : "gray", children: g }, i)) });
2143
+ })()
2104
2144
  ] }),
2105
2145
  /* @__PURE__ */ jsxs6(Box6, { width: SIDEBAR_W, flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, children: [
2106
2146
  /* @__PURE__ */ jsx6(Text6, { bold: true, color: "magenta", children: "MenteE SWE \u{1F380}" }),
@@ -2221,7 +2261,7 @@ function App(props) {
2221
2261
  }
2222
2262
  )
2223
2263
  ] }),
2224
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: (scrollOffset > 0 ? `\u2191${scrollOffset} hidden \xB7 ` : "") + "Alt+M model \xB7 Ctrl+P provider \xB7 Ctrl+K key \xB7 Alt+D details \xB7 Alt+E edits \xB7 PgUp/PgDn scroll \xB7 /help".slice(
2264
+ /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: (scrollOffset > 0 ? `\u2191${scrollOffset} hidden \xB7 ` : "") + "Alt+M model \xB7 Ctrl+P provider \xB7 Ctrl+K key \xB7 Alt+D details \xB7 Alt+E edits \xB7 \u2191/\u2193\xB7PgUp/PgDn\xB7wheel scroll \xB7 /help".slice(
2225
2265
  0,
2226
2266
  Math.max(10, cols - (scrollOffset > 0 ? 16 : 0))
2227
2267
  ) })
@@ -3920,6 +3960,8 @@ Saved to ${configFilePath()}
3920
3960
  // src/cli.tsx
3921
3961
  init_package();
3922
3962
  import path9 from "path";
3963
+ import { PassThrough } from "stream";
3964
+ import { EventEmitter } from "events";
3923
3965
  import { jsx as jsx7 } from "react/jsx-runtime";
3924
3966
  var program = new Command();
3925
3967
  program.name("mentee").description("MenteE SWE \u2014 an autonomous SWE agent in your terminal. Bring your own model: Kimi, GLM, Z.ai, OpenRouter, NVIDIA, and more.").version(version);
@@ -3973,6 +4015,46 @@ program.argument("[task...]", "the software task to perform (omit to type it int
3973
4015
  return { error: error.message };
3974
4016
  }
3975
4017
  };
4018
+ const scrollEvents = new EventEmitter();
4019
+ const virtualStdin = new PassThrough();
4020
+ const anyStdin = virtualStdin;
4021
+ anyStdin.isTTY = process.stdin.isTTY === true;
4022
+ anyStdin.setRawMode = (mode) => {
4023
+ if (process.stdin.isTTY) process.stdin.setRawMode(mode);
4024
+ };
4025
+ let pending = "";
4026
+ const flush = (s) => {
4027
+ if (s) virtualStdin.write(s);
4028
+ };
4029
+ const onRawData = (chunk) => {
4030
+ pending += chunk.toString("utf8");
4031
+ for (; ; ) {
4032
+ const esc = pending.indexOf("\x1B[<");
4033
+ if (esc === -1) {
4034
+ flush(pending);
4035
+ pending = "";
4036
+ return;
4037
+ }
4038
+ flush(pending.slice(0, esc));
4039
+ pending = pending.slice(esc);
4040
+ const m = /^\u001b\[<(\d+);\d+;\d+([Mm])/.exec(pending);
4041
+ if (m) {
4042
+ const cb = m[1] ?? "";
4043
+ if (cb === "64") scrollEvents.emit("wheel", "up");
4044
+ else if (cb === "65") scrollEvents.emit("wheel", "down");
4045
+ pending = pending.slice(m[0].length);
4046
+ continue;
4047
+ }
4048
+ if (pending.length > 32) {
4049
+ flush(pending);
4050
+ pending = "";
4051
+ }
4052
+ return;
4053
+ }
4054
+ };
4055
+ process.stdin.on("data", onRawData);
4056
+ if (process.stdin.isTTY) process.stdin.setRawMode(true);
4057
+ process.stdout.write("\x1B[?1000;1006h");
3976
4058
  const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
3977
4059
  const { render } = await import("ink");
3978
4060
  const { waitUntilExit } = render(
@@ -3985,12 +4067,19 @@ program.argument("[task...]", "the software task to perform (omit to type it int
3985
4067
  tools,
3986
4068
  cwd: path9.resolve(cwd),
3987
4069
  yes: options.yes === true,
3988
- maxIterations
4070
+ maxIterations,
4071
+ scrollEvents
3989
4072
  }
3990
4073
  ),
3991
- { exitOnCtrlC: false }
4074
+ { exitOnCtrlC: false, stdin: virtualStdin }
3992
4075
  );
3993
- await waitUntilExit();
4076
+ try {
4077
+ await waitUntilExit();
4078
+ } finally {
4079
+ process.stdout.write("\x1B[?1000;1006l");
4080
+ if (process.stdin.isTTY) process.stdin.setRawMode(false);
4081
+ process.stdin.off("data", onRawData);
4082
+ }
3994
4083
  });
3995
4084
  program.parseAsync(process.argv).catch((error) => {
3996
4085
  console.error(chalk4.red(error.message));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@menteeai/menteeswe",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
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",