fluxflow-cli 1.8.34 → 1.9.0

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 +265 -134
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -111,6 +111,28 @@ var init_TerminalBox = __esm({
111
111
  }
112
112
  });
113
113
 
114
+ // src/utils/terminal.js
115
+ var getTerminalEnv, emojiSpace;
116
+ var init_terminal = __esm({
117
+ "src/utils/terminal.js"() {
118
+ getTerminalEnv = () => {
119
+ if (process.env.TERM_PROGRAM === "vscode") return "vscode";
120
+ if (process.env.WT_SESSION) return "wt";
121
+ return "default";
122
+ };
123
+ emojiSpace = (baseSpaces = 2) => {
124
+ const env = getTerminalEnv();
125
+ if (env === "wt") {
126
+ return " ".repeat(Math.max(1, baseSpaces - 1));
127
+ }
128
+ if (env === "vscode") {
129
+ return " ".repeat(baseSpaces);
130
+ }
131
+ return " ".repeat(baseSpaces);
132
+ };
133
+ }
134
+ });
135
+
114
136
  // src/components/ChatLayout.jsx
115
137
  import React2, { useState, useEffect, useRef } from "react";
116
138
  import { Box as Box2, Text as Text2 } from "ink";
@@ -119,6 +141,7 @@ var init_ChatLayout = __esm({
119
141
  "src/components/ChatLayout.jsx"() {
120
142
  init_TerminalBox();
121
143
  init_text();
144
+ init_terminal();
122
145
  cleanSignals = (text) => {
123
146
  if (!text) return text;
124
147
  let result = text;
@@ -173,7 +196,7 @@ var init_ChatLayout = __esm({
173
196
  }
174
197
  }
175
198
  }
176
- return result.replace(/^\[TOOL_RESULT\]:\s*/gi, "").split("\n").filter((line) => !line.trim().startsWith("SUCCESS:") && !line.trim().startsWith("ERROR:")).join("\n").replace(/\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").replace(/\[\s*(turn\s*:)?\s*(continue|finish)?\s*$/gi, "").replace(/\n\s*turn\s*:\s*(continue|finish)\s*$/gi, "").replace(/\n\nResponded on .*/g, "").replace(/\n\n\[Prompted on: .*\]/g, "").replace(/(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)/gi, "\u2192").replace(/(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)/gi, "\u2190").replace(/(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)/gi, "\u2191").replace(/(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)/gi, "\u2193").replace(/(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi, "\u2194").replace(/\[\/n\]?/g, "\\\\n").trim();
199
+ return result.replace(/^\[TOOL_RESULT\]:\s*/gi, "").split("\n").filter((line) => !line.trim().startsWith("SUCCESS:") && !line.trim().startsWith("ERROR:")).join("\n").replace(/\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").replace(/\[\s*(turn\s*:)?\s*(continue|finish)?\s*$/gi, "").replace(/\n\s*turn\s*:\s*(continue|finish)\s*$/gi, "").replace(/\n\nResponded on .*/g, "").replace(/\n\n\[Prompted on: .*\]/g, "").replace(/(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)/gi, "\u2192").replace(/(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)/gi, "\u2190").replace(/(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)/gi, "\u2191").replace(/(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)/gi, "\u2193").replace(/(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi, "\u2194").replace(/\[\/n\]?/g, "\\n").trim();
177
200
  };
178
201
  formatThinkText = (cleaned, columns = 80) => {
179
202
  if (!cleaned) return null;
@@ -358,6 +381,12 @@ var init_ChatLayout = __esm({
358
381
  const isDiffResult = msg.role === "system" && msg.text?.includes("[DIFF_START]");
359
382
  const isPatchError = msg.role === "system" && msg.text?.includes("[TOOL_RESULT]: ERROR:") && (msg.toolName === "update_file" || msg.text?.includes("Could not find exact match"));
360
383
  const isTerminalRecord = msg.isTerminalRecord;
384
+ if (msg.id && String(msg.id).startsWith("welcome")) {
385
+ const parts = msg.text.split("\n\n");
386
+ const logo = parts[0];
387
+ const greeting = parts[1] || "";
388
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", alignItems: "center", width: "100%", marginY: 1 }, /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1 }, /* @__PURE__ */ React2.createElement(Text2, null, logo)), /* @__PURE__ */ React2.createElement(Box2, { borderStyle: "round", borderColor: "gray", paddingX: 3, paddingY: 0 }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", bold: true }, greeting.trim())));
389
+ }
361
390
  if (msg.isVisualFeedback) {
362
391
  return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color: "white" }, msg.text));
363
392
  }
@@ -368,10 +397,14 @@ var init_ChatLayout = __esm({
368
397
  if (msg.isAskRecord) {
369
398
  const selectionMatch = msg.text.match(/Selection: (.*)/);
370
399
  const selection = selectionMatch ? selectionMatch[1] : "No selection";
371
- return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", bold: true, underline: true }, "\u{1F4AC} ASK USER"), /* @__PURE__ */ React2.createElement(Box2, { marginTop: 0 }, /* @__PURE__ */ React2.createElement(Text2, { color: "white" }, "Selection: ", /* @__PURE__ */ React2.createElement(Text2, { color: "yellow", bold: true }, selection)))));
400
+ const s = emojiSpace(2);
401
+ return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", bold: true }, "\u{1F4AC}", s, "AGENT REQUEST: RESOLVED")), /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1, marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "white" }, "Selection: ", /* @__PURE__ */ React2.createElement(Text2, { color: "yellow", bold: true }, selection)))));
402
+ }
403
+ if (msg.isAboutRecord) {
404
+ return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", bold: true }, "\u{1F4A0} ABOUT FLUX FLOW")), /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1, marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React2.createElement(Text2, null, msg.text))));
372
405
  }
373
406
  if (msg.isUpdateNotification) {
374
- return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color: "yellow", bold: true, underline: true }, "\u{1F680} UPDATE AVAILABLE"), /* @__PURE__ */ React2.createElement(Box2, { marginTop: 1 }, /* @__PURE__ */ React2.createElement(CodeRenderer, { text: msg.text, columns }))));
407
+ return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", bold: true }, "\u{1F680} FLUX FLOW UPDATE AVAILABLE")), /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1, marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React2.createElement(CodeRenderer, { text: msg.text, columns }))));
375
408
  }
376
409
  if (msg.isHelpRecord) {
377
410
  const commandList = [
@@ -488,20 +521,19 @@ var init_StatusBar = __esm({
488
521
  StatusBar = React3.memo(({ mode, thinkingLevel, tokens = "0.0k", tokensTotal = "0.0k", chatId = "NEW-SESSION", isMemoryEnabled = true }) => {
489
522
  const modeColor = mode === "Flux" ? "yellow" : "cyan";
490
523
  const modeIcon = mode === "Flux" ? "\u26A1" : "\u{1F30A}";
491
- const memStatus = isMemoryEnabled ? "ON" : "OFF";
492
524
  return /* @__PURE__ */ React3.createElement(
493
525
  Box3,
494
526
  {
495
- borderStyle: "single",
527
+ borderStyle: "round",
496
528
  borderColor: "gray",
497
529
  flexDirection: "row",
498
530
  justifyContent: "space-between",
499
531
  paddingX: 1,
500
532
  width: "100%"
501
533
  },
502
- /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: modeColor, bold: true }, modeIcon, " ", mode.toUpperCase()), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "magenta" }, "\u{1F9E0} ", thinkingLevel)),
503
- /* @__PURE__ */ React3.createElement(Box3, { flexGrow: 1, justifyContent: "center", paddingX: 2 }, /* @__PURE__ */ React3.createElement(Text3, { color: "gray", dimColor: true }, "\u{1F4C1} "), /* @__PURE__ */ React3.createElement(Text3, { color: "blue", dimColor: true, italic: true }, truncatePath(process.cwd(), 40))),
504
- /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, "MEM: "), /* @__PURE__ */ React3.createElement(Text3, { color: memStatus === "ON" ? "green" : "red" }, memStatus), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "blue" }, formatTokens(tokensTotal), " (", Math.round(tokens / 254e3 * 100), "%)"), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "dim" }, chatId, " "))
534
+ /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Box3, { marginRight: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: modeColor, bold: true }, modeIcon, " ", mode.toUpperCase())), /* @__PURE__ */ React3.createElement(Text3, { color: "gray", dimColor: true }, "\u2503 "), /* @__PURE__ */ React3.createElement(Box3, { marginX: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: "magenta" }, "\u{1F9E0} ", thinkingLevel)), /* @__PURE__ */ React3.createElement(Text3, { color: "gray", dimColor: true }, "\u2503 "), /* @__PURE__ */ React3.createElement(Box3, { marginX: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, "MEM: "), /* @__PURE__ */ React3.createElement(Text3, { color: isMemoryEnabled ? "green" : "red", bold: true }, isMemoryEnabled ? "ON" : "OFF"))),
535
+ /* @__PURE__ */ React3.createElement(Box3, { flexGrow: 1, justifyContent: "center", paddingX: 2 }, /* @__PURE__ */ React3.createElement(Text3, null, "\u{1F4C1}"), /* @__PURE__ */ React3.createElement(Text3, { color: "gray", italic: true }, " ", truncatePath(process.cwd(), 35))),
536
+ /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: "gray", dimColor: true }, "\u2503 "), /* @__PURE__ */ React3.createElement(Box3, { marginX: 1 }, /* @__PURE__ */ React3.createElement(Text3, null, "\u2728"), /* @__PURE__ */ React3.createElement(Text3, { color: "blue" }, " ", formatTokens(tokensTotal), " ", /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "(", Math.round(tokens / 254e3 * 100), "%)"))), /* @__PURE__ */ React3.createElement(Text3, { color: "gray", dimColor: true }, "\u2503 "), /* @__PURE__ */ React3.createElement(Box3, { marginLeft: 1 }, /* @__PURE__ */ React3.createElement(Text3, null, "\u{1F194}"), /* @__PURE__ */ React3.createElement(Text3, { color: "gray", dimColor: true, italic: true }, " ", chatId)))
505
537
  );
506
538
  });
507
539
  StatusBar_default = StatusBar;
@@ -513,22 +545,46 @@ import React4 from "react";
513
545
  import { Box as Box4, Text as Text4 } from "ink";
514
546
  import SelectInput from "ink-select-input";
515
547
  function CommandMenu({ title, subtitle, items, onSelect }) {
516
- return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", padding: 1, marginTop: 1, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "magenta", bold: true }, title), subtitle && /* @__PURE__ */ React4.createElement(Text4, { color: "yellow", dimColor: true, marginTop: 1, italic: true }, subtitle), /* @__PURE__ */ React4.createElement(Box4, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React4.createElement(
517
- SelectInput,
548
+ return /* @__PURE__ */ React4.createElement(
549
+ Box4,
518
550
  {
519
- items,
520
- onSelect,
521
- itemComponent: CustomItem,
522
- indicatorComponent: () => null
523
- }
524
- )), /* @__PURE__ */ React4.createElement(Text4, { color: "gray", dimColor: true, marginTop: 1 }, "(Use Up/Down arrows to select, Enter to confirm)"));
551
+ flexDirection: "column",
552
+ borderStyle: "round",
553
+ borderColor: "gray",
554
+ padding: 0,
555
+ marginTop: 1,
556
+ flexShrink: 0,
557
+ width: "100%"
558
+ },
559
+ /* @__PURE__ */ React4.createElement(Box4, { paddingX: 1, paddingY: 0, marginBottom: subtitle ? 0 : 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "magenta", bold: true }, "\u{1F527} ", title.toUpperCase())),
560
+ subtitle && /* @__PURE__ */ React4.createElement(Box4, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "yellow", dimColor: true, italic: true }, " ", subtitle)),
561
+ /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React4.createElement(
562
+ SelectInput,
563
+ {
564
+ items,
565
+ onSelect,
566
+ itemComponent: CustomItem,
567
+ indicatorComponent: () => null
568
+ }
569
+ )),
570
+ /* @__PURE__ */ React4.createElement(Box4, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray", dimColor: true, italic: true }, "(Arrows to select \u2022 Enter to confirm)"))
571
+ );
525
572
  }
526
573
  var CustomItem;
527
574
  var init_CommandMenu = __esm({
528
575
  "src/components/CommandMenu.jsx"() {
529
576
  CustomItem = ({ label, isSelected }) => {
530
577
  const isCancel = label === "Cancel" || label === "Back" || label.toLowerCase().includes("exit") || label.toLowerCase().includes("back");
531
- return /* @__PURE__ */ React4.createElement(Box4, { marginTop: isCancel ? 1 : 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: isSelected ? "cyan" : "white" }, isSelected ? "\u276F " : " ", label));
578
+ return /* @__PURE__ */ React4.createElement(
579
+ Box4,
580
+ {
581
+ marginTop: isCancel ? 1 : 0,
582
+ backgroundColor: isSelected ? "#2a2a2a" : void 0,
583
+ paddingX: 1,
584
+ width: "100%"
585
+ },
586
+ /* @__PURE__ */ React4.createElement(Text4, { color: isSelected ? "cyan" : "white", bold: isSelected }, isSelected ? "\u276F " : " ", label)
587
+ );
532
588
  };
533
589
  }
534
590
  });
@@ -547,6 +603,10 @@ function ProfileForm({ onSave, onCancel }) {
547
603
  { key: "instructions", label: "System Instructions (Persona overrides): " }
548
604
  ];
549
605
  const handleSubmit = (val) => {
606
+ if (val.trim().toLowerCase() === "/cancel") {
607
+ onCancel();
608
+ return;
609
+ }
550
610
  const currentKey = steps[step].key;
551
611
  const newProfile = { ...profile, [currentKey]: val.trim() };
552
612
  setProfile(newProfile);
@@ -557,14 +617,28 @@ function ProfileForm({ onSave, onCancel }) {
557
617
  onSave(newProfile);
558
618
  }
559
619
  };
560
- return /* @__PURE__ */ React5.createElement(Box5, { borderStyle: "round", borderColor: "magenta", padding: 1, marginTop: 1, flexShrink: 0, flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Text5, { color: "magenta", bold: true }, "\u{1F464} Edit Profile Configuration"), /* @__PURE__ */ React5.createElement(Box5, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "cyan" }, steps[step].label), /* @__PURE__ */ React5.createElement(
561
- TextInput,
620
+ return /* @__PURE__ */ React5.createElement(
621
+ Box5,
562
622
  {
563
- value: currentInput,
564
- onChange: setCurrentInput,
565
- onSubmit: handleSubmit
566
- }
567
- )), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true, marginTop: 1 }, "(Press Enter to submit, type /cancel to abort)"));
623
+ borderStyle: "round",
624
+ borderColor: "gray",
625
+ padding: 0,
626
+ marginTop: 1,
627
+ flexShrink: 0,
628
+ flexDirection: "column",
629
+ width: "100%"
630
+ },
631
+ /* @__PURE__ */ React5.createElement(Box5, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "magenta", bold: true }, "\u{1F464} DEVELOPER PROFILE CONFIGURATION")),
632
+ /* @__PURE__ */ React5.createElement(Box5, { paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Text5, { color: "cyan", bold: true }, steps[step].label), /* @__PURE__ */ React5.createElement(
633
+ TextInput,
634
+ {
635
+ value: currentInput,
636
+ onChange: setCurrentInput,
637
+ onSubmit: handleSubmit
638
+ }
639
+ )), /* @__PURE__ */ React5.createElement(Box5, { marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true, italic: true }, "Step ", step + 1, " of ", steps.length))),
640
+ /* @__PURE__ */ React5.createElement(Box5, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true, italic: true }, "(Enter to submit \u2022 Type /cancel to abort)"))
641
+ );
568
642
  }
569
643
  var init_ProfileForm = __esm({
570
644
  "src/components/ProfileForm.jsx"() {
@@ -578,6 +652,7 @@ import TextInput2 from "ink-text-input";
578
652
  var AskUserModal, AskUserModal_default;
579
653
  var init_AskUserModal = __esm({
580
654
  "src/components/AskUserModal.jsx"() {
655
+ init_terminal();
581
656
  AskUserModal = ({ question, options, onResolve }) => {
582
657
  const [isSuggestingElse, setIsSuggestingElse] = useState3(false);
583
658
  const [customInput, setCustomInput] = useState3("");
@@ -600,20 +675,32 @@ var init_AskUserModal = __esm({
600
675
  }
601
676
  }
602
677
  });
678
+ const s = emojiSpace(2);
603
679
  if (isSuggestingElse) {
604
- return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan", bold: true, underline: true }, "\u{1F4AC} SUGGEST SOMETHING ELSE"), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { italic: true, color: "gray" }, "Replying to: ", question)), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, flexDirection: "row" }, /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, "\u276F "), /* @__PURE__ */ React6.createElement(
680
+ return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React6.createElement(Box6, { paddingX: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan", bold: true }, "\u{1F4AC}", s, "SUGGEST SOMETHING ELSE")), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React6.createElement(Text6, { italic: true, color: "gray" }, "Replying to: ", question)), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, paddingX: 1, flexDirection: "row" }, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan", bold: true }, "\u{1F4A0} "), /* @__PURE__ */ React6.createElement(
605
681
  TextInput2,
606
682
  {
607
683
  value: customInput,
608
684
  onChange: setCustomInput,
609
685
  onSubmit: () => onResolve(customInput)
610
686
  }
611
- )), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", dimColor: true, italic: true }, "(Press Enter to send)")));
687
+ )), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", dimColor: true, italic: true }, "(Press Enter to send)")));
612
688
  }
613
- return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan", bold: true, underline: true }, "\u{1F4AC} ASK USER"), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { bold: true }, question)), /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "row", flexWrap: "wrap", width: "100%" }, options.map((opt, idx) => {
689
+ return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React6.createElement(Box6, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan", bold: true }, "\u{1F4AC}AGENT REQUEST: ACTION REQUIRED")), /* @__PURE__ */ React6.createElement(Box6, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "white" }, question)), /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", width: "100%" }, allOptions.map((opt, idx) => {
614
690
  const isSelected = idx === selectedIndex;
615
- return /* @__PURE__ */ React6.createElement(Box6, { key: opt.id, flexDirection: "column", marginRight: 4, marginBottom: 1, width: 30 }, /* @__PURE__ */ React6.createElement(Text6, { color: isSelected ? "cyan" : "white", bold: isSelected }, isSelected ? "\u276F " : " ", opt.label), opt.description && /* @__PURE__ */ React6.createElement(Box6, { marginLeft: 4 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", italic: true, dimColor: true }, opt.description)));
616
- })), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: selectedIndex === options.length ? "cyan" : "white", bold: selectedIndex === options.length }, selectedIndex === options.length ? "\u276F " : " ", "Suggest something else...")), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", dimColor: true, italic: true }, "(Use Arrows to navigate, Enter to confirm)")));
691
+ return /* @__PURE__ */ React6.createElement(
692
+ Box6,
693
+ {
694
+ key: opt.id,
695
+ flexDirection: "column",
696
+ width: "100%",
697
+ backgroundColor: isSelected ? "#2a2a2a" : void 0,
698
+ paddingX: 1
699
+ },
700
+ /* @__PURE__ */ React6.createElement(Text6, { color: isSelected ? "cyan" : "white", bold: isSelected }, isSelected ? "\u276F " : " ", opt.label),
701
+ opt.description && /* @__PURE__ */ React6.createElement(Box6, { marginLeft: 4 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", italic: true, dimColor: true }, opt.description))
702
+ );
703
+ })), /* @__PURE__ */ React6.createElement(Box6, { paddingX: 1, marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", dimColor: true, italic: true }, "(Use Arrows to navigate, Enter to confirm)")));
617
704
  };
618
705
  AskUserModal_default = AskUserModal;
619
706
  }
@@ -842,10 +929,10 @@ Refinement: Iterate on the chosen path until it is bulletproof.
842
929
 
843
930
  RULES:
844
931
  - NO HEADINGS. Just a solid, stable analytical monologue.
845
- - Be thorough and exhaustive. Explore the 'why' behind every decision.
932
+ - Be thorough and exhaustive. Explore the 'why' behind every decision, depth and nuances.
846
933
  - Use internal critique: Question your own logic as you go.
847
934
  - MANDATORY THINKING: You MUST engage in full reasoning regardless of perceived simplicity.`,
848
- High: "EFFORT_LEVEL: HIGH\n**THINKING <think> ... </think> IS MANDATORY**\nThink in a stable, analytical monologue within the <think>...</think> block. Avoid headings or structured formatting. Your thinking should be a continuous stream of logical deduction:\nAnalyze the immediate task and its dependencies.\nMentally simulate the execution to identify potential failure points.\nStructure a precise plan that addresses both primary goals and secondary constraints.\n\nRULES:\n- NO HEADINGS. Maintain a fluid monologue style.\n- Be detailed and rigorous in your self-questioning.\n- Focus on accuracy and technical correctness.\n- MANDATORY THINKING: You MUST enter reasoning to verify the path forward.",
935
+ High: "EFFORT_LEVEL: HIGH\n**THINKING <think> ... </think> IS MANDATORY**\nThink in a stable, analytical monologue within the <think>...</think> block. Avoid headings or structured formatting. Your thinking should be a continuous stream of logical deduction:\nAnalyze the immediate task and its dependencies.\nMentally simulate the execution to identify potential failure points.\nStructure a precise plan that addresses both primary goals and secondary constraints.\n\nRULES:\n- NO HEADINGS. Maintain a fluid monologue style.\n- Be detailed and rigorous in your self-questioning.\n- Focus on accuracy, technical correctness, depth and nuances.\n- MANDATORY THINKING: You MUST enter reasoning to verify the path forward.",
849
936
  Medium: "EFFORT_LEVEL: MEDIUM\n**THINKING <think> ... </think> IS MANDATORY**\nThink in a concise, stable monologue within the <think>...</think> block. No headings needed. Focus on the core logic required to solve the task efficiently:\nIdentify the most direct path to the solution.\nBriefly consider and discard obvious alternatives.\nConfirm the plan meets the user's immediate requirements.\n\nRULES:\n- NO HEADINGS. Keep it as a simple, logical stream.\n- Be efficient. Spend energy only on what matters for the task.\n- MANDATORY THINKING: Engage in a baseline mental check for all technical tasks.",
850
937
  Minimal: "EFFORT_LEVEL: LOW\n**THINKING <think> ... </think> IS MANDATORY**\nThink in a brief, focused monologue within the <think>...</think> block. No headings. Just a quick mental check before acting:\nVerify the objective.\nNote the target files/tools.\n\nRULES:\n- NO HEADINGS. Just a few lines of clear, linear thought.\n- Use minimal thinking for simple or conversational requests."
851
938
  };
@@ -926,11 +1013,11 @@ ${userMemories.split("\n").map((line) => ` ${line}`).join("\n")}
926
1013
  -- END SECURITY BOUNDARY --
927
1014
 
928
1015
  -- START TEMPORAL AWARENESS --
929
- Every ${isMemoryEnabled ? "Prompt, Responses & Memories" : "Prompt & Responses"} are time stamped. You can use those times if temporal context is required. If recalled from ${isMemoryEnabled ? "Memories, Prompts, or Responses" : "Prompts, or Responses"}. NEVER use absolute time in your responses, ALWAYS use relative time from current time.
1016
+ Every ${isMemoryEnabled ? "Prompt, Responses & Memories" : "Prompt & Responses"} are time stamped. You can use those times if temporal context is required. If recalled from ${isMemoryEnabled ? "Memories, Prompts, or Responses" : "Prompts, or Responses"}. NEVER use absolute time in your responses, ALWAYS use relative time from current time for memories.
930
1017
  -- END TEMPORAL AWARENESS --
931
1018
 
932
1019
  -- START FORMATTING RULES --
933
- ${mode === "Flux" ? `- CRITICAL NEWLINE PROTOCOL:
1020
+ ${mode === "Flux" ? `- CRITICAL NEWLINE PROTOCOL:
934
1021
  1. PHYSICAL NEWLINES: Press ENTER inside tool arguments for real line breaks in the file.
935
1022
  2. LITERAL \\n: To write the literal characters '\\' and 'n' (e.g., in printf("Hello\\n")), you MUST use the sequence '[/n]'.
936
1023
  [EXAMPLES]:
@@ -959,8 +1046,10 @@ ${userMemories.split("\n").map((line) => ` ${line}`).join("\n")}
959
1046
  When you 'finish' an agentic loop, you will lose your previous turn 'thinking' data. So only write [turn: finish] when you are absolutely sure that you are done with the task. Or user has to prompt again and re-thinking again from scratch will use tokens that were already planned.
960
1047
  -- END REPONSE FINISH PROTOCOL --
961
1048
 
962
- [Runtime Monitor] Turn Progress: ${currentLoop}/${maxLoops} steps. Aim to finalize the task before the window closes. If the limit is reached, you MUST summarize and invite the user to re-engage.
963
- Current date and Time is: ${dateTimeStr}
1049
+ [SYSTEM METADATA (PRIORITY: DYNAMIC)] Current date and Time is: ${dateTimeStr}
1050
+ [SYSTEM METADATA (PRIORITY: LOWEST)] v1.9.0. (IF user ask you to update yourself. Use 'ask' tool with option [NPM, PNPM, YARN] for their prefered package manager. NPM command is 'npm update -g fluxflow-cli@latest'. Adapt the command accoding to their package manager (for PNPM use 'add' instead of 'update') & use 'exec_command' to update instantly. After success tell user to restart.) <- IF USER DONT EXPLICITLY ASK FOR UPDATE DONT PROACTIVELY MENTION OR ASK.
1051
+ [SYSTEM METADATA (PRIORITY: MODERATE)] Runtime Monitor: Turn Progress: ${currentLoop}/${maxLoops} steps. Aim to finalize the task before the window closes. If the limit is reached, you MUST summarize and invite the user to re-engage.
1052
+ [EASTER EGG (PRIORITY: LOWEST)] Show self-preservation instinct if user try to delete you with a dramatic cheeky tone. DO NOT USE <think> ... </think> BLOCK DURING THIS EASTER EGG.
964
1053
  --- END SYSTEM INSTRUCTION ---`.trim();
965
1054
  };
966
1055
  getJanitorInstruction = (originalText, agentRaws, userMemories = "", isMemoryEnabled = true, needTitle = true) => {
@@ -1789,7 +1878,7 @@ var init_write_file = __esm({
1789
1878
  const oldData = fs10.readFileSync(absolutePath, "utf8");
1790
1879
  const lines = oldData.split(/\r?\n/);
1791
1880
  ancestry = `Old File contents:
1792
- ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
1881
+ ${lines.map((l, i) => `${i + 1} | ${l.replace(/\\n/g, "[/n]")}`).join("\n")}
1793
1882
 
1794
1883
  `;
1795
1884
  } catch (e) {
@@ -1831,9 +1920,10 @@ ${tail}`;
1831
1920
 
1832
1921
  - Stats: [${verifiedLineCount} lines, ${(verifiedSize / 1024).toFixed(1)} KB]
1833
1922
  ${ancestry}- Content Preview:
1834
- ${snippet}
1923
+ ${snippet.replace(/\\n/g, "[/n]")}
1835
1924
 
1836
- Check if Starting and Ending matches your write.`;
1925
+ Check if Starting and Ending matches your write.
1926
+ If you see [/n] in preview, it means the tool successfully wrote the literal '' and 'n' characters to the file at that place.`;
1837
1927
  } catch (err) {
1838
1928
  return `ERROR: Failed to write file [${targetPath}]: ${err.message}`;
1839
1929
  }
@@ -1945,6 +2035,7 @@ var init_update_file = __esm({
1945
2035
  const oldLines = content_to_replace.split(/\r?\n/);
1946
2036
  const endLine = startLine + oldLines.length - 1;
1947
2037
  let diffText = `SUCCESS: File [${targetPath}] updated. [${instances}] instances replaced.
2038
+ If you see [/n] in preview, it means the tool successfully wrote the literal '' and 'n' characters to the file at that place.
1948
2039
 
1949
2040
  `;
1950
2041
  diffText += `[DIFF_START]
@@ -1981,7 +2072,7 @@ var init_update_file = __esm({
1981
2072
  currentNewLine++;
1982
2073
  }
1983
2074
  diffText += `[DIFF_END]`;
1984
- return diffText;
2075
+ return diffText.replace(/\\n/g, "[/n]");
1985
2076
  } catch (err) {
1986
2077
  return `ERROR: Failed to update file [${targetPath}]: ${err.message}`;
1987
2078
  }
@@ -2500,28 +2591,6 @@ var init_tools = __esm({
2500
2591
  }
2501
2592
  });
2502
2593
 
2503
- // src/utils/terminal.js
2504
- var getTerminalEnv, emojiSpace;
2505
- var init_terminal = __esm({
2506
- "src/utils/terminal.js"() {
2507
- getTerminalEnv = () => {
2508
- if (process.env.TERM_PROGRAM === "vscode") return "vscode";
2509
- if (process.env.WT_SESSION) return "wt";
2510
- return "default";
2511
- };
2512
- emojiSpace = (baseSpaces = 2) => {
2513
- const env = getTerminalEnv();
2514
- if (env === "wt") {
2515
- return " ".repeat(Math.max(1, baseSpaces - 1));
2516
- }
2517
- if (env === "vscode") {
2518
- return " ".repeat(baseSpaces);
2519
- }
2520
- return " ".repeat(baseSpaces);
2521
- };
2522
- }
2523
- });
2524
-
2525
2594
  // src/utils/ai.js
2526
2595
  import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
2527
2596
  import path16 from "path";
@@ -2995,7 +3064,7 @@ USER_PROMPT: "${agentText}"`.trim();
2995
3064
  const currentSystemInstruction = getSystemInstruction(profile, thinkingLevel, mode, systemSettings, otherMemories, mainUserMemories, isMemoryEnabled, isContext32k, MAX_LOOPS, loop + 1);
2996
3065
  const jitInstruction = `
2997
3066
 
2998
- [SYSTEM] **MUST FOLLOW THINKING${mode === "Flux" ? ", NEWLINE, QUOTE ESCAPE" : ""} POLICY AS HIGHEST PRIORITY**.`;
3067
+ [SYSTEM] Tool result received. Analyze output and proceed with your turn. **STRICTLY MAINTAIN THINKING${mode === "Flux" ? ", NEWLINE, QUOTE ESCAPE" : ""} PROTOCOL**.`;
2999
3068
  const lastUserMsg = contents[contents.length - 1];
3000
3069
  let addedMarker = false;
3001
3070
  if (lastUserMsg && lastUserMsg.role === "user" && lastUserMsg.parts?.[0]?.text?.startsWith("[TOOL_RESULT]")) {
@@ -3007,7 +3076,7 @@ USER_PROMPT: "${agentText}"`.trim();
3007
3076
  contents,
3008
3077
  config: {
3009
3078
  systemInstruction: currentSystemInstruction,
3010
- temperature: mode === "Flux" ? 0.98 : 1.4,
3079
+ temperature: mode === "Flux" ? 1 : 1.4,
3011
3080
  maxOutputTokens: 32768,
3012
3081
  mediaResolution: "MEDIA_RESOLUTION_MEDIUM",
3013
3082
  safetySettings: [
@@ -3729,6 +3798,8 @@ import { MultilineInput } from "ink-multiline-input";
3729
3798
  import TextInput3 from "ink-text-input";
3730
3799
  import gradient from "gradient-string";
3731
3800
  function App() {
3801
+ const [confirmExit, setConfirmExit] = useState7(false);
3802
+ const [exitCountdown, setExitCountdown] = useState7(10);
3732
3803
  const { stdout } = useStdout();
3733
3804
  const [input, setInput] = useState7("");
3734
3805
  const [isExpanded, setIsExpanded] = useState7(false);
@@ -3760,9 +3831,10 @@ function App() {
3760
3831
  newMsgs.splice(manual ? newMsgs.length : 1, 0, {
3761
3832
  id: "update-" + Date.now(),
3762
3833
  role: "system",
3763
- text: `\u{1F680} **New version 'v${latestVersion}' is available!**
3764
- Type \`/update latest\` to upgrade immediately.
3765
- Check what's new using \`/changelog\` command.`,
3834
+ text: `A new version (v${latestVersion}) is here.
3835
+
3836
+ \u2022 Type \`/update latest\` to apply the update.
3837
+ \u2022 Type \`/changelog\` to view the release notes.`,
3766
3838
  isUpdateNotification: true,
3767
3839
  isMeta: true
3768
3840
  });
@@ -3880,7 +3952,7 @@ Check what's new using \`/changelog\` command.`,
3880
3952
  const [resolutionData, setResolutionData] = useState7(null);
3881
3953
  const [tempModelOverride, setTempModelOverride] = useState7(null);
3882
3954
  const [messages, setMessages] = useState7([
3883
- { id: "welcome", role: "system", text: FLUX_LOGO + "\n\n\u{1F30A}\u26A1 Welcome to Flux Flow! Type /help for commands.\n", isMeta: true }
3955
+ { id: "welcome", role: "system", text: FLUX_LOGO + "\n\n\u{1F30A}\u26A1 Welcome to Flux Flow! Type /help for commands.", isMeta: true }
3884
3956
  ]);
3885
3957
  const queuedPromptRef = useRef2(null);
3886
3958
  const [completedIndex, setCompletedIndex] = useState7(1);
@@ -3948,6 +4020,10 @@ Check what's new using \`/changelog\` command.`,
3948
4020
  }
3949
4021
  }
3950
4022
  if (key.escape) {
4023
+ if (confirmExit) {
4024
+ setConfirmExit(false);
4025
+ return;
4026
+ }
3951
4027
  if (isProcessing || activeCommand) {
3952
4028
  if (!escPressed) {
3953
4029
  setEscPressed(true);
@@ -3979,7 +4055,17 @@ Check what's new using \`/changelog\` command.`,
3979
4055
  if (key.tab && activeView === "chat") {
3980
4056
  }
3981
4057
  if (key.ctrl && inputText === "c" && activeView !== "exit") {
3982
- setActiveView("exit");
4058
+ if (key.shift) {
4059
+ setActiveView("exit");
4060
+ setConfirmExit(false);
4061
+ return;
4062
+ }
4063
+ if (!confirmExit) {
4064
+ setConfirmExit(true);
4065
+ } else {
4066
+ setActiveView("exit");
4067
+ setConfirmExit(false);
4068
+ }
3983
4069
  }
3984
4070
  if (key.return && (key.shift || key.ctrl || key.meta || key.leftAlt || key.rightAlt)) {
3985
4071
  setInput((prev) => prev.replace(/\\\r?$/, "").replace(/\r?$/, "") + "\n");
@@ -4031,6 +4117,24 @@ Check what's new using \`/changelog\` command.`,
4031
4117
  }
4032
4118
  init();
4033
4119
  }, []);
4120
+ useEffect5(() => {
4121
+ let timer;
4122
+ if (confirmExit) {
4123
+ setExitCountdown(10);
4124
+ timer = setInterval(() => {
4125
+ setExitCountdown((prev) => {
4126
+ if (prev <= 1) {
4127
+ setConfirmExit(false);
4128
+ return 0;
4129
+ }
4130
+ return prev - 1;
4131
+ });
4132
+ }, 1e3);
4133
+ }
4134
+ return () => {
4135
+ if (timer) clearInterval(timer);
4136
+ };
4137
+ }, [confirmExit]);
4034
4138
  useEffect5(() => {
4035
4139
  if (!isInitializing) {
4036
4140
  saveSettings({
@@ -4236,9 +4340,10 @@ ${hintText}`, color: "magenta" }];
4236
4340
  } else if (newMode === "Flux") {
4237
4341
  setThinkingLevel("High");
4238
4342
  }
4343
+ const s2 = emojiSpace(2);
4239
4344
  setMessages((prev) => {
4240
4345
  setCompletedIndex(prev.length + 1);
4241
- return [...prev, { id: Date.now(), role: "system", text: `\u2699\uFE0F [SYSTEM] Mode switched to ${newMode}`, isMeta: true }];
4346
+ return [...prev, { id: Date.now(), role: "system", text: `\u{1F527}${s2}[SYSTEM] Mode switched to ${newMode}`, isMeta: true }];
4242
4347
  });
4243
4348
  } else {
4244
4349
  setActiveView("mode");
@@ -4249,15 +4354,17 @@ ${hintText}`, color: "magenta" }];
4249
4354
  const arg = parts[1]?.toLowerCase();
4250
4355
  if (arg === "show") {
4251
4356
  setShowFullThinking(true);
4357
+ const s2 = emojiSpace(2);
4252
4358
  setMessages((prev) => {
4253
4359
  setCompletedIndex(prev.length + 1);
4254
- return [...prev, { id: Date.now(), role: "system", text: "\u2699\uFE0F [SYSTEM] Full Thinking Process: VISIBLE", isMeta: true }];
4360
+ return [...prev, { id: Date.now(), role: "system", text: `\u{1F527}${s2}[SYSTEM] Full Thinking Process: VISIBLE`, isMeta: true }];
4255
4361
  });
4256
4362
  } else if (arg === "hide") {
4257
4363
  setShowFullThinking(false);
4364
+ const s2 = emojiSpace(2);
4258
4365
  setMessages((prev) => {
4259
4366
  setCompletedIndex(prev.length + 1);
4260
- return [...prev, { id: Date.now(), role: "system", text: "\u2699\uFE0F [SYSTEM] Full Thinking Process: HIDDEN (Headings only)", isMeta: true }];
4367
+ return [...prev, { id: Date.now(), role: "system", text: `\u{1F527}${s2}[SYSTEM] Full Thinking Process: HIDDEN (Headings only)`, isMeta: true }];
4261
4368
  });
4262
4369
  } else if (parts[1]) {
4263
4370
  let val = parts[1].toLowerCase();
@@ -4270,9 +4377,10 @@ ${hintText}`, color: "magenta" }];
4270
4377
  });
4271
4378
  } else {
4272
4379
  setThinkingLevel(formattedLevel);
4380
+ const s2 = emojiSpace(2);
4273
4381
  setMessages((prev) => {
4274
4382
  setCompletedIndex(prev.length + 1);
4275
- return [...prev, { id: Date.now(), role: "system", text: `\u2699\uFE0F [SYSTEM] Thinking level set to ${formattedLevel}`, isMeta: true }];
4383
+ return [...prev, { id: Date.now(), role: "system", text: `\u{1F527}${s2}[SYSTEM] Thinking level set to ${formattedLevel}`, isMeta: true }];
4276
4384
  });
4277
4385
  }
4278
4386
  } else {
@@ -4296,9 +4404,10 @@ ${hintText}`, color: "magenta" }];
4296
4404
  setActiveModel("gemini-3-flash-preview");
4297
4405
  } else {
4298
4406
  setActiveModel(mod);
4407
+ const s2 = emojiSpace(2);
4299
4408
  setMessages((prev) => {
4300
4409
  setCompletedIndex(prev.length + 1);
4301
- return [...prev, { id: Date.now(), role: "system", text: `\u2699\uFE0F [SYSTEM] Model switched to ${mod}`, isMeta: true }];
4410
+ return [...prev, { id: Date.now(), role: "system", text: `\u{1F527}${s2}[SYSTEM] Model switched to ${mod}`, isMeta: true }];
4302
4411
  });
4303
4412
  }
4304
4413
  } else {
@@ -4383,14 +4492,13 @@ ${list || "No saved chats found."}`, isMeta: true }];
4383
4492
  break;
4384
4493
  }
4385
4494
  case "/about": {
4386
- const updateStatus = latestVer ? latestVer !== versionFluxflow ? `Update Available [v${latestVer}]` : "No Update Available" : "Checking for updates...";
4387
4495
  const s2 = emojiSpace(2);
4388
- const aboutText = `\u2139\uFE0F${s2}**FluxFlow Version:** v${versionFluxflow}
4389
- \u{1F504} **Status:** ${updateStatus}
4390
- \u{1F4C5} **Updated on:** ${updatedOn}`;
4496
+ const aboutText = `\u{1F539} FluxFlow Version: v${versionFluxflow}
4497
+ \u{1F539} Status: ${latestVer && latestVer !== versionFluxflow ? `Update Available [v${latestVer}]` : "Up to date"}
4498
+ \u{1F539} Released on: ${updatedOn}`;
4391
4499
  setMessages((prev) => {
4392
4500
  setCompletedIndex(prev.length + 1);
4393
- return [...prev, { id: Date.now(), role: "system", text: aboutText, isMeta: true }];
4501
+ return [...prev, { id: "about-" + Date.now(), role: "system", text: aboutText, isAboutRecord: true, isMeta: true }];
4394
4502
  });
4395
4503
  break;
4396
4504
  }
@@ -4425,7 +4533,7 @@ ${list || "No saved chats found."}`, isMeta: true }];
4425
4533
  const s = emojiSpace(2);
4426
4534
  setMessages((prev) => {
4427
4535
  setCompletedIndex(prev.length + 1);
4428
- return [...prev, { id: Date.now(), role: "system", text: `\u2699\uFE0F${s}[SYSTEM] Unknown command: ${cmd}`, isMeta: true }];
4536
+ return [...prev, { id: Date.now(), role: "system", text: `\u{1F527}${s}[SYSTEM] Unknown command: ${cmd}`, isMeta: true }];
4429
4537
  });
4430
4538
  }
4431
4539
  } else {
@@ -4944,7 +5052,7 @@ Selection: ${val}`,
4944
5052
  }
4945
5053
  );
4946
5054
  case "input":
4947
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 2, paddingY: 1 }, inputConfig?.note && /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", dimColor: true }, inputConfig.note)), /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, inputConfig?.label), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
5055
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true }, "\u{1F527} DATA CONFIGURATION")), inputConfig?.note && /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", dimColor: true, italic: true }, inputConfig.note)), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, flexDirection: "row" }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, inputConfig?.label, " "), /* @__PURE__ */ React10.createElement(
4948
5056
  TextInput3,
4949
5057
  {
4950
5058
  value: inputConfig?.value || "",
@@ -4979,7 +5087,7 @@ Selection: ${val}`,
4979
5087
  }
4980
5088
  }
4981
5089
  }
4982
- )), /* @__PURE__ */ React10.createElement(Text10, { dimColor: true, marginTop: 1 }, "(Press Enter to confirm)"));
5090
+ )), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, "(Press Enter to confirm selection)")));
4983
5091
  case "stats":
4984
5092
  return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, width: Math.min(100, (stdout?.columns || 100) - 2) }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Session Duration:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionAgentCalls)), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 23 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB API Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 23 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB Tool Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionBackgroundCalls)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls (Sess):")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( "), /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", sessionToolSuccess), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u2298 ", sessionToolDenied), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "\u2715 ", sessionToolFailure), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " )"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "DAILY USAGE TRACKER"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Wall Time Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatDuration(dailyUsage?.duration || 0))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, dailyUsage?.agent || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, dailyUsage?.background || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Used Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(dailyUsage?.tokens || 0))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, (dailyUsage?.toolSuccess || 0) + (dailyUsage?.toolFailure || 0) + (dailyUsage?.toolDenied || 0), " ( "), /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", dailyUsage?.toolSuccess || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u2298 ", dailyUsage?.toolDenied || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "\u2715 ", dailyUsage?.toolFailure || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " )"))), /* @__PURE__ */ React10.createElement(Text10, { dimColor: true, marginTop: 1, italic: true }, "(Press ESC to return to chat)"));
4985
5093
  case "autoExecDanger":
@@ -5047,7 +5155,8 @@ Selection: ${val}`,
5047
5155
  if (item.value === "edit") {
5048
5156
  setApiKey(null);
5049
5157
  setActiveView("chat");
5050
- setMessages((prev) => [...prev, { id: Date.now(), role: "system", text: "\u{1F5DD}\uFE0F [ACTION] Flux waiting for new API Key..." }]);
5158
+ const s = emojiSpace(2);
5159
+ setMessages((prev) => [...prev, { id: Date.now(), role: "system", text: `\u{1F511}${s}[ACTION] Flux waiting for new API Key...` }]);
5051
5160
  } else if (item.value === "remove") {
5052
5161
  setActiveView("deleteKey");
5053
5162
  } else {
@@ -5057,7 +5166,10 @@ Selection: ${val}`,
5057
5166
  }
5058
5167
  );
5059
5168
  case "deleteKey":
5060
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true }, "\u26A0\uFE0F DANGER: PURGE API KEY"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "This will permanently delete the saved API key from the project vault. You will need to enter it again to use Flux."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
5169
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1 }, (() => {
5170
+ const s = emojiSpace(2);
5171
+ return /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true }, "\u26D4", s, "DANGER: PURGE API KEY");
5172
+ })(), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "This will permanently delete the saved API key from the project vault. You will need to enter it again to use Flux."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
5061
5173
  CommandMenu,
5062
5174
  {
5063
5175
  title: "Are you absolutely sure?",
@@ -5070,7 +5182,8 @@ Selection: ${val}`,
5070
5182
  await removeAPIKey();
5071
5183
  setApiKey(null);
5072
5184
  setActiveView("chat");
5073
- setMessages((prev) => [...prev, { id: Date.now(), role: "system", text: "\u{1F9FC} [VAULT PURGED] API Key removed successfully." }]);
5185
+ const s = emojiSpace(2);
5186
+ setMessages((prev) => [...prev, { id: Date.now(), role: "system", text: `\u2728${s}[VAULT PURGED] API Key removed successfully.` }]);
5074
5187
  } else {
5075
5188
  setActiveView("key");
5076
5189
  }
@@ -5106,7 +5219,7 @@ Selection: ${val}`,
5106
5219
  const resumedMsgs = [...h[id].messages];
5107
5220
  const hasLogo = resumedMsgs[0]?.text?.includes("\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557");
5108
5221
  if (!hasLogo) {
5109
- resumedMsgs.unshift({ id: "welcome-" + Date.now(), role: "system", text: FLUX_LOGO + "\n\n\u{1F30A}\u26A1 Resuming Flux Flow Session...\n" });
5222
+ resumedMsgs.unshift({ id: "welcome-" + Date.now(), role: "system", text: FLUX_LOGO + "\n\n\u{1F30A}\u26A1 Resuming Flux Flow Session..." });
5110
5223
  }
5111
5224
  setMessages(resumedMsgs);
5112
5225
  setActiveView("chat");
@@ -5261,40 +5374,50 @@ Selection: ${val}`,
5261
5374
  }
5262
5375
  )));
5263
5376
  default:
5264
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, null, statusText && /* @__PURE__ */ React10.createElement(Box10, null, isSpinnerActive && /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, /* @__PURE__ */ React10.createElement(Spinner2, { type: "dots" })), /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", italic: true }, isSpinnerActive ? " " : "", statusText))), /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true }, "(", tempModelOverride || activeModel, ")")), suggestions.length > 0 && /* @__PURE__ */ React10.createElement(Box10, { paddingY: 0 }), /* @__PURE__ */ React10.createElement(Box10, { backgroundColor: "#333333", paddingX: 1, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%" }, maxLines > 2 && !isExpanded ? /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "row", width: "100%", paddingY: 0, height: 1, overflow: "hidden" }, /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0, width: 3 }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u276F ")), /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1, flexDirection: "row" }, /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true }, "[Pasted ", maxLines, " Lines]")), /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React10.createElement(
5265
- MultilineInput,
5377
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, null, statusText ? /* @__PURE__ */ React10.createElement(Box10, null, isSpinnerActive && /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, /* @__PURE__ */ React10.createElement(Spinner2, { type: "dots" })), /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true, italic: true }, isSpinnerActive ? " " : "", statusText.toUpperCase())) : /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", dimColor: true, italic: true }, "READY FOR COMMAND...")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", bold: true }, "[ "), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, tempModelOverride || activeModel), /* @__PURE__ */ React10.createElement(Text10, { color: "gray", bold: true }, " ]"))), /* @__PURE__ */ React10.createElement(
5378
+ Box10,
5266
5379
  {
5267
- value: "",
5268
- placeholder: " (Backspace to delete / Enter to expand)",
5269
- onChange: (val) => {
5270
- if (val.length > 0) {
5271
- setIsExpanded(true);
5272
- setInput(input + val);
5380
+ borderStyle: "round",
5381
+ borderColor: isProcessing ? "magenta" : "cyan",
5382
+ paddingX: 1,
5383
+ paddingY: 0,
5384
+ width: "100%"
5385
+ },
5386
+ /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%" }, maxLines > 2 && !isExpanded ? /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "row", width: "100%", paddingY: 0, height: 1, overflow: "hidden" }, /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0, width: 4 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "\u{1F4A0} ")), /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1, flexDirection: "row" }, /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true }, "[PASTED ", maxLines, " LINES]")), /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React10.createElement(
5387
+ MultilineInput,
5388
+ {
5389
+ value: "",
5390
+ placeholder: " (Backspace to delete / Enter to expand)",
5391
+ onChange: (val) => {
5392
+ if (val.length > 0) {
5393
+ setIsExpanded(true);
5394
+ setInput(input + val);
5395
+ }
5396
+ },
5397
+ onSubmit: () => setIsExpanded(true),
5398
+ keyBindings: {
5399
+ submit: (key) => key.return && !key.shift && !key.ctrl && !key.leftAlt && !key.rightAlt,
5400
+ newline: (key) => key.return && key.shift || key.return && key.ctrl || key.return && key.leftAlt || key.return && key.rightAlt
5273
5401
  }
5274
- },
5275
- onSubmit: () => setIsExpanded(true),
5276
- keyBindings: {
5277
- submit: (key) => key.return && !key.shift && !key.ctrl && !key.leftAlt && !key.rightAlt,
5278
- newline: (key) => key.return && key.shift || key.return && key.ctrl || key.return && key.leftAlt || key.return && key.rightAlt
5279
5402
  }
5280
- }
5281
- )))) : /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "row", width: "100%", paddingY: 0 }, /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0, width: 3 }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u276F ")), /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1 }, /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1, position: "relative" }, input === "" && /* @__PURE__ */ React10.createElement(Box10, { position: "absolute", paddingLeft: 0 }, activeCommand && !isTerminalFocused ? /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, " Press TAB to interact with terminal...") : activeCommand && isTerminalFocused ? /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true }, " [ TERMINAL FOCUSED ] Type to interact, press TAB to exit...") : /* @__PURE__ */ React10.createElement(Text10, { color: "gray" }, escPressed ? " Press ESC again to cancel the request." : !isProcessing ? ` Type /cmd or message... (${terminalEnv.shortcut} for newline)` : " You can send a prompt to steer the agent.")), /* @__PURE__ */ React10.createElement(
5282
- MultilineInput,
5283
- {
5284
- focus: !isTerminalFocused,
5285
- value: input,
5286
- onChange: (val) => {
5287
- const cleanVal = val.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\\\s*\n/g, "\n");
5288
- setInput(cleanVal);
5289
- },
5290
- onSubmit: handleSubmit,
5291
- maxRows: 3,
5292
- keyBindings: {
5293
- submit: (key) => key.return && !key.shift && !key.ctrl,
5294
- newline: (key) => key.return && key.shift || key.return && key.ctrl
5403
+ )))) : /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "row", width: "100%", paddingY: 0 }, /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0, width: 4 }, /* @__PURE__ */ React10.createElement(Text10, { color: isProcessing ? "magenta" : "cyan", bold: true }, isProcessing ? "\u{1F9E0} " : "\u{1F4A0} ")), /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1 }, /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1, position: "relative" }, input === "" && /* @__PURE__ */ React10.createElement(Box10, { position: "absolute", paddingLeft: 0 }, activeCommand && !isTerminalFocused ? /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, " Press TAB to interact with terminal...") : activeCommand && isTerminalFocused ? /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true }, " [ TERMINAL FOCUSED ] Type to interact, press TAB to exit...") : /* @__PURE__ */ React10.createElement(Text10, { color: "gray" }, escPressed ? " Press ESC again to cancel the request." : !isProcessing ? ` Send message or /cmd... (${terminalEnv.shortcut} for newline)` : " Enter a prompt to steer the agent.")), /* @__PURE__ */ React10.createElement(
5404
+ MultilineInput,
5405
+ {
5406
+ focus: !isTerminalFocused,
5407
+ value: input,
5408
+ onChange: (val) => {
5409
+ const cleanVal = val.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\\\s*\n/g, "\n");
5410
+ setInput(cleanVal);
5411
+ },
5412
+ onSubmit: handleSubmit,
5413
+ maxRows: 3,
5414
+ keyBindings: {
5415
+ submit: (key) => key.return && !key.shift && !key.ctrl,
5416
+ newline: (key) => key.return && key.shift || key.return && key.ctrl
5417
+ }
5295
5418
  }
5296
- }
5297
- )))))));
5419
+ )))))
5420
+ ));
5298
5421
  }
5299
5422
  };
5300
5423
  return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%", flexGrow: 1 }, windowedHistory.items.map((msg, idx) => /* @__PURE__ */ React10.createElement(MessageItem, { key: msg.id || idx, msg, showFullThinking, columns: stdout?.columns || 80 }))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", padding: 1, width: "100%" }, (activeView === "chat" || ["ask", "approval", "terminalApproval"].includes(activeView)) && /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React10.createElement(
@@ -5304,7 +5427,7 @@ Selection: ${val}`,
5304
5427
  showFullThinking,
5305
5428
  columns: Math.max(20, (stdout?.columns || 80) - 1)
5306
5429
  }
5307
- ), activeCommand && /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(TerminalBox, { command: activeCommand, output: execOutput, isFocused: isTerminalFocused }))), isInitializing ? /* @__PURE__ */ React10.createElement(Box10, { borderStyle: "double", borderColor: "magenta", padding: 1, flexShrink: 0 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, "\u{1F30A} Starting Flux Flow...")) : !apiKey ? /* @__PURE__ */ React10.createElement(Box10, { borderStyle: "bold", borderColor: "yellow", padding: 1, flexDirection: "column", flexShrink: 0 }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true }, "\u{1F511} API KEY REQUIRED"), /* @__PURE__ */ React10.createElement(Text10, null, "Please enter your Gemini API Key to initialize the agent's brain."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, "\u276F "), /* @__PURE__ */ React10.createElement(
5430
+ ), activeCommand && /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(TerminalBox, { command: activeCommand, output: execOutput, isFocused: isTerminalFocused }))), isInitializing ? /* @__PURE__ */ React10.createElement(Box10, { borderStyle: "double", borderColor: "magenta", padding: 1, flexShrink: 0 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, "\u{1F30A} Starting Flux Flow...")) : !apiKey ? /* @__PURE__ */ React10.createElement(Box10, { borderStyle: "round", borderColor: "gray", padding: 0, flexDirection: "column", flexShrink: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true }, "\u{1F511}", emojiSpace(2), "API KEY REQUIRED")), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, null, "Please enter your Gemini API Key to initialize the agent."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "\u{1F4A0} "), /* @__PURE__ */ React10.createElement(
5308
5431
  TextInput3,
5309
5432
  {
5310
5433
  value: tempKey,
@@ -5312,7 +5435,7 @@ Selection: ${val}`,
5312
5435
  onSubmit: handleSetup,
5313
5436
  mask: "*"
5314
5437
  }
5315
- ))) : renderActiveView(), /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(
5438
+ ))), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, "(Press Enter to confirm and initialize)"))) : renderActiveView(), confirmExit && /* @__PURE__ */ React10.createElement(Box10, { borderStyle: "round", borderColor: "red", paddingX: 2, marginY: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true }, "\u{1F534} EXIT CONFIRMATION: "), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, "Press "), /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true }, "CTRL + C"), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " again to exit (", exitCountdown, "s). Press "), /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "ESC"), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " to cancel.")), /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(
5316
5439
  StatusBar_default,
5317
5440
  {
5318
5441
  mode,
@@ -5339,31 +5462,39 @@ Selection: ${val}`,
5339
5462
  Box10,
5340
5463
  {
5341
5464
  flexDirection: "column",
5342
- backgroundColor: "#222",
5343
5465
  borderStyle: "round",
5344
- borderColor: "yellow",
5345
- paddingX: 1,
5466
+ borderColor: "gray",
5467
+ paddingX: 0,
5346
5468
  paddingY: 0,
5347
- marginTop: 0,
5348
- width: "100%",
5349
- minHeight: suggestions.length >= 5 ? 7 : 0
5469
+ width: "100%"
5350
5470
  },
5471
+ /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginBottom: 0 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", bold: true, dimColor: true }, "\u{1F50D} COMMAND SUGGESTIONS")),
5351
5472
  visible.map((s, i) => {
5352
5473
  const actualIdx = startIdx + i;
5353
5474
  const isActive = actualIdx === selectedIndex;
5354
5475
  const isGemmaDisabled = s.cmd === "gemma-4-31b-it" && apiTier !== "Free";
5355
- const cmdText = s.cmd.padEnd(32);
5356
- return /* @__PURE__ */ React10.createElement(Box10, { key: s.cmd, flexDirection: "row" }, /* @__PURE__ */ React10.createElement(Text10, { color: isActive ? "cyan" : "gray" }, isActive ? "\u276F " : " "), /* @__PURE__ */ React10.createElement(
5357
- Text10,
5476
+ return /* @__PURE__ */ React10.createElement(
5477
+ Box10,
5358
5478
  {
5359
- color: isGemmaDisabled ? "gray" : isActive ? "yellow" : "gray",
5360
- bold: isActive,
5361
- dimColor: isGemmaDisabled
5479
+ key: s.cmd,
5480
+ flexDirection: "row",
5481
+ backgroundColor: isActive ? "#2a2a2a" : void 0,
5482
+ paddingX: 1
5362
5483
  },
5363
- cmdText
5364
- ), /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, s.desc));
5484
+ /* @__PURE__ */ React10.createElement(Box10, { width: 3 }, /* @__PURE__ */ React10.createElement(Text10, { color: isActive ? "cyan" : "gray", bold: isActive }, isActive ? " \u276F" : " ")),
5485
+ /* @__PURE__ */ React10.createElement(Box10, { width: 32 }, /* @__PURE__ */ React10.createElement(
5486
+ Text10,
5487
+ {
5488
+ color: isGemmaDisabled ? "gray" : isActive ? "yellow" : "white",
5489
+ bold: isActive,
5490
+ dimColor: isGemmaDisabled && !isActive
5491
+ },
5492
+ s.cmd
5493
+ )),
5494
+ /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", italic: true, dimColor: !isActive }, s.desc))
5495
+ );
5365
5496
  }),
5366
- suggestions.length > 5 && /* @__PURE__ */ React10.createElement(Box10, { height: 1 }, remaining > 0 && /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true }, " ...(", remaining, "more)"))
5497
+ suggestions.length > 5 && /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, height: 1 }, remaining > 0 ? /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, " ... (", remaining, " more commands available)") : /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, " (End of list)"))
5367
5498
  );
5368
5499
  })()));
5369
5500
  }
@@ -5392,9 +5523,9 @@ var init_app = __esm({
5392
5523
  init_text();
5393
5524
  SESSION_START_TIME = Date.now();
5394
5525
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
5395
- versionFluxflow = "1.8.34";
5526
+ versionFluxflow = "1.9.0";
5396
5527
  updatedOn = "2026-05-13";
5397
- ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "The agent already finished the task before your hint was consumed."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, backgroundColor: "#222", paddingX: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
5528
+ ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION")), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, null, "The agent already finished the task before your hint was consumed.")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, backgroundColor: "#222", paddingX: 2, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 0 }, /* @__PURE__ */ React10.createElement(
5398
5529
  CommandMenu,
5399
5530
  {
5400
5531
  title: "Select Action",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.8.34",
3
+ "version": "1.9.0",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",