fluxflow-cli 3.2.2 → 3.2.5

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 +461 -202
  2. package/package.json +2 -2
package/dist/fluxflow.js CHANGED
@@ -326,7 +326,8 @@ var init_settings = __esm({
326
326
  useExternalData: false,
327
327
  externalDataPath: "",
328
328
  preserveThinking: true,
329
- loadingPhrases: true
329
+ loadingPhrases: true,
330
+ progressiveRendering: false
330
331
  },
331
332
  profileData: {
332
333
  name: null,
@@ -2138,7 +2139,8 @@ var init_text = __esm({
2138
2139
  if (currentVisibleLength + tokenVisibleLength > width) {
2139
2140
  if (currentLine.trim().length > 0) {
2140
2141
  finalLines.push(currentLine.trimEnd());
2141
- currentLine = indent + token;
2142
+ const cappedIndent = indent.substring(0, Math.min(indent.length, 8));
2143
+ currentLine = cappedIndent + token;
2142
2144
  currentVisibleLength = getVisibleLength(currentLine);
2143
2145
  } else {
2144
2146
  if (ansiRegex.test(token)) {
@@ -2227,36 +2229,20 @@ var init_text = __esm({
2227
2229
  };
2228
2230
  const adjustIndentation = (newText, originalMatch, leadingContext = "") => {
2229
2231
  if (!newText || originalMatch === void 0) return newText;
2230
- const getIndentStyle = (text) => {
2231
- const lines = text.split("\n").filter((l) => l.trim() !== "");
2232
- if (lines.length === 0) return { char: " ", size: 4 };
2233
- const firstIndent = lines[0].match(/^\s*/)[0];
2234
- if (firstIndent.includes(" ")) return { char: " ", size: 1 };
2235
- const indents = lines.map((l) => l.match(/^\s*/)[0].length).filter((l) => l > 0);
2236
- if (indents.length === 0) return { char: " ", size: firstIndent.length || 4 };
2237
- const gcd = (a, b) => b ? gcd(b, a % b) : a;
2238
- const step = indents.reduce((a, b) => gcd(a, b));
2239
- return { char: " ", size: step || 4 };
2240
- };
2241
- const fileStyle = getIndentStyle(originalMatch);
2242
- const modelStyle = getIndentStyle(newText);
2243
- const matchMinIndent = getMinIndent(originalMatch).length;
2244
- const leadingIndent = (leadingContext.match(/^\s*/) || [""])[0].length;
2245
- const targetBaseIndentRaw = leadingIndent + matchMinIndent;
2246
- const targetUnits = targetBaseIndentRaw / fileStyle.size;
2247
- const modelBaseUnits = getMinIndent(newText).length / modelStyle.size;
2248
- const deltaUnits = targetUnits - modelBaseUnits;
2232
+ const usesTabs = /^\t/m.test(originalMatch);
2233
+ const indentChar = usesTabs ? " " : " ";
2234
+ const firstNonEmpty = (text) => text.split("\n").find((l) => l.trim() !== "") ?? "";
2235
+ const origFirstIndent = firstNonEmpty(originalMatch).match(/^\s*/)[0].length;
2236
+ const newFirstIndent = firstNonEmpty(newText).match(/^\s*/)[0].length;
2237
+ const delta = origFirstIndent - newFirstIndent;
2238
+ const leadingLen = (leadingContext.match(/^\s*/) || [""])[0].length;
2249
2239
  const newLines = newText.split("\n");
2250
2240
  return newLines.map((line, i) => {
2251
2241
  if (line.trim() === "" && i !== 0) return "";
2252
- const currentLineUnits = line.match(/^\s*/)[0].length / modelStyle.size;
2253
- const finalUnits = Math.max(0, currentLineUnits + deltaUnits);
2254
- let unitCount = finalUnits;
2255
- if (i === 0) {
2256
- const leadingUnits = leadingIndent / fileStyle.size;
2257
- unitCount = Math.max(0, finalUnits - leadingUnits);
2258
- }
2259
- return fileStyle.char.repeat(unitCount * fileStyle.size) + line.trimStart();
2242
+ const currentIndent = line.match(/^\s*/)[0].length;
2243
+ let targetIndent = Math.max(0, currentIndent + delta);
2244
+ if (i === 0) targetIndent = Math.max(0, targetIndent - leadingLen);
2245
+ return indentChar.repeat(targetIndent) + line.trimStart();
2260
2246
  }).join("\n");
2261
2247
  };
2262
2248
  const patchMatches = [];
@@ -2559,7 +2545,7 @@ var init_text = __esm({
2559
2545
  };
2560
2546
  parseMessageToBlocks = (msg, columns) => {
2561
2547
  if (!msg) return { completed: [], active: [] };
2562
- const cacheKey = `${msg.id}-${msg.text?.length || 0}-${columns}-${msg.isStreaming}`;
2548
+ const cacheKey = `${msg.id}-${msg.text?.length || 0}-${columns}-${msg.isStreaming}-${msg.workedDuration || 0}-${msg.memoryUpdated ? 1 : 0}-${msg.color || ""}`;
2563
2549
  if (!msg.isStreaming && blocksCache.has(cacheKey)) {
2564
2550
  return blocksCache.get(cacheKey);
2565
2551
  }
@@ -4017,7 +4003,7 @@ ${coloredArt[7]}`;
4017
4003
  import React4, { useState as useState4, useEffect as useEffect3, useRef as useRef2 } from "react";
4018
4004
  import { Box as Box3, Text as Text4 } from "ink";
4019
4005
  import { diffWordsWithSpace } from "diff";
4020
- 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;
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;
4021
4007
  var init_ChatLayout = __esm({
4022
4008
  "src/components/ChatLayout.jsx"() {
4023
4009
  init_TerminalBox();
@@ -4073,7 +4059,6 @@ var init_ChatLayout = __esm({
4073
4059
  /\b(true|false|null|undefined|nil|None)\b/.source,
4074
4060
  /\b(\d+(?:\.\d+)?|0x[0-9a-fA-F]+)\b/.source
4075
4061
  ];
4076
- REGEX_SYNTAX = new RegExp(SYNTAX_RULES.join("|"), "g");
4077
4062
  tokenCache = /* @__PURE__ */ new Map();
4078
4063
  MAX_TOKEN_CACHE_SIZE = 1e3;
4079
4064
  tokenizeLine = (line, lang) => {
@@ -4085,8 +4070,8 @@ var init_ChatLayout = __esm({
4085
4070
  let lastIndex = 0;
4086
4071
  const tokens = [];
4087
4072
  let match;
4088
- REGEX_SYNTAX.lastIndex = 0;
4089
- while ((match = REGEX_SYNTAX.exec(line)) !== null) {
4073
+ const localRegex = new RegExp(SYNTAX_RULES.join("|"), "g");
4074
+ while ((match = localRegex.exec(line)) !== null) {
4090
4075
  const matchText = match[0];
4091
4076
  const matchIndex = match.index;
4092
4077
  if (matchIndex > lastIndex) {
@@ -4109,7 +4094,7 @@ var init_ChatLayout = __esm({
4109
4094
  color = "#ff9e64";
4110
4095
  }
4111
4096
  tokens.push({ text: matchText, color, bold });
4112
- lastIndex = REGEX_SYNTAX.lastIndex;
4097
+ lastIndex = localRegex.lastIndex;
4113
4098
  }
4114
4099
  if (lastIndex < line.length) {
4115
4100
  tokens.push({ text: line.substring(lastIndex) });
@@ -4311,12 +4296,12 @@ var init_ChatLayout = __esm({
4311
4296
  const renderInlineDiff = () => {
4312
4297
  if (isPureUnpairedBlock) {
4313
4298
  const blockColor = isRemoval ? "#ffdddd" : "#ddffdd";
4314
- const wrappedLines = wrapText(content, columns - 14).split("\n");
4299
+ const wrappedLines = wrapText(content, columns - 15).split("\n");
4315
4300
  return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, blockColor))));
4316
4301
  }
4317
4302
  if (!(isRemoval || isAddition) || words.length === 0 || !hasInlineChange) {
4318
4303
  const textColor = isRemoval ? "#885555" : isAddition ? "#558866" : "gray";
4319
- const wrappedLines = wrapText(content, columns - 14).split("\n");
4304
+ const wrappedLines = wrapText(content, columns - 15).split("\n");
4320
4305
  return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, textColor))));
4321
4306
  }
4322
4307
  return /* @__PURE__ */ React4.createElement(Text4, { wrap: "anywhere" }, words.map((part, idx) => {
@@ -4340,7 +4325,7 @@ var init_ChatLayout = __esm({
4340
4325
  return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "gray" }, part.value);
4341
4326
  }));
4342
4327
  };
4343
- 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()));
4328
+ return /* @__PURE__ */ React4.createElement(Box3, { backgroundColor: "#1a1a1a", paddingX: 1, width: columns }, /* @__PURE__ */ React4.createElement(Box3, { width: 4, 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()));
4344
4329
  });
4345
4330
  DiffBlock = React4.memo(({ text, columns = 80, extension }) => {
4346
4331
  const match = text.match(/\[DIFF_START\]([\s\S]*?)(?:\[DIFF_END\]|$)/);
@@ -4530,12 +4515,8 @@ var init_ChatLayout = __esm({
4530
4515
  Box3,
4531
4516
  {
4532
4517
  flexDirection: "column",
4533
- borderStyle: "single",
4534
- borderLeft: true,
4535
- borderRight: false,
4536
- borderTop: false,
4537
- borderBottom: false,
4538
- borderColor: "#444444",
4518
+ borderStyle: "round",
4519
+ border: true,
4539
4520
  paddingLeft: 2,
4540
4521
  paddingRight: 0,
4541
4522
  paddingTop: 1,
@@ -4552,12 +4533,8 @@ var init_ChatLayout = __esm({
4552
4533
  Box3,
4553
4534
  {
4554
4535
  flexDirection: "column",
4555
- borderStyle: "single",
4556
- borderLeft: true,
4557
- borderRight: false,
4558
- borderTop: false,
4559
- borderBottom: false,
4560
- borderColor: "#444444",
4536
+ borderStyle: "round",
4537
+ border: true,
4561
4538
  paddingLeft: 2,
4562
4539
  paddingRight: 0,
4563
4540
  paddingTop: 1,
@@ -4744,7 +4721,7 @@ var init_ChatLayout = __esm({
4744
4721
  paddingLeft: 2,
4745
4722
  width: "100%"
4746
4723
  },
4747
- /* @__PURE__ */ React4.createElement(Box3, { width: 4, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray", dimColor: true }, String(lineNum).padStart(3, " "), " ")),
4724
+ /* @__PURE__ */ React4.createElement(Box3, { width: 5, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray", dimColor: true }, String(lineNum).padStart(4, " "), " ")),
4748
4725
  /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, renderHighlightedLine(text, lang, "#e1e4e8"))
4749
4726
  );
4750
4727
  }
@@ -4852,16 +4829,30 @@ var init_StatusBar = __esm({
4852
4829
  if (delay >= 5e3) return "#ff0000";
4853
4830
  const points = [
4854
4831
  { t: 370, r: 0, g: 165, b: 100 },
4855
- { t: 800, r: 120, g: 220, b: 80 },
4856
- { t: 1500, r: 250, g: 210, b: 40 },
4857
- { t: 3e3, r: 255, g: 120, b: 0 },
4832
+ // deep green
4833
+ { t: 550, r: 40, g: 195, b: 80 },
4834
+ // green
4835
+ { t: 800, r: 120, g: 220, b: 50 },
4836
+ // lime-green
4837
+ { t: 1100, r: 190, g: 225, b: 20 },
4838
+ // yellow-green
4839
+ { t: 1500, r: 250, g: 210, b: 15 },
4840
+ // yellow
4841
+ { t: 2e3, r: 255, g: 170, b: 0 },
4842
+ // amber
4843
+ { t: 2800, r: 255, g: 110, b: 0 },
4844
+ // orange
4845
+ { t: 3800, r: 255, g: 50, b: 0 },
4846
+ // deep orange
4858
4847
  { t: 5e3, r: 255, g: 0, b: 0 }
4848
+ // red
4859
4849
  ];
4860
4850
  for (let i = 0; i < points.length - 1; i++) {
4861
4851
  const p1 = points[i];
4862
4852
  const p2 = points[i + 1];
4863
4853
  if (delay >= p1.t && delay <= p2.t) {
4864
- const ratio = (delay - p1.t) / (p2.t - p1.t);
4854
+ let ratio = (delay - p1.t) / (p2.t - p1.t);
4855
+ ratio = ratio * ratio * (3 - 2 * ratio);
4865
4856
  const r = Math.round(p1.r + (p2.r - p1.r) * ratio);
4866
4857
  const g = Math.round(p1.g + (p2.g - p1.g) * ratio);
4867
4858
  const b = Math.round(p1.b + (p2.b - p1.b) * ratio);
@@ -4877,6 +4868,7 @@ var init_StatusBar = __esm({
4877
4868
  const [memoryUnit, setMemoryUnit] = useState5("MB");
4878
4869
  const [dotColor, setDotColor] = useState5("green");
4879
4870
  const chunkTimesRef = useRef3([]);
4871
+ const smoothedDelayRef = useRef3(370);
4880
4872
  useEffect4(() => {
4881
4873
  if (!isProcessing) {
4882
4874
  chunkTimesRef.current = [];
@@ -4886,7 +4878,7 @@ var init_StatusBar = __esm({
4886
4878
  const times = chunkTimesRef.current;
4887
4879
  if (times.length === 0 || times[times.length - 1] !== lastChunkTime) {
4888
4880
  times.push(lastChunkTime);
4889
- if (times.length > 5) {
4881
+ if (times.length > 10) {
4890
4882
  times.shift();
4891
4883
  }
4892
4884
  }
@@ -4906,8 +4898,13 @@ var init_StatusBar = __esm({
4906
4898
  averageInterval = sum / (times.length - 1);
4907
4899
  }
4908
4900
  const timeSinceLast = Date.now() - lastChunkTime;
4909
- const delay = Math.max(averageInterval, timeSinceLast);
4910
- setDotColor(getLatencyColor(delay));
4901
+ const STALL_THRESHOLD = 2500;
4902
+ const isStalled = timeSinceLast >= STALL_THRESHOLD;
4903
+ const cappedTimeSinceLast = !isStalled && averageInterval > 0 ? Math.min(timeSinceLast, averageInterval * 3) : timeSinceLast;
4904
+ const rawDelay = Math.max(averageInterval, cappedTimeSinceLast);
4905
+ const alpha = isStalled ? 0.4 : 0.2;
4906
+ smoothedDelayRef.current = smoothedDelayRef.current * (1 - alpha) + rawDelay * alpha;
4907
+ setDotColor(getLatencyColor(smoothedDelayRef.current));
4911
4908
  };
4912
4909
  checkLatency();
4913
4910
  const timer = setInterval(checkLatency, 100);
@@ -5200,11 +5197,11 @@ Info: 'initial' = user prompted for THIS active task, revert 'id' should be a tu
5200
5197
  1. [tool:functions.EmergencyRollback(method="getCheckpoint/forceRevert", id="...")]. Rollback workspace to a specific checkpoint in THIS agent loop. Usage: ONLY in catastrophic situations. Verify nothing catastrophic happened in codebase before ending agent loop. 'id' not needed with getCheckPoint
5201
5198
  ` : ""}
5202
5199
  - SUB AGENT TOOLS -
5203
- **PROACTIVE USE OF SUB AGENTS HIGHLY RECOMMENDED, PREFER USING FOR ALL TASK WHERE PLAUSIBLE & BENEFICIAL, EVEN WITHOUT EXPLICIT USER NUDGE**
5200
+ **PROACTIVE USE OF SUB AGENTS HIGHLY RECOMMENDED, PREFER USING FOR ALL TASK WHERE EVEN SLIGHTLY BENEFICIAL, EVEN WITHOUT EXPLICIT USER NUDGE**
5204
5201
  Invocation Types:
5205
5202
  - Invoke (async, background worker for parallel tasks, upto 7 parallel agents together). Usage: Benefits parallelism & speed. Can take long time, If invoked DO NOT REPEAT SAME TASK WHILE ACTIVE
5206
- - InvokeSync (sync, blocking main agent loop). Usage: Repeatetive work, Sequential tasks, Task delegation. Huge tokens/costs savings
5207
- 1. [agent:generalist.InvokeSync/Invoke(title="...", task="...")]. Task must me detailed, including exact file paths, imports/exports, dependency, folder structure
5203
+ - InvokeSync (sync, blocking main agent loop). Usage: Repeatetive work, Sequential tasks, Task delegation. Tokens/Costs savings
5204
+ 1. [agent:generalist.InvokeSync/Invoke(title="...", task="...")]. Task must me detailed, including exact file paths, imports/exports, dependency, folder structure. No terminal access
5208
5205
  2. [agent:generalist.GetProgress(id="...")]. Usage: Check progress of async subagent task, taking time? continue your task, MUST await (exponentially longer after 1st check) than spamming getProgress. NEVER FINISH WITHOUT 'AWAIT' WHILE SUBAGENT WORKING
5209
5206
  3. [agent:generalist.Cancel(id="...")]. Usage: Cancel async subagent task, LAST RESORT ONLY IF ITS STUCK FOR UNUSUALLY LONG (2m+) WITH NO PROGRESS`.trim() : `- CREATIVE TOOLS (path = relative to CWD & WILL BE FIRST ARGUMENT, path separator: '/') -
5210
5207
  1. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. PROACTIVE A4 PAGE BREAKS MUST IN CSS. HTML/CSS for PREMIUM layout
@@ -5969,6 +5966,7 @@ function SettingsMenu({
5969
5966
  { label: "Key Strategy", value: "apiTier", status: apiTier === "Free" ? "Free" : quotas?.providerBudgets?.__useProvider ? "Paid" : "Paid" },
5970
5967
  { label: "Preserve Thinking", value: "preserveThinking", status: systemSettings.preserveThinking !== false ? "ON" : "OFF" },
5971
5968
  { label: "Loading Phrases", value: "loadingPhrases", status: systemSettings.loadingPhrases !== false ? "ON" : "OFF" },
5969
+ { label: "Progressive Rendering [EXPERIMENTAL]", value: "progressiveRendering", status: systemSettings.progressiveRendering ? "ON" : "OFF" },
5972
5970
  { label: "Download Language Parsers", value: "parserDownload", status: "ACTION" }
5973
5971
  ];
5974
5972
  default:
@@ -6137,6 +6135,12 @@ function SettingsMenu({
6137
6135
  saveSettings2({ systemSettings: newSysSettings, apiTier, quotas });
6138
6136
  return newSysSettings;
6139
6137
  });
6138
+ } else if (item.value === "progressiveRendering") {
6139
+ setSystemSettings((s) => {
6140
+ const newSysSettings = { ...s, progressiveRendering: !s.progressiveRendering };
6141
+ saveSettings2({ systemSettings: newSysSettings, apiTier, quotas });
6142
+ return newSysSettings;
6143
+ });
6140
6144
  }
6141
6145
  };
6142
6146
  return /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "white", padding: 0, width: "100%", minHeight: 32 }, /* @__PURE__ */ React7.createElement(Box6, { paddingX: 1, paddingY: 0, marginBottom: 0, borderStyle: "single", borderColor: "gray", width: "100%" }, /* @__PURE__ */ React7.createElement(Text7, { color: "white", bold: true }, "SYSTEM CONFIGURATION")), /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "row", width: "100%", minHeight: 26 }, /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", width: "30%", borderStyle: "round", borderColor: activeColumn === "categories" ? "white" : "grey", padding: 1, paddingY: 0 }, /* @__PURE__ */ React7.createElement(Box6, { marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: activeColumn === "categories" ? "white" : "grey", bold: true, underline: true }, "CATEGORIES")), CATEGORIES.map((cat, index) => {
@@ -6173,7 +6177,7 @@ function SettingsMenu({
6173
6177
  currentItems.forEach((item, index) => {
6174
6178
  const isSelected = activeColumn === "items" && selectedItemIndex === index;
6175
6179
  const labelLength = item.label.length;
6176
- const dotsCount = Math.max(2, 35 - labelLength);
6180
+ const dotsCount = Math.max(2, 38 - labelLength);
6177
6181
  const dots = ".".repeat(dotsCount);
6178
6182
  const getStatusColor = (item2) => {
6179
6183
  if (currentCatId === "security") {
@@ -6221,7 +6225,7 @@ function SettingsMenu({
6221
6225
  });
6222
6226
  if (currentCatId === "other") {
6223
6227
  elements.push(
6224
- /* @__PURE__ */ React7.createElement(Box6, { key: "pty-notice", marginTop: 15, paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "white" }, isPtyAvailable ? "\u2713 Advance Interactive Terminal Supported" : "\u26A0 Interactive Terminal is Limited"))
6228
+ /* @__PURE__ */ React7.createElement(Box6, { key: "pty-notice", marginTop: 14, paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "white" }, isPtyAvailable ? "\u2713 Advance Interactive Terminal Supported" : "\u26A0 Interactive Terminal is Limited"))
6225
6229
  );
6226
6230
  elements.push(
6227
6231
  /* @__PURE__ */ React7.createElement(Box6, { key: "memory-load-2026", paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, "Memory Load: ", currentMemory, "/", maxMemory, " ", memoryUnit))
@@ -10763,7 +10767,7 @@ var init_ai = __esm({
10763
10767
  "openai/gpt-5.5-pro",
10764
10768
  "moonshotai/kimi-k2.6",
10765
10769
  // NVIDIA vision models
10766
- "moonshotai/kimi-k2.6",
10770
+ "moonshotai/kimi-k2.7",
10767
10771
  "stepfun-ai/step-3.7-flash",
10768
10772
  "google/gemma-4-31b-it",
10769
10773
  "mistralai/mistral-medium-3.5-128b",
@@ -11193,6 +11197,8 @@ var init_ai = __esm({
11193
11197
  push({ value: { type: "status", content: `Queue ${depth || 1}` }, done: false });
11194
11198
  }
11195
11199
  }
11200
+ } else if (!isStreamingStarted) {
11201
+ push({ value: { type: "status", content: `Queue '${res.status}'` }, done: false });
11196
11202
  }
11197
11203
  } catch (e) {
11198
11204
  }
@@ -14953,7 +14959,7 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
14953
14959
  "filemap": '- [tool:functions.FileMap(path="path/file")]. Shows file structure, functions, classes, imports/exports',
14954
14960
  "patchfile": '- [tool:functions.PatchFile(path="...", replaceContent1="...", newContent1="...")]. Surgical block replacement for editing files',
14955
14961
  "writefile": '- [tool:functions.WriteFile(path="...", content="...")]. Creates or overwrites a file',
14956
- "searchkeyword": '- [tool:functions.SearchKeyword(keyword="...", file="optional", subString="true/false")]. Global project text search',
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`,
14957
14963
  "websearch": '- [tool:functions.WebSearch(query="...", limit=number)]. Web Search',
14958
14964
  "webscrape": '- [tool:functions.WebScrape(url="...")]. Web Scrape',
14959
14965
  "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`
@@ -16033,7 +16039,7 @@ var init_GlintText = __esm({
16033
16039
  return () => clearInterval(timer);
16034
16040
  }, [displayedText.length, speed, glintWidth]);
16035
16041
  useEffect11(() => {
16036
- if (text && text.includes("Trying to reach") && displayedText && displayedText.includes("Trying to reach")) {
16042
+ if (text && (text.includes("Trying to reach") && displayedText && displayedText.includes("Trying to reach") || text.includes("Error Occurred") && displayedText && displayedText.includes("Error Occurred"))) {
16037
16043
  setDisplayedText(text);
16038
16044
  return;
16039
16045
  }
@@ -16474,8 +16480,8 @@ function App({ args = [] }) {
16474
16480
  defaultModel = "deepseek-v4-flash";
16475
16481
  modelDisplayName = "DeepSeek Flash (Free default)";
16476
16482
  } else if (aiProvider === "NVIDIA") {
16477
- defaultModel = "moonshotai/kimi-k2.6";
16478
- modelDisplayName = "Moonshot Kimi (NVIDIA)";
16483
+ defaultModel = "stepfun-ai/step-3.7-flash";
16484
+ modelDisplayName = "Step 3.7 Flash (NVIDIA)";
16479
16485
  } else {
16480
16486
  defaultModel = "google/gemma-4-31b-it:free";
16481
16487
  modelDisplayName = "Gemma 4 (Free default)";
@@ -16488,8 +16494,8 @@ function App({ args = [] }) {
16488
16494
  defaultModel = "deepseek-v4-flash";
16489
16495
  modelDisplayName = "DeepSeek Flash";
16490
16496
  } else if (aiProvider === "NVIDIA") {
16491
- defaultModel = "moonshotai/kimi-k2.6";
16492
- modelDisplayName = "Moonshot Kimi (NVIDIA)";
16497
+ defaultModel = "stepfun-ai/step-3.7-flash";
16498
+ modelDisplayName = "Step 3.7 Flash (NVIDIA)";
16493
16499
  } else {
16494
16500
  defaultModel = "deepseek/deepseek-v4-flash";
16495
16501
  modelDisplayName = "DeepSeek Flash";
@@ -16550,7 +16556,7 @@ function App({ args = [] }) {
16550
16556
  const [wittyPhrase, setWittyPhrase] = useState15("");
16551
16557
  const [hasPasteBlock, setHasPasteBlock] = useState15(false);
16552
16558
  const [activeTime, setActiveTime] = useState15(0);
16553
- let interval_for_timer;
16559
+ const activeTimeIntervalRef = useRef4(null);
16554
16560
  useEffect12(() => {
16555
16561
  let interval;
16556
16562
  if (statusText && systemSettings.loadingPhrases !== false) {
@@ -16661,6 +16667,11 @@ function App({ args = [] }) {
16661
16667
  }, [messages]);
16662
16668
  const [completedIndex, setCompletedIndex] = useState15(messages.length);
16663
16669
  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);
16664
16675
  const lastCompletedBlocksRef = useRef4([]);
16665
16676
  const cachedHistoryRef = useRef4({
16666
16677
  completedIndex: 0,
@@ -16734,7 +16745,7 @@ function App({ args = [] }) {
16734
16745
  };
16735
16746
  }
16736
16747
  }
16737
- const activeMsgs = messages.slice(completedIndex);
16748
+ const activeMsgs = activeStreamMessages;
16738
16749
  const streamingCompletedBlocks = [];
16739
16750
  const activeBlocks = [];
16740
16751
  for (let i = 0; i < activeMsgs.length; i++) {
@@ -16750,7 +16761,15 @@ function App({ args = [] }) {
16750
16761
  for (let j = 0; j < parsed.completed.length; j++) streamingCompletedBlocks.push(parsed.completed[j]);
16751
16762
  for (let j = 0; j < parsed.active.length; j++) activeBlocks.push(parsed.active[j]);
16752
16763
  }
16753
- const finalCompleted = [...historicalBlocks];
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
+ });
16754
16773
  for (let j = 0; j < streamingCompletedBlocks.length; j++) {
16755
16774
  finalCompleted.push(streamingCompletedBlocks[j]);
16756
16775
  }
@@ -16770,7 +16789,7 @@ function App({ args = [] }) {
16770
16789
  completed: finalCompleted,
16771
16790
  active: activeBlocks
16772
16791
  };
16773
- }, [messages, completedIndex, terminalSize.columns, clearKey, chatId]);
16792
+ }, [messages, activeStreamMessages, completedIndex, terminalSize.columns, clearKey, chatId]);
16774
16793
  const isTerminalWaitingForInput = useMemo2(() => {
16775
16794
  if (!activeCommand || !execOutput) return false;
16776
16795
  const lastChunk = execOutput.trim();
@@ -17068,7 +17087,7 @@ function App({ args = [] }) {
17068
17087
  } else if (startupProvider === "OpenRouter") {
17069
17088
  defaultModel = "google/gemma-4-31b-it:free";
17070
17089
  } else if (startupProvider === "NVIDIA") {
17071
- defaultModel = "moonshotai/kimi-k2.6";
17090
+ defaultModel = "stepfun-ai/step-3.7-flash";
17072
17091
  }
17073
17092
  } else {
17074
17093
  if (startupProvider === "Google") {
@@ -17078,7 +17097,7 @@ function App({ args = [] }) {
17078
17097
  } else if (startupProvider === "OpenRouter") {
17079
17098
  defaultModel = "deepseek/deepseek-v4-flash";
17080
17099
  } else if (startupProvider === "NVIDIA") {
17081
- defaultModel = "moonshotai/kimi-k2.6";
17100
+ defaultModel = "stepfun-ai/step-3.7-flash";
17082
17101
  }
17083
17102
  }
17084
17103
  setActiveModel(defaultModel);
@@ -17295,7 +17314,7 @@ function App({ args = [] }) {
17295
17314
  } else if (aiProvider === "DeepSeek") {
17296
17315
  defaultModel = "deepseek-v4-flash";
17297
17316
  } else if (aiProvider === "NVIDIA") {
17298
- defaultModel = "moonshotai/kimi-k2.6";
17317
+ defaultModel = "stepfun-ai/step-3.7-flash";
17299
17318
  }
17300
17319
  setActiveModel(defaultModel);
17301
17320
  setMessages((prev) => [...prev, { role: "system", text: `${aiProvider} API Key saved successfully! Model set to ${defaultModel}. Initialization complete.`, isMeta: true }]);
@@ -17469,9 +17488,13 @@ function App({ args = [] }) {
17469
17488
  ] : aiProvider === "NVIDIA" ? [
17470
17489
  // --- Kimi (Moonshot AI) ---
17471
17490
  {
17472
- cmd: "moonshotai/kimi-k2.6",
17491
+ cmd: "moonshotai/kimi-k2.7",
17473
17492
  desc: "Multimodal"
17474
17493
  },
17494
+ {
17495
+ cmd: "moonshotai/kimi-k2.6",
17496
+ desc: "[DEPRICATED]"
17497
+ },
17475
17498
  // --- DeepSeek Family ---
17476
17499
  {
17477
17500
  cmd: "deepseek-ai/deepseek-v4-flash",
@@ -17510,10 +17533,6 @@ function App({ args = [] }) {
17510
17533
  desc: "Text Only"
17511
17534
  },
17512
17535
  // --- GLM (Zhipu AI) ---
17513
- {
17514
- cmd: "z-ai/glm-5.1",
17515
- desc: "Text Only [DEPRICATED]"
17516
- },
17517
17536
  {
17518
17537
  cmd: "z-ai/glm-5.2",
17519
17538
  desc: "Text Only"
@@ -17854,7 +17873,7 @@ ${cleanText}`, color: "magenta" }];
17854
17873
  setTimeout(() => {
17855
17874
  if (global.gc) {
17856
17875
  const gCAsync = async () => {
17857
- for (let i = 0; i < 5; i++) {
17876
+ for (let i = 0; i < 3; i++) {
17858
17877
  global.gc();
17859
17878
  await new Promise((resolve) => setImmediate(resolve));
17860
17879
  }
@@ -17881,7 +17900,7 @@ ${cleanText}`, color: "magenta" }];
17881
17900
  setTimeout(() => {
17882
17901
  if (global.gc) {
17883
17902
  const gCAsync = async () => {
17884
- for (let i = 0; i < 5; i++) {
17903
+ for (let i = 0; i < 3; i++) {
17885
17904
  global.gc();
17886
17905
  await new Promise((resolve) => setImmediate(resolve));
17887
17906
  }
@@ -18504,12 +18523,24 @@ ${timestamp}` };
18504
18523
  const appendCancelMessage = () => {
18505
18524
  if (didAppendCancel) return;
18506
18525
  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 = [];
18507
18534
  setMessages((prev) => {
18508
18535
  const lastMsg = prev[prev.length - 1];
18509
18536
  if (lastMsg && lastMsg.text && lastMsg.text.includes("Request Cancelled")) {
18510
18537
  return prev;
18511
18538
  }
18512
- const updatedPrev = prev.map((m) => m.isStreaming ? { ...m, isStreaming: false } : m);
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);
18513
18544
  const newMsgs = [...updatedPrev, {
18514
18545
  id: "cancel-" + Date.now(),
18515
18546
  role: "system",
@@ -18520,6 +18551,159 @@ ${timestamp}` };
18520
18551
  return newMsgs;
18521
18552
  });
18522
18553
  };
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 = 1;
18656
+ if (queue.length > 35) batchSize = 5;
18657
+ else if (queue.length > 15) batchSize = 3;
18658
+ else if (queue.length > 5) batchSize = 2;
18659
+ let changed = false;
18660
+ const nextMsgs = [...activeStreamMessagesRef.current];
18661
+ const clonedIndices = /* @__PURE__ */ new Set();
18662
+ for (let i = 0; i < batchSize; i++) {
18663
+ if (queue.length === 0) break;
18664
+ const task = queue.shift();
18665
+ if (task.type === "create") {
18666
+ nextMsgs.push(task.msg);
18667
+ changed = true;
18668
+ } else if (task.type === "text") {
18669
+ const idx = nextMsgs.findIndex((m) => m.id === task.id);
18670
+ if (idx !== -1) {
18671
+ if (!clonedIndices.has(idx)) {
18672
+ nextMsgs[idx] = { ...nextMsgs[idx] };
18673
+ clonedIndices.add(idx);
18674
+ }
18675
+ nextMsgs[idx].text += task.text;
18676
+ changed = true;
18677
+ }
18678
+ } else if (task.type === "finalize-think") {
18679
+ const idx = nextMsgs.findIndex((m) => m.id === task.id);
18680
+ if (idx !== -1) {
18681
+ if (!clonedIndices.has(idx)) {
18682
+ nextMsgs[idx] = { ...nextMsgs[idx] };
18683
+ clonedIndices.add(idx);
18684
+ }
18685
+ nextMsgs[idx].isStreaming = false;
18686
+ nextMsgs[idx].duration = task.duration;
18687
+ changed = true;
18688
+ }
18689
+ }
18690
+ }
18691
+ if (changed) {
18692
+ activeStreamMessagesRef.current = nextMsgs;
18693
+ setActiveStreamMessages(nextMsgs);
18694
+ }
18695
+ } else if (streamFinishedRef.current) {
18696
+ clearInterval(typewriterIntervalRef.current);
18697
+ typewriterIntervalRef.current = null;
18698
+ finalizeTurn(apiStartVal);
18699
+ }
18700
+ }, 35);
18701
+ };
18702
+ const awaitTypewriter = async () => {
18703
+ while (systemSettings.progressiveRendering && typewriterQueueRef.current.length > 0) {
18704
+ await new Promise((resolve) => setTimeout(resolve, 10));
18705
+ }
18706
+ };
18523
18707
  let hasFiredJanitor = false;
18524
18708
  setIsProcessing(true);
18525
18709
  setLastChunkTime(Date.now());
@@ -18741,27 +18925,29 @@ Selection: ${val}`,
18741
18925
  let inToolCallString = null;
18742
18926
  const signalRegex = /\[?\s*turn\s*:\s*.*?\s*\]?/gi;
18743
18927
  for await (const packet of stream) {
18744
- await new Promise((resolve) => setTimeout(resolve, 3));
18745
18928
  if (packet.type === "text") {
18746
18929
  setLastChunkTime(Date.now());
18747
18930
  }
18748
18931
  if (isFirstPacket && packet.type === "text") {
18749
18932
  apiStart = Date.now();
18750
18933
  isFirstPacket = false;
18934
+ if (systemSettings.progressiveRendering) {
18935
+ startTypewriter(apiStart);
18936
+ }
18751
18937
  }
18752
18938
  if (packet.type === "status") {
18753
18939
  if (!packet.content?.includes("[start]")) {
18754
18940
  setStatusText(packet.content);
18755
18941
  }
18756
18942
  if (packet.content?.includes("[start]")) {
18757
- clearInterval(interval_for_timer);
18943
+ clearInterval(activeTimeIntervalRef.current);
18758
18944
  setActiveTime(0);
18759
- interval_for_timer = setInterval(() => {
18945
+ activeTimeIntervalRef.current = setInterval(() => {
18760
18946
  setActiveTime((prev) => prev + 1);
18761
18947
  }, 1e3);
18762
18948
  } else if (packet.content?.includes("[end]")) {
18763
18949
  setActiveTime(0);
18764
- clearInterval(interval_for_timer);
18950
+ clearInterval(activeTimeIntervalRef.current);
18765
18951
  }
18766
18952
  if (isBridgeConnected()) {
18767
18953
  sendStatus(packet.content);
@@ -18794,6 +18980,9 @@ Selection: ${val}`,
18794
18980
  continue;
18795
18981
  }
18796
18982
  if (packet.type === "turn_reset") {
18983
+ if (systemSettings.progressiveRendering) {
18984
+ await awaitTypewriter();
18985
+ }
18797
18986
  currentThinkId = null;
18798
18987
  currentAgentId = null;
18799
18988
  inThinkMode = false;
@@ -18801,21 +18990,29 @@ Selection: ${val}`,
18801
18990
  inToolCall = false;
18802
18991
  toolCallEncounteredInTurn = false;
18803
18992
  thinkConsumedInTurn = false;
18993
+ const streamingMsgs = activeStreamMessagesRef.current;
18994
+ activeStreamMessagesRef.current = [];
18995
+ setActiveStreamMessages([]);
18804
18996
  setMessages((prev) => {
18805
- const newMsgs = prev.map((m) => {
18806
- if (m.isStreaming) {
18807
- const flatText = m.text ? (" " + m.text).slice(1) : m.text;
18808
- const flatFullText = m.fullText ? (" " + m.fullText).slice(1) : m.fullText;
18809
- return { ...m, isStreaming: false, text: flatText, fullText: flatFullText };
18810
- }
18811
- return m;
18997
+ const totalDuration = Date.now() - apiStart;
18998
+ const flushed = streamingMsgs.map((m) => {
18999
+ const flatText = m.text ? (" " + m.text).slice(1) : m.text;
19000
+ const flatFullText = m.fullText ? (" " + m.fullText).slice(1) : m.fullText;
19001
+ return {
19002
+ ...m,
19003
+ isStreaming: false,
19004
+ text: flatText,
19005
+ fullText: flatFullText,
19006
+ workedDuration: m.role === "agent" ? totalDuration : m.workedDuration
19007
+ };
18812
19008
  });
19009
+ const newMsgs = [...prev, ...flushed];
18813
19010
  setCompletedIndex(newMsgs.length);
18814
19011
  return newMsgs;
18815
19012
  });
18816
19013
  clearBlocksCache();
18817
19014
  if (global.gc) {
18818
- for (let i = 0; i < 2; i++) {
19015
+ for (let i = 0; i < 1; i++) {
18819
19016
  global.gc();
18820
19017
  await new Promise((resolve) => setImmediate(resolve));
18821
19018
  }
@@ -18826,7 +19023,7 @@ Selection: ${val}`,
18826
19023
  if (packet.type === "interactive_turn_finished") {
18827
19024
  setIsProcessing(false);
18828
19025
  setActiveTime(0);
18829
- clearInterval(interval_for_timer);
19026
+ clearInterval(activeTimeIntervalRef.current);
18830
19027
  if (isBridgeConnected()) {
18831
19028
  sendStatus(null);
18832
19029
  }
@@ -18849,9 +19046,15 @@ Selection: ${val}`,
18849
19046
  continue;
18850
19047
  }
18851
19048
  if (packet.type === "visual_feedback") {
19049
+ if (systemSettings.progressiveRendering) {
19050
+ await awaitTypewriter();
19051
+ }
19052
+ const streamingMsgs = activeStreamMessagesRef.current;
19053
+ activeStreamMessagesRef.current = [];
19054
+ setActiveStreamMessages([]);
18852
19055
  setMessages((prev) => {
18853
- const updatedPrev = prev.map((m) => m.isStreaming ? { ...m, isStreaming: false } : m);
18854
- const newMsgs = [...updatedPrev, {
19056
+ const flushed = streamingMsgs.map((m) => ({ ...m, isStreaming: false }));
19057
+ const newMsgs = [...prev, ...flushed, {
18855
19058
  id: "feedback-" + Date.now() + "-" + Math.random().toString(36).substring(2, 9),
18856
19059
  role: "system",
18857
19060
  text: packet.content,
@@ -18889,9 +19092,15 @@ Selection: ${val}`,
18889
19092
  continue;
18890
19093
  }
18891
19094
  if (packet.type === "tool_result") {
19095
+ if (systemSettings.progressiveRendering) {
19096
+ await awaitTypewriter();
19097
+ }
19098
+ const streamingMsgs = activeStreamMessagesRef.current;
19099
+ activeStreamMessagesRef.current = [];
19100
+ setActiveStreamMessages([]);
18892
19101
  setMessages((prev) => {
18893
- const updatedPrev = prev.map((m) => m.isStreaming ? { ...m, isStreaming: false } : m);
18894
- const newMsgs = [...updatedPrev, {
19102
+ const flushed = streamingMsgs.map((m) => ({ ...m, isStreaming: false }));
19103
+ const newMsgs = [...prev, ...flushed, {
18895
19104
  id: "tool-" + Date.now(),
18896
19105
  role: "system",
18897
19106
  text: packet.content,
@@ -18957,7 +19166,7 @@ Selection: ${val}`,
18957
19166
  let chunkText = packet.content;
18958
19167
  if (packet.type === "text" && chunkText.includes("Request Cancelled")) {
18959
19168
  if (global.gc) {
18960
- for (let i = 0; i < 5; i++) {
19169
+ for (let i = 0; i < 3; i++) {
18961
19170
  global.gc();
18962
19171
  await new Promise((resolve) => setImmediate(resolve));
18963
19172
  }
@@ -19000,26 +19209,62 @@ Selection: ${val}`,
19000
19209
  if (beforeText) {
19001
19210
  if (!currentAgentId) {
19002
19211
  currentAgentId = "agent-" + Date.now();
19003
- setMessages((prev) => [...prev, { id: currentAgentId, role: "agent", text: beforeText, isStreaming: true }]);
19212
+ const newMsg = { id: currentAgentId, role: "agent", text: beforeText, isStreaming: true };
19213
+ if (systemSettings.progressiveRendering) {
19214
+ typewriterQueueRef.current.push({ type: "create", msg: { ...newMsg, text: "" } });
19215
+ pushTokenText(currentAgentId, beforeText);
19216
+ } else {
19217
+ activeStreamMessagesRef.current = [...activeStreamMessagesRef.current, newMsg];
19218
+ }
19004
19219
  } else {
19005
- setMessages((prev) => prev.map(
19006
- (m) => m.id === currentAgentId ? { ...m, text: m.text + beforeText, isStreaming: true } : m
19007
- ));
19220
+ if (systemSettings.progressiveRendering) {
19221
+ pushTokenText(currentAgentId, beforeText);
19222
+ } else {
19223
+ activeStreamMessagesRef.current = activeStreamMessagesRef.current.map(
19224
+ (m) => m.id === currentAgentId ? { ...m, text: m.text + beforeText, isStreaming: true } : m
19225
+ );
19226
+ }
19227
+ }
19228
+ if (!systemSettings.progressiveRendering) {
19229
+ setActiveStreamMessages([...activeStreamMessagesRef.current]);
19008
19230
  }
19009
19231
  }
19010
19232
  inThinkMode = true;
19011
19233
  thinkConsumedInTurn = true;
19012
19234
  let thinkStartText = afterText.replace(/<(think|thought)>/gi, "");
19013
19235
  currentThinkId = "think-" + Date.now();
19014
- setMessages((prev) => [...prev, { id: currentThinkId, role: "think", text: thinkStartText, isStreaming: true, startTime: Date.now() }]);
19236
+ const thinkMsg = { id: currentThinkId, role: "think", text: thinkStartText, isStreaming: true, startTime: Date.now() };
19237
+ if (systemSettings.progressiveRendering) {
19238
+ typewriterQueueRef.current.push({ type: "create", msg: { ...thinkMsg, text: "", startTime: Date.now() } });
19239
+ if (thinkStartText) {
19240
+ pushTokenText(currentThinkId, thinkStartText);
19241
+ }
19242
+ } else {
19243
+ activeStreamMessagesRef.current = [...activeStreamMessagesRef.current, thinkMsg];
19244
+ setActiveStreamMessages([...activeStreamMessagesRef.current]);
19245
+ }
19015
19246
  continue;
19016
19247
  }
19017
19248
  if ((chunkLower.includes("</think>") || chunkLower.includes("</thought>")) && currentThinkId) {
19018
19249
  const parts = chunkText.split(/<\/(think|thought)>/gi);
19019
19250
  const thinkPart = parts[0] || "";
19020
19251
  const agentPart = parts.slice(2).join("").replace(/<\/?(think|thought)>/gi, "");
19021
- setMessages((prev) => {
19022
- const newMsgs = prev.map((m) => {
19252
+ inThinkMode = false;
19253
+ currentAgentId = "agent-" + Date.now();
19254
+ if (systemSettings.progressiveRendering) {
19255
+ if (thinkPart) {
19256
+ pushTokenText(currentThinkId, thinkPart);
19257
+ }
19258
+ const startTime = parseInt(currentThinkId.split("-")[1]) || Date.now();
19259
+ const duration = Date.now() - startTime;
19260
+ typewriterQueueRef.current.push({ type: "finalize-think", id: currentThinkId, duration });
19261
+ const newAgentMsg = { id: currentAgentId, role: "agent", text: "", isStreaming: true };
19262
+ typewriterQueueRef.current.push({ type: "create", msg: newAgentMsg });
19263
+ if (agentPart) {
19264
+ pushTokenText(currentAgentId, agentPart);
19265
+ }
19266
+ } else {
19267
+ activeStreamMessagesRef.current = activeStreamMessagesRef.current.map((m) => {
19023
19268
  if (m.id === currentThinkId && typeof m.id === "string") {
19024
19269
  const startTime = m.startTime || parseInt(m.id.split("-")[1]) || Date.now();
19025
19270
  const duration = Date.now() - startTime;
@@ -19027,40 +19272,56 @@ Selection: ${val}`,
19027
19272
  }
19028
19273
  return m;
19029
19274
  });
19030
- inThinkMode = false;
19031
- currentAgentId = "agent-" + Date.now();
19032
- return [...newMsgs, { id: currentAgentId, role: "agent", text: agentPart, isStreaming: true }];
19033
- });
19275
+ activeStreamMessagesRef.current = [...activeStreamMessagesRef.current, { id: currentAgentId, role: "agent", text: agentPart, isStreaming: true }];
19276
+ setActiveStreamMessages([...activeStreamMessagesRef.current]);
19277
+ }
19034
19278
  continue;
19035
19279
  }
19036
19280
  if (inThinkMode && currentThinkId) {
19037
- setMessages((prev) => {
19038
- const next = [...prev];
19039
- let transitioning = false;
19040
- let transitionContent = "";
19041
- for (let i = next.length - 1; i >= 0; i--) {
19042
- if (next[i].id === currentThinkId) {
19043
- const newText = next[i].text + chunkText;
19281
+ let transitioning = false;
19282
+ let transitionContent = "";
19283
+ if (systemSettings.progressiveRendering) {
19284
+ if (chunkText.toLowerCase().includes("</think>")) {
19285
+ transitioning = true;
19286
+ const parts = chunkText.split(/<\/think>/gi);
19287
+ const thinkPart = parts[0] || "";
19288
+ transitionContent = parts.slice(1).join("</think>") || "";
19289
+ if (thinkPart) pushTokenText(currentThinkId, thinkPart);
19290
+ const startTime = parseInt(currentThinkId.split("-")[1]) || Date.now();
19291
+ const duration = Date.now() - startTime;
19292
+ typewriterQueueRef.current.push({ type: "finalize-think", id: currentThinkId, duration });
19293
+ inThinkMode = false;
19294
+ currentAgentId = "agent-" + Date.now();
19295
+ typewriterQueueRef.current.push({ type: "create", msg: { id: currentAgentId, role: "agent", text: "", isStreaming: true } });
19296
+ if (transitionContent) {
19297
+ pushTokenText(currentAgentId, transitionContent.replace(/<\/?(think|thought)>/gi, ""));
19298
+ }
19299
+ } else {
19300
+ pushTokenText(currentThinkId, chunkText);
19301
+ }
19302
+ } else {
19303
+ activeStreamMessagesRef.current = activeStreamMessagesRef.current.map((m) => {
19304
+ if (m.id === currentThinkId) {
19305
+ const newText = m.text + chunkText;
19044
19306
  if (newText.toLowerCase().includes("</think>")) {
19045
19307
  transitioning = true;
19046
19308
  const parts = newText.split(/<\/think>/gi);
19047
19309
  transitionContent = parts.slice(1).join("</think>") || "";
19048
- const startTime = next[i].startTime || parseInt(String(next[i].id).split("-")[1]) || Date.now();
19310
+ const startTime = m.startTime || parseInt(String(m.id).split("-")[1]) || Date.now();
19049
19311
  const duration = Date.now() - startTime;
19050
- next[i] = { ...next[i], text: parts[0], isStreaming: false, duration };
19051
- } else {
19052
- next[i] = { ...next[i], text: newText, isStreaming: true };
19312
+ return { ...m, text: parts[0], isStreaming: false, duration };
19053
19313
  }
19054
- break;
19314
+ return { ...m, text: newText, isStreaming: true };
19055
19315
  }
19056
- }
19316
+ return m;
19317
+ });
19057
19318
  if (transitioning) {
19058
19319
  inThinkMode = false;
19059
19320
  currentAgentId = "agent-" + Date.now();
19060
- next.push({ id: currentAgentId, role: "agent", text: transitionContent.replace(/<\/?(think|thought)>/gi, ""), isStreaming: true });
19321
+ activeStreamMessagesRef.current = [...activeStreamMessagesRef.current, { id: currentAgentId, role: "agent", text: transitionContent.replace(/<\/?(think|thought)>/gi, ""), isStreaming: true }];
19061
19322
  }
19062
- return next;
19063
- });
19323
+ setActiveStreamMessages([...activeStreamMessagesRef.current]);
19324
+ }
19064
19325
  } else if (!inThinkMode) {
19065
19326
  const chunkLower2 = chunkText.toLowerCase();
19066
19327
  if (!toolCallEncounteredInTurn && (chunkLower2.includes("tool:functions.") || chunkLower2.includes("agent:generalist."))) {
@@ -19068,91 +19329,69 @@ Selection: ${val}`,
19068
19329
  }
19069
19330
  if (!currentAgentId) {
19070
19331
  currentAgentId = "agent-" + Date.now();
19071
- setMessages((prev) => [...prev, { id: currentAgentId, role: "agent", text: chunkText, isStreaming: true }]);
19332
+ const newMsg = { id: currentAgentId, role: "agent", text: chunkText, isStreaming: true };
19333
+ if (systemSettings.progressiveRendering) {
19334
+ typewriterQueueRef.current.push({ type: "create", msg: { ...newMsg, text: "" } });
19335
+ pushTokenText(currentAgentId, chunkText);
19336
+ } else {
19337
+ activeStreamMessagesRef.current = [...activeStreamMessagesRef.current, newMsg];
19338
+ setActiveStreamMessages([...activeStreamMessagesRef.current]);
19339
+ }
19072
19340
  } else {
19073
- setMessages((prev) => {
19074
- const next = [...prev];
19341
+ if (systemSettings.progressiveRendering) {
19342
+ pushTokenText(currentAgentId, chunkText);
19343
+ } else {
19344
+ const next = [...activeStreamMessagesRef.current];
19075
19345
  for (let i = next.length - 1; i >= 0; i--) {
19076
19346
  if (next[i].id === currentAgentId) {
19077
19347
  next[i] = { ...next[i], text: next[i].text + chunkText, isStreaming: true };
19078
19348
  break;
19079
19349
  }
19080
19350
  }
19081
- return next;
19082
- });
19351
+ activeStreamMessagesRef.current = next;
19352
+ setActiveStreamMessages([...activeStreamMessagesRef.current]);
19353
+ }
19083
19354
  }
19084
19355
  }
19085
19356
  }
19357
+ if (systemSettings.progressiveRendering) {
19358
+ streamFinishedRef.current = true;
19359
+ } else {
19360
+ await finalizeTurn(apiStart);
19361
+ }
19086
19362
  const apiEnd = Date.now();
19087
19363
  setSessionApiTime((prev) => prev + (apiEnd - apiStart));
19088
19364
  } catch (err) {
19365
+ if (typewriterIntervalRef.current) {
19366
+ clearInterval(typewriterIntervalRef.current);
19367
+ typewriterIntervalRef.current = null;
19368
+ }
19369
+ typewriterQueueRef.current = [];
19089
19370
  setMessages((prev) => {
19090
19371
  setCompletedIndex(prev.length + 1);
19091
19372
  return [...prev, { id: "error-" + Date.now(), role: "system", text: `\u274C ERROR: ${err.message}` }];
19092
19373
  });
19093
19374
  } finally {
19094
- setIsProcessing(false);
19095
- setStatusText(null);
19096
- setActiveTime(0);
19097
- clearInterval(interval_for_timer);
19098
- if (didSignalTerminationRef.current) {
19099
- appendCancelMessage();
19100
- }
19101
- clearBlocksCache();
19102
- if (global.gc) {
19103
- try {
19104
- for (let i = 0; i < 5; i++) {
19105
- global.gc();
19106
- await new Promise((resolve) => setImmediate(resolve));
19107
- }
19108
- lastGCTime = Date.now();
19109
- } catch (e) {
19110
- }
19111
- }
19112
- if (!hasFiredJanitor) {
19113
- if (process.stdout.isTTY) {
19114
- process.stdout.write("\x1B]0;FluxFlow | Idle\x07");
19115
- process.stdout.write("\x1B]633;P;TerminalTitle=FluxFlow | Idle\x07");
19375
+ if (!systemSettings.progressiveRendering) {
19376
+ setIsProcessing(false);
19377
+ setStatusText(null);
19378
+ setActiveTime(0);
19379
+ clearInterval(activeTimeIntervalRef.current);
19380
+ if (didSignalTerminationRef.current) {
19381
+ appendCancelMessage();
19116
19382
  }
19117
- }
19118
- if (queuedPromptRef.current) {
19119
- setResolutionData(queuedPromptRef.current);
19120
- setQueuedPrompt(null);
19121
- const hintToResolve = queuedPromptRef.current;
19122
- queuedPromptRef.current = null;
19123
- setMessages((prev) => {
19124
- const newMsgs = [...prev];
19125
- const hintMsg = newMsgs.reverse().find((m) => m.text?.includes("[STEERING HINT: QUEUED]") || m.text?.includes("[QUESTION: QUEUED]"));
19126
- if (hintMsg) {
19127
- if (hintMsg.text.includes("[STEERING HINT: QUEUED]")) {
19128
- hintMsg.text = hintMsg.text.replace("[STEERING HINT: QUEUED]", "[STEERING HINT: FINISHED_TURN]");
19129
- } else if (hintMsg.text.includes("[QUESTION: QUEUED]")) {
19130
- hintMsg.text = hintMsg.text.replace("[QUESTION: QUEUED]", "[QUESTION: FINISHED_TURN]");
19383
+ clearBlocksCache();
19384
+ if (global.gc) {
19385
+ try {
19386
+ for (let i = 0; i < 3; i++) {
19387
+ global.gc();
19388
+ await new Promise((resolve) => setImmediate(resolve));
19131
19389
  }
19390
+ lastGCTime = Date.now();
19391
+ } catch (e) {
19132
19392
  }
19133
- return newMsgs.reverse();
19134
- });
19135
- setActiveView("resolution");
19393
+ }
19136
19394
  }
19137
- setMessages((prev) => {
19138
- const totalDuration = Date.now() - apiStart;
19139
- let foundLastAgent = false;
19140
- const newMsgs = [...prev].reverse().map((m) => {
19141
- let updated = m.isStreaming ? { ...m, isStreaming: false } : m;
19142
- if (updated.text) {
19143
- updated.text = (" " + updated.text).slice(1);
19144
- }
19145
- if (!foundLastAgent && updated.role === "agent") {
19146
- foundLastAgent = true;
19147
- updated = { ...updated, workedDuration: totalDuration };
19148
- }
19149
- return updated;
19150
- }).reverse();
19151
- const historyToSave = newMsgs.filter((m) => !String(m.id).startsWith("welcome") && (!m.isMeta || m.text && m.text.includes("Request Cancelled")));
19152
- saveChat(chatId, null, historyToSave);
19153
- setCompletedIndex(newMsgs.length);
19154
- return newMsgs;
19155
- });
19156
19395
  }
19157
19396
  };
19158
19397
  streamChat();
@@ -19386,7 +19625,7 @@ Selection: ${val}`,
19386
19625
  } else if (selectedProvider === "DeepSeek") {
19387
19626
  defaultModel = "deepseek-v4-flash";
19388
19627
  } else if (selectedProvider === "NVIDIA") {
19389
- defaultModel = "moonshotai/kimi-k2.6";
19628
+ defaultModel = "stepfun-ai/step-3.7-flash";
19390
19629
  }
19391
19630
  setActiveModel(defaultModel);
19392
19631
  const targetTier = (quotas.providerTiers || {})[selectedProvider] || "Free";
@@ -19714,7 +19953,7 @@ Selection: ${val}`,
19714
19953
  } else if (prov === "DeepSeek") {
19715
19954
  defaultModel = "deepseek-v4-flash";
19716
19955
  } else if (prov === "NVIDIA") {
19717
- defaultModel = "moonshotai/kimi-k2.6";
19956
+ defaultModel = "stepfun-ai/step-3.7-flash";
19718
19957
  }
19719
19958
  setActiveModel(defaultModel);
19720
19959
  const targetTier = (quotas.providerTiers || {})[prov] || "Free";
@@ -20625,16 +20864,30 @@ var init_app = __esm({
20625
20864
  if (delay >= 5e3) return "#ff0000";
20626
20865
  const points = [
20627
20866
  { t: 370, r: 0, g: 165, b: 100 },
20628
- { t: 800, r: 120, g: 220, b: 80 },
20629
- { t: 1500, r: 250, g: 210, b: 40 },
20630
- { t: 3e3, r: 255, g: 120, b: 0 },
20867
+ // deep green
20868
+ { t: 550, r: 40, g: 195, b: 80 },
20869
+ // green
20870
+ { t: 800, r: 120, g: 220, b: 50 },
20871
+ // lime-green
20872
+ { t: 1100, r: 190, g: 225, b: 20 },
20873
+ // yellow-green
20874
+ { t: 1500, r: 250, g: 210, b: 15 },
20875
+ // yellow
20876
+ { t: 2e3, r: 255, g: 170, b: 0 },
20877
+ // amber
20878
+ { t: 2800, r: 255, g: 110, b: 0 },
20879
+ // orange
20880
+ { t: 3800, r: 255, g: 50, b: 0 },
20881
+ // deep orange
20631
20882
  { t: 5e3, r: 255, g: 0, b: 0 }
20883
+ // red
20632
20884
  ];
20633
20885
  for (let i = 0; i < points.length - 1; i++) {
20634
20886
  const p1 = points[i];
20635
20887
  const p2 = points[i + 1];
20636
20888
  if (delay >= p1.t && delay <= p2.t) {
20637
- const ratio = (delay - p1.t) / (p2.t - p1.t);
20889
+ let ratio = (delay - p1.t) / (p2.t - p1.t);
20890
+ ratio = ratio * ratio * (3 - 2 * ratio);
20638
20891
  const r = Math.round(p1.r + (p2.r - p1.r) * ratio);
20639
20892
  const g = Math.round(p1.g + (p2.g - p1.g) * ratio);
20640
20893
  const b = Math.round(p1.b + (p2.b - p1.b) * ratio);
@@ -20646,6 +20899,7 @@ var init_app = __esm({
20646
20899
  SubagentRow = React16.memo(({ sa }) => {
20647
20900
  const [dotColor, setDotColor] = useState15("green");
20648
20901
  const chunkTimesRef = useRef4([]);
20902
+ const smoothedDelayRef = useRef4(370);
20649
20903
  useEffect12(() => {
20650
20904
  if (sa.status !== "running") {
20651
20905
  chunkTimesRef.current = [];
@@ -20656,7 +20910,7 @@ var init_app = __esm({
20656
20910
  const times = chunkTimesRef.current;
20657
20911
  if (times.length === 0 || times[times.length - 1] !== lastChunkTime) {
20658
20912
  times.push(lastChunkTime);
20659
- if (times.length > 5) {
20913
+ if (times.length > 10) {
20660
20914
  times.shift();
20661
20915
  }
20662
20916
  }
@@ -20676,8 +20930,13 @@ var init_app = __esm({
20676
20930
  averageInterval = sum / (times.length - 1);
20677
20931
  }
20678
20932
  const timeSinceLast = Date.now() - lastChunkTime;
20679
- const delay = Math.max(averageInterval, timeSinceLast);
20680
- setDotColor(getLatencyColor2(delay));
20933
+ const STALL_THRESHOLD = 2500;
20934
+ const isStalled = timeSinceLast >= STALL_THRESHOLD;
20935
+ const cappedTimeSinceLast = !isStalled && averageInterval > 0 ? Math.min(timeSinceLast, averageInterval * 3) : timeSinceLast;
20936
+ const rawDelay = Math.max(averageInterval, cappedTimeSinceLast);
20937
+ const alpha = isStalled ? 0.4 : 0.2;
20938
+ smoothedDelayRef.current = smoothedDelayRef.current * (1 - alpha) + rawDelay * alpha;
20939
+ setDotColor(getLatencyColor2(smoothedDelayRef.current));
20681
20940
  };
20682
20941
  checkLatency();
20683
20942
  const timer = setInterval(checkLatency, 100);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "3.2.2",
4
- "date": "2026-07-07",
3
+ "version": "3.2.5",
4
+ "date": "2026-07-08",
5
5
  "description": "A High-Fidelity Agentic CLI with Sub-Agents for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",