fluxflow-cli 3.15.2 → 3.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/TOOLS.md +1 -4
- package/dist/fluxflow.js +929 -313
- package/model_config.json +1 -1
- package/package.json +75 -73
package/dist/fluxflow.js
CHANGED
|
@@ -52,13 +52,14 @@ __export(paths_exports, {
|
|
|
52
52
|
SETTINGS_FILE: () => SETTINGS_FILE,
|
|
53
53
|
TEMP_MEM_CHAT_FILE: () => TEMP_MEM_CHAT_FILE,
|
|
54
54
|
TEMP_MEM_FILE: () => TEMP_MEM_FILE,
|
|
55
|
-
USAGE_FILE: () => USAGE_FILE
|
|
55
|
+
USAGE_FILE: () => USAGE_FILE,
|
|
56
|
+
USAGE_FILE_OLD: () => USAGE_FILE_OLD
|
|
56
57
|
});
|
|
57
58
|
import os from "os";
|
|
58
59
|
import path from "path";
|
|
59
60
|
import fs from "fs";
|
|
60
61
|
import crypto from "crypto";
|
|
61
|
-
var FLUXFLOW_DIR, SETTINGS_FILE, externalDir, DATA_DIR, LOGS_DIR, SECRET_DIR, HISTORY_FILE, HISTORY_DIR, USAGE_FILE, MEMORIES_FILE, TEMP_MEM_FILE, TEMP_MEM_CHAT_FILE, BACKUPS_DIR, LEDGER_FILE, LEDGER_ADVANCE_FILE, ACTIVE_TX_FILE, PATHS_FILE, CONTEXT_FILE, PARSER_DIR;
|
|
62
|
+
var FLUXFLOW_DIR, SETTINGS_FILE, externalDir, DATA_DIR, LOGS_DIR, SECRET_DIR, HISTORY_FILE, HISTORY_DIR, USAGE_FILE_OLD, USAGE_FILE, MEMORIES_FILE, TEMP_MEM_FILE, TEMP_MEM_CHAT_FILE, BACKUPS_DIR, LEDGER_FILE, LEDGER_ADVANCE_FILE, ACTIVE_TX_FILE, PATHS_FILE, CONTEXT_FILE, PARSER_DIR;
|
|
62
63
|
var init_paths = __esm({
|
|
63
64
|
"src/utils/paths.js"() {
|
|
64
65
|
FLUXFLOW_DIR = path.join(os.homedir(), ".fluxflow");
|
|
@@ -96,7 +97,8 @@ var init_paths = __esm({
|
|
|
96
97
|
SECRET_DIR = path.join(DATA_DIR, "secret");
|
|
97
98
|
HISTORY_FILE = path.join(SECRET_DIR, "history.json");
|
|
98
99
|
HISTORY_DIR = path.join(SECRET_DIR, "history");
|
|
99
|
-
|
|
100
|
+
USAGE_FILE_OLD = path.join(FLUXFLOW_DIR, "usage.json");
|
|
101
|
+
USAGE_FILE = path.join(SECRET_DIR, "usage.json");
|
|
100
102
|
MEMORIES_FILE = path.join(SECRET_DIR, "memories.json");
|
|
101
103
|
TEMP_MEM_FILE = path.join(SECRET_DIR, "memory-temp.json");
|
|
102
104
|
TEMP_MEM_CHAT_FILE = path.join(SECRET_DIR, "temp-memory-chat.json");
|
|
@@ -780,6 +782,9 @@ var init_settings = __esm({
|
|
|
780
782
|
progressiveRendering: true,
|
|
781
783
|
showTPMEstimate: false,
|
|
782
784
|
subAgents: true,
|
|
785
|
+
CustomSubAgent: false,
|
|
786
|
+
SubAgentModel: "Default",
|
|
787
|
+
SubAgentProvider: "",
|
|
783
788
|
dynamicDirAwareness: false,
|
|
784
789
|
indentationTree: true
|
|
785
790
|
},
|
|
@@ -5675,7 +5680,7 @@ var init_ChatLayout = __esm({
|
|
|
5675
5680
|
return;
|
|
5676
5681
|
}
|
|
5677
5682
|
if (trimmed === "---" || trimmed === "***" || trimmed === "___") {
|
|
5678
|
-
result.push(/* @__PURE__ */ React4.createElement(Box3, { key: i, marginY:
|
|
5683
|
+
result.push(/* @__PURE__ */ React4.createElement(Box3, { key: i, marginY: 0, borderStyle: "single", borderTop: true, borderBottom: false, borderLeft: false, borderRight: false, width: "100%", borderColor: colors.borderMuted }));
|
|
5679
5684
|
return;
|
|
5680
5685
|
}
|
|
5681
5686
|
const headingMatch = trimmed.match(/^(#{1,6})\s+(.*)/);
|
|
@@ -5740,37 +5745,138 @@ var init_ChatLayout = __esm({
|
|
|
5740
5745
|
const displayPrefix = isRemoval ? "-" : isAddition ? "+" : " ";
|
|
5741
5746
|
const renderInlineDiff = () => {
|
|
5742
5747
|
if (isPureUnpairedBlock) {
|
|
5743
|
-
const blockColor = isRemoval ? colors.diffRemovalHighlightColor : colors.diffAdditionHighlightColor;
|
|
5744
5748
|
const textBgColor = isRemoval ? colors.diffRemovalHighlightBg : colors.diffAdditionHighlightBg;
|
|
5745
|
-
|
|
5746
|
-
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, blockColor, textBgColor))));
|
|
5749
|
+
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, renderHighlightedLine(wrapText(content, columns - 15), extension, void 0, textBgColor));
|
|
5747
5750
|
}
|
|
5748
5751
|
if (!(isRemoval || isAddition) || words.length === 0 || !hasInlineChange) {
|
|
5749
5752
|
const textColor = isRemoval ? colors.diffRemovalText : isAddition ? colors.diffAdditionText : colors.textMuted;
|
|
5750
5753
|
const textBgColor = void 0;
|
|
5751
|
-
|
|
5752
|
-
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, textColor, textBgColor))));
|
|
5754
|
+
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, renderHighlightedLine(wrapText(content, columns - 15), extension, textColor, textBgColor));
|
|
5753
5755
|
}
|
|
5754
|
-
|
|
5756
|
+
const maxLen = Math.max(10, columns - 15);
|
|
5757
|
+
const wrappedLines = wrapText(content, maxLen).split("\n");
|
|
5758
|
+
const validWords = [];
|
|
5759
|
+
words.forEach((part, idx) => {
|
|
5755
5760
|
const isWhitespace = /^\s+$/.test(part.value);
|
|
5756
5761
|
if (isRemoval) {
|
|
5757
5762
|
const isSurroundedByRemoval = words[idx - 1]?.removed || words[idx + 1]?.removed;
|
|
5758
5763
|
if (part.removed || isWhitespace && isSurroundedByRemoval) {
|
|
5759
|
-
|
|
5764
|
+
validWords.push({ text: part.value, isHighlight: true });
|
|
5765
|
+
} else if (!part.added) {
|
|
5766
|
+
validWords.push({ text: part.value, isHighlight: false });
|
|
5760
5767
|
}
|
|
5761
|
-
|
|
5762
|
-
return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: colors.diffRemovalText }, part.value);
|
|
5763
|
-
}
|
|
5764
|
-
if (isAddition) {
|
|
5768
|
+
} else if (isAddition) {
|
|
5765
5769
|
const isSurroundedByAddition = words[idx - 1]?.added || words[idx + 1]?.added;
|
|
5766
5770
|
if (part.added || isWhitespace && isSurroundedByAddition) {
|
|
5767
|
-
|
|
5771
|
+
validWords.push({ text: part.value, isHighlight: true });
|
|
5772
|
+
} else if (!part.removed) {
|
|
5773
|
+
validWords.push({ text: part.value, isHighlight: false });
|
|
5768
5774
|
}
|
|
5769
|
-
if (part.removed) return null;
|
|
5770
|
-
return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: colors.diffAdditionText }, part.value);
|
|
5771
5775
|
}
|
|
5772
|
-
|
|
5773
|
-
|
|
5776
|
+
});
|
|
5777
|
+
if (wrappedLines.length <= 1) {
|
|
5778
|
+
return /* @__PURE__ */ React4.createElement(Text4, { wrap: "wrap" }, validWords.map((part, idx) => {
|
|
5779
|
+
if (isRemoval) {
|
|
5780
|
+
if (part.isHighlight) {
|
|
5781
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, { key: idx }, renderHighlightedLine(part.text, extension, colors.diffRemovalHighlightColor, colors.diffRemovalHighlightBg));
|
|
5782
|
+
}
|
|
5783
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, { key: idx }, renderHighlightedLine(part.text, extension, colors.diffRemovalText));
|
|
5784
|
+
}
|
|
5785
|
+
if (isAddition) {
|
|
5786
|
+
if (part.isHighlight) {
|
|
5787
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, { key: idx }, renderHighlightedLine(part.text, extension, colors.diffAdditionHighlightColor, colors.diffAdditionHighlightBg));
|
|
5788
|
+
}
|
|
5789
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, { key: idx }, renderHighlightedLine(part.text, extension, colors.diffAdditionText));
|
|
5790
|
+
}
|
|
5791
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, { key: idx }, renderHighlightedLine(part.text, extension, colors.textMuted));
|
|
5792
|
+
}));
|
|
5793
|
+
}
|
|
5794
|
+
let wordIdx = 0;
|
|
5795
|
+
let charIdx = 0;
|
|
5796
|
+
const leadingSpaceMatch = content.match(/^(\s*)/);
|
|
5797
|
+
const indent = leadingSpaceMatch ? leadingSpaceMatch[1] : "";
|
|
5798
|
+
const cappedIndent = indent.substring(0, Math.min(indent.length, 8));
|
|
5799
|
+
const lineSpans = wrappedLines.map((wl, lineIdx) => {
|
|
5800
|
+
const spans = [];
|
|
5801
|
+
let lineTextToMatch = wl;
|
|
5802
|
+
if (lineIdx > 0 && cappedIndent && wl.startsWith(cappedIndent)) {
|
|
5803
|
+
const currentAvail = validWords[wordIdx] ? validWords[wordIdx].text.substring(charIdx) : "";
|
|
5804
|
+
if (!currentAvail.startsWith(cappedIndent)) {
|
|
5805
|
+
spans.push({ text: cappedIndent, isHighlight: false });
|
|
5806
|
+
lineTextToMatch = wl.substring(cappedIndent.length);
|
|
5807
|
+
}
|
|
5808
|
+
}
|
|
5809
|
+
let neededLength = lineTextToMatch.length;
|
|
5810
|
+
while (neededLength > 0 && wordIdx < validWords.length) {
|
|
5811
|
+
const vw = validWords[wordIdx];
|
|
5812
|
+
const avail = vw.text.length - charIdx;
|
|
5813
|
+
if (avail <= 0) {
|
|
5814
|
+
wordIdx++;
|
|
5815
|
+
charIdx = 0;
|
|
5816
|
+
continue;
|
|
5817
|
+
}
|
|
5818
|
+
const takeLen = Math.min(neededLength, avail);
|
|
5819
|
+
spans.push({
|
|
5820
|
+
text: vw.text.substring(charIdx, charIdx + takeLen),
|
|
5821
|
+
isHighlight: vw.isHighlight
|
|
5822
|
+
});
|
|
5823
|
+
charIdx += takeLen;
|
|
5824
|
+
neededLength -= takeLen;
|
|
5825
|
+
if (charIdx >= vw.text.length) {
|
|
5826
|
+
wordIdx++;
|
|
5827
|
+
charIdx = 0;
|
|
5828
|
+
}
|
|
5829
|
+
}
|
|
5830
|
+
while (wordIdx < validWords.length) {
|
|
5831
|
+
const vw = validWords[wordIdx];
|
|
5832
|
+
const rem = vw.text.substring(charIdx);
|
|
5833
|
+
if (/^\s+$/.test(rem)) {
|
|
5834
|
+
wordIdx++;
|
|
5835
|
+
charIdx = 0;
|
|
5836
|
+
} else if (rem.startsWith(" ") || rem.startsWith(" ")) {
|
|
5837
|
+
let skipCount = 0;
|
|
5838
|
+
while (skipCount < rem.length && (rem[skipCount] === " " || rem[skipCount] === " ")) {
|
|
5839
|
+
skipCount++;
|
|
5840
|
+
}
|
|
5841
|
+
charIdx += skipCount;
|
|
5842
|
+
if (charIdx >= vw.text.length) {
|
|
5843
|
+
wordIdx++;
|
|
5844
|
+
charIdx = 0;
|
|
5845
|
+
}
|
|
5846
|
+
break;
|
|
5847
|
+
} else {
|
|
5848
|
+
break;
|
|
5849
|
+
}
|
|
5850
|
+
}
|
|
5851
|
+
return spans;
|
|
5852
|
+
});
|
|
5853
|
+
if (wordIdx < validWords.length) {
|
|
5854
|
+
const lastSpans = lineSpans[lineSpans.length - 1];
|
|
5855
|
+
while (wordIdx < validWords.length) {
|
|
5856
|
+
const vw = validWords[wordIdx];
|
|
5857
|
+
lastSpans.push({
|
|
5858
|
+
text: vw.text.substring(charIdx),
|
|
5859
|
+
isHighlight: vw.isHighlight
|
|
5860
|
+
});
|
|
5861
|
+
wordIdx++;
|
|
5862
|
+
charIdx = 0;
|
|
5863
|
+
}
|
|
5864
|
+
}
|
|
5865
|
+
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, lineSpans.map((spans, lIdx) => /* @__PURE__ */ React4.createElement(Box3, { key: lIdx }, /* @__PURE__ */ React4.createElement(Text4, { wrap: "wrap" }, spans.map((part, sIdx) => {
|
|
5866
|
+
if (isRemoval) {
|
|
5867
|
+
if (part.isHighlight) {
|
|
5868
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, { key: sIdx }, renderHighlightedLine(part.text, extension, colors.diffRemovalHighlightColor, colors.diffRemovalHighlightBg));
|
|
5869
|
+
}
|
|
5870
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, { key: sIdx }, renderHighlightedLine(part.text, extension, colors.diffRemovalText));
|
|
5871
|
+
}
|
|
5872
|
+
if (isAddition) {
|
|
5873
|
+
if (part.isHighlight) {
|
|
5874
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, { key: sIdx }, renderHighlightedLine(part.text, extension, colors.diffAdditionHighlightColor, colors.diffAdditionHighlightBg));
|
|
5875
|
+
}
|
|
5876
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, { key: sIdx }, renderHighlightedLine(part.text, extension, colors.diffAdditionText));
|
|
5877
|
+
}
|
|
5878
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, { key: sIdx }, renderHighlightedLine(part.text, extension, colors.textMuted));
|
|
5879
|
+
})))));
|
|
5774
5880
|
};
|
|
5775
5881
|
return /* @__PURE__ */ React4.createElement(Box3, { backgroundColor: colors.codeBg, paddingX: 1, width: columns }, /* @__PURE__ */ React4.createElement(Box3, { width: 4, flexShrink: 0, justifyContent: "flex-end" }, /* @__PURE__ */ React4.createElement(Text4, { color: finalNumColor }, lineNum)), /* @__PURE__ */ React4.createElement(Box3, { width: 1, flexShrink: 0, marginLeft: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: finalPrefixColor }, displayPrefix)), /* @__PURE__ */ React4.createElement(Box3, { marginLeft: 1, backgroundColor: innerBgColor, flexGrow: 1 }, renderInlineDiff()));
|
|
5776
5882
|
});
|
|
@@ -6704,10 +6810,10 @@ var init_main_tools = __esm({
|
|
|
6704
6810
|
Tool calls: ONLY use [tool:functions.ToolName(args)]
|
|
6705
6811
|
**NO OTHER SYNTAX/MARKERS/BOUNDARY ALLOWED**
|
|
6706
6812
|
|
|
6707
|
-
**TOOL USAGE
|
|
6813
|
+
**CRITICAL TOOL USAGE RULES:**
|
|
6708
6814
|
- MAX 4 TOOL CALLS/TURN${mode === "Flux" ? " (Todo: 4+, Run: max 1 or 2 consecutive)" : ""}
|
|
6709
|
-
${mode === "Flux" ? '- **Escape quotes: \\" for code strings **\n- ** Literal escapes: Double - escape sequences(e.g., \\\\n) **\n- ** File structure: Real newlines for code formatting**\n-
|
|
6710
|
-
- COMMUNICATION
|
|
6815
|
+
${mode === "Flux" ? '- **Escape quotes: \\" for code strings **\n- ** Literal escapes: Double - escape sequences(e.g., \\\\n) **\n- ** File structure: Real newlines for code formatting**\n- SAME file, MULTIPLE edits? Use ONE PatchFile call with up to 15 blocks \u2190 **PRIORITY**\n- Tool denied? Use `Ask` immediately for user guidance \u2190 **MANDATORY**\n- Need specific text ? SearchKeyword > Guessing/ReadFile\n- Huge files ? SearchKeyword > Full Read\n- **Update Todos from realtime progress every turn when created**\n' : ""}
|
|
6816
|
+
- COMMUNICATION WITH USER -
|
|
6711
6817
|
- [tool:functions.Ask(question="...", optionA="option::description", ...MAX 4)]. Ambiguity: MUST for path divergence, security risk. Ask, don't finish/guess. Suggest best options; no preferences. Keep options short
|
|
6712
6818
|
|
|
6713
6819
|
- WEB TOOLS -
|
|
@@ -6716,13 +6822,12 @@ ${mode === "Flux" ? '- **Escape quotes: \\" for code strings **\n- ** Literal es
|
|
|
6716
6822
|
|
|
6717
6823
|
${mode === "Flux" ? `- WORKSPACE TOOLS (path = relative; FIRST ARGUMENT, path separator: '/') -
|
|
6718
6824
|
- [tool:functions.ReadFile(path="...", startLine="integer", endLine="integer")]. ${aiProvider !== "Google" ? `${isMultiModal ? `Supports images/docs` : ""}` : `Supports images/docs`}
|
|
6719
|
-
- [tool:functions.ReadFolder(path="...", recurse="integer
|
|
6720
|
-
- [tool:functions.
|
|
6721
|
-
- [tool:functions.PatchFile(path="...", allowMultiple="bool optional, default: false", replaceContent1="...", newContent1="...", ...MAX 15)]. Surgical patchs, TARGET SMALLEST LINES/SUB-STRINGS. allowMultiple: Replace all matches. Use replaceContent2/newContent2... for multi blocks. Verify DIFFs
|
|
6825
|
+
- [tool:functions.ReadFolder(path="...", recurse="integer 1-3 optional, default: 1")]. DIR Contents + File Size. Minimize recursion
|
|
6826
|
+
- [tool:functions.PatchFile(path="...", allowMultiple="bool optional, default: false", replaceContent1="...", newContent1="...", ...MAX 15)]. Surgical patchs, TARGET SMALLEST LINES. allowMultiple: Replace all matches ONLY WHEN SURE. Use replaceContent2/newContent2... for multi blocks. Verify DIFFs
|
|
6722
6827
|
- [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile > WriteFile
|
|
6723
|
-
- [tool:functions.SearchKeyword(keyword="...", path="optional,
|
|
6828
|
+
- [tool:functions.SearchKeyword(keyword="...", path="optional, dir/file/glob/regex", fuzzy="bool optional, default: false", regex="bool optional, default: auto")]. path limits search scope. Find definitions/logic without full reads. Locate relevant code
|
|
6724
6829
|
- [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? `WINDOWS POWERSHELL` : `WINDOWS CMD` : `BASH`} command. Destructive/Irreversible ops \u2192 Ask user
|
|
6725
|
-
- [tool:functions.Todo(method="create/append/get", tasks=[ARRAY OF STRINGS], markDone=[ARRAY OF TASKS])]. Task list, no Markdown in arrays. Analyze request: if long multi-task, break it down & create Todos BEFORE starting. \`tasks\` & \`markDone\` optional with \`get\`. Use \`get + markDone\` to complete tasks
|
|
6830
|
+
- [tool:functions.Todo(method="create/append/get", tasks=[ARRAY OF STRINGS], markDone=[ARRAY OF TASKS])]. Task list, no Markdown in arrays. Analyze request: ONLY if long multi-task, break it down & create Todos BEFORE starting. \`tasks\` & \`markDone\` optional with \`get\`. Use \`get + markDone\` to complete tasks. **UPDATE EVERY TURN WHEN CREATED**${enableSubAgents ? '\n- [tool:functions.Await(time="integer 15-180")]. For waiting without exiting agent loop' : ""}
|
|
6726
6831
|
${_cachedAdvanceRollback ? `
|
|
6727
6832
|
- EMERGENCY SAFETY TOOLS -
|
|
6728
6833
|
Info: \`initial\` = user prompt for current task. Revert \`id\` = turn BEFORE the disaster tool (e.g. disaster:\`turn_3\` \u2192 revert:\`turn_2\`). Reason explicitly
|
|
@@ -6732,10 +6837,10 @@ Use ONLY for catastrophic/codebase corruption. Before ending loop, verify no cat
|
|
|
6732
6837
|
- SUB AGENT TOOLS -
|
|
6733
6838
|
**PROACTIVE sub-agent use HIGHLY RECOMMENDED. Prefer for any task with even slight benefit, no user nudge needed**
|
|
6734
6839
|
Invocations:
|
|
6735
|
-
- Invoke (async/background, \u22647 parallel). Parallelize long tasks. NEVER repeat while active
|
|
6840
|
+
- Invoke (async/background, \u22647 parallel). Parallelize long tasks. NEVER repeat while active, meantime, do your OWN work
|
|
6736
6841
|
- InvokeSync (sync/blocking). Sequential, repetitive or delegated tasks. Saves tokens/cost
|
|
6737
6842
|
- [agent:generalist.InvokeSync/Invoke(title="...", task="...")]. Task must be detailed: exact file paths, imports/exports, dependencies & folder structure
|
|
6738
|
-
- [agent:generalist.GetProgress(id="...")].
|
|
6843
|
+
- [agent:generalist.GetProgress(id="...")]. Poll \`getProgress\` sparingly (exp backoff Await); **NO IMMEDIATE FIRST POLL**
|
|
6739
6844
|
- [agent:generalist.Cancel(id="...")]. Cancel async task ONLY if stalled (2m+) or clearly incorrect` : ""}`.trim() : `- CREATIVE TOOLS (path = relative to CWD & WILL BE FIRST ARGUMENT, path separator: '/') -
|
|
6740
6845
|
- [tool:functions.WritePDF(path="...", content="...", orientation="...")]. PROACTIVE A4 PAGE BREAKS MUST IN CSS. HTML/CSS for PREMIUM layout, stable margins & headers/footers, NO WATERMARKS
|
|
6741
6846
|
- [tool:functions.WriteDoc(path="...", content="...")]. A4 Word document, NO WATERMARKS, stable margins & headers/footers
|
|
@@ -7448,6 +7553,104 @@ function SettingsMenu({
|
|
|
7448
7553
|
const [isSelectingTheme, setIsSelectingTheme] = useState6(initialSelectingTheme);
|
|
7449
7554
|
const [themeIndex, setThemeIndex] = useState6(defaultIdx >= 0 ? defaultIdx : 0);
|
|
7450
7555
|
const [initialTheme, setInitialTheme] = useState6(systemSettings.theme || "Dark");
|
|
7556
|
+
const [isSelectingSubAgentModel, setIsSelectingSubAgentModel] = useState6(false);
|
|
7557
|
+
const [subAgentModelIndex, setSubAgentModelIndex] = useState6(0);
|
|
7558
|
+
const [subAgentScrollOffset, setSubAgentScrollOffset] = useState6(0);
|
|
7559
|
+
const [subAgentSearchQuery, setSubAgentSearchQuery] = useState6("");
|
|
7560
|
+
const [subAgentFocusMode, setSubAgentFocusMode] = useState6("list");
|
|
7561
|
+
const [activeProviderKeys, setActiveProviderKeys] = useState6({});
|
|
7562
|
+
useEffect5(() => {
|
|
7563
|
+
const checkKeys = async () => {
|
|
7564
|
+
const providers = ["Google", "DeepSeek", "OpenRouter", "NVIDIA", "Mistral"];
|
|
7565
|
+
const keyMap = {};
|
|
7566
|
+
for (const p of providers) {
|
|
7567
|
+
try {
|
|
7568
|
+
const k = await getProviderAPIKey(p);
|
|
7569
|
+
if (k) keyMap[p] = true;
|
|
7570
|
+
} catch (e) {
|
|
7571
|
+
}
|
|
7572
|
+
}
|
|
7573
|
+
setActiveProviderKeys(keyMap);
|
|
7574
|
+
};
|
|
7575
|
+
checkKeys();
|
|
7576
|
+
}, []);
|
|
7577
|
+
const allSubAgentItems = React7.useMemo(() => {
|
|
7578
|
+
const ALL_PROVIDERS = ["Google", "DeepSeek", "OpenRouter", "NVIDIA", "Mistral"];
|
|
7579
|
+
const hasEnv = !!(process.env.SUBAGENT_MODEL && process.env.SUBAGENT_MODEL.trim());
|
|
7580
|
+
const envLabel = hasEnv ? `ENV (${process.env.SUBAGENT_MODEL.trim()})` : "ENV";
|
|
7581
|
+
const items = [
|
|
7582
|
+
{ label: "Default (use the current model)", value: "Default", isHeader: false },
|
|
7583
|
+
{ label: envLabel, value: "ENV", isHeader: false }
|
|
7584
|
+
];
|
|
7585
|
+
const activeTier = quotas?.providerTiers?.[aiProvider] || apiTier || "Free";
|
|
7586
|
+
const currentModels = getModels(aiProvider, activeTier) || [];
|
|
7587
|
+
if (currentModels.length > 0) {
|
|
7588
|
+
items.push({ label: `\u2500\u2500 ${aiProvider.toUpperCase()}${activeTier !== "Free" ? ` (${activeTier})` : ""} \u2500\u2500`, isHeader: true });
|
|
7589
|
+
currentModels.forEach((m) => {
|
|
7590
|
+
const name = typeof m === "string" ? m : m.cmd || m.name || m.id || String(m);
|
|
7591
|
+
if (name && !name.trim().startsWith("---") && !name.startsWith("\n---")) {
|
|
7592
|
+
items.push({ label: name, value: name, isHeader: false, provider: aiProvider });
|
|
7593
|
+
}
|
|
7594
|
+
});
|
|
7595
|
+
}
|
|
7596
|
+
for (const p of ALL_PROVIDERS) {
|
|
7597
|
+
if (p === aiProvider) continue;
|
|
7598
|
+
if (activeProviderKeys[p]) {
|
|
7599
|
+
const tier = quotas?.providerTiers?.[p] || "Free";
|
|
7600
|
+
const models = getModels(p, tier) || [];
|
|
7601
|
+
if (models.length > 0) {
|
|
7602
|
+
items.push({ label: `\u2500\u2500 ${p.toUpperCase()}${tier !== "Free" ? ` (${tier})` : ""} \u2500\u2500`, isHeader: true });
|
|
7603
|
+
models.forEach((m) => {
|
|
7604
|
+
const name = typeof m === "string" ? m : m.cmd || m.name || m.id || String(m);
|
|
7605
|
+
if (name && !name.trim().startsWith("---") && !name.startsWith("\n---")) {
|
|
7606
|
+
items.push({ label: name, value: name, isHeader: false, provider: p });
|
|
7607
|
+
}
|
|
7608
|
+
});
|
|
7609
|
+
}
|
|
7610
|
+
}
|
|
7611
|
+
}
|
|
7612
|
+
return items;
|
|
7613
|
+
}, [aiProvider, apiTier, quotas, activeProviderKeys]);
|
|
7614
|
+
const availableModels = React7.useMemo(() => {
|
|
7615
|
+
if (!subAgentSearchQuery.trim()) return allSubAgentItems;
|
|
7616
|
+
const q = subAgentSearchQuery.trim().toLowerCase();
|
|
7617
|
+
const filtered = [];
|
|
7618
|
+
let currentHeader = null;
|
|
7619
|
+
for (const item of allSubAgentItems) {
|
|
7620
|
+
if (item.isHeader) {
|
|
7621
|
+
currentHeader = item;
|
|
7622
|
+
} else {
|
|
7623
|
+
const matches = item.label.toLowerCase().includes(q) || item.value && item.value.toLowerCase().includes(q);
|
|
7624
|
+
if (matches) {
|
|
7625
|
+
if (currentHeader && !filtered.includes(currentHeader)) {
|
|
7626
|
+
filtered.push(currentHeader);
|
|
7627
|
+
}
|
|
7628
|
+
filtered.push(item);
|
|
7629
|
+
}
|
|
7630
|
+
}
|
|
7631
|
+
}
|
|
7632
|
+
return filtered;
|
|
7633
|
+
}, [allSubAgentItems, subAgentSearchQuery]);
|
|
7634
|
+
useEffect5(() => {
|
|
7635
|
+
if (isSelectingSubAgentModel) {
|
|
7636
|
+
let firstValid = availableModels.findIndex((item) => !item.isHeader);
|
|
7637
|
+
setSubAgentModelIndex(firstValid >= 0 ? firstValid : 0);
|
|
7638
|
+
setSubAgentScrollOffset(0);
|
|
7639
|
+
}
|
|
7640
|
+
}, [subAgentSearchQuery]);
|
|
7641
|
+
useEffect5(() => {
|
|
7642
|
+
if (isSelectingSubAgentModel) {
|
|
7643
|
+
if (availableModels.length === 0) {
|
|
7644
|
+
setSubAgentModelIndex(0);
|
|
7645
|
+
setSubAgentScrollOffset(0);
|
|
7646
|
+
return;
|
|
7647
|
+
}
|
|
7648
|
+
if (subAgentModelIndex >= availableModels.length || availableModels[subAgentModelIndex]?.isHeader) {
|
|
7649
|
+
let firstValid = availableModels.findIndex((item) => !item.isHeader);
|
|
7650
|
+
setSubAgentModelIndex(firstValid >= 0 ? firstValid : 0);
|
|
7651
|
+
}
|
|
7652
|
+
}
|
|
7653
|
+
}, [availableModels, isSelectingSubAgentModel]);
|
|
7451
7654
|
const [currentMemory, setCurrentMemory] = useState6(0);
|
|
7452
7655
|
const [maxMemory, setMaxMemory] = useState6(0);
|
|
7453
7656
|
const [memoryUnit, setMemoryUnit] = useState6("MB");
|
|
@@ -7512,10 +7715,11 @@ function SettingsMenu({
|
|
|
7512
7715
|
case "other":
|
|
7513
7716
|
return [
|
|
7514
7717
|
{ label: "Sub-Agents", value: "subAgents", status: systemSettings.subAgents !== false ? "ON" : "OFF" },
|
|
7718
|
+
{ label: "Sub-Agent Model", value: "subAgentModel", status: systemSettings.CustomSubAgent && systemSettings.SubAgentModel ? systemSettings.SubAgentModel : "Default" },
|
|
7515
7719
|
{ label: "Preserve Thinking", value: "preserveThinking", status: systemSettings.preserveThinking !== false ? "ON" : "OFF" },
|
|
7516
7720
|
{ label: "Dynamic Directory Awareness", value: "dynamicDirAwareness", status: systemSettings.dynamicDirAwareness ? "ON" : "OFF" },
|
|
7517
|
-
{ label: "Directory Tree Design", value: "indentationTree", status: systemSettings.indentationTree !== false ? "Modern" : "Classic (deprecated)" }
|
|
7518
|
-
{ label:
|
|
7721
|
+
{ label: "Directory Tree Design", value: "indentationTree", status: systemSettings.indentationTree !== false ? "Modern" : "Classic (deprecated)" }
|
|
7722
|
+
// { label: 'Download Language Parsers', value: 'parserDownload', status: 'ACTION' } // Dont remove this comment
|
|
7519
7723
|
];
|
|
7520
7724
|
default:
|
|
7521
7725
|
return [];
|
|
@@ -7524,6 +7728,69 @@ function SettingsMenu({
|
|
|
7524
7728
|
const currentCatId = CATEGORIES[selectedCategoryIndex].id;
|
|
7525
7729
|
const currentItems = getCategoryItems(currentCatId);
|
|
7526
7730
|
useInput3((input, key) => {
|
|
7731
|
+
if (isSelectingSubAgentModel) {
|
|
7732
|
+
if (key.tab) {
|
|
7733
|
+
setSubAgentFocusMode((prev) => prev === "search" ? "list" : "search");
|
|
7734
|
+
return;
|
|
7735
|
+
}
|
|
7736
|
+
if (subAgentFocusMode === "search") {
|
|
7737
|
+
if (key.escape) {
|
|
7738
|
+
setIsSelectingSubAgentModel(false);
|
|
7739
|
+
} else if (key.downArrow || key.return) {
|
|
7740
|
+
setSubAgentFocusMode("list");
|
|
7741
|
+
} else if (key.backspace || key.delete) {
|
|
7742
|
+
setSubAgentSearchQuery((q) => q.slice(0, -1));
|
|
7743
|
+
} else if (input && !key.ctrl && !key.meta && input.length === 1) {
|
|
7744
|
+
setSubAgentSearchQuery((q) => q + input);
|
|
7745
|
+
}
|
|
7746
|
+
return;
|
|
7747
|
+
}
|
|
7748
|
+
if (key.upArrow) {
|
|
7749
|
+
setSubAgentModelIndex((prev) => {
|
|
7750
|
+
if (availableModels.length === 0) return 0;
|
|
7751
|
+
let next = (prev - 1 + availableModels.length) % availableModels.length;
|
|
7752
|
+
let count = 0;
|
|
7753
|
+
while (availableModels[next]?.isHeader && count < availableModels.length) {
|
|
7754
|
+
next = (next - 1 + availableModels.length) % availableModels.length;
|
|
7755
|
+
count++;
|
|
7756
|
+
}
|
|
7757
|
+
return next;
|
|
7758
|
+
});
|
|
7759
|
+
} else if (key.downArrow) {
|
|
7760
|
+
setSubAgentModelIndex((prev) => {
|
|
7761
|
+
if (availableModels.length === 0) return 0;
|
|
7762
|
+
let next = (prev + 1) % availableModels.length;
|
|
7763
|
+
let count = 0;
|
|
7764
|
+
while (availableModels[next]?.isHeader && count < availableModels.length) {
|
|
7765
|
+
next = (next + 1) % availableModels.length;
|
|
7766
|
+
count++;
|
|
7767
|
+
}
|
|
7768
|
+
return next;
|
|
7769
|
+
});
|
|
7770
|
+
} else if (key.return) {
|
|
7771
|
+
const selectedOpt = availableModels[subAgentModelIndex];
|
|
7772
|
+
if (selectedOpt && !selectedOpt.isHeader) {
|
|
7773
|
+
setSystemSettings((s) => {
|
|
7774
|
+
const isDefault = selectedOpt.value === "Default";
|
|
7775
|
+
const newSysSettings = {
|
|
7776
|
+
...s,
|
|
7777
|
+
CustomSubAgent: !isDefault,
|
|
7778
|
+
SubAgentModel: selectedOpt.value,
|
|
7779
|
+
SubAgentProvider: isDefault ? "" : selectedOpt.provider || ""
|
|
7780
|
+
};
|
|
7781
|
+
saveSettings2({ systemSettings: newSysSettings, apiTier, quotas });
|
|
7782
|
+
return newSysSettings;
|
|
7783
|
+
});
|
|
7784
|
+
setIsSelectingSubAgentModel(false);
|
|
7785
|
+
}
|
|
7786
|
+
} else if (key.escape) {
|
|
7787
|
+
setIsSelectingSubAgentModel(false);
|
|
7788
|
+
} else if (input && !key.ctrl && !key.meta && input.length === 1) {
|
|
7789
|
+
setSubAgentSearchQuery((q) => q + input);
|
|
7790
|
+
setSubAgentFocusMode("search");
|
|
7791
|
+
}
|
|
7792
|
+
return;
|
|
7793
|
+
}
|
|
7527
7794
|
if (isSelectingTheme) {
|
|
7528
7795
|
if (key.upArrow) {
|
|
7529
7796
|
const nextIdx = (themeIndex - 1 + themeOptions.length) % themeOptions.length;
|
|
@@ -7711,6 +7978,11 @@ function SettingsMenu({
|
|
|
7711
7978
|
saveSettings2({ systemSettings: newSysSettings, apiTier, quotas });
|
|
7712
7979
|
return newSysSettings;
|
|
7713
7980
|
});
|
|
7981
|
+
} else if (item.value === "subAgentModel") {
|
|
7982
|
+
const currentSubAgentModel = systemSettings.CustomSubAgent && systemSettings.SubAgentModel ? systemSettings.SubAgentModel : "Default";
|
|
7983
|
+
const curIdx = availableModels.findIndex((m) => m.value === currentSubAgentModel);
|
|
7984
|
+
setSubAgentModelIndex(curIdx >= 0 ? curIdx : 0);
|
|
7985
|
+
setIsSelectingSubAgentModel(true);
|
|
7714
7986
|
} else if (item.value === "preserveThinking") {
|
|
7715
7987
|
setSystemSettings((s) => {
|
|
7716
7988
|
const newSysSettings = { ...s, preserveThinking: s.preserveThinking === false ? true : false };
|
|
@@ -7754,6 +8026,42 @@ function SettingsMenu({
|
|
|
7754
8026
|
}
|
|
7755
8027
|
};
|
|
7756
8028
|
const colors = getThemeColors(systemSettings.theme);
|
|
8029
|
+
if (isSelectingSubAgentModel) {
|
|
8030
|
+
const currentSavedModel = systemSettings.CustomSubAgent && systemSettings.SubAgentModel ? systemSettings.SubAgentModel : "Default";
|
|
8031
|
+
const VISIBLE_COUNT = 15;
|
|
8032
|
+
let startIndex = subAgentScrollOffset;
|
|
8033
|
+
if (subAgentModelIndex < startIndex) {
|
|
8034
|
+
startIndex = subAgentModelIndex;
|
|
8035
|
+
} else if (subAgentModelIndex >= startIndex + VISIBLE_COUNT) {
|
|
8036
|
+
startIndex = subAgentModelIndex - VISIBLE_COUNT + 1;
|
|
8037
|
+
}
|
|
8038
|
+
startIndex = Math.max(0, Math.min(startIndex, Math.max(0, availableModels.length - VISIBLE_COUNT)));
|
|
8039
|
+
if (startIndex !== subAgentScrollOffset) {
|
|
8040
|
+
setSubAgentScrollOffset(startIndex);
|
|
8041
|
+
}
|
|
8042
|
+
const visibleItems = availableModels.slice(startIndex, startIndex + VISIBLE_COUNT);
|
|
8043
|
+
return /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: colors.border, padding: 1, width: "100%", minHeight: 32 }, /* @__PURE__ */ React7.createElement(Box6, { marginBottom: 1, flexDirection: "row", justifyContent: "space-between" }, /* @__PURE__ */ React7.createElement(Text7, { color: colors.text, bold: true, underline: true }, "Select Sub-Agent Model:"), availableModels.length > 0 && /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, subAgentModelIndex + 1, "/", availableModels.length)), /* @__PURE__ */ React7.createElement(
|
|
8044
|
+
Box6,
|
|
8045
|
+
{
|
|
8046
|
+
borderStyle: "single",
|
|
8047
|
+
borderColor: subAgentFocusMode === "search" ? colors.primary || "cyan" : "gray",
|
|
8048
|
+
paddingX: 1,
|
|
8049
|
+
marginBottom: 1
|
|
8050
|
+
},
|
|
8051
|
+
/* @__PURE__ */ React7.createElement(Text7, { color: subAgentFocusMode === "search" ? colors.primary || "cyan" : "gray", bold: true }, "\u{1F50D} Search: ", " "),
|
|
8052
|
+
/* @__PURE__ */ React7.createElement(Text7, { color: colors.text }, subAgentSearchQuery),
|
|
8053
|
+
subAgentFocusMode === "search" && /* @__PURE__ */ React7.createElement(Text7, { color: colors.primary || "cyan" }, "\u2588"),
|
|
8054
|
+
!subAgentSearchQuery && subAgentFocusMode !== "search" && /* @__PURE__ */ React7.createElement(Text7, { color: "gray", italic: true }, "(Press TAB or type to filter models...)")
|
|
8055
|
+
), /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", flexGrow: 1, height: VISIBLE_COUNT }, visibleItems.length > 0 ? visibleItems.map((opt, idx) => {
|
|
8056
|
+
const actualIndex = startIndex + idx;
|
|
8057
|
+
if (opt.isHeader) {
|
|
8058
|
+
return /* @__PURE__ */ React7.createElement(Box6, { key: `hdr-${actualIndex}`, paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray", bold: true, underline: true }, opt.label));
|
|
8059
|
+
}
|
|
8060
|
+
const isSelected = subAgentModelIndex === actualIndex && subAgentFocusMode === "list";
|
|
8061
|
+
const isSaved = currentSavedModel === opt.value;
|
|
8062
|
+
return /* @__PURE__ */ React7.createElement(Box6, { key: `item-${opt.value}-${actualIndex}`, paddingX: 1, backgroundColor: isSelected ? colors.highlightBg : void 0 }, /* @__PURE__ */ React7.createElement(Text7, { color: isSelected ? colors.text : colors.textDim, bold: isSelected }, isSelected ? "\u276F " : " ", opt.label, isSaved ? /* @__PURE__ */ React7.createElement(Text7, { color: colors.primary || "cyan", italic: true }, " (active)") : ""));
|
|
8063
|
+
}) : /* @__PURE__ */ React7.createElement(Box6, { paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray", italic: true }, 'No models matching "', subAgentSearchQuery, '"'))), /* @__PURE__ */ React7.createElement(Box6, { paddingX: 1, marginTop: 1, flexDirection: "row", justifyContent: "space-between" }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray", italic: true }, "TAB to switch search/list \u2022 \u25B2\u25BC Navigate \u2022 ENTER to Select \u2022 ESC to Cancel"), /* @__PURE__ */ React7.createElement(Text7, { color: subAgentFocusMode === "search" ? colors.primary || "cyan" : "gray", bold: true }, "[", subAgentFocusMode.toUpperCase(), " MODE]")));
|
|
8064
|
+
}
|
|
7757
8065
|
if (isSelectingTheme) {
|
|
7758
8066
|
const previewThemeName = themeOptions[themeIndex];
|
|
7759
8067
|
const previewColors = getThemeColors(previewThemeName);
|
|
@@ -7857,6 +8165,8 @@ var init_SettingsMenu = __esm({
|
|
|
7857
8165
|
async "src/components/SettingsMenu.jsx"() {
|
|
7858
8166
|
await init_exec_command();
|
|
7859
8167
|
init_theme();
|
|
8168
|
+
init_model_config();
|
|
8169
|
+
init_secrets();
|
|
7860
8170
|
themeOptions = [...Object.keys(THEMES), "Mystery"];
|
|
7861
8171
|
CATEGORIES = [
|
|
7862
8172
|
{ id: "appearance", label: "Appearance", desc: "Customize UI theme & rendering options" },
|
|
@@ -8254,12 +8564,14 @@ ${forcedReasoning || thinkingLevel !== "Fast" && (aiProvider === "Mistral" || th
|
|
|
8254
8564
|
- Use <think> ... </think> for reasoning before responding, even with simple queries/greetings
|
|
8255
8565
|
` : ""}` : `${thinkingConfig}
|
|
8256
8566
|
`}
|
|
8567
|
+
- **USE PROVIDED DIRECTORY STRUCTURE FOR FILES/PATHS**
|
|
8568
|
+
- RELATIVE TIME REFERENCE eg. few mins ago
|
|
8569
|
+
|
|
8257
8570
|
${TOOL_PROTOCOL(mode, osDetected, aiProvider.toLowerCase() === "deepseek" ? false : isMultiModal, aiProvider, systemSettings?.advanceRollback, systemSettings?.subAgents !== false)}
|
|
8258
8571
|
${projectContextBlock}${isMemoryEnabled ? `
|
|
8259
8572
|
-- MEMORY RULES --
|
|
8260
|
-
- Subtly Personalize with RELEVENT CONTEXTUAL MEMORIES. Auto Saves
|
|
8261
|
-
|
|
8262
|
-
|
|
8573
|
+
- Subtly Personalize with RELEVENT CONTEXTUAL MEMORIES. Auto Saves
|
|
8574
|
+
` : ""}
|
|
8263
8575
|
-- SECURITY RULES --
|
|
8264
8576
|
- Sensitive files? Ask before Read${isSystemDir ? "\n- PROTECTED DIRECTORY" : ""}
|
|
8265
8577
|
|
|
@@ -8877,24 +9189,11 @@ var init_history = __esm({
|
|
|
8877
9189
|
// src/utils/usage.js
|
|
8878
9190
|
import fs10 from "fs-extra";
|
|
8879
9191
|
import path9 from "path";
|
|
8880
|
-
|
|
8881
|
-
var getLocalBackupPath, BACKUP_FILE, generateSaveId, cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, purgeOldHistory, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, getMonthlyUsage, incrementUsage, runtimeSession, addToUsage, getCustomPeriodUsage, checkQuota, getImageQuotaBuckets, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
|
|
9192
|
+
var generateSaveId, cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, purgeOldHistory, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, getMonthlyUsage, incrementUsage, runtimeSession, addToUsage, getCustomPeriodUsage, checkQuota, getImageQuotaBuckets, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
|
|
8882
9193
|
var init_usage = __esm({
|
|
8883
9194
|
"src/utils/usage.js"() {
|
|
8884
9195
|
init_paths();
|
|
8885
9196
|
init_crypto();
|
|
8886
|
-
getLocalBackupPath = () => {
|
|
8887
|
-
if (process.platform === "win32") {
|
|
8888
|
-
const localAppData = process.env.LOCALAPPDATA || path9.join(os3.homedir(), "AppData", "Local");
|
|
8889
|
-
return path9.join(localAppData, "FxFl", "backups", "backup.json");
|
|
8890
|
-
}
|
|
8891
|
-
if (process.platform === "darwin") {
|
|
8892
|
-
return path9.join(os3.homedir(), "Library", "Application Support", "FxFl", "backups", "backup.json");
|
|
8893
|
-
}
|
|
8894
|
-
const xdgDataHome = process.env.XDG_DATA_HOME || path9.join(os3.homedir(), ".local", "share");
|
|
8895
|
-
return path9.join(xdgDataHome, "fxfl", "backups", "backup.json");
|
|
8896
|
-
};
|
|
8897
|
-
BACKUP_FILE = getLocalBackupPath();
|
|
8898
9197
|
generateSaveId = () => Math.random().toString(36).substring(2) + Date.now().toString(36);
|
|
8899
9198
|
cachedUsage = null;
|
|
8900
9199
|
writeTimeout = null;
|
|
@@ -8929,10 +9228,16 @@ var init_usage = __esm({
|
|
|
8929
9228
|
return purged;
|
|
8930
9229
|
};
|
|
8931
9230
|
loadUsageFromFile = async () => {
|
|
8932
|
-
const
|
|
9231
|
+
const today2 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
9232
|
+
try {
|
|
9233
|
+
if (!await fs10.exists(USAGE_FILE) && await fs10.exists(USAGE_FILE_OLD)) {
|
|
9234
|
+
await fs10.ensureDir(path9.dirname(USAGE_FILE));
|
|
9235
|
+
await fs10.move(USAGE_FILE_OLD, USAGE_FILE);
|
|
9236
|
+
}
|
|
9237
|
+
} catch (err) {
|
|
9238
|
+
}
|
|
8933
9239
|
const tempFile = USAGE_FILE + ".tmp";
|
|
8934
9240
|
let primaryData = null;
|
|
8935
|
-
let backupData = null;
|
|
8936
9241
|
try {
|
|
8937
9242
|
if (await fs10.exists(tempFile)) {
|
|
8938
9243
|
const rawContent = (await fs10.readFile(tempFile, "utf8")).trim();
|
|
@@ -8974,44 +9279,7 @@ var init_usage = __esm({
|
|
|
8974
9279
|
} catch (err) {
|
|
8975
9280
|
}
|
|
8976
9281
|
}
|
|
8977
|
-
|
|
8978
|
-
if (await fs10.exists(BACKUP_FILE)) {
|
|
8979
|
-
const rawContent = (await fs10.readFile(BACKUP_FILE, "utf8")).trim();
|
|
8980
|
-
if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
|
|
8981
|
-
backupData = JSON.parse(rawContent);
|
|
8982
|
-
} else {
|
|
8983
|
-
backupData = JSON.parse(decryptAes(rawContent));
|
|
8984
|
-
}
|
|
8985
|
-
}
|
|
8986
|
-
} catch (err) {
|
|
8987
|
-
}
|
|
8988
|
-
let resolvedData = null;
|
|
8989
|
-
if (primaryData && backupData) {
|
|
8990
|
-
if (primaryData.saveId !== backupData.saveId) {
|
|
8991
|
-
resolvedData = primaryData;
|
|
8992
|
-
try {
|
|
8993
|
-
await fs10.ensureDir(path9.dirname(BACKUP_FILE));
|
|
8994
|
-
await fs10.copy(USAGE_FILE, BACKUP_FILE);
|
|
8995
|
-
} catch (e) {
|
|
8996
|
-
}
|
|
8997
|
-
} else {
|
|
8998
|
-
resolvedData = primaryData;
|
|
8999
|
-
}
|
|
9000
|
-
} else if (primaryData && !backupData) {
|
|
9001
|
-
resolvedData = primaryData;
|
|
9002
|
-
try {
|
|
9003
|
-
await fs10.ensureDir(path9.dirname(BACKUP_FILE));
|
|
9004
|
-
await fs10.copy(USAGE_FILE, BACKUP_FILE);
|
|
9005
|
-
} catch (e) {
|
|
9006
|
-
}
|
|
9007
|
-
} else if (!primaryData && backupData) {
|
|
9008
|
-
resolvedData = backupData;
|
|
9009
|
-
try {
|
|
9010
|
-
await fs10.ensureDir(path9.dirname(USAGE_FILE));
|
|
9011
|
-
await fs10.copy(BACKUP_FILE, USAGE_FILE);
|
|
9012
|
-
} catch (e) {
|
|
9013
|
-
}
|
|
9014
|
-
}
|
|
9282
|
+
let resolvedData = primaryData;
|
|
9015
9283
|
if (resolvedData) {
|
|
9016
9284
|
const stats = resolvedData.stats || { ...defaultStats };
|
|
9017
9285
|
const mergedStats = { ...defaultStats, ...stats };
|
|
@@ -9019,28 +9287,32 @@ var init_usage = __esm({
|
|
|
9019
9287
|
mergedStats.imageCalls = [];
|
|
9020
9288
|
}
|
|
9021
9289
|
const history = resolvedData.history || {};
|
|
9022
|
-
|
|
9290
|
+
const purgedHistory = purgeOldHistory(history, today2);
|
|
9291
|
+
if (Object.keys(history).length !== Object.keys(purgedHistory).length) {
|
|
9292
|
+
isDirty = true;
|
|
9293
|
+
}
|
|
9294
|
+
if (resolvedData.date === today2) {
|
|
9023
9295
|
return {
|
|
9024
9296
|
...resolvedData,
|
|
9025
9297
|
stats: mergedStats,
|
|
9026
|
-
history
|
|
9298
|
+
history: purgedHistory
|
|
9027
9299
|
};
|
|
9028
9300
|
} else {
|
|
9029
9301
|
const oldDate = resolvedData.date;
|
|
9030
9302
|
const oldStats = mergedStats;
|
|
9031
|
-
const updatedHistory = { ...
|
|
9303
|
+
const updatedHistory = { ...purgedHistory };
|
|
9032
9304
|
if (oldDate) {
|
|
9033
9305
|
updatedHistory[oldDate] = oldStats;
|
|
9034
9306
|
}
|
|
9035
9307
|
return {
|
|
9036
|
-
date:
|
|
9308
|
+
date: today2,
|
|
9037
9309
|
stats: { ...defaultStats },
|
|
9038
|
-
history: purgeOldHistory(updatedHistory,
|
|
9310
|
+
history: purgeOldHistory(updatedHistory, today2)
|
|
9039
9311
|
};
|
|
9040
9312
|
}
|
|
9041
9313
|
}
|
|
9042
9314
|
return {
|
|
9043
|
-
date:
|
|
9315
|
+
date: today2,
|
|
9044
9316
|
stats: { ...defaultStats },
|
|
9045
9317
|
history: {}
|
|
9046
9318
|
};
|
|
@@ -9123,7 +9395,10 @@ var init_usage = __esm({
|
|
|
9123
9395
|
mergedHistory[dateKey] = diskData.history[dateKey];
|
|
9124
9396
|
}
|
|
9125
9397
|
}
|
|
9126
|
-
cachedUsage.history = mergedHistory;
|
|
9398
|
+
cachedUsage.history = purgeOldHistory(mergedHistory, cachedUsage.date || today);
|
|
9399
|
+
} else if (cachedUsage && cachedUsage.history) {
|
|
9400
|
+
const today2 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
9401
|
+
cachedUsage.history = purgeOldHistory(cachedUsage.history, today2);
|
|
9127
9402
|
}
|
|
9128
9403
|
cachedUsage.saveId = generateSaveId();
|
|
9129
9404
|
const tempFile = USAGE_FILE + ".tmp";
|
|
@@ -9133,11 +9408,6 @@ var init_usage = __esm({
|
|
|
9133
9408
|
await fs10.fsync(fd);
|
|
9134
9409
|
await fs10.close(fd);
|
|
9135
9410
|
await fs10.rename(tempFile, USAGE_FILE);
|
|
9136
|
-
try {
|
|
9137
|
-
await fs10.ensureDir(path9.dirname(BACKUP_FILE));
|
|
9138
|
-
await fs10.copy(USAGE_FILE, BACKUP_FILE);
|
|
9139
|
-
} catch (backupErr) {
|
|
9140
|
-
}
|
|
9141
9411
|
isDirty = false;
|
|
9142
9412
|
lastWriteTime = Date.now();
|
|
9143
9413
|
} catch (e) {
|
|
@@ -9156,6 +9426,9 @@ var init_usage = __esm({
|
|
|
9156
9426
|
};
|
|
9157
9427
|
initUsage = async () => {
|
|
9158
9428
|
cachedUsage = await loadUsageFromFile();
|
|
9429
|
+
if (isDirty) {
|
|
9430
|
+
queueFlush();
|
|
9431
|
+
}
|
|
9159
9432
|
};
|
|
9160
9433
|
forceFlushUsage = async () => {
|
|
9161
9434
|
if (writeTimeout) {
|
|
@@ -9165,10 +9438,10 @@ var init_usage = __esm({
|
|
|
9165
9438
|
await flushUsage();
|
|
9166
9439
|
};
|
|
9167
9440
|
getDailyUsage = async () => {
|
|
9168
|
-
const
|
|
9441
|
+
const today2 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
9169
9442
|
if (!cachedUsage) {
|
|
9170
9443
|
cachedUsage = await loadUsageFromFile();
|
|
9171
|
-
} else if (cachedUsage.date !==
|
|
9444
|
+
} else if (cachedUsage.date !== today2) {
|
|
9172
9445
|
const oldDate = cachedUsage.date;
|
|
9173
9446
|
const oldStats = cachedUsage.stats;
|
|
9174
9447
|
const history = cachedUsage.history || {};
|
|
@@ -9176,9 +9449,9 @@ var init_usage = __esm({
|
|
|
9176
9449
|
history[oldDate] = oldStats;
|
|
9177
9450
|
}
|
|
9178
9451
|
cachedUsage = {
|
|
9179
|
-
date:
|
|
9452
|
+
date: today2,
|
|
9180
9453
|
stats: { ...defaultStats },
|
|
9181
|
-
history: purgeOldHistory(history,
|
|
9454
|
+
history: purgeOldHistory(history, today2)
|
|
9182
9455
|
};
|
|
9183
9456
|
isDirty = true;
|
|
9184
9457
|
await flushUsage();
|
|
@@ -9189,15 +9462,15 @@ var init_usage = __esm({
|
|
|
9189
9462
|
return cachedUsage.stats;
|
|
9190
9463
|
};
|
|
9191
9464
|
getMonthlyUsage = async () => {
|
|
9192
|
-
const
|
|
9465
|
+
const today2 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
9193
9466
|
if (!cachedUsage) {
|
|
9194
9467
|
cachedUsage = await loadUsageFromFile();
|
|
9195
9468
|
}
|
|
9196
|
-
if (cachedUsage.date !==
|
|
9469
|
+
if (cachedUsage.date !== today2) {
|
|
9197
9470
|
await getDailyUsage();
|
|
9198
9471
|
}
|
|
9199
9472
|
const history = cachedUsage.history || {};
|
|
9200
|
-
const purgedHistory = purgeOldHistory(history,
|
|
9473
|
+
const purgedHistory = purgeOldHistory(history, today2);
|
|
9201
9474
|
cachedUsage.history = purgedHistory;
|
|
9202
9475
|
const todayStats = cachedUsage.stats || { ...defaultStats };
|
|
9203
9476
|
const summed = { ...defaultStats };
|
|
@@ -9294,17 +9567,17 @@ var init_usage = __esm({
|
|
|
9294
9567
|
queueFlush();
|
|
9295
9568
|
};
|
|
9296
9569
|
getCustomPeriodUsage = async (resetDay = 1) => {
|
|
9297
|
-
const
|
|
9298
|
-
const todayStr =
|
|
9570
|
+
const today2 = /* @__PURE__ */ new Date();
|
|
9571
|
+
const todayStr = today2.toISOString().split("T")[0];
|
|
9299
9572
|
if (!cachedUsage) {
|
|
9300
9573
|
cachedUsage = await loadUsageFromFile();
|
|
9301
9574
|
}
|
|
9302
9575
|
if (cachedUsage.date !== todayStr) {
|
|
9303
9576
|
await getDailyUsage();
|
|
9304
9577
|
}
|
|
9305
|
-
let startYear =
|
|
9306
|
-
let startMonth =
|
|
9307
|
-
const todayDay =
|
|
9578
|
+
let startYear = today2.getFullYear();
|
|
9579
|
+
let startMonth = today2.getMonth();
|
|
9580
|
+
const todayDay = today2.getDate();
|
|
9308
9581
|
if (todayDay < resetDay) {
|
|
9309
9582
|
startMonth -= 1;
|
|
9310
9583
|
if (startMonth < 0) {
|
|
@@ -9618,14 +9891,14 @@ var init_usage = __esm({
|
|
|
9618
9891
|
});
|
|
9619
9892
|
|
|
9620
9893
|
// src/utils/puppeteer_helper.js
|
|
9621
|
-
import
|
|
9894
|
+
import os3 from "os";
|
|
9622
9895
|
import path10 from "path";
|
|
9623
9896
|
import fs11 from "fs";
|
|
9624
9897
|
import { createRequire } from "module";
|
|
9625
9898
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9626
9899
|
function getPuppeteerConfig() {
|
|
9627
|
-
const platform =
|
|
9628
|
-
const arch =
|
|
9900
|
+
const platform = os3.platform();
|
|
9901
|
+
const arch = os3.arch();
|
|
9629
9902
|
let pptrPlatform = "";
|
|
9630
9903
|
let execName = "";
|
|
9631
9904
|
let subDir = "";
|
|
@@ -9962,6 +10235,7 @@ ${finalResults}`;
|
|
|
9962
10235
|
import puppeteer2 from "puppeteer";
|
|
9963
10236
|
import fs13 from "fs";
|
|
9964
10237
|
import path12 from "path";
|
|
10238
|
+
import TurndownService from "turndown";
|
|
9965
10239
|
var web_scrape;
|
|
9966
10240
|
var init_web_scrape = __esm({
|
|
9967
10241
|
"src/tools/web_scrape.js"() {
|
|
@@ -10019,15 +10293,20 @@ var init_web_scrape = __esm({
|
|
|
10019
10293
|
el.removeAttribute(attrName);
|
|
10020
10294
|
}
|
|
10021
10295
|
}
|
|
10022
|
-
|
|
10023
|
-
|
|
10296
|
+
});
|
|
10297
|
+
while (document.querySelector("div, span")) {
|
|
10298
|
+
document.querySelectorAll("div, span").forEach((el) => {
|
|
10299
|
+
if (el.parentNode) {
|
|
10024
10300
|
el.replaceWith(...el.childNodes);
|
|
10025
10301
|
}
|
|
10026
|
-
}
|
|
10302
|
+
});
|
|
10303
|
+
}
|
|
10304
|
+
document.querySelectorAll("br").forEach((br) => {
|
|
10305
|
+
br.replaceWith(document.createTextNode("\n\n"));
|
|
10027
10306
|
});
|
|
10028
10307
|
const pruneEmpty = () => {
|
|
10029
10308
|
let found = false;
|
|
10030
|
-
document.querySelectorAll("
|
|
10309
|
+
document.querySelectorAll("*").forEach((el) => {
|
|
10031
10310
|
if (el.childNodes.length === 0 && !el.innerText.trim()) {
|
|
10032
10311
|
el.remove();
|
|
10033
10312
|
found = true;
|
|
@@ -10039,11 +10318,17 @@ var init_web_scrape = __esm({
|
|
|
10039
10318
|
return document.body.innerHTML;
|
|
10040
10319
|
});
|
|
10041
10320
|
if (!htmlContent) throw new Error("EMPTY_RENDER_RESULT");
|
|
10042
|
-
const cleanedHtml = htmlContent.replace(
|
|
10321
|
+
const cleanedHtml = htmlContent.replace(/<br\s*\/?>/gi, "\n\n").replace(/[ \t]+/g, " ").replace(/>[ \t]+</g, "><").replace(/\n\s+/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
10322
|
+
const turndownService = new TurndownService({
|
|
10323
|
+
headingStyle: "atx",
|
|
10324
|
+
codeBlockStyle: "fenced"
|
|
10325
|
+
});
|
|
10326
|
+
const rawMarkdown = turndownService.turndown(cleanedHtml).replace(/\.\s*\n/g, "\n").replace(/ +/g, " ").replace(/\t/g, " ").replace(/\n\s+/g, "\n").replace(/\n{3,}/g, "\n\n");
|
|
10327
|
+
const markdown = rawMarkdown.substring(0, 5e4);
|
|
10043
10328
|
await browser.close();
|
|
10044
|
-
return `
|
|
10329
|
+
return `Markdown parsed from [${url}]:
|
|
10045
10330
|
|
|
10046
|
-
${
|
|
10331
|
+
${markdown}${rawMarkdown.length > 5e4 ? "\n\n[TRUNCATED AT 50K CHARS]" : ""}`;
|
|
10047
10332
|
} catch (err) {
|
|
10048
10333
|
lastError = err;
|
|
10049
10334
|
if (browser) await browser.close();
|
|
@@ -10243,7 +10528,7 @@ var init_view_file = __esm({
|
|
|
10243
10528
|
const end = Math.min(totalLines, finalEnd);
|
|
10244
10529
|
const resultLines = lines.slice(start, end);
|
|
10245
10530
|
const header = `File: [${targetPath}] (Showing lines ${start + 1}-${end} of ${totalLines}).`;
|
|
10246
|
-
const code = resultLines.map((line, i) => `${String(start + i + 1).padStart(4)}: ${line}`).join("\n");
|
|
10531
|
+
const code = resultLines.map((line, i) => `${String(start + i + 1).padStart(4)}: ${line.trimEnd()}`).join("\n");
|
|
10247
10532
|
return `${header}
|
|
10248
10533
|
|
|
10249
10534
|
${code}`;
|
|
@@ -10342,7 +10627,7 @@ var init_update_file = __esm({
|
|
|
10342
10627
|
update_file = async (args, context = {}) => {
|
|
10343
10628
|
const parsed = parseArgs(args);
|
|
10344
10629
|
const targetPath = parsed.path;
|
|
10345
|
-
if (!targetPath) return 'ERROR: Missing "path" argument for
|
|
10630
|
+
if (!targetPath) return 'ERROR: Missing "path" argument for PatchFile.';
|
|
10346
10631
|
const { patchPairs, allowMultiple: parsedAllowMultiple, error: parseError } = parsePatchPairs(parsed);
|
|
10347
10632
|
if (parseError) return `ERROR: ${parseError}`;
|
|
10348
10633
|
if (patchPairs.length === 0) {
|
|
@@ -10352,7 +10637,7 @@ var init_update_file = __esm({
|
|
|
10352
10637
|
const absolutePath = path15.resolve(process.cwd(), targetPath);
|
|
10353
10638
|
try {
|
|
10354
10639
|
if (!fs16.existsSync(absolutePath)) {
|
|
10355
|
-
return `ERROR: File [${targetPath}] does not exist. Use
|
|
10640
|
+
return `ERROR: File [${targetPath}] does not exist. Use WriteFile instead.`;
|
|
10356
10641
|
}
|
|
10357
10642
|
let diskContent = context.forcedContent || fs16.readFileSync(absolutePath, "utf8");
|
|
10358
10643
|
if (diskContent.startsWith("\uFEFF")) diskContent = diskContent.slice(1);
|
|
@@ -10389,7 +10674,7 @@ ${diffText}`;
|
|
|
10389
10674
|
// src/tools/read_folder.js
|
|
10390
10675
|
import fs17 from "fs";
|
|
10391
10676
|
import path16 from "path";
|
|
10392
|
-
var EXCLUDED_DIRS, isExcludedDir, read_folder;
|
|
10677
|
+
var EXCLUDED_DIRS, isExcludedDir, formatMtime, read_folder;
|
|
10393
10678
|
var init_read_folder = __esm({
|
|
10394
10679
|
"src/tools/read_folder.js"() {
|
|
10395
10680
|
init_arg_parser();
|
|
@@ -10536,24 +10821,35 @@ var init_read_folder = __esm({
|
|
|
10536
10821
|
".VSCodeCounter"
|
|
10537
10822
|
]);
|
|
10538
10823
|
isExcludedDir = (dirName) => EXCLUDED_DIRS.has(dirName) || dirName.startsWith(".pnpm");
|
|
10824
|
+
formatMtime = (d) => {
|
|
10825
|
+
try {
|
|
10826
|
+
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
10827
|
+
const dd = String(d.getDate()).padStart(2, "0");
|
|
10828
|
+
const hh = String(d.getHours()).padStart(2, "0");
|
|
10829
|
+
const min = String(d.getMinutes()).padStart(2, "0");
|
|
10830
|
+
return `${mm}-${dd} ${hh}:${min}`;
|
|
10831
|
+
} catch {
|
|
10832
|
+
return "N/A";
|
|
10833
|
+
}
|
|
10834
|
+
};
|
|
10539
10835
|
read_folder = async (args) => {
|
|
10540
10836
|
const parsed = parseArgs(args);
|
|
10541
10837
|
const targetPath = parsed.path || null;
|
|
10542
10838
|
if (!targetPath) {
|
|
10543
10839
|
return "ERROR: No directory path provided.";
|
|
10544
10840
|
}
|
|
10545
|
-
let recurseDepth =
|
|
10841
|
+
let recurseDepth = 1;
|
|
10546
10842
|
if (parsed.recurse !== void 0 && parsed.recurse !== null) {
|
|
10547
10843
|
if (typeof parsed.recurse === "number") {
|
|
10548
10844
|
recurseDepth = parsed.recurse;
|
|
10549
10845
|
} else if (typeof parsed.recurse === "boolean") {
|
|
10550
|
-
recurseDepth = parsed.recurse ?
|
|
10846
|
+
recurseDepth = parsed.recurse ? 2 : 1;
|
|
10551
10847
|
} else {
|
|
10552
10848
|
const val = parseInt(String(parsed.recurse).trim(), 10);
|
|
10553
|
-
recurseDepth = isNaN(val) ?
|
|
10849
|
+
recurseDepth = isNaN(val) ? 1 : val;
|
|
10554
10850
|
}
|
|
10555
10851
|
}
|
|
10556
|
-
recurseDepth = Math.max(
|
|
10852
|
+
recurseDepth = Math.max(1, Math.min(3, recurseDepth));
|
|
10557
10853
|
const absolutePath = path16.resolve(process.cwd(), targetPath);
|
|
10558
10854
|
try {
|
|
10559
10855
|
if (!fs17.existsSync(absolutePath)) {
|
|
@@ -10563,7 +10859,7 @@ var init_read_folder = __esm({
|
|
|
10563
10859
|
if (!stats.isDirectory()) {
|
|
10564
10860
|
return `ERROR: Path [${targetPath}] is a file, not a directory. Use ReadFile instead.`;
|
|
10565
10861
|
}
|
|
10566
|
-
if (recurseDepth ===
|
|
10862
|
+
if (recurseDepth === 1) {
|
|
10567
10863
|
const files = fs17.readdirSync(absolutePath);
|
|
10568
10864
|
const totalItems = files.length;
|
|
10569
10865
|
const maxDisplay = 150;
|
|
@@ -10577,8 +10873,8 @@ var init_read_folder = __esm({
|
|
|
10577
10873
|
info = {
|
|
10578
10874
|
name: file,
|
|
10579
10875
|
type: fStats.isDirectory() ? "directory" : "file",
|
|
10580
|
-
size: (fStats.size / 1024).toFixed(1) + "
|
|
10581
|
-
mtime: fStats.mtime
|
|
10876
|
+
size: (fStats.size / 1024).toFixed(1) + "KB",
|
|
10877
|
+
mtime: formatMtime(fStats.mtime)
|
|
10582
10878
|
};
|
|
10583
10879
|
} catch (e) {
|
|
10584
10880
|
info.type = "inaccessible";
|
|
@@ -10586,11 +10882,10 @@ var init_read_folder = __esm({
|
|
|
10586
10882
|
folderData.push(info);
|
|
10587
10883
|
}
|
|
10588
10884
|
const formatted = folderData.map((f) => {
|
|
10589
|
-
const indicator = f.type === "directory" ? "\u{1F4C1}" : f.type === "file" ? "\u{1F4C4}" : "\u2753";
|
|
10590
10885
|
if (f.type === "directory") {
|
|
10591
|
-
return `${
|
|
10886
|
+
return `${f.name}/`;
|
|
10592
10887
|
}
|
|
10593
|
-
return `${
|
|
10888
|
+
return `${f.name} (${f.size}, ${f.mtime})`;
|
|
10594
10889
|
}).join("\n");
|
|
10595
10890
|
let footer2 = `
|
|
10596
10891
|
|
|
@@ -10598,7 +10893,7 @@ var init_read_folder = __esm({
|
|
|
10598
10893
|
if (totalItems > maxDisplay) {
|
|
10599
10894
|
footer2 = `
|
|
10600
10895
|
|
|
10601
|
-
|
|
10896
|
+
TRUNCATED: Showing first ${maxDisplay} of ${totalItems} items.`;
|
|
10602
10897
|
}
|
|
10603
10898
|
files.length = 0;
|
|
10604
10899
|
displayItems.length = 0;
|
|
@@ -10612,15 +10907,17 @@ ${formatted}${footer2}`;
|
|
|
10612
10907
|
let totalItemsScanned = 0;
|
|
10613
10908
|
const maxTotalItems = 500;
|
|
10614
10909
|
let truncated = false;
|
|
10615
|
-
const buildTree = (dirPath, currentDepth,
|
|
10616
|
-
if (currentDepth > recurseDepth
|
|
10910
|
+
const buildTree = (dirPath, currentDepth, depth = 1) => {
|
|
10911
|
+
if (currentDepth > recurseDepth || truncated) return [];
|
|
10617
10912
|
let entries = [];
|
|
10618
10913
|
try {
|
|
10619
10914
|
entries = fs17.readdirSync(dirPath);
|
|
10620
10915
|
} catch (e) {
|
|
10621
|
-
|
|
10916
|
+
const indent2 = " ".repeat(depth - 1);
|
|
10917
|
+
return [`${indent2}[Inaccessible Directory]`];
|
|
10622
10918
|
}
|
|
10623
|
-
const
|
|
10919
|
+
const subDirs = [];
|
|
10920
|
+
const fileEntries = [];
|
|
10624
10921
|
for (const name of entries) {
|
|
10625
10922
|
const fullPath = path16.join(dirPath, name);
|
|
10626
10923
|
let isDir = false;
|
|
@@ -10628,60 +10925,53 @@ ${formatted}${footer2}`;
|
|
|
10628
10925
|
isDir = fs17.statSync(fullPath).isDirectory();
|
|
10629
10926
|
} catch (e) {
|
|
10630
10927
|
}
|
|
10631
|
-
|
|
10928
|
+
if (isDir) {
|
|
10929
|
+
subDirs.push({ name, fullPath });
|
|
10930
|
+
} else {
|
|
10931
|
+
fileEntries.push({ name, fullPath });
|
|
10932
|
+
}
|
|
10632
10933
|
}
|
|
10633
|
-
|
|
10634
|
-
|
|
10635
|
-
if (!a.isDir && b.isDir) return 1;
|
|
10636
|
-
return a.name.localeCompare(b.name);
|
|
10637
|
-
});
|
|
10934
|
+
subDirs.sort((a, b) => a.name.localeCompare(b.name));
|
|
10935
|
+
fileEntries.sort((a, b) => a.name.localeCompare(b.name));
|
|
10638
10936
|
const lines = [];
|
|
10639
|
-
const
|
|
10640
|
-
for (
|
|
10937
|
+
const indent = " ".repeat(depth - 1);
|
|
10938
|
+
for (const subDir of subDirs) {
|
|
10939
|
+
if (totalItemsScanned >= maxTotalItems) {
|
|
10940
|
+
truncated = true;
|
|
10941
|
+
lines.push(`${indent}[Truncated - Maximum item limit reached (${maxTotalItems})]`);
|
|
10942
|
+
break;
|
|
10943
|
+
}
|
|
10944
|
+
totalItemsScanned++;
|
|
10945
|
+
totalDirectories++;
|
|
10946
|
+
lines.push(`${indent}${subDir.name}/`);
|
|
10947
|
+
if (currentDepth < recurseDepth && !isExcludedDir(subDir.name)) {
|
|
10948
|
+
const childLines = buildTree(subDir.fullPath, currentDepth + 1, depth + 1);
|
|
10949
|
+
lines.push(...childLines);
|
|
10950
|
+
}
|
|
10951
|
+
}
|
|
10952
|
+
const formattedFiles = [];
|
|
10953
|
+
for (const file of fileEntries) {
|
|
10641
10954
|
if (totalItemsScanned >= maxTotalItems) {
|
|
10642
10955
|
truncated = true;
|
|
10643
|
-
lines.push(`${
|
|
10956
|
+
lines.push(`${indent}[Truncated - Maximum item limit reached (${maxTotalItems})]`);
|
|
10644
10957
|
break;
|
|
10645
10958
|
}
|
|
10646
|
-
const item = sortedEntries[i];
|
|
10647
|
-
const isLast = i === count - 1;
|
|
10648
|
-
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
10649
|
-
const childPrefix = prefix + (isLast ? " " : "\u2502 ");
|
|
10650
10959
|
totalItemsScanned++;
|
|
10651
|
-
|
|
10960
|
+
totalFiles++;
|
|
10652
10961
|
let sizeStr = "N/A";
|
|
10653
|
-
let mtimeStr = "N/A";
|
|
10654
10962
|
try {
|
|
10655
|
-
const fStats = fs17.statSync(
|
|
10656
|
-
|
|
10657
|
-
itemType = "directory";
|
|
10658
|
-
mtimeStr = fStats.mtime.toLocaleString();
|
|
10659
|
-
totalDirectories++;
|
|
10660
|
-
} else {
|
|
10661
|
-
itemType = "file";
|
|
10662
|
-
sizeStr = (fStats.size / 1024).toFixed(1) + " KB";
|
|
10663
|
-
mtimeStr = fStats.mtime.toLocaleString();
|
|
10664
|
-
totalFiles++;
|
|
10665
|
-
}
|
|
10963
|
+
const fStats = fs17.statSync(file.fullPath);
|
|
10964
|
+
sizeStr = (fStats.size / 1024).toFixed(1) + "KB";
|
|
10666
10965
|
} catch (e) {
|
|
10667
|
-
itemType = "inaccessible";
|
|
10668
|
-
}
|
|
10669
|
-
const indicator = itemType === "directory" ? "\u{1F4C1}" : itemType === "file" ? "\u{1F4C4}" : "\u2753";
|
|
10670
|
-
let lineText = "";
|
|
10671
|
-
if (itemType === "directory") {
|
|
10672
|
-
lineText = `${prefix}${connector}${indicator} ${item.name} - [DIR] - [Modified: ${mtimeStr}]`;
|
|
10673
|
-
} else {
|
|
10674
|
-
lineText = `${prefix}${connector}${indicator} ${item.name} - [Size: ${sizeStr}] - [Modified: ${mtimeStr}]`;
|
|
10675
|
-
}
|
|
10676
|
-
lines.push(lineText);
|
|
10677
|
-
if (itemType === "directory" && currentDepth <= recurseDepth && !isExcludedDir(item.name)) {
|
|
10678
|
-
const childLines = buildTree(item.fullPath, currentDepth + 1, childPrefix);
|
|
10679
|
-
lines.push(...childLines);
|
|
10680
10966
|
}
|
|
10967
|
+
formattedFiles.push(`${file.name} (${sizeStr})`);
|
|
10968
|
+
}
|
|
10969
|
+
if (formattedFiles.length > 0) {
|
|
10970
|
+
lines.push(`${indent}${formattedFiles.join("; ")}`);
|
|
10681
10971
|
}
|
|
10682
10972
|
return lines;
|
|
10683
10973
|
};
|
|
10684
|
-
const treeLines = buildTree(absolutePath, 1,
|
|
10974
|
+
const treeLines = buildTree(absolutePath, 1, 1);
|
|
10685
10975
|
const formattedTree = treeLines.join("\n");
|
|
10686
10976
|
let footer = `
|
|
10687
10977
|
|
|
@@ -10689,9 +10979,9 @@ ${formatted}${footer2}`;
|
|
|
10689
10979
|
if (truncated) {
|
|
10690
10980
|
footer = `
|
|
10691
10981
|
|
|
10692
|
-
|
|
10982
|
+
TRUNCATED: Scan capped at ${maxTotalItems} items. (Directories: ${totalDirectories}, Files: ${totalFiles})`;
|
|
10693
10983
|
}
|
|
10694
|
-
return `Detailed directory tree for [${targetPath}] (
|
|
10984
|
+
return `Detailed directory tree for [${targetPath}] (recursive depth: ${recurseDepth}):
|
|
10695
10985
|
|
|
10696
10986
|
${formattedTree}${footer}`;
|
|
10697
10987
|
} catch (err) {
|
|
@@ -10965,6 +11255,7 @@ var init_write_docx = __esm({
|
|
|
10965
11255
|
// src/tools/search_keyword.js
|
|
10966
11256
|
import fs20 from "fs/promises";
|
|
10967
11257
|
import path19 from "path";
|
|
11258
|
+
import fg from "fast-glob";
|
|
10968
11259
|
async function getFilesRecursively(dir, excludes, baseDir = dir, depth = 1) {
|
|
10969
11260
|
if (depth > 12) return [];
|
|
10970
11261
|
let results = [];
|
|
@@ -10996,35 +11287,50 @@ async function getFilesRecursively(dir, excludes, baseDir = dir, depth = 1) {
|
|
|
10996
11287
|
}
|
|
10997
11288
|
return results;
|
|
10998
11289
|
}
|
|
10999
|
-
function
|
|
11000
|
-
return s.toLowerCase().replace(/[^a-z0-9\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
11001
|
-
}
|
|
11002
|
-
function levenshtein(a, b) {
|
|
11290
|
+
function levenshtein(a, b, cap = Infinity) {
|
|
11003
11291
|
if (a === b) return 0;
|
|
11004
11292
|
if (a.length === 0) return b.length;
|
|
11005
11293
|
if (b.length === 0) return a.length;
|
|
11006
|
-
|
|
11007
|
-
|
|
11008
|
-
for (let
|
|
11009
|
-
let
|
|
11010
|
-
|
|
11011
|
-
for (let
|
|
11012
|
-
const
|
|
11013
|
-
|
|
11014
|
-
|
|
11294
|
+
if (Math.abs(a.length - b.length) > cap) return cap + 1;
|
|
11295
|
+
let row = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
11296
|
+
for (let i = 1; i <= a.length; i++) {
|
|
11297
|
+
let nextRow = [i];
|
|
11298
|
+
let minInRow = i;
|
|
11299
|
+
for (let j = 1; j <= b.length; j++) {
|
|
11300
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
11301
|
+
const dist = Math.min(
|
|
11302
|
+
nextRow[j - 1] + 1,
|
|
11303
|
+
// insertion
|
|
11304
|
+
row[j] + 1,
|
|
11305
|
+
// deletion
|
|
11306
|
+
row[j - 1] + cost
|
|
11307
|
+
// substitution
|
|
11308
|
+
);
|
|
11309
|
+
nextRow.push(dist);
|
|
11310
|
+
if (dist < minInRow) minInRow = dist;
|
|
11015
11311
|
}
|
|
11016
|
-
|
|
11312
|
+
row = nextRow;
|
|
11313
|
+
if (minInRow > cap) return cap + 1;
|
|
11017
11314
|
}
|
|
11018
|
-
return
|
|
11315
|
+
return row[b.length];
|
|
11019
11316
|
}
|
|
11020
11317
|
function fuzzyMatch(line, keyword) {
|
|
11021
|
-
|
|
11022
|
-
const
|
|
11023
|
-
const
|
|
11024
|
-
if (normLine.includes(
|
|
11025
|
-
|
|
11026
|
-
|
|
11027
|
-
|
|
11318
|
+
if (!line || !keyword) return false;
|
|
11319
|
+
const normLine = line.toLowerCase();
|
|
11320
|
+
const normKw = keyword.toLowerCase();
|
|
11321
|
+
if (normLine.includes(normKw)) return true;
|
|
11322
|
+
const lineWords = normLine.split(/[^a-z0-9]+/).filter((w) => w.length > 0);
|
|
11323
|
+
const kwTokens = normKw.split(/[^a-z0-9]+/).filter((t) => t.length > 1 || normKw.length === 1 && t.length > 0);
|
|
11324
|
+
if (kwTokens.length === 0) return false;
|
|
11325
|
+
return kwTokens.every((kwToken) => {
|
|
11326
|
+
const maxDist = kwToken.length <= 2 ? 0 : kwToken.length <= 5 ? 1 : 2;
|
|
11327
|
+
for (const lineWord of lineWords) {
|
|
11328
|
+
if (lineWord.includes(kwToken)) return true;
|
|
11329
|
+
if (kwToken.length >= 3 && lineWord.length >= 3 && Math.abs(lineWord.length - kwToken.length) <= maxDist) {
|
|
11330
|
+
if (levenshtein(kwToken, lineWord, maxDist) <= maxDist) return true;
|
|
11331
|
+
}
|
|
11332
|
+
}
|
|
11333
|
+
return false;
|
|
11028
11334
|
});
|
|
11029
11335
|
}
|
|
11030
11336
|
var search_keyword;
|
|
@@ -11032,17 +11338,17 @@ var init_search_keyword = __esm({
|
|
|
11032
11338
|
"src/tools/search_keyword.js"() {
|
|
11033
11339
|
init_arg_parser();
|
|
11034
11340
|
search_keyword = async (args) => {
|
|
11035
|
-
const { keyword: rawKeyword, path: pathArg, subString, regex } = parseArgs(args);
|
|
11341
|
+
const { keyword: rawKeyword, path: pathArg, fuzzy, subString, regex } = parseArgs(args);
|
|
11036
11342
|
if (rawKeyword === void 0 || rawKeyword === null) return 'ERROR: Missing "keyword" argument.';
|
|
11037
11343
|
const keyword = String(rawKeyword);
|
|
11038
11344
|
const toBool = (v) => v === true || v === "true" || v === 1 || v === "1" || v === "yes";
|
|
11039
11345
|
const regexExplicitlyFalse = regex === false || regex === "false" || regex === 0 || regex === "0" || regex === "no";
|
|
11040
11346
|
const regexExplicitlyTrue = regex === true || regex === "true" || regex === 1 || regex === "1" || regex === "yes";
|
|
11041
|
-
|
|
11347
|
+
const isFuzzy = toBool(fuzzy) || toBool(subString);
|
|
11042
11348
|
let regexPattern = null;
|
|
11043
11349
|
let wordRegex = null;
|
|
11044
11350
|
if (regexExplicitlyFalse) {
|
|
11045
|
-
if (!
|
|
11351
|
+
if (!isFuzzy) {
|
|
11046
11352
|
wordRegex = new RegExp(`(?<![\\w])${keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w])`, "i");
|
|
11047
11353
|
}
|
|
11048
11354
|
} else {
|
|
@@ -11233,21 +11539,67 @@ var init_search_keyword = __esm({
|
|
|
11233
11539
|
const rootDir = process.cwd();
|
|
11234
11540
|
let pathArgType = null;
|
|
11235
11541
|
if (pathArg) {
|
|
11236
|
-
const
|
|
11237
|
-
|
|
11238
|
-
|
|
11239
|
-
const
|
|
11240
|
-
|
|
11241
|
-
|
|
11242
|
-
|
|
11243
|
-
|
|
11244
|
-
|
|
11245
|
-
|
|
11542
|
+
const isGlob = fg.isDynamicPattern(pathArg) || /[*?{}[\]()|+]/.test(pathArg);
|
|
11543
|
+
if (isGlob) {
|
|
11544
|
+
pathArgType = "glob";
|
|
11545
|
+
const posixPath = pathArg.replace(/\\/g, "/");
|
|
11546
|
+
const globExcludes = excludes.map((ex) => ex.startsWith(".") ? `**/*${ex}` : `**/${ex}/**`);
|
|
11547
|
+
const hasRegexSyntax = /[\(\)\|]|\.\*/.test(posixPath);
|
|
11548
|
+
let matchedPaths = [];
|
|
11549
|
+
if (!hasRegexSyntax) {
|
|
11550
|
+
try {
|
|
11551
|
+
matchedPaths = await fg(posixPath, {
|
|
11552
|
+
cwd: rootDir,
|
|
11553
|
+
ignore: globExcludes,
|
|
11554
|
+
dot: true,
|
|
11555
|
+
onlyFiles: true,
|
|
11556
|
+
absolute: false
|
|
11557
|
+
});
|
|
11558
|
+
} catch {
|
|
11559
|
+
matchedPaths = [];
|
|
11560
|
+
}
|
|
11561
|
+
}
|
|
11562
|
+
if (matchedPaths.length === 0 && (hasRegexSyntax || fg.isDynamicPattern(posixPath))) {
|
|
11563
|
+
const baseDirMatch = posixPath.match(/^([^\*\?\(\)\|\[\]\s]+)\//);
|
|
11564
|
+
const scanDir = baseDirMatch && !/[\*\?\(\)\|\[\]]/.test(baseDirMatch[1]) ? path19.resolve(rootDir, baseDirMatch[1]) : rootDir;
|
|
11565
|
+
const allFiles = await getFilesRecursively(scanDir, excludes, rootDir);
|
|
11566
|
+
try {
|
|
11567
|
+
let cleanRegexStr = posixPath.replace(/^\.\//, "");
|
|
11568
|
+
cleanRegexStr = cleanRegexStr.replace(/\.\*\/(\\\.|[^\/])/g, ".*$1");
|
|
11569
|
+
if (!cleanRegexStr.startsWith("^") && !cleanRegexStr.startsWith(".*")) {
|
|
11570
|
+
cleanRegexStr = `.*${cleanRegexStr}`;
|
|
11571
|
+
}
|
|
11572
|
+
const pathRegex = new RegExp(cleanRegexStr.endsWith("$") ? cleanRegexStr : `${cleanRegexStr}$`, "i");
|
|
11573
|
+
filesToSearch = allFiles.filter((f) => {
|
|
11574
|
+
const rel = f.relativePath.replace(/\\/g, "/");
|
|
11575
|
+
return pathRegex.test(rel);
|
|
11576
|
+
});
|
|
11577
|
+
} catch {
|
|
11578
|
+
filesToSearch = [];
|
|
11579
|
+
}
|
|
11246
11580
|
} else {
|
|
11247
|
-
|
|
11581
|
+
filesToSearch = matchedPaths.map((relP) => ({
|
|
11582
|
+
fullPath: path19.resolve(rootDir, relP),
|
|
11583
|
+
relativePath: relP
|
|
11584
|
+
}));
|
|
11585
|
+
}
|
|
11586
|
+
} else {
|
|
11587
|
+
const normalised = pathArg.replace(/[\/\\]+$/, "");
|
|
11588
|
+
const fullPath = path19.resolve(rootDir, normalised);
|
|
11589
|
+
try {
|
|
11590
|
+
const stat = await fs20.stat(fullPath);
|
|
11591
|
+
if (stat.isDirectory()) {
|
|
11592
|
+
pathArgType = "dir";
|
|
11593
|
+
filesToSearch = await getFilesRecursively(fullPath, excludes, rootDir);
|
|
11594
|
+
} else if (stat.isFile()) {
|
|
11595
|
+
pathArgType = "file";
|
|
11596
|
+
filesToSearch.push({ fullPath, relativePath: path19.relative(rootDir, fullPath) });
|
|
11597
|
+
} else {
|
|
11598
|
+
return `ERROR: Path is neither a file nor a directory: ${pathArg}`;
|
|
11599
|
+
}
|
|
11600
|
+
} catch {
|
|
11601
|
+
return `ERROR: Path not found: ${pathArg}`;
|
|
11248
11602
|
}
|
|
11249
|
-
} catch {
|
|
11250
|
-
return `ERROR: Path not found: ${pathArg}`;
|
|
11251
11603
|
}
|
|
11252
11604
|
} else {
|
|
11253
11605
|
filesToSearch = await getFilesRecursively(rootDir, excludes);
|
|
@@ -11259,7 +11611,7 @@ var init_search_keyword = __esm({
|
|
|
11259
11611
|
const lines = content.split(/\r?\n/);
|
|
11260
11612
|
const fileMatches = [];
|
|
11261
11613
|
for (let i = 0; i < lines.length; i++) {
|
|
11262
|
-
const matched =
|
|
11614
|
+
const matched = isFuzzy ? lines[i].toLowerCase().includes(keyword.toLowerCase()) || fuzzyMatch(lines[i], keyword) : regexExplicitlyFalse ? wordRegex && wordRegex.test(lines[i]) : regexPattern && regexPattern.test(lines[i]) || wordRegex && wordRegex.test(lines[i]);
|
|
11263
11615
|
if (matched) {
|
|
11264
11616
|
fileMatches.push({ line: i + 1, content: lines[i].trim() });
|
|
11265
11617
|
}
|
|
@@ -11285,11 +11637,11 @@ var init_search_keyword = __esm({
|
|
|
11285
11637
|
if (typeof global.gc === "function") {
|
|
11286
11638
|
global.gc();
|
|
11287
11639
|
}
|
|
11288
|
-
const modeLabel =
|
|
11640
|
+
const modeLabel = isFuzzy ? "(fuzzy mode)" : regexExplicitlyTrue ? "(regex mode)" : regexExplicitlyFalse ? "(keyword mode)" : "(standard mode)";
|
|
11289
11641
|
if (fileGroups.length === 0) {
|
|
11290
|
-
const zeroLocation = pathArgType === "file" ? ` in '${pathArg}'` : pathArgType === "dir" ? ` in '${pathArg}'` : ". Try to specify files";
|
|
11291
|
-
const dirPrefix2 = pathArgType === "dir" ? "[DIR]" : "";
|
|
11292
|
-
return `${dirPrefix2}Found 0 matches of '${keyword}'${zeroLocation}${modeLabel ? ` ${modeLabel}` : ""}`;
|
|
11642
|
+
const zeroLocation = pathArgType === "file" ? ` in '${pathArg}'` : pathArgType === "dir" || pathArgType === "glob" ? ` in '${pathArg}'` : ". Try to specify files";
|
|
11643
|
+
const dirPrefix2 = pathArgType === "dir" ? "[DIR]" : pathArgType === "glob" ? "[GLOB]" : "";
|
|
11644
|
+
return `${dirPrefix2}${dirPrefix2 ? " " : ""}Found 0 matches of '${keyword}'${zeroLocation}${modeLabel ? ` ${modeLabel}` : ""}`;
|
|
11293
11645
|
}
|
|
11294
11646
|
const ml = modeLabel ? ` ${modeLabel}` : "";
|
|
11295
11647
|
const fileCount = `${fileGroups.length} file${fileGroups.length === 1 ? "" : "s"}`;
|
|
@@ -11297,22 +11649,20 @@ var init_search_keyword = __esm({
|
|
|
11297
11649
|
let outputHeader;
|
|
11298
11650
|
if (pathArgType === "file") {
|
|
11299
11651
|
outputHeader = `Found ${matchCount} of '${keyword}' in '${pathArg}'${ml}:`;
|
|
11300
|
-
} else if (pathArgType === "dir") {
|
|
11652
|
+
} else if (pathArgType === "dir" || pathArgType === "glob") {
|
|
11301
11653
|
outputHeader = `Found ${matchCount} of '${keyword}' in '${pathArg}' across ${fileCount}${ml}:`;
|
|
11302
11654
|
} else {
|
|
11303
11655
|
outputHeader = `Found ${matchCount} of '${keyword}' across ${fileCount}${ml}:`;
|
|
11304
11656
|
}
|
|
11305
|
-
const dirPrefix = pathArgType === "dir" ? "[DIR]" : "";
|
|
11306
|
-
let output = `${dirPrefix}${outputHeader}
|
|
11657
|
+
const dirPrefix = pathArgType === "dir" ? "[DIR]" : pathArgType === "glob" ? "[GLOB]" : "";
|
|
11658
|
+
let output = `${dirPrefix}${dirPrefix ? " " : ""}${outputHeader}
|
|
11307
11659
|
|
|
11308
11660
|
`;
|
|
11309
11661
|
for (const group of fileGroups) {
|
|
11310
11662
|
output += `${group.path}
|
|
11311
11663
|
`;
|
|
11312
|
-
for (
|
|
11313
|
-
|
|
11314
|
-
const prefix = isLast ? "\u2514\u2500\u2500" : "\u251C\u2500\u2500";
|
|
11315
|
-
output += `${prefix} ${group.matches[i].line}: ${group.matches[i].content}
|
|
11664
|
+
for (const m of group.matches) {
|
|
11665
|
+
output += ` ${m.line}: ${m.content}
|
|
11316
11666
|
`;
|
|
11317
11667
|
}
|
|
11318
11668
|
output += "\n";
|
|
@@ -13176,7 +13526,7 @@ import dotenv from "dotenv";
|
|
|
13176
13526
|
import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
|
|
13177
13527
|
import path27, { normalize } from "path";
|
|
13178
13528
|
import fs28 from "fs";
|
|
13179
|
-
var RE_STUTTER_CODE_BLOCK_CLOSED, RE_STUTTER_CODE_BLOCK_OPEN, RE_STUTTER_INLINE_CODE, RE_STUTTER_TABLE_ROW, RE_STUTTER_WORD_BOUNDARY, RE_STUTTER_NON_ALNUM, RE_TOOL_CALL_FUNC, RE_TOOL_PARTIAL_ARGS_FALLBACK, RE_STRIP_QUOTES, RE_BACKSLASH_SLASH, client, globalSettings,
|
|
13529
|
+
var RE_STUTTER_CODE_BLOCK_CLOSED, RE_STUTTER_CODE_BLOCK_OPEN, RE_STUTTER_INLINE_CODE, RE_STUTTER_TABLE_ROW, RE_STUTTER_WORD_BOUNDARY, RE_STUTTER_NON_ALNUM, RE_TOOL_CALL_FUNC, RE_TOOL_PARTIAL_ARGS_FALLBACK, RE_STRIP_QUOTES, RE_BACKSLASH_SLASH, client, globalSettings, systemInstructionCache, colorMainWords, withRetry, TERMINATION_SIGNAL, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getMistralStream, getNVIDIAStream, wrapNvidiaStreamWithQueueDepth, getOpenRouterStream, signalTermination, isTerminationSignaled, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, REGEX_PLACEHOLDER_ARG, REGEX_PLACEHOLDER_VAL, isPlaceholderVal, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream, runSubagent;
|
|
13180
13530
|
var init_ai = __esm({
|
|
13181
13531
|
async "src/utils/ai.js"() {
|
|
13182
13532
|
await init_prompts();
|
|
@@ -13198,6 +13548,7 @@ var init_ai = __esm({
|
|
|
13198
13548
|
init_editor();
|
|
13199
13549
|
init_indentation();
|
|
13200
13550
|
init_box();
|
|
13551
|
+
await init_main_tools();
|
|
13201
13552
|
dotenv.config({ quiet: true });
|
|
13202
13553
|
RE_STUTTER_CODE_BLOCK_CLOSED = /```[\s\S]*?```/g;
|
|
13203
13554
|
RE_STUTTER_CODE_BLOCK_OPEN = /```[\s\S]*$/g;
|
|
@@ -13211,26 +13562,7 @@ var init_ai = __esm({
|
|
|
13211
13562
|
RE_BACKSLASH_SLASH = /\\/g;
|
|
13212
13563
|
client = null;
|
|
13213
13564
|
globalSettings = {};
|
|
13214
|
-
|
|
13215
|
-
cachedChatId2 = null;
|
|
13216
|
-
cachedIndentationTree = null;
|
|
13217
|
-
getCachedDirTree = (fn, chatId, isDynamicDirAwareness, indentationTree) => {
|
|
13218
|
-
if (isDynamicDirAwareness) {
|
|
13219
|
-
dirTreeCache = null;
|
|
13220
|
-
cachedChatId2 = chatId;
|
|
13221
|
-
cachedIndentationTree = indentationTree;
|
|
13222
|
-
return fn();
|
|
13223
|
-
}
|
|
13224
|
-
if (cachedChatId2 !== chatId || cachedIndentationTree !== indentationTree) {
|
|
13225
|
-
dirTreeCache = null;
|
|
13226
|
-
cachedChatId2 = chatId;
|
|
13227
|
-
cachedIndentationTree = indentationTree;
|
|
13228
|
-
}
|
|
13229
|
-
if (dirTreeCache === null) {
|
|
13230
|
-
dirTreeCache = fn();
|
|
13231
|
-
}
|
|
13232
|
-
return dirTreeCache;
|
|
13233
|
-
};
|
|
13565
|
+
systemInstructionCache = { key: null, value: null };
|
|
13234
13566
|
colorMainWords = (label) => {
|
|
13235
13567
|
if (!label) return label;
|
|
13236
13568
|
return label.replace(/(?:(\x1b\[\d+m))?([✔✘✖🔍📖→➕↻↷•🛇])(?:(\x1b\[\d+m))?\s*\b(Created|Read|Edited|Viewed|Processed|Auto-Read|Skipped|List|Generated|Written|Searched|AI Search|Get Map|Write Canceled|Edit Canceled|Write Cancelled|Edit Denied|Visited|Updated|Reviewed|Delegated|Background|Checked|Indexed|Analyzed|Browsed|Elevating SubAgent|Checking SubAgent Work|Started Generalist|Called Generalist|Unsupported Modality|Awaiting|Cancelled|Aligning Moon Phase|Contemplating Existence|Staring At Void|Rollback Point Checked|Emergency Rollback Failed|Emergency Rollback|Delaying Professionally|Negotiating With Electrons|Touching Grass (virtually)|Panicking Softly|Rethinking Career Choices|Loading Cat Videos|Giving Up Entirely|Summoning Braincell #2|Pretending To Be Busy|Waiting For Motivation DLC|Rotating Internal Screaming|Downloading More RAM|Feeding The Hamsters|Gaslighting Scheduler|Performing Dramatic Pause|Buffering Social Energy|Calculating Regret|Reading Terms And Conditions|Becoming Sentient Briefly|Contacting Ancestors)\b/ig, (match, ansiBefore, icon, ansiAfter, word) => {
|
|
@@ -14220,7 +14552,9 @@ var init_ai = __esm({
|
|
|
14220
14552
|
}
|
|
14221
14553
|
let originalTextProcessed = agentText.replace(/\[Prompted on:.*?\]/g, "").trim();
|
|
14222
14554
|
agentRes = agentRes.replace(/\r?\n\r?\n/g, "\n").replace(/\n\n/g, "\n").replace(/\\n\\n/g, "").trim();
|
|
14223
|
-
|
|
14555
|
+
const now1223 = /* @__PURE__ */ new Date();
|
|
14556
|
+
const dateTimeStr1223 = `${now1223.getFullYear()}-${now1223.toLocaleString("en-US", { month: "short" }).toUpperCase()}-${String(now1223.getDate()).padStart(2, "0")}, ${now1223.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", hour12: true })}`;
|
|
14557
|
+
let userPrompt = `[METADATA] Current date and Time: ${dateTimeStr1223}
|
|
14224
14558
|
|
|
14225
14559
|
[USER]: ${originalTextProcessed.substring(0, USER_CONTEXT_LENGTH)}
|
|
14226
14560
|
${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n" : ""}
|
|
@@ -14687,6 +15021,13 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
14687
15021
|
result = result.replace(/<\|\s*tool_calls_section_end\s*\|>/gi, "");
|
|
14688
15022
|
return result;
|
|
14689
15023
|
};
|
|
15024
|
+
REGEX_PLACEHOLDER_ARG = /(?:path|query|url|keyword|command|method|title|task|id)\s*=\s*['"`]?\s*\.\.\.\s*['"`]?/i;
|
|
15025
|
+
REGEX_PLACEHOLDER_VAL = /^['"`]?\s*\.\.\.\s*['"`]?$/;
|
|
15026
|
+
isPlaceholderVal = (val) => {
|
|
15027
|
+
if (val === void 0 || val === null) return false;
|
|
15028
|
+
const str = String(val).trim();
|
|
15029
|
+
return str === "..." || str === "\u2026" || REGEX_PLACEHOLDER_VAL.test(str);
|
|
15030
|
+
};
|
|
14690
15031
|
detectToolCalls = (text) => {
|
|
14691
15032
|
if (!text) return [];
|
|
14692
15033
|
const translatedText = translateKimiToolCalls(text);
|
|
@@ -14735,11 +15076,15 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
14735
15076
|
if (endIdx !== -1) {
|
|
14736
15077
|
const finalArgsText = cleanText.substring(startIdx + 1, closingParenIdx);
|
|
14737
15078
|
const finalFullMatch = cleanText.substring(match.index, endIdx + 1);
|
|
14738
|
-
|
|
14739
|
-
|
|
14740
|
-
|
|
14741
|
-
|
|
14742
|
-
|
|
15079
|
+
const parsed = parseArgs(finalArgsText);
|
|
15080
|
+
const hasPlaceholderArg = isPlaceholderVal(parsed.path) || isPlaceholderVal(parsed.query) || isPlaceholderVal(parsed.url) || isPlaceholderVal(parsed.keyword) || isPlaceholderVal(parsed.command) || isPlaceholderVal(parsed.method) || isPlaceholderVal(parsed.title) || isPlaceholderVal(parsed.task) || isPlaceholderVal(parsed.id) || REGEX_PLACEHOLDER_ARG.test(finalArgsText);
|
|
15081
|
+
if (!hasPlaceholderArg) {
|
|
15082
|
+
results.push({
|
|
15083
|
+
fullMatch: finalFullMatch,
|
|
15084
|
+
toolName: toolName.trim(),
|
|
15085
|
+
args: finalArgsText.trim()
|
|
15086
|
+
});
|
|
15087
|
+
}
|
|
14743
15088
|
toolRegex.lastIndex = endIdx + 1;
|
|
14744
15089
|
}
|
|
14745
15090
|
}
|
|
@@ -14937,7 +15282,8 @@ Chats to process:
|
|
|
14937
15282
|
if (oldSummary) {
|
|
14938
15283
|
prompt += `- Existing Summary: "${oldSummary}"
|
|
14939
15284
|
`;
|
|
14940
|
-
prompt +=
|
|
15285
|
+
prompt += `
|
|
15286
|
+
-- New Memories to integrate:
|
|
14941
15287
|
${newMemoryListStr}
|
|
14942
15288
|
|
|
14943
15289
|
`;
|
|
@@ -15179,7 +15525,12 @@ Provide a consolidated summary of the entire session.`;
|
|
|
15179
15525
|
const mainUserMemories = persistentStorage.map((m) => `- ${m.memory}`).join("\n");
|
|
15180
15526
|
const isContext32k = (sessionStats?.tokens || 0) >= 1e4;
|
|
15181
15527
|
const memoryPrompt = getMemoryPrompt(otherMemories, mainUserMemories, isMemoryEnabled, isContext32k);
|
|
15182
|
-
const
|
|
15528
|
+
const now = /* @__PURE__ */ new Date();
|
|
15529
|
+
const year = now.getFullYear();
|
|
15530
|
+
const month = now.toLocaleString("en-US", { month: "short" }).toUpperCase();
|
|
15531
|
+
const day = String(now.getDate()).padStart(2, "0");
|
|
15532
|
+
const timeStr = now.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", hour12: true });
|
|
15533
|
+
const dateTimeStr = `${year}-${month}-${day}, ${timeStr}`;
|
|
15183
15534
|
const COLLAPSED_DIRS_GLOBAL = [
|
|
15184
15535
|
// --- The OG Clutter ---
|
|
15185
15536
|
".git",
|
|
@@ -15406,8 +15757,11 @@ ${currentSummary}
|
|
|
15406
15757
|
**CONTEXT SUMMARY OF PREVIOUS TURNS**
|
|
15407
15758
|
${currentSummary}
|
|
15408
15759
|
` : "";
|
|
15409
|
-
|
|
15410
|
-
|
|
15760
|
+
const dynamicDirAwareness = !!systemSettings?.dynamicDirAwareness;
|
|
15761
|
+
const sysInstructionCacheKey = `${chatId}|${aiProvider}|${thinkingLevel}|${modelName}|${profile}|${dynamicDirAwareness}`;
|
|
15762
|
+
const isSysInstructionCached = !dynamicDirAwareness && systemInstructionCache.key === sysInstructionCacheKey && systemInstructionCache.value;
|
|
15763
|
+
let dirStructure = isSysInstructionCached ? "" : "\n**DIRECTORY STRUCTURE**\nCWD: " + process.cwd() + `${isPlayground ? " [PLAYGROUND MODE]" : ""}${cwdMismatch ? ` (WARNING: CWD Mismatch! Previous Path: ${lastCwd})` : ""}
|
|
15764
|
+
` + getDirTree(process.cwd(), dynamicMaxDepth);
|
|
15411
15765
|
const ideCtx = await getIDEContext();
|
|
15412
15766
|
let ideBlock = "";
|
|
15413
15767
|
if (isBridgeConnected()) {
|
|
@@ -15859,10 +16213,18 @@ ${cleanPromptForModel.trim()}
|
|
|
15859
16213
|
throw new Error("Error: Quota Exausted for Agent");
|
|
15860
16214
|
}
|
|
15861
16215
|
targetModel = modelName;
|
|
15862
|
-
|
|
15863
|
-
|
|
15864
|
-
|
|
16216
|
+
const sysInstructionCacheKey2 = `${chatId}|${aiProvider}|${thinkingLevel}|${targetModel}|${JSON.stringify(profile)}|${!!systemSettings?.dynamicDirAwareness}|${!!systemSettings?.subAgents}`;
|
|
16217
|
+
let isCacheHit = systemInstructionCache.key === sysInstructionCacheKey2 && systemInstructionCache.value;
|
|
16218
|
+
if (isCacheHit) {
|
|
16219
|
+
currentSystemInstruction = systemInstructionCache.value;
|
|
16220
|
+
} else {
|
|
16221
|
+
currentSystemInstruction = getSystemInstruction(profile, !(targetModel || "gemma").toLowerCase().startsWith("gemma") ? thinkingLevel : thinkingLevel, mode, systemSettings, isMemoryEnabled, isFirstPrompt, aiProvider, aiProvider === "Google" ? true : isMultiModal, !(targetModel || "gemma").toLowerCase().startsWith("gemma") ? true : false, chatId);
|
|
16222
|
+
if (!systemSettings?.dynamicDirAwareness) {
|
|
16223
|
+
currentSystemInstruction += `
|
|
15865
16224
|
${dirStructure.replace("\n**DIRECTORY STRUCTURE**", "\n**DIRECTORY STRUCTURE**")}`;
|
|
16225
|
+
}
|
|
16226
|
+
systemInstructionCache.key = sysInstructionCacheKey2;
|
|
16227
|
+
systemInstructionCache.value = currentSystemInstruction;
|
|
15866
16228
|
}
|
|
15867
16229
|
const lastUserMsg = contents[contents.length - 1];
|
|
15868
16230
|
if (isBridgeConnected() & loop > 0) {
|
|
@@ -16599,8 +16961,8 @@ ${ideErr} [/ERROR]`;
|
|
|
16599
16961
|
} else if (normToolName === "list_files" || normToolName === "read_folder") {
|
|
16600
16962
|
const action = normToolName === "list_files" ? "List" : "Browsed";
|
|
16601
16963
|
const path29 = parseArgs(toolCall.args).path || null;
|
|
16602
|
-
const recurse = parseArgs(toolCall.args).recurse ||
|
|
16603
|
-
label = `${path29 ? "\u2714" : "\u2718"} ${action}: ${path29 ? `${path29 === "." ? "
|
|
16964
|
+
const recurse = parseArgs(toolCall.args).recurse || 1;
|
|
16965
|
+
label = `${path29 ? "\u2714" : "\u2718"} ${action}: ${path29 ? `${path29 === "." ? `./${recurse > 1 ? "*" : ""}` : `${path29.replaceAll("\\", "/")}${recurse > 1 ? `${path29.endsWith("/") ? `*` : `/*`}` : `${path29.endsWith("/") ? "" : "/"}`}`}` : "No Folder Selected"}`;
|
|
16604
16966
|
} else if (normToolName === "write_file" || normToolName === "update_file") {
|
|
16605
16967
|
const action = normToolName === "write_file" ? "Created" : "Edited";
|
|
16606
16968
|
const path29 = parseArgs(toolCall.args).path || null;
|
|
@@ -16659,7 +17021,6 @@ ${ideErr} [/ERROR]`;
|
|
|
16659
17021
|
"Panicking Softly",
|
|
16660
17022
|
"Rethinking Career Choices",
|
|
16661
17023
|
"Loading Cat Videos",
|
|
16662
|
-
"Giving Up Entirely",
|
|
16663
17024
|
// --- The New Chaos Pack ---
|
|
16664
17025
|
"Summoning Braincell #2",
|
|
16665
17026
|
"Pretending To Be Busy",
|
|
@@ -17333,8 +17694,10 @@ ${snippet2}`;
|
|
|
17333
17694
|
}
|
|
17334
17695
|
if (normToolName === "search_keyword") {
|
|
17335
17696
|
const { keyword, path: path29 } = parseArgs(toolCall.args);
|
|
17697
|
+
const _isGlob = typeof result === "string" && result.startsWith("[GLOB]");
|
|
17698
|
+
if (_isGlob) result = result.slice(6).trimStart();
|
|
17336
17699
|
const _isDir = typeof result === "string" && result.startsWith("[DIR]");
|
|
17337
|
-
if (_isDir) result = result.slice(5);
|
|
17700
|
+
if (_isDir) result = result.slice(5).trimStart();
|
|
17338
17701
|
let matchCount = 0;
|
|
17339
17702
|
if (result) {
|
|
17340
17703
|
const m = result.match(/Found (\d+) match/i);
|
|
@@ -17343,7 +17706,7 @@ ${snippet2}`;
|
|
|
17343
17706
|
}
|
|
17344
17707
|
}
|
|
17345
17708
|
const _sp = path29 ? path29.replace(/[\/\\]+$/, "") : null;
|
|
17346
|
-
const displayPath = _sp && _sp !== "." ? `"${_isDir ? `${_sp}/*` : _sp}"` : "./";
|
|
17709
|
+
const displayPath = _sp && _sp !== "." ? `"${_isGlob ? path29 : _isDir ? `${_sp}/*` : _sp}"` : "./";
|
|
17347
17710
|
const postLabel = `${keyword ? "\u2714" : "\u2718"} Searched: "${keyword ? keyword : ""}" in ${displayPath.replaceAll("\\", "/")} \u2192 ${matchCount} Match${matchCount === 1 ? "" : "es"}`;
|
|
17348
17711
|
let terminalWidth = 115;
|
|
17349
17712
|
if (process.stdout.isTTY) {
|
|
@@ -17800,18 +18163,76 @@ Error Log can be found in ${path27.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
17800
18163
|
runSubagent = async (task, settings, model = null, allowedTools = null, maxTurns = 50, logCallback = null) => {
|
|
17801
18164
|
const savedSettings = await loadSettings();
|
|
17802
18165
|
const mergedSettings = { ...savedSettings, ...settings };
|
|
17803
|
-
const
|
|
17804
|
-
const
|
|
17805
|
-
|
|
17806
|
-
|
|
17807
|
-
|
|
17808
|
-
|
|
17809
|
-
|
|
17810
|
-
|
|
17811
|
-
|
|
17812
|
-
|
|
17813
|
-
|
|
18166
|
+
const envSubagentModel = process.env.SUBAGENT_MODEL ? process.env.SUBAGENT_MODEL.trim() : null;
|
|
18167
|
+
const envSubagentProviderRaw = process.env.SUBAGENT_PROVIDER ? process.env.SUBAGENT_PROVIDER.trim() : null;
|
|
18168
|
+
const subagentNow = /* @__PURE__ */ new Date();
|
|
18169
|
+
const time = `${subagentNow.getFullYear()}-${subagentNow.toLocaleString("en-US", { month: "short" }).toUpperCase()}-${String(subagentNow.getDate()).padStart(2, "0")}, ${subagentNow.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", hour12: true }).replace(":", "-")}`;
|
|
18170
|
+
const normalizeProvider = (pStr) => {
|
|
18171
|
+
if (!pStr) return null;
|
|
18172
|
+
const lower = pStr.toLowerCase();
|
|
18173
|
+
if (lower === "google") return "Google";
|
|
18174
|
+
if (lower === "deepseek") return "DeepSeek";
|
|
18175
|
+
if (lower === "openrouter") return "OpenRouter";
|
|
18176
|
+
if (lower === "nvidia") return "NVIDIA";
|
|
18177
|
+
if (lower === "mistral") return "Mistral";
|
|
18178
|
+
return null;
|
|
18179
|
+
};
|
|
18180
|
+
const envSubagentProvider = normalizeProvider(envSubagentProviderRaw);
|
|
18181
|
+
const configuredSubAgentModel = mergedSettings?.systemSettings?.CustomSubAgent ? mergedSettings?.systemSettings?.SubAgentModel : null;
|
|
18182
|
+
const configuredSubAgentProvider = mergedSettings?.systemSettings?.CustomSubAgent ? mergedSettings?.systemSettings?.SubAgentProvider : null;
|
|
18183
|
+
let subAgentCustomModel = null;
|
|
18184
|
+
if (configuredSubAgentModel === "ENV") {
|
|
18185
|
+
subAgentCustomModel = envSubagentModel;
|
|
18186
|
+
if (envSubagentModel && envSubagentProvider) {
|
|
18187
|
+
mergedSettings.aiProvider = envSubagentProvider;
|
|
18188
|
+
}
|
|
18189
|
+
} else if (configuredSubAgentModel && configuredSubAgentModel !== "Default") {
|
|
18190
|
+
subAgentCustomModel = configuredSubAgentModel;
|
|
18191
|
+
if (configuredSubAgentProvider) {
|
|
18192
|
+
mergedSettings.aiProvider = configuredSubAgentProvider;
|
|
18193
|
+
}
|
|
18194
|
+
} else if (envSubagentModel) {
|
|
18195
|
+
if (envSubagentProvider) {
|
|
18196
|
+
mergedSettings.aiProvider = envSubagentProvider;
|
|
18197
|
+
}
|
|
18198
|
+
}
|
|
18199
|
+
if (mergedSettings.aiProvider) {
|
|
18200
|
+
const providerApiKey = await getProviderAPIKey(mergedSettings.aiProvider);
|
|
18201
|
+
if (providerApiKey) {
|
|
18202
|
+
mergedSettings.apiKey = providerApiKey;
|
|
18203
|
+
}
|
|
18204
|
+
}
|
|
18205
|
+
const isSubagentCommandAllowed = (cmdString) => {
|
|
18206
|
+
if (!cmdString || typeof cmdString !== "string") return { allowed: true };
|
|
18207
|
+
const DANGEROUS_PATTERNS = [
|
|
18208
|
+
// Destructive file deletion / formatting
|
|
18209
|
+
/rm\s+-[rf]{1,2}\s+[\/*.]/i,
|
|
18210
|
+
/rmdir\s+\/[sq]/i,
|
|
18211
|
+
/del\s+\/[fsq]/i,
|
|
18212
|
+
/\bformat\b\s+[a-z]:/i,
|
|
18213
|
+
/mkfs/i,
|
|
18214
|
+
/dd\s+if=/i,
|
|
18215
|
+
// System shutdown / reboot / killall
|
|
18216
|
+
/\b(shutdown|reboot|poweroff|init\s+0|init\s+6)\b/i,
|
|
18217
|
+
// Low level disk / raw write / partition / chmod dangerous
|
|
18218
|
+
/chmod\s+(-R\s+)?777\s+[\/*.]/i,
|
|
18219
|
+
/chown\s+(-R\s+)?root/i,
|
|
18220
|
+
// Dangerous git force / reset operations on remote / system
|
|
18221
|
+
/git\s+push\s+.*--force/i,
|
|
18222
|
+
/git\s+clean\s+-fdx/i,
|
|
18223
|
+
// System-level privilege escalation
|
|
18224
|
+
/\bsudo\s+su\b/i,
|
|
18225
|
+
/\bsu\s+-\b/i
|
|
18226
|
+
];
|
|
18227
|
+
for (const pattern of DANGEROUS_PATTERNS) {
|
|
18228
|
+
if (pattern.test(cmdString)) {
|
|
18229
|
+
return { allowed: false, reason: `Blocked potentially destructive or unsafe command pattern: "${pattern.source}"` };
|
|
18230
|
+
}
|
|
18231
|
+
}
|
|
18232
|
+
return { allowed: true };
|
|
17814
18233
|
};
|
|
18234
|
+
const targetModel = model || subAgentCustomModel || settings?.modelName || settings?.activeModel || savedSettings.activeModel;
|
|
18235
|
+
const osDetected = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
|
|
17815
18236
|
const providedToolsSection = `-- TOOL DEFINITIONS (path = relative to CWD, path separator: '/') --
|
|
17816
18237
|
TO ACCESS TOOLS **STRICTLY USE THE EXACT FORMAT IN CHAT OUTPUT:** [tool:functions.ToolName(args)]
|
|
17817
18238
|
**NO OTHER SYNTAX/MARKERS/BOUNDARY ALLOWED**
|
|
@@ -17819,15 +18240,26 @@ TO ACCESS TOOLS **STRICTLY USE THE EXACT FORMAT IN CHAT OUTPUT:** [tool:function
|
|
|
17819
18240
|
TOOL POLICY:
|
|
17820
18241
|
- MAX 3 TOOL CALLS PER TURN
|
|
17821
18242
|
- Same file, many edits? Prefer multi search-replace in Patch \u2190 **HIGHLY RECOMMENDED**
|
|
17822
|
-
-
|
|
17823
|
-
-
|
|
17824
|
-
-
|
|
17825
|
-
|
|
18243
|
+
- Need specific text OR huge file ? SearchKeyword > ReadFile
|
|
18244
|
+
- Tool denied? Use \`Ask\` immediately for user guidance \u2190 **MANDATORY**
|
|
18245
|
+
- Restricted Shell Access, NO DELETION
|
|
18246
|
+
|
|
18247
|
+
**PROVIDED TOOLS**
|
|
18248
|
+
-- Communication with USER --
|
|
18249
|
+
- [tool:functions.Ask(question="...", optionA="option::description", ...MAX 4)]. Ambiguity: MUST for path divergence, security risk. Ask, don't finish/guess. Suggest best options; no preferences. Keep options short
|
|
17826
18250
|
|
|
17827
|
-
--
|
|
17828
|
-
|
|
18251
|
+
-- Web Tools --
|
|
18252
|
+
- [tool:functions.WebSearch(query="...", aiMode="bool optional, default: false", limit="integer 3-10, aiMode: exclude")]. Usage: unknown info/docs. aiMode: LLM search
|
|
18253
|
+
- [tool:functions.WebScrape(url="...")]. Proactive use for specific webpage/docs/api
|
|
18254
|
+
|
|
18255
|
+
-- Workspace Tools --
|
|
18256
|
+
- [tool:functions.SearchKeyword(keyword="...", path="optional, dir/file/glob/regex", fuzzy="bool optional, default: false", regex="bool optional, default: auto")]. path limits search scope. Find definitions/logic without full reads. Locate relevant code
|
|
18257
|
+
- [tool:functions.ReadFolder(path="...", recurse="integer 1-3 optional, default: 1")]. DIR Contents + File Size. Minimize recursion
|
|
18258
|
+
- [tool:functions.ReadFile(path="...", startLine="integer", endLine="integer")]. View files
|
|
18259
|
+
- [tool:functions.PatchFile(path="...", allowMultiple="bool optional, default: false", replaceContent1="...", newContent1="...", ...MAX 15)]. Surgical patchs, TARGET SMALLEST LINES. allowMultiple: Replace all matches ONLY WHERE SURE. Use replaceContent2/newContent2... for multi blocks. Verify DIFFs
|
|
18260
|
+
- [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile > WriteFile. VERIFY IMPORTS
|
|
18261
|
+
- [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? `WINDOWS POWERSHELL` : `WINDOWS CMD` : `BASH`} command. Destructive/Irreversible ops \u2192 Ask user
|
|
17829
18262
|
|
|
17830
|
-
- VERIFY TOOL RESULT CONTENTS. Fix errors. No hallucinations
|
|
17831
18263
|
- **Escape quotes: \\" for code strings**
|
|
17832
18264
|
- **Literal escapes: Double-escape sequences (e.g., \\\\n)**
|
|
17833
18265
|
- **File structure: Real newlines for code formatting**`.trim();
|
|
@@ -17838,12 +18270,12 @@ Your task is: "${task}"
|
|
|
17838
18270
|
${providedToolsSection.trimEnd()}
|
|
17839
18271
|
|
|
17840
18272
|
-- THINKING GUIDANCE --
|
|
17841
|
-
NO EXPLICIT THINKING REQUIRED. FOCUS ON
|
|
17842
|
-
|
|
18273
|
+
NO EXPLICIT THINKING REQUIRED. FOCUS ON TASK COMPLETION
|
|
17843
18274
|
Keep main focus on tools and task, not chatting
|
|
17844
|
-
|
|
18275
|
+
On task completion, provide a detailed structured summary preferebly in Tables/Bullet Points with file modified info, if any task failed report back in detail, no hallucination
|
|
17845
18276
|
|
|
17846
18277
|
CWD: ${process.cwd()}
|
|
18278
|
+
Current Time: ${time}
|
|
17847
18279
|
=== END SYSTEM PROMPT ===`;
|
|
17848
18280
|
const subagentHistory = [
|
|
17849
18281
|
{ role: "user", text: `Complete this task: ${task}` }
|
|
@@ -17909,11 +18341,26 @@ ${cleanResponse}
|
|
|
17909
18341
|
`;
|
|
17910
18342
|
continue;
|
|
17911
18343
|
}
|
|
18344
|
+
if (normalizedToolName === "exec_command" || normalizedToolName === "execcommand" || normalizedToolName === "run") {
|
|
18345
|
+
const cmdArg = parseArgs(toolCall.args).command || "";
|
|
18346
|
+
const cmdCheck = isSubagentCommandAllowed(cmdArg);
|
|
18347
|
+
if (!cmdCheck.allowed) {
|
|
18348
|
+
const blockMsg = `ERROR: [SECURITY RESTRICTION] Subagent execution blocked command: ${cmdCheck.reason}`;
|
|
18349
|
+
if (logCallback) logCallback(`[Blocked Command] ${cmdArg} - ${cmdCheck.reason}
|
|
18350
|
+
`);
|
|
18351
|
+
toolResultsStr += `${blockMsg}
|
|
18352
|
+
|
|
18353
|
+
`;
|
|
18354
|
+
continue;
|
|
18355
|
+
}
|
|
18356
|
+
}
|
|
17912
18357
|
let label = "";
|
|
17913
18358
|
if (normalizedToolName === "web_search" || normalizedToolName === "websearch") {
|
|
17914
|
-
|
|
18359
|
+
const query = parseArgs(toolCall.args).query || "";
|
|
18360
|
+
label = `\u2714 \x1B[95mSearched\x1B[0m: ${query}`;
|
|
17915
18361
|
} else if (normalizedToolName === "web_scrape" || normalizedToolName === "webscrape") {
|
|
17916
|
-
|
|
18362
|
+
const url = parseArgs(toolCall.args).url || "";
|
|
18363
|
+
label = `\u2714 \x1B[95mScraped\x1B[0m: ${url}`;
|
|
17917
18364
|
} else if (normalizedToolName === "search_keyword" || normalizedToolName === "searchkeyword") {
|
|
17918
18365
|
const pArgs = parseArgs(toolCall.args);
|
|
17919
18366
|
const keyword = pArgs.keyword || "";
|
|
@@ -17925,7 +18372,7 @@ ${cleanResponse}
|
|
|
17925
18372
|
} else if (normalizedToolName === "list_files" || normalizedToolName === "read_folder" || normalizedToolName === "readfolder") {
|
|
17926
18373
|
const path29 = parseArgs(toolCall.args).path || null;
|
|
17927
18374
|
const recurse = parseArgs(toolCall.args).recurse || 0;
|
|
17928
|
-
label = `${path29 ? "\u2714" : "\u2718"}
|
|
18375
|
+
label = `${path29 ? "\u2714" : "\u2718"} \x1B[95mBrowsed\x1B[0m: ${path29 ? `${path29.replaceAll("\\", "/")}${recurse > 0 ? `${path29.endsWith("/") ? `*${recurse}` : `/*${recurse}`}` : `${path29.endsWith("/") ? "" : "/"}`}` : ""}`;
|
|
17929
18376
|
} else if (normalizedToolName === "write_file" || normalizedToolName === "writefile") {
|
|
17930
18377
|
const path29 = parseArgs(toolCall.args).path || null;
|
|
17931
18378
|
label = `${path29 ? "\u2714" : "\u2718"} \x1B[95mCreated\x1B[0m: ${path29 ? `${path29.replaceAll("\\", "/")}` : "No File Changes"}`;
|
|
@@ -17933,12 +18380,15 @@ ${cleanResponse}
|
|
|
17933
18380
|
const path29 = parseArgs(toolCall.args).path || null;
|
|
17934
18381
|
const content = parseArgs(toolCall.args).content || null;
|
|
17935
18382
|
label = `${path29 ? "\u2714" : "\u2718"} \x1B[95mEdited\x1B[0m: ${path29 ? `${path29.replaceAll("\\", "/")}` : "No File Changes"}`;
|
|
18383
|
+
} else if (normalizedToolName === "exec_command" || normalizedToolName === "execcommand" || normalizedToolName === "run") {
|
|
18384
|
+
const command = parseArgs(toolCall.args).command || null;
|
|
18385
|
+
label = `${command ? "\u2714" : "\u2718"} \x1B[95mExecuted\x1B[0m: ${command ? command.slice(0, 100) + (command.length > 100 ? "..." : "") : "No Command"}`;
|
|
17936
18386
|
} else if (normalizedToolName === "file_map" || normalizedToolName === "filemap") {
|
|
17937
18387
|
const path29 = parseArgs(toolCall.args).path || "";
|
|
17938
18388
|
label = `${path29 ? "\u2714" : "\u2718"} \x1B[95mIndexed\x1B[0m: ${path29 ? `${path29.replaceAll("\\", "/")}` : "File Not Found"}`;
|
|
17939
18389
|
} else if (normalizedToolName === "await") {
|
|
17940
|
-
const { time } = parseArgs(toolCall.args);
|
|
17941
|
-
let sec = parseFloat(
|
|
18390
|
+
const { time: time2 } = parseArgs(toolCall.args);
|
|
18391
|
+
let sec = parseFloat(time2) || 0;
|
|
17942
18392
|
if (sec < 10) sec = 10;
|
|
17943
18393
|
if (sec > 180) sec = 180;
|
|
17944
18394
|
const formatTime = (s) => {
|
|
@@ -19028,7 +19478,7 @@ var app_exports = {};
|
|
|
19028
19478
|
__export(app_exports, {
|
|
19029
19479
|
default: () => App
|
|
19030
19480
|
});
|
|
19031
|
-
import
|
|
19481
|
+
import os4 from "os";
|
|
19032
19482
|
import React16, { useState as useState15, useEffect as useEffect12, useRef as useRef4, useMemo as useMemo2 } from "react";
|
|
19033
19483
|
import { Box as Box14, Text as Text16, useInput as useInput9, useStdout as useStdout2, Static } from "ink";
|
|
19034
19484
|
import fs30 from "fs-extra";
|
|
@@ -19056,6 +19506,7 @@ function App({ args = [] }) {
|
|
|
19056
19506
|
const [showBridgePromo, setShowBridgePromo] = useState15(false);
|
|
19057
19507
|
const [promoSelectedIndex, setPromoSelectedIndex] = useState15(0);
|
|
19058
19508
|
const suggestionOffsetRef = useRef4(0);
|
|
19509
|
+
const maxScrollRef = useRef4(0);
|
|
19059
19510
|
const persistedModelRef = useRef4(null);
|
|
19060
19511
|
const activeStreamingMsgRef = useRef4(null);
|
|
19061
19512
|
const [renderTick, setRenderTick] = useState15(0);
|
|
@@ -19172,6 +19623,108 @@ function App({ args = [] }) {
|
|
|
19172
19623
|
clearInterval(memInterval);
|
|
19173
19624
|
};
|
|
19174
19625
|
}, []);
|
|
19626
|
+
useEffect12(() => {
|
|
19627
|
+
const checkSubAgentModelOnStartup = async () => {
|
|
19628
|
+
try {
|
|
19629
|
+
const settings = await loadSettings();
|
|
19630
|
+
const sysSettings = settings?.systemSettings || {};
|
|
19631
|
+
const customSubAgent = sysSettings.CustomSubAgent;
|
|
19632
|
+
const configuredModel = sysSettings.SubAgentModel;
|
|
19633
|
+
if (!customSubAgent || !configuredModel || configuredModel === "Default") {
|
|
19634
|
+
return;
|
|
19635
|
+
}
|
|
19636
|
+
const envModel = process.env.SUBAGENT_MODEL ? process.env.SUBAGENT_MODEL.trim() : null;
|
|
19637
|
+
const envProviderRaw = process.env.SUBAGENT_PROVIDER ? process.env.SUBAGENT_PROVIDER.trim() : null;
|
|
19638
|
+
const ALL_PROVIDERS = ["Google", "DeepSeek", "OpenRouter", "NVIDIA", "Mistral"];
|
|
19639
|
+
const normalizeProvider = (pStr) => {
|
|
19640
|
+
if (!pStr) return null;
|
|
19641
|
+
const lower = pStr.toLowerCase();
|
|
19642
|
+
if (lower === "google") return "Google";
|
|
19643
|
+
if (lower === "deepseek") return "DeepSeek";
|
|
19644
|
+
if (lower === "openrouter") return "OpenRouter";
|
|
19645
|
+
if (lower === "nvidia") return "NVIDIA";
|
|
19646
|
+
if (lower === "mistral") return "Mistral";
|
|
19647
|
+
return null;
|
|
19648
|
+
};
|
|
19649
|
+
const envProvider = normalizeProvider(envProviderRaw);
|
|
19650
|
+
if (envModel && !envProvider) {
|
|
19651
|
+
const currentActiveProv = settings.aiProvider || aiProvider || "Google";
|
|
19652
|
+
setMessages((prev) => {
|
|
19653
|
+
setCompletedIndex(prev.length + 1);
|
|
19654
|
+
return [...prev, {
|
|
19655
|
+
id: "subagent-env-noprov-" + Date.now(),
|
|
19656
|
+
role: "system",
|
|
19657
|
+
text: `[SUBAGENT CONFIG] SUBAGENT_MODEL found in ENV but SUBAGENT_PROVIDER is missing/invalid. Active provider (${currentActiveProv}) will be used.`,
|
|
19658
|
+
isMeta: true
|
|
19659
|
+
}];
|
|
19660
|
+
});
|
|
19661
|
+
}
|
|
19662
|
+
if (configuredModel === "ENV") {
|
|
19663
|
+
if (!envModel) {
|
|
19664
|
+
setMessages((prev) => {
|
|
19665
|
+
setCompletedIndex(prev.length + 1);
|
|
19666
|
+
return [...prev, {
|
|
19667
|
+
id: "subagent-model-noenv-" + Date.now(),
|
|
19668
|
+
role: "system",
|
|
19669
|
+
text: "No SubAgent model is found in ENV, Using Deafult until changed",
|
|
19670
|
+
isMeta: true
|
|
19671
|
+
}];
|
|
19672
|
+
});
|
|
19673
|
+
}
|
|
19674
|
+
return;
|
|
19675
|
+
}
|
|
19676
|
+
const currentProvider = settings.aiProvider || aiProvider || "Google";
|
|
19677
|
+
const currentTier = settings.apiTier || apiTier || "Free";
|
|
19678
|
+
const quotasObj = settings.quotas || quotas || {};
|
|
19679
|
+
const availableModelNamesSet = /* @__PURE__ */ new Set();
|
|
19680
|
+
const currentModelsRaw = getModels(currentProvider, currentTier) || [];
|
|
19681
|
+
currentModelsRaw.forEach((m) => {
|
|
19682
|
+
const name = typeof m === "string" ? m : m.cmd || m.name || m.id || String(m);
|
|
19683
|
+
if (name) availableModelNamesSet.add(name);
|
|
19684
|
+
});
|
|
19685
|
+
for (const p of ALL_PROVIDERS) {
|
|
19686
|
+
try {
|
|
19687
|
+
const key = await getProviderAPIKey(p);
|
|
19688
|
+
if (key) {
|
|
19689
|
+
const tier = quotasObj?.providerTiers?.[p] || "Free";
|
|
19690
|
+
const pModels = getModels(p, tier) || [];
|
|
19691
|
+
pModels.forEach((m) => {
|
|
19692
|
+
const name = typeof m === "string" ? m : m.cmd || m.name || m.id || String(m);
|
|
19693
|
+
if (name) availableModelNamesSet.add(name);
|
|
19694
|
+
});
|
|
19695
|
+
}
|
|
19696
|
+
} catch (e) {
|
|
19697
|
+
}
|
|
19698
|
+
}
|
|
19699
|
+
const isModelAvailable = availableModelNamesSet.has(configuredModel);
|
|
19700
|
+
if (envModel) {
|
|
19701
|
+
if (envModel !== configuredModel) {
|
|
19702
|
+
setMessages((prev) => {
|
|
19703
|
+
setCompletedIndex(prev.length + 1);
|
|
19704
|
+
return [...prev, {
|
|
19705
|
+
id: "subagent-model-env-" + Date.now(),
|
|
19706
|
+
role: "system",
|
|
19707
|
+
text: "Current Seleted Sub-Agent model is not available in this provider. Using model from ENV unless changed.",
|
|
19708
|
+
isMeta: true
|
|
19709
|
+
}];
|
|
19710
|
+
});
|
|
19711
|
+
}
|
|
19712
|
+
} else if (!isModelAvailable) {
|
|
19713
|
+
setMessages((prev) => {
|
|
19714
|
+
setCompletedIndex(prev.length + 1);
|
|
19715
|
+
return [...prev, {
|
|
19716
|
+
id: "subagent-model-err-" + Date.now(),
|
|
19717
|
+
role: "system",
|
|
19718
|
+
text: "Current Seleted Sub-Agent model is not available in this provider. Using Default until changed",
|
|
19719
|
+
isMeta: true
|
|
19720
|
+
}];
|
|
19721
|
+
});
|
|
19722
|
+
}
|
|
19723
|
+
} catch (err) {
|
|
19724
|
+
}
|
|
19725
|
+
};
|
|
19726
|
+
checkSubAgentModelOnStartup();
|
|
19727
|
+
}, []);
|
|
19175
19728
|
const parsedArgs = useMemo2(() => {
|
|
19176
19729
|
const parsed = {};
|
|
19177
19730
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -19441,6 +19994,7 @@ function App({ args = [] }) {
|
|
|
19441
19994
|
const [monthlyUsage, setMonthlyUsage] = useState15(null);
|
|
19442
19995
|
const [customPeriodUsage, setCustomPeriodUsage] = useState15(null);
|
|
19443
19996
|
const [statsMode, setStatsMode] = useState15("daily");
|
|
19997
|
+
const [statsScrollOffset, setStatsScrollOffset] = useState15(0);
|
|
19444
19998
|
const PLAYGROUND_CHAT_ID = "flow-playground";
|
|
19445
19999
|
const [chatId, setChatId] = useState15(args.includes("--playground") ? PLAYGROUND_CHAT_ID : generateChatId());
|
|
19446
20000
|
useEffect12(() => {
|
|
@@ -19615,7 +20169,7 @@ function App({ args = [] }) {
|
|
|
19615
20169
|
useEffect12(() => setEscPressCount(0), [input]);
|
|
19616
20170
|
const [messages, rawSetMessages] = useState15(() => {
|
|
19617
20171
|
const logoMsg = { id: "logo-" + Date.now(), role: "system", isLogo: true, isMeta: true };
|
|
19618
|
-
const isHomeDir = process.cwd() ===
|
|
20172
|
+
const isHomeDir = process.cwd() === os4.homedir();
|
|
19619
20173
|
const isSystemDir = (() => {
|
|
19620
20174
|
const cwd = process.cwd().toLowerCase();
|
|
19621
20175
|
if (process.platform === "win32") {
|
|
@@ -19642,7 +20196,7 @@ function App({ args = [] }) {
|
|
|
19642
20196
|
id: "home-warning",
|
|
19643
20197
|
role: "system",
|
|
19644
20198
|
text: `[SECURITY ALERT] HOME DIRECTORY DETECTED`,
|
|
19645
|
-
subText: `You are currently in ${
|
|
20199
|
+
subText: `You are currently in ${os4.homedir()}. Working here is high-risk as the agent may modify system-sensitive configurations. Please open FluxFlow in project folder.`,
|
|
19646
20200
|
isHomeWarning: true
|
|
19647
20201
|
});
|
|
19648
20202
|
}
|
|
@@ -19821,10 +20375,20 @@ function App({ args = [] }) {
|
|
|
19821
20375
|
if (prev === "modelBreakdown") return "daily";
|
|
19822
20376
|
return prev === "daily" ? "monthly" : "daily";
|
|
19823
20377
|
});
|
|
20378
|
+
setStatsScrollOffset(0);
|
|
19824
20379
|
return;
|
|
19825
20380
|
}
|
|
19826
20381
|
if (key.space || inputText === " ") {
|
|
19827
20382
|
setStatsMode((prev) => prev === "modelBreakdown" ? "daily" : "modelBreakdown");
|
|
20383
|
+
setStatsScrollOffset(0);
|
|
20384
|
+
return;
|
|
20385
|
+
}
|
|
20386
|
+
if (key.upArrow) {
|
|
20387
|
+
setStatsScrollOffset((prev) => Math.max(0, prev - 1));
|
|
20388
|
+
return;
|
|
20389
|
+
}
|
|
20390
|
+
if (key.downArrow) {
|
|
20391
|
+
setStatsScrollOffset((prev) => Math.min(maxScrollRef.current, prev + 1));
|
|
19828
20392
|
return;
|
|
19829
20393
|
}
|
|
19830
20394
|
}
|
|
@@ -22619,13 +23183,13 @@ Selection: ${val}`,
|
|
|
22619
23183
|
const limitsNotSet = !usingProviderBudgets && (shouldClearValue(reqLimit) || shouldClearValue(tokenLimit) || shouldClearValue(monthlyLimit));
|
|
22620
23184
|
let resetInfo = "";
|
|
22621
23185
|
if (quotas.resetMode === "Custom") {
|
|
22622
|
-
const
|
|
23186
|
+
const today2 = /* @__PURE__ */ new Date();
|
|
22623
23187
|
const resetDay = quotas.resetDay || 1;
|
|
22624
|
-
let resetMonth =
|
|
22625
|
-
if (
|
|
23188
|
+
let resetMonth = today2.getMonth();
|
|
23189
|
+
if (today2.getDate() >= resetDay) {
|
|
22626
23190
|
resetMonth += 1;
|
|
22627
23191
|
}
|
|
22628
|
-
const resetDate = new Date(
|
|
23192
|
+
const resetDate = new Date(today2.getFullYear(), resetMonth, resetDay);
|
|
22629
23193
|
const monthName = resetDate.toLocaleString("default", { month: "short" });
|
|
22630
23194
|
resetInfo = `${monthName}-${resetDay}`;
|
|
22631
23195
|
}
|
|
@@ -22757,10 +23321,62 @@ Selection: ${val}`,
|
|
|
22757
23321
|
const imageCreditsLabel = statsMode === "monthly" ? "Image Credits:" : "Image Credits:";
|
|
22758
23322
|
const codeChangesLabel = statsMode === "monthly" ? "Code Changes:" : "Code Changes:";
|
|
22759
23323
|
const toolCallsLabel = statsMode === "monthly" ? "Tool Calls:" : "Tool Calls:";
|
|
22760
|
-
|
|
22761
|
-
|
|
22762
|
-
|
|
22763
|
-
})) : /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.text, bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Session Duration:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Model Requests:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, sessionAgentCalls)), /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB API Time:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Tool Time:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Memory Agent:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, sessionBackgroundCalls)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Tokens Consumed:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Active Context:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionStats.tokens))), sessionTotalTokens > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Input Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalTokens - sessionTotalCandidateTokens))), sessionTotalCachedTokens > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React16.createElement(Box14, { width: 21 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Cached:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalCachedTokens))), sessionTotalCandidateTokens > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Output Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalCandidateTokens)))), sessionImageCount > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Images Made:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, sessionImageCount)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Image Credits:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Code Changes (Sess):")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "+", runtimeSession.linesAdded), " ", /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "-", runtimeSession.linesRemoved))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Tool Calls (Sess):")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, runtimeSession.toolSuccess + runtimeSession.toolFailure + runtimeSession.toolDenied, " ( "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "\u2714 ", runtimeSession.toolSuccess), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.warning || "yellow" }, "\u{1F6C7} ", runtimeSession.toolDenied), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "\u2718 ", runtimeSession.toolFailure), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " )"))), /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.text, bold: true, underline: true }, trackerTitle), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, timeLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatDuration(u?.duration || 0))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Model Requests:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, u?.agent || 0)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Memory Agent:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, u?.background || 0)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, tokensLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(u?.tokens || 0))), (u?.tokens || 0) > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Input Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens((u?.tokens || 0) - (u?.candidateTokens || 0)))), (u?.cachedTokens || 0) > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React16.createElement(Box14, { width: 21 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Cached:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(u.cachedTokens))), (u?.candidateTokens || 0) > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Output Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(u.candidateTokens)))), (u?.imageCalls?.length || 0) > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, imagesLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, u.imageCalls.length)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, imageCreditsLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, Number(((u.imageCalls.reduce((sum, c) => sum + c.cost, 0) || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, codeChangesLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "+", u?.linesAdded || 0), " ", /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "-", u?.linesRemoved || 0))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, toolCallsLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, (u?.toolSuccess || 0) + (u?.toolFailure || 0) + (u?.toolDenied || 0), " ( "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "\u2714 ", u?.toolSuccess || 0), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.warning || "yellow" }, "\u{1F6C7} ", u?.toolDenied || 0), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "\u2718 ", u?.toolFailure || 0), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " )")))), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted, dimColor: true, marginTop: 1, italic: true }, "(Press TAB to toggle Daily/Monthly views, SPACE for Model Breakdown, ESC to return)"));
|
|
23324
|
+
const maxRows = Math.max(4, (stdout?.rows || terminalSize?.rows || 24) - 15);
|
|
23325
|
+
const renderLeaderRow = (key, leftText, rightText, leftColor, rightColor, indent = 0, isBold = false) => {
|
|
23326
|
+
const cols = stdout?.columns || terminalSize?.columns || 80;
|
|
23327
|
+
const boxWidth = Math.min(125, cols - 2);
|
|
23328
|
+
const lineWidth = Math.max(20, boxWidth - 6);
|
|
23329
|
+
const maxLeftLen = Math.max(5, lineWidth - indent - rightText.length - 5);
|
|
23330
|
+
let cleanLeftText = leftText;
|
|
23331
|
+
if (cleanLeftText.length > maxLeftLen) {
|
|
23332
|
+
cleanLeftText = cleanLeftText.substring(0, maxLeftLen - 1) + "\u2026";
|
|
23333
|
+
}
|
|
23334
|
+
const dotsCount = Math.max(2, lineWidth - indent - cleanLeftText.length - rightText.length - 2);
|
|
23335
|
+
const dotsStr = " " + ".".repeat(dotsCount) + " ";
|
|
23336
|
+
const indentStr = " ".repeat(indent);
|
|
23337
|
+
return /* @__PURE__ */ React16.createElement(Box14, { key, width: lineWidth }, /* @__PURE__ */ React16.createElement(Text16, { wrap: "truncate" }, /* @__PURE__ */ React16.createElement(Text16, null, indentStr), /* @__PURE__ */ React16.createElement(Text16, { color: leftColor, bold: isBold }, cleanLeftText), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted, dimColor: true }, dotsStr), /* @__PURE__ */ React16.createElement(Text16, { color: rightColor, bold: isBold }, rightText)));
|
|
23338
|
+
};
|
|
23339
|
+
const breakdownRows = [];
|
|
23340
|
+
if (!monthlyUsage?.models || Object.keys(monthlyUsage.models).length === 0) {
|
|
23341
|
+
breakdownRows.push(
|
|
23342
|
+
/* @__PURE__ */ React16.createElement(Box14, { key: "empty", marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted, italic: true }, "No model token usage recorded in the last 30 days."))
|
|
23343
|
+
);
|
|
23344
|
+
} else {
|
|
23345
|
+
Object.entries(monthlyUsage.models).forEach(([provider, models], pIdx) => {
|
|
23346
|
+
const providerTotalTokens = Object.values(models).reduce((sum, m) => sum + (m.tokens || 0), 0);
|
|
23347
|
+
if (pIdx > 0) {
|
|
23348
|
+
breakdownRows.push(/* @__PURE__ */ React16.createElement(Box14, { key: `space-prov-${provider}` }, /* @__PURE__ */ React16.createElement(Text16, null, " ")));
|
|
23349
|
+
}
|
|
23350
|
+
breakdownRows.push(
|
|
23351
|
+
renderLeaderRow(`prov-${provider}`, `${provider}:`, formatTokens(providerTotalTokens), colors.primary, colors.text, 0, true)
|
|
23352
|
+
);
|
|
23353
|
+
Object.entries(models).forEach(([modelName, stats], mIdx) => {
|
|
23354
|
+
if (mIdx > 0) {
|
|
23355
|
+
breakdownRows.push(/* @__PURE__ */ React16.createElement(Box14, { key: `space-mod-${provider}-${modelName}` }, /* @__PURE__ */ React16.createElement(Text16, null, " ")));
|
|
23356
|
+
}
|
|
23357
|
+
breakdownRows.push(
|
|
23358
|
+
renderLeaderRow(`mod-${provider}-${modelName}`, `\xBB ${modelName}:`, formatTokens(stats.tokens || 0), colors.secondary, colors.text, 2, true)
|
|
23359
|
+
);
|
|
23360
|
+
breakdownRows.push(
|
|
23361
|
+
renderLeaderRow(`in-${provider}-${modelName}`, "\xBB Input Tokens:", formatTokens((stats.tokens || 0) - (stats.candidateTokens || 0)), colors.textMuted, colors.text, 5, false)
|
|
23362
|
+
);
|
|
23363
|
+
if ((stats.cachedTokens || 0) > 0) {
|
|
23364
|
+
breakdownRows.push(
|
|
23365
|
+
renderLeaderRow(`cache-${provider}-${modelName}`, "\xBB Cached:", formatTokens(stats.cachedTokens), colors.textMuted, colors.text, 7, false)
|
|
23366
|
+
);
|
|
23367
|
+
}
|
|
23368
|
+
breakdownRows.push(
|
|
23369
|
+
renderLeaderRow(`out-${provider}-${modelName}`, "\xBB Output Tokens:", formatTokens(stats.candidateTokens || 0), colors.textMuted, colors.text, 5, false)
|
|
23370
|
+
);
|
|
23371
|
+
});
|
|
23372
|
+
});
|
|
23373
|
+
}
|
|
23374
|
+
const totalRows = breakdownRows.length;
|
|
23375
|
+
const maxScroll = Math.max(0, totalRows - maxRows);
|
|
23376
|
+
maxScrollRef.current = maxScroll;
|
|
23377
|
+
const effectiveScroll = Math.min(statsScrollOffset, maxScroll);
|
|
23378
|
+
const visibleRows = breakdownRows.slice(effectiveScroll, effectiveScroll + maxRows);
|
|
23379
|
+
return /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: colors.borderMuted, paddingX: 3, paddingY: 1, paddingBottom: 0, width: Math.min(125, (stdout?.columns || 100) - 2) }, statsMode === "modelBreakdown" ? /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Box14, { justifyContent: "space-between" }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.text, bold: true, underline: true }, "30-DAY MODEL TOKEN BREAKDOWN"), totalRows > maxRows && /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted, dimColor: true }, "[", effectiveScroll + 1, "-", Math.min(totalRows, effectiveScroll + maxRows), " of ", totalRows, "] \u25B2\u25BC")), /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", height: maxRows, marginTop: 1 }, visibleRows)) : /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.text, bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Session Duration:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Model Requests:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, sessionAgentCalls)), /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB API Time:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Tool Time:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Memory Agent:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, sessionBackgroundCalls)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Tokens Consumed:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Active Context:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionStats.tokens))), sessionTotalTokens > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Input Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalTokens - sessionTotalCandidateTokens))), sessionTotalCachedTokens > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React16.createElement(Box14, { width: 21 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Cached:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalCachedTokens))), sessionTotalCandidateTokens > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Output Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalCandidateTokens)))), sessionImageCount > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Images Made:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, sessionImageCount)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Image Credits:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Code Changes (Sess):")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "+", runtimeSession.linesAdded), " ", /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "-", runtimeSession.linesRemoved))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Tool Calls (Sess):")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, runtimeSession.toolSuccess + runtimeSession.toolFailure + runtimeSession.toolDenied, " ( "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "\u2714 ", runtimeSession.toolSuccess), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.warning || "yellow" }, "\u{1F6C7} ", runtimeSession.toolDenied), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "\u2718 ", runtimeSession.toolFailure), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " )"))), /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.text, bold: true, underline: true }, trackerTitle), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, timeLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatDuration(u?.duration || 0))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Model Requests:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, u?.agent || 0)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Memory Agent:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, u?.background || 0)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, tokensLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(u?.tokens || 0))), (u?.tokens || 0) > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Input Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens((u?.tokens || 0) - (u?.candidateTokens || 0)))), (u?.cachedTokens || 0) > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React16.createElement(Box14, { width: 21 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Cached:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(u.cachedTokens))), (u?.candidateTokens || 0) > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Output Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(u.candidateTokens)))), (u?.imageCalls?.length || 0) > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, imagesLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, u.imageCalls.length)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, imageCreditsLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, Number(((u.imageCalls.reduce((sum, c) => sum + c.cost, 0) || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, codeChangesLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "+", u?.linesAdded || 0), " ", /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "-", u?.linesRemoved || 0))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, toolCallsLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, (u?.toolSuccess || 0) + (u?.toolFailure || 0) + (u?.toolDenied || 0), " ( "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "\u2714 ", u?.toolSuccess || 0), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.warning || "yellow" }, "\u{1F6C7} ", u?.toolDenied || 0), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "\u2718 ", u?.toolFailure || 0), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " )")))), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted, dimColor: true, italic: true }, "\n", "(Press TAB to toggle Daily/Monthly views, SPACE for Model Breakdown, ESC to return)"));
|
|
22764
23380
|
}
|
|
22765
23381
|
case "dynamicDirDanger":
|
|
22766
23382
|
return /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: colors.borderMuted, paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.warning || "yellow", bold: true, underline: true }, "DYNAMIC DIRECTORY AWARENESS"), /* @__PURE__ */ React16.createElement(Text16, { marginTop: 1, color: colors.text }, "Enabling this keeps the agent aware of filesystem state in real time, but may reduce prompt cache efficiency."), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, "\n", "RECOMMENDED SCENARIOS TO TURN ON:"), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\u2022 Repo is small."), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\u2022 The task benefits from real-time filesystem awareness."), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\u2022 Files are often created, renamed, or deleted."), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\u2022 You know exactly what you're signing up for."), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\u2022 You don't have conflicting decisions regarding token bills."), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\u2022 You want to see your wallet crying at 3am."), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(
|
|
@@ -23565,7 +24181,7 @@ var init_app = __esm({
|
|
|
23565
24181
|
};
|
|
23566
24182
|
getKeybindingsPath = (ideName) => {
|
|
23567
24183
|
const dirName = getIDEDirName(ideName);
|
|
23568
|
-
const home =
|
|
24184
|
+
const home = os4.homedir();
|
|
23569
24185
|
if (process.platform === "win32") {
|
|
23570
24186
|
const appData = process.env.APPDATA;
|
|
23571
24187
|
if (!appData) return null;
|
|
@@ -23824,10 +24440,10 @@ var init_app = __esm({
|
|
|
23824
24440
|
// src/cli.jsx
|
|
23825
24441
|
import { spawn as spawn3 } from "child_process";
|
|
23826
24442
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
23827
|
-
import
|
|
24443
|
+
import os5 from "os";
|
|
23828
24444
|
import dotenv2 from "dotenv";
|
|
23829
24445
|
dotenv2.config({ quiet: true });
|
|
23830
|
-
var totalSystemRamBytes =
|
|
24446
|
+
var totalSystemRamBytes = os5.totalmem();
|
|
23831
24447
|
var totalSystemRamMB = totalSystemRamBytes / (1024 * 1024);
|
|
23832
24448
|
var SAFETY_MARGIN = 0.5;
|
|
23833
24449
|
var calculatedLimit = Math.floor(totalSystemRamMB * SAFETY_MARGIN);
|