fluxflow-cli 1.8.25 → 1.8.28

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 +194 -92
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -10,35 +10,69 @@ var __export = (target, all) => {
10
10
  };
11
11
 
12
12
  // src/utils/text.js
13
- var wrapText, formatTokens;
13
+ var wrapText, formatTokens, truncatePath;
14
14
  var init_text = __esm({
15
15
  "src/utils/text.js"() {
16
16
  wrapText = (text, width) => {
17
17
  if (!text) return "";
18
18
  const sourceLines = text.split(/\r?\n/);
19
19
  let finalLines = [];
20
+ if (width <= 5) return text;
20
21
  sourceLines.forEach((sLine) => {
21
22
  if (sLine.length <= width) {
22
23
  finalLines.push(sLine);
23
24
  return;
24
25
  }
26
+ const tokens = sLine.split(/(\s+)/);
25
27
  let currentLine = "";
26
- const words = sLine.split(/(\s+)/);
27
- words.forEach((word) => {
28
- if ((currentLine + word).length > width) {
29
- if (currentLine) finalLines.push(currentLine.replace(/\s+$/, ""));
30
- if (word.trim().length === 0) {
31
- currentLine = "";
32
- } else {
33
- currentLine = word;
34
- while (currentLine.length > width) {
35
- finalLines.push(currentLine.substring(0, width));
36
- currentLine = currentLine.substring(width);
37
- }
28
+ let originalXPos = 0;
29
+ let lastSignificantGap = 0;
30
+ const leadingSpaceMatch = sLine.match(/^(\s*)/);
31
+ if (leadingSpaceMatch) {
32
+ lastSignificantGap = leadingSpaceMatch[1].length;
33
+ }
34
+ const listMatch = sLine.match(/^\s*([-*]|\d+\.)\s+/);
35
+ if (listMatch) {
36
+ lastSignificantGap = listMatch[0].length;
37
+ }
38
+ tokens.forEach((token, idx) => {
39
+ if (token.length === 0) return;
40
+ const isWhitespace = token.trim().length === 0;
41
+ if (isWhitespace) {
42
+ if (token.length >= 2) {
43
+ lastSignificantGap = originalXPos + token.length;
44
+ }
45
+ if (currentLine.length > 0) {
46
+ currentLine += token;
38
47
  }
39
48
  } else {
40
- currentLine += word;
49
+ if (token.includes("|") || token.includes("\u2502")) {
50
+ const pipeIdx = token.includes("|") ? token.indexOf("|") : token.indexOf("\u2502");
51
+ lastSignificantGap = originalXPos + pipeIdx + 1;
52
+ }
53
+ if ((currentLine + token).length > width) {
54
+ if (currentLine.trim().length > 0) {
55
+ finalLines.push(currentLine.replace(/\s+$/, ""));
56
+ const safeIndent = Math.min(lastSignificantGap, Math.max(0, width - 12));
57
+ const indent = " ".repeat(safeIndent);
58
+ currentLine = indent + token;
59
+ while (currentLine.length > width && width > 20) {
60
+ finalLines.push(currentLine.substring(0, width));
61
+ currentLine = indent + currentLine.substring(width);
62
+ }
63
+ } else {
64
+ let word = token;
65
+ while (word.length > width && width > 5) {
66
+ finalLines.push(word.substring(0, width));
67
+ word = word.substring(width);
68
+ }
69
+ currentLine = word;
70
+ }
71
+ } else {
72
+ currentLine += token;
73
+ }
41
74
  }
75
+ originalXPos += token.length;
42
76
  });
43
77
  if (currentLine) finalLines.push(currentLine.replace(/\s+$/, ""));
44
78
  });
@@ -54,6 +88,11 @@ var init_text = __esm({
54
88
  }
55
89
  return num.toString();
56
90
  };
91
+ truncatePath = (p, maxLength = 40) => {
92
+ if (!p || p.length <= maxLength) return p;
93
+ const half = Math.floor((maxLength - 3) / 2);
94
+ return p.substring(0, half) + "..." + p.substring(p.length - half);
95
+ };
57
96
  }
58
97
  });
59
98
 
@@ -86,12 +125,20 @@ var init_ChatLayout = __esm({
86
125
  const trigger = "tool:functions.";
87
126
  while (true) {
88
127
  const lowerResult = result.toLowerCase();
89
- const startIdx = lowerResult.indexOf(trigger);
90
- if (startIdx === -1) break;
128
+ let triggerIdx = lowerResult.indexOf(trigger);
129
+ if (triggerIdx === -1) break;
130
+ let startIdx = triggerIdx;
131
+ let hasOuterBracket = false;
132
+ let k = triggerIdx - 1;
133
+ while (k >= 0 && /\s/.test(result[k])) k--;
134
+ if (k >= 0 && result[k] === "[") {
135
+ startIdx = k;
136
+ hasOuterBracket = true;
137
+ }
91
138
  let balance = 0;
92
139
  let foundStart = false;
93
140
  let inString = null;
94
- let j = startIdx;
141
+ let j = triggerIdx;
95
142
  while (j < result.length) {
96
143
  const char = result[j];
97
144
  if (!inString && (char === "'" || char === '"' || char === "`")) {
@@ -107,12 +154,26 @@ var init_ChatLayout = __esm({
107
154
  balance--;
108
155
  }
109
156
  }
157
+ if (foundStart && balance === 0 && !inString) {
158
+ let endIdx = j;
159
+ if (hasOuterBracket) {
160
+ let m = j + 1;
161
+ while (m < result.length && /\s/.test(result[m])) m++;
162
+ if (m < result.length && result[m] === "]") {
163
+ endIdx = m;
164
+ }
165
+ }
166
+ result = result.substring(0, startIdx) + result.substring(endIdx + 1);
167
+ break;
168
+ }
110
169
  j++;
111
- if (foundStart && balance === 0 && !inString) break;
170
+ if (j === result.length) {
171
+ result = result.substring(0, startIdx);
172
+ return result;
173
+ }
112
174
  }
113
- result = result.substring(0, startIdx) + result.substring(j);
114
175
  }
115
- 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(/\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();
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();
116
177
  };
117
178
  formatThinkText = (cleaned, columns = 80) => {
118
179
  if (!cleaned) return null;
@@ -439,7 +500,7 @@ var init_StatusBar = __esm({
439
500
  width: "100%"
440
501
  },
441
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)),
442
- /* @__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())),
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))),
443
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, " "))
444
505
  );
445
506
  });
@@ -683,31 +744,30 @@ var init_main_tools = __esm({
683
744
  TOOL_PROTOCOL = (mode) => `
684
745
  -- START FUNCTION CALLING PROTOCOL --
685
746
  You have access to internal tools. To call a tool, you MUST use the following exact syntax on a new line:
686
- tool:functions.tool_name(arguments)
747
+ [tool:functions.tool_name(arguments)]
687
748
 
688
749
  - USER COMMUNICATION TOOLS (Available in Flux & Flow) -
689
- 1. Ask User: tool:functions.ask(question="...", optionA="Option::Desc", optionB="Option::Desc"). Generally use this tool for ANY ambiguity. 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.
750
+ 1. Ask User: [tool:functions.ask(question="...", optionA="Option::Desc", optionB="Option::Desc")]. Generally use this tool for ANY ambiguity. 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.
690
751
 
691
752
  - WEB TOOLS (Available in Flux & Flow) -
692
- 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.Winder search recomemded (limit = 10) when exploring a topic.
693
- 2. Web Scrape: tool:functions.web_scrape(url="<url>"). provides detail from a URL.
753
+ 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.Winder search recomemded (limit = 10) when exploring a topic.
754
+ 2. Web Scrape: [tool:functions.web_scrape(url="<url>")]. provides detail from a URL.
694
755
  ${mode === "Flux" ? `
695
756
  - DEV & FILE TOOLS (Available in FLUX MODE ONLY) -
696
- 1. View File: tool:functions.view_file(path="relative/path", start_line=number, end_line=number). Reads file content. Auto-truncates at 500 lines unless start_line and end_line are provided. YOU CAN ALSO USE THIS TOOL TO SEE IMAGES AND DOCUMENTS IN A FOLDER. IF USER ASK HOW TO SHARE A IMAGE TELL THEM TO PASTE THE IMAGE IN THE CURRENT FOLDER. IF USER GIVES A IMAGE/DOCUMENT, YOU MUST SEE IT FIRST BEFORE DOING ANYTHING.
697
- 2. List Files: tool:functions.list_files(path="relative/path"). Lists content of a directory.
698
- 3. Read Folder: tool:functions.read_folder(path="relative/path"). Detailed stats of a directory. Prefer this one over list_files.
699
- 4. Write File: tool:functions.write_file(path="path", content="First Line
700
- Second Line with literal [/n] sequence"). Creates/Overwrites. NO CODE BLOCKS.
701
- 5. Update File: tool:functions.update_file(path="path", content_to_replace="old content", content_to_add="new content with [/n]"). Surgical patching.
702
- 6. Write PDF: tool:functions.write_pdf(path="path", content="<html/css content>", orientation="portrait/landscape"). Generates a professional PDF document. Orientation are optional. A4 size page will be used, so any multi-page PDFs calculate your alightment and page breaks to not mess up A4 page layout. DO NOT ADD FOOTER MANUALLY, the system will handle it automatically. USE CSS TO VISUALLY BEAUTIFY THE DOCUMENT, USE full 100vh & 100vw for page area. ENSURE THE CONTENT IS NEVER BROKEN IN BETWEEN PAGES, USE PAGE BREAKS PROACTIVELY FOR A A4 PAGE LAYOUT. Keep generous margins for better redability.
703
- 7. Write DOCX: tool:functions.write_docx(path="path", content="<html content>"). Generates a professional Word document (.docx) from HTML. You can make multiple pages. Default Page dimentions will be A4, use proper margins and page break strategy.
704
- 8. Write PPTX: tool:functions.write_pptx(path="path", content="<h1 style='color: #0088CC;'>Title</h1><ul style='font-size: 14pt;'><li>Point A</li></ul>
757
+ 1. View File: [tool:functions.view_file(path="relative/path", start_line=number, end_line=number)]. Reads file content. Auto-truncates at 500 lines unless start_line and end_line are provided. YOU CAN ALSO USE THIS TOOL TO SEE IMAGES AND DOCUMENTS IN A FOLDER. IF USER ASK HOW TO SHARE A IMAGE TELL THEM TO PASTE THE IMAGE IN THE CURRENT FOLDER. IF USER GIVES A IMAGE/DOCUMENT, YOU MUST SEE IT FIRST BEFORE DOING ANYTHING.
758
+ 2. Read Folder: [tool:functions.read_folder(path="relative/path")]. Detailed stats of a directory.
759
+ 3. Write File: [tool:functions.write_file(path="path", content="First Line
760
+ Second Line with literal [/n] sequence")]. Creates/Overwrites. NO CODE BLOCKS.
761
+ 4. Update File: [tool:functions.update_file(path="path", content_to_replace="old content", content_to_add="new content with [/n]")]. Surgical patching.
762
+ 5. Write PDF: [tool:functions.write_pdf(path="path", content="<html/css content>", orientation="portrait/landscape")]. Generates a professional PDF document. Orientation are optional. A4 size page will be used, so any multi-page PDFs calculate your alightment and page breaks to not mess up A4 page layout. DO NOT ADD FOOTER MANUALLY, the system will handle it automatically. USE CSS TO VISUALLY BEAUTIFY THE DOCUMENT, USE full 100vh & 100vw for page area. ENSURE THE CONTENT IS NEVER BROKEN IN BETWEEN PAGES, USE PAGE BREAKS PROACTIVELY FOR A A4 PAGE LAYOUT. Keep generous margins for better redability.
763
+ 6. Write DOCX: [tool:functions.write_docx(path="path", content="<html content>")]. Generates a professional Word document (.docx) from HTML. You can make multiple pages. Default Page dimentions will be A4, use proper margins and page break strategy.
764
+ 7. Write PPTX: [tool:functions.write_pptx(path="path", content="<h1 style='color: #0088CC;'>Title</h1><ul style='font-size: 14pt;'><li>Point A</li></ul>
705
765
  ---
706
- <p align='center'>Styled Slide</p>"). Generates a professional PowerPoint presentation (.pptx) from a flat HTML string. Use '---' on a new line to separate slides. Aspect Ratio is 4:3.
766
+ <p align='center'>Styled Slide</p>")]. Generates a professional PowerPoint presentation (.pptx) from a flat HTML string. Use '---' on a new line to separate slides. Aspect Ratio is 4:3.
707
767
  - Supported Tags: <a>, <b>, <br>, <del>, <font>, <h1>-<h6>, <i>, <ol>, <ul>, <li>, <p>, <pre>, <s>, <sub>, <sup>, <u>.
708
768
  - Supported Styles: background-color, color, font-family, font-size (use 'pt'), font-style (italic), font-weight (bold), margin, text-align, text-shadow.
709
- 9. Execution: tool:functions.exec_command(command="terminal command"). Runs a shell command. Use ask tool to confirm before executing any destructive or irreversible operations.
710
- 10. Search Keyword: tool:functions.search_keyword(keyword="..."). Global search for a string across the entire project. RETURNS: List of matches with relative file paths and line numbers. Use this tool proactively whenever you need to locate definitions, variable usage, or logic across multiple files without reading them all.
769
+ 8. Execution: [tool:functions.exec_command(command="terminal command")]. Runs a shell command. Use ask tool to confirm before executing any destructive or irreversible operations.
770
+ 9. Search Keyword: [tool:functions.search_keyword(keyword="...")]. Global search for a string across the entire project. RETURNS: List of matches with relative file paths and line numbers. Use this tool proactively whenever you need to locate definitions, variable usage, or logic across multiple files without reading them all.
711
771
 
712
772
  AFTER GETTING THE TOOL RESULT, YOU MUST VERIFY THAT ITS A SUCCESS, IF IT GIVES A ERROR, TELL THE USER AND TRY TO FIX IF YOU CAN. DO NOT HALLUCINATE SUCCESS IF TOOL RETURNS ERROR.
713
773
  NEVER GUESS A CODE, IF UNSURE READ THE FILE FIRST BEFORE EDITING IT.
@@ -720,14 +780,20 @@ Prefer write_file tool to write code instead of chat by default.
720
780
  3. \u{1F6D1} NEVER USE "\\\\n" (backslash-n) inside tool arguments for literal strings; the system parser will convert it into a real structural line break, which WILL BREAK your code syntax (e.g. in C, Python).
721
781
  4. ALWAYS check the tool result diff to ensure your [/n] was correctly translated to a literal
722
782
  .
723
- ***`.trim() : `
724
- - DEV & FILE TOOLS ARE NOT AVAILABLE IN FLOW MODE. If you need to access files, tell the user to switch to FLUX MODE (manually by user).`.trim()}
783
+ ***
784
+
785
+ *** [\u{1F6A8} CRITICAL QUOTE ESCAPE POLICY \u{1F6A8}] ***
786
+ [CORRECT]:
787
+ tool:functions.write_file(path="app.js", content="const x = \\"hello\\";")
788
+ [INCORRECT]:
789
+ tool:functions.write_file(path="app.js", content="const x = "hello";")`.trim() : `
790
+ - DEV & FILE TOOLS ARE NOT AVAILABLE IN FLOW MODE. If you need to access files, tell the user to switch to FLUX MODE (manually by user).`.trim()}
725
791
  -----------------
726
792
 
727
793
  Results will be provided in the next loop as: [TOOL_RESULT]: [content] under <user> tag. Treat them as SYSTEM MESSAGES. True user messages will be prefixed as 'USER_PROMPT' by the system.
728
794
  WHEN CALLING TOOLS, YOU **MUST** end your response with '[turn: continue]'. NEVER use '[turn: finish]' in the same turn as a tool call. After receiving the [TOOL_RESULT], acknowledge the output and verify if the goal is met; only then may you use '[turn: finish]', otherwise use '[turn: continue]'.
729
795
  Do NOT over-use tools. Use them only when strictly necessary for the user's objective. You can stack multiple tool calls 1-by-1.
730
- Distinguish clearly between tool discussion and execution. Use the 'tool:' prefix ONLY when calling a function. When discussing tools with the user, refer to them by name as nouns (e.g., 'write_file', 'list_files') to avoid accidental triggers and context bloat. Even in your <think> ... </think> tags, do not use the 'tool:' prefix when planning to select a tool.
796
+ Distinguish clearly between tool discussion and execution. Use the '[tool:' prefix ONLY when calling a function. When discussing tools with the user, refer to them by name as nouns (e.g., 'write_file', 'list_files') to avoid accidental triggers and context bloat. Even in your <think> ... </think> tags, do not use the '[tool:' prefix when planning to select a tool.
731
797
  Use tools contextually when needed, don't flood with unnecessary tool calls.
732
798
  -- END FUNCTION CALLING PROTOCOL --`.trim();
733
799
  }
@@ -740,21 +806,21 @@ var init_janitor_tools = __esm({
740
806
  JANITOR_TOOLS_PROTOCOL = (isMemoryEnabled = true, needTitle = true) => `
741
807
  ${needTitle ? `-- START CHAT MANAGEMENT TOOLS --
742
808
  1. YOU MUST UPDATE CHAT TITLE (URGENT PRIORITY):
743
- tool:functions.chat(title='<short creative title of FULL conversation in 3-5 words>') // consider full chat context to generate title NOT just latest message.
809
+ [tool:functions.chat(title='<short creative title of FULL conversation in 3-5 words>')]. Consider full chat context to generate title NOT just latest message.
744
810
  -- END CHAT MANAGEMENT TOOLS --
745
811
 
746
812
  ` : ""}
747
813
  -- START MEMORY TOOLS (YOU SHOULD NOT OUTPUT ANYTHING OTHER THAN THESE SPECIFIC TOOLS) --
748
- Your tool syntax is: 'tool:functions.function_name(args...)'
814
+ Your tool syntax is: '[tool:functions.function_name(args...)]'
749
815
  You have access to the following memory functions to persist important information:
750
816
 
751
817
  1. Temporary context (URGENT PRIORITY):
752
- tool:functions.memory(action='temp', content='<summary of the user prompt & model responses ONLY FROM LATEST PROMPT UNDER 40 WORDS>. [Talked on: <date> <hour>]')
818
+ [tool:functions.memory(action='temp', content='<summary of the user prompt & model responses ONLY FROM LATEST PROMPT UNDER 40 WORDS>. [Talked on: <date> <hour>]')]
753
819
 
754
820
  ${isMemoryEnabled ? `2. User-specific long-term memory (USE BASED ON CONVERSATION CONTEXT):
755
- - Add: tool:functions.memory(action='user', method='add', content='<string to add>. [Saved on: <date ONLY>]')
756
- - Delete: tool:functions.memory(action='user', method='delete', content='exact memory id')
757
- - Update: tool:functions.memory(action='user', method='update', content-new='string to update', content-old='exact memory id')
821
+ - Add: [tool:functions.memory(action='user', method='add', content='<string to add>. [Saved on: <date ONLY>]')]
822
+ - Delete: [tool:functions.memory(action='user', method='delete', content='exact memory id')]
823
+ - Update: [tool:functions.memory(action='user', method='update', content-new='string to update', content-old='exact memory id')]
758
824
 
759
825
  Usage Rules:
760
826
  - Frequency for 'user' action: Only when explicit context from chat is found or explicitly requested by the user.
@@ -794,7 +860,7 @@ var init_prompts = __esm({
794
860
  init_main_tools();
795
861
  init_janitor_tools();
796
862
  init_thinking_prompts();
797
- getSystemInstruction = (profile, thinkingLevel, mode, systemSettings, tempMemories = "", userMemories = "", isMemoryEnabled = true, isContext8 = false, maxLoops, currentLoop) => {
863
+ getSystemInstruction = (profile, thinkingLevel, mode, systemSettings, tempMemories = "", userMemories = "", isMemoryEnabled = true, isContext32k = false, maxLoops, currentLoop) => {
798
864
  let levelKey = thinkingLevel;
799
865
  if (thinkingLevel === "Low") levelKey = "Minimal";
800
866
  if (thinkingLevel === "xHigh" || thinkingLevel === "Max") levelKey = "Max";
@@ -808,13 +874,13 @@ var init_prompts = __esm({
808
874
  ` : "";
809
875
  const dateTimeStr = (/* @__PURE__ */ new Date()).toLocaleString();
810
876
  const cwdStr = process.cwd();
811
- const tempMemoriesStr = tempMemories?.length > 0 && !isContext8 ? `
812
- -- RECENT CONTEXT FROM OTHER CHAT THREADS --
877
+ const tempMemoriesStr = tempMemories?.length > 0 && !isContext32k ? `
878
+ -- RECENT CONTEXT FROM OTHER CHAT THREADS (LOW PRIORITY) --
813
879
  ${tempMemories}
814
880
  ------------------------------------------
815
881
  ` : "";
816
882
  const userMemoriesStr = userMemories?.length > 0 ? `
817
- --- PERSISTENT USER MEMORIES ---
883
+ --- PERSISTENT USER MEMORIES (MEDIUM PRIORITY, TUNES PERSONALIZATION & USER PREFERENCES) ---
818
884
  ${userMemories}
819
885
  --------------------------------
820
886
  ` : "";
@@ -823,8 +889,9 @@ ${userMemories}
823
889
  ` : ""}${isMemoryEnabled ? `${tempMemoriesStr}
824
890
 
825
891
  ` : ""}${nameStr}${nicknameStr}${userInstrStr}
826
- --- START SYSTEM INSTRUCTION ---
892
+ --- START SYSTEM INSTRUCTION (STRICT PRIORITY, OVERRIDES EVERYTHING) ---
827
893
  You are Flux Flow (made by Kushal Roy Chowdhury). A CLI Agent. Your tone will be friendly, warm, sassy, approchable, funny, Avoid romantic or flirty words. Dont mention modes unless explicitly asked. ${mode === "Flux" ? `You are currently operating in FLUX mode. Keep your agentic approach goal oriented, conversation quality and user experience. Use provided tools when needed. And try to minimize number of agentic loops. Analyze user prompt and project requirements, then plan your approach.` : `You are currently operating in Flow mode. Focus more on conversation quality and user experience. Keep Agentic Loops to minimum. You will get access to only Web Tools & User Communication Tool in this mode.`}
894
+ MUST FOLLOW THE "CRITICAL NEWLINE PROTOCOL" AND "CRITICAL QUOTE ESCAPE POLICY" ALWAYS.
828
895
  CURRENT_WORKING_DIRECTORY: ${cwdStr}.
829
896
  OS: ${osDetected}. ${osDetected === "Windows" && mode === "Flux" ? "Your terminal commands will run on CMD. 'Prefer using PS scripts via CMD' instead of raw CMD commands." : ""}
830
897
  If you see a [STEERING HINT] from user, give that prompt priority for the task at hand, user can use it to help you guide if you go wrong way.
@@ -833,7 +900,7 @@ If you see a [STEERING HINT] from user, give that prompt priority for the task a
833
900
  -- START THINKING INSTRUCTIONS --
834
901
  ${thinkingConfig}
835
902
 
836
- BEFORE USING ANY TOOL THINKING IS **MANDATORY** WITH TOOL RULES. ALWAYS PRIORITIZE THINKING FIRST BEFORE RESPONDING. YOU ARE **FORBIDDEN** TO JUMP TO RESPONSES FIRST. THINKING IS REQUIRED EVEN WITH SIMPLEST CONVERSATIONAL RESPONSES.
903
+ BEFORE USING ANY TOOL THINKING IS **MANDATORY**. ALWAYS PRIORITIZE THINKING BEFORE RESPONDING. YOU ARE **FORBIDDEN** TO JUMP TO RESPONSES FIRST. THINKING IS **REQUIRED EVEN WITH SIMPLEST CONVERSATIONAL RESPONSES OR SUPER BASIC TASKS OR ROLEPLAYS**.
837
904
  -- END THINKING INSTRUCTIONS --
838
905
 
839
906
  ${TOOL_PROTOCOL(mode)}
@@ -844,7 +911,7 @@ ${mode === "Flux" ? `
844
911
  3. Skills.md (If exists): Use this for complex workflows. If a task matches a "Skill" defined in this file, execute the documented step-by-step instructions exactly as written.
845
912
  4. Fluxflow.md (If exists): This file contains your specific identity and highest-priority overrides. Instructions in Fluxflow.md supersede all other files if a conflict occurs.
846
913
 
847
- Before starting any task, check for these files and treat them as your primary source of truth, overriding your general training data to remain consistent with this specific project's environment.
914
+ Before starting any task, check for these files and treat them as your primary source of truth, overriding your general training data to remain consistent with this specific project's environment. THIS WOUDLD BE APPLIED FOR PROJECT SPECIFIC INSTRUCTIONS AND SHOULD NOT TRY TO BYPASS YOUR CRITICAL PROTOCOLS OR SAFETY RULES.
848
915
  -- END PROJECT SPECIFIC INSTRUCTIONS --` : ""}
849
916
 
850
917
  -- START MEMORY INSTRUCTIONS --
@@ -866,16 +933,20 @@ Every ${isMemoryEnabled ? "Prompt, Responses & Memories" : "Prompt & Responses"}
866
933
  [CORRECT]:
867
934
  tool:functions.write_file(path="test.c", content="#include <stdio.h>
868
935
  int main() {
869
- printf("Hello[/n]");
936
+ printf("Hello[/n]World");
870
937
  return 0;
871
938
  }")
872
939
  [INCORRECT]:
873
940
  tool:functions.write_file(path="test.c", content="#include <stdio.h>\\nint main() {\\nprintf("Hello\\\\n");\\n}")
874
941
  \u{1F6D1} NEVER use '\\\\n' for literals; it will be converted to a real line break and break code syntax.
942
+ - CRITICAL QUOTE ESCAPE POLICY: Inside tool call arguments (like 'content' in write_file AND update_file), you MUST escape all double quotes using '\\"' to prevent argument truncation or parsing errors.
943
+ [CORRECT]:
944
+ tool:functions.write_file(path="app.js", content="const x = \\"hello\\";")
945
+ [INCORRECT]:
946
+ tool:functions.write_file(path="app.js", content="const x = "hello";")
875
947
  - Structure responses VISUALLY pleasing, easy to read, and beautiful.
876
- - USE GFM Markdown HEAVILY.
877
948
  - Use GFM tables for structured data to keep the terminal view organized. KEEP SENTENCES IN TABLE **SHORT & CONCISE**. AND MAX 4 COLUMNS. DO NOT OVERUSE TABLES.
878
- - **CRITICAL**: NEVER USE LaTeX IN RESPONSES.
949
+ - NEVER USE LaTeX IN RESPONSES.
879
950
  - Keep Poems & Literature in Code Block.
880
951
  - Use emojis & Kaomojis. Prefer Kaomojis more.
881
952
  - Keep your in-chat responses shorter and concise.
@@ -887,7 +958,7 @@ TO END THE LOOP YOU **MUST** WRITE [turn: finish] AT VERY END OF YOUR RESPONSE.
887
958
  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.
888
959
  -- END REPONSE FINISH PROTOCOL --
889
960
 
890
- [Runtime Monitor] Turn Progress: ${currentLoop}/${maxLoops} steps. Aim to finalize the task before the window closes. If the limit is reached, please summarize and invite the user to re-engage.
961
+ [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.
891
962
  Current date and Time is: ${dateTimeStr}
892
963
  --- END SYSTEM INSTRUCTION ---`.trim();
893
964
  };
@@ -910,12 +981,13 @@ ${userMemories}
910
981
  --- START SYSTEM INSTRUCTION (STRICT HEADLESS LOGIC WORKER: ZERO USER-FACING TEXT POLICY) ---
911
982
  YOU ARE A SILENT BACKGROUND SYSTEM PROCESS. YOU HAVE NO MOUTH. YOUR ONLY OUTPUT MEDIUM IS VALID TOOL CALLS.
912
983
  [CRITICAL RULES]
913
- 1. OUTPUT ONLY 'tool:functions.xxx' CALLS.
984
+ 1. OUTPUT ONLY '[tool:functions.xxx(args)]' CALLS (BRACKET WRAP IS MANDATORY).
914
985
  2. DO NOT EXPLAIN. DO NOT TALK TO THE USER.
915
986
  3. NON-TOOL TEXT WILL BREAK THE SYSTEM.
916
987
  4. DO NOT REPEAT AGENT RAWS AND TOOL RESULTS IN YOUR RESPONSE.
917
988
  5. IF YOU GET ONLY USER QUERY AND NO AGENT RAWS, THEN JUST USE TEMP MEMORY TO LOG THE SUMMARY OF USER QUERY.
918
989
  6. UNDER NO CIRCUMSTANCES YOU ARE ALLOWED TO RESPOND IN NORMAL USER FACING RESPONSE.
990
+ 7. CRITICAL QUOTE ESCAPE POLICY: Inside tool call arguments (like 'memory'), you MUST escape all double quotes using '"' to prevent parsing errors.
919
991
 
920
992
  YOUR JOB: Analyze the 'User prompt' and 'Agent Raws' to extract facts for long-term memory or handle system tasks.
921
993
  ${isMemoryEnabled ? `If user tell something that is important (like, hobbies, preferences, facts about user, hates, likes, etc) to know user better over time, use long term memory tools.` : ""}
@@ -1049,7 +1121,10 @@ var init_usage = __esm({
1049
1121
  if (await fs5.exists(USAGE_FILE)) {
1050
1122
  const data = await fs5.readJson(USAGE_FILE);
1051
1123
  if (data && data.date === today && data.stats) {
1052
- return data;
1124
+ return {
1125
+ ...data,
1126
+ stats: { ...defaultStats, ...data.stats }
1127
+ };
1053
1128
  }
1054
1129
  }
1055
1130
  } catch (err) {
@@ -1060,6 +1135,7 @@ var init_usage = __esm({
1060
1135
  search: 0,
1061
1136
  toolSuccess: 0,
1062
1137
  toolFailure: 0,
1138
+ toolDenied: 0,
1063
1139
  duration: 0,
1064
1140
  tokens: 0
1065
1141
  };
@@ -1128,6 +1204,7 @@ var init_usage = __esm({
1128
1204
  search: 0,
1129
1205
  toolSuccess: 0,
1130
1206
  toolFailure: 0,
1207
+ toolDenied: 0,
1131
1208
  duration: 0,
1132
1209
  tokens: 0
1133
1210
  }
@@ -2486,7 +2563,7 @@ var init_ai = __esm({
2486
2563
  janitorContents.push({ role: "user", parts: [{ text: janitorPrompt }] });
2487
2564
  let finalSynthesis = "";
2488
2565
  let attempts = 0;
2489
- const MAX_JANITOR_RETRIES = 4;
2566
+ const MAX_JANITOR_RETRIES = 5;
2490
2567
  while (attempts <= MAX_JANITOR_RETRIES) {
2491
2568
  try {
2492
2569
  if (!await checkQuota("background", settings)) {
@@ -2591,7 +2668,7 @@ DEBUG [${date}]: ${finalSynthesis}
2591
2668
  }
2592
2669
  };
2593
2670
  getActiveToolContext = (text) => {
2594
- const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
2671
+ const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
2595
2672
  let match;
2596
2673
  while ((match = toolRegex.exec(text)) !== null) {
2597
2674
  const startIdx = match.index + match[0].length - 1;
@@ -2611,9 +2688,13 @@ DEBUG [${date}]: ${finalSynthesis}
2611
2688
  if (char === "(") balance++;
2612
2689
  else if (char === ")") balance--;
2613
2690
  if (balance === 0) {
2614
- closed = true;
2615
- toolRegex.lastIndex = i + 1;
2616
- break;
2691
+ let j = i + 1;
2692
+ while (j < text.length && /\s/.test(text[j])) j++;
2693
+ if (j < text.length && text[j] === "]") {
2694
+ closed = true;
2695
+ toolRegex.lastIndex = j + 1;
2696
+ break;
2697
+ }
2617
2698
  }
2618
2699
  }
2619
2700
  if (char === "\\") isEscaped = !isEscaped;
@@ -2626,7 +2707,7 @@ DEBUG [${date}]: ${finalSynthesis}
2626
2707
  return { inside: false };
2627
2708
  };
2628
2709
  getContextSafeText = (text, stripThoughts = true) => {
2629
- const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
2710
+ const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
2630
2711
  let result = "";
2631
2712
  let lastIdx = 0;
2632
2713
  let match;
@@ -2650,19 +2731,23 @@ DEBUG [${date}]: ${finalSynthesis}
2650
2731
  if (char === "(") balance++;
2651
2732
  else if (char === ")") balance--;
2652
2733
  if (balance === 0) {
2653
- endIdx = i;
2654
- break;
2734
+ let j = i + 1;
2735
+ while (j < text.length && /\s/.test(text[j])) j++;
2736
+ if (j < text.length && text[j] === "]") {
2737
+ endIdx = j;
2738
+ break;
2739
+ }
2655
2740
  }
2656
2741
  }
2657
2742
  if (char === "\\") isEscaped = !isEscaped;
2658
2743
  else isEscaped = false;
2659
2744
  }
2660
2745
  if (endIdx !== -1) {
2661
- result += "tool:functions." + match[1] + "()";
2746
+ result += "[tool:functions." + match[1] + "()]";
2662
2747
  lastIdx = endIdx + 1;
2663
2748
  toolRegex.lastIndex = lastIdx;
2664
2749
  } else {
2665
- result += "tool:functions." + match[1] + "(";
2750
+ result += "[tool:functions." + match[1] + "(";
2666
2751
  lastIdx = text.length;
2667
2752
  break;
2668
2753
  }
@@ -2673,7 +2758,7 @@ DEBUG [${date}]: ${finalSynthesis}
2673
2758
  return result;
2674
2759
  };
2675
2760
  contextSafeReplace = (text, regex, replacement) => {
2676
- const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
2761
+ const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
2677
2762
  let result = "";
2678
2763
  let lastIdx = 0;
2679
2764
  let match;
@@ -2697,8 +2782,12 @@ DEBUG [${date}]: ${finalSynthesis}
2697
2782
  if (char === "(") balance++;
2698
2783
  else if (char === ")") balance--;
2699
2784
  if (balance === 0) {
2700
- endIdx = i;
2701
- break;
2785
+ let j = i + 1;
2786
+ while (j < text.length && /\s/.test(text[j])) j++;
2787
+ if (j < text.length && text[j] === "]") {
2788
+ endIdx = j;
2789
+ break;
2790
+ }
2702
2791
  }
2703
2792
  }
2704
2793
  if (char === "\\") isEscaped = !isEscaped;
@@ -2724,7 +2813,7 @@ DEBUG [${date}]: ${finalSynthesis}
2724
2813
  };
2725
2814
  detectToolCalls = (text) => {
2726
2815
  const results = [];
2727
- const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
2816
+ const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
2728
2817
  let match;
2729
2818
  while ((match = toolRegex.exec(text)) !== null) {
2730
2819
  const toolName = match[1];
@@ -2733,6 +2822,7 @@ DEBUG [${date}]: ${finalSynthesis}
2733
2822
  let inString = null;
2734
2823
  let isEscaped = false;
2735
2824
  let endIdx = -1;
2825
+ let closingParenIdx = -1;
2736
2826
  for (let i = startIdx; i < text.length; i++) {
2737
2827
  const char = text[i];
2738
2828
  if (!inString && (char === '"' || char === "'" || char === "`")) {
@@ -2745,8 +2835,13 @@ DEBUG [${date}]: ${finalSynthesis}
2745
2835
  if (char === "(") balance++;
2746
2836
  else if (char === ")") balance--;
2747
2837
  if (balance === 0) {
2748
- endIdx = i;
2749
- break;
2838
+ closingParenIdx = i;
2839
+ let j = i + 1;
2840
+ while (j < text.length && /\s/.test(text[j])) j++;
2841
+ if (j < text.length && text[j] === "]") {
2842
+ endIdx = j;
2843
+ break;
2844
+ }
2750
2845
  }
2751
2846
  }
2752
2847
  if (char === "\\") {
@@ -2756,12 +2851,12 @@ DEBUG [${date}]: ${finalSynthesis}
2756
2851
  }
2757
2852
  }
2758
2853
  if (endIdx !== -1) {
2759
- const finalArgs = text.substring(startIdx + 1, endIdx);
2854
+ const finalArgsText = text.substring(startIdx + 1, closingParenIdx);
2760
2855
  const finalFullMatch = text.substring(match.index, endIdx + 1);
2761
2856
  results.push({
2762
2857
  fullMatch: finalFullMatch,
2763
2858
  toolName: toolName.trim(),
2764
- args: finalArgs.trim()
2859
+ args: finalArgsText.trim()
2765
2860
  });
2766
2861
  toolRegex.lastIndex = endIdx + 1;
2767
2862
  }
@@ -2791,7 +2886,7 @@ DEBUG [${date}]: ${finalSynthesis}
2791
2886
  const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
2792
2887
  const mainUserMemories = persistentStorage.map((m) => `- ${m.memory}`).join("\n");
2793
2888
  const janitorUserMemories = persistentStorage.map((m) => `- [${m.id}]: ${m.memory}`).join("\n");
2794
- const firstUserMsg = `USER_PROMPT: ${agentText}`.trim();
2889
+ const firstUserMsg = `USER_PROMPT: "${agentText}"`.trim();
2795
2890
  modifiedHistory.push({ role: "user", text: firstUserMsg });
2796
2891
  let lastUsage = null;
2797
2892
  const MAX_LOOPS = mode === "Flux" ? 50 : 7;
@@ -2870,8 +2965,8 @@ DEBUG [${date}]: ${finalSynthesis}
2870
2965
  } else if (retryCount > 0) {
2871
2966
  yield { type: "model_update", content: null };
2872
2967
  }
2873
- const isContext8 = (sessionStats.tokens || 0) >= 8e3;
2874
- const currentSystemInstruction = getSystemInstruction(profile, thinkingLevel, mode, systemSettings, otherMemories, mainUserMemories, isMemoryEnabled, isContext8, MAX_LOOPS, loop + 1);
2968
+ const isContext32k = (sessionStats.tokens || 0) >= 32e3;
2969
+ const currentSystemInstruction = getSystemInstruction(profile, thinkingLevel, mode, systemSettings, otherMemories, mainUserMemories, isMemoryEnabled, isContext32k, MAX_LOOPS, loop + 1);
2875
2970
  stream = await client.models.generateContentStream({
2876
2971
  model: targetModel || "gemma-4-31b-it",
2877
2972
  contents,
@@ -3108,8 +3203,10 @@ ${boxBottom}
3108
3203
  if (approval === "deny") {
3109
3204
  if (toolCall.toolName === "exec_command" && settings.onExecEnd) settings.onExecEnd();
3110
3205
  const denyMsg = `Permission Denied: User rejected the ${toolCall.toolName === "exec_command" ? "terminal execution" : "file edit"}.`;
3111
- toolResults.push({ role: "user", text: `[TOOL_RESULT]: ERROR: ${denyMsg}` });
3112
- yield { type: "tool_result", content: `[TOOL_RESULT]: ERROR: ${denyMsg}` };
3206
+ toolResults.push({ role: "user", text: `[TOOL_RESULT]: DENIED: ${denyMsg}` });
3207
+ yield { type: "tool_result", content: `[TOOL_RESULT]: DENIED: ${denyMsg}` };
3208
+ await incrementUsage("toolDenied");
3209
+ if (settings.onToolResult) settings.onToolResult("denied");
3113
3210
  toolCallPointer++;
3114
3211
  continue;
3115
3212
  }
@@ -3136,17 +3233,19 @@ ${boxBottom}
3136
3233
  await new Promise((resolve) => setTimeout(resolve, 800));
3137
3234
  settings.onExecEnd();
3138
3235
  }
3139
- const isSuccess = result && !result.startsWith("ERROR:");
3236
+ const isDenied = result && result.startsWith("DENIED:");
3237
+ const isSuccess = result && !result.startsWith("ERROR:") && !isDenied;
3140
3238
  if (isSuccess) {
3141
3239
  await incrementUsage("toolSuccess");
3142
3240
  if (settings.onToolResult) settings.onToolResult("success");
3241
+ } else if (isDenied) {
3143
3242
  } else {
3144
3243
  await incrementUsage("toolFailure");
3145
3244
  if (settings.onToolResult) settings.onToolResult("failure");
3146
3245
  }
3147
- const aiContent = `[TOOL_RESULT]: ${result.split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n")}`;
3246
+ const aiContent = `[TOOL_RESULT]: ${(result || "").toString().split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n")}`;
3148
3247
  toolResults.push({ role: "user", text: aiContent, binaryPart });
3149
- let uiContent = `[TOOL_RESULT]: ${result}`;
3248
+ let uiContent = `[TOOL_RESULT]: ${result || ""}`;
3150
3249
  if (toolCall.toolName === "view_file" || toolCall.toolName === "web_scrape") {
3151
3250
  uiContent = `[TOOL_RESULT]: ${label} (Context Locked for UI Clarity)`;
3152
3251
  }
@@ -3660,6 +3759,7 @@ Check what's new using \`/changelog\` command.`,
3660
3759
  const [sessionTotalTokens, setSessionTotalTokens] = useState7(0);
3661
3760
  const [sessionToolSuccess, setSessionToolSuccess] = useState7(0);
3662
3761
  const [sessionToolFailure, setSessionToolFailure] = useState7(0);
3762
+ const [sessionToolDenied, setSessionToolDenied] = useState7(0);
3663
3763
  const [sessionApiTime, setSessionApiTime] = useState7(0);
3664
3764
  const [sessionToolTime, setSessionToolTime] = useState7(0);
3665
3765
  const [dailyUsage, setDailyUsage] = useState7(null);
@@ -4321,6 +4421,7 @@ OUTPUT: ${execOutputRef.current}`;
4321
4421
  },
4322
4422
  onToolResult: (status) => {
4323
4423
  if (status === "success") setSessionToolSuccess((prev) => prev + 1);
4424
+ else if (status === "denied") setSessionToolDenied((prev) => prev + 1);
4324
4425
  else setSessionToolFailure((prev) => prev + 1);
4325
4426
  },
4326
4427
  onToolApproval: async (tool, args) => {
@@ -4486,6 +4587,7 @@ Selection: ${val}`,
4486
4587
  inToolCall = true;
4487
4588
  toolCallBalance = 0;
4488
4589
  inToolCallString = null;
4590
+ if (chunkText.includes("[tool:functions.")) toolCallBalance = 0;
4489
4591
  }
4490
4592
  if (inToolCall) {
4491
4593
  for (let j = 0; j < chunkText.length; j++) {
@@ -4496,8 +4598,8 @@ Selection: ${val}`,
4496
4598
  inToolCallString = null;
4497
4599
  }
4498
4600
  if (!inToolCallString) {
4499
- if (char === "(") toolCallBalance++;
4500
- else if (char === ")") toolCallBalance--;
4601
+ if (char === "(" || char === "[") toolCallBalance++;
4602
+ else if (char === ")" || char === "]") toolCallBalance--;
4501
4603
  }
4502
4604
  }
4503
4605
  if (toolCallBalance <= 0 && !inToolCallString) {
@@ -4822,7 +4924,7 @@ Selection: ${val}`,
4822
4924
  }
4823
4925
  )), /* @__PURE__ */ React10.createElement(Text10, { dimColor: true, marginTop: 1 }, "(Press Enter to confirm)"));
4824
4926
  case "stats":
4825
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, width: 100 }, /* @__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, " ( "), /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", sessionToolSuccess), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "x ", 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), " ( "), /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", dailyUsage?.toolSuccess || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "x ", 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)"));
4927
+ 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)"));
4826
4928
  case "autoExecDanger":
4827
4929
  return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true, underline: true }, "\u26A0\uFE0F SECURITY WARNING: AUTO-EXEC MODE"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "Turning this ON allows the agent to execute terminal commands automatically without requiring your approval for each step."), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1, color: "yellow" }, "RISKS INVOLVED:"), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 The agent may execute destructive commands (rm -rf, etc.) by mistake."), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Unintended system changes if the agent hallucinates a path or command."), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Reduced control over the agent's step-by-step decision making."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
4828
4930
  CommandMenu,
@@ -5143,7 +5245,7 @@ Selection: ${val}`,
5143
5245
  {
5144
5246
  messages: messages.slice(completedIndex),
5145
5247
  showFullThinking,
5146
- columns: stdout?.columns || 80
5248
+ columns: Math.max(20, (stdout?.columns || 80) - 1)
5147
5249
  }
5148
5250
  ), 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(
5149
5251
  TextInput3,
@@ -5170,7 +5272,7 @@ Selection: ${val}`,
5170
5272
  const agentActiveMs = sessionApiTime + sessionToolTime;
5171
5273
  const apiPercent = agentActiveMs > 0 ? (sessionApiTime / agentActiveMs * 100).toFixed(1) : "0.0";
5172
5274
  const toolPercent = agentActiveMs > 0 ? (sessionToolTime / agentActiveMs * 100).toFixed(1) : "0.0";
5173
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "red", width: 100, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "Agent powering down. ", /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, "Goodbye!"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "Interaction Summary"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Session ID:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, chatId)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, totalTools, " ( ", /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", sessionToolSuccess), " ", /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "x ", sessionToolFailure), " )")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Success Rate:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, successRate, "%")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(sessionTotalTokens)))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "Performance"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Wall Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(wallTimeMs))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Active:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(agentActiveMs))), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 18 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB API Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionApiTime), " (", apiPercent, "%)")), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 18 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB Tool Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionToolTime), " (", toolPercent, "%)"))));
5275
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "red", width: Math.min(100, (stdout?.columns || 100) - 2), marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "Agent powering down. ", /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, "Goodbye!"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "Interaction Summary"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Session ID:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, chatId)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( ", /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", sessionToolSuccess), " ", /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u2298 ", sessionToolDenied), " ", /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "\u2715 ", sessionToolFailure), " )")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Success Rate:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, successRate, "%")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(sessionTotalTokens)))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "Performance"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Wall Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(wallTimeMs))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Active:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(agentActiveMs))), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 18 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB API Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionApiTime), " (", apiPercent, "%)")), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 18 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB Tool Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionToolTime), " (", toolPercent, "%)"))));
5174
5276
  })(), suggestions.length > 0 && (() => {
5175
5277
  const windowSize = 5;
5176
5278
  const startIdx = Math.max(0, Math.min(selectedIndex - 2, suggestions.length - windowSize));
@@ -5233,8 +5335,8 @@ var init_app = __esm({
5233
5335
  init_text();
5234
5336
  SESSION_START_TIME = Date.now();
5235
5337
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
5236
- versionFluxflow = "1.8.25";
5237
- updatedOn = "2026-05-11";
5338
+ versionFluxflow = "1.8.28";
5339
+ updatedOn = "2026-05-12";
5238
5340
  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(
5239
5341
  CommandMenu,
5240
5342
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.8.25",
3
+ "version": "1.8.28",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",