fluxflow-cli 1.3.2 โ†’ 1.3.3

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 (3) hide show
  1. package/README.md +47 -56
  2. package/dist/fluxflow.js +74 -29
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,35 +1,14 @@
1
- # ๐ŸŒŠ Flux Flow
2
- ![Flux Flow Hero](./fluxflow.png)
1
+ # ๐ŸŒŒ Flux Flow (`fluxflow-cli`)
2
+ ![Flux Flow Logo](https://github.com/KushalRoyChowdhury/fluxflow-cli/blob/main/fluxflow.png)
3
3
 
4
- **A Beautiful, Autonomous Terminal AI Agent**
4
+ ### *The High-Fidelity Agentic Terminal for the Flux Era.*
5
5
 
6
- Flux Flow is an advanced, fully autonomous AI agent that lives directly in your terminal. Built with Node.js and [Ink](https://github.com/vadimdemedes/ink) (React for interactive command-line apps), it provides a highly responsive, component-based UI powered by a sophisticated dual-model AI architecture.
7
-
8
- Whether you need a conversational partner or an autonomous developer that can write code, run shell commands, and read your project files, Flux Flow adapts to your needs.
6
+ **Flux Flow** is not just another CLIโ€”it's a high-speed, sassy, and goal-oriented CLI AI Agent powered by the latest Gemini/Gemma frontier models. Designed for developers who demand a premium UI/UX while managing complex file-system tasks, web research, and autonomous workflows.
9
7
 
10
8
  ---
11
9
 
12
- ## โœจ Features
13
-
14
- - **Responsive Terminal UI**: A gorgeous, reactive interface built with React and Ink, featuring multi-line input, status bars, modals, and diff views.
15
- - **Dual-Model Architecture**: A primary agent interacts with you and executes tasks, while a silent background "Janitor" model handles chat summarization and long-term memory extraction without blocking the main UI.
16
- - **Two Operating Modes**:
17
- - **Flux (Dev Mode)**: Full system access. The agent can read/write files, execute shell commands, and run autonomous agentic loops (up to 45 iterations) to solve complex coding tasks.
18
- - **Flow (Chat Mode)**: Focused on conversation and web research, with limited agentic loops for faster response times.
19
- - **Advanced Memory System**: Features both temporary session context and persistent, cross-session user memories encrypted locally on your machine.
20
- - **Agentic Tooling**: Built-in tools for smart file patching, web scraping, web searching, and terminal execution.
21
- - **Autonomous Project Alignment**: Automatically detects and adheres to project-specific instructions in `Agent.md`, `Skills.md`, and `Fluxflow.md` for high-fidelity coding standards and complex workflows.
22
- - **Customizable "Thinking" Levels**: Adjust the depth of the model's reasoning process (from Minimal to Max).
23
- - **High-Reliability Fallback**: Automatic failover to a lighter, high-concurrency model (Gemini 3.1 Flash Lite) during peak traffic to ensure 100% session persistence.
24
-
25
- ## ๐Ÿš€ Quick Start
26
-
27
- ### Prerequisites
28
- - [Node.js](https://nodejs.org/) (v18 or higher recommended)
29
- - `npm`, `yarn`, or `pnpm`
30
-
31
- ### Via NPM (Global & Instant)
32
- You can run the agent instantly or install it globally for high-speed access:
10
+ ## ๐Ÿš€ Instant Ignition (No Setup Required)
11
+ You don't even need to install it. Just fire up your terminal and run:
33
12
 
34
13
  ```bash
35
14
  # Run instantly (Zero Setup)
@@ -37,44 +16,56 @@ npx fluxflow-cli
37
16
 
38
17
  # OR Install Globally
39
18
  npm install -g fluxflow-cli
40
- fluxflow
19
+ fluxflow-cli
41
20
  ```
42
21
 
43
- ### From Source (Local Development)
44
- 1. Clone the repository and install dependencies:
45
- ```bash
46
- git clone <repository-url>
47
- cd Flux-Flow
48
- npm install
49
- ```
22
+ *The agent will prompt you for your Gemini API Key on the first run and store it securely in an XOR-encrypted vault.*
50
23
 
51
- 2. Start the agent:
52
- ```bash
53
- npm start
54
- ```
24
+ ---
55
25
 
56
- ## ๐Ÿ“– Documentation
26
+ ## โœจ Why Flux Flow?
57
27
 
58
- To keep this README concise, detailed information about specific components of Flux Flow has been split into separate documents:
28
+ ### ๐ŸŽจ **Premium Visual Sovereignty**
29
+ Experience a terminal UI that feels alive. Built with **Ink** and **React**, Flux Flow features:
30
+ - **Dynamic Status Bar**: Real-time telemetry showing your "Neural Headroom" (token usage), Thinking Level, and Session ID.
31
+ - **Archived Terminal Flow**: See execution outputs transform from live elements into permanent conversation records.
32
+ - **Rich Aesthetics**: High-contrast, sleek design with smooth transitions and micro-animations.
59
33
 
60
- - **[Architecture & Design](./ARCHITECTURE.md)**: Deep dive into the React/Ink rendering, the Agentic Loop, and the Janitor background process.
61
- - **[Agent Tools & Capabilities](./TOOLS.md)**: A comprehensive list of the tools available to the agent (e.g., File I/O, Execution, Web tools).
62
- - **[UI & Interaction Features](./UI_FEATURES.md)**: Details on commands, thinking levels, and human-in-the-loop verification.
34
+ ### ๐Ÿง  **The Dual-Intelligence System**
35
+ - **Flux Mode (Dev)**: High-speed, agentic problem solving with a 50-turn persistent loop for massive coding tasks.
36
+ - **Flow Mode (Chat)**: Optimized for deep research, high-quality conversation, and web-assisted reasoning.
63
37
 
64
- ## ๐Ÿ”’ Security & Privacy
38
+ ### ๐Ÿ›ก๏ธ **Digital Fortress Governance**
39
+ Security isn't an afterthought; it's a boundary.
40
+ - **External Path Hardlock**: Restricts the agent to your Current Working Directory (CWD) unless you explicitly unlock it.
41
+ - **Human-in-the-Loop (HITL)**: Every file write and terminal command requires your high-fidelity approval.
42
+ - **XOR Vaulting**: All local session histories, memories, and API keys are obfuscated and encrypted at rest.
43
+ - **Adaptive Failover**: Automatic multi-stage retry logic with high-concurrency fallback model switching (Gemini 3.1 Flash Lite) during peak API congestion.
65
44
 
66
- Flux Flow runs entirely locally on your machine.
67
- - **Global Storage**: All history, memories, and API keys are stored securely in your home directory at `~/.fluxflow`. Sensitive data is encrypted.
68
- - **Nuclear Reset**: Use the `/reset` command to instantly purge all logs, secrets, and settings from the global storage directory.
69
- - **Configurable Boundaries**: In Flux mode, file access can be strictly confined to the Current Working Directory, or expanded globally via settings.
70
- - **API Keys**: You supply your own Gemini/Google AI Studio API keys.
45
+ ### ๐Ÿงน **The Background Janitor**
46
+ While you move at high speed, the Janitor follows behindโ€”refining session titles, compressing data, and ensuring your context window remains at absolute peak performance.
71
47
 
72
- ## ๐Ÿ› ๏ธ Built With
48
+ ---
49
+
50
+ ## ๐Ÿ› ๏ธ Key Capabilities
51
+ - **Deep File-System Interaction**: Edit, move, and refactor code across multiple files with atomic precision.
52
+ - **Real-Time Web Intelligence**: Autonomous web-searching via DuckDuckGo for live news and technical research.
53
+ - **Autonomous Project Alignment**: Automatically detects and adheres to project-specific instructions in `Agent.md`, `Skills.md`, and `Fluxflow.md` for high-fidelity alignment with your coding standards and custom workflows.
54
+ - **High-Reliability Fallback**: Automatic failover to a lighter, high-concurrency model during peak traffic to ensure zero session loss.
55
+ - **Persistent Memory**: The agent learns from your preferences and project requirements across sessions.
56
+
57
+ ---
58
+
59
+ ## โš™๏ธ Configuration
60
+ Type `/settings` in-app to live-configure:
61
+ - **Thinking Level**: Low, Medium, or High (Deep-Reasoning).
62
+ - **Auto-Execution**: For ultimate high-speed flow (Advanced users only).
63
+ - **Security Perimeter**: Toggle External Workspace access.
64
+
65
+ ---
73
66
 
74
- - **[React](https://react.dev/) & [Ink](https://github.com/vadimdemedes/ink)**: For the interactive CLI rendering.
75
- - **[@google/genai](https://www.npmjs.com/package/@google/genai)**: The core AI SDK powering the agent's intelligence.
76
- - **[chalk](https://www.npmjs.com/package/chalk) & [gradient-string](https://www.npmjs.com/package/gradient-string)**: For terminal styling and aesthetics.
77
- - **[fs-extra](https://www.npmjs.com/package/fs-extra)**: For robust file system operations.
67
+ ## ๐Ÿ License
68
+ MIT ยฉ 2026 Flux Flow Team.
78
69
 
79
70
  ---
80
- *Created as a demonstration of highly capable AI tooling.*
71
+ *Forged with โšก and ๐Ÿงฌ. Welcome to the FluxFlow.*
package/dist/fluxflow.js CHANGED
@@ -71,13 +71,14 @@ var init_ChatLayout = __esm({
71
71
  };
72
72
  InlineMarkdown = React2.memo(({ text, color }) => {
73
73
  if (!text) return null;
74
- const parts = text.split(/(\*\*.*?\*\*|\*.*?\*|`.*?`|\$\\viewtext\{.*?\}\$|\[.*?\]\(.*?\))/g);
74
+ const parts = text.split(/(\*\*.*?\*\*|\*.*?\*|`.*?`|\$\\viewtext\{.*?\}\$|\[.*?\]\s*\(.*?\)|\[.*?\]\s*\[.*?\]|https?:\/\/[^\s]+)/g);
75
75
  return /* @__PURE__ */ React2.createElement(Text2, { color, wrap: "anywhere" }, parts.map((part, j) => {
76
+ if (!part) return null;
76
77
  if (part.startsWith("**") && part.endsWith("**")) {
77
- return /* @__PURE__ */ React2.createElement(Text2, { key: j, bold: true, color: "white" }, part.slice(2, -2));
78
+ return /* @__PURE__ */ React2.createElement(Text2, { key: j, bold: true, color: "white" }, /* @__PURE__ */ React2.createElement(InlineMarkdown, { text: part.slice(2, -2), color: "white" }));
78
79
  }
79
80
  if (part.startsWith("*") && part.endsWith("*")) {
80
- return /* @__PURE__ */ React2.createElement(Text2, { key: j, italic: true, color: "gray" }, part.slice(1, -1));
81
+ return /* @__PURE__ */ React2.createElement(Text2, { key: j, italic: true, color: "gray" }, /* @__PURE__ */ React2.createElement(InlineMarkdown, { text: part.slice(1, -1), color: "gray" }));
81
82
  }
82
83
  if (part.startsWith("`") && part.endsWith("`")) {
83
84
  return /* @__PURE__ */ React2.createElement(Text2, { key: j, color: "cyan", backgroundColor: "#003333" }, " ", part.slice(1, -1), " ");
@@ -86,11 +87,16 @@ var init_ChatLayout = __esm({
86
87
  const content = part.slice(11, -2);
87
88
  return /* @__PURE__ */ React2.createElement(Text2, { key: j, color: "white", backgroundColor: "#4c0099", bold: true, italic: true }, " ", content, " ");
88
89
  }
89
- if (part.startsWith("[") && part.includes("](")) {
90
- const match = part.match(/\[(.*?)\]\((.*?)\)/);
91
- if (match) {
92
- return /* @__PURE__ */ React2.createElement(Text2, { key: j }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", underline: true }, match[1]), /* @__PURE__ */ React2.createElement(Text2, { color: "gray", dimColor: true }, " (", match[2], ")"));
93
- }
90
+ if (part.startsWith("[") && (part.includes("](") || part.includes("] ("))) {
91
+ const match = part.match(/\[(.*?)\]\s*\((.*?)\)/);
92
+ if (match) return /* @__PURE__ */ React2.createElement(Text2, { key: j }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", underline: true, bold: true }, match[1]), /* @__PURE__ */ React2.createElement(Text2, { color: "gray", dimColor: true, italic: true }, " (", match[2], ")"));
93
+ }
94
+ if (part.startsWith("[") && (part.includes("][") || part.includes("] ["))) {
95
+ const match = part.match(/\[(.*?)\]\s*\[(.*?)\]/);
96
+ if (match) return /* @__PURE__ */ React2.createElement(Text2, { key: j }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", underline: true, bold: true }, match[1]), /* @__PURE__ */ React2.createElement(Text2, { color: "gray", dimColor: true, italic: true }, " [", match[2], "]"));
97
+ }
98
+ if (part.startsWith("http")) {
99
+ return /* @__PURE__ */ React2.createElement(Text2, { key: j, color: "cyan", underline: true, italic: true }, part);
94
100
  }
95
101
  return part;
96
102
  }));
@@ -102,15 +108,8 @@ var init_ChatLayout = __esm({
102
108
  );
103
109
  const header = rows[0];
104
110
  const data = rows.slice(2);
105
- const colWidths = header.map((_, i) => {
106
- let max = header[i].replace(/\*|`/g, "").length;
107
- data.forEach((row) => {
108
- const cleanCell = (row[i] || "").replace(/\*|`/g, "");
109
- if (cleanCell.length > max) max = cleanCell.length;
110
- });
111
- return max;
112
- });
113
- return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "single", borderColor: "#333", paddingX: 1, marginY: 1, alignSelf: "flex-start" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "row", marginBottom: 1 }, header.map((cell, i) => /* @__PURE__ */ React2.createElement(Box2, { key: i, width: colWidths[i] + 4, paddingRight: 4 }, /* @__PURE__ */ React2.createElement(InlineMarkdown, { text: cell, color: "cyan" })))), /* @__PURE__ */ React2.createElement(Box2, { borderStyle: "single", borderTop: true, borderBottom: false, borderLeft: false, borderRight: false, borderColor: "#444", width: "100%", marginBottom: 1 }), data.map((row, ri) => /* @__PURE__ */ React2.createElement(Box2, { key: ri, flexDirection: "row", marginBottom: ri === data.length - 1 ? 0 : 1 }, row.map((cell, ci) => /* @__PURE__ */ React2.createElement(Box2, { key: ci, width: colWidths[ci] + 4, paddingRight: 4, flexDirection: "column" }, /* @__PURE__ */ React2.createElement(InlineMarkdown, { text: cell, color: "white" }))))));
111
+ const colPercentage = Math.floor(100 / header.length);
112
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "single", borderColor: "#333", paddingX: 1, marginY: 1, width: "100%", flexGrow: 1 }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "row", borderStyle: "single", borderBottom: true, borderTop: false, borderLeft: false, borderRight: false, borderColor: "#444", marginBottom: 1, paddingBottom: 1, width: "100%" }, header.map((cell, i) => /* @__PURE__ */ React2.createElement(Box2, { key: i, flexBasis: `${colPercentage}%`, flexGrow: 1, flexShrink: 0, paddingRight: 2 }, /* @__PURE__ */ React2.createElement(InlineMarkdown, { text: cell, color: "cyan" })))), data.map((row, ri) => /* @__PURE__ */ React2.createElement(Box2, { key: ri, flexDirection: "row", marginBottom: ri === data.length - 1 ? 0 : 1, width: "100%" }, row.map((cell, ci) => /* @__PURE__ */ React2.createElement(Box2, { key: ci, flexBasis: `${colPercentage}%`, flexGrow: 1, flexShrink: 0, paddingRight: 2, flexDirection: "column" }, /* @__PURE__ */ React2.createElement(InlineMarkdown, { text: cell, color: "white" }))))));
114
113
  });
115
114
  MarkdownText = React2.memo(({ text, color = "white", columns = 80 }) => {
116
115
  if (!text) return null;
@@ -171,7 +170,7 @@ var init_ChatLayout = __esm({
171
170
  }
172
171
  });
173
172
  flushBuffers("final");
174
- return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, result);
173
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: columns - 2 }, result);
175
174
  });
176
175
  DiffLine = React2.memo(({ line }) => {
177
176
  const isContext = line.includes("[UI_CONTEXT]");
@@ -262,7 +261,7 @@ var init_ChatLayout = __esm({
262
261
  }
263
262
  return content;
264
263
  }, [content, msg.role, showFullThinking]);
265
- return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, flexDirection: "column", flexShrink: 0, width: "100%" }, msg.role === "user" ? /* @__PURE__ */ React2.createElement(
264
+ return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, flexDirection: "column", flexShrink: 0, width: "100%", flexGrow: 1 }, msg.role === "user" ? /* @__PURE__ */ React2.createElement(
266
265
  Box2,
267
266
  {
268
267
  backgroundColor: "#262626",
@@ -577,7 +576,8 @@ ${isMemoryEnabled ? `2. User-specific long-term memory (USE BASED ON CONVERSATIO
577
576
  - Update: tool:functions.memory(action='user', method='update', content-new='string to update', content-old='exact memory id')
578
577
 
579
578
  Usage Rules:
580
- - Frequency for 'user' action: Only when explicit context from chat is found or explicitly requested by the user.` : ""}
579
+ - Frequency for 'user' action: Only when explicit context from chat is found or explicitly requested by the user.
580
+ - IF YOU WANT TO SAVE SOMETHING, BUT SIMILAR MEMORY ALREADY EXISTS, USE THE UPDATE METHOD NOT THE ADD METHOD` : ""}
581
581
  -- END MEMORY TOOLS --`.trim();
582
582
  }
583
583
  });
@@ -2487,11 +2487,30 @@ Check what's new using \`/changelog\` command.`,
2487
2487
  setTempKey("");
2488
2488
  }
2489
2489
  };
2490
- const COMMANDS = ["/quit", "/help", "/clear", "/resume", "/save", "/chats", "/mode", "/thinking", "/model", "/settings", "/key", "/profile", "/memory", "/stats", "/reset", "/about", "/changelog", "/update"];
2490
+ const COMMANDS = [
2491
+ { cmd: "/quit", desc: "Exit and shutdown Flux" },
2492
+ { cmd: "/help", desc: "Show all available commands" },
2493
+ { cmd: "/clear", desc: "Clear terminal screen" },
2494
+ { cmd: "/resume", desc: "Load previous session" },
2495
+ { cmd: "/save", desc: "Force save current chat" },
2496
+ { cmd: "/chats", desc: "List all chat sessions" },
2497
+ { cmd: "/mode", desc: "Toggle Flux/Flow modes" },
2498
+ { cmd: "/thinking", desc: "Set AI reasoning depth" },
2499
+ { cmd: "/model", desc: "Switch AI brain model" },
2500
+ { cmd: "/settings", desc: "Configure system prefs" },
2501
+ { cmd: "/key", desc: "Manage API keys" },
2502
+ { cmd: "/profile", desc: "Edit developer persona" },
2503
+ { cmd: "/memory", desc: "Manage agent memory" },
2504
+ { cmd: "/stats", desc: "Show session usage" },
2505
+ { cmd: "/reset", desc: "Wipe all project data" },
2506
+ { cmd: "/about", desc: "Project info & credits" },
2507
+ { cmd: "/changelog", desc: "View latest updates" },
2508
+ { cmd: "/update", desc: "Check/Install updates" }
2509
+ ];
2491
2510
  const handleSubmit = (value) => {
2492
2511
  if (suggestions.length > 0) {
2493
- const nextCmd = suggestions[selectedIndex] || suggestions[0];
2494
- setInput(nextCmd + " ");
2512
+ const nextMatch = suggestions[selectedIndex] || suggestions[0];
2513
+ setInput(nextMatch.cmd + " ");
2495
2514
  setSelectedIndex(0);
2496
2515
  return;
2497
2516
  }
@@ -3005,7 +3024,7 @@ Selection: ${val}`,
3005
3024
  };
3006
3025
  const suggestions = useMemo(() => {
3007
3026
  if (!input.startsWith("/") || input.includes(" ")) return [];
3008
- return COMMANDS.filter((c) => c.startsWith(input.toLowerCase()));
3027
+ return COMMANDS.filter((c) => c.cmd.startsWith(input.toLowerCase()));
3009
3028
  }, [input]);
3010
3029
  useEffect4(() => {
3011
3030
  setSelectedIndex(0);
@@ -3059,7 +3078,7 @@ Selection: ${val}`,
3059
3078
  CommandMenu,
3060
3079
  {
3061
3080
  title: "\u{1F916} Select AI Model",
3062
- items: [{ label: "Gemma 4 31B (Default)", value: "gemma-4-31b-it" }, { label: "Gemini 3.1 Pro (Req. paid API Key)", value: "gemini-3.1-pro-preview" }, { label: "Gemini 3 Flash", value: "gemini-3-flash-preview" }, { label: "Gemini 3.1 Flash Lite", value: "gemini-3.1-flash-lite-preview" }, { label: "Cancel", value: "Cancel" }],
3081
+ items: [{ label: "Gemma 4 31B (Recomended - Default)", value: "gemma-4-31b-it" }, { label: "Gemini 3.1 Pro (Recomended - Req. paid API Key)", value: "gemini-3.1-pro-preview" }, { label: "Gemini 3 Flash (Paid API Key Recomended)", value: "gemini-3-flash-preview" }, { label: "Gemini 3.1 Flash Lite (Fastest - For Quick Tasks ONLY)", value: "gemini-3.1-flash-lite-preview" }, { label: "Cancel", value: "Cancel" }],
3063
3082
  onSelect: (item) => {
3064
3083
  if (item.value !== "Cancel") setActiveModel(item.value);
3065
3084
  setActiveView("chat");
@@ -3546,7 +3565,7 @@ Selection: ${val}`,
3546
3565
  )))))));
3547
3566
  }
3548
3567
  };
3549
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%" }, windowedHistory.isTruncated && /* @__PURE__ */ React10.createElement(Box10, { borderStyle: "single", borderColor: "gray", paddingX: 1, marginBottom: 1, width: "100%", justifyContent: "center" }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, "[ \u2191 History truncated for performance (showing last ~1000 lines) ]")), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, windowedHistory.items.map((msg, idx) => /* @__PURE__ */ React10.createElement(MessageItem, { key: msg.id || idx, msg, showFullThinking }))), /* @__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(
3568
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%" }, windowedHistory.isTruncated && /* @__PURE__ */ React10.createElement(Box10, { borderStyle: "single", borderColor: "gray", paddingX: 1, marginBottom: 1, width: "100%", justifyContent: "center" }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, "[ \u2191 History truncated for performance (showing last ~1000 lines) ]")), /* @__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(
3550
3569
  ChatLayout_default,
3551
3570
  {
3552
3571
  messages: messages.slice(completedIndex),
@@ -3571,7 +3590,33 @@ Selection: ${val}`,
3571
3590
  chatId,
3572
3591
  isMemoryEnabled: systemSettings.memory
3573
3592
  }
3574
- ))), suggestions.length > 0 && /* @__PURE__ */ React10.createElement(Box10, { position: "absolute", bottom: 9, left: 4, flexDirection: "column", backgroundColor: "#222", borderStyle: "round", borderColor: "yellow", paddingX: 1, paddingY: 0, zIndex: 999 }, suggestions.slice(0, 15).map((s, i) => /* @__PURE__ */ React10.createElement(Box10, { key: s, flexDirection: "row" }, /* @__PURE__ */ React10.createElement(Text10, { color: i === selectedIndex ? "cyan" : "gray" }, i === selectedIndex ? "\u276F " : " "), /* @__PURE__ */ React10.createElement(Text10, { color: i === selectedIndex ? "yellow" : "gray", bold: i === selectedIndex }, s))), suggestions.length > 15 && /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true }, " ... (", suggestions.length - 15, " more)")));
3593
+ )), suggestions.length > 0 && (() => {
3594
+ const windowSize = 5;
3595
+ const startIdx = Math.max(0, Math.min(selectedIndex - 2, suggestions.length - windowSize));
3596
+ const visible = suggestions.slice(startIdx, startIdx + windowSize);
3597
+ const remaining = suggestions.length - (startIdx + visible.length);
3598
+ return /* @__PURE__ */ React10.createElement(
3599
+ Box10,
3600
+ {
3601
+ flexDirection: "column",
3602
+ backgroundColor: "#222",
3603
+ borderStyle: "round",
3604
+ borderColor: "yellow",
3605
+ paddingX: 1,
3606
+ paddingY: 0,
3607
+ marginTop: 0,
3608
+ width: "100%",
3609
+ minHeight: suggestions.length >= 5 ? 7 : 0
3610
+ },
3611
+ visible.map((s, i) => {
3612
+ const actualIdx = startIdx + i;
3613
+ const isActive = actualIdx === selectedIndex;
3614
+ const cmdText = s.cmd.padEnd(12);
3615
+ return /* @__PURE__ */ React10.createElement(Box10, { key: s.cmd, flexDirection: "row" }, /* @__PURE__ */ React10.createElement(Text10, { color: isActive ? "cyan" : "gray" }, isActive ? "\u276F " : " "), /* @__PURE__ */ React10.createElement(Text10, { color: isActive ? "yellow" : "gray", bold: isActive }, cmdText), /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, s.desc));
3616
+ }),
3617
+ suggestions.length > 5 && /* @__PURE__ */ React10.createElement(Box10, { height: 1 }, remaining > 0 && /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true }, " ... (", remaining, " more)"))
3618
+ );
3619
+ })()));
3575
3620
  }
3576
3621
  var SESSION_START_TIME, CHANGELOG_URL, versionFluxflow, updatedOn, ResolutionModal, FLUX_LOGO;
3577
3622
  var init_app = __esm({
@@ -3595,8 +3640,8 @@ var init_app = __esm({
3595
3640
  init_terminal();
3596
3641
  SESSION_START_TIME = Date.now();
3597
3642
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
3598
- versionFluxflow = "1.3.2";
3599
- updatedOn = "2026-04-28";
3643
+ versionFluxflow = "1.3.3";
3644
+ updatedOn = "2026-04-29";
3600
3645
  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 (turn: finish) 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(
3601
3646
  CommandMenu,
3602
3647
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",