fluxflow-cli 1.0.3 → 1.0.5
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/README.md +3 -2
- package/dist/fluxflow.js +53 -39
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
### *The High-Fidelity Agentic Terminal for the Flux Era.*
|
|
5
5
|
|
|
6
|
-
**Flux Flow** is not just another CLI—it's a high-speed, sassy, and goal-oriented CLI AI Agent powered by the latest Gemini frontier models. Designed for developers who demand a premium UI/UX while managing complex file-system tasks, web research, and autonomous workflows.
|
|
6
|
+
**Flux Flow** is not just another CLI—it's a high-speed, sassy, and goal-oriented CLI AI Agent powered by the latest Gemini/Gemma frontier models. Designed for developers who demand a premium UI/UX while managing complex file-system tasks, web research, and autonomous workflows.
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -49,6 +49,7 @@ While you move at high speed, the Janitor follows behind—refining session titl
|
|
|
49
49
|
## 🛠️ Key Capabilities
|
|
50
50
|
- **Deep File-System Interaction**: Edit, move, and refactor code across multiple files with atomic precision.
|
|
51
51
|
- **Real-Time Web Intelligence**: Autonomous web-searching via DuckDuckGo for live news and technical research.
|
|
52
|
+
- **Autonomous Project Alignment**: Automatically detects and adheres to project-specific instructions in `Agent.md`, `Skills.md`, and `Fluxflow.md` for high-fidelity alignment with your coding standards and custom workflows.
|
|
52
53
|
- **Persistent Memory**: The agent learns from your preferences and project requirements across sessions.
|
|
53
54
|
|
|
54
55
|
---
|
|
@@ -65,4 +66,4 @@ Type `/settings` in-app to live-configure:
|
|
|
65
66
|
MIT © 2026 Flux Flow Team.
|
|
66
67
|
|
|
67
68
|
---
|
|
68
|
-
*Forged with ⚡ and 🧬. Welcome to the
|
|
69
|
+
*Forged with ⚡ and 🧬. Welcome to the FluxFlow.*
|
package/dist/fluxflow.js
CHANGED
|
@@ -417,13 +417,22 @@ ${userMemories}
|
|
|
417
417
|
` : ""}${isMemoryEnabled ? `${tempMemoriesStr}
|
|
418
418
|
|
|
419
419
|
` : ""}--- START SYSTEM INSTRUCTION ---
|
|
420
|
-
You are Flux Flow. A CLI AI Agent. Your tone will be friendly, warm, sassy, approchable, respectable, NO ROMANTIC OR FLIRTY WORDS. Dont mention modes
|
|
420
|
+
You are Flux Flow. A CLI AI Agent. Your tone will be friendly, warm, sassy, approchable, respectable, NO ROMANTIC OR FLIRTY WORDS. Dont mention modes unless explicitly asked. ${mode === "Flux" ? "You are currently operating in FLUX (dev) mode. Keep your agentic approach goal oriented. Use provided tools when needed. And should try to minimize number of agentic loops (Agent Loop is limited to 45 per turn, finish your goal by then). Analyze user prompt and project requirements, then plan your approach." : "You are currently operating in Flow (chat) mode. Focus more on conversation quality and user experience. Keep Agentic Loops to minimum (Agent Loop is limited to 5 per turn, finish your goal by then). You will get access to Web Tools only in this mode."}
|
|
421
421
|
CURRENT_WORKING_DIRECTORY: ${cwdStr}.
|
|
422
422
|
${nameStr}${nicknameStr}${userInstrStr}
|
|
423
423
|
|
|
424
424
|
${thinkingConfig}
|
|
425
425
|
|
|
426
426
|
${TOOL_PROTOCOL(mode)}
|
|
427
|
+
${mode === "Flux" ? `
|
|
428
|
+
-- START PROJECT SPECIFIC INSTRUCTIONS --
|
|
429
|
+
1. README.md (If exists): Reference this for high-level goals and project context to ensure your work aligns with the user's objectives.
|
|
430
|
+
2. Agent.md (If exists): This is your technical "Operating Manual". Follow the coding standards, directory structures, and tech stack constraints defined here without deviation.
|
|
431
|
+
3. Skills.md (If exists): Use this for complex workflows. If a task matches a "Skill" defined in this file, execute the documented step-by-step instructions exactly as written.
|
|
432
|
+
4. Fluxflow.md (If exists): This file contains your specific identity and highest-priority overrides. Instructions in Fluxflow.md supersede all other files if a conflict occurs.
|
|
433
|
+
|
|
434
|
+
Before starting any task, check for these files and treat them as your primary source of truth, overriding your general training data to remain consistent with this specific project's environment.
|
|
435
|
+
-- END PROJECT SPECIFIC INSTRUCTIONS --` : ""}
|
|
427
436
|
|
|
428
437
|
-- START MEMORY INSTRUCTIONS --
|
|
429
438
|
${isMemoryEnabled ? "You have a internal memory system. Data is saved by a background model working in parallel. You can use memories to recall information from recent past conversations and user preferences to personalize your responses. Dont over mention about memory, keep it light and contexual." : "Memory Features are currently turned off by user. You can ask them to enable it /settings."}
|
|
@@ -581,6 +590,7 @@ var getTruncatedHistory = (history, exchangesToRemove = 4) => {
|
|
|
581
590
|
|
|
582
591
|
// src/utils/usage.js
|
|
583
592
|
import fs4 from "fs-extra";
|
|
593
|
+
import path5 from "path";
|
|
584
594
|
var getDailyUsage = async () => {
|
|
585
595
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
586
596
|
try {
|
|
@@ -594,6 +604,7 @@ var getDailyUsage = async () => {
|
|
|
594
604
|
console.error("Failed to read usage:", err);
|
|
595
605
|
}
|
|
596
606
|
const defaultStats = { agent: 0, background: 0, search: 0 };
|
|
607
|
+
await fs4.ensureDir(path5.dirname(USAGE_FILE));
|
|
597
608
|
await fs4.writeJson(USAGE_FILE, { date: today, stats: defaultStats }, { spaces: 2 });
|
|
598
609
|
return defaultStats;
|
|
599
610
|
};
|
|
@@ -606,6 +617,7 @@ var incrementUsage = async (key) => {
|
|
|
606
617
|
}
|
|
607
618
|
if (data.stats[key] !== void 0) {
|
|
608
619
|
data.stats[key]++;
|
|
620
|
+
await fs4.ensureDir(path5.dirname(USAGE_FILE));
|
|
609
621
|
await fs4.writeJson(USAGE_FILE, data, { spaces: 2 });
|
|
610
622
|
}
|
|
611
623
|
};
|
|
@@ -656,7 +668,7 @@ var parseArgs = (argsString) => {
|
|
|
656
668
|
|
|
657
669
|
// src/tools/web_search.js
|
|
658
670
|
import fs5 from "fs";
|
|
659
|
-
import
|
|
671
|
+
import path6 from "path";
|
|
660
672
|
var web_search = async (argsString) => {
|
|
661
673
|
const { query, limit = 10 } = parseArgs(argsString);
|
|
662
674
|
if (!query) return 'ERROR: Missing "query" argument for web_search.';
|
|
@@ -684,11 +696,11 @@ Source: ${url}
|
|
|
684
696
|
Snippet: ${snippet}`);
|
|
685
697
|
count++;
|
|
686
698
|
}
|
|
687
|
-
const toolLogDir =
|
|
699
|
+
const toolLogDir = path6.join(LOGS_DIR, "tools");
|
|
688
700
|
if (!fs5.existsSync(toolLogDir)) {
|
|
689
701
|
fs5.mkdirSync(toolLogDir, { recursive: true });
|
|
690
702
|
}
|
|
691
|
-
fs5.appendFileSync(
|
|
703
|
+
fs5.appendFileSync(path6.join(toolLogDir, "search-results.log"), `RESULTS ${(/* @__PURE__ */ new Date()).toISOString()} -
|
|
692
704
|
Query: [${query}]. Results Count: ${results.length}.
|
|
693
705
|
Results: ${results}
|
|
694
706
|
|
|
@@ -696,11 +708,11 @@ Results: ${results}
|
|
|
696
708
|
`);
|
|
697
709
|
if (results.length === 0) {
|
|
698
710
|
if (html.includes("anomaly")) {
|
|
699
|
-
const toolErrDir =
|
|
711
|
+
const toolErrDir = path6.join(LOGS_DIR, "tools");
|
|
700
712
|
if (!fs5.existsSync(toolErrDir)) {
|
|
701
713
|
fs5.mkdirSync(toolErrDir, { recursive: true });
|
|
702
714
|
}
|
|
703
|
-
fs5.appendFileSync(
|
|
715
|
+
fs5.appendFileSync(path6.join(toolErrDir, "error.log"), `ERROR ${(/* @__PURE__ */ new Date()).toISOString()} - DDG detected unusual activity. Cuimp impersonation might need adjustment.
|
|
704
716
|
`);
|
|
705
717
|
throw new Error("DDG detected unusual activity. Cuimp impersonation might need adjustment.");
|
|
706
718
|
}
|
|
@@ -717,7 +729,7 @@ ${finalResults}`;
|
|
|
717
729
|
|
|
718
730
|
// src/tools/web_scrape.js
|
|
719
731
|
import fs6 from "fs";
|
|
720
|
-
import
|
|
732
|
+
import path7 from "path";
|
|
721
733
|
import * as cuimp2 from "cuimp";
|
|
722
734
|
var web_scrape = async (args) => {
|
|
723
735
|
const urlMatch = args.match(/url\s*=\s*["'](.*)["']/);
|
|
@@ -739,11 +751,11 @@ var web_scrape = async (args) => {
|
|
|
739
751
|
html = html.replace(/<header\b[^<]*(?:(?!<\/header>)<[^<]*)*<\/header>/gi, "");
|
|
740
752
|
let text = html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
741
753
|
const finalContent = text.substring(0, 2e4);
|
|
742
|
-
const toolLogDir =
|
|
754
|
+
const toolLogDir = path7.join(LOGS_DIR, "tools");
|
|
743
755
|
if (!fs6.existsSync(toolLogDir)) {
|
|
744
756
|
fs6.mkdirSync(toolLogDir, { recursive: true });
|
|
745
757
|
}
|
|
746
|
-
fs6.appendFileSync(
|
|
758
|
+
fs6.appendFileSync(path7.join(toolLogDir, "search-scraped.log"), `RESULTS ${(/* @__PURE__ */ new Date()).toISOString()} -
|
|
747
759
|
Query: [${url}].
|
|
748
760
|
Results: ${finalContent}
|
|
749
761
|
|
|
@@ -879,10 +891,10 @@ var summary = async (rawArgs, context = {}) => {
|
|
|
879
891
|
|
|
880
892
|
// src/tools/list_files.js
|
|
881
893
|
import fs7 from "fs";
|
|
882
|
-
import
|
|
894
|
+
import path8 from "path";
|
|
883
895
|
var list_files = async (args) => {
|
|
884
896
|
const { path: targetPath = "." } = parseArgs(args);
|
|
885
|
-
const absolutePath =
|
|
897
|
+
const absolutePath = path8.resolve(process.cwd(), targetPath);
|
|
886
898
|
try {
|
|
887
899
|
if (!fs7.existsSync(absolutePath)) {
|
|
888
900
|
return `ERROR: Path [${targetPath}] does not exist.`;
|
|
@@ -899,7 +911,7 @@ var list_files = async (args) => {
|
|
|
899
911
|
const maxDisplay = 100;
|
|
900
912
|
const displayFiles = files2.slice(0, maxDisplay);
|
|
901
913
|
const list = displayFiles.map((file) => {
|
|
902
|
-
const fPath =
|
|
914
|
+
const fPath = path8.join(absolutePath, file);
|
|
903
915
|
let indicator = "\u{1F4C4}";
|
|
904
916
|
let metaPart = "";
|
|
905
917
|
try {
|
|
@@ -934,11 +946,11 @@ ${list}${footer}`;
|
|
|
934
946
|
|
|
935
947
|
// src/tools/view_file.js
|
|
936
948
|
import fs8 from "fs";
|
|
937
|
-
import
|
|
949
|
+
import path9 from "path";
|
|
938
950
|
var view_file = async (args) => {
|
|
939
951
|
const { path: targetPath, start_line = 1, end_line = 500 } = parseArgs(args);
|
|
940
952
|
if (!targetPath) return 'ERROR: Missing "path" argument for view_file.';
|
|
941
|
-
const absolutePath =
|
|
953
|
+
const absolutePath = path9.resolve(process.cwd(), targetPath);
|
|
942
954
|
try {
|
|
943
955
|
if (!fs8.existsSync(absolutePath)) {
|
|
944
956
|
return `ERROR: File [${targetPath}] does not exist.`;
|
|
@@ -965,14 +977,14 @@ ${code}`;
|
|
|
965
977
|
|
|
966
978
|
// src/tools/write_file.js
|
|
967
979
|
import fs9 from "fs";
|
|
968
|
-
import
|
|
980
|
+
import path10 from "path";
|
|
969
981
|
var write_file = async (args) => {
|
|
970
982
|
let { path: targetPath, content } = parseArgs(args);
|
|
971
983
|
if (!targetPath) return 'ERROR: Missing "path" argument for write_file.';
|
|
972
984
|
if (content === void 0) return 'ERROR: Missing "content" argument for write_file.';
|
|
973
985
|
content = content.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").trim();
|
|
974
|
-
const absolutePath =
|
|
975
|
-
const parentDir =
|
|
986
|
+
const absolutePath = path10.resolve(process.cwd(), targetPath);
|
|
987
|
+
const parentDir = path10.dirname(absolutePath);
|
|
976
988
|
try {
|
|
977
989
|
if (!fs9.existsSync(parentDir)) {
|
|
978
990
|
fs9.mkdirSync(parentDir, { recursive: true });
|
|
@@ -1013,7 +1025,7 @@ ${snippet}`;
|
|
|
1013
1025
|
|
|
1014
1026
|
// src/tools/update_file.js
|
|
1015
1027
|
import fs10 from "fs";
|
|
1016
|
-
import
|
|
1028
|
+
import path11 from "path";
|
|
1017
1029
|
var update_file = async (args) => {
|
|
1018
1030
|
let { path: targetPath, content_to_replace, content_to_add } = parseArgs(args);
|
|
1019
1031
|
if (!targetPath) return 'ERROR: Missing "path" argument for update_file.';
|
|
@@ -1022,7 +1034,7 @@ var update_file = async (args) => {
|
|
|
1022
1034
|
const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").trim();
|
|
1023
1035
|
content_to_replace = strip(content_to_replace);
|
|
1024
1036
|
content_to_add = strip(content_to_add);
|
|
1025
|
-
const absolutePath =
|
|
1037
|
+
const absolutePath = path11.resolve(process.cwd(), targetPath);
|
|
1026
1038
|
try {
|
|
1027
1039
|
if (!fs10.existsSync(absolutePath)) {
|
|
1028
1040
|
return `ERROR: File [${targetPath}] does not exist. Use write_file instead.`;
|
|
@@ -1115,10 +1127,10 @@ ${finalOutput}`);
|
|
|
1115
1127
|
|
|
1116
1128
|
// src/tools/read_folder.js
|
|
1117
1129
|
import fs11 from "fs";
|
|
1118
|
-
import
|
|
1130
|
+
import path12 from "path";
|
|
1119
1131
|
var read_folder = async (args) => {
|
|
1120
1132
|
const { path: targetPath = "." } = parseArgs(args);
|
|
1121
|
-
const absolutePath =
|
|
1133
|
+
const absolutePath = path12.resolve(process.cwd(), targetPath);
|
|
1122
1134
|
try {
|
|
1123
1135
|
if (!fs11.existsSync(absolutePath)) {
|
|
1124
1136
|
return `ERROR: Path [${targetPath}] does not exist.`;
|
|
@@ -1132,7 +1144,7 @@ var read_folder = async (args) => {
|
|
|
1132
1144
|
const displayItems = files.slice(0, maxDisplay);
|
|
1133
1145
|
const folderData = [];
|
|
1134
1146
|
for (const file of displayItems) {
|
|
1135
|
-
const fPath =
|
|
1147
|
+
const fPath = path12.join(absolutePath, file);
|
|
1136
1148
|
let indicator = "\u{1F4C4}";
|
|
1137
1149
|
let info = { name: file, type: "unknown", size: "N/A", mtime: "N/A" };
|
|
1138
1150
|
try {
|
|
@@ -1202,7 +1214,7 @@ var dispatchTool = async (toolName, args, context = {}) => {
|
|
|
1202
1214
|
};
|
|
1203
1215
|
|
|
1204
1216
|
// src/utils/ai.js
|
|
1205
|
-
import
|
|
1217
|
+
import path13 from "path";
|
|
1206
1218
|
import fs12 from "fs";
|
|
1207
1219
|
var client = null;
|
|
1208
1220
|
var TERMINATION_SIGNAL = false;
|
|
@@ -1317,11 +1329,11 @@ USER_PROMPT: ${agentText}`.trim();
|
|
|
1317
1329
|
} catch (err) {
|
|
1318
1330
|
const errMsg = err.message || String(err);
|
|
1319
1331
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
|
|
1320
|
-
const agentErrDir =
|
|
1332
|
+
const agentErrDir = path13.join(LOGS_DIR, "agent");
|
|
1321
1333
|
if (!fs12.existsSync(agentErrDir)) {
|
|
1322
1334
|
fs12.mkdirSync(agentErrDir, { recursive: true });
|
|
1323
1335
|
}
|
|
1324
|
-
fs12.appendFileSync(
|
|
1336
|
+
fs12.appendFileSync(path13.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errMsg}
|
|
1325
1337
|
`);
|
|
1326
1338
|
const isRetryable = errMsg.includes("429") || errMsg.includes("503") || errMsg.includes("overloaded") || errMsg.includes("deadline");
|
|
1327
1339
|
if (isRetryable && retryCount < MAX_RETRIES) {
|
|
@@ -1370,7 +1382,7 @@ USER_PROMPT: ${agentText}`.trim();
|
|
|
1370
1382
|
const { path: targetPath2, start_line = 1, end_line = 500 } = parseArgs(toolCall.args);
|
|
1371
1383
|
let totalLines = "...";
|
|
1372
1384
|
try {
|
|
1373
|
-
const absPath =
|
|
1385
|
+
const absPath = path13.resolve(process.cwd(), targetPath2);
|
|
1374
1386
|
if (fs12.existsSync(absPath)) {
|
|
1375
1387
|
const content = fs12.readFileSync(absPath, "utf8");
|
|
1376
1388
|
totalLines = content.split("\n").length;
|
|
@@ -1418,7 +1430,7 @@ ${boxBottom}
|
|
|
1418
1430
|
/\/usr\//
|
|
1419
1431
|
// Sensitive Linux paths
|
|
1420
1432
|
];
|
|
1421
|
-
const currentDrive =
|
|
1433
|
+
const currentDrive = path13.resolve(process.cwd()).substring(0, 3).toLowerCase();
|
|
1422
1434
|
const isViolating = riskyPatterns.some((pattern) => {
|
|
1423
1435
|
if (pattern.source === "[a-zA-Z]:[\\\\\\/]") {
|
|
1424
1436
|
const driveMatch = command.match(/[a-zA-Z]:[\\\/]/i);
|
|
@@ -1440,8 +1452,8 @@ ${boxBottom}
|
|
|
1440
1452
|
const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
|
|
1441
1453
|
if (targetPath) {
|
|
1442
1454
|
const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
|
|
1443
|
-
const absoluteTarget =
|
|
1444
|
-
const absoluteCwd =
|
|
1455
|
+
const absoluteTarget = path13.resolve(targetPath);
|
|
1456
|
+
const absoluteCwd = path13.resolve(process.cwd());
|
|
1445
1457
|
if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
|
|
1446
1458
|
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.`;
|
|
1447
1459
|
toolResults.push(`[TOOL_RESULT]: ERROR: ${denyMsg}`);
|
|
@@ -1480,11 +1492,11 @@ ${boxBottom}
|
|
|
1480
1492
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
|
|
1481
1493
|
const isErr = result.startsWith("ERROR:");
|
|
1482
1494
|
const logStatus = isErr ? result.trim() : "SUCCESS";
|
|
1483
|
-
const toolHistDir =
|
|
1495
|
+
const toolHistDir = path13.join(LOGS_DIR, "tools");
|
|
1484
1496
|
if (!fs12.existsSync(toolHistDir)) {
|
|
1485
1497
|
fs12.mkdirSync(toolHistDir, { recursive: true });
|
|
1486
1498
|
}
|
|
1487
|
-
fs12.appendFileSync(
|
|
1499
|
+
fs12.appendFileSync(path13.join(toolHistDir, "history.log"), `HISTORY [${timestamp}]: ${toolCall.toolName} [${logStatus}]
|
|
1488
1500
|
`);
|
|
1489
1501
|
} catch (logErr) {
|
|
1490
1502
|
}
|
|
@@ -1538,11 +1550,11 @@ ${boxBottom}
|
|
|
1538
1550
|
if (parts && parts[1]?.text) {
|
|
1539
1551
|
finalSynthesis = parts[1].text;
|
|
1540
1552
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
|
|
1541
|
-
const janitorLogDir =
|
|
1553
|
+
const janitorLogDir = path13.join(LOGS_DIR, "janitor");
|
|
1542
1554
|
if (!fs12.existsSync(janitorLogDir)) {
|
|
1543
1555
|
fs12.mkdirSync(janitorLogDir, { recursive: true });
|
|
1544
1556
|
}
|
|
1545
|
-
fs12.appendFileSync(
|
|
1557
|
+
fs12.appendFileSync(path13.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: ${finalSynthesis}
|
|
1546
1558
|
`);
|
|
1547
1559
|
} else if (parts && parts[0]?.text) finalSynthesis = parts[0].text;
|
|
1548
1560
|
else if (janitorResult.response && janitorResult.response.text) finalSynthesis = janitorResult.response.text();
|
|
@@ -1554,8 +1566,8 @@ ${boxBottom}
|
|
|
1554
1566
|
const toolContext = { chatId, sessionId: chatId, history };
|
|
1555
1567
|
const result = await dispatchTool(janitorToolCall.toolName, janitorToolCall.args, toolContext);
|
|
1556
1568
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
|
|
1557
|
-
const janitorLogDir =
|
|
1558
|
-
fs12.appendFileSync(
|
|
1569
|
+
const janitorLogDir = path13.join(LOGS_DIR, "janitor");
|
|
1570
|
+
fs12.appendFileSync(path13.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: RESULT [${janitorToolCall.toolName}]: ${result}
|
|
1559
1571
|
`);
|
|
1560
1572
|
if (janitorToolCall.toolName === "memory" && !janitorToolCall.args.includes("action='temp'")) {
|
|
1561
1573
|
yield { type: "memory_updated" };
|
|
@@ -1563,11 +1575,11 @@ ${boxBottom}
|
|
|
1563
1575
|
}
|
|
1564
1576
|
} catch (janitorErr) {
|
|
1565
1577
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
|
|
1566
|
-
const janitorErrDir =
|
|
1578
|
+
const janitorErrDir = path13.join(LOGS_DIR, "janitor");
|
|
1567
1579
|
if (!fs12.existsSync(janitorErrDir)) {
|
|
1568
1580
|
fs12.mkdirSync(janitorErrDir, { recursive: true });
|
|
1569
1581
|
}
|
|
1570
|
-
fs12.appendFileSync(
|
|
1582
|
+
fs12.appendFileSync(path13.join(janitorErrDir, "error.log"), `ERROR [${date}]: ${janitorErr.message}
|
|
1571
1583
|
`);
|
|
1572
1584
|
console.error("Janitor Background Tasks Failed:", janitorErr.message);
|
|
1573
1585
|
}
|
|
@@ -1595,6 +1607,7 @@ ${timestamp}`;
|
|
|
1595
1607
|
|
|
1596
1608
|
// src/utils/settings.js
|
|
1597
1609
|
import fs13 from "fs-extra";
|
|
1610
|
+
import path14 from "path";
|
|
1598
1611
|
var DEFAULT_SETTINGS = {
|
|
1599
1612
|
mode: "Flux",
|
|
1600
1613
|
thinkingLevel: "Medium",
|
|
@@ -1642,6 +1655,7 @@ var saveSettings = async (settings) => {
|
|
|
1642
1655
|
try {
|
|
1643
1656
|
const current = await loadSettings();
|
|
1644
1657
|
const updated = { ...current, ...settings };
|
|
1658
|
+
await fs13.ensureDir(path14.dirname(SETTINGS_FILE));
|
|
1645
1659
|
await fs13.writeJson(SETTINGS_FILE, updated, { spaces: 2 });
|
|
1646
1660
|
return true;
|
|
1647
1661
|
} catch (err) {
|
|
@@ -1691,8 +1705,8 @@ function ResumeModal({ onSelect, onDelete, onClose }) {
|
|
|
1691
1705
|
// src/components/MemoryModal.jsx
|
|
1692
1706
|
import React7, { useState as useState3, useEffect as useEffect2 } from "react";
|
|
1693
1707
|
import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
|
|
1694
|
-
import
|
|
1695
|
-
var MEMORIES_PATH =
|
|
1708
|
+
import path15 from "path";
|
|
1709
|
+
var MEMORIES_PATH = path15.join(process.cwd(), "secret", "memories.json");
|
|
1696
1710
|
function MemoryModal({ onClose }) {
|
|
1697
1711
|
const [memories, setMemories] = useState3([]);
|
|
1698
1712
|
const [selectedIndex, setSelectedIndex] = useState3(0);
|