@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.
package/dist/index.js CHANGED
@@ -903,7 +903,7 @@ var init_status_bar = __esm(() => {
903
903
  var require_package = __commonJS((exports, module) => {
904
904
  module.exports = {
905
905
  name: "@ai-setting/roy-agent-cli",
906
- version: "1.6.15",
906
+ version: "1.6.16",
907
907
  type: "module",
908
908
  description: "CLI for roy-agent - Non-interactive command execution",
909
909
  main: "./dist/index.js",
@@ -1065,10 +1065,187 @@ function execAsync(cmd, args) {
1065
1065
  }
1066
1066
  var init_clipboard_helper = () => {};
1067
1067
 
1068
- // src/commands/markdown-renderer.tsx
1068
+ // src/commands/ui/commands-registry.ts
1069
+ function filterCommands(query) {
1070
+ const q = query.trim().replace(/^\/+/, "").toLowerCase();
1071
+ if (q === "") {
1072
+ return [...COMMANDS];
1073
+ }
1074
+ return COMMANDS.filter((c) => {
1075
+ const cmdName = c.cmd.replace(/^\/+/, "").toLowerCase();
1076
+ if (cmdName.startsWith(q))
1077
+ return true;
1078
+ if (cmdName.includes(q))
1079
+ return true;
1080
+ if (c.aliases) {
1081
+ for (const a of c.aliases) {
1082
+ if (a.toLowerCase().startsWith(q))
1083
+ return true;
1084
+ if (a.toLowerCase().includes(q))
1085
+ return true;
1086
+ }
1087
+ }
1088
+ return false;
1089
+ });
1090
+ }
1091
+ var COMMANDS, MAX_POPUP_ITEMS = 8;
1092
+ var init_commands_registry = __esm(() => {
1093
+ COMMANDS = [
1094
+ { cmd: "/help", desc: "Show all commands", category: "general", aliases: ["h"] },
1095
+ { cmd: "/quit", desc: "Exit interactive mode", category: "general", aliases: ["q", "exit"] },
1096
+ { cmd: "/init", desc: "Create memory file", category: "memory" },
1097
+ { cmd: "/memory", desc: "Show memory", category: "memory" },
1098
+ { cmd: "/model", desc: "Switch model", category: "model" },
1099
+ { cmd: "/compact", desc: "Compress context", category: "session", aliases: ["c"] },
1100
+ { cmd: "/sessions", desc: "List sessions", category: "session", aliases: ["s"] },
1101
+ { cmd: "/attach", desc: "Add file/URL to attach", category: "attachment" },
1102
+ { cmd: "/list", desc: "List attachments", category: "attachment" },
1103
+ { cmd: "/paste", desc: "Paste from clipboard", category: "attachment" },
1104
+ { cmd: "/clear", desc: "Clear attach list", category: "attachment", aliases: ["cls"] },
1105
+ { cmd: "/status", desc: "Show session status", category: "system", aliases: ["st"] },
1106
+ { cmd: "/abort", desc: "Abort in-flight request", category: "system" }
1107
+ ];
1108
+ });
1109
+
1110
+ // src/commands/ui/slash-command-popup.tsx
1069
1111
  import * as React from "react";
1070
- import { Box, Text } from "ink";
1112
+ import { Box, Text, useInput } from "ink";
1113
+ import { jsxDEV } from "react/jsx-dev-runtime";
1114
+ function clampSelectedIndex(index, filteredLength) {
1115
+ if (filteredLength === 0)
1116
+ return 0;
1117
+ return Math.max(0, Math.min(filteredLength - 1, index));
1118
+ }
1119
+ var CommandRow, SlashCommandPopup;
1120
+ var init_slash_command_popup = __esm(() => {
1121
+ init_commands_registry();
1122
+ CommandRow = React.memo(function CommandRow2({
1123
+ cmd,
1124
+ isSelected
1125
+ }) {
1126
+ const cmdPadded = cmd.cmd.padEnd(12, " ");
1127
+ if (isSelected) {
1128
+ return /* @__PURE__ */ jsxDEV(Text, {
1129
+ inverse: true,
1130
+ children: [
1131
+ "▶ ",
1132
+ cmdPadded,
1133
+ cmd.desc
1134
+ ]
1135
+ }, cmd.cmd, true, undefined, this);
1136
+ }
1137
+ return /* @__PURE__ */ jsxDEV(Text, {
1138
+ children: [
1139
+ " ",
1140
+ cmdPadded,
1141
+ /* @__PURE__ */ jsxDEV(Text, {
1142
+ color: "gray",
1143
+ children: cmd.desc
1144
+ }, undefined, false, undefined, this)
1145
+ ]
1146
+ }, cmd.cmd, true, undefined, this);
1147
+ });
1148
+ SlashCommandPopup = React.memo(function SlashCommandPopup2({
1149
+ query,
1150
+ selectedIndex: externalSelectedIndex,
1151
+ onIndexChange,
1152
+ onSelect,
1153
+ onClose
1154
+ }) {
1155
+ const filtered = React.useMemo(() => filterCommands(query), [query]);
1156
+ const [internalSelectedIndex, setInternalSelectedIndex] = React.useState(() => externalSelectedIndex ?? 0);
1157
+ React.useEffect(() => {
1158
+ if (externalSelectedIndex !== undefined && externalSelectedIndex !== internalSelectedIndex) {
1159
+ setInternalSelectedIndex(externalSelectedIndex);
1160
+ }
1161
+ }, [externalSelectedIndex, internalSelectedIndex]);
1162
+ const updateIndex = React.useCallback((next) => {
1163
+ setInternalSelectedIndex(next);
1164
+ onIndexChange?.(next);
1165
+ }, [onIndexChange]);
1166
+ React.useEffect(() => {
1167
+ if (filtered.length === 0)
1168
+ return;
1169
+ if (internalSelectedIndex >= filtered.length) {
1170
+ updateIndex(0);
1171
+ }
1172
+ }, [filtered, internalSelectedIndex, updateIndex]);
1173
+ useInput((input, key) => {
1174
+ if (key.upArrow) {
1175
+ if (filtered.length === 0)
1176
+ return;
1177
+ updateIndex((internalSelectedIndex - 1 + filtered.length) % filtered.length);
1178
+ return;
1179
+ }
1180
+ if (key.downArrow) {
1181
+ if (filtered.length === 0)
1182
+ return;
1183
+ updateIndex((internalSelectedIndex + 1) % filtered.length);
1184
+ return;
1185
+ }
1186
+ if (key.return && !key.meta && !key.shift && !key.ctrl) {
1187
+ const cmd = filtered[internalSelectedIndex];
1188
+ if (cmd && onSelect) {
1189
+ onSelect(cmd);
1190
+ }
1191
+ return;
1192
+ }
1193
+ if (key.tab) {
1194
+ const cmd = filtered[internalSelectedIndex];
1195
+ if (cmd && onSelect) {
1196
+ onSelect(cmd);
1197
+ }
1198
+ return;
1199
+ }
1200
+ if (key.escape) {
1201
+ if (onClose) {
1202
+ onClose();
1203
+ }
1204
+ return;
1205
+ }
1206
+ }, { isActive: filtered.length > 0 });
1207
+ if (filtered.length === 0) {
1208
+ return null;
1209
+ }
1210
+ const selectedIndex = Math.max(0, Math.min(filtered.length - 1, internalSelectedIndex));
1211
+ const filteredLength = filtered.length;
1212
+ const scrollOffset = filteredLength <= MAX_POPUP_ITEMS ? 0 : Math.max(0, Math.min(filteredLength - MAX_POPUP_ITEMS, selectedIndex - 3));
1213
+ const visible = filtered.slice(scrollOffset, scrollOffset + MAX_POPUP_ITEMS);
1214
+ const hiddenBefore = scrollOffset;
1215
+ const hiddenAfter = filteredLength - (scrollOffset + visible.length);
1216
+ const windowedIndex = selectedIndex - scrollOffset;
1217
+ return /* @__PURE__ */ jsxDEV(Box, {
1218
+ flexDirection: "column",
1219
+ borderStyle: "single",
1220
+ borderColor: "cyan",
1221
+ paddingX: 1,
1222
+ marginBottom: 0,
1223
+ children: [
1224
+ /* @__PURE__ */ jsxDEV(Text, {
1225
+ color: "gray",
1226
+ dimColor: true,
1227
+ children: [
1228
+ "Commands (",
1229
+ filteredLength,
1230
+ ")",
1231
+ hiddenBefore > 0 ? ` · ${hiddenBefore} more ↑` : "",
1232
+ hiddenAfter > 0 ? ` · ${hiddenAfter} more ↓` : ""
1233
+ ]
1234
+ }, undefined, true, undefined, this),
1235
+ visible.map((cmd, i) => /* @__PURE__ */ jsxDEV(CommandRow, {
1236
+ cmd,
1237
+ isSelected: i === windowedIndex
1238
+ }, cmd.cmd, false, undefined, this))
1239
+ ]
1240
+ }, undefined, true, undefined, this);
1241
+ });
1242
+ });
1243
+
1244
+ // src/commands/markdown-renderer.tsx
1245
+ import * as React2 from "react";
1246
+ import { Box as Box2, Text as Text2 } from "ink";
1071
1247
  import chalk6 from "chalk";
1248
+ import { wrapFunction } from "@ai-setting/roy-agent-core";
1072
1249
  function parseInline(text, keyPrefix) {
1073
1250
  const nodes = [];
1074
1251
  const pattern = /(`([^`]+)`)|(\*\*([^*]+)\*\*)|(\*([^*]+)\*)|(~~([^~]+)~~)|(\[([^\]]+)\]\(([^)]+)\))/g;
@@ -1077,30 +1254,144 @@ function parseInline(text, keyPrefix) {
1077
1254
  let counter = 0;
1078
1255
  while ((match = pattern.exec(text)) !== null) {
1079
1256
  if (match.index > lastIndex) {
1080
- nodes.push(React.createElement(Text, { key: `${keyPrefix}-t-${counter++}` }, text.slice(lastIndex, match.index)));
1257
+ nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-t-${counter++}` }, text.slice(lastIndex, match.index)));
1081
1258
  }
1082
1259
  if (match[1] !== undefined) {
1083
- nodes.push(React.createElement(Text, { key: `${keyPrefix}-c-${counter++}`, color: "white", backgroundColor: "gray" }, ` ${match[2]} `));
1260
+ nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-c-${counter++}`, color: "white", backgroundColor: "gray" }, ` ${match[2]} `));
1084
1261
  } else if (match[3] !== undefined) {
1085
- nodes.push(React.createElement(Text, { key: `${keyPrefix}-b-${counter++}`, color: "yellow", bold: true }, match[4]));
1262
+ nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-b-${counter++}`, color: "yellow", bold: true }, match[4]));
1086
1263
  } else if (match[5] !== undefined) {
1087
- nodes.push(React.createElement(Text, { key: `${keyPrefix}-i-${counter++}`, color: "yellow" }, match[6]));
1264
+ nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-i-${counter++}`, color: "yellow" }, match[6]));
1088
1265
  } else if (match[7] !== undefined) {
1089
- nodes.push(React.createElement(Text, { key: `${keyPrefix}-s-${counter++}`, dimColor: true }, match[8]));
1266
+ nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-s-${counter++}`, dimColor: true }, match[8]));
1090
1267
  } else if (match[9] !== undefined) {
1091
- 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]})`));
1268
+ 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]})`));
1092
1269
  }
1093
1270
  lastIndex = pattern.lastIndex;
1094
1271
  }
1095
1272
  if (lastIndex < text.length) {
1096
- nodes.push(React.createElement(Text, { key: `${keyPrefix}-e-${counter++}` }, text.slice(lastIndex)));
1273
+ nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-e-${counter++}` }, text.slice(lastIndex)));
1097
1274
  }
1098
1275
  if (nodes.length === 0) {
1099
- nodes.push(React.createElement(Text, { key: `${keyPrefix}-all` }, text));
1276
+ nodes.push(React2.createElement(Text2, { key: `${keyPrefix}-all` }, text));
1100
1277
  }
1101
1278
  return nodes;
1102
1279
  }
1103
- function renderMarkdown(content) {
1280
+ function splitTableRow(rawLine) {
1281
+ let s = rawLine.trim();
1282
+ if (s.startsWith("|"))
1283
+ s = s.slice(1);
1284
+ if (s.endsWith("|") && !s.endsWith("\\|"))
1285
+ s = s.slice(0, -1);
1286
+ return s.split("|").map((c) => c.trim());
1287
+ }
1288
+ function isTableSeparator(line) {
1289
+ const trimmed = line.trim();
1290
+ if (!trimmed.includes("|"))
1291
+ return false;
1292
+ const cells = splitTableRow(trimmed);
1293
+ if (cells.length === 0)
1294
+ return false;
1295
+ return cells.every((c) => /^:?\s*-{1,}\s*:?$/.test(c));
1296
+ }
1297
+ function parseAlignments(sepCells) {
1298
+ return sepCells.map((c) => {
1299
+ const t = c.trim();
1300
+ const startsColon = t.startsWith(":");
1301
+ const endsColon = t.endsWith(":");
1302
+ if (startsColon && endsColon)
1303
+ return "center";
1304
+ if (endsColon)
1305
+ return "right";
1306
+ if (startsColon)
1307
+ return "left";
1308
+ return "left";
1309
+ });
1310
+ }
1311
+ function padCell(content, width, align) {
1312
+ const len = content.length;
1313
+ if (len >= width)
1314
+ return content;
1315
+ const totalPad = width - len;
1316
+ if (align === "right")
1317
+ return " ".repeat(totalPad) + content;
1318
+ if (align === "center") {
1319
+ const left = Math.floor(totalPad / 2);
1320
+ const right = totalPad - left;
1321
+ return " ".repeat(left) + content + " ".repeat(right);
1322
+ }
1323
+ return content + " ".repeat(totalPad);
1324
+ }
1325
+ function parseTableStart(lines, i) {
1326
+ const header = lines[i] ?? "";
1327
+ const sep = lines[i + 1] ?? "";
1328
+ if (!header.trim().startsWith("|"))
1329
+ return false;
1330
+ if (!header.trim().includes("|"))
1331
+ return false;
1332
+ if (!isTableSeparator(sep))
1333
+ return false;
1334
+ return true;
1335
+ }
1336
+ function parseTableBlock(lines, startIndex) {
1337
+ if (!parseTableStart(lines, startIndex))
1338
+ return null;
1339
+ const header = splitTableRow(lines[startIndex] ?? "");
1340
+ const alignments = parseAlignments(splitTableRow(lines[startIndex + 1] ?? ""));
1341
+ const rows = [];
1342
+ let i = startIndex + 2;
1343
+ while (i < lines.length) {
1344
+ const ln = lines[i] ?? "";
1345
+ if (ln.trim() === "")
1346
+ break;
1347
+ if (!ln.trim().startsWith("|"))
1348
+ break;
1349
+ rows.push(splitTableRow(ln));
1350
+ i++;
1351
+ }
1352
+ return { header, rows, alignments, endIndex: i };
1353
+ }
1354
+ function renderTableBlock(tbl, key) {
1355
+ const colCount = Math.max(tbl.header.length, ...tbl.rows.map((r) => r.length));
1356
+ const widths = [];
1357
+ for (let c = 0;c < colCount; c++) {
1358
+ const headerW = (tbl.header[c] ?? "").length;
1359
+ let dataW = 0;
1360
+ for (const r of tbl.rows) {
1361
+ const cell = r[c] ?? "";
1362
+ if (cell.length > dataW)
1363
+ dataW = cell.length;
1364
+ }
1365
+ widths.push(Math.max(headerW, dataW));
1366
+ }
1367
+ const alignments = [];
1368
+ for (let c = 0;c < colCount; c++) {
1369
+ alignments.push(tbl.alignments[c] ?? "left");
1370
+ }
1371
+ const renderRow = (cells, rowIdx) => {
1372
+ const cellNodes = [];
1373
+ for (let c = 0;c < colCount; c++) {
1374
+ const raw = cells[c] ?? "";
1375
+ const w = widths[c] ?? raw.length;
1376
+ const align = alignments[c] ?? "left";
1377
+ const padded = padCell(raw, w, align);
1378
+ cellNodes.push(React2.createElement(Box2, { key: `tbl-${rowIdx}-c${c}`, flexDirection: "row" }, ...parseInline(padded, `tbl-${rowIdx}-c${c}`)));
1379
+ if (c < colCount - 1) {
1380
+ cellNodes.push(React2.createElement(Text2, { key: `tbl-${rowIdx}-sep${c}`, color: "gray" }, " │ "));
1381
+ }
1382
+ }
1383
+ return React2.createElement(Box2, { key: `tbl-${rowIdx}`, flexDirection: "row" }, React2.createElement(Text2, { color: "gray" }, "│ "), ...cellNodes, React2.createElement(Text2, { color: "gray" }, " │"));
1384
+ };
1385
+ const children = [];
1386
+ children.push(renderRow(tbl.header, 0));
1387
+ const sepLine = "├" + widths.map((w) => "─".repeat(w + 2)).join("┼") + "┤";
1388
+ children.push(React2.createElement(Text2, { key: "tbl-sep", color: "gray" }, sepLine));
1389
+ tbl.rows.forEach((r, ri) => {
1390
+ children.push(renderRow(r, ri + 1));
1391
+ });
1392
+ return React2.createElement(Box2, { key, flexDirection: "column", marginY: 1 }, ...children);
1393
+ }
1394
+ function renderMarkdownLegacyImpl(content) {
1104
1395
  const lines = content.split(`
1105
1396
  `);
1106
1397
  const blocks = [];
@@ -1116,19 +1407,19 @@ function renderMarkdown(content) {
1116
1407
  i++;
1117
1408
  }
1118
1409
  i++;
1119
- blocks.push(React.createElement(Box, {
1410
+ blocks.push(React2.createElement(Box2, {
1120
1411
  key: `blk-code-${blockKey++}`,
1121
1412
  flexDirection: "column",
1122
1413
  borderStyle: "single",
1123
1414
  borderColor: "gray",
1124
1415
  paddingX: 1,
1125
1416
  marginY: 1
1126
- }, React.createElement(Text, { color: "white" }, codeLines.length === 0 ? " " : codeLines.join(`
1417
+ }, React2.createElement(Text2, { color: "white" }, codeLines.length === 0 ? " " : codeLines.join(`
1127
1418
  `))));
1128
1419
  continue;
1129
1420
  }
1130
1421
  if (/^(-{3,}|\*{3,})$/.test(line.trim())) {
1131
- blocks.push(React.createElement(Box, { key: `blk-hr-${blockKey++}`, marginY: 1 }, React.createElement(Text, { color: "gray" }, "─".repeat(50))));
1422
+ blocks.push(React2.createElement(Box2, { key: `blk-hr-${blockKey++}`, marginY: 1 }, React2.createElement(Text2, { color: "gray" }, "─".repeat(50))));
1132
1423
  i++;
1133
1424
  continue;
1134
1425
  }
@@ -1138,10 +1429,10 @@ function renderMarkdown(content) {
1138
1429
  const text = headingMatch[2];
1139
1430
  if (level === 1) {
1140
1431
  const styled = chalk6.cyan.bold.underline(`▌ ${text}`);
1141
- blocks.push(React.createElement(Box, { key: `blk-h1-${blockKey++}`, marginY: 1 }, React.createElement(Text, {}, styled)));
1432
+ blocks.push(React2.createElement(Box2, { key: `blk-h1-${blockKey++}`, marginY: 1 }, React2.createElement(Text2, {}, styled)));
1142
1433
  } else if (level === 2) {
1143
1434
  const styled = chalk6.green.bold(`▶ ${text}`);
1144
- blocks.push(React.createElement(Box, { key: `blk-h2-${blockKey++}`, marginY: 1 }, React.createElement(Text, {}, styled)));
1435
+ blocks.push(React2.createElement(Box2, { key: `blk-h2-${blockKey++}`, marginY: 1 }, React2.createElement(Text2, {}, styled)));
1145
1436
  } else {
1146
1437
  const colors = {
1147
1438
  3: "yellow",
@@ -1151,7 +1442,7 @@ function renderMarkdown(content) {
1151
1442
  };
1152
1443
  const color = colors[level] ?? "white";
1153
1444
  const prefix = "▶".repeat(level - 1) + " ";
1154
- blocks.push(React.createElement(Box, { key: `blk-h-${blockKey++}`, marginY: 1 }, React.createElement(Text, { color, bold: true }, `${prefix}${text}`)));
1445
+ blocks.push(React2.createElement(Box2, { key: `blk-h-${blockKey++}`, marginY: 1 }, React2.createElement(Text2, { color, bold: true }, `${prefix}${text}`)));
1155
1446
  }
1156
1447
  i++;
1157
1448
  continue;
@@ -1162,7 +1453,7 @@ function renderMarkdown(content) {
1162
1453
  quoteLines.push((lines[i] ?? "").replace(/^>\s?/, ""));
1163
1454
  i++;
1164
1455
  }
1165
- blocks.push(React.createElement(Box, {
1456
+ blocks.push(React2.createElement(Box2, {
1166
1457
  key: `blk-q-${blockKey++}`,
1167
1458
  flexDirection: "column",
1168
1459
  marginLeft: 2,
@@ -1173,7 +1464,7 @@ function renderMarkdown(content) {
1173
1464
  borderRight: false,
1174
1465
  borderBottom: false,
1175
1466
  paddingLeft: 1
1176
- }, ...quoteLines.map((ql, qi) => React.createElement(Box, { key: `q-${qi}` }, React.createElement(Text, { color: "gray", dimColor: true }, ql)))));
1467
+ }, ...quoteLines.map((ql, qi) => React2.createElement(Box2, { key: `q-${qi}` }, React2.createElement(Text2, { color: "gray", dimColor: true }, ql)))));
1177
1468
  continue;
1178
1469
  }
1179
1470
  if (/^[-*]\s+/.test(line)) {
@@ -1182,7 +1473,7 @@ function renderMarkdown(content) {
1182
1473
  items.push((lines[i] ?? "").replace(/^[-*]\s+/, ""));
1183
1474
  i++;
1184
1475
  }
1185
- 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}`)))));
1476
+ 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}`)))));
1186
1477
  continue;
1187
1478
  }
1188
1479
  if (/^\d+\.\s+/.test(line)) {
@@ -1191,9 +1482,17 @@ function renderMarkdown(content) {
1191
1482
  items.push((lines[i] ?? "").replace(/^\d+\.\s+/, ""));
1192
1483
  i++;
1193
1484
  }
1194
- 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}`)))));
1485
+ 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}`)))));
1195
1486
  continue;
1196
1487
  }
1488
+ if (parseTableStart(lines, i)) {
1489
+ const tbl = parseTableBlock(lines, i);
1490
+ if (tbl) {
1491
+ i = tbl.endIndex;
1492
+ blocks.push(renderTableBlock(tbl, `blk-table-${blockKey++}`));
1493
+ continue;
1494
+ }
1495
+ }
1197
1496
  if (line.trim() === "") {
1198
1497
  i++;
1199
1498
  continue;
@@ -1204,11 +1503,22 @@ function renderMarkdown(content) {
1204
1503
  i++;
1205
1504
  }
1206
1505
  const paraText = paraLines.join(" ");
1207
- blocks.push(React.createElement(Box, { key: `blk-p-${blockKey++}`, marginY: 0 }, ...parseInline(paraText, `p-${blockKey}`)));
1506
+ blocks.push(React2.createElement(Box2, { key: `blk-p-${blockKey++}`, marginY: 0 }, ...parseInline(paraText, `p-${blockKey}`)));
1208
1507
  }
1209
1508
  return blocks;
1210
1509
  }
1211
- var init_markdown_renderer2 = () => {};
1510
+ var renderMarkdown;
1511
+ var init_markdown_renderer2 = __esm(() => {
1512
+ renderMarkdown = wrapFunction(renderMarkdownLegacyImpl, "markdown.render", {
1513
+ recordParams: true,
1514
+ recordResult: false,
1515
+ paramFilter: (args) => ({
1516
+ "content.length": (args?.[0] && typeof args[0] === "string" ? args[0].length : 0) ?? 0,
1517
+ "content.first-line": (args?.[0] && typeof args[0] === "string" ? args[0].split(`
1518
+ `)[0]?.slice(0, 60) : "") ?? ""
1519
+ })
1520
+ });
1521
+ });
1212
1522
 
1213
1523
  // src/commands/repl-ink.tsx
1214
1524
  var exports_repl_ink = {};
@@ -1217,10 +1527,10 @@ __export(exports_repl_ink, {
1217
1527
  REPLInk: () => REPLInk,
1218
1528
  MultilineInput: () => MultilineInput
1219
1529
  });
1220
- import * as React2 from "react";
1221
- import { Box as Box2, Text as Text2, useApp, useInput } from "ink";
1530
+ import * as React3 from "react";
1531
+ import { Box as Box3, Text as Text3, Static, useApp, useInput as useInput2 } from "ink";
1222
1532
  import { createLogger as createLogger4 } from "@ai-setting/roy-agent-core";
1223
- import { jsxDEV } from "react/jsx-dev-runtime";
1533
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
1224
1534
  function REPLInk(props) {
1225
1535
  const {
1226
1536
  initialContext,
@@ -1233,19 +1543,55 @@ function REPLInk(props) {
1233
1543
  onEscape
1234
1544
  } = props;
1235
1545
  const { exit: appExit } = useApp();
1236
- const [messages, setMessages] = React2.useState(initialMessages);
1237
- const [mode, setMode] = React2.useState(initialMode);
1238
- const [statusBarCtx, setStatusBarCtxState] = React2.useState({
1546
+ const [messages, setMessages] = React3.useState(() => [
1547
+ {
1548
+ role: "system",
1549
+ kind: "welcome",
1550
+ content: buildWelcomeCardText(initialContext)
1551
+ },
1552
+ ...initialMessages
1553
+ ]);
1554
+ const [mode, setMode] = React3.useState(initialMode);
1555
+ const [statusBarCtx, setStatusBarCtxState] = React3.useState({
1239
1556
  mode: initialMode,
1240
1557
  cwd: initialStatusBarCtx.cwd ?? initialContext.cwd,
1241
1558
  gitBranch: initialStatusBarCtx.gitBranch,
1242
1559
  model: initialStatusBarCtx.model ?? initialContext.model
1243
1560
  });
1244
- const streamingIndexRef = React2.useRef(-1);
1245
- const multilineInputRef = React2.useRef(null);
1246
- const pendingDeltaRef = React2.useRef("");
1247
- const throttleTimerRef = React2.useRef(null);
1248
- const flushStreamingDelta = React2.useCallback(() => {
1561
+ const [inputValue, setInputValue] = React3.useState("");
1562
+ const [popupIndex, setPopupIndex] = React3.useState(0);
1563
+ const filteredCmds = React3.useMemo(() => {
1564
+ if (!/^\/\S*$/.test(inputValue))
1565
+ return [];
1566
+ return filterCommands(inputValue);
1567
+ }, [inputValue]);
1568
+ const showPopup = filteredCmds.length > 0;
1569
+ React3.useEffect(() => {
1570
+ setPopupIndex(0);
1571
+ }, [filteredCmds]);
1572
+ const safePopupIndex = clampSelectedIndex(popupIndex, filteredCmds.length);
1573
+ const handlePopupSelect = React3.useCallback((cmd) => {
1574
+ multilineInputRef.current?.setBuffer(cmd.cmd + " ");
1575
+ setInputValue(cmd.cmd + " ");
1576
+ }, []);
1577
+ const handlePopupClose = React3.useCallback(() => {
1578
+ const current = multilineInputRef.current?.getBuffer() ?? "";
1579
+ const stripped = current.replace(/^\/+/, "");
1580
+ multilineInputRef.current?.setBuffer(stripped);
1581
+ setInputValue(stripped);
1582
+ }, []);
1583
+ const handlePopupIndexChange = React3.useCallback((idx) => {
1584
+ setPopupIndex(idx);
1585
+ }, []);
1586
+ const streamingIndexRef = React3.useRef(-1);
1587
+ const lastFlushTsRef = React3.useRef(0);
1588
+ const STALE_STREAM_THRESHOLD_MS = 1000;
1589
+ const multilineInputRef = React3.useRef(null);
1590
+ const lastEscapeTsRef = React3.useRef(0);
1591
+ const pendingDeltaRef = React3.useRef("");
1592
+ const throttleTimerRef = React3.useRef(null);
1593
+ const isFirstDeltaInStreamRef = React3.useRef(true);
1594
+ const flushStreamingDelta = React3.useCallback(() => {
1249
1595
  const delta = pendingDeltaRef.current;
1250
1596
  pendingDeltaRef.current = "";
1251
1597
  throttleTimerRef.current = null;
@@ -1259,6 +1605,11 @@ function REPLInk(props) {
1259
1605
  break;
1260
1606
  }
1261
1607
  }
1608
+ if (idx !== -1 && Date.now() - lastFlushTsRef.current > STALE_STREAM_THRESHOLD_MS) {
1609
+ const updated2 = [...msgs];
1610
+ updated2[idx] = { ...updated2[idx], streaming: false };
1611
+ idx = -1;
1612
+ }
1262
1613
  if (idx === -1) {
1263
1614
  streamingIndexRef.current = msgs.length;
1264
1615
  return [...msgs, { role: "assistant", content: delta, streaming: true }];
@@ -1267,8 +1618,9 @@ function REPLInk(props) {
1267
1618
  updated[idx] = { ...updated[idx], content: updated[idx].content + delta };
1268
1619
  return updated;
1269
1620
  });
1621
+ lastFlushTsRef.current = Date.now();
1270
1622
  }, []);
1271
- React2.useEffect(() => {
1623
+ React3.useEffect(() => {
1272
1624
  return () => {
1273
1625
  if (throttleTimerRef.current !== null) {
1274
1626
  clearTimeout(throttleTimerRef.current);
@@ -1276,8 +1628,8 @@ function REPLInk(props) {
1276
1628
  }
1277
1629
  };
1278
1630
  }, []);
1279
- const apiRef = React2.useRef(null);
1280
- React2.useEffect(() => {
1631
+ const apiRef = React3.useRef(null);
1632
+ React3.useEffect(() => {
1281
1633
  const api = {
1282
1634
  appendMessage: (msg) => {
1283
1635
  setMessages((msgs) => [...msgs, msg]);
@@ -1287,7 +1639,12 @@ function REPLInk(props) {
1287
1639
  return;
1288
1640
  pendingDeltaRef.current += delta;
1289
1641
  if (throttleTimerRef.current === null) {
1290
- throttleTimerRef.current = setTimeout(flushStreamingDelta, 50);
1642
+ if (isFirstDeltaInStreamRef.current) {
1643
+ isFirstDeltaInStreamRef.current = false;
1644
+ flushStreamingDelta();
1645
+ } else {
1646
+ throttleTimerRef.current = setTimeout(flushStreamingDelta, 50);
1647
+ }
1291
1648
  }
1292
1649
  },
1293
1650
  finishAssistantStream: () => {
@@ -1311,6 +1668,7 @@ function REPLInk(props) {
1311
1668
  return updated;
1312
1669
  });
1313
1670
  streamingIndexRef.current = -1;
1671
+ isFirstDeltaInStreamRef.current = true;
1314
1672
  },
1315
1673
  setMode: (newMode) => {
1316
1674
  setMode(newMode);
@@ -1320,7 +1678,13 @@ function REPLInk(props) {
1320
1678
  setStatusBarCtxState((s) => ({ ...s, ...ctx }));
1321
1679
  },
1322
1680
  clearMessages: () => {
1323
- setMessages([]);
1681
+ setMessages([
1682
+ {
1683
+ role: "system",
1684
+ kind: "welcome",
1685
+ content: buildWelcomeCardText(initialContext)
1686
+ }
1687
+ ]);
1324
1688
  },
1325
1689
  exit: () => {
1326
1690
  appExit();
@@ -1329,19 +1693,42 @@ function REPLInk(props) {
1329
1693
  if (onCommand) {
1330
1694
  Promise.resolve(onCommand("compact")).catch(() => {});
1331
1695
  }
1696
+ },
1697
+ setInputBuffer: (value) => {
1698
+ multilineInputRef.current?.setBuffer(value);
1699
+ setInputValue(value);
1700
+ },
1701
+ getInputBuffer: () => {
1702
+ return multilineInputRef.current?.getBuffer() ?? "";
1332
1703
  }
1333
1704
  };
1334
1705
  apiRef.current = api;
1335
1706
  onReady?.(api);
1336
1707
  }, [appExit, onCommand, onReady]);
1337
- useInput((_input, key) => {
1708
+ const handleEscapeCascade = React3.useCallback(() => {
1709
+ const now = Date.now();
1710
+ if (now - lastEscapeTsRef.current < 100) {
1711
+ return;
1712
+ }
1713
+ lastEscapeTsRef.current = now;
1714
+ if (onEscape) {
1715
+ Promise.resolve().then(() => onEscape()).catch((err) => {
1716
+ inkLogger.warn(`[REPLInk] onEscape failed: ${err}`);
1717
+ });
1718
+ }
1719
+ }, [onEscape]);
1720
+ useInput2((_input, key) => {
1721
+ if (showPopup) {
1722
+ if (key.escape || key.upArrow || key.downArrow || key.tab) {
1723
+ return;
1724
+ }
1725
+ if (key.return && !key.meta && !key.shift && !key.ctrl) {
1726
+ return;
1727
+ }
1728
+ }
1338
1729
  if (key.escape) {
1339
1730
  multilineInputRef.current?.clearBuffer();
1340
- if (onEscape) {
1341
- Promise.resolve().then(() => onEscape()).catch((err) => {
1342
- inkLogger.warn(`[REPLInk] onEscape failed: ${err}`);
1343
- });
1344
- }
1731
+ handleEscapeCascade();
1345
1732
  }
1346
1733
  if (key.ctrl && key.c === true) {
1347
1734
  if (onCommand) {
@@ -1362,7 +1749,7 @@ function REPLInk(props) {
1362
1749
  }
1363
1750
  }
1364
1751
  });
1365
- const handleSubmit = React2.useCallback(async (value) => {
1752
+ const handleSubmit = React3.useCallback(async (value) => {
1366
1753
  if (!value || value.trim() === "") {
1367
1754
  return;
1368
1755
  }
@@ -1388,43 +1775,60 @@ function REPLInk(props) {
1388
1775
  setMessages((msgs) => [...msgs, { role: "system", content: `[Error] ${msg}` }]);
1389
1776
  }
1390
1777
  }, [onCommand, onSubmit]);
1778
+ const staticItems = React3.useMemo(() => {
1779
+ if (messages.length <= 1)
1780
+ return [];
1781
+ return messages.slice(0, -1);
1782
+ }, [messages.length <= 1 ? 0 : messages.length - 1]);
1391
1783
  const statusBarText = buildStatusBar({
1392
1784
  mode,
1393
1785
  cwd: statusBarCtx.cwd,
1394
1786
  gitBranch: statusBarCtx.gitBranch,
1395
1787
  model: shortModel(statusBarCtx.model)
1396
1788
  });
1397
- return /* @__PURE__ */ jsxDEV(Box2, {
1789
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1398
1790
  flexDirection: "column",
1399
1791
  children: [
1400
- messages.length === 0 && /* @__PURE__ */ jsxDEV(Box2, {
1401
- flexDirection: "column",
1402
- marginBottom: 1,
1403
- children: /* @__PURE__ */ jsxDEV(Text2, {
1404
- children: buildWelcomeCardText(initialContext)
1405
- }, undefined, false, undefined, this)
1406
- }, undefined, false, undefined, this),
1407
- messages.map((msg, i) => /* @__PURE__ */ jsxDEV(MessageView, {
1408
- msg
1409
- }, i, false, undefined, this)),
1410
- /* @__PURE__ */ jsxDEV(Box2, {
1792
+ staticItems.length > 0 ? /* @__PURE__ */ jsxDEV2(Static, {
1793
+ items: staticItems,
1794
+ children: (msg, i) => /* @__PURE__ */ jsxDEV2(MessageView, {
1795
+ msg
1796
+ }, `h-${i}`, false, undefined, this)
1797
+ }, undefined, false, undefined, this) : null,
1798
+ messages.length > 0 ? /* @__PURE__ */ jsxDEV2(MessageView, {
1799
+ msg: messages[messages.length - 1]
1800
+ }, undefined, false, undefined, this) : null,
1801
+ /* @__PURE__ */ jsxDEV2(Box3, {
1411
1802
  flexDirection: "column",
1412
1803
  marginTop: 1,
1413
- children: /* @__PURE__ */ jsxDEV(Text2, {
1804
+ children: /* @__PURE__ */ jsxDEV2(Text3, {
1414
1805
  children: statusBarText
1415
1806
  }, undefined, false, undefined, this)
1416
1807
  }, undefined, false, undefined, this),
1417
- /* @__PURE__ */ jsxDEV(Box2, {
1808
+ showPopup ? /* @__PURE__ */ jsxDEV2(Box3, {
1809
+ marginBottom: 0,
1810
+ children: /* @__PURE__ */ jsxDEV2(SlashCommandPopup, {
1811
+ query: inputValue,
1812
+ selectedIndex: safePopupIndex,
1813
+ onIndexChange: handlePopupIndexChange,
1814
+ onSelect: handlePopupSelect,
1815
+ onClose: handlePopupClose
1816
+ }, undefined, false, undefined, this)
1817
+ }, undefined, false, undefined, this) : null,
1818
+ /* @__PURE__ */ jsxDEV2(Box3, {
1418
1819
  flexDirection: "column",
1419
1820
  children: [
1420
- /* @__PURE__ */ jsxDEV(Text2, {
1821
+ /* @__PURE__ */ jsxDEV2(Text3, {
1421
1822
  children: COLORS.muted("─".repeat(40))
1422
1823
  }, undefined, false, undefined, this),
1423
- /* @__PURE__ */ jsxDEV(MultilineInput, {
1824
+ /* @__PURE__ */ jsxDEV2(MultilineInput, {
1424
1825
  ref: multilineInputRef,
1425
- onSubmit: handleSubmit
1826
+ onSubmit: handleSubmit,
1827
+ onEscape: handleEscapeCascade,
1828
+ popupActive: showPopup,
1829
+ onChange: setInputValue
1426
1830
  }, undefined, false, undefined, this),
1427
- /* @__PURE__ */ jsxDEV(Text2, {
1831
+ /* @__PURE__ */ jsxDEV2(Text3, {
1428
1832
  children: COLORS.muted("─".repeat(40))
1429
1833
  }, undefined, false, undefined, this)
1430
1834
  ]
@@ -1443,7 +1847,7 @@ function shortModel(model) {
1443
1847
  }
1444
1848
  async function renderInkREPL(props) {
1445
1849
  const ink = await import("ink");
1446
- const { waitUntilExit } = ink.render(React2.createElement(REPLInk, props));
1850
+ const { waitUntilExit } = ink.render(React3.createElement(REPLInk, props));
1447
1851
  await waitUntilExit();
1448
1852
  }
1449
1853
  var inkLogger, MultilineInput, MessageView;
@@ -1451,19 +1855,43 @@ var init_repl_ink = __esm(() => {
1451
1855
  init_stream_output_service();
1452
1856
  init_status_bar();
1453
1857
  init_welcome_card();
1858
+ init_commands_registry();
1859
+ init_slash_command_popup();
1454
1860
  init_markdown_renderer2();
1455
1861
  inkLogger = createLogger4("repl-ink");
1456
- MultilineInput = React2.memo(React2.forwardRef(function MultilineInput2(props, ref) {
1457
- const { onSubmit, placeholder } = props;
1458
- const [buffer, setBuffer] = React2.useState("");
1459
- const [cursor, setCursor] = React2.useState(0);
1460
- React2.useImperativeHandle(ref, () => ({
1862
+ MultilineInput = React3.memo(React3.forwardRef(function MultilineInput2(props, ref) {
1863
+ const { onSubmit, placeholder, popupActive, onChange, onEscape } = props;
1864
+ const [buffer, setBuffer] = React3.useState("");
1865
+ const [cursor, setCursor] = React3.useState(0);
1866
+ React3.useEffect(() => {
1867
+ onChange?.(buffer);
1868
+ }, [buffer, onChange]);
1869
+ React3.useImperativeHandle(ref, () => ({
1461
1870
  clearBuffer: () => {
1462
1871
  setBuffer("");
1463
1872
  setCursor(0);
1873
+ },
1874
+ getBuffer: () => {
1875
+ return buffer;
1876
+ },
1877
+ setBuffer: (value) => {
1878
+ setBuffer(value);
1879
+ setCursor(value.length);
1880
+ }
1881
+ }), [buffer]);
1882
+ useInput2((input, key) => {
1883
+ if (key.escape) {
1884
+ setBuffer("");
1885
+ setCursor(0);
1886
+ if (onEscape) {
1887
+ try {
1888
+ onEscape();
1889
+ } catch (err) {
1890
+ inkLogger.warn(`[MultilineInput] onEscape failed: ${err}`);
1891
+ }
1892
+ }
1893
+ return;
1464
1894
  }
1465
- }), []);
1466
- useInput((input, key) => {
1467
1895
  if (key.return && (key.meta || key.shift || key.ctrl)) {
1468
1896
  setBuffer((b) => {
1469
1897
  const newBuf = b.slice(0, cursor) + `
@@ -1474,6 +1902,9 @@ var init_repl_ink = __esm(() => {
1474
1902
  return;
1475
1903
  }
1476
1904
  if (key.return) {
1905
+ if (popupActive) {
1906
+ return;
1907
+ }
1477
1908
  if (buffer.trim() === "") {
1478
1909
  return;
1479
1910
  }
@@ -1623,12 +2054,12 @@ var init_repl_ink = __esm(() => {
1623
2054
  }
1624
2055
  }
1625
2056
  const showPlaceholder = buffer.length === 0 && placeholder;
1626
- return /* @__PURE__ */ jsxDEV(Box2, {
2057
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1627
2058
  flexDirection: "column",
1628
2059
  children: lines.map((line, i) => {
1629
2060
  const isFirst = i === 0;
1630
2061
  const isCursorRow = i === cursorRow;
1631
- const prefixEl = /* @__PURE__ */ jsxDEV(Text2, {
2062
+ const prefixEl = /* @__PURE__ */ jsxDEV2(Text3, {
1632
2063
  color: isFirst ? "red" : "gray",
1633
2064
  children: isFirst ? "❯ " : "... "
1634
2065
  }, undefined, false, undefined, this);
@@ -1643,29 +2074,29 @@ var init_repl_ink = __esm(() => {
1643
2074
  atCursor = line[cursorCol] ?? " ";
1644
2075
  afterCursor = line.slice(cursorCol + 1);
1645
2076
  }
1646
- return /* @__PURE__ */ jsxDEV(Box2, {
2077
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1647
2078
  children: [
1648
2079
  prefixEl,
1649
- /* @__PURE__ */ jsxDEV(Text2, {
2080
+ /* @__PURE__ */ jsxDEV2(Text3, {
1650
2081
  children: beforeCursor
1651
2082
  }, undefined, false, undefined, this),
1652
- /* @__PURE__ */ jsxDEV(Text2, {
2083
+ /* @__PURE__ */ jsxDEV2(Text3, {
1653
2084
  inverse: !showPlaceholder,
1654
2085
  children: atCursor
1655
2086
  }, undefined, false, undefined, this),
1656
- showPlaceholder ? /* @__PURE__ */ jsxDEV(Text2, {
2087
+ showPlaceholder ? /* @__PURE__ */ jsxDEV2(Text3, {
1657
2088
  color: "gray",
1658
2089
  children: placeholder?.slice(1) ?? ""
1659
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV(Text2, {
2090
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV2(Text3, {
1660
2091
  children: afterCursor
1661
2092
  }, undefined, false, undefined, this)
1662
2093
  ]
1663
2094
  }, i, true, undefined, this);
1664
2095
  }
1665
- return /* @__PURE__ */ jsxDEV(Box2, {
2096
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1666
2097
  children: [
1667
2098
  prefixEl,
1668
- /* @__PURE__ */ jsxDEV(Text2, {
2099
+ /* @__PURE__ */ jsxDEV2(Text3, {
1669
2100
  children: line
1670
2101
  }, undefined, false, undefined, this)
1671
2102
  ]
@@ -1673,7 +2104,15 @@ var init_repl_ink = __esm(() => {
1673
2104
  })
1674
2105
  }, undefined, false, undefined, this);
1675
2106
  }));
1676
- MessageView = React2.memo(function MessageView2({ msg }) {
2107
+ MessageView = React3.memo(function MessageView2({ msg }) {
2108
+ if (msg.kind === "welcome") {
2109
+ return /* @__PURE__ */ jsxDEV2(Box3, {
2110
+ flexDirection: "column",
2111
+ children: /* @__PURE__ */ jsxDEV2(Text3, {
2112
+ children: msg.content
2113
+ }, undefined, false, undefined, this)
2114
+ }, undefined, false, undefined, this);
2115
+ }
1677
2116
  let prefix;
1678
2117
  let color;
1679
2118
  let contentColor;
@@ -1712,11 +2151,11 @@ var init_repl_ink = __esm(() => {
1712
2151
  }
1713
2152
  const displayContent = msg.role === "tool" || msg.role === "tool_result" ? `${msg.toolName ?? "tool"}: ${msg.content}` : msg.content;
1714
2153
  if (msg.role === "assistant") {
1715
- return /* @__PURE__ */ jsxDEV(Box2, {
2154
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1716
2155
  flexDirection: "column",
1717
2156
  children: [
1718
- /* @__PURE__ */ jsxDEV(Box2, {
1719
- children: /* @__PURE__ */ jsxDEV(Text2, {
2157
+ /* @__PURE__ */ jsxDEV2(Box3, {
2158
+ children: /* @__PURE__ */ jsxDEV2(Text3, {
1720
2159
  color: "green",
1721
2160
  bold: true,
1722
2161
  children: [
@@ -1725,12 +2164,12 @@ var init_repl_ink = __esm(() => {
1725
2164
  ]
1726
2165
  }, undefined, true, undefined, this)
1727
2166
  }, undefined, false, undefined, this),
1728
- /* @__PURE__ */ jsxDEV(Box2, {
2167
+ /* @__PURE__ */ jsxDEV2(Box3, {
1729
2168
  flexDirection: "column",
1730
2169
  marginLeft: 2,
1731
2170
  children: [
1732
2171
  renderMarkdown(displayContent),
1733
- msg.streaming ? /* @__PURE__ */ jsxDEV(Text2, {
2172
+ msg.streaming ? /* @__PURE__ */ jsxDEV2(Text3, {
1734
2173
  color: "gray",
1735
2174
  children: "▌"
1736
2175
  }, undefined, false, undefined, this) : null
@@ -1739,9 +2178,9 @@ var init_repl_ink = __esm(() => {
1739
2178
  ]
1740
2179
  }, undefined, true, undefined, this);
1741
2180
  }
1742
- return /* @__PURE__ */ jsxDEV(Box2, {
2181
+ return /* @__PURE__ */ jsxDEV2(Box3, {
1743
2182
  children: [
1744
- /* @__PURE__ */ jsxDEV(Text2, {
2183
+ /* @__PURE__ */ jsxDEV2(Text3, {
1745
2184
  color,
1746
2185
  bold: true,
1747
2186
  children: [
@@ -1749,7 +2188,7 @@ var init_repl_ink = __esm(() => {
1749
2188
  " "
1750
2189
  ]
1751
2190
  }, undefined, true, undefined, this),
1752
- /* @__PURE__ */ jsxDEV(Text2, {
2191
+ /* @__PURE__ */ jsxDEV2(Text3, {
1753
2192
  color: contentColor,
1754
2193
  children: [
1755
2194
  displayContent,
@@ -12159,6 +12598,13 @@ ${COLORS.error("❌ 执行失败: " + error)}
12159
12598
  }
12160
12599
  }
12161
12600
  abortStream();
12601
+ if (this.inkApi && typeof this.inkApi.finishAssistantStream === "function") {
12602
+ try {
12603
+ this.inkApi.finishAssistantStream();
12604
+ } catch (err) {
12605
+ logger4.warn("[Esc] finishAssistantStream failed", { error: String(err) });
12606
+ }
12607
+ }
12162
12608
  const mainSessionId = this.options.sessionId;
12163
12609
  if (this.env && mainSessionId) {
12164
12610
  let timer;
@@ -21972,9 +22418,9 @@ import chalk73 from "chalk";
21972
22418
  import fs5 from "fs";
21973
22419
  import path8 from "path";
21974
22420
  import { createRunWorkflowTool } from "@ai-setting/roy-agent-core/env/workflow/tools";
21975
- import { getTracerProvider as getTracerProvider4, propagation, wrapFunction } from "@ai-setting/roy-agent-core";
22421
+ import { getTracerProvider as getTracerProvider4, propagation, wrapFunction as wrapFunction2 } from "@ai-setting/roy-agent-core";
21976
22422
  import { isValidSessionId } from "@ai-setting/roy-agent-core/env/session";
21977
- var runWorkflow = wrapFunction(async function runWorkflowImpl(args) {
22423
+ var runWorkflow = wrapFunction2(async function runWorkflowImpl(args) {
21978
22424
  const output = new OutputService2;
21979
22425
  const envService = new EnvironmentService(output);
21980
22426
  const traceparent = process.env.TRACEPARENT;
@@ -22251,8 +22697,8 @@ var WorkflowRunCommand = {
22251
22697
  // src/commands/workflow/commands/stop.ts
22252
22698
  import chalk74 from "chalk";
22253
22699
  import { createWorkflowRunStopTool } from "@ai-setting/roy-agent-core/env/workflow/tools";
22254
- import { wrapFunction as wrapFunction2 } from "@ai-setting/roy-agent-core";
22255
- var stopWorkflow = wrapFunction2(async function stopWorkflowImpl(args) {
22700
+ import { wrapFunction as wrapFunction3 } from "@ai-setting/roy-agent-core";
22701
+ var stopWorkflow = wrapFunction3(async function stopWorkflowImpl(args) {
22256
22702
  const output = new OutputService2;
22257
22703
  const envService = new EnvironmentService(output);
22258
22704
  try {
@@ -22907,7 +23353,7 @@ Error: ${error.message}`));
22907
23353
 
22908
23354
  // src/commands/workflow/commands/search.ts
22909
23355
  import chalk78 from "chalk";
22910
- import { wrapFunction as wrapFunction3 } from "@ai-setting/roy-agent-core";
23356
+ import { wrapFunction as wrapFunction4 } from "@ai-setting/roy-agent-core";
22911
23357
  var WorkflowSearchCommand = {
22912
23358
  command: "search",
22913
23359
  describe: "Search workflows by keyword and/or tags (multiple tags use AND filter). v2: returns available_tags.",
@@ -23082,14 +23528,14 @@ var _runWorkflowSearchImpl = async function(opts) {
23082
23528
  }
23083
23529
  }
23084
23530
  };
23085
- var runWorkflowSearch = wrapFunction3(_runWorkflowSearchImpl, "workflow.cli.search", {
23531
+ var runWorkflowSearch = wrapFunction4(_runWorkflowSearchImpl, "workflow.cli.search", {
23086
23532
  recordParams: true,
23087
23533
  recordResult: false,
23088
23534
  log: false
23089
23535
  });
23090
23536
 
23091
23537
  // src/commands/workflow/commands/tag.ts
23092
- import { wrapFunction as wrapFunction4 } from "@ai-setting/roy-agent-core";
23538
+ import { wrapFunction as wrapFunction5 } from "@ai-setting/roy-agent-core";
23093
23539
  import chalk79 from "chalk";
23094
23540
  var WorkflowTagListCommand = {
23095
23541
  command: "list",
@@ -23289,12 +23735,12 @@ function formatDate2(iso) {
23289
23735
  return iso;
23290
23736
  }
23291
23737
  }
23292
- var runWorkflowTagList = wrapFunction4(_runWorkflowTagListImpl, "workflow.cli.tag.list", {
23738
+ var runWorkflowTagList = wrapFunction5(_runWorkflowTagListImpl, "workflow.cli.tag.list", {
23293
23739
  recordParams: true,
23294
23740
  recordResult: false,
23295
23741
  log: false
23296
23742
  });
23297
- var runWorkflowTagGet = wrapFunction4(_runWorkflowTagGetImpl, "workflow.cli.tag.get", {
23743
+ var runWorkflowTagGet = wrapFunction5(_runWorkflowTagGetImpl, "workflow.cli.tag.get", {
23298
23744
  recordParams: true,
23299
23745
  recordResult: false,
23300
23746
  log: false