openfox 2.0.14 → 2.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chat-handler-ITXCBFJK.js → chat-handler-PC6OVDUR.js} +8 -6
- package/dist/{chunk-7GJ6XYAF.js → chunk-63UEI4AF.js} +20 -16
- package/dist/{chunk-4U45A7B3.js → chunk-DQ6SV26Y.js} +111 -45
- package/dist/{chunk-3QB2RMX2.js → chunk-F4PMNP7S.js} +2 -2
- package/dist/{chunk-TIKQWNYK.js → chunk-J7KOV4ST.js} +2 -2
- package/dist/{chunk-4ZTQO5JP.js → chunk-JO6RF2U2.js} +463 -15
- package/dist/{chunk-LNEBVOH6.js → chunk-OUK5IW26.js} +6 -6
- package/dist/{chunk-PP6VQXQW.js → chunk-SNQT7LNU.js} +2 -1
- package/dist/{chunk-4W2Z4B5U.js → chunk-WOTBK3QQ.js} +36 -41
- package/dist/{chunk-5BDVM6YI.js → chunk-YD6NDTKF.js} +1 -1
- package/dist/cli/dev.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/{config-YFHA5MWV.js → config-Z66BQTNX.js} +2 -2
- package/dist/{orchestrator-VP74KOXI.js → orchestrator-3SB2BMQ7.js} +7 -5
- package/dist/package.json +3 -2
- package/dist/{processor-CCXZYLX6.js → processor-KWPYXPL7.js} +8 -6
- package/dist/{protocol-BE5dRtYw.d.ts → protocol-BC1QSQ-Y.d.ts} +7 -1
- package/dist/{protocol-YYWMFR35.js → protocol-BKNLAEPJ.js} +3 -3
- package/dist/{provider-QUJQLVOM.js → provider-YBTRC77Y.js} +3 -3
- package/dist/{serve-GA2UIHHB.js → serve-HZXJXK6T.js} +9 -9
- package/dist/server/index.d.ts +19 -1
- package/dist/server/index.js +8 -7
- package/dist/{server-EA6W7YIC.js → server-RYKKAOFF.js} +10 -8
- package/dist/shared/index.d.ts +2 -2
- package/dist/shared/index.js +1 -1
- package/dist/{tools-DUC54GEH.js → tools-Y7ZGLK7A.js} +6 -4
- package/dist/web/assets/{index-D0qVcBva.js → index-BMz5-yAf.js} +31 -31
- package/dist/web/index.html +1 -1
- package/dist/web/sw.js +1 -1
- package/package.json +3 -2
|
@@ -31,6 +31,9 @@ import {
|
|
|
31
31
|
getMaxPerSession,
|
|
32
32
|
getSessionProcessCount
|
|
33
33
|
} from "./chunk-VRGRAQDG.js";
|
|
34
|
+
import {
|
|
35
|
+
createMcpTools
|
|
36
|
+
} from "./chunk-NWO6GRYE.js";
|
|
34
37
|
import {
|
|
35
38
|
getCurrentContextWindowId,
|
|
36
39
|
getCurrentWindowMessageOptions,
|
|
@@ -52,7 +55,7 @@ import {
|
|
|
52
55
|
createChatMessageUpdatedMessage,
|
|
53
56
|
createChatPathConfirmationMessage,
|
|
54
57
|
createQueueStateMessage
|
|
55
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-F4PMNP7S.js";
|
|
56
59
|
import {
|
|
57
60
|
AskUserInterrupt,
|
|
58
61
|
askUserTool
|
|
@@ -62,6 +65,10 @@ import {
|
|
|
62
65
|
deleteSetting,
|
|
63
66
|
getSetting
|
|
64
67
|
} from "./chunk-RFNEDBVO.js";
|
|
68
|
+
import {
|
|
69
|
+
loadGlobalConfig,
|
|
70
|
+
saveGlobalConfig
|
|
71
|
+
} from "./chunk-SNQT7LNU.js";
|
|
65
72
|
import {
|
|
66
73
|
getGlobalConfigDir
|
|
67
74
|
} from "./chunk-CQGTEGKL.js";
|
|
@@ -602,6 +609,182 @@ function isNodeError(error) {
|
|
|
602
609
|
return error instanceof Error && "code" in error;
|
|
603
610
|
}
|
|
604
611
|
|
|
612
|
+
// src/server/utils/encoding.ts
|
|
613
|
+
import { detect } from "jschardet";
|
|
614
|
+
import * as iconv from "iconv-lite";
|
|
615
|
+
function detectEncoding(buffer) {
|
|
616
|
+
if (buffer.length === 0) {
|
|
617
|
+
return { encoding: "utf-8", confidence: 1, bomSize: 0 };
|
|
618
|
+
}
|
|
619
|
+
const bomSize = detectBOM(buffer);
|
|
620
|
+
const bomStripped = bomSize > 0 ? buffer.subarray(bomSize) : buffer;
|
|
621
|
+
if (bomSize > 0) {
|
|
622
|
+
const bomEncoding = bomEncodingForSize(buffer);
|
|
623
|
+
return { encoding: bomEncoding, confidence: 1, bomSize };
|
|
624
|
+
}
|
|
625
|
+
if (isValidUtf8(bomStripped)) {
|
|
626
|
+
return { encoding: "utf-8", confidence: 0.95, bomSize: 0 };
|
|
627
|
+
}
|
|
628
|
+
const detected = detect(bomStripped);
|
|
629
|
+
if (detected && detected.encoding && detected.confidence > 0.2) {
|
|
630
|
+
return { encoding: normalizeEncoding(detected.encoding), confidence: detected.confidence, bomSize: 0 };
|
|
631
|
+
}
|
|
632
|
+
return { encoding: "ISO-8859-1", confidence: 0.1, bomSize: 0 };
|
|
633
|
+
}
|
|
634
|
+
function detectBOM(buffer) {
|
|
635
|
+
if (buffer.length >= 4 && buffer[0] === 0 && buffer[1] === 0 && buffer[2] === 254 && buffer[3] === 255)
|
|
636
|
+
return 4;
|
|
637
|
+
if (buffer.length >= 4 && buffer[0] === 255 && buffer[1] === 254 && buffer[2] === 0 && buffer[3] === 0)
|
|
638
|
+
return 4;
|
|
639
|
+
if (buffer.length >= 2 && buffer[0] === 254 && buffer[1] === 255) return 2;
|
|
640
|
+
if (buffer.length >= 2 && buffer[0] === 255 && buffer[1] === 254) return 2;
|
|
641
|
+
if (buffer.length >= 3 && buffer[0] === 239 && buffer[1] === 187 && buffer[2] === 191) return 3;
|
|
642
|
+
return 0;
|
|
643
|
+
}
|
|
644
|
+
function bomEncodingForSize(buffer) {
|
|
645
|
+
if (buffer.length >= 2) {
|
|
646
|
+
if (buffer[0] === 254 && buffer[1] === 255) return "utf-16be";
|
|
647
|
+
if (buffer[0] === 255 && buffer[1] === 254) {
|
|
648
|
+
if (buffer.length >= 4 && buffer[2] === 0 && buffer[3] === 0) return "utf-32";
|
|
649
|
+
return "utf-16le";
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
if (buffer.length >= 3 && buffer[0] === 239 && buffer[1] === 187 && buffer[2] === 191) return "utf-8";
|
|
653
|
+
if (buffer.length >= 4 && buffer[0] === 0 && buffer[1] === 0 && buffer[2] === 254 && buffer[3] === 255)
|
|
654
|
+
return "utf-32be";
|
|
655
|
+
return "utf-8";
|
|
656
|
+
}
|
|
657
|
+
function isValidUtf8(buffer) {
|
|
658
|
+
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
659
|
+
try {
|
|
660
|
+
decoder.decode(buffer);
|
|
661
|
+
return true;
|
|
662
|
+
} catch {
|
|
663
|
+
return false;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
function normalizeEncoding(enc) {
|
|
667
|
+
const lower = enc.toLowerCase().replace(/_/g, "-");
|
|
668
|
+
const map = {
|
|
669
|
+
"utf-8": "utf-8",
|
|
670
|
+
utf8: "utf-8",
|
|
671
|
+
ascii: "utf-8",
|
|
672
|
+
"iso-8859-1": "ISO-8859-1",
|
|
673
|
+
"iso8859-1": "ISO-8859-1",
|
|
674
|
+
latin1: "ISO-8859-1",
|
|
675
|
+
"windows-1252": "windows-1252",
|
|
676
|
+
"shift-jis": "Shift_JIS",
|
|
677
|
+
shift_jis: "Shift_JIS",
|
|
678
|
+
"euc-jp": "EUC-JP",
|
|
679
|
+
"euc-kr": "EUC-KR",
|
|
680
|
+
gb2312: "GB2312",
|
|
681
|
+
gb18030: "GB18030",
|
|
682
|
+
big5: "Big5",
|
|
683
|
+
"utf-16": "utf-16le",
|
|
684
|
+
"utf-16le": "utf-16le",
|
|
685
|
+
"utf-16be": "utf-16be",
|
|
686
|
+
"utf-32": "utf-32le",
|
|
687
|
+
"utf-32le": "utf-32le",
|
|
688
|
+
"utf-32be": "utf-32be",
|
|
689
|
+
"koi8-r": "KOI8-R",
|
|
690
|
+
"koi8-u": "KOI8-U"
|
|
691
|
+
};
|
|
692
|
+
return map[lower] ?? enc;
|
|
693
|
+
}
|
|
694
|
+
function decodeContent(buffer, encoding) {
|
|
695
|
+
const bomSize = detectBOM(buffer);
|
|
696
|
+
const contentBuf = bomSize > 0 ? buffer.subarray(bomSize) : buffer;
|
|
697
|
+
const normalized = normalizeEncoding(encoding);
|
|
698
|
+
if (normalized === "utf-8") {
|
|
699
|
+
return contentBuf.toString("utf-8");
|
|
700
|
+
}
|
|
701
|
+
if (normalized === "utf-16le") {
|
|
702
|
+
return contentBuf.toString("utf-16le");
|
|
703
|
+
}
|
|
704
|
+
if (normalized === "utf-16be") {
|
|
705
|
+
return swapUtf16Endianness(contentBuf).toString("utf-16le");
|
|
706
|
+
}
|
|
707
|
+
if (normalized === "utf-32le") {
|
|
708
|
+
return utf32ToString(contentBuf, true);
|
|
709
|
+
}
|
|
710
|
+
if (normalized === "utf-32be") {
|
|
711
|
+
return utf32ToString(contentBuf, false);
|
|
712
|
+
}
|
|
713
|
+
return iconv.decode(contentBuf, normalized);
|
|
714
|
+
}
|
|
715
|
+
function encodeContent(content, encoding, addBom = false) {
|
|
716
|
+
const normalized = normalizeEncoding(encoding);
|
|
717
|
+
let encoded;
|
|
718
|
+
if (normalized === "utf-8") {
|
|
719
|
+
encoded = Buffer.from(content, "utf-8");
|
|
720
|
+
} else if (normalized === "utf-16le") {
|
|
721
|
+
encoded = Buffer.from(content, "utf-16le");
|
|
722
|
+
} else if (normalized === "utf-16be") {
|
|
723
|
+
encoded = swapUtf16Endianness(Buffer.from(content, "utf-16le"));
|
|
724
|
+
} else if (normalized === "utf-32le") {
|
|
725
|
+
encoded = stringToUtf32(content, true);
|
|
726
|
+
} else if (normalized === "utf-32be") {
|
|
727
|
+
encoded = stringToUtf32(content, false);
|
|
728
|
+
} else {
|
|
729
|
+
encoded = iconv.encode(content, normalized);
|
|
730
|
+
}
|
|
731
|
+
if (addBom) {
|
|
732
|
+
const bom = bomForEncoding(normalized);
|
|
733
|
+
if (bom) {
|
|
734
|
+
encoded = Buffer.concat([bom, encoded]);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
return encoded;
|
|
738
|
+
}
|
|
739
|
+
function bomForEncoding(encoding) {
|
|
740
|
+
switch (encoding) {
|
|
741
|
+
case "utf-8":
|
|
742
|
+
return Buffer.from([239, 187, 191]);
|
|
743
|
+
case "utf-16le":
|
|
744
|
+
return Buffer.from([255, 254]);
|
|
745
|
+
case "utf-16be":
|
|
746
|
+
return Buffer.from([254, 255]);
|
|
747
|
+
case "utf-32le":
|
|
748
|
+
return Buffer.from([255, 254, 0, 0]);
|
|
749
|
+
case "utf-32be":
|
|
750
|
+
return Buffer.from([0, 0, 254, 255]);
|
|
751
|
+
default:
|
|
752
|
+
return null;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
function swapUtf16Endianness(buf) {
|
|
756
|
+
const out = Buffer.alloc(buf.length);
|
|
757
|
+
for (let i = 0; i + 1 < buf.length; i += 2) {
|
|
758
|
+
out[i] = buf[i + 1];
|
|
759
|
+
out[i + 1] = buf[i];
|
|
760
|
+
}
|
|
761
|
+
return out;
|
|
762
|
+
}
|
|
763
|
+
function utf32ToString(buffer, littleEndian) {
|
|
764
|
+
const chars = [];
|
|
765
|
+
for (let i = 0; i + 3 < buffer.length; i += 4) {
|
|
766
|
+
const code = littleEndian ? buffer.readUInt32LE(i) : buffer.readUInt32BE(i);
|
|
767
|
+
if (code > 1114111) continue;
|
|
768
|
+
chars.push(String.fromCodePoint(code));
|
|
769
|
+
}
|
|
770
|
+
return chars.join("");
|
|
771
|
+
}
|
|
772
|
+
function stringToUtf32(str, littleEndian) {
|
|
773
|
+
const codes = [];
|
|
774
|
+
for (const ch of str) {
|
|
775
|
+
codes.push(ch.codePointAt(0));
|
|
776
|
+
}
|
|
777
|
+
const buf = Buffer.alloc(codes.length * 4);
|
|
778
|
+
for (let i = 0; i < codes.length; i++) {
|
|
779
|
+
if (littleEndian) {
|
|
780
|
+
buf.writeUInt32LE(codes[i], i * 4);
|
|
781
|
+
} else {
|
|
782
|
+
buf.writeUInt32BE(codes[i], i * 4);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
return buf;
|
|
786
|
+
}
|
|
787
|
+
|
|
605
788
|
// src/server/tools/read.ts
|
|
606
789
|
var IMAGE_MIME_TYPES = {
|
|
607
790
|
".png": "image/png",
|
|
@@ -752,7 +935,8 @@ var readFileTool = createTool(
|
|
|
752
935
|
}
|
|
753
936
|
});
|
|
754
937
|
}
|
|
755
|
-
const
|
|
938
|
+
const { encoding, confidence } = detectEncoding(rawBuffer);
|
|
939
|
+
const content = decodeContent(rawBuffer, encoding);
|
|
756
940
|
const lines = content.split("\n");
|
|
757
941
|
const totalLines = lines.length;
|
|
758
942
|
const startLine = Math.max(1, offset);
|
|
@@ -774,7 +958,13 @@ var readFileTool = createTool(
|
|
|
774
958
|
if (contentHash2) {
|
|
775
959
|
context.sessionManager.recordFileRead(context.sessionId, fullPath, contentHash2);
|
|
776
960
|
}
|
|
777
|
-
return helpers.success(output, truncated
|
|
961
|
+
return helpers.success(output, truncated, {
|
|
962
|
+
metadata: {
|
|
963
|
+
encoding,
|
|
964
|
+
confidence: Math.round(confidence * 100) / 100,
|
|
965
|
+
lineCount: totalLines
|
|
966
|
+
}
|
|
967
|
+
});
|
|
778
968
|
}
|
|
779
969
|
);
|
|
780
970
|
|
|
@@ -806,6 +996,14 @@ function formatDiagnosticsForLLM(diagnostics) {
|
|
|
806
996
|
}
|
|
807
997
|
return output;
|
|
808
998
|
}
|
|
999
|
+
function appendLspInstallHint(output, lspManager, path) {
|
|
1000
|
+
if (!lspManager) return output;
|
|
1001
|
+
const hint = lspManager.getInstallHint(path);
|
|
1002
|
+
if (!hint) return output;
|
|
1003
|
+
return output + `
|
|
1004
|
+
|
|
1005
|
+
\u26A0\uFE0F Language server not installed. To enable diagnostics: \`${hint}\``;
|
|
1006
|
+
}
|
|
809
1007
|
|
|
810
1008
|
// src/server/tools/write.ts
|
|
811
1009
|
var writeFileTool = createTool(
|
|
@@ -825,6 +1023,10 @@ var writeFileTool = createTool(
|
|
|
825
1023
|
content: {
|
|
826
1024
|
type: "string",
|
|
827
1025
|
description: "Content to write to the file"
|
|
1026
|
+
},
|
|
1027
|
+
encoding: {
|
|
1028
|
+
type: "string",
|
|
1029
|
+
description: 'Optional file encoding (e.g. "ISO-8859-1", "windows-1252", "utf-16"). Defaults to "utf-8". Use the encoding reported by read_file to match project conventions.'
|
|
828
1030
|
}
|
|
829
1031
|
},
|
|
830
1032
|
required: ["path", "content"]
|
|
@@ -841,14 +1043,17 @@ var writeFileTool = createTool(
|
|
|
841
1043
|
}
|
|
842
1044
|
const dir = dirname(fullPath);
|
|
843
1045
|
await mkdir(dir, { recursive: true });
|
|
844
|
-
|
|
1046
|
+
const encoding = args.encoding ?? "utf-8";
|
|
1047
|
+
const encoded = encodeContent(args.content, encoding);
|
|
1048
|
+
await writeFile(fullPath, encoded);
|
|
845
1049
|
const lineCount = args.content.split("\n").length;
|
|
846
|
-
const byteCount =
|
|
1050
|
+
const byteCount = encoded.length;
|
|
847
1051
|
let output = `Successfully wrote ${lineCount} lines (${byteCount} bytes) to ${args.path}`;
|
|
848
1052
|
let diagnostics = [];
|
|
849
1053
|
if (context.lspManager) {
|
|
850
1054
|
diagnostics = await context.lspManager.notifyFileChange(fullPath, args.content);
|
|
851
1055
|
output += formatDiagnosticsForLLM(diagnostics);
|
|
1056
|
+
output = appendLspInstallHint(output, context.lspManager, fullPath);
|
|
852
1057
|
}
|
|
853
1058
|
const newHash = await computeFileHash(fullPath);
|
|
854
1059
|
if (newHash) {
|
|
@@ -1029,12 +1234,14 @@ var editFileTool = createTool(
|
|
|
1029
1234
|
if (!validation.valid) {
|
|
1030
1235
|
return helpers.error(validation.error?.message ?? "File validation failed");
|
|
1031
1236
|
}
|
|
1032
|
-
let
|
|
1237
|
+
let rawBuffer;
|
|
1033
1238
|
try {
|
|
1034
|
-
|
|
1239
|
+
rawBuffer = await readFile3(fullPath);
|
|
1035
1240
|
} catch {
|
|
1036
1241
|
return helpers.error(`File not found: ${args.path}`);
|
|
1037
1242
|
}
|
|
1243
|
+
const { encoding, bomSize } = detectEncoding(rawBuffer);
|
|
1244
|
+
const content = decodeContent(rawBuffer, encoding);
|
|
1038
1245
|
const fileLineEnding = detectLineEnding(content);
|
|
1039
1246
|
const normalizedContent = normalizeToLF(content);
|
|
1040
1247
|
const normalizedOldString = normalizeToLF(args.old_string);
|
|
@@ -1092,16 +1299,18 @@ Make sure whitespace and indentation match exactly.`
|
|
|
1092
1299
|
}
|
|
1093
1300
|
replacedContent = normalizedContent.slice(0, index) + normalizedNewString + normalizedContent.slice(index + normalizedOldString.length);
|
|
1094
1301
|
}
|
|
1095
|
-
const
|
|
1302
|
+
const restoredContent = replacedContent.replace(
|
|
1096
1303
|
/\n/g,
|
|
1097
1304
|
fileLineEnding === "crlf" ? "\r\n" : fileLineEnding === "cr" ? "\r" : "\n"
|
|
1098
1305
|
);
|
|
1099
|
-
|
|
1306
|
+
const encoded = encodeContent(restoredContent, encoding, bomSize > 0);
|
|
1307
|
+
await writeFile2(fullPath, encoded);
|
|
1100
1308
|
let output = `Successfully replaced ${replaceAll ? occurrences : 1} occurrence(s) in ${args.path}`;
|
|
1101
1309
|
let diagnostics = [];
|
|
1102
1310
|
if (context.lspManager) {
|
|
1103
|
-
diagnostics = await context.lspManager.notifyFileChange(fullPath,
|
|
1311
|
+
diagnostics = await context.lspManager.notifyFileChange(fullPath, restoredContent);
|
|
1104
1312
|
output += formatDiagnosticsForLLM(diagnostics);
|
|
1313
|
+
output = appendLspInstallHint(output, context.lspManager, fullPath);
|
|
1105
1314
|
}
|
|
1106
1315
|
const newHash = await computeFileHash(fullPath);
|
|
1107
1316
|
if (newHash) {
|
|
@@ -2677,10 +2886,10 @@ async function describeImageFromDataUrl(dataUrl, visionModel, options) {
|
|
|
2677
2886
|
import { createHash as createHash2 } from "crypto";
|
|
2678
2887
|
async function loadVisionModelFromGlobalConfig() {
|
|
2679
2888
|
try {
|
|
2680
|
-
const { loadGlobalConfig, getVisionFallback } = await import("./config-
|
|
2889
|
+
const { loadGlobalConfig: loadGlobalConfig2, getVisionFallback } = await import("./config-Z66BQTNX.js");
|
|
2681
2890
|
const runtimeConfig = getRuntimeConfig();
|
|
2682
2891
|
const mode = runtimeConfig.mode ?? "production";
|
|
2683
|
-
const globalConfig = await
|
|
2892
|
+
const globalConfig = await loadGlobalConfig2(mode);
|
|
2684
2893
|
const fallback = getVisionFallback(globalConfig);
|
|
2685
2894
|
if (fallback?.enabled && fallback.model) {
|
|
2686
2895
|
return { baseUrl: fallback.url, model: fallback.model, timeout: fallback.timeout * 1e3 };
|
|
@@ -3132,7 +3341,7 @@ var callSubAgentTool = {
|
|
|
3132
3341
|
};
|
|
3133
3342
|
}
|
|
3134
3343
|
try {
|
|
3135
|
-
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-
|
|
3344
|
+
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-Y7ZGLK7A.js");
|
|
3136
3345
|
const toolRegistry = getToolRegistryForAgent2(agentDef);
|
|
3137
3346
|
const turnMetrics = new TurnMetrics();
|
|
3138
3347
|
const result = await executeSubAgent({
|
|
@@ -3919,6 +4128,238 @@ These processes run independently of agent turns and persist across session comp
|
|
|
3919
4128
|
}
|
|
3920
4129
|
);
|
|
3921
4130
|
|
|
4131
|
+
// src/server/chat/dynamic-context.ts
|
|
4132
|
+
import { createHash as createHash3 } from "crypto";
|
|
4133
|
+
function computeDynamicContextHash(instructionContent, skills, toolFingerprint) {
|
|
4134
|
+
const dynamicInputs = JSON.stringify({
|
|
4135
|
+
instructions: instructionContent,
|
|
4136
|
+
skills: skills.map((s) => s.id).sort(),
|
|
4137
|
+
...toolFingerprint ? { tools: toolFingerprint } : {}
|
|
4138
|
+
});
|
|
4139
|
+
return createHash3("sha256").update(dynamicInputs).digest("hex");
|
|
4140
|
+
}
|
|
4141
|
+
function getToolFingerprint(tools) {
|
|
4142
|
+
return tools.map((t) => `${t.function.name}:${JSON.stringify(t.function.parameters)}`).sort().join("|");
|
|
4143
|
+
}
|
|
4144
|
+
async function computeContextHash(sessionManager, sessionId) {
|
|
4145
|
+
const session = sessionManager.requireSession(sessionId);
|
|
4146
|
+
const { content: instructionContent } = await getAllInstructions(session.workdir, session.projectId);
|
|
4147
|
+
const runtimeConfig = getRuntimeConfig();
|
|
4148
|
+
const configDir = getGlobalConfigDir(runtimeConfig.mode ?? "production");
|
|
4149
|
+
const skills = await getEnabledSkillMetadata(configDir, runtimeConfig.workdir);
|
|
4150
|
+
const { createToolRegistry: createToolRegistry2 } = await import("./tools-Y7ZGLK7A.js");
|
|
4151
|
+
const allTools = createToolRegistry2().definitions;
|
|
4152
|
+
const toolFingerprint = getToolFingerprint(allTools);
|
|
4153
|
+
const hash = computeDynamicContextHash(instructionContent, skills, toolFingerprint);
|
|
4154
|
+
return { hash, instructionContent, skills, allTools };
|
|
4155
|
+
}
|
|
4156
|
+
async function applyDynamicContext(sessionManager, sessionId) {
|
|
4157
|
+
const { hash, instructionContent, skills, allTools } = await computeContextHash(sessionManager, sessionId);
|
|
4158
|
+
const allAgents = await loadAllAgentsDefault();
|
|
4159
|
+
const subAgentDefs = getSubAgents(allAgents);
|
|
4160
|
+
const systemPrompt = buildTopLevelSystemPrompt(
|
|
4161
|
+
sessionManager.requireSession(sessionId).workdir,
|
|
4162
|
+
instructionContent || void 0,
|
|
4163
|
+
skills,
|
|
4164
|
+
subAgentDefs
|
|
4165
|
+
);
|
|
4166
|
+
sessionManager.setCachedPrompt(sessionId, systemPrompt, allTools, hash);
|
|
4167
|
+
sessionManager.setDynamicContextChanged(sessionId, false);
|
|
4168
|
+
sessionManager.clearDebugDump(sessionId);
|
|
4169
|
+
logger.debug("applyDynamicContext done", { sessionId, hash, toolCount: allTools.length });
|
|
4170
|
+
}
|
|
4171
|
+
|
|
4172
|
+
// src/server/tools/mcp-config.ts
|
|
4173
|
+
var mcpManagerForTools = null;
|
|
4174
|
+
var mcpConfigMode = "production";
|
|
4175
|
+
var mcpNotifyChanged = null;
|
|
4176
|
+
function setMcpManagerForTools(manager) {
|
|
4177
|
+
mcpManagerForTools = manager;
|
|
4178
|
+
}
|
|
4179
|
+
function setMcpConfigMode(mode) {
|
|
4180
|
+
mcpConfigMode = mode;
|
|
4181
|
+
}
|
|
4182
|
+
function setNotifyMcpServersChanged(fn) {
|
|
4183
|
+
mcpNotifyChanged = fn;
|
|
4184
|
+
}
|
|
4185
|
+
var mcpConfigTool = createTool(
|
|
4186
|
+
"mcp_config",
|
|
4187
|
+
{
|
|
4188
|
+
type: "function",
|
|
4189
|
+
function: {
|
|
4190
|
+
name: "mcp_config",
|
|
4191
|
+
description: "Configure MCP servers (Model Context Protocol). Actions: list (show all servers and tools), add (add a server), remove (delete a server), toggle-tool (enable/disable a tool). Use this when the user asks to add, remove, or configure MCP servers or tools.",
|
|
4192
|
+
parameters: {
|
|
4193
|
+
type: "object",
|
|
4194
|
+
properties: {
|
|
4195
|
+
action: {
|
|
4196
|
+
type: "string",
|
|
4197
|
+
enum: ["list", "add", "remove", "toggle-tool"],
|
|
4198
|
+
description: "Action: list (show servers), add (add new server), remove (delete a server), toggle-tool (enable/disable a tool)"
|
|
4199
|
+
},
|
|
4200
|
+
name: {
|
|
4201
|
+
type: "string",
|
|
4202
|
+
description: "Server name (required for: add, remove, toggle-tool)"
|
|
4203
|
+
},
|
|
4204
|
+
transport: {
|
|
4205
|
+
type: "string",
|
|
4206
|
+
enum: ["stdio", "http"],
|
|
4207
|
+
description: "Transport type (for add). Default: stdio"
|
|
4208
|
+
},
|
|
4209
|
+
command: {
|
|
4210
|
+
type: "string",
|
|
4211
|
+
description: 'Command for stdio transport (e.g. "npx")'
|
|
4212
|
+
},
|
|
4213
|
+
args: {
|
|
4214
|
+
type: "array",
|
|
4215
|
+
items: { type: "string" },
|
|
4216
|
+
description: "Command arguments for stdio transport"
|
|
4217
|
+
},
|
|
4218
|
+
env: {
|
|
4219
|
+
type: "object",
|
|
4220
|
+
additionalProperties: { type: "string" },
|
|
4221
|
+
description: "Environment variables for stdio transport"
|
|
4222
|
+
},
|
|
4223
|
+
url: {
|
|
4224
|
+
type: "string",
|
|
4225
|
+
description: 'Server URL for HTTP transport (e.g. "https://mcp.example.com/mcp")'
|
|
4226
|
+
},
|
|
4227
|
+
headers: {
|
|
4228
|
+
type: "object",
|
|
4229
|
+
additionalProperties: { type: "string" },
|
|
4230
|
+
description: 'HTTP headers for HTTP transport (e.g. {"Authorization": "Bearer xxx"})'
|
|
4231
|
+
},
|
|
4232
|
+
toolName: {
|
|
4233
|
+
type: "string",
|
|
4234
|
+
description: "Tool name to toggle (required for: toggle-tool)"
|
|
4235
|
+
},
|
|
4236
|
+
enabled: {
|
|
4237
|
+
type: "boolean",
|
|
4238
|
+
description: "Whether the tool should be enabled (required for: toggle-tool)"
|
|
4239
|
+
}
|
|
4240
|
+
},
|
|
4241
|
+
required: ["action"]
|
|
4242
|
+
}
|
|
4243
|
+
}
|
|
4244
|
+
},
|
|
4245
|
+
async (args, context, helpers) => {
|
|
4246
|
+
const actionError = validateActionWithPermission(
|
|
4247
|
+
args.action,
|
|
4248
|
+
["list", "add", "remove", "toggle-tool"],
|
|
4249
|
+
"mcp_config",
|
|
4250
|
+
context.permittedActions
|
|
4251
|
+
);
|
|
4252
|
+
if (actionError) return actionError;
|
|
4253
|
+
if (!mcpManagerForTools) {
|
|
4254
|
+
return helpers.error("MCP manager not available");
|
|
4255
|
+
}
|
|
4256
|
+
async function persistAndRebuild(updater) {
|
|
4257
|
+
const globalConfig = await loadGlobalConfig(mcpConfigMode);
|
|
4258
|
+
const mcpServers = { ...globalConfig.mcpServers ?? {} };
|
|
4259
|
+
const updated = updater(mcpServers);
|
|
4260
|
+
await saveGlobalConfig(mcpConfigMode, { ...globalConfig, mcpServers: updated });
|
|
4261
|
+
}
|
|
4262
|
+
async function rebuildTools() {
|
|
4263
|
+
const { setMcpTools: setMcpTools2 } = await import("./tools-Y7ZGLK7A.js");
|
|
4264
|
+
const mcpTools = createMcpTools(mcpManagerForTools);
|
|
4265
|
+
setMcpTools2(mcpTools);
|
|
4266
|
+
}
|
|
4267
|
+
if (args.action === "list") {
|
|
4268
|
+
const servers = mcpManagerForTools.getAllServers();
|
|
4269
|
+
if (servers.length === 0) {
|
|
4270
|
+
return helpers.success("No MCP servers configured.");
|
|
4271
|
+
}
|
|
4272
|
+
const lines = [];
|
|
4273
|
+
for (const server of servers) {
|
|
4274
|
+
const connStr = server.status === "connected" ? "\u25CF" : server.status === "error" ? "\u2717" : "\u25CB";
|
|
4275
|
+
const cmdStr = server.config.command ? `${server.config.command} ${(server.config.args ?? []).join(" ")}` : server.config.url ?? "";
|
|
4276
|
+
lines.push(
|
|
4277
|
+
`${connStr} ${server.name} (${server.config.transport}) \u2014 ${server.status}${server.error ? `: ${server.error}` : ""}`
|
|
4278
|
+
);
|
|
4279
|
+
lines.push(` ${cmdStr}`);
|
|
4280
|
+
lines.push(` ${server.tools.length} tools, ~${server.estimatedTokens} tokens`);
|
|
4281
|
+
const enabledTools = server.tools.filter((t) => t.enabled);
|
|
4282
|
+
const disabledTools = server.tools.filter((t) => !t.enabled);
|
|
4283
|
+
if (enabledTools.length > 0) {
|
|
4284
|
+
lines.push(` Enabled: ${enabledTools.map((t) => t.name).join(", ")}`);
|
|
4285
|
+
}
|
|
4286
|
+
if (disabledTools.length > 0) {
|
|
4287
|
+
lines.push(` Disabled: ${disabledTools.map((t) => t.name).join(", ")}`);
|
|
4288
|
+
}
|
|
4289
|
+
}
|
|
4290
|
+
return helpers.success(lines.join("\n"));
|
|
4291
|
+
}
|
|
4292
|
+
if (args.action === "add") {
|
|
4293
|
+
if (!args.name) return helpers.error("Missing required field: name");
|
|
4294
|
+
if (args.transport === "http") {
|
|
4295
|
+
if (!args.url) return helpers.error("url is required for http transport");
|
|
4296
|
+
} else if (!args.command) {
|
|
4297
|
+
return helpers.error("command is required for stdio transport");
|
|
4298
|
+
}
|
|
4299
|
+
const serverCfg = {
|
|
4300
|
+
transport: args.transport ?? "stdio",
|
|
4301
|
+
...args.command ? { command: args.command } : {},
|
|
4302
|
+
...args.args && args.args.length > 0 ? { args: args.args } : {},
|
|
4303
|
+
...args.env && Object.keys(args.env).length > 0 ? { env: args.env } : {},
|
|
4304
|
+
...args.url ? { url: args.url } : {},
|
|
4305
|
+
...args.headers && Object.keys(args.headers).length > 0 ? { headers: args.headers } : {}
|
|
4306
|
+
};
|
|
4307
|
+
await persistAndRebuild((mcpServers) => {
|
|
4308
|
+
mcpServers[args.name] = serverCfg;
|
|
4309
|
+
return mcpServers;
|
|
4310
|
+
});
|
|
4311
|
+
await mcpManagerForTools.addServer(args.name, serverCfg);
|
|
4312
|
+
await rebuildTools();
|
|
4313
|
+
await applyDynamicContext(context.sessionManager, context.sessionId);
|
|
4314
|
+
mcpNotifyChanged?.(context.sessionId);
|
|
4315
|
+
const server = mcpManagerForTools.getServer(args.name);
|
|
4316
|
+
const toolCount = server?.tools.length ?? 0;
|
|
4317
|
+
return helpers.success(`Added MCP server "${args.name}" (${toolCount} tools discovered).`);
|
|
4318
|
+
}
|
|
4319
|
+
if (args.action === "remove") {
|
|
4320
|
+
if (!args.name) return helpers.error("Missing required field: name");
|
|
4321
|
+
await persistAndRebuild((mcpServers) => {
|
|
4322
|
+
delete mcpServers[args.name];
|
|
4323
|
+
return mcpServers;
|
|
4324
|
+
});
|
|
4325
|
+
mcpManagerForTools.removeServer(args.name);
|
|
4326
|
+
await rebuildTools();
|
|
4327
|
+
await applyDynamicContext(context.sessionManager, context.sessionId);
|
|
4328
|
+
mcpNotifyChanged?.(context.sessionId);
|
|
4329
|
+
return helpers.success(`Removed MCP server "${args.name}".`);
|
|
4330
|
+
}
|
|
4331
|
+
if (args.action === "toggle-tool") {
|
|
4332
|
+
if (!args.name) return helpers.error("Missing required field: name");
|
|
4333
|
+
if (!args.toolName) return helpers.error("Missing required field: toolName");
|
|
4334
|
+
if (args.enabled === void 0) return helpers.error("Missing required field: enabled");
|
|
4335
|
+
const server = mcpManagerForTools.getServer(args.name);
|
|
4336
|
+
const currentDisabled = (server?.tools ?? []).filter((t) => !t.enabled).map((t) => t.name);
|
|
4337
|
+
const afterDisabled = args.enabled ? currentDisabled.filter((n) => n !== args.toolName) : [...currentDisabled, args.toolName];
|
|
4338
|
+
await persistAndRebuild((mcpServers) => {
|
|
4339
|
+
const cfg = mcpServers[args.name];
|
|
4340
|
+
if (cfg) {
|
|
4341
|
+
const updated = { ...cfg };
|
|
4342
|
+
if (afterDisabled.length > 0) {
|
|
4343
|
+
updated.disabledTools = afterDisabled;
|
|
4344
|
+
} else {
|
|
4345
|
+
delete updated.disabledTools;
|
|
4346
|
+
}
|
|
4347
|
+
mcpServers[args.name] = updated;
|
|
4348
|
+
}
|
|
4349
|
+
return mcpServers;
|
|
4350
|
+
});
|
|
4351
|
+
await mcpManagerForTools.setToolEnabled(args.name, args.toolName, args.enabled);
|
|
4352
|
+
await rebuildTools();
|
|
4353
|
+
await applyDynamicContext(context.sessionManager, context.sessionId);
|
|
4354
|
+
mcpNotifyChanged?.(context.sessionId);
|
|
4355
|
+
return helpers.success(
|
|
4356
|
+
`Tool "${args.toolName}" ${args.enabled ? "enabled" : "disabled"} on server "${args.name}".`
|
|
4357
|
+
);
|
|
4358
|
+
}
|
|
4359
|
+
return helpers.error("Unexpected error");
|
|
4360
|
+
}
|
|
4361
|
+
);
|
|
4362
|
+
|
|
3922
4363
|
// src/server/tools/index.ts
|
|
3923
4364
|
function parseToolPermissions(allowedTools) {
|
|
3924
4365
|
const result = {};
|
|
@@ -4075,7 +4516,8 @@ function getAllToolsMap() {
|
|
|
4075
4516
|
webFetchTool,
|
|
4076
4517
|
devServerTool,
|
|
4077
4518
|
stepDoneTool,
|
|
4078
|
-
backgroundProcessTool
|
|
4519
|
+
backgroundProcessTool,
|
|
4520
|
+
mcpConfigTool
|
|
4079
4521
|
].map((t) => [t.name, t]);
|
|
4080
4522
|
const mcpEntries = mcpToolsOverride.map((t) => [t.name, t]);
|
|
4081
4523
|
return new Map([...builtInTools, ...mcpEntries]);
|
|
@@ -4183,6 +4625,12 @@ export {
|
|
|
4183
4625
|
executeSubAgent,
|
|
4184
4626
|
devServerManager,
|
|
4185
4627
|
stepDoneTool,
|
|
4628
|
+
computeDynamicContextHash,
|
|
4629
|
+
getToolFingerprint,
|
|
4630
|
+
applyDynamicContext,
|
|
4631
|
+
setMcpManagerForTools,
|
|
4632
|
+
setMcpConfigMode,
|
|
4633
|
+
setNotifyMcpServersChanged,
|
|
4186
4634
|
parseToolPermissions,
|
|
4187
4635
|
getToolPermissions,
|
|
4188
4636
|
validateToolAction,
|
|
@@ -4192,4 +4640,4 @@ export {
|
|
|
4192
4640
|
getToolRegistryForAgent,
|
|
4193
4641
|
createToolRegistry
|
|
4194
4642
|
};
|
|
4195
|
-
//# sourceMappingURL=chunk-
|
|
4643
|
+
//# sourceMappingURL=chunk-JO6RF2U2.js.map
|
|
@@ -33,7 +33,7 @@ Options:
|
|
|
33
33
|
}
|
|
34
34
|
async function runNetworkSetup(mode) {
|
|
35
35
|
const { loadAuthConfig, saveAuthConfig, encryptPassword } = await import("./auth-56SIRACI.js");
|
|
36
|
-
const { saveGlobalConfig } = await import("./config-
|
|
36
|
+
const { saveGlobalConfig } = await import("./config-Z66BQTNX.js");
|
|
37
37
|
const { getAuthKeyPath } = await import("./paths-X46PPOI2.js");
|
|
38
38
|
const existingAuth = await loadAuthConfig(mode);
|
|
39
39
|
if (existingAuth) {
|
|
@@ -94,7 +94,7 @@ async function runNetworkSetup(mode) {
|
|
|
94
94
|
console.log("\u2713 Configuration saved!\n");
|
|
95
95
|
}
|
|
96
96
|
async function runConfig(mode) {
|
|
97
|
-
const { loadGlobalConfig, getActiveProvider, getDefaultModel } = await import("./config-
|
|
97
|
+
const { loadGlobalConfig, getActiveProvider, getDefaultModel } = await import("./config-Z66BQTNX.js");
|
|
98
98
|
const { getGlobalConfigPath } = await import("./paths-X46PPOI2.js");
|
|
99
99
|
const config = await loadGlobalConfig(mode);
|
|
100
100
|
const configPath = getGlobalConfigPath(mode);
|
|
@@ -152,7 +152,7 @@ async function runCli(options) {
|
|
|
152
152
|
break;
|
|
153
153
|
}
|
|
154
154
|
case "provider": {
|
|
155
|
-
const { runProviderCommand } = await import("./provider-
|
|
155
|
+
const { runProviderCommand } = await import("./provider-YBTRC77Y.js");
|
|
156
156
|
const [, subcommand] = positionals;
|
|
157
157
|
await runProviderCommand(mode, subcommand);
|
|
158
158
|
break;
|
|
@@ -191,12 +191,12 @@ async function runCli(options) {
|
|
|
191
191
|
break;
|
|
192
192
|
}
|
|
193
193
|
default: {
|
|
194
|
-
const { configFileExists } = await import("./config-
|
|
194
|
+
const { configFileExists } = await import("./config-Z66BQTNX.js");
|
|
195
195
|
const configExists = await configFileExists(mode);
|
|
196
196
|
if (!configExists) {
|
|
197
197
|
await runNetworkSetup(mode);
|
|
198
198
|
}
|
|
199
|
-
const { runServe } = await import("./serve-
|
|
199
|
+
const { runServe } = await import("./serve-HZXJXK6T.js");
|
|
200
200
|
const serveOptions = { mode };
|
|
201
201
|
if (values.port) serveOptions.port = parseInt(values.port);
|
|
202
202
|
if (values["no-browser"] === true) serveOptions.openBrowser = false;
|
|
@@ -208,4 +208,4 @@ async function runCli(options) {
|
|
|
208
208
|
export {
|
|
209
209
|
runCli
|
|
210
210
|
};
|
|
211
|
-
//# sourceMappingURL=chunk-
|
|
211
|
+
//# sourceMappingURL=chunk-OUK5IW26.js.map
|
|
@@ -67,6 +67,7 @@ var mcpServerSchema = z.object({
|
|
|
67
67
|
args: z.array(z.string()).optional(),
|
|
68
68
|
env: z.record(z.string(), z.string()).optional(),
|
|
69
69
|
url: z.string().optional(),
|
|
70
|
+
headers: z.record(z.string(), z.string()).optional(),
|
|
70
71
|
disabledTools: z.array(z.string()).optional()
|
|
71
72
|
});
|
|
72
73
|
var defaultVisionFallback = { enabled: false, url: "http://localhost:11434", model: "qwen3.5:0.8b", timeout: 120 };
|
|
@@ -435,4 +436,4 @@ export {
|
|
|
435
436
|
activateProvider,
|
|
436
437
|
mergeConfigs
|
|
437
438
|
};
|
|
438
|
-
//# sourceMappingURL=chunk-
|
|
439
|
+
//# sourceMappingURL=chunk-SNQT7LNU.js.map
|