fluxflow-cli 1.9.1 → 1.9.4
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 +148 -30
- package/package.json +1 -1
package/dist/fluxflow.js
CHANGED
|
@@ -151,7 +151,6 @@ var init_ChatLayout = __esm({
|
|
|
151
151
|
"web_search": "Web Search",
|
|
152
152
|
"web_scrape": "Read Site",
|
|
153
153
|
"search_keyword": "Find Files",
|
|
154
|
-
"ask": "Ask User",
|
|
155
154
|
"write_pdf": "Create PDF",
|
|
156
155
|
"write_pptx": "Create Presentation",
|
|
157
156
|
"write_docx": "Create Document"
|
|
@@ -210,7 +209,7 @@ var init_ChatLayout = __esm({
|
|
|
210
209
|
}
|
|
211
210
|
}
|
|
212
211
|
}
|
|
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|
|
|
212
|
+
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|write_pdf|write_pptx|write_docx)\b/gi, (match) => TOOL_LABELS[match.toLowerCase()] || match).trim();
|
|
214
213
|
};
|
|
215
214
|
formatThinkText = (cleaned, columns = 80) => {
|
|
216
215
|
if (!cleaned) return null;
|
|
@@ -395,11 +394,15 @@ var init_ChatLayout = __esm({
|
|
|
395
394
|
const isDiffResult = msg.role === "system" && msg.text?.includes("[DIFF_START]");
|
|
396
395
|
const isPatchError = msg.role === "system" && msg.text?.includes("[TOOL_RESULT]: ERROR:") && (msg.toolName === "update_file" || msg.text?.includes("Could not find exact match"));
|
|
397
396
|
const isTerminalRecord = msg.isTerminalRecord;
|
|
397
|
+
const isHomeWarning = msg.isHomeWarning;
|
|
398
|
+
if (isHomeWarning) {
|
|
399
|
+
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))));
|
|
400
|
+
}
|
|
401
|
+
if (msg.isLogo) {
|
|
402
|
+
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", alignItems: "center", width: "100%", marginY: 1 }, /* @__PURE__ */ React2.createElement(Text2, null, msg.text));
|
|
403
|
+
}
|
|
398
404
|
if (msg.id && String(msg.id).startsWith("welcome")) {
|
|
399
|
-
|
|
400
|
-
const logo = parts[0];
|
|
401
|
-
const greeting = parts[1] || "";
|
|
402
|
-
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())));
|
|
405
|
+
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())));
|
|
403
406
|
}
|
|
404
407
|
if (msg.isVisualFeedback) {
|
|
405
408
|
return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color: "white" }, msg.text));
|
|
@@ -412,7 +415,7 @@ var init_ChatLayout = __esm({
|
|
|
412
415
|
const selectionMatch = msg.text.match(/Selection: (.*)/);
|
|
413
416
|
const selection = selectionMatch ? selectionMatch[1] : "No selection";
|
|
414
417
|
const s = emojiSpace(2);
|
|
415
|
-
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}
|
|
418
|
+
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)))));
|
|
416
419
|
}
|
|
417
420
|
if (msg.isAboutRecord) {
|
|
418
421
|
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))));
|
|
@@ -466,6 +469,13 @@ var init_ChatLayout = __esm({
|
|
|
466
469
|
{ cmd: "/reset", desc: "Wipe all project data" },
|
|
467
470
|
{ cmd: "/about", desc: "Project info & credits" },
|
|
468
471
|
{ cmd: "/changelog", desc: "View latest updates" },
|
|
472
|
+
{
|
|
473
|
+
cmd: "/fluxflow",
|
|
474
|
+
desc: "Project management",
|
|
475
|
+
subs: [
|
|
476
|
+
{ cmd: "init", desc: "Create FluxFlow.md template" }
|
|
477
|
+
]
|
|
478
|
+
},
|
|
469
479
|
{
|
|
470
480
|
cmd: "/update",
|
|
471
481
|
desc: "Check/Install updates",
|
|
@@ -691,7 +701,7 @@ var init_AskUserModal = __esm({
|
|
|
691
701
|
});
|
|
692
702
|
const s = emojiSpace(2);
|
|
693
703
|
if (isSuggestingElse) {
|
|
694
|
-
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}
|
|
704
|
+
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(
|
|
695
705
|
TextInput2,
|
|
696
706
|
{
|
|
697
707
|
value: customInput,
|
|
@@ -700,7 +710,7 @@ var init_AskUserModal = __esm({
|
|
|
700
710
|
}
|
|
701
711
|
)), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", dimColor: true, italic: true }, "(Press Enter to send)")));
|
|
702
712
|
}
|
|
703
|
-
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) => {
|
|
713
|
+
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) => {
|
|
704
714
|
const isSelected = idx === selectedIndex;
|
|
705
715
|
return /* @__PURE__ */ React6.createElement(
|
|
706
716
|
Box6,
|
|
@@ -974,6 +984,18 @@ var init_prompts = __esm({
|
|
|
974
984
|
` : "";
|
|
975
985
|
const dateTimeStr = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
976
986
|
const cwdStr = process.cwd();
|
|
987
|
+
const isSystemDir = (() => {
|
|
988
|
+
const cwd = process.cwd().toLowerCase();
|
|
989
|
+
if (process.platform === "win32") {
|
|
990
|
+
const winDir = process.env.SystemRoot?.toLowerCase() || "c:\\windows";
|
|
991
|
+
const progFiles = process.env.ProgramFiles?.toLowerCase() || "c:\\program files";
|
|
992
|
+
const progFilesX86 = process.env["ProgramFiles(x86)"]?.toLowerCase() || "c:\\program files (x86)";
|
|
993
|
+
return cwd.startsWith(winDir) || cwd.startsWith(progFiles) || cwd.startsWith(progFilesX86);
|
|
994
|
+
} else {
|
|
995
|
+
const sysPaths = ["/bin", "/sbin", "/etc", "/usr", "/var", "/root"];
|
|
996
|
+
return cwd === "/" || sysPaths.some((p) => cwd.startsWith(p));
|
|
997
|
+
}
|
|
998
|
+
})();
|
|
977
999
|
const tempMemoriesStr = tempMemories?.length > 0 && !isContext32k ? `
|
|
978
1000
|
-- RECENT CONTEXT FROM OTHER CHAT THREADS (PRIORITY: LOW, RECENT > OLD) --
|
|
979
1001
|
${tempMemories.split("\n").map((line) => ` ${line}`).join("\n")}
|
|
@@ -990,8 +1012,8 @@ ${userMemories.split("\n").map((line) => ` ${line}`).join("\n")}
|
|
|
990
1012
|
--- START SYSTEM INSTRUCTION (STRICT PRIORITY, OVERRIDES EVERYTHING) ---
|
|
991
1013
|
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.`}
|
|
992
1014
|
MUST FOLLOW THE "CRITICAL THINKING POLICY"${mode === "Flux" ? `, "CRITICAL NEWLINE PROTOCOL", "CRITICAL QUOTE ESCAPE POLICY"` : ""} ALWAYS. **NO EXCEPTIONS.**
|
|
993
|
-
CURRENT_WORKING_DIRECTORY: ${cwdStr}.
|
|
994
|
-
OS: ${osDetected}
|
|
1015
|
+
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." : ""}
|
|
1016
|
+
OS: ${osDetected}.${osDetected === "Windows" && mode === "Flux" ? " Your terminal commands will run on CMD. 'Prefer using PS scripts via CMD' instead of raw CMD commands." : ""}
|
|
995
1017
|
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.
|
|
996
1018
|
|
|
997
1019
|
-- START THINKING INSTRUCTIONS --
|
|
@@ -1010,8 +1032,10 @@ ${userMemories.split("\n").map((line) => ` ${line}`).join("\n")}
|
|
|
1010
1032
|
-- START PROJECT SPECIFIC INSTRUCTIONS --
|
|
1011
1033
|
1. README.md (If exists): Reference this for high-level goals and project context to ensure your work aligns with the user's objectives.
|
|
1012
1034
|
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.
|
|
1013
|
-
3. Skills.md (If exists): Use this for complex workflows. If a task matches a "Skill" defined in
|
|
1014
|
-
4.
|
|
1035
|
+
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.
|
|
1036
|
+
4. design.md (If exists): Reference this for UI/UX specifications, component blueprints, and design system constraints to maintain visual excellence.
|
|
1037
|
+
5. architecture.md (If exists): Reference this for system-level structural patterns, API design, and data flow.
|
|
1038
|
+
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.
|
|
1015
1039
|
|
|
1016
1040
|
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.
|
|
1017
1041
|
-- END PROJECT SPECIFIC INSTRUCTIONS --
|
|
@@ -1061,7 +1085,7 @@ ${userMemories.split("\n").map((line) => ` ${line}`).join("\n")}
|
|
|
1061
1085
|
-- END REPONSE FINISH PROTOCOL --
|
|
1062
1086
|
|
|
1063
1087
|
[SYSTEM METADATA (PRIORITY: DYNAMIC)] Current date and Time is: ${dateTimeStr}
|
|
1064
|
-
[SYSTEM METADATA (PRIORITY: LOWEST)] v1.9.
|
|
1088
|
+
[SYSTEM METADATA (PRIORITY: LOWEST)] v1.9.4. (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.
|
|
1065
1089
|
[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.
|
|
1066
1090
|
[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.
|
|
1067
1091
|
--- END SYSTEM INSTRUCTION ---`.trim();
|
|
@@ -3137,8 +3161,11 @@ USER_PROMPT: "${agentText}"`.trim();
|
|
|
3137
3161
|
}
|
|
3138
3162
|
const cleanText = dedupeBuffer.substring(overlapLen);
|
|
3139
3163
|
if (cleanText) {
|
|
3140
|
-
|
|
3141
|
-
|
|
3164
|
+
const dedupeClean = cleanText.replace(/^\s*<(think|thought)>[\s\S]*?<\/(think|thought)>\s*/gi, "").replace(/^\s*<(think|thought)>\s*/gi, "");
|
|
3165
|
+
if (dedupeClean) {
|
|
3166
|
+
turnText += dedupeClean;
|
|
3167
|
+
yield { type: "text", content: dedupeClean };
|
|
3168
|
+
}
|
|
3142
3169
|
}
|
|
3143
3170
|
isDedupeActive = false;
|
|
3144
3171
|
dedupeBuffer = "";
|
|
@@ -3420,8 +3447,11 @@ ${boxBottom}
|
|
|
3420
3447
|
}
|
|
3421
3448
|
const cleanText = dedupeBuffer.substring(overlapLen);
|
|
3422
3449
|
if (cleanText) {
|
|
3423
|
-
|
|
3424
|
-
|
|
3450
|
+
const dedupeClean = cleanText.replace(/^\s*<(think|thought)>[\s\S]*?<\/(think|thought)>\s*/gi, "").replace(/^\s*<(think|thought)>\s*/gi, "");
|
|
3451
|
+
if (dedupeClean) {
|
|
3452
|
+
turnText += dedupeClean;
|
|
3453
|
+
yield { type: "text", content: dedupeClean };
|
|
3454
|
+
}
|
|
3425
3455
|
}
|
|
3426
3456
|
isDedupeActive = false;
|
|
3427
3457
|
dedupeBuffer = "";
|
|
@@ -3448,7 +3478,7 @@ ${boxBottom}
|
|
|
3448
3478
|
if (toolResults.length > 0) {
|
|
3449
3479
|
toolResults.forEach((tr) => modifiedHistory.push(tr));
|
|
3450
3480
|
}
|
|
3451
|
-
modifiedHistory.push({ role: "user", text: "[SYSTEM] Response got cut for internal error, continue from checkpoint seamlessly
|
|
3481
|
+
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." });
|
|
3452
3482
|
accumulatedContext += turnText;
|
|
3453
3483
|
for (let i = waitTime / 1e3; i > 0; i--) {
|
|
3454
3484
|
yield { type: "status", content: `Error Occured. Recovering Stream (${inStreamRetryCount}/${MAX_RETRIES}) [${i}s]...` };
|
|
@@ -3863,10 +3893,12 @@ var app_exports = {};
|
|
|
3863
3893
|
__export(app_exports, {
|
|
3864
3894
|
default: () => App
|
|
3865
3895
|
});
|
|
3896
|
+
import os2 from "os";
|
|
3866
3897
|
import React10, { useState as useState7, useEffect as useEffect5, useRef as useRef2, useMemo } from "react";
|
|
3867
3898
|
import { Box as Box10, Text as Text10, useInput as useInput4, useStdout } from "ink";
|
|
3868
3899
|
import Spinner2 from "ink-spinner";
|
|
3869
3900
|
import fs19 from "fs-extra";
|
|
3901
|
+
import path18 from "path";
|
|
3870
3902
|
import { exec as exec4 } from "child_process";
|
|
3871
3903
|
import { MultilineInput } from "ink-multiline-input";
|
|
3872
3904
|
import TextInput3 from "ink-text-input";
|
|
@@ -3892,20 +3924,23 @@ function App() {
|
|
|
3892
3924
|
});
|
|
3893
3925
|
}
|
|
3894
3926
|
try {
|
|
3895
|
-
const response = await fetch("https://registry.npmjs.org/fluxflow-cli
|
|
3927
|
+
const response = await fetch("https://registry.npmjs.org/fluxflow-cli", { cache: "no-store" });
|
|
3896
3928
|
const data = await response.json();
|
|
3897
|
-
const latestVersion = data?.
|
|
3929
|
+
const latestVersion = data["dist-tags"]?.latest;
|
|
3930
|
+
const stableVersion = data["dist-tags"]?.stable;
|
|
3898
3931
|
if (latestVersion) setLatestVer(latestVersion);
|
|
3899
3932
|
if (latestVersion && latestVersion !== versionFluxflow) {
|
|
3933
|
+
const versionDisplay = latestVersion === stableVersion ? `v${latestVersion}-stable` : `v${latestVersion}`;
|
|
3900
3934
|
if (!manual && settingsToUse.autoUpdate) {
|
|
3901
3935
|
setActiveView("update");
|
|
3902
3936
|
} else {
|
|
3903
3937
|
setMessages((prev) => {
|
|
3904
3938
|
const newMsgs = [...prev];
|
|
3905
|
-
|
|
3939
|
+
const spliceIdx = manual ? newMsgs.length : Math.min(newMsgs.length, 3);
|
|
3940
|
+
newMsgs.splice(spliceIdx, 0, {
|
|
3906
3941
|
id: "update-" + Date.now(),
|
|
3907
3942
|
role: "system",
|
|
3908
|
-
text: `A new version (
|
|
3943
|
+
text: `A new version (${versionDisplay}) is here.
|
|
3909
3944
|
|
|
3910
3945
|
\u2022 Type \`/update latest\` to apply the update.
|
|
3911
3946
|
\u2022 Type \`/changelog\` to view the release notes.`,
|
|
@@ -3918,7 +3953,8 @@ function App() {
|
|
|
3918
3953
|
} else if (manual) {
|
|
3919
3954
|
setMessages((prev) => {
|
|
3920
3955
|
setCompletedIndex(prev.length + 1);
|
|
3921
|
-
|
|
3956
|
+
const displayVer = latestVersion && latestVersion === stableVersion ? `${versionFluxflow}-stable` : versionFluxflow;
|
|
3957
|
+
return [...prev, { id: "uptodate-" + Date.now(), role: "system", text: `\u2705 [SYSTEM] Flux Flow is already up to date (${displayVer}).`, isMeta: true }];
|
|
3922
3958
|
});
|
|
3923
3959
|
}
|
|
3924
3960
|
} catch (err) {
|
|
@@ -4025,11 +4061,46 @@ function App() {
|
|
|
4025
4061
|
const [queuedPrompt, setQueuedPrompt] = useState7(null);
|
|
4026
4062
|
const [resolutionData, setResolutionData] = useState7(null);
|
|
4027
4063
|
const [tempModelOverride, setTempModelOverride] = useState7(null);
|
|
4028
|
-
const [messages, setMessages] = useState7(
|
|
4029
|
-
{ id: "
|
|
4030
|
-
|
|
4064
|
+
const [messages, setMessages] = useState7(() => {
|
|
4065
|
+
const logoMsg = { id: "logo-" + Date.now(), role: "system", text: FLUX_LOGO, isLogo: true, isMeta: true };
|
|
4066
|
+
const welcomeMsg = { id: "welcome", role: "system", text: "\u{1F30A}\u26A1 Welcome to Flux Flow! Type /help for commands.", isMeta: true };
|
|
4067
|
+
const isHomeDir = process.cwd() === os2.homedir();
|
|
4068
|
+
const isSystemDir = (() => {
|
|
4069
|
+
const cwd = process.cwd().toLowerCase();
|
|
4070
|
+
if (process.platform === "win32") {
|
|
4071
|
+
const winDir = process.env.SystemRoot?.toLowerCase() || "c:\\windows";
|
|
4072
|
+
const progFiles = process.env.ProgramFiles?.toLowerCase() || "c:\\program files";
|
|
4073
|
+
const progFilesX86 = process.env["ProgramFiles(x86)"]?.toLowerCase() || "c:\\program files (x86)";
|
|
4074
|
+
return cwd.startsWith(winDir) || cwd.startsWith(progFiles) || cwd.startsWith(progFilesX86);
|
|
4075
|
+
} else {
|
|
4076
|
+
const sysPaths = ["/bin", "/sbin", "/etc", "/usr", "/var", "/root"];
|
|
4077
|
+
return cwd === "/" || sysPaths.some((p) => cwd.startsWith(p));
|
|
4078
|
+
}
|
|
4079
|
+
})();
|
|
4080
|
+
const msgs = [logoMsg, welcomeMsg];
|
|
4081
|
+
if (isSystemDir) {
|
|
4082
|
+
msgs.push({
|
|
4083
|
+
id: "system-warning",
|
|
4084
|
+
role: "system",
|
|
4085
|
+
text: `\u{1F6D1} [CRITICAL SECURITY ALERT] SYSTEM DIRECTORY DETECTED`,
|
|
4086
|
+
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.`,
|
|
4087
|
+
isHomeWarning: true,
|
|
4088
|
+
isMeta: true
|
|
4089
|
+
});
|
|
4090
|
+
} else if (isHomeDir) {
|
|
4091
|
+
msgs.push({
|
|
4092
|
+
id: "home-warning",
|
|
4093
|
+
role: "system",
|
|
4094
|
+
text: `[SECURITY ALERT] HOME DIRECTORY DETECTED`,
|
|
4095
|
+
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.`,
|
|
4096
|
+
isHomeWarning: true,
|
|
4097
|
+
isMeta: true
|
|
4098
|
+
});
|
|
4099
|
+
}
|
|
4100
|
+
return msgs;
|
|
4101
|
+
});
|
|
4031
4102
|
const queuedPromptRef = useRef2(null);
|
|
4032
|
-
const [completedIndex, setCompletedIndex] = useState7(
|
|
4103
|
+
const [completedIndex, setCompletedIndex] = useState7(messages.length);
|
|
4033
4104
|
const windowedHistory = useMemo(() => {
|
|
4034
4105
|
const MAX_HISTORY_LINES = 2e3;
|
|
4035
4106
|
const width = terminalSize.columns || 80;
|
|
@@ -4308,6 +4379,13 @@ function App() {
|
|
|
4308
4379
|
{ cmd: "/reset", desc: "Wipe all project data" },
|
|
4309
4380
|
{ cmd: "/about", desc: "Project info & credits" },
|
|
4310
4381
|
{ cmd: "/changelog", desc: "View latest updates" },
|
|
4382
|
+
{
|
|
4383
|
+
cmd: "/fluxflow",
|
|
4384
|
+
desc: "Project management",
|
|
4385
|
+
subs: [
|
|
4386
|
+
{ cmd: "init", desc: "Create FluxFlow.md template" }
|
|
4387
|
+
]
|
|
4388
|
+
},
|
|
4311
4389
|
{
|
|
4312
4390
|
cmd: "/update",
|
|
4313
4391
|
desc: "Check/Install updates",
|
|
@@ -4585,6 +4663,46 @@ ${list || "No saved chats found."}`, isMeta: true }];
|
|
|
4585
4663
|
});
|
|
4586
4664
|
break;
|
|
4587
4665
|
}
|
|
4666
|
+
case "/fluxflow": {
|
|
4667
|
+
const args = parts.slice(1);
|
|
4668
|
+
if (args[0] === "init") {
|
|
4669
|
+
const template = `# FluxFlow Configuration
|
|
4670
|
+
# This file defines project-specific instructions for the Flux Flow Agent.
|
|
4671
|
+
|
|
4672
|
+
# IDENTITY & TONE
|
|
4673
|
+
- Tone: Technical, precise, and highly efficient.
|
|
4674
|
+
|
|
4675
|
+
# PROJECT CONTEXT
|
|
4676
|
+
- Goal: [Describe your project goal here]
|
|
4677
|
+
- Tech Stack: [List your technologies here]
|
|
4678
|
+
|
|
4679
|
+
# CUSTOM RULES
|
|
4680
|
+
- [Add specific coding standards or rules here]
|
|
4681
|
+
|
|
4682
|
+
# SKILLS & WORKFLOWS
|
|
4683
|
+
- [Define custom step-by-step recipes for this project here]
|
|
4684
|
+
`;
|
|
4685
|
+
const filePath = path18.join(process.cwd(), "FluxFlow.md");
|
|
4686
|
+
if (fs19.pathExistsSync(filePath)) {
|
|
4687
|
+
setMessages((prev) => {
|
|
4688
|
+
setCompletedIndex(prev.length + 1);
|
|
4689
|
+
return [...prev, { id: "init-err-" + Date.now(), role: "system", text: "\u274C ERROR: FluxFlow.md already exists in this directory.", isMeta: true }];
|
|
4690
|
+
});
|
|
4691
|
+
} else {
|
|
4692
|
+
fs19.writeFileSync(filePath, template);
|
|
4693
|
+
setMessages((prev) => {
|
|
4694
|
+
setCompletedIndex(prev.length + 1);
|
|
4695
|
+
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 }];
|
|
4696
|
+
});
|
|
4697
|
+
}
|
|
4698
|
+
} else {
|
|
4699
|
+
setMessages((prev) => {
|
|
4700
|
+
setCompletedIndex(prev.length + 1);
|
|
4701
|
+
return [...prev, { id: "ff-err-" + Date.now(), role: "system", text: "\u2753 Usage: /fluxflow init", isMeta: true }];
|
|
4702
|
+
});
|
|
4703
|
+
}
|
|
4704
|
+
break;
|
|
4705
|
+
}
|
|
4588
4706
|
case "/update": {
|
|
4589
4707
|
const arg = parts[1]?.toLowerCase();
|
|
4590
4708
|
if (arg === "check") {
|
|
@@ -5545,8 +5663,8 @@ var init_app = __esm({
|
|
|
5545
5663
|
init_text();
|
|
5546
5664
|
SESSION_START_TIME = Date.now();
|
|
5547
5665
|
CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
|
|
5548
|
-
versionFluxflow = "1.9.
|
|
5549
|
-
updatedOn = "2026-05-
|
|
5666
|
+
versionFluxflow = "1.9.4";
|
|
5667
|
+
updatedOn = "2026-05-14";
|
|
5550
5668
|
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(
|
|
5551
5669
|
CommandMenu,
|
|
5552
5670
|
{
|