fluxflow-cli 1.0.0 โ†’ 1.0.2

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.
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # ๐ŸŒŒ Flux Flow (`fluxflow-cli`)
2
- ![Flux Flow Logo](./fluxflow.png)
2
+ ![Flux Flow Logo](https://github.com/KushalRoyChowdhury/fluxflow-cli/blob/main/fluxflow.png)
3
3
 
4
4
  ### *The High-Fidelity Agentic Terminal for the Flux Era.*
5
5
 
6
- **Flux Flow** is not just another CLIโ€”it's a high-speed, sassy, and goal-oriented Terminal AI Agent powered by the latest Gemini frontier models. Designed for developers who demand a premium UI/UX while managing complex file-system tasks, web research, and autonomous workflows.
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 frontier models. Designed for developers who demand a premium UI/UX while managing complex file-system tasks, web research, and autonomous workflows.
7
7
 
8
8
  ---
9
9
 
package/TOOLS.md ADDED
@@ -0,0 +1,48 @@
1
+ # ๐Ÿงฐ Agent Tools & Capabilities
2
+
3
+ Flux Flow provides a robust set of tools that allow the AI to interact with the file system, execute code, and search the web. The availability of these tools depends on the active operating mode.
4
+
5
+ ## Tool Availability by Mode
6
+
7
+ | Tool | Flux Mode (Dev) | Flow Mode (Chat) |
8
+ | :--- | :---: | :---: |
9
+ | **Web Search** | โœ… | โœ… |
10
+ | **Web Scrape** | โœ… | โœ… |
11
+ | **View/Read Files** | โœ… | โŒ |
12
+ | **Write/Update Files** | โœ… | โŒ |
13
+ | **Execute Commands** | โœ… | โŒ |
14
+
15
+ ---
16
+
17
+ ## Core Tools
18
+
19
+ ### ๐ŸŒ Web & Research
20
+ - **`web_search`**: Uses DuckDuckGo to find up-to-date information on the internet. Crucial for answering questions about recent events or unlearned documentation.
21
+ - **`web_scrape`**: Extracts the detailed text content from a specific URL, allowing the agent to read documentation or articles.
22
+
23
+ ### ๐Ÿ“ File System Operations
24
+ - **`list_files`**: Lists the contents of a directory to help the agent understand the project structure.
25
+ - **`read_folder`**: Provides detailed statistics and metadata about a directory's contents.
26
+ - **`view_file`**: Reads the content of a file. Supports reading specific line ranges (`start_line`, `end_line`) to manage context size efficiently.
27
+
28
+ ### โœ๏ธ Code Editing
29
+ - **`write_file`**: Creates a new file or completely overwrites an existing one with new content.
30
+ - **`update_file` (Smart Patching)**: Surgically replaces a specific block of text within a file.
31
+ - *Diff Generation*: It returns a high-fidelity visual diff (Red/Green changes with context lines) to the UI, allowing the user to see exactly what the agent modified.
32
+
33
+ ### ๐Ÿ’ป Terminal Execution
34
+ - **`exec_command`**: Runs a shell command directly in the terminal using Node's `child_process.spawn`.
35
+ - *Context Aware*: Runs in the current working directory.
36
+ - *Cross-Platform*: Uses `shell: true` to handle Windows `.cmd`/`.bat` files natively.
37
+
38
+ ---
39
+
40
+ ## Memory Management
41
+
42
+ The memory tool (`memory.js`) is primarily used by the background **Janitor** model, but can be accessed by the main agent if necessary.
43
+
44
+ - **Temporary Context (`action='temp'`)**: Saves a rolling summary of the current session to maintain conversational context without bloating the main prompt history.
45
+ - **Persistent User Memory (`action='user'`)**:
46
+ - The Janitor analyzes conversations to detect user preferences, hobbies, or instructions.
47
+ - It uses `add`, `update`, or `delete` methods to manage facts in the encrypted `memories.json` vault.
48
+ - These memories are injected into the system prompt of *future* sessions, allowing Flux Flow to learn and adapt to the user over time.
package/UI_FEATURES.md ADDED
@@ -0,0 +1,66 @@
1
+ # ๐ŸŽฎ User Interface & Interaction Features
2
+
3
+ Flux Flow is designed to be a high-performance terminal application. Beyond basic chat, it includes a variety of advanced UI features and human-in-the-loop controls to keep you in command of the agent.
4
+
5
+ ## โŒจ๏ธ Command System
6
+
7
+ You can control the application using `/` commands directly in the chat input:
8
+
9
+ - **/mode [flux|flow]**: Quickly switch between **Flux** (Dev) and **Flow** (Chat) modes. Using it without arguments opens the selection menu.
10
+ - **/thinking [low|medium|high|max|show|hide]**: Adjust reasoning depth or toggle visibility of the thinking process. Using it without arguments opens the selection menu.
11
+ - **/model [name]**: Choose which AI model to use for the main interaction.
12
+ - **/key**: Open the API Key management view to update or remove your credentials.
13
+ - **/settings**: Access the system configuration menu.
14
+ - **/profile**: Update your name, nickname, and custom instructions.
15
+ - **/memory**: View and manage the persistent memories extracted by the Janitor.
16
+ - **/resume <chat-id>**: Switch back to a previous conversation.
17
+ - **/help**: List all available commands.
18
+
19
+ ### Command Shortcuts
20
+
21
+ For power users, several commands support direct arguments to skip the menus:
22
+ - ` /mode flux ` or ` /mode flow `
23
+ - ` /thinking low ` / ` /thinking medium ` / ` /thinking high ` / ` /thinking max `
24
+ - ` /thinking show ` / ` /thinking hide ` (Toggles thinking process visibility)
25
+ - ` /model gemini-3.1-pro-preview ` (Switches model directly)
26
+
27
+ ## ๐Ÿง  Thinking Levels & Visualization
28
+
29
+ Flux Flow separates the model's "internal monologue" (reasoning) from its final response using `<think>` tags.
30
+
31
+ - **Thinking Levels**: Depending on the mode, you can choose from **Low**, **Medium**, **High**, or **Max**. Higher levels allow the agent more "space" to reason through complex architecture or debugging problems.
32
+ - **Show/Hide Thinking**: You can toggle the visibility of the thinking process using `/thinking show/hide`.
33
+ - When **Hidden**, the agent doesn't just disappear; it provides a "minimalist" view showing only the core **Headings** and **Action Steps** (bolded lines) from its reasoning. This keeps you informed of its current "step" without cluttering the screen with detailed internal monologue.
34
+
35
+ ## ๐Ÿ›ก๏ธ Human-in-the-Loop (HITL) Verification
36
+
37
+ Security and safety are paramount when an AI has access to your file system and terminal. Flux Flow implements several layers of verification:
38
+
39
+ ### Tool Approval
40
+ By default, the agent **cannot** execute dangerous actions without your consent.
41
+ - **Terminal Approval**: If the agent attempts to run a shell command (`exec_command`), a dedicated approval screen appears showing the exact command. You can **Allow** or **Deny** the execution.
42
+ - **File Approval**: Similar to terminal commands, writing or updating files requires manual approval unless configured otherwise.
43
+ - **Safe Commands**: Basic read-only commands (like `ls`, `git status`, `pwd`) are automatically allowed to minimize friction.
44
+
45
+ ### Auto-Execution (Advanced)
46
+ For power users, **Auto-Exec** can be enabled in `/settings`.
47
+ - **โš ๏ธ Warning**: This allows the agent to run any tool and execute any command autonomously.
48
+ - **External Access**: You can also toggle whether the agent is allowed to access files outside of its current working directory.
49
+
50
+ ## ๐Ÿ”„ Steering & Resolution
51
+
52
+ ### Real-time Steering
53
+ If you realize the agent is going down the wrong path *while* it is in an agentic loop, you can provide "Steering Hints." The system will inject your feedback into the next loop to course-correct the agent.
54
+
55
+ ### Resolution Modal
56
+ If the agent finishes its task just as you send a steering hint, a **Resolution Modal** appears. It asks if you want to:
57
+ - **Send Anyway**: Start a new loop with your feedback.
58
+ - **Edit Prompt**: Refine your feedback before sending.
59
+
60
+ ## ๐Ÿ“Š Status Bar & Feedback
61
+ The bottom of the screen features a dynamic status bar showing:
62
+ - **Active Mode** (Flux/Flow)
63
+ - **Thinking Level**
64
+ - **Token Usage**: Real-time tracking of tokens used in the current session.
65
+ - **Agentic Loops**: Counters showing how many times the agent has "looped" to solve the current task.
66
+ - **API Status**: Visual feedback when the model is thinking or executing a tool.
@@ -7,6 +7,9 @@ import { render } from "ink";
7
7
  // src/app.jsx
8
8
  import React8, { useState as useState4, useEffect as useEffect3, useRef, useMemo } from "react";
9
9
  import { Box as Box8, Text as Text8, useInput as useInput3, useStdout, Static } from "ink";
10
+ import fs14 from "fs-extra";
11
+ import path16 from "path";
12
+ import { fileURLToPath as fileURLToPath9 } from "url";
10
13
  import { MultilineInput } from "ink-multiline-input";
11
14
  import TextInput2 from "ink-text-input";
12
15
 
@@ -191,7 +194,7 @@ function StatusBar({ mode, thinkingLevel, tokens = "0.0k", chatId = "NEW-SESSION
191
194
  },
192
195
  /* @__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)),
193
196
  /* @__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 }, process.cwd())),
194
- /* @__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" }, " Tokens ", tokens > 1e3 ? `${(tokens / 1e3).toFixed(1)}k` : tokens, " (", Math.round(tokens / 128e3 * 100), "%)"), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "dim" }, "ID: ", chatId, " "))
197
+ /* @__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" }, " Tokens ", tokens > 1e3 ? `${(tokens / 1e3).toFixed(1)}k` : tokens, " (", Math.round(tokens / 196e3 * 100), "%)"), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "dim" }, "ID: ", chatId, " "))
195
198
  );
196
199
  }
197
200
 
@@ -792,7 +795,7 @@ var memory = async (rawArgs, context = {}) => {
792
795
  if (!content) return "ERROR: Missing 'content' for temp memory.";
793
796
  const tempStorage = readEncryptedJson(TEMP_MEM_PATH, {});
794
797
  if (!tempStorage[chatId]) tempStorage[chatId] = [];
795
- const MAX_CHARS = 4e3 * 4;
798
+ const MAX_CHARS = 3e3 * 4;
796
799
  let currentTotalLength = tempStorage[chatId].reduce((acc, m) => acc + m.length, 0);
797
800
  while (tempStorage[chatId].length > 0 && currentTotalLength + content.length > MAX_CHARS) {
798
801
  const removed = tempStorage[chatId].shift();
@@ -806,7 +809,7 @@ var memory = async (rawArgs, context = {}) => {
806
809
  const memories = readEncryptedJson(MEMORIES_PATH, []);
807
810
  if (method === "add") {
808
811
  if (!content) return "ERROR: Missing 'content' for memory addition.";
809
- const MAX_CHARS = 3e3 * 4;
812
+ const MAX_CHARS = 2e3 * 4;
810
813
  let currentTotalLength = memories.reduce((acc, m) => acc + (m.memory?.length || 0), 0);
811
814
  while (memories.length > 0 && currentTotalLength + content.length > MAX_CHARS) {
812
815
  const removed = memories.shift();
@@ -1282,7 +1285,7 @@ var getAIStream = async function* (modelName, history, settings, steeringCallbac
1282
1285
  const needTitle = isFirstPrompt || hasTitleSignal;
1283
1286
  const agentText = originalText.replace(/\[TITLE-UPDATE\]/g, "").trim();
1284
1287
  let modifiedHistory = [...history.slice(0, -1)];
1285
- if (systemSettings?.compression === 0 && (sessionStats?.tokens || 0) > 128e3) {
1288
+ if (systemSettings?.compression === 0 && (sessionStats?.tokens || 0) > 196e3) {
1286
1289
  modifiedHistory = getTruncatedHistory(modifiedHistory, 4);
1287
1290
  }
1288
1291
  const tempStorage = readEncryptedJson(TEMP_MEM_PATH2, {});
@@ -1391,7 +1394,17 @@ USER_PROMPT: ${agentText}`.trim();
1391
1394
  const url = parseArgs(toolCall.args).url || "...";
1392
1395
  label = `\u{1F4D6} READING SITE: ${url}`.toUpperCase();
1393
1396
  } else if (toolCall.toolName === "view_file") {
1394
- label = `\u{1F4C4} READING FILE: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
1397
+ const { path: targetPath2, start_line = 1, end_line = 500 } = parseArgs(toolCall.args);
1398
+ let totalLines = "...";
1399
+ try {
1400
+ const absPath = path13.resolve(process.cwd(), targetPath2);
1401
+ if (fs12.existsSync(absPath)) {
1402
+ const content = fs12.readFileSync(absPath, "utf8");
1403
+ totalLines = content.split("\n").length;
1404
+ }
1405
+ } catch (e) {
1406
+ }
1407
+ label = `\u{1F4C4} READING FILE: ${targetPath2}. LINES ${start_line} - ${end_line} FROM ${totalLines}`.toUpperCase();
1395
1408
  } else if (toolCall.toolName === "list_files" || toolCall.toolName === "read_folder") {
1396
1409
  const action = toolCall.toolName === "list_files" ? "LISTING" : "DISCOVERING";
1397
1410
  label = `\u{1F4C2} ${action} DIRECTORY: ${parseArgs(toolCall.args).path || "."}`.toUpperCase();
@@ -1910,7 +1923,7 @@ function App() {
1910
1923
  setTempKey("");
1911
1924
  }
1912
1925
  };
1913
- const COMMANDS = ["/mode", "/thinking", "/model", "/resume", "/memory", "/profile", "/settings", "/key", "/stats", "/help", "/clear", "/quit"];
1926
+ const COMMANDS = ["/mode", "/thinking", "/model", "/resume", "/memory", "/profile", "/settings", "/key", "/stats", "/reset", "/help", "/clear", "/quit"];
1914
1927
  const handleSubmit = (value) => {
1915
1928
  const normalizedValue = value.replace(/\r\n/g, "\n").replace(/\r/g, "\n").trimEnd();
1916
1929
  if (normalizedValue.endsWith("\\")) {
@@ -2081,6 +2094,34 @@ ${list || "No saved chats found."}` }];
2081
2094
  setActiveView("memory");
2082
2095
  break;
2083
2096
  }
2097
+ case "/reset": {
2098
+ const runReset = async () => {
2099
+ const AGENT_ROOT7 = path16.join(path16.dirname(fileURLToPath9(import.meta.url)), "../");
2100
+ const logsDir = path16.join(AGENT_ROOT7, "logs");
2101
+ const secretDir = path16.join(AGENT_ROOT7, "secret");
2102
+ const settingsFile = path16.join(AGENT_ROOT7, "settings.json");
2103
+ try {
2104
+ setMessages((prev) => {
2105
+ setCompletedIndex(prev.length + 1);
2106
+ return [...prev, { id: Date.now(), role: "system", text: "\u2622\uFE0F [NUCLEAR] Initiating reset..." }];
2107
+ });
2108
+ if (fs14.existsSync(logsDir)) fs14.removeSync(logsDir);
2109
+ if (fs14.existsSync(secretDir)) fs14.removeSync(secretDir);
2110
+ if (fs14.existsSync(settingsFile)) fs14.removeSync(settingsFile);
2111
+ setTimeout(() => {
2112
+ setActiveView("exit");
2113
+ setTimeout(() => process.exit(0), 500);
2114
+ }, 500);
2115
+ } catch (err) {
2116
+ setMessages((prev) => {
2117
+ setCompletedIndex(prev.length + 1);
2118
+ return [...prev, { id: Date.now(), role: "system", text: `\u274C [RESET ERROR] Failed to purge data: ${err.message}` }];
2119
+ });
2120
+ }
2121
+ };
2122
+ runReset();
2123
+ break;
2124
+ }
2084
2125
  case "/help": {
2085
2126
  setMessages((prev) => {
2086
2127
  setCompletedIndex(prev.length + 1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",
@@ -12,20 +12,29 @@
12
12
  "flux"
13
13
  ],
14
14
  "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/KushalRoyChowdhury/fluxflow-cli.git"
18
+ },
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
15
22
  "files": [
16
23
  "dist",
17
24
  "README.md",
18
25
  "package.json",
19
26
  "ARCHITECTURE.md",
20
- "fluxflow.png"
27
+ "TOOLS.md",
28
+ "UI_FEATURES.md"
21
29
  ],
22
30
  "type": "module",
23
31
  "bin": {
24
- "fluxflow-cli": "dist/index.js"
32
+ "fluxflow-cli": "dist/fluxflow.js",
33
+ "fluxflow": "dist/fluxflow.js"
25
34
  },
26
35
  "scripts": {
27
36
  "start": "tsx ./src/cli.jsx",
28
- "build": "esbuild ./src/cli.jsx --bundle --platform=node --format=esm --outfile=./dist/index.js --external:react --external:ink --external:chalk --external:fs-extra --external:gradient-string --external:ink-text-input --external:ink-select-input --external:ink-spinner --external:ink-multiline-input --external:@google/genai --external:zod --external:duck-duck-scrape --external:nanoid --external:cuimp"
37
+ "build": "esbuild ./src/cli.jsx --bundle --platform=node --format=esm --outfile=./dist/fluxflow.js --external:react --external:ink --external:chalk --external:fs-extra --external:gradient-string --external:ink-text-input --external:ink-select-input --external:ink-spinner --external:ink-multiline-input --external:@google/genai --external:zod --external:duck-duck-scrape --external:nanoid --external:cuimp"
29
38
  },
30
39
  "dependencies": {
31
40
  "@google/genai": "^1.50.1",
package/fluxflow.png DELETED
Binary file