@bike4mind/cli 0.2.7-basic-cli-shortcuts.17131 → 0.2.7-feat-cli-rewind-command.17128

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +293 -189
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -80,12 +80,12 @@ import {
80
80
 
81
81
  // src/index.tsx
82
82
  import React14, { useState as useState5, useEffect as useEffect3, useCallback, useRef } from "react";
83
- import { render, Box as Box13, Text as Text13, useApp, useInput as useInput4 } from "ink";
83
+ import { render, Box as Box14, Text as Text13, useApp, useInput as useInput4 } from "ink";
84
84
  import { v4 as uuidv49 } from "uuid";
85
85
 
86
86
  // src/components/App.tsx
87
- import React10 from "react";
88
- import { Box as Box9, Text as Text9, Static } from "ink";
87
+ import React9 from "react";
88
+ import { Box as Box9, Text as Text8, Static } from "ink";
89
89
 
90
90
  // src/components/StatusBar.tsx
91
91
  import React from "react";
@@ -95,127 +95,27 @@ var StatusBar = React.memo(function StatusBar2({ sessionName, model, tokenUsage
95
95
  });
96
96
 
97
97
  // src/components/InputPrompt.tsx
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
- }
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";
201
101
 
202
102
  // src/components/CommandAutocomplete.tsx
203
- import React3 from "react";
204
- import { Box as Box2, Text as Text3 } from "ink";
103
+ import React2 from "react";
104
+ import { Box as Box2, Text as Text2 } from "ink";
205
105
  function CommandAutocomplete({ commands, selectedIndex }) {
206
106
  if (commands.length === 0) {
207
- return /* @__PURE__ */ React3.createElement(Box2, { marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "No matching commands"));
107
+ return /* @__PURE__ */ React2.createElement(Box2, { marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "No matching commands"));
208
108
  }
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) => {
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) => {
210
110
  const args = cmd.args ? ` ${cmd.args}` : "";
211
111
  const isSelected = index === selectedIndex;
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));
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));
213
113
  }));
214
114
  }
215
115
 
216
116
  // src/components/FileAutocomplete.tsx
217
- import React4 from "react";
218
- import { Box as Box3, Text as Text4 } from "ink";
117
+ import React3 from "react";
118
+ import { Box as Box3, Text as Text3 } from "ink";
219
119
 
220
120
  // src/utils/fileSearch.ts
221
121
  import * as fs from "fs";
@@ -404,14 +304,14 @@ var MAX_FILE_SIZE = 10 * 1024 * 1024;
404
304
  // src/components/FileAutocomplete.tsx
405
305
  function FileAutocomplete({ files, selectedIndex, query }) {
406
306
  if (files.length === 0) {
407
- return /* @__PURE__ */ React4.createElement(Box3, { marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, "No matching files", query ? ` for "${query}"` : ""));
307
+ return /* @__PURE__ */ React3.createElement(Box3, { marginLeft: 2, marginTop: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "No matching files", query ? ` for "${query}"` : ""));
408
308
  }
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) => {
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) => {
410
310
  const isSelected = index === selectedIndex;
411
311
  const icon = file.isDirectory ? "[folder]" : "[file] ";
412
312
  const sizeDisplay = file.isDirectory ? "" : file.size !== void 0 ? ` (${formatFileSize(file.size)})` : "";
413
313
  const pathDisplay = file.isDirectory ? `${file.path}/` : file.path;
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));
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));
415
315
  }));
416
316
  }
417
317
 
@@ -489,6 +389,11 @@ var COMMANDS = [
489
389
  name: "clear",
490
390
  description: "Start a new session",
491
391
  aliases: ["new"]
392
+ },
393
+ {
394
+ name: "rewind",
395
+ description: "Rewind conversation to a previous point",
396
+ aliases: ["undo"]
492
397
  }
493
398
  ];
494
399
 
@@ -725,13 +630,28 @@ function findAtTrigger(value) {
725
630
  }
726
631
  return null;
727
632
  }
728
- function InputPrompt({ onSubmit, onImageDetected, disabled = false, history = [] }) {
729
- const [value, setValue] = useState2("");
730
- const [selectedIndex, setSelectedIndex] = useState2(0);
731
- const [historyIndex, setHistoryIndex] = useState2(-1);
732
- const [tempInput, setTempInput] = useState2("");
733
- const [fileAutocomplete, setFileAutocomplete] = useState2(null);
734
- const [fileSelectedIndex, setFileSelectedIndex] = useState2(0);
633
+ function InputPrompt({
634
+ onSubmit,
635
+ onImageDetected,
636
+ disabled = false,
637
+ history = [],
638
+ prefillInput,
639
+ onPrefillConsumed
640
+ }) {
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);
646
+ useEffect(() => {
647
+ if (prefillInput) {
648
+ setValue(prefillInput);
649
+ setInputKey((prev) => prev + 1);
650
+ onPrefillConsumed?.();
651
+ }
652
+ }, [prefillInput, onPrefillConsumed]);
653
+ const [fileAutocomplete, setFileAutocomplete] = useState(null);
654
+ const [fileSelectedIndex, setFileSelectedIndex] = useState(0);
735
655
  const shouldShowCommandAutocomplete = value.startsWith("/") && !disabled && !fileAutocomplete?.active;
736
656
  const commandQuery = shouldShowCommandAutocomplete ? value.slice(1) : "";
737
657
  const filteredCommands = useMemo(() => {
@@ -748,7 +668,7 @@ function InputPrompt({ onSubmit, onImageDetected, disabled = false, history = []
748
668
  useEffect(() => {
749
669
  setFileSelectedIndex(0);
750
670
  }, [filteredFiles]);
751
- useInput2((_input, key) => {
671
+ useInput((input, key) => {
752
672
  if (fileAutocomplete?.active && filteredFiles.length > 0) {
753
673
  if (key.upArrow) {
754
674
  setFileSelectedIndex((prev) => prev > 0 ? prev - 1 : filteredFiles.length - 1);
@@ -805,6 +725,7 @@ function InputPrompt({ onSubmit, onImageDetected, disabled = false, history = []
805
725
  const pathToInsert = file.isDirectory ? `@${file.path}/` : `@${file.path}`;
806
726
  const newValue = beforeAt + pathToInsert + afterQuery;
807
727
  setValue(newValue);
728
+ setInputKey((prev) => prev + 1);
808
729
  if (file.isDirectory) {
809
730
  setFileAutocomplete({
810
731
  active: true,
@@ -831,6 +752,7 @@ function InputPrompt({ onSubmit, onImageDetected, disabled = false, history = []
831
752
  if (selectedCommand.args) {
832
753
  setValue(commandText + " ");
833
754
  setHistoryIndex(-1);
755
+ setInputKey((prev) => prev + 1);
834
756
  return;
835
757
  }
836
758
  setValue("");
@@ -849,6 +771,7 @@ function InputPrompt({ onSubmit, onImageDetected, disabled = false, history = []
849
771
  if (imageEvent && onImageDetected) {
850
772
  const placeholder = await onImageDetected(imageEvent.data);
851
773
  setValue(`${placeholder} `);
774
+ setInputKey((prev) => prev + 1);
852
775
  return;
853
776
  }
854
777
  }
@@ -868,28 +791,29 @@ function InputPrompt({ onSubmit, onImageDetected, disabled = false, history = []
868
791
  setFileAutocomplete(null);
869
792
  }
870
793
  };
871
- return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { bold: true, color: "cyan" }, "> "), /* @__PURE__ */ React5.createElement(
872
- CustomTextInput,
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,
873
796
  {
797
+ key: inputKey,
874
798
  value,
875
799
  onChange: handleChange,
876
800
  onSubmit: handleSubmit,
877
801
  placeholder: disabled ? "Thinking..." : "Type your message, /help for commands, or @file to reference",
878
802
  showCursor: !disabled
879
803
  }
880
- )), shouldShowCommandAutocomplete && /* @__PURE__ */ React5.createElement(CommandAutocomplete, { commands: filteredCommands, selectedIndex }), fileAutocomplete?.active && /* @__PURE__ */ React5.createElement(FileAutocomplete, { files: filteredFiles, selectedIndex: fileSelectedIndex, query: fileAutocomplete.query }));
804
+ )), shouldShowCommandAutocomplete && /* @__PURE__ */ React4.createElement(CommandAutocomplete, { commands: filteredCommands, selectedIndex }), fileAutocomplete?.active && /* @__PURE__ */ React4.createElement(FileAutocomplete, { files: filteredFiles, selectedIndex: fileSelectedIndex, query: fileAutocomplete.query }));
881
805
  }
882
806
 
883
807
  // src/components/AgentThinking.tsx
884
- import React7 from "react";
808
+ import React6 from "react";
885
809
  import { Box as Box6 } from "ink";
886
810
 
887
811
  // src/components/ThoughtStream.tsx
888
- import React6 from "react";
889
- import { Box as Box5, Text as Text6 } from "ink";
812
+ import React5 from "react";
813
+ import { Box as Box5, Text as Text5 } from "ink";
890
814
  import Spinner from "ink-spinner";
891
- var ThoughtStream = React6.memo(function ThoughtStream2({ steps }) {
892
- 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...")));
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...")));
893
817
  });
894
818
 
895
819
  // src/store/index.ts
@@ -918,32 +842,32 @@ var useCliStore = create((set) => ({
918
842
  }));
919
843
 
920
844
  // src/components/AgentThinking.tsx
921
- var AgentThinking = React7.memo(function AgentThinking2() {
845
+ var AgentThinking = React6.memo(function AgentThinking2() {
922
846
  const isThinking = useCliStore((state) => state.isThinking);
923
847
  const agentSteps = useCliStore((state) => state.agentSteps);
924
848
  if (!isThinking) {
925
849
  return null;
926
850
  }
927
- return /* @__PURE__ */ React7.createElement(Box6, { borderStyle: "single", borderColor: "yellow", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React7.createElement(ThoughtStream, { steps: agentSteps }));
851
+ return /* @__PURE__ */ React6.createElement(Box6, { borderStyle: "single", borderColor: "yellow", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React6.createElement(ThoughtStream, { steps: agentSteps }));
928
852
  });
929
853
 
930
854
  // src/components/PermissionPrompt.tsx
931
- import React8 from "react";
932
- import { Box as Box7, Text as Text7 } from "ink";
855
+ import React7 from "react";
856
+ import { Box as Box7, Text as Text6 } from "ink";
933
857
  import SelectInput from "ink-select-input";
934
858
  function renderDiffPreview(preview) {
935
859
  const lines = preview.split("\n");
936
860
  return lines.map((line, index) => {
937
861
  if (line.startsWith("+")) {
938
- return /* @__PURE__ */ React8.createElement(Text7, { key: index, color: "green" }, line);
862
+ return /* @__PURE__ */ React7.createElement(Text6, { key: index, color: "green" }, line);
939
863
  }
940
864
  if (line.startsWith("-")) {
941
- return /* @__PURE__ */ React8.createElement(Text7, { key: index, color: "red" }, line);
865
+ return /* @__PURE__ */ React7.createElement(Text6, { key: index, color: "red" }, line);
942
866
  }
943
867
  if (line.startsWith("@@")) {
944
- return /* @__PURE__ */ React8.createElement(Text7, { key: index, color: "cyan" }, line);
868
+ return /* @__PURE__ */ React7.createElement(Text6, { key: index, color: "cyan" }, line);
945
869
  }
946
- return /* @__PURE__ */ React8.createElement(Text7, { key: index, dimColor: true }, line);
870
+ return /* @__PURE__ */ React7.createElement(Text6, { key: index, dimColor: true }, line);
947
871
  });
948
872
  }
949
873
  function PermissionPrompt({
@@ -963,12 +887,12 @@ function PermissionPrompt({
963
887
  { label: "\u2717 Deny", value: "deny" }
964
888
  ];
965
889
  const argsString = typeof args === "string" ? args : JSON.stringify(args, null, 2);
966
- 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) })));
890
+ 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) })));
967
891
  }
968
892
 
969
893
  // src/components/ConfigEditor.tsx
970
- import React9, { useState as useState3, useMemo as useMemo2 } from "react";
971
- import { Box as Box8, Text as Text8, useInput as useInput3 } from "ink";
894
+ import React8, { useState as useState2, useMemo as useMemo2 } from "react";
895
+ import { Box as Box8, Text as Text7, useInput as useInput2 } from "ink";
972
896
  var MAX_ITERATIONS_OPTIONS = [
973
897
  { label: "10", value: 10 },
974
898
  { label: "20", value: 20 },
@@ -1099,10 +1023,10 @@ function buildConfigItems(availableModels) {
1099
1023
  return items;
1100
1024
  }
1101
1025
  function ConfigEditor({ config, availableModels, onSave, onClose }) {
1102
- const [selectedIndex, setSelectedIndex] = useState3(0);
1103
- const [editedConfig, setEditedConfig] = useState3(config);
1104
- const [saveError, setSaveError] = useState3(null);
1105
- const [isSaving, setIsSaving] = useState3(false);
1026
+ const [selectedIndex, setSelectedIndex] = useState2(0);
1027
+ const [editedConfig, setEditedConfig] = useState2(config);
1028
+ const [saveError, setSaveError] = useState2(null);
1029
+ const [isSaving, setIsSaving] = useState2(false);
1106
1030
  const configItems = useMemo2(() => buildConfigItems(availableModels), [availableModels]);
1107
1031
  const hasChanges = useMemo2(() => {
1108
1032
  return JSON.stringify(config.preferences) !== JSON.stringify(editedConfig.preferences) || config.defaultModel !== editedConfig.defaultModel;
@@ -1122,7 +1046,7 @@ function ConfigEditor({ config, availableModels, onSave, onClose }) {
1122
1046
  }
1123
1047
  onClose();
1124
1048
  };
1125
- useInput3((input, key) => {
1049
+ useInput2((input, key) => {
1126
1050
  const currentItem = configItems[selectedIndex];
1127
1051
  if (key.upArrow) {
1128
1052
  setSelectedIndex((prev) => prev > 0 ? prev - 1 : configItems.length - 1);
@@ -1187,13 +1111,13 @@ function ConfigEditor({ config, availableModels, onSave, onClose }) {
1187
1111
  }
1188
1112
  return String(value);
1189
1113
  };
1190
- 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) => {
1114
+ 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) => {
1191
1115
  const isSelected = index === selectedIndex;
1192
1116
  const value = item.getValue(editedConfig);
1193
1117
  const displayValue = formatValue(item, value);
1194
1118
  const hasOptions = item.type === "select" || item.type === "boolean" || item.type === "number";
1195
- 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 }, " >")));
1196
- })), /* @__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")));
1119
+ 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 }, " >")));
1120
+ })), /* @__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")));
1197
1121
  }
1198
1122
 
1199
1123
  // src/utils/processFileReferences.ts
@@ -1319,7 +1243,9 @@ function App({
1319
1243
  commandHistory = [],
1320
1244
  config,
1321
1245
  availableModels = [],
1322
- onSaveConfig
1246
+ onSaveConfig,
1247
+ prefillInput,
1248
+ onPrefillConsumed
1323
1249
  }) {
1324
1250
  const messages = useCliStore((state) => state.session?.messages || []);
1325
1251
  const sessionName = useCliStore((state) => state.session?.name || "New Session");
@@ -1331,7 +1257,7 @@ function App({
1331
1257
  const setShowConfigEditor = useCliStore((state) => state.setShowConfigEditor);
1332
1258
  const exitRequested = useCliStore((state) => state.exitRequested);
1333
1259
  const setIsThinking = useCliStore((state) => state.setIsThinking);
1334
- const handleSubmit = React10.useCallback(
1260
+ const handleSubmit = React9.useCallback(
1335
1261
  async (input) => {
1336
1262
  const trimmed = input.trim();
1337
1263
  if (!trimmed) return;
@@ -1360,7 +1286,7 @@ ${errorBlock}`;
1360
1286
  },
1361
1287
  [onMessage, onCommand, setIsThinking]
1362
1288
  );
1363
- 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(
1289
+ 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(
1364
1290
  ConfigEditor,
1365
1291
  {
1366
1292
  config,
@@ -1368,7 +1294,7 @@ ${errorBlock}`;
1368
1294
  onSave: onSaveConfig,
1369
1295
  onClose: () => setShowConfigEditor(false)
1370
1296
  }
1371
- )) : permissionPrompt ? /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React10.createElement(
1297
+ )) : permissionPrompt ? /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React9.createElement(
1372
1298
  PermissionPrompt,
1373
1299
  {
1374
1300
  toolName: permissionPrompt.toolName,
@@ -1377,47 +1303,49 @@ ${errorBlock}`;
1377
1303
  canBeTrusted: permissionPrompt.canBeTrusted,
1378
1304
  onResponse: onPermissionResponse
1379
1305
  }
1380
- )) : /* @__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(
1306
+ )) : /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(Static, { items: messages }, (message, index) => /* @__PURE__ */ React9.createElement(Box9, { key: index, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React9.createElement(MessageItem, { message }))), /* @__PURE__ */ React9.createElement(AgentThinking, null), exitRequested && /* @__PURE__ */ React9.createElement(Box9, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text8, { color: "yellow", bold: true }, "Press Ctrl+C again to exit")), /* @__PURE__ */ React9.createElement(Box9, { borderStyle: "single", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React9.createElement(
1381
1307
  InputPrompt,
1382
1308
  {
1383
1309
  onSubmit: handleSubmit,
1384
1310
  onImageDetected,
1385
1311
  disabled: isThinking,
1386
- history: commandHistory
1312
+ history: commandHistory,
1313
+ prefillInput,
1314
+ onPrefillConsumed
1387
1315
  }
1388
1316
  ))));
1389
1317
  }
1390
1318
  function MessageItem({ message }) {
1391
- 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) => {
1319
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Box9, null, /* @__PURE__ */ React9.createElement(Text8, { bold: true, color: message.role === "user" ? "cyan" : "green" }, message.role === "user" ? "\u{1F464} You" : "\u{1F916} Assistant"), /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, " \u2022 ", new Date(message.timestamp).toLocaleTimeString())), /* @__PURE__ */ React9.createElement(Box9, { paddingLeft: 2 }, message.metadata?.permissionDenied ? /* @__PURE__ */ React9.createElement(Text8, { color: "yellow" }, "\u26A0\uFE0F ", message.content) : /* @__PURE__ */ React9.createElement(Text8, null, message.content)), message.metadata?.steps && message.metadata.steps.length > 0 && /* @__PURE__ */ React9.createElement(Box9, { paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true, bold: true }, "\u{1F527} Agent Reasoning Trace (", message.metadata.steps.filter((s) => s.type === "action").length, " ", "tools used, ", message.metadata.steps.length, " total steps)", message.metadata.tokenUsage && ` \u2022 ${message.metadata.tokenUsage.total} tokens`), /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, "Step types: ", message.metadata.steps.map((s) => s.type).join(", ")), message.metadata.steps.map((step, idx) => {
1392
1320
  if (step.type === "thought") {
1393
- 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 ? "..." : ""}`));
1321
+ 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 ? "..." : ""}`));
1394
1322
  }
1395
1323
  if (step.type === "action") {
1396
1324
  const toolName = step.metadata?.toolName || "unknown";
1397
1325
  const toolInput = step.metadata?.toolInput;
1398
1326
  const observationStep = message.metadata.steps[idx + 1];
1399
1327
  const result = observationStep?.type === "observation" ? observationStep.content : null;
1400
- 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 ? "..." : ""}`));
1328
+ 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 ? "..." : ""}`));
1401
1329
  }
1402
1330
  return null;
1403
- }).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`)));
1331
+ }).filter(Boolean)), message.metadata?.tokenUsage && (!message.metadata.steps || message.metadata.steps.length === 0) && /* @__PURE__ */ React9.createElement(Box9, { paddingLeft: 2 }, /* @__PURE__ */ React9.createElement(Text8, { dimColor: true }, `${message.metadata.tokenUsage.total} tokens`)));
1404
1332
  }
1405
1333
 
1406
1334
  // src/components/MessageList.tsx
1407
- import React11 from "react";
1408
- import { Box as Box10, Text as Text10 } from "ink";
1335
+ import React10 from "react";
1336
+ import { Box as Box10, Text as Text9 } from "ink";
1409
1337
  function stripThinkingTags(content) {
1410
1338
  return content.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
1411
1339
  }
1412
- var MessageList = React11.memo(
1340
+ var MessageList = React10.memo(
1413
1341
  function MessageList2({ messages }) {
1414
1342
  if (messages.length === 0) {
1415
- return /* @__PURE__ */ React11.createElement(Box10, { paddingY: 1 }, /* @__PURE__ */ React11.createElement(Text10, { dimColor: true }, "No messages yet. Type a message to start!"));
1343
+ return /* @__PURE__ */ React10.createElement(Box10, { paddingY: 1 }, /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, "No messages yet. Type a message to start!"));
1416
1344
  }
1417
- 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) => {
1345
+ 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) => {
1418
1346
  if (step.type === "thought") {
1419
- 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(
1420
- Text10,
1347
+ 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(
1348
+ Text9,
1421
1349
  {
1422
1350
  dimColor: true
1423
1351
  },
@@ -1429,10 +1357,10 @@ var MessageList = React11.memo(
1429
1357
  const toolInput = step.metadata?.toolInput;
1430
1358
  const observationStep = message.metadata.steps[idx + 1];
1431
1359
  const result = observationStep?.type === "observation" ? observationStep.content : null;
1432
- 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 ? "..." : ""}`));
1360
+ 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 ? "..." : ""}`));
1433
1361
  }
1434
1362
  return null;
1435
- }).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`)))));
1363
+ }).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`)))));
1436
1364
  },
1437
1365
  (prevProps, nextProps) => {
1438
1366
  if (prevProps.messages.length !== nextProps.messages.length) {
@@ -1443,8 +1371,8 @@ var MessageList = React11.memo(
1443
1371
  );
1444
1372
 
1445
1373
  // src/components/TrustLocationSelector.tsx
1446
- import React12 from "react";
1447
- import { Box as Box11, Text as Text11 } from "ink";
1374
+ import React11 from "react";
1375
+ import { Box as Box11, Text as Text10 } from "ink";
1448
1376
  import SelectInput2 from "ink-select-input";
1449
1377
  function TrustLocationSelector({ inProject, onSelect, onCancel }) {
1450
1378
  const items = [];
@@ -1465,19 +1393,88 @@ function TrustLocationSelector({ inProject, onSelect, onCancel }) {
1465
1393
  const handleSelect = (item) => {
1466
1394
  onSelect(item.value);
1467
1395
  };
1468
- 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(
1396
+ 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(
1469
1397
  SelectInput2,
1470
1398
  {
1471
1399
  items,
1472
1400
  onSelect: handleSelect,
1473
- itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React12.createElement(Box11, null, /* @__PURE__ */ React12.createElement(Text11, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
1401
+ itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Text10, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
1402
+ }
1403
+ ), /* @__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")));
1404
+ }
1405
+
1406
+ // src/components/RewindSelector.tsx
1407
+ import React12, { useState as useState3 } from "react";
1408
+ import { Box as Box12, Text as Text11, useInput as useInput3 } from "ink";
1409
+ import SelectInput3 from "ink-select-input";
1410
+ function RewindSelector({ messages, onSelect, onCancel }) {
1411
+ const [step, setStep] = useState3("selection");
1412
+ const [selectedMessageIndex, setSelectedMessageIndex] = useState3(null);
1413
+ useInput3((input, key) => {
1414
+ if (key.escape) {
1415
+ if (step === "confirmation") {
1416
+ setStep("selection");
1417
+ setSelectedMessageIndex(null);
1418
+ } else {
1419
+ onCancel();
1420
+ }
1421
+ }
1422
+ });
1423
+ const userMessages = messages.map((msg, idx) => ({ msg, originalIndex: idx })).filter(({ msg }) => msg.role === "user");
1424
+ const items = userMessages.map(({ msg, originalIndex }, index) => {
1425
+ const preview = msg.content.length > 50 ? msg.content.substring(0, 50) + "..." : msg.content;
1426
+ const timestamp = new Date(msg.timestamp).toLocaleString();
1427
+ const position = index + 1;
1428
+ return {
1429
+ label: `[${position}] ${timestamp} - ${preview}`,
1430
+ value: originalIndex
1431
+ };
1432
+ });
1433
+ const handleSelectionSelect = (item) => {
1434
+ setSelectedMessageIndex(item.value);
1435
+ setStep("confirmation");
1436
+ };
1437
+ const handleConfirmationSelect = (item) => {
1438
+ if (item.value === "confirm" && selectedMessageIndex !== null) {
1439
+ onSelect(selectedMessageIndex);
1440
+ } else {
1441
+ setStep("selection");
1442
+ setSelectedMessageIndex(null);
1443
+ }
1444
+ };
1445
+ const messagesToRemove = selectedMessageIndex !== null && selectedMessageIndex >= 0 && selectedMessageIndex < messages.length ? messages.slice(selectedMessageIndex) : [];
1446
+ const tokensToRemove = messagesToRemove.reduce((sum2, msg) => {
1447
+ return sum2 + (msg.metadata?.tokenUsage?.total || 0);
1448
+ }, 0);
1449
+ if (step === "selection") {
1450
+ 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(
1451
+ SelectInput3,
1452
+ {
1453
+ items,
1454
+ onSelect: handleSelectionSelect,
1455
+ itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React12.createElement(Box12, null, /* @__PURE__ */ React12.createElement(Text11, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
1456
+ }
1457
+ ), /* @__PURE__ */ React12.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Esc to cancel")));
1458
+ }
1459
+ const confirmationItems = [
1460
+ { label: "Yes, rewind to this point", value: "confirm" },
1461
+ { label: "No, go back to selection", value: "cancel" }
1462
+ ];
1463
+ const selectedMessage = selectedMessageIndex !== null && selectedMessageIndex >= 0 && selectedMessageIndex < messages.length ? messages[selectedMessageIndex] : null;
1464
+ const selectedPreview = selectedMessage ? selectedMessage.content.length > 50 ? selectedMessage.content.substring(0, 50) + "..." : selectedMessage.content : "";
1465
+ 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(
1466
+ SelectInput3,
1467
+ {
1468
+ items: confirmationItems,
1469
+ onSelect: handleConfirmationSelect,
1470
+ itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React12.createElement(Box12, null, /* @__PURE__ */ React12.createElement(Text11, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
1474
1471
  }
1475
- ), /* @__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")));
1472
+ ), /* @__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")));
1476
1473
  }
1477
1474
 
1478
1475
  // src/components/LoginFlow.tsx
1479
1476
  import React13, { useState as useState4, useEffect as useEffect2 } from "react";
1480
- import { Box as Box12, Text as Text12 } from "ink";
1477
+ import { Box as Box13, Text as Text12 } from "ink";
1481
1478
  import Spinner2 from "ink-spinner";
1482
1479
  import jwt from "jsonwebtoken";
1483
1480
  import open from "open";
@@ -1640,15 +1637,15 @@ function LoginFlow({ apiUrl = "http://localhost:3000", configStore, onSuccess, o
1640
1637
  }
1641
1638
  }, [deviceFlow, status]);
1642
1639
  if (status === "initiating") {
1643
- return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React13.createElement(Box12, null, /* @__PURE__ */ React13.createElement(Text12, { color: "cyan" }, /* @__PURE__ */ React13.createElement(Spinner2, { type: "dots" }), " Initiating device authorization...")));
1640
+ 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...")));
1644
1641
  }
1645
1642
  if (status === "error") {
1646
- return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React13.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text12, { color: "red", bold: true }, "\u2716 Authentication Failed")), /* @__PURE__ */ React13.createElement(Box12, null, /* @__PURE__ */ React13.createElement(Text12, { color: "red" }, error)));
1643
+ 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)));
1647
1644
  }
1648
1645
  if (status === "success") {
1649
- return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React13.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text12, { color: "green", bold: true }, "\u2714 Successfully authenticated!")), /* @__PURE__ */ React13.createElement(Box12, null, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "You can now use B4M CLI with your account.")));
1646
+ 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.")));
1650
1647
  }
1651
- return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan" }, /* @__PURE__ */ React13.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text12, { color: "cyan", bold: true }, "\u{1F510} Device Authorization")), /* @__PURE__ */ React13.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text12, null, "Opening browser automatically... If it doesn't open, please visit:")), /* @__PURE__ */ React13.createElement(Box12, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React13.createElement(Text12, { color: "blue", bold: true }, deviceFlow?.verification_uri)), /* @__PURE__ */ React13.createElement(Box12, { marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text12, null, "And enter this code when prompted:")), /* @__PURE__ */ React13.createElement(Box12, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React13.createElement(Text12, { color: "yellow", bold: true }, deviceFlow?.user_code)), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text12, { color: "cyan" }, /* @__PURE__ */ React13.createElement(Spinner2, { type: "dots" }), " ", statusMessage)), /* @__PURE__ */ React13.createElement(Box12, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text12, { dimColor: true }, "Expires in ", deviceFlow ? Math.floor(deviceFlow.expires_in / 60) : 0, " minutes")));
1648
+ 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")));
1652
1649
  }
1653
1650
 
1654
1651
  // src/storage/SessionStore.ts
@@ -10356,7 +10353,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
10356
10353
  // package.json
10357
10354
  var package_default = {
10358
10355
  name: "@bike4mind/cli",
10359
- version: "0.2.7-basic-cli-shortcuts.17131+b79f34724",
10356
+ version: "0.2.7-feat-cli-rewind-command.17128+8d4de110f",
10360
10357
  type: "module",
10361
10358
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
10362
10359
  license: "UNLICENSED",
@@ -10459,10 +10456,10 @@ var package_default = {
10459
10456
  },
10460
10457
  devDependencies: {
10461
10458
  "@bike4mind/agents": "0.1.0",
10462
- "@bike4mind/common": "2.38.1-basic-cli-shortcuts.17131+b79f34724",
10463
- "@bike4mind/mcp": "1.20.1-basic-cli-shortcuts.17131+b79f34724",
10464
- "@bike4mind/services": "2.33.1-basic-cli-shortcuts.17131+b79f34724",
10465
- "@bike4mind/utils": "2.1.2-basic-cli-shortcuts.17131+b79f34724",
10459
+ "@bike4mind/common": "2.38.1-feat-cli-rewind-command.17128+8d4de110f",
10460
+ "@bike4mind/mcp": "1.20.1-feat-cli-rewind-command.17128+8d4de110f",
10461
+ "@bike4mind/services": "2.33.1-feat-cli-rewind-command.17128+8d4de110f",
10462
+ "@bike4mind/utils": "2.1.2-feat-cli-rewind-command.17128+8d4de110f",
10466
10463
  "@types/better-sqlite3": "^7.6.12",
10467
10464
  "@types/diff": "^5.0.9",
10468
10465
  "@types/jsonwebtoken": "^9.0.4",
@@ -10475,7 +10472,7 @@ var package_default = {
10475
10472
  typescript: "^5.9.3",
10476
10473
  vitest: "^3.2.4"
10477
10474
  },
10478
- gitHead: "b79f34724ba9a60aae19010065d78ac75c2f8396"
10475
+ gitHead: "8d4de110f7d8f55bff6bd26cb38b8ca1d4dbd996"
10479
10476
  };
10480
10477
 
10481
10478
  // src/config/constants.ts
@@ -10510,7 +10507,8 @@ function CliApp() {
10510
10507
  mcpManager: null,
10511
10508
  permissionManager: null,
10512
10509
  permissionPrompt: null,
10513
- trustLocationSelector: null
10510
+ trustLocationSelector: null,
10511
+ rewindSelector: null
10514
10512
  });
10515
10513
  const [isInitialized, setIsInitialized] = useState5(false);
10516
10514
  const [initError, setInitError] = useState5(null);
@@ -10909,6 +10907,30 @@ Remember: Use context from previous messages to understand follow-up questions.`
10909
10907
  throw error;
10910
10908
  }
10911
10909
  };
10910
+ const recalculateSessionMetadata = (messages) => {
10911
+ let totalTokens = 0;
10912
+ let totalCost = 0;
10913
+ let toolCallCount = 0;
10914
+ for (const msg of messages) {
10915
+ if (msg.metadata) {
10916
+ if (msg.metadata.tokenUsage) {
10917
+ totalTokens += msg.metadata.tokenUsage.total || 0;
10918
+ }
10919
+ if (msg.metadata.cost) {
10920
+ totalCost += msg.metadata.cost;
10921
+ }
10922
+ if (msg.metadata.steps) {
10923
+ const observations = msg.metadata.steps.filter((s) => s.type === "observation");
10924
+ toolCallCount += observations.length;
10925
+ }
10926
+ }
10927
+ }
10928
+ return {
10929
+ totalTokens,
10930
+ totalCost,
10931
+ toolCallCount
10932
+ };
10933
+ };
10912
10934
  const handleCommand = async (command, args) => {
10913
10935
  switch (command) {
10914
10936
  case "help":
@@ -10917,6 +10939,7 @@ Available commands:
10917
10939
  /help - Show this help message
10918
10940
  /exit - Exit the CLI
10919
10941
  /clear - Start a new session
10942
+ /rewind - Rewind conversation to a previous point
10920
10943
  /login - Authenticate with your B4M account
10921
10944
  /logout - Clear authentication and sign out
10922
10945
  /whoami - Show current authenticated user
@@ -11192,6 +11215,65 @@ Project Configuration:
11192
11215
  `);
11193
11216
  break;
11194
11217
  }
11218
+ case "rewind":
11219
+ case "undo": {
11220
+ if (!state.session) {
11221
+ console.log("No active session to rewind");
11222
+ return;
11223
+ }
11224
+ if (state.session.messages.length === 0) {
11225
+ console.log("\u26A0\uFE0F Conversation is empty. Nothing to rewind.");
11226
+ return;
11227
+ }
11228
+ const userMessages = state.session.messages.filter((msg) => msg.role === "user");
11229
+ if (userMessages.length === 0) {
11230
+ console.log("\u26A0\uFE0F No user messages found. Nothing to rewind.");
11231
+ return;
11232
+ }
11233
+ if (userMessages.length === 1) {
11234
+ console.log("\u26A0\uFE0F Only one exchange in the conversation. Use /clear to start a new session instead.");
11235
+ return;
11236
+ }
11237
+ const handleRewindSelect = async (messageIndex) => {
11238
+ setState((prev) => ({ ...prev, rewindSelector: null }));
11239
+ if (messageIndex === null) {
11240
+ console.log("\u274C Rewind operation cancelled");
11241
+ return;
11242
+ }
11243
+ if (!state.session) {
11244
+ console.log("\u274C No active session");
11245
+ return;
11246
+ }
11247
+ const selectedMessage = state.session.messages[messageIndex];
11248
+ const prefillContent = selectedMessage?.content || "";
11249
+ const rewindedMessages = state.session.messages.slice(0, messageIndex);
11250
+ const newMetadata = recalculateSessionMetadata(rewindedMessages);
11251
+ const rewindedSession = {
11252
+ ...state.session,
11253
+ messages: rewindedMessages,
11254
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
11255
+ metadata: newMetadata
11256
+ };
11257
+ setState((prev) => ({
11258
+ ...prev,
11259
+ session: rewindedSession,
11260
+ prefillInput: prefillContent
11261
+ }));
11262
+ setStoreSession(rewindedSession);
11263
+ await state.sessionStore.save(rewindedSession);
11264
+ console.log("\u2705 Conversation rewound successfully");
11265
+ console.log(`\u{1F4CA} Current state: ${rewindedMessages.length} messages, ${newMetadata.totalTokens} tokens`);
11266
+ console.log(`\u{1F4DD} Your message has been placed in the input. Edit and send when ready.
11267
+ `);
11268
+ };
11269
+ setState((prev) => ({
11270
+ ...prev,
11271
+ rewindSelector: {
11272
+ resolve: handleRewindSelect
11273
+ }
11274
+ }));
11275
+ break;
11276
+ }
11195
11277
  case "usage": {
11196
11278
  const usageAuthTokens = await state.configStore.getAuthTokens();
11197
11279
  if (!usageAuthTokens || new Date(usageAuthTokens.expiresAt) <= /* @__PURE__ */ new Date()) {
@@ -11345,7 +11427,7 @@ No usage data available for the last ${USAGE_DAYS} days.`);
11345
11427
  setState((prev) => ({ ...prev, config: updatedConfig }));
11346
11428
  };
11347
11429
  if (initError) {
11348
- return /* @__PURE__ */ React14.createElement(Box13, { 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"));
11430
+ 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"));
11349
11431
  }
11350
11432
  if (state.trustLocationSelector) {
11351
11433
  const projectDir = state.configStore.getProjectConfigDir();
@@ -11367,6 +11449,24 @@ No usage data available for the last ${USAGE_DAYS} days.`);
11367
11449
  }
11368
11450
  );
11369
11451
  }
11452
+ if (state.rewindSelector && state.session) {
11453
+ return /* @__PURE__ */ React14.createElement(
11454
+ RewindSelector,
11455
+ {
11456
+ messages: state.session.messages,
11457
+ onSelect: (messageIndex) => {
11458
+ if (state.rewindSelector) {
11459
+ state.rewindSelector.resolve(messageIndex);
11460
+ }
11461
+ },
11462
+ onCancel: () => {
11463
+ if (state.rewindSelector) {
11464
+ state.rewindSelector.resolve(null);
11465
+ }
11466
+ }
11467
+ }
11468
+ );
11469
+ }
11370
11470
  if (state.showLoginFlow) {
11371
11471
  const loginApiUrl = getApiUrl(state.config?.apiConfig);
11372
11472
  return /* @__PURE__ */ React14.createElement(
@@ -11392,7 +11492,7 @@ No usage data available for the last ${USAGE_DAYS} days.`);
11392
11492
  );
11393
11493
  }
11394
11494
  if (!isInitialized) {
11395
- return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React14.createElement(Text13, null, "\u{1F680} Initializing..."));
11495
+ return /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React14.createElement(Text13, null, "\u{1F680} Initializing..."));
11396
11496
  }
11397
11497
  return /* @__PURE__ */ React14.createElement(
11398
11498
  App,
@@ -11404,6 +11504,10 @@ No usage data available for the last ${USAGE_DAYS} days.`);
11404
11504
  config: state.config,
11405
11505
  availableModels: state.availableModels,
11406
11506
  onSaveConfig: handleSaveConfig,
11507
+ prefillInput: state.prefillInput,
11508
+ onPrefillConsumed: () => {
11509
+ setState((prev) => ({ ...prev, prefillInput: void 0 }));
11510
+ },
11407
11511
  onPermissionResponse: (response) => {
11408
11512
  if (state.permissionPrompt) {
11409
11513
  state.permissionPrompt.resolve({ action: response });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.7-basic-cli-shortcuts.17131+b79f34724",
3
+ "version": "0.2.7-feat-cli-rewind-command.17128+8d4de110f",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -103,10 +103,10 @@
103
103
  },
104
104
  "devDependencies": {
105
105
  "@bike4mind/agents": "0.1.0",
106
- "@bike4mind/common": "2.38.1-basic-cli-shortcuts.17131+b79f34724",
107
- "@bike4mind/mcp": "1.20.1-basic-cli-shortcuts.17131+b79f34724",
108
- "@bike4mind/services": "2.33.1-basic-cli-shortcuts.17131+b79f34724",
109
- "@bike4mind/utils": "2.1.2-basic-cli-shortcuts.17131+b79f34724",
106
+ "@bike4mind/common": "2.38.1-feat-cli-rewind-command.17128+8d4de110f",
107
+ "@bike4mind/mcp": "1.20.1-feat-cli-rewind-command.17128+8d4de110f",
108
+ "@bike4mind/services": "2.33.1-feat-cli-rewind-command.17128+8d4de110f",
109
+ "@bike4mind/utils": "2.1.2-feat-cli-rewind-command.17128+8d4de110f",
110
110
  "@types/better-sqlite3": "^7.6.12",
111
111
  "@types/diff": "^5.0.9",
112
112
  "@types/jsonwebtoken": "^9.0.4",
@@ -119,5 +119,5 @@
119
119
  "typescript": "^5.9.3",
120
120
  "vitest": "^3.2.4"
121
121
  },
122
- "gitHead": "b79f34724ba9a60aae19010065d78ac75c2f8396"
122
+ "gitHead": "8d4de110f7d8f55bff6bd26cb38b8ca1d4dbd996"
123
123
  }