@bike4mind/cli 0.2.12-cli-todo-list.17408 → 0.2.12-ctrl-c-clear-input.17412

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 +155 -82
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -773,6 +773,63 @@ var ImageInputDetector = class {
773
773
  }
774
774
  };
775
775
 
776
+ // src/store/index.ts
777
+ import { create } from "zustand";
778
+ var useCliStore = create((set) => ({
779
+ // Session state
780
+ session: null,
781
+ setSession: (session) => set({ session }),
782
+ addMessage: (message) => set((state) => {
783
+ if (!state.session) return state;
784
+ return {
785
+ session: {
786
+ ...state.session,
787
+ messages: [...state.session.messages, message],
788
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
789
+ }
790
+ };
791
+ }),
792
+ // Pending messages
793
+ pendingMessages: [],
794
+ addPendingMessage: (message) => set((state) => ({ pendingMessages: [...state.pendingMessages, message] })),
795
+ updatePendingMessage: (index, message) => set((state) => {
796
+ const updated = [...state.pendingMessages];
797
+ updated[index] = message;
798
+ return { pendingMessages: updated };
799
+ }),
800
+ clearPendingMessages: () => set({ pendingMessages: [] }),
801
+ completePendingMessage: (index, finalMessage) => set((state) => {
802
+ const pending = [...state.pendingMessages];
803
+ pending.splice(index, 1);
804
+ const session = state.session;
805
+ if (!session) return { pendingMessages: pending };
806
+ return {
807
+ pendingMessages: pending,
808
+ session: {
809
+ ...session,
810
+ messages: [...session.messages, finalMessage],
811
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
812
+ }
813
+ };
814
+ }),
815
+ // UI state
816
+ isThinking: false,
817
+ setIsThinking: (thinking) => set({ isThinking: thinking }),
818
+ // Input state (for Ctrl+C clearing)
819
+ inputValue: "",
820
+ setInputValue: (value) => set({ inputValue: value }),
821
+ clearInput: () => set({ inputValue: "" }),
822
+ // Permission prompt
823
+ permissionPrompt: null,
824
+ setPermissionPrompt: (prompt) => set({ permissionPrompt: prompt }),
825
+ // Config editor
826
+ showConfigEditor: false,
827
+ setShowConfigEditor: (show) => set({ showConfigEditor: show }),
828
+ // Exit handling
829
+ exitRequested: false,
830
+ setExitRequested: (requested) => set({ exitRequested: requested })
831
+ }));
832
+
776
833
  // src/components/InputPrompt.tsx
777
834
  function looksLikeFilePath(input) {
778
835
  const trimmed = input.trim();
@@ -810,7 +867,9 @@ function InputPrompt({
810
867
  onPrefillConsumed,
811
868
  onBashModeChange
812
869
  }) {
813
- const [value, setValue] = useState2("");
870
+ const value = useCliStore((state) => state.inputValue);
871
+ const setInputValue = useCliStore((state) => state.setInputValue);
872
+ const setValue = setInputValue;
814
873
  const [selectedIndex, setSelectedIndex] = useState2(0);
815
874
  const [historyIndex, setHistoryIndex] = useState2(-1);
816
875
  const [tempInput, setTempInput] = useState2("");
@@ -866,10 +925,11 @@ function InputPrompt({
866
925
  if (shouldShowCommandAutocomplete && filteredCommands.length > 0) {
867
926
  if (key.upArrow) {
868
927
  setSelectedIndex((prev) => prev > 0 ? prev - 1 : filteredCommands.length - 1);
928
+ return;
869
929
  } else if (key.downArrow) {
870
930
  setSelectedIndex((prev) => prev < filteredCommands.length - 1 ? prev + 1 : 0);
931
+ return;
871
932
  }
872
- return;
873
933
  }
874
934
  if (!shouldShowCommandAutocomplete && !fileAutocomplete?.active && history.length > 0) {
875
935
  if (key.upArrow) {
@@ -1007,59 +1067,6 @@ var ThoughtStream = React6.memo(function ThoughtStream2({ isThinking }) {
1007
1067
  return /* @__PURE__ */ React6.createElement(Box5, { flexDirection: "column", gap: 1 }, isThinking && /* @__PURE__ */ React6.createElement(Box5, null, /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, /* @__PURE__ */ React6.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React6.createElement(Text6, null, " Thinking...")));
1008
1068
  });
1009
1069
 
1010
- // src/store/index.ts
1011
- import { create } from "zustand";
1012
- var useCliStore = create((set) => ({
1013
- // Session state
1014
- session: null,
1015
- setSession: (session) => set({ session }),
1016
- addMessage: (message) => set((state) => {
1017
- if (!state.session) return state;
1018
- return {
1019
- session: {
1020
- ...state.session,
1021
- messages: [...state.session.messages, message],
1022
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1023
- }
1024
- };
1025
- }),
1026
- // Pending messages
1027
- pendingMessages: [],
1028
- addPendingMessage: (message) => set((state) => ({ pendingMessages: [...state.pendingMessages, message] })),
1029
- updatePendingMessage: (index, message) => set((state) => {
1030
- const updated = [...state.pendingMessages];
1031
- updated[index] = message;
1032
- return { pendingMessages: updated };
1033
- }),
1034
- clearPendingMessages: () => set({ pendingMessages: [] }),
1035
- completePendingMessage: (index, finalMessage) => set((state) => {
1036
- const pending = [...state.pendingMessages];
1037
- pending.splice(index, 1);
1038
- const session = state.session;
1039
- if (!session) return { pendingMessages: pending };
1040
- return {
1041
- pendingMessages: pending,
1042
- session: {
1043
- ...session,
1044
- messages: [...session.messages, finalMessage],
1045
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1046
- }
1047
- };
1048
- }),
1049
- // UI state
1050
- isThinking: false,
1051
- setIsThinking: (thinking) => set({ isThinking: thinking }),
1052
- // Permission prompt
1053
- permissionPrompt: null,
1054
- setPermissionPrompt: (prompt) => set({ permissionPrompt: prompt }),
1055
- // Config editor
1056
- showConfigEditor: false,
1057
- setShowConfigEditor: (show) => set({ showConfigEditor: show }),
1058
- // Exit handling
1059
- exitRequested: false,
1060
- setExitRequested: (requested) => set({ exitRequested: requested })
1061
- }));
1062
-
1063
1070
  // src/components/AgentThinking.tsx
1064
1071
  var AgentThinking = React7.memo(function AgentThinking2() {
1065
1072
  const isThinking = useCliStore((state) => state.isThinking);
@@ -1348,7 +1355,7 @@ function MessageItem({ message }) {
1348
1355
  const isUser = message.role === "user";
1349
1356
  return /* @__PURE__ */ React10.createElement(Box9, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Box9, null, /* @__PURE__ */ React10.createElement(Text9, { bold: true, color: isUser ? "cyan" : "green" }, isUser ? "\u{1F464} You" : "\u{1F916} Assistant"), isUser && /* @__PURE__ */ React10.createElement(Text9, { dimColor: true }, " \u2022 ", new Date(message.timestamp).toLocaleTimeString())), isUser && message.content && /* @__PURE__ */ React10.createElement(Box9, { paddingLeft: 2 }, /* @__PURE__ */ React10.createElement(Text9, { backgroundColor: "whiteBright", color: "black" }, " ", message.content, " ")), !isUser && 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) => {
1350
1357
  if (step.type === "thought") {
1351
- 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 ? "..." : ""}`));
1358
+ 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}`));
1352
1359
  }
1353
1360
  if (step.type === "action") {
1354
1361
  const toolName = step.metadata?.toolName || "unknown";
@@ -10835,6 +10842,82 @@ async function loadContextFiles(projectDir) {
10835
10842
  };
10836
10843
  }
10837
10844
 
10845
+ // src/utils/formatStep.ts
10846
+ var MAX_INPUT_LENGTH = 500;
10847
+ var formatStep = (step) => {
10848
+ if (step.type === "action" && step.metadata?.toolInput) {
10849
+ let parsedInput = step.metadata.toolInput;
10850
+ if (typeof parsedInput === "string") {
10851
+ try {
10852
+ parsedInput = JSON.parse(parsedInput);
10853
+ } catch {
10854
+ }
10855
+ }
10856
+ if (step.metadata.toolName === "edit_local_file") {
10857
+ const pathOnly = typeof parsedInput === "object" && parsedInput !== null && "path" in parsedInput ? { path: parsedInput.path } : parsedInput;
10858
+ return {
10859
+ ...step,
10860
+ metadata: {
10861
+ ...step.metadata,
10862
+ toolInput: pathOnly
10863
+ }
10864
+ };
10865
+ }
10866
+ if (step.metadata.toolName === "write_todos") {
10867
+ const todos = typeof parsedInput === "object" && parsedInput !== null && "todos" in parsedInput ? parsedInput.todos : null;
10868
+ const count = Array.isArray(todos) ? todos.length : 0;
10869
+ return {
10870
+ ...step,
10871
+ metadata: {
10872
+ ...step.metadata,
10873
+ toolInput: `${count} todo${count !== 1 ? "s" : ""}`
10874
+ }
10875
+ };
10876
+ }
10877
+ const inputStr = typeof parsedInput === "string" ? parsedInput : JSON.stringify(parsedInput);
10878
+ if (inputStr.length > MAX_INPUT_LENGTH) {
10879
+ const truncatedInput = inputStr.slice(0, MAX_INPUT_LENGTH) + `... (${inputStr.length - MAX_INPUT_LENGTH} more chars)`;
10880
+ return {
10881
+ ...step,
10882
+ metadata: {
10883
+ ...step.metadata,
10884
+ toolInput: truncatedInput
10885
+ }
10886
+ };
10887
+ }
10888
+ }
10889
+ if (step.type === "observation" && step.content) {
10890
+ if (step.metadata?.toolName === "file_read") {
10891
+ const lineCount = step.content.split("\n").length;
10892
+ return {
10893
+ ...step,
10894
+ content: `Read ${lineCount} line${lineCount !== 1 ? "s" : ""}`
10895
+ };
10896
+ }
10897
+ if (step.metadata?.toolName === "grep_search") {
10898
+ const match = step.content.match(/^Found (\d+) file\(s\)/);
10899
+ if (match) {
10900
+ const count = parseInt(match[1], 10);
10901
+ return {
10902
+ ...step,
10903
+ content: `Found ${count} file${count !== 1 ? "s" : ""}`
10904
+ };
10905
+ }
10906
+ }
10907
+ if (step.metadata?.toolName === "glob_files") {
10908
+ const match = step.content.match(/^Found (\d+) file\(s\)/);
10909
+ if (match) {
10910
+ const count = parseInt(match[1], 10);
10911
+ return {
10912
+ ...step,
10913
+ content: `Found ${count} file${count !== 1 ? "s" : ""}`
10914
+ };
10915
+ }
10916
+ }
10917
+ }
10918
+ return step;
10919
+ };
10920
+
10838
10921
  // src/utils/argumentSubstitution.ts
10839
10922
  function substituteArguments(template, args) {
10840
10923
  let result = template;
@@ -11750,7 +11833,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
11750
11833
  // package.json
11751
11834
  var package_default = {
11752
11835
  name: "@bike4mind/cli",
11753
- version: "0.2.12-cli-todo-list.17408+244ee96b6",
11836
+ version: "0.2.12-ctrl-c-clear-input.17412+46c1f7133",
11754
11837
  type: "module",
11755
11838
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
11756
11839
  license: "UNLICENSED",
@@ -11856,10 +11939,10 @@ var package_default = {
11856
11939
  },
11857
11940
  devDependencies: {
11858
11941
  "@bike4mind/agents": "0.1.0",
11859
- "@bike4mind/common": "2.41.1-cli-todo-list.17408+244ee96b6",
11860
- "@bike4mind/mcp": "1.21.1-cli-todo-list.17408+244ee96b6",
11861
- "@bike4mind/services": "2.36.1-cli-todo-list.17408+244ee96b6",
11862
- "@bike4mind/utils": "2.1.6-cli-todo-list.17408+244ee96b6",
11942
+ "@bike4mind/common": "2.41.1-ctrl-c-clear-input.17412+46c1f7133",
11943
+ "@bike4mind/mcp": "1.21.1-ctrl-c-clear-input.17412+46c1f7133",
11944
+ "@bike4mind/services": "2.36.1-ctrl-c-clear-input.17412+46c1f7133",
11945
+ "@bike4mind/utils": "2.1.6-ctrl-c-clear-input.17412+46c1f7133",
11863
11946
  "@types/better-sqlite3": "^7.6.13",
11864
11947
  "@types/diff": "^5.0.9",
11865
11948
  "@types/jsonwebtoken": "^9.0.4",
@@ -11872,7 +11955,7 @@ var package_default = {
11872
11955
  typescript: "^5.9.3",
11873
11956
  vitest: "^3.2.4"
11874
11957
  },
11875
- gitHead: "244ee96b6f743aeff0513fc84f573050b624d4e7"
11958
+ gitHead: "46c1f7133ac46ff30ab650cda7ec3c332e35fb4c"
11876
11959
  };
11877
11960
 
11878
11961
  // src/config/constants.ts
@@ -12443,12 +12526,16 @@ function CliApp() {
12443
12526
  if (key.ctrl && input === "c") {
12444
12527
  const now = Date.now();
12445
12528
  if (exitTimestamp && now - exitTimestamp < EXIT_TIMEOUT_MS) {
12446
- logger.debug("[EXIT Second Ctrl+C - cleaning up and exiting...");
12529
+ logger.debug("[EXIT] Second Ctrl+C - cleaning up and exiting...");
12447
12530
  performCleanup().then(() => {
12448
12531
  exit();
12449
12532
  });
12450
12533
  } else {
12451
- logger.debug("[EXIT First Ctrl+C - press again to exit");
12534
+ logger.debug("[EXIT] First Ctrl+C - press again to exit");
12535
+ const currentInput = useCliStore.getState().inputValue;
12536
+ if (currentInput.length > 0) {
12537
+ useCliStore.getState().clearInput();
12538
+ }
12452
12539
  exitTimestamp = now;
12453
12540
  setExitRequested(true);
12454
12541
  setTimeout(() => {
@@ -12679,26 +12766,12 @@ ${contextResult.mergedContent}` : "";
12679
12766
  const lastIdx = pendingMessages.length - 1;
12680
12767
  if (lastIdx >= 0 && pendingMessages[lastIdx].role === "assistant") {
12681
12768
  const existingSteps = pendingMessages[lastIdx].metadata?.steps || [];
12682
- const MAX_INPUT_LENGTH = 500;
12683
- let truncatedStep = step;
12684
- if (step.type === "action" && step.metadata?.toolInput) {
12685
- const inputStr = typeof step.metadata.toolInput === "string" ? step.metadata.toolInput : JSON.stringify(step.metadata.toolInput);
12686
- if (inputStr.length > MAX_INPUT_LENGTH) {
12687
- const truncatedInput = inputStr.slice(0, MAX_INPUT_LENGTH) + `... (${inputStr.length - MAX_INPUT_LENGTH} more chars)`;
12688
- truncatedStep = {
12689
- ...step,
12690
- metadata: {
12691
- ...step.metadata,
12692
- toolInput: truncatedInput
12693
- }
12694
- };
12695
- }
12696
- }
12769
+ const formattedStep = formatStep(step);
12697
12770
  updatePendingMessage(lastIdx, {
12698
12771
  ...pendingMessages[lastIdx],
12699
12772
  metadata: {
12700
12773
  ...pendingMessages[lastIdx].metadata,
12701
- steps: [...existingSteps, truncatedStep]
12774
+ steps: [...existingSteps, formattedStep]
12702
12775
  }
12703
12776
  });
12704
12777
  }
@@ -12840,7 +12913,7 @@ ${contextResult.mergedContent}` : "";
12840
12913
  content: result.finalAnswer,
12841
12914
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12842
12915
  metadata: {
12843
- steps: result.steps,
12916
+ steps: result.steps.map(formatStep),
12844
12917
  tokenUsage: {
12845
12918
  prompt: 0,
12846
12919
  completion: 0,
@@ -13013,7 +13086,7 @@ ${contextResult.mergedContent}` : "";
13013
13086
  completion: 0,
13014
13087
  total: result.completionInfo.totalTokens
13015
13088
  },
13016
- steps: result.steps,
13089
+ steps: result.steps.map(formatStep),
13017
13090
  // Complete history: thoughts, actions, observations
13018
13091
  permissionDenied
13019
13092
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.12-cli-todo-list.17408+244ee96b6",
3
+ "version": "0.2.12-ctrl-c-clear-input.17412+46c1f7133",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -106,10 +106,10 @@
106
106
  },
107
107
  "devDependencies": {
108
108
  "@bike4mind/agents": "0.1.0",
109
- "@bike4mind/common": "2.41.1-cli-todo-list.17408+244ee96b6",
110
- "@bike4mind/mcp": "1.21.1-cli-todo-list.17408+244ee96b6",
111
- "@bike4mind/services": "2.36.1-cli-todo-list.17408+244ee96b6",
112
- "@bike4mind/utils": "2.1.6-cli-todo-list.17408+244ee96b6",
109
+ "@bike4mind/common": "2.41.1-ctrl-c-clear-input.17412+46c1f7133",
110
+ "@bike4mind/mcp": "1.21.1-ctrl-c-clear-input.17412+46c1f7133",
111
+ "@bike4mind/services": "2.36.1-ctrl-c-clear-input.17412+46c1f7133",
112
+ "@bike4mind/utils": "2.1.6-ctrl-c-clear-input.17412+46c1f7133",
113
113
  "@types/better-sqlite3": "^7.6.13",
114
114
  "@types/diff": "^5.0.9",
115
115
  "@types/jsonwebtoken": "^9.0.4",
@@ -122,5 +122,5 @@
122
122
  "typescript": "^5.9.3",
123
123
  "vitest": "^3.2.4"
124
124
  },
125
- "gitHead": "244ee96b6f743aeff0513fc84f573050b624d4e7"
125
+ "gitHead": "46c1f7133ac46ff30ab650cda7ec3c332e35fb4c"
126
126
  }