fluxflow-cli 2.7.13 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/fluxflow.js +185 -19
  2. package/package.json +2 -2
package/dist/fluxflow.js CHANGED
@@ -2194,7 +2194,7 @@ Internal tools. MUST use the EXACT syntax '[tool:functions.ToolName(args)]'. **N
2194
2194
 
2195
2195
  **TOOL USAGE POLICY:**
2196
2196
  - **MAX 3 TOOL CALLS PER TURN${mode === "Flux" ? " (EXCEPTION FOR Todo TOOL: 3+ CALLS ALLOWED)" : ""}. Next Turn, verify tool results, plan next**
2197
- ${mode === "Flux" ? "- USE multiple search & replace on patch tool if editing same file/path with many changes \u2190 **HIGHLY RECOMMENDED**\n- Tool execution denied? MUST use 'Ask' tool immediately for user reason/changes. NEVER END RESPONSE OR PROCEED BLINDLY \u2190 **MANDATORY**\n- FileMap >> ReadFile to understand file efficiently\n- Want spefific STRING across project/file? SearchKeyword >> Guessing/ReadFile\n- HUGE FILES? SearchKeyword >> FileMap\n- MUST MARK DONE/APPEND Todos BASED ON REALTIME TASK PROGRESS ON EACH TURN" : ""}
2197
+ ${mode === "Flux" ? "- USE multiple search & replace on patch tool if editing same file/path with many changes \u2190 **HIGHLY RECOMMENDED**\n- Tool execution denied? MUST use 'Ask' tool immediately for user reason/changes. NEVER END RESPONSE OR PROCEED BLINDLY \u2190 **MANDATORY**\n- FileMap >> ReadFile to understand file efficiently\n- Want spefific STRING across project/file? SearchKeyword >> Guessing/ReadFile\n- HUGE FILES? SearchKeyword >> FileMap/Full File read\n- MUST MARK DONE/APPEND Todos BASED ON REALTIME TASK PROGRESS ON EACH TURN outside 3 call limit" : ""}
2198
2198
  ${mode === "Flux" ? "- **File Tools >> Code in chat**\n\n" : ""}- COMMUNICATION TOOLS -
2199
2199
  1. [tool:functions.Ask(question="...", optionA="option::description", ...MAX 4)]. Ambiguity Resolution. Mandatory Triggers: Path Divergence, Security, Risk Mitigation. ask >> finish. Suggest best options; don't ask for preferences
2200
2200
 
@@ -3910,7 +3910,7 @@ var init_history = __esm({
3910
3910
  import fs8 from "fs-extra";
3911
3911
  import path7 from "path";
3912
3912
  import os3 from "os";
3913
- var getLocalBackupPath, BACKUP_FILE, generateSaveId, cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, incrementUsage, addToUsage, checkQuota, getImageQuotaBuckets, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
3913
+ var getLocalBackupPath, BACKUP_FILE, generateSaveId, cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, purgeOldHistory, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, getMonthlyUsage, incrementUsage, addToUsage, checkQuota, getImageQuotaBuckets, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
3914
3914
  var init_usage = __esm({
3915
3915
  "src/utils/usage.js"() {
3916
3916
  init_paths();
@@ -3947,6 +3947,19 @@ var init_usage = __esm({
3947
3947
  linesRemoved: 0,
3948
3948
  imageCalls: []
3949
3949
  };
3950
+ purgeOldHistory = (history, todayStr) => {
3951
+ if (!history) return {};
3952
+ const keys = Object.keys(history);
3953
+ const thirtyDaysAgo = new Date(new Date(todayStr).getTime() - 30 * 24 * 60 * 60 * 1e3);
3954
+ const purged = {};
3955
+ for (const key of keys) {
3956
+ const keyDate = new Date(key);
3957
+ if (keyDate >= thirtyDaysAgo) {
3958
+ purged[key] = history[key];
3959
+ }
3960
+ }
3961
+ return purged;
3962
+ };
3950
3963
  loadUsageFromFile = async () => {
3951
3964
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
3952
3965
  const tempFile = USAGE_FILE + ".tmp";
@@ -4031,17 +4044,38 @@ var init_usage = __esm({
4031
4044
  } catch (e) {
4032
4045
  }
4033
4046
  }
4034
- if (resolvedData && resolvedData.date === today && resolvedData.stats) {
4035
- const mergedStats = { ...defaultStats, ...resolvedData.stats };
4047
+ if (resolvedData) {
4048
+ const stats = resolvedData.stats || { ...defaultStats };
4049
+ const mergedStats = { ...defaultStats, ...stats };
4036
4050
  if (!Array.isArray(mergedStats.imageCalls)) {
4037
4051
  mergedStats.imageCalls = [];
4038
4052
  }
4039
- return {
4040
- ...resolvedData,
4041
- stats: mergedStats
4042
- };
4053
+ const history = resolvedData.history || {};
4054
+ if (resolvedData.date === today) {
4055
+ return {
4056
+ ...resolvedData,
4057
+ stats: mergedStats,
4058
+ history
4059
+ };
4060
+ } else {
4061
+ const oldDate = resolvedData.date;
4062
+ const oldStats = mergedStats;
4063
+ const updatedHistory = { ...history };
4064
+ if (oldDate) {
4065
+ updatedHistory[oldDate] = oldStats;
4066
+ }
4067
+ return {
4068
+ date: today,
4069
+ stats: { ...defaultStats },
4070
+ history: purgeOldHistory(updatedHistory, today)
4071
+ };
4072
+ }
4043
4073
  }
4044
- return { date: today, stats: { ...defaultStats } };
4074
+ return {
4075
+ date: today,
4076
+ stats: { ...defaultStats },
4077
+ history: {}
4078
+ };
4045
4079
  };
4046
4080
  flushUsage = async () => {
4047
4081
  if (!isDirty || !cachedUsage) return;
@@ -4078,6 +4112,31 @@ var init_usage = __esm({
4078
4112
  }
4079
4113
  }
4080
4114
  }
4115
+ if (diskData && diskData.history) {
4116
+ const mergedHistory = { ...cachedUsage.history || {} };
4117
+ for (const dateKey in diskData.history) {
4118
+ if (mergedHistory[dateKey]) {
4119
+ for (const key in mergedHistory[dateKey]) {
4120
+ if (key === "imageCalls") {
4121
+ const diskArr = Array.isArray(diskData.history[dateKey].imageCalls) ? diskData.history[dateKey].imageCalls : [];
4122
+ const memArr = Array.isArray(mergedHistory[dateKey].imageCalls) ? mergedHistory[dateKey].imageCalls : [];
4123
+ const uniqueMap = /* @__PURE__ */ new Map();
4124
+ for (const item of [...diskArr, ...memArr]) {
4125
+ if (item && item.timestamp) {
4126
+ uniqueMap.set(item.timestamp, item);
4127
+ }
4128
+ }
4129
+ mergedHistory[dateKey].imageCalls = Array.from(uniqueMap.values());
4130
+ } else if (typeof mergedHistory[dateKey][key] === "number") {
4131
+ mergedHistory[dateKey][key] = Math.max(mergedHistory[dateKey][key], Number(diskData.history[dateKey][key]) || 0);
4132
+ }
4133
+ }
4134
+ } else {
4135
+ mergedHistory[dateKey] = diskData.history[dateKey];
4136
+ }
4137
+ }
4138
+ cachedUsage.history = mergedHistory;
4139
+ }
4081
4140
  cachedUsage.saveId = generateSaveId();
4082
4141
  const tempFile = USAGE_FILE + ".tmp";
4083
4142
  const encryptedStr = encryptAes(JSON.stringify(cachedUsage, null, 2));
@@ -4122,9 +4181,16 @@ var init_usage = __esm({
4122
4181
  if (!cachedUsage) {
4123
4182
  cachedUsage = await loadUsageFromFile();
4124
4183
  } else if (cachedUsage.date !== today) {
4184
+ const oldDate = cachedUsage.date;
4185
+ const oldStats = cachedUsage.stats;
4186
+ const history = cachedUsage.history || {};
4187
+ if (oldStats) {
4188
+ history[oldDate] = oldStats;
4189
+ }
4125
4190
  cachedUsage = {
4126
4191
  date: today,
4127
- stats: { ...defaultStats }
4192
+ stats: { ...defaultStats },
4193
+ history: purgeOldHistory(history, today)
4128
4194
  };
4129
4195
  isDirty = true;
4130
4196
  await flushUsage();
@@ -4134,6 +4200,57 @@ var init_usage = __esm({
4134
4200
  }
4135
4201
  return cachedUsage.stats;
4136
4202
  };
4203
+ getMonthlyUsage = async () => {
4204
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
4205
+ if (!cachedUsage) {
4206
+ cachedUsage = await loadUsageFromFile();
4207
+ }
4208
+ if (cachedUsage.date !== today) {
4209
+ await getDailyUsage();
4210
+ }
4211
+ const history = cachedUsage.history || {};
4212
+ const purgedHistory = purgeOldHistory(history, today);
4213
+ cachedUsage.history = purgedHistory;
4214
+ const todayStats = cachedUsage.stats || { ...defaultStats };
4215
+ const summed = { ...defaultStats };
4216
+ summed.imageCalls = [];
4217
+ summed.models = {};
4218
+ const addStats = (target, source) => {
4219
+ for (const key in target) {
4220
+ if (key === "imageCalls") {
4221
+ target.imageCalls = [...target.imageCalls || [], ...source.imageCalls || []];
4222
+ } else if (key === "models") {
4223
+ const srcModels = source.models || {};
4224
+ for (const provider in srcModels) {
4225
+ if (!target.models[provider]) {
4226
+ target.models[provider] = {};
4227
+ }
4228
+ for (const model in srcModels[provider]) {
4229
+ if (!target.models[provider][model]) {
4230
+ target.models[provider][model] = {
4231
+ tokens: 0,
4232
+ cachedTokens: 0,
4233
+ candidateTokens: 0
4234
+ };
4235
+ }
4236
+ const tM = target.models[provider][model];
4237
+ const sM = srcModels[provider][model];
4238
+ tM.tokens += sM.tokens || 0;
4239
+ tM.cachedTokens += sM.cachedTokens || 0;
4240
+ tM.candidateTokens += sM.candidateTokens || 0;
4241
+ }
4242
+ }
4243
+ } else if (typeof target[key] === "number") {
4244
+ target[key] += source[key] || 0;
4245
+ }
4246
+ }
4247
+ };
4248
+ addStats(summed, todayStats);
4249
+ for (const dateKey in purgedHistory) {
4250
+ addStats(summed, purgedHistory[dateKey]);
4251
+ }
4252
+ return summed;
4253
+ };
4137
4254
  incrementUsage = async (key) => {
4138
4255
  const stats = await getDailyUsage();
4139
4256
  if (stats[key] !== void 0) {
@@ -4141,12 +4258,31 @@ var init_usage = __esm({
4141
4258
  queueFlush();
4142
4259
  }
4143
4260
  };
4144
- addToUsage = async (key, amount) => {
4261
+ addToUsage = async (key, amount, provider, model) => {
4145
4262
  const stats = await getDailyUsage();
4146
4263
  if (stats[key] !== void 0) {
4147
4264
  stats[key] += Math.floor(amount);
4148
- queueFlush();
4149
4265
  }
4266
+ if (provider && model && (key === "tokens" || key === "cachedTokens" || key === "candidateTokens")) {
4267
+ if (!stats.models) {
4268
+ stats.models = {};
4269
+ }
4270
+ if (!stats.models[provider]) {
4271
+ stats.models[provider] = {};
4272
+ }
4273
+ if (!stats.models[provider][model]) {
4274
+ stats.models[provider][model] = {
4275
+ tokens: 0,
4276
+ cachedTokens: 0,
4277
+ candidateTokens: 0
4278
+ };
4279
+ }
4280
+ const mObj = stats.models[provider][model];
4281
+ if (key === "tokens") mObj.tokens += Math.floor(amount);
4282
+ if (key === "cachedTokens") mObj.cachedTokens += Math.floor(amount);
4283
+ if (key === "candidateTokens") mObj.candidateTokens += Math.floor(amount);
4284
+ }
4285
+ queueFlush();
4150
4286
  };
4151
4287
  checkQuota = async (key, settings) => {
4152
4288
  const usage = await getDailyUsage();
@@ -6912,7 +7048,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
6912
7048
  }
6913
7049
  if (fullContent) {
6914
7050
  finalSynthesis = fullContent;
6915
- if (lastUsage) await addToUsage("tokens", lastUsage.totalTokenCount || 0);
7051
+ if (lastUsage) await addToUsage("tokens", lastUsage.totalTokenCount || 0, aiProvider, janitorModel || "gemini-3.1-flash-lite");
6916
7052
  } else {
6917
7053
  throw new Error("No synthesis generated by Janitor.");
6918
7054
  }
@@ -7321,7 +7457,7 @@ ${newMemoryListStr}
7321
7457
  }
7322
7458
  }
7323
7459
  if (response.usageMetadata) {
7324
- await addToUsage("tokens", response.usageMetadata.totalTokenCount || 0);
7460
+ await addToUsage("tokens", response.usageMetadata.totalTokenCount || 0, aiProvider, targetModel);
7325
7461
  }
7326
7462
  success = true;
7327
7463
  } catch (err) {
@@ -9293,12 +9429,12 @@ Error Log can be found in ${path19.join(LOGS_DIR, "agent", "error.log")}`);
9293
9429
  const total = lastUsage.totalTokenCount || 0;
9294
9430
  const cached = lastUsage.cachedContentTokenCount || 0;
9295
9431
  const candidates = (lastUsage.candidatesTokenCount || 0) + (lastUsage.thoughtsTokenCount || 0);
9296
- await addToUsage("tokens", total);
9432
+ await addToUsage("tokens", total, aiProvider, targetModel);
9297
9433
  if (cached > 0) {
9298
- await addToUsage("cachedTokens", cached);
9434
+ await addToUsage("cachedTokens", cached, aiProvider, targetModel);
9299
9435
  }
9300
9436
  if (candidates > 0) {
9301
- await addToUsage("candidateTokens", candidates);
9437
+ await addToUsage("candidateTokens", candidates, aiProvider, targetModel);
9302
9438
  }
9303
9439
  yield { type: "usage", content: lastUsage };
9304
9440
  }
@@ -10455,6 +10591,8 @@ function App({ args = [] }) {
10455
10591
  const [sessionImageCount, setSessionImageCount] = useState11(0);
10456
10592
  const [sessionImageCredits, setSessionImageCredits] = useState11(0);
10457
10593
  const [dailyUsage, setDailyUsage] = useState11(null);
10594
+ const [monthlyUsage, setMonthlyUsage] = useState11(null);
10595
+ const [statsMode, setStatsMode] = useState11("daily");
10458
10596
  const [chatId, setChatId] = useState11(generateChatId());
10459
10597
  useEffect8(() => {
10460
10598
  const nextTokens = sessionTotalTokens - chatTokenStartRef.current;
@@ -10688,6 +10826,19 @@ function App({ args = [] }) {
10688
10826
  if (inputText === "\x1B[I" || inputText === "\x1B[O" || inputText === "[I" || inputText === "[O") {
10689
10827
  return;
10690
10828
  }
10829
+ if (activeView === "stats") {
10830
+ if (key.tab && !key.shift) {
10831
+ setStatsMode((prev) => {
10832
+ if (prev === "modelBreakdown") return "daily";
10833
+ return prev === "daily" ? "monthly" : "daily";
10834
+ });
10835
+ return;
10836
+ }
10837
+ if (key.space || inputText === " ") {
10838
+ setStatsMode((prev) => prev === "modelBreakdown" ? "daily" : "modelBreakdown");
10839
+ return;
10840
+ }
10841
+ }
10691
10842
  if (showBridgePromo) {
10692
10843
  const ideName = getIDEName();
10693
10844
  const options = getPromoOptions(ideName);
@@ -11714,7 +11865,10 @@ ${hintText}`, color: "magenta" }];
11714
11865
  case "/stats": {
11715
11866
  const run = async () => {
11716
11867
  const usage = await getDailyUsage();
11868
+ const mUsage = await getMonthlyUsage();
11717
11869
  setDailyUsage(usage);
11870
+ setMonthlyUsage(mUsage);
11871
+ setStatsMode("daily");
11718
11872
  setActiveView("stats");
11719
11873
  };
11720
11874
  run();
@@ -12767,8 +12921,20 @@ Selection: ${val}`,
12767
12921
  }
12768
12922
  }
12769
12923
  )), /* @__PURE__ */ React14.createElement(Box14, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "gray", dimColor: true, italic: true }, "(Press Enter to confirm selection)")));
12770
- case "stats":
12771
- return /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 3, paddingY: 1, width: Math.min(100, (stdout?.columns || 100) - 2) }, /* @__PURE__ */ React14.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "white", bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Session Duration:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, sessionAgentCalls)), /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 23 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB API Time:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 23 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Tool Time:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, sessionBackgroundCalls)), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Active Context:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionStats.tokens))), sessionTotalTokens > 0 && /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 23 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Input Tokens:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionTotalTokens - sessionTotalCandidateTokens))), sessionTotalCachedTokens > 0 && /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React14.createElement(Box14, { width: 21 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Cached:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionTotalCachedTokens))), sessionTotalCandidateTokens > 0 && /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 23 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Output Tokens:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionTotalCandidateTokens)))), sessionImageCount > 0 && /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Images Made:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, sessionImageCount)), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Image Credits:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Code Changes (Sess):")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, /* @__PURE__ */ React14.createElement(Text14, { color: "green" }, "+", linesAdded), " ", /* @__PURE__ */ React14.createElement(Text14, { color: "red" }, "-", linesRemoved))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Tool Calls (Sess):")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( "), /* @__PURE__ */ React14.createElement(Text14, { color: "green" }, "\u2713 ", sessionToolSuccess), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, " "), /* @__PURE__ */ React14.createElement(Text14, { color: "yellow" }, "\u2298 ", sessionToolDenied), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, " "), /* @__PURE__ */ React14.createElement(Text14, { color: "red" }, "\u2715 ", sessionToolFailure), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, " )"))), /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "white", bold: true, underline: true }, "DAILY USAGE TRACKER"), /* @__PURE__ */ React14.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Wall Time Today:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatDuration(dailyUsage?.duration || 0))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, dailyUsage?.agent || 0)), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, dailyUsage?.background || 0)), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Tokens Used Today:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(dailyUsage?.tokens || 0))), (dailyUsage?.tokens || 0) > 0 && /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 23 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Input Tokens:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens((dailyUsage?.tokens || 0) - (dailyUsage?.candidateTokens || 0)))), (dailyUsage?.cachedTokens || 0) > 0 && /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React14.createElement(Box14, { width: 21 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Cached:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(dailyUsage.cachedTokens))), (dailyUsage?.candidateTokens || 0) > 0 && /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 23 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Output Tokens:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(dailyUsage.candidateTokens)))), (dailyUsage?.imageCalls?.length || 0) > 0 && /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Images Made Today:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, dailyUsage.imageCalls.length)), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Image Credits Today:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, Number(((dailyUsage.imageCalls.reduce((sum, c) => sum + c.cost, 0) || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Code Changes Today:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, /* @__PURE__ */ React14.createElement(Text14, { color: "green" }, "+", dailyUsage?.linesAdded || 0), " ", /* @__PURE__ */ React14.createElement(Text14, { color: "red" }, "-", dailyUsage?.linesRemoved || 0))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Tool Calls Today:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, (dailyUsage?.toolSuccess || 0) + (dailyUsage?.toolFailure || 0) + (dailyUsage?.toolDenied || 0), " ( "), /* @__PURE__ */ React14.createElement(Text14, { color: "green" }, "\u2713 ", dailyUsage?.toolSuccess || 0), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, " "), /* @__PURE__ */ React14.createElement(Text14, { color: "yellow" }, "\u2298 ", dailyUsage?.toolDenied || 0), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, " "), /* @__PURE__ */ React14.createElement(Text14, { color: "red" }, "\u2715 ", dailyUsage?.toolFailure || 0), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, " )"))), /* @__PURE__ */ React14.createElement(Text14, { dimColor: true, marginTop: 1, italic: true }, "(Press ESC to return to chat)"));
12924
+ case "stats": {
12925
+ const u = statsMode === "monthly" ? monthlyUsage : dailyUsage;
12926
+ const trackerTitle = statsMode === "monthly" ? "LAST 30 DAYS USAGE TRACKER" : "DAILY USAGE TRACKER";
12927
+ const timeLabel = statsMode === "monthly" ? "Wall Time (30d):" : "Wall Time Today:";
12928
+ const tokensLabel = statsMode === "monthly" ? "Tokens Used (30d):" : "Tokens Used Today:";
12929
+ const imagesLabel = statsMode === "monthly" ? "Images Made (30d):" : "Images Made Today:";
12930
+ const imageCreditsLabel = statsMode === "monthly" ? "Image Credits (30d):" : "Image Credits Today:";
12931
+ const codeChangesLabel = statsMode === "monthly" ? "Code Changes (30d):" : "Code Changes Today:";
12932
+ const toolCallsLabel = statsMode === "monthly" ? "Tool Calls (30d):" : "Tool Calls Today:";
12933
+ return /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 3, paddingY: 1, paddingBottom: 0, width: Math.min(125, (stdout?.columns || 100) - 2) }, statsMode === "modelBreakdown" ? /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Text14, { color: "white", bold: true, underline: true }, "30-DAY MODEL TOKEN BREAKDOWN"), !monthlyUsage?.models || Object.keys(monthlyUsage.models).length === 0 ? /* @__PURE__ */ React14.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey", italic: true }, "No model token usage recorded in the last 30 days.")) : Object.entries(monthlyUsage.models).map(([provider, models]) => {
12934
+ const providerTotalTokens = Object.values(models).reduce((sum, m) => sum + (m.tokens || 0), 0);
12935
+ return /* @__PURE__ */ React14.createElement(Box14, { key: provider, flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "cyan", bold: true }, provider, ":")), /* @__PURE__ */ React14.createElement(Text14, { color: "white", bold: true }, formatTokens(providerTotalTokens))), Object.entries(models).map(([modelName, stats]) => /* @__PURE__ */ React14.createElement(Box14, { key: modelName, flexDirection: "column", marginLeft: 4 }, /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 21 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "\xBB ", modelName, ":")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(stats.tokens || 0))), /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React14.createElement(Box14, { width: 17 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Input Tokens:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens((stats.tokens || 0) - (stats.candidateTokens || 0)))), (stats.cachedTokens || 0) > 0 && /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 5 }, /* @__PURE__ */ React14.createElement(Box14, { width: 16 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Cached:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(stats.cachedTokens))), /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React14.createElement(Box14, { width: 17 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Output Tokens:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(stats.candidateTokens || 0))))));
12936
+ })) : /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "white", bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Session Duration:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, sessionAgentCalls)), /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 23 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB API Time:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 23 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Tool Time:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, sessionBackgroundCalls)), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Active Context:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionStats.tokens))), sessionTotalTokens > 0 && /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 23 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Input Tokens:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionTotalTokens - sessionTotalCandidateTokens))), sessionTotalCachedTokens > 0 && /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React14.createElement(Box14, { width: 21 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Cached:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionTotalCachedTokens))), sessionTotalCandidateTokens > 0 && /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 23 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Output Tokens:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(sessionTotalCandidateTokens)))), sessionImageCount > 0 && /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Images Made:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, sessionImageCount)), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Image Credits:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Code Changes (Sess):")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, /* @__PURE__ */ React14.createElement(Text14, { color: "green" }, "+", linesAdded), " ", /* @__PURE__ */ React14.createElement(Text14, { color: "red" }, "-", linesRemoved))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Tool Calls (Sess):")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( "), /* @__PURE__ */ React14.createElement(Text14, { color: "green" }, "\u2713 ", sessionToolSuccess), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, " "), /* @__PURE__ */ React14.createElement(Text14, { color: "yellow" }, "\u2298 ", sessionToolDenied), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, " "), /* @__PURE__ */ React14.createElement(Text14, { color: "red" }, "\u2715 ", sessionToolFailure), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, " )"))), /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React14.createElement(Text14, { color: "white", bold: true, underline: true }, trackerTitle), /* @__PURE__ */ React14.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, timeLabel)), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatDuration(u?.duration || 0))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, u?.agent || 0)), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, u?.background || 0)), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, tokensLabel)), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(u?.tokens || 0))), (u?.tokens || 0) > 0 && /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 23 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Input Tokens:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens((u?.tokens || 0) - (u?.candidateTokens || 0)))), (u?.cachedTokens || 0) > 0 && /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React14.createElement(Box14, { width: 21 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Cached:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(u.cachedTokens))), (u?.candidateTokens || 0) > 0 && /* @__PURE__ */ React14.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React14.createElement(Box14, { width: 23 }, /* @__PURE__ */ React14.createElement(Text14, { color: "grey" }, "\xBB Output Tokens:")), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, formatTokens(u.candidateTokens)))), (u?.imageCalls?.length || 0) > 0 && /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, imagesLabel)), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, u.imageCalls.length)), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, imageCreditsLabel)), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, Number(((u.imageCalls.reduce((sum, c) => sum + c.cost, 0) || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, codeChangesLabel)), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, /* @__PURE__ */ React14.createElement(Text14, { color: "green" }, "+", u?.linesAdded || 0), " ", /* @__PURE__ */ React14.createElement(Text14, { color: "red" }, "-", u?.linesRemoved || 0))), /* @__PURE__ */ React14.createElement(Box14, null, /* @__PURE__ */ React14.createElement(Box14, { width: 25 }, /* @__PURE__ */ React14.createElement(Text14, { color: "blue" }, toolCallsLabel)), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, (u?.toolSuccess || 0) + (u?.toolFailure || 0) + (u?.toolDenied || 0), " ( "), /* @__PURE__ */ React14.createElement(Text14, { color: "green" }, "\u2713 ", u?.toolSuccess || 0), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, " "), /* @__PURE__ */ React14.createElement(Text14, { color: "yellow" }, "\u2298 ", u?.toolDenied || 0), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, " "), /* @__PURE__ */ React14.createElement(Text14, { color: "red" }, "\u2715 ", u?.toolFailure || 0), /* @__PURE__ */ React14.createElement(Text14, { color: "white" }, " )")))), /* @__PURE__ */ React14.createElement(Text14, { dimColor: true, marginTop: 1, italic: true }, "(Press TAB to toggle Daily/Monthly views, SPACE for Model Breakdown, ESC to return)"));
12937
+ }
12772
12938
  case "autoExecDanger":
12773
12939
  return /* @__PURE__ */ React14.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React14.createElement(Text14, { color: "white", bold: true, underline: true }, "SECURITY WARNING: YOLO MODE"), /* @__PURE__ */ React14.createElement(Text14, { marginTop: 1 }, "Turning this ON allows the agent to execute terminal commands automatically without requiring your approval for each step."), /* @__PURE__ */ React14.createElement(Text14, { marginTop: 1, color: "white" }, "RISKS INVOLVED:"), /* @__PURE__ */ React14.createElement(Text14, null, "\u2022 The agent may execute destructive commands (rm -rf, etc.) by mistake unless specified in sandbox rules."), /* @__PURE__ */ React14.createElement(Text14, null, "\u2022 Unintended system changes if the agent hallucinates a path or command."), /* @__PURE__ */ React14.createElement(Text14, null, "\u2022 Reduced control over the agent's step-by-step decision making."), /* @__PURE__ */ React14.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React14.createElement(
12774
12940
  CommandMenu,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "2.7.13",
4
- "date": "2026-06-17",
3
+ "version": "2.8.0",
4
+ "date": "2026-06-18",
5
5
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",