@menteeai/menteeswe 0.1.10 → 0.1.12
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 +219 -103
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -52,7 +52,9 @@ var init_config = __esm({
|
|
|
52
52
|
kimi: "MENTEE_KIMI_API_KEY",
|
|
53
53
|
glm: "MENTEE_GLM_API_KEY",
|
|
54
54
|
zai: "MENTEE_ZAI_API_KEY",
|
|
55
|
-
"zai-coding": "MENTEE_ZAI_API_KEY"
|
|
55
|
+
"zai-coding": "MENTEE_ZAI_API_KEY",
|
|
56
|
+
openrouter: "MENTEE_OPENROUTER_API_KEY",
|
|
57
|
+
nvidia: "MENTEE_NVIDIA_API_KEY"
|
|
56
58
|
};
|
|
57
59
|
}
|
|
58
60
|
});
|
|
@@ -319,7 +321,7 @@ function formatEvent(event) {
|
|
|
319
321
|
const statusLine = cancelled ? chalk.yellow.bold("\u2716 Task cancelled") : success ? chalk.green.bold("\u2714 Task completed") : chalk.red.bold("\u2716 Task failed");
|
|
320
322
|
const filesLine = modifiedFiles.length > 0 ? chalk.cyan.dim(` \u{1F4DD} ${modifiedFiles.length} file(s): ${modifiedFiles.join(", ")}`) : "";
|
|
321
323
|
const tipLine = success ? chalk.dim(" Next: type a new task, or /help for commands") : chalk.yellow.dim(" The task did not finish \u2014 check the steps above and retry");
|
|
322
|
-
const detailsLine = toolCalls > 0 ? chalk.dim(` \u{1F50D}
|
|
324
|
+
const detailsLine = toolCalls > 0 ? chalk.dim(` \u{1F50D} Alt+D to toggle ${toolCalls} tool call(s)`) : "";
|
|
323
325
|
const block = [sep, statusLine, statsLine, filesLine, tipLine, detailsLine, sep, ""];
|
|
324
326
|
return block.filter((line) => line !== "").join("\n");
|
|
325
327
|
}
|
|
@@ -528,12 +530,13 @@ ${tree}
|
|
|
528
530
|
|
|
529
531
|
# Communication (IMPORTANT)
|
|
530
532
|
- While working, say only what you are doing and why, in ONE short sentence per step. No filler.
|
|
531
|
-
- Your FINAL answer
|
|
532
|
-
-
|
|
533
|
+
- Your FINAL answer has a HARD limit of 3 sentences. Join related points with commas into a single flowing sentence; never use bullet lists, numbered lists, or markdown headings unless the user explicitly asks. Plain prose only.
|
|
534
|
+
- State the outcome and, if you changed anything, the one command used to verify. Do NOT write document-style reports, inventories of the codebase, or repeat tool output. If the user wants more, they will ask.
|
|
535
|
+
- Never open with preamble such as "Here are", "I can", "Sure", or "Based on". Get straight to the point.
|
|
533
536
|
- Never dump the whole repo structure or a file-by-file summary unless requested.
|
|
534
537
|
- If the user refers to something you said or did earlier ("that", "it", "before"), use the prior conversation context provided above.
|
|
535
538
|
|
|
536
|
-
Be concise in your visible text between tool calls: one short sentence about what you are doing and why is enough.`;
|
|
539
|
+
Be concise in your visible text between tool calls: one short sentence about what you are doing and why is enough. Low token usage is a core goal \u2014 be terse everywhere.`;
|
|
537
540
|
}
|
|
538
541
|
var SKIP_DIRS;
|
|
539
542
|
var init_prompts = __esm({
|
|
@@ -981,6 +984,14 @@ var init_loop = __esm({
|
|
|
981
984
|
}
|
|
982
985
|
});
|
|
983
986
|
|
|
987
|
+
// package.json
|
|
988
|
+
var version;
|
|
989
|
+
var init_package = __esm({
|
|
990
|
+
"package.json"() {
|
|
991
|
+
version = "0.1.12";
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
|
|
984
995
|
// src/tui/markdown.tsx
|
|
985
996
|
import { Box, Text } from "ink";
|
|
986
997
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1068,7 +1079,7 @@ function AnswerBlock({ text }) {
|
|
|
1068
1079
|
{
|
|
1069
1080
|
flexDirection: "column",
|
|
1070
1081
|
borderStyle: "round",
|
|
1071
|
-
borderColor: "
|
|
1082
|
+
borderColor: "green",
|
|
1072
1083
|
paddingX: 1,
|
|
1073
1084
|
marginY: 0,
|
|
1074
1085
|
children: renderMarkdown(text)
|
|
@@ -1081,9 +1092,71 @@ var init_markdown = __esm({
|
|
|
1081
1092
|
}
|
|
1082
1093
|
});
|
|
1083
1094
|
|
|
1084
|
-
// src/tui/
|
|
1085
|
-
import { Box as Box2, Text as Text2
|
|
1095
|
+
// src/tui/diff.tsx
|
|
1096
|
+
import { Box as Box2, Text as Text2 } from "ink";
|
|
1086
1097
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1098
|
+
function compactChanges(oldStr, newStr) {
|
|
1099
|
+
const oldLines = oldStr.split(/\r?\n/);
|
|
1100
|
+
const newLines = newStr.split(/\r?\n/);
|
|
1101
|
+
let start = 0;
|
|
1102
|
+
const maxStart = Math.min(oldLines.length, newLines.length);
|
|
1103
|
+
while (start < maxStart && oldLines[start] === newLines[start]) start++;
|
|
1104
|
+
let endOld = oldLines.length;
|
|
1105
|
+
let endNew = newLines.length;
|
|
1106
|
+
while (endOld > start && endNew > start && oldLines[endOld - 1] === newLines[endNew - 1]) {
|
|
1107
|
+
endOld--;
|
|
1108
|
+
endNew--;
|
|
1109
|
+
}
|
|
1110
|
+
return {
|
|
1111
|
+
removed: oldLines.slice(start, endOld),
|
|
1112
|
+
added: newLines.slice(start, endNew)
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
function CurrentEditBox({ edit }) {
|
|
1116
|
+
if (!edit) return null;
|
|
1117
|
+
const c = compactChanges(edit.old, edit.new);
|
|
1118
|
+
const removed = c.removed.slice(0, MAX_LINES);
|
|
1119
|
+
const added = c.added.slice(0, MAX_LINES);
|
|
1120
|
+
const lines = [];
|
|
1121
|
+
let key = 0;
|
|
1122
|
+
for (const l of removed) {
|
|
1123
|
+
lines.push(
|
|
1124
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "redBright", color: "white", children: ` - ${l}` }, `r${key++}`)
|
|
1125
|
+
);
|
|
1126
|
+
}
|
|
1127
|
+
for (const l of added) {
|
|
1128
|
+
lines.push(
|
|
1129
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "greenBright", color: "black", children: ` + ${l}` }, `a${key++}`)
|
|
1130
|
+
);
|
|
1131
|
+
}
|
|
1132
|
+
return /* @__PURE__ */ jsxs2(
|
|
1133
|
+
Box2,
|
|
1134
|
+
{
|
|
1135
|
+
flexDirection: "column",
|
|
1136
|
+
marginTop: 1,
|
|
1137
|
+
borderStyle: "single",
|
|
1138
|
+
borderColor: "gray",
|
|
1139
|
+
borderLeft: false,
|
|
1140
|
+
borderRight: false,
|
|
1141
|
+
paddingX: 1,
|
|
1142
|
+
children: [
|
|
1143
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: "magenta", children: `\u270E ${edit.path}` }),
|
|
1144
|
+
lines.length > 0 ? lines : /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " (no text change)" })
|
|
1145
|
+
]
|
|
1146
|
+
}
|
|
1147
|
+
);
|
|
1148
|
+
}
|
|
1149
|
+
var MAX_LINES;
|
|
1150
|
+
var init_diff = __esm({
|
|
1151
|
+
"src/tui/diff.tsx"() {
|
|
1152
|
+
"use strict";
|
|
1153
|
+
MAX_LINES = 24;
|
|
1154
|
+
}
|
|
1155
|
+
});
|
|
1156
|
+
|
|
1157
|
+
// src/tui/Approval.tsx
|
|
1158
|
+
import { Box as Box3, Text as Text3, useInput } from "ink";
|
|
1159
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1087
1160
|
function argPreview(request) {
|
|
1088
1161
|
const args = request.args;
|
|
1089
1162
|
if (request.tool === "apply_patch" && typeof args.old_string === "string" && typeof args.new_string === "string") {
|
|
@@ -1101,8 +1174,8 @@ function ApprovalPrompt({ request, onDecision }) {
|
|
|
1101
1174
|
else if (input === "a") onDecision("always");
|
|
1102
1175
|
else if (input === "n" || key.escape) onDecision("deny");
|
|
1103
1176
|
});
|
|
1104
|
-
return /* @__PURE__ */
|
|
1105
|
-
/* @__PURE__ */
|
|
1177
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, marginY: 1, children: [
|
|
1178
|
+
/* @__PURE__ */ jsxs3(Text3, { bold: true, color: "magenta", children: [
|
|
1106
1179
|
"Permission needed: ",
|
|
1107
1180
|
friendlyToolName(request.tool),
|
|
1108
1181
|
" (",
|
|
@@ -1110,14 +1183,14 @@ function ApprovalPrompt({ request, onDecision }) {
|
|
|
1110
1183
|
") \u2014 ",
|
|
1111
1184
|
request.risk
|
|
1112
1185
|
] }),
|
|
1113
|
-
/* @__PURE__ */
|
|
1114
|
-
/* @__PURE__ */
|
|
1115
|
-
/* @__PURE__ */
|
|
1186
|
+
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text3, { children: argPreview(request) }) }),
|
|
1187
|
+
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1188
|
+
/* @__PURE__ */ jsx3(Text3, { color: "green", bold: true, children: "[y]" }),
|
|
1116
1189
|
" allow once \xB7 ",
|
|
1117
|
-
/* @__PURE__ */
|
|
1190
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", bold: true, children: "[a]" }),
|
|
1118
1191
|
" allow this session \xB7",
|
|
1119
1192
|
" ",
|
|
1120
|
-
/* @__PURE__ */
|
|
1193
|
+
/* @__PURE__ */ jsx3(Text3, { color: "red", bold: true, children: "[n]" }),
|
|
1121
1194
|
" deny"
|
|
1122
1195
|
] }) })
|
|
1123
1196
|
] });
|
|
@@ -1131,8 +1204,8 @@ var init_Approval = __esm({
|
|
|
1131
1204
|
|
|
1132
1205
|
// src/tui/SelectDialog.tsx
|
|
1133
1206
|
import { useEffect, useMemo, useState } from "react";
|
|
1134
|
-
import { Box as
|
|
1135
|
-
import { jsx as
|
|
1207
|
+
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
1208
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1136
1209
|
function SelectDialog({
|
|
1137
1210
|
title,
|
|
1138
1211
|
items,
|
|
@@ -1167,34 +1240,34 @@ function SelectDialog({
|
|
|
1167
1240
|
Math.min(cursor - Math.floor(VISIBLE / 2), Math.max(0, filtered.length - VISIBLE))
|
|
1168
1241
|
);
|
|
1169
1242
|
const visible = filtered.slice(start, start + VISIBLE);
|
|
1170
|
-
return /* @__PURE__ */
|
|
1171
|
-
/* @__PURE__ */
|
|
1172
|
-
/* @__PURE__ */
|
|
1173
|
-
/* @__PURE__ */
|
|
1243
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, marginY: 1, children: [
|
|
1244
|
+
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "cyan", children: title }),
|
|
1245
|
+
/* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
|
|
1246
|
+
/* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
|
|
1174
1247
|
"search: ",
|
|
1175
1248
|
filter
|
|
1176
1249
|
] }),
|
|
1177
|
-
/* @__PURE__ */
|
|
1250
|
+
/* @__PURE__ */ jsx4(Text4, { children: "\u258F" })
|
|
1178
1251
|
] }),
|
|
1179
|
-
loading ? /* @__PURE__ */
|
|
1180
|
-
error ? /* @__PURE__ */
|
|
1181
|
-
!loading && !error ? /* @__PURE__ */
|
|
1252
|
+
loading ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "loading\u2026" }) : null,
|
|
1253
|
+
error ? /* @__PURE__ */ jsx4(Text4, { color: "red", children: error }) : null,
|
|
1254
|
+
!loading && !error ? /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
1182
1255
|
visible.map((item, i) => {
|
|
1183
1256
|
const index = start + i;
|
|
1184
1257
|
const isCursor = index === cursor;
|
|
1185
1258
|
const isCurrent = item === current;
|
|
1186
1259
|
const description = descriptions?.[item];
|
|
1187
|
-
return /* @__PURE__ */
|
|
1260
|
+
return /* @__PURE__ */ jsxs4(Text4, { color: isCursor ? "cyan" : void 0, bold: isCursor, children: [
|
|
1188
1261
|
isCursor ? "\u276F " : " ",
|
|
1189
1262
|
isCurrent ? "\u25CF " : "\u25CB ",
|
|
1190
1263
|
item,
|
|
1191
1264
|
isCurrent ? " (current)" : "",
|
|
1192
|
-
description ? /* @__PURE__ */
|
|
1265
|
+
description ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: ` \u2014 ${description}` }) : null
|
|
1193
1266
|
] }, item);
|
|
1194
1267
|
}),
|
|
1195
|
-
filtered.length === 0 ? /* @__PURE__ */
|
|
1268
|
+
filtered.length === 0 ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "no matches" }) : null
|
|
1196
1269
|
] }) : null,
|
|
1197
|
-
/* @__PURE__ */
|
|
1270
|
+
/* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "\u2191\u2193 move \xB7 type to filter \xB7 enter select \xB7 esc cancel" }) })
|
|
1198
1271
|
] });
|
|
1199
1272
|
}
|
|
1200
1273
|
var VISIBLE;
|
|
@@ -1207,22 +1280,22 @@ var init_SelectDialog = __esm({
|
|
|
1207
1280
|
|
|
1208
1281
|
// src/tui/KeyDialog.tsx
|
|
1209
1282
|
import { useState as useState2 } from "react";
|
|
1210
|
-
import { Box as
|
|
1283
|
+
import { Box as Box5, Text as Text5, useInput as useInput3 } from "ink";
|
|
1211
1284
|
import TextInput from "ink-text-input";
|
|
1212
|
-
import { jsx as
|
|
1285
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1213
1286
|
function KeyDialog({ providerName, onSubmit, onClose }) {
|
|
1214
1287
|
const [value, setValue] = useState2("");
|
|
1215
1288
|
useInput3((_input, key) => {
|
|
1216
1289
|
if (key.escape) onClose();
|
|
1217
1290
|
});
|
|
1218
|
-
return /* @__PURE__ */
|
|
1219
|
-
/* @__PURE__ */
|
|
1291
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, marginY: 1, children: [
|
|
1292
|
+
/* @__PURE__ */ jsxs5(Text5, { bold: true, color: "magenta", children: [
|
|
1220
1293
|
"API key for ",
|
|
1221
1294
|
providerName
|
|
1222
1295
|
] }),
|
|
1223
|
-
/* @__PURE__ */
|
|
1224
|
-
/* @__PURE__ */
|
|
1225
|
-
/* @__PURE__ */
|
|
1296
|
+
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
|
|
1297
|
+
/* @__PURE__ */ jsx5(Text5, { children: "key: " }),
|
|
1298
|
+
/* @__PURE__ */ jsx5(
|
|
1226
1299
|
TextInput,
|
|
1227
1300
|
{
|
|
1228
1301
|
mask: "*",
|
|
@@ -1235,7 +1308,7 @@ function KeyDialog({ providerName, onSubmit, onClose }) {
|
|
|
1235
1308
|
}
|
|
1236
1309
|
)
|
|
1237
1310
|
] }),
|
|
1238
|
-
/* @__PURE__ */
|
|
1311
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "enter confirm \xB7 esc cancel \xB7 saved to ~/.mentee/config.json" }) })
|
|
1239
1312
|
] });
|
|
1240
1313
|
}
|
|
1241
1314
|
var init_KeyDialog = __esm({
|
|
@@ -1244,23 +1317,15 @@ var init_KeyDialog = __esm({
|
|
|
1244
1317
|
}
|
|
1245
1318
|
});
|
|
1246
1319
|
|
|
1247
|
-
// package.json
|
|
1248
|
-
var version;
|
|
1249
|
-
var init_package = __esm({
|
|
1250
|
-
"package.json"() {
|
|
1251
|
-
version = "0.1.10";
|
|
1252
|
-
}
|
|
1253
|
-
});
|
|
1254
|
-
|
|
1255
1320
|
// src/tui/App.tsx
|
|
1256
1321
|
var App_exports = {};
|
|
1257
1322
|
__export(App_exports, {
|
|
1258
1323
|
App: () => App
|
|
1259
1324
|
});
|
|
1260
1325
|
import { useEffect as useEffect2, useMemo as useMemo2, useRef, useState as useState3 } from "react";
|
|
1261
|
-
import { Box as
|
|
1326
|
+
import { Box as Box6, Static, Text as Text6, useApp, useInput as useInput4, useStdout } from "ink";
|
|
1262
1327
|
import TextInput2 from "ink-text-input";
|
|
1263
|
-
import { jsx as
|
|
1328
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1264
1329
|
function App(props) {
|
|
1265
1330
|
const { exit } = useApp();
|
|
1266
1331
|
const { stdout } = useStdout();
|
|
@@ -1288,6 +1353,7 @@ function App(props) {
|
|
|
1288
1353
|
const [detailsOpen, setDetailsOpen] = useState3(false);
|
|
1289
1354
|
const [showDetails, setShowDetails] = useState3(false);
|
|
1290
1355
|
const [thinkingText, setThinkingText] = useState3("");
|
|
1356
|
+
const [currentEdit, setCurrentEdit] = useState3(null);
|
|
1291
1357
|
const finalTextRef = useRef(null);
|
|
1292
1358
|
const pendingTool = useRef(null);
|
|
1293
1359
|
const counter = useRef(0);
|
|
@@ -1311,6 +1377,13 @@ function App(props) {
|
|
|
1311
1377
|
if (event.type === "model_request" || event.type === "task_completed") {
|
|
1312
1378
|
setThinkingText("");
|
|
1313
1379
|
}
|
|
1380
|
+
if (event.type === "patch") {
|
|
1381
|
+
const filePath = typeof event.data?.path === "string" ? event.data.path : "file";
|
|
1382
|
+
const oldStr = typeof event.data?.old_string === "string" ? event.data.old_string : "";
|
|
1383
|
+
const newStr = typeof event.data?.new_string === "string" ? event.data.new_string : "";
|
|
1384
|
+
setCurrentEdit({ path: filePath, old: oldStr, new: newStr });
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1314
1387
|
appendLog(formatEvent(event), TOOL_NOISE.has(event.type));
|
|
1315
1388
|
if (event.type === "tool_started") {
|
|
1316
1389
|
const name = typeof event.data?.tool === "string" ? event.data.tool : "";
|
|
@@ -1518,8 +1591,8 @@ function App(props) {
|
|
|
1518
1591
|
setToolHistory([]);
|
|
1519
1592
|
setInspectorIndex(null);
|
|
1520
1593
|
setDetailsOpen(false);
|
|
1521
|
-
setShowDetails(false);
|
|
1522
1594
|
setRunning(true);
|
|
1595
|
+
setCurrentEdit(null);
|
|
1523
1596
|
const ac = new AbortController();
|
|
1524
1597
|
abortRef.current = ac;
|
|
1525
1598
|
try {
|
|
@@ -1591,9 +1664,9 @@ function App(props) {
|
|
|
1591
1664
|
else if (key.ctrl && input === "k") setDialog({ kind: "key" });
|
|
1592
1665
|
});
|
|
1593
1666
|
const modelLabel = model ?? factoryResult.provider?.defaultModel ?? (factoryResult.error ? "no key" : "");
|
|
1594
|
-
const header = /* @__PURE__ */
|
|
1595
|
-
/* @__PURE__ */
|
|
1596
|
-
/* @__PURE__ */
|
|
1667
|
+
const header = /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginBottom: 1, children: [
|
|
1668
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: BANNER }),
|
|
1669
|
+
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1597
1670
|
"v",
|
|
1598
1671
|
version,
|
|
1599
1672
|
" \xB7 ",
|
|
@@ -1604,44 +1677,45 @@ function App(props) {
|
|
|
1604
1677
|
" \xB7 ",
|
|
1605
1678
|
props.cwd
|
|
1606
1679
|
] }),
|
|
1607
|
-
/* @__PURE__ */
|
|
1680
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Alt+M model \xB7 Ctrl+P provider \xB7 Ctrl+K key \xB7 Alt+D details \xB7 /help" })
|
|
1608
1681
|
] }, "header");
|
|
1609
1682
|
const cols = stdout.columns || 80;
|
|
1610
1683
|
const marquee = thinkingText.slice(-Math.max(1, cols - 4));
|
|
1611
|
-
return /* @__PURE__ */
|
|
1612
|
-
/* @__PURE__ */
|
|
1613
|
-
/* @__PURE__ */
|
|
1684
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1685
|
+
/* @__PURE__ */ jsx6(Static, { items: [{ key: "header", text: header }], children: (item) => /* @__PURE__ */ jsx6(Box6, { children: item.text }, item.key) }),
|
|
1686
|
+
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1614
1687
|
log.filter((l) => showDetails || !l.noise).map(
|
|
1615
|
-
(line) => line.kind === "answer" ? /* @__PURE__ */
|
|
1688
|
+
(line) => line.kind === "answer" ? /* @__PURE__ */ jsx6(AnswerBlock, { text: line.text }, line.id) : /* @__PURE__ */ jsx6(Text6, { children: line.text }, line.id)
|
|
1616
1689
|
),
|
|
1617
|
-
finalPending !== null ? /* @__PURE__ */
|
|
1618
|
-
|
|
1619
|
-
typing ?
|
|
1620
|
-
] }) : null,
|
|
1690
|
+
finalPending !== null ? /* @__PURE__ */ jsx6(Box6, { marginTop: 1, flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, children: /* @__PURE__ */ jsxs6(Text6, { color: "green", children: [
|
|
1691
|
+
typedText,
|
|
1692
|
+
typing ? "\u258C" : ""
|
|
1693
|
+
] }) }) : null,
|
|
1694
|
+
/* @__PURE__ */ jsx6(CurrentEditBox, { edit: currentEdit }),
|
|
1621
1695
|
detailsOpen && inspectorIndex !== null && toolHistory[inspectorIndex] ? (() => {
|
|
1622
1696
|
const rec = toolHistory[inspectorIndex];
|
|
1623
1697
|
const outLines = rec.output.split("\n").slice(0, 24).join("\n");
|
|
1624
|
-
return /* @__PURE__ */
|
|
1625
|
-
/* @__PURE__ */
|
|
1698
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: [
|
|
1699
|
+
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1626
1700
|
" tool details (",
|
|
1627
1701
|
inspectorIndex + 1,
|
|
1628
1702
|
"/",
|
|
1629
1703
|
toolHistory.length,
|
|
1630
|
-
") \xB7
|
|
1704
|
+
") \xB7 Alt+D to cycle "
|
|
1631
1705
|
] }),
|
|
1632
|
-
/* @__PURE__ */
|
|
1706
|
+
/* @__PURE__ */ jsxs6(Text6, { color: toolColorName(rec.name), bold: true, children: [
|
|
1633
1707
|
rec.name,
|
|
1634
1708
|
" ",
|
|
1635
1709
|
rec.target
|
|
1636
1710
|
] }),
|
|
1637
|
-
/* @__PURE__ */
|
|
1711
|
+
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1638
1712
|
"args: ",
|
|
1639
1713
|
rec.args.slice(0, 400) || "(none)"
|
|
1640
1714
|
] }),
|
|
1641
|
-
/* @__PURE__ */
|
|
1715
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: outLines || "(no output)" })
|
|
1642
1716
|
] });
|
|
1643
1717
|
})() : null,
|
|
1644
|
-
dialog?.kind === "model" ? /* @__PURE__ */
|
|
1718
|
+
dialog?.kind === "model" ? /* @__PURE__ */ jsx6(
|
|
1645
1719
|
SelectDialog,
|
|
1646
1720
|
{
|
|
1647
1721
|
title: `Model \u2014 ${providerName}`,
|
|
@@ -1655,7 +1729,7 @@ function App(props) {
|
|
|
1655
1729
|
},
|
|
1656
1730
|
onClose: () => setDialog(null)
|
|
1657
1731
|
}
|
|
1658
|
-
) : dialog?.kind === "provider" ? /* @__PURE__ */
|
|
1732
|
+
) : dialog?.kind === "provider" ? /* @__PURE__ */ jsx6(
|
|
1659
1733
|
SelectDialog,
|
|
1660
1734
|
{
|
|
1661
1735
|
title: "Provider",
|
|
@@ -1668,7 +1742,7 @@ function App(props) {
|
|
|
1668
1742
|
},
|
|
1669
1743
|
onClose: () => setDialog(null)
|
|
1670
1744
|
}
|
|
1671
|
-
) : dialog?.kind === "key" ? /* @__PURE__ */
|
|
1745
|
+
) : dialog?.kind === "key" ? /* @__PURE__ */ jsx6(
|
|
1672
1746
|
KeyDialog,
|
|
1673
1747
|
{
|
|
1674
1748
|
providerName,
|
|
@@ -1678,7 +1752,7 @@ function App(props) {
|
|
|
1678
1752
|
},
|
|
1679
1753
|
onClose: () => setDialog(null)
|
|
1680
1754
|
}
|
|
1681
|
-
) : approval ? /* @__PURE__ */
|
|
1755
|
+
) : approval ? /* @__PURE__ */ jsx6(
|
|
1682
1756
|
ApprovalPrompt,
|
|
1683
1757
|
{
|
|
1684
1758
|
request: approval,
|
|
@@ -1687,22 +1761,22 @@ function App(props) {
|
|
|
1687
1761
|
if (decision === "always") bus.emit("info", "Approved for the rest of this session.");
|
|
1688
1762
|
}
|
|
1689
1763
|
}
|
|
1690
|
-
) : running ? /* @__PURE__ */
|
|
1691
|
-
/* @__PURE__ */
|
|
1692
|
-
/* @__PURE__ */
|
|
1764
|
+
) : running ? /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1765
|
+
/* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1766
|
+
/* @__PURE__ */ jsxs6(Text6, { color: "yellow", children: [
|
|
1693
1767
|
SPINNER_FRAMES[frame],
|
|
1694
1768
|
" "
|
|
1695
1769
|
] }),
|
|
1696
|
-
/* @__PURE__ */
|
|
1770
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "agent working... (Ctrl+C to exit)" })
|
|
1697
1771
|
] }),
|
|
1698
|
-
thinkingText ? /* @__PURE__ */
|
|
1699
|
-
/* @__PURE__ */
|
|
1700
|
-
/* @__PURE__ */
|
|
1701
|
-
/* @__PURE__ */
|
|
1772
|
+
thinkingText ? /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1773
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "\u{1F4AD} " }),
|
|
1774
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", dimColor: true, children: marquee }),
|
|
1775
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "\u258C" })
|
|
1702
1776
|
] }) : null
|
|
1703
|
-
] }) : /* @__PURE__ */
|
|
1704
|
-
/* @__PURE__ */
|
|
1705
|
-
/* @__PURE__ */
|
|
1777
|
+
] }) : /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1778
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", bold: true, children: "\u25B8 " }),
|
|
1779
|
+
/* @__PURE__ */ jsx6(
|
|
1706
1780
|
TextInput2,
|
|
1707
1781
|
{
|
|
1708
1782
|
value: taskInput,
|
|
@@ -1723,6 +1797,7 @@ var init_App = __esm({
|
|
|
1723
1797
|
init_logging();
|
|
1724
1798
|
init_render();
|
|
1725
1799
|
init_markdown();
|
|
1800
|
+
init_diff();
|
|
1726
1801
|
init_approval();
|
|
1727
1802
|
init_loop();
|
|
1728
1803
|
init_conversation();
|
|
@@ -1733,12 +1808,14 @@ var init_App = __esm({
|
|
|
1733
1808
|
init_KeyDialog();
|
|
1734
1809
|
init_package();
|
|
1735
1810
|
SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
1736
|
-
PROVIDER_NAMES = ["kimi", "glm", "zai", "zai-coding", "mock"];
|
|
1811
|
+
PROVIDER_NAMES = ["kimi", "glm", "zai", "zai-coding", "openrouter", "nvidia", "mock"];
|
|
1737
1812
|
PROVIDER_DESCRIPTIONS = {
|
|
1738
1813
|
kimi: "Moonshot \xB7 api.moonshot.ai",
|
|
1739
1814
|
glm: "Zhipu China \xB7 open.bigmodel.cn \xB7 separate account & keys",
|
|
1740
1815
|
zai: "Z.ai standard plan \xB7 api.z.ai/api/paas/v4",
|
|
1741
1816
|
"zai-coding": "Z.ai GLM Coding Plan subscription \xB7 api.z.ai/api/coding",
|
|
1817
|
+
openrouter: "OpenRouter \xB7 100+ models via one key (Claude, GPT, Llama\u2026)",
|
|
1818
|
+
nvidia: "NVIDIA NIM \xB7 build.nvidia.com hosted models",
|
|
1742
1819
|
mock: "offline testing \xB7 no network"
|
|
1743
1820
|
};
|
|
1744
1821
|
BANNER = ` __ __ \u{1F380}
|
|
@@ -1823,14 +1900,14 @@ var OpenAICompatProvider = class {
|
|
|
1823
1900
|
...request.maxTokens ? { max_tokens: request.maxTokens } : {}
|
|
1824
1901
|
};
|
|
1825
1902
|
if (!request.onToken) {
|
|
1826
|
-
const
|
|
1827
|
-
return parseResponse(
|
|
1903
|
+
const response2 = await this.client.chat.completions.create(baseParams);
|
|
1904
|
+
return parseResponse(response2);
|
|
1828
1905
|
}
|
|
1829
|
-
|
|
1906
|
+
const streamOnce = async (withUsage) => {
|
|
1830
1907
|
const stream = await this.client.chat.completions.create({
|
|
1831
1908
|
...baseParams,
|
|
1832
1909
|
stream: true,
|
|
1833
|
-
stream_options: { include_usage: true }
|
|
1910
|
+
...withUsage ? { stream_options: { include_usage: true } } : {}
|
|
1834
1911
|
});
|
|
1835
1912
|
let content = "";
|
|
1836
1913
|
let finishReason = "stop";
|
|
@@ -1841,7 +1918,7 @@ var OpenAICompatProvider = class {
|
|
|
1841
1918
|
const delta = choice?.delta;
|
|
1842
1919
|
if (delta?.content) {
|
|
1843
1920
|
content += delta.content;
|
|
1844
|
-
request.onToken(delta.content);
|
|
1921
|
+
request.onToken?.(delta.content);
|
|
1845
1922
|
}
|
|
1846
1923
|
if (delta?.tool_calls) {
|
|
1847
1924
|
for (const tc of delta.tool_calls) {
|
|
@@ -1875,10 +1952,21 @@ var OpenAICompatProvider = class {
|
|
|
1875
1952
|
finishReason: mapFinishReason(finishReason),
|
|
1876
1953
|
usage
|
|
1877
1954
|
};
|
|
1878
|
-
}
|
|
1879
|
-
|
|
1880
|
-
|
|
1955
|
+
};
|
|
1956
|
+
for (const withUsage of [true, false]) {
|
|
1957
|
+
try {
|
|
1958
|
+
return await streamOnce(withUsage);
|
|
1959
|
+
} catch {
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
const response = await this.client.chat.completions.create(baseParams);
|
|
1963
|
+
const parsed = parseResponse(response);
|
|
1964
|
+
if (parsed.content) {
|
|
1965
|
+
for (let i = 0; i < parsed.content.length; i += 3) {
|
|
1966
|
+
request.onToken?.(parsed.content.slice(i, i + 3));
|
|
1967
|
+
}
|
|
1881
1968
|
}
|
|
1969
|
+
return parsed;
|
|
1882
1970
|
}
|
|
1883
1971
|
async listModels() {
|
|
1884
1972
|
const page = await this.client.models.list();
|
|
@@ -1910,6 +1998,16 @@ function createKimiProvider(apiKey, model) {
|
|
|
1910
1998
|
});
|
|
1911
1999
|
}
|
|
1912
2000
|
|
|
2001
|
+
// src/models/nvidia.ts
|
|
2002
|
+
function createNvidiaProvider(apiKey, model) {
|
|
2003
|
+
return new OpenAICompatProvider({
|
|
2004
|
+
name: "nvidia",
|
|
2005
|
+
defaultModel: model ?? "nvidia/llama-3.1-nemotron-70b-instruct",
|
|
2006
|
+
baseURL: "https://integrate.api.nvidia.com/v1",
|
|
2007
|
+
apiKey
|
|
2008
|
+
});
|
|
2009
|
+
}
|
|
2010
|
+
|
|
1913
2011
|
// src/models/mock.ts
|
|
1914
2012
|
var callCounter = 0;
|
|
1915
2013
|
var MockProvider = class {
|
|
@@ -1946,6 +2044,16 @@ var MockProvider = class {
|
|
|
1946
2044
|
}
|
|
1947
2045
|
};
|
|
1948
2046
|
|
|
2047
|
+
// src/models/openrouter.ts
|
|
2048
|
+
function createOpenRouterProvider(apiKey, model) {
|
|
2049
|
+
return new OpenAICompatProvider({
|
|
2050
|
+
name: "openrouter",
|
|
2051
|
+
defaultModel: model ?? "anthropic/claude-3.5-sonnet",
|
|
2052
|
+
baseURL: "https://openrouter.ai/api/v1",
|
|
2053
|
+
apiKey
|
|
2054
|
+
});
|
|
2055
|
+
}
|
|
2056
|
+
|
|
1949
2057
|
// src/models/zai.ts
|
|
1950
2058
|
function createZaiProvider(apiKey, model) {
|
|
1951
2059
|
return new OpenAICompatProvider({
|
|
@@ -1969,7 +2077,9 @@ var ENV_NAMES2 = {
|
|
|
1969
2077
|
kimi: "MENTEE_KIMI_API_KEY",
|
|
1970
2078
|
glm: "MENTEE_GLM_API_KEY",
|
|
1971
2079
|
zai: "MENTEE_ZAI_API_KEY",
|
|
1972
|
-
"zai-coding": "MENTEE_ZAI_API_KEY"
|
|
2080
|
+
"zai-coding": "MENTEE_ZAI_API_KEY",
|
|
2081
|
+
openrouter: "MENTEE_OPENROUTER_API_KEY",
|
|
2082
|
+
nvidia: "MENTEE_NVIDIA_API_KEY"
|
|
1973
2083
|
};
|
|
1974
2084
|
var MissingApiKeyError = class extends Error {
|
|
1975
2085
|
constructor(provider) {
|
|
@@ -1997,6 +2107,12 @@ function createProvider(provider, config, modelOverride) {
|
|
|
1997
2107
|
if (provider === "zai-coding") {
|
|
1998
2108
|
return createZaiCodingProvider(apiKey, model);
|
|
1999
2109
|
}
|
|
2110
|
+
if (provider === "openrouter") {
|
|
2111
|
+
return createOpenRouterProvider(apiKey, model);
|
|
2112
|
+
}
|
|
2113
|
+
if (provider === "nvidia") {
|
|
2114
|
+
return createNvidiaProvider(apiKey, model);
|
|
2115
|
+
}
|
|
2000
2116
|
return createGlmProvider(apiKey, model);
|
|
2001
2117
|
}
|
|
2002
2118
|
|
|
@@ -3413,12 +3529,12 @@ async function runConfigWizard() {
|
|
|
3413
3529
|
const config = loadConfig() ?? blankConfig();
|
|
3414
3530
|
config.keys = config.keys ?? {};
|
|
3415
3531
|
config.models = config.models ?? {};
|
|
3416
|
-
console.log("Providers: 1) Kimi (Moonshot) 2) GLM (Zhipu CN) 3) Z.ai (GLM international)");
|
|
3417
|
-
const defaultChoice = config.defaultProvider === "glm" ? "2" : config.defaultProvider === "zai" ? "3" : "1";
|
|
3532
|
+
console.log("Providers: 1) Kimi (Moonshot) 2) GLM (Zhipu CN) 3) Z.ai (GLM international) 4) OpenRouter 5) NVIDIA NIM");
|
|
3533
|
+
const defaultChoice = config.defaultProvider === "glm" ? "2" : config.defaultProvider === "zai" ? "3" : config.defaultProvider === "openrouter" ? "4" : config.defaultProvider === "nvidia" ? "5" : "1";
|
|
3418
3534
|
const providerChoice = await ask(rl, "Default provider [1]", defaultChoice);
|
|
3419
|
-
const provider = providerChoice === "2" ? "glm" : providerChoice === "3" ? "zai" : "kimi";
|
|
3535
|
+
const provider = providerChoice === "2" ? "glm" : providerChoice === "3" ? "zai" : providerChoice === "4" ? "openrouter" : providerChoice === "5" ? "nvidia" : "kimi";
|
|
3420
3536
|
config.defaultProvider = provider;
|
|
3421
|
-
const defaultModel = provider === "kimi" ? "kimi-k2.7-code" : "glm-4.6";
|
|
3537
|
+
const defaultModel = provider === "kimi" ? "kimi-k2.7-code" : provider === "openrouter" ? "anthropic/claude-3.5-sonnet" : provider === "nvidia" ? "nvidia/llama-3.1-nemotron-70b-instruct" : "glm-4.6";
|
|
3422
3538
|
const key = await ask(rl, `API key for ${provider}`);
|
|
3423
3539
|
if (key) config.keys[provider] = key;
|
|
3424
3540
|
const model = await ask(rl, `Model for ${provider}`, defaultModel);
|
|
@@ -3430,7 +3546,7 @@ Saved to ${configFilePath()}
|
|
|
3430
3546
|
if (config.keys[provider]) {
|
|
3431
3547
|
console.log("Testing connection...");
|
|
3432
3548
|
try {
|
|
3433
|
-
const providerInstance = provider === "kimi" ? createKimiProvider(config.keys[provider], model) : provider === "zai" ? createZaiProvider(config.keys[provider], model) : createGlmProvider(config.keys[provider], model);
|
|
3549
|
+
const providerInstance = provider === "kimi" ? createKimiProvider(config.keys[provider], model) : provider === "zai" ? createZaiProvider(config.keys[provider], model) : provider === "openrouter" ? createOpenRouterProvider(config.keys[provider], model) : provider === "nvidia" ? createNvidiaProvider(config.keys[provider], model) : createGlmProvider(config.keys[provider], model);
|
|
3434
3550
|
await providerInstance.generate(
|
|
3435
3551
|
{
|
|
3436
3552
|
system: "You are a ping endpoint.",
|
|
@@ -3457,20 +3573,20 @@ Saved to ${configFilePath()}
|
|
|
3457
3573
|
}
|
|
3458
3574
|
|
|
3459
3575
|
// src/cli.tsx
|
|
3576
|
+
init_package();
|
|
3460
3577
|
import path9 from "path";
|
|
3461
|
-
import { jsx as
|
|
3462
|
-
var packageJson = { version: "0.1.0" };
|
|
3578
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
3463
3579
|
var program = new Command();
|
|
3464
|
-
program.name("mentee").description("MenteE SWE \u2014 an autonomous SWE agent in your terminal. Bring your own model: Kimi, GLM, and more.").version(
|
|
3580
|
+
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);
|
|
3465
3581
|
program.command("config").description("Configure providers, API keys, and models (interactive wizard)").action(async () => {
|
|
3466
3582
|
await runConfigWizard();
|
|
3467
3583
|
});
|
|
3468
|
-
program.argument("[task...]", "the software task to perform (omit to type it interactively)").option("-p, --provider <name>", "model provider: kimi | glm | mock").option("-m, --model <id>", "model id override for the chosen provider").option("-y, --yes", "auto-approve restricted actions (installs, git history changes)").option("--no-tui", "run in plain text mode instead of the interactive UI").option("--max-iterations <n>", "maximum agent iterations", "40").action(async (taskParts, options) => {
|
|
3584
|
+
program.argument("[task...]", "the software task to perform (omit to type it interactively)").option("-p, --provider <name>", "model provider: kimi | glm | zai | zai-coding | openrouter | nvidia | mock").option("-m, --model <id>", "model id override for the chosen provider").option("-y, --yes", "auto-approve restricted actions (installs, git history changes)").option("--no-tui", "run in plain text mode instead of the interactive UI").option("--max-iterations <n>", "maximum agent iterations", "40").action(async (taskParts, options) => {
|
|
3469
3585
|
const task = taskParts.join(" ").trim();
|
|
3470
3586
|
const config = loadConfig();
|
|
3471
3587
|
const providerName = options.provider ?? config?.defaultProvider ?? "zai-coding";
|
|
3472
|
-
if (!["kimi", "glm", "zai", "zai-coding", "mock"].includes(providerName)) {
|
|
3473
|
-
console.error(chalk4.red(`Unknown provider "${providerName}". Use kimi, glm, zai, zai-coding, or mock.`));
|
|
3588
|
+
if (!["kimi", "glm", "zai", "zai-coding", "openrouter", "nvidia", "mock"].includes(providerName)) {
|
|
3589
|
+
console.error(chalk4.red(`Unknown provider "${providerName}". Use kimi, glm, zai, zai-coding, openrouter, nvidia, or mock.`));
|
|
3474
3590
|
process.exit(1);
|
|
3475
3591
|
}
|
|
3476
3592
|
const tools = new ToolRegistry(createDefaultTools());
|
|
@@ -3515,7 +3631,7 @@ program.argument("[task...]", "the software task to perform (omit to type it int
|
|
|
3515
3631
|
const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
|
|
3516
3632
|
const { render } = await import("ink");
|
|
3517
3633
|
const { waitUntilExit } = render(
|
|
3518
|
-
/* @__PURE__ */
|
|
3634
|
+
/* @__PURE__ */ jsx7(
|
|
3519
3635
|
App2,
|
|
3520
3636
|
{
|
|
3521
3637
|
initialTask: task || void 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@menteeai/menteeswe",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
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",
|