fluxflow-cli 3.2.2 → 3.2.4

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 +88 -69
  2. package/package.json +2 -2
package/dist/fluxflow.js CHANGED
@@ -2138,7 +2138,8 @@ var init_text = __esm({
2138
2138
  if (currentVisibleLength + tokenVisibleLength > width) {
2139
2139
  if (currentLine.trim().length > 0) {
2140
2140
  finalLines.push(currentLine.trimEnd());
2141
- currentLine = indent + token;
2141
+ const cappedIndent = indent.substring(0, Math.min(indent.length, 8));
2142
+ currentLine = cappedIndent + token;
2142
2143
  currentVisibleLength = getVisibleLength(currentLine);
2143
2144
  } else {
2144
2145
  if (ansiRegex.test(token)) {
@@ -2227,36 +2228,20 @@ var init_text = __esm({
2227
2228
  };
2228
2229
  const adjustIndentation = (newText, originalMatch, leadingContext = "") => {
2229
2230
  if (!newText || originalMatch === void 0) return newText;
2230
- const getIndentStyle = (text) => {
2231
- const lines = text.split("\n").filter((l) => l.trim() !== "");
2232
- if (lines.length === 0) return { char: " ", size: 4 };
2233
- const firstIndent = lines[0].match(/^\s*/)[0];
2234
- if (firstIndent.includes(" ")) return { char: " ", size: 1 };
2235
- const indents = lines.map((l) => l.match(/^\s*/)[0].length).filter((l) => l > 0);
2236
- if (indents.length === 0) return { char: " ", size: firstIndent.length || 4 };
2237
- const gcd = (a, b) => b ? gcd(b, a % b) : a;
2238
- const step = indents.reduce((a, b) => gcd(a, b));
2239
- return { char: " ", size: step || 4 };
2240
- };
2241
- const fileStyle = getIndentStyle(originalMatch);
2242
- const modelStyle = getIndentStyle(newText);
2243
- const matchMinIndent = getMinIndent(originalMatch).length;
2244
- const leadingIndent = (leadingContext.match(/^\s*/) || [""])[0].length;
2245
- const targetBaseIndentRaw = leadingIndent + matchMinIndent;
2246
- const targetUnits = targetBaseIndentRaw / fileStyle.size;
2247
- const modelBaseUnits = getMinIndent(newText).length / modelStyle.size;
2248
- const deltaUnits = targetUnits - modelBaseUnits;
2231
+ const usesTabs = /^\t/m.test(originalMatch);
2232
+ const indentChar = usesTabs ? " " : " ";
2233
+ const firstNonEmpty = (text) => text.split("\n").find((l) => l.trim() !== "") ?? "";
2234
+ const origFirstIndent = firstNonEmpty(originalMatch).match(/^\s*/)[0].length;
2235
+ const newFirstIndent = firstNonEmpty(newText).match(/^\s*/)[0].length;
2236
+ const delta = origFirstIndent - newFirstIndent;
2237
+ const leadingLen = (leadingContext.match(/^\s*/) || [""])[0].length;
2249
2238
  const newLines = newText.split("\n");
2250
2239
  return newLines.map((line, i) => {
2251
2240
  if (line.trim() === "" && i !== 0) return "";
2252
- const currentLineUnits = line.match(/^\s*/)[0].length / modelStyle.size;
2253
- const finalUnits = Math.max(0, currentLineUnits + deltaUnits);
2254
- let unitCount = finalUnits;
2255
- if (i === 0) {
2256
- const leadingUnits = leadingIndent / fileStyle.size;
2257
- unitCount = Math.max(0, finalUnits - leadingUnits);
2258
- }
2259
- return fileStyle.char.repeat(unitCount * fileStyle.size) + line.trimStart();
2241
+ const currentIndent = line.match(/^\s*/)[0].length;
2242
+ let targetIndent = Math.max(0, currentIndent + delta);
2243
+ if (i === 0) targetIndent = Math.max(0, targetIndent - leadingLen);
2244
+ return indentChar.repeat(targetIndent) + line.trimStart();
2260
2245
  }).join("\n");
2261
2246
  };
2262
2247
  const patchMatches = [];
@@ -4311,12 +4296,12 @@ var init_ChatLayout = __esm({
4311
4296
  const renderInlineDiff = () => {
4312
4297
  if (isPureUnpairedBlock) {
4313
4298
  const blockColor = isRemoval ? "#ffdddd" : "#ddffdd";
4314
- const wrappedLines = wrapText(content, columns - 14).split("\n");
4299
+ const wrappedLines = wrapText(content, columns - 15).split("\n");
4315
4300
  return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, blockColor))));
4316
4301
  }
4317
4302
  if (!(isRemoval || isAddition) || words.length === 0 || !hasInlineChange) {
4318
4303
  const textColor = isRemoval ? "#885555" : isAddition ? "#558866" : "gray";
4319
- const wrappedLines = wrapText(content, columns - 14).split("\n");
4304
+ const wrappedLines = wrapText(content, columns - 15).split("\n");
4320
4305
  return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, textColor))));
4321
4306
  }
4322
4307
  return /* @__PURE__ */ React4.createElement(Text4, { wrap: "anywhere" }, words.map((part, idx) => {
@@ -4340,7 +4325,7 @@ var init_ChatLayout = __esm({
4340
4325
  return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "gray" }, part.value);
4341
4326
  }));
4342
4327
  };
4343
- return /* @__PURE__ */ React4.createElement(Box3, { backgroundColor: "#1a1a1a", paddingX: 1, width: columns }, /* @__PURE__ */ React4.createElement(Box3, { width: 3, flexShrink: 0, justifyContent: "flex-end" }, /* @__PURE__ */ React4.createElement(Text4, { color: finalNumColor }, lineNum)), /* @__PURE__ */ React4.createElement(Box3, { width: 1, flexShrink: 0, marginLeft: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: finalPrefixColor }, displayPrefix)), /* @__PURE__ */ React4.createElement(Box3, { marginLeft: 1, backgroundColor: innerBgColor, flexShrink: 1 }, renderInlineDiff()));
4328
+ return /* @__PURE__ */ React4.createElement(Box3, { backgroundColor: "#1a1a1a", paddingX: 1, width: columns }, /* @__PURE__ */ React4.createElement(Box3, { width: 4, flexShrink: 0, justifyContent: "flex-end" }, /* @__PURE__ */ React4.createElement(Text4, { color: finalNumColor }, lineNum)), /* @__PURE__ */ React4.createElement(Box3, { width: 1, flexShrink: 0, marginLeft: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: finalPrefixColor }, displayPrefix)), /* @__PURE__ */ React4.createElement(Box3, { marginLeft: 1, backgroundColor: innerBgColor, flexShrink: 1 }, renderInlineDiff()));
4344
4329
  });
4345
4330
  DiffBlock = React4.memo(({ text, columns = 80, extension }) => {
4346
4331
  const match = text.match(/\[DIFF_START\]([\s\S]*?)(?:\[DIFF_END\]|$)/);
@@ -4530,12 +4515,8 @@ var init_ChatLayout = __esm({
4530
4515
  Box3,
4531
4516
  {
4532
4517
  flexDirection: "column",
4533
- borderStyle: "single",
4534
- borderLeft: true,
4535
- borderRight: false,
4536
- borderTop: false,
4537
- borderBottom: false,
4538
- borderColor: "#444444",
4518
+ borderStyle: "round",
4519
+ border: true,
4539
4520
  paddingLeft: 2,
4540
4521
  paddingRight: 0,
4541
4522
  paddingTop: 1,
@@ -4552,12 +4533,8 @@ var init_ChatLayout = __esm({
4552
4533
  Box3,
4553
4534
  {
4554
4535
  flexDirection: "column",
4555
- borderStyle: "single",
4556
- borderLeft: true,
4557
- borderRight: false,
4558
- borderTop: false,
4559
- borderBottom: false,
4560
- borderColor: "#444444",
4536
+ borderStyle: "round",
4537
+ border: true,
4561
4538
  paddingLeft: 2,
4562
4539
  paddingRight: 0,
4563
4540
  paddingTop: 1,
@@ -4744,7 +4721,7 @@ var init_ChatLayout = __esm({
4744
4721
  paddingLeft: 2,
4745
4722
  width: "100%"
4746
4723
  },
4747
- /* @__PURE__ */ React4.createElement(Box3, { width: 4, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray", dimColor: true }, String(lineNum).padStart(3, " "), " ")),
4724
+ /* @__PURE__ */ React4.createElement(Box3, { width: 5, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray", dimColor: true }, String(lineNum).padStart(4, " "), " ")),
4748
4725
  /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, renderHighlightedLine(text, lang, "#e1e4e8"))
4749
4726
  );
4750
4727
  }
@@ -4852,16 +4829,30 @@ var init_StatusBar = __esm({
4852
4829
  if (delay >= 5e3) return "#ff0000";
4853
4830
  const points = [
4854
4831
  { t: 370, r: 0, g: 165, b: 100 },
4855
- { t: 800, r: 120, g: 220, b: 80 },
4856
- { t: 1500, r: 250, g: 210, b: 40 },
4857
- { t: 3e3, r: 255, g: 120, b: 0 },
4832
+ // deep green
4833
+ { t: 550, r: 40, g: 195, b: 80 },
4834
+ // green
4835
+ { t: 800, r: 120, g: 220, b: 50 },
4836
+ // lime-green
4837
+ { t: 1100, r: 190, g: 225, b: 20 },
4838
+ // yellow-green
4839
+ { t: 1500, r: 250, g: 210, b: 15 },
4840
+ // yellow
4841
+ { t: 2e3, r: 255, g: 170, b: 0 },
4842
+ // amber
4843
+ { t: 2800, r: 255, g: 110, b: 0 },
4844
+ // orange
4845
+ { t: 3800, r: 255, g: 50, b: 0 },
4846
+ // deep orange
4858
4847
  { t: 5e3, r: 255, g: 0, b: 0 }
4848
+ // red
4859
4849
  ];
4860
4850
  for (let i = 0; i < points.length - 1; i++) {
4861
4851
  const p1 = points[i];
4862
4852
  const p2 = points[i + 1];
4863
4853
  if (delay >= p1.t && delay <= p2.t) {
4864
- const ratio = (delay - p1.t) / (p2.t - p1.t);
4854
+ let ratio = (delay - p1.t) / (p2.t - p1.t);
4855
+ ratio = ratio * ratio * (3 - 2 * ratio);
4865
4856
  const r = Math.round(p1.r + (p2.r - p1.r) * ratio);
4866
4857
  const g = Math.round(p1.g + (p2.g - p1.g) * ratio);
4867
4858
  const b = Math.round(p1.b + (p2.b - p1.b) * ratio);
@@ -4877,6 +4868,7 @@ var init_StatusBar = __esm({
4877
4868
  const [memoryUnit, setMemoryUnit] = useState5("MB");
4878
4869
  const [dotColor, setDotColor] = useState5("green");
4879
4870
  const chunkTimesRef = useRef3([]);
4871
+ const smoothedDelayRef = useRef3(370);
4880
4872
  useEffect4(() => {
4881
4873
  if (!isProcessing) {
4882
4874
  chunkTimesRef.current = [];
@@ -4886,7 +4878,7 @@ var init_StatusBar = __esm({
4886
4878
  const times = chunkTimesRef.current;
4887
4879
  if (times.length === 0 || times[times.length - 1] !== lastChunkTime) {
4888
4880
  times.push(lastChunkTime);
4889
- if (times.length > 5) {
4881
+ if (times.length > 10) {
4890
4882
  times.shift();
4891
4883
  }
4892
4884
  }
@@ -4906,8 +4898,13 @@ var init_StatusBar = __esm({
4906
4898
  averageInterval = sum / (times.length - 1);
4907
4899
  }
4908
4900
  const timeSinceLast = Date.now() - lastChunkTime;
4909
- const delay = Math.max(averageInterval, timeSinceLast);
4910
- setDotColor(getLatencyColor(delay));
4901
+ const STALL_THRESHOLD = 2500;
4902
+ const isStalled = timeSinceLast >= STALL_THRESHOLD;
4903
+ const cappedTimeSinceLast = !isStalled && averageInterval > 0 ? Math.min(timeSinceLast, averageInterval * 3) : timeSinceLast;
4904
+ const rawDelay = Math.max(averageInterval, cappedTimeSinceLast);
4905
+ const alpha = isStalled ? 0.4 : 0.2;
4906
+ smoothedDelayRef.current = smoothedDelayRef.current * (1 - alpha) + rawDelay * alpha;
4907
+ setDotColor(getLatencyColor(smoothedDelayRef.current));
4911
4908
  };
4912
4909
  checkLatency();
4913
4910
  const timer = setInterval(checkLatency, 100);
@@ -5200,11 +5197,11 @@ Info: 'initial' = user prompted for THIS active task, revert 'id' should be a tu
5200
5197
  1. [tool:functions.EmergencyRollback(method="getCheckpoint/forceRevert", id="...")]. Rollback workspace to a specific checkpoint in THIS agent loop. Usage: ONLY in catastrophic situations. Verify nothing catastrophic happened in codebase before ending agent loop. 'id' not needed with getCheckPoint
5201
5198
  ` : ""}
5202
5199
  - SUB AGENT TOOLS -
5203
- **PROACTIVE USE OF SUB AGENTS HIGHLY RECOMMENDED, PREFER USING FOR ALL TASK WHERE PLAUSIBLE & BENEFICIAL, EVEN WITHOUT EXPLICIT USER NUDGE**
5200
+ **PROACTIVE USE OF SUB AGENTS HIGHLY RECOMMENDED, PREFER USING FOR ALL TASK WHERE EVEN SLIGHTLY BENEFICIAL, EVEN WITHOUT EXPLICIT USER NUDGE**
5204
5201
  Invocation Types:
5205
5202
  - Invoke (async, background worker for parallel tasks, upto 7 parallel agents together). Usage: Benefits parallelism & speed. Can take long time, If invoked DO NOT REPEAT SAME TASK WHILE ACTIVE
5206
- - InvokeSync (sync, blocking main agent loop). Usage: Repeatetive work, Sequential tasks, Task delegation. Huge tokens/costs savings
5207
- 1. [agent:generalist.InvokeSync/Invoke(title="...", task="...")]. Task must me detailed, including exact file paths, imports/exports, dependency, folder structure
5203
+ - InvokeSync (sync, blocking main agent loop). Usage: Repeatetive work, Sequential tasks, Task delegation. Tokens/Costs savings
5204
+ 1. [agent:generalist.InvokeSync/Invoke(title="...", task="...")]. Task must me detailed, including exact file paths, imports/exports, dependency, folder structure. No terminal access
5208
5205
  2. [agent:generalist.GetProgress(id="...")]. Usage: Check progress of async subagent task, taking time? continue your task, MUST await (exponentially longer after 1st check) than spamming getProgress. NEVER FINISH WITHOUT 'AWAIT' WHILE SUBAGENT WORKING
5209
5206
  3. [agent:generalist.Cancel(id="...")]. Usage: Cancel async subagent task, LAST RESORT ONLY IF ITS STUCK FOR UNUSUALLY LONG (2m+) WITH NO PROGRESS`.trim() : `- CREATIVE TOOLS (path = relative to CWD & WILL BE FIRST ARGUMENT, path separator: '/') -
5210
5207
  1. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. PROACTIVE A4 PAGE BREAKS MUST IN CSS. HTML/CSS for PREMIUM layout
@@ -10763,7 +10760,7 @@ var init_ai = __esm({
10763
10760
  "openai/gpt-5.5-pro",
10764
10761
  "moonshotai/kimi-k2.6",
10765
10762
  // NVIDIA vision models
10766
- "moonshotai/kimi-k2.6",
10763
+ "moonshotai/kimi-k2.7",
10767
10764
  "stepfun-ai/step-3.7-flash",
10768
10765
  "google/gemma-4-31b-it",
10769
10766
  "mistralai/mistral-medium-3.5-128b",
@@ -11193,6 +11190,8 @@ var init_ai = __esm({
11193
11190
  push({ value: { type: "status", content: `Queue ${depth || 1}` }, done: false });
11194
11191
  }
11195
11192
  }
11193
+ } else if (!isStreamingStarted) {
11194
+ push({ value: { type: "status", content: `Queue '${res.status}'` }, done: false });
11196
11195
  }
11197
11196
  } catch (e) {
11198
11197
  }
@@ -14953,7 +14952,7 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
14953
14952
  "filemap": '- [tool:functions.FileMap(path="path/file")]. Shows file structure, functions, classes, imports/exports',
14954
14953
  "patchfile": '- [tool:functions.PatchFile(path="...", replaceContent1="...", newContent1="...")]. Surgical block replacement for editing files',
14955
14954
  "writefile": '- [tool:functions.WriteFile(path="...", content="...")]. Creates or overwrites a file',
14956
- "searchkeyword": '- [tool:functions.SearchKeyword(keyword="...", file="optional", subString="true/false")]. Global project text search',
14955
+ "searchkeyword": `- [tool:functions.SearchKeyword(keyword="...", file="optional", subString="true/false optional", regex="true/false optional")]. Global project search. If 'file' is provided, searches only that file. Finds definitions/logic without reading every file. Usage: Can search for relevent lines/logic area to read specifically for edit. Optional parameters default to false`,
14957
14956
  "websearch": '- [tool:functions.WebSearch(query="...", limit=number)]. Web Search',
14958
14957
  "webscrape": '- [tool:functions.WebScrape(url="...")]. Web Scrape',
14959
14958
  "ask": `- [tool:functions.Ask(question="...", optionA="option::description", ...MAX 4)]. Ambiguity Resolution. Mandatory Triggers: Path Divergence, Security, Risk Mitigation. ask >> finish/guess. Suggest best options; don't ask for preferences. 'option' SHOULD be short`
@@ -16033,7 +16032,7 @@ var init_GlintText = __esm({
16033
16032
  return () => clearInterval(timer);
16034
16033
  }, [displayedText.length, speed, glintWidth]);
16035
16034
  useEffect11(() => {
16036
- if (text && text.includes("Trying to reach") && displayedText && displayedText.includes("Trying to reach")) {
16035
+ if (text && (text.includes("Trying to reach") && displayedText && displayedText.includes("Trying to reach") || text.includes("Error Occurred") && displayedText && displayedText.includes("Error Occurred"))) {
16037
16036
  setDisplayedText(text);
16038
16037
  return;
16039
16038
  }
@@ -17469,9 +17468,13 @@ function App({ args = [] }) {
17469
17468
  ] : aiProvider === "NVIDIA" ? [
17470
17469
  // --- Kimi (Moonshot AI) ---
17471
17470
  {
17472
- cmd: "moonshotai/kimi-k2.6",
17471
+ cmd: "moonshotai/kimi-k2.7",
17473
17472
  desc: "Multimodal"
17474
17473
  },
17474
+ {
17475
+ cmd: "moonshotai/kimi-k2.6",
17476
+ desc: "[DEPRICATED]"
17477
+ },
17475
17478
  // --- DeepSeek Family ---
17476
17479
  {
17477
17480
  cmd: "deepseek-ai/deepseek-v4-flash",
@@ -17510,10 +17513,6 @@ function App({ args = [] }) {
17510
17513
  desc: "Text Only"
17511
17514
  },
17512
17515
  // --- GLM (Zhipu AI) ---
17513
- {
17514
- cmd: "z-ai/glm-5.1",
17515
- desc: "Text Only [DEPRICATED]"
17516
- },
17517
17516
  {
17518
17517
  cmd: "z-ai/glm-5.2",
17519
17518
  desc: "Text Only"
@@ -20625,16 +20624,30 @@ var init_app = __esm({
20625
20624
  if (delay >= 5e3) return "#ff0000";
20626
20625
  const points = [
20627
20626
  { t: 370, r: 0, g: 165, b: 100 },
20628
- { t: 800, r: 120, g: 220, b: 80 },
20629
- { t: 1500, r: 250, g: 210, b: 40 },
20630
- { t: 3e3, r: 255, g: 120, b: 0 },
20627
+ // deep green
20628
+ { t: 550, r: 40, g: 195, b: 80 },
20629
+ // green
20630
+ { t: 800, r: 120, g: 220, b: 50 },
20631
+ // lime-green
20632
+ { t: 1100, r: 190, g: 225, b: 20 },
20633
+ // yellow-green
20634
+ { t: 1500, r: 250, g: 210, b: 15 },
20635
+ // yellow
20636
+ { t: 2e3, r: 255, g: 170, b: 0 },
20637
+ // amber
20638
+ { t: 2800, r: 255, g: 110, b: 0 },
20639
+ // orange
20640
+ { t: 3800, r: 255, g: 50, b: 0 },
20641
+ // deep orange
20631
20642
  { t: 5e3, r: 255, g: 0, b: 0 }
20643
+ // red
20632
20644
  ];
20633
20645
  for (let i = 0; i < points.length - 1; i++) {
20634
20646
  const p1 = points[i];
20635
20647
  const p2 = points[i + 1];
20636
20648
  if (delay >= p1.t && delay <= p2.t) {
20637
- const ratio = (delay - p1.t) / (p2.t - p1.t);
20649
+ let ratio = (delay - p1.t) / (p2.t - p1.t);
20650
+ ratio = ratio * ratio * (3 - 2 * ratio);
20638
20651
  const r = Math.round(p1.r + (p2.r - p1.r) * ratio);
20639
20652
  const g = Math.round(p1.g + (p2.g - p1.g) * ratio);
20640
20653
  const b = Math.round(p1.b + (p2.b - p1.b) * ratio);
@@ -20646,6 +20659,7 @@ var init_app = __esm({
20646
20659
  SubagentRow = React16.memo(({ sa }) => {
20647
20660
  const [dotColor, setDotColor] = useState15("green");
20648
20661
  const chunkTimesRef = useRef4([]);
20662
+ const smoothedDelayRef = useRef4(370);
20649
20663
  useEffect12(() => {
20650
20664
  if (sa.status !== "running") {
20651
20665
  chunkTimesRef.current = [];
@@ -20656,7 +20670,7 @@ var init_app = __esm({
20656
20670
  const times = chunkTimesRef.current;
20657
20671
  if (times.length === 0 || times[times.length - 1] !== lastChunkTime) {
20658
20672
  times.push(lastChunkTime);
20659
- if (times.length > 5) {
20673
+ if (times.length > 10) {
20660
20674
  times.shift();
20661
20675
  }
20662
20676
  }
@@ -20676,8 +20690,13 @@ var init_app = __esm({
20676
20690
  averageInterval = sum / (times.length - 1);
20677
20691
  }
20678
20692
  const timeSinceLast = Date.now() - lastChunkTime;
20679
- const delay = Math.max(averageInterval, timeSinceLast);
20680
- setDotColor(getLatencyColor2(delay));
20693
+ const STALL_THRESHOLD = 2500;
20694
+ const isStalled = timeSinceLast >= STALL_THRESHOLD;
20695
+ const cappedTimeSinceLast = !isStalled && averageInterval > 0 ? Math.min(timeSinceLast, averageInterval * 3) : timeSinceLast;
20696
+ const rawDelay = Math.max(averageInterval, cappedTimeSinceLast);
20697
+ const alpha = isStalled ? 0.4 : 0.2;
20698
+ smoothedDelayRef.current = smoothedDelayRef.current * (1 - alpha) + rawDelay * alpha;
20699
+ setDotColor(getLatencyColor2(smoothedDelayRef.current));
20681
20700
  };
20682
20701
  checkLatency();
20683
20702
  const timer = setInterval(checkLatency, 100);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "3.2.2",
4
- "date": "2026-07-07",
3
+ "version": "3.2.4",
4
+ "date": "2026-07-08",
5
5
  "description": "A High-Fidelity Agentic CLI with Sub-Agents for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",