fluxflow-cli 1.0.13 → 1.1.0

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 CHANGED
@@ -1,15 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.jsx
4
- import React9 from "react";
4
+ import React10 from "react";
5
5
  import { render } from "ink";
6
6
 
7
7
  // src/app.jsx
8
- import React8, { useState as useState4, useEffect as useEffect3, useRef, useMemo } from "react";
9
- import { Box as Box8, Text as Text8, useInput as useInput3, useStdout, Static } from "ink";
8
+ import React9, { useState as useState5, useEffect as useEffect3, useRef, useMemo } from "react";
9
+ import { Box as Box9, Text as Text9, useInput as useInput4, useStdout } from "ink";
10
10
  import fs14 from "fs-extra";
11
+ import { exec } from "child_process";
11
12
  import { MultilineInput } from "ink-multiline-input";
12
- import TextInput2 from "ink-text-input";
13
+ import TextInput3 from "ink-text-input";
13
14
 
14
15
  // src/components/ChatLayout.jsx
15
16
  import React2 from "react";
@@ -18,15 +19,15 @@ import { Box as Box2, Text as Text2 } from "ink";
18
19
  // src/components/TerminalBox.jsx
19
20
  import React from "react";
20
21
  import { Box, Text } from "ink";
21
- var TerminalBox = ({ command, output, completed = false }) => {
22
+ var TerminalBox = React.memo(({ command, output, completed = false }) => {
22
23
  const cleanOutput = (output || "").replace(/\r/g, "").trim();
23
24
  return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: completed ? "#334155" : "cyan", paddingX: 2, paddingY: completed ? 0 : 1, width: "100%" }, /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between" }, /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: completed ? "gray" : "cyan", bold: true }, completed ? "\u{1F3C1} FINISHED:" : "\u26A1 EXECUTING:", " "), /* @__PURE__ */ React.createElement(Text, { color: completed ? "gray" : "white" }, command)), /* @__PURE__ */ React.createElement(Text, { color: completed ? "#475569" : "yellow", bold: true }, completed ? "\u25CF ARCHIVED" : "\u25CF LIVE")), cleanOutput ? /* @__PURE__ */ React.createElement(Box, { marginTop: completed ? 0 : 1, backgroundColor: "#0a0a0a", paddingX: 1 }, /* @__PURE__ */ React.createElement(Text, { color: completed ? "gray" : "green", wrap: "anywhere" }, cleanOutput)) : !completed && /* @__PURE__ */ React.createElement(Box, { marginTop: 1, backgroundColor: "#0a0a0a", paddingX: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "gray", italic: true }, "Waiting for output...")), !completed && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "gray", dimColor: true, italic: true }, "Double-press ESC to terminate if hanging.")));
24
- };
25
+ });
25
26
 
26
27
  // src/components/ChatLayout.jsx
27
28
  var cleanSignals = (text) => {
28
29
  if (!text) return text;
29
- let result = "";
30
+ const parts = [];
30
31
  let i = 0;
31
32
  while (i < text.length) {
32
33
  const trigger = "tool:functions.";
@@ -46,64 +47,27 @@ var cleanSignals = (text) => {
46
47
  }
47
48
  i = j;
48
49
  } else {
49
- result += text[i];
50
+ parts.push(text[i]);
50
51
  i++;
51
52
  }
52
53
  }
53
- return result.replace(/^\[TOOL_RESULT\]:\s*/gi, "").split("\n").filter((line) => !line.trim().startsWith("SUCCESS:") && !line.trim().startsWith("ERROR:")).join("\n").replace(/\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").replace(/\n\s*turn\s*:\s*(continue|finish)\s*$/gi, "").replace(/\n\nResponded on .*/g, "").replace(/\n\n\[Prompted on: .*\]/g, "").trim();
54
+ return parts.join("").replace(/^\[TOOL_RESULT\]:\s*/gi, "").split("\n").filter((line) => !line.trim().startsWith("SUCCESS:") && !line.trim().startsWith("ERROR:")).join("\n").replace(/\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").replace(/\n\s*turn\s*:\s*(continue|finish)\s*$/gi, "").replace(/\n\nResponded on .*/g, "").replace(/\n\n\[Prompted on: .*\]/g, "").replace(/(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)/gi, "\u2192").trim();
54
55
  };
55
- var formatThinkText = (text) => {
56
- const cleaned = cleanSignals(text);
56
+ var formatThinkText = (cleaned) => {
57
57
  if (!cleaned) return null;
58
58
  const lines = cleaned.split("\n").filter((l) => l.trim() !== "");
59
59
  return lines.map((line, i) => {
60
60
  const trimmed = line.trim();
61
61
  if (trimmed.startsWith("**") && trimmed.endsWith("**") || trimmed.startsWith("#")) {
62
- return /* @__PURE__ */ React2.createElement(Box2, { key: i, marginTop: i === 0 ? 0 : 1, marginBottom: 0 }, /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "white" }, trimmed.replace(/\*|#/g, "").trim()));
62
+ return /* @__PURE__ */ React2.createElement(Box2, { key: i, marginTop: i === 0 ? 0 : 1, marginBottom: 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "white" }, trimmed.replace(/\*|#/g, "").trim()));
63
63
  }
64
64
  const isBullet = trimmed.startsWith("*");
65
- return /* @__PURE__ */ React2.createElement(Box2, { key: i, marginLeft: isBullet ? 2 : 0 }, /* @__PURE__ */ React2.createElement(Text2, { italic: true, color: "gray", wrap: "anywhere" }, isBullet ? "\u2022 " : "", trimmed.replace(/^\*|\s\*/g, "").trim()));
65
+ return /* @__PURE__ */ React2.createElement(Box2, { key: i, marginLeft: isBullet ? 2 : 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { italic: true, color: "gray", wrap: "anywhere" }, isBullet ? "\u2022 " : "", trimmed.replace(/^\*|\s\*/g, "").trim()));
66
66
  });
67
67
  };
68
- var CodeRenderer = ({ text }) => {
68
+ var MarkdownText = React2.memo(({ text, color = "white" }) => {
69
69
  if (!text) return null;
70
- if (text.includes("[DIFF_START]")) {
71
- const beforeDiff = text.substring(0, text.indexOf("[DIFF_START]")).trim();
72
- const afterDiff = text.substring(text.indexOf("[DIFF_END]") + 10).trim();
73
- const match = text.match(/\[DIFF_START\]([\s\S]*?)\[DIFF_END\]/);
74
- const diffBody = match ? match[1].trim() : "";
75
- const diffLines = diffBody.split("\n");
76
- return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, beforeDiff && /* @__PURE__ */ React2.createElement(MarkdownText, { text: beforeDiff }), /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", marginTop: 1, backgroundColor: "#1a1a1a", paddingY: 0 }, diffLines.map((line, i) => {
77
- const isContext = line.includes("[UI_CONTEXT]");
78
- const cleanLine = line.replace("[UI_CONTEXT]", "");
79
- const isRemoval = cleanLine.startsWith("-");
80
- const isAddition = cleanLine.startsWith("+");
81
- const parts = cleanLine.substring(1).split("|");
82
- const lineNum = parts[0]?.trim() || "";
83
- const content = parts.slice(1).join("|");
84
- const bgColor = isRemoval ? "#3a0c0c" : isAddition ? "#0c3a1a" : "#1a1a1a";
85
- const textColor = isRemoval ? "#ff4d4d" : isAddition ? "#4dff88" : "white";
86
- return /* @__PURE__ */ React2.createElement(Box2, { key: i, backgroundColor: bgColor, paddingX: 1 }, /* @__PURE__ */ React2.createElement(Box2, { width: 5, flexShrink: 0 }, /* @__PURE__ */ React2.createElement(Text2, { color: isRemoval ? "#cf3a3a" : isAddition ? "#3acf65" : "gray", dimColor: true }, lineNum)), /* @__PURE__ */ React2.createElement(Box2, { width: 2, flexShrink: 0, marginLeft: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: textColor, bold: true }, isRemoval ? "-" : isAddition ? "+" : " ")), /* @__PURE__ */ React2.createElement(Box2, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: textColor, wrap: "anywhere" }, content)));
87
- })), afterDiff && /* @__PURE__ */ React2.createElement(MarkdownText, { text: afterDiff }));
88
- }
89
- if (text.includes("```")) {
90
- const parts = text.split(/(```[\s\S]*?```)/g);
91
- return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, parts.map((part, i) => {
92
- if (part.startsWith("```") && part.endsWith("```")) {
93
- const match = part.match(/```(\w*)\n([\s\S]*?)```/);
94
- const lang = match ? match[1] : "code";
95
- const code = match ? match[2] : part.slice(3, -3);
96
- return /* @__PURE__ */ React2.createElement(Box2, { key: i, flexDirection: "column", marginY: 1, backgroundColor: "#111", borderStyle: "round", borderColor: "#333", paddingX: 1 }, /* @__PURE__ */ React2.createElement(Box2, { alignSelf: "flex-end", marginTop: -1, marginRight: 1 }, /* @__PURE__ */ React2.createElement(Text2, { backgroundColor: "#333", color: "white" }, " ", lang.toUpperCase(), " ")), /* @__PURE__ */ React2.createElement(Box2, { paddingY: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", wrap: "anywhere" }, code.trim())));
97
- }
98
- return /* @__PURE__ */ React2.createElement(MarkdownText, { key: i, text: part });
99
- }));
100
- }
101
- return /* @__PURE__ */ React2.createElement(MarkdownText, { text });
102
- };
103
- var MarkdownText = ({ text, color = "white" }) => {
104
- const cleaned = cleanSignals(text);
105
- if (!cleaned) return null;
106
- const lines = cleaned.split("\n");
70
+ const lines = text.split("\n");
107
71
  return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, lines.map((line, i) => {
108
72
  const trimmed = line.trim();
109
73
  if (trimmed === "---" || trimmed === "***" || trimmed === "___") {
@@ -113,7 +77,7 @@ var MarkdownText = ({ text, color = "white" }) => {
113
77
  if (headingMatch) {
114
78
  const level = headingMatch[1].length;
115
79
  const hText = headingMatch[2];
116
- return /* @__PURE__ */ React2.createElement(Box2, { key: i, marginTop: 1, marginBottom: 0 }, /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: level === 1 ? "cyan" : level === 2 ? "magenta" : "yellow", underline: true }, hText.toUpperCase()));
80
+ return /* @__PURE__ */ React2.createElement(Box2, { key: i, marginTop: 1, marginBottom: 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: level === 1 ? "cyan" : level === 2 ? "magenta" : "yellow", underline: true }, hText.toUpperCase()));
117
81
  }
118
82
  const isUnordered = trimmed.startsWith("* ") || trimmed.startsWith("- ");
119
83
  const isOrdered = /^\d+\.\s/.test(trimmed);
@@ -122,7 +86,7 @@ var MarkdownText = ({ text, color = "white" }) => {
122
86
  content = (isUnordered ? " \u2022 " : "") + trimmed.replace(/^[\*\-\d+\.]+\s/, "");
123
87
  }
124
88
  const parts = content.split(/(\*\*.*?\*\*|\*.*?\*|`.*?`)/g);
125
- return /* @__PURE__ */ React2.createElement(Text2, { key: i, color, wrap: "anywhere" }, parts.map((part, j) => {
89
+ return /* @__PURE__ */ React2.createElement(Box2, { key: i, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color, wrap: "anywhere" }, parts.map((part, j) => {
126
90
  if (part.startsWith("**") && part.endsWith("**")) {
127
91
  return /* @__PURE__ */ React2.createElement(Text2, { key: j, bold: true, color: "white" }, part.slice(2, -2));
128
92
  }
@@ -133,50 +97,109 @@ var MarkdownText = ({ text, color = "white" }) => {
133
97
  return /* @__PURE__ */ React2.createElement(Text2, { key: j, color: "cyan", backgroundColor: "#003333" }, " ", part.slice(1, -1), " ");
134
98
  }
135
99
  return part;
136
- }));
100
+ })));
137
101
  }));
138
- };
139
- function ChatLayout({ messages, showFullThinking }) {
140
- return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, messages.map((msg, idx) => {
141
- const isDiffResult = msg.role === "system" && msg.text.includes("[DIFF_START]");
142
- const isTerminalRecord = msg.isTerminalRecord;
143
- if (msg.role === "system" && msg.text.includes("[TOOL_RESULT]") && !isDiffResult && !isTerminalRecord) return null;
144
- if (isTerminalRecord) {
145
- const cmdMatch = msg.text.match(/COMMAND: (.*)\n/);
146
- const outputMatch = msg.text.match(/OUTPUT: ([\s\S]*)$/);
147
- const cmd = cmdMatch ? cmdMatch[1] : "Unknown";
148
- const outputList = outputMatch ? outputMatch[1] : "";
149
- return /* @__PURE__ */ React2.createElement(Box2, { key: idx, marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(TerminalBox, { command: cmd, output: outputList, completed: true }));
150
- }
151
- let color = "white";
152
- let content = cleanSignals(msg.text);
102
+ });
103
+ var DiffLine = React2.memo(({ line }) => {
104
+ const isContext = line.includes("[UI_CONTEXT]");
105
+ const cleanLine = line.replace("[UI_CONTEXT]", "");
106
+ const isRemoval = cleanLine.startsWith("-");
107
+ const isAddition = cleanLine.startsWith("+");
108
+ const parts = cleanLine.substring(1).split("|");
109
+ const lineNum = parts[0]?.trim() || "";
110
+ const content = parts.slice(1).join("|");
111
+ const bgColor = isRemoval ? "#3a0c0c" : isAddition ? "#0c3a1a" : "#1a1a1a";
112
+ const textColor = isRemoval ? "#ff4d4d" : isAddition ? "#4dff88" : "white";
113
+ return /* @__PURE__ */ React2.createElement(Box2, { backgroundColor: bgColor, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { width: 5, flexShrink: 0 }, /* @__PURE__ */ React2.createElement(Text2, { color: isRemoval ? "#cf3a3a" : isAddition ? "#3acf65" : "gray", dimColor: true }, lineNum)), /* @__PURE__ */ React2.createElement(Box2, { width: 2, flexShrink: 0, marginLeft: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: textColor, bold: true }, isRemoval ? "-" : isAddition ? "+" : " ")), /* @__PURE__ */ React2.createElement(Box2, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: textColor, wrap: "anywhere" }, content)));
114
+ });
115
+ var DiffBlock = React2.memo(({ text }) => {
116
+ const beforeDiff = text.substring(0, text.indexOf("[DIFF_START]")).trim();
117
+ const afterDiff = text.substring(text.indexOf("[DIFF_END]") + 10).trim();
118
+ const match = text.match(/\[DIFF_START\]([\s\S]*?)\[DIFF_END\]/);
119
+ const diffBody = match ? match[1].trim() : "";
120
+ const diffLines = diffBody.split("\n");
121
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, beforeDiff && /* @__PURE__ */ React2.createElement(MarkdownText, { text: beforeDiff }), /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", marginTop: 1, backgroundColor: "#1a1a1a", paddingY: 0, width: "100%" }, diffLines.map((line, i) => /* @__PURE__ */ React2.createElement(DiffLine, { key: i, line }))), afterDiff && /* @__PURE__ */ React2.createElement(MarkdownText, { text: afterDiff }));
122
+ });
123
+ var CodeRenderer = React2.memo(({ text }) => {
124
+ if (!text) return null;
125
+ if (text.includes("[DIFF_START]")) {
126
+ return /* @__PURE__ */ React2.createElement(DiffBlock, { text });
127
+ }
128
+ if (text.includes("```")) {
129
+ const parts = text.split(/(```[\s\S]*?```)/g);
130
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, parts.map((part, i) => {
131
+ if (part.startsWith("```") && part.endsWith("```")) {
132
+ const match = part.match(/```(\w*)\n([\s\S]*?)```/);
133
+ const lang = match ? match[1] : "code";
134
+ const code = match ? match[2] : part.slice(3, -3);
135
+ return /* @__PURE__ */ React2.createElement(Box2, { key: i, flexDirection: "column", marginY: 1, backgroundColor: "#111", borderStyle: "round", borderColor: "#333", paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { alignSelf: "flex-end", marginTop: -1, marginRight: 1 }, /* @__PURE__ */ React2.createElement(Text2, { backgroundColor: "#333", color: "white" }, " ", lang.toUpperCase(), " ")), /* @__PURE__ */ React2.createElement(Box2, { paddingY: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", wrap: "anywhere" }, code.trim())));
136
+ }
137
+ return /* @__PURE__ */ React2.createElement(MarkdownText, { key: i, text: part });
138
+ }));
139
+ }
140
+ return /* @__PURE__ */ React2.createElement(MarkdownText, { text });
141
+ });
142
+ var MessageItem = React2.memo(({ msg, showFullThinking }) => {
143
+ const isDiffResult = msg.role === "system" && msg.text.includes("[DIFF_START]");
144
+ const isTerminalRecord = msg.isTerminalRecord;
145
+ if (msg.role === "system" && msg.text.includes("[TOOL_RESULT]") && !isDiffResult && !isTerminalRecord) return null;
146
+ if (msg.isAskRecord) {
147
+ const selectionMatch = msg.text.match(/Selection: (.*)/);
148
+ const selection = selectionMatch ? selectionMatch[1] : "No selection";
149
+ return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", bold: true, underline: true }, "\u{1F4AC} ASK USER"), /* @__PURE__ */ React2.createElement(Box2, { marginTop: 0 }, /* @__PURE__ */ React2.createElement(Text2, { color: "white" }, "Selection: ", /* @__PURE__ */ React2.createElement(Text2, { color: "yellow", bold: true }, selection)))));
150
+ }
151
+ if (msg.isUpdateNotification) {
152
+ return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color: "yellow", bold: true, underline: true }, "\u{1F680} UPDATE AVAILABLE"), /* @__PURE__ */ React2.createElement(Box2, { marginTop: 1 }, /* @__PURE__ */ React2.createElement(CodeRenderer, { text: msg.text }))));
153
+ }
154
+ if (isTerminalRecord) {
155
+ const cmdMatch = msg.text.match(/COMMAND: (.*)\n/);
156
+ const outputMatch = msg.text.match(/OUTPUT: ([\s\S]*)$/);
157
+ const cmd = cmdMatch ? cmdMatch[1] : "Unknown";
158
+ const outputList = outputMatch ? outputMatch[1] : "";
159
+ return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(TerminalBox, { command: cmd, output: outputList, completed: true }));
160
+ }
161
+ const content = React2.useMemo(() => cleanSignals(msg.text), [msg.text]);
162
+ const finalContent = React2.useMemo(() => {
153
163
  if (msg.role === "think" && !showFullThinking) {
154
- content = content.split("\n").filter((line) => {
164
+ const lines = content.split("\n").filter((line) => {
155
165
  const trimmed = line.trim();
156
166
  const isHeading = trimmed.startsWith("# ");
157
167
  const isActionStep = trimmed.startsWith("**") && trimmed.endsWith("**");
158
168
  return isHeading || isActionStep;
159
- }).join("\n");
160
- if (!content.trim()) content = "*Reasoning...*";
169
+ });
170
+ if (lines.length === 0) return "*Reasoning...*";
171
+ return lines.join("\n");
161
172
  }
162
- return /* @__PURE__ */ React2.createElement(Box2, { key: idx, marginBottom: 1, flexDirection: "column", flexShrink: 0, width: "100%" }, msg.role === "user" ? /* @__PURE__ */ React2.createElement(
163
- Box2,
164
- {
165
- backgroundColor: "#262626",
166
- paddingX: 1,
167
- paddingY: 1,
168
- width: "100%",
169
- flexDirection: "column"
170
- },
171
- content.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\\\n/g, "\n").replace(/\\$/, "").split("\n").map((line, lineIdx) => /* @__PURE__ */ React2.createElement(Box2, { key: lineIdx, flexDirection: "row" }, /* @__PURE__ */ React2.createElement(Box2, { flexShrink: 0, width: 2 }, /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "white" }, lineIdx === 0 ? "\u276F" : " ")), /* @__PURE__ */ React2.createElement(Box2, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: msg.color || "white", wrap: "anywhere" }, line))))
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
- }));
174
- }
173
+ return content;
174
+ }, [content, msg.role, showFullThinking]);
175
+ return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, flexDirection: "column", flexShrink: 0, width: "100%" }, msg.role === "user" ? /* @__PURE__ */ React2.createElement(
176
+ Box2,
177
+ {
178
+ backgroundColor: "#262626",
179
+ paddingX: 1,
180
+ paddingY: 1,
181
+ width: "100%",
182
+ flexDirection: "column"
183
+ },
184
+ finalContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\\\n/g, "\n").replace(/\\$/, "").split("\n").map((line, lineIdx) => /* @__PURE__ */ React2.createElement(Box2, { key: lineIdx, flexDirection: "row", width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexShrink: 0, width: 2 }, /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "white" }, lineIdx === 0 ? "\u276F" : " ")), /* @__PURE__ */ React2.createElement(Box2, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: msg.color || "white", wrap: "anywhere" }, line))))
185
+ ) : msg.role === "think" ? /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", marginTop: 1, paddingX: 1, width: "100%" }, /* @__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", width: "100%" }, formatThinkText(finalContent))) : /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", paddingX: 1, marginTop: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(CodeRenderer, { text: finalContent }), msg.memoryUpdated && /* @__PURE__ */ React2.createElement(Box2, { marginTop: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color: "yellow", italic: true }, "\u2728 [Memory Updated]"))));
186
+ });
187
+ var ChatLayout = React2.memo(({ messages, showFullThinking }) => {
188
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, messages.map((msg, idx) => /* @__PURE__ */ React2.createElement(
189
+ MessageItem,
190
+ {
191
+ key: msg.id || idx,
192
+ msg,
193
+ showFullThinking
194
+ }
195
+ )));
196
+ });
197
+ var ChatLayout_default = ChatLayout;
175
198
 
176
199
  // src/components/StatusBar.jsx
177
200
  import React3 from "react";
178
201
  import { Box as Box3, Text as Text3 } from "ink";
179
- function StatusBar({ mode, thinkingLevel, tokens = "0.0k", chatId = "NEW-SESSION", isMemoryEnabled = true }) {
202
+ var StatusBar = React3.memo(({ mode, thinkingLevel, tokens = "0.0k", chatId = "NEW-SESSION", isMemoryEnabled = true }) => {
180
203
  const modeColor = mode === "Flux" ? "yellow" : "cyan";
181
204
  const modeIcon = mode === "Flux" ? "\u26A1" : "\u{1F30A}";
182
205
  const memStatus = isMemoryEnabled ? "ON" : "OFF";
@@ -194,7 +217,8 @@ function StatusBar({ mode, thinkingLevel, tokens = "0.0k", chatId = "NEW-SESSION
194
217
  /* @__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
218
  /* @__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
219
  );
197
- }
220
+ });
221
+ var StatusBar_default = StatusBar;
198
222
 
199
223
  // src/components/CommandMenu.jsx
200
224
  import React4 from "react";
@@ -250,6 +274,49 @@ function ProfileForm({ onSave, onCancel }) {
250
274
  )), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true, marginTop: 1 }, "(Press Enter to submit, type /cancel to abort)"));
251
275
  }
252
276
 
277
+ // src/components/AskUserModal.jsx
278
+ import React6, { useState as useState2 } from "react";
279
+ import { Box as Box6, Text as Text6, useInput } from "ink";
280
+ import TextInput2 from "ink-text-input";
281
+ var AskUserModal = ({ question, options, onResolve }) => {
282
+ const [isSuggestingElse, setIsSuggestingElse] = useState2(false);
283
+ const [customInput, setCustomInput] = useState2("");
284
+ const [selectedIndex, setSelectedIndex] = useState2(0);
285
+ const allOptions = [...options, { id: "CUSTOM", label: "Suggest something else...", description: "Provide a custom response" }];
286
+ useInput((input, key) => {
287
+ if (isSuggestingElse) return;
288
+ if (key.leftArrow || key.upArrow) {
289
+ setSelectedIndex((prev) => Math.max(0, prev - 1));
290
+ }
291
+ if (key.rightArrow || key.downArrow) {
292
+ setSelectedIndex((prev) => Math.min(allOptions.length - 1, prev + 1));
293
+ }
294
+ if (key.return) {
295
+ const selected = allOptions[selectedIndex];
296
+ if (selected.id === "CUSTOM") {
297
+ setIsSuggestingElse(true);
298
+ } else {
299
+ onResolve(selected.label);
300
+ }
301
+ }
302
+ });
303
+ if (isSuggestingElse) {
304
+ return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan", bold: true, underline: true }, "\u{1F4AC} SUGGEST SOMETHING ELSE"), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { italic: true, color: "gray" }, "Replying to: ", question)), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, flexDirection: "row" }, /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, "\u276F "), /* @__PURE__ */ React6.createElement(
305
+ TextInput2,
306
+ {
307
+ value: customInput,
308
+ onChange: setCustomInput,
309
+ onSubmit: () => onResolve(customInput)
310
+ }
311
+ )), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", dimColor: true, italic: true }, "(Press Enter to send)")));
312
+ }
313
+ return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan", bold: true, underline: true }, "\u{1F4AC} ASK USER"), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { bold: true }, question)), /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "row", flexWrap: "wrap", width: "100%" }, options.map((opt, idx) => {
314
+ const isSelected = idx === selectedIndex;
315
+ return /* @__PURE__ */ React6.createElement(Box6, { key: opt.id, flexDirection: "column", marginRight: 4, marginBottom: 1, width: 30 }, /* @__PURE__ */ React6.createElement(Text6, { color: isSelected ? "cyan" : "white", bold: isSelected }, isSelected ? "\u276F " : " ", opt.label), opt.description && /* @__PURE__ */ React6.createElement(Box6, { marginLeft: 4 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", italic: true, dimColor: true }, opt.description)));
316
+ })), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: selectedIndex === options.length ? "cyan" : "white", bold: selectedIndex === options.length }, selectedIndex === options.length ? "\u276F " : " ", "Suggest something else...")), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", dimColor: true, italic: true }, "(Use Arrows to navigate, Enter to confirm)")));
317
+ };
318
+ var AskUserModal_default = AskUserModal;
319
+
253
320
  // src/app.jsx
254
321
  import gradient from "gradient-string";
255
322
 
@@ -343,6 +410,7 @@ tool:functions.tool_name(arguments)
343
410
  - WEB TOOLS (Available in Flux & Flow) -
344
411
  1. Web Search: tool:functions.web_search(query="<query>", limit=number). Find info. limit is optional (3-10, default 10). If user asks about something that is not in your training data, proactively use this tool to find the information.Winder search recomemded (limit = 10) when exploring a topic.
345
412
  2. Web Scrape: tool:functions.web_scrape(url="<url>"). provides detail from a URL.
413
+ 3. Ask User: tool:functions.ask(question="...", optionA="Option::Desc", optionB="Option::Desc"). Use this ONLY when you reach a decision point with multiple valid paths and need user preference to proceed / confirmation. This allows you to pause for guidance without ending your task loop. Format options as 'Short Label::Detailed Description'. You can provide 2 - 4 options (optionA, optionB, optionC, optionD). Tool can also return result as none of the 4 if user write custom one.
346
414
  ${mode === "Flux" ? `
347
415
  - DEV & FILE TOOLS (Available in FLUX MODE ONLY) -
348
416
  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.
@@ -356,7 +424,7 @@ ${mode === "Flux" ? `
356
424
  Results will be provided in the next loop as: [TOOL_RESULT]: [content]
357
425
  WHEN CALLING TOOLS, YOU **MUST** END YOUR RESPONSE WITH '[turn: continue]' AFTER CALLING FUNCTIONS.
358
426
  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
- 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.
427
+ 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. Even in your <think> ... </think> tags, do not use the 'tool:' prefix when planning to select a tool.
360
428
  -- END FUNCTION CALLING PROTOCOL --`.trim();
361
429
 
362
430
  // src/data/janitor_tools.js
@@ -471,7 +539,8 @@ YOU ARE A SILENT BACKGROUND SYSTEM PROCESS. YOU HAVE NO MOUTH. YOUR ONLY OUTPUT
471
539
  1. OUTPUT ONLY 'tool:functions.xxx' CALLS.
472
540
  2. DO NOT EXPLAIN. DO NOT SUMMARIZE AGENT RAWS. DO NOT TALK TO THE USER.
473
541
  3. NON-TOOL TEXT WILL BREAK THE SYSTEM.
474
- 4.
542
+ 4. DO NOT REPEAT AGENT RAWS IN YOUR RESPONSE.
543
+ 5. IF YOU GET ONLY USER RESPONSE AND NO AGENT RAWS, THEN JUST USE TEMP MEMORY TO LOG THE SUMMARY OF USER QUERY.
475
544
 
476
545
  YOUR JOB: Analyze the 'User prompt' and 'Agent Raws' to extract facts for long-term memory or handle system tasks.
477
546
  ${isMemoryEnabled ? `If user tell something that is important (like, hobbies, preferences, facts about user, hates, likes, etc) to know user better over time, use long term memory tools.` : ""}
@@ -1156,6 +1225,40 @@ ${formatted}${footer}`;
1156
1225
  }
1157
1226
  };
1158
1227
 
1228
+ // src/tools/ask_user.js
1229
+ var ask_user = async (args, context) => {
1230
+ const parsed = parseArgs(args);
1231
+ const { question } = parsed;
1232
+ if (!question) return 'ERROR: Missing "question" argument for ask_user.';
1233
+ if (!context.onAskUser) return "ERROR: onAskUser callback not provided in tool context.";
1234
+ const options = [];
1235
+ Object.keys(parsed).forEach((key) => {
1236
+ if (key.startsWith("option")) {
1237
+ const val = parsed[key];
1238
+ if (typeof val === "string" && val.includes("::")) {
1239
+ const [label, desc] = val.split("::");
1240
+ options.push({
1241
+ id: key,
1242
+ label: label.trim(),
1243
+ description: desc.trim()
1244
+ });
1245
+ } else {
1246
+ options.push({
1247
+ id: key,
1248
+ label: String(val).trim(),
1249
+ description: ""
1250
+ });
1251
+ }
1252
+ }
1253
+ });
1254
+ try {
1255
+ const choice = await context.onAskUser(question, options);
1256
+ return `USER CHOOSE: ${choice}`;
1257
+ } catch (err) {
1258
+ return `ERROR: Failed to get user input: ${err.message}`;
1259
+ }
1260
+ };
1261
+
1159
1262
  // src/utils/tools.js
1160
1263
  var TOOL_MAP = {
1161
1264
  web_search,
@@ -1167,7 +1270,8 @@ var TOOL_MAP = {
1167
1270
  write_file,
1168
1271
  update_file,
1169
1272
  exec_command,
1170
- read_folder
1273
+ read_folder,
1274
+ ask: ask_user
1171
1275
  };
1172
1276
  var dispatchTool = async (toolName, args, context = {}) => {
1173
1277
  const tool = TOOL_MAP[toolName];
@@ -1386,7 +1490,7 @@ USER_PROMPT: ${agentText}`.trim();
1386
1490
  } else if (toolCall.toolName === "write_file" || toolCall.toolName === "update_file") {
1387
1491
  const action = toolCall.toolName === "write_file" ? "WRITING" : "PATCHING";
1388
1492
  label = `\u{1F4BE} ${action} FILE: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
1389
- } else if (toolCall.toolName === "exec_command") {
1493
+ } else if (toolCall.toolName === "exec_command" || toolCall.toolName === "ask") {
1390
1494
  label = "";
1391
1495
  } else {
1392
1496
  label = `EXECUTING ${toolCall.toolName}`.toUpperCase();
@@ -1472,7 +1576,8 @@ ${boxBottom}
1472
1576
  const result = await dispatchTool(toolCall.toolName, toolCall.args, {
1473
1577
  chatId,
1474
1578
  history,
1475
- onChunk: (chunk) => settings.onExecChunk ? settings.onExecChunk(chunk) : null
1579
+ onChunk: (chunk) => settings.onExecChunk ? settings.onExecChunk(chunk) : null,
1580
+ onAskUser: settings.onAskUser
1476
1581
  });
1477
1582
  if (toolCall.toolName === "exec_command" && settings.onExecEnd) {
1478
1583
  await new Promise((resolve) => setTimeout(resolve, 800));
@@ -1660,12 +1765,12 @@ var saveSettings = async (settings) => {
1660
1765
  };
1661
1766
 
1662
1767
  // src/components/ResumeModal.jsx
1663
- import React6, { useState as useState2, useEffect } from "react";
1664
- import { Box as Box6, Text as Text6, useInput } from "ink";
1768
+ import React7, { useState as useState3, useEffect } from "react";
1769
+ import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
1665
1770
  function ResumeModal({ onSelect, onDelete, onClose }) {
1666
- const [history, setHistory] = useState2({});
1667
- const [keys, setKeys] = useState2([]);
1668
- const [selectedIndex, setSelectedIndex] = useState2(0);
1771
+ const [history, setHistory] = useState3({});
1772
+ const [keys, setKeys] = useState3([]);
1773
+ const [selectedIndex, setSelectedIndex] = useState3(0);
1669
1774
  useEffect(() => {
1670
1775
  const fetchHistory = async () => {
1671
1776
  const h = await loadHistory();
@@ -1674,7 +1779,7 @@ function ResumeModal({ onSelect, onDelete, onClose }) {
1674
1779
  };
1675
1780
  fetchHistory();
1676
1781
  }, []);
1677
- useInput((input, key) => {
1782
+ useInput2((input, key) => {
1678
1783
  if (key.escape) onClose();
1679
1784
  if (key.upArrow) setSelectedIndex((prev) => Math.max(0, prev - 1));
1680
1785
  if (key.downArrow) setSelectedIndex((prev) => Math.min(keys.length - 1, prev + 1));
@@ -1690,19 +1795,19 @@ function ResumeModal({ onSelect, onDelete, onClose }) {
1690
1795
  });
1691
1796
  }
1692
1797
  });
1693
- return /* @__PURE__ */ React6.createElement(Box6, { flexDirection: "column", borderStyle: "double", borderColor: "cyan", padding: 1, width: 80 }, /* @__PURE__ */ React6.createElement(Box6, { justifyContent: "center", marginBottom: 1 }, /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "cyan" }, " \u{1F4C2} RESUME SESSION ")), keys.length === 0 ? /* @__PURE__ */ React6.createElement(Text6, { italic: true, color: "gray" }, " No saved chats found. ") : keys.map((id, index) => {
1798
+ return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", borderStyle: "double", borderColor: "cyan", padding: 1, width: 80 }, /* @__PURE__ */ React7.createElement(Box7, { justifyContent: "center", marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true, color: "cyan" }, " \u{1F4C2} RESUME SESSION ")), keys.length === 0 ? /* @__PURE__ */ React7.createElement(Text7, { italic: true, color: "gray" }, " No saved chats found. ") : keys.map((id, index) => {
1694
1799
  const chat2 = history[id];
1695
1800
  const isSelected = index === selectedIndex;
1696
- return /* @__PURE__ */ React6.createElement(Box6, { key: id, paddingX: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: isSelected ? "cyan" : "white" }, isSelected ? "\u276F " : " ", /* @__PURE__ */ React6.createElement(Text6, { bold: isSelected }, chat2.name || id), /* @__PURE__ */ React6.createElement(Text6, { color: "gray" }, " [", id.slice(5), "]")), isSelected && /* @__PURE__ */ React6.createElement(Box6, { marginLeft: "auto" }, /* @__PURE__ */ React6.createElement(Text6, { color: "red" }, " (x to delete) ")));
1697
- }), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1, justifyContent: "center", borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \u2191\u2193 navigate \u2022 Enter select \u2022 x delete \u2022 Esc close ")));
1801
+ return /* @__PURE__ */ React7.createElement(Box7, { key: id, paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: isSelected ? "cyan" : "white" }, isSelected ? "\u276F " : " ", /* @__PURE__ */ React7.createElement(Text7, { bold: isSelected }, chat2.name || id), /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, " [", id.slice(5), "]")), isSelected && /* @__PURE__ */ React7.createElement(Box7, { marginLeft: "auto" }, /* @__PURE__ */ React7.createElement(Text7, { color: "red" }, " (x to delete) ")));
1802
+ }), /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1, justifyContent: "center", borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, " \u2191\u2193 navigate \u2022 Enter select \u2022 x delete \u2022 Esc close ")));
1698
1803
  }
1699
1804
 
1700
1805
  // src/components/MemoryModal.jsx
1701
- import React7, { useState as useState3, useEffect as useEffect2 } from "react";
1702
- import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
1806
+ import React8, { useState as useState4, useEffect as useEffect2 } from "react";
1807
+ import { Box as Box8, Text as Text8, useInput as useInput3 } from "ink";
1703
1808
  function MemoryModal({ onClose }) {
1704
- const [memories, setMemories] = useState3([]);
1705
- const [selectedIndex, setSelectedIndex] = useState3(0);
1809
+ const [memories, setMemories] = useState4([]);
1810
+ const [selectedIndex, setSelectedIndex] = useState4(0);
1706
1811
  const loadMemories = () => {
1707
1812
  const data = readEncryptedJson(MEMORIES_FILE, []);
1708
1813
  setMemories(data);
@@ -1710,7 +1815,7 @@ function MemoryModal({ onClose }) {
1710
1815
  useEffect2(() => {
1711
1816
  loadMemories();
1712
1817
  }, []);
1713
- useInput2((input, key) => {
1818
+ useInput3((input, key) => {
1714
1819
  if (key.escape) onClose();
1715
1820
  if (key.upArrow) setSelectedIndex((prev) => Math.max(0, prev - 1));
1716
1821
  if (key.downArrow) setSelectedIndex((prev) => Math.min(memories.length - 1, prev + 1));
@@ -1727,12 +1832,14 @@ function MemoryModal({ onClose }) {
1727
1832
  const cleanDisplay = (text) => {
1728
1833
  return text.replace(/\[Saved on: .*?\]/g, "").trim();
1729
1834
  };
1730
- return /* @__PURE__ */ React7.createElement(Box7, { flexDirection: "column", borderStyle: "double", borderColor: "yellow", padding: 1, width: 80 }, /* @__PURE__ */ React7.createElement(Box7, { justifyContent: "center", marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { bold: true, color: "yellow" }, "\u{1F9E0} LONG-TERM MEMORY VAULT")), memories.length === 0 ? /* @__PURE__ */ React7.createElement(Box7, { justifyContent: "center", paddingY: 2 }, /* @__PURE__ */ React7.createElement(Text7, { italic: true, color: "gray" }, "The vault is currently empty...")) : memories.map((mem, idx) => /* @__PURE__ */ React7.createElement(Box7, { key: mem.id, paddingX: 1, backgroundColor: idx === selectedIndex ? "#333" : void 0 }, /* @__PURE__ */ React7.createElement(Text7, { color: idx === selectedIndex ? "yellow" : "white" }, idx === selectedIndex ? "\u276F " : " ", idx + 1, ". ", cleanDisplay(mem.memory)))), /* @__PURE__ */ React7.createElement(Box7, { marginTop: 1, borderStyle: "single", borderTop: true, borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, "\u2191/\u2193 Navigate \u2022 ", /* @__PURE__ */ React7.createElement(Text7, { color: "red" }, "x"), " Delete Memory \u2022 ", /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, "Esc"), " Back to Chat")));
1835
+ return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "double", borderColor: "yellow", padding: 1, width: 80 }, /* @__PURE__ */ React8.createElement(Box8, { justifyContent: "center", marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Text8, { bold: true, color: "yellow" }, "\u{1F9E0} LONG-TERM MEMORY VAULT")), memories.length === 0 ? /* @__PURE__ */ React8.createElement(Box8, { justifyContent: "center", paddingY: 2 }, /* @__PURE__ */ React8.createElement(Text8, { italic: true, color: "gray" }, "The vault is currently empty...")) : memories.map((mem, idx) => /* @__PURE__ */ React8.createElement(Box8, { key: mem.id, paddingX: 1, backgroundColor: idx === selectedIndex ? "#333" : void 0 }, /* @__PURE__ */ React8.createElement(Text8, { color: idx === selectedIndex ? "yellow" : "white" }, idx === selectedIndex ? "\u276F " : " ", idx + 1, ". ", cleanDisplay(mem.memory)))), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1, borderStyle: "single", borderTop: true, borderBottom: false, borderLeft: false, borderRight: false, paddingTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "gray" }, "\u2191/\u2193 Navigate \u2022 ", /* @__PURE__ */ React8.createElement(Text8, { color: "red" }, "x"), " Delete Memory \u2022 ", /* @__PURE__ */ React8.createElement(Text8, { color: "cyan" }, "Esc"), " Back to Chat")));
1731
1836
  }
1732
1837
 
1733
1838
  // src/app.jsx
1734
1839
  var SESSION_START_TIME = Date.now();
1735
- var ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React8.createElement(Text8, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION"), /* @__PURE__ */ React8.createElement(Text8, { marginTop: 1 }, "The agent already finished the task (turn: finish) before your hint was consumed."), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1, backgroundColor: "#222", paddingX: 1, width: "100%" }, /* @__PURE__ */ React8.createElement(Text8, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(
1840
+ var CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
1841
+ var versionFluxflow = "1.1.0";
1842
+ var ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React9.createElement(Text9, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION"), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1 }, "The agent already finished the task (turn: finish) before your hint was consumed."), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1, backgroundColor: "#222", paddingX: 1, width: "100%" }, /* @__PURE__ */ React9.createElement(Text9, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text9, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(
1736
1843
  CommandMenu,
1737
1844
  {
1738
1845
  title: "Select Action",
@@ -1756,9 +1863,9 @@ var FLUX_LOGO = gradient(["#00ffff", "#0077ff", "#ff00ff"]).multiline(
1756
1863
  );
1757
1864
  function App() {
1758
1865
  const { stdout } = useStdout();
1759
- const [input, setInput] = useState4("");
1760
- const [mode, setMode] = useState4("Flux");
1761
- const [terminalSize, setTerminalSize] = useState4({
1866
+ const [input, setInput] = useState5("");
1867
+ const [mode, setMode] = useState5("Flux");
1868
+ const [terminalSize, setTerminalSize] = useState5({
1762
1869
  columns: stdout?.columns || 80,
1763
1870
  rows: stdout?.rows || 24
1764
1871
  });
@@ -1775,27 +1882,52 @@ function App() {
1775
1882
  stdout.off("resize", handleResize);
1776
1883
  };
1777
1884
  }, [stdout]);
1778
- const [thinkingLevel, setThinkingLevel] = useState4("Medium");
1779
- const [showFullThinking, setShowFullThinking] = useState4(false);
1780
- const [activeModel, setActiveModel] = useState4("gemma-4-31b-it");
1781
- const [janitorModel, setJanitorModel] = useState4("gemma-4-26b-a4b-it");
1782
- const [isInitializing, setIsInitializing] = useState4(true);
1783
- const [apiKey, setApiKey] = useState4(null);
1784
- const [tempKey, setTempKey] = useState4("");
1785
- const [activeView, setActiveView] = useState4("chat");
1786
- const [apiTier, setApiTier] = useState4("Free");
1787
- const [quotas, setQuotas] = useState4({ agentLimit: 1500, backgroundLimit: 1500, searchLimit: 100, customModelId: "", customLimit: 0 });
1788
- const [inputConfig, setInputConfig] = useState4(null);
1789
- const [systemSettings, setSystemSettings] = useState4({ memory: true, compression: 0, autoExec: false, autoDeleteHistory: "7d" });
1790
- const [profileData, setProfileData] = useState4({ name: null, nickname: null, instructions: null });
1791
- const [sessionStats, setSessionStats] = useState4({ tokens: 0 });
1792
- const [sessionAgentCalls, setSessionAgentCalls] = useState4(0);
1793
- const [sessionBackgroundCalls, setSessionBackgroundCalls] = useState4(0);
1794
- const [sessionTotalTokens, setSessionTotalTokens] = useState4(0);
1795
- const [dailyUsage, setDailyUsage] = useState4(null);
1796
- const [chatId, setChatId] = useState4(generateChatId());
1797
- const [activeCommand, setActiveCommand] = useState4(null);
1798
- const [execOutput, setExecOutput] = useState4("");
1885
+ useEffect3(() => {
1886
+ const checkVersion = async () => {
1887
+ try {
1888
+ const response = await fetch("https://registry.npmjs.org/fluxflow-cli/latest");
1889
+ const data = await response.json();
1890
+ const latestVersion = data?.version;
1891
+ if (latestVersion && latestVersion !== versionFluxflow) {
1892
+ setMessages((prev) => {
1893
+ const newMsgs = [...prev];
1894
+ newMsgs.splice(1, 0, {
1895
+ id: "update-" + Date.now(),
1896
+ role: "system",
1897
+ text: `\u{1F680} **New version '${latestVersion}' is available!**
1898
+ Type \`npm i -g fluxflow-cli\` to update.
1899
+ Check what's new using \`/changelog\` command.`,
1900
+ isUpdateNotification: true
1901
+ });
1902
+ return newMsgs;
1903
+ });
1904
+ }
1905
+ } catch (err) {
1906
+ }
1907
+ };
1908
+ checkVersion();
1909
+ }, []);
1910
+ const [thinkingLevel, setThinkingLevel] = useState5("Medium");
1911
+ const [showFullThinking, setShowFullThinking] = useState5(false);
1912
+ const [activeModel, setActiveModel] = useState5("gemma-4-31b-it");
1913
+ const [janitorModel, setJanitorModel] = useState5("gemma-4-26b-a4b-it");
1914
+ const [isInitializing, setIsInitializing] = useState5(true);
1915
+ const [apiKey, setApiKey] = useState5(null);
1916
+ const [tempKey, setTempKey] = useState5("");
1917
+ const [activeView, setActiveView] = useState5("chat");
1918
+ const [apiTier, setApiTier] = useState5("Free");
1919
+ const [quotas, setQuotas] = useState5({ agentLimit: 1500, backgroundLimit: 1500, searchLimit: 100, customModelId: "", customLimit: 0 });
1920
+ const [inputConfig, setInputConfig] = useState5(null);
1921
+ const [systemSettings, setSystemSettings] = useState5({ memory: true, compression: 0, autoExec: false, autoDeleteHistory: "7d" });
1922
+ const [profileData, setProfileData] = useState5({ name: null, nickname: null, instructions: null });
1923
+ const [sessionStats, setSessionStats] = useState5({ tokens: 0 });
1924
+ const [sessionAgentCalls, setSessionAgentCalls] = useState5(0);
1925
+ const [sessionBackgroundCalls, setSessionBackgroundCalls] = useState5(0);
1926
+ const [sessionTotalTokens, setSessionTotalTokens] = useState5(0);
1927
+ const [dailyUsage, setDailyUsage] = useState5(null);
1928
+ const [chatId, setChatId] = useState5(generateChatId());
1929
+ const [activeCommand, setActiveCommand] = useState5(null);
1930
+ const [execOutput, setExecOutput] = useState5("");
1799
1931
  const activeCommandRef = useRef(null);
1800
1932
  const execOutputRef = useRef("");
1801
1933
  useEffect3(() => {
@@ -1804,8 +1936,9 @@ function App() {
1804
1936
  useEffect3(() => {
1805
1937
  execOutputRef.current = execOutput;
1806
1938
  }, [execOutput]);
1807
- const [autoAcceptWrites, setAutoAcceptWrites] = useState4(false);
1808
- const [pendingApproval, setPendingApproval] = useState4(null);
1939
+ const [autoAcceptWrites, setAutoAcceptWrites] = useState5(false);
1940
+ const [pendingApproval, setPendingApproval] = useState5(null);
1941
+ const [pendingAsk, setPendingAsk] = useState5(null);
1809
1942
  const formatDuration = (totalSecs) => {
1810
1943
  const h = Math.floor(totalSecs / 3600);
1811
1944
  const m = Math.floor(totalSecs % 3600 / 60);
@@ -1815,19 +1948,43 @@ function App() {
1815
1948
  }
1816
1949
  return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
1817
1950
  };
1818
- const [statusText, setStatusText] = useState4(null);
1819
- const [isProcessing, setIsProcessing] = useState4(false);
1820
- const [escPressed, setEscPressed] = useState4(false);
1821
- const [escTimer, setEscTimer] = useState4(null);
1822
- const [queuedPrompt, setQueuedPrompt] = useState4(null);
1823
- const [resolutionData, setResolutionData] = useState4(null);
1824
- const [tempModelOverride, setTempModelOverride] = useState4(null);
1825
- const [messages, setMessages] = useState4([
1951
+ const [statusText, setStatusText] = useState5(null);
1952
+ const [isProcessing, setIsProcessing] = useState5(false);
1953
+ const [escPressed, setEscPressed] = useState5(false);
1954
+ const [escTimer, setEscTimer] = useState5(null);
1955
+ const [queuedPrompt, setQueuedPrompt] = useState5(null);
1956
+ const [resolutionData, setResolutionData] = useState5(null);
1957
+ const [tempModelOverride, setTempModelOverride] = useState5(null);
1958
+ const [messages, setMessages] = useState5([
1826
1959
  { id: "welcome", role: "system", text: FLUX_LOGO + "\n\n\u{1F30A}\u26A1 Welcome to Flux Flow! Type /help for commands.\n" }
1827
1960
  ]);
1828
1961
  const queuedPromptRef = useRef(null);
1829
- const [completedIndex, setCompletedIndex] = useState4(1);
1830
- useInput3((inputText, key) => {
1962
+ const [completedIndex, setCompletedIndex] = useState5(1);
1963
+ const windowedHistory = useMemo(() => {
1964
+ const MAX_LINES = 1e3;
1965
+ const width = stdout?.columns || 80;
1966
+ let totalLines = 0;
1967
+ let startIdx = 0;
1968
+ for (let i = completedIndex - 1; i >= 0; i--) {
1969
+ const msg = messages[i];
1970
+ if (!msg) continue;
1971
+ let lines = (msg.text || "").split("\n").length;
1972
+ msg.text.split("\n").forEach((l) => {
1973
+ lines += Math.floor(l.length / width);
1974
+ });
1975
+ lines += msg.role === "think" ? 3 : 2;
1976
+ if (totalLines + lines > MAX_LINES && completedIndex - i > 2) {
1977
+ startIdx = i + 1;
1978
+ break;
1979
+ }
1980
+ totalLines += lines;
1981
+ }
1982
+ return {
1983
+ items: messages.slice(startIdx, completedIndex),
1984
+ isTruncated: startIdx > 0
1985
+ };
1986
+ }, [messages, completedIndex, stdout?.columns]);
1987
+ useInput4((inputText, key) => {
1831
1988
  if (key.escape) {
1832
1989
  if (isProcessing) {
1833
1990
  if (!escPressed) {
@@ -1901,7 +2058,7 @@ function App() {
1901
2058
  setTempKey("");
1902
2059
  }
1903
2060
  };
1904
- const COMMANDS = ["/mode", "/thinking", "/model", "/resume", "/memory", "/profile", "/settings", "/key", "/stats", "/reset", "/help", "/clear", "/quit"];
2061
+ const COMMANDS = ["/mode", "/thinking", "/model", "/resume", "/memory", "/profile", "/settings", "/key", "/stats", "/reset", "/help", "/clear", "/quit", "/changelog"];
1905
2062
  const handleSubmit = (value) => {
1906
2063
  const normalizedValue = value.replace(/\r\n/g, "\n").replace(/\r/g, "\n").trimEnd();
1907
2064
  if (normalizedValue.endsWith("\\")) {
@@ -1942,9 +2099,14 @@ ${hintText}`, color: "magenta" }];
1942
2099
  const h = await loadHistory();
1943
2100
  const target = h[targetId] || Object.values(h).find((h2) => h2.name.toLowerCase() === targetId.toLowerCase());
1944
2101
  if (target) {
1945
- process.stdout.write("\x1Bc");
2102
+ stdout.write("\x1B[2J\x1B[3J\x1B[H");
1946
2103
  setChatId(targetId);
1947
- setMessages(target.messages);
2104
+ const resumedMsgs = [...target.messages];
2105
+ const hasLogo = resumedMsgs[0]?.text?.includes("\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557");
2106
+ if (!hasLogo) {
2107
+ resumedMsgs.unshift({ id: "welcome-" + Date.now(), role: "system", text: FLUX_LOGO + "\n\n\u{1F30A}\u26A1 Resuming Flux Flow Session...\n" });
2108
+ }
2109
+ setMessages(resumedMsgs);
1948
2110
  setMessages((prev) => [...prev, { id: "sys-" + Date.now(), role: "system", text: `\u{1F4E1} SESSION RESUMED: [${targetId}]` }]);
1949
2111
  setCompletedIndex(0);
1950
2112
  } else {
@@ -1958,7 +2120,7 @@ ${hintText}`, color: "magenta" }];
1958
2120
  break;
1959
2121
  }
1960
2122
  case "/clear": {
1961
- process.stdout.write("\x1Bc");
2123
+ stdout.write("\x1B[2J\x1B[3J\x1B[H");
1962
2124
  setMessages([{ id: "welcome-" + Date.now(), role: "system", text: FLUX_LOGO + "\n\n\u{1F30A}\u26A1 Welcome back to Flux Flow! Context cleared.\n" }]);
1963
2125
  setCompletedIndex(0);
1964
2126
  setChatId(generateChatId());
@@ -2102,6 +2264,16 @@ ${list || "No saved chats found."}` }];
2102
2264
  runReset();
2103
2265
  break;
2104
2266
  }
2267
+ case "/changelog": {
2268
+ const platform = process.platform;
2269
+ const command = platform === "win32" ? "start" : platform === "darwin" ? "open" : "xdg-open";
2270
+ exec(`${command} ${CHANGELOG_URL}`);
2271
+ setMessages((prev) => {
2272
+ setCompletedIndex(prev.length + 1);
2273
+ return [...prev, { id: Date.now(), role: "system", text: `\u{1F310} [BROWSER] Opening changelog: ${CHANGELOG_URL}` }];
2274
+ });
2275
+ break;
2276
+ }
2105
2277
  case "/help": {
2106
2278
  setMessages((prev) => {
2107
2279
  setCompletedIndex(prev.length + 1);
@@ -2174,23 +2346,47 @@ OUTPUT: ${execOutputRef.current}`;
2174
2346
  setPendingApproval({ tool, args, resolve });
2175
2347
  setActiveView("approval");
2176
2348
  });
2349
+ },
2350
+ onAskUser: async (question, options) => {
2351
+ return new Promise((resolve) => {
2352
+ setPendingAsk({
2353
+ question,
2354
+ options,
2355
+ resolve: (val) => {
2356
+ setMessages((prev) => [
2357
+ ...prev,
2358
+ {
2359
+ id: "ask-" + Date.now(),
2360
+ role: "system",
2361
+ text: `\u{1F4AC} **Ask User**
2362
+ Selection: ${val}`,
2363
+ isAskRecord: true
2364
+ }
2365
+ ]);
2366
+ resolve(val);
2367
+ }
2368
+ });
2369
+ setActiveView("ask");
2370
+ });
2177
2371
  }
2178
2372
  },
2179
- async () => {
2180
- if (queuedPromptRef.current) {
2181
- const p = queuedPromptRef.current;
2182
- setQueuedPrompt(null);
2183
- queuedPromptRef.current = null;
2184
- setMessages((prev) => {
2185
- const newMsgs = [...prev];
2186
- const hintMsg = newMsgs.reverse().find((m) => m.text?.includes("[STEERING HINT: QUEUED]"));
2187
- if (hintMsg) {
2188
- hintMsg.text = hintMsg.text.replace("[STEERING HINT: QUEUED]", "[STEERING HINT: INJECTED]");
2189
- hintMsg.color = "cyan";
2190
- }
2191
- return newMsgs.reverse();
2192
- });
2193
- return p;
2373
+ async (hint) => {
2374
+ if (queuedPrompt) {
2375
+ if (queuedPromptRef.current) {
2376
+ const p = queuedPromptRef.current;
2377
+ setQueuedPrompt(null);
2378
+ queuedPromptRef.current = null;
2379
+ setMessages((prev) => {
2380
+ const newMsgs = [...prev];
2381
+ const hintMsg = newMsgs.reverse().find((m) => m.text?.includes("[STEERING HINT: QUEUED]"));
2382
+ if (hintMsg) {
2383
+ hintMsg.text = hintMsg.text.replace("[STEERING HINT: QUEUED]", "[STEERING HINT: INJECTED]");
2384
+ hintMsg.color = "cyan";
2385
+ }
2386
+ return newMsgs.reverse();
2387
+ });
2388
+ return p;
2389
+ }
2194
2390
  }
2195
2391
  return null;
2196
2392
  }
@@ -2253,9 +2449,9 @@ OUTPUT: ${execOutputRef.current}`;
2253
2449
  const [thinkPart, agentPart] = chunkText.split("</think>");
2254
2450
  if (inThinkMode) {
2255
2451
  setMessages((prev) => {
2256
- const newMsgs = [...prev];
2257
- const thinkMsg = newMsgs.find((m) => m.id === currentThinkId);
2258
- if (thinkMsg) thinkMsg.text += thinkPart.replace(signalRegex, "");
2452
+ const newMsgs = prev.map(
2453
+ (m) => m.id === currentThinkId ? { ...m, text: m.text + thinkPart.replace(signalRegex, "") } : m
2454
+ );
2259
2455
  currentAgentId = "agent-" + Date.now();
2260
2456
  const cleanedAgentPart = (agentPart || "").replace(signalRegex, "");
2261
2457
  return [...newMsgs, { id: currentAgentId, role: "agent", text: cleanedAgentPart }];
@@ -2267,35 +2463,26 @@ OUTPUT: ${execOutputRef.current}`;
2267
2463
  currentAgentId = "agent-" + Date.now();
2268
2464
  setMessages((prev) => [...prev, { id: currentAgentId, role: "agent", text: cleanedContent }]);
2269
2465
  } else {
2270
- setMessages((prev) => {
2271
- const newMsgs = [...prev];
2272
- const msg = newMsgs.find((m) => m.id === currentAgentId);
2273
- if (msg) msg.text += cleanedContent;
2274
- return newMsgs;
2275
- });
2466
+ setMessages((prev) => prev.map(
2467
+ (m) => m.id === currentAgentId ? { ...m, text: m.text + cleanedContent } : m
2468
+ ));
2276
2469
  }
2277
2470
  }
2278
2471
  continue;
2279
2472
  }
2280
2473
  if (inThinkMode && currentThinkId) {
2281
- setMessages((prev) => {
2282
- const newMsgs = [...prev];
2283
- const msg = newMsgs.find((m) => m.id === currentThinkId);
2284
- if (msg) msg.text += chunkText.replace(signalRegex, "");
2285
- return newMsgs;
2286
- });
2474
+ setMessages((prev) => prev.map(
2475
+ (m) => m.id === currentThinkId ? { ...m, text: m.text + chunkText.replace(signalRegex, "") } : m
2476
+ ));
2287
2477
  } else if (!inThinkMode) {
2288
2478
  const cleanedText = chunkText.replace(/<\/?think>/gi, "").replace(signalRegex, "");
2289
2479
  if (!currentAgentId) {
2290
2480
  currentAgentId = "agent-" + Date.now();
2291
2481
  setMessages((prev) => [...prev, { id: currentAgentId, role: "agent", text: cleanedText }]);
2292
2482
  } else {
2293
- setMessages((prev) => {
2294
- const newMsgs = [...prev];
2295
- const msg = newMsgs.find((m) => m.id === currentAgentId);
2296
- if (msg) msg.text += cleanedText;
2297
- return newMsgs;
2298
- });
2483
+ setMessages((prev) => prev.map(
2484
+ (m) => m.id === currentAgentId ? { ...m, text: m.text + cleanedText } : m
2485
+ ));
2299
2486
  }
2300
2487
  }
2301
2488
  }
@@ -2342,7 +2529,7 @@ OUTPUT: ${execOutputRef.current}`;
2342
2529
  const renderActiveView = () => {
2343
2530
  switch (activeView) {
2344
2531
  case "mode":
2345
- return /* @__PURE__ */ React8.createElement(
2532
+ return /* @__PURE__ */ React9.createElement(
2346
2533
  CommandMenu,
2347
2534
  {
2348
2535
  title: "\u26A1 Select Operating Mode",
@@ -2371,7 +2558,7 @@ OUTPUT: ${execOutputRef.current}`;
2371
2558
  { label: "Max (Architecture)", value: "Max" }
2372
2559
  ];
2373
2560
  options.push({ label: "Cancel", value: "Cancel" });
2374
- return /* @__PURE__ */ React8.createElement(
2561
+ return /* @__PURE__ */ React9.createElement(
2375
2562
  CommandMenu,
2376
2563
  {
2377
2564
  title: `\u{1F9E0} Select Thinking Level (${mode} Mode)`,
@@ -2384,7 +2571,7 @@ OUTPUT: ${execOutputRef.current}`;
2384
2571
  );
2385
2572
  }
2386
2573
  case "model":
2387
- return /* @__PURE__ */ React8.createElement(
2574
+ return /* @__PURE__ */ React9.createElement(
2388
2575
  CommandMenu,
2389
2576
  {
2390
2577
  title: "\u{1F916} Select AI Model",
@@ -2396,7 +2583,7 @@ OUTPUT: ${execOutputRef.current}`;
2396
2583
  }
2397
2584
  );
2398
2585
  case "settings":
2399
- return /* @__PURE__ */ React8.createElement(
2586
+ return /* @__PURE__ */ React9.createElement(
2400
2587
  CommandMenu,
2401
2588
  {
2402
2589
  title: "System Settings",
@@ -2441,7 +2628,7 @@ OUTPUT: ${execOutputRef.current}`;
2441
2628
  }
2442
2629
  );
2443
2630
  case "apiTier":
2444
- return /* @__PURE__ */ React8.createElement(
2631
+ return /* @__PURE__ */ React9.createElement(
2445
2632
  CommandMenu,
2446
2633
  {
2447
2634
  title: `API Tier: ${apiTier}`,
@@ -2506,8 +2693,8 @@ OUTPUT: ${execOutputRef.current}`;
2506
2693
  }
2507
2694
  );
2508
2695
  case "input":
2509
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", paddingX: 2, paddingY: 1 }, inputConfig?.note && /* @__PURE__ */ React8.createElement(Box8, { marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "yellow", dimColor: true }, inputConfig.note)), /* @__PURE__ */ React8.createElement(Text8, { color: "cyan" }, inputConfig?.label), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(
2510
- TextInput2,
2696
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", paddingX: 2, paddingY: 1 }, inputConfig?.note && /* @__PURE__ */ React9.createElement(Box9, { marginBottom: 1 }, /* @__PURE__ */ React9.createElement(Text9, { color: "yellow", dimColor: true }, inputConfig.note)), /* @__PURE__ */ React9.createElement(Text9, { color: "cyan" }, inputConfig?.label), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(
2697
+ TextInput3,
2511
2698
  {
2512
2699
  value: inputConfig?.value || "",
2513
2700
  onChange: (val) => setInputConfig((prev) => ({ ...prev, value: val })),
@@ -2536,11 +2723,11 @@ OUTPUT: ${execOutputRef.current}`;
2536
2723
  }
2537
2724
  }
2538
2725
  }
2539
- )), /* @__PURE__ */ React8.createElement(Text8, { dimColor: true, marginTop: 1 }, "(Press Enter to confirm)"));
2726
+ )), /* @__PURE__ */ React9.createElement(Text9, { dimColor: true, marginTop: 1 }, "(Press Enter to confirm)"));
2540
2727
  case "stats":
2541
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "cyan", bold: true }, "\u{1F4CA} DAILY PERFORMANCE LEDGER"), /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, null, "\u2022 Agent Model Calls: ", /* @__PURE__ */ React8.createElement(Text8, { color: "green" }, dailyUsage?.agent || 0)), /* @__PURE__ */ React8.createElement(Text8, null, "\u2022 Background Tasks: ", /* @__PURE__ */ React8.createElement(Text8, { color: "blue" }, dailyUsage?.background || 0))), /* @__PURE__ */ React8.createElement(Text8, { dimColor: true, marginTop: 1 }, "(Press ESC to return to chat)"));
2728
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React9.createElement(Text9, { color: "cyan", bold: true }, "\u{1F4CA} DAILY PERFORMANCE LEDGER"), /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Agent Model Calls: ", /* @__PURE__ */ React9.createElement(Text9, { color: "green" }, dailyUsage?.agent || 0)), /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Background Tasks: ", /* @__PURE__ */ React9.createElement(Text9, { color: "blue" }, dailyUsage?.background || 0))), /* @__PURE__ */ React9.createElement(Text9, { dimColor: true, marginTop: 1 }, "(Press ESC to return to chat)"));
2542
2729
  case "autoExecDanger":
2543
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React8.createElement(Text8, { color: "yellow", bold: true, underline: true }, "\u26A0\uFE0F SECURITY WARNING: AUTO-EXEC MODE"), /* @__PURE__ */ React8.createElement(Text8, { marginTop: 1 }, "Turning this ON allows the agent to execute terminal commands automatically without requiring your approval for each step."), /* @__PURE__ */ React8.createElement(Text8, { marginTop: 1, color: "yellow" }, "RISKS INVOLVED:"), /* @__PURE__ */ React8.createElement(Text8, null, "\u2022 The agent may execute destructive commands (rm -rf, etc.) by mistake."), /* @__PURE__ */ React8.createElement(Text8, null, "\u2022 Unintended system changes if the agent hallucinates a path or command."), /* @__PURE__ */ React8.createElement(Text8, null, "\u2022 Reduced control over the agent's step-by-step decision making."), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(
2730
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React9.createElement(Text9, { color: "yellow", bold: true, underline: true }, "\u26A0\uFE0F SECURITY WARNING: AUTO-EXEC MODE"), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1 }, "Turning this ON allows the agent to execute terminal commands automatically without requiring your approval for each step."), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1, color: "yellow" }, "RISKS INVOLVED:"), /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 The agent may execute destructive commands (rm -rf, etc.) by mistake."), /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Unintended system changes if the agent hallucinates a path or command."), /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Reduced control over the agent's step-by-step decision making."), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(
2544
2731
  CommandMenu,
2545
2732
  {
2546
2733
  title: "Confirm Intent",
@@ -2557,7 +2744,7 @@ OUTPUT: ${execOutputRef.current}`;
2557
2744
  }
2558
2745
  )));
2559
2746
  case "externalDanger":
2560
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React8.createElement(Text8, { color: "red", bold: true, underline: true }, "\u26A0\uFE0F SECURITY WARNING: EXTERNAL WORKSPACE ACCESS"), /* @__PURE__ */ React8.createElement(Text8, { marginTop: 1 }, "Turning this ON allows the agent to execute tools (Read/Write/Exec) outside of the current active workspace directory."), /* @__PURE__ */ React8.createElement(Text8, { marginTop: 1, color: "yellow" }, "RISKS INVOLVED:"), /* @__PURE__ */ React8.createElement(Text8, null, "\u2022 Access to sensitive system files (SSH keys, Browser data, etc.)"), /* @__PURE__ */ React8.createElement(Text8, null, "\u2022 Potential for accidental or malicious deletion of OS-critical files."), /* @__PURE__ */ React8.createElement(Text8, null, "\u2022 Unauthorized script execution across your entire file system."), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(
2747
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React9.createElement(Text9, { color: "red", bold: true, underline: true }, "\u26A0\uFE0F SECURITY WARNING: EXTERNAL WORKSPACE ACCESS"), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1 }, "Turning this ON allows the agent to execute tools (Read/Write/Exec) outside of the current active workspace directory."), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1, color: "yellow" }, "RISKS INVOLVED:"), /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Access to sensitive system files (SSH keys, Browser data, etc.)"), /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Potential for accidental or malicious deletion of OS-critical files."), /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Unauthorized script execution across your entire file system."), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(
2561
2748
  CommandMenu,
2562
2749
  {
2563
2750
  title: "Confirm Intent",
@@ -2574,7 +2761,7 @@ OUTPUT: ${execOutputRef.current}`;
2574
2761
  }
2575
2762
  )));
2576
2763
  case "doubleDanger":
2577
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React8.createElement(Text8, { color: "red", bold: true, underline: true }, "\u26D4 CRITICAL SECURITY WARNING: COMBINED SYSTEM RISK"), /* @__PURE__ */ React8.createElement(Text8, { marginTop: 1 }, "You are attempting to enable BOTH [Auto-Exec] and [External Workspace Access] simultaneously."), /* @__PURE__ */ React8.createElement(Text8, { marginTop: 1, color: "red", bold: true }, "THIS IS NOT RECOMMENDED."), /* @__PURE__ */ React8.createElement(Text8, { marginTop: 1, color: "yellow" }, "THE CRITICAL RISK:"), /* @__PURE__ */ React8.createElement(Text8, null, "The agent will have the power to execute any command across your entire system WITHOUT your approval or supervision."), /* @__PURE__ */ React8.createElement(Text8, { color: "red", italic: true, marginTop: 1 }, "A single hallucination or error could result in full system wipe or data theft."), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(
2764
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React9.createElement(Text9, { color: "red", bold: true, underline: true }, "\u26D4 CRITICAL SECURITY WARNING: COMBINED SYSTEM RISK"), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1 }, "You are attempting to enable BOTH [Auto-Exec] and [External Workspace Access] simultaneously."), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1, color: "red", bold: true }, "THIS IS NOT RECOMMENDED."), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1, color: "yellow" }, "THE CRITICAL RISK:"), /* @__PURE__ */ React9.createElement(Text9, null, "The agent will have the power to execute any command across your entire system WITHOUT your approval or supervision."), /* @__PURE__ */ React9.createElement(Text9, { color: "red", italic: true, marginTop: 1 }, "A single hallucination or error could result in full system wipe or data theft."), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(
2578
2765
  CommandMenu,
2579
2766
  {
2580
2767
  title: "Final Confirmation",
@@ -2591,7 +2778,7 @@ OUTPUT: ${execOutputRef.current}`;
2591
2778
  }
2592
2779
  )));
2593
2780
  case "key":
2594
- return /* @__PURE__ */ React8.createElement(
2781
+ return /* @__PURE__ */ React9.createElement(
2595
2782
  CommandMenu,
2596
2783
  {
2597
2784
  title: "\u{1F511} API KEY MANAGEMENT",
@@ -2614,7 +2801,7 @@ OUTPUT: ${execOutputRef.current}`;
2614
2801
  }
2615
2802
  );
2616
2803
  case "deleteKey":
2617
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "red", bold: true }, "\u26A0\uFE0F DANGER: PURGE API KEY"), /* @__PURE__ */ React8.createElement(Text8, { marginTop: 1 }, "This will permanently delete the saved API key from the project vault. You will need to enter it again to use Flux."), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(
2804
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React9.createElement(Text9, { color: "red", bold: true }, "\u26A0\uFE0F DANGER: PURGE API KEY"), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1 }, "This will permanently delete the saved API key from the project vault. You will need to enter it again to use Flux."), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(
2618
2805
  CommandMenu,
2619
2806
  {
2620
2807
  title: "Are you absolutely sure?",
@@ -2635,7 +2822,7 @@ OUTPUT: ${execOutputRef.current}`;
2635
2822
  }
2636
2823
  )));
2637
2824
  case "exit":
2638
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "red" }, /* @__PURE__ */ React8.createElement(Text8, { color: "red", bold: true }, "\u{1F3C1} SESSION DASHBOARD"), /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, null, "\u2022 Agent Active For: ", /* @__PURE__ */ React8.createElement(Text8, { color: "yellow" }, formatDuration(Math.floor((Date.now() - SESSION_START_TIME) / 1e3)))), /* @__PURE__ */ React8.createElement(Text8, null, "\u2022 Total Agent Queries: ", /* @__PURE__ */ React8.createElement(Text8, { color: "green" }, sessionAgentCalls)), /* @__PURE__ */ React8.createElement(Text8, null, "\u2022 Memory Tasks: ", /* @__PURE__ */ React8.createElement(Text8, { color: "blue" }, sessionBackgroundCalls)), /* @__PURE__ */ React8.createElement(Text8, null, "\u2022 Total Tokens Consumed: ", /* @__PURE__ */ React8.createElement(Text8, { color: "magenta" }, (sessionTotalTokens / 1e3).toFixed(2), "k"))), /* @__PURE__ */ React8.createElement(Text8, { marginTop: 1 }, "Are you sure you want to exit?"), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(
2825
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "red" }, /* @__PURE__ */ React9.createElement(Text9, { color: "red", bold: true }, "\u{1F3C1} SESSION DASHBOARD"), /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Agent Active For: ", /* @__PURE__ */ React9.createElement(Text9, { color: "yellow" }, formatDuration(Math.floor((Date.now() - SESSION_START_TIME) / 1e3)))), /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Total Agent Queries: ", /* @__PURE__ */ React9.createElement(Text9, { color: "green" }, sessionAgentCalls)), /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Memory Tasks: ", /* @__PURE__ */ React9.createElement(Text9, { color: "blue" }, sessionBackgroundCalls)), /* @__PURE__ */ React9.createElement(Text9, null, "\u2022 Total Tokens Consumed: ", /* @__PURE__ */ React9.createElement(Text9, { color: "magenta" }, (sessionTotalTokens / 1e3).toFixed(2), "k"))), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1 }, "Are you sure you want to exit?"), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(
2639
2826
  CommandMenu,
2640
2827
  {
2641
2828
  title: "Exit Confirmation",
@@ -2652,15 +2839,36 @@ OUTPUT: ${execOutputRef.current}`;
2652
2839
  }
2653
2840
  }
2654
2841
  )));
2842
+ case "ask":
2843
+ return /* @__PURE__ */ React9.createElement(Box9, { width: "100%" }, /* @__PURE__ */ React9.createElement(
2844
+ AskUserModal_default,
2845
+ {
2846
+ question: pendingAsk?.question,
2847
+ options: pendingAsk?.options,
2848
+ onResolve: (choice) => {
2849
+ if (pendingAsk?.resolve) {
2850
+ pendingAsk.resolve(choice);
2851
+ }
2852
+ setPendingAsk(null);
2853
+ setActiveView("chat");
2854
+ }
2855
+ }
2856
+ ));
2655
2857
  case "resume":
2656
- return /* @__PURE__ */ React8.createElement(Box8, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React8.createElement(
2858
+ return /* @__PURE__ */ React9.createElement(Box9, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React9.createElement(
2657
2859
  ResumeModal,
2658
2860
  {
2659
2861
  onSelect: async (id) => {
2660
2862
  const h = await loadHistory();
2661
2863
  if (h[id]) {
2864
+ stdout.write("\x1B[2J\x1B[3J\x1B[H");
2662
2865
  setChatId(id);
2663
- setMessages(h[id].messages);
2866
+ const resumedMsgs = [...h[id].messages];
2867
+ const hasLogo = resumedMsgs[0]?.text?.includes("\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557");
2868
+ if (!hasLogo) {
2869
+ resumedMsgs.unshift({ id: "welcome-" + Date.now(), role: "system", text: FLUX_LOGO + "\n\n\u{1F30A}\u26A1 Resuming Flux Flow Session...\n" });
2870
+ }
2871
+ setMessages(resumedMsgs);
2664
2872
  setActiveView("chat");
2665
2873
  setMessages((prev) => [...prev, { id: "sys-" + Date.now(), role: "system", text: `\u{1F4E1} SESSION RESUMED: [${id}]` }]);
2666
2874
  setCompletedIndex(0);
@@ -2674,9 +2882,9 @@ OUTPUT: ${execOutputRef.current}`;
2674
2882
  }
2675
2883
  ));
2676
2884
  case "memory":
2677
- return /* @__PURE__ */ React8.createElement(Box8, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React8.createElement(MemoryModal, { onClose: () => setActiveView("chat") }));
2885
+ return /* @__PURE__ */ React9.createElement(Box9, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React9.createElement(MemoryModal, { onClose: () => setActiveView("chat") }));
2678
2886
  case "profile":
2679
- return /* @__PURE__ */ React8.createElement(
2887
+ return /* @__PURE__ */ React9.createElement(
2680
2888
  ProfileForm,
2681
2889
  {
2682
2890
  onSave: (profile) => {
@@ -2688,7 +2896,7 @@ OUTPUT: ${execOutputRef.current}`;
2688
2896
  }
2689
2897
  );
2690
2898
  case "resolution":
2691
- return /* @__PURE__ */ React8.createElement(Box8, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React8.createElement(
2899
+ return /* @__PURE__ */ React9.createElement(Box9, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React9.createElement(
2692
2900
  ResolutionModal,
2693
2901
  {
2694
2902
  data: resolutionData,
@@ -2705,15 +2913,15 @@ OUTPUT: ${execOutputRef.current}`;
2705
2913
  }
2706
2914
  ));
2707
2915
  case "approval":
2708
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React8.createElement(Text8, { color: "yellow", bold: true, underline: true }, "\u{1F6E1}\uFE0F SECURITY GATE: FILE WRITE PERMISSION"), /* @__PURE__ */ React8.createElement(Text8, { marginTop: 1 }, "The agent is attempting to modify: ", /* @__PURE__ */ React8.createElement(Text8, { color: "cyan" }, parseArgs(pendingApproval?.args || "{}").path || "Unknown File")), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1, borderStyle: "single", borderColor: "#333", paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Text8, { color: "gray" }, "--- PROPOSED CONTENT / DIFF ---"), (() => {
2916
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React9.createElement(Text9, { color: "yellow", bold: true, underline: true }, "\u{1F6E1}\uFE0F SECURITY GATE: FILE WRITE PERMISSION"), /* @__PURE__ */ React9.createElement(Text9, { marginTop: 1 }, "The agent is attempting to modify: ", /* @__PURE__ */ React9.createElement(Text9, { color: "cyan" }, parseArgs(pendingApproval?.args || "{}").path || "Unknown File")), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1, borderStyle: "single", borderColor: "#333", paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React9.createElement(Text9, { color: "gray" }, "--- PROPOSED CONTENT / DIFF ---"), (() => {
2709
2917
  const args = parseArgs(pendingApproval?.args || "{}");
2710
2918
  const oldVal = args.TargetContent || args.content_to_replace || null;
2711
2919
  const newVal = args.content || args.ReplacementContent || args.content_to_add || args.replacementContent || null;
2712
2920
  if (oldVal && newVal) {
2713
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React8.createElement(Box8, null, /* @__PURE__ */ React8.createElement(Text8, { color: "red", wrap: "anywhere", bold: true }, "- ", oldVal)), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "green", wrap: "anywhere", bold: true }, "+ ", newVal)));
2921
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React9.createElement(Box9, null, /* @__PURE__ */ React9.createElement(Text9, { color: "red", wrap: "anywhere", bold: true }, "- ", oldVal)), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text9, { color: "green", wrap: "anywhere", bold: true }, "+ ", newVal)));
2714
2922
  }
2715
- return /* @__PURE__ */ React8.createElement(Text8, { color: "white", wrap: "anywhere" }, newVal || "Updating file content...");
2716
- })()), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(
2923
+ return /* @__PURE__ */ React9.createElement(Text9, { color: "white", wrap: "anywhere" }, newVal || "Updating file content...");
2924
+ })()), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(
2717
2925
  CommandMenu,
2718
2926
  {
2719
2927
  title: "Action Required",
@@ -2732,7 +2940,7 @@ OUTPUT: ${execOutputRef.current}`;
2732
2940
  }
2733
2941
  )));
2734
2942
  case "terminalApproval":
2735
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React8.createElement(Text8, { color: "red", bold: true, underline: true }, "\u{1F6E1}\uFE0F SECURITY GATE: TERMINAL COMMAND OVERSIGHT"), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, null, "Agent requested to run: ", /* @__PURE__ */ React8.createElement(Text8, { color: "yellow", bold: true }, parseArgs(pendingApproval?.args || "{}").command || "Unknown Command"))), /* @__PURE__ */ React8.createElement(Box8, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(
2943
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React9.createElement(Text9, { color: "red", bold: true, underline: true }, "\u{1F6E1}\uFE0F SECURITY GATE: TERMINAL COMMAND OVERSIGHT"), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text9, null, "Agent requested to run: ", /* @__PURE__ */ React9.createElement(Text9, { color: "yellow", bold: true }, parseArgs(pendingApproval?.args || "{}").command || "Unknown Command"))), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(
2736
2944
  CommandMenu,
2737
2945
  {
2738
2946
  title: "Risk Assessment Required",
@@ -2754,8 +2962,8 @@ OUTPUT: ${execOutputRef.current}`;
2754
2962
  return acc + Math.max(1, Math.ceil(line.length / wrapWidth));
2755
2963
  }, 0);
2756
2964
  const maxLines = Math.max(1, wrappedLines);
2757
- return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, /* @__PURE__ */ React8.createElement(Box8, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React8.createElement(Box8, null, statusText && /* @__PURE__ */ React8.createElement(Text8, { color: "magenta", italic: true }, "\u23F3 ", statusText)), /* @__PURE__ */ React8.createElement(Text8, { color: "gray", dimColor: true }, "(", tempModelOverride || activeModel, ")")), suggestions.length > 0 && /* @__PURE__ */ React8.createElement(Box8, { paddingX: 1, marginBottom: 0 }, /* @__PURE__ */ React8.createElement(Text8, { color: "gray" }, "\u{1F4A1} Suggestions: "), suggestions.map((s, i) => /* @__PURE__ */ React8.createElement(Text8, { key: s, color: "yellow", bold: i === 0 }, " ", s, " "))), /* @__PURE__ */ React8.createElement(Box8, { backgroundColor: "#333333", paddingX: 1, paddingY: 1, width: "100%" }, /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", width: "100%" }, maxLines > 3 ? /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", width: "100%", paddingY: 0 }, /* @__PURE__ */ React8.createElement(Text8, { color: "gray", dimColor: true }, "[\u{1F4E6} ", maxLines, " lines of text in buffer - Full content will be sent]"), /* @__PURE__ */ React8.createElement(
2758
- Box8,
2965
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, /* @__PURE__ */ React9.createElement(Box9, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React9.createElement(Box9, null, statusText && /* @__PURE__ */ React9.createElement(Text9, { color: "magenta", italic: true }, "\u23F3 ", statusText)), /* @__PURE__ */ React9.createElement(Text9, { color: "gray", dimColor: true }, "(", tempModelOverride || activeModel, ")")), suggestions.length > 0 && /* @__PURE__ */ React9.createElement(Box9, { paddingX: 1, marginBottom: 0 }, /* @__PURE__ */ React9.createElement(Text9, { color: "gray" }, "\u{1F4A1} Suggestions: "), suggestions.map((s, i) => /* @__PURE__ */ React9.createElement(Text9, { key: s, color: "yellow", bold: i === 0 }, " ", s, " "))), /* @__PURE__ */ React9.createElement(Box9, { backgroundColor: "#333333", paddingX: 1, paddingY: 1, width: "100%" }, /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", width: "100%" }, maxLines > 3 ? /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", width: "100%", paddingY: 0 }, /* @__PURE__ */ React9.createElement(Text9, { color: "gray", dimColor: true }, "[\u{1F4E6} ", maxLines, " lines of text in buffer - Full content will be sent]"), /* @__PURE__ */ React9.createElement(
2966
+ Box9,
2759
2967
  {
2760
2968
  flexDirection: "row",
2761
2969
  width: "100%",
@@ -2763,8 +2971,8 @@ OUTPUT: ${execOutputRef.current}`;
2763
2971
  overflow: "hidden",
2764
2972
  alignItems: "flex-end"
2765
2973
  },
2766
- /* @__PURE__ */ React8.createElement(Box8, { flexShrink: 0, width: 3 }, /* @__PURE__ */ React8.createElement(Text8, { color: "yellow" }, "\u276F ")),
2767
- /* @__PURE__ */ React8.createElement(Box8, { flexGrow: 1 }, /* @__PURE__ */ React8.createElement(Box8, { flexGrow: 1, position: "relative" }, input.split("\n").pop() === "" && !isProcessing && /* @__PURE__ */ React8.createElement(Box8, { position: "absolute", paddingLeft: 0 }, /* @__PURE__ */ React8.createElement(Text8, { color: "gray", dimColor: true }, "Type your message...")), /* @__PURE__ */ React8.createElement(
2974
+ /* @__PURE__ */ React9.createElement(Box9, { flexShrink: 0, width: 3 }, /* @__PURE__ */ React9.createElement(Text9, { color: "yellow" }, "\u276F ")),
2975
+ /* @__PURE__ */ React9.createElement(Box9, { flexGrow: 1 }, /* @__PURE__ */ React9.createElement(Box9, { flexGrow: 1, position: "relative" }, input.split("\n").pop() === "" && !isProcessing && /* @__PURE__ */ React9.createElement(Box9, { position: "absolute", paddingLeft: 0 }, /* @__PURE__ */ React9.createElement(Text9, { color: "gray", dimColor: true }, "Type your message...")), /* @__PURE__ */ React9.createElement(
2768
2976
  MultilineInput,
2769
2977
  {
2770
2978
  value: input.split("\n").pop() || "",
@@ -2781,7 +2989,7 @@ OUTPUT: ${execOutputRef.current}`;
2781
2989
  }
2782
2990
  }
2783
2991
  )))
2784
- )) : /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "row", width: "100%", paddingY: 0 }, /* @__PURE__ */ React8.createElement(Box8, { flexShrink: 0, width: 3 }, /* @__PURE__ */ React8.createElement(Text8, { color: "yellow" }, "\u276F ")), /* @__PURE__ */ React8.createElement(Box8, { flexGrow: 1 }, /* @__PURE__ */ React8.createElement(Box8, { flexGrow: 1, position: "relative" }, input === "" && !isProcessing && /* @__PURE__ */ React8.createElement(Box8, { position: "absolute", paddingLeft: 0 }, /* @__PURE__ */ React8.createElement(Text8, { color: "gray", dimColor: true }, escPressed ? " Press ESC again to cancel the request." : " Type your message or /command...")), /* @__PURE__ */ React8.createElement(
2992
+ )) : /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "row", width: "100%", paddingY: 0 }, /* @__PURE__ */ React9.createElement(Box9, { flexShrink: 0, width: 3 }, /* @__PURE__ */ React9.createElement(Text9, { color: "yellow" }, "\u276F ")), /* @__PURE__ */ React9.createElement(Box9, { flexGrow: 1 }, /* @__PURE__ */ React9.createElement(Box9, { flexGrow: 1, position: "relative" }, input === "" && !isProcessing && /* @__PURE__ */ React9.createElement(Box9, { position: "absolute", paddingLeft: 0 }, /* @__PURE__ */ React9.createElement(Text9, { color: "gray", dimColor: true }, escPressed ? " Press ESC again to cancel the request." : " Type your message or /command...")), /* @__PURE__ */ React9.createElement(
2785
2993
  MultilineInput,
2786
2994
  {
2787
2995
  value: input,
@@ -2799,16 +3007,16 @@ OUTPUT: ${execOutputRef.current}`;
2799
3007
  )))))));
2800
3008
  }
2801
3009
  };
2802
- 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(
2803
- TextInput2,
3010
+ return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", width: "100%" }, windowedHistory.isTruncated && /* @__PURE__ */ React9.createElement(Box9, { borderStyle: "single", borderColor: "gray", paddingX: 1, marginBottom: 1, width: "100%", justifyContent: "center" }, /* @__PURE__ */ React9.createElement(Text9, { color: "gray", dimColor: true, italic: true }, "[ \u2191 History truncated for performance (showing last ~1000 lines) ]")), /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column" }, windowedHistory.items.map((msg, idx) => /* @__PURE__ */ React9.createElement(MessageItem, { key: msg.id || idx, msg, showFullThinking }))), /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", padding: 1, width: "100%" }, (activeView === "chat" || ["ask", "approval", "terminalApproval"].includes(activeView)) && /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React9.createElement(ChatLayout_default, { messages: messages.slice(completedIndex), showFullThinking }), activeCommand && /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(TerminalBox, { command: activeCommand, output: execOutput }))), isInitializing ? /* @__PURE__ */ React9.createElement(Box9, { borderStyle: "double", borderColor: "magenta", padding: 1, flexShrink: 0 }, /* @__PURE__ */ React9.createElement(Text9, { color: "magenta" }, "\u{1F30A} Starting Flux Flow...")) : !apiKey ? /* @__PURE__ */ React9.createElement(Box9, { borderStyle: "bold", borderColor: "yellow", padding: 1, flexDirection: "column", flexShrink: 0 }, /* @__PURE__ */ React9.createElement(Text9, { color: "yellow", bold: true }, "\u{1F511} API KEY REQUIRED"), /* @__PURE__ */ React9.createElement(Text9, null, "Please enter your Gemini API Key to initialize the agent's brain."), /* @__PURE__ */ React9.createElement(Box9, { marginTop: 1 }, /* @__PURE__ */ React9.createElement(Text9, { color: "cyan" }, "\u276F "), /* @__PURE__ */ React9.createElement(
3011
+ TextInput3,
2804
3012
  {
2805
3013
  value: tempKey,
2806
3014
  onChange: setTempKey,
2807
3015
  onSubmit: handleSetup,
2808
3016
  mask: "*"
2809
3017
  }
2810
- ))) : renderActiveView(), /* @__PURE__ */ React8.createElement(Box8, { flexShrink: 0, width: "100%" }, /* @__PURE__ */ React8.createElement(
2811
- StatusBar,
3018
+ ))) : renderActiveView(), /* @__PURE__ */ React9.createElement(Box9, { flexShrink: 0, width: "100%" }, /* @__PURE__ */ React9.createElement(
3019
+ StatusBar_default,
2812
3020
  {
2813
3021
  mode,
2814
3022
  thinkingLevel,
@@ -2820,5 +3028,24 @@ OUTPUT: ${execOutputRef.current}`;
2820
3028
  }
2821
3029
 
2822
3030
  // src/cli.jsx
3031
+ process.env.NODE_NO_WARNINGS = "1";
3032
+ var silentPatterns = [
3033
+ "cuimp",
3034
+ "Found existing binary",
3035
+ "Binary verified",
3036
+ "curl.exe not found",
3037
+ "Falling back to .bat file",
3038
+ "DeprecationWarning"
3039
+ ];
3040
+ var originalLog = console.log;
3041
+ var originalWarn = console.warn;
3042
+ var originalError = console.error;
3043
+ var isNoise = (args) => {
3044
+ const msg = args.map(String).join(" ");
3045
+ return silentPatterns.some((p) => msg.includes(p));
3046
+ };
3047
+ console.log = (...args) => !isNoise(args) && originalLog(...args);
3048
+ console.warn = (...args) => !isNoise(args) && originalWarn(...args);
3049
+ console.error = (...args) => !isNoise(args) && originalError(...args);
2823
3050
  process.stdout.write("\x1Bc");
2824
- render(/* @__PURE__ */ React9.createElement(App, null));
3051
+ render(/* @__PURE__ */ React10.createElement(App, null));