fluxflow-cli 3.1.7 → 3.2.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 +167 -36
  2. package/package.json +2 -2
package/dist/fluxflow.js CHANGED
@@ -324,7 +324,8 @@ var init_settings = __esm({
324
324
  advanceRollback: false,
325
325
  autoDeleteHistory: "7d",
326
326
  useExternalData: false,
327
- externalDataPath: ""
327
+ externalDataPath: "",
328
+ preserveThinking: true
328
329
  },
329
330
  profileData: {
330
331
  name: null,
@@ -4844,10 +4845,10 @@ var init_StatusBar = __esm({
4844
4845
  init_text();
4845
4846
  activeGetMemoryInfo = null;
4846
4847
  getLatencyColor = (delay) => {
4847
- if (delay <= 400) return "#00a564";
4848
+ if (delay <= 500) return "#00a564";
4848
4849
  if (delay >= 5e3) return "#ff0000";
4849
4850
  const points = [
4850
- { t: 400, r: 0, g: 165, b: 100 },
4851
+ { t: 500, r: 0, g: 165, b: 100 },
4851
4852
  { t: 800, r: 120, g: 220, b: 80 },
4852
4853
  { t: 1500, r: 250, g: 210, b: 40 },
4853
4854
  { t: 3e3, r: 255, g: 120, b: 0 },
@@ -5963,6 +5964,7 @@ function SettingsMenu({
5963
5964
  return [
5964
5965
  { label: "Current Provider", value: "aiProvider", status: aiProvider },
5965
5966
  { label: "Key Strategy", value: "apiTier", status: apiTier === "Free" ? "Free" : quotas?.providerBudgets?.__useProvider ? "Paid" : "Paid" },
5967
+ { label: "Preserve Thinking", value: "preserveThinking", status: systemSettings.preserveThinking !== false ? "ON" : "OFF" },
5966
5968
  { label: "Download Language Parsers", value: "parserDownload", status: "ACTION" }
5967
5969
  ];
5968
5970
  default:
@@ -6119,6 +6121,12 @@ function SettingsMenu({
6119
6121
  setActiveView("updateManager");
6120
6122
  } else if (item.value === "parserDownload") {
6121
6123
  setActiveView("parserDownload");
6124
+ } else if (item.value === "preserveThinking") {
6125
+ setSystemSettings((s) => {
6126
+ const newSysSettings = { ...s, preserveThinking: s.preserveThinking === false ? true : false };
6127
+ saveSettings2({ systemSettings: newSysSettings, apiTier, quotas });
6128
+ return newSysSettings;
6129
+ });
6122
6130
  }
6123
6131
  };
6124
6132
  return /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "white", padding: 0, width: "100%", minHeight: 32 }, /* @__PURE__ */ React7.createElement(Box6, { paddingX: 1, paddingY: 0, marginBottom: 0, borderStyle: "single", borderColor: "gray", width: "100%" }, /* @__PURE__ */ React7.createElement(Text7, { color: "white", bold: true }, "SYSTEM CONFIGURATION")), /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "row", width: "100%", minHeight: 26 }, /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", width: "30%", borderStyle: "round", borderColor: activeColumn === "categories" ? "white" : "grey", padding: 1, paddingY: 0 }, /* @__PURE__ */ React7.createElement(Box6, { marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: activeColumn === "categories" ? "white" : "grey", bold: true, underline: true }, "CATEGORIES")), CATEGORIES.map((cat, index) => {
@@ -6203,7 +6211,7 @@ function SettingsMenu({
6203
6211
  });
6204
6212
  if (currentCatId === "other") {
6205
6213
  elements.push(
6206
- /* @__PURE__ */ React7.createElement(Box6, { key: "pty-notice", marginTop: 17, paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "white" }, isPtyAvailable ? "\u2713 Advance Interactive Terminal Supported" : "\u26A0 Interactive Terminal is Limited"))
6214
+ /* @__PURE__ */ React7.createElement(Box6, { key: "pty-notice", marginTop: 16, paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "white" }, isPtyAvailable ? "\u2713 Advance Interactive Terminal Supported" : "\u26A0 Interactive Terminal is Limited"))
6207
6215
  );
6208
6216
  elements.push(
6209
6217
  /* @__PURE__ */ React7.createElement(Box6, { key: "memory-load-2026", paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, "Memory Load: ", currentMemory, "/", maxMemory, " ", memoryUnit))
@@ -6829,6 +6837,7 @@ var init_history = __esm({
6829
6837
  init_crypto();
6830
6838
  init_paths();
6831
6839
  init_revert();
6840
+ init_settings();
6832
6841
  WRITE_LOCK = Promise.resolve();
6833
6842
  withLock = (op) => {
6834
6843
  const nextLock = WRITE_LOCK.then(async () => {
@@ -6883,9 +6892,16 @@ var init_history = __esm({
6883
6892
  await fs7.ensureDir(HISTORY_DIR);
6884
6893
  const history = await loadHistory();
6885
6894
  const existingChat = history[id];
6886
- const persistentMessages = (messages || []).filter(
6895
+ let persistentMessages = (messages || []).filter(
6887
6896
  (m) => !m.isUpdateNotification && (!m.isMeta || m.text && m.text.includes("Request Cancelled"))
6888
6897
  );
6898
+ try {
6899
+ const settings = await loadSettings();
6900
+ if (settings.systemSettings?.preserveThinking === false) {
6901
+ persistentMessages = persistentMessages.filter((m) => m.role !== "think");
6902
+ }
6903
+ } catch (e) {
6904
+ }
6889
6905
  const finalName = name || (existingChat ? existingChat.name : `Session ${id.slice(-6)}`);
6890
6906
  const chatFile = path6.join(HISTORY_DIR, `${id}.json`);
6891
6907
  writeEncryptedJson(chatFile, persistentMessages);
@@ -7142,7 +7158,7 @@ var init_history = __esm({
7142
7158
  import fs8 from "fs-extra";
7143
7159
  import path7 from "path";
7144
7160
  import os3 from "os";
7145
- var getLocalBackupPath, BACKUP_FILE, generateSaveId, cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, purgeOldHistory, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, getMonthlyUsage, incrementUsage, addToUsage, getCustomPeriodUsage, checkQuota, getImageQuotaBuckets, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
7161
+ var getLocalBackupPath, BACKUP_FILE, generateSaveId, cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, purgeOldHistory, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, getMonthlyUsage, incrementUsage, runtimeSession, addToUsage, getCustomPeriodUsage, checkQuota, getImageQuotaBuckets, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
7146
7162
  var init_usage = __esm({
7147
7163
  "src/utils/usage.js"() {
7148
7164
  init_paths();
@@ -7504,6 +7520,9 @@ var init_usage = __esm({
7504
7520
  return summed;
7505
7521
  };
7506
7522
  incrementUsage = async (key, provider) => {
7523
+ if (key === "toolSuccess") runtimeSession.toolSuccess++;
7524
+ else if (key === "toolFailure") runtimeSession.toolFailure++;
7525
+ else if (key === "toolDenied") runtimeSession.toolDenied++;
7507
7526
  const stats = await getDailyUsage();
7508
7527
  if (stats[key] !== void 0) {
7509
7528
  stats[key]++;
@@ -7516,7 +7535,19 @@ var init_usage = __esm({
7516
7535
  }
7517
7536
  queueFlush();
7518
7537
  };
7538
+ runtimeSession = {
7539
+ linesAdded: 0,
7540
+ linesRemoved: 0,
7541
+ toolSuccess: 0,
7542
+ toolFailure: 0,
7543
+ toolDenied: 0
7544
+ };
7519
7545
  addToUsage = async (key, amount, provider, model) => {
7546
+ if (key === "linesAdded") {
7547
+ runtimeSession.linesAdded += amount;
7548
+ } else if (key === "linesRemoved") {
7549
+ runtimeSession.linesRemoved += amount;
7550
+ }
7520
7551
  const stats = await getDailyUsage();
7521
7552
  if (stats[key] !== void 0) {
7522
7553
  stats[key] += Math.floor(amount);
@@ -9744,7 +9775,7 @@ var init_invokeSync = __esm({
9744
9775
  if (context.onVisualFeedback) {
9745
9776
  context.onVisualFeedback(`\x1B[95mSubAgent\x1B[0m: \x1B[32mGeneralist\x1B[0m \u2192 ${title}`);
9746
9777
  }
9747
- const result = await runSubagent2(task, context, model, allowedTools, 20);
9778
+ const result = await runSubagent2(task, context, model, allowedTools, 50);
9748
9779
  if (context.onVisualFeedback) {
9749
9780
  context.onVisualFeedback(`\x1B[95mSubAgent\x1B[0m: \x1B[32mGeneralist\x1B[0m \u2192 ${title} [COMPLETED]
9750
9781
  `);
@@ -9835,7 +9866,7 @@ var init_invoke = __esm({
9835
9866
  }
9836
9867
  }
9837
9868
  };
9838
- runSubagent2(task, subagentContext, model, allowedTools, 20, (logMessage) => {
9869
+ runSubagent2(task, subagentContext, model, allowedTools, 50, (logMessage) => {
9839
9870
  if (taskEntry.status === "cancelled") return;
9840
9871
  if (logMessage.startsWith("[Subagent Turn")) {
9841
9872
  if (currentTurnLogs.length > 0) {
@@ -9990,7 +10021,8 @@ ${task.finalAnswer}
9990
10021
  output += `Failure Error: ${task.error}
9991
10022
  `;
9992
10023
  }
9993
- return output.trim();
10024
+ const sanitized = output.trim().replace(/\[TOOL RESULT\]/gi, "TOOL RESULT:");
10025
+ return sanitized;
9994
10026
  };
9995
10027
  }
9996
10028
  });
@@ -10096,24 +10128,35 @@ async function copyWorkspaceFiles(destDir, manifest) {
10096
10128
  });
10097
10129
  }
10098
10130
  }
10099
- async function restoreSnapshotDir(srcDir, destDir) {
10131
+ async function restoreSnapshotDir(srcDir, destDir, stats = null, baseDir = null) {
10100
10132
  if (!await fs21.pathExists(srcDir)) return;
10133
+ if (!baseDir) baseDir = srcDir;
10101
10134
  const entries = await fs21.readdir(srcDir, { withFileTypes: true }).catch(() => []);
10102
10135
  for (const entry of entries) {
10103
10136
  const srcPath = path20.join(srcDir, entry.name);
10104
10137
  const destPath = path20.join(destDir, entry.name);
10105
10138
  if (entry.isDirectory()) {
10106
- await restoreSnapshotDir(srcPath, destPath);
10139
+ await restoreSnapshotDir(srcPath, destPath, stats, baseDir);
10107
10140
  } else {
10108
- if (await fs21.pathExists(destPath)) {
10141
+ const relPath = path20.relative(baseDir, srcPath).replace(/\\/g, "/");
10142
+ const existed = await fs21.pathExists(destPath);
10143
+ if (existed) {
10109
10144
  await fs21.chmod(destPath, 438).catch(() => {
10110
10145
  });
10111
10146
  }
10112
10147
  await fs21.ensureDir(path20.dirname(destPath));
10113
- await fs21.copyFile(srcPath, destPath).catch(() => {
10114
- });
10148
+ const ok = await fs21.copyFile(srcPath, destPath).then(() => true).catch(() => false);
10115
10149
  await fs21.chmod(destPath, 438).catch(() => {
10116
10150
  });
10151
+ if (stats) {
10152
+ if (!ok) {
10153
+ stats.failed.push(relPath);
10154
+ } else if (existed) {
10155
+ stats.replaced++;
10156
+ } else {
10157
+ stats.restored++;
10158
+ }
10159
+ }
10117
10160
  }
10118
10161
  }
10119
10162
  }
@@ -10230,6 +10273,7 @@ var init_advanceRevert = __esm({
10230
10273
  const targetIdx = checkpoints.findIndex((c) => c.id === checkpointId);
10231
10274
  if (targetIdx === -1) throw new Error(`Checkpoint [${checkpointId}] not found.`);
10232
10275
  const snapshotsDir = path20.join(DATA_DIR, "snapshots", chatId);
10276
+ const stats = { restored: 0, replaced: 0, failed: [] };
10233
10277
  const currentFiles = await scanWorkspace(process.cwd());
10234
10278
  for (const relPath of Object.keys(currentFiles)) {
10235
10279
  const fullPath = path20.join(process.cwd(), relPath);
@@ -10239,11 +10283,11 @@ var init_advanceRevert = __esm({
10239
10283
  });
10240
10284
  }
10241
10285
  const initialDir = path20.join(snapshotsDir, "initial");
10242
- await restoreSnapshotDir(initialDir, process.cwd());
10286
+ await restoreSnapshotDir(initialDir, process.cwd(), stats, initialDir);
10243
10287
  for (let i = 1; i <= targetIdx; i++) {
10244
10288
  const cp = checkpoints[i];
10245
10289
  const turnDir = path20.join(snapshotsDir, cp.id);
10246
- await restoreSnapshotDir(turnDir, process.cwd());
10290
+ await restoreSnapshotDir(turnDir, process.cwd(), stats, turnDir);
10247
10291
  if (cp.deletedFiles && cp.deletedFiles.length > 0) {
10248
10292
  for (const delFile of cp.deletedFiles) {
10249
10293
  const fullPath = path20.join(process.cwd(), delFile);
@@ -10257,7 +10301,7 @@ var init_advanceRevert = __esm({
10257
10301
  session.checkpoints = checkpoints.slice(0, targetIdx + 1);
10258
10302
  session.currentManifest = await scanWorkspace(process.cwd());
10259
10303
  writeEncryptedJson(LEDGER_ADVANCE_FILE, ledger);
10260
- return true;
10304
+ return { checkpointId, stats };
10261
10305
  } catch (err) {
10262
10306
  throw new Error(`Rollback failed: ${err.message}`);
10263
10307
  }
@@ -10351,8 +10395,28 @@ Tools Used: ${toolsStr}
10351
10395
  return "ERROR: Missing required parameter 'id' for forceRevert.";
10352
10396
  }
10353
10397
  try {
10354
- await AdvanceRevertManager.rollbackToCheckpoint(chatId, id);
10355
- return `SUCCESS: Repository rolled back to checkpoint [${id}].`;
10398
+ const result = await AdvanceRevertManager.rollbackToCheckpoint(chatId, id);
10399
+ const { checkpointId, stats } = result;
10400
+ const totalFiles = stats.restored + stats.replaced + stats.failed.length;
10401
+ let output = `SUCCESS: Repository rolled back to checkpoint [${checkpointId}].
10402
+
10403
+ `;
10404
+ output += `Stats:
10405
+ `;
10406
+ output += ` Restored : ${stats.restored} file${stats.restored !== 1 ? "s" : ""} (new to workspace)
10407
+ `;
10408
+ output += ` Replaced : ${stats.replaced} file${stats.replaced !== 1 ? "s" : ""} (overwritten)
10409
+ `;
10410
+ output += ` Failed : ${stats.failed.length} file${stats.failed.length !== 1 ? "s" : ""}`;
10411
+ if (stats.failed.length > 0) {
10412
+ output += `
10413
+ ${stats.failed.join("\n ")}`;
10414
+ }
10415
+ output += `
10416
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500-
10417
+ `;
10418
+ output += ` Total : ${totalFiles} file${totalFiles !== 1 ? "s" : ""} processed`;
10419
+ return output;
10356
10420
  } catch (err) {
10357
10421
  return `ERROR: ${err.message}`;
10358
10422
  }
@@ -10622,7 +10686,7 @@ var init_ai = __esm({
10622
10686
  globalSettings = {};
10623
10687
  colorMainWords = (label) => {
10624
10688
  if (!label) return label;
10625
- return label.replace(/(?:(\x1b\[\d+m))?([✔✘✖🔍📖→➕↻•🛇])(?:(\x1b\[\d+m))?\s*\b(Created|Read|Edited|Viewed|Auto-Read|List|Generated|Written|Searched|Get Map|Write Canceled|Edit Canceled|Write Cancelled|Edit Denied|Visited|Updated|Reviewed|Delegated|Background|Checked|Indexed|Analyzed|Browsed|Elevating SubAgent|Checking SubAgent Work|Started Generalist|Called Generalist|Unsupported Modality|Awaiting|Cancelled|Aligning Moon Phase|Contemplating Existence|Staring At Void|Rollback Checked|Emergency Rollback|Delaying Professionally|Negotiating With Electrons|Touching Grass (virtually)|Panicking Softly|Rethinking Career Choices|Loading Cat Videos|Giving Up Entirely|Summoning Braincell #2|Pretending To Be Busy|Waiting For Motivation DLC|Rotating Internal Screaming|Downloading More RAM|Feeding The Hamsters|Gaslighting Scheduler|Performing Dramatic Pause|Buffering Social Energy|Calculating Regret|Reading Terms And Conditions|Becoming Sentient Briefly|Contacting Ancestors)\b/ig, (match, ansiBefore, icon, ansiAfter, word) => {
10689
+ return label.replace(/(?:(\x1b\[\d+m))?([✔✘✖🔍📖→➕↻•🛇])(?:(\x1b\[\d+m))?\s*\b(Created|Read|Edited|Viewed|Auto-Read|List|Generated|Written|Searched|Get Map|Write Canceled|Edit Canceled|Write Cancelled|Edit Denied|Visited|Updated|Reviewed|Delegated|Background|Checked|Indexed|Analyzed|Browsed|Elevating SubAgent|Checking SubAgent Work|Started Generalist|Called Generalist|Unsupported Modality|Awaiting|Cancelled|Aligning Moon Phase|Contemplating Existence|Staring At Void|Rollback Point Checked|Emergency Rollback Failed|Emergency Rollback|Delaying Professionally|Negotiating With Electrons|Touching Grass (virtually)|Panicking Softly|Rethinking Career Choices|Loading Cat Videos|Giving Up Entirely|Summoning Braincell #2|Pretending To Be Busy|Waiting For Motivation DLC|Rotating Internal Screaming|Downloading More RAM|Feeding The Hamsters|Gaslighting Scheduler|Performing Dramatic Pause|Buffering Social Energy|Calculating Regret|Reading Terms And Conditions|Becoming Sentient Briefly|Contacting Ancestors)\b/ig, (match, ansiBefore, icon, ansiAfter, word) => {
10626
10690
  return `${ansiBefore || ""}${icon}${ansiAfter || ""} \x1B[95m${word}\x1B[0m`;
10627
10691
  });
10628
10692
  };
@@ -13680,7 +13744,7 @@ ${ideErr} [/ERROR]`;
13680
13744
  label = `\u{1F6C7} Cancelled${detail2 ? `: ${detail2}` : ""}`;
13681
13745
  } else if (normToolName === "EmergencyRollback") {
13682
13746
  const { method } = parseArgs(toolCall.args);
13683
- label = `\u2714 ${method === "forceRevert" ? "Emergency Rollback" : "Rollback Checked"}`;
13747
+ label = method === "forceRevert" ? "" : "\u2714 Rollback Point Checked";
13684
13748
  } else if (normToolName === "await" || normToolName === "Await") {
13685
13749
  const { time } = parseArgs(toolCall.args);
13686
13750
  let sec = parseFloat(time) || 0;
@@ -14397,6 +14461,28 @@ ${boxBottom}`}`) };
14397
14461
  ${boxMid}
14398
14462
  `) };
14399
14463
  }
14464
+ if (normToolName === "EmergencyRollback") {
14465
+ const { method } = parseArgs(toolCall.args);
14466
+ if (method === "forceRevert") {
14467
+ let totalFiles = 0;
14468
+ if (result) {
14469
+ const m = result.match(/Total\s*:\s*(\d+)/i);
14470
+ if (m) totalFiles = parseInt(m[1]);
14471
+ }
14472
+ const isErr = result && result.startsWith("ERROR:");
14473
+ const postLabel = isErr ? `\u2718 Emergency Rollback Failed` : `\u2714 Emergency Rollback \u2192 ${totalFiles} file${totalFiles === 1 ? "" : "s"} processed`;
14474
+ let terminalWidth = 115;
14475
+ if (process.stdout.isTTY) {
14476
+ terminalWidth = process.stdout.columns - 5 || 120;
14477
+ }
14478
+ const boxWidth = Math.min(postLabel.length + 4, terminalWidth);
14479
+ const boxMid = `${postLabel.padEnd(boxWidth - 2).substring(0, boxWidth - 2)}`;
14480
+ const boxBottom = ` ${" ".repeat(boxWidth)} `;
14481
+ yield { type: "visual_feedback", content: colorMainWords(`${boxBottom}
14482
+ ${boxMid}
14483
+ `) };
14484
+ }
14485
+ }
14400
14486
  if (normToolName === "todo") {
14401
14487
  const { method, tasks, markDone } = parseArgs(toolCall.args);
14402
14488
  let uiTitle = "";
@@ -14612,7 +14698,7 @@ ${colorMainWords(output)}` };
14612
14698
 
14613
14699
  `);
14614
14700
  const status = err.status || err.statusCode || err.code;
14615
- const isRetryable = status && (status >= 500 && status < 600 || status === 408) || !status && (/status[ :]+(5\d\d|408)/i.test(String(err)) || /code[ :]+(5\d\d|408)/i.test(String(err)) || /(500|503|408)/.test(String(err)));
14701
+ const isRetryable = status && (status >= 500 && status < 600 || status === 408 || status === 429) || !status && (/status[ :]+(5\d\d|408|429)/i.test(String(err)) || /code[ :]+(5\d\d|408|429)/i.test(String(err)) || /(500|503|408|429)/.test(String(err)));
14616
14702
  if (!isRetryable) {
14617
14703
  if (retryCount < MAX_RETRIES - 3) {
14618
14704
  throw err;
@@ -14801,7 +14887,7 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
14801
14887
  }
14802
14888
  yield { type: "status", content: null };
14803
14889
  };
14804
- runSubagent = async (task, settings, model = null, allowedTools = null, maxTurns = 20, logCallback = null) => {
14890
+ runSubagent = async (task, settings, model = null, allowedTools = null, maxTurns = 50, logCallback = null) => {
14805
14891
  const savedSettings = await loadSettings();
14806
14892
  const mergedSettings = { ...savedSettings, ...settings };
14807
14893
  const targetModel = model || settings?.modelName || settings?.activeModel || savedSettings.activeModel;
@@ -14825,6 +14911,7 @@ TOOL POLICY:
14825
14911
  - Want spefific STRING across project/file? SearchKeyword >> Guessing/ReadFile
14826
14912
  - HUGE FILES? SearchKeyword >> FileMap/Full Read
14827
14913
  - NO Terminal Access
14914
+
14828
14915
  -- PROVIDED TOOLS --
14829
14916
  ${Object.values(SUBAGENT_TOOL_DEFINITIONS).join("\n")}
14830
14917
 
@@ -14944,6 +15031,55 @@ ${result}
14944
15031
  toolResultsStr += `[TOOL RESULT for ${toolCall.toolName}]: ${result}
14945
15032
 
14946
15033
  `;
15034
+ await incrementUsage("toolSuccess");
15035
+ if (normalizedToolName === "patchfile" || normalizedToolName === "update_file" || normalizedToolName === "updatefile" || normalizedToolName === "patch_file") {
15036
+ if (result) {
15037
+ const diffLines = result.split("\n");
15038
+ let added = 0, removed = 0, insideDiff = false;
15039
+ for (const line of diffLines) {
15040
+ if (line.includes("[DIFF_START]")) {
15041
+ insideDiff = true;
15042
+ continue;
15043
+ }
15044
+ if (line.includes("[DIFF_END]")) {
15045
+ insideDiff = false;
15046
+ continue;
15047
+ }
15048
+ if (insideDiff) {
15049
+ if (/^\+\d+/.test(line)) added++;
15050
+ else if (/^\-\d+/.test(line)) removed++;
15051
+ }
15052
+ }
15053
+ if (added > 0 || removed > 0) {
15054
+ await addToUsage("linesAdded", added);
15055
+ await addToUsage("linesRemoved", removed);
15056
+ }
15057
+ }
15058
+ } else if (normalizedToolName === "writefile" || normalizedToolName === "write_file") {
15059
+ if (result) {
15060
+ const statsMatch = result.match(/- Stats: \[(\d+) lines/);
15061
+ const verifiedLinesCount = statsMatch ? parseInt(statsMatch[1]) : 0;
15062
+ let oldLinesCount = 0;
15063
+ if (result.includes("Old File contents:")) {
15064
+ let insideOldFile = false;
15065
+ for (const line of result.split("\n")) {
15066
+ if (line.includes("Old File contents:")) {
15067
+ insideOldFile = true;
15068
+ continue;
15069
+ }
15070
+ if (insideOldFile) {
15071
+ if (line.trim() === "") {
15072
+ insideOldFile = false;
15073
+ } else if (/^\d+ \|/.test(line)) oldLinesCount++;
15074
+ }
15075
+ }
15076
+ }
15077
+ if (verifiedLinesCount > 0 || oldLinesCount > 0) {
15078
+ await addToUsage("linesAdded", verifiedLinesCount);
15079
+ await addToUsage("linesRemoved", oldLinesCount);
15080
+ }
15081
+ }
15082
+ }
14947
15083
  } catch (e) {
14948
15084
  const errorMsg = `ERROR: Execution failed for [${toolCall.toolName}]: ${e.message}`;
14949
15085
  if (logCallback) logCallback(`[Tool Error] ${errorMsg}
@@ -14951,6 +15087,7 @@ ${result}
14951
15087
  toolResultsStr += `${errorMsg}
14952
15088
 
14953
15089
  `;
15090
+ await incrementUsage("toolFailure");
14954
15091
  }
14955
15092
  }
14956
15093
  subagentHistory.push({ role: "user", text: toolResultsStr.trim() });
@@ -18675,8 +18812,6 @@ Selection: ${val}`,
18675
18812
  }
18676
18813
  }
18677
18814
  }
18678
- linesAdded += added;
18679
- linesRemoved += removed;
18680
18815
  addToUsage("linesAdded", added);
18681
18816
  addToUsage("linesRemoved", removed);
18682
18817
  } else if (packet.toolName === "write_file" && packet.aiContent) {
@@ -18700,8 +18835,6 @@ Selection: ${val}`,
18700
18835
  }
18701
18836
  }
18702
18837
  }
18703
- linesAdded += verifiedLinesCount;
18704
- linesRemoved += oldLinesCount;
18705
18838
  addToUsage("linesAdded", verifiedLinesCount);
18706
18839
  addToUsage("linesRemoved", oldLinesCount);
18707
18840
  }
@@ -19483,7 +19616,7 @@ Selection: ${val}`,
19483
19616
  return /* @__PURE__ */ React15.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__ */ React15.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, "30-DAY MODEL TOKEN BREAKDOWN"), !monthlyUsage?.models || Object.keys(monthlyUsage.models).length === 0 ? /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey", italic: true }, "No model token usage recorded in the last 30 days.")) : Object.entries(monthlyUsage.models).map(([provider, models]) => {
19484
19617
  const providerTotalTokens = Object.values(models).reduce((sum, m) => sum + (m.tokens || 0), 0);
19485
19618
  return /* @__PURE__ */ React15.createElement(Box14, { key: provider, flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 40 }, /* @__PURE__ */ React15.createElement(Text15, { color: "cyan", bold: true }, provider, ":")), /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true }, formatTokens(providerTotalTokens))), Object.entries(models).map(([modelName, stats]) => /* @__PURE__ */ React15.createElement(Box14, { key: modelName, flexDirection: "column", marginLeft: 4, marginTop: 1 }, /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 36 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "\xBB ", modelName, ":")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(stats.tokens || 0))), /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React15.createElement(Box14, { width: 32 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Input Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens((stats.tokens || 0) - (stats.candidateTokens || 0)))), (stats.cachedTokens || 0) > 0 && /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 5 }, /* @__PURE__ */ React15.createElement(Box14, { width: 31 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Cached:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(stats.cachedTokens))), /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React15.createElement(Box14, { width: 32 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Output Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(stats.candidateTokens || 0))))));
19486
- })) : /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Session Duration:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Model Requests:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, sessionAgentCalls)), /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 23 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB API Time:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 23 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Tool Time:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Memory Agent:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, sessionBackgroundCalls)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Active Context:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionStats.tokens))), sessionTotalTokens > 0 && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 23 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Input Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalTokens - sessionTotalCandidateTokens))), sessionTotalCachedTokens > 0 && /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React15.createElement(Box14, { width: 21 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Cached:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalCachedTokens))), sessionTotalCandidateTokens > 0 && /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 23 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Output Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalCandidateTokens)))), sessionImageCount > 0 && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Images Made:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, sessionImageCount)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Image Credits:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Code Changes (Sess):")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, /* @__PURE__ */ React15.createElement(Text15, { color: "green" }, "+", linesAdded), " ", /* @__PURE__ */ React15.createElement(Text15, { color: "red" }, "-", linesRemoved))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Tool Calls (Sess):")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( "), /* @__PURE__ */ React15.createElement(Text15, { color: "green" }, "\u2714 ", sessionToolSuccess), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, " "), /* @__PURE__ */ React15.createElement(Text15, { color: "yellow" }, "\u{1F6C7} ", sessionToolDenied), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, " "), /* @__PURE__ */ React15.createElement(Text15, { color: "red" }, "\u2718 ", sessionToolFailure), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, " )"))), /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, trackerTitle), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, timeLabel)), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatDuration(u?.duration || 0))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Model Requests:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, u?.agent || 0)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Memory Agent:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, u?.background || 0)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, tokensLabel)), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(u?.tokens || 0))), (u?.tokens || 0) > 0 && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 23 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Input Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens((u?.tokens || 0) - (u?.candidateTokens || 0)))), (u?.cachedTokens || 0) > 0 && /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React15.createElement(Box14, { width: 21 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Cached:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(u.cachedTokens))), (u?.candidateTokens || 0) > 0 && /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 23 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Output Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(u.candidateTokens)))), (u?.imageCalls?.length || 0) > 0 && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, imagesLabel)), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, u.imageCalls.length)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, imageCreditsLabel)), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, Number(((u.imageCalls.reduce((sum, c) => sum + c.cost, 0) || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, codeChangesLabel)), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, /* @__PURE__ */ React15.createElement(Text15, { color: "green" }, "+", u?.linesAdded || 0), " ", /* @__PURE__ */ React15.createElement(Text15, { color: "red" }, "-", u?.linesRemoved || 0))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, toolCallsLabel)), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, (u?.toolSuccess || 0) + (u?.toolFailure || 0) + (u?.toolDenied || 0), " ( "), /* @__PURE__ */ React15.createElement(Text15, { color: "green" }, "\u2714 ", u?.toolSuccess || 0), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, " "), /* @__PURE__ */ React15.createElement(Text15, { color: "yellow" }, "\u{1F6C7} ", u?.toolDenied || 0), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, " "), /* @__PURE__ */ React15.createElement(Text15, { color: "red" }, "\u2718 ", u?.toolFailure || 0), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, " )")))), /* @__PURE__ */ React15.createElement(Text15, { dimColor: true, marginTop: 1, italic: true }, "(Press TAB to toggle Daily/Monthly views, SPACE for Model Breakdown, ESC to return)"));
19619
+ })) : /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Session Duration:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Model Requests:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, sessionAgentCalls)), /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 23 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB API Time:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 23 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Tool Time:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Memory Agent:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, sessionBackgroundCalls)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Active Context:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionStats.tokens))), sessionTotalTokens > 0 && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 23 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Input Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalTokens - sessionTotalCandidateTokens))), sessionTotalCachedTokens > 0 && /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React15.createElement(Box14, { width: 21 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Cached:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalCachedTokens))), sessionTotalCandidateTokens > 0 && /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 23 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Output Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalCandidateTokens)))), sessionImageCount > 0 && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Images Made:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, sessionImageCount)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Image Credits:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Code Changes (Sess):")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, /* @__PURE__ */ React15.createElement(Text15, { color: "green" }, "+", runtimeSession.linesAdded), " ", /* @__PURE__ */ React15.createElement(Text15, { color: "red" }, "-", runtimeSession.linesRemoved))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Tool Calls (Sess):")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, runtimeSession.toolSuccess + runtimeSession.toolFailure + runtimeSession.toolDenied, " ( "), /* @__PURE__ */ React15.createElement(Text15, { color: "green" }, "\u2714 ", runtimeSession.toolSuccess), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, " "), /* @__PURE__ */ React15.createElement(Text15, { color: "yellow" }, "\u{1F6C7} ", runtimeSession.toolDenied), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, " "), /* @__PURE__ */ React15.createElement(Text15, { color: "red" }, "\u2718 ", runtimeSession.toolFailure), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, " )"))), /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, trackerTitle), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, timeLabel)), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatDuration(u?.duration || 0))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Model Requests:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, u?.agent || 0)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Memory Agent:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, u?.background || 0)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, tokensLabel)), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(u?.tokens || 0))), (u?.tokens || 0) > 0 && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 23 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Input Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens((u?.tokens || 0) - (u?.candidateTokens || 0)))), (u?.cachedTokens || 0) > 0 && /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React15.createElement(Box14, { width: 21 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Cached:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(u.cachedTokens))), (u?.candidateTokens || 0) > 0 && /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 23 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Output Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(u.candidateTokens)))), (u?.imageCalls?.length || 0) > 0 && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, imagesLabel)), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, u.imageCalls.length)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, imageCreditsLabel)), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, Number(((u.imageCalls.reduce((sum, c) => sum + c.cost, 0) || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, codeChangesLabel)), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, /* @__PURE__ */ React15.createElement(Text15, { color: "green" }, "+", u?.linesAdded || 0), " ", /* @__PURE__ */ React15.createElement(Text15, { color: "red" }, "-", u?.linesRemoved || 0))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 25 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, toolCallsLabel)), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, (u?.toolSuccess || 0) + (u?.toolFailure || 0) + (u?.toolDenied || 0), " ( "), /* @__PURE__ */ React15.createElement(Text15, { color: "green" }, "\u2714 ", u?.toolSuccess || 0), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, " "), /* @__PURE__ */ React15.createElement(Text15, { color: "yellow" }, "\u{1F6C7} ", u?.toolDenied || 0), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, " "), /* @__PURE__ */ React15.createElement(Text15, { color: "red" }, "\u2718 ", u?.toolFailure || 0), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, " )")))), /* @__PURE__ */ React15.createElement(Text15, { dimColor: true, marginTop: 1, italic: true }, "(Press TAB to toggle Daily/Monthly views, SPACE for Model Breakdown, ESC to return)"));
19487
19620
  }
19488
19621
  case "autoExecDanger":
19489
19622
  return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, "SECURITY WARNING: YOLO MODE"), /* @__PURE__ */ React15.createElement(Text15, { marginTop: 1 }, "Turning this ON allows the agent to execute terminal commands automatically without requiring your approval for each step."), /* @__PURE__ */ React15.createElement(Text15, { marginTop: 1, color: "white" }, "RISKS INVOLVED:"), /* @__PURE__ */ React15.createElement(Text15, null, "\u2022 The agent may execute destructive commands (rm -rf, etc.) by mistake unless specified in sandbox rules."), /* @__PURE__ */ React15.createElement(Text15, null, "\u2022 Unintended system changes if the agent hallucinates a path or command."), /* @__PURE__ */ React15.createElement(Text15, null, "\u2022 Reduced control over the agent's step-by-step decision making."), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(
@@ -20075,15 +20208,15 @@ Selection: ${val}`,
20075
20208
  }
20076
20209
  )), activeView === "exit" && (() => {
20077
20210
  const wallTimeMs = Date.now() - SESSION_START_TIME;
20078
- const totalTools = sessionToolSuccess + sessionToolFailure;
20079
- const successRate = totalTools > 0 ? (sessionToolSuccess / totalTools * 100).toFixed(1) : "0.0";
20211
+ const totalTools = runtimeSession.toolSuccess + runtimeSession.toolFailure;
20212
+ const successRate = totalTools > 0 ? (runtimeSession.toolSuccess / totalTools * 100).toFixed(1) : "0.0";
20080
20213
  const agentActiveMs = sessionApiTime + sessionToolTime;
20081
20214
  const apiPercent = agentActiveMs > 0 ? (sessionApiTime / agentActiveMs * 100).toFixed(1) : "0.0";
20082
20215
  const toolPercent = agentActiveMs > 0 ? (sessionToolTime / agentActiveMs * 100).toFixed(1) : "0.0";
20083
- return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "grey", width: Math.min(100, (stdout?.columns || 100) - 2), marginTop: 0, marginBottom: 0 }, /* @__PURE__ */ React15.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text15, { bold: true }, gradient2(["blue", "purple"])("Agent powering down. Goodbye!"))), /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, "Interaction Summary"), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Session ID:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, chatId)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Tool Calls:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( ", /* @__PURE__ */ React15.createElement(Text15, { color: "green" }, "\u2714 ", sessionToolSuccess), " ", /* @__PURE__ */ React15.createElement(Text15, { color: "yellow" }, "\u{1F6C7} ", sessionToolDenied), " ", /* @__PURE__ */ React15.createElement(Text15, { color: "red" }, "\u2718 ", sessionToolFailure), " )")), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Success Rate:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, successRate, "%")), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Code Changes:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, /* @__PURE__ */ React15.createElement(Text15, { color: "green" }, "+", linesAdded), " ", /* @__PURE__ */ React15.createElement(Text15, { color: "red" }, "-", linesRemoved))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalTokens))), sessionTotalTokens > 0 && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 18 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Input Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalTokens - sessionTotalCandidateTokens))), sessionTotalCachedTokens > 0 && /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React15.createElement(Box14, { width: 16 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Cached:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalCachedTokens))), sessionTotalCandidateTokens > 0 && /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 18 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Output Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalCandidateTokens)))), sessionImageCount > 0 && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Images Made:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, sessionImageCount)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Image Credits:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits")))), /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, "Performance"), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Wall Time:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(wallTimeMs))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Agent Active:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(agentActiveMs))), /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 18 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB API Time:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(sessionApiTime), " (", apiPercent, "%)")), /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 18 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Tool Time:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(sessionToolTime), " (", toolPercent, "%)"))));
20216
+ return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "grey", width: Math.min(100, (stdout?.columns || 100) - 2), marginTop: 0, marginBottom: 0 }, /* @__PURE__ */ React15.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text15, { bold: true }, gradient2(["blue", "purple"])("Agent powering down. Goodbye!"))), /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, "Interaction Summary"), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Session ID:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, chatId)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Tool Calls:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, runtimeSession.toolSuccess + runtimeSession.toolFailure + runtimeSession.toolDenied, " ( ", /* @__PURE__ */ React15.createElement(Text15, { color: "green" }, "\u2714 ", runtimeSession.toolSuccess), " ", /* @__PURE__ */ React15.createElement(Text15, { color: "yellow" }, "\u{1F6C7} ", runtimeSession.toolDenied), " ", /* @__PURE__ */ React15.createElement(Text15, { color: "red" }, "\u2718 ", runtimeSession.toolFailure), " )")), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Success Rate:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, successRate, "%")), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Code Changes:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, /* @__PURE__ */ React15.createElement(Text15, { color: "green" }, "+", runtimeSession.linesAdded), " ", /* @__PURE__ */ React15.createElement(Text15, { color: "red" }, "-", runtimeSession.linesRemoved))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalTokens))), sessionTotalTokens > 0 && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 18 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Input Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalTokens - sessionTotalCandidateTokens))), sessionTotalCachedTokens > 0 && /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React15.createElement(Box14, { width: 16 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Cached:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalCachedTokens))), sessionTotalCandidateTokens > 0 && /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 18 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Output Tokens:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatTokens(sessionTotalCandidateTokens)))), sessionImageCount > 0 && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Images Made:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, sessionImageCount)), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Image Credits:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits")))), /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, "Performance"), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Wall Time:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(wallTimeMs))), /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Box14, { width: 20 }, /* @__PURE__ */ React15.createElement(Text15, { color: "blue" }, "Agent Active:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(agentActiveMs))), /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 18 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB API Time:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(sessionApiTime), " (", apiPercent, "%)")), /* @__PURE__ */ React15.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React15.createElement(Box14, { width: 18 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "\xBB Tool Time:")), /* @__PURE__ */ React15.createElement(Text15, { color: "white" }, formatMsDuration(sessionToolTime), " (", toolPercent, "%)"))));
20084
20217
  })())));
20085
20218
  }
20086
- var shouldClearValue, getPrefilledValue, getIDEName, getIDEDirName, getKeybindingsPath, parseJsonc, hasShiftEnterBinding, getPromoOptions, BridgePromo, SESSION_START_TIME, CHANGELOG_URL, DOCS_URL, linesAdded, linesRemoved, packageJsonPath, packageJson, versionFluxflow, updatedOn, ResolutionModal, parseAgentText, getProjectFiles, cachedShortcut, getLatencyColor2, SubagentRow;
20219
+ var shouldClearValue, getPrefilledValue, getIDEName, getIDEDirName, getKeybindingsPath, parseJsonc, hasShiftEnterBinding, getPromoOptions, BridgePromo, SESSION_START_TIME, CHANGELOG_URL, DOCS_URL, packageJsonPath, packageJson, versionFluxflow, updatedOn, ResolutionModal, parseAgentText, getProjectFiles, cachedShortcut, getLatencyColor2, SubagentRow;
20087
20220
  var init_app = __esm({
20088
20221
  async "src/app.jsx"() {
20089
20222
  init_build();
@@ -20214,8 +20347,6 @@ var init_app = __esm({
20214
20347
  SESSION_START_TIME = Date.now();
20215
20348
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog";
20216
20349
  DOCS_URL = "https://fluxflow-cli.onrender.com/";
20217
- linesAdded = 0;
20218
- linesRemoved = 0;
20219
20350
  packageJsonPath = path22.join(path22.dirname(fileURLToPath2(import.meta.url)), "../package.json");
20220
20351
  packageJson = JSON.parse(fs24.readFileSync(packageJsonPath, "utf8"));
20221
20352
  versionFluxflow = packageJson.version;
@@ -20340,10 +20471,10 @@ var init_app = __esm({
20340
20471
  })();
20341
20472
  cachedShortcut = "Ctrl + Enter";
20342
20473
  getLatencyColor2 = (delay) => {
20343
- if (delay <= 400) return "#00a564";
20474
+ if (delay <= 500) return "#00a564";
20344
20475
  if (delay >= 5e3) return "#ff0000";
20345
20476
  const points = [
20346
- { t: 400, r: 0, g: 165, b: 100 },
20477
+ { t: 500, r: 0, g: 165, b: 100 },
20347
20478
  { t: 800, r: 120, g: 220, b: 80 },
20348
20479
  { t: 1500, r: 250, g: 210, b: 40 },
20349
20480
  { t: 3e3, r: 255, g: 120, b: 0 },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "3.1.7",
4
- "date": "2026-07-06",
3
+ "version": "3.2.0",
4
+ "date": "2026-07-07",
5
5
  "description": "A High-Fidelity Agentic CLI with Sub-Agents for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",