fluxflow-cli 2.9.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/fluxflow.js +212 -26
  2. package/package.json +2 -2
package/dist/fluxflow.js CHANGED
@@ -1586,7 +1586,7 @@ var init_ChatLayout = __esm({
1586
1586
  }
1587
1587
  }
1588
1588
  }
1589
- return result.replace(/\[SYSTEM\][\s\S]*?\[\/SYSTEM\]/gi, "").replace(/\[TOOL RESULT\]:?\s*/gi, "").split("\n").filter((line) => !line.trim().startsWith("SUCCESS:") && !line.trim().startsWith("ERROR:")).join("\n").replace(/\[\s*turn\s*:\s*(continue|finish)\s*\]/gi, "").replace(/\[\[END\]\]/gi, "").replace(/\[\s*turn\s*:?.*?$/gi, "").replace(/\n\s*turn\s*:?.*?$/gi, "").replace(/\[\s*$/gi, "").replace(/\n\nResponded on .*/g, "").replace(/\n\n\[Prompted on: .*\]/g, "").replace(/(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)/gi, "\u2192").replace(/(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)/gi, "\u2190").replace(/(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)/gi, "\u2191").replace(/(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)/gi, "\u2193").replace(/(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi, "\u2194").replace(/@\[TerminalName:.*?, ProcessId:.*?\]/gi, "").replace(/\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, (match) => TOOL_LABELS[match.toLowerCase()] || match).trim();
1589
+ return result.replaceAll(/\[SYSTEM\][\s\S]*?\[\/SYSTEM\]/gi, "").replaceAll(/<(think|thought)>[\s\S]*?(?:<\/(think|thought)>|$)/gi, "").replace(/\[ANSWER\][\s\S]*?(?:\[\/ANSWER\]|$)/gi, "").replaceAll(/\[TOOL RESULT\]:?\s*/gi, "").split("\n").filter((line) => !line.trim().startsWith("SUCCESS:") && !line.trim().startsWith("ERROR:")).join("\n").replaceAll(/\[\s*turn\s*:\s*(continue|finish)\s*\]/gi, "").replaceAll(/\[\[END\]\]/gi, "").replaceAll(/\[\s*turn\s*:?.*?$/gi, "").replaceAll(/\n\s*turn\s*:?.*?$/gi, "").replaceAll(/\[\s*$/gi, "").replaceAll(/\n\nResponded on .*/g, "").replaceAll(/\n\n\[Prompted on: .*\]/g, "").replaceAll(/(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)/gi, "\u2192").replaceAll(/(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)/gi, "\u2190").replaceAll(/(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)/gi, "\u2191").replaceAll(/(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)/gi, "\u2193").replaceAll(/(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi, "\u2194").replaceAll(/@\[TerminalName:.*?, ProcessId:.*?\]/gi, "").replaceAll(/\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, (match) => TOOL_LABELS[match.toLowerCase()] || match).trim();
1590
1590
  };
1591
1591
  formatThinkText = (cleaned, columns = 80) => {
1592
1592
  if (!cleaned) return null;
@@ -1896,6 +1896,7 @@ var init_ChatLayout = __esm({
1896
1896
  { cmd: "/save", desc: "Force save current chat" },
1897
1897
  { cmd: "/export", desc: "Export current chat in a .txt file" },
1898
1898
  { cmd: "/chats", desc: "List all chat sessions" },
1899
+ { cmd: "/btw", desc: "Send raw inquiry mid-turn" },
1899
1900
  { cmd: "/image", desc: "Generate images" },
1900
1901
  { cmd: "/mode", desc: "Toggle Flux/Flow modes" },
1901
1902
  { cmd: "/thinking", desc: "Set AI reasoning depth" },
@@ -2462,6 +2463,7 @@ var init_exec_command = __esm({
2462
2463
  const looksLikePath = (str) => {
2463
2464
  if (!str.includes("/")) return false;
2464
2465
  if (/^(https?|file|ftp):\/\//i.test(str)) return false;
2466
+ if (str.startsWith("@")) return false;
2465
2467
  if (str.startsWith("/") && (str.match(/\//g) || []).length === 1) {
2466
2468
  return false;
2467
2469
  }
@@ -3448,8 +3450,7 @@ ${projectContextBlock}
3448
3450
 
3449
3451
  -- FORMATTING --
3450
3452
  - GFM Supported
3451
- - NO CHAT RESPONSE **AFTER** CALLING TOOLS IN SAME TURN
3452
- - ONE THINKING BLOCK PER TURN
3453
+ - NO CHAT **AFTER** FIRING TOOLS IN THIS TURN
3453
3454
  - Basic LaTeX${mode === "Flux" ? "" : ". Kaomojis"}
3454
3455
  === END SYSTEM PROMPT ===`.trim();
3455
3456
  };
@@ -8187,14 +8188,25 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
8187
8188
  if (steeringCallback) {
8188
8189
  const hint = await steeringCallback();
8189
8190
  if (hint) {
8190
- if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "user") {
8191
- modifiedHistory[modifiedHistory.length - 1].text += `
8191
+ if (hint.startsWith("/btw")) {
8192
+ if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "user") {
8193
+ modifiedHistory[modifiedHistory.length - 1].text += `
8192
8194
 
8193
- [STEERING HINT]: ${hint}`;
8195
+ [SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY [/SYSTEM]
8196
+ [QUESTION] ${hint.replace("/btw", "").trim()} [/QUESTION]`;
8197
+ } else {
8198
+ 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]` });
8199
+ }
8194
8200
  } else {
8195
- 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}` });
8201
+ if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "user") {
8202
+ modifiedHistory[modifiedHistory.length - 1].text += `
8203
+
8204
+ [STEERING HINT] ${hint.trim()} [/STEERING HINT]`;
8205
+ } else {
8206
+ 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]` });
8207
+ }
8196
8208
  }
8197
- yield { type: "status", content: "Steering Hint Injected." };
8209
+ yield { type: "status", content: `${hint.startsWith("/btw") ? "Question Forwarded..." : "Steering Hint Injected..."}` };
8198
8210
  }
8199
8211
  }
8200
8212
  let stream;
@@ -8320,13 +8332,15 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
8320
8332
  currentSystemInstruction = getSystemInstruction(profile, !(targetModel || "gemma").toLowerCase().startsWith("gemma") ? "GEM" : thinkingLevel, mode, systemSettings, isMemoryEnabled, isFirstPrompt, aiProvider, isMultiModal);
8321
8333
  const lastUserMsg = contents[contents.length - 1];
8322
8334
  if (isBridgeConnected()) {
8323
- await new Promise((resolve) => setTimeout(resolve, 2e3));
8335
+ yield { type: "status", content: "Checking Code..." };
8336
+ await new Promise((resolve) => setTimeout(resolve, 2500));
8324
8337
  const ideCtxJIT = await getIDEContext();
8325
8338
  const ideErr = ideCtxJIT ? ideCtxJIT.diagnostics : null;
8326
8339
  if (ideErr && lastUserMsg && lastUserMsg.role === "user" && lastUserMsg.parts?.[0]?.text) {
8327
8340
  lastUserMsg.parts[0].text += `
8328
8341
  ${ideErr} [/ERROR]`;
8329
8342
  }
8343
+ yield { type: "status", content: "Working..." };
8330
8344
  }
8331
8345
  const isGemma = modelName && modelName.toLowerCase().startsWith("gemma") && aiProvider === "Google";
8332
8346
  if (isGemma) {
@@ -8885,12 +8899,112 @@ ${ideErr} [/ERROR]`;
8885
8899
  if (command && settings.systemSettings && settings.systemSettings.allowExternalAccess === false) {
8886
8900
  const riskyPatterns = [/[a-zA-Z]:[\\\/]/i, /^\//, /\.\.[\\\/]/, /\/etc\//, /\/var\//, /\/root\//, /\/bin\//, /\/usr\//];
8887
8901
  const currentDrive = path19.resolve(process.cwd()).substring(0, 3).toLowerCase();
8888
- const isViolating = riskyPatterns.some((pattern) => {
8889
- if (pattern.source === "[a-zA-Z]:[\\\\\\/]") {
8890
- const driveMatch = command.match(/[a-zA-Z]:[\\\/]/i);
8891
- return driveMatch && driveMatch[0].toLowerCase() !== currentDrive;
8902
+ const splitCommands = (cmdString) => {
8903
+ const commands = [];
8904
+ let current = "";
8905
+ let inQuote = null;
8906
+ for (let i = 0; i < cmdString.length; i++) {
8907
+ const char = cmdString[i];
8908
+ if (inQuote) {
8909
+ if (char === inQuote) inQuote = null;
8910
+ current += char;
8911
+ } else {
8912
+ if (char === '"' || char === "'") {
8913
+ inQuote = char;
8914
+ current += char;
8915
+ } else if (char === "&" && cmdString[i + 1] === "&" || char === "|" && cmdString[i + 1] === "|") {
8916
+ if (current.trim()) {
8917
+ commands.push(current.trim());
8918
+ current = "";
8919
+ }
8920
+ i++;
8921
+ } else if (char === ";" || char === "|" || char === "&") {
8922
+ if (current.trim()) {
8923
+ commands.push(current.trim());
8924
+ current = "";
8925
+ }
8926
+ } else {
8927
+ current += char;
8928
+ }
8929
+ }
8930
+ }
8931
+ if (current.trim()) {
8932
+ commands.push(current.trim());
8933
+ }
8934
+ return commands;
8935
+ };
8936
+ const tokenizeCommand = (cmd) => {
8937
+ const tokens = [];
8938
+ let current = "";
8939
+ let inQuote = null;
8940
+ for (let i = 0; i < cmd.length; i++) {
8941
+ const char = cmd[i];
8942
+ if (inQuote) {
8943
+ if (char === inQuote) {
8944
+ inQuote = null;
8945
+ current += char;
8946
+ } else {
8947
+ current += char;
8948
+ }
8949
+ } else {
8950
+ if (char === '"' || char === "'") {
8951
+ inQuote = char;
8952
+ current += char;
8953
+ } else if (/\s/.test(char)) {
8954
+ if (current) {
8955
+ tokens.push(current);
8956
+ current = "";
8957
+ }
8958
+ } else {
8959
+ current += char;
8960
+ }
8961
+ }
8962
+ }
8963
+ if (current) {
8964
+ tokens.push(current);
8965
+ }
8966
+ return tokens;
8967
+ };
8968
+ const checkToken = (token) => {
8969
+ const cleanToken = token.replace(/^['"]|['"]$/g, "").trim();
8970
+ if (!cleanToken) return false;
8971
+ if (process.platform === "win32" && /^\/[a-zA-Z0-9?]+$/.test(cleanToken)) {
8972
+ return false;
8973
+ }
8974
+ return riskyPatterns.some((pattern) => {
8975
+ if (pattern.source === "[a-zA-Z]:[\\\\\\/]") {
8976
+ const driveMatch = cleanToken.match(/[a-zA-Z]:[\\\/]/i);
8977
+ return driveMatch && driveMatch[0].toLowerCase() !== currentDrive;
8978
+ }
8979
+ return pattern.test(cleanToken);
8980
+ });
8981
+ };
8982
+ const commandParts = splitCommands(command);
8983
+ const isViolating = commandParts.some((cmdPart) => {
8984
+ const tokens = tokenizeCommand(cmdPart);
8985
+ if (tokens.length === 0) return false;
8986
+ const exe = tokens[0].replace(/^['"]|['"]$/g, "").toLowerCase();
8987
+ const isSafePrint = ["echo", "printf", "write-output"].includes(exe);
8988
+ if (isSafePrint) {
8989
+ let checkNext = false;
8990
+ return tokens.some((token) => {
8991
+ const clean = token.replace(/^['"]|['"]$/g, "");
8992
+ if (clean === ">" || clean === ">>" || clean === "<") {
8993
+ checkNext = true;
8994
+ return false;
8995
+ }
8996
+ if (clean.startsWith(">") || clean.startsWith("<")) {
8997
+ const pathPart = clean.replace(/^[><]+/, "");
8998
+ return checkToken(pathPart);
8999
+ }
9000
+ if (checkNext) {
9001
+ checkNext = false;
9002
+ return checkToken(token);
9003
+ }
9004
+ return false;
9005
+ });
8892
9006
  }
8893
- return pattern.test(command);
9007
+ return tokens.some((token) => checkToken(token));
8894
9008
  });
8895
9009
  if (isViolating) {
8896
9010
  const denyMsg = `Access Denied. Terminal is prohibited from accessing system drives (C://) or external directories while "External Workspace Access" is disabled.`;
@@ -11041,6 +11155,28 @@ function App({ args = [] }) {
11041
11155
  return msgs;
11042
11156
  });
11043
11157
  const queuedPromptRef = useRef3(null);
11158
+ const [btwResponse, setBtwResponse] = useState11("");
11159
+ const [showBtwBox, setShowBtwBox] = useState11(false);
11160
+ const btwResponseRef = useRef3("");
11161
+ const btwClosedRef = useRef3(null);
11162
+ useEffect8(() => {
11163
+ if (messages.length === 0) return;
11164
+ const lastMsg = messages[messages.length - 1];
11165
+ if (lastMsg && (lastMsg.role === "agent" || lastMsg.role === "assistant")) {
11166
+ const text = lastMsg.text || "";
11167
+ const match = text.match(/\[ANSWER\]([\s\S]*?)(?:\[\/ANSWER\]|$)/i);
11168
+ if (match) {
11169
+ const content = match[1].trim();
11170
+ if (content && content !== btwResponseRef.current) {
11171
+ setBtwResponse(content);
11172
+ btwResponseRef.current = content;
11173
+ if (btwClosedRef.current !== lastMsg.id) {
11174
+ setShowBtwBox(true);
11175
+ }
11176
+ }
11177
+ }
11178
+ }
11179
+ }, [messages]);
11044
11180
  const [completedIndex, setCompletedIndex] = useState11(messages.length);
11045
11181
  const windowedHistory = useMemo2(() => {
11046
11182
  const MAX_HISTORY_LINES = 2e3;
@@ -11151,6 +11287,16 @@ function App({ args = [] }) {
11151
11287
  return;
11152
11288
  }
11153
11289
  if (key.escape) {
11290
+ if (showBtwBox) {
11291
+ setShowBtwBox(false);
11292
+ if (messages.length > 0) {
11293
+ const lastMsg = messages[messages.length - 1];
11294
+ if (lastMsg) {
11295
+ btwClosedRef.current = lastMsg.id;
11296
+ }
11297
+ }
11298
+ return;
11299
+ }
11154
11300
  if (suggestions.length > 0 && activeView === "chat") {
11155
11301
  setIsFilePickerDismissed(true);
11156
11302
  return;
@@ -11537,6 +11683,7 @@ function App({ args = [] }) {
11537
11683
  { cmd: "/save", desc: "Force save current chat" },
11538
11684
  { cmd: "/export", desc: "Export current chat in a .txt file" },
11539
11685
  { cmd: "/chats", desc: "List all chat sessions" },
11686
+ { cmd: "/btw", desc: "Ask a question without intefering with ongoing tasks" },
11540
11687
  // {
11541
11688
  // cmd: '/image', desc: 'Generate images using Pollinations', subs: [
11542
11689
  // {
@@ -11833,7 +11980,17 @@ function App({ args = [] }) {
11833
11980
  if (!absoluteClean.trim()) return;
11834
11981
  if (isProcessing) {
11835
11982
  const hintText = absoluteClean.trim();
11836
- if (hintText.startsWith("/")) {
11983
+ if (hintText.startsWith("/btw")) {
11984
+ const question = hintText.replace(/^\/btw\s*/, "").trim();
11985
+ if (question.length <= 3) {
11986
+ setMessages((prev) => {
11987
+ setCompletedIndex(prev.length + 1);
11988
+ return [...prev, { id: "hint-err-" + Date.now(), role: "system", text: "[RESTRICTED] Inquiry question must be more than 3 characters.", isMeta: true }];
11989
+ });
11990
+ setInput("");
11991
+ return;
11992
+ }
11993
+ } else if (hintText.startsWith("/")) {
11837
11994
  setMessages((prev) => {
11838
11995
  setCompletedIndex(prev.length + 1);
11839
11996
  return [...prev, { id: "hint-err-" + Date.now(), role: "system", text: "[RESTRICTED] Steering Hints cannot start with /", isMeta: true }];
@@ -11845,8 +12002,11 @@ function App({ args = [] }) {
11845
12002
  queuedPromptRef.current = hintText;
11846
12003
  setMessages((prev) => {
11847
12004
  setCompletedIndex(prev.length + 1);
11848
- return [...prev, { id: "hint-" + Date.now(), role: "user", text: `[STEERING HINT: QUEUED]
11849
- ${hintText}`, color: "magenta" }];
12005
+ const isBtw = hintText.startsWith("/btw");
12006
+ const cleanText = isBtw ? hintText.replace(/^\/btw\s*/, "") : hintText;
12007
+ const prefix = isBtw ? "[QUESTION: QUEUED]" : "[STEERING HINT: QUEUED]";
12008
+ return [...prev, { id: "hint-" + Date.now(), role: "user", text: `${prefix}
12009
+ ${cleanText}`, color: "magenta" }];
11850
12010
  });
11851
12011
  setInput("");
11852
12012
  return;
@@ -12619,13 +12779,19 @@ Selection: ${val}`,
12619
12779
  setQueuedPrompt(null);
12620
12780
  queuedPromptRef.current = null;
12621
12781
  setMessages((prev) => {
12622
- const index = [...prev].reverse().findIndex((m) => m.text?.includes("[STEERING HINT: QUEUED]"));
12782
+ const index = [...prev].reverse().findIndex((m) => m.text?.includes("[STEERING HINT: QUEUED]") || m.text?.includes("[QUESTION: QUEUED]"));
12623
12783
  if (index !== -1) {
12624
12784
  const actualIndex = prev.length - 1 - index;
12625
12785
  const newMsgs = [...prev];
12786
+ let text = newMsgs[actualIndex].text;
12787
+ if (text.includes("[STEERING HINT: QUEUED]")) {
12788
+ text = text.replace("[STEERING HINT: QUEUED]", "[STEERING HINT: INJECTED]");
12789
+ } else if (text.includes("[QUESTION: QUEUED]")) {
12790
+ text = text.replace("[QUESTION: QUEUED]", "[QUESTION: ASKED]");
12791
+ }
12626
12792
  newMsgs[actualIndex] = {
12627
12793
  ...newMsgs[actualIndex],
12628
- text: newMsgs[actualIndex].text.replace("[STEERING HINT: QUEUED]", "[STEERING HINT: INJECTED]"),
12794
+ text,
12629
12795
  color: "cyan"
12630
12796
  };
12631
12797
  return newMsgs;
@@ -12843,11 +13009,26 @@ Selection: ${val}`,
12843
13009
  const hasThinkTag = chunkLower.includes("<think") || chunkLower.includes("<thought");
12844
13010
  const canThink = !inThinkMode && !inCodeBlock && !inToolCall && !thinkConsumedInTurn;
12845
13011
  if (hasThinkTag && canThink) {
13012
+ const match = chunkText.match(/<(think|thought)/i);
13013
+ const tagIndex = match.index;
13014
+ const beforeText = chunkText.substring(0, tagIndex);
13015
+ const afterText = chunkText.substring(tagIndex);
13016
+ if (beforeText) {
13017
+ if (!currentAgentId) {
13018
+ currentAgentId = "agent-" + Date.now();
13019
+ setMessages((prev) => [...prev, { id: currentAgentId, role: "agent", text: beforeText, isStreaming: true }]);
13020
+ } else {
13021
+ setMessages((prev) => prev.map(
13022
+ (m) => m.id === currentAgentId ? { ...m, text: m.text + beforeText, isStreaming: true } : m
13023
+ ));
13024
+ }
13025
+ }
12846
13026
  inThinkMode = true;
12847
13027
  thinkConsumedInTurn = true;
12848
- chunkText = chunkText.replace(/<(think|thought)>[\s\S]*?<\/(think|thought)>/gi, "").replace(/<(think|thought)>/gi, "");
13028
+ let thinkStartText = afterText.replace(/<(think|thought)>/gi, "");
12849
13029
  currentThinkId = "think-" + Date.now();
12850
- setMessages((prev) => [...prev, { id: currentThinkId, role: "think", text: "", isStreaming: true, startTime: Date.now() }]);
13030
+ setMessages((prev) => [...prev, { id: currentThinkId, role: "think", text: thinkStartText, isStreaming: true, startTime: Date.now() }]);
13031
+ continue;
12851
13032
  }
12852
13033
  if ((chunkLower.includes("</think>") || chunkLower.includes("</thought>")) && currentThinkId) {
12853
13034
  const parts = chunkText.split(/<\/(think|thought)>/gi);
@@ -12932,9 +13113,13 @@ Selection: ${val}`,
12932
13113
  queuedPromptRef.current = null;
12933
13114
  setMessages((prev) => {
12934
13115
  const newMsgs = [...prev];
12935
- const hintMsg = newMsgs.reverse().find((m) => m.text?.includes("[STEERING HINT: QUEUED]"));
13116
+ const hintMsg = newMsgs.reverse().find((m) => m.text?.includes("[STEERING HINT: QUEUED]") || m.text?.includes("[QUESTION: QUEUED]"));
12936
13117
  if (hintMsg) {
12937
- hintMsg.text = hintMsg.text.replace("[STEERING HINT: QUEUED]", "[STEERING HINT: FINISHED_TURN]");
13118
+ if (hintMsg.text.includes("[STEERING HINT: QUEUED]")) {
13119
+ hintMsg.text = hintMsg.text.replace("[STEERING HINT: QUEUED]", "[STEERING HINT: FINISHED_TURN]");
13120
+ } else if (hintMsg.text.includes("[QUESTION: QUEUED]")) {
13121
+ hintMsg.text = hintMsg.text.replace("[QUESTION: QUEUED]", "[QUESTION: FINISHED_TURN]");
13122
+ }
12938
13123
  }
12939
13124
  return newMsgs.reverse();
12940
13125
  });
@@ -13604,7 +13789,7 @@ Selection: ${val}`,
13604
13789
  }
13605
13790
  )));
13606
13791
  default:
13607
- return /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, /* @__PURE__ */ React14.createElement(Box14, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React14.createElement(Box14, null, statusText ? /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Text14, { color: "gray", bold: true, italic: true }, statusText)) : /* @__PURE__ */ React14.createElement(Text14, { color: "gray", italic: true }, input.length > 0 && escPressCount ? "Press ESC again to clear input" : "Waiting for input...")), /* @__PURE__ */ React14.createElement(Box14, null, wittyPhrase && /* @__PURE__ */ React14.createElement(Text14, { color: "gray", italic: true }, wittyPhrase, " "), /* @__PURE__ */ React14.createElement(Text14, { color: "gray", bold: true }, "[ "), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, tempModelOverride || activeModel), /* @__PURE__ */ React14.createElement(Text14, { color: "gray", bold: true }, " ]"))), /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React14.createElement(Box14, { width: "100%", height: 1, overflow: "hidden" }, /* @__PURE__ */ React14.createElement(Text14, { color: "#555555" }, "\u2584".repeat(Math.max(1, terminalSize.columns)))), /* @__PURE__ */ React14.createElement(
13792
+ return /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, showBtwBox && btwResponse && /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 2, paddingY: 1, width: "100%", marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Box14, { justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React14.createElement(Text14, { color: "white", bold: true, underline: true }, "INQUIRY RESPONSE"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, "[ ESC to Close ]")), /* @__PURE__ */ React14.createElement(Box14, { marginTop: 1, width: "100%" }, /* @__PURE__ */ React14.createElement(CodeRenderer, { text: btwResponse, columns: terminalSize.columns - 6 }))), /* @__PURE__ */ React14.createElement(Box14, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React14.createElement(Box14, null, statusText ? /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Text14, { color: "gray", bold: true, italic: true }, statusText)) : /* @__PURE__ */ React14.createElement(Text14, { color: "gray", italic: true }, input.length > 0 && escPressCount ? "Press ESC again to clear input" : "Waiting for input...")), /* @__PURE__ */ React14.createElement(Box14, null, wittyPhrase && /* @__PURE__ */ React14.createElement(Text14, { color: "gray", italic: true }, wittyPhrase, " "), /* @__PURE__ */ React14.createElement(Text14, { color: "gray", bold: true }, "[ "), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, tempModelOverride || activeModel), /* @__PURE__ */ React14.createElement(Text14, { color: "gray", bold: true }, " ]"))), /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React14.createElement(Box14, { width: "100%", height: 1, overflow: "hidden" }, /* @__PURE__ */ React14.createElement(Text14, { color: "#555555" }, "\u2584".repeat(Math.max(1, terminalSize.columns)))), /* @__PURE__ */ React14.createElement(
13608
13793
  Box14,
13609
13794
  {
13610
13795
  backgroundColor: "#555555",
@@ -13880,7 +14065,7 @@ var init_app = __esm({
13880
14065
  height
13881
14066
  },
13882
14067
  /* @__PURE__ */ React14.createElement(Box14, { marginBottom: 1, width: Math.min(80, width - 4), justifyContent: "flex-start" }, /* @__PURE__ */ React14.createElement(Text14, null, getFluxLogo(versionFluxflow))),
13883
- /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", borderStyle: "double", borderColor: "grey", paddingX: 3, paddingY: 1, width: Math.min(80, width - 4) }, /* @__PURE__ */ React14.createElement(Text14, { bold: true, color: "white", textAlign: "center" }, "\u{1F680} UPGRADE YOUR WORKFLOW"), /* @__PURE__ */ React14.createElement(Box14, { marginY: 1, flexDirection: "column", alignItems: "left" }, /* @__PURE__ */ React14.createElement(Text14, null, "You're in ", /* @__PURE__ */ React14.createElement(Text14, { bold: true, color: "cyan" }, ideName), ", but the ", /* @__PURE__ */ React14.createElement(Text14, { bold: true, color: "white" }, "FluxFlow-CLI Companion"), " is not installed."), /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Real-time file & cursor tracking"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Auto-open files created by agent"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Native DIFF viewer for AI edits"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Direct IDE context sharing"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Surgical Diagnostic Sync"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Native Right-Click \u276F Chat integration"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Live Status in IDE"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Clickable terminal-to-code links"))), /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", marginTop: 1 }, options.map((opt, i) => /* @__PURE__ */ React14.createElement(Box14, { key: i }, /* @__PURE__ */ React14.createElement(Text14, { color: selectedIndex === i ? "yellow" : "white", bold: selectedIndex === i }, selectedIndex === i ? " \u276F " : " ", opt.label)))), /* @__PURE__ */ React14.createElement(Box14, { marginTop: 1, alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React14.createElement(Text14, { dimColor: true, italic: true }, "(Use arrows to navigate, Enter to select)")))
14068
+ /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", borderStyle: "double", borderColor: "grey", paddingX: 3, paddingY: 1, width: Math.min(80, width - 4) }, /* @__PURE__ */ React14.createElement(Text14, { bold: true, color: "white", textAlign: "center" }, "\u{1F680} UPGRADE YOUR WORKFLOW"), /* @__PURE__ */ React14.createElement(Box14, { marginY: 1, flexDirection: "column", alignItems: "left" }, /* @__PURE__ */ React14.createElement(Text14, null, "You're in ", /* @__PURE__ */ React14.createElement(Text14, { bold: true, color: "cyan" }, ideName), ", but the ", /* @__PURE__ */ React14.createElement(Text14, { bold: true, color: "white" }, "FluxFlow-CLI Companion"), " is not installed."), /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Real-time IDE context & Error Resolution"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Auto-open files created by agent"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Native DIFFing for AI edits"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Direct IDE context sharing"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Surgical Diagnostic Sync"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Native Right-Click \u276F Chat integration"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Live Status in IDE"), /* @__PURE__ */ React14.createElement(Text14, { color: "gray" }, " \u2705 Clickable terminal-to-code links"))), /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", marginTop: 1 }, options.map((opt, i) => /* @__PURE__ */ React14.createElement(Box14, { key: i }, /* @__PURE__ */ React14.createElement(Text14, { color: selectedIndex === i ? "yellow" : "white", bold: selectedIndex === i }, selectedIndex === i ? " \u276F " : " ", opt.label)))), /* @__PURE__ */ React14.createElement(Box14, { marginTop: 1, alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React14.createElement(Text14, { dimColor: true, italic: true }, "(Use arrows to navigate, Enter to select)")))
13884
14069
  );
13885
14070
  };
13886
14071
  SESSION_START_TIME = Date.now();
@@ -13892,7 +14077,7 @@ var init_app = __esm({
13892
14077
  packageJson = JSON.parse(fs22.readFileSync(packageJsonPath, "utf8"));
13893
14078
  versionFluxflow = packageJson.version;
13894
14079
  updatedOn = packageJson.date || "2026-05-20";
13895
- ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React14.createElement(Box14, { paddingX: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION")), /* @__PURE__ */ React14.createElement(Box14, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text14, null, "The agent already finished the task before your hint was consumed.")), /* @__PURE__ */ React14.createElement(Box14, { marginTop: 1, backgroundColor: "#222", paddingX: 2, width: "100%" }, /* @__PURE__ */ React14.createElement(Text14, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React14.createElement(Box14, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React14.createElement(Box14, { marginTop: 0 }, /* @__PURE__ */ React14.createElement(
14080
+ ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", padding: 0, width: "100%" }, /* @__PURE__ */ React14.createElement(Box14, { paddingX: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "white", bold: true, underline: true }, data.startsWith("/btw") ? "QUESTION" : "STEERING HINT", " RESOLUTION")), /* @__PURE__ */ React14.createElement(Box14, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text14, null, "The agent already finished the task before your ", data.startsWith("/btw") ? "question" : "hint", " was consumed.")), /* @__PURE__ */ React14.createElement(Box14, { marginTop: 1, backgroundColor: "#222", paddingX: 2, width: "100%" }, /* @__PURE__ */ React14.createElement(Text14, { italic: true, color: "gray" }, '"', data.replace("/btw", "").trim(), '"')), /* @__PURE__ */ React14.createElement(Box14, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "How would you like to proceed?")), /* @__PURE__ */ React14.createElement(Box14, { marginTop: 0 }, /* @__PURE__ */ React14.createElement(
13896
14081
  CommandMenu,
13897
14082
  {
13898
14083
  title: "Select Action",
@@ -14076,6 +14261,7 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
14076
14261
  /save Force save current chat
14077
14262
  /export Export current chat in a .txt file
14078
14263
  /chats List all chat sessions
14264
+ /btw <question> Send raw inquiry to the agent mid-turn
14079
14265
  /image setup key <default|custom> Configure image API key strategy
14080
14266
  /image setup quality <low...premium> Configure default image generation quality
14081
14267
  /image stats Show image quota stats
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "2.9.0",
4
- "date": "2026-06-19",
3
+ "version": "2.10.0",
4
+ "date": "2026-06-20",
5
5
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",