fluxflow-cli 1.11.3 → 1.12.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 (3) hide show
  1. package/README.md +19 -0
  2. package/dist/fluxflow.js +361 -220
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -83,6 +83,25 @@ While you move at high speed, the Janitor follows behind—refining session titl
83
83
 
84
84
  ---
85
85
 
86
+ ## 💻 CLI Startup Arguments
87
+ Customize your session parameters directly from your console launch command:
88
+
89
+ ```bash
90
+ fluxflow [options]
91
+ ```
92
+
93
+ ### Supported Flags:
94
+ - `--model <model-name>`: Temporary override for the active AI model (e.g., `gemini-2.5-pro`). Keeps settings file untouched.
95
+ - `--memory <on|off>`: Toggle persistent long-term agent memory for the session.
96
+ - `--resume <session-id>`: Resume a previous chat session programmatically.
97
+ - `--update <check|latest>`: Manually run an update check (`check`) or execute latest update setup (`latest`).
98
+ - `--package <npm|pnpm|yarn|bun>`: Override default package manager to run core application updates.
99
+ - `--auto-del <1d|7d|30d>`: Set automated chat log deletion schedule.
100
+ - `--auto-exec <on|off>`: Toggle autonomous command execution permission.
101
+ - `--external-access <on|off>`: Toggle permission to let agent read files outside CWD.
102
+
103
+ ---
104
+
86
105
  ## ⚙️ Configuration
87
106
  Type `/settings` in-app to live-configure:
88
107
  - **Thinking Level**: Fast (No Reasoning), Low, Medium, High, xHigh (Extended Reasoning).
package/dist/fluxflow.js CHANGED
@@ -609,18 +609,26 @@ var init_CommandMenu = __esm({
609
609
  });
610
610
 
611
611
  // src/components/ProfileForm.jsx
612
- import React5, { useState as useState2 } from "react";
612
+ import React5, { useState as useState2, useEffect as useEffect2 } from "react";
613
613
  import { Box as Box5, Text as Text5 } from "ink";
614
614
  import TextInput from "ink-text-input";
615
- function ProfileForm({ onSave, onCancel }) {
615
+ function ProfileForm({ initialData, onSave, onCancel }) {
616
616
  const [step, setStep] = useState2(0);
617
617
  const [currentInput, setCurrentInput] = useState2("");
618
- const [profile, setProfile] = useState2({ name: "", nickname: "", instructions: "" });
618
+ const [profile, setProfile] = useState2(() => ({
619
+ name: initialData?.name || "",
620
+ nickname: initialData?.nickname || "",
621
+ instructions: initialData?.instructions || ""
622
+ }));
619
623
  const steps = [
620
624
  { key: "name", label: "Enter your Name: " },
621
625
  { key: "nickname", label: "Enter a Nickname (Agent will use this): " },
622
626
  { key: "instructions", label: "System Instructions (Persona overrides): " }
623
627
  ];
628
+ useEffect2(() => {
629
+ const currentKey = steps[step].key;
630
+ setCurrentInput(profile[currentKey] || "");
631
+ }, [step, profile]);
624
632
  const handleSubmit = (val) => {
625
633
  if (val.trim().toLowerCase() === "/cancel") {
626
634
  onCancel();
@@ -714,7 +722,8 @@ var init_AskUserModal = __esm({
714
722
  flexDirection: "column",
715
723
  width: "100%",
716
724
  backgroundColor: isSelected ? "#2a2a2a" : void 0,
717
- paddingX: 1
725
+ paddingX: 1,
726
+ marginBottom: idx === allOptions.length - 1 ? 0 : 1
718
727
  },
719
728
  /* @__PURE__ */ React6.createElement(Text6, { color: isSelected ? "cyan" : "white", bold: isSelected }, isSelected ? "\u276F " : " ", opt.label),
720
729
  opt.description && /* @__PURE__ */ React6.createElement(Box6, { marginLeft: 4 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", italic: true, dimColor: true }, opt.description))
@@ -952,11 +961,11 @@ ${mode === "Flux" ? `- FILE TOOLS (path = relative to CWD) -
952
961
  2. [tool:functions.ReadFolder(path="...")]. Detailed DIR stats
953
962
  3. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? -> update_file > write_file
954
963
  4. [tool:functions.PatchFile(path="...", content_to_replace="exact old content", content_to_add="new content")]. Surgical patching. Unsure content_to_replace? -> view_file >> guessing.
955
- 5. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. A4 PDF. Use CSS for layout (100vh/vw). Handle page breaks; no manual footers
964
+ 5. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. A4 PDF. HTML/CSS for premium layout (100vh/vw). Handle page breaks; no manual footers
956
965
  6. [tool:functions.WriteDoc(path="...", content="...")]. A4 Word doc. Proper margins and page breaks
957
966
  7. [tool:functions.Run(command="...")]. Runs a shell command. Destructive/Irreversible ops -> ask user
958
967
  8. [tool:functions.SearchKeyword(keyword="...")]. Global search. Finds definitions/logic without reading every file
959
- 9. [tool:functions.GenerateImage(path="... png", prompt="...", ratio="16:9, 9:16, 1:1, 4:3, 3:4")]. AI images. Usage: Mockups, PDF thumbnails, any visual content
968
+ 9. [tool:functions.GenerateImage(path="... png", prompt="detailed", ratio="16:9, 9:16, 1:1, 4:3, 3:4")]. AI images. Usage: Mockups, PDF thumbnails, any visual content
960
969
 
961
970
  - VERIFY RESULT CONTENTS. Fix errors. No hallucinations
962
971
  - File tools > code chat
@@ -1404,18 +1413,49 @@ var init_usage = __esm({
1404
1413
  };
1405
1414
  loadUsageFromFile = async () => {
1406
1415
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1416
+ const tempFile = USAGE_FILE + ".tmp";
1407
1417
  let primaryData = null;
1408
1418
  let backupData = null;
1409
1419
  try {
1410
- if (await fs6.exists(USAGE_FILE)) {
1411
- const rawContent = (await fs6.readFile(USAGE_FILE, "utf8")).trim();
1420
+ if (await fs6.exists(tempFile)) {
1421
+ const rawContent = (await fs6.readFile(tempFile, "utf8")).trim();
1422
+ let parsed = null;
1412
1423
  if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
1413
- primaryData = JSON.parse(rawContent);
1424
+ parsed = JSON.parse(rawContent);
1425
+ } else {
1426
+ parsed = JSON.parse(decryptAes(rawContent));
1427
+ }
1428
+ if (parsed && parsed.date && parsed.stats) {
1429
+ primaryData = parsed;
1430
+ try {
1431
+ await fs6.rename(tempFile, USAGE_FILE);
1432
+ } catch (e) {
1433
+ }
1414
1434
  } else {
1415
- primaryData = JSON.parse(decryptAes(rawContent));
1435
+ try {
1436
+ await fs6.remove(tempFile);
1437
+ } catch (e) {
1438
+ }
1416
1439
  }
1417
1440
  }
1418
1441
  } catch (err) {
1442
+ try {
1443
+ await fs6.remove(tempFile);
1444
+ } catch (e) {
1445
+ }
1446
+ }
1447
+ if (!primaryData) {
1448
+ try {
1449
+ if (await fs6.exists(USAGE_FILE)) {
1450
+ const rawContent = (await fs6.readFile(USAGE_FILE, "utf8")).trim();
1451
+ if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
1452
+ primaryData = JSON.parse(rawContent);
1453
+ } else {
1454
+ primaryData = JSON.parse(decryptAes(rawContent));
1455
+ }
1456
+ }
1457
+ } catch (err) {
1458
+ }
1419
1459
  }
1420
1460
  try {
1421
1461
  if (await fs6.exists(BACKUP_FILE)) {
@@ -2148,70 +2188,9 @@ var init_chat = __esm({
2148
2188
  }
2149
2189
  });
2150
2190
 
2151
- // src/tools/list_files.js
2191
+ // src/tools/view_file.js
2152
2192
  import fs7 from "fs";
2153
2193
  import path6 from "path";
2154
- var list_files;
2155
- var init_list_files = __esm({
2156
- "src/tools/list_files.js"() {
2157
- init_arg_parser();
2158
- list_files = async (args) => {
2159
- const { path: targetPath = "." } = parseArgs(args);
2160
- const absolutePath = path6.resolve(process.cwd(), targetPath);
2161
- try {
2162
- if (!fs7.existsSync(absolutePath)) {
2163
- return `ERROR: Path [${targetPath}] does not exist.`;
2164
- }
2165
- const stats = fs7.statSync(absolutePath);
2166
- if (!stats.isDirectory()) {
2167
- return `ERROR: Path [${targetPath}] is a file, not a directory. Use view_file instead.`;
2168
- }
2169
- const files = fs7.readdirSync(absolutePath);
2170
- if (files.length === 0) {
2171
- return `Directory [${targetPath}] is empty.`;
2172
- }
2173
- const totalFiles = files.length;
2174
- const maxDisplay = 100;
2175
- const displayFiles = files.slice(0, maxDisplay);
2176
- const list = displayFiles.map((file) => {
2177
- const fPath = path6.join(absolutePath, file);
2178
- let indicator = "\u{1F4C4}";
2179
- let metaPart = "";
2180
- try {
2181
- const fStats = fs7.statSync(fPath);
2182
- indicator = fStats.isDirectory() ? "\u{1F4C1}" : "\u{1F4C4}";
2183
- const sizeKB = (fStats.size / 1024).toFixed(1);
2184
- metaPart = fStats.isFile() ? ` - [${sizeKB} KB]` : "";
2185
- } catch (e) {
2186
- indicator = "\u2753";
2187
- metaPart = " - [Access Denied]";
2188
- }
2189
- return `${indicator} ${file}${metaPart}`;
2190
- }).join("\n");
2191
- let footer = `
2192
-
2193
- (Total items: ${totalFiles})`;
2194
- if (totalFiles > maxDisplay) {
2195
- footer = `
2196
-
2197
- \u26A0\uFE0F TRUNCATED: Showing first ${maxDisplay} of ${totalFiles} items. Use more specific paths to see others.`;
2198
- }
2199
- const result = `Contents of [${targetPath}]:
2200
-
2201
- ${list}${footer}`;
2202
- files.length = 0;
2203
- displayFiles.length = 0;
2204
- return result;
2205
- } catch (err) {
2206
- return `ERROR: Failed to list files in [${targetPath}]: ${err.message}`;
2207
- }
2208
- };
2209
- }
2210
- });
2211
-
2212
- // src/tools/view_file.js
2213
- import fs8 from "fs";
2214
- import path7 from "path";
2215
2194
  var view_file;
2216
2195
  var init_view_file = __esm({
2217
2196
  "src/tools/view_file.js"() {
@@ -2223,16 +2202,21 @@ var init_view_file = __esm({
2223
2202
  const finalStart = sLine || 1;
2224
2203
  const finalEnd = eLine || (sLine ? sLine + 800 : 800);
2225
2204
  if (!targetPath) return 'ERROR: Missing "path" argument for view_file.';
2226
- const absolutePath = path7.resolve(process.cwd(), targetPath);
2205
+ const absolutePath = path6.resolve(process.cwd(), targetPath);
2227
2206
  try {
2228
- if (!fs8.existsSync(absolutePath)) {
2207
+ if (!fs7.existsSync(absolutePath)) {
2229
2208
  return `ERROR: File [${targetPath}] does not exist.`;
2230
2209
  }
2231
- const stats = fs8.statSync(absolutePath);
2210
+ const stats = fs7.statSync(absolutePath);
2232
2211
  if (stats.isDirectory()) {
2233
2212
  return `ERROR: Path [${targetPath}] is a directory. Use list_files instead.`;
2234
2213
  }
2235
- const ext = path7.extname(targetPath).toLowerCase();
2214
+ const ext = path6.extname(targetPath).toLowerCase();
2215
+ const videoExtensions = [".mp4", ".mkv", ".avi", ".mov", ".webm", ".flv", ".wmv", ".mpeg", ".mpg"];
2216
+ if (videoExtensions.includes(ext)) {
2217
+ const format = ext.slice(1).toUpperCase();
2218
+ return `ERROR: Unable to read. Type ${format} not supported`;
2219
+ }
2236
2220
  const mimeMap = {
2237
2221
  ".pdf": "application/pdf",
2238
2222
  ".jpg": "image/jpeg",
@@ -2243,7 +2227,7 @@ var init_view_file = __esm({
2243
2227
  ".doc": "application/msword"
2244
2228
  };
2245
2229
  if (mimeMap[ext]) {
2246
- const buffer = fs8.readFileSync(absolutePath);
2230
+ const buffer = fs7.readFileSync(absolutePath);
2247
2231
  const base64 = buffer.toString("base64");
2248
2232
  const mimeType = mimeMap[ext];
2249
2233
  return {
@@ -2256,7 +2240,7 @@ var init_view_file = __esm({
2256
2240
  }
2257
2241
  };
2258
2242
  }
2259
- let content = fs8.readFileSync(absolutePath, "utf8");
2243
+ let content = fs7.readFileSync(absolutePath, "utf8");
2260
2244
  if (content.startsWith("\uFEFF")) {
2261
2245
  content = content.slice(1);
2262
2246
  }
@@ -2279,8 +2263,8 @@ ${code}`;
2279
2263
  });
2280
2264
 
2281
2265
  // src/tools/write_file.js
2282
- import fs9 from "fs";
2283
- import path8 from "path";
2266
+ import fs8 from "fs";
2267
+ import path7 from "path";
2284
2268
  var write_file;
2285
2269
  var init_write_file = __esm({
2286
2270
  "src/tools/write_file.js"() {
@@ -2290,13 +2274,13 @@ var init_write_file = __esm({
2290
2274
  if (!targetPath) return 'ERROR: Missing "path" argument for write_file.';
2291
2275
  if (content === void 0) return 'ERROR: Missing "content" argument for write_file.';
2292
2276
  content = content.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
2293
- const absolutePath = path8.resolve(process.cwd(), targetPath);
2294
- const parentDir = path8.dirname(absolutePath);
2277
+ const absolutePath = path7.resolve(process.cwd(), targetPath);
2278
+ const parentDir = path7.dirname(absolutePath);
2295
2279
  try {
2296
2280
  let ancestry = "";
2297
- if (fs9.existsSync(absolutePath)) {
2281
+ if (fs8.existsSync(absolutePath)) {
2298
2282
  try {
2299
- const oldData = fs9.readFileSync(absolutePath, "utf8");
2283
+ const oldData = fs8.readFileSync(absolutePath, "utf8");
2300
2284
  const lines = oldData.split(/\r?\n/);
2301
2285
  ancestry = `Old File contents:
2302
2286
  ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
@@ -2308,15 +2292,15 @@ ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
2308
2292
  `;
2309
2293
  }
2310
2294
  }
2311
- if (!fs9.existsSync(parentDir)) {
2312
- fs9.mkdirSync(parentDir, { recursive: true });
2295
+ if (!fs8.existsSync(parentDir)) {
2296
+ fs8.mkdirSync(parentDir, { recursive: true });
2313
2297
  }
2314
2298
  const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
2315
2299
  const processedContent = strip(content);
2316
2300
  const lineCount = processedContent.split(/\r?\n/).length;
2317
2301
  const originalSize = Buffer.byteLength(processedContent, "utf8");
2318
- fs9.writeFileSync(absolutePath, processedContent, "utf8");
2319
- let verifiedContent = fs9.readFileSync(absolutePath, "utf8");
2302
+ fs8.writeFileSync(absolutePath, processedContent, "utf8");
2303
+ let verifiedContent = fs8.readFileSync(absolutePath, "utf8");
2320
2304
  const verifiedSize = Buffer.byteLength(verifiedContent, "utf8");
2321
2305
  const verifiedLines = verifiedContent.split(/\r?\n/);
2322
2306
  const verifiedLineCount = verifiedLines.length;
@@ -2352,8 +2336,8 @@ Check if Starting and Ending matches your write.`;
2352
2336
  });
2353
2337
 
2354
2338
  // src/tools/update_file.js
2355
- import fs10 from "fs";
2356
- import path9 from "path";
2339
+ import fs9 from "fs";
2340
+ import path8 from "path";
2357
2341
  var update_file;
2358
2342
  var init_update_file = __esm({
2359
2343
  "src/tools/update_file.js"() {
@@ -2366,18 +2350,18 @@ var init_update_file = __esm({
2366
2350
  const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
2367
2351
  content_to_replace = strip(content_to_replace);
2368
2352
  content_to_add = strip(content_to_add);
2369
- const absolutePath = path9.resolve(process.cwd(), targetPath);
2353
+ const absolutePath = path8.resolve(process.cwd(), targetPath);
2370
2354
  try {
2371
- if (!fs10.existsSync(absolutePath)) {
2355
+ if (!fs9.existsSync(absolutePath)) {
2372
2356
  return `ERROR: File [${targetPath}] does not exist. Use write_file instead.`;
2373
2357
  }
2374
- let diskContent = fs10.readFileSync(absolutePath, "utf8");
2358
+ let diskContent = fs9.readFileSync(absolutePath, "utf8");
2375
2359
  if (diskContent.startsWith("\uFEFF")) {
2376
2360
  diskContent = diskContent.slice(1);
2377
2361
  }
2378
2362
  const normalizedDisk = diskContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
2379
2363
  if (diskContent !== normalizedDisk) {
2380
- fs10.writeFileSync(absolutePath, normalizedDisk, "utf8");
2364
+ fs9.writeFileSync(absolutePath, normalizedDisk, "utf8");
2381
2365
  diskContent = normalizedDisk;
2382
2366
  }
2383
2367
  const currentContent = diskContent;
@@ -2446,7 +2430,7 @@ var init_update_file = __esm({
2446
2430
  const firstLeadingContext = currentContent.substring(firstLineStart, startPos);
2447
2431
  const finalContentToAdd = adjustIndentation(content_to_add, firstMatchContent, firstLeadingContext);
2448
2432
  const finalContentToReplace = firstMatchContent;
2449
- fs10.writeFileSync(absolutePath, newFileContent, "utf8");
2433
+ fs9.writeFileSync(absolutePath, newFileContent, "utf8");
2450
2434
  const allOriginalLines = currentContent.split(/\r?\n/);
2451
2435
  const startLine = currentContent.substring(0, startPos).split(/\r?\n/).length;
2452
2436
  const oldLines = content_to_replace.split(/\r?\n/);
@@ -2709,34 +2693,34 @@ ${finalOutput}`);
2709
2693
  });
2710
2694
 
2711
2695
  // src/tools/read_folder.js
2712
- import fs11 from "fs";
2713
- import path10 from "path";
2696
+ import fs10 from "fs";
2697
+ import path9 from "path";
2714
2698
  var read_folder;
2715
2699
  var init_read_folder = __esm({
2716
2700
  "src/tools/read_folder.js"() {
2717
2701
  init_arg_parser();
2718
2702
  read_folder = async (args) => {
2719
2703
  const { path: targetPath = "." } = parseArgs(args);
2720
- const absolutePath = path10.resolve(process.cwd(), targetPath);
2704
+ const absolutePath = path9.resolve(process.cwd(), targetPath);
2721
2705
  try {
2722
- if (!fs11.existsSync(absolutePath)) {
2706
+ if (!fs10.existsSync(absolutePath)) {
2723
2707
  return `ERROR: Path [${targetPath}] does not exist.`;
2724
2708
  }
2725
- const stats = fs11.statSync(absolutePath);
2709
+ const stats = fs10.statSync(absolutePath);
2726
2710
  if (!stats.isDirectory()) {
2727
2711
  return `ERROR: Path [${targetPath}] is a file, not a directory. Use view_file instead.`;
2728
2712
  }
2729
- const files = fs11.readdirSync(absolutePath);
2713
+ const files = fs10.readdirSync(absolutePath);
2730
2714
  const totalItems = files.length;
2731
2715
  const maxDisplay = 100;
2732
2716
  const displayItems = files.slice(0, maxDisplay);
2733
2717
  const folderData = [];
2734
2718
  for (const file of displayItems) {
2735
- const fPath = path10.join(absolutePath, file);
2719
+ const fPath = path9.join(absolutePath, file);
2736
2720
  let indicator = "\u{1F4C4}";
2737
2721
  let info = { name: file, type: "unknown", size: "N/A", mtime: "N/A" };
2738
2722
  try {
2739
- const fStats = fs11.statSync(fPath);
2723
+ const fStats = fs10.statSync(fPath);
2740
2724
  info = {
2741
2725
  name: file,
2742
2726
  type: fStats.isDirectory() ? "directory" : "file",
@@ -2819,8 +2803,8 @@ var init_ask_user = __esm({
2819
2803
 
2820
2804
  // src/tools/write_pdf.js
2821
2805
  import puppeteer3 from "puppeteer";
2822
- import path11 from "path";
2823
- import fs12 from "fs-extra";
2806
+ import path10 from "path";
2807
+ import fs11 from "fs-extra";
2824
2808
  import { PDFDocument } from "pdf-lib";
2825
2809
  var write_pdf;
2826
2810
  var init_write_pdf = __esm({
@@ -2835,10 +2819,10 @@ var init_write_pdf = __esm({
2835
2819
  } = parseArgs(args);
2836
2820
  if (!targetPath) return 'ERROR: Missing "path" argument for write_pdf.';
2837
2821
  if (!content) return 'ERROR: Missing "content" (HTML/CSS) for write_pdf.';
2838
- const absolutePath = path11.resolve(process.cwd(), targetPath);
2822
+ const absolutePath = path10.resolve(process.cwd(), targetPath);
2839
2823
  let browser = null;
2840
2824
  try {
2841
- await fs12.ensureDir(path11.dirname(absolutePath));
2825
+ await fs11.ensureDir(path10.dirname(absolutePath));
2842
2826
  browser = await puppeteer3.launch({
2843
2827
  headless: true,
2844
2828
  args: [
@@ -2858,11 +2842,11 @@ var init_write_pdf = __esm({
2858
2842
  continue;
2859
2843
  }
2860
2844
  try {
2861
- const imgPath = path11.resolve(process.cwd(), originalSrc);
2862
- if (await fs12.pathExists(imgPath)) {
2863
- const ext = path11.extname(imgPath).toLowerCase().replace(".", "") || "png";
2845
+ const imgPath = path10.resolve(process.cwd(), originalSrc);
2846
+ if (await fs11.pathExists(imgPath)) {
2847
+ const ext = path10.extname(imgPath).toLowerCase().replace(".", "") || "png";
2864
2848
  const mime = ext === "jpg" ? "jpeg" : ext === "svg" ? "svg+xml" : ext;
2865
- const base64 = await fs12.readFile(imgPath, "base64");
2849
+ const base64 = await fs11.readFile(imgPath, "base64");
2866
2850
  const dataUri = `data:image/${mime};base64,${base64}`;
2867
2851
  resolvedContent = resolvedContent.split(originalSrc).join(dataUri);
2868
2852
  }
@@ -2913,7 +2897,7 @@ var init_write_pdf = __esm({
2913
2897
  printBackground: true
2914
2898
  });
2915
2899
  const pdfDoc = await PDFDocument.load(pdfBytes);
2916
- const fileName = path11.basename(targetPath);
2900
+ const fileName = path10.basename(targetPath);
2917
2901
  pdfDoc.setTitle(`FluxFlow_${fileName}`);
2918
2902
  pdfDoc.setAuthor("FluxFlow CLI");
2919
2903
  pdfDoc.setSubject("Generated with Agentic AI System");
@@ -2921,8 +2905,8 @@ var init_write_pdf = __esm({
2921
2905
  pdfDoc.setCreator("FluxFlow PDF Engine");
2922
2906
  pdfDoc.setProducer("FluxFlow (Generative AI)");
2923
2907
  const finalPdfBytes = await pdfDoc.save();
2924
- await fs12.writeFile(absolutePath, finalPdfBytes);
2925
- const stats = await fs12.stat(absolutePath);
2908
+ await fs11.writeFile(absolutePath, finalPdfBytes);
2909
+ const stats = await fs11.stat(absolutePath);
2926
2910
  return `SUCCESS: PDF generated successfully at [${targetPath}] (${(stats.size / 1024).toFixed(2)} KB).`;
2927
2911
  } catch (err) {
2928
2912
  return `ERROR: Failed to generate PDF [${targetPath}]: ${err.message}`;
@@ -2934,8 +2918,8 @@ var init_write_pdf = __esm({
2934
2918
  });
2935
2919
 
2936
2920
  // src/tools/write_docx.js
2937
- import fs13 from "fs-extra";
2938
- import path12 from "path";
2921
+ import fs12 from "fs-extra";
2922
+ import path11 from "path";
2939
2923
  import HTMLtoDOCX from "html-to-docx";
2940
2924
  var write_docx;
2941
2925
  var init_write_docx = __esm({
@@ -2948,10 +2932,10 @@ var init_write_docx = __esm({
2948
2932
  } = parseArgs(args);
2949
2933
  if (!targetPath) return 'ERROR: Missing "path" argument for write_docx.';
2950
2934
  if (!content) return 'ERROR: Missing "content" (HTML) for write_docx.';
2951
- const absolutePath = path12.resolve(process.cwd(), targetPath);
2935
+ const absolutePath = path11.resolve(process.cwd(), targetPath);
2952
2936
  try {
2953
- await fs13.ensureDir(path12.dirname(absolutePath));
2954
- const fileName = path12.basename(targetPath);
2937
+ await fs12.ensureDir(path11.dirname(absolutePath));
2938
+ const fileName = path11.basename(targetPath);
2955
2939
  const fullHtml = content.includes("<html") ? content : `
2956
2940
  <!DOCTYPE html>
2957
2941
  <html lang="en">
@@ -2972,7 +2956,7 @@ var init_write_docx = __esm({
2972
2956
  footer: true,
2973
2957
  pageNumber: true
2974
2958
  });
2975
- await fs13.writeFile(absolutePath, docxBuffer);
2959
+ await fs12.writeFile(absolutePath, docxBuffer);
2976
2960
  return `SUCCESS: Word document [${targetPath}] generated successfully.
2977
2961
  - Size: ${(docxBuffer.length / 1024).toFixed(1)} KB`;
2978
2962
  } catch (err) {
@@ -3029,7 +3013,7 @@ var init_search_keyword = __esm({
3029
3013
  `;
3030
3014
  output += matches.join("\n");
3031
3015
  if (filteredLines.length > 100) {
3032
- output += "\n\n... (Truncated to first 100 matches to avoid context bloat)";
3016
+ output += "\n\n... (Truncated to first 100 matches)";
3033
3017
  }
3034
3018
  resolve(output);
3035
3019
  });
@@ -3039,8 +3023,8 @@ var init_search_keyword = __esm({
3039
3023
  });
3040
3024
 
3041
3025
  // src/utils/settings.js
3042
- import fs14 from "fs-extra";
3043
- import path13 from "path";
3026
+ import fs13 from "fs-extra";
3027
+ import path12 from "path";
3044
3028
  var DEFAULT_SETTINGS, loadSettings, migrateToExternal, saveSettings;
3045
3029
  var init_settings = __esm({
3046
3030
  "src/utils/settings.js"() {
@@ -3082,7 +3066,7 @@ var init_settings = __esm({
3082
3066
  loadSettings = async () => {
3083
3067
  let settingsObj = { ...DEFAULT_SETTINGS };
3084
3068
  try {
3085
- if (await fs14.exists(SETTINGS_FILE)) {
3069
+ if (await fs13.exists(SETTINGS_FILE)) {
3086
3070
  const saved = readAesEncryptedJson(SETTINGS_FILE);
3087
3071
  if (saved.imageSettings && saved.imageSettings.apiKey) {
3088
3072
  try {
@@ -3127,12 +3111,12 @@ var init_settings = __esm({
3127
3111
  const { FLUXFLOW_DIR: FLUXFLOW_DIR2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
3128
3112
  const folders = ["logs", "secret"];
3129
3113
  for (const folder of folders) {
3130
- const src = path13.join(FLUXFLOW_DIR2, folder);
3131
- const dest = path13.join(newPath, folder);
3114
+ const src = path12.join(FLUXFLOW_DIR2, folder);
3115
+ const dest = path12.join(newPath, folder);
3132
3116
  try {
3133
- if (await fs14.exists(src)) {
3134
- await fs14.ensureDir(dest);
3135
- await fs14.copy(src, dest, { overwrite: true });
3117
+ if (await fs13.exists(src)) {
3118
+ await fs13.ensureDir(dest);
3119
+ await fs13.copy(src, dest, { overwrite: true });
3136
3120
  }
3137
3121
  } catch (err) {
3138
3122
  console.error(`Migration failed for ${folder}:`, err);
@@ -3158,7 +3142,7 @@ var init_settings = __esm({
3158
3142
  if (updated.imageSettings) {
3159
3143
  updated.imageSettings = { ...updated.imageSettings, apiKey: "" };
3160
3144
  }
3161
- await fs14.ensureDir(path13.dirname(SETTINGS_FILE));
3145
+ await fs13.ensureDir(path12.dirname(SETTINGS_FILE));
3162
3146
  writeAesEncryptedJson(SETTINGS_FILE, updated);
3163
3147
  return true;
3164
3148
  } catch (err) {
@@ -3178,8 +3162,8 @@ var init_fallback_key = __esm({
3178
3162
  });
3179
3163
 
3180
3164
  // src/tools/generate_image.js
3181
- import fs15 from "fs-extra";
3182
- import path14 from "path";
3165
+ import fs14 from "fs-extra";
3166
+ import path13 from "path";
3183
3167
  var injectPngMetadata, generate_image;
3184
3168
  var init_generate_image = __esm({
3185
3169
  "src/tools/generate_image.js"() {
@@ -3251,6 +3235,30 @@ var init_generate_image = __esm({
3251
3235
  if (!prompt) {
3252
3236
  return 'ERROR: Missing "prompt" argument for generate_image.';
3253
3237
  }
3238
+ const BLOCKED_KEYWORDS = [
3239
+ "nsfw",
3240
+ "naked",
3241
+ "nudity",
3242
+ "nude",
3243
+ "porn",
3244
+ "sex",
3245
+ "xxx",
3246
+ "erotic",
3247
+ "gore",
3248
+ "bloody",
3249
+ "violence",
3250
+ "abuse",
3251
+ "suicide",
3252
+ "murder",
3253
+ "hentai",
3254
+ "pedophile",
3255
+ "rape"
3256
+ ];
3257
+ const promptLower = prompt.toLowerCase();
3258
+ const isBlocked = BLOCKED_KEYWORDS.some((kw) => promptLower.includes(kw));
3259
+ if (isBlocked) {
3260
+ return "ERROR: Prompt blocked by system safety filter (inappropriate or unsafe content detected).";
3261
+ }
3254
3262
  try {
3255
3263
  const settings = await loadSettings();
3256
3264
  const hasQuota = await checkImageQuota(settings);
@@ -3292,7 +3300,8 @@ var init_generate_image = __esm({
3292
3300
  }
3293
3301
  }
3294
3302
  const seed = Math.floor(Math.random() * 1e7);
3295
- const url = `https://gen.pollinations.ai/image/${encodeURIComponent(prompt)}?model=${selectedModel}&width=${width}&height=${height}&seed=${seed}&enhance=true&reasoning=high&quality=high`;
3303
+ const negativePrompt = "deformed, distorted, disfigured, poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, disconnected limbs, mutation, mutated hands and fingers, blurry, low quality, low resolution, extra fingers, censored, watermarks, signatures";
3304
+ const url = `https://gen.pollinations.ai/image/${encodeURIComponent(prompt)}?model=${selectedModel}&width=${width}&height=${height}&seed=${seed}&enhance=true&reasoning=high&quality=high&negative=${encodeURIComponent(negativePrompt)}`;
3296
3305
  const response = await fetch(url, {
3297
3306
  method: "GET",
3298
3307
  headers: {
@@ -3333,9 +3342,9 @@ var init_generate_image = __esm({
3333
3342
  "Seed": String(seed)
3334
3343
  };
3335
3344
  finalBuffer = injectPngMetadata(finalBuffer, metadata);
3336
- const absolutePath = path14.resolve(process.cwd(), outputPath);
3337
- await fs15.ensureDir(path14.dirname(absolutePath));
3338
- await fs15.writeFile(absolutePath, finalBuffer);
3345
+ const absolutePath = path13.resolve(process.cwd(), outputPath);
3346
+ await fs14.ensureDir(path13.dirname(absolutePath));
3347
+ await fs14.writeFile(absolutePath, finalBuffer);
3339
3348
  await recordImageGeneration(settings);
3340
3349
  return `SUCCESS: Image successfully generated from prompt [${prompt}] and saved to [${outputPath}].`;
3341
3350
  } catch (err) {
@@ -3353,7 +3362,6 @@ var init_tools = __esm({
3353
3362
  init_web_scrape();
3354
3363
  init_memory();
3355
3364
  init_chat();
3356
- init_list_files();
3357
3365
  init_view_file();
3358
3366
  init_write_file();
3359
3367
  init_update_file();
@@ -3369,7 +3377,6 @@ var init_tools = __esm({
3369
3377
  web_scrape,
3370
3378
  memory,
3371
3379
  chat,
3372
- list_files,
3373
3380
  view_file,
3374
3381
  write_file,
3375
3382
  update_file,
@@ -3412,8 +3419,8 @@ var init_tools = __esm({
3412
3419
 
3413
3420
  // src/utils/ai.js
3414
3421
  import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
3415
- import path15 from "path";
3416
- import fs16 from "fs";
3422
+ import path14 from "path";
3423
+ import fs15 from "fs";
3417
3424
  var client, TERMINATION_SIGNAL, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, getAIStream;
3418
3425
  var init_ai = __esm({
3419
3426
  "src/utils/ai.js"() {
@@ -3449,7 +3456,7 @@ var init_ai = __esm({
3449
3456
  try {
3450
3457
  const pArgs = parseArgs(argsStr);
3451
3458
  const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
3452
- return filePath ? path15.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
3459
+ return filePath ? path14.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
3453
3460
  } catch (e) {
3454
3461
  return null;
3455
3462
  }
@@ -3562,8 +3569,8 @@ ${originalTextProcessed.length > 1500 ? "... (truncated) ...\n\n" : ""}
3562
3569
  const toolContext = { chatId, sessionId: chatId, history };
3563
3570
  const result = await dispatchTool(janitorToolCall.toolName, janitorToolCall.args, toolContext);
3564
3571
  const date = (/* @__PURE__ */ new Date()).toLocaleString();
3565
- const janitorLogDir = path15.join(LOGS_DIR, "janitor");
3566
- fs16.appendFileSync(path15.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: RESULT [${janitorToolCall.toolName}]: ${result}
3572
+ const janitorLogDir = path14.join(LOGS_DIR, "janitor");
3573
+ fs15.appendFileSync(path14.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: RESULT [${janitorToolCall.toolName}]: ${result}
3567
3574
  `);
3568
3575
  if (janitorToolCall.toolName.toLowerCase() === "memory" && !janitorToolCall.args.includes("action='temp'")) {
3569
3576
  if (onMemoryUpdated) onMemoryUpdated();
@@ -3581,9 +3588,9 @@ ${originalTextProcessed.length > 1500 ? "... (truncated) ...\n\n" : ""}
3581
3588
  process.stdout.write(`\x1B]0;Memory Error\x07`);
3582
3589
  }
3583
3590
  await new Promise((resolve) => setTimeout(resolve, 3e3));
3584
- const janitorErrDir = path15.join(LOGS_DIR, "janitor");
3585
- if (!fs16.existsSync(janitorErrDir)) fs16.mkdirSync(janitorErrDir, { recursive: true });
3586
- fs16.appendFileSync(path15.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${String(janitorErr)}
3591
+ const janitorErrDir = path14.join(LOGS_DIR, "janitor");
3592
+ if (!fs15.existsSync(janitorErrDir)) fs15.mkdirSync(janitorErrDir, { recursive: true });
3593
+ fs15.appendFileSync(path14.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${String(janitorErr)}
3587
3594
 
3588
3595
  `);
3589
3596
  if (attempts > MAX_JANITOR_RETRIES) break;
@@ -3592,8 +3599,8 @@ ${originalTextProcessed.length > 1500 ? "... (truncated) ...\n\n" : ""}
3592
3599
  }
3593
3600
  }
3594
3601
  if (attempts) {
3595
- const janitorErrDir = path15.join(LOGS_DIR, "janitor");
3596
- fs16.appendFileSync(path15.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
3602
+ const janitorErrDir = path14.join(LOGS_DIR, "janitor");
3603
+ fs15.appendFileSync(path14.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
3597
3604
 
3598
3605
 
3599
3606
  `);
@@ -4036,12 +4043,12 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
4036
4043
  if (keyword) {
4037
4044
  detail = keyword.replace(/["']/g, "");
4038
4045
  } else if (filePath) {
4039
- detail = path15.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/"));
4046
+ detail = path14.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/"));
4040
4047
  } else {
4041
4048
  const m = partialArgs.match(/(?:path|targetFile|TargetFile|directory|keyword)\s*=\s*\\?["']?([^\\"' \),]+)/);
4042
4049
  if (m) {
4043
4050
  const val = m[1].replace(/["']/g, "");
4044
- detail = potentialTool === "search_keyword" ? val : path15.basename(val.replace(/\\/g, "/"));
4051
+ detail = potentialTool === "search_keyword" ? val : path14.basename(val.replace(/\\/g, "/"));
4045
4052
  }
4046
4053
  }
4047
4054
  }
@@ -4201,9 +4208,9 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
4201
4208
  let totalLines = "...";
4202
4209
  let actualEndLine = eLine;
4203
4210
  try {
4204
- const absPath = path15.resolve(process.cwd(), targetPath2);
4205
- if (fs16.existsSync(absPath)) {
4206
- const content = fs16.readFileSync(absPath, "utf8");
4211
+ const absPath = path14.resolve(process.cwd(), targetPath2);
4212
+ if (fs15.existsSync(absPath)) {
4213
+ const content = fs15.readFileSync(absPath, "utf8");
4207
4214
  const lines = content.split("\n").length;
4208
4215
  totalLines = lines;
4209
4216
  actualEndLine = Math.min(eLine, lines);
@@ -4254,7 +4261,7 @@ ${boxBottom}` };
4254
4261
  const { command } = parseArgs(toolCall.args);
4255
4262
  if (command && settings.systemSettings && settings.systemSettings.allowExternalAccess === false) {
4256
4263
  const riskyPatterns = [/[a-zA-Z]:[\\\/]/i, /^\//, /\.\.[\\\/]/, /\/etc\//, /\/var\//, /\/root\//, /\/bin\//, /\/usr\//];
4257
- const currentDrive = path15.resolve(process.cwd()).substring(0, 3).toLowerCase();
4264
+ const currentDrive = path14.resolve(process.cwd()).substring(0, 3).toLowerCase();
4258
4265
  const isViolating = riskyPatterns.some((pattern) => {
4259
4266
  if (pattern.source === "[a-zA-Z]:[\\\\\\/]") {
4260
4267
  const driveMatch = command.match(/[a-zA-Z]:[\\\/]/i);
@@ -4277,8 +4284,8 @@ ${boxBottom}` };
4277
4284
  const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
4278
4285
  if (targetPath) {
4279
4286
  const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
4280
- const absoluteTarget = path15.resolve(targetPath);
4281
- const absoluteCwd = path15.resolve(process.cwd());
4287
+ const absoluteTarget = path14.resolve(targetPath);
4288
+ const absoluteCwd = path14.resolve(process.cwd());
4282
4289
  if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
4283
4290
  const denyMsg = `Access Denied. You are not allowed to access files outside the current workspace. To enable this, ask the user to turn on "External Workspace Access" in /settings.`;
4284
4291
  toolResults.push({ role: "user", text: `[TOOL RESULT]: ERROR: ${denyMsg}${thinkingLevel != "Fast" ? "\n\n[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRICT PRIORITY. DO NOT START A RESPONSE WITHOUT THINKING**" : ""}` });
@@ -4393,6 +4400,11 @@ ${boxBottom}` };
4393
4400
  success = true;
4394
4401
  await incrementUsage("agent");
4395
4402
  } catch (err) {
4403
+ if (String(err).includes("Incomplete JSON segment at the end")) {
4404
+ success = true;
4405
+ await incrementUsage("agent");
4406
+ break;
4407
+ }
4396
4408
  if (isDedupeActive && dedupeBuffer.length > 0) {
4397
4409
  let overlapLen = 0;
4398
4410
  const maxPossibleOverlap = Math.min(accumulatedContext.length, dedupeBuffer.length);
@@ -4415,9 +4427,9 @@ ${boxBottom}` };
4415
4427
  const errMsg = err.status || err.error && err.error.message || String(err);
4416
4428
  const errLog = String(err);
4417
4429
  const date = (/* @__PURE__ */ new Date()).toLocaleString();
4418
- const agentErrDir = path15.join(LOGS_DIR, "agent");
4419
- if (!fs16.existsSync(agentErrDir)) fs16.mkdirSync(agentErrDir, { recursive: true });
4420
- fs16.appendFileSync(path15.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
4430
+ const agentErrDir = path14.join(LOGS_DIR, "agent");
4431
+ if (!fs15.existsSync(agentErrDir)) fs15.mkdirSync(agentErrDir, { recursive: true });
4432
+ fs15.appendFileSync(path14.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
4421
4433
  DEBUG STATE: turnText='${turnText}', length=${turnText.trim().length}, inStreamRetryCount=${inStreamRetryCount}, retryCount=${retryCount}, isDedupeActive=${isDedupeActive}, dedupeBuffer='${dedupeBuffer}'
4422
4434
 
4423
4435
  ----------------------------------------------------------------------
@@ -4462,7 +4474,7 @@ ${recoveryText}`
4462
4474
  yield { type: "status", content: `Error Occured. Recovering Stream...` };
4463
4475
  } else {
4464
4476
  throw new Error(`Stream collapsed too many times. (Failed to resolve ${MAX_RETRIES} times)
4465
- Error Log can be found in ${path15.join(LOGS_DIR, "agent", "error.log")}`);
4477
+ Error Log can be found in ${path14.join(LOGS_DIR, "agent", "error.log")}`);
4466
4478
  }
4467
4479
  } else {
4468
4480
  if (retryCount <= MAX_RETRIES) {
@@ -4479,7 +4491,7 @@ Error Log can be found in ${path15.join(LOGS_DIR, "agent", "error.log")}`);
4479
4491
  yield { type: "status", content: `Retrying Connection...` };
4480
4492
  } else {
4481
4493
  throw new Error(`Model cannot be reached. (Failed ${MAX_RETRIES} times)
4482
- Error Log can be found in ${path15.join(LOGS_DIR, "agent", "error.log")}`);
4494
+ Error Log can be found in ${path14.join(LOGS_DIR, "agent", "error.log")}`);
4483
4495
  }
4484
4496
  }
4485
4497
  }
@@ -4540,13 +4552,13 @@ ${timestamp}`;
4540
4552
  });
4541
4553
 
4542
4554
  // src/components/ResumeModal.jsx
4543
- import React7, { useState as useState4, useEffect as useEffect2 } from "react";
4555
+ import React7, { useState as useState4, useEffect as useEffect3 } from "react";
4544
4556
  import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
4545
4557
  function ResumeModal({ onSelect, onDelete, onClose }) {
4546
4558
  const [history, setHistory] = useState4({});
4547
4559
  const [keys, setKeys] = useState4([]);
4548
4560
  const [selectedIndex, setSelectedIndex] = useState4(0);
4549
- useEffect2(() => {
4561
+ useEffect3(() => {
4550
4562
  const fetchHistory = async () => {
4551
4563
  const h = await loadHistory();
4552
4564
  setHistory(h);
@@ -4571,9 +4583,23 @@ function ResumeModal({ onSelect, onDelete, onClose }) {
4571
4583
  }
4572
4584
  });
4573
4585
  const s = emojiSpace(2);
4574
- return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: 80 }, /* @__PURE__ */ React7.createElement(Box7, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "cyan", bold: true }, "\u{1F4A0} CHAT HISTORY: RESUME CONVERSATION")), keys.length === 0 ? /* @__PURE__ */ React7.createElement(Box7, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React7.createElement(Text7, { italic: true, color: "gray" }, "No saved chats found.")) : /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column" }, keys.map((id, index) => {
4586
+ const MAX_VISIBLE = 15;
4587
+ let startIndex = 0;
4588
+ if (keys.length > MAX_VISIBLE) {
4589
+ const half = Math.floor(MAX_VISIBLE / 2);
4590
+ startIndex = selectedIndex - half;
4591
+ if (startIndex < 0) {
4592
+ startIndex = 0;
4593
+ } else if (startIndex + MAX_VISIBLE > keys.length) {
4594
+ startIndex = keys.length - MAX_VISIBLE;
4595
+ }
4596
+ }
4597
+ const visibleKeys = keys.slice(startIndex, startIndex + MAX_VISIBLE);
4598
+ return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: 95 }, /* @__PURE__ */ React7.createElement(Box7, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "cyan", bold: true }, "\u{1F4A0} CHAT HISTORY: RESUME CONVERSATION")), keys.length === 0 ? /* @__PURE__ */ React7.createElement(Box7, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React7.createElement(Text7, { italic: true, color: "gray" }, "No saved chats found.")) : /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", width: "100%" }, startIndex > 0 && /* @__PURE__ */ React7.createElement(Box7, { paddingX: 2, marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray", dimColor: true }, "\u25B2 (+", startIndex, " more chats above)")), visibleKeys.map((id, index) => {
4575
4599
  const chat2 = history[id];
4576
- const isSelected = index === selectedIndex;
4600
+ const actualIndex = startIndex + index;
4601
+ const isSelected = actualIndex === selectedIndex;
4602
+ const dateStr = formatDate(chat2?.updatedAt);
4577
4603
  return /* @__PURE__ */ React7.createElement(
4578
4604
  Box7,
4579
4605
  {
@@ -4582,10 +4608,10 @@ function ResumeModal({ onSelect, onDelete, onClose }) {
4582
4608
  backgroundColor: isSelected ? "#2a2a2a" : void 0,
4583
4609
  width: "100%"
4584
4610
  },
4585
- /* @__PURE__ */ React7.createElement(Box7, { flexGrow: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: isSelected ? "cyan" : "white", bold: isSelected }, isSelected ? "\u276F " : " ", chat2.name || id, /* @__PURE__ */ React7.createElement(Text7, { color: "gray", dimColor: !isSelected }, " [", id.slice(5), "]"))),
4611
+ /* @__PURE__ */ React7.createElement(Box7, { flexGrow: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: isSelected ? "cyan" : "white", bold: isSelected }, isSelected ? "\u276F " : " ", chat2?.name || id, /* @__PURE__ */ React7.createElement(Text7, { color: "gray", dimColor: !isSelected }, " [", dateStr, " \u2022 ", id.slice(5), "]"))),
4586
4612
  isSelected && /* @__PURE__ */ React7.createElement(Box7, { flexShrink: 0 }, /* @__PURE__ */ React7.createElement(Text7, { color: "red", bold: true }, "[X] DELETE "))
4587
4613
  );
4588
- })), /* @__PURE__ */ React7.createElement(
4614
+ }), startIndex + MAX_VISIBLE < keys.length && /* @__PURE__ */ React7.createElement(Box7, { paddingX: 2, marginTop: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray", dimColor: true }, "\u25BC (+", keys.length - (startIndex + MAX_VISIBLE), " more chats below)"))), /* @__PURE__ */ React7.createElement(
4589
4615
  Box7,
4590
4616
  {
4591
4617
  marginTop: 1,
@@ -4599,6 +4625,17 @@ function ResumeModal({ onSelect, onDelete, onClose }) {
4599
4625
  /* @__PURE__ */ React7.createElement(Text7, { dimColor: true, italic: true }, "\u2191\u2193 navigate \u2022 Enter select \u2022 x delete \u2022 Esc close")
4600
4626
  ));
4601
4627
  }
4628
+ function formatDate(timestamp) {
4629
+ if (!timestamp) return "N/A";
4630
+ const d = new Date(timestamp);
4631
+ if (isNaN(d.getTime())) return "N/A";
4632
+ const pad = (n) => String(n).padStart(2, "0");
4633
+ const mm = pad(d.getMonth() + 1);
4634
+ const dd = pad(d.getDate());
4635
+ const hh = pad(d.getHours());
4636
+ const min = pad(d.getMinutes());
4637
+ return `${mm}-${dd} ${hh}:${min}`;
4638
+ }
4602
4639
  var init_ResumeModal = __esm({
4603
4640
  "src/components/ResumeModal.jsx"() {
4604
4641
  init_history();
@@ -4607,16 +4644,24 @@ var init_ResumeModal = __esm({
4607
4644
  });
4608
4645
 
4609
4646
  // src/components/MemoryModal.jsx
4610
- import React8, { useState as useState5, useEffect as useEffect3 } from "react";
4647
+ import React8, { useState as useState5, useEffect as useEffect4 } from "react";
4611
4648
  import { Box as Box8, Text as Text8, useInput as useInput3 } from "ink";
4612
4649
  function MemoryModal({ onClose }) {
4613
4650
  const [memories, setMemories] = useState5([]);
4614
4651
  const [selectedIndex, setSelectedIndex] = useState5(0);
4652
+ const [isMemoryOn, setIsMemoryOn] = useState5(true);
4615
4653
  const loadMemories = () => {
4616
4654
  const data = readEncryptedJson(MEMORIES_FILE, []);
4617
4655
  setMemories(data);
4656
+ try {
4657
+ const settings = readAesEncryptedJson(SETTINGS_FILE, {});
4658
+ const memoryOn = settings.systemSettings?.memory !== false;
4659
+ setIsMemoryOn(memoryOn);
4660
+ } catch (e) {
4661
+ setIsMemoryOn(true);
4662
+ }
4618
4663
  };
4619
- useEffect3(() => {
4664
+ useEffect4(() => {
4620
4665
  loadMemories();
4621
4666
  }, []);
4622
4667
  useInput3((input, key) => {
@@ -4637,7 +4682,7 @@ function MemoryModal({ onClose }) {
4637
4682
  return text.replace(/\[Saved on: .*?\]/g, "").trim();
4638
4683
  };
4639
4684
  const s = emojiSpace(2);
4640
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: 80 }, /* @__PURE__ */ React8.createElement(Box8, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "cyan", bold: true }, "\u{1F9E0} AGENT MEMORY: LONG-TERM KNOWLEDGE")), memories.length === 0 ? /* @__PURE__ */ React8.createElement(Box8, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React8.createElement(Text8, { italic: true, color: "gray" }, "Still Learning...")) : /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column" }, memories.map((mem, idx) => {
4685
+ return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: 80 }, /* @__PURE__ */ React8.createElement(Box8, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "cyan", bold: true }, "\u{1F9E0} AGENT MEMORY: LONG-TERM KNOWLEDGE")), !isMemoryOn && memories.length > 0 ? /* @__PURE__ */ React8.createElement(Box8, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React8.createElement(Text8, { italic: true, color: "gray" }, "Memory is currently Off...")) : memories.length === 0 ? /* @__PURE__ */ React8.createElement(Box8, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React8.createElement(Text8, { italic: true, color: "gray" }, isMemoryOn ? "Learning..." : "Memory not available...")) : /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column" }, memories.map((mem, idx) => {
4641
4686
  const isSelected = idx === selectedIndex;
4642
4687
  return /* @__PURE__ */ React8.createElement(
4643
4688
  Box8,
@@ -4673,7 +4718,7 @@ var init_MemoryModal = __esm({
4673
4718
  });
4674
4719
 
4675
4720
  // src/components/UpdateProcessor.jsx
4676
- import React9, { useState as useState6, useEffect as useEffect4 } from "react";
4721
+ import React9, { useState as useState6, useEffect as useEffect5 } from "react";
4677
4722
  import { Box as Box9, Text as Text9 } from "ink";
4678
4723
  import Spinner from "ink-spinner";
4679
4724
  import { exec as exec2 } from "child_process";
@@ -4684,7 +4729,7 @@ var init_UpdateProcessor = __esm({
4684
4729
  const [status, setStatus] = useState6("initializing");
4685
4730
  const [log, setLog] = useState6("");
4686
4731
  const [error, setError] = useState6(null);
4687
- useEffect4(() => {
4732
+ useEffect5(() => {
4688
4733
  let child;
4689
4734
  const runUpdate = async () => {
4690
4735
  const manager = settings.updateManager || "npm";
@@ -4727,7 +4772,7 @@ var init_UpdateProcessor = __esm({
4727
4772
  return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React9.createElement(Box9, null, /* @__PURE__ */ React9.createElement(Text9, { color: "cyan" }, /* @__PURE__ */ React9.createElement(Spinner, { type: "dots" })), /* @__PURE__ */ React9.createElement(Text9, { marginLeft: 1, bold: true }, " Updating Flux Flow to v", latest, "...")), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "#333" }, /* @__PURE__ */ React9.createElement(Text9, { color: "gray", dimColor: true, italic: true }, log || "Preparing environment...")), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1, dimColor: true }, "(Please do not close the terminal)"));
4728
4773
  }
4729
4774
  if (status === "success") {
4730
- return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React9.createElement(Text9, { color: "green", bold: true }, "\u2705 UPDATE SUCCESSFUL!"), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1 }, "Flux Flow has been upgraded to ", /* @__PURE__ */ React9.createElement(Text9, { color: "cyan" }, "v", latest), "."), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1, color: "yellow", bold: true }, "CRITICAL: Please restart your terminal session to apply changes."), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, "(Press ESC to return to chat)")));
4775
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React9.createElement(Text9, { color: "green", bold: true }, "\u2705 UPDATE SUCCESSFUL!"), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1 }, "Flux Flow has been updated to ", /* @__PURE__ */ React9.createElement(Text9, { color: "cyan" }, "v", latest), "."), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1, color: "yellow", bold: true }, "CRITICAL: Please restart your terminal session to apply changes."), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, "(Press ESC to return to chat)")));
4731
4776
  }
4732
4777
  if (status === "error") {
4733
4778
  return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React9.createElement(Text9, { color: "red", bold: true }, "\u274C UPDATE FAILED"), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "red" }, /* @__PURE__ */ React9.createElement(Text9, { color: "red" }, error)), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1 }, "Possible causes:"), /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Missing permissions (Try running as Administrator/Sudo)"), /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Package manager (", settings.updateManager, ") not found"), /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Network failure"), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text9, { dimColor: true }, "(Press ESC to return to chat)")));
@@ -4742,7 +4787,7 @@ var init_UpdateProcessor = __esm({
4742
4787
  import puppeteer4 from "puppeteer";
4743
4788
  import { exec as exec3 } from "child_process";
4744
4789
  import { promisify } from "util";
4745
- import fs17 from "fs";
4790
+ import fs16 from "fs";
4746
4791
  var execAsync, checkPuppeteerReady, installPuppeteerBrowser;
4747
4792
  var init_setup = __esm({
4748
4793
  "src/utils/setup.js"() {
@@ -4750,7 +4795,7 @@ var init_setup = __esm({
4750
4795
  checkPuppeteerReady = () => {
4751
4796
  try {
4752
4797
  const exePath = puppeteer4.executablePath();
4753
- const exists = exePath && fs17.existsSync(exePath);
4798
+ const exists = exePath && fs16.existsSync(exePath);
4754
4799
  if (exists) return true;
4755
4800
  } catch (e) {
4756
4801
  return false;
@@ -4781,17 +4826,17 @@ __export(app_exports, {
4781
4826
  default: () => App
4782
4827
  });
4783
4828
  import os4 from "os";
4784
- import React10, { useState as useState7, useEffect as useEffect5, useRef as useRef2, useMemo } from "react";
4829
+ import React10, { useState as useState7, useEffect as useEffect6, useRef as useRef2, useMemo } from "react";
4785
4830
  import { Box as Box10, Text as Text10, useInput as useInput4, useStdout } from "ink";
4786
4831
  import Spinner2 from "ink-spinner";
4787
- import fs18 from "fs-extra";
4788
- import path16 from "path";
4832
+ import fs17 from "fs-extra";
4833
+ import path15 from "path";
4789
4834
  import { exec as exec4 } from "child_process";
4790
4835
  import { fileURLToPath } from "url";
4791
4836
  import { MultilineInput } from "ink-multiline-input";
4792
4837
  import TextInput3 from "ink-text-input";
4793
4838
  import gradient from "gradient-string";
4794
- function App() {
4839
+ function App({ args = [] }) {
4795
4840
  const [confirmExit, setConfirmExit] = useState7(false);
4796
4841
  const [exitCountdown, setExitCountdown] = useState7(10);
4797
4842
  const { stdout } = useStdout();
@@ -4803,6 +4848,45 @@ function App() {
4803
4848
  rows: stdout?.rows || 24
4804
4849
  });
4805
4850
  const [selectedIndex, setSelectedIndex] = useState7(0);
4851
+ const persistedModelRef = useRef2(null);
4852
+ const parsedArgs = useMemo(() => {
4853
+ const parsed = {};
4854
+ for (let i = 0; i < args.length; i++) {
4855
+ const arg = args[i];
4856
+ if (arg === "--model" && args[i + 1]) {
4857
+ parsed.model = args[i + 1];
4858
+ i++;
4859
+ } else if (arg === "--memory" && args[i + 1]) {
4860
+ parsed.memory = args[i + 1].toLowerCase();
4861
+ i++;
4862
+ } else if (arg === "--resume" && args[i + 1]) {
4863
+ parsed.resume = args[i + 1];
4864
+ i++;
4865
+ } else if (arg === "--update" && args[i + 1]) {
4866
+ parsed.update = args[i + 1].toLowerCase();
4867
+ i++;
4868
+ } else if (arg === "--package" && args[i + 1]) {
4869
+ const pkg = args[i + 1].toLowerCase();
4870
+ if (["npm", "pnpm", "yarn", "bun"].includes(pkg)) {
4871
+ parsed.package = pkg;
4872
+ }
4873
+ i++;
4874
+ } else if (arg === "--auto-del" && args[i + 1]) {
4875
+ const del = args[i + 1].toLowerCase();
4876
+ if (["1d", "7d", "30d"].includes(del)) {
4877
+ parsed.autoDel = del;
4878
+ }
4879
+ i++;
4880
+ } else if (arg === "--auto-exec" && args[i + 1]) {
4881
+ parsed.autoExec = args[i + 1].toLowerCase();
4882
+ i++;
4883
+ } else if (arg === "--external-access" && args[i + 1]) {
4884
+ parsed.externalAccess = args[i + 1].toLowerCase();
4885
+ i++;
4886
+ }
4887
+ }
4888
+ return parsed;
4889
+ }, [args]);
4806
4890
  const performVersionCheck = async (manual = false, settingsOverride = null) => {
4807
4891
  const settingsToUse = settingsOverride || systemSettings;
4808
4892
  if (manual) {
@@ -4854,7 +4938,7 @@ function App() {
4854
4938
  }
4855
4939
  }
4856
4940
  };
4857
- useEffect5(() => {
4941
+ useEffect6(() => {
4858
4942
  const handleResize = () => {
4859
4943
  stdout.write("\x1Bc");
4860
4944
  setTerminalSize({
@@ -4898,7 +4982,7 @@ function App() {
4898
4982
  const [activeCommand, setActiveCommand] = useState7(null);
4899
4983
  const [execOutput, setExecOutput] = useState7("");
4900
4984
  const [isTerminalFocused, setIsTerminalFocused] = useState7(false);
4901
- useEffect5(() => {
4985
+ useEffect6(() => {
4902
4986
  if (apiTier !== "Free" && activeModel === "gemma-4-31b-it") {
4903
4987
  setActiveModel("gemini-3-flash-preview");
4904
4988
  setMessages((prev) => {
@@ -4921,10 +5005,10 @@ function App() {
4921
5005
  }, []);
4922
5006
  const activeCommandRef = useRef2(null);
4923
5007
  const execOutputRef = useRef2("");
4924
- useEffect5(() => {
5008
+ useEffect6(() => {
4925
5009
  activeCommandRef.current = activeCommand;
4926
5010
  }, [activeCommand]);
4927
- useEffect5(() => {
5011
+ useEffect6(() => {
4928
5012
  execOutputRef.current = execOutput;
4929
5013
  }, [execOutput]);
4930
5014
  const [autoAcceptWrites, setAutoAcceptWrites] = useState7(false);
@@ -5107,7 +5191,7 @@ function App() {
5107
5191
  setInput((prev) => prev.replace(/\\\r?$/, "").replace(/\r?$/, "") + "\n");
5108
5192
  }
5109
5193
  });
5110
- useEffect5(() => {
5194
+ useEffect6(() => {
5111
5195
  async function init() {
5112
5196
  if (process.stdout.isTTY) {
5113
5197
  process.stdout.write(`\x1B]0;FluxFlow | Ready\x07`);
@@ -5126,7 +5210,12 @@ function App() {
5126
5210
  const saved = await loadSettings();
5127
5211
  setMode(saved.mode);
5128
5212
  setThinkingLevel(saved.thinkingLevel);
5129
- setActiveModel(saved.activeModel);
5213
+ persistedModelRef.current = saved.activeModel;
5214
+ if (parsedArgs.model) {
5215
+ setActiveModel(parsedArgs.model);
5216
+ } else {
5217
+ setActiveModel(saved.activeModel);
5218
+ }
5130
5219
  setShowFullThinking(saved.showFullThinking);
5131
5220
  setApiTier(saved.apiTier || "Free");
5132
5221
  setQuotas(saved.quotas || { agentLimit: 1500, searchLimit: 100, customModelId: "", customLimit: 0 });
@@ -5140,6 +5229,27 @@ function App() {
5140
5229
  customUpdateCommand: "",
5141
5230
  ...saved.systemSettings || {}
5142
5231
  };
5232
+ if (parsedArgs.memory === "on") {
5233
+ freshSettings.memory = true;
5234
+ } else if (parsedArgs.memory === "off") {
5235
+ freshSettings.memory = false;
5236
+ }
5237
+ if (parsedArgs.package) {
5238
+ freshSettings.updateManager = parsedArgs.package;
5239
+ }
5240
+ if (parsedArgs.autoDel) {
5241
+ freshSettings.autoDeleteHistory = parsedArgs.autoDel;
5242
+ }
5243
+ if (parsedArgs.autoExec === "on") {
5244
+ freshSettings.autoExec = true;
5245
+ } else if (parsedArgs.autoExec === "off") {
5246
+ freshSettings.autoExec = false;
5247
+ }
5248
+ if (parsedArgs.externalAccess === "on") {
5249
+ freshSettings.allowExternalAccess = true;
5250
+ } else if (parsedArgs.externalAccess === "off") {
5251
+ freshSettings.allowExternalAccess = false;
5252
+ }
5143
5253
  setSystemSettings(freshSettings);
5144
5254
  setProfileData(saved.profileData);
5145
5255
  setImageSettings(saved.imageSettings || { keyType: "Default", quality: "Low-High", apiKey: "" });
@@ -5152,13 +5262,41 @@ function App() {
5152
5262
  cleanupOldHistory(saved.systemSettings.autoDeleteHistory);
5153
5263
  }
5154
5264
  cleanupOldLogs(LOGS_DIR);
5155
- performVersionCheck(false, freshSettings);
5265
+ if (parsedArgs.update === "check") {
5266
+ performVersionCheck(true, freshSettings);
5267
+ } else if (parsedArgs.update === "latest") {
5268
+ setActiveView("update");
5269
+ performVersionCheck(true, freshSettings);
5270
+ } else {
5271
+ performVersionCheck(false, freshSettings);
5272
+ }
5156
5273
  await initUsage();
5274
+ if (parsedArgs.resume) {
5275
+ const h = await loadHistory();
5276
+ const id = parsedArgs.resume;
5277
+ if (h[id]) {
5278
+ setChatId(id);
5279
+ const resumedMsgs = [...h[id].messages];
5280
+ const hasLogo = resumedMsgs[0]?.text?.includes("\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557");
5281
+ if (!hasLogo) {
5282
+ resumedMsgs.unshift({ id: "welcome-" + Date.now(), role: "system", text: FLUX_LOGO + "\n\n\u{1F30A}\u26A1 Resuming Flux Flow Session...", isMeta: true });
5283
+ }
5284
+ setMessages(resumedMsgs);
5285
+ setActiveView("chat");
5286
+ setMessages((prev) => {
5287
+ const newMsgs = [...prev, { id: "sys-" + Date.now(), role: "system", text: `\u{1F4E1} SESSION RESUMED VIA CLI: [${id}]`, isMeta: true }];
5288
+ setCompletedIndex(newMsgs.length);
5289
+ return newMsgs;
5290
+ });
5291
+ } else {
5292
+ setMessages((prev) => [...prev, { id: "sys-err-" + Date.now(), role: "system", text: `\u274C ERROR: Chat session [${id}] not found. Started new session.`, isMeta: true }]);
5293
+ }
5294
+ }
5157
5295
  setIsInitializing(false);
5158
5296
  }
5159
5297
  init();
5160
5298
  }, []);
5161
- useEffect5(() => {
5299
+ useEffect6(() => {
5162
5300
  let timer;
5163
5301
  if (confirmExit) {
5164
5302
  setExitCountdown(10);
@@ -5176,19 +5314,20 @@ function App() {
5176
5314
  if (timer) clearInterval(timer);
5177
5315
  };
5178
5316
  }, [confirmExit]);
5179
- useEffect5(() => {
5317
+ useEffect6(() => {
5180
5318
  if (!isInitializing) {
5319
+ const modelToSave = parsedArgs.model && activeModel === parsedArgs.model ? persistedModelRef.current : activeModel;
5181
5320
  saveSettings({
5182
5321
  mode,
5183
5322
  thinkingLevel,
5184
- activeModel,
5323
+ activeModel: modelToSave || activeModel,
5185
5324
  showFullThinking,
5186
5325
  systemSettings,
5187
5326
  profileData,
5188
5327
  imageSettings
5189
5328
  });
5190
5329
  }
5191
- }, [mode, thinkingLevel, activeModel, showFullThinking, systemSettings, profileData, imageSettings, isInitializing]);
5330
+ }, [mode, thinkingLevel, activeModel, showFullThinking, systemSettings, profileData, imageSettings, isInitializing, parsedArgs]);
5192
5331
  const handleSetup = async (val) => {
5193
5332
  const key = val.trim();
5194
5333
  if (key.length >= 30) {
@@ -5202,7 +5341,7 @@ function App() {
5202
5341
  }
5203
5342
  };
5204
5343
  const lastSavedTimeRef = useRef2(SESSION_START_TIME);
5205
- useEffect5(() => {
5344
+ useEffect6(() => {
5206
5345
  if (activeView === "exit") {
5207
5346
  const flush = async () => {
5208
5347
  const now = Date.now();
@@ -5220,7 +5359,7 @@ function App() {
5220
5359
  return () => clearTimeout(timer);
5221
5360
  }
5222
5361
  }, [activeView]);
5223
- useEffect5(() => {
5362
+ useEffect6(() => {
5224
5363
  const interval = setInterval(async () => {
5225
5364
  if (!isInitializing) {
5226
5365
  const now = Date.now();
@@ -5297,10 +5436,11 @@ function App() {
5297
5436
  cmd: "/model",
5298
5437
  desc: "Switch AI model",
5299
5438
  subs: [
5300
- { cmd: "gemma-4-31b-it", desc: apiTier === "Free" ? "Standard Default (Free, Recommended)" : "Standard Default (Free, Recommended) - Use Free API Key to use this model " },
5301
- { cmd: "gemini-3.1-pro-preview", desc: "Most Capable (Paid)" },
5439
+ { cmd: "gemma-4-31b-it", desc: apiTier === "Free" ? "Standard Default (Free, Recommended)" : "Standard Default (Free, Recommended) - Use Free API Key to use this model " },
5440
+ { cmd: "gemini-3.1-pro-preview", desc: "Most Capable (Paid)" },
5302
5441
  { cmd: "gemini-3-flash-preview", desc: "Fast & Lightweight (Paid, Limited Free quota)" },
5303
- { cmd: "gemini-3.1-flash-lite", desc: "Ultra Fast (Paid, Decent Free quota)" }
5442
+ { cmd: "gemini-3.5-flash", desc: "New (Paid, Limited Free quota)" },
5443
+ { cmd: "gemini-3.1-flash-lite", desc: "Ultra Fast (Paid, Decent Free quota)" }
5304
5444
  ]
5305
5445
  },
5306
5446
  { cmd: "/settings", desc: "Configure system prefs" },
@@ -5327,8 +5467,8 @@ function App() {
5327
5467
  ]
5328
5468
  }
5329
5469
  ];
5330
- const handleSubmit = async (value) => {
5331
- if (suggestions.length > 0) {
5470
+ const handleSubmit = async (value, isProgrammatic = false) => {
5471
+ if (!isProgrammatic && suggestions.length > 0) {
5332
5472
  const nextMatch = suggestions[selectedIndex] || suggestions[0];
5333
5473
  const parts = value.split(" ");
5334
5474
  if (parts.length === 1) {
@@ -5676,12 +5816,12 @@ ${list || "No saved chats found."}`, isMeta: true }];
5676
5816
  setCompletedIndex(prev.length + 1);
5677
5817
  return [...prev, { id: Date.now(), role: "system", text: "\u2622\uFE0F [NUCLEAR] Initiating reset...", isMeta: true }];
5678
5818
  });
5679
- if (fs18.existsSync(LOGS_DIR)) fs18.removeSync(LOGS_DIR);
5680
- if (fs18.existsSync(SECRET_DIR)) fs18.removeSync(SECRET_DIR);
5681
- if (fs18.existsSync(SETTINGS_FILE)) fs18.removeSync(SETTINGS_FILE);
5819
+ if (fs17.existsSync(LOGS_DIR)) fs17.removeSync(LOGS_DIR);
5820
+ if (fs17.existsSync(SECRET_DIR)) fs17.removeSync(SECRET_DIR);
5821
+ if (fs17.existsSync(SETTINGS_FILE)) fs17.removeSync(SETTINGS_FILE);
5682
5822
  try {
5683
- const items = fs18.readdirSync(FLUXFLOW_DIR);
5684
- if (items.length === 0) fs18.removeSync(FLUXFLOW_DIR);
5823
+ const items = fs17.readdirSync(FLUXFLOW_DIR);
5824
+ if (items.length === 0) fs17.removeSync(FLUXFLOW_DIR);
5685
5825
  } catch (e) {
5686
5826
  }
5687
5827
  setTimeout(() => {
@@ -5720,8 +5860,8 @@ ${list || "No saved chats found."}`, isMeta: true }];
5720
5860
  break;
5721
5861
  }
5722
5862
  case "/fluxflow": {
5723
- const args = parts.slice(1);
5724
- if (args[0] === "init") {
5863
+ const args2 = parts.slice(1);
5864
+ if (args2[0] === "init") {
5725
5865
  const template = `# FluxFlow Configuration
5726
5866
  # This file defines project-specific instructions for the Flux Flow Agent.
5727
5867
 
@@ -5738,14 +5878,14 @@ ${list || "No saved chats found."}`, isMeta: true }];
5738
5878
  # SKILLS & WORKFLOWS
5739
5879
  - [Define custom step-by-step recipes for this project here]
5740
5880
  `;
5741
- const filePath = path16.join(process.cwd(), "FluxFlow.md");
5742
- if (fs18.pathExistsSync(filePath)) {
5881
+ const filePath = path15.join(process.cwd(), "FluxFlow.md");
5882
+ if (fs17.pathExistsSync(filePath)) {
5743
5883
  setMessages((prev) => {
5744
5884
  setCompletedIndex(prev.length + 1);
5745
5885
  return [...prev, { id: "init-err-" + Date.now(), role: "system", text: "\u274C ERROR: FluxFlow.md already exists in this directory.", isMeta: true }];
5746
5886
  });
5747
5887
  } else {
5748
- fs18.writeFileSync(filePath, template);
5888
+ fs17.writeFileSync(filePath, template);
5749
5889
  setMessages((prev) => {
5750
5890
  setCompletedIndex(prev.length + 1);
5751
5891
  return [...prev, { id: "init-ok-" + Date.now(), role: "system", text: "\u2705 [SUCCESS] FluxFlow.md has been initialized. You can now customize it for this project.", isMeta: true }];
@@ -5856,20 +5996,20 @@ OUTPUT: ${execOutputRef.current}`;
5856
5996
  setSessionToolFailure((prev) => prev + 1);
5857
5997
  }
5858
5998
  },
5859
- onToolApproval: async (tool, args) => {
5999
+ onToolApproval: async (tool, args2) => {
5860
6000
  const isAuto = autoAcceptWrites || systemSettings.autoExec;
5861
6001
  if (tool === "exec_command") {
5862
- const { command } = parseArgs(args || "{}");
6002
+ const { command } = parseArgs(args2 || "{}");
5863
6003
  const safeRegex = /^(echo|ls|dir|pwd|cd|git status|git log|git diff|type|cat|help)\b/i;
5864
6004
  if (isAuto || command && safeRegex.test(command.trim())) return "allow";
5865
6005
  return new Promise((resolve) => {
5866
- setPendingApproval({ tool, args, resolve });
6006
+ setPendingApproval({ tool, args: args2, resolve });
5867
6007
  setActiveView("terminalApproval");
5868
6008
  });
5869
6009
  }
5870
6010
  if (isAuto) return "allow";
5871
6011
  return new Promise((resolve) => {
5872
- setPendingApproval({ tool, args, resolve });
6012
+ setPendingApproval({ tool, args: args2, resolve });
5873
6013
  setActiveView("approval");
5874
6014
  });
5875
6015
  },
@@ -6168,7 +6308,7 @@ Selection: ${val}`,
6168
6308
  }
6169
6309
  return currentList.filter((s) => s.cmd.toLowerCase().includes(query));
6170
6310
  }, [input]);
6171
- useEffect5(() => {
6311
+ useEffect6(() => {
6172
6312
  setSelectedIndex(0);
6173
6313
  }, [suggestions]);
6174
6314
  const renderActiveView = () => {
@@ -6484,6 +6624,7 @@ Selection: ${val}`,
6484
6624
  return /* @__PURE__ */ React10.createElement(
6485
6625
  ProfileForm,
6486
6626
  {
6627
+ initialData: profileData,
6487
6628
  onSave: (profile) => {
6488
6629
  setProfileData(profile);
6489
6630
  setMessages((prev) => [...prev, { id: Date.now(), role: "system", text: `\u2705 Profile updated: ${profile.name} (${profile.nickname})` }]);
@@ -6501,7 +6642,7 @@ Selection: ${val}`,
6501
6642
  setResolutionData(null);
6502
6643
  setActiveView("chat");
6503
6644
  setTimeout(() => {
6504
- handleSubmit(val);
6645
+ handleSubmit(val, true);
6505
6646
  }, 500);
6506
6647
  },
6507
6648
  onEdit: (val) => {
@@ -6513,9 +6654,9 @@ Selection: ${val}`,
6513
6654
  ));
6514
6655
  case "approval":
6515
6656
  return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true, underline: true }, "\u{1F510} SECURITY GATE: FILE WRITE PERMISSION"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "The agent is attempting to modify: ", /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, parseArgs(pendingApproval?.args || "{}").path || "Unknown File")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, borderStyle: "single", borderColor: "#333", paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray" }, "--- PROPOSED CONTENT / DIFF ---"), (() => {
6516
- const args = parseArgs(pendingApproval?.args || "{}");
6517
- const oldVal = args.TargetContent || args.content_to_replace || null;
6518
- const newVal = args.content || args.ReplacementContent || args.content_to_add || args.replacementContent || null;
6657
+ const args2 = parseArgs(pendingApproval?.args || "{}");
6658
+ const oldVal = args2.TargetContent || args2.content_to_replace || null;
6659
+ const newVal = args2.content || args2.ReplacementContent || args2.content_to_add || args2.replacementContent || null;
6519
6660
  if (oldVal && newVal) {
6520
6661
  return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Text10, { color: "red", wrap: "anywhere", bold: true }, "- ", oldVal)), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "green", wrap: "anywhere", bold: true }, "+ ", newVal.replace(/\[\/n\]?/g, "\\n"))));
6521
6662
  }
@@ -6767,10 +6908,10 @@ var init_app = __esm({
6767
6908
  init_text();
6768
6909
  SESSION_START_TIME = Date.now();
6769
6910
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
6770
- packageJsonPath = path16.join(path16.dirname(fileURLToPath(import.meta.url)), "../package.json");
6771
- packageJson = JSON.parse(fs18.readFileSync(packageJsonPath, "utf8"));
6911
+ packageJsonPath = path15.join(path15.dirname(fileURLToPath(import.meta.url)), "../package.json");
6912
+ packageJson = JSON.parse(fs17.readFileSync(packageJsonPath, "utf8"));
6772
6913
  versionFluxflow = packageJson.version;
6773
- updatedOn = "2026-05-20";
6914
+ updatedOn = packageJson.date || "2026-05-20";
6774
6915
  ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION")), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, null, "The agent already finished the task before your hint was consumed.")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, backgroundColor: "#222", paddingX: 2, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 0 }, /* @__PURE__ */ React10.createElement(
6775
6916
  CommandMenu,
6776
6917
  {
@@ -6832,5 +6973,5 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
6832
6973
  console.warn = (...args) => !isNoise(args) && originalWarn(...args);
6833
6974
  console.error = (...args) => !isNoise(args) && originalError(...args);
6834
6975
  process.stdout.write("\x1Bc");
6835
- render(/* @__PURE__ */ React11.createElement(App2, null), { exitOnCtrlC: false });
6976
+ render(/* @__PURE__ */ React11.createElement(App2, { args: process.argv.slice(2) }), { exitOnCtrlC: false });
6836
6977
  }
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.11.3",
3
+ "version": "1.12.0",
4
+ "date": "2026-05-21",
4
5
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
6
  "keywords": [
6
7
  "ai",