fluxflow-cli 1.0.2 → 1.0.3

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/LICENSE +21 -0
  2. package/dist/fluxflow.js +79 -109
  3. package/package.json +1 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kushal Roy Chowdhury
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/fluxflow.js CHANGED
@@ -8,8 +8,6 @@ import { render } from "ink";
8
8
  import React8, { useState as useState4, useEffect as useEffect3, useRef, useMemo } from "react";
9
9
  import { Box as Box8, Text as Text8, useInput as useInput3, useStdout, Static } from "ink";
10
10
  import fs14 from "fs-extra";
11
- import path16 from "path";
12
- import { fileURLToPath as fileURLToPath9 } from "url";
13
11
  import { MultilineInput } from "ink-multiline-input";
14
12
  import TextInput2 from "ink-text-input";
15
13
 
@@ -257,8 +255,6 @@ import gradient from "gradient-string";
257
255
 
258
256
  // src/utils/secrets.js
259
257
  import fs2 from "fs-extra";
260
- import path2 from "path";
261
- import { fileURLToPath } from "url";
262
258
 
263
259
  // src/utils/crypto.js
264
260
  import fs from "fs";
@@ -295,12 +291,21 @@ var writeEncryptedJson = (filePath, data) => {
295
291
  }
296
292
  };
297
293
 
294
+ // src/utils/paths.js
295
+ import os from "os";
296
+ import path2 from "path";
297
+ var FLUXFLOW_DIR = path2.join(os.homedir(), ".fluxflow");
298
+ var LOGS_DIR = path2.join(FLUXFLOW_DIR, "logs");
299
+ var SECRET_DIR = path2.join(FLUXFLOW_DIR, "secret");
300
+ var SETTINGS_FILE = path2.join(FLUXFLOW_DIR, "settings.json");
301
+ var HISTORY_FILE = path2.join(SECRET_DIR, "history.json");
302
+ var USAGE_FILE = path2.join(SECRET_DIR, "usage.json");
303
+ var MEMORIES_FILE = path2.join(SECRET_DIR, "memories.json");
304
+ var TEMP_MEM_FILE = path2.join(SECRET_DIR, "memory-temp.json");
305
+
298
306
  // src/utils/secrets.js
299
- var __filename = fileURLToPath(import.meta.url);
300
- var __dirname = path2.dirname(__filename);
301
- var AGENT_ROOT = path2.join(__dirname, "../../");
302
- var SECRET_DIR = path2.join(AGENT_ROOT, "secret");
303
- var SECRET_FILE = path2.join(SECRET_DIR, "secrets.json");
307
+ import path3 from "path";
308
+ var SECRET_FILE = path3.join(SECRET_DIR, "secrets.json");
304
309
  var getAPIKey = async () => {
305
310
  try {
306
311
  const secrets = readEncryptedJson(SECRET_FILE, {});
@@ -476,13 +481,8 @@ Current date and Time: ${(/* @__PURE__ */ new Date()).toLocaleString()}
476
481
 
477
482
  // src/utils/history.js
478
483
  import fs3 from "fs-extra";
479
- import path3 from "path";
480
- import { fileURLToPath as fileURLToPath2 } from "url";
484
+ import path4 from "path";
481
485
  import { nanoid } from "nanoid";
482
- var __filename2 = fileURLToPath2(import.meta.url);
483
- var __dirname2 = path3.dirname(__filename2);
484
- var AGENT_ROOT2 = path3.join(__dirname2, "../../");
485
- var HISTORY_FILE = path3.join(AGENT_ROOT2, "secret/history.json");
486
486
  var WRITE_LOCK = Promise.resolve();
487
487
  var withLock = (op) => {
488
488
  const nextLock = WRITE_LOCK.then(async () => {
@@ -517,7 +517,7 @@ var saveChat = async (id, name, messages) => {
517
517
  messages,
518
518
  updatedAt: Date.now()
519
519
  };
520
- await fs3.ensureDir(path3.dirname(HISTORY_FILE));
520
+ await fs3.ensureDir(path4.dirname(HISTORY_FILE));
521
521
  await fs3.writeJson(HISTORY_FILE, history, { spaces: 2 });
522
522
  });
523
523
  };
@@ -530,7 +530,7 @@ var saveChatTitle = async (id, title) => {
530
530
  } else {
531
531
  history[id] = { name: title, messages: [], updatedAt: Date.now() };
532
532
  }
533
- await fs3.ensureDir(path3.dirname(HISTORY_FILE));
533
+ await fs3.ensureDir(path4.dirname(HISTORY_FILE));
534
534
  await fs3.writeJson(HISTORY_FILE, history, { spaces: 2 });
535
535
  });
536
536
  };
@@ -539,13 +539,12 @@ var deleteChat = async (id) => {
539
539
  const history = await loadHistory();
540
540
  delete history[id];
541
541
  await fs3.writeJson(HISTORY_FILE, history, { spaces: 2 });
542
- const tempFile = path3.join(AGENT_ROOT2, "secret/memory-temp.json");
543
- if (await fs3.pathExists(tempFile)) {
542
+ if (await fs3.pathExists(TEMP_MEM_FILE)) {
544
543
  try {
545
- const temp = await fs3.readJson(tempFile);
544
+ const temp = await fs3.readJson(TEMP_MEM_FILE);
546
545
  if (temp[id]) {
547
546
  delete temp[id];
548
- await fs3.writeJson(tempFile, temp, { spaces: 2 });
547
+ await fs3.writeJson(TEMP_MEM_FILE, temp, { spaces: 2 });
549
548
  }
550
549
  } catch (e) {
551
550
  }
@@ -582,15 +581,11 @@ var getTruncatedHistory = (history, exchangesToRemove = 4) => {
582
581
 
583
582
  // src/utils/usage.js
584
583
  import fs4 from "fs-extra";
585
- import path4 from "path";
586
- import { fileURLToPath as fileURLToPath3 } from "url";
587
- var __dirname3 = path4.dirname(fileURLToPath3(import.meta.url));
588
- var USAGE_PATH = path4.join(__dirname3, "../../secret/usage.json");
589
584
  var getDailyUsage = async () => {
590
585
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
591
586
  try {
592
- if (await fs4.exists(USAGE_PATH)) {
593
- const data = await fs4.readJson(USAGE_PATH);
587
+ if (await fs4.exists(USAGE_FILE)) {
588
+ const data = await fs4.readJson(USAGE_FILE);
594
589
  if (data.date === today) {
595
590
  return data.stats;
596
591
  }
@@ -599,19 +594,19 @@ var getDailyUsage = async () => {
599
594
  console.error("Failed to read usage:", err);
600
595
  }
601
596
  const defaultStats = { agent: 0, background: 0, search: 0 };
602
- await fs4.writeJson(USAGE_PATH, { date: today, stats: defaultStats }, { spaces: 2 });
597
+ await fs4.writeJson(USAGE_FILE, { date: today, stats: defaultStats }, { spaces: 2 });
603
598
  return defaultStats;
604
599
  };
605
600
  var incrementUsage = async (key) => {
606
601
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
607
- const data = await fs4.readJson(USAGE_PATH).catch(() => ({ date: today, stats: { agent: 0, background: 0, search: 0 } }));
602
+ const data = await fs4.readJson(USAGE_FILE).catch(() => ({ date: today, stats: { agent: 0, background: 0, search: 0 } }));
608
603
  if (data.date !== today) {
609
604
  data.date = today;
610
605
  data.stats = { agent: 0, background: 0, search: 0 };
611
606
  }
612
607
  if (data.stats[key] !== void 0) {
613
608
  data.stats[key]++;
614
- await fs4.writeJson(USAGE_PATH, data, { spaces: 2 });
609
+ await fs4.writeJson(USAGE_FILE, data, { spaces: 2 });
615
610
  }
616
611
  };
617
612
  var checkQuota = async (key, settings) => {
@@ -662,10 +657,6 @@ var parseArgs = (argsString) => {
662
657
  // src/tools/web_search.js
663
658
  import fs5 from "fs";
664
659
  import path5 from "path";
665
- import { fileURLToPath as fileURLToPath4 } from "url";
666
- var __filename3 = fileURLToPath4(import.meta.url);
667
- var __dirname4 = path5.dirname(__filename3);
668
- var AGENT_ROOT3 = path5.join(__dirname4, "../../");
669
660
  var web_search = async (argsString) => {
670
661
  const { query, limit = 10 } = parseArgs(argsString);
671
662
  if (!query) return 'ERROR: Missing "query" argument for web_search.';
@@ -693,7 +684,7 @@ Source: ${url}
693
684
  Snippet: ${snippet}`);
694
685
  count++;
695
686
  }
696
- const toolLogDir = path5.join(AGENT_ROOT3, "logs", "tools");
687
+ const toolLogDir = path5.join(LOGS_DIR, "tools");
697
688
  if (!fs5.existsSync(toolLogDir)) {
698
689
  fs5.mkdirSync(toolLogDir, { recursive: true });
699
690
  }
@@ -705,7 +696,7 @@ Results: ${results}
705
696
  `);
706
697
  if (results.length === 0) {
707
698
  if (html.includes("anomaly")) {
708
- const toolErrDir = path5.join(AGENT_ROOT3, "logs", "tools");
699
+ const toolErrDir = path5.join(LOGS_DIR, "tools");
709
700
  if (!fs5.existsSync(toolErrDir)) {
710
701
  fs5.mkdirSync(toolErrDir, { recursive: true });
711
702
  }
@@ -727,11 +718,7 @@ ${finalResults}`;
727
718
  // src/tools/web_scrape.js
728
719
  import fs6 from "fs";
729
720
  import path6 from "path";
730
- import { fileURLToPath as fileURLToPath5 } from "url";
731
721
  import * as cuimp2 from "cuimp";
732
- var __filename4 = fileURLToPath5(import.meta.url);
733
- var __dirname5 = path6.dirname(__filename4);
734
- var AGENT_ROOT4 = path6.join(__dirname5, "../../");
735
722
  var web_scrape = async (args) => {
736
723
  const urlMatch = args.match(/url\s*=\s*["'](.*)["']/);
737
724
  const url = urlMatch ? urlMatch[1] : args;
@@ -752,7 +739,7 @@ var web_scrape = async (args) => {
752
739
  html = html.replace(/<header\b[^<]*(?:(?!<\/header>)<[^<]*)*<\/header>/gi, "");
753
740
  let text = html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
754
741
  const finalContent = text.substring(0, 2e4);
755
- const toolLogDir = path6.join(AGENT_ROOT4, "logs", "tools");
742
+ const toolLogDir = path6.join(LOGS_DIR, "tools");
756
743
  if (!fs6.existsSync(toolLogDir)) {
757
744
  fs6.mkdirSync(toolLogDir, { recursive: true });
758
745
  }
@@ -771,14 +758,6 @@ ${finalContent}${text.length > 2e4 ? "\n\n[TRUNCATED AT 20K CHARS]" : ""}`;
771
758
  };
772
759
 
773
760
  // src/tools/memory.js
774
- import path7 from "path";
775
- import { fileURLToPath as fileURLToPath6 } from "url";
776
- var __filename5 = fileURLToPath6(import.meta.url);
777
- var __dirname6 = path7.dirname(__filename5);
778
- var AGENT_ROOT5 = path7.join(__dirname6, "../../");
779
- var SECRET_DIR2 = path7.join(AGENT_ROOT5, "secret");
780
- var MEMORIES_PATH = path7.join(SECRET_DIR2, "memories.json");
781
- var TEMP_MEM_PATH = path7.join(SECRET_DIR2, "memory-temp.json");
782
761
  var memory = async (rawArgs, context = {}) => {
783
762
  const parseArg = (key) => {
784
763
  const regex = new RegExp(`${key}\\s*=\\s*(["'])(.*?)\\1(?=\\s*[,)]|\\s+\\w+\\s*=|$)`, "s");
@@ -793,7 +772,7 @@ var memory = async (rawArgs, context = {}) => {
793
772
  const chatId = parseArg("chat-id") || context.chatId || context.sessionId || "default-session";
794
773
  if (action === "temp") {
795
774
  if (!content) return "ERROR: Missing 'content' for temp memory.";
796
- const tempStorage = readEncryptedJson(TEMP_MEM_PATH, {});
775
+ const tempStorage = readEncryptedJson(TEMP_MEM_FILE, {});
797
776
  if (!tempStorage[chatId]) tempStorage[chatId] = [];
798
777
  const MAX_CHARS = 3e3 * 4;
799
778
  let currentTotalLength = tempStorage[chatId].reduce((acc, m) => acc + m.length, 0);
@@ -802,11 +781,11 @@ var memory = async (rawArgs, context = {}) => {
802
781
  currentTotalLength -= removed.length;
803
782
  }
804
783
  tempStorage[chatId].push(content);
805
- writeEncryptedJson(TEMP_MEM_PATH, tempStorage);
784
+ writeEncryptedJson(TEMP_MEM_FILE, tempStorage);
806
785
  return `SUCCESS: Temporary context saved for session [${chatId}]. (Size: ${currentTotalLength + content.length} chars)`;
807
786
  }
808
787
  if (action === "user") {
809
- const memories = readEncryptedJson(MEMORIES_PATH, []);
788
+ const memories = readEncryptedJson(MEMORIES_FILE, []);
810
789
  if (method === "add") {
811
790
  if (!content) return "ERROR: Missing 'content' for memory addition.";
812
791
  const MAX_CHARS = 2e3 * 4;
@@ -817,7 +796,7 @@ var memory = async (rawArgs, context = {}) => {
817
796
  }
818
797
  const newMemory = { id: `mem-${Date.now().toString(36)}`, memory: content };
819
798
  memories.push(newMemory);
820
- writeEncryptedJson(MEMORIES_PATH, memories);
799
+ writeEncryptedJson(MEMORIES_FILE, memories);
821
800
  return `SUCCESS: Memory added with ID [${newMemory.id}]. (Vault Size: ${currentTotalLength + content.length} chars)`;
822
801
  }
823
802
  if (method === "update") {
@@ -827,7 +806,7 @@ var memory = async (rawArgs, context = {}) => {
827
806
  const index = memories.findIndex((m) => m.id === memId);
828
807
  if (index === -1) return `ERROR: Memory ID [${memId}] not found.`;
829
808
  memories[index].memory = newText;
830
- writeEncryptedJson(MEMORIES_PATH, memories);
809
+ writeEncryptedJson(MEMORIES_FILE, memories);
831
810
  return `SUCCESS: Memory [${memId}] updated.`;
832
811
  }
833
812
  if (method === "delete") {
@@ -836,7 +815,7 @@ var memory = async (rawArgs, context = {}) => {
836
815
  const initialLen = memories.length;
837
816
  const updatedMemories = memories.filter((m) => m.id !== memId);
838
817
  if (updatedMemories.length === initialLen) return `ERROR: Memory ID [${memId}] not found.`;
839
- writeEncryptedJson(MEMORIES_PATH, updatedMemories);
818
+ writeEncryptedJson(MEMORIES_FILE, updatedMemories);
840
819
  return `SUCCESS: Memory [${memId}] deleted.`;
841
820
  }
842
821
  return `ERROR: Invalid method [${method}] for user memory. Use 'add', 'update', or 'delete'.`;
@@ -900,10 +879,10 @@ var summary = async (rawArgs, context = {}) => {
900
879
 
901
880
  // src/tools/list_files.js
902
881
  import fs7 from "fs";
903
- import path8 from "path";
882
+ import path7 from "path";
904
883
  var list_files = async (args) => {
905
884
  const { path: targetPath = "." } = parseArgs(args);
906
- const absolutePath = path8.resolve(process.cwd(), targetPath);
885
+ const absolutePath = path7.resolve(process.cwd(), targetPath);
907
886
  try {
908
887
  if (!fs7.existsSync(absolutePath)) {
909
888
  return `ERROR: Path [${targetPath}] does not exist.`;
@@ -920,7 +899,7 @@ var list_files = async (args) => {
920
899
  const maxDisplay = 100;
921
900
  const displayFiles = files2.slice(0, maxDisplay);
922
901
  const list = displayFiles.map((file) => {
923
- const fPath = path8.join(absolutePath, file);
902
+ const fPath = path7.join(absolutePath, file);
924
903
  let indicator = "\u{1F4C4}";
925
904
  let metaPart = "";
926
905
  try {
@@ -955,11 +934,11 @@ ${list}${footer}`;
955
934
 
956
935
  // src/tools/view_file.js
957
936
  import fs8 from "fs";
958
- import path9 from "path";
937
+ import path8 from "path";
959
938
  var view_file = async (args) => {
960
939
  const { path: targetPath, start_line = 1, end_line = 500 } = parseArgs(args);
961
940
  if (!targetPath) return 'ERROR: Missing "path" argument for view_file.';
962
- const absolutePath = path9.resolve(process.cwd(), targetPath);
941
+ const absolutePath = path8.resolve(process.cwd(), targetPath);
963
942
  try {
964
943
  if (!fs8.existsSync(absolutePath)) {
965
944
  return `ERROR: File [${targetPath}] does not exist.`;
@@ -986,14 +965,14 @@ ${code}`;
986
965
 
987
966
  // src/tools/write_file.js
988
967
  import fs9 from "fs";
989
- import path10 from "path";
968
+ import path9 from "path";
990
969
  var write_file = async (args) => {
991
970
  let { path: targetPath, content } = parseArgs(args);
992
971
  if (!targetPath) return 'ERROR: Missing "path" argument for write_file.';
993
972
  if (content === void 0) return 'ERROR: Missing "content" argument for write_file.';
994
973
  content = content.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").trim();
995
- const absolutePath = path10.resolve(process.cwd(), targetPath);
996
- const parentDir = path10.dirname(absolutePath);
974
+ const absolutePath = path9.resolve(process.cwd(), targetPath);
975
+ const parentDir = path9.dirname(absolutePath);
997
976
  try {
998
977
  if (!fs9.existsSync(parentDir)) {
999
978
  fs9.mkdirSync(parentDir, { recursive: true });
@@ -1034,7 +1013,7 @@ ${snippet}`;
1034
1013
 
1035
1014
  // src/tools/update_file.js
1036
1015
  import fs10 from "fs";
1037
- import path11 from "path";
1016
+ import path10 from "path";
1038
1017
  var update_file = async (args) => {
1039
1018
  let { path: targetPath, content_to_replace, content_to_add } = parseArgs(args);
1040
1019
  if (!targetPath) return 'ERROR: Missing "path" argument for update_file.';
@@ -1043,7 +1022,7 @@ var update_file = async (args) => {
1043
1022
  const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").trim();
1044
1023
  content_to_replace = strip(content_to_replace);
1045
1024
  content_to_add = strip(content_to_add);
1046
- const absolutePath = path11.resolve(process.cwd(), targetPath);
1025
+ const absolutePath = path10.resolve(process.cwd(), targetPath);
1047
1026
  try {
1048
1027
  if (!fs10.existsSync(absolutePath)) {
1049
1028
  return `ERROR: File [${targetPath}] does not exist. Use write_file instead.`;
@@ -1136,10 +1115,10 @@ ${finalOutput}`);
1136
1115
 
1137
1116
  // src/tools/read_folder.js
1138
1117
  import fs11 from "fs";
1139
- import path12 from "path";
1118
+ import path11 from "path";
1140
1119
  var read_folder = async (args) => {
1141
1120
  const { path: targetPath = "." } = parseArgs(args);
1142
- const absolutePath = path12.resolve(process.cwd(), targetPath);
1121
+ const absolutePath = path11.resolve(process.cwd(), targetPath);
1143
1122
  try {
1144
1123
  if (!fs11.existsSync(absolutePath)) {
1145
1124
  return `ERROR: Path [${targetPath}] does not exist.`;
@@ -1153,7 +1132,7 @@ var read_folder = async (args) => {
1153
1132
  const displayItems = files.slice(0, maxDisplay);
1154
1133
  const folderData = [];
1155
1134
  for (const file of displayItems) {
1156
- const fPath = path12.join(absolutePath, file);
1135
+ const fPath = path11.join(absolutePath, file);
1157
1136
  let indicator = "\u{1F4C4}";
1158
1137
  let info = { name: file, type: "unknown", size: "N/A", mtime: "N/A" };
1159
1138
  try {
@@ -1223,15 +1202,9 @@ var dispatchTool = async (toolName, args, context = {}) => {
1223
1202
  };
1224
1203
 
1225
1204
  // src/utils/ai.js
1226
- import { fileURLToPath as fileURLToPath7 } from "url";
1227
- import path13 from "path";
1205
+ import path12 from "path";
1228
1206
  import fs12 from "fs";
1229
- var __filename6 = fileURLToPath7(import.meta.url);
1230
- var __dirname7 = path13.dirname(__filename6);
1231
- var AGENT_ROOT6 = path13.join(__dirname7, "../../");
1232
1207
  var client = null;
1233
- var TEMP_MEM_PATH2 = path13.join(AGENT_ROOT6, "secret", "memory-temp.json");
1234
- var PERSISTENT_MEM_PATH = path13.join(AGENT_ROOT6, "secret", "memories.json");
1235
1208
  var TERMINATION_SIGNAL = false;
1236
1209
  var signalTermination = () => {
1237
1210
  TERMINATION_SIGNAL = true;
@@ -1288,9 +1261,9 @@ var getAIStream = async function* (modelName, history, settings, steeringCallbac
1288
1261
  if (systemSettings?.compression === 0 && (sessionStats?.tokens || 0) > 196e3) {
1289
1262
  modifiedHistory = getTruncatedHistory(modifiedHistory, 4);
1290
1263
  }
1291
- const tempStorage = readEncryptedJson(TEMP_MEM_PATH2, {});
1264
+ const tempStorage = readEncryptedJson(TEMP_MEM_FILE, {});
1292
1265
  const otherMemories = Object.entries(tempStorage).filter(([id]) => id !== chatId).flatMap(([_, mems]) => mems).map((mem) => `- ${mem}`).join("\n");
1293
- const persistentStorage = readEncryptedJson(PERSISTENT_MEM_PATH, []);
1266
+ const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
1294
1267
  const mainUserMemories = persistentStorage.map((m) => `- ${m.memory}`).join("\n");
1295
1268
  const janitorUserMemories = persistentStorage.map((m) => `- [${m.id}]: ${m.memory}`).join("\n");
1296
1269
  const systemInstruction = getSystemInstruction(profile, thinkingLevel, mode, systemSettings, otherMemories, mainUserMemories, isMemoryEnabled);
@@ -1344,11 +1317,11 @@ USER_PROMPT: ${agentText}`.trim();
1344
1317
  } catch (err) {
1345
1318
  const errMsg = err.message || String(err);
1346
1319
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1347
- const agentErrDir = path13.join(AGENT_ROOT6, "logs", "agent");
1320
+ const agentErrDir = path12.join(LOGS_DIR, "agent");
1348
1321
  if (!fs12.existsSync(agentErrDir)) {
1349
1322
  fs12.mkdirSync(agentErrDir, { recursive: true });
1350
1323
  }
1351
- fs12.appendFileSync(path13.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errMsg}
1324
+ fs12.appendFileSync(path12.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errMsg}
1352
1325
  `);
1353
1326
  const isRetryable = errMsg.includes("429") || errMsg.includes("503") || errMsg.includes("overloaded") || errMsg.includes("deadline");
1354
1327
  if (isRetryable && retryCount < MAX_RETRIES) {
@@ -1397,7 +1370,7 @@ USER_PROMPT: ${agentText}`.trim();
1397
1370
  const { path: targetPath2, start_line = 1, end_line = 500 } = parseArgs(toolCall.args);
1398
1371
  let totalLines = "...";
1399
1372
  try {
1400
- const absPath = path13.resolve(process.cwd(), targetPath2);
1373
+ const absPath = path12.resolve(process.cwd(), targetPath2);
1401
1374
  if (fs12.existsSync(absPath)) {
1402
1375
  const content = fs12.readFileSync(absPath, "utf8");
1403
1376
  totalLines = content.split("\n").length;
@@ -1445,7 +1418,7 @@ ${boxBottom}
1445
1418
  /\/usr\//
1446
1419
  // Sensitive Linux paths
1447
1420
  ];
1448
- const currentDrive = path13.resolve(process.cwd()).substring(0, 3).toLowerCase();
1421
+ const currentDrive = path12.resolve(process.cwd()).substring(0, 3).toLowerCase();
1449
1422
  const isViolating = riskyPatterns.some((pattern) => {
1450
1423
  if (pattern.source === "[a-zA-Z]:[\\\\\\/]") {
1451
1424
  const driveMatch = command.match(/[a-zA-Z]:[\\\/]/i);
@@ -1467,8 +1440,8 @@ ${boxBottom}
1467
1440
  const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
1468
1441
  if (targetPath) {
1469
1442
  const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
1470
- const absoluteTarget = path13.resolve(targetPath);
1471
- const absoluteCwd = path13.resolve(process.cwd());
1443
+ const absoluteTarget = path12.resolve(targetPath);
1444
+ const absoluteCwd = path12.resolve(process.cwd());
1472
1445
  if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
1473
1446
  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.`;
1474
1447
  toolResults.push(`[TOOL_RESULT]: ERROR: ${denyMsg}`);
@@ -1507,11 +1480,11 @@ ${boxBottom}
1507
1480
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1508
1481
  const isErr = result.startsWith("ERROR:");
1509
1482
  const logStatus = isErr ? result.trim() : "SUCCESS";
1510
- const toolHistDir = path13.join(AGENT_ROOT6, "logs", "tools");
1483
+ const toolHistDir = path12.join(LOGS_DIR, "tools");
1511
1484
  if (!fs12.existsSync(toolHistDir)) {
1512
1485
  fs12.mkdirSync(toolHistDir, { recursive: true });
1513
1486
  }
1514
- fs12.appendFileSync(path13.join(toolHistDir, "history.log"), `HISTORY [${timestamp}]: ${toolCall.toolName} [${logStatus}]
1487
+ fs12.appendFileSync(path12.join(toolHistDir, "history.log"), `HISTORY [${timestamp}]: ${toolCall.toolName} [${logStatus}]
1515
1488
  `);
1516
1489
  } catch (logErr) {
1517
1490
  }
@@ -1565,11 +1538,11 @@ ${boxBottom}
1565
1538
  if (parts && parts[1]?.text) {
1566
1539
  finalSynthesis = parts[1].text;
1567
1540
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1568
- const janitorLogDir = path13.join(AGENT_ROOT6, "logs", "janitor");
1541
+ const janitorLogDir = path12.join(LOGS_DIR, "janitor");
1569
1542
  if (!fs12.existsSync(janitorLogDir)) {
1570
1543
  fs12.mkdirSync(janitorLogDir, { recursive: true });
1571
1544
  }
1572
- fs12.appendFileSync(path13.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: ${finalSynthesis}
1545
+ fs12.appendFileSync(path12.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: ${finalSynthesis}
1573
1546
  `);
1574
1547
  } else if (parts && parts[0]?.text) finalSynthesis = parts[0].text;
1575
1548
  else if (janitorResult.response && janitorResult.response.text) finalSynthesis = janitorResult.response.text();
@@ -1581,8 +1554,8 @@ ${boxBottom}
1581
1554
  const toolContext = { chatId, sessionId: chatId, history };
1582
1555
  const result = await dispatchTool(janitorToolCall.toolName, janitorToolCall.args, toolContext);
1583
1556
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1584
- const janitorLogDir = path13.join(AGENT_ROOT6, "logs", "janitor");
1585
- fs12.appendFileSync(path13.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: RESULT [${janitorToolCall.toolName}]: ${result}
1557
+ const janitorLogDir = path12.join(LOGS_DIR, "janitor");
1558
+ fs12.appendFileSync(path12.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: RESULT [${janitorToolCall.toolName}]: ${result}
1586
1559
  `);
1587
1560
  if (janitorToolCall.toolName === "memory" && !janitorToolCall.args.includes("action='temp'")) {
1588
1561
  yield { type: "memory_updated" };
@@ -1590,11 +1563,11 @@ ${boxBottom}
1590
1563
  }
1591
1564
  } catch (janitorErr) {
1592
1565
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1593
- const janitorErrDir = path13.join(AGENT_ROOT6, "logs", "janitor");
1566
+ const janitorErrDir = path12.join(LOGS_DIR, "janitor");
1594
1567
  if (!fs12.existsSync(janitorErrDir)) {
1595
1568
  fs12.mkdirSync(janitorErrDir, { recursive: true });
1596
1569
  }
1597
- fs12.appendFileSync(path13.join(janitorErrDir, "error.log"), `ERROR [${date}]: ${janitorErr.message}
1570
+ fs12.appendFileSync(path12.join(janitorErrDir, "error.log"), `ERROR [${date}]: ${janitorErr.message}
1598
1571
  `);
1599
1572
  console.error("Janitor Background Tasks Failed:", janitorErr.message);
1600
1573
  }
@@ -1622,10 +1595,6 @@ ${timestamp}`;
1622
1595
 
1623
1596
  // src/utils/settings.js
1624
1597
  import fs13 from "fs-extra";
1625
- import path14 from "path";
1626
- import { fileURLToPath as fileURLToPath8 } from "url";
1627
- var __dirname8 = path14.dirname(fileURLToPath8(import.meta.url));
1628
- var SETTINGS_PATH = path14.join(__dirname8, "../../settings.json");
1629
1598
  var DEFAULT_SETTINGS = {
1630
1599
  mode: "Flux",
1631
1600
  thinkingLevel: "Medium",
@@ -1654,8 +1623,8 @@ var DEFAULT_SETTINGS = {
1654
1623
  };
1655
1624
  var loadSettings = async () => {
1656
1625
  try {
1657
- if (await fs13.exists(SETTINGS_PATH)) {
1658
- const saved = await fs13.readJson(SETTINGS_PATH);
1626
+ if (await fs13.exists(SETTINGS_FILE)) {
1627
+ const saved = await fs13.readJson(SETTINGS_FILE);
1659
1628
  return {
1660
1629
  ...DEFAULT_SETTINGS,
1661
1630
  ...saved,
@@ -1673,7 +1642,7 @@ var saveSettings = async (settings) => {
1673
1642
  try {
1674
1643
  const current = await loadSettings();
1675
1644
  const updated = { ...current, ...settings };
1676
- await fs13.writeJson(SETTINGS_PATH, updated, { spaces: 2 });
1645
+ await fs13.writeJson(SETTINGS_FILE, updated, { spaces: 2 });
1677
1646
  return true;
1678
1647
  } catch (err) {
1679
1648
  console.error("Failed to save settings:", err);
@@ -1722,13 +1691,13 @@ function ResumeModal({ onSelect, onDelete, onClose }) {
1722
1691
  // src/components/MemoryModal.jsx
1723
1692
  import React7, { useState as useState3, useEffect as useEffect2 } from "react";
1724
1693
  import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
1725
- import path15 from "path";
1726
- var MEMORIES_PATH2 = path15.join(process.cwd(), "secret", "memories.json");
1694
+ import path13 from "path";
1695
+ var MEMORIES_PATH = path13.join(process.cwd(), "secret", "memories.json");
1727
1696
  function MemoryModal({ onClose }) {
1728
1697
  const [memories, setMemories] = useState3([]);
1729
1698
  const [selectedIndex, setSelectedIndex] = useState3(0);
1730
1699
  const loadMemories = () => {
1731
- const data = readEncryptedJson(MEMORIES_PATH2, []);
1700
+ const data = readEncryptedJson(MEMORIES_PATH, []);
1732
1701
  setMemories(data);
1733
1702
  };
1734
1703
  useEffect2(() => {
@@ -1741,7 +1710,7 @@ function MemoryModal({ onClose }) {
1741
1710
  if (input === "x" && memories.length > 0) {
1742
1711
  const idToDelete = memories[selectedIndex].id;
1743
1712
  const updated = memories.filter((m) => m.id !== idToDelete);
1744
- writeEncryptedJson(MEMORIES_PATH2, updated);
1713
+ writeEncryptedJson(MEMORIES_PATH, updated);
1745
1714
  setMemories(updated);
1746
1715
  if (selectedIndex >= updated.length && updated.length > 0) {
1747
1716
  setSelectedIndex(updated.length - 1);
@@ -2096,18 +2065,19 @@ ${list || "No saved chats found."}` }];
2096
2065
  }
2097
2066
  case "/reset": {
2098
2067
  const runReset = async () => {
2099
- const AGENT_ROOT7 = path16.join(path16.dirname(fileURLToPath9(import.meta.url)), "../");
2100
- const logsDir = path16.join(AGENT_ROOT7, "logs");
2101
- const secretDir = path16.join(AGENT_ROOT7, "secret");
2102
- const settingsFile = path16.join(AGENT_ROOT7, "settings.json");
2103
2068
  try {
2104
2069
  setMessages((prev) => {
2105
2070
  setCompletedIndex(prev.length + 1);
2106
2071
  return [...prev, { id: Date.now(), role: "system", text: "\u2622\uFE0F [NUCLEAR] Initiating reset..." }];
2107
2072
  });
2108
- if (fs14.existsSync(logsDir)) fs14.removeSync(logsDir);
2109
- if (fs14.existsSync(secretDir)) fs14.removeSync(secretDir);
2110
- if (fs14.existsSync(settingsFile)) fs14.removeSync(settingsFile);
2073
+ if (fs14.existsSync(LOGS_DIR)) fs14.removeSync(LOGS_DIR);
2074
+ if (fs14.existsSync(SECRET_DIR)) fs14.removeSync(SECRET_DIR);
2075
+ if (fs14.existsSync(SETTINGS_FILE)) fs14.removeSync(SETTINGS_FILE);
2076
+ try {
2077
+ const items = fs14.readdirSync(FLUXFLOW_DIR);
2078
+ if (items.length === 0) fs14.removeSync(FLUXFLOW_DIR);
2079
+ } catch (e) {
2080
+ }
2111
2081
  setTimeout(() => {
2112
2082
  setActiveView("exit");
2113
2083
  setTimeout(() => process.exit(0), 500);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",