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.
- package/dist/fluxflow.js +57 -24
- 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
|
-
|
|
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
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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 (
|
|
2205
|
-
const p =
|
|
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 (
|
|
2325
|
-
setResolutionData(
|
|
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(
|
|
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,
|