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.
- package/LICENSE +21 -0
- package/dist/fluxflow.js +79 -109
- 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
|
-
|
|
300
|
-
var
|
|
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
|
|
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(
|
|
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(
|
|
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
|
-
|
|
543
|
-
if (await fs3.pathExists(tempFile)) {
|
|
542
|
+
if (await fs3.pathExists(TEMP_MEM_FILE)) {
|
|
544
543
|
try {
|
|
545
|
-
const temp = await fs3.readJson(
|
|
544
|
+
const temp = await fs3.readJson(TEMP_MEM_FILE);
|
|
546
545
|
if (temp[id]) {
|
|
547
546
|
delete temp[id];
|
|
548
|
-
await fs3.writeJson(
|
|
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(
|
|
593
|
-
const data = await fs4.readJson(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
882
|
+
import path7 from "path";
|
|
904
883
|
var list_files = async (args) => {
|
|
905
884
|
const { path: targetPath = "." } = parseArgs(args);
|
|
906
|
-
const absolutePath =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
996
|
-
const parentDir =
|
|
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
|
|
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 =
|
|
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
|
|
1118
|
+
import path11 from "path";
|
|
1140
1119
|
var read_folder = async (args) => {
|
|
1141
1120
|
const { path: targetPath = "." } = parseArgs(args);
|
|
1142
|
-
const absolutePath =
|
|
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 =
|
|
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
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
1471
|
-
const absoluteCwd =
|
|
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 =
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
1585
|
-
fs12.appendFileSync(
|
|
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 =
|
|
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(
|
|
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(
|
|
1658
|
-
const saved = await fs13.readJson(
|
|
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(
|
|
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
|
|
1726
|
-
var
|
|
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(
|
|
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(
|
|
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(
|
|
2109
|
-
if (fs14.existsSync(
|
|
2110
|
-
if (fs14.existsSync(
|
|
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);
|