@bike4mind/cli 0.2.10-fix-b4m-cli-flicker.17235 → 0.2.10-fix-b4m-cli-flicker.17243

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 +109 -32
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -79,12 +79,13 @@ import {
79
79
  } from "./chunk-PDX44BCA.js";
80
80
 
81
81
  // src/index.tsx
82
- import React17, { useState as useState7, useEffect as useEffect3, useCallback, useRef } from "react";
82
+ import React17, { useState as useState8, useEffect as useEffect3, useCallback, useRef as useRef2 } from "react";
83
83
  import { render, Box as Box16, Text as Text16, useApp, useInput as useInput6 } from "ink";
84
+ import { execSync } from "child_process";
84
85
  import { v4 as uuidv49 } from "uuid";
85
86
 
86
87
  // src/components/App.tsx
87
- import React11 from "react";
88
+ import React11, { useState as useState4 } from "react";
88
89
  import { Box as Box10, Text as Text10, Static } from "ink";
89
90
 
90
91
  // src/components/StatusBar.tsx
@@ -95,7 +96,7 @@ var StatusBar = React.memo(function StatusBar2({ sessionName, model, tokenUsage
95
96
  });
96
97
 
97
98
  // src/components/InputPrompt.tsx
98
- import React5, { useState as useState2, useMemo, useEffect } from "react";
99
+ import React5, { useState as useState2, useMemo, useEffect, useRef } from "react";
99
100
  import { Box as Box4, Text as Text5, useInput as useInput2 } from "ink";
100
101
 
101
102
  // src/components/CustomTextInput.tsx
@@ -732,17 +733,19 @@ function findAtTrigger(value) {
732
733
  }
733
734
  function InputPrompt({
734
735
  onSubmit,
736
+ onBashCommand,
735
737
  onImageDetected,
736
738
  disabled = false,
737
739
  history = [],
738
740
  prefillInput,
739
- onPrefillConsumed
741
+ onPrefillConsumed,
742
+ onBashModeChange
740
743
  }) {
741
744
  const [value, setValue] = useState2("");
742
745
  const [selectedIndex, setSelectedIndex] = useState2(0);
743
746
  const [historyIndex, setHistoryIndex] = useState2(-1);
744
747
  const [tempInput, setTempInput] = useState2("");
745
- const [inputKey, setInputKey] = useState2(0);
748
+ const inputKey = useRef(0);
746
749
  useEffect(() => {
747
750
  if (prefillInput) {
748
751
  setValue(prefillInput);
@@ -751,6 +754,10 @@ function InputPrompt({
751
754
  }, [prefillInput, onPrefillConsumed]);
752
755
  const [fileAutocomplete, setFileAutocomplete] = useState2(null);
753
756
  const [fileSelectedIndex, setFileSelectedIndex] = useState2(0);
757
+ const isBashMode = value.startsWith("!");
758
+ useEffect(() => {
759
+ onBashModeChange?.(isBashMode);
760
+ }, [isBashMode, onBashModeChange]);
754
761
  const shouldShowCommandAutocomplete = value.startsWith("/") && !disabled && !fileAutocomplete?.active;
755
762
  const commandQuery = shouldShowCommandAutocomplete ? value.slice(1) : "";
756
763
  const filteredCommands = useMemo(() => {
@@ -857,6 +864,16 @@ function InputPrompt({
857
864
  onSubmit(commandText);
858
865
  return;
859
866
  }
867
+ if (isBashMode && onBashCommand) {
868
+ const command = input.slice(1).trim();
869
+ if (command) {
870
+ onBashCommand(command);
871
+ setValue("");
872
+ setHistoryIndex(-1);
873
+ setFileAutocomplete(null);
874
+ }
875
+ return;
876
+ }
860
877
  onSubmit(input);
861
878
  setValue("");
862
879
  setHistoryIndex(-1);
@@ -887,14 +904,19 @@ function InputPrompt({
887
904
  setFileAutocomplete(null);
888
905
  }
889
906
  };
890
- return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { bold: true, color: "cyan" }, "> "), /* @__PURE__ */ React5.createElement(
907
+ const getPlaceholder = () => {
908
+ if (disabled) return "Thinking...";
909
+ if (isBashMode) return "Enter shell command to execute...";
910
+ return "Type your message, /help for commands, @file to reference, or ! for bash";
911
+ };
912
+ return /* @__PURE__ */ React5.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { bold: true, color: isBashMode ? "yellow" : "cyan" }, isBashMode ? "$ " : "> "), /* @__PURE__ */ React5.createElement(
891
913
  CustomTextInput,
892
914
  {
893
- key: inputKey,
915
+ key: inputKey.current,
894
916
  value,
895
917
  onChange: handleChange,
896
918
  onSubmit: handleSubmit,
897
- placeholder: disabled ? "" : "Type your message, /help for commands, or @file to reference",
919
+ placeholder: getPlaceholder(),
898
920
  showCursor: !disabled
899
921
  }
900
922
  )), shouldShowCommandAutocomplete && /* @__PURE__ */ React5.createElement(CommandAutocomplete, { commands: filteredCommands, selectedIndex }), fileAutocomplete?.active && /* @__PURE__ */ React5.createElement(FileAutocomplete, { files: filteredFiles, selectedIndex: fileSelectedIndex, query: fileAutocomplete.query }));
@@ -918,6 +940,16 @@ var useCliStore = create((set) => ({
918
940
  // Session state
919
941
  session: null,
920
942
  setSession: (session) => set({ session }),
943
+ addMessage: (message) => set((state) => {
944
+ if (!state.session) return state;
945
+ return {
946
+ session: {
947
+ ...state.session,
948
+ messages: [...state.session.messages, message],
949
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
950
+ }
951
+ };
952
+ }),
921
953
  // Pending messages
922
954
  pendingMessages: [],
923
955
  addPendingMessage: (message) => set((state) => ({ pendingMessages: [...state.pendingMessages, message] })),
@@ -1378,6 +1410,7 @@ function hasFileReferences(message) {
1378
1410
  function App({
1379
1411
  onMessage,
1380
1412
  onCommand,
1413
+ onBashCommand,
1381
1414
  onPermissionResponse,
1382
1415
  onImageDetected,
1383
1416
  commandHistory = [],
@@ -1398,6 +1431,7 @@ function App({
1398
1431
  const setShowConfigEditor = useCliStore((state) => state.setShowConfigEditor);
1399
1432
  const exitRequested = useCliStore((state) => state.exitRequested);
1400
1433
  const setIsThinking = useCliStore((state) => state.setIsThinking);
1434
+ const [isBashMode, setIsBashMode] = useState4(false);
1401
1435
  const handleSubmit = React11.useCallback(
1402
1436
  async (input) => {
1403
1437
  const trimmed = input.trim();
@@ -1444,15 +1478,17 @@ ${errorBlock}`;
1444
1478
  canBeTrusted: permissionPrompt.canBeTrusted,
1445
1479
  onResponse: onPermissionResponse
1446
1480
  }
1447
- )) : /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(Static, { items: messages }, (message, index) => /* @__PURE__ */ React11.createElement(Box10, { key: `${message.timestamp}-${message.role}-${index}`, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React11.createElement(MessageItem, { message }))), /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column" }, pendingMessages.map((message, index) => /* @__PURE__ */ React11.createElement(Box10, { key: `pending-${message.timestamp}-${index}`, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React11.createElement(MessageItem, { message })))), /* @__PURE__ */ React11.createElement(AgentThinking, null), exitRequested && /* @__PURE__ */ React11.createElement(Box10, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text10, { color: "yellow", bold: true }, "Press Ctrl+C again to exit")), /* @__PURE__ */ React11.createElement(Box10, { borderStyle: "single", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React11.createElement(
1481
+ )) : /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(Static, { items: messages }, (message, index) => /* @__PURE__ */ React11.createElement(Box10, { key: `${message.timestamp}-${message.role}-${index}`, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React11.createElement(MessageItem, { message }))), /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column" }, pendingMessages.map((message, index) => /* @__PURE__ */ React11.createElement(Box10, { key: `pending-${message.timestamp}-${index}`, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React11.createElement(MessageItem, { message })))), /* @__PURE__ */ React11.createElement(AgentThinking, null), exitRequested && /* @__PURE__ */ React11.createElement(Box10, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text10, { color: "yellow", bold: true }, "Press Ctrl+C again to exit")), /* @__PURE__ */ React11.createElement(Box10, { borderStyle: "single", borderColor: isBashMode ? "yellow" : "cyan", paddingX: 1 }, /* @__PURE__ */ React11.createElement(
1448
1482
  InputPrompt,
1449
1483
  {
1450
1484
  onSubmit: handleSubmit,
1485
+ onBashCommand,
1451
1486
  onImageDetected,
1452
1487
  disabled: isThinking,
1453
1488
  history: commandHistory,
1454
1489
  prefillInput,
1455
- onPrefillConsumed
1490
+ onPrefillConsumed,
1491
+ onBashModeChange: setIsBashMode
1456
1492
  }
1457
1493
  )), /* @__PURE__ */ React11.createElement(StatusBar, { sessionName, model: currentModel, tokenUsage: totalTokens })));
1458
1494
  }
@@ -1530,12 +1566,12 @@ function TrustLocationSelector({ inProject, onSelect, onCancel }) {
1530
1566
  }
1531
1567
 
1532
1568
  // src/components/RewindSelector.tsx
1533
- import React14, { useState as useState4 } from "react";
1569
+ import React14, { useState as useState5 } from "react";
1534
1570
  import { Box as Box13, Text as Text13, useInput as useInput4 } from "ink";
1535
1571
  import SelectInput3 from "ink-select-input";
1536
1572
  function RewindSelector({ messages, onSelect, onCancel }) {
1537
- const [step, setStep] = useState4("selection");
1538
- const [selectedMessageIndex, setSelectedMessageIndex] = useState4(null);
1573
+ const [step, setStep] = useState5("selection");
1574
+ const [selectedMessageIndex, setSelectedMessageIndex] = useState5(null);
1539
1575
  useInput4((input, key) => {
1540
1576
  if (key.escape) {
1541
1577
  if (step === "confirmation") {
@@ -1599,12 +1635,12 @@ function RewindSelector({ messages, onSelect, onCancel }) {
1599
1635
  }
1600
1636
 
1601
1637
  // src/components/SessionSelector.tsx
1602
- import React15, { useState as useState5 } from "react";
1638
+ import React15, { useState as useState6 } from "react";
1603
1639
  import { Box as Box14, Text as Text14, useInput as useInput5 } from "ink";
1604
1640
  import SelectInput4 from "ink-select-input";
1605
1641
  function SessionSelector({ sessions, currentSession, onSelect, onCancel }) {
1606
- const [step, setStep] = useState5("selection");
1607
- const [selectedSession, setSelectedSession] = useState5(null);
1642
+ const [step, setStep] = useState6("selection");
1643
+ const [selectedSession, setSelectedSession] = useState6(null);
1608
1644
  useInput5((input, key) => {
1609
1645
  if (key.escape) {
1610
1646
  if (step === "confirmation") {
@@ -1662,7 +1698,7 @@ function SessionSelector({ sessions, currentSession, onSelect, onCancel }) {
1662
1698
  }
1663
1699
 
1664
1700
  // src/components/LoginFlow.tsx
1665
- import React16, { useState as useState6, useEffect as useEffect2 } from "react";
1701
+ import React16, { useState as useState7, useEffect as useEffect2 } from "react";
1666
1702
  import { Box as Box15, Text as Text15 } from "ink";
1667
1703
  import Spinner2 from "ink-spinner";
1668
1704
  import jwt from "jsonwebtoken";
@@ -1779,10 +1815,10 @@ var OAuthClient = class {
1779
1815
 
1780
1816
  // src/components/LoginFlow.tsx
1781
1817
  function LoginFlow({ apiUrl = "http://localhost:3000", configStore, onSuccess, onError }) {
1782
- const [status, setStatus] = useState6("initiating");
1783
- const [deviceFlow, setDeviceFlow] = useState6(null);
1784
- const [statusMessage, setStatusMessage] = useState6("Initiating device authorization...");
1785
- const [error, setError] = useState6(null);
1818
+ const [status, setStatus] = useState7("initiating");
1819
+ const [deviceFlow, setDeviceFlow] = useState7(null);
1820
+ const [statusMessage, setStatusMessage] = useState7("Initiating device authorization...");
1821
+ const [error, setError] = useState7(null);
1786
1822
  useEffect2(() => {
1787
1823
  const runLoginFlow = async () => {
1788
1824
  const oauth = new OAuthClient(apiUrl);
@@ -11114,7 +11150,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
11114
11150
  // package.json
11115
11151
  var package_default = {
11116
11152
  name: "@bike4mind/cli",
11117
- version: "0.2.10-fix-b4m-cli-flicker.17235+479bb7772",
11153
+ version: "0.2.10-fix-b4m-cli-flicker.17243+cbbca593a",
11118
11154
  type: "module",
11119
11155
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
11120
11156
  license: "UNLICENSED",
@@ -11217,10 +11253,10 @@ var package_default = {
11217
11253
  },
11218
11254
  devDependencies: {
11219
11255
  "@bike4mind/agents": "0.1.0",
11220
- "@bike4mind/common": "2.39.1-fix-b4m-cli-flicker.17235+479bb7772",
11221
- "@bike4mind/mcp": "1.20.4-fix-b4m-cli-flicker.17235+479bb7772",
11222
- "@bike4mind/services": "2.34.2-fix-b4m-cli-flicker.17235+479bb7772",
11223
- "@bike4mind/utils": "2.1.4-fix-b4m-cli-flicker.17235+479bb7772",
11256
+ "@bike4mind/common": "2.39.1-fix-b4m-cli-flicker.17243+cbbca593a",
11257
+ "@bike4mind/mcp": "1.20.4-fix-b4m-cli-flicker.17243+cbbca593a",
11258
+ "@bike4mind/services": "2.34.2-fix-b4m-cli-flicker.17243+cbbca593a",
11259
+ "@bike4mind/utils": "2.1.4-fix-b4m-cli-flicker.17243+cbbca593a",
11224
11260
  "@types/better-sqlite3": "^7.6.13",
11225
11261
  "@types/diff": "^5.0.9",
11226
11262
  "@types/jsonwebtoken": "^9.0.4",
@@ -11233,7 +11269,7 @@ var package_default = {
11233
11269
  typescript: "^5.9.3",
11234
11270
  vitest: "^3.2.4"
11235
11271
  },
11236
- gitHead: "479bb77726d7e49cda72367ba8fd3c84e346474d"
11272
+ gitHead: "cbbca593a8f5107d0ff9ca4a7911de7616a61a91"
11237
11273
  };
11238
11274
 
11239
11275
  // src/config/constants.ts
@@ -11255,7 +11291,7 @@ var usageCache = null;
11255
11291
  function CliApp() {
11256
11292
  const { exit } = useApp();
11257
11293
  const imageRenderer = new ImageRenderer();
11258
- const [state, setState] = useState7({
11294
+ const [state, setState] = useState8({
11259
11295
  session: null,
11260
11296
  sessionStore: new SessionStore(),
11261
11297
  configStore: new ConfigStore(),
@@ -11272,10 +11308,10 @@ function CliApp() {
11272
11308
  rewindSelector: null,
11273
11309
  sessionSelector: null
11274
11310
  });
11275
- const [isInitialized, setIsInitialized] = useState7(false);
11276
- const [initError, setInitError] = useState7(null);
11277
- const [commandHistory, setCommandHistory] = useState7([]);
11278
- const imageStoreInitPromise = useRef(null);
11311
+ const [isInitialized, setIsInitialized] = useState8(false);
11312
+ const [initError, setInitError] = useState8(null);
11313
+ const [commandHistory, setCommandHistory] = useState8([]);
11314
+ const imageStoreInitPromise = useRef2(null);
11279
11315
  const setStoreSession = useCliStore((state2) => state2.setSession);
11280
11316
  const setPermissionPrompt = useCliStore((state2) => state2.setPermissionPrompt);
11281
11317
  const setShowConfigEditor = useCliStore((state2) => state2.setShowConfigEditor);
@@ -11683,6 +11719,46 @@ Remember: Use context from previous messages to understand follow-up questions.$
11683
11719
  state.agent.off("action", stepHandler);
11684
11720
  }
11685
11721
  };
11722
+ const handleBashCommand = useCallback(
11723
+ (command) => {
11724
+ if (!state.session) return;
11725
+ let output;
11726
+ let isError = false;
11727
+ try {
11728
+ output = execSync(command, {
11729
+ encoding: "utf-8",
11730
+ stdio: ["pipe", "pipe", "pipe"],
11731
+ cwd: process.cwd(),
11732
+ maxBuffer: 10 * 1024 * 1024
11733
+ // 10MB buffer
11734
+ });
11735
+ } catch (error) {
11736
+ const execError = error;
11737
+ output = execError.stderr || execError.message || "Command failed";
11738
+ isError = true;
11739
+ }
11740
+ const userMessage = {
11741
+ role: "user",
11742
+ content: `$ ${command}`,
11743
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
11744
+ };
11745
+ const assistantMessage = {
11746
+ role: "assistant",
11747
+ content: isError ? `\u274C Error:
11748
+ ${output}` : output.trim() || "(no output)",
11749
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
11750
+ };
11751
+ const updatedSession = {
11752
+ ...state.session,
11753
+ messages: [...state.session.messages, userMessage, assistantMessage],
11754
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
11755
+ };
11756
+ setState((prev) => ({ ...prev, session: updatedSession }));
11757
+ setStoreSession(updatedSession);
11758
+ state.sessionStore.save(updatedSession);
11759
+ },
11760
+ [state.session, state.sessionStore]
11761
+ );
11686
11762
  const handleImageDetected = async (imageData) => {
11687
11763
  try {
11688
11764
  let imageStore = state.imageStore;
@@ -12355,6 +12431,7 @@ No usage data available for the last ${USAGE_DAYS} days.`);
12355
12431
  {
12356
12432
  onMessage: handleMessage,
12357
12433
  onCommand: handleCommand,
12434
+ onBashCommand: handleBashCommand,
12358
12435
  onImageDetected: handleImageDetected,
12359
12436
  commandHistory,
12360
12437
  config: state.config,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.10-fix-b4m-cli-flicker.17235+479bb7772",
3
+ "version": "0.2.10-fix-b4m-cli-flicker.17243+cbbca593a",
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.39.1-fix-b4m-cli-flicker.17235+479bb7772",
107
- "@bike4mind/mcp": "1.20.4-fix-b4m-cli-flicker.17235+479bb7772",
108
- "@bike4mind/services": "2.34.2-fix-b4m-cli-flicker.17235+479bb7772",
109
- "@bike4mind/utils": "2.1.4-fix-b4m-cli-flicker.17235+479bb7772",
106
+ "@bike4mind/common": "2.39.1-fix-b4m-cli-flicker.17243+cbbca593a",
107
+ "@bike4mind/mcp": "1.20.4-fix-b4m-cli-flicker.17243+cbbca593a",
108
+ "@bike4mind/services": "2.34.2-fix-b4m-cli-flicker.17243+cbbca593a",
109
+ "@bike4mind/utils": "2.1.4-fix-b4m-cli-flicker.17243+cbbca593a",
110
110
  "@types/better-sqlite3": "^7.6.13",
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": "479bb77726d7e49cda72367ba8fd3c84e346474d"
122
+ "gitHead": "cbbca593a8f5107d0ff9ca4a7911de7616a61a91"
123
123
  }