@botconnector/bccli 0.4.6 → 0.4.8

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.
Files changed (48) hide show
  1. package/dist/{acp-YGQXX2L7.js → acp-VEXFXT5P.js} +2 -2
  2. package/dist/{args-TFKRCKTY.js → args-6XMUZDAK.js} +4 -4
  3. package/dist/{chunk-WTCWBY2D.js → chunk-2YG6L3YO.js} +2 -2
  4. package/dist/{chunk-27REMLDV.js → chunk-62UTSCWF.js} +1 -1
  5. package/dist/{chunk-CILTKMZW.js → chunk-6H6MPG7L.js} +7 -7
  6. package/dist/{chunk-QZKB6VTU.js → chunk-AWBEZY4D.js} +4 -4
  7. package/dist/{chunk-NSARPM5C.js → chunk-CSIQDFEF.js} +1 -1
  8. package/dist/{chunk-AK6TWKET.js → chunk-DRJSANKH.js} +1 -1
  9. package/dist/{chunk-XSUFHD67.js → chunk-EAR2C6TS.js} +1 -1
  10. package/dist/{chunk-BBZLRWPR.js → chunk-EOJNFGOP.js} +4 -4
  11. package/dist/{chunk-2Y6TH4MA.js → chunk-HPYI7L4W.js} +4 -4
  12. package/dist/{chunk-AN7SNPFA.js → chunk-KREGVQ63.js} +11 -11
  13. package/dist/{chunk-ZGIK5INC.js → chunk-O6NTUSSE.js} +1 -1
  14. package/dist/{chunk-BL2KOEXJ.js → chunk-OETLWNGS.js} +1 -1
  15. package/dist/{chunk-D7GAZKXT.js → chunk-OUJRD7GG.js} +3 -3
  16. package/dist/{chunk-6EGQI6HJ.js → chunk-RRECJTOG.js} +1 -1
  17. package/dist/{chunk-XQVEAF3F.js → chunk-TLCFBQ6E.js} +2 -2
  18. package/dist/{chunk-O5ATYRUP.js → chunk-WSSJH765.js} +1 -1
  19. package/dist/{chunk-EOOWV6C6.js → chunk-XCVYR5BK.js} +1 -0
  20. package/dist/{chunk-3JQZ2IKV.js → chunk-Z2ELYJ5O.js} +3 -3
  21. package/dist/cli.js +38 -38
  22. package/dist/{completion-JCBMQKNQ.js → completion-FETH4OGC.js} +1 -1
  23. package/dist/{config-JCI7NAVY.js → config-KR5JI5RA.js} +3 -3
  24. package/dist/{config-2MR6V7U7.js → config-RVMC23W3.js} +2 -2
  25. package/dist/{ghBotCli-IXRHTHC5.js → ghBotCli-Z6GWXCJ6.js} +14 -14
  26. package/dist/{integrationCli-KOCF73GG.js → integrationCli-GPRR6J6W.js} +2 -2
  27. package/dist/{login-IMVSN4X3.js → login-DFSN77L3.js} +4 -4
  28. package/dist/{mcpCli-IBC3WCHG.js → mcpCli-64P3SVUE.js} +6 -6
  29. package/dist/{modelsCli-BOPAZIG4.js → modelsCli-PFQY3G2Q.js} +6 -6
  30. package/dist/{oauthLogin-TUXZLIQN.js → oauthLogin-NR22NWEV.js} +1 -1
  31. package/dist/{pluginsCli-X7NZRU7X.js → pluginsCli-UKRJ3AHN.js} +2 -2
  32. package/dist/{prCli-GPDLWYWC.js → prCli-6FCI36AJ.js} +1 -1
  33. package/dist/providerCli-PBSZECBM.js +15 -0
  34. package/dist/sdk.js +3 -2
  35. package/dist/{serve-XRFCR6MG.js → serve-DTTFDRUY.js} +15 -15
  36. package/dist/{serve-A764QS5U.js → serve-PKUTKQQT.js} +3 -3
  37. package/dist/session-XABMBIIF.js +12 -0
  38. package/dist/setup-CLPQLTM7.js +24 -0
  39. package/dist/{statsCli-FKGON32O.js → statsCli-FR7GOKWO.js} +1 -1
  40. package/dist/{transferCli-BQXPUFPH.js → transferCli-GIE4MEJ4.js} +4 -4
  41. package/dist/ui/PromptInput.d.ts +3 -1
  42. package/dist/ui/thinkingMouse.d.ts +2 -0
  43. package/dist/{ui-S6OQOIFO.js → ui-NZVOCQSU.js} +197 -83
  44. package/dist/{update-SYDSYLR6.js → update-W2D2XJVP.js} +2 -2
  45. package/package.json +1 -1
  46. package/dist/providerCli-IRJTX5JF.js +0 -15
  47. package/dist/session-NPKTEDKV.js +0 -12
  48. package/dist/setup-KYDIUOOG.js +0 -24
@@ -2,14 +2,14 @@
2
2
  import {
3
3
  CATALOG,
4
4
  fillTemplate
5
- } from "./chunk-XQVEAF3F.js";
5
+ } from "./chunk-TLCFBQ6E.js";
6
6
  import {
7
7
  MAX_VERIFY_ROUNDS,
8
8
  runVerify,
9
9
  toolLabel,
10
10
  verifyFollowup,
11
11
  worktreeListText
12
- } from "./chunk-D7GAZKXT.js";
12
+ } from "./chunk-OUJRD7GG.js";
13
13
  import {
14
14
  BUILTIN_AGENTS,
15
15
  appendMemory,
@@ -24,7 +24,7 @@ import {
24
24
  runCommand,
25
25
  runHooks,
26
26
  validateGlobPattern
27
- } from "./chunk-NSARPM5C.js";
27
+ } from "./chunk-CSIQDFEF.js";
28
28
  import "./chunk-PSO7R5AD.js";
29
29
  import {
30
30
  nextMode,
@@ -34,39 +34,39 @@ import {
34
34
  hasKey,
35
35
  providerName,
36
36
  writeGlobalConfig
37
- } from "./chunk-27REMLDV.js";
37
+ } from "./chunk-62UTSCWF.js";
38
38
  import {
39
39
  Session
40
- } from "./chunk-BL2KOEXJ.js";
40
+ } from "./chunk-OETLWNGS.js";
41
41
  import {
42
42
  contentText
43
- } from "./chunk-BBZLRWPR.js";
43
+ } from "./chunk-EOJNFGOP.js";
44
44
  import {
45
45
  REASONING_LEVELS,
46
46
  assertReasoningSupported,
47
47
  parseReasoningLevel,
48
48
  supportedReasoningLevels
49
- } from "./chunk-XSUFHD67.js";
49
+ } from "./chunk-EAR2C6TS.js";
50
50
  import {
51
51
  addGlobalServer,
52
52
  globalMcpPath,
53
53
  readMcpFile,
54
54
  removeGlobalServer
55
- } from "./chunk-WTCWBY2D.js";
55
+ } from "./chunk-2YG6L3YO.js";
56
56
  import {
57
57
  ACCENT,
58
58
  PRESETS,
59
59
  color,
60
60
  matchKeybind,
61
61
  removeCredential
62
- } from "./chunk-AK6TWKET.js";
62
+ } from "./chunk-DRJSANKH.js";
63
63
  import {
64
64
  getLanguage,
65
65
  locale,
66
66
  parseLang,
67
67
  setLanguage,
68
68
  t
69
- } from "./chunk-EOOWV6C6.js";
69
+ } from "./chunk-XCVYR5BK.js";
70
70
 
71
71
  // src/ui/index.tsx
72
72
  import { render } from "ink";
@@ -82,6 +82,7 @@ import { useCallback, useEffect as useEffect3, useRef as useRef2, useState as us
82
82
  // src/commands.ts
83
83
  var SLASH_COMMANDS = [
84
84
  { name: "help", description: "list of commands and shortcuts" },
85
+ { name: "thinking", description: "show/hide the model\u2019s thinking" },
85
86
  { name: "model", description: "change model" },
86
87
  { name: "reasoning", description: "set reasoning: auto/off/low/medium/high/max" },
87
88
  { name: "provider", description: "add/choose an AI provider" },
@@ -841,7 +842,7 @@ function clickedThinking(click, cursorRow, rootHeight, target) {
841
842
  const origin = cursorRow - rootHeight + 1;
842
843
  const row = origin + target.y;
843
844
  const col = target.x + 1;
844
- return (click.y === row || click.y === row - 1) && click.x >= col && click.x < col + Math.min(target.width, 46);
845
+ return (click.y === row || click.y === row - 1) && click.x >= col && click.x < col + Math.min(target.width, 72);
845
846
  }
846
847
  function parseMouseWheel(input) {
847
848
  const match = /^\[<?(\d+);\d+;\d+[mM]$/.exec(input);
@@ -853,6 +854,9 @@ function parseMouseWheel(input) {
853
854
  if (dir === 1) return "down";
854
855
  return void 0;
855
856
  }
857
+ function hasMouseWheelSequence(chunk) {
858
+ return chunk.includes("\x1B[") && /\[<?6[4567];\d+;\d+[mM]/.test(chunk);
859
+ }
856
860
  function isMouseControlInput(input) {
857
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[<");
858
862
  }
@@ -1295,7 +1299,7 @@ ${s.value.slice(start)}`, cursor: start }, mode: "insert", handled: true };
1295
1299
 
1296
1300
  // src/ui/PromptInput.tsx
1297
1301
  import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1298
- function PromptInput({ disabled, history, cwd, onSubmit, extraCommands, injected, vim }) {
1302
+ function PromptInput({ disabled, history, cwd, onSubmit, extraCommands, injected, vim, onEmptyTab }) {
1299
1303
  const [line, setLine] = useState6({ value: "", cursor: 0 });
1300
1304
  const { value } = line;
1301
1305
  const [historyIndex, setHistoryIndex] = useState6(null);
@@ -1438,6 +1442,10 @@ ${value.slice(line.cursor)}`, cursor: before.length });
1438
1442
  return;
1439
1443
  }
1440
1444
  if (key.tab && !key.shift) {
1445
+ if (!value.trim() && onEmptyTab) {
1446
+ onEmptyTab();
1447
+ return;
1448
+ }
1441
1449
  const before = value.slice(0, line.cursor);
1442
1450
  const completed = completeFile(before, cwd);
1443
1451
  if (completed !== before) edit({ value: completed + value.slice(line.cursor), cursor: completed.length });
@@ -1853,17 +1861,44 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
1853
1861
  const [showToolOutput, setShowToolOutput] = useState10(false);
1854
1862
  const [staticKey, setStaticKey] = useState10(0);
1855
1863
  const [, setConfigRev] = useState10(0);
1856
- const liveThinkingEntryId = transcript.live.findLast((e) => e.kind === "thinking" && !!e.text.trim())?.id;
1864
+ const lastUserIdx = transcript.done.findLastIndex((e) => e.kind === "user");
1857
1865
  const { stdin } = useStdin();
1858
1866
  const { stdout } = useStdout2();
1867
+ const isRealTty = Boolean(stdout?.isTTY && "fd" in stdout);
1868
+ const maxLiveLines = Math.max(8, (stdout?.rows ?? 24) - 10);
1869
+ const maxSplitIdxRef = useRef2(0);
1859
1870
  const refreshStatic = useCallback(() => {
1860
1871
  if (stdout?.isTTY && "fd" in stdout) {
1861
1872
  stdout.write("\x1B[2J\x1B[3J\x1B[H");
1862
1873
  }
1874
+ maxSplitIdxRef.current = 0;
1863
1875
  setStaticKey((k2) => k2 + 1);
1864
1876
  }, [stdout]);
1877
+ let splitIdx = Math.max(maxSplitIdxRef.current, lastUserIdx > 0 ? lastUserIdx : 0);
1878
+ if (isRealTty) {
1879
+ const entryLines = (e) => {
1880
+ if (e.kind === "thinking") return showThinking ? Math.min(maxLiveLines, e.text.split("\n").length + 2) : 2;
1881
+ if (e.kind === "tool") return showToolOutput ? Math.min(maxLiveLines, (e.output ?? e.display ?? "").split("\n").length + 2) : 5;
1882
+ if (e.kind === "assistant" || e.kind === "notice" || e.kind === "user") return e.text.split("\n").length + 1;
1883
+ return 2;
1884
+ };
1885
+ const liveLines = transcript.live.reduce((acc, e) => acc + entryLines(e), 0);
1886
+ let doneLines = transcript.done.slice(splitIdx).reduce((acc, e) => acc + entryLines(e), 0);
1887
+ while (splitIdx < transcript.done.length - 1 && doneLines + liveLines > maxLiveLines) {
1888
+ doneLines -= entryLines(transcript.done[splitIdx]);
1889
+ splitIdx++;
1890
+ }
1891
+ maxSplitIdxRef.current = splitIdx;
1892
+ }
1893
+ const staticDone = transcript.done.slice(0, splitIdx);
1894
+ const activeTurnDone = transcript.done.slice(splitIdx);
1895
+ const activeTurnEntries = [...activeTurnDone, ...transcript.live];
1896
+ const lastThinkingEntryId = activeTurnEntries.findLast((e) => e.kind === "thinking" && !!e.text.trim())?.id;
1897
+ const hasThinking = lastThinkingEntryId !== void 0 || transcript.done.some((e) => e.kind === "thinking" && !!e.text.trim());
1865
1898
  const liveRootRef = useRef2(null);
1866
1899
  const thinkingTargetRef = useRef2(null);
1900
+ const spinnerTargetRef = useRef2(null);
1901
+ const thinkingEntryRefs = useRef2(/* @__PURE__ */ new Map());
1867
1902
  const [injected, setInjected] = useState10();
1868
1903
  useEffect3(() => runtime.todos.subscribe(setTodos), [runtime]);
1869
1904
  const extraCommands = [
@@ -1946,16 +1981,50 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
1946
1981
  },
1947
1982
  [runtime, notice]
1948
1983
  );
1984
+ const toggleThinking = useCallback(() => {
1985
+ const next = !showThinkingRef.current;
1986
+ showThinkingRef.current = next;
1987
+ setShowThinking(next);
1988
+ if (maxSplitIdxRef.current > 0) refreshStatic();
1989
+ try {
1990
+ writeGlobalConfig({ thinkingVisible: next }, runtime.env);
1991
+ } catch (error) {
1992
+ notice(t("Could not save thinking visibility: {error}", { error: error.message }), "warn");
1993
+ }
1994
+ }, [runtime, notice, refreshStatic]);
1949
1995
  const runSlashCommand = useCallback(
1950
1996
  async (name, args) => {
1951
1997
  switch (name) {
1952
1998
  case "help":
1953
1999
  notice(helpText(runtime));
1954
2000
  return;
2001
+ case "thinking":
2002
+ case "t": {
2003
+ const v = args.trim().toLowerCase();
2004
+ if (v === "on" || v === "true") {
2005
+ if (!showThinkingRef.current) toggleThinking();
2006
+ } else if (v === "off" || v === "false") {
2007
+ if (showThinkingRef.current) toggleThinking();
2008
+ } else {
2009
+ toggleThinking();
2010
+ }
2011
+ return;
2012
+ }
2013
+ case "output":
2014
+ case "o":
2015
+ setShowToolOutput((prev) => !prev);
2016
+ if (maxSplitIdxRef.current > 0) refreshStatic();
2017
+ return;
1955
2018
  case "exit":
2019
+ case "quit":
1956
2020
  exit();
1957
2021
  return;
1958
2022
  case "clear":
2023
+ controller.current?.abort();
2024
+ controller.current = null;
2025
+ setQueued([]);
2026
+ setBusy(false);
2027
+ setCancelling(false);
1959
2028
  runtime.agent.clear();
1960
2029
  setTokens(0);
1961
2030
  setShowToolOutput(false);
@@ -2053,6 +2122,11 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
2053
2122
  return;
2054
2123
  }
2055
2124
  case "new":
2125
+ controller.current?.abort();
2126
+ controller.current = null;
2127
+ setQueued([]);
2128
+ setBusy(false);
2129
+ setCancelling(false);
2056
2130
  runtime.newSession();
2057
2131
  setTokens(0);
2058
2132
  setShowToolOutput(false);
@@ -2403,7 +2477,7 @@ function App({ runtime, initialPrompt, version, updateMessage }) {
2403
2477
  notice(t("Unknown command: /{name}. Type /help.", { name }), "warn");
2404
2478
  }
2405
2479
  },
2406
- [runtime, notice, exit, version, runTurn, ask, refreshStatic]
2480
+ [runtime, notice, exit, version, runTurn, ask, refreshStatic, toggleThinking]
2407
2481
  );
2408
2482
  const runSlash = useCallback(
2409
2483
  (name, args) => runSlashCommand(name, args).catch((error) => notice(`/${name}: ${error.message}`, "error")),
@@ -2447,7 +2521,7 @@ ${out}` };
2447
2521
  }
2448
2522
  const command = runtime.commands.find((c) => c.name.toLowerCase() === slash.name);
2449
2523
  const skill = runtime.skills.find((s) => s.name.toLowerCase() === slash.name);
2450
- if (SLASH_COMMANDS.some((b) => b.name === slash.name) || !command && !skill) void runSlash(slash.name, slash.args);
2524
+ if (SLASH_COMMANDS.some((b) => b.name === slash.name) || slash.name === "t" || slash.name === "output" || slash.name === "o" || slash.name === "quit" || !command && !skill) void runSlash(slash.name, slash.args);
2451
2525
  else if (command) void runTurn(expandCommand(command, slash.args));
2452
2526
  else if (skill) {
2453
2527
  let body;
@@ -2466,10 +2540,26 @@ ARGUMENTS: ${slash.args}`);
2466
2540
  );
2467
2541
  const onPrompt = useCallback(
2468
2542
  (text) => {
2469
- if (busy) setQueued((q) => [...q, text]);
2470
- else submit(text);
2543
+ if (!busy) {
2544
+ submit(text);
2545
+ return;
2546
+ }
2547
+ if (text.startsWith("#") && text.slice(1).trim()) {
2548
+ submit(text);
2549
+ return;
2550
+ }
2551
+ const slash = parseSlash(text);
2552
+ if (slash) {
2553
+ const turnMutating = /* @__PURE__ */ new Set(["init", "pr", "compact", "rewind", "undo", "redo", "resume"]);
2554
+ const isCustomTurn = !SLASH_COMMANDS.some((b) => b.name === slash.name) && slash.name !== "t" && slash.name !== "output" && slash.name !== "o" && slash.name !== "quit" && (runtime.commands.some((c) => c.name.toLowerCase() === slash.name) || runtime.skills.some((s) => s.name.toLowerCase() === slash.name));
2555
+ if (!turnMutating.has(slash.name) && !isCustomTurn) {
2556
+ submit(text);
2557
+ return;
2558
+ }
2559
+ }
2560
+ setQueued((q) => [...q, text]);
2471
2561
  },
2472
- [busy, submit]
2562
+ [busy, submit, runtime]
2473
2563
  );
2474
2564
  useEffect3(() => {
2475
2565
  if (busy || pending || planAsk || !queued.length) return;
@@ -2484,17 +2574,6 @@ ARGUMENTS: ${slash.args}`);
2484
2574
  submit(initialPrompt);
2485
2575
  }
2486
2576
  }, [initialPrompt, submit]);
2487
- const toggleThinking = useCallback(() => {
2488
- const next = !showThinkingRef.current;
2489
- showThinkingRef.current = next;
2490
- setShowThinking(next);
2491
- refreshStatic();
2492
- try {
2493
- writeGlobalConfig({ thinkingVisible: next }, runtime.env);
2494
- } catch (error) {
2495
- notice(t("Could not save thinking visibility: {error}", { error: error.message }), "warn");
2496
- }
2497
- }, [runtime, notice, refreshStatic]);
2498
2577
  useEffect3(() => {
2499
2578
  if (!stdout?.isTTY || !("fd" in stdout)) return;
2500
2579
  stdout.write("\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?2004h");
@@ -2502,49 +2581,59 @@ ARGUMENTS: ${slash.args}`);
2502
2581
  stdout.write("\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?2004l");
2503
2582
  };
2504
2583
  }, [stdout]);
2505
- const scrollableModalOpen = !!(picker || listPicker || mcpMenu || providerMenu || pending || planAsk);
2506
- useEffect3(() => {
2507
- if (!scrollableModalOpen || !stdout?.isTTY || !("fd" in stdout)) return;
2508
- stdout.write("\x1B[?1000h\x1B[?1006h");
2509
- return () => {
2510
- stdout.write("\x1B[?1000l\x1B[?1006l");
2511
- };
2512
- }, [scrollableModalOpen, stdout]);
2513
2584
  useEffect3(() => {
2514
2585
  const modalOpen = !!(pending || planAsk || picker || listPicker || mcpMenu || providerMenu || prompt);
2515
- if (!runtime.config.thinkingClickCollapse || !busy || modalOpen || !stdin.isTTY || !stdout.isTTY || !thinkingTargetRef.current) return;
2586
+ if (!runtime.config.thinkingClickCollapse || !busy && !hasThinking || modalOpen || !stdin.isTTY || !stdout.isTTY) return;
2516
2587
  let click;
2517
2588
  let mouseBuffer = "";
2589
+ let wheelTimer;
2518
2590
  const onData = (data) => {
2519
- mouseBuffer += String(data);
2591
+ const chunk = String(data);
2592
+ if (hasMouseWheelSequence(chunk)) {
2593
+ stdout.write("\x1B[?1000l\x1B[?1006l");
2594
+ if (wheelTimer) clearTimeout(wheelTimer);
2595
+ wheelTimer = setTimeout(() => {
2596
+ stdout.write("\x1B[?1000h\x1B[?1006h");
2597
+ }, 1200);
2598
+ }
2599
+ mouseBuffer += chunk;
2520
2600
  const reports = parseThinkingReports(mouseBuffer);
2521
2601
  mouseBuffer = reports.rest.slice(-80);
2522
2602
  for (const report of reports.events) {
2523
2603
  if (report.type === "mouse") {
2524
2604
  click = report.press;
2525
2605
  stdout.write("\x1B[6n");
2526
- } else if (click && liveRootRef.current && thinkingTargetRef.current) {
2606
+ } else if (click && liveRootRef.current) {
2527
2607
  const current = click;
2528
2608
  click = void 0;
2529
2609
  const root = measureElement(liveRootRef.current);
2530
- const target = measureElement(thinkingTargetRef.current);
2531
- if (clickedThinking(current, report.cursor.row, root.height, target)) toggleThinking();
2610
+ const candidates = [];
2611
+ if (thinkingTargetRef.current) candidates.push(thinkingTargetRef.current);
2612
+ if (spinnerTargetRef.current) candidates.push(spinnerTargetRef.current);
2613
+ for (const el of thinkingEntryRefs.current.values()) {
2614
+ if (!candidates.includes(el)) candidates.push(el);
2615
+ }
2616
+ if (candidates.some((el) => clickedThinking(current, report.cursor.row, root.height, measureElement(el)))) {
2617
+ toggleThinking();
2618
+ }
2532
2619
  }
2533
2620
  }
2534
2621
  };
2535
2622
  stdin.on("data", onData);
2536
2623
  stdout.write("\x1B[?1000h\x1B[?1006h");
2537
2624
  return () => {
2625
+ if (wheelTimer) clearTimeout(wheelTimer);
2538
2626
  stdin.off("data", onData);
2539
2627
  stdout.write("\x1B[?1000l\x1B[?1006l");
2540
2628
  };
2541
- }, [busy, pending, planAsk, picker, listPicker, mcpMenu, providerMenu, prompt, stdin, stdout, toggleThinking, runtime.config.thinkingClickCollapse]);
2629
+ }, [busy, hasThinking, pending, planAsk, picker, listPicker, mcpMenu, providerMenu, prompt, stdin, stdout, toggleThinking, runtime.config.thinkingClickCollapse]);
2542
2630
  useInput9((input, key) => {
2631
+ const modalOpen = !!(pending || planAsk || picker || listPicker || mcpMenu || providerMenu || prompt);
2543
2632
  if (key.tab && key.shift) {
2544
2633
  const next = nextMode(runtime.agent.permissions.mode);
2545
2634
  runtime.agent.permissions.mode = next;
2546
2635
  setMode(next);
2547
- } else if (key.escape && busy && !pending && !planAsk) {
2636
+ } else if (key.escape && busy && !modalOpen) {
2548
2637
  controller.current?.abort();
2549
2638
  setCancelling(true);
2550
2639
  if (queued.length) {
@@ -2561,11 +2650,11 @@ ARGUMENTS: ${slash.args}`);
2561
2650
  notice(t("No image on the clipboard."), "warn");
2562
2651
  }
2563
2652
  })();
2564
- } else if (matchKeybind(runtime.config.keybinds.thinking, input, key)) {
2653
+ } else if (matchKeybind(runtime.config.keybinds.thinking, input, key) || key.meta && !key.ctrl && input.toLowerCase() === "t") {
2565
2654
  toggleThinking();
2566
- } else if (matchKeybind(runtime.config.keybinds.toolOutput, input, key)) {
2655
+ } else if (matchKeybind(runtime.config.keybinds.toolOutput, input, key) || key.meta && !key.ctrl && input.toLowerCase() === "o") {
2567
2656
  setShowToolOutput((prev) => !prev);
2568
- refreshStatic();
2657
+ if (maxSplitIdxRef.current > 0) refreshStatic();
2569
2658
  } else if (key.ctrl && input.toLowerCase() === "l") {
2570
2659
  refreshStatic();
2571
2660
  }
@@ -2632,8 +2721,6 @@ ARGUMENTS: ${slash.args}`);
2632
2721
  pending?.resolve(a);
2633
2722
  setAsks((q) => q.slice(1));
2634
2723
  };
2635
- const isRealTty = Boolean(stdout?.isTTY && "fd" in stdout);
2636
- const maxLiveLines = Math.max(8, (stdout?.rows ?? 24) - 10);
2637
2724
  const capLiveMarkdown = (raw) => {
2638
2725
  if (!isRealTty) return raw;
2639
2726
  const lines = raw.split("\n");
@@ -2676,21 +2763,35 @@ ARGUMENTS: ${slash.args}`);
2676
2763
  const lines = allLines.length;
2677
2764
  const shownText = isLive && isRealTty && allLines.length > maxLiveLines ? `\u2026 (${allLines.length - maxLiveLines} lines above) \u2026
2678
2765
  ${allLines.slice(-maxLiveLines).join("\n")}` : text;
2679
- const isTarget = e.id === liveThinkingEntryId;
2680
- return /* @__PURE__ */ jsxs12(Box13, { ref: isTarget ? thinkingTargetRef : void 0, marginTop: 1, flexDirection: "column", children: [
2681
- /* @__PURE__ */ jsxs12(Box13, { flexDirection: "row", children: [
2682
- /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: showThinking ? t("\u273B Thinking") : t("\u273B Thinking \xB7 {n} lines", { n: lines }) }),
2683
- /* @__PURE__ */ jsxs12(Text16, { dimColor: true, children: [
2684
- " \xB7 ",
2685
- runtime.config.keybinds.thinking.spec,
2686
- runtime.config.thinkingClickCollapse ? ` \xB7 ${t("click to toggle")}` : ""
2687
- ] })
2688
- ] }),
2689
- showThinking ? /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", paddingLeft: 2, children: [
2690
- /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: t("Model: {model} \xB7 reasoning: {level}", { model: runtime.modelRef, level: reasoning }) }),
2691
- /* @__PURE__ */ jsx16(Text16, { dimColor: true, italic: true, children: shownText })
2692
- ] }) : null
2693
- ] }, e.id);
2766
+ const isTarget = e.id === lastThinkingEntryId;
2767
+ return /* @__PURE__ */ jsxs12(
2768
+ Box13,
2769
+ {
2770
+ ref: (el) => {
2771
+ if (isTarget) thinkingTargetRef.current = el;
2772
+ if (el) thinkingEntryRefs.current.set(e.id, el);
2773
+ else thinkingEntryRefs.current.delete(e.id);
2774
+ },
2775
+ marginTop: 1,
2776
+ flexDirection: "column",
2777
+ children: [
2778
+ /* @__PURE__ */ jsxs12(Box13, { flexDirection: "row", children: [
2779
+ /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: showThinking ? t("\u273B Thinking") : t("\u273B Thinking \xB7 {n} lines", { n: lines }) }),
2780
+ /* @__PURE__ */ jsxs12(Text16, { dimColor: true, children: [
2781
+ " \xB7 ",
2782
+ runtime.config.keybinds.thinking.spec,
2783
+ " / tab",
2784
+ runtime.config.thinkingClickCollapse ? ` \xB7 ${t("click to toggle")}` : ""
2785
+ ] })
2786
+ ] }),
2787
+ showThinking ? /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", paddingLeft: 2, children: [
2788
+ /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: t("Model: {model} \xB7 reasoning: {level}", { model: runtime.modelRef, level: reasoning }) }),
2789
+ /* @__PURE__ */ jsx16(Text16, { dimColor: true, italic: true, children: shownText })
2790
+ ] }) : null
2791
+ ]
2792
+ },
2793
+ e.id
2794
+ );
2694
2795
  }
2695
2796
  case "tool":
2696
2797
  return /* @__PURE__ */ jsx16(ToolBlock, { tool: e.tool, target: e.target, output: e.output, display: e.display, isError: e.isError, done: e.done, expanded: showToolOutput, sub: e.sub, moreBind: runtime.config.keybinds.toolOutput.spec }, e.id);
@@ -2704,23 +2805,36 @@ ${allLines.slice(-maxLiveLines).join("\n")}` : text;
2704
2805
  const activeSpinnerSummary = activeToolEntry ? `${toolLabel(activeToolEntry.tool)}${activeTarget ? ` ${activeTarget.length > 20 ? `${activeTarget.slice(0, 20)}\u2026` : activeTarget}` : ""}` : "";
2705
2806
  const activeToolSummary = activeToolEntry ? `${toolLabel(activeToolEntry.tool)}${activeTarget ? ` ${activeTarget.length > 68 ? `${activeTarget.slice(0, 68)}\u2026` : activeTarget}` : ""}` : "";
2706
2807
  return /* @__PURE__ */ jsxs12(Box13, { ref: liveRootRef, flexDirection: "column", children: [
2707
- /* @__PURE__ */ jsx16(Static, { items: transcript.done, children: renderEntry }, staticKey),
2808
+ /* @__PURE__ */ jsx16(Static, { items: staticDone, children: renderEntry }, staticKey),
2809
+ activeTurnDone.map(renderEntry),
2708
2810
  transcript.live.map(renderEntry),
2709
- busy && !pending && !planAsk ? /* @__PURE__ */ jsxs12(Box13, { ref: liveThinkingEntryId === void 0 ? thinkingTargetRef : void 0, marginTop: 1, flexDirection: "column", children: [
2710
- /* @__PURE__ */ jsxs12(Box13, { flexDirection: "row", children: [
2711
- /* @__PURE__ */ jsx16(Spinner, { label: cancelling ? t("Cancelling") : activeSpinnerSummary ? `${t("Thinking")} \xB7 ${activeSpinnerSummary}` : t("Thinking"), startedAt }),
2712
- /* @__PURE__ */ jsxs12(Text16, { dimColor: true, children: [
2713
- " \xB7 ",
2714
- runtime.config.keybinds.thinking.spec,
2715
- runtime.config.thinkingClickCollapse ? ` \xB7 ${t("click to toggle")}` : ""
2716
- ] })
2717
- ] }),
2718
- showThinking && liveThinkingEntryId === void 0 ? /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", paddingLeft: 2, children: [
2719
- /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: t("Model: {model} \xB7 reasoning: {level}", { model: runtime.modelRef, level: reasoning }) }),
2720
- activeToolSummary ? /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: `\u25B6 ${activeToolSummary}` }) : null,
2721
- !activeToolSummary ? /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: t("No reasoning summary received yet; tool activity remains visible above.") }) : null
2722
- ] }) : null
2723
- ] }) : null,
2811
+ busy && !pending && !planAsk ? /* @__PURE__ */ jsxs12(
2812
+ Box13,
2813
+ {
2814
+ ref: (el) => {
2815
+ spinnerTargetRef.current = el;
2816
+ if (lastThinkingEntryId === void 0) thinkingTargetRef.current = el;
2817
+ },
2818
+ marginTop: 1,
2819
+ flexDirection: "column",
2820
+ children: [
2821
+ /* @__PURE__ */ jsxs12(Box13, { flexDirection: "row", children: [
2822
+ /* @__PURE__ */ jsx16(Spinner, { label: cancelling ? t("Cancelling") : activeSpinnerSummary ? `${t("Thinking")} \xB7 ${activeSpinnerSummary}` : t("Thinking"), startedAt }),
2823
+ /* @__PURE__ */ jsxs12(Text16, { dimColor: true, children: [
2824
+ " \xB7 ",
2825
+ runtime.config.keybinds.thinking.spec,
2826
+ " / tab",
2827
+ runtime.config.thinkingClickCollapse ? ` \xB7 ${t("click to toggle")}` : ""
2828
+ ] })
2829
+ ] }),
2830
+ showThinking && lastThinkingEntryId === void 0 ? /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", paddingLeft: 2, children: [
2831
+ /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: t("Model: {model} \xB7 reasoning: {level}", { model: runtime.modelRef, level: reasoning }) }),
2832
+ activeToolSummary ? /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: `\u25B6 ${activeToolSummary}` }) : null,
2833
+ !activeToolSummary ? /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: t("No reasoning summary received yet; tool activity remains visible above.") }) : null
2834
+ ] }) : null
2835
+ ]
2836
+ }
2837
+ ) : null,
2724
2838
  pending ? /* @__PURE__ */ jsx16(PermissionPrompt, { request: pending.request, onAnswer: answer }, pending.id) : null,
2725
2839
  picker ? /* @__PURE__ */ jsx16(
2726
2840
  ModelPicker,
@@ -2764,7 +2878,7 @@ ${allLines.slice(-maxLiveLines).join("\n")}` : text;
2764
2878
  ) : null,
2765
2879
  /* @__PURE__ */ jsx16(TodoList, { items: todos }),
2766
2880
  queued.map((q, i) => /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: t(" \u23F3 queued: {q}", { q }) }, `${i}-${q}`)),
2767
- /* @__PURE__ */ jsx16(PromptInput, { disabled: !!pending || !!picker || !!providerMenu || !!prompt || !!planAsk || !!mcpMenu || !!listPicker, history, cwd: runtime.cwd, onSubmit: onPrompt, extraCommands, injected, vim: runtime.config.editor === "vim" }),
2881
+ /* @__PURE__ */ jsx16(PromptInput, { disabled: !!pending || !!picker || !!providerMenu || !!prompt || !!planAsk || !!mcpMenu || !!listPicker, history, cwd: runtime.cwd, onSubmit: onPrompt, onEmptyTab: toggleThinking, extraCommands, injected, vim: runtime.config.editor === "vim" }),
2768
2882
  /* @__PURE__ */ jsx16(StatusBar, { mode, tokens, busy, model: modelLabel, reasoning })
2769
2883
  ] });
2770
2884
  }
@@ -2773,7 +2887,7 @@ ${allLines.slice(-maxLiveLines).join("\n")}` : text;
2773
2887
  import { jsx as jsx17 } from "react/jsx-runtime";
2774
2888
  async function startInteractive(rt, opts) {
2775
2889
  if (opts.resume) {
2776
- const { Session: Session2 } = await import("./session-NPKTEDKV.js");
2890
+ const { Session: Session2 } = await import("./session-XABMBIIF.js");
2777
2891
  const list = Session2.list(rt.home, rt.cwd).slice(0, 20);
2778
2892
  if (!list.length) console.log(t("No sessions in this folder yet; starting a new one."));
2779
2893
  else {
@@ -2789,7 +2903,7 @@ async function startInteractive(rt, opts) {
2789
2903
  if (chosen) rt.resume(chosen.session);
2790
2904
  }
2791
2905
  }
2792
- const { serversToStart, setProjectTrust } = await import("./config-JCI7NAVY.js");
2906
+ const { serversToStart, setProjectTrust } = await import("./config-KR5JI5RA.js");
2793
2907
  const plan = serversToStart(rt.home, rt.cwd);
2794
2908
  if (plan.needTrust.length) {
2795
2909
  const { createInterface } = await import("readline/promises");
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  VERSION
4
- } from "./chunk-ZGIK5INC.js";
4
+ } from "./chunk-O6NTUSSE.js";
5
5
  import {
6
6
  t
7
- } from "./chunk-EOOWV6C6.js";
7
+ } from "./chunk-XCVYR5BK.js";
8
8
 
9
9
  // src/update.ts
10
10
  import { spawnSync } from "child_process";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botconnector/bccli",
3
- "version": "0.4.6",
3
+ "version": "0.4.8",
4
4
  "description": "BCCLI — BotConnector AI coding agent for the terminal",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- addProviderKey,
4
- runProviderCommand
5
- } from "./chunk-QZKB6VTU.js";
6
- import "./chunk-2Y6TH4MA.js";
7
- import "./chunk-27REMLDV.js";
8
- import "./chunk-BBZLRWPR.js";
9
- import "./chunk-XSUFHD67.js";
10
- import "./chunk-AK6TWKET.js";
11
- import "./chunk-EOOWV6C6.js";
12
- export {
13
- addProviderKey,
14
- runProviderCommand
15
- };
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- Session,
4
- pruneSessions
5
- } from "./chunk-BL2KOEXJ.js";
6
- import "./chunk-BBZLRWPR.js";
7
- import "./chunk-XSUFHD67.js";
8
- import "./chunk-EOOWV6C6.js";
9
- export {
10
- Session,
11
- pruneSessions
12
- };
@@ -1,24 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- createRuntime,
4
- lunaPtcAutoEnabled
5
- } from "./chunk-AN7SNPFA.js";
6
- import "./chunk-OK2USAXX.js";
7
- import "./chunk-NSARPM5C.js";
8
- import "./chunk-O5ATYRUP.js";
9
- import "./chunk-PSO7R5AD.js";
10
- import "./chunk-WFZKJY3R.js";
11
- import "./chunk-QZKB6VTU.js";
12
- import "./chunk-2Y6TH4MA.js";
13
- import "./chunk-27REMLDV.js";
14
- import "./chunk-6EGQI6HJ.js";
15
- import "./chunk-BL2KOEXJ.js";
16
- import "./chunk-BBZLRWPR.js";
17
- import "./chunk-XSUFHD67.js";
18
- import "./chunk-WTCWBY2D.js";
19
- import "./chunk-AK6TWKET.js";
20
- import "./chunk-EOOWV6C6.js";
21
- export {
22
- createRuntime,
23
- lunaPtcAutoEnabled
24
- };