@robota-sdk/agent-cli 3.0.0-beta.29 → 3.0.0-beta.30

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/node/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startCli
4
- } from "./chunk-74GXDZY7.js";
4
+ } from "./chunk-MCZP5QLE.js";
5
5
 
6
6
  // src/bin.ts
7
7
  process.on("uncaughtException", (err) => {
@@ -150,12 +150,38 @@ import { render } from "ink";
150
150
 
151
151
  // src/ui/App.tsx
152
152
  import { useState as useState7, useRef as useRef5 } from "react";
153
- import { Box as Box8, Text as Text10, useApp, useInput as useInput5 } from "ink";
153
+ import { Box as Box9, Text as Text11, useApp, useInput as useInput5 } from "ink";
154
154
  import { getModelName } from "@robota-sdk/agent-core";
155
155
 
156
156
  // src/ui/hooks/useSession.ts
157
157
  import { useState, useCallback, useRef } from "react";
158
158
  import { createSession, FileSessionLogger, projectPaths } from "@robota-sdk/agent-sdk";
159
+
160
+ // src/utils/edit-diff.ts
161
+ function generateDiffLines(oldStr, newStr) {
162
+ if (oldStr === newStr) return [];
163
+ const lines = [];
164
+ for (const line of oldStr.split("\n")) {
165
+ lines.push({ type: "remove", text: line });
166
+ }
167
+ for (const line of newStr.split("\n")) {
168
+ lines.push({ type: "add", text: line });
169
+ }
170
+ return lines;
171
+ }
172
+ function extractEditDiff(toolName, toolArgs) {
173
+ if (toolName !== "Edit" || !toolArgs) return null;
174
+ const filePath = toolArgs.file_path ?? toolArgs.filePath;
175
+ const oldStr = toolArgs.old_string ?? toolArgs.oldString;
176
+ const newStr = toolArgs.new_string ?? toolArgs.newString;
177
+ if (typeof filePath !== "string") return null;
178
+ if (typeof oldStr !== "string" || typeof newStr !== "string") return null;
179
+ const lines = generateDiffLines(oldStr, newStr);
180
+ if (lines.length === 0) return null;
181
+ return { file: filePath, lines };
182
+ }
183
+
184
+ // src/ui/hooks/useSession.ts
159
185
  var TOOL_ARG_DISPLAY_MAX = 80;
160
186
  var TAIL_KEEP = 30;
161
187
  var MAX_COMPLETED_TOOLS = 50;
@@ -221,14 +247,26 @@ function useSession(props) {
221
247
  }
222
248
  setActiveTools((prev) => [
223
249
  ...prev,
224
- { toolName: event.toolName, firstArg, isRunning: true }
250
+ { toolName: event.toolName, firstArg, isRunning: true, _toolArgs: event.toolArgs }
225
251
  ]);
226
252
  } else {
227
253
  const toolResult = event.denied ? "denied" : event.success === false ? "error" : "success";
228
254
  setActiveTools((prev) => {
229
- const updated = prev.map(
230
- (t) => t.toolName === event.toolName && t.isRunning ? { ...t, isRunning: false, result: toolResult } : t
231
- );
255
+ const updated = prev.map((t) => {
256
+ if (!(t.toolName === event.toolName && t.isRunning)) return t;
257
+ const editDiff = extractEditDiff(event.toolName, t._toolArgs);
258
+ const finished = {
259
+ ...t,
260
+ isRunning: false,
261
+ result: toolResult
262
+ };
263
+ if (editDiff) {
264
+ finished.diffLines = editDiff.lines;
265
+ finished.diffFile = editDiff.file;
266
+ }
267
+ delete finished._toolArgs;
268
+ return finished;
269
+ });
232
270
  const completed = updated.filter((t) => !t.isRunning);
233
271
  if (completed.length > MAX_COMPLETED_TOOLS) {
234
272
  const excess = completed.length - MAX_COMPLETED_TOOLS;
@@ -609,19 +647,33 @@ import { useCallback as useCallback4 } from "react";
609
647
  // src/utils/tool-call-extractor.ts
610
648
  var TOOL_ARG_MAX_LENGTH = 80;
611
649
  var TAIL_KEEP2 = 30;
612
- function extractToolCalls(history, startIndex) {
613
- const lines = [];
650
+ function extractToolCallsWithDiff(history, startIndex) {
651
+ const summaries = [];
614
652
  for (let i = startIndex; i < history.length; i++) {
615
653
  const msg = history[i];
616
654
  if (msg.role === "assistant" && msg.toolCalls) {
617
655
  for (const tc of msg.toolCalls) {
618
656
  const value = parseFirstArgValue(tc.function.arguments);
619
657
  const truncated = value.length > TOOL_ARG_MAX_LENGTH ? value.slice(0, TOOL_ARG_MAX_LENGTH - TAIL_KEEP2 - 3) + "..." + value.slice(-TAIL_KEEP2) : value;
620
- lines.push(`${tc.function.name}(${truncated})`);
658
+ const summary = {
659
+ line: `${tc.function.name}(${truncated})`
660
+ };
661
+ if (tc.function.name === "Edit") {
662
+ try {
663
+ const args = JSON.parse(tc.function.arguments);
664
+ const diff = extractEditDiff("Edit", args);
665
+ if (diff) {
666
+ summary.diffLines = diff.lines;
667
+ summary.diffFile = diff.file;
668
+ }
669
+ } catch {
670
+ }
671
+ }
672
+ summaries.push(summary);
621
673
  }
622
674
  }
623
675
  }
624
- return lines;
676
+ return summaries;
625
677
  }
626
678
  function parseFirstArgValue(argsJson) {
627
679
  try {
@@ -708,15 +760,15 @@ async function runSessionPrompt(prompt, session, addMessage, clearStreamingText,
708
760
  const response = await session.run(prompt, rawInput);
709
761
  clearStreamingText();
710
762
  const history = session.getHistory();
711
- const toolLines = extractToolCalls(
763
+ const toolSummaries = extractToolCallsWithDiff(
712
764
  history,
713
765
  historyBefore
714
766
  );
715
- if (toolLines.length > 0) {
767
+ if (toolSummaries.length > 0) {
716
768
  addMessage({
717
769
  role: "tool",
718
- content: toolLines.join("\n"),
719
- toolName: `${toolLines.length} tools`
770
+ content: JSON.stringify(toolSummaries),
771
+ toolName: `${toolSummaries.length} tools`
720
772
  });
721
773
  }
722
774
  addMessage({ role: "assistant", content: response || "(empty response)" });
@@ -1215,7 +1267,7 @@ function usePluginCallbacks(cwd) {
1215
1267
 
1216
1268
  // src/ui/MessageList.tsx
1217
1269
  import React2 from "react";
1218
- import { Box, Text } from "ink";
1270
+ import { Box as Box2, Text as Text2 } from "ink";
1219
1271
 
1220
1272
  // src/ui/render-markdown.ts
1221
1273
  import { marked } from "marked";
@@ -1228,48 +1280,103 @@ function renderMarkdown(md) {
1228
1280
  return typeof result === "string" ? result.trimEnd() : md;
1229
1281
  }
1230
1282
 
1283
+ // src/ui/DiffBlock.tsx
1284
+ import { Box, Text } from "ink";
1285
+ import { jsxs } from "react/jsx-runtime";
1286
+ var MAX_DIFF_LINES = 10;
1287
+ var TRUNCATED_SHOW = 8;
1288
+ function DiffBlock({ file, lines }) {
1289
+ const truncated = lines.length > MAX_DIFF_LINES;
1290
+ const visible = truncated ? lines.slice(0, TRUNCATED_SHOW) : lines;
1291
+ const remaining = lines.length - TRUNCATED_SHOW;
1292
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 4, children: [
1293
+ file && /* @__PURE__ */ jsxs(Text, { color: "white", dimColor: true, children: [
1294
+ "\u2502 ",
1295
+ file
1296
+ ] }),
1297
+ visible.map((line, i) => /* @__PURE__ */ jsxs(Text, { color: line.type === "remove" ? "red" : "greenBright", children: [
1298
+ "\u2502 ",
1299
+ line.type === "remove" ? "-" : "+",
1300
+ " ",
1301
+ line.text
1302
+ ] }, i)),
1303
+ truncated && /* @__PURE__ */ jsxs(Text, { color: "white", dimColor: true, children: [
1304
+ "\u2502 ... and ",
1305
+ remaining,
1306
+ " more lines"
1307
+ ] })
1308
+ ] });
1309
+ }
1310
+
1231
1311
  // src/ui/MessageList.tsx
1232
- import { jsx, jsxs } from "react/jsx-runtime";
1312
+ import { jsx, jsxs as jsxs2 } from "react/jsx-runtime";
1233
1313
  function RoleLabel({ role }) {
1234
1314
  switch (role) {
1235
1315
  case "user":
1236
- return /* @__PURE__ */ jsxs(Text, { color: "green", bold: true, children: [
1316
+ return /* @__PURE__ */ jsxs2(Text2, { color: "green", bold: true, children: [
1237
1317
  "You:",
1238
1318
  " "
1239
1319
  ] });
1240
1320
  case "assistant":
1241
- return /* @__PURE__ */ jsxs(Text, { color: "cyan", bold: true, children: [
1321
+ return /* @__PURE__ */ jsxs2(Text2, { color: "cyan", bold: true, children: [
1242
1322
  "Robota:",
1243
1323
  " "
1244
1324
  ] });
1245
1325
  case "system":
1246
- return /* @__PURE__ */ jsxs(Text, { color: "yellow", bold: true, children: [
1326
+ return /* @__PURE__ */ jsxs2(Text2, { color: "yellow", bold: true, children: [
1247
1327
  "System:",
1248
1328
  " "
1249
1329
  ] });
1250
1330
  case "tool":
1251
- return /* @__PURE__ */ jsxs(Text, { color: "white", bold: true, children: [
1331
+ return /* @__PURE__ */ jsxs2(Text2, { color: "white", bold: true, children: [
1252
1332
  "Tool:",
1253
1333
  " "
1254
1334
  ] });
1255
1335
  }
1256
1336
  }
1257
1337
  function ToolMessage({ message }) {
1258
- const lines = message.content.split("\n").filter((l) => l.trim());
1259
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
1260
- /* @__PURE__ */ jsxs(Box, { children: [
1261
- /* @__PURE__ */ jsxs(Text, { color: "white", bold: true, children: [
1262
- "Tool:",
1263
- " "
1338
+ let summaries = null;
1339
+ try {
1340
+ const parsed = JSON.parse(message.content);
1341
+ if (Array.isArray(parsed) && parsed.length > 0 && typeof parsed[0].line === "string") {
1342
+ summaries = parsed;
1343
+ }
1344
+ } catch {
1345
+ }
1346
+ if (summaries) {
1347
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
1348
+ /* @__PURE__ */ jsxs2(Box2, { children: [
1349
+ /* @__PURE__ */ jsx(Text2, { color: "white", bold: true, children: "Tool: " }),
1350
+ message.toolName && /* @__PURE__ */ jsxs2(Text2, { color: "white", dimColor: true, children: [
1351
+ "[",
1352
+ message.toolName,
1353
+ "]"
1354
+ ] })
1264
1355
  ] }),
1265
- message.toolName && /* @__PURE__ */ jsxs(Text, { color: "white", dimColor: true, children: [
1356
+ /* @__PURE__ */ jsx(Text2, { children: " " }),
1357
+ summaries.map((s, i) => /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
1358
+ /* @__PURE__ */ jsxs2(Text2, { color: "green", children: [
1359
+ " ",
1360
+ "\u2713",
1361
+ " ",
1362
+ s.line
1363
+ ] }),
1364
+ s.diffLines && s.diffLines.length > 0 && /* @__PURE__ */ jsx(DiffBlock, { file: s.diffFile, lines: s.diffLines })
1365
+ ] }, i))
1366
+ ] });
1367
+ }
1368
+ const lines = message.content.split("\n").filter((l) => l.trim());
1369
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
1370
+ /* @__PURE__ */ jsxs2(Box2, { children: [
1371
+ /* @__PURE__ */ jsx(Text2, { color: "white", bold: true, children: "Tool: " }),
1372
+ message.toolName && /* @__PURE__ */ jsxs2(Text2, { color: "white", dimColor: true, children: [
1266
1373
  "[",
1267
1374
  message.toolName,
1268
1375
  "]"
1269
1376
  ] })
1270
1377
  ] }),
1271
- /* @__PURE__ */ jsx(Text, { children: " " }),
1272
- lines.map((line, i) => /* @__PURE__ */ jsxs(Text, { color: "green", children: [
1378
+ /* @__PURE__ */ jsx(Text2, { children: " " }),
1379
+ lines.map((line, i) => /* @__PURE__ */ jsxs2(Text2, { color: "green", children: [
1273
1380
  " ",
1274
1381
  "\u2713",
1275
1382
  " ",
@@ -1283,28 +1390,28 @@ var MessageItem = React2.memo(function MessageItem2({
1283
1390
  if (message.role === "tool") {
1284
1391
  return /* @__PURE__ */ jsx(ToolMessage, { message });
1285
1392
  }
1286
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
1287
- /* @__PURE__ */ jsxs(Box, { children: [
1393
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
1394
+ /* @__PURE__ */ jsxs2(Box2, { children: [
1288
1395
  /* @__PURE__ */ jsx(RoleLabel, { role: message.role }),
1289
- message.toolName && /* @__PURE__ */ jsxs(Text, { color: "magenta", dimColor: true, children: [
1396
+ message.toolName && /* @__PURE__ */ jsxs2(Text2, { color: "magenta", dimColor: true, children: [
1290
1397
  "[",
1291
1398
  message.toolName,
1292
1399
  "]",
1293
1400
  " "
1294
1401
  ] })
1295
1402
  ] }),
1296
- /* @__PURE__ */ jsx(Text, { children: " " }),
1297
- /* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text, { wrap: "wrap", children: message.role === "assistant" ? renderMarkdown(message.content) : message.content }) })
1403
+ /* @__PURE__ */ jsx(Text2, { children: " " }),
1404
+ /* @__PURE__ */ jsx(Box2, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text2, { wrap: "wrap", children: message.role === "assistant" ? renderMarkdown(message.content) : message.content }) })
1298
1405
  ] });
1299
1406
  });
1300
1407
  function MessageList({ messages }) {
1301
- return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: messages.map((msg) => /* @__PURE__ */ jsx(MessageItem, { message: msg }, msg.id)) });
1408
+ return /* @__PURE__ */ jsx(Box2, { flexDirection: "column", children: messages.map((msg) => /* @__PURE__ */ jsx(MessageItem, { message: msg }, msg.id)) });
1302
1409
  }
1303
1410
 
1304
1411
  // src/ui/StatusBar.tsx
1305
- import { Box as Box2, Text as Text2 } from "ink";
1412
+ import { Box as Box3, Text as Text3 } from "ink";
1306
1413
  import { formatTokenCount as formatTokenCount2 } from "@robota-sdk/agent-core";
1307
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1414
+ import { jsx as jsx2, jsxs as jsxs3 } from "react/jsx-runtime";
1308
1415
  var CONTEXT_YELLOW_THRESHOLD = 70;
1309
1416
  var CONTEXT_RED_THRESHOLD = 90;
1310
1417
  function getContextColor(percentage) {
@@ -1323,8 +1430,8 @@ function StatusBar({
1323
1430
  contextMaxTokens
1324
1431
  }) {
1325
1432
  const contextColor = getContextColor(contextPercentage);
1326
- return /* @__PURE__ */ jsxs2(
1327
- Box2,
1433
+ return /* @__PURE__ */ jsxs3(
1434
+ Box3,
1328
1435
  {
1329
1436
  borderStyle: "single",
1330
1437
  borderColor: "gray",
@@ -1332,14 +1439,14 @@ function StatusBar({
1332
1439
  paddingRight: 1,
1333
1440
  justifyContent: "space-between",
1334
1441
  children: [
1335
- /* @__PURE__ */ jsxs2(Text2, { children: [
1336
- /* @__PURE__ */ jsx2(Text2, { color: "cyan", bold: true, children: "Mode:" }),
1442
+ /* @__PURE__ */ jsxs3(Text3, { children: [
1443
+ /* @__PURE__ */ jsx2(Text3, { color: "cyan", bold: true, children: "Mode:" }),
1337
1444
  " ",
1338
- /* @__PURE__ */ jsx2(Text2, { children: permissionMode }),
1445
+ /* @__PURE__ */ jsx2(Text3, { children: permissionMode }),
1339
1446
  " | ",
1340
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: modelName }),
1447
+ /* @__PURE__ */ jsx2(Text3, { dimColor: true, children: modelName }),
1341
1448
  " | ",
1342
- /* @__PURE__ */ jsxs2(Text2, { color: contextColor, children: [
1449
+ /* @__PURE__ */ jsxs3(Text3, { color: contextColor, children: [
1343
1450
  "Context: ",
1344
1451
  Math.round(contextPercentage),
1345
1452
  "% (",
@@ -1349,9 +1456,9 @@ function StatusBar({
1349
1456
  ")"
1350
1457
  ] })
1351
1458
  ] }),
1352
- /* @__PURE__ */ jsxs2(Text2, { children: [
1353
- isThinking && /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "Thinking... " }),
1354
- /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
1459
+ /* @__PURE__ */ jsxs3(Text3, { children: [
1460
+ isThinking && /* @__PURE__ */ jsx2(Text3, { color: "yellow", children: "Thinking... " }),
1461
+ /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
1355
1462
  "msgs: ",
1356
1463
  messageCount
1357
1464
  ] })
@@ -1363,11 +1470,11 @@ function StatusBar({
1363
1470
 
1364
1471
  // src/ui/InputArea.tsx
1365
1472
  import React5, { useState as useState5, useCallback as useCallback5, useMemo as useMemo2 } from "react";
1366
- import { Box as Box4, Text as Text6, useInput as useInput2 } from "ink";
1473
+ import { Box as Box5, Text as Text7, useInput as useInput2 } from "ink";
1367
1474
 
1368
1475
  // src/ui/CjkTextInput.tsx
1369
1476
  import { useRef as useRef3, useState as useState3 } from "react";
1370
- import { Text as Text3, useInput } from "ink";
1477
+ import { Text as Text4, useInput } from "ink";
1371
1478
  import chalk from "chalk";
1372
1479
  import { jsx as jsx3 } from "react/jsx-runtime";
1373
1480
  function filterPrintable(input) {
@@ -1440,7 +1547,7 @@ function CjkTextInput({
1440
1547
  },
1441
1548
  { isActive: focus }
1442
1549
  );
1443
- return /* @__PURE__ */ jsx3(Text3, { children: renderWithCursor(valueRef.current, cursorRef.current, placeholder, showCursor && focus) });
1550
+ return /* @__PURE__ */ jsx3(Text4, { children: renderWithCursor(valueRef.current, cursorRef.current, placeholder, showCursor && focus) });
1444
1551
  }
1445
1552
  function renderWithCursor(value, cursorOffset, placeholder, showCursor) {
1446
1553
  if (!showCursor) {
@@ -1466,7 +1573,7 @@ function renderWithCursor(value, cursorOffset, placeholder, showCursor) {
1466
1573
 
1467
1574
  // src/ui/WaveText.tsx
1468
1575
  import { useState as useState4, useEffect } from "react";
1469
- import { Text as Text4 } from "ink";
1576
+ import { Text as Text5 } from "ink";
1470
1577
  import { jsx as jsx4 } from "react/jsx-runtime";
1471
1578
  var WAVE_COLORS = ["#666666", "#888888", "#aaaaaa", "#888888"];
1472
1579
  var INTERVAL_MS = 400;
@@ -1480,23 +1587,23 @@ function WaveText({ text }) {
1480
1587
  return () => clearInterval(timer);
1481
1588
  }, []);
1482
1589
  const chars = [...text];
1483
- return /* @__PURE__ */ jsx4(Text4, { children: chars.map((char, i) => {
1590
+ return /* @__PURE__ */ jsx4(Text5, { children: chars.map((char, i) => {
1484
1591
  const group = Math.floor(i / CHARS_PER_GROUP);
1485
1592
  const colorIndex = (tick + group) % WAVE_COLORS.length;
1486
- return /* @__PURE__ */ jsx4(Text4, { color: WAVE_COLORS[colorIndex], children: char }, i);
1593
+ return /* @__PURE__ */ jsx4(Text5, { color: WAVE_COLORS[colorIndex], children: char }, i);
1487
1594
  }) });
1488
1595
  }
1489
1596
 
1490
1597
  // src/ui/SlashAutocomplete.tsx
1491
- import { Box as Box3, Text as Text5 } from "ink";
1492
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1598
+ import { Box as Box4, Text as Text6 } from "ink";
1599
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1493
1600
  var MAX_VISIBLE = 8;
1494
1601
  function CommandRow(props) {
1495
1602
  const { cmd, isSelected, showSlash } = props;
1496
1603
  const indicator = isSelected ? "\u25B8 " : " ";
1497
1604
  const nameColor = isSelected ? "cyan" : void 0;
1498
1605
  const dimmed = !isSelected;
1499
- return /* @__PURE__ */ jsx5(Box3, { children: /* @__PURE__ */ jsxs3(Text5, { color: nameColor, dimColor: dimmed, children: [
1606
+ return /* @__PURE__ */ jsx5(Box4, { children: /* @__PURE__ */ jsxs4(Text6, { color: nameColor, dimColor: dimmed, children: [
1500
1607
  indicator,
1501
1608
  showSlash ? `/${cmd.name} ${cmd.description}` : cmd.description
1502
1609
  ] }) });
@@ -1510,7 +1617,7 @@ function SlashAutocomplete({
1510
1617
  if (!visible || commands.length === 0) return null;
1511
1618
  const scrollOffset = computeScrollOffset(selectedIndex, commands.length);
1512
1619
  const visibleCommands = commands.slice(scrollOffset, scrollOffset + MAX_VISIBLE);
1513
- return /* @__PURE__ */ jsx5(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: visibleCommands.map((cmd, i) => /* @__PURE__ */ jsx5(
1620
+ return /* @__PURE__ */ jsx5(Box4, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: visibleCommands.map((cmd, i) => /* @__PURE__ */ jsx5(
1514
1621
  CommandRow,
1515
1622
  {
1516
1623
  cmd,
@@ -1528,7 +1635,7 @@ function computeScrollOffset(selectedIndex, total) {
1528
1635
  }
1529
1636
 
1530
1637
  // src/ui/InputArea.tsx
1531
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1638
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1532
1639
  function parseSlashInput(value) {
1533
1640
  if (!value.startsWith("/")) return { isSlash: false, parentCommand: "", filter: "" };
1534
1641
  const afterSlash = value.slice(1);
@@ -1639,7 +1746,7 @@ function InputArea({ onSubmit, isDisabled, registry }) {
1639
1746
  },
1640
1747
  { isActive: showPopup && !isDisabled }
1641
1748
  );
1642
- return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
1749
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1643
1750
  showPopup && /* @__PURE__ */ jsx6(
1644
1751
  SlashAutocomplete,
1645
1752
  {
@@ -1649,8 +1756,8 @@ function InputArea({ onSubmit, isDisabled, registry }) {
1649
1756
  isSubcommandMode
1650
1757
  }
1651
1758
  ),
1652
- /* @__PURE__ */ jsx6(Box4, { borderStyle: "single", borderColor: isDisabled ? "gray" : "green", paddingLeft: 1, children: isDisabled ? /* @__PURE__ */ jsx6(WaveText, { text: " Waiting for response..." }) : /* @__PURE__ */ jsxs4(Box4, { children: [
1653
- /* @__PURE__ */ jsx6(Text6, { color: "green", bold: true, children: "> " }),
1759
+ /* @__PURE__ */ jsx6(Box5, { borderStyle: "single", borderColor: isDisabled ? "gray" : "green", paddingLeft: 1, children: isDisabled ? /* @__PURE__ */ jsx6(WaveText, { text: " Waiting for response..." }) : /* @__PURE__ */ jsxs5(Box5, { children: [
1760
+ /* @__PURE__ */ jsx6(Text7, { color: "green", bold: true, children: "> " }),
1654
1761
  /* @__PURE__ */ jsx6(
1655
1762
  CjkTextInput,
1656
1763
  {
@@ -1666,8 +1773,8 @@ function InputArea({ onSubmit, isDisabled, registry }) {
1666
1773
 
1667
1774
  // src/ui/ConfirmPrompt.tsx
1668
1775
  import { useState as useState6, useCallback as useCallback6, useRef as useRef4 } from "react";
1669
- import { Box as Box5, Text as Text7, useInput as useInput3 } from "ink";
1670
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1776
+ import { Box as Box6, Text as Text8, useInput as useInput3 } from "ink";
1777
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1671
1778
  function ConfirmPrompt({
1672
1779
  message,
1673
1780
  options = ["Yes", "No"],
@@ -1697,20 +1804,20 @@ function ConfirmPrompt({
1697
1804
  doSelect(1);
1698
1805
  }
1699
1806
  });
1700
- return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
1701
- /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: message }),
1702
- /* @__PURE__ */ jsx7(Box5, { marginTop: 1, children: options.map((opt, i) => /* @__PURE__ */ jsx7(Box5, { marginRight: 2, children: /* @__PURE__ */ jsxs5(Text7, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
1807
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
1808
+ /* @__PURE__ */ jsx7(Text8, { color: "yellow", children: message }),
1809
+ /* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: options.map((opt, i) => /* @__PURE__ */ jsx7(Box6, { marginRight: 2, children: /* @__PURE__ */ jsxs6(Text8, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
1703
1810
  i === selected ? "> " : " ",
1704
1811
  opt
1705
1812
  ] }) }, opt)) }),
1706
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " arrow keys to select, Enter to confirm" })
1813
+ /* @__PURE__ */ jsx7(Text8, { dimColor: true, children: " arrow keys to select, Enter to confirm" })
1707
1814
  ] });
1708
1815
  }
1709
1816
 
1710
1817
  // src/ui/PermissionPrompt.tsx
1711
1818
  import React7 from "react";
1712
- import { Box as Box6, Text as Text8, useInput as useInput4 } from "ink";
1713
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1819
+ import { Box as Box7, Text as Text9, useInput as useInput4 } from "ink";
1820
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1714
1821
  var OPTIONS = ["Allow", "Allow always (this session)", "Deny"];
1715
1822
  function formatArgs(args) {
1716
1823
  const entries = Object.entries(args);
@@ -1752,28 +1859,28 @@ function PermissionPrompt({ request }) {
1752
1859
  doResolve(2);
1753
1860
  }
1754
1861
  });
1755
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
1756
- /* @__PURE__ */ jsx8(Text8, { color: "yellow", bold: true, children: "[Permission Required]" }),
1757
- /* @__PURE__ */ jsxs6(Text8, { children: [
1862
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
1863
+ /* @__PURE__ */ jsx8(Text9, { color: "yellow", bold: true, children: "[Permission Required]" }),
1864
+ /* @__PURE__ */ jsxs7(Text9, { children: [
1758
1865
  "Tool:",
1759
1866
  " ",
1760
- /* @__PURE__ */ jsx8(Text8, { color: "cyan", bold: true, children: request.toolName })
1867
+ /* @__PURE__ */ jsx8(Text9, { color: "cyan", bold: true, children: request.toolName })
1761
1868
  ] }),
1762
- /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
1869
+ /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
1763
1870
  " ",
1764
1871
  formatArgs(request.toolArgs)
1765
1872
  ] }),
1766
- /* @__PURE__ */ jsx8(Box6, { marginTop: 1, children: OPTIONS.map((opt, i) => /* @__PURE__ */ jsx8(Box6, { marginRight: 2, children: /* @__PURE__ */ jsxs6(Text8, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
1873
+ /* @__PURE__ */ jsx8(Box7, { marginTop: 1, children: OPTIONS.map((opt, i) => /* @__PURE__ */ jsx8(Box7, { marginRight: 2, children: /* @__PURE__ */ jsxs7(Text9, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
1767
1874
  i === selected ? "> " : " ",
1768
1875
  opt
1769
1876
  ] }) }, opt)) }),
1770
- /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: " left/right to select, Enter to confirm" })
1877
+ /* @__PURE__ */ jsx8(Text9, { dimColor: true, children: " left/right to select, Enter to confirm" })
1771
1878
  ] });
1772
1879
  }
1773
1880
 
1774
1881
  // src/ui/StreamingIndicator.tsx
1775
- import { Box as Box7, Text as Text9 } from "ink";
1776
- import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1882
+ import { Box as Box8, Text as Text10 } from "ink";
1883
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1777
1884
  function getToolStyle(t) {
1778
1885
  if (t.isRunning) return { color: "yellow", icon: "\u27F3", strikethrough: false };
1779
1886
  if (t.result === "error") return { color: "red", icon: "\u2717", strikethrough: true };
@@ -1784,35 +1891,38 @@ function StreamingIndicator({ text, activeTools }) {
1784
1891
  const hasTools = activeTools.length > 0;
1785
1892
  const hasText = text.length > 0;
1786
1893
  if (!hasTools && !hasText) {
1787
- return /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "Thinking..." });
1894
+ return /* @__PURE__ */ jsx9(Text10, { color: "yellow", children: "Thinking..." });
1788
1895
  }
1789
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
1790
- hasTools && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginBottom: 1, children: [
1791
- /* @__PURE__ */ jsx9(Text9, { color: "white", bold: true, children: "Tools:" }),
1792
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
1896
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
1897
+ hasTools && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginBottom: 1, children: [
1898
+ /* @__PURE__ */ jsx9(Text10, { color: "white", bold: true, children: "Tools:" }),
1899
+ /* @__PURE__ */ jsx9(Text10, { children: " " }),
1793
1900
  activeTools.map((t, i) => {
1794
1901
  const { color, icon, strikethrough } = getToolStyle(t);
1795
- return /* @__PURE__ */ jsxs7(Text9, { color, strikethrough, children: [
1796
- " ",
1797
- icon,
1798
- " ",
1799
- t.toolName,
1800
- "(",
1801
- t.firstArg,
1802
- ")"
1902
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
1903
+ /* @__PURE__ */ jsxs8(Text10, { color, strikethrough, children: [
1904
+ " ",
1905
+ icon,
1906
+ " ",
1907
+ t.toolName,
1908
+ "(",
1909
+ t.firstArg,
1910
+ ")"
1911
+ ] }),
1912
+ t.diffLines && t.diffLines.length > 0 && /* @__PURE__ */ jsx9(DiffBlock, { file: t.diffFile, lines: t.diffLines })
1803
1913
  ] }, `${t.toolName}-${i}`);
1804
1914
  })
1805
1915
  ] }),
1806
- hasText && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginBottom: 1, children: [
1807
- /* @__PURE__ */ jsx9(Text9, { color: "cyan", bold: true, children: "Robota:" }),
1808
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
1809
- /* @__PURE__ */ jsx9(Box7, { marginLeft: 2, children: /* @__PURE__ */ jsx9(Text9, { wrap: "wrap", children: renderMarkdown(text) }) })
1916
+ hasText && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginBottom: 1, children: [
1917
+ /* @__PURE__ */ jsx9(Text10, { color: "cyan", bold: true, children: "Robota:" }),
1918
+ /* @__PURE__ */ jsx9(Text10, { children: " " }),
1919
+ /* @__PURE__ */ jsx9(Box8, { marginLeft: 2, children: /* @__PURE__ */ jsx9(Text10, { wrap: "wrap", children: renderMarkdown(text) }) })
1810
1920
  ] })
1811
1921
  ] });
1812
1922
  }
1813
1923
 
1814
1924
  // src/ui/App.tsx
1815
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1925
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1816
1926
  var EXIT_DELAY_MS2 = 500;
1817
1927
  function mergeHooksIntoConfig(configHooks, pluginHooks) {
1818
1928
  const pluginKeys = Object.keys(pluginHooks);
@@ -1880,23 +1990,23 @@ function App(props) {
1880
1990
  },
1881
1991
  { isActive: !permissionRequest }
1882
1992
  );
1883
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
1884
- /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
1885
- /* @__PURE__ */ jsx10(Text10, { color: "cyan", bold: true, children: `
1993
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
1994
+ /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
1995
+ /* @__PURE__ */ jsx10(Text11, { color: "cyan", bold: true, children: `
1886
1996
  ____ ___ ____ ___ _____ _
1887
1997
  | _ \\ / _ \\| __ ) / _ \\_ _|/ \\
1888
1998
  | |_) | | | | _ \\| | | || | / _ \\
1889
1999
  | _ <| |_| | |_) | |_| || |/ ___ \\
1890
2000
  |_| \\_\\\\___/|____/ \\___/ |_/_/ \\_\\
1891
2001
  ` }),
1892
- /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
2002
+ /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
1893
2003
  " v",
1894
2004
  props.version ?? "0.0.0"
1895
2005
  ] })
1896
2006
  ] }),
1897
- /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
2007
+ /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
1898
2008
  /* @__PURE__ */ jsx10(MessageList, { messages }),
1899
- isThinking && /* @__PURE__ */ jsx10(Box8, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx10(StreamingIndicator, { text: streamingText, activeTools }) })
2009
+ isThinking && /* @__PURE__ */ jsx10(Box9, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx10(StreamingIndicator, { text: streamingText, activeTools }) })
1900
2010
  ] }),
1901
2011
  permissionRequest && /* @__PURE__ */ jsx10(PermissionPrompt, { request: permissionRequest }),
1902
2012
  pendingModelId && /* @__PURE__ */ jsx10(
@@ -1948,7 +2058,7 @@ function App(props) {
1948
2058
  registry
1949
2059
  }
1950
2060
  ),
1951
- /* @__PURE__ */ jsx10(Text10, { children: " " })
2061
+ /* @__PURE__ */ jsx10(Text11, { children: " " })
1952
2062
  ] });
1953
2063
  }
1954
2064