fluxflow-cli 3.2.6 → 3.3.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 +378 -465
  2. package/package.json +2 -2
package/dist/fluxflow.js CHANGED
@@ -2111,10 +2111,14 @@ var init_build = __esm({
2111
2111
 
2112
2112
  // src/utils/text.js
2113
2113
  import os2 from "os";
2114
- 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;
2114
+ var flattenString, 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;
2115
2115
  var init_text = __esm({
2116
2116
  "src/utils/text.js"() {
2117
2117
  init_paths();
2118
+ flattenString = (str) => {
2119
+ if (typeof str !== "string") return str;
2120
+ return str.length > 12 ? (str + "").replace("", "") : str;
2121
+ };
2118
2122
  wrapText = (text, width) => {
2119
2123
  if (!text) return "";
2120
2124
  const ansiRegex = /\x1B\[[0-?]*[ -/]*[@-~]/g;
@@ -2166,7 +2170,7 @@ var init_text = __esm({
2166
2170
  finalLines.push(currentLine.trimEnd());
2167
2171
  }
2168
2172
  });
2169
- return finalLines.join("\n");
2173
+ return flattenString(finalLines.join("\n"));
2170
2174
  };
2171
2175
  formatTokens = (tokens) => {
2172
2176
  if (!tokens && tokens !== 0) return "0.0k";
@@ -2181,9 +2185,9 @@ var init_text = __esm({
2181
2185
  truncatePath = (p, maxLength = 40) => {
2182
2186
  let data_dir = DATA_DIR.replaceAll("\\\\", "\\");
2183
2187
  p = p.replace(os2.homedir(), "~").replace(data_dir, "FluxFlow").replaceAll("\\", "/");
2184
- if (!p || p.length <= maxLength) return p;
2188
+ if (!p || p.length <= maxLength) return flattenString(p);
2185
2189
  const half = Math.floor((maxLength - 3) / 2);
2186
- return p.substring(0, half) + "..." + p.substring(p.length - half).replaceAll("\\", "/");
2190
+ return flattenString(p.substring(0, half) + "..." + p.substring(p.length - half).replaceAll("\\", "/"));
2187
2191
  };
2188
2192
  parsePatchPairs = (args) => {
2189
2193
  const patchPairs = [];
@@ -2438,7 +2442,7 @@ var init_text = __esm({
2438
2442
  }
2439
2443
  }
2440
2444
  diffText += `[DIFF_END]`;
2441
- return diffText;
2445
+ return flattenString(diffText);
2442
2446
  };
2443
2447
  parseLineInfo = (l) => {
2444
2448
  if (!l) return null;
@@ -2448,8 +2452,8 @@ var init_text = __esm({
2448
2452
  let rest = isR || isA ? clean.substring(1) : clean;
2449
2453
  rest = rest.trim();
2450
2454
  const splitIdx = rest.indexOf("|");
2451
- const num = splitIdx !== -1 ? rest.substring(0, splitIdx).trim() : "";
2452
- const content = splitIdx !== -1 ? rest.substring(splitIdx + 1) : rest;
2455
+ const num = splitIdx !== -1 ? flattenString(rest.substring(0, splitIdx).trim()) : "";
2456
+ const content = splitIdx !== -1 ? flattenString(rest.substring(splitIdx + 1)) : flattenString(rest);
2453
2457
  return { isR, isA, num, content };
2454
2458
  };
2455
2459
  getSimilarity = (s1, s2) => {
@@ -2457,21 +2461,35 @@ var init_text = __esm({
2457
2461
  if (!s1 || !s2) return 0;
2458
2462
  const l1 = s1.length;
2459
2463
  const l2 = s2.length;
2460
- const dp = Array.from({ length: l1 + 1 }, () => Array(l2 + 1).fill(0));
2461
- for (let i = 0; i <= l1; i++) dp[i][0] = i;
2462
- for (let j = 0; j <= l2; j++) dp[0][j] = j;
2463
- for (let i = 1; i <= l1; i++) {
2464
- for (let j = 1; j <= l2; j++) {
2465
- if (s1[i - 1] === s2[j - 1]) {
2466
- dp[i][j] = dp[i - 1][j - 1];
2464
+ let str1 = s1;
2465
+ let str2 = s2;
2466
+ if (l1 < l2) {
2467
+ str1 = s2;
2468
+ str2 = s1;
2469
+ }
2470
+ const n = str1.length;
2471
+ const m = str2.length;
2472
+ const prevRow = new Int32Array(m + 1);
2473
+ const currRow = new Int32Array(m + 1);
2474
+ for (let j = 0; j <= m; j++) {
2475
+ prevRow[j] = j;
2476
+ }
2477
+ for (let i = 1; i <= n; i++) {
2478
+ currRow[0] = i;
2479
+ const char1 = str1[i - 1];
2480
+ for (let j = 1; j <= m; j++) {
2481
+ if (char1 === str2[j - 1]) {
2482
+ currRow[j] = prevRow[j - 1];
2467
2483
  } else {
2468
- dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1;
2484
+ currRow[j] = Math.min(prevRow[j], currRow[j - 1], prevRow[j - 1]) + 1;
2469
2485
  }
2470
2486
  }
2487
+ prevRow.set(currRow);
2471
2488
  }
2489
+ const dist = prevRow[m];
2472
2490
  const maxLen = Math.max(l1, l2);
2473
2491
  if (maxLen === 0) return 1;
2474
- return 1 - dp[l1][l2] / maxLen;
2492
+ return 1 - dist / maxLen;
2475
2493
  };
2476
2494
  alignChangeGroup = (group) => {
2477
2495
  const removals = [];
@@ -2545,11 +2563,11 @@ var init_text = __esm({
2545
2563
  };
2546
2564
  parseMessageToBlocks = (msg, columns) => {
2547
2565
  if (!msg) return { completed: [], active: [] };
2548
- const cacheKey = `${msg.id}-${msg.text?.length || 0}-${columns}-${msg.isStreaming}-${msg.workedDuration || 0}-${msg.memoryUpdated ? 1 : 0}-${msg.color || ""}`;
2566
+ const cacheKey = `${msg.id}-${msg.text?.length || 0}-${columns}-${msg.isStreaming}-${msg.workedDuration || 0}`;
2549
2567
  if (!msg.isStreaming && blocksCache.has(cacheKey)) {
2550
2568
  return blocksCache.get(cacheKey);
2551
2569
  }
2552
- const text = cleanSignals(msg.text || "");
2570
+ const text = flattenString(cleanSignals(msg.text || ""));
2553
2571
  const streamCacheKey = `${msg.id}-${columns}`;
2554
2572
  let cachedBlocks = /* @__PURE__ */ new Map();
2555
2573
  if (msg.isStreaming) {
@@ -2563,13 +2581,13 @@ var init_text = __esm({
2563
2581
  if (existing && existing.text === textContent && existing.type === type && !!existing.isActiveBlock === !!extra.isActiveBlock && !!existing.isStreaming === !!extra.isStreaming && existing.pairContent === extra.pairContent) {
2564
2582
  return existing;
2565
2583
  }
2566
- const flatText = typeof textContent === "string" ? (" " + textContent).slice(1) : textContent;
2584
+ const flatText = flattenString(textContent);
2567
2585
  const flatExtra = { ...extra };
2568
2586
  if (typeof flatExtra.pairContent === "string") {
2569
- flatExtra.pairContent = (" " + flatExtra.pairContent).slice(1);
2587
+ flatExtra.pairContent = flattenString(flatExtra.pairContent);
2570
2588
  }
2571
2589
  if (Array.isArray(flatExtra.wrappedLines)) {
2572
- flatExtra.wrappedLines = flatExtra.wrappedLines.map((l) => typeof l === "string" ? (" " + l).slice(1) : l);
2590
+ flatExtra.wrappedLines = flatExtra.wrappedLines.map(flattenString);
2573
2591
  }
2574
2592
  return {
2575
2593
  key,
@@ -4003,7 +4021,7 @@ ${coloredArt[7]}`;
4003
4021
  import React4, { useState as useState4, useEffect as useEffect3, useRef as useRef2 } from "react";
4004
4022
  import { Box as Box3, Text as Text4 } from "ink";
4005
4023
  import { diffWordsWithSpace } from "diff";
4006
- var useStreamingText, formatThinkText, REGEX_MD_TOKENS, REGEX_LATEX_FRAC, REGEX_LATEX_STYLE, parseMathSymbols, SYNTAX_KEYWORDS, SYNTAX_RULES, tokenCache, MAX_TOKEN_CACHE_SIZE, tokenizeLine, renderHighlightedLine, renderLatexText, InlineMarkdown, TableRenderer, MarkdownText, DiffLine, DiffBlock, CodeRenderer, formatThinkingDuration, MessageItem, BlockItem, ChatLayout;
4024
+ 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;
4007
4025
  var init_ChatLayout = __esm({
4008
4026
  "src/components/ChatLayout.jsx"() {
4009
4027
  init_TerminalBox();
@@ -4059,6 +4077,7 @@ var init_ChatLayout = __esm({
4059
4077
  /\b(true|false|null|undefined|nil|None)\b/.source,
4060
4078
  /\b(\d+(?:\.\d+)?|0x[0-9a-fA-F]+)\b/.source
4061
4079
  ];
4080
+ REGEX_SYNTAX = new RegExp(SYNTAX_RULES.join("|"), "g");
4062
4081
  tokenCache = /* @__PURE__ */ new Map();
4063
4082
  MAX_TOKEN_CACHE_SIZE = 1e3;
4064
4083
  tokenizeLine = (line, lang) => {
@@ -4070,12 +4089,12 @@ var init_ChatLayout = __esm({
4070
4089
  let lastIndex = 0;
4071
4090
  const tokens = [];
4072
4091
  let match;
4073
- const localRegex = new RegExp(SYNTAX_RULES.join("|"), "g");
4074
- while ((match = localRegex.exec(line)) !== null) {
4092
+ REGEX_SYNTAX.lastIndex = 0;
4093
+ while ((match = REGEX_SYNTAX.exec(line)) !== null) {
4075
4094
  const matchText = match[0];
4076
4095
  const matchIndex = match.index;
4077
4096
  if (matchIndex > lastIndex) {
4078
- tokens.push({ text: line.substring(lastIndex, matchIndex) });
4097
+ tokens.push({ text: flattenString(line.substring(lastIndex, matchIndex)) });
4079
4098
  }
4080
4099
  let color = void 0;
4081
4100
  let bold = false;
@@ -4093,11 +4112,11 @@ var init_ChatLayout = __esm({
4093
4112
  } else if (match[7] || match[8]) {
4094
4113
  color = "#ff9e64";
4095
4114
  }
4096
- tokens.push({ text: matchText, color, bold });
4097
- lastIndex = localRegex.lastIndex;
4115
+ tokens.push({ text: flattenString(matchText), color, bold });
4116
+ lastIndex = REGEX_SYNTAX.lastIndex;
4098
4117
  }
4099
4118
  if (lastIndex < line.length) {
4100
- tokens.push({ text: line.substring(lastIndex) });
4119
+ tokens.push({ text: flattenString(line.substring(lastIndex)) });
4101
4120
  }
4102
4121
  if (tokenCache.size >= MAX_TOKEN_CACHE_SIZE) {
4103
4122
  const firstKey = tokenCache.keys().next().value;
@@ -4106,10 +4125,10 @@ var init_ChatLayout = __esm({
4106
4125
  tokenCache.set(cacheKey, tokens);
4107
4126
  return tokens;
4108
4127
  };
4109
- renderHighlightedLine = (line, lang, defaultColor = void 0) => {
4110
- if (!line) return /* @__PURE__ */ React4.createElement(Text4, null, " ");
4128
+ renderHighlightedLine = (line, lang, defaultColor = void 0, defaultBgColor = void 0) => {
4129
+ if (!line) return /* @__PURE__ */ React4.createElement(Text4, { backgroundColor: defaultBgColor }, " ");
4111
4130
  const tokens = tokenizeLine(line, lang);
4112
- 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)));
4131
+ return /* @__PURE__ */ React4.createElement(Text4, { color: defaultColor, backgroundColor: defaultBgColor }, tokens.map((token, idx) => /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: token.color || defaultColor, backgroundColor: defaultBgColor, bold: token.bold }, token.text)));
4113
4132
  };
4114
4133
  renderLatexText = (content, key) => {
4115
4134
  if (!content) return null;
@@ -4239,7 +4258,7 @@ var init_ChatLayout = __esm({
4239
4258
  const level = headingMatch[1].length;
4240
4259
  const hText = headingMatch[2];
4241
4260
  result.push(
4242
- /* @__PURE__ */ React4.createElement(Box3, { key: i, marginTop: 1, marginBottom: 0, width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: level === 1 ? "cyan" : level === 2 ? "purple" : level === 3 ? "yellow" : level === 4 ? "green" : level === 5 ? "blue" : "white", underline: true }, hText.toUpperCase()))
4261
+ /* @__PURE__ */ React4.createElement(Box3, { key: i, marginTop: 1, marginBottom: 0, width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: level === 1 ? "cyan" : level === 2 ? "purple" : level === 3 ? "yellow" : level === 4 ? "green" : level === 5 ? "blue" : "white", underline: true }, hText))
4243
4262
  );
4244
4263
  return;
4245
4264
  }
@@ -4295,14 +4314,16 @@ var init_ChatLayout = __esm({
4295
4314
  const displayPrefix = isRemoval ? "-" : isAddition ? "+" : " ";
4296
4315
  const renderInlineDiff = () => {
4297
4316
  if (isPureUnpairedBlock) {
4298
- const blockColor = isRemoval ? "#ffdddd" : "#ddffdd";
4317
+ const blockColor = isRemoval ? "#ff3333" : "#33ff66";
4318
+ const textBgColor = isRemoval ? "#5a1818" : "#185a25";
4299
4319
  const wrappedLines = wrapText(content, columns - 15).split("\n");
4300
- return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, blockColor))));
4320
+ return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, blockColor, textBgColor))));
4301
4321
  }
4302
4322
  if (!(isRemoval || isAddition) || words.length === 0 || !hasInlineChange) {
4303
4323
  const textColor = isRemoval ? "#885555" : isAddition ? "#558866" : "gray";
4324
+ const textBgColor = void 0;
4304
4325
  const wrappedLines = wrapText(content, columns - 15).split("\n");
4305
- return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, textColor))));
4326
+ return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, textColor, textBgColor))));
4306
4327
  }
4307
4328
  return /* @__PURE__ */ React4.createElement(Text4, { wrap: "anywhere" }, words.map((part, idx) => {
4308
4329
  const isWhitespace = /^\s+$/.test(part.value);
@@ -4951,7 +4972,11 @@ var init_StatusBar = __esm({
4951
4972
  },
4952
4973
  /* @__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"))),
4953
4974
  /* @__PURE__ */ React5.createElement(Box4, { flexGrow: 1, justifyContent: "center", paddingX: 2 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", italic: true }, truncatePath(process.cwd(), 35))),
4954
- /* @__PURE__ */ React5.createElement(Box4, null, isProcessing ? /* @__PURE__ */ React5.createElement(Box4, { marginRight: 0 }, /* @__PURE__ */ React5.createElement(Text5, { color: dotColor }, "\u25CF")) : /* @__PURE__ */ React5.createElement(Text5, 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"))))
4975
+ /* @__PURE__ */ React5.createElement(Box4, null, isProcessing ? /* @__PURE__ */ React5.createElement(Box4, { marginRight: 0 }, /* @__PURE__ */ React5.createElement(Text5, { color: dotColor }, "\u25CF")) : /* @__PURE__ */ React5.createElement(Text5, null, " "), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white" }, formatTokens(tokensTotal), " ", (() => {
4976
+ const pct = tokens / maxLimit * 100;
4977
+ const color = pct < 60 ? "white" : pct < 80 ? "yellow" : "red";
4978
+ return /* @__PURE__ */ React5.createElement(Text5, { color, dimColor: true }, pct.toFixed(0), "%");
4979
+ })())), /* @__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"))))
4955
4980
  );
4956
4981
  });
4957
4982
  StatusBar_default = StatusBar;
@@ -5187,7 +5212,7 @@ ${mode === "Flux" ? `- WORKSPACE TOOLS (path = relative to CWD & WILL BE FIRST A
5187
5212
  3. [tool:functions.FileMap(path="path/file")]. Shows file structure, functions, class, import/export, variable
5188
5213
  4. [tool:functions.PatchFile(path="...", replaceContent1="full line/block", newContent1="...", ...MAX 6)]. Surgical Patch. **Multiple patch on same file/path? Use replaceContent2, newContent2 etc >>> multiple spams**. Unsure? ReadFile >> guessing. **MUST VERIFY DIFF**
5189
5214
  5. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile > WriteFile. Verify Imports
5190
- 6. [tool:functions.SearchKeyword(keyword="...", file="optional", subString="true/false optional", regex="true/false optional")]. Global project search. If 'file' is provided, searches only that file. Finds definitions/logic without reading every file. Usage: Can search for relevent lines/logic area to read specifically for edit. Optional parameters default to false
5215
+ 6. [tool:functions.SearchKeyword(keyword="...", file="optional", subString="true/false optional", regex="optional, false for keyword")]. Global project search. If 'file' is provided, searches only that file. Finds definitions/logic without reading every file. Usage: Can search for relevent lines/logic area to read specifically for edit. defaults subString: false, regex: auto-detect
5191
5216
  7. [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? `WINDOWS POWERSHELL ONLY` : `WINDOWS CMD ONLY` : `BASH`} command. Destructive/Irreversible ops \u2192 Ask user
5192
5217
  8. [tool:functions.Todo(method="create/append/get", tasks=[ARRAY OF STRINGS], markDone=[ARRAY OF TASK STRINGS])]. Task List, NO Markdown IN ARRAY. USAGE: ANALYZE USER REQUEST **IF** MULTIPLE TASK \u2192 BREAK DOWN TASK \u2192 CREATE TODO **BEFORE** DIVING IN. 'tasks' & 'markDone' OPTIONAL PARAMETERS WITH method 'get'. USE 'get' method WITH 'markDone' to mark task completed. **EVERY TURN UPDATE POLICY**
5193
5218
  9. [tool:functions.Await(time="seconds")]. For waiting without exiting agent loop, 15s - 180s
@@ -8912,8 +8937,15 @@ var init_search_keyword = __esm({
8912
8937
  const { keyword, file, subString, regex } = parseArgs(args);
8913
8938
  if (!keyword) return 'ERROR: Missing "keyword" argument.';
8914
8939
  const toBool = (v) => v === true || v === "true" || v === 1 || v === "1" || v === "yes";
8915
- const matchRegex = toBool(regex);
8916
- const matchSubstring = !matchRegex && toBool(subString);
8940
+ const regexExplicitlyFalse = regex === false || regex === "false" || regex === 0 || regex === "0" || regex === "no";
8941
+ let matchRegex = toBool(regex);
8942
+ let matchSubstring = !matchRegex && toBool(subString);
8943
+ const hasRegexIndicators = /[|]/.test(keyword) || /\\([*+?{}()|[\]\^$])/.test(keyword);
8944
+ let isAutoRegex = false;
8945
+ if (!matchRegex && !regexExplicitlyFalse && hasRegexIndicators) {
8946
+ matchRegex = true;
8947
+ isAutoRegex = true;
8948
+ }
8917
8949
  let regexPattern;
8918
8950
  let wordRegex;
8919
8951
  if (matchRegex) {
@@ -8990,7 +9022,7 @@ var init_search_keyword = __esm({
8990
9022
  if (typeof global.gc === "function") {
8991
9023
  global.gc();
8992
9024
  }
8993
- const modeLabel = matchRegex ? "(regex mode)" : matchSubstring ? "(subString mode)" : "";
9025
+ const modeLabel = matchRegex ? isAutoRegex ? "(regex mode)" : "(keyword mode)" : matchSubstring ? "(subString mode)" : "";
8994
9026
  if (fileGroups.length === 0) {
8995
9027
  return `Found 0 matches for keyword: "${keyword}"${file ? ` in file: ${file}` : ". Try to specify files"} ${modeLabel}`;
8996
9028
  }
@@ -10809,10 +10841,18 @@ var init_ai = __esm({
10809
10841
  throw new DOMException("The user aborted a request.", "AbortError");
10810
10842
  }
10811
10843
  try {
10812
- const response = await fetch(url, options);
10813
- if (response.ok) return response;
10814
- if (response.status !== 429 && response.status < 500) return response;
10844
+ const response2 = await fetch(url, options);
10845
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
10846
+ performance.clearMeasures();
10847
+ performance.clearMarks();
10848
+ }
10849
+ if (response2.ok) return response2;
10850
+ if (response2.status !== 429 && response2.status < 500) return response2;
10815
10851
  } catch (e) {
10852
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
10853
+ performance.clearMeasures();
10854
+ performance.clearMarks();
10855
+ }
10816
10856
  if (e.name === "AbortError" || signal?.aborted) throw e;
10817
10857
  if (i === retries - 1) throw e;
10818
10858
  }
@@ -10835,7 +10875,12 @@ var init_ai = __esm({
10835
10875
  if (signal?.aborted) {
10836
10876
  throw new DOMException("The user aborted a request.", "AbortError");
10837
10877
  }
10838
- return fetch(url, options);
10878
+ const response = await fetch(url, options);
10879
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
10880
+ performance.clearMeasures();
10881
+ performance.clearMarks();
10882
+ }
10883
+ return response;
10839
10884
  };
10840
10885
  getDeepSeekStream = async function* (apiKey, model, contents, systemInstruction, thinkingLevel, mode, isMultiModal, signal, temperature = 0.99) {
10841
10886
  const messages = [];
@@ -11546,7 +11591,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
11546
11591
  } else if (aiProvider === "NVIDIA") {
11547
11592
  const stream = getNVIDIAStream(
11548
11593
  apiKey,
11549
- "moonshotai/kimi-k2.6",
11594
+ "deepseek-ai/deepseek-v4-flash",
11550
11595
  janitorContents,
11551
11596
  janitorPrompt,
11552
11597
  "Fast",
@@ -11984,6 +12029,32 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
11984
12029
  if (!apiKey) return null;
11985
12030
  globalSettings = settings;
11986
12031
  client = new GoogleGenAI({ apiKey });
12032
+ if (!globalThis.__perfCleanupInstalled) {
12033
+ globalThis.__perfCleanupInstalled = true;
12034
+ setInterval(() => {
12035
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
12036
+ performance.clearMeasures();
12037
+ performance.clearMarks();
12038
+ }
12039
+ }, 6e4);
12040
+ const originalFetch = globalThis.fetch;
12041
+ globalThis.fetch = async (...args) => {
12042
+ try {
12043
+ const response = await originalFetch(...args);
12044
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
12045
+ performance.clearMeasures();
12046
+ performance.clearMarks();
12047
+ }
12048
+ return response;
12049
+ } catch (e) {
12050
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
12051
+ performance.clearMeasures();
12052
+ performance.clearMarks();
12053
+ }
12054
+ throw e;
12055
+ }
12056
+ };
12057
+ }
11987
12058
  return client;
11988
12059
  };
11989
12060
  generateSimpleContent = async (settings, model, contents, systemInstruction, thinkingLevel = "Fast", temperature = 0.75, usageKey = "agent") => {
@@ -12141,7 +12212,7 @@ ${newMemoryListStr}
12141
12212
  let targetModel = "gemma-4-26b-a4b-it";
12142
12213
  if (aiProvider === "OpenRouter") targetModel = "google/gemma-4-26b-a4b-it:free";
12143
12214
  if (aiProvider === "DeepSeek") targetModel = "deepseek-v4-flash";
12144
- if (aiProvider === "NVIDIA") targetModel = "moonshotai/kimi-k2.6";
12215
+ if (aiProvider === "NVIDIA") targetModel = "deepseek-ai/deepseek-v4-flash";
12145
12216
  while (attempts <= maxAttempts && !success) {
12146
12217
  attempts++;
12147
12218
  try {
@@ -12208,7 +12279,7 @@ Provide a consolidated summary of the entire session.`;
12208
12279
  let targetModel = "gemma-4-26b-a4b-it";
12209
12280
  if (aiProvider === "OpenRouter") targetModel = "google/gemma-4-26b-a4b-it:free";
12210
12281
  if (aiProvider === "DeepSeek") targetModel = "deepseek-v4-flash";
12211
- if (aiProvider === "NVIDIA") targetModel = "moonshotai/kimi-k2.6";
12282
+ if (aiProvider === "NVIDIA") targetModel = "deepseek-ai/deepseek-v4-flash";
12212
12283
  let attempts = 0;
12213
12284
  let success = false;
12214
12285
  let response = null;
@@ -12900,7 +12971,7 @@ ${boxMid}
12900
12971
  }
12901
12972
  let taggedContextStr = "";
12902
12973
  if (taggedContextBlocks.length > 0) {
12903
- taggedContextStr = "[TAGGED CONTEXT]\n" + taggedContextBlocks.join("\n\n") + "\n[/TAGGED CONTEXT]\n";
12974
+ taggedContextStr = "[TAGGED FILE CONTENTS] Auto Read, System Provided Context\n" + taggedContextBlocks.join("\n\n") + "\n[/TAGGED FILE CONTENTS]\n";
12904
12975
  }
12905
12976
  const osDetected = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
12906
12977
  const firstUserMsg = `[SYSTEM METADATA (PRIORITY: DYNAMIC), Chat Context >> Metadata] Time: ${dateTimeStr}
@@ -12908,7 +12979,7 @@ OS: ${osDetected}
12908
12979
  CWD: ${process.cwd()}${isPlayground ? " [PLAYGROUND MODE]" : ""}${cwdMismatch ? ` (WARNING: CWD Mismatch! Previous Path: ${lastCwd})` : ""}
12909
12980
  **DIRECTORY STRUCTURE**
12910
12981
  ${dirStructure}${memoryPrompt}${ideBlock}
12911
- ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && aiProvider === "Google" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS CRITICAL PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]\n" : ""}` : ""}${taggedContextStr}[USER] ${cleanAgentText.trim()} [/USER]`.trim();
12982
+ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && aiProvider === "Google" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]\n" : ""}` : "\n"}${taggedContextStr}[USER PROMPT] ${cleanAgentText.trim()} [/USER PROMPT]`.trim();
12912
12983
  const userMsgObj = { role: "user", text: firstUserMsg };
12913
12984
  if (attachedBinaryPart) {
12914
12985
  userMsgObj.binaryPart = attachedBinaryPart;
@@ -12954,7 +13025,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
12954
13025
  [SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY [/SYSTEM]
12955
13026
  [QUESTION] ${hint.replace("/btw", "").trim()} [/QUESTION]`;
12956
13027
  } else {
12957
- modifiedHistory.push({ role: "user", text: `${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && aiProvider === "Google" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY\n**STRICTLY FOLLOW THINKING POLICY AS CRITICAL PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]\n" : ""}` : ""}[QUESTION] ${hint.replace("/btw", "").trim()} [/QUESTION]` });
13028
+ modifiedHistory.push({ role: "user", text: `${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && aiProvider === "Google" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY\n**STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]\n" : ""}` : ""}[QUESTION] ${hint.replace("/btw", "").trim()} [/QUESTION]` });
12958
13029
  }
12959
13030
  } else {
12960
13031
  if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "user") {
@@ -12962,7 +13033,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
12962
13033
 
12963
13034
  [STEERING HINT] ${hint.trim()} [/STEERING HINT]`;
12964
13035
  } else {
12965
- modifiedHistory.push({ role: "user", text: `${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && aiProvider === "Google" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS CRITICAL PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]\n" : ""}` : ""}[STEERING HINT] ${hint.trim()} [/STEERING HINT]` });
13036
+ modifiedHistory.push({ role: "user", text: `${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && aiProvider === "Google" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]\n" : ""}` : ""}[STEERING HINT] ${hint.trim()} [/STEERING HINT]` });
12966
13037
  }
12967
13038
  }
12968
13039
  yield { type: "status", content: `${hint.startsWith("/btw") ? "Question Forwarded..." : "Steering Hint Injected..."}` };
@@ -14904,8 +14975,8 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
14904
14975
 
14905
14976
  [SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY [/SYSTEM]
14906
14977
  `, "").replace(`[SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY
14907
- **STRICTLY FOLLOW THINKING POLICY AS CRITICAL PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
14908
- `, "").replace(`[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS CRITICAL PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
14978
+ **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
14979
+ `, "").replace(`[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
14909
14980
  `, "");
14910
14981
  if (modelName && modelName.toLowerCase().startsWith("gemma") && aiProvider === "Google" && msg.text.startsWith("[TOOL RESULT]")) {
14911
14982
  const jitInstructionFast = `
@@ -14942,6 +15013,10 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
14942
15013
  clearInterval(connectionPollInterval);
14943
15014
  connectionPollInterval = null;
14944
15015
  }
15016
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
15017
+ performance.clearMeasures();
15018
+ performance.clearMarks();
15019
+ }
14945
15020
  await RevertManager.commitTransaction();
14946
15021
  if (systemSettings?.advanceRollback) {
14947
15022
  await AdvanceRevertManager.cleanup(chatId);
@@ -14959,7 +15034,7 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
14959
15034
  "filemap": '- [tool:functions.FileMap(path="path/file")]. Shows file structure, functions, classes, imports/exports',
14960
15035
  "patchfile": '- [tool:functions.PatchFile(path="...", replaceContent1="...", newContent1="...")]. Surgical block replacement for editing files',
14961
15036
  "writefile": '- [tool:functions.WriteFile(path="...", content="...")]. Creates or overwrites a file',
14962
- "searchkeyword": `- [tool:functions.SearchKeyword(keyword="...", file="optional", subString="true/false optional", regex="true/false optional")]. Global project search. If 'file' is provided, searches only that file. Finds definitions/logic without reading every file. Usage: Can search for relevent lines/logic area to read specifically for edit. Optional parameters default to false`,
15037
+ "searchkeyword": `- [tool:functions.SearchKeyword(keyword="...", file="optional", subString="true/false optional", regex="optional, false for keyword")]. Global project search. If 'file' is provided, searches only that file. Finds definitions/logic without reading every file. Usage: Can search for relevent lines/logic area to read specifically for edit. defaults subString: false, regex: auto-detect`,
14963
15038
  "websearch": '- [tool:functions.WebSearch(query="...", limit=number)]. Web Search',
14964
15039
  "webscrape": '- [tool:functions.WebScrape(url="...")]. Web Scrape',
14965
15040
  "ask": `- [tool:functions.Ask(question="...", optionA="option::description", ...MAX 4)]. Ambiguity Resolution. Mandatory Triggers: Path Divergence, Security, Risk Mitigation. ask >> finish/guess. Suggest best options; don't ask for preferences. 'option' SHOULD be short`
@@ -15051,17 +15126,20 @@ ${cleanResponse}
15051
15126
  } else if (normalizedToolName === "web_scrape" || normalizedToolName === "webscrape") {
15052
15127
  label = `\u2714 \x1B[95mScraped\x1B[0m`;
15053
15128
  } else if (normalizedToolName === "view_file" || normalizedToolName === "viewfile" || normalizedToolName === "readfile") {
15054
- label = `\u2714 \x1B[95mRead File\x1B[0m`;
15129
+ const path23 = parseArgs(toolCall.args).path || "";
15130
+ label = `\u2714 \x1B[95mRead File\x1B[0m: ${path23}`;
15055
15131
  } else if (normalizedToolName === "list_files" || normalizedToolName === "read_folder" || normalizedToolName === "readfolder") {
15056
- label = `\u2714 \x1B[95mBrowsed Folder\x1B[0m`;
15132
+ const path23 = parseArgs(toolCall.args).path || "";
15133
+ label = `\u2714 \x1B[95mBrowsed Folder\x1B[0m: ${path23}`;
15057
15134
  } else if (normalizedToolName === "write_file" || normalizedToolName === "writefile") {
15058
- const path23 = parseArgs(toolCall.args).path || "...";
15135
+ const path23 = parseArgs(toolCall.args).path || "";
15059
15136
  label = `\u2714 \x1B[95mFile Created\x1B[0m: ${path23}`;
15060
15137
  } else if (normalizedToolName === "update_file" || normalizedToolName === "updatefile" || normalizedToolName === "patchfile" || normalizedToolName === "patch_file" || normalizedToolName === "patchfile" || normalizedToolName === "updatefile") {
15061
- const path23 = parseArgs(toolCall.args).path || "...";
15138
+ const path23 = parseArgs(toolCall.args).path || "";
15062
15139
  label = `\u2714 \x1B[95mFile Edited\x1B[0m: ${path23}`;
15063
15140
  } else if (normalizedToolName === "file_map" || normalizedToolName === "filemap") {
15064
- label = `\u2714 \x1B[95mIndexed\x1B[0m`;
15141
+ const path23 = parseArgs(toolCall.args).path || "";
15142
+ label = `\u2714 \x1B[95mIndexed\x1B[0m: ${path23}`;
15065
15143
  } else if (normalizedToolName === "await") {
15066
15144
  const { time } = parseArgs(toolCall.args);
15067
15145
  let sec = parseFloat(time) || 0;
@@ -16084,7 +16162,7 @@ import TextInput4 from "ink-text-input";
16084
16162
  import SelectInput2 from "ink-select-input";
16085
16163
  import gradient2 from "gradient-string";
16086
16164
  function App({ args = [] }) {
16087
- let lastGCTime = 1;
16165
+ const lastGCTimeRef = useRef4(1);
16088
16166
  const [confirmExit, setConfirmExit] = useState15(false);
16089
16167
  const [exitCountdown, setExitCountdown] = useState15(10);
16090
16168
  const { stdout } = useStdout2();
@@ -16102,6 +16180,78 @@ function App({ args = [] }) {
16102
16180
  const [promoSelectedIndex, setPromoSelectedIndex] = useState15(0);
16103
16181
  const suggestionOffsetRef = useRef4(0);
16104
16182
  const persistedModelRef = useRef4(null);
16183
+ const activeStreamingMsgRef = useRef4(null);
16184
+ const [renderTick, setRenderTick] = useState15(0);
16185
+ const forceRender = () => setRenderTick((t) => t + 1);
16186
+ const typewriterQueueRef = useRef4([]);
16187
+ const typewriterTickRef = useRef4(null);
16188
+ const commitActiveStreamingMessage = () => {
16189
+ if (activeStreamingMsgRef.current) {
16190
+ const msg = {
16191
+ ...activeStreamingMsgRef.current,
16192
+ text: flattenString(activeStreamingMsgRef.current.text),
16193
+ isStreaming: false
16194
+ };
16195
+ setMessages((prev) => {
16196
+ const next = [...prev, msg];
16197
+ setCompletedIndex(next.length);
16198
+ return next;
16199
+ });
16200
+ activeStreamingMsgRef.current = null;
16201
+ }
16202
+ };
16203
+ const startTypewriter = () => {
16204
+ if (typewriterTickRef.current) {
16205
+ clearInterval(typewriterTickRef.current);
16206
+ }
16207
+ typewriterQueueRef.current = [];
16208
+ typewriterTickRef.current = setInterval(() => {
16209
+ const queue = typewriterQueueRef.current;
16210
+ if (queue.length > 0 && activeStreamingMsgRef.current) {
16211
+ let batchSize = 2;
16212
+ if (queue.length > 65) batchSize = 16;
16213
+ else if (queue.length > 50) batchSize = 12;
16214
+ else if (queue.length > 35) batchSize = 8;
16215
+ else if (queue.length > 15) batchSize = 6;
16216
+ else if (queue.length > 5) batchSize = 4;
16217
+ let batchedText = "";
16218
+ for (let i = 0; i < batchSize && queue.length > 0; i++) {
16219
+ batchedText += queue.shift();
16220
+ }
16221
+ activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + batchedText);
16222
+ forceRender();
16223
+ }
16224
+ }, 100);
16225
+ };
16226
+ const awaitTypewriter = async () => {
16227
+ while (systemSettings.progressiveRendering && typewriterQueueRef.current.length > 0) {
16228
+ await new Promise((resolve) => setTimeout(resolve, 10));
16229
+ }
16230
+ };
16231
+ const flushTypewriterNow = () => {
16232
+ const queue = typewriterQueueRef.current;
16233
+ if (queue.length > 0 && activeStreamingMsgRef.current) {
16234
+ const remaining = queue.join("");
16235
+ queue.length = 0;
16236
+ activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + remaining);
16237
+ forceRender();
16238
+ }
16239
+ };
16240
+ const appendStreamText = (chunkText) => {
16241
+ if (systemSettings.progressiveRendering && typewriterTickRef.current) {
16242
+ const tokens = chunkText.split(/(\s+)/).filter(Boolean);
16243
+ for (const tok of tokens) {
16244
+ typewriterQueueRef.current.push(tok);
16245
+ }
16246
+ } else {
16247
+ if (!activeStreamingMsgRef.current) {
16248
+ activeStreamingMsgRef.current = { id: "agent-" + Date.now(), role: "agent", text: flattenString(chunkText), isStreaming: true };
16249
+ } else {
16250
+ activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + chunkText);
16251
+ }
16252
+ forceRender();
16253
+ }
16254
+ };
16105
16255
  useEffect12(() => {
16106
16256
  const ideName = getIDEName();
16107
16257
  const isIDE = !["Terminal", "Windows Terminal"].includes(ideName) || !!process.env.VSC_TERMINAL_URL;
@@ -16115,10 +16265,10 @@ function App({ args = [] }) {
16115
16265
  setShowBridgePromo(false);
16116
16266
  }
16117
16267
  }, 1e3);
16118
- lastGCTime = Date.now();
16268
+ lastGCTimeRef.current = Date.now();
16119
16269
  const memInterval = setInterval(() => {
16120
- if (lastGCTime) {
16121
- const diff = Date.now() - lastGCTime || 0;
16270
+ if (lastGCTimeRef.current) {
16271
+ const diff = Date.now() - lastGCTimeRef.current || 0;
16122
16272
  if (diff > 3e4) {
16123
16273
  if (global.gc) {
16124
16274
  const gCAsync = async () => {
@@ -16126,7 +16276,7 @@ function App({ args = [] }) {
16126
16276
  global.gc();
16127
16277
  await new Promise((resolve) => setImmediate(resolve));
16128
16278
  }
16129
- lastGCTime = Date.now();
16279
+ lastGCTimeRef.current = Date.now();
16130
16280
  };
16131
16281
  gCAsync();
16132
16282
  }
@@ -16480,8 +16630,8 @@ function App({ args = [] }) {
16480
16630
  defaultModel = "deepseek-v4-flash";
16481
16631
  modelDisplayName = "DeepSeek Flash (Free default)";
16482
16632
  } else if (aiProvider === "NVIDIA") {
16483
- defaultModel = "stepfun-ai/step-3.7-flash";
16484
- modelDisplayName = "Step 3.7 Flash (NVIDIA)";
16633
+ defaultModel = "deepseek-ai/deepseek-v4-flash";
16634
+ modelDisplayName = "DeepSeek V4 Flash (NVIDIA)";
16485
16635
  } else {
16486
16636
  defaultModel = "google/gemma-4-31b-it:free";
16487
16637
  modelDisplayName = "Gemma 4 (Free default)";
@@ -16494,8 +16644,8 @@ function App({ args = [] }) {
16494
16644
  defaultModel = "deepseek-v4-flash";
16495
16645
  modelDisplayName = "DeepSeek Flash";
16496
16646
  } else if (aiProvider === "NVIDIA") {
16497
- defaultModel = "stepfun-ai/step-3.7-flash";
16498
- modelDisplayName = "Step 3.7 Flash (NVIDIA)";
16647
+ defaultModel = "deepseek-ai/deepseek-v4-flash";
16648
+ modelDisplayName = "DeepSeek V4 Flash (NVIDIA)";
16499
16649
  } else {
16500
16650
  defaultModel = "deepseek/deepseek-v4-flash";
16501
16651
  modelDisplayName = "DeepSeek Flash";
@@ -16556,7 +16706,7 @@ function App({ args = [] }) {
16556
16706
  const [wittyPhrase, setWittyPhrase] = useState15("");
16557
16707
  const [hasPasteBlock, setHasPasteBlock] = useState15(false);
16558
16708
  const [activeTime, setActiveTime] = useState15(0);
16559
- const activeTimeIntervalRef = useRef4(null);
16709
+ let interval_for_timer;
16560
16710
  useEffect12(() => {
16561
16711
  let interval;
16562
16712
  if (statusText && systemSettings.loadingPhrases !== false) {
@@ -16667,11 +16817,6 @@ function App({ args = [] }) {
16667
16817
  }, [messages]);
16668
16818
  const [completedIndex, setCompletedIndex] = useState15(messages.length);
16669
16819
  const [clearKey, setClearKey] = useState15(0);
16670
- const [activeStreamMessages, setActiveStreamMessages] = useState15([]);
16671
- const activeStreamMessagesRef = useRef4([]);
16672
- const typewriterQueueRef = useRef4([]);
16673
- const typewriterIntervalRef = useRef4(null);
16674
- const streamFinishedRef = useRef4(false);
16675
16820
  const lastCompletedBlocksRef = useRef4([]);
16676
16821
  const cachedHistoryRef = useRef4({
16677
16822
  completedIndex: 0,
@@ -16745,7 +16890,7 @@ function App({ args = [] }) {
16745
16890
  };
16746
16891
  }
16747
16892
  }
16748
- const activeMsgs = activeStreamMessages;
16893
+ const activeMsgs = messages.slice(completedIndex);
16749
16894
  const streamingCompletedBlocks = [];
16750
16895
  const activeBlocks = [];
16751
16896
  for (let i = 0; i < activeMsgs.length; i++) {
@@ -16761,19 +16906,14 @@ function App({ args = [] }) {
16761
16906
  for (let j = 0; j < parsed.completed.length; j++) streamingCompletedBlocks.push(parsed.completed[j]);
16762
16907
  for (let j = 0; j < parsed.active.length; j++) activeBlocks.push(parsed.active[j]);
16763
16908
  }
16764
- const finalCompleted = historicalBlocks.map((block) => {
16765
- if (block.type === "full-message" && block.msg) {
16766
- const latestMsg = messages.find((m) => m.id === block.msg.id);
16767
- if (latestMsg && latestMsg !== block.msg) {
16768
- return { ...block, msg: latestMsg };
16769
- }
16770
- }
16771
- return block;
16772
- });
16773
- for (let j = 0; j < streamingCompletedBlocks.length; j++) {
16774
- finalCompleted.push(streamingCompletedBlocks[j]);
16909
+ if (activeStreamingMsgRef.current) {
16910
+ const parsed = parseMessageToBlocks(activeStreamingMsgRef.current, columns);
16911
+ for (let j = 0; j < parsed.completed.length; j++) streamingCompletedBlocks.push(parsed.completed[j]);
16912
+ for (let j = 0; j < parsed.active.length; j++) activeBlocks.push(parsed.active[j]);
16775
16913
  }
16914
+ let finalCompleted = streamingCompletedBlocks.length === 0 ? historicalBlocks : historicalBlocks.concat(streamingCompletedBlocks);
16776
16915
  if (finalCompleted.length >= 75e3) {
16916
+ finalCompleted = [...finalCompleted];
16777
16917
  finalCompleted.push({
16778
16918
  key: `memory-warning-block-${finalCompleted.length}`,
16779
16919
  msg: {
@@ -16789,7 +16929,7 @@ function App({ args = [] }) {
16789
16929
  completed: finalCompleted,
16790
16930
  active: activeBlocks
16791
16931
  };
16792
- }, [messages, activeStreamMessages, completedIndex, terminalSize.columns, clearKey, chatId]);
16932
+ }, [messages, completedIndex, terminalSize.columns, clearKey, chatId, renderTick]);
16793
16933
  const isTerminalWaitingForInput = useMemo2(() => {
16794
16934
  if (!activeCommand || !execOutput) return false;
16795
16935
  const lastChunk = execOutput.trim();
@@ -17087,7 +17227,7 @@ function App({ args = [] }) {
17087
17227
  } else if (startupProvider === "OpenRouter") {
17088
17228
  defaultModel = "google/gemma-4-31b-it:free";
17089
17229
  } else if (startupProvider === "NVIDIA") {
17090
- defaultModel = "stepfun-ai/step-3.7-flash";
17230
+ defaultModel = "deepseek-ai/deepseek-v4-flash";
17091
17231
  }
17092
17232
  } else {
17093
17233
  if (startupProvider === "Google") {
@@ -17097,7 +17237,7 @@ function App({ args = [] }) {
17097
17237
  } else if (startupProvider === "OpenRouter") {
17098
17238
  defaultModel = "deepseek/deepseek-v4-flash";
17099
17239
  } else if (startupProvider === "NVIDIA") {
17100
- defaultModel = "stepfun-ai/step-3.7-flash";
17240
+ defaultModel = "deepseek-ai/deepseek-v4-flash";
17101
17241
  }
17102
17242
  }
17103
17243
  setActiveModel(defaultModel);
@@ -17314,7 +17454,7 @@ function App({ args = [] }) {
17314
17454
  } else if (aiProvider === "DeepSeek") {
17315
17455
  defaultModel = "deepseek-v4-flash";
17316
17456
  } else if (aiProvider === "NVIDIA") {
17317
- defaultModel = "stepfun-ai/step-3.7-flash";
17457
+ defaultModel = "deepseek-ai/deepseek-v4-flash";
17318
17458
  }
17319
17459
  setActiveModel(defaultModel);
17320
17460
  setMessages((prev) => [...prev, { role: "system", text: `${aiProvider} API Key saved successfully! Model set to ${defaultModel}. Initialization complete.`, isMeta: true }]);
@@ -17491,10 +17631,6 @@ function App({ args = [] }) {
17491
17631
  cmd: "moonshotai/kimi-k2.7",
17492
17632
  desc: "Multimodal"
17493
17633
  },
17494
- {
17495
- cmd: "moonshotai/kimi-k2.6",
17496
- desc: "[DEPRICATED]"
17497
- },
17498
17634
  // --- DeepSeek Family ---
17499
17635
  {
17500
17636
  cmd: "deepseek-ai/deepseek-v4-flash",
@@ -17877,7 +18013,7 @@ ${cleanText}`, color: "magenta" }];
17877
18013
  global.gc();
17878
18014
  await new Promise((resolve) => setImmediate(resolve));
17879
18015
  }
17880
- lastGCTime = Date.now();
18016
+ lastGCTimeRef.current = Date.now();
17881
18017
  };
17882
18018
  gCAsync();
17883
18019
  }
@@ -17904,7 +18040,7 @@ ${cleanText}`, color: "magenta" }];
17904
18040
  global.gc();
17905
18041
  await new Promise((resolve) => setImmediate(resolve));
17906
18042
  }
17907
- lastGCTime = Date.now();
18043
+ lastGCTimeRef.current = Date.now();
17908
18044
  };
17909
18045
  gCAsync();
17910
18046
  }
@@ -18523,27 +18659,15 @@ ${timestamp}` };
18523
18659
  const appendCancelMessage = () => {
18524
18660
  if (didAppendCancel) return;
18525
18661
  didAppendCancel = true;
18526
- const dangling = activeStreamMessagesRef.current;
18527
- activeStreamMessagesRef.current = [];
18528
- setActiveStreamMessages([]);
18529
- if (typewriterIntervalRef.current) {
18530
- clearInterval(typewriterIntervalRef.current);
18531
- typewriterIntervalRef.current = null;
18532
- }
18533
- typewriterQueueRef.current = [];
18534
18662
  setMessages((prev) => {
18535
18663
  const lastMsg = prev[prev.length - 1];
18536
18664
  if (lastMsg && lastMsg.text && lastMsg.text.includes("Request Cancelled")) {
18537
18665
  return prev;
18538
18666
  }
18539
- const flushed = dangling.map((m) => {
18540
- const flatText = m.text ? (" " + m.text).slice(1) : m.text;
18541
- return { ...m, isStreaming: false, text: flatText };
18542
- });
18543
- const updatedPrev = [...prev, ...flushed].map((m) => m.isStreaming ? { ...m, isStreaming: false } : m);
18667
+ const updatedPrev = prev.map((m) => m.isStreaming ? { ...m, isStreaming: false } : m);
18544
18668
  const newMsgs = [...updatedPrev, {
18545
18669
  id: "cancel-" + Date.now(),
18546
- role: "system",
18670
+ role: "agent",
18547
18671
  text: "\n\n\x1B[33m\u24D8 Request Cancelled\x1B[0m",
18548
18672
  isMeta: false
18549
18673
  }];
@@ -18551,161 +18675,6 @@ ${timestamp}` };
18551
18675
  return newMsgs;
18552
18676
  });
18553
18677
  };
18554
- const finalizeTurn = async (apiStartVal) => {
18555
- const dangling = activeStreamMessagesRef.current;
18556
- if (dangling.length > 0) {
18557
- activeStreamMessagesRef.current = [];
18558
- setActiveStreamMessages([]);
18559
- setMessages((prev) => {
18560
- const totalDuration = Date.now() - apiStartVal;
18561
- const flushed = dangling.map((m) => {
18562
- const flatText = m.text ? (" " + m.text).slice(1) : m.text;
18563
- return {
18564
- ...m,
18565
- isStreaming: false,
18566
- text: flatText,
18567
- workedDuration: m.role === "agent" ? totalDuration : m.workedDuration
18568
- };
18569
- });
18570
- const newMsgs = [...prev, ...flushed];
18571
- setCompletedIndex(newMsgs.length);
18572
- return newMsgs;
18573
- });
18574
- }
18575
- setIsProcessing(false);
18576
- setStatusText(null);
18577
- setActiveTime(0);
18578
- clearInterval(activeTimeIntervalRef.current);
18579
- if (didSignalTerminationRef.current) {
18580
- appendCancelMessage();
18581
- }
18582
- clearBlocksCache();
18583
- if (global.gc) {
18584
- try {
18585
- for (let i = 0; i < 3; i++) {
18586
- global.gc();
18587
- await new Promise((resolve) => setImmediate(resolve));
18588
- }
18589
- lastGCTime = Date.now();
18590
- } catch (e) {
18591
- }
18592
- }
18593
- if (!hasFiredJanitor) {
18594
- if (process.stdout.isTTY) {
18595
- process.stdout.write("\x1B]0;FluxFlow | Idle\x07");
18596
- process.stdout.write("\x1B]633;P;TerminalTitle=FluxFlow | Idle\x07");
18597
- }
18598
- }
18599
- if (queuedPromptRef.current) {
18600
- setResolutionData(queuedPromptRef.current);
18601
- setQueuedPrompt(null);
18602
- const hintToResolve = queuedPromptRef.current;
18603
- queuedPromptRef.current = null;
18604
- setMessages((prev) => {
18605
- const newMsgs = [...prev];
18606
- const hintMsg = newMsgs.reverse().find((m) => m.text?.includes("[STEERING HINT: QUEUED]") || m.text?.includes("[QUESTION: QUEUED]"));
18607
- if (hintMsg) {
18608
- if (hintMsg.text.includes("[STEERING HINT: QUEUED]")) {
18609
- hintMsg.text = hintMsg.text.replace("[STEERING HINT: QUEUED]", "[STEERING HINT: FINISHED_TURN]");
18610
- } else if (hintMsg.text.includes("[QUESTION: QUEUED]")) {
18611
- hintMsg.text = hintMsg.text.replace("[QUESTION: QUEUED]", "[QUESTION: FINISHED_TURN]");
18612
- }
18613
- }
18614
- return newMsgs.reverse();
18615
- });
18616
- setActiveView("resolution");
18617
- }
18618
- setMessages((prev) => {
18619
- const totalDuration = Date.now() - apiStartVal;
18620
- let foundLastAgent = false;
18621
- const newMsgs = [...prev].reverse().map((m) => {
18622
- let updated = m.isStreaming ? { ...m, isStreaming: false } : m;
18623
- if (updated.text) {
18624
- updated.text = (" " + updated.text).slice(1);
18625
- }
18626
- if (!foundLastAgent && updated.role === "agent") {
18627
- foundLastAgent = true;
18628
- updated = { ...updated, workedDuration: totalDuration };
18629
- }
18630
- return updated;
18631
- }).reverse();
18632
- const historyToSave = newMsgs.filter((m) => !String(m.id).startsWith("welcome") && (!m.isMeta || m.text && m.text.includes("Request Cancelled")));
18633
- saveChat(chatId, null, historyToSave);
18634
- setCompletedIndex(newMsgs.length);
18635
- return newMsgs;
18636
- });
18637
- };
18638
- const pushTokenText = (id, text) => {
18639
- if (systemSettings.progressiveRendering) {
18640
- const tokens = text.split(/(\s+)/).filter(Boolean);
18641
- for (const tok of tokens) {
18642
- typewriterQueueRef.current.push({ type: "text", id, text: tok });
18643
- }
18644
- }
18645
- };
18646
- const startTypewriter = (apiStartVal) => {
18647
- if (typewriterIntervalRef.current) {
18648
- clearInterval(typewriterIntervalRef.current);
18649
- }
18650
- streamFinishedRef.current = false;
18651
- typewriterQueueRef.current = [];
18652
- typewriterIntervalRef.current = setInterval(() => {
18653
- const queue = typewriterQueueRef.current;
18654
- if (queue.length > 0) {
18655
- let batchSize = 2;
18656
- if (queue.length > 65) batchSize = 16;
18657
- else if (queue.length > 50) batchSize = 12;
18658
- else if (queue.length > 35) batchSize = 8;
18659
- else if (queue.length > 15) batchSize = 6;
18660
- else if (queue.length > 5) batchSize = 4;
18661
- let changed = false;
18662
- const nextMsgs = [...activeStreamMessagesRef.current];
18663
- const clonedIndices = /* @__PURE__ */ new Set();
18664
- for (let i = 0; i < batchSize; i++) {
18665
- if (queue.length === 0) break;
18666
- const task = queue.shift();
18667
- if (task.type === "create") {
18668
- nextMsgs.push(task.msg);
18669
- changed = true;
18670
- } else if (task.type === "text") {
18671
- const idx = nextMsgs.findIndex((m) => m.id === task.id);
18672
- if (idx !== -1) {
18673
- if (!clonedIndices.has(idx)) {
18674
- nextMsgs[idx] = { ...nextMsgs[idx] };
18675
- clonedIndices.add(idx);
18676
- }
18677
- nextMsgs[idx].text += task.text;
18678
- changed = true;
18679
- }
18680
- } else if (task.type === "finalize-think") {
18681
- const idx = nextMsgs.findIndex((m) => m.id === task.id);
18682
- if (idx !== -1) {
18683
- if (!clonedIndices.has(idx)) {
18684
- nextMsgs[idx] = { ...nextMsgs[idx] };
18685
- clonedIndices.add(idx);
18686
- }
18687
- nextMsgs[idx].isStreaming = false;
18688
- nextMsgs[idx].duration = task.duration;
18689
- changed = true;
18690
- }
18691
- }
18692
- }
18693
- if (changed) {
18694
- activeStreamMessagesRef.current = nextMsgs;
18695
- setActiveStreamMessages(nextMsgs);
18696
- }
18697
- } else if (streamFinishedRef.current) {
18698
- clearInterval(typewriterIntervalRef.current);
18699
- typewriterIntervalRef.current = null;
18700
- finalizeTurn(apiStartVal);
18701
- }
18702
- }, 100);
18703
- };
18704
- const awaitTypewriter = async () => {
18705
- while (systemSettings.progressiveRendering && typewriterQueueRef.current.length > 0) {
18706
- await new Promise((resolve) => setTimeout(resolve, 10));
18707
- }
18708
- };
18709
18678
  let hasFiredJanitor = false;
18710
18679
  setIsProcessing(true);
18711
18680
  setLastChunkTime(Date.now());
@@ -18797,6 +18766,8 @@ ${timestamp}` };
18797
18766
  setActiveCommand(null);
18798
18767
  setIsTerminalFocused(false);
18799
18768
  setExecOutput("");
18769
+ activeCommandRef.current = null;
18770
+ execOutputRef.current = "";
18800
18771
  },
18801
18772
  onToolResult: (status, toolName) => {
18802
18773
  if (status === "success") {
@@ -18927,6 +18898,7 @@ Selection: ${val}`,
18927
18898
  let inToolCallString = null;
18928
18899
  const signalRegex = /\[?\s*turn\s*:\s*.*?\s*\]?/gi;
18929
18900
  for await (const packet of stream) {
18901
+ await new Promise((resolve) => setTimeout(resolve, 3));
18930
18902
  if (packet.type === "text") {
18931
18903
  setLastChunkTime(Date.now());
18932
18904
  }
@@ -18934,7 +18906,7 @@ Selection: ${val}`,
18934
18906
  apiStart = Date.now();
18935
18907
  isFirstPacket = false;
18936
18908
  if (systemSettings.progressiveRendering) {
18937
- startTypewriter(apiStart);
18909
+ startTypewriter();
18938
18910
  }
18939
18911
  }
18940
18912
  if (packet.type === "status") {
@@ -18942,19 +18914,21 @@ Selection: ${val}`,
18942
18914
  setStatusText(packet.content);
18943
18915
  }
18944
18916
  if (packet.content?.includes("[start]")) {
18945
- clearInterval(activeTimeIntervalRef.current);
18917
+ clearInterval(interval_for_timer);
18946
18918
  setActiveTime(0);
18947
- activeTimeIntervalRef.current = setInterval(() => {
18919
+ interval_for_timer = setInterval(() => {
18948
18920
  setActiveTime((prev) => prev + 1);
18949
18921
  }, 1e3);
18950
18922
  } else if (packet.content?.includes("[end]")) {
18951
18923
  setActiveTime(0);
18952
- clearInterval(activeTimeIntervalRef.current);
18924
+ clearInterval(interval_for_timer);
18953
18925
  }
18954
18926
  if (isBridgeConnected()) {
18955
18927
  sendStatus(packet.content);
18956
18928
  }
18957
18929
  if (packet.content === "Request Cancelled") {
18930
+ flushTypewriterNow();
18931
+ commitActiveStreamingMessage();
18958
18932
  appendCancelMessage();
18959
18933
  }
18960
18934
  continue;
@@ -18982,9 +18956,7 @@ Selection: ${val}`,
18982
18956
  continue;
18983
18957
  }
18984
18958
  if (packet.type === "turn_reset") {
18985
- if (systemSettings.progressiveRendering) {
18986
- await awaitTypewriter();
18987
- }
18959
+ flushTypewriterNow();
18988
18960
  currentThinkId = null;
18989
18961
  currentAgentId = null;
18990
18962
  inThinkMode = false;
@@ -18992,40 +18964,32 @@ Selection: ${val}`,
18992
18964
  inToolCall = false;
18993
18965
  toolCallEncounteredInTurn = false;
18994
18966
  thinkConsumedInTurn = false;
18995
- const streamingMsgs = activeStreamMessagesRef.current;
18996
- activeStreamMessagesRef.current = [];
18997
- setActiveStreamMessages([]);
18998
18967
  setMessages((prev) => {
18999
- const totalDuration = Date.now() - apiStart;
19000
- const flushed = streamingMsgs.map((m) => {
19001
- const flatText = m.text ? (" " + m.text).slice(1) : m.text;
19002
- const flatFullText = m.fullText ? (" " + m.fullText).slice(1) : m.fullText;
19003
- return {
19004
- ...m,
19005
- isStreaming: false,
19006
- text: flatText,
19007
- fullText: flatFullText,
19008
- workedDuration: m.role === "agent" ? totalDuration : m.workedDuration
19009
- };
18968
+ const newMsgs = prev.map((m) => {
18969
+ if (m.isStreaming) {
18970
+ const flatText = m.text ? flattenString(m.text) : m.text;
18971
+ const flatFullText = m.fullText ? flattenString(m.fullText) : m.fullText;
18972
+ return { ...m, isStreaming: false, text: flatText, fullText: flatFullText };
18973
+ }
18974
+ return m;
19010
18975
  });
19011
- const newMsgs = [...prev, ...flushed];
19012
18976
  setCompletedIndex(newMsgs.length);
19013
18977
  return newMsgs;
19014
18978
  });
19015
18979
  clearBlocksCache();
19016
18980
  if (global.gc) {
19017
- for (let i = 0; i < 1; i++) {
18981
+ for (let i = 0; i < 2; i++) {
19018
18982
  global.gc();
19019
18983
  await new Promise((resolve) => setImmediate(resolve));
19020
18984
  }
19021
- lastGCTime = Date.now();
18985
+ lastGCTimeRef.current = Date.now();
19022
18986
  }
19023
18987
  continue;
19024
18988
  }
19025
18989
  if (packet.type === "interactive_turn_finished") {
19026
18990
  setIsProcessing(false);
19027
18991
  setActiveTime(0);
19028
- clearInterval(activeTimeIntervalRef.current);
18992
+ clearInterval(interval_for_timer);
19029
18993
  if (isBridgeConnected()) {
19030
18994
  sendStatus(null);
19031
18995
  }
@@ -19048,18 +19012,13 @@ Selection: ${val}`,
19048
19012
  continue;
19049
19013
  }
19050
19014
  if (packet.type === "visual_feedback") {
19051
- if (systemSettings.progressiveRendering) {
19052
- await awaitTypewriter();
19053
- }
19054
- const streamingMsgs = activeStreamMessagesRef.current;
19055
- activeStreamMessagesRef.current = [];
19056
- setActiveStreamMessages([]);
19015
+ flushTypewriterNow();
19016
+ commitActiveStreamingMessage();
19057
19017
  setMessages((prev) => {
19058
- const flushed = streamingMsgs.map((m) => ({ ...m, isStreaming: false }));
19059
- const newMsgs = [...prev, ...flushed, {
19018
+ const newMsgs = [...prev, {
19060
19019
  id: "feedback-" + Date.now() + "-" + Math.random().toString(36).substring(2, 9),
19061
19020
  role: "system",
19062
- text: packet.content,
19021
+ text: flattenString(packet.content),
19063
19022
  isVisualFeedback: true
19064
19023
  }];
19065
19024
  setCompletedIndex(newMsgs.length);
@@ -19094,19 +19053,13 @@ Selection: ${val}`,
19094
19053
  continue;
19095
19054
  }
19096
19055
  if (packet.type === "tool_result") {
19097
- if (systemSettings.progressiveRendering) {
19098
- await awaitTypewriter();
19099
- }
19100
- const streamingMsgs = activeStreamMessagesRef.current;
19101
- activeStreamMessagesRef.current = [];
19102
- setActiveStreamMessages([]);
19056
+ commitActiveStreamingMessage();
19103
19057
  setMessages((prev) => {
19104
- const flushed = streamingMsgs.map((m) => ({ ...m, isStreaming: false }));
19105
- const newMsgs = [...prev, ...flushed, {
19058
+ const newMsgs = [...prev, {
19106
19059
  id: "tool-" + Date.now(),
19107
19060
  role: "system",
19108
- text: packet.content,
19109
- fullText: packet.aiContent,
19061
+ text: flattenString(packet.content),
19062
+ fullText: flattenString(packet.aiContent),
19110
19063
  // Preserve raw data for next turn
19111
19064
  binaryPart: packet.binaryPart,
19112
19065
  // v1.5.0 Multimodal Support
@@ -19172,7 +19125,7 @@ Selection: ${val}`,
19172
19125
  global.gc();
19173
19126
  await new Promise((resolve) => setImmediate(resolve));
19174
19127
  }
19175
- lastGCTime = Date.now();
19128
+ lastGCTimeRef.current = Date.now();
19176
19129
  }
19177
19130
  continue;
19178
19131
  }
@@ -19209,191 +19162,149 @@ Selection: ${val}`,
19209
19162
  const beforeText = chunkText.substring(0, tagIndex);
19210
19163
  const afterText = chunkText.substring(tagIndex);
19211
19164
  if (beforeText) {
19212
- if (!currentAgentId) {
19213
- currentAgentId = "agent-" + Date.now();
19214
- const newMsg = { id: currentAgentId, role: "agent", text: beforeText, isStreaming: true };
19215
- if (systemSettings.progressiveRendering) {
19216
- typewriterQueueRef.current.push({ type: "create", msg: { ...newMsg, text: "" } });
19217
- pushTokenText(currentAgentId, beforeText);
19218
- } else {
19219
- activeStreamMessagesRef.current = [...activeStreamMessagesRef.current, newMsg];
19220
- }
19165
+ if (!activeStreamingMsgRef.current || activeStreamingMsgRef.current.role !== "agent") {
19166
+ activeStreamingMsgRef.current = { id: "agent-" + Date.now(), role: "agent", text: flattenString(beforeText), isStreaming: true };
19221
19167
  } else {
19222
- if (systemSettings.progressiveRendering) {
19223
- pushTokenText(currentAgentId, beforeText);
19224
- } else {
19225
- activeStreamMessagesRef.current = activeStreamMessagesRef.current.map(
19226
- (m) => m.id === currentAgentId ? { ...m, text: m.text + beforeText, isStreaming: true } : m
19227
- );
19228
- }
19229
- }
19230
- if (!systemSettings.progressiveRendering) {
19231
- setActiveStreamMessages([...activeStreamMessagesRef.current]);
19168
+ activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + beforeText);
19232
19169
  }
19233
19170
  }
19171
+ flushTypewriterNow();
19172
+ commitActiveStreamingMessage();
19234
19173
  inThinkMode = true;
19235
19174
  thinkConsumedInTurn = true;
19236
19175
  let thinkStartText = afterText.replace(/<(think|thought)>/gi, "");
19237
19176
  currentThinkId = "think-" + Date.now();
19238
- const thinkMsg = { id: currentThinkId, role: "think", text: thinkStartText, isStreaming: true, startTime: Date.now() };
19239
- if (systemSettings.progressiveRendering) {
19240
- typewriterQueueRef.current.push({ type: "create", msg: { ...thinkMsg, text: "", startTime: Date.now() } });
19241
- if (thinkStartText) {
19242
- pushTokenText(currentThinkId, thinkStartText);
19243
- }
19244
- } else {
19245
- activeStreamMessagesRef.current = [...activeStreamMessagesRef.current, thinkMsg];
19246
- setActiveStreamMessages([...activeStreamMessagesRef.current]);
19247
- }
19177
+ activeStreamingMsgRef.current = { id: currentThinkId, role: "think", text: "", isStreaming: true, startTime: Date.now() };
19178
+ appendStreamText(thinkStartText);
19248
19179
  continue;
19249
19180
  }
19250
- if ((chunkLower.includes("</think>") || chunkLower.includes("</thought>")) && currentThinkId) {
19181
+ if ((chunkLower.includes("</think>") || chunkLower.includes("</thought>")) && activeStreamingMsgRef.current?.role === "think") {
19251
19182
  const parts = chunkText.split(/<\/(think|thought)>/gi);
19252
19183
  const thinkPart = parts[0] || "";
19253
19184
  const agentPart = parts.slice(2).join("").replace(/<\/?(think|thought)>/gi, "");
19185
+ activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + thinkPart);
19186
+ const startTime = activeStreamingMsgRef.current.startTime || Date.now();
19187
+ activeStreamingMsgRef.current.duration = Date.now() - startTime;
19188
+ flushTypewriterNow();
19189
+ commitActiveStreamingMessage();
19254
19190
  inThinkMode = false;
19255
19191
  currentAgentId = "agent-" + Date.now();
19256
- if (systemSettings.progressiveRendering) {
19257
- if (thinkPart) {
19258
- pushTokenText(currentThinkId, thinkPart);
19259
- }
19260
- const startTime = parseInt(currentThinkId.split("-")[1]) || Date.now();
19261
- const duration = Date.now() - startTime;
19262
- typewriterQueueRef.current.push({ type: "finalize-think", id: currentThinkId, duration });
19263
- const newAgentMsg = { id: currentAgentId, role: "agent", text: "", isStreaming: true };
19264
- typewriterQueueRef.current.push({ type: "create", msg: newAgentMsg });
19265
- if (agentPart) {
19266
- pushTokenText(currentAgentId, agentPart);
19267
- }
19268
- } else {
19269
- activeStreamMessagesRef.current = activeStreamMessagesRef.current.map((m) => {
19270
- if (m.id === currentThinkId && typeof m.id === "string") {
19271
- const startTime = m.startTime || parseInt(m.id.split("-")[1]) || Date.now();
19272
- const duration = Date.now() - startTime;
19273
- return { ...m, text: m.text + thinkPart, isStreaming: false, duration };
19274
- }
19275
- return m;
19276
- });
19277
- activeStreamMessagesRef.current = [...activeStreamMessagesRef.current, { id: currentAgentId, role: "agent", text: agentPart, isStreaming: true }];
19278
- setActiveStreamMessages([...activeStreamMessagesRef.current]);
19279
- }
19192
+ activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text: "", isStreaming: true };
19193
+ appendStreamText(agentPart);
19280
19194
  continue;
19281
19195
  }
19282
- if (inThinkMode && currentThinkId) {
19283
- let transitioning = false;
19284
- let transitionContent = "";
19285
- if (systemSettings.progressiveRendering) {
19286
- if (chunkText.toLowerCase().includes("</think>")) {
19287
- transitioning = true;
19288
- const parts = chunkText.split(/<\/think>/gi);
19289
- const thinkPart = parts[0] || "";
19290
- transitionContent = parts.slice(1).join("</think>") || "";
19291
- if (thinkPart) pushTokenText(currentThinkId, thinkPart);
19292
- const startTime = parseInt(currentThinkId.split("-")[1]) || Date.now();
19293
- const duration = Date.now() - startTime;
19294
- typewriterQueueRef.current.push({ type: "finalize-think", id: currentThinkId, duration });
19295
- inThinkMode = false;
19296
- currentAgentId = "agent-" + Date.now();
19297
- typewriterQueueRef.current.push({ type: "create", msg: { id: currentAgentId, role: "agent", text: "", isStreaming: true } });
19298
- if (transitionContent) {
19299
- pushTokenText(currentAgentId, transitionContent.replace(/<\/?(think|thought)>/gi, ""));
19300
- }
19301
- } else {
19302
- pushTokenText(currentThinkId, chunkText);
19303
- }
19196
+ if (inThinkMode && activeStreamingMsgRef.current?.role === "think") {
19197
+ const newText = activeStreamingMsgRef.current.text + chunkText;
19198
+ if (newText.toLowerCase().includes("</think>")) {
19199
+ const parts = newText.split(/<\/think>/gi);
19200
+ const thinkPart = parts[0] || "";
19201
+ const agentPart = parts.slice(1).join("</think>") || "";
19202
+ activeStreamingMsgRef.current.text = flattenString(thinkPart);
19203
+ const startTime = activeStreamingMsgRef.current.startTime || Date.now();
19204
+ activeStreamingMsgRef.current.duration = Date.now() - startTime;
19205
+ flushTypewriterNow();
19206
+ commitActiveStreamingMessage();
19207
+ inThinkMode = false;
19208
+ currentAgentId = "agent-" + Date.now();
19209
+ activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text: "", isStreaming: true };
19210
+ appendStreamText(agentPart.replace(/<\/?(think|thought)>/gi, ""));
19304
19211
  } else {
19305
- activeStreamMessagesRef.current = activeStreamMessagesRef.current.map((m) => {
19306
- if (m.id === currentThinkId) {
19307
- const newText = m.text + chunkText;
19308
- if (newText.toLowerCase().includes("</think>")) {
19309
- transitioning = true;
19310
- const parts = newText.split(/<\/think>/gi);
19311
- transitionContent = parts.slice(1).join("</think>") || "";
19312
- const startTime = m.startTime || parseInt(String(m.id).split("-")[1]) || Date.now();
19313
- const duration = Date.now() - startTime;
19314
- return { ...m, text: parts[0], isStreaming: false, duration };
19315
- }
19316
- return { ...m, text: newText, isStreaming: true };
19317
- }
19318
- return m;
19319
- });
19320
- if (transitioning) {
19321
- inThinkMode = false;
19322
- currentAgentId = "agent-" + Date.now();
19323
- activeStreamMessagesRef.current = [...activeStreamMessagesRef.current, { id: currentAgentId, role: "agent", text: transitionContent.replace(/<\/?(think|thought)>/gi, ""), isStreaming: true }];
19324
- }
19325
- setActiveStreamMessages([...activeStreamMessagesRef.current]);
19212
+ appendStreamText(chunkText);
19326
19213
  }
19327
19214
  } else if (!inThinkMode) {
19328
19215
  const chunkLower2 = chunkText.toLowerCase();
19329
19216
  if (!toolCallEncounteredInTurn && (chunkLower2.includes("tool:functions.") || chunkLower2.includes("agent:generalist."))) {
19330
19217
  toolCallEncounteredInTurn = true;
19331
19218
  }
19332
- if (!currentAgentId) {
19219
+ if (!activeStreamingMsgRef.current || activeStreamingMsgRef.current.role !== "agent") {
19333
19220
  currentAgentId = "agent-" + Date.now();
19334
- const newMsg = { id: currentAgentId, role: "agent", text: chunkText, isStreaming: true };
19335
- if (systemSettings.progressiveRendering) {
19336
- typewriterQueueRef.current.push({ type: "create", msg: { ...newMsg, text: "" } });
19337
- pushTokenText(currentAgentId, chunkText);
19338
- } else {
19339
- activeStreamMessagesRef.current = [...activeStreamMessagesRef.current, newMsg];
19340
- setActiveStreamMessages([...activeStreamMessagesRef.current]);
19341
- }
19221
+ activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text: flattenString(chunkText), isStreaming: true };
19222
+ forceRender();
19342
19223
  } else {
19343
- if (systemSettings.progressiveRendering) {
19344
- pushTokenText(currentAgentId, chunkText);
19345
- } else {
19346
- const next = [...activeStreamMessagesRef.current];
19347
- for (let i = next.length - 1; i >= 0; i--) {
19348
- if (next[i].id === currentAgentId) {
19349
- next[i] = { ...next[i], text: next[i].text + chunkText, isStreaming: true };
19350
- break;
19351
- }
19352
- }
19353
- activeStreamMessagesRef.current = next;
19354
- setActiveStreamMessages([...activeStreamMessagesRef.current]);
19355
- }
19224
+ appendStreamText(chunkText);
19356
19225
  }
19357
19226
  }
19358
19227
  }
19359
- if (systemSettings.progressiveRendering) {
19360
- streamFinishedRef.current = true;
19361
- } else {
19362
- await finalizeTurn(apiStart);
19363
- }
19364
19228
  const apiEnd = Date.now();
19365
19229
  setSessionApiTime((prev) => prev + (apiEnd - apiStart));
19366
19230
  } catch (err) {
19367
- if (typewriterIntervalRef.current) {
19368
- clearInterval(typewriterIntervalRef.current);
19369
- typewriterIntervalRef.current = null;
19370
- }
19371
- typewriterQueueRef.current = [];
19372
19231
  setMessages((prev) => {
19373
19232
  setCompletedIndex(prev.length + 1);
19374
19233
  return [...prev, { id: "error-" + Date.now(), role: "system", text: `\u274C ERROR: ${err.message}` }];
19375
19234
  });
19376
19235
  } finally {
19377
- if (!systemSettings.progressiveRendering) {
19378
- setIsProcessing(false);
19379
- setStatusText(null);
19380
- setActiveTime(0);
19381
- clearInterval(activeTimeIntervalRef.current);
19382
- if (didSignalTerminationRef.current) {
19383
- appendCancelMessage();
19236
+ const totalDuration = Date.now() - apiStart;
19237
+ if (activeStreamingMsgRef.current) {
19238
+ activeStreamingMsgRef.current.workedDuration = totalDuration;
19239
+ }
19240
+ if (typewriterTickRef.current) {
19241
+ await awaitTypewriter();
19242
+ clearInterval(typewriterTickRef.current);
19243
+ typewriterTickRef.current = null;
19244
+ }
19245
+ setIsProcessing(false);
19246
+ setStatusText(null);
19247
+ setActiveTime(0);
19248
+ clearInterval(interval_for_timer);
19249
+ commitActiveStreamingMessage();
19250
+ if (didSignalTerminationRef.current) {
19251
+ appendCancelMessage();
19252
+ }
19253
+ clearBlocksCache();
19254
+ if (global.gc) {
19255
+ try {
19256
+ for (let i = 0; i < 3; i++) {
19257
+ global.gc();
19258
+ await new Promise((resolve) => setImmediate(resolve));
19259
+ }
19260
+ lastGCTimeRef.current = Date.now();
19261
+ } catch (e) {
19384
19262
  }
19385
- clearBlocksCache();
19386
- if (global.gc) {
19387
- try {
19388
- for (let i = 0; i < 3; i++) {
19389
- global.gc();
19390
- await new Promise((resolve) => setImmediate(resolve));
19263
+ }
19264
+ if (!hasFiredJanitor) {
19265
+ if (process.stdout.isTTY) {
19266
+ process.stdout.write("\x1B]0;FluxFlow | Idle\x07");
19267
+ process.stdout.write("\x1B]633;P;TerminalTitle=FluxFlow | Idle\x07");
19268
+ }
19269
+ }
19270
+ if (queuedPromptRef.current) {
19271
+ setResolutionData(queuedPromptRef.current);
19272
+ setQueuedPrompt(null);
19273
+ const hintToResolve = queuedPromptRef.current;
19274
+ queuedPromptRef.current = null;
19275
+ setMessages((prev) => {
19276
+ const newMsgs = [...prev];
19277
+ const hintMsg = newMsgs.reverse().find((m) => m.text?.includes("[STEERING HINT: QUEUED]") || m.text?.includes("[QUESTION: QUEUED]"));
19278
+ if (hintMsg) {
19279
+ if (hintMsg.text.includes("[STEERING HINT: QUEUED]")) {
19280
+ hintMsg.text = hintMsg.text.replace("[STEERING HINT: QUEUED]", "[STEERING HINT: FINISHED_TURN]");
19281
+ } else if (hintMsg.text.includes("[QUESTION: QUEUED]")) {
19282
+ hintMsg.text = hintMsg.text.replace("[QUESTION: QUEUED]", "[QUESTION: FINISHED_TURN]");
19391
19283
  }
19392
- lastGCTime = Date.now();
19393
- } catch (e) {
19394
19284
  }
19395
- }
19285
+ return newMsgs.reverse();
19286
+ });
19287
+ setActiveView("resolution");
19396
19288
  }
19289
+ setMessages((prev) => {
19290
+ const totalDuration2 = Date.now() - apiStart;
19291
+ let foundLastAgent = false;
19292
+ const newMsgs = [...prev].reverse().map((m) => {
19293
+ let updated = m.isStreaming ? { ...m, isStreaming: false } : m;
19294
+ if (updated.text) {
19295
+ updated.text = (" " + updated.text).slice(1);
19296
+ }
19297
+ if (!foundLastAgent && updated.role === "agent") {
19298
+ foundLastAgent = true;
19299
+ updated = { ...updated, workedDuration: totalDuration2 };
19300
+ }
19301
+ return updated;
19302
+ }).reverse();
19303
+ const historyToSave = newMsgs.filter((m) => !String(m.id).startsWith("welcome") && (!m.isMeta || m.text && m.text.includes("Request Cancelled")));
19304
+ saveChat(chatId, null, historyToSave);
19305
+ setCompletedIndex(newMsgs.length);
19306
+ return newMsgs;
19307
+ });
19397
19308
  }
19398
19309
  };
19399
19310
  streamChat();
@@ -19627,7 +19538,7 @@ Selection: ${val}`,
19627
19538
  } else if (selectedProvider === "DeepSeek") {
19628
19539
  defaultModel = "deepseek-v4-flash";
19629
19540
  } else if (selectedProvider === "NVIDIA") {
19630
- defaultModel = "stepfun-ai/step-3.7-flash";
19541
+ defaultModel = "deepseek-ai/deepseek-v4-flash";
19631
19542
  }
19632
19543
  setActiveModel(defaultModel);
19633
19544
  const targetTier = (quotas.providerTiers || {})[selectedProvider] || "Free";
@@ -19955,7 +19866,7 @@ Selection: ${val}`,
19955
19866
  } else if (prov === "DeepSeek") {
19956
19867
  defaultModel = "deepseek-v4-flash";
19957
19868
  } else if (prov === "NVIDIA") {
19958
- defaultModel = "stepfun-ai/step-3.7-flash";
19869
+ defaultModel = "moonshotai/kimi-k2.6";
19959
19870
  }
19960
19871
  setActiveModel(defaultModel);
19961
19872
  const targetTier = (quotas.providerTiers || {})[prov] || "Free";
@@ -20800,15 +20711,15 @@ var init_app = __esm({
20800
20711
  }
20801
20712
  }
20802
20713
  if (endIdx !== -1) {
20803
- const beforeText = text.substring(lastIdx, match.index);
20714
+ const beforeText = flattenString(text.substring(lastIdx, match.index));
20804
20715
  if (beforeText.trim()) {
20805
20716
  blocks.push({ type: "output", content: beforeText });
20806
20717
  }
20807
- const finalArgsText = text.substring(startIdx + 1, closingParenIdx);
20718
+ const finalArgsText = flattenString(text.substring(startIdx + 1, closingParenIdx));
20808
20719
  blocks.push({
20809
20720
  type: "tool",
20810
- toolName: toolName.trim(),
20811
- args: finalArgsText.trim()
20721
+ toolName: flattenString(toolName.trim()),
20722
+ args: flattenString(finalArgsText.trim())
20812
20723
  });
20813
20724
  lastIdx = endIdx + 1;
20814
20725
  toolRegex.lastIndex = lastIdx;
@@ -20817,7 +20728,7 @@ var init_app = __esm({
20817
20728
  }
20818
20729
  }
20819
20730
  if (lastIdx < text.length) {
20820
- const remainingText = text.substring(lastIdx);
20731
+ const remainingText = flattenString(text.substring(lastIdx));
20821
20732
  if (remainingText.trim()) {
20822
20733
  blocks.push({ type: "output", content: remainingText });
20823
20734
  }
@@ -20829,14 +20740,16 @@ var init_app = __esm({
20829
20740
  let lastScanTime = 0;
20830
20741
  return (dir) => {
20831
20742
  const now = Date.now();
20832
- if (cachedFiles && now - lastScanTime < 5e3) {
20743
+ if (cachedFiles && now - lastScanTime < 1e4) {
20833
20744
  return cachedFiles;
20834
20745
  }
20835
20746
  const fileList = [];
20836
20747
  const scan = (currentDir) => {
20748
+ if (fileList.length >= 2e3) return;
20837
20749
  try {
20838
20750
  const files = fs24.readdirSync(currentDir);
20839
20751
  for (const file of files) {
20752
+ if (fileList.length >= 2e3) return;
20840
20753
  if (["node_modules", ".git", ".gemini", "dist", "build", ".next", ".cache", "out"].includes(file)) {
20841
20754
  continue;
20842
20755
  }
@@ -20846,8 +20759,8 @@ var init_app = __esm({
20846
20759
  scan(filePath);
20847
20760
  } else {
20848
20761
  fileList.push({
20849
- name: file,
20850
- relativePath: path22.relative(process.cwd(), filePath)
20762
+ name: flattenString(file),
20763
+ relativePath: flattenString(path22.relative(process.cwd(), filePath))
20851
20764
  });
20852
20765
  }
20853
20766
  }