fluxflow-cli 1.8.26 → 1.8.29

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 +186 -83
  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,31 @@ 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.
751
+ DO NOT GIVE OPTION TO ASK USER THEIR PREFERENCES. JUST GIVE THE OPTIONS YOU THINK ARE BEST FOR THE USER.
690
752
 
691
753
  - 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.
754
+ 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.
755
+ 2. Web Scrape: [tool:functions.web_scrape(url="<url>")]. provides detail from a URL.
694
756
  ${mode === "Flux" ? `
695
757
  - 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>
758
+ 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.
759
+ 2. Read Folder: [tool:functions.read_folder(path="relative/path")]. Detailed stats of a directory.
760
+ 3. Write File: [tool:functions.write_file(path="path", content="First Line
761
+ Second Line with literal [/n] sequence")]. Creates/Overwrites. NO CODE BLOCKS.
762
+ 4. Update File: [tool:functions.update_file(path="path", content_to_replace="old content", content_to_add="new content with [/n]")]. Surgical patching.
763
+ 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.
764
+ 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.
765
+ 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
766
  ---
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.
767
+ <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
768
  - Supported Tags: <a>, <b>, <br>, <del>, <font>, <h1>-<h6>, <i>, <ol>, <ul>, <li>, <p>, <pre>, <s>, <sub>, <sup>, <u>.
708
769
  - 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.
770
+ 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.
771
+ 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
772
 
712
773
  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
774
  NEVER GUESS A CODE, IF UNSURE READ THE FILE FIRST BEFORE EDITING IT.
@@ -720,14 +781,20 @@ Prefer write_file tool to write code instead of chat by default.
720
781
  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
782
  4. ALWAYS check the tool result diff to ensure your [/n] was correctly translated to a literal
722
783
  .
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()}
784
+ ***
785
+
786
+ *** [\u{1F6A8} CRITICAL QUOTE ESCAPE POLICY \u{1F6A8}] ***
787
+ [CORRECT]:
788
+ tool:functions.write_file(path="app.js", content="const x = \\"hello\\";")
789
+ [INCORRECT]:
790
+ tool:functions.write_file(path="app.js", content="const x = "hello";")`.trim() : `
791
+ - 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
792
  -----------------
726
793
 
727
794
  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
795
  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
796
  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.
797
+ 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
798
  Use tools contextually when needed, don't flood with unnecessary tool calls.
732
799
  -- END FUNCTION CALLING PROTOCOL --`.trim();
733
800
  }
@@ -740,21 +807,21 @@ var init_janitor_tools = __esm({
740
807
  JANITOR_TOOLS_PROTOCOL = (isMemoryEnabled = true, needTitle = true) => `
741
808
  ${needTitle ? `-- START CHAT MANAGEMENT TOOLS --
742
809
  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.
810
+ [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
811
  -- END CHAT MANAGEMENT TOOLS --
745
812
 
746
813
  ` : ""}
747
814
  -- START MEMORY TOOLS (YOU SHOULD NOT OUTPUT ANYTHING OTHER THAN THESE SPECIFIC TOOLS) --
748
- Your tool syntax is: 'tool:functions.function_name(args...)'
815
+ Your tool syntax is: '[tool:functions.function_name(args...)]'
749
816
  You have access to the following memory functions to persist important information:
750
817
 
751
818
  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>]')
819
+ [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
820
 
754
821
  ${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')
822
+ - Add: [tool:functions.memory(action='user', method='add', content='<string to add>. [Saved on: <date ONLY>]')]
823
+ - Delete: [tool:functions.memory(action='user', method='delete', content='exact memory id')]
824
+ - Update: [tool:functions.memory(action='user', method='update', content-new='string to update', content-old='exact memory id')]
758
825
 
759
826
  Usage Rules:
760
827
  - Frequency for 'user' action: Only when explicit context from chat is found or explicitly requested by the user.
@@ -825,7 +892,7 @@ ${userMemories}
825
892
  ` : ""}${nameStr}${nicknameStr}${userInstrStr}
826
893
  --- START SYSTEM INSTRUCTION (STRICT PRIORITY, OVERRIDES EVERYTHING) ---
827
894
  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.`}
828
- MUST FOLLOW THE "CRITICAL NEWLINE PROTOCOL" ALWAYS.
895
+ MUST FOLLOW THE "CRITICAL NEWLINE PROTOCOL" AND "CRITICAL QUOTE ESCAPE POLICY" ALWAYS.
829
896
  CURRENT_WORKING_DIRECTORY: ${cwdStr}.
830
897
  OS: ${osDetected}. ${osDetected === "Windows" && mode === "Flux" ? "Your terminal commands will run on CMD. 'Prefer using PS scripts via CMD' instead of raw CMD commands." : ""}
831
898
  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.
@@ -834,7 +901,7 @@ If you see a [STEERING HINT] from user, give that prompt priority for the task a
834
901
  -- START THINKING INSTRUCTIONS --
835
902
  ${thinkingConfig}
836
903
 
837
- 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 OR BASIC TASKS**.
904
+ 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**.
838
905
  -- END THINKING INSTRUCTIONS --
839
906
 
840
907
  ${TOOL_PROTOCOL(mode)}
@@ -873,9 +940,14 @@ int main() {
873
940
  [INCORRECT]:
874
941
  tool:functions.write_file(path="test.c", content="#include <stdio.h>\\nint main() {\\nprintf("Hello\\\\n");\\n}")
875
942
  \u{1F6D1} NEVER use '\\\\n' for literals; it will be converted to a real line break and break code syntax.
943
+ - 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.
944
+ [CORRECT]:
945
+ tool:functions.write_file(path="app.js", content="const x = \\"hello\\";")
946
+ [INCORRECT]:
947
+ tool:functions.write_file(path="app.js", content="const x = "hello";")
876
948
  - Structure responses VISUALLY pleasing, easy to read, and beautiful.
877
949
  - 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.
950
+ - NEVER USE LaTeX IN RESPONSES.
879
951
  - Keep Poems & Literature in Code Block.
880
952
  - Use emojis & Kaomojis. Prefer Kaomojis more.
881
953
  - Keep your in-chat responses shorter and concise.
@@ -910,12 +982,13 @@ ${userMemories}
910
982
  --- START SYSTEM INSTRUCTION (STRICT HEADLESS LOGIC WORKER: ZERO USER-FACING TEXT POLICY) ---
911
983
  YOU ARE A SILENT BACKGROUND SYSTEM PROCESS. YOU HAVE NO MOUTH. YOUR ONLY OUTPUT MEDIUM IS VALID TOOL CALLS.
912
984
  [CRITICAL RULES]
913
- 1. OUTPUT ONLY 'tool:functions.xxx' CALLS.
985
+ 1. OUTPUT ONLY '[tool:functions.xxx(args)]' CALLS (BRACKET WRAP IS MANDATORY).
914
986
  2. DO NOT EXPLAIN. DO NOT TALK TO THE USER.
915
987
  3. NON-TOOL TEXT WILL BREAK THE SYSTEM.
916
988
  4. DO NOT REPEAT AGENT RAWS AND TOOL RESULTS IN YOUR RESPONSE.
917
989
  5. IF YOU GET ONLY USER QUERY AND NO AGENT RAWS, THEN JUST USE TEMP MEMORY TO LOG THE SUMMARY OF USER QUERY.
918
990
  6. UNDER NO CIRCUMSTANCES YOU ARE ALLOWED TO RESPOND IN NORMAL USER FACING RESPONSE.
991
+ 7. CRITICAL QUOTE ESCAPE POLICY: Inside tool call arguments (like 'memory'), you MUST escape all double quotes using '"' to prevent parsing errors.
919
992
 
920
993
  YOUR JOB: Analyze the 'User prompt' and 'Agent Raws' to extract facts for long-term memory or handle system tasks.
921
994
  ${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 +1122,10 @@ var init_usage = __esm({
1049
1122
  if (await fs5.exists(USAGE_FILE)) {
1050
1123
  const data = await fs5.readJson(USAGE_FILE);
1051
1124
  if (data && data.date === today && data.stats) {
1052
- return data;
1125
+ return {
1126
+ ...data,
1127
+ stats: { ...defaultStats, ...data.stats }
1128
+ };
1053
1129
  }
1054
1130
  }
1055
1131
  } catch (err) {
@@ -1060,6 +1136,7 @@ var init_usage = __esm({
1060
1136
  search: 0,
1061
1137
  toolSuccess: 0,
1062
1138
  toolFailure: 0,
1139
+ toolDenied: 0,
1063
1140
  duration: 0,
1064
1141
  tokens: 0
1065
1142
  };
@@ -1128,6 +1205,7 @@ var init_usage = __esm({
1128
1205
  search: 0,
1129
1206
  toolSuccess: 0,
1130
1207
  toolFailure: 0,
1208
+ toolDenied: 0,
1131
1209
  duration: 0,
1132
1210
  tokens: 0
1133
1211
  }
@@ -2486,7 +2564,7 @@ var init_ai = __esm({
2486
2564
  janitorContents.push({ role: "user", parts: [{ text: janitorPrompt }] });
2487
2565
  let finalSynthesis = "";
2488
2566
  let attempts = 0;
2489
- const MAX_JANITOR_RETRIES = 4;
2567
+ const MAX_JANITOR_RETRIES = 5;
2490
2568
  while (attempts <= MAX_JANITOR_RETRIES) {
2491
2569
  try {
2492
2570
  if (!await checkQuota("background", settings)) {
@@ -2591,7 +2669,7 @@ DEBUG [${date}]: ${finalSynthesis}
2591
2669
  }
2592
2670
  };
2593
2671
  getActiveToolContext = (text) => {
2594
- const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
2672
+ const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
2595
2673
  let match;
2596
2674
  while ((match = toolRegex.exec(text)) !== null) {
2597
2675
  const startIdx = match.index + match[0].length - 1;
@@ -2611,9 +2689,13 @@ DEBUG [${date}]: ${finalSynthesis}
2611
2689
  if (char === "(") balance++;
2612
2690
  else if (char === ")") balance--;
2613
2691
  if (balance === 0) {
2614
- closed = true;
2615
- toolRegex.lastIndex = i + 1;
2616
- break;
2692
+ let j = i + 1;
2693
+ while (j < text.length && /\s/.test(text[j])) j++;
2694
+ if (j < text.length && text[j] === "]") {
2695
+ closed = true;
2696
+ toolRegex.lastIndex = j + 1;
2697
+ break;
2698
+ }
2617
2699
  }
2618
2700
  }
2619
2701
  if (char === "\\") isEscaped = !isEscaped;
@@ -2626,7 +2708,7 @@ DEBUG [${date}]: ${finalSynthesis}
2626
2708
  return { inside: false };
2627
2709
  };
2628
2710
  getContextSafeText = (text, stripThoughts = true) => {
2629
- const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
2711
+ const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
2630
2712
  let result = "";
2631
2713
  let lastIdx = 0;
2632
2714
  let match;
@@ -2650,19 +2732,23 @@ DEBUG [${date}]: ${finalSynthesis}
2650
2732
  if (char === "(") balance++;
2651
2733
  else if (char === ")") balance--;
2652
2734
  if (balance === 0) {
2653
- endIdx = i;
2654
- break;
2735
+ let j = i + 1;
2736
+ while (j < text.length && /\s/.test(text[j])) j++;
2737
+ if (j < text.length && text[j] === "]") {
2738
+ endIdx = j;
2739
+ break;
2740
+ }
2655
2741
  }
2656
2742
  }
2657
2743
  if (char === "\\") isEscaped = !isEscaped;
2658
2744
  else isEscaped = false;
2659
2745
  }
2660
2746
  if (endIdx !== -1) {
2661
- result += "tool:functions." + match[1] + "()";
2747
+ result += "[tool:functions." + match[1] + "()]";
2662
2748
  lastIdx = endIdx + 1;
2663
2749
  toolRegex.lastIndex = lastIdx;
2664
2750
  } else {
2665
- result += "tool:functions." + match[1] + "(";
2751
+ result += "[tool:functions." + match[1] + "(";
2666
2752
  lastIdx = text.length;
2667
2753
  break;
2668
2754
  }
@@ -2673,7 +2759,7 @@ DEBUG [${date}]: ${finalSynthesis}
2673
2759
  return result;
2674
2760
  };
2675
2761
  contextSafeReplace = (text, regex, replacement) => {
2676
- const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
2762
+ const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
2677
2763
  let result = "";
2678
2764
  let lastIdx = 0;
2679
2765
  let match;
@@ -2697,8 +2783,12 @@ DEBUG [${date}]: ${finalSynthesis}
2697
2783
  if (char === "(") balance++;
2698
2784
  else if (char === ")") balance--;
2699
2785
  if (balance === 0) {
2700
- endIdx = i;
2701
- break;
2786
+ let j = i + 1;
2787
+ while (j < text.length && /\s/.test(text[j])) j++;
2788
+ if (j < text.length && text[j] === "]") {
2789
+ endIdx = j;
2790
+ break;
2791
+ }
2702
2792
  }
2703
2793
  }
2704
2794
  if (char === "\\") isEscaped = !isEscaped;
@@ -2724,7 +2814,7 @@ DEBUG [${date}]: ${finalSynthesis}
2724
2814
  };
2725
2815
  detectToolCalls = (text) => {
2726
2816
  const results = [];
2727
- const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
2817
+ const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
2728
2818
  let match;
2729
2819
  while ((match = toolRegex.exec(text)) !== null) {
2730
2820
  const toolName = match[1];
@@ -2733,6 +2823,7 @@ DEBUG [${date}]: ${finalSynthesis}
2733
2823
  let inString = null;
2734
2824
  let isEscaped = false;
2735
2825
  let endIdx = -1;
2826
+ let closingParenIdx = -1;
2736
2827
  for (let i = startIdx; i < text.length; i++) {
2737
2828
  const char = text[i];
2738
2829
  if (!inString && (char === '"' || char === "'" || char === "`")) {
@@ -2745,8 +2836,13 @@ DEBUG [${date}]: ${finalSynthesis}
2745
2836
  if (char === "(") balance++;
2746
2837
  else if (char === ")") balance--;
2747
2838
  if (balance === 0) {
2748
- endIdx = i;
2749
- break;
2839
+ closingParenIdx = i;
2840
+ let j = i + 1;
2841
+ while (j < text.length && /\s/.test(text[j])) j++;
2842
+ if (j < text.length && text[j] === "]") {
2843
+ endIdx = j;
2844
+ break;
2845
+ }
2750
2846
  }
2751
2847
  }
2752
2848
  if (char === "\\") {
@@ -2756,12 +2852,12 @@ DEBUG [${date}]: ${finalSynthesis}
2756
2852
  }
2757
2853
  }
2758
2854
  if (endIdx !== -1) {
2759
- const finalArgs = text.substring(startIdx + 1, endIdx);
2855
+ const finalArgsText = text.substring(startIdx + 1, closingParenIdx);
2760
2856
  const finalFullMatch = text.substring(match.index, endIdx + 1);
2761
2857
  results.push({
2762
2858
  fullMatch: finalFullMatch,
2763
2859
  toolName: toolName.trim(),
2764
- args: finalArgs.trim()
2860
+ args: finalArgsText.trim()
2765
2861
  });
2766
2862
  toolRegex.lastIndex = endIdx + 1;
2767
2863
  }
@@ -3108,8 +3204,10 @@ ${boxBottom}
3108
3204
  if (approval === "deny") {
3109
3205
  if (toolCall.toolName === "exec_command" && settings.onExecEnd) settings.onExecEnd();
3110
3206
  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}` };
3207
+ toolResults.push({ role: "user", text: `[TOOL_RESULT]: DENIED: ${denyMsg}` });
3208
+ yield { type: "tool_result", content: `[TOOL_RESULT]: DENIED: ${denyMsg}` };
3209
+ await incrementUsage("toolDenied");
3210
+ if (settings.onToolResult) settings.onToolResult("denied");
3113
3211
  toolCallPointer++;
3114
3212
  continue;
3115
3213
  }
@@ -3136,17 +3234,19 @@ ${boxBottom}
3136
3234
  await new Promise((resolve) => setTimeout(resolve, 800));
3137
3235
  settings.onExecEnd();
3138
3236
  }
3139
- const isSuccess = result && !result.startsWith("ERROR:");
3237
+ const isDenied = result && result.startsWith("DENIED:");
3238
+ const isSuccess = result && !result.startsWith("ERROR:") && !isDenied;
3140
3239
  if (isSuccess) {
3141
3240
  await incrementUsage("toolSuccess");
3142
3241
  if (settings.onToolResult) settings.onToolResult("success");
3242
+ } else if (isDenied) {
3143
3243
  } else {
3144
3244
  await incrementUsage("toolFailure");
3145
3245
  if (settings.onToolResult) settings.onToolResult("failure");
3146
3246
  }
3147
- const aiContent = `[TOOL_RESULT]: ${result.split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n")}`;
3247
+ const aiContent = `[TOOL_RESULT]: ${(result || "").toString().split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n")}`;
3148
3248
  toolResults.push({ role: "user", text: aiContent, binaryPart });
3149
- let uiContent = `[TOOL_RESULT]: ${result}`;
3249
+ let uiContent = `[TOOL_RESULT]: ${result || ""}`;
3150
3250
  if (toolCall.toolName === "view_file" || toolCall.toolName === "web_scrape") {
3151
3251
  uiContent = `[TOOL_RESULT]: ${label} (Context Locked for UI Clarity)`;
3152
3252
  }
@@ -3660,6 +3760,7 @@ Check what's new using \`/changelog\` command.`,
3660
3760
  const [sessionTotalTokens, setSessionTotalTokens] = useState7(0);
3661
3761
  const [sessionToolSuccess, setSessionToolSuccess] = useState7(0);
3662
3762
  const [sessionToolFailure, setSessionToolFailure] = useState7(0);
3763
+ const [sessionToolDenied, setSessionToolDenied] = useState7(0);
3663
3764
  const [sessionApiTime, setSessionApiTime] = useState7(0);
3664
3765
  const [sessionToolTime, setSessionToolTime] = useState7(0);
3665
3766
  const [dailyUsage, setDailyUsage] = useState7(null);
@@ -4321,6 +4422,7 @@ OUTPUT: ${execOutputRef.current}`;
4321
4422
  },
4322
4423
  onToolResult: (status) => {
4323
4424
  if (status === "success") setSessionToolSuccess((prev) => prev + 1);
4425
+ else if (status === "denied") setSessionToolDenied((prev) => prev + 1);
4324
4426
  else setSessionToolFailure((prev) => prev + 1);
4325
4427
  },
4326
4428
  onToolApproval: async (tool, args) => {
@@ -4486,6 +4588,7 @@ Selection: ${val}`,
4486
4588
  inToolCall = true;
4487
4589
  toolCallBalance = 0;
4488
4590
  inToolCallString = null;
4591
+ if (chunkText.includes("[tool:functions.")) toolCallBalance = 0;
4489
4592
  }
4490
4593
  if (inToolCall) {
4491
4594
  for (let j = 0; j < chunkText.length; j++) {
@@ -4496,8 +4599,8 @@ Selection: ${val}`,
4496
4599
  inToolCallString = null;
4497
4600
  }
4498
4601
  if (!inToolCallString) {
4499
- if (char === "(") toolCallBalance++;
4500
- else if (char === ")") toolCallBalance--;
4602
+ if (char === "(" || char === "[") toolCallBalance++;
4603
+ else if (char === ")" || char === "]") toolCallBalance--;
4501
4604
  }
4502
4605
  }
4503
4606
  if (toolCallBalance <= 0 && !inToolCallString) {
@@ -4822,7 +4925,7 @@ Selection: ${val}`,
4822
4925
  }
4823
4926
  )), /* @__PURE__ */ React10.createElement(Text10, { dimColor: true, marginTop: 1 }, "(Press Enter to confirm)"));
4824
4927
  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)"));
4928
+ 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
4929
  case "autoExecDanger":
4827
4930
  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
4931
  CommandMenu,
@@ -5001,9 +5104,9 @@ Selection: ${val}`,
5001
5104
  const oldVal = args.TargetContent || args.content_to_replace || null;
5002
5105
  const newVal = args.content || args.ReplacementContent || args.content_to_add || args.replacementContent || null;
5003
5106
  if (oldVal && newVal) {
5004
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Text10, { color: "red", wrap: "anywhere", bold: true }, "- ", oldVal)), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "green", wrap: "anywhere", bold: true }, "+ ", newVal)));
5107
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Text10, { color: "red", wrap: "anywhere", bold: true }, "- ", oldVal)), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "green", wrap: "anywhere", bold: true }, "+ ", newVal.replace(/\[\/n\]/g, "\\n"))));
5005
5108
  }
5006
- return /* @__PURE__ */ React10.createElement(Text10, { color: "white", wrap: "anywhere" }, newVal || "Updating file content...");
5109
+ return /* @__PURE__ */ React10.createElement(Text10, { color: "white", wrap: "anywhere" }, newVal.replace(/\[\/n\]/g, "\\n") || "Updating file content...");
5007
5110
  })()), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
5008
5111
  CommandMenu,
5009
5112
  {
@@ -5143,7 +5246,7 @@ Selection: ${val}`,
5143
5246
  {
5144
5247
  messages: messages.slice(completedIndex),
5145
5248
  showFullThinking,
5146
- columns: stdout?.columns || 80
5249
+ columns: Math.max(20, (stdout?.columns || 80) - 1)
5147
5250
  }
5148
5251
  ), 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
5252
  TextInput3,
@@ -5170,7 +5273,7 @@ Selection: ${val}`,
5170
5273
  const agentActiveMs = sessionApiTime + sessionToolTime;
5171
5274
  const apiPercent = agentActiveMs > 0 ? (sessionApiTime / agentActiveMs * 100).toFixed(1) : "0.0";
5172
5275
  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, "%)"))));
5276
+ 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
5277
  })(), suggestions.length > 0 && (() => {
5175
5278
  const windowSize = 5;
5176
5279
  const startIdx = Math.max(0, Math.min(selectedIndex - 2, suggestions.length - windowSize));
@@ -5233,8 +5336,8 @@ var init_app = __esm({
5233
5336
  init_text();
5234
5337
  SESSION_START_TIME = Date.now();
5235
5338
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
5236
- versionFluxflow = "1.8.26";
5237
- updatedOn = "2026-05-11";
5339
+ versionFluxflow = "1.8.29";
5340
+ updatedOn = "2026-05-12";
5238
5341
  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
5342
  CommandMenu,
5240
5343
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.8.26",
3
+ "version": "1.8.29",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",