fluxflow-cli 1.9.0 → 1.9.1

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 +119 -97
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -136,12 +136,26 @@ var init_terminal = __esm({
136
136
  // src/components/ChatLayout.jsx
137
137
  import React2, { useState, useEffect, useRef } from "react";
138
138
  import { Box as Box2, Text as Text2 } from "ink";
139
- var cleanSignals, formatThinkText, parseMathSymbols, InlineMarkdown, TableRenderer, MarkdownText, DiffLine, DiffBlock, CodeRenderer, MessageItem, ChatLayout, ChatLayout_default;
139
+ var TOOL_LABELS, cleanSignals, formatThinkText, parseMathSymbols, InlineMarkdown, TableRenderer, MarkdownText, DiffLine, DiffBlock, CodeRenderer, MessageItem, ChatLayout, ChatLayout_default;
140
140
  var init_ChatLayout = __esm({
141
141
  "src/components/ChatLayout.jsx"() {
142
142
  init_TerminalBox();
143
143
  init_text();
144
144
  init_terminal();
145
+ TOOL_LABELS = {
146
+ "write_file": "Write File",
147
+ "update_file": "Update File",
148
+ "read_folder": "Read Folder",
149
+ "view_file": "View File",
150
+ "exec_command": "Execute Command",
151
+ "web_search": "Web Search",
152
+ "web_scrape": "Read Site",
153
+ "search_keyword": "Find Files",
154
+ "ask": "Ask User",
155
+ "write_pdf": "Create PDF",
156
+ "write_pptx": "Create Presentation",
157
+ "write_docx": "Create Document"
158
+ };
145
159
  cleanSignals = (text) => {
146
160
  if (!text) return text;
147
161
  let result = text;
@@ -196,7 +210,7 @@ var init_ChatLayout = __esm({
196
210
  }
197
211
  }
198
212
  }
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();
213
+ 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*:?.*?$/gi, "").replace(/\n\s*turn\s*:?.*?$/gi, "").replace(/\[\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").replace(/@\[TerminalName:.*?, ProcessId:.*?\]/gi, "").replace(/\b(write_file|update_file|read_folder|view_file|exec_command|web_search|web_scrape|search_keyword|ask|write_pdf|write_pptx|write_docx)\b/gi, (match) => TOOL_LABELS[match.toLowerCase()] || match).trim();
200
214
  };
201
215
  formatThinkText = (cleaned, columns = 80) => {
202
216
  if (!cleaned) return null;
@@ -835,7 +849,7 @@ var init_main_tools = __esm({
835
849
 
836
850
  - USER COMMUNICATION TOOLS (Available in Flux & Flow) -
837
851
  1. Ask User: [tool:functions.ask(question="...", optionA="Option::Desc", optionB="Option::Desc")]. Generally use this tool for ANY ambiguity. Can use upto 4 arguments. Mandatory triggers include: 1) **Path Divergence**: When multiple architectural or technical solutions exist, present options via 'ask' instead of choosing arbitrarily. 2) **Security Boundaries**: Explicitly request permission via 'ask' before accessing sensitive files (e.g., .env, config keys, credentials). 3) **Ambiguity Resolution**: Use 'ask' to clarify vague prompts before executing terminal commands or writing code. 4) **Risk Mitigation**: Require a 'Yes/No' confirmation for any destructive or irreversible operations. Options must always follow the 'Short Label::Detailed Description' format. This tool is a non-terminating suspension so you can get guidance without losing context. PREFER USING THIS TOOL RATHER THAN FINISHING THE LOOP FOR USER CLARIFICATION.
838
- DO NOT GIVE OPTION TO ASK USER THEIR PREFERENCES. JUST GIVE THE OPTIONS YOU THINK ARE BEST FOR THE USER.
852
+ DO NOT GIVE OPTION TO ASK USER THEIR PREFERENCES. JUST GIVE THE OPTIONS YOU THINK ARE BEST FOR THE USER. REST WILL BE HANDLED BY THE SYSTEM.
839
853
 
840
854
  - WEB TOOLS (Available in Flux & Flow) -
841
855
  1. Web Search: [tool:functions.web_search(query="<query>", limit=number)]. Find info. limit is optional (3-10, default 10). If user asks about something that is not in your training data, proactively use this tool to find the information. Wider search recomemded (limit = 10) when exploring a topic.
@@ -961,14 +975,14 @@ var init_prompts = __esm({
961
975
  const dateTimeStr = (/* @__PURE__ */ new Date()).toLocaleString();
962
976
  const cwdStr = process.cwd();
963
977
  const tempMemoriesStr = tempMemories?.length > 0 && !isContext32k ? `
964
- -- RECENT CONTEXT FROM OTHER CHAT THREADS (LOW PRIORITY) --
978
+ -- RECENT CONTEXT FROM OTHER CHAT THREADS (PRIORITY: LOW, RECENT > OLD) --
965
979
  ${tempMemories.split("\n").map((line) => ` ${line}`).join("\n")}
966
980
  -- END RECENT CONTEXT --
967
981
  ` : "";
968
982
  const userMemoriesStr = userMemories?.length > 0 ? `
969
- --- PERSISTENT USER MEMORIES (MEDIUM PRIORITY, TUNES PERSONALIZATION & USER PREFERENCES) ---
983
+ --- SAVED MEMORIES (PRIORITY: MEDIUM, TUNES PERSONALIZATION & USER PREFERENCES) ---
970
984
  ${userMemories.split("\n").map((line) => ` ${line}`).join("\n")}
971
- -- END USER MEMORIES --
985
+ -- END SAVED MEMORIES --
972
986
  ` : "";
973
987
  return `${isMemoryEnabled ? `${userMemoriesStr}
974
988
  ` : ""}${isMemoryEnabled ? `${tempMemoriesStr}
@@ -1654,7 +1668,7 @@ var init_memory = __esm({
1654
1668
  if (!content) return "ERROR: Missing 'content' for temp memory.";
1655
1669
  const tempStorage = readEncryptedJson(TEMP_MEM_FILE, {});
1656
1670
  if (!tempStorage[chatId]) tempStorage[chatId] = [];
1657
- const MAX_CHARS = 2e3 * 4;
1671
+ const MAX_CHARS = 3072 * 4;
1658
1672
  let currentTotalLength = tempStorage[chatId].reduce((acc, m) => acc + m.length, 0);
1659
1673
  while (tempStorage[chatId].length > 0 && currentTotalLength + content.length > MAX_CHARS) {
1660
1674
  const removed = tempStorage[chatId].shift();
@@ -1668,7 +1682,7 @@ var init_memory = __esm({
1668
1682
  const memories = readEncryptedJson(MEMORIES_FILE, []);
1669
1683
  if (method === "add") {
1670
1684
  if (!content) return "ERROR: Missing 'content' for memory addition.";
1671
- const MAX_CHARS = 2e3 * 4;
1685
+ const MAX_CHARS = 2048 * 4;
1672
1686
  let currentTotalLength = memories.reduce((acc, m) => acc + (m.memory?.length || 0), 0);
1673
1687
  while (memories.length > 0 && currentTotalLength + content.length > MAX_CHARS) {
1674
1688
  const removed = memories.shift();
@@ -1845,7 +1859,7 @@ var init_view_file = __esm({
1845
1859
  const start = Math.max(0, finalStart - 1);
1846
1860
  const end = Math.min(totalLines, finalEnd);
1847
1861
  const resultLines = lines.slice(start, end);
1848
- const header = `File: [${targetPath}] (Showing lines ${start + 1}-${end} of ${totalLines})`;
1862
+ const header = `File: [${targetPath}] (Showing lines ${start + 1}-${end} of ${totalLines}). \\\\n in strings are encoded as [/n].`;
1849
1863
  const code = resultLines.map((line, i) => `${String(start + i + 1).padStart(4)}: ${line}`).join("\n");
1850
1864
  return `${header}
1851
1865
 
@@ -2595,7 +2609,7 @@ var init_tools = __esm({
2595
2609
  import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
2596
2610
  import path16 from "path";
2597
2611
  import fs16 from "fs";
2598
- var client, TERMINATION_SIGNAL, signalTermination, TOOL_LABELS, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, getAIStream;
2612
+ var client, TERMINATION_SIGNAL, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, getAIStream;
2599
2613
  var init_ai = __esm({
2600
2614
  "src/utils/ai.js"() {
2601
2615
  init_prompts();
@@ -2611,7 +2625,7 @@ var init_ai = __esm({
2611
2625
  signalTermination = () => {
2612
2626
  TERMINATION_SIGNAL = true;
2613
2627
  };
2614
- TOOL_LABELS = {
2628
+ TOOL_LABELS2 = {
2615
2629
  "write_file": "Writing File",
2616
2630
  "update_file": "Updating File",
2617
2631
  "read_folder": "Listing Directory",
@@ -2621,7 +2635,10 @@ var init_ai = __esm({
2621
2635
  "web_scrape": "Reading Site",
2622
2636
  "memory": "Updating Memory",
2623
2637
  "search_keyword": "Finding Files",
2624
- "ask": "Asking User"
2638
+ "ask": "Asking User",
2639
+ "write_pdf": "Creating PDF",
2640
+ "write_pptx": "Creating Presentation",
2641
+ "write_docx": "Creating Document"
2625
2642
  };
2626
2643
  getToolDetail = (toolName, argsStr) => {
2627
2644
  try {
@@ -3138,17 +3155,23 @@ USER_PROMPT: "${agentText}"`.trim();
3138
3155
  const potentialTool = toolContext.toolName;
3139
3156
  const partialArgs = toolContext.args || "";
3140
3157
  let detail = null;
3141
- if (["write_file", "update_file", "view_file", "read_folder"].includes(potentialTool)) {
3158
+ if (["write_file", "update_file", "view_file", "read_folder", "write_pdf", "write_pptx", "write_docx", "search_keyword"].includes(potentialTool)) {
3142
3159
  const pArgs = parseArgs(partialArgs);
3143
3160
  const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
3144
- if (filePath) {
3161
+ const keyword = pArgs.keyword;
3162
+ if (keyword) {
3163
+ detail = keyword.replace(/[\\"]/g, "");
3164
+ } else if (filePath) {
3145
3165
  detail = path16.basename(filePath.replace(/[\\"]/g, ""));
3146
3166
  } else {
3147
- const m = partialArgs.match(/(?:path|targetFile|TargetFile|directory)\s*=\s*\\?["']?([^\\"' \),]+)/);
3148
- if (m) detail = path16.basename(m[1].replace(/[\\"]/g, ""));
3167
+ const m = partialArgs.match(/(?:path|targetFile|TargetFile|directory|keyword)\s*=\s*\\?["']?([^\\"' \),]+)/);
3168
+ if (m) {
3169
+ const val = m[1].replace(/[\\"]/g, "");
3170
+ detail = potentialTool === "search_keyword" ? val : path16.basename(val);
3171
+ }
3149
3172
  }
3150
3173
  }
3151
- const currentLabel = `${TOOL_LABELS[potentialTool] || potentialTool}${detail ? ` (${detail})` : ""}`;
3174
+ const currentLabel = `${TOOL_LABELS2[potentialTool] || potentialTool}${detail ? ` (${detail})` : ""}`;
3152
3175
  if (potentialTool !== lastToolSniffed || detail !== lastToolDetail) {
3153
3176
  lastToolSniffed = potentialTool;
3154
3177
  lastToolDetail = detail;
@@ -3212,16 +3235,16 @@ USER_PROMPT: "${agentText}"`.trim();
3212
3235
  const allToolsFound = detectToolCalls(toolActionableText);
3213
3236
  while (allToolsFound.length > toolCallPointer) {
3214
3237
  const toolCall = allToolsFound[toolCallPointer];
3215
- const displayLabel = TOOL_LABELS[toolCall.toolName] || toolCall.toolName;
3238
+ const displayLabel = TOOL_LABELS2[toolCall.toolName] || toolCall.toolName;
3216
3239
  const detail = getToolDetail(toolCall.toolName, toolCall.args);
3217
3240
  yield { type: "status", content: `${displayLabel}${detail ? ` (${detail})` : ""}...` };
3218
3241
  let label = "";
3219
3242
  if (toolCall.toolName === "web_search") {
3220
3243
  const { query, limit = 10 } = parseArgs(toolCall.args);
3221
- label = `\u{1F50D} SEARCHING: "${query}" (${limit})`.toUpperCase();
3244
+ label = `\u{1F50D} SEARCHED: "${query}" (${limit})`.toUpperCase();
3222
3245
  } else if (toolCall.toolName === "web_scrape") {
3223
3246
  const url = parseArgs(toolCall.args).url || "...";
3224
- label = `\u{1F4D6} READING SITE: ${url}`.toUpperCase();
3247
+ label = `\u{1F4D6} READ SITE: ${url}`.toUpperCase();
3225
3248
  } else if (toolCall.toolName === "view_file") {
3226
3249
  const { path: targetPath2, StartLine, EndLine, start_line, end_line } = parseArgs(toolCall.args);
3227
3250
  const rawStart = StartLine || start_line;
@@ -3244,31 +3267,31 @@ USER_PROMPT: "${agentText}"`.trim();
3244
3267
  const isPdf = pathLower.endsWith(".pdf");
3245
3268
  const isImage = /\.(png|jpg|jpeg|webp|gif|bmp)$/.test(pathLower);
3246
3269
  if (isPdf) {
3247
- label = `\u{1F4C4} ANALYZING PDF: ${targetPath2}`.toUpperCase();
3270
+ label = `\u{1F4C4} ANALYSED PDF: ${targetPath2}`.toUpperCase();
3248
3271
  } else if (isImage) {
3249
- label = `\u{1F4F8} ANALYZING IMAGE: ${targetPath2}`.toUpperCase();
3272
+ label = `\u{1F4F8} ANALYSED IMAGE: ${targetPath2}`.toUpperCase();
3250
3273
  } else {
3251
- label = `\u{1F4C4} READING FILE: ${targetPath2}. LINES ${sLine} - ${actualEndLine} FROM ${totalLines}`.toUpperCase();
3274
+ label = `\u{1F4C4} READ FILE: ${targetPath2} | LINES: ${sLine}-${actualEndLine} OF ${totalLines}`.toUpperCase();
3252
3275
  }
3253
3276
  } else if (toolCall.toolName === "list_files" || toolCall.toolName === "read_folder") {
3254
- const action = toolCall.toolName === "list_files" ? "LISTING" : "DISCOVERING";
3255
- label = `\u{1F4C2} ${action} DIRECTORY: ${parseArgs(toolCall.args).path || "."}`.toUpperCase();
3277
+ const action = toolCall.toolName === "list_files" ? "LIST" : "ANALYSED";
3278
+ label = `\u{1F4C2} ${action} FOLDER: ${parseArgs(toolCall.args).path || "."}`.toUpperCase();
3256
3279
  } else if (toolCall.toolName === "write_file" || toolCall.toolName === "update_file") {
3257
- const action = toolCall.toolName === "write_file" ? "WRITING" : "PATCHING";
3280
+ const action = toolCall.toolName === "write_file" ? "WROTE" : "UPDATED";
3258
3281
  label = `\u{1F4BE} ${action} FILE: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
3259
3282
  } else if (toolCall.toolName === "write_pdf") {
3260
- label = `\u{1F4D1} GENERATING PDF: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
3283
+ label = `\u{1F4D1} PDF CREATED: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
3261
3284
  } else if (toolCall.toolName === "write_docx") {
3262
- label = `\u{1F4DD} GENERATING DOCX: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
3285
+ label = `\u{1F4DD} DOCX CREATED: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
3263
3286
  } else if (toolCall.toolName === "write_pptx") {
3264
- label = `\u{1F4CA} GENERATING PPTX: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
3287
+ label = `\u{1F4CA} PPTX CREATED: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
3265
3288
  } else if (toolCall.toolName === "search_keyword") {
3266
3289
  const { keyword } = parseArgs(toolCall.args);
3267
- label = `\u{1F50E} SEARCHING KEYWORD: "${keyword}"`.toUpperCase();
3290
+ label = `\u{1F50E} KEYWORD SEARCHED: "${keyword}"`.toUpperCase();
3268
3291
  } else if (toolCall.toolName === "exec_command" || toolCall.toolName === "ask") {
3269
3292
  label = "";
3270
3293
  } else {
3271
- label = `EXECUTING ${toolCall.toolName}`.toUpperCase();
3294
+ label = `EXECUTED: ${toolCall.toolName}`.toUpperCase();
3272
3295
  }
3273
3296
  if (label) {
3274
3297
  const boxWidth = Math.min(label.length + 4, 115);
@@ -3498,7 +3521,7 @@ ${timestamp}`;
3498
3521
  if (toolResults.length > 0) {
3499
3522
  toolResults.forEach((tr) => modifiedHistory.push(tr));
3500
3523
  } else {
3501
- modifiedHistory.push({ role: "user", text: `[SYSTEM] ${isStutteringLoop && !isThinkingLoop ? `STUTTERING DETECTED by Internal System. Re-calibrate your response & proceed.` : `${isThinkingLoop ? " OVER-THINKING" : " LOOP"} DETECTED by Internal System${isThinkingLoop && " for current EFFORT_LEVEL"}. ${isThinkingLoop ? "If you have planned the task, prioritize the execution/output. " : "If you have finished your task use [turn: finish] else continue."}`}` });
3524
+ modifiedHistory.push({ role: "user", text: `[SYSTEM] ${isStutteringLoop && !isThinkingLoop ? `STUTTERING DETECTED by Internal System. Re-calibrate your response & proceed.` : `${isThinkingLoop ? " OVER-THINKING" : " LOOP"} DETECTED by Internal System${isThinkingLoop ? " for current EFFORT_LEVEL" : ""}. ${isThinkingLoop ? "If you have planned the task, prioritize the execution/output. " : "If you have finished your task use [turn: finish] else continue."}`}` });
3502
3525
  isThinkingLoop = false;
3503
3526
  isStutteringLoop = false;
3504
3527
  }
@@ -3630,15 +3653,39 @@ function ResumeModal({ onSelect, onDelete, onClose }) {
3630
3653
  });
3631
3654
  }
3632
3655
  });
3633
- return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", borderStyle: "double", borderColor: "cyan", padding: 1, width: 80 }, /* @__PURE__ */ React7.createElement(Box7, { justifyContent: "center", marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true, color: "cyan" }, " \u{1F4C2} RESUME SESSION ")), keys.length === 0 ? /* @__PURE__ */ React7.createElement(Text7, { italic: true, color: "gray" }, " No saved chats found. ") : keys.map((id, index) => {
3656
+ const s = emojiSpace(2);
3657
+ return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: 80 }, /* @__PURE__ */ React7.createElement(Box7, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "cyan", bold: true }, "\u{1F4A0} CHAT HISTORY: RESUME CONVERSATION")), keys.length === 0 ? /* @__PURE__ */ React7.createElement(Box7, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React7.createElement(Text7, { italic: true, color: "gray" }, "No saved chats found.")) : /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, keys.map((id, index) => {
3634
3658
  const chat2 = history[id];
3635
3659
  const isSelected = index === selectedIndex;
3636
- return /* @__PURE__ */ React7.createElement(Box7, { key: id, paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: isSelected ? "cyan" : "white" }, isSelected ? "\u276F " : " ", /* @__PURE__ */ React7.createElement(Text7, { bold: isSelected }, chat2.name || id), /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, " [", id.slice(5), "]")), isSelected && /* @__PURE__ */ React7.createElement(Box7, { marginLeft: "auto" }, /* @__PURE__ */ React7.createElement(Text7, { color: "red" }, " (x to delete) ")));
3637
- }), /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1, justifyContent: "center", borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, " \u2191\u2193 navigate \u2022 Enter select \u2022 x delete \u2022 Esc close ")));
3660
+ return /* @__PURE__ */ React7.createElement(
3661
+ Box7,
3662
+ {
3663
+ key: id,
3664
+ paddingX: 1,
3665
+ backgroundColor: isSelected ? "#2a2a2a" : void 0,
3666
+ width: "100%"
3667
+ },
3668
+ /* @__PURE__ */ React7.createElement(Box7, { flexGrow: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: isSelected ? "cyan" : "white", bold: isSelected }, isSelected ? "\u276F " : " ", chat2.name || id, /* @__PURE__ */ React7.createElement(Text7, { color: "gray", dimColor: !isSelected }, " [", id.slice(5), "]"))),
3669
+ isSelected && /* @__PURE__ */ React7.createElement(Box7, { flexShrink: 0 }, /* @__PURE__ */ React7.createElement(Text7, { color: "red", bold: true }, "[X] DELETE "))
3670
+ );
3671
+ })), /* @__PURE__ */ React7.createElement(
3672
+ Box7,
3673
+ {
3674
+ marginTop: 1,
3675
+ paddingX: 1,
3676
+ borderStyle: "single",
3677
+ borderLeft: false,
3678
+ borderRight: false,
3679
+ borderBottom: false,
3680
+ borderColor: "gray"
3681
+ },
3682
+ /* @__PURE__ */ React7.createElement(Text7, { dimColor: true, italic: true }, "\u2191\u2193 navigate \u2022 Enter select \u2022 x delete \u2022 Esc close")
3683
+ ));
3638
3684
  }
3639
3685
  var init_ResumeModal = __esm({
3640
3686
  "src/components/ResumeModal.jsx"() {
3641
3687
  init_history();
3688
+ init_terminal();
3642
3689
  }
3643
3690
  });
3644
3691
 
@@ -3672,12 +3719,39 @@ function MemoryModal({ onClose }) {
3672
3719
  const cleanDisplay = (text) => {
3673
3720
  return text.replace(/\[Saved on: .*?\]/g, "").trim();
3674
3721
  };
3675
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "double", borderColor: "yellow", padding: 1, width: 80 }, /* @__PURE__ */ React8.createElement(Box8, { justifyContent: "center", marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Text8, { bold: true, color: "yellow" }, "\u{1F9E0} LONG-TERM MEMORY VAULT")), memories.length === 0 ? /* @__PURE__ */ React8.createElement(Box8, { justifyContent: "center", paddingY: 2 }, /* @__PURE__ */ React8.createElement(Text8, { italic: true, color: "gray" }, "The vault is currently empty...")) : memories.map((mem, idx) => /* @__PURE__ */ React8.createElement(Box8, { key: mem.id, paddingX: 1, backgroundColor: idx === selectedIndex ? "#333" : void 0 }, /* @__PURE__ */ React8.createElement(Text8, { color: idx === selectedIndex ? "yellow" : "white" }, idx === selectedIndex ? "\u276F " : " ", idx + 1, ". ", cleanDisplay(mem.memory)))), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1, borderStyle: "single", borderTop: true, borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "gray" }, "\u2191/\u2193 Navigate \u2022 ", /* @__PURE__ */ React8.createElement(Text8, { color: "red" }, "x"), " Delete Memory \u2022 ", /* @__PURE__ */ React8.createElement(Text8, { color: "cyan" }, "Esc"), " Back to Chat")));
3722
+ const s = emojiSpace(2);
3723
+ return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: 80 }, /* @__PURE__ */ React8.createElement(Box8, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "cyan", bold: true }, "\u{1F9E0} AGENT MEMORY: LONG-TERM KNOWLEDGE")), memories.length === 0 ? /* @__PURE__ */ React8.createElement(Box8, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React8.createElement(Text8, { italic: true, color: "gray" }, "Still Learning...")) : /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column" }, memories.map((mem, idx) => {
3724
+ const isSelected = idx === selectedIndex;
3725
+ return /* @__PURE__ */ React8.createElement(
3726
+ Box8,
3727
+ {
3728
+ key: mem.id,
3729
+ paddingX: 1,
3730
+ backgroundColor: isSelected ? "#2a2a2a" : void 0,
3731
+ width: "100%"
3732
+ },
3733
+ /* @__PURE__ */ React8.createElement(Box8, { flexGrow: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: isSelected ? "cyan" : "white", bold: isSelected }, isSelected ? "\u276F " : " ", idx + 1, ". ", cleanDisplay(mem.memory))),
3734
+ isSelected && /* @__PURE__ */ React8.createElement(Box8, { flexShrink: 0 }, /* @__PURE__ */ React8.createElement(Text8, { color: "red", bold: true }, "[X] WIPE "))
3735
+ );
3736
+ })), /* @__PURE__ */ React8.createElement(
3737
+ Box8,
3738
+ {
3739
+ marginTop: 1,
3740
+ paddingX: 1,
3741
+ borderStyle: "single",
3742
+ borderLeft: false,
3743
+ borderRight: false,
3744
+ borderBottom: false,
3745
+ borderColor: "gray"
3746
+ },
3747
+ /* @__PURE__ */ React8.createElement(Text8, { dimColor: true, italic: true }, "\u2191\u2193 navigate \u2022 x wipe memory \u2022 Esc close")
3748
+ ));
3676
3749
  }
3677
3750
  var init_MemoryModal = __esm({
3678
3751
  "src/components/MemoryModal.jsx"() {
3679
3752
  init_crypto();
3680
3753
  init_paths();
3754
+ init_terminal();
3681
3755
  }
3682
3756
  });
3683
3757
 
@@ -3905,7 +3979,7 @@ function App() {
3905
3979
  return [...prev, {
3906
3980
  id: "tier-switch-" + Date.now(),
3907
3981
  role: "system",
3908
- text: `\u26A0\uFE0F **[TIER LIMIT]** Gemma is only available on Free API tier. Automatically switched to Gemini 3 Flash Preview.`,
3982
+ text: `\u26A0\uFE0F **[TIER LIMIT]** Gemma is only available on Free API tier. Auto-switched to Gemini 3 Flash Preview.`,
3909
3983
  isMeta: true
3910
3984
  }];
3911
3985
  });
@@ -4323,9 +4397,8 @@ ${hintText}`, color: "magenta" }];
4323
4397
  break;
4324
4398
  }
4325
4399
  case "/clear": {
4326
- stdout.write("\x1B[2J\x1B[3J\x1B[H");
4327
4400
  setMessages([{ id: "welcome-" + Date.now(), role: "system", text: FLUX_LOGO + "\n\n\u{1F30A}\u26A1 Welcome back to Flux Flow! Context cleared.\n", isMeta: true }]);
4328
- setCompletedIndex(0);
4401
+ setCompletedIndex(1);
4329
4402
  setChatId(generateChatId());
4330
4403
  setSessionStats({ tokens: 0 });
4331
4404
  setIsExpanded(false);
@@ -4896,60 +4969,6 @@ Selection: ${val}`,
4896
4969
  }, [suggestions]);
4897
4970
  const renderActiveView = () => {
4898
4971
  switch (activeView) {
4899
- case "mode":
4900
- return /* @__PURE__ */ React10.createElement(
4901
- CommandMenu,
4902
- {
4903
- title: "\u26A1 Select Operating Mode",
4904
- items: [{ label: "Flux (Dev mode - Extended Toolset)", value: "Flux" }, { label: "Flow (Chat mode - Basic Toolset)", value: "Flow" }, { label: "Cancel", value: "Cancel" }],
4905
- onSelect: (item) => {
4906
- if (item.value !== "Cancel") {
4907
- setMode(item.value);
4908
- if (item.value === "Flow") {
4909
- setThinkingLevel("Low");
4910
- } else if (item.value === "Flux") {
4911
- setThinkingLevel("High");
4912
- }
4913
- }
4914
- setActiveView("chat");
4915
- }
4916
- }
4917
- );
4918
- case "thinking": {
4919
- const options = mode === "Flow" ? [
4920
- { label: "Low (Fastest)", value: "Low" },
4921
- { label: "Medium (Balanced)", value: "Medium" }
4922
- ] : [
4923
- { label: "Low (Fastest)", value: "Low" },
4924
- { label: "Medium (Balanced)", value: "Medium" },
4925
- { label: "High (Complex coding)", value: "High" },
4926
- { label: "Max (Architecture)", value: "Max" }
4927
- ];
4928
- options.push({ label: "Cancel", value: "Cancel" });
4929
- return /* @__PURE__ */ React10.createElement(
4930
- CommandMenu,
4931
- {
4932
- title: `\u{1F9E0} Select Thinking Level (${mode} Mode)`,
4933
- items: options,
4934
- onSelect: (item) => {
4935
- if (item.value !== "Cancel") setThinkingLevel(item.value);
4936
- setActiveView("chat");
4937
- }
4938
- }
4939
- );
4940
- }
4941
- case "model":
4942
- return /* @__PURE__ */ React10.createElement(
4943
- CommandMenu,
4944
- {
4945
- title: "\u{1F916} Select AI Model",
4946
- items: [{ label: "Gemma 4 31B (Recomended - Default, Use Free Tier Key)", value: "gemma-4-31b-it" }, { label: "Gemini 3.1 Pro (Best - Req. Paid 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, Limited Free Quota)", value: "gemini-3.1-flash-lite-preview" }, { label: "Cancel", value: "Cancel" }],
4947
- onSelect: (item) => {
4948
- if (item.value !== "Cancel") setActiveModel(item.value);
4949
- setActiveView("chat");
4950
- }
4951
- }
4952
- );
4953
4972
  case "settings":
4954
4973
  return /* @__PURE__ */ React10.createElement(
4955
4974
  CommandMenu,
@@ -5223,8 +5242,11 @@ Selection: ${val}`,
5223
5242
  }
5224
5243
  setMessages(resumedMsgs);
5225
5244
  setActiveView("chat");
5226
- setMessages((prev) => [...prev, { id: "sys-" + Date.now(), role: "system", text: `\u{1F4E1} SESSION RESUMED: [${id}]` }]);
5227
- setCompletedIndex(0);
5245
+ setMessages((prev) => {
5246
+ const newMsgs = [...prev, { id: "sys-" + Date.now(), role: "system", text: `\u{1F4E1} SESSION RESUMED: [${id}]` }];
5247
+ setCompletedIndex(newMsgs.length);
5248
+ return newMsgs;
5249
+ });
5228
5250
  }
5229
5251
  },
5230
5252
  onDelete: async (id) => {
@@ -5258,7 +5280,7 @@ Selection: ${val}`,
5258
5280
  setActiveView("chat");
5259
5281
  setTimeout(() => {
5260
5282
  handleSubmit(val);
5261
- }, 200);
5283
+ }, 500);
5262
5284
  },
5263
5285
  onEdit: (val) => {
5264
5286
  setResolutionData(null);
@@ -5523,7 +5545,7 @@ var init_app = __esm({
5523
5545
  init_text();
5524
5546
  SESSION_START_TIME = Date.now();
5525
5547
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
5526
- versionFluxflow = "1.9.0";
5548
+ versionFluxflow = "1.9.1";
5527
5549
  updatedOn = "2026-05-13";
5528
5550
  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(
5529
5551
  CommandMenu,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.9.0",
3
+ "version": "1.9.1",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",