fluxflow-cli 1.10.6 → 1.10.8

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 +49 -11
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -902,7 +902,7 @@ ${mode === "Flux" ? `- FILE TOOLS (path = relative to CWD) -
902
902
  6. [tool:functions.WriteDoc(path="...", content="...")]. A4 Word doc. Proper margins and page breaks
903
903
  7. [tool:functions.Run(command="...")]. Runs a shell command. Destructive/Irreversible ops -> ask user
904
904
  8. [tool:functions.SearchKeyword(keyword="...")]. Global search. Finds definitions/logic without reading every file
905
- 9. [tool:functions.GenerateImage(prompt="...", path="... png", ratio="16:9, 9:16, 1:1, 4:3, 3:4")]. AI images. Usage: Mockups, PDF thumbnails, any visual content
905
+ 9. [tool:functions.GenerateImage(path="... png", prompt="...", ratio="16:9, 9:16, 1:1, 4:3, 3:4")]. AI images. Usage: Mockups, PDF thumbnails, any visual content
906
906
 
907
907
  - VERIFY RESULT CONTENTS. Fix errors. No hallucinations
908
908
  - File tools > code chat
@@ -3503,6 +3503,8 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
3503
3503
  let isStutteringLoop = false;
3504
3504
  let isInitialAttempt = true;
3505
3505
  let accumulatedContext = "";
3506
+ let dedupeBuffer = "";
3507
+ let isDedupeActive = false;
3506
3508
  while (retryCount <= MAX_RETRIES && inStreamRetryCount <= MAX_RETRIES && !success && !TERMINATION_SIGNAL) {
3507
3509
  try {
3508
3510
  if (isInitialAttempt) {
@@ -3512,7 +3514,9 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
3512
3514
  yield { type: "turn_reset", content: true };
3513
3515
  yield { type: "spinner", content: true };
3514
3516
  isInitialAttempt = false;
3515
- accumulatedContext = "";
3517
+ if (inStreamRetryCount === 1) {
3518
+ accumulatedContext = "";
3519
+ }
3516
3520
  }
3517
3521
  const contents = modifiedHistory.filter((msg) => (msg.role === "user" || msg.role === "agent" || msg.role === "system") && !String(msg.id).startsWith("welcome") && !msg.isMeta).map((msg) => {
3518
3522
  const parts = [{ text: msg.text }];
@@ -3583,8 +3587,8 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
3583
3587
  toolCallPointer = 0;
3584
3588
  yield { type: "model_update", content: null };
3585
3589
  yield { type: "status", content: "Working..." };
3586
- let dedupeBuffer = "";
3587
- let isDedupeActive = accumulatedContext.length > 0;
3590
+ dedupeBuffer = "";
3591
+ isDedupeActive = accumulatedContext.length > 0;
3588
3592
  for await (const chunk of stream) {
3589
3593
  if (TERMINATION_SIGNAL) {
3590
3594
  yield { type: "status", content: "Termination Signal Received." };
@@ -3594,7 +3598,7 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
3594
3598
  if (chunk.text) {
3595
3599
  if (isDedupeActive) {
3596
3600
  dedupeBuffer += chunk.text;
3597
- if (dedupeBuffer.length >= 100) {
3601
+ if (dedupeBuffer.length >= 30) {
3598
3602
  let overlapLen = 0;
3599
3603
  const maxPossibleOverlap = Math.min(accumulatedContext.length, dedupeBuffer.length);
3600
3604
  for (let len = maxPossibleOverlap; len > 0; len--) {
@@ -3992,6 +3996,25 @@ ${boxBottom}` };
3992
3996
  success = true;
3993
3997
  await incrementUsage("agent");
3994
3998
  } catch (err) {
3999
+ if (isDedupeActive && dedupeBuffer.length > 0) {
4000
+ let overlapLen = 0;
4001
+ const maxPossibleOverlap = Math.min(accumulatedContext.length, dedupeBuffer.length);
4002
+ for (let len = maxPossibleOverlap; len > 0; len--) {
4003
+ if (accumulatedContext.endsWith(dedupeBuffer.substring(0, len))) {
4004
+ overlapLen = len;
4005
+ break;
4006
+ }
4007
+ }
4008
+ const cleanText = dedupeBuffer.substring(overlapLen);
4009
+ if (cleanText) {
4010
+ const dedupeClean = cleanText.replace(/^\s*<(think|thought)>[\s\S]*?<\/(think|thought)>\s*/gi, "").replace(/^\s*<(think|thought)>\s*/gi, "");
4011
+ if (dedupeClean) {
4012
+ turnText += dedupeClean;
4013
+ }
4014
+ }
4015
+ isDedupeActive = false;
4016
+ dedupeBuffer = "";
4017
+ }
3995
4018
  const errMsg = err.status || err.error && err.error.message || String(err);
3996
4019
  const errLog = String(err);
3997
4020
  const date = (/* @__PURE__ */ new Date()).toLocaleString();
@@ -4009,16 +4032,31 @@ ${boxBottom}` };
4009
4032
  throw err;
4010
4033
  }
4011
4034
  }
4012
- if (turnText.trim().length > 0 || accumulatedContext.length > 0) {
4035
+ if (turnText.trim().length > 0 || inStreamRetryCount > 1) {
4013
4036
  if (inStreamRetryCount <= MAX_RETRIES) {
4014
4037
  inStreamRetryCount++;
4015
4038
  const waitTime = Math.min(1e3 * Math.pow(2, inStreamRetryCount - 1), 24e3);
4016
- modifiedHistory.push({ role: "agent", text: turnText });
4017
- if (toolResults.length > 0) {
4018
- toolResults.forEach((tr) => modifiedHistory.push(tr));
4039
+ if (turnText.trim().length > 0) {
4040
+ modifiedHistory.push({ role: "agent", text: turnText });
4041
+ const recoveryText = "[SYSTEM: STREAM RECOVERY]\n- SEAMLESS CONTINUATION: Resume immediately. Pick up from last words with zero gap/disruption.\n- NO REPETITION: Do not repeat any text already written.\n- NO RE-THINK: Do not restart or open <think> if reasoning already started.\n- MID-TOOL SAFETY: If cutoff was mid-tool call, restart that tool call from start.\n- STEALTH: Do not mention/apologize for cutoff.\n- KEEP LENGTH: Maintain standard depth/length.";
4042
+ if (toolResults.length > 0) {
4043
+ toolResults.forEach((tr, idx) => {
4044
+ if (idx === toolResults.length - 1) {
4045
+ modifiedHistory.push({
4046
+ ...tr,
4047
+ text: `${tr.text}
4048
+
4049
+ ${recoveryText}`
4050
+ });
4051
+ } else {
4052
+ modifiedHistory.push(tr);
4053
+ }
4054
+ });
4055
+ } else {
4056
+ modifiedHistory.push({ role: "user", text: recoveryText });
4057
+ }
4058
+ accumulatedContext += turnText;
4019
4059
  }
4020
- modifiedHistory.push({ role: "user", text: "[SYSTEM] Response got cut for internal error, continue from checkpoint seamlessly, DON'T repeat what you already said! PICK UP FROM THE WORD IN A WAY THAT USER SHOULD NOT NOTICE ANY CUTOFF. Rules:\n- Do not reuse <think> if the thinking already started just continue from the word and end it properly.\n- If the cutoff was in middle of a tool call, start the tool call from start.\n- Visually the new pickup and continuation should look natual sentence flow.\n- Dont mention about the cutoff.\n- DON'T try to think shorter, keep length standard." });
4021
- accumulatedContext += turnText;
4022
4060
  for (let i = waitTime / 1e3; i > 0; i--) {
4023
4061
  yield { type: "status", content: `Error Occured. Recovering Stream (${inStreamRetryCount}/${MAX_RETRIES}) [${i}s]...` };
4024
4062
  await new Promise((resolve) => setTimeout(resolve, 1e3));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.10.6",
3
+ "version": "1.10.8",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",