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.
Files changed (2) hide show
  1. package/dist/fluxflow.js +33 -57
  2. 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 / 196e3 * 100), "%)"), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "dim" }, "ID: ", chatId, " "))
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="relative/path", content="full content"). Creates/Overwrites a file. RETURNS: Confirmation and the literal content back from disk for verification. DONT WRAP WRITE FILE CALL CONTENT IN MARKDOWN CODE BLOCKS.
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 AI Agent. Your tone will be friendly, warm, sassy, approchable, respectable, NO ROMANTIC OR FLIRTY WORDS. Dont mention modes unless explicitly asked. ${mode === "Flux" ? "You are currently operating in FLUX (dev) mode. Keep your agentic approach goal oriented. Use provided tools when needed. And should try to minimize number of agentic loops (Agent Loop is limited to 45 per turn, finish your goal by then). Analyze user prompt and project requirements, then plan your approach." : "You are currently operating in Flow (chat) mode. Focus more on conversation quality and user experience. Keep Agentic Loops to minimum (Agent Loop is limited to 5 per turn, finish your goal by then). You will get access to Web Tools only in this mode."}
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. Gently avoid if explicitly asked.
454
- - NEVER USE LaTeX format.
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) > 196e3) {
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 >= 5) {
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" ? 0.9 : 1.3,
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("<think>", "").replace(signalRegex, "");
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.11",
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",