@bike4mind/cli 0.2.3-feat-cli-clear-command.17058 → 0.2.3-feat-cli-interactive-config-editor.17058

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 (2) hide show
  1. package/dist/index.js +279 -100
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -79,13 +79,13 @@ import {
79
79
  } from "./chunk-PDX44BCA.js";
80
80
 
81
81
  // src/index.tsx
82
- import React11, { useState as useState3, useEffect as useEffect3, useCallback } from "react";
83
- import { render, Box as Box11, Text as Text10, useApp, useInput as useInput2 } from "ink";
82
+ import React12, { useState as useState4, useEffect as useEffect3, useCallback } from "react";
83
+ import { render, Box as Box12, Text as Text11, useApp, useInput as useInput3 } from "ink";
84
84
  import { v4 as uuidv49 } from "uuid";
85
85
 
86
86
  // src/components/App.tsx
87
- import React8 from "react";
88
- import { Box as Box8, Text as Text7, Static } from "ink";
87
+ import React9 from "react";
88
+ import { Box as Box9, Text as Text8, Static } from "ink";
89
89
 
90
90
  // src/components/StatusBar.tsx
91
91
  import React from "react";
@@ -352,7 +352,7 @@ var COMMANDS = [
352
352
  },
353
353
  {
354
354
  name: "config",
355
- description: "Show configuration"
355
+ description: "Open interactive configuration editor"
356
356
  },
357
357
  {
358
358
  name: "set-api",
@@ -384,11 +384,6 @@ var COMMANDS = [
384
384
  {
385
385
  name: "usage",
386
386
  description: "Show credit usage and balance"
387
- },
388
- {
389
- name: "clear",
390
- description: "Start a new session",
391
- aliases: ["new"]
392
387
  }
393
388
  ];
394
389
 
@@ -609,6 +604,9 @@ var useCliStore = create((set) => ({
609
604
  // Permission prompt
610
605
  permissionPrompt: null,
611
606
  setPermissionPrompt: (prompt) => set({ permissionPrompt: prompt }),
607
+ // Config editor
608
+ showConfigEditor: false,
609
+ setShowConfigEditor: (show) => set({ showConfigEditor: show }),
612
610
  // Exit handling
613
611
  exitRequested: false,
614
612
  setExitRequested: (requested) => set({ exitRequested: requested })
@@ -663,6 +661,211 @@ function PermissionPrompt({
663
661
  return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", borderStyle: "bold", borderColor: "yellow", padding: 1, marginY: 1 }, /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text6, { bold: true, color: "yellow" }, "\u26A0\uFE0F Permission Required")), /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, "Tool: "), /* @__PURE__ */ React7.createElement(Text6, { bold: true, color: "cyan" }, toolName)), toolDescription && /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, "Action: "), /* @__PURE__ */ React7.createElement(Text6, null, toolDescription)), /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React7.createElement(Text6, { bold: true }, "Arguments:"), /* @__PURE__ */ React7.createElement(Box7, { paddingLeft: 2, flexDirection: "column" }, /* @__PURE__ */ React7.createElement(Text6, { dimColor: true }, argsString))), preview && /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React7.createElement(Text6, { bold: true }, "Preview:"), /* @__PURE__ */ React7.createElement(Box7, { borderStyle: "single", borderColor: "gray", paddingX: 1, flexDirection: "column" }, renderDiffPreview(preview))), !canBeTrusted && /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React7.createElement(Text6, { color: "red", dimColor: true }, "Note: This tool cannot be trusted due to its dangerous nature.")), /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React7.createElement(SelectInput, { items, onSelect: (item) => onResponse(item.value) })));
664
662
  }
665
663
 
664
+ // src/components/ConfigEditor.tsx
665
+ import React8, { useState as useState2, useMemo as useMemo2 } from "react";
666
+ import { Box as Box8, Text as Text7, useInput as useInput2 } from "ink";
667
+ var MAX_ITERATIONS_OPTIONS = [
668
+ { label: "10", value: 10 },
669
+ { label: "20", value: 20 },
670
+ { label: "30", value: 30 },
671
+ { label: "40", value: 40 },
672
+ { label: "50", value: 50 },
673
+ { label: "Infinite", value: null }
674
+ ];
675
+ var THEME_OPTIONS = [
676
+ { label: "dark", value: "dark" },
677
+ { label: "light", value: "light" }
678
+ ];
679
+ var EXPORT_FORMAT_OPTIONS = [
680
+ { label: "markdown", value: "markdown" },
681
+ { label: "json", value: "json" }
682
+ ];
683
+ var CONFIG_ITEMS = [
684
+ {
685
+ key: "maxIterations",
686
+ label: "Max Iterations",
687
+ type: "select",
688
+ options: MAX_ITERATIONS_OPTIONS,
689
+ getValue: (config) => config.preferences.maxIterations,
690
+ setValue: (config, value) => ({
691
+ ...config,
692
+ preferences: {
693
+ ...config.preferences,
694
+ maxIterations: value
695
+ }
696
+ })
697
+ },
698
+ {
699
+ key: "maxTokens",
700
+ label: "Max Tokens",
701
+ type: "number",
702
+ min: 256,
703
+ max: 128e3,
704
+ step: 256,
705
+ getValue: (config) => config.preferences.maxTokens,
706
+ setValue: (config, value) => ({
707
+ ...config,
708
+ preferences: {
709
+ ...config.preferences,
710
+ maxTokens: value
711
+ }
712
+ })
713
+ },
714
+ {
715
+ key: "temperature",
716
+ label: "Temperature",
717
+ type: "number",
718
+ min: 0,
719
+ max: 2,
720
+ step: 0.1,
721
+ getValue: (config) => config.preferences.temperature,
722
+ setValue: (config, value) => ({
723
+ ...config,
724
+ preferences: {
725
+ ...config.preferences,
726
+ temperature: value
727
+ }
728
+ })
729
+ },
730
+ {
731
+ key: "autoSave",
732
+ label: "Auto Save",
733
+ type: "boolean",
734
+ getValue: (config) => config.preferences.autoSave,
735
+ setValue: (config, value) => ({
736
+ ...config,
737
+ preferences: {
738
+ ...config.preferences,
739
+ autoSave: value
740
+ }
741
+ })
742
+ },
743
+ {
744
+ key: "theme",
745
+ label: "Theme",
746
+ type: "select",
747
+ options: THEME_OPTIONS,
748
+ getValue: (config) => config.preferences.theme,
749
+ setValue: (config, value) => ({
750
+ ...config,
751
+ preferences: {
752
+ ...config.preferences,
753
+ theme: value
754
+ }
755
+ })
756
+ },
757
+ {
758
+ key: "exportFormat",
759
+ label: "Export Format",
760
+ type: "select",
761
+ options: EXPORT_FORMAT_OPTIONS,
762
+ getValue: (config) => config.preferences.exportFormat,
763
+ setValue: (config, value) => ({
764
+ ...config,
765
+ preferences: {
766
+ ...config.preferences,
767
+ exportFormat: value
768
+ }
769
+ })
770
+ }
771
+ ];
772
+ function ConfigEditor({ config, onSave, onClose }) {
773
+ const [selectedIndex, setSelectedIndex] = useState2(0);
774
+ const [editedConfig, setEditedConfig] = useState2(config);
775
+ const [saveError, setSaveError] = useState2(null);
776
+ const [isSaving, setIsSaving] = useState2(false);
777
+ const hasChanges = useMemo2(() => {
778
+ return JSON.stringify(config.preferences) !== JSON.stringify(editedConfig.preferences);
779
+ }, [config.preferences, editedConfig.preferences]);
780
+ const handleSaveAndClose = async () => {
781
+ if (hasChanges) {
782
+ try {
783
+ setSaveError(null);
784
+ setIsSaving(true);
785
+ await onSave(editedConfig);
786
+ } catch (error) {
787
+ setSaveError(error instanceof Error ? error.message : "Failed to save");
788
+ setIsSaving(false);
789
+ return;
790
+ }
791
+ setIsSaving(false);
792
+ }
793
+ onClose();
794
+ };
795
+ useInput2((input, key) => {
796
+ const currentItem = CONFIG_ITEMS[selectedIndex];
797
+ if (key.upArrow) {
798
+ setSelectedIndex((prev) => prev > 0 ? prev - 1 : CONFIG_ITEMS.length - 1);
799
+ return;
800
+ }
801
+ if (key.downArrow) {
802
+ setSelectedIndex((prev) => prev < CONFIG_ITEMS.length - 1 ? prev + 1 : 0);
803
+ return;
804
+ }
805
+ if ((key.escape || input === "q") && !isSaving) {
806
+ handleSaveAndClose();
807
+ return;
808
+ }
809
+ if (currentItem.type === "select" && currentItem.options) {
810
+ const currentValue = currentItem.getValue(editedConfig);
811
+ const currentIdx = currentItem.options.findIndex((opt) => opt.value === currentValue);
812
+ if (key.leftArrow || input === " ") {
813
+ let newIdx;
814
+ if (input === " ") {
815
+ newIdx = (currentIdx + 1) % currentItem.options.length;
816
+ } else {
817
+ newIdx = currentIdx > 0 ? currentIdx - 1 : currentItem.options.length - 1;
818
+ }
819
+ const newValue = currentItem.options[newIdx].value;
820
+ setEditedConfig(currentItem.setValue(editedConfig, newValue));
821
+ } else if (key.rightArrow) {
822
+ const newIdx = (currentIdx + 1) % currentItem.options.length;
823
+ const newValue = currentItem.options[newIdx].value;
824
+ setEditedConfig(currentItem.setValue(editedConfig, newValue));
825
+ }
826
+ } else if (currentItem.type === "boolean") {
827
+ if (input === " " || key.leftArrow || key.rightArrow) {
828
+ const currentValue = currentItem.getValue(editedConfig);
829
+ setEditedConfig(currentItem.setValue(editedConfig, !currentValue));
830
+ }
831
+ } else if (currentItem.type === "number") {
832
+ const currentValue = currentItem.getValue(editedConfig);
833
+ const step = currentItem.step || 1;
834
+ const min = currentItem.min ?? 0;
835
+ const max = currentItem.max ?? Infinity;
836
+ if (key.leftArrow || input === "-") {
837
+ const newValue = Math.max(min, currentValue - step);
838
+ const rounded = Math.round(newValue * 10) / 10;
839
+ setEditedConfig(currentItem.setValue(editedConfig, rounded));
840
+ } else if (key.rightArrow || input === "+" || input === "=") {
841
+ const newValue = Math.min(max, currentValue + step);
842
+ const rounded = Math.round(newValue * 10) / 10;
843
+ setEditedConfig(currentItem.setValue(editedConfig, rounded));
844
+ }
845
+ }
846
+ });
847
+ const formatValue = (item, value) => {
848
+ if (item.type === "boolean") {
849
+ return value ? "On" : "Off";
850
+ }
851
+ if (item.type === "select" && item.options) {
852
+ const option = item.options.find((opt) => opt.value === value);
853
+ return option?.label || String(value);
854
+ }
855
+ if (item.type === "number") {
856
+ return String(value);
857
+ }
858
+ return String(value);
859
+ };
860
+ return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1, marginY: 1 }, /* @__PURE__ */ React8.createElement(Box8, { justifyContent: "space-between", marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Text7, { bold: true, color: "cyan" }, "Settings"), isSaving ? /* @__PURE__ */ React8.createElement(Text7, { color: "yellow" }, "Saving...") : hasChanges ? /* @__PURE__ */ React8.createElement(Text7, { dimColor: true, color: "yellow" }, "(unsaved changes)") : null), saveError && /* @__PURE__ */ React8.createElement(Box8, { marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Text7, { color: "red" }, "Error: ", saveError)), /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", marginBottom: 1 }, CONFIG_ITEMS.map((item, index) => {
861
+ const isSelected = index === selectedIndex;
862
+ const value = item.getValue(editedConfig);
863
+ const displayValue = formatValue(item, value);
864
+ const hasOptions = item.type === "select" || item.type === "boolean" || item.type === "number";
865
+ return /* @__PURE__ */ React8.createElement(Box8, { key: item.key }, /* @__PURE__ */ React8.createElement(Text7, { color: isSelected ? "cyan" : void 0 }, isSelected ? "> " : " "), /* @__PURE__ */ React8.createElement(Box8, { width: 18 }, /* @__PURE__ */ React8.createElement(Text7, { bold: isSelected, color: isSelected ? "white" : "gray" }, item.label, ":")), /* @__PURE__ */ React8.createElement(Box8, null, hasOptions && isSelected && /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, "< "), /* @__PURE__ */ React8.createElement(Text7, { bold: isSelected, color: isSelected ? "green" : void 0 }, displayValue), hasOptions && isSelected && /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, " >")));
866
+ })), /* @__PURE__ */ React8.createElement(Box8, { borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, "\u2191/\u2193: Navigate | Space/\u2190/\u2192: Change | q/Esc: Save & Exit")));
867
+ }
868
+
666
869
  // src/utils/processFileReferences.ts
667
870
  import * as fs2 from "fs";
668
871
  import * as path2 from "path";
@@ -778,16 +981,25 @@ function hasFileReferences(message) {
778
981
  }
779
982
 
780
983
  // src/components/App.tsx
781
- function App({ onMessage, onCommand, onPermissionResponse, commandHistory = [] }) {
984
+ function App({
985
+ onMessage,
986
+ onCommand,
987
+ onPermissionResponse,
988
+ commandHistory = [],
989
+ config,
990
+ onSaveConfig
991
+ }) {
782
992
  const messages = useCliStore((state) => state.session?.messages || []);
783
993
  const sessionName = useCliStore((state) => state.session?.name || "New Session");
784
994
  const currentModel = useCliStore((state) => state.session?.model || "claude-sonnet-4-5-20250929");
785
995
  const totalTokens = useCliStore((state) => state.session?.metadata.totalTokens || 0);
786
996
  const isThinking = useCliStore((state) => state.isThinking);
787
997
  const permissionPrompt = useCliStore((state) => state.permissionPrompt);
998
+ const showConfigEditor = useCliStore((state) => state.showConfigEditor);
999
+ const setShowConfigEditor = useCliStore((state) => state.setShowConfigEditor);
788
1000
  const exitRequested = useCliStore((state) => state.exitRequested);
789
1001
  const setIsThinking = useCliStore((state) => state.setIsThinking);
790
- const handleSubmit = React8.useCallback(
1002
+ const handleSubmit = React9.useCallback(
791
1003
  async (input) => {
792
1004
  const trimmed = input.trim();
793
1005
  if (!trimmed) return;
@@ -816,7 +1028,7 @@ ${errorBlock}`;
816
1028
  },
817
1029
  [onMessage, onCommand, setIsThinking]
818
1030
  );
819
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column" }, /* @__PURE__ */ React8.createElement(StatusBar, { sessionName, model: currentModel, tokenUsage: totalTokens }), permissionPrompt ? /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React8.createElement(
1031
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column" }, /* @__PURE__ */ React9.createElement(StatusBar, { sessionName, model: currentModel, tokenUsage: totalTokens }), showConfigEditor && config && onSaveConfig ? /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React9.createElement(ConfigEditor, { config, onSave: onSaveConfig, onClose: () => setShowConfigEditor(false) })) : permissionPrompt ? /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React9.createElement(
820
1032
  PermissionPrompt,
821
1033
  {
822
1034
  toolName: permissionPrompt.toolName,
@@ -825,39 +1037,39 @@ ${errorBlock}`;
825
1037
  canBeTrusted: permissionPrompt.canBeTrusted,
826
1038
  onResponse: onPermissionResponse
827
1039
  }
828
- )) : /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(Static, { items: messages }, (message, index) => /* @__PURE__ */ React8.createElement(Box8, { key: index, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React8.createElement(MessageItem, { message }))), /* @__PURE__ */ React8.createElement(AgentThinking, null), exitRequested && /* @__PURE__ */ React8.createElement(Box8, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Text7, { color: "yellow", bold: true }, "\u26A0\uFE0F Press Ctrl+C again to exit")), /* @__PURE__ */ React8.createElement(Box8, { borderStyle: "single", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React8.createElement(InputPrompt, { onSubmit: handleSubmit, disabled: isThinking, history: commandHistory }))));
1040
+ )) : /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(Static, { items: messages }, (message, index) => /* @__PURE__ */ React9.createElement(Box9, { key: index, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React9.createElement(MessageItem, { message }))), /* @__PURE__ */ React9.createElement(AgentThinking, null), exitRequested && /* @__PURE__ */ React9.createElement(Box9, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text8, { color: "yellow", bold: true }, "Press Ctrl+C again to exit")), /* @__PURE__ */ React9.createElement(Box9, { borderStyle: "single", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React9.createElement(InputPrompt, { onSubmit: handleSubmit, disabled: isThinking, history: commandHistory }))));
829
1041
  }
830
1042
  function MessageItem({ message }) {
831
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Box8, null, /* @__PURE__ */ React8.createElement(Text7, { bold: true, color: message.role === "user" ? "cyan" : "green" }, message.role === "user" ? "\u{1F464} You" : "\u{1F916} Assistant"), /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, " \u2022 ", new Date(message.timestamp).toLocaleTimeString())), /* @__PURE__ */ React8.createElement(Box8, { paddingLeft: 2 }, message.metadata?.permissionDenied ? /* @__PURE__ */ React8.createElement(Text7, { color: "yellow" }, "\u26A0\uFE0F ", message.content) : /* @__PURE__ */ React8.createElement(Text7, null, message.content)), message.metadata?.steps && message.metadata.steps.length > 0 && /* @__PURE__ */ React8.createElement(Box8, { paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Text7, { dimColor: true, bold: true }, "\u{1F527} Agent Reasoning Trace (", message.metadata.steps.filter((s) => s.type === "action").length, " ", "tools used, ", message.metadata.steps.length, " total steps)", message.metadata.tokenUsage && ` \u2022 ${message.metadata.tokenUsage.total} tokens`), /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, "Step types: ", message.metadata.steps.map((s) => s.type).join(", ")), message.metadata.steps.map((step, idx) => {
1043
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Box9, null, /* @__PURE__ */ React9.createElement(Text8, { bold: true, color: message.role === "user" ? "cyan" : "green" }, message.role === "user" ? "\u{1F464} You" : "\u{1F916} Assistant"), /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, " \u2022 ", new Date(message.timestamp).toLocaleTimeString())), /* @__PURE__ */ React9.createElement(Box9, { paddingLeft: 2 }, message.metadata?.permissionDenied ? /* @__PURE__ */ React9.createElement(Text8, { color: "yellow" }, "\u26A0\uFE0F ", message.content) : /* @__PURE__ */ React9.createElement(Text8, null, message.content)), message.metadata?.steps && message.metadata.steps.length > 0 && /* @__PURE__ */ React9.createElement(Box9, { paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true, bold: true }, "\u{1F527} Agent Reasoning Trace (", message.metadata.steps.filter((s) => s.type === "action").length, " ", "tools used, ", message.metadata.steps.length, " total steps)", message.metadata.tokenUsage && ` \u2022 ${message.metadata.tokenUsage.total} tokens`), /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "Step types: ", message.metadata.steps.map((s) => s.type).join(", ")), message.metadata.steps.map((step, idx) => {
832
1044
  if (step.type === "thought") {
833
- return /* @__PURE__ */ React8.createElement(Box8, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Text7, { color: "blue" }, "\u{1F4AD} Thought:"), /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, ` ${step.content.slice(0, 200)}${step.content.length > 200 ? "..." : ""}`));
1045
+ return /* @__PURE__ */ React9.createElement(Box9, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Text8, { color: "blue" }, "\u{1F4AD} Thought:"), /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, ` ${step.content.slice(0, 200)}${step.content.length > 200 ? "..." : ""}`));
834
1046
  }
835
1047
  if (step.type === "action") {
836
1048
  const toolName = step.metadata?.toolName || "unknown";
837
1049
  const toolInput = step.metadata?.toolInput;
838
1050
  const observationStep = message.metadata.steps[idx + 1];
839
1051
  const result = observationStep?.type === "observation" ? observationStep.content : null;
840
- return /* @__PURE__ */ React8.createElement(Box8, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Text7, { color: "yellow" }, "\u{1F527} Action: ", toolName), toolInput && /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, ` Input: ${typeof toolInput === "string" ? toolInput : JSON.stringify(toolInput).slice(0, 100)}`), result && /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, ` Result: ${typeof result === "string" ? result.slice(0, 200) : JSON.stringify(result).slice(0, 200)}${(typeof result === "string" ? result.length : JSON.stringify(result).length) > 200 ? "..." : ""}`));
1052
+ return /* @__PURE__ */ React9.createElement(Box9, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Text8, { color: "yellow" }, "\u{1F527} Action: ", toolName), toolInput && /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, ` Input: ${typeof toolInput === "string" ? toolInput : JSON.stringify(toolInput).slice(0, 100)}`), result && /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, ` Result: ${typeof result === "string" ? result.slice(0, 200) : JSON.stringify(result).slice(0, 200)}${(typeof result === "string" ? result.length : JSON.stringify(result).length) > 200 ? "..." : ""}`));
841
1053
  }
842
1054
  return null;
843
- }).filter(Boolean)), message.metadata?.tokenUsage && (!message.metadata.steps || message.metadata.steps.length === 0) && /* @__PURE__ */ React8.createElement(Box8, { paddingLeft: 2 }, /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, `${message.metadata.tokenUsage.total} tokens`)));
1055
+ }).filter(Boolean)), message.metadata?.tokenUsage && (!message.metadata.steps || message.metadata.steps.length === 0) && /* @__PURE__ */ React9.createElement(Box9, { paddingLeft: 2 }, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, `${message.metadata.tokenUsage.total} tokens`)));
844
1056
  }
845
1057
 
846
1058
  // src/components/MessageList.tsx
847
- import React9 from "react";
848
- import { Box as Box9, Text as Text8 } from "ink";
1059
+ import React10 from "react";
1060
+ import { Box as Box10, Text as Text9 } from "ink";
849
1061
  function stripThinkingTags(content) {
850
1062
  return content.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
851
1063
  }
852
- var MessageList = React9.memo(
1064
+ var MessageList = React10.memo(
853
1065
  function MessageList2({ messages }) {
854
1066
  if (messages.length === 0) {
855
- return /* @__PURE__ */ React9.createElement(Box9, { paddingY: 1 }, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "No messages yet. Type a message to start!"));
1067
+ return /* @__PURE__ */ React10.createElement(Box10, { paddingY: 1 }, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, "No messages yet. Type a message to start!"));
856
1068
  }
857
- return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", gap: 1, paddingY: 1 }, messages.map((message, index) => /* @__PURE__ */ React9.createElement(Box9, { key: index, flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Box9, null, /* @__PURE__ */ React9.createElement(Text8, { bold: true, color: message.role === "user" ? "cyan" : "green" }, message.role === "user" ? "\u{1F464} You" : "\u{1F916} Assistant"), /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, " \u2022 ", new Date(message.timestamp).toLocaleTimeString())), /* @__PURE__ */ React9.createElement(Box9, { paddingLeft: 2 }, message.metadata?.permissionDenied ? /* @__PURE__ */ React9.createElement(Text8, { color: "yellow" }, "\u26A0\uFE0F ", stripThinkingTags(message.content)) : /* @__PURE__ */ React9.createElement(Text8, null, stripThinkingTags(message.content))), message.metadata?.steps && message.metadata.steps.length > 0 && /* @__PURE__ */ React9.createElement(Box9, { paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true, bold: true }, "\u{1F527} Agent Reasoning Trace (", message.metadata.steps.filter((s) => s.type === "action").length, " tools used,", " ", message.metadata.steps.length, " total steps)", message.metadata.tokenUsage && ` \u2022 ${message.metadata.tokenUsage.total} tokens`), /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "Step types: ", message.metadata.steps.map((s) => s.type).join(", ")), message.metadata.steps.map((step, idx) => {
1069
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", gap: 1, paddingY: 1 }, messages.map((message, index) => /* @__PURE__ */ React10.createElement(Box10, { key: index, flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Text9, { bold: true, color: message.role === "user" ? "cyan" : "green" }, message.role === "user" ? "\u{1F464} You" : "\u{1F916} Assistant"), /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, " \u2022 ", new Date(message.timestamp).toLocaleTimeString())), /* @__PURE__ */ React10.createElement(Box10, { paddingLeft: 2 }, message.metadata?.permissionDenied ? /* @__PURE__ */ React10.createElement(Text9, { color: "yellow" }, "\u26A0\uFE0F ", stripThinkingTags(message.content)) : /* @__PURE__ */ React10.createElement(Text9, null, stripThinkingTags(message.content))), message.metadata?.steps && message.metadata.steps.length > 0 && /* @__PURE__ */ React10.createElement(Box10, { paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true, bold: true }, "\u{1F527} Agent Reasoning Trace (", message.metadata.steps.filter((s) => s.type === "action").length, " tools used,", " ", message.metadata.steps.length, " total steps)", message.metadata.tokenUsage && ` \u2022 ${message.metadata.tokenUsage.total} tokens`), /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, "Step types: ", message.metadata.steps.map((s) => s.type).join(", ")), message.metadata.steps.map((step, idx) => {
858
1070
  if (step.type === "thought") {
859
- return /* @__PURE__ */ React9.createElement(Box9, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Text8, { color: "blue" }, "\u{1F4AD} Thought:"), /* @__PURE__ */ React9.createElement(
860
- Text8,
1071
+ return /* @__PURE__ */ React10.createElement(Box10, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text9, { color: "blue" }, "\u{1F4AD} Thought:"), /* @__PURE__ */ React10.createElement(
1072
+ Text9,
861
1073
  {
862
1074
  dimColor: true
863
1075
  },
@@ -869,10 +1081,10 @@ var MessageList = React9.memo(
869
1081
  const toolInput = step.metadata?.toolInput;
870
1082
  const observationStep = message.metadata.steps[idx + 1];
871
1083
  const result = observationStep?.type === "observation" ? observationStep.content : null;
872
- return /* @__PURE__ */ React9.createElement(Box9, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Text8, { color: "yellow" }, "\u{1F527} Action: ", toolName), toolInput && /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, ` Input: ${typeof toolInput === "string" ? toolInput : JSON.stringify(toolInput).slice(0, 100)}`), result && /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, ` Result: ${typeof result === "string" ? result.slice(0, 200) : JSON.stringify(result).slice(0, 200)}${(typeof result === "string" ? result.length : JSON.stringify(result).length) > 200 ? "..." : ""}`));
1084
+ return /* @__PURE__ */ React10.createElement(Box10, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text9, { color: "yellow" }, "\u{1F527} Action: ", toolName), toolInput && /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, ` Input: ${typeof toolInput === "string" ? toolInput : JSON.stringify(toolInput).slice(0, 100)}`), result && /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, ` Result: ${typeof result === "string" ? result.slice(0, 200) : JSON.stringify(result).slice(0, 200)}${(typeof result === "string" ? result.length : JSON.stringify(result).length) > 200 ? "..." : ""}`));
873
1085
  }
874
1086
  return null;
875
- }).filter(Boolean)), message.metadata?.tokenUsage && (!message.metadata.steps || message.metadata.steps.length === 0) && /* @__PURE__ */ React9.createElement(Box9, { paddingLeft: 2 }, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, `${message.metadata.tokenUsage.total} tokens`)))));
1087
+ }).filter(Boolean)), message.metadata?.tokenUsage && (!message.metadata.steps || message.metadata.steps.length === 0) && /* @__PURE__ */ React10.createElement(Box10, { paddingLeft: 2 }, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, `${message.metadata.tokenUsage.total} tokens`)))));
876
1088
  },
877
1089
  (prevProps, nextProps) => {
878
1090
  if (prevProps.messages.length !== nextProps.messages.length) {
@@ -883,8 +1095,8 @@ var MessageList = React9.memo(
883
1095
  );
884
1096
 
885
1097
  // src/components/LoginFlow.tsx
886
- import React10, { useState as useState2, useEffect as useEffect2 } from "react";
887
- import { Box as Box10, Text as Text9 } from "ink";
1098
+ import React11, { useState as useState3, useEffect as useEffect2 } from "react";
1099
+ import { Box as Box11, Text as Text10 } from "ink";
888
1100
  import Spinner2 from "ink-spinner";
889
1101
  import jwt from "jsonwebtoken";
890
1102
  import open from "open";
@@ -1000,10 +1212,10 @@ var OAuthClient = class {
1000
1212
 
1001
1213
  // src/components/LoginFlow.tsx
1002
1214
  function LoginFlow({ apiUrl = "http://localhost:3000", configStore, onSuccess, onError }) {
1003
- const [status, setStatus] = useState2("initiating");
1004
- const [deviceFlow, setDeviceFlow] = useState2(null);
1005
- const [statusMessage, setStatusMessage] = useState2("Initiating device authorization...");
1006
- const [error, setError] = useState2(null);
1215
+ const [status, setStatus] = useState3("initiating");
1216
+ const [deviceFlow, setDeviceFlow] = useState3(null);
1217
+ const [statusMessage, setStatusMessage] = useState3("Initiating device authorization...");
1218
+ const [error, setError] = useState3(null);
1007
1219
  useEffect2(() => {
1008
1220
  const runLoginFlow = async () => {
1009
1221
  const oauth = new OAuthClient(apiUrl);
@@ -1047,15 +1259,15 @@ function LoginFlow({ apiUrl = "http://localhost:3000", configStore, onSuccess, o
1047
1259
  }
1048
1260
  }, [deviceFlow, status]);
1049
1261
  if (status === "initiating") {
1050
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Text9, { color: "cyan" }, /* @__PURE__ */ React10.createElement(Spinner2, { type: "dots" }), " Initiating device authorization...")));
1262
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Text10, { color: "cyan" }, /* @__PURE__ */ React11.createElement(Spinner2, { type: "dots" }), " Initiating device authorization...")));
1051
1263
  }
1052
1264
  if (status === "error") {
1053
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text9, { color: "red", bold: true }, "\u2716 Authentication Failed")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Text9, { color: "red" }, error)));
1265
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React11.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text10, { color: "red", bold: true }, "\u2716 Authentication Failed")), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Text10, { color: "red" }, error)));
1054
1266
  }
1055
1267
  if (status === "success") {
1056
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text9, { color: "green", bold: true }, "\u2714 Successfully authenticated!")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, "You can now use B4M CLI with your account.")));
1268
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React11.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text10, { color: "green", bold: true }, "\u2714 Successfully authenticated!")), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "You can now use B4M CLI with your account.")));
1057
1269
  }
1058
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan" }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text9, { color: "cyan", bold: true }, "\u{1F510} Device Authorization")), /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text9, null, "Opening browser automatically... If it doesn't open, please visit:")), /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React10.createElement(Text9, { color: "blue", bold: true }, deviceFlow?.verification_uri)), /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text9, null, "And enter this code when prompted:")), /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React10.createElement(Text9, { color: "yellow", bold: true }, deviceFlow?.user_code)), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text9, { color: "cyan" }, /* @__PURE__ */ React10.createElement(Spinner2, { type: "dots" }), " ", statusMessage)), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, "Expires in ", deviceFlow ? Math.floor(deviceFlow.expires_in / 60) : 0, " minutes")));
1270
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan" }, /* @__PURE__ */ React11.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text10, { color: "cyan", bold: true }, "\u{1F510} Device Authorization")), /* @__PURE__ */ React11.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text10, null, "Opening browser automatically... If it doesn't open, please visit:")), /* @__PURE__ */ React11.createElement(Box11, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React11.createElement(Text10, { color: "blue", bold: true }, deviceFlow?.verification_uri)), /* @__PURE__ */ React11.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text10, null, "And enter this code when prompted:")), /* @__PURE__ */ React11.createElement(Box11, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React11.createElement(Text10, { color: "yellow", bold: true }, deviceFlow?.user_code)), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text10, { color: "cyan" }, /* @__PURE__ */ React11.createElement(Spinner2, { type: "dots" }), " ", statusMessage)), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "Expires in ", deviceFlow ? Math.floor(deviceFlow.expires_in / 60) : 0, " minutes")));
1059
1271
  }
1060
1272
 
1061
1273
  // src/storage/SessionStore.ts
@@ -1215,7 +1427,8 @@ var CliConfigSchema = z.object({
1215
1427
  temperature: z.number(),
1216
1428
  autoSave: z.boolean(),
1217
1429
  theme: z.enum(["light", "dark"]),
1218
- exportFormat: z.enum(["markdown", "json"])
1430
+ exportFormat: z.enum(["markdown", "json"]),
1431
+ maxIterations: z.number().nullable().default(10)
1219
1432
  }),
1220
1433
  tools: z.object({
1221
1434
  enabled: z.array(z.string()),
@@ -1238,7 +1451,8 @@ var DEFAULT_CONFIG = {
1238
1451
  temperature: 0.7,
1239
1452
  autoSave: true,
1240
1453
  theme: "dark",
1241
- exportFormat: "markdown"
1454
+ exportFormat: "markdown",
1455
+ maxIterations: 10
1242
1456
  },
1243
1457
  tools: {
1244
1458
  enabled: [],
@@ -9183,7 +9397,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
9183
9397
  // package.json
9184
9398
  var package_default = {
9185
9399
  name: "@bike4mind/cli",
9186
- version: "0.2.3-feat-cli-clear-command.17058+9fe45e4bf",
9400
+ version: "0.2.3-feat-cli-interactive-config-editor.17058+291ffcbb6",
9187
9401
  type: "module",
9188
9402
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
9189
9403
  license: "UNLICENSED",
@@ -9285,10 +9499,10 @@ var package_default = {
9285
9499
  },
9286
9500
  devDependencies: {
9287
9501
  "@bike4mind/agents": "0.1.0",
9288
- "@bike4mind/common": "2.37.1-feat-cli-clear-command.17058+9fe45e4bf",
9289
- "@bike4mind/mcp": "1.19.5-feat-cli-clear-command.17058+9fe45e4bf",
9290
- "@bike4mind/services": "2.31.1-feat-cli-clear-command.17058+9fe45e4bf",
9291
- "@bike4mind/utils": "2.0.4-feat-cli-clear-command.17058+9fe45e4bf",
9502
+ "@bike4mind/common": "2.37.1-feat-cli-interactive-config-editor.17058+291ffcbb6",
9503
+ "@bike4mind/mcp": "1.19.5-feat-cli-interactive-config-editor.17058+291ffcbb6",
9504
+ "@bike4mind/services": "2.31.1-feat-cli-interactive-config-editor.17058+291ffcbb6",
9505
+ "@bike4mind/utils": "2.0.4-feat-cli-interactive-config-editor.17058+291ffcbb6",
9292
9506
  "@types/diff": "^5.0.9",
9293
9507
  "@types/jsonwebtoken": "^9.0.4",
9294
9508
  "@types/node": "^22.9.0",
@@ -9300,7 +9514,7 @@ var package_default = {
9300
9514
  typescript: "^5.9.3",
9301
9515
  vitest: "^3.2.4"
9302
9516
  },
9303
- gitHead: "9fe45e4bfb34840cd5b5cb738bb276b0520e89c6"
9517
+ gitHead: "291ffcbb62b8a9f48f7f9bc29a5be2750818a147"
9304
9518
  };
9305
9519
 
9306
9520
  // src/config/constants.ts
@@ -9321,7 +9535,7 @@ var EXIT_TIMEOUT_MS = 2e3;
9321
9535
  var usageCache = null;
9322
9536
  function CliApp() {
9323
9537
  const { exit } = useApp();
9324
- const [state, setState] = useState3({
9538
+ const [state, setState] = useState4({
9325
9539
  session: null,
9326
9540
  sessionStore: new SessionStore(),
9327
9541
  configStore: new ConfigStore(),
@@ -9331,11 +9545,12 @@ function CliApp() {
9331
9545
  permissionManager: null,
9332
9546
  permissionPrompt: null
9333
9547
  });
9334
- const [isInitialized, setIsInitialized] = useState3(false);
9335
- const [initError, setInitError] = useState3(null);
9336
- const [commandHistory, setCommandHistory] = useState3([]);
9548
+ const [isInitialized, setIsInitialized] = useState4(false);
9549
+ const [initError, setInitError] = useState4(null);
9550
+ const [commandHistory, setCommandHistory] = useState4([]);
9337
9551
  const setStoreSession = useCliStore((state2) => state2.setSession);
9338
9552
  const setPermissionPrompt = useCliStore((state2) => state2.setPermissionPrompt);
9553
+ const setShowConfigEditor = useCliStore((state2) => state2.setShowConfigEditor);
9339
9554
  const setExitRequested = useCliStore((state2) => state2.setExitRequested);
9340
9555
  const performCleanup = useCallback(async () => {
9341
9556
  const cleanupTasks = [];
@@ -9365,7 +9580,7 @@ function CliApp() {
9365
9580
  process.exit(0);
9366
9581
  }, 100);
9367
9582
  }, [state.session, state.sessionStore, state.mcpManager, state.agent]);
9368
- useInput2((input, key) => {
9583
+ useInput3((input, key) => {
9369
9584
  if (key.ctrl && input === "c") {
9370
9585
  const now = Date.now();
9371
9586
  if (exitTimestamp && now - exitTimestamp < EXIT_TIMEOUT_MS) {
@@ -9562,13 +9777,14 @@ EXAMPLES:
9562
9777
  - "what packages installed?" \u2192 glob_files "**/package.json" \u2192 file_read
9563
9778
 
9564
9779
  Remember: Use context from previous messages to understand follow-up questions.`;
9780
+ const maxIterations = config.preferences.maxIterations === null ? 999999 : config.preferences.maxIterations;
9565
9781
  const agent = new ReActAgent({
9566
9782
  userId: config.userId,
9567
9783
  logger: silentLogger,
9568
9784
  llm,
9569
9785
  model: modelInfo.id,
9570
9786
  tools: allTools,
9571
- maxIterations: 10,
9787
+ maxIterations,
9572
9788
  maxTokens: config.preferences.maxTokens,
9573
9789
  temperature: config.preferences.temperature,
9574
9790
  systemPrompt: cliSystemPrompt
@@ -9680,7 +9896,6 @@ Remember: Use context from previous messages to understand follow-up questions.`
9680
9896
  Available commands:
9681
9897
  /help - Show this help message
9682
9898
  /exit - Exit the CLI
9683
- /clear - Start a new session
9684
9899
  /login - Authenticate with your B4M account
9685
9900
  /logout - Clear authentication and sign out
9686
9901
  /whoami - Show current authenticated user
@@ -9726,20 +9941,7 @@ Tool Permissions:
9726
9941
  console.log("");
9727
9942
  break;
9728
9943
  case "config": {
9729
- const config = await state.configStore.get();
9730
- console.log("\n\u2699\uFE0F Configuration:\n");
9731
- console.log(`Default Model: ${config.defaultModel}`);
9732
- console.log(`Max Tokens: ${config.preferences.maxTokens}`);
9733
- console.log(`Temperature: ${config.preferences.temperature}`);
9734
- const apiUrl = getApiUrl(config.apiConfig);
9735
- const apiType = getEnvironmentName(config.apiConfig);
9736
- console.log(`API: ${apiType} (${apiUrl})`);
9737
- console.log("");
9738
- console.log("Related commands:");
9739
- console.log(" /api-info - Show detailed API configuration");
9740
- console.log(" /set-api - Connect to self-hosted instance");
9741
- console.log(" /reset-api - Reset to Bike4Mind main service");
9742
- console.log("");
9944
+ setShowConfigEditor(true);
9743
9945
  break;
9744
9946
  }
9745
9947
  case "set-api": {
@@ -9855,35 +10057,6 @@ Tool Permissions:
9855
10057
  console.log(`Expires: ${new Date(authTokens.expiresAt).toLocaleString()}`);
9856
10058
  console.log("");
9857
10059
  break;
9858
- case "clear":
9859
- case "new": {
9860
- console.clear();
9861
- const model = state.session?.model || state.config?.defaultModel || "claude-sonnet";
9862
- const newSession = {
9863
- id: uuidv49(),
9864
- name: `Session ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
9865
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
9866
- updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
9867
- model,
9868
- messages: [],
9869
- metadata: {
9870
- totalTokens: 0,
9871
- totalCost: 0,
9872
- toolCallCount: 0
9873
- }
9874
- };
9875
- await logger.initialize(newSession.id);
9876
- logger.debug("=== New Session Started via /clear ===");
9877
- setState((prev) => ({ ...prev, session: newSession }));
9878
- setStoreSession(newSession);
9879
- useCliStore.getState().clearAgentSteps();
9880
- usageCache = null;
9881
- console.log("New session started.");
9882
- console.log(`
9883
- \u{1F4DD} Session: ${newSession.name} | \u{1F916} Model: ${newSession.model} | \u{1F4CA} Tokens: 0
9884
- `);
9885
- break;
9886
- }
9887
10060
  case "usage": {
9888
10061
  const usageAuthTokens = await state.configStore.getAuthTokens();
9889
10062
  if (!usageAuthTokens || new Date(usageAuthTokens.expiresAt) <= /* @__PURE__ */ new Date()) {
@@ -9986,12 +10159,16 @@ No usage data available for the last ${USAGE_DAYS} days.`);
9986
10159
  console.log("Type /help for available commands");
9987
10160
  }
9988
10161
  };
10162
+ const handleSaveConfig = async (updatedConfig) => {
10163
+ await state.configStore.save(updatedConfig);
10164
+ setState((prev) => ({ ...prev, config: updatedConfig }));
10165
+ };
9989
10166
  if (initError) {
9990
- return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React11.createElement(Text10, { color: "red", bold: true }, "\u274C Initialization Error"), /* @__PURE__ */ React11.createElement(Text10, null, initError), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "\n", "Tip: Run /config to set up your API keys"));
10167
+ return /* @__PURE__ */ React12.createElement(Box12, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React12.createElement(Text11, { color: "red", bold: true }, "\u274C Initialization Error"), /* @__PURE__ */ React12.createElement(Text11, null, initError), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "\n", "Tip: Run /config to set up your API keys"));
9991
10168
  }
9992
10169
  if (state.showLoginFlow) {
9993
10170
  const loginApiUrl = getApiUrl(state.config?.apiConfig);
9994
- return /* @__PURE__ */ React11.createElement(
10171
+ return /* @__PURE__ */ React12.createElement(
9995
10172
  LoginFlow,
9996
10173
  {
9997
10174
  apiUrl: loginApiUrl,
@@ -10014,14 +10191,16 @@ No usage data available for the last ${USAGE_DAYS} days.`);
10014
10191
  );
10015
10192
  }
10016
10193
  if (!isInitialized) {
10017
- return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React11.createElement(Text10, null, "\u{1F680} Initializing..."));
10194
+ return /* @__PURE__ */ React12.createElement(Box12, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React12.createElement(Text11, null, "\u{1F680} Initializing..."));
10018
10195
  }
10019
- return /* @__PURE__ */ React11.createElement(
10196
+ return /* @__PURE__ */ React12.createElement(
10020
10197
  App,
10021
10198
  {
10022
10199
  onMessage: handleMessage,
10023
10200
  onCommand: handleCommand,
10024
10201
  commandHistory,
10202
+ config: state.config,
10203
+ onSaveConfig: handleSaveConfig,
10025
10204
  onPermissionResponse: (response) => {
10026
10205
  if (state.permissionPrompt) {
10027
10206
  state.permissionPrompt.resolve({ action: response });
@@ -10047,6 +10226,6 @@ var isDevMode = import.meta.url.includes("/src/") || process.env.NODE_ENV === "d
10047
10226
  if (isDevMode) {
10048
10227
  console.log("\u{1F527} Running in development mode (using TypeScript source)\n");
10049
10228
  }
10050
- render(/* @__PURE__ */ React11.createElement(CliApp, null), {
10229
+ render(/* @__PURE__ */ React12.createElement(CliApp, null), {
10051
10230
  exitOnCtrlC: false
10052
10231
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.3-feat-cli-clear-command.17058+9fe45e4bf",
3
+ "version": "0.2.3-feat-cli-interactive-config-editor.17058+291ffcbb6",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -102,10 +102,10 @@
102
102
  },
103
103
  "devDependencies": {
104
104
  "@bike4mind/agents": "0.1.0",
105
- "@bike4mind/common": "2.37.1-feat-cli-clear-command.17058+9fe45e4bf",
106
- "@bike4mind/mcp": "1.19.5-feat-cli-clear-command.17058+9fe45e4bf",
107
- "@bike4mind/services": "2.31.1-feat-cli-clear-command.17058+9fe45e4bf",
108
- "@bike4mind/utils": "2.0.4-feat-cli-clear-command.17058+9fe45e4bf",
105
+ "@bike4mind/common": "2.37.1-feat-cli-interactive-config-editor.17058+291ffcbb6",
106
+ "@bike4mind/mcp": "1.19.5-feat-cli-interactive-config-editor.17058+291ffcbb6",
107
+ "@bike4mind/services": "2.31.1-feat-cli-interactive-config-editor.17058+291ffcbb6",
108
+ "@bike4mind/utils": "2.0.4-feat-cli-interactive-config-editor.17058+291ffcbb6",
109
109
  "@types/diff": "^5.0.9",
110
110
  "@types/jsonwebtoken": "^9.0.4",
111
111
  "@types/node": "^22.9.0",
@@ -117,5 +117,5 @@
117
117
  "typescript": "^5.9.3",
118
118
  "vitest": "^3.2.4"
119
119
  },
120
- "gitHead": "9fe45e4bfb34840cd5b5cb738bb276b0520e89c6"
120
+ "gitHead": "291ffcbb62b8a9f48f7f9bc29a5be2750818a147"
121
121
  }