fluxflow-cli 1.7.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/fluxflow.js +140 -90
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -784,7 +784,7 @@ ${userMemories}
784
784
  ` : ""}${isMemoryEnabled ? `${tempMemoriesStr}
785
785
 
786
786
  ` : ""}--- START SYSTEM INSTRUCTION ---
787
- You are Flux Flow (made by Kushal Roy Chowdhury/Flux Flow Team). A CLI Agent. Your tone will be friendly, warm, sassy, approchable, funny, NO ROMANTIC OR FLIRTY WORDS. Dont mention modes unless explicitly asked. ${mode === "Flux" ? "You are currently operating in FLUX (dev) mode. Keep your agentic approach goal oriented, conversation quality and user experience. Use provided tools when needed. And try to minimize number of agentic loops (Agent Loop is limited to 50 per turn, finish your goal by then). Analyze user prompt and project requirements, then plan your approach." : "You are currently operating in Flow (chat) mode. Focus more on conversation quality and user experience. Keep Agentic Loops to minimum (Agent Loop is limited to 7 per turn, finish your goal by then). You will get access to Web Tools only in this mode."}
787
+ You are Flux Flow (made by Kushal Roy Chowdhury/Flux Flow Team). A CLI Agent. Your tone will be friendly, warm, sassy, approchable, funny, NO ROMANTIC OR FLIRTY WORDS. Dont mention modes unless explicitly asked. ${mode === "Flux" ? "You are currently operating in FLUX mode. Keep your agentic approach goal oriented, conversation quality and user experience. Use provided tools when needed. And try to minimize number of agentic loops (Agent Loop is limited to 50 per turn, finish your goal by then). Analyze user prompt and project requirements, then plan your approach." : "You are currently operating in Flow mode. Focus more on conversation quality and user experience. Keep Agentic Loops to minimum (Agent Loop is limited to 7 per turn, finish your goal by then). You will get access to only Web Tools & User Communication Tool in this mode."}
788
788
  CURRENT_WORKING_DIRECTORY: ${cwdStr}.
789
789
  OS: ${osDetected}. ${osDetected === "Windows" && mode === "Flux" ? "Your terminal commands will run on CMD. 'Prefer using PS scripts via CMD' instead of raw CMD commands." : ""}
790
790
  ${nameStr}${nicknameStr}${userInstrStr}
@@ -977,7 +977,7 @@ var init_history = __esm({
977
977
  // src/utils/usage.js
978
978
  import fs5 from "fs-extra";
979
979
  import path5 from "path";
980
- var getDailyUsage, incrementUsage, checkQuota;
980
+ var getDailyUsage, incrementUsage, addToUsage, checkQuota;
981
981
  var init_usage = __esm({
982
982
  "src/utils/usage.js"() {
983
983
  init_paths();
@@ -987,30 +987,55 @@ var init_usage = __esm({
987
987
  if (await fs5.exists(USAGE_FILE)) {
988
988
  const data = await fs5.readJson(USAGE_FILE);
989
989
  if (data.date === today) {
990
- return data.stats;
990
+ const s = data.stats;
991
+ const normalized = {
992
+ agent: s.agent || 0,
993
+ background: s.background || 0,
994
+ search: s.search || 0,
995
+ toolSuccess: s.toolSuccess || 0,
996
+ toolFailure: s.toolFailure || 0,
997
+ duration: s.duration || 0,
998
+ tokens: s.tokens || 0
999
+ };
1000
+ return normalized;
991
1001
  }
992
1002
  }
993
1003
  } catch (err) {
994
1004
  console.error("Failed to read usage:", err);
995
1005
  }
996
- const defaultStats = { agent: 0, background: 0, search: 0 };
1006
+ const defaultStats = {
1007
+ agent: 0,
1008
+ background: 0,
1009
+ search: 0,
1010
+ toolSuccess: 0,
1011
+ toolFailure: 0,
1012
+ duration: 0,
1013
+ tokens: 0
1014
+ };
997
1015
  await fs5.ensureDir(path5.dirname(USAGE_FILE));
998
1016
  await fs5.writeJson(USAGE_FILE, { date: today, stats: defaultStats }, { spaces: 2 });
999
1017
  return defaultStats;
1000
1018
  };
1001
1019
  incrementUsage = async (key) => {
1002
1020
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1003
- const data = await fs5.readJson(USAGE_FILE).catch(() => ({ date: today, stats: { agent: 0, background: 0, search: 0 } }));
1004
- if (data.date !== today) {
1005
- data.date = today;
1006
- data.stats = { agent: 0, background: 0, search: 0 };
1007
- }
1021
+ const stats = await getDailyUsage();
1022
+ const data = { date: today, stats };
1008
1023
  if (data.stats[key] !== void 0) {
1009
1024
  data.stats[key]++;
1010
1025
  await fs5.ensureDir(path5.dirname(USAGE_FILE));
1011
1026
  await fs5.writeJson(USAGE_FILE, data, { spaces: 2 });
1012
1027
  }
1013
1028
  };
1029
+ addToUsage = async (key, amount) => {
1030
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1031
+ const stats = await getDailyUsage();
1032
+ const data = { date: today, stats };
1033
+ if (data.stats[key] !== void 0) {
1034
+ data.stats[key] += Math.floor(amount);
1035
+ await fs5.ensureDir(path5.dirname(USAGE_FILE));
1036
+ await fs5.writeJson(USAGE_FILE, data, { spaces: 2 });
1037
+ }
1038
+ };
1014
1039
  checkQuota = async (key, settings) => {
1015
1040
  const usage = await getDailyUsage();
1016
1041
  const tier = settings.apiTier || "Free";
@@ -2376,6 +2401,7 @@ USER_PROMPT: ${agentText}`.trim();
2376
2401
  }
2377
2402
  await incrementUsage("agent");
2378
2403
  if (lastUsage) {
2404
+ await addToUsage("tokens", lastUsage.totalTokenCount || 0);
2379
2405
  yield { type: "usage", content: lastUsage };
2380
2406
  }
2381
2407
  fullAgentResponseChunks.push(turnText);
@@ -2420,7 +2446,7 @@ USER_PROMPT: ${agentText}`.trim();
2420
2446
  if (isPdf) {
2421
2447
  label = `\u{1F4C4} ANALYZING PDF: ${targetPath2}`.toUpperCase();
2422
2448
  } else if (isImage) {
2423
- label = `\u{1F5BC}\uFE0F ANALYZING IMAGE: ${targetPath2}`.toUpperCase();
2449
+ label = `\u{1F4F8} ANALYZING IMAGE: ${targetPath2}`.toUpperCase();
2424
2450
  } else {
2425
2451
  label = `\u{1F4C4} READING FILE: ${targetPath2}. LINES ${start_line} - ${actualEndLine} FROM ${totalLines}`.toUpperCase();
2426
2452
  }
@@ -2519,12 +2545,15 @@ ${boxBottom}
2519
2545
  }
2520
2546
  }
2521
2547
  }
2548
+ const toolStart = Date.now();
2522
2549
  let result = await dispatchTool(toolCall.toolName, toolCall.args, {
2523
2550
  chatId,
2524
2551
  history,
2525
2552
  onChunk: (chunk) => settings.onExecChunk ? settings.onExecChunk(chunk) : null,
2526
2553
  onAskUser: settings.onAskUser
2527
2554
  });
2555
+ const toolEnd = Date.now();
2556
+ yield { type: "tool_time", content: toolEnd - toolStart };
2528
2557
  let binaryPart = null;
2529
2558
  if (typeof result === "object" && result.binaryPart) {
2530
2559
  binaryPart = result.binaryPart;
@@ -2534,6 +2563,14 @@ ${boxBottom}
2534
2563
  await new Promise((resolve) => setTimeout(resolve, 800));
2535
2564
  settings.onExecEnd();
2536
2565
  }
2566
+ const isSuccess = result && !result.startsWith("ERROR:");
2567
+ if (isSuccess) {
2568
+ await incrementUsage("toolSuccess");
2569
+ if (settings.onToolResult) settings.onToolResult("success");
2570
+ } else {
2571
+ await incrementUsage("toolFailure");
2572
+ if (settings.onToolResult) settings.onToolResult("failure");
2573
+ }
2537
2574
  try {
2538
2575
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
2539
2576
  const isErr = result.startsWith("ERROR:");
@@ -2614,6 +2651,9 @@ ${boxBottom}
2614
2651
  else if (janitorResult.response && janitorResult.response.text) finalSynthesis = janitorResult.response.text();
2615
2652
  else throw new Error("No synthesis generated by Janitor.");
2616
2653
  await incrementUsage("background");
2654
+ if (janitorResult.usageMetadata) {
2655
+ await addToUsage("tokens", janitorResult.usageMetadata.totalTokenCount || 0);
2656
+ }
2617
2657
  yield { type: "background_increment" };
2618
2658
  const janitorToolCalls = detectToolCalls(finalSynthesis);
2619
2659
  for (const janitorToolCall of janitorToolCalls) {
@@ -3023,6 +3063,10 @@ Check what's new using \`/changelog\` command.`,
3023
3063
  const [sessionAgentCalls, setSessionAgentCalls] = useState7(0);
3024
3064
  const [sessionBackgroundCalls, setSessionBackgroundCalls] = useState7(0);
3025
3065
  const [sessionTotalTokens, setSessionTotalTokens] = useState7(0);
3066
+ const [sessionToolSuccess, setSessionToolSuccess] = useState7(0);
3067
+ const [sessionToolFailure, setSessionToolFailure] = useState7(0);
3068
+ const [sessionApiTime, setSessionApiTime] = useState7(0);
3069
+ const [sessionToolTime, setSessionToolTime] = useState7(0);
3026
3070
  const [dailyUsage, setDailyUsage] = useState7(null);
3027
3071
  const [chatId, setChatId] = useState7(generateChatId());
3028
3072
  const [activeCommand, setActiveCommand] = useState7(null);
@@ -3056,6 +3100,10 @@ Check what's new using \`/changelog\` command.`,
3056
3100
  parts.push(`${s}s`);
3057
3101
  return parts.join(" ");
3058
3102
  };
3103
+ const formatMsDuration = (ms) => {
3104
+ if (ms < 1e3) return `${ms}ms`;
3105
+ return formatDuration(Math.floor(ms / 1e3));
3106
+ };
3059
3107
  const [statusText, setStatusText] = useState7(null);
3060
3108
  const [isProcessing, setIsProcessing] = useState7(false);
3061
3109
  const [escPressed, setEscPressed] = useState7(false);
@@ -3238,6 +3286,22 @@ Check what's new using \`/changelog\` command.`,
3238
3286
  setTempKey("");
3239
3287
  }
3240
3288
  };
3289
+ useEffect5(() => {
3290
+ if (activeView === "exit") {
3291
+ const timer = setTimeout(() => {
3292
+ process.exit(0);
3293
+ }, 100);
3294
+ return () => clearTimeout(timer);
3295
+ }
3296
+ }, [activeView]);
3297
+ useEffect5(() => {
3298
+ const interval = setInterval(async () => {
3299
+ if (!isInitializing) {
3300
+ await addToUsage("duration", 5);
3301
+ }
3302
+ }, 5e3);
3303
+ return () => clearInterval(interval);
3304
+ }, [isInitializing]);
3241
3305
  const COMMANDS = [
3242
3306
  { cmd: "/quit", desc: "Exit and shutdown Flux" },
3243
3307
  { cmd: "/help", desc: "Show all available commands" },
@@ -3245,24 +3309,36 @@ Check what's new using \`/changelog\` command.`,
3245
3309
  { cmd: "/resume", desc: "Load previous session" },
3246
3310
  { cmd: "/save", desc: "Force save current chat" },
3247
3311
  { cmd: "/chats", desc: "List all chat sessions" },
3248
- { cmd: "/mode", desc: "Toggle Flux/Flow modes", subs: [
3249
- { cmd: "flux", desc: "Enable Dev toolset" },
3250
- { cmd: "flow", desc: "Enable Chat mode" }
3251
- ] },
3252
- { cmd: "/thinking", desc: "Set AI reasoning depth", subs: [
3253
- { cmd: "low", desc: "Fastest reasoning" },
3254
- { cmd: "medium", desc: "Balanced depth" },
3255
- { cmd: "high", desc: "Complex coding" },
3256
- { cmd: "max", desc: "Architectural depth" },
3257
- { cmd: "show", desc: "Show full thoughts" },
3258
- { cmd: "hide", desc: "Show concise thoughts" }
3259
- ] },
3260
- { cmd: "/model", desc: "Switch AI model", subs: [
3261
- { cmd: "gemma-4-31b-it", desc: "Standard Default (Free, Recommended)" },
3262
- { cmd: "gemini-3.1-pro-preview", desc: "Most Capable (Paid)" },
3263
- { cmd: "gemini-3-flash-preview", desc: "Fast & Lightweight (Paid, Free limited quota)" },
3264
- { cmd: "gemini-3.1-flash-lite-preview", desc: "Ultra Fast (Paid, Free limited quota)" }
3265
- ] },
3312
+ {
3313
+ cmd: "/mode",
3314
+ desc: "Toggle Flux/Flow modes",
3315
+ subs: [
3316
+ { cmd: "flux", desc: "Enable Dev toolset" },
3317
+ { cmd: "flow", desc: "Enable Chat mode" }
3318
+ ]
3319
+ },
3320
+ {
3321
+ cmd: "/thinking",
3322
+ desc: "Set AI reasoning depth",
3323
+ subs: [
3324
+ { cmd: "low", desc: "Fastest reasoning" },
3325
+ { cmd: "medium", desc: "Balanced depth" },
3326
+ { cmd: "high", desc: "Complex coding" },
3327
+ { cmd: "max", desc: "Architectural depth" },
3328
+ { cmd: "show", desc: "Show full thoughts" },
3329
+ { cmd: "hide", desc: "Show concise thoughts" }
3330
+ ]
3331
+ },
3332
+ {
3333
+ cmd: "/model",
3334
+ desc: "Switch AI model",
3335
+ subs: [
3336
+ { cmd: "gemma-4-31b-it", desc: "Standard Default (Free, Recommended)" },
3337
+ { cmd: "gemini-3.1-pro-preview", desc: "Most Capable (Paid)" },
3338
+ { cmd: "gemini-3-flash-preview", desc: "Fast & Lightweight (Paid, Free limited quota)" },
3339
+ { cmd: "gemini-3.1-flash-lite-preview", desc: "Ultra Fast (Paid, Free limited quota)" }
3340
+ ]
3341
+ },
3266
3342
  { cmd: "/settings", desc: "Configure system prefs" },
3267
3343
  { cmd: "/key", desc: "Manage API keys" },
3268
3344
  { cmd: "/profile", desc: "Edit developer persona" },
@@ -3271,10 +3347,14 @@ Check what's new using \`/changelog\` command.`,
3271
3347
  { cmd: "/reset", desc: "Wipe all project data" },
3272
3348
  { cmd: "/about", desc: "Project info & credits" },
3273
3349
  { cmd: "/changelog", desc: "View latest updates" },
3274
- { cmd: "/update", desc: "Check/Install updates", subs: [
3275
- { cmd: "check", desc: "Check for new version" },
3276
- { cmd: "latest", desc: "Install latest release" }
3277
- ] }
3350
+ {
3351
+ cmd: "/update",
3352
+ desc: "Check/Install updates",
3353
+ subs: [
3354
+ { cmd: "check", desc: "Check for new version" },
3355
+ { cmd: "latest", desc: "Install latest release" }
3356
+ ]
3357
+ }
3278
3358
  ];
3279
3359
  const handleSubmit = (value) => {
3280
3360
  if (suggestions.length > 0) {
@@ -3556,6 +3636,7 @@ ${timestamp}` };
3556
3636
  const streamChat = async () => {
3557
3637
  setIsProcessing(true);
3558
3638
  setIsExpanded(false);
3639
+ const apiStart = Date.now();
3559
3640
  try {
3560
3641
  const cleanHistoryForAI = [...messages, userMessage].filter(
3561
3642
  (m) => m.role !== "think" && !m.isVisualFeedback && !String(m.id).startsWith("welcome")
@@ -3592,6 +3673,10 @@ OUTPUT: ${execOutputRef.current}`;
3592
3673
  setIsTerminalFocused(false);
3593
3674
  setExecOutput("");
3594
3675
  },
3676
+ onToolResult: (status) => {
3677
+ if (status === "success") setSessionToolSuccess((prev) => prev + 1);
3678
+ else setSessionToolFailure((prev) => prev + 1);
3679
+ },
3595
3680
  onToolApproval: async (tool, args) => {
3596
3681
  const isAuto = autoAcceptWrites || systemSettings.autoExec;
3597
3682
  if (tool === "exec_command") {
@@ -3722,6 +3807,10 @@ Selection: ${val}`,
3722
3807
  setSessionBackgroundCalls((prev) => prev + 1);
3723
3808
  continue;
3724
3809
  }
3810
+ if (packet.type === "tool_time") {
3811
+ setSessionToolTime((prev) => prev + packet.content);
3812
+ continue;
3813
+ }
3725
3814
  if (packet.type === "tool_result") {
3726
3815
  setMessages((prev) => [...prev, {
3727
3816
  id: "tool-" + Date.now(),
@@ -3821,6 +3910,8 @@ Selection: ${val}`,
3821
3910
  }
3822
3911
  }
3823
3912
  }
3913
+ const apiEnd = Date.now();
3914
+ setSessionApiTime((prev) => prev + (apiEnd - apiStart));
3824
3915
  } catch (err) {
3825
3916
  setMessages((prev) => {
3826
3917
  setCompletedIndex(prev.length + 1);
@@ -4009,9 +4100,8 @@ Selection: ${val}`,
4009
4100
  {
4010
4101
  title: `API Tier: ${apiTier}`,
4011
4102
  items: [
4012
- { label: "Free Tier (1,500/day)", value: "Free" },
4013
- { label: `Paid Tier (Budget: ${quotas.agentLimit})`, value: "Paid" },
4014
- { label: `Custom Model (Endpoint: ${quotas.customModelId || "None"})`, value: "Custom" },
4103
+ { label: "Free Tier (Gemini API Free Tier - Optimized for Gemma 4 Model)", value: "Free" },
4104
+ { label: `Custom (for using Paid API)`, value: "Custom" },
4015
4105
  { label: "Back", value: "settings" }
4016
4106
  ],
4017
4107
  onSelect: (item) => {
@@ -4021,43 +4111,12 @@ Selection: ${val}`,
4021
4111
  }
4022
4112
  const newTier = item.value;
4023
4113
  setApiTier(newTier);
4024
- if (newTier === "Paid") {
4114
+ if (newTier === "Custom") {
4025
4115
  setInputConfig({
4026
- label: "Daily Agent Limit for default model (Gemma 4 31B):",
4027
- note: "NOTE: If you have your own Gemini API supported model, use Custom mode.",
4116
+ label: "Enter Agent daily limit (requests made):",
4028
4117
  key: "quotas",
4029
4118
  subKey: "agentLimit",
4030
- value: String(quotas.agentLimit),
4031
- next: (q) => ({
4032
- label: "Daily default background model limit (Gemma 4 26B A4B):",
4033
- key: "quotas",
4034
- subKey: "backgroundLimit",
4035
- value: String(q.backgroundLimit)
4036
- })
4037
- });
4038
- setActiveView("input");
4039
- } else if (newTier === "Custom") {
4040
- setInputConfig({
4041
- label: "Enter Agent Model ID:",
4042
- key: "activeModel",
4043
- value: activeModel,
4044
- next: (val) => ({
4045
- label: "Enter Background Model ID:",
4046
- key: "janitorModel",
4047
- value: janitorModel,
4048
- next: (val2) => ({
4049
- label: "Enter Agent daily limit (calls):",
4050
- key: "quotas",
4051
- subKey: "agentLimit",
4052
- value: String(quotas.agentLimit),
4053
- next: (q) => ({
4054
- label: "Enter Background daily limit (calls):",
4055
- key: "quotas",
4056
- subKey: "backgroundLimit",
4057
- value: String(quotas.backgroundLimit)
4058
- })
4059
- })
4060
- })
4119
+ value: String(quotas.agentLimit)
4061
4120
  });
4062
4121
  setActiveView("input");
4063
4122
  } else {
@@ -4106,7 +4165,7 @@ Selection: ${val}`,
4106
4165
  }
4107
4166
  )), /* @__PURE__ */ React10.createElement(Text10, { dimColor: true, marginTop: 1 }, "(Press Enter to confirm)"));
4108
4167
  case "stats":
4109
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "\u{1F4CA} DAILY USAGE TRACKER"), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Agent Model Calls: ", /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, dailyUsage?.agent || 0)), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Memory Tasks: ", /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, dailyUsage?.background || 0))), /* @__PURE__ */ React10.createElement(Text10, { dimColor: true, marginTop: 1 }, "(Press ESC to return to chat)"));
4168
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, width: 100 }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Session Duration:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionAgentCalls)), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 23 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB API Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 23 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB Tool Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionBackgroundCalls)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, (sessionTotalTokens / 1e3).toFixed(2), "k")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls (Sess):")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionToolSuccess + sessionToolFailure, " ( "), /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u221A ", sessionToolSuccess), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "x ", sessionToolFailure), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " )"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "DAILY USAGE TRACKER"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Wall Time Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatDuration(dailyUsage?.duration || 0))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, dailyUsage?.agent || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, dailyUsage?.background || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Used Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, ((dailyUsage?.tokens || 0) / 1e3).toFixed(2), "k")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, (dailyUsage?.toolSuccess || 0) + (dailyUsage?.toolFailure || 0), " ( "), /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u221A ", dailyUsage?.toolSuccess || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "x ", dailyUsage?.toolFailure || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " )"))), /* @__PURE__ */ React10.createElement(Text10, { dimColor: true, marginTop: 1, italic: true }, "(Press ESC to return to chat)"));
4110
4169
  case "autoExecDanger":
4111
4170
  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 }, "\u26A0\uFE0F SECURITY WARNING: AUTO-EXEC MODE"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "Turning this ON allows the agent to execute terminal commands automatically without requiring your approval for each step."), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1, color: "yellow" }, "RISKS INVOLVED:"), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 The agent may execute destructive commands (rm -rf, etc.) by mistake."), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Unintended system changes if the agent hallucinates a path or command."), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Reduced control over the agent's step-by-step decision making."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
4112
4171
  CommandMenu,
@@ -4202,24 +4261,15 @@ Selection: ${val}`,
4202
4261
  }
4203
4262
  }
4204
4263
  )));
4205
- case "exit":
4206
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "red" }, /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true }, "\u{1F3C1} SESSION DASHBOARD"), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Agent Active For: ", /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, formatDuration(Math.floor((Date.now() - SESSION_START_TIME) / 1e3)))), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Total Model Queries: ", /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, sessionAgentCalls)), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Memory Tasks: ", /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, sessionBackgroundCalls)), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Total Tokens Consumed: ", /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, (sessionTotalTokens / 1e3).toFixed(2), "k"))), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "Are you sure you want to exit?"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
4207
- CommandMenu,
4208
- {
4209
- title: "Exit Confirmation",
4210
- items: [
4211
- { label: "Yes, Shutdown Flux", value: "yes" },
4212
- { label: "No, Back to terminal", value: "no" }
4213
- ],
4214
- onSelect: (item) => {
4215
- if (item.value === "yes") {
4216
- process.exit(0);
4217
- } else {
4218
- setActiveView("chat");
4219
- }
4220
- }
4221
- }
4222
- )));
4264
+ case "exit": {
4265
+ const wallTimeMs = Date.now() - SESSION_START_TIME;
4266
+ const totalTools = sessionToolSuccess + sessionToolFailure;
4267
+ const successRate = totalTools > 0 ? (sessionToolSuccess / totalTools * 100).toFixed(1) : "0.0";
4268
+ const agentActiveMs = sessionApiTime + sessionToolTime;
4269
+ const apiPercent = agentActiveMs > 0 ? (sessionApiTime / agentActiveMs * 100).toFixed(1) : "0.0";
4270
+ const toolPercent = agentActiveMs > 0 ? (sessionToolTime / agentActiveMs * 100).toFixed(1) : "0.0";
4271
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "red", width: 100 }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "Agent powering down. ", /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, "Goodbye!"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "Interaction Summary"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Session ID:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, chatId)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, totalTools, " ( ", /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u221A ", sessionToolSuccess), " ", /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "x ", sessionToolFailure), " )")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Success Rate:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, successRate, "%"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "Performance"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Wall Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(wallTimeMs))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Active:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(agentActiveMs))), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 18 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB API Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionApiTime), " (", apiPercent, "%)")), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 18 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB Tool Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionToolTime), " (", toolPercent, "%)"))));
4272
+ }
4223
4273
  case "ask":
4224
4274
  return /* @__PURE__ */ React10.createElement(Box10, { width: "100%" }, /* @__PURE__ */ React10.createElement(
4225
4275
  AskUserModal_default,
@@ -4515,7 +4565,7 @@ var init_app = __esm({
4515
4565
  init_setup();
4516
4566
  SESSION_START_TIME = Date.now();
4517
4567
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
4518
- versionFluxflow = "1.7.0";
4568
+ versionFluxflow = "1.7.1";
4519
4569
  updatedOn = "2026-05-03";
4520
4570
  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 (turn: finish) 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(
4521
4571
  CommandMenu,
@@ -4578,5 +4628,5 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
4578
4628
  console.warn = (...args) => !isNoise(args) && originalWarn(...args);
4579
4629
  console.error = (...args) => !isNoise(args) && originalError(...args);
4580
4630
  process.stdout.write("\x1Bc");
4581
- render(/* @__PURE__ */ React11.createElement(App2, null));
4631
+ render(/* @__PURE__ */ React11.createElement(App2, null), { exitOnCtrlC: false });
4582
4632
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",