bravecode-cli 0.1.11 → 0.1.13

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
@@ -38047,7 +38047,7 @@ var APP_VERSION;
38047
38047
  var init_version = __esm({
38048
38048
  "src/version.ts"() {
38049
38049
  "use strict";
38050
- APP_VERSION = "0.1.11";
38050
+ APP_VERSION = "0.1.13";
38051
38051
  }
38052
38052
  });
38053
38053
 
@@ -41577,55 +41577,36 @@ var init_toast = __esm({
41577
41577
  }
41578
41578
  });
41579
41579
 
41580
- // src/core/tui/components/header-bar.tsx
41580
+ // src/core/tui/components/logo.tsx
41581
41581
  import "react";
41582
41582
  import { Box, Text } from "ink";
41583
- import { jsx as jsx6, jsxs } from "react/jsx-runtime";
41584
- function HeaderBar() {
41585
- const { colors } = useTheme();
41586
- const { currentAgent, currentModel, isRunning } = useAgent();
41587
- const { session } = useSession();
41588
- const width = process.stdout.columns || 80;
41589
- const separatorWidth = width - 2;
41590
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
41591
- /* @__PURE__ */ jsx6(Text, { color: colors.border, children: "\u2500".repeat(separatorWidth) }),
41592
- /* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", children: [
41593
- /* @__PURE__ */ jsxs(Box, { children: [
41594
- /* @__PURE__ */ jsx6(Text, { bold: true, color: colors.primary, children: "BraveCode" }),
41595
- /* @__PURE__ */ jsx6(Text, { color: colors.textMuted, children: " \xB7 " }),
41596
- /* @__PURE__ */ jsx6(Text, { color: colors.textSecondary, children: currentAgent.name })
41597
- ] }),
41598
- /* @__PURE__ */ jsxs(Box, { children: [
41599
- isRunning && /* @__PURE__ */ jsx6(Text, { color: colors.warning, children: "\u25CF " }),
41600
- /* @__PURE__ */ jsx6(Text, { color: colors.textMuted, children: "model " }),
41601
- /* @__PURE__ */ jsx6(Text, { color: colors.accent, children: currentModel })
41602
- ] })
41603
- ] }),
41604
- session && /* @__PURE__ */ jsxs(Box, { children: [
41605
- /* @__PURE__ */ jsx6(Text, { color: colors.textMuted, children: "session " }),
41606
- /* @__PURE__ */ jsx6(Text, { color: colors.textSecondary, children: session.title }),
41607
- /* @__PURE__ */ jsx6(Text, { color: colors.textMuted, children: " \xB7 " }),
41608
- /* @__PURE__ */ jsxs(Text, { color: colors.textMuted, children: [
41609
- session.messages.length,
41610
- " messages"
41611
- ] })
41612
- ] }),
41613
- /* @__PURE__ */ jsx6(Text, { color: colors.border, children: "\u2500".repeat(separatorWidth) })
41614
- ] });
41583
+ 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
+ const maxLineWidth = Math.max(...logo.map((line) => line.length));
41594
+ const centeredLines = logo.map((line) => {
41595
+ const padding = Math.max(0, Math.floor((width - line.length) / 2));
41596
+ return " ".repeat(padding) + line;
41597
+ });
41598
+ return /* @__PURE__ */ jsx6(Box, { flexDirection: "column", alignItems: "center", children: centeredLines.map((line, i) => /* @__PURE__ */ jsx6(Text, { color: "gray", children: line }, i)) });
41615
41599
  }
41616
- var init_header_bar = __esm({
41617
- "src/core/tui/components/header-bar.tsx"() {
41600
+ var init_logo = __esm({
41601
+ "src/core/tui/components/logo.tsx"() {
41618
41602
  "use strict";
41619
- init_theme();
41620
- init_agent2();
41621
- init_session();
41622
41603
  }
41623
41604
  });
41624
41605
 
41625
41606
  // src/core/tui/components/message.tsx
41626
41607
  import "react";
41627
41608
  import { Box as Box2, Text as Text2 } from "ink";
41628
- import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
41609
+ import { jsx as jsx7, jsxs } from "react/jsx-runtime";
41629
41610
  function ToolCallDisplay({ toolCall }) {
41630
41611
  const { colors } = useTheme();
41631
41612
  const statusIcon = {
@@ -41655,17 +41636,17 @@ function ToolCallDisplay({ toolCall }) {
41655
41636
  };
41656
41637
  const label = toolLabels[toolCall.name]?.past || toolCall.name;
41657
41638
  const argStr = getToolArgs(toolCall);
41658
- return /* @__PURE__ */ jsxs2(Box2, { marginLeft: 2, children: [
41659
- /* @__PURE__ */ jsxs2(Text2, { color: statusColor, children: [
41639
+ return /* @__PURE__ */ jsxs(Box2, { marginLeft: 2, children: [
41640
+ /* @__PURE__ */ jsxs(Text2, { color: statusColor, children: [
41660
41641
  statusIcon,
41661
41642
  " "
41662
41643
  ] }),
41663
41644
  /* @__PURE__ */ jsx7(Text2, { bold: true, color: colors.text, children: label }),
41664
- argStr && /* @__PURE__ */ jsxs2(Text2, { color: colors.textMuted, children: [
41645
+ argStr && /* @__PURE__ */ jsxs(Text2, { color: colors.textMuted, children: [
41665
41646
  " ",
41666
41647
  argStr
41667
41648
  ] }),
41668
- toolCall.output && toolCall.status === "completed" && /* @__PURE__ */ jsxs2(Text2, { color: colors.textMuted, children: [
41649
+ toolCall.output && toolCall.status === "completed" && /* @__PURE__ */ jsxs(Text2, { color: colors.textMuted, children: [
41669
41650
  " \u2514 ",
41670
41651
  truncate(toolCall.output.split("\n")[0], 60)
41671
41652
  ] })
@@ -41731,19 +41712,19 @@ function Message({ message, showTimestamp = false }) {
41731
41712
  }
41732
41713
  };
41733
41714
  const config2 = roleConfig[message.role];
41734
- return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
41735
- /* @__PURE__ */ jsxs2(Box2, { children: [
41736
- /* @__PURE__ */ jsxs2(Text2, { bold: true, color: config2.color, children: [
41715
+ return /* @__PURE__ */ jsxs(Box2, { flexDirection: "column", marginBottom: 1, children: [
41716
+ /* @__PURE__ */ jsxs(Box2, { children: [
41717
+ /* @__PURE__ */ jsxs(Text2, { bold: true, color: config2.color, children: [
41737
41718
  config2.prefix,
41738
41719
  " ",
41739
41720
  config2.label
41740
41721
  ] }),
41741
- message.agent && /* @__PURE__ */ jsxs2(Text2, { color: colors.textMuted, children: [
41722
+ message.agent && /* @__PURE__ */ jsxs(Text2, { color: colors.textMuted, children: [
41742
41723
  " (",
41743
41724
  message.agent,
41744
41725
  ")"
41745
41726
  ] }),
41746
- showTimestamp && /* @__PURE__ */ jsxs2(Text2, { color: colors.textMuted, children: [
41727
+ showTimestamp && /* @__PURE__ */ jsxs(Text2, { color: colors.textMuted, children: [
41747
41728
  " ",
41748
41729
  formatTime(message.timestamp)
41749
41730
  ] })
@@ -41762,7 +41743,7 @@ var init_message = __esm({
41762
41743
  // src/core/tui/components/message-container.tsx
41763
41744
  import { useRef, useEffect as useEffect2 } from "react";
41764
41745
  import { Box as Box3, Text as Text3 } from "ink";
41765
- import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
41746
+ import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
41766
41747
  function MessageContainer() {
41767
41748
  const { colors } = useTheme();
41768
41749
  const { messages } = useSession();
@@ -41772,7 +41753,7 @@ function MessageContainer() {
41772
41753
  }
41773
41754
  }, [messages.length]);
41774
41755
  if (messages.length === 0) {
41775
- return /* @__PURE__ */ jsxs3(
41756
+ return /* @__PURE__ */ jsxs2(
41776
41757
  Box3,
41777
41758
  {
41778
41759
  flexDirection: "column",
@@ -41816,9 +41797,9 @@ var init_message_container = __esm({
41816
41797
  });
41817
41798
 
41818
41799
  // src/core/tui/components/input-editor.tsx
41819
- import { useState as useState6, useRef as useRef2, useEffect as useEffect3 } from "react";
41800
+ import { useState as useState6 } from "react";
41820
41801
  import { Box as Box4, Text as Text4, useInput, useApp } from "ink";
41821
- import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
41802
+ import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
41822
41803
  function InputEditor({ onSubmit, placeholder = "Type a message...", disabled = false }) {
41823
41804
  const { colors } = useTheme();
41824
41805
  const { isRunning } = useAgent();
@@ -41827,11 +41808,6 @@ function InputEditor({ onSubmit, placeholder = "Type a message...", disabled = f
41827
41808
  const [cursorPos, setCursorPos] = useState6(0);
41828
41809
  const [history, setHistory] = useState6([]);
41829
41810
  const [historyIndex, setHistoryIndex] = useState6(-1);
41830
- const [isMultiline, setIsMultiline] = useState6(false);
41831
- const inputRef = useRef2("");
41832
- useEffect3(() => {
41833
- inputRef.current = value;
41834
- }, [value]);
41835
41811
  useInput((input, key) => {
41836
41812
  if (disabled || isRunning) return;
41837
41813
  if (key.return) {
@@ -41839,7 +41815,6 @@ function InputEditor({ onSubmit, placeholder = "Type a message...", disabled = f
41839
41815
  const newValue = value.slice(0, cursorPos) + "\n" + value.slice(cursorPos);
41840
41816
  setValue(newValue);
41841
41817
  setCursorPos(cursorPos + 1);
41842
- setIsMultiline(true);
41843
41818
  return;
41844
41819
  }
41845
41820
  if (value.trim()) {
@@ -41848,7 +41823,6 @@ function InputEditor({ onSubmit, placeholder = "Type a message...", disabled = f
41848
41823
  setValue("");
41849
41824
  setCursorPos(0);
41850
41825
  setHistoryIndex(-1);
41851
- setIsMultiline(false);
41852
41826
  }
41853
41827
  return;
41854
41828
  }
@@ -41941,10 +41915,6 @@ function InputEditor({ onSubmit, placeholder = "Type a message...", disabled = f
41941
41915
  }
41942
41916
  return;
41943
41917
  }
41944
- if (key.ctrl && input === "l") {
41945
- process.stdout.write("\x1B[2J\x1B[H");
41946
- return;
41947
- }
41948
41918
  if (input.length === 1 && !key.ctrl && !key.meta) {
41949
41919
  const newValue = value.slice(0, cursorPos) + input + value.slice(cursorPos);
41950
41920
  setValue(newValue);
@@ -41955,32 +41925,22 @@ function InputEditor({ onSubmit, placeholder = "Type a message...", disabled = f
41955
41925
  if (disabled || isRunning) {
41956
41926
  return /* @__PURE__ */ jsx9(Box4, { children: /* @__PURE__ */ jsx9(Text4, { color: colors.textMuted, children: isRunning ? "Thinking..." : "Disabled" }) });
41957
41927
  }
41958
- if (!value && !isMultiline) {
41928
+ if (!value) {
41959
41929
  return /* @__PURE__ */ jsx9(Box4, { children: /* @__PURE__ */ jsx9(Text4, { color: colors.textMuted, children: placeholder }) });
41960
41930
  }
41961
41931
  const before = value.slice(0, cursorPos);
41962
41932
  const cursor = value[cursorPos] || " ";
41963
41933
  const after = value.slice(cursorPos + 1);
41964
- return /* @__PURE__ */ jsx9(Box4, { flexDirection: "column", children: /* @__PURE__ */ jsxs4(Box4, { children: [
41934
+ return /* @__PURE__ */ jsxs3(Box4, { children: [
41965
41935
  /* @__PURE__ */ jsx9(Text4, { children: before }),
41966
41936
  /* @__PURE__ */ jsx9(Text4, { inverse: true, children: cursor }),
41967
41937
  /* @__PURE__ */ jsx9(Text4, { children: after })
41968
- ] }) });
41938
+ ] });
41969
41939
  };
41970
- return /* @__PURE__ */ jsx9(
41971
- Box4,
41972
- {
41973
- borderStyle: "round",
41974
- borderColor: colors.borderFocused,
41975
- paddingX: 1,
41976
- paddingY: 0,
41977
- flexDirection: "column",
41978
- children: /* @__PURE__ */ jsxs4(Box4, { children: [
41979
- /* @__PURE__ */ jsx9(Text4, { bold: true, color: colors.primary, children: "\u203A " }),
41980
- renderInput()
41981
- ] })
41982
- }
41983
- );
41940
+ return /* @__PURE__ */ jsxs3(Box4, { children: [
41941
+ /* @__PURE__ */ jsx9(Text4, { bold: true, color: colors.primary, children: "\u203A " }),
41942
+ renderInput()
41943
+ ] });
41984
41944
  }
41985
41945
  var init_input_editor = __esm({
41986
41946
  "src/core/tui/components/input-editor.tsx"() {
@@ -41993,18 +41953,21 @@ var init_input_editor = __esm({
41993
41953
  // src/core/tui/components/status-bar.tsx
41994
41954
  import "react";
41995
41955
  import { Box as Box5, Text as Text5 } from "ink";
41996
- import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
41956
+ import { Fragment, jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
41997
41957
  function StatusBar() {
41998
41958
  const { colors } = useTheme();
41999
41959
  const { currentAgent, isRunning } = useAgent();
42000
41960
  const width = process.stdout.columns || 80;
42001
- return /* @__PURE__ */ jsxs5(Box5, { justifyContent: "space-between", children: [
42002
- /* @__PURE__ */ jsx10(Box5, { children: /* @__PURE__ */ jsxs5(Text5, { color: colors.textMuted, children: [
42003
- "v",
42004
- APP_VERSION
42005
- ] }) }),
42006
- /* @__PURE__ */ jsx10(Box5, { children: isRunning ? /* @__PURE__ */ jsx10(Text5, { color: colors.warning, children: "\u25CF Running" }) : /* @__PURE__ */ jsx10(Text5, { color: colors.textMuted, children: "Ready" }) }),
42007
- /* @__PURE__ */ jsx10(Box5, { children: /* @__PURE__ */ jsx10(Text5, { color: colors.textMuted, children: "/help for commands" }) })
41961
+ const cwd = process.cwd().replace(process.env.HOME || "", "~");
41962
+ return /* @__PURE__ */ jsxs4(Box5, { justifyContent: "space-between", width, children: [
41963
+ /* @__PURE__ */ jsxs4(Box5, { gap: 1, children: [
41964
+ /* @__PURE__ */ jsx10(Text5, { color: colors.textMuted, children: cwd }),
41965
+ isRunning && /* @__PURE__ */ jsxs4(Fragment, { children: [
41966
+ /* @__PURE__ */ jsx10(Text5, { color: colors.textMuted, children: "\xB7" }),
41967
+ /* @__PURE__ */ jsx10(Text5, { color: colors.warning, children: "\u25CF running" })
41968
+ ] })
41969
+ ] }),
41970
+ /* @__PURE__ */ jsx10(Text5, { color: colors.textMuted, children: APP_VERSION })
42008
41971
  ] });
42009
41972
  }
42010
41973
  var init_status_bar = __esm({
@@ -42019,14 +41982,14 @@ var init_status_bar = __esm({
42019
41982
  // src/core/tui/components/toast.tsx
42020
41983
  import "react";
42021
41984
  import { Box as Box6, Text as Text6 } from "ink";
42022
- import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
41985
+ import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
42023
41986
  function ToastContainer() {
42024
41987
  const { colors } = useTheme();
42025
41988
  const { toasts } = useToast();
42026
41989
  if (toasts.length === 0) {
42027
41990
  return null;
42028
41991
  }
42029
- return /* @__PURE__ */ jsx11(Box6, { flexDirection: "column", position: "absolute", bottom: 2, right: 2, children: toasts.map((toast) => /* @__PURE__ */ jsxs6(
41992
+ return /* @__PURE__ */ jsx11(Box6, { flexDirection: "column", position: "absolute", bottom: 2, right: 2, children: toasts.map((toast) => /* @__PURE__ */ jsxs5(
42030
41993
  Box6,
42031
41994
  {
42032
41995
  borderStyle: "round",
@@ -42034,7 +41997,7 @@ function ToastContainer() {
42034
41997
  paddingX: 1,
42035
41998
  marginBottom: 1,
42036
41999
  children: [
42037
- /* @__PURE__ */ jsxs6(Text6, { color: colors[variantColors[toast.variant]], children: [
42000
+ /* @__PURE__ */ jsxs5(Text6, { color: colors[variantColors[toast.variant]], children: [
42038
42001
  variantIcons[toast.variant],
42039
42002
  " "
42040
42003
  ] }),
@@ -42068,110 +42031,39 @@ var init_toast2 = __esm({
42068
42031
  // src/core/tui/components/command-palette.tsx
42069
42032
  import { useState as useState7 } from "react";
42070
42033
  import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
42071
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
42072
- function CommandPalette() {
42034
+ import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
42035
+ var init_command_palette = __esm({
42036
+ "src/core/tui/components/command-palette.tsx"() {
42037
+ "use strict";
42038
+ init_theme();
42039
+ init_dialog();
42040
+ init_agent2();
42041
+ init_session();
42042
+ init_toast();
42043
+ }
42044
+ });
42045
+
42046
+ // src/core/tui/components/model-selector.tsx
42047
+ import { useState as useState8 } from "react";
42048
+ import { Box as Box8, Text as Text8, useInput as useInput3 } from "ink";
42049
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
42050
+ function ModelSelector() {
42073
42051
  const { colors } = useTheme();
42052
+ const { currentModel, setModel } = useAgent();
42074
42053
  const { closeDialog } = useDialog();
42075
- const { setAgent, setModel, availableAgents } = useAgent();
42076
- const { createSession, clearMessages } = useSession();
42077
42054
  const toast = useToast();
42078
- const [query, setQuery] = useState7("");
42079
- const [selectedIndex, setSelectedIndex] = useState7(0);
42080
- const commands = [
42081
- // Session commands
42082
- {
42083
- name: "new",
42084
- label: "New Session",
42085
- description: "Start a new conversation",
42086
- category: "Session",
42087
- action: () => {
42088
- createSession();
42089
- toast.success("New session created");
42090
- closeDialog();
42091
- }
42092
- },
42093
- {
42094
- name: "clear",
42095
- label: "Clear Messages",
42096
- description: "Clear current conversation",
42097
- category: "Session",
42098
- action: () => {
42099
- clearMessages();
42100
- toast.success("Messages cleared");
42101
- closeDialog();
42102
- }
42103
- },
42104
- // Agent commands
42105
- ...availableAgents.map((agent) => ({
42106
- name: `agent:${agent.id}`,
42107
- label: `Switch to ${agent.name}`,
42108
- description: agent.description,
42109
- category: "Agent",
42110
- action: () => {
42111
- setAgent(agent.id);
42112
- toast.success(`Switched to ${agent.name}`);
42113
- closeDialog();
42114
- }
42115
- })),
42116
- // Model commands
42117
- {
42118
- name: "model:codestral",
42119
- label: "Switch to Codestral",
42120
- description: "Code generation model",
42121
- category: "Model",
42122
- action: () => {
42123
- setModel("codestral-latest");
42124
- toast.success("Switched to Codestral");
42125
- closeDialog();
42126
- }
42127
- },
42128
- {
42129
- name: "model:deepseek-r1",
42130
- label: "Switch to DeepSeek R1",
42131
- description: "Reasoning model",
42132
- category: "Model",
42133
- action: () => {
42134
- setModel("DeepSeek-R1");
42135
- toast.success("Switched to DeepSeek R1");
42136
- closeDialog();
42137
- }
42138
- },
42139
- {
42140
- name: "model:mistral",
42141
- label: "Switch to Mistral Large",
42142
- description: "General purpose model",
42143
- category: "Model",
42144
- action: () => {
42145
- setModel("mistral-large-2512");
42146
- toast.success("Switched to Mistral Large");
42147
- closeDialog();
42148
- }
42149
- },
42150
- // System commands
42151
- {
42152
- name: "help",
42153
- label: "Help",
42154
- description: "Show help information",
42155
- category: "System",
42156
- action: () => {
42157
- toast.info("Help: Use arrow keys to navigate, Enter to select, Esc to close");
42158
- closeDialog();
42159
- }
42160
- },
42161
- {
42162
- name: "exit",
42163
- label: "Exit",
42164
- description: "Quit the application",
42165
- category: "System",
42166
- action: () => {
42167
- process.exit(0);
42168
- }
42169
- }
42170
- ];
42171
- const filteredCommands = commands.filter(
42172
- (cmd) => cmd.label.toLowerCase().includes(query.toLowerCase()) || cmd.description.toLowerCase().includes(query.toLowerCase())
42055
+ const [selectedIndex, setSelectedIndex] = useState8(0);
42056
+ const [filter3, setFilter] = useState8("");
42057
+ const models = models_default.models.map((m) => ({
42058
+ id: m.id,
42059
+ name: m.name,
42060
+ provider: m.provider,
42061
+ tags: m.tags
42062
+ }));
42063
+ const filteredModels = models.filter(
42064
+ (m) => m.tags.includes("free") && (m.name.toLowerCase().includes(filter3.toLowerCase()) || m.id.toLowerCase().includes(filter3.toLowerCase()))
42173
42065
  );
42174
- useInput2((input, key) => {
42066
+ useInput3((input, key) => {
42175
42067
  if (key.escape) {
42176
42068
  closeDialog();
42177
42069
  return;
@@ -42181,75 +42073,84 @@ function CommandPalette() {
42181
42073
  return;
42182
42074
  }
42183
42075
  if (key.downArrow) {
42184
- setSelectedIndex((prev) => Math.min(filteredCommands.length - 1, prev + 1));
42076
+ setSelectedIndex((prev) => Math.min(filteredModels.length - 1, prev + 1));
42185
42077
  return;
42186
42078
  }
42187
42079
  if (key.return) {
42188
- if (filteredCommands[selectedIndex]) {
42189
- filteredCommands[selectedIndex].action();
42080
+ if (filteredModels[selectedIndex]) {
42081
+ const selected = filteredModels[selectedIndex];
42082
+ setModel(selected.id);
42083
+ toast.success(`Switched to ${selected.name}`);
42084
+ closeDialog();
42190
42085
  }
42191
42086
  return;
42192
42087
  }
42193
42088
  if (!key.ctrl && !key.meta && input.length === 1) {
42194
- setQuery((prev) => prev + input);
42089
+ setFilter((prev) => prev + input);
42195
42090
  setSelectedIndex(0);
42196
42091
  }
42197
42092
  if (key.backspace) {
42198
- setQuery((prev) => prev.slice(0, -1));
42093
+ setFilter((prev) => prev.slice(0, -1));
42199
42094
  setSelectedIndex(0);
42200
42095
  }
42201
42096
  });
42097
+ const renderModel = (model, index) => {
42098
+ const isSelected = model.id === currentModel;
42099
+ const isHighlighted = index === selectedIndex;
42100
+ return /* @__PURE__ */ jsxs7(Box8, { children: [
42101
+ /* @__PURE__ */ jsxs7(
42102
+ Text8,
42103
+ {
42104
+ bold: isHighlighted,
42105
+ color: isSelected ? colors.primary : isHighlighted ? colors.accent : colors.text,
42106
+ children: [
42107
+ isSelected ? "\u25CF " : "\u25CB ",
42108
+ model.name
42109
+ ]
42110
+ }
42111
+ ),
42112
+ /* @__PURE__ */ jsxs7(Text8, { color: colors.textMuted, children: [
42113
+ " (",
42114
+ model.provider,
42115
+ ")"
42116
+ ] }),
42117
+ model.tags.includes("free") && /* @__PURE__ */ jsx13(Text8, { color: colors.success, children: " free" })
42118
+ ] }, model.id);
42119
+ };
42202
42120
  return /* @__PURE__ */ jsxs7(
42203
- Box7,
42121
+ Box8,
42204
42122
  {
42205
42123
  flexDirection: "column",
42206
42124
  borderStyle: "double",
42207
42125
  borderColor: colors.borderFocused,
42126
+ width: 60,
42208
42127
  position: "absolute",
42209
42128
  top: "50%",
42210
42129
  left: "50%",
42211
- width: "60%",
42212
42130
  children: [
42213
- /* @__PURE__ */ jsx12(Box7, { paddingX: 1, children: /* @__PURE__ */ jsx12(Text7, { bold: true, color: colors.primary, children: "Command Palette" }) }),
42214
- /* @__PURE__ */ jsxs7(Box7, { paddingX: 1, paddingY: 0, children: [
42215
- /* @__PURE__ */ jsx12(Text7, { color: colors.textMuted, children: "Search: " }),
42216
- /* @__PURE__ */ jsx12(Text7, { children: query }),
42217
- /* @__PURE__ */ jsx12(Text7, { inverse: true, children: " " })
42131
+ /* @__PURE__ */ jsx13(Box8, { paddingX: 1, children: /* @__PURE__ */ jsx13(Text8, { bold: true, color: colors.primary, children: "Select Model" }) }),
42132
+ /* @__PURE__ */ jsxs7(Box8, { paddingX: 1, children: [
42133
+ /* @__PURE__ */ jsx13(Text8, { color: colors.textMuted, children: "Search: " }),
42134
+ /* @__PURE__ */ jsx13(Text8, { children: filter3 }),
42135
+ /* @__PURE__ */ jsx13(Text8, { inverse: true, children: " " })
42218
42136
  ] }),
42219
- /* @__PURE__ */ jsx12(Box7, { flexDirection: "column", paddingX: 1, maxHeight: 15, children: filteredCommands.length === 0 ? /* @__PURE__ */ jsx12(Text7, { color: colors.textMuted, children: "No matching commands" }) : filteredCommands.map((cmd, index) => /* @__PURE__ */ jsxs7(
42220
- Box7,
42221
- {
42222
- backgroundColor: index === selectedIndex ? colors.backgroundHighlight : void 0,
42223
- children: [
42224
- /* @__PURE__ */ jsx12(
42225
- Text7,
42226
- {
42227
- bold: index === selectedIndex,
42228
- color: index === selectedIndex ? colors.primary : colors.text,
42229
- children: cmd.label
42230
- }
42231
- ),
42232
- /* @__PURE__ */ jsxs7(Text7, { color: colors.textMuted, children: [
42233
- " - ",
42234
- cmd.description
42235
- ] })
42236
- ]
42237
- },
42238
- cmd.name
42239
- )) }),
42240
- /* @__PURE__ */ jsx12(Box7, { paddingX: 1, children: /* @__PURE__ */ jsx12(Text7, { color: colors.textMuted, children: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc close" }) })
42137
+ /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", paddingX: 1, maxHeight: 15, children: [
42138
+ /* @__PURE__ */ jsx13(Text8, { color: colors.textMuted, children: "Available Models (free):" }),
42139
+ filteredModels.map((model, index) => renderModel(model, index))
42140
+ ] }),
42141
+ /* @__PURE__ */ jsx13(Box8, { paddingX: 1, children: /* @__PURE__ */ jsx13(Text8, { color: colors.textMuted, children: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc close" }) })
42241
42142
  ]
42242
42143
  }
42243
42144
  );
42244
42145
  }
42245
- var init_command_palette = __esm({
42246
- "src/core/tui/components/command-palette.tsx"() {
42146
+ var init_model_selector = __esm({
42147
+ "src/core/tui/components/model-selector.tsx"() {
42247
42148
  "use strict";
42248
42149
  init_theme();
42249
- init_dialog();
42250
42150
  init_agent2();
42251
- init_session();
42151
+ init_dialog();
42252
42152
  init_toast();
42153
+ init_models();
42253
42154
  }
42254
42155
  });
42255
42156
 
@@ -42350,20 +42251,27 @@ var init_use_agent = __esm({
42350
42251
 
42351
42252
  // src/core/tui/app.tsx
42352
42253
  import "react";
42353
- import { Box as Box8, useInput as useInput3, useApp as useApp2 } from "ink";
42354
- import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
42254
+ import { Box as Box9, Text as Text9, useInput as useInput4, useApp as useApp2 } from "ink";
42255
+ import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
42355
42256
  function App() {
42356
42257
  const { colors } = useTheme();
42357
42258
  const { messages } = useSession();
42358
- const { isRunning } = useAgent();
42359
- const { isOpen, openDialog, closeDialog } = useDialog();
42259
+ const { currentAgent, currentModel, isRunning, setAgent } = useAgent();
42260
+ const { isOpen, openDialog, closeDialog, dialog } = useDialog();
42360
42261
  const { sendMessage, cancelCurrent } = useAgent2();
42361
42262
  const { exit } = useApp2();
42362
- useInput3((input, key) => {
42263
+ useInput4((input, key) => {
42363
42264
  if (key.ctrl && input === "p") {
42364
42265
  openDialog("model");
42365
42266
  return;
42366
42267
  }
42268
+ if (key.tab) {
42269
+ const agents = ["build", "plan", "debug", "testing", "security"];
42270
+ const currentIndex = agents.indexOf(currentAgent.id);
42271
+ const nextIndex = (currentIndex + 1) % agents.length;
42272
+ setAgent(agents[nextIndex]);
42273
+ return;
42274
+ }
42367
42275
  if (key.ctrl && input === "c") {
42368
42276
  if (isRunning) {
42369
42277
  cancelCurrent();
@@ -42409,29 +42317,51 @@ function App() {
42409
42317
  }
42410
42318
  await sendMessage(value);
42411
42319
  };
42320
+ const hasMessages = messages.length > 0;
42412
42321
  return /* @__PURE__ */ jsxs8(
42413
- Box8,
42322
+ Box9,
42414
42323
  {
42415
42324
  flexDirection: "column",
42416
42325
  width: "100%",
42417
42326
  height: "100%",
42418
42327
  backgroundColor: colors.background,
42419
42328
  children: [
42420
- /* @__PURE__ */ jsx13(HeaderBar, {}),
42421
- /* @__PURE__ */ jsx13(Box8, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children: /* @__PURE__ */ jsx13(MessageContainer, {}) }),
42422
- /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
42423
- /* @__PURE__ */ jsx13(
42424
- InputEditor,
42425
- {
42426
- onSubmit: handleSubmit,
42427
- disabled: isOpen,
42428
- placeholder: isRunning ? "Press Ctrl+C to cancel..." : "Type a message... (Ctrl+P for commands)"
42429
- }
42430
- ),
42431
- /* @__PURE__ */ jsx13(StatusBar, {})
42432
- ] }),
42433
- isOpen && /* @__PURE__ */ jsx13(CommandPalette, {}),
42434
- /* @__PURE__ */ jsx13(ToastContainer, {})
42329
+ /* @__PURE__ */ jsx14(Box9, { flexDirection: "column", flexGrow: 1, justifyContent: hasMessages ? "flex-start" : "center", children: hasMessages ? /* @__PURE__ */ jsx14(MessageContainer, {}) : (
42330
+ /* Welcome screen - centered layout like OpenCode */
42331
+ /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", alignItems: "center", gap: 1, children: [
42332
+ /* @__PURE__ */ jsx14(Logo, { width: 80 }),
42333
+ /* @__PURE__ */ jsx14(
42334
+ Box9,
42335
+ {
42336
+ flexDirection: "column",
42337
+ width: 60,
42338
+ borderStyle: "round",
42339
+ borderColor: colors.border,
42340
+ paddingX: 2,
42341
+ paddingY: 1,
42342
+ children: /* @__PURE__ */ jsx14(
42343
+ InputEditor,
42344
+ {
42345
+ onSubmit: handleSubmit,
42346
+ placeholder: 'Ask anything... "What is the tech stack of this project?"'
42347
+ }
42348
+ )
42349
+ }
42350
+ ),
42351
+ /* @__PURE__ */ jsxs8(Box9, { gap: 1, children: [
42352
+ /* @__PURE__ */ jsx14(Text9, { bold: true, color: colors.primary, children: currentAgent.name }),
42353
+ /* @__PURE__ */ jsx14(Text9, { color: colors.textMuted, children: "\xB7" }),
42354
+ /* @__PURE__ */ jsx14(Text9, { color: colors.textSecondary, children: currentModel })
42355
+ ] }),
42356
+ /* @__PURE__ */ jsxs8(Box9, { gap: 2, children: [
42357
+ /* @__PURE__ */ jsx14(Text9, { color: colors.textMuted, children: "tab agents" }),
42358
+ /* @__PURE__ */ jsx14(Text9, { color: colors.textMuted, children: "ctrl+p commands" })
42359
+ ] })
42360
+ ] })
42361
+ ) }),
42362
+ /* @__PURE__ */ jsx14(StatusBar, {}),
42363
+ isOpen && dialog.type === "model" && /* @__PURE__ */ jsx14(ModelSelector, {}),
42364
+ /* @__PURE__ */ jsx14(ToastContainer, {})
42435
42365
  ]
42436
42366
  }
42437
42367
  );
@@ -42443,12 +42373,13 @@ var init_app = __esm({
42443
42373
  init_session();
42444
42374
  init_agent2();
42445
42375
  init_dialog();
42446
- init_header_bar();
42376
+ init_logo();
42447
42377
  init_message_container();
42448
42378
  init_input_editor();
42449
42379
  init_status_bar();
42450
42380
  init_toast2();
42451
42381
  init_command_palette();
42382
+ init_model_selector();
42452
42383
  init_use_agent();
42453
42384
  }
42454
42385
  });
@@ -42460,7 +42391,7 @@ __export(tui_exports, {
42460
42391
  });
42461
42392
  import "react";
42462
42393
  import { render } from "ink";
42463
- import { jsx as jsx14 } from "react/jsx-runtime";
42394
+ import { jsx as jsx15 } from "react/jsx-runtime";
42464
42395
  var TUILauncher;
42465
42396
  var init_tui = __esm({
42466
42397
  "src/core/tui/index.tsx"() {
@@ -42478,12 +42409,12 @@ var init_tui = __esm({
42478
42409
  }
42479
42410
  async start() {
42480
42411
  const { waitUntilExit } = render(
42481
- /* @__PURE__ */ jsx14(ThemeProvider, { children: /* @__PURE__ */ jsx14(SessionProvider, { children: /* @__PURE__ */ jsx14(
42412
+ /* @__PURE__ */ jsx15(ThemeProvider, { children: /* @__PURE__ */ jsx15(SessionProvider, { children: /* @__PURE__ */ jsx15(
42482
42413
  AgentProvider,
42483
42414
  {
42484
42415
  initialAgent: this.options.agent || "build",
42485
42416
  initialModel: this.options.model,
42486
- children: /* @__PURE__ */ jsx14(DialogProvider, { children: /* @__PURE__ */ jsx14(ToastProvider, { children: /* @__PURE__ */ jsx14(App, {}) }) })
42417
+ children: /* @__PURE__ */ jsx15(DialogProvider, { children: /* @__PURE__ */ jsx15(ToastProvider, { children: /* @__PURE__ */ jsx15(App, {}) }) })
42487
42418
  }
42488
42419
  ) }) })
42489
42420
  );