@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.
@@ -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.15",
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/markdown-renderer.tsx
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(React.createElement(Text, { key: `${keyPrefix}-t-${counter++}` }, text.slice(lastIndex, match.index)));
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(React.createElement(Text, { key: `${keyPrefix}-c-${counter++}`, color: "white", backgroundColor: "gray" }, ` ${match[2]} `));
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(React.createElement(Text, { key: `${keyPrefix}-b-${counter++}`, color: "yellow", bold: true }, match[4]));
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(React.createElement(Text, { key: `${keyPrefix}-i-${counter++}`, color: "yellow" }, match[6]));
1265
+ nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-i-${counter++}`, color: "yellow" }, match[6]));
1089
1266
  } else if (match[7] !== undefined) {
1090
- nodes.push(React.createElement(Text, { key: `${keyPrefix}-s-${counter++}`, dimColor: true }, match[8]));
1267
+ nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-s-${counter++}`, dimColor: true }, match[8]));
1091
1268
  } else if (match[9] !== undefined) {
1092
- nodes.push(React.createElement(Text, { key: `${keyPrefix}-l-${counter++}`, color: "cyan", underline: true }, match[10]), React.createElement(Text, { key: `${keyPrefix}-u-${counter++}`, color: "blue", dimColor: true }, ` (${match[11]})`));
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(React.createElement(Text, { key: `${keyPrefix}-e-${counter++}` }, text.slice(lastIndex)));
1274
+ nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-e-${counter++}` }, text.slice(lastIndex)));
1098
1275
  }
1099
1276
  if (nodes.length === 0) {
1100
- nodes.push(React.createElement(Text, { key: `${keyPrefix}-all` }, text));
1277
+ nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-all` }, text));
1101
1278
  }
1102
1279
  return nodes;
1103
1280
  }
1104
- function renderMarkdown(content) {
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(React.createElement(Box, {
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
- }, React.createElement(Text, { color: "white" }, codeLines.length === 0 ? " " : codeLines.join(`
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(React.createElement(Box, { key: `blk-hr-${blockKey++}`, marginY: 1 }, React.createElement(Text, { color: "gray" }, "─".repeat(50))));
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(React.createElement(Box, { key: `blk-h1-${blockKey++}`, marginY: 1 }, React.createElement(Text, {}, styled)));
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(React.createElement(Box, { key: `blk-h2-${blockKey++}`, marginY: 1 }, React.createElement(Text, {}, styled)));
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(React.createElement(Box, { key: `blk-h-${blockKey++}`, marginY: 1 }, React.createElement(Text, { color, bold: true }, `${prefix}${text}`)));
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(React.createElement(Box, {
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) => React.createElement(Box, { key: `q-${qi}` }, React.createElement(Text, { color: "gray", dimColor: true }, ql)))));
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(React.createElement(Box, { key: `blk-ul-${blockKey++}`, flexDirection: "column", marginLeft: 2 }, ...items.map((it, ii) => React.createElement(Box, { key: `ul-${ii}` }, React.createElement(Text, { color: "yellow", bold: true }, "▸ "), ...parseInline(it, `ul-${ii}`)))));
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(React.createElement(Box, { key: `blk-ol-${blockKey++}`, flexDirection: "column", marginLeft: 2 }, ...items.map((it, ii) => React.createElement(Box, { key: `ol-${ii}` }, React.createElement(Text, { color: "cyan", bold: true }, `${(ii + 1).toString().padStart(2, " ")}. `), ...parseInline(it, `ol-${ii}`)))));
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(React.createElement(Box, { key: `blk-p-${blockKey++}`, marginY: 0 }, ...parseInline(paraText, `p-${blockKey}`)));
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 init_markdown_renderer2 = () => {};
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 React2 from "react";
1222
- import { Box as Box2, Text as Text2, useApp, useInput } from "ink";
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] = React2.useState(initialMessages);
1238
- const [mode, setMode] = React2.useState(initialMode);
1239
- const [statusBarCtx, setStatusBarCtxState] = React2.useState({
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 streamingIndexRef = React2.useRef(-1);
1246
- const multilineInputRef = React2.useRef(null);
1247
- const pendingDeltaRef = React2.useRef("");
1248
- const throttleTimerRef = React2.useRef(null);
1249
- const flushStreamingDelta = React2.useCallback(() => {
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
- React2.useEffect(() => {
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 = React2.useRef(null);
1281
- React2.useEffect(() => {
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
- throttleTimerRef.current = setTimeout(flushStreamingDelta, 50);
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
- useInput((_input, key) => {
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
- if (onEscape) {
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 = React2.useCallback(async (value) => {
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__ */ jsxDEV(Box2, {
1790
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1399
1791
  flexDirection: "column",
1400
1792
  children: [
1401
- messages.length === 0 && /* @__PURE__ */ jsxDEV(Box2, {
1402
- flexDirection: "column",
1403
- marginBottom: 1,
1404
- children: /* @__PURE__ */ jsxDEV(Text2, {
1405
- children: buildWelcomeCardText(initialContext)
1406
- }, undefined, false, undefined, this)
1407
- }, undefined, false, undefined, this),
1408
- messages.map((msg, i) => /* @__PURE__ */ jsxDEV(MessageView, {
1409
- msg
1410
- }, i, false, undefined, this)),
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__ */ jsxDEV(Text2, {
1805
+ children: /* @__PURE__ */ jsxDEV2(Text3, {
1415
1806
  children: statusBarText
1416
1807
  }, undefined, false, undefined, this)
1417
1808
  }, undefined, false, undefined, this),
1418
- /* @__PURE__ */ jsxDEV(Box2, {
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__ */ jsxDEV(Text2, {
1822
+ /* @__PURE__ */ jsxDEV2(Text3, {
1422
1823
  children: COLORS.muted("─".repeat(40))
1423
1824
  }, undefined, false, undefined, this),
1424
- /* @__PURE__ */ jsxDEV(MultilineInput, {
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__ */ jsxDEV(Text2, {
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(React2.createElement(REPLInk, props));
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 = React2.memo(React2.forwardRef(function MultilineInput2(props, ref) {
1458
- const { onSubmit, placeholder } = props;
1459
- const [buffer, setBuffer] = React2.useState("");
1460
- const [cursor, setCursor] = React2.useState(0);
1461
- React2.useImperativeHandle(ref, () => ({
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__ */ jsxDEV(Box2, {
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__ */ jsxDEV(Text2, {
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__ */ jsxDEV(Box2, {
2080
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1648
2081
  children: [
1649
2082
  prefixEl,
1650
- /* @__PURE__ */ jsxDEV(Text2, {
2083
+ /* @__PURE__ */ jsxDEV2(Text3, {
1651
2084
  children: beforeCursor
1652
2085
  }, undefined, false, undefined, this),
1653
- /* @__PURE__ */ jsxDEV(Text2, {
2086
+ /* @__PURE__ */ jsxDEV2(Text3, {
1654
2087
  inverse: !showPlaceholder,
1655
2088
  children: atCursor
1656
2089
  }, undefined, false, undefined, this),
1657
- showPlaceholder ? /* @__PURE__ */ jsxDEV(Text2, {
2090
+ showPlaceholder ? /* @__PURE__ */ jsxDEV2(Text3, {
1658
2091
  color: "gray",
1659
2092
  children: placeholder?.slice(1) ?? ""
1660
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV(Text2, {
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__ */ jsxDEV(Box2, {
2099
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1667
2100
  children: [
1668
2101
  prefixEl,
1669
- /* @__PURE__ */ jsxDEV(Text2, {
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 = React2.memo(function MessageView2({ msg }) {
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__ */ jsxDEV(Box2, {
2157
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1717
2158
  flexDirection: "column",
1718
2159
  children: [
1719
- /* @__PURE__ */ jsxDEV(Box2, {
1720
- children: /* @__PURE__ */ jsxDEV(Text2, {
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__ */ jsxDEV(Box2, {
2170
+ /* @__PURE__ */ jsxDEV2(Box3, {
1730
2171
  flexDirection: "column",
1731
2172
  marginLeft: 2,
1732
2173
  children: [
1733
2174
  renderMarkdown(displayContent),
1734
- msg.streaming ? /* @__PURE__ */ jsxDEV(Text2, {
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__ */ jsxDEV(Box2, {
2184
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1744
2185
  children: [
1745
- /* @__PURE__ */ jsxDEV(Text2, {
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__ */ jsxDEV(Text2, {
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.prompt(true);
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.prompt(true);
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.prompt(true);
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.setPrompt(COLORS.accent("❯ "));
11860
- this.redrawInputArea();
11861
- this.rl.prompt(true);
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.prompt(true);
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.setPrompt(COLORS.accent("❯ "));
12069
- this.redrawInputArea();
12070
- this.rl.prompt(true);
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 = wrapFunction(async function runWorkflowImpl(args) {
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 wrapFunction2 } from "@ai-setting/roy-agent-core";
22256
- var stopWorkflow = wrapFunction2(async function stopWorkflowImpl(args) {
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 wrapFunction3 } from "@ai-setting/roy-agent-core";
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 = wrapFunction3(_runWorkflowSearchImpl, "workflow.cli.search", {
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 wrapFunction4 } from "@ai-setting/roy-agent-core";
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 = wrapFunction4(_runWorkflowTagListImpl, "workflow.cli.tag.list", {
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 = wrapFunction4(_runWorkflowTagGetImpl, "workflow.cli.tag.get", {
23762
+ var runWorkflowTagGet = wrapFunction5(_runWorkflowTagGetImpl, "workflow.cli.tag.get", {
23299
23763
  recordParams: true,
23300
23764
  recordResult: false,
23301
23765
  log: false