@ai-setting/roy-agent-cli 1.6.15 → 1.6.17
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/bin/roy-agent.js +574 -110
- package/dist/index.js +574 -110
- package/dist/roy-agent-linux-x64/bin/roy-agent +0 -0
- package/package.json +1 -1
package/dist/bin/roy-agent.js
CHANGED
|
@@ -904,7 +904,7 @@ var init_status_bar = __esm(() => {
|
|
|
904
904
|
var require_package = __commonJS((exports, module) => {
|
|
905
905
|
module.exports = {
|
|
906
906
|
name: "@ai-setting/roy-agent-cli",
|
|
907
|
-
version: "1.6.
|
|
907
|
+
version: "1.6.17",
|
|
908
908
|
type: "module",
|
|
909
909
|
description: "CLI for roy-agent - Non-interactive command execution",
|
|
910
910
|
main: "./dist/index.js",
|
|
@@ -1066,10 +1066,187 @@ function execAsync(cmd, args) {
|
|
|
1066
1066
|
}
|
|
1067
1067
|
var init_clipboard_helper = () => {};
|
|
1068
1068
|
|
|
1069
|
-
// src/commands/
|
|
1069
|
+
// src/commands/ui/commands-registry.ts
|
|
1070
|
+
function filterCommands(query) {
|
|
1071
|
+
const q = query.trim().replace(/^\/+/, "").toLowerCase();
|
|
1072
|
+
if (q === "") {
|
|
1073
|
+
return [...COMMANDS];
|
|
1074
|
+
}
|
|
1075
|
+
return COMMANDS.filter((c) => {
|
|
1076
|
+
const cmdName = c.cmd.replace(/^\/+/, "").toLowerCase();
|
|
1077
|
+
if (cmdName.startsWith(q))
|
|
1078
|
+
return true;
|
|
1079
|
+
if (cmdName.includes(q))
|
|
1080
|
+
return true;
|
|
1081
|
+
if (c.aliases) {
|
|
1082
|
+
for (const a of c.aliases) {
|
|
1083
|
+
if (a.toLowerCase().startsWith(q))
|
|
1084
|
+
return true;
|
|
1085
|
+
if (a.toLowerCase().includes(q))
|
|
1086
|
+
return true;
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
return false;
|
|
1090
|
+
});
|
|
1091
|
+
}
|
|
1092
|
+
var COMMANDS, MAX_POPUP_ITEMS = 8;
|
|
1093
|
+
var init_commands_registry = __esm(() => {
|
|
1094
|
+
COMMANDS = [
|
|
1095
|
+
{ cmd: "/help", desc: "Show all commands", category: "general", aliases: ["h"] },
|
|
1096
|
+
{ cmd: "/quit", desc: "Exit interactive mode", category: "general", aliases: ["q", "exit"] },
|
|
1097
|
+
{ cmd: "/init", desc: "Create memory file", category: "memory" },
|
|
1098
|
+
{ cmd: "/memory", desc: "Show memory", category: "memory" },
|
|
1099
|
+
{ cmd: "/model", desc: "Switch model", category: "model" },
|
|
1100
|
+
{ cmd: "/compact", desc: "Compress context", category: "session", aliases: ["c"] },
|
|
1101
|
+
{ cmd: "/sessions", desc: "List sessions", category: "session", aliases: ["s"] },
|
|
1102
|
+
{ cmd: "/attach", desc: "Add file/URL to attach", category: "attachment" },
|
|
1103
|
+
{ cmd: "/list", desc: "List attachments", category: "attachment" },
|
|
1104
|
+
{ cmd: "/paste", desc: "Paste from clipboard", category: "attachment" },
|
|
1105
|
+
{ cmd: "/clear", desc: "Clear attach list", category: "attachment", aliases: ["cls"] },
|
|
1106
|
+
{ cmd: "/status", desc: "Show session status", category: "system", aliases: ["st"] },
|
|
1107
|
+
{ cmd: "/abort", desc: "Abort in-flight request", category: "system" }
|
|
1108
|
+
];
|
|
1109
|
+
});
|
|
1110
|
+
|
|
1111
|
+
// src/commands/ui/slash-command-popup.tsx
|
|
1070
1112
|
import * as React from "react";
|
|
1071
|
-
import { Box, Text } from "ink";
|
|
1113
|
+
import { Box, Text, useInput } from "ink";
|
|
1114
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
1115
|
+
function clampSelectedIndex(index, filteredLength) {
|
|
1116
|
+
if (filteredLength === 0)
|
|
1117
|
+
return 0;
|
|
1118
|
+
return Math.max(0, Math.min(filteredLength - 1, index));
|
|
1119
|
+
}
|
|
1120
|
+
var CommandRow, SlashCommandPopup;
|
|
1121
|
+
var init_slash_command_popup = __esm(() => {
|
|
1122
|
+
init_commands_registry();
|
|
1123
|
+
CommandRow = React.memo(function CommandRow2({
|
|
1124
|
+
cmd,
|
|
1125
|
+
isSelected
|
|
1126
|
+
}) {
|
|
1127
|
+
const cmdPadded = cmd.cmd.padEnd(12, " ");
|
|
1128
|
+
if (isSelected) {
|
|
1129
|
+
return /* @__PURE__ */ jsxDEV(Text, {
|
|
1130
|
+
inverse: true,
|
|
1131
|
+
children: [
|
|
1132
|
+
"▶ ",
|
|
1133
|
+
cmdPadded,
|
|
1134
|
+
cmd.desc
|
|
1135
|
+
]
|
|
1136
|
+
}, cmd.cmd, true, undefined, this);
|
|
1137
|
+
}
|
|
1138
|
+
return /* @__PURE__ */ jsxDEV(Text, {
|
|
1139
|
+
children: [
|
|
1140
|
+
" ",
|
|
1141
|
+
cmdPadded,
|
|
1142
|
+
/* @__PURE__ */ jsxDEV(Text, {
|
|
1143
|
+
color: "gray",
|
|
1144
|
+
children: cmd.desc
|
|
1145
|
+
}, undefined, false, undefined, this)
|
|
1146
|
+
]
|
|
1147
|
+
}, cmd.cmd, true, undefined, this);
|
|
1148
|
+
});
|
|
1149
|
+
SlashCommandPopup = React.memo(function SlashCommandPopup2({
|
|
1150
|
+
query,
|
|
1151
|
+
selectedIndex: externalSelectedIndex,
|
|
1152
|
+
onIndexChange,
|
|
1153
|
+
onSelect,
|
|
1154
|
+
onClose
|
|
1155
|
+
}) {
|
|
1156
|
+
const filtered = React.useMemo(() => filterCommands(query), [query]);
|
|
1157
|
+
const [internalSelectedIndex, setInternalSelectedIndex] = React.useState(() => externalSelectedIndex ?? 0);
|
|
1158
|
+
React.useEffect(() => {
|
|
1159
|
+
if (externalSelectedIndex !== undefined && externalSelectedIndex !== internalSelectedIndex) {
|
|
1160
|
+
setInternalSelectedIndex(externalSelectedIndex);
|
|
1161
|
+
}
|
|
1162
|
+
}, [externalSelectedIndex, internalSelectedIndex]);
|
|
1163
|
+
const updateIndex = React.useCallback((next) => {
|
|
1164
|
+
setInternalSelectedIndex(next);
|
|
1165
|
+
onIndexChange?.(next);
|
|
1166
|
+
}, [onIndexChange]);
|
|
1167
|
+
React.useEffect(() => {
|
|
1168
|
+
if (filtered.length === 0)
|
|
1169
|
+
return;
|
|
1170
|
+
if (internalSelectedIndex >= filtered.length) {
|
|
1171
|
+
updateIndex(0);
|
|
1172
|
+
}
|
|
1173
|
+
}, [filtered, internalSelectedIndex, updateIndex]);
|
|
1174
|
+
useInput((input, key) => {
|
|
1175
|
+
if (key.upArrow) {
|
|
1176
|
+
if (filtered.length === 0)
|
|
1177
|
+
return;
|
|
1178
|
+
updateIndex((internalSelectedIndex - 1 + filtered.length) % filtered.length);
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
if (key.downArrow) {
|
|
1182
|
+
if (filtered.length === 0)
|
|
1183
|
+
return;
|
|
1184
|
+
updateIndex((internalSelectedIndex + 1) % filtered.length);
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1187
|
+
if (key.return && !key.meta && !key.shift && !key.ctrl) {
|
|
1188
|
+
const cmd = filtered[internalSelectedIndex];
|
|
1189
|
+
if (cmd && onSelect) {
|
|
1190
|
+
onSelect(cmd);
|
|
1191
|
+
}
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
if (key.tab) {
|
|
1195
|
+
const cmd = filtered[internalSelectedIndex];
|
|
1196
|
+
if (cmd && onSelect) {
|
|
1197
|
+
onSelect(cmd);
|
|
1198
|
+
}
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
if (key.escape) {
|
|
1202
|
+
if (onClose) {
|
|
1203
|
+
onClose();
|
|
1204
|
+
}
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1207
|
+
}, { isActive: filtered.length > 0 });
|
|
1208
|
+
if (filtered.length === 0) {
|
|
1209
|
+
return null;
|
|
1210
|
+
}
|
|
1211
|
+
const selectedIndex = Math.max(0, Math.min(filtered.length - 1, internalSelectedIndex));
|
|
1212
|
+
const filteredLength = filtered.length;
|
|
1213
|
+
const scrollOffset = filteredLength <= MAX_POPUP_ITEMS ? 0 : Math.max(0, Math.min(filteredLength - MAX_POPUP_ITEMS, selectedIndex - 3));
|
|
1214
|
+
const visible = filtered.slice(scrollOffset, scrollOffset + MAX_POPUP_ITEMS);
|
|
1215
|
+
const hiddenBefore = scrollOffset;
|
|
1216
|
+
const hiddenAfter = filteredLength - (scrollOffset + visible.length);
|
|
1217
|
+
const windowedIndex = selectedIndex - scrollOffset;
|
|
1218
|
+
return /* @__PURE__ */ jsxDEV(Box, {
|
|
1219
|
+
flexDirection: "column",
|
|
1220
|
+
borderStyle: "single",
|
|
1221
|
+
borderColor: "cyan",
|
|
1222
|
+
paddingX: 1,
|
|
1223
|
+
marginBottom: 0,
|
|
1224
|
+
children: [
|
|
1225
|
+
/* @__PURE__ */ jsxDEV(Text, {
|
|
1226
|
+
color: "gray",
|
|
1227
|
+
dimColor: true,
|
|
1228
|
+
children: [
|
|
1229
|
+
"Commands (",
|
|
1230
|
+
filteredLength,
|
|
1231
|
+
")",
|
|
1232
|
+
hiddenBefore > 0 ? ` · ${hiddenBefore} more ↑` : "",
|
|
1233
|
+
hiddenAfter > 0 ? ` · ${hiddenAfter} more ↓` : ""
|
|
1234
|
+
]
|
|
1235
|
+
}, undefined, true, undefined, this),
|
|
1236
|
+
visible.map((cmd, i) => /* @__PURE__ */ jsxDEV(CommandRow, {
|
|
1237
|
+
cmd,
|
|
1238
|
+
isSelected: i === windowedIndex
|
|
1239
|
+
}, cmd.cmd, false, undefined, this))
|
|
1240
|
+
]
|
|
1241
|
+
}, undefined, true, undefined, this);
|
|
1242
|
+
});
|
|
1243
|
+
});
|
|
1244
|
+
|
|
1245
|
+
// src/commands/markdown-renderer.tsx
|
|
1246
|
+
import * as React2 from "react";
|
|
1247
|
+
import { Box as Box2, Text as Text2 } from "ink";
|
|
1072
1248
|
import chalk6 from "chalk";
|
|
1249
|
+
import { wrapFunction } from "@ai-setting/roy-agent-core";
|
|
1073
1250
|
function parseInline(text, keyPrefix) {
|
|
1074
1251
|
const nodes = [];
|
|
1075
1252
|
const pattern = /(`([^`]+)`)|(\*\*([^*]+)\*\*)|(\*([^*]+)\*)|(~~([^~]+)~~)|(\[([^\]]+)\]\(([^)]+)\))/g;
|
|
@@ -1078,30 +1255,144 @@ function parseInline(text, keyPrefix) {
|
|
|
1078
1255
|
let counter = 0;
|
|
1079
1256
|
while ((match = pattern.exec(text)) !== null) {
|
|
1080
1257
|
if (match.index > lastIndex) {
|
|
1081
|
-
nodes.push(
|
|
1258
|
+
nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-t-${counter++}` }, text.slice(lastIndex, match.index)));
|
|
1082
1259
|
}
|
|
1083
1260
|
if (match[1] !== undefined) {
|
|
1084
|
-
nodes.push(
|
|
1261
|
+
nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-c-${counter++}`, color: "white", backgroundColor: "gray" }, ` ${match[2]} `));
|
|
1085
1262
|
} else if (match[3] !== undefined) {
|
|
1086
|
-
nodes.push(
|
|
1263
|
+
nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-b-${counter++}`, color: "yellow", bold: true }, match[4]));
|
|
1087
1264
|
} else if (match[5] !== undefined) {
|
|
1088
|
-
nodes.push(
|
|
1265
|
+
nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-i-${counter++}`, color: "yellow" }, match[6]));
|
|
1089
1266
|
} else if (match[7] !== undefined) {
|
|
1090
|
-
nodes.push(
|
|
1267
|
+
nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-s-${counter++}`, dimColor: true }, match[8]));
|
|
1091
1268
|
} else if (match[9] !== undefined) {
|
|
1092
|
-
nodes.push(
|
|
1269
|
+
nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-l-${counter++}`, color: "cyan", underline: true }, match[10]), React2.createElement(Text2, { key: `${keyPrefix}-u-${counter++}`, color: "blue", dimColor: true }, ` (${match[11]})`));
|
|
1093
1270
|
}
|
|
1094
1271
|
lastIndex = pattern.lastIndex;
|
|
1095
1272
|
}
|
|
1096
1273
|
if (lastIndex < text.length) {
|
|
1097
|
-
nodes.push(
|
|
1274
|
+
nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-e-${counter++}` }, text.slice(lastIndex)));
|
|
1098
1275
|
}
|
|
1099
1276
|
if (nodes.length === 0) {
|
|
1100
|
-
nodes.push(
|
|
1277
|
+
nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-all` }, text));
|
|
1101
1278
|
}
|
|
1102
1279
|
return nodes;
|
|
1103
1280
|
}
|
|
1104
|
-
function
|
|
1281
|
+
function splitTableRow(rawLine) {
|
|
1282
|
+
let s = rawLine.trim();
|
|
1283
|
+
if (s.startsWith("|"))
|
|
1284
|
+
s = s.slice(1);
|
|
1285
|
+
if (s.endsWith("|") && !s.endsWith("\\|"))
|
|
1286
|
+
s = s.slice(0, -1);
|
|
1287
|
+
return s.split("|").map((c) => c.trim());
|
|
1288
|
+
}
|
|
1289
|
+
function isTableSeparator(line) {
|
|
1290
|
+
const trimmed = line.trim();
|
|
1291
|
+
if (!trimmed.includes("|"))
|
|
1292
|
+
return false;
|
|
1293
|
+
const cells = splitTableRow(trimmed);
|
|
1294
|
+
if (cells.length === 0)
|
|
1295
|
+
return false;
|
|
1296
|
+
return cells.every((c) => /^:?\s*-{1,}\s*:?$/.test(c));
|
|
1297
|
+
}
|
|
1298
|
+
function parseAlignments(sepCells) {
|
|
1299
|
+
return sepCells.map((c) => {
|
|
1300
|
+
const t = c.trim();
|
|
1301
|
+
const startsColon = t.startsWith(":");
|
|
1302
|
+
const endsColon = t.endsWith(":");
|
|
1303
|
+
if (startsColon && endsColon)
|
|
1304
|
+
return "center";
|
|
1305
|
+
if (endsColon)
|
|
1306
|
+
return "right";
|
|
1307
|
+
if (startsColon)
|
|
1308
|
+
return "left";
|
|
1309
|
+
return "left";
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
function padCell(content, width, align) {
|
|
1313
|
+
const len = content.length;
|
|
1314
|
+
if (len >= width)
|
|
1315
|
+
return content;
|
|
1316
|
+
const totalPad = width - len;
|
|
1317
|
+
if (align === "right")
|
|
1318
|
+
return " ".repeat(totalPad) + content;
|
|
1319
|
+
if (align === "center") {
|
|
1320
|
+
const left = Math.floor(totalPad / 2);
|
|
1321
|
+
const right = totalPad - left;
|
|
1322
|
+
return " ".repeat(left) + content + " ".repeat(right);
|
|
1323
|
+
}
|
|
1324
|
+
return content + " ".repeat(totalPad);
|
|
1325
|
+
}
|
|
1326
|
+
function parseTableStart(lines, i) {
|
|
1327
|
+
const header = lines[i] ?? "";
|
|
1328
|
+
const sep = lines[i + 1] ?? "";
|
|
1329
|
+
if (!header.trim().startsWith("|"))
|
|
1330
|
+
return false;
|
|
1331
|
+
if (!header.trim().includes("|"))
|
|
1332
|
+
return false;
|
|
1333
|
+
if (!isTableSeparator(sep))
|
|
1334
|
+
return false;
|
|
1335
|
+
return true;
|
|
1336
|
+
}
|
|
1337
|
+
function parseTableBlock(lines, startIndex) {
|
|
1338
|
+
if (!parseTableStart(lines, startIndex))
|
|
1339
|
+
return null;
|
|
1340
|
+
const header = splitTableRow(lines[startIndex] ?? "");
|
|
1341
|
+
const alignments = parseAlignments(splitTableRow(lines[startIndex + 1] ?? ""));
|
|
1342
|
+
const rows = [];
|
|
1343
|
+
let i = startIndex + 2;
|
|
1344
|
+
while (i < lines.length) {
|
|
1345
|
+
const ln = lines[i] ?? "";
|
|
1346
|
+
if (ln.trim() === "")
|
|
1347
|
+
break;
|
|
1348
|
+
if (!ln.trim().startsWith("|"))
|
|
1349
|
+
break;
|
|
1350
|
+
rows.push(splitTableRow(ln));
|
|
1351
|
+
i++;
|
|
1352
|
+
}
|
|
1353
|
+
return { header, rows, alignments, endIndex: i };
|
|
1354
|
+
}
|
|
1355
|
+
function renderTableBlock(tbl, key) {
|
|
1356
|
+
const colCount = Math.max(tbl.header.length, ...tbl.rows.map((r) => r.length));
|
|
1357
|
+
const widths = [];
|
|
1358
|
+
for (let c = 0;c < colCount; c++) {
|
|
1359
|
+
const headerW = (tbl.header[c] ?? "").length;
|
|
1360
|
+
let dataW = 0;
|
|
1361
|
+
for (const r of tbl.rows) {
|
|
1362
|
+
const cell = r[c] ?? "";
|
|
1363
|
+
if (cell.length > dataW)
|
|
1364
|
+
dataW = cell.length;
|
|
1365
|
+
}
|
|
1366
|
+
widths.push(Math.max(headerW, dataW));
|
|
1367
|
+
}
|
|
1368
|
+
const alignments = [];
|
|
1369
|
+
for (let c = 0;c < colCount; c++) {
|
|
1370
|
+
alignments.push(tbl.alignments[c] ?? "left");
|
|
1371
|
+
}
|
|
1372
|
+
const renderRow = (cells, rowIdx) => {
|
|
1373
|
+
const cellNodes = [];
|
|
1374
|
+
for (let c = 0;c < colCount; c++) {
|
|
1375
|
+
const raw = cells[c] ?? "";
|
|
1376
|
+
const w = widths[c] ?? raw.length;
|
|
1377
|
+
const align = alignments[c] ?? "left";
|
|
1378
|
+
const padded = padCell(raw, w, align);
|
|
1379
|
+
cellNodes.push(React2.createElement(Box2, { key: `tbl-${rowIdx}-c${c}`, flexDirection: "row" }, ...parseInline(padded, `tbl-${rowIdx}-c${c}`)));
|
|
1380
|
+
if (c < colCount - 1) {
|
|
1381
|
+
cellNodes.push(React2.createElement(Text2, { key: `tbl-${rowIdx}-sep${c}`, color: "gray" }, " │ "));
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
return React2.createElement(Box2, { key: `tbl-${rowIdx}`, flexDirection: "row" }, React2.createElement(Text2, { color: "gray" }, "│ "), ...cellNodes, React2.createElement(Text2, { color: "gray" }, " │"));
|
|
1385
|
+
};
|
|
1386
|
+
const children = [];
|
|
1387
|
+
children.push(renderRow(tbl.header, 0));
|
|
1388
|
+
const sepLine = "├" + widths.map((w) => "─".repeat(w + 2)).join("┼") + "┤";
|
|
1389
|
+
children.push(React2.createElement(Text2, { key: "tbl-sep", color: "gray" }, sepLine));
|
|
1390
|
+
tbl.rows.forEach((r, ri) => {
|
|
1391
|
+
children.push(renderRow(r, ri + 1));
|
|
1392
|
+
});
|
|
1393
|
+
return React2.createElement(Box2, { key, flexDirection: "column", marginY: 1 }, ...children);
|
|
1394
|
+
}
|
|
1395
|
+
function renderMarkdownLegacyImpl(content) {
|
|
1105
1396
|
const lines = content.split(`
|
|
1106
1397
|
`);
|
|
1107
1398
|
const blocks = [];
|
|
@@ -1117,19 +1408,19 @@ function renderMarkdown(content) {
|
|
|
1117
1408
|
i++;
|
|
1118
1409
|
}
|
|
1119
1410
|
i++;
|
|
1120
|
-
blocks.push(
|
|
1411
|
+
blocks.push(React2.createElement(Box2, {
|
|
1121
1412
|
key: `blk-code-${blockKey++}`,
|
|
1122
1413
|
flexDirection: "column",
|
|
1123
1414
|
borderStyle: "single",
|
|
1124
1415
|
borderColor: "gray",
|
|
1125
1416
|
paddingX: 1,
|
|
1126
1417
|
marginY: 1
|
|
1127
|
-
},
|
|
1418
|
+
}, React2.createElement(Text2, { color: "white" }, codeLines.length === 0 ? " " : codeLines.join(`
|
|
1128
1419
|
`))));
|
|
1129
1420
|
continue;
|
|
1130
1421
|
}
|
|
1131
1422
|
if (/^(-{3,}|\*{3,})$/.test(line.trim())) {
|
|
1132
|
-
blocks.push(
|
|
1423
|
+
blocks.push(React2.createElement(Box2, { key: `blk-hr-${blockKey++}`, marginY: 1 }, React2.createElement(Text2, { color: "gray" }, "─".repeat(50))));
|
|
1133
1424
|
i++;
|
|
1134
1425
|
continue;
|
|
1135
1426
|
}
|
|
@@ -1139,10 +1430,10 @@ function renderMarkdown(content) {
|
|
|
1139
1430
|
const text = headingMatch[2];
|
|
1140
1431
|
if (level === 1) {
|
|
1141
1432
|
const styled = chalk6.cyan.bold.underline(`▌ ${text}`);
|
|
1142
|
-
blocks.push(
|
|
1433
|
+
blocks.push(React2.createElement(Box2, { key: `blk-h1-${blockKey++}`, marginY: 1 }, React2.createElement(Text2, {}, styled)));
|
|
1143
1434
|
} else if (level === 2) {
|
|
1144
1435
|
const styled = chalk6.green.bold(`▶ ${text}`);
|
|
1145
|
-
blocks.push(
|
|
1436
|
+
blocks.push(React2.createElement(Box2, { key: `blk-h2-${blockKey++}`, marginY: 1 }, React2.createElement(Text2, {}, styled)));
|
|
1146
1437
|
} else {
|
|
1147
1438
|
const colors = {
|
|
1148
1439
|
3: "yellow",
|
|
@@ -1152,7 +1443,7 @@ function renderMarkdown(content) {
|
|
|
1152
1443
|
};
|
|
1153
1444
|
const color = colors[level] ?? "white";
|
|
1154
1445
|
const prefix = "▶".repeat(level - 1) + " ";
|
|
1155
|
-
blocks.push(
|
|
1446
|
+
blocks.push(React2.createElement(Box2, { key: `blk-h-${blockKey++}`, marginY: 1 }, React2.createElement(Text2, { color, bold: true }, `${prefix}${text}`)));
|
|
1156
1447
|
}
|
|
1157
1448
|
i++;
|
|
1158
1449
|
continue;
|
|
@@ -1163,7 +1454,7 @@ function renderMarkdown(content) {
|
|
|
1163
1454
|
quoteLines.push((lines[i] ?? "").replace(/^>\s?/, ""));
|
|
1164
1455
|
i++;
|
|
1165
1456
|
}
|
|
1166
|
-
blocks.push(
|
|
1457
|
+
blocks.push(React2.createElement(Box2, {
|
|
1167
1458
|
key: `blk-q-${blockKey++}`,
|
|
1168
1459
|
flexDirection: "column",
|
|
1169
1460
|
marginLeft: 2,
|
|
@@ -1174,7 +1465,7 @@ function renderMarkdown(content) {
|
|
|
1174
1465
|
borderRight: false,
|
|
1175
1466
|
borderBottom: false,
|
|
1176
1467
|
paddingLeft: 1
|
|
1177
|
-
}, ...quoteLines.map((ql, qi) =>
|
|
1468
|
+
}, ...quoteLines.map((ql, qi) => React2.createElement(Box2, { key: `q-${qi}` }, React2.createElement(Text2, { color: "gray", dimColor: true }, ql)))));
|
|
1178
1469
|
continue;
|
|
1179
1470
|
}
|
|
1180
1471
|
if (/^[-*]\s+/.test(line)) {
|
|
@@ -1183,7 +1474,7 @@ function renderMarkdown(content) {
|
|
|
1183
1474
|
items.push((lines[i] ?? "").replace(/^[-*]\s+/, ""));
|
|
1184
1475
|
i++;
|
|
1185
1476
|
}
|
|
1186
|
-
blocks.push(
|
|
1477
|
+
blocks.push(React2.createElement(Box2, { key: `blk-ul-${blockKey++}`, flexDirection: "column", marginLeft: 2 }, ...items.map((it, ii) => React2.createElement(Box2, { key: `ul-${ii}` }, React2.createElement(Text2, { color: "yellow", bold: true }, "▸ "), ...parseInline(it, `ul-${ii}`)))));
|
|
1187
1478
|
continue;
|
|
1188
1479
|
}
|
|
1189
1480
|
if (/^\d+\.\s+/.test(line)) {
|
|
@@ -1192,9 +1483,17 @@ function renderMarkdown(content) {
|
|
|
1192
1483
|
items.push((lines[i] ?? "").replace(/^\d+\.\s+/, ""));
|
|
1193
1484
|
i++;
|
|
1194
1485
|
}
|
|
1195
|
-
blocks.push(
|
|
1486
|
+
blocks.push(React2.createElement(Box2, { key: `blk-ol-${blockKey++}`, flexDirection: "column", marginLeft: 2 }, ...items.map((it, ii) => React2.createElement(Box2, { key: `ol-${ii}` }, React2.createElement(Text2, { color: "cyan", bold: true }, `${(ii + 1).toString().padStart(2, " ")}. `), ...parseInline(it, `ol-${ii}`)))));
|
|
1196
1487
|
continue;
|
|
1197
1488
|
}
|
|
1489
|
+
if (parseTableStart(lines, i)) {
|
|
1490
|
+
const tbl = parseTableBlock(lines, i);
|
|
1491
|
+
if (tbl) {
|
|
1492
|
+
i = tbl.endIndex;
|
|
1493
|
+
blocks.push(renderTableBlock(tbl, `blk-table-${blockKey++}`));
|
|
1494
|
+
continue;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1198
1497
|
if (line.trim() === "") {
|
|
1199
1498
|
i++;
|
|
1200
1499
|
continue;
|
|
@@ -1205,11 +1504,22 @@ function renderMarkdown(content) {
|
|
|
1205
1504
|
i++;
|
|
1206
1505
|
}
|
|
1207
1506
|
const paraText = paraLines.join(" ");
|
|
1208
|
-
blocks.push(
|
|
1507
|
+
blocks.push(React2.createElement(Box2, { key: `blk-p-${blockKey++}`, marginY: 0 }, ...parseInline(paraText, `p-${blockKey}`)));
|
|
1209
1508
|
}
|
|
1210
1509
|
return blocks;
|
|
1211
1510
|
}
|
|
1212
|
-
var
|
|
1511
|
+
var renderMarkdown;
|
|
1512
|
+
var init_markdown_renderer2 = __esm(() => {
|
|
1513
|
+
renderMarkdown = wrapFunction(renderMarkdownLegacyImpl, "markdown.render", {
|
|
1514
|
+
recordParams: true,
|
|
1515
|
+
recordResult: false,
|
|
1516
|
+
paramFilter: (args) => ({
|
|
1517
|
+
"content.length": (args?.[0] && typeof args[0] === "string" ? args[0].length : 0) ?? 0,
|
|
1518
|
+
"content.first-line": (args?.[0] && typeof args[0] === "string" ? args[0].split(`
|
|
1519
|
+
`)[0]?.slice(0, 60) : "") ?? ""
|
|
1520
|
+
})
|
|
1521
|
+
});
|
|
1522
|
+
});
|
|
1213
1523
|
|
|
1214
1524
|
// src/commands/repl-ink.tsx
|
|
1215
1525
|
var exports_repl_ink = {};
|
|
@@ -1218,10 +1528,10 @@ __export(exports_repl_ink, {
|
|
|
1218
1528
|
REPLInk: () => REPLInk,
|
|
1219
1529
|
MultilineInput: () => MultilineInput
|
|
1220
1530
|
});
|
|
1221
|
-
import * as
|
|
1222
|
-
import { Box as
|
|
1531
|
+
import * as React3 from "react";
|
|
1532
|
+
import { Box as Box3, Text as Text3, Static, useApp, useInput as useInput2 } from "ink";
|
|
1223
1533
|
import { createLogger as createLogger4 } from "@ai-setting/roy-agent-core";
|
|
1224
|
-
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
1534
|
+
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
1225
1535
|
function REPLInk(props) {
|
|
1226
1536
|
const {
|
|
1227
1537
|
initialContext,
|
|
@@ -1234,19 +1544,55 @@ function REPLInk(props) {
|
|
|
1234
1544
|
onEscape
|
|
1235
1545
|
} = props;
|
|
1236
1546
|
const { exit: appExit } = useApp();
|
|
1237
|
-
const [messages, setMessages] =
|
|
1238
|
-
|
|
1239
|
-
|
|
1547
|
+
const [messages, setMessages] = React3.useState(() => [
|
|
1548
|
+
{
|
|
1549
|
+
role: "system",
|
|
1550
|
+
kind: "welcome",
|
|
1551
|
+
content: buildWelcomeCardText(initialContext)
|
|
1552
|
+
},
|
|
1553
|
+
...initialMessages
|
|
1554
|
+
]);
|
|
1555
|
+
const [mode, setMode] = React3.useState(initialMode);
|
|
1556
|
+
const [statusBarCtx, setStatusBarCtxState] = React3.useState({
|
|
1240
1557
|
mode: initialMode,
|
|
1241
1558
|
cwd: initialStatusBarCtx.cwd ?? initialContext.cwd,
|
|
1242
1559
|
gitBranch: initialStatusBarCtx.gitBranch,
|
|
1243
1560
|
model: initialStatusBarCtx.model ?? initialContext.model
|
|
1244
1561
|
});
|
|
1245
|
-
const
|
|
1246
|
-
const
|
|
1247
|
-
const
|
|
1248
|
-
|
|
1249
|
-
|
|
1562
|
+
const [inputValue, setInputValue] = React3.useState("");
|
|
1563
|
+
const [popupIndex, setPopupIndex] = React3.useState(0);
|
|
1564
|
+
const filteredCmds = React3.useMemo(() => {
|
|
1565
|
+
if (!/^\/\S*$/.test(inputValue))
|
|
1566
|
+
return [];
|
|
1567
|
+
return filterCommands(inputValue);
|
|
1568
|
+
}, [inputValue]);
|
|
1569
|
+
const showPopup = filteredCmds.length > 0;
|
|
1570
|
+
React3.useEffect(() => {
|
|
1571
|
+
setPopupIndex(0);
|
|
1572
|
+
}, [filteredCmds]);
|
|
1573
|
+
const safePopupIndex = clampSelectedIndex(popupIndex, filteredCmds.length);
|
|
1574
|
+
const handlePopupSelect = React3.useCallback((cmd) => {
|
|
1575
|
+
multilineInputRef.current?.setBuffer(cmd.cmd + " ");
|
|
1576
|
+
setInputValue(cmd.cmd + " ");
|
|
1577
|
+
}, []);
|
|
1578
|
+
const handlePopupClose = React3.useCallback(() => {
|
|
1579
|
+
const current = multilineInputRef.current?.getBuffer() ?? "";
|
|
1580
|
+
const stripped = current.replace(/^\/+/, "");
|
|
1581
|
+
multilineInputRef.current?.setBuffer(stripped);
|
|
1582
|
+
setInputValue(stripped);
|
|
1583
|
+
}, []);
|
|
1584
|
+
const handlePopupIndexChange = React3.useCallback((idx) => {
|
|
1585
|
+
setPopupIndex(idx);
|
|
1586
|
+
}, []);
|
|
1587
|
+
const streamingIndexRef = React3.useRef(-1);
|
|
1588
|
+
const lastFlushTsRef = React3.useRef(0);
|
|
1589
|
+
const STALE_STREAM_THRESHOLD_MS = 1000;
|
|
1590
|
+
const multilineInputRef = React3.useRef(null);
|
|
1591
|
+
const lastEscapeTsRef = React3.useRef(0);
|
|
1592
|
+
const pendingDeltaRef = React3.useRef("");
|
|
1593
|
+
const throttleTimerRef = React3.useRef(null);
|
|
1594
|
+
const isFirstDeltaInStreamRef = React3.useRef(true);
|
|
1595
|
+
const flushStreamingDelta = React3.useCallback(() => {
|
|
1250
1596
|
const delta = pendingDeltaRef.current;
|
|
1251
1597
|
pendingDeltaRef.current = "";
|
|
1252
1598
|
throttleTimerRef.current = null;
|
|
@@ -1260,6 +1606,11 @@ function REPLInk(props) {
|
|
|
1260
1606
|
break;
|
|
1261
1607
|
}
|
|
1262
1608
|
}
|
|
1609
|
+
if (idx !== -1 && Date.now() - lastFlushTsRef.current > STALE_STREAM_THRESHOLD_MS) {
|
|
1610
|
+
const updated2 = [...msgs];
|
|
1611
|
+
updated2[idx] = { ...updated2[idx], streaming: false };
|
|
1612
|
+
idx = -1;
|
|
1613
|
+
}
|
|
1263
1614
|
if (idx === -1) {
|
|
1264
1615
|
streamingIndexRef.current = msgs.length;
|
|
1265
1616
|
return [...msgs, { role: "assistant", content: delta, streaming: true }];
|
|
@@ -1268,8 +1619,9 @@ function REPLInk(props) {
|
|
|
1268
1619
|
updated[idx] = { ...updated[idx], content: updated[idx].content + delta };
|
|
1269
1620
|
return updated;
|
|
1270
1621
|
});
|
|
1622
|
+
lastFlushTsRef.current = Date.now();
|
|
1271
1623
|
}, []);
|
|
1272
|
-
|
|
1624
|
+
React3.useEffect(() => {
|
|
1273
1625
|
return () => {
|
|
1274
1626
|
if (throttleTimerRef.current !== null) {
|
|
1275
1627
|
clearTimeout(throttleTimerRef.current);
|
|
@@ -1277,8 +1629,8 @@ function REPLInk(props) {
|
|
|
1277
1629
|
}
|
|
1278
1630
|
};
|
|
1279
1631
|
}, []);
|
|
1280
|
-
const apiRef =
|
|
1281
|
-
|
|
1632
|
+
const apiRef = React3.useRef(null);
|
|
1633
|
+
React3.useEffect(() => {
|
|
1282
1634
|
const api = {
|
|
1283
1635
|
appendMessage: (msg) => {
|
|
1284
1636
|
setMessages((msgs) => [...msgs, msg]);
|
|
@@ -1288,7 +1640,12 @@ function REPLInk(props) {
|
|
|
1288
1640
|
return;
|
|
1289
1641
|
pendingDeltaRef.current += delta;
|
|
1290
1642
|
if (throttleTimerRef.current === null) {
|
|
1291
|
-
|
|
1643
|
+
if (isFirstDeltaInStreamRef.current) {
|
|
1644
|
+
isFirstDeltaInStreamRef.current = false;
|
|
1645
|
+
flushStreamingDelta();
|
|
1646
|
+
} else {
|
|
1647
|
+
throttleTimerRef.current = setTimeout(flushStreamingDelta, 50);
|
|
1648
|
+
}
|
|
1292
1649
|
}
|
|
1293
1650
|
},
|
|
1294
1651
|
finishAssistantStream: () => {
|
|
@@ -1312,6 +1669,7 @@ function REPLInk(props) {
|
|
|
1312
1669
|
return updated;
|
|
1313
1670
|
});
|
|
1314
1671
|
streamingIndexRef.current = -1;
|
|
1672
|
+
isFirstDeltaInStreamRef.current = true;
|
|
1315
1673
|
},
|
|
1316
1674
|
setMode: (newMode) => {
|
|
1317
1675
|
setMode(newMode);
|
|
@@ -1321,7 +1679,13 @@ function REPLInk(props) {
|
|
|
1321
1679
|
setStatusBarCtxState((s) => ({ ...s, ...ctx }));
|
|
1322
1680
|
},
|
|
1323
1681
|
clearMessages: () => {
|
|
1324
|
-
setMessages([
|
|
1682
|
+
setMessages([
|
|
1683
|
+
{
|
|
1684
|
+
role: "system",
|
|
1685
|
+
kind: "welcome",
|
|
1686
|
+
content: buildWelcomeCardText(initialContext)
|
|
1687
|
+
}
|
|
1688
|
+
]);
|
|
1325
1689
|
},
|
|
1326
1690
|
exit: () => {
|
|
1327
1691
|
appExit();
|
|
@@ -1330,19 +1694,42 @@ function REPLInk(props) {
|
|
|
1330
1694
|
if (onCommand) {
|
|
1331
1695
|
Promise.resolve(onCommand("compact")).catch(() => {});
|
|
1332
1696
|
}
|
|
1697
|
+
},
|
|
1698
|
+
setInputBuffer: (value) => {
|
|
1699
|
+
multilineInputRef.current?.setBuffer(value);
|
|
1700
|
+
setInputValue(value);
|
|
1701
|
+
},
|
|
1702
|
+
getInputBuffer: () => {
|
|
1703
|
+
return multilineInputRef.current?.getBuffer() ?? "";
|
|
1333
1704
|
}
|
|
1334
1705
|
};
|
|
1335
1706
|
apiRef.current = api;
|
|
1336
1707
|
onReady?.(api);
|
|
1337
1708
|
}, [appExit, onCommand, onReady]);
|
|
1338
|
-
|
|
1709
|
+
const handleEscapeCascade = React3.useCallback(() => {
|
|
1710
|
+
const now = Date.now();
|
|
1711
|
+
if (now - lastEscapeTsRef.current < 100) {
|
|
1712
|
+
return;
|
|
1713
|
+
}
|
|
1714
|
+
lastEscapeTsRef.current = now;
|
|
1715
|
+
if (onEscape) {
|
|
1716
|
+
Promise.resolve().then(() => onEscape()).catch((err) => {
|
|
1717
|
+
inkLogger.warn(`[REPLInk] onEscape failed: ${err}`);
|
|
1718
|
+
});
|
|
1719
|
+
}
|
|
1720
|
+
}, [onEscape]);
|
|
1721
|
+
useInput2((_input, key) => {
|
|
1722
|
+
if (showPopup) {
|
|
1723
|
+
if (key.escape || key.upArrow || key.downArrow || key.tab) {
|
|
1724
|
+
return;
|
|
1725
|
+
}
|
|
1726
|
+
if (key.return && !key.meta && !key.shift && !key.ctrl) {
|
|
1727
|
+
return;
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1339
1730
|
if (key.escape) {
|
|
1340
1731
|
multilineInputRef.current?.clearBuffer();
|
|
1341
|
-
|
|
1342
|
-
Promise.resolve().then(() => onEscape()).catch((err) => {
|
|
1343
|
-
inkLogger.warn(`[REPLInk] onEscape failed: ${err}`);
|
|
1344
|
-
});
|
|
1345
|
-
}
|
|
1732
|
+
handleEscapeCascade();
|
|
1346
1733
|
}
|
|
1347
1734
|
if (key.ctrl && key.c === true) {
|
|
1348
1735
|
if (onCommand) {
|
|
@@ -1363,7 +1750,7 @@ function REPLInk(props) {
|
|
|
1363
1750
|
}
|
|
1364
1751
|
}
|
|
1365
1752
|
});
|
|
1366
|
-
const handleSubmit =
|
|
1753
|
+
const handleSubmit = React3.useCallback(async (value) => {
|
|
1367
1754
|
if (!value || value.trim() === "") {
|
|
1368
1755
|
return;
|
|
1369
1756
|
}
|
|
@@ -1389,43 +1776,60 @@ function REPLInk(props) {
|
|
|
1389
1776
|
setMessages((msgs) => [...msgs, { role: "system", content: `[Error] ${msg}` }]);
|
|
1390
1777
|
}
|
|
1391
1778
|
}, [onCommand, onSubmit]);
|
|
1779
|
+
const staticItems = React3.useMemo(() => {
|
|
1780
|
+
if (messages.length <= 1)
|
|
1781
|
+
return [];
|
|
1782
|
+
return messages.slice(0, -1);
|
|
1783
|
+
}, [messages.length <= 1 ? 0 : messages.length - 1]);
|
|
1392
1784
|
const statusBarText = buildStatusBar({
|
|
1393
1785
|
mode,
|
|
1394
1786
|
cwd: statusBarCtx.cwd,
|
|
1395
1787
|
gitBranch: statusBarCtx.gitBranch,
|
|
1396
1788
|
model: shortModel(statusBarCtx.model)
|
|
1397
1789
|
});
|
|
1398
|
-
return /* @__PURE__ */
|
|
1790
|
+
return /* @__PURE__ */ jsxDEV2(Box3, {
|
|
1399
1791
|
flexDirection: "column",
|
|
1400
1792
|
children: [
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
/* @__PURE__ */ jsxDEV(Box2, {
|
|
1793
|
+
staticItems.length > 0 ? /* @__PURE__ */ jsxDEV2(Static, {
|
|
1794
|
+
items: staticItems,
|
|
1795
|
+
children: (msg, i) => /* @__PURE__ */ jsxDEV2(MessageView, {
|
|
1796
|
+
msg
|
|
1797
|
+
}, `h-${i}`, false, undefined, this)
|
|
1798
|
+
}, undefined, false, undefined, this) : null,
|
|
1799
|
+
messages.length > 0 ? /* @__PURE__ */ jsxDEV2(MessageView, {
|
|
1800
|
+
msg: messages[messages.length - 1]
|
|
1801
|
+
}, undefined, false, undefined, this) : null,
|
|
1802
|
+
/* @__PURE__ */ jsxDEV2(Box3, {
|
|
1412
1803
|
flexDirection: "column",
|
|
1413
1804
|
marginTop: 1,
|
|
1414
|
-
children: /* @__PURE__ */
|
|
1805
|
+
children: /* @__PURE__ */ jsxDEV2(Text3, {
|
|
1415
1806
|
children: statusBarText
|
|
1416
1807
|
}, undefined, false, undefined, this)
|
|
1417
1808
|
}, undefined, false, undefined, this),
|
|
1418
|
-
/* @__PURE__ */
|
|
1809
|
+
showPopup ? /* @__PURE__ */ jsxDEV2(Box3, {
|
|
1810
|
+
marginBottom: 0,
|
|
1811
|
+
children: /* @__PURE__ */ jsxDEV2(SlashCommandPopup, {
|
|
1812
|
+
query: inputValue,
|
|
1813
|
+
selectedIndex: safePopupIndex,
|
|
1814
|
+
onIndexChange: handlePopupIndexChange,
|
|
1815
|
+
onSelect: handlePopupSelect,
|
|
1816
|
+
onClose: handlePopupClose
|
|
1817
|
+
}, undefined, false, undefined, this)
|
|
1818
|
+
}, undefined, false, undefined, this) : null,
|
|
1819
|
+
/* @__PURE__ */ jsxDEV2(Box3, {
|
|
1419
1820
|
flexDirection: "column",
|
|
1420
1821
|
children: [
|
|
1421
|
-
/* @__PURE__ */
|
|
1822
|
+
/* @__PURE__ */ jsxDEV2(Text3, {
|
|
1422
1823
|
children: COLORS.muted("─".repeat(40))
|
|
1423
1824
|
}, undefined, false, undefined, this),
|
|
1424
|
-
/* @__PURE__ */
|
|
1825
|
+
/* @__PURE__ */ jsxDEV2(MultilineInput, {
|
|
1425
1826
|
ref: multilineInputRef,
|
|
1426
|
-
onSubmit: handleSubmit
|
|
1827
|
+
onSubmit: handleSubmit,
|
|
1828
|
+
onEscape: handleEscapeCascade,
|
|
1829
|
+
popupActive: showPopup,
|
|
1830
|
+
onChange: setInputValue
|
|
1427
1831
|
}, undefined, false, undefined, this),
|
|
1428
|
-
/* @__PURE__ */
|
|
1832
|
+
/* @__PURE__ */ jsxDEV2(Text3, {
|
|
1429
1833
|
children: COLORS.muted("─".repeat(40))
|
|
1430
1834
|
}, undefined, false, undefined, this)
|
|
1431
1835
|
]
|
|
@@ -1444,7 +1848,7 @@ function shortModel(model) {
|
|
|
1444
1848
|
}
|
|
1445
1849
|
async function renderInkREPL(props) {
|
|
1446
1850
|
const ink = await import("ink");
|
|
1447
|
-
const { waitUntilExit } = ink.render(
|
|
1851
|
+
const { waitUntilExit } = ink.render(React3.createElement(REPLInk, props));
|
|
1448
1852
|
await waitUntilExit();
|
|
1449
1853
|
}
|
|
1450
1854
|
var inkLogger, MultilineInput, MessageView;
|
|
@@ -1452,19 +1856,45 @@ var init_repl_ink = __esm(() => {
|
|
|
1452
1856
|
init_stream_output_service();
|
|
1453
1857
|
init_status_bar();
|
|
1454
1858
|
init_welcome_card();
|
|
1859
|
+
init_commands_registry();
|
|
1860
|
+
init_slash_command_popup();
|
|
1455
1861
|
init_markdown_renderer2();
|
|
1456
1862
|
inkLogger = createLogger4("repl-ink");
|
|
1457
|
-
MultilineInput =
|
|
1458
|
-
const { onSubmit, placeholder } = props;
|
|
1459
|
-
const [buffer, setBuffer] =
|
|
1460
|
-
const [cursor, setCursor] =
|
|
1461
|
-
|
|
1863
|
+
MultilineInput = React3.memo(React3.forwardRef(function MultilineInput2(props, ref) {
|
|
1864
|
+
const { onSubmit, placeholder, popupActive, onChange, onEscape } = props;
|
|
1865
|
+
const [buffer, setBuffer] = React3.useState("");
|
|
1866
|
+
const [cursor, setCursor] = React3.useState(0);
|
|
1867
|
+
React3.useEffect(() => {
|
|
1868
|
+
if (popupActive || buffer.startsWith("/")) {
|
|
1869
|
+
onChange?.(buffer);
|
|
1870
|
+
}
|
|
1871
|
+
}, [buffer, onChange, popupActive]);
|
|
1872
|
+
React3.useImperativeHandle(ref, () => ({
|
|
1462
1873
|
clearBuffer: () => {
|
|
1463
1874
|
setBuffer("");
|
|
1464
1875
|
setCursor(0);
|
|
1876
|
+
},
|
|
1877
|
+
getBuffer: () => {
|
|
1878
|
+
return buffer;
|
|
1879
|
+
},
|
|
1880
|
+
setBuffer: (value) => {
|
|
1881
|
+
setBuffer(value);
|
|
1882
|
+
setCursor(value.length);
|
|
1883
|
+
}
|
|
1884
|
+
}), [buffer]);
|
|
1885
|
+
useInput2((input, key) => {
|
|
1886
|
+
if (key.escape) {
|
|
1887
|
+
setBuffer("");
|
|
1888
|
+
setCursor(0);
|
|
1889
|
+
if (onEscape) {
|
|
1890
|
+
try {
|
|
1891
|
+
onEscape();
|
|
1892
|
+
} catch (err) {
|
|
1893
|
+
inkLogger.warn(`[MultilineInput] onEscape failed: ${err}`);
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
return;
|
|
1465
1897
|
}
|
|
1466
|
-
}), []);
|
|
1467
|
-
useInput((input, key) => {
|
|
1468
1898
|
if (key.return && (key.meta || key.shift || key.ctrl)) {
|
|
1469
1899
|
setBuffer((b) => {
|
|
1470
1900
|
const newBuf = b.slice(0, cursor) + `
|
|
@@ -1475,6 +1905,9 @@ var init_repl_ink = __esm(() => {
|
|
|
1475
1905
|
return;
|
|
1476
1906
|
}
|
|
1477
1907
|
if (key.return) {
|
|
1908
|
+
if (popupActive) {
|
|
1909
|
+
return;
|
|
1910
|
+
}
|
|
1478
1911
|
if (buffer.trim() === "") {
|
|
1479
1912
|
return;
|
|
1480
1913
|
}
|
|
@@ -1624,12 +2057,12 @@ var init_repl_ink = __esm(() => {
|
|
|
1624
2057
|
}
|
|
1625
2058
|
}
|
|
1626
2059
|
const showPlaceholder = buffer.length === 0 && placeholder;
|
|
1627
|
-
return /* @__PURE__ */
|
|
2060
|
+
return /* @__PURE__ */ jsxDEV2(Box3, {
|
|
1628
2061
|
flexDirection: "column",
|
|
1629
2062
|
children: lines.map((line, i) => {
|
|
1630
2063
|
const isFirst = i === 0;
|
|
1631
2064
|
const isCursorRow = i === cursorRow;
|
|
1632
|
-
const prefixEl = /* @__PURE__ */
|
|
2065
|
+
const prefixEl = /* @__PURE__ */ jsxDEV2(Text3, {
|
|
1633
2066
|
color: isFirst ? "red" : "gray",
|
|
1634
2067
|
children: isFirst ? "❯ " : "... "
|
|
1635
2068
|
}, undefined, false, undefined, this);
|
|
@@ -1644,29 +2077,29 @@ var init_repl_ink = __esm(() => {
|
|
|
1644
2077
|
atCursor = line[cursorCol] ?? " ";
|
|
1645
2078
|
afterCursor = line.slice(cursorCol + 1);
|
|
1646
2079
|
}
|
|
1647
|
-
return /* @__PURE__ */
|
|
2080
|
+
return /* @__PURE__ */ jsxDEV2(Box3, {
|
|
1648
2081
|
children: [
|
|
1649
2082
|
prefixEl,
|
|
1650
|
-
/* @__PURE__ */
|
|
2083
|
+
/* @__PURE__ */ jsxDEV2(Text3, {
|
|
1651
2084
|
children: beforeCursor
|
|
1652
2085
|
}, undefined, false, undefined, this),
|
|
1653
|
-
/* @__PURE__ */
|
|
2086
|
+
/* @__PURE__ */ jsxDEV2(Text3, {
|
|
1654
2087
|
inverse: !showPlaceholder,
|
|
1655
2088
|
children: atCursor
|
|
1656
2089
|
}, undefined, false, undefined, this),
|
|
1657
|
-
showPlaceholder ? /* @__PURE__ */
|
|
2090
|
+
showPlaceholder ? /* @__PURE__ */ jsxDEV2(Text3, {
|
|
1658
2091
|
color: "gray",
|
|
1659
2092
|
children: placeholder?.slice(1) ?? ""
|
|
1660
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
2093
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV2(Text3, {
|
|
1661
2094
|
children: afterCursor
|
|
1662
2095
|
}, undefined, false, undefined, this)
|
|
1663
2096
|
]
|
|
1664
2097
|
}, i, true, undefined, this);
|
|
1665
2098
|
}
|
|
1666
|
-
return /* @__PURE__ */
|
|
2099
|
+
return /* @__PURE__ */ jsxDEV2(Box3, {
|
|
1667
2100
|
children: [
|
|
1668
2101
|
prefixEl,
|
|
1669
|
-
/* @__PURE__ */
|
|
2102
|
+
/* @__PURE__ */ jsxDEV2(Text3, {
|
|
1670
2103
|
children: line
|
|
1671
2104
|
}, undefined, false, undefined, this)
|
|
1672
2105
|
]
|
|
@@ -1674,7 +2107,15 @@ var init_repl_ink = __esm(() => {
|
|
|
1674
2107
|
})
|
|
1675
2108
|
}, undefined, false, undefined, this);
|
|
1676
2109
|
}));
|
|
1677
|
-
MessageView =
|
|
2110
|
+
MessageView = React3.memo(function MessageView2({ msg }) {
|
|
2111
|
+
if (msg.kind === "welcome") {
|
|
2112
|
+
return /* @__PURE__ */ jsxDEV2(Box3, {
|
|
2113
|
+
flexDirection: "column",
|
|
2114
|
+
children: /* @__PURE__ */ jsxDEV2(Text3, {
|
|
2115
|
+
children: msg.content
|
|
2116
|
+
}, undefined, false, undefined, this)
|
|
2117
|
+
}, undefined, false, undefined, this);
|
|
2118
|
+
}
|
|
1678
2119
|
let prefix;
|
|
1679
2120
|
let color;
|
|
1680
2121
|
let contentColor;
|
|
@@ -1713,11 +2154,11 @@ var init_repl_ink = __esm(() => {
|
|
|
1713
2154
|
}
|
|
1714
2155
|
const displayContent = msg.role === "tool" || msg.role === "tool_result" ? `${msg.toolName ?? "tool"}: ${msg.content}` : msg.content;
|
|
1715
2156
|
if (msg.role === "assistant") {
|
|
1716
|
-
return /* @__PURE__ */
|
|
2157
|
+
return /* @__PURE__ */ jsxDEV2(Box3, {
|
|
1717
2158
|
flexDirection: "column",
|
|
1718
2159
|
children: [
|
|
1719
|
-
/* @__PURE__ */
|
|
1720
|
-
children: /* @__PURE__ */
|
|
2160
|
+
/* @__PURE__ */ jsxDEV2(Box3, {
|
|
2161
|
+
children: /* @__PURE__ */ jsxDEV2(Text3, {
|
|
1721
2162
|
color: "green",
|
|
1722
2163
|
bold: true,
|
|
1723
2164
|
children: [
|
|
@@ -1726,12 +2167,12 @@ var init_repl_ink = __esm(() => {
|
|
|
1726
2167
|
]
|
|
1727
2168
|
}, undefined, true, undefined, this)
|
|
1728
2169
|
}, undefined, false, undefined, this),
|
|
1729
|
-
/* @__PURE__ */
|
|
2170
|
+
/* @__PURE__ */ jsxDEV2(Box3, {
|
|
1730
2171
|
flexDirection: "column",
|
|
1731
2172
|
marginLeft: 2,
|
|
1732
2173
|
children: [
|
|
1733
2174
|
renderMarkdown(displayContent),
|
|
1734
|
-
msg.streaming ? /* @__PURE__ */
|
|
2175
|
+
msg.streaming ? /* @__PURE__ */ jsxDEV2(Text3, {
|
|
1735
2176
|
color: "gray",
|
|
1736
2177
|
children: "▌"
|
|
1737
2178
|
}, undefined, false, undefined, this) : null
|
|
@@ -1740,9 +2181,9 @@ var init_repl_ink = __esm(() => {
|
|
|
1740
2181
|
]
|
|
1741
2182
|
}, undefined, true, undefined, this);
|
|
1742
2183
|
}
|
|
1743
|
-
return /* @__PURE__ */
|
|
2184
|
+
return /* @__PURE__ */ jsxDEV2(Box3, {
|
|
1744
2185
|
children: [
|
|
1745
|
-
/* @__PURE__ */
|
|
2186
|
+
/* @__PURE__ */ jsxDEV2(Text3, {
|
|
1746
2187
|
color,
|
|
1747
2188
|
bold: true,
|
|
1748
2189
|
children: [
|
|
@@ -1750,7 +2191,7 @@ var init_repl_ink = __esm(() => {
|
|
|
1750
2191
|
" "
|
|
1751
2192
|
]
|
|
1752
2193
|
}, undefined, true, undefined, this),
|
|
1753
|
-
/* @__PURE__ */
|
|
2194
|
+
/* @__PURE__ */ jsxDEV2(Text3, {
|
|
1754
2195
|
color: contentColor,
|
|
1755
2196
|
children: [
|
|
1756
2197
|
displayContent,
|
|
@@ -11535,14 +11976,18 @@ class REPL {
|
|
|
11535
11976
|
console.clear();
|
|
11536
11977
|
this.printHeader();
|
|
11537
11978
|
this.redrawInputArea();
|
|
11538
|
-
this.rl
|
|
11979
|
+
if (this.rl) {
|
|
11980
|
+
this.rl.prompt(true);
|
|
11981
|
+
}
|
|
11539
11982
|
this.sessionManager?.clearAttachments();
|
|
11540
11983
|
});
|
|
11541
11984
|
this.commandRegistry.set("cls", async () => {
|
|
11542
11985
|
console.clear();
|
|
11543
11986
|
this.printHeader();
|
|
11544
11987
|
this.redrawInputArea();
|
|
11545
|
-
this.rl
|
|
11988
|
+
if (this.rl) {
|
|
11989
|
+
this.rl.prompt(true);
|
|
11990
|
+
}
|
|
11546
11991
|
this.sessionManager?.clearAttachments();
|
|
11547
11992
|
});
|
|
11548
11993
|
this.commandRegistry.set("sessions", async () => {
|
|
@@ -11772,7 +12217,9 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
11772
12217
|
}
|
|
11773
12218
|
this.printHeader();
|
|
11774
12219
|
this.redrawInputArea();
|
|
11775
|
-
this.rl
|
|
12220
|
+
if (this.rl) {
|
|
12221
|
+
this.rl.prompt(true);
|
|
12222
|
+
}
|
|
11776
12223
|
readline2.emitKeypressEvents(process.stdin);
|
|
11777
12224
|
if (process.stdin.isTTY) {
|
|
11778
12225
|
process.stdin.setRawMode?.(true);
|
|
@@ -11856,9 +12303,13 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
11856
12303
|
printSlotBottomBorder();
|
|
11857
12304
|
}
|
|
11858
12305
|
updatePrompt() {
|
|
11859
|
-
this.rl
|
|
11860
|
-
|
|
11861
|
-
|
|
12306
|
+
if (this.rl) {
|
|
12307
|
+
this.rl.setPrompt(COLORS.accent("❯ "));
|
|
12308
|
+
this.redrawInputArea();
|
|
12309
|
+
this.rl.prompt(true);
|
|
12310
|
+
} else {
|
|
12311
|
+
this.redrawInputArea();
|
|
12312
|
+
}
|
|
11862
12313
|
}
|
|
11863
12314
|
async handleCommand(input) {
|
|
11864
12315
|
const [cmd] = input.split(/\s+/);
|
|
@@ -12006,7 +12457,9 @@ ${COLORS.error("❌ 执行失败: " + error)}
|
|
|
12006
12457
|
this.setMode("ready");
|
|
12007
12458
|
if (options.showPrompt) {
|
|
12008
12459
|
this.redrawInputArea();
|
|
12009
|
-
this.rl
|
|
12460
|
+
if (this.rl) {
|
|
12461
|
+
this.rl.prompt(true);
|
|
12462
|
+
}
|
|
12010
12463
|
}
|
|
12011
12464
|
}
|
|
12012
12465
|
}
|
|
@@ -12065,9 +12518,13 @@ ${COLORS.error("❌ 执行失败: " + error)}
|
|
|
12065
12518
|
promptUser(question, options, errorInfo, opts) {
|
|
12066
12519
|
const timeoutMs = opts?.timeoutMs ?? this.askUserTimeoutMs ?? ASK_USER_TIMEOUT_MS;
|
|
12067
12520
|
return new Promise((resolve) => {
|
|
12068
|
-
this.rl
|
|
12069
|
-
|
|
12070
|
-
|
|
12521
|
+
if (this.rl) {
|
|
12522
|
+
this.rl.setPrompt(COLORS.accent("❯ "));
|
|
12523
|
+
this.redrawInputArea();
|
|
12524
|
+
this.rl.prompt(true);
|
|
12525
|
+
} else {
|
|
12526
|
+
this.redrawInputArea();
|
|
12527
|
+
}
|
|
12071
12528
|
const finishWithUserInput = (input) => {
|
|
12072
12529
|
const trimmedInput = input.trim();
|
|
12073
12530
|
if (!trimmedInput) {
|
|
@@ -12160,6 +12617,13 @@ ${COLORS.error("❌ 执行失败: " + error)}
|
|
|
12160
12617
|
}
|
|
12161
12618
|
}
|
|
12162
12619
|
abortStream();
|
|
12620
|
+
if (this.inkApi && typeof this.inkApi.finishAssistantStream === "function") {
|
|
12621
|
+
try {
|
|
12622
|
+
this.inkApi.finishAssistantStream();
|
|
12623
|
+
} catch (err) {
|
|
12624
|
+
logger4.warn("[Esc] finishAssistantStream failed", { error: String(err) });
|
|
12625
|
+
}
|
|
12626
|
+
}
|
|
12163
12627
|
const mainSessionId = this.options.sessionId;
|
|
12164
12628
|
if (this.env && mainSessionId) {
|
|
12165
12629
|
let timer;
|
|
@@ -21973,9 +22437,9 @@ import chalk73 from "chalk";
|
|
|
21973
22437
|
import fs5 from "fs";
|
|
21974
22438
|
import path8 from "path";
|
|
21975
22439
|
import { createRunWorkflowTool } from "@ai-setting/roy-agent-core/env/workflow/tools";
|
|
21976
|
-
import { getTracerProvider as getTracerProvider4, propagation, wrapFunction } from "@ai-setting/roy-agent-core";
|
|
22440
|
+
import { getTracerProvider as getTracerProvider4, propagation, wrapFunction as wrapFunction2 } from "@ai-setting/roy-agent-core";
|
|
21977
22441
|
import { isValidSessionId } from "@ai-setting/roy-agent-core/env/session";
|
|
21978
|
-
var runWorkflow =
|
|
22442
|
+
var runWorkflow = wrapFunction2(async function runWorkflowImpl(args) {
|
|
21979
22443
|
const output = new OutputService2;
|
|
21980
22444
|
const envService = new EnvironmentService(output);
|
|
21981
22445
|
const traceparent = process.env.TRACEPARENT;
|
|
@@ -22252,8 +22716,8 @@ var WorkflowRunCommand = {
|
|
|
22252
22716
|
// src/commands/workflow/commands/stop.ts
|
|
22253
22717
|
import chalk74 from "chalk";
|
|
22254
22718
|
import { createWorkflowRunStopTool } from "@ai-setting/roy-agent-core/env/workflow/tools";
|
|
22255
|
-
import { wrapFunction as
|
|
22256
|
-
var stopWorkflow =
|
|
22719
|
+
import { wrapFunction as wrapFunction3 } from "@ai-setting/roy-agent-core";
|
|
22720
|
+
var stopWorkflow = wrapFunction3(async function stopWorkflowImpl(args) {
|
|
22257
22721
|
const output = new OutputService2;
|
|
22258
22722
|
const envService = new EnvironmentService(output);
|
|
22259
22723
|
try {
|
|
@@ -22908,7 +23372,7 @@ Error: ${error.message}`));
|
|
|
22908
23372
|
|
|
22909
23373
|
// src/commands/workflow/commands/search.ts
|
|
22910
23374
|
import chalk78 from "chalk";
|
|
22911
|
-
import { wrapFunction as
|
|
23375
|
+
import { wrapFunction as wrapFunction4 } from "@ai-setting/roy-agent-core";
|
|
22912
23376
|
var WorkflowSearchCommand = {
|
|
22913
23377
|
command: "search",
|
|
22914
23378
|
describe: "Search workflows by keyword and/or tags (multiple tags use AND filter). v2: returns available_tags.",
|
|
@@ -23083,14 +23547,14 @@ var _runWorkflowSearchImpl = async function(opts) {
|
|
|
23083
23547
|
}
|
|
23084
23548
|
}
|
|
23085
23549
|
};
|
|
23086
|
-
var runWorkflowSearch =
|
|
23550
|
+
var runWorkflowSearch = wrapFunction4(_runWorkflowSearchImpl, "workflow.cli.search", {
|
|
23087
23551
|
recordParams: true,
|
|
23088
23552
|
recordResult: false,
|
|
23089
23553
|
log: false
|
|
23090
23554
|
});
|
|
23091
23555
|
|
|
23092
23556
|
// src/commands/workflow/commands/tag.ts
|
|
23093
|
-
import { wrapFunction as
|
|
23557
|
+
import { wrapFunction as wrapFunction5 } from "@ai-setting/roy-agent-core";
|
|
23094
23558
|
import chalk79 from "chalk";
|
|
23095
23559
|
var WorkflowTagListCommand = {
|
|
23096
23560
|
command: "list",
|
|
@@ -23290,12 +23754,12 @@ function formatDate2(iso) {
|
|
|
23290
23754
|
return iso;
|
|
23291
23755
|
}
|
|
23292
23756
|
}
|
|
23293
|
-
var runWorkflowTagList =
|
|
23757
|
+
var runWorkflowTagList = wrapFunction5(_runWorkflowTagListImpl, "workflow.cli.tag.list", {
|
|
23294
23758
|
recordParams: true,
|
|
23295
23759
|
recordResult: false,
|
|
23296
23760
|
log: false
|
|
23297
23761
|
});
|
|
23298
|
-
var runWorkflowTagGet =
|
|
23762
|
+
var runWorkflowTagGet = wrapFunction5(_runWorkflowTagGetImpl, "workflow.cli.tag.get", {
|
|
23299
23763
|
recordParams: true,
|
|
23300
23764
|
recordResult: false,
|
|
23301
23765
|
log: false
|