bravecode-cli 0.1.15 → 0.1.17

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/cli.mjs CHANGED
@@ -38043,11 +38043,12 @@ var init_task = __esm({
38043
38043
  });
38044
38044
 
38045
38045
  // src/version.ts
38046
- var APP_VERSION;
38046
+ var APP_VERSION, APP_NAME;
38047
38047
  var init_version = __esm({
38048
38048
  "src/version.ts"() {
38049
38049
  "use strict";
38050
- APP_VERSION = "0.1.15";
38050
+ APP_VERSION = "0.1.17";
38051
+ APP_NAME = "BraveCode";
38051
38052
  }
38052
38053
  });
38053
38054
 
@@ -41581,27 +41582,74 @@ var init_toast = __esm({
41581
41582
  import "react";
41582
41583
  import { Box, Text } from "ink";
41583
41584
  import { jsx as jsx6 } from "react/jsx-runtime";
41584
- function Logo({ width = 80 }) {
41585
- const logo = [
41586
- "\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557",
41587
- "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551",
41588
- "\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2557 \u2588\u2588\u2551",
41589
- "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2557\u2588\u2588\u2551",
41590
- "\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2554\u2588\u2588\u2588\u2554\u255D",
41591
- "\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u255D\u255A\u2550\u2550\u255D"
41592
- ];
41593
- return /* @__PURE__ */ jsx6(Box, { flexDirection: "column", alignItems: "center", children: logo.map((line, i) => /* @__PURE__ */ jsx6(Text, { color: "gray", children: line }, i)) });
41585
+ function Logo() {
41586
+ return /* @__PURE__ */ jsx6(Box, { flexDirection: "column", alignItems: "center", children: ROWS.map((row, i) => /* @__PURE__ */ jsx6(
41587
+ Text,
41588
+ {
41589
+ dimColor: !row.bright,
41590
+ italic: row.italic,
41591
+ bold: row.bright,
41592
+ children: row.chars
41593
+ },
41594
+ i
41595
+ )) });
41594
41596
  }
41597
+ var ROWS;
41595
41598
  var init_logo = __esm({
41596
41599
  "src/core/tui/components/logo.tsx"() {
41597
41600
  "use strict";
41601
+ ROWS = [
41602
+ { chars: " ____ ", bright: false, italic: true },
41603
+ { chars: "| _ \\ __ _ _ __ __ _ ", bright: false, italic: true },
41604
+ { chars: "| |_) / _` | '_ \\ / _` |", bright: false, italic: true },
41605
+ { chars: "| __/ (_| | | | | (_| |", bright: true, italic: false },
41606
+ { chars: "|_| \\__,_|_| |_|\\__,_|", bright: true, italic: false }
41607
+ ];
41598
41608
  }
41599
41609
  });
41600
41610
 
41601
- // src/core/tui/components/message.tsx
41611
+ // src/core/tui/components/header-bar.tsx
41602
41612
  import "react";
41603
41613
  import { Box as Box2, Text as Text2 } from "ink";
41604
41614
  import { jsx as jsx7, jsxs } from "react/jsx-runtime";
41615
+ function HeaderBar({ title, subtitle }) {
41616
+ const { colors } = useTheme();
41617
+ const cwd = process.cwd().replace(process.env.HOME || "", "~");
41618
+ return /* @__PURE__ */ jsxs(
41619
+ Box2,
41620
+ {
41621
+ flexDirection: "row",
41622
+ justifyContent: "space-between",
41623
+ width: "100%",
41624
+ paddingX: 1,
41625
+ children: [
41626
+ /* @__PURE__ */ jsxs(Box2, { flexDirection: "column", alignItems: "center", flexGrow: 1, children: [
41627
+ /* @__PURE__ */ jsxs(Text2, { children: [
41628
+ /* @__PURE__ */ jsx7(Text2, { bold: true, color: colors.text, children: title }),
41629
+ /* @__PURE__ */ jsx7(Text2, { color: colors.textMuted, children: " \u2014 " }),
41630
+ /* @__PURE__ */ jsx7(Text2, { color: colors.textSecondary, children: subtitle })
41631
+ ] }),
41632
+ /* @__PURE__ */ jsx7(Text2, { color: colors.textMuted, children: cwd })
41633
+ ] }),
41634
+ /* @__PURE__ */ jsxs(Box2, { gap: 1, children: [
41635
+ /* @__PURE__ */ jsx7(Text2, { color: colors.textMuted, children: "\u25A6" }),
41636
+ /* @__PURE__ */ jsx7(Text2, { color: colors.textMuted, children: "\u2261" })
41637
+ ] })
41638
+ ]
41639
+ }
41640
+ );
41641
+ }
41642
+ var init_header_bar = __esm({
41643
+ "src/core/tui/components/header-bar.tsx"() {
41644
+ "use strict";
41645
+ init_theme();
41646
+ }
41647
+ });
41648
+
41649
+ // src/core/tui/components/message.tsx
41650
+ import { memo, useEffect as useEffect2, useRef, useState as useState6 } from "react";
41651
+ import { Box as Box3, Text as Text3 } from "ink";
41652
+ import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
41605
41653
  function ToolCallDisplay({ toolCall }) {
41606
41654
  const { colors } = useTheme();
41607
41655
  const statusIcon = {
@@ -41631,17 +41679,17 @@ function ToolCallDisplay({ toolCall }) {
41631
41679
  };
41632
41680
  const label = toolLabels[toolCall.name]?.past || toolCall.name;
41633
41681
  const argStr = getToolArgs(toolCall);
41634
- return /* @__PURE__ */ jsxs(Box2, { marginLeft: 2, children: [
41635
- /* @__PURE__ */ jsxs(Text2, { color: statusColor, children: [
41682
+ return /* @__PURE__ */ jsxs2(Box3, { marginLeft: 2, children: [
41683
+ /* @__PURE__ */ jsxs2(Text3, { color: statusColor, children: [
41636
41684
  statusIcon,
41637
41685
  " "
41638
41686
  ] }),
41639
- /* @__PURE__ */ jsx7(Text2, { bold: true, color: colors.text, children: label }),
41640
- argStr && /* @__PURE__ */ jsxs(Text2, { color: colors.textMuted, children: [
41687
+ /* @__PURE__ */ jsx8(Text3, { bold: true, color: colors.text, children: label }),
41688
+ argStr && /* @__PURE__ */ jsxs2(Text3, { color: colors.textMuted, children: [
41641
41689
  " ",
41642
41690
  argStr
41643
41691
  ] }),
41644
- toolCall.output && toolCall.status === "completed" && /* @__PURE__ */ jsxs(Text2, { color: colors.textMuted, children: [
41692
+ toolCall.output && toolCall.status === "completed" && /* @__PURE__ */ jsxs2(Text3, { color: colors.textMuted, children: [
41645
41693
  " \u2514 ",
41646
41694
  truncate(toolCall.output.split("\n")[0], 60)
41647
41695
  ] })
@@ -41687,14 +41735,59 @@ function formatTime(date5) {
41687
41735
  hour12: false
41688
41736
  });
41689
41737
  }
41690
- function Message({ message, showTimestamp = false }) {
41738
+ function wrapLines(text2, width) {
41739
+ const innerWidth = Math.max(10, width);
41740
+ const out = [];
41741
+ for (const line of text2.split("\n")) {
41742
+ if (line.length === 0) {
41743
+ out.push("");
41744
+ continue;
41745
+ }
41746
+ for (let i = 0; i < line.length; i += innerWidth) {
41747
+ out.push(line.slice(i, i + innerWidth));
41748
+ }
41749
+ }
41750
+ return out;
41751
+ }
41752
+ function clipContent(content, width, skipTop, skipBottom) {
41753
+ if (!skipTop && !skipBottom) return content;
41754
+ const wrapped = wrapLines(content, Math.max(10, width - 2));
41755
+ const start = Math.min(skipTop, wrapped.length);
41756
+ const end = Math.max(start, wrapped.length - skipBottom);
41757
+ return wrapped.slice(start, end).join("\n");
41758
+ }
41759
+ function MessageImpl({
41760
+ message,
41761
+ showTimestamp = false,
41762
+ clipTop = 0,
41763
+ clipBottom = 0,
41764
+ maxRenderedLines
41765
+ }) {
41691
41766
  const { colors } = useTheme();
41767
+ if (message.role === "user") {
41768
+ return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "row", marginBottom: 1, children: [
41769
+ /* @__PURE__ */ jsx8(Text3, { color: colors.primary, children: "\u2502 " }),
41770
+ /* @__PURE__ */ jsx8(Text3, { color: colors.text, children: message.content })
41771
+ ] });
41772
+ }
41773
+ const isStreaming = message.toolCalls && message.toolCalls.some((tc) => tc.status === "running");
41774
+ const [renderedContent, setRenderedContent] = useState6(() => {
41775
+ if (!maxRenderedLines) return message.content;
41776
+ const wrapped = wrapLines(message.content, 80);
41777
+ return wrapped.slice(-maxRenderedLines).join("\n");
41778
+ });
41779
+ const lastSeenContent = useRef(message.content);
41780
+ useEffect2(() => {
41781
+ if (message.content === lastSeenContent.current) return;
41782
+ lastSeenContent.current = message.content;
41783
+ if (!maxRenderedLines) {
41784
+ setRenderedContent(message.content);
41785
+ return;
41786
+ }
41787
+ const wrapped = wrapLines(message.content, 80);
41788
+ setRenderedContent(wrapped.slice(-maxRenderedLines).join("\n"));
41789
+ }, [message.content, maxRenderedLines]);
41692
41790
  const roleConfig = {
41693
- user: {
41694
- label: "You",
41695
- color: colors.primary,
41696
- prefix: "\u203A"
41697
- },
41698
41791
  assistant: {
41699
41792
  label: "Assistant",
41700
41793
  color: colors.secondary,
@@ -41707,80 +41800,185 @@ function Message({ message, showTimestamp = false }) {
41707
41800
  }
41708
41801
  };
41709
41802
  const config2 = roleConfig[message.role];
41710
- return /* @__PURE__ */ jsxs(Box2, { flexDirection: "column", marginBottom: 1, children: [
41711
- /* @__PURE__ */ jsxs(Box2, { children: [
41712
- /* @__PURE__ */ jsxs(Text2, { bold: true, color: config2.color, children: [
41803
+ const baseContent = clipTop || clipBottom ? clipContent(renderedContent, 80, clipTop, clipBottom) : renderedContent;
41804
+ return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", marginBottom: 1, children: [
41805
+ /* @__PURE__ */ jsxs2(Box3, { children: [
41806
+ /* @__PURE__ */ jsxs2(Text3, { bold: true, color: config2.color, children: [
41713
41807
  config2.prefix,
41714
41808
  " ",
41715
41809
  config2.label
41716
41810
  ] }),
41717
- message.agent && /* @__PURE__ */ jsxs(Text2, { color: colors.textMuted, children: [
41811
+ message.agent && /* @__PURE__ */ jsxs2(Text3, { color: colors.textMuted, children: [
41718
41812
  " (",
41719
41813
  message.agent,
41720
41814
  ")"
41721
41815
  ] }),
41722
- showTimestamp && /* @__PURE__ */ jsxs(Text2, { color: colors.textMuted, children: [
41816
+ showTimestamp && /* @__PURE__ */ jsxs2(Text3, { color: colors.textMuted, children: [
41723
41817
  " ",
41724
41818
  formatTime(message.timestamp)
41725
- ] })
41819
+ ] }),
41820
+ isStreaming && /* @__PURE__ */ jsx8(Text3, { color: colors.textMuted, children: " streaming\u2026" })
41726
41821
  ] }),
41727
- message.role === "user" ? /* @__PURE__ */ jsx7(Box2, { marginLeft: 2, children: /* @__PURE__ */ jsx7(Text2, { color: colors.text, children: message.content }) }) : /* @__PURE__ */ jsx7(Box2, { marginLeft: 2, flexDirection: "column", children: /* @__PURE__ */ jsx7(Text2, { color: colors.text, children: message.content }) }),
41728
- message.toolCalls && message.toolCalls.length > 0 && /* @__PURE__ */ jsx7(Box2, { flexDirection: "column", marginTop: 1, children: message.toolCalls.map((toolCall) => /* @__PURE__ */ jsx7(ToolCallDisplay, { toolCall }, toolCall.id)) })
41822
+ /* @__PURE__ */ jsx8(Box3, { marginLeft: 2, flexDirection: "column", children: /* @__PURE__ */ jsx8(Text3, { color: colors.text, children: baseContent }) }),
41823
+ message.toolCalls && message.toolCalls.length > 0 && /* @__PURE__ */ jsx8(Box3, { flexDirection: "column", marginTop: 1, children: message.toolCalls.map((toolCall) => /* @__PURE__ */ jsx8(ToolCallDisplay, { toolCall }, toolCall.id)) })
41729
41824
  ] });
41730
41825
  }
41826
+ var Message;
41731
41827
  var init_message = __esm({
41732
41828
  "src/core/tui/components/message.tsx"() {
41733
41829
  "use strict";
41734
41830
  init_theme();
41831
+ Message = memo(MessageImpl, (prev, next) => {
41832
+ return prev.message === next.message && prev.showTimestamp === next.showTimestamp && prev.clipTop === next.clipTop && prev.clipBottom === next.clipBottom && prev.maxRenderedLines === next.maxRenderedLines;
41833
+ });
41834
+ }
41835
+ });
41836
+
41837
+ // src/core/tui/hooks/use-terminal-size.ts
41838
+ import { useEffect as useEffect3, useState as useState7 } from "react";
41839
+ import { useStdout } from "ink";
41840
+ function useTerminalSize() {
41841
+ const { stdout } = useStdout();
41842
+ const [size, setSize] = useState7(() => ({
41843
+ columns: stdout?.columns ?? 80,
41844
+ rows: stdout?.rows ?? 24
41845
+ }));
41846
+ useEffect3(() => {
41847
+ if (!stdout) return;
41848
+ const update = () => {
41849
+ setSize({
41850
+ columns: stdout.columns ?? 80,
41851
+ rows: stdout.rows ?? 24
41852
+ });
41853
+ };
41854
+ stdout.on("resize", update);
41855
+ update();
41856
+ return () => {
41857
+ stdout.off("resize", update);
41858
+ };
41859
+ }, [stdout]);
41860
+ return size;
41861
+ }
41862
+ var init_use_terminal_size = __esm({
41863
+ "src/core/tui/hooks/use-terminal-size.ts"() {
41864
+ "use strict";
41735
41865
  }
41736
41866
  });
41737
41867
 
41738
41868
  // src/core/tui/components/message-container.tsx
41739
- import { useRef, useEffect as useEffect2 } from "react";
41740
- import { Box as Box3, Text as Text3 } from "ink";
41741
- import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
41869
+ import { useEffect as useEffect4, useMemo, useRef as useRef2, useState as useState8 } from "react";
41870
+ import { Box as Box4, Text as Text4, useInput } from "ink";
41871
+ import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
41872
+ function messageLineCount(content, width, extras) {
41873
+ const innerWidth = Math.max(10, width - 4);
41874
+ const lines = content.split("\n");
41875
+ let rows = 0;
41876
+ for (const line of lines) {
41877
+ rows += Math.max(1, Math.ceil((line.length || 1) / innerWidth));
41878
+ }
41879
+ rows += 1;
41880
+ rows += extras.toolCalls ?? 0;
41881
+ return rows;
41882
+ }
41742
41883
  function MessageContainer() {
41743
41884
  const { colors } = useTheme();
41744
41885
  const { messages } = useSession();
41745
- const containerRef = useRef(null);
41746
- useEffect2(() => {
41747
- if (containerRef.current) {
41886
+ const { rows, columns } = useTerminalSize();
41887
+ const viewportHeight = Math.max(5, rows - 3);
41888
+ const messageHeights = useMemo(() => {
41889
+ return messages.map(
41890
+ (m) => messageLineCount(m.content, columns, {
41891
+ role: m.role,
41892
+ toolCalls: m.toolCalls?.length
41893
+ })
41894
+ );
41895
+ }, [messages, columns]);
41896
+ const totalLines = useMemo(
41897
+ () => messageHeights.reduce((a, b) => a + b, 0),
41898
+ [messageHeights]
41899
+ );
41900
+ const [scrollOffset, setScrollOffset] = useState8(0);
41901
+ const stickToBottom = useRef2(true);
41902
+ useEffect4(() => {
41903
+ if (stickToBottom.current) {
41904
+ setScrollOffset(0);
41905
+ }
41906
+ }, [totalLines]);
41907
+ useInput((input, key) => {
41908
+ if (key.pageUp) {
41909
+ stickToBottom.current = false;
41910
+ setScrollOffset((o) => Math.min(o + Math.floor(viewportHeight * 0.9), Math.max(0, totalLines - viewportHeight)));
41911
+ } else if (key.pageDown) {
41912
+ setScrollOffset((o) => {
41913
+ const next = Math.max(0, o - Math.floor(viewportHeight * 0.9));
41914
+ if (next === 0) stickToBottom.current = true;
41915
+ return next;
41916
+ });
41917
+ } else if (input === "g" && key.shift) {
41918
+ stickToBottom.current = true;
41919
+ setScrollOffset(0);
41920
+ } else if (input === "g" && !key.shift) {
41921
+ stickToBottom.current = false;
41922
+ setScrollOffset(Math.max(0, totalLines - viewportHeight));
41923
+ } else if (key.upArrow) {
41924
+ stickToBottom.current = false;
41925
+ setScrollOffset((o) => Math.min(o + 1, Math.max(0, totalLines - viewportHeight)));
41926
+ } else if (key.downArrow) {
41927
+ setScrollOffset((o) => {
41928
+ const next = Math.max(0, o - 1);
41929
+ if (next === 0) stickToBottom.current = true;
41930
+ return next;
41931
+ });
41748
41932
  }
41749
- }, [messages.length]);
41933
+ });
41750
41934
  if (messages.length === 0) {
41751
- return /* @__PURE__ */ jsxs2(
41752
- Box3,
41753
- {
41754
- flexDirection: "column",
41755
- justifyContent: "center",
41756
- alignItems: "center",
41757
- flexGrow: 1,
41758
- children: [
41759
- /* @__PURE__ */ jsx8(Text3, { bold: true, color: colors.primary, children: "BraveCode AI" }),
41760
- /* @__PURE__ */ jsx8(Text3, { color: colors.textMuted, children: "Agentic coding assistant with free model access" }),
41761
- /* @__PURE__ */ jsx8(Text3, { color: colors.textMuted, children: " " }),
41762
- /* @__PURE__ */ jsx8(Text3, { color: colors.textMuted, children: "Type a message to start. Use /help for commands." })
41763
- ]
41764
- }
41765
- );
41935
+ return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", justifyContent: "center", alignItems: "center", flexGrow: 1, children: [
41936
+ /* @__PURE__ */ jsx9(Text4, { bold: true, color: colors.primary, children: "BraveCode AI" }),
41937
+ /* @__PURE__ */ jsx9(Text4, { color: colors.textMuted, children: "Agentic coding assistant with free model access" }),
41938
+ /* @__PURE__ */ jsx9(Text4, { color: colors.textMuted, children: " " }),
41939
+ /* @__PURE__ */ jsx9(Text4, { color: colors.textMuted, children: "Type a message to start. Use /help for commands." })
41940
+ ] });
41766
41941
  }
41767
- return /* @__PURE__ */ jsx8(
41768
- Box3,
41769
- {
41770
- ref: containerRef,
41771
- flexDirection: "column",
41772
- flexGrow: 1,
41773
- overflow: "hidden",
41774
- children: messages.map((message) => /* @__PURE__ */ jsx8(
41942
+ const windowTop = totalLines - viewportHeight - scrollOffset;
41943
+ const windowBottom = totalLines - scrollOffset;
41944
+ let cursor = 0;
41945
+ const visible = [];
41946
+ for (let i = 0; i < messages.length; i++) {
41947
+ const h = messageHeights[i];
41948
+ const msgTop = cursor;
41949
+ const msgBottom = cursor + h;
41950
+ if (msgBottom > windowTop && msgTop < windowBottom) {
41951
+ const overlapTop = Math.max(0, windowTop - msgTop);
41952
+ const overlapBottom = Math.min(h, windowBottom - msgTop);
41953
+ visible.push({ idx: i, skipTop: overlapTop, skipBottom: h - overlapBottom });
41954
+ }
41955
+ cursor += h;
41956
+ if (msgBottom >= windowBottom) break;
41957
+ }
41958
+ const STREAMING_LINE_CAP = Math.max(10, Math.floor(viewportHeight * 0.6));
41959
+ const lastIndex = messages.length - 1;
41960
+ return /* @__PURE__ */ jsxs3(Box4, { ref: () => {
41961
+ }, flexDirection: "column", flexGrow: 1, overflow: "hidden", children: [
41962
+ visible.map(({ idx, skipTop, skipBottom }) => {
41963
+ const m = messages[idx];
41964
+ if (m.role === "user") {
41965
+ return /* @__PURE__ */ jsx9(Message, { message: m }, m.id);
41966
+ }
41967
+ const isStreaming = idx === lastIndex && m.content !== "";
41968
+ return /* @__PURE__ */ jsx9(
41775
41969
  Message,
41776
41970
  {
41777
- message,
41778
- showTimestamp: true
41971
+ message: m,
41972
+ showTimestamp: true,
41973
+ clipTop: skipTop,
41974
+ clipBottom: skipBottom,
41975
+ maxRenderedLines: isStreaming ? STREAMING_LINE_CAP : void 0
41779
41976
  },
41780
- message.id
41781
- ))
41782
- }
41783
- );
41977
+ m.id
41978
+ );
41979
+ }),
41980
+ !stickToBottom.current && /* @__PURE__ */ jsx9(Box4, { children: /* @__PURE__ */ jsx9(Text4, { color: colors.textMuted, children: "\u2191\u2193 scroll \xB7 pgup/pgdn \xB7 g/G top/bottom" }) })
41981
+ ] });
41784
41982
  }
41785
41983
  var init_message_container = __esm({
41786
41984
  "src/core/tui/components/message-container.tsx"() {
@@ -41788,22 +41986,23 @@ var init_message_container = __esm({
41788
41986
  init_theme();
41789
41987
  init_session();
41790
41988
  init_message();
41989
+ init_use_terminal_size();
41791
41990
  }
41792
41991
  });
41793
41992
 
41794
41993
  // src/core/tui/components/input-editor.tsx
41795
- import { useState as useState6 } from "react";
41796
- import { Box as Box4, Text as Text4, useInput, useApp } from "ink";
41797
- import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
41994
+ import { useState as useState9 } from "react";
41995
+ import { Box as Box5, Text as Text5, useInput as useInput2, useApp } from "ink";
41996
+ import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
41798
41997
  function InputEditor({ onSubmit, placeholder = "Type a message...", disabled = false }) {
41799
41998
  const { colors } = useTheme();
41800
41999
  const { isRunning } = useAgent();
41801
42000
  const { exit } = useApp();
41802
- const [value, setValue] = useState6("");
41803
- const [cursorPos, setCursorPos] = useState6(0);
41804
- const [history, setHistory] = useState6([]);
41805
- const [historyIndex, setHistoryIndex] = useState6(-1);
41806
- useInput((input, key) => {
42001
+ const [value, setValue] = useState9("");
42002
+ const [cursorPos, setCursorPos] = useState9(0);
42003
+ const [history, setHistory] = useState9([]);
42004
+ const [historyIndex, setHistoryIndex] = useState9(-1);
42005
+ useInput2((input, key) => {
41807
42006
  if (disabled || isRunning) return;
41808
42007
  if (key.return) {
41809
42008
  if (key.shift) {
@@ -41918,22 +42117,22 @@ function InputEditor({ onSubmit, placeholder = "Type a message...", disabled = f
41918
42117
  });
41919
42118
  const renderInput = () => {
41920
42119
  if (disabled || isRunning) {
41921
- return /* @__PURE__ */ jsx9(Box4, { children: /* @__PURE__ */ jsx9(Text4, { color: colors.textMuted, children: isRunning ? "Thinking..." : "Disabled" }) });
42120
+ return /* @__PURE__ */ jsx10(Box5, { children: /* @__PURE__ */ jsx10(Text5, { color: colors.textMuted, children: isRunning ? "Thinking..." : "Disabled" }) });
41922
42121
  }
41923
42122
  if (!value) {
41924
- return /* @__PURE__ */ jsx9(Box4, { children: /* @__PURE__ */ jsx9(Text4, { color: colors.textMuted, children: placeholder }) });
42123
+ return /* @__PURE__ */ jsx10(Box5, { children: /* @__PURE__ */ jsx10(Text5, { color: colors.textMuted, children: placeholder }) });
41925
42124
  }
41926
42125
  const before = value.slice(0, cursorPos);
41927
42126
  const cursor = value[cursorPos] || " ";
41928
42127
  const after = value.slice(cursorPos + 1);
41929
- return /* @__PURE__ */ jsxs3(Box4, { children: [
41930
- /* @__PURE__ */ jsx9(Text4, { children: before }),
41931
- /* @__PURE__ */ jsx9(Text4, { inverse: true, children: cursor }),
41932
- /* @__PURE__ */ jsx9(Text4, { children: after })
42128
+ return /* @__PURE__ */ jsxs4(Box5, { children: [
42129
+ /* @__PURE__ */ jsx10(Text5, { children: before }),
42130
+ /* @__PURE__ */ jsx10(Text5, { inverse: true, children: cursor }),
42131
+ /* @__PURE__ */ jsx10(Text5, { children: after })
41933
42132
  ] });
41934
42133
  };
41935
- return /* @__PURE__ */ jsxs3(Box4, { children: [
41936
- /* @__PURE__ */ jsx9(Text4, { bold: true, color: colors.primary, children: "\u203A " }),
42134
+ return /* @__PURE__ */ jsxs4(Box5, { children: [
42135
+ /* @__PURE__ */ jsx10(Text5, { bold: true, color: colors.primary, children: "\u203A " }),
41937
42136
  renderInput()
41938
42137
  ] });
41939
42138
  }
@@ -41945,56 +42144,91 @@ var init_input_editor = __esm({
41945
42144
  }
41946
42145
  });
41947
42146
 
42147
+ // src/core/tui/components/spinner.tsx
42148
+ import { useEffect as useEffect6, useState as useState10 } from "react";
42149
+ import { Text as Text6 } from "ink";
42150
+ import { jsxs as jsxs5 } from "react/jsx-runtime";
42151
+ function Spinner({ color, suffix = "" }) {
42152
+ const [frame, setFrame] = useState10(0);
42153
+ useEffect6(() => {
42154
+ const id = setInterval(() => {
42155
+ setFrame((f) => (f + 1) % FRAMES.length);
42156
+ }, TICK_MS);
42157
+ return () => clearInterval(id);
42158
+ }, []);
42159
+ return /* @__PURE__ */ jsxs5(Text6, { color, children: [
42160
+ FRAMES[frame],
42161
+ suffix
42162
+ ] });
42163
+ }
42164
+ var FRAMES, TICK_MS;
42165
+ var init_spinner = __esm({
42166
+ "src/core/tui/components/spinner.tsx"() {
42167
+ "use strict";
42168
+ FRAMES = ["\xB7\xB7\xB7\xB7\xB7\xB7\u25A0", "\xB7\xB7\xB7\xB7\xB7\u25A0\xB7", "\xB7\xB7\xB7\xB7\u25A0\xB7\xB7", "\xB7\xB7\xB7\u25A0\xB7\xB7\xB7", "\xB7\xB7\u25A0\xB7\xB7\xB7\xB7", "\xB7\u25A0\xB7\xB7\xB7\xB7\xB7", "\u25A0\xB7\xB7\xB7\xB7\xB7\xB7", "\xB7\u25A0\xB7\xB7\xB7\xB7\xB7", "\xB7\xB7\u25A0\xB7\xB7\xB7\xB7", "\xB7\xB7\xB7\u25A0\xB7\xB7\xB7", "\xB7\xB7\xB7\xB7\u25A0\xB7\xB7", "\xB7\xB7\xB7\xB7\xB7\u25A0\xB7"];
42169
+ TICK_MS = 100;
42170
+ }
42171
+ });
42172
+
41948
42173
  // src/core/tui/components/status-bar.tsx
41949
42174
  import "react";
41950
- import { Box as Box5, Text as Text5 } from "ink";
41951
- import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
42175
+ import { Box as Box6, Text as Text7 } from "ink";
42176
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
41952
42177
  function StatusBar() {
41953
42178
  const { colors } = useTheme();
41954
- const { currentAgent, isRunning } = useAgent();
41955
- const width = process.stdout.columns || 80;
41956
- const cwd = process.cwd().replace(process.env.HOME || "", "~");
41957
- return /* @__PURE__ */ jsxs4(Box5, { justifyContent: "space-between", width, children: [
41958
- /* @__PURE__ */ jsxs4(Box5, { gap: 2, children: [
41959
- /* @__PURE__ */ jsx10(Text5, { color: colors.textMuted, children: cwd }),
41960
- /* @__PURE__ */ jsx10(Text5, { color: colors.textMuted, children: "\u25CF 1 MCP" }),
41961
- /* @__PURE__ */ jsx10(Text5, { color: colors.textMuted, children: "/status" })
41962
- ] }),
41963
- /* @__PURE__ */ jsx10(Text5, { color: colors.textMuted, children: APP_VERSION })
41964
- ] });
42179
+ const { isRunning } = useAgent();
42180
+ return /* @__PURE__ */ jsxs6(
42181
+ Box6,
42182
+ {
42183
+ flexDirection: "row",
42184
+ justifyContent: "space-between",
42185
+ width: "100%",
42186
+ paddingX: 1,
42187
+ children: [
42188
+ /* @__PURE__ */ jsx11(Box6, { children: isRunning ? /* @__PURE__ */ jsx11(Spinner, { color: colors.textMuted, suffix: " esc interrupt" }) : /* @__PURE__ */ jsx11(Text7, { color: colors.textMuted, children: " " }) }),
42189
+ /* @__PURE__ */ jsxs6(Box6, { gap: 2, children: [
42190
+ /* @__PURE__ */ jsx11(Text7, { color: colors.textMuted, children: "tab agents" }),
42191
+ /* @__PURE__ */ jsx11(Text7, { color: colors.textMuted, children: "ctrl+p commands" }),
42192
+ /* @__PURE__ */ jsx11(Text7, { color: colors.textMuted, children: "\xB7" }),
42193
+ /* @__PURE__ */ jsx11(Text7, { color: colors.textMuted, children: APP_VERSION })
42194
+ ] })
42195
+ ]
42196
+ }
42197
+ );
41965
42198
  }
41966
42199
  var init_status_bar = __esm({
41967
42200
  "src/core/tui/components/status-bar.tsx"() {
41968
42201
  "use strict";
41969
42202
  init_theme();
41970
42203
  init_agent2();
42204
+ init_spinner();
41971
42205
  init_version();
41972
42206
  }
41973
42207
  });
41974
42208
 
41975
42209
  // src/core/tui/components/toast.tsx
41976
42210
  import "react";
41977
- import { Box as Box6, Text as Text6 } from "ink";
41978
- import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
42211
+ import { Box as Box7, Text as Text8 } from "ink";
42212
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
41979
42213
  function ToastContainer() {
41980
42214
  const { colors } = useTheme();
41981
42215
  const { toasts } = useToast();
41982
42216
  if (toasts.length === 0) {
41983
42217
  return null;
41984
42218
  }
41985
- return /* @__PURE__ */ jsx11(Box6, { flexDirection: "column", position: "absolute", bottom: 2, right: 2, children: toasts.map((toast) => /* @__PURE__ */ jsxs5(
41986
- Box6,
42219
+ return /* @__PURE__ */ jsx12(Box7, { flexDirection: "column", position: "absolute", bottom: 2, right: 2, children: toasts.map((toast) => /* @__PURE__ */ jsxs7(
42220
+ Box7,
41987
42221
  {
41988
42222
  borderStyle: "round",
41989
42223
  borderColor: colors[variantColors[toast.variant]],
41990
42224
  paddingX: 1,
41991
42225
  marginBottom: 1,
41992
42226
  children: [
41993
- /* @__PURE__ */ jsxs5(Text6, { color: colors[variantColors[toast.variant]], children: [
42227
+ /* @__PURE__ */ jsxs7(Text8, { color: colors[variantColors[toast.variant]], children: [
41994
42228
  variantIcons[toast.variant],
41995
42229
  " "
41996
42230
  ] }),
41997
- /* @__PURE__ */ jsx11(Text6, { children: toast.message })
42231
+ /* @__PURE__ */ jsx12(Text8, { children: toast.message })
41998
42232
  ]
41999
42233
  },
42000
42234
  toast.id
@@ -42022,16 +42256,16 @@ var init_toast2 = __esm({
42022
42256
  });
42023
42257
 
42024
42258
  // src/core/tui/components/model-selector.tsx
42025
- import { useState as useState7 } from "react";
42026
- import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
42027
- import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
42259
+ import { useState as useState11 } from "react";
42260
+ import { Box as Box8, Text as Text9, useInput as useInput3 } from "ink";
42261
+ import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
42028
42262
  function ModelSelector() {
42029
42263
  const { colors } = useTheme();
42030
42264
  const { currentModel, setModel } = useAgent();
42031
42265
  const { closeDialog } = useDialog();
42032
42266
  const toast = useToast();
42033
- const [selectedIndex, setSelectedIndex] = useState7(0);
42034
- const [filter3, setFilter] = useState7("");
42267
+ const [selectedIndex, setSelectedIndex] = useState11(0);
42268
+ const [filter3, setFilter] = useState11("");
42035
42269
  const models = models_default.models.map((m) => ({
42036
42270
  id: m.id,
42037
42271
  name: m.name,
@@ -42041,7 +42275,7 @@ function ModelSelector() {
42041
42275
  const filteredModels = models.filter(
42042
42276
  (m) => m.tags.includes("free") && (m.name.toLowerCase().includes(filter3.toLowerCase()) || m.id.toLowerCase().includes(filter3.toLowerCase()))
42043
42277
  );
42044
- useInput2((input, key) => {
42278
+ useInput3((input, key) => {
42045
42279
  if (key.escape) {
42046
42280
  closeDialog();
42047
42281
  return;
@@ -42075,9 +42309,9 @@ function ModelSelector() {
42075
42309
  const renderModel = (model, index) => {
42076
42310
  const isSelected = model.id === currentModel;
42077
42311
  const isHighlighted = index === selectedIndex;
42078
- return /* @__PURE__ */ jsxs6(Box7, { children: [
42079
- /* @__PURE__ */ jsxs6(
42080
- Text7,
42312
+ return /* @__PURE__ */ jsxs8(Box8, { children: [
42313
+ /* @__PURE__ */ jsxs8(
42314
+ Text9,
42081
42315
  {
42082
42316
  bold: isHighlighted,
42083
42317
  color: isSelected ? colors.primary : isHighlighted ? colors.accent : colors.text,
@@ -42087,16 +42321,16 @@ function ModelSelector() {
42087
42321
  ]
42088
42322
  }
42089
42323
  ),
42090
- /* @__PURE__ */ jsxs6(Text7, { color: colors.textMuted, children: [
42324
+ /* @__PURE__ */ jsxs8(Text9, { color: colors.textMuted, children: [
42091
42325
  " (",
42092
42326
  model.provider,
42093
42327
  ")"
42094
42328
  ] }),
42095
- model.tags.includes("free") && /* @__PURE__ */ jsx12(Text7, { color: colors.success, children: " free" })
42329
+ model.tags.includes("free") && /* @__PURE__ */ jsx13(Text9, { color: colors.success, children: " free" })
42096
42330
  ] }, model.id);
42097
42331
  };
42098
- return /* @__PURE__ */ jsxs6(
42099
- Box7,
42332
+ return /* @__PURE__ */ jsxs8(
42333
+ Box8,
42100
42334
  {
42101
42335
  flexDirection: "column",
42102
42336
  borderStyle: "double",
@@ -42106,17 +42340,17 @@ function ModelSelector() {
42106
42340
  top: "50%",
42107
42341
  left: "50%",
42108
42342
  children: [
42109
- /* @__PURE__ */ jsx12(Box7, { paddingX: 1, children: /* @__PURE__ */ jsx12(Text7, { bold: true, color: colors.primary, children: "Select Model" }) }),
42110
- /* @__PURE__ */ jsxs6(Box7, { paddingX: 1, children: [
42111
- /* @__PURE__ */ jsx12(Text7, { color: colors.textMuted, children: "Search: " }),
42112
- /* @__PURE__ */ jsx12(Text7, { children: filter3 }),
42113
- /* @__PURE__ */ jsx12(Text7, { inverse: true, children: " " })
42343
+ /* @__PURE__ */ jsx13(Box8, { paddingX: 1, children: /* @__PURE__ */ jsx13(Text9, { bold: true, color: colors.primary, children: "Select Model" }) }),
42344
+ /* @__PURE__ */ jsxs8(Box8, { paddingX: 1, children: [
42345
+ /* @__PURE__ */ jsx13(Text9, { color: colors.textMuted, children: "Search: " }),
42346
+ /* @__PURE__ */ jsx13(Text9, { children: filter3 }),
42347
+ /* @__PURE__ */ jsx13(Text9, { inverse: true, children: " " })
42114
42348
  ] }),
42115
- /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", paddingX: 1, maxHeight: 15, children: [
42116
- /* @__PURE__ */ jsx12(Text7, { color: colors.textMuted, children: "Available Models (free):" }),
42349
+ /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 1, maxHeight: 15, children: [
42350
+ /* @__PURE__ */ jsx13(Text9, { color: colors.textMuted, children: "Available Models (free):" }),
42117
42351
  filteredModels.map((model, index) => renderModel(model, index))
42118
42352
  ] }),
42119
- /* @__PURE__ */ jsx12(Box7, { paddingX: 1, children: /* @__PURE__ */ jsx12(Text7, { color: colors.textMuted, children: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc close" }) })
42353
+ /* @__PURE__ */ jsx13(Box8, { paddingX: 1, children: /* @__PURE__ */ jsx13(Text9, { color: colors.textMuted, children: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc close" }) })
42120
42354
  ]
42121
42355
  }
42122
42356
  );
@@ -42133,13 +42367,13 @@ var init_model_selector = __esm({
42133
42367
  });
42134
42368
 
42135
42369
  // src/core/tui/hooks/use-agent.ts
42136
- import { useCallback as useCallback7, useRef as useRef3 } from "react";
42370
+ import { useCallback as useCallback7, useRef as useRef4 } from "react";
42137
42371
  function useAgent2() {
42138
42372
  const { addMessage, updateMessage, addToolCall, updateToolCall } = useSession();
42139
42373
  const { currentAgent, currentModel, setRunning } = useAgent();
42140
42374
  const toast = useToast();
42141
- const agentRef = useRef3(null);
42142
- const abortRef = useRef3(null);
42375
+ const agentRef = useRef4(null);
42376
+ const abortRef = useRef4(null);
42143
42377
  const sendMessage = useCallback7(async (content) => {
42144
42378
  const userMessage = addMessage({
42145
42379
  role: "user",
@@ -42228,9 +42462,9 @@ var init_use_agent = __esm({
42228
42462
  });
42229
42463
 
42230
42464
  // src/core/tui/app.tsx
42231
- import "react";
42232
- import { Box as Box8, Text as Text8, useInput as useInput3, useApp as useApp2 } from "ink";
42233
- import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
42465
+ import React15 from "react";
42466
+ import { Box as Box9, Text as Text10, useInput as useInput4, useApp as useApp2 } from "ink";
42467
+ import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
42234
42468
  function App() {
42235
42469
  const { colors } = useTheme();
42236
42470
  const { messages } = useSession();
@@ -42238,11 +42472,18 @@ function App() {
42238
42472
  const { isOpen, openDialog, closeDialog, dialog } = useDialog();
42239
42473
  const { sendMessage, cancelCurrent } = useAgent2();
42240
42474
  const { exit } = useApp2();
42241
- useInput3((input, key) => {
42475
+ const { columns } = useTerminalSize();
42476
+ const [sidebarForced, setSidebarForced] = React15.useState(false);
42477
+ const sidebarVisible = sidebarForced || columns >= SIDEBAR_BREAKPOINT;
42478
+ useInput4((input, key) => {
42242
42479
  if (key.ctrl && input === "p") {
42243
42480
  openDialog("model");
42244
42481
  return;
42245
42482
  }
42483
+ if (key.ctrl && input === "b") {
42484
+ setSidebarForced((v) => !v);
42485
+ return;
42486
+ }
42246
42487
  if (key.tab) {
42247
42488
  const agents = ["build", "plan", "debug", "testing", "security"];
42248
42489
  const currentIndex = agents.indexOf(currentAgent.id);
@@ -42258,8 +42499,12 @@ function App() {
42258
42499
  }
42259
42500
  return;
42260
42501
  }
42261
- if (key.escape && isOpen) {
42262
- closeDialog();
42502
+ if (key.escape) {
42503
+ if (isRunning) {
42504
+ cancelCurrent();
42505
+ } else if (isOpen) {
42506
+ closeDialog();
42507
+ }
42263
42508
  return;
42264
42509
  }
42265
42510
  });
@@ -42292,82 +42537,121 @@ function App() {
42292
42537
  await sendMessage(value);
42293
42538
  };
42294
42539
  const hasMessages = messages.length > 0;
42295
- const cwd = process.cwd().replace(process.env.HOME || "", "~");
42296
- return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "row", width: "100%", height: "100%", children: [
42297
- /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", flexGrow: 1, backgroundColor: colors.background, children: [
42298
- /* @__PURE__ */ jsx13(Box8, { flexDirection: "column", flexGrow: 1, justifyContent: hasMessages ? "flex-start" : "center", children: hasMessages ? /* @__PURE__ */ jsx13(MessageContainer, {}) : (
42299
- /* Welcome screen - centered vertically */
42300
- /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", alignItems: "center", gap: 1, children: [
42301
- /* @__PURE__ */ jsx13(Logo, {}),
42302
- /* @__PURE__ */ jsx13(
42303
- Box8,
42304
- {
42305
- flexDirection: "column",
42306
- width: 60,
42307
- borderStyle: "round",
42308
- borderColor: colors.border,
42309
- paddingX: 2,
42310
- paddingY: 1,
42311
- children: /* @__PURE__ */ jsx13(
42312
- InputEditor,
42313
- {
42314
- onSubmit: handleSubmit,
42315
- placeholder: 'Ask anything... "What is the tech stack of this project?"'
42316
- }
42317
- )
42318
- }
42319
- ),
42320
- /* @__PURE__ */ jsxs7(Box8, { gap: 1, children: [
42321
- /* @__PURE__ */ jsx13(Text8, { bold: true, color: colors.primary, children: currentAgent.name }),
42322
- /* @__PURE__ */ jsx13(Text8, { color: colors.textMuted, children: "\xB7" }),
42323
- /* @__PURE__ */ jsx13(Text8, { color: colors.textSecondary, children: currentModel })
42324
- ] }),
42325
- /* @__PURE__ */ jsxs7(Box8, { gap: 2, children: [
42326
- /* @__PURE__ */ jsx13(Text8, { color: colors.textMuted, children: "tab agents" }),
42327
- /* @__PURE__ */ jsx13(Text8, { color: colors.textMuted, children: "ctrl+p commands" })
42540
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", width: "100%", height: "100%", children: [
42541
+ /* @__PURE__ */ jsx14(HeaderBar, { title: APP_NAME, subtitle: APP_NAME.toLowerCase() }),
42542
+ /* @__PURE__ */ jsxs9(Box9, { flexDirection: "row", flexGrow: 1, width: "100%", children: [
42543
+ /* @__PURE__ */ jsx14(Box9, { flexDirection: "column", flexGrow: 1, backgroundColor: colors.background, children: /* @__PURE__ */ jsx14(
42544
+ Box9,
42545
+ {
42546
+ flexDirection: "column",
42547
+ flexGrow: 1,
42548
+ justifyContent: hasMessages ? "flex-start" : "center",
42549
+ children: hasMessages ? /* @__PURE__ */ jsx14(MessageContainer, {}) : /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", alignItems: "center", gap: 1, children: [
42550
+ /* @__PURE__ */ jsx14(Logo, {}),
42551
+ /* @__PURE__ */ jsx14(
42552
+ Box9,
42553
+ {
42554
+ flexDirection: "column",
42555
+ width: 60,
42556
+ borderStyle: "round",
42557
+ borderColor: colors.border,
42558
+ paddingX: 2,
42559
+ paddingY: 1,
42560
+ children: /* @__PURE__ */ jsx14(
42561
+ InputEditor,
42562
+ {
42563
+ onSubmit: handleSubmit,
42564
+ placeholder: 'Ask anything... "Fix broken tests"'
42565
+ }
42566
+ )
42567
+ }
42568
+ ),
42569
+ /* @__PURE__ */ jsxs9(Box9, { gap: 1, children: [
42570
+ /* @__PURE__ */ jsx14(Text10, { bold: true, color: colors.primary, children: currentAgent.name }),
42571
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: "\xB7" }),
42572
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textSecondary, children: currentModel })
42573
+ ] }),
42574
+ /* @__PURE__ */ jsxs9(Box9, { gap: 2, children: [
42575
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: "tab agents" }),
42576
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: "ctrl+p commands" })
42577
+ ] })
42328
42578
  ] })
42329
- ] })
42579
+ }
42330
42580
  ) }),
42331
- /* @__PURE__ */ jsx13(StatusBar, {})
42332
- ] }),
42333
- /* @__PURE__ */ jsxs7(
42334
- Box8,
42335
- {
42336
- flexDirection: "column",
42337
- width: 35,
42338
- borderStyle: "single",
42339
- borderColor: colors.border,
42340
- paddingLeft: 1,
42341
- children: [
42342
- /* @__PURE__ */ jsx13(Text8, { bold: true, color: colors.textSecondary, children: "New session" }),
42343
- /* @__PURE__ */ jsxs7(Text8, { color: colors.textMuted, children: [
42344
- (/* @__PURE__ */ new Date()).toISOString().split(".")[0],
42345
- "Z"
42346
- ] }),
42347
- /* @__PURE__ */ jsx13(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text8, { bold: true, color: colors.textSecondary, children: "Context" }) }),
42348
- /* @__PURE__ */ jsx13(Text8, { color: colors.textMuted, children: "0 tokens" }),
42349
- /* @__PURE__ */ jsx13(Text8, { color: colors.textMuted, children: "0% used" }),
42350
- /* @__PURE__ */ jsx13(Text8, { color: colors.textMuted, children: "$0.00 spent" }),
42351
- /* @__PURE__ */ jsx13(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text8, { bold: true, color: colors.textSecondary, children: "MCP" }) }),
42352
- /* @__PURE__ */ jsx13(Text8, { color: colors.textMuted, children: "\u25CF railway Connected" }),
42353
- /* @__PURE__ */ jsx13(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text8, { bold: true, color: colors.textSecondary, children: "LSP" }) }),
42354
- /* @__PURE__ */ jsx13(Text8, { color: colors.textMuted, children: "LSPs are disabled" }),
42355
- /* @__PURE__ */ jsx13(Box8, { flexGrow: 1 }),
42356
- /* @__PURE__ */ jsx13(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text8, { color: colors.textMuted, children: cwd }) }),
42357
- /* @__PURE__ */ jsxs7(Box8, { children: [
42358
- /* @__PURE__ */ jsx13(Text8, { color: colors.success, children: "\u25CF" }),
42359
- /* @__PURE__ */ jsxs7(Text8, { color: colors.textMuted, children: [
42360
- " ",
42361
- APP_VERSION
42581
+ sidebarVisible && /* @__PURE__ */ jsxs9(
42582
+ Box9,
42583
+ {
42584
+ flexDirection: "column",
42585
+ width: 35,
42586
+ borderStyle: "single",
42587
+ borderColor: colors.border,
42588
+ paddingLeft: 1,
42589
+ children: [
42590
+ /* @__PURE__ */ jsx14(Text10, { bold: true, color: colors.text, children: "New session" }),
42591
+ /* @__PURE__ */ jsxs9(Text10, { color: colors.textMuted, children: [
42592
+ (/* @__PURE__ */ new Date()).toISOString().split(".")[0],
42593
+ "Z"
42594
+ ] }),
42595
+ /* @__PURE__ */ jsx14(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text10, { bold: true, color: colors.text, children: "Context" }) }),
42596
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: "0 tokens" }),
42597
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: "0% used" }),
42598
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: "$0.00 spent" }),
42599
+ /* @__PURE__ */ jsx14(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text10, { bold: true, color: colors.text, children: "MCP" }) }),
42600
+ /* @__PURE__ */ jsxs9(Box9, { children: [
42601
+ /* @__PURE__ */ jsx14(Text10, { color: colors.success, children: "\u25CF" }),
42602
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textSecondary, children: " railway " }),
42603
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: "Connected" })
42604
+ ] }),
42605
+ /* @__PURE__ */ jsx14(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text10, { bold: true, color: colors.text, children: "LSP" }) }),
42606
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: "LSPs are disabled" }),
42607
+ /* @__PURE__ */ jsx14(Box9, { flexGrow: 1 }),
42608
+ /* @__PURE__ */ jsx14(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: process.cwd().replace(process.env.HOME || "", "~") }) }),
42609
+ /* @__PURE__ */ jsxs9(Box9, { children: [
42610
+ /* @__PURE__ */ jsxs9(Text10, { bold: true, color: colors.text, children: [
42611
+ "\u25CF ",
42612
+ APP_NAME,
42613
+ " "
42614
+ ] }),
42615
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: APP_VERSION })
42362
42616
  ] })
42363
- ] })
42364
- ]
42365
- }
42366
- ),
42367
- isOpen && dialog.type === "model" && /* @__PURE__ */ jsx13(ModelSelector, {}),
42368
- /* @__PURE__ */ jsx13(ToastContainer, {})
42617
+ ]
42618
+ }
42619
+ ),
42620
+ !sidebarVisible && /* @__PURE__ */ jsxs9(
42621
+ Box9,
42622
+ {
42623
+ flexDirection: "column",
42624
+ width: 28,
42625
+ borderStyle: "single",
42626
+ borderColor: colors.border,
42627
+ paddingLeft: 1,
42628
+ children: [
42629
+ /* @__PURE__ */ jsx14(Text10, { bold: true, color: colors.text, children: "Info" }),
42630
+ /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
42631
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: "agent " }),
42632
+ /* @__PURE__ */ jsx14(Text10, { color: colors.primary, children: currentAgent.name })
42633
+ ] }),
42634
+ /* @__PURE__ */ jsxs9(Text10, { color: colors.textMuted, children: [
42635
+ "model ",
42636
+ currentModel
42637
+ ] }),
42638
+ /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
42639
+ /* @__PURE__ */ jsx14(Text10, { color: colors.success, children: "\u25CF" }),
42640
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: " mcp connected" })
42641
+ ] }),
42642
+ /* @__PURE__ */ jsx14(Box9, { flexGrow: 1 }),
42643
+ /* @__PURE__ */ jsx14(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: APP_VERSION }) }),
42644
+ /* @__PURE__ */ jsx14(Text10, { color: colors.textMuted, children: "ctrl+b sidebar" })
42645
+ ]
42646
+ }
42647
+ )
42648
+ ] }),
42649
+ /* @__PURE__ */ jsx14(StatusBar, {}),
42650
+ isOpen && dialog.type === "model" && /* @__PURE__ */ jsx14(ModelSelector, {}),
42651
+ /* @__PURE__ */ jsx14(ToastContainer, {})
42369
42652
  ] });
42370
42653
  }
42654
+ var SIDEBAR_BREAKPOINT;
42371
42655
  var init_app = __esm({
42372
42656
  "src/core/tui/app.tsx"() {
42373
42657
  "use strict";
@@ -42376,13 +42660,16 @@ var init_app = __esm({
42376
42660
  init_agent2();
42377
42661
  init_dialog();
42378
42662
  init_logo();
42663
+ init_header_bar();
42379
42664
  init_message_container();
42380
42665
  init_input_editor();
42381
42666
  init_status_bar();
42382
42667
  init_toast2();
42383
42668
  init_model_selector();
42384
42669
  init_use_agent();
42670
+ init_use_terminal_size();
42385
42671
  init_version();
42672
+ SIDEBAR_BREAKPOINT = 90;
42386
42673
  }
42387
42674
  });
42388
42675
 
@@ -42393,7 +42680,7 @@ __export(tui_exports, {
42393
42680
  });
42394
42681
  import "react";
42395
42682
  import { render } from "ink";
42396
- import { jsx as jsx14 } from "react/jsx-runtime";
42683
+ import { jsx as jsx15 } from "react/jsx-runtime";
42397
42684
  var TUILauncher;
42398
42685
  var init_tui = __esm({
42399
42686
  "src/core/tui/index.tsx"() {
@@ -42412,12 +42699,12 @@ var init_tui = __esm({
42412
42699
  async start() {
42413
42700
  process.stdout.write("\x1B[2J\x1B[H");
42414
42701
  const { waitUntilExit } = render(
42415
- /* @__PURE__ */ jsx14(ThemeProvider, { children: /* @__PURE__ */ jsx14(SessionProvider, { children: /* @__PURE__ */ jsx14(
42702
+ /* @__PURE__ */ jsx15(ThemeProvider, { children: /* @__PURE__ */ jsx15(SessionProvider, { children: /* @__PURE__ */ jsx15(
42416
42703
  AgentProvider,
42417
42704
  {
42418
42705
  initialAgent: this.options.agent || "build",
42419
42706
  initialModel: this.options.model,
42420
- children: /* @__PURE__ */ jsx14(DialogProvider, { children: /* @__PURE__ */ jsx14(ToastProvider, { children: /* @__PURE__ */ jsx14(App, {}) }) })
42707
+ children: /* @__PURE__ */ jsx15(DialogProvider, { children: /* @__PURE__ */ jsx15(ToastProvider, { children: /* @__PURE__ */ jsx15(App, {}) }) })
42421
42708
  }
42422
42709
  ) }) }),
42423
42710
  {