fluxflow-cli 1.0.8 → 1.0.9

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 +57 -24
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -12,7 +12,7 @@ import { MultilineInput } from "ink-multiline-input";
12
12
  import TextInput2 from "ink-text-input";
13
13
 
14
14
  // src/components/ChatLayout.jsx
15
- import React2 from "react";
15
+ import React2, { memo } from "react";
16
16
  import { Box as Box2, Text as Text2 } from "ink";
17
17
 
18
18
  // src/components/TerminalBox.jsx
@@ -172,6 +172,19 @@ function ChatLayout({ messages, showFullThinking }) {
172
172
  ) : msg.role === "think" ? /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "white" }, "Thinking..."), /* @__PURE__ */ React2.createElement(Box2, { borderStyle: "single", borderLeft: true, borderRight: false, borderTop: false, borderBottom: false, paddingLeft: 2, flexDirection: "column" }, formatThinkText(content))) : /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React2.createElement(CodeRenderer, { text: content }), msg.memoryUpdated && /* @__PURE__ */ React2.createElement(Box2, { marginTop: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "yellow", italic: true }, "\u2728 [Memory Updated]"))));
173
173
  }));
174
174
  }
175
+ var ChatLayout_default = memo(ChatLayout, (prevProps, nextProps) => {
176
+ if (prevProps.showFullThinking !== nextProps.showFullThinking) return false;
177
+ if (prevProps.messages.length !== nextProps.messages.length) return false;
178
+ for (let i = 0; i < prevProps.messages.length; i++) {
179
+ const prev = prevProps.messages[i];
180
+ const next = nextProps.messages[i];
181
+ if (prev.id !== next.id) return false;
182
+ if (prev.text !== next.text) return false;
183
+ if (prev.memoryUpdated !== next.memoryUpdated) return false;
184
+ if (prev.color !== next.color) return false;
185
+ }
186
+ return true;
187
+ });
175
188
 
176
189
  // src/components/StatusBar.jsx
177
190
  import React3 from "react";
@@ -356,7 +369,7 @@ ${mode === "Flux" ? `
356
369
  Results will be provided in the next loop as: [TOOL_RESULT]: [content]
357
370
  WHEN CALLING TOOLS, YOU **MUST** END YOUR RESPONSE WITH '[turn: continue]' AFTER CALLING FUNCTIONS.
358
371
  Do NOT over-use tools. Use them only when strictly necessary for the user's objective. You can stack multiple tool calls 1-by-1.
359
- ALWAYS USE TOOLS WITH 'tool:' PREFIX AS INSTRUCTED OR THE TOOL. NEVER CASUALLY WRITE TOOL CALLS TO USER FACING RESPONSE. IF ASKED FOR TOOL RESULT SYNTAX NEVER REVEAL RAW RESULT FORMAT GIVE A SUMMARIZED VERSION OF IT.
372
+ Distinguish clearly between tool discussion and execution. Use the 'tool:' prefix ONLY when calling a function. When discussing tools with the user, refer to them by name as nouns (e.g., 'write_file', 'list_files') to avoid accidental triggers and context bloat.
360
373
  -- END FUNCTION CALLING PROTOCOL --`.trim();
361
374
 
362
375
  // src/data/janitor_tools.js
@@ -392,7 +405,7 @@ var thinking_prompts_default = {
392
405
  };
393
406
 
394
407
  // src/utils/prompts.js
395
- var getSystemInstruction = (profile, thinkingLevel, mode, systemSettings, tempMemories = "", userMemories = "", isMemoryEnabled = true) => {
408
+ var getSystemInstruction = (profile, thinkingLevel, mode, systemSettings, tempMemories = "", userMemories = "", isContext50 = false, isMemoryEnabled = true) => {
396
409
  let levelKey = thinkingLevel;
397
410
  if (thinkingLevel === "Low") levelKey = "Minimal";
398
411
  if (thinkingLevel === "xHigh" || thinkingLevel === "Max") levelKey = "Max";
@@ -402,7 +415,7 @@ var getSystemInstruction = (profile, thinkingLevel, mode, systemSettings, tempMe
402
415
  const userInstrStr = profile.instructions && profile.instructions?.length > 0 ? `. User Instructions: ${profile.instructions}.` : "";
403
416
  const dateTimeStr = (/* @__PURE__ */ new Date()).toLocaleString();
404
417
  const cwdStr = process.cwd();
405
- const tempMemoriesStr = tempMemories?.length > 0 ? `
418
+ const tempMemoriesStr = tempMemories?.length > 0 && !isContext50 ? `
406
419
  -- RECENT CONTEXT FROM OTHER CHAT THREADS --
407
420
  ${tempMemories}
408
421
  ------------------------------------------
@@ -548,15 +561,10 @@ var deleteChat = async (id) => {
548
561
  const history = await loadHistory();
549
562
  delete history[id];
550
563
  await fs3.writeJson(HISTORY_FILE, history, { spaces: 2 });
551
- if (await fs3.pathExists(TEMP_MEM_FILE)) {
552
- try {
553
- const temp = await fs3.readJson(TEMP_MEM_FILE);
554
- if (temp[id]) {
555
- delete temp[id];
556
- await fs3.writeJson(TEMP_MEM_FILE, temp, { spaces: 2 });
557
- }
558
- } catch (e) {
559
- }
564
+ const temp = readEncryptedJson(TEMP_MEM_FILE, {});
565
+ if (temp[id]) {
566
+ delete temp[id];
567
+ writeEncryptedJson(TEMP_MEM_FILE, temp);
560
568
  }
561
569
  return history;
562
570
  });
@@ -1278,7 +1286,8 @@ var getAIStream = async function* (modelName, history, settings, steeringCallbac
1278
1286
  const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
1279
1287
  const mainUserMemories = persistentStorage.map((m) => `- ${m.memory}`).join("\n");
1280
1288
  const janitorUserMemories = persistentStorage.map((m) => `- [${m.id}]: ${m.memory}`).join("\n");
1281
- const systemInstruction = getSystemInstruction(profile, thinkingLevel, mode, systemSettings, otherMemories, mainUserMemories, isMemoryEnabled);
1289
+ const isContext50 = (sessionStats.tokens || 0) >= 54e3;
1290
+ const systemInstruction = getSystemInstruction(profile, thinkingLevel, mode, systemSettings, otherMemories, mainUserMemories, isMemoryEnabled, isContext50);
1282
1291
  const firstUserMsg = `${systemInstruction}
1283
1292
 
1284
1293
  USER_PROMPT: ${agentText}`.trim();
@@ -1520,7 +1529,11 @@ ${boxBottom}
1520
1529
  }
1521
1530
  const cleanResultForAI = result.split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n");
1522
1531
  toolResults.push(`[TOOL_RESULT]: ${cleanResultForAI}`);
1523
- yield { type: "tool_result", content: `[TOOL_RESULT]: ${result}` };
1532
+ let uiContent = `[TOOL_RESULT]: ${result}`;
1533
+ if (toolCall.toolName === "view_file" || toolCall.toolName === "web_scrape") {
1534
+ uiContent = `[TOOL_RESULT]: ${label} (Context Locked for UI Clarity)`;
1535
+ }
1536
+ yield { type: "tool_result", content: uiContent };
1524
1537
  if (toolCall.toolName === "memory" && result.includes("SUCCESS")) {
1525
1538
  yield { type: "memory_updated" };
1526
1539
  }
@@ -1724,13 +1737,11 @@ function ResumeModal({ onSelect, onDelete, onClose }) {
1724
1737
  // src/components/MemoryModal.jsx
1725
1738
  import React7, { useState as useState3, useEffect as useEffect2 } from "react";
1726
1739
  import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
1727
- import path15 from "path";
1728
- var MEMORIES_PATH = path15.join(process.cwd(), "secret", "memories.json");
1729
1740
  function MemoryModal({ onClose }) {
1730
1741
  const [memories, setMemories] = useState3([]);
1731
1742
  const [selectedIndex, setSelectedIndex] = useState3(0);
1732
1743
  const loadMemories = () => {
1733
- const data = readEncryptedJson(MEMORIES_PATH, []);
1744
+ const data = readEncryptedJson(MEMORIES_FILE, []);
1734
1745
  setMemories(data);
1735
1746
  };
1736
1747
  useEffect2(() => {
@@ -1743,7 +1754,7 @@ function MemoryModal({ onClose }) {
1743
1754
  if (input === "x" && memories.length > 0) {
1744
1755
  const idToDelete = memories[selectedIndex].id;
1745
1756
  const updated = memories.filter((m) => m.id !== idToDelete);
1746
- writeEncryptedJson(MEMORIES_PATH, updated);
1757
+ writeEncryptedJson(MEMORIES_FILE, updated);
1747
1758
  setMemories(updated);
1748
1759
  if (selectedIndex >= updated.length && updated.length > 0) {
1749
1760
  setSelectedIndex(updated.length - 1);
@@ -1851,6 +1862,7 @@ function App() {
1851
1862
  const [messages, setMessages] = useState4([
1852
1863
  { id: "welcome", role: "system", text: FLUX_LOGO + "\n\n\u{1F30A}\u26A1 Welcome to Flux Flow! Type /help for commands.\n" }
1853
1864
  ]);
1865
+ const queuedPromptRef = useRef(null);
1854
1866
  const [completedIndex, setCompletedIndex] = useState4(1);
1855
1867
  useInput3((inputText, key) => {
1856
1868
  if (key.escape) {
@@ -1938,6 +1950,7 @@ function App() {
1938
1950
  if (isProcessing) {
1939
1951
  const hintText = absoluteClean.trim();
1940
1952
  setQueuedPrompt(hintText);
1953
+ queuedPromptRef.current = hintText;
1941
1954
  setMessages((prev) => {
1942
1955
  setCompletedIndex(prev.length + 1);
1943
1956
  return [...prev, { id: "hint-" + Date.now(), role: "user", text: `[STEERING HINT: QUEUED]
@@ -2201,9 +2214,19 @@ OUTPUT: ${execOutputRef.current}`;
2201
2214
  }
2202
2215
  },
2203
2216
  async () => {
2204
- if (queuedPrompt) {
2205
- const p = queuedPrompt;
2217
+ if (queuedPromptRef.current) {
2218
+ const p = queuedPromptRef.current;
2206
2219
  setQueuedPrompt(null);
2220
+ queuedPromptRef.current = null;
2221
+ setMessages((prev) => {
2222
+ const newMsgs = [...prev];
2223
+ const hintMsg = newMsgs.reverse().find((m) => m.text?.includes("[STEERING HINT: QUEUED]"));
2224
+ if (hintMsg) {
2225
+ hintMsg.text = hintMsg.text.replace("[STEERING HINT: QUEUED]", "[STEERING HINT: INJECTED]");
2226
+ hintMsg.color = "cyan";
2227
+ }
2228
+ return newMsgs.reverse();
2229
+ });
2207
2230
  return p;
2208
2231
  }
2209
2232
  return null;
@@ -2321,9 +2344,19 @@ OUTPUT: ${execOutputRef.current}`;
2321
2344
  } finally {
2322
2345
  setIsProcessing(false);
2323
2346
  setStatusText(null);
2324
- if (queuedPrompt) {
2325
- setResolutionData(queuedPrompt);
2347
+ if (queuedPromptRef.current) {
2348
+ setResolutionData(queuedPromptRef.current);
2326
2349
  setQueuedPrompt(null);
2350
+ const hintToResolve = queuedPromptRef.current;
2351
+ queuedPromptRef.current = null;
2352
+ setMessages((prev) => {
2353
+ const newMsgs = [...prev];
2354
+ const hintMsg = newMsgs.reverse().find((m) => m.text?.includes("[STEERING HINT: QUEUED]"));
2355
+ if (hintMsg) {
2356
+ hintMsg.text = hintMsg.text.replace("[STEERING HINT: QUEUED]", "[STEERING HINT: FINISHED_TURN]");
2357
+ }
2358
+ return newMsgs.reverse();
2359
+ });
2327
2360
  setActiveView("resolution");
2328
2361
  }
2329
2362
  setMessages((prev) => {
@@ -2803,7 +2836,7 @@ OUTPUT: ${execOutputRef.current}`;
2803
2836
  )))))));
2804
2837
  }
2805
2838
  };
2806
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column" }, messages.slice(0, completedIndex).map((msg, idx) => /* @__PURE__ */ React8.createElement(ChatLayout, { key: msg.id || idx, messages: [msg], showFullThinking }))), /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", padding: 1, width: "100%" }, activeView === "chat" && /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React8.createElement(ChatLayout, { messages: messages.slice(completedIndex), showFullThinking }), activeCommand && /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(TerminalBox, { command: activeCommand, output: execOutput }))), isInitializing ? /* @__PURE__ */ React8.createElement(Box8, { borderStyle: "double", borderColor: "magenta", padding: 1, flexShrink: 0 }, /* @__PURE__ */ React8.createElement(Text8, { color: "magenta" }, "\u{1F30A} Starting Flux Flow...")) : !apiKey ? /* @__PURE__ */ React8.createElement(Box8, { borderStyle: "bold", borderColor: "yellow", padding: 1, flexDirection: "column", flexShrink: 0 }, /* @__PURE__ */ React8.createElement(Text8, { color: "yellow", bold: true }, "\u{1F511} API KEY REQUIRED"), /* @__PURE__ */ React8.createElement(Text8, null, "Please enter your Gemini API Key to initialize the agent's brain."), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "cyan" }, "\u276F "), /* @__PURE__ */ React8.createElement(
2839
+ return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column" }, messages.slice(0, completedIndex).map((msg, idx) => /* @__PURE__ */ React8.createElement(ChatLayout_default, { key: msg.id || idx, messages: [msg], showFullThinking }))), /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", padding: 1, width: "100%" }, activeView === "chat" && /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React8.createElement(ChatLayout_default, { messages: messages.slice(completedIndex), showFullThinking }), activeCommand && /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(TerminalBox, { command: activeCommand, output: execOutput }))), isInitializing ? /* @__PURE__ */ React8.createElement(Box8, { borderStyle: "double", borderColor: "magenta", padding: 1, flexShrink: 0 }, /* @__PURE__ */ React8.createElement(Text8, { color: "magenta" }, "\u{1F30A} Starting Flux Flow...")) : !apiKey ? /* @__PURE__ */ React8.createElement(Box8, { borderStyle: "bold", borderColor: "yellow", padding: 1, flexDirection: "column", flexShrink: 0 }, /* @__PURE__ */ React8.createElement(Text8, { color: "yellow", bold: true }, "\u{1F511} API KEY REQUIRED"), /* @__PURE__ */ React8.createElement(Text8, null, "Please enter your Gemini API Key to initialize the agent's brain."), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "cyan" }, "\u276F "), /* @__PURE__ */ React8.createElement(
2807
2840
  TextInput2,
2808
2841
  {
2809
2842
  value: tempKey,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",