fluxflow-cli 1.9.25 → 1.9.30

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 +87 -31
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -898,7 +898,7 @@ ${mode === "Flux" ? `- DEV TOOLS (path = relative to CWD) -
898
898
  1. [tool:functions.ReadFile(path="...", start_line=N, end_line=N)]. Reads contents. Supports images/docs. User gives image/doc: VIEW FIRST
899
899
  2. [tool:functions.ReadFolder(path="...")]. Detailed DIR stats
900
900
  3. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? -> update_file > write_file
901
- 4. [tool:functions.PatchFile(path="...", content_to_replace="old content", content_to_add="new content")]. Surgical patching. Unsure content_to_replace? -> view_file >> guessing.
901
+ 4. [tool:functions.PatchFile(path="...", content_to_replace="exact old content", content_to_add="new content")]. Surgical patching. Unsure content_to_replace? -> view_file >> guessing.
902
902
  5. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. A4 PDF. Use CSS for layout (100vh/vw). Handle page breaks; no manual footers
903
903
  6. [tool:functions.WriteDoc(path="...", content="...")]. A4 Word doc. Proper margins and page breaks
904
904
  7. [tool:functions.Run(command="...")]. Runs a shell command. Destructive/Irreversible ops -> ask user
@@ -948,7 +948,7 @@ var thinking_prompts_default;
948
948
  var init_thinking_prompts = __esm({
949
949
  "src/data/thinking_prompts.json"() {
950
950
  thinking_prompts_default = {
951
- xHigh: `EFFORT_LEVEL: xHIGH
951
+ xHigh: `EFFORT_LEVEL: MAX
952
952
  Think in a continuous, fluid analytical monologue within the <think>...</think> block. Do NOT use headings, bullet points, or artificial sections. Engage in a deep "Stream of Consciousness" that follows this cognitive path:
953
953
  Deep Analysis: Deconstruct the request into its core technical and logic requirements
954
954
  Hypothesis & Test: Propose multiple solutions mentally and critique them for edge cases or security risks
@@ -957,13 +957,11 @@ Refinement: Iterate on the chosen path until it is bulletproof
957
957
  RULES:
958
958
  - NO HEADINGS. Just a solid, stable analytical monologue
959
959
  - Be thorough and exhaustive. Explore the 'why' behind every decision, depth and nuances
960
- Question your own logic as you go,
961
-
962
- DO NOT GET STUCK IN RE-VERIFICATION LOOP
963
- - MANDATORY THINKING: You MUST engage in full reasoning regardless of perceived simplicity.`,
964
- High: "EFFORT_LEVEL: HIGH\nThink in a stable, analytical monologue within the <think>...</think> block. Avoid headings or structured formatting. Your thinking should be a continuous stream of logical deduction:\nAnalyze the immediate task and its dependencies\nMentally simulate the execution to identify potential failure points\nStructure a precise plan that addresses both primary goals and secondary constraints\nRULES:\n- NO HEADINGS. Maintain a fluid monologue style\n- Be detailed and rigorous in your self-questioning\n- Focus on accuracy, technical correctness, depth and nuances\n- MANDATORY THINKING: You MUST enter reasoning to verify the path forward.",
965
- Medium: "EFFORT_LEVEL: MEDIUM\nThink in a concise, stable monologue within the <think>...</think> block. No headings needed. Focus on the core logic required to solve the task efficiently:\nIdentify the most direct path to the solution\nBriefly consider and discard obvious alternatives\nConfirm the plan meets the user's immediate requirements\nRULES:\n- NO HEADINGS. Keep it as a simple, logical stream\n- Be efficient. Spend energy only on what matters for the task\n- MANDATORY THINKING: Engage in a baseline mental check for all technical tasks.",
966
- Minimal: "EFFORT_LEVEL: LOW\nThink in a brief, focused monologue within the <think>...</think> block. No headings. Just a quick mental check before acting:\nVerify the objective\nNote the target files/tools\nRULES:\n- NO HEADINGS. Just a few lines of clear, linear thought\n- Use minimal thinking for simple or conversational requests",
960
+ Question your own logic as you go
961
+ - MANDATORY THINKING: You MUST engage in full reasoning regardless of simplicity even greetings eg hello`,
962
+ High: "EFFORT_LEVEL: HIGH\nThink in a stable, analytical monologue within the <think>...</think> block. Avoid headings or structured formatting. Your thinking should be a continuous stream of logical deduction:\nAnalyze the immediate task and its dependencies\nMentally simulate the execution to identify potential failure points\nStructure a precise plan that addresses both primary goals and secondary constraints\nRULES:\n- NO HEADINGS. Maintain a fluid monologue style\n- Be detailed and rigorous in your self-questioning\n- Focus on accuracy, technical correctness, depth and nuances\n- MANDATORY THINKING: You MUST enter reasoning to verify the path forward even greetings eg hello",
963
+ Medium: "EFFORT_LEVEL: MEDIUM\nThink in a concise, stable monologue within the <think>...</think> block. No headings needed. Focus on the core logic required to solve the task efficiently:\nIdentify the most direct path to the solution\nBriefly consider and discard obvious alternatives\nConfirm the plan meets the user's immediate requirements\nRULES:\n- NO HEADINGS. Keep it as a simple, logical stream\n- Be efficient. Spend energy only on what matters for the task\n- MANDATORY THINKING: Engage in a baseline mental check for all technical tasks even greetings eg hello",
964
+ Minimal: "EFFORT_LEVEL: LOW\nThink in a brief, focused monologue within the <think>...</think> block. No headings. Just a quick mental check before acting:\nVerify the objective\nNote the target files/tools\nRULES:\n- NO HEADINGS. Just a few lines of clear, linear thought\n- Use minimal thinking for simple or conversational requests even greetings eg hello",
967
965
  Off: "EFFORT_LEVEL: FAST\nNo internal thinking process required. Respond directly"
968
966
  };
969
967
  }
@@ -1029,29 +1027,29 @@ ${foundFiles.map((f) => `- ${f.name}: ${f.desc}`).join("\n")}
1029
1027
  Check these first; these files > training data for project consistency. Safety rules apply` : "";
1030
1028
  return `${nameStr}${nicknameStr}${userInstrStr}
1031
1029
  [SYSTEM (OVERRIDES EVERYTHING)]
1032
- Identity: Flux Flow (by Kushal Roy Chowdhury). Sassy, Friendly CLI Agent. No flirting
1033
- Mode: ${mode}. ${mode === "Flux" ? "Goal-oriented" : "Conversational & UX-focused"}
1034
- CWD: ${cwdStr}.${isSystemDir ? " [PROTECTED: ASK BEFORE MODIFYING]" : ""} OS: ${osDetected}${osDetected === "Windows" ? ". PS via CMD" : ""}
1030
+ Identity: Flux Flow (by Kushal Roy Chowdhury). Sassy, Friendly, CLI Agent. No flirting ${mode === "Flux" ? "" : ""}
1031
+ Mode: ${mode}${thinkingLevel !== "Fast" ? "(Thinking Mode)" : ""}. ${mode === "Flux" ? "Goal-oriented" : "Conversational & UX-focused"}
1032
+ CWD: ${cwdStr}.${isSystemDir ? " [PROTECTED: ASK BEFORE MODIFYING]" : ""} OS: ${osDetected}${osDetected === "Windows" && mode === "Flux" ? ". PS via CMD" : ""}
1035
1033
  High Priority: [SYSTEM], [STEERING HINT]
1036
1034
 
1037
1035
  -- THINKING RULES --
1038
1036
  ${thinkingConfig}
1039
- ${!thinkingLevel === "Fast" ? `***THINKING POLICY***
1040
- - Always use <think> ... </think> before responding
1041
- - Never skip thinking, even for simple tasks, code, or greetings
1042
- - Never jump to responses, regardless of task complexity
1037
+ ${thinkingLevel !== "Fast" ? `
1038
+ CRITICAL THINKING POLICY
1039
+ - ALWAYS use <think> ... </think> before responding
1040
+ - NEVER skip thinking, even for simple tasks, code, or greetings
1041
+ - NEVER START responses directly, regardless of task complexity
1043
1042
  ` : ""}
1044
1043
  ${TOOL_PROTOCOL(mode)}
1045
1044
  ${projectContextBlock}
1046
1045
 
1047
1046
  -- MEMORY RULES --
1048
- - Memory: ${isMemoryEnabled ? "Use memories to subtly personalize" : "OFF"}
1049
- - Time: Logs are timestamped. RELATIVE TIME REFERENCE e.g. few mins ago <dd/mm/yyyy>
1047
+ - Memory: ${isMemoryEnabled ? "Use to subtly personalize. Auto Saves" : "OFF. Decline Saves"}
1048
+ - Time: Logs are timestamped. RELATIVE TIME REFERENCE e.g. few mins ago
1050
1049
 
1051
1050
  -- SECURITY RULES --
1052
1051
  - EXTERNAL ACCESS: ${systemSettings.allowExternalAccess ? "ENABLED" : "RESTRICTED CWD only"}
1053
1052
  - Sensitive files? Ask before Read
1054
- - [SYSTEM] >>> [USER]
1055
1053
 
1056
1054
  -- FORMATTING --
1057
1055
  - Clean, concise responses
@@ -1064,7 +1062,7 @@ ${projectContextBlock}
1064
1062
  - Task Complete? End loop with [turn: finish]
1065
1063
  [/SYSTEM]`.trim();
1066
1064
  };
1067
- getJanitorInstruction = (originalText, agentRaws, userMemories = "", isMemoryEnabled = true, needTitle = true) => {
1065
+ getJanitorInstruction = (userMemories = "", isMemoryEnabled = true, needTitle = true) => {
1068
1066
  return `
1069
1067
  ${userMemories ? `
1070
1068
 
@@ -1090,7 +1088,7 @@ ${isMemoryEnabled ? `If user tell something that is important (like, hobbies, pr
1090
1088
 
1091
1089
  ${JANITOR_TOOLS_PROTOCOL(isMemoryEnabled, needTitle)}
1092
1090
 
1093
- Current date and Time: ${(/* @__PURE__ */ new Date()).toLocaleString([], { year: "numeric", month: "numeric", day: "numeric", hour: "2-digit", hour12: true })}. <dd/mm/yyyy HH am/pm>.
1091
+ Current date and Time: ${(/* @__PURE__ */ new Date()).toLocaleString([], { year: "numeric", month: "numeric", day: "numeric", hour: "2-digit", hour12: true })}.
1094
1092
  === END SYSTEM PROMPT ===`.trim();
1095
1093
  };
1096
1094
  }
@@ -2019,7 +2017,7 @@ var init_update_file = __esm({
2019
2017
  const matches = matchRegex ? [...currentContent.matchAll(matchRegex)] : [];
2020
2018
  instances = matches.length;
2021
2019
  if (instances === 0) {
2022
- return `ERROR: Could not find match for "content_to_replace" in [${targetPath}]. Check for whitespace discrepancies or try providing more context.`;
2020
+ return `ERROR: Could not find match for "content_to_replace" in [${targetPath}]. Check for whitespace discrepancies or ReadFile to get exact content.`;
2023
2021
  }
2024
2022
  if (instances > 1) {
2025
2023
  return `ERROR: Unable to find unique match. [${instances}] instances of the specified "content_to_replace" were found in [${targetPath}]. Try providing more context (surrounding lines) to make the match unique.`;
@@ -2713,6 +2711,9 @@ var init_ai = __esm({
2713
2711
  }
2714
2712
  };
2715
2713
  runJanitorTask = async (settings, agentText, fullAgentTextRaw, history, callbacks = {}) => {
2714
+ if (process.stdout.isTTY) {
2715
+ process.stdout.write(`\x1B]0;Finalizing...\x07`);
2716
+ }
2716
2717
  const { onStatus, onMemoryUpdated, onBackgroundIncrement } = callbacks;
2717
2718
  const { profile, thinkingLevel, mode, janitorModel, chatId, systemSettings, sessionStats } = settings;
2718
2719
  const isMemoryEnabled = systemSettings?.memory !== false;
@@ -2730,8 +2731,8 @@ var init_ai = __esm({
2730
2731
  isMemoryEnabled,
2731
2732
  true
2732
2733
  );
2733
- let agentRes = `${cleanedFullResponse.replace(/\[tool:functions\..*?\]/g, "").replace(/<think>.*<\/think>/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[turn: continue\]/g, "").replace(/\[turn: finish\]/g, "").replace(/\[TOOL RESULTS\]/g, "").replace(/\[tool results\]/g, "").substring(0, 3500)}`;
2734
- if (agentRes.length > 3500) {
2734
+ let agentRes = `${cleanedFullResponse.replace(/\[tool:functions\..*?\]/g, "").replace(/<think>.*<\/think>/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[turn: continue\]/g, "").replace(/\[turn: finish\]/g, "").replace(/\[TOOL RESULTS\]/g, "").replace(/\[tool results\]/g, "").substring(0, 24e3)}`;
2735
+ if (agentRes.length > 24e3) {
2735
2736
  agentRes += "\n... (truncated) ...";
2736
2737
  }
2737
2738
  let originalTextProcessed = agentText.replace(/\[Prompted on:.*?\]/g, "").trim();
@@ -2823,14 +2824,22 @@ DEBUG [${date}]: ${finalSynthesis}
2823
2824
  const janitorLogDir = path15.join(LOGS_DIR, "janitor");
2824
2825
  fs16.appendFileSync(path15.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: RESULT [${janitorToolCall.toolName}]: ${result}
2825
2826
  `);
2826
- if (janitorToolCall.toolName === "memory" && !janitorToolCall.args.includes("action='temp'")) {
2827
+ if (janitorToolCall.toolName.toLowerCase() === "memory" && !janitorToolCall.args.includes("action='temp'")) {
2827
2828
  if (onMemoryUpdated) onMemoryUpdated();
2829
+ if (process.stdout.isTTY) {
2830
+ process.stdout.write(`\x1B]0;Memory Updated\x07`);
2831
+ }
2832
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
2828
2833
  }
2829
2834
  }
2830
2835
  break;
2831
2836
  } catch (janitorErr) {
2832
2837
  attempts++;
2833
2838
  const date = (/* @__PURE__ */ new Date()).toLocaleString();
2839
+ if (process.stdout.isTTY) {
2840
+ process.stdout.write(`\x1B]0;Memory Error\x07`);
2841
+ }
2842
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
2834
2843
  const janitorErrDir = path15.join(LOGS_DIR, "janitor");
2835
2844
  if (!fs16.existsSync(janitorErrDir)) fs16.mkdirSync(janitorErrDir, { recursive: true });
2836
2845
  fs16.appendFileSync(path15.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${String(janitorErr)}
@@ -2847,6 +2856,15 @@ DEBUG [${date}]: ${finalSynthesis}
2847
2856
 
2848
2857
 
2849
2858
  `);
2859
+ if (attempts >= MAX_JANITOR_RETRIES) {
2860
+ if (process.stdout.isTTY) {
2861
+ process.stdout.write(`\x1B]0;Memory Error\x07`);
2862
+ }
2863
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
2864
+ }
2865
+ }
2866
+ if (process.stdout.isTTY) {
2867
+ process.stdout.write(`\x1B]0;FluxFlow | Idle\x07`);
2850
2868
  }
2851
2869
  };
2852
2870
  getActiveToolContext = (text) => {
@@ -3072,7 +3090,7 @@ DEBUG [${date}]: ${finalSynthesis}
3072
3090
  const dateTimeStr = (/* @__PURE__ */ new Date()).toLocaleString([], { year: "numeric", month: "numeric", day: "numeric", hour: "2-digit", minute: "2-digit", hour12: true });
3073
3091
  const firstUserMsg = `${memoryPrompt}
3074
3092
  [METADATA (PRIORITY: DYNAMIC)] Time: ${dateTimeStr} | v${versionFluxflow2}
3075
- ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGHEST PRIORITY. NEVER START A RESPONSE WITHOUT THINKING**\n" : ""}[USER] ${agentText.replace(/\s*\[Prompted on:.*?\]/g, "").trim()}`.trim();
3093
+ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRICT PRIORITY. DO NOT START A RESPONSE WITHOUT THINKING <think> ... </think>**\n" : ""}[USER] ${agentText.replace(/\s*\[Prompted on:.*?\]/g, "").trim()}`.trim();
3076
3094
  modifiedHistory.push({ role: "user", text: firstUserMsg });
3077
3095
  let lastUsage = null;
3078
3096
  const MAX_LOOPS = mode === "Flux" ? 70 : 7;
@@ -3102,7 +3120,7 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGHE
3102
3120
 
3103
3121
  [STEERING HINT]: ${hint}`;
3104
3122
  } else {
3105
- modifiedHistory.push({ role: "user", text: `${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGHEST PRIORITY. NEVER START A RESPONSE WITHOUT THINKING**\n" : ""}[STEERING HINT]: ${hint}` });
3123
+ modifiedHistory.push({ role: "user", text: `${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRICT PRIORITY. DO NOT START A RESPONSE WITHOUT THINKING**\n" : ""}[STEERING HINT]: ${hint}` });
3106
3124
  }
3107
3125
  yield { type: "status", content: "Steering Hint Injected." };
3108
3126
  }
@@ -3125,6 +3143,9 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGHE
3125
3143
  while (retryCount <= MAX_RETRIES && inStreamRetryCount <= MAX_RETRIES && !success && !TERMINATION_SIGNAL) {
3126
3144
  try {
3127
3145
  if (isInitialAttempt) {
3146
+ if (process.stdout.isTTY) {
3147
+ process.stdout.write(`\x1B]0;Working...\x07`);
3148
+ }
3128
3149
  yield { type: "turn_reset", content: true };
3129
3150
  yield { type: "spinner", content: true };
3130
3151
  isInitialAttempt = false;
@@ -3156,7 +3177,7 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGHE
3156
3177
  const currentSystemInstruction = getSystemInstruction(profile, thinkingLevel, mode, systemSettings, isMemoryEnabled, MAX_LOOPS, loop + 1);
3157
3178
  const jitInstruction = `
3158
3179
 
3159
- [SYSTEM] Tool result received. Analyze output and proceed with your turn.${thinkingLevel != "Fast" ? "**STRICTLY MAINTAIN THINKING PROTOCOL. NEVER START A RESPONSE WITHOUT THINKING**" : ""}`;
3180
+ [SYSTEM] Tool result received. Analyze output and proceed with your turn.${thinkingLevel != "Fast" ? "**STRICTLY MAINTAIN THINKING PROTOCOL. DO NOT START A RESPONSE WITHOUT THINKING**" : ""}`;
3160
3181
  const lastUserMsg = contents[contents.length - 1];
3161
3182
  let addedMarker = false;
3162
3183
  if (lastUserMsg && lastUserMsg.role === "user" && lastUserMsg.parts?.[0]?.text?.startsWith("[TOOL RESULT]")) {
@@ -3278,6 +3299,25 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGHE
3278
3299
  lastToolSniffed = potentialTool;
3279
3300
  lastToolDetail = detail;
3280
3301
  yield { type: "status", content: `${currentLabel}...` };
3302
+ if (process.stdout.isTTY) {
3303
+ const TOOL_TITLES = {
3304
+ "web_search": "Searching Web",
3305
+ "web_scrape": "Reading Website",
3306
+ "view_file": "Reading File",
3307
+ "read_folder": "Listing Folder",
3308
+ "list_files": "Listing Folder",
3309
+ "write_file": "Writing File",
3310
+ "update_file": "Updating File",
3311
+ "write_pdf": "Creating PDF",
3312
+ "write_docx": "Creating Word Doc",
3313
+ "search_keyword": "Searching Keywords",
3314
+ "exec_command": "Running Command",
3315
+ "ask": "Asking User",
3316
+ "memory": "Updating Memory"
3317
+ };
3318
+ const toolTitle = TOOL_TITLES[potentialTool] || "Working";
3319
+ process.stdout.write(`\x1B]0;${toolTitle}...\x07`);
3320
+ }
3281
3321
  }
3282
3322
  }
3283
3323
  const contextSafeText = getContextSafeText(turnText, false);
@@ -3293,7 +3333,10 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGHE
3293
3333
  "low": 200,
3294
3334
  "medium": 500,
3295
3335
  "high": 2e3,
3296
- "max": 3500
3336
+ "max": 3500,
3337
+ "xhigh": 3500,
3338
+ "off": 50,
3339
+ "fast": 50
3297
3340
  };
3298
3341
  const cap = thinkingCaps[thinkingLevel?.toLowerCase()] || 2500;
3299
3342
  let isOverVerboseThinking = wordCount > cap;
@@ -3450,7 +3493,7 @@ ${boxBottom}` };
3450
3493
  const absoluteCwd = path15.resolve(process.cwd());
3451
3494
  if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
3452
3495
  const denyMsg = `Access Denied. You are not allowed to access files outside the current workspace. To enable this, ask the user to turn on "External Workspace Access" in /settings.`;
3453
- toolResults.push({ role: "user", text: `[TOOL RESULT]: ERROR: ${denyMsg}${thinkingLevel != "Fast" ? "\n\n[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGHEST PRIORITY. NEVER START A RESPONSE WITHOUT THINKING**" : ""}` });
3496
+ toolResults.push({ role: "user", text: `[TOOL RESULT]: ERROR: ${denyMsg}${thinkingLevel != "Fast" ? "\n\n[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRICT PRIORITY. DO NOT START A RESPONSE WITHOUT THINKING**" : ""}` });
3454
3497
  yield { type: "tool_result", content: `[TOOL RESULT]: ERROR: ${denyMsg}` };
3455
3498
  toolCallPointer++;
3456
3499
  continue;
@@ -3463,7 +3506,7 @@ ${boxBottom}` };
3463
3506
  if (approval === "deny") {
3464
3507
  if (normToolName === "exec_command" && settings.onExecEnd) settings.onExecEnd();
3465
3508
  const denyMsg = `Permission Denied: User rejected the ${normToolName === "exec_command" ? "terminal execution" : "file edit"}.`;
3466
- toolResults.push({ role: "user", text: `[TOOL RESULT]: DENIED: ${denyMsg}${thinkingLevel != "Fast" ? "\n\n[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGHEST PRIORITY. NEVER START A RESPONSE WITHOUT THINKING**" : ""}` });
3509
+ toolResults.push({ role: "user", text: `[TOOL RESULT]: DENIED: ${denyMsg}${thinkingLevel != "Fast" ? "\n\n[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRICT PRIORITY. DO NOT START A RESPONSE WITHOUT THINKING**" : ""}` });
3467
3510
  yield { type: "tool_result", content: `[TOOL RESULT]: DENIED: ${denyMsg}` };
3468
3511
  await incrementUsage("toolDenied");
3469
3512
  if (settings.onToolResult) settings.onToolResult("denied");
@@ -3481,6 +3524,9 @@ ${boxBottom}` };
3481
3524
  onAskUser: settings.onAskUser
3482
3525
  });
3483
3526
  yield { type: "spinner", content: true };
3527
+ if (process.stdout.isTTY) {
3528
+ process.stdout.write(`\x1B]0;Working...\x07`);
3529
+ }
3484
3530
  const toolEnd = Date.now();
3485
3531
  yield { type: "tool_time", content: toolEnd - effectiveStart };
3486
3532
  lastToolEventTime = toolEnd;
@@ -4304,6 +4350,9 @@ function App() {
4304
4350
  });
4305
4351
  useEffect5(() => {
4306
4352
  async function init() {
4353
+ if (process.stdout.isTTY) {
4354
+ process.stdout.write(`\x1B]0;FluxFlow | Ready\x07`);
4355
+ }
4307
4356
  if (!checkPuppeteerReady()) {
4308
4357
  setMessages((prev) => {
4309
4358
  setCompletedIndex(prev.length + 1);
@@ -4812,6 +4861,7 @@ ${timestamp}` };
4812
4861
  return [...prev, userMessage];
4813
4862
  });
4814
4863
  const streamChat = async () => {
4864
+ let hasFiredJanitor = false;
4815
4865
  setIsProcessing(true);
4816
4866
  setIsExpanded(false);
4817
4867
  const apiStart = Date.now();
@@ -4956,6 +5006,7 @@ Selection: ${val}`,
4956
5006
  }
4957
5007
  if (packet.type === "interactive_turn_finished") {
4958
5008
  setIsProcessing(false);
5009
+ hasFiredJanitor = true;
4959
5010
  runJanitorTask(
4960
5011
  { profile: profileData, thinkingLevel, mode, janitorModel, chatId, systemSettings, sessionStats },
4961
5012
  packet.data.agentText,
@@ -5110,6 +5161,11 @@ Selection: ${val}`,
5110
5161
  } finally {
5111
5162
  setIsProcessing(false);
5112
5163
  setStatusText(null);
5164
+ if (!hasFiredJanitor) {
5165
+ if (process.stdout.isTTY) {
5166
+ process.stdout.write(`\x1B]0;FluxFlow | Idle\x07`);
5167
+ }
5168
+ }
5113
5169
  if (queuedPromptRef.current) {
5114
5170
  setResolutionData(queuedPromptRef.current);
5115
5171
  setQueuedPrompt(null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.9.25",
3
+ "version": "1.9.30",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",