@menteeai/menteeswe 0.1.9 → 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 +358 -109
- 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({
|
|
@@ -593,16 +596,24 @@ function appendTurn(cwd, task, response) {
|
|
|
593
596
|
if (turns.length > 50) turns = turns.slice(-50);
|
|
594
597
|
fs9.writeFileSync(file, JSON.stringify(turns, null, 2));
|
|
595
598
|
}
|
|
596
|
-
function formatConversationContext(cwd, limit =
|
|
599
|
+
function formatConversationContext(cwd, limit = 10) {
|
|
597
600
|
const turns = loadConversation(cwd, limit);
|
|
598
601
|
if (turns.length === 0) return "";
|
|
599
|
-
const
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
602
|
+
const MAX_PRIOR_CHARS = 5e3;
|
|
603
|
+
const header = "# Prior conversation in this project (most recent shown)";
|
|
604
|
+
const blocks = [];
|
|
605
|
+
let total = header.length;
|
|
606
|
+
for (let i = turns.length - 1; i >= 0; i--) {
|
|
607
|
+
const t = turns[i];
|
|
608
|
+
if (!t) continue;
|
|
609
|
+
const block = `User: ${t.task}
|
|
610
|
+
Assistant: ${t.response.trim()}
|
|
611
|
+
`;
|
|
612
|
+
if (blocks.length > 0 && total + block.length > MAX_PRIOR_CHARS) break;
|
|
613
|
+
blocks.unshift(block);
|
|
614
|
+
total += block.length;
|
|
604
615
|
}
|
|
605
|
-
return
|
|
616
|
+
return [header, ...blocks, ""].join("\n");
|
|
606
617
|
}
|
|
607
618
|
var init_conversation = __esm({
|
|
608
619
|
"src/agent/conversation.ts"() {
|
|
@@ -700,10 +711,17 @@ function estimateContextChars(messages, system) {
|
|
|
700
711
|
return total;
|
|
701
712
|
}
|
|
702
713
|
function trimOldToolResults(messages) {
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
714
|
+
let seen = 0;
|
|
715
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
716
|
+
const message = messages[i];
|
|
717
|
+
if (!message) continue;
|
|
718
|
+
if (message.role !== "tool") continue;
|
|
719
|
+
seen++;
|
|
720
|
+
if (seen <= KEEP_RECENT_TOOL) continue;
|
|
721
|
+
const content = message.content ?? "";
|
|
722
|
+
if (content.length <= 240) continue;
|
|
723
|
+
const head = content.replace(/\s+/g, " ").slice(0, 160);
|
|
724
|
+
message.content = `\u27E8prior tool output trimmed: ${head}\u2026 (${content.length} chars)\u27E9`;
|
|
707
725
|
}
|
|
708
726
|
}
|
|
709
727
|
async function runAgent(options) {
|
|
@@ -951,7 +969,7 @@ ${systemExtra}` : "");
|
|
|
951
969
|
});
|
|
952
970
|
return { success, finalText, state };
|
|
953
971
|
}
|
|
954
|
-
var MAX_CONTEXT_CHARS, READ_BUDGET, RATE_LIMIT_MAX_ATTEMPTS;
|
|
972
|
+
var MAX_CONTEXT_CHARS, READ_BUDGET, RATE_LIMIT_MAX_ATTEMPTS, KEEP_RECENT_TOOL;
|
|
955
973
|
var init_loop = __esm({
|
|
956
974
|
"src/agent/loop.ts"() {
|
|
957
975
|
"use strict";
|
|
@@ -959,15 +977,200 @@ var init_loop = __esm({
|
|
|
959
977
|
init_conversation();
|
|
960
978
|
init_state();
|
|
961
979
|
init_base();
|
|
962
|
-
MAX_CONTEXT_CHARS =
|
|
980
|
+
MAX_CONTEXT_CHARS = 7e4;
|
|
963
981
|
READ_BUDGET = 6;
|
|
964
982
|
RATE_LIMIT_MAX_ATTEMPTS = 8;
|
|
983
|
+
KEEP_RECENT_TOOL = 4;
|
|
965
984
|
}
|
|
966
985
|
});
|
|
967
986
|
|
|
968
|
-
//
|
|
969
|
-
|
|
987
|
+
// package.json
|
|
988
|
+
var version;
|
|
989
|
+
var init_package = __esm({
|
|
990
|
+
"package.json"() {
|
|
991
|
+
version = "0.1.11";
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
|
|
995
|
+
// src/tui/markdown.tsx
|
|
996
|
+
import { Box, Text } from "ink";
|
|
970
997
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
998
|
+
function renderInline(text, keyPrefix) {
|
|
999
|
+
const nodes = [];
|
|
1000
|
+
const regex = /(\*\*([^*]+)\*\*)|(\*([^*]+)\*)|(`([^`]+)`)/g;
|
|
1001
|
+
let last = 0;
|
|
1002
|
+
let m;
|
|
1003
|
+
let i = 0;
|
|
1004
|
+
while ((m = regex.exec(text)) !== null) {
|
|
1005
|
+
if (m.index > last) nodes.push(text.slice(last, m.index));
|
|
1006
|
+
if (m[2] !== void 0) {
|
|
1007
|
+
nodes.push(
|
|
1008
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: m[2] }, `${keyPrefix}-b${i}`)
|
|
1009
|
+
);
|
|
1010
|
+
} else if (m[4] !== void 0) {
|
|
1011
|
+
nodes.push(
|
|
1012
|
+
/* @__PURE__ */ jsx(Text, { italic: true, children: m[4] }, `${keyPrefix}-i${i}`)
|
|
1013
|
+
);
|
|
1014
|
+
} else if (m[6] !== void 0) {
|
|
1015
|
+
nodes.push(
|
|
1016
|
+
/* @__PURE__ */ jsx(Text, { color: "greenBright", children: m[6] }, `${keyPrefix}-c${i}`)
|
|
1017
|
+
);
|
|
1018
|
+
}
|
|
1019
|
+
last = m.index + m[0].length;
|
|
1020
|
+
i++;
|
|
1021
|
+
}
|
|
1022
|
+
if (last < text.length) nodes.push(text.slice(last));
|
|
1023
|
+
return nodes;
|
|
1024
|
+
}
|
|
1025
|
+
function renderMarkdown(md) {
|
|
1026
|
+
const lines = md.split("\n");
|
|
1027
|
+
const blocks = [];
|
|
1028
|
+
let para = [];
|
|
1029
|
+
let key = 0;
|
|
1030
|
+
const flushPara = () => {
|
|
1031
|
+
if (para.length === 0) return;
|
|
1032
|
+
blocks.push(/* @__PURE__ */ jsx(Text, { children: renderInline(para.join(" "), `p${key}`) }, `p${key++}`));
|
|
1033
|
+
para = [];
|
|
1034
|
+
};
|
|
1035
|
+
for (const line of lines) {
|
|
1036
|
+
if (line.trim() === "") {
|
|
1037
|
+
flushPara();
|
|
1038
|
+
continue;
|
|
1039
|
+
}
|
|
1040
|
+
const heading = /^(#{1,6})\s+(.*)$/.exec(line);
|
|
1041
|
+
if (heading) {
|
|
1042
|
+
flushPara();
|
|
1043
|
+
const level = heading[1]?.length ?? 0;
|
|
1044
|
+
blocks.push(
|
|
1045
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: level <= 2 ? "cyan" : "white", children: renderInline(heading[2] ?? "", `h${key}`) }, `h${key++}`)
|
|
1046
|
+
);
|
|
1047
|
+
continue;
|
|
1048
|
+
}
|
|
1049
|
+
const bullet = /^\s*[-*]\s+(.*)$/.exec(line);
|
|
1050
|
+
if (bullet) {
|
|
1051
|
+
flushPara();
|
|
1052
|
+
blocks.push(
|
|
1053
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1054
|
+
" \u2022 ",
|
|
1055
|
+
renderInline(bullet[1] ?? "", `b${key}`)
|
|
1056
|
+
] }, `b${key++}`)
|
|
1057
|
+
);
|
|
1058
|
+
continue;
|
|
1059
|
+
}
|
|
1060
|
+
const numbered = /^\s*\d+\.\s+(.*)$/.exec(line);
|
|
1061
|
+
if (numbered) {
|
|
1062
|
+
flushPara();
|
|
1063
|
+
blocks.push(
|
|
1064
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1065
|
+
" ",
|
|
1066
|
+
renderInline(numbered[1] ?? "", `n${key}`)
|
|
1067
|
+
] }, `n${key++}`)
|
|
1068
|
+
);
|
|
1069
|
+
continue;
|
|
1070
|
+
}
|
|
1071
|
+
para.push(line.trim());
|
|
1072
|
+
}
|
|
1073
|
+
flushPara();
|
|
1074
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: blocks });
|
|
1075
|
+
}
|
|
1076
|
+
function AnswerBlock({ text }) {
|
|
1077
|
+
return /* @__PURE__ */ jsx(
|
|
1078
|
+
Box,
|
|
1079
|
+
{
|
|
1080
|
+
flexDirection: "column",
|
|
1081
|
+
borderStyle: "round",
|
|
1082
|
+
borderColor: "green",
|
|
1083
|
+
paddingX: 1,
|
|
1084
|
+
marginY: 0,
|
|
1085
|
+
children: renderMarkdown(text)
|
|
1086
|
+
}
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1089
|
+
var init_markdown = __esm({
|
|
1090
|
+
"src/tui/markdown.tsx"() {
|
|
1091
|
+
"use strict";
|
|
1092
|
+
}
|
|
1093
|
+
});
|
|
1094
|
+
|
|
1095
|
+
// src/tui/diff.tsx
|
|
1096
|
+
import { Box as Box2, Text as Text2 } from "ink";
|
|
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";
|
|
971
1174
|
function argPreview(request) {
|
|
972
1175
|
const args = request.args;
|
|
973
1176
|
if (request.tool === "apply_patch" && typeof args.old_string === "string" && typeof args.new_string === "string") {
|
|
@@ -985,8 +1188,8 @@ function ApprovalPrompt({ request, onDecision }) {
|
|
|
985
1188
|
else if (input === "a") onDecision("always");
|
|
986
1189
|
else if (input === "n" || key.escape) onDecision("deny");
|
|
987
1190
|
});
|
|
988
|
-
return /* @__PURE__ */
|
|
989
|
-
/* @__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: [
|
|
990
1193
|
"Permission needed: ",
|
|
991
1194
|
friendlyToolName(request.tool),
|
|
992
1195
|
" (",
|
|
@@ -994,14 +1197,14 @@ function ApprovalPrompt({ request, onDecision }) {
|
|
|
994
1197
|
") \u2014 ",
|
|
995
1198
|
request.risk
|
|
996
1199
|
] }),
|
|
997
|
-
/* @__PURE__ */
|
|
998
|
-
/* @__PURE__ */
|
|
999
|
-
/* @__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]" }),
|
|
1000
1203
|
" allow once \xB7 ",
|
|
1001
|
-
/* @__PURE__ */
|
|
1204
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", bold: true, children: "[a]" }),
|
|
1002
1205
|
" allow this session \xB7",
|
|
1003
1206
|
" ",
|
|
1004
|
-
/* @__PURE__ */
|
|
1207
|
+
/* @__PURE__ */ jsx3(Text3, { color: "red", bold: true, children: "[n]" }),
|
|
1005
1208
|
" deny"
|
|
1006
1209
|
] }) })
|
|
1007
1210
|
] });
|
|
@@ -1015,8 +1218,8 @@ var init_Approval = __esm({
|
|
|
1015
1218
|
|
|
1016
1219
|
// src/tui/SelectDialog.tsx
|
|
1017
1220
|
import { useEffect, useMemo, useState } from "react";
|
|
1018
|
-
import { Box as
|
|
1019
|
-
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";
|
|
1020
1223
|
function SelectDialog({
|
|
1021
1224
|
title,
|
|
1022
1225
|
items,
|
|
@@ -1051,34 +1254,34 @@ function SelectDialog({
|
|
|
1051
1254
|
Math.min(cursor - Math.floor(VISIBLE / 2), Math.max(0, filtered.length - VISIBLE))
|
|
1052
1255
|
);
|
|
1053
1256
|
const visible = filtered.slice(start, start + VISIBLE);
|
|
1054
|
-
return /* @__PURE__ */
|
|
1055
|
-
/* @__PURE__ */
|
|
1056
|
-
/* @__PURE__ */
|
|
1057
|
-
/* @__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: [
|
|
1058
1261
|
"search: ",
|
|
1059
1262
|
filter
|
|
1060
1263
|
] }),
|
|
1061
|
-
/* @__PURE__ */
|
|
1264
|
+
/* @__PURE__ */ jsx4(Text4, { children: "\u258F" })
|
|
1062
1265
|
] }),
|
|
1063
|
-
loading ? /* @__PURE__ */
|
|
1064
|
-
error ? /* @__PURE__ */
|
|
1065
|
-
!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: [
|
|
1066
1269
|
visible.map((item, i) => {
|
|
1067
1270
|
const index = start + i;
|
|
1068
1271
|
const isCursor = index === cursor;
|
|
1069
1272
|
const isCurrent = item === current;
|
|
1070
1273
|
const description = descriptions?.[item];
|
|
1071
|
-
return /* @__PURE__ */
|
|
1274
|
+
return /* @__PURE__ */ jsxs4(Text4, { color: isCursor ? "cyan" : void 0, bold: isCursor, children: [
|
|
1072
1275
|
isCursor ? "\u276F " : " ",
|
|
1073
1276
|
isCurrent ? "\u25CF " : "\u25CB ",
|
|
1074
1277
|
item,
|
|
1075
1278
|
isCurrent ? " (current)" : "",
|
|
1076
|
-
description ? /* @__PURE__ */
|
|
1279
|
+
description ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: ` \u2014 ${description}` }) : null
|
|
1077
1280
|
] }, item);
|
|
1078
1281
|
}),
|
|
1079
|
-
filtered.length === 0 ? /* @__PURE__ */
|
|
1282
|
+
filtered.length === 0 ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "no matches" }) : null
|
|
1080
1283
|
] }) : null,
|
|
1081
|
-
/* @__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" }) })
|
|
1082
1285
|
] });
|
|
1083
1286
|
}
|
|
1084
1287
|
var VISIBLE;
|
|
@@ -1091,22 +1294,22 @@ var init_SelectDialog = __esm({
|
|
|
1091
1294
|
|
|
1092
1295
|
// src/tui/KeyDialog.tsx
|
|
1093
1296
|
import { useState as useState2 } from "react";
|
|
1094
|
-
import { Box as
|
|
1297
|
+
import { Box as Box5, Text as Text5, useInput as useInput3 } from "ink";
|
|
1095
1298
|
import TextInput from "ink-text-input";
|
|
1096
|
-
import { jsx as
|
|
1299
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1097
1300
|
function KeyDialog({ providerName, onSubmit, onClose }) {
|
|
1098
1301
|
const [value, setValue] = useState2("");
|
|
1099
1302
|
useInput3((_input, key) => {
|
|
1100
1303
|
if (key.escape) onClose();
|
|
1101
1304
|
});
|
|
1102
|
-
return /* @__PURE__ */
|
|
1103
|
-
/* @__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: [
|
|
1104
1307
|
"API key for ",
|
|
1105
1308
|
providerName
|
|
1106
1309
|
] }),
|
|
1107
|
-
/* @__PURE__ */
|
|
1108
|
-
/* @__PURE__ */
|
|
1109
|
-
/* @__PURE__ */
|
|
1310
|
+
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
|
|
1311
|
+
/* @__PURE__ */ jsx5(Text5, { children: "key: " }),
|
|
1312
|
+
/* @__PURE__ */ jsx5(
|
|
1110
1313
|
TextInput,
|
|
1111
1314
|
{
|
|
1112
1315
|
mask: "*",
|
|
@@ -1119,7 +1322,7 @@ function KeyDialog({ providerName, onSubmit, onClose }) {
|
|
|
1119
1322
|
}
|
|
1120
1323
|
)
|
|
1121
1324
|
] }),
|
|
1122
|
-
/* @__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" }) })
|
|
1123
1326
|
] });
|
|
1124
1327
|
}
|
|
1125
1328
|
var init_KeyDialog = __esm({
|
|
@@ -1128,23 +1331,15 @@ var init_KeyDialog = __esm({
|
|
|
1128
1331
|
}
|
|
1129
1332
|
});
|
|
1130
1333
|
|
|
1131
|
-
// package.json
|
|
1132
|
-
var version;
|
|
1133
|
-
var init_package = __esm({
|
|
1134
|
-
"package.json"() {
|
|
1135
|
-
version = "0.1.9";
|
|
1136
|
-
}
|
|
1137
|
-
});
|
|
1138
|
-
|
|
1139
1334
|
// src/tui/App.tsx
|
|
1140
1335
|
var App_exports = {};
|
|
1141
1336
|
__export(App_exports, {
|
|
1142
1337
|
App: () => App
|
|
1143
1338
|
});
|
|
1144
1339
|
import { useEffect as useEffect2, useMemo as useMemo2, useRef, useState as useState3 } from "react";
|
|
1145
|
-
import { Box as
|
|
1340
|
+
import { Box as Box6, Static, Text as Text6, useApp, useInput as useInput4, useStdout } from "ink";
|
|
1146
1341
|
import TextInput2 from "ink-text-input";
|
|
1147
|
-
import { jsx as
|
|
1342
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1148
1343
|
function App(props) {
|
|
1149
1344
|
const { exit } = useApp();
|
|
1150
1345
|
const { stdout } = useStdout();
|
|
@@ -1172,15 +1367,17 @@ function App(props) {
|
|
|
1172
1367
|
const [detailsOpen, setDetailsOpen] = useState3(false);
|
|
1173
1368
|
const [showDetails, setShowDetails] = useState3(false);
|
|
1174
1369
|
const [thinkingText, setThinkingText] = useState3("");
|
|
1370
|
+
const [fileDiffs, setFileDiffs] = useState3({});
|
|
1371
|
+
const finalTextRef = useRef(null);
|
|
1175
1372
|
const pendingTool = useRef(null);
|
|
1176
1373
|
const counter = useRef(0);
|
|
1177
1374
|
const stateRef = useRef({ running, approval, dialog, factoryResult, providerName, model });
|
|
1178
1375
|
stateRef.current = { running, approval, dialog, factoryResult, providerName, model };
|
|
1179
1376
|
const abortRef = useRef(null);
|
|
1180
|
-
const appendLog = (text, noise = false) => {
|
|
1377
|
+
const appendLog = (text, noise = false, kind) => {
|
|
1181
1378
|
if (!text) return;
|
|
1182
1379
|
counter.current += 1;
|
|
1183
|
-
const line = { id: counter.current, text, noise };
|
|
1380
|
+
const line = { id: counter.current, text, noise, kind };
|
|
1184
1381
|
setLog((prev) => [...prev, line]);
|
|
1185
1382
|
};
|
|
1186
1383
|
useEffect2(() => {
|
|
@@ -1194,6 +1391,16 @@ function App(props) {
|
|
|
1194
1391
|
if (event.type === "model_request" || event.type === "task_completed") {
|
|
1195
1392
|
setThinkingText("");
|
|
1196
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
|
+
}
|
|
1197
1404
|
appendLog(formatEvent(event), TOOL_NOISE.has(event.type));
|
|
1198
1405
|
if (event.type === "tool_started") {
|
|
1199
1406
|
const name = typeof event.data?.tool === "string" ? event.data.tool : "";
|
|
@@ -1211,10 +1418,12 @@ function App(props) {
|
|
|
1211
1418
|
} else if (event.type === "task_completed") {
|
|
1212
1419
|
const text = typeof event.data?.finalText === "string" ? event.data.finalText.trim() : "";
|
|
1213
1420
|
if (text) {
|
|
1214
|
-
|
|
1421
|
+
finalTextRef.current = text;
|
|
1215
1422
|
setFinalPending(text);
|
|
1216
1423
|
setTypedText("");
|
|
1217
1424
|
setTyping(true);
|
|
1425
|
+
} else {
|
|
1426
|
+
finalTextRef.current = null;
|
|
1218
1427
|
}
|
|
1219
1428
|
}
|
|
1220
1429
|
});
|
|
@@ -1389,6 +1598,10 @@ function App(props) {
|
|
|
1389
1598
|
appendLog(factoryResult.error ?? "No provider configured. Press Ctrl+K to add an API key.");
|
|
1390
1599
|
return;
|
|
1391
1600
|
}
|
|
1601
|
+
if (finalTextRef.current) {
|
|
1602
|
+
appendLog(finalTextRef.current, false, "answer");
|
|
1603
|
+
finalTextRef.current = null;
|
|
1604
|
+
}
|
|
1392
1605
|
setFinalPending(null);
|
|
1393
1606
|
setTypedText("");
|
|
1394
1607
|
setTyping(false);
|
|
@@ -1397,6 +1610,7 @@ function App(props) {
|
|
|
1397
1610
|
setDetailsOpen(false);
|
|
1398
1611
|
setShowDetails(false);
|
|
1399
1612
|
setRunning(true);
|
|
1613
|
+
setFileDiffs({});
|
|
1400
1614
|
const ac = new AbortController();
|
|
1401
1615
|
abortRef.current = ac;
|
|
1402
1616
|
try {
|
|
@@ -1468,9 +1682,9 @@ function App(props) {
|
|
|
1468
1682
|
else if (key.ctrl && input === "k") setDialog({ kind: "key" });
|
|
1469
1683
|
});
|
|
1470
1684
|
const modelLabel = model ?? factoryResult.provider?.defaultModel ?? (factoryResult.error ? "no key" : "");
|
|
1471
|
-
const header = /* @__PURE__ */
|
|
1472
|
-
/* @__PURE__ */
|
|
1473
|
-
/* @__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: [
|
|
1474
1688
|
"v",
|
|
1475
1689
|
version,
|
|
1476
1690
|
" \xB7 ",
|
|
@@ -1481,42 +1695,45 @@ function App(props) {
|
|
|
1481
1695
|
" \xB7 ",
|
|
1482
1696
|
props.cwd
|
|
1483
1697
|
] }),
|
|
1484
|
-
/* @__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" })
|
|
1485
1699
|
] }, "header");
|
|
1486
1700
|
const cols = stdout.columns || 80;
|
|
1487
1701
|
const marquee = thinkingText.slice(-Math.max(1, cols - 4));
|
|
1488
|
-
return /* @__PURE__ */
|
|
1489
|
-
/* @__PURE__ */
|
|
1490
|
-
/* @__PURE__ */
|
|
1491
|
-
log.filter((l) => showDetails || !l.noise).map(
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
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: [
|
|
1705
|
+
log.filter((l) => showDetails || !l.noise).map(
|
|
1706
|
+
(line) => line.kind === "answer" ? /* @__PURE__ */ jsx6(AnswerBlock, { text: line.text }, line.id) : /* @__PURE__ */ jsx6(Text6, { children: line.text }, line.id)
|
|
1707
|
+
),
|
|
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 }),
|
|
1496
1713
|
detailsOpen && inspectorIndex !== null && toolHistory[inspectorIndex] ? (() => {
|
|
1497
1714
|
const rec = toolHistory[inspectorIndex];
|
|
1498
1715
|
const outLines = rec.output.split("\n").slice(0, 24).join("\n");
|
|
1499
|
-
return /* @__PURE__ */
|
|
1500
|
-
/* @__PURE__ */
|
|
1716
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: [
|
|
1717
|
+
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1501
1718
|
" tool details (",
|
|
1502
1719
|
inspectorIndex + 1,
|
|
1503
1720
|
"/",
|
|
1504
1721
|
toolHistory.length,
|
|
1505
|
-
") \xB7
|
|
1722
|
+
") \xB7 Alt+D to cycle "
|
|
1506
1723
|
] }),
|
|
1507
|
-
/* @__PURE__ */
|
|
1724
|
+
/* @__PURE__ */ jsxs6(Text6, { color: toolColorName(rec.name), bold: true, children: [
|
|
1508
1725
|
rec.name,
|
|
1509
1726
|
" ",
|
|
1510
1727
|
rec.target
|
|
1511
1728
|
] }),
|
|
1512
|
-
/* @__PURE__ */
|
|
1729
|
+
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1513
1730
|
"args: ",
|
|
1514
1731
|
rec.args.slice(0, 400) || "(none)"
|
|
1515
1732
|
] }),
|
|
1516
|
-
/* @__PURE__ */
|
|
1733
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: outLines || "(no output)" })
|
|
1517
1734
|
] });
|
|
1518
1735
|
})() : null,
|
|
1519
|
-
dialog?.kind === "model" ? /* @__PURE__ */
|
|
1736
|
+
dialog?.kind === "model" ? /* @__PURE__ */ jsx6(
|
|
1520
1737
|
SelectDialog,
|
|
1521
1738
|
{
|
|
1522
1739
|
title: `Model \u2014 ${providerName}`,
|
|
@@ -1530,7 +1747,7 @@ function App(props) {
|
|
|
1530
1747
|
},
|
|
1531
1748
|
onClose: () => setDialog(null)
|
|
1532
1749
|
}
|
|
1533
|
-
) : dialog?.kind === "provider" ? /* @__PURE__ */
|
|
1750
|
+
) : dialog?.kind === "provider" ? /* @__PURE__ */ jsx6(
|
|
1534
1751
|
SelectDialog,
|
|
1535
1752
|
{
|
|
1536
1753
|
title: "Provider",
|
|
@@ -1543,7 +1760,7 @@ function App(props) {
|
|
|
1543
1760
|
},
|
|
1544
1761
|
onClose: () => setDialog(null)
|
|
1545
1762
|
}
|
|
1546
|
-
) : dialog?.kind === "key" ? /* @__PURE__ */
|
|
1763
|
+
) : dialog?.kind === "key" ? /* @__PURE__ */ jsx6(
|
|
1547
1764
|
KeyDialog,
|
|
1548
1765
|
{
|
|
1549
1766
|
providerName,
|
|
@@ -1553,7 +1770,7 @@ function App(props) {
|
|
|
1553
1770
|
},
|
|
1554
1771
|
onClose: () => setDialog(null)
|
|
1555
1772
|
}
|
|
1556
|
-
) : approval ? /* @__PURE__ */
|
|
1773
|
+
) : approval ? /* @__PURE__ */ jsx6(
|
|
1557
1774
|
ApprovalPrompt,
|
|
1558
1775
|
{
|
|
1559
1776
|
request: approval,
|
|
@@ -1562,22 +1779,22 @@ function App(props) {
|
|
|
1562
1779
|
if (decision === "always") bus.emit("info", "Approved for the rest of this session.");
|
|
1563
1780
|
}
|
|
1564
1781
|
}
|
|
1565
|
-
) : running ? /* @__PURE__ */
|
|
1566
|
-
/* @__PURE__ */
|
|
1567
|
-
/* @__PURE__ */
|
|
1782
|
+
) : running ? /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
1783
|
+
/* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1784
|
+
/* @__PURE__ */ jsxs6(Text6, { color: "yellow", children: [
|
|
1568
1785
|
SPINNER_FRAMES[frame],
|
|
1569
1786
|
" "
|
|
1570
1787
|
] }),
|
|
1571
|
-
/* @__PURE__ */
|
|
1788
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "agent working... (Ctrl+C to exit)" })
|
|
1572
1789
|
] }),
|
|
1573
|
-
thinkingText ? /* @__PURE__ */
|
|
1574
|
-
/* @__PURE__ */
|
|
1575
|
-
/* @__PURE__ */
|
|
1576
|
-
/* @__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" })
|
|
1577
1794
|
] }) : null
|
|
1578
|
-
] }) : /* @__PURE__ */
|
|
1579
|
-
/* @__PURE__ */
|
|
1580
|
-
/* @__PURE__ */
|
|
1795
|
+
] }) : /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
1796
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", bold: true, children: "\u25B8 " }),
|
|
1797
|
+
/* @__PURE__ */ jsx6(
|
|
1581
1798
|
TextInput2,
|
|
1582
1799
|
{
|
|
1583
1800
|
value: taskInput,
|
|
@@ -1597,6 +1814,8 @@ var init_App = __esm({
|
|
|
1597
1814
|
init_events();
|
|
1598
1815
|
init_logging();
|
|
1599
1816
|
init_render();
|
|
1817
|
+
init_markdown();
|
|
1818
|
+
init_diff();
|
|
1600
1819
|
init_approval();
|
|
1601
1820
|
init_loop();
|
|
1602
1821
|
init_conversation();
|
|
@@ -1607,12 +1826,14 @@ var init_App = __esm({
|
|
|
1607
1826
|
init_KeyDialog();
|
|
1608
1827
|
init_package();
|
|
1609
1828
|
SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
1610
|
-
PROVIDER_NAMES = ["kimi", "glm", "zai", "zai-coding", "mock"];
|
|
1829
|
+
PROVIDER_NAMES = ["kimi", "glm", "zai", "zai-coding", "openrouter", "nvidia", "mock"];
|
|
1611
1830
|
PROVIDER_DESCRIPTIONS = {
|
|
1612
1831
|
kimi: "Moonshot \xB7 api.moonshot.ai",
|
|
1613
1832
|
glm: "Zhipu China \xB7 open.bigmodel.cn \xB7 separate account & keys",
|
|
1614
1833
|
zai: "Z.ai standard plan \xB7 api.z.ai/api/paas/v4",
|
|
1615
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",
|
|
1616
1837
|
mock: "offline testing \xB7 no network"
|
|
1617
1838
|
};
|
|
1618
1839
|
BANNER = ` __ __ \u{1F380}
|
|
@@ -1784,6 +2005,16 @@ function createKimiProvider(apiKey, model) {
|
|
|
1784
2005
|
});
|
|
1785
2006
|
}
|
|
1786
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
|
+
|
|
1787
2018
|
// src/models/mock.ts
|
|
1788
2019
|
var callCounter = 0;
|
|
1789
2020
|
var MockProvider = class {
|
|
@@ -1820,6 +2051,16 @@ var MockProvider = class {
|
|
|
1820
2051
|
}
|
|
1821
2052
|
};
|
|
1822
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
|
+
|
|
1823
2064
|
// src/models/zai.ts
|
|
1824
2065
|
function createZaiProvider(apiKey, model) {
|
|
1825
2066
|
return new OpenAICompatProvider({
|
|
@@ -1843,7 +2084,9 @@ var ENV_NAMES2 = {
|
|
|
1843
2084
|
kimi: "MENTEE_KIMI_API_KEY",
|
|
1844
2085
|
glm: "MENTEE_GLM_API_KEY",
|
|
1845
2086
|
zai: "MENTEE_ZAI_API_KEY",
|
|
1846
|
-
"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"
|
|
1847
2090
|
};
|
|
1848
2091
|
var MissingApiKeyError = class extends Error {
|
|
1849
2092
|
constructor(provider) {
|
|
@@ -1871,6 +2114,12 @@ function createProvider(provider, config, modelOverride) {
|
|
|
1871
2114
|
if (provider === "zai-coding") {
|
|
1872
2115
|
return createZaiCodingProvider(apiKey, model);
|
|
1873
2116
|
}
|
|
2117
|
+
if (provider === "openrouter") {
|
|
2118
|
+
return createOpenRouterProvider(apiKey, model);
|
|
2119
|
+
}
|
|
2120
|
+
if (provider === "nvidia") {
|
|
2121
|
+
return createNvidiaProvider(apiKey, model);
|
|
2122
|
+
}
|
|
1874
2123
|
return createGlmProvider(apiKey, model);
|
|
1875
2124
|
}
|
|
1876
2125
|
|
|
@@ -3287,12 +3536,12 @@ async function runConfigWizard() {
|
|
|
3287
3536
|
const config = loadConfig() ?? blankConfig();
|
|
3288
3537
|
config.keys = config.keys ?? {};
|
|
3289
3538
|
config.models = config.models ?? {};
|
|
3290
|
-
console.log("Providers: 1) Kimi (Moonshot) 2) GLM (Zhipu CN) 3) Z.ai (GLM international)");
|
|
3291
|
-
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";
|
|
3292
3541
|
const providerChoice = await ask(rl, "Default provider [1]", defaultChoice);
|
|
3293
|
-
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";
|
|
3294
3543
|
config.defaultProvider = provider;
|
|
3295
|
-
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";
|
|
3296
3545
|
const key = await ask(rl, `API key for ${provider}`);
|
|
3297
3546
|
if (key) config.keys[provider] = key;
|
|
3298
3547
|
const model = await ask(rl, `Model for ${provider}`, defaultModel);
|
|
@@ -3304,7 +3553,7 @@ Saved to ${configFilePath()}
|
|
|
3304
3553
|
if (config.keys[provider]) {
|
|
3305
3554
|
console.log("Testing connection...");
|
|
3306
3555
|
try {
|
|
3307
|
-
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);
|
|
3308
3557
|
await providerInstance.generate(
|
|
3309
3558
|
{
|
|
3310
3559
|
system: "You are a ping endpoint.",
|
|
@@ -3331,20 +3580,20 @@ Saved to ${configFilePath()}
|
|
|
3331
3580
|
}
|
|
3332
3581
|
|
|
3333
3582
|
// src/cli.tsx
|
|
3583
|
+
init_package();
|
|
3334
3584
|
import path9 from "path";
|
|
3335
|
-
import { jsx as
|
|
3336
|
-
var packageJson = { version: "0.1.0" };
|
|
3585
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
3337
3586
|
var program = new Command();
|
|
3338
|
-
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);
|
|
3339
3588
|
program.command("config").description("Configure providers, API keys, and models (interactive wizard)").action(async () => {
|
|
3340
3589
|
await runConfigWizard();
|
|
3341
3590
|
});
|
|
3342
|
-
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) => {
|
|
3343
3592
|
const task = taskParts.join(" ").trim();
|
|
3344
3593
|
const config = loadConfig();
|
|
3345
3594
|
const providerName = options.provider ?? config?.defaultProvider ?? "zai-coding";
|
|
3346
|
-
if (!["kimi", "glm", "zai", "zai-coding", "mock"].includes(providerName)) {
|
|
3347
|
-
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.`));
|
|
3348
3597
|
process.exit(1);
|
|
3349
3598
|
}
|
|
3350
3599
|
const tools = new ToolRegistry(createDefaultTools());
|
|
@@ -3389,7 +3638,7 @@ program.argument("[task...]", "the software task to perform (omit to type it int
|
|
|
3389
3638
|
const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
|
|
3390
3639
|
const { render } = await import("ink");
|
|
3391
3640
|
const { waitUntilExit } = render(
|
|
3392
|
-
/* @__PURE__ */
|
|
3641
|
+
/* @__PURE__ */ jsx7(
|
|
3393
3642
|
App2,
|
|
3394
3643
|
{
|
|
3395
3644
|
initialTask: task || void 0,
|
package/package.json
CHANGED