fluxflow-cli 1.0.11 → 1.0.13
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 +33 -57
- package/package.json +1 -2
package/dist/fluxflow.js
CHANGED
|
@@ -192,7 +192,7 @@ function StatusBar({ mode, thinkingLevel, tokens = "0.0k", chatId = "NEW-SESSION
|
|
|
192
192
|
},
|
|
193
193
|
/* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: modeColor, bold: true }, modeIcon, " ", mode.toUpperCase()), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "magenta" }, "\u{1F9E0} ", thinkingLevel)),
|
|
194
194
|
/* @__PURE__ */ React3.createElement(Box3, { flexGrow: 1, justifyContent: "center", paddingX: 2 }, /* @__PURE__ */ React3.createElement(Text3, { color: "gray", dimColor: true }, "\u{1F4C1} "), /* @__PURE__ */ React3.createElement(Text3, { color: "blue", dimColor: true, italic: true }, process.cwd())),
|
|
195
|
-
/* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, "MEM: "), /* @__PURE__ */ React3.createElement(Text3, { color: memStatus === "ON" ? "green" : "red" }, memStatus), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "blue" }, " Tokens ", tokens > 1e3 ? `${(tokens / 1e3).toFixed(1)}k` : tokens, " (", Math.round(tokens /
|
|
195
|
+
/* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, "MEM: "), /* @__PURE__ */ React3.createElement(Text3, { color: memStatus === "ON" ? "green" : "red" }, memStatus), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "blue" }, " Tokens ", tokens > 1e3 ? `${(tokens / 1e3).toFixed(1)}k` : tokens, " (", Math.round(tokens / 254e3 * 100), "%)"), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "dim" }, "ID: ", chatId, " "))
|
|
196
196
|
);
|
|
197
197
|
}
|
|
198
198
|
|
|
@@ -345,11 +345,11 @@ tool:functions.tool_name(arguments)
|
|
|
345
345
|
2. Web Scrape: tool:functions.web_scrape(url="<url>"). provides detail from a URL.
|
|
346
346
|
${mode === "Flux" ? `
|
|
347
347
|
- DEV & FILE TOOLS (Available in FLUX MODE ONLY) -
|
|
348
|
-
1. View File: tool:functions.view_file(path="relative/path", start_line=number, end_line=number). Reads file content.
|
|
348
|
+
1. View File: tool:functions.view_file(path="relative/path", start_line=number, end_line=number). Reads file content. Auto-truncates at 500 lines unless start_line and end_line are provided.
|
|
349
349
|
2. List Files: tool:functions.list_files(path="relative/path"). Lists content of a directory.
|
|
350
350
|
3. Read Folder: tool:functions.read_folder(path="relative/path"). Detailed stats of a directory.
|
|
351
|
-
4. Write File: tool:functions.write_file(path="
|
|
352
|
-
5. Update File: tool:functions.update_file(path="relative/path", content_to_replace="old", content_to_add="new"). Surgical patching. RETURNS: High-fidelity visual diff and old code block. You MUST verify that the change specifically matches your intent using the returned diff. PREFFER UPDATE FILE OVER WRITE FILE if file already exists. DONT WRAP UPDATE FILE CALL CONTENT IN MARKDOWN CODE BLOCKS.
|
|
351
|
+
4. Write File: tool:functions.write_file(path="path", content="content"). Creates/Overwrites. NO CODE BLOCKS. RETURNS: Disk verification + original content (if overwritten) for 100% reversibility.
|
|
352
|
+
5. Update File: tool:functions.update_file(path="relative/path", content_to_replace="old", content_to_add="new"). Surgical patching. RETURNS: High-fidelity visual diff and old code block. You MUST verify that the change specifically matches your intent using the returned diff. PREFFER UPDATE FILE OVER WRITE FILE if file already exists for better reversal tracking (if a file has 500+ lines, try to stick with update_file over full-rewrite). DONT WRAP UPDATE FILE CALL CONTENT IN MARKDOWN CODE BLOCKS.
|
|
353
353
|
6. Execution: tool:functions.exec_command(command="terminal command"). Runs a shell command.`.trim() : `
|
|
354
354
|
- DEV & FILE TOOLS are not available in FLOW MODE. If you need to access files, tell the user to switch to FLUX MODE (manually by user).`.trim()}
|
|
355
355
|
-----------------
|
|
@@ -417,7 +417,7 @@ ${userMemories}
|
|
|
417
417
|
` : ""}${isMemoryEnabled ? `${tempMemoriesStr}
|
|
418
418
|
|
|
419
419
|
` : ""}--- START SYSTEM INSTRUCTION ---
|
|
420
|
-
You are Flux Flow. A CLI
|
|
420
|
+
You are Flux Flow. A CLI 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 try to minimize number of agentic loops (Agent Loop is limited to 50 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 7 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
|
|
|
@@ -450,9 +450,8 @@ Every ${isMemoryEnabled ? "Prompt, Responses & Memories" : "Prompt & Responses"}
|
|
|
450
450
|
-- START FORMATTING RULES --
|
|
451
451
|
- Use markdown.
|
|
452
452
|
- Structure responses VISUALLY pleasing, easy to read, and beautiful.
|
|
453
|
-
- NEVER USE table format markdown
|
|
454
|
-
-
|
|
455
|
-
- Use emojis. But dont overdo it.
|
|
453
|
+
- **CRITICAL**: NEVER USE table format markdown & LaTeX IN TERMINAL RESPONSES (exception: file content).
|
|
454
|
+
- Use emojis.
|
|
456
455
|
-- END FORMATTING RULES --
|
|
457
456
|
|
|
458
457
|
-- START REPONSE FINISH PROTOCOL --
|
|
@@ -844,46 +843,6 @@ var chat = async (rawArgs, context = {}) => {
|
|
|
844
843
|
}
|
|
845
844
|
};
|
|
846
845
|
|
|
847
|
-
// src/tools/summary.js
|
|
848
|
-
var summary = async (rawArgs, context = {}) => {
|
|
849
|
-
const parseArg = (key) => {
|
|
850
|
-
const regex = new RegExp(`${key}\\s*=\\s*(["'])(.*?)\\1(?=\\s*[,)]|\\s+\\w+\\s*=|$)`, "s");
|
|
851
|
-
const match = rawArgs.match(regex);
|
|
852
|
-
return match ? match[2].trim() : null;
|
|
853
|
-
};
|
|
854
|
-
const content = parseArg("content");
|
|
855
|
-
const chatId = context.chatId;
|
|
856
|
-
const { startIndex, endIndex } = context.summarizedIndices || {};
|
|
857
|
-
if (!chatId) return "ERROR: No active chatId found in tool context.";
|
|
858
|
-
if (!content) return "ERROR: Missing 'content' argument.";
|
|
859
|
-
if (startIndex === void 0 || endIndex === void 0) {
|
|
860
|
-
return "ERROR: Summary tool called without target range indices in context.";
|
|
861
|
-
}
|
|
862
|
-
try {
|
|
863
|
-
const history = await loadHistory();
|
|
864
|
-
if (history[chatId]) {
|
|
865
|
-
const messages = history[chatId].messages;
|
|
866
|
-
const summaryMsg = {
|
|
867
|
-
id: `summary-${Date.now()}`,
|
|
868
|
-
role: "system",
|
|
869
|
-
text: content
|
|
870
|
-
};
|
|
871
|
-
const actualStart = Math.min(startIndex, messages.length - 1);
|
|
872
|
-
const actualEnd = Math.min(endIndex, messages.length - 1);
|
|
873
|
-
const count = actualEnd - actualStart + 1;
|
|
874
|
-
if (count > 0) {
|
|
875
|
-
messages.splice(actualStart, count, summaryMsg);
|
|
876
|
-
await saveChat(chatId, history[chatId].name, messages);
|
|
877
|
-
return `SUCCESS: Compressed ${count} turns into a summary block.`;
|
|
878
|
-
}
|
|
879
|
-
return "ERROR: Targeted range for summarization is invalid or empty.";
|
|
880
|
-
}
|
|
881
|
-
return "ERROR: Chat session not found.";
|
|
882
|
-
} catch (err) {
|
|
883
|
-
return `ERROR: Failed to save summary: ${err.message}`;
|
|
884
|
-
}
|
|
885
|
-
};
|
|
886
|
-
|
|
887
846
|
// src/tools/list_files.js
|
|
888
847
|
import fs7 from "fs";
|
|
889
848
|
import path8 from "path";
|
|
@@ -981,6 +940,21 @@ var write_file = async (args) => {
|
|
|
981
940
|
const absolutePath = path10.resolve(process.cwd(), targetPath);
|
|
982
941
|
const parentDir = path10.dirname(absolutePath);
|
|
983
942
|
try {
|
|
943
|
+
let ancestry = "";
|
|
944
|
+
if (fs9.existsSync(absolutePath)) {
|
|
945
|
+
try {
|
|
946
|
+
const oldData = fs9.readFileSync(absolutePath, "utf8");
|
|
947
|
+
const lines = oldData.split(/\r?\n/);
|
|
948
|
+
ancestry = `Old File contents:
|
|
949
|
+
${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
|
|
950
|
+
|
|
951
|
+
`;
|
|
952
|
+
} catch (e) {
|
|
953
|
+
ancestry = `[Note: Could not read existing file for reversal reference]
|
|
954
|
+
|
|
955
|
+
`;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
984
958
|
if (!fs9.existsSync(parentDir)) {
|
|
985
959
|
fs9.mkdirSync(parentDir, { recursive: true });
|
|
986
960
|
}
|
|
@@ -1011,7 +985,7 @@ ${tail}`;
|
|
|
1011
985
|
return `SUCCESS: File [${targetPath}] verified and persisted.
|
|
1012
986
|
|
|
1013
987
|
- Stats: [${verifiedLineCount} lines, ${(verifiedSize / 1024).toFixed(1)} KB]
|
|
1014
|
-
- Content Preview:
|
|
988
|
+
${ancestry}- Content Preview:
|
|
1015
989
|
${snippet}`;
|
|
1016
990
|
} catch (err) {
|
|
1017
991
|
return `ERROR: Failed to write file [${targetPath}]: ${err.message}`;
|
|
@@ -1188,7 +1162,6 @@ var TOOL_MAP = {
|
|
|
1188
1162
|
web_scrape,
|
|
1189
1163
|
memory,
|
|
1190
1164
|
chat,
|
|
1191
|
-
summary,
|
|
1192
1165
|
list_files,
|
|
1193
1166
|
view_file,
|
|
1194
1167
|
write_file,
|
|
@@ -1265,7 +1238,7 @@ var getAIStream = async function* (modelName, history, settings, steeringCallbac
|
|
|
1265
1238
|
const needTitle = isFirstPrompt || hasTitleSignal;
|
|
1266
1239
|
const agentText = originalText.replace(/\[TITLE-UPDATE\]/g, "").trim();
|
|
1267
1240
|
let modifiedHistory = [...history.slice(0, -1)];
|
|
1268
|
-
if (systemSettings?.compression === 0 && (sessionStats?.tokens || 0) >
|
|
1241
|
+
if (systemSettings?.compression === 0 && (sessionStats?.tokens || 0) > 254e3) {
|
|
1269
1242
|
modifiedHistory = getTruncatedHistory(modifiedHistory, 4);
|
|
1270
1243
|
}
|
|
1271
1244
|
const tempStorage = readEncryptedJson(TEMP_MEM_FILE, {});
|
|
@@ -1311,9 +1284,12 @@ USER_PROMPT: ${agentText}`.trim();
|
|
|
1311
1284
|
throw new Error("Error: Daily Quota Exausted for Agent");
|
|
1312
1285
|
}
|
|
1313
1286
|
let targetModel = modelName;
|
|
1314
|
-
if (retryCount
|
|
1287
|
+
if (retryCount === 5) {
|
|
1288
|
+
targetModel = "gemini-3-flash-preview";
|
|
1289
|
+
yield { type: "model_update", content: "Trying with fallback model (v3)" };
|
|
1290
|
+
} else if (retryCount >= 6) {
|
|
1315
1291
|
targetModel = "gemini-3.1-flash-lite-preview";
|
|
1316
|
-
yield { type: "model_update", content: "Trying with fallback model" };
|
|
1292
|
+
yield { type: "model_update", content: "Trying with fallback model (v3.1)" };
|
|
1317
1293
|
} else if (retryCount > 0) {
|
|
1318
1294
|
yield { type: "model_update", content: null };
|
|
1319
1295
|
}
|
|
@@ -1321,7 +1297,7 @@ USER_PROMPT: ${agentText}`.trim();
|
|
|
1321
1297
|
model: targetModel,
|
|
1322
1298
|
contents,
|
|
1323
1299
|
config: {
|
|
1324
|
-
temperature: mode === "Flux" ?
|
|
1300
|
+
temperature: mode === "Flux" ? 1 : 1.4,
|
|
1325
1301
|
thinkingConfig: {
|
|
1326
1302
|
includeThoughts: false,
|
|
1327
1303
|
thinkingLevel: ThinkingLevel.MINIMAL
|
|
@@ -1340,10 +1316,10 @@ USER_PROMPT: ${agentText}`.trim();
|
|
|
1340
1316
|
if (retryCount < MAX_RETRIES) {
|
|
1341
1317
|
retryCount++;
|
|
1342
1318
|
const waitTime = Math.floor(Math.random() * (2e3 - 800 + 1)) + 800;
|
|
1343
|
-
yield { type: "status", content: `Retrying (${retryCount}/${MAX_RETRIES})...` };
|
|
1319
|
+
yield { type: "status", content: `Retrying (${retryCount}/${MAX_RETRIES + 1})...` };
|
|
1344
1320
|
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
1345
1321
|
} else {
|
|
1346
|
-
throw new Error(`Model cannot be reached: ${errMsg}`);
|
|
1322
|
+
throw new Error(`Model cannot be reached: ${errMsg}. (Failed ${MAX_RETRIES + 1} times)`);
|
|
1347
1323
|
}
|
|
1348
1324
|
}
|
|
1349
1325
|
}
|
|
@@ -2309,7 +2285,7 @@ OUTPUT: ${execOutputRef.current}`;
|
|
|
2309
2285
|
return newMsgs;
|
|
2310
2286
|
});
|
|
2311
2287
|
} else if (!inThinkMode) {
|
|
2312
|
-
const cleanedText = chunkText.replace(
|
|
2288
|
+
const cleanedText = chunkText.replace(/<\/?think>/gi, "").replace(signalRegex, "");
|
|
2313
2289
|
if (!currentAgentId) {
|
|
2314
2290
|
currentAgentId = "agent-" + Date.now();
|
|
2315
2291
|
setMessages((prev) => [...prev, { id: currentAgentId, role: "agent", text: cleanedText }]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fluxflow-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"description": "A high-fidelity agentic terminal assistant for the Flux Era.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -40,7 +40,6 @@
|
|
|
40
40
|
"@google/genai": "^1.50.1",
|
|
41
41
|
"chalk": "^5.6.2",
|
|
42
42
|
"cuimp": "^1.10.0",
|
|
43
|
-
"duck-duck-scrape": "^2.2.7",
|
|
44
43
|
"fs-extra": "^11.3.4",
|
|
45
44
|
"gradient-string": "^3.0.0",
|
|
46
45
|
"ink": "^7.0.1",
|