fluxflow-cli 2.8.8 → 2.8.9

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/fluxflow.js +132 -2
  2. package/package.json +2 -2
package/dist/fluxflow.js CHANGED
@@ -10649,6 +10649,56 @@ function App({ args = [] }) {
10649
10649
  const lastFocusEventTime = useRef3(0);
10650
10650
  const [apiKey, setApiKey] = useState11(null);
10651
10651
  const [tempKey, setTempKey] = useState11("");
10652
+ const addShiftEnterBinding = async (ideName) => {
10653
+ const kbPath = getKeybindingsPath(ideName);
10654
+ if (!kbPath) return;
10655
+ try {
10656
+ await fs22.ensureDir(path20.dirname(kbPath));
10657
+ let bindings = [];
10658
+ if (fs22.existsSync(kbPath)) {
10659
+ const content = fs22.readFileSync(kbPath, "utf8").trim();
10660
+ if (content) {
10661
+ try {
10662
+ bindings = parseJsonc(content);
10663
+ } catch (e) {
10664
+ bindings = [];
10665
+ }
10666
+ }
10667
+ }
10668
+ if (!Array.isArray(bindings)) {
10669
+ bindings = [];
10670
+ }
10671
+ bindings.push({
10672
+ "key": "shift+enter",
10673
+ "command": "workbench.action.terminal.sendSequence",
10674
+ "args": {
10675
+ "text": "\x1B[13;2u"
10676
+ },
10677
+ "when": "terminalFocus"
10678
+ });
10679
+ fs22.writeFileSync(kbPath, JSON.stringify(bindings, null, 4), "utf8");
10680
+ cachedShortcut = "Shift + Enter";
10681
+ setMessages((prev) => {
10682
+ setCompletedIndex(prev.length + 1);
10683
+ return [...prev, {
10684
+ id: "kb-success-" + Date.now(),
10685
+ role: "system",
10686
+ text: `\u2705 Successfully configured Shift+Enter in your ${ideName} keybindings!`,
10687
+ isMeta: true
10688
+ }];
10689
+ });
10690
+ } catch (err) {
10691
+ setMessages((prev) => {
10692
+ setCompletedIndex(prev.length + 1);
10693
+ return [...prev, {
10694
+ id: "kb-error-" + Date.now(),
10695
+ role: "system",
10696
+ text: `\u274C Failed to update keybindings: ${err.message}`,
10697
+ isMeta: true
10698
+ }];
10699
+ });
10700
+ }
10701
+ };
10652
10702
  const [activeView, setActiveView] = useState11("chat");
10653
10703
  const [apiTier, setApiTier] = useState11("Free");
10654
10704
  const [quotas, setQuotas] = useState11({ agentLimit: 999999, backgroundLimit: 999999, searchLimit: 100, customModelId: "", customLimit: 0 });
@@ -10771,7 +10821,9 @@ function App({ args = [] }) {
10771
10821
  const isIDE = !["Terminal", "Windows Terminal"].includes(ideName) || !!process.env.VSC_TERMINAL_URL || !!process.env.INTELLIJ_TERMINAL_COMMAND_BLOCKS;
10772
10822
  return {
10773
10823
  isIDE,
10774
- shortcut: isIDE ? "Shift + Enter" : "Ctrl + Enter"
10824
+ get shortcut() {
10825
+ return cachedShortcut;
10826
+ }
10775
10827
  };
10776
10828
  }, []);
10777
10829
  const activeCommandRef = useRef3(null);
@@ -11237,6 +11289,28 @@ function App({ args = [] }) {
11237
11289
  setMessages((prev) => [...prev, { id: "sys-err-" + Date.now(), role: "system", text: `ERROR: Chat session [${id}] not found. Started new session.`, isMeta: true }]);
11238
11290
  }
11239
11291
  }
11292
+ const detectedIde = getIDEName();
11293
+ const isIDE = !["Terminal", "Windows Terminal"].includes(detectedIde);
11294
+ if (isIDE) {
11295
+ const kbPath = getKeybindingsPath(detectedIde);
11296
+ if (kbPath) {
11297
+ try {
11298
+ let bindings = [];
11299
+ if (fs22.existsSync(kbPath)) {
11300
+ const content = fs22.readFileSync(kbPath, "utf8").trim();
11301
+ if (content) {
11302
+ bindings = parseJsonc(content);
11303
+ }
11304
+ }
11305
+ if (!hasShiftEnterBinding(bindings)) {
11306
+ setActiveView("keybindingsPrompt");
11307
+ } else {
11308
+ cachedShortcut = "Shift + Enter";
11309
+ }
11310
+ } catch (e) {
11311
+ }
11312
+ }
11313
+ }
11240
11314
  setIsInitializing(false);
11241
11315
  }
11242
11316
  init();
@@ -13222,6 +13296,25 @@ Selection: ${val}`,
13222
13296
  onClose: () => setActiveView("chat")
13223
13297
  }
13224
13298
  ));
13299
+ case "keybindingsPrompt":
13300
+ return /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React14.createElement(Text14, { color: "cyan", bold: true, underline: true }, "\u2328\uFE0F CONFIGURE SHIFT+ENTER NEWLINE"), /* @__PURE__ */ React14.createElement(Text14, { marginTop: 1 }, "To support multi-line inputs with ", /* @__PURE__ */ React14.createElement(Text14, { bold: true, color: "white" }, "Shift + Enter"), " for newline, a terminal sequence keybinding needs to be added to your IDE configuration."), /* @__PURE__ */ React14.createElement(Text14, { marginTop: 1 }, "Would you like FluxFlow to automatically add this to your ", getIDEName(), " keybindings?"), /* @__PURE__ */ React14.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(
13301
+ CommandMenu,
13302
+ {
13303
+ title: "Add Keybinding?",
13304
+ items: [
13305
+ { label: "Yes, configure automatically", value: "yes" },
13306
+ { label: "No, skip", value: "no" }
13307
+ ],
13308
+ onSelect: async (item) => {
13309
+ if (item.value === "yes") {
13310
+ await addShiftEnterBinding(getIDEName());
13311
+ } else {
13312
+ cachedShortcut = "\\ + Enter";
13313
+ }
13314
+ setActiveView("chat");
13315
+ }
13316
+ }
13317
+ )));
13225
13318
  case "memory":
13226
13319
  return /* @__PURE__ */ React14.createElement(Box14, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React14.createElement(MemoryModal, { onClose: () => setActiveView("chat") }));
13227
13320
  case "parserDownload":
@@ -13554,7 +13647,7 @@ Selection: ${val}`,
13554
13647
  return /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "grey", width: Math.min(100, (stdout?.columns || 100) - 2), marginTop: 0, marginBottom: 0 }, /* @__PURE__ */ React14.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text14, { bold: true }, gradient2(["blue", "purple"])("Agent powering down. Goodbye!"))), /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Text14, { color: "white", bold: true, underline: true }, "Interaction Summary"), /* @__PURE__ */ React14.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Box14, { width: 20 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Session ID:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, chatId)), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 20 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Tool Calls:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( ", /* @__PURE__ */ React14.createElement(Text14, { color: "green" }, "\u2713 ", sessionToolSuccess), " ", /* @__PURE__ */ React14.createElement(Text14, { color: "yellow" }, "\u2298 ", sessionToolDenied), " ", /* @__PURE__ */ React14.createElement(Text14, { color: "red" }, "\u2715 ", sessionToolFailure), " )")), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 20 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Success Rate:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, successRate, "%")), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 20 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Code Changes:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, /* @__PURE__ */ React14.createElement(Text14, { color: "green" }, "+", linesAdded), " ", /* @__PURE__ */ React14.createElement(Text14, { color: "red" }, "-", linesRemoved))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 20 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionTotalTokens))), sessionTotalTokens > 0 && /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 18 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Input Tokens:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionTotalTokens - sessionTotalCandidateTokens))), sessionTotalCachedTokens > 0 && /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React14.createElement(Box14, { width: 16 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Cached:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionTotalCachedTokens))), sessionTotalCandidateTokens > 0 && /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 18 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Output Tokens:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionTotalCandidateTokens)))), sessionImageCount > 0 && /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 20 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Images Made:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, sessionImageCount)), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 20 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Image Credits:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits")))), /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "white", bold: true, underline: true }, "Performance"), /* @__PURE__ */ React14.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Box14, { width: 20 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Wall Time:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatMsDuration(wallTimeMs))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 20 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Agent Active:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatMsDuration(agentActiveMs))), /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 18 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB API Time:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatMsDuration(sessionApiTime), " (", apiPercent, "%)")), /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 18 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Tool Time:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatMsDuration(sessionToolTime), " (", toolPercent, "%)"))));
13555
13648
  })())));
13556
13649
  }
13557
- var getIDEName, getPromoOptions, BridgePromo, SESSION_START_TIME, CHANGELOG_URL, DOCS_URL, linesAdded, linesRemoved, packageJsonPath, packageJson, versionFluxflow, updatedOn, ResolutionModal, parseAgentText, getProjectFiles;
13650
+ var getIDEName, getIDEDirName, getKeybindingsPath, parseJsonc, hasShiftEnterBinding, getPromoOptions, BridgePromo, SESSION_START_TIME, CHANGELOG_URL, DOCS_URL, linesAdded, linesRemoved, packageJsonPath, packageJson, versionFluxflow, updatedOn, ResolutionModal, parseAgentText, getProjectFiles, cachedShortcut;
13558
13651
  var init_app = __esm({
13559
13652
  async "src/app.jsx"() {
13560
13653
  init_MultilineInput();
@@ -13602,10 +13695,46 @@ var init_app = __esm({
13602
13695
  if (termProgram === "trae" || inEnvVars("trae")) return "Trae";
13603
13696
  if (termProgram === "codium" || inEnvVars("codium") || inEnvVars("vscode-oss")) return "VSCodium";
13604
13697
  if (inEnvVars("positron")) return "Positron";
13698
+ if (termProgram === "vscode-insiders" || inEnvVars("insiders")) return "VS Code Insiders";
13605
13699
  if (termProgram === "vscode" || process.env.VSCODE_GIT_IPC_HANDLE || inEnvVars("vscode")) return "VS Code";
13606
13700
  if (process.env.INTELLIJ_TERMINAL_COMMAND_BLOCKS || inEnvVars("intellij")) return "JetBrains";
13607
13701
  return "Terminal";
13608
13702
  };
13703
+ getIDEDirName = (ideName) => {
13704
+ switch (ideName) {
13705
+ case "VS Code":
13706
+ return "Code";
13707
+ case "VS Code Insiders":
13708
+ return "Code - Insiders";
13709
+ case "Antigravity":
13710
+ return "Antigravity IDE";
13711
+ default:
13712
+ return ideName;
13713
+ }
13714
+ };
13715
+ getKeybindingsPath = (ideName) => {
13716
+ const dirName = getIDEDirName(ideName);
13717
+ const home = os4.homedir();
13718
+ if (process.platform === "win32") {
13719
+ const appData = process.env.APPDATA;
13720
+ if (!appData) return null;
13721
+ return path20.join(appData, dirName, "User", "keybindings.json");
13722
+ } else if (process.platform === "darwin") {
13723
+ return path20.join(home, "Library", "Application Support", dirName, "User", "keybindings.json");
13724
+ } else {
13725
+ return path20.join(home, ".config", dirName, "User", "keybindings.json");
13726
+ }
13727
+ };
13728
+ parseJsonc = (content) => {
13729
+ const clean = content.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, "$1");
13730
+ return JSON.parse(clean);
13731
+ };
13732
+ hasShiftEnterBinding = (bindings) => {
13733
+ if (!Array.isArray(bindings)) return false;
13734
+ return bindings.some(
13735
+ (b) => b && typeof b.key === "string" && b.key.toLowerCase().replace(/\s+/g, "") === "shift+enter" && b.command === "workbench.action.terminal.sendSequence" && b.args && b.args.text === "\x1B[13;2u" && typeof b.when === "string" && b.when.includes("terminalFocus")
13736
+ );
13737
+ };
13609
13738
  getPromoOptions = (ideName) => {
13610
13739
  const isStandardVSCode = ideName === "VS Code";
13611
13740
  const options = [];
@@ -13761,6 +13890,7 @@ var init_app = __esm({
13761
13890
  return fileList;
13762
13891
  };
13763
13892
  })();
13893
+ cachedShortcut = "\\ + Enter";
13764
13894
  }
13765
13895
  });
13766
13896
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "2.8.8",
4
- "date": "2026-06-18",
3
+ "version": "2.8.9",
4
+ "date": "2026-06-19",
5
5
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",