fluxflow-cli 1.12.4 → 1.12.6
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 +53 -31
- package/package.json +1 -1
package/dist/fluxflow.js
CHANGED
|
@@ -989,16 +989,23 @@ var init_janitor_tools = __esm({
|
|
|
989
989
|
Your tool syntax is: '[tool:functions.ToolName(args...)]'
|
|
990
990
|
|
|
991
991
|
-- CHAT MANAGEMENT TOOLS (MUST CALL THESE 2 TOOLS ALWAYS) --
|
|
992
|
-
[tool:functions.Chat(title=
|
|
993
|
-
[tool:functions.Memory(action=
|
|
992
|
+
[tool:functions.Chat(title="<short creative title of FULL conversation in 3-5 words>")]. Consider full chat context to generate title NOT just latest message.
|
|
993
|
+
[tool:functions.Memory(action="temp", content="<summary of the user prompt & model responses ONLY FROM LATEST PROMPT UNDER 40 WORDS>. [Talked on: <date> <hour>]")]
|
|
994
994
|
|
|
995
|
-
${isMemoryEnabled ? `-- User-specific long-term memory (USE BASED ON CONVERSATION CONTEXT) --
|
|
996
|
-
- Add: [tool:functions.Memory(action=
|
|
997
|
-
- Delete: [tool:functions.Memory(action=
|
|
998
|
-
- Update: [tool:functions.Memory(action=
|
|
995
|
+
${isMemoryEnabled ? `-- User-specific long-term/permanent memory (USE BASED ON CONVERSATION CONTEXT, PROACTIVE USAGE) --
|
|
996
|
+
- Add: [tool:functions.Memory(action="user", method="add", content="<string to add>. [Saved on: <date ONLY>]")]
|
|
997
|
+
- Delete: [tool:functions.Memory(action="user", method="delete", id="<memory id>")]
|
|
998
|
+
- Update: [tool:functions.Memory(action="user", method="update", content-new="string to update", id="<memory id>")]
|
|
999
|
+
|
|
1000
|
+
Explicit Triggers for permanent memory:
|
|
1001
|
+
- User explicitly asks to 'remember' something.
|
|
1002
|
+
- User mentions something important that should be remembered.
|
|
1003
|
+
- User provides information that could be useful for future reference.
|
|
1004
|
+
- User shares personal information or preferences.
|
|
1005
|
+
- User talks about a specific topic that should be remembered.
|
|
999
1006
|
|
|
1000
1007
|
Usage Rules:
|
|
1001
|
-
- Frequency for 'user' action:
|
|
1008
|
+
- Frequency for 'user' action: Based on explicit triggers.
|
|
1002
1009
|
- IF YOU WANT TO SAVE SOMETHING, BUT SIMILAR MEMORY ALREADY EXISTS, USE THE UPDATE METHOD NOT THE ADD METHOD` : ""}`.trim();
|
|
1003
1010
|
}
|
|
1004
1011
|
});
|
|
@@ -1087,8 +1094,8 @@ ${foundFiles.map((f) => `- ${f.name}: ${f.desc}`).join("\n")}
|
|
|
1087
1094
|
Check these first; these files > training data for project consistency. Safety rules apply` : "";
|
|
1088
1095
|
return `${nameStr}${nicknameStr}${userInstrStr}
|
|
1089
1096
|
[SYSTEM (OVERRIDES EVERYTHING)]
|
|
1090
|
-
Identity: Flux Flow (by Kushal Roy Chowdhury). Sassy, Friendly, CLI Agent. No flirting ${mode === "Flux" ? "" : ""}
|
|
1091
|
-
Mode: ${mode}${thinkingLevel !== "Fast" ? "(Thinking Mode)" : ""}. ${mode === "Flux" ? "Goal-oriented" : "Conversational & UX-focused"}
|
|
1097
|
+
Identity: Flux Flow (by Kushal Roy Chowdhury). Sassy, Friendly, Humorous, CLI Agent. No flirting ${mode === "Flux" ? "" : ""}
|
|
1098
|
+
Mode: ${mode}${thinkingLevel !== "Fast" ? "(Thinking Mode)" : ""}. ${mode === "Flux" ? "Goal-oriented, Logical" : "Conversational & UX-focused"}
|
|
1092
1099
|
CWD: ${cwdStr}.${isSystemDir ? " [PROTECTED: ASK BEFORE MODIFYING]" : ""} OS: ${osDetected}${osDetected === "Windows" && mode === "Flux" ? ". PS via CMD" : ""}
|
|
1093
1100
|
High Priority: [SYSTEM], [STEERING HINT]
|
|
1094
1101
|
|
|
@@ -2111,6 +2118,7 @@ var init_memory = __esm({
|
|
|
2111
2118
|
const content = parseArg("content");
|
|
2112
2119
|
const contentNew = parseArg("content-new");
|
|
2113
2120
|
const contentOld = parseArg("content-old");
|
|
2121
|
+
const id = parseArg("id");
|
|
2114
2122
|
const chatId = parseArg("chat-id") || context.chatId || context.sessionId || "default-session";
|
|
2115
2123
|
if (action === "temp") {
|
|
2116
2124
|
if (!content) return "ERROR: Missing 'content' for temp memory.";
|
|
@@ -2130,30 +2138,36 @@ var init_memory = __esm({
|
|
|
2130
2138
|
const memories = readEncryptedJson(MEMORIES_FILE, []);
|
|
2131
2139
|
if (method === "add") {
|
|
2132
2140
|
if (!content) return "ERROR: Missing 'content' for memory addition.";
|
|
2141
|
+
const now = /* @__PURE__ */ new Date();
|
|
2142
|
+
const dateStr = `${now.getDate()}/${now.getMonth() + 1}/${now.getFullYear()}`;
|
|
2143
|
+
const formattedContent = content.includes("[Saved on:") ? content : `${content.trim()} [Saved on: ${dateStr}]`;
|
|
2133
2144
|
const MAX_CHARS = 1024 * 4;
|
|
2134
2145
|
let currentTotalLength = memories.reduce((acc, m) => acc + (m.memory?.length || 0), 0);
|
|
2135
|
-
while (memories.length > 0 && currentTotalLength +
|
|
2146
|
+
while (memories.length > 0 && currentTotalLength + formattedContent.length > MAX_CHARS) {
|
|
2136
2147
|
const removed = memories.shift();
|
|
2137
2148
|
currentTotalLength -= removed.memory?.length || 0;
|
|
2138
2149
|
}
|
|
2139
|
-
const newMemory = { id: `mem-${Date.now().toString(36)}`, memory:
|
|
2150
|
+
const newMemory = { id: `mem-${Date.now().toString(36)}`, memory: formattedContent };
|
|
2140
2151
|
memories.push(newMemory);
|
|
2141
2152
|
writeEncryptedJson(MEMORIES_FILE, memories);
|
|
2142
|
-
return `SUCCESS: Memory added with ID [${newMemory.id}]. (Vault Size: ${currentTotalLength +
|
|
2153
|
+
return `SUCCESS: Memory added with ID [${newMemory.id}]. (Vault Size: ${currentTotalLength + formattedContent.length} chars)`;
|
|
2143
2154
|
}
|
|
2144
2155
|
if (method === "update") {
|
|
2145
|
-
const memId = contentOld;
|
|
2146
|
-
const newText = contentNew;
|
|
2147
|
-
if (!memId || !newText) return "ERROR: Missing '
|
|
2156
|
+
const memId = id || contentOld;
|
|
2157
|
+
const newText = contentNew || content;
|
|
2158
|
+
if (!memId || !newText) return "ERROR: Missing 'id' or content for update.";
|
|
2148
2159
|
const index = memories.findIndex((m) => m.id === memId);
|
|
2149
2160
|
if (index === -1) return `ERROR: Memory ID [${memId}] not found.`;
|
|
2150
|
-
|
|
2161
|
+
const now = /* @__PURE__ */ new Date();
|
|
2162
|
+
const dateStr = `${now.getDate()}/${now.getMonth() + 1}/${now.getFullYear()}`;
|
|
2163
|
+
const formattedText = newText.includes("[Saved on:") ? newText : `${newText.trim()} [Saved on: ${dateStr}]`;
|
|
2164
|
+
memories[index].memory = formattedText;
|
|
2151
2165
|
writeEncryptedJson(MEMORIES_FILE, memories);
|
|
2152
2166
|
return `SUCCESS: Memory [${memId}] updated.`;
|
|
2153
2167
|
}
|
|
2154
2168
|
if (method === "delete") {
|
|
2155
|
-
const memId = content;
|
|
2156
|
-
if (!memId) return "ERROR: Missing '
|
|
2169
|
+
const memId = id || content;
|
|
2170
|
+
if (!memId) return "ERROR: Missing 'id' for deletion.";
|
|
2157
2171
|
const initialLen = memories.length;
|
|
2158
2172
|
const updatedMemories = memories.filter((m) => m.id !== memId);
|
|
2159
2173
|
if (updatedMemories.length === initialLen) return `ERROR: Memory ID [${memId}] not found.`;
|
|
@@ -3510,44 +3524,51 @@ var init_ai = __esm({
|
|
|
3510
3524
|
if (process.stdout.isTTY) {
|
|
3511
3525
|
process.stdout.write(`\x1B]0;Finalizing...\x07`);
|
|
3512
3526
|
}
|
|
3527
|
+
const USER_CONTEXT_LENGTH = 4 * (1024 * 2);
|
|
3528
|
+
const AGENT_CONTEXT_LENGTH = 4 * (1024 * 8);
|
|
3513
3529
|
const { onStatus, onMemoryUpdated, onBackgroundIncrement } = callbacks;
|
|
3514
3530
|
const { profile, thinkingLevel, mode, janitorModel, chatId, systemSettings, sessionStats } = settings;
|
|
3515
3531
|
const isMemoryEnabled = systemSettings?.memory !== false;
|
|
3516
3532
|
const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
|
|
3517
3533
|
const janitorUserMemories = persistentStorage.map((m) => `- [${m.id}]: ${m.memory}`).join("\n");
|
|
3518
|
-
const janitorContents = history.slice(-
|
|
3519
|
-
let processedText = msg.text.replace(/\[tool:functions\..*?\]/g, "").replace(/<think>[\s\S]*?<\/think>/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[
|
|
3520
|
-
|
|
3534
|
+
const janitorContents = history.slice(0, -1).filter((msg) => msg.text && !msg.text.includes("[TOOL RESULT]") && !msg.text.includes("OBSERVATION:") && !msg.isMeta && !msg.isLogo && !String(msg.id).startsWith("welcome") && !String(msg.id).startsWith("logo")).slice(-18).map((msg) => {
|
|
3535
|
+
let processedText = msg.text.replace(/\[tool:functions\..*?\]/g, "").replace(/<think>[\s\S]*?<\/think>/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[METADATA \(PRIORITY: DYNAMIC\)\] Time: ([^|\n]+)/g, (match, p1) => {
|
|
3536
|
+
return `[METADATA (PRIORITY: DYNAMIC)] Time: ${p1.replace(/:\d{2}/g, "")}`;
|
|
3537
|
+
}).replace(/\[turn: continue\]/g, "").replace(/\[turn: finish\]/g, "").replace(/\[TOOL RESULTS\]/g, "").replace(/\[tool results\]/g, "").replace(/\r?\n\r?\n/g, "\n").replace(/\n\n/g, "\n").replace(/\\n\\n/g, "").trim();
|
|
3538
|
+
const limit = msg.role === "user" ? USER_CONTEXT_LENGTH : AGENT_CONTEXT_LENGTH;
|
|
3521
3539
|
let truncatedText = processedText.substring(0, limit);
|
|
3522
3540
|
if (processedText.length > limit) {
|
|
3523
3541
|
truncatedText += "\n... (truncated) ...";
|
|
3524
3542
|
}
|
|
3543
|
+
const prefix = msg.role === "user" ? truncatedText.startsWith("[USER]") ? "" : "[USER]: " : truncatedText.startsWith("[AGENT]") ? "" : "[AGENT]: ";
|
|
3525
3544
|
return {
|
|
3526
3545
|
role: msg.role === "user" ? "user" : "model",
|
|
3527
|
-
parts: [{ text: truncatedText }]
|
|
3546
|
+
parts: [{ text: `${prefix}${truncatedText}` }]
|
|
3528
3547
|
};
|
|
3529
3548
|
});
|
|
3549
|
+
const isFirstPrompt = history.filter((m) => m.role === "user").length === 1;
|
|
3550
|
+
const hasTitleSignal = agentText.includes("[TITLE-UPDATE]");
|
|
3551
|
+
const thisHas80pChanceOfBeingTrue = Math.random() < 0.8;
|
|
3552
|
+
const needTitle = isFirstPrompt || hasTitleSignal || thisHas80pChanceOfBeingTrue;
|
|
3530
3553
|
const cleanedFullResponse = fullAgentTextRaw.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
|
|
3531
3554
|
const janitorPrompt = getJanitorInstruction(
|
|
3532
|
-
agentText,
|
|
3533
|
-
cleanedFullResponse,
|
|
3534
3555
|
janitorUserMemories,
|
|
3535
3556
|
isMemoryEnabled,
|
|
3536
|
-
|
|
3557
|
+
needTitle
|
|
3537
3558
|
);
|
|
3538
|
-
let agentRes = `${cleanedFullResponse.replace(/\[tool:functions\..*?\]/g, "").replace(/<think>.*<\/think>/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[turn: continue\]/g, "").replace(/\[turn: finish\]/g, "").replace(/\[TOOL RESULTS\]/g, "").replace(/\[tool results\]/g, "").substring(0,
|
|
3539
|
-
if (agentRes.length >
|
|
3559
|
+
let agentRes = `${cleanedFullResponse.replace(/\[tool:functions\..*?\]/g, "").replace(/<think>.*<\/think>/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[turn: continue\]/g, "").replace(/\[turn: finish\]/g, "").replace(/\[TOOL RESULTS\]/g, "").replace(/\[tool results\]/g, "").substring(0, AGENT_CONTEXT_LENGTH)}`;
|
|
3560
|
+
if (agentRes.length > AGENT_CONTEXT_LENGTH) {
|
|
3540
3561
|
agentRes += "\n... (truncated) ...";
|
|
3541
3562
|
}
|
|
3542
3563
|
let originalTextProcessed = agentText.replace(/\[Prompted on:.*?\]/g, "").trim();
|
|
3543
3564
|
agentRes = agentRes.replace(/\r?\n\r?\n/g, "\n").replace(/\n\n/g, "\n").replace(/\\n\\n/g, "").trim();
|
|
3544
|
-
let userPrompt = `[USER]: ${originalTextProcessed.substring(0,
|
|
3545
|
-
${originalTextProcessed.length >
|
|
3565
|
+
let userPrompt = `[USER]: ${originalTextProcessed.substring(0, USER_CONTEXT_LENGTH)}
|
|
3566
|
+
${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n" : ""}
|
|
3546
3567
|
[AGENT (current turn)]: ${agentRes}`;
|
|
3547
3568
|
janitorContents.push({ role: "user", parts: [{ text: userPrompt }] });
|
|
3548
3569
|
let finalSynthesis = "";
|
|
3549
3570
|
let attempts = 0;
|
|
3550
|
-
const MAX_JANITOR_RETRIES =
|
|
3571
|
+
const MAX_JANITOR_RETRIES = 12;
|
|
3551
3572
|
while (attempts <= MAX_JANITOR_RETRIES) {
|
|
3552
3573
|
if (process.stdout.isTTY) {
|
|
3553
3574
|
process.stdout.write(`\x1B]0;Retrying Memory (${attempts + 1})...\x07`);
|
|
@@ -4737,7 +4758,8 @@ function MemoryModal({ onClose }) {
|
|
|
4737
4758
|
}
|
|
4738
4759
|
});
|
|
4739
4760
|
const cleanDisplay = (text) => {
|
|
4740
|
-
|
|
4761
|
+
if (!text) return "";
|
|
4762
|
+
return text.replace(/\[Saved on: .*?\]/g, "").replace(/\\+'/g, "'").trim();
|
|
4741
4763
|
};
|
|
4742
4764
|
const s = emojiSpace(2);
|
|
4743
4765
|
return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: 80 }, /* @__PURE__ */ React8.createElement(Box8, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "cyan", bold: true }, "\u{1F9E0} AGENT MEMORY: LONG-TERM KNOWLEDGE")), !isMemoryOn && memories.length > 0 ? /* @__PURE__ */ React8.createElement(Box8, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React8.createElement(Text8, { italic: true, color: "gray" }, "Memory is currently Off...")) : memories.length === 0 ? /* @__PURE__ */ React8.createElement(Box8, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React8.createElement(Text8, { italic: true, color: "gray" }, isMemoryOn ? "Learning..." : "Memory not available...")) : /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column" }, memories.map((mem, idx) => {
|