@menteeai/menteeswe 0.1.9 → 0.1.10

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 +209 -83
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -593,16 +593,24 @@ function appendTurn(cwd, task, response) {
593
593
  if (turns.length > 50) turns = turns.slice(-50);
594
594
  fs9.writeFileSync(file, JSON.stringify(turns, null, 2));
595
595
  }
596
- function formatConversationContext(cwd, limit = 12) {
596
+ function formatConversationContext(cwd, limit = 10) {
597
597
  const turns = loadConversation(cwd, limit);
598
598
  if (turns.length === 0) return "";
599
- const lines = ["# Prior conversation in this project (oldest first)"];
600
- for (const t of turns) {
601
- lines.push(`User: ${t.task}`);
602
- lines.push(`Assistant: ${t.response.trim()}`);
603
- lines.push("");
599
+ const MAX_PRIOR_CHARS = 5e3;
600
+ const header = "# Prior conversation in this project (most recent shown)";
601
+ const blocks = [];
602
+ let total = header.length;
603
+ for (let i = turns.length - 1; i >= 0; i--) {
604
+ const t = turns[i];
605
+ if (!t) continue;
606
+ const block = `User: ${t.task}
607
+ Assistant: ${t.response.trim()}
608
+ `;
609
+ if (blocks.length > 0 && total + block.length > MAX_PRIOR_CHARS) break;
610
+ blocks.unshift(block);
611
+ total += block.length;
604
612
  }
605
- return lines.join("\n");
613
+ return [header, ...blocks, ""].join("\n");
606
614
  }
607
615
  var init_conversation = __esm({
608
616
  "src/agent/conversation.ts"() {
@@ -700,10 +708,17 @@ function estimateContextChars(messages, system) {
700
708
  return total;
701
709
  }
702
710
  function trimOldToolResults(messages) {
703
- for (const message of messages) {
704
- if (message.role === "tool" && (message.content?.length ?? 0) > 2e3) {
705
- message.content = message.content.slice(0, 500) + "\n...[older tool output trimmed to save context]";
706
- }
711
+ let seen = 0;
712
+ for (let i = messages.length - 1; i >= 0; i--) {
713
+ const message = messages[i];
714
+ if (!message) continue;
715
+ if (message.role !== "tool") continue;
716
+ seen++;
717
+ if (seen <= KEEP_RECENT_TOOL) continue;
718
+ const content = message.content ?? "";
719
+ if (content.length <= 240) continue;
720
+ const head = content.replace(/\s+/g, " ").slice(0, 160);
721
+ message.content = `\u27E8prior tool output trimmed: ${head}\u2026 (${content.length} chars)\u27E9`;
707
722
  }
708
723
  }
709
724
  async function runAgent(options) {
@@ -951,7 +966,7 @@ ${systemExtra}` : "");
951
966
  });
952
967
  return { success, finalText, state };
953
968
  }
954
- var MAX_CONTEXT_CHARS, READ_BUDGET, RATE_LIMIT_MAX_ATTEMPTS;
969
+ var MAX_CONTEXT_CHARS, READ_BUDGET, RATE_LIMIT_MAX_ATTEMPTS, KEEP_RECENT_TOOL;
955
970
  var init_loop = __esm({
956
971
  "src/agent/loop.ts"() {
957
972
  "use strict";
@@ -959,15 +974,116 @@ var init_loop = __esm({
959
974
  init_conversation();
960
975
  init_state();
961
976
  init_base();
962
- MAX_CONTEXT_CHARS = 48e4;
977
+ MAX_CONTEXT_CHARS = 7e4;
963
978
  READ_BUDGET = 6;
964
979
  RATE_LIMIT_MAX_ATTEMPTS = 8;
980
+ KEEP_RECENT_TOOL = 4;
965
981
  }
966
982
  });
967
983
 
968
- // src/tui/Approval.tsx
969
- import { Box, Text, useInput } from "ink";
984
+ // src/tui/markdown.tsx
985
+ import { Box, Text } from "ink";
970
986
  import { jsx, jsxs } from "react/jsx-runtime";
987
+ function renderInline(text, keyPrefix) {
988
+ const nodes = [];
989
+ const regex = /(\*\*([^*]+)\*\*)|(\*([^*]+)\*)|(`([^`]+)`)/g;
990
+ let last = 0;
991
+ let m;
992
+ let i = 0;
993
+ while ((m = regex.exec(text)) !== null) {
994
+ if (m.index > last) nodes.push(text.slice(last, m.index));
995
+ if (m[2] !== void 0) {
996
+ nodes.push(
997
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: m[2] }, `${keyPrefix}-b${i}`)
998
+ );
999
+ } else if (m[4] !== void 0) {
1000
+ nodes.push(
1001
+ /* @__PURE__ */ jsx(Text, { italic: true, children: m[4] }, `${keyPrefix}-i${i}`)
1002
+ );
1003
+ } else if (m[6] !== void 0) {
1004
+ nodes.push(
1005
+ /* @__PURE__ */ jsx(Text, { color: "greenBright", children: m[6] }, `${keyPrefix}-c${i}`)
1006
+ );
1007
+ }
1008
+ last = m.index + m[0].length;
1009
+ i++;
1010
+ }
1011
+ if (last < text.length) nodes.push(text.slice(last));
1012
+ return nodes;
1013
+ }
1014
+ function renderMarkdown(md) {
1015
+ const lines = md.split("\n");
1016
+ const blocks = [];
1017
+ let para = [];
1018
+ let key = 0;
1019
+ const flushPara = () => {
1020
+ if (para.length === 0) return;
1021
+ blocks.push(/* @__PURE__ */ jsx(Text, { children: renderInline(para.join(" "), `p${key}`) }, `p${key++}`));
1022
+ para = [];
1023
+ };
1024
+ for (const line of lines) {
1025
+ if (line.trim() === "") {
1026
+ flushPara();
1027
+ continue;
1028
+ }
1029
+ const heading = /^(#{1,6})\s+(.*)$/.exec(line);
1030
+ if (heading) {
1031
+ flushPara();
1032
+ const level = heading[1]?.length ?? 0;
1033
+ blocks.push(
1034
+ /* @__PURE__ */ jsx(Text, { bold: true, color: level <= 2 ? "cyan" : "white", children: renderInline(heading[2] ?? "", `h${key}`) }, `h${key++}`)
1035
+ );
1036
+ continue;
1037
+ }
1038
+ const bullet = /^\s*[-*]\s+(.*)$/.exec(line);
1039
+ if (bullet) {
1040
+ flushPara();
1041
+ blocks.push(
1042
+ /* @__PURE__ */ jsxs(Text, { children: [
1043
+ " \u2022 ",
1044
+ renderInline(bullet[1] ?? "", `b${key}`)
1045
+ ] }, `b${key++}`)
1046
+ );
1047
+ continue;
1048
+ }
1049
+ const numbered = /^\s*\d+\.\s+(.*)$/.exec(line);
1050
+ if (numbered) {
1051
+ flushPara();
1052
+ blocks.push(
1053
+ /* @__PURE__ */ jsxs(Text, { children: [
1054
+ " ",
1055
+ renderInline(numbered[1] ?? "", `n${key}`)
1056
+ ] }, `n${key++}`)
1057
+ );
1058
+ continue;
1059
+ }
1060
+ para.push(line.trim());
1061
+ }
1062
+ flushPara();
1063
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: blocks });
1064
+ }
1065
+ function AnswerBlock({ text }) {
1066
+ return /* @__PURE__ */ jsx(
1067
+ Box,
1068
+ {
1069
+ flexDirection: "column",
1070
+ borderStyle: "round",
1071
+ borderColor: "cyan",
1072
+ paddingX: 1,
1073
+ marginY: 0,
1074
+ children: renderMarkdown(text)
1075
+ }
1076
+ );
1077
+ }
1078
+ var init_markdown = __esm({
1079
+ "src/tui/markdown.tsx"() {
1080
+ "use strict";
1081
+ }
1082
+ });
1083
+
1084
+ // src/tui/Approval.tsx
1085
+ import { Box as Box2, Text as Text2, useInput } from "ink";
1086
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
971
1087
  function argPreview(request) {
972
1088
  const args = request.args;
973
1089
  if (request.tool === "apply_patch" && typeof args.old_string === "string" && typeof args.new_string === "string") {
@@ -985,8 +1101,8 @@ function ApprovalPrompt({ request, onDecision }) {
985
1101
  else if (input === "a") onDecision("always");
986
1102
  else if (input === "n" || key.escape) onDecision("deny");
987
1103
  });
988
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, marginY: 1, children: [
989
- /* @__PURE__ */ jsxs(Text, { bold: true, color: "magenta", children: [
1104
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, marginY: 1, children: [
1105
+ /* @__PURE__ */ jsxs2(Text2, { bold: true, color: "magenta", children: [
990
1106
  "Permission needed: ",
991
1107
  friendlyToolName(request.tool),
992
1108
  " (",
@@ -994,14 +1110,14 @@ function ApprovalPrompt({ request, onDecision }) {
994
1110
  ") \u2014 ",
995
1111
  request.risk
996
1112
  ] }),
997
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { children: argPreview(request) }) }),
998
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { children: [
999
- /* @__PURE__ */ jsx(Text, { color: "green", bold: true, children: "[y]" }),
1113
+ /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { children: argPreview(request) }) }),
1114
+ /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsxs2(Text2, { children: [
1115
+ /* @__PURE__ */ jsx2(Text2, { color: "green", bold: true, children: "[y]" }),
1000
1116
  " allow once \xB7 ",
1001
- /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "[a]" }),
1117
+ /* @__PURE__ */ jsx2(Text2, { color: "cyan", bold: true, children: "[a]" }),
1002
1118
  " allow this session \xB7",
1003
1119
  " ",
1004
- /* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "[n]" }),
1120
+ /* @__PURE__ */ jsx2(Text2, { color: "red", bold: true, children: "[n]" }),
1005
1121
  " deny"
1006
1122
  ] }) })
1007
1123
  ] });
@@ -1015,8 +1131,8 @@ var init_Approval = __esm({
1015
1131
 
1016
1132
  // src/tui/SelectDialog.tsx
1017
1133
  import { useEffect, useMemo, useState } from "react";
1018
- import { Box as Box2, Text as Text2, useInput as useInput2 } from "ink";
1019
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1134
+ import { Box as Box3, Text as Text3, useInput as useInput2 } from "ink";
1135
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1020
1136
  function SelectDialog({
1021
1137
  title,
1022
1138
  items,
@@ -1051,34 +1167,34 @@ function SelectDialog({
1051
1167
  Math.min(cursor - Math.floor(VISIBLE / 2), Math.max(0, filtered.length - VISIBLE))
1052
1168
  );
1053
1169
  const visible = filtered.slice(start, start + VISIBLE);
1054
- return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, marginY: 1, children: [
1055
- /* @__PURE__ */ jsx2(Text2, { bold: true, color: "cyan", children: title }),
1056
- /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
1057
- /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
1170
+ return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, marginY: 1, children: [
1171
+ /* @__PURE__ */ jsx3(Text3, { bold: true, color: "cyan", children: title }),
1172
+ /* @__PURE__ */ jsxs3(Box3, { marginTop: 1, children: [
1173
+ /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
1058
1174
  "search: ",
1059
1175
  filter
1060
1176
  ] }),
1061
- /* @__PURE__ */ jsx2(Text2, { children: "\u258F" })
1177
+ /* @__PURE__ */ jsx3(Text3, { children: "\u258F" })
1062
1178
  ] }),
1063
- loading ? /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "loading\u2026" }) : null,
1064
- error ? /* @__PURE__ */ jsx2(Text2, { color: "red", children: error }) : null,
1065
- !loading && !error ? /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
1179
+ loading ? /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "loading\u2026" }) : null,
1180
+ error ? /* @__PURE__ */ jsx3(Text3, { color: "red", children: error }) : null,
1181
+ !loading && !error ? /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
1066
1182
  visible.map((item, i) => {
1067
1183
  const index = start + i;
1068
1184
  const isCursor = index === cursor;
1069
1185
  const isCurrent = item === current;
1070
1186
  const description = descriptions?.[item];
1071
- return /* @__PURE__ */ jsxs2(Text2, { color: isCursor ? "cyan" : void 0, bold: isCursor, children: [
1187
+ return /* @__PURE__ */ jsxs3(Text3, { color: isCursor ? "cyan" : void 0, bold: isCursor, children: [
1072
1188
  isCursor ? "\u276F " : " ",
1073
1189
  isCurrent ? "\u25CF " : "\u25CB ",
1074
1190
  item,
1075
1191
  isCurrent ? " (current)" : "",
1076
- description ? /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: ` \u2014 ${description}` }) : null
1192
+ description ? /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: ` \u2014 ${description}` }) : null
1077
1193
  ] }, item);
1078
1194
  }),
1079
- filtered.length === 0 ? /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "no matches" }) : null
1195
+ filtered.length === 0 ? /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "no matches" }) : null
1080
1196
  ] }) : null,
1081
- /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "\u2191\u2193 move \xB7 type to filter \xB7 enter select \xB7 esc cancel" }) })
1197
+ /* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "\u2191\u2193 move \xB7 type to filter \xB7 enter select \xB7 esc cancel" }) })
1082
1198
  ] });
1083
1199
  }
1084
1200
  var VISIBLE;
@@ -1091,22 +1207,22 @@ var init_SelectDialog = __esm({
1091
1207
 
1092
1208
  // src/tui/KeyDialog.tsx
1093
1209
  import { useState as useState2 } from "react";
1094
- import { Box as Box3, Text as Text3, useInput as useInput3 } from "ink";
1210
+ import { Box as Box4, Text as Text4, useInput as useInput3 } from "ink";
1095
1211
  import TextInput from "ink-text-input";
1096
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1212
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1097
1213
  function KeyDialog({ providerName, onSubmit, onClose }) {
1098
1214
  const [value, setValue] = useState2("");
1099
1215
  useInput3((_input, key) => {
1100
1216
  if (key.escape) onClose();
1101
1217
  });
1102
- return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, marginY: 1, children: [
1103
- /* @__PURE__ */ jsxs3(Text3, { bold: true, color: "magenta", children: [
1218
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, marginY: 1, children: [
1219
+ /* @__PURE__ */ jsxs4(Text4, { bold: true, color: "magenta", children: [
1104
1220
  "API key for ",
1105
1221
  providerName
1106
1222
  ] }),
1107
- /* @__PURE__ */ jsxs3(Box3, { marginTop: 1, children: [
1108
- /* @__PURE__ */ jsx3(Text3, { children: "key: " }),
1109
- /* @__PURE__ */ jsx3(
1223
+ /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
1224
+ /* @__PURE__ */ jsx4(Text4, { children: "key: " }),
1225
+ /* @__PURE__ */ jsx4(
1110
1226
  TextInput,
1111
1227
  {
1112
1228
  mask: "*",
@@ -1119,7 +1235,7 @@ function KeyDialog({ providerName, onSubmit, onClose }) {
1119
1235
  }
1120
1236
  )
1121
1237
  ] }),
1122
- /* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "enter confirm \xB7 esc cancel \xB7 saved to ~/.mentee/config.json" }) })
1238
+ /* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "enter confirm \xB7 esc cancel \xB7 saved to ~/.mentee/config.json" }) })
1123
1239
  ] });
1124
1240
  }
1125
1241
  var init_KeyDialog = __esm({
@@ -1132,7 +1248,7 @@ var init_KeyDialog = __esm({
1132
1248
  var version;
1133
1249
  var init_package = __esm({
1134
1250
  "package.json"() {
1135
- version = "0.1.9";
1251
+ version = "0.1.10";
1136
1252
  }
1137
1253
  });
1138
1254
 
@@ -1142,9 +1258,9 @@ __export(App_exports, {
1142
1258
  App: () => App
1143
1259
  });
1144
1260
  import { useEffect as useEffect2, useMemo as useMemo2, useRef, useState as useState3 } from "react";
1145
- import { Box as Box4, Static, Text as Text4, useApp, useInput as useInput4, useStdout } from "ink";
1261
+ import { Box as Box5, Static, Text as Text5, useApp, useInput as useInput4, useStdout } from "ink";
1146
1262
  import TextInput2 from "ink-text-input";
1147
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1263
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1148
1264
  function App(props) {
1149
1265
  const { exit } = useApp();
1150
1266
  const { stdout } = useStdout();
@@ -1172,15 +1288,16 @@ function App(props) {
1172
1288
  const [detailsOpen, setDetailsOpen] = useState3(false);
1173
1289
  const [showDetails, setShowDetails] = useState3(false);
1174
1290
  const [thinkingText, setThinkingText] = useState3("");
1291
+ const finalTextRef = useRef(null);
1175
1292
  const pendingTool = useRef(null);
1176
1293
  const counter = useRef(0);
1177
1294
  const stateRef = useRef({ running, approval, dialog, factoryResult, providerName, model });
1178
1295
  stateRef.current = { running, approval, dialog, factoryResult, providerName, model };
1179
1296
  const abortRef = useRef(null);
1180
- const appendLog = (text, noise = false) => {
1297
+ const appendLog = (text, noise = false, kind) => {
1181
1298
  if (!text) return;
1182
1299
  counter.current += 1;
1183
- const line = { id: counter.current, text, noise };
1300
+ const line = { id: counter.current, text, noise, kind };
1184
1301
  setLog((prev) => [...prev, line]);
1185
1302
  };
1186
1303
  useEffect2(() => {
@@ -1211,10 +1328,12 @@ function App(props) {
1211
1328
  } else if (event.type === "task_completed") {
1212
1329
  const text = typeof event.data?.finalText === "string" ? event.data.finalText.trim() : "";
1213
1330
  if (text) {
1214
- appendLog(text);
1331
+ finalTextRef.current = text;
1215
1332
  setFinalPending(text);
1216
1333
  setTypedText("");
1217
1334
  setTyping(true);
1335
+ } else {
1336
+ finalTextRef.current = null;
1218
1337
  }
1219
1338
  }
1220
1339
  });
@@ -1389,6 +1508,10 @@ function App(props) {
1389
1508
  appendLog(factoryResult.error ?? "No provider configured. Press Ctrl+K to add an API key.");
1390
1509
  return;
1391
1510
  }
1511
+ if (finalTextRef.current) {
1512
+ appendLog(finalTextRef.current, false, "answer");
1513
+ finalTextRef.current = null;
1514
+ }
1392
1515
  setFinalPending(null);
1393
1516
  setTypedText("");
1394
1517
  setTyping(false);
@@ -1468,9 +1591,9 @@ function App(props) {
1468
1591
  else if (key.ctrl && input === "k") setDialog({ kind: "key" });
1469
1592
  });
1470
1593
  const modelLabel = model ?? factoryResult.provider?.defaultModel ?? (factoryResult.error ? "no key" : "");
1471
- const header = /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginBottom: 1, children: [
1472
- /* @__PURE__ */ jsx4(Text4, { color: "cyan", children: BANNER }),
1473
- /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
1594
+ const header = /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginBottom: 1, children: [
1595
+ /* @__PURE__ */ jsx5(Text5, { color: "cyan", children: BANNER }),
1596
+ /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
1474
1597
  "v",
1475
1598
  version,
1476
1599
  " \xB7 ",
@@ -1481,42 +1604,44 @@ function App(props) {
1481
1604
  " \xB7 ",
1482
1605
  props.cwd
1483
1606
  ] }),
1484
- /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "Alt+M model \xB7 Ctrl+P provider \xB7 Ctrl+K key \xB7 Alt+D details \xB7 /help" })
1607
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Alt+M model \xB7 Ctrl+P provider \xB7 Ctrl+K key \xB7 Alt+D details \xB7 /help" })
1485
1608
  ] }, "header");
1486
1609
  const cols = stdout.columns || 80;
1487
1610
  const marquee = thinkingText.slice(-Math.max(1, cols - 4));
1488
- return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
1489
- /* @__PURE__ */ jsx4(Static, { items: [{ key: "header", text: header }], children: (item) => /* @__PURE__ */ jsx4(Box4, { children: item.text }, item.key) }),
1490
- /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
1491
- log.filter((l) => showDetails || !l.noise).map((line) => /* @__PURE__ */ jsx4(Text4, { children: line.text }, line.id)),
1492
- finalPending !== null ? /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
1493
- /* @__PURE__ */ jsx4(Text4, { color: "green", children: typedText }),
1494
- typing ? /* @__PURE__ */ jsx4(Text4, { color: "green", children: "\u258C" }) : null
1611
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1612
+ /* @__PURE__ */ jsx5(Static, { items: [{ key: "header", text: header }], children: (item) => /* @__PURE__ */ jsx5(Box5, { children: item.text }, item.key) }),
1613
+ /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1614
+ log.filter((l) => showDetails || !l.noise).map(
1615
+ (line) => line.kind === "answer" ? /* @__PURE__ */ jsx5(AnswerBlock, { text: line.text }, line.id) : /* @__PURE__ */ jsx5(Text5, { children: line.text }, line.id)
1616
+ ),
1617
+ finalPending !== null ? /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
1618
+ /* @__PURE__ */ jsx5(Text5, { color: "green", children: typedText }),
1619
+ typing ? /* @__PURE__ */ jsx5(Text5, { color: "green", children: "\u258C" }) : null
1495
1620
  ] }) : null,
1496
1621
  detailsOpen && inspectorIndex !== null && toolHistory[inspectorIndex] ? (() => {
1497
1622
  const rec = toolHistory[inspectorIndex];
1498
1623
  const outLines = rec.output.split("\n").slice(0, 24).join("\n");
1499
- return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: [
1500
- /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
1624
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: [
1625
+ /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
1501
1626
  " tool details (",
1502
1627
  inspectorIndex + 1,
1503
1628
  "/",
1504
1629
  toolHistory.length,
1505
1630
  ") \xB7 press d to cycle "
1506
1631
  ] }),
1507
- /* @__PURE__ */ jsxs4(Text4, { color: toolColorName(rec.name), bold: true, children: [
1632
+ /* @__PURE__ */ jsxs5(Text5, { color: toolColorName(rec.name), bold: true, children: [
1508
1633
  rec.name,
1509
1634
  " ",
1510
1635
  rec.target
1511
1636
  ] }),
1512
- /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
1637
+ /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
1513
1638
  "args: ",
1514
1639
  rec.args.slice(0, 400) || "(none)"
1515
1640
  ] }),
1516
- /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: outLines || "(no output)" })
1641
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: outLines || "(no output)" })
1517
1642
  ] });
1518
1643
  })() : null,
1519
- dialog?.kind === "model" ? /* @__PURE__ */ jsx4(
1644
+ dialog?.kind === "model" ? /* @__PURE__ */ jsx5(
1520
1645
  SelectDialog,
1521
1646
  {
1522
1647
  title: `Model \u2014 ${providerName}`,
@@ -1530,7 +1655,7 @@ function App(props) {
1530
1655
  },
1531
1656
  onClose: () => setDialog(null)
1532
1657
  }
1533
- ) : dialog?.kind === "provider" ? /* @__PURE__ */ jsx4(
1658
+ ) : dialog?.kind === "provider" ? /* @__PURE__ */ jsx5(
1534
1659
  SelectDialog,
1535
1660
  {
1536
1661
  title: "Provider",
@@ -1543,7 +1668,7 @@ function App(props) {
1543
1668
  },
1544
1669
  onClose: () => setDialog(null)
1545
1670
  }
1546
- ) : dialog?.kind === "key" ? /* @__PURE__ */ jsx4(
1671
+ ) : dialog?.kind === "key" ? /* @__PURE__ */ jsx5(
1547
1672
  KeyDialog,
1548
1673
  {
1549
1674
  providerName,
@@ -1553,7 +1678,7 @@ function App(props) {
1553
1678
  },
1554
1679
  onClose: () => setDialog(null)
1555
1680
  }
1556
- ) : approval ? /* @__PURE__ */ jsx4(
1681
+ ) : approval ? /* @__PURE__ */ jsx5(
1557
1682
  ApprovalPrompt,
1558
1683
  {
1559
1684
  request: approval,
@@ -1562,22 +1687,22 @@ function App(props) {
1562
1687
  if (decision === "always") bus.emit("info", "Approved for the rest of this session.");
1563
1688
  }
1564
1689
  }
1565
- ) : running ? /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
1566
- /* @__PURE__ */ jsxs4(Box4, { children: [
1567
- /* @__PURE__ */ jsxs4(Text4, { color: "yellow", children: [
1690
+ ) : running ? /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1691
+ /* @__PURE__ */ jsxs5(Box5, { children: [
1692
+ /* @__PURE__ */ jsxs5(Text5, { color: "yellow", children: [
1568
1693
  SPINNER_FRAMES[frame],
1569
1694
  " "
1570
1695
  ] }),
1571
- /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "agent working... (Ctrl+C to exit)" })
1696
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "agent working... (Ctrl+C to exit)" })
1572
1697
  ] }),
1573
- thinkingText ? /* @__PURE__ */ jsxs4(Box4, { children: [
1574
- /* @__PURE__ */ jsx4(Text4, { color: "cyan", children: "\u{1F4AD} " }),
1575
- /* @__PURE__ */ jsx4(Text4, { color: "cyan", dimColor: true, children: marquee }),
1576
- /* @__PURE__ */ jsx4(Text4, { color: "cyan", children: "\u258C" })
1698
+ thinkingText ? /* @__PURE__ */ jsxs5(Box5, { children: [
1699
+ /* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "\u{1F4AD} " }),
1700
+ /* @__PURE__ */ jsx5(Text5, { color: "cyan", dimColor: true, children: marquee }),
1701
+ /* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "\u258C" })
1577
1702
  ] }) : null
1578
- ] }) : /* @__PURE__ */ jsxs4(Box4, { children: [
1579
- /* @__PURE__ */ jsx4(Text4, { color: "cyan", bold: true, children: "\u25B8 " }),
1580
- /* @__PURE__ */ jsx4(
1703
+ ] }) : /* @__PURE__ */ jsxs5(Box5, { children: [
1704
+ /* @__PURE__ */ jsx5(Text5, { color: "cyan", bold: true, children: "\u25B8 " }),
1705
+ /* @__PURE__ */ jsx5(
1581
1706
  TextInput2,
1582
1707
  {
1583
1708
  value: taskInput,
@@ -1597,6 +1722,7 @@ var init_App = __esm({
1597
1722
  init_events();
1598
1723
  init_logging();
1599
1724
  init_render();
1725
+ init_markdown();
1600
1726
  init_approval();
1601
1727
  init_loop();
1602
1728
  init_conversation();
@@ -3332,7 +3458,7 @@ Saved to ${configFilePath()}
3332
3458
 
3333
3459
  // src/cli.tsx
3334
3460
  import path9 from "path";
3335
- import { jsx as jsx5 } from "react/jsx-runtime";
3461
+ import { jsx as jsx6 } from "react/jsx-runtime";
3336
3462
  var packageJson = { version: "0.1.0" };
3337
3463
  var program = new Command();
3338
3464
  program.name("mentee").description("MenteE SWE \u2014 an autonomous SWE agent in your terminal. Bring your own model: Kimi, GLM, and more.").version(packageJson.version);
@@ -3389,7 +3515,7 @@ program.argument("[task...]", "the software task to perform (omit to type it int
3389
3515
  const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
3390
3516
  const { render } = await import("ink");
3391
3517
  const { waitUntilExit } = render(
3392
- /* @__PURE__ */ jsx5(
3518
+ /* @__PURE__ */ jsx6(
3393
3519
  App2,
3394
3520
  {
3395
3521
  initialTask: task || void 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@menteeai/menteeswe",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
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",