llmist 17.2.1 → 17.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/chunk-HM7PUGPA.js +2252 -0
- package/dist/chunk-HM7PUGPA.js.map +1 -0
- package/dist/index.cjs +1547 -341
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +452 -23
- package/dist/index.d.ts +452 -23
- package/dist/index.js +635 -1706
- package/dist/index.js.map +1 -1
- package/dist/runtime-GKQ6QIQP.js +187 -0
- package/dist/runtime-GKQ6QIQP.js.map +1 -0
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1,29 +1,87 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
import {
|
|
2
|
+
AbortException,
|
|
3
|
+
AbstractGadget,
|
|
4
|
+
BudgetPricingUnavailableError,
|
|
5
|
+
CHARS_PER_TOKEN,
|
|
6
|
+
DEFAULT_GADGET_OUTPUT_LIMIT,
|
|
7
|
+
DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT,
|
|
8
|
+
DEFAULT_HINTS,
|
|
9
|
+
DEFAULT_MCP_COMMAND_ALLOWLIST,
|
|
10
|
+
DEFAULT_PROMPTS,
|
|
11
|
+
FALLBACK_CONTEXT_WINDOW,
|
|
12
|
+
GADGET_ARG_PREFIX,
|
|
13
|
+
GADGET_END_PREFIX,
|
|
14
|
+
GADGET_START_PREFIX,
|
|
15
|
+
HumanInputRequiredException,
|
|
16
|
+
JsonSchemaConversionError,
|
|
17
|
+
LLMMessageBuilder,
|
|
18
|
+
McpClient,
|
|
19
|
+
McpConnectError,
|
|
20
|
+
McpError,
|
|
21
|
+
McpLifecycle,
|
|
22
|
+
McpToolCallError,
|
|
23
|
+
McpUntrustedCommandError,
|
|
24
|
+
TaskCompletionSignal,
|
|
25
|
+
TimeoutException,
|
|
26
|
+
__esm,
|
|
27
|
+
__export,
|
|
28
|
+
__require,
|
|
29
|
+
__toCommonJS,
|
|
30
|
+
assertCommandAllowed,
|
|
31
|
+
audioFromBase64,
|
|
32
|
+
audioFromBuffer,
|
|
33
|
+
createGadget,
|
|
34
|
+
createLogger,
|
|
35
|
+
createMediaOutput,
|
|
36
|
+
defaultLogger,
|
|
37
|
+
detectAudioMimeType,
|
|
38
|
+
detectImageMimeType,
|
|
39
|
+
extractMessageText,
|
|
40
|
+
gadgetError,
|
|
41
|
+
gadgetSuccess,
|
|
42
|
+
getErrorMessage,
|
|
43
|
+
imageFromBase64,
|
|
44
|
+
imageFromBuffer,
|
|
45
|
+
imageFromUrl,
|
|
46
|
+
init_allowlist,
|
|
47
|
+
init_client,
|
|
48
|
+
init_constants,
|
|
49
|
+
init_create_gadget,
|
|
50
|
+
init_errors,
|
|
51
|
+
init_exceptions,
|
|
52
|
+
init_gadget,
|
|
53
|
+
init_helpers,
|
|
54
|
+
init_input_content,
|
|
55
|
+
init_json_schema_to_zod,
|
|
56
|
+
init_lifecycle,
|
|
57
|
+
init_logger,
|
|
58
|
+
init_messages,
|
|
59
|
+
init_prompt_config,
|
|
60
|
+
init_schema_to_json,
|
|
61
|
+
init_schema_validator,
|
|
62
|
+
init_tool_adapter,
|
|
63
|
+
isAudioPart,
|
|
64
|
+
isDataUrl,
|
|
65
|
+
isImagePart,
|
|
66
|
+
isTextPart,
|
|
67
|
+
jsonSchemaToZod,
|
|
68
|
+
mcpToolToGadget,
|
|
69
|
+
normalizeMessageContent,
|
|
70
|
+
parseDataUrl,
|
|
71
|
+
resolveHintTemplate,
|
|
72
|
+
resolvePromptTemplate,
|
|
73
|
+
resolveRulesTemplate,
|
|
74
|
+
resultWithAudio,
|
|
75
|
+
resultWithFile,
|
|
76
|
+
resultWithImage,
|
|
77
|
+
resultWithImages,
|
|
78
|
+
resultWithMedia,
|
|
79
|
+
schemaToJSONSchema,
|
|
80
|
+
text,
|
|
81
|
+
toBase64,
|
|
82
|
+
validateGadgetSchema,
|
|
83
|
+
withErrorHandling
|
|
84
|
+
} from "./chunk-HM7PUGPA.js";
|
|
27
85
|
|
|
28
86
|
// src/core/execution-tree-aggregator.ts
|
|
29
87
|
var ExecutionTreeAggregator;
|
|
@@ -803,679 +861,6 @@ var init_execution_tree = __esm({
|
|
|
803
861
|
}
|
|
804
862
|
});
|
|
805
863
|
|
|
806
|
-
// src/core/constants.ts
|
|
807
|
-
var GADGET_START_PREFIX, GADGET_END_PREFIX, GADGET_ARG_PREFIX, DEFAULT_GADGET_OUTPUT_LIMIT, DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT, CHARS_PER_TOKEN, FALLBACK_CONTEXT_WINDOW;
|
|
808
|
-
var init_constants = __esm({
|
|
809
|
-
"src/core/constants.ts"() {
|
|
810
|
-
"use strict";
|
|
811
|
-
GADGET_START_PREFIX = "!!!GADGET_START:";
|
|
812
|
-
GADGET_END_PREFIX = "!!!GADGET_END";
|
|
813
|
-
GADGET_ARG_PREFIX = "!!!ARG:";
|
|
814
|
-
DEFAULT_GADGET_OUTPUT_LIMIT = true;
|
|
815
|
-
DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;
|
|
816
|
-
CHARS_PER_TOKEN = 2;
|
|
817
|
-
FALLBACK_CONTEXT_WINDOW = 128e3;
|
|
818
|
-
}
|
|
819
|
-
});
|
|
820
|
-
|
|
821
|
-
// src/core/input-content.ts
|
|
822
|
-
function isTextPart(part) {
|
|
823
|
-
return part.type === "text";
|
|
824
|
-
}
|
|
825
|
-
function isImagePart(part) {
|
|
826
|
-
return part.type === "image";
|
|
827
|
-
}
|
|
828
|
-
function isAudioPart(part) {
|
|
829
|
-
return part.type === "audio";
|
|
830
|
-
}
|
|
831
|
-
function text(content) {
|
|
832
|
-
return { type: "text", text: content };
|
|
833
|
-
}
|
|
834
|
-
function imageFromBase64(data, mediaType) {
|
|
835
|
-
return {
|
|
836
|
-
type: "image",
|
|
837
|
-
source: { type: "base64", mediaType, data }
|
|
838
|
-
};
|
|
839
|
-
}
|
|
840
|
-
function imageFromUrl(url) {
|
|
841
|
-
return {
|
|
842
|
-
type: "image",
|
|
843
|
-
source: { type: "url", url }
|
|
844
|
-
};
|
|
845
|
-
}
|
|
846
|
-
function detectImageMimeType(data) {
|
|
847
|
-
const bytes = data instanceof Buffer ? data : Buffer.from(data);
|
|
848
|
-
for (const { bytes: magic, mimeType } of IMAGE_MAGIC_BYTES) {
|
|
849
|
-
if (bytes.length >= magic.length) {
|
|
850
|
-
let matches = true;
|
|
851
|
-
for (let i = 0; i < magic.length; i++) {
|
|
852
|
-
if (bytes[i] !== magic[i]) {
|
|
853
|
-
matches = false;
|
|
854
|
-
break;
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
if (matches) {
|
|
858
|
-
if (mimeType === "image/webp") {
|
|
859
|
-
if (bytes.length >= 12) {
|
|
860
|
-
const webpMarker = bytes[8] === 87 && bytes[9] === 69 && bytes[10] === 66 && bytes[11] === 80;
|
|
861
|
-
if (!webpMarker) continue;
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
return mimeType;
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
return null;
|
|
869
|
-
}
|
|
870
|
-
function detectAudioMimeType(data) {
|
|
871
|
-
const bytes = data instanceof Buffer ? data : Buffer.from(data);
|
|
872
|
-
for (const { bytes: magic, mimeType } of AUDIO_MAGIC_BYTES) {
|
|
873
|
-
if (bytes.length >= magic.length) {
|
|
874
|
-
let matches = true;
|
|
875
|
-
for (let i = 0; i < magic.length; i++) {
|
|
876
|
-
if (bytes[i] !== magic[i]) {
|
|
877
|
-
matches = false;
|
|
878
|
-
break;
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
if (matches) {
|
|
882
|
-
if (mimeType === "audio/wav") {
|
|
883
|
-
if (bytes.length >= 12) {
|
|
884
|
-
const waveMarker = bytes[8] === 87 && bytes[9] === 65 && bytes[10] === 86 && bytes[11] === 69;
|
|
885
|
-
if (!waveMarker) continue;
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
return mimeType;
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
return null;
|
|
893
|
-
}
|
|
894
|
-
function toBase64(data) {
|
|
895
|
-
if (typeof data === "string") {
|
|
896
|
-
return data;
|
|
897
|
-
}
|
|
898
|
-
return Buffer.from(data).toString("base64");
|
|
899
|
-
}
|
|
900
|
-
function imageFromBuffer(buffer, mediaType) {
|
|
901
|
-
const detectedType = mediaType ?? detectImageMimeType(buffer);
|
|
902
|
-
if (!detectedType) {
|
|
903
|
-
throw new Error(
|
|
904
|
-
"Could not detect image MIME type. Please provide the mediaType parameter explicitly."
|
|
905
|
-
);
|
|
906
|
-
}
|
|
907
|
-
return {
|
|
908
|
-
type: "image",
|
|
909
|
-
source: {
|
|
910
|
-
type: "base64",
|
|
911
|
-
mediaType: detectedType,
|
|
912
|
-
data: toBase64(buffer)
|
|
913
|
-
}
|
|
914
|
-
};
|
|
915
|
-
}
|
|
916
|
-
function audioFromBase64(data, mediaType) {
|
|
917
|
-
return {
|
|
918
|
-
type: "audio",
|
|
919
|
-
source: { type: "base64", mediaType, data }
|
|
920
|
-
};
|
|
921
|
-
}
|
|
922
|
-
function audioFromBuffer(buffer, mediaType) {
|
|
923
|
-
const detectedType = mediaType ?? detectAudioMimeType(buffer);
|
|
924
|
-
if (!detectedType) {
|
|
925
|
-
throw new Error(
|
|
926
|
-
"Could not detect audio MIME type. Please provide the mediaType parameter explicitly."
|
|
927
|
-
);
|
|
928
|
-
}
|
|
929
|
-
return {
|
|
930
|
-
type: "audio",
|
|
931
|
-
source: {
|
|
932
|
-
type: "base64",
|
|
933
|
-
mediaType: detectedType,
|
|
934
|
-
data: toBase64(buffer)
|
|
935
|
-
}
|
|
936
|
-
};
|
|
937
|
-
}
|
|
938
|
-
function isDataUrl(input) {
|
|
939
|
-
return input.startsWith("data:");
|
|
940
|
-
}
|
|
941
|
-
function parseDataUrl(url) {
|
|
942
|
-
const match = url.match(/^data:([^;]+);base64,(.+)$/);
|
|
943
|
-
if (!match) return null;
|
|
944
|
-
return { mimeType: match[1], data: match[2] };
|
|
945
|
-
}
|
|
946
|
-
var IMAGE_MAGIC_BYTES, AUDIO_MAGIC_BYTES;
|
|
947
|
-
var init_input_content = __esm({
|
|
948
|
-
"src/core/input-content.ts"() {
|
|
949
|
-
"use strict";
|
|
950
|
-
IMAGE_MAGIC_BYTES = [
|
|
951
|
-
{ bytes: [255, 216, 255], mimeType: "image/jpeg" },
|
|
952
|
-
{ bytes: [137, 80, 78, 71], mimeType: "image/png" },
|
|
953
|
-
{ bytes: [71, 73, 70, 56], mimeType: "image/gif" },
|
|
954
|
-
// WebP starts with RIFF....WEBP
|
|
955
|
-
{ bytes: [82, 73, 70, 70], mimeType: "image/webp" }
|
|
956
|
-
];
|
|
957
|
-
AUDIO_MAGIC_BYTES = [
|
|
958
|
-
// MP3 frame sync
|
|
959
|
-
{ bytes: [255, 251], mimeType: "audio/mp3" },
|
|
960
|
-
{ bytes: [255, 250], mimeType: "audio/mp3" },
|
|
961
|
-
// ID3 tag (MP3)
|
|
962
|
-
{ bytes: [73, 68, 51], mimeType: "audio/mp3" },
|
|
963
|
-
// OGG
|
|
964
|
-
{ bytes: [79, 103, 103, 83], mimeType: "audio/ogg" },
|
|
965
|
-
// WAV (RIFF)
|
|
966
|
-
{ bytes: [82, 73, 70, 70], mimeType: "audio/wav" },
|
|
967
|
-
// WebM
|
|
968
|
-
{ bytes: [26, 69, 223, 163], mimeType: "audio/webm" },
|
|
969
|
-
// FLAC (fLaC)
|
|
970
|
-
{ bytes: [102, 76, 97, 67], mimeType: "audio/flac" }
|
|
971
|
-
];
|
|
972
|
-
}
|
|
973
|
-
});
|
|
974
|
-
|
|
975
|
-
// src/core/prompt-config.ts
|
|
976
|
-
function resolvePromptTemplate(template, defaultValue, context) {
|
|
977
|
-
const resolved = template ?? defaultValue;
|
|
978
|
-
return typeof resolved === "function" ? resolved(context) : resolved;
|
|
979
|
-
}
|
|
980
|
-
function resolveRulesTemplate(rules, context) {
|
|
981
|
-
const resolved = rules ?? DEFAULT_PROMPTS.rules;
|
|
982
|
-
if (Array.isArray(resolved)) {
|
|
983
|
-
return resolved;
|
|
984
|
-
}
|
|
985
|
-
if (typeof resolved === "function") {
|
|
986
|
-
const result = resolved(context);
|
|
987
|
-
return Array.isArray(result) ? result : [result];
|
|
988
|
-
}
|
|
989
|
-
return [resolved];
|
|
990
|
-
}
|
|
991
|
-
function resolveHintTemplate(template, defaultValue, context) {
|
|
992
|
-
const resolved = template ?? defaultValue;
|
|
993
|
-
if (typeof resolved === "function") {
|
|
994
|
-
return resolved(context);
|
|
995
|
-
}
|
|
996
|
-
return resolved.replace(/\{iteration\}/g, String(context.iteration)).replace(/\{maxIterations\}/g, String(context.maxIterations)).replace(/\{remaining\}/g, String(context.remaining));
|
|
997
|
-
}
|
|
998
|
-
var DEFAULT_HINTS, DEFAULT_PROMPTS;
|
|
999
|
-
var init_prompt_config = __esm({
|
|
1000
|
-
"src/core/prompt-config.ts"() {
|
|
1001
|
-
"use strict";
|
|
1002
|
-
DEFAULT_HINTS = {
|
|
1003
|
-
parallelGadgetsHint: "Tip: You can call multiple gadgets in a single response for efficiency.",
|
|
1004
|
-
iterationProgressHint: "[Iteration {iteration}/{maxIterations}] Plan your actions accordingly."
|
|
1005
|
-
};
|
|
1006
|
-
DEFAULT_PROMPTS = {
|
|
1007
|
-
mainInstruction: [
|
|
1008
|
-
"\u26A0\uFE0F CRITICAL: RESPOND ONLY WITH GADGET INVOCATIONS",
|
|
1009
|
-
"DO NOT use function calling or tool calling",
|
|
1010
|
-
"You must output the exact text markers shown below in plain text.",
|
|
1011
|
-
"EACH MARKER MUST START WITH A NEWLINE."
|
|
1012
|
-
].join("\n"),
|
|
1013
|
-
criticalUsage: "INVOKE gadgets using the markers - do not describe what you want to do.",
|
|
1014
|
-
formatDescription: (ctx) => `Parameters using ${ctx.argPrefix}name markers (value on next line(s), no escaping needed)`,
|
|
1015
|
-
rules: () => [
|
|
1016
|
-
"Output ONLY plain text with the exact markers - never use function/tool calling",
|
|
1017
|
-
"You can invoke multiple gadgets in a single response",
|
|
1018
|
-
"Gadgets without dependencies execute immediately (in parallel if multiple)",
|
|
1019
|
-
"Use :invocation_id:dep1,dep2 syntax when a gadget needs results from prior gadgets",
|
|
1020
|
-
"If any dependency fails, dependent gadgets are automatically skipped"
|
|
1021
|
-
],
|
|
1022
|
-
customExamples: null
|
|
1023
|
-
};
|
|
1024
|
-
}
|
|
1025
|
-
});
|
|
1026
|
-
|
|
1027
|
-
// src/core/messages.ts
|
|
1028
|
-
function normalizeMessageContent(content) {
|
|
1029
|
-
if (typeof content === "string") {
|
|
1030
|
-
return [{ type: "text", text: content }];
|
|
1031
|
-
}
|
|
1032
|
-
return content;
|
|
1033
|
-
}
|
|
1034
|
-
function extractMessageText(content) {
|
|
1035
|
-
if (typeof content === "string") {
|
|
1036
|
-
return content;
|
|
1037
|
-
}
|
|
1038
|
-
return content.filter((part) => part.type === "text").map((part) => part.text).join("");
|
|
1039
|
-
}
|
|
1040
|
-
var LLMMessageBuilder;
|
|
1041
|
-
var init_messages = __esm({
|
|
1042
|
-
"src/core/messages.ts"() {
|
|
1043
|
-
"use strict";
|
|
1044
|
-
init_constants();
|
|
1045
|
-
init_input_content();
|
|
1046
|
-
init_prompt_config();
|
|
1047
|
-
LLMMessageBuilder = class {
|
|
1048
|
-
messages = [];
|
|
1049
|
-
startPrefix = GADGET_START_PREFIX;
|
|
1050
|
-
endPrefix = GADGET_END_PREFIX;
|
|
1051
|
-
argPrefix = GADGET_ARG_PREFIX;
|
|
1052
|
-
promptConfig;
|
|
1053
|
-
constructor(promptConfig) {
|
|
1054
|
-
this.promptConfig = promptConfig ?? {};
|
|
1055
|
-
}
|
|
1056
|
-
/**
|
|
1057
|
-
* Set custom prefixes for gadget markers.
|
|
1058
|
-
* Used to configure history builder to match system prompt markers.
|
|
1059
|
-
*/
|
|
1060
|
-
withPrefixes(startPrefix, endPrefix, argPrefix) {
|
|
1061
|
-
this.startPrefix = startPrefix;
|
|
1062
|
-
this.endPrefix = endPrefix;
|
|
1063
|
-
if (argPrefix) {
|
|
1064
|
-
this.argPrefix = argPrefix;
|
|
1065
|
-
}
|
|
1066
|
-
return this;
|
|
1067
|
-
}
|
|
1068
|
-
addSystem(content, metadata) {
|
|
1069
|
-
this.messages.push({ role: "system", content, metadata });
|
|
1070
|
-
return this;
|
|
1071
|
-
}
|
|
1072
|
-
addGadgets(gadgets, options) {
|
|
1073
|
-
if (options?.startPrefix) {
|
|
1074
|
-
this.startPrefix = options.startPrefix;
|
|
1075
|
-
}
|
|
1076
|
-
if (options?.endPrefix) {
|
|
1077
|
-
this.endPrefix = options.endPrefix;
|
|
1078
|
-
}
|
|
1079
|
-
if (options?.argPrefix) {
|
|
1080
|
-
this.argPrefix = options.argPrefix;
|
|
1081
|
-
}
|
|
1082
|
-
const context = {
|
|
1083
|
-
startPrefix: this.startPrefix,
|
|
1084
|
-
endPrefix: this.endPrefix,
|
|
1085
|
-
argPrefix: this.argPrefix,
|
|
1086
|
-
gadgetCount: gadgets.length,
|
|
1087
|
-
gadgetNames: gadgets.map((g) => g.name ?? g.constructor.name)
|
|
1088
|
-
};
|
|
1089
|
-
const parts = [];
|
|
1090
|
-
const mainInstruction = resolvePromptTemplate(
|
|
1091
|
-
this.promptConfig.mainInstruction,
|
|
1092
|
-
DEFAULT_PROMPTS.mainInstruction,
|
|
1093
|
-
context
|
|
1094
|
-
);
|
|
1095
|
-
parts.push(mainInstruction);
|
|
1096
|
-
parts.push(this.buildGadgetsSection(gadgets));
|
|
1097
|
-
parts.push(this.buildUsageSection(context));
|
|
1098
|
-
this.messages.push({ role: "system", content: parts.join("") });
|
|
1099
|
-
return this;
|
|
1100
|
-
}
|
|
1101
|
-
buildGadgetsSection(gadgets) {
|
|
1102
|
-
const parts = [];
|
|
1103
|
-
parts.push("\n\nAVAILABLE GADGETS");
|
|
1104
|
-
parts.push("\n=================\n");
|
|
1105
|
-
for (const gadget of gadgets) {
|
|
1106
|
-
const gadgetName = gadget.name ?? gadget.constructor.name;
|
|
1107
|
-
const instruction = gadget.getInstruction({
|
|
1108
|
-
argPrefix: this.argPrefix,
|
|
1109
|
-
startPrefix: this.startPrefix,
|
|
1110
|
-
endPrefix: this.endPrefix
|
|
1111
|
-
});
|
|
1112
|
-
const schemaMarker = "\n\nInput Schema (BLOCK):";
|
|
1113
|
-
const schemaIndex = instruction.indexOf(schemaMarker);
|
|
1114
|
-
const description = (schemaIndex !== -1 ? instruction.substring(0, schemaIndex) : instruction).trim();
|
|
1115
|
-
const schema = schemaIndex !== -1 ? instruction.substring(schemaIndex + schemaMarker.length).trim() : "";
|
|
1116
|
-
parts.push(`
|
|
1117
|
-
GADGET: ${gadgetName}`);
|
|
1118
|
-
parts.push(`
|
|
1119
|
-
${description}`);
|
|
1120
|
-
if (schema) {
|
|
1121
|
-
parts.push(`
|
|
1122
|
-
|
|
1123
|
-
PARAMETERS (BLOCK):
|
|
1124
|
-
${schema}`);
|
|
1125
|
-
}
|
|
1126
|
-
parts.push("\n\n---");
|
|
1127
|
-
}
|
|
1128
|
-
return parts.join("");
|
|
1129
|
-
}
|
|
1130
|
-
buildUsageSection(context) {
|
|
1131
|
-
const parts = [];
|
|
1132
|
-
const formatDescription = resolvePromptTemplate(
|
|
1133
|
-
this.promptConfig.formatDescription,
|
|
1134
|
-
DEFAULT_PROMPTS.formatDescription,
|
|
1135
|
-
context
|
|
1136
|
-
);
|
|
1137
|
-
parts.push("\n\nHOW TO INVOKE GADGETS");
|
|
1138
|
-
parts.push("\n=====================\n");
|
|
1139
|
-
const criticalUsage = resolvePromptTemplate(
|
|
1140
|
-
this.promptConfig.criticalUsage,
|
|
1141
|
-
DEFAULT_PROMPTS.criticalUsage,
|
|
1142
|
-
context
|
|
1143
|
-
);
|
|
1144
|
-
parts.push(`
|
|
1145
|
-
CRITICAL: ${criticalUsage}
|
|
1146
|
-
`);
|
|
1147
|
-
parts.push("\nFORMAT:");
|
|
1148
|
-
parts.push(`
|
|
1149
|
-
1. Start marker: ${this.startPrefix}gadget_name`);
|
|
1150
|
-
parts.push(`
|
|
1151
|
-
With ID: ${this.startPrefix}gadget_name:my_id`);
|
|
1152
|
-
parts.push(`
|
|
1153
|
-
With dependencies: ${this.startPrefix}gadget_name:my_id:dep1,dep2`);
|
|
1154
|
-
parts.push(`
|
|
1155
|
-
2. ${formatDescription}`);
|
|
1156
|
-
parts.push(`
|
|
1157
|
-
3. End marker: ${this.endPrefix}`);
|
|
1158
|
-
parts.push(this.buildExamplesSection(context));
|
|
1159
|
-
parts.push(this.buildRulesSection(context));
|
|
1160
|
-
parts.push("\n");
|
|
1161
|
-
return parts.join("");
|
|
1162
|
-
}
|
|
1163
|
-
buildExamplesSection(context) {
|
|
1164
|
-
if (this.promptConfig.customExamples) {
|
|
1165
|
-
return this.promptConfig.customExamples(context);
|
|
1166
|
-
}
|
|
1167
|
-
const parts = [];
|
|
1168
|
-
const singleExample = `${this.startPrefix}translate
|
|
1169
|
-
${this.argPrefix}from
|
|
1170
|
-
English
|
|
1171
|
-
${this.argPrefix}to
|
|
1172
|
-
Polish
|
|
1173
|
-
${this.argPrefix}content
|
|
1174
|
-
Paris is the capital of France: a beautiful city.
|
|
1175
|
-
${this.endPrefix}`;
|
|
1176
|
-
parts.push(`
|
|
1177
|
-
|
|
1178
|
-
EXAMPLE (Single Gadget):
|
|
1179
|
-
|
|
1180
|
-
${singleExample}`);
|
|
1181
|
-
const multipleExample = `${this.startPrefix}translate
|
|
1182
|
-
${this.argPrefix}from
|
|
1183
|
-
English
|
|
1184
|
-
${this.argPrefix}to
|
|
1185
|
-
Polish
|
|
1186
|
-
${this.argPrefix}content
|
|
1187
|
-
Paris is the capital of France: a beautiful city.
|
|
1188
|
-
${this.endPrefix}
|
|
1189
|
-
${this.startPrefix}analyze
|
|
1190
|
-
${this.argPrefix}type
|
|
1191
|
-
economic_analysis
|
|
1192
|
-
${this.argPrefix}matter
|
|
1193
|
-
Polish Economy
|
|
1194
|
-
${this.argPrefix}question
|
|
1195
|
-
Analyze the following:
|
|
1196
|
-
- Polish arms exports 2025
|
|
1197
|
-
- Economic implications
|
|
1198
|
-
${this.endPrefix}`;
|
|
1199
|
-
parts.push(`
|
|
1200
|
-
|
|
1201
|
-
EXAMPLE (Multiple Gadgets):
|
|
1202
|
-
|
|
1203
|
-
${multipleExample}`);
|
|
1204
|
-
const dependencyExample = `${this.startPrefix}fetch_data:fetch_1
|
|
1205
|
-
${this.argPrefix}url
|
|
1206
|
-
https://api.example.com/users
|
|
1207
|
-
${this.endPrefix}
|
|
1208
|
-
${this.startPrefix}fetch_data:fetch_2
|
|
1209
|
-
${this.argPrefix}url
|
|
1210
|
-
https://api.example.com/orders
|
|
1211
|
-
${this.endPrefix}
|
|
1212
|
-
${this.startPrefix}merge_data:merge_1:fetch_1,fetch_2
|
|
1213
|
-
${this.argPrefix}format
|
|
1214
|
-
json
|
|
1215
|
-
${this.endPrefix}`;
|
|
1216
|
-
parts.push(`
|
|
1217
|
-
|
|
1218
|
-
EXAMPLE (With Dependencies):
|
|
1219
|
-
merge_1 waits for fetch_1 AND fetch_2 to complete.
|
|
1220
|
-
If either fails, merge_1 is automatically skipped.
|
|
1221
|
-
|
|
1222
|
-
${dependencyExample}`);
|
|
1223
|
-
parts.push(`
|
|
1224
|
-
|
|
1225
|
-
BLOCK FORMAT SYNTAX:
|
|
1226
|
-
Block format uses ${this.argPrefix}name markers. Values are captured verbatim until the next marker.
|
|
1227
|
-
|
|
1228
|
-
${this.argPrefix}filename
|
|
1229
|
-
calculator.ts
|
|
1230
|
-
${this.argPrefix}code
|
|
1231
|
-
class Calculator {
|
|
1232
|
-
private history: string[] = [];
|
|
1233
|
-
|
|
1234
|
-
add(a: number, b: number): number {
|
|
1235
|
-
const result = a + b;
|
|
1236
|
-
this.history.push(\`\${a} + \${b} = \${result}\`);
|
|
1237
|
-
return result;
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
|
-
BLOCK FORMAT RULES:
|
|
1242
|
-
- Each parameter starts with ${this.argPrefix}parameterName on its own line
|
|
1243
|
-
- The value starts on the NEXT line after the marker
|
|
1244
|
-
- Value ends when the next ${this.argPrefix} or ${this.endPrefix} appears
|
|
1245
|
-
- NO escaping needed - write values exactly as they should appear
|
|
1246
|
-
- Perfect for code, JSON, markdown, or any content with special characters
|
|
1247
|
-
|
|
1248
|
-
NESTED OBJECTS (use / separator):
|
|
1249
|
-
${this.argPrefix}config/timeout
|
|
1250
|
-
30
|
|
1251
|
-
${this.argPrefix}config/retries
|
|
1252
|
-
3
|
|
1253
|
-
Produces: { "config": { "timeout": "30", "retries": "3" } }
|
|
1254
|
-
|
|
1255
|
-
ARRAYS (use numeric indices):
|
|
1256
|
-
${this.argPrefix}items/0
|
|
1257
|
-
first
|
|
1258
|
-
${this.argPrefix}items/1
|
|
1259
|
-
second
|
|
1260
|
-
Produces: { "items": ["first", "second"] }`);
|
|
1261
|
-
return parts.join("");
|
|
1262
|
-
}
|
|
1263
|
-
buildRulesSection(context) {
|
|
1264
|
-
const parts = [];
|
|
1265
|
-
parts.push("\n\nRULES:");
|
|
1266
|
-
const rules = resolveRulesTemplate(this.promptConfig.rules, context);
|
|
1267
|
-
for (const rule of rules) {
|
|
1268
|
-
parts.push(`
|
|
1269
|
-
- ${rule}`);
|
|
1270
|
-
}
|
|
1271
|
-
return parts.join("");
|
|
1272
|
-
}
|
|
1273
|
-
/**
|
|
1274
|
-
* Add a user message.
|
|
1275
|
-
* Content can be a string (text only) or an array of content parts (multimodal).
|
|
1276
|
-
*
|
|
1277
|
-
* @param content - Message content
|
|
1278
|
-
* @param metadata - Optional metadata
|
|
1279
|
-
*
|
|
1280
|
-
* @example
|
|
1281
|
-
* ```typescript
|
|
1282
|
-
* // Text only
|
|
1283
|
-
* builder.addUser("Hello!");
|
|
1284
|
-
*
|
|
1285
|
-
* // Multimodal
|
|
1286
|
-
* builder.addUser([
|
|
1287
|
-
* text("What's in this image?"),
|
|
1288
|
-
* imageFromBuffer(imageData),
|
|
1289
|
-
* ]);
|
|
1290
|
-
* ```
|
|
1291
|
-
*/
|
|
1292
|
-
addUser(content, metadata) {
|
|
1293
|
-
this.messages.push({ role: "user", content, metadata });
|
|
1294
|
-
return this;
|
|
1295
|
-
}
|
|
1296
|
-
addAssistant(content, metadata) {
|
|
1297
|
-
this.messages.push({ role: "assistant", content, metadata });
|
|
1298
|
-
return this;
|
|
1299
|
-
}
|
|
1300
|
-
/**
|
|
1301
|
-
* Add a user message with an image attachment.
|
|
1302
|
-
*
|
|
1303
|
-
* @param textContent - Text prompt
|
|
1304
|
-
* @param imageData - Image data (Buffer, Uint8Array, or base64 string)
|
|
1305
|
-
* @param mimeType - Optional MIME type (auto-detected if not provided)
|
|
1306
|
-
*
|
|
1307
|
-
* @example
|
|
1308
|
-
* ```typescript
|
|
1309
|
-
* builder.addUserWithImage(
|
|
1310
|
-
* "What's in this image?",
|
|
1311
|
-
* await fs.readFile("photo.jpg"),
|
|
1312
|
-
* "image/jpeg" // Optional - auto-detected
|
|
1313
|
-
* );
|
|
1314
|
-
* ```
|
|
1315
|
-
*/
|
|
1316
|
-
addUserWithImage(textContent, imageData, mimeType) {
|
|
1317
|
-
const imageBuffer = typeof imageData === "string" ? Buffer.from(imageData, "base64") : imageData;
|
|
1318
|
-
const detectedMime = mimeType ?? detectImageMimeType(imageBuffer);
|
|
1319
|
-
if (!detectedMime) {
|
|
1320
|
-
throw new Error(
|
|
1321
|
-
"Could not detect image MIME type. Please provide the mimeType parameter explicitly."
|
|
1322
|
-
);
|
|
1323
|
-
}
|
|
1324
|
-
const content = [
|
|
1325
|
-
text(textContent),
|
|
1326
|
-
{
|
|
1327
|
-
type: "image",
|
|
1328
|
-
source: {
|
|
1329
|
-
type: "base64",
|
|
1330
|
-
mediaType: detectedMime,
|
|
1331
|
-
data: toBase64(imageBuffer)
|
|
1332
|
-
}
|
|
1333
|
-
}
|
|
1334
|
-
];
|
|
1335
|
-
this.messages.push({ role: "user", content });
|
|
1336
|
-
return this;
|
|
1337
|
-
}
|
|
1338
|
-
/**
|
|
1339
|
-
* Add a user message with an image URL (OpenAI only).
|
|
1340
|
-
*
|
|
1341
|
-
* @param textContent - Text prompt
|
|
1342
|
-
* @param imageUrl - URL to the image
|
|
1343
|
-
*
|
|
1344
|
-
* @example
|
|
1345
|
-
* ```typescript
|
|
1346
|
-
* builder.addUserWithImageUrl(
|
|
1347
|
-
* "What's in this image?",
|
|
1348
|
-
* "https://example.com/image.jpg"
|
|
1349
|
-
* );
|
|
1350
|
-
* ```
|
|
1351
|
-
*/
|
|
1352
|
-
addUserWithImageUrl(textContent, imageUrl) {
|
|
1353
|
-
const content = [text(textContent), imageFromUrl(imageUrl)];
|
|
1354
|
-
this.messages.push({ role: "user", content });
|
|
1355
|
-
return this;
|
|
1356
|
-
}
|
|
1357
|
-
/**
|
|
1358
|
-
* Add a user message with an audio attachment (Gemini only).
|
|
1359
|
-
*
|
|
1360
|
-
* @param textContent - Text prompt
|
|
1361
|
-
* @param audioData - Audio data (Buffer, Uint8Array, or base64 string)
|
|
1362
|
-
* @param mimeType - Optional MIME type (auto-detected if not provided)
|
|
1363
|
-
*
|
|
1364
|
-
* @example
|
|
1365
|
-
* ```typescript
|
|
1366
|
-
* builder.addUserWithAudio(
|
|
1367
|
-
* "Transcribe this audio",
|
|
1368
|
-
* await fs.readFile("recording.mp3"),
|
|
1369
|
-
* "audio/mp3" // Optional - auto-detected
|
|
1370
|
-
* );
|
|
1371
|
-
* ```
|
|
1372
|
-
*/
|
|
1373
|
-
addUserWithAudio(textContent, audioData, mimeType) {
|
|
1374
|
-
const audioBuffer = typeof audioData === "string" ? Buffer.from(audioData, "base64") : audioData;
|
|
1375
|
-
const content = [text(textContent), audioFromBuffer(audioBuffer, mimeType)];
|
|
1376
|
-
this.messages.push({ role: "user", content });
|
|
1377
|
-
return this;
|
|
1378
|
-
}
|
|
1379
|
-
/**
|
|
1380
|
-
* Add a user message with multiple content parts.
|
|
1381
|
-
* Provides full flexibility for complex multimodal messages.
|
|
1382
|
-
*
|
|
1383
|
-
* @param parts - Array of content parts
|
|
1384
|
-
*
|
|
1385
|
-
* @example
|
|
1386
|
-
* ```typescript
|
|
1387
|
-
* builder.addUserMultimodal([
|
|
1388
|
-
* text("Compare these images:"),
|
|
1389
|
-
* imageFromBuffer(image1),
|
|
1390
|
-
* imageFromBuffer(image2),
|
|
1391
|
-
* ]);
|
|
1392
|
-
* ```
|
|
1393
|
-
*/
|
|
1394
|
-
addUserMultimodal(parts) {
|
|
1395
|
-
this.messages.push({ role: "user", content: parts });
|
|
1396
|
-
return this;
|
|
1397
|
-
}
|
|
1398
|
-
/**
|
|
1399
|
-
* Record a gadget execution result in the message history.
|
|
1400
|
-
* Creates an assistant message with the gadget invocation and a user message with the result.
|
|
1401
|
-
*
|
|
1402
|
-
* The invocationId is shown to the LLM so it can reference previous calls when building dependencies.
|
|
1403
|
-
*
|
|
1404
|
-
* @param gadget - Name of the gadget that was executed
|
|
1405
|
-
* @param parameters - Parameters that were passed to the gadget
|
|
1406
|
-
* @param result - Text result from the gadget execution
|
|
1407
|
-
* @param invocationId - Invocation ID (shown to LLM so it can reference for dependencies)
|
|
1408
|
-
* @param media - Optional media outputs from the gadget
|
|
1409
|
-
* @param mediaIds - Optional IDs for the media outputs
|
|
1410
|
-
* @param storedMedia - Optional stored media info including file paths
|
|
1411
|
-
*/
|
|
1412
|
-
addGadgetCallResult(gadget, parameters, result, invocationId, media, mediaIds, storedMedia) {
|
|
1413
|
-
const paramStr = this.formatBlockParameters(parameters, "");
|
|
1414
|
-
this.messages.push({
|
|
1415
|
-
role: "assistant",
|
|
1416
|
-
content: `${this.startPrefix}${gadget}:${invocationId}
|
|
1417
|
-
${paramStr}
|
|
1418
|
-
${this.endPrefix}`
|
|
1419
|
-
});
|
|
1420
|
-
if (media && media.length > 0 && mediaIds && mediaIds.length > 0) {
|
|
1421
|
-
const idRefs = media.map((m, i) => {
|
|
1422
|
-
const path3 = storedMedia?.[i]?.path;
|
|
1423
|
-
const pathInfo = path3 ? ` \u2192 saved to: ${path3}` : "";
|
|
1424
|
-
return `[Media: ${mediaIds[i]} (${m.kind})${pathInfo}]`;
|
|
1425
|
-
}).join("\n");
|
|
1426
|
-
const textWithIds = `Result (${invocationId}): ${result}
|
|
1427
|
-
${idRefs}`;
|
|
1428
|
-
const parts = [text(textWithIds)];
|
|
1429
|
-
for (const item of media) {
|
|
1430
|
-
if (item.kind === "image") {
|
|
1431
|
-
parts.push(imageFromBase64(item.data, item.mimeType));
|
|
1432
|
-
} else if (item.kind === "audio") {
|
|
1433
|
-
parts.push(audioFromBase64(item.data, item.mimeType));
|
|
1434
|
-
}
|
|
1435
|
-
}
|
|
1436
|
-
this.messages.push({ role: "user", content: parts });
|
|
1437
|
-
} else {
|
|
1438
|
-
this.messages.push({
|
|
1439
|
-
role: "user",
|
|
1440
|
-
content: `Result (${invocationId}): ${result}`
|
|
1441
|
-
});
|
|
1442
|
-
}
|
|
1443
|
-
return this;
|
|
1444
|
-
}
|
|
1445
|
-
/**
|
|
1446
|
-
* Format parameters as Block format with JSON Pointer paths.
|
|
1447
|
-
* Uses the configured argPrefix for consistency with system prompt.
|
|
1448
|
-
*/
|
|
1449
|
-
formatBlockParameters(params, prefix) {
|
|
1450
|
-
const lines = [];
|
|
1451
|
-
for (const [key, value] of Object.entries(params)) {
|
|
1452
|
-
const fullPath = prefix ? `${prefix}/${key}` : key;
|
|
1453
|
-
if (Array.isArray(value)) {
|
|
1454
|
-
value.forEach((item, index) => {
|
|
1455
|
-
const itemPath = `${fullPath}/${index}`;
|
|
1456
|
-
if (typeof item === "object" && item !== null) {
|
|
1457
|
-
lines.push(this.formatBlockParameters(item, itemPath));
|
|
1458
|
-
} else {
|
|
1459
|
-
lines.push(`${this.argPrefix}${itemPath}`);
|
|
1460
|
-
lines.push(String(item));
|
|
1461
|
-
}
|
|
1462
|
-
});
|
|
1463
|
-
} else if (typeof value === "object" && value !== null) {
|
|
1464
|
-
lines.push(this.formatBlockParameters(value, fullPath));
|
|
1465
|
-
} else {
|
|
1466
|
-
lines.push(`${this.argPrefix}${fullPath}`);
|
|
1467
|
-
lines.push(String(value));
|
|
1468
|
-
}
|
|
1469
|
-
}
|
|
1470
|
-
return lines.join("\n");
|
|
1471
|
-
}
|
|
1472
|
-
build() {
|
|
1473
|
-
return [...this.messages];
|
|
1474
|
-
}
|
|
1475
|
-
};
|
|
1476
|
-
}
|
|
1477
|
-
});
|
|
1478
|
-
|
|
1479
864
|
// src/core/model-shortcuts.ts
|
|
1480
865
|
function isKnownModelPattern(model) {
|
|
1481
866
|
const normalized = model.toLowerCase();
|
|
@@ -2178,56 +1563,6 @@ var init_retry = __esm({
|
|
|
2178
1563
|
}
|
|
2179
1564
|
});
|
|
2180
1565
|
|
|
2181
|
-
// src/gadgets/exceptions.ts
|
|
2182
|
-
var TaskCompletionSignal, HumanInputRequiredException, TimeoutException, AbortException, BudgetPricingUnavailableError;
|
|
2183
|
-
var init_exceptions = __esm({
|
|
2184
|
-
"src/gadgets/exceptions.ts"() {
|
|
2185
|
-
"use strict";
|
|
2186
|
-
TaskCompletionSignal = class extends Error {
|
|
2187
|
-
constructor(message) {
|
|
2188
|
-
super(message ?? "Agent loop terminated by gadget");
|
|
2189
|
-
this.name = "TaskCompletionSignal";
|
|
2190
|
-
}
|
|
2191
|
-
};
|
|
2192
|
-
HumanInputRequiredException = class extends Error {
|
|
2193
|
-
question;
|
|
2194
|
-
constructor(question) {
|
|
2195
|
-
super(`Human input required: ${question}`);
|
|
2196
|
-
this.name = "HumanInputRequiredException";
|
|
2197
|
-
this.question = question;
|
|
2198
|
-
}
|
|
2199
|
-
};
|
|
2200
|
-
TimeoutException = class extends Error {
|
|
2201
|
-
timeoutMs;
|
|
2202
|
-
gadgetName;
|
|
2203
|
-
constructor(gadgetName, timeoutMs) {
|
|
2204
|
-
super(`Gadget '${gadgetName}' execution exceeded timeout of ${timeoutMs}ms`);
|
|
2205
|
-
this.name = "TimeoutException";
|
|
2206
|
-
this.gadgetName = gadgetName;
|
|
2207
|
-
this.timeoutMs = timeoutMs;
|
|
2208
|
-
}
|
|
2209
|
-
};
|
|
2210
|
-
AbortException = class extends Error {
|
|
2211
|
-
constructor(message) {
|
|
2212
|
-
super(message || "Gadget execution was aborted");
|
|
2213
|
-
this.name = "AbortException";
|
|
2214
|
-
}
|
|
2215
|
-
};
|
|
2216
|
-
BudgetPricingUnavailableError = class extends Error {
|
|
2217
|
-
model;
|
|
2218
|
-
budget;
|
|
2219
|
-
constructor(model, budget) {
|
|
2220
|
-
super(
|
|
2221
|
-
`Budget of $${budget.toFixed(2)} was set but model "${model}" has no valid pricing information in the model registry. Either register pricing for this model via client.modelRegistry.registerModel() or remove the budget constraint.`
|
|
2222
|
-
);
|
|
2223
|
-
this.name = "BudgetPricingUnavailableError";
|
|
2224
|
-
this.model = model;
|
|
2225
|
-
this.budget = budget;
|
|
2226
|
-
}
|
|
2227
|
-
};
|
|
2228
|
-
}
|
|
2229
|
-
});
|
|
2230
|
-
|
|
2231
1566
|
// src/gadgets/media-store.ts
|
|
2232
1567
|
import { randomBytes } from "crypto";
|
|
2233
1568
|
import { mkdir, rm, writeFile } from "fs/promises";
|
|
@@ -2404,151 +1739,31 @@ var init_media_store = __esm({
|
|
|
2404
1739
|
* Check if a media ID exists.
|
|
2405
1740
|
*/
|
|
2406
1741
|
has(id) {
|
|
2407
|
-
return this.items.has(id);
|
|
2408
|
-
}
|
|
2409
|
-
/**
|
|
2410
|
-
* Clear in-memory store without deleting files.
|
|
2411
|
-
* Resets the counter but leaves files on disk.
|
|
2412
|
-
*/
|
|
2413
|
-
clear() {
|
|
2414
|
-
this.items.clear();
|
|
2415
|
-
this.counter = 0;
|
|
2416
|
-
}
|
|
2417
|
-
/**
|
|
2418
|
-
* Delete all stored files and clear memory.
|
|
2419
|
-
* Removes the entire session directory.
|
|
2420
|
-
*/
|
|
2421
|
-
async cleanup() {
|
|
2422
|
-
if (this.initialized) {
|
|
2423
|
-
try {
|
|
2424
|
-
await rm(this.outputDir, { recursive: true, force: true });
|
|
2425
|
-
} catch {
|
|
2426
|
-
}
|
|
2427
|
-
this.initialized = false;
|
|
2428
|
-
}
|
|
2429
|
-
this.clear();
|
|
2430
|
-
}
|
|
2431
|
-
};
|
|
2432
|
-
}
|
|
2433
|
-
});
|
|
2434
|
-
|
|
2435
|
-
// src/logging/logger.ts
|
|
2436
|
-
import { createWriteStream, mkdirSync } from "fs";
|
|
2437
|
-
import { dirname } from "path";
|
|
2438
|
-
import { Logger } from "tslog";
|
|
2439
|
-
function parseLogLevel(value) {
|
|
2440
|
-
if (!value) {
|
|
2441
|
-
return void 0;
|
|
2442
|
-
}
|
|
2443
|
-
const normalized = value.trim().toLowerCase();
|
|
2444
|
-
if (normalized === "") {
|
|
2445
|
-
return void 0;
|
|
2446
|
-
}
|
|
2447
|
-
const numericLevel = Number(normalized);
|
|
2448
|
-
if (Number.isFinite(numericLevel)) {
|
|
2449
|
-
return Math.max(0, Math.min(6, Math.floor(numericLevel)));
|
|
2450
|
-
}
|
|
2451
|
-
return LEVEL_NAME_TO_ID[normalized];
|
|
2452
|
-
}
|
|
2453
|
-
function parseEnvBoolean(value) {
|
|
2454
|
-
if (!value) return void 0;
|
|
2455
|
-
const normalized = value.trim().toLowerCase();
|
|
2456
|
-
if (normalized === "true" || normalized === "1") return true;
|
|
2457
|
-
if (normalized === "false" || normalized === "0") return false;
|
|
2458
|
-
return void 0;
|
|
2459
|
-
}
|
|
2460
|
-
function stripAnsi(str) {
|
|
2461
|
-
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
2462
|
-
}
|
|
2463
|
-
function createLogger(options = {}) {
|
|
2464
|
-
const envMinLevel = parseLogLevel(process.env.LLMIST_LOG_LEVEL);
|
|
2465
|
-
const envLogFile = process.env.LLMIST_LOG_FILE?.trim() ?? "";
|
|
2466
|
-
const envLogReset = parseEnvBoolean(process.env.LLMIST_LOG_RESET);
|
|
2467
|
-
const minLevel = options.minLevel ?? envMinLevel ?? 4;
|
|
2468
|
-
const defaultType = options.type ?? "pretty";
|
|
2469
|
-
const name = options.name ?? "llmist";
|
|
2470
|
-
const logReset = options.logReset ?? envLogReset ?? false;
|
|
2471
|
-
const envLogTee = parseEnvBoolean(process.env.LLMIST_LOG_TEE);
|
|
2472
|
-
const teeToConsole = options.teeToConsole ?? envLogTee ?? false;
|
|
2473
|
-
if (envLogFile && (!logFileInitialized || sharedLogFilePath !== envLogFile)) {
|
|
2474
|
-
try {
|
|
2475
|
-
if (sharedLogFileStream) {
|
|
2476
|
-
sharedLogFileStream.end();
|
|
2477
|
-
sharedLogFileStream = void 0;
|
|
2478
|
-
}
|
|
2479
|
-
mkdirSync(dirname(envLogFile), { recursive: true });
|
|
2480
|
-
const flags = logReset ? "w" : "a";
|
|
2481
|
-
sharedLogFileStream = createWriteStream(envLogFile, { flags });
|
|
2482
|
-
sharedLogFilePath = envLogFile;
|
|
2483
|
-
logFileInitialized = true;
|
|
2484
|
-
writeErrorCount = 0;
|
|
2485
|
-
writeErrorReported = false;
|
|
2486
|
-
sharedLogFileStream.on("error", (error) => {
|
|
2487
|
-
writeErrorCount++;
|
|
2488
|
-
if (!writeErrorReported) {
|
|
2489
|
-
console.error(`[llmist] Log file write error: ${error.message}`);
|
|
2490
|
-
writeErrorReported = true;
|
|
2491
|
-
}
|
|
2492
|
-
if (writeErrorCount >= MAX_WRITE_ERRORS_BEFORE_DISABLE) {
|
|
2493
|
-
console.error(
|
|
2494
|
-
`[llmist] Too many log file errors (${writeErrorCount}), disabling file logging`
|
|
2495
|
-
);
|
|
2496
|
-
sharedLogFileStream?.end();
|
|
2497
|
-
sharedLogFileStream = void 0;
|
|
2498
|
-
}
|
|
2499
|
-
});
|
|
2500
|
-
} catch (error) {
|
|
2501
|
-
console.error("Failed to initialize LLMIST_LOG_FILE output:", error);
|
|
2502
|
-
}
|
|
2503
|
-
}
|
|
2504
|
-
const useFileLogging = Boolean(sharedLogFileStream);
|
|
2505
|
-
const logger2 = new Logger({
|
|
2506
|
-
name,
|
|
2507
|
-
minLevel,
|
|
2508
|
-
type: useFileLogging ? "pretty" : defaultType,
|
|
2509
|
-
// Hide log position for file logging and non-pretty types
|
|
2510
|
-
hideLogPositionForProduction: useFileLogging || defaultType !== "pretty",
|
|
2511
|
-
prettyLogTemplate: LOG_TEMPLATE,
|
|
2512
|
-
// Use overwrite to redirect tslog's formatted output to file instead of console
|
|
2513
|
-
overwrite: useFileLogging ? {
|
|
2514
|
-
transportFormatted: (logMetaMarkup, logArgs, _logErrors) => {
|
|
2515
|
-
const args = logArgs.map(
|
|
2516
|
-
(arg) => typeof arg === "string" ? arg : JSON.stringify(arg)
|
|
2517
|
-
);
|
|
2518
|
-
if (sharedLogFileStream) {
|
|
2519
|
-
const meta = stripAnsi(logMetaMarkup);
|
|
2520
|
-
const fileArgs = args.map((a) => stripAnsi(a));
|
|
2521
|
-
sharedLogFileStream.write(`${meta}${fileArgs.join(" ")}
|
|
2522
|
-
`);
|
|
2523
|
-
}
|
|
2524
|
-
if (teeToConsole) {
|
|
2525
|
-
process.stdout.write(`${logMetaMarkup}${args.join(" ")}
|
|
2526
|
-
`);
|
|
1742
|
+
return this.items.has(id);
|
|
1743
|
+
}
|
|
1744
|
+
/**
|
|
1745
|
+
* Clear in-memory store without deleting files.
|
|
1746
|
+
* Resets the counter but leaves files on disk.
|
|
1747
|
+
*/
|
|
1748
|
+
clear() {
|
|
1749
|
+
this.items.clear();
|
|
1750
|
+
this.counter = 0;
|
|
1751
|
+
}
|
|
1752
|
+
/**
|
|
1753
|
+
* Delete all stored files and clear memory.
|
|
1754
|
+
* Removes the entire session directory.
|
|
1755
|
+
*/
|
|
1756
|
+
async cleanup() {
|
|
1757
|
+
if (this.initialized) {
|
|
1758
|
+
try {
|
|
1759
|
+
await rm(this.outputDir, { recursive: true, force: true });
|
|
1760
|
+
} catch {
|
|
1761
|
+
}
|
|
1762
|
+
this.initialized = false;
|
|
2527
1763
|
}
|
|
1764
|
+
this.clear();
|
|
2528
1765
|
}
|
|
2529
|
-
} : void 0
|
|
2530
|
-
});
|
|
2531
|
-
return logger2;
|
|
2532
|
-
}
|
|
2533
|
-
var LEVEL_NAME_TO_ID, sharedLogFilePath, sharedLogFileStream, logFileInitialized, writeErrorCount, writeErrorReported, MAX_WRITE_ERRORS_BEFORE_DISABLE, LOG_TEMPLATE, defaultLogger;
|
|
2534
|
-
var init_logger = __esm({
|
|
2535
|
-
"src/logging/logger.ts"() {
|
|
2536
|
-
"use strict";
|
|
2537
|
-
LEVEL_NAME_TO_ID = {
|
|
2538
|
-
silly: 0,
|
|
2539
|
-
trace: 1,
|
|
2540
|
-
debug: 2,
|
|
2541
|
-
info: 3,
|
|
2542
|
-
warn: 4,
|
|
2543
|
-
error: 5,
|
|
2544
|
-
fatal: 6
|
|
2545
1766
|
};
|
|
2546
|
-
logFileInitialized = false;
|
|
2547
|
-
writeErrorCount = 0;
|
|
2548
|
-
writeErrorReported = false;
|
|
2549
|
-
MAX_WRITE_ERRORS_BEFORE_DISABLE = 5;
|
|
2550
|
-
LOG_TEMPLATE = "{{yyyy}}-{{mm}}-{{dd}} {{hh}}:{{MM}}:{{ss}}:{{ms}} {{logLevelName}} [{{name}}] ";
|
|
2551
|
-
defaultLogger = createLogger();
|
|
2552
1767
|
}
|
|
2553
1768
|
});
|
|
2554
1769
|
|
|
@@ -3066,6 +2281,16 @@ var init_conversation_manager = __esm({
|
|
|
3066
2281
|
getBaseMessages() {
|
|
3067
2282
|
return [...this.baseMessages, ...this.initialMessages];
|
|
3068
2283
|
}
|
|
2284
|
+
/**
|
|
2285
|
+
* Replace the base (system + gadget catalog) messages.
|
|
2286
|
+
*
|
|
2287
|
+
* Used when async setup (e.g. MCP server connect-and-list) discovers
|
|
2288
|
+
* additional gadgets after the agent was constructed. Conversation history
|
|
2289
|
+
* is preserved; only the leading system block is swapped.
|
|
2290
|
+
*/
|
|
2291
|
+
replaceBaseMessages(newBase) {
|
|
2292
|
+
this.baseMessages = newBase;
|
|
2293
|
+
}
|
|
3069
2294
|
replaceHistory(newHistory) {
|
|
3070
2295
|
this.historyBuilder = new LLMMessageBuilder();
|
|
3071
2296
|
if (this.startPrefix && this.endPrefix) {
|
|
@@ -4028,632 +3253,52 @@ var init_llm_call_lifecycle = __esm({
|
|
|
4028
3253
|
* to preserve the original Agent behavior: the `afterLLMCall` controller was never
|
|
4029
3254
|
* invoked for interrupted calls in the pre-extraction code. Skipping it here prevents
|
|
4030
3255
|
* side effects (e.g., `append_messages` mutating conversation state) during cleanup
|
|
4031
|
-
* of an already-exited run loop.
|
|
4032
|
-
*/
|
|
4033
|
-
async processAfterLLMCallController(iteration, llmOptions, result, gadgetCallCount) {
|
|
4034
|
-
let finalMessage = result.finalMessage;
|
|
4035
|
-
if (!this.hooks.controllers?.afterLLMCall || result.finishReason === "interrupted") {
|
|
4036
|
-
return finalMessage;
|
|
4037
|
-
}
|
|
4038
|
-
const context = {
|
|
4039
|
-
iteration,
|
|
4040
|
-
maxIterations: this.maxIterations,
|
|
4041
|
-
budget: this.budget,
|
|
4042
|
-
totalCost: this.tree.getTotalCost(),
|
|
4043
|
-
options: llmOptions,
|
|
4044
|
-
finishReason: result.finishReason,
|
|
4045
|
-
usage: result.usage,
|
|
4046
|
-
finalMessage: result.finalMessage,
|
|
4047
|
-
gadgetCallCount,
|
|
4048
|
-
logger: this.logger
|
|
4049
|
-
};
|
|
4050
|
-
const action = await this.hooks.controllers.afterLLMCall(context);
|
|
4051
|
-
validateAfterLLMCallAction(action);
|
|
4052
|
-
if (action.action === "modify_and_continue" || action.action === "append_and_modify") {
|
|
4053
|
-
finalMessage = action.modifiedMessage;
|
|
4054
|
-
}
|
|
4055
|
-
if (action.action === "append_messages" || action.action === "append_and_modify") {
|
|
4056
|
-
for (const msg of action.messages) {
|
|
4057
|
-
if (msg.role === "user") {
|
|
4058
|
-
this.conversation.addUserMessage(msg.content);
|
|
4059
|
-
} else if (msg.role === "assistant") {
|
|
4060
|
-
this.conversation.addAssistantMessage(extractMessageText(msg.content));
|
|
4061
|
-
} else if (msg.role === "system") {
|
|
4062
|
-
this.conversation.addUserMessage(`[System] ${extractMessageText(msg.content)}`);
|
|
4063
|
-
}
|
|
4064
|
-
}
|
|
4065
|
-
}
|
|
4066
|
-
return finalMessage;
|
|
4067
|
-
}
|
|
4068
|
-
};
|
|
4069
|
-
}
|
|
4070
|
-
});
|
|
4071
|
-
|
|
4072
|
-
// src/gadgets/schema-to-json.ts
|
|
4073
|
-
import * as z from "zod";
|
|
4074
|
-
function schemaToJSONSchema(schema, options) {
|
|
4075
|
-
const jsonSchema = z.toJSONSchema(schema, options ?? { target: "draft-7" });
|
|
4076
|
-
const mismatches = detectDescriptionMismatch(schema, jsonSchema);
|
|
4077
|
-
if (mismatches.length > 0) {
|
|
4078
|
-
defaultLogger.warn(
|
|
4079
|
-
`Zod instance mismatch detected: ${mismatches.length} description(s) lost. For best results, use: import { z } from "llmist"`
|
|
4080
|
-
);
|
|
4081
|
-
return mergeDescriptions(schema, jsonSchema);
|
|
4082
|
-
}
|
|
4083
|
-
return jsonSchema;
|
|
4084
|
-
}
|
|
4085
|
-
function detectDescriptionMismatch(schema, jsonSchema) {
|
|
4086
|
-
const mismatches = [];
|
|
4087
|
-
function checkSchema(zodSchema, json, path3) {
|
|
4088
|
-
if (!zodSchema || typeof zodSchema !== "object") return;
|
|
4089
|
-
const def = zodSchema._def;
|
|
4090
|
-
const jsonObj = json;
|
|
4091
|
-
if (def?.description && !jsonObj?.description) {
|
|
4092
|
-
mismatches.push(path3 || "root");
|
|
4093
|
-
}
|
|
4094
|
-
if (def?.typeName === "ZodObject" && def?.shape) {
|
|
4095
|
-
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
4096
|
-
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
4097
|
-
const properties = jsonObj?.properties;
|
|
4098
|
-
const jsonProp = properties?.[key];
|
|
4099
|
-
checkSchema(fieldSchema, jsonProp, path3 ? `${path3}.${key}` : key);
|
|
4100
|
-
}
|
|
4101
|
-
}
|
|
4102
|
-
if (def?.typeName === "ZodArray" && def?.type) {
|
|
4103
|
-
checkSchema(def.type, jsonObj?.items, path3 ? `${path3}[]` : "[]");
|
|
4104
|
-
}
|
|
4105
|
-
if ((def?.typeName === "ZodOptional" || def?.typeName === "ZodNullable") && def?.innerType) {
|
|
4106
|
-
checkSchema(def.innerType, json, path3);
|
|
4107
|
-
}
|
|
4108
|
-
if (def?.typeName === "ZodDefault" && def?.innerType) {
|
|
4109
|
-
checkSchema(def.innerType, json, path3);
|
|
4110
|
-
}
|
|
4111
|
-
}
|
|
4112
|
-
checkSchema(schema, jsonSchema, "");
|
|
4113
|
-
return mismatches;
|
|
4114
|
-
}
|
|
4115
|
-
function mergeDescriptions(schema, jsonSchema) {
|
|
4116
|
-
function merge(zodSchema, json) {
|
|
4117
|
-
if (!json || typeof json !== "object") return json;
|
|
4118
|
-
const def = zodSchema._def;
|
|
4119
|
-
const jsonObj = json;
|
|
4120
|
-
const merged = { ...jsonObj };
|
|
4121
|
-
if (def?.description && !jsonObj.description) {
|
|
4122
|
-
merged.description = def.description;
|
|
4123
|
-
}
|
|
4124
|
-
if (def?.typeName === "ZodObject" && def?.shape && jsonObj.properties) {
|
|
4125
|
-
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
4126
|
-
const properties = jsonObj.properties;
|
|
4127
|
-
merged.properties = { ...properties };
|
|
4128
|
-
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
4129
|
-
if (properties[key]) {
|
|
4130
|
-
merged.properties[key] = merge(fieldSchema, properties[key]);
|
|
4131
|
-
}
|
|
4132
|
-
}
|
|
4133
|
-
}
|
|
4134
|
-
if (def?.typeName === "ZodArray" && def?.type && jsonObj.items) {
|
|
4135
|
-
merged.items = merge(def.type, jsonObj.items);
|
|
4136
|
-
}
|
|
4137
|
-
if ((def?.typeName === "ZodOptional" || def?.typeName === "ZodNullable") && def?.innerType) {
|
|
4138
|
-
return merge(def.innerType, json);
|
|
4139
|
-
}
|
|
4140
|
-
if (def?.typeName === "ZodDefault" && def?.innerType) {
|
|
4141
|
-
return merge(def.innerType, json);
|
|
4142
|
-
}
|
|
4143
|
-
return merged;
|
|
4144
|
-
}
|
|
4145
|
-
return merge(schema, jsonSchema);
|
|
4146
|
-
}
|
|
4147
|
-
var init_schema_to_json = __esm({
|
|
4148
|
-
"src/gadgets/schema-to-json.ts"() {
|
|
4149
|
-
"use strict";
|
|
4150
|
-
init_logger();
|
|
4151
|
-
}
|
|
4152
|
-
});
|
|
4153
|
-
|
|
4154
|
-
// src/gadgets/schema-validator.ts
|
|
4155
|
-
import * as z2 from "zod";
|
|
4156
|
-
function validateGadgetSchema(schema, gadgetName) {
|
|
4157
|
-
let jsonSchema;
|
|
4158
|
-
try {
|
|
4159
|
-
jsonSchema = z2.toJSONSchema(schema, { target: "draft-7" });
|
|
4160
|
-
} catch (error) {
|
|
4161
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4162
|
-
throw new Error(
|
|
4163
|
-
`Gadget "${gadgetName}" has a schema that cannot be serialized to JSON Schema.
|
|
4164
|
-
This usually happens with unsupported patterns like:
|
|
4165
|
-
- z.record() - use z.object({}).passthrough() instead
|
|
4166
|
-
- Complex transforms or custom refinements
|
|
4167
|
-
- Circular references
|
|
4168
|
-
|
|
4169
|
-
Original error: ${errorMessage}
|
|
4170
|
-
|
|
4171
|
-
Only use schema patterns that Zod v4's native toJSONSchema() supports.`
|
|
4172
|
-
);
|
|
4173
|
-
}
|
|
4174
|
-
const issues = findUnknownTypes(jsonSchema);
|
|
4175
|
-
if (issues.length > 0) {
|
|
4176
|
-
const fieldList = issues.join(", ");
|
|
4177
|
-
throw new Error(
|
|
4178
|
-
`Gadget "${gadgetName}" uses z.unknown() which produces incomplete schemas.
|
|
4179
|
-
Problematic fields: ${fieldList}
|
|
4180
|
-
|
|
4181
|
-
z.unknown() doesn't generate type information in JSON Schema, making it unclear
|
|
4182
|
-
to the LLM what data structure to provide.
|
|
4183
|
-
|
|
4184
|
-
Suggestions:
|
|
4185
|
-
- Use z.object({}).passthrough() for flexible objects
|
|
4186
|
-
- Use z.record(z.string()) for key-value objects with string values
|
|
4187
|
-
- Define specific structure if possible
|
|
4188
|
-
|
|
4189
|
-
Example fixes:
|
|
4190
|
-
// \u274C Bad
|
|
4191
|
-
content: z.unknown()
|
|
4192
|
-
|
|
4193
|
-
// \u2705 Good
|
|
4194
|
-
content: z.object({}).passthrough() // for flexible objects
|
|
4195
|
-
content: z.record(z.string()) // for key-value objects
|
|
4196
|
-
content: z.array(z.string()) // for arrays of strings
|
|
4197
|
-
`
|
|
4198
|
-
);
|
|
4199
|
-
}
|
|
4200
|
-
}
|
|
4201
|
-
function findUnknownTypes(schema, path3 = []) {
|
|
4202
|
-
const issues = [];
|
|
4203
|
-
if (!schema || typeof schema !== "object") {
|
|
4204
|
-
return issues;
|
|
4205
|
-
}
|
|
4206
|
-
if (schema.definitions) {
|
|
4207
|
-
for (const defSchema of Object.values(schema.definitions)) {
|
|
4208
|
-
issues.push(...findUnknownTypes(defSchema, []));
|
|
4209
|
-
}
|
|
4210
|
-
}
|
|
4211
|
-
if (schema.properties) {
|
|
4212
|
-
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
4213
|
-
const propPath = [...path3, propName];
|
|
4214
|
-
if (hasNoType(propSchema)) {
|
|
4215
|
-
issues.push(propPath.join(".") || propName);
|
|
4216
|
-
}
|
|
4217
|
-
issues.push(...findUnknownTypes(propSchema, propPath));
|
|
4218
|
-
}
|
|
4219
|
-
}
|
|
4220
|
-
if (schema.items) {
|
|
4221
|
-
const itemPath = [...path3, "[]"];
|
|
4222
|
-
if (hasNoType(schema.items)) {
|
|
4223
|
-
issues.push(itemPath.join("."));
|
|
4224
|
-
}
|
|
4225
|
-
issues.push(...findUnknownTypes(schema.items, itemPath));
|
|
4226
|
-
}
|
|
4227
|
-
if (schema.anyOf) {
|
|
4228
|
-
schema.anyOf.forEach((subSchema, index) => {
|
|
4229
|
-
issues.push(...findUnknownTypes(subSchema, [...path3, `anyOf[${index}]`]));
|
|
4230
|
-
});
|
|
4231
|
-
}
|
|
4232
|
-
if (schema.oneOf) {
|
|
4233
|
-
schema.oneOf.forEach((subSchema, index) => {
|
|
4234
|
-
issues.push(...findUnknownTypes(subSchema, [...path3, `oneOf[${index}]`]));
|
|
4235
|
-
});
|
|
4236
|
-
}
|
|
4237
|
-
if (schema.allOf) {
|
|
4238
|
-
schema.allOf.forEach((subSchema, index) => {
|
|
4239
|
-
issues.push(...findUnknownTypes(subSchema, [...path3, `allOf[${index}]`]));
|
|
4240
|
-
});
|
|
4241
|
-
}
|
|
4242
|
-
return issues;
|
|
4243
|
-
}
|
|
4244
|
-
function hasNoType(prop) {
|
|
4245
|
-
if (!prop || typeof prop !== "object") {
|
|
4246
|
-
return false;
|
|
4247
|
-
}
|
|
4248
|
-
const hasType = prop.type !== void 0;
|
|
4249
|
-
const hasRef = prop.$ref !== void 0;
|
|
4250
|
-
const hasUnion = prop.anyOf !== void 0 || prop.oneOf !== void 0 || prop.allOf !== void 0;
|
|
4251
|
-
if (hasType || hasRef || hasUnion) {
|
|
4252
|
-
return false;
|
|
4253
|
-
}
|
|
4254
|
-
const keys = Object.keys(prop);
|
|
4255
|
-
const metadataKeys = ["description", "title", "default", "examples"];
|
|
4256
|
-
const hasOnlyMetadata = keys.every((key) => metadataKeys.includes(key));
|
|
4257
|
-
return hasOnlyMetadata || keys.length === 0;
|
|
4258
|
-
}
|
|
4259
|
-
var init_schema_validator = __esm({
|
|
4260
|
-
"src/gadgets/schema-validator.ts"() {
|
|
4261
|
-
"use strict";
|
|
4262
|
-
}
|
|
4263
|
-
});
|
|
4264
|
-
|
|
4265
|
-
// src/gadgets/gadget.ts
|
|
4266
|
-
function formatParamsForBlockExample(params, prefix = "", argPrefix = GADGET_ARG_PREFIX) {
|
|
4267
|
-
const lines = [];
|
|
4268
|
-
for (const [key, value] of Object.entries(params)) {
|
|
4269
|
-
const fullPath = prefix ? `${prefix}/${key}` : key;
|
|
4270
|
-
if (Array.isArray(value)) {
|
|
4271
|
-
value.forEach((item, index) => {
|
|
4272
|
-
const itemPath = `${fullPath}/${index}`;
|
|
4273
|
-
if (typeof item === "object" && item !== null) {
|
|
4274
|
-
lines.push(
|
|
4275
|
-
formatParamsForBlockExample(item, itemPath, argPrefix)
|
|
4276
|
-
);
|
|
4277
|
-
} else {
|
|
4278
|
-
lines.push(`${argPrefix}${itemPath}`);
|
|
4279
|
-
lines.push(String(item));
|
|
4280
|
-
}
|
|
4281
|
-
});
|
|
4282
|
-
} else if (typeof value === "object" && value !== null) {
|
|
4283
|
-
lines.push(
|
|
4284
|
-
formatParamsForBlockExample(value, fullPath, argPrefix)
|
|
4285
|
-
);
|
|
4286
|
-
} else {
|
|
4287
|
-
lines.push(`${argPrefix}${fullPath}`);
|
|
4288
|
-
lines.push(String(value));
|
|
4289
|
-
}
|
|
4290
|
-
}
|
|
4291
|
-
return lines.join("\n");
|
|
4292
|
-
}
|
|
4293
|
-
function formatParamLine(key, propObj, isRequired, indent = "") {
|
|
4294
|
-
const type = propObj.type;
|
|
4295
|
-
const description = propObj.description;
|
|
4296
|
-
const enumValues = propObj.enum;
|
|
4297
|
-
let line = `${indent}- ${key}`;
|
|
4298
|
-
if (type === "array") {
|
|
4299
|
-
const items = propObj.items;
|
|
4300
|
-
const itemType = items?.type || "any";
|
|
4301
|
-
line += ` (array of ${itemType})`;
|
|
4302
|
-
} else if (type === "object" && propObj.properties) {
|
|
4303
|
-
line += " (object)";
|
|
4304
|
-
} else {
|
|
4305
|
-
line += ` (${type})`;
|
|
4306
|
-
}
|
|
4307
|
-
if (isRequired && indent !== "") {
|
|
4308
|
-
line += " [required]";
|
|
4309
|
-
}
|
|
4310
|
-
if (description) {
|
|
4311
|
-
line += `: ${description}`;
|
|
4312
|
-
}
|
|
4313
|
-
if (enumValues) {
|
|
4314
|
-
line += ` - one of: ${enumValues.map((v) => `"${v}"`).join(", ")}`;
|
|
4315
|
-
}
|
|
4316
|
-
return line;
|
|
4317
|
-
}
|
|
4318
|
-
function formatSchemaAsPlainText(schema, indent = "", atRoot = true) {
|
|
4319
|
-
const lines = [];
|
|
4320
|
-
const properties = schema.properties || {};
|
|
4321
|
-
const required = schema.required || [];
|
|
4322
|
-
if (atRoot && indent === "") {
|
|
4323
|
-
const requiredProps = [];
|
|
4324
|
-
const optionalProps = [];
|
|
4325
|
-
for (const [key, prop] of Object.entries(properties)) {
|
|
4326
|
-
if (required.includes(key)) {
|
|
4327
|
-
requiredProps.push([key, prop]);
|
|
4328
|
-
} else {
|
|
4329
|
-
optionalProps.push([key, prop]);
|
|
4330
|
-
}
|
|
4331
|
-
}
|
|
4332
|
-
const reqCount = requiredProps.length;
|
|
4333
|
-
const optCount = optionalProps.length;
|
|
4334
|
-
if (reqCount > 0 || optCount > 0) {
|
|
4335
|
-
const parts = [];
|
|
4336
|
-
if (reqCount > 0) parts.push(`${reqCount} required`);
|
|
4337
|
-
if (optCount > 0) parts.push(`${optCount} optional`);
|
|
4338
|
-
lines.push(parts.join(", "));
|
|
4339
|
-
lines.push("");
|
|
4340
|
-
}
|
|
4341
|
-
if (reqCount > 0) {
|
|
4342
|
-
lines.push("REQUIRED Parameters:");
|
|
4343
|
-
for (const [key, prop] of requiredProps) {
|
|
4344
|
-
lines.push(formatParamLine(key, prop, true, ""));
|
|
4345
|
-
const propObj = prop;
|
|
4346
|
-
if (propObj.type === "object" && propObj.properties) {
|
|
4347
|
-
lines.push(formatSchemaAsPlainText(propObj, " ", false));
|
|
4348
|
-
}
|
|
4349
|
-
}
|
|
4350
|
-
}
|
|
4351
|
-
if (optCount > 0) {
|
|
4352
|
-
if (reqCount > 0) lines.push("");
|
|
4353
|
-
lines.push("OPTIONAL Parameters:");
|
|
4354
|
-
for (const [key, prop] of optionalProps) {
|
|
4355
|
-
lines.push(formatParamLine(key, prop, false, ""));
|
|
4356
|
-
const propObj = prop;
|
|
4357
|
-
if (propObj.type === "object" && propObj.properties) {
|
|
4358
|
-
lines.push(formatSchemaAsPlainText(propObj, " ", false));
|
|
4359
|
-
}
|
|
4360
|
-
}
|
|
4361
|
-
}
|
|
4362
|
-
return lines.join("\n");
|
|
4363
|
-
}
|
|
4364
|
-
for (const [key, prop] of Object.entries(properties)) {
|
|
4365
|
-
const isRequired = required.includes(key);
|
|
4366
|
-
lines.push(formatParamLine(key, prop, isRequired, indent));
|
|
4367
|
-
const propObj = prop;
|
|
4368
|
-
if (propObj.type === "object" && propObj.properties) {
|
|
4369
|
-
lines.push(formatSchemaAsPlainText(propObj, indent + " ", false));
|
|
4370
|
-
}
|
|
4371
|
-
}
|
|
4372
|
-
return lines.join("\n");
|
|
4373
|
-
}
|
|
4374
|
-
var AbstractGadget;
|
|
4375
|
-
var init_gadget = __esm({
|
|
4376
|
-
"src/gadgets/gadget.ts"() {
|
|
4377
|
-
"use strict";
|
|
4378
|
-
init_constants();
|
|
4379
|
-
init_exceptions();
|
|
4380
|
-
init_schema_to_json();
|
|
4381
|
-
init_schema_validator();
|
|
4382
|
-
AbstractGadget = class {
|
|
4383
|
-
/**
|
|
4384
|
-
* The name of the gadget. Used for identification when LLM calls it.
|
|
4385
|
-
* If not provided, defaults to the class name.
|
|
4386
|
-
*/
|
|
4387
|
-
name;
|
|
4388
|
-
/**
|
|
4389
|
-
* Optional Zod schema describing the expected input payload. When provided,
|
|
4390
|
-
* it will be validated before execution and transformed into a JSON Schema
|
|
4391
|
-
* representation that is surfaced to the LLM as part of the instructions.
|
|
4392
|
-
*/
|
|
4393
|
-
parameterSchema;
|
|
4394
|
-
/**
|
|
4395
|
-
* Optional timeout in milliseconds for gadget execution.
|
|
4396
|
-
* If execution exceeds this timeout, a TimeoutException will be thrown.
|
|
4397
|
-
* If not set, the global defaultGadgetTimeoutMs from runtime options will be used.
|
|
4398
|
-
* Set to 0 or undefined to disable timeout for this gadget.
|
|
4399
|
-
*/
|
|
4400
|
-
timeoutMs;
|
|
4401
|
-
/**
|
|
4402
|
-
* Optional usage examples to help LLMs understand proper invocation.
|
|
4403
|
-
* Examples are rendered in getInstruction() alongside the schema.
|
|
4404
|
-
*
|
|
4405
|
-
* Note: Uses broader `unknown` type to allow typed examples from subclasses
|
|
4406
|
-
* while maintaining runtime compatibility.
|
|
4407
|
-
*/
|
|
4408
|
-
examples;
|
|
4409
|
-
/**
|
|
4410
|
-
* Maximum number of concurrent executions allowed for this gadget.
|
|
4411
|
-
* Use this to prevent race conditions in gadgets that modify shared state.
|
|
4412
|
-
*
|
|
4413
|
-
* - `1` = Sequential execution (only one instance runs at a time)
|
|
4414
|
-
* - `0` or `undefined` = Unlimited concurrency (default)
|
|
4415
|
-
* - `N > 1` = At most N concurrent executions
|
|
4416
|
-
*
|
|
4417
|
-
* This property sets a safety floor: external configuration (SubagentConfig)
|
|
4418
|
-
* can only make concurrency MORE restrictive, never less. For example, if
|
|
4419
|
-
* a gadget declares `maxConcurrent: 1`, external config cannot override it
|
|
4420
|
-
* to allow parallel execution.
|
|
4421
|
-
*
|
|
4422
|
-
* @example
|
|
4423
|
-
* ```typescript
|
|
4424
|
-
* // File writer that must run sequentially to avoid race conditions
|
|
4425
|
-
* class WriteFile extends Gadget({
|
|
4426
|
-
* description: 'Writes content to a file',
|
|
4427
|
-
* schema: z.object({ path: z.string(), content: z.string() }),
|
|
4428
|
-
* maxConcurrent: 1, // Sequential - prevents race conditions
|
|
4429
|
-
* }) {
|
|
4430
|
-
* execute(params: this['params']) { ... }
|
|
4431
|
-
* }
|
|
4432
|
-
* ```
|
|
4433
|
-
*/
|
|
4434
|
-
maxConcurrent;
|
|
4435
|
-
/**
|
|
4436
|
-
* If true, this gadget must execute alone — no other gadgets in the same
|
|
4437
|
-
* LLM response can run in parallel. When an exclusive gadget arrives and
|
|
4438
|
-
* other gadgets are already in-flight, it is deferred until they complete.
|
|
4439
|
-
*
|
|
4440
|
-
* Use for gadgets that terminate the agent loop (e.g., Finish), where
|
|
4441
|
-
* sibling tool results must be visible to the LLM before the loop ends.
|
|
4442
|
-
*
|
|
4443
|
-
* This is a safety floor: external config cannot weaken it.
|
|
4444
|
-
*/
|
|
4445
|
-
exclusive;
|
|
4446
|
-
/**
|
|
4447
|
-
* Throws an AbortException if the execution has been aborted.
|
|
4448
|
-
*
|
|
4449
|
-
* Call this at key checkpoints in long-running gadgets to allow early exit
|
|
4450
|
-
* when the gadget has been cancelled (e.g., due to timeout). This enables
|
|
4451
|
-
* resource cleanup and prevents unnecessary work after cancellation.
|
|
4452
|
-
*
|
|
4453
|
-
* @param ctx - The execution context containing the abort signal
|
|
4454
|
-
* @throws AbortException if ctx.signal.aborted is true
|
|
4455
|
-
*
|
|
4456
|
-
* @example
|
|
4457
|
-
* ```typescript
|
|
4458
|
-
* class DataProcessor extends Gadget({
|
|
4459
|
-
* description: 'Processes data in multiple steps',
|
|
4460
|
-
* schema: z.object({ items: z.array(z.string()) }),
|
|
4461
|
-
* }) {
|
|
4462
|
-
* async execute(params: this['params'], ctx?: ExecutionContext): Promise<string> {
|
|
4463
|
-
* const results: string[] = [];
|
|
4464
|
-
*
|
|
4465
|
-
* for (const item of params.items) {
|
|
4466
|
-
* // Check before each expensive operation
|
|
4467
|
-
* this.throwIfAborted(ctx);
|
|
4468
|
-
*
|
|
4469
|
-
* results.push(await this.processItem(item));
|
|
4470
|
-
* }
|
|
4471
|
-
*
|
|
4472
|
-
* return results.join(', ');
|
|
4473
|
-
* }
|
|
4474
|
-
* }
|
|
4475
|
-
* ```
|
|
4476
|
-
*/
|
|
4477
|
-
throwIfAborted(ctx) {
|
|
4478
|
-
if (ctx?.signal?.aborted) {
|
|
4479
|
-
throw new AbortException();
|
|
4480
|
-
}
|
|
4481
|
-
}
|
|
4482
|
-
/**
|
|
4483
|
-
* Register a cleanup function to run when execution is aborted (timeout or cancellation).
|
|
4484
|
-
* The cleanup function is called immediately if the signal is already aborted.
|
|
4485
|
-
* Errors thrown by the cleanup function are silently ignored.
|
|
4486
|
-
*
|
|
4487
|
-
* Use this to clean up resources like browser instances, database connections,
|
|
4488
|
-
* or child processes when the gadget is cancelled due to timeout.
|
|
4489
|
-
*
|
|
4490
|
-
* @param ctx - The execution context containing the abort signal
|
|
4491
|
-
* @param cleanup - Function to run on abort (can be sync or async)
|
|
4492
|
-
*
|
|
4493
|
-
* @example
|
|
4494
|
-
* ```typescript
|
|
4495
|
-
* class BrowserGadget extends Gadget({
|
|
4496
|
-
* description: 'Fetches web page content',
|
|
4497
|
-
* schema: z.object({ url: z.string() }),
|
|
4498
|
-
* }) {
|
|
4499
|
-
* async execute(params: this['params'], ctx?: ExecutionContext): Promise<string> {
|
|
4500
|
-
* const browser = await chromium.launch();
|
|
4501
|
-
* this.onAbort(ctx, () => browser.close());
|
|
4502
|
-
*
|
|
4503
|
-
* const page = await browser.newPage();
|
|
4504
|
-
* this.onAbort(ctx, () => page.close());
|
|
4505
|
-
*
|
|
4506
|
-
* await page.goto(params.url);
|
|
4507
|
-
* const content = await page.content();
|
|
4508
|
-
*
|
|
4509
|
-
* await browser.close();
|
|
4510
|
-
* return content;
|
|
4511
|
-
* }
|
|
4512
|
-
* }
|
|
4513
|
-
* ```
|
|
4514
|
-
*/
|
|
4515
|
-
onAbort(ctx, cleanup) {
|
|
4516
|
-
if (!ctx?.signal) return;
|
|
4517
|
-
const safeCleanup = () => {
|
|
4518
|
-
try {
|
|
4519
|
-
const result = cleanup();
|
|
4520
|
-
if (result && typeof result === "object" && "catch" in result) {
|
|
4521
|
-
result.catch(() => {
|
|
4522
|
-
});
|
|
4523
|
-
}
|
|
4524
|
-
} catch {
|
|
4525
|
-
}
|
|
4526
|
-
};
|
|
4527
|
-
if (ctx.signal.aborted) {
|
|
4528
|
-
safeCleanup();
|
|
4529
|
-
return;
|
|
4530
|
-
}
|
|
4531
|
-
ctx.signal.addEventListener("abort", safeCleanup, { once: true });
|
|
4532
|
-
}
|
|
4533
|
-
/**
|
|
4534
|
-
* Create an AbortController linked to the execution context's signal.
|
|
4535
|
-
* When the parent signal aborts, the returned controller also aborts with the same reason.
|
|
4536
|
-
*
|
|
4537
|
-
* Useful for passing abort signals to child operations like fetch() while still
|
|
4538
|
-
* being able to abort them independently if needed.
|
|
4539
|
-
*
|
|
4540
|
-
* @param ctx - The execution context containing the parent abort signal
|
|
4541
|
-
* @returns A new AbortController linked to the parent signal
|
|
4542
|
-
*
|
|
4543
|
-
* @example
|
|
4544
|
-
* ```typescript
|
|
4545
|
-
* class FetchGadget extends Gadget({
|
|
4546
|
-
* description: 'Fetches data from URL',
|
|
4547
|
-
* schema: z.object({ url: z.string() }),
|
|
4548
|
-
* }) {
|
|
4549
|
-
* async execute(params: this['params'], ctx?: ExecutionContext): Promise<string> {
|
|
4550
|
-
* const controller = this.createLinkedAbortController(ctx);
|
|
4551
|
-
*
|
|
4552
|
-
* // fetch() will automatically abort when parent times out
|
|
4553
|
-
* const response = await fetch(params.url, { signal: controller.signal });
|
|
4554
|
-
* return response.text();
|
|
4555
|
-
* }
|
|
4556
|
-
* }
|
|
4557
|
-
* ```
|
|
4558
|
-
*/
|
|
4559
|
-
createLinkedAbortController(ctx) {
|
|
4560
|
-
const controller = new AbortController();
|
|
4561
|
-
if (ctx?.signal) {
|
|
4562
|
-
if (ctx.signal.aborted) {
|
|
4563
|
-
controller.abort(ctx.signal.reason);
|
|
4564
|
-
} else {
|
|
4565
|
-
ctx.signal.addEventListener(
|
|
4566
|
-
"abort",
|
|
4567
|
-
() => {
|
|
4568
|
-
controller.abort(ctx.signal.reason);
|
|
4569
|
-
},
|
|
4570
|
-
{ once: true }
|
|
4571
|
-
);
|
|
4572
|
-
}
|
|
4573
|
-
}
|
|
4574
|
-
return controller;
|
|
4575
|
-
}
|
|
4576
|
-
/**
|
|
4577
|
-
* Generate instruction text for the LLM.
|
|
4578
|
-
* Combines name, description, and parameter schema into a formatted instruction.
|
|
4579
|
-
*
|
|
4580
|
-
* @param optionsOrArgPrefix - Optional custom prefixes for examples, or just argPrefix string for backwards compatibility
|
|
4581
|
-
* @returns Formatted instruction string
|
|
3256
|
+
* of an already-exited run loop.
|
|
4582
3257
|
*/
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
formatParamsForBlockExample(
|
|
4614
|
-
example.params,
|
|
4615
|
-
"",
|
|
4616
|
-
effectiveArgPrefix
|
|
4617
|
-
)
|
|
4618
|
-
);
|
|
4619
|
-
parts.push(effectiveEndPrefix);
|
|
4620
|
-
if (example.output !== void 0) {
|
|
4621
|
-
parts.push("");
|
|
4622
|
-
parts.push("Expected Output:");
|
|
4623
|
-
parts.push(example.output);
|
|
3258
|
+
async processAfterLLMCallController(iteration, llmOptions, result, gadgetCallCount) {
|
|
3259
|
+
let finalMessage = result.finalMessage;
|
|
3260
|
+
if (!this.hooks.controllers?.afterLLMCall || result.finishReason === "interrupted") {
|
|
3261
|
+
return finalMessage;
|
|
3262
|
+
}
|
|
3263
|
+
const context = {
|
|
3264
|
+
iteration,
|
|
3265
|
+
maxIterations: this.maxIterations,
|
|
3266
|
+
budget: this.budget,
|
|
3267
|
+
totalCost: this.tree.getTotalCost(),
|
|
3268
|
+
options: llmOptions,
|
|
3269
|
+
finishReason: result.finishReason,
|
|
3270
|
+
usage: result.usage,
|
|
3271
|
+
finalMessage: result.finalMessage,
|
|
3272
|
+
gadgetCallCount,
|
|
3273
|
+
logger: this.logger
|
|
3274
|
+
};
|
|
3275
|
+
const action = await this.hooks.controllers.afterLLMCall(context);
|
|
3276
|
+
validateAfterLLMCallAction(action);
|
|
3277
|
+
if (action.action === "modify_and_continue" || action.action === "append_and_modify") {
|
|
3278
|
+
finalMessage = action.modifiedMessage;
|
|
3279
|
+
}
|
|
3280
|
+
if (action.action === "append_messages" || action.action === "append_and_modify") {
|
|
3281
|
+
for (const msg of action.messages) {
|
|
3282
|
+
if (msg.role === "user") {
|
|
3283
|
+
this.conversation.addUserMessage(msg.content);
|
|
3284
|
+
} else if (msg.role === "assistant") {
|
|
3285
|
+
this.conversation.addAssistantMessage(extractMessageText(msg.content));
|
|
3286
|
+
} else if (msg.role === "system") {
|
|
3287
|
+
this.conversation.addUserMessage(`[System] ${extractMessageText(msg.content)}`);
|
|
4624
3288
|
}
|
|
4625
|
-
}
|
|
3289
|
+
}
|
|
4626
3290
|
}
|
|
4627
|
-
return
|
|
3291
|
+
return finalMessage;
|
|
4628
3292
|
}
|
|
4629
3293
|
};
|
|
4630
3294
|
}
|
|
4631
3295
|
});
|
|
4632
3296
|
|
|
4633
|
-
// src/gadgets/create-gadget.ts
|
|
4634
|
-
function createGadget(config) {
|
|
4635
|
-
class DynamicGadget extends AbstractGadget {
|
|
4636
|
-
name = config.name;
|
|
4637
|
-
description = config.description;
|
|
4638
|
-
parameterSchema = config.schema;
|
|
4639
|
-
timeoutMs = config.timeoutMs;
|
|
4640
|
-
examples = config.examples;
|
|
4641
|
-
maxConcurrent = config.maxConcurrent;
|
|
4642
|
-
execute(params, ctx) {
|
|
4643
|
-
return config.execute(params, ctx);
|
|
4644
|
-
}
|
|
4645
|
-
}
|
|
4646
|
-
return new DynamicGadget();
|
|
4647
|
-
}
|
|
4648
|
-
var init_create_gadget = __esm({
|
|
4649
|
-
"src/gadgets/create-gadget.ts"() {
|
|
4650
|
-
"use strict";
|
|
4651
|
-
init_gadget();
|
|
4652
|
-
}
|
|
4653
|
-
});
|
|
4654
|
-
|
|
4655
3297
|
// src/gadgets/output-viewer.ts
|
|
4656
|
-
import { z
|
|
3298
|
+
import { z } from "zod";
|
|
3299
|
+
function pluralize(count, singular, plural = `${singular}s`) {
|
|
3300
|
+
return count === 1 ? singular : plural;
|
|
3301
|
+
}
|
|
4657
3302
|
function applyPattern(lines, pattern) {
|
|
4658
3303
|
const regex = new RegExp(pattern.regex);
|
|
4659
3304
|
if (!pattern.include) {
|
|
@@ -4678,80 +3323,169 @@ function applyPatterns(lines, patterns) {
|
|
|
4678
3323
|
}
|
|
4679
3324
|
return result;
|
|
4680
3325
|
}
|
|
4681
|
-
function
|
|
3326
|
+
function parseLimitWindow(limit) {
|
|
4682
3327
|
const trimmed = limit.trim();
|
|
4683
3328
|
if (trimmed.endsWith("-") && !trimmed.startsWith("-")) {
|
|
4684
3329
|
const n = parseInt(trimmed.slice(0, -1), 10);
|
|
4685
|
-
if (!isNaN(n) && n > 0) {
|
|
4686
|
-
return
|
|
3330
|
+
if (!Number.isNaN(n) && n > 0) {
|
|
3331
|
+
return { kind: "first", count: n };
|
|
4687
3332
|
}
|
|
4688
3333
|
}
|
|
4689
3334
|
if (trimmed.startsWith("-") && !trimmed.includes("-", 1)) {
|
|
4690
3335
|
const n = parseInt(trimmed, 10);
|
|
4691
|
-
if (!isNaN(n) && n < 0) {
|
|
4692
|
-
return
|
|
3336
|
+
if (!Number.isNaN(n) && n < 0) {
|
|
3337
|
+
return { kind: "last", count: Math.abs(n) };
|
|
4693
3338
|
}
|
|
4694
3339
|
}
|
|
4695
3340
|
const rangeMatch = trimmed.match(/^(\d+)-(\d+)$/);
|
|
4696
3341
|
if (rangeMatch) {
|
|
4697
3342
|
const start = parseInt(rangeMatch[1], 10);
|
|
4698
3343
|
const end = parseInt(rangeMatch[2], 10);
|
|
4699
|
-
if (!isNaN(start) && !isNaN(end) && start > 0 && end >= start) {
|
|
4700
|
-
return
|
|
3344
|
+
if (!Number.isNaN(start) && !Number.isNaN(end) && start > 0 && end >= start) {
|
|
3345
|
+
return { kind: "range", start, end };
|
|
3346
|
+
}
|
|
3347
|
+
}
|
|
3348
|
+
return null;
|
|
3349
|
+
}
|
|
3350
|
+
function applyLineLimit(lines, limit) {
|
|
3351
|
+
const window = parseLimitWindow(limit);
|
|
3352
|
+
if (!window) return lines;
|
|
3353
|
+
switch (window.kind) {
|
|
3354
|
+
case "first":
|
|
3355
|
+
return lines.slice(0, window.count);
|
|
3356
|
+
case "last":
|
|
3357
|
+
return lines.slice(-window.count);
|
|
3358
|
+
case "range":
|
|
3359
|
+
return lines.slice(window.start - 1, window.end);
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
function applyCharacterLimit(content, limit, maxOutputChars) {
|
|
3363
|
+
const total = content.length;
|
|
3364
|
+
if (total === 0) {
|
|
3365
|
+
return { text: "", start: 0, end: 0, total: 0, truncatedBySize: false, hasMoreAfter: false };
|
|
3366
|
+
}
|
|
3367
|
+
let startIndex = 0;
|
|
3368
|
+
let endExclusive = total;
|
|
3369
|
+
const window = limit ? parseLimitWindow(limit) : null;
|
|
3370
|
+
if (window) {
|
|
3371
|
+
switch (window.kind) {
|
|
3372
|
+
case "first":
|
|
3373
|
+
endExclusive = Math.min(window.count, total);
|
|
3374
|
+
break;
|
|
3375
|
+
case "last":
|
|
3376
|
+
startIndex = Math.max(0, total - window.count);
|
|
3377
|
+
break;
|
|
3378
|
+
case "range":
|
|
3379
|
+
startIndex = Math.min(window.start - 1, total);
|
|
3380
|
+
endExclusive = Math.min(window.end, total);
|
|
3381
|
+
break;
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
let text3 = content.slice(startIndex, endExclusive);
|
|
3385
|
+
let truncatedBySize = false;
|
|
3386
|
+
if (text3.length > maxOutputChars) {
|
|
3387
|
+
text3 = window?.kind === "last" ? text3.slice(-maxOutputChars) : text3.slice(0, maxOutputChars);
|
|
3388
|
+
if (window?.kind === "last") {
|
|
3389
|
+
startIndex = endExclusive - text3.length;
|
|
4701
3390
|
}
|
|
3391
|
+
truncatedBySize = true;
|
|
4702
3392
|
}
|
|
4703
|
-
return
|
|
3393
|
+
return {
|
|
3394
|
+
text: text3,
|
|
3395
|
+
start: text3.length === 0 ? 0 : startIndex + 1,
|
|
3396
|
+
end: text3.length === 0 ? 0 : startIndex + text3.length,
|
|
3397
|
+
total,
|
|
3398
|
+
truncatedBySize,
|
|
3399
|
+
hasMoreAfter: startIndex + text3.length < total
|
|
3400
|
+
};
|
|
3401
|
+
}
|
|
3402
|
+
function buildCharacterRangeHint(start, total) {
|
|
3403
|
+
if (total <= 0 || start > total) return null;
|
|
3404
|
+
const end = Math.min(total, start + CHARACTER_HINT_WINDOW - 1);
|
|
3405
|
+
return `${start}-${end}`;
|
|
3406
|
+
}
|
|
3407
|
+
function buildCharacterModeSuggestion(stored, opts = {}) {
|
|
3408
|
+
const hint = buildCharacterRangeHint(opts.start ?? 1, stored.charCount);
|
|
3409
|
+
const action = opts.removePatterns ? "Remove patterns and then try" : "Try";
|
|
3410
|
+
const lineLabel = pluralize(stored.lineCount, "line");
|
|
3411
|
+
return `This output is dense (${stored.lineCount.toLocaleString()} ${lineLabel}; longest line ${stored.maxLineLength.toLocaleString()} chars). ${action} mode: "character"` + (hint ? `, limit: "${hint}"` : "") + ".";
|
|
3412
|
+
}
|
|
3413
|
+
function shouldSuggestCharacterMode(stored, maxOutputChars = DEFAULT_MAX_OUTPUT_CHARS) {
|
|
3414
|
+
return stored.lineCount <= 3 && (stored.maxLineLength > maxOutputChars || stored.maxLineLength >= DENSE_LINE_THRESHOLD);
|
|
4704
3415
|
}
|
|
4705
3416
|
function createGadgetOutputViewer(store, maxOutputChars = DEFAULT_MAX_OUTPUT_CHARS) {
|
|
4706
3417
|
return createGadget({
|
|
4707
3418
|
name: "GadgetOutputViewer",
|
|
4708
|
-
description:
|
|
4709
|
-
schema:
|
|
4710
|
-
id:
|
|
4711
|
-
|
|
4712
|
-
|
|
3419
|
+
description: 'View stored output from gadgets that returned too much data. Use mode "line" for grep-like filtering and mode "character" for raw chunked browsing when the output is dense or effectively single-line. Patterns work only in line mode.',
|
|
3420
|
+
schema: z.object({
|
|
3421
|
+
id: z.string().describe("ID of the stored output (from the truncation message)"),
|
|
3422
|
+
mode: z.enum(["line", "character"]).default("line").describe(
|
|
3423
|
+
'Browse by "line" (supports patterns) or by "character" (raw windows for dense output).'
|
|
4713
3424
|
),
|
|
4714
|
-
|
|
4715
|
-
|
|
3425
|
+
patterns: z.array(patternSchema).optional().describe(
|
|
3426
|
+
'Line-mode filter patterns applied in order (like piping through grep). Not supported in mode "character".'
|
|
3427
|
+
),
|
|
3428
|
+
limit: z.string().optional().describe(
|
|
3429
|
+
`Pagination window. In mode "line" it is a line range; in mode "character" it is a character range. Formats: "100-" (first 100), "-25" (last 25), "50-100" (inclusive range).`
|
|
4716
3430
|
)
|
|
4717
3431
|
}),
|
|
4718
3432
|
examples: [
|
|
4719
3433
|
{
|
|
4720
3434
|
comment: "View first 50 lines of stored output",
|
|
4721
|
-
params: { id: "Search_abc12345", limit: "50-" }
|
|
3435
|
+
params: { id: "Search_abc12345", mode: "line", limit: "50-" }
|
|
4722
3436
|
},
|
|
4723
3437
|
{
|
|
4724
3438
|
comment: "Filter for error lines with context",
|
|
4725
3439
|
params: {
|
|
4726
3440
|
id: "Search_abc12345",
|
|
3441
|
+
mode: "line",
|
|
4727
3442
|
patterns: [{ regex: "error|Error|ERROR", include: true, before: 2, after: 5 }]
|
|
4728
3443
|
}
|
|
4729
3444
|
},
|
|
4730
3445
|
{
|
|
4731
|
-
comment: "Exclude blank lines, then show first 100",
|
|
3446
|
+
comment: "Exclude blank lines, then show first 100 lines",
|
|
4732
3447
|
params: {
|
|
4733
3448
|
id: "Search_abc12345",
|
|
3449
|
+
mode: "line",
|
|
4734
3450
|
patterns: [{ regex: "^\\s*$", include: false, before: 0, after: 0 }],
|
|
4735
3451
|
limit: "100-"
|
|
4736
3452
|
}
|
|
4737
3453
|
},
|
|
4738
3454
|
{
|
|
4739
|
-
comment: "
|
|
3455
|
+
comment: "Browse the raw output by character window when line mode is too dense",
|
|
4740
3456
|
params: {
|
|
4741
3457
|
id: "Search_abc12345",
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
{ regex: "test|spec", include: false, before: 0, after: 0 }
|
|
4745
|
-
],
|
|
4746
|
-
limit: "50-"
|
|
3458
|
+
mode: "character",
|
|
3459
|
+
limit: "1-2000"
|
|
4747
3460
|
}
|
|
4748
3461
|
}
|
|
4749
3462
|
],
|
|
4750
|
-
execute: ({ id, patterns, limit }) => {
|
|
3463
|
+
execute: ({ id, mode, patterns, limit }) => {
|
|
4751
3464
|
const stored = store.get(id);
|
|
4752
3465
|
if (!stored) {
|
|
4753
3466
|
return `Error: No stored output with id "${id}". Available IDs: ${store.getIds().join(", ") || "(none)"}`;
|
|
4754
3467
|
}
|
|
3468
|
+
const suggestCharacterMode = shouldSuggestCharacterMode(stored, maxOutputChars);
|
|
3469
|
+
if (mode === "character") {
|
|
3470
|
+
if (patterns && patterns.length > 0) {
|
|
3471
|
+
return 'Error: patterns are only supported in mode "line". Remove patterns or switch back to mode: "line".';
|
|
3472
|
+
}
|
|
3473
|
+
const window = applyCharacterLimit(stored.content, limit, maxOutputChars);
|
|
3474
|
+
if (window.total === 0) {
|
|
3475
|
+
return "[Mode: character | Output is empty]";
|
|
3476
|
+
}
|
|
3477
|
+
const header2 = [
|
|
3478
|
+
`[Mode: character | Showing chars ${window.start.toLocaleString()}-${window.end.toLocaleString()} of ${window.total.toLocaleString()}${window.truncatedBySize ? " (truncated due to viewer size limit)" : ""}]`
|
|
3479
|
+
];
|
|
3480
|
+
if (window.hasMoreAfter) {
|
|
3481
|
+
const nextRange = buildCharacterRangeHint(window.end + 1, window.total);
|
|
3482
|
+
if (nextRange) {
|
|
3483
|
+
header2.push(`[Next chunk: mode: "character", limit: "${nextRange}"]`);
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
return `${header2.join("\n")}
|
|
3487
|
+
${window.text}`;
|
|
3488
|
+
}
|
|
4755
3489
|
let lines = stored.content.split("\n");
|
|
4756
3490
|
if (patterns && patterns.length > 0) {
|
|
4757
3491
|
lines = applyPatterns(
|
|
@@ -4767,54 +3501,76 @@ function createGadgetOutputViewer(store, maxOutputChars = DEFAULT_MAX_OUTPUT_CHA
|
|
|
4767
3501
|
if (limit) {
|
|
4768
3502
|
lines = applyLineLimit(lines, limit);
|
|
4769
3503
|
}
|
|
4770
|
-
let output = lines.join("\n");
|
|
4771
3504
|
const totalLines = stored.lineCount;
|
|
3505
|
+
const totalLineLabel = pluralize(totalLines, "line");
|
|
4772
3506
|
const returnedLines = lines.length;
|
|
4773
3507
|
if (returnedLines === 0) {
|
|
4774
|
-
|
|
3508
|
+
const base = `No lines matched the filters. Original output had ${totalLines.toLocaleString()} lines.`;
|
|
3509
|
+
if (!suggestCharacterMode) return base;
|
|
3510
|
+
return `${base} ${buildCharacterModeSuggestion(stored, {
|
|
3511
|
+
removePatterns: Boolean(patterns && patterns.length > 0)
|
|
3512
|
+
})}`;
|
|
4775
3513
|
}
|
|
3514
|
+
let output = lines.join("\n");
|
|
4776
3515
|
let truncatedBySize = false;
|
|
4777
3516
|
let linesIncluded = returnedLines;
|
|
3517
|
+
let clippedFirstLine = false;
|
|
4778
3518
|
if (output.length > maxOutputChars) {
|
|
4779
3519
|
truncatedBySize = true;
|
|
4780
3520
|
let truncatedOutput = "";
|
|
4781
3521
|
linesIncluded = 0;
|
|
4782
3522
|
for (const line of lines) {
|
|
4783
|
-
|
|
4784
|
-
|
|
3523
|
+
const addition = linesIncluded === 0 ? line : `
|
|
3524
|
+
${line}`;
|
|
3525
|
+
if (truncatedOutput.length + addition.length > maxOutputChars) break;
|
|
3526
|
+
truncatedOutput += addition;
|
|
4785
3527
|
linesIncluded++;
|
|
4786
3528
|
}
|
|
3529
|
+
if (linesIncluded === 0) {
|
|
3530
|
+
clippedFirstLine = true;
|
|
3531
|
+
linesIncluded = 1;
|
|
3532
|
+
truncatedOutput = lines[0].slice(0, maxOutputChars);
|
|
3533
|
+
}
|
|
4787
3534
|
output = truncatedOutput;
|
|
4788
3535
|
}
|
|
4789
3536
|
let header;
|
|
4790
|
-
if (
|
|
3537
|
+
if (clippedFirstLine) {
|
|
3538
|
+
header = `[Mode: line | Showing 1 partial line of ${totalLines.toLocaleString()} ${totalLineLabel} (the selected line exceeds the viewer size limit)]
|
|
3539
|
+
`;
|
|
3540
|
+
} else if (truncatedBySize) {
|
|
4791
3541
|
const remainingLines = returnedLines - linesIncluded;
|
|
4792
|
-
header = `[Showing ${linesIncluded} of ${totalLines}
|
|
4793
|
-
[... ${remainingLines.toLocaleString()} more
|
|
3542
|
+
header = `[Mode: line | Showing ${linesIncluded.toLocaleString()} of ${totalLines.toLocaleString()} ${totalLineLabel} (truncated due to size limit)]
|
|
3543
|
+
[... ${remainingLines.toLocaleString()} more ${pluralize(remainingLines, "line")}. Use limit parameter to paginate, e.g., limit: "${linesIncluded + 1}-${linesIncluded + 200}"]
|
|
4794
3544
|
`;
|
|
4795
3545
|
} else if (returnedLines < totalLines) {
|
|
4796
|
-
header = `[Showing ${returnedLines} of ${totalLines}
|
|
3546
|
+
header = `[Mode: line | Showing ${returnedLines.toLocaleString()} of ${totalLines.toLocaleString()} ${totalLineLabel}]
|
|
4797
3547
|
`;
|
|
4798
3548
|
} else {
|
|
4799
|
-
header = `[Showing all ${totalLines}
|
|
3549
|
+
header = `[Mode: line | Showing all ${totalLines.toLocaleString()} ${totalLineLabel}]
|
|
4800
3550
|
`;
|
|
4801
3551
|
}
|
|
4802
|
-
|
|
3552
|
+
const footer = suggestCharacterMode || clippedFirstLine ? `
|
|
3553
|
+
[Tip: ${buildCharacterModeSuggestion(stored, {
|
|
3554
|
+
removePatterns: Boolean(patterns && patterns.length > 0)
|
|
3555
|
+
})}]` : "";
|
|
3556
|
+
return header + output + footer;
|
|
4803
3557
|
}
|
|
4804
3558
|
});
|
|
4805
3559
|
}
|
|
4806
|
-
var
|
|
3560
|
+
var DEFAULT_MAX_OUTPUT_CHARS, CHARACTER_HINT_WINDOW, DENSE_LINE_THRESHOLD, patternSchema;
|
|
4807
3561
|
var init_output_viewer = __esm({
|
|
4808
3562
|
"src/gadgets/output-viewer.ts"() {
|
|
4809
3563
|
"use strict";
|
|
4810
3564
|
init_create_gadget();
|
|
4811
|
-
patternSchema = z3.object({
|
|
4812
|
-
regex: z3.string().describe("Regular expression to match"),
|
|
4813
|
-
include: z3.boolean().default(true).describe("true = keep matching lines, false = exclude matching lines"),
|
|
4814
|
-
before: z3.number().int().min(0).default(0).describe("Context lines before each match (like grep -B)"),
|
|
4815
|
-
after: z3.number().int().min(0).default(0).describe("Context lines after each match (like grep -A)")
|
|
4816
|
-
});
|
|
4817
3565
|
DEFAULT_MAX_OUTPUT_CHARS = 76800;
|
|
3566
|
+
CHARACTER_HINT_WINDOW = 2e3;
|
|
3567
|
+
DENSE_LINE_THRESHOLD = 4e3;
|
|
3568
|
+
patternSchema = z.object({
|
|
3569
|
+
regex: z.string().describe("Regular expression to match"),
|
|
3570
|
+
include: z.boolean().default(true).describe("true = keep matching lines, false = exclude matching lines"),
|
|
3571
|
+
before: z.number().int().min(0).default(0).describe("Context lines before each match (like grep -B)"),
|
|
3572
|
+
after: z.number().int().min(0).default(0).describe("Context lines after each match (like grep -A)")
|
|
3573
|
+
});
|
|
4818
3574
|
}
|
|
4819
3575
|
});
|
|
4820
3576
|
|
|
@@ -4836,12 +3592,15 @@ var init_gadget_output_store = __esm({
|
|
|
4836
3592
|
store(gadgetName, content) {
|
|
4837
3593
|
const id = this.generateId(gadgetName);
|
|
4838
3594
|
const encoder = new TextEncoder();
|
|
3595
|
+
const lines = content.split("\n");
|
|
4839
3596
|
const stored = {
|
|
4840
3597
|
id,
|
|
4841
3598
|
gadgetName,
|
|
4842
3599
|
content,
|
|
3600
|
+
charCount: content.length,
|
|
4843
3601
|
byteSize: encoder.encode(content).length,
|
|
4844
|
-
lineCount:
|
|
3602
|
+
lineCount: lines.length,
|
|
3603
|
+
maxLineLength: lines.reduce((max, line) => Math.max(max, line.length), 0),
|
|
4845
3604
|
timestamp: /* @__PURE__ */ new Date()
|
|
4846
3605
|
};
|
|
4847
3606
|
this.outputs.set(id, stored);
|
|
@@ -4945,16 +3704,20 @@ var init_output_limit_manager = __esm({
|
|
|
4945
3704
|
}
|
|
4946
3705
|
if (result.length > this.charLimit) {
|
|
4947
3706
|
const id = this.outputStore.store(ctx.gadgetName, result);
|
|
4948
|
-
const
|
|
4949
|
-
const
|
|
3707
|
+
const stored = this.outputStore.get(id);
|
|
3708
|
+
const lines = stored?.lineCount ?? result.split("\n").length;
|
|
3709
|
+
const bytes = stored?.byteSize ?? new TextEncoder().encode(result).length;
|
|
3710
|
+
const denseSuggestion = stored && shouldSuggestCharacterMode(stored, this.charLimit) ? ` ${buildCharacterModeSuggestion(stored)}` : "";
|
|
4950
3711
|
this.logger.info("Gadget output exceeded limit, stored for browsing", {
|
|
4951
3712
|
gadgetName: ctx.gadgetName,
|
|
4952
3713
|
outputId: id,
|
|
4953
3714
|
bytes,
|
|
4954
3715
|
lines,
|
|
3716
|
+
charCount: stored?.charCount,
|
|
3717
|
+
maxLineLength: stored?.maxLineLength,
|
|
4955
3718
|
charLimit: this.charLimit
|
|
4956
3719
|
});
|
|
4957
|
-
return `[Gadget "${ctx.gadgetName}" returned too much data: ${bytes.toLocaleString()} bytes, ${lines.toLocaleString()} lines. Use GadgetOutputViewer with id "${id}" to read it]
|
|
3720
|
+
return `[Gadget "${ctx.gadgetName}" returned too much data: ${bytes.toLocaleString()} bytes, ${lines.toLocaleString()} lines. Use GadgetOutputViewer with id "${id}" to read it.]` + denseSuggestion;
|
|
4958
3721
|
}
|
|
4959
3722
|
return result;
|
|
4960
3723
|
};
|
|
@@ -5340,7 +4103,7 @@ var init_activation = __esm({
|
|
|
5340
4103
|
});
|
|
5341
4104
|
|
|
5342
4105
|
// src/skills/load-skill-gadget.ts
|
|
5343
|
-
import { z as
|
|
4106
|
+
import { z as z2 } from "zod";
|
|
5344
4107
|
function createLoadSkillGadget(registry) {
|
|
5345
4108
|
const summaries = registry.getMetadataSummaries();
|
|
5346
4109
|
const skillNames = registry.getModelInvocable().map((s) => s.name);
|
|
@@ -5352,9 +4115,9 @@ function createLoadSkillGadget(registry) {
|
|
|
5352
4115
|
return createGadget({
|
|
5353
4116
|
name: LOAD_SKILL_GADGET_NAME,
|
|
5354
4117
|
description,
|
|
5355
|
-
schema:
|
|
5356
|
-
skill:
|
|
5357
|
-
arguments:
|
|
4118
|
+
schema: z2.object({
|
|
4119
|
+
skill: z2.enum(skillNames).describe("Name of the skill to load"),
|
|
4120
|
+
arguments: z2.string().optional().describe("Arguments for the skill (e.g., a filename, issue number, or search query)")
|
|
5358
4121
|
}),
|
|
5359
4122
|
execute: async ({ skill: skillName, arguments: args }) => {
|
|
5360
4123
|
const skill = registry.get(skillName);
|
|
@@ -12789,7 +11552,7 @@ __export(client_exports, {
|
|
|
12789
11552
|
LLMist: () => LLMist
|
|
12790
11553
|
});
|
|
12791
11554
|
var LLMist;
|
|
12792
|
-
var
|
|
11555
|
+
var init_client2 = __esm({
|
|
12793
11556
|
"src/core/client.ts"() {
|
|
12794
11557
|
"use strict";
|
|
12795
11558
|
init_builder();
|
|
@@ -13103,6 +11866,7 @@ var init_builder = __esm({
|
|
|
13103
11866
|
subagents;
|
|
13104
11867
|
policies;
|
|
13105
11868
|
skills;
|
|
11869
|
+
mcp;
|
|
13106
11870
|
constructor(client) {
|
|
13107
11871
|
this.core = { client, initialMessages: [] };
|
|
13108
11872
|
this.gadgets = { gadgets: [] };
|
|
@@ -13110,6 +11874,7 @@ var init_builder = __esm({
|
|
|
13110
11874
|
this.subagents = {};
|
|
13111
11875
|
this.policies = {};
|
|
13112
11876
|
this.skills = { preActivated: [], skillDirs: [] };
|
|
11877
|
+
this.mcp = { servers: [] };
|
|
13113
11878
|
}
|
|
13114
11879
|
/** Set the model to use. Supports aliases like "sonnet", "flash". */
|
|
13115
11880
|
withModel(model) {
|
|
@@ -13156,6 +11921,45 @@ var init_builder = __esm({
|
|
|
13156
11921
|
this.gadgets.gadgets.push(...gadgets);
|
|
13157
11922
|
return this;
|
|
13158
11923
|
}
|
|
11924
|
+
/**
|
|
11925
|
+
* Attach a Model Context Protocol (MCP) server.
|
|
11926
|
+
*
|
|
11927
|
+
* The agent connects to the server lazily at the start of `run()`,
|
|
11928
|
+
* discovers its tools, and registers them as native gadgets so the LLM
|
|
11929
|
+
* can call them through the standard streaming block format.
|
|
11930
|
+
*
|
|
11931
|
+
* Calling this multiple times accumulates servers. Tools across servers
|
|
11932
|
+
* are merged into a single registry; in plan 1, conflicting tool names
|
|
11933
|
+
* raise a registration warning. Plan 2 introduces deterministic
|
|
11934
|
+
* `<server>__<tool>` prefixing for collisions.
|
|
11935
|
+
*
|
|
11936
|
+
* STDIO commands are gated by an allowlist (see allowlist.ts) — pass
|
|
11937
|
+
* `trust: true` on the spec to opt in for non-allowlisted binaries.
|
|
11938
|
+
*
|
|
11939
|
+
* Zero-overhead invariant: if you never call this method, the MCP
|
|
11940
|
+
* runtime module is never loaded. Agents without MCP pay nothing.
|
|
11941
|
+
*
|
|
11942
|
+
* @example
|
|
11943
|
+
* ```typescript
|
|
11944
|
+
* const agent = LLMist.createAgent()
|
|
11945
|
+
* .withModel("sonnet")
|
|
11946
|
+
* .withMcpServer({
|
|
11947
|
+
* name: "filesystem",
|
|
11948
|
+
* transport: "stdio",
|
|
11949
|
+
* command: "npx",
|
|
11950
|
+
* args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
|
|
11951
|
+
* })
|
|
11952
|
+
* .ask("list files in /tmp");
|
|
11953
|
+
* ```
|
|
11954
|
+
*/
|
|
11955
|
+
withMcpServer(spec) {
|
|
11956
|
+
this.mcp.servers.push(spec);
|
|
11957
|
+
return this;
|
|
11958
|
+
}
|
|
11959
|
+
/** Inspect the configured MCP server specs. Useful for tests. */
|
|
11960
|
+
getMcpServerSpecs() {
|
|
11961
|
+
return this.mcp.servers;
|
|
11962
|
+
}
|
|
13159
11963
|
/** Add conversation history messages. */
|
|
13160
11964
|
withHistory(messages) {
|
|
13161
11965
|
this.core.initialMessages.push(...normalizeHistory(messages));
|
|
@@ -13417,7 +12221,7 @@ ${resolved}`);
|
|
|
13417
12221
|
}
|
|
13418
12222
|
buildAgentOptions(userPrompt) {
|
|
13419
12223
|
if (!this.core.client) {
|
|
13420
|
-
const { LLMist: LLMistClass } = (
|
|
12224
|
+
const { LLMist: LLMistClass } = (init_client2(), __toCommonJS(client_exports));
|
|
13421
12225
|
this.core.client = new LLMistClass();
|
|
13422
12226
|
}
|
|
13423
12227
|
const registry = GadgetRegistry.from(this.gadgets.gadgets);
|
|
@@ -13476,7 +12280,8 @@ ${preActivatedBlock}` : preActivatedBlock;
|
|
|
13476
12280
|
parentObservers: this.subagents.parentObservers
|
|
13477
12281
|
},
|
|
13478
12282
|
sharedRateLimitTracker: this.subagents.sharedRateLimitTracker,
|
|
13479
|
-
sharedRetryConfig: this.retry.sharedRetryConfig
|
|
12283
|
+
sharedRetryConfig: this.retry.sharedRetryConfig,
|
|
12284
|
+
mcpSpecs: this.mcp.servers.length > 0 ? [...this.mcp.servers] : void 0
|
|
13480
12285
|
};
|
|
13481
12286
|
}
|
|
13482
12287
|
/** Create agent and start with a user prompt. */
|
|
@@ -14400,7 +13205,7 @@ var init_typed_gadget = __esm({
|
|
|
14400
13205
|
|
|
14401
13206
|
// src/gadgets/executor.ts
|
|
14402
13207
|
import equal from "fast-deep-equal";
|
|
14403
|
-
import { z as
|
|
13208
|
+
import { z as z3 } from "zod";
|
|
14404
13209
|
function getHostExportsInternal() {
|
|
14405
13210
|
return {
|
|
14406
13211
|
AgentBuilder,
|
|
@@ -14408,7 +13213,7 @@ function getHostExportsInternal() {
|
|
|
14408
13213
|
createGadget,
|
|
14409
13214
|
ExecutionTree,
|
|
14410
13215
|
LLMist,
|
|
14411
|
-
z:
|
|
13216
|
+
z: z3
|
|
14412
13217
|
};
|
|
14413
13218
|
}
|
|
14414
13219
|
var GadgetExecutor;
|
|
@@ -14417,7 +13222,7 @@ var init_executor = __esm({
|
|
|
14417
13222
|
"use strict";
|
|
14418
13223
|
init_builder();
|
|
14419
13224
|
init_hook_utils();
|
|
14420
|
-
|
|
13225
|
+
init_client2();
|
|
14421
13226
|
init_constants();
|
|
14422
13227
|
init_execution_tree();
|
|
14423
13228
|
init_logger();
|
|
@@ -16548,6 +15353,10 @@ var init_agent = __esm({
|
|
|
16548
15353
|
streamProcessorFactory;
|
|
16549
15354
|
// LLM call lifecycle helper (encapsulates prepareLLMCall, completeLLMCall, notifyLLMError)
|
|
16550
15355
|
llmCallLifecycle;
|
|
15356
|
+
// MCP integration — populated only when mcpSpecs were provided.
|
|
15357
|
+
mcpSpecs;
|
|
15358
|
+
mcpLifecycle = null;
|
|
15359
|
+
mcpDiscoveredPrompts = [];
|
|
16551
15360
|
/**
|
|
16552
15361
|
* Creates a new Agent instance.
|
|
16553
15362
|
* @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.
|
|
@@ -16619,6 +15428,7 @@ var init_agent = __esm({
|
|
|
16619
15428
|
);
|
|
16620
15429
|
}
|
|
16621
15430
|
this.signal = options.signal;
|
|
15431
|
+
this.mcpSpecs = options.mcpSpecs ?? [];
|
|
16622
15432
|
this.reasoning = options.reasoning;
|
|
16623
15433
|
this.caching = options.caching;
|
|
16624
15434
|
this.retryConfig = options.sharedRetryConfig ?? resolveRetryConfig(options.retryConfig);
|
|
@@ -16878,6 +15688,18 @@ var init_agent = __esm({
|
|
|
16878
15688
|
);
|
|
16879
15689
|
}
|
|
16880
15690
|
const unsubscribeBridge = bridgeTreeToHooks(this.tree, this.hooks, this.logger);
|
|
15691
|
+
if (this.mcpSpecs.length > 0) {
|
|
15692
|
+
const { setupMcpServers } = await import("./runtime-GKQ6QIQP.js");
|
|
15693
|
+
this.mcpLifecycle = await setupMcpServers({
|
|
15694
|
+
specs: this.mcpSpecs,
|
|
15695
|
+
registry: this.registry,
|
|
15696
|
+
conversation: this.conversation,
|
|
15697
|
+
prefixConfig: this.prefixConfig,
|
|
15698
|
+
systemPrompt: this.conversation.getBaseMessages()[0]?.role === "system" ? this.conversation.getBaseMessages()[0].content : void 0,
|
|
15699
|
+
logger: this.logger,
|
|
15700
|
+
onPromptDiscovered: (skill) => this.mcpDiscoveredPrompts.push(skill)
|
|
15701
|
+
});
|
|
15702
|
+
}
|
|
16881
15703
|
let currentIteration = 0;
|
|
16882
15704
|
this.logger.info("Starting agent loop", {
|
|
16883
15705
|
model: this.model,
|
|
@@ -17077,6 +15899,14 @@ var init_agent = __esm({
|
|
|
17077
15899
|
}
|
|
17078
15900
|
}
|
|
17079
15901
|
unsubscribeBridge();
|
|
15902
|
+
if (this.mcpLifecycle) {
|
|
15903
|
+
try {
|
|
15904
|
+
await this.mcpLifecycle.closeAll();
|
|
15905
|
+
} catch (err) {
|
|
15906
|
+
this.logger.debug("MCP lifecycle teardown error (suppressed):", err);
|
|
15907
|
+
}
|
|
15908
|
+
this.mcpLifecycle = null;
|
|
15909
|
+
}
|
|
17080
15910
|
}
|
|
17081
15911
|
}
|
|
17082
15912
|
/**
|
|
@@ -17268,7 +16098,7 @@ init_builder();
|
|
|
17268
16098
|
init_event_handlers();
|
|
17269
16099
|
init_file_logging();
|
|
17270
16100
|
init_hook_presets();
|
|
17271
|
-
import { z as
|
|
16101
|
+
import { z as z4 } from "zod";
|
|
17272
16102
|
|
|
17273
16103
|
// src/agent/compaction/index.ts
|
|
17274
16104
|
init_config();
|
|
@@ -17381,7 +16211,7 @@ function createHints(config) {
|
|
|
17381
16211
|
init_stream_processor();
|
|
17382
16212
|
|
|
17383
16213
|
// src/index.ts
|
|
17384
|
-
|
|
16214
|
+
init_client2();
|
|
17385
16215
|
init_constants();
|
|
17386
16216
|
|
|
17387
16217
|
// src/core/errors.ts
|
|
@@ -17446,140 +16276,254 @@ init_create_gadget();
|
|
|
17446
16276
|
init_exceptions();
|
|
17447
16277
|
init_executor();
|
|
17448
16278
|
init_gadget();
|
|
16279
|
+
init_helpers();
|
|
16280
|
+
init_output_viewer();
|
|
16281
|
+
init_parser2();
|
|
16282
|
+
init_registry();
|
|
16283
|
+
init_typed_gadget();
|
|
17449
16284
|
|
|
17450
|
-
// src/
|
|
17451
|
-
|
|
17452
|
-
|
|
17453
|
-
|
|
17454
|
-
|
|
17455
|
-
|
|
17456
|
-
|
|
17457
|
-
|
|
17458
|
-
|
|
17459
|
-
|
|
17460
|
-
|
|
17461
|
-
|
|
17462
|
-
|
|
17463
|
-
|
|
17464
|
-
|
|
17465
|
-
}
|
|
17466
|
-
|
|
17467
|
-
|
|
17468
|
-
|
|
17469
|
-
|
|
17470
|
-
|
|
17471
|
-
const
|
|
16285
|
+
// src/mcp/index.ts
|
|
16286
|
+
init_allowlist();
|
|
16287
|
+
init_client();
|
|
16288
|
+
init_errors();
|
|
16289
|
+
|
|
16290
|
+
// src/mcp/gadget-exporter.ts
|
|
16291
|
+
init_schema_to_json();
|
|
16292
|
+
|
|
16293
|
+
// src/gadgets/validation.ts
|
|
16294
|
+
function validateAndApplyDefaults(schema, params) {
|
|
16295
|
+
const result = schema.safeParse(params);
|
|
16296
|
+
if (result.success) {
|
|
16297
|
+
return {
|
|
16298
|
+
success: true,
|
|
16299
|
+
data: result.data
|
|
16300
|
+
};
|
|
16301
|
+
}
|
|
16302
|
+
const issues = result.error.issues.map((issue) => ({
|
|
16303
|
+
path: issue.path.join(".") || "root",
|
|
16304
|
+
message: issue.message
|
|
16305
|
+
}));
|
|
16306
|
+
const formattedError = `Invalid parameters: ${issues.map((i) => `${i.path}: ${i.message}`).join("; ")}`;
|
|
17472
16307
|
return {
|
|
17473
|
-
|
|
17474
|
-
|
|
17475
|
-
|
|
17476
|
-
description: options?.description,
|
|
17477
|
-
metadata: options?.metadata,
|
|
17478
|
-
fileName: options?.fileName
|
|
16308
|
+
success: false,
|
|
16309
|
+
error: formattedError,
|
|
16310
|
+
issues
|
|
17479
16311
|
};
|
|
17480
16312
|
}
|
|
17481
|
-
function
|
|
17482
|
-
if (
|
|
17483
|
-
|
|
16313
|
+
function validateGadgetParams(gadget, params) {
|
|
16314
|
+
if (!gadget.parameterSchema) {
|
|
16315
|
+
return {
|
|
16316
|
+
success: true,
|
|
16317
|
+
data: params
|
|
16318
|
+
};
|
|
17484
16319
|
}
|
|
17485
|
-
return
|
|
17486
|
-
result,
|
|
17487
|
-
media,
|
|
17488
|
-
cost
|
|
17489
|
-
};
|
|
16320
|
+
return validateAndApplyDefaults(gadget.parameterSchema, params);
|
|
17490
16321
|
}
|
|
17491
|
-
|
|
17492
|
-
|
|
17493
|
-
|
|
17494
|
-
|
|
17495
|
-
|
|
17496
|
-
|
|
17497
|
-
);
|
|
16322
|
+
|
|
16323
|
+
// src/mcp/gadget-exporter.ts
|
|
16324
|
+
function gadgetToMcpTool(gadget) {
|
|
16325
|
+
const description = gadget.description && gadget.description.length > 0 ? gadget.description : `Native llmist gadget "${gadget.name ?? "unnamed"}"`;
|
|
16326
|
+
let inputSchema;
|
|
16327
|
+
if (gadget.parameterSchema) {
|
|
16328
|
+
inputSchema = schemaToJSONSchema(gadget.parameterSchema);
|
|
16329
|
+
} else {
|
|
16330
|
+
inputSchema = { type: "object", properties: {} };
|
|
17498
16331
|
}
|
|
17499
16332
|
return {
|
|
17500
|
-
|
|
17501
|
-
|
|
17502
|
-
|
|
17503
|
-
kind: "image",
|
|
17504
|
-
data: buffer.toString("base64"),
|
|
17505
|
-
mimeType,
|
|
17506
|
-
description: options?.description,
|
|
17507
|
-
metadata: options?.metadata,
|
|
17508
|
-
fileName: options?.fileName
|
|
17509
|
-
}
|
|
17510
|
-
],
|
|
17511
|
-
cost: options?.cost
|
|
16333
|
+
name: gadget.name ?? "unnamed-gadget",
|
|
16334
|
+
description,
|
|
16335
|
+
inputSchema
|
|
17512
16336
|
};
|
|
17513
16337
|
}
|
|
17514
|
-
function
|
|
17515
|
-
if (
|
|
17516
|
-
|
|
17517
|
-
}
|
|
17518
|
-
|
|
17519
|
-
const
|
|
17520
|
-
const
|
|
17521
|
-
if (
|
|
17522
|
-
|
|
17523
|
-
|
|
17524
|
-
);
|
|
16338
|
+
function gadgetResultToMcpContent(ret) {
|
|
16339
|
+
if (typeof ret === "string") {
|
|
16340
|
+
return [{ type: "text", text: ret }];
|
|
16341
|
+
}
|
|
16342
|
+
if (ret && typeof ret === "object" && "result" in ret) {
|
|
16343
|
+
const r = ret;
|
|
16344
|
+
const blocks = [];
|
|
16345
|
+
if (typeof r.result === "string") {
|
|
16346
|
+
blocks.push({ type: "text", text: r.result });
|
|
16347
|
+
} else {
|
|
16348
|
+
blocks.push({ type: "text", text: JSON.stringify(r.result) });
|
|
16349
|
+
}
|
|
16350
|
+
if (r.media) {
|
|
16351
|
+
for (const m of r.media) {
|
|
16352
|
+
if (m.kind === "image" || m.kind === "audio") {
|
|
16353
|
+
blocks.push({
|
|
16354
|
+
type: m.kind,
|
|
16355
|
+
data: m.data,
|
|
16356
|
+
mimeType: m.mimeType
|
|
16357
|
+
});
|
|
16358
|
+
}
|
|
16359
|
+
}
|
|
16360
|
+
}
|
|
16361
|
+
return blocks;
|
|
16362
|
+
}
|
|
16363
|
+
return [{ type: "text", text: JSON.stringify(ret) }];
|
|
16364
|
+
}
|
|
16365
|
+
async function runGadgetForMcp(gadget, rawParams) {
|
|
16366
|
+
if (gadget.parameterSchema) {
|
|
16367
|
+
const validation = validateAndApplyDefaults(
|
|
16368
|
+
gadget.parameterSchema,
|
|
16369
|
+
rawParams ?? {}
|
|
16370
|
+
);
|
|
16371
|
+
if (!validation.success) {
|
|
16372
|
+
return {
|
|
16373
|
+
isError: true,
|
|
16374
|
+
content: [
|
|
16375
|
+
{
|
|
16376
|
+
type: "text",
|
|
16377
|
+
text: `Invalid arguments for gadget "${gadget.name}": ${validation.error}`
|
|
16378
|
+
}
|
|
16379
|
+
]
|
|
16380
|
+
};
|
|
17525
16381
|
}
|
|
16382
|
+
rawParams = validation.data;
|
|
16383
|
+
}
|
|
16384
|
+
try {
|
|
16385
|
+
const result = await gadget.execute(rawParams);
|
|
17526
16386
|
return {
|
|
17527
|
-
|
|
17528
|
-
data: buffer.toString("base64"),
|
|
17529
|
-
mimeType,
|
|
17530
|
-
description: img.description,
|
|
17531
|
-
metadata: img.metadata,
|
|
17532
|
-
fileName: img.fileName
|
|
16387
|
+
content: gadgetResultToMcpContent(result)
|
|
17533
16388
|
};
|
|
17534
|
-
})
|
|
17535
|
-
|
|
16389
|
+
} catch (err) {
|
|
16390
|
+
return {
|
|
16391
|
+
isError: true,
|
|
16392
|
+
content: [
|
|
16393
|
+
{
|
|
16394
|
+
type: "text",
|
|
16395
|
+
text: `Gadget "${gadget.name}" failed: ${err.message}`
|
|
16396
|
+
}
|
|
16397
|
+
]
|
|
16398
|
+
};
|
|
16399
|
+
}
|
|
17536
16400
|
}
|
|
17537
|
-
|
|
17538
|
-
|
|
17539
|
-
|
|
17540
|
-
|
|
17541
|
-
|
|
17542
|
-
|
|
17543
|
-
|
|
16401
|
+
|
|
16402
|
+
// src/mcp/index.ts
|
|
16403
|
+
init_json_schema_to_zod();
|
|
16404
|
+
init_lifecycle();
|
|
16405
|
+
|
|
16406
|
+
// src/mcp/skill-exporter.ts
|
|
16407
|
+
function skillToMcpPrompt(skill) {
|
|
16408
|
+
const description = skill.description && skill.description.length > 0 ? skill.description : `Native llmist skill "${skill.name}"`;
|
|
16409
|
+
const args = [];
|
|
16410
|
+
if (skill.metadata.argumentHint) {
|
|
16411
|
+
args.push({
|
|
16412
|
+
name: "arguments",
|
|
16413
|
+
description: skill.metadata.argumentHint,
|
|
16414
|
+
required: false
|
|
16415
|
+
});
|
|
17544
16416
|
}
|
|
17545
|
-
const metadata = options?.durationMs ? { durationMs: options.durationMs } : void 0;
|
|
17546
16417
|
return {
|
|
17547
|
-
|
|
17548
|
-
|
|
16418
|
+
name: skill.name,
|
|
16419
|
+
description,
|
|
16420
|
+
...args.length > 0 ? { arguments: args } : {}
|
|
16421
|
+
};
|
|
16422
|
+
}
|
|
16423
|
+
async function renderSkillForMcpPrompt(skill, args) {
|
|
16424
|
+
const argString = typeof args.arguments === "string" ? args.arguments : Object.values(args).filter((v) => typeof v === "string").join(" ");
|
|
16425
|
+
const activation = await skill.activate({
|
|
16426
|
+
arguments: argString || void 0
|
|
16427
|
+
});
|
|
16428
|
+
return {
|
|
16429
|
+
description: skill.description,
|
|
16430
|
+
messages: [
|
|
17549
16431
|
{
|
|
17550
|
-
|
|
17551
|
-
|
|
17552
|
-
mimeType,
|
|
17553
|
-
description: options?.description,
|
|
17554
|
-
metadata,
|
|
17555
|
-
fileName: options?.fileName
|
|
16432
|
+
role: "user",
|
|
16433
|
+
content: { type: "text", text: activation.resolvedInstructions }
|
|
17556
16434
|
}
|
|
17557
|
-
]
|
|
17558
|
-
cost: options?.cost
|
|
16435
|
+
]
|
|
17559
16436
|
};
|
|
17560
16437
|
}
|
|
17561
|
-
|
|
17562
|
-
|
|
16438
|
+
|
|
16439
|
+
// src/mcp/server.ts
|
|
16440
|
+
var DEFAULT_SERVER_INFO = { name: "llmist", version: "0.0.0" };
|
|
16441
|
+
function createMcpServer(opts) {
|
|
16442
|
+
const { gadgets, skills } = opts;
|
|
16443
|
+
const hasTools = gadgets.getAll().length > 0;
|
|
16444
|
+
const hasPrompts = !!skills && skills.size > 0;
|
|
16445
|
+
const capabilities = {};
|
|
16446
|
+
if (hasTools) capabilities.tools = {};
|
|
16447
|
+
if (hasPrompts) capabilities.prompts = {};
|
|
16448
|
+
let sdkServer = null;
|
|
16449
|
+
let running = false;
|
|
16450
|
+
async function ensureServer() {
|
|
16451
|
+
if (sdkServer) return sdkServer;
|
|
16452
|
+
const [serverMod, typesMod] = await Promise.all([
|
|
16453
|
+
import("@modelcontextprotocol/sdk/server/index.js"),
|
|
16454
|
+
import("@modelcontextprotocol/sdk/types.js")
|
|
16455
|
+
]);
|
|
16456
|
+
const ServerClass = serverMod.Server;
|
|
16457
|
+
const server = new ServerClass(opts.serverInfo ?? DEFAULT_SERVER_INFO, {
|
|
16458
|
+
capabilities
|
|
16459
|
+
});
|
|
16460
|
+
if (hasTools) {
|
|
16461
|
+
server.setRequestHandler(typesMod.ListToolsRequestSchema, async () => ({
|
|
16462
|
+
tools: gadgets.getAll().map(gadgetToMcpTool)
|
|
16463
|
+
}));
|
|
16464
|
+
server.setRequestHandler(
|
|
16465
|
+
typesMod.CallToolRequestSchema,
|
|
16466
|
+
async (req) => {
|
|
16467
|
+
const gadget = gadgets.get(req.params.name);
|
|
16468
|
+
if (!gadget) {
|
|
16469
|
+
return {
|
|
16470
|
+
isError: true,
|
|
16471
|
+
content: [
|
|
16472
|
+
{
|
|
16473
|
+
type: "text",
|
|
16474
|
+
text: `Unknown tool "${req.params.name}". Call tools/list first.`
|
|
16475
|
+
}
|
|
16476
|
+
]
|
|
16477
|
+
};
|
|
16478
|
+
}
|
|
16479
|
+
return runGadgetForMcp(gadget, req.params.arguments ?? {});
|
|
16480
|
+
}
|
|
16481
|
+
);
|
|
16482
|
+
}
|
|
16483
|
+
if (hasPrompts && skills) {
|
|
16484
|
+
server.setRequestHandler(typesMod.ListPromptsRequestSchema, async () => ({
|
|
16485
|
+
prompts: Array.from(skills.getAll()).map(skillToMcpPrompt)
|
|
16486
|
+
}));
|
|
16487
|
+
server.setRequestHandler(
|
|
16488
|
+
typesMod.GetPromptRequestSchema,
|
|
16489
|
+
async (req) => {
|
|
16490
|
+
const skill = skills.get(req.params.name);
|
|
16491
|
+
if (!skill) {
|
|
16492
|
+
throw new Error(`Unknown prompt "${req.params.name}"`);
|
|
16493
|
+
}
|
|
16494
|
+
const result = await renderSkillForMcpPrompt(skill, req.params.arguments ?? {});
|
|
16495
|
+
return result;
|
|
16496
|
+
}
|
|
16497
|
+
);
|
|
16498
|
+
}
|
|
16499
|
+
sdkServer = server;
|
|
16500
|
+
return server;
|
|
16501
|
+
}
|
|
17563
16502
|
return {
|
|
17564
|
-
|
|
17565
|
-
|
|
17566
|
-
|
|
17567
|
-
|
|
17568
|
-
|
|
17569
|
-
|
|
17570
|
-
|
|
17571
|
-
|
|
16503
|
+
get running() {
|
|
16504
|
+
return running;
|
|
16505
|
+
},
|
|
16506
|
+
async connect(transport) {
|
|
16507
|
+
const server = await ensureServer();
|
|
16508
|
+
await server.connect(transport);
|
|
16509
|
+
running = true;
|
|
16510
|
+
},
|
|
16511
|
+
async stop() {
|
|
16512
|
+
if (!sdkServer) return;
|
|
16513
|
+
try {
|
|
16514
|
+
await sdkServer.close();
|
|
16515
|
+
} catch {
|
|
17572
16516
|
}
|
|
17573
|
-
|
|
17574
|
-
|
|
16517
|
+
sdkServer = null;
|
|
16518
|
+
running = false;
|
|
16519
|
+
}
|
|
17575
16520
|
};
|
|
17576
16521
|
}
|
|
17577
16522
|
|
|
16523
|
+
// src/mcp/index.ts
|
|
16524
|
+
init_tool_adapter();
|
|
16525
|
+
|
|
17578
16526
|
// src/index.ts
|
|
17579
|
-
init_output_viewer();
|
|
17580
|
-
init_parser2();
|
|
17581
|
-
init_registry();
|
|
17582
|
-
init_typed_gadget();
|
|
17583
16527
|
init_constants2();
|
|
17584
16528
|
|
|
17585
16529
|
// src/utils/config-resolver.ts
|
|
@@ -17688,38 +16632,6 @@ function hasHostExports(ctx) {
|
|
|
17688
16632
|
init_media_store();
|
|
17689
16633
|
init_schema_to_json();
|
|
17690
16634
|
init_schema_validator();
|
|
17691
|
-
|
|
17692
|
-
// src/gadgets/validation.ts
|
|
17693
|
-
function validateAndApplyDefaults(schema, params) {
|
|
17694
|
-
const result = schema.safeParse(params);
|
|
17695
|
-
if (result.success) {
|
|
17696
|
-
return {
|
|
17697
|
-
success: true,
|
|
17698
|
-
data: result.data
|
|
17699
|
-
};
|
|
17700
|
-
}
|
|
17701
|
-
const issues = result.error.issues.map((issue) => ({
|
|
17702
|
-
path: issue.path.join(".") || "root",
|
|
17703
|
-
message: issue.message
|
|
17704
|
-
}));
|
|
17705
|
-
const formattedError = `Invalid parameters: ${issues.map((i) => `${i.path}: ${i.message}`).join("; ")}`;
|
|
17706
|
-
return {
|
|
17707
|
-
success: false,
|
|
17708
|
-
error: formattedError,
|
|
17709
|
-
issues
|
|
17710
|
-
};
|
|
17711
|
-
}
|
|
17712
|
-
function validateGadgetParams(gadget, params) {
|
|
17713
|
-
if (!gadget.parameterSchema) {
|
|
17714
|
-
return {
|
|
17715
|
-
success: true,
|
|
17716
|
-
data: params
|
|
17717
|
-
};
|
|
17718
|
-
}
|
|
17719
|
-
return validateAndApplyDefaults(gadget.parameterSchema, params);
|
|
17720
|
-
}
|
|
17721
|
-
|
|
17722
|
-
// src/index.ts
|
|
17723
16635
|
init_logger();
|
|
17724
16636
|
|
|
17725
16637
|
// src/package/manifest.ts
|
|
@@ -18017,6 +16929,7 @@ export {
|
|
|
18017
16929
|
ConversationManager,
|
|
18018
16930
|
DEFAULT_COMPACTION_CONFIG,
|
|
18019
16931
|
DEFAULT_HINTS,
|
|
16932
|
+
DEFAULT_MCP_COMMAND_ALLOWLIST,
|
|
18020
16933
|
DEFAULT_PROMPTS,
|
|
18021
16934
|
DEFAULT_RATE_LIMIT_CONFIG,
|
|
18022
16935
|
DEFAULT_RETRY_CONFIG,
|
|
@@ -18036,10 +16949,17 @@ export {
|
|
|
18036
16949
|
HuggingFaceProvider,
|
|
18037
16950
|
HumanInputRequiredException,
|
|
18038
16951
|
HybridStrategy,
|
|
16952
|
+
JsonSchemaConversionError,
|
|
18039
16953
|
LLMMessageBuilder,
|
|
18040
16954
|
LLMist,
|
|
18041
16955
|
LOAD_SKILL_GADGET_NAME,
|
|
18042
16956
|
MODEL_ALIASES,
|
|
16957
|
+
McpClient,
|
|
16958
|
+
McpConnectError,
|
|
16959
|
+
McpError,
|
|
16960
|
+
McpLifecycle,
|
|
16961
|
+
McpToolCallError,
|
|
16962
|
+
McpUntrustedCommandError,
|
|
18043
16963
|
MediaStore,
|
|
18044
16964
|
ModelIdentifierParser,
|
|
18045
16965
|
ModelRegistry,
|
|
@@ -18055,6 +16975,7 @@ export {
|
|
|
18055
16975
|
SummarizationStrategy,
|
|
18056
16976
|
TaskCompletionSignal,
|
|
18057
16977
|
TimeoutException,
|
|
16978
|
+
assertCommandAllowed,
|
|
18058
16979
|
audioFromBase64,
|
|
18059
16980
|
audioFromBuffer,
|
|
18060
16981
|
collectEvents,
|
|
@@ -18069,6 +16990,7 @@ export {
|
|
|
18069
16990
|
createHuggingFaceProviderFromEnv,
|
|
18070
16991
|
createLoadSkillGadget,
|
|
18071
16992
|
createLogger,
|
|
16993
|
+
createMcpServer,
|
|
18072
16994
|
createMediaOutput,
|
|
18073
16995
|
createOpenAIProviderFromEnv,
|
|
18074
16996
|
createOpenRouterProviderFromEnv,
|
|
@@ -18091,7 +17013,9 @@ export {
|
|
|
18091
17013
|
formatLLMError,
|
|
18092
17014
|
formatLlmRequest,
|
|
18093
17015
|
gadgetError,
|
|
17016
|
+
gadgetResultToMcpContent,
|
|
18094
17017
|
gadgetSuccess,
|
|
17018
|
+
gadgetToMcpTool,
|
|
18095
17019
|
getErrorMessage,
|
|
18096
17020
|
getHostExports2 as getHostExports,
|
|
18097
17021
|
getModelId,
|
|
@@ -18119,9 +17043,11 @@ export {
|
|
|
18119
17043
|
isSubagentEvent,
|
|
18120
17044
|
isTextPart,
|
|
18121
17045
|
iterationProgressHint,
|
|
17046
|
+
jsonSchemaToZod,
|
|
18122
17047
|
listPresets,
|
|
18123
17048
|
listSubagents,
|
|
18124
17049
|
loadSkillsFromDirectory,
|
|
17050
|
+
mcpToolToGadget,
|
|
18125
17051
|
normalizeMessageContent,
|
|
18126
17052
|
parallelGadgetHint,
|
|
18127
17053
|
parseDataUrl,
|
|
@@ -18132,6 +17058,7 @@ export {
|
|
|
18132
17058
|
parseSkillContent,
|
|
18133
17059
|
parseSkillFile,
|
|
18134
17060
|
randomDelay,
|
|
17061
|
+
renderSkillForMcpPrompt,
|
|
18135
17062
|
resetFileLoggingState,
|
|
18136
17063
|
resolveConfig,
|
|
18137
17064
|
resolveHintTemplate,
|
|
@@ -18149,9 +17076,11 @@ export {
|
|
|
18149
17076
|
resultWithImage,
|
|
18150
17077
|
resultWithImages,
|
|
18151
17078
|
resultWithMedia,
|
|
17079
|
+
runGadgetForMcp,
|
|
18152
17080
|
runWithHandlers,
|
|
18153
17081
|
scanResources,
|
|
18154
17082
|
schemaToJSONSchema,
|
|
17083
|
+
skillToMcpPrompt,
|
|
18155
17084
|
stream,
|
|
18156
17085
|
stripProviderPrefix,
|
|
18157
17086
|
substituteArguments,
|
|
@@ -18167,6 +17096,6 @@ export {
|
|
|
18167
17096
|
withErrorHandling,
|
|
18168
17097
|
withRetry,
|
|
18169
17098
|
withTimeout,
|
|
18170
|
-
|
|
17099
|
+
z4 as z
|
|
18171
17100
|
};
|
|
18172
17101
|
//# sourceMappingURL=index.js.map
|