llmist 0.4.0 → 0.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 +4 -1
- package/dist/{chunk-I55AV3WV.js → chunk-LKIBXQ5I.js} +3 -2
- package/dist/chunk-LKIBXQ5I.js.map +1 -0
- package/dist/{chunk-VYBRYR2S.js → chunk-MH4TQ5AD.js} +471 -97
- package/dist/chunk-MH4TQ5AD.js.map +1 -0
- package/dist/{chunk-VRTKJK2X.js → chunk-VF2WOCHM.js} +2 -2
- package/dist/cli.cjs +1243 -202
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +773 -107
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +473 -97
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -7
- package/dist/index.d.ts +36 -7
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/{mock-stream-C0vOqI3L.d.cts → mock-stream-C8mBXRzJ.d.cts} +58 -3
- package/dist/{mock-stream-C0vOqI3L.d.ts → mock-stream-C8mBXRzJ.d.ts} +58 -3
- package/dist/testing/index.cjs +471 -97
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +2 -2
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +2 -2
- package/package.json +5 -1
- package/dist/chunk-I55AV3WV.js.map +0 -1
- package/dist/chunk-VYBRYR2S.js.map +0 -1
- /package/dist/{chunk-VRTKJK2X.js.map → chunk-VF2WOCHM.js.map} +0 -0
package/dist/testing/index.cjs
CHANGED
|
@@ -436,6 +436,7 @@ var init_prompt_config = __esm({
|
|
|
436
436
|
criticalUsage: "INVOKE gadgets using the markers - do not describe what you want to do.",
|
|
437
437
|
formatDescriptionYaml: "Parameters in YAML format (one per line)",
|
|
438
438
|
formatDescriptionJson: "Parameters in JSON format (valid JSON object)",
|
|
439
|
+
formatDescriptionToml: "Parameters in TOML format (key = value pairs, use triple-quotes for multiline)",
|
|
439
440
|
rules: () => [
|
|
440
441
|
"Output ONLY plain text with the exact markers - never use function/tool calling",
|
|
441
442
|
"You can invoke multiple gadgets in a single response",
|
|
@@ -443,6 +444,7 @@ var init_prompt_config = __esm({
|
|
|
443
444
|
],
|
|
444
445
|
schemaLabelJson: "\n\nInput Schema (JSON):",
|
|
445
446
|
schemaLabelYaml: "\n\nInput Schema (YAML):",
|
|
447
|
+
schemaLabelToml: "\n\nInput Schema (TOML):",
|
|
446
448
|
customExamples: null
|
|
447
449
|
};
|
|
448
450
|
}
|
|
@@ -463,6 +465,15 @@ var init_messages = __esm({
|
|
|
463
465
|
constructor(promptConfig) {
|
|
464
466
|
this.promptConfig = promptConfig ?? {};
|
|
465
467
|
}
|
|
468
|
+
/**
|
|
469
|
+
* Set custom prefixes for gadget markers.
|
|
470
|
+
* Used to configure history builder to match system prompt markers.
|
|
471
|
+
*/
|
|
472
|
+
withPrefixes(startPrefix, endPrefix) {
|
|
473
|
+
this.startPrefix = startPrefix;
|
|
474
|
+
this.endPrefix = endPrefix;
|
|
475
|
+
return this;
|
|
476
|
+
}
|
|
466
477
|
addSystem(content, metadata) {
|
|
467
478
|
this.messages.push({ role: "system", content, metadata });
|
|
468
479
|
return this;
|
|
@@ -500,7 +511,14 @@ var init_messages = __esm({
|
|
|
500
511
|
for (const gadget of gadgets) {
|
|
501
512
|
const gadgetName = gadget.name ?? gadget.constructor.name;
|
|
502
513
|
const instruction = gadget.getInstruction(parameterFormat);
|
|
503
|
-
const
|
|
514
|
+
const schemaMarkers = {
|
|
515
|
+
yaml: "\n\nInput Schema (YAML):",
|
|
516
|
+
json: "\n\nInput Schema (JSON):",
|
|
517
|
+
toml: "\n\nInput Schema (TOML):",
|
|
518
|
+
auto: "\n\nInput Schema (JSON):"
|
|
519
|
+
// auto defaults to JSON schema display
|
|
520
|
+
};
|
|
521
|
+
const schemaMarker = schemaMarkers[parameterFormat];
|
|
504
522
|
const schemaIndex = instruction.indexOf(schemaMarker);
|
|
505
523
|
const description = (schemaIndex !== -1 ? instruction.substring(0, schemaIndex) : instruction).trim();
|
|
506
524
|
const schema = schemaIndex !== -1 ? instruction.substring(schemaIndex + schemaMarker.length).trim() : "";
|
|
@@ -520,15 +538,26 @@ ${schema}`);
|
|
|
520
538
|
}
|
|
521
539
|
buildUsageSection(parameterFormat, context) {
|
|
522
540
|
const parts = [];
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
541
|
+
const formatDescriptionMap = {
|
|
542
|
+
yaml: {
|
|
543
|
+
config: this.promptConfig.formatDescriptionYaml,
|
|
544
|
+
defaultValue: DEFAULT_PROMPTS.formatDescriptionYaml
|
|
545
|
+
},
|
|
546
|
+
json: {
|
|
547
|
+
config: this.promptConfig.formatDescriptionJson,
|
|
548
|
+
defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
|
|
549
|
+
},
|
|
550
|
+
toml: {
|
|
551
|
+
config: this.promptConfig.formatDescriptionToml,
|
|
552
|
+
defaultValue: DEFAULT_PROMPTS.formatDescriptionToml
|
|
553
|
+
},
|
|
554
|
+
auto: {
|
|
555
|
+
config: this.promptConfig.formatDescriptionJson,
|
|
556
|
+
defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
const { config, defaultValue } = formatDescriptionMap[parameterFormat];
|
|
560
|
+
const formatDescription = resolvePromptTemplate(config, defaultValue, context);
|
|
532
561
|
parts.push("\n\nHOW TO INVOKE GADGETS");
|
|
533
562
|
parts.push("\n=====================\n");
|
|
534
563
|
const criticalUsage = resolvePromptTemplate(
|
|
@@ -556,38 +585,110 @@ CRITICAL: ${criticalUsage}
|
|
|
556
585
|
return this.promptConfig.customExamples(context);
|
|
557
586
|
}
|
|
558
587
|
const parts = [];
|
|
559
|
-
const
|
|
588
|
+
const singleExamples = {
|
|
589
|
+
yaml: `${this.startPrefix}translate
|
|
560
590
|
from: English
|
|
561
591
|
to: Polish
|
|
562
|
-
content: Paris is the capital of France.
|
|
563
|
-
${this.endPrefix}
|
|
564
|
-
|
|
565
|
-
|
|
592
|
+
content: "Paris is the capital of France: a beautiful city."
|
|
593
|
+
${this.endPrefix}`,
|
|
594
|
+
json: `${this.startPrefix}translate
|
|
595
|
+
{"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
|
|
596
|
+
${this.endPrefix}`,
|
|
597
|
+
toml: `${this.startPrefix}translate
|
|
598
|
+
from = "English"
|
|
599
|
+
to = "Polish"
|
|
600
|
+
content = "Paris is the capital of France: a beautiful city."
|
|
601
|
+
${this.endPrefix}`,
|
|
602
|
+
auto: `${this.startPrefix}translate
|
|
603
|
+
{"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
|
|
604
|
+
${this.endPrefix}`
|
|
605
|
+
};
|
|
566
606
|
parts.push(`
|
|
567
607
|
|
|
568
608
|
EXAMPLE (Single Gadget):
|
|
569
609
|
|
|
570
|
-
${
|
|
571
|
-
const
|
|
610
|
+
${singleExamples[parameterFormat]}`);
|
|
611
|
+
const multipleExamples = {
|
|
612
|
+
yaml: `${this.startPrefix}translate
|
|
572
613
|
from: English
|
|
573
614
|
to: Polish
|
|
574
|
-
content: Paris is the capital of France.
|
|
615
|
+
content: "Paris is the capital of France: a beautiful city."
|
|
575
616
|
${this.endPrefix}
|
|
576
617
|
${this.startPrefix}analyze
|
|
577
618
|
type: economic_analysis
|
|
578
619
|
matter: "Polish Economy"
|
|
579
|
-
question:
|
|
580
|
-
|
|
581
|
-
|
|
620
|
+
question: |
|
|
621
|
+
Analyze the following:
|
|
622
|
+
- Polish arms exports 2025
|
|
623
|
+
- Economic implications
|
|
624
|
+
${this.endPrefix}`,
|
|
625
|
+
json: `${this.startPrefix}translate
|
|
626
|
+
{"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
|
|
627
|
+
${this.endPrefix}
|
|
628
|
+
${this.startPrefix}analyze
|
|
629
|
+
{"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
|
|
630
|
+
${this.endPrefix}`,
|
|
631
|
+
toml: `${this.startPrefix}translate
|
|
632
|
+
from = "English"
|
|
633
|
+
to = "Polish"
|
|
634
|
+
content = "Paris is the capital of France: a beautiful city."
|
|
635
|
+
${this.endPrefix}
|
|
636
|
+
${this.startPrefix}analyze
|
|
637
|
+
type = "economic_analysis"
|
|
638
|
+
matter = "Polish Economy"
|
|
639
|
+
question = """
|
|
640
|
+
Analyze the following:
|
|
641
|
+
- Polish arms exports 2025
|
|
642
|
+
- Economic implications
|
|
643
|
+
"""
|
|
644
|
+
${this.endPrefix}`,
|
|
645
|
+
auto: `${this.startPrefix}translate
|
|
646
|
+
{"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
|
|
582
647
|
${this.endPrefix}
|
|
583
648
|
${this.startPrefix}analyze
|
|
584
|
-
{"type": "economic_analysis", "matter": "Polish Economy", "question": "Polish arms exports 2025
|
|
585
|
-
${this.endPrefix}
|
|
649
|
+
{"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
|
|
650
|
+
${this.endPrefix}`
|
|
651
|
+
};
|
|
586
652
|
parts.push(`
|
|
587
653
|
|
|
588
654
|
EXAMPLE (Multiple Gadgets):
|
|
589
655
|
|
|
590
|
-
${
|
|
656
|
+
${multipleExamples[parameterFormat]}`);
|
|
657
|
+
if (parameterFormat === "yaml") {
|
|
658
|
+
parts.push(`
|
|
659
|
+
|
|
660
|
+
YAML MULTILINE SYNTAX:
|
|
661
|
+
For string values with special characters (colons, dashes, quotes) or multiple lines,
|
|
662
|
+
use the pipe (|) syntax. ALL content lines MUST be indented with 2 spaces:
|
|
663
|
+
|
|
664
|
+
CORRECT - all lines indented:
|
|
665
|
+
question: |
|
|
666
|
+
Which option do you prefer?
|
|
667
|
+
- Option A: fast processing
|
|
668
|
+
- Option B: thorough analysis
|
|
669
|
+
Please choose one.
|
|
670
|
+
|
|
671
|
+
WRONG - inconsistent indentation breaks YAML:
|
|
672
|
+
question: |
|
|
673
|
+
Which option do you prefer?
|
|
674
|
+
- Option A: fast
|
|
675
|
+
Please choose one. <-- ERROR: not indented, breaks out of the block`);
|
|
676
|
+
} else if (parameterFormat === "toml") {
|
|
677
|
+
parts.push(`
|
|
678
|
+
|
|
679
|
+
TOML MULTILINE SYNTAX:
|
|
680
|
+
For string values with multiple lines or special characters, use triple-quotes ("""):
|
|
681
|
+
|
|
682
|
+
filePath = "README.md"
|
|
683
|
+
content = """
|
|
684
|
+
# Project Title
|
|
685
|
+
|
|
686
|
+
This content can contain:
|
|
687
|
+
- Markdown lists
|
|
688
|
+
- Special characters: # : -
|
|
689
|
+
- Multiple paragraphs
|
|
690
|
+
"""`);
|
|
691
|
+
}
|
|
591
692
|
return parts.join("");
|
|
592
693
|
}
|
|
593
694
|
buildRulesSection(context) {
|
|
@@ -631,6 +732,16 @@ ${this.endPrefix}`
|
|
|
631
732
|
return `${key}: ${JSON.stringify(value)}`;
|
|
632
733
|
}).join("\n");
|
|
633
734
|
}
|
|
735
|
+
if (format === "toml") {
|
|
736
|
+
return Object.entries(parameters).map(([key, value]) => {
|
|
737
|
+
if (typeof value === "string" && value.includes("\n")) {
|
|
738
|
+
return `${key} = """
|
|
739
|
+
${value}
|
|
740
|
+
"""`;
|
|
741
|
+
}
|
|
742
|
+
return `${key} = ${JSON.stringify(value)}`;
|
|
743
|
+
}).join("\n");
|
|
744
|
+
}
|
|
634
745
|
return JSON.stringify(parameters);
|
|
635
746
|
}
|
|
636
747
|
build() {
|
|
@@ -663,11 +774,14 @@ var init_conversation_manager = __esm({
|
|
|
663
774
|
initialMessages;
|
|
664
775
|
historyBuilder;
|
|
665
776
|
parameterFormat;
|
|
666
|
-
constructor(baseMessages, initialMessages,
|
|
777
|
+
constructor(baseMessages, initialMessages, options = {}) {
|
|
667
778
|
this.baseMessages = baseMessages;
|
|
668
779
|
this.initialMessages = initialMessages;
|
|
669
|
-
this.parameterFormat = parameterFormat;
|
|
780
|
+
this.parameterFormat = options.parameterFormat ?? "json";
|
|
670
781
|
this.historyBuilder = new LLMMessageBuilder();
|
|
782
|
+
if (options.startPrefix && options.endPrefix) {
|
|
783
|
+
this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix);
|
|
784
|
+
}
|
|
671
785
|
}
|
|
672
786
|
addUserMessage(content) {
|
|
673
787
|
this.historyBuilder.addUser(content);
|
|
@@ -1138,11 +1252,109 @@ var init_executor = __esm({
|
|
|
1138
1252
|
});
|
|
1139
1253
|
|
|
1140
1254
|
// src/gadgets/parser.ts
|
|
1141
|
-
|
|
1255
|
+
function preprocessYaml(yamlStr) {
|
|
1256
|
+
const lines = yamlStr.split("\n");
|
|
1257
|
+
const result = [];
|
|
1258
|
+
let i = 0;
|
|
1259
|
+
while (i < lines.length) {
|
|
1260
|
+
const line = lines[i];
|
|
1261
|
+
const match = line.match(/^(\s*)([\w-]+):\s+(.+)$/);
|
|
1262
|
+
if (match) {
|
|
1263
|
+
const [, indent, key, value] = match;
|
|
1264
|
+
if (value === "|" || value === ">" || value === "|-" || value === ">-") {
|
|
1265
|
+
result.push(line);
|
|
1266
|
+
i++;
|
|
1267
|
+
const keyIndentLen2 = indent.length;
|
|
1268
|
+
const blockLines = [];
|
|
1269
|
+
let minContentIndent = Infinity;
|
|
1270
|
+
while (i < lines.length) {
|
|
1271
|
+
const blockLine = lines[i];
|
|
1272
|
+
const blockIndentMatch = blockLine.match(/^(\s*)/);
|
|
1273
|
+
const blockIndentLen = blockIndentMatch ? blockIndentMatch[1].length : 0;
|
|
1274
|
+
if (blockLine.trim() === "") {
|
|
1275
|
+
blockLines.push({ content: "", originalIndent: 0 });
|
|
1276
|
+
i++;
|
|
1277
|
+
continue;
|
|
1278
|
+
}
|
|
1279
|
+
if (blockIndentLen > keyIndentLen2) {
|
|
1280
|
+
const content = blockLine.substring(blockIndentLen);
|
|
1281
|
+
blockLines.push({ content, originalIndent: blockIndentLen });
|
|
1282
|
+
if (content.trim().length > 0) {
|
|
1283
|
+
minContentIndent = Math.min(minContentIndent, blockIndentLen);
|
|
1284
|
+
}
|
|
1285
|
+
i++;
|
|
1286
|
+
} else {
|
|
1287
|
+
break;
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
const targetIndent = keyIndentLen2 + 2;
|
|
1291
|
+
for (const blockLine of blockLines) {
|
|
1292
|
+
if (blockLine.content === "") {
|
|
1293
|
+
result.push("");
|
|
1294
|
+
} else {
|
|
1295
|
+
result.push(" ".repeat(targetIndent) + blockLine.content);
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
continue;
|
|
1299
|
+
}
|
|
1300
|
+
if (value.startsWith('"') || value.startsWith("'") || value === "true" || value === "false" || /^-?\d+(\.\d+)?$/.test(value)) {
|
|
1301
|
+
result.push(line);
|
|
1302
|
+
i++;
|
|
1303
|
+
continue;
|
|
1304
|
+
}
|
|
1305
|
+
const keyIndentLen = indent.length;
|
|
1306
|
+
const continuationLines = [];
|
|
1307
|
+
let j = i + 1;
|
|
1308
|
+
while (j < lines.length) {
|
|
1309
|
+
const nextLine = lines[j];
|
|
1310
|
+
if (nextLine.trim() === "") {
|
|
1311
|
+
continuationLines.push(nextLine);
|
|
1312
|
+
j++;
|
|
1313
|
+
continue;
|
|
1314
|
+
}
|
|
1315
|
+
const nextIndentMatch = nextLine.match(/^(\s*)/);
|
|
1316
|
+
const nextIndentLen = nextIndentMatch ? nextIndentMatch[1].length : 0;
|
|
1317
|
+
if (nextIndentLen > keyIndentLen) {
|
|
1318
|
+
continuationLines.push(nextLine);
|
|
1319
|
+
j++;
|
|
1320
|
+
} else {
|
|
1321
|
+
break;
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
if (continuationLines.length > 0 && continuationLines.some((l) => l.trim().length > 0)) {
|
|
1325
|
+
result.push(`${indent}${key}: |`);
|
|
1326
|
+
result.push(`${indent} ${value}`);
|
|
1327
|
+
for (const contLine of continuationLines) {
|
|
1328
|
+
if (contLine.trim() === "") {
|
|
1329
|
+
result.push("");
|
|
1330
|
+
} else {
|
|
1331
|
+
const contIndentMatch = contLine.match(/^(\s*)/);
|
|
1332
|
+
const contIndent = contIndentMatch ? contIndentMatch[1] : "";
|
|
1333
|
+
const contContent = contLine.substring(contIndent.length);
|
|
1334
|
+
result.push(`${indent} ${contContent}`);
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
i = j;
|
|
1338
|
+
continue;
|
|
1339
|
+
}
|
|
1340
|
+
if (value.includes(": ") || value.endsWith(":")) {
|
|
1341
|
+
const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
1342
|
+
result.push(`${indent}${key}: "${escaped}"`);
|
|
1343
|
+
i++;
|
|
1344
|
+
continue;
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
result.push(line);
|
|
1348
|
+
i++;
|
|
1349
|
+
}
|
|
1350
|
+
return result.join("\n");
|
|
1351
|
+
}
|
|
1352
|
+
var yaml, import_js_toml, globalInvocationCounter, StreamParser;
|
|
1142
1353
|
var init_parser = __esm({
|
|
1143
1354
|
"src/gadgets/parser.ts"() {
|
|
1144
1355
|
"use strict";
|
|
1145
1356
|
yaml = __toESM(require("js-yaml"), 1);
|
|
1357
|
+
import_js_toml = require("js-toml");
|
|
1146
1358
|
init_constants();
|
|
1147
1359
|
globalInvocationCounter = 0;
|
|
1148
1360
|
StreamParser = class {
|
|
@@ -1164,6 +1376,17 @@ var init_parser = __esm({
|
|
|
1164
1376
|
this.lastReportedTextLength = index;
|
|
1165
1377
|
return segment.trim().length > 0 ? segment : void 0;
|
|
1166
1378
|
}
|
|
1379
|
+
/**
|
|
1380
|
+
* Parse gadget name, handling both old format (name:invocationId) and new format (just name).
|
|
1381
|
+
* For new format, generates a unique invocation ID.
|
|
1382
|
+
*/
|
|
1383
|
+
parseGadgetName(gadgetName) {
|
|
1384
|
+
if (gadgetName.includes(":")) {
|
|
1385
|
+
const parts = gadgetName.split(":");
|
|
1386
|
+
return { actualName: parts[0], invocationId: parts[1] };
|
|
1387
|
+
}
|
|
1388
|
+
return { actualName: gadgetName, invocationId: `gadget_${++globalInvocationCounter}` };
|
|
1389
|
+
}
|
|
1167
1390
|
/**
|
|
1168
1391
|
* Parse parameter string according to configured format
|
|
1169
1392
|
*/
|
|
@@ -1177,20 +1400,31 @@ var init_parser = __esm({
|
|
|
1177
1400
|
}
|
|
1178
1401
|
if (this.parameterFormat === "yaml") {
|
|
1179
1402
|
try {
|
|
1180
|
-
return { parameters: yaml.load(raw) };
|
|
1403
|
+
return { parameters: yaml.load(preprocessYaml(raw)) };
|
|
1181
1404
|
} catch (error) {
|
|
1182
1405
|
return { parseError: error instanceof Error ? error.message : "Failed to parse YAML" };
|
|
1183
1406
|
}
|
|
1184
1407
|
}
|
|
1408
|
+
if (this.parameterFormat === "toml") {
|
|
1409
|
+
try {
|
|
1410
|
+
return { parameters: (0, import_js_toml.load)(raw) };
|
|
1411
|
+
} catch (error) {
|
|
1412
|
+
return { parseError: error instanceof Error ? error.message : "Failed to parse TOML" };
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1185
1415
|
try {
|
|
1186
1416
|
return { parameters: JSON.parse(raw) };
|
|
1187
1417
|
} catch {
|
|
1188
1418
|
try {
|
|
1189
|
-
return { parameters:
|
|
1190
|
-
} catch
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
}
|
|
1419
|
+
return { parameters: (0, import_js_toml.load)(raw) };
|
|
1420
|
+
} catch {
|
|
1421
|
+
try {
|
|
1422
|
+
return { parameters: yaml.load(preprocessYaml(raw)) };
|
|
1423
|
+
} catch (error) {
|
|
1424
|
+
return {
|
|
1425
|
+
parseError: error instanceof Error ? error.message : "Failed to parse as JSON, TOML, or YAML"
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1194
1428
|
}
|
|
1195
1429
|
}
|
|
1196
1430
|
}
|
|
@@ -1209,16 +1443,7 @@ var init_parser = __esm({
|
|
|
1209
1443
|
const metadataEndIndex = this.buffer.indexOf("\n", metadataStartIndex);
|
|
1210
1444
|
if (metadataEndIndex === -1) break;
|
|
1211
1445
|
const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
|
|
1212
|
-
|
|
1213
|
-
let actualGadgetName;
|
|
1214
|
-
if (gadgetName.includes(":")) {
|
|
1215
|
-
const parts = gadgetName.split(":");
|
|
1216
|
-
actualGadgetName = parts[0];
|
|
1217
|
-
invocationId = parts[1];
|
|
1218
|
-
} else {
|
|
1219
|
-
actualGadgetName = gadgetName;
|
|
1220
|
-
invocationId = `gadget_${++globalInvocationCounter}`;
|
|
1221
|
-
}
|
|
1446
|
+
const { actualName: actualGadgetName, invocationId } = this.parseGadgetName(gadgetName);
|
|
1222
1447
|
const contentStartIndex = metadataEndIndex + 1;
|
|
1223
1448
|
let partEndIndex;
|
|
1224
1449
|
let endMarkerLength = 0;
|
|
@@ -1228,23 +1453,29 @@ var init_parser = __esm({
|
|
|
1228
1453
|
if (partEndIndex === -1) break;
|
|
1229
1454
|
endMarkerLength = oldEndMarker.length;
|
|
1230
1455
|
} else {
|
|
1231
|
-
|
|
1456
|
+
const nextStartPos = this.buffer.indexOf(this.startPrefix, contentStartIndex);
|
|
1457
|
+
let validEndPos = -1;
|
|
1458
|
+
let searchPos = contentStartIndex;
|
|
1232
1459
|
while (true) {
|
|
1233
|
-
const endPos = this.buffer.indexOf(this.endPrefix,
|
|
1234
|
-
if (endPos === -1)
|
|
1235
|
-
partEndIndex = -1;
|
|
1236
|
-
break;
|
|
1237
|
-
}
|
|
1460
|
+
const endPos = this.buffer.indexOf(this.endPrefix, searchPos);
|
|
1461
|
+
if (endPos === -1) break;
|
|
1238
1462
|
const afterEnd = this.buffer.substring(endPos + this.endPrefix.length);
|
|
1239
1463
|
if (afterEnd.startsWith("\n") || afterEnd.startsWith("\r") || afterEnd.startsWith(this.startPrefix) || afterEnd.length === 0) {
|
|
1240
|
-
|
|
1241
|
-
endMarkerLength = this.endPrefix.length;
|
|
1464
|
+
validEndPos = endPos;
|
|
1242
1465
|
break;
|
|
1243
1466
|
} else {
|
|
1244
|
-
|
|
1467
|
+
searchPos = endPos + this.endPrefix.length;
|
|
1245
1468
|
}
|
|
1246
1469
|
}
|
|
1247
|
-
if (
|
|
1470
|
+
if (nextStartPos !== -1 && (validEndPos === -1 || nextStartPos < validEndPos)) {
|
|
1471
|
+
partEndIndex = nextStartPos;
|
|
1472
|
+
endMarkerLength = 0;
|
|
1473
|
+
} else if (validEndPos !== -1) {
|
|
1474
|
+
partEndIndex = validEndPos;
|
|
1475
|
+
endMarkerLength = this.endPrefix.length;
|
|
1476
|
+
} else {
|
|
1477
|
+
break;
|
|
1478
|
+
}
|
|
1248
1479
|
}
|
|
1249
1480
|
const parametersRaw = this.buffer.substring(contentStartIndex, partEndIndex).trim();
|
|
1250
1481
|
const { parameters, parseError } = this.parseParameters(parametersRaw);
|
|
@@ -1267,8 +1498,35 @@ var init_parser = __esm({
|
|
|
1267
1498
|
this.lastReportedTextLength = 0;
|
|
1268
1499
|
}
|
|
1269
1500
|
}
|
|
1270
|
-
// Finalize parsing and return remaining text
|
|
1501
|
+
// Finalize parsing and return remaining text or incomplete gadgets
|
|
1271
1502
|
*finalize() {
|
|
1503
|
+
const startIndex = this.buffer.indexOf(this.startPrefix, this.lastReportedTextLength);
|
|
1504
|
+
if (startIndex !== -1) {
|
|
1505
|
+
const textBefore = this.takeTextUntil(startIndex);
|
|
1506
|
+
if (textBefore !== void 0) {
|
|
1507
|
+
yield { type: "text", content: textBefore };
|
|
1508
|
+
}
|
|
1509
|
+
const metadataStartIndex = startIndex + this.startPrefix.length;
|
|
1510
|
+
const metadataEndIndex = this.buffer.indexOf("\n", metadataStartIndex);
|
|
1511
|
+
if (metadataEndIndex !== -1) {
|
|
1512
|
+
const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
|
|
1513
|
+
const { actualName: actualGadgetName, invocationId } = this.parseGadgetName(gadgetName);
|
|
1514
|
+
const contentStartIndex = metadataEndIndex + 1;
|
|
1515
|
+
const parametersRaw = this.buffer.substring(contentStartIndex).trim();
|
|
1516
|
+
const { parameters, parseError } = this.parseParameters(parametersRaw);
|
|
1517
|
+
yield {
|
|
1518
|
+
type: "gadget_call",
|
|
1519
|
+
call: {
|
|
1520
|
+
gadgetName: actualGadgetName,
|
|
1521
|
+
invocationId,
|
|
1522
|
+
parametersYaml: parametersRaw,
|
|
1523
|
+
parameters,
|
|
1524
|
+
parseError
|
|
1525
|
+
}
|
|
1526
|
+
};
|
|
1527
|
+
return;
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1272
1530
|
const remainingText = this.takeTextUntil(this.buffer.length);
|
|
1273
1531
|
if (remainingText !== void 0) {
|
|
1274
1532
|
yield { type: "text", content: remainingText };
|
|
@@ -1749,11 +2007,11 @@ var init_agent = __esm({
|
|
|
1749
2007
|
role: message.role,
|
|
1750
2008
|
content: message.content
|
|
1751
2009
|
}));
|
|
1752
|
-
this.conversation = new ConversationManager(
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
);
|
|
2010
|
+
this.conversation = new ConversationManager(baseMessages, initialMessages, {
|
|
2011
|
+
parameterFormat: this.parameterFormat,
|
|
2012
|
+
startPrefix: options.gadgetStartPrefix,
|
|
2013
|
+
endPrefix: options.gadgetEndPrefix
|
|
2014
|
+
});
|
|
1757
2015
|
this.userPromptProvided = !!options.userPrompt;
|
|
1758
2016
|
if (options.userPrompt) {
|
|
1759
2017
|
this.conversation.addUserMessage(options.userPrompt);
|
|
@@ -3256,10 +3514,11 @@ var init_gemini = __esm({
|
|
|
3256
3514
|
return GEMINI_MODELS;
|
|
3257
3515
|
}
|
|
3258
3516
|
buildRequestPayload(options, descriptor, _spec, messages) {
|
|
3259
|
-
const
|
|
3517
|
+
const contents = this.convertMessagesToContents(messages);
|
|
3260
3518
|
const generationConfig = this.buildGenerationConfig(options);
|
|
3261
3519
|
const config = {
|
|
3262
|
-
|
|
3520
|
+
// Note: systemInstruction removed - it doesn't work with countTokens()
|
|
3521
|
+
// System messages are now included in contents as user+model exchanges
|
|
3263
3522
|
...generationConfig ? { ...generationConfig } : {},
|
|
3264
3523
|
// Explicitly disable function calling to prevent UNEXPECTED_TOOL_CALL errors
|
|
3265
3524
|
toolConfig: {
|
|
@@ -3280,31 +3539,37 @@ var init_gemini = __esm({
|
|
|
3280
3539
|
const streamResponse = await client.models.generateContentStream(payload);
|
|
3281
3540
|
return streamResponse;
|
|
3282
3541
|
}
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3542
|
+
/**
|
|
3543
|
+
* Convert LLM messages to Gemini contents format.
|
|
3544
|
+
*
|
|
3545
|
+
* For Gemini, we convert system messages to user+model exchanges instead of
|
|
3546
|
+
* using systemInstruction, because:
|
|
3547
|
+
* 1. systemInstruction doesn't work with countTokens() API
|
|
3548
|
+
* 2. This approach gives perfect token counting accuracy (0% error)
|
|
3549
|
+
* 3. The model receives and follows system instructions identically
|
|
3550
|
+
*
|
|
3551
|
+
* System message: "You are a helpful assistant"
|
|
3552
|
+
* Becomes:
|
|
3553
|
+
* - User: "You are a helpful assistant"
|
|
3554
|
+
* - Model: "Understood."
|
|
3555
|
+
*/
|
|
3556
|
+
convertMessagesToContents(messages) {
|
|
3557
|
+
const expandedMessages = [];
|
|
3558
|
+
for (const message of messages) {
|
|
3559
|
+
if (message.role === "system") {
|
|
3560
|
+
expandedMessages.push({
|
|
3561
|
+
role: "user",
|
|
3562
|
+
content: message.content
|
|
3563
|
+
});
|
|
3564
|
+
expandedMessages.push({
|
|
3565
|
+
role: "assistant",
|
|
3566
|
+
content: "Understood."
|
|
3567
|
+
});
|
|
3568
|
+
} else {
|
|
3569
|
+
expandedMessages.push(message);
|
|
3570
|
+
}
|
|
3290
3571
|
}
|
|
3291
|
-
|
|
3292
|
-
while (systemBlockEnd < messages.length && messages[systemBlockEnd].role === "system") {
|
|
3293
|
-
systemBlockEnd++;
|
|
3294
|
-
}
|
|
3295
|
-
const systemMessages = messages.slice(firstSystemIndex, systemBlockEnd);
|
|
3296
|
-
const nonSystemMessages = [
|
|
3297
|
-
...messages.slice(0, firstSystemIndex),
|
|
3298
|
-
...messages.slice(systemBlockEnd)
|
|
3299
|
-
];
|
|
3300
|
-
const systemInstruction = {
|
|
3301
|
-
role: "system",
|
|
3302
|
-
parts: systemMessages.map((message) => ({ text: message.content }))
|
|
3303
|
-
};
|
|
3304
|
-
return {
|
|
3305
|
-
systemInstruction,
|
|
3306
|
-
contents: this.mergeConsecutiveMessages(nonSystemMessages)
|
|
3307
|
-
};
|
|
3572
|
+
return this.mergeConsecutiveMessages(expandedMessages);
|
|
3308
3573
|
}
|
|
3309
3574
|
mergeConsecutiveMessages(messages) {
|
|
3310
3575
|
if (messages.length === 0) {
|
|
@@ -3393,8 +3658,8 @@ var init_gemini = __esm({
|
|
|
3393
3658
|
*
|
|
3394
3659
|
* This method provides accurate token estimation for Gemini models by:
|
|
3395
3660
|
* - Using the SDK's countTokens() method
|
|
3396
|
-
* -
|
|
3397
|
-
* -
|
|
3661
|
+
* - Converting system messages to user+model exchanges (same as in generation)
|
|
3662
|
+
* - This gives perfect token counting accuracy (0% error vs actual usage)
|
|
3398
3663
|
*
|
|
3399
3664
|
* @param messages - The messages to count tokens for
|
|
3400
3665
|
* @param descriptor - Model descriptor containing the model name
|
|
@@ -3413,16 +3678,14 @@ var init_gemini = __esm({
|
|
|
3413
3678
|
*/
|
|
3414
3679
|
async countTokens(messages, descriptor, _spec) {
|
|
3415
3680
|
const client = this.client;
|
|
3416
|
-
const
|
|
3417
|
-
const request = {
|
|
3418
|
-
model: descriptor.name,
|
|
3419
|
-
contents: this.convertContentsForNewSDK(contents)
|
|
3420
|
-
};
|
|
3421
|
-
if (systemInstruction) {
|
|
3422
|
-
request.systemInstruction = systemInstruction.parts.map((p) => p.text).join("\n");
|
|
3423
|
-
}
|
|
3681
|
+
const contents = this.convertMessagesToContents(messages);
|
|
3424
3682
|
try {
|
|
3425
|
-
const response = await client.models.countTokens(
|
|
3683
|
+
const response = await client.models.countTokens({
|
|
3684
|
+
model: descriptor.name,
|
|
3685
|
+
contents: this.convertContentsForNewSDK(contents)
|
|
3686
|
+
// Note: systemInstruction not used - it's not supported by countTokens()
|
|
3687
|
+
// and would cause a 2100% token counting error
|
|
3688
|
+
});
|
|
3426
3689
|
return response.totalTokens ?? 0;
|
|
3427
3690
|
} catch (error) {
|
|
3428
3691
|
console.warn(
|
|
@@ -5085,6 +5348,83 @@ function mergeDescriptions(schema, jsonSchema) {
|
|
|
5085
5348
|
|
|
5086
5349
|
// src/gadgets/gadget.ts
|
|
5087
5350
|
init_schema_validator();
|
|
5351
|
+
function formatYamlValue(value, indent = "") {
|
|
5352
|
+
if (typeof value === "string") {
|
|
5353
|
+
const lines = value.split("\n");
|
|
5354
|
+
if (lines.length === 1 && !value.includes(":") && !value.startsWith("-")) {
|
|
5355
|
+
return value;
|
|
5356
|
+
}
|
|
5357
|
+
const indentedLines = lines.map((line) => `${indent} ${line}`).join("\n");
|
|
5358
|
+
return `|
|
|
5359
|
+
${indentedLines}`;
|
|
5360
|
+
}
|
|
5361
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
5362
|
+
return String(value);
|
|
5363
|
+
}
|
|
5364
|
+
if (value === null || value === void 0) {
|
|
5365
|
+
return "null";
|
|
5366
|
+
}
|
|
5367
|
+
if (Array.isArray(value)) {
|
|
5368
|
+
if (value.length === 0) return "[]";
|
|
5369
|
+
const items = value.map((item) => `${indent}- ${formatYamlValue(item, indent + " ")}`);
|
|
5370
|
+
return "\n" + items.join("\n");
|
|
5371
|
+
}
|
|
5372
|
+
if (typeof value === "object") {
|
|
5373
|
+
const entries = Object.entries(value);
|
|
5374
|
+
if (entries.length === 0) return "{}";
|
|
5375
|
+
const lines = entries.map(([k, v]) => {
|
|
5376
|
+
const formattedValue = formatYamlValue(v, indent + " ");
|
|
5377
|
+
if (formattedValue.startsWith("\n") || formattedValue.startsWith("|")) {
|
|
5378
|
+
return `${indent}${k}: ${formattedValue}`;
|
|
5379
|
+
}
|
|
5380
|
+
return `${indent}${k}: ${formattedValue}`;
|
|
5381
|
+
});
|
|
5382
|
+
return "\n" + lines.join("\n");
|
|
5383
|
+
}
|
|
5384
|
+
return yaml2.dump(value).trimEnd();
|
|
5385
|
+
}
|
|
5386
|
+
function formatParamsAsYaml(params) {
|
|
5387
|
+
const lines = [];
|
|
5388
|
+
for (const [key, value] of Object.entries(params)) {
|
|
5389
|
+
const formattedValue = formatYamlValue(value, "");
|
|
5390
|
+
if (formattedValue.startsWith("\n")) {
|
|
5391
|
+
lines.push(`${key}:${formattedValue}`);
|
|
5392
|
+
} else {
|
|
5393
|
+
lines.push(`${key}: ${formattedValue}`);
|
|
5394
|
+
}
|
|
5395
|
+
}
|
|
5396
|
+
return lines.join("\n");
|
|
5397
|
+
}
|
|
5398
|
+
function formatTomlValue(value) {
|
|
5399
|
+
if (typeof value === "string") {
|
|
5400
|
+
if (value.includes("\n")) {
|
|
5401
|
+
return `"""
|
|
5402
|
+
${value}
|
|
5403
|
+
"""`;
|
|
5404
|
+
}
|
|
5405
|
+
return JSON.stringify(value);
|
|
5406
|
+
}
|
|
5407
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
5408
|
+
return String(value);
|
|
5409
|
+
}
|
|
5410
|
+
if (value === null || value === void 0) {
|
|
5411
|
+
return '""';
|
|
5412
|
+
}
|
|
5413
|
+
if (Array.isArray(value)) {
|
|
5414
|
+
return JSON.stringify(value);
|
|
5415
|
+
}
|
|
5416
|
+
if (typeof value === "object") {
|
|
5417
|
+
return JSON.stringify(value);
|
|
5418
|
+
}
|
|
5419
|
+
return JSON.stringify(value);
|
|
5420
|
+
}
|
|
5421
|
+
function formatParamsAsToml(params) {
|
|
5422
|
+
const lines = [];
|
|
5423
|
+
for (const [key, value] of Object.entries(params)) {
|
|
5424
|
+
lines.push(`${key} = ${formatTomlValue(value)}`);
|
|
5425
|
+
}
|
|
5426
|
+
return lines.join("\n");
|
|
5427
|
+
}
|
|
5088
5428
|
var BaseGadget = class {
|
|
5089
5429
|
/**
|
|
5090
5430
|
* The name of the gadget. Used for identification when LLM calls it.
|
|
@@ -5104,6 +5444,14 @@ var BaseGadget = class {
|
|
|
5104
5444
|
* Set to 0 or undefined to disable timeout for this gadget.
|
|
5105
5445
|
*/
|
|
5106
5446
|
timeoutMs;
|
|
5447
|
+
/**
|
|
5448
|
+
* Optional usage examples to help LLMs understand proper invocation.
|
|
5449
|
+
* Examples are rendered in getInstruction() alongside the schema.
|
|
5450
|
+
*
|
|
5451
|
+
* Note: Uses broader `unknown` type to allow typed examples from subclasses
|
|
5452
|
+
* while maintaining runtime compatibility.
|
|
5453
|
+
*/
|
|
5454
|
+
examples;
|
|
5107
5455
|
/**
|
|
5108
5456
|
* Auto-generated instruction text for the LLM.
|
|
5109
5457
|
* Combines name, description, and parameter schema into a formatted instruction.
|
|
@@ -5116,7 +5464,7 @@ var BaseGadget = class {
|
|
|
5116
5464
|
* Generate instruction text for the LLM with format-specific schema.
|
|
5117
5465
|
* Combines name, description, and parameter schema into a formatted instruction.
|
|
5118
5466
|
*
|
|
5119
|
-
* @param format - Format for the schema representation ('json' | 'yaml' | 'auto')
|
|
5467
|
+
* @param format - Format for the schema representation ('json' | 'yaml' | 'toml' | 'auto')
|
|
5120
5468
|
* @returns Formatted instruction string
|
|
5121
5469
|
*/
|
|
5122
5470
|
getInstruction(format = "json") {
|
|
@@ -5131,12 +5479,38 @@ var BaseGadget = class {
|
|
|
5131
5479
|
if (format === "json" || format === "auto") {
|
|
5132
5480
|
parts.push("\n\nInput Schema (JSON):");
|
|
5133
5481
|
parts.push(JSON.stringify(jsonSchema, null, 2));
|
|
5482
|
+
} else if (format === "toml") {
|
|
5483
|
+
parts.push("\n\nInput Schema (TOML):");
|
|
5484
|
+
parts.push(JSON.stringify(jsonSchema, null, 2));
|
|
5134
5485
|
} else {
|
|
5135
5486
|
const yamlSchema = yaml2.dump(jsonSchema).trimEnd();
|
|
5136
5487
|
parts.push("\n\nInput Schema (YAML):");
|
|
5137
5488
|
parts.push(yamlSchema);
|
|
5138
5489
|
}
|
|
5139
5490
|
}
|
|
5491
|
+
if (this.examples && this.examples.length > 0) {
|
|
5492
|
+
parts.push("\n\nExamples:");
|
|
5493
|
+
this.examples.forEach((example, index) => {
|
|
5494
|
+
if (index > 0) {
|
|
5495
|
+
parts.push("");
|
|
5496
|
+
}
|
|
5497
|
+
if (example.comment) {
|
|
5498
|
+
parts.push(`# ${example.comment}`);
|
|
5499
|
+
}
|
|
5500
|
+
parts.push("Input:");
|
|
5501
|
+
if (format === "json" || format === "auto") {
|
|
5502
|
+
parts.push(JSON.stringify(example.params, null, 2));
|
|
5503
|
+
} else if (format === "toml") {
|
|
5504
|
+
parts.push(formatParamsAsToml(example.params));
|
|
5505
|
+
} else {
|
|
5506
|
+
parts.push(formatParamsAsYaml(example.params));
|
|
5507
|
+
}
|
|
5508
|
+
if (example.output !== void 0) {
|
|
5509
|
+
parts.push("Output:");
|
|
5510
|
+
parts.push(example.output);
|
|
5511
|
+
}
|
|
5512
|
+
});
|
|
5513
|
+
}
|
|
5140
5514
|
return parts.join("\n");
|
|
5141
5515
|
}
|
|
5142
5516
|
};
|