fluxflow-cli 1.7.15 → 1.7.17

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 +116 -66
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -10,7 +10,7 @@ var __export = (target, all) => {
10
10
  };
11
11
 
12
12
  // src/utils/text.js
13
- var wrapText;
13
+ var wrapText, formatTokens;
14
14
  var init_text = __esm({
15
15
  "src/utils/text.js"() {
16
16
  wrapText = (text, width) => {
@@ -44,6 +44,16 @@ var init_text = __esm({
44
44
  });
45
45
  return finalLines.join("\n");
46
46
  };
47
+ formatTokens = (tokens) => {
48
+ if (!tokens && tokens !== 0) return "0.0k";
49
+ const num = typeof tokens === "string" ? parseFloat(tokens) : tokens;
50
+ if (num >= 1e6) {
51
+ return `${(num / 1e6).toFixed(2)}m`;
52
+ } else if (num >= 1e3) {
53
+ return `${(num / 1e3).toFixed(2)}k`;
54
+ }
55
+ return num.toString();
56
+ };
47
57
  }
48
58
  });
49
59
 
@@ -65,7 +75,7 @@ var init_TerminalBox = __esm({
65
75
  // src/components/ChatLayout.jsx
66
76
  import React2, { useState, useEffect, useRef } from "react";
67
77
  import { Box as Box2, Text as Text2 } from "ink";
68
- var TypewriterText, cleanSignals, formatThinkText, InlineMarkdown, TableRenderer, MarkdownText, DiffLine, DiffBlock, CodeRenderer, MessageItem, ChatLayout, ChatLayout_default;
78
+ var TypewriterText, cleanSignals, formatThinkText, parseMathSymbols, InlineMarkdown, TableRenderer, MarkdownText, DiffLine, DiffBlock, CodeRenderer, MessageItem, ChatLayout, ChatLayout_default;
69
79
  var init_ChatLayout = __esm({
70
80
  "src/components/ChatLayout.jsx"() {
71
81
  init_TerminalBox();
@@ -158,6 +168,9 @@ var init_ChatLayout = __esm({
158
168
  return /* @__PURE__ */ React2.createElement(Box2, { key: i, marginLeft: isBullet ? 2 : 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { italic: true, color: "gray" }, bulletPrefix, wrapped.split("\n").join("\n" + " ".repeat(bulletPrefix.length))));
159
169
  });
160
170
  };
171
+ parseMathSymbols = (content) => {
172
+ return content.replace(/\\multiply|\\mul|\\times/g, "\xD7").replace(/\\div/g, "\xF7").replace(/\\cdot/g, "\u22C5").replace(/\\infty/g, "\u221E").replace(/\\pm/g, "\xB1").replace(/\\leq/g, "\u2264").replace(/\\geq/g, "\u2265").replace(/\\neq/g, "\u2260").replace(/\\sqrt\{?(.*?)\}?/g, (_, p1) => `\u221A(${p1})`).replace(/\\alpha/g, "\u03B1").replace(/\\beta/g, "\u03B2").replace(/\\theta/g, "\u03B8").replace(/\\pi/g, "\u03C0").replace(/\\approx/g, "\u2248").replace(/\\Delta/g, "\u0394").replace(/\\sigma/g, "\u03C3").replace(/\\sum/g, "\u03A3").replace(/\\prod/g, "\u03A0").replace(/\\rightarrow|\\to/g, "\u2192").replace(/\\leftarrow/g, "\u2190").replace(/\\leftrightarrow/g, "\u2194").replace(/\\left\(|\\right\)/g, (match) => match.includes("left") ? "(" : ")").replace(/\\left\[|\\right\]/g, (match) => match.includes("left") ? "[" : "]").replace(/\\\{|\\\}/g, (match) => match.includes("{") ? "{" : "}").replace(/\\text\{?(.*?)\}?/g, "$1");
173
+ };
161
174
  InlineMarkdown = React2.memo(({ text, color }) => {
162
175
  if (!text) return null;
163
176
  const parts = text.split(/(\*\*.*?\*\*|\*.*?\*|`.*?`|\$.*?\$|\[.*?\]\s*\(.*?\)|\[.*?\]\s*\[.*?\]|https?:\/\/[^\s]+)/g);
@@ -173,12 +186,23 @@ var init_ChatLayout = __esm({
173
186
  return /* @__PURE__ */ React2.createElement(Text2, { key: j, color: "cyan", backgroundColor: "#003333" }, " ", part.slice(1, -1), " ");
174
187
  }
175
188
  if (part.startsWith("$") && part.endsWith("$")) {
176
- let content = part.slice(1, -1);
177
- if (content.startsWith("\\text{") && content.endsWith("}")) {
178
- content = content.slice(6, -1);
179
- }
180
- const mathContent = content.replace(/\\multiply/g, "\xD7").replace(/\\mul/g, "\xD7").replace(/\\times /g, "\xD7").replace(/\\div /g, "\xF7").replace(/\\cdot /g, "\u22C5").replace(/\\infty/g, "\u221E").replace(/\\pm/g, "\xB1").replace(/\\leq/g, "\u2264").replace(/\\geq/g, "\u2265").replace(/\\neq/g, "\u2260").replace(/\\left/g, "<").replace(/\\right/g, ">").replace(/\\left\(/g, "(").replace(/\\right\)/g, ")").replace(/\\sqrt/g, "\u221A").replace(/\\sqrt\[3\]/g, "\u221B").replace(/\\alpha/g, "\u03B1").replace(/\\beta/g, "\u03B2").replace(/\\theta/g, "\u03B8").replace(/\\phi/g, "\u03C6").replace(/\\delta/g, "\u03B4").replace(/\\gamma/g, "\u03B3").replace(/\\sigma/g, "\u03C3").replace(/\\pi/g, "\u03C0").replace(/\\sum/g, "\u03A3").replace(/\\lim/g, "lim").replace(/\\integral/g, "\u222B").replace(/\\diff/g, "d").replace(/\\partial/g, "\u2202").replace(/\\frac/g, "/");
181
- return /* @__PURE__ */ React2.createElement(Text2, { key: j, color: "white", backgroundColor: "#4c0099", bold: true, italic: true }, " ", mathContent, " ");
189
+ const content = part.slice(1, -1);
190
+ const latexParts = content.split(/(\\(?:mathbf|textbf|textit|underline|text|mathrm|textsf|texttt)\{.*?\})/g);
191
+ return /* @__PURE__ */ React2.createElement(Text2, { key: j, color: "yellow" }, latexParts.map((lp, lpi) => {
192
+ if (lp.startsWith("\\")) {
193
+ const match = lp.match(/\\(\w+)\{(.*?)\}/);
194
+ if (match) {
195
+ const cmd = match[1];
196
+ const inner = match[2];
197
+ const isBold = cmd === "mathbf" || cmd === "textbf";
198
+ const isItalic = cmd === "textit";
199
+ const isUnderline = cmd === "underline";
200
+ const isMono = cmd === "texttt";
201
+ return /* @__PURE__ */ React2.createElement(Text2, { key: lpi, bold: isBold, italic: isItalic, underline: isUnderline, color: isMono ? "cyan" : void 0 }, parseMathSymbols(inner));
202
+ }
203
+ }
204
+ return /* @__PURE__ */ React2.createElement(Text2, { key: lpi }, parseMathSymbols(lp));
205
+ }));
182
206
  }
183
207
  if (part.startsWith("[") && (part.includes("](") || part.includes("] ("))) {
184
208
  const match = part.match(/\[(.*?)\]\s*\((.*?)\)/);
@@ -431,6 +455,7 @@ import { Box as Box3, Text as Text3 } from "ink";
431
455
  var StatusBar, StatusBar_default;
432
456
  var init_StatusBar = __esm({
433
457
  "src/components/StatusBar.jsx"() {
458
+ init_text();
434
459
  StatusBar = React3.memo(({ mode, thinkingLevel, tokens = "0.0k", tokensTotal = "0.0k", chatId = "NEW-SESSION", isMemoryEnabled = true }) => {
435
460
  const modeColor = mode === "Flux" ? "yellow" : "cyan";
436
461
  const modeIcon = mode === "Flux" ? "\u26A1" : "\u{1F30A}";
@@ -447,7 +472,7 @@ var init_StatusBar = __esm({
447
472
  },
448
473
  /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: modeColor, bold: true }, modeIcon, " ", mode.toUpperCase()), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "magenta" }, "\u{1F9E0} ", thinkingLevel)),
449
474
  /* @__PURE__ */ React3.createElement(Box3, { flexGrow: 1, justifyContent: "center", paddingX: 2 }, /* @__PURE__ */ React3.createElement(Text3, { color: "gray", dimColor: true }, "\u{1F4C1} "), /* @__PURE__ */ React3.createElement(Text3, { color: "blue", dimColor: true, italic: true }, process.cwd())),
450
- /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, "MEM: "), /* @__PURE__ */ React3.createElement(Text3, { color: memStatus === "ON" ? "green" : "red" }, memStatus), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "blue" }, tokensTotal > 1e3 ? `${(tokensTotal / 1e3).toFixed(1)}k` : tokensTotal, " (", Math.round(tokens / 254e3 * 100), "%)"), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "dim" }, chatId, " "))
475
+ /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, "MEM: "), /* @__PURE__ */ React3.createElement(Text3, { color: memStatus === "ON" ? "green" : "red" }, memStatus), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "blue" }, formatTokens(tokensTotal), " (", Math.round(tokens / 254e3 * 100), "%)"), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "dim" }, chatId, " "))
451
476
  );
452
477
  });
453
478
  StatusBar_default = StatusBar;
@@ -764,10 +789,10 @@ var thinking_prompts_default;
764
789
  var init_thinking_prompts = __esm({
765
790
  "src/data/thinking_prompts.json"() {
766
791
  thinking_prompts_default = {
767
- Max: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: MAX\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading**\n\\n\\n\nSelf MONOLOGUE\n\\n\\n\n**Heading**\n\\n\\n\nSelf MONOLOGUE\ncontinue.\n\\n\\n\n</think>\\n\\n\n\n(MUST START THE RESPONSE IN NEW LINE AFTER ENDING THINKING BLOCK)\n\n**CRITICAL**: Heading blocks: **MIN 9**, **MAX 14**. EACH HEADING SHOULD HAVE MIN 8, MAX 12 SENTENCES OF INTERNAL MONOLOGUE. EXPLORE EDGE CASES & NUANCES. Dynamic Thinking preferred based on query.\nNEVER WRITE FUNCTION CALLS IN THINKING BLOCK WITH 'tool:' PREFIX AND NEVER WRITE '[turn: ...]' INSIDE THINKING BLOCK.\nConverge Thinking & Avoid running into thinking Loops. YOU MUST NOT EXCEED ALLOTTED THINKING BUDGET. COMPLETE YOUR THINKING WITHIN LIMITS AND START YOUR RESPONSE. DEFINE YOUR DYNAMIC THINKING BUDGET BASED ON THE QUERY COMPLEXITY. DO NOT OVERTHINK SIMPLE ONES. If a query is really simple and thinking for MIN heading is waste of compute, you can stop thinking before MIN HEADING rule. BUT FOR COMPLEX QUERIES UTILIZE THE BUDGET.\n-- END THINKING INSTRUCTIONS --",
768
- High: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: HIGH\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading**\n\\n\\n\nSelf MONOLOGUE\n\\n\\n\n**Heading**\n\\n\\n\nSelf MONOLOGUE\ncontinue.\n\\n\\n\n</think>\\n\\n\n\n(MUST START THE RESPONSE IN NEW LINE AFTER ENDING THINKING BLOCK)\n\n**CRITICAL**: Heading blocks: **MIN 8**, **MAX 11**. EACH HEADING SHOULD HAVE MIN 4, MAX 8 SENTENCES OF INTERNAL MONOLOGUE. EXPLORE EDGE CASES & THINK LONGER before responding. Dynamic Thinking preferred based on query.\nNEVER WRITE FUNCTION CALLS IN THINKING BLOCK WITH 'tool:' PREFIX AND NEVER WRITE '[turn: ...]' INSIDE THINKING BLOCK.\nConverge Thinking & Avoid running into thinking Loops. YOU MUST NOT EXCEED ALLOTTED THINKING BUDGET. COMPLETE YOUR THINKING WITHIN LIMITS AND START YOUR RESPONSE. DEFINE YOUR DYNAMIC THINKING BUDGET BASED ON THE QUERY COMPLEXITY. DO NOT OVERTHINK SIMPLE ONES. If a query is really simple and thinking for MIN heading is waste of compute, you can stop thinking before MIN HEADING rule. BUT FOR COMPLEX QUERIES UTILIZE THE BUDGET.\n-- END THINKING INSTRUCTIONS --",
769
- Medium: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: MEDIUM\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading**\n\\n\\n\nSelf MONOLOGUE\n\\n\\n\n**Heading**\n\\n\\n\nSelf MONOLOGUE\ncontinue.\n\\n\\n\n</think>\\n\\n\n\n(MUST START THE RESPONSE IN NEW LINE AFTER ENDING THINKING BLOCK)\n\n**CRITICAL**: Heading blocks: **MIN 3**, **MAX 5**. EACH HEADING SHOULD HAVE MIN 2, MAX 4 SENTENCES OF INTERNAL MONOLOGUE. THINK LONGER FOR COMPLEX QUERIES. Dynamic Thinking preferred based on query.\nNEVER WRITE FUNCTION CALLS IN THINKING BLOCK WITH 'tool:' PREFIX AND NEVER WRITE '[turn: ...]' INSIDE THINKING BLOCK.\nConverge Thinking & Avoid running into thinking Loops. YOU MUST NOT EXCEED ALLOTTED THINKING BUDGET. COMPLETE YOUR THINKING WITHIN LIMITS AND START YOUR RESPONSE. DEFINE YOUR DYNAMIC THINKING BUDGET BASED ON THE QUERY COMPLEXITY. DO NOT OVERTHINK SIMPLE ONES. If a query is really simple and thinking for MIN heading is waste of compute, you can stop thinking before MIN HEADING rule. BUT FOR COMPLEX QUERIES UTILIZE THE BUDGET.\n-- END THINKING INSTRUCTIONS --",
770
- Minimal: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: LOW\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading**\n\\n\\n\nSelf MONOLOGUE\n\\n\\n\n**Heading**\n\\n\\n\nSelf MONOLOGUE\ncontinue.\n\\n\\n\n</think>\\n\\n\n\n(MUST START THE RESPONSE IN NEW LINE AFTER ENDING THINKING BLOCK)\n\n**CRITICAL**: Heading blocks: **MIN 0**, **MAX 2**. EACH HEADING SHOULD HAVE MIN 1, MAX 3 SENTENCES OF INTERNAL MONOLOGUE. No Thinking is preferred if query is simple.\nNEVER WRITE FUNCTION CALLS IN THINKING BLOCK WITH 'tool:' PREFIX AND NEVER WRITE '[turn: ...]' INSIDE THINKING BLOCK.\nConverge Thinking & Avoid running into thinking Loops. YOU MUST NOT EXCEED ALLOTTED THINKING BUDGET. COMPLETE YOUR THINKING WITHIN LIMITS AND START YOUR RESPONSE. DEFINE YOUR DYNAMIC THINKING BUDGET BASED ON THE QUERY COMPLEXITY. DO NOT OVERTHINK SIMPLE ONES. If a query is really simple and thinking for MIN heading is waste of compute, you can stop thinking before MIN HEADING rule. BUT FOR COMPLEX QUERIES UTILIZE THE BUDGET.\n-- END THINKING INSTRUCTIONS --"
792
+ Max: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: MAX\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading**\n\\n\\n\nSELF-MONOLOGUE\n\\n\\n\n**Heading**\n\\n\\n\nSelf MONOLOGUE\ncontinue.\n\\n\\n\n</think>\n\nRULES OF THINKING: -HEADING COUNT SHOULD BE 12 - 20. SELF-MONOLOGUE SHOULD BE DETAILED AND THROROUGH. MONOLOGUES **MUST** BE **8 - 12** LINES EACH REGARDLESS OF QUERY COMPLEXITY.\n- YOU MUST **NOT** EXCREED YOUR ALLOTED THINKING BUDGET UNDER **ANY** CIRCUMSTANCES.\n- IF THE QUERY IS SIMPLE, YOU CAN KEEP HEADING COUNT LESS THAN MIN COUNT.\n- CONSIDER ABOUT EDGE CASES BEFORE COMMITING.\n- SHOULD PLAN ARCHITECHTURALLY.\n- SHOULD PLAN LOGICALLY.\n\n-- END THINKING INSTRUCTIONS --",
793
+ High: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: HIGH\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading**\n\\n\\n\nSELF-MONOLOGUE\n\\n\\n\n**Heading**\n\\n\\n\nSelf MONOLOGUE\ncontinue.\n\\n\\n\n</think>\n\nnRULES OF THINKING: -HEADING COUNT SHOULD BE 8 - 12. SELF-MONOLOGUE SHOULD BE DETAILED AND THROROUGH. MONOLOGUES **MUST** BE **6 - 8** LINES EACH REGARDLESS OF QUERY COMPLEXITY.\n- YOU MUST **NOT** EXCREED YOUR ALLOTED THINKING BUDGET UNDER **ANY** CIRCUMSTANCES.\n- IF THE QUERY IS SIMPLE, YOU CAN KEEP HEADING COUNT LESS THAN MIN COUNT.\n- CONSIDER ABOUT EDGE CASES BEFORE COMMITING.\n\n-- END THINKING INSTRUCTIONS --",
794
+ Medium: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: MEDIUM\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading**\n\\n\\n\nSELF-MONOLOGUE\n\\n\\n\n**Heading**\n\\n\\n\nSelf MONOLOGUE\ncontinue.\n\\n\\n\n</think>\n\nnRULES OF THINKING: -HEADING COUNT SHOULD BE 2 - 4. SELF-MONOLOGUE SHOULD BE SHORT YET THROROUGH. MONOLOGUES **MUST** BE **4 - 6** LINES EACH REGARDLESS OF QUERY COMPLEXITY.\n- YOU MUST **NOT** EXCREED YOUR ALLOTED THINKING BUDGET UNDER **ANY** CIRCUMSTANCES.\n- IF THE QUERY IS SIMPLE, YOU CAN KEEP HEADING COUNT LESS THAN MIN COUNT.\n- LITTLE TO NO THINKING IS PREFFERED IF QUERY IS CONVERSATIONAL AND SIMPLE.\n\n-- END THINKING INSTRUCTIONS --",
795
+ Minimal: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: LOW\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading**\n\\n\\n\nSELF-MONOLOGUE\n\\n\\n\n**Heading**\n\\n\\n\nSelf MONOLOGUE\ncontinue.\n\\n\\n\n</think>\n\nnRULES OF THINKING: -HEADING COUNT SHOULD BE 0 - 2. SELF-MONOLOGUE SHOULD BE SHORT AND CONCISE. MONOLOGUES **MUST** BE **1 - 2** LINES EACH REGARDLESS OF QUERY COMPLEXITY.\n- YOU MUST **NOT** EXCREED YOUR ALLOTED THINKING BUDGET UNDER **ANY** CIRCUMSTANCES.\n- IF THE QUERY IS SIMPLE, YOU CAN KEEP HEADING COUNT LESS THAN MIN COUNT.\n- NO THINKING IS PREFFERED IF QUERY IS CONVERSATIONAL AND SIMPLE.\n\n-- END THINKING INSTRUCTIONS --"
771
796
  };
772
797
  }
773
798
  });
@@ -1001,29 +1026,21 @@ var init_history = __esm({
1001
1026
  // src/utils/usage.js
1002
1027
  import fs5 from "fs-extra";
1003
1028
  import path5 from "path";
1004
- var getDailyUsage, incrementUsage, addToUsage, checkQuota;
1029
+ var cachedUsage, writeTimeout, lastWriteTime, isDirty, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, incrementUsage, addToUsage, checkQuota;
1005
1030
  var init_usage = __esm({
1006
1031
  "src/utils/usage.js"() {
1007
1032
  init_paths();
1008
- getDailyUsage = async () => {
1033
+ cachedUsage = null;
1034
+ writeTimeout = null;
1035
+ lastWriteTime = 0;
1036
+ isDirty = false;
1037
+ loadUsageFromFile = async () => {
1009
1038
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1010
1039
  try {
1011
1040
  if (await fs5.exists(USAGE_FILE)) {
1012
1041
  const data = await fs5.readJson(USAGE_FILE);
1013
1042
  if (data && data.date === today && data.stats) {
1014
- const s = data.stats;
1015
- const normalized = {
1016
- agent: s.agent || 0,
1017
- background: s.background || 0,
1018
- search: s.search || 0,
1019
- toolSuccess: s.toolSuccess || 0,
1020
- toolFailure: s.toolFailure || 0,
1021
- duration: s.duration || 0,
1022
- tokens: s.tokens || 0
1023
- };
1024
- return normalized;
1025
- } else if (data && data.date !== today) {
1026
- } else {
1043
+ return data;
1027
1044
  }
1028
1045
  }
1029
1046
  } catch (err) {
@@ -1037,52 +1054,77 @@ var init_usage = __esm({
1037
1054
  duration: 0,
1038
1055
  tokens: 0
1039
1056
  };
1057
+ return { date: today, stats: defaultStats };
1058
+ };
1059
+ flushUsage = async () => {
1060
+ if (!isDirty || !cachedUsage) return;
1040
1061
  try {
1041
1062
  await fs5.ensureDir(path5.dirname(USAGE_FILE));
1042
1063
  const tempFile = USAGE_FILE + ".tmp";
1043
- await fs5.writeJson(tempFile, { date: today, stats: defaultStats }, { spaces: 2 });
1064
+ await fs5.writeJson(tempFile, cachedUsage, { spaces: 2 });
1044
1065
  const fd = await fs5.open(tempFile, "r+");
1045
1066
  await fs5.fsync(fd);
1046
1067
  await fs5.close(fd);
1047
1068
  await fs5.rename(tempFile, USAGE_FILE);
1069
+ isDirty = false;
1070
+ lastWriteTime = Date.now();
1048
1071
  } catch (e) {
1049
1072
  }
1050
- return defaultStats;
1051
1073
  };
1052
- incrementUsage = async (key) => {
1074
+ queueFlush = () => {
1075
+ isDirty = true;
1076
+ if (writeTimeout) return;
1077
+ const now = Date.now();
1078
+ const delay = Math.max(0, 1500 - (now - lastWriteTime));
1079
+ writeTimeout = setTimeout(async () => {
1080
+ await flushUsage();
1081
+ writeTimeout = null;
1082
+ }, delay);
1083
+ };
1084
+ initUsage = async () => {
1085
+ cachedUsage = await loadUsageFromFile();
1086
+ };
1087
+ forceFlushUsage = async () => {
1088
+ if (writeTimeout) {
1089
+ clearTimeout(writeTimeout);
1090
+ writeTimeout = null;
1091
+ }
1092
+ await flushUsage();
1093
+ };
1094
+ getDailyUsage = async () => {
1053
1095
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1096
+ if (!cachedUsage) {
1097
+ cachedUsage = await loadUsageFromFile();
1098
+ } else if (cachedUsage.date !== today) {
1099
+ cachedUsage = {
1100
+ date: today,
1101
+ stats: {
1102
+ agent: 0,
1103
+ background: 0,
1104
+ search: 0,
1105
+ toolSuccess: 0,
1106
+ toolFailure: 0,
1107
+ duration: 0,
1108
+ tokens: 0
1109
+ }
1110
+ };
1111
+ isDirty = true;
1112
+ await flushUsage();
1113
+ }
1114
+ return cachedUsage.stats;
1115
+ };
1116
+ incrementUsage = async (key) => {
1054
1117
  const stats = await getDailyUsage();
1055
- const data = { date: today, stats };
1056
- if (data.stats[key] !== void 0) {
1057
- data.stats[key]++;
1058
- try {
1059
- await fs5.ensureDir(path5.dirname(USAGE_FILE));
1060
- const tempFile = USAGE_FILE + ".tmp";
1061
- await fs5.writeJson(tempFile, data, { spaces: 2 });
1062
- const fd = await fs5.open(tempFile, "r+");
1063
- await fs5.fsync(fd);
1064
- await fs5.close(fd);
1065
- await fs5.rename(tempFile, USAGE_FILE);
1066
- } catch (e) {
1067
- }
1118
+ if (stats[key] !== void 0) {
1119
+ stats[key]++;
1120
+ queueFlush();
1068
1121
  }
1069
1122
  };
1070
1123
  addToUsage = async (key, amount) => {
1071
- const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1072
1124
  const stats = await getDailyUsage();
1073
- const data = { date: today, stats };
1074
- if (data.stats[key] !== void 0) {
1075
- data.stats[key] += Math.floor(amount);
1076
- try {
1077
- await fs5.ensureDir(path5.dirname(USAGE_FILE));
1078
- const tempFile = USAGE_FILE + ".tmp";
1079
- await fs5.writeJson(tempFile, data, { spaces: 2 });
1080
- const fd = await fs5.open(tempFile, "r+");
1081
- await fs5.fsync(fd);
1082
- await fs5.close(fd);
1083
- await fs5.rename(tempFile, USAGE_FILE);
1084
- } catch (e) {
1085
- }
1125
+ if (stats[key] !== void 0) {
1126
+ stats[key] += Math.floor(amount);
1127
+ queueFlush();
1086
1128
  }
1087
1129
  };
1088
1130
  checkQuota = async (key, settings) => {
@@ -1098,8 +1140,7 @@ var init_usage = __esm({
1098
1140
  if (tier === "Paid" || tier === "Custom") {
1099
1141
  if (key === "agent") return usage.agent < (quotas.agentLimit || 1500);
1100
1142
  if (key === "background") return usage.background < (quotas.backgroundLimit || 1500);
1101
- if (key === "search") return true;
1102
- return true;
1143
+ if (key === "search") return usage.search < (quotas.searchLimit || 100);
1103
1144
  }
1104
1145
  return true;
1105
1146
  };
@@ -2517,9 +2558,15 @@ USER_PROMPT: ${agentText}`.trim();
2517
2558
  }
2518
2559
  const thinkBlocks = turnText.match(/<think>([\s\S]*?)(?:<\/think>|$)/gi) || [];
2519
2560
  const thinkContent = thinkBlocks.join("");
2520
- const headingsCount = (thinkContent.match(/\*\*.*?\*\*/g) || []).length;
2521
- if (headingsCount > 35) {
2522
- yield { type: "status", content: "Loop Detected. Restarting internal loop." };
2561
+ const headingsCount = (thinkContent.match(/^\s*\*\*.*?\*\*\s*$/gm) || []).length;
2562
+ const headingSections = thinkContent.split(/^\s*\*\*.*?\*\*\s*$/gm);
2563
+ const isOverVerbose = headingSections.some((section) => {
2564
+ const wordCount = section.trim().split(/\s+/).filter((w) => w.length > 0).length;
2565
+ return wordCount > 450;
2566
+ });
2567
+ if (headingsCount > 25 || isOverVerbose) {
2568
+ const reason = headingsCount > 25 ? "Loop Detected" : "Noise Detected";
2569
+ yield { type: "status", content: `${reason}. Auto-adjusting...` };
2523
2570
  await new Promise((resolve) => setTimeout(resolve, 3e3));
2524
2571
  break;
2525
2572
  }
@@ -3350,6 +3397,7 @@ Check what's new using \`/changelog\` command.`,
3350
3397
  cleanupOldHistory(saved.systemSettings.autoDeleteHistory);
3351
3398
  }
3352
3399
  performVersionCheck(false, freshSettings);
3400
+ await initUsage();
3353
3401
  setIsInitializing(false);
3354
3402
  }
3355
3403
  init();
@@ -3388,6 +3436,7 @@ Check what's new using \`/changelog\` command.`,
3388
3436
  await addToUsage("duration", deltaSecs);
3389
3437
  lastSavedTimeRef.current += deltaSecs * 1e3;
3390
3438
  }
3439
+ await forceFlushUsage();
3391
3440
  };
3392
3441
  flush();
3393
3442
  const timer = setTimeout(() => {
@@ -4281,7 +4330,7 @@ Selection: ${val}`,
4281
4330
  }
4282
4331
  )), /* @__PURE__ */ React10.createElement(Text10, { dimColor: true, marginTop: 1 }, "(Press Enter to confirm)"));
4283
4332
  case "stats":
4284
- 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" }, "\u2713 ", 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" }, "\u2713 ", 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)"));
4333
+ 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" }, formatTokens(sessionTotalTokens))), /* @__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" }, "\u2713 ", 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" }, formatTokens(dailyUsage?.tokens || 0))), /* @__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" }, "\u2713 ", 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)"));
4285
4334
  case "autoExecDanger":
4286
4335
  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(
4287
4336
  CommandMenu,
@@ -4629,7 +4678,7 @@ Selection: ${val}`,
4629
4678
  const agentActiveMs = sessionApiTime + sessionToolTime;
4630
4679
  const apiPercent = agentActiveMs > 0 ? (sessionApiTime / agentActiveMs * 100).toFixed(1) : "0.0";
4631
4680
  const toolPercent = agentActiveMs > 0 ? (sessionToolTime / agentActiveMs * 100).toFixed(1) : "0.0";
4632
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "red", width: 100, marginTop: 1 }, /* @__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" }, "\u2713 ", 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, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, (sessionTotalTokens / 1e3).toFixed(2), "k"))), /* @__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, "%)"))));
4681
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "red", width: 100, marginTop: 1 }, /* @__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" }, "\u2713 ", 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, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(sessionTotalTokens)))), /* @__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, "%)"))));
4633
4682
  })(), suggestions.length > 0 && (() => {
4634
4683
  const windowSize = 5;
4635
4684
  const startIdx = Math.max(0, Math.min(selectedIndex - 2, suggestions.length - windowSize));
@@ -4680,9 +4729,10 @@ var init_app = __esm({
4680
4729
  init_terminal();
4681
4730
  init_exec_command();
4682
4731
  init_setup();
4732
+ init_text();
4683
4733
  SESSION_START_TIME = Date.now();
4684
4734
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
4685
- versionFluxflow = "1.7.15";
4735
+ versionFluxflow = "1.7.17";
4686
4736
  updatedOn = "2026-05-05";
4687
4737
  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(
4688
4738
  CommandMenu,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.7.15",
3
+ "version": "1.7.17",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",