@ai-setting/roy-agent-cli 1.6.15 → 1.6.16

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.16",
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,43 @@ 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
+ onChange?.(buffer);
1869
+ }, [buffer, onChange]);
1870
+ React3.useImperativeHandle(ref, () => ({
1462
1871
  clearBuffer: () => {
1463
1872
  setBuffer("");
1464
1873
  setCursor(0);
1874
+ },
1875
+ getBuffer: () => {
1876
+ return buffer;
1877
+ },
1878
+ setBuffer: (value) => {
1879
+ setBuffer(value);
1880
+ setCursor(value.length);
1881
+ }
1882
+ }), [buffer]);
1883
+ useInput2((input, key) => {
1884
+ if (key.escape) {
1885
+ setBuffer("");
1886
+ setCursor(0);
1887
+ if (onEscape) {
1888
+ try {
1889
+ onEscape();
1890
+ } catch (err) {
1891
+ inkLogger.warn(`[MultilineInput] onEscape failed: ${err}`);
1892
+ }
1893
+ }
1894
+ return;
1465
1895
  }
1466
- }), []);
1467
- useInput((input, key) => {
1468
1896
  if (key.return && (key.meta || key.shift || key.ctrl)) {
1469
1897
  setBuffer((b) => {
1470
1898
  const newBuf = b.slice(0, cursor) + `
@@ -1475,6 +1903,9 @@ var init_repl_ink = __esm(() => {
1475
1903
  return;
1476
1904
  }
1477
1905
  if (key.return) {
1906
+ if (popupActive) {
1907
+ return;
1908
+ }
1478
1909
  if (buffer.trim() === "") {
1479
1910
  return;
1480
1911
  }
@@ -1624,12 +2055,12 @@ var init_repl_ink = __esm(() => {
1624
2055
  }
1625
2056
  }
1626
2057
  const showPlaceholder = buffer.length === 0 && placeholder;
1627
- return /* @__PURE__ */ jsxDEV(Box2, {
2058
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1628
2059
  flexDirection: "column",
1629
2060
  children: lines.map((line, i) => {
1630
2061
  const isFirst = i === 0;
1631
2062
  const isCursorRow = i === cursorRow;
1632
- const prefixEl = /* @__PURE__ */ jsxDEV(Text2, {
2063
+ const prefixEl = /* @__PURE__ */ jsxDEV2(Text3, {
1633
2064
  color: isFirst ? "red" : "gray",
1634
2065
  children: isFirst ? "❯ " : "... "
1635
2066
  }, undefined, false, undefined, this);
@@ -1644,29 +2075,29 @@ var init_repl_ink = __esm(() => {
1644
2075
  atCursor = line[cursorCol] ?? " ";
1645
2076
  afterCursor = line.slice(cursorCol + 1);
1646
2077
  }
1647
- return /* @__PURE__ */ jsxDEV(Box2, {
2078
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1648
2079
  children: [
1649
2080
  prefixEl,
1650
- /* @__PURE__ */ jsxDEV(Text2, {
2081
+ /* @__PURE__ */ jsxDEV2(Text3, {
1651
2082
  children: beforeCursor
1652
2083
  }, undefined, false, undefined, this),
1653
- /* @__PURE__ */ jsxDEV(Text2, {
2084
+ /* @__PURE__ */ jsxDEV2(Text3, {
1654
2085
  inverse: !showPlaceholder,
1655
2086
  children: atCursor
1656
2087
  }, undefined, false, undefined, this),
1657
- showPlaceholder ? /* @__PURE__ */ jsxDEV(Text2, {
2088
+ showPlaceholder ? /* @__PURE__ */ jsxDEV2(Text3, {
1658
2089
  color: "gray",
1659
2090
  children: placeholder?.slice(1) ?? ""
1660
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV(Text2, {
2091
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV2(Text3, {
1661
2092
  children: afterCursor
1662
2093
  }, undefined, false, undefined, this)
1663
2094
  ]
1664
2095
  }, i, true, undefined, this);
1665
2096
  }
1666
- return /* @__PURE__ */ jsxDEV(Box2, {
2097
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1667
2098
  children: [
1668
2099
  prefixEl,
1669
- /* @__PURE__ */ jsxDEV(Text2, {
2100
+ /* @__PURE__ */ jsxDEV2(Text3, {
1670
2101
  children: line
1671
2102
  }, undefined, false, undefined, this)
1672
2103
  ]
@@ -1674,7 +2105,15 @@ var init_repl_ink = __esm(() => {
1674
2105
  })
1675
2106
  }, undefined, false, undefined, this);
1676
2107
  }));
1677
- MessageView = React2.memo(function MessageView2({ msg }) {
2108
+ MessageView = React3.memo(function MessageView2({ msg }) {
2109
+ if (msg.kind === "welcome") {
2110
+ return /* @__PURE__ */ jsxDEV2(Box3, {
2111
+ flexDirection: "column",
2112
+ children: /* @__PURE__ */ jsxDEV2(Text3, {
2113
+ children: msg.content
2114
+ }, undefined, false, undefined, this)
2115
+ }, undefined, false, undefined, this);
2116
+ }
1678
2117
  let prefix;
1679
2118
  let color;
1680
2119
  let contentColor;
@@ -1713,11 +2152,11 @@ var init_repl_ink = __esm(() => {
1713
2152
  }
1714
2153
  const displayContent = msg.role === "tool" || msg.role === "tool_result" ? `${msg.toolName ?? "tool"}: ${msg.content}` : msg.content;
1715
2154
  if (msg.role === "assistant") {
1716
- return /* @__PURE__ */ jsxDEV(Box2, {
2155
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1717
2156
  flexDirection: "column",
1718
2157
  children: [
1719
- /* @__PURE__ */ jsxDEV(Box2, {
1720
- children: /* @__PURE__ */ jsxDEV(Text2, {
2158
+ /* @__PURE__ */ jsxDEV2(Box3, {
2159
+ children: /* @__PURE__ */ jsxDEV2(Text3, {
1721
2160
  color: "green",
1722
2161
  bold: true,
1723
2162
  children: [
@@ -1726,12 +2165,12 @@ var init_repl_ink = __esm(() => {
1726
2165
  ]
1727
2166
  }, undefined, true, undefined, this)
1728
2167
  }, undefined, false, undefined, this),
1729
- /* @__PURE__ */ jsxDEV(Box2, {
2168
+ /* @__PURE__ */ jsxDEV2(Box3, {
1730
2169
  flexDirection: "column",
1731
2170
  marginLeft: 2,
1732
2171
  children: [
1733
2172
  renderMarkdown(displayContent),
1734
- msg.streaming ? /* @__PURE__ */ jsxDEV(Text2, {
2173
+ msg.streaming ? /* @__PURE__ */ jsxDEV2(Text3, {
1735
2174
  color: "gray",
1736
2175
  children: "▌"
1737
2176
  }, undefined, false, undefined, this) : null
@@ -1740,9 +2179,9 @@ var init_repl_ink = __esm(() => {
1740
2179
  ]
1741
2180
  }, undefined, true, undefined, this);
1742
2181
  }
1743
- return /* @__PURE__ */ jsxDEV(Box2, {
2182
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1744
2183
  children: [
1745
- /* @__PURE__ */ jsxDEV(Text2, {
2184
+ /* @__PURE__ */ jsxDEV2(Text3, {
1746
2185
  color,
1747
2186
  bold: true,
1748
2187
  children: [
@@ -1750,7 +2189,7 @@ var init_repl_ink = __esm(() => {
1750
2189
  " "
1751
2190
  ]
1752
2191
  }, undefined, true, undefined, this),
1753
- /* @__PURE__ */ jsxDEV(Text2, {
2192
+ /* @__PURE__ */ jsxDEV2(Text3, {
1754
2193
  color: contentColor,
1755
2194
  children: [
1756
2195
  displayContent,
@@ -12160,6 +12599,13 @@ ${COLORS.error("❌ 执行失败: " + error)}
12160
12599
  }
12161
12600
  }
12162
12601
  abortStream();
12602
+ if (this.inkApi && typeof this.inkApi.finishAssistantStream === "function") {
12603
+ try {
12604
+ this.inkApi.finishAssistantStream();
12605
+ } catch (err) {
12606
+ logger4.warn("[Esc] finishAssistantStream failed", { error: String(err) });
12607
+ }
12608
+ }
12163
12609
  const mainSessionId = this.options.sessionId;
12164
12610
  if (this.env && mainSessionId) {
12165
12611
  let timer;
@@ -21973,9 +22419,9 @@ import chalk73 from "chalk";
21973
22419
  import fs5 from "fs";
21974
22420
  import path8 from "path";
21975
22421
  import { createRunWorkflowTool } from "@ai-setting/roy-agent-core/env/workflow/tools";
21976
- import { getTracerProvider as getTracerProvider4, propagation, wrapFunction } from "@ai-setting/roy-agent-core";
22422
+ import { getTracerProvider as getTracerProvider4, propagation, wrapFunction as wrapFunction2 } from "@ai-setting/roy-agent-core";
21977
22423
  import { isValidSessionId } from "@ai-setting/roy-agent-core/env/session";
21978
- var runWorkflow = wrapFunction(async function runWorkflowImpl(args) {
22424
+ var runWorkflow = wrapFunction2(async function runWorkflowImpl(args) {
21979
22425
  const output = new OutputService2;
21980
22426
  const envService = new EnvironmentService(output);
21981
22427
  const traceparent = process.env.TRACEPARENT;
@@ -22252,8 +22698,8 @@ var WorkflowRunCommand = {
22252
22698
  // src/commands/workflow/commands/stop.ts
22253
22699
  import chalk74 from "chalk";
22254
22700
  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) {
22701
+ import { wrapFunction as wrapFunction3 } from "@ai-setting/roy-agent-core";
22702
+ var stopWorkflow = wrapFunction3(async function stopWorkflowImpl(args) {
22257
22703
  const output = new OutputService2;
22258
22704
  const envService = new EnvironmentService(output);
22259
22705
  try {
@@ -22908,7 +23354,7 @@ Error: ${error.message}`));
22908
23354
 
22909
23355
  // src/commands/workflow/commands/search.ts
22910
23356
  import chalk78 from "chalk";
22911
- import { wrapFunction as wrapFunction3 } from "@ai-setting/roy-agent-core";
23357
+ import { wrapFunction as wrapFunction4 } from "@ai-setting/roy-agent-core";
22912
23358
  var WorkflowSearchCommand = {
22913
23359
  command: "search",
22914
23360
  describe: "Search workflows by keyword and/or tags (multiple tags use AND filter). v2: returns available_tags.",
@@ -23083,14 +23529,14 @@ var _runWorkflowSearchImpl = async function(opts) {
23083
23529
  }
23084
23530
  }
23085
23531
  };
23086
- var runWorkflowSearch = wrapFunction3(_runWorkflowSearchImpl, "workflow.cli.search", {
23532
+ var runWorkflowSearch = wrapFunction4(_runWorkflowSearchImpl, "workflow.cli.search", {
23087
23533
  recordParams: true,
23088
23534
  recordResult: false,
23089
23535
  log: false
23090
23536
  });
23091
23537
 
23092
23538
  // src/commands/workflow/commands/tag.ts
23093
- import { wrapFunction as wrapFunction4 } from "@ai-setting/roy-agent-core";
23539
+ import { wrapFunction as wrapFunction5 } from "@ai-setting/roy-agent-core";
23094
23540
  import chalk79 from "chalk";
23095
23541
  var WorkflowTagListCommand = {
23096
23542
  command: "list",
@@ -23290,12 +23736,12 @@ function formatDate2(iso) {
23290
23736
  return iso;
23291
23737
  }
23292
23738
  }
23293
- var runWorkflowTagList = wrapFunction4(_runWorkflowTagListImpl, "workflow.cli.tag.list", {
23739
+ var runWorkflowTagList = wrapFunction5(_runWorkflowTagListImpl, "workflow.cli.tag.list", {
23294
23740
  recordParams: true,
23295
23741
  recordResult: false,
23296
23742
  log: false
23297
23743
  });
23298
- var runWorkflowTagGet = wrapFunction4(_runWorkflowTagGetImpl, "workflow.cli.tag.get", {
23744
+ var runWorkflowTagGet = wrapFunction5(_runWorkflowTagGetImpl, "workflow.cli.tag.get", {
23299
23745
  recordParams: true,
23300
23746
  recordResult: false,
23301
23747
  log: false