@bike4mind/cli 0.2.8-cli-bash-tools.17140 → 0.2.8-fix-cli-type-error.17148

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/index.js CHANGED
@@ -4,9 +4,9 @@ import {
4
4
  getEffectiveApiKey,
5
5
  getOpenWeatherKey,
6
6
  getSerperKey
7
- } from "./chunk-6S7HV2GF.js";
8
- import "./chunk-F2K7OCDJ.js";
9
- import "./chunk-RJYG7BUV.js";
7
+ } from "./chunk-3CCBDIFR.js";
8
+ import "./chunk-LIRY24M5.js";
9
+ import "./chunk-YXHQN7SK.js";
10
10
  import {
11
11
  BFLImageService,
12
12
  BaseStorage,
@@ -15,7 +15,7 @@ import {
15
15
  OpenAIBackend,
16
16
  OpenAIImageService,
17
17
  XAIImageService
18
- } from "./chunk-SE2T5GED.js";
18
+ } from "./chunk-DNSBC3LO.js";
19
19
  import {
20
20
  Logger
21
21
  } from "./chunk-AMDXHL6S.js";
@@ -73,19 +73,19 @@ import {
73
73
  XAI_IMAGE_MODELS,
74
74
  b4mLLMTools,
75
75
  getMcpProviderMetadata
76
- } from "./chunk-HD4QQGS6.js";
76
+ } from "./chunk-H6SHASMZ.js";
77
77
  import {
78
78
  __require
79
79
  } from "./chunk-PDX44BCA.js";
80
80
 
81
81
  // src/index.tsx
82
- import React14, { useState as useState5, useEffect as useEffect3, useCallback, useRef } from "react";
83
- import { render, Box as Box14, Text as Text13, useApp, useInput as useInput4 } from "ink";
82
+ import React15, { useState as useState6, useEffect as useEffect3, useCallback, useRef } from "react";
83
+ import { render, Box as Box14, Text as Text14, useApp, useInput as useInput5 } from "ink";
84
84
  import { v4 as uuidv49 } from "uuid";
85
85
 
86
86
  // src/components/App.tsx
87
- import React9 from "react";
88
- import { Box as Box9, Text as Text8 } from "ink";
87
+ import React10 from "react";
88
+ import { Box as Box9, Text as Text9, Static } from "ink";
89
89
 
90
90
  // src/components/StatusBar.tsx
91
91
  import React from "react";
@@ -95,27 +95,127 @@ var StatusBar = React.memo(function StatusBar2({ sessionName, model, tokenUsage
95
95
  });
96
96
 
97
97
  // src/components/InputPrompt.tsx
98
- import React4, { useState, useMemo, useEffect } from "react";
99
- import { Box as Box4, Text as Text4, useInput } from "ink";
100
- import TextInput from "ink-text-input";
98
+ import React5, { useState as useState2, useMemo, useEffect } from "react";
99
+ import { Box as Box4, Text as Text5, useInput as useInput2 } from "ink";
100
+
101
+ // src/components/CustomTextInput.tsx
102
+ import React2, { useState } from "react";
103
+ import { Text as Text2, useInput } from "ink";
104
+ function CustomTextInput({
105
+ value,
106
+ onChange,
107
+ onSubmit,
108
+ placeholder = "",
109
+ showCursor = true
110
+ }) {
111
+ const [cursorOffset, setCursorOffset] = useState(value.length);
112
+ useInput(
113
+ (input, key) => {
114
+ if (key.return && !key.meta && !key.shift) {
115
+ onSubmit(value);
116
+ return;
117
+ }
118
+ if (key.ctrl) {
119
+ switch (input) {
120
+ case "u":
121
+ {
122
+ const lines = value.split("\n");
123
+ let currentLineStart = 0;
124
+ let currentLineIndex = 0;
125
+ let charCount = 0;
126
+ for (let i = 0; i < lines.length; i++) {
127
+ const lineLength = lines[i].length;
128
+ if (charCount + lineLength >= cursorOffset) {
129
+ currentLineIndex = i;
130
+ currentLineStart = charCount;
131
+ break;
132
+ }
133
+ charCount += lineLength + 1;
134
+ }
135
+ lines.splice(currentLineIndex, 1);
136
+ const newValue = lines.join("\n");
137
+ onChange(newValue);
138
+ setCursorOffset(Math.min(currentLineStart, newValue.length));
139
+ }
140
+ return;
141
+ case "k":
142
+ onChange(value.slice(0, cursorOffset));
143
+ return;
144
+ case "w":
145
+ {
146
+ const beforeCursor2 = value.slice(0, cursorOffset);
147
+ const afterCursor2 = value.slice(cursorOffset);
148
+ const trimmed = beforeCursor2.trimEnd();
149
+ const lastSpace = trimmed.lastIndexOf(" ");
150
+ const newBefore = lastSpace === -1 ? "" : trimmed.slice(0, lastSpace + 1);
151
+ const newValue = newBefore + afterCursor2;
152
+ onChange(newValue);
153
+ setCursorOffset(newBefore.length);
154
+ }
155
+ return;
156
+ case "a":
157
+ setCursorOffset(0);
158
+ return;
159
+ case "e":
160
+ setCursorOffset(value.length);
161
+ return;
162
+ case "l":
163
+ onChange("");
164
+ return;
165
+ }
166
+ }
167
+ if (key.backspace || key.delete) {
168
+ if (cursorOffset > 0) {
169
+ const newValue = value.slice(0, cursorOffset - 1) + value.slice(cursorOffset);
170
+ onChange(newValue);
171
+ setCursorOffset(cursorOffset - 1);
172
+ }
173
+ return;
174
+ }
175
+ if (key.leftArrow) {
176
+ setCursorOffset(Math.max(0, cursorOffset - 1));
177
+ return;
178
+ }
179
+ if (key.rightArrow) {
180
+ setCursorOffset(Math.min(value.length, cursorOffset + 1));
181
+ return;
182
+ }
183
+ if (!key.ctrl && !key.meta && input.length === 1) {
184
+ const sanitizedInput = input === "\r" ? "\n" : input;
185
+ const newValue = value.slice(0, cursorOffset) + sanitizedInput + value.slice(cursorOffset);
186
+ onChange(newValue);
187
+ setCursorOffset(cursorOffset + 1);
188
+ }
189
+ },
190
+ { isActive: true }
191
+ );
192
+ const hasValue = value.length > 0;
193
+ if (!hasValue) {
194
+ return /* @__PURE__ */ React2.createElement(Text2, null, showCursor ? /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Text2, { inverse: true }, " "), /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, placeholder)) : /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, placeholder));
195
+ }
196
+ const beforeCursor = value.slice(0, cursorOffset);
197
+ const cursorChar = value[cursorOffset] || " ";
198
+ const afterCursor = value.slice(cursorOffset + 1);
199
+ return /* @__PURE__ */ React2.createElement(Text2, null, beforeCursor, showCursor && /* @__PURE__ */ React2.createElement(Text2, { inverse: true }, cursorChar), !showCursor && cursorChar, afterCursor);
200
+ }
101
201
 
102
202
  // src/components/CommandAutocomplete.tsx
103
- import React2 from "react";
104
- import { Box as Box2, Text as Text2 } from "ink";
203
+ import React3 from "react";
204
+ import { Box as Box2, Text as Text3 } from "ink";
105
205
  function CommandAutocomplete({ commands, selectedIndex }) {
106
206
  if (commands.length === 0) {
107
- return /* @__PURE__ */ React2.createElement(Box2, { marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "No matching commands"));
207
+ return /* @__PURE__ */ React3.createElement(Box2, { marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "No matching commands"));
108
208
  }
109
- return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1 }, /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, commands.length === 1 ? "1 command" : `${commands.length} commands`, " \u2022 Use \u2191\u2193 to navigate, Enter to select")), commands.map((cmd, index) => {
209
+ return /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column", marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React3.createElement(Box2, { marginBottom: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, commands.length === 1 ? "1 command" : `${commands.length} commands`, " \u2022 Use \u2191\u2193 to navigate, Enter to select")), commands.map((cmd, index) => {
110
210
  const args = cmd.args ? ` ${cmd.args}` : "";
111
211
  const isSelected = index === selectedIndex;
112
- return /* @__PURE__ */ React2.createElement(Box2, { key: cmd.name, marginLeft: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: isSelected ? "cyan" : void 0, bold: isSelected }, isSelected ? "\u25B8 " : " ", "/", cmd.name, args, " - ", cmd.description));
212
+ return /* @__PURE__ */ React3.createElement(Box2, { key: cmd.name, marginLeft: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: isSelected ? "cyan" : void 0, bold: isSelected }, isSelected ? "\u25B8 " : " ", "/", cmd.name, args, " - ", cmd.description));
113
213
  }));
114
214
  }
115
215
 
116
216
  // src/components/FileAutocomplete.tsx
117
- import React3 from "react";
118
- import { Box as Box3, Text as Text3 } from "ink";
217
+ import React4 from "react";
218
+ import { Box as Box3, Text as Text4 } from "ink";
119
219
 
120
220
  // src/utils/fileSearch.ts
121
221
  import * as fs from "fs";
@@ -304,14 +404,14 @@ var MAX_FILE_SIZE = 10 * 1024 * 1024;
304
404
  // src/components/FileAutocomplete.tsx
305
405
  function FileAutocomplete({ files, selectedIndex, query }) {
306
406
  if (files.length === 0) {
307
- return /* @__PURE__ */ React3.createElement(Box3, { marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "No matching files", query ? ` for "${query}"` : ""));
407
+ return /* @__PURE__ */ React4.createElement(Box3, { marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, "No matching files", query ? ` for "${query}"` : ""));
308
408
  }
309
- return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React3.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, files.length === 1 ? "1 match" : `${files.length} matches`, " - Use up/down to navigate, Tab to select")), files.map((file, index) => {
409
+ return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React4.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, files.length === 1 ? "1 match" : `${files.length} matches`, " - Use up/down to navigate, Tab to select")), files.map((file, index) => {
310
410
  const isSelected = index === selectedIndex;
311
411
  const icon = file.isDirectory ? "[folder]" : "[file] ";
312
412
  const sizeDisplay = file.isDirectory ? "" : file.size !== void 0 ? ` (${formatFileSize(file.size)})` : "";
313
413
  const pathDisplay = file.isDirectory ? `${file.path}/` : file.path;
314
- return /* @__PURE__ */ React3.createElement(Box3, { key: file.path, marginLeft: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: isSelected ? "cyan" : void 0, bold: isSelected }, isSelected ? "> " : " "), /* @__PURE__ */ React3.createElement(Text3, { color: file.isDirectory ? "yellow" : isSelected ? "cyan" : void 0, bold: isSelected }, icon), /* @__PURE__ */ React3.createElement(Text3, { color: isSelected ? "cyan" : void 0, bold: isSelected }, " ", pathDisplay), /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, sizeDisplay));
414
+ return /* @__PURE__ */ React4.createElement(Box3, { key: file.path, marginLeft: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: isSelected ? "cyan" : void 0, bold: isSelected }, isSelected ? "> " : " "), /* @__PURE__ */ React4.createElement(Text4, { color: file.isDirectory ? "yellow" : isSelected ? "cyan" : void 0, bold: isSelected }, icon), /* @__PURE__ */ React4.createElement(Text4, { color: isSelected ? "cyan" : void 0, bold: isSelected }, " ", pathDisplay), /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, sizeDisplay));
315
415
  }));
316
416
  }
317
417
 
@@ -638,20 +738,18 @@ function InputPrompt({
638
738
  prefillInput,
639
739
  onPrefillConsumed
640
740
  }) {
641
- const [value, setValue] = useState("");
642
- const [selectedIndex, setSelectedIndex] = useState(0);
643
- const [historyIndex, setHistoryIndex] = useState(-1);
644
- const [tempInput, setTempInput] = useState("");
645
- const [inputKey, setInputKey] = useState(0);
741
+ const [value, setValue] = useState2("");
742
+ const [selectedIndex, setSelectedIndex] = useState2(0);
743
+ const [historyIndex, setHistoryIndex] = useState2(-1);
744
+ const [tempInput, setTempInput] = useState2("");
646
745
  useEffect(() => {
647
746
  if (prefillInput) {
648
747
  setValue(prefillInput);
649
- setInputKey((prev) => prev + 1);
650
748
  onPrefillConsumed?.();
651
749
  }
652
750
  }, [prefillInput, onPrefillConsumed]);
653
- const [fileAutocomplete, setFileAutocomplete] = useState(null);
654
- const [fileSelectedIndex, setFileSelectedIndex] = useState(0);
751
+ const [fileAutocomplete, setFileAutocomplete] = useState2(null);
752
+ const [fileSelectedIndex, setFileSelectedIndex] = useState2(0);
655
753
  const shouldShowCommandAutocomplete = value.startsWith("/") && !disabled && !fileAutocomplete?.active;
656
754
  const commandQuery = shouldShowCommandAutocomplete ? value.slice(1) : "";
657
755
  const filteredCommands = useMemo(() => {
@@ -668,7 +766,7 @@ function InputPrompt({
668
766
  useEffect(() => {
669
767
  setFileSelectedIndex(0);
670
768
  }, [filteredFiles]);
671
- useInput((input, key) => {
769
+ useInput2((_input, key) => {
672
770
  if (fileAutocomplete?.active && filteredFiles.length > 0) {
673
771
  if (key.upArrow) {
674
772
  setFileSelectedIndex((prev) => prev > 0 ? prev - 1 : filteredFiles.length - 1);
@@ -725,7 +823,6 @@ function InputPrompt({
725
823
  const pathToInsert = file.isDirectory ? `@${file.path}/` : `@${file.path}`;
726
824
  const newValue = beforeAt + pathToInsert + afterQuery;
727
825
  setValue(newValue);
728
- setInputKey((prev) => prev + 1);
729
826
  if (file.isDirectory) {
730
827
  setFileAutocomplete({
731
828
  active: true,
@@ -752,7 +849,6 @@ function InputPrompt({
752
849
  if (selectedCommand.args) {
753
850
  setValue(commandText + " ");
754
851
  setHistoryIndex(-1);
755
- setInputKey((prev) => prev + 1);
756
852
  return;
757
853
  }
758
854
  setValue("");
@@ -771,7 +867,6 @@ function InputPrompt({
771
867
  if (imageEvent && onImageDetected) {
772
868
  const placeholder = await onImageDetected(imageEvent.data);
773
869
  setValue(`${placeholder} `);
774
- setInputKey((prev) => prev + 1);
775
870
  return;
776
871
  }
777
872
  }
@@ -791,29 +886,28 @@ function InputPrompt({
791
886
  setFileAutocomplete(null);
792
887
  }
793
888
  };
794
- return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React4.createElement(Box4, null, /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: "cyan" }, "> "), /* @__PURE__ */ React4.createElement(
795
- TextInput,
889
+ return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { bold: true, color: "cyan" }, "> "), /* @__PURE__ */ React5.createElement(
890
+ CustomTextInput,
796
891
  {
797
- key: inputKey,
798
892
  value,
799
893
  onChange: handleChange,
800
894
  onSubmit: handleSubmit,
801
- placeholder: disabled ? "" : "Type your message, /help for commands, or @file to reference",
895
+ placeholder: disabled ? "Thinking..." : "Type your message, /help for commands, or @file to reference",
802
896
  showCursor: !disabled
803
897
  }
804
- )), shouldShowCommandAutocomplete && /* @__PURE__ */ React4.createElement(CommandAutocomplete, { commands: filteredCommands, selectedIndex }), fileAutocomplete?.active && /* @__PURE__ */ React4.createElement(FileAutocomplete, { files: filteredFiles, selectedIndex: fileSelectedIndex, query: fileAutocomplete.query }));
898
+ )), shouldShowCommandAutocomplete && /* @__PURE__ */ React5.createElement(CommandAutocomplete, { commands: filteredCommands, selectedIndex }), fileAutocomplete?.active && /* @__PURE__ */ React5.createElement(FileAutocomplete, { files: filteredFiles, selectedIndex: fileSelectedIndex, query: fileAutocomplete.query }));
805
899
  }
806
900
 
807
901
  // src/components/AgentThinking.tsx
808
- import React6 from "react";
902
+ import React7 from "react";
809
903
  import { Box as Box6 } from "ink";
810
904
 
811
905
  // src/components/ThoughtStream.tsx
812
- import React5 from "react";
813
- import { Box as Box5, Text as Text5 } from "ink";
906
+ import React6 from "react";
907
+ import { Box as Box5, Text as Text6 } from "ink";
814
908
  import Spinner from "ink-spinner";
815
- var ThoughtStream = React5.memo(function ThoughtStream2({ steps }) {
816
- return /* @__PURE__ */ React5.createElement(Box5, { flexDirection: "column", gap: 1 }, steps.map((step, index) => /* @__PURE__ */ React5.createElement(Box5, { key: index, flexDirection: "column" }, step.type === "thought" && /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { color: "magenta" }, "\u{1F914} Thought: "), /* @__PURE__ */ React5.createElement(Text5, null, step.content)), step.type === "action" && /* @__PURE__ */ React5.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { color: "yellow" }, "\u26A1 Action: "), /* @__PURE__ */ React5.createElement(Text5, { bold: true }, step.metadata?.toolName || "unknown")), step.metadata?.toolInput && /* @__PURE__ */ React5.createElement(Box5, { paddingLeft: 2 }, /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, JSON.stringify(step.metadata.toolInput, null, 2)))), step.type === "observation" && /* @__PURE__ */ React5.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { color: "blue" }, "\u{1F4CA} Observation: ")), /* @__PURE__ */ React5.createElement(Box5, { paddingLeft: 2 }, /* @__PURE__ */ React5.createElement(Text5, null, step.content))), step.type === "final_answer" && /* @__PURE__ */ React5.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { color: "green", bold: true }, "\u2705 Final Answer:", " ")), /* @__PURE__ */ React5.createElement(Box5, { paddingLeft: 2 }, /* @__PURE__ */ React5.createElement(Text5, null, step.content)), step.metadata?.tokenUsage && /* @__PURE__ */ React5.createElement(Box5, { paddingLeft: 2 }, /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, "(", step.metadata.tokenUsage.total, " tokens)"))))), !steps.some((s) => s.type === "final_answer") && /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { color: "yellow" }, /* @__PURE__ */ React5.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React5.createElement(Text5, null, " ", steps.length === 0 ? "Thinking..." : "Processing...")));
909
+ var ThoughtStream = React6.memo(function ThoughtStream2({ steps }) {
910
+ return /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column", gap: 1 }, steps.map((step, index) => /* @__PURE__ */ React6.createElement(Box5, { key: index, flexDirection: "column" }, step.type === "thought" && /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text6, { color: "magenta" }, "\u{1F914} Thought: "), /* @__PURE__ */ React6.createElement(Text6, null, step.content)), step.type === "action" && /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, "\u26A1 Action: "), /* @__PURE__ */ React6.createElement(Text6, { bold: true }, step.metadata?.toolName || "unknown")), step.metadata?.toolInput && /* @__PURE__ */ React6.createElement(Box5, { paddingLeft: 2 }, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, JSON.stringify(step.metadata.toolInput, null, 2)))), step.type === "observation" && /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text6, { color: "blue" }, "\u{1F4CA} Observation: ")), /* @__PURE__ */ React6.createElement(Box5, { paddingLeft: 2 }, /* @__PURE__ */ React6.createElement(Text6, null, step.content))), step.type === "final_answer" && /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column" }, /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text6, { color: "green", bold: true }, "\u2705 Final Answer:", " ")), /* @__PURE__ */ React6.createElement(Box5, { paddingLeft: 2 }, /* @__PURE__ */ React6.createElement(Text6, null, step.content)), step.metadata?.tokenUsage && /* @__PURE__ */ React6.createElement(Box5, { paddingLeft: 2 }, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "(", step.metadata.tokenUsage.total, " tokens)"))))), !steps.some((s) => s.type === "final_answer") && /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, /* @__PURE__ */ React6.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React6.createElement(Text6, null, " ", steps.length === 0 ? "Thinking..." : "Processing...")));
817
911
  });
818
912
 
819
913
  // src/store/index.ts
@@ -829,7 +923,6 @@ var useCliStore = create((set) => ({
829
923
  addAgentStep: (step) => set((state) => ({
830
924
  agentSteps: [...state.agentSteps, step]
831
925
  })),
832
- setAgentSteps: (steps) => set({ agentSteps: steps }),
833
926
  clearAgentSteps: () => set({ agentSteps: [] }),
834
927
  // Permission prompt
835
928
  permissionPrompt: null,
@@ -843,32 +936,32 @@ var useCliStore = create((set) => ({
843
936
  }));
844
937
 
845
938
  // src/components/AgentThinking.tsx
846
- var AgentThinking = React6.memo(function AgentThinking2() {
939
+ var AgentThinking = React7.memo(function AgentThinking2() {
847
940
  const isThinking = useCliStore((state) => state.isThinking);
848
941
  const agentSteps = useCliStore((state) => state.agentSteps);
849
942
  if (!isThinking) {
850
943
  return null;
851
944
  }
852
- return /* @__PURE__ */ React6.createElement(Box6, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React6.createElement(ThoughtStream, { steps: agentSteps }));
945
+ return /* @__PURE__ */ React7.createElement(Box6, { borderStyle: "single", borderColor: "yellow", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React7.createElement(ThoughtStream, { steps: agentSteps }));
853
946
  });
854
947
 
855
948
  // src/components/PermissionPrompt.tsx
856
- import React7 from "react";
857
- import { Box as Box7, Text as Text6 } from "ink";
949
+ import React8 from "react";
950
+ import { Box as Box7, Text as Text7 } from "ink";
858
951
  import SelectInput from "ink-select-input";
859
952
  function renderDiffPreview(preview) {
860
953
  const lines = preview.split("\n");
861
954
  return lines.map((line, index) => {
862
955
  if (line.startsWith("+")) {
863
- return /* @__PURE__ */ React7.createElement(Text6, { key: index, color: "green" }, line);
956
+ return /* @__PURE__ */ React8.createElement(Text7, { key: index, color: "green" }, line);
864
957
  }
865
958
  if (line.startsWith("-")) {
866
- return /* @__PURE__ */ React7.createElement(Text6, { key: index, color: "red" }, line);
959
+ return /* @__PURE__ */ React8.createElement(Text7, { key: index, color: "red" }, line);
867
960
  }
868
961
  if (line.startsWith("@@")) {
869
- return /* @__PURE__ */ React7.createElement(Text6, { key: index, color: "cyan" }, line);
962
+ return /* @__PURE__ */ React8.createElement(Text7, { key: index, color: "cyan" }, line);
870
963
  }
871
- return /* @__PURE__ */ React7.createElement(Text6, { key: index, dimColor: true }, line);
964
+ return /* @__PURE__ */ React8.createElement(Text7, { key: index, dimColor: true }, line);
872
965
  });
873
966
  }
874
967
  function PermissionPrompt({
@@ -888,12 +981,12 @@ function PermissionPrompt({
888
981
  { label: "\u2717 Deny", value: "deny" }
889
982
  ];
890
983
  const argsString = typeof args === "string" ? args : JSON.stringify(args, null, 2);
891
- 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) })));
984
+ return /* @__PURE__ */ React8.createElement(Box7, { flexDirection: "column", borderStyle: "bold", borderColor: "yellow", padding: 1, marginY: 1 }, /* @__PURE__ */ React8.createElement(Box7, null, /* @__PURE__ */ React8.createElement(Text7, { bold: true, color: "yellow" }, "\u26A0\uFE0F Permission Required")), /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, "Tool: "), /* @__PURE__ */ React8.createElement(Text7, { bold: true, color: "cyan" }, toolName)), toolDescription && /* @__PURE__ */ React8.createElement(Box7, null, /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, "Action: "), /* @__PURE__ */ React8.createElement(Text7, null, toolDescription)), /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Text7, { bold: true }, "Arguments:"), /* @__PURE__ */ React8.createElement(Box7, { paddingLeft: 2, flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, argsString))), preview && /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Text7, { bold: true }, "Preview:"), /* @__PURE__ */ React8.createElement(Box7, { borderStyle: "single", borderColor: "gray", paddingX: 1, flexDirection: "column" }, renderDiffPreview(preview))), !canBeTrusted && /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text7, { color: "red", dimColor: true }, "Note: This tool cannot be trusted due to its dangerous nature.")), /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(SelectInput, { items, onSelect: (item) => onResponse(item.value) })));
892
985
  }
893
986
 
894
987
  // src/components/ConfigEditor.tsx
895
- import React8, { useState as useState2, useMemo as useMemo2 } from "react";
896
- import { Box as Box8, Text as Text7, useInput as useInput2 } from "ink";
988
+ import React9, { useState as useState3, useMemo as useMemo2 } from "react";
989
+ import { Box as Box8, Text as Text8, useInput as useInput3 } from "ink";
897
990
  var MAX_ITERATIONS_OPTIONS = [
898
991
  { label: "10", value: 10 },
899
992
  { label: "20", value: 20 },
@@ -1024,10 +1117,10 @@ function buildConfigItems(availableModels) {
1024
1117
  return items;
1025
1118
  }
1026
1119
  function ConfigEditor({ config, availableModels, onSave, onClose }) {
1027
- const [selectedIndex, setSelectedIndex] = useState2(0);
1028
- const [editedConfig, setEditedConfig] = useState2(config);
1029
- const [saveError, setSaveError] = useState2(null);
1030
- const [isSaving, setIsSaving] = useState2(false);
1120
+ const [selectedIndex, setSelectedIndex] = useState3(0);
1121
+ const [editedConfig, setEditedConfig] = useState3(config);
1122
+ const [saveError, setSaveError] = useState3(null);
1123
+ const [isSaving, setIsSaving] = useState3(false);
1031
1124
  const configItems = useMemo2(() => buildConfigItems(availableModels), [availableModels]);
1032
1125
  const hasChanges = useMemo2(() => {
1033
1126
  return JSON.stringify(config.preferences) !== JSON.stringify(editedConfig.preferences) || config.defaultModel !== editedConfig.defaultModel;
@@ -1047,7 +1140,7 @@ function ConfigEditor({ config, availableModels, onSave, onClose }) {
1047
1140
  }
1048
1141
  onClose();
1049
1142
  };
1050
- useInput2((input, key) => {
1143
+ useInput3((input, key) => {
1051
1144
  const currentItem = configItems[selectedIndex];
1052
1145
  if (key.upArrow) {
1053
1146
  setSelectedIndex((prev) => prev > 0 ? prev - 1 : configItems.length - 1);
@@ -1112,13 +1205,13 @@ function ConfigEditor({ config, availableModels, onSave, onClose }) {
1112
1205
  }
1113
1206
  return String(value);
1114
1207
  };
1115
- 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 }, configItems.map((item, index) => {
1208
+ return /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1, marginY: 1 }, /* @__PURE__ */ React9.createElement(Box8, { justifyContent: "space-between", marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text8, { bold: true, color: "cyan" }, "Settings"), isSaving ? /* @__PURE__ */ React9.createElement(Text8, { color: "yellow" }, "Saving...") : hasChanges ? /* @__PURE__ */ React9.createElement(Text8, { dimColor: true, color: "yellow" }, "(unsaved changes)") : null), saveError && /* @__PURE__ */ React9.createElement(Box8, { marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text8, { color: "red" }, "Error: ", saveError)), /* @__PURE__ */ React9.createElement(Box8, { flexDirection: "column", marginBottom: 1 }, configItems.map((item, index) => {
1116
1209
  const isSelected = index === selectedIndex;
1117
1210
  const value = item.getValue(editedConfig);
1118
1211
  const displayValue = formatValue(item, value);
1119
1212
  const hasOptions = item.type === "select" || item.type === "boolean" || item.type === "number";
1120
- 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 }, " >")));
1121
- })), /* @__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")));
1213
+ return /* @__PURE__ */ React9.createElement(Box8, { key: item.key }, /* @__PURE__ */ React9.createElement(Text8, { color: isSelected ? "cyan" : void 0 }, isSelected ? "> " : " "), /* @__PURE__ */ React9.createElement(Box8, { width: 18 }, /* @__PURE__ */ React9.createElement(Text8, { bold: isSelected, color: isSelected ? "white" : "gray" }, item.label, ":")), /* @__PURE__ */ React9.createElement(Box8, null, hasOptions && isSelected && /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "< "), /* @__PURE__ */ React9.createElement(Text8, { bold: isSelected, color: isSelected ? "green" : void 0 }, displayValue), hasOptions && isSelected && /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, " >")));
1214
+ })), /* @__PURE__ */ React9.createElement(Box8, { borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "\u2191/\u2193: Navigate | Space/\u2190/\u2192: Change | q/Esc: Save & Exit")));
1122
1215
  }
1123
1216
 
1124
1217
  // src/utils/processFileReferences.ts
@@ -1258,7 +1351,7 @@ function App({
1258
1351
  const setShowConfigEditor = useCliStore((state) => state.setShowConfigEditor);
1259
1352
  const exitRequested = useCliStore((state) => state.exitRequested);
1260
1353
  const setIsThinking = useCliStore((state) => state.setIsThinking);
1261
- const handleSubmit = React9.useCallback(
1354
+ const handleSubmit = React10.useCallback(
1262
1355
  async (input) => {
1263
1356
  const trimmed = input.trim();
1264
1357
  if (!trimmed) return;
@@ -1287,7 +1380,7 @@ ${errorBlock}`;
1287
1380
  },
1288
1381
  [onMessage, onCommand, setIsThinking]
1289
1382
  );
1290
- 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(
1383
+ return /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(StatusBar, { sessionName, model: currentModel, tokenUsage: totalTokens }), showConfigEditor && config && onSaveConfig ? /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React10.createElement(
1291
1384
  ConfigEditor,
1292
1385
  {
1293
1386
  config,
@@ -1295,7 +1388,7 @@ ${errorBlock}`;
1295
1388
  onSave: onSaveConfig,
1296
1389
  onClose: () => setShowConfigEditor(false)
1297
1390
  }
1298
- )) : permissionPrompt ? /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React9.createElement(
1391
+ )) : permissionPrompt ? /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React10.createElement(
1299
1392
  PermissionPrompt,
1300
1393
  {
1301
1394
  toolName: permissionPrompt.toolName,
@@ -1304,7 +1397,7 @@ ${errorBlock}`;
1304
1397
  canBeTrusted: permissionPrompt.canBeTrusted,
1305
1398
  onResponse: onPermissionResponse
1306
1399
  }
1307
- )) : /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column" }, messages.map((message, index) => /* @__PURE__ */ React9.createElement(Box9, { key: `${message.timestamp}-${message.role}-${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(
1400
+ )) : /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Static, { items: messages }, (message, index) => /* @__PURE__ */ React10.createElement(Box9, { key: index, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React10.createElement(MessageItem, { message }))), /* @__PURE__ */ React10.createElement(AgentThinking, null), exitRequested && /* @__PURE__ */ React10.createElement(Box9, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text9, { color: "yellow", bold: true }, "Press Ctrl+C again to exit")), /* @__PURE__ */ React10.createElement(Box9, { borderStyle: "single", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React10.createElement(
1308
1401
  InputPrompt,
1309
1402
  {
1310
1403
  onSubmit: handleSubmit,
@@ -1317,37 +1410,36 @@ ${errorBlock}`;
1317
1410
  ))));
1318
1411
  }
1319
1412
  function MessageItem({ message }) {
1320
- const isUser = message.role === "user";
1321
- return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Box9, null, /* @__PURE__ */ React9.createElement(Text8, { bold: true, color: isUser ? "cyan" : "green" }, isUser ? "\u{1F464} You" : "\u{1F916} Assistant"), /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, " \u2022 ", new Date(message.timestamp).toLocaleTimeString())), isUser && message.content && /* @__PURE__ */ React9.createElement(Box9, { paddingLeft: 2 }, /* @__PURE__ */ React9.createElement(Text8, { backgroundColor: "whiteBright", color: "black" }, " ", message.content, " ")), !isUser && 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) => {
1413
+ return /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Box9, 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(Box9, { paddingLeft: 2 }, message.metadata?.permissionDenied ? /* @__PURE__ */ React10.createElement(Text9, { color: "yellow" }, "\u26A0\uFE0F ", message.content) : /* @__PURE__ */ React10.createElement(Text9, null, message.content)), message.metadata?.steps && message.metadata.steps.length > 0 && /* @__PURE__ */ React10.createElement(Box9, { 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) => {
1322
1414
  if (step.type === "thought") {
1323
- 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 ? "..." : ""}`));
1415
+ return /* @__PURE__ */ React10.createElement(Box9, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text9, { color: "blue" }, "\u{1F4AD} Thought:"), /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, ` ${step.content.slice(0, 200)}${step.content.length > 200 ? "..." : ""}`));
1324
1416
  }
1325
1417
  if (step.type === "action") {
1326
1418
  const toolName = step.metadata?.toolName || "unknown";
1327
1419
  const toolInput = step.metadata?.toolInput;
1328
1420
  const observationStep = message.metadata.steps[idx + 1];
1329
1421
  const result = observationStep?.type === "observation" ? observationStep.content : null;
1330
- 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 ? "..." : ""}`));
1422
+ return /* @__PURE__ */ React10.createElement(Box9, { 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 ? "..." : ""}`));
1331
1423
  }
1332
1424
  return null;
1333
- }).filter(Boolean)), !isUser && message.content !== "..." && /* @__PURE__ */ React9.createElement(Box9, { paddingLeft: 2, marginTop: message.metadata?.steps?.length ? 1 : 0 }, message.metadata?.permissionDenied ? /* @__PURE__ */ React9.createElement(Text8, { color: "yellow" }, "\u26A0\uFE0F ", message.content) : /* @__PURE__ */ React9.createElement(Text8, null, message.content)), 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`)));
1425
+ }).filter(Boolean)), message.metadata?.tokenUsage && (!message.metadata.steps || message.metadata.steps.length === 0) && /* @__PURE__ */ React10.createElement(Box9, { paddingLeft: 2 }, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, `${message.metadata.tokenUsage.total} tokens`)));
1334
1426
  }
1335
1427
 
1336
1428
  // src/components/MessageList.tsx
1337
- import React10 from "react";
1338
- import { Box as Box10, Text as Text9 } from "ink";
1429
+ import React11 from "react";
1430
+ import { Box as Box10, Text as Text10 } from "ink";
1339
1431
  function stripThinkingTags(content) {
1340
1432
  return content.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
1341
1433
  }
1342
- var MessageList = React10.memo(
1434
+ var MessageList = React11.memo(
1343
1435
  function MessageList2({ messages }) {
1344
1436
  if (messages.length === 0) {
1345
- return /* @__PURE__ */ React10.createElement(Box10, { paddingY: 1 }, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, "No messages yet. Type a message to start!"));
1437
+ return /* @__PURE__ */ React11.createElement(Box10, { paddingY: 1 }, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "No messages yet. Type a message to start!"));
1346
1438
  }
1347
- 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) => {
1439
+ return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column", gap: 1, paddingY: 1 }, messages.map((message, index) => /* @__PURE__ */ React11.createElement(Box10, { key: index, flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Box10, null, /* @__PURE__ */ React11.createElement(Text10, { bold: true, color: message.role === "user" ? "cyan" : "green" }, message.role === "user" ? "\u{1F464} You" : "\u{1F916} Assistant"), /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, " \u2022 ", new Date(message.timestamp).toLocaleTimeString())), /* @__PURE__ */ React11.createElement(Box10, { paddingLeft: 2 }, message.metadata?.permissionDenied ? /* @__PURE__ */ React11.createElement(Text10, { color: "yellow" }, "\u26A0\uFE0F ", stripThinkingTags(message.content)) : /* @__PURE__ */ React11.createElement(Text10, null, stripThinkingTags(message.content))), message.metadata?.steps && message.metadata.steps.length > 0 && /* @__PURE__ */ React11.createElement(Box10, { paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Text10, { 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__ */ React11.createElement(Text10, { dimColor: true }, "Step types: ", message.metadata.steps.map((s) => s.type).join(", ")), message.metadata.steps.map((step, idx) => {
1348
1440
  if (step.type === "thought") {
1349
- 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(
1350
- Text9,
1441
+ return /* @__PURE__ */ React11.createElement(Box10, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Text10, { color: "blue" }, "\u{1F4AD} Thought:"), /* @__PURE__ */ React11.createElement(
1442
+ Text10,
1351
1443
  {
1352
1444
  dimColor: true
1353
1445
  },
@@ -1359,10 +1451,10 @@ var MessageList = React10.memo(
1359
1451
  const toolInput = step.metadata?.toolInput;
1360
1452
  const observationStep = message.metadata.steps[idx + 1];
1361
1453
  const result = observationStep?.type === "observation" ? observationStep.content : null;
1362
- 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 ? "..." : ""}`));
1454
+ return /* @__PURE__ */ React11.createElement(Box10, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Text10, { color: "yellow" }, "\u{1F527} Action: ", toolName), toolInput && /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, ` Input: ${typeof toolInput === "string" ? toolInput : JSON.stringify(toolInput).slice(0, 100)}`), result && /* @__PURE__ */ React11.createElement(Text10, { 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 ? "..." : ""}`));
1363
1455
  }
1364
1456
  return null;
1365
- }).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`)))));
1457
+ }).filter(Boolean)), message.metadata?.tokenUsage && (!message.metadata.steps || message.metadata.steps.length === 0) && /* @__PURE__ */ React11.createElement(Box10, { paddingLeft: 2 }, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, `${message.metadata.tokenUsage.total} tokens`)))));
1366
1458
  },
1367
1459
  (prevProps, nextProps) => {
1368
1460
  if (prevProps.messages.length !== nextProps.messages.length) {
@@ -1373,8 +1465,8 @@ var MessageList = React10.memo(
1373
1465
  );
1374
1466
 
1375
1467
  // src/components/TrustLocationSelector.tsx
1376
- import React11 from "react";
1377
- import { Box as Box11, Text as Text10 } from "ink";
1468
+ import React12 from "react";
1469
+ import { Box as Box11, Text as Text11 } from "ink";
1378
1470
  import SelectInput2 from "ink-select-input";
1379
1471
  function TrustLocationSelector({ inProject, onSelect, onCancel }) {
1380
1472
  const items = [];
@@ -1395,24 +1487,24 @@ function TrustLocationSelector({ inProject, onSelect, onCancel }) {
1395
1487
  const handleSelect = (item) => {
1396
1488
  onSelect(item.value);
1397
1489
  };
1398
- return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React11.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text10, { bold: true }, "Where should this rule be saved?")), /* @__PURE__ */ React11.createElement(
1490
+ return /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React12.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React12.createElement(Text11, { bold: true }, "Where should this rule be saved?")), /* @__PURE__ */ React12.createElement(
1399
1491
  SelectInput2,
1400
1492
  {
1401
1493
  items,
1402
1494
  onSelect: handleSelect,
1403
- itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Text10, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
1495
+ itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React12.createElement(Box11, null, /* @__PURE__ */ React12.createElement(Text11, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
1404
1496
  }
1405
- ), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Ctrl+C to cancel")));
1497
+ ), /* @__PURE__ */ React12.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Ctrl+C to cancel")));
1406
1498
  }
1407
1499
 
1408
1500
  // src/components/RewindSelector.tsx
1409
- import React12, { useState as useState3 } from "react";
1410
- import { Box as Box12, Text as Text11, useInput as useInput3 } from "ink";
1501
+ import React13, { useState as useState4 } from "react";
1502
+ import { Box as Box12, Text as Text12, useInput as useInput4 } from "ink";
1411
1503
  import SelectInput3 from "ink-select-input";
1412
1504
  function RewindSelector({ messages, onSelect, onCancel }) {
1413
- const [step, setStep] = useState3("selection");
1414
- const [selectedMessageIndex, setSelectedMessageIndex] = useState3(null);
1415
- useInput3((input, key) => {
1505
+ const [step, setStep] = useState4("selection");
1506
+ const [selectedMessageIndex, setSelectedMessageIndex] = useState4(null);
1507
+ useInput4((input, key) => {
1416
1508
  if (key.escape) {
1417
1509
  if (step === "confirmation") {
1418
1510
  setStep("selection");
@@ -1449,14 +1541,14 @@ function RewindSelector({ messages, onSelect, onCancel }) {
1449
1541
  return sum2 + (msg.metadata?.tokenUsage?.total || 0);
1450
1542
  }, 0);
1451
1543
  if (step === "selection") {
1452
- return /* @__PURE__ */ React12.createElement(Box12, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React12.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React12.createElement(Text11, { bold: true }, "Select a point to rewind to:")), /* @__PURE__ */ React12.createElement(
1544
+ return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React13.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text12, { bold: true }, "Select a point to rewind to:")), /* @__PURE__ */ React13.createElement(
1453
1545
  SelectInput3,
1454
1546
  {
1455
1547
  items,
1456
1548
  onSelect: handleSelectionSelect,
1457
- itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React12.createElement(Box12, null, /* @__PURE__ */ React12.createElement(Text11, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
1549
+ itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React13.createElement(Box12, null, /* @__PURE__ */ React13.createElement(Text12, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
1458
1550
  }
1459
- ), /* @__PURE__ */ React12.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Esc to cancel")));
1551
+ ), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Esc to cancel")));
1460
1552
  }
1461
1553
  const confirmationItems = [
1462
1554
  { label: "Yes, rewind to this point", value: "confirm" },
@@ -1464,19 +1556,19 @@ function RewindSelector({ messages, onSelect, onCancel }) {
1464
1556
  ];
1465
1557
  const selectedMessage = selectedMessageIndex !== null && selectedMessageIndex >= 0 && selectedMessageIndex < messages.length ? messages[selectedMessageIndex] : null;
1466
1558
  const selectedPreview = selectedMessage ? selectedMessage.content.length > 50 ? selectedMessage.content.substring(0, 50) + "..." : selectedMessage.content : "";
1467
- return /* @__PURE__ */ React12.createElement(Box12, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React12.createElement(Box12, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React12.createElement(Text11, { bold: true }, "Confirm rewind operation:"), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "Message: ", selectedPreview), /* @__PURE__ */ React12.createElement(Text11, { color: "yellow" }, "This will remove ", messagesToRemove.length, " message(s) (", tokensToRemove.toLocaleString(), " tokens)"), /* @__PURE__ */ React12.createElement(Text11, { color: "cyan" }, "The selected message will be placed in your input for editing.")), /* @__PURE__ */ React12.createElement(
1559
+ return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React13.createElement(Box12, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(Text12, { bold: true }, "Confirm rewind operation:"), /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "Message: ", selectedPreview), /* @__PURE__ */ React13.createElement(Text12, { color: "yellow" }, "This will remove ", messagesToRemove.length, " message(s) (", tokensToRemove.toLocaleString(), " tokens)"), /* @__PURE__ */ React13.createElement(Text12, { color: "cyan" }, "The selected message will be placed in your input for editing.")), /* @__PURE__ */ React13.createElement(
1468
1560
  SelectInput3,
1469
1561
  {
1470
1562
  items: confirmationItems,
1471
1563
  onSelect: handleConfirmationSelect,
1472
- itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React12.createElement(Box12, null, /* @__PURE__ */ React12.createElement(Text11, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
1564
+ itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React13.createElement(Box12, null, /* @__PURE__ */ React13.createElement(Text12, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
1473
1565
  }
1474
- ), /* @__PURE__ */ React12.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Esc to go back")));
1566
+ ), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Esc to go back")));
1475
1567
  }
1476
1568
 
1477
1569
  // src/components/LoginFlow.tsx
1478
- import React13, { useState as useState4, useEffect as useEffect2 } from "react";
1479
- import { Box as Box13, Text as Text12 } from "ink";
1570
+ import React14, { useState as useState5, useEffect as useEffect2 } from "react";
1571
+ import { Box as Box13, Text as Text13 } from "ink";
1480
1572
  import Spinner2 from "ink-spinner";
1481
1573
  import jwt from "jsonwebtoken";
1482
1574
  import open from "open";
@@ -1592,10 +1684,10 @@ var OAuthClient = class {
1592
1684
 
1593
1685
  // src/components/LoginFlow.tsx
1594
1686
  function LoginFlow({ apiUrl = "http://localhost:3000", configStore, onSuccess, onError }) {
1595
- const [status, setStatus] = useState4("initiating");
1596
- const [deviceFlow, setDeviceFlow] = useState4(null);
1597
- const [statusMessage, setStatusMessage] = useState4("Initiating device authorization...");
1598
- const [error, setError] = useState4(null);
1687
+ const [status, setStatus] = useState5("initiating");
1688
+ const [deviceFlow, setDeviceFlow] = useState5(null);
1689
+ const [statusMessage, setStatusMessage] = useState5("Initiating device authorization...");
1690
+ const [error, setError] = useState5(null);
1599
1691
  useEffect2(() => {
1600
1692
  const runLoginFlow = async () => {
1601
1693
  const oauth = new OAuthClient(apiUrl);
@@ -1639,15 +1731,15 @@ function LoginFlow({ apiUrl = "http://localhost:3000", configStore, onSuccess, o
1639
1731
  }
1640
1732
  }, [deviceFlow, status]);
1641
1733
  if (status === "initiating") {
1642
- return /* @__PURE__ */ React13.createElement(Box13, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React13.createElement(Box13, null, /* @__PURE__ */ React13.createElement(Text12, { color: "cyan" }, /* @__PURE__ */ React13.createElement(Spinner2, { type: "dots" }), " Initiating device authorization...")));
1734
+ return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React14.createElement(Box13, null, /* @__PURE__ */ React14.createElement(Text13, { color: "cyan" }, /* @__PURE__ */ React14.createElement(Spinner2, { type: "dots" }), " Initiating device authorization...")));
1643
1735
  }
1644
1736
  if (status === "error") {
1645
- return /* @__PURE__ */ React13.createElement(Box13, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React13.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text12, { color: "red", bold: true }, "\u2716 Authentication Failed")), /* @__PURE__ */ React13.createElement(Box13, null, /* @__PURE__ */ React13.createElement(Text12, { color: "red" }, error)));
1737
+ return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text13, { color: "red", bold: true }, "\u2716 Authentication Failed")), /* @__PURE__ */ React14.createElement(Box13, null, /* @__PURE__ */ React14.createElement(Text13, { color: "red" }, error)));
1646
1738
  }
1647
1739
  if (status === "success") {
1648
- return /* @__PURE__ */ React13.createElement(Box13, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React13.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text12, { color: "green", bold: true }, "\u2714 Successfully authenticated!")), /* @__PURE__ */ React13.createElement(Box13, null, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "You can now use B4M CLI with your account.")));
1740
+ return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text13, { color: "green", bold: true }, "\u2714 Successfully authenticated!")), /* @__PURE__ */ React14.createElement(Box13, null, /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "You can now use B4M CLI with your account.")));
1649
1741
  }
1650
- return /* @__PURE__ */ React13.createElement(Box13, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan" }, /* @__PURE__ */ React13.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text12, { color: "cyan", bold: true }, "\u{1F510} Device Authorization")), /* @__PURE__ */ React13.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text12, null, "Opening browser automatically... If it doesn't open, please visit:")), /* @__PURE__ */ React13.createElement(Box13, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React13.createElement(Text12, { color: "blue", bold: true }, deviceFlow?.verification_uri)), /* @__PURE__ */ React13.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text12, null, "And enter this code when prompted:")), /* @__PURE__ */ React13.createElement(Box13, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React13.createElement(Text12, { color: "yellow", bold: true }, deviceFlow?.user_code)), /* @__PURE__ */ React13.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text12, { color: "cyan" }, /* @__PURE__ */ React13.createElement(Spinner2, { type: "dots" }), " ", statusMessage)), /* @__PURE__ */ React13.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "Expires in ", deviceFlow ? Math.floor(deviceFlow.expires_in / 60) : 0, " minutes")));
1742
+ return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan" }, /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text13, { color: "cyan", bold: true }, "\u{1F510} Device Authorization")), /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text13, null, "Opening browser automatically... If it doesn't open, please visit:")), /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React14.createElement(Text13, { color: "blue", bold: true }, deviceFlow?.verification_uri)), /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text13, null, "And enter this code when prompted:")), /* @__PURE__ */ React14.createElement(Box13, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React14.createElement(Text13, { color: "yellow", bold: true }, deviceFlow?.user_code)), /* @__PURE__ */ React14.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text13, { color: "cyan" }, /* @__PURE__ */ React14.createElement(Spinner2, { type: "dots" }), " ", statusMessage)), /* @__PURE__ */ React14.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "Expires in ", deviceFlow ? Math.floor(deviceFlow.expires_in / 60) : 0, " minutes")));
1651
1743
  }
1652
1744
 
1653
1745
  // src/storage/SessionStore.ts
@@ -2533,9 +2625,10 @@ ${options.context}` : this.getSystemPrompt()
2533
2625
  content: query
2534
2626
  }
2535
2627
  ];
2628
+ console.log("[DEBUG ReActAgent] Messages array being sent to LLM:");
2536
2629
  messages.forEach((msg, i) => {
2537
2630
  const content = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
2538
- this.context.logger.debug(` [${i}] ${msg.role}: ${content.substring(0, 150)}...`);
2631
+ console.log(` [${i}] ${msg.role}: ${content.substring(0, 150)}...`);
2539
2632
  });
2540
2633
  let finalAnswer = "";
2541
2634
  let reachedMaxIterations = false;
@@ -4928,8 +5021,8 @@ async function processAndStoreImages(images, context) {
4928
5021
  const buffer = await downloadImage(image);
4929
5022
  const fileType = await fileTypeFromBuffer2(buffer);
4930
5023
  const filename = `${uuidv45()}.${fileType?.ext}`;
4931
- const path14 = await context.imageGenerateStorage.upload(buffer, filename, {});
4932
- return path14;
5024
+ const path13 = await context.imageGenerateStorage.upload(buffer, filename, {});
5025
+ return path13;
4933
5026
  }));
4934
5027
  }
4935
5028
  async function updateQuestAndReturnMarkdown(storedImageUrls, context) {
@@ -6141,8 +6234,8 @@ async function processAndStoreImage(imageUrl, context) {
6141
6234
  const buffer = await downloadImage2(imageUrl);
6142
6235
  const fileType = await fileTypeFromBuffer3(buffer);
6143
6236
  const filename = `${uuidv46()}.${fileType?.ext}`;
6144
- const path14 = await context.imageGenerateStorage.upload(buffer, filename, {});
6145
- return path14;
6237
+ const path13 = await context.imageGenerateStorage.upload(buffer, filename, {});
6238
+ return path13;
6146
6239
  }
6147
6240
  async function updateQuestAndReturnMarkdown2(storedImagePath, context) {
6148
6241
  await context.onFinish?.("edit_image", storedImagePath);
@@ -8554,381 +8647,6 @@ var deleteFileTool = {
8554
8647
  })
8555
8648
  };
8556
8649
 
8557
- // ../../b4m-core/packages/services/dist/src/llm/tools/implementation/bashExecute/index.js
8558
- import { spawn } from "child_process";
8559
- import path11 from "path";
8560
- var DEFAULT_TIMEOUT_MS = 6e4;
8561
- var MAX_OUTPUT_SIZE = 100 * 1024;
8562
- var DANGEROUS_PATTERNS = [
8563
- // Destructive file operations
8564
- {
8565
- pattern: /\brm\s+(-[a-zA-Z]*r[a-zA-Z]*\s+|.*\s+-[a-zA-Z]*r).*\//i,
8566
- reason: "Recursive delete with path",
8567
- block: true
8568
- },
8569
- {
8570
- pattern: /\brm\s+(-[a-zA-Z]*f[a-zA-Z]*\s+|.*\s+-[a-zA-Z]*f).*--no-preserve-root/i,
8571
- reason: "Force delete without preserve root",
8572
- block: true
8573
- },
8574
- {
8575
- pattern: /\brm\s+-[a-zA-Z]*r[a-zA-Z]*f[a-zA-Z]*\s+\//i,
8576
- reason: "Recursive force delete on root paths",
8577
- block: true
8578
- },
8579
- {
8580
- pattern: /\brm\s+-[a-zA-Z]*f[a-zA-Z]*r[a-zA-Z]*\s+\//i,
8581
- reason: "Force recursive delete on root paths",
8582
- block: true
8583
- },
8584
- // System-level dangerous commands
8585
- { pattern: /\bsudo\b/i, reason: "Elevated privileges (sudo)", block: true },
8586
- { pattern: /\bsu\s+(-|root)/i, reason: "Switch to root user", block: true },
8587
- { pattern: /\bchmod\s+777\b/i, reason: "Overly permissive chmod", block: false },
8588
- { pattern: /\bchown\s+-R\s+root/i, reason: "Recursive chown to root", block: true },
8589
- // Disk/partition operations
8590
- { pattern: /\bmkfs\b/i, reason: "Filesystem creation", block: true },
8591
- { pattern: /\bfdisk\b/i, reason: "Disk partitioning", block: true },
8592
- { pattern: /\bdd\s+.*of=\/dev\//i, reason: "Direct disk write", block: true },
8593
- // Network attacks
8594
- { pattern: /\b(nc|netcat)\s+.*-e\s+\/bin\/(ba)?sh/i, reason: "Reverse shell attempt", block: true },
8595
- { pattern: /\bcurl\s+.*\|\s*(ba)?sh/i, reason: "Piping remote script to shell", block: true },
8596
- { pattern: /\bwget\s+.*\|\s*(ba)?sh/i, reason: "Piping remote script to shell", block: true },
8597
- // Fork bombs and resource exhaustion
8598
- { pattern: /:\(\)\s*\{\s*:\|:&\s*\}\s*;/i, reason: "Fork bomb", block: true },
8599
- { pattern: /\bwhile\s+true.*do.*done.*&/i, reason: "Infinite loop in background", block: false },
8600
- // Credential/sensitive data access
8601
- { pattern: /\/etc\/shadow/i, reason: "Access to shadow file", block: true },
8602
- { pattern: /\/etc\/passwd.*>/i, reason: "Modifying passwd file", block: true },
8603
- { pattern: /\baws\s+.*--profile\s+/i, reason: "AWS profile access", block: false },
8604
- // History/log manipulation
8605
- { pattern: /\bhistory\s+-c\b/i, reason: "Clearing shell history", block: false },
8606
- { pattern: />\s*\/var\/log\//i, reason: "Overwriting system logs", block: true },
8607
- // Dangerous redirects
8608
- { pattern: />\s*\/dev\/sda/i, reason: "Writing to block device", block: true },
8609
- { pattern: />\s*\/dev\/null.*2>&1.*</i, reason: "Potentially hiding output", block: false },
8610
- // Environment manipulation
8611
- { pattern: /\bexport\s+PATH\s*=\s*[^$]/i, reason: "Overwriting PATH", block: false },
8612
- { pattern: /\bexport\s+LD_PRELOAD/i, reason: "LD_PRELOAD manipulation", block: true },
8613
- // Process/system control
8614
- { pattern: /\bkill\s+-9\s+(-1|1)\b/i, reason: "Killing all processes", block: true },
8615
- { pattern: /\bkillall\s+-9\b/i, reason: "Force killing processes", block: false },
8616
- { pattern: /\bshutdown\b/i, reason: "System shutdown", block: true },
8617
- { pattern: /\breboot\b/i, reason: "System reboot", block: true },
8618
- { pattern: /\binit\s+[06]\b/i, reason: "System runlevel change", block: true }
8619
- ];
8620
- var SAFE_COMMAND_PREFIXES = [
8621
- "ls",
8622
- "cat",
8623
- "head",
8624
- "tail",
8625
- "grep",
8626
- "find",
8627
- "echo",
8628
- "pwd",
8629
- "whoami",
8630
- "date",
8631
- "cal",
8632
- "wc",
8633
- "sort",
8634
- "uniq",
8635
- "cut",
8636
- "tr",
8637
- "sed",
8638
- "awk",
8639
- "git",
8640
- "npm",
8641
- "pnpm",
8642
- "yarn",
8643
- "node",
8644
- "npx",
8645
- "tsx",
8646
- "ts-node",
8647
- "python",
8648
- "python3",
8649
- "pip",
8650
- "pip3",
8651
- "docker",
8652
- "docker-compose",
8653
- "curl",
8654
- "wget",
8655
- // These are safe for fetching, blocked when piped to shell
8656
- "mkdir",
8657
- "touch",
8658
- "cp",
8659
- "mv",
8660
- // File operations (still require permission)
8661
- "which",
8662
- "whereis",
8663
- "type",
8664
- "file",
8665
- "stat",
8666
- "env",
8667
- "printenv",
8668
- "set",
8669
- "man",
8670
- "help",
8671
- "info",
8672
- "diff",
8673
- "comm",
8674
- "cmp",
8675
- "tar",
8676
- "zip",
8677
- "unzip",
8678
- "gzip",
8679
- "gunzip",
8680
- "ssh",
8681
- "scp",
8682
- "rsync",
8683
- // Network tools
8684
- "make",
8685
- "cmake",
8686
- "cargo",
8687
- "go",
8688
- "rustc",
8689
- "gcc",
8690
- "g++",
8691
- // Build tools
8692
- "jest",
8693
- "vitest",
8694
- "mocha",
8695
- "pytest",
8696
- // Test runners
8697
- "eslint",
8698
- "prettier",
8699
- "tsc"
8700
- // Linters/formatters
8701
- ];
8702
- function checkDangerousPatterns(command) {
8703
- for (const { pattern, reason, block } of DANGEROUS_PATTERNS) {
8704
- if (pattern.test(command)) {
8705
- return { blocked: block, reason };
8706
- }
8707
- }
8708
- return { blocked: false };
8709
- }
8710
- function getBaseCommand(command) {
8711
- const trimmed = command.trim();
8712
- const match = trimmed.match(/^(\S+)/);
8713
- return match ? match[1] : "";
8714
- }
8715
- function isSafeCommandPrefix(command) {
8716
- const baseCommand = getBaseCommand(command);
8717
- return SAFE_COMMAND_PREFIXES.some((safe) => baseCommand === safe || baseCommand.endsWith(`/${safe}`));
8718
- }
8719
- async function executeBashCommand(params) {
8720
- const { command, cwd: relativeCwd, timeout = DEFAULT_TIMEOUT_MS } = params;
8721
- if (!command || command.trim().length === 0) {
8722
- return {
8723
- stdout: "",
8724
- stderr: "Error: Command cannot be empty",
8725
- exitCode: 1,
8726
- timedOut: false,
8727
- blocked: true,
8728
- blockedReason: "Empty command"
8729
- };
8730
- }
8731
- const dangerCheck = checkDangerousPatterns(command);
8732
- if (dangerCheck.blocked) {
8733
- return {
8734
- stdout: "",
8735
- stderr: `Command blocked for safety: ${dangerCheck.reason}`,
8736
- exitCode: 1,
8737
- timedOut: false,
8738
- blocked: true,
8739
- blockedReason: dangerCheck.reason
8740
- };
8741
- }
8742
- const baseCwd = process.cwd();
8743
- const targetCwd = relativeCwd ? path11.resolve(baseCwd, relativeCwd) : baseCwd;
8744
- const effectiveTimeout = Math.min(timeout, 5 * 60 * 1e3);
8745
- return new Promise((resolve3) => {
8746
- let stdout = "";
8747
- let stderr = "";
8748
- let timedOut = false;
8749
- const proc = spawn("bash", ["-c", command], {
8750
- cwd: targetCwd,
8751
- env: {
8752
- ...process.env,
8753
- // Prevent color codes that might be hard to read
8754
- NO_COLOR: "1",
8755
- FORCE_COLOR: "0"
8756
- },
8757
- stdio: ["ignore", "pipe", "pipe"]
8758
- });
8759
- const timeoutId = setTimeout(() => {
8760
- timedOut = true;
8761
- proc.kill("SIGTERM");
8762
- setTimeout(() => {
8763
- if (!proc.killed) {
8764
- proc.kill("SIGKILL");
8765
- }
8766
- }, 5e3);
8767
- }, effectiveTimeout);
8768
- proc.stdout.on("data", (data) => {
8769
- if (stdout.length < MAX_OUTPUT_SIZE) {
8770
- stdout += data.toString();
8771
- if (stdout.length > MAX_OUTPUT_SIZE) {
8772
- stdout = stdout.slice(0, MAX_OUTPUT_SIZE) + "\n... [output truncated]";
8773
- }
8774
- }
8775
- });
8776
- proc.stderr.on("data", (data) => {
8777
- if (stderr.length < MAX_OUTPUT_SIZE) {
8778
- stderr += data.toString();
8779
- if (stderr.length > MAX_OUTPUT_SIZE) {
8780
- stderr = stderr.slice(0, MAX_OUTPUT_SIZE) + "\n... [output truncated]";
8781
- }
8782
- }
8783
- });
8784
- proc.on("close", (exitCode) => {
8785
- clearTimeout(timeoutId);
8786
- resolve3({
8787
- stdout: stdout.trim(),
8788
- stderr: stderr.trim(),
8789
- exitCode,
8790
- timedOut,
8791
- blocked: false
8792
- });
8793
- });
8794
- proc.on("error", (error) => {
8795
- clearTimeout(timeoutId);
8796
- resolve3({
8797
- stdout: "",
8798
- stderr: `Failed to execute command: ${error.message}`,
8799
- exitCode: 1,
8800
- timedOut: false,
8801
- blocked: false
8802
- });
8803
- });
8804
- });
8805
- }
8806
- function formatResult(result, command) {
8807
- const parts = [];
8808
- parts.push(`$ ${command}`);
8809
- parts.push("");
8810
- if (result.blocked) {
8811
- parts.push(`BLOCKED: ${result.blockedReason}`);
8812
- parts.push("");
8813
- parts.push("This command was blocked for safety reasons.");
8814
- parts.push("If you believe this is a false positive, please run the command manually.");
8815
- return parts.join("\n");
8816
- }
8817
- if (result.timedOut) {
8818
- parts.push("WARNING: Command timed out and was terminated.");
8819
- parts.push("");
8820
- }
8821
- if (result.stdout) {
8822
- parts.push(result.stdout);
8823
- }
8824
- if (result.stderr) {
8825
- if (result.stdout) {
8826
- parts.push("");
8827
- }
8828
- parts.push("STDERR:");
8829
- parts.push(result.stderr);
8830
- }
8831
- if (result.exitCode !== 0 && result.exitCode !== null) {
8832
- parts.push("");
8833
- parts.push(`Exit code: ${result.exitCode}`);
8834
- }
8835
- if (!result.stdout && !result.stderr && !result.timedOut) {
8836
- parts.push("(command completed with no output)");
8837
- }
8838
- return parts.join("\n");
8839
- }
8840
- var bashExecuteTool = {
8841
- name: "bash_execute",
8842
- implementation: (context) => ({
8843
- toolFn: async (value) => {
8844
- const params = value;
8845
- const isSafe = isSafeCommandPrefix(params.command);
8846
- context.logger.info("Bash: Executing command", {
8847
- command: params.command,
8848
- cwd: params.cwd || ".",
8849
- timeout: params.timeout || DEFAULT_TIMEOUT_MS,
8850
- isSafeCommand: isSafe
8851
- });
8852
- if (context.onStart) {
8853
- await context.onStart("bash_execute", {
8854
- command: params.command,
8855
- cwd: params.cwd
8856
- });
8857
- }
8858
- try {
8859
- const result = await executeBashCommand(params);
8860
- const formattedResult = formatResult(result, params.command);
8861
- context.logger.info("Bash: Command completed", {
8862
- exitCode: result.exitCode,
8863
- timedOut: result.timedOut,
8864
- blocked: result.blocked
8865
- });
8866
- if (context.onFinish) {
8867
- await context.onFinish("bash_execute", {
8868
- command: params.command,
8869
- exitCode: result.exitCode,
8870
- blocked: result.blocked
8871
- });
8872
- }
8873
- return formattedResult;
8874
- } catch (error) {
8875
- context.logger.error("Bash: Command failed", error);
8876
- if (context.onFinish) {
8877
- await context.onFinish("bash_execute", {
8878
- command: params.command,
8879
- error: error instanceof Error ? error.message : "Unknown error"
8880
- });
8881
- }
8882
- throw error;
8883
- }
8884
- },
8885
- toolSchema: {
8886
- name: "bash_execute",
8887
- description: `Execute a bash command in the terminal. Use this for running shell commands, scripts, build tools, git operations, and other CLI tasks.
8888
-
8889
- SAFETY NOTES:
8890
- - Commands are executed in the current working directory (or specified cwd)
8891
- - Dangerous commands (sudo, rm -rf /, etc.) are automatically blocked
8892
- - Commands have a default timeout of 60 seconds (max 5 minutes)
8893
- - Output is limited to prevent overwhelming responses
8894
- - This tool ALWAYS requires user permission before execution
8895
-
8896
- COMMON USE CASES:
8897
- - Running build commands: npm run build, make, cargo build
8898
- - Git operations: git status, git log, git diff
8899
- - Viewing system info: ls, pwd, cat, head, tail
8900
- - Running tests: npm test, pytest, cargo test
8901
- - Package management: npm install, pip install
8902
- - File operations: mkdir, cp, mv (with permission)
8903
-
8904
- BLOCKED OPERATIONS:
8905
- - sudo and privilege escalation
8906
- - Recursive deletes on system paths
8907
- - Direct disk operations
8908
- - Fork bombs and resource exhaustion
8909
- - Piping remote scripts to shell`,
8910
- parameters: {
8911
- type: "object",
8912
- properties: {
8913
- command: {
8914
- type: "string",
8915
- description: "The bash command to execute. Can include pipes, redirects, and chained commands."
8916
- },
8917
- cwd: {
8918
- type: "string",
8919
- description: "Working directory for the command (optional). Can be relative or absolute path. Defaults to current directory."
8920
- },
8921
- timeout: {
8922
- type: "number",
8923
- description: "Timeout in milliseconds (optional, default: 60000, max: 300000). Command will be terminated if it exceeds this time."
8924
- }
8925
- },
8926
- required: ["command"]
8927
- }
8928
- }
8929
- })
8930
- };
8931
-
8932
8650
  // ../../b4m-core/packages/services/dist/src/llm/tools/index.js
8933
8651
  var tools = {
8934
8652
  dice_roll: diceRollTool,
@@ -8956,9 +8674,7 @@ var tools = {
8956
8674
  create_file: createFileTool,
8957
8675
  glob_files: globFilesTool,
8958
8676
  grep_search: grepSearchTool,
8959
- delete_file: deleteFileTool,
8960
- // Shell execution
8961
- bash_execute: bashExecuteTool
8677
+ delete_file: deleteFileTool
8962
8678
  };
8963
8679
  var generateTools = (userId, user, logger2, { db }, storage, imageGenerateStorage, statusUpdate, onStart, onFinish, llm, config, model) => {
8964
8680
  const context = {
@@ -9183,6 +8899,17 @@ var MementoEvalResponseSchema = z142.object({
9183
8899
  // ../../b4m-core/packages/services/dist/src/auth/AccessTokenGeneratorService.js
9184
8900
  import jwt2 from "jsonwebtoken";
9185
8901
 
8902
+ // ../../b4m-core/packages/services/dist/src/cliTools/types.js
8903
+ var ToolErrorType;
8904
+ (function(ToolErrorType2) {
8905
+ ToolErrorType2["INVALID_INPUT"] = "INVALID_INPUT";
8906
+ ToolErrorType2["API_KEY_MISSING"] = "API_KEY_MISSING";
8907
+ ToolErrorType2["EXTERNAL_API_ERROR"] = "EXTERNAL_API_ERROR";
8908
+ ToolErrorType2["RATE_LIMIT"] = "RATE_LIMIT";
8909
+ ToolErrorType2["NETWORK_ERROR"] = "NETWORK_ERROR";
8910
+ ToolErrorType2["UNKNOWN"] = "UNKNOWN";
8911
+ })(ToolErrorType || (ToolErrorType = {}));
8912
+
9186
8913
  // src/utils/diffPreview.ts
9187
8914
  import * as Diff from "diff";
9188
8915
  import { readFile } from "fs/promises";
@@ -9233,57 +8960,389 @@ Last modified: ${stats.mtime.toLocaleString()}`;
9233
8960
  }
9234
8961
  }
9235
8962
 
9236
- // src/utils/toolsAdapter.ts
9237
- var NoOpStorage = class extends BaseStorage {
9238
- async upload(input, destination, options) {
9239
- return `/tmp/${destination}`;
9240
- }
9241
- async download(path14) {
9242
- throw new Error("Download not supported in CLI");
9243
- }
9244
- async delete(path14) {
8963
+ // src/utils/Logger.ts
8964
+ import fs10 from "fs/promises";
8965
+ import path11 from "path";
8966
+ import os from "os";
8967
+ var Logger2 = class _Logger {
8968
+ constructor() {
8969
+ this.logFilePath = null;
8970
+ this.sessionId = null;
8971
+ this.fileLoggingEnabled = true;
8972
+ this.consoleVerbose = false;
9245
8973
  }
9246
- async getSignedUrl(path14) {
9247
- return `/tmp/${path14}`;
8974
+ static {
8975
+ this.instance = null;
9248
8976
  }
9249
- getPublicUrl(path14) {
9250
- return `/tmp/${path14}`;
8977
+ static getInstance() {
8978
+ if (!_Logger.instance) {
8979
+ _Logger.instance = new _Logger();
8980
+ }
8981
+ return _Logger.instance;
9251
8982
  }
9252
- async getPreview(path14) {
9253
- return `/tmp/${path14}`;
8983
+ /**
8984
+ * Initialize the logger with a session ID
8985
+ */
8986
+ async initialize(sessionId) {
8987
+ this.sessionId = sessionId;
8988
+ const debugDir = path11.join(os.homedir(), ".bike4mind", "debug");
8989
+ await fs10.mkdir(debugDir, { recursive: true });
8990
+ this.logFilePath = path11.join(debugDir, `${sessionId}.txt`);
8991
+ await this.writeToFile("INFO", "=== CLI SESSION START ===");
9254
8992
  }
9255
- async getMetadata(path14) {
9256
- return { size: 0, contentType: "application/octet-stream" };
8993
+ /**
8994
+ * Set whether verbose console logging is enabled
8995
+ */
8996
+ setVerbose(enabled) {
8997
+ this.consoleVerbose = enabled;
9257
8998
  }
9258
- };
9259
- var CliLogger = class extends Logger {
9260
- constructor() {
9261
- super({ logInJson: false });
8999
+ /**
9000
+ * Set whether file logging is enabled
9001
+ */
9002
+ setFileLoggingEnabled(enabled) {
9003
+ this.fileLoggingEnabled = enabled;
9262
9004
  }
9263
- // Override all logging methods to be silent
9264
- info(...args) {
9005
+ /**
9006
+ * DEBUG level - verbose-only console, always file
9007
+ */
9008
+ debug(message) {
9009
+ this.writeToFile("DEBUG", message).catch(() => {
9010
+ });
9011
+ if (this.consoleVerbose) {
9012
+ console.log(message);
9013
+ }
9265
9014
  }
9266
- warn(...args) {
9015
+ /**
9016
+ * INFO level - always shown to user
9017
+ */
9018
+ info(message) {
9019
+ this.writeToFile("INFO", message).catch(() => {
9020
+ });
9021
+ console.log(message);
9267
9022
  }
9268
- error(...args) {
9023
+ /**
9024
+ * WARN level - always shown to user
9025
+ */
9026
+ warn(message) {
9027
+ this.writeToFile("WARN", message).catch(() => {
9028
+ });
9029
+ console.warn(message);
9269
9030
  }
9270
- debug(...args) {
9031
+ /**
9032
+ * ERROR level - always shown to user
9033
+ */
9034
+ error(message, err) {
9035
+ this.writeToFile("ERROR", message).catch(() => {
9036
+ });
9037
+ if (err) {
9038
+ this.logErrorDetailsToFile(err).catch(() => {
9039
+ });
9040
+ }
9041
+ console.error(message);
9271
9042
  }
9272
- log(...args) {
9043
+ /**
9044
+ * Write log entry to file
9045
+ */
9046
+ async writeToFile(level, message) {
9047
+ if (!this.fileLoggingEnabled || !this.logFilePath) {
9048
+ return;
9049
+ }
9050
+ try {
9051
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").substring(0, 19);
9052
+ const logEntry = `[${timestamp}] [${level}] ${message}
9053
+ `;
9054
+ await fs10.appendFile(this.logFilePath, logEntry, "utf-8");
9055
+ } catch (error) {
9056
+ console.error("File logging failed:", error);
9057
+ }
9273
9058
  }
9274
- };
9275
- function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, agentContext, configStore) {
9276
- const originalFn = tool.toolFn;
9277
- const toolName = tool.toolSchema.name;
9278
- return {
9279
- ...tool,
9280
- toolFn: async (args) => {
9281
- if (!permissionManager.needsPermission(toolName)) {
9282
- const result2 = await originalFn(args);
9283
- agentContext.observationQueue.push({ toolName, result: result2 });
9284
- return result2;
9059
+ /**
9060
+ * Log error details to file
9061
+ */
9062
+ async logErrorDetailsToFile(err) {
9063
+ if (!this.fileLoggingEnabled || !this.logFilePath) {
9064
+ return;
9065
+ }
9066
+ try {
9067
+ if (err && typeof err === "object" && "response" in err && err.response) {
9068
+ const response = err.response;
9069
+ const config = err && typeof err === "object" && "config" in err ? err.config : void 0;
9070
+ await this.writeToFile("ERROR", ` Status: ${response.status} ${response.statusText || ""}`);
9071
+ await this.writeToFile("ERROR", ` URL: ${config?.url || "unknown"}`);
9072
+ await this.writeToFile("ERROR", ` Headers: ${this.safeStringify(response.headers)}`);
9073
+ if (response.data) {
9074
+ const errorText = this.extractErrorMessage(response.data);
9075
+ if (errorText.trim().startsWith("<!DOCTYPE") || errorText.trim().startsWith("<html")) {
9076
+ await this.writeToFile("ERROR", ` Response Type: HTML Error Page`);
9077
+ const parsedError = this.parseHtmlError(errorText);
9078
+ if (parsedError) {
9079
+ await this.writeToFile("ERROR", ` Error Message: ${parsedError}`);
9080
+ }
9081
+ await this.writeToFile("ERROR", ` Raw HTML: ${this.truncate(errorText, 1e3)}`);
9082
+ } else {
9083
+ const preview = this.truncate(errorText, 500);
9084
+ await this.writeToFile("ERROR", ` Response: ${preview}`);
9085
+ }
9086
+ } else {
9087
+ await this.writeToFile("ERROR", ` Response: (no data)`);
9088
+ }
9285
9089
  }
9286
- let preview;
9090
+ if (err && typeof err === "object" && "stack" in err && typeof err.stack === "string") {
9091
+ const stackLines = err.stack.split("\n").slice(0, 5).join("\n ");
9092
+ await this.writeToFile("ERROR", ` Stack: ${stackLines}`);
9093
+ } else if (err && typeof err === "object" && "message" in err && typeof err.message === "string") {
9094
+ await this.writeToFile("ERROR", ` Message: ${err.message}`);
9095
+ }
9096
+ } catch (error) {
9097
+ }
9098
+ }
9099
+ /**
9100
+ * Safely stringify object, handling circular references
9101
+ */
9102
+ safeStringify(obj) {
9103
+ try {
9104
+ return JSON.stringify(obj);
9105
+ } catch (error) {
9106
+ if (error instanceof Error && error.message.includes("circular")) {
9107
+ try {
9108
+ const seen = /* @__PURE__ */ new WeakSet();
9109
+ return JSON.stringify(obj, (key, value) => {
9110
+ if (typeof value === "object" && value !== null) {
9111
+ if (seen.has(value)) {
9112
+ return "[Circular]";
9113
+ }
9114
+ seen.add(value);
9115
+ }
9116
+ return value;
9117
+ });
9118
+ } catch {
9119
+ return "[Unable to stringify]";
9120
+ }
9121
+ }
9122
+ return "[Stringify error]";
9123
+ }
9124
+ }
9125
+ /**
9126
+ * Extract readable text from error response data
9127
+ */
9128
+ extractErrorMessage(data) {
9129
+ if (Buffer.isBuffer(data)) {
9130
+ return data.toString("utf-8");
9131
+ }
9132
+ if (typeof data === "string") {
9133
+ return data;
9134
+ }
9135
+ if (data && typeof data === "object" && "_readableState" in data && data._readableState && typeof data._readableState === "object" && "buffer" in data._readableState && Array.isArray(data._readableState.buffer) && data._readableState.buffer.length > 0) {
9136
+ const chunks = [];
9137
+ for (const chunk of data._readableState.buffer) {
9138
+ if (chunk && typeof chunk === "object" && "type" in chunk && chunk.type === "Buffer" && "data" in chunk && Array.isArray(chunk.data)) {
9139
+ chunks.push(Buffer.from(chunk.data));
9140
+ } else if (Buffer.isBuffer(chunk)) {
9141
+ chunks.push(chunk);
9142
+ } else if (chunk && typeof chunk === "object" && "data" in chunk) {
9143
+ if (Buffer.isBuffer(chunk.data)) {
9144
+ chunks.push(chunk.data);
9145
+ } else if (Array.isArray(chunk.data)) {
9146
+ chunks.push(Buffer.from(chunk.data));
9147
+ }
9148
+ }
9149
+ }
9150
+ if (chunks.length > 0) {
9151
+ return Buffer.concat(chunks).toString("utf-8");
9152
+ }
9153
+ }
9154
+ return this.safeStringify(data);
9155
+ }
9156
+ /**
9157
+ * Parse HTML error page to extract error message
9158
+ */
9159
+ parseHtmlError(html) {
9160
+ const titleMatch = html.match(/<title>(.*?)<\/title>/i);
9161
+ const h1Match = html.match(/<h1>(.*?)<\/h1>/i);
9162
+ const bodyMatch = html.match(/<body[^>]*>(.*?)<\/body>/is);
9163
+ if (titleMatch && titleMatch[1] !== "Error") {
9164
+ return titleMatch[1].trim();
9165
+ }
9166
+ if (h1Match) {
9167
+ return h1Match[1].trim();
9168
+ }
9169
+ if (bodyMatch) {
9170
+ const text = bodyMatch[1].replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
9171
+ return text.substring(0, 200);
9172
+ }
9173
+ return null;
9174
+ }
9175
+ /**
9176
+ * Truncate string to max length with ellipsis
9177
+ */
9178
+ truncate(str, maxLength) {
9179
+ if (str.length <= maxLength) {
9180
+ return str;
9181
+ }
9182
+ return str.substring(0, maxLength) + "... [truncated]";
9183
+ }
9184
+ /**
9185
+ * Format bytes to human-readable size
9186
+ */
9187
+ formatBytes(bytes) {
9188
+ if (bytes === 0) return "0 B";
9189
+ const k = 1024;
9190
+ const sizes = ["B", "KB", "MB", "GB"];
9191
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
9192
+ return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
9193
+ }
9194
+ /**
9195
+ * Clean up old debug logs (older than 30 days)
9196
+ */
9197
+ async cleanupOldLogs() {
9198
+ if (!this.fileLoggingEnabled) return;
9199
+ try {
9200
+ const debugDir = path11.join(os.homedir(), ".bike4mind", "debug");
9201
+ const files = await fs10.readdir(debugDir);
9202
+ const now = Date.now();
9203
+ const thirtyDaysAgo = now - 30 * 24 * 60 * 60 * 1e3;
9204
+ for (const file of files) {
9205
+ const filePath = path11.join(debugDir, file);
9206
+ const stats = await fs10.stat(filePath);
9207
+ if (stats.mtime.getTime() < thirtyDaysAgo) {
9208
+ await fs10.unlink(filePath);
9209
+ }
9210
+ }
9211
+ } catch (error) {
9212
+ console.error("Failed to cleanup old logs:", error);
9213
+ }
9214
+ }
9215
+ };
9216
+ var logger = Logger2.getInstance();
9217
+
9218
+ // src/llm/ServerToolExecutor.ts
9219
+ var ServerToolExecutor = class {
9220
+ constructor(apiClient) {
9221
+ this.toolsEndpoint = "/api/ai/v1/tools";
9222
+ this.apiClient = apiClient;
9223
+ }
9224
+ /**
9225
+ * Execute a tool server-side
9226
+ *
9227
+ * @param toolName - Name of the tool to execute (e.g., 'weather_info', 'web_search')
9228
+ * @param input - Tool input parameters
9229
+ * @returns Tool execution result (content or error)
9230
+ */
9231
+ async executeTool(toolName, input) {
9232
+ logger.debug(`[ServerToolExecutor] Executing tool: ${toolName}`);
9233
+ logger.debug(`[ServerToolExecutor] Endpoint: ${this.toolsEndpoint}`);
9234
+ logger.debug(`[ServerToolExecutor] Input: ${JSON.stringify(input)}`);
9235
+ try {
9236
+ const result = await this.apiClient.post(this.toolsEndpoint, {
9237
+ toolName,
9238
+ input
9239
+ });
9240
+ logger.debug(`[ServerToolExecutor] Response: ${JSON.stringify(result)}`);
9241
+ if (!result.success) {
9242
+ const errorMessage = result.error || "Tool execution failed";
9243
+ logger.error(`[ServerToolExecutor] Tool ${toolName} failed: ${errorMessage}`);
9244
+ return `Error executing ${toolName}: ${errorMessage}`;
9245
+ }
9246
+ logger.debug(`[ServerToolExecutor] Tool ${toolName} succeeded in ${result.executionTimeMs}ms`);
9247
+ return result.content || "";
9248
+ } catch (error) {
9249
+ const err = error;
9250
+ const errorMessage = err?.response?.data?.error || err?.message || "Unknown error";
9251
+ const status = err?.response?.status || "unknown";
9252
+ logger.error(`[ServerToolExecutor] Request failed for ${toolName}: ${errorMessage} (status: ${status})`);
9253
+ logger.error(`[ServerToolExecutor] Full error: ${JSON.stringify(err, null, 2)}`);
9254
+ return `Error executing ${toolName}: ${errorMessage}`;
9255
+ }
9256
+ }
9257
+ };
9258
+
9259
+ // src/llm/ToolRouter.ts
9260
+ var SERVER_TOOLS = ["weather_info", "web_search"];
9261
+ var LOCAL_TOOLS = [
9262
+ "file_read",
9263
+ "create_file",
9264
+ "glob_files",
9265
+ "grep_search",
9266
+ "delete_file",
9267
+ "edit_file",
9268
+ "dice_roll",
9269
+ "math_evaluate",
9270
+ "current_datetime"
9271
+ ];
9272
+ function isServerTool(toolName) {
9273
+ return SERVER_TOOLS.includes(toolName);
9274
+ }
9275
+ function isLocalTool(toolName) {
9276
+ return LOCAL_TOOLS.includes(toolName);
9277
+ }
9278
+ async function executeTool(toolName, input, apiClient, localToolFn) {
9279
+ if (isServerTool(toolName)) {
9280
+ logger.debug(`[ToolRouter] Routing ${toolName} to server`);
9281
+ const executor = new ServerToolExecutor(apiClient);
9282
+ return await executor.executeTool(toolName, input);
9283
+ } else if (isLocalTool(toolName)) {
9284
+ logger.debug(`[ToolRouter] Executing ${toolName} locally`);
9285
+ if (!localToolFn) {
9286
+ throw new Error(`Local tool ${toolName} has no implementation`);
9287
+ }
9288
+ const result = await localToolFn(input);
9289
+ return typeof result === "string" ? result : JSON.stringify(result);
9290
+ } else {
9291
+ throw new Error(`Unknown tool: ${toolName}`);
9292
+ }
9293
+ }
9294
+
9295
+ // src/utils/toolsAdapter.ts
9296
+ var NoOpStorage = class extends BaseStorage {
9297
+ async upload(input, destination, options) {
9298
+ return `/tmp/${destination}`;
9299
+ }
9300
+ async download(path13) {
9301
+ throw new Error("Download not supported in CLI");
9302
+ }
9303
+ async delete(path13) {
9304
+ }
9305
+ async getSignedUrl(path13) {
9306
+ return `/tmp/${path13}`;
9307
+ }
9308
+ getPublicUrl(path13) {
9309
+ return `/tmp/${path13}`;
9310
+ }
9311
+ async getPreview(path13) {
9312
+ return `/tmp/${path13}`;
9313
+ }
9314
+ async getMetadata(path13) {
9315
+ return { size: 0, contentType: "application/octet-stream" };
9316
+ }
9317
+ };
9318
+ var CliLogger = class extends Logger {
9319
+ constructor() {
9320
+ super({ logInJson: false });
9321
+ }
9322
+ // Override all logging methods to be silent
9323
+ info(...args) {
9324
+ }
9325
+ warn(...args) {
9326
+ }
9327
+ error(...args) {
9328
+ }
9329
+ debug(...args) {
9330
+ }
9331
+ log(...args) {
9332
+ }
9333
+ };
9334
+ function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, agentContext, configStore, apiClient) {
9335
+ const originalFn = tool.toolFn;
9336
+ const toolName = tool.toolSchema.name;
9337
+ return {
9338
+ ...tool,
9339
+ toolFn: async (args) => {
9340
+ if (!permissionManager.needsPermission(toolName)) {
9341
+ const result2 = await executeTool(toolName, args, apiClient, originalFn);
9342
+ agentContext.observationQueue.push({ toolName, result: result2 });
9343
+ return result2;
9344
+ }
9345
+ let preview;
9287
9346
  if (toolName === "edit_file" && args?.path && args?.content) {
9288
9347
  try {
9289
9348
  preview = await generateFileDiffPreview({
@@ -9310,10 +9369,6 @@ function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, a
9310
9369
  } catch (error) {
9311
9370
  preview = `[Could not generate preview: ${error instanceof Error ? error.message : "Unknown error"}]`;
9312
9371
  }
9313
- } else if (toolName === "bash_execute" && args?.command) {
9314
- const cwd = args.cwd ? ` (in ${args.cwd})` : "";
9315
- const timeout = args.timeout ? ` [timeout: ${args.timeout}ms]` : "";
9316
- preview = `$ ${args.command}${cwd}${timeout}`;
9317
9372
  }
9318
9373
  const response = await showPermissionPrompt(toolName, args, preview);
9319
9374
  if (response.action === "deny") {
@@ -9340,13 +9395,13 @@ function wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, a
9340
9395
  }
9341
9396
  }
9342
9397
  }
9343
- const result = await originalFn(args);
9398
+ const result = await executeTool(toolName, args, apiClient, originalFn);
9344
9399
  agentContext.observationQueue.push({ toolName, result });
9345
9400
  return result;
9346
9401
  }
9347
9402
  };
9348
9403
  }
9349
- function generateCliTools(userId, llm, model, permissionManager, showPermissionPrompt, agentContext, configStore, toolApiKeys) {
9404
+ function generateCliTools(userId, llm, model, permissionManager, showPermissionPrompt, agentContext, configStore, apiClient) {
9350
9405
  const logger2 = new CliLogger();
9351
9406
  const storage = new NoOpStorage();
9352
9407
  const user = {
@@ -9363,18 +9418,6 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
9363
9418
  };
9364
9419
  const mockAdminSettings = {
9365
9420
  findBySettingName: async (settingName) => {
9366
- if (settingName === "OpenWeatherKey") {
9367
- const key = toolApiKeys?.openweather || process.env.OPENWEATHER_API_KEY;
9368
- if (key) {
9369
- return { settingValue: key };
9370
- }
9371
- }
9372
- if (settingName === "SerperKey") {
9373
- const key = toolApiKeys?.serper || process.env.SERPER_API_KEY;
9374
- if (key) {
9375
- return { settingValue: key };
9376
- }
9377
- }
9378
9421
  return null;
9379
9422
  }
9380
9423
  };
@@ -9384,29 +9427,22 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
9384
9427
  adminSettings: mockAdminSettings
9385
9428
  }
9386
9429
  };
9387
- const hasSerperKey = !!(toolApiKeys?.serper || process.env.SERPER_API_KEY);
9388
- const hasOpenWeatherKey = !!(toolApiKeys?.openweather || process.env.OPENWEATHER_API_KEY);
9389
9430
  const toolConfig = {
9390
- // Enable these tools for CLI (no external API keys needed)
9431
+ // Local-only tools (no external API keys needed)
9391
9432
  dice_roll: {},
9392
9433
  math_evaluate: {},
9393
9434
  current_datetime: {},
9394
9435
  prompt_enhancement: {},
9395
- // File operation tools (CLI-specific)
9436
+ // File operation tools (CLI-specific, local execution)
9396
9437
  file_read: {},
9397
9438
  create_file: {},
9398
9439
  glob_files: {},
9399
9440
  grep_search: {},
9400
9441
  delete_file: {},
9401
- // Shell execution (always requires permission)
9402
- bash_execute: {},
9403
- // Tools requiring API keys (only include if API key is available)
9404
- ...hasSerperKey && { web_search: {} },
9405
- // Requires SERPER_API_KEY
9406
- ...hasOpenWeatherKey && { weather_info: {} },
9407
- // Requires OPENWEATHER_API_KEY
9408
- ...hasSerperKey && { deep_research: {} }
9409
- // Requires SERPER_API_KEY
9442
+ // Server-side tools (executed via /api/ai/v1/tools Lambda)
9443
+ // Routed by ToolRouter to use B4M company API keys
9444
+ weather_info: {},
9445
+ web_search: {}
9410
9446
  // Disable web-only tools
9411
9447
  // blog_publish: undefined,
9412
9448
  // blog_edit: undefined,
@@ -9416,6 +9452,7 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
9416
9452
  // mermaid_chart: undefined,
9417
9453
  // recharts: undefined,
9418
9454
  // edit_file: undefined,
9455
+ // deep_research: undefined,
9419
9456
  };
9420
9457
  const toolsMap = generateTools(
9421
9458
  userId,
@@ -9433,7 +9470,7 @@ function generateCliTools(userId, llm, model, permissionManager, showPermissionP
9433
9470
  model
9434
9471
  );
9435
9472
  const tools2 = Object.entries(toolsMap).filter(([key]) => toolConfig[key] !== void 0).map(
9436
- ([_, tool]) => wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, agentContext, configStore)
9473
+ ([_, tool]) => wrapToolWithPermission(tool, permissionManager, showPermissionPrompt, agentContext, configStore, apiClient)
9437
9474
  );
9438
9475
  return { tools: tools2, agentContext };
9439
9476
  }
@@ -9467,7 +9504,6 @@ var DEFAULT_TOOL_CATEGORIES = {
9467
9504
  create_file: "prompt_always",
9468
9505
  delete_file: "prompt_always",
9469
9506
  shell_execute: "prompt_always",
9470
- bash_execute: "prompt_always",
9471
9507
  git_commit: "prompt_always",
9472
9508
  git_push: "prompt_always",
9473
9509
  // ===== PROMPT DEFAULT (Repository read tools) =====
@@ -9629,265 +9665,10 @@ function getEnvironmentName(configApiConfig) {
9629
9665
  return "Bike4Mind";
9630
9666
  }
9631
9667
 
9632
- // src/utils/Logger.ts
9633
- import fs10 from "fs/promises";
9634
- import path12 from "path";
9635
- import os from "os";
9636
- var Logger2 = class _Logger {
9637
- constructor() {
9638
- this.logFilePath = null;
9639
- this.sessionId = null;
9640
- this.fileLoggingEnabled = true;
9641
- this.consoleVerbose = false;
9642
- }
9643
- static {
9644
- this.instance = null;
9645
- }
9646
- static getInstance() {
9647
- if (!_Logger.instance) {
9648
- _Logger.instance = new _Logger();
9649
- }
9650
- return _Logger.instance;
9651
- }
9652
- /**
9653
- * Initialize the logger with a session ID
9654
- */
9655
- async initialize(sessionId) {
9656
- this.sessionId = sessionId;
9657
- const debugDir = path12.join(os.homedir(), ".bike4mind", "debug");
9658
- await fs10.mkdir(debugDir, { recursive: true });
9659
- this.logFilePath = path12.join(debugDir, `${sessionId}.txt`);
9660
- await this.writeToFile("INFO", "=== CLI SESSION START ===");
9661
- }
9662
- /**
9663
- * Set whether verbose console logging is enabled
9664
- */
9665
- setVerbose(enabled) {
9666
- this.consoleVerbose = enabled;
9667
- }
9668
- /**
9669
- * Set whether file logging is enabled
9670
- */
9671
- setFileLoggingEnabled(enabled) {
9672
- this.fileLoggingEnabled = enabled;
9673
- }
9674
- /**
9675
- * DEBUG level - verbose-only console, always file
9676
- */
9677
- debug(message) {
9678
- this.writeToFile("DEBUG", message).catch(() => {
9679
- });
9680
- if (this.consoleVerbose) {
9681
- console.log(message);
9682
- }
9683
- }
9684
- /**
9685
- * INFO level - always shown to user
9686
- */
9687
- info(message) {
9688
- this.writeToFile("INFO", message).catch(() => {
9689
- });
9690
- console.log(message);
9691
- }
9692
- /**
9693
- * WARN level - always shown to user
9694
- */
9695
- warn(message) {
9696
- this.writeToFile("WARN", message).catch(() => {
9697
- });
9698
- console.warn(message);
9699
- }
9700
- /**
9701
- * ERROR level - always shown to user
9702
- */
9703
- error(message, err) {
9704
- this.writeToFile("ERROR", message).catch(() => {
9705
- });
9706
- if (err) {
9707
- this.logErrorDetailsToFile(err).catch(() => {
9708
- });
9709
- }
9710
- console.error(message);
9711
- }
9712
- /**
9713
- * Write log entry to file
9714
- */
9715
- async writeToFile(level, message) {
9716
- if (!this.fileLoggingEnabled || !this.logFilePath) {
9717
- return;
9718
- }
9719
- try {
9720
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").substring(0, 19);
9721
- const logEntry = `[${timestamp}] [${level}] ${message}
9722
- `;
9723
- await fs10.appendFile(this.logFilePath, logEntry, "utf-8");
9724
- } catch (error) {
9725
- console.error("File logging failed:", error);
9726
- }
9727
- }
9728
- /**
9729
- * Log error details to file
9730
- */
9731
- async logErrorDetailsToFile(err) {
9732
- if (!this.fileLoggingEnabled || !this.logFilePath) {
9733
- return;
9734
- }
9735
- try {
9736
- if (err && typeof err === "object" && "response" in err && err.response) {
9737
- const response = err.response;
9738
- const config = err && typeof err === "object" && "config" in err ? err.config : void 0;
9739
- await this.writeToFile("ERROR", ` Status: ${response.status} ${response.statusText || ""}`);
9740
- await this.writeToFile("ERROR", ` URL: ${config?.url || "unknown"}`);
9741
- await this.writeToFile("ERROR", ` Headers: ${this.safeStringify(response.headers)}`);
9742
- if (response.data) {
9743
- const errorText = this.extractErrorMessage(response.data);
9744
- if (errorText.trim().startsWith("<!DOCTYPE") || errorText.trim().startsWith("<html")) {
9745
- await this.writeToFile("ERROR", ` Response Type: HTML Error Page`);
9746
- const parsedError = this.parseHtmlError(errorText);
9747
- if (parsedError) {
9748
- await this.writeToFile("ERROR", ` Error Message: ${parsedError}`);
9749
- }
9750
- await this.writeToFile("ERROR", ` Raw HTML: ${this.truncate(errorText, 1e3)}`);
9751
- } else {
9752
- const preview = this.truncate(errorText, 500);
9753
- await this.writeToFile("ERROR", ` Response: ${preview}`);
9754
- }
9755
- } else {
9756
- await this.writeToFile("ERROR", ` Response: (no data)`);
9757
- }
9758
- }
9759
- if (err && typeof err === "object" && "stack" in err && typeof err.stack === "string") {
9760
- const stackLines = err.stack.split("\n").slice(0, 5).join("\n ");
9761
- await this.writeToFile("ERROR", ` Stack: ${stackLines}`);
9762
- } else if (err && typeof err === "object" && "message" in err && typeof err.message === "string") {
9763
- await this.writeToFile("ERROR", ` Message: ${err.message}`);
9764
- }
9765
- } catch (error) {
9766
- }
9767
- }
9768
- /**
9769
- * Safely stringify object, handling circular references
9770
- */
9771
- safeStringify(obj) {
9772
- try {
9773
- return JSON.stringify(obj);
9774
- } catch (error) {
9775
- if (error instanceof Error && error.message.includes("circular")) {
9776
- try {
9777
- const seen = /* @__PURE__ */ new WeakSet();
9778
- return JSON.stringify(obj, (key, value) => {
9779
- if (typeof value === "object" && value !== null) {
9780
- if (seen.has(value)) {
9781
- return "[Circular]";
9782
- }
9783
- seen.add(value);
9784
- }
9785
- return value;
9786
- });
9787
- } catch {
9788
- return "[Unable to stringify]";
9789
- }
9790
- }
9791
- return "[Stringify error]";
9792
- }
9793
- }
9794
- /**
9795
- * Extract readable text from error response data
9796
- */
9797
- extractErrorMessage(data) {
9798
- if (Buffer.isBuffer(data)) {
9799
- return data.toString("utf-8");
9800
- }
9801
- if (typeof data === "string") {
9802
- return data;
9803
- }
9804
- if (data && typeof data === "object" && "_readableState" in data && data._readableState && typeof data._readableState === "object" && "buffer" in data._readableState && Array.isArray(data._readableState.buffer) && data._readableState.buffer.length > 0) {
9805
- const chunks = [];
9806
- for (const chunk of data._readableState.buffer) {
9807
- if (chunk && typeof chunk === "object" && "type" in chunk && chunk.type === "Buffer" && "data" in chunk && Array.isArray(chunk.data)) {
9808
- chunks.push(Buffer.from(chunk.data));
9809
- } else if (Buffer.isBuffer(chunk)) {
9810
- chunks.push(chunk);
9811
- } else if (chunk && typeof chunk === "object" && "data" in chunk) {
9812
- if (Buffer.isBuffer(chunk.data)) {
9813
- chunks.push(chunk.data);
9814
- } else if (Array.isArray(chunk.data)) {
9815
- chunks.push(Buffer.from(chunk.data));
9816
- }
9817
- }
9818
- }
9819
- if (chunks.length > 0) {
9820
- return Buffer.concat(chunks).toString("utf-8");
9821
- }
9822
- }
9823
- return this.safeStringify(data);
9824
- }
9825
- /**
9826
- * Parse HTML error page to extract error message
9827
- */
9828
- parseHtmlError(html) {
9829
- const titleMatch = html.match(/<title>(.*?)<\/title>/i);
9830
- const h1Match = html.match(/<h1>(.*?)<\/h1>/i);
9831
- const bodyMatch = html.match(/<body[^>]*>(.*?)<\/body>/is);
9832
- if (titleMatch && titleMatch[1] !== "Error") {
9833
- return titleMatch[1].trim();
9834
- }
9835
- if (h1Match) {
9836
- return h1Match[1].trim();
9837
- }
9838
- if (bodyMatch) {
9839
- const text = bodyMatch[1].replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
9840
- return text.substring(0, 200);
9841
- }
9842
- return null;
9843
- }
9844
- /**
9845
- * Truncate string to max length with ellipsis
9846
- */
9847
- truncate(str, maxLength) {
9848
- if (str.length <= maxLength) {
9849
- return str;
9850
- }
9851
- return str.substring(0, maxLength) + "... [truncated]";
9852
- }
9853
- /**
9854
- * Format bytes to human-readable size
9855
- */
9856
- formatBytes(bytes) {
9857
- if (bytes === 0) return "0 B";
9858
- const k = 1024;
9859
- const sizes = ["B", "KB", "MB", "GB"];
9860
- const i = Math.floor(Math.log(bytes) / Math.log(k));
9861
- return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
9862
- }
9863
- /**
9864
- * Clean up old debug logs (older than 30 days)
9865
- */
9866
- async cleanupOldLogs() {
9867
- if (!this.fileLoggingEnabled) return;
9868
- try {
9869
- const debugDir = path12.join(os.homedir(), ".bike4mind", "debug");
9870
- const files = await fs10.readdir(debugDir);
9871
- const now = Date.now();
9872
- const thirtyDaysAgo = now - 30 * 24 * 60 * 60 * 1e3;
9873
- for (const file of files) {
9874
- const filePath = path12.join(debugDir, file);
9875
- const stats = await fs10.stat(filePath);
9876
- if (stats.mtime.getTime() < thirtyDaysAgo) {
9877
- await fs10.unlink(filePath);
9878
- }
9879
- }
9880
- } catch (error) {
9881
- console.error("Failed to cleanup old logs:", error);
9882
- }
9883
- }
9884
- };
9885
- var logger = Logger2.getInstance();
9886
-
9887
9668
  // ../../b4m-core/packages/mcp/dist/src/client.js
9888
9669
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
9889
9670
  import { Client as Client2 } from "@modelcontextprotocol/sdk/client/index.js";
9890
- import path13 from "path";
9671
+ import path12 from "path";
9891
9672
  import { existsSync as existsSync8, readdirSync as readdirSync3 } from "fs";
9892
9673
  var MCPClient = class {
9893
9674
  // Note: This class handles MCP server communication with repository filtering
@@ -9928,16 +9709,16 @@ var MCPClient = class {
9928
9709
  const root = process.env.INIT_CWD || process.cwd();
9929
9710
  const candidatePaths = [
9930
9711
  // When running from SST Lambda with node_modules structure (copyFiles)
9931
- path13.join(root, `node_modules/@bike4mind/mcp/dist/src/${this.serverName}/index.js`),
9712
+ path12.join(root, `node_modules/@bike4mind/mcp/dist/src/${this.serverName}/index.js`),
9932
9713
  // When running from SST Lambda deployed environment (/var/task)
9933
- path13.join(root, `b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9714
+ path12.join(root, `b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9934
9715
  // When running from SST Lambda (.sst/artifacts/mcpHandler-dev), navigate to monorepo root (3 levels up)
9935
- path13.join(root, `../../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9716
+ path12.join(root, `../../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9936
9717
  // When running from packages/client (Next.js app), navigate to monorepo root (2 levels up)
9937
- path13.join(root, `../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9718
+ path12.join(root, `../../b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9938
9719
  // Original paths (backward compatibility)
9939
- path13.join(root, `/b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9940
- path13.join(root, "core", "mcp", "servers", this.serverName, "dist", "index.js")
9720
+ path12.join(root, `/b4m-core/packages/mcp/dist/src/${this.serverName}/index.js`),
9721
+ path12.join(root, "core", "mcp", "servers", this.serverName, "dist", "index.js")
9941
9722
  ];
9942
9723
  const serverScriptPath = candidatePaths.find((p) => existsSync8(p));
9943
9724
  if (!serverScriptPath) {
@@ -10687,7 +10468,10 @@ var ApiClient = class {
10687
10468
  * Make a POST request
10688
10469
  */
10689
10470
  async post(url, data, config) {
10471
+ logger.debug(`[ApiClient] POST ${this.client.defaults.baseURL}${url}`);
10472
+ logger.debug(`[ApiClient] Request body: ${JSON.stringify(data)}`);
10690
10473
  const response = await this.client.post(url, data, config);
10474
+ logger.debug(`[ApiClient] Response status: ${response.status}`);
10691
10475
  return response.data;
10692
10476
  }
10693
10477
  /**
@@ -10738,7 +10522,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
10738
10522
  // package.json
10739
10523
  var package_default = {
10740
10524
  name: "@bike4mind/cli",
10741
- version: "0.2.8-cli-bash-tools.17140+f678d9888",
10525
+ version: "0.2.8-fix-cli-type-error.17148+5ef98d7d2",
10742
10526
  type: "module",
10743
10527
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
10744
10528
  license: "UNLICENSED",
@@ -10841,10 +10625,10 @@ var package_default = {
10841
10625
  },
10842
10626
  devDependencies: {
10843
10627
  "@bike4mind/agents": "0.1.0",
10844
- "@bike4mind/common": "2.38.2-cli-bash-tools.17140+f678d9888",
10845
- "@bike4mind/mcp": "1.20.2-cli-bash-tools.17140+f678d9888",
10846
- "@bike4mind/services": "2.33.2-cli-bash-tools.17140+f678d9888",
10847
- "@bike4mind/utils": "2.1.3-cli-bash-tools.17140+f678d9888",
10628
+ "@bike4mind/common": "2.38.2-fix-cli-type-error.17148+5ef98d7d2",
10629
+ "@bike4mind/mcp": "1.20.2-fix-cli-type-error.17148+5ef98d7d2",
10630
+ "@bike4mind/services": "2.33.2-fix-cli-type-error.17148+5ef98d7d2",
10631
+ "@bike4mind/utils": "2.1.3-fix-cli-type-error.17148+5ef98d7d2",
10848
10632
  "@types/better-sqlite3": "^7.6.12",
10849
10633
  "@types/diff": "^5.0.9",
10850
10634
  "@types/jsonwebtoken": "^9.0.4",
@@ -10857,7 +10641,7 @@ var package_default = {
10857
10641
  typescript: "^5.9.3",
10858
10642
  vitest: "^3.2.4"
10859
10643
  },
10860
- gitHead: "f678d98888d841ba0496d91a1225dd89edb21e35"
10644
+ gitHead: "5ef98d7d29cde0f6125959fe3a2acc3c5d7f40e6"
10861
10645
  };
10862
10646
 
10863
10647
  // src/config/constants.ts
@@ -10879,7 +10663,7 @@ var usageCache = null;
10879
10663
  function CliApp() {
10880
10664
  const { exit } = useApp();
10881
10665
  const imageRenderer = new ImageRenderer();
10882
- const [state, setState] = useState5({
10666
+ const [state, setState] = useState6({
10883
10667
  session: null,
10884
10668
  sessionStore: new SessionStore(),
10885
10669
  configStore: new ConfigStore(),
@@ -10895,9 +10679,9 @@ function CliApp() {
10895
10679
  trustLocationSelector: null,
10896
10680
  rewindSelector: null
10897
10681
  });
10898
- const [isInitialized, setIsInitialized] = useState5(false);
10899
- const [initError, setInitError] = useState5(null);
10900
- const [commandHistory, setCommandHistory] = useState5([]);
10682
+ const [isInitialized, setIsInitialized] = useState6(false);
10683
+ const [initError, setInitError] = useState6(null);
10684
+ const [commandHistory, setCommandHistory] = useState6([]);
10901
10685
  const imageStoreInitPromise = useRef(null);
10902
10686
  const setStoreSession = useCliStore((state2) => state2.setSession);
10903
10687
  const setPermissionPrompt = useCliStore((state2) => state2.setPermissionPrompt);
@@ -10938,7 +10722,7 @@ function CliApp() {
10938
10722
  process.exit(0);
10939
10723
  }, 100);
10940
10724
  }, [state.session, state.sessionStore, state.mcpManager, state.agent, state.imageStore]);
10941
- useInput4((input, key) => {
10725
+ useInput5((input, key) => {
10942
10726
  if (key.ctrl && input === "c") {
10943
10727
  const now = Date.now();
10944
10728
  if (exitTimestamp && now - exitTimestamp < EXIT_TIMEOUT_MS) {
@@ -11082,10 +10866,6 @@ function CliApp() {
11082
10866
  setPermissionPrompt(prompt);
11083
10867
  });
11084
10868
  };
11085
- console.log("\u{1F511} Tool API Keys:", {
11086
- openweather: config.toolApiKeys?.openweather ? "\u2713 configured" : "\u2717 missing",
11087
- serper: config.toolApiKeys?.serper ? "\u2713 configured" : "\u2717 missing"
11088
- });
11089
10869
  const agentContext = {
11090
10870
  currentAgent: null,
11091
10871
  observationQueue: []
@@ -11098,7 +10878,7 @@ function CliApp() {
11098
10878
  promptFn,
11099
10879
  agentContext,
11100
10880
  state.configStore,
11101
- config.toolApiKeys
10881
+ apiClient
11102
10882
  );
11103
10883
  console.log(`\u{1F6E0}\uFE0F Loaded ${b4mTools.length} B4M tool(s)`);
11104
10884
  const mcpManager = new McpManager(config);
@@ -11196,29 +10976,6 @@ Remember: Use context from previous messages to understand follow-up questions.`
11196
10976
  console.log("\u{1F4A1} Run /login to authenticate with your B4M account.\n");
11197
10977
  return;
11198
10978
  }
11199
- const currentSteps = [];
11200
- const stepHandler = (step) => {
11201
- currentSteps.push(step);
11202
- const currentSession = useCliStore.getState().session;
11203
- if (currentSession) {
11204
- const messages = [...currentSession.messages];
11205
- const lastMessage = messages[messages.length - 1];
11206
- if (lastMessage && lastMessage.role === "assistant") {
11207
- messages[messages.length - 1] = {
11208
- ...lastMessage,
11209
- metadata: {
11210
- ...lastMessage.metadata,
11211
- steps: [...currentSteps]
11212
- }
11213
- };
11214
- setStoreSession({
11215
- ...currentSession,
11216
- messages
11217
- });
11218
- }
11219
- }
11220
- };
11221
- state.agent.on("action", stepHandler);
11222
10979
  try {
11223
10980
  let messageContent = message;
11224
10981
  let userMessageContent = message;
@@ -11232,21 +10989,6 @@ Remember: Use context from previous messages to understand follow-up questions.`
11232
10989
  content: userMessageContent,
11233
10990
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
11234
10991
  };
11235
- const pendingAssistantMessage = {
11236
- role: "assistant",
11237
- content: "...",
11238
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
11239
- metadata: {
11240
- steps: []
11241
- }
11242
- };
11243
- const sessionWithMessages = {
11244
- ...state.session,
11245
- messages: [...state.session.messages, userMessage, pendingAssistantMessage],
11246
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
11247
- };
11248
- setState((prev) => ({ ...prev, session: sessionWithMessages }));
11249
- setStoreSession(sessionWithMessages);
11250
10992
  const recentMessages = state.session.messages.slice(-20);
11251
10993
  const previousMessages = recentMessages.filter((msg) => msg.role === "user" || msg.role === "assistant").map((msg) => ({
11252
10994
  role: msg.role,
@@ -11260,28 +11002,26 @@ Remember: Use context from previous messages to understand follow-up questions.`
11260
11002
  console.log("\n\u26A0\uFE0F Action denied by user\n");
11261
11003
  }
11262
11004
  const successfulToolCalls = result.steps.filter((s) => s.type === "observation").length;
11263
- const currentSession = useCliStore.getState().session;
11264
- if (!currentSession) return;
11265
- const finalMessages = [...currentSession.messages];
11266
- const finalAssistantMessage = {
11005
+ const assistantMessage = {
11267
11006
  role: "assistant",
11268
11007
  content: result.finalAnswer,
11269
- timestamp: pendingAssistantMessage.timestamp,
11008
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
11270
11009
  metadata: {
11271
11010
  tokenUsage: {
11272
11011
  prompt: 0,
11012
+ // TODO: Extract from result
11273
11013
  completion: 0,
11274
11014
  total: result.completionInfo.totalTokens
11275
11015
  },
11276
11016
  steps: result.steps,
11277
11017
  // Complete history: thoughts, actions, observations
11278
11018
  permissionDenied
11019
+ // Mark if this ended due to permission denial
11279
11020
  }
11280
11021
  };
11281
- finalMessages[finalMessages.length - 1] = finalAssistantMessage;
11282
11022
  const updatedSession = {
11283
- ...currentSession,
11284
- messages: finalMessages,
11023
+ ...state.session,
11024
+ messages: [...state.session.messages, userMessage, assistantMessage],
11285
11025
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
11286
11026
  metadata: {
11287
11027
  ...state.session.metadata,
@@ -11301,8 +11041,6 @@ Remember: Use context from previous messages to understand follow-up questions.`
11301
11041
  }
11302
11042
  }
11303
11043
  console.error("Error processing message:", error);
11304
- } finally {
11305
- state.agent.off("action", stepHandler);
11306
11044
  }
11307
11045
  };
11308
11046
  const handleImageDetected = async (imageData) => {
@@ -11854,12 +11592,12 @@ No usage data available for the last ${USAGE_DAYS} days.`);
11854
11592
  setState((prev) => ({ ...prev, config: updatedConfig }));
11855
11593
  };
11856
11594
  if (initError) {
11857
- return /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React14.createElement(Text13, { color: "red", bold: true }, "\u274C Initialization Error"), /* @__PURE__ */ React14.createElement(Text13, null, initError), /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "\n", "Tip: Run /config to set up your API keys"));
11595
+ return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React15.createElement(Text14, { color: "red", bold: true }, "\u274C Initialization Error"), /* @__PURE__ */ React15.createElement(Text14, null, initError), /* @__PURE__ */ React15.createElement(Text14, { dimColor: true }, "\n", "Tip: Run /config to set up your API keys"));
11858
11596
  }
11859
11597
  if (state.trustLocationSelector) {
11860
11598
  const projectDir = state.configStore.getProjectConfigDir();
11861
11599
  const inProject = projectDir !== null;
11862
- return /* @__PURE__ */ React14.createElement(
11600
+ return /* @__PURE__ */ React15.createElement(
11863
11601
  TrustLocationSelector,
11864
11602
  {
11865
11603
  inProject,
@@ -11877,7 +11615,7 @@ No usage data available for the last ${USAGE_DAYS} days.`);
11877
11615
  );
11878
11616
  }
11879
11617
  if (state.rewindSelector && state.session) {
11880
- return /* @__PURE__ */ React14.createElement(
11618
+ return /* @__PURE__ */ React15.createElement(
11881
11619
  RewindSelector,
11882
11620
  {
11883
11621
  messages: state.session.messages,
@@ -11896,7 +11634,7 @@ No usage data available for the last ${USAGE_DAYS} days.`);
11896
11634
  }
11897
11635
  if (state.showLoginFlow) {
11898
11636
  const loginApiUrl = getApiUrl(state.config?.apiConfig);
11899
- return /* @__PURE__ */ React14.createElement(
11637
+ return /* @__PURE__ */ React15.createElement(
11900
11638
  LoginFlow,
11901
11639
  {
11902
11640
  apiUrl: loginApiUrl,
@@ -11919,9 +11657,9 @@ No usage data available for the last ${USAGE_DAYS} days.`);
11919
11657
  );
11920
11658
  }
11921
11659
  if (!isInitialized) {
11922
- return /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React14.createElement(Text13, null, "\u{1F680} Initializing..."));
11660
+ return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React15.createElement(Text14, null, "\u{1F680} Initializing..."));
11923
11661
  }
11924
- return /* @__PURE__ */ React14.createElement(
11662
+ return /* @__PURE__ */ React15.createElement(
11925
11663
  App,
11926
11664
  {
11927
11665
  onMessage: handleMessage,
@@ -11960,6 +11698,6 @@ var isDevMode = import.meta.url.includes("/src/") || process.env.NODE_ENV === "d
11960
11698
  if (isDevMode) {
11961
11699
  console.log("\u{1F527} Running in development mode (using TypeScript source)\n");
11962
11700
  }
11963
- render(/* @__PURE__ */ React14.createElement(CliApp, null), {
11701
+ render(/* @__PURE__ */ React15.createElement(CliApp, null), {
11964
11702
  exitOnCtrlC: false
11965
11703
  });