@probelabs/probe 0.6.0-rc161 → 0.6.0-rc163
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/README.md +89 -0
- package/build/agent/ProbeAgent.js +361 -97
- package/build/agent/contextCompactor.js +271 -0
- package/build/agent/index.js +854 -94
- package/build/agent/schemaUtils.js +81 -0
- package/build/agent/xmlParsingUtils.js +24 -4
- package/build/tools/common.js +16 -1
- package/cjs/agent/ProbeAgent.cjs +889 -144
- package/cjs/index.cjs +889 -144
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +361 -97
- package/src/agent/contextCompactor.js +271 -0
- package/src/agent/index.js +30 -1
- package/src/agent/schemaUtils.js +81 -0
- package/src/agent/xmlParsingUtils.js +24 -4
- package/src/tools/common.js +16 -1
package/build/agent/index.js
CHANGED
|
@@ -552,6 +552,162 @@ var init_BytePairEncodingCore = __esm({
|
|
|
552
552
|
}
|
|
553
553
|
});
|
|
554
554
|
|
|
555
|
+
// node_modules/gpt-tokenizer/esm/functionCalling.js
|
|
556
|
+
function countMessageTokens(message, countStringTokens) {
|
|
557
|
+
let tokens = 0;
|
|
558
|
+
if (message.role) {
|
|
559
|
+
tokens += countStringTokens(message.role);
|
|
560
|
+
}
|
|
561
|
+
if (message.content) {
|
|
562
|
+
tokens += countStringTokens(message.content);
|
|
563
|
+
}
|
|
564
|
+
if (message.name) {
|
|
565
|
+
tokens += countStringTokens(message.name) + MESSAGE_NAME_TOKEN_OVERHEAD;
|
|
566
|
+
}
|
|
567
|
+
if (message.function_call) {
|
|
568
|
+
const { name, arguments: args } = message.function_call;
|
|
569
|
+
if (name) {
|
|
570
|
+
tokens += countStringTokens(name);
|
|
571
|
+
}
|
|
572
|
+
if (args) {
|
|
573
|
+
tokens += countStringTokens(args);
|
|
574
|
+
}
|
|
575
|
+
tokens += FUNCTION_CALL_METADATA_TOKEN_OVERHEAD;
|
|
576
|
+
}
|
|
577
|
+
tokens += MESSAGE_TOKEN_OVERHEAD;
|
|
578
|
+
if (message.role === "function") {
|
|
579
|
+
tokens -= FUNCTION_ROLE_TOKEN_DISCOUNT;
|
|
580
|
+
}
|
|
581
|
+
return tokens;
|
|
582
|
+
}
|
|
583
|
+
function formatObjectProperties(obj, indent, formatType) {
|
|
584
|
+
if (!obj.properties) {
|
|
585
|
+
return "";
|
|
586
|
+
}
|
|
587
|
+
const lines = [];
|
|
588
|
+
const requiredParams = new Set(obj.required ?? []);
|
|
589
|
+
const indentString = " ".repeat(indent);
|
|
590
|
+
for (const [name, param] of Object.entries(obj.properties)) {
|
|
591
|
+
if (param.description && indent < 2) {
|
|
592
|
+
lines.push(`${indentString}// ${param.description}`);
|
|
593
|
+
}
|
|
594
|
+
const isRequired = requiredParams.has(name);
|
|
595
|
+
const formattedType = formatType(param, indent);
|
|
596
|
+
lines.push(`${indentString}${name}${isRequired ? "" : "?"}: ${formattedType},`);
|
|
597
|
+
}
|
|
598
|
+
return lines.join("\n");
|
|
599
|
+
}
|
|
600
|
+
function formatFunctionType(param, indent) {
|
|
601
|
+
switch (param.type) {
|
|
602
|
+
case "string":
|
|
603
|
+
return param.enum?.map((value) => JSON.stringify(value)).join(" | ") ?? "string";
|
|
604
|
+
case "integer":
|
|
605
|
+
case "number":
|
|
606
|
+
return param.enum?.map((value) => `${value}`).join(" | ") ?? "number";
|
|
607
|
+
case "boolean":
|
|
608
|
+
return "boolean";
|
|
609
|
+
case "null":
|
|
610
|
+
return "null";
|
|
611
|
+
case "array":
|
|
612
|
+
return param.items ? `${formatFunctionType(param.items, indent)}[]` : "any[]";
|
|
613
|
+
case "object": {
|
|
614
|
+
const inner = formatObjectProperties(param, indent + 2, formatFunctionType);
|
|
615
|
+
const closingIndent = " ".repeat(indent);
|
|
616
|
+
return `{
|
|
617
|
+
${inner}
|
|
618
|
+
${closingIndent}}`;
|
|
619
|
+
}
|
|
620
|
+
default:
|
|
621
|
+
return "any";
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
function formatFunctionDefinitions(functions) {
|
|
625
|
+
const lines = ["namespace functions {", ""];
|
|
626
|
+
for (const fn of functions) {
|
|
627
|
+
if (fn.description) {
|
|
628
|
+
lines.push(`// ${fn.description}`);
|
|
629
|
+
}
|
|
630
|
+
const { parameters } = fn;
|
|
631
|
+
const properties = parameters?.properties;
|
|
632
|
+
if (!parameters || !properties || Object.keys(properties).length === 0) {
|
|
633
|
+
lines.push(`type ${fn.name} = () => any;`);
|
|
634
|
+
} else {
|
|
635
|
+
lines.push(`type ${fn.name} = (_: {`);
|
|
636
|
+
const formattedProperties = formatObjectProperties(parameters, 0, formatFunctionType);
|
|
637
|
+
if (formattedProperties.length > 0) {
|
|
638
|
+
lines.push(formattedProperties);
|
|
639
|
+
}
|
|
640
|
+
lines.push("}) => any;");
|
|
641
|
+
}
|
|
642
|
+
lines.push("");
|
|
643
|
+
}
|
|
644
|
+
lines.push("} // namespace functions");
|
|
645
|
+
return lines.join("\n");
|
|
646
|
+
}
|
|
647
|
+
function estimateTokensInFunctions(functions, countStringTokens) {
|
|
648
|
+
const formatted = formatFunctionDefinitions(functions);
|
|
649
|
+
let tokens = countStringTokens(formatted);
|
|
650
|
+
tokens += FUNCTION_DEFINITION_TOKEN_OVERHEAD;
|
|
651
|
+
return tokens;
|
|
652
|
+
}
|
|
653
|
+
function padSystemMessage(message, hasFunctions, isSystemPadded) {
|
|
654
|
+
if (!hasFunctions || isSystemPadded || message.role !== "system") {
|
|
655
|
+
return message;
|
|
656
|
+
}
|
|
657
|
+
if (!message.content || message.content.endsWith(NEWLINE)) {
|
|
658
|
+
return message;
|
|
659
|
+
}
|
|
660
|
+
return {
|
|
661
|
+
...message,
|
|
662
|
+
content: `${message.content}${NEWLINE}`
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
function computeChatCompletionTokenCount(request, countStringTokens) {
|
|
666
|
+
const { messages, functions, function_call: functionCall } = request;
|
|
667
|
+
const hasFunctions = Boolean(functions && functions.length > 0);
|
|
668
|
+
let paddedSystem = false;
|
|
669
|
+
let total = 0;
|
|
670
|
+
for (const message of messages) {
|
|
671
|
+
const messageToCount = padSystemMessage(message, hasFunctions, paddedSystem);
|
|
672
|
+
if (messageToCount !== message && message.role === "system") {
|
|
673
|
+
paddedSystem = true;
|
|
674
|
+
} else if (message.role === "system" && hasFunctions && !paddedSystem) {
|
|
675
|
+
paddedSystem = true;
|
|
676
|
+
}
|
|
677
|
+
total += countMessageTokens(messageToCount, countStringTokens);
|
|
678
|
+
}
|
|
679
|
+
total += COMPLETION_REQUEST_TOKEN_OVERHEAD;
|
|
680
|
+
if (hasFunctions && functions) {
|
|
681
|
+
total += estimateTokensInFunctions(functions, countStringTokens);
|
|
682
|
+
if (messages.some((message) => message.role === "system")) {
|
|
683
|
+
total -= SYSTEM_FUNCTION_TOKEN_DEDUCTION;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
if (functionCall && functionCall !== "auto") {
|
|
687
|
+
if (functionCall === "none") {
|
|
688
|
+
total += FUNCTION_CALL_NONE_TOKEN_OVERHEAD;
|
|
689
|
+
} else if (typeof functionCall === "object" && functionCall.name) {
|
|
690
|
+
total += countStringTokens(functionCall.name) + FUNCTION_CALL_NAME_TOKEN_OVERHEAD;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
return total;
|
|
694
|
+
}
|
|
695
|
+
var MESSAGE_TOKEN_OVERHEAD, MESSAGE_NAME_TOKEN_OVERHEAD, FUNCTION_ROLE_TOKEN_DISCOUNT, FUNCTION_CALL_METADATA_TOKEN_OVERHEAD, FUNCTION_DEFINITION_TOKEN_OVERHEAD, COMPLETION_REQUEST_TOKEN_OVERHEAD, FUNCTION_CALL_NAME_TOKEN_OVERHEAD, FUNCTION_CALL_NONE_TOKEN_OVERHEAD, SYSTEM_FUNCTION_TOKEN_DEDUCTION, NEWLINE;
|
|
696
|
+
var init_functionCalling = __esm({
|
|
697
|
+
"node_modules/gpt-tokenizer/esm/functionCalling.js"() {
|
|
698
|
+
MESSAGE_TOKEN_OVERHEAD = 3;
|
|
699
|
+
MESSAGE_NAME_TOKEN_OVERHEAD = 1;
|
|
700
|
+
FUNCTION_ROLE_TOKEN_DISCOUNT = 2;
|
|
701
|
+
FUNCTION_CALL_METADATA_TOKEN_OVERHEAD = 3;
|
|
702
|
+
FUNCTION_DEFINITION_TOKEN_OVERHEAD = 9;
|
|
703
|
+
COMPLETION_REQUEST_TOKEN_OVERHEAD = 3;
|
|
704
|
+
FUNCTION_CALL_NAME_TOKEN_OVERHEAD = 4;
|
|
705
|
+
FUNCTION_CALL_NONE_TOKEN_OVERHEAD = 1;
|
|
706
|
+
SYSTEM_FUNCTION_TOKEN_DEDUCTION = 4;
|
|
707
|
+
NEWLINE = "\n";
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
|
|
555
711
|
// node_modules/gpt-tokenizer/esm/modelsChatEnabled.gen.js
|
|
556
712
|
var chatEnabledModels;
|
|
557
713
|
var init_modelsChatEnabled_gen = __esm({
|
|
@@ -565,11 +721,12 @@ var modelsMap_exports = {};
|
|
|
565
721
|
__export(modelsMap_exports, {
|
|
566
722
|
cl100k_base: () => cl100k_base,
|
|
567
723
|
o200k_base: () => o200k_base,
|
|
724
|
+
o200k_harmony: () => o200k_harmony,
|
|
568
725
|
p50k_base: () => p50k_base,
|
|
569
726
|
p50k_edit: () => p50k_edit,
|
|
570
727
|
r50k_base: () => r50k_base
|
|
571
728
|
});
|
|
572
|
-
var p50k_base, r50k_base, p50k_edit, cl100k_base, o200k_base;
|
|
729
|
+
var p50k_base, r50k_base, p50k_edit, cl100k_base, o200k_base, o200k_harmony;
|
|
573
730
|
var init_modelsMap = __esm({
|
|
574
731
|
"node_modules/gpt-tokenizer/esm/modelsMap.js"() {
|
|
575
732
|
p50k_base = [
|
|
@@ -644,11 +801,15 @@ var init_modelsMap = __esm({
|
|
|
644
801
|
"davinci-002"
|
|
645
802
|
];
|
|
646
803
|
o200k_base = [];
|
|
804
|
+
o200k_harmony = [
|
|
805
|
+
"gpt-oss-20b",
|
|
806
|
+
"gpt-oss-120b"
|
|
807
|
+
];
|
|
647
808
|
}
|
|
648
809
|
});
|
|
649
810
|
|
|
650
811
|
// node_modules/gpt-tokenizer/esm/specialTokens.js
|
|
651
|
-
var EndOfText, FimPrefix, FimMiddle, FimSuffix, ImStart, ImEnd, ImSep, EndOfPrompt;
|
|
812
|
+
var EndOfText, FimPrefix, FimMiddle, FimSuffix, ImStart, ImEnd, ImSep, EndOfPrompt, HarmonyStartOfText, HarmonyStart, HarmonyEnd, HarmonyMessage, HarmonyChannel, HarmonyReturn, HarmonyConstrain, HarmonyCall;
|
|
652
813
|
var init_specialTokens = __esm({
|
|
653
814
|
"node_modules/gpt-tokenizer/esm/specialTokens.js"() {
|
|
654
815
|
EndOfText = "<|endoftext|>";
|
|
@@ -659,6 +820,14 @@ var init_specialTokens = __esm({
|
|
|
659
820
|
ImEnd = "<|im_end|>";
|
|
660
821
|
ImSep = "<|im_sep|>";
|
|
661
822
|
EndOfPrompt = "<|endofprompt|>";
|
|
823
|
+
HarmonyStartOfText = "<|startoftext|>";
|
|
824
|
+
HarmonyStart = "<|start|>";
|
|
825
|
+
HarmonyEnd = "<|end|>";
|
|
826
|
+
HarmonyMessage = "<|message|>";
|
|
827
|
+
HarmonyChannel = "<|channel|>";
|
|
828
|
+
HarmonyReturn = "<|return|>";
|
|
829
|
+
HarmonyConstrain = "<|constrain|>";
|
|
830
|
+
HarmonyCall = "<|call|>";
|
|
662
831
|
}
|
|
663
832
|
});
|
|
664
833
|
|
|
@@ -685,11 +854,16 @@ var init_mapping = __esm({
|
|
|
685
854
|
});
|
|
686
855
|
|
|
687
856
|
// node_modules/gpt-tokenizer/esm/encodingParams/constants.js
|
|
688
|
-
var R50K_TOKEN_SPLIT_REGEX,
|
|
857
|
+
var R50K_TOKEN_SPLIT_REGEX, CONTRACTION_SUFFIX_PATTERN, OPTIONAL_CONTRACTION_SUFFIX, CL100K_TOKEN_SPLIT_PATTERN, CL100K_TOKEN_SPLIT_REGEX, O200K_TOKEN_SPLIT_PATTERN, O200K_TOKEN_SPLIT_REGEX;
|
|
689
858
|
var init_constants2 = __esm({
|
|
690
859
|
"node_modules/gpt-tokenizer/esm/encodingParams/constants.js"() {
|
|
691
860
|
R50K_TOKEN_SPLIT_REGEX = new RegExp("'s|'t|'re|'ve|'m|'ll|'d| ?\\p{L}+| ?\\p{N}+| ?[^\\s\\p{L}\\p{N}]+|\\s+(?!\\S)|\\s+", "gu");
|
|
692
|
-
|
|
861
|
+
CONTRACTION_SUFFIX_PATTERN = String.raw`'(?:[sS]|[dD]|[mM]|[tT]|[lL][lL]|[vV][eE]|[rR][eE])`;
|
|
862
|
+
OPTIONAL_CONTRACTION_SUFFIX = String.raw`(?:${CONTRACTION_SUFFIX_PATTERN})?`;
|
|
863
|
+
CL100K_TOKEN_SPLIT_PATTERN = String.raw`${CONTRACTION_SUFFIX_PATTERN}|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}{1,3}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s+$|\s*[\r\n]|\s+(?!\S)|\s`;
|
|
864
|
+
CL100K_TOKEN_SPLIT_REGEX = new RegExp(CL100K_TOKEN_SPLIT_PATTERN, "gu");
|
|
865
|
+
O200K_TOKEN_SPLIT_PATTERN = String.raw`[^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}]*[\p{Ll}\p{Lm}\p{Lo}\p{M}]+${OPTIONAL_CONTRACTION_SUFFIX}|[^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}]+[\p{Ll}\p{Lm}\p{Lo}\p{M}]*${OPTIONAL_CONTRACTION_SUFFIX}|\p{N}{1,3}| ?[^\s\p{L}\p{N}]+[\r\n/]*|\s*[\r\n]+|\s+(?!\S)|\s+`;
|
|
866
|
+
O200K_TOKEN_SPLIT_REGEX = new RegExp(O200K_TOKEN_SPLIT_PATTERN, "gu");
|
|
693
867
|
}
|
|
694
868
|
});
|
|
695
869
|
|
|
@@ -706,7 +880,7 @@ function Cl100KBase(bytePairRankDecoder) {
|
|
|
706
880
|
[EndOfPrompt, 100276]
|
|
707
881
|
]);
|
|
708
882
|
return {
|
|
709
|
-
tokenSplitRegex:
|
|
883
|
+
tokenSplitRegex: CL100K_TOKEN_SPLIT_REGEX,
|
|
710
884
|
bytePairRankDecoder,
|
|
711
885
|
specialTokensEncoder: specialTokenMapping
|
|
712
886
|
};
|
|
@@ -720,26 +894,69 @@ var init_cl100k_base = __esm({
|
|
|
720
894
|
|
|
721
895
|
// node_modules/gpt-tokenizer/esm/encodingParams/o200k_base.js
|
|
722
896
|
function O200KBase(bytePairRankDecoder) {
|
|
723
|
-
const specialTokenMapping = /* @__PURE__ */ new Map([
|
|
724
|
-
[EndOfText, 199999],
|
|
725
|
-
[FimPrefix, 2e5],
|
|
726
|
-
[FimMiddle, 200001],
|
|
727
|
-
[FimSuffix, 200002],
|
|
728
|
-
[ImStart, 200003],
|
|
729
|
-
[ImEnd, 200004],
|
|
730
|
-
[ImSep, 200005],
|
|
731
|
-
[EndOfPrompt, 200006]
|
|
732
|
-
]);
|
|
733
897
|
return {
|
|
734
|
-
tokenSplitRegex:
|
|
898
|
+
tokenSplitRegex: O200K_TOKEN_SPLIT_REGEX,
|
|
735
899
|
bytePairRankDecoder,
|
|
736
|
-
specialTokensEncoder:
|
|
900
|
+
specialTokensEncoder: createO200KSpecialTokenMap()
|
|
737
901
|
};
|
|
738
902
|
}
|
|
903
|
+
var O200K_BASE_SPECIAL_TOKEN_ENTRIES, createO200KSpecialTokenMap;
|
|
739
904
|
var init_o200k_base2 = __esm({
|
|
740
905
|
"node_modules/gpt-tokenizer/esm/encodingParams/o200k_base.js"() {
|
|
741
906
|
init_specialTokens();
|
|
742
907
|
init_constants2();
|
|
908
|
+
O200K_BASE_SPECIAL_TOKEN_ENTRIES = [
|
|
909
|
+
[EndOfText, 199999],
|
|
910
|
+
[FimPrefix, 2e5],
|
|
911
|
+
[FimMiddle, 200001],
|
|
912
|
+
[FimSuffix, 200002],
|
|
913
|
+
[ImStart, 200003],
|
|
914
|
+
[ImEnd, 200004],
|
|
915
|
+
[ImSep, 200005],
|
|
916
|
+
[EndOfPrompt, 200006]
|
|
917
|
+
];
|
|
918
|
+
createO200KSpecialTokenMap = () => new Map(O200K_BASE_SPECIAL_TOKEN_ENTRIES);
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
// node_modules/gpt-tokenizer/esm/encodingParams/o200k_harmony.js
|
|
923
|
+
function O200KHarmony(bytePairRankDecoder) {
|
|
924
|
+
const specialTokensEncoder = new Map(STATIC_SPECIAL_TOKEN_ENTRIES);
|
|
925
|
+
for (let tokenId = RESERVED_TOKEN_RANGE_START; tokenId < RESERVED_TOKEN_RANGE_END; tokenId += 1) {
|
|
926
|
+
specialTokensEncoder.set(`<|reserved_${tokenId}|>`, tokenId);
|
|
927
|
+
}
|
|
928
|
+
specialTokensEncoder.set(EndOfPrompt, 200018);
|
|
929
|
+
return {
|
|
930
|
+
tokenSplitRegex: O200K_TOKEN_SPLIT_REGEX,
|
|
931
|
+
bytePairRankDecoder,
|
|
932
|
+
specialTokensEncoder,
|
|
933
|
+
chatFormatter: "harmony"
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
var RESERVED_TOKEN_RANGE_START, RESERVED_TOKEN_RANGE_END, STATIC_SPECIAL_TOKEN_ENTRIES;
|
|
937
|
+
var init_o200k_harmony = __esm({
|
|
938
|
+
"node_modules/gpt-tokenizer/esm/encodingParams/o200k_harmony.js"() {
|
|
939
|
+
init_specialTokens();
|
|
940
|
+
init_constants2();
|
|
941
|
+
RESERVED_TOKEN_RANGE_START = 200013;
|
|
942
|
+
RESERVED_TOKEN_RANGE_END = 201088;
|
|
943
|
+
STATIC_SPECIAL_TOKEN_ENTRIES = [
|
|
944
|
+
[HarmonyStartOfText, 199998],
|
|
945
|
+
[EndOfText, 199999],
|
|
946
|
+
["<|reserved_200000|>", 2e5],
|
|
947
|
+
["<|reserved_200001|>", 200001],
|
|
948
|
+
[HarmonyReturn, 200002],
|
|
949
|
+
[HarmonyConstrain, 200003],
|
|
950
|
+
["<|reserved_200004|>", 200004],
|
|
951
|
+
[HarmonyChannel, 200005],
|
|
952
|
+
[HarmonyStart, 200006],
|
|
953
|
+
[HarmonyEnd, 200007],
|
|
954
|
+
[HarmonyMessage, 200008],
|
|
955
|
+
["<|reserved_200009|>", 200009],
|
|
956
|
+
["<|reserved_200010|>", 200010],
|
|
957
|
+
["<|reserved_200011|>", 200011],
|
|
958
|
+
[HarmonyCall, 200012]
|
|
959
|
+
];
|
|
743
960
|
}
|
|
744
961
|
});
|
|
745
962
|
|
|
@@ -813,6 +1030,8 @@ function getEncodingParams(encodingName, getMergeableRanks) {
|
|
|
813
1030
|
return Cl100KBase(mergeableBytePairRanks);
|
|
814
1031
|
case "o200k_base":
|
|
815
1032
|
return O200KBase(mergeableBytePairRanks);
|
|
1033
|
+
case "o200k_harmony":
|
|
1034
|
+
return O200KHarmony(mergeableBytePairRanks);
|
|
816
1035
|
default:
|
|
817
1036
|
throw new Error(`Unknown encoding name: ${encodingName}`);
|
|
818
1037
|
}
|
|
@@ -821,6 +1040,7 @@ var init_modelParams = __esm({
|
|
|
821
1040
|
"node_modules/gpt-tokenizer/esm/modelParams.js"() {
|
|
822
1041
|
init_cl100k_base();
|
|
823
1042
|
init_o200k_base2();
|
|
1043
|
+
init_o200k_harmony();
|
|
824
1044
|
init_p50k_base();
|
|
825
1045
|
init_p50k_edit();
|
|
826
1046
|
init_r50k_base();
|
|
@@ -833,6 +1053,7 @@ var init_GptEncoding = __esm({
|
|
|
833
1053
|
"node_modules/gpt-tokenizer/esm/GptEncoding.js"() {
|
|
834
1054
|
init_BytePairEncodingCore();
|
|
835
1055
|
init_constants();
|
|
1056
|
+
init_functionCalling();
|
|
836
1057
|
init_mapping();
|
|
837
1058
|
init_modelParams();
|
|
838
1059
|
init_specialTokens();
|
|
@@ -851,8 +1072,10 @@ var init_GptEncoding = __esm({
|
|
|
851
1072
|
specialTokensSet;
|
|
852
1073
|
allSpecialTokenRegex;
|
|
853
1074
|
defaultSpecialTokenConfig;
|
|
1075
|
+
chatFormatter;
|
|
1076
|
+
countChatCompletionTokens;
|
|
854
1077
|
vocabularySize;
|
|
855
|
-
constructor({ bytePairRankDecoder: mergeableBytePairRanks, specialTokensEncoder, expectedVocabularySize, modelName, modelSpec, ...rest }) {
|
|
1078
|
+
constructor({ bytePairRankDecoder: mergeableBytePairRanks, specialTokensEncoder, expectedVocabularySize, modelName, modelSpec, chatFormatter, ...rest }) {
|
|
856
1079
|
this.specialTokensEncoder = specialTokensEncoder;
|
|
857
1080
|
this.specialTokensSet = new Set(this.specialTokensEncoder.keys());
|
|
858
1081
|
this.allSpecialTokenRegex = getSpecialTokenRegex(this.specialTokensSet);
|
|
@@ -885,8 +1108,69 @@ var init_GptEncoding = __esm({
|
|
|
885
1108
|
this.setMergeCacheSize = this.setMergeCacheSize.bind(this);
|
|
886
1109
|
this.clearMergeCache = this.clearMergeCache.bind(this);
|
|
887
1110
|
this.estimateCost = this.estimateCost.bind(this);
|
|
1111
|
+
if (modelSpec?.supported_features?.includes("function_calling")) {
|
|
1112
|
+
this.countChatCompletionTokens = this.countChatCompletionTokensInternal.bind(this);
|
|
1113
|
+
}
|
|
888
1114
|
this.modelName = modelName;
|
|
889
1115
|
this.modelSpec = modelSpec;
|
|
1116
|
+
this.chatFormatter = chatFormatter ?? "chatml";
|
|
1117
|
+
}
|
|
1118
|
+
*encodeHarmonyChatGenerator(chat, encodeOptions) {
|
|
1119
|
+
const harmonyStart = this.specialTokensEncoder.get(HarmonyStart);
|
|
1120
|
+
const harmonyMessage = this.specialTokensEncoder.get(HarmonyMessage);
|
|
1121
|
+
const harmonyEnd = this.specialTokensEncoder.get(HarmonyEnd);
|
|
1122
|
+
const harmonyReturn = this.specialTokensEncoder.get(HarmonyReturn);
|
|
1123
|
+
const harmonyCall = this.specialTokensEncoder.get(HarmonyCall);
|
|
1124
|
+
const harmonyChannel = this.specialTokensEncoder.get(HarmonyChannel);
|
|
1125
|
+
const harmonyConstrain = this.specialTokensEncoder.get(HarmonyConstrain);
|
|
1126
|
+
if (harmonyStart === void 0 || harmonyMessage === void 0 || harmonyEnd === void 0 || harmonyReturn === void 0 || harmonyCall === void 0 || harmonyChannel === void 0 || harmonyConstrain === void 0) {
|
|
1127
|
+
throw new Error("Harmony chat format requires dedicated special tokens.");
|
|
1128
|
+
}
|
|
1129
|
+
const encodeHeaderText = (text) => text.length > 0 ? this.encode(text) : [];
|
|
1130
|
+
const resolveTerminatorToken = (terminator) => {
|
|
1131
|
+
switch (terminator) {
|
|
1132
|
+
case "<|return|>":
|
|
1133
|
+
return harmonyReturn;
|
|
1134
|
+
case "<|call|>":
|
|
1135
|
+
return harmonyCall;
|
|
1136
|
+
// eslint-disable-next-line unicorn/no-useless-switch-case
|
|
1137
|
+
case "<|end|>":
|
|
1138
|
+
default:
|
|
1139
|
+
return harmonyEnd;
|
|
1140
|
+
}
|
|
1141
|
+
};
|
|
1142
|
+
for (const message of chat) {
|
|
1143
|
+
if (message.content === void 0) {
|
|
1144
|
+
throw new Error("Content must be defined for all messages.");
|
|
1145
|
+
}
|
|
1146
|
+
const roleOrName = message.name ?? message.role ?? "user";
|
|
1147
|
+
yield [harmonyStart];
|
|
1148
|
+
yield encodeHeaderText(roleOrName);
|
|
1149
|
+
const recipientInRole = message.recipient && (message.recipientPlacement === "role" || !message.channel);
|
|
1150
|
+
const recipientInChannel = message.recipient && !recipientInRole;
|
|
1151
|
+
if (recipientInRole) {
|
|
1152
|
+
yield encodeHeaderText(` to=${message.recipient}`);
|
|
1153
|
+
}
|
|
1154
|
+
if (message.channel) {
|
|
1155
|
+
yield [harmonyChannel];
|
|
1156
|
+
yield encodeHeaderText(message.channel);
|
|
1157
|
+
if (recipientInChannel) {
|
|
1158
|
+
yield encodeHeaderText(` to=${message.recipient}`);
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
if (message.constraint) {
|
|
1162
|
+
yield [harmonyConstrain];
|
|
1163
|
+
yield encodeHeaderText(message.constraint);
|
|
1164
|
+
}
|
|
1165
|
+
yield [harmonyMessage];
|
|
1166
|
+
yield* this.encodeGenerator(message.content, encodeOptions);
|
|
1167
|
+
yield [resolveTerminatorToken(message.terminator)];
|
|
1168
|
+
}
|
|
1169
|
+
const assistantPrime = encodeOptions?.primeWithAssistantResponse ?? "assistant";
|
|
1170
|
+
if (assistantPrime.length > 0) {
|
|
1171
|
+
yield [harmonyStart];
|
|
1172
|
+
yield encodeHeaderText(assistantPrime);
|
|
1173
|
+
}
|
|
890
1174
|
}
|
|
891
1175
|
static getEncodingApi(encodingName, getMergeableRanks) {
|
|
892
1176
|
const modelParams = getEncodingParams(encodingName, getMergeableRanks);
|
|
@@ -959,9 +1243,16 @@ var init_GptEncoding = __esm({
|
|
|
959
1243
|
throw new Error("Model name must be provided either during initialization or passed in to the method.");
|
|
960
1244
|
}
|
|
961
1245
|
const params = chatModelParams[model];
|
|
1246
|
+
if (!params) {
|
|
1247
|
+
throw new Error(`Model '${model}' does not support chat.`);
|
|
1248
|
+
}
|
|
1249
|
+
if (this.chatFormatter === "harmony") {
|
|
1250
|
+
yield* this.encodeHarmonyChatGenerator(chat, encodeOptions);
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
962
1253
|
const chatStartToken = this.specialTokensEncoder.get(ImStart);
|
|
963
1254
|
const chatEndToken = this.specialTokensEncoder.get(ImEnd);
|
|
964
|
-
if (
|
|
1255
|
+
if (chatStartToken === void 0 || chatEndToken === void 0) {
|
|
965
1256
|
throw new Error(`Model '${model}' does not support chat.`);
|
|
966
1257
|
}
|
|
967
1258
|
const allowedSpecial = /* @__PURE__ */ new Set([ImSep]);
|
|
@@ -984,8 +1275,11 @@ var init_GptEncoding = __esm({
|
|
|
984
1275
|
yield [chatEndToken];
|
|
985
1276
|
yield encodedMessageSeparator;
|
|
986
1277
|
}
|
|
987
|
-
|
|
988
|
-
|
|
1278
|
+
const assistantPrime = encodeOptions?.primeWithAssistantResponse ?? "assistant";
|
|
1279
|
+
if (assistantPrime.length > 0) {
|
|
1280
|
+
yield [chatStartToken];
|
|
1281
|
+
yield* this.encodeGenerator(assistantPrime, encodeOptions);
|
|
1282
|
+
}
|
|
989
1283
|
if (encodedRoleSeparator.length > 0) {
|
|
990
1284
|
yield encodedRoleSeparator;
|
|
991
1285
|
}
|
|
@@ -1043,6 +1337,15 @@ var init_GptEncoding = __esm({
|
|
|
1043
1337
|
}
|
|
1044
1338
|
return count;
|
|
1045
1339
|
}
|
|
1340
|
+
countStringTokens(text) {
|
|
1341
|
+
if (!text) {
|
|
1342
|
+
return 0;
|
|
1343
|
+
}
|
|
1344
|
+
return this.bytePairEncodingCoreProcessor.countNative(text);
|
|
1345
|
+
}
|
|
1346
|
+
countChatCompletionTokensInternal(request) {
|
|
1347
|
+
return computeChatCompletionTokenCount(request, (text) => this.countStringTokens(text));
|
|
1348
|
+
}
|
|
1046
1349
|
setMergeCacheSize(size) {
|
|
1047
1350
|
this.bytePairEncodingCoreProcessor.setMergeCacheSize(size);
|
|
1048
1351
|
}
|
|
@@ -7483,7 +7786,15 @@ function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
|
|
|
7483
7786
|
if (openIndex === -1) {
|
|
7484
7787
|
continue;
|
|
7485
7788
|
}
|
|
7486
|
-
let closeIndex
|
|
7789
|
+
let closeIndex;
|
|
7790
|
+
if (toolName === "attempt_completion") {
|
|
7791
|
+
closeIndex = xmlString.lastIndexOf(closeTag);
|
|
7792
|
+
if (closeIndex !== -1 && closeIndex <= openIndex + openTag.length) {
|
|
7793
|
+
closeIndex = -1;
|
|
7794
|
+
}
|
|
7795
|
+
} else {
|
|
7796
|
+
closeIndex = xmlString.indexOf(closeTag, openIndex + openTag.length);
|
|
7797
|
+
}
|
|
7487
7798
|
let hasClosingTag = closeIndex !== -1;
|
|
7488
7799
|
if (closeIndex === -1) {
|
|
7489
7800
|
closeIndex = xmlString.length;
|
|
@@ -17148,10 +17459,22 @@ function extractThinkingContent(xmlString) {
|
|
|
17148
17459
|
return thinkingMatch ? thinkingMatch[1].trim() : null;
|
|
17149
17460
|
}
|
|
17150
17461
|
function checkAttemptCompleteRecovery(cleanedXmlString, validTools = []) {
|
|
17151
|
-
const
|
|
17152
|
-
if (
|
|
17153
|
-
const
|
|
17154
|
-
const
|
|
17462
|
+
const openTagIndex = cleanedXmlString.indexOf("<attempt_completion>");
|
|
17463
|
+
if (openTagIndex !== -1) {
|
|
17464
|
+
const afterOpenTag = cleanedXmlString.substring(openTagIndex + "<attempt_completion>".length);
|
|
17465
|
+
const closeTagIndex = cleanedXmlString.lastIndexOf("</attempt_completion>");
|
|
17466
|
+
let content;
|
|
17467
|
+
let hasClosingTag = false;
|
|
17468
|
+
if (closeTagIndex !== -1 && closeTagIndex >= openTagIndex + "<attempt_completion>".length) {
|
|
17469
|
+
content = cleanedXmlString.substring(
|
|
17470
|
+
openTagIndex + "<attempt_completion>".length,
|
|
17471
|
+
closeTagIndex
|
|
17472
|
+
).trim();
|
|
17473
|
+
hasClosingTag = true;
|
|
17474
|
+
} else {
|
|
17475
|
+
content = afterOpenTag.trim();
|
|
17476
|
+
hasClosingTag = false;
|
|
17477
|
+
}
|
|
17155
17478
|
if (content) {
|
|
17156
17479
|
return {
|
|
17157
17480
|
toolName: "attempt_completion",
|
|
@@ -53941,6 +54264,8 @@ __export(schemaUtils_exports, {
|
|
|
53941
54264
|
createSchemaDefinitionCorrectionPrompt: () => createSchemaDefinitionCorrectionPrompt,
|
|
53942
54265
|
decodeHtmlEntities: () => decodeHtmlEntities,
|
|
53943
54266
|
extractMermaidFromMarkdown: () => extractMermaidFromMarkdown,
|
|
54267
|
+
generateExampleFromSchema: () => generateExampleFromSchema,
|
|
54268
|
+
generateSchemaInstructions: () => generateSchemaInstructions,
|
|
53944
54269
|
isJsonSchema: () => isJsonSchema,
|
|
53945
54270
|
isJsonSchemaDefinition: () => isJsonSchemaDefinition,
|
|
53946
54271
|
isMermaidSchema: () => isMermaidSchema,
|
|
@@ -53953,6 +54278,63 @@ __export(schemaUtils_exports, {
|
|
|
53953
54278
|
validateMermaidResponse: () => validateMermaidResponse,
|
|
53954
54279
|
validateXmlResponse: () => validateXmlResponse
|
|
53955
54280
|
});
|
|
54281
|
+
function generateExampleFromSchema(schema, options = {}) {
|
|
54282
|
+
const { debug = false } = options;
|
|
54283
|
+
try {
|
|
54284
|
+
const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
|
|
54285
|
+
if (parsedSchema.type !== "object" || !parsedSchema.properties) {
|
|
54286
|
+
return null;
|
|
54287
|
+
}
|
|
54288
|
+
const exampleObj = {};
|
|
54289
|
+
for (const [key, value] of Object.entries(parsedSchema.properties)) {
|
|
54290
|
+
if (value.type === "boolean") {
|
|
54291
|
+
exampleObj[key] = false;
|
|
54292
|
+
} else if (value.type === "number") {
|
|
54293
|
+
exampleObj[key] = 0;
|
|
54294
|
+
} else if (value.type === "string") {
|
|
54295
|
+
exampleObj[key] = value.description || "your answer here";
|
|
54296
|
+
} else if (value.type === "array") {
|
|
54297
|
+
exampleObj[key] = [];
|
|
54298
|
+
} else {
|
|
54299
|
+
exampleObj[key] = {};
|
|
54300
|
+
}
|
|
54301
|
+
}
|
|
54302
|
+
return exampleObj;
|
|
54303
|
+
} catch (e) {
|
|
54304
|
+
if (debug) {
|
|
54305
|
+
console.error("[DEBUG] generateExampleFromSchema: Failed to parse schema:", e.message);
|
|
54306
|
+
}
|
|
54307
|
+
return null;
|
|
54308
|
+
}
|
|
54309
|
+
}
|
|
54310
|
+
function generateSchemaInstructions(schema, options = {}) {
|
|
54311
|
+
const { debug = false } = options;
|
|
54312
|
+
let instructions = "\n\nIMPORTANT: When you provide your final answer using attempt_completion, you MUST format it as valid JSON matching this schema:\n\n";
|
|
54313
|
+
try {
|
|
54314
|
+
const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
|
|
54315
|
+
instructions += `${JSON.stringify(parsedSchema, null, 2)}
|
|
54316
|
+
|
|
54317
|
+
`;
|
|
54318
|
+
const exampleObj = generateExampleFromSchema(parsedSchema, { debug });
|
|
54319
|
+
if (exampleObj) {
|
|
54320
|
+
instructions += `Example:
|
|
54321
|
+
<attempt_completion>
|
|
54322
|
+
${JSON.stringify(exampleObj, null, 2)}
|
|
54323
|
+
</attempt_completion>
|
|
54324
|
+
|
|
54325
|
+
`;
|
|
54326
|
+
}
|
|
54327
|
+
} catch (e) {
|
|
54328
|
+
if (debug) {
|
|
54329
|
+
console.error("[DEBUG] generateSchemaInstructions: Failed to parse schema:", e.message);
|
|
54330
|
+
}
|
|
54331
|
+
instructions += `${schema}
|
|
54332
|
+
|
|
54333
|
+
`;
|
|
54334
|
+
}
|
|
54335
|
+
instructions += "Your response inside attempt_completion must be ONLY valid JSON - no plain text, no explanations, no markdown.";
|
|
54336
|
+
return instructions;
|
|
54337
|
+
}
|
|
53956
54338
|
function enforceNoAdditionalProperties(schema) {
|
|
53957
54339
|
if (!schema || typeof schema !== "object") {
|
|
53958
54340
|
return schema;
|
|
@@ -56656,6 +57038,170 @@ var init_FallbackManager = __esm({
|
|
|
56656
57038
|
}
|
|
56657
57039
|
});
|
|
56658
57040
|
|
|
57041
|
+
// src/agent/contextCompactor.js
|
|
57042
|
+
var contextCompactor_exports = {};
|
|
57043
|
+
__export(contextCompactor_exports, {
|
|
57044
|
+
calculateCompactionStats: () => calculateCompactionStats,
|
|
57045
|
+
compactMessages: () => compactMessages,
|
|
57046
|
+
handleContextLimitError: () => handleContextLimitError,
|
|
57047
|
+
identifyMessageSegments: () => identifyMessageSegments,
|
|
57048
|
+
isContextLimitError: () => isContextLimitError
|
|
57049
|
+
});
|
|
57050
|
+
function isContextLimitError(error) {
|
|
57051
|
+
if (!error) return false;
|
|
57052
|
+
const errorMessage = (typeof error === "string" ? error : error?.message || "").toLowerCase();
|
|
57053
|
+
const errorString = error.toString().toLowerCase();
|
|
57054
|
+
for (const pattern of CONTEXT_LIMIT_ERROR_PATTERNS) {
|
|
57055
|
+
const lowerPattern = pattern.toLowerCase();
|
|
57056
|
+
if (errorMessage.includes(lowerPattern) || errorString.includes(lowerPattern)) {
|
|
57057
|
+
return true;
|
|
57058
|
+
}
|
|
57059
|
+
}
|
|
57060
|
+
return false;
|
|
57061
|
+
}
|
|
57062
|
+
function identifyMessageSegments(messages) {
|
|
57063
|
+
const segments = [];
|
|
57064
|
+
let currentSegment = null;
|
|
57065
|
+
for (let i = 0; i < messages.length; i++) {
|
|
57066
|
+
const msg = messages[i];
|
|
57067
|
+
if (msg.role === "system") {
|
|
57068
|
+
continue;
|
|
57069
|
+
}
|
|
57070
|
+
if (msg.role === "user") {
|
|
57071
|
+
const content = typeof msg.content === "string" ? msg.content : "";
|
|
57072
|
+
const isToolResult = content.includes("<tool_result>");
|
|
57073
|
+
if (isToolResult && currentSegment) {
|
|
57074
|
+
currentSegment.finalIndex = i;
|
|
57075
|
+
segments.push(currentSegment);
|
|
57076
|
+
currentSegment = null;
|
|
57077
|
+
} else {
|
|
57078
|
+
if (currentSegment) {
|
|
57079
|
+
segments.push(currentSegment);
|
|
57080
|
+
}
|
|
57081
|
+
currentSegment = {
|
|
57082
|
+
userIndex: i,
|
|
57083
|
+
monologueIndices: [],
|
|
57084
|
+
finalIndex: null
|
|
57085
|
+
};
|
|
57086
|
+
}
|
|
57087
|
+
}
|
|
57088
|
+
if (msg.role === "assistant" && currentSegment) {
|
|
57089
|
+
const content = typeof msg.content === "string" ? msg.content : "";
|
|
57090
|
+
if (content.includes("<attempt_completion>") || content.includes("attempt_completion")) {
|
|
57091
|
+
currentSegment.monologueIndices.push(i);
|
|
57092
|
+
currentSegment.finalIndex = i;
|
|
57093
|
+
segments.push(currentSegment);
|
|
57094
|
+
currentSegment = null;
|
|
57095
|
+
} else {
|
|
57096
|
+
currentSegment.monologueIndices.push(i);
|
|
57097
|
+
}
|
|
57098
|
+
}
|
|
57099
|
+
}
|
|
57100
|
+
if (currentSegment) {
|
|
57101
|
+
segments.push(currentSegment);
|
|
57102
|
+
}
|
|
57103
|
+
return segments;
|
|
57104
|
+
}
|
|
57105
|
+
function compactMessages(messages, options = {}) {
|
|
57106
|
+
const {
|
|
57107
|
+
keepLastSegment = true,
|
|
57108
|
+
minSegmentsToKeep = 1
|
|
57109
|
+
} = options;
|
|
57110
|
+
if (!messages || messages.length === 0) {
|
|
57111
|
+
return messages;
|
|
57112
|
+
}
|
|
57113
|
+
const segments = identifyMessageSegments(messages);
|
|
57114
|
+
if (segments.length === 0) {
|
|
57115
|
+
return messages;
|
|
57116
|
+
}
|
|
57117
|
+
const segmentsToPreserve = keepLastSegment ? Math.max(minSegmentsToKeep, 1) : minSegmentsToKeep;
|
|
57118
|
+
const compactableSegments = segments.slice(0, -segmentsToPreserve);
|
|
57119
|
+
const preservedSegments = segments.slice(-segmentsToPreserve);
|
|
57120
|
+
const indicesToKeep = /* @__PURE__ */ new Set();
|
|
57121
|
+
messages.forEach((msg, idx) => {
|
|
57122
|
+
if (msg.role === "system") {
|
|
57123
|
+
indicesToKeep.add(idx);
|
|
57124
|
+
}
|
|
57125
|
+
});
|
|
57126
|
+
compactableSegments.forEach((segment) => {
|
|
57127
|
+
indicesToKeep.add(segment.userIndex);
|
|
57128
|
+
if (segment.finalIndex !== null) {
|
|
57129
|
+
indicesToKeep.add(segment.finalIndex);
|
|
57130
|
+
}
|
|
57131
|
+
});
|
|
57132
|
+
preservedSegments.forEach((segment) => {
|
|
57133
|
+
indicesToKeep.add(segment.userIndex);
|
|
57134
|
+
segment.monologueIndices.forEach((idx) => indicesToKeep.add(idx));
|
|
57135
|
+
if (segment.finalIndex !== null) {
|
|
57136
|
+
indicesToKeep.add(segment.finalIndex);
|
|
57137
|
+
}
|
|
57138
|
+
});
|
|
57139
|
+
const compactedMessages = messages.filter((_, idx) => indicesToKeep.has(idx));
|
|
57140
|
+
return compactedMessages;
|
|
57141
|
+
}
|
|
57142
|
+
function calculateCompactionStats(originalMessages, compactedMessages) {
|
|
57143
|
+
const originalCount = originalMessages.length;
|
|
57144
|
+
const compactedCount = compactedMessages.length;
|
|
57145
|
+
const removed = originalCount - compactedCount;
|
|
57146
|
+
const reductionPercent = originalCount > 0 ? (removed / originalCount * 100).toFixed(1) : 0;
|
|
57147
|
+
const estimateTokens = (msgs) => {
|
|
57148
|
+
return msgs.reduce((sum, msg) => {
|
|
57149
|
+
const content = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
|
|
57150
|
+
return sum + Math.ceil(content.length / 4);
|
|
57151
|
+
}, 0);
|
|
57152
|
+
};
|
|
57153
|
+
const originalTokens = estimateTokens(originalMessages);
|
|
57154
|
+
const compactedTokens = estimateTokens(compactedMessages);
|
|
57155
|
+
const tokensSaved = originalTokens - compactedTokens;
|
|
57156
|
+
return {
|
|
57157
|
+
originalCount,
|
|
57158
|
+
compactedCount,
|
|
57159
|
+
removed,
|
|
57160
|
+
reductionPercent: parseFloat(reductionPercent),
|
|
57161
|
+
originalTokens,
|
|
57162
|
+
compactedTokens,
|
|
57163
|
+
tokensSaved
|
|
57164
|
+
};
|
|
57165
|
+
}
|
|
57166
|
+
function handleContextLimitError(error, messages, options = {}) {
|
|
57167
|
+
if (!isContextLimitError(error)) {
|
|
57168
|
+
return null;
|
|
57169
|
+
}
|
|
57170
|
+
const compactedMessages = compactMessages(messages, options);
|
|
57171
|
+
const stats = calculateCompactionStats(messages, compactedMessages);
|
|
57172
|
+
return {
|
|
57173
|
+
compacted: true,
|
|
57174
|
+
messages: compactedMessages,
|
|
57175
|
+
stats
|
|
57176
|
+
};
|
|
57177
|
+
}
|
|
57178
|
+
var CONTEXT_LIMIT_ERROR_PATTERNS;
|
|
57179
|
+
var init_contextCompactor = __esm({
|
|
57180
|
+
"src/agent/contextCompactor.js"() {
|
|
57181
|
+
"use strict";
|
|
57182
|
+
CONTEXT_LIMIT_ERROR_PATTERNS = [
|
|
57183
|
+
// Anthropic
|
|
57184
|
+
"context_length_exceeded",
|
|
57185
|
+
"prompt is too long",
|
|
57186
|
+
// OpenAI
|
|
57187
|
+
"maximum context length",
|
|
57188
|
+
"context length is",
|
|
57189
|
+
// Google/Gemini
|
|
57190
|
+
"input token count exceeds",
|
|
57191
|
+
"token limit exceeded",
|
|
57192
|
+
// Generic patterns
|
|
57193
|
+
"context window",
|
|
57194
|
+
"too many tokens",
|
|
57195
|
+
"token limit",
|
|
57196
|
+
"context limit",
|
|
57197
|
+
"exceed",
|
|
57198
|
+
// Catches "exceeds", "exceed maximum", etc.
|
|
57199
|
+
"over the limit",
|
|
57200
|
+
"maximum tokens"
|
|
57201
|
+
];
|
|
57202
|
+
}
|
|
57203
|
+
});
|
|
57204
|
+
|
|
56659
57205
|
// src/agent/ProbeAgent.js
|
|
56660
57206
|
var ProbeAgent_exports = {};
|
|
56661
57207
|
__export(ProbeAgent_exports, {
|
|
@@ -56690,6 +57236,7 @@ var init_ProbeAgent = __esm({
|
|
|
56690
57236
|
init_mcp();
|
|
56691
57237
|
init_RetryManager();
|
|
56692
57238
|
init_FallbackManager();
|
|
57239
|
+
init_contextCompactor();
|
|
56693
57240
|
dotenv2.config();
|
|
56694
57241
|
MAX_TOOL_ITERATIONS = (() => {
|
|
56695
57242
|
const val = parseInt(process.env.MAX_TOOL_ITERATIONS || "30", 10);
|
|
@@ -56725,6 +57272,8 @@ var init_ProbeAgent = __esm({
|
|
|
56725
57272
|
* @param {Array} [options.mcpServers] - Deprecated, use mcpConfig instead
|
|
56726
57273
|
* @param {Object} [options.storageAdapter] - Custom storage adapter for history management
|
|
56727
57274
|
* @param {Object} [options.hooks] - Hook callbacks for events (e.g., {'tool:start': callback})
|
|
57275
|
+
* @param {Array<string>|null} [options.allowedTools] - List of allowed tool names. Use ['*'] for all tools (default), [] or null for no tools (raw AI mode), or specific tool names like ['search', 'query', 'extract']. Supports exclusion with '!' prefix (e.g., ['*', '!bash'])
|
|
57276
|
+
* @param {boolean} [options.disableTools=false] - Convenience flag to disable all tools (equivalent to allowedTools: []). Takes precedence over allowedTools if set.
|
|
56728
57277
|
* @param {Object} [options.retry] - Retry configuration
|
|
56729
57278
|
* @param {number} [options.retry.maxRetries=3] - Maximum retry attempts per provider
|
|
56730
57279
|
* @param {number} [options.retry.initialDelay=1000] - Initial delay in ms
|
|
@@ -56758,6 +57307,8 @@ var init_ProbeAgent = __esm({
|
|
|
56758
57307
|
this.maxIterations = options.maxIterations || null;
|
|
56759
57308
|
this.disableMermaidValidation = !!options.disableMermaidValidation;
|
|
56760
57309
|
this.disableJsonValidation = !!options.disableJsonValidation;
|
|
57310
|
+
const effectiveAllowedTools = options.disableTools ? [] : options.allowedTools;
|
|
57311
|
+
this.allowedTools = this._parseAllowedTools(effectiveAllowedTools);
|
|
56761
57312
|
this.storageAdapter = options.storageAdapter || new InMemoryStorageAdapter();
|
|
56762
57313
|
this.hooks = new HookManager();
|
|
56763
57314
|
if (options.hooks) {
|
|
@@ -56801,6 +57352,61 @@ var init_ProbeAgent = __esm({
|
|
|
56801
57352
|
this.fallbackManager = null;
|
|
56802
57353
|
this.initializeModel();
|
|
56803
57354
|
}
|
|
57355
|
+
/**
|
|
57356
|
+
* Parse allowedTools configuration
|
|
57357
|
+
* @param {Array<string>|null|undefined} allowedTools - Tool filtering configuration
|
|
57358
|
+
* @returns {Object} Parsed configuration with isEnabled method
|
|
57359
|
+
* @private
|
|
57360
|
+
*/
|
|
57361
|
+
_parseAllowedTools(allowedTools) {
|
|
57362
|
+
const matchesPattern2 = (toolName, pattern) => {
|
|
57363
|
+
if (!pattern.includes("*")) {
|
|
57364
|
+
return toolName === pattern;
|
|
57365
|
+
}
|
|
57366
|
+
const regexPattern = pattern.replace(/\*/g, ".*");
|
|
57367
|
+
return new RegExp(`^${regexPattern}$`).test(toolName);
|
|
57368
|
+
};
|
|
57369
|
+
if (!allowedTools || Array.isArray(allowedTools) && allowedTools.includes("*")) {
|
|
57370
|
+
const exclusions = Array.isArray(allowedTools) ? allowedTools.filter((t) => t.startsWith("!")).map((t) => t.slice(1)) : [];
|
|
57371
|
+
return {
|
|
57372
|
+
mode: "all",
|
|
57373
|
+
exclusions,
|
|
57374
|
+
isEnabled: (toolName) => !exclusions.some((pattern) => matchesPattern2(toolName, pattern))
|
|
57375
|
+
};
|
|
57376
|
+
}
|
|
57377
|
+
if (Array.isArray(allowedTools) && allowedTools.length === 0) {
|
|
57378
|
+
return {
|
|
57379
|
+
mode: "none",
|
|
57380
|
+
isEnabled: () => false
|
|
57381
|
+
};
|
|
57382
|
+
}
|
|
57383
|
+
const allowedPatterns = allowedTools.filter((t) => !t.startsWith("!"));
|
|
57384
|
+
return {
|
|
57385
|
+
mode: "whitelist",
|
|
57386
|
+
allowed: allowedPatterns,
|
|
57387
|
+
isEnabled: (toolName) => allowedPatterns.some((pattern) => matchesPattern2(toolName, pattern))
|
|
57388
|
+
};
|
|
57389
|
+
}
|
|
57390
|
+
/**
|
|
57391
|
+
* Check if an MCP tool is allowed based on allowedTools configuration
|
|
57392
|
+
* Uses mcp__ prefix convention (like Claude Code)
|
|
57393
|
+
* @param {string} toolName - The MCP tool name (without mcp__ prefix)
|
|
57394
|
+
* @returns {boolean} - Whether the tool is allowed
|
|
57395
|
+
* @private
|
|
57396
|
+
*/
|
|
57397
|
+
_isMcpToolAllowed(toolName) {
|
|
57398
|
+
const mcpToolName = `mcp__${toolName}`;
|
|
57399
|
+
return this.allowedTools.isEnabled(mcpToolName) || this.allowedTools.isEnabled(toolName);
|
|
57400
|
+
}
|
|
57401
|
+
/**
|
|
57402
|
+
* Filter MCP tools based on allowedTools configuration
|
|
57403
|
+
* @param {string[]} mcpToolNames - Array of MCP tool names
|
|
57404
|
+
* @returns {string[]} - Filtered array of allowed MCP tool names
|
|
57405
|
+
* @private
|
|
57406
|
+
*/
|
|
57407
|
+
_filterMcpTools(mcpToolNames) {
|
|
57408
|
+
return mcpToolNames.filter((toolName) => this._isMcpToolAllowed(toolName));
|
|
57409
|
+
}
|
|
56804
57410
|
/**
|
|
56805
57411
|
* Initialize the agent asynchronously (must be called after constructor)
|
|
56806
57412
|
* This method initializes MCP and merges MCP tools into the tool list, and loads history from storage
|
|
@@ -56827,7 +57433,11 @@ var init_ProbeAgent = __esm({
|
|
|
56827
57433
|
if (this.mcpBridge) {
|
|
56828
57434
|
const mcpTools = this.mcpBridge.mcpTools || {};
|
|
56829
57435
|
for (const [toolName, toolImpl] of Object.entries(mcpTools)) {
|
|
56830
|
-
this.
|
|
57436
|
+
if (this._isMcpToolAllowed(toolName)) {
|
|
57437
|
+
this.toolImplementations[toolName] = toolImpl;
|
|
57438
|
+
} else if (this.debug) {
|
|
57439
|
+
console.error(`[DEBUG] MCP tool '${toolName}' filtered out by allowedTools`);
|
|
57440
|
+
}
|
|
56831
57441
|
}
|
|
56832
57442
|
}
|
|
56833
57443
|
if (this.debug) {
|
|
@@ -57447,7 +58057,11 @@ var init_ProbeAgent = __esm({
|
|
|
57447
58057
|
if (this.mcpBridge) {
|
|
57448
58058
|
const mcpTools = this.mcpBridge.mcpTools || {};
|
|
57449
58059
|
for (const [toolName, toolImpl] of Object.entries(mcpTools)) {
|
|
57450
|
-
this.
|
|
58060
|
+
if (this._isMcpToolAllowed(toolName)) {
|
|
58061
|
+
this.toolImplementations[toolName] = toolImpl;
|
|
58062
|
+
} else if (this.debug) {
|
|
58063
|
+
console.error(`[DEBUG] MCP tool '${toolName}' filtered out by allowedTools`);
|
|
58064
|
+
}
|
|
57451
58065
|
}
|
|
57452
58066
|
}
|
|
57453
58067
|
} catch (error) {
|
|
@@ -57457,27 +58071,49 @@ var init_ProbeAgent = __esm({
|
|
|
57457
58071
|
}
|
|
57458
58072
|
}
|
|
57459
58073
|
}
|
|
57460
|
-
let toolDefinitions =
|
|
57461
|
-
|
|
57462
|
-
|
|
57463
|
-
|
|
57464
|
-
${listFilesToolDefinition}
|
|
57465
|
-
${searchFilesToolDefinition}
|
|
57466
|
-
${attemptCompletionToolDefinition}
|
|
58074
|
+
let toolDefinitions = "";
|
|
58075
|
+
const isToolAllowed = (toolName) => this.allowedTools.isEnabled(toolName);
|
|
58076
|
+
if (isToolAllowed("search")) {
|
|
58077
|
+
toolDefinitions += `${searchToolDefinition}
|
|
57467
58078
|
`;
|
|
57468
|
-
|
|
58079
|
+
}
|
|
58080
|
+
if (isToolAllowed("query")) {
|
|
58081
|
+
toolDefinitions += `${queryToolDefinition}
|
|
58082
|
+
`;
|
|
58083
|
+
}
|
|
58084
|
+
if (isToolAllowed("extract")) {
|
|
58085
|
+
toolDefinitions += `${extractToolDefinition}
|
|
58086
|
+
`;
|
|
58087
|
+
}
|
|
58088
|
+
if (isToolAllowed("listFiles")) {
|
|
58089
|
+
toolDefinitions += `${listFilesToolDefinition}
|
|
58090
|
+
`;
|
|
58091
|
+
}
|
|
58092
|
+
if (isToolAllowed("searchFiles")) {
|
|
58093
|
+
toolDefinitions += `${searchFilesToolDefinition}
|
|
58094
|
+
`;
|
|
58095
|
+
}
|
|
58096
|
+
if (this.allowEdit && isToolAllowed("implement")) {
|
|
57469
58097
|
toolDefinitions += `${implementToolDefinition}
|
|
57470
58098
|
`;
|
|
58099
|
+
}
|
|
58100
|
+
if (this.allowEdit && isToolAllowed("edit")) {
|
|
57471
58101
|
toolDefinitions += `${editToolDefinition}
|
|
57472
58102
|
`;
|
|
58103
|
+
}
|
|
58104
|
+
if (this.allowEdit && isToolAllowed("create")) {
|
|
57473
58105
|
toolDefinitions += `${createToolDefinition}
|
|
57474
58106
|
`;
|
|
57475
58107
|
}
|
|
57476
|
-
if (this.enableBash) {
|
|
58108
|
+
if (this.enableBash && isToolAllowed("bash")) {
|
|
57477
58109
|
toolDefinitions += `${bashToolDefinition}
|
|
57478
58110
|
`;
|
|
57479
58111
|
}
|
|
57480
|
-
if (
|
|
58112
|
+
if (isToolAllowed("attempt_completion")) {
|
|
58113
|
+
toolDefinitions += `${attemptCompletionToolDefinition}
|
|
58114
|
+
`;
|
|
58115
|
+
}
|
|
58116
|
+
if (this.enableDelegate && isToolAllowed("delegate")) {
|
|
57481
58117
|
toolDefinitions += `${delegateToolDefinition}
|
|
57482
58118
|
`;
|
|
57483
58119
|
}
|
|
@@ -57639,11 +58275,14 @@ ${xmlToolGuidelines}
|
|
|
57639
58275
|
${toolDefinitions}
|
|
57640
58276
|
`;
|
|
57641
58277
|
if (this.mcpBridge && this.mcpBridge.getToolNames().length > 0) {
|
|
57642
|
-
|
|
58278
|
+
const allMcpTools = this.mcpBridge.getToolNames();
|
|
58279
|
+
const allowedMcpTools = this._filterMcpTools(allMcpTools);
|
|
58280
|
+
if (allowedMcpTools.length > 0) {
|
|
58281
|
+
systemMessage += `
|
|
57643
58282
|
## MCP Tools (JSON parameters in <params> tag)
|
|
57644
58283
|
`;
|
|
57645
|
-
|
|
57646
|
-
|
|
58284
|
+
systemMessage += this.mcpBridge.getXmlToolDefinitions(allowedMcpTools);
|
|
58285
|
+
systemMessage += `
|
|
57647
58286
|
|
|
57648
58287
|
For MCP tools, use JSON format within the params tag, e.g.:
|
|
57649
58288
|
<mcp_tool>
|
|
@@ -57652,6 +58291,7 @@ For MCP tools, use JSON format within the params tag, e.g.:
|
|
|
57652
58291
|
</params>
|
|
57653
58292
|
</mcp_tool>
|
|
57654
58293
|
`;
|
|
58294
|
+
}
|
|
57655
58295
|
}
|
|
57656
58296
|
const searchDirectory = this.allowedFolders.length > 0 ? this.allowedFolders[0] : process.cwd();
|
|
57657
58297
|
if (this.debug) {
|
|
@@ -57724,9 +58364,14 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
57724
58364
|
});
|
|
57725
58365
|
const systemMessage = await this.getSystemMessage();
|
|
57726
58366
|
let userMessage = { role: "user", content: message.trim() };
|
|
58367
|
+
if (options.schema && !options._schemaFormatted) {
|
|
58368
|
+
const schemaInstructions = generateSchemaInstructions(options.schema, { debug: this.debug });
|
|
58369
|
+
userMessage.content = message.trim() + schemaInstructions;
|
|
58370
|
+
}
|
|
57727
58371
|
if (images && images.length > 0) {
|
|
58372
|
+
const textContent = userMessage.content;
|
|
57728
58373
|
userMessage.content = [
|
|
57729
|
-
{ type: "text", text:
|
|
58374
|
+
{ type: "text", text: textContent },
|
|
57730
58375
|
...images.map((image) => ({
|
|
57731
58376
|
type: "image",
|
|
57732
58377
|
image
|
|
@@ -57808,44 +58453,83 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
57808
58453
|
}
|
|
57809
58454
|
}
|
|
57810
58455
|
let assistantResponseContent = "";
|
|
57811
|
-
|
|
57812
|
-
|
|
57813
|
-
|
|
57814
|
-
const
|
|
57815
|
-
|
|
57816
|
-
|
|
57817
|
-
|
|
57818
|
-
|
|
57819
|
-
|
|
57820
|
-
|
|
57821
|
-
|
|
57822
|
-
|
|
57823
|
-
|
|
57824
|
-
|
|
58456
|
+
let compactionAttempted = false;
|
|
58457
|
+
while (true) {
|
|
58458
|
+
try {
|
|
58459
|
+
const executeAIRequest = async () => {
|
|
58460
|
+
const messagesForAI = this.prepareMessagesWithImages(currentMessages);
|
|
58461
|
+
const result = await this.streamTextWithRetryAndFallback({
|
|
58462
|
+
model: this.provider(this.model),
|
|
58463
|
+
messages: messagesForAI,
|
|
58464
|
+
maxTokens: maxResponseTokens,
|
|
58465
|
+
temperature: 0.3
|
|
58466
|
+
});
|
|
58467
|
+
const usagePromise = result.usage;
|
|
58468
|
+
for await (const delta of result.textStream) {
|
|
58469
|
+
assistantResponseContent += delta;
|
|
58470
|
+
if (options.onStream) {
|
|
58471
|
+
options.onStream(delta);
|
|
58472
|
+
}
|
|
57825
58473
|
}
|
|
58474
|
+
const usage = await usagePromise;
|
|
58475
|
+
if (usage) {
|
|
58476
|
+
this.tokenCounter.recordUsage(usage, result.experimental_providerMetadata);
|
|
58477
|
+
}
|
|
58478
|
+
return result;
|
|
58479
|
+
};
|
|
58480
|
+
if (this.tracer) {
|
|
58481
|
+
await this.tracer.withSpan("ai.request", executeAIRequest, {
|
|
58482
|
+
"ai.model": this.model,
|
|
58483
|
+
"ai.provider": this.clientApiProvider || "auto",
|
|
58484
|
+
"iteration": currentIteration,
|
|
58485
|
+
"max_tokens": maxResponseTokens,
|
|
58486
|
+
"temperature": 0.3,
|
|
58487
|
+
"message_count": currentMessages.length
|
|
58488
|
+
});
|
|
58489
|
+
} else {
|
|
58490
|
+
await executeAIRequest();
|
|
57826
58491
|
}
|
|
57827
|
-
|
|
57828
|
-
|
|
57829
|
-
|
|
58492
|
+
break;
|
|
58493
|
+
} catch (error) {
|
|
58494
|
+
if (!compactionAttempted && handleContextLimitError) {
|
|
58495
|
+
const compactionResult = handleContextLimitError(error, currentMessages, {
|
|
58496
|
+
keepLastSegment: true,
|
|
58497
|
+
minSegmentsToKeep: 1
|
|
58498
|
+
});
|
|
58499
|
+
if (compactionResult) {
|
|
58500
|
+
const { messages: compactedMessages, stats } = compactionResult;
|
|
58501
|
+
if (stats.removed === 0) {
|
|
58502
|
+
console.error(`[ERROR] Context window exceeded but no messages can be compacted.`);
|
|
58503
|
+
console.error(`[ERROR] The conversation history is already minimal (${stats.originalCount} messages).`);
|
|
58504
|
+
finalResult = `Error: Context window limit exceeded and conversation cannot be compacted further. Consider starting a new session or reducing system message size.`;
|
|
58505
|
+
throw new Error(finalResult);
|
|
58506
|
+
}
|
|
58507
|
+
compactionAttempted = true;
|
|
58508
|
+
console.log(`[INFO] Context window limit exceeded. Compacting conversation...`);
|
|
58509
|
+
console.log(`[INFO] Removed ${stats.removed} messages (${stats.reductionPercent}% reduction)`);
|
|
58510
|
+
console.log(`[INFO] Estimated token savings: ${stats.tokensSaved} tokens`);
|
|
58511
|
+
if (this.debug) {
|
|
58512
|
+
console.log(`[DEBUG] Compaction stats:`, stats);
|
|
58513
|
+
console.log(`[DEBUG] Original message count: ${stats.originalCount}`);
|
|
58514
|
+
console.log(`[DEBUG] Compacted message count: ${stats.compactedCount}`);
|
|
58515
|
+
}
|
|
58516
|
+
currentMessages = [...compactedMessages];
|
|
58517
|
+
if (this.tracer) {
|
|
58518
|
+
this.tracer.addEvent("context.compacted", {
|
|
58519
|
+
"iteration": currentIteration,
|
|
58520
|
+
"original_count": stats.originalCount,
|
|
58521
|
+
"compacted_count": stats.compactedCount,
|
|
58522
|
+
"reduction_percent": stats.reductionPercent,
|
|
58523
|
+
"tokens_saved": stats.tokensSaved
|
|
58524
|
+
});
|
|
58525
|
+
}
|
|
58526
|
+
continue;
|
|
58527
|
+
}
|
|
57830
58528
|
}
|
|
57831
|
-
|
|
57832
|
-
|
|
57833
|
-
|
|
57834
|
-
await this.tracer.withSpan("ai.request", executeAIRequest, {
|
|
57835
|
-
"ai.model": this.model,
|
|
57836
|
-
"ai.provider": this.clientApiProvider || "auto",
|
|
57837
|
-
"iteration": currentIteration,
|
|
57838
|
-
"max_tokens": maxResponseTokens,
|
|
57839
|
-
"temperature": 0.3,
|
|
57840
|
-
"message_count": currentMessages.length
|
|
57841
|
-
});
|
|
57842
|
-
} else {
|
|
57843
|
-
await executeAIRequest();
|
|
58529
|
+
console.error(`Error during streamText (Iter ${currentIteration}):`, error);
|
|
58530
|
+
finalResult = `Error: Failed to get response from AI model during iteration ${currentIteration}. ${error.message}`;
|
|
58531
|
+
throw new Error(finalResult);
|
|
57844
58532
|
}
|
|
57845
|
-
} catch (error) {
|
|
57846
|
-
console.error(`Error during streamText (Iter ${currentIteration}):`, error);
|
|
57847
|
-
finalResult = `Error: Failed to get response from AI model during iteration ${currentIteration}. ${error.message}`;
|
|
57848
|
-
throw new Error(finalResult);
|
|
57849
58533
|
}
|
|
57850
58534
|
if (this.debug && assistantResponseContent) {
|
|
57851
58535
|
const assistantPreview = createMessagePreview(assistantResponseContent);
|
|
@@ -58116,15 +58800,7 @@ Remember: Use proper XML format with BOTH opening and closing tags:
|
|
|
58116
58800
|
<tool_name>
|
|
58117
58801
|
<parameter>value</parameter>
|
|
58118
58802
|
</tool_name>
|
|
58119
|
-
|
|
58120
|
-
IMPORTANT: A schema was provided for the final output format.
|
|
58121
|
-
|
|
58122
|
-
You MUST use attempt_completion to provide your answer:
|
|
58123
|
-
<attempt_completion>
|
|
58124
|
-
[Your complete answer here - provide in natural language, it will be automatically formatted to match the schema]
|
|
58125
|
-
</attempt_completion>
|
|
58126
|
-
|
|
58127
|
-
Your response will be automatically formatted to JSON. You can provide your answer in natural language or as JSON - either will work.`;
|
|
58803
|
+
` + generateSchemaInstructions(options.schema, { debug: this.debug }).trim();
|
|
58128
58804
|
} else {
|
|
58129
58805
|
reminderContent = `Please use one of the available tools to help answer the question, or use attempt_completion if you have enough information to provide a final answer.
|
|
58130
58806
|
|
|
@@ -58210,7 +58886,6 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
58210
58886
|
...options,
|
|
58211
58887
|
_schemaFormatted: true
|
|
58212
58888
|
});
|
|
58213
|
-
finalResult = cleanSchemaResponse(finalResult);
|
|
58214
58889
|
if (!this.disableMermaidValidation) {
|
|
58215
58890
|
try {
|
|
58216
58891
|
if (this.debug) {
|
|
@@ -58266,14 +58941,11 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
58266
58941
|
} else if (this.debug) {
|
|
58267
58942
|
console.log(`[DEBUG] Mermaid validation: Skipped due to disableMermaidValidation option`);
|
|
58268
58943
|
}
|
|
58944
|
+
finalResult = cleanSchemaResponse(finalResult);
|
|
58269
58945
|
if (isJsonSchema(options.schema)) {
|
|
58270
58946
|
if (this.debug) {
|
|
58271
58947
|
console.log(`[DEBUG] JSON validation: Starting validation process for schema response`);
|
|
58272
|
-
console.log(`[DEBUG] JSON validation:
|
|
58273
|
-
}
|
|
58274
|
-
finalResult = cleanSchemaResponse(finalResult);
|
|
58275
|
-
if (this.debug) {
|
|
58276
|
-
console.log(`[DEBUG] JSON validation: After cleaning, length: ${finalResult.length} chars`);
|
|
58948
|
+
console.log(`[DEBUG] JSON validation: Cleaned response length: ${finalResult.length} chars`);
|
|
58277
58949
|
}
|
|
58278
58950
|
if (this.tracer) {
|
|
58279
58951
|
this.tracer.recordJsonValidationEvent("started", {
|
|
@@ -58363,10 +59035,9 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
58363
59035
|
console.log("[DEBUG] Skipping schema formatting due to max iterations reached without completion");
|
|
58364
59036
|
} else if (completionAttempted && options.schema && !options._schemaFormatted && !options._skipValidation) {
|
|
58365
59037
|
try {
|
|
58366
|
-
finalResult = cleanSchemaResponse(finalResult);
|
|
58367
59038
|
if (!this.disableMermaidValidation) {
|
|
58368
59039
|
if (this.debug) {
|
|
58369
|
-
console.log(`[DEBUG] Mermaid validation: Validating attempt_completion result...`);
|
|
59040
|
+
console.log(`[DEBUG] Mermaid validation: Validating attempt_completion result BEFORE schema cleaning...`);
|
|
58370
59041
|
}
|
|
58371
59042
|
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
58372
59043
|
debug: this.debug,
|
|
@@ -58389,6 +59060,7 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
58389
59060
|
} else if (this.debug) {
|
|
58390
59061
|
console.log(`[DEBUG] Mermaid validation: Skipped for attempt_completion result due to disableMermaidValidation option`);
|
|
58391
59062
|
}
|
|
59063
|
+
finalResult = cleanSchemaResponse(finalResult);
|
|
58392
59064
|
if (isJsonSchema(options.schema)) {
|
|
58393
59065
|
if (this.debug) {
|
|
58394
59066
|
console.log(`[DEBUG] JSON validation: Starting validation process for attempt_completion result`);
|
|
@@ -58562,6 +59234,56 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
58562
59234
|
console.log(`[DEBUG] Cleared conversation history and reset counters for session ${this.sessionId}`);
|
|
58563
59235
|
}
|
|
58564
59236
|
}
|
|
59237
|
+
/**
|
|
59238
|
+
* Manually compact conversation history
|
|
59239
|
+
* Removes intermediate monologues from older segments while preserving
|
|
59240
|
+
* user messages, final answers, and the most recent segment
|
|
59241
|
+
*
|
|
59242
|
+
* @param {Object} options - Compaction options
|
|
59243
|
+
* @param {boolean} [options.keepLastSegment=true] - Keep the most recent segment intact
|
|
59244
|
+
* @param {number} [options.minSegmentsToKeep=1] - Number of recent segments to preserve fully
|
|
59245
|
+
* @returns {Object} Compaction statistics
|
|
59246
|
+
*/
|
|
59247
|
+
async compactHistory(options = {}) {
|
|
59248
|
+
const { compactMessages: compactMessages2, calculateCompactionStats: calculateCompactionStats2 } = await Promise.resolve().then(() => (init_contextCompactor(), contextCompactor_exports));
|
|
59249
|
+
if (this.history.length === 0) {
|
|
59250
|
+
if (this.debug) {
|
|
59251
|
+
console.log(`[DEBUG] No history to compact for session ${this.sessionId}`);
|
|
59252
|
+
}
|
|
59253
|
+
return {
|
|
59254
|
+
originalCount: 0,
|
|
59255
|
+
compactedCount: 0,
|
|
59256
|
+
removed: 0,
|
|
59257
|
+
reductionPercent: 0,
|
|
59258
|
+
originalTokens: 0,
|
|
59259
|
+
compactedTokens: 0,
|
|
59260
|
+
tokensSaved: 0
|
|
59261
|
+
};
|
|
59262
|
+
}
|
|
59263
|
+
const compactedMessages = compactMessages2(this.history, options);
|
|
59264
|
+
const stats = calculateCompactionStats2(this.history, compactedMessages);
|
|
59265
|
+
this.history = compactedMessages;
|
|
59266
|
+
try {
|
|
59267
|
+
await this.storageAdapter.clearHistory(this.sessionId);
|
|
59268
|
+
for (const message of compactedMessages) {
|
|
59269
|
+
await this.storageAdapter.saveMessage(this.sessionId, message);
|
|
59270
|
+
}
|
|
59271
|
+
} catch (error) {
|
|
59272
|
+
console.error(`[ERROR] Failed to save compacted messages to storage:`, error);
|
|
59273
|
+
}
|
|
59274
|
+
console.log(`[INFO] Manually compacted conversation history`);
|
|
59275
|
+
console.log(`[INFO] Removed ${stats.removed} messages (${stats.reductionPercent}% reduction)`);
|
|
59276
|
+
console.log(`[INFO] Estimated token savings: ${stats.tokensSaved} tokens`);
|
|
59277
|
+
if (this.debug) {
|
|
59278
|
+
console.log(`[DEBUG] Compaction stats:`, stats);
|
|
59279
|
+
}
|
|
59280
|
+
await this.hooks.emit(HOOK_TYPES.STORAGE_SAVE, {
|
|
59281
|
+
sessionId: this.sessionId,
|
|
59282
|
+
compacted: true,
|
|
59283
|
+
stats
|
|
59284
|
+
});
|
|
59285
|
+
return stats;
|
|
59286
|
+
}
|
|
58565
59287
|
/**
|
|
58566
59288
|
* Clone this agent's session to create a new agent with shared conversation history
|
|
58567
59289
|
* @param {Object} options - Clone options
|
|
@@ -58584,6 +59306,14 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
58584
59306
|
if (stripInternalMessages) {
|
|
58585
59307
|
clonedHistory = this._stripInternalMessages(clonedHistory, keepSystemMessage);
|
|
58586
59308
|
}
|
|
59309
|
+
let allowedToolsArray = null;
|
|
59310
|
+
if (this.allowedTools.mode === "whitelist") {
|
|
59311
|
+
allowedToolsArray = [...this.allowedTools.allowed];
|
|
59312
|
+
} else if (this.allowedTools.mode === "none") {
|
|
59313
|
+
allowedToolsArray = [];
|
|
59314
|
+
} else if (this.allowedTools.mode === "all" && this.allowedTools.exclusions.length > 0) {
|
|
59315
|
+
allowedToolsArray = ["*", ...this.allowedTools.exclusions.map((t) => "!" + t)];
|
|
59316
|
+
}
|
|
58587
59317
|
const clonedAgent = new _ProbeAgent({
|
|
58588
59318
|
// Copy current agent's config
|
|
58589
59319
|
customPrompt: this.customPrompt,
|
|
@@ -58601,6 +59331,7 @@ Convert your previous response content into actual JSON data that follows this s
|
|
|
58601
59331
|
maxIterations: this.maxIterations,
|
|
58602
59332
|
disableMermaidValidation: this.disableMermaidValidation,
|
|
58603
59333
|
disableJsonValidation: this.disableJsonValidation,
|
|
59334
|
+
allowedTools: allowedToolsArray,
|
|
58604
59335
|
enableMcp: !!this.mcpBridge,
|
|
58605
59336
|
mcpConfig: this.mcpConfig,
|
|
58606
59337
|
enableBash: this.enableBash,
|
|
@@ -59535,6 +60266,10 @@ function parseArgs() {
|
|
|
59535
60266
|
// New flag to enable outline format
|
|
59536
60267
|
noMermaidValidation: false,
|
|
59537
60268
|
// New flag to disable mermaid validation
|
|
60269
|
+
allowedTools: null,
|
|
60270
|
+
// Tool filtering: ['*'] = all, [] = none, ['tool1', 'tool2'] = specific
|
|
60271
|
+
disableTools: false,
|
|
60272
|
+
// Convenience flag to disable all tools
|
|
59538
60273
|
// Bash tool configuration
|
|
59539
60274
|
enableBash: false,
|
|
59540
60275
|
bashAllow: null,
|
|
@@ -59588,6 +60323,17 @@ function parseArgs() {
|
|
|
59588
60323
|
config.outline = true;
|
|
59589
60324
|
} else if (arg === "--no-mermaid-validation") {
|
|
59590
60325
|
config.noMermaidValidation = true;
|
|
60326
|
+
} else if (arg === "--allowed-tools" && i + 1 < args.length) {
|
|
60327
|
+
const toolsArg = args[++i];
|
|
60328
|
+
if (toolsArg === "*" || toolsArg === "all") {
|
|
60329
|
+
config.allowedTools = ["*"];
|
|
60330
|
+
} else if (toolsArg === "none" || toolsArg === "") {
|
|
60331
|
+
config.allowedTools = [];
|
|
60332
|
+
} else {
|
|
60333
|
+
config.allowedTools = toolsArg.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
60334
|
+
}
|
|
60335
|
+
} else if (arg === "--disable-tools") {
|
|
60336
|
+
config.disableTools = true;
|
|
59591
60337
|
} else if (arg === "--enable-bash") {
|
|
59592
60338
|
config.enableBash = true;
|
|
59593
60339
|
} else if (arg === "--bash-allow" && i + 1 < args.length) {
|
|
@@ -59632,6 +60378,13 @@ Options:
|
|
|
59632
60378
|
--model <name> Override model name
|
|
59633
60379
|
--allow-edit Enable code modification capabilities
|
|
59634
60380
|
--enable-delegate Enable delegate tool for task distribution to subagents
|
|
60381
|
+
--allowed-tools <tools> Filter available tools (comma-separated list)
|
|
60382
|
+
Use '*' or 'all' for all tools (default)
|
|
60383
|
+
Use 'none' or '' for no tools (raw AI mode)
|
|
60384
|
+
Specific tools: search,query,extract,listFiles,searchFiles
|
|
60385
|
+
Supports exclusion: '*,!bash' (all except bash)
|
|
60386
|
+
--disable-tools Disable all tools (raw AI mode, no code analysis)
|
|
60387
|
+
Convenience flag equivalent to --allowed-tools none
|
|
59635
60388
|
--verbose Enable verbose output
|
|
59636
60389
|
--outline Use outline-xml format for code search results
|
|
59637
60390
|
--mcp Run as MCP server
|
|
@@ -59673,6 +60426,9 @@ Examples:
|
|
|
59673
60426
|
probe agent "Analyze codebase" --schema schema.json # Schema from file
|
|
59674
60427
|
probe agent "Debug issue" --trace-file ./debug.jsonl --verbose
|
|
59675
60428
|
probe agent "Analyze code" --trace-remote http://localhost:4318/v1/traces
|
|
60429
|
+
probe agent "Explain this code" --allowed-tools search,extract # Only search and extract
|
|
60430
|
+
probe agent "What is this project about?" --allowed-tools none # Raw AI mode (no tools)
|
|
60431
|
+
probe agent "Tell me about this project" --disable-tools # Raw AI mode (convenience flag)
|
|
59676
60432
|
probe agent --mcp # Start MCP server mode
|
|
59677
60433
|
probe agent --acp # Start ACP server mode
|
|
59678
60434
|
|
|
@@ -59799,7 +60555,9 @@ var ProbeAgentMcpServer = class {
|
|
|
59799
60555
|
allowEdit: !!args.allow_edit,
|
|
59800
60556
|
debug: process.env.DEBUG === "1",
|
|
59801
60557
|
maxResponseTokens: args.max_response_tokens,
|
|
59802
|
-
disableMermaidValidation: !!args.no_mermaid_validation
|
|
60558
|
+
disableMermaidValidation: !!args.no_mermaid_validation,
|
|
60559
|
+
allowedTools: args.allowed_tools,
|
|
60560
|
+
disableTools: args.disable_tools
|
|
59803
60561
|
};
|
|
59804
60562
|
this.agent = new ProbeAgent(agentConfig2);
|
|
59805
60563
|
await this.agent.initialize();
|
|
@@ -60037,6 +60795,8 @@ async function main() {
|
|
|
60037
60795
|
outline: config.outline,
|
|
60038
60796
|
maxResponseTokens: config.maxResponseTokens,
|
|
60039
60797
|
disableMermaidValidation: config.noMermaidValidation,
|
|
60798
|
+
allowedTools: config.allowedTools,
|
|
60799
|
+
disableTools: config.disableTools,
|
|
60040
60800
|
enableBash: config.enableBash,
|
|
60041
60801
|
bashConfig
|
|
60042
60802
|
};
|