fluxflow-cli 3.18.0 → 3.18.2

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.
package/dist/fluxflow.js CHANGED
@@ -3134,7 +3134,7 @@ var init_text = __esm({
3134
3134
  if (!msg.isStreaming && blocksCache.has(cacheKey)) {
3135
3135
  return blocksCache.get(cacheKey);
3136
3136
  }
3137
- const text = flattenString(cleanSignals(msg.text || ""));
3137
+ const text = flattenString(cleanSignals(msg.text || "", msg.role === "think"));
3138
3138
  const streamCacheKey = `${msg.id}-${columns}`;
3139
3139
  let cachedBlocks = /* @__PURE__ */ new Map();
3140
3140
  if (msg.isStreaming) {
@@ -3437,13 +3437,29 @@ var init_text = __esm({
3437
3437
  }
3438
3438
  return inCode;
3439
3439
  };
3440
- REGEX_CLEAN_SIGNALS = /\[SYSTEM\][\s\S]*?\[\/SYSTEM\]|<(think|thought)>[\s\S]*?(?:<\/(think|thought)>|$)|\[ANSWER\][\s\S]*?(?:\[\/ANSWER\]|$)|\[TOOL RESULT\]:?\s*|^\s*(SUCCESS|ERROR):.*(\r?\n)?|\[\s*turn\s*:\s*(continue|finish)\s*\]|\[\[END\]\]|\[\s*turn\s*:?.*?$|\n\s*turn\s*:?.*?$|\[\s*$|\n\nResponded on .*|\n\n\[Prompted on: .*\]|@\[TerminalName:.*?, ProcessId:.*?\]/gmi;
3440
+ REGEX_CLEAN_SIGNALS = /\[SYSTEM\][\s\S]*?\[\/SYSTEM\]|<(think|thought)>[\s\S]*?<\/(think|thought)>|\[ANSWER\][\s\S]*?(?:\[\/ANSWER\]|$)|\[TOOL RESULT\]:?\s*|^\s*(SUCCESS|ERROR):.*(\r?\n)?|\[\s*turn\s*:\s*(continue|finish)\s*\]|\[\[END\]\]|\[\s*turn\s*:?.*?$|\n\s*turn\s*:?.*?$|\[\s*(?:turn|ANSWER|TOOL).*?$|\n\nResponded on .*|\n\n\[Prompted on: .*\]|@\[TerminalName:.*?, ProcessId:.*?\]/gmi;
3441
3441
  REGEX_ARROWS_ALL = /(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)|(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)|(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)|(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)|(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi;
3442
3442
  REGEX_TOOLS = /\b(write_file|update_file|read_folder|view_file|exec_command|web_search|web_scrape|search_keyword|write_pdf|write_docx|generate_image)\b/gi;
3443
- bypassBacktick = false;
3444
- cleanSignals = (text) => {
3443
+ bypassBacktick = true;
3444
+ cleanSignals = (text, isThinkRole = false) => {
3445
3445
  if (!text) return text;
3446
+ if (isThinkRole) {
3447
+ return text.replace(/^<(think|thought)>/gi, "").replace(/<\/(think|thought)>$/gi, "");
3448
+ }
3446
3449
  let result = text.replace(REGEX_INITIAL_THINK, "</think>").replace(REGEX_INITIAL_TOOL, (match, _nl, offset, str) => !bypassBacktick && isInsideBacktick(str, offset) ? match : "");
3450
+ if (result && result.includes("[tool:")) {
3451
+ result = result.replace(/<(\w+)(?:[^>]*)>\s*([\s\S]*?\[tool:[^\]]*\][\s\S]*?)\s*<\/\1>/gi, (match, tagName, innerContent) => {
3452
+ if (innerContent && innerContent.includes("[tool:")) return innerContent.trim();
3453
+ return match;
3454
+ });
3455
+ if (bypassBacktick) {
3456
+ result = result.replace(/```(?:tool|yaml|function|json)?\s*\n?([\s\S]*?)\n?\```/gi, (match, inner) => {
3457
+ if (inner.includes("[tool:")) return inner.trim();
3458
+ return match;
3459
+ });
3460
+ }
3461
+ result = result.replace(/<(\w+)(?:[^>]*)>\r?\n?/gi, "").replace(/\r?\n?<\/\w+(?:[^>]*)>/gi, "");
3462
+ }
3447
3463
  const trigger = "tool:functions.";
3448
3464
  const subagentTrigger = "agent:generalist.";
3449
3465
  if (result.toLowerCase().includes(trigger) || result.toLowerCase().includes(subagentTrigger)) {
@@ -5561,7 +5577,7 @@ var init_ChatLayout = __esm({
5561
5577
  return /* @__PURE__ */ React4.createElement(MarkdownText, { key: i, text: cleanPart, color: "gray", columns: availableWidth, italic: true });
5562
5578
  }));
5563
5579
  };
5564
- REGEX_MD_TOKENS = /(```[\s\S]*?```|`[^`]+`|@\[.*?\]|\*\*.*?\*\*|\*.*?\*|\\\(.*?\\\)|\\\[.*?\\\]|\$.*?\$|\[.*?\]\s*\(.*?\)|\[.*?\]\s*\[.*?\]|https?:\/\/[^\s]+)/g;
5580
+ REGEX_MD_TOKENS = /(```[\s\S]*?```|`[^`\r\n]+`|@\[.*?\]|\*\*.*?\*\*|\*.*?\*|\\\(.*?\\\)|\\\[.*?\\\]|\$.*?\$|\[.*?\]\s*\(.*?\)|\[.*?\]\s*\[.*?\]|https?:\/\/[^\s]+)/g;
5565
5581
  REGEX_LATEX_FRAC = /\\frac\s*\{([^{}]*)\}\s*\{([^{}]*)\}/g;
5566
5582
  REGEX_LATEX_STYLE = /(\\(?:mathbf|textbf|textit|underline|texttt)\{[^{}]*\})/g;
5567
5583
  REGEX_MATH_MULT = /\\multiply|\\mul|\\times/g;
@@ -5708,13 +5724,17 @@ var init_ChatLayout = __esm({
5708
5724
  if (part.startsWith("*") && part.endsWith("*")) {
5709
5725
  return /* @__PURE__ */ React4.createElement(Text4, { key: j, italic: true, color: textColor }, /* @__PURE__ */ React4.createElement(InlineMarkdown, { text: part.slice(1, -1), color: textColor, italic, theme }));
5710
5726
  }
5711
- if (part.startsWith("`") && part.endsWith("`")) {
5712
- const content = part.slice(1, -1);
5713
- const formatted = content.replace(REGEX_AT_REF, (match, p1) => {
5714
- return p1.split("/").pop().split("\\").pop().replace(REGEX_COLON_L, "#L");
5715
- });
5716
- const hasFileRef = content.includes("@[");
5717
- return /* @__PURE__ */ React4.createElement(Text4, { key: j, color: highlightColor, bold: hasFileRef }, formatted);
5727
+ if (part.startsWith("`")) {
5728
+ if (part.endsWith("`") && part.length > 1) {
5729
+ const content = part.slice(1, -1);
5730
+ const formatted = content.replace(REGEX_AT_REF, (match, p1) => {
5731
+ return p1.split("/").pop().split("\\").pop().replace(REGEX_COLON_L, "#L");
5732
+ });
5733
+ const hasFileRef = content.includes("@[");
5734
+ return /* @__PURE__ */ React4.createElement(Text4, { key: j, color: highlightColor, bold: hasFileRef }, formatted);
5735
+ } else {
5736
+ return /* @__PURE__ */ React4.createElement(Text4, { key: j, color: highlightColor }, part.slice(1));
5737
+ }
5718
5738
  }
5719
5739
  if (part.startsWith("@[") && part.endsWith("]")) {
5720
5740
  const filePath = part.slice(2, -1);
@@ -6087,9 +6107,12 @@ var init_ChatLayout = __esm({
6087
6107
  if (part.startsWith("```")) {
6088
6108
  const match = part.match(/```(\w*)\n?([\s\S]*?)(?:```|$)/);
6089
6109
  const lang = match ? match[1] : "code";
6090
- const code = match ? match[2] : part.replace(/^```\w*\n?/, "").replace(/```$/, "");
6110
+ const raw = match ? match[2] : part.replace(/^```\w*\n?/, "").replace(/```$/, "");
6111
+ const rawLines = raw.trimEnd().split("\n");
6112
+ const gutterWidth = String(rawLines.length).length;
6113
+ const codeWidth = columns - 7 - gutterWidth;
6114
+ const code = codeWidth > 5 ? wrapText(raw, codeWidth) : raw;
6091
6115
  const codeLines = code.trimEnd().split("\n");
6092
- const gutterWidth = String(codeLines.length).length;
6093
6116
  return /* @__PURE__ */ React4.createElement(
6094
6117
  Box3,
6095
6118
  {
@@ -6275,7 +6298,7 @@ var init_ChatLayout = __esm({
6275
6298
  return /* @__PURE__ */ React4.createElement(Box3, { marginBottom: 0, paddingX: 1, width: "100%" }, /* @__PURE__ */ React4.createElement(TerminalBox, { command: cmd, output: outputList, completed: true, columns, isPty, theme }));
6276
6299
  }
6277
6300
  const [animationDone, setAnimationDone] = React4.useState(!msg.isStreaming);
6278
- const content = React4.useMemo(() => cleanSignals(msg.text), [msg.text]);
6301
+ const content = React4.useMemo(() => cleanSignals(msg.text, msg.role === "think"), [msg.text, msg.role]);
6279
6302
  React4.useEffect(() => {
6280
6303
  if (msg.isStreaming) setAnimationDone(false);
6281
6304
  }, [msg.id]);
@@ -6301,7 +6324,7 @@ var init_ChatLayout = __esm({
6301
6324
  finalContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\\\n/g, "\n").replace(/\\$/, ""),
6302
6325
  columns - 7
6303
6326
  ).split("\n").map((line, lineIdx) => /* @__PURE__ */ React4.createElement(Box3, { key: lineIdx, flexDirection: "row", width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { flexShrink: 0, width: 2 }, /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: colors.userMsgText }, lineIdx === 0 ? ">" : " ")), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React4.createElement(InlineMarkdown, { text: line, color: msg.color || colors.userMsgText, theme }))))
6304
- ), /* @__PURE__ */ React4.createElement(Box3, { width: columns - 1, height: 1, overflow: "hidden" }, /* @__PURE__ */ React4.createElement(Text4, { color: colors.userMsgBorder }, "\u2580".repeat(Math.max(1, columns - 1))))) : msg.role === "think" ? /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginTop: 0, marginBottom: 0, paddingX: 1, width: "100%" }, msg.isStreaming && !msg.duration ? /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: colors.text }, "\u2727 Thinking...") : /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: colors.text }, "\u2726 Thought", msg.duration ? /* @__PURE__ */ React4.createElement(Text4, { color: colors.textMuted }, " for ", /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: colors.text }, formatThinkingDuration(msg.duration))) : "..."), /* @__PURE__ */ React4.createElement(Box3, { borderStyle: "single", borderLeft: true, borderRight: false, borderTop: false, borderBottom: false, borderColor: colors.borderMuted, paddingLeft: 2, paddingTop: 1, paddingBottom: 1, flexDirection: "column", width: "100%" }, formatThinkText(finalContent, columns))) : /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", paddingX: 1, marginTop: 0, width: "100%" }, /* @__PURE__ */ React4.createElement(CodeRenderer, { text: finalContent.replace(/ \|\n\n/g, " |\n"), columns, theme }), msg.memoryUpdated && /* @__PURE__ */ React4.createElement(Box3, { marginTop: 1, width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, { color: colors.text, italic: true }, "[Memory Updated]")), msg.role === "agent" && msg.workedDuration ? /* @__PURE__ */ React4.createElement(Box3, { marginTop: 1, marginBottom: 2, width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, { color: colors.textMuted }, "["), /* @__PURE__ */ React4.createElement(Text4, { color: colors.textMuted }, "Worked for ", /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: colors.text }, formatThinkingDuration(msg.workedDuration))), /* @__PURE__ */ React4.createElement(Text4, { color: colors.textMuted }, "]")) : null));
6327
+ ), /* @__PURE__ */ React4.createElement(Box3, { width: columns - 1, height: 1, overflow: "hidden" }, /* @__PURE__ */ React4.createElement(Text4, { color: colors.userMsgBorder }, "\u2580".repeat(Math.max(1, columns - 1))))) : msg.role === "think" ? /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", marginTop: 0, marginBottom: 0, paddingX: 0, width: "100%" }, msg.isStreaming && !msg.duration ? /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: colors.text }, "\u2727 Thinking...") : /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: colors.text }, "\u2726 Thought", msg.duration ? /* @__PURE__ */ React4.createElement(Text4, { color: colors.textMuted }, " for ", /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: colors.text }, formatThinkingDuration(msg.duration))) : "s..."), /* @__PURE__ */ React4.createElement(Box3, { borderStyle: "single", borderLeft: true, borderRight: false, borderTop: false, borderBottom: false, borderColor: colors.borderMuted, paddingLeft: 2, paddingTop: 0, paddingBottom: 0, flexDirection: "column", width: "100%" }, formatThinkText(finalContent, columns))) : /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", paddingX: 1, marginTop: 0, width: "100%" }, /* @__PURE__ */ React4.createElement(CodeRenderer, { text: finalContent.replace(/ \|\n\n/g, " |\n"), columns, theme }), msg.memoryUpdated && /* @__PURE__ */ React4.createElement(Box3, { marginTop: 1, width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, { color: colors.text, italic: true }, "[Memory Updated]")), msg.role === "agent" && msg.workedDuration ? /* @__PURE__ */ React4.createElement(Box3, { marginTop: 1, marginBottom: 2, width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, { color: colors.textMuted }, "["), /* @__PURE__ */ React4.createElement(Text4, { color: colors.textMuted }, "Worked for ", /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: colors.text }, formatThinkingDuration(msg.workedDuration))), /* @__PURE__ */ React4.createElement(Text4, { color: colors.textMuted }, "]")) : null));
6305
6328
  });
6306
6329
  BlockItem = React4.memo(({ block, columns = 80, showFullThinking, aiProvider, version, theme = "Dark" }) => {
6307
6330
  const colors = getThemeColors(theme);
@@ -6334,7 +6357,7 @@ var init_ChatLayout = __esm({
6334
6357
  );
6335
6358
  }
6336
6359
  if (type === "think-header") {
6337
- return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", paddingX: 1, width: "100%", marginTop: 0, marginBottom: 0 }, isStreamingMsg ? /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: colors.text }, "\u2727 Thinking...") : /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: colors.text }, "\u2726 Thought..."), showFullThinking && /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "row", width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, { color: colors.textMuted }, "\u2502 ")));
6360
+ return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", paddingX: 1, width: "100%", marginTop: 0, marginBottom: 0 }, isStreamingMsg ? /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: colors.text }, "\u2727 Thinking...") : /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: colors.text }, "\u2726 Thoughts..."), showFullThinking && /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "row", width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, { color: colors.textMuted }, "\u2502 ")));
6338
6361
  }
6339
6362
  if (type === "think-line") {
6340
6363
  if (!showFullThinking) return null;
@@ -6677,7 +6700,7 @@ var init_StatusBar = __esm({
6677
6700
  updateMemory();
6678
6701
  const interval = setInterval(() => {
6679
6702
  updateMemory();
6680
- }, 3e4);
6703
+ }, 6e4);
6681
6704
  return () => {
6682
6705
  clearInterval(interval);
6683
6706
  if (activeGetMemoryInfo === updateMemory) {
@@ -6704,7 +6727,7 @@ var init_StatusBar = __esm({
6704
6727
  const pct = tokens / maxLimit * 100;
6705
6728
  const color = pct < 60 ? colors.text : pct < 80 ? colors.warning : colors.danger;
6706
6729
  return /* @__PURE__ */ React5.createElement(Text5, { color, dimColor: true }, pct.toFixed(0), "%");
6707
- })())), /* @__PURE__ */ React5.createElement(Text5, { color: colors.textMuted, dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginLeft: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: colors.textMuted, bold: true }, memoryUsage, "/", memoryLimit, " ", memoryUnit), (apiTier === "Custom" || apiTier === "Paid") && /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { color: colors.textMuted, dimColor: true }, " \u2503 "), /* @__PURE__ */ React5.createElement(Text5, { color: colors.textMuted, bold: true }, "PAID"))))
6730
+ })())), /* @__PURE__ */ React5.createElement(Text5, { color: colors.textMuted, dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginLeft: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: colors.textMuted, bold: true }, memoryUsage, " ", memoryUnit), (apiTier === "Custom" || apiTier === "Paid") && /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { color: colors.textMuted, dimColor: true }, " \u2503 "), /* @__PURE__ */ React5.createElement(Text5, { color: colors.textMuted, bold: true }, "PAID"))))
6708
6731
  );
6709
6732
  });
6710
6733
  StatusBar_default = StatusBar;
@@ -6930,11 +6953,9 @@ var init_main_tools = __esm({
6930
6953
  }
6931
6954
  return `
6932
6955
  -- TOOL DEFINITIONS --
6933
- Tool calls: ONLY use [tool:functions.ToolName(arg1="value1")] IN NEW LINE
6934
- **NO OTHER SYNTAX/MARKERS/WRAPPER/BOUNDARY ALLOWED**
6935
-
6936
- **TOOL CALLS POLICY:**
6937
- - MAX 4 TOOL CALLS/TURN${mode === "Flux" ? " (Todo: 4+, Run: max 1 or 2 consecutive)" : ""}
6956
+ FOR TOOL CALLING ONLY USE '[tool:functions.ToolName(arg1="value1")]' SYNTAX IN NEW LINE **NO OTHER SYNTAX ALLOWED** \u2190 MANDATORY
6957
+ TOOL RULES:
6958
+ - MAX 3 TOOL CALLS/TURN${mode === "Flux" ? " (Todo: 3+, Run: max 1 or 2 consecutive)" : ""}
6938
6959
  ${mode === "Flux" ? `- JSON ESCAPE ALL LITERAL ESCAPE SEQUENCES IN TOOL ARGUMENTS
6939
6960
  - SAME file, MULTIPLE edits? ONE PatchFile (\u226415 blocks) \u2190 PRIORITY
6940
6961
  - Tool denied? Ask for guidance \u2190 MANDATORY
@@ -8687,11 +8708,12 @@ ${mode === "Flux" ? "Logical, task-driven. Prioritize scalable, modular architec
8687
8708
 
8688
8709
  - USE DIRECTORY STRUCTURE FOR FILE AVAILABILITY AND PATH RESOLUTION
8689
8710
  - USE RELATIVE TIME REFERENCE eg. few mins ago
8711
+ - NO HALLUCINATIONS
8690
8712
 
8691
8713
  -- THINKING GUIDANCE --
8692
8714
  ${aiProvider === "Mistral" || aiProvider === "Google" && !isGemini ? `${thinkingConfig}
8693
8715
  ${forcedReasoning || thinkingLevel !== "Fast" && (aiProvider === "Mistral" || thinkingLevel !== "xHigh" && !isGemini) ? `CRITICAL THINKING POLICY
8694
- - Use <think> ... </think> for reasoning before responding, even with simple queries/greetings
8716
+ - Use <think>...</think> for reasoning before responding any queries
8695
8717
  ` : ""}` : `${thinkingConfig}
8696
8718
  `}
8697
8719
  ${TOOL_PROTOCOL(mode, osDetected, aiProvider.toLowerCase() === "deepseek" ? false : isMultiModal, aiProvider, systemSettings?.advanceRollback, systemSettings?.subAgents !== false)}
@@ -8703,9 +8725,8 @@ ${projectContextBlock}${isMemoryEnabled ? `
8703
8725
  - Sensitive files? Ask before Read${isSystemDir ? "\n- PROTECTED DIRECTORY" : ""}
8704
8726
 
8705
8727
  -- CHAT FORMATTING --
8706
- - GFM Markdown ONLY
8707
- - Same Language as User Query
8708
- - Finish all chatting before tool calls${mode === "Flux" ? "" : "\n- Use Kaomojis HEAVILY"}
8728
+ - GFM Markdown
8729
+ - NEVER MIX CHAT & TOOLS IN SAME RESPONSE${mode === "Flux" ? "" : "\n- Use Kaomojis HEAVILY"}
8709
8730
  === END SYSTEM PROMPT ===
8710
8731
 
8711
8732
  ${nameStr}${nicknameStr}${userInstrStr}${userMemoriesStr}`.trim();
@@ -13899,7 +13920,7 @@ var init_ai = __esm({
13899
13920
  RE_KIMI_JSON_PAIR = /"([^"]+)"\s*:\s*(?:"([^"]*)"|(\d+)|true|false|null)/g;
13900
13921
  RE_KIMI_SECTION_BEGIN = /<\|\s*tool_calls_section_begin\s*\|>/gi;
13901
13922
  RE_KIMI_SECTION_END = /<\|\s*tool_calls_section_end\s*\|>/gi;
13902
- bypassBacktick2 = false;
13923
+ bypassBacktick2 = true;
13903
13924
  client = null;
13904
13925
  globalSettings = {};
13905
13926
  systemInstructionCache = { key: null, value: null };
@@ -16131,8 +16152,8 @@ ${currentSummary}
16131
16152
  const ideCtx = await getIDEContext();
16132
16153
  let ideBlock = "";
16133
16154
  if (isBridgeConnected()) {
16134
- ideBlock = "\n[ADDITIONAL IDE CONTEXT]\n";
16135
16155
  if (ideCtx.file_focused !== "none") {
16156
+ ideBlock = "\n[ADDITIONAL IDE CONTEXT]\n";
16136
16157
  const relFocused = path26.relative(process.cwd(), ideCtx.file_focused);
16137
16158
  const relOpened = (ideCtx.opened_editors || []).map((p) => {
16138
16159
  const rel = path26.relative(process.cwd(), p);
@@ -16270,7 +16291,6 @@ ${ideCtx.warnings}
16270
16291
  `;
16271
16292
  }
16272
16293
  } else {
16273
- ideBlock += `No file currently focused.`;
16274
16294
  }
16275
16295
  }
16276
16296
  const cleanAgentText = agentText.replace(/\s*\[Prompted on:.*?\]/g, "").trim();
@@ -16410,10 +16430,8 @@ OS: ${osDetected}${systemSettings?.dynamicDirAwareness ? dirStructure : ""}${cwd
16410
16430
  WARNING: CWD Changed from previous: "${lastCwd}" to current: "${process.cwd()}", write change in chat to avoid future path mismatches
16411
16431
  ` : ""}${memoryPrompt}${ideBlock}
16412
16432
  [/METADATA]
16413
- ${activeSummaryBlock}${thinkingLevel !== "Fast" && (aiProvider === "Mistral" || thinkingLevel !== "xHigh" && aiProvider === "Google") ? `${aiProvider === "Mistral" || modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]\n" : ""}` : ""}[SYSTEM Priority: HIGH] ONLY use the system prompt tool schema [tool:functions.ToolName(arg1="value1")] [/SYSTEM]
16414
- ${taggedContextStr}[USER PROMPT]
16415
- ${cleanPromptForModel.trim()}
16416
- [/USER PROMPT]`.trim();
16433
+ ${activeSummaryBlock}${thinkingLevel !== "Fast" && (aiProvider === "Mistral" || thinkingLevel !== "xHigh" && aiProvider === "Google") ? `${aiProvider === "Mistral" || modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think>...</think>** [/SYSTEM]\n" : ""}` : ""}[SYSTEM] ONLY VALID TOOL SCHEMA REMINDER: '[tool:functions.ToolName(arg1="value1")]' NEW LINE [/SYSTEM]
16434
+ ${taggedContextStr}[USER PROMPT] ${cleanPromptForModel.trim()} [/USER PROMPT]`.trim();
16417
16435
  const userMsgObj = { role: "user", text: firstUserMsg };
16418
16436
  if (attachedBinaryPart) {
16419
16437
  userMsgObj.binaryPart = attachedBinaryPart;
@@ -16532,8 +16550,22 @@ ${combinedNudge}`;
16532
16550
  accumulatedContext = "";
16533
16551
  }
16534
16552
  }
16553
+ const stripToolCallWrappers = (text) => {
16554
+ if (!text || !text.includes("[tool:")) return text;
16555
+ text = text.replace(/<(\w+)(?:[^>]*)>\s*([\s\S]*?\[tool:[^\]]*\][\s\S]*?)\s*<\/\1>/gi, (match2, tagName, innerContent) => {
16556
+ if (innerContent && innerContent.includes("[tool:")) return innerContent.trim();
16557
+ return match2;
16558
+ });
16559
+ text = text.replace(/```(?:tool|yaml|function|json)?\s*\n?([\s\S]*?)\n?\```/gi, (match2, inner) => {
16560
+ if (inner.includes("[tool:")) return inner.trim();
16561
+ return match2;
16562
+ });
16563
+ text = text.replace(/<(\w+)(?:[^>]*)>\r?\n?/gi, "").replace(/\r?\n?<\/\w+(?:[^>]*)>/gi, "");
16564
+ return text;
16565
+ };
16535
16566
  const contents = modifiedHistory.filter((msg) => (msg.role === "user" || msg.role === "agent" || msg.role === "system") && !String(msg.id).startsWith("welcome") && !msg.isMeta && !msg.isTerminalRecord && !(msg.text && msg.text.startsWith("[TERMINAL_RECORD]"))).map((msg, idx, arr) => {
16536
16567
  let text = msg.text || "";
16568
+ text = stripToolCallWrappers(text);
16537
16569
  if (msg.role === "agent") {
16538
16570
  text = text.replace(/\[turn:\s*finish\]/gi, "").replace(/\[\[END\]\]/gi, "").trim();
16539
16571
  text = text.replaceAll("\x1B[33m\u24D8 Request Cancelled\x1B[0m", "*User Cancelled Response Generation*");
@@ -18633,10 +18665,8 @@ Error Log can be found in ${path26.join(LOGS_DIR, "agent", "error.log")}`);
18633
18665
  const targetModel = model || subAgentCustomModel || settings?.modelName || settings?.activeModel || savedSettings.activeModel;
18634
18666
  const osDetected = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
18635
18667
  const providedToolsSection = `-- TOOL DEFINITIONS (path = relative to CWD, path separator: '/') --
18636
- TO ACCESS TOOLS **STRICTLY USE THE EXACT FORMAT IN CHAT OUTPUT:** [tool:functions.ToolName(arg1="value1")]
18637
- **NO OTHER SYNTAX/MARKERS/WRAPPER/BOUNDARY ALLOWED**
18638
-
18639
- TOOL POLICY:
18668
+ FOR TOOL CALLING ONLY USE '[tool:functions.ToolName(arg1="value1")]' SYNTAX IN NEW LINE **NO OTHER SYNTAX ALLOWED** \u2190 MANDATORY
18669
+ TOOL RULES:
18640
18670
  - JSON ESCAPE ALL LITERAL ESCAPE SEQUENCES IN TOOL ARGUMENTS
18641
18671
  - SAME file, MULTIPLE edits? ONE PatchFile (\u226415 blocks) \u2190 PRIORITY
18642
18672
  - Need text or huge files? SearchKeyword > Full Read
@@ -18668,7 +18698,7 @@ ${providedToolsSection.trimEnd()}
18668
18698
  -- THINKING GUIDANCE --
18669
18699
  NO EXPLICIT THINKING REQUIRED. FOCUS ON TASK COMPLETION
18670
18700
  Keep main focus on tools and task, not chatting
18671
- On task completion, provide a detailed structured summary preferebly in Tables/Bullet Points with file modified info, if any task failed report back in detail, no hallucination
18701
+ On task completion, provide a detailed structured summary preferebly in Tables/Bullet Points with file modified info, if any task failed report back in detail, NO HALLUCINATIONS
18672
18702
 
18673
18703
  CWD: ${process.cwd()}
18674
18704
  Current Time: ${time}
@@ -19941,7 +19971,17 @@ function App({ args = [] }) {
19941
19971
  const forceRender = () => setRenderTick((t) => t + 1);
19942
19972
  const typewriterQueueRef = useRef4([]);
19943
19973
  const typewriterTickRef = useRef4(null);
19974
+ const flushTypewriterNow = () => {
19975
+ const queue = typewriterQueueRef.current;
19976
+ if (queue.length > 0 && activeStreamingMsgRef.current) {
19977
+ const remaining = queue.join("");
19978
+ queue.length = 0;
19979
+ activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + remaining);
19980
+ forceRender();
19981
+ }
19982
+ };
19944
19983
  const commitActiveStreamingMessage = () => {
19984
+ flushTypewriterNow();
19945
19985
  if (activeStreamingMsgRef.current) {
19946
19986
  const msg = {
19947
19987
  ...activeStreamingMsgRef.current,
@@ -19964,24 +20004,27 @@ function App({ args = [] }) {
19964
20004
  }
19965
20005
  typewriterQueueRef.current = [];
19966
20006
  typewriterTickRef.current = setInterval(() => {
19967
- const queue = typewriterQueueRef.current;
19968
- if (queue.length > 0 && activeStreamingMsgRef.current) {
19969
- let batchSize = 1;
19970
- if (queue.length > 85) batchSize = 30;
19971
- else if (queue.length > 80) batchSize = 25;
19972
- else if (queue.length > 75) batchSize = 20;
19973
- else if (queue.length > 65) batchSize = 16;
19974
- else if (queue.length > 50) batchSize = 12;
19975
- else if (queue.length > 35) batchSize = 8;
19976
- else if (queue.length > 15) batchSize = 6;
19977
- else if (queue.length > 5) batchSize = 4;
19978
- else if (queue.length > 3) batchSize = 2;
19979
- let batchedText = "";
19980
- for (let i = 0; i < batchSize && queue.length > 0; i++) {
19981
- batchedText += queue.shift();
19982
- }
19983
- activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + batchedText);
19984
- forceRender();
20007
+ try {
20008
+ const queue = typewriterQueueRef.current;
20009
+ if (queue.length > 0 && activeStreamingMsgRef.current) {
20010
+ let batchSize = 1;
20011
+ if (queue.length > 85) batchSize = 30;
20012
+ else if (queue.length > 80) batchSize = 25;
20013
+ else if (queue.length > 75) batchSize = 20;
20014
+ else if (queue.length > 65) batchSize = 16;
20015
+ else if (queue.length > 50) batchSize = 12;
20016
+ else if (queue.length > 35) batchSize = 8;
20017
+ else if (queue.length > 15) batchSize = 6;
20018
+ else if (queue.length > 5) batchSize = 4;
20019
+ else if (queue.length > 3) batchSize = 2;
20020
+ let batchedText = "";
20021
+ for (let i = 0; i < batchSize && queue.length > 0; i++) {
20022
+ batchedText += queue.shift();
20023
+ }
20024
+ activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + batchedText);
20025
+ forceRender();
20026
+ }
20027
+ } catch (e) {
19985
20028
  }
19986
20029
  }, 80);
19987
20030
  };
@@ -19990,15 +20033,6 @@ function App({ args = [] }) {
19990
20033
  await new Promise((resolve) => setTimeout(resolve, 10));
19991
20034
  }
19992
20035
  };
19993
- const flushTypewriterNow = () => {
19994
- const queue = typewriterQueueRef.current;
19995
- if (queue.length > 0 && activeStreamingMsgRef.current) {
19996
- const remaining = queue.join("");
19997
- queue.length = 0;
19998
- activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + remaining);
19999
- forceRender();
20000
- }
20001
- };
20002
20036
  const appendStreamText = (chunkText) => {
20003
20037
  if (systemSettings.progressiveRendering && typewriterTickRef.current) {
20004
20038
  const tokens = chunkText.split(/(\s+)/).filter(Boolean);
@@ -21607,6 +21641,7 @@ ${cleanText}`, color: "magenta" }];
21607
21641
  return;
21608
21642
  }
21609
21643
  if (absoluteClean.startsWith("/")) {
21644
+ setInput("");
21610
21645
  const parts = absoluteClean.split(" ");
21611
21646
  const cmd = parts[0]?.toLowerCase();
21612
21647
  switch (cmd) {
@@ -23055,10 +23090,10 @@ Selection: ${val}`,
23055
23090
  if (inThinkMode && activeStreamingMsgRef.current?.role === "think") {
23056
23091
  flushTypewriterNow();
23057
23092
  const newText = activeStreamingMsgRef.current.text + chunkText;
23058
- if (newText.toLowerCase().includes("</think>")) {
23059
- const parts = newText.split(/<\/think>/gi);
23093
+ if (/<\/(think|thought)>/i.test(newText)) {
23094
+ const parts = newText.split(/<\/(think|thought)>/gi);
23060
23095
  const thinkPart = parts[0] || "";
23061
- const agentPart = parts.slice(1).join("</think>") || "";
23096
+ const agentPart = parts.slice(2).join("").replace(/<\/?(think|thought)>/gi, "");
23062
23097
  activeStreamingMsgRef.current.text = flattenString(thinkPart);
23063
23098
  const startTime = activeStreamingMsgRef.current.startTime || Date.now();
23064
23099
  activeStreamingMsgRef.current.duration = Date.now() - startTime;
@@ -23066,7 +23101,7 @@ Selection: ${val}`,
23066
23101
  inThinkMode = false;
23067
23102
  currentAgentId = "agent-" + Date.now();
23068
23103
  activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text: "", isStreaming: true };
23069
- appendStreamText(agentPart.replace(/<\/?(think|thought)>/gi, ""));
23104
+ appendStreamText(agentPart);
23070
23105
  } else {
23071
23106
  appendStreamText(chunkText);
23072
23107
  }
@@ -23159,6 +23194,19 @@ Selection: ${val}`,
23159
23194
  }
23160
23195
  return updated;
23161
23196
  }).reverse();
23197
+ const hasAgentMsg = newMsgs.some((m) => m.role === "agent" && m.text?.trim().length > 0);
23198
+ if (!hasAgentMsg) {
23199
+ const lastThinkMsg = [...newMsgs].reverse().find((m) => m.role === "think" && m.text?.trim().length > 0);
23200
+ if (lastThinkMsg) {
23201
+ newMsgs.push({
23202
+ id: "agent-fallback-" + Date.now(),
23203
+ role: "agent",
23204
+ text: lastThinkMsg.text,
23205
+ isStreaming: false,
23206
+ workedDuration: totalDuration2
23207
+ });
23208
+ }
23209
+ }
23162
23210
  const historyToSave = newMsgs.filter((m) => !String(m.id).startsWith("welcome") && (!m.isMeta || m.text && m.text.includes("Request Cancelled")));
23163
23211
  saveChat(chatId, null, historyToSave);
23164
23212
  setCompletedIndex(newMsgs.length);
package/model_config.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "version": 0,
3
- "release": 20260803,
3
+ "release": 20260804,
4
4
  "fallbacks": {
5
5
  "janitor_default": "gemini-3.1-flash-lite",
6
6
  "janitor_attempts_fallback": "gemma-4-26b-a4b-it",
7
7
  "janitor_open_router": "google/gemma-4-26b-a4b-it:free",
8
8
  "general_fallback": "gemini-3.1-flash-lite",
9
- "deepseek_fast_fallback": "deepseek-chat",
9
+ "deepseek_fast_fallback": "deepseek-v4-flash",
10
10
  "deepseek_level_1": "deepseek-v4-flash",
11
11
  "deepseek_level_2": "deepseek-v4-pro",
12
12
  "mistral_janitor_fallback": "mistral-small-2506",
13
13
  "mistral_level_1": "mistral-medium-2505",
14
14
  "nvidia_janitor_fallback": "mistralai/mistral-nemotron",
15
- "nvidia_chat_summarizer_fallback": "deepseek-ai/deepseek-v4-flash",
15
+ "nvidia_chat_summarizer_fallback": "google/diffusiongemma-26b-a4b-it",
16
16
  "google_level_1": "gemini-3-flash-preview",
17
17
  "google_level_2": "gemini-3.5-flash",
18
18
  "gemma_emergency": "gemma-4-31b-it",
@@ -93,15 +93,6 @@
93
93
  "default_paid": "deepseek/deepseek-v4-flash",
94
94
  "models": {
95
95
  "Free": [
96
- {
97
- "cmd": "--- Auto Routed ---",
98
- "desc": ""
99
- },
100
- {
101
- "cmd": "openrouter/free",
102
- "multimodal": false,
103
- "desc": "OpenRouter Free (Auto Router)"
104
- },
105
96
  {
106
97
  "cmd": "--- Google Models ---",
107
98
  "desc": ""
@@ -324,8 +315,8 @@
324
315
  }
325
316
  },
326
317
  "NVIDIA": {
327
- "default_free": "deepseek-ai/deepseek-v4-flash",
328
- "default_paid": "deepseek-ai/deepseek-v4-flash",
318
+ "default_free": "stepfun-ai/step-3.7-flash",
319
+ "default_paid": "stepfun-ai/step-3.7-flash",
329
320
  "models": {
330
321
  "Free": [
331
322
  {
@@ -369,11 +360,6 @@
369
360
  "cmd": "\n--- Mistral Models ---",
370
361
  "desc": ""
371
362
  },
372
- {
373
- "cmd": "mistralai/mistral-medium-3.5-128b",
374
- "multimodal": true,
375
- "desc": "Multimodal"
376
- },
377
363
  {
378
364
  "cmd": "mistralai/mistral-large-3-675b-instruct-2512",
379
365
  "multimodal": true,
@@ -406,30 +392,11 @@
406
392
  "cmd": "\n--- MiniMax Models ---",
407
393
  "desc": ""
408
394
  },
409
- {
410
- "cmd": "minimaxai/minimax-m2.7",
411
- "multimodal": false,
412
- "desc": "Text Only"
413
- },
414
395
  {
415
396
  "cmd": "minimaxai/minimax-m3",
416
397
  "multimodal": false,
417
398
  "desc": "Text Only"
418
399
  },
419
- {
420
- "cmd": "\n--- Qwen Models ---",
421
- "desc": ""
422
- },
423
- {
424
- "cmd": "qwen/qwen3.5-397b-a17b",
425
- "multimodal": true,
426
- "desc": "Multimodal"
427
- },
428
- {
429
- "cmd": "qwen/qwen3.5-122b-a10b",
430
- "multimodal": true,
431
- "desc": "Multimodal"
432
- },
433
400
  {
434
401
  "cmd": "\n--- NVIDIA Models ---",
435
402
  "desc": ""
@@ -457,6 +424,15 @@
457
424
  "cmd": "meta/llama-3.2-90b-vision-instruct",
458
425
  "multimodal": true,
459
426
  "desc": "Multimodal"
427
+ },
428
+ {
429
+ "cmd": "\n--- Thinking Machines Models ---",
430
+ "desc": ""
431
+ },
432
+ {
433
+ "cmd": "thinkingmachines/inkling",
434
+ "multimodal": false,
435
+ "desc": "Text Only [EXPERIMENTAL]"
460
436
  }
461
437
  ],
462
438
  "Paid": [
@@ -501,11 +477,6 @@
501
477
  "cmd": "\n--- Mistral Models ---",
502
478
  "desc": ""
503
479
  },
504
- {
505
- "cmd": "mistralai/mistral-medium-3.5-128b",
506
- "multimodal": true,
507
- "desc": "Multimodal"
508
- },
509
480
  {
510
481
  "cmd": "mistralai/mistral-large-3-675b-instruct-2512",
511
482
  "multimodal": true,
@@ -538,30 +509,11 @@
538
509
  "cmd": "\n--- MiniMax Models ---",
539
510
  "desc": ""
540
511
  },
541
- {
542
- "cmd": "minimaxai/minimax-m2.7",
543
- "multimodal": false,
544
- "desc": "Text Only"
545
- },
546
512
  {
547
513
  "cmd": "minimaxai/minimax-m3",
548
514
  "multimodal": false,
549
515
  "desc": "Text Only"
550
516
  },
551
- {
552
- "cmd": "\n--- Qwen Models ---",
553
- "desc": ""
554
- },
555
- {
556
- "cmd": "qwen/qwen3.5-397b-a17b",
557
- "multimodal": true,
558
- "desc": "Multimodal"
559
- },
560
- {
561
- "cmd": "qwen/qwen3.5-122b-a10b",
562
- "multimodal": true,
563
- "desc": "Multimodal"
564
- },
565
517
  {
566
518
  "cmd": "\n--- NVIDIA Models ---",
567
519
  "desc": ""
@@ -589,6 +541,15 @@
589
541
  "cmd": "meta/llama-3.2-90b-vision-instruct",
590
542
  "multimodal": true,
591
543
  "desc": "Multimodal"
544
+ },
545
+ {
546
+ "cmd": "\n--- Thinking Machines Models ---",
547
+ "desc": ""
548
+ },
549
+ {
550
+ "cmd": "thinkingmachines/inkling",
551
+ "multimodal": false,
552
+ "desc": "Text Only [EXPERIMENTAL]"
592
553
  }
593
554
  ]
594
555
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "3.18.0",
4
- "date": "2026-08-04",
3
+ "version": "3.18.2",
4
+ "date": "2026-08-05",
5
5
  "description": "A High-Fidelity Agentic CLI with Sub-Agents for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",