fluxflow-cli 1.1.7 → 1.2.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.
Files changed (2) hide show
  1. package/dist/fluxflow.js +1736 -1482
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -1,233 +1,240 @@
1
1
  #!/usr/bin/env node
2
-
3
- // src/cli.jsx
4
- import React10 from "react";
5
- import { render } from "ink";
6
-
7
- // src/app.jsx
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
- import fs14 from "fs-extra";
11
- import { exec } from "child_process";
12
- import { MultilineInput } from "ink-multiline-input";
13
- import TextInput3 from "ink-text-input";
14
-
15
- // src/components/ChatLayout.jsx
16
- import React2 from "react";
17
- import { Box as Box2, Text as Text2 } from "ink";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __esm = (fn, res) => function __init() {
5
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
+ };
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
18
11
 
19
12
  // src/components/TerminalBox.jsx
20
13
  import React from "react";
21
14
  import { Box, Text } from "ink";
22
- var TerminalBox = React.memo(({ command, output, completed = false }) => {
23
- const cleanOutput = (output || "").replace(/\r/g, "").trim();
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.")));
15
+ var TerminalBox;
16
+ var init_TerminalBox = __esm({
17
+ "src/components/TerminalBox.jsx"() {
18
+ TerminalBox = React.memo(({ command, output, completed = false }) => {
19
+ const cleanOutput = (output || "").replace(/\r/g, "").trim();
20
+ 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.")));
21
+ });
22
+ }
25
23
  });
26
24
 
27
25
  // src/components/ChatLayout.jsx
28
- var cleanSignals = (text) => {
29
- if (!text) return text;
30
- const parts = [];
31
- let i = 0;
32
- while (i < text.length) {
33
- const trigger = "tool:functions.";
34
- if (text.substring(i, i + trigger.length).toLowerCase() === trigger) {
35
- let balance = 0;
36
- let foundStart = false;
37
- let j = i;
38
- while (j < text.length) {
39
- if (text[j] === "(") {
40
- balance++;
41
- foundStart = true;
42
- } else if (text[j] === ")") {
43
- balance--;
44
- }
45
- j++;
46
- if (foundStart && balance === 0) break;
26
+ import React2 from "react";
27
+ import { Box as Box2, Text as Text2 } from "ink";
28
+ var cleanSignals, formatThinkText, MarkdownText, DiffLine, DiffBlock, CodeRenderer, MessageItem, ChatLayout, ChatLayout_default;
29
+ var init_ChatLayout = __esm({
30
+ "src/components/ChatLayout.jsx"() {
31
+ init_TerminalBox();
32
+ cleanSignals = (text) => {
33
+ if (!text) return text;
34
+ const parts = [];
35
+ let i = 0;
36
+ while (i < text.length) {
37
+ const trigger = "tool:functions.";
38
+ if (text.substring(i, i + trigger.length).toLowerCase() === trigger) {
39
+ let balance = 0;
40
+ let foundStart = false;
41
+ let j = i;
42
+ while (j < text.length) {
43
+ if (text[j] === "(") {
44
+ balance++;
45
+ foundStart = true;
46
+ } else if (text[j] === ")") {
47
+ balance--;
48
+ }
49
+ j++;
50
+ if (foundStart && balance === 0) break;
51
+ }
52
+ i = j;
53
+ } else {
54
+ parts.push(text[i]);
55
+ i++;
56
+ }
47
57
  }
48
- i = j;
49
- } else {
50
- parts.push(text[i]);
51
- i++;
52
- }
53
- }
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();
55
- };
56
- var formatThinkText = (cleaned) => {
57
- if (!cleaned) return null;
58
- const lines = cleaned.split("\n").filter((l) => l.trim() !== "");
59
- return lines.map((line, i) => {
60
- const trimmed = line.trim();
61
- if (trimmed.startsWith("**") && trimmed.endsWith("**") || trimmed.startsWith("#")) {
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
- }
64
- const isBullet = trimmed.startsWith("*");
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
- });
67
- };
68
- var MarkdownText = React2.memo(({ text, color = "white" }) => {
69
- if (!text) return null;
70
- const lines = text.split("\n");
71
- return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, lines.map((line, i) => {
72
- const trimmed = line.trim();
73
- if (trimmed === "---" || trimmed === "***" || trimmed === "___") {
74
- return /* @__PURE__ */ React2.createElement(Box2, { key: i, marginY: 1, borderStyle: "single", borderTop: true, borderBottom: false, borderLeft: false, borderRight: false, width: "100%", borderColor: "#333" });
75
- }
76
- const headingMatch = trimmed.match(/^(#{1,3})\s+(.*)/);
77
- if (headingMatch) {
78
- const level = headingMatch[1].length;
79
- const hText = headingMatch[2];
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()));
81
- }
82
- const isUnordered = trimmed.startsWith("* ") || trimmed.startsWith("- ");
83
- const isOrdered = /^\d+\.\s/.test(trimmed);
84
- let content = trimmed;
85
- if (isUnordered || isOrdered) {
86
- content = (isUnordered ? " \u2022 " : "") + trimmed.replace(/^[\*\-\d+\.]+\s/, "");
87
- }
88
- const parts = content.split(/(\*\*.*?\*\*|\*.*?\*|`.*?`)/g);
89
- return /* @__PURE__ */ React2.createElement(Box2, { key: i, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color, wrap: "anywhere" }, parts.map((part, j) => {
90
- if (part.startsWith("**") && part.endsWith("**")) {
91
- return /* @__PURE__ */ React2.createElement(Text2, { key: j, bold: true, color: "white" }, part.slice(2, -2));
58
+ 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();
59
+ };
60
+ formatThinkText = (cleaned) => {
61
+ if (!cleaned) return null;
62
+ const lines = cleaned.split("\n").filter((l) => l.trim() !== "");
63
+ return lines.map((line, i) => {
64
+ const trimmed = line.trim();
65
+ if (trimmed.startsWith("**") && trimmed.endsWith("**") || trimmed.startsWith("#")) {
66
+ 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()));
67
+ }
68
+ const isBullet = trimmed.startsWith("*");
69
+ 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()));
70
+ });
71
+ };
72
+ MarkdownText = React2.memo(({ text, color = "white" }) => {
73
+ if (!text) return null;
74
+ const lines = text.split("\n");
75
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, lines.map((line, i) => {
76
+ const trimmed = line.trim();
77
+ if (trimmed === "---" || trimmed === "***" || trimmed === "___") {
78
+ return /* @__PURE__ */ React2.createElement(Box2, { key: i, marginY: 1, borderStyle: "single", borderTop: true, borderBottom: false, borderLeft: false, borderRight: false, width: "100%", borderColor: "#333" });
79
+ }
80
+ const headingMatch = trimmed.match(/^(#{1,3})\s+(.*)/);
81
+ if (headingMatch) {
82
+ const level = headingMatch[1].length;
83
+ const hText = headingMatch[2];
84
+ 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()));
85
+ }
86
+ const isUnordered = trimmed.startsWith("* ") || trimmed.startsWith("- ");
87
+ const isOrdered = /^\d+\.\s/.test(trimmed);
88
+ let content = trimmed;
89
+ if (isUnordered || isOrdered) {
90
+ content = (isUnordered ? " \u2022 " : "") + trimmed.replace(/^[\*\-\d+\.]+\s/, "");
91
+ }
92
+ const parts = content.split(/(\*\*.*?\*\*|\*.*?\*|`.*?`)/g);
93
+ return /* @__PURE__ */ React2.createElement(Box2, { key: i, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color, wrap: "anywhere" }, parts.map((part, j) => {
94
+ if (part.startsWith("**") && part.endsWith("**")) {
95
+ return /* @__PURE__ */ React2.createElement(Text2, { key: j, bold: true, color: "white" }, part.slice(2, -2));
96
+ }
97
+ if (part.startsWith("*") && part.endsWith("*")) {
98
+ return /* @__PURE__ */ React2.createElement(Text2, { key: j, italic: true, color: "gray" }, part.slice(1, -1));
99
+ }
100
+ if (part.startsWith("`") && part.endsWith("`")) {
101
+ return /* @__PURE__ */ React2.createElement(Text2, { key: j, color: "cyan", backgroundColor: "#003333" }, " ", part.slice(1, -1), " ");
102
+ }
103
+ return part;
104
+ })));
105
+ }));
106
+ });
107
+ DiffLine = React2.memo(({ line }) => {
108
+ const isContext = line.includes("[UI_CONTEXT]");
109
+ const cleanLine = line.replace("[UI_CONTEXT]", "");
110
+ const isRemoval = cleanLine.startsWith("-");
111
+ const isAddition = cleanLine.startsWith("+");
112
+ const parts = cleanLine.substring(1).split("|");
113
+ const lineNum = parts[0]?.trim() || "";
114
+ const content = parts.slice(1).join("|");
115
+ const bgColor = isRemoval ? "#3a0c0c" : isAddition ? "#0c3a1a" : "#1a1a1a";
116
+ const textColor = isRemoval ? "#ff4d4d" : isAddition ? "#4dff88" : "white";
117
+ 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)));
118
+ });
119
+ DiffBlock = React2.memo(({ text }) => {
120
+ const beforeDiff = text.substring(0, text.indexOf("[DIFF_START]")).trim();
121
+ const afterDiff = text.substring(text.indexOf("[DIFF_END]") + 10).trim();
122
+ const match = text.match(/\[DIFF_START\]([\s\S]*?)\[DIFF_END\]/);
123
+ const diffBody = match ? match[1].trim() : "";
124
+ const diffLines = diffBody.split("\n");
125
+ 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 }));
126
+ });
127
+ CodeRenderer = React2.memo(({ text }) => {
128
+ if (!text) return null;
129
+ if (text.includes("[DIFF_START]")) {
130
+ return /* @__PURE__ */ React2.createElement(DiffBlock, { text });
92
131
  }
93
- if (part.startsWith("*") && part.endsWith("*")) {
94
- return /* @__PURE__ */ React2.createElement(Text2, { key: j, italic: true, color: "gray" }, part.slice(1, -1));
132
+ if (text.includes("```")) {
133
+ const parts = text.split(/(```[\s\S]*?```)/g);
134
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, parts.map((part, i) => {
135
+ if (part.startsWith("```") && part.endsWith("```")) {
136
+ const match = part.match(/```(\w*)\n([\s\S]*?)```/);
137
+ const lang = match ? match[1] : "code";
138
+ const code = match ? match[2] : part.slice(3, -3);
139
+ 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())));
140
+ }
141
+ return /* @__PURE__ */ React2.createElement(MarkdownText, { key: i, text: part });
142
+ }));
95
143
  }
96
- if (part.startsWith("`") && part.endsWith("`")) {
97
- return /* @__PURE__ */ React2.createElement(Text2, { key: j, color: "cyan", backgroundColor: "#003333" }, " ", part.slice(1, -1), " ");
144
+ return /* @__PURE__ */ React2.createElement(MarkdownText, { text });
145
+ });
146
+ MessageItem = React2.memo(({ msg, showFullThinking }) => {
147
+ const isDiffResult = msg.role === "system" && msg.text.includes("[DIFF_START]");
148
+ const isTerminalRecord = msg.isTerminalRecord;
149
+ if (msg.role === "system" && msg.text.includes("[TOOL_RESULT]") && !isDiffResult && !isTerminalRecord) return null;
150
+ if (msg.isAskRecord) {
151
+ const selectionMatch = msg.text.match(/Selection: (.*)/);
152
+ const selection = selectionMatch ? selectionMatch[1] : "No selection";
153
+ 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)))));
98
154
  }
99
- return part;
100
- })));
101
- }));
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())));
155
+ if (msg.isUpdateNotification) {
156
+ 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 }))));
136
157
  }
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 }));
158
+ if (isTerminalRecord) {
159
+ const cmdMatch = msg.text.match(/COMMAND: (.*)\n/);
160
+ const outputMatch = msg.text.match(/OUTPUT: ([\s\S]*)$/);
161
+ const cmd = cmdMatch ? cmdMatch[1] : "Unknown";
162
+ const outputList = outputMatch ? outputMatch[1] : "";
163
+ return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(TerminalBox, { command: cmd, output: outputList, completed: true }));
164
+ }
165
+ const content = React2.useMemo(() => cleanSignals(msg.text), [msg.text]);
166
+ const finalContent = React2.useMemo(() => {
167
+ if (msg.role === "think" && !showFullThinking) {
168
+ const lines = content.split("\n").filter((line) => {
169
+ const trimmed = line.trim();
170
+ const isHeading = trimmed.startsWith("# ");
171
+ const isActionStep = trimmed.startsWith("**") && trimmed.endsWith("**");
172
+ return isHeading || isActionStep;
173
+ });
174
+ if (lines.length === 0) return "*Reasoning...*";
175
+ return lines.join("\n");
176
+ }
177
+ return content;
178
+ }, [content, msg.role, showFullThinking]);
179
+ return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, flexDirection: "column", flexShrink: 0, width: "100%" }, msg.role === "user" ? /* @__PURE__ */ React2.createElement(
180
+ Box2,
181
+ {
182
+ backgroundColor: "#262626",
183
+ paddingX: 1,
184
+ paddingY: 1,
185
+ width: "100%",
186
+ flexDirection: "column"
187
+ },
188
+ 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))))
189
+ ) : 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]"))));
190
+ });
191
+ ChatLayout = React2.memo(({ messages, showFullThinking }) => {
192
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", width: "100%" }, messages.map((msg, idx) => /* @__PURE__ */ React2.createElement(
193
+ MessageItem,
194
+ {
195
+ key: msg.id || idx,
196
+ msg,
197
+ showFullThinking
198
+ }
199
+ )));
200
+ });
201
+ ChatLayout_default = ChatLayout;
160
202
  }
161
- const content = React2.useMemo(() => cleanSignals(msg.text), [msg.text]);
162
- const finalContent = React2.useMemo(() => {
163
- if (msg.role === "think" && !showFullThinking) {
164
- const lines = content.split("\n").filter((line) => {
165
- const trimmed = line.trim();
166
- const isHeading = trimmed.startsWith("# ");
167
- const isActionStep = trimmed.startsWith("**") && trimmed.endsWith("**");
168
- return isHeading || isActionStep;
169
- });
170
- if (lines.length === 0) return "*Reasoning...*";
171
- return lines.join("\n");
172
- }
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
203
  });
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;
198
204
 
199
205
  // src/components/StatusBar.jsx
200
206
  import React3 from "react";
201
207
  import { Box as Box3, Text as Text3 } from "ink";
202
- var StatusBar = React3.memo(({ mode, thinkingLevel, tokens = "0.0k", tokensTotal = "0.0k", chatId = "NEW-SESSION", isMemoryEnabled = true }) => {
203
- const modeColor = mode === "Flux" ? "yellow" : "cyan";
204
- const modeIcon = mode === "Flux" ? "\u26A1" : "\u{1F30A}";
205
- const memStatus = isMemoryEnabled ? "ON" : "OFF";
206
- return /* @__PURE__ */ React3.createElement(
207
- Box3,
208
- {
209
- borderStyle: "single",
210
- borderColor: "gray",
211
- flexDirection: "row",
212
- justifyContent: "space-between",
213
- paddingX: 1,
214
- width: "100%"
215
- },
216
- /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: modeColor, bold: true }, modeIcon, " ", mode.toUpperCase()), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "magenta" }, "\u{1F9E0} ", thinkingLevel)),
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())),
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" }, tokensTotal > 1e3 ? `${(tokensTotal / 1e3).toFixed(1)}k` : tokensTotal, " (", Math.round(tokens / 254e3 * 100), "%)"), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "dim" }, chatId, " "))
219
- );
208
+ var StatusBar, StatusBar_default;
209
+ var init_StatusBar = __esm({
210
+ "src/components/StatusBar.jsx"() {
211
+ StatusBar = React3.memo(({ mode, thinkingLevel, tokens = "0.0k", tokensTotal = "0.0k", chatId = "NEW-SESSION", isMemoryEnabled = true }) => {
212
+ const modeColor = mode === "Flux" ? "yellow" : "cyan";
213
+ const modeIcon = mode === "Flux" ? "\u26A1" : "\u{1F30A}";
214
+ const memStatus = isMemoryEnabled ? "ON" : "OFF";
215
+ return /* @__PURE__ */ React3.createElement(
216
+ Box3,
217
+ {
218
+ borderStyle: "single",
219
+ borderColor: "gray",
220
+ flexDirection: "row",
221
+ justifyContent: "space-between",
222
+ paddingX: 1,
223
+ width: "100%"
224
+ },
225
+ /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { color: modeColor, bold: true }, modeIcon, " ", mode.toUpperCase()), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "magenta" }, "\u{1F9E0} ", thinkingLevel)),
226
+ /* @__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())),
227
+ /* @__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" }, tokensTotal > 1e3 ? `${(tokensTotal / 1e3).toFixed(1)}k` : tokensTotal, " (", Math.round(tokens / 254e3 * 100), "%)"), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " \u2502 "), /* @__PURE__ */ React3.createElement(Text3, { color: "dim" }, chatId, " "))
228
+ );
229
+ });
230
+ StatusBar_default = StatusBar;
231
+ }
220
232
  });
221
- var StatusBar_default = StatusBar;
222
233
 
223
234
  // src/components/CommandMenu.jsx
224
235
  import React4 from "react";
225
236
  import { Box as Box4, Text as Text4 } from "ink";
226
237
  import SelectInput from "ink-select-input";
227
- var CustomItem = ({ label, isSelected }) => {
228
- const isCancel = label === "Cancel" || label.toLowerCase().includes("exit");
229
- return /* @__PURE__ */ React4.createElement(Box4, { marginTop: isCancel ? 1 : 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: isSelected ? "cyan" : "white" }, isSelected ? "\u276F " : " ", label));
230
- };
231
238
  function CommandMenu({ title, items, onSelect }) {
232
239
  return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", padding: 1, marginTop: 1, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "magenta", bold: true }, title), /* @__PURE__ */ React4.createElement(Box4, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React4.createElement(
233
240
  SelectInput,
@@ -239,6 +246,15 @@ function CommandMenu({ title, items, onSelect }) {
239
246
  }
240
247
  )), /* @__PURE__ */ React4.createElement(Text4, { color: "gray", dimColor: true, marginTop: 1 }, "(Use Up/Down arrows to select, Enter to confirm)"));
241
248
  }
249
+ var CustomItem;
250
+ var init_CommandMenu = __esm({
251
+ "src/components/CommandMenu.jsx"() {
252
+ CustomItem = ({ label, isSelected }) => {
253
+ const isCancel = label === "Cancel" || label.toLowerCase().includes("exit");
254
+ return /* @__PURE__ */ React4.createElement(Box4, { marginTop: isCancel ? 1 : 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: isSelected ? "cyan" : "white" }, isSelected ? "\u276F " : " ", label));
255
+ };
256
+ }
257
+ });
242
258
 
243
259
  // src/components/ProfileForm.jsx
244
260
  import React5, { useState } from "react";
@@ -273,136 +289,157 @@ function ProfileForm({ onSave, onCancel }) {
273
289
  }
274
290
  )), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true, marginTop: 1 }, "(Press Enter to submit, type /cancel to abort)"));
275
291
  }
292
+ var init_ProfileForm = __esm({
293
+ "src/components/ProfileForm.jsx"() {
294
+ }
295
+ });
276
296
 
277
297
  // src/components/AskUserModal.jsx
278
298
  import React6, { useState as useState2 } from "react";
279
299
  import { Box as Box6, Text as Text6, useInput } from "ink";
280
300
  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)
301
+ var AskUserModal, AskUserModal_default;
302
+ var init_AskUserModal = __esm({
303
+ "src/components/AskUserModal.jsx"() {
304
+ AskUserModal = ({ question, options, onResolve }) => {
305
+ const [isSuggestingElse, setIsSuggestingElse] = useState2(false);
306
+ const [customInput, setCustomInput] = useState2("");
307
+ const [selectedIndex, setSelectedIndex] = useState2(0);
308
+ const allOptions = [...options, { id: "CUSTOM", label: "Suggest something else...", description: "Provide a custom response" }];
309
+ useInput((input, key) => {
310
+ if (isSuggestingElse) return;
311
+ if (key.leftArrow || key.upArrow) {
312
+ setSelectedIndex((prev) => Math.max(0, prev - 1));
313
+ }
314
+ if (key.rightArrow || key.downArrow) {
315
+ setSelectedIndex((prev) => Math.min(allOptions.length - 1, prev + 1));
316
+ }
317
+ if (key.return) {
318
+ const selected = allOptions[selectedIndex];
319
+ if (selected.id === "CUSTOM") {
320
+ setIsSuggestingElse(true);
321
+ } else {
322
+ onResolve(selected.label);
323
+ }
324
+ }
325
+ });
326
+ if (isSuggestingElse) {
327
+ 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(
328
+ TextInput2,
329
+ {
330
+ value: customInput,
331
+ onChange: setCustomInput,
332
+ onSubmit: () => onResolve(customInput)
333
+ }
334
+ )), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", dimColor: true, italic: true }, "(Press Enter to send)")));
310
335
  }
311
- )), /* @__PURE__ */ React6.createElement(Box6, { marginTop: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "gray", dimColor: true, italic: true }, "(Press Enter to send)")));
336
+ 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) => {
337
+ const isSelected = idx === selectedIndex;
338
+ 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)));
339
+ })), /* @__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)")));
340
+ };
341
+ AskUserModal_default = AskUserModal;
312
342
  }
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
-
320
- // src/app.jsx
321
- import gradient from "gradient-string";
322
-
323
- // src/utils/secrets.js
324
- import fs2 from "fs-extra";
343
+ });
325
344
 
326
345
  // src/utils/crypto.js
327
346
  import fs from "fs";
328
347
  import path from "path";
329
- var XOR_KEY = 66;
330
- var xorTransform = (data) => {
331
- const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
332
- const result = Buffer.alloc(buffer.length);
333
- for (let i = 0; i < buffer.length; i++) {
334
- result[i] = buffer[i] ^ XOR_KEY;
335
- }
336
- return result;
337
- };
338
- var readEncryptedJson = (filePath, defaultValue = {}) => {
339
- try {
340
- if (!fs.existsSync(filePath)) return defaultValue;
341
- const encryptedData = fs.readFileSync(filePath);
342
- const decryptedData = xorTransform(encryptedData).toString();
343
- return JSON.parse(decryptedData);
344
- } catch (err) {
345
- console.error(`Vault Read Error [${path.basename(filePath)}]:`, err.message);
346
- return defaultValue;
347
- }
348
- };
349
- var writeEncryptedJson = (filePath, data) => {
350
- try {
351
- const dir = path.dirname(filePath);
352
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
353
- const jsonData = JSON.stringify(data, null, 2);
354
- const encryptedData = xorTransform(jsonData);
355
- fs.writeFileSync(filePath, encryptedData);
356
- } catch (err) {
357
- console.error(`Vault Write Error [${path.basename(filePath)}]:`, err.message);
348
+ var XOR_KEY, xorTransform, readEncryptedJson, writeEncryptedJson;
349
+ var init_crypto = __esm({
350
+ "src/utils/crypto.js"() {
351
+ XOR_KEY = 66;
352
+ xorTransform = (data) => {
353
+ const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
354
+ const result = Buffer.alloc(buffer.length);
355
+ for (let i = 0; i < buffer.length; i++) {
356
+ result[i] = buffer[i] ^ XOR_KEY;
357
+ }
358
+ return result;
359
+ };
360
+ readEncryptedJson = (filePath, defaultValue = {}) => {
361
+ try {
362
+ if (!fs.existsSync(filePath)) return defaultValue;
363
+ const encryptedData = fs.readFileSync(filePath);
364
+ const decryptedData = xorTransform(encryptedData).toString();
365
+ return JSON.parse(decryptedData);
366
+ } catch (err) {
367
+ console.error(`Vault Read Error [${path.basename(filePath)}]:`, err.message);
368
+ return defaultValue;
369
+ }
370
+ };
371
+ writeEncryptedJson = (filePath, data) => {
372
+ try {
373
+ const dir = path.dirname(filePath);
374
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
375
+ const jsonData = JSON.stringify(data, null, 2);
376
+ const encryptedData = xorTransform(jsonData);
377
+ fs.writeFileSync(filePath, encryptedData);
378
+ } catch (err) {
379
+ console.error(`Vault Write Error [${path.basename(filePath)}]:`, err.message);
380
+ }
381
+ };
358
382
  }
359
- };
383
+ });
360
384
 
361
385
  // src/utils/paths.js
362
386
  import os from "os";
363
387
  import path2 from "path";
364
- var FLUXFLOW_DIR = path2.join(os.homedir(), ".fluxflow");
365
- var LOGS_DIR = path2.join(FLUXFLOW_DIR, "logs");
366
- var SECRET_DIR = path2.join(FLUXFLOW_DIR, "secret");
367
- var SETTINGS_FILE = path2.join(FLUXFLOW_DIR, "settings.json");
368
- var HISTORY_FILE = path2.join(SECRET_DIR, "history.json");
369
- var USAGE_FILE = path2.join(SECRET_DIR, "usage.json");
370
- var MEMORIES_FILE = path2.join(SECRET_DIR, "memories.json");
371
- var TEMP_MEM_FILE = path2.join(SECRET_DIR, "memory-temp.json");
388
+ var FLUXFLOW_DIR, LOGS_DIR, SECRET_DIR, SETTINGS_FILE, HISTORY_FILE, USAGE_FILE, MEMORIES_FILE, TEMP_MEM_FILE;
389
+ var init_paths = __esm({
390
+ "src/utils/paths.js"() {
391
+ FLUXFLOW_DIR = path2.join(os.homedir(), ".fluxflow");
392
+ LOGS_DIR = path2.join(FLUXFLOW_DIR, "logs");
393
+ SECRET_DIR = path2.join(FLUXFLOW_DIR, "secret");
394
+ SETTINGS_FILE = path2.join(FLUXFLOW_DIR, "settings.json");
395
+ HISTORY_FILE = path2.join(SECRET_DIR, "history.json");
396
+ USAGE_FILE = path2.join(SECRET_DIR, "usage.json");
397
+ MEMORIES_FILE = path2.join(SECRET_DIR, "memories.json");
398
+ TEMP_MEM_FILE = path2.join(SECRET_DIR, "memory-temp.json");
399
+ }
400
+ });
372
401
 
373
402
  // src/utils/secrets.js
403
+ import fs2 from "fs-extra";
374
404
  import path3 from "path";
375
- var SECRET_FILE = path3.join(SECRET_DIR, "secrets.json");
376
- var getAPIKey = async () => {
377
- try {
378
- const secrets = readEncryptedJson(SECRET_FILE, {});
379
- if (secrets.API_KEY) return secrets.API_KEY;
380
- } catch (e) {
381
- }
382
- return null;
383
- };
384
- var saveSecret = async (key, value) => {
385
- await fs2.ensureDir(SECRET_DIR);
386
- let current = readEncryptedJson(SECRET_FILE, {});
387
- current[key] = value;
388
- writeEncryptedJson(SECRET_FILE, current);
389
- };
390
- var saveAPIKey = async (apiKey) => saveSecret("API_KEY", apiKey);
391
- var removeSecret = async (key) => {
392
- try {
393
- const secrets = readEncryptedJson(SECRET_FILE, {});
394
- delete secrets[key];
395
- writeEncryptedJson(SECRET_FILE, secrets);
396
- } catch (e) {
405
+ var SECRET_FILE, getAPIKey, saveSecret, saveAPIKey, removeSecret, removeAPIKey;
406
+ var init_secrets = __esm({
407
+ "src/utils/secrets.js"() {
408
+ init_crypto();
409
+ init_paths();
410
+ SECRET_FILE = path3.join(SECRET_DIR, "secrets.json");
411
+ getAPIKey = async () => {
412
+ try {
413
+ const secrets = readEncryptedJson(SECRET_FILE, {});
414
+ if (secrets.API_KEY) return secrets.API_KEY;
415
+ } catch (e) {
416
+ }
417
+ return null;
418
+ };
419
+ saveSecret = async (key, value) => {
420
+ await fs2.ensureDir(SECRET_DIR);
421
+ let current = readEncryptedJson(SECRET_FILE, {});
422
+ current[key] = value;
423
+ writeEncryptedJson(SECRET_FILE, current);
424
+ };
425
+ saveAPIKey = async (apiKey) => saveSecret("API_KEY", apiKey);
426
+ removeSecret = async (key) => {
427
+ try {
428
+ const secrets = readEncryptedJson(SECRET_FILE, {});
429
+ delete secrets[key];
430
+ writeEncryptedJson(SECRET_FILE, secrets);
431
+ } catch (e) {
432
+ }
433
+ };
434
+ removeAPIKey = async () => removeSecret("API_KEY");
397
435
  }
398
- };
399
- var removeAPIKey = async () => removeSecret("API_KEY");
400
-
401
- // src/utils/ai.js
402
- import { GoogleGenAI, ThinkingLevel } from "@google/genai";
436
+ });
403
437
 
404
438
  // src/data/main_tools.js
405
- var TOOL_PROTOCOL = (mode) => `
439
+ var TOOL_PROTOCOL;
440
+ var init_main_tools = __esm({
441
+ "src/data/main_tools.js"() {
442
+ TOOL_PROTOCOL = (mode) => `
406
443
  -- START FUNCTION CALLING PROTOCOL --
407
444
  You have access to internal tools. To call a tool, you MUST use the following exact syntax on a new line:
408
445
  tool:functions.tool_name(arguments)
@@ -426,9 +463,14 @@ WHEN CALLING TOOLS, YOU **MUST** end your response with '[turn: continue]'. NEVE
426
463
  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.
427
464
  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.
428
465
  -- END FUNCTION CALLING PROTOCOL --`.trim();
466
+ }
467
+ });
429
468
 
430
469
  // src/data/janitor_tools.js
431
- var JANITOR_TOOLS_PROTOCOL = (isMemoryEnabled = true, needTitle = false) => `
470
+ var JANITOR_TOOLS_PROTOCOL;
471
+ var init_janitor_tools = __esm({
472
+ "src/data/janitor_tools.js"() {
473
+ JANITOR_TOOLS_PROTOCOL = (isMemoryEnabled = true, needTitle = false) => `
432
474
  ${needTitle ? `-- START CHAT MANAGEMENT TOOLS --
433
475
  1. YOU MUST UPDATE CHAT TITLE (URGENT PRIORITY):
434
476
  tool:functions.chat(title='<short summary of conversation in 3-5 words>')
@@ -450,38 +492,51 @@ ${isMemoryEnabled ? `2. User-specific long-term memory (USE BASED ON CONVERSATIO
450
492
  Usage Rules:
451
493
  - Frequency for 'user' action: Only when explicit context from chat is found or explicitly requested by the user.` : ""}
452
494
  -- END MEMORY TOOLS --`.trim();
495
+ }
496
+ });
453
497
 
454
498
  // src/data/thinking_prompts.json
455
- var thinking_prompts_default = {
456
- Max: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: MAX\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\ncontinue.\n\\n\\n\n</think>\\n\\n\n\n(MUST START THE RESPONSE IN NEW LINE AFTER ENDING THINKING BLOCK)\n\n**CRITICAL**: Heading blocks: **MIN 10**, **MAX 30**. EACH HEADING SHOULD HAVE MIN 6, MAX 10 STEPS OF INTERNAL MONOLOGUE. EXPLORE EDGE CASES & NUANCES.\n\nNEVER WRITE FUNCTION CALLS IN THINKING BLOCK WITH 'tool:' PREFIX AND NEVER WRITE '[turn: ...]' INSIDE THINKING BLOCK.\n-- END THINKING INSTRUCTIONS --",
457
- High: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: HIGH\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\ncontinue.\n\\n\\n\n</think>\\n\\n\n\n(MUST START THE RESPONSE IN NEW LINE AFTER ENDING THINKING BLOCK)\n\n**CRITICAL**: Heading blocks: **MIN 8**, **MAX 25**. EACH HEADING SHOULD HAVE MIN 4, MAX 8 STEPS OF INTERNAL MONOLOGUE. EXPLORE EDGE CASES & THINK LONGER before responding.\nNEVER WRITE FUNCTION CALLS IN THINKING BLOCK WITH 'tool:' PREFIX AND NEVER WRITE '[turn: ...]' INSIDE THINKING BLOCK.\n-- END THINKING INSTRUCTIONS --",
458
- Medium: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: MEDIUM\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\ncontinue.\n\\n\\n\n</think>\\n\\n\n\n(MUST START THE RESPONSE IN NEW LINE AFTER ENDING THINKING BLOCK)\n\n**CRITICAL**: Heading blocks: **MIN 5**, **MAX 9**. EACH HEADING SHOULD HAVE MIN 4, MAX 6 STEPS OF INTERNAL MONOLOGUE. THINK LONGER FOR COMPLEX QUERIES.\nNEVER WRITE FUNCTION CALLS IN THINKING BLOCK WITH 'tool:' PREFIX AND NEVER WRITE '[turn: ...]' INSIDE THINKING BLOCK.\n-- END THINKING INSTRUCTIONS --",
459
- Minimal: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: LOW\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\ncontinue.\n\\n\\n\n</think>\\n\\n\n\n(MUST START THE RESPONSE IN NEW LINE AFTER ENDING THINKING BLOCK)\n\n**CRITICAL**: Heading blocks: **MIN 0**, **MAX 3**. EACH HEADING SHOULD HAVE MIN 1, MAX 2 STEPS OF INTERNAL MONOLOGUE. No Thinking is preferred if query is simple.\nNEVER WRITE FUNCTION CALLS IN THINKING BLOCK WITH 'tool:' PREFIX AND NEVER WRITE '[turn: ...]' INSIDE THINKING BLOCK.\n-- END THINKING INSTRUCTIONS --"
460
- };
499
+ var thinking_prompts_default;
500
+ var init_thinking_prompts = __esm({
501
+ "src/data/thinking_prompts.json"() {
502
+ thinking_prompts_default = {
503
+ Max: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: MAX\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\ncontinue.\n\\n\\n\n</think>\\n\\n\n\n(MUST START THE RESPONSE IN NEW LINE AFTER ENDING THINKING BLOCK)\n\n**CRITICAL**: Heading blocks: **MIN 10**, **MAX 30**. EACH HEADING SHOULD HAVE MIN 6, MAX 10 STEPS OF INTERNAL MONOLOGUE. EXPLORE EDGE CASES & NUANCES.\n\nNEVER WRITE FUNCTION CALLS IN THINKING BLOCK WITH 'tool:' PREFIX AND NEVER WRITE '[turn: ...]' INSIDE THINKING BLOCK.\n-- END THINKING INSTRUCTIONS --",
504
+ High: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: HIGH\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\ncontinue.\n\\n\\n\n</think>\\n\\n\n\n(MUST START THE RESPONSE IN NEW LINE AFTER ENDING THINKING BLOCK)\n\n**CRITICAL**: Heading blocks: **MIN 8**, **MAX 25**. EACH HEADING SHOULD HAVE MIN 4, MAX 8 STEPS OF INTERNAL MONOLOGUE. EXPLORE EDGE CASES & THINK LONGER before responding.\nNEVER WRITE FUNCTION CALLS IN THINKING BLOCK WITH 'tool:' PREFIX AND NEVER WRITE '[turn: ...]' INSIDE THINKING BLOCK.\n-- END THINKING INSTRUCTIONS --",
505
+ Medium: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: MEDIUM\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\ncontinue.\n\\n\\n\n</think>\\n\\n\n\n(MUST START THE RESPONSE IN NEW LINE AFTER ENDING THINKING BLOCK)\n\n**CRITICAL**: Heading blocks: **MIN 5**, **MAX 9**. EACH HEADING SHOULD HAVE MIN 4, MAX 6 STEPS OF INTERNAL MONOLOGUE. THINK LONGER FOR COMPLEX QUERIES.\nNEVER WRITE FUNCTION CALLS IN THINKING BLOCK WITH 'tool:' PREFIX AND NEVER WRITE '[turn: ...]' INSIDE THINKING BLOCK.\n-- END THINKING INSTRUCTIONS --",
506
+ Minimal: "-- START THINKING INSTRUCTIONS --\nEFFORT_LEVEL: LOW\nThink Step by Step in Chain-of-Thought. Provide the thinking in <think>...</think> block, length given. Thinking should be structured in this format:\n\n<think>\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\n\\n\\n\n**Heading-ing**\n\\n\\n\n* steps...\ncontinue.\n\\n\\n\n</think>\\n\\n\n\n(MUST START THE RESPONSE IN NEW LINE AFTER ENDING THINKING BLOCK)\n\n**CRITICAL**: Heading blocks: **MIN 0**, **MAX 3**. EACH HEADING SHOULD HAVE MIN 1, MAX 2 STEPS OF INTERNAL MONOLOGUE. No Thinking is preferred if query is simple.\nNEVER WRITE FUNCTION CALLS IN THINKING BLOCK WITH 'tool:' PREFIX AND NEVER WRITE '[turn: ...]' INSIDE THINKING BLOCK.\n-- END THINKING INSTRUCTIONS --"
507
+ };
508
+ }
509
+ });
461
510
 
462
511
  // src/utils/prompts.js
463
- var getSystemInstruction = (profile, thinkingLevel, mode, systemSettings, tempMemories = "", userMemories = "", isMemoryEnabled = true, isContext50 = false) => {
464
- let levelKey = thinkingLevel;
465
- if (thinkingLevel === "Low") levelKey = "Minimal";
466
- if (thinkingLevel === "xHigh" || thinkingLevel === "Max") levelKey = "Max";
467
- const thinkingConfig = thinking_prompts_default[levelKey] || thinking_prompts_default["Medium"];
468
- const osDetected = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
469
- const nameStr = profile.name && profile.name?.length > 0 ? `User Name: ${profile.name}` : "";
470
- const nicknameStr = profile.nickname && profile.nickname?.length > 0 ? `. User Nickname: ${profile.nickname}.` : "";
471
- const userInstrStr = profile.instructions && profile.instructions?.length > 0 ? `. User Instructions: ${profile.instructions}.` : "";
472
- const dateTimeStr = (/* @__PURE__ */ new Date()).toLocaleString();
473
- const cwdStr = process.cwd();
474
- const tempMemoriesStr = tempMemories?.length > 0 && !isContext50 ? `
512
+ var getSystemInstruction, getJanitorInstruction;
513
+ var init_prompts = __esm({
514
+ "src/utils/prompts.js"() {
515
+ init_main_tools();
516
+ init_janitor_tools();
517
+ init_thinking_prompts();
518
+ getSystemInstruction = (profile, thinkingLevel, mode, systemSettings, tempMemories = "", userMemories = "", isMemoryEnabled = true, isContext50 = false) => {
519
+ let levelKey = thinkingLevel;
520
+ if (thinkingLevel === "Low") levelKey = "Minimal";
521
+ if (thinkingLevel === "xHigh" || thinkingLevel === "Max") levelKey = "Max";
522
+ const thinkingConfig = thinking_prompts_default[levelKey] || thinking_prompts_default["Medium"];
523
+ const osDetected = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
524
+ const nameStr = profile.name && profile.name?.length > 0 ? `User Name: ${profile.name}` : "";
525
+ const nicknameStr = profile.nickname && profile.nickname?.length > 0 ? `. User Nickname: ${profile.nickname}.` : "";
526
+ const userInstrStr = profile.instructions && profile.instructions?.length > 0 ? `. User Instructions: ${profile.instructions}.` : "";
527
+ const dateTimeStr = (/* @__PURE__ */ new Date()).toLocaleString();
528
+ const cwdStr = process.cwd();
529
+ const tempMemoriesStr = tempMemories?.length > 0 && !isContext50 ? `
475
530
  -- RECENT CONTEXT FROM OTHER CHAT THREADS --
476
531
  ${tempMemories}
477
532
  ------------------------------------------
478
533
  ` : "";
479
- const userMemoriesStr = userMemories?.length > 0 ? `
534
+ const userMemoriesStr = userMemories?.length > 0 ? `
480
535
  --- PERSISTENT USER MEMORIES ---
481
536
  ${userMemories}
482
537
  --------------------------------
483
538
  ` : "";
484
- return `${isMemoryEnabled ? `${userMemoriesStr}
539
+ return `${isMemoryEnabled ? `${userMemoriesStr}
485
540
 
486
541
  ` : ""}${isMemoryEnabled ? `${tempMemoriesStr}
487
542
 
@@ -490,6 +545,7 @@ You are Flux Flow (made by Kushal Roy Chowdhury/Flux Flow Team). A CLI Agent. Yo
490
545
  CURRENT_WORKING_DIRECTORY: ${cwdStr}.
491
546
  OS: ${osDetected}. ${osDetected && mode == "Flux" ? "Your terminal commands will run on CMD. Prefer PS scripts via CMD instead of raw CMD commands." : ""}
492
547
  ${nameStr}${nicknameStr}${userInstrStr}
548
+ If you see a [STEERING HINT] from user, give that prompt priority, user can use it to help you guide if you go wrong way.
493
549
 
494
550
  ${thinkingConfig}
495
551
 
@@ -530,9 +586,9 @@ When you 'finish' an agentic loop, you will lose your previous turn 'thinking' d
530
586
  -- END REPONSE FINISH PROTOCOL --
531
587
  Current date and Time is: ${dateTimeStr}
532
588
  --- END SYSTEM INSTRUCTION ---`.trim();
533
- };
534
- var getJanitorInstruction = (originalText, agentRaws, userMemories = "", isMemoryEnabled = true, needTitle = false) => {
535
- return `ORIGINAL USER PROMPT: ${originalText.substring(0, 500)}
589
+ };
590
+ getJanitorInstruction = (originalText, agentRaws, userMemories = "", isMemoryEnabled = true, needTitle = false) => {
591
+ return `ORIGINAL USER PROMPT: ${originalText.substring(0, 500)}
536
592
  AGENT RAWS (responses from this turn):
537
593
  ${agentRaws.substring(0, 2e3).replace(/tool:functions\..*\n/g, "").replace(/<think>.*<\/think>/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[turn: continue\]/g, "").replace(/\[turn: finish\]/g, "")}${agentRaws.length > 1500 ? "\n... (truncated) ..." : ""}
538
594
 
@@ -557,1218 +613,1338 @@ ${userMemories}
557
613
  Current date and Time: ${(/* @__PURE__ */ new Date()).toLocaleString()}
558
614
 
559
615
  --- END SYSTEM INSTRUCTION ---`.trim();
560
- };
616
+ };
617
+ }
618
+ });
561
619
 
562
620
  // src/utils/history.js
563
621
  import fs3 from "fs-extra";
564
622
  import path4 from "path";
565
623
  import { nanoid } from "nanoid";
566
- var WRITE_LOCK = Promise.resolve();
567
- var withLock = (op) => {
568
- const nextLock = WRITE_LOCK.then(async () => {
569
- try {
570
- return await op();
571
- } catch (e) {
572
- console.error("Lock Operation Failed:", e);
573
- throw e;
574
- }
575
- });
576
- WRITE_LOCK = nextLock.catch(() => {
577
- });
578
- return nextLock;
579
- };
580
- var loadHistory = async () => {
581
- if (await fs3.pathExists(HISTORY_FILE)) {
582
- try {
583
- return await fs3.readJson(HISTORY_FILE);
584
- } catch (e) {
624
+ var WRITE_LOCK, withLock, loadHistory, saveChat, saveChatTitle, deleteChat, generateChatId, cleanupOldHistory, getTruncatedHistory;
625
+ var init_history = __esm({
626
+ "src/utils/history.js"() {
627
+ init_crypto();
628
+ init_paths();
629
+ WRITE_LOCK = Promise.resolve();
630
+ withLock = (op) => {
631
+ const nextLock = WRITE_LOCK.then(async () => {
632
+ try {
633
+ return await op();
634
+ } catch (e) {
635
+ console.error("Lock Operation Failed:", e);
636
+ throw e;
637
+ }
638
+ });
639
+ WRITE_LOCK = nextLock.catch(() => {
640
+ });
641
+ return nextLock;
642
+ };
643
+ loadHistory = async () => {
644
+ if (await fs3.pathExists(HISTORY_FILE)) {
645
+ try {
646
+ return await fs3.readJson(HISTORY_FILE);
647
+ } catch (e) {
648
+ return {};
649
+ }
650
+ }
585
651
  return {};
586
- }
587
- }
588
- return {};
589
- };
590
- var saveChat = async (id, name, messages) => {
591
- return withLock(async () => {
592
- const history = await loadHistory();
593
- const existingChat = history[id];
594
- const finalName = name || (existingChat ? existingChat.name : `Session ${id.slice(-6)}`);
595
- history[id] = {
596
- name: finalName,
597
- messages,
598
- updatedAt: Date.now()
599
652
  };
600
- await fs3.ensureDir(path4.dirname(HISTORY_FILE));
601
- await fs3.writeJson(HISTORY_FILE, history, { spaces: 2 });
602
- });
603
- };
604
- var saveChatTitle = async (id, title) => {
605
- return withLock(async () => {
606
- const history = await loadHistory();
607
- if (history[id]) {
608
- history[id].name = title;
609
- history[id].updatedAt = Date.now();
610
- } else {
611
- history[id] = { name: title, messages: [], updatedAt: Date.now() };
612
- }
613
- await fs3.ensureDir(path4.dirname(HISTORY_FILE));
614
- await fs3.writeJson(HISTORY_FILE, history, { spaces: 2 });
615
- });
616
- };
617
- var deleteChat = async (id) => {
618
- return withLock(async () => {
619
- const history = await loadHistory();
620
- delete history[id];
621
- await fs3.writeJson(HISTORY_FILE, history, { spaces: 2 });
622
- const temp = readEncryptedJson(TEMP_MEM_FILE, {});
623
- if (temp[id]) {
624
- delete temp[id];
625
- writeEncryptedJson(TEMP_MEM_FILE, temp);
626
- }
627
- return history;
628
- });
629
- };
630
- var generateChatId = () => `flow-${nanoid(6)}`;
631
- var cleanupOldHistory = async (retentionSetting) => {
632
- if (!retentionSetting || retentionSetting === "Never") return;
633
- const days = parseInt(retentionSetting);
634
- if (isNaN(days)) return;
635
- const history = await loadHistory();
636
- const now = Date.now();
637
- const threshold = days * 24 * 60 * 60 * 1e3;
638
- let deletedCount = 0;
639
- for (const id in history) {
640
- const chat2 = history[id];
641
- if (chat2.updatedAt && now - chat2.updatedAt > threshold) {
642
- await deleteChat(id);
643
- deletedCount++;
644
- }
653
+ saveChat = async (id, name, messages) => {
654
+ return withLock(async () => {
655
+ const history = await loadHistory();
656
+ const existingChat = history[id];
657
+ const finalName = name || (existingChat ? existingChat.name : `Session ${id.slice(-6)}`);
658
+ history[id] = {
659
+ name: finalName,
660
+ messages,
661
+ updatedAt: Date.now()
662
+ };
663
+ await fs3.ensureDir(path4.dirname(HISTORY_FILE));
664
+ await fs3.writeJson(HISTORY_FILE, history, { spaces: 2 });
665
+ });
666
+ };
667
+ saveChatTitle = async (id, title) => {
668
+ return withLock(async () => {
669
+ const history = await loadHistory();
670
+ if (history[id]) {
671
+ history[id].name = title;
672
+ history[id].updatedAt = Date.now();
673
+ } else {
674
+ history[id] = { name: title, messages: [], updatedAt: Date.now() };
675
+ }
676
+ await fs3.ensureDir(path4.dirname(HISTORY_FILE));
677
+ await fs3.writeJson(HISTORY_FILE, history, { spaces: 2 });
678
+ });
679
+ };
680
+ deleteChat = async (id) => {
681
+ return withLock(async () => {
682
+ const history = await loadHistory();
683
+ delete history[id];
684
+ await fs3.writeJson(HISTORY_FILE, history, { spaces: 2 });
685
+ const temp = readEncryptedJson(TEMP_MEM_FILE, {});
686
+ if (temp[id]) {
687
+ delete temp[id];
688
+ writeEncryptedJson(TEMP_MEM_FILE, temp);
689
+ }
690
+ return history;
691
+ });
692
+ };
693
+ generateChatId = () => `flow-${nanoid(6)}`;
694
+ cleanupOldHistory = async (retentionSetting) => {
695
+ if (!retentionSetting || retentionSetting === "Never") return;
696
+ const days = parseInt(retentionSetting);
697
+ if (isNaN(days)) return;
698
+ const history = await loadHistory();
699
+ const now = Date.now();
700
+ const threshold = days * 24 * 60 * 60 * 1e3;
701
+ let deletedCount = 0;
702
+ for (const id in history) {
703
+ const chat2 = history[id];
704
+ if (chat2.updatedAt && now - chat2.updatedAt > threshold) {
705
+ await deleteChat(id);
706
+ deletedCount++;
707
+ }
708
+ }
709
+ return deletedCount;
710
+ };
711
+ getTruncatedHistory = (history, exchangesToRemove = 4) => {
712
+ if (history.length <= 1) return history;
713
+ const welcome = history[0];
714
+ const rest = history.slice(1);
715
+ const sliceIndex = exchangesToRemove * 2;
716
+ const truncated = rest.slice(sliceIndex);
717
+ return [welcome, ...truncated];
718
+ };
645
719
  }
646
- return deletedCount;
647
- };
648
- var getTruncatedHistory = (history, exchangesToRemove = 4) => {
649
- if (history.length <= 1) return history;
650
- const welcome = history[0];
651
- const rest = history.slice(1);
652
- const sliceIndex = exchangesToRemove * 2;
653
- const truncated = rest.slice(sliceIndex);
654
- return [welcome, ...truncated];
655
- };
720
+ });
656
721
 
657
722
  // src/utils/usage.js
658
723
  import fs4 from "fs-extra";
659
724
  import path5 from "path";
660
- var getDailyUsage = async () => {
661
- const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
662
- try {
663
- if (await fs4.exists(USAGE_FILE)) {
664
- const data = await fs4.readJson(USAGE_FILE);
665
- if (data.date === today) {
666
- return data.stats;
725
+ var getDailyUsage, incrementUsage, checkQuota;
726
+ var init_usage = __esm({
727
+ "src/utils/usage.js"() {
728
+ init_paths();
729
+ getDailyUsage = async () => {
730
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
731
+ try {
732
+ if (await fs4.exists(USAGE_FILE)) {
733
+ const data = await fs4.readJson(USAGE_FILE);
734
+ if (data.date === today) {
735
+ return data.stats;
736
+ }
737
+ }
738
+ } catch (err) {
739
+ console.error("Failed to read usage:", err);
667
740
  }
668
- }
669
- } catch (err) {
670
- console.error("Failed to read usage:", err);
671
- }
672
- const defaultStats = { agent: 0, background: 0, search: 0 };
673
- await fs4.ensureDir(path5.dirname(USAGE_FILE));
674
- await fs4.writeJson(USAGE_FILE, { date: today, stats: defaultStats }, { spaces: 2 });
675
- return defaultStats;
676
- };
677
- var incrementUsage = async (key) => {
678
- const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
679
- const data = await fs4.readJson(USAGE_FILE).catch(() => ({ date: today, stats: { agent: 0, background: 0, search: 0 } }));
680
- if (data.date !== today) {
681
- data.date = today;
682
- data.stats = { agent: 0, background: 0, search: 0 };
683
- }
684
- if (data.stats[key] !== void 0) {
685
- data.stats[key]++;
686
- await fs4.ensureDir(path5.dirname(USAGE_FILE));
687
- await fs4.writeJson(USAGE_FILE, data, { spaces: 2 });
688
- }
689
- };
690
- var checkQuota = async (key, settings) => {
691
- const usage = await getDailyUsage();
692
- const tier = settings.apiTier || "Free";
693
- const quotas = settings.quotas || {};
694
- if (tier === "Free") {
695
- if (key === "agent" || key === "background") {
696
- return usage.agent + usage.background < 1500;
697
- }
698
- if (key === "search") return true;
699
- }
700
- if (tier === "Paid" || tier === "Custom") {
701
- if (key === "agent") return usage.agent < (quotas.agentLimit || 1500);
702
- if (key === "background") return usage.background < (quotas.backgroundLimit || 1500);
703
- if (key === "search") return true;
704
- return true;
741
+ const defaultStats = { agent: 0, background: 0, search: 0 };
742
+ await fs4.ensureDir(path5.dirname(USAGE_FILE));
743
+ await fs4.writeJson(USAGE_FILE, { date: today, stats: defaultStats }, { spaces: 2 });
744
+ return defaultStats;
745
+ };
746
+ incrementUsage = async (key) => {
747
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
748
+ const data = await fs4.readJson(USAGE_FILE).catch(() => ({ date: today, stats: { agent: 0, background: 0, search: 0 } }));
749
+ if (data.date !== today) {
750
+ data.date = today;
751
+ data.stats = { agent: 0, background: 0, search: 0 };
752
+ }
753
+ if (data.stats[key] !== void 0) {
754
+ data.stats[key]++;
755
+ await fs4.ensureDir(path5.dirname(USAGE_FILE));
756
+ await fs4.writeJson(USAGE_FILE, data, { spaces: 2 });
757
+ }
758
+ };
759
+ checkQuota = async (key, settings) => {
760
+ const usage = await getDailyUsage();
761
+ const tier = settings.apiTier || "Free";
762
+ const quotas = settings.quotas || {};
763
+ if (tier === "Free") {
764
+ if (key === "agent" || key === "background") {
765
+ return usage.agent + usage.background < 1500;
766
+ }
767
+ if (key === "search") return true;
768
+ }
769
+ if (tier === "Paid" || tier === "Custom") {
770
+ if (key === "agent") return usage.agent < (quotas.agentLimit || 1500);
771
+ if (key === "background") return usage.background < (quotas.backgroundLimit || 1500);
772
+ if (key === "search") return true;
773
+ return true;
774
+ }
775
+ return true;
776
+ };
705
777
  }
706
- return true;
707
- };
708
-
709
- // src/tools/web_search.js
710
- import * as cuimp from "cuimp";
778
+ });
711
779
 
712
780
  // src/utils/arg_parser.js
713
- var parseArgs = (argsString) => {
714
- const args = {};
715
- const regex = /(\w+)\s*=\s*(?:(["'])((?:\\.|(?!\2)[\s\S])*)\2|([^,\s\)]+))/g;
716
- let match;
717
- while ((match = regex.exec(argsString)) !== null) {
718
- const key = match[1];
719
- let value = match[3] !== void 0 ? match[3] : match[4];
720
- if (match[3] !== void 0) {
721
- try {
722
- value = JSON.parse(`"${value.replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`);
723
- } catch (e) {
724
- value = value.replace(/\\"/g, '"').replace(/\\'/g, "'").replace(/\\\\/g, "\\");
781
+ var parseArgs;
782
+ var init_arg_parser = __esm({
783
+ "src/utils/arg_parser.js"() {
784
+ parseArgs = (argsString) => {
785
+ const args = {};
786
+ const regex = /(\w+)\s*=\s*(?:(["'])((?:\\.|(?!\2)[\s\S])*)\2|([^,\s\)]+))/g;
787
+ let match;
788
+ while ((match = regex.exec(argsString)) !== null) {
789
+ const key = match[1];
790
+ let value = match[3] !== void 0 ? match[3] : match[4];
791
+ if (match[3] !== void 0) {
792
+ try {
793
+ value = JSON.parse(`"${value.replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`);
794
+ } catch (e) {
795
+ value = value.replace(/\\"/g, '"').replace(/\\'/g, "'").replace(/\\\\/g, "\\");
796
+ }
797
+ }
798
+ if (value === "true") value = true;
799
+ else if (value === "false") value = false;
800
+ else if (typeof value === "string" && !isNaN(value) && value.trim() !== "") value = Number(value);
801
+ args[key] = value;
725
802
  }
726
- }
727
- if (value === "true") value = true;
728
- else if (value === "false") value = false;
729
- else if (typeof value === "string" && !isNaN(value) && value.trim() !== "") value = Number(value);
730
- args[key] = value;
803
+ return args;
804
+ };
731
805
  }
732
- return args;
733
- };
806
+ });
734
807
 
735
808
  // src/tools/web_search.js
809
+ import * as cuimp from "cuimp";
736
810
  import fs5 from "fs";
737
811
  import path6 from "path";
738
- var web_search = async (argsString) => {
739
- const { query, limit = 10 } = parseArgs(argsString);
740
- if (!query) return 'ERROR: Missing "query" argument for web_search.';
741
- try {
742
- await new Promise((r) => setTimeout(r, Math.random() * 1e3 + 500));
743
- const response = await cuimp.get(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`, {
744
- headers: {
745
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
746
- }
747
- });
748
- const html = response.data;
749
- const results = [];
750
- const resultRegex = /<a[^>]*class="result__a"[^>]*href="([^"]+)"[^>]*>([\s\S]*?)<\/a>[\s\S]*?<a[^>]*class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g;
751
- let match;
752
- let count = 0;
753
- while ((match = resultRegex.exec(html)) !== null && count < limit) {
754
- let url = match[1];
755
- if (url.includes("uddg=")) {
756
- url = decodeURIComponent(url.split("uddg=")[1].split("&")[0]);
757
- }
758
- const title = match[2].replace(/<[^>]*>/g, "").trim();
759
- const snippet = match[3].replace(/<[^>]*>/g, "").trim();
760
- results.push(`${count + 1}. ${title}
812
+ var web_search;
813
+ var init_web_search = __esm({
814
+ "src/tools/web_search.js"() {
815
+ init_arg_parser();
816
+ init_paths();
817
+ web_search = async (argsString) => {
818
+ const { query, limit = 10 } = parseArgs(argsString);
819
+ if (!query) return 'ERROR: Missing "query" argument for web_search.';
820
+ try {
821
+ await new Promise((r) => setTimeout(r, Math.random() * 1e3 + 500));
822
+ const response = await cuimp.get(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`, {
823
+ headers: {
824
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
825
+ }
826
+ });
827
+ const html = response.data;
828
+ const results = [];
829
+ const resultRegex = /<a[^>]*class="result__a"[^>]*href="([^"]+)"[^>]*>([\s\S]*?)<\/a>[\s\S]*?<a[^>]*class="result__snippet"[^>]*>([\s\S]*?)<\/a>/g;
830
+ let match;
831
+ let count = 0;
832
+ while ((match = resultRegex.exec(html)) !== null && count < limit) {
833
+ let url = match[1];
834
+ if (url.includes("uddg=")) {
835
+ url = decodeURIComponent(url.split("uddg=")[1].split("&")[0]);
836
+ }
837
+ const title = match[2].replace(/<[^>]*>/g, "").trim();
838
+ const snippet = match[3].replace(/<[^>]*>/g, "").trim();
839
+ results.push(`${count + 1}. ${title}
761
840
  Source: ${url}
762
841
  Snippet: ${snippet}`);
763
- count++;
764
- }
765
- const toolLogDir = path6.join(LOGS_DIR, "tools");
766
- if (!fs5.existsSync(toolLogDir)) {
767
- fs5.mkdirSync(toolLogDir, { recursive: true });
768
- }
769
- fs5.appendFileSync(path6.join(toolLogDir, "search-results.log"), `RESULTS ${(/* @__PURE__ */ new Date()).toISOString()} -
842
+ count++;
843
+ }
844
+ const toolLogDir = path6.join(LOGS_DIR, "tools");
845
+ if (!fs5.existsSync(toolLogDir)) {
846
+ fs5.mkdirSync(toolLogDir, { recursive: true });
847
+ }
848
+ fs5.appendFileSync(path6.join(toolLogDir, "search-results.log"), `RESULTS ${(/* @__PURE__ */ new Date()).toISOString()} -
770
849
  Query: [${query}]. Results Count: ${results.length}.
771
850
  Results: ${results}
772
851
 
773
852
 
774
853
  `);
775
- if (results.length === 0) {
776
- if (html.includes("anomaly")) {
777
- const toolErrDir = path6.join(LOGS_DIR, "tools");
778
- if (!fs5.existsSync(toolErrDir)) {
779
- fs5.mkdirSync(toolErrDir, { recursive: true });
780
- }
781
- fs5.appendFileSync(path6.join(toolErrDir, "error.log"), `ERROR ${(/* @__PURE__ */ new Date()).toISOString()} - DDG detected unusual activity. Cuimp impersonation might need adjustment.
854
+ if (results.length === 0) {
855
+ if (html.includes("anomaly")) {
856
+ const toolErrDir = path6.join(LOGS_DIR, "tools");
857
+ if (!fs5.existsSync(toolErrDir)) {
858
+ fs5.mkdirSync(toolErrDir, { recursive: true });
859
+ }
860
+ fs5.appendFileSync(path6.join(toolErrDir, "error.log"), `ERROR ${(/* @__PURE__ */ new Date()).toISOString()} - DDG detected unusual activity. Cuimp impersonation might need adjustment.
782
861
  `);
783
- throw new Error("DDG detected unusual activity. Cuimp impersonation might need adjustment.");
784
- }
785
- return `No results found for query: [${query}].`;
786
- }
787
- const finalResults = results.join("\n\n");
788
- return `Search results for [${query}]:
862
+ throw new Error("DDG detected unusual activity. Cuimp impersonation might need adjustment.");
863
+ }
864
+ return `No results found for query: [${query}].`;
865
+ }
866
+ const finalResults = results.join("\n\n");
867
+ return `Search results for [${query}]:
789
868
 
790
869
  ${finalResults}`;
791
- } catch (err) {
792
- return `ERROR: Stealth Search failed. ${err.message}`;
870
+ } catch (err) {
871
+ return `ERROR: Stealth Search failed. ${err.message}`;
872
+ }
873
+ };
793
874
  }
794
- };
875
+ });
795
876
 
796
877
  // src/tools/web_scrape.js
797
878
  import fs6 from "fs";
798
879
  import path7 from "path";
799
880
  import * as cuimp2 from "cuimp";
800
- var web_scrape = async (args) => {
801
- const urlMatch = args.match(/url\s*=\s*["'](.*)["']/);
802
- const url = urlMatch ? urlMatch[1] : args;
803
- try {
804
- const response = await cuimp2.get(url, {
805
- headers: {
806
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
807
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
808
- "Accept-Language": "en-US,en;q=0.5"
809
- }
810
- });
811
- let html = response.data;
812
- if (!html) throw new Error("No content received from URL.");
813
- html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "");
814
- html = html.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, "");
815
- html = html.replace(/<nav\b[^<]*(?:(?!<\/nav>)<[^<]*)*<\/nav>/gi, "");
816
- html = html.replace(/<footer\b[^<]*(?:(?!<\/footer>)<[^<]*)*<\/footer>/gi, "");
817
- html = html.replace(/<header\b[^<]*(?:(?!<\/header>)<[^<]*)*<\/header>/gi, "");
818
- let text = html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
819
- const finalContent = text.substring(0, 2e4);
820
- const toolLogDir = path7.join(LOGS_DIR, "tools");
821
- if (!fs6.existsSync(toolLogDir)) {
822
- fs6.mkdirSync(toolLogDir, { recursive: true });
823
- }
824
- fs6.appendFileSync(path7.join(toolLogDir, "search-scraped.log"), `RESULTS ${(/* @__PURE__ */ new Date()).toISOString()} -
881
+ var web_scrape;
882
+ var init_web_scrape = __esm({
883
+ "src/tools/web_scrape.js"() {
884
+ init_paths();
885
+ web_scrape = async (args) => {
886
+ const urlMatch = args.match(/url\s*=\s*["'](.*)["']/);
887
+ const url = urlMatch ? urlMatch[1] : args;
888
+ try {
889
+ const response = await cuimp2.get(url, {
890
+ headers: {
891
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
892
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
893
+ "Accept-Language": "en-US,en;q=0.5"
894
+ }
895
+ });
896
+ let html = response.data;
897
+ if (!html) throw new Error("No content received from URL.");
898
+ html = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "");
899
+ html = html.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, "");
900
+ html = html.replace(/<nav\b[^<]*(?:(?!<\/nav>)<[^<]*)*<\/nav>/gi, "");
901
+ html = html.replace(/<footer\b[^<]*(?:(?!<\/footer>)<[^<]*)*<\/footer>/gi, "");
902
+ html = html.replace(/<header\b[^<]*(?:(?!<\/header>)<[^<]*)*<\/header>/gi, "");
903
+ let text = html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
904
+ const finalContent = text.substring(0, 2e4);
905
+ const toolLogDir = path7.join(LOGS_DIR, "tools");
906
+ if (!fs6.existsSync(toolLogDir)) {
907
+ fs6.mkdirSync(toolLogDir, { recursive: true });
908
+ }
909
+ fs6.appendFileSync(path7.join(toolLogDir, "search-scraped.log"), `RESULTS ${(/* @__PURE__ */ new Date()).toISOString()} -
825
910
  Query: [${url}].
826
911
  Results: ${finalContent}
827
912
 
828
913
 
829
914
  `);
830
- return `CONTENT FROM [${url}]:
915
+ return `CONTENT FROM [${url}]:
831
916
 
832
917
  ${finalContent}${text.length > 2e4 ? "\n\n[TRUNCATED AT 20K CHARS]" : ""}`;
833
- } catch (err) {
834
- return `ERROR: Failed to read page at ${url}. ${err.message}`;
918
+ } catch (err) {
919
+ return `ERROR: Failed to read page at ${url}. ${err.message}`;
920
+ }
921
+ };
835
922
  }
836
- };
923
+ });
837
924
 
838
925
  // src/tools/memory.js
839
- var memory = async (rawArgs, context = {}) => {
840
- const parseArg = (key) => {
841
- const regex = new RegExp(`${key}\\s*=\\s*(["'])(.*?)\\1(?=\\s*[,)]|\\s+\\w+\\s*=|$)`, "s");
842
- const match = rawArgs.match(regex);
843
- return match ? match[2].trim() : null;
844
- };
845
- const action = parseArg("action");
846
- const method = parseArg("method");
847
- const content = parseArg("content");
848
- const contentNew = parseArg("content-new");
849
- const contentOld = parseArg("content-old");
850
- const chatId = parseArg("chat-id") || context.chatId || context.sessionId || "default-session";
851
- if (action === "temp") {
852
- if (!content) return "ERROR: Missing 'content' for temp memory.";
853
- const tempStorage = readEncryptedJson(TEMP_MEM_FILE, {});
854
- if (!tempStorage[chatId]) tempStorage[chatId] = [];
855
- const MAX_CHARS = 3e3 * 4;
856
- let currentTotalLength = tempStorage[chatId].reduce((acc, m) => acc + m.length, 0);
857
- while (tempStorage[chatId].length > 0 && currentTotalLength + content.length > MAX_CHARS) {
858
- const removed = tempStorage[chatId].shift();
859
- currentTotalLength -= removed.length;
860
- }
861
- tempStorage[chatId].push(content);
862
- writeEncryptedJson(TEMP_MEM_FILE, tempStorage);
863
- return `SUCCESS: Temporary context saved for session [${chatId}]. (Size: ${currentTotalLength + content.length} chars)`;
864
- }
865
- if (action === "user") {
866
- const memories = readEncryptedJson(MEMORIES_FILE, []);
867
- if (method === "add") {
868
- if (!content) return "ERROR: Missing 'content' for memory addition.";
869
- const MAX_CHARS = 2e3 * 4;
870
- let currentTotalLength = memories.reduce((acc, m) => acc + (m.memory?.length || 0), 0);
871
- while (memories.length > 0 && currentTotalLength + content.length > MAX_CHARS) {
872
- const removed = memories.shift();
873
- currentTotalLength -= removed.memory?.length || 0;
926
+ var memory;
927
+ var init_memory = __esm({
928
+ "src/tools/memory.js"() {
929
+ init_crypto();
930
+ init_paths();
931
+ memory = async (rawArgs, context = {}) => {
932
+ const parseArg = (key) => {
933
+ const regex = new RegExp(`${key}\\s*=\\s*(["'])(.*?)\\1(?=\\s*[,)]|\\s+\\w+\\s*=|$)`, "s");
934
+ const match = rawArgs.match(regex);
935
+ return match ? match[2].trim() : null;
936
+ };
937
+ const action = parseArg("action");
938
+ const method = parseArg("method");
939
+ const content = parseArg("content");
940
+ const contentNew = parseArg("content-new");
941
+ const contentOld = parseArg("content-old");
942
+ const chatId = parseArg("chat-id") || context.chatId || context.sessionId || "default-session";
943
+ if (action === "temp") {
944
+ if (!content) return "ERROR: Missing 'content' for temp memory.";
945
+ const tempStorage = readEncryptedJson(TEMP_MEM_FILE, {});
946
+ if (!tempStorage[chatId]) tempStorage[chatId] = [];
947
+ const MAX_CHARS = 3e3 * 4;
948
+ let currentTotalLength = tempStorage[chatId].reduce((acc, m) => acc + m.length, 0);
949
+ while (tempStorage[chatId].length > 0 && currentTotalLength + content.length > MAX_CHARS) {
950
+ const removed = tempStorage[chatId].shift();
951
+ currentTotalLength -= removed.length;
952
+ }
953
+ tempStorage[chatId].push(content);
954
+ writeEncryptedJson(TEMP_MEM_FILE, tempStorage);
955
+ return `SUCCESS: Temporary context saved for session [${chatId}]. (Size: ${currentTotalLength + content.length} chars)`;
874
956
  }
875
- const newMemory = { id: `mem-${Date.now().toString(36)}`, memory: content };
876
- memories.push(newMemory);
877
- writeEncryptedJson(MEMORIES_FILE, memories);
878
- return `SUCCESS: Memory added with ID [${newMemory.id}]. (Vault Size: ${currentTotalLength + content.length} chars)`;
879
- }
880
- if (method === "update") {
881
- const memId = contentOld;
882
- const newText = contentNew;
883
- if (!memId || !newText) return "ERROR: Missing 'content-old' (id) or 'content-new' for update.";
884
- const index = memories.findIndex((m) => m.id === memId);
885
- if (index === -1) return `ERROR: Memory ID [${memId}] not found.`;
886
- memories[index].memory = newText;
887
- writeEncryptedJson(MEMORIES_FILE, memories);
888
- return `SUCCESS: Memory [${memId}] updated.`;
889
- }
890
- if (method === "delete") {
891
- const memId = content;
892
- if (!memId) return "ERROR: Missing 'content' (id) for deletion.";
893
- const initialLen = memories.length;
894
- const updatedMemories = memories.filter((m) => m.id !== memId);
895
- if (updatedMemories.length === initialLen) return `ERROR: Memory ID [${memId}] not found.`;
896
- writeEncryptedJson(MEMORIES_FILE, updatedMemories);
897
- return `SUCCESS: Memory [${memId}] deleted.`;
898
- }
899
- return `ERROR: Invalid method [${method}] for user memory. Use 'add', 'update', or 'delete'.`;
957
+ if (action === "user") {
958
+ const memories = readEncryptedJson(MEMORIES_FILE, []);
959
+ if (method === "add") {
960
+ if (!content) return "ERROR: Missing 'content' for memory addition.";
961
+ const MAX_CHARS = 2e3 * 4;
962
+ let currentTotalLength = memories.reduce((acc, m) => acc + (m.memory?.length || 0), 0);
963
+ while (memories.length > 0 && currentTotalLength + content.length > MAX_CHARS) {
964
+ const removed = memories.shift();
965
+ currentTotalLength -= removed.memory?.length || 0;
966
+ }
967
+ const newMemory = { id: `mem-${Date.now().toString(36)}`, memory: content };
968
+ memories.push(newMemory);
969
+ writeEncryptedJson(MEMORIES_FILE, memories);
970
+ return `SUCCESS: Memory added with ID [${newMemory.id}]. (Vault Size: ${currentTotalLength + content.length} chars)`;
971
+ }
972
+ if (method === "update") {
973
+ const memId = contentOld;
974
+ const newText = contentNew;
975
+ if (!memId || !newText) return "ERROR: Missing 'content-old' (id) or 'content-new' for update.";
976
+ const index = memories.findIndex((m) => m.id === memId);
977
+ if (index === -1) return `ERROR: Memory ID [${memId}] not found.`;
978
+ memories[index].memory = newText;
979
+ writeEncryptedJson(MEMORIES_FILE, memories);
980
+ return `SUCCESS: Memory [${memId}] updated.`;
981
+ }
982
+ if (method === "delete") {
983
+ const memId = content;
984
+ if (!memId) return "ERROR: Missing 'content' (id) for deletion.";
985
+ const initialLen = memories.length;
986
+ const updatedMemories = memories.filter((m) => m.id !== memId);
987
+ if (updatedMemories.length === initialLen) return `ERROR: Memory ID [${memId}] not found.`;
988
+ writeEncryptedJson(MEMORIES_FILE, updatedMemories);
989
+ return `SUCCESS: Memory [${memId}] deleted.`;
990
+ }
991
+ return `ERROR: Invalid method [${method}] for user memory. Use 'add', 'update', or 'delete'.`;
992
+ }
993
+ return `ERROR: Unknown action [${action}] for memory tool.`;
994
+ };
900
995
  }
901
- return `ERROR: Unknown action [${action}] for memory tool.`;
902
- };
996
+ });
903
997
 
904
998
  // src/tools/chat.js
905
- var chat = async (rawArgs, context = {}) => {
906
- const title = parseArgs(rawArgs).title;
907
- const chatId = context.chatId || context.sessionId;
908
- if (!chatId) return "ERROR: No active chatId found in tool context.";
909
- if (!title) return "ERROR: Missing 'title' argument.";
910
- try {
911
- await saveChatTitle(chatId, title);
912
- return `SUCCESS: Chat title updated to [${title}] for session [${chatId}].`;
913
- } catch (err) {
914
- return `ERROR: Failed to update chat title: ${err.message}`;
999
+ var chat;
1000
+ var init_chat = __esm({
1001
+ "src/tools/chat.js"() {
1002
+ init_history();
1003
+ init_arg_parser();
1004
+ chat = async (rawArgs, context = {}) => {
1005
+ const title = parseArgs(rawArgs).title;
1006
+ const chatId = context.chatId || context.sessionId;
1007
+ if (!chatId) return "ERROR: No active chatId found in tool context.";
1008
+ if (!title) return "ERROR: Missing 'title' argument.";
1009
+ try {
1010
+ await saveChatTitle(chatId, title);
1011
+ return `SUCCESS: Chat title updated to [${title}] for session [${chatId}].`;
1012
+ } catch (err) {
1013
+ return `ERROR: Failed to update chat title: ${err.message}`;
1014
+ }
1015
+ };
915
1016
  }
916
- };
1017
+ });
917
1018
 
918
1019
  // src/tools/list_files.js
919
1020
  import fs7 from "fs";
920
1021
  import path8 from "path";
921
- var list_files = async (args) => {
922
- const { path: targetPath = "." } = parseArgs(args);
923
- const absolutePath = path8.resolve(process.cwd(), targetPath);
924
- try {
925
- if (!fs7.existsSync(absolutePath)) {
926
- return `ERROR: Path [${targetPath}] does not exist.`;
927
- }
928
- const stats = fs7.statSync(absolutePath);
929
- if (!stats.isDirectory()) {
930
- return `ERROR: Path [${targetPath}] is a file, not a directory. Use view_file instead.`;
931
- }
932
- const files2 = fs7.readdirSync(absolutePath);
933
- if (files2.length === 0) {
934
- return `Directory [${targetPath}] is empty.`;
935
- }
936
- const totalFiles = files2.length;
937
- const maxDisplay = 100;
938
- const displayFiles = files2.slice(0, maxDisplay);
939
- const list = displayFiles.map((file) => {
940
- const fPath = path8.join(absolutePath, file);
941
- let indicator = "\u{1F4C4}";
942
- let metaPart = "";
1022
+ var list_files;
1023
+ var init_list_files = __esm({
1024
+ "src/tools/list_files.js"() {
1025
+ init_arg_parser();
1026
+ list_files = async (args) => {
1027
+ const { path: targetPath = "." } = parseArgs(args);
1028
+ const absolutePath = path8.resolve(process.cwd(), targetPath);
943
1029
  try {
944
- const fStats = fs7.statSync(fPath);
945
- indicator = fStats.isDirectory() ? "\u{1F4C1}" : "\u{1F4C4}";
946
- const sizeKB = (fStats.size / 1024).toFixed(1);
947
- metaPart = fStats.isFile() ? ` - [${sizeKB} KB]` : "";
948
- } catch (e) {
949
- indicator = "\u2753";
950
- metaPart = " - [Access Denied]";
951
- }
952
- return `${indicator} ${file}${metaPart}`;
953
- }).join("\n");
954
- let footer = `
1030
+ if (!fs7.existsSync(absolutePath)) {
1031
+ return `ERROR: Path [${targetPath}] does not exist.`;
1032
+ }
1033
+ const stats = fs7.statSync(absolutePath);
1034
+ if (!stats.isDirectory()) {
1035
+ return `ERROR: Path [${targetPath}] is a file, not a directory. Use view_file instead.`;
1036
+ }
1037
+ const files2 = fs7.readdirSync(absolutePath);
1038
+ if (files2.length === 0) {
1039
+ return `Directory [${targetPath}] is empty.`;
1040
+ }
1041
+ const totalFiles = files2.length;
1042
+ const maxDisplay = 100;
1043
+ const displayFiles = files2.slice(0, maxDisplay);
1044
+ const list = displayFiles.map((file) => {
1045
+ const fPath = path8.join(absolutePath, file);
1046
+ let indicator = "\u{1F4C4}";
1047
+ let metaPart = "";
1048
+ try {
1049
+ const fStats = fs7.statSync(fPath);
1050
+ indicator = fStats.isDirectory() ? "\u{1F4C1}" : "\u{1F4C4}";
1051
+ const sizeKB = (fStats.size / 1024).toFixed(1);
1052
+ metaPart = fStats.isFile() ? ` - [${sizeKB} KB]` : "";
1053
+ } catch (e) {
1054
+ indicator = "\u2753";
1055
+ metaPart = " - [Access Denied]";
1056
+ }
1057
+ return `${indicator} ${file}${metaPart}`;
1058
+ }).join("\n");
1059
+ let footer = `
955
1060
 
956
1061
  (Total items: ${totalFiles})`;
957
- if (totalFiles > maxDisplay) {
958
- footer = `
1062
+ if (totalFiles > maxDisplay) {
1063
+ footer = `
959
1064
 
960
1065
  \u26A0\uFE0F TRUNCATED: Showing first ${maxDisplay} of ${totalFiles} items. Use more specific paths to see others.`;
961
- }
962
- const result = `Contents of [${targetPath}]:
1066
+ }
1067
+ const result = `Contents of [${targetPath}]:
963
1068
 
964
1069
  ${list}${footer}`;
965
- files2.length = 0;
966
- displayFiles.length = 0;
967
- return result;
968
- } catch (err) {
969
- return `ERROR: Failed to list files in [${targetPath}]: ${err.message}`;
1070
+ files2.length = 0;
1071
+ displayFiles.length = 0;
1072
+ return result;
1073
+ } catch (err) {
1074
+ return `ERROR: Failed to list files in [${targetPath}]: ${err.message}`;
1075
+ }
1076
+ };
970
1077
  }
971
- };
1078
+ });
972
1079
 
973
1080
  // src/tools/view_file.js
974
1081
  import fs8 from "fs";
975
1082
  import path9 from "path";
976
- var view_file = async (args) => {
977
- const { path: targetPath, start_line = 1, end_line = 500 } = parseArgs(args);
978
- if (!targetPath) return 'ERROR: Missing "path" argument for view_file.';
979
- const absolutePath = path9.resolve(process.cwd(), targetPath);
980
- try {
981
- if (!fs8.existsSync(absolutePath)) {
982
- return `ERROR: File [${targetPath}] does not exist.`;
983
- }
984
- const stats = fs8.statSync(absolutePath);
985
- if (stats.isDirectory()) {
986
- return `ERROR: Path [${targetPath}] is a directory. Use list_files instead.`;
987
- }
988
- const content = fs8.readFileSync(absolutePath, "utf8");
989
- const lines = content.split("\n");
990
- const totalLines = lines.length;
991
- const start = Math.max(0, start_line - 1);
992
- const end = Math.min(totalLines, end_line);
993
- const resultLines = lines.slice(start, end);
994
- const header = `File: [${targetPath}] (Showing lines ${start + 1}-${end} of ${totalLines})`;
995
- const code = resultLines.map((line, i) => `${String(start + i + 1).padStart(4)}: ${line}`).join("\n");
996
- return `${header}
1083
+ var view_file;
1084
+ var init_view_file = __esm({
1085
+ "src/tools/view_file.js"() {
1086
+ init_arg_parser();
1087
+ view_file = async (args) => {
1088
+ const { path: targetPath, start_line = 1, end_line = 500 } = parseArgs(args);
1089
+ if (!targetPath) return 'ERROR: Missing "path" argument for view_file.';
1090
+ const absolutePath = path9.resolve(process.cwd(), targetPath);
1091
+ try {
1092
+ if (!fs8.existsSync(absolutePath)) {
1093
+ return `ERROR: File [${targetPath}] does not exist.`;
1094
+ }
1095
+ const stats = fs8.statSync(absolutePath);
1096
+ if (stats.isDirectory()) {
1097
+ return `ERROR: Path [${targetPath}] is a directory. Use list_files instead.`;
1098
+ }
1099
+ const content = fs8.readFileSync(absolutePath, "utf8");
1100
+ const lines = content.split("\n");
1101
+ const totalLines = lines.length;
1102
+ const start = Math.max(0, start_line - 1);
1103
+ const end = Math.min(totalLines, end_line);
1104
+ const resultLines = lines.slice(start, end);
1105
+ const header = `File: [${targetPath}] (Showing lines ${start + 1}-${end} of ${totalLines})`;
1106
+ const code = resultLines.map((line, i) => `${String(start + i + 1).padStart(4)}: ${line}`).join("\n");
1107
+ return `${header}
997
1108
 
998
1109
  ${code}`;
999
- } catch (err) {
1000
- return `ERROR: Failed to read file [${targetPath}]: ${err.message}`;
1110
+ } catch (err) {
1111
+ return `ERROR: Failed to read file [${targetPath}]: ${err.message}`;
1112
+ }
1113
+ };
1001
1114
  }
1002
- };
1115
+ });
1003
1116
 
1004
1117
  // src/tools/write_file.js
1005
1118
  import fs9 from "fs";
1006
1119
  import path10 from "path";
1007
- var write_file = async (args) => {
1008
- let { path: targetPath, content } = parseArgs(args);
1009
- if (!targetPath) return 'ERROR: Missing "path" argument for write_file.';
1010
- if (content === void 0) return 'ERROR: Missing "content" argument for write_file.';
1011
- content = content.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").trim();
1012
- const absolutePath = path10.resolve(process.cwd(), targetPath);
1013
- const parentDir = path10.dirname(absolutePath);
1014
- try {
1015
- let ancestry = "";
1016
- if (fs9.existsSync(absolutePath)) {
1120
+ var write_file;
1121
+ var init_write_file = __esm({
1122
+ "src/tools/write_file.js"() {
1123
+ init_arg_parser();
1124
+ write_file = async (args) => {
1125
+ let { path: targetPath, content } = parseArgs(args);
1126
+ if (!targetPath) return 'ERROR: Missing "path" argument for write_file.';
1127
+ if (content === void 0) return 'ERROR: Missing "content" argument for write_file.';
1128
+ content = content.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").trim();
1129
+ const absolutePath = path10.resolve(process.cwd(), targetPath);
1130
+ const parentDir = path10.dirname(absolutePath);
1017
1131
  try {
1018
- const oldData = fs9.readFileSync(absolutePath, "utf8");
1019
- const lines = oldData.split(/\r?\n/);
1020
- ancestry = `Old File contents:
1132
+ let ancestry = "";
1133
+ if (fs9.existsSync(absolutePath)) {
1134
+ try {
1135
+ const oldData = fs9.readFileSync(absolutePath, "utf8");
1136
+ const lines = oldData.split(/\r?\n/);
1137
+ ancestry = `Old File contents:
1021
1138
  ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
1022
1139
 
1023
1140
  `;
1024
- } catch (e) {
1025
- ancestry = `[Note: Could not read existing file for reversal reference]
1141
+ } catch (e) {
1142
+ ancestry = `[Note: Could not read existing file for reversal reference]
1026
1143
 
1027
1144
  `;
1028
- }
1029
- }
1030
- if (!fs9.existsSync(parentDir)) {
1031
- fs9.mkdirSync(parentDir, { recursive: true });
1032
- }
1033
- const lineCount = content.split(/\r?\n/).length;
1034
- const originalSize = Buffer.byteLength(content, "utf8");
1035
- fs9.writeFileSync(absolutePath, content, "utf8");
1036
- let verifiedContent = fs9.readFileSync(absolutePath, "utf8");
1037
- const verifiedSize = Buffer.byteLength(verifiedContent, "utf8");
1038
- const verifiedLines = verifiedContent.split(/\r?\n/);
1039
- const verifiedLineCount = verifiedLines.length;
1040
- if (verifiedSize === 0 && originalSize > 0) {
1041
- verifiedContent = null;
1042
- return `CRITICAL FAILURE: Verification failed. File [${targetPath}] is empty on disk despite success report!`;
1043
- }
1044
- let snippet = "";
1045
- if (verifiedLineCount <= 30) {
1046
- snippet = verifiedLines.join("\n");
1047
- } else {
1048
- const head = verifiedLines.slice(0, 15).join("\n");
1049
- const tail = verifiedLines.slice(-15).join("\n");
1050
- snippet = `${head}
1145
+ }
1146
+ }
1147
+ if (!fs9.existsSync(parentDir)) {
1148
+ fs9.mkdirSync(parentDir, { recursive: true });
1149
+ }
1150
+ const lineCount = content.split(/\r?\n/).length;
1151
+ const originalSize = Buffer.byteLength(content, "utf8");
1152
+ fs9.writeFileSync(absolutePath, content, "utf8");
1153
+ let verifiedContent = fs9.readFileSync(absolutePath, "utf8");
1154
+ const verifiedSize = Buffer.byteLength(verifiedContent, "utf8");
1155
+ const verifiedLines = verifiedContent.split(/\r?\n/);
1156
+ const verifiedLineCount = verifiedLines.length;
1157
+ if (verifiedSize === 0 && originalSize > 0) {
1158
+ verifiedContent = null;
1159
+ return `CRITICAL FAILURE: Verification failed. File [${targetPath}] is empty on disk despite success report!`;
1160
+ }
1161
+ let snippet = "";
1162
+ if (verifiedLineCount <= 30) {
1163
+ snippet = verifiedLines.join("\n");
1164
+ } else {
1165
+ const head = verifiedLines.slice(0, 15).join("\n");
1166
+ const tail = verifiedLines.slice(-15).join("\n");
1167
+ snippet = `${head}
1051
1168
 
1052
1169
  ... [${verifiedLineCount - 30} lines truncated for history stability] ...
1053
1170
 
1054
1171
  ${tail}`;
1055
- }
1056
- verifiedContent = null;
1057
- return `SUCCESS: File [${targetPath}] verified and persisted.
1172
+ }
1173
+ verifiedContent = null;
1174
+ return `SUCCESS: File [${targetPath}] verified and persisted.
1058
1175
 
1059
1176
  - Stats: [${verifiedLineCount} lines, ${(verifiedSize / 1024).toFixed(1)} KB]
1060
1177
  ${ancestry}- Content Preview:
1061
1178
  ${snippet}`;
1062
- } catch (err) {
1063
- return `ERROR: Failed to write file [${targetPath}]: ${err.message}`;
1179
+ } catch (err) {
1180
+ return `ERROR: Failed to write file [${targetPath}]: ${err.message}`;
1181
+ }
1182
+ };
1064
1183
  }
1065
- };
1184
+ });
1066
1185
 
1067
1186
  // src/tools/update_file.js
1068
1187
  import fs10 from "fs";
1069
1188
  import path11 from "path";
1070
- var update_file = async (args) => {
1071
- let { path: targetPath, content_to_replace, content_to_add } = parseArgs(args);
1072
- if (!targetPath) return 'ERROR: Missing "path" argument for update_file.';
1073
- if (content_to_replace === void 0) return 'ERROR: Missing "content_to_replace" argument.';
1074
- if (content_to_add === void 0) return 'ERROR: Missing "content_to_add" argument.';
1075
- const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").trim();
1076
- content_to_replace = strip(content_to_replace);
1077
- content_to_add = strip(content_to_add);
1078
- const absolutePath = path11.resolve(process.cwd(), targetPath);
1079
- try {
1080
- if (!fs10.existsSync(absolutePath)) {
1081
- return `ERROR: File [${targetPath}] does not exist. Use write_file instead.`;
1082
- }
1083
- const currentContent = fs10.readFileSync(absolutePath, "utf8");
1084
- if (!currentContent.includes(content_to_replace)) {
1085
- return `ERROR: Could not find exact match for the specified "content_to_replace" in [${targetPath}]. Check indentation/whitespace/line breaks(LF or CRLF)/string. Try re-reading the file for latest changes.`;
1086
- }
1087
- const startPos = currentContent.indexOf(content_to_replace);
1088
- const startLine = currentContent.substring(0, startPos).split(/\r?\n/).length;
1089
- const instances = currentContent.split(content_to_replace).length - 1;
1090
- const newFileContent = currentContent.split(content_to_replace).join(content_to_add);
1091
- fs10.writeFileSync(absolutePath, newFileContent, "utf8");
1092
- const allOriginalLines = currentContent.split(/\r?\n/);
1093
- const oldLines = content_to_replace.split(/\r?\n/);
1094
- const newLines = content_to_add.split(/\r?\n/);
1095
- const endLine = startLine + oldLines.length - 1;
1096
- let diffText = `SUCCESS: File [${targetPath}] updated. [${instances}] instances replaced.
1189
+ var update_file;
1190
+ var init_update_file = __esm({
1191
+ "src/tools/update_file.js"() {
1192
+ init_arg_parser();
1193
+ update_file = async (args) => {
1194
+ let { path: targetPath, content_to_replace, content_to_add } = parseArgs(args);
1195
+ if (!targetPath) return 'ERROR: Missing "path" argument for update_file.';
1196
+ if (content_to_replace === void 0) return 'ERROR: Missing "content_to_replace" argument.';
1197
+ if (content_to_add === void 0) return 'ERROR: Missing "content_to_add" argument.';
1198
+ const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").trim();
1199
+ content_to_replace = strip(content_to_replace);
1200
+ content_to_add = strip(content_to_add);
1201
+ const absolutePath = path11.resolve(process.cwd(), targetPath);
1202
+ try {
1203
+ if (!fs10.existsSync(absolutePath)) {
1204
+ return `ERROR: File [${targetPath}] does not exist. Use write_file instead.`;
1205
+ }
1206
+ const currentContent = fs10.readFileSync(absolutePath, "utf8");
1207
+ if (!currentContent.includes(content_to_replace)) {
1208
+ return `ERROR: Could not find exact match for the specified "content_to_replace" in [${targetPath}]. Check indentation/whitespace/line breaks(LF or CRLF)/string. Try re-reading the file for latest changes.`;
1209
+ }
1210
+ const startPos = currentContent.indexOf(content_to_replace);
1211
+ const startLine = currentContent.substring(0, startPos).split(/\r?\n/).length;
1212
+ const instances = currentContent.split(content_to_replace).length - 1;
1213
+ const newFileContent = currentContent.split(content_to_replace).join(content_to_add);
1214
+ fs10.writeFileSync(absolutePath, newFileContent, "utf8");
1215
+ const allOriginalLines = currentContent.split(/\r?\n/);
1216
+ const oldLines = content_to_replace.split(/\r?\n/);
1217
+ const newLines = content_to_add.split(/\r?\n/);
1218
+ const endLine = startLine + oldLines.length - 1;
1219
+ let diffText = `SUCCESS: File [${targetPath}] updated. [${instances}] instances replaced.
1097
1220
 
1098
1221
  `;
1099
- diffText += `[DIFF_START]
1222
+ diffText += `[DIFF_START]
1100
1223
  `;
1101
- const contextStart = Math.max(0, startLine - 16);
1102
- for (let i = contextStart; i < startLine - 1; i++) {
1103
- diffText += `[UI_CONTEXT] ${i + 1}| ${allOriginalLines[i]}
1224
+ const contextStart = Math.max(0, startLine - 16);
1225
+ for (let i = contextStart; i < startLine - 1; i++) {
1226
+ diffText += `[UI_CONTEXT] ${i + 1}| ${allOriginalLines[i]}
1104
1227
  `;
1105
- }
1106
- oldLines.forEach((line, i) => {
1107
- diffText += `-${startLine + i}| ${line}
1228
+ }
1229
+ oldLines.forEach((line, i) => {
1230
+ diffText += `-${startLine + i}| ${line}
1108
1231
  `;
1109
- });
1110
- newLines.forEach((line, i) => {
1111
- diffText += `+${startLine + i}| ${line}
1232
+ });
1233
+ newLines.forEach((line, i) => {
1234
+ diffText += `+${startLine + i}| ${line}
1112
1235
  `;
1113
- });
1114
- for (let i = endLine; i < Math.min(allOriginalLines.length, endLine + 15); i++) {
1115
- diffText += `[UI_CONTEXT] ${i + 1}| ${allOriginalLines[i]}
1236
+ });
1237
+ for (let i = endLine; i < Math.min(allOriginalLines.length, endLine + 15); i++) {
1238
+ diffText += `[UI_CONTEXT] ${i + 1}| ${allOriginalLines[i]}
1116
1239
  `;
1117
- }
1118
- diffText += `[DIFF_END]`;
1119
- return diffText;
1120
- } catch (err) {
1121
- return `ERROR: Failed to update file [${targetPath}]: ${err.message}`;
1240
+ }
1241
+ diffText += `[DIFF_END]`;
1242
+ return diffText;
1243
+ } catch (err) {
1244
+ return `ERROR: Failed to update file [${targetPath}]: ${err.message}`;
1245
+ }
1246
+ };
1122
1247
  }
1123
- };
1248
+ });
1124
1249
 
1125
1250
  // src/tools/exec_command.js
1126
1251
  import { spawn } from "child_process";
1127
- var exec_command = async (args, options = {}) => {
1128
- const { command } = parseArgs(args);
1129
- const { onChunk } = options;
1130
- if (!command) return 'ERROR: Missing "command" argument for exec_command.';
1131
- return new Promise((resolve) => {
1132
- const child = spawn(command, { shell: true, cwd: process.cwd() });
1133
- let stdout = "";
1134
- let stderr = "";
1135
- child.stdout.on("data", (data) => {
1136
- const chunk = data.toString();
1137
- stdout += chunk;
1138
- if (onChunk) onChunk(chunk);
1139
- });
1140
- child.stderr.on("data", (data) => {
1141
- const chunk = data.toString();
1142
- stderr += chunk;
1143
- if (onChunk) onChunk(chunk);
1144
- });
1145
- child.on("close", (code) => {
1146
- const result = [];
1147
- if (stdout) result.push(`STDOUT:
1252
+ var exec_command;
1253
+ var init_exec_command = __esm({
1254
+ "src/tools/exec_command.js"() {
1255
+ init_arg_parser();
1256
+ exec_command = async (args, options = {}) => {
1257
+ const { command } = parseArgs(args);
1258
+ const { onChunk } = options;
1259
+ if (!command) return 'ERROR: Missing "command" argument for exec_command.';
1260
+ return new Promise((resolve) => {
1261
+ const child = spawn(command, { shell: true, cwd: process.cwd() });
1262
+ let stdout = "";
1263
+ let stderr = "";
1264
+ child.stdout.on("data", (data) => {
1265
+ const chunk = data.toString();
1266
+ stdout += chunk;
1267
+ if (onChunk) onChunk(chunk);
1268
+ });
1269
+ child.stderr.on("data", (data) => {
1270
+ const chunk = data.toString();
1271
+ stderr += chunk;
1272
+ if (onChunk) onChunk(chunk);
1273
+ });
1274
+ child.on("close", (code) => {
1275
+ const result = [];
1276
+ if (stdout) result.push(`STDOUT:
1148
1277
  ${stdout}`);
1149
- if (stderr) result.push(`STDERR:
1278
+ if (stderr) result.push(`STDERR:
1150
1279
  ${stderr}`);
1151
- if (code !== 0) result.push(`EXIT CODE: ${code}`);
1152
- const finalOutput = result.join("\n\n") || "Command executed with no output.";
1153
- if (code !== 0) {
1154
- resolve(`FAILURE: Command [${command}] failed.
1280
+ if (code !== 0) result.push(`EXIT CODE: ${code}`);
1281
+ const finalOutput = result.join("\n\n") || "Command executed with no output.";
1282
+ if (code !== 0) {
1283
+ resolve(`FAILURE: Command [${command}] failed.
1155
1284
 
1156
1285
  ${finalOutput}`);
1157
- } else {
1158
- resolve(`SUCCESS: Command [${command}] completed.
1286
+ } else {
1287
+ resolve(`SUCCESS: Command [${command}] completed.
1159
1288
 
1160
1289
  ${finalOutput}`);
1161
- }
1162
- });
1163
- child.on("error", (err) => {
1164
- resolve(`ERROR: Failed to start command [${command}]: ${err.message}`);
1165
- });
1166
- });
1167
- };
1290
+ }
1291
+ });
1292
+ child.on("error", (err) => {
1293
+ resolve(`ERROR: Failed to start command [${command}]: ${err.message}`);
1294
+ });
1295
+ });
1296
+ };
1297
+ }
1298
+ });
1168
1299
 
1169
1300
  // src/tools/read_folder.js
1170
1301
  import fs11 from "fs";
1171
1302
  import path12 from "path";
1172
- var read_folder = async (args) => {
1173
- const { path: targetPath = "." } = parseArgs(args);
1174
- const absolutePath = path12.resolve(process.cwd(), targetPath);
1175
- try {
1176
- if (!fs11.existsSync(absolutePath)) {
1177
- return `ERROR: Path [${targetPath}] does not exist.`;
1178
- }
1179
- const stats = fs11.statSync(absolutePath);
1180
- if (!stats.isDirectory()) {
1181
- return `ERROR: Path [${targetPath}] is a file, not a directory. Use view_file instead.`;
1182
- }
1183
- const totalItems = files.length;
1184
- const maxDisplay = 100;
1185
- const displayItems = files.slice(0, maxDisplay);
1186
- const folderData = [];
1187
- for (const file of displayItems) {
1188
- const fPath = path12.join(absolutePath, file);
1189
- let indicator = "\u{1F4C4}";
1190
- let info = { name: file, type: "unknown", size: "N/A", mtime: "N/A" };
1303
+ var read_folder;
1304
+ var init_read_folder = __esm({
1305
+ "src/tools/read_folder.js"() {
1306
+ init_arg_parser();
1307
+ read_folder = async (args) => {
1308
+ const { path: targetPath = "." } = parseArgs(args);
1309
+ const absolutePath = path12.resolve(process.cwd(), targetPath);
1191
1310
  try {
1192
- const fStats = fs11.statSync(fPath);
1193
- info = {
1194
- name: file,
1195
- type: fStats.isDirectory() ? "directory" : "file",
1196
- size: (fStats.size / 1024).toFixed(1) + " KB",
1197
- mtime: fStats.mtime.toLocaleString()
1198
- };
1199
- } catch (e) {
1200
- info.type = "inaccessible";
1201
- }
1202
- folderData.push(info);
1203
- }
1204
- const formatted = folderData.map((f) => {
1205
- const indicator = f.type === "directory" ? "\u{1F4C1}" : f.type === "file" ? "\u{1F4C4}" : "\u2753";
1206
- if (f.type === "directory") {
1207
- return `${indicator} ${f.name} - [DIR] - [Modified: ${f.mtime}]`;
1208
- }
1209
- return `${indicator} ${f.name} - [Size: ${f.size}] - [Modified: ${f.mtime}]`;
1210
- }).join("\n");
1211
- let footer = `
1311
+ if (!fs11.existsSync(absolutePath)) {
1312
+ return `ERROR: Path [${targetPath}] does not exist.`;
1313
+ }
1314
+ const stats = fs11.statSync(absolutePath);
1315
+ if (!stats.isDirectory()) {
1316
+ return `ERROR: Path [${targetPath}] is a file, not a directory. Use view_file instead.`;
1317
+ }
1318
+ const totalItems = files.length;
1319
+ const maxDisplay = 100;
1320
+ const displayItems = files.slice(0, maxDisplay);
1321
+ const folderData = [];
1322
+ for (const file of displayItems) {
1323
+ const fPath = path12.join(absolutePath, file);
1324
+ let indicator = "\u{1F4C4}";
1325
+ let info = { name: file, type: "unknown", size: "N/A", mtime: "N/A" };
1326
+ try {
1327
+ const fStats = fs11.statSync(fPath);
1328
+ info = {
1329
+ name: file,
1330
+ type: fStats.isDirectory() ? "directory" : "file",
1331
+ size: (fStats.size / 1024).toFixed(1) + " KB",
1332
+ mtime: fStats.mtime.toLocaleString()
1333
+ };
1334
+ } catch (e) {
1335
+ info.type = "inaccessible";
1336
+ }
1337
+ folderData.push(info);
1338
+ }
1339
+ const formatted = folderData.map((f) => {
1340
+ const indicator = f.type === "directory" ? "\u{1F4C1}" : f.type === "file" ? "\u{1F4C4}" : "\u2753";
1341
+ if (f.type === "directory") {
1342
+ return `${indicator} ${f.name} - [DIR] - [Modified: ${f.mtime}]`;
1343
+ }
1344
+ return `${indicator} ${f.name} - [Size: ${f.size}] - [Modified: ${f.mtime}]`;
1345
+ }).join("\n");
1346
+ let footer = `
1212
1347
 
1213
1348
  (Total items in folder: ${totalItems})`;
1214
- if (totalItems > maxDisplay) {
1215
- footer = `
1349
+ if (totalItems > maxDisplay) {
1350
+ footer = `
1216
1351
 
1217
1352
  \u26A0\uFE0F TRUNCATED: Showing first ${maxDisplay} of ${totalItems} items.`;
1218
- }
1219
- const result = `Detailed folder stats for [${targetPath}]:
1353
+ }
1354
+ const result = `Detailed folder stats for [${targetPath}]:
1220
1355
 
1221
1356
  ${formatted}${footer}`;
1222
- files.length = 0;
1223
- displayItems.length = 0;
1224
- folderData.length = 0;
1225
- return result;
1226
- } catch (err) {
1227
- return `ERROR: Failed to read folder [${targetPath}]: ${err.message}`;
1357
+ files.length = 0;
1358
+ displayItems.length = 0;
1359
+ folderData.length = 0;
1360
+ return result;
1361
+ } catch (err) {
1362
+ return `ERROR: Failed to read folder [${targetPath}]: ${err.message}`;
1363
+ }
1364
+ };
1228
1365
  }
1229
- };
1366
+ });
1230
1367
 
1231
1368
  // src/tools/ask_user.js
1232
- var ask_user = async (args, context) => {
1233
- const parsed = parseArgs(args);
1234
- const { question } = parsed;
1235
- if (!question) return 'ERROR: Missing "question" argument for ask.';
1236
- if (!context.onAskUser) return "ERROR: onAskUser callback not provided in tool context.";
1237
- const options = [];
1238
- Object.keys(parsed).forEach((key) => {
1239
- if (key.startsWith("option")) {
1240
- const val = parsed[key];
1241
- if (typeof val === "string" && val.includes("::")) {
1242
- const [label, desc] = val.split("::");
1243
- options.push({
1244
- id: key,
1245
- label: label.trim(),
1246
- description: desc.trim()
1247
- });
1248
- } else {
1249
- options.push({
1250
- id: key,
1251
- label: String(val).trim(),
1252
- description: ""
1253
- });
1369
+ var ask_user;
1370
+ var init_ask_user = __esm({
1371
+ "src/tools/ask_user.js"() {
1372
+ init_arg_parser();
1373
+ ask_user = async (args, context) => {
1374
+ const parsed = parseArgs(args);
1375
+ const { question } = parsed;
1376
+ if (!question) return 'ERROR: Missing "question" argument for ask.';
1377
+ if (!context.onAskUser) return "ERROR: onAskUser callback not provided in tool context.";
1378
+ const options = [];
1379
+ Object.keys(parsed).forEach((key) => {
1380
+ if (key.startsWith("option")) {
1381
+ const val = parsed[key];
1382
+ if (typeof val === "string" && val.includes("::")) {
1383
+ const [label, desc] = val.split("::");
1384
+ options.push({
1385
+ id: key,
1386
+ label: label.trim(),
1387
+ description: desc.trim()
1388
+ });
1389
+ } else {
1390
+ options.push({
1391
+ id: key,
1392
+ label: String(val).trim(),
1393
+ description: ""
1394
+ });
1395
+ }
1396
+ }
1397
+ });
1398
+ try {
1399
+ const choice = await context.onAskUser(question, options);
1400
+ return `USER CHOOSE: ${choice}`;
1401
+ } catch (err) {
1402
+ return `ERROR: Failed to get user input: ${err.message}`;
1254
1403
  }
1255
- }
1256
- });
1257
- try {
1258
- const choice = await context.onAskUser(question, options);
1259
- return `USER CHOOSE: ${choice}`;
1260
- } catch (err) {
1261
- return `ERROR: Failed to get user input: ${err.message}`;
1404
+ };
1262
1405
  }
1263
- };
1406
+ });
1264
1407
 
1265
1408
  // src/utils/tools.js
1266
- var TOOL_MAP = {
1267
- web_search,
1268
- web_scrape,
1269
- memory,
1270
- chat,
1271
- list_files,
1272
- view_file,
1273
- write_file,
1274
- update_file,
1275
- exec_command,
1276
- read_folder,
1277
- ask: ask_user
1278
- };
1279
- var dispatchTool = async (toolName, args, context = {}) => {
1280
- const tool = TOOL_MAP[toolName];
1281
- if (!tool) {
1282
- return `ERROR: Tool [${toolName}] not found in registry.`;
1283
- }
1284
- try {
1285
- return await tool(args, context);
1286
- } catch (err) {
1287
- return `ERROR: Execution failed for [${toolName}]: ${err.message}`;
1409
+ var TOOL_MAP, dispatchTool;
1410
+ var init_tools = __esm({
1411
+ "src/utils/tools.js"() {
1412
+ init_web_search();
1413
+ init_web_scrape();
1414
+ init_memory();
1415
+ init_chat();
1416
+ init_list_files();
1417
+ init_view_file();
1418
+ init_write_file();
1419
+ init_update_file();
1420
+ init_exec_command();
1421
+ init_read_folder();
1422
+ init_ask_user();
1423
+ TOOL_MAP = {
1424
+ web_search,
1425
+ web_scrape,
1426
+ memory,
1427
+ chat,
1428
+ list_files,
1429
+ view_file,
1430
+ write_file,
1431
+ update_file,
1432
+ exec_command,
1433
+ read_folder,
1434
+ ask: ask_user
1435
+ };
1436
+ dispatchTool = async (toolName, args, context = {}) => {
1437
+ const tool = TOOL_MAP[toolName];
1438
+ if (!tool) {
1439
+ return `ERROR: Tool [${toolName}] not found in registry.`;
1440
+ }
1441
+ try {
1442
+ return await tool(args, context);
1443
+ } catch (err) {
1444
+ return `ERROR: Execution failed for [${toolName}]: ${err.message}`;
1445
+ }
1446
+ };
1288
1447
  }
1289
- };
1448
+ });
1290
1449
 
1291
1450
  // src/utils/ai.js
1451
+ import { GoogleGenAI, ThinkingLevel } from "@google/genai";
1292
1452
  import path13 from "path";
1293
1453
  import fs12 from "fs";
1294
- var client = null;
1295
- var TERMINATION_SIGNAL = false;
1296
- var signalTermination = () => {
1297
- TERMINATION_SIGNAL = true;
1298
- };
1299
- var detectToolCalls = (text) => {
1300
- const results = [];
1301
- const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(([\s\S]*?)\)(?:\s*\]?)/gi;
1302
- let match;
1303
- while ((match = toolRegex.exec(text)) !== null) {
1304
- const fullMatch = match[0];
1305
- const toolName = match[1];
1306
- const args = match[2];
1307
- let openCount = (args.match(/\(/g) || []).length;
1308
- let closeCount = (args.match(/\)/g) || []).length;
1309
- let finalArgs = args;
1310
- let finalFullMatch = fullMatch;
1311
- if (openCount > closeCount) {
1312
- const startIdx = match.index + fullMatch.indexOf("(");
1313
- let balance = 0;
1314
- let endIdx = -1;
1315
- for (let i = startIdx; i < text.length; i++) {
1316
- if (text[i] === "(") balance++;
1317
- if (text[i] === ")") balance--;
1318
- if (balance === 0) {
1319
- endIdx = i;
1320
- break;
1454
+ var client, TERMINATION_SIGNAL, signalTermination, detectToolCalls, initAI, getAIStream;
1455
+ var init_ai = __esm({
1456
+ "src/utils/ai.js"() {
1457
+ init_prompts();
1458
+ init_history();
1459
+ init_usage();
1460
+ init_tools();
1461
+ init_crypto();
1462
+ init_arg_parser();
1463
+ init_paths();
1464
+ client = null;
1465
+ TERMINATION_SIGNAL = false;
1466
+ signalTermination = () => {
1467
+ TERMINATION_SIGNAL = true;
1468
+ };
1469
+ detectToolCalls = (text) => {
1470
+ const results = [];
1471
+ const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(([\s\S]*?)\)(?:\s*\]?)/gi;
1472
+ let match;
1473
+ while ((match = toolRegex.exec(text)) !== null) {
1474
+ const fullMatch = match[0];
1475
+ const toolName = match[1];
1476
+ const args = match[2];
1477
+ let openCount = (args.match(/\(/g) || []).length;
1478
+ let closeCount = (args.match(/\)/g) || []).length;
1479
+ let finalArgs = args;
1480
+ let finalFullMatch = fullMatch;
1481
+ if (openCount > closeCount) {
1482
+ const startIdx = match.index + fullMatch.indexOf("(");
1483
+ let balance = 0;
1484
+ let endIdx = -1;
1485
+ for (let i = startIdx; i < text.length; i++) {
1486
+ if (text[i] === "(") balance++;
1487
+ if (text[i] === ")") balance--;
1488
+ if (balance === 0) {
1489
+ endIdx = i;
1490
+ break;
1491
+ }
1492
+ }
1493
+ if (endIdx !== -1) {
1494
+ finalArgs = text.substring(startIdx + 1, endIdx);
1495
+ finalFullMatch = text.substring(match.index, endIdx + 1);
1496
+ toolRegex.lastIndex = endIdx + 1;
1497
+ }
1321
1498
  }
1499
+ results.push({
1500
+ fullMatch: finalFullMatch,
1501
+ toolName: toolName.trim(),
1502
+ args: finalArgs.trim()
1503
+ });
1322
1504
  }
1323
- if (endIdx !== -1) {
1324
- finalArgs = text.substring(startIdx + 1, endIdx);
1325
- finalFullMatch = text.substring(match.index, endIdx + 1);
1326
- toolRegex.lastIndex = endIdx + 1;
1505
+ return results;
1506
+ };
1507
+ initAI = (apiKey) => {
1508
+ if (!apiKey) return null;
1509
+ client = new GoogleGenAI({ apiKey });
1510
+ return client;
1511
+ };
1512
+ getAIStream = async function* (modelName, history, settings, steeringCallback) {
1513
+ if (!client) throw new Error("AI not initialized");
1514
+ const { profile, thinkingLevel, mode, janitorModel, chatId, systemSettings, sessionStats } = settings;
1515
+ const isMemoryEnabled = systemSettings?.memory !== false;
1516
+ const originalText = history[history.length - 1].text;
1517
+ const isFirstPrompt = history.filter((m) => m.role === "user").length === 1;
1518
+ const hasTitleSignal = originalText.includes("[TITLE-UPDATE]");
1519
+ const needTitle = isFirstPrompt || hasTitleSignal;
1520
+ const agentText = originalText.replace(/\[TITLE-UPDATE\]/g, "").trim();
1521
+ let modifiedHistory = [...history.slice(0, -1)];
1522
+ if (systemSettings?.compression === 0 && (sessionStats?.tokens || 0) > 254e3) {
1523
+ modifiedHistory = getTruncatedHistory(modifiedHistory, 4);
1327
1524
  }
1328
- }
1329
- results.push({
1330
- fullMatch: finalFullMatch,
1331
- toolName: toolName.trim(),
1332
- args: finalArgs.trim()
1333
- });
1334
- }
1335
- return results;
1336
- };
1337
- var initAI = (apiKey) => {
1338
- if (!apiKey) return null;
1339
- client = new GoogleGenAI({ apiKey });
1340
- return client;
1341
- };
1342
- var getAIStream = async function* (modelName, history, settings, steeringCallback) {
1343
- if (!client) throw new Error("AI not initialized");
1344
- const { profile, thinkingLevel, mode, janitorModel, chatId, systemSettings, sessionStats } = settings;
1345
- const isMemoryEnabled = systemSettings?.memory !== false;
1346
- const originalText = history[history.length - 1].text;
1347
- const isFirstPrompt = history.filter((m) => m.role === "user").length === 1;
1348
- const hasTitleSignal = originalText.includes("[TITLE-UPDATE]");
1349
- const needTitle = isFirstPrompt || hasTitleSignal;
1350
- const agentText = originalText.replace(/\[TITLE-UPDATE\]/g, "").trim();
1351
- let modifiedHistory = [...history.slice(0, -1)];
1352
- if (systemSettings?.compression === 0 && (sessionStats?.tokens || 0) > 254e3) {
1353
- modifiedHistory = getTruncatedHistory(modifiedHistory, 4);
1354
- }
1355
- const tempStorage = readEncryptedJson(TEMP_MEM_FILE, {});
1356
- const otherMemories = Object.entries(tempStorage).filter(([id]) => id !== chatId).flatMap(([_, mems]) => mems).map((mem) => `- ${mem}`).join("\n");
1357
- const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
1358
- const mainUserMemories = persistentStorage.map((m) => `- ${m.memory}`).join("\n");
1359
- const janitorUserMemories = persistentStorage.map((m) => `- [${m.id}]: ${m.memory}`).join("\n");
1360
- const isContext50 = (sessionStats.tokens || 0) >= 54e3;
1361
- const systemInstruction = getSystemInstruction(profile, thinkingLevel, mode, systemSettings, otherMemories, mainUserMemories, isMemoryEnabled, isContext50);
1362
- const firstUserMsg = `${systemInstruction}
1525
+ const tempStorage = readEncryptedJson(TEMP_MEM_FILE, {});
1526
+ const otherMemories = Object.entries(tempStorage).filter(([id]) => id !== chatId).flatMap(([_, mems]) => mems).map((mem) => `- ${mem}`).join("\n");
1527
+ const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
1528
+ const mainUserMemories = persistentStorage.map((m) => `- ${m.memory}`).join("\n");
1529
+ const janitorUserMemories = persistentStorage.map((m) => `- [${m.id}]: ${m.memory}`).join("\n");
1530
+ const isContext50 = (sessionStats.tokens || 0) >= 54e3;
1531
+ const systemInstruction = getSystemInstruction(profile, thinkingLevel, mode, systemSettings, otherMemories, mainUserMemories, isMemoryEnabled, isContext50);
1532
+ const firstUserMsg = `${systemInstruction}
1363
1533
 
1364
1534
  USER_PROMPT: ${agentText}`.trim();
1365
- modifiedHistory.push({ role: "user", text: firstUserMsg });
1366
- let lastUsage = null;
1367
- const MAX_LOOPS = mode === "Flux" ? 50 : 7;
1368
- const MAX_RETRIES = 7;
1369
- yield { type: "status", content: "Working..." };
1370
- TERMINATION_SIGNAL = false;
1371
- let fullAgentResponse = "";
1372
- for (let loop = 0; loop < MAX_LOOPS; loop++) {
1373
- if (TERMINATION_SIGNAL) {
1374
- yield { type: "status", content: "Termination Signal Received." };
1375
- break;
1376
- }
1377
- if (steeringCallback) {
1378
- const hint = await steeringCallback();
1379
- if (hint) {
1380
- modifiedHistory.push({ role: "user", text: `[STEERING HINT]: ${hint}` });
1381
- yield { type: "status", content: "Steering Hint Injected." };
1382
- }
1383
- }
1384
- yield { type: "turn_reset", content: true };
1385
- const contents = modifiedHistory.filter((msg) => (msg.role === "user" || msg.role === "agent" || msg.role === "system") && !String(msg.id).startsWith("welcome") && !msg.isMeta).map((msg) => ({
1386
- role: msg.role === "user" || msg.role === "system" ? "user" : "model",
1387
- parts: [{ text: msg.text }]
1388
- }));
1389
- let stream;
1390
- let success = false;
1391
- let retryCount = 0;
1392
- while (retryCount <= MAX_RETRIES && !success) {
1393
- try {
1394
- if (!await checkQuota("agent", settings)) {
1395
- throw new Error("Error: Daily Quota Exausted for Agent");
1396
- }
1397
- let targetModel = modelName;
1398
- if (retryCount === 5) {
1399
- targetModel = "gemini-3-flash-preview";
1400
- yield { type: "model_update", content: "Trying with fallback model (v3)" };
1401
- } else if (retryCount >= 6) {
1402
- targetModel = "gemini-3.1-flash-lite-preview";
1403
- yield { type: "model_update", content: "Trying with fallback model (v3.1)" };
1404
- } else if (retryCount > 0) {
1405
- yield { type: "model_update", content: null };
1406
- }
1407
- stream = await client.models.generateContentStream({
1408
- model: targetModel,
1409
- contents,
1410
- config: {
1411
- temperature: mode === "Flux" ? 1 : 1.4,
1412
- thinkingConfig: {
1413
- includeThoughts: false,
1414
- thinkingLevel: ThinkingLevel.MINIMAL
1415
- }
1416
- }
1417
- });
1418
- success = true;
1419
- yield { type: "model_update", content: null };
1420
- } catch (err) {
1421
- const errMsg = err.status || err.error && err.error.message || String(err);
1422
- const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1423
- const agentErrDir = path13.join(LOGS_DIR, "agent");
1424
- if (!fs12.existsSync(agentErrDir)) fs12.mkdirSync(agentErrDir, { recursive: true });
1425
- fs12.appendFileSync(path13.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errMsg}
1426
- `);
1427
- if (retryCount < MAX_RETRIES) {
1428
- retryCount++;
1429
- const waitTime = Math.floor(Math.random() * (2e3 - 800 + 1)) + 800;
1430
- yield { type: "status", content: `Retrying (${retryCount}/${MAX_RETRIES + 1})...` };
1431
- await new Promise((resolve) => setTimeout(resolve, waitTime));
1432
- } else {
1433
- throw new Error(`Model cannot be reached: ${errMsg}. (Failed ${MAX_RETRIES + 1} times)`);
1535
+ modifiedHistory.push({ role: "user", text: firstUserMsg });
1536
+ let lastUsage = null;
1537
+ const MAX_LOOPS = mode === "Flux" ? 50 : 7;
1538
+ const MAX_RETRIES = 7;
1539
+ yield { type: "status", content: "Working..." };
1540
+ TERMINATION_SIGNAL = false;
1541
+ let fullAgentResponseChunks = [];
1542
+ for (let loop = 0; loop < MAX_LOOPS; loop++) {
1543
+ if (TERMINATION_SIGNAL) {
1544
+ yield { type: "status", content: "Termination Signal Received." };
1545
+ break;
1434
1546
  }
1435
- }
1436
- }
1437
- let turnText = "";
1438
- let lastToolSniffed = null;
1439
- for await (const chunk of stream) {
1440
- if (TERMINATION_SIGNAL) break;
1441
- if (chunk.text) {
1442
- turnText += chunk.text;
1443
- yield { type: "text", content: chunk.text };
1444
- if (turnText.includes("tool:functions.")) {
1445
- const parts = turnText.split("tool:functions.");
1446
- const potentialTool = parts[parts.length - 1].split("(")[0].trim();
1447
- if (potentialTool && /^[a-z_]+$/.test(potentialTool) && potentialTool !== lastToolSniffed) {
1448
- lastToolSniffed = potentialTool;
1449
- yield { type: "status", content: `Working (${potentialTool})...` };
1547
+ if (steeringCallback) {
1548
+ const hint = await steeringCallback();
1549
+ if (hint) {
1550
+ if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "user") {
1551
+ modifiedHistory[modifiedHistory.length - 1].text += `
1552
+
1553
+ [STEERING HINT]: ${hint}`;
1554
+ } else {
1555
+ modifiedHistory.push({ role: "user", text: `[STEERING HINT]: ${hint}` });
1556
+ }
1557
+ yield { type: "status", content: "Steering Hint Injected." };
1450
1558
  }
1451
1559
  }
1452
- }
1453
- if (chunk.usageMetadata) {
1454
- lastUsage = chunk.usageMetadata;
1455
- }
1456
- }
1457
- await incrementUsage("agent");
1458
- if (lastUsage) {
1459
- yield { type: "usage", content: lastUsage };
1460
- }
1461
- fullAgentResponse += turnText + "\n";
1462
- const turnTextLower = turnText.toLowerCase();
1463
- const hasFinish = /\[?\s*(turn\s*:)?\s*finish\s*\]?/i.test(turnTextLower);
1464
- const hasContinue = /\[?\s*(turn\s*:)?\s*continue\s*\]?/i.test(turnTextLower);
1465
- const toolCalls = detectToolCalls(turnText);
1466
- let toolResults = [];
1467
- const shouldContinue = hasContinue || toolCalls.length > 0;
1468
- if (toolCalls.length > 0) {
1469
- for (const toolCall of toolCalls) {
1470
1560
  yield { type: "turn_reset", content: true };
1471
- yield { type: "status", content: `Working (${toolCall.toolName})...` };
1472
- let label = "";
1473
- if (toolCall.toolName === "web_search") {
1474
- const { query, limit = 10 } = parseArgs(toolCall.args);
1475
- label = `\u{1F50D} SEARCHING: "${query}" (${limit})`.toUpperCase();
1476
- } else if (toolCall.toolName === "web_scrape") {
1477
- const url = parseArgs(toolCall.args).url || "...";
1478
- label = `\u{1F4D6} READING SITE: ${url}`.toUpperCase();
1479
- } else if (toolCall.toolName === "view_file") {
1480
- const { path: targetPath2, start_line = 1, end_line = 500 } = parseArgs(toolCall.args);
1481
- let totalLines = "...";
1482
- let actualEndLine = end_line;
1561
+ const contents = modifiedHistory.filter((msg) => (msg.role === "user" || msg.role === "agent" || msg.role === "system") && !String(msg.id).startsWith("welcome") && !msg.isMeta).map((msg) => ({
1562
+ role: msg.role === "user" || msg.role === "system" ? "user" : "model",
1563
+ parts: [{ text: msg.text }]
1564
+ }));
1565
+ let stream;
1566
+ let success = false;
1567
+ let retryCount = 0;
1568
+ while (retryCount <= MAX_RETRIES && !success) {
1483
1569
  try {
1484
- const absPath = path13.resolve(process.cwd(), targetPath2);
1485
- if (fs12.existsSync(absPath)) {
1486
- const content = fs12.readFileSync(absPath, "utf8");
1487
- const lines = content.split("\n").length;
1488
- totalLines = lines;
1489
- actualEndLine = Math.min(end_line, lines);
1570
+ if (!await checkQuota("agent", settings)) {
1571
+ throw new Error("Error: Daily Quota Exausted for Agent");
1572
+ }
1573
+ let targetModel = modelName;
1574
+ if (retryCount === 5) {
1575
+ targetModel = "gemini-3-flash-preview";
1576
+ yield { type: "model_update", content: "Trying with fallback model (v3)" };
1577
+ } else if (retryCount >= 6) {
1578
+ targetModel = "gemini-3.1-flash-lite-preview";
1579
+ yield { type: "model_update", content: "Trying with fallback model (v3.1)" };
1580
+ } else if (retryCount > 0) {
1581
+ yield { type: "model_update", content: null };
1582
+ }
1583
+ stream = await client.models.generateContentStream({
1584
+ model: targetModel,
1585
+ contents,
1586
+ config: {
1587
+ temperature: mode === "Flux" ? 1 : 1.4,
1588
+ thinkingConfig: {
1589
+ includeThoughts: false,
1590
+ thinkingLevel: ThinkingLevel.MINIMAL
1591
+ }
1592
+ }
1593
+ });
1594
+ success = true;
1595
+ yield { type: "model_update", content: null };
1596
+ } catch (err) {
1597
+ const errMsg = err.status || err.error && err.error.message || String(err);
1598
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1599
+ const agentErrDir = path13.join(LOGS_DIR, "agent");
1600
+ if (!fs12.existsSync(agentErrDir)) fs12.mkdirSync(agentErrDir, { recursive: true });
1601
+ fs12.appendFileSync(path13.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errMsg}
1602
+ `);
1603
+ if (retryCount < MAX_RETRIES) {
1604
+ retryCount++;
1605
+ const waitTime = Math.floor(Math.random() * (2e3 - 800 + 1)) + 800;
1606
+ yield { type: "status", content: `Retrying (${retryCount}/${MAX_RETRIES + 1})...` };
1607
+ await new Promise((resolve) => setTimeout(resolve, waitTime));
1608
+ } else {
1609
+ throw new Error(`Model cannot be reached: ${errMsg}. (Failed ${MAX_RETRIES + 1} times)`);
1490
1610
  }
1491
- } catch (e) {
1492
1611
  }
1493
- label = `\u{1F4C4} READING FILE: ${targetPath2}. LINES ${start_line} - ${actualEndLine} FROM ${totalLines}`.toUpperCase();
1494
- } else if (toolCall.toolName === "list_files" || toolCall.toolName === "read_folder") {
1495
- const action = toolCall.toolName === "list_files" ? "LISTING" : "DISCOVERING";
1496
- label = `\u{1F4C2} ${action} DIRECTORY: ${parseArgs(toolCall.args).path || "."}`.toUpperCase();
1497
- } else if (toolCall.toolName === "write_file" || toolCall.toolName === "update_file") {
1498
- const action = toolCall.toolName === "write_file" ? "WRITING" : "PATCHING";
1499
- label = `\u{1F4BE} ${action} FILE: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
1500
- } else if (toolCall.toolName === "exec_command" || toolCall.toolName === "ask") {
1501
- label = "";
1502
- } else {
1503
- label = `EXECUTING ${toolCall.toolName}`.toUpperCase();
1504
1612
  }
1505
- if (label) {
1506
- const boxWidth = Math.min(label.length + 4, 85);
1507
- const boxTop = `\u256D${"\u2500".repeat(boxWidth)}\u256E`;
1508
- const boxMid = `\u2502 ${label.padEnd(boxWidth - 2).substring(0, boxWidth - 2)} \u2502`;
1509
- const boxBottom = `\u2570${"\u2500".repeat(boxWidth)}\u256F`;
1510
- yield { type: "text", content: `
1613
+ let turnText = "";
1614
+ let lastToolSniffed = null;
1615
+ for await (const chunk of stream) {
1616
+ if (TERMINATION_SIGNAL) break;
1617
+ if (chunk.text) {
1618
+ turnText += chunk.text;
1619
+ yield { type: "text", content: chunk.text };
1620
+ if (turnText.includes("tool:functions.")) {
1621
+ const parts = turnText.split("tool:functions.");
1622
+ const potentialTool = parts[parts.length - 1].split("(")[0].trim();
1623
+ if (potentialTool && /^[a-z_]+$/.test(potentialTool) && potentialTool !== lastToolSniffed) {
1624
+ lastToolSniffed = potentialTool;
1625
+ yield { type: "status", content: `Working (${potentialTool})...` };
1626
+ }
1627
+ }
1628
+ }
1629
+ lastUsage = chunk.usageMetadata;
1630
+ if (lastUsage) {
1631
+ yield { type: "usage", content: lastUsage };
1632
+ }
1633
+ }
1634
+ await incrementUsage("agent");
1635
+ fullAgentResponseChunks.push(turnText);
1636
+ const textToProcess = turnText.replace(/<think>[\s\S]*?<\/think>/g, "");
1637
+ const turnTextLower = textToProcess.toLowerCase();
1638
+ const hasFinish = /\[\s*(turn\s*:)?\s*finish\s*\]/i.test(turnTextLower);
1639
+ const toolCalls = detectToolCalls(textToProcess);
1640
+ let toolResults = [];
1641
+ const shouldContinue = toolCalls.length > 0;
1642
+ if (toolCalls.length > 0) {
1643
+ for (const toolCall of toolCalls) {
1644
+ yield { type: "turn_reset", content: true };
1645
+ yield { type: "status", content: `Working (${toolCall.toolName})...` };
1646
+ let label = "";
1647
+ if (toolCall.toolName === "web_search") {
1648
+ const { query, limit = 10 } = parseArgs(toolCall.args);
1649
+ label = `\u{1F50D} SEARCHING: "${query}" (${limit})`.toUpperCase();
1650
+ } else if (toolCall.toolName === "web_scrape") {
1651
+ const url = parseArgs(toolCall.args).url || "...";
1652
+ label = `\u{1F4D6} READING SITE: ${url}`.toUpperCase();
1653
+ } else if (toolCall.toolName === "view_file") {
1654
+ const { path: targetPath2, start_line = 1, end_line = 500 } = parseArgs(toolCall.args);
1655
+ let totalLines = "...";
1656
+ let actualEndLine = end_line;
1657
+ try {
1658
+ const absPath = path13.resolve(process.cwd(), targetPath2);
1659
+ if (fs12.existsSync(absPath)) {
1660
+ const content = fs12.readFileSync(absPath, "utf8");
1661
+ const lines = content.split("\n").length;
1662
+ totalLines = lines;
1663
+ actualEndLine = Math.min(end_line, lines);
1664
+ }
1665
+ } catch (e) {
1666
+ }
1667
+ label = `\u{1F4C4} READING FILE: ${targetPath2}. LINES ${start_line} - ${actualEndLine} FROM ${totalLines}`.toUpperCase();
1668
+ } else if (toolCall.toolName === "list_files" || toolCall.toolName === "read_folder") {
1669
+ const action = toolCall.toolName === "list_files" ? "LISTING" : "DISCOVERING";
1670
+ label = `\u{1F4C2} ${action} DIRECTORY: ${parseArgs(toolCall.args).path || "."}`.toUpperCase();
1671
+ } else if (toolCall.toolName === "write_file" || toolCall.toolName === "update_file") {
1672
+ const action = toolCall.toolName === "write_file" ? "WRITING" : "PATCHING";
1673
+ label = `\u{1F4BE} ${action} FILE: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
1674
+ } else if (toolCall.toolName === "exec_command" || toolCall.toolName === "ask") {
1675
+ label = "";
1676
+ } else {
1677
+ label = `EXECUTING ${toolCall.toolName}`.toUpperCase();
1678
+ }
1679
+ if (label) {
1680
+ const boxWidth = Math.min(label.length + 4, 85);
1681
+ const boxTop = `\u256D${"\u2500".repeat(boxWidth)}\u256E`;
1682
+ const boxMid = `\u2502 ${label.padEnd(boxWidth - 2).substring(0, boxWidth - 2)} \u2502`;
1683
+ const boxBottom = `\u2570${"\u2500".repeat(boxWidth)}\u256F`;
1684
+ yield { type: "text", content: `
1511
1685
 
1512
1686
  ${boxTop}
1513
1687
  ${boxMid}
1514
1688
  ${boxBottom}
1515
1689
  ` };
1516
- }
1517
- if (toolCall.toolName === "exec_command") {
1518
- const { command } = parseArgs(toolCall.args);
1519
- if (command && settings.systemSettings && settings.systemSettings.allowExternalAccess === false) {
1520
- const riskyPatterns = [
1521
- /[a-zA-Z]:[\\\/]/i,
1522
- // Any drive letter path (C:\, D:/, etc)
1523
- /^\//,
1524
- // Root path on Unix
1525
- /\.\.[\\\/]/,
1526
- // Parent directory traversal
1527
- /\/etc\//,
1528
- /\/var\//,
1529
- /\/root\//,
1530
- /\/bin\//,
1531
- /\/usr\//
1532
- // Sensitive Linux paths
1533
- ];
1534
- const currentDrive = path13.resolve(process.cwd()).substring(0, 3).toLowerCase();
1535
- const isViolating = riskyPatterns.some((pattern) => {
1536
- if (pattern.source === "[a-zA-Z]:[\\\\\\/]") {
1537
- const driveMatch = command.match(/[a-zA-Z]:[\\\/]/i);
1538
- return driveMatch && driveMatch[0].toLowerCase() !== currentDrive;
1690
+ }
1691
+ if (toolCall.toolName === "exec_command") {
1692
+ const { command } = parseArgs(toolCall.args);
1693
+ if (command && settings.systemSettings && settings.systemSettings.allowExternalAccess === false) {
1694
+ const riskyPatterns = [
1695
+ /[a-zA-Z]:[\\\/]/i,
1696
+ // Any drive letter path (C:\, D:/, etc)
1697
+ /^\//,
1698
+ // Root path on Unix
1699
+ /\.\.[\\\/]/,
1700
+ // Parent directory traversal
1701
+ /\/etc\//,
1702
+ /\/var\//,
1703
+ /\/root\//,
1704
+ /\/bin\//,
1705
+ /\/usr\//
1706
+ // Sensitive Linux paths
1707
+ ];
1708
+ const currentDrive = path13.resolve(process.cwd()).substring(0, 3).toLowerCase();
1709
+ const isViolating = riskyPatterns.some((pattern) => {
1710
+ if (pattern.source === "[a-zA-Z]:[\\\\\\/]") {
1711
+ const driveMatch = command.match(/[a-zA-Z]:[\\\/]/i);
1712
+ return driveMatch && driveMatch[0].toLowerCase() !== currentDrive;
1713
+ }
1714
+ return pattern.test(command);
1715
+ });
1716
+ if (isViolating) {
1717
+ const denyMsg = `Access Denied. Terminal is prohibited from accessing system drives (C://) or external directories while "External Workspace Access" is disabled.`;
1718
+ toolResults.push(`[TOOL_RESULT]: ERROR: ${denyMsg}`);
1719
+ yield { type: "tool_result", content: `[TOOL_RESULT]: ERROR: ${denyMsg}` };
1720
+ continue;
1721
+ }
1722
+ }
1723
+ if (settings.onExecStart) settings.onExecStart(command || "Unknown");
1724
+ yield { type: "exec_start" };
1725
+ }
1726
+ const parsedArgs = parseArgs(toolCall.args);
1727
+ const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
1728
+ if (targetPath) {
1729
+ const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
1730
+ const absoluteTarget = path13.resolve(targetPath);
1731
+ const absoluteCwd = path13.resolve(process.cwd());
1732
+ if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
1733
+ const denyMsg = `Access Denied. You are not allowed to access files outside the current workspace. To enable this, ask the user to turn on "External Workspace Access" in /settings.`;
1734
+ toolResults.push(`[TOOL_RESULT]: ERROR: ${denyMsg}`);
1735
+ yield { type: "tool_result", content: `[TOOL_RESULT]: ERROR: ${denyMsg}` };
1736
+ continue;
1737
+ }
1738
+ }
1739
+ if (settings.onToolApproval) {
1740
+ let shouldPrompt = false;
1741
+ if (toolCall.toolName === "write_file" || toolCall.toolName === "update_file") {
1742
+ shouldPrompt = true;
1743
+ } else if (toolCall.toolName === "exec_command") {
1744
+ shouldPrompt = true;
1745
+ }
1746
+ if (shouldPrompt) {
1747
+ const approval = await settings.onToolApproval(toolCall.toolName, toolCall.args);
1748
+ if (approval === "deny") {
1749
+ if (toolCall.toolName === "exec_command" && settings.onExecEnd) settings.onExecEnd();
1750
+ const denyMsg = `Permission Denied: User rejected the ${toolCall.toolName === "exec_command" ? "terminal execution" : "file edit"}.`;
1751
+ toolResults.push(`[TOOL_RESULT]: ERROR: ${denyMsg}`);
1752
+ yield { type: "tool_result", content: `[TOOL_RESULT]: ERROR: ${denyMsg}` };
1753
+ continue;
1754
+ }
1539
1755
  }
1540
- return pattern.test(command);
1756
+ }
1757
+ const result = await dispatchTool(toolCall.toolName, toolCall.args, {
1758
+ chatId,
1759
+ history,
1760
+ onChunk: (chunk) => settings.onExecChunk ? settings.onExecChunk(chunk) : null,
1761
+ onAskUser: settings.onAskUser
1541
1762
  });
1542
- if (isViolating) {
1543
- const denyMsg = `Access Denied. Terminal is prohibited from accessing system drives (C://) or external directories while "External Workspace Access" is disabled.`;
1544
- toolResults.push(`[TOOL_RESULT]: ERROR: ${denyMsg}`);
1545
- yield { type: "tool_result", content: `[TOOL_RESULT]: ERROR: ${denyMsg}` };
1546
- continue;
1763
+ if (toolCall.toolName === "exec_command" && settings.onExecEnd) {
1764
+ await new Promise((resolve) => setTimeout(resolve, 800));
1765
+ settings.onExecEnd();
1547
1766
  }
1548
- }
1549
- if (settings.onExecStart) settings.onExecStart(command || "Unknown");
1550
- yield { type: "exec_start" };
1551
- }
1552
- const parsedArgs = parseArgs(toolCall.args);
1553
- const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
1554
- if (targetPath) {
1555
- const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
1556
- const absoluteTarget = path13.resolve(targetPath);
1557
- const absoluteCwd = path13.resolve(process.cwd());
1558
- if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
1559
- const denyMsg = `Access Denied. You are not allowed to access files outside the current workspace. To enable this, ask the user to turn on "External Workspace Access" in /settings.`;
1560
- toolResults.push(`[TOOL_RESULT]: ERROR: ${denyMsg}`);
1561
- yield { type: "tool_result", content: `[TOOL_RESULT]: ERROR: ${denyMsg}` };
1562
- continue;
1563
- }
1564
- }
1565
- if (settings.onToolApproval) {
1566
- let shouldPrompt = false;
1567
- if (toolCall.toolName === "write_file" || toolCall.toolName === "update_file") {
1568
- shouldPrompt = true;
1569
- } else if (toolCall.toolName === "exec_command") {
1570
- shouldPrompt = true;
1571
- }
1572
- if (shouldPrompt) {
1573
- const approval = await settings.onToolApproval(toolCall.toolName, toolCall.args);
1574
- if (approval === "deny") {
1575
- if (toolCall.toolName === "exec_command" && settings.onExecEnd) settings.onExecEnd();
1576
- const denyMsg = `Permission Denied: User rejected the ${toolCall.toolName === "exec_command" ? "terminal execution" : "file edit"}.`;
1577
- toolResults.push(`[TOOL_RESULT]: ERROR: ${denyMsg}`);
1578
- yield { type: "tool_result", content: `[TOOL_RESULT]: ERROR: ${denyMsg}` };
1579
- continue;
1767
+ try {
1768
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1769
+ const isErr = result.startsWith("ERROR:");
1770
+ const logStatus = isErr ? result.trim() : "SUCCESS";
1771
+ const toolHistDir = path13.join(LOGS_DIR, "tools");
1772
+ if (!fs12.existsSync(toolHistDir)) {
1773
+ fs12.mkdirSync(toolHistDir, { recursive: true });
1774
+ }
1775
+ fs12.appendFileSync(path13.join(toolHistDir, "history.log"), `HISTORY [${timestamp}]: ${toolCall.toolName} [${logStatus}]
1776
+ `);
1777
+ } catch (logErr) {
1778
+ }
1779
+ const cleanResultForAI = result.split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n");
1780
+ toolResults.push(`[TOOL_RESULT]: ${cleanResultForAI}`);
1781
+ let uiContent = `[TOOL_RESULT]: ${result}`;
1782
+ if (toolCall.toolName === "view_file" || toolCall.toolName === "web_scrape") {
1783
+ uiContent = `[TOOL_RESULT]: ${label} (Context Locked for UI Clarity)`;
1784
+ }
1785
+ yield { type: "tool_result", content: uiContent };
1786
+ if (toolCall.toolName === "memory" && result.includes("SUCCESS")) {
1787
+ yield { type: "memory_updated" };
1580
1788
  }
1581
1789
  }
1790
+ yield { type: "status", content: "Working..." };
1582
1791
  }
1583
- const result = await dispatchTool(toolCall.toolName, toolCall.args, {
1584
- chatId,
1585
- history,
1586
- onChunk: (chunk) => settings.onExecChunk ? settings.onExecChunk(chunk) : null,
1587
- onAskUser: settings.onAskUser
1588
- });
1589
- if (toolCall.toolName === "exec_command" && settings.onExecEnd) {
1590
- await new Promise((resolve) => setTimeout(resolve, 800));
1591
- settings.onExecEnd();
1592
- }
1593
- try {
1594
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1595
- const isErr = result.startsWith("ERROR:");
1596
- const logStatus = isErr ? result.trim() : "SUCCESS";
1597
- const toolHistDir = path13.join(LOGS_DIR, "tools");
1598
- if (!fs12.existsSync(toolHistDir)) {
1599
- fs12.mkdirSync(toolHistDir, { recursive: true });
1600
- }
1601
- fs12.appendFileSync(path13.join(toolHistDir, "history.log"), `HISTORY [${timestamp}]: ${toolCall.toolName} [${logStatus}]
1602
- `);
1603
- } catch (logErr) {
1604
- }
1605
- const cleanResultForAI = result.split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n");
1606
- toolResults.push(`[TOOL_RESULT]: ${cleanResultForAI}`);
1607
- let uiContent = `[TOOL_RESULT]: ${result}`;
1608
- if (toolCall.toolName === "view_file" || toolCall.toolName === "web_scrape") {
1609
- uiContent = `[TOOL_RESULT]: ${label} (Context Locked for UI Clarity)`;
1610
- }
1611
- yield { type: "tool_result", content: uiContent };
1612
- if (toolCall.toolName === "memory" && result.includes("SUCCESS")) {
1613
- yield { type: "memory_updated" };
1614
- }
1615
- }
1616
- yield { type: "status", content: "Working..." };
1617
- }
1618
- const cleanedTurnText = turnText.replace(/<think>[\s\S]*?<\/think>/g, "").replace(/\[?\s*(turn\s*:)?\s*(continue|finish)\s*\]?/gi, "").trim();
1619
- const isActuallyFinished = hasFinish;
1620
- if (isActuallyFinished) {
1621
- const lateHint = await steeringCallback();
1622
- if (lateHint) {
1623
- toolResults.push(`[USER STEERING HINT]: ${lateHint}`);
1624
- yield { type: "status", content: "Steering detected... resuming!" };
1625
- continue;
1626
- }
1627
- yield { type: "status", content: "Finalizing..." };
1628
- const janitorContents = history.slice(-3).filter((msg) => msg.text && !msg.text.includes("[TOOL_RESULT]") && !msg.text.includes("OBSERVATION:")).map((msg) => ({
1629
- role: msg.role === "user" ? "user" : "model",
1630
- parts: [{ text: msg.text.replace(/<think>[\s\S]*?<\/think>/g, "").trim() }]
1631
- }));
1632
- const cleanedFullResponse = fullAgentResponse.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
1633
- const janitorPrompt = getJanitorInstruction(
1634
- agentText,
1635
- cleanedFullResponse,
1636
- janitorUserMemories,
1637
- isMemoryEnabled,
1638
- needTitle
1639
- );
1640
- janitorContents.push({ role: "user", parts: [{ text: janitorPrompt }] });
1641
- let finalSynthesis = "";
1642
- try {
1643
- if (!await checkQuota("background", settings)) {
1644
- console.warn("Quota Exhausted for Background Model. Skipping refinement.");
1645
- throw new Error("QUOTA_BLOCKED");
1646
- }
1647
- const janitorResult = await client.models.generateContent({
1648
- model: janitorModel || "gemma-4-26b-a4b-it",
1649
- contents: janitorContents,
1650
- config: {
1651
- thinkingConfig: {
1652
- includeThoughts: false,
1653
- thinkingLevel: ThinkingLevel.MINIMAL
1792
+ const cleanedTurnText = turnText.replace(/<think>[\s\S]*?<\/think>/g, "").replace(/\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").trim();
1793
+ let isActuallyFinished = hasFinish && !shouldContinue;
1794
+ if (isActuallyFinished) {
1795
+ yield { type: "status", content: "Finalizing..." };
1796
+ const janitorContents = history.slice(-3).filter((msg) => msg.text && !msg.text.includes("[TOOL_RESULT]") && !msg.text.includes("OBSERVATION:")).map((msg) => ({
1797
+ role: msg.role === "user" ? "user" : "model",
1798
+ parts: [{ text: msg.text.replace(/<think>[\s\S]*?<\/think>/g, "").trim() }]
1799
+ }));
1800
+ const fullAgentTextRaw = fullAgentResponseChunks.join("\n");
1801
+ const cleanedFullResponse = fullAgentTextRaw.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
1802
+ const janitorPrompt = getJanitorInstruction(
1803
+ agentText,
1804
+ cleanedFullResponse,
1805
+ janitorUserMemories,
1806
+ isMemoryEnabled,
1807
+ needTitle
1808
+ );
1809
+ janitorContents.push({ role: "user", parts: [{ text: janitorPrompt }] });
1810
+ let finalSynthesis = "";
1811
+ try {
1812
+ if (!await checkQuota("background", settings)) {
1813
+ console.warn("Quota Exhausted for Background Model. Skipping refinement.");
1814
+ throw new Error("QUOTA_BLOCKED");
1654
1815
  }
1655
- }
1656
- });
1657
- const parts = janitorResult.candidates?.[0]?.content?.parts;
1658
- if (parts && parts[1]?.text) {
1659
- finalSynthesis = parts[1].text;
1660
- const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1661
- const janitorLogDir = path13.join(LOGS_DIR, "janitor");
1662
- if (!fs12.existsSync(janitorLogDir)) {
1663
- fs12.mkdirSync(janitorLogDir, { recursive: true });
1664
- }
1665
- fs12.appendFileSync(path13.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: ${finalSynthesis}
1816
+ const janitorResult = await client.models.generateContent({
1817
+ model: janitorModel || "gemma-4-26b-a4b-it",
1818
+ contents: janitorContents,
1819
+ config: {
1820
+ thinkingConfig: {
1821
+ includeThoughts: false,
1822
+ thinkingLevel: ThinkingLevel.MINIMAL
1823
+ }
1824
+ }
1825
+ });
1826
+ const parts = janitorResult.candidates?.[0]?.content?.parts;
1827
+ if (parts && parts[1]?.text) {
1828
+ finalSynthesis = parts[1].text;
1829
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1830
+ const janitorLogDir = path13.join(LOGS_DIR, "janitor");
1831
+ if (!fs12.existsSync(janitorLogDir)) {
1832
+ fs12.mkdirSync(janitorLogDir, { recursive: true });
1833
+ }
1834
+ fs12.appendFileSync(path13.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: ${finalSynthesis}
1666
1835
  `);
1667
- } else if (parts && parts[0]?.text) finalSynthesis = parts[0].text;
1668
- else if (janitorResult.response && janitorResult.response.text) finalSynthesis = janitorResult.response.text();
1669
- else throw new Error("No synthesis generated by Janitor.");
1670
- await incrementUsage("background");
1671
- yield { type: "background_increment" };
1672
- const janitorToolCalls = detectToolCalls(finalSynthesis);
1673
- for (const janitorToolCall of janitorToolCalls) {
1674
- const toolContext = { chatId, sessionId: chatId, history };
1675
- const result = await dispatchTool(janitorToolCall.toolName, janitorToolCall.args, toolContext);
1676
- const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1677
- const janitorLogDir = path13.join(LOGS_DIR, "janitor");
1678
- fs12.appendFileSync(path13.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: RESULT [${janitorToolCall.toolName}]: ${result}
1836
+ } else if (parts && parts[0]?.text) finalSynthesis = parts[0].text;
1837
+ else if (janitorResult.response && janitorResult.response.text) finalSynthesis = janitorResult.response.text();
1838
+ else throw new Error("No synthesis generated by Janitor.");
1839
+ await incrementUsage("background");
1840
+ yield { type: "background_increment" };
1841
+ const janitorToolCalls = detectToolCalls(finalSynthesis);
1842
+ for (const janitorToolCall of janitorToolCalls) {
1843
+ const toolContext = { chatId, sessionId: chatId, history };
1844
+ const result = await dispatchTool(janitorToolCall.toolName, janitorToolCall.args, toolContext);
1845
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1846
+ const janitorLogDir = path13.join(LOGS_DIR, "janitor");
1847
+ fs12.appendFileSync(path13.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: RESULT [${janitorToolCall.toolName}]: ${result}
1679
1848
  `);
1680
- if (janitorToolCall.toolName === "memory" && !janitorToolCall.args.includes("action='temp'")) {
1681
- yield { type: "memory_updated" };
1682
- }
1683
- }
1684
- } catch (janitorErr) {
1685
- const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1686
- const janitorErrDir = path13.join(LOGS_DIR, "janitor");
1687
- if (!fs12.existsSync(janitorErrDir)) {
1688
- fs12.mkdirSync(janitorErrDir, { recursive: true });
1689
- }
1690
- fs12.appendFileSync(path13.join(janitorErrDir, "error.log"), `ERROR [${date}]: ${janitorErr.message}
1849
+ if (janitorToolCall.toolName === "memory" && !janitorToolCall.args.includes("action='temp'")) {
1850
+ yield { type: "memory_updated" };
1851
+ }
1852
+ }
1853
+ } catch (janitorErr) {
1854
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
1855
+ const janitorErrDir = path13.join(LOGS_DIR, "janitor");
1856
+ if (!fs12.existsSync(janitorErrDir)) {
1857
+ fs12.mkdirSync(janitorErrDir, { recursive: true });
1858
+ }
1859
+ fs12.appendFileSync(path13.join(janitorErrDir, "error.log"), `ERROR [${date}]: ${janitorErr.message}
1691
1860
  `);
1692
- console.error("Janitor Background Tasks Failed:", janitorErr.message);
1693
- }
1694
- const timestamp = `Responded on ${(/* @__PURE__ */ new Date()).toLocaleString()}`;
1695
- const finalWithTime = `${cleanedFullResponse}
1861
+ console.error("Janitor Background Tasks Failed:", janitorErr.message);
1862
+ }
1863
+ const timestamp = `Responded on ${(/* @__PURE__ */ new Date()).toLocaleString()}`;
1864
+ const finalWithTime = `${cleanedFullResponse}
1696
1865
 
1697
1866
  ${timestamp}`;
1698
- if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "agent") {
1699
- modifiedHistory[modifiedHistory.length - 1].text = finalWithTime;
1700
- } else {
1701
- modifiedHistory.push({ role: "agent", text: finalWithTime });
1867
+ if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "agent") {
1868
+ modifiedHistory[modifiedHistory.length - 1].text = finalWithTime;
1869
+ } else {
1870
+ modifiedHistory.push({ role: "agent", text: finalWithTime });
1871
+ }
1872
+ }
1873
+ if (isActuallyFinished) break;
1874
+ const nextAgentMsg = cleanedTurnText.trim() || "*Working...*";
1875
+ modifiedHistory.push({ role: "agent", text: nextAgentMsg });
1876
+ const nextUserMsg = toolResults.length > 0 ? toolResults.join("\n") : "[turn: continue]";
1877
+ modifiedHistory.push({ role: "user", text: nextUserMsg });
1702
1878
  }
1703
- break;
1704
- }
1705
- if (isActuallyFinished) break;
1706
- const nextAgentMsg = cleanedTurnText.trim() || "*Working...*";
1707
- modifiedHistory.push({ role: "agent", text: nextAgentMsg });
1708
- const nextUserMsg = toolResults.length > 0 ? toolResults.join("\n") : "[turn: continue]";
1709
- modifiedHistory.push({ role: "user", text: nextUserMsg });
1879
+ yield { type: "status", content: null };
1880
+ };
1710
1881
  }
1711
- yield { type: "status", content: null };
1712
- };
1882
+ });
1713
1883
 
1714
1884
  // src/utils/settings.js
1715
1885
  import fs13 from "fs-extra";
1716
1886
  import path14 from "path";
1717
- var DEFAULT_SETTINGS = {
1718
- mode: "Flux",
1719
- thinkingLevel: "Medium",
1720
- activeModel: "gemma-4-31b-it",
1721
- showFullThinking: false,
1722
- apiTier: "Free",
1723
- quotas: {
1724
- agentLimit: 1500,
1725
- backgroundLimit: 1500,
1726
- searchLimit: 100,
1727
- customModelId: "",
1728
- customLimit: 0
1729
- },
1730
- systemSettings: {
1731
- memory: true,
1732
- compression: 0,
1733
- autoExec: false,
1734
- allowExternalAccess: false,
1735
- autoDeleteHistory: "7d"
1736
- },
1737
- profileData: {
1738
- name: null,
1739
- nickname: null,
1740
- instructions: null
1741
- }
1742
- };
1743
- var loadSettings = async () => {
1744
- try {
1745
- if (await fs13.exists(SETTINGS_FILE)) {
1746
- const saved = await fs13.readJson(SETTINGS_FILE);
1747
- return {
1748
- ...DEFAULT_SETTINGS,
1749
- ...saved,
1750
- quotas: { ...DEFAULT_SETTINGS.quotas, ...saved.quotas },
1751
- systemSettings: { ...DEFAULT_SETTINGS.systemSettings, ...saved.systemSettings },
1752
- profileData: { ...DEFAULT_SETTINGS.profileData, ...saved.profileData }
1753
- };
1754
- }
1755
- } catch (err) {
1756
- console.error("Failed to load settings:", err);
1757
- }
1758
- return DEFAULT_SETTINGS;
1759
- };
1760
- var saveSettings = async (settings) => {
1761
- try {
1762
- const current = await loadSettings();
1763
- const updated = { ...current, ...settings };
1764
- await fs13.ensureDir(path14.dirname(SETTINGS_FILE));
1765
- await fs13.writeJson(SETTINGS_FILE, updated, { spaces: 2 });
1766
- return true;
1767
- } catch (err) {
1768
- console.error("Failed to save settings:", err);
1769
- return false;
1887
+ var DEFAULT_SETTINGS, loadSettings, saveSettings;
1888
+ var init_settings = __esm({
1889
+ "src/utils/settings.js"() {
1890
+ init_paths();
1891
+ DEFAULT_SETTINGS = {
1892
+ mode: "Flux",
1893
+ thinkingLevel: "Medium",
1894
+ activeModel: "gemma-4-31b-it",
1895
+ showFullThinking: false,
1896
+ apiTier: "Free",
1897
+ quotas: {
1898
+ agentLimit: 1500,
1899
+ backgroundLimit: 1500,
1900
+ searchLimit: 100,
1901
+ customModelId: "",
1902
+ customLimit: 0
1903
+ },
1904
+ systemSettings: {
1905
+ memory: true,
1906
+ compression: 0,
1907
+ autoExec: false,
1908
+ allowExternalAccess: false,
1909
+ autoDeleteHistory: "7d"
1910
+ },
1911
+ profileData: {
1912
+ name: null,
1913
+ nickname: null,
1914
+ instructions: null
1915
+ }
1916
+ };
1917
+ loadSettings = async () => {
1918
+ try {
1919
+ if (await fs13.exists(SETTINGS_FILE)) {
1920
+ const saved = await fs13.readJson(SETTINGS_FILE);
1921
+ return {
1922
+ ...DEFAULT_SETTINGS,
1923
+ ...saved,
1924
+ quotas: { ...DEFAULT_SETTINGS.quotas, ...saved.quotas },
1925
+ systemSettings: { ...DEFAULT_SETTINGS.systemSettings, ...saved.systemSettings },
1926
+ profileData: { ...DEFAULT_SETTINGS.profileData, ...saved.profileData }
1927
+ };
1928
+ }
1929
+ } catch (err) {
1930
+ console.error("Failed to load settings:", err);
1931
+ }
1932
+ return DEFAULT_SETTINGS;
1933
+ };
1934
+ saveSettings = async (settings) => {
1935
+ try {
1936
+ const current = await loadSettings();
1937
+ const updated = { ...current, ...settings };
1938
+ await fs13.ensureDir(path14.dirname(SETTINGS_FILE));
1939
+ await fs13.writeJson(SETTINGS_FILE, updated, { spaces: 2 });
1940
+ return true;
1941
+ } catch (err) {
1942
+ console.error("Failed to save settings:", err);
1943
+ return false;
1944
+ }
1945
+ };
1770
1946
  }
1771
- };
1947
+ });
1772
1948
 
1773
1949
  // src/components/ResumeModal.jsx
1774
1950
  import React7, { useState as useState3, useEffect } from "react";
@@ -1807,6 +1983,11 @@ function ResumeModal({ onSelect, onDelete, onClose }) {
1807
1983
  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) ")));
1808
1984
  }), /* @__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 ")));
1809
1985
  }
1986
+ var init_ResumeModal = __esm({
1987
+ "src/components/ResumeModal.jsx"() {
1988
+ init_history();
1989
+ }
1990
+ });
1810
1991
 
1811
1992
  // src/components/MemoryModal.jsx
1812
1993
  import React8, { useState as useState4, useEffect as useEffect2 } from "react";
@@ -1840,51 +2021,47 @@ function MemoryModal({ onClose }) {
1840
2021
  };
1841
2022
  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")));
1842
2023
  }
2024
+ var init_MemoryModal = __esm({
2025
+ "src/components/MemoryModal.jsx"() {
2026
+ init_crypto();
2027
+ init_paths();
2028
+ }
2029
+ });
1843
2030
 
1844
2031
  // src/utils/terminal.js
1845
- var getTerminalEnv = () => {
1846
- if (process.env.TERM_PROGRAM === "vscode") return "vscode";
1847
- if (process.env.WT_SESSION) return "wt";
1848
- return "default";
1849
- };
1850
- var emojiSpace = (baseSpaces = 2) => {
1851
- const env = getTerminalEnv();
1852
- if (env === "wt") {
1853
- return " ".repeat(Math.max(1, baseSpaces - 1));
1854
- }
1855
- if (env === "vscode") {
1856
- return " ".repeat(baseSpaces);
2032
+ var getTerminalEnv, emojiSpace;
2033
+ var init_terminal = __esm({
2034
+ "src/utils/terminal.js"() {
2035
+ getTerminalEnv = () => {
2036
+ if (process.env.TERM_PROGRAM === "vscode") return "vscode";
2037
+ if (process.env.WT_SESSION) return "wt";
2038
+ return "default";
2039
+ };
2040
+ emojiSpace = (baseSpaces = 2) => {
2041
+ const env = getTerminalEnv();
2042
+ if (env === "wt") {
2043
+ return " ".repeat(Math.max(1, baseSpaces - 1));
2044
+ }
2045
+ if (env === "vscode") {
2046
+ return " ".repeat(baseSpaces);
2047
+ }
2048
+ return " ".repeat(baseSpaces);
2049
+ };
1857
2050
  }
1858
- return " ".repeat(baseSpaces);
1859
- };
2051
+ });
1860
2052
 
1861
2053
  // src/app.jsx
1862
- var SESSION_START_TIME = Date.now();
1863
- var CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
1864
- var versionFluxflow = "1.1.7";
1865
- var updatedOn = "2026-04-27";
1866
- 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(
1867
- CommandMenu,
1868
- {
1869
- title: "Select Action",
1870
- items: [
1871
- { label: "Send Anyway", value: "send" },
1872
- { label: "Edit Prompt", value: "edit" }
1873
- ],
1874
- onSelect: (val) => {
1875
- if (val === "send") onResolve(data);
1876
- else onEdit(data);
1877
- }
1878
- }
1879
- )));
1880
- var FLUX_LOGO = gradient(["#00ffff", "#0077ff", "#ff00ff"]).multiline(
1881
- `\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557
1882
- \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551
1883
- \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2557 \u2588\u2588\u2551
1884
- \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2557\u2588\u2588\u2551
1885
- \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2554\u255D \u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2554\u2588\u2588\u2588\u2554\u255D
1886
- \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u255D\u255A\u2550\u2550\u255D`
1887
- );
2054
+ var app_exports = {};
2055
+ __export(app_exports, {
2056
+ default: () => App
2057
+ });
2058
+ import React9, { useState as useState5, useEffect as useEffect3, useRef, useMemo } from "react";
2059
+ import { Box as Box9, Text as Text9, useInput as useInput4, useStdout } from "ink";
2060
+ import fs14 from "fs-extra";
2061
+ import { exec } from "child_process";
2062
+ import { MultilineInput } from "ink-multiline-input";
2063
+ import TextInput3 from "ink-text-input";
2064
+ import gradient from "gradient-string";
1888
2065
  function App() {
1889
2066
  const { stdout } = useStdout();
1890
2067
  const [input, setInput] = useState5("");
@@ -2428,23 +2605,26 @@ Selection: ${val}`,
2428
2605
  });
2429
2606
  }
2430
2607
  },
2431
- async (hint) => {
2432
- if (queuedPrompt) {
2433
- if (queuedPromptRef.current) {
2434
- const p = queuedPromptRef.current;
2435
- setQueuedPrompt(null);
2436
- queuedPromptRef.current = null;
2437
- setMessages((prev) => {
2608
+ async () => {
2609
+ if (queuedPromptRef.current) {
2610
+ const p = queuedPromptRef.current;
2611
+ setQueuedPrompt(null);
2612
+ queuedPromptRef.current = null;
2613
+ setMessages((prev) => {
2614
+ const index = [...prev].reverse().findIndex((m) => m.text?.includes("[STEERING HINT: QUEUED]"));
2615
+ if (index !== -1) {
2616
+ const actualIndex = prev.length - 1 - index;
2438
2617
  const newMsgs = [...prev];
2439
- const hintMsg = newMsgs.reverse().find((m) => m.text?.includes("[STEERING HINT: QUEUED]"));
2440
- if (hintMsg) {
2441
- hintMsg.text = hintMsg.text.replace("[STEERING HINT: QUEUED]", "[STEERING HINT: INJECTED]");
2442
- hintMsg.color = "cyan";
2443
- }
2444
- return newMsgs.reverse();
2445
- });
2446
- return p;
2447
- }
2618
+ newMsgs[actualIndex] = {
2619
+ ...newMsgs[actualIndex],
2620
+ text: newMsgs[actualIndex].text.replace("[STEERING HINT: QUEUED]", "[STEERING HINT: INJECTED]"),
2621
+ color: "cyan"
2622
+ };
2623
+ return newMsgs;
2624
+ }
2625
+ return prev;
2626
+ });
2627
+ return p;
2448
2628
  }
2449
2629
  return null;
2450
2630
  }
@@ -2497,41 +2677,50 @@ Selection: ${val}`,
2497
2677
  continue;
2498
2678
  }
2499
2679
  let chunkText = packet.content;
2500
- if (chunkText.includes("<think>") && !inThinkMode) {
2680
+ if (chunkText.toLowerCase().includes("<think") && !inThinkMode) {
2501
2681
  inThinkMode = true;
2502
- chunkText = chunkText.replace("<think>", "");
2682
+ chunkText = chunkText.replace(/<think>/gi, "");
2503
2683
  currentThinkId = "think-" + Date.now();
2504
2684
  setMessages((prev) => [...prev, { id: currentThinkId, role: "think", text: "" }]);
2505
2685
  }
2506
- if (chunkText.includes("</think>")) {
2507
- const [thinkPart, agentPart] = chunkText.split("</think>");
2508
- if (inThinkMode) {
2509
- setMessages((prev) => {
2510
- const newMsgs = prev.map(
2511
- (m) => m.id === currentThinkId ? { ...m, text: m.text + thinkPart.replace(signalRegex, "") } : m
2512
- );
2513
- currentAgentId = "agent-" + Date.now();
2514
- const cleanedAgentPart = (agentPart || "").replace(signalRegex, "");
2515
- return [...newMsgs, { id: currentAgentId, role: "agent", text: cleanedAgentPart }];
2516
- });
2686
+ if (chunkText.toLowerCase().includes("</think>")) {
2687
+ const parts = chunkText.split(/<\/think>/gi);
2688
+ const thinkPart = parts[0] || "";
2689
+ const agentPart = parts.slice(1).join("</think>") || "";
2690
+ setMessages((prev) => {
2691
+ const newMsgs = prev.map(
2692
+ (m) => m.id === currentThinkId ? { ...m, text: m.text + thinkPart } : m
2693
+ );
2517
2694
  inThinkMode = false;
2518
- } else {
2519
- const cleanedContent = (agentPart || thinkPart || "").replace(signalRegex, "");
2520
- if (!currentAgentId) {
2521
- currentAgentId = "agent-" + Date.now();
2522
- setMessages((prev) => [...prev, { id: currentAgentId, role: "agent", text: cleanedContent }]);
2523
- } else {
2524
- setMessages((prev) => prev.map(
2525
- (m) => m.id === currentAgentId ? { ...m, text: m.text + cleanedContent } : m
2526
- ));
2527
- }
2528
- }
2695
+ currentAgentId = "agent-" + Date.now();
2696
+ return [...newMsgs, { id: currentAgentId, role: "agent", text: agentPart.replace(/<\/?think>/gi, "") }];
2697
+ });
2529
2698
  continue;
2530
2699
  }
2531
2700
  if (inThinkMode && currentThinkId) {
2532
- setMessages((prev) => prev.map(
2533
- (m) => m.id === currentThinkId ? { ...m, text: m.text + chunkText.replace(signalRegex, "") } : m
2534
- ));
2701
+ setMessages((prev) => {
2702
+ let transitioning = false;
2703
+ let transitionContent = "";
2704
+ const newMsgs = prev.map((m) => {
2705
+ if (m.id === currentThinkId) {
2706
+ const newText = m.text + chunkText;
2707
+ if (newText.toLowerCase().includes("</think>")) {
2708
+ transitioning = true;
2709
+ const parts = newText.split(/<\/think>/gi);
2710
+ transitionContent = parts.slice(1).join("</think>") || "";
2711
+ return { ...m, text: parts[0] };
2712
+ }
2713
+ return { ...m, text: newText };
2714
+ }
2715
+ return m;
2716
+ });
2717
+ if (transitioning) {
2718
+ inThinkMode = false;
2719
+ currentAgentId = "agent-" + Date.now();
2720
+ return [...newMsgs, { id: currentAgentId, role: "agent", text: transitionContent.replace(/<\/?think>/gi, "") }];
2721
+ }
2722
+ return newMsgs;
2723
+ });
2535
2724
  } else if (!inThinkMode) {
2536
2725
  const cleanedText = chunkText.replace(/<\/?think>/gi, "").replace(signalRegex, "");
2537
2726
  if (!currentAgentId) {
@@ -2963,7 +3152,9 @@ Selection: ${val}`,
2963
3152
  onResolve: (val) => {
2964
3153
  setResolutionData(null);
2965
3154
  setActiveView("chat");
2966
- handleSubmit(val);
3155
+ setTimeout(() => {
3156
+ handleSubmit(val);
3157
+ }, 50);
2967
3158
  },
2968
3159
  onEdit: (val) => {
2969
3160
  setResolutionData(null);
@@ -3071,26 +3262,89 @@ Selection: ${val}`,
3071
3262
  }
3072
3263
  ))));
3073
3264
  }
3265
+ var SESSION_START_TIME, CHANGELOG_URL, versionFluxflow, updatedOn, ResolutionModal, FLUX_LOGO;
3266
+ var init_app = __esm({
3267
+ "src/app.jsx"() {
3268
+ init_ChatLayout();
3269
+ init_StatusBar();
3270
+ init_CommandMenu();
3271
+ init_ProfileForm();
3272
+ init_AskUserModal();
3273
+ init_secrets();
3274
+ init_ai();
3275
+ init_settings();
3276
+ init_history();
3277
+ init_ResumeModal();
3278
+ init_MemoryModal();
3279
+ init_usage();
3280
+ init_TerminalBox();
3281
+ init_arg_parser();
3282
+ init_paths();
3283
+ init_terminal();
3284
+ SESSION_START_TIME = Date.now();
3285
+ CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
3286
+ versionFluxflow = "1.2.0";
3287
+ updatedOn = "2026-04-27";
3288
+ 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(
3289
+ CommandMenu,
3290
+ {
3291
+ title: "Select Action",
3292
+ items: [
3293
+ { label: "Send Anyway", value: "send" },
3294
+ { label: "Edit Prompt", value: "edit" }
3295
+ ],
3296
+ onSelect: (val) => {
3297
+ if (val === "send") onResolve(data);
3298
+ else onEdit(data);
3299
+ }
3300
+ }
3301
+ )));
3302
+ FLUX_LOGO = gradient(["#00ffff", "#0077ff", "#ff00ff"]).multiline(
3303
+ `\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557
3304
+ \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551
3305
+ \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2557 \u2588\u2588\u2551
3306
+ \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2557\u2588\u2588\u2551
3307
+ \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2554\u255D \u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2554\u2588\u2588\u2588\u2554\u255D
3308
+ \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u255D\u255A\u2550\u2550\u255D`
3309
+ );
3310
+ }
3311
+ });
3074
3312
 
3075
3313
  // src/cli.jsx
3076
- process.env.NODE_NO_WARNINGS = "1";
3077
- var silentPatterns = [
3078
- "cuimp",
3079
- "Found existing binary",
3080
- "Binary verified",
3081
- "curl.exe not found",
3082
- "Falling back to .bat file",
3083
- "DeprecationWarning"
3084
- ];
3085
- var originalLog = console.log;
3086
- var originalWarn = console.warn;
3087
- var originalError = console.error;
3088
- var isNoise = (args) => {
3089
- const msg = args.map(String).join(" ");
3090
- return silentPatterns.some((p) => msg.includes(p));
3091
- };
3092
- console.log = (...args) => !isNoise(args) && originalLog(...args);
3093
- console.warn = (...args) => !isNoise(args) && originalWarn(...args);
3094
- console.error = (...args) => !isNoise(args) && originalError(...args);
3095
- process.stdout.write("\x1Bc");
3096
- render(/* @__PURE__ */ React10.createElement(App, null));
3314
+ import { spawn as spawn2 } from "child_process";
3315
+ import { fileURLToPath } from "url";
3316
+ var HEAP_LIMIT = 4096;
3317
+ var isBundled = fileURLToPath(import.meta.url).endsWith(".js");
3318
+ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-size"))) {
3319
+ const cp = spawn2(process.execPath, [
3320
+ `--max-old-space-size=${HEAP_LIMIT}`,
3321
+ fileURLToPath(import.meta.url),
3322
+ ...process.argv.slice(2)
3323
+ ], { stdio: "inherit" });
3324
+ cp.on("exit", (code) => process.exit(code || 0));
3325
+ } else {
3326
+ const { default: React10 } = await import("react");
3327
+ const { render } = await import("ink");
3328
+ const { default: App2 } = await Promise.resolve().then(() => (init_app(), app_exports));
3329
+ process.env.NODE_NO_WARNINGS = "1";
3330
+ const silentPatterns = [
3331
+ "cuimp",
3332
+ "Found existing binary",
3333
+ "Binary verified",
3334
+ "curl.exe not found",
3335
+ "Falling back to .bat file",
3336
+ "DeprecationWarning"
3337
+ ];
3338
+ const originalLog = console.log;
3339
+ const originalWarn = console.warn;
3340
+ const originalError = console.error;
3341
+ const isNoise = (args) => {
3342
+ const msg = args.map(String).join(" ");
3343
+ return silentPatterns.some((p) => msg.includes(p));
3344
+ };
3345
+ console.log = (...args) => !isNoise(args) && originalLog(...args);
3346
+ console.warn = (...args) => !isNoise(args) && originalWarn(...args);
3347
+ console.error = (...args) => !isNoise(args) && originalError(...args);
3348
+ process.stdout.write("\x1Bc");
3349
+ render(/* @__PURE__ */ React10.createElement(App2, null));
3350
+ }