@botconnector/bccli 0.4.13 → 0.4.14

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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/version.ts
4
- var VERSION = true ? "0.4.13" : "0.0.0-dev";
4
+ var VERSION = true ? "0.4.14" : "0.0.0-dev";
5
5
 
6
6
  export {
7
7
  VERSION
package/dist/cli.js CHANGED
@@ -13,7 +13,7 @@ import "./chunk-7GM6NN5E.js";
13
13
  import "./chunk-PSO7R5AD.js";
14
14
  import {
15
15
  VERSION
16
- } from "./chunk-F6NNUUF3.js";
16
+ } from "./chunk-RRE6WRU5.js";
17
17
  import {
18
18
  helpText,
19
19
  parseCliArgs
@@ -109,7 +109,7 @@ async function main() {
109
109
  return runModelsCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), fetch: globalThis.fetch });
110
110
  }
111
111
  if (args.command === "update") {
112
- const { runUpdateCommand } = await import("./update-PXXUITFS.js");
112
+ const { runUpdateCommand } = await import("./update-CRFQXBNM.js");
113
113
  return runUpdateCommand({ env: process.env });
114
114
  }
115
115
  if (args.command === "acp") {
@@ -118,7 +118,7 @@ async function main() {
118
118
  return 0;
119
119
  }
120
120
  if (args.command === "serve") {
121
- const { serveBanner, startServe } = await import("./serve-6NK2IR6R.js");
121
+ const { serveBanner, startServe } = await import("./serve-KBXP23UW.js");
122
122
  const handle = await startServe({ port: args.port, host: args.host, token: args.token, cwd, env: process.env });
123
123
  process.stderr.write(serveBanner(handle, { token: args.token }));
124
124
  await new Promise((resolve) => {
@@ -215,13 +215,13 @@ async function main() {
215
215
  let updateMessage;
216
216
  if (rt.config.updateCheck !== "off" && !process.env.BCCLI_NO_UPDATE_CHECK) {
217
217
  try {
218
- const { checkForUpdate } = await import("./update-PXXUITFS.js");
218
+ const { checkForUpdate } = await import("./update-CRFQXBNM.js");
219
219
  const update = await checkForUpdate({ home: rt.home, fetch: globalThis.fetch, now: /* @__PURE__ */ new Date() });
220
220
  updateMessage = update;
221
221
  } catch {
222
222
  }
223
223
  }
224
- const { startInteractive } = await import("./ui-IMCUSB6Q.js");
224
+ const { startInteractive } = await import("./ui-K5RLE2R6.js");
225
225
  return startInteractive(rt, { initialPrompt: args.prompt, resume: args.resume, version: VERSION, updateMessage });
226
226
  }
227
227
  main().then(
@@ -8,7 +8,7 @@ import "./chunk-7GM6NN5E.js";
8
8
  import "./chunk-PSO7R5AD.js";
9
9
  import {
10
10
  VERSION
11
- } from "./chunk-F6NNUUF3.js";
11
+ } from "./chunk-RRE6WRU5.js";
12
12
  import {
13
13
  LOOPBACK_BIND,
14
14
  MAX_FRAME_BYTES,
@@ -15,12 +15,8 @@ export declare function clickedThinking(click: MousePress, cursorRow: number, ro
15
15
  width: number;
16
16
  height: number;
17
17
  }): boolean;
18
- /** Parse SGR or Urxvt mouse wheel / 2-finger touchpad vertical scroll events after Ink strips ESC. */
19
- export declare function parseMouseWheel(input: string): 'up' | 'down' | undefined;
20
18
  /** Detect raw SGR/Urxvt wheel packets in a raw stdin data chunk (before ESC is stripped). */
21
19
  export declare function hasMouseWheelSequence(chunk: string): boolean;
22
- /** Ink useInput receives these control reports too; they must not enter the prompt. */
23
- export declare function isMouseControlInput(input: string): boolean;
24
20
  /** Tokenize split/coalesced Windows ConPTY SGR presses and cursor reports. */
25
21
  export declare function parseThinkingReports(value: string): {
26
22
  events: Array<{
@@ -0,0 +1,9 @@
1
+ /** True when the stream reports itself as a TTY (fake test streams may still report `true`). */
2
+ export declare function isTtyStream(stream: unknown): boolean;
3
+ /** True only for a real terminal: a TTY that also exposes a file descriptor. */
4
+ export declare function isRealTty(stream: unknown): boolean;
5
+ /**
6
+ * Terminal width at render time. Reading it instead of listening to `resize` keeps one listener per app
7
+ * (App's `useWindowSize`) rather than one per rendered message; App re-renders on resize and passes the new width down.
8
+ */
9
+ export declare function streamColumns(stream: unknown): number;
@@ -76,7 +76,7 @@ import { execFile as execFile3 } from "child_process";
76
76
  import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
77
77
  import { homedir, tmpdir } from "os";
78
78
  import { dirname, join as join3, relative as relative2, resolve as resolve2 } from "path";
79
- import { Box as Box13, Static, Text as Text16, measureElement, useApp, useInput as useInput9, useStdin, useStdout as useStdout2 } from "ink";
79
+ import { Box as Box13, Static, Text as Text16, measureElement, useApp, useInput as useInput9, useStdin, useStdout as useStdout2, useWindowSize } from "ink";
80
80
  import { useCallback, useEffect as useEffect3, useRef as useRef2, useState as useState10 } from "react";
81
81
 
82
82
  // src/commands.ts
@@ -547,6 +547,18 @@ function layoutTable(table, width) {
547
547
  return out;
548
548
  }
549
549
 
550
+ // src/ui/tty.ts
551
+ function isTtyStream(stream) {
552
+ return typeof stream === "object" && stream !== null && stream.isTTY === true;
553
+ }
554
+ function isRealTty(stream) {
555
+ return isTtyStream(stream) && typeof stream.fd === "number";
556
+ }
557
+ function streamColumns(stream) {
558
+ const columns = typeof stream === "object" && stream !== null ? stream.columns : void 0;
559
+ return typeof columns === "number" && columns > 0 ? columns : 80;
560
+ }
561
+
550
562
  // src/ui/Markdown.tsx
551
563
  import { jsx, jsxs } from "react/jsx-runtime";
552
564
  function segment(seg, key) {
@@ -584,7 +596,7 @@ function hanging(key, marker, body, width, padding = 0) {
584
596
  }
585
597
  function Markdown({ text, indent = 2 }) {
586
598
  const { stdout } = useStdout();
587
- const width = Math.max(20, (stdout?.columns ?? 80) - indent - 1);
599
+ const width = Math.max(20, streamColumns(stdout) - indent - 1);
588
600
  const lines = text.split("\n");
589
601
  const rows = [];
590
602
  let inCode = false;
@@ -811,86 +823,15 @@ function EditableText({ state, mask = false, showCursor = true }) {
811
823
  ] });
812
824
  }
813
825
 
814
- // src/ui/focusReport.ts
815
- var isFocusReport = (input) => input === "[I" || input === "[O";
816
-
817
- // src/ui/thinkingMouse.ts
818
- function parseMousePress(value) {
819
- const start = value.indexOf("\x1B[<");
820
- if (start < 0) return void 0;
821
- const match = /^<(\d+);(\d+);(\d+)M/.exec(value.slice(start + 2));
822
- if (!match) return void 0;
823
- const button = Number(match[1]);
824
- if (button !== 0) return void 0;
825
- const x = Number(match[2]);
826
- const y = Number(match[3]);
827
- if (x < 1 || y < 1) return void 0;
828
- return { x, y };
829
- }
830
- function parseCursorPosition(value) {
831
- const start = value.indexOf("\x1B[");
832
- if (start < 0) return void 0;
833
- const match = /^(\d+);(\d+)R/.exec(value.slice(start + 2));
834
- if (!match) return void 0;
835
- const row = Number(match[1]);
836
- const col = Number(match[2]);
837
- if (row < 1 || col < 1) return void 0;
838
- return { row, col };
839
- }
840
- function clickedThinking(click, cursorRow, rootHeight, target) {
841
- if (!rootHeight || !target.width || !target.height) return false;
842
- const origin = cursorRow - rootHeight + 1;
843
- const row = origin + target.y;
844
- const col = target.x + 1;
845
- return (click.y === row || click.y === row - 1) && click.x >= col && click.x < col + Math.min(target.width, 72);
846
- }
847
- function parseMouseWheel(input) {
848
- const match = /^\[<?(\d+);\d+;\d+[mM]$/.exec(input);
849
- if (!match) return void 0;
850
- const button = Number(match[1]);
851
- if ((button & 64) === 0) return void 0;
852
- const dir = button & 3;
853
- if (dir === 0) return "up";
854
- if (dir === 1) return "down";
855
- return void 0;
856
- }
857
- function hasMouseWheelSequence(chunk) {
858
- return chunk.includes("\x1B[") && /\[<?6[4567];\d+;\d+[mM]/.test(chunk);
859
- }
860
- function isMouseControlInput(input) {
861
- return /^\[<[\d;]*[mM]?$/.test(input) || /^\[(?:\d+;){2}\d+[mM]$/.test(input) || /^\[(?:\d+;)+\d*R?$/.test(input) || /^\[M[\s\S]{0,3}$/.test(input) || input.includes("\x1B[<");
862
- }
863
- function parseThinkingReports(value) {
864
- const events = [];
865
- let offset = 0;
866
- while (true) {
867
- const start = value.indexOf("\x1B[", offset);
868
- if (start < 0) break;
869
- const finish = /[a-zA-Z~]/.exec(value.slice(start + 2));
870
- if (!finish) return { events, rest: value.slice(start) };
871
- const end = start + 2 + finish.index + 1;
872
- const raw = value.slice(start, end);
873
- const press = parseMousePress(raw);
874
- const cursor = parseCursorPosition(raw);
875
- if (press) events.push({ type: "mouse", press });
876
- else if (cursor) events.push({ type: "cursor", cursor });
877
- offset = end;
878
- }
879
- const remaining = value.lastIndexOf("\x1B[");
880
- if (remaining >= offset) return { events, rest: value.slice(remaining) };
881
- return { events, rest: value.endsWith("\x1B") ? "\x1B" : "" };
882
- }
883
-
884
826
  // src/ui/LinePrompt.tsx
885
827
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
886
828
  function LinePrompt({ label, mask, onSubmit, onCancel }) {
887
829
  const [line, setLine] = useState({ value: "", cursor: 0 });
888
830
  useInput((input, key) => {
889
- if (isMouseControlInput(input)) return;
890
831
  if (key.return) onSubmit(line.value.trim());
891
832
  else if (key.escape) onCancel();
892
833
  else if (applyEditKey(line, input, key)) setLine((current) => applyEditKey(current, input, key) ?? current);
893
- else if (!key.ctrl && !key.meta && !key.tab && !key.upArrow && !key.downArrow && !isFocusReport(input)) {
834
+ else if (!key.ctrl && !key.meta && !key.tab && !key.upArrow && !key.downArrow) {
894
835
  const text = input.replace(/[\r\n]/g, "");
895
836
  if (text) setLine((current) => insert(current, text));
896
837
  }
@@ -913,16 +854,6 @@ function ListPicker({ title, items, onPick }) {
913
854
  const shown = items.filter((i) => i.label.toLowerCase().includes(filter.toLowerCase()));
914
855
  const cursor = Math.min(index, Math.max(0, shown.length - 1));
915
856
  useInput2((input, key) => {
916
- const wheel = parseMouseWheel(input);
917
- if (wheel === "up") {
918
- setIndex(Math.max(0, cursor - 1));
919
- return;
920
- }
921
- if (wheel === "down") {
922
- setIndex(Math.min(Math.max(0, shown.length - 1), cursor + 1));
923
- return;
924
- }
925
- if (isMouseControlInput(input)) return;
926
857
  if (key.upArrow) setIndex(Math.max(0, cursor - 1));
927
858
  else if (key.downArrow) setIndex(Math.min(Math.max(0, shown.length - 1), cursor + 1));
928
859
  else if (key.pageUp) setIndex(Math.max(0, cursor - VISIBLE));
@@ -932,7 +863,7 @@ function ListPicker({ title, items, onPick }) {
932
863
  else if (key.backspace || key.delete) {
933
864
  setFilter((f) => f.slice(0, -1));
934
865
  setIndex(0);
935
- } else if (!key.ctrl && !key.meta && !key.tab && input && !isFocusReport(input)) {
866
+ } else if (!key.ctrl && !key.meta && !key.tab && input) {
936
867
  setFilter((f) => f + input);
937
868
  setIndex(0);
938
869
  }
@@ -969,16 +900,6 @@ function ModelPicker({ groups, current, onPick }) {
969
900
  const clampedIndex = Math.min(index, Math.max(0, selectable.length - 1));
970
901
  const cursor = selectable[clampedIndex] ?? -1;
971
902
  useInput3((input, key) => {
972
- const wheel = parseMouseWheel(input);
973
- if (wheel === "up") {
974
- setIndex(Math.max(0, clampedIndex - 1));
975
- return;
976
- }
977
- if (wheel === "down") {
978
- setIndex(Math.min(Math.max(0, selectable.length - 1), clampedIndex + 1));
979
- return;
980
- }
981
- if (isMouseControlInput(input)) return;
982
903
  if (key.upArrow) setIndex(Math.max(0, clampedIndex - 1));
983
904
  else if (key.downArrow) setIndex(Math.min(Math.max(0, selectable.length - 1), clampedIndex + 1));
984
905
  else if (key.pageUp) setIndex(Math.max(0, clampedIndex - VISIBLE2));
@@ -990,7 +911,7 @@ function ModelPicker({ groups, current, onPick }) {
990
911
  else if (key.backspace || key.delete) {
991
912
  setFilter((f) => f.slice(0, -1));
992
913
  setIndex(0);
993
- } else if (!key.ctrl && !key.meta && !key.tab && input && !isFocusReport(input)) {
914
+ } else if (!key.ctrl && !key.meta && !key.tab && input) {
994
915
  setFilter((f) => f + input);
995
916
  setIndex(0);
996
917
  }
@@ -1013,17 +934,7 @@ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1013
934
  function ProviderMenu({ entries, onPick }) {
1014
935
  const rows = [...entries.map((e) => e.id), "custom"];
1015
936
  const [index, setIndex] = useState4(0);
1016
- useInput4((input, key) => {
1017
- const wheel = parseMouseWheel(input);
1018
- if (wheel === "up") {
1019
- setIndex((i) => Math.max(0, i - 1));
1020
- return;
1021
- }
1022
- if (wheel === "down") {
1023
- setIndex((i) => Math.min(rows.length - 1, i + 1));
1024
- return;
1025
- }
1026
- if (isMouseControlInput(input) || isFocusReport(input)) return;
937
+ useInput4((_input, key) => {
1027
938
  if (key.upArrow) setIndex((i) => Math.max(0, i - 1));
1028
939
  else if (key.downArrow) setIndex((i) => Math.min(rows.length - 1, i + 1));
1029
940
  else if (key.pageUp) setIndex((i) => Math.max(0, i - 10));
@@ -1068,16 +979,6 @@ function PermissionPrompt({
1068
979
  const maxOffset = Math.max(0, diffLines.length - MAX_DIFF_LINES);
1069
980
  const [offset, setOffset] = useState5(0);
1070
981
  useInput5((input, key) => {
1071
- const wheel = parseMouseWheel(input);
1072
- if (wheel === "up") {
1073
- setOffset((o) => Math.max(0, o - 2));
1074
- return;
1075
- }
1076
- if (wheel === "down") {
1077
- setOffset((o) => Math.min(maxOffset, o + 2));
1078
- return;
1079
- }
1080
- if (isMouseControlInput(input) || isFocusReport(input)) return;
1081
982
  if (key.upArrow) {
1082
983
  setOffset((o) => Math.max(0, o - 1));
1083
984
  return;
@@ -1331,14 +1232,6 @@ function PromptInput({ disabled, history, cwd, onSubmit, extraCommands, injected
1331
1232
  };
1332
1233
  useInput6(
1333
1234
  (input, key) => {
1334
- const wheel = parseMouseWheel(input);
1335
- if (wheel) {
1336
- if (activeCount > 0) {
1337
- setSelected((current) => wheel === "up" ? Math.max(0, Math.min(current, activeCount - 1) - 1) : Math.min(activeCount - 1, Math.min(current, activeCount - 1) + 1));
1338
- }
1339
- return;
1340
- }
1341
- if (isMouseControlInput(input)) return;
1342
1235
  if (suggestions.length) {
1343
1236
  if (key.escape) {
1344
1237
  setDismissed(true);
@@ -1451,7 +1344,7 @@ ${value.slice(line.cursor)}`, cursor: before.length });
1451
1344
  if (completed !== before) edit({ value: completed + value.slice(line.cursor), cursor: completed.length });
1452
1345
  return;
1453
1346
  }
1454
- if (key.ctrl || key.meta || key.escape || key.tab || isFocusReport(input)) return;
1347
+ if (key.ctrl || key.meta || key.escape || key.tab) return;
1455
1348
  const text = input.replace(/\r\n?/g, "\n");
1456
1349
  if (text) edit((current) => insert(current, text));
1457
1350
  },
@@ -1486,6 +1379,60 @@ function Spinner({ label, startedAt }) {
1486
1379
  return /* @__PURE__ */ jsx10(Text10, { color: color(ACCENT), children: `${FRAMES[tick % FRAMES.length]} ${t("{label}\u2026 ({seconds}s \xB7 esc to cancel)", { label, seconds })}` });
1487
1380
  }
1488
1381
 
1382
+ // src/ui/thinkingMouse.ts
1383
+ function parseMousePress(value) {
1384
+ const start = value.indexOf("\x1B[<");
1385
+ if (start < 0) return void 0;
1386
+ const match = /^<(\d+);(\d+);(\d+)M/.exec(value.slice(start + 2));
1387
+ if (!match) return void 0;
1388
+ const button = Number(match[1]);
1389
+ if (button !== 0) return void 0;
1390
+ const x = Number(match[2]);
1391
+ const y = Number(match[3]);
1392
+ if (x < 1 || y < 1) return void 0;
1393
+ return { x, y };
1394
+ }
1395
+ function parseCursorPosition(value) {
1396
+ const start = value.indexOf("\x1B[");
1397
+ if (start < 0) return void 0;
1398
+ const match = /^(\d+);(\d+)R/.exec(value.slice(start + 2));
1399
+ if (!match) return void 0;
1400
+ const row = Number(match[1]);
1401
+ const col = Number(match[2]);
1402
+ if (row < 1 || col < 1) return void 0;
1403
+ return { row, col };
1404
+ }
1405
+ function clickedThinking(click, cursorRow, rootHeight, target) {
1406
+ if (!rootHeight || !target.width || !target.height) return false;
1407
+ const origin = cursorRow - rootHeight + 1;
1408
+ const row = origin + target.y;
1409
+ const col = target.x + 1;
1410
+ return (click.y === row || click.y === row - 1) && click.x >= col && click.x < col + Math.min(target.width, 72);
1411
+ }
1412
+ function hasMouseWheelSequence(chunk) {
1413
+ return chunk.includes("\x1B[") && /\[<?6[4567];\d+;\d+[mM]/.test(chunk);
1414
+ }
1415
+ function parseThinkingReports(value) {
1416
+ const events = [];
1417
+ let offset = 0;
1418
+ while (true) {
1419
+ const start = value.indexOf("\x1B[", offset);
1420
+ if (start < 0) break;
1421
+ const finish = /[a-zA-Z~]/.exec(value.slice(start + 2));
1422
+ if (!finish) return { events, rest: value.slice(start) };
1423
+ const end = start + 2 + finish.index + 1;
1424
+ const raw = value.slice(start, end);
1425
+ const press = parseMousePress(raw);
1426
+ const cursor = parseCursorPosition(raw);
1427
+ if (press) events.push({ type: "mouse", press });
1428
+ else if (cursor) events.push({ type: "cursor", cursor });
1429
+ offset = end;
1430
+ }
1431
+ const remaining = value.lastIndexOf("\x1B[");
1432
+ if (remaining >= offset) return { events, rest: value.slice(remaining) };
1433
+ return { events, rest: value.endsWith("\x1B") ? "\x1B" : "" };
1434
+ }
1435
+
1489
1436
  // src/ui/StatusBar.tsx
1490
1437
  import { Text as Text11 } from "ink";
1491
1438
  import { jsx as jsx11 } from "react/jsx-runtime";
@@ -1510,17 +1457,7 @@ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
1510
1457
  var MARK = { ready: "\u2713", error: "\u2717", starting: "\u2026", off: "\u25CB" };
1511
1458
  function McpMenu({ items, onPick }) {
1512
1459
  const [index, setIndex] = useState8(0);
1513
- useInput7((input, key) => {
1514
- const wheel = parseMouseWheel(input);
1515
- if (wheel === "up") {
1516
- setIndex((i) => Math.max(0, i - 1));
1517
- return;
1518
- }
1519
- if (wheel === "down") {
1520
- setIndex((i) => Math.min(items.length - 1, i + 1));
1521
- return;
1522
- }
1523
- if (isMouseControlInput(input) || isFocusReport(input)) return;
1460
+ useInput7((_input, key) => {
1524
1461
  if (key.upArrow) setIndex((i) => Math.max(0, i - 1));
1525
1462
  else if (key.downArrow) setIndex((i) => Math.min(items.length - 1, i + 1));
1526
1463
  else if (key.pageUp) setIndex((i) => Math.max(0, i - 10));
@@ -1547,16 +1484,6 @@ function PlanApproval({ plan, onAnswer }) {
1547
1484
  const maxOffset = Math.max(0, planLines.length - MAX_PLAN_LINES);
1548
1485
  const [offset, setOffset] = useState9(0);
1549
1486
  useInput8((input, key) => {
1550
- const wheel = parseMouseWheel(input);
1551
- if (wheel === "up") {
1552
- setOffset((o) => Math.max(0, o - 2));
1553
- return;
1554
- }
1555
- if (wheel === "down") {
1556
- setOffset((o) => Math.min(maxOffset, o + 2));
1557
- return;
1558
- }
1559
- if (isMouseControlInput(input) || isFocusReport(input)) return;
1560
1487
  if (key.upArrow) {
1561
1488
  setOffset((o) => Math.max(0, o - 1));
1562
1489
  return;
@@ -1864,18 +1791,19 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
1864
1791
  const lastUserIdx = transcript.done.findLastIndex((e) => e.kind === "user");
1865
1792
  const { stdin } = useStdin();
1866
1793
  const { stdout } = useStdout2();
1867
- const isRealTty = Boolean(stdout?.isTTY && "fd" in stdout);
1868
- const maxLiveLines = Math.max(8, (stdout?.rows ?? 24) - 10);
1794
+ const realStdout = isRealTty(stdout);
1795
+ const { rows: windowRows } = useWindowSize();
1796
+ const maxLiveLines = Math.max(8, windowRows - 10);
1869
1797
  const maxSplitIdxRef = useRef2(0);
1870
1798
  const refreshStatic = useCallback(() => {
1871
- if (stdout?.isTTY && "fd" in stdout) {
1799
+ if (realStdout) {
1872
1800
  stdout.write("\x1B[2J\x1B[3J\x1B[H");
1873
1801
  }
1874
1802
  maxSplitIdxRef.current = 0;
1875
1803
  setStaticKey((k2) => k2 + 1);
1876
- }, [stdout]);
1804
+ }, [stdout, realStdout]);
1877
1805
  let splitIdx = Math.max(maxSplitIdxRef.current, lastUserIdx > 0 ? lastUserIdx : 0);
1878
- if (isRealTty) {
1806
+ if (realStdout) {
1879
1807
  const entryLines = (e) => {
1880
1808
  if (e.kind === "thinking") return showThinking ? Math.min(maxLiveLines, e.text.split("\n").length + 2) : 2;
1881
1809
  if (e.kind === "tool") return showToolOutput ? Math.min(maxLiveLines, (e.output ?? e.display ?? "").split("\n").length + 2) : 5;
@@ -2575,7 +2503,7 @@ ARGUMENTS: ${slash.args}`);
2575
2503
  }
2576
2504
  }, [initialPrompt, submit]);
2577
2505
  useEffect3(() => {
2578
- if (!stdout?.isTTY || !("fd" in stdout)) return;
2506
+ if (!isRealTty(stdout)) return;
2579
2507
  stdout.write("\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?2004h");
2580
2508
  return () => {
2581
2509
  stdout.write("\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?2004l");
@@ -2583,7 +2511,7 @@ ARGUMENTS: ${slash.args}`);
2583
2511
  }, [stdout]);
2584
2512
  useEffect3(() => {
2585
2513
  const modalOpen = !!(pending || planAsk || picker || listPicker || mcpMenu || providerMenu || prompt);
2586
- if (!runtime.config.thinkingClickCollapse || !busy && !hasThinking || modalOpen || !stdin.isTTY || !stdout.isTTY) return;
2514
+ if (!runtime.config.thinkingClickCollapse || !busy && !hasThinking || modalOpen || !isTtyStream(stdin) || !isTtyStream(stdout)) return;
2587
2515
  let click;
2588
2516
  let mouseBuffer = "";
2589
2517
  let wheelTimer;
@@ -2761,7 +2689,7 @@ ARGUMENTS: ${slash.args}`);
2761
2689
  if (!text) return null;
2762
2690
  const allLines = text.split("\n");
2763
2691
  const lines = allLines.length;
2764
- const shownText = isLive && isRealTty && allLines.length > maxLiveLines ? `\u2026 (${allLines.length - maxLiveLines} lines above) \u2026
2692
+ const shownText = isLive && realStdout && allLines.length > maxLiveLines ? `\u2026 (${allLines.length - maxLiveLines} lines above) \u2026
2765
2693
  ${allLines.slice(-maxLiveLines).join("\n")}` : text;
2766
2694
  const isTarget = e.id === lastThinkingEntryId;
2767
2695
  return /* @__PURE__ */ jsxs12(
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  VERSION
4
- } from "./chunk-F6NNUUF3.js";
4
+ } from "./chunk-RRE6WRU5.js";
5
5
  import {
6
6
  t
7
7
  } from "./chunk-R754XIBJ.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botconnector/bccli",
3
- "version": "0.4.13",
3
+ "version": "0.4.14",
4
4
  "description": "BCCLI — BotConnector AI coding agent for the terminal",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,7 +27,7 @@
27
27
  "dependencies": {
28
28
  "@modelcontextprotocol/sdk": "^1.32.1",
29
29
  "diff": "^9.0.0",
30
- "ink": "^7.1.1",
30
+ "ink": "^8.0.0",
31
31
  "openai": "^7.27.0",
32
32
  "react": "^19.3.0",
33
33
  "undici": "^8.12.1",
@@ -1 +0,0 @@
1
- export declare const isFocusReport: (input: string) => boolean;