fluxflow-cli 3.2.7 → 3.3.1

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 +306 -119
  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,
@@ -2562,7 +2563,7 @@ var init_text = __esm({
2562
2563
  };
2563
2564
  parseMessageToBlocks = (msg, columns) => {
2564
2565
  if (!msg) return { completed: [], active: [] };
2565
- const cacheKey = `${msg.id}-${msg.text?.length || 0}-${columns}-${msg.isStreaming}`;
2566
+ const cacheKey = `${msg.id}-${msg.text?.length || 0}-${columns}-${msg.isStreaming}-${msg.workedDuration || 0}`;
2566
2567
  if (!msg.isStreaming && blocksCache.has(cacheKey)) {
2567
2568
  return blocksCache.get(cacheKey);
2568
2569
  }
@@ -4124,10 +4125,10 @@ var init_ChatLayout = __esm({
4124
4125
  tokenCache.set(cacheKey, tokens);
4125
4126
  return tokens;
4126
4127
  };
4127
- renderHighlightedLine = (line, lang, defaultColor = void 0) => {
4128
- 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 }, " ");
4129
4130
  const tokens = tokenizeLine(line, lang);
4130
- 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)));
4131
4132
  };
4132
4133
  renderLatexText = (content, key) => {
4133
4134
  if (!content) return null;
@@ -4257,7 +4258,7 @@ var init_ChatLayout = __esm({
4257
4258
  const level = headingMatch[1].length;
4258
4259
  const hText = headingMatch[2];
4259
4260
  result.push(
4260
- /* @__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))
4261
4262
  );
4262
4263
  return;
4263
4264
  }
@@ -4313,14 +4314,16 @@ var init_ChatLayout = __esm({
4313
4314
  const displayPrefix = isRemoval ? "-" : isAddition ? "+" : " ";
4314
4315
  const renderInlineDiff = () => {
4315
4316
  if (isPureUnpairedBlock) {
4316
- const blockColor = isRemoval ? "#ffdddd" : "#ddffdd";
4317
+ const blockColor = isRemoval ? "#ff3333" : "#33ff66";
4318
+ const textBgColor = isRemoval ? "#5a1818" : "#185a25";
4317
4319
  const wrappedLines = wrapText(content, columns - 15).split("\n");
4318
- 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))));
4319
4321
  }
4320
4322
  if (!(isRemoval || isAddition) || words.length === 0 || !hasInlineChange) {
4321
4323
  const textColor = isRemoval ? "#885555" : isAddition ? "#558866" : "gray";
4324
+ const textBgColor = void 0;
4322
4325
  const wrappedLines = wrapText(content, columns - 15).split("\n");
4323
- 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))));
4324
4327
  }
4325
4328
  return /* @__PURE__ */ React4.createElement(Text4, { wrap: "anywhere" }, words.map((part, idx) => {
4326
4329
  const isWhitespace = /^\s+$/.test(part.value);
@@ -4969,7 +4972,11 @@ var init_StatusBar = __esm({
4969
4972
  },
4970
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"))),
4971
4974
  /* @__PURE__ */ React5.createElement(Box4, { flexGrow: 1, justifyContent: "center", paddingX: 2 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", italic: true }, truncatePath(process.cwd(), 35))),
4972
- /* @__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"))))
4973
4980
  );
4974
4981
  });
4975
4982
  StatusBar_default = StatusBar;
@@ -5205,7 +5212,7 @@ ${mode === "Flux" ? `- WORKSPACE TOOLS (path = relative to CWD & WILL BE FIRST A
5205
5212
  3. [tool:functions.FileMap(path="path/file")]. Shows file structure, functions, class, import/export, variable
5206
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**
5207
5214
  5. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile > WriteFile. Verify Imports
5208
- 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
5209
5216
  7. [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? `WINDOWS POWERSHELL ONLY` : `WINDOWS CMD ONLY` : `BASH`} command. Destructive/Irreversible ops \u2192 Ask user
5210
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**
5211
5218
  9. [tool:functions.Await(time="seconds")]. For waiting without exiting agent loop, 15s - 180s
@@ -5984,6 +5991,7 @@ function SettingsMenu({
5984
5991
  { label: "Key Strategy", value: "apiTier", status: apiTier === "Free" ? "Free" : quotas?.providerBudgets?.__useProvider ? "Paid" : "Paid" },
5985
5992
  { label: "Preserve Thinking", value: "preserveThinking", status: systemSettings.preserveThinking !== false ? "ON" : "OFF" },
5986
5993
  { label: "Loading Phrases", value: "loadingPhrases", status: systemSettings.loadingPhrases !== false ? "ON" : "OFF" },
5994
+ { label: "Progressive Rendering [EXPERIMENTAL]", value: "progressiveRendering", status: systemSettings.progressiveRendering ? "ON" : "OFF" },
5987
5995
  { label: "Download Language Parsers", value: "parserDownload", status: "ACTION" }
5988
5996
  ];
5989
5997
  default:
@@ -6152,6 +6160,12 @@ function SettingsMenu({
6152
6160
  saveSettings2({ systemSettings: newSysSettings, apiTier, quotas });
6153
6161
  return newSysSettings;
6154
6162
  });
6163
+ } else if (item.value === "progressiveRendering") {
6164
+ setSystemSettings((s) => {
6165
+ const newSysSettings = { ...s, progressiveRendering: !s.progressiveRendering };
6166
+ saveSettings2({ systemSettings: newSysSettings, apiTier, quotas });
6167
+ return newSysSettings;
6168
+ });
6155
6169
  }
6156
6170
  };
6157
6171
  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) => {
@@ -6188,7 +6202,7 @@ function SettingsMenu({
6188
6202
  currentItems.forEach((item, index) => {
6189
6203
  const isSelected = activeColumn === "items" && selectedItemIndex === index;
6190
6204
  const labelLength = item.label.length;
6191
- const dotsCount = Math.max(2, 35 - labelLength);
6205
+ const dotsCount = Math.max(2, 38 - labelLength);
6192
6206
  const dots = ".".repeat(dotsCount);
6193
6207
  const getStatusColor = (item2) => {
6194
6208
  if (currentCatId === "security") {
@@ -6236,7 +6250,7 @@ function SettingsMenu({
6236
6250
  });
6237
6251
  if (currentCatId === "other") {
6238
6252
  elements.push(
6239
- /* @__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"))
6253
+ /* @__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"))
6240
6254
  );
6241
6255
  elements.push(
6242
6256
  /* @__PURE__ */ React7.createElement(Box6, { key: "memory-load-2026", paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, "Memory Load: ", currentMemory, "/", maxMemory, " ", memoryUnit))
@@ -8923,8 +8937,15 @@ var init_search_keyword = __esm({
8923
8937
  const { keyword, file, subString, regex } = parseArgs(args);
8924
8938
  if (!keyword) return 'ERROR: Missing "keyword" argument.';
8925
8939
  const toBool = (v) => v === true || v === "true" || v === 1 || v === "1" || v === "yes";
8926
- const matchRegex = toBool(regex);
8927
- 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
+ }
8928
8949
  let regexPattern;
8929
8950
  let wordRegex;
8930
8951
  if (matchRegex) {
@@ -9001,7 +9022,7 @@ var init_search_keyword = __esm({
9001
9022
  if (typeof global.gc === "function") {
9002
9023
  global.gc();
9003
9024
  }
9004
- const modeLabel = matchRegex ? "(regex mode)" : matchSubstring ? "(subString mode)" : "";
9025
+ const modeLabel = matchRegex ? isAutoRegex ? "(regex mode)" : "(keyword mode)" : matchSubstring ? "(subString mode)" : "";
9005
9026
  if (fileGroups.length === 0) {
9006
9027
  return `Found 0 matches for keyword: "${keyword}"${file ? ` in file: ${file}` : ". Try to specify files"} ${modeLabel}`;
9007
9028
  }
@@ -9825,8 +9846,11 @@ var init_invokeSync = __esm({
9825
9846
  }
9826
9847
  return result;
9827
9848
  } catch (err) {
9849
+ const { isTerminationSignaled: isTerminationSignaled2 } = await init_ai().then(() => ai_exports);
9850
+ const isCancelled = err.message === "Subagent task was cancelled by user." || isTerminationSignaled2();
9828
9851
  if (context.onVisualFeedback) {
9829
- context.onVisualFeedback(`\x1B[95mSubAgent\x1B[0m: \x1B[32mGeneralist\x1B[0m \u2192 ${title} [FAILED]
9852
+ const statusLabel = isCancelled ? "[CANCELLED]" : "[FAILED]";
9853
+ context.onVisualFeedback(`\x1B[95mSubAgent\x1B[0m: \x1B[32mGeneralist\x1B[0m \u2192 ${title} ${statusLabel}
9830
9854
  `);
9831
9855
  }
9832
9856
  return `ERROR: Subagent execution failed: ${err.message}`;
@@ -9946,8 +9970,18 @@ ${finalAnswer}`);
9946
9970
  if (context.onSubagentUpdate) {
9947
9971
  context.onSubagentUpdate();
9948
9972
  }
9949
- }).catch((err) => {
9950
- if (taskEntry.status === "cancelled") return;
9973
+ }).catch(async (err) => {
9974
+ const { isTerminationSignaled: isTerminationSignaled2 } = await init_ai().then(() => ai_exports);
9975
+ const isCancelled = err.message === "Subagent task was cancelled." || taskEntry.status === "cancelled" || isTerminationSignaled2();
9976
+ if (isCancelled) {
9977
+ taskEntry.status = "cancelled";
9978
+ currentTurnLogs.push(`[SUBAGENT CANCELLED] Task was cancelled.`);
9979
+ taskEntry.progress.push([...currentTurnLogs]);
9980
+ if (context.onSubagentUpdate) {
9981
+ context.onSubagentUpdate();
9982
+ }
9983
+ return;
9984
+ }
9951
9985
  currentTurnLogs.push(`[SUBAGENT FAILURE] Error: ${err.message}`);
9952
9986
  taskEntry.progress.push([...currentTurnLogs]);
9953
9987
  taskEntry.status = "failed";
@@ -10700,6 +10734,7 @@ __export(ai_exports, {
10700
10734
  getCleanGroupedLength: () => getCleanGroupedLength,
10701
10735
  initAI: () => initAI,
10702
10736
  isModelMultimodal: () => isModelMultimodal,
10737
+ isTerminationSignaled: () => isTerminationSignaled,
10703
10738
  runJanitorTask: () => runJanitorTask,
10704
10739
  runSubagent: () => runSubagent,
10705
10740
  signalTermination: () => signalTermination
@@ -10707,7 +10742,7 @@ __export(ai_exports, {
10707
10742
  import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
10708
10743
  import path21, { normalize } from "path";
10709
10744
  import fs22 from "fs";
10710
- var client, globalSettings, colorMainWords, withRetry, TERMINATION_SIGNAL, MULTIMODAL_MODELS, isModelMultimodal, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getNVIDIAStream, wrapNvidiaStreamWithQueueDepth, getOpenRouterStream, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream, runSubagent;
10745
+ var client, globalSettings, colorMainWords, withRetry, TERMINATION_SIGNAL, MULTIMODAL_MODELS, isModelMultimodal, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getNVIDIAStream, wrapNvidiaStreamWithQueueDepth, getOpenRouterStream, signalTermination, isTerminationSignaled, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream, runSubagent;
10711
10746
  var init_ai = __esm({
10712
10747
  async "src/utils/ai.js"() {
10713
10748
  await init_prompts();
@@ -10820,10 +10855,18 @@ var init_ai = __esm({
10820
10855
  throw new DOMException("The user aborted a request.", "AbortError");
10821
10856
  }
10822
10857
  try {
10823
- const response = await fetch(url, options);
10824
- if (response.ok) return response;
10825
- if (response.status !== 429 && response.status < 500) return response;
10858
+ const response2 = await fetch(url, options);
10859
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
10860
+ performance.clearMeasures();
10861
+ performance.clearMarks();
10862
+ }
10863
+ if (response2.ok) return response2;
10864
+ if (response2.status !== 429 && response2.status < 500) return response2;
10826
10865
  } catch (e) {
10866
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
10867
+ performance.clearMeasures();
10868
+ performance.clearMarks();
10869
+ }
10827
10870
  if (e.name === "AbortError" || signal?.aborted) throw e;
10828
10871
  if (i === retries - 1) throw e;
10829
10872
  }
@@ -10846,7 +10889,12 @@ var init_ai = __esm({
10846
10889
  if (signal?.aborted) {
10847
10890
  throw new DOMException("The user aborted a request.", "AbortError");
10848
10891
  }
10849
- return fetch(url, options);
10892
+ const response = await fetch(url, options);
10893
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
10894
+ performance.clearMeasures();
10895
+ performance.clearMarks();
10896
+ }
10897
+ return response;
10850
10898
  };
10851
10899
  getDeepSeekStream = async function* (apiKey, model, contents, systemInstruction, thinkingLevel, mode, isMultiModal, signal, temperature = 0.99) {
10852
10900
  const messages = [];
@@ -11415,6 +11463,9 @@ var init_ai = __esm({
11415
11463
  signalTermination = () => {
11416
11464
  TERMINATION_SIGNAL = true;
11417
11465
  };
11466
+ isTerminationSignaled = () => {
11467
+ return TERMINATION_SIGNAL;
11468
+ };
11418
11469
  TOOL_LABELS2 = {
11419
11470
  "write_file": "Writing",
11420
11471
  "update_file": "Editing",
@@ -11995,6 +12046,32 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
11995
12046
  if (!apiKey) return null;
11996
12047
  globalSettings = settings;
11997
12048
  client = new GoogleGenAI({ apiKey });
12049
+ if (!globalThis.__perfCleanupInstalled) {
12050
+ globalThis.__perfCleanupInstalled = true;
12051
+ setInterval(() => {
12052
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
12053
+ performance.clearMeasures();
12054
+ performance.clearMarks();
12055
+ }
12056
+ }, 6e4);
12057
+ const originalFetch = globalThis.fetch;
12058
+ globalThis.fetch = async (...args) => {
12059
+ try {
12060
+ const response = await originalFetch(...args);
12061
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
12062
+ performance.clearMeasures();
12063
+ performance.clearMarks();
12064
+ }
12065
+ return response;
12066
+ } catch (e) {
12067
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
12068
+ performance.clearMeasures();
12069
+ performance.clearMarks();
12070
+ }
12071
+ throw e;
12072
+ }
12073
+ };
12074
+ }
11998
12075
  return client;
11999
12076
  };
12000
12077
  generateSimpleContent = async (settings, model, contents, systemInstruction, thinkingLevel = "Fast", temperature = 0.75, usageKey = "agent") => {
@@ -12003,78 +12080,93 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
12003
12080
  let fullText = "";
12004
12081
  let usageMetadata = null;
12005
12082
  const normalizedContents = typeof contents === "string" ? [{ role: "user", parts: [{ text: contents }] }] : contents;
12006
- let stream;
12007
- if (aiProvider === "OpenRouter") {
12008
- stream = getOpenRouterStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, null, temperature);
12009
- } else if (aiProvider === "DeepSeek") {
12010
- stream = getDeepSeekStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, null, temperature);
12011
- } else if (aiProvider === "NVIDIA") {
12012
- stream = getNVIDIAStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, null, temperature);
12013
- } else {
12014
- const genStream = await client.models.generateContentStream({
12015
- model,
12016
- contents: normalizedContents,
12017
- config: {
12018
- systemInstruction,
12019
- temperature,
12020
- thinkingConfig: (() => {
12021
- const modelLower = (model || "").toLowerCase();
12022
- const isGemma4 = modelLower.includes("gemma-4") || modelLower.startsWith("gemma");
12023
- const isGemini3 = modelLower.includes("gemini-3");
12024
- if (isGemma4 || isGemini3) {
12025
- if (isGemma4) {
12026
- if (thinkingLevel.toLowerCase() !== "xhigh" || false) return { includeThoughts: false, thinkingLevel: ThinkingLevel.MINIMAL };
12027
- else return { includeThoughts: true, thinkingLevel: ThinkingLevel.HIGH };
12028
- }
12029
- return {
12030
- includeThoughts: true,
12031
- thinkingLevel: {
12032
- "Fast": modelLower.includes("pro") ? ThinkingLevel.LOW : ThinkingLevel.MINIMAL,
12033
- "Low": ThinkingLevel.LOW,
12034
- "Medium": ThinkingLevel.MEDIUM,
12035
- "Standard": ThinkingLevel.MEDIUM,
12036
- "High": ThinkingLevel.HIGH,
12037
- "xHigh": ThinkingLevel.HIGH
12038
- }[thinkingLevel] || ThinkingLevel.MEDIUM
12039
- };
12040
- } else {
12041
- const budget = {
12042
- "Fast": 0,
12043
- "Low": 512,
12044
- "Medium": 2048,
12045
- "Standard": 2048,
12046
- "High": 16384,
12047
- "xHigh": 24576
12048
- }[thinkingLevel] || 2048;
12049
- if (budget === 0) {
12050
- return { includeThoughts: false };
12083
+ const abortController = new AbortController();
12084
+ const signal = abortController.signal;
12085
+ let connectionPollInterval = setInterval(() => {
12086
+ if (TERMINATION_SIGNAL) {
12087
+ abortController.abort();
12088
+ clearInterval(connectionPollInterval);
12089
+ }
12090
+ }, 100);
12091
+ try {
12092
+ let stream;
12093
+ if (aiProvider === "OpenRouter") {
12094
+ stream = getOpenRouterStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, signal, temperature);
12095
+ } else if (aiProvider === "DeepSeek") {
12096
+ stream = getDeepSeekStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, signal, temperature);
12097
+ } else if (aiProvider === "NVIDIA") {
12098
+ stream = getNVIDIAStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, signal, temperature);
12099
+ } else {
12100
+ const genStream = await client.models.generateContentStream({
12101
+ model,
12102
+ contents: normalizedContents,
12103
+ config: {
12104
+ systemInstruction,
12105
+ temperature,
12106
+ thinkingConfig: (() => {
12107
+ const modelLower = (model || "").toLowerCase();
12108
+ const isGemma4 = modelLower.includes("gemma-4") || modelLower.startsWith("gemma");
12109
+ const isGemini3 = modelLower.includes("gemini-3");
12110
+ if (isGemma4 || isGemini3) {
12111
+ if (isGemma4) {
12112
+ if (thinkingLevel.toLowerCase() !== "xhigh" || false) return { includeThoughts: false, thinkingLevel: ThinkingLevel.MINIMAL };
12113
+ else return { includeThoughts: true, thinkingLevel: ThinkingLevel.HIGH };
12114
+ }
12115
+ return {
12116
+ includeThoughts: true,
12117
+ thinkingLevel: {
12118
+ "Fast": modelLower.includes("pro") ? ThinkingLevel.LOW : ThinkingLevel.MINIMAL,
12119
+ "Low": ThinkingLevel.LOW,
12120
+ "Medium": ThinkingLevel.MEDIUM,
12121
+ "Standard": ThinkingLevel.MEDIUM,
12122
+ "High": ThinkingLevel.HIGH,
12123
+ "xHigh": ThinkingLevel.HIGH
12124
+ }[thinkingLevel] || ThinkingLevel.MEDIUM
12125
+ };
12126
+ } else {
12127
+ const budget = {
12128
+ "Fast": 0,
12129
+ "Low": 512,
12130
+ "Medium": 2048,
12131
+ "Standard": 2048,
12132
+ "High": 16384,
12133
+ "xHigh": 24576
12134
+ }[thinkingLevel] || 2048;
12135
+ if (budget === 0) {
12136
+ return { includeThoughts: false };
12137
+ }
12138
+ return {
12139
+ includeThoughts: true,
12140
+ thinkingBudget: budget
12141
+ };
12051
12142
  }
12052
- return {
12053
- includeThoughts: true,
12054
- thinkingBudget: budget
12055
- };
12056
- }
12057
- })()
12058
- }
12059
- });
12060
- stream = genStream;
12061
- }
12062
- for await (const chunk of stream) {
12063
- if (settings?.taskId && typeof subagentProgress !== "undefined") {
12064
- const taskObj = subagentProgress.find((t) => t.id === settings.taskId);
12065
- if (taskObj && taskObj.status === "cancelled") {
12143
+ })()
12144
+ }
12145
+ }, { signal });
12146
+ stream = genStream;
12147
+ }
12148
+ for await (const chunk of stream) {
12149
+ if (TERMINATION_SIGNAL) {
12066
12150
  throw new Error("Subagent task was cancelled.");
12067
12151
  }
12068
- }
12069
- if (settings && typeof settings.onTokenChunk === "function") {
12070
- settings.onTokenChunk();
12071
- }
12072
- if (chunk.candidates?.[0]?.content?.parts) {
12073
- for (const part of chunk.candidates[0].content.parts) {
12074
- if (part.text && !part.thought) fullText += part.text;
12152
+ if (settings?.taskId && typeof subagentProgress !== "undefined") {
12153
+ const taskObj = subagentProgress.find((t) => t.id === settings.taskId);
12154
+ if (taskObj && taskObj.status === "cancelled") {
12155
+ throw new Error("Subagent task was cancelled.");
12156
+ }
12075
12157
  }
12158
+ if (settings && typeof settings.onTokenChunk === "function") {
12159
+ settings.onTokenChunk();
12160
+ }
12161
+ if (chunk.candidates?.[0]?.content?.parts) {
12162
+ for (const part of chunk.candidates[0].content.parts) {
12163
+ if (part.text && !part.thought) fullText += part.text;
12164
+ }
12165
+ }
12166
+ if (chunk.usageMetadata) usageMetadata = chunk.usageMetadata;
12076
12167
  }
12077
- if (chunk.usageMetadata) usageMetadata = chunk.usageMetadata;
12168
+ } finally {
12169
+ clearInterval(connectionPollInterval);
12078
12170
  }
12079
12171
  if (usageMetadata) {
12080
12172
  const total = usageMetadata.totalTokenCount || 0;
@@ -12911,7 +13003,7 @@ ${boxMid}
12911
13003
  }
12912
13004
  let taggedContextStr = "";
12913
13005
  if (taggedContextBlocks.length > 0) {
12914
- taggedContextStr = "[TAGGED CONTEXT]\n" + taggedContextBlocks.join("\n\n") + "\n[/TAGGED CONTEXT]\n";
13006
+ taggedContextStr = "[TAGGED FILE CONTENTS] Auto Read, System Provided Context\n" + taggedContextBlocks.join("\n\n") + "\n[/TAGGED FILE CONTENTS]\n";
12915
13007
  }
12916
13008
  const osDetected = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
12917
13009
  const firstUserMsg = `[SYSTEM METADATA (PRIORITY: DYNAMIC), Chat Context >> Metadata] Time: ${dateTimeStr}
@@ -12919,7 +13011,7 @@ OS: ${osDetected}
12919
13011
  CWD: ${process.cwd()}${isPlayground ? " [PLAYGROUND MODE]" : ""}${cwdMismatch ? ` (WARNING: CWD Mismatch! Previous Path: ${lastCwd})` : ""}
12920
13012
  **DIRECTORY STRUCTURE**
12921
13013
  ${dirStructure}${memoryPrompt}${ideBlock}
12922
- ${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();
13014
+ ${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();
12923
13015
  const userMsgObj = { role: "user", text: firstUserMsg };
12924
13016
  if (attachedBinaryPart) {
12925
13017
  userMsgObj.binaryPart = attachedBinaryPart;
@@ -12965,7 +13057,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
12965
13057
  [SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY [/SYSTEM]
12966
13058
  [QUESTION] ${hint.replace("/btw", "").trim()} [/QUESTION]`;
12967
13059
  } else {
12968
- 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]` });
13060
+ 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]` });
12969
13061
  }
12970
13062
  } else {
12971
13063
  if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "user") {
@@ -12973,7 +13065,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
12973
13065
 
12974
13066
  [STEERING HINT] ${hint.trim()} [/STEERING HINT]`;
12975
13067
  } else {
12976
- 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]` });
13068
+ 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]` });
12977
13069
  }
12978
13070
  }
12979
13071
  yield { type: "status", content: `${hint.startsWith("/btw") ? "Question Forwarded..." : "Steering Hint Injected..."}` };
@@ -13020,6 +13112,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
13020
13112
  let text = msg.text || "";
13021
13113
  if (msg.role === "agent") {
13022
13114
  text = text.replace(/\[turn:\s*finish\]/gi, "").replace(/\[\[END\]\]/gi, "").trim();
13115
+ text = text.replaceAll("\x1B[33m\u24D8 Request Cancelled\x1B[0m", "*User Cancelled Response Generation*");
13023
13116
  }
13024
13117
  const parts = [{ text }];
13025
13118
  if (msg.binaryPart && isModelMultimodal(targetModel)) {
@@ -14915,8 +15008,8 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
14915
15008
 
14916
15009
  [SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY [/SYSTEM]
14917
15010
  `, "").replace(`[SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY
14918
- **STRICTLY FOLLOW THINKING POLICY AS CRITICAL PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
14919
- `, "").replace(`[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS CRITICAL PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
15011
+ **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
15012
+ `, "").replace(`[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
14920
15013
  `, "");
14921
15014
  if (modelName && modelName.toLowerCase().startsWith("gemma") && aiProvider === "Google" && msg.text.startsWith("[TOOL RESULT]")) {
14922
15015
  const jitInstructionFast = `
@@ -14953,6 +15046,10 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
14953
15046
  clearInterval(connectionPollInterval);
14954
15047
  connectionPollInterval = null;
14955
15048
  }
15049
+ if (typeof performance !== "undefined" && performance.clearMeasures) {
15050
+ performance.clearMeasures();
15051
+ performance.clearMarks();
15052
+ }
14956
15053
  await RevertManager.commitTransaction();
14957
15054
  if (systemSettings?.advanceRollback) {
14958
15055
  await AdvanceRevertManager.cleanup(chatId);
@@ -14970,7 +15067,7 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
14970
15067
  "filemap": '- [tool:functions.FileMap(path="path/file")]. Shows file structure, functions, classes, imports/exports',
14971
15068
  "patchfile": '- [tool:functions.PatchFile(path="...", replaceContent1="...", newContent1="...")]. Surgical block replacement for editing files',
14972
15069
  "writefile": '- [tool:functions.WriteFile(path="...", content="...")]. Creates or overwrites a file',
14973
- "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`,
15070
+ "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`,
14974
15071
  "websearch": '- [tool:functions.WebSearch(query="...", limit=number)]. Web Search',
14975
15072
  "webscrape": '- [tool:functions.WebScrape(url="...")]. Web Scrape',
14976
15073
  "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`
@@ -15013,6 +15110,14 @@ Current Time: ${(/* @__PURE__ */ new Date()).toLocaleString("en-US", { year: "nu
15013
15110
  let turn = 0;
15014
15111
  let finalAnswer = "";
15015
15112
  while (turn < maxTurns) {
15113
+ if (TERMINATION_SIGNAL) {
15114
+ if (settings?.taskId && typeof subagentProgress !== "undefined") {
15115
+ const taskObj = subagentProgress.find((t) => t.id === settings.taskId);
15116
+ if (taskObj) taskObj.status = "cancelled";
15117
+ }
15118
+ if (logCallback) logCallback(`[SUBAGENT CANCELLED] Subagent task was cancelled.`);
15119
+ throw new Error("Subagent task was cancelled.");
15120
+ }
15016
15121
  if (settings?.taskId && typeof subagentProgress !== "undefined") {
15017
15122
  const taskObj = subagentProgress.find((t) => t.id === settings.taskId);
15018
15123
  if (taskObj && taskObj.status === "cancelled") {
@@ -15039,6 +15144,13 @@ ${cleanResponse}
15039
15144
  }
15040
15145
  let toolResultsStr = "";
15041
15146
  for (const toolCall of toolCalls) {
15147
+ if (TERMINATION_SIGNAL) {
15148
+ if (settings?.taskId && typeof subagentProgress !== "undefined") {
15149
+ const taskObj = subagentProgress.find((t) => t.id === settings.taskId);
15150
+ if (taskObj) taskObj.status = "cancelled";
15151
+ }
15152
+ throw new Error("Subagent task was cancelled.");
15153
+ }
15042
15154
  if (settings?.taskId && typeof subagentProgress !== "undefined") {
15043
15155
  const taskObj = subagentProgress.find((t) => t.id === settings.taskId);
15044
15156
  if (taskObj && taskObj.status === "cancelled") {
@@ -15062,17 +15174,20 @@ ${cleanResponse}
15062
15174
  } else if (normalizedToolName === "web_scrape" || normalizedToolName === "webscrape") {
15063
15175
  label = `\u2714 \x1B[95mScraped\x1B[0m`;
15064
15176
  } else if (normalizedToolName === "view_file" || normalizedToolName === "viewfile" || normalizedToolName === "readfile") {
15065
- label = `\u2714 \x1B[95mRead File\x1B[0m`;
15177
+ const path23 = parseArgs(toolCall.args).path || "";
15178
+ label = `\u2714 \x1B[95mRead File\x1B[0m: ${path23}`;
15066
15179
  } else if (normalizedToolName === "list_files" || normalizedToolName === "read_folder" || normalizedToolName === "readfolder") {
15067
- label = `\u2714 \x1B[95mBrowsed Folder\x1B[0m`;
15180
+ const path23 = parseArgs(toolCall.args).path || "";
15181
+ label = `\u2714 \x1B[95mBrowsed Folder\x1B[0m: ${path23}`;
15068
15182
  } else if (normalizedToolName === "write_file" || normalizedToolName === "writefile") {
15069
- const path23 = parseArgs(toolCall.args).path || "...";
15183
+ const path23 = parseArgs(toolCall.args).path || "";
15070
15184
  label = `\u2714 \x1B[95mFile Created\x1B[0m: ${path23}`;
15071
15185
  } else if (normalizedToolName === "update_file" || normalizedToolName === "updatefile" || normalizedToolName === "patchfile" || normalizedToolName === "patch_file" || normalizedToolName === "patchfile" || normalizedToolName === "updatefile") {
15072
- const path23 = parseArgs(toolCall.args).path || "...";
15186
+ const path23 = parseArgs(toolCall.args).path || "";
15073
15187
  label = `\u2714 \x1B[95mFile Edited\x1B[0m: ${path23}`;
15074
15188
  } else if (normalizedToolName === "file_map" || normalizedToolName === "filemap") {
15075
- label = `\u2714 \x1B[95mIndexed\x1B[0m`;
15189
+ const path23 = parseArgs(toolCall.args).path || "";
15190
+ label = `\u2714 \x1B[95mIndexed\x1B[0m: ${path23}`;
15076
15191
  } else if (normalizedToolName === "await") {
15077
15192
  const { time } = parseArgs(toolCall.args);
15078
15193
  let sec = parseFloat(time) || 0;
@@ -16116,6 +16231,8 @@ function App({ args = [] }) {
16116
16231
  const activeStreamingMsgRef = useRef4(null);
16117
16232
  const [renderTick, setRenderTick] = useState15(0);
16118
16233
  const forceRender = () => setRenderTick((t) => t + 1);
16234
+ const typewriterQueueRef = useRef4([]);
16235
+ const typewriterTickRef = useRef4(null);
16119
16236
  const commitActiveStreamingMessage = () => {
16120
16237
  if (activeStreamingMsgRef.current) {
16121
16238
  const msg = {
@@ -16131,6 +16248,58 @@ function App({ args = [] }) {
16131
16248
  activeStreamingMsgRef.current = null;
16132
16249
  }
16133
16250
  };
16251
+ const startTypewriter = () => {
16252
+ if (typewriterTickRef.current) {
16253
+ clearInterval(typewriterTickRef.current);
16254
+ }
16255
+ typewriterQueueRef.current = [];
16256
+ typewriterTickRef.current = setInterval(() => {
16257
+ const queue = typewriterQueueRef.current;
16258
+ if (queue.length > 0 && activeStreamingMsgRef.current) {
16259
+ let batchSize = 2;
16260
+ if (queue.length > 65) batchSize = 16;
16261
+ else if (queue.length > 50) batchSize = 12;
16262
+ else if (queue.length > 35) batchSize = 8;
16263
+ else if (queue.length > 15) batchSize = 6;
16264
+ else if (queue.length > 5) batchSize = 4;
16265
+ let batchedText = "";
16266
+ for (let i = 0; i < batchSize && queue.length > 0; i++) {
16267
+ batchedText += queue.shift();
16268
+ }
16269
+ activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + batchedText);
16270
+ forceRender();
16271
+ }
16272
+ }, 100);
16273
+ };
16274
+ const awaitTypewriter = async () => {
16275
+ while (systemSettings.progressiveRendering && typewriterQueueRef.current.length > 0) {
16276
+ await new Promise((resolve) => setTimeout(resolve, 10));
16277
+ }
16278
+ };
16279
+ const flushTypewriterNow = () => {
16280
+ const queue = typewriterQueueRef.current;
16281
+ if (queue.length > 0 && activeStreamingMsgRef.current) {
16282
+ const remaining = queue.join("");
16283
+ queue.length = 0;
16284
+ activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + remaining);
16285
+ forceRender();
16286
+ }
16287
+ };
16288
+ const appendStreamText = (chunkText) => {
16289
+ if (systemSettings.progressiveRendering && typewriterTickRef.current) {
16290
+ const tokens = chunkText.split(/(\s+)/).filter(Boolean);
16291
+ for (const tok of tokens) {
16292
+ typewriterQueueRef.current.push(tok);
16293
+ }
16294
+ } else {
16295
+ if (!activeStreamingMsgRef.current) {
16296
+ activeStreamingMsgRef.current = { id: "agent-" + Date.now(), role: "agent", text: flattenString(chunkText), isStreaming: true };
16297
+ } else {
16298
+ activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + chunkText);
16299
+ }
16300
+ forceRender();
16301
+ }
16302
+ };
16134
16303
  useEffect12(() => {
16135
16304
  const ideName = getIDEName();
16136
16305
  const isIDE = !["Terminal", "Windows Terminal"].includes(ideName) || !!process.env.VSC_TERMINAL_URL;
@@ -16790,11 +16959,9 @@ function App({ args = [] }) {
16790
16959
  for (let j = 0; j < parsed.completed.length; j++) streamingCompletedBlocks.push(parsed.completed[j]);
16791
16960
  for (let j = 0; j < parsed.active.length; j++) activeBlocks.push(parsed.active[j]);
16792
16961
  }
16793
- const finalCompleted = [...historicalBlocks];
16794
- for (let j = 0; j < streamingCompletedBlocks.length; j++) {
16795
- finalCompleted.push(streamingCompletedBlocks[j]);
16796
- }
16962
+ let finalCompleted = streamingCompletedBlocks.length === 0 ? historicalBlocks : historicalBlocks.concat(streamingCompletedBlocks);
16797
16963
  if (finalCompleted.length >= 75e3) {
16964
+ finalCompleted = [...finalCompleted];
16798
16965
  finalCompleted.push({
16799
16966
  key: `memory-warning-block-${finalCompleted.length}`,
16800
16967
  msg: {
@@ -18548,7 +18715,7 @@ ${timestamp}` };
18548
18715
  const updatedPrev = prev.map((m) => m.isStreaming ? { ...m, isStreaming: false } : m);
18549
18716
  const newMsgs = [...updatedPrev, {
18550
18717
  id: "cancel-" + Date.now(),
18551
- role: "system",
18718
+ role: "agent",
18552
18719
  text: "\n\n\x1B[33m\u24D8 Request Cancelled\x1B[0m",
18553
18720
  isMeta: false
18554
18721
  }];
@@ -18647,6 +18814,8 @@ ${timestamp}` };
18647
18814
  setActiveCommand(null);
18648
18815
  setIsTerminalFocused(false);
18649
18816
  setExecOutput("");
18817
+ activeCommandRef.current = null;
18818
+ execOutputRef.current = "";
18650
18819
  },
18651
18820
  onToolResult: (status, toolName) => {
18652
18821
  if (status === "success") {
@@ -18784,6 +18953,9 @@ Selection: ${val}`,
18784
18953
  if (isFirstPacket && packet.type === "text") {
18785
18954
  apiStart = Date.now();
18786
18955
  isFirstPacket = false;
18956
+ if (systemSettings.progressiveRendering) {
18957
+ startTypewriter();
18958
+ }
18787
18959
  }
18788
18960
  if (packet.type === "status") {
18789
18961
  if (!packet.content?.includes("[start]")) {
@@ -18803,6 +18975,7 @@ Selection: ${val}`,
18803
18975
  sendStatus(packet.content);
18804
18976
  }
18805
18977
  if (packet.content === "Request Cancelled") {
18978
+ flushTypewriterNow();
18806
18979
  commitActiveStreamingMessage();
18807
18980
  appendCancelMessage();
18808
18981
  }
@@ -18831,6 +19004,7 @@ Selection: ${val}`,
18831
19004
  continue;
18832
19005
  }
18833
19006
  if (packet.type === "turn_reset") {
19007
+ flushTypewriterNow();
18834
19008
  currentThinkId = null;
18835
19009
  currentAgentId = null;
18836
19010
  inThinkMode = false;
@@ -18886,6 +19060,7 @@ Selection: ${val}`,
18886
19060
  continue;
18887
19061
  }
18888
19062
  if (packet.type === "visual_feedback") {
19063
+ flushTypewriterNow();
18889
19064
  commitActiveStreamingMessage();
18890
19065
  setMessages((prev) => {
18891
19066
  const newMsgs = [...prev, {
@@ -19041,13 +19216,14 @@ Selection: ${val}`,
19041
19216
  activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + beforeText);
19042
19217
  }
19043
19218
  }
19219
+ flushTypewriterNow();
19044
19220
  commitActiveStreamingMessage();
19045
19221
  inThinkMode = true;
19046
19222
  thinkConsumedInTurn = true;
19047
19223
  let thinkStartText = afterText.replace(/<(think|thought)>/gi, "");
19048
19224
  currentThinkId = "think-" + Date.now();
19049
- activeStreamingMsgRef.current = { id: currentThinkId, role: "think", text: flattenString(thinkStartText), isStreaming: true, startTime: Date.now() };
19050
- forceRender();
19225
+ activeStreamingMsgRef.current = { id: currentThinkId, role: "think", text: "", isStreaming: true, startTime: Date.now() };
19226
+ appendStreamText(thinkStartText);
19051
19227
  continue;
19052
19228
  }
19053
19229
  if ((chunkLower.includes("</think>") || chunkLower.includes("</thought>")) && activeStreamingMsgRef.current?.role === "think") {
@@ -19057,11 +19233,12 @@ Selection: ${val}`,
19057
19233
  activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + thinkPart);
19058
19234
  const startTime = activeStreamingMsgRef.current.startTime || Date.now();
19059
19235
  activeStreamingMsgRef.current.duration = Date.now() - startTime;
19236
+ flushTypewriterNow();
19060
19237
  commitActiveStreamingMessage();
19061
19238
  inThinkMode = false;
19062
19239
  currentAgentId = "agent-" + Date.now();
19063
- activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text: flattenString(agentPart), isStreaming: true };
19064
- forceRender();
19240
+ activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text: "", isStreaming: true };
19241
+ appendStreamText(agentPart);
19065
19242
  continue;
19066
19243
  }
19067
19244
  if (inThinkMode && activeStreamingMsgRef.current?.role === "think") {
@@ -19073,14 +19250,15 @@ Selection: ${val}`,
19073
19250
  activeStreamingMsgRef.current.text = flattenString(thinkPart);
19074
19251
  const startTime = activeStreamingMsgRef.current.startTime || Date.now();
19075
19252
  activeStreamingMsgRef.current.duration = Date.now() - startTime;
19253
+ flushTypewriterNow();
19076
19254
  commitActiveStreamingMessage();
19077
19255
  inThinkMode = false;
19078
19256
  currentAgentId = "agent-" + Date.now();
19079
- activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text: flattenString(agentPart.replace(/<\/?(think|thought)>/gi, "")), isStreaming: true };
19257
+ activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text: "", isStreaming: true };
19258
+ appendStreamText(agentPart.replace(/<\/?(think|thought)>/gi, ""));
19080
19259
  } else {
19081
- activeStreamingMsgRef.current.text = flattenString(newText);
19260
+ appendStreamText(chunkText);
19082
19261
  }
19083
- forceRender();
19084
19262
  } else if (!inThinkMode) {
19085
19263
  const chunkLower2 = chunkText.toLowerCase();
19086
19264
  if (!toolCallEncounteredInTurn && (chunkLower2.includes("tool:functions.") || chunkLower2.includes("agent:generalist."))) {
@@ -19089,10 +19267,10 @@ Selection: ${val}`,
19089
19267
  if (!activeStreamingMsgRef.current || activeStreamingMsgRef.current.role !== "agent") {
19090
19268
  currentAgentId = "agent-" + Date.now();
19091
19269
  activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text: flattenString(chunkText), isStreaming: true };
19270
+ forceRender();
19092
19271
  } else {
19093
- activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + chunkText);
19272
+ appendStreamText(chunkText);
19094
19273
  }
19095
- forceRender();
19096
19274
  }
19097
19275
  }
19098
19276
  const apiEnd = Date.now();
@@ -19103,6 +19281,15 @@ Selection: ${val}`,
19103
19281
  return [...prev, { id: "error-" + Date.now(), role: "system", text: `\u274C ERROR: ${err.message}` }];
19104
19282
  });
19105
19283
  } finally {
19284
+ const totalDuration = Date.now() - apiStart;
19285
+ if (activeStreamingMsgRef.current) {
19286
+ activeStreamingMsgRef.current.workedDuration = totalDuration;
19287
+ }
19288
+ if (typewriterTickRef.current) {
19289
+ await awaitTypewriter();
19290
+ clearInterval(typewriterTickRef.current);
19291
+ typewriterTickRef.current = null;
19292
+ }
19106
19293
  setIsProcessing(false);
19107
19294
  setStatusText(null);
19108
19295
  setActiveTime(0);
@@ -19148,7 +19335,7 @@ Selection: ${val}`,
19148
19335
  setActiveView("resolution");
19149
19336
  }
19150
19337
  setMessages((prev) => {
19151
- const totalDuration = Date.now() - apiStart;
19338
+ const totalDuration2 = Date.now() - apiStart;
19152
19339
  let foundLastAgent = false;
19153
19340
  const newMsgs = [...prev].reverse().map((m) => {
19154
19341
  let updated = m.isStreaming ? { ...m, isStreaming: false } : m;
@@ -19157,7 +19344,7 @@ Selection: ${val}`,
19157
19344
  }
19158
19345
  if (!foundLastAgent && updated.role === "agent") {
19159
19346
  foundLastAgent = true;
19160
- updated = { ...updated, workedDuration: totalDuration };
19347
+ updated = { ...updated, workedDuration: totalDuration2 };
19161
19348
  }
19162
19349
  return updated;
19163
19350
  }).reverse();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "3.2.7",
4
- "date": "2026-07-08",
3
+ "version": "3.3.1",
4
+ "date": "2026-07-09",
5
5
  "description": "A High-Fidelity Agentic CLI with Sub-Agents for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",