@menteeai/menteeswe 0.1.10 → 0.1.11
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 +217 -94
- 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.11";
|
|
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,85 @@ 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 FileDiffView({ diffs }) {
|
|
1116
|
+
const files = Object.entries(diffs);
|
|
1117
|
+
if (files.length === 0) return null;
|
|
1118
|
+
const blocks = [];
|
|
1119
|
+
let key = 0;
|
|
1120
|
+
let lineBudget = MAX_LINES;
|
|
1121
|
+
const shown = files.slice(0, MAX_FILES);
|
|
1122
|
+
shown.forEach(([file, edits], fi) => {
|
|
1123
|
+
let removedTotal = 0;
|
|
1124
|
+
let addedTotal = 0;
|
|
1125
|
+
const lines = [];
|
|
1126
|
+
for (const edit of edits) {
|
|
1127
|
+
const c = compactChanges(edit.old, edit.new);
|
|
1128
|
+
removedTotal += c.removed.length;
|
|
1129
|
+
addedTotal += c.added.length;
|
|
1130
|
+
if (lineBudget > 0) {
|
|
1131
|
+
for (const l of c.removed) {
|
|
1132
|
+
if (lineBudget <= 0) break;
|
|
1133
|
+
lines.push(
|
|
1134
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "redBright", color: "white", children: ` - ${l}` }, `r${key++}`)
|
|
1135
|
+
);
|
|
1136
|
+
lineBudget--;
|
|
1137
|
+
}
|
|
1138
|
+
for (const l of c.added) {
|
|
1139
|
+
if (lineBudget <= 0) break;
|
|
1140
|
+
lines.push(
|
|
1141
|
+
/* @__PURE__ */ jsx2(Text2, { backgroundColor: "greenBright", color: "black", children: ` + ${l}` }, `a${key++}`)
|
|
1142
|
+
);
|
|
1143
|
+
lineBudget--;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
blocks.push(
|
|
1148
|
+
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginTop: 1, children: [
|
|
1149
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: "magenta", children: `\u270E ${file}` }),
|
|
1150
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: ` ${edits.length} edit(s) \xB7 +${addedTotal} / -${removedTotal}` }),
|
|
1151
|
+
lines
|
|
1152
|
+
] }, `f${fi}`)
|
|
1153
|
+
);
|
|
1154
|
+
});
|
|
1155
|
+
if (files.length > MAX_FILES) {
|
|
1156
|
+
blocks.push(
|
|
1157
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: ` \u2026 and ${files.length - MAX_FILES} more file(s)` }, "more")
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: blocks });
|
|
1161
|
+
}
|
|
1162
|
+
var MAX_FILES, MAX_LINES;
|
|
1163
|
+
var init_diff = __esm({
|
|
1164
|
+
"src/tui/diff.tsx"() {
|
|
1165
|
+
"use strict";
|
|
1166
|
+
MAX_FILES = 12;
|
|
1167
|
+
MAX_LINES = 160;
|
|
1168
|
+
}
|
|
1169
|
+
});
|
|
1170
|
+
|
|
1171
|
+
// src/tui/Approval.tsx
|
|
1172
|
+
import { Box as Box3, Text as Text3, useInput } from "ink";
|
|
1173
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1087
1174
|
function argPreview(request) {
|
|
1088
1175
|
const args = request.args;
|
|
1089
1176
|
if (request.tool === "apply_patch" && typeof args.old_string === "string" && typeof args.new_string === "string") {
|
|
@@ -1101,8 +1188,8 @@ function ApprovalPrompt({ request, onDecision }) {
|
|
|
1101
1188
|
else if (input === "a") onDecision("always");
|
|
1102
1189
|
else if (input === "n" || key.escape) onDecision("deny");
|
|
1103
1190
|
});
|
|
1104
|
-
return /* @__PURE__ */
|
|
1105
|
-
/* @__PURE__ */
|
|
1191
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, marginY: 1, children: [
|
|
1192
|
+
/* @__PURE__ */ jsxs3(Text3, { bold: true, color: "magenta", children: [
|
|
1106
1193
|
"Permission needed: ",
|
|
1107
1194
|
friendlyToolName(request.tool),
|
|
1108
1195
|
" (",
|
|
@@ -1110,14 +1197,14 @@ function ApprovalPrompt({ request, onDecision }) {
|
|
|
1110
1197
|
") \u2014 ",
|
|
1111
1198
|
request.risk
|
|
1112
1199
|
] }),
|
|
1113
|
-
/* @__PURE__ */
|
|
1114
|
-
/* @__PURE__ */
|
|
1115
|
-
/* @__PURE__ */
|
|
1200
|
+
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text3, { children: argPreview(request) }) }),
|
|
1201
|
+
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsxs3(Text3, { children: [
|
|
1202
|
+
/* @__PURE__ */ jsx3(Text3, { color: "green", bold: true, children: "[y]" }),
|
|
1116
1203
|
" allow once \xB7 ",
|
|
1117
|
-
/* @__PURE__ */
|
|
1204
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", bold: true, children: "[a]" }),
|
|
1118
1205
|
" allow this session \xB7",
|
|
1119
1206
|
" ",
|
|
1120
|
-
/* @__PURE__ */
|
|
1207
|
+
/* @__PURE__ */ jsx3(Text3, { color: "red", bold: true, children: "[n]" }),
|
|
1121
1208
|
" deny"
|
|
1122
1209
|
] }) })
|
|
1123
1210
|
] });
|
|
@@ -1131,8 +1218,8 @@ var init_Approval = __esm({
|
|
|
1131
1218
|
|
|
1132
1219
|
// src/tui/SelectDialog.tsx
|
|
1133
1220
|
import { useEffect, useMemo, useState } from "react";
|
|
1134
|
-
import { Box as
|
|
1135
|
-
import { jsx as
|
|
1221
|
+
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
1222
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1136
1223
|
function SelectDialog({
|
|
1137
1224
|
title,
|
|
1138
1225
|
items,
|
|
@@ -1167,34 +1254,34 @@ function SelectDialog({
|
|
|
1167
1254
|
Math.min(cursor - Math.floor(VISIBLE / 2), Math.max(0, filtered.length - VISIBLE))
|
|
1168
1255
|
);
|
|
1169
1256
|
const visible = filtered.slice(start, start + VISIBLE);
|
|
1170
|
-
return /* @__PURE__ */
|
|
1171
|
-
/* @__PURE__ */
|
|
1172
|
-
/* @__PURE__ */
|
|
1173
|
-
/* @__PURE__ */
|
|
1257
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, marginY: 1, children: [
|
|
1258
|
+
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "cyan", children: title }),
|
|
1259
|
+
/* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
|
|
1260
|
+
/* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
|
|
1174
1261
|
"search: ",
|
|
1175
1262
|
filter
|
|
1176
1263
|
] }),
|
|
1177
|
-
/* @__PURE__ */
|
|
1264
|
+
/* @__PURE__ */ jsx4(Text4, { children: "\u258F" })
|
|
1178
1265
|
] }),
|
|
1179
|
-
loading ? /* @__PURE__ */
|
|
1180
|
-
error ? /* @__PURE__ */
|
|
1181
|
-
!loading && !error ? /* @__PURE__ */
|
|
1266
|
+
loading ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "loading\u2026" }) : null,
|
|
1267
|
+
error ? /* @__PURE__ */ jsx4(Text4, { color: "red", children: error }) : null,
|
|
1268
|
+
!loading && !error ? /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
1182
1269
|
visible.map((item, i) => {
|
|
1183
1270
|
const index = start + i;
|
|
1184
1271
|
const isCursor = index === cursor;
|
|
1185
1272
|
const isCurrent = item === current;
|
|
1186
1273
|
const description = descriptions?.[item];
|
|
1187
|
-
return /* @__PURE__ */
|
|
1274
|
+
return /* @__PURE__ */ jsxs4(Text4, { color: isCursor ? "cyan" : void 0, bold: isCursor, children: [
|
|
1188
1275
|
isCursor ? "\u276F " : " ",
|
|
1189
1276
|
isCurrent ? "\u25CF " : "\u25CB ",
|
|
1190
1277
|
item,
|
|
1191
1278
|
isCurrent ? " (current)" : "",
|
|
1192
|
-
description ? /* @__PURE__ */
|
|
1279
|
+
description ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: ` \u2014 ${description}` }) : null
|
|
1193
1280
|
] }, item);
|
|
1194
1281
|
}),
|
|
1195
|
-
filtered.length === 0 ? /* @__PURE__ */
|
|
1282
|
+
filtered.length === 0 ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "no matches" }) : null
|
|
1196
1283
|
] }) : null,
|
|
1197
|
-
/* @__PURE__ */
|
|
1284
|
+
/* @__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
1285
|
] });
|
|
1199
1286
|
}
|
|
1200
1287
|
var VISIBLE;
|
|
@@ -1207,22 +1294,22 @@ var init_SelectDialog = __esm({
|
|
|
1207
1294
|
|
|
1208
1295
|
// src/tui/KeyDialog.tsx
|
|
1209
1296
|
import { useState as useState2 } from "react";
|
|
1210
|
-
import { Box as
|
|
1297
|
+
import { Box as Box5, Text as Text5, useInput as useInput3 } from "ink";
|
|
1211
1298
|
import TextInput from "ink-text-input";
|
|
1212
|
-
import { jsx as
|
|
1299
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1213
1300
|
function KeyDialog({ providerName, onSubmit, onClose }) {
|
|
1214
1301
|
const [value, setValue] = useState2("");
|
|
1215
1302
|
useInput3((_input, key) => {
|
|
1216
1303
|
if (key.escape) onClose();
|
|
1217
1304
|
});
|
|
1218
|
-
return /* @__PURE__ */
|
|
1219
|
-
/* @__PURE__ */
|
|
1305
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 1, marginY: 1, children: [
|
|
1306
|
+
/* @__PURE__ */ jsxs5(Text5, { bold: true, color: "magenta", children: [
|
|
1220
1307
|
"API key for ",
|
|
1221
1308
|
providerName
|
|
1222
1309
|
] }),
|
|
1223
|
-
/* @__PURE__ */
|
|
1224
|
-
/* @__PURE__ */
|
|
1225
|
-
/* @__PURE__ */
|
|
1310
|
+
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
|
|
1311
|
+
/* @__PURE__ */ jsx5(Text5, { children: "key: " }),
|
|
1312
|
+
/* @__PURE__ */ jsx5(
|
|
1226
1313
|
TextInput,
|
|
1227
1314
|
{
|
|
1228
1315
|
mask: "*",
|
|
@@ -1235,7 +1322,7 @@ function KeyDialog({ providerName, onSubmit, onClose }) {
|
|
|
1235
1322
|
}
|
|
1236
1323
|
)
|
|
1237
1324
|
] }),
|
|
1238
|
-
/* @__PURE__ */
|
|
1325
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "enter confirm \xB7 esc cancel \xB7 saved to ~/.mentee/config.json" }) })
|
|
1239
1326
|
] });
|
|
1240
1327
|
}
|
|
1241
1328
|
var init_KeyDialog = __esm({
|
|
@@ -1244,23 +1331,15 @@ var init_KeyDialog = __esm({
|
|
|
1244
1331
|
}
|
|
1245
1332
|
});
|
|
1246
1333
|
|
|
1247
|
-
// package.json
|
|
1248
|
-
var version;
|
|
1249
|
-
var init_package = __esm({
|
|
1250
|
-
"package.json"() {
|
|
1251
|
-
version = "0.1.10";
|
|
1252
|
-
}
|
|
1253
|
-
});
|
|
1254
|
-
|
|
1255
1334
|
// src/tui/App.tsx
|
|
1256
1335
|
var App_exports = {};
|
|
1257
1336
|
__export(App_exports, {
|
|
1258
1337
|
App: () => App
|
|
1259
1338
|
});
|
|
1260
1339
|
import { useEffect as useEffect2, useMemo as useMemo2, useRef, useState as useState3 } from "react";
|
|
1261
|
-
import { Box as
|
|
1340
|
+
import { Box as Box6, Static, Text as Text6, useApp, useInput as useInput4, useStdout } from "ink";
|
|
1262
1341
|
import TextInput2 from "ink-text-input";
|
|
1263
|
-
import { jsx as
|
|
1342
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1264
1343
|
function App(props) {
|
|
1265
1344
|
const { exit } = useApp();
|
|
1266
1345
|
const { stdout } = useStdout();
|
|
@@ -1288,6 +1367,7 @@ function App(props) {
|
|
|
1288
1367
|
const [detailsOpen, setDetailsOpen] = useState3(false);
|
|
1289
1368
|
const [showDetails, setShowDetails] = useState3(false);
|
|
1290
1369
|
const [thinkingText, setThinkingText] = useState3("");
|
|
1370
|
+
const [fileDiffs, setFileDiffs] = useState3({});
|
|
1291
1371
|
const finalTextRef = useRef(null);
|
|
1292
1372
|
const pendingTool = useRef(null);
|
|
1293
1373
|
const counter = useRef(0);
|
|
@@ -1311,6 +1391,16 @@ function App(props) {
|
|
|
1311
1391
|
if (event.type === "model_request" || event.type === "task_completed") {
|
|
1312
1392
|
setThinkingText("");
|
|
1313
1393
|
}
|
|
1394
|
+
if (event.type === "patch") {
|
|
1395
|
+
const filePath = typeof event.data?.path === "string" ? event.data.path : "file";
|
|
1396
|
+
const oldStr = typeof event.data?.old_string === "string" ? event.data.old_string : "";
|
|
1397
|
+
const newStr = typeof event.data?.new_string === "string" ? event.data.new_string : "";
|
|
1398
|
+
setFileDiffs((prev) => {
|
|
1399
|
+
const arr = prev[filePath] ? [...prev[filePath], { old: oldStr, new: newStr }] : [{ old: oldStr, new: newStr }];
|
|
1400
|
+
return { ...prev, [filePath]: arr };
|
|
1401
|
+
});
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1314
1404
|
appendLog(formatEvent(event), TOOL_NOISE.has(event.type));
|
|
1315
1405
|
if (event.type === "tool_started") {
|
|
1316
1406
|
const name = typeof event.data?.tool === "string" ? event.data.tool : "";
|
|
@@ -1520,6 +1610,7 @@ function App(props) {
|
|
|
1520
1610
|
setDetailsOpen(false);
|
|
1521
1611
|
setShowDetails(false);
|
|
1522
1612
|
setRunning(true);
|
|
1613
|
+
setFileDiffs({});
|
|
1523
1614
|
const ac = new AbortController();
|
|
1524
1615
|
abortRef.current = ac;
|
|
1525
1616
|
try {
|
|
@@ -1591,9 +1682,9 @@ function App(props) {
|
|
|
1591
1682
|
else if (key.ctrl && input === "k") setDialog({ kind: "key" });
|
|
1592
1683
|
});
|
|
1593
1684
|
const modelLabel = model ?? factoryResult.provider?.defaultModel ?? (factoryResult.error ? "no key" : "");
|
|
1594
|
-
const header = /* @__PURE__ */
|
|
1595
|
-
/* @__PURE__ */
|
|
1596
|
-
/* @__PURE__ */
|
|
1685
|
+
const header = /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginBottom: 1, children: [
|
|
1686
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: BANNER }),
|
|
1687
|
+
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1597
1688
|
"v",
|
|
1598
1689
|
version,
|
|
1599
1690
|
" \xB7 ",
|
|
@@ -1604,44 +1695,45 @@ function App(props) {
|
|
|
1604
1695
|
" \xB7 ",
|
|
1605
1696
|
props.cwd
|
|
1606
1697
|
] }),
|
|
1607
|
-
/* @__PURE__ */
|
|
1698
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Alt+M model \xB7 Ctrl+P provider \xB7 Ctrl+K key \xB7 Alt+D details \xB7 /help" })
|
|
1608
1699
|
] }, "header");
|
|
1609
1700
|
const cols = stdout.columns || 80;
|
|
1610
1701
|
const marquee = thinkingText.slice(-Math.max(1, cols - 4));
|
|
1611
|
-
return /* @__PURE__ */
|
|
1612
|
-
/* @__PURE__ */
|
|
1613
|
-
/* @__PURE__ */
|
|
1702
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1703
|
+
/* @__PURE__ */ jsx6(Static, { items: [{ key: "header", text: header }], children: (item) => /* @__PURE__ */ jsx6(Box6, { children: item.text }, item.key) }),
|
|
1704
|
+
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1614
1705
|
log.filter((l) => showDetails || !l.noise).map(
|
|
1615
|
-
(line) => line.kind === "answer" ? /* @__PURE__ */
|
|
1706
|
+
(line) => line.kind === "answer" ? /* @__PURE__ */ jsx6(AnswerBlock, { text: line.text }, line.id) : /* @__PURE__ */ jsx6(Text6, { children: line.text }, line.id)
|
|
1616
1707
|
),
|
|
1617
|
-
finalPending !== null ? /* @__PURE__ */
|
|
1618
|
-
|
|
1619
|
-
typing ?
|
|
1620
|
-
] }) : null,
|
|
1708
|
+
finalPending !== null ? /* @__PURE__ */ jsx6(Box6, { marginTop: 1, flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, children: /* @__PURE__ */ jsxs6(Text6, { color: "green", children: [
|
|
1709
|
+
typedText,
|
|
1710
|
+
typing ? "\u258C" : ""
|
|
1711
|
+
] }) }) : null,
|
|
1712
|
+
/* @__PURE__ */ jsx6(FileDiffView, { diffs: fileDiffs }),
|
|
1621
1713
|
detailsOpen && inspectorIndex !== null && toolHistory[inspectorIndex] ? (() => {
|
|
1622
1714
|
const rec = toolHistory[inspectorIndex];
|
|
1623
1715
|
const outLines = rec.output.split("\n").slice(0, 24).join("\n");
|
|
1624
|
-
return /* @__PURE__ */
|
|
1625
|
-
/* @__PURE__ */
|
|
1716
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: [
|
|
1717
|
+
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1626
1718
|
" tool details (",
|
|
1627
1719
|
inspectorIndex + 1,
|
|
1628
1720
|
"/",
|
|
1629
1721
|
toolHistory.length,
|
|
1630
|
-
") \xB7
|
|
1722
|
+
") \xB7 Alt+D to cycle "
|
|
1631
1723
|
] }),
|
|
1632
|
-
/* @__PURE__ */
|
|
1724
|
+
/* @__PURE__ */ jsxs6(Text6, { color: toolColorName(rec.name), bold: true, children: [
|
|
1633
1725
|
rec.name,
|
|
1634
1726
|
" ",
|
|
1635
1727
|
rec.target
|
|
1636
1728
|
] }),
|
|
1637
|
-
/* @__PURE__ */
|
|
1729
|
+
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1638
1730
|
"args: ",
|
|
1639
1731
|
rec.args.slice(0, 400) || "(none)"
|
|
1640
1732
|
] }),
|
|
1641
|
-
/* @__PURE__ */
|
|
1733
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: outLines || "(no output)" })
|
|
1642
1734
|
] });
|
|
1643
1735
|
})() : null,
|
|
1644
|
-
dialog?.kind === "model" ? /* @__PURE__ */
|
|
1736
|
+
dialog?.kind === "model" ? /* @__PURE__ */ jsx6(
|
|
1645
1737
|
SelectDialog,
|
|
1646
1738
|
{
|
|
1647
1739
|
title: `Model \u2014 ${providerName}`,
|
|
@@ -1655,7 +1747,7 @@ function App(props) {
|
|
|
1655
1747
|
},
|
|
1656
1748
|
onClose: () => setDialog(null)
|
|
1657
1749
|
}
|
|
1658
|
-
) : dialog?.kind === "provider" ? /* @__PURE__ */
|
|
1750
|
+
) : dialog?.kind === "provider" ? /* @__PURE__ */ jsx6(
|
|
1659
1751
|
SelectDialog,
|
|
1660
1752
|
{
|
|
1661
1753
|
title: "Provider",
|
|
@@ -1668,7 +1760,7 @@ function App(props) {
|
|
|
1668
1760
|
},
|
|
1669
1761
|
onClose: () => setDialog(null)
|
|
1670
1762
|
}
|
|
1671
|
-
) : dialog?.kind === "key" ? /* @__PURE__ */
|
|
1763
|
+
) : dialog?.kind === "key" ? /* @__PURE__ */ jsx6(
|
|
1672
1764
|
KeyDialog,
|
|
1673
1765
|
{
|
|
1674
1766
|
providerName,
|
|
@@ -1678,7 +1770,7 @@ function App(props) {
|
|
|
1678
1770
|
},
|
|
1679
1771
|
onClose: () => setDialog(null)
|
|
1680
1772
|
}
|
|
1681
|
-
) : approval ? /* @__PURE__ */
|
|
1773
|
+
) : approval ? /* @__PURE__ */ jsx6(
|
|
1682
1774
|
ApprovalPrompt,
|
|
1683
1775
|
{
|
|
1684
1776
|
request: approval,
|
|
@@ -1687,22 +1779,22 @@ function App(props) {
|
|
|
1687
1779
|
if (decision === "always") bus.emit("info", "Approved for the rest of this session.");
|
|
1688
1780
|
}
|
|
1689
1781
|
}
|
|
1690
|
-
) : running ? /* @__PURE__ */
|
|
1691
|
-
/* @__PURE__ */
|
|
1692
|
-
/* @__PURE__ */
|
|
1782
|
+
) : running ? /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1783
|
+
/* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1784
|
+
/* @__PURE__ */ jsxs6(Text6, { color: "yellow", children: [
|
|
1693
1785
|
SPINNER_FRAMES[frame],
|
|
1694
1786
|
" "
|
|
1695
1787
|
] }),
|
|
1696
|
-
/* @__PURE__ */
|
|
1788
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "agent working... (Ctrl+C to exit)" })
|
|
1697
1789
|
] }),
|
|
1698
|
-
thinkingText ? /* @__PURE__ */
|
|
1699
|
-
/* @__PURE__ */
|
|
1700
|
-
/* @__PURE__ */
|
|
1701
|
-
/* @__PURE__ */
|
|
1790
|
+
thinkingText ? /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1791
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "\u{1F4AD} " }),
|
|
1792
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", dimColor: true, children: marquee }),
|
|
1793
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "\u258C" })
|
|
1702
1794
|
] }) : null
|
|
1703
|
-
] }) : /* @__PURE__ */
|
|
1704
|
-
/* @__PURE__ */
|
|
1705
|
-
/* @__PURE__ */
|
|
1795
|
+
] }) : /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1796
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", bold: true, children: "\u25B8 " }),
|
|
1797
|
+
/* @__PURE__ */ jsx6(
|
|
1706
1798
|
TextInput2,
|
|
1707
1799
|
{
|
|
1708
1800
|
value: taskInput,
|
|
@@ -1723,6 +1815,7 @@ var init_App = __esm({
|
|
|
1723
1815
|
init_logging();
|
|
1724
1816
|
init_render();
|
|
1725
1817
|
init_markdown();
|
|
1818
|
+
init_diff();
|
|
1726
1819
|
init_approval();
|
|
1727
1820
|
init_loop();
|
|
1728
1821
|
init_conversation();
|
|
@@ -1733,12 +1826,14 @@ var init_App = __esm({
|
|
|
1733
1826
|
init_KeyDialog();
|
|
1734
1827
|
init_package();
|
|
1735
1828
|
SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
1736
|
-
PROVIDER_NAMES = ["kimi", "glm", "zai", "zai-coding", "mock"];
|
|
1829
|
+
PROVIDER_NAMES = ["kimi", "glm", "zai", "zai-coding", "openrouter", "nvidia", "mock"];
|
|
1737
1830
|
PROVIDER_DESCRIPTIONS = {
|
|
1738
1831
|
kimi: "Moonshot \xB7 api.moonshot.ai",
|
|
1739
1832
|
glm: "Zhipu China \xB7 open.bigmodel.cn \xB7 separate account & keys",
|
|
1740
1833
|
zai: "Z.ai standard plan \xB7 api.z.ai/api/paas/v4",
|
|
1741
1834
|
"zai-coding": "Z.ai GLM Coding Plan subscription \xB7 api.z.ai/api/coding",
|
|
1835
|
+
openrouter: "OpenRouter \xB7 100+ models via one key (Claude, GPT, Llama\u2026)",
|
|
1836
|
+
nvidia: "NVIDIA NIM \xB7 build.nvidia.com hosted models",
|
|
1742
1837
|
mock: "offline testing \xB7 no network"
|
|
1743
1838
|
};
|
|
1744
1839
|
BANNER = ` __ __ \u{1F380}
|
|
@@ -1910,6 +2005,16 @@ function createKimiProvider(apiKey, model) {
|
|
|
1910
2005
|
});
|
|
1911
2006
|
}
|
|
1912
2007
|
|
|
2008
|
+
// src/models/nvidia.ts
|
|
2009
|
+
function createNvidiaProvider(apiKey, model) {
|
|
2010
|
+
return new OpenAICompatProvider({
|
|
2011
|
+
name: "nvidia",
|
|
2012
|
+
defaultModel: model ?? "nvidia/llama-3.1-nemotron-70b-instruct",
|
|
2013
|
+
baseURL: "https://integrate.api.nvidia.com/v1",
|
|
2014
|
+
apiKey
|
|
2015
|
+
});
|
|
2016
|
+
}
|
|
2017
|
+
|
|
1913
2018
|
// src/models/mock.ts
|
|
1914
2019
|
var callCounter = 0;
|
|
1915
2020
|
var MockProvider = class {
|
|
@@ -1946,6 +2051,16 @@ var MockProvider = class {
|
|
|
1946
2051
|
}
|
|
1947
2052
|
};
|
|
1948
2053
|
|
|
2054
|
+
// src/models/openrouter.ts
|
|
2055
|
+
function createOpenRouterProvider(apiKey, model) {
|
|
2056
|
+
return new OpenAICompatProvider({
|
|
2057
|
+
name: "openrouter",
|
|
2058
|
+
defaultModel: model ?? "anthropic/claude-3.5-sonnet",
|
|
2059
|
+
baseURL: "https://openrouter.ai/api/v1",
|
|
2060
|
+
apiKey
|
|
2061
|
+
});
|
|
2062
|
+
}
|
|
2063
|
+
|
|
1949
2064
|
// src/models/zai.ts
|
|
1950
2065
|
function createZaiProvider(apiKey, model) {
|
|
1951
2066
|
return new OpenAICompatProvider({
|
|
@@ -1969,7 +2084,9 @@ var ENV_NAMES2 = {
|
|
|
1969
2084
|
kimi: "MENTEE_KIMI_API_KEY",
|
|
1970
2085
|
glm: "MENTEE_GLM_API_KEY",
|
|
1971
2086
|
zai: "MENTEE_ZAI_API_KEY",
|
|
1972
|
-
"zai-coding": "MENTEE_ZAI_API_KEY"
|
|
2087
|
+
"zai-coding": "MENTEE_ZAI_API_KEY",
|
|
2088
|
+
openrouter: "MENTEE_OPENROUTER_API_KEY",
|
|
2089
|
+
nvidia: "MENTEE_NVIDIA_API_KEY"
|
|
1973
2090
|
};
|
|
1974
2091
|
var MissingApiKeyError = class extends Error {
|
|
1975
2092
|
constructor(provider) {
|
|
@@ -1997,6 +2114,12 @@ function createProvider(provider, config, modelOverride) {
|
|
|
1997
2114
|
if (provider === "zai-coding") {
|
|
1998
2115
|
return createZaiCodingProvider(apiKey, model);
|
|
1999
2116
|
}
|
|
2117
|
+
if (provider === "openrouter") {
|
|
2118
|
+
return createOpenRouterProvider(apiKey, model);
|
|
2119
|
+
}
|
|
2120
|
+
if (provider === "nvidia") {
|
|
2121
|
+
return createNvidiaProvider(apiKey, model);
|
|
2122
|
+
}
|
|
2000
2123
|
return createGlmProvider(apiKey, model);
|
|
2001
2124
|
}
|
|
2002
2125
|
|
|
@@ -3413,12 +3536,12 @@ async function runConfigWizard() {
|
|
|
3413
3536
|
const config = loadConfig() ?? blankConfig();
|
|
3414
3537
|
config.keys = config.keys ?? {};
|
|
3415
3538
|
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";
|
|
3539
|
+
console.log("Providers: 1) Kimi (Moonshot) 2) GLM (Zhipu CN) 3) Z.ai (GLM international) 4) OpenRouter 5) NVIDIA NIM");
|
|
3540
|
+
const defaultChoice = config.defaultProvider === "glm" ? "2" : config.defaultProvider === "zai" ? "3" : config.defaultProvider === "openrouter" ? "4" : config.defaultProvider === "nvidia" ? "5" : "1";
|
|
3418
3541
|
const providerChoice = await ask(rl, "Default provider [1]", defaultChoice);
|
|
3419
|
-
const provider = providerChoice === "2" ? "glm" : providerChoice === "3" ? "zai" : "kimi";
|
|
3542
|
+
const provider = providerChoice === "2" ? "glm" : providerChoice === "3" ? "zai" : providerChoice === "4" ? "openrouter" : providerChoice === "5" ? "nvidia" : "kimi";
|
|
3420
3543
|
config.defaultProvider = provider;
|
|
3421
|
-
const defaultModel = provider === "kimi" ? "kimi-k2.7-code" : "glm-4.6";
|
|
3544
|
+
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
3545
|
const key = await ask(rl, `API key for ${provider}`);
|
|
3423
3546
|
if (key) config.keys[provider] = key;
|
|
3424
3547
|
const model = await ask(rl, `Model for ${provider}`, defaultModel);
|
|
@@ -3430,7 +3553,7 @@ Saved to ${configFilePath()}
|
|
|
3430
3553
|
if (config.keys[provider]) {
|
|
3431
3554
|
console.log("Testing connection...");
|
|
3432
3555
|
try {
|
|
3433
|
-
const providerInstance = provider === "kimi" ? createKimiProvider(config.keys[provider], model) : provider === "zai" ? createZaiProvider(config.keys[provider], model) : createGlmProvider(config.keys[provider], model);
|
|
3556
|
+
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
3557
|
await providerInstance.generate(
|
|
3435
3558
|
{
|
|
3436
3559
|
system: "You are a ping endpoint.",
|
|
@@ -3457,20 +3580,20 @@ Saved to ${configFilePath()}
|
|
|
3457
3580
|
}
|
|
3458
3581
|
|
|
3459
3582
|
// src/cli.tsx
|
|
3583
|
+
init_package();
|
|
3460
3584
|
import path9 from "path";
|
|
3461
|
-
import { jsx as
|
|
3462
|
-
var packageJson = { version: "0.1.0" };
|
|
3585
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
3463
3586
|
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(
|
|
3587
|
+
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
3588
|
program.command("config").description("Configure providers, API keys, and models (interactive wizard)").action(async () => {
|
|
3466
3589
|
await runConfigWizard();
|
|
3467
3590
|
});
|
|
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) => {
|
|
3591
|
+
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
3592
|
const task = taskParts.join(" ").trim();
|
|
3470
3593
|
const config = loadConfig();
|
|
3471
3594
|
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.`));
|
|
3595
|
+
if (!["kimi", "glm", "zai", "zai-coding", "openrouter", "nvidia", "mock"].includes(providerName)) {
|
|
3596
|
+
console.error(chalk4.red(`Unknown provider "${providerName}". Use kimi, glm, zai, zai-coding, openrouter, nvidia, or mock.`));
|
|
3474
3597
|
process.exit(1);
|
|
3475
3598
|
}
|
|
3476
3599
|
const tools = new ToolRegistry(createDefaultTools());
|
|
@@ -3515,7 +3638,7 @@ program.argument("[task...]", "the software task to perform (omit to type it int
|
|
|
3515
3638
|
const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
|
|
3516
3639
|
const { render } = await import("ink");
|
|
3517
3640
|
const { waitUntilExit } = render(
|
|
3518
|
-
/* @__PURE__ */
|
|
3641
|
+
/* @__PURE__ */ jsx7(
|
|
3519
3642
|
App2,
|
|
3520
3643
|
{
|
|
3521
3644
|
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.11",
|
|
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",
|