fluxflow-cli 2.15.2 → 2.16.0

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 +320 -136
  2. package/package.json +2 -2
package/dist/fluxflow.js CHANGED
@@ -2104,7 +2104,7 @@ var init_build = __esm({
2104
2104
 
2105
2105
  // src/utils/text.js
2106
2106
  import os2 from "os";
2107
- var wrapText, formatTokens, truncatePath, parsePatchPairs, applyPatches, generateHighFidelityDiff, parseLineInfo, getSimilarity, alignChangeGroup, blocksCache, streamingBlocksCache, MAX_CACHE_SIZE, CHUNK_SIZE, indexBlockIntoMap, parseMessageToBlocks, TOOL_LABELS, REGEX_INITIAL_THINK, REGEX_INITIAL_TOOL, REGEX_SYSTEM, REGEX_THINK, REGEX_ANSWER, REGEX_TOOL_RES, REGEX_SUCCESS_ERROR, REGEX_TURN_1, REGEX_END, REGEX_TURN_2, REGEX_TURN_3, REGEX_OPEN_BRACKET, REGEX_RESPONDED, REGEX_PROMPTED, REGEX_ARROWS, REGEX_ARROWS_L, REGEX_ARROWS_U, REGEX_ARROWS_D, REGEX_ARROWS_LR, REGEX_TERMINAL, REGEX_TOOLS, cleanSignals, clearBlocksCache;
2107
+ var wrapText, formatTokens, truncatePath, parsePatchPairs, applyPatches, generateHighFidelityDiff, parseLineInfo, getSimilarity, alignChangeGroup, blocksCache, streamingBlocksCache, MAX_CACHE_SIZE, CHUNK_SIZE, indexBlockIntoMap, parseMessageToBlocks, TOOL_LABELS, REGEX_INITIAL_THINK, REGEX_INITIAL_TOOL, REGEX_CLEAN_SIGNALS, REGEX_ARROWS_ALL, REGEX_TOOLS, cleanSignals, clearBlocksCache;
2108
2108
  var init_text = __esm({
2109
2109
  "src/utils/text.js"() {
2110
2110
  init_paths();
@@ -2571,15 +2571,31 @@ var init_text = __esm({
2571
2571
  if (existing && existing.text === textContent && existing.type === type && !!existing.isActiveBlock === !!extra.isActiveBlock && !!existing.isStreaming === !!extra.isStreaming && existing.pairContent === extra.pairContent) {
2572
2572
  return existing;
2573
2573
  }
2574
+ const flatText = typeof textContent === "string" ? (" " + textContent).slice(1) : textContent;
2575
+ const flatExtra = { ...extra };
2576
+ if (typeof flatExtra.pairContent === "string") {
2577
+ flatExtra.pairContent = (" " + flatExtra.pairContent).slice(1);
2578
+ }
2579
+ if (Array.isArray(flatExtra.wrappedLines)) {
2580
+ flatExtra.wrappedLines = flatExtra.wrappedLines.map((l) => typeof l === "string" ? (" " + l).slice(1) : l);
2581
+ }
2574
2582
  return {
2575
2583
  key,
2576
- msg,
2584
+ isStreamingMsg: !!msg.isStreaming,
2585
+ workedDuration: msg.workedDuration,
2577
2586
  type,
2578
- text: textContent,
2579
- ...extra
2587
+ text: flatText,
2588
+ msg: type === "full-message" ? msg : void 0,
2589
+ // Only full-message requires role/meta checks
2590
+ ...flatExtra
2580
2591
  };
2581
2592
  };
2582
2593
  if (text.includes("- Content Preview:")) {
2594
+ let extension = "";
2595
+ const fileMatch = text.match(/File\s+\[(.*?)\]/i);
2596
+ if (fileMatch) {
2597
+ extension = fileMatch[1].split(".").pop().toLowerCase();
2598
+ }
2583
2599
  const mainParts = text.split("- Content Preview:");
2584
2600
  const contentPart = mainParts[1] || "";
2585
2601
  const footerMarker = "[SYSTEM] Check the content preview for verification [/SYSTEM]";
@@ -2595,18 +2611,21 @@ var init_text = __esm({
2595
2611
  writeChunk = [];
2596
2612
  completedBlocks2.push(batch.length === 1 ? batch[0] : {
2597
2613
  key: `${batch[0].key}-chunk`,
2598
- msg,
2599
2614
  type: "chunk",
2600
2615
  blocks: batch
2601
2616
  });
2602
2617
  };
2618
+ const innerWidth = columns - (gutterWidth + 6);
2603
2619
  codeLines.forEach((line, idx) => {
2604
2620
  const isLast = idx === codeLines.length - 1;
2621
+ const wrappedLines = wrapText(line, innerWidth).split("\n");
2605
2622
  const block = getBlock(`${msg.id || Date.now()}-write-line-${idx}`, "write-line", line, {
2606
2623
  gutterWidth,
2607
2624
  lineNum: idx + 1,
2608
2625
  isFirstLine: idx === 0,
2609
- isLastLine: isLast
2626
+ isLastLine: isLast,
2627
+ extension,
2628
+ wrappedLines
2610
2629
  });
2611
2630
  if (isLast && msg.isStreaming) {
2612
2631
  flushWrite();
@@ -2646,17 +2665,22 @@ var init_text = __esm({
2646
2665
  diffChunk = [];
2647
2666
  completedBlocks2.push(batch.length === 1 ? batch[0] : {
2648
2667
  key: `${batch[0].key}-chunk`,
2649
- msg,
2650
2668
  type: "chunk",
2651
2669
  blocks: batch
2652
2670
  });
2653
2671
  };
2654
2672
  diffLines.forEach((line, i) => {
2655
2673
  const isLast = i === diffLines.length - 1;
2674
+ const parsed = parsedLines[i].parsed;
2675
+ let wrappedLines = null;
2676
+ if (parsed) {
2677
+ wrappedLines = wrapText(parsed.content, columns - 17).split("\n");
2678
+ }
2656
2679
  const block = getBlock(`${msg.id || Date.now()}-diff-${i}`, "diff-line", line, {
2657
2680
  isFirstLine: i === 0,
2658
2681
  isLastLine: isLast,
2659
- pairContent: parsedLines[i].pairContent
2682
+ pairContent: parsedLines[i].pairContent,
2683
+ wrappedLines
2660
2684
  });
2661
2685
  if (isLast && msg.isStreaming) {
2662
2686
  flushDiff();
@@ -2686,32 +2710,36 @@ var init_text = __esm({
2686
2710
  pendingChunkType = null;
2687
2711
  completedBlocks.push(batch.length === 1 ? batch[0] : {
2688
2712
  key: `${msg.id || "x"}-chunk-${batch[0].key}`,
2689
- msg,
2690
2713
  type: "chunk",
2691
2714
  blocks: batch
2692
2715
  });
2693
2716
  };
2694
- const enqueue = (block) => {
2717
+ const enqueue = (block, isLastOfMessage = false) => {
2695
2718
  if (pendingChunkType !== null && pendingChunkType !== block.type) flushPending();
2696
2719
  pendingChunk.push(block);
2697
2720
  pendingChunkType = block.type;
2698
- if (pendingChunk.length >= CHUNK_SIZE) flushPending();
2721
+ if (pendingChunk.length >= CHUNK_SIZE) {
2722
+ if (msg.isStreaming && isLastOfMessage) return;
2723
+ flushPending();
2724
+ }
2699
2725
  };
2700
2726
  if (msg.role === "think") {
2701
2727
  completedBlocks.push(getBlock(`${msg.id}-header`, "think-header", ""));
2702
2728
  const lines = text.split("\n");
2703
2729
  lines.forEach((line, idx) => {
2704
- enqueue(getBlock(`${msg.id}-${idx}`, "think-line", line, {}));
2730
+ const isLast = idx === lines.length - 1;
2731
+ enqueue(getBlock(`${msg.id}-${idx}`, "think-line", line, {}), isLast);
2705
2732
  });
2706
2733
  if (!msg.isStreaming) {
2707
2734
  flushPending();
2708
- completedBlocks.push({ key: `${msg.id}-footer-padding`, msg, type: "think-footer-padding", text: "" });
2735
+ completedBlocks.push({ key: `${msg.id}-footer-padding`, type: "think-footer-padding", text: "" });
2709
2736
  }
2710
2737
  } else {
2711
2738
  const lines = text.split("\n");
2712
2739
  let inTable = false;
2713
2740
  let tableLines = [];
2714
2741
  let inCodeBlock = false;
2742
+ let currentLang = "";
2715
2743
  let codeLineNum = 0;
2716
2744
  let codeStartIdx = 0;
2717
2745
  lines.forEach((line, idx) => {
@@ -2721,17 +2749,17 @@ var init_text = __esm({
2721
2749
  if (inCodeBlock) {
2722
2750
  if (isCodeBlockMarker) {
2723
2751
  inCodeBlock = false;
2724
- enqueue(getBlock(`${msg.id}-code-close-${codeStartIdx}`, "code-fence-close", "", {}));
2752
+ enqueue(getBlock(`${msg.id}-code-close-${codeStartIdx}`, "code-fence-close", "", {}), isLast);
2725
2753
  } else {
2726
2754
  codeLineNum++;
2727
- enqueue(getBlock(`${msg.id}-code-line-${idx}`, "code-line", line, { lineNum: codeLineNum }));
2755
+ enqueue(getBlock(`${msg.id}-code-line-${idx}`, "code-line", line, { lineNum: codeLineNum, lang: currentLang }), isLast);
2728
2756
  }
2729
2757
  } else if (isCodeBlockMarker) {
2730
2758
  inCodeBlock = true;
2731
2759
  codeStartIdx = idx;
2732
2760
  codeLineNum = 0;
2733
- const lang = line.trim().replace(/^```/, "").trim();
2734
- enqueue(getBlock(`${msg.id}-code-open-${idx}`, "code-fence-open", lang, {}));
2761
+ currentLang = line.trim().replace(/^```/, "").trim();
2762
+ enqueue(getBlock(`${msg.id}-code-open-${idx}`, "code-fence-open", currentLang, {}), isLast);
2735
2763
  } else if (isTableRow) {
2736
2764
  inTable = true;
2737
2765
  tableLines.push(line);
@@ -2750,7 +2778,7 @@ var init_text = __esm({
2750
2778
  inTable = false;
2751
2779
  tableLines = [];
2752
2780
  }
2753
- enqueue(getBlock(`${msg.id}-${idx}`, "agent-line", line, {}));
2781
+ enqueue(getBlock(`${msg.id}-${idx}`, "agent-line", line, {}), isLast);
2754
2782
  }
2755
2783
  });
2756
2784
  if (!msg.isStreaming && msg.workedDuration) {
@@ -2761,7 +2789,6 @@ var init_text = __esm({
2761
2789
  if (msg.isStreaming && pendingChunk.length > 0) {
2762
2790
  activeBlock = pendingChunk.length === 1 ? pendingChunk[0] : {
2763
2791
  key: `${msg.id || "x"}-chunk-active-${pendingChunk[0].key}`,
2764
- msg,
2765
2792
  type: "chunk",
2766
2793
  blocks: pendingChunk
2767
2794
  };
@@ -2820,24 +2847,8 @@ var init_text = __esm({
2820
2847
  };
2821
2848
  REGEX_INITIAL_THINK = /<\/think>(\r?\n){2}/gi;
2822
2849
  REGEX_INITIAL_TOOL = /(\r?\n){2}(?=\[?(?:tool:functions|tool\.functions|\s*turn\s*:))/gi;
2823
- REGEX_SYSTEM = /\[SYSTEM\][\s\S]*?\[\/SYSTEM\]/gi;
2824
- REGEX_THINK = /<(think|thought)>[\s\S]*?(?:<\/(think|thought)>|$)/gi;
2825
- REGEX_ANSWER = /\[ANSWER\][\s\S]*?(?:\[\/ANSWER\]|$)/gi;
2826
- REGEX_TOOL_RES = /\[TOOL RESULT\]:?\s*/gi;
2827
- REGEX_SUCCESS_ERROR = /^\s*(SUCCESS|ERROR):.*(\r?\n)?/gm;
2828
- REGEX_TURN_1 = /\[\s*turn\s*:\s*(continue|finish)\s*\]/gi;
2829
- REGEX_END = /\[\[END\]\]/gi;
2830
- REGEX_TURN_2 = /\[\s*turn\s*:?.*?$/gi;
2831
- REGEX_TURN_3 = /\n\s*turn\s*:?.*?$/gi;
2832
- REGEX_OPEN_BRACKET = /\[\s*$/gi;
2833
- REGEX_RESPONDED = /\n\nResponded on .*/g;
2834
- REGEX_PROMPTED = /\n\n\[Prompted on: .*\]/g;
2835
- REGEX_ARROWS = /(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)/gi;
2836
- REGEX_ARROWS_L = /(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)/gi;
2837
- REGEX_ARROWS_U = /(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)/gi;
2838
- REGEX_ARROWS_D = /(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)/gi;
2839
- REGEX_ARROWS_LR = /(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi;
2840
- REGEX_TERMINAL = /@\[TerminalName:.*?, ProcessId:.*?\]/gi;
2850
+ REGEX_CLEAN_SIGNALS = /\[SYSTEM\][\s\S]*?\[\/SYSTEM\]|<(think|thought)>[\s\S]*?(?:<\/(think|thought)>|$)|\[ANSWER\][\s\S]*?(?:\[\/ANSWER\]|$)|\[TOOL RESULT\]:?\s*|^\s*(SUCCESS|ERROR):.*(\r?\n)?|\[\s*turn\s*:\s*(continue|finish)\s*\]|\[\[END\]\]|\[\s*turn\s*:?.*?$|\n\s*turn\s*:?.*?$|\[\s*$|\n\nResponded on .*|\n\n\[Prompted on: .*\]|@\[TerminalName:.*?, ProcessId:.*?\]/gmi;
2851
+ REGEX_ARROWS_ALL = /(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)|(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)|(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)|(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)|(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi;
2841
2852
  REGEX_TOOLS = /\b(write_file|update_file|read_folder|view_file|exec_command|web_search|web_scrape|search_keyword|write_pdf|write_docx|generate_image)\b/gi;
2842
2853
  cleanSignals = (text) => {
2843
2854
  if (!text) return text;
@@ -2895,7 +2906,18 @@ var init_text = __esm({
2895
2906
  }
2896
2907
  }
2897
2908
  }
2898
- return result.replaceAll(REGEX_SYSTEM, "").replaceAll(REGEX_THINK, "").replace(REGEX_ANSWER, "").replaceAll(REGEX_TOOL_RES, "").replaceAll(REGEX_SUCCESS_ERROR, "").replaceAll(REGEX_TURN_1, "").replaceAll(REGEX_END, "").replaceAll(REGEX_TURN_2, "").replaceAll(REGEX_TURN_3, "").replaceAll(REGEX_OPEN_BRACKET, "").replaceAll(REGEX_RESPONDED, "").replaceAll(REGEX_PROMPTED, "").replaceAll(REGEX_ARROWS, "\u2192").replaceAll(REGEX_ARROWS_L, "\u2190").replaceAll(REGEX_ARROWS_U, "\u2191").replaceAll(REGEX_ARROWS_D, "\u2193").replaceAll(REGEX_ARROWS_LR, "\u2194").replaceAll(REGEX_TERMINAL, "").replaceAll(REGEX_TOOLS, (match) => TOOL_LABELS[match.toLowerCase()] || match).trim();
2909
+ result = result.replace(REGEX_CLEAN_SIGNALS, "");
2910
+ result = result.replace(REGEX_ARROWS_ALL, (match) => {
2911
+ const lower = match.toLowerCase();
2912
+ if (lower.includes("leftrightarrow")) return "\u2194";
2913
+ if (lower.includes("rightarrow")) return "\u2192";
2914
+ if (lower.includes("leftarrow")) return "\u2190";
2915
+ if (lower.includes("uparrow")) return "\u2191";
2916
+ if (lower.includes("downarrow")) return "\u2193";
2917
+ return match;
2918
+ });
2919
+ result = result.replace(REGEX_TOOLS, (match) => TOOL_LABELS[match.toLowerCase()] || match);
2920
+ return result.trim();
2899
2921
  };
2900
2922
  clearBlocksCache = () => {
2901
2923
  blocksCache.clear();
@@ -3509,7 +3531,7 @@ var init_MultilineInput = __esm({
3509
3531
  } else {
3510
3532
  pasteTimerRef.current = setTimeout(() => {
3511
3533
  finalizePasteTransaction();
3512
- }, 100);
3534
+ }, 80);
3513
3535
  }
3514
3536
  } else {
3515
3537
  adjustPasteBlocksOnEdit(curIdx, cleanInput.length);
@@ -3669,14 +3691,13 @@ var init_TerminalBox = __esm({
3669
3691
  return resultLines.join("\n");
3670
3692
  };
3671
3693
  const cleanOutput = processPTY(output).replace(/\n{3,}/g, "\n\n");
3672
- const displayOutput = isPty ? cleanOutput : cleanOutput ? wrapText(cleanOutput, columns - 6) : "";
3694
+ const rawLines = isPty ? cleanOutput ? cleanOutput.split("\n") : [] : cleanOutput ? wrapText(cleanOutput, columns - 6) : [];
3673
3695
  const [isExpanded, setIsExpanded] = useState3(false);
3674
3696
  useInput2((input, key) => {
3675
3697
  if (isFocused && key.ctrl && (input === "o" || input === "")) {
3676
3698
  setIsExpanded((prev) => !prev);
3677
3699
  }
3678
3700
  }, { isActive: isFocused });
3679
- const rawLines = displayOutput ? displayOutput.split("\n") : [];
3680
3701
  const limit = Math.max(5, completed ? terminalHeight - 10 : terminalHeight - 20);
3681
3702
  const hasCollapsibleContent = rawLines.length > limit;
3682
3703
  const collapsedCount = rawLines.length - limit;
@@ -3979,7 +4000,7 @@ ${coloredArt[7]}`;
3979
4000
  import React4, { useState as useState4, useEffect as useEffect3, useRef as useRef2 } from "react";
3980
4001
  import { Box as Box3, Text as Text4 } from "ink";
3981
4002
  import { diffWordsWithSpace } from "diff";
3982
- var useStreamingText, formatThinkText, REGEX_MD_TOKENS, REGEX_LATEX_FRAC, REGEX_LATEX_STYLE, parseMathSymbols, renderLatexText, InlineMarkdown, TableRenderer, MarkdownText, DiffLine, DiffBlock, CodeRenderer, formatThinkingDuration, MessageItem, BlockItem, ChatLayout;
4003
+ var useStreamingText, formatThinkText, REGEX_MD_TOKENS, REGEX_LATEX_FRAC, REGEX_LATEX_STYLE, parseMathSymbols, SYNTAX_KEYWORDS, SYNTAX_RULES, REGEX_SYNTAX, tokenCache, MAX_TOKEN_CACHE_SIZE, tokenizeLine, renderHighlightedLine, renderLatexText, InlineMarkdown, TableRenderer, MarkdownText, DiffLine, DiffBlock, CodeRenderer, formatThinkingDuration, MessageItem, BlockItem, ChatLayout;
3983
4004
  var init_ChatLayout = __esm({
3984
4005
  "src/components/ChatLayout.jsx"() {
3985
4006
  init_TerminalBox();
@@ -4020,6 +4041,74 @@ var init_ChatLayout = __esm({
4020
4041
  parseMathSymbols = (content) => {
4021
4042
  return content.replace(/\\multiply|\\mul|\\times/g, "\xD7").replace(/\\div/g, "\xF7").replace(/\\cdot/g, "\u22C5").replace(/\\infty/g, "\u221E").replace(/\\pm/g, "\xB1").replace(/\\leq/g, "\u2264").replace(/\\geq/g, "\u2265").replace(/\\neq/g, "\u2260").replace(/\\sqrt\s*\{([^}]+)\}/g, "\u221A($1)").replace(/\\sqrt\s*(\w+|\d+)/g, "\u221A($1)").replace(/\\alpha/g, "\u03B1").replace(/\\beta/g, "\u03B2").replace(/\\theta/g, "\u03B8").replace(/\\pi/g, "\u03C0").replace(/\\approx/g, "\u2248").replace(/\\Delta/g, "\u0394").replace(/\\sigma/g, "\u03C3").replace(/\\sum/g, "\u03A3").replace(/\\prod/g, "\u03A0").replace(/\\rightarrow|\\to/g, "\u2192").replace(/\\left\b|\\right\b/g, "").replace(/\\left\(|\\right\)/g, (match) => match.includes("left") ? "(" : ")").replace(/\\left\[|\\right\]/g, (match) => match.includes("left") ? "[" : "]").replace(/\\\{|\\\}/g, (match) => match.includes("{") ? "{" : "}").replace(/\\text\s*\{([^}]+)\}/g, "$1").replace(/\\text\s+(\w+)/g, "$1").replace(/\\%/g, "%");
4022
4043
  };
4044
+ SYNTAX_KEYWORDS = /\b(const|let|var|function|return|if|else|for|while|do|switch|case|break|continue|import|export|from|default|class|extends|new|this|typeof|instanceof|try|catch|finally|throw|async|await|yield|public|private|protected|static|void|int|float|double|char|bool|boolean|def|elif|fn|pub|mut|struct|impl|enum|type|interface|package|namespace|using|include|define|nil|None|self|lambda)\b/;
4045
+ SYNTAX_RULES = [
4046
+ // Include paths
4047
+ /((?<=\binclude\s+)(?:<[^>]+>|"[^"]+"))/.source,
4048
+ // Import paths
4049
+ /((?<=\b(?:from|import|require\s*\(\s*)\s*)(?:'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"))/.source,
4050
+ // Comments
4051
+ /(\/\/.*|#.*)/.source,
4052
+ // Strings
4053
+ /("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^\`\\])*`)/.source,
4054
+ SYNTAX_KEYWORDS.source,
4055
+ /\b([a-zA-Z_][a-zA-Z0-9_]*)(?=\s*\()/.source,
4056
+ /\b(true|false|null|undefined|nil|None)\b/.source,
4057
+ /\b(\d+(?:\.\d+)?|0x[0-9a-fA-F]+)\b/.source
4058
+ ];
4059
+ REGEX_SYNTAX = new RegExp(SYNTAX_RULES.join("|"), "g");
4060
+ tokenCache = /* @__PURE__ */ new Map();
4061
+ MAX_TOKEN_CACHE_SIZE = 1e3;
4062
+ tokenizeLine = (line, lang) => {
4063
+ if (!line) return [];
4064
+ const cacheKey = `${lang}:${line}`;
4065
+ if (tokenCache.has(cacheKey)) {
4066
+ return tokenCache.get(cacheKey);
4067
+ }
4068
+ let lastIndex = 0;
4069
+ const tokens = [];
4070
+ let match;
4071
+ REGEX_SYNTAX.lastIndex = 0;
4072
+ while ((match = REGEX_SYNTAX.exec(line)) !== null) {
4073
+ const matchText = match[0];
4074
+ const matchIndex = match.index;
4075
+ if (matchIndex > lastIndex) {
4076
+ tokens.push({ text: line.substring(lastIndex, matchIndex) });
4077
+ }
4078
+ let color = void 0;
4079
+ let bold = false;
4080
+ if (match[1] || match[2]) {
4081
+ color = "#ce9178";
4082
+ } else if (match[3]) {
4083
+ color = "#9ece6a";
4084
+ } else if (match[4]) {
4085
+ color = "#fcfca4";
4086
+ } else if (match[5]) {
4087
+ color = "#ff7b72";
4088
+ bold = true;
4089
+ } else if (match[6]) {
4090
+ color = "#b392f0";
4091
+ } else if (match[7] || match[8]) {
4092
+ color = "#ff9e64";
4093
+ }
4094
+ tokens.push({ text: matchText, color, bold });
4095
+ lastIndex = REGEX_SYNTAX.lastIndex;
4096
+ }
4097
+ if (lastIndex < line.length) {
4098
+ tokens.push({ text: line.substring(lastIndex) });
4099
+ }
4100
+ if (tokenCache.size >= MAX_TOKEN_CACHE_SIZE) {
4101
+ const firstKey = tokenCache.keys().next().value;
4102
+ tokenCache.delete(firstKey);
4103
+ }
4104
+ tokenCache.set(cacheKey, tokens);
4105
+ return tokens;
4106
+ };
4107
+ renderHighlightedLine = (line, lang, defaultColor = void 0) => {
4108
+ if (!line) return /* @__PURE__ */ React4.createElement(Text4, null, " ");
4109
+ const tokens = tokenizeLine(line, lang);
4110
+ return /* @__PURE__ */ React4.createElement(Text4, { color: defaultColor }, tokens.map((token, idx) => /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: token.color || defaultColor, bold: token.bold }, token.text)));
4111
+ };
4023
4112
  renderLatexText = (content, key) => {
4024
4113
  if (!content) return null;
4025
4114
  let formatted = content.replace(REGEX_LATEX_FRAC, "($1/$2)");
@@ -4166,15 +4255,16 @@ var init_ChatLayout = __esm({
4166
4255
  } else {
4167
4256
  content = wrapText(trimmed, columns - 4);
4168
4257
  }
4258
+ const linesOfContent = content.split("\n");
4169
4259
  result.push(
4170
- /* @__PURE__ */ React4.createElement(Box3, { key: i, width: "100%" }, /* @__PURE__ */ React4.createElement(InlineMarkdown, { text: content, color, italic }))
4260
+ /* @__PURE__ */ React4.createElement(Box3, { key: i, flexDirection: "column", width: "100%" }, linesOfContent.map((l, lIdx) => /* @__PURE__ */ React4.createElement(InlineMarkdown, { key: lIdx, text: l, color, italic })))
4171
4261
  );
4172
4262
  }
4173
4263
  });
4174
4264
  flushBuffers("final");
4175
4265
  return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", width: columns - 2 }, result);
4176
4266
  });
4177
- DiffLine = React4.memo(({ line, pairContent, parentText, columns = 80 }) => {
4267
+ DiffLine = React4.memo(({ line, pairContent, parentText, columns = 80, extension }) => {
4178
4268
  const isContext = line.includes("[UI_CONTEXT]");
4179
4269
  const cleanLine = line.replace("[UI_CONTEXT]", "");
4180
4270
  if (isContext && cleanLine.includes("\u2550")) {
@@ -4186,37 +4276,6 @@ var init_ChatLayout = __esm({
4186
4276
  }
4187
4277
  const { isR: isRemoval, isA: isAddition, num: lineNum, content } = parsedCurrent;
4188
4278
  let finalPairContent = pairContent;
4189
- if (!finalPairContent && parentText && (isRemoval || isAddition)) {
4190
- const match = parentText.match(/\[DIFF_START\]([\s\S]*?)(?:\[DIFF_END\]|$)/);
4191
- const diffBody = match ? match[1].trim() : "";
4192
- const diffLines = diffBody.split("\n").map((l) => l.replace(/\r$/, ""));
4193
- const parsedLines = diffLines.map((l) => {
4194
- return {
4195
- line: l,
4196
- parsed: parseLineInfo(l),
4197
- pairContent: null
4198
- };
4199
- });
4200
- let currentGroup = [];
4201
- for (let idx = 0; idx < parsedLines.length; idx++) {
4202
- const item = parsedLines[idx];
4203
- if (item.parsed && (item.parsed.isR || item.parsed.isA)) {
4204
- currentGroup.push(item);
4205
- } else {
4206
- if (currentGroup.length > 0) {
4207
- alignChangeGroup(currentGroup);
4208
- currentGroup = [];
4209
- }
4210
- }
4211
- }
4212
- if (currentGroup.length > 0) {
4213
- alignChangeGroup(currentGroup);
4214
- }
4215
- const matchedItem = parsedLines.find((item) => item.parsed && item.parsed.num === lineNum && item.parsed.isR === isRemoval);
4216
- if (matchedItem) {
4217
- finalPairContent = matchedItem.pairContent;
4218
- }
4219
- }
4220
4279
  let words = [];
4221
4280
  if (finalPairContent !== void 0 && finalPairContent !== null) {
4222
4281
  const oldStr = isRemoval ? content : finalPairContent;
@@ -4235,19 +4294,21 @@ var init_ChatLayout = __esm({
4235
4294
  const displayPrefix = isRemoval ? "-" : isAddition ? "+" : " ";
4236
4295
  const renderInlineDiff = () => {
4237
4296
  if (isPureUnpairedBlock) {
4238
- const blockColor = isRemoval ? "#ff3333" : "#33ff66";
4239
- return /* @__PURE__ */ React4.createElement(Text4, { color: blockColor }, wrapText(content, columns - 14));
4297
+ const blockColor = isRemoval ? "#ffdddd" : "#ddffdd";
4298
+ const wrappedLines = wrapText(content, columns - 14).split("\n");
4299
+ return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, blockColor))));
4240
4300
  }
4241
4301
  if (!(isRemoval || isAddition) || words.length === 0 || !hasInlineChange) {
4242
4302
  const textColor = isRemoval ? "#885555" : isAddition ? "#558866" : "gray";
4243
- return /* @__PURE__ */ React4.createElement(Text4, { color: textColor }, wrapText(content, columns - 14));
4303
+ const wrappedLines = wrapText(content, columns - 14).split("\n");
4304
+ return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, textColor))));
4244
4305
  }
4245
4306
  return /* @__PURE__ */ React4.createElement(Text4, { wrap: "anywhere" }, words.map((part, idx) => {
4246
4307
  const isWhitespace = /^\s+$/.test(part.value);
4247
4308
  if (isRemoval) {
4248
4309
  const isSurroundedByRemoval = words[idx - 1]?.removed || words[idx + 1]?.removed;
4249
4310
  if (part.removed || isWhitespace && isSurroundedByRemoval) {
4250
- return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "#ff3333" }, part.value);
4311
+ return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "#ff3333", backgroundColor: "#5a1818" }, part.value);
4251
4312
  }
4252
4313
  if (part.added) return null;
4253
4314
  return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "#885555" }, part.value);
@@ -4255,7 +4316,7 @@ var init_ChatLayout = __esm({
4255
4316
  if (isAddition) {
4256
4317
  const isSurroundedByAddition = words[idx - 1]?.added || words[idx + 1]?.added;
4257
4318
  if (part.added || isWhitespace && isSurroundedByAddition) {
4258
- return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "#33ff66" }, part.value);
4319
+ return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "#33ff66", backgroundColor: "#185a25" }, part.value);
4259
4320
  }
4260
4321
  if (part.removed) return null;
4261
4322
  return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "#558866" }, part.value);
@@ -4265,8 +4326,8 @@ var init_ChatLayout = __esm({
4265
4326
  };
4266
4327
  return /* @__PURE__ */ React4.createElement(Box3, { backgroundColor: "#1a1a1a", paddingX: 1, width: columns }, /* @__PURE__ */ React4.createElement(Box3, { width: 3, flexShrink: 0, justifyContent: "flex-end" }, /* @__PURE__ */ React4.createElement(Text4, { color: finalNumColor }, lineNum)), /* @__PURE__ */ React4.createElement(Box3, { width: 1, flexShrink: 0, marginLeft: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: finalPrefixColor }, displayPrefix)), /* @__PURE__ */ React4.createElement(Box3, { marginLeft: 1, backgroundColor: innerBgColor, flexShrink: 1 }, renderInlineDiff()));
4267
4328
  });
4268
- DiffBlock = React4.memo(({ text, columns = 80 }) => {
4269
- const match = text.match(/\[DIFF_START\]([\s\S]*?)\[DIFF_END\]/);
4329
+ DiffBlock = React4.memo(({ text, columns = 80, extension }) => {
4330
+ const match = text.match(/\[DIFF_START\]([\s\S]*?)(?:\[DIFF_END\]|$)/);
4270
4331
  const diffBody = match ? match[1].trim() : "";
4271
4332
  const diffLines = diffBody.split("\n");
4272
4333
  const parsedLines = diffLines.map((line) => {
@@ -4297,14 +4358,20 @@ var init_ChatLayout = __esm({
4297
4358
  key: i,
4298
4359
  line: item.line,
4299
4360
  pairContent: item.pairContent,
4300
- columns: columns - 3
4361
+ columns: columns - 3,
4362
+ extension
4301
4363
  }
4302
4364
  )), /* @__PURE__ */ React4.createElement(Box3, { backgroundColor: "#1a1a1a", paddingX: 1, width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: 3, flexShrink: 0 }), /* @__PURE__ */ React4.createElement(Box3, { width: 1, flexShrink: 0, marginLeft: 1 }), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React4.createElement(Text4, null, " ")))));
4303
4365
  });
4304
4366
  CodeRenderer = React4.memo(({ text, columns = 80 }) => {
4305
4367
  if (!text) return null;
4368
+ let extension = "";
4369
+ const fileMatch = text.match(/File\s+\[(.*?)\]/i);
4370
+ if (fileMatch) {
4371
+ extension = fileMatch[1].split(".").pop().toLowerCase();
4372
+ }
4306
4373
  if (text.includes("[DIFF_START]")) {
4307
- return /* @__PURE__ */ React4.createElement(DiffBlock, { text, columns });
4374
+ return /* @__PURE__ */ React4.createElement(DiffBlock, { text, columns, extension });
4308
4375
  }
4309
4376
  if (text.includes("- Content Preview:")) {
4310
4377
  const mainParts = text.split("- Content Preview:");
@@ -4332,7 +4399,7 @@ var init_ChatLayout = __esm({
4332
4399
  marginBottom: 1,
4333
4400
  backgroundColor: "#1a1a1a"
4334
4401
  },
4335
- /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: gutterWidth + 2, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, null, " ")), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, /* @__PURE__ */ React4.createElement(Text4, null, " "))), codeLines.map((line, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx, width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: gutterWidth + 2, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray", dimColor: true }, String(idx + 1).padStart(gutterWidth, " "), " ")), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "white" }, line)))), /* @__PURE__ */ React4.createElement(Box3, { width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: gutterWidth + 2, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, null, " ")), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, /* @__PURE__ */ React4.createElement(Text4, null, " "))))
4402
+ /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: gutterWidth + 2, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, null, " ")), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, /* @__PURE__ */ React4.createElement(Text4, null, " "))), codeLines.map((line, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx, width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: gutterWidth + 2, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray", dimColor: true }, String(idx + 1).padStart(gutterWidth, " "), " ")), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, renderHighlightedLine(line, extension, "white")))), /* @__PURE__ */ React4.createElement(Box3, { width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: gutterWidth + 2, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, null, " ")), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, /* @__PURE__ */ React4.createElement(Text4, null, " "))))
4336
4403
  ));
4337
4404
  }
4338
4405
  if (text.includes("```")) {
@@ -4361,7 +4428,7 @@ var init_ChatLayout = __esm({
4361
4428
  width: "100%"
4362
4429
  },
4363
4430
  /* @__PURE__ */ React4.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray", bold: true }, "\u25B6_ ", lang.toUpperCase() || "CODE")),
4364
- /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", width: "100%" }, codeLines.map((line, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx, width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: gutterWidth + 2, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray" }, String(idx + 1).padStart(gutterWidth, " "), " ")), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "#fcfca4ff" }, line)))))
4431
+ /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", width: "100%" }, codeLines.map((line, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx, width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: gutterWidth + 2, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray" }, String(idx + 1).padStart(gutterWidth, " "), " ")), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, renderHighlightedLine(line, lang, "#e1e4e8")))))
4365
4432
  );
4366
4433
  }
4367
4434
  let cleanPart = part;
@@ -4553,7 +4620,7 @@ var init_ChatLayout = __esm({
4553
4620
  );
4554
4621
  });
4555
4622
  BlockItem = React4.memo(({ block, columns = 80, showFullThinking, aiProvider, version }) => {
4556
- const { msg, type, text, isStreaming } = block;
4623
+ const { msg, type, text, isStreamingMsg, workedDuration } = block;
4557
4624
  if (type === "chunk") {
4558
4625
  return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", width: "100%" }, block.blocks.map((b) => /* @__PURE__ */ React4.createElement(
4559
4626
  BlockItem,
@@ -4580,14 +4647,14 @@ var init_ChatLayout = __esm({
4580
4647
  );
4581
4648
  }
4582
4649
  if (type === "think-header") {
4583
- return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", paddingX: 1, width: "100%", marginTop: 0, marginBottom: 0 }, msg.isStreaming ? /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: "white" }, "\u2727 Thinking...") : /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: "white" }, "\u2726 Thought..."), showFullThinking && /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "row", width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray" }, "\u2502 ")));
4650
+ return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", paddingX: 1, width: "100%", marginTop: 0, marginBottom: 0 }, isStreamingMsg ? /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: "white" }, "\u2727 Thinking...") : /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: "white" }, "\u2726 Thought..."), showFullThinking && /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "row", width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray" }, "\u2502 ")));
4584
4651
  }
4585
4652
  if (type === "think-line") {
4586
4653
  if (!showFullThinking) return null;
4587
4654
  if (!text || text.trim() === "") {
4588
4655
  return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "row", width: "100%", paddingX: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray" }, "\u2502 "));
4589
4656
  }
4590
- const animatedText = useStreamingText(text, msg.isStreaming, block.isActiveBlock);
4657
+ const animatedText = useStreamingText(text, isStreamingMsg, block.isActiveBlock);
4591
4658
  const trimmed = animatedText.trim();
4592
4659
  const isUnordered = /^[\*\-\+]\s/.test(trimmed);
4593
4660
  const isOrdered = /^\d+\.\s/.test(trimmed);
@@ -4611,7 +4678,7 @@ var init_ChatLayout = __esm({
4611
4678
  if (!text || text.trim() === "") {
4612
4679
  return /* @__PURE__ */ React4.createElement(Box3, { height: 1 });
4613
4680
  }
4614
- const animatedText = useStreamingText(text, msg.isStreaming, block.isActiveBlock);
4681
+ const animatedText = useStreamingText(text, isStreamingMsg, block.isActiveBlock);
4615
4682
  return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", paddingX: 1, width: "100%" }, /* @__PURE__ */ React4.createElement(CodeRenderer, { text: animatedText, columns }));
4616
4683
  }
4617
4684
  if (type === "table") {
@@ -4625,7 +4692,7 @@ var init_ChatLayout = __esm({
4625
4692
  {
4626
4693
  line: text,
4627
4694
  pairContent: block.pairContent,
4628
- parentText: msg?.text,
4695
+ parentText: void 0,
4629
4696
  columns
4630
4697
  }
4631
4698
  ), isLastLine && renderPaddingLine(true));
@@ -4644,7 +4711,7 @@ var init_ChatLayout = __esm({
4644
4711
  return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginTop: 1, width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "row", ...borderProps }, /* @__PURE__ */ React4.createElement(Text4, null, " ")), /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "row", ...borderProps }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray", bold: true }, "\u25B6_ ", (text || "CODE").toUpperCase())));
4645
4712
  }
4646
4713
  if (type === "code-line") {
4647
- const { lineNum } = block;
4714
+ const { lineNum, lang } = block;
4648
4715
  return /* @__PURE__ */ React4.createElement(
4649
4716
  Box3,
4650
4717
  {
@@ -4659,7 +4726,7 @@ var init_ChatLayout = __esm({
4659
4726
  width: "100%"
4660
4727
  },
4661
4728
  /* @__PURE__ */ React4.createElement(Box3, { width: 4, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray", dimColor: true }, String(lineNum).padStart(3, " "), " ")),
4662
- /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "#fcfca4ff" }, text))
4729
+ /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, renderHighlightedLine(text, lang, "#e1e4e8"))
4663
4730
  );
4664
4731
  }
4665
4732
  if (type === "code-fence-close") {
@@ -4684,7 +4751,7 @@ var init_ChatLayout = __esm({
4684
4751
  return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", paddingX: 1, width: columns }, /* @__PURE__ */ React4.createElement(MarkdownText, { text, columns }));
4685
4752
  }
4686
4753
  if (type === "write-line") {
4687
- const { gutterWidth, lineNum, isFirstLine, isLastLine } = block;
4754
+ const { gutterWidth, lineNum, isFirstLine, isLastLine, extension, wrappedLines } = block;
4688
4755
  const renderPaddingLine = (isEnd = false) => /* @__PURE__ */ React4.createElement(
4689
4756
  Box3,
4690
4757
  {
@@ -4720,14 +4787,14 @@ var init_ChatLayout = __esm({
4720
4787
  backgroundColor: "#1a1a1a"
4721
4788
  },
4722
4789
  /* @__PURE__ */ React4.createElement(Box3, { width: gutterWidth + 2, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray", dimColor: true }, String(lineNum).padStart(gutterWidth, " "), " ")),
4723
- /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "white" }, text))
4790
+ /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1, flexDirection: "column" }, (wrappedLines || [text]).map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, "white"))))
4724
4791
  ), isLastLine && renderPaddingLine(true));
4725
4792
  }
4726
4793
  if (type === "write-footer") {
4727
4794
  return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", paddingX: 1, width: columns, marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React4.createElement(MarkdownText, { text, columns }));
4728
4795
  }
4729
4796
  if (type === "worked-duration") {
4730
- return /* @__PURE__ */ React4.createElement(Box3, { marginTop: 1, marginBottom: 2, paddingX: 1, width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, null, "["), /* @__PURE__ */ React4.createElement(Text4, { color: "gray" }, "Worked for ", /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: "white" }, formatThinkingDuration(msg.workedDuration))), /* @__PURE__ */ React4.createElement(Text4, null, "]"));
4797
+ return /* @__PURE__ */ React4.createElement(Box3, { marginTop: 1, marginBottom: 2, paddingX: 1, width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, null, "["), /* @__PURE__ */ React4.createElement(Text4, { color: "gray" }, "Worked for ", /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: "white" }, formatThinkingDuration(workedDuration))), /* @__PURE__ */ React4.createElement(Text4, null, "]"));
4731
4798
  }
4732
4799
  return null;
4733
4800
  });
@@ -4776,7 +4843,7 @@ var init_StatusBar = __esm({
4776
4843
  getMemoryInfo();
4777
4844
  const interval = setInterval(() => {
4778
4845
  getMemoryInfo();
4779
- }, 3e3);
4846
+ }, 3e4);
4780
4847
  return () => clearInterval(interval);
4781
4848
  }, []);
4782
4849
  let maxLimit = 256e3;
@@ -4793,7 +4860,7 @@ var init_StatusBar = __esm({
4793
4860
  },
4794
4861
  /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Box4, { marginRight: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", bold: true }, mode.toUpperCase())), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", bold: true }, thinkingLevel.toUpperCase())), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", bold: true }, "MEM: "), /* @__PURE__ */ React5.createElement(Text5, { color: "white", bold: true }, isMemoryEnabled ? "ON" : "OFF"))),
4795
4862
  /* @__PURE__ */ React5.createElement(Box4, { flexGrow: 1, justifyContent: "center", paddingX: 2 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", italic: true }, truncatePath(process.cwd(), 35))),
4796
- /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white" }, formatTokens(tokensTotal), " ", /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, (tokens / maxLimit * 100).toFixed(0), "%"))), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "grey", bold: true }, memoryUsage, "/", memoryLimit, " ", memoryUnit)), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginLeft: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", bold: true }, chatId), (apiTier === "Custom" || apiTier === "Paid") && /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, " \u2503 "), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", bold: true }, "PAID"))))
4863
+ /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white" }, formatTokens(tokensTotal), " ", /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, (tokens / maxLimit * 100).toFixed(0), "%"))), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "grey", bold: true }, memoryUsage, "/", memoryLimit, " ", memoryUnit)), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginLeft: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", bold: true }, chatId), (apiTier === "Custom" || apiTier === "Paid") && /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, " \u2503 "), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", bold: true }, "PAID"))))
4797
4864
  );
4798
4865
  });
4799
4866
  StatusBar_default = StatusBar;
@@ -5728,7 +5795,7 @@ function SettingsMenu({
5728
5795
  getMemoryStats();
5729
5796
  const interval = setInterval(() => {
5730
5797
  getMemoryStats();
5731
- }, 5e3);
5798
+ }, 3e4);
5732
5799
  return () => clearInterval(interval);
5733
5800
  }, []);
5734
5801
  const getCategoryItems = (catId) => {
@@ -6361,8 +6428,8 @@ ${projectContextBlock}
6361
6428
  -- FORMATTING --
6362
6429
  - GFM Supported
6363
6430
  - NO CHAT **AFTER** FIRING TOOLS IN CURRENT TURN
6364
- - Short headsup about actions before firing tools
6365
- - Task Complete & Results Verified? End response with summary of changes made and files edited
6431
+ - Short headsup summary of actions before firing tools
6432
+ - Task Complete & Results Verified? End response with summary of changes made (why) and files edited
6366
6433
  - Basic LaTeX${mode === "Flux" ? "" : ". Kaomojis"}
6367
6434
  === END SYSTEM PROMPT ===`.trim();
6368
6435
  };
@@ -11215,6 +11282,7 @@ Provide a consolidated summary of the entire session.`;
11215
11282
  });
11216
11283
  return result;
11217
11284
  };
11285
+ yield { type: "status", content: "[start]" };
11218
11286
  yield { type: "status", content: "Gathering Context..." };
11219
11287
  await new Promise((resolve) => setTimeout(resolve, 500));
11220
11288
  const totalFolders = countFolders(process.cwd());
@@ -13315,6 +13383,7 @@ Error Log can be found in ${path19.join(LOGS_DIR, "agent", "error.log")}`);
13315
13383
  } else {
13316
13384
  modifiedHistory.push({ role: "agent", text: cleanedFullResponse });
13317
13385
  }
13386
+ yield { type: "status", content: "[end]" };
13318
13387
  }
13319
13388
  if (isActuallyFinished) break;
13320
13389
  const nextAgentMsg = cleanedTurnText.trim() || "*Working...*";
@@ -14403,6 +14472,7 @@ import TextInput4 from "ink-text-input";
14403
14472
  import SelectInput2 from "ink-select-input";
14404
14473
  import gradient2 from "gradient-string";
14405
14474
  function App({ args = [] }) {
14475
+ let lastGCTime = 1;
14406
14476
  const [confirmExit, setConfirmExit] = useState14(false);
14407
14477
  const [exitCountdown, setExitCountdown] = useState14(10);
14408
14478
  const { stdout } = useStdout2();
@@ -14433,9 +14503,25 @@ function App({ args = [] }) {
14433
14503
  setShowBridgePromo(false);
14434
14504
  }
14435
14505
  }, 1e3);
14506
+ lastGCTime = Date.now();
14507
+ const memInterval = setInterval(() => {
14508
+ if (lastGCTime) {
14509
+ const diff = Date.now() - lastGCTime || 0;
14510
+ if (diff > 3e4) {
14511
+ if (global.gc) {
14512
+ try {
14513
+ global.gc();
14514
+ lastGCTime = Date.now();
14515
+ } catch (e) {
14516
+ }
14517
+ }
14518
+ }
14519
+ }
14520
+ }, 3e3);
14436
14521
  return () => {
14437
14522
  clearTimeout(graceTimer);
14438
14523
  clearInterval(interval);
14524
+ clearInterval(memInterval);
14439
14525
  };
14440
14526
  }, []);
14441
14527
  const parsedArgs = useMemo2(() => {
@@ -14704,6 +14790,7 @@ function App({ args = [] }) {
14704
14790
  const PLAYGROUND_CHAT_ID = "flow-playground";
14705
14791
  const [chatId, setChatId] = useState14(args.includes("--playground") ? PLAYGROUND_CHAT_ID : generateChatId());
14706
14792
  useEffect11(() => {
14793
+ if (chatLoadingRef.current) return;
14707
14794
  const nextTokens = sessionTotalTokens - chatTokenStartRef.current;
14708
14795
  setChatTokens(nextTokens);
14709
14796
  if (chatId) {
@@ -14851,6 +14938,8 @@ function App({ args = [] }) {
14851
14938
  const [statusText, setStatusText] = useState14(null);
14852
14939
  const [wittyPhrase, setWittyPhrase] = useState14("");
14853
14940
  const [hasPasteBlock, setHasPasteBlock] = useState14(false);
14941
+ const [activeTime, setActiveTime] = useState14(0);
14942
+ let interval_for_timer;
14854
14943
  useEffect11(() => {
14855
14944
  let interval;
14856
14945
  if (statusText) {
@@ -14863,7 +14952,9 @@ function App({ args = [] }) {
14863
14952
  } else {
14864
14953
  setWittyPhrase("");
14865
14954
  }
14866
- return () => clearInterval(interval);
14955
+ return () => {
14956
+ clearInterval(interval);
14957
+ };
14867
14958
  }, [statusText]);
14868
14959
  const [isSpinnerActive, setIsSpinnerActive] = useState14(true);
14869
14960
  const [isProcessing, setIsProcessing] = useState14(false);
@@ -14873,6 +14964,14 @@ function App({ args = [] }) {
14873
14964
  const [escPressCount, setEscPressCount] = useState14(0);
14874
14965
  const [recentPrompts, setRecentPrompts] = useState14([]);
14875
14966
  const escDoubleTimerRef = useRef3(null);
14967
+ const chatLoadingRef = useRef3(false);
14968
+ useEffect11(() => {
14969
+ return () => {
14970
+ if (escDoubleTimerRef.current) {
14971
+ clearTimeout(escDoubleTimerRef.current);
14972
+ }
14973
+ };
14974
+ }, []);
14876
14975
  const didSignalTerminationRef = useRef3(false);
14877
14976
  const [queuedPrompt, setQueuedPrompt] = useState14(null);
14878
14977
  const [resolutionData, setResolutionData] = useState14(null);
@@ -14956,7 +15055,9 @@ function App({ args = [] }) {
14956
15055
  completedIndex: 0,
14957
15056
  columns: 0,
14958
15057
  historicalBlocks: [],
14959
- seenSelections: /* @__PURE__ */ new Set()
15058
+ seenSelections: /* @__PURE__ */ new Set(),
15059
+ chatId: "",
15060
+ clearKey: 0
14960
15061
  });
14961
15062
  const parsedBlocks = useMemo2(() => {
14962
15063
  const columns = terminalSize.columns || 80;
@@ -14965,7 +15066,9 @@ function App({ args = [] }) {
14965
15066
  let seenAskSelections = /* @__PURE__ */ new Set();
14966
15067
  const isResize = cachedHistoryRef.current.columns !== columns;
14967
15068
  const isClear = completedIndex < cachedHistoryRef.current.completedIndex;
14968
- if (isResize || isClear) {
15069
+ const isChatChanged = cachedHistoryRef.current.chatId !== chatId;
15070
+ const isClearKeyChanged = cachedHistoryRef.current.clearKey !== clearKey;
15071
+ if (isResize || isClear || isChatChanged || isClearKeyChanged) {
14969
15072
  const completedMsgs = messages.slice(0, completedIndex);
14970
15073
  for (let i = 0; i < completedMsgs.length; i++) {
14971
15074
  const msg = completedMsgs[i];
@@ -14985,7 +15088,9 @@ function App({ args = [] }) {
14985
15088
  completedIndex,
14986
15089
  columns,
14987
15090
  historicalBlocks,
14988
- seenSelections: new Set(seenAskSelections)
15091
+ seenSelections: new Set(seenAskSelections),
15092
+ chatId,
15093
+ clearKey
14989
15094
  };
14990
15095
  } else {
14991
15096
  historicalBlocks = cachedHistoryRef.current.historicalBlocks;
@@ -15012,7 +15117,9 @@ function App({ args = [] }) {
15012
15117
  completedIndex,
15013
15118
  columns,
15014
15119
  historicalBlocks,
15015
- seenSelections: seenAskSelections
15120
+ seenSelections: seenAskSelections,
15121
+ chatId,
15122
+ clearKey
15016
15123
  };
15017
15124
  }
15018
15125
  }
@@ -15032,7 +15139,10 @@ function App({ args = [] }) {
15032
15139
  for (let j = 0; j < parsed.completed.length; j++) streamingCompletedBlocks.push(parsed.completed[j]);
15033
15140
  for (let j = 0; j < parsed.active.length; j++) activeBlocks.push(parsed.active[j]);
15034
15141
  }
15035
- const finalCompleted = historicalBlocks.concat(streamingCompletedBlocks);
15142
+ const finalCompleted = [...historicalBlocks];
15143
+ for (let j = 0; j < streamingCompletedBlocks.length; j++) {
15144
+ finalCompleted.push(streamingCompletedBlocks[j]);
15145
+ }
15036
15146
  if (finalCompleted.length >= 75e3) {
15037
15147
  finalCompleted.push({
15038
15148
  key: `memory-warning-block-${finalCompleted.length}`,
@@ -15049,7 +15159,7 @@ function App({ args = [] }) {
15049
15159
  completed: finalCompleted,
15050
15160
  active: activeBlocks
15051
15161
  };
15052
- }, [messages, completedIndex, terminalSize.columns]);
15162
+ }, [messages, completedIndex, terminalSize.columns, clearKey, chatId]);
15053
15163
  const isTerminalWaitingForInput = useMemo2(() => {
15054
15164
  if (!activeCommand || !execOutput) return false;
15055
15165
  const lastChunk = execOutput.trim();
@@ -15181,10 +15291,18 @@ function App({ args = [] }) {
15181
15291
  setConfirmExit(false);
15182
15292
  return;
15183
15293
  }
15184
- if (isProcessing || activeCommand) {
15294
+ if (isProcessing || activeCommand || pendingApproval || pendingAsk) {
15185
15295
  didSignalTerminationRef.current = true;
15186
15296
  signalTermination();
15187
15297
  terminateActiveCommand();
15298
+ if (pendingApproval) {
15299
+ pendingApproval.resolve("deny");
15300
+ setPendingApproval(null);
15301
+ }
15302
+ if (pendingAsk) {
15303
+ pendingAsk.resolve(null);
15304
+ setPendingAsk(null);
15305
+ }
15188
15306
  setEscPressed(false);
15189
15307
  if (escTimer) clearTimeout(escTimer);
15190
15308
  } else {
@@ -15418,9 +15536,11 @@ function App({ args = [] }) {
15418
15536
  const h = await loadHistory();
15419
15537
  const id = parsedArgs.resume;
15420
15538
  if (h[id]) {
15539
+ chatLoadingRef.current = true;
15421
15540
  setChatId(id);
15422
15541
  const savedData = await loadChatContext(id);
15423
15542
  chatTokenStartRef.current = sessionTotalTokens - savedData.total;
15543
+ chatLoadingRef.current = false;
15424
15544
  setChatTokens(savedData.total);
15425
15545
  setSessionStats({ tokens: savedData.context });
15426
15546
  const resumedMsgs = [...h[id].messages];
@@ -15598,7 +15718,7 @@ function App({ args = [] }) {
15598
15718
  lastSavedTimeRef.current += deltaSecs * 1e3;
15599
15719
  }
15600
15720
  }
15601
- }, 2e3);
15721
+ }, 5e3);
15602
15722
  return () => clearInterval(interval);
15603
15723
  }, [isInitializing]);
15604
15724
  const COMMANDS = [
@@ -15963,9 +16083,11 @@ ${cleanText}`, color: "magenta" }];
15963
16083
  if (target) {
15964
16084
  stdout.write("\x1B[2J\x1B[3J\x1B[H");
15965
16085
  clearBlocksCache();
16086
+ chatLoadingRef.current = true;
15966
16087
  setChatId(targetId);
15967
16088
  const savedData = await loadChatContext(targetId);
15968
16089
  chatTokenStartRef.current = sessionTotalTokens - savedData.total;
16090
+ chatLoadingRef.current = false;
15969
16091
  setChatTokens(savedData.total);
15970
16092
  setSessionStats({ tokens: savedData.context });
15971
16093
  const resumedMsgs = [...target.messages];
@@ -16047,6 +16169,14 @@ ${cleanText}`, color: "magenta" }];
16047
16169
  setCompletedIndex(1);
16048
16170
  setClearKey((prev) => prev + 1);
16049
16171
  clearBlocksCache();
16172
+ cachedHistoryRef.current = {
16173
+ completedIndex: 0,
16174
+ columns: terminalSize.columns,
16175
+ historicalBlocks: [],
16176
+ seenSelections: /* @__PURE__ */ new Set(),
16177
+ chatId,
16178
+ clearKey: clearKey + 1
16179
+ };
16050
16180
  if (parsedArgs.playground) {
16051
16181
  parsedArgs.playground = false;
16052
16182
  deleteChat(PLAYGROUND_CHAT_ID).catch(() => {
@@ -16096,6 +16226,7 @@ ${cleanText}`, color: "magenta" }];
16096
16226
  if (global.gc) {
16097
16227
  try {
16098
16228
  global.gc();
16229
+ lastGCTime = Date.now();
16099
16230
  } catch (e) {
16100
16231
  }
16101
16232
  }
@@ -16119,6 +16250,7 @@ ${cleanText}`, color: "magenta" }];
16119
16250
  if (global.gc) {
16120
16251
  try {
16121
16252
  global.gc();
16253
+ lastGCTime = Date.now();
16122
16254
  } catch (e) {
16123
16255
  }
16124
16256
  }
@@ -16945,20 +17077,23 @@ Selection: ${val}`,
16945
17077
  let toolCallBalance = 0;
16946
17078
  let inToolCallString = null;
16947
17079
  const signalRegex = /\[?\s*turn\s*:\s*.*?\s*\]?/gi;
16948
- const bullyTheBug = path20.join(DATA_DIR, "padding");
16949
17080
  for await (const packet of stream) {
16950
- if (packet.type === "interactive_turn_finished") {
16951
- fs22.writeFileSync(bullyTheBug, "pad_0xa\n");
16952
- } else {
16953
- fs22.appendFileSync(bullyTheBug, "\r");
16954
- parsedBlocks.completed = [];
16955
- }
16956
17081
  if (isFirstPacket && packet.type === "text") {
16957
17082
  apiStart = Date.now();
16958
17083
  isFirstPacket = false;
16959
17084
  }
16960
17085
  if (packet.type === "status") {
16961
17086
  setStatusText(packet.content);
17087
+ if (packet.content?.includes("[start]")) {
17088
+ clearInterval(interval_for_timer);
17089
+ setActiveTime(0);
17090
+ interval_for_timer = setInterval(() => {
17091
+ setActiveTime((prev) => prev + 1);
17092
+ }, 1e3);
17093
+ } else if (packet.content?.includes("[end]")) {
17094
+ setActiveTime(0);
17095
+ clearInterval(interval_for_timer);
17096
+ }
16962
17097
  if (isBridgeConnected()) {
16963
17098
  sendStatus(packet.content);
16964
17099
  }
@@ -16998,26 +17133,39 @@ Selection: ${val}`,
16998
17133
  toolCallEncounteredInTurn = false;
16999
17134
  thinkConsumedInTurn = false;
17000
17135
  setMessages((prev) => {
17001
- const newMsgs = prev.map((m) => m.isStreaming ? { ...m, isStreaming: false } : m);
17136
+ const newMsgs = prev.map((m) => {
17137
+ if (m.isStreaming) {
17138
+ const flatText = m.text ? (" " + m.text).slice(1) : m.text;
17139
+ const flatFullText = m.fullText ? (" " + m.fullText).slice(1) : m.fullText;
17140
+ return { ...m, isStreaming: false, text: flatText, fullText: flatFullText };
17141
+ }
17142
+ return m;
17143
+ });
17002
17144
  setCompletedIndex(newMsgs.length);
17003
17145
  return newMsgs;
17004
17146
  });
17005
- setTimeout(() => {
17006
- if (global.gc) {
17007
- try {
17008
- global.gc();
17009
- } catch (e) {
17010
- }
17147
+ clearBlocksCache();
17148
+ if (global.gc) {
17149
+ try {
17150
+ global.gc();
17151
+ setTimeout(() => {
17152
+ if (global.gc) global.gc();
17153
+ lastGCTime = Date.now();
17154
+ }, 100);
17155
+ } catch (e) {
17011
17156
  }
17012
- }, 100);
17157
+ }
17013
17158
  continue;
17014
17159
  }
17015
17160
  if (packet.type === "interactive_turn_finished") {
17016
17161
  setIsProcessing(false);
17162
+ setActiveTime(0);
17163
+ clearInterval(interval_for_timer);
17017
17164
  if (isBridgeConnected()) {
17018
17165
  sendStatus(null);
17019
17166
  }
17020
17167
  hasFiredJanitor = true;
17168
+ clearBlocksCache();
17021
17169
  runJanitorTask(
17022
17170
  { profile: profileData, thinkingLevel, mode, janitorModel, chatId, systemSettings, sessionStats, aiProvider, apiKey },
17023
17171
  packet.data.agentText,
@@ -17032,6 +17180,16 @@ Selection: ${val}`,
17032
17180
  onBackgroundIncrement: () => setSessionBackgroundCalls((prev) => prev + 1)
17033
17181
  }
17034
17182
  );
17183
+ if (global.gc) {
17184
+ try {
17185
+ global.gc();
17186
+ setTimeout(() => {
17187
+ if (global.gc) global.gc();
17188
+ lastGCTime = Date.now();
17189
+ }, 150);
17190
+ } catch (e) {
17191
+ }
17192
+ }
17035
17193
  continue;
17036
17194
  }
17037
17195
  if (packet.type === "visual_feedback") {
@@ -17146,6 +17304,10 @@ Selection: ${val}`,
17146
17304
  }
17147
17305
  let chunkText = packet.content;
17148
17306
  if (packet.type === "text" && chunkText.includes("Request Cancelled")) {
17307
+ if (global.gc) {
17308
+ global.gc();
17309
+ lastGCTime = Date.now();
17310
+ }
17149
17311
  continue;
17150
17312
  }
17151
17313
  const chunkLower = chunkText.toLowerCase();
@@ -17276,9 +17438,22 @@ Selection: ${val}`,
17276
17438
  } finally {
17277
17439
  setIsProcessing(false);
17278
17440
  setStatusText(null);
17441
+ setActiveTime(0);
17442
+ clearInterval(interval_for_timer);
17279
17443
  if (didSignalTerminationRef.current) {
17280
17444
  appendCancelMessage();
17281
17445
  }
17446
+ clearBlocksCache();
17447
+ if (global.gc) {
17448
+ try {
17449
+ global.gc();
17450
+ setTimeout(() => {
17451
+ if (global.gc) global.gc();
17452
+ lastGCTime = Date.now();
17453
+ }, 500);
17454
+ } catch (e) {
17455
+ }
17456
+ }
17282
17457
  if (!hasFiredJanitor) {
17283
17458
  if (process.stdout.isTTY) {
17284
17459
  process.stdout.write("\x1B]0;FluxFlow | Idle\x07");
@@ -17309,6 +17484,9 @@ Selection: ${val}`,
17309
17484
  let foundLastAgent = false;
17310
17485
  const newMsgs = [...prev].reverse().map((m) => {
17311
17486
  let updated = m.isStreaming ? { ...m, isStreaming: false } : m;
17487
+ if (updated.text) {
17488
+ updated.text = (" " + updated.text).slice(1);
17489
+ }
17312
17490
  if (!foundLastAgent && updated.role === "agent") {
17313
17491
  foundLastAgent = true;
17314
17492
  updated = { ...updated, workedDuration: totalDuration };
@@ -18022,24 +18200,26 @@ Selection: ${val}`,
18022
18200
  {
18023
18201
  prompts: recentPrompts,
18024
18202
  onSelect: async (txId) => {
18203
+ if (stdout) {
18204
+ stdout.write("\x1B[2J\x1B[3J\x1B[H");
18205
+ if (stdout.isTTY) {
18206
+ stdout.write("\x1B[?2004h");
18207
+ }
18208
+ }
18025
18209
  try {
18026
18210
  const result = await RevertManager.rollbackToBefore(txId);
18027
18211
  if (result.success) {
18028
18212
  const { targetPrompt } = result;
18029
18213
  deleteChatSummary(chatId);
18030
- if (stdout) {
18031
- stdout.write("\x1B[2J\x1B[3J\x1B[H");
18032
- if (stdout.isTTY) {
18033
- stdout.write("\x1B[?2004h");
18034
- }
18035
- }
18036
18214
  setClearKey((prev) => prev + 1);
18037
18215
  clearBlocksCache();
18038
18216
  cachedHistoryRef.current = {
18039
18217
  completedIndex: 0,
18040
- columns: 0,
18218
+ columns: terminalSize.columns,
18041
18219
  historicalBlocks: [],
18042
- seenSelections: /* @__PURE__ */ new Set()
18220
+ seenSelections: /* @__PURE__ */ new Set(),
18221
+ chatId,
18222
+ clearKey: clearKey + 1
18043
18223
  };
18044
18224
  const targetIdx = messages.findLastIndex(
18045
18225
  (m) => m.role === "user" && m.text && (m.text.startsWith(targetPrompt) || m.text.includes(targetPrompt))
@@ -18094,9 +18274,11 @@ Selection: ${val}`,
18094
18274
  if (h[id]) {
18095
18275
  stdout.write("\x1B[2J\x1B[3J\x1B[H");
18096
18276
  clearBlocksCache();
18277
+ chatLoadingRef.current = true;
18097
18278
  setChatId(id);
18098
18279
  const savedData = await loadChatContext(id);
18099
18280
  chatTokenStartRef.current = sessionTotalTokens - savedData.total;
18281
+ chatLoadingRef.current = false;
18100
18282
  setChatTokens(savedData.total);
18101
18283
  setSessionStats({ tokens: savedData.context });
18102
18284
  const resumedMsgs = [...h[id].messages];
@@ -18308,7 +18490,7 @@ Selection: ${val}`,
18308
18490
  }
18309
18491
  )));
18310
18492
  default:
18311
- return /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, showBtwBox && btwResponse && /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 2, paddingY: 1, width: "100%", marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Box15, { justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Text16, { color: "white", bold: true, underline: true }, "INQUIRY RESPONSE"), /* @__PURE__ */ React15.createElement(Text16, { color: "gray" }, "[ ESC to Close ]")), /* @__PURE__ */ React15.createElement(Box15, { marginTop: 1, width: "100%" }, /* @__PURE__ */ React15.createElement(CodeRenderer, { text: btwResponse, columns: terminalSize.columns - 6 }))), /* @__PURE__ */ React15.createElement(Box15, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Box15, null, statusText ? /* @__PURE__ */ React15.createElement(Box15, { gap: 1 }, /* @__PURE__ */ React15.createElement(dist_default, { colors: ["#001a1a", "#080510", "#12021c"] }, /* @__PURE__ */ React15.createElement(build_default, null)), /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true, italic: true }, statusText)) : /* @__PURE__ */ React15.createElement(Text16, { color: "gray", italic: true }, input.length > 0 && escPressCount ? "Press ESC again to clear input" : hasPasteBlock ? "Press CTRL + O to expand" : "Waiting for input...")), /* @__PURE__ */ React15.createElement(Box15, null, wittyPhrase && /* @__PURE__ */ React15.createElement(Text16, { color: "gray", italic: true }, wittyPhrase, " "), /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true }, "[ "), /* @__PURE__ */ React15.createElement(Text16, { color: "white" }, tempModelOverride || activeModel), /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true }, " ]"))), /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React15.createElement(Box15, { width: "100%", height: 1, overflow: "hidden" }, /* @__PURE__ */ React15.createElement(Text16, { color: "#555555" }, "\u2584".repeat(Math.max(1, terminalSize.columns)))), /* @__PURE__ */ React15.createElement(
18493
+ return /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, showBtwBox && btwResponse && /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 2, paddingY: 1, width: "100%", marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Box15, { justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Text16, { color: "white", bold: true, underline: true }, "INQUIRY RESPONSE"), /* @__PURE__ */ React15.createElement(Text16, { color: "gray" }, "[ ESC to Close ]")), /* @__PURE__ */ React15.createElement(Box15, { marginTop: 1, width: "100%" }, /* @__PURE__ */ React15.createElement(CodeRenderer, { text: btwResponse, columns: terminalSize.columns - 6 }))), /* @__PURE__ */ React15.createElement(Box15, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Box15, null, statusText ? /* @__PURE__ */ React15.createElement(Box15, { gap: 1 }, /* @__PURE__ */ React15.createElement(dist_default, { colors: ["#001a1a", "#080510", "#12021c"] }, /* @__PURE__ */ React15.createElement(build_default, null)), /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true, italic: true }, statusText), /* @__PURE__ */ React15.createElement(Text16, { color: "gray", italic: true, dimColor: true }, activeTime > 0 ? ` [${activeTime.toFixed(0)}s]` : "")) : /* @__PURE__ */ React15.createElement(Text16, { color: "gray", italic: true }, input.length > 0 && escPressCount ? "Press ESC again to clear input" : hasPasteBlock ? "Press CTRL + O to expand" : "Waiting for input...")), /* @__PURE__ */ React15.createElement(Box15, null, wittyPhrase && /* @__PURE__ */ React15.createElement(Text16, { color: "gray", italic: true }, wittyPhrase, " "), /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true }, "[ "), /* @__PURE__ */ React15.createElement(Text16, { color: "white" }, tempModelOverride || activeModel), /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true }, " ]"))), /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React15.createElement(Box15, { width: "100%", height: 1, overflow: "hidden" }, /* @__PURE__ */ React15.createElement(Text16, { color: "#555555" }, "\u2584".repeat(Math.max(1, terminalSize.columns)))), /* @__PURE__ */ React15.createElement(
18312
18494
  Box15,
18313
18495
  {
18314
18496
  backgroundColor: "#555555",
@@ -18345,7 +18527,7 @@ Selection: ${val}`,
18345
18527
  ), /* @__PURE__ */ React15.createElement(Box15, { width: "100%", height: 1, overflow: "hidden" }, /* @__PURE__ */ React15.createElement(Text16, { color: "#555555" }, "\u2580".repeat(Math.max(1, terminalSize.columns))))));
18346
18528
  }
18347
18529
  };
18348
- return /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", width: "100%" }, showBridgePromo ? /* @__PURE__ */ React15.createElement(BridgePromo, { width: stdout?.columns || 80, height: stdout?.rows || 24, selectedIndex: promoSelectedIndex }) : /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box15, { paddingX: 1, flexDirection: "column", width: "100%" }, /* @__PURE__ */ React15.createElement(Static, { key: `static-${clearKey}-${terminalSize.columns}-${terminalSize.rows}`, items: parsedBlocks.completed }, (block) => /* @__PURE__ */ React15.createElement(
18530
+ return /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", width: "100%" }, showBridgePromo ? /* @__PURE__ */ React15.createElement(BridgePromo, { width: stdout?.columns || 80, height: stdout?.rows || 24, selectedIndex: promoSelectedIndex }) : /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box15, { paddingX: 1, flexDirection: "column", width: "100%" }, /* @__PURE__ */ React15.createElement(Static, { key: `static-${clearKey}-${chatId}-${terminalSize.columns}-${terminalSize.rows}`, items: parsedBlocks.completed }, (block) => /* @__PURE__ */ React15.createElement(
18349
18531
  BlockItem,
18350
18532
  {
18351
18533
  key: block.key,
@@ -18755,11 +18937,13 @@ var isBundled = fileURLToPath2(import.meta.url).endsWith(".js");
18755
18937
  if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-size"))) {
18756
18938
  if (!Number.isNaN(_allocValue)) {
18757
18939
  console.log(`
18758
- [MEMORY] Starting with: '${_allocValue > _maxAllowed ? _maxAllowed : _allocValue} MB' Allocation ${_allocValue > _maxAllowed ? "(Max allowed: '" + _maxAllowed + " MB')" : ""}. Please Wait...`);
18940
+ [MEMORY] Starting with: '${_allocValue > _maxAllowed ? _maxAllowed : _allocValue} MB' Allocation${_allocValue > _maxAllowed ? " (Max allowed: '" + _maxAllowed + " MB')" : ""}. Please Wait...`);
18759
18941
  await new Promise((resolve) => setTimeout(resolve, 5e3));
18760
18942
  }
18761
18943
  const cp = spawn3(process.execPath, [
18762
18944
  `--max-old-space-size=${HEAP_LIMIT}`,
18945
+ `--expose-gc`,
18946
+ `--max-semi-space-size=1`,
18763
18947
  fileURLToPath2(import.meta.url),
18764
18948
  ...process.argv.slice(2)
18765
18949
  ], { stdio: "inherit" });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "2.15.2",
4
- "date": "2026-06-30",
3
+ "version": "2.16.0",
4
+ "date": "2026-07-01",
5
5
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",