fluxflow-cli 1.8.10 → 1.8.12

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 +193 -22
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -1301,7 +1301,7 @@ var init_web_search = __esm({
1301
1301
  const jitter = attempt === 1 ? Math.random() * 1e3 + 500 : Math.random() * 2e3 + 1e3;
1302
1302
  await new Promise((r) => setTimeout(r, jitter));
1303
1303
  const searchUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
1304
- await page.goto(searchUrl, { waitUntil: "networkidle2" });
1304
+ await page.goto(searchUrl, { waitUntil: "networkidle2", timeout: 18e4 });
1305
1305
  const results = await page.$$eval(".result", (elements, maxLimit) => {
1306
1306
  return elements.slice(0, maxLimit).map((el, i) => {
1307
1307
  const titleEl = el.querySelector(".result__a");
@@ -1384,7 +1384,7 @@ var init_web_scrape = __esm({
1384
1384
  await page.setViewport({ width: 1366, height: 768 });
1385
1385
  const jitter = attempt === 1 ? Math.random() * 1e3 + 500 : Math.random() * 2e3 + 1e3;
1386
1386
  await new Promise((r) => setTimeout(r, jitter));
1387
- await page.goto(url, { waitUntil: "networkidle2", timeout: 45e3 });
1387
+ await page.goto(url, { waitUntil: "networkidle2", timeout: 18e4 });
1388
1388
  await new Promise((r) => setTimeout(r, 5e3));
1389
1389
  let htmlContent = await page.evaluate(() => {
1390
1390
  const junk = document.querySelectorAll("script, style, nav, footer, header, noscript, svg, canvas, iframe, ad, .ads, link, meta, img");
@@ -2150,7 +2150,7 @@ var init_write_pdf = __esm({
2150
2150
  <div class="watermark">Generated by FluxFlow CLI (AI)</div>
2151
2151
  ${content}
2152
2152
  `;
2153
- await page.setContent(styledContent, { waitUntil: "networkidle0" });
2153
+ await page.setContent(styledContent, { waitUntil: "networkidle0", timeout: 18e4 });
2154
2154
  const pdfBytes = await page.pdf({
2155
2155
  format: "A4",
2156
2156
  landscape: orientation.toLowerCase() === "landscape",
@@ -2430,7 +2430,7 @@ var init_terminal = __esm({
2430
2430
  import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
2431
2431
  import path16 from "path";
2432
2432
  import fs16 from "fs";
2433
- var client, TERMINATION_SIGNAL, signalTermination, detectToolCalls, initAI, getAIStream;
2433
+ var client, TERMINATION_SIGNAL, signalTermination, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, getAIStream;
2434
2434
  var init_ai = __esm({
2435
2435
  "src/utils/ai.js"() {
2436
2436
  init_prompts();
@@ -2446,6 +2446,138 @@ var init_ai = __esm({
2446
2446
  signalTermination = () => {
2447
2447
  TERMINATION_SIGNAL = true;
2448
2448
  };
2449
+ getActiveToolContext = (text) => {
2450
+ const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
2451
+ let match;
2452
+ while ((match = toolRegex.exec(text)) !== null) {
2453
+ const startIdx = match.index + match[0].length - 1;
2454
+ let balance = 0;
2455
+ let inString = null;
2456
+ let isEscaped = false;
2457
+ let closed = false;
2458
+ for (let i = startIdx; i < text.length; i++) {
2459
+ const char = text[i];
2460
+ if (!inString && (char === '"' || char === "'" || char === "`")) {
2461
+ inString = char;
2462
+ isEscaped = false;
2463
+ } else if (inString && char === inString && !isEscaped) {
2464
+ inString = null;
2465
+ }
2466
+ if (!inString) {
2467
+ if (char === "(") balance++;
2468
+ else if (char === ")") balance--;
2469
+ if (balance === 0) {
2470
+ closed = true;
2471
+ toolRegex.lastIndex = i + 1;
2472
+ break;
2473
+ }
2474
+ }
2475
+ if (char === "\\") isEscaped = !isEscaped;
2476
+ else isEscaped = false;
2477
+ }
2478
+ if (!closed) {
2479
+ return { inside: true, toolName: match[1], startIndex: match.index };
2480
+ }
2481
+ }
2482
+ return { inside: false };
2483
+ };
2484
+ getContextSafeText = (text, stripThoughts = true) => {
2485
+ const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
2486
+ let result = "";
2487
+ let lastIdx = 0;
2488
+ let match;
2489
+ while ((match = toolRegex.exec(text)) !== null) {
2490
+ const before = text.substring(lastIdx, match.index);
2491
+ result += stripThoughts ? before.replace(/<think>[\s\S]*?(?:<\/think>|$)/gi, "") : before;
2492
+ const startIdx = match.index + match[0].length - 1;
2493
+ let balance = 0;
2494
+ let inString = null;
2495
+ let isEscaped = false;
2496
+ let endIdx = -1;
2497
+ for (let i = startIdx; i < text.length; i++) {
2498
+ const char = text[i];
2499
+ if (!inString && (char === '"' || char === "'" || char === "`")) {
2500
+ inString = char;
2501
+ isEscaped = false;
2502
+ } else if (inString && char === inString && !isEscaped) {
2503
+ inString = null;
2504
+ }
2505
+ if (!inString) {
2506
+ if (char === "(") balance++;
2507
+ else if (char === ")") balance--;
2508
+ if (balance === 0) {
2509
+ endIdx = i;
2510
+ break;
2511
+ }
2512
+ }
2513
+ if (char === "\\") isEscaped = !isEscaped;
2514
+ else isEscaped = false;
2515
+ }
2516
+ if (endIdx !== -1) {
2517
+ result += "tool:functions." + match[1] + "()";
2518
+ lastIdx = endIdx + 1;
2519
+ toolRegex.lastIndex = lastIdx;
2520
+ } else {
2521
+ result += "tool:functions." + match[1] + "(";
2522
+ lastIdx = text.length;
2523
+ break;
2524
+ }
2525
+ }
2526
+ if (lastIdx < text.length) {
2527
+ result += stripThoughts ? text.substring(lastIdx).replace(/<think>[\s\S]*?(?:<\/think>|$)/gi, "") : text.substring(lastIdx);
2528
+ }
2529
+ return result;
2530
+ };
2531
+ contextSafeReplace = (text, regex, replacement) => {
2532
+ const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
2533
+ let result = "";
2534
+ let lastIdx = 0;
2535
+ let match;
2536
+ while ((match = toolRegex.exec(text)) !== null) {
2537
+ const before = text.substring(lastIdx, match.index);
2538
+ result += before.replace(regex, replacement);
2539
+ const startIdx = match.index + match[0].length - 1;
2540
+ let balance = 0;
2541
+ let inString = null;
2542
+ let isEscaped = false;
2543
+ let endIdx = -1;
2544
+ for (let i = startIdx; i < text.length; i++) {
2545
+ const char = text[i];
2546
+ if (!inString && (char === '"' || char === "'" || char === "`")) {
2547
+ inString = char;
2548
+ isEscaped = false;
2549
+ } else if (inString && char === inString && !isEscaped) {
2550
+ inString = null;
2551
+ }
2552
+ if (!inString) {
2553
+ if (char === "(") balance++;
2554
+ else if (char === ")") balance--;
2555
+ if (balance === 0) {
2556
+ endIdx = i;
2557
+ break;
2558
+ }
2559
+ }
2560
+ if (char === "\\") isEscaped = !isEscaped;
2561
+ else isEscaped = false;
2562
+ }
2563
+ if (endIdx !== -1) {
2564
+ result += text.substring(match.index, endIdx + 1);
2565
+ lastIdx = endIdx + 1;
2566
+ toolRegex.lastIndex = lastIdx;
2567
+ } else {
2568
+ result += text.substring(match.index);
2569
+ lastIdx = text.length;
2570
+ break;
2571
+ }
2572
+ }
2573
+ if (lastIdx < text.length) {
2574
+ result += text.substring(lastIdx).replace(regex, replacement);
2575
+ }
2576
+ return result;
2577
+ };
2578
+ getSanitizedText = (text) => {
2579
+ return getContextSafeText(text, true);
2580
+ };
2449
2581
  detectToolCalls = (text) => {
2450
2582
  const results = [];
2451
2583
  const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
@@ -2565,6 +2697,7 @@ var init_ai = __esm({
2565
2697
  try {
2566
2698
  if (isInitialAttempt) {
2567
2699
  yield { type: "turn_reset", content: true };
2700
+ yield { type: "spinner", content: true };
2568
2701
  isInitialAttempt = false;
2569
2702
  accumulatedContext = "";
2570
2703
  }
@@ -2661,32 +2794,63 @@ var init_ai = __esm({
2661
2794
  turnText += chunk.text;
2662
2795
  yield { type: "text", content: chunk.text };
2663
2796
  }
2664
- const actionableText = turnText.replace(/<think>[\s\S]*?(?:<\/think>|$)/gi, "");
2665
- if (actionableText.includes("tool:functions.")) {
2797
+ const signalSafeText2 = getSanitizedText(turnText);
2798
+ const toolContext = getActiveToolContext(turnText);
2799
+ if (toolContext.inside) {
2666
2800
  if (!lastToolEventTime) lastToolEventTime = Date.now();
2667
- const parts = actionableText.split("tool:functions.");
2668
- const potentialTool = parts[parts.length - 1].split("(")[0].trim();
2801
+ const potentialTool = toolContext.toolName;
2669
2802
  if (potentialTool && /^[a-z_]+$/.test(potentialTool) && potentialTool !== lastToolSniffed) {
2670
2803
  lastToolSniffed = potentialTool;
2671
2804
  yield { type: "status", content: `Working (${potentialTool})...` };
2672
2805
  }
2673
2806
  }
2674
- const thinkBlocks = turnText.match(/<think>([\s\S]*?)(?:<\/think>|$)/gi) || [];
2807
+ const contextSafeText = getContextSafeText(turnText, false);
2808
+ const thinkBlocks = contextSafeText.match(/<think>([\s\S]*?)(?:<\/think>|$)/gi) || [];
2675
2809
  const thinkContent = thinkBlocks.join("").trim();
2676
2810
  const sentences = thinkContent.split(/[.!?]\s+/);
2677
2811
  const uniqueSentences = new Set(sentences);
2678
2812
  const repetitionRatio = sentences.length > 10 ? (sentences.length - uniqueSentences.size) / sentences.length : 0;
2679
2813
  const wordCount = thinkContent.split(/\s+/).filter((w) => w.length > 0).length;
2680
- let repetitionThreshold = 0.4;
2681
- let isOverVerbose = wordCount > 2500;
2682
- if (repetitionRatio > repetitionThreshold || isOverVerbose) {
2683
- const reason = repetitionRatio > repetitionThreshold ? "Thinking Loop Detected" : "Rambling Detected";
2814
+ let repetitionThresholdThinking = 0.4;
2815
+ let repetitionThresholdResponse = 0.6;
2816
+ let isOverVerboseThinking = wordCount > 2500;
2817
+ if (repetitionRatio > repetitionThresholdThinking || isOverVerboseThinking) {
2818
+ const reason = repetitionRatio > repetitionThresholdThinking ? "Thinking Loop Detected" : "Rambling Detected";
2684
2819
  yield { type: "status", content: `${reason}. Re-centering...` };
2685
2820
  isThinkingLoop = true;
2686
2821
  await new Promise((resolve) => setTimeout(resolve, 3e3));
2687
2822
  break;
2688
2823
  }
2689
- const allToolsFound = detectToolCalls(actionableText);
2824
+ const responseContent = signalSafeText2.trim();
2825
+ const respSentences = responseContent.split(/[.!?]\s+/);
2826
+ const uniqueRespSentences = new Set(respSentences);
2827
+ const respRepetitionRatio = respSentences.length > 10 ? (respSentences.length - uniqueRespSentences.size) / respSentences.length : 0;
2828
+ if (respRepetitionRatio > repetitionThresholdResponse) {
2829
+ yield { type: "status", content: `Response Loop Detected. Re-centering...` };
2830
+ isThinkingLoop = false;
2831
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
2832
+ break;
2833
+ }
2834
+ const allWords = contextSafeText.split(/\s+/).filter((w) => w.length > 0);
2835
+ if (allWords.length > 12) {
2836
+ let stutterDetected = false;
2837
+ for (let i = 0; i < allWords.length - 10; i++) {
2838
+ const sub = allWords.slice(i, i + 5).join(" ");
2839
+ const next = allWords.slice(i + 5, i + 10).join(" ");
2840
+ if (sub === next) {
2841
+ stutterDetected = true;
2842
+ break;
2843
+ }
2844
+ }
2845
+ if (stutterDetected) {
2846
+ yield { type: "status", content: `Stuttering Detected. Re-centering...` };
2847
+ isThinkingLoop = false;
2848
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
2849
+ break;
2850
+ }
2851
+ }
2852
+ const toolActionableText = turnText.replace(/<think>[\s\S]*?(?:<\/think>|$)/gi, "");
2853
+ const allToolsFound = detectToolCalls(toolActionableText);
2690
2854
  while (allToolsFound.length > toolCallPointer) {
2691
2855
  const toolCall = allToolsFound[toolCallPointer];
2692
2856
  yield { type: "status", content: `Working (${toolCall.toolName})...` };
@@ -2809,12 +2973,14 @@ ${boxBottom}
2809
2973
  }
2810
2974
  }
2811
2975
  const effectiveStart = lastToolEventTime || Date.now();
2976
+ yield { type: "spinner", content: false };
2812
2977
  let result = await dispatchTool(toolCall.toolName, toolCall.args, {
2813
2978
  chatId,
2814
2979
  history,
2815
2980
  onChunk: (chunk2) => settings.onExecChunk ? settings.onExecChunk(chunk2) : null,
2816
2981
  onAskUser: settings.onAskUser
2817
2982
  });
2983
+ yield { type: "spinner", content: true };
2818
2984
  const toolEnd = Date.now();
2819
2985
  yield { type: "tool_time", content: toolEnd - effectiveStart };
2820
2986
  lastToolEventTime = toolEnd;
@@ -2893,11 +3059,11 @@ ${boxBottom}
2893
3059
  if (thinkMatch) {
2894
3060
  textToProcess = turnText.replace(/<think>[\s\S]*?<\/think>/i, "");
2895
3061
  }
2896
- const finalActionableText = turnText.replace(/<think>[\s\S]*?(?:<\/think>|$)/gi, "");
2897
- const hasFinish = /\[\s*(turn\s*:)?\s*finish\s*\]/i.test(finalActionableText.toLowerCase());
3062
+ const signalSafeText = getSanitizedText(turnText);
3063
+ const hasFinish = /\[\s*(turn\s*:)?\s*finish\s*\]/i.test(signalSafeText.toLowerCase());
2898
3064
  const shouldContinue = toolCallPointer > 0;
2899
3065
  yield { type: "status", content: "Working..." };
2900
- const cleanedTurnText = turnText.replace(/\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").trim();
3066
+ const cleanedTurnText = contextSafeReplace(turnText, /\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").trim();
2901
3067
  let isActuallyFinished = hasFinish && !shouldContinue;
2902
3068
  if (isActuallyFinished) {
2903
3069
  yield { type: "status", content: "Finalizing..." };
@@ -3434,6 +3600,7 @@ Check what's new using \`/changelog\` command.`,
3434
3600
  return formatDuration(Math.floor(ms / 1e3));
3435
3601
  };
3436
3602
  const [statusText, setStatusText] = useState7(null);
3603
+ const [isSpinnerActive, setIsSpinnerActive] = useState7(true);
3437
3604
  const [isProcessing, setIsProcessing] = useState7(false);
3438
3605
  const [escPressed, setEscPressed] = useState7(false);
3439
3606
  const [escTimer, setEscTimer] = useState7(null);
@@ -4108,6 +4275,10 @@ Selection: ${val}`,
4108
4275
  setStatusText(packet.content);
4109
4276
  continue;
4110
4277
  }
4278
+ if (packet.type === "spinner") {
4279
+ setIsSpinnerActive(packet.content);
4280
+ continue;
4281
+ }
4111
4282
  if (packet.type === "model_update") {
4112
4283
  setTempModelOverride(packet.content);
4113
4284
  continue;
@@ -4693,7 +4864,7 @@ Selection: ${val}`,
4693
4864
  }
4694
4865
  ));
4695
4866
  case "approval":
4696
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true, underline: true }, "\u{1F6E1}\uFE0F SECURITY GATE: FILE WRITE PERMISSION"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "The agent is attempting to modify: ", /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, parseArgs(pendingApproval?.args || "{}").path || "Unknown File")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, borderStyle: "single", borderColor: "#333", paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray" }, "--- PROPOSED CONTENT / DIFF ---"), (() => {
4867
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true, underline: true }, "\u{1F510} SECURITY GATE: FILE WRITE PERMISSION"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "The agent is attempting to modify: ", /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, parseArgs(pendingApproval?.args || "{}").path || "Unknown File")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, borderStyle: "single", borderColor: "#333", paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray" }, "--- PROPOSED CONTENT / DIFF ---"), (() => {
4697
4868
  const args = parseArgs(pendingApproval?.args || "{}");
4698
4869
  const oldVal = args.TargetContent || args.content_to_replace || null;
4699
4870
  const newVal = args.content || args.ReplacementContent || args.content_to_add || args.replacementContent || null;
@@ -4707,7 +4878,7 @@ Selection: ${val}`,
4707
4878
  title: "Action Required",
4708
4879
  items: [
4709
4880
  { label: "\u2705 Accept this time", value: "allow" },
4710
- { label: "\u{1F6E1}\uFE0F Accept for this session", value: "always" },
4881
+ { label: "\u{1F510} Accept for this session", value: "always" },
4711
4882
  { label: "\u274C Don't accept", value: "deny" }
4712
4883
  ],
4713
4884
  onSelect: (item) => {
@@ -4783,7 +4954,7 @@ Selection: ${val}`,
4783
4954
  }
4784
4955
  );
4785
4956
  case "terminalApproval":
4786
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true, underline: true }, "\u{1F6E1}\uFE0F SECURITY GATE: TERMINAL COMMAND OVERSIGHT"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, null, "Agent requested to run: ", /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true }, parseArgs(pendingApproval?.args || "{}").command || "Unknown Command"))), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
4957
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true, underline: true }, "\u{1F510} SECURITY GATE: TERMINAL COMMAND OVERSIGHT"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, null, "Agent requested to run: ", /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true }, parseArgs(pendingApproval?.args || "{}").command || "Unknown Command"))), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
4787
4958
  CommandMenu,
4788
4959
  {
4789
4960
  title: "Risk Assessment Required",
@@ -4799,7 +4970,7 @@ Selection: ${val}`,
4799
4970
  }
4800
4971
  )));
4801
4972
  default:
4802
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, null, statusText && /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, /* @__PURE__ */ React10.createElement(Spinner2, { type: "dots" })), /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", italic: true }, " ", statusText))), /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true }, "(", tempModelOverride || activeModel, ")")), suggestions.length > 0 && /* @__PURE__ */ React10.createElement(Box10, { paddingY: 0 }), /* @__PURE__ */ React10.createElement(Box10, { backgroundColor: "#333333", paddingX: 1, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%" }, maxLines > 2 && !isExpanded ? /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "row", width: "100%", paddingY: 0, height: 1, overflow: "hidden" }, /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0, width: 3 }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u276F ")), /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1, flexDirection: "row" }, /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true }, "[Pasted ", maxLines, " Lines]")), /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React10.createElement(
4973
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, null, statusText && /* @__PURE__ */ React10.createElement(Box10, null, isSpinnerActive && /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, /* @__PURE__ */ React10.createElement(Spinner2, { type: "dots" })), /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", italic: true }, isSpinnerActive ? " " : "", statusText))), /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true }, "(", tempModelOverride || activeModel, ")")), suggestions.length > 0 && /* @__PURE__ */ React10.createElement(Box10, { paddingY: 0 }), /* @__PURE__ */ React10.createElement(Box10, { backgroundColor: "#333333", paddingX: 1, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%" }, maxLines > 2 && !isExpanded ? /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "row", width: "100%", paddingY: 0, height: 1, overflow: "hidden" }, /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0, width: 3 }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u276F ")), /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1, flexDirection: "row" }, /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true }, "[Pasted ", maxLines, " Lines]")), /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React10.createElement(
4803
4974
  MultilineInput,
4804
4975
  {
4805
4976
  value: "",
@@ -4921,7 +5092,7 @@ var init_app = __esm({
4921
5092
  init_text();
4922
5093
  SESSION_START_TIME = Date.now();
4923
5094
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
4924
- versionFluxflow = "1.8.10";
5095
+ versionFluxflow = "1.8.12";
4925
5096
  updatedOn = "2026-05-09";
4926
5097
  ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "The agent already finished the task before your hint was consumed."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, backgroundColor: "#222", paddingX: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
4927
5098
  CommandMenu,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.8.10",
3
+ "version": "1.8.12",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",