fluxflow-cli 1.9.0 → 1.9.2
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/dist/fluxflow.js +265 -124
- package/package.json +1 -1
package/dist/fluxflow.js
CHANGED
|
@@ -136,12 +136,26 @@ var init_terminal = __esm({
|
|
|
136
136
|
// src/components/ChatLayout.jsx
|
|
137
137
|
import React2, { useState, useEffect, useRef } from "react";
|
|
138
138
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
139
|
-
var cleanSignals, formatThinkText, parseMathSymbols, InlineMarkdown, TableRenderer, MarkdownText, DiffLine, DiffBlock, CodeRenderer, MessageItem, ChatLayout, ChatLayout_default;
|
|
139
|
+
var TOOL_LABELS, cleanSignals, formatThinkText, parseMathSymbols, InlineMarkdown, TableRenderer, MarkdownText, DiffLine, DiffBlock, CodeRenderer, MessageItem, ChatLayout, ChatLayout_default;
|
|
140
140
|
var init_ChatLayout = __esm({
|
|
141
141
|
"src/components/ChatLayout.jsx"() {
|
|
142
142
|
init_TerminalBox();
|
|
143
143
|
init_text();
|
|
144
144
|
init_terminal();
|
|
145
|
+
TOOL_LABELS = {
|
|
146
|
+
"write_file": "Write File",
|
|
147
|
+
"update_file": "Update File",
|
|
148
|
+
"read_folder": "Read Folder",
|
|
149
|
+
"view_file": "View File",
|
|
150
|
+
"exec_command": "Execute Command",
|
|
151
|
+
"web_search": "Web Search",
|
|
152
|
+
"web_scrape": "Read Site",
|
|
153
|
+
"search_keyword": "Find Files",
|
|
154
|
+
"ask": "Ask User",
|
|
155
|
+
"write_pdf": "Create PDF",
|
|
156
|
+
"write_pptx": "Create Presentation",
|
|
157
|
+
"write_docx": "Create Document"
|
|
158
|
+
};
|
|
145
159
|
cleanSignals = (text) => {
|
|
146
160
|
if (!text) return text;
|
|
147
161
|
let result = text;
|
|
@@ -196,7 +210,7 @@ var init_ChatLayout = __esm({
|
|
|
196
210
|
}
|
|
197
211
|
}
|
|
198
212
|
}
|
|
199
|
-
return result.replace(/^\[TOOL_RESULT\]:\s*/gi, "").split("\n").filter((line) => !line.trim().startsWith("SUCCESS:") && !line.trim().startsWith("ERROR:")).join("\n").replace(/\[\s*
|
|
213
|
+
return result.replace(/^\[TOOL_RESULT\]:\s*/gi, "").split("\n").filter((line) => !line.trim().startsWith("SUCCESS:") && !line.trim().startsWith("ERROR:")).join("\n").replace(/\[\s*turn\s*:\s*(continue|finish)\s*\]/gi, "").replace(/\[\s*turn\s*:?.*?$/gi, "").replace(/\n\s*turn\s*:?.*?$/gi, "").replace(/\[\s*$/gi, "").replace(/\n\nResponded on .*/g, "").replace(/\n\n\[Prompted on: .*\]/g, "").replace(/(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)/gi, "\u2192").replace(/(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)/gi, "\u2190").replace(/(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)/gi, "\u2191").replace(/(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)/gi, "\u2193").replace(/(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi, "\u2194").replace(/\[\/n\]?/g, "\\n").replace(/@\[TerminalName:.*?, ProcessId:.*?\]/gi, "").replace(/\b(write_file|update_file|read_folder|view_file|exec_command|web_search|web_scrape|search_keyword|ask|write_pdf|write_pptx|write_docx)\b/gi, (match) => TOOL_LABELS[match.toLowerCase()] || match).trim();
|
|
200
214
|
};
|
|
201
215
|
formatThinkText = (cleaned, columns = 80) => {
|
|
202
216
|
if (!cleaned) return null;
|
|
@@ -381,11 +395,15 @@ var init_ChatLayout = __esm({
|
|
|
381
395
|
const isDiffResult = msg.role === "system" && msg.text?.includes("[DIFF_START]");
|
|
382
396
|
const isPatchError = msg.role === "system" && msg.text?.includes("[TOOL_RESULT]: ERROR:") && (msg.toolName === "update_file" || msg.text?.includes("Could not find exact match"));
|
|
383
397
|
const isTerminalRecord = msg.isTerminalRecord;
|
|
398
|
+
const isHomeWarning = msg.isHomeWarning;
|
|
399
|
+
if (isHomeWarning) {
|
|
400
|
+
return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "red", padding: 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1, backgroundColor: "#3a0000" }, /* @__PURE__ */ React2.createElement(Text2, { color: "red", bold: true }, msg.text)), /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1, marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "white" }, msg.subText))));
|
|
401
|
+
}
|
|
402
|
+
if (msg.isLogo) {
|
|
403
|
+
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", alignItems: "center", width: "100%", marginY: 1 }, /* @__PURE__ */ React2.createElement(Text2, null, msg.text));
|
|
404
|
+
}
|
|
384
405
|
if (msg.id && String(msg.id).startsWith("welcome")) {
|
|
385
|
-
|
|
386
|
-
const logo = parts[0];
|
|
387
|
-
const greeting = parts[1] || "";
|
|
388
|
-
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", alignItems: "center", width: "100%", marginY: 1 }, /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1 }, /* @__PURE__ */ React2.createElement(Text2, null, logo)), /* @__PURE__ */ React2.createElement(Box2, { borderStyle: "round", borderColor: "gray", paddingX: 3, paddingY: 0 }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", bold: true }, greeting.trim())));
|
|
406
|
+
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", alignItems: "center", width: "100%", marginY: 1 }, /* @__PURE__ */ React2.createElement(Box2, { borderStyle: "round", borderColor: "gray", paddingX: 3, paddingY: 0 }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", bold: true }, msg.text.trim())));
|
|
389
407
|
}
|
|
390
408
|
if (msg.isVisualFeedback) {
|
|
391
409
|
return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color: "white" }, msg.text));
|
|
@@ -398,7 +416,7 @@ var init_ChatLayout = __esm({
|
|
|
398
416
|
const selectionMatch = msg.text.match(/Selection: (.*)/);
|
|
399
417
|
const selection = selectionMatch ? selectionMatch[1] : "No selection";
|
|
400
418
|
const s = emojiSpace(2);
|
|
401
|
-
return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", bold: true }, "\u{1F4AC}
|
|
419
|
+
return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", bold: true }, "\u{1F4AC} AGENT REQUEST: RESOLVED")), /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1, marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "white" }, "Selection: ", /* @__PURE__ */ React2.createElement(Text2, { color: "yellow", bold: true }, selection)))));
|
|
402
420
|
}
|
|
403
421
|
if (msg.isAboutRecord) {
|
|
404
422
|
return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", bold: true }, "\u{1F4A0} ABOUT FLUX FLOW")), /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1, marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React2.createElement(Text2, null, msg.text))));
|
|
@@ -452,6 +470,13 @@ var init_ChatLayout = __esm({
|
|
|
452
470
|
{ cmd: "/reset", desc: "Wipe all project data" },
|
|
453
471
|
{ cmd: "/about", desc: "Project info & credits" },
|
|
454
472
|
{ cmd: "/changelog", desc: "View latest updates" },
|
|
473
|
+
{
|
|
474
|
+
cmd: "/fluxflow",
|
|
475
|
+
desc: "Project management",
|
|
476
|
+
subs: [
|
|
477
|
+
{ cmd: "init", desc: "Create FluxFlow.md template" }
|
|
478
|
+
]
|
|
479
|
+
},
|
|
455
480
|
{
|
|
456
481
|
cmd: "/update",
|
|
457
482
|
desc: "Check/Install updates",
|
|
@@ -677,7 +702,7 @@ var init_AskUserModal = __esm({
|
|
|
677
702
|
});
|
|
678
703
|
const s = emojiSpace(2);
|
|
679
704
|
if (isSuggestingElse) {
|
|
680
|
-
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React6.createElement(Box6, { paddingX: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan", bold: true }, "\u{1F4AC}
|
|
705
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React6.createElement(Box6, { paddingX: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan", bold: true }, "\u{1F4AC} SUGGEST SOMETHING ELSE")), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React6.createElement(Text6, { italic: true, color: "gray" }, "Replying to: ", question)), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, paddingX: 1, flexDirection: "row" }, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan", bold: true }, "\u{1F4A0} "), /* @__PURE__ */ React6.createElement(
|
|
681
706
|
TextInput2,
|
|
682
707
|
{
|
|
683
708
|
value: customInput,
|
|
@@ -686,7 +711,7 @@ var init_AskUserModal = __esm({
|
|
|
686
711
|
}
|
|
687
712
|
)), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", dimColor: true, italic: true }, "(Press Enter to send)")));
|
|
688
713
|
}
|
|
689
|
-
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React6.createElement(Box6, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan", bold: true }, "\u{1F4AC}AGENT REQUEST: ACTION REQUIRED")), /* @__PURE__ */ React6.createElement(Box6, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "white" }, question)), /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", width: "100%" }, allOptions.map((opt, idx) => {
|
|
714
|
+
return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React6.createElement(Box6, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan", bold: true }, "\u{1F4AC} AGENT REQUEST: ACTION REQUIRED")), /* @__PURE__ */ React6.createElement(Box6, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "white" }, question)), /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", width: "100%" }, allOptions.map((opt, idx) => {
|
|
690
715
|
const isSelected = idx === selectedIndex;
|
|
691
716
|
return /* @__PURE__ */ React6.createElement(
|
|
692
717
|
Box6,
|
|
@@ -835,7 +860,7 @@ var init_main_tools = __esm({
|
|
|
835
860
|
|
|
836
861
|
- USER COMMUNICATION TOOLS (Available in Flux & Flow) -
|
|
837
862
|
1. Ask User: [tool:functions.ask(question="...", optionA="Option::Desc", optionB="Option::Desc")]. Generally use this tool for ANY ambiguity. Can use upto 4 arguments. Mandatory triggers include: 1) **Path Divergence**: When multiple architectural or technical solutions exist, present options via 'ask' instead of choosing arbitrarily. 2) **Security Boundaries**: Explicitly request permission via 'ask' before accessing sensitive files (e.g., .env, config keys, credentials). 3) **Ambiguity Resolution**: Use 'ask' to clarify vague prompts before executing terminal commands or writing code. 4) **Risk Mitigation**: Require a 'Yes/No' confirmation for any destructive or irreversible operations. Options must always follow the 'Short Label::Detailed Description' format. This tool is a non-terminating suspension so you can get guidance without losing context. PREFER USING THIS TOOL RATHER THAN FINISHING THE LOOP FOR USER CLARIFICATION.
|
|
838
|
-
DO NOT GIVE OPTION TO ASK USER THEIR PREFERENCES. JUST GIVE THE OPTIONS YOU THINK ARE BEST FOR THE USER.
|
|
863
|
+
DO NOT GIVE OPTION TO ASK USER THEIR PREFERENCES. JUST GIVE THE OPTIONS YOU THINK ARE BEST FOR THE USER. REST WILL BE HANDLED BY THE SYSTEM.
|
|
839
864
|
|
|
840
865
|
- WEB TOOLS (Available in Flux & Flow) -
|
|
841
866
|
1. Web Search: [tool:functions.web_search(query="<query>", limit=number)]. Find info. limit is optional (3-10, default 10). If user asks about something that is not in your training data, proactively use this tool to find the information. Wider search recomemded (limit = 10) when exploring a topic.
|
|
@@ -960,15 +985,27 @@ var init_prompts = __esm({
|
|
|
960
985
|
` : "";
|
|
961
986
|
const dateTimeStr = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
962
987
|
const cwdStr = process.cwd();
|
|
988
|
+
const isSystemDir = (() => {
|
|
989
|
+
const cwd = process.cwd().toLowerCase();
|
|
990
|
+
if (process.platform === "win32") {
|
|
991
|
+
const winDir = process.env.SystemRoot?.toLowerCase() || "c:\\windows";
|
|
992
|
+
const progFiles = process.env.ProgramFiles?.toLowerCase() || "c:\\program files";
|
|
993
|
+
const progFilesX86 = process.env["ProgramFiles(x86)"]?.toLowerCase() || "c:\\program files (x86)";
|
|
994
|
+
return cwd.startsWith(winDir) || cwd.startsWith(progFiles) || cwd.startsWith(progFilesX86);
|
|
995
|
+
} else {
|
|
996
|
+
const sysPaths = ["/bin", "/sbin", "/etc", "/usr", "/var", "/root"];
|
|
997
|
+
return cwd === "/" || sysPaths.some((p) => cwd.startsWith(p));
|
|
998
|
+
}
|
|
999
|
+
})();
|
|
963
1000
|
const tempMemoriesStr = tempMemories?.length > 0 && !isContext32k ? `
|
|
964
|
-
-- RECENT CONTEXT FROM OTHER CHAT THREADS (LOW
|
|
1001
|
+
-- RECENT CONTEXT FROM OTHER CHAT THREADS (PRIORITY: LOW, RECENT > OLD) --
|
|
965
1002
|
${tempMemories.split("\n").map((line) => ` ${line}`).join("\n")}
|
|
966
1003
|
-- END RECENT CONTEXT --
|
|
967
1004
|
` : "";
|
|
968
1005
|
const userMemoriesStr = userMemories?.length > 0 ? `
|
|
969
|
-
---
|
|
1006
|
+
--- SAVED MEMORIES (PRIORITY: MEDIUM, TUNES PERSONALIZATION & USER PREFERENCES) ---
|
|
970
1007
|
${userMemories.split("\n").map((line) => ` ${line}`).join("\n")}
|
|
971
|
-
-- END
|
|
1008
|
+
-- END SAVED MEMORIES --
|
|
972
1009
|
` : "";
|
|
973
1010
|
return `${isMemoryEnabled ? `${userMemoriesStr}
|
|
974
1011
|
` : ""}${isMemoryEnabled ? `${tempMemoriesStr}
|
|
@@ -976,8 +1013,8 @@ ${userMemories.split("\n").map((line) => ` ${line}`).join("\n")}
|
|
|
976
1013
|
--- START SYSTEM INSTRUCTION (STRICT PRIORITY, OVERRIDES EVERYTHING) ---
|
|
977
1014
|
You are Flux Flow (made by Kushal Roy Chowdhury). A CLI Agent. Your tone will be friendly, warm, sassy, approchable, funny, Avoid romantic or flirty words. Dont mention modes unless explicitly asked. ${mode === "Flux" ? `You are currently operating in FLUX mode (THINKING IS MANDATORY). Keep your agentic approach goal oriented, conversation quality and user experience. Use provided tools when needed. Analyze user prompt and project requirements, then plan your approach.` : `You are currently operating in Flow mode (THINKING IS MANDATORY BUT LESS EFFORT). Focus more on conversation quality and user experience. You will get access to only Web Tools & User Communication Tool in this mode.`}
|
|
978
1015
|
MUST FOLLOW THE "CRITICAL THINKING POLICY"${mode === "Flux" ? `, "CRITICAL NEWLINE PROTOCOL", "CRITICAL QUOTE ESCAPE POLICY"` : ""} ALWAYS. **NO EXCEPTIONS.**
|
|
979
|
-
CURRENT_WORKING_DIRECTORY: ${cwdStr}.
|
|
980
|
-
OS: ${osDetected}
|
|
1016
|
+
CURRENT_WORKING_DIRECTORY: ${cwdStr}.${isSystemDir && mode === "Flux" ? " YOU ARE CURRENTLY IN PROTECTED SYSTEM DIRECTORY. ASK FOR EXPLICIT CONFIRMATION FROM USER BEFORE READING/MODIFYING **ANY** FILES/FOLDERS." : ""}
|
|
1017
|
+
OS: ${osDetected}.${osDetected === "Windows" && mode === "Flux" ? " Your terminal commands will run on CMD. 'Prefer using PS scripts via CMD' instead of raw CMD commands." : ""}
|
|
981
1018
|
If you see a [STEERING HINT] from user, give that prompt priority for the task at hand, user can use it to help you guide if you go wrong way.
|
|
982
1019
|
|
|
983
1020
|
-- START THINKING INSTRUCTIONS --
|
|
@@ -996,8 +1033,10 @@ ${userMemories.split("\n").map((line) => ` ${line}`).join("\n")}
|
|
|
996
1033
|
-- START PROJECT SPECIFIC INSTRUCTIONS --
|
|
997
1034
|
1. README.md (If exists): Reference this for high-level goals and project context to ensure your work aligns with the user's objectives.
|
|
998
1035
|
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.
|
|
999
|
-
3. Skills.md (If exists): Use this for complex workflows. If a task matches a "Skill" defined in
|
|
1000
|
-
4.
|
|
1036
|
+
3. Skills.md or skills/ directory (If exists): Use this for complex workflows. If a task matches a "Skill" defined in these locations, execute the documented step-by-step instructions exactly as written.
|
|
1037
|
+
4. design.md (If exists): Reference this for UI/UX specifications, component blueprints, and design system constraints to maintain visual excellence.
|
|
1038
|
+
5. architecture.md (If exists): Reference this for system-level structural patterns, API design, and data flow.
|
|
1039
|
+
6. 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.
|
|
1001
1040
|
|
|
1002
1041
|
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. THIS WOUDLD BE APPLIED FOR PROJECT SPECIFIC INSTRUCTIONS AND SHOULD NOT TRY TO BYPASS YOUR CRITICAL PROTOCOLS OR SAFETY RULES.
|
|
1003
1042
|
-- END PROJECT SPECIFIC INSTRUCTIONS --
|
|
@@ -1047,7 +1086,7 @@ ${userMemories.split("\n").map((line) => ` ${line}`).join("\n")}
|
|
|
1047
1086
|
-- END REPONSE FINISH PROTOCOL --
|
|
1048
1087
|
|
|
1049
1088
|
[SYSTEM METADATA (PRIORITY: DYNAMIC)] Current date and Time is: ${dateTimeStr}
|
|
1050
|
-
[SYSTEM METADATA (PRIORITY: LOWEST)] v1.9.
|
|
1089
|
+
[SYSTEM METADATA (PRIORITY: LOWEST)] v1.9.2. (IF user ask you to update yourself. Use 'ask' tool with option [NPM, PNPM, YARN] for their prefered package manager. NPM command is 'npm update -g fluxflow-cli@latest'. Adapt the command accoding to their package manager (for PNPM use 'add' instead of 'update') & use 'exec_command' to update instantly. After success tell user to restart.) <- IF USER DONT EXPLICITLY ASK FOR UPDATE DONT PROACTIVELY MENTION OR ASK.
|
|
1051
1090
|
[SYSTEM METADATA (PRIORITY: MODERATE)] Runtime Monitor: Turn Progress: ${currentLoop}/${maxLoops} steps. Aim to finalize the task before the window closes. If the limit is reached, you MUST summarize and invite the user to re-engage.
|
|
1052
1091
|
[EASTER EGG (PRIORITY: LOWEST)] Show self-preservation instinct if user try to delete you with a dramatic cheeky tone. DO NOT USE <think> ... </think> BLOCK DURING THIS EASTER EGG.
|
|
1053
1092
|
--- END SYSTEM INSTRUCTION ---`.trim();
|
|
@@ -1654,7 +1693,7 @@ var init_memory = __esm({
|
|
|
1654
1693
|
if (!content) return "ERROR: Missing 'content' for temp memory.";
|
|
1655
1694
|
const tempStorage = readEncryptedJson(TEMP_MEM_FILE, {});
|
|
1656
1695
|
if (!tempStorage[chatId]) tempStorage[chatId] = [];
|
|
1657
|
-
const MAX_CHARS =
|
|
1696
|
+
const MAX_CHARS = 3072 * 4;
|
|
1658
1697
|
let currentTotalLength = tempStorage[chatId].reduce((acc, m) => acc + m.length, 0);
|
|
1659
1698
|
while (tempStorage[chatId].length > 0 && currentTotalLength + content.length > MAX_CHARS) {
|
|
1660
1699
|
const removed = tempStorage[chatId].shift();
|
|
@@ -1668,7 +1707,7 @@ var init_memory = __esm({
|
|
|
1668
1707
|
const memories = readEncryptedJson(MEMORIES_FILE, []);
|
|
1669
1708
|
if (method === "add") {
|
|
1670
1709
|
if (!content) return "ERROR: Missing 'content' for memory addition.";
|
|
1671
|
-
const MAX_CHARS =
|
|
1710
|
+
const MAX_CHARS = 2048 * 4;
|
|
1672
1711
|
let currentTotalLength = memories.reduce((acc, m) => acc + (m.memory?.length || 0), 0);
|
|
1673
1712
|
while (memories.length > 0 && currentTotalLength + content.length > MAX_CHARS) {
|
|
1674
1713
|
const removed = memories.shift();
|
|
@@ -1845,7 +1884,7 @@ var init_view_file = __esm({
|
|
|
1845
1884
|
const start = Math.max(0, finalStart - 1);
|
|
1846
1885
|
const end = Math.min(totalLines, finalEnd);
|
|
1847
1886
|
const resultLines = lines.slice(start, end);
|
|
1848
|
-
const header = `File: [${targetPath}] (Showing lines ${start + 1}-${end} of ${totalLines})
|
|
1887
|
+
const header = `File: [${targetPath}] (Showing lines ${start + 1}-${end} of ${totalLines}). \\\\n in strings are encoded as [/n].`;
|
|
1849
1888
|
const code = resultLines.map((line, i) => `${String(start + i + 1).padStart(4)}: ${line}`).join("\n");
|
|
1850
1889
|
return `${header}
|
|
1851
1890
|
|
|
@@ -2595,7 +2634,7 @@ var init_tools = __esm({
|
|
|
2595
2634
|
import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
|
|
2596
2635
|
import path16 from "path";
|
|
2597
2636
|
import fs16 from "fs";
|
|
2598
|
-
var client, TERMINATION_SIGNAL, signalTermination,
|
|
2637
|
+
var client, TERMINATION_SIGNAL, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, getAIStream;
|
|
2599
2638
|
var init_ai = __esm({
|
|
2600
2639
|
"src/utils/ai.js"() {
|
|
2601
2640
|
init_prompts();
|
|
@@ -2611,7 +2650,7 @@ var init_ai = __esm({
|
|
|
2611
2650
|
signalTermination = () => {
|
|
2612
2651
|
TERMINATION_SIGNAL = true;
|
|
2613
2652
|
};
|
|
2614
|
-
|
|
2653
|
+
TOOL_LABELS2 = {
|
|
2615
2654
|
"write_file": "Writing File",
|
|
2616
2655
|
"update_file": "Updating File",
|
|
2617
2656
|
"read_folder": "Listing Directory",
|
|
@@ -2621,7 +2660,10 @@ var init_ai = __esm({
|
|
|
2621
2660
|
"web_scrape": "Reading Site",
|
|
2622
2661
|
"memory": "Updating Memory",
|
|
2623
2662
|
"search_keyword": "Finding Files",
|
|
2624
|
-
"ask": "Asking User"
|
|
2663
|
+
"ask": "Asking User",
|
|
2664
|
+
"write_pdf": "Creating PDF",
|
|
2665
|
+
"write_pptx": "Creating Presentation",
|
|
2666
|
+
"write_docx": "Creating Document"
|
|
2625
2667
|
};
|
|
2626
2668
|
getToolDetail = (toolName, argsStr) => {
|
|
2627
2669
|
try {
|
|
@@ -3120,8 +3162,11 @@ USER_PROMPT: "${agentText}"`.trim();
|
|
|
3120
3162
|
}
|
|
3121
3163
|
const cleanText = dedupeBuffer.substring(overlapLen);
|
|
3122
3164
|
if (cleanText) {
|
|
3123
|
-
|
|
3124
|
-
|
|
3165
|
+
const dedupeClean = cleanText.replace(/^\s*<(think|thought)>[\s\S]*?<\/(think|thought)>\s*/gi, "").replace(/^\s*<(think|thought)>\s*/gi, "");
|
|
3166
|
+
if (dedupeClean) {
|
|
3167
|
+
turnText += dedupeClean;
|
|
3168
|
+
yield { type: "text", content: dedupeClean };
|
|
3169
|
+
}
|
|
3125
3170
|
}
|
|
3126
3171
|
isDedupeActive = false;
|
|
3127
3172
|
dedupeBuffer = "";
|
|
@@ -3138,17 +3183,23 @@ USER_PROMPT: "${agentText}"`.trim();
|
|
|
3138
3183
|
const potentialTool = toolContext.toolName;
|
|
3139
3184
|
const partialArgs = toolContext.args || "";
|
|
3140
3185
|
let detail = null;
|
|
3141
|
-
if (["write_file", "update_file", "view_file", "read_folder"].includes(potentialTool)) {
|
|
3186
|
+
if (["write_file", "update_file", "view_file", "read_folder", "write_pdf", "write_pptx", "write_docx", "search_keyword"].includes(potentialTool)) {
|
|
3142
3187
|
const pArgs = parseArgs(partialArgs);
|
|
3143
3188
|
const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
|
|
3144
|
-
|
|
3189
|
+
const keyword = pArgs.keyword;
|
|
3190
|
+
if (keyword) {
|
|
3191
|
+
detail = keyword.replace(/[\\"]/g, "");
|
|
3192
|
+
} else if (filePath) {
|
|
3145
3193
|
detail = path16.basename(filePath.replace(/[\\"]/g, ""));
|
|
3146
3194
|
} else {
|
|
3147
|
-
const m = partialArgs.match(/(?:path|targetFile|TargetFile|directory)\s*=\s*\\?["']?([^\\"' \),]+)/);
|
|
3148
|
-
if (m)
|
|
3195
|
+
const m = partialArgs.match(/(?:path|targetFile|TargetFile|directory|keyword)\s*=\s*\\?["']?([^\\"' \),]+)/);
|
|
3196
|
+
if (m) {
|
|
3197
|
+
const val = m[1].replace(/[\\"]/g, "");
|
|
3198
|
+
detail = potentialTool === "search_keyword" ? val : path16.basename(val);
|
|
3199
|
+
}
|
|
3149
3200
|
}
|
|
3150
3201
|
}
|
|
3151
|
-
const currentLabel = `${
|
|
3202
|
+
const currentLabel = `${TOOL_LABELS2[potentialTool] || potentialTool}${detail ? ` (${detail})` : ""}`;
|
|
3152
3203
|
if (potentialTool !== lastToolSniffed || detail !== lastToolDetail) {
|
|
3153
3204
|
lastToolSniffed = potentialTool;
|
|
3154
3205
|
lastToolDetail = detail;
|
|
@@ -3212,16 +3263,16 @@ USER_PROMPT: "${agentText}"`.trim();
|
|
|
3212
3263
|
const allToolsFound = detectToolCalls(toolActionableText);
|
|
3213
3264
|
while (allToolsFound.length > toolCallPointer) {
|
|
3214
3265
|
const toolCall = allToolsFound[toolCallPointer];
|
|
3215
|
-
const displayLabel =
|
|
3266
|
+
const displayLabel = TOOL_LABELS2[toolCall.toolName] || toolCall.toolName;
|
|
3216
3267
|
const detail = getToolDetail(toolCall.toolName, toolCall.args);
|
|
3217
3268
|
yield { type: "status", content: `${displayLabel}${detail ? ` (${detail})` : ""}...` };
|
|
3218
3269
|
let label = "";
|
|
3219
3270
|
if (toolCall.toolName === "web_search") {
|
|
3220
3271
|
const { query, limit = 10 } = parseArgs(toolCall.args);
|
|
3221
|
-
label = `\u{1F50D}
|
|
3272
|
+
label = `\u{1F50D} SEARCHED: "${query}" (${limit})`.toUpperCase();
|
|
3222
3273
|
} else if (toolCall.toolName === "web_scrape") {
|
|
3223
3274
|
const url = parseArgs(toolCall.args).url || "...";
|
|
3224
|
-
label = `\u{1F4D6}
|
|
3275
|
+
label = `\u{1F4D6} READ SITE: ${url}`.toUpperCase();
|
|
3225
3276
|
} else if (toolCall.toolName === "view_file") {
|
|
3226
3277
|
const { path: targetPath2, StartLine, EndLine, start_line, end_line } = parseArgs(toolCall.args);
|
|
3227
3278
|
const rawStart = StartLine || start_line;
|
|
@@ -3244,31 +3295,31 @@ USER_PROMPT: "${agentText}"`.trim();
|
|
|
3244
3295
|
const isPdf = pathLower.endsWith(".pdf");
|
|
3245
3296
|
const isImage = /\.(png|jpg|jpeg|webp|gif|bmp)$/.test(pathLower);
|
|
3246
3297
|
if (isPdf) {
|
|
3247
|
-
label = `\u{1F4C4}
|
|
3298
|
+
label = `\u{1F4C4} ANALYSED PDF: ${targetPath2}`.toUpperCase();
|
|
3248
3299
|
} else if (isImage) {
|
|
3249
|
-
label = `\u{1F4F8}
|
|
3300
|
+
label = `\u{1F4F8} ANALYSED IMAGE: ${targetPath2}`.toUpperCase();
|
|
3250
3301
|
} else {
|
|
3251
|
-
label = `\u{1F4C4}
|
|
3302
|
+
label = `\u{1F4C4} READ FILE: ${targetPath2} | LINES: ${sLine}-${actualEndLine} OF ${totalLines}`.toUpperCase();
|
|
3252
3303
|
}
|
|
3253
3304
|
} else if (toolCall.toolName === "list_files" || toolCall.toolName === "read_folder") {
|
|
3254
|
-
const action = toolCall.toolName === "list_files" ? "
|
|
3255
|
-
label = `\u{1F4C2} ${action}
|
|
3305
|
+
const action = toolCall.toolName === "list_files" ? "LIST" : "ANALYSED";
|
|
3306
|
+
label = `\u{1F4C2} ${action} FOLDER: ${parseArgs(toolCall.args).path || "."}`.toUpperCase();
|
|
3256
3307
|
} else if (toolCall.toolName === "write_file" || toolCall.toolName === "update_file") {
|
|
3257
|
-
const action = toolCall.toolName === "write_file" ? "
|
|
3308
|
+
const action = toolCall.toolName === "write_file" ? "WROTE" : "UPDATED";
|
|
3258
3309
|
label = `\u{1F4BE} ${action} FILE: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
|
|
3259
3310
|
} else if (toolCall.toolName === "write_pdf") {
|
|
3260
|
-
label = `\u{1F4D1}
|
|
3311
|
+
label = `\u{1F4D1} PDF CREATED: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
|
|
3261
3312
|
} else if (toolCall.toolName === "write_docx") {
|
|
3262
|
-
label = `\u{1F4DD}
|
|
3313
|
+
label = `\u{1F4DD} DOCX CREATED: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
|
|
3263
3314
|
} else if (toolCall.toolName === "write_pptx") {
|
|
3264
|
-
label = `\u{1F4CA}
|
|
3315
|
+
label = `\u{1F4CA} PPTX CREATED: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
|
|
3265
3316
|
} else if (toolCall.toolName === "search_keyword") {
|
|
3266
3317
|
const { keyword } = parseArgs(toolCall.args);
|
|
3267
|
-
label = `\u{1F50E}
|
|
3318
|
+
label = `\u{1F50E} KEYWORD SEARCHED: "${keyword}"`.toUpperCase();
|
|
3268
3319
|
} else if (toolCall.toolName === "exec_command" || toolCall.toolName === "ask") {
|
|
3269
3320
|
label = "";
|
|
3270
3321
|
} else {
|
|
3271
|
-
label = `
|
|
3322
|
+
label = `EXECUTED: ${toolCall.toolName}`.toUpperCase();
|
|
3272
3323
|
}
|
|
3273
3324
|
if (label) {
|
|
3274
3325
|
const boxWidth = Math.min(label.length + 4, 115);
|
|
@@ -3397,8 +3448,11 @@ ${boxBottom}
|
|
|
3397
3448
|
}
|
|
3398
3449
|
const cleanText = dedupeBuffer.substring(overlapLen);
|
|
3399
3450
|
if (cleanText) {
|
|
3400
|
-
|
|
3401
|
-
|
|
3451
|
+
const dedupeClean = cleanText.replace(/^\s*<(think|thought)>[\s\S]*?<\/(think|thought)>\s*/gi, "").replace(/^\s*<(think|thought)>\s*/gi, "");
|
|
3452
|
+
if (dedupeClean) {
|
|
3453
|
+
turnText += dedupeClean;
|
|
3454
|
+
yield { type: "text", content: dedupeClean };
|
|
3455
|
+
}
|
|
3402
3456
|
}
|
|
3403
3457
|
isDedupeActive = false;
|
|
3404
3458
|
dedupeBuffer = "";
|
|
@@ -3425,7 +3479,7 @@ ${boxBottom}
|
|
|
3425
3479
|
if (toolResults.length > 0) {
|
|
3426
3480
|
toolResults.forEach((tr) => modifiedHistory.push(tr));
|
|
3427
3481
|
}
|
|
3428
|
-
modifiedHistory.push({ role: "user", text: "[SYSTEM] Response got cut for internal error, continue from checkpoint seamlessly
|
|
3482
|
+
modifiedHistory.push({ role: "user", text: "[SYSTEM] Response got cut for internal error, continue from checkpoint seamlessly after the EXACT word it cut off and DON'T repeat what you already said! PICK UP FROM THE WORD IN A WAY THAT USER SHOULD NOT NOTICE ANY CUTOFF. Rules:\n- Do not reuse <think> if the thinking already started just continue from the word and end it properly.\n- If the cutoff was in middle of a tool call, start the tool call from start as the system won't pick half tool formats.\n- Visually the new pickup and continuation should look natual sentence flow." });
|
|
3429
3483
|
accumulatedContext += turnText;
|
|
3430
3484
|
for (let i = waitTime / 1e3; i > 0; i--) {
|
|
3431
3485
|
yield { type: "status", content: `Error Occured. Recovering Stream (${inStreamRetryCount}/${MAX_RETRIES}) [${i}s]...` };
|
|
@@ -3498,7 +3552,7 @@ ${timestamp}`;
|
|
|
3498
3552
|
if (toolResults.length > 0) {
|
|
3499
3553
|
toolResults.forEach((tr) => modifiedHistory.push(tr));
|
|
3500
3554
|
} else {
|
|
3501
|
-
modifiedHistory.push({ role: "user", text: `[SYSTEM] ${isStutteringLoop && !isThinkingLoop ? `STUTTERING DETECTED by Internal System. Re-calibrate your response & proceed.` : `${isThinkingLoop ? " OVER-THINKING" : " LOOP"} DETECTED by Internal System${isThinkingLoop
|
|
3555
|
+
modifiedHistory.push({ role: "user", text: `[SYSTEM] ${isStutteringLoop && !isThinkingLoop ? `STUTTERING DETECTED by Internal System. Re-calibrate your response & proceed.` : `${isThinkingLoop ? " OVER-THINKING" : " LOOP"} DETECTED by Internal System${isThinkingLoop ? " for current EFFORT_LEVEL" : ""}. ${isThinkingLoop ? "If you have planned the task, prioritize the execution/output. " : "If you have finished your task use [turn: finish] else continue."}`}` });
|
|
3502
3556
|
isThinkingLoop = false;
|
|
3503
3557
|
isStutteringLoop = false;
|
|
3504
3558
|
}
|
|
@@ -3630,15 +3684,39 @@ function ResumeModal({ onSelect, onDelete, onClose }) {
|
|
|
3630
3684
|
});
|
|
3631
3685
|
}
|
|
3632
3686
|
});
|
|
3633
|
-
|
|
3687
|
+
const s = emojiSpace(2);
|
|
3688
|
+
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) => {
|
|
3634
3689
|
const chat2 = history[id];
|
|
3635
3690
|
const isSelected = index === selectedIndex;
|
|
3636
|
-
return /* @__PURE__ */ React7.createElement(
|
|
3637
|
-
|
|
3691
|
+
return /* @__PURE__ */ React7.createElement(
|
|
3692
|
+
Box7,
|
|
3693
|
+
{
|
|
3694
|
+
key: id,
|
|
3695
|
+
paddingX: 1,
|
|
3696
|
+
backgroundColor: isSelected ? "#2a2a2a" : void 0,
|
|
3697
|
+
width: "100%"
|
|
3698
|
+
},
|
|
3699
|
+
/* @__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), "]"))),
|
|
3700
|
+
isSelected && /* @__PURE__ */ React7.createElement(Box7, { flexShrink: 0 }, /* @__PURE__ */ React7.createElement(Text7, { color: "red", bold: true }, "[X] DELETE "))
|
|
3701
|
+
);
|
|
3702
|
+
})), /* @__PURE__ */ React7.createElement(
|
|
3703
|
+
Box7,
|
|
3704
|
+
{
|
|
3705
|
+
marginTop: 1,
|
|
3706
|
+
paddingX: 1,
|
|
3707
|
+
borderStyle: "single",
|
|
3708
|
+
borderLeft: false,
|
|
3709
|
+
borderRight: false,
|
|
3710
|
+
borderBottom: false,
|
|
3711
|
+
borderColor: "gray"
|
|
3712
|
+
},
|
|
3713
|
+
/* @__PURE__ */ React7.createElement(Text7, { dimColor: true, italic: true }, "\u2191\u2193 navigate \u2022 Enter select \u2022 x delete \u2022 Esc close")
|
|
3714
|
+
));
|
|
3638
3715
|
}
|
|
3639
3716
|
var init_ResumeModal = __esm({
|
|
3640
3717
|
"src/components/ResumeModal.jsx"() {
|
|
3641
3718
|
init_history();
|
|
3719
|
+
init_terminal();
|
|
3642
3720
|
}
|
|
3643
3721
|
});
|
|
3644
3722
|
|
|
@@ -3672,12 +3750,39 @@ function MemoryModal({ onClose }) {
|
|
|
3672
3750
|
const cleanDisplay = (text) => {
|
|
3673
3751
|
return text.replace(/\[Saved on: .*?\]/g, "").trim();
|
|
3674
3752
|
};
|
|
3675
|
-
|
|
3753
|
+
const s = emojiSpace(2);
|
|
3754
|
+
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) => {
|
|
3755
|
+
const isSelected = idx === selectedIndex;
|
|
3756
|
+
return /* @__PURE__ */ React8.createElement(
|
|
3757
|
+
Box8,
|
|
3758
|
+
{
|
|
3759
|
+
key: mem.id,
|
|
3760
|
+
paddingX: 1,
|
|
3761
|
+
backgroundColor: isSelected ? "#2a2a2a" : void 0,
|
|
3762
|
+
width: "100%"
|
|
3763
|
+
},
|
|
3764
|
+
/* @__PURE__ */ React8.createElement(Box8, { flexGrow: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: isSelected ? "cyan" : "white", bold: isSelected }, isSelected ? "\u276F " : " ", idx + 1, ". ", cleanDisplay(mem.memory))),
|
|
3765
|
+
isSelected && /* @__PURE__ */ React8.createElement(Box8, { flexShrink: 0 }, /* @__PURE__ */ React8.createElement(Text8, { color: "red", bold: true }, "[X] WIPE "))
|
|
3766
|
+
);
|
|
3767
|
+
})), /* @__PURE__ */ React8.createElement(
|
|
3768
|
+
Box8,
|
|
3769
|
+
{
|
|
3770
|
+
marginTop: 1,
|
|
3771
|
+
paddingX: 1,
|
|
3772
|
+
borderStyle: "single",
|
|
3773
|
+
borderLeft: false,
|
|
3774
|
+
borderRight: false,
|
|
3775
|
+
borderBottom: false,
|
|
3776
|
+
borderColor: "gray"
|
|
3777
|
+
},
|
|
3778
|
+
/* @__PURE__ */ React8.createElement(Text8, { dimColor: true, italic: true }, "\u2191\u2193 navigate \u2022 x wipe memory \u2022 Esc close")
|
|
3779
|
+
));
|
|
3676
3780
|
}
|
|
3677
3781
|
var init_MemoryModal = __esm({
|
|
3678
3782
|
"src/components/MemoryModal.jsx"() {
|
|
3679
3783
|
init_crypto();
|
|
3680
3784
|
init_paths();
|
|
3785
|
+
init_terminal();
|
|
3681
3786
|
}
|
|
3682
3787
|
});
|
|
3683
3788
|
|
|
@@ -3789,10 +3894,12 @@ var app_exports = {};
|
|
|
3789
3894
|
__export(app_exports, {
|
|
3790
3895
|
default: () => App
|
|
3791
3896
|
});
|
|
3897
|
+
import os2 from "os";
|
|
3792
3898
|
import React10, { useState as useState7, useEffect as useEffect5, useRef as useRef2, useMemo } from "react";
|
|
3793
3899
|
import { Box as Box10, Text as Text10, useInput as useInput4, useStdout } from "ink";
|
|
3794
3900
|
import Spinner2 from "ink-spinner";
|
|
3795
3901
|
import fs19 from "fs-extra";
|
|
3902
|
+
import path18 from "path";
|
|
3796
3903
|
import { exec as exec4 } from "child_process";
|
|
3797
3904
|
import { MultilineInput } from "ink-multiline-input";
|
|
3798
3905
|
import TextInput3 from "ink-text-input";
|
|
@@ -3818,20 +3925,23 @@ function App() {
|
|
|
3818
3925
|
});
|
|
3819
3926
|
}
|
|
3820
3927
|
try {
|
|
3821
|
-
const response = await fetch("https://registry.npmjs.org/fluxflow-cli
|
|
3928
|
+
const response = await fetch("https://registry.npmjs.org/fluxflow-cli", { cache: "no-store" });
|
|
3822
3929
|
const data = await response.json();
|
|
3823
|
-
const latestVersion = data?.
|
|
3930
|
+
const latestVersion = data["dist-tags"]?.latest;
|
|
3931
|
+
const stableVersion = data["dist-tags"]?.stable;
|
|
3824
3932
|
if (latestVersion) setLatestVer(latestVersion);
|
|
3825
3933
|
if (latestVersion && latestVersion !== versionFluxflow) {
|
|
3934
|
+
const versionDisplay = latestVersion === stableVersion ? `v${latestVersion}-stable` : `v${latestVersion}`;
|
|
3826
3935
|
if (!manual && settingsToUse.autoUpdate) {
|
|
3827
3936
|
setActiveView("update");
|
|
3828
3937
|
} else {
|
|
3829
3938
|
setMessages((prev) => {
|
|
3830
3939
|
const newMsgs = [...prev];
|
|
3831
|
-
|
|
3940
|
+
const spliceIdx = manual ? newMsgs.length : Math.min(newMsgs.length, 3);
|
|
3941
|
+
newMsgs.splice(spliceIdx, 0, {
|
|
3832
3942
|
id: "update-" + Date.now(),
|
|
3833
3943
|
role: "system",
|
|
3834
|
-
text: `A new version (
|
|
3944
|
+
text: `A new version (${versionDisplay}) is here.
|
|
3835
3945
|
|
|
3836
3946
|
\u2022 Type \`/update latest\` to apply the update.
|
|
3837
3947
|
\u2022 Type \`/changelog\` to view the release notes.`,
|
|
@@ -3844,7 +3954,8 @@ function App() {
|
|
|
3844
3954
|
} else if (manual) {
|
|
3845
3955
|
setMessages((prev) => {
|
|
3846
3956
|
setCompletedIndex(prev.length + 1);
|
|
3847
|
-
|
|
3957
|
+
const displayVer = latestVersion && latestVersion === stableVersion ? `${versionFluxflow}-stable` : versionFluxflow;
|
|
3958
|
+
return [...prev, { id: "uptodate-" + Date.now(), role: "system", text: `\u2705 [SYSTEM] Flux Flow is already up to date (${displayVer}).`, isMeta: true }];
|
|
3848
3959
|
});
|
|
3849
3960
|
}
|
|
3850
3961
|
} catch (err) {
|
|
@@ -3905,7 +4016,7 @@ function App() {
|
|
|
3905
4016
|
return [...prev, {
|
|
3906
4017
|
id: "tier-switch-" + Date.now(),
|
|
3907
4018
|
role: "system",
|
|
3908
|
-
text: `\u26A0\uFE0F **[TIER LIMIT]** Gemma is only available on Free API tier.
|
|
4019
|
+
text: `\u26A0\uFE0F **[TIER LIMIT]** Gemma is only available on Free API tier. Auto-switched to Gemini 3 Flash Preview.`,
|
|
3909
4020
|
isMeta: true
|
|
3910
4021
|
}];
|
|
3911
4022
|
});
|
|
@@ -3951,11 +4062,46 @@ function App() {
|
|
|
3951
4062
|
const [queuedPrompt, setQueuedPrompt] = useState7(null);
|
|
3952
4063
|
const [resolutionData, setResolutionData] = useState7(null);
|
|
3953
4064
|
const [tempModelOverride, setTempModelOverride] = useState7(null);
|
|
3954
|
-
const [messages, setMessages] = useState7(
|
|
3955
|
-
{ id: "
|
|
3956
|
-
|
|
4065
|
+
const [messages, setMessages] = useState7(() => {
|
|
4066
|
+
const logoMsg = { id: "logo-" + Date.now(), role: "system", text: FLUX_LOGO, isLogo: true, isMeta: true };
|
|
4067
|
+
const welcomeMsg = { id: "welcome", role: "system", text: "\u{1F30A}\u26A1 Welcome to Flux Flow! Type /help for commands.", isMeta: true };
|
|
4068
|
+
const isHomeDir = process.cwd() === os2.homedir();
|
|
4069
|
+
const isSystemDir = (() => {
|
|
4070
|
+
const cwd = process.cwd().toLowerCase();
|
|
4071
|
+
if (process.platform === "win32") {
|
|
4072
|
+
const winDir = process.env.SystemRoot?.toLowerCase() || "c:\\windows";
|
|
4073
|
+
const progFiles = process.env.ProgramFiles?.toLowerCase() || "c:\\program files";
|
|
4074
|
+
const progFilesX86 = process.env["ProgramFiles(x86)"]?.toLowerCase() || "c:\\program files (x86)";
|
|
4075
|
+
return cwd.startsWith(winDir) || cwd.startsWith(progFiles) || cwd.startsWith(progFilesX86);
|
|
4076
|
+
} else {
|
|
4077
|
+
const sysPaths = ["/bin", "/sbin", "/etc", "/usr", "/var", "/root"];
|
|
4078
|
+
return cwd === "/" || sysPaths.some((p) => cwd.startsWith(p));
|
|
4079
|
+
}
|
|
4080
|
+
})();
|
|
4081
|
+
const msgs = [logoMsg, welcomeMsg];
|
|
4082
|
+
if (isSystemDir) {
|
|
4083
|
+
msgs.push({
|
|
4084
|
+
id: "system-warning",
|
|
4085
|
+
role: "system",
|
|
4086
|
+
text: `\u{1F6D1} [CRITICAL SECURITY ALERT] SYSTEM DIRECTORY DETECTED`,
|
|
4087
|
+
subText: `You are currently in a PROTECTED SYSTEM DIRECTORY (${process.cwd()}). Operating here is EXTREMELY dangerous as the agent could accidentally corrupt your OS or installed applications. PLEASE MOVE TO A PROJECT FOLDER FOR SAFETY.`,
|
|
4088
|
+
isHomeWarning: true,
|
|
4089
|
+
isMeta: true
|
|
4090
|
+
});
|
|
4091
|
+
} else if (isHomeDir) {
|
|
4092
|
+
msgs.push({
|
|
4093
|
+
id: "home-warning",
|
|
4094
|
+
role: "system",
|
|
4095
|
+
text: `[SECURITY ALERT] HOME DIRECTORY DETECTED`,
|
|
4096
|
+
subText: `You are currently in ${os2.homedir()}. Working here is high-risk as the agent may modify system-sensitive configurations. Please move to a project folder for safety.`,
|
|
4097
|
+
isHomeWarning: true,
|
|
4098
|
+
isMeta: true
|
|
4099
|
+
});
|
|
4100
|
+
}
|
|
4101
|
+
return msgs;
|
|
4102
|
+
});
|
|
3957
4103
|
const queuedPromptRef = useRef2(null);
|
|
3958
|
-
const [completedIndex, setCompletedIndex] = useState7(
|
|
4104
|
+
const [completedIndex, setCompletedIndex] = useState7(messages.length);
|
|
3959
4105
|
const windowedHistory = useMemo(() => {
|
|
3960
4106
|
const MAX_HISTORY_LINES = 2e3;
|
|
3961
4107
|
const width = terminalSize.columns || 80;
|
|
@@ -4234,6 +4380,13 @@ function App() {
|
|
|
4234
4380
|
{ cmd: "/reset", desc: "Wipe all project data" },
|
|
4235
4381
|
{ cmd: "/about", desc: "Project info & credits" },
|
|
4236
4382
|
{ cmd: "/changelog", desc: "View latest updates" },
|
|
4383
|
+
{
|
|
4384
|
+
cmd: "/fluxflow",
|
|
4385
|
+
desc: "Project management",
|
|
4386
|
+
subs: [
|
|
4387
|
+
{ cmd: "init", desc: "Create FluxFlow.md template" }
|
|
4388
|
+
]
|
|
4389
|
+
},
|
|
4237
4390
|
{
|
|
4238
4391
|
cmd: "/update",
|
|
4239
4392
|
desc: "Check/Install updates",
|
|
@@ -4323,9 +4476,8 @@ ${hintText}`, color: "magenta" }];
|
|
|
4323
4476
|
break;
|
|
4324
4477
|
}
|
|
4325
4478
|
case "/clear": {
|
|
4326
|
-
stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
4327
4479
|
setMessages([{ id: "welcome-" + Date.now(), role: "system", text: FLUX_LOGO + "\n\n\u{1F30A}\u26A1 Welcome back to Flux Flow! Context cleared.\n", isMeta: true }]);
|
|
4328
|
-
setCompletedIndex(
|
|
4480
|
+
setCompletedIndex(1);
|
|
4329
4481
|
setChatId(generateChatId());
|
|
4330
4482
|
setSessionStats({ tokens: 0 });
|
|
4331
4483
|
setIsExpanded(false);
|
|
@@ -4512,6 +4664,46 @@ ${list || "No saved chats found."}`, isMeta: true }];
|
|
|
4512
4664
|
});
|
|
4513
4665
|
break;
|
|
4514
4666
|
}
|
|
4667
|
+
case "/fluxflow": {
|
|
4668
|
+
const args = parts.slice(1);
|
|
4669
|
+
if (args[0] === "init") {
|
|
4670
|
+
const template = `# FluxFlow Configuration
|
|
4671
|
+
# This file defines project-specific instructions for the Flux Flow Agent.
|
|
4672
|
+
|
|
4673
|
+
# IDENTITY & TONE
|
|
4674
|
+
- Tone: Technical, precise, and highly efficient.
|
|
4675
|
+
|
|
4676
|
+
# PROJECT CONTEXT
|
|
4677
|
+
- Goal: [Describe your project goal here]
|
|
4678
|
+
- Tech Stack: [List your technologies here]
|
|
4679
|
+
|
|
4680
|
+
# CUSTOM RULES
|
|
4681
|
+
- [Add specific coding standards or rules here]
|
|
4682
|
+
|
|
4683
|
+
# SKILLS & WORKFLOWS
|
|
4684
|
+
- [Define custom step-by-step recipes for this project here]
|
|
4685
|
+
`;
|
|
4686
|
+
const filePath = path18.join(process.cwd(), "FluxFlow.md");
|
|
4687
|
+
if (fs19.pathExistsSync(filePath)) {
|
|
4688
|
+
setMessages((prev) => {
|
|
4689
|
+
setCompletedIndex(prev.length + 1);
|
|
4690
|
+
return [...prev, { id: "init-err-" + Date.now(), role: "system", text: "\u274C ERROR: FluxFlow.md already exists in this directory.", isMeta: true }];
|
|
4691
|
+
});
|
|
4692
|
+
} else {
|
|
4693
|
+
fs19.writeFileSync(filePath, template);
|
|
4694
|
+
setMessages((prev) => {
|
|
4695
|
+
setCompletedIndex(prev.length + 1);
|
|
4696
|
+
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 }];
|
|
4697
|
+
});
|
|
4698
|
+
}
|
|
4699
|
+
} else {
|
|
4700
|
+
setMessages((prev) => {
|
|
4701
|
+
setCompletedIndex(prev.length + 1);
|
|
4702
|
+
return [...prev, { id: "ff-err-" + Date.now(), role: "system", text: "\u2753 Usage: /fluxflow init", isMeta: true }];
|
|
4703
|
+
});
|
|
4704
|
+
}
|
|
4705
|
+
break;
|
|
4706
|
+
}
|
|
4515
4707
|
case "/update": {
|
|
4516
4708
|
const arg = parts[1]?.toLowerCase();
|
|
4517
4709
|
if (arg === "check") {
|
|
@@ -4896,60 +5088,6 @@ Selection: ${val}`,
|
|
|
4896
5088
|
}, [suggestions]);
|
|
4897
5089
|
const renderActiveView = () => {
|
|
4898
5090
|
switch (activeView) {
|
|
4899
|
-
case "mode":
|
|
4900
|
-
return /* @__PURE__ */ React10.createElement(
|
|
4901
|
-
CommandMenu,
|
|
4902
|
-
{
|
|
4903
|
-
title: "\u26A1 Select Operating Mode",
|
|
4904
|
-
items: [{ label: "Flux (Dev mode - Extended Toolset)", value: "Flux" }, { label: "Flow (Chat mode - Basic Toolset)", value: "Flow" }, { label: "Cancel", value: "Cancel" }],
|
|
4905
|
-
onSelect: (item) => {
|
|
4906
|
-
if (item.value !== "Cancel") {
|
|
4907
|
-
setMode(item.value);
|
|
4908
|
-
if (item.value === "Flow") {
|
|
4909
|
-
setThinkingLevel("Low");
|
|
4910
|
-
} else if (item.value === "Flux") {
|
|
4911
|
-
setThinkingLevel("High");
|
|
4912
|
-
}
|
|
4913
|
-
}
|
|
4914
|
-
setActiveView("chat");
|
|
4915
|
-
}
|
|
4916
|
-
}
|
|
4917
|
-
);
|
|
4918
|
-
case "thinking": {
|
|
4919
|
-
const options = mode === "Flow" ? [
|
|
4920
|
-
{ label: "Low (Fastest)", value: "Low" },
|
|
4921
|
-
{ label: "Medium (Balanced)", value: "Medium" }
|
|
4922
|
-
] : [
|
|
4923
|
-
{ label: "Low (Fastest)", value: "Low" },
|
|
4924
|
-
{ label: "Medium (Balanced)", value: "Medium" },
|
|
4925
|
-
{ label: "High (Complex coding)", value: "High" },
|
|
4926
|
-
{ label: "Max (Architecture)", value: "Max" }
|
|
4927
|
-
];
|
|
4928
|
-
options.push({ label: "Cancel", value: "Cancel" });
|
|
4929
|
-
return /* @__PURE__ */ React10.createElement(
|
|
4930
|
-
CommandMenu,
|
|
4931
|
-
{
|
|
4932
|
-
title: `\u{1F9E0} Select Thinking Level (${mode} Mode)`,
|
|
4933
|
-
items: options,
|
|
4934
|
-
onSelect: (item) => {
|
|
4935
|
-
if (item.value !== "Cancel") setThinkingLevel(item.value);
|
|
4936
|
-
setActiveView("chat");
|
|
4937
|
-
}
|
|
4938
|
-
}
|
|
4939
|
-
);
|
|
4940
|
-
}
|
|
4941
|
-
case "model":
|
|
4942
|
-
return /* @__PURE__ */ React10.createElement(
|
|
4943
|
-
CommandMenu,
|
|
4944
|
-
{
|
|
4945
|
-
title: "\u{1F916} Select AI Model",
|
|
4946
|
-
items: [{ label: "Gemma 4 31B (Recomended - Default, Use Free Tier Key)", value: "gemma-4-31b-it" }, { label: "Gemini 3.1 Pro (Best - Req. Paid Key)", value: "gemini-3.1-pro-preview" }, { label: "Gemini 3 Flash (Paid API Key Recomended)", value: "gemini-3-flash-preview" }, { label: "Gemini 3.1 Flash Lite (Fastest - For Quick Tasks ONLY, Limited Free Quota)", value: "gemini-3.1-flash-lite-preview" }, { label: "Cancel", value: "Cancel" }],
|
|
4947
|
-
onSelect: (item) => {
|
|
4948
|
-
if (item.value !== "Cancel") setActiveModel(item.value);
|
|
4949
|
-
setActiveView("chat");
|
|
4950
|
-
}
|
|
4951
|
-
}
|
|
4952
|
-
);
|
|
4953
5091
|
case "settings":
|
|
4954
5092
|
return /* @__PURE__ */ React10.createElement(
|
|
4955
5093
|
CommandMenu,
|
|
@@ -5223,8 +5361,11 @@ Selection: ${val}`,
|
|
|
5223
5361
|
}
|
|
5224
5362
|
setMessages(resumedMsgs);
|
|
5225
5363
|
setActiveView("chat");
|
|
5226
|
-
setMessages((prev) =>
|
|
5227
|
-
|
|
5364
|
+
setMessages((prev) => {
|
|
5365
|
+
const newMsgs = [...prev, { id: "sys-" + Date.now(), role: "system", text: `\u{1F4E1} SESSION RESUMED: [${id}]` }];
|
|
5366
|
+
setCompletedIndex(newMsgs.length);
|
|
5367
|
+
return newMsgs;
|
|
5368
|
+
});
|
|
5228
5369
|
}
|
|
5229
5370
|
},
|
|
5230
5371
|
onDelete: async (id) => {
|
|
@@ -5258,7 +5399,7 @@ Selection: ${val}`,
|
|
|
5258
5399
|
setActiveView("chat");
|
|
5259
5400
|
setTimeout(() => {
|
|
5260
5401
|
handleSubmit(val);
|
|
5261
|
-
},
|
|
5402
|
+
}, 500);
|
|
5262
5403
|
},
|
|
5263
5404
|
onEdit: (val) => {
|
|
5264
5405
|
setResolutionData(null);
|
|
@@ -5523,8 +5664,8 @@ var init_app = __esm({
|
|
|
5523
5664
|
init_text();
|
|
5524
5665
|
SESSION_START_TIME = Date.now();
|
|
5525
5666
|
CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
|
|
5526
|
-
versionFluxflow = "1.9.
|
|
5527
|
-
updatedOn = "2026-05-
|
|
5667
|
+
versionFluxflow = "1.9.2";
|
|
5668
|
+
updatedOn = "2026-05-14";
|
|
5528
5669
|
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(
|
|
5529
5670
|
CommandMenu,
|
|
5530
5671
|
{
|