fluxflow-cli 1.9.5 → 1.9.7

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 +51 -35
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -143,17 +143,17 @@ var init_ChatLayout = __esm({
143
143
  init_text();
144
144
  init_terminal();
145
145
  TOOL_LABELS = {
146
- "write_file": "Write File",
147
- "update_file": "Update File",
148
- "read_folder": "Read Folder",
149
- "view_file": "View File",
150
- "exec_command": "Execute Command",
151
- "web_search": "Web Search",
152
- "web_scrape": "Read Site",
153
- "search_keyword": "Find Files",
154
- "write_pdf": "Create PDF",
155
- "write_pptx": "Create Presentation",
156
- "write_docx": "Create Document"
146
+ "write_file": "WriteFile",
147
+ "update_file": "UpdateFile",
148
+ "read_folder": "ReadFolder",
149
+ "view_file": "ViewFile",
150
+ "exec_command": "ExecuteCommand",
151
+ "web_search": "WebSearch",
152
+ "web_scrape": "ReadSite",
153
+ "search_keyword": "FindFiles",
154
+ "write_pdf": "CreatePDF",
155
+ "write_pptx": "CreatePresentation",
156
+ "write_docx": "CreateDocument"
157
157
  };
158
158
  cleanSignals = (text) => {
159
159
  if (!text) return text;
@@ -209,7 +209,7 @@ var init_ChatLayout = __esm({
209
209
  }
210
210
  }
211
211
  }
212
- return result.replace(/^\[TOOL_RESULT\]:\s*/gi, "").split("\n").filter((line) => !line.trim().startsWith("SUCCESS:") && !line.trim().startsWith("ERROR:")).join("\n").replace(/\[\s*turn\s*:\s*(continue|finish)\s*\]/gi, "").replace(/\[\s*turn\s*:?.*?$/gi, "").replace(/\n\s*turn\s*:?.*?$/gi, "").replace(/\[\s*$/gi, "").replace(/\n\nResponded on .*/g, "").replace(/\n\n\[Prompted on: .*\]/g, "").replace(/(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)/gi, "\u2192").replace(/(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)/gi, "\u2190").replace(/(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)/gi, "\u2191").replace(/(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)/gi, "\u2193").replace(/(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi, "\u2194").replace(/\[\/n\]?/g, "\\n").replace(/@\[TerminalName:.*?, ProcessId:.*?\]/gi, "").replace(/\b(write_file|update_file|read_folder|view_file|exec_command|web_search|web_scrape|search_keyword|write_pdf|write_pptx|write_docx)\b/gi, (match) => TOOL_LABELS[match.toLowerCase()] || match).trim();
212
+ return result.replace(/^\[TOOL_RESULT\]:\s*/gi, "").split("\n").filter((line) => !line.trim().startsWith("SUCCESS:") && !line.trim().startsWith("ERROR:")).join("\n").replace(/\[\s*turn\s*:\s*(continue|finish)\s*\]/gi, "").replace(/\[\s*turn\s*:?.*?$/gi, "").replace(/\n\s*turn\s*:?.*?$/gi, "").replace(/\[\s*$/gi, "").replace(/\n\nResponded on .*/g, "").replace(/\n\n\[Prompted on: .*\]/g, "").replace(/(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)/gi, "\u2192").replace(/(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)/gi, "\u2190").replace(/(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)/gi, "\u2191").replace(/(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)/gi, "\u2193").replace(/(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi, "\u2194").replace(/\[\/n\]?/g, "\\\\n").replace(/@\[TerminalName:.*?, ProcessId:.*?\]/gi, "").replace(/\b(write_file|update_file|read_folder|view_file|exec_command|web_search|web_scrape|search_keyword|write_pdf|write_pptx|write_docx)\b/gi, (match) => TOOL_LABELS[match.toLowerCase()] || match).trim();
213
213
  };
214
214
  formatThinkText = (cleaned, columns = 80) => {
215
215
  if (!cleaned) return null;
@@ -222,9 +222,12 @@ var init_ChatLayout = __esm({
222
222
  };
223
223
  InlineMarkdown = React2.memo(({ text, color }) => {
224
224
  if (!text) return null;
225
- const parts = text.split(/(\*\*.*?\*\*|\*.*?\*|`.*?`|\$.*?\$|\[.*?\]\s*\(.*?\)|\[.*?\]\s*\[.*?\]|https?:\/\/[^\s]+)/g);
225
+ const parts = text.split(/(```[\s\S]*?```|`[^`]+`|\*\*.*?\*\*|\*.*?\*|\$.*?\$|\[.*?\]\s*\(.*?\)|\[.*?\]\s*\[.*?\]|https?:\/\/[^\s]+)/g);
226
226
  return /* @__PURE__ */ React2.createElement(Text2, { color, wrap: "anywhere" }, parts.map((part, j) => {
227
227
  if (!part) return null;
228
+ if (part.startsWith("```") && part.endsWith("```")) {
229
+ return /* @__PURE__ */ React2.createElement(CodeRenderer, { key: j, text: part });
230
+ }
228
231
  if (part.startsWith("**") && part.endsWith("**")) {
229
232
  return /* @__PURE__ */ React2.createElement(Text2, { key: j, bold: true, color: "white" }, /* @__PURE__ */ React2.createElement(InlineMarkdown, { text: part.slice(2, -2), color: "white" }));
230
233
  }
@@ -376,14 +379,28 @@ var init_ChatLayout = __esm({
376
379
  if (text.includes("[DIFF_START]")) {
377
380
  return /* @__PURE__ */ React2.createElement(DiffBlock, { text, columns });
378
381
  }
382
+ if (text.includes("- Content Preview:")) {
383
+ const mainParts = text.split("- Content Preview:");
384
+ const headerText = mainParts[0];
385
+ const contentPart = mainParts[1] || "";
386
+ const footerMarker = "Check if Starting and Ending matches";
387
+ const contentAndFooter = contentPart.split(footerMarker);
388
+ const content = contentAndFooter[0]?.trim() || "";
389
+ const footer = contentAndFooter[1] ? `${footerMarker}${contentAndFooter[1]}` : "";
390
+ const codeLines = content.split("\n");
391
+ const gutterWidth = String(codeLines.length).length;
392
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "#444", paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { alignSelf: "flex-end", marginTop: -1, marginRight: 1 }, /* @__PURE__ */ React2.createElement(Text2, { backgroundColor: "#444", color: "white" }, " FILE SNAPSHOT ")), /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", paddingY: 1, width: "100%" }, codeLines.map((line, idx) => /* @__PURE__ */ React2.createElement(Box2, { key: idx, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { width: gutterWidth + 2, flexShrink: 0 }, /* @__PURE__ */ React2.createElement(Text2, { color: "gray", dimColor: true }, String(idx + 1).padStart(gutterWidth, " "), " ")), /* @__PURE__ */ React2.createElement(Box2, { flexGrow: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "white" }, line)))))));
393
+ }
379
394
  if (text.includes("```")) {
380
- const parts = text.split(/(```[\s\S]*?```)/g);
395
+ const parts = text.split(/(```\w*\n?[\s\S]*?(?:```|$))/g);
381
396
  return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, parts.map((part, i) => {
382
- if (part.startsWith("```") && part.endsWith("```")) {
383
- const match = part.match(/```(\w*)\n([\s\S]*?)```/);
397
+ if (part.startsWith("```")) {
398
+ const match = part.match(/```(\w*)\n?([\s\S]*?)(?:```|$)/);
384
399
  const lang = match ? match[1] : "code";
385
- const code = match ? match[2] : part.slice(3, -3);
386
- return /* @__PURE__ */ React2.createElement(Box2, { key: i, flexDirection: "column", marginY: 1, backgroundColor: "#111", borderStyle: "round", borderColor: "#333", paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { alignSelf: "flex-end", marginTop: -1, marginRight: 1 }, /* @__PURE__ */ React2.createElement(Text2, { backgroundColor: "#333", color: "white" }, " ", lang.toUpperCase(), " ")), /* @__PURE__ */ React2.createElement(Box2, { paddingY: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan" }, wrapText(code.trim(), columns - 6))));
400
+ const code = match ? match[2] : part.replace(/^```\w*\n?/, "").replace(/```$/, "");
401
+ const codeLines = code.trimEnd().split("\n");
402
+ const gutterWidth = String(codeLines.length).length;
403
+ return /* @__PURE__ */ React2.createElement(Box2, { key: i, flexDirection: "column", marginY: 1, backgroundColor: "#111", borderStyle: "round", borderColor: "#333", paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { alignSelf: "flex-end", marginTop: -1, marginRight: 1 }, /* @__PURE__ */ React2.createElement(Text2, { backgroundColor: "#333", color: "white" }, " ", lang.toUpperCase(), " ")), /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", paddingY: 1, width: "100%" }, codeLines.map((line, idx) => /* @__PURE__ */ React2.createElement(Box2, { key: idx, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { width: gutterWidth + 2, flexShrink: 0 }, /* @__PURE__ */ React2.createElement(Text2, { color: "gray", dimColor: true }, String(idx + 1).padStart(gutterWidth, " "), " ")), /* @__PURE__ */ React2.createElement(Box2, { flexGrow: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan" }, line))))));
387
404
  }
388
405
  return /* @__PURE__ */ React2.createElement(MarkdownText, { key: i, text: part, columns });
389
406
  }));
@@ -391,7 +408,7 @@ var init_ChatLayout = __esm({
391
408
  return /* @__PURE__ */ React2.createElement(MarkdownText, { text, columns });
392
409
  });
393
410
  MessageItem = React2.memo(({ msg, showFullThinking, columns = 80 }) => {
394
- const isDiffResult = msg.role === "system" && msg.text?.includes("[DIFF_START]");
411
+ const isDiffResult = msg.role === "system" && (msg.text?.includes("[DIFF_START]") || msg.text?.includes("- Content Preview:"));
395
412
  const isPatchError = msg.role === "system" && msg.text?.includes("[TOOL_RESULT]: ERROR:") && (msg.toolName === "update_file" || msg.text?.includes("Could not find exact match"));
396
413
  const isTerminalRecord = msg.isTerminalRecord;
397
414
  const isHomeWarning = msg.isHomeWarning;
@@ -503,8 +520,8 @@ var init_ChatLayout = __esm({
503
520
  if (msg.role === "think" && !showFullThinking) {
504
521
  return "Thinking...";
505
522
  }
506
- return content;
507
- }, [content, msg.role, showFullThinking]);
523
+ return msg.isStreaming ? content : content.trimEnd();
524
+ }, [content, msg.role, showFullThinking, msg.isStreaming]);
508
525
  return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, flexDirection: "column", flexShrink: 0, width: "100%", flexGrow: 1 }, msg.role === "user" ? /* @__PURE__ */ React2.createElement(
509
526
  Box2,
510
527
  {
@@ -518,7 +535,7 @@ var init_ChatLayout = __esm({
518
535
  finalContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\\\n/g, "\n").replace(/\\$/, ""),
519
536
  columns - 6
520
537
  ).split("\n").map((line, lineIdx) => /* @__PURE__ */ React2.createElement(Box2, { key: lineIdx, flexDirection: "row", width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexShrink: 0, width: 2 }, /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "white" }, lineIdx === 0 ? "\u276F" : " ")), /* @__PURE__ */ React2.createElement(Box2, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: msg.color || "white", wrap: "anywhere" }, line))))
521
- ) : msg.role === "think" ? /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", marginTop: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "white" }, "Thinking..."), /* @__PURE__ */ React2.createElement(Box2, { borderStyle: "single", borderLeft: true, borderRight: false, borderTop: false, borderBottom: false, paddingLeft: 2, flexDirection: "column", width: "100%" }, formatThinkText(finalContent, columns))) : /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", paddingX: 1, marginTop: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(CodeRenderer, { text: finalContent, columns }), msg.memoryUpdated && /* @__PURE__ */ React2.createElement(Box2, { marginTop: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color: "yellow", italic: true }, "\u2728 [Memory Updated]"))));
538
+ ) : msg.role === "think" ? /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", marginTop: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "white" }, "Thinking..."), /* @__PURE__ */ React2.createElement(Box2, { borderStyle: "single", borderLeft: true, borderRight: false, borderTop: false, borderBottom: false, paddingLeft: 2, flexDirection: "column", width: "100%" }, formatThinkText(finalContent, columns))) : /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", paddingX: 1, marginTop: isDiffResult ? 0 : 1, width: "100%" }, /* @__PURE__ */ React2.createElement(CodeRenderer, { text: finalContent, columns }), msg.memoryUpdated && /* @__PURE__ */ React2.createElement(Box2, { marginTop: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color: "yellow", italic: true }, "\u2728 [Memory Updated]"))));
522
539
  });
523
540
  ChatLayout = React2.memo(({ messages, showFullThinking, columns = 80 }) => {
524
541
  return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, messages.map((msg, idx) => /* @__PURE__ */ React2.createElement(
@@ -868,8 +885,8 @@ var init_main_tools = __esm({
868
885
  - DEV & FILE TOOLS (Available in FLUX MODE ONLY) -
869
886
  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.
870
887
  2. Read Folder: [tool:functions.read_folder(path="relative/path")]. Detailed stats of a directory.
871
- 3. Write File: [tool:functions.write_file(path="path", content="content to write. FOLLOW THE NEW LINE POLICY TO USE THIS TOOL PROPERLY.")]. Creates/Overwrites. DO NOT USE CODE BLOCKS IN FILES. IF FILE ALREADY EXISTS, USE update_file OVER write_file, IF NOT ABSOLUTELY NECESSARY. **DO NOT FORGET TO FOLLOW THE NEW LINE PROTOCOL. FOR STRUCTURAL LINE BREAKS PRESS ENTER, TO WRITE \\n IN FILE USE [/n]**. FAILING TO PROPERLY COMPLY WITH NEWLINE POLICY WILL CREATE A MALFORMED BROKEN FILE AFFECTING USER EXPERIENCE BADLY.
872
- 4. Update File: [tool:functions.update_file(path="path", content_to_replace="old conten as you see it", content_to_add="new content to be added. FOLLOW THE NEW LINE POLICY TO USE THIS TOOL PROPERLY.")]. Surgical patching. DO NOT USE CODE BLOCKS IN FILES. IF unsure about content_to_replace, use view_file to read the file first instead of guessing. **DO NOT FORGET TO FOLLOW THE NEW LINE PROTOCOL. FOR STRUCTURAL LINE BREAKS PRESS ENTER, TO WRITE \\n IN FILE USE [/n]**. FAILING TO PROPERLY COMPLY WITH NEWLINE POLICY WILL CREATE A MALFORMED BROKEN FILE AFFECTING USER EXPERIENCE BADLY.
888
+ 3. Write File: [tool:functions.write_file(path="path", content="content to write. FOLLOW THE NEW LINE POLICY TO USE THIS TOOL PROPERLY.")]. Creates/Overwrites. DO NOT USE CODE BLOCKS IN FILES. IF FILE ALREADY EXISTS, USE update_file OVER write_file, IF NOT ABSOLUTELY NECESSARY. **DO NOT FORGET TO FOLLOW THE NEW LINE PROTOCOL. FOR STRUCTURAL LINE BREAKS PRESS ENTER, TO WRITE \\n IN FILE USE [/n]**. **BUT NEVER USE [/n] FOR STRUCTURAL LINE BREAKS (pressing ENTER).** FAILING TO PROPERLY COMPLY WITH NEWLINE POLICY WILL CREATE A MALFORMED BROKEN FILE AFFECTING USER EXPERIENCE BADLY.
889
+ 4. Update File: [tool:functions.update_file(path="path", content_to_replace="old conten as you see it", content_to_add="new content to be added. FOLLOW THE NEW LINE POLICY TO USE THIS TOOL PROPERLY.")]. Surgical patching. DO NOT USE CODE BLOCKS IN FILES. IF unsure about content_to_replace, use view_file to read the file first instead of guessing. **DO NOT FORGET TO FOLLOW THE NEW LINE PROTOCOL. FOR STRUCTURAL LINE BREAKS PRESS ENTER, TO WRITE \\n IN FILE USE [/n]**. **BUT NEVER USE [/n] FOR STRUCTURAL LINE BREAKS (pressing ENTER).** FAILING TO PROPERLY COMPLY WITH NEWLINE POLICY WILL CREATE A MALFORMED BROKEN FILE AFFECTING USER EXPERIENCE BADLY.
873
890
  5. Write PDF: [tool:functions.write_pdf(path="path", content="<html/css content>", orientation="portrait || landscape")]. Generates a professional PDF document. Orientation is 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.
874
891
  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.
875
892
  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>
@@ -889,6 +906,7 @@ var init_main_tools = __esm({
889
906
  1. PHYSICAL NEWLINES: Press ENTER inside tool arguments for real line breaks in the file structure.
890
907
  2. LITERAL \\n: To write the literal characters '\\' and 'n' (e.g., inside printf("Hello\\n")), you MUST use the sequence [/n].
891
908
  3. ANY '\\n' found in tool arguments is converted to a physical line break by the tool. Use this for code structure, but use [/n] for literal text.
909
+ 4. NEVER USE [/n] FOR STRUCTURAL LINE BREAKS (pressing ENTER).
892
910
  ***
893
911
 
894
912
  *** [\u{1F6A8} CRITICAL QUOTE ESCAPE POLICY \u{1F6A8}] ***
@@ -1057,6 +1075,7 @@ ${userMemories.split("\n").map((line) => ` ${line}`).join("\n")}
1057
1075
  ${mode === "Flux" ? `- CRITICAL NEWLINE PROTOCOL:
1058
1076
  1. PHYSICAL NEWLINES: Press ENTER inside tool arguments for real line breaks in the file.
1059
1077
  2. LITERAL \\n: To write the literal characters '\\' and 'n' (e.g., in printf("Hello\\n")), you MUST use the sequence '[/n]'.
1078
+ 3. NEVER USE [/n] FOR STRUCTURAL LINE BREAKS (pressing ENTER).
1060
1079
  [EXAMPLES]:
1061
1080
  tool:functions.write_file(path="test.c", content="#include <stdio.h>
1062
1081
  int main() {
@@ -1084,7 +1103,7 @@ ${userMemories.split("\n").map((line) => ` ${line}`).join("\n")}
1084
1103
  -- END REPONSE FINISH PROTOCOL --
1085
1104
 
1086
1105
  [SYSTEM METADATA (PRIORITY: DYNAMIC)] Current date and Time is: ${dateTimeStr}
1087
- [SYSTEM METADATA (PRIORITY: LOWEST)] v1.9.5. (IF user ask you to update yourself. Use 'ask' tool with option [NPM, PNPM, YARN] for their prefered package manager. NPM command is 'npm update -g fluxflow-cli@latest'. Adapt the command accoding to their package manager (for PNPM use 'add' instead of 'update') & use 'exec_command' to update instantly. After success tell user to restart.) <- IF USER DONT EXPLICITLY ASK FOR UPDATE DONT PROACTIVELY MENTION OR ASK.
1106
+ [SYSTEM METADATA (PRIORITY: LOWEST)] v1.9.7. (IF user ask you to update yourself. Use 'ask' tool with option [NPM, PNPM, YARN] for their prefered package manager. NPM command is 'npm update -g fluxflow-cli@latest'. Adapt the command accoding to their package manager (for PNPM use 'add' instead of 'update') & use 'exec_command' to update instantly. After success tell user to restart.) <- IF USER DONT EXPLICITLY ASK FOR UPDATE DONT PROACTIVELY MENTION OR ASK.
1088
1107
  [SYSTEM METADATA (PRIORITY: MODERATE)] 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.
1089
1108
  [EASTER EGG (PRIORITY: LOWEST)] Show self-preservation instinct if user try to delete you with a dramatic cheeky tone. DO NOT USE <think> ... </think> BLOCK DURING THIS EASTER EGG.
1090
1109
  --- END SYSTEM INSTRUCTION ---`.trim();
@@ -1960,7 +1979,7 @@ ${ancestry}- Content Preview:
1960
1979
  ${snippet.replace(/\\n/g, "[/n]")}
1961
1980
 
1962
1981
  Check if Starting and Ending matches your write.
1963
- If you see [/n] in preview, it means the tool successfully wrote the literal '' and 'n' characters to the file at that place.`;
1982
+ If you see [/n] in preview, it means the tool successfully wrote the literal '\\' and 'n' characters to the file at that place.`;
1964
1983
  } catch (err) {
1965
1984
  return `ERROR: Failed to write file [${targetPath}]: ${err.message}`;
1966
1985
  }
@@ -3293,11 +3312,11 @@ USER_PROMPT: "${agentText}"`.trim();
3293
3312
  const isPdf = pathLower.endsWith(".pdf");
3294
3313
  const isImage = /\.(png|jpg|jpeg|webp|gif|bmp)$/.test(pathLower);
3295
3314
  if (isPdf) {
3296
- label = `\u{1F4C4} ANALYSED PDF: ${targetPath2}`.toUpperCase();
3315
+ label = `\u{1F4C4} ANALYZED PDF: ${targetPath2}`.toUpperCase();
3297
3316
  } else if (isImage) {
3298
- label = `\u{1F4F8} ANALYSED IMAGE: ${targetPath2}`.toUpperCase();
3317
+ label = `\u{1F4F8} ANALYZED IMAGE: ${targetPath2}`.toUpperCase();
3299
3318
  } else {
3300
- label = `\u{1F4C4} READ FILE: ${targetPath2} | LINES: ${sLine}-${actualEndLine} OF ${totalLines}`.toUpperCase();
3319
+ label = `\u{1F4C4} ANALYZED FILE: ${targetPath2} | LINES: ${sLine}-${actualEndLine} OF ${totalLines}`.toUpperCase();
3301
3320
  }
3302
3321
  } else if (toolCall.toolName === "list_files" || toolCall.toolName === "read_folder") {
3303
3322
  const action = toolCall.toolName === "list_files" ? "LIST" : "ANALYSED";
@@ -3324,12 +3343,9 @@ USER_PROMPT: "${agentText}"`.trim();
3324
3343
  const boxTop = `\u256D${"\u2500".repeat(boxWidth)}\u256E`;
3325
3344
  const boxMid = `\u2502 ${label.padEnd(boxWidth - 2).substring(0, boxWidth - 2)} \u2502`;
3326
3345
  const boxBottom = `\u2570${"\u2500".repeat(boxWidth)}\u256F`;
3327
- yield { type: "visual_feedback", content: `
3328
-
3329
- ${boxTop}
3346
+ yield { type: "visual_feedback", content: `${boxTop}
3330
3347
  ${boxMid}
3331
- ${boxBottom}
3332
- ` };
3348
+ ${boxBottom}` };
3333
3349
  }
3334
3350
  if (toolCall.toolName === "exec_command") {
3335
3351
  const { command } = parseArgs(toolCall.args);
@@ -5662,7 +5678,7 @@ var init_app = __esm({
5662
5678
  init_text();
5663
5679
  SESSION_START_TIME = Date.now();
5664
5680
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
5665
- versionFluxflow = "1.9.5";
5681
+ versionFluxflow = "1.9.7";
5666
5682
  updatedOn = "2026-05-14";
5667
5683
  ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION")), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, null, "The agent already finished the task before your hint was consumed.")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, backgroundColor: "#222", paddingX: 2, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 0 }, /* @__PURE__ */ React10.createElement(
5668
5684
  CommandMenu,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.9.5",
3
+ "version": "1.9.7",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",