llmist 0.8.0 → 1.1.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/dist/index.cjs CHANGED
@@ -31,12 +31,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
33
  // src/core/constants.ts
34
- var GADGET_START_PREFIX, GADGET_END_PREFIX, DEFAULT_GADGET_OUTPUT_LIMIT, DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT, CHARS_PER_TOKEN, FALLBACK_CONTEXT_WINDOW;
34
+ 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;
35
35
  var init_constants = __esm({
36
36
  "src/core/constants.ts"() {
37
37
  "use strict";
38
38
  GADGET_START_PREFIX = "!!!GADGET_START:";
39
39
  GADGET_END_PREFIX = "!!!GADGET_END";
40
+ GADGET_ARG_PREFIX = "!!!ARG:";
40
41
  DEFAULT_GADGET_OUTPUT_LIMIT = true;
41
42
  DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;
42
43
  CHARS_PER_TOKEN = 4;
@@ -386,17 +387,12 @@ var init_prompt_config = __esm({
386
387
  "EACH MARKER MUST START WITH A NEWLINE."
387
388
  ].join("\n"),
388
389
  criticalUsage: "INVOKE gadgets using the markers - do not describe what you want to do.",
389
- formatDescriptionYaml: "Parameters in YAML format (one per line)",
390
- formatDescriptionJson: "Parameters in JSON format (valid JSON object)",
391
- formatDescriptionToml: "Parameters in TOML format (key = value pairs, use heredoc for multiline: key = <<<EOF ... EOF)",
390
+ formatDescription: (ctx) => `Parameters using ${ctx.argPrefix}name markers (value on next line(s), no escaping needed)`,
392
391
  rules: () => [
393
392
  "Output ONLY plain text with the exact markers - never use function/tool calling",
394
393
  "You can invoke multiple gadgets in a single response",
395
394
  "For dependent gadgets, invoke the first one and wait for the result"
396
395
  ],
397
- schemaLabelJson: "\n\nInput Schema (JSON):",
398
- schemaLabelYaml: "\n\nInput Schema (YAML):",
399
- schemaLabelToml: "\n\nInput Schema (TOML):",
400
396
  customExamples: null
401
397
  };
402
398
  }
@@ -413,6 +409,7 @@ var init_messages = __esm({
413
409
  messages = [];
414
410
  startPrefix = GADGET_START_PREFIX;
415
411
  endPrefix = GADGET_END_PREFIX;
412
+ argPrefix = GADGET_ARG_PREFIX;
416
413
  promptConfig;
417
414
  constructor(promptConfig) {
418
415
  this.promptConfig = promptConfig ?? {};
@@ -421,26 +418,32 @@ var init_messages = __esm({
421
418
  * Set custom prefixes for gadget markers.
422
419
  * Used to configure history builder to match system prompt markers.
423
420
  */
424
- withPrefixes(startPrefix, endPrefix) {
421
+ withPrefixes(startPrefix, endPrefix, argPrefix) {
425
422
  this.startPrefix = startPrefix;
426
423
  this.endPrefix = endPrefix;
424
+ if (argPrefix) {
425
+ this.argPrefix = argPrefix;
426
+ }
427
427
  return this;
428
428
  }
429
429
  addSystem(content, metadata) {
430
430
  this.messages.push({ role: "system", content, metadata });
431
431
  return this;
432
432
  }
433
- addGadgets(gadgets, parameterFormat = "json", options) {
433
+ addGadgets(gadgets, options) {
434
434
  if (options?.startPrefix) {
435
435
  this.startPrefix = options.startPrefix;
436
436
  }
437
437
  if (options?.endPrefix) {
438
438
  this.endPrefix = options.endPrefix;
439
439
  }
440
+ if (options?.argPrefix) {
441
+ this.argPrefix = options.argPrefix;
442
+ }
440
443
  const context = {
441
- parameterFormat,
442
444
  startPrefix: this.startPrefix,
443
445
  endPrefix: this.endPrefix,
446
+ argPrefix: this.argPrefix,
444
447
  gadgetCount: gadgets.length,
445
448
  gadgetNames: gadgets.map((g) => g.name ?? g.constructor.name)
446
449
  };
@@ -451,26 +454,19 @@ var init_messages = __esm({
451
454
  context
452
455
  );
453
456
  parts.push(mainInstruction);
454
- parts.push(this.buildGadgetsSection(gadgets, parameterFormat));
455
- parts.push(this.buildUsageSection(parameterFormat, context));
457
+ parts.push(this.buildGadgetsSection(gadgets));
458
+ parts.push(this.buildUsageSection(context));
456
459
  this.messages.push({ role: "system", content: parts.join("") });
457
460
  return this;
458
461
  }
459
- buildGadgetsSection(gadgets, parameterFormat) {
462
+ buildGadgetsSection(gadgets) {
460
463
  const parts = [];
461
464
  parts.push("\n\nAVAILABLE GADGETS");
462
465
  parts.push("\n=================\n");
463
466
  for (const gadget of gadgets) {
464
467
  const gadgetName = gadget.name ?? gadget.constructor.name;
465
- const instruction = gadget.getInstruction(parameterFormat);
466
- const schemaMarkers = {
467
- yaml: "\n\nInput Schema (YAML):",
468
- json: "\n\nInput Schema (JSON):",
469
- toml: "\n\nInput Schema (TOML):",
470
- auto: "\n\nInput Schema (JSON):"
471
- // auto defaults to JSON schema display
472
- };
473
- const schemaMarker = schemaMarkers[parameterFormat];
468
+ const instruction = gadget.getInstruction(this.argPrefix);
469
+ const schemaMarker = "\n\nInput Schema (BLOCK):";
474
470
  const schemaIndex = instruction.indexOf(schemaMarker);
475
471
  const description = (schemaIndex !== -1 ? instruction.substring(0, schemaIndex) : instruction).trim();
476
472
  const schema = schemaIndex !== -1 ? instruction.substring(schemaIndex + schemaMarker.length).trim() : "";
@@ -481,35 +477,20 @@ ${description}`);
481
477
  if (schema) {
482
478
  parts.push(`
483
479
 
484
- PARAMETERS (${parameterFormat.toUpperCase()}):
480
+ PARAMETERS (BLOCK):
485
481
  ${schema}`);
486
482
  }
487
483
  parts.push("\n\n---");
488
484
  }
489
485
  return parts.join("");
490
486
  }
491
- buildUsageSection(parameterFormat, context) {
487
+ buildUsageSection(context) {
492
488
  const parts = [];
493
- const formatDescriptionMap = {
494
- yaml: {
495
- config: this.promptConfig.formatDescriptionYaml,
496
- defaultValue: DEFAULT_PROMPTS.formatDescriptionYaml
497
- },
498
- json: {
499
- config: this.promptConfig.formatDescriptionJson,
500
- defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
501
- },
502
- toml: {
503
- config: this.promptConfig.formatDescriptionToml,
504
- defaultValue: DEFAULT_PROMPTS.formatDescriptionToml
505
- },
506
- auto: {
507
- config: this.promptConfig.formatDescriptionJson,
508
- defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
509
- }
510
- };
511
- const { config, defaultValue } = formatDescriptionMap[parameterFormat];
512
- const formatDescription = resolvePromptTemplate(config, defaultValue, context);
489
+ const formatDescription = resolvePromptTemplate(
490
+ this.promptConfig.formatDescription,
491
+ DEFAULT_PROMPTS.formatDescription,
492
+ context
493
+ );
513
494
  parts.push("\n\nHOW TO INVOKE GADGETS");
514
495
  parts.push("\n=====================\n");
515
496
  const criticalUsage = resolvePromptTemplate(
@@ -527,124 +508,90 @@ CRITICAL: ${criticalUsage}
527
508
  2. ${formatDescription}`);
528
509
  parts.push(`
529
510
  3. End marker: ${this.endPrefix}`);
530
- parts.push(this.buildExamplesSection(parameterFormat, context));
511
+ parts.push(this.buildExamplesSection(context));
531
512
  parts.push(this.buildRulesSection(context));
532
513
  parts.push("\n");
533
514
  return parts.join("");
534
515
  }
535
- buildExamplesSection(parameterFormat, context) {
516
+ buildExamplesSection(context) {
536
517
  if (this.promptConfig.customExamples) {
537
518
  return this.promptConfig.customExamples(context);
538
519
  }
539
520
  const parts = [];
540
- const singleExamples = {
541
- yaml: `${this.startPrefix}translate
542
- from: English
543
- to: Polish
544
- content: "Paris is the capital of France: a beautiful city."
545
- ${this.endPrefix}`,
546
- json: `${this.startPrefix}translate
547
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
548
- ${this.endPrefix}`,
549
- toml: `${this.startPrefix}translate
550
- from = "English"
551
- to = "Polish"
552
- content = "Paris is the capital of France: a beautiful city."
553
- ${this.endPrefix}`,
554
- auto: `${this.startPrefix}translate
555
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
556
- ${this.endPrefix}`
557
- };
521
+ const singleExample = `${this.startPrefix}translate
522
+ ${this.argPrefix}from
523
+ English
524
+ ${this.argPrefix}to
525
+ Polish
526
+ ${this.argPrefix}content
527
+ Paris is the capital of France: a beautiful city.
528
+ ${this.endPrefix}`;
558
529
  parts.push(`
559
530
 
560
531
  EXAMPLE (Single Gadget):
561
532
 
562
- ${singleExamples[parameterFormat]}`);
563
- const multipleExamples = {
564
- yaml: `${this.startPrefix}translate
565
- from: English
566
- to: Polish
567
- content: "Paris is the capital of France: a beautiful city."
533
+ ${singleExample}`);
534
+ const multipleExample = `${this.startPrefix}translate
535
+ ${this.argPrefix}from
536
+ English
537
+ ${this.argPrefix}to
538
+ Polish
539
+ ${this.argPrefix}content
540
+ Paris is the capital of France: a beautiful city.
568
541
  ${this.endPrefix}
569
542
  ${this.startPrefix}analyze
570
- type: economic_analysis
571
- matter: "Polish Economy"
572
- question: <<<EOF
543
+ ${this.argPrefix}type
544
+ economic_analysis
545
+ ${this.argPrefix}matter
546
+ Polish Economy
547
+ ${this.argPrefix}question
573
548
  Analyze the following:
574
549
  - Polish arms exports 2025
575
550
  - Economic implications
576
- EOF
577
- ${this.endPrefix}`,
578
- json: `${this.startPrefix}translate
579
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
580
- ${this.endPrefix}
581
- ${this.startPrefix}analyze
582
- {"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
583
- ${this.endPrefix}`,
584
- toml: `${this.startPrefix}translate
585
- from = "English"
586
- to = "Polish"
587
- content = "Paris is the capital of France: a beautiful city."
588
- ${this.endPrefix}
589
- ${this.startPrefix}analyze
590
- type = "economic_analysis"
591
- matter = "Polish Economy"
592
- question = <<<EOF
593
- Analyze the following:
594
- - Polish arms exports 2025
595
- - Economic implications
596
- EOF
597
- ${this.endPrefix}`,
598
- auto: `${this.startPrefix}translate
599
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
600
- ${this.endPrefix}
601
- ${this.startPrefix}analyze
602
- {"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
603
- ${this.endPrefix}`
604
- };
551
+ ${this.endPrefix}`;
605
552
  parts.push(`
606
553
 
607
554
  EXAMPLE (Multiple Gadgets):
608
555
 
609
- ${multipleExamples[parameterFormat]}`);
610
- if (parameterFormat === "yaml") {
611
- parts.push(`
612
-
613
- YAML HEREDOC SYNTAX:
614
- For string values with multiple lines, use heredoc syntax (<<<DELIMITER...DELIMITER):
556
+ ${multipleExample}`);
557
+ parts.push(`
615
558
 
616
- filePath: "README.md"
617
- content: <<<EOF
618
- # Project Title
559
+ BLOCK FORMAT SYNTAX:
560
+ Block format uses ${this.argPrefix}name markers. Values are captured verbatim until the next marker.
619
561
 
620
- This content can contain:
621
- - Markdown lists
622
- - Special characters: # : -
623
- - Multiple paragraphs
624
- EOF
562
+ ${this.argPrefix}filename
563
+ calculator.ts
564
+ ${this.argPrefix}code
565
+ class Calculator {
566
+ private history: string[] = [];
625
567
 
626
- The delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.
627
- No indentation is required for the content.`);
628
- } else if (parameterFormat === "toml") {
629
- parts.push(`
630
-
631
- TOML HEREDOC SYNTAX:
632
- For string values with multiple lines, use heredoc syntax (<<<DELIMITER...DELIMITER):
568
+ add(a: number, b: number): number {
569
+ const result = a + b;
570
+ this.history.push(\`\${a} + \${b} = \${result}\`);
571
+ return result;
572
+ }
573
+ }
633
574
 
634
- filePath = "README.md"
635
- content = <<<EOF
636
- # Project Title
575
+ BLOCK FORMAT RULES:
576
+ - Each parameter starts with ${this.argPrefix}parameterName on its own line
577
+ - The value starts on the NEXT line after the marker
578
+ - Value ends when the next ${this.argPrefix} or ${this.endPrefix} appears
579
+ - NO escaping needed - write values exactly as they should appear
580
+ - Perfect for code, JSON, markdown, or any content with special characters
637
581
 
638
- This content can contain:
639
- - Markdown lists
640
- - Special characters: # : -
641
- - Multiple paragraphs
642
- EOF
582
+ NESTED OBJECTS (use / separator):
583
+ ${this.argPrefix}config/timeout
584
+ 30
585
+ ${this.argPrefix}config/retries
586
+ 3
587
+ Produces: { "config": { "timeout": "30", "retries": "3" } }
643
588
 
644
- The delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.
645
- IMPORTANT: Content inside heredoc is LITERAL - do NOT escape backticks, dollar signs, or any characters.
646
- NEVER use TOML triple-quote strings ("""). ALWAYS use heredoc syntax (<<<EOF...EOF) for multiline content.`);
647
- }
589
+ ARRAYS (use numeric indices):
590
+ ${this.argPrefix}items/0
591
+ first
592
+ ${this.argPrefix}items/1
593
+ second
594
+ Produces: { "items": ["first", "second"] }`);
648
595
  return parts.join("");
649
596
  }
650
597
  buildRulesSection(context) {
@@ -665,8 +612,8 @@ NEVER use TOML triple-quote strings ("""). ALWAYS use heredoc syntax (<<<EOF...E
665
612
  this.messages.push({ role: "assistant", content, metadata });
666
613
  return this;
667
614
  }
668
- addGadgetCall(gadget, parameters, result, parameterFormat = "json") {
669
- const paramStr = this.formatParameters(parameters, parameterFormat);
615
+ addGadgetCall(gadget, parameters, result) {
616
+ const paramStr = this.formatBlockParameters(parameters, "");
670
617
  this.messages.push({
671
618
  role: "assistant",
672
619
  content: `${this.startPrefix}${gadget}
@@ -679,26 +626,32 @@ ${this.endPrefix}`
679
626
  });
680
627
  return this;
681
628
  }
682
- formatParameters(parameters, format) {
683
- if (format === "yaml") {
684
- return Object.entries(parameters).map(([key, value]) => {
685
- if (typeof value === "string") {
686
- return `${key}: ${value}`;
687
- }
688
- return `${key}: ${JSON.stringify(value)}`;
689
- }).join("\n");
690
- }
691
- if (format === "toml") {
692
- return Object.entries(parameters).map(([key, value]) => {
693
- if (typeof value === "string" && value.includes("\n")) {
694
- return `${key} = <<<EOF
695
- ${value}
696
- EOF`;
697
- }
698
- return `${key} = ${JSON.stringify(value)}`;
699
- }).join("\n");
629
+ /**
630
+ * Format parameters as Block format with JSON Pointer paths.
631
+ * Uses the configured argPrefix for consistency with system prompt.
632
+ */
633
+ formatBlockParameters(params, prefix) {
634
+ const lines = [];
635
+ for (const [key, value] of Object.entries(params)) {
636
+ const fullPath = prefix ? `${prefix}/${key}` : key;
637
+ if (Array.isArray(value)) {
638
+ value.forEach((item, index) => {
639
+ const itemPath = `${fullPath}/${index}`;
640
+ if (typeof item === "object" && item !== null) {
641
+ lines.push(this.formatBlockParameters(item, itemPath));
642
+ } else {
643
+ lines.push(`${this.argPrefix}${itemPath}`);
644
+ lines.push(String(item));
645
+ }
646
+ });
647
+ } else if (typeof value === "object" && value !== null) {
648
+ lines.push(this.formatBlockParameters(value, fullPath));
649
+ } else {
650
+ lines.push(`${this.argPrefix}${fullPath}`);
651
+ lines.push(String(value));
652
+ }
700
653
  }
701
- return JSON.stringify(parameters);
654
+ return lines.join("\n");
702
655
  }
703
656
  build() {
704
657
  return [...this.messages];
@@ -870,134 +823,72 @@ var init_schema_to_json = __esm({
870
823
  });
871
824
 
872
825
  // src/gadgets/gadget.ts
873
- function findSafeDelimiter(content) {
874
- const lines = content.split("\n");
875
- for (const delimiter of HEREDOC_DELIMITERS) {
876
- const regex = new RegExp(`^${delimiter}\\s*$`);
877
- const isUsed = lines.some((line) => regex.test(line));
878
- if (!isUsed) {
879
- return delimiter;
880
- }
881
- }
882
- let counter = 1;
883
- while (counter < 1e3) {
884
- const delimiter = `__GADGET_PARAM_${counter}__`;
885
- const regex = new RegExp(`^${delimiter}\\s*$`);
886
- const isUsed = lines.some((line) => regex.test(line));
887
- if (!isUsed) {
888
- return delimiter;
889
- }
890
- counter++;
891
- }
892
- return "HEREDOC_FALLBACK";
893
- }
894
- function formatYamlValue(value, indent = "") {
895
- if (typeof value === "string") {
896
- const lines = value.split("\n");
897
- if (lines.length === 1 && !value.includes(":") && !value.startsWith("-")) {
898
- return value;
899
- }
900
- const delimiter = findSafeDelimiter(value);
901
- return `<<<${delimiter}
902
- ${value}
903
- ${delimiter}`;
904
- }
905
- if (typeof value === "number" || typeof value === "boolean") {
906
- return String(value);
907
- }
908
- if (value === null || value === void 0) {
909
- return "null";
910
- }
911
- if (Array.isArray(value)) {
912
- if (value.length === 0) return "[]";
913
- const items = value.map((item) => `${indent}- ${formatYamlValue(item, indent + " ")}`);
914
- return "\n" + items.join("\n");
915
- }
916
- if (typeof value === "object") {
917
- const entries = Object.entries(value);
918
- if (entries.length === 0) return "{}";
919
- const lines = entries.map(([k, v]) => {
920
- const formattedValue = formatYamlValue(v, indent + " ");
921
- if (formattedValue.startsWith("\n") || formattedValue.startsWith("|")) {
922
- return `${indent}${k}: ${formattedValue}`;
923
- }
924
- return `${indent}${k}: ${formattedValue}`;
925
- });
926
- return "\n" + lines.join("\n");
927
- }
928
- return yaml.dump(value).trimEnd();
929
- }
930
- function formatParamsAsYaml(params) {
826
+ function formatParamsAsBlock(params, prefix = "", argPrefix = GADGET_ARG_PREFIX) {
931
827
  const lines = [];
932
828
  for (const [key, value] of Object.entries(params)) {
933
- const formattedValue = formatYamlValue(value, "");
934
- if (formattedValue.startsWith("\n")) {
935
- lines.push(`${key}:${formattedValue}`);
829
+ const fullPath = prefix ? `${prefix}/${key}` : key;
830
+ if (Array.isArray(value)) {
831
+ value.forEach((item, index) => {
832
+ const itemPath = `${fullPath}/${index}`;
833
+ if (typeof item === "object" && item !== null) {
834
+ lines.push(formatParamsAsBlock(item, itemPath, argPrefix));
835
+ } else {
836
+ lines.push(`${argPrefix}${itemPath}`);
837
+ lines.push(String(item));
838
+ }
839
+ });
840
+ } else if (typeof value === "object" && value !== null) {
841
+ lines.push(formatParamsAsBlock(value, fullPath, argPrefix));
936
842
  } else {
937
- lines.push(`${key}: ${formattedValue}`);
843
+ lines.push(`${argPrefix}${fullPath}`);
844
+ lines.push(String(value));
938
845
  }
939
846
  }
940
847
  return lines.join("\n");
941
848
  }
942
- function formatTomlInlineTable(obj) {
943
- const entries = Object.entries(obj).map(([k, v]) => `${k} = ${formatTomlValue(v)}`);
944
- return `{ ${entries.join(", ")} }`;
945
- }
946
- function formatTomlValue(value) {
947
- if (typeof value === "string") {
948
- if (value.includes("\n")) {
949
- const delimiter = findSafeDelimiter(value);
950
- return `<<<${delimiter}
951
- ${value}
952
- ${delimiter}`;
953
- }
954
- return JSON.stringify(value);
955
- }
956
- if (typeof value === "number" || typeof value === "boolean") {
957
- return String(value);
958
- }
959
- if (value === null || value === void 0) {
960
- return '""';
961
- }
962
- if (Array.isArray(value)) {
963
- if (value.length === 0) return "[]";
964
- const items = value.map((item) => {
965
- if (typeof item === "object" && item !== null && !Array.isArray(item)) {
966
- return formatTomlInlineTable(item);
967
- }
968
- return formatTomlValue(item);
969
- });
970
- return `[${items.join(", ")}]`;
971
- }
972
- if (typeof value === "object") {
973
- return formatTomlInlineTable(value);
974
- }
975
- return JSON.stringify(value);
976
- }
977
- function formatParamsAsToml(params) {
849
+ function formatSchemaAsPlainText(schema, indent = "") {
978
850
  const lines = [];
979
- for (const [key, value] of Object.entries(params)) {
980
- lines.push(`${key} = ${formatTomlValue(value)}`);
851
+ const properties = schema.properties || {};
852
+ const required = schema.required || [];
853
+ for (const [key, prop] of Object.entries(properties)) {
854
+ const propObj = prop;
855
+ const type = propObj.type;
856
+ const description = propObj.description;
857
+ const isRequired = required.includes(key);
858
+ const enumValues = propObj.enum;
859
+ let line = `${indent}- ${key}`;
860
+ if (type === "array") {
861
+ const items = propObj.items;
862
+ const itemType = items?.type || "any";
863
+ line += ` (array of ${itemType})`;
864
+ } else if (type === "object" && propObj.properties) {
865
+ line += " (object)";
866
+ } else {
867
+ line += ` (${type})`;
868
+ }
869
+ if (isRequired) {
870
+ line += " [required]";
871
+ }
872
+ if (description) {
873
+ line += `: ${description}`;
874
+ }
875
+ if (enumValues) {
876
+ line += ` - one of: ${enumValues.map((v) => `"${v}"`).join(", ")}`;
877
+ }
878
+ lines.push(line);
879
+ if (type === "object" && propObj.properties) {
880
+ lines.push(formatSchemaAsPlainText(propObj, indent + " "));
881
+ }
981
882
  }
982
883
  return lines.join("\n");
983
884
  }
984
- var yaml, HEREDOC_DELIMITERS, BaseGadget;
885
+ var BaseGadget;
985
886
  var init_gadget = __esm({
986
887
  "src/gadgets/gadget.ts"() {
987
888
  "use strict";
988
- yaml = __toESM(require("js-yaml"), 1);
889
+ init_constants();
989
890
  init_schema_to_json();
990
891
  init_schema_validator();
991
- HEREDOC_DELIMITERS = [
992
- "__GADGET_PARAM_EOF__",
993
- "__GADGET_PARAM_END__",
994
- "__GADGET_PARAM_DOC__",
995
- "__GADGET_PARAM_CONTENT__",
996
- "__GADGET_PARAM_TEXT__",
997
- "__GADGET_PARAM_HEREDOC__",
998
- "__GADGET_PARAM_DATA__",
999
- "__GADGET_PARAM_BLOCK__"
1000
- ];
1001
892
  BaseGadget = class {
1002
893
  /**
1003
894
  * The name of the gadget. Used for identification when LLM calls it.
@@ -1028,19 +919,19 @@ var init_gadget = __esm({
1028
919
  /**
1029
920
  * Auto-generated instruction text for the LLM.
1030
921
  * Combines name, description, and parameter schema into a formatted instruction.
1031
- * @deprecated Use getInstruction(format) instead for format-specific schemas
922
+ * @deprecated Use getInstruction() instead
1032
923
  */
1033
924
  get instruction() {
1034
- return this.getInstruction("yaml");
925
+ return this.getInstruction();
1035
926
  }
1036
927
  /**
1037
- * Generate instruction text for the LLM with format-specific schema.
928
+ * Generate instruction text for the LLM.
1038
929
  * Combines name, description, and parameter schema into a formatted instruction.
1039
930
  *
1040
- * @param format - Format for the schema representation ('json' | 'yaml' | 'toml' | 'auto')
931
+ * @param argPrefix - Optional custom argument prefix for block format examples
1041
932
  * @returns Formatted instruction string
1042
933
  */
1043
- getInstruction(format = "json") {
934
+ getInstruction(argPrefix) {
1044
935
  const parts = [];
1045
936
  parts.push(this.description);
1046
937
  if (this.parameterSchema) {
@@ -1049,20 +940,12 @@ var init_gadget = __esm({
1049
940
  const jsonSchema = schemaToJSONSchema(this.parameterSchema, {
1050
941
  target: "draft-7"
1051
942
  });
1052
- if (format === "json" || format === "auto") {
1053
- parts.push("\n\nInput Schema (JSON):");
1054
- parts.push(JSON.stringify(jsonSchema, null, 2));
1055
- } else if (format === "toml") {
1056
- parts.push("\n\nInput Schema (TOML):");
1057
- parts.push(JSON.stringify(jsonSchema, null, 2));
1058
- } else {
1059
- const yamlSchema = yaml.dump(jsonSchema).trimEnd();
1060
- parts.push("\n\nInput Schema (YAML):");
1061
- parts.push(yamlSchema);
1062
- }
943
+ parts.push("\n\nParameters:");
944
+ parts.push(formatSchemaAsPlainText(jsonSchema));
1063
945
  }
1064
946
  if (this.examples && this.examples.length > 0) {
1065
947
  parts.push("\n\nExamples:");
948
+ const effectiveArgPrefix = argPrefix ?? GADGET_ARG_PREFIX;
1066
949
  this.examples.forEach((example, index) => {
1067
950
  if (index > 0) {
1068
951
  parts.push("");
@@ -1071,13 +954,7 @@ var init_gadget = __esm({
1071
954
  parts.push(`# ${example.comment}`);
1072
955
  }
1073
956
  parts.push("Input:");
1074
- if (format === "json" || format === "auto") {
1075
- parts.push(JSON.stringify(example.params, null, 2));
1076
- } else if (format === "toml") {
1077
- parts.push(formatParamsAsToml(example.params));
1078
- } else {
1079
- parts.push(formatParamsAsYaml(example.params));
1080
- }
957
+ parts.push(formatParamsAsBlock(example.params, "", effectiveArgPrefix));
1081
958
  if (example.output !== void 0) {
1082
959
  parts.push("Output:");
1083
960
  parts.push(example.output);
@@ -1354,14 +1231,12 @@ var init_conversation_manager = __esm({
1354
1231
  baseMessages;
1355
1232
  initialMessages;
1356
1233
  historyBuilder;
1357
- parameterFormat;
1358
1234
  constructor(baseMessages, initialMessages, options = {}) {
1359
1235
  this.baseMessages = baseMessages;
1360
1236
  this.initialMessages = initialMessages;
1361
- this.parameterFormat = options.parameterFormat ?? "json";
1362
1237
  this.historyBuilder = new LLMMessageBuilder();
1363
1238
  if (options.startPrefix && options.endPrefix) {
1364
- this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix);
1239
+ this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix, options.argPrefix);
1365
1240
  }
1366
1241
  }
1367
1242
  addUserMessage(content) {
@@ -1371,7 +1246,7 @@ var init_conversation_manager = __esm({
1371
1246
  this.historyBuilder.addAssistant(content);
1372
1247
  }
1373
1248
  addGadgetCall(gadgetName, parameters, result) {
1374
- this.historyBuilder.addGadgetCall(gadgetName, parameters, result, this.parameterFormat);
1249
+ this.historyBuilder.addGadgetCall(gadgetName, parameters, result);
1375
1250
  }
1376
1251
  getMessages() {
1377
1252
  return [...this.baseMessages, ...this.initialMessages, ...this.historyBuilder.build()];
@@ -1394,7 +1269,7 @@ async function runWithHandlers(agentGenerator, handlers) {
1394
1269
  await handlers.onGadgetCall({
1395
1270
  gadgetName: event.call.gadgetName,
1396
1271
  parameters: event.call.parameters,
1397
- parametersYaml: event.call.parametersYaml
1272
+ parametersRaw: event.call.parametersRaw
1398
1273
  });
1399
1274
  }
1400
1275
  break;
@@ -1618,6 +1493,89 @@ var init_hook_validators = __esm({
1618
1493
  }
1619
1494
  });
1620
1495
 
1496
+ // src/gadgets/error-formatter.ts
1497
+ var GadgetErrorFormatter;
1498
+ var init_error_formatter = __esm({
1499
+ "src/gadgets/error-formatter.ts"() {
1500
+ "use strict";
1501
+ init_constants();
1502
+ GadgetErrorFormatter = class {
1503
+ argPrefix;
1504
+ startPrefix;
1505
+ endPrefix;
1506
+ constructor(options = {}) {
1507
+ this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;
1508
+ this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;
1509
+ this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;
1510
+ }
1511
+ /**
1512
+ * Format a Zod validation error with full gadget instructions.
1513
+ *
1514
+ * @param gadgetName - Name of the gadget that was called
1515
+ * @param zodError - The Zod validation error
1516
+ * @param gadget - The gadget instance (for generating instructions)
1517
+ * @returns Formatted error message with usage instructions
1518
+ */
1519
+ formatValidationError(gadgetName, zodError, gadget) {
1520
+ const parts = [];
1521
+ parts.push(`Error: Invalid parameters for '${gadgetName}':`);
1522
+ for (const issue of zodError.issues) {
1523
+ const path = issue.path.join(".") || "root";
1524
+ parts.push(` - ${path}: ${issue.message}`);
1525
+ }
1526
+ parts.push("");
1527
+ parts.push("Gadget Usage:");
1528
+ parts.push(gadget.getInstruction(this.argPrefix));
1529
+ return parts.join("\n");
1530
+ }
1531
+ /**
1532
+ * Format a parse error with block format reference.
1533
+ *
1534
+ * @param gadgetName - Name of the gadget that was called
1535
+ * @param parseError - The parse error message
1536
+ * @param gadget - The gadget instance if found (for generating instructions)
1537
+ * @returns Formatted error message with format reference
1538
+ */
1539
+ formatParseError(gadgetName, parseError, gadget) {
1540
+ const parts = [];
1541
+ parts.push(`Error: Failed to parse parameters for '${gadgetName}':`);
1542
+ parts.push(` ${parseError}`);
1543
+ if (gadget) {
1544
+ parts.push("");
1545
+ parts.push("Gadget Usage:");
1546
+ parts.push(gadget.getInstruction(this.argPrefix));
1547
+ }
1548
+ parts.push("");
1549
+ parts.push("Block Format Reference:");
1550
+ parts.push(` ${this.startPrefix}${gadgetName}`);
1551
+ parts.push(` ${this.argPrefix}parameterName`);
1552
+ parts.push(" parameter value here");
1553
+ parts.push(` ${this.endPrefix}`);
1554
+ return parts.join("\n");
1555
+ }
1556
+ /**
1557
+ * Format a registry error (gadget not found) with available gadgets list.
1558
+ *
1559
+ * @param gadgetName - Name of the gadget that was not found
1560
+ * @param availableGadgets - List of available gadget names
1561
+ * @returns Formatted error message with available gadgets
1562
+ */
1563
+ formatRegistryError(gadgetName, availableGadgets) {
1564
+ const parts = [];
1565
+ parts.push(`Error: Gadget '${gadgetName}' not found.`);
1566
+ if (availableGadgets.length > 0) {
1567
+ parts.push("");
1568
+ parts.push(`Available gadgets: ${availableGadgets.join(", ")}`);
1569
+ } else {
1570
+ parts.push("");
1571
+ parts.push("No gadgets are currently registered.");
1572
+ }
1573
+ return parts.join("\n");
1574
+ }
1575
+ };
1576
+ }
1577
+ });
1578
+
1621
1579
  // src/gadgets/exceptions.ts
1622
1580
  var BreakLoopException, HumanInputException, TimeoutException;
1623
1581
  var init_exceptions = __esm({
@@ -1656,15 +1614,18 @@ var init_executor = __esm({
1656
1614
  "src/gadgets/executor.ts"() {
1657
1615
  "use strict";
1658
1616
  init_logger();
1617
+ init_error_formatter();
1659
1618
  init_exceptions();
1660
1619
  GadgetExecutor = class {
1661
- constructor(registry, onHumanInputRequired, logger, defaultGadgetTimeoutMs) {
1620
+ constructor(registry, onHumanInputRequired, logger, defaultGadgetTimeoutMs, errorFormatterOptions) {
1662
1621
  this.registry = registry;
1663
1622
  this.onHumanInputRequired = onHumanInputRequired;
1664
1623
  this.defaultGadgetTimeoutMs = defaultGadgetTimeoutMs;
1665
1624
  this.logger = logger ?? createLogger({ name: "llmist:executor" });
1625
+ this.errorFormatter = new GadgetErrorFormatter(errorFormatterOptions);
1666
1626
  }
1667
1627
  logger;
1628
+ errorFormatter;
1668
1629
  /**
1669
1630
  * Creates a promise that rejects with a TimeoutException after the specified timeout.
1670
1631
  */
@@ -1689,11 +1650,12 @@ var init_executor = __esm({
1689
1650
  const gadget = this.registry.get(call.gadgetName);
1690
1651
  if (!gadget) {
1691
1652
  this.logger.error("Gadget not found", { gadgetName: call.gadgetName });
1653
+ const availableGadgets = this.registry.getNames();
1692
1654
  return {
1693
1655
  gadgetName: call.gadgetName,
1694
1656
  invocationId: call.invocationId,
1695
1657
  parameters: call.parameters ?? {},
1696
- error: `Gadget '${call.gadgetName}' not found in registry`,
1658
+ error: this.errorFormatter.formatRegistryError(call.gadgetName, availableGadgets),
1697
1659
  executionTimeMs: Date.now() - startTime
1698
1660
  };
1699
1661
  }
@@ -1701,27 +1663,28 @@ var init_executor = __esm({
1701
1663
  this.logger.error("Gadget parameter parse error", {
1702
1664
  gadgetName: call.gadgetName,
1703
1665
  parseError: call.parseError,
1704
- rawParameters: call.parametersYaml
1666
+ rawParameters: call.parametersRaw
1705
1667
  });
1668
+ const parseErrorMessage = call.parseError ?? "Failed to parse parameters";
1706
1669
  return {
1707
1670
  gadgetName: call.gadgetName,
1708
1671
  invocationId: call.invocationId,
1709
1672
  parameters: {},
1710
- error: call.parseError ?? "Failed to parse parameters",
1673
+ error: this.errorFormatter.formatParseError(call.gadgetName, parseErrorMessage, gadget),
1711
1674
  executionTimeMs: Date.now() - startTime
1712
1675
  };
1713
1676
  }
1714
1677
  if (gadget.parameterSchema) {
1715
1678
  const validationResult = gadget.parameterSchema.safeParse(rawParameters);
1716
1679
  if (!validationResult.success) {
1717
- const formattedIssues = validationResult.error.issues.map((issue) => {
1718
- const path = issue.path.join(".") || "root";
1719
- return `${path}: ${issue.message}`;
1720
- }).join("; ");
1721
- const validationError = `Invalid parameters: ${formattedIssues}`;
1680
+ const validationError = this.errorFormatter.formatValidationError(
1681
+ call.gadgetName,
1682
+ validationResult.error,
1683
+ gadget
1684
+ );
1722
1685
  this.logger.error("Gadget parameter validation failed", {
1723
1686
  gadgetName: call.gadgetName,
1724
- error: validationError
1687
+ issueCount: validationResult.error.issues.length
1725
1688
  });
1726
1689
  return {
1727
1690
  gadgetName: call.gadgetName,
@@ -1863,168 +1826,107 @@ var init_executor = __esm({
1863
1826
  }
1864
1827
  });
1865
1828
 
1866
- // src/gadgets/parser.ts
1867
- function preprocessYaml(yamlStr) {
1868
- const lines = yamlStr.split("\n");
1869
- const result = [];
1870
- let i = 0;
1871
- while (i < lines.length) {
1872
- const line = lines[i];
1873
- const heredocMatch = line.match(/^(\s*)([\w-]+):\s*<<<([A-Za-z_][A-Za-z0-9_]*)\s*$/);
1874
- if (heredocMatch) {
1875
- const [, indent, key, delimiter] = heredocMatch;
1876
- const bodyLines = [];
1877
- i++;
1878
- const closingRegex = new RegExp(`^${delimiter}\\s*$`);
1879
- while (i < lines.length && !closingRegex.test(lines[i])) {
1880
- bodyLines.push(lines[i]);
1881
- i++;
1882
- }
1883
- if (i < lines.length) {
1884
- i++;
1885
- }
1886
- result.push(`${indent}${key}: |`);
1887
- for (const bodyLine of bodyLines) {
1888
- result.push(`${indent} ${bodyLine}`);
1829
+ // src/gadgets/block-params.ts
1830
+ function parseBlockParams(content, options) {
1831
+ const argPrefix = options?.argPrefix ?? GADGET_ARG_PREFIX;
1832
+ const result = {};
1833
+ const seenPointers = /* @__PURE__ */ new Set();
1834
+ const parts = content.split(argPrefix);
1835
+ for (let i = 1; i < parts.length; i++) {
1836
+ const part = parts[i];
1837
+ const newlineIndex = part.indexOf("\n");
1838
+ if (newlineIndex === -1) {
1839
+ const pointer2 = part.trim();
1840
+ if (pointer2) {
1841
+ if (seenPointers.has(pointer2)) {
1842
+ throw new Error(`Duplicate pointer: ${pointer2}`);
1843
+ }
1844
+ seenPointers.add(pointer2);
1845
+ setByPointer(result, pointer2, "");
1889
1846
  }
1890
1847
  continue;
1891
1848
  }
1892
- const match = line.match(/^(\s*)([\w-]+):\s+(.+)$/);
1893
- if (match) {
1894
- const [, indent, key, value] = match;
1895
- if (value === "|" || value === ">" || value === "|-" || value === ">-") {
1896
- result.push(line);
1897
- i++;
1898
- const keyIndentLen2 = indent.length;
1899
- const blockLines = [];
1900
- let minContentIndent = Infinity;
1901
- while (i < lines.length) {
1902
- const blockLine = lines[i];
1903
- const blockIndentMatch = blockLine.match(/^(\s*)/);
1904
- const blockIndentLen = blockIndentMatch ? blockIndentMatch[1].length : 0;
1905
- if (blockLine.trim() === "") {
1906
- blockLines.push({ content: "", originalIndent: 0 });
1907
- i++;
1908
- continue;
1909
- }
1910
- if (blockIndentLen > keyIndentLen2) {
1911
- const content = blockLine.substring(blockIndentLen);
1912
- blockLines.push({ content, originalIndent: blockIndentLen });
1913
- if (content.trim().length > 0) {
1914
- minContentIndent = Math.min(minContentIndent, blockIndentLen);
1915
- }
1916
- i++;
1917
- } else {
1918
- break;
1919
- }
1920
- }
1921
- const targetIndent = keyIndentLen2 + 2;
1922
- for (const blockLine of blockLines) {
1923
- if (blockLine.content === "") {
1924
- result.push("");
1925
- } else {
1926
- result.push(" ".repeat(targetIndent) + blockLine.content);
1927
- }
1928
- }
1929
- continue;
1930
- }
1931
- if (value.startsWith('"') || value.startsWith("'") || value === "true" || value === "false" || /^-?\d+(\.\d+)?$/.test(value)) {
1932
- result.push(line);
1933
- i++;
1934
- continue;
1935
- }
1936
- const keyIndentLen = indent.length;
1937
- const continuationLines = [];
1938
- let j = i + 1;
1939
- while (j < lines.length) {
1940
- const nextLine = lines[j];
1941
- if (nextLine.trim() === "") {
1942
- continuationLines.push(nextLine);
1943
- j++;
1944
- continue;
1945
- }
1946
- const nextIndentMatch = nextLine.match(/^(\s*)/);
1947
- const nextIndentLen = nextIndentMatch ? nextIndentMatch[1].length : 0;
1948
- if (nextIndentLen > keyIndentLen) {
1949
- continuationLines.push(nextLine);
1950
- j++;
1951
- } else {
1952
- break;
1953
- }
1954
- }
1955
- if (continuationLines.length > 0 && continuationLines.some((l) => l.trim().length > 0)) {
1956
- result.push(`${indent}${key}: |`);
1957
- result.push(`${indent} ${value}`);
1958
- for (const contLine of continuationLines) {
1959
- if (contLine.trim() === "") {
1960
- result.push("");
1961
- } else {
1962
- const contIndentMatch = contLine.match(/^(\s*)/);
1963
- const contIndent = contIndentMatch ? contIndentMatch[1] : "";
1964
- const contContent = contLine.substring(contIndent.length);
1965
- result.push(`${indent} ${contContent}`);
1966
- }
1967
- }
1968
- i = j;
1969
- continue;
1970
- }
1971
- if (value.includes(": ") || value.endsWith(":")) {
1972
- const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
1973
- result.push(`${indent}${key}: "${escaped}"`);
1974
- i++;
1975
- continue;
1976
- }
1849
+ const pointer = part.substring(0, newlineIndex).trim();
1850
+ let value = part.substring(newlineIndex + 1);
1851
+ if (value.endsWith("\n")) {
1852
+ value = value.slice(0, -1);
1977
1853
  }
1978
- result.push(line);
1979
- i++;
1854
+ if (!pointer) {
1855
+ continue;
1856
+ }
1857
+ if (seenPointers.has(pointer)) {
1858
+ throw new Error(`Duplicate pointer: ${pointer}`);
1859
+ }
1860
+ seenPointers.add(pointer);
1861
+ setByPointer(result, pointer, value);
1980
1862
  }
1981
- return result.join("\n");
1863
+ return result;
1982
1864
  }
1983
- function unescapeHeredocContent(content) {
1984
- return content.replace(/\\`/g, "`").replace(/\\\$/g, "$").replace(/\\{/g, "{").replace(/\\}/g, "}");
1865
+ function coerceValue(value) {
1866
+ if (value.includes("\n")) {
1867
+ return value;
1868
+ }
1869
+ const trimmed = value.trim();
1870
+ if (trimmed === "true") return true;
1871
+ if (trimmed === "false") return false;
1872
+ if (trimmed !== "" && /^-?\d+(\.\d+)?$/.test(trimmed)) {
1873
+ const num = Number(trimmed);
1874
+ if (!isNaN(num) && isFinite(num)) {
1875
+ return num;
1876
+ }
1877
+ }
1878
+ return value;
1985
1879
  }
1986
- function preprocessTomlHeredoc(tomlStr) {
1987
- const lines = tomlStr.split("\n");
1988
- const result = [];
1989
- let i = 0;
1990
- const heredocStartRegex = /^(\s*)([\w-]+)\s*=\s*<<<([A-Za-z_][A-Za-z0-9_]*)\s*$/;
1991
- while (i < lines.length) {
1992
- const line = lines[i];
1993
- const match = line.match(heredocStartRegex);
1994
- if (match) {
1995
- const [, indent, key, delimiter] = match;
1996
- const bodyLines = [];
1997
- i++;
1998
- const closingRegex = new RegExp(`^${delimiter}\\s*$`);
1999
- let foundClosing = false;
2000
- while (i < lines.length) {
2001
- const bodyLine = lines[i];
2002
- if (closingRegex.test(bodyLine)) {
2003
- foundClosing = true;
2004
- i++;
2005
- break;
2006
- }
2007
- bodyLines.push(bodyLine);
2008
- i++;
2009
- }
2010
- if (bodyLines.length === 0) {
2011
- result.push(`${indent}${key} = ''''''`);
2012
- } else {
2013
- result.push(`${indent}${key} = '''`);
2014
- for (let j = 0; j < bodyLines.length - 1; j++) {
2015
- result.push(unescapeHeredocContent(bodyLines[j]));
2016
- }
2017
- result.push(`${unescapeHeredocContent(bodyLines[bodyLines.length - 1])}'''`);
2018
- }
2019
- if (!foundClosing) {
1880
+ function setByPointer(obj, pointer, value) {
1881
+ const segments = pointer.split("/");
1882
+ let current = obj;
1883
+ for (let i = 0; i < segments.length - 1; i++) {
1884
+ const segment = segments[i];
1885
+ const nextSegment = segments[i + 1];
1886
+ const nextIsArrayIndex = /^\d+$/.test(nextSegment);
1887
+ if (Array.isArray(current)) {
1888
+ const index = parseInt(segment, 10);
1889
+ if (isNaN(index) || index < 0) {
1890
+ throw new Error(`Invalid array index: ${segment}`);
1891
+ }
1892
+ if (index > current.length) {
1893
+ throw new Error(`Array index gap: expected ${current.length}, got ${index}`);
1894
+ }
1895
+ if (current[index] === void 0) {
1896
+ current[index] = nextIsArrayIndex ? [] : {};
1897
+ }
1898
+ current = current[index];
1899
+ } else {
1900
+ const rec = current;
1901
+ if (rec[segment] === void 0) {
1902
+ rec[segment] = nextIsArrayIndex ? [] : {};
2020
1903
  }
2021
- continue;
1904
+ current = rec[segment];
1905
+ }
1906
+ }
1907
+ const lastSegment = segments[segments.length - 1];
1908
+ const coercedValue = coerceValue(value);
1909
+ if (Array.isArray(current)) {
1910
+ const index = parseInt(lastSegment, 10);
1911
+ if (isNaN(index) || index < 0) {
1912
+ throw new Error(`Invalid array index: ${lastSegment}`);
1913
+ }
1914
+ if (index > current.length) {
1915
+ throw new Error(`Array index gap: expected ${current.length}, got ${index}`);
2022
1916
  }
2023
- result.push(line);
2024
- i++;
1917
+ current[index] = coercedValue;
1918
+ } else {
1919
+ current[lastSegment] = coercedValue;
2025
1920
  }
2026
- return result.join("\n");
2027
1921
  }
1922
+ var init_block_params = __esm({
1923
+ "src/gadgets/block-params.ts"() {
1924
+ "use strict";
1925
+ init_constants();
1926
+ }
1927
+ });
1928
+
1929
+ // src/gadgets/parser.ts
2028
1930
  function stripMarkdownFences(content) {
2029
1931
  let cleaned = content.trim();
2030
1932
  const openingFence = /^```(?:toml|yaml|json)?\s*\n/i;
@@ -2033,24 +1935,23 @@ function stripMarkdownFences(content) {
2033
1935
  cleaned = cleaned.replace(closingFence, "");
2034
1936
  return cleaned.trim();
2035
1937
  }
2036
- var yaml2, import_js_toml, globalInvocationCounter, StreamParser;
1938
+ var globalInvocationCounter, StreamParser;
2037
1939
  var init_parser = __esm({
2038
1940
  "src/gadgets/parser.ts"() {
2039
1941
  "use strict";
2040
- yaml2 = __toESM(require("js-yaml"), 1);
2041
- import_js_toml = require("js-toml");
2042
1942
  init_constants();
1943
+ init_block_params();
2043
1944
  globalInvocationCounter = 0;
2044
1945
  StreamParser = class {
2045
1946
  buffer = "";
2046
1947
  lastReportedTextLength = 0;
2047
1948
  startPrefix;
2048
1949
  endPrefix;
2049
- parameterFormat;
1950
+ argPrefix;
2050
1951
  constructor(options = {}) {
2051
1952
  this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;
2052
1953
  this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;
2053
- this.parameterFormat = options.parameterFormat ?? "json";
1954
+ this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;
2054
1955
  }
2055
1956
  takeTextUntil(index) {
2056
1957
  if (index <= this.lastReportedTextLength) {
@@ -2072,56 +1973,22 @@ var init_parser = __esm({
2072
1973
  return { actualName: gadgetName, invocationId: `gadget_${++globalInvocationCounter}` };
2073
1974
  }
2074
1975
  /**
2075
- * Truncate verbose parse errors to avoid context overflow.
2076
- * Keeps first meaningful line and limits total length.
1976
+ * Extract the error message from a parse error.
1977
+ * Preserves full message since the error formatter adds contextual help
1978
+ * that benefits from precise, detailed error information.
2077
1979
  */
2078
- truncateParseError(error, format) {
2079
- const message = error instanceof Error ? error.message : String(error);
2080
- const firstLine = message.split("\n")[0];
2081
- const maxLen = 200;
2082
- if (firstLine.length <= maxLen) {
2083
- return firstLine;
2084
- }
2085
- return `${firstLine.slice(0, maxLen)}... (${message.length} chars total)`;
1980
+ extractParseError(error) {
1981
+ return error instanceof Error ? error.message : String(error);
2086
1982
  }
2087
1983
  /**
2088
- * Parse parameter string according to configured format
1984
+ * Parse parameter string using block format
2089
1985
  */
2090
1986
  parseParameters(raw) {
2091
1987
  const cleaned = stripMarkdownFences(raw);
2092
- if (this.parameterFormat === "json") {
2093
- try {
2094
- return { parameters: JSON.parse(cleaned) };
2095
- } catch (error) {
2096
- return { parseError: this.truncateParseError(error, "JSON") };
2097
- }
2098
- }
2099
- if (this.parameterFormat === "yaml") {
2100
- try {
2101
- return { parameters: yaml2.load(preprocessYaml(cleaned)) };
2102
- } catch (error) {
2103
- return { parseError: this.truncateParseError(error, "YAML") };
2104
- }
2105
- }
2106
- if (this.parameterFormat === "toml") {
2107
- try {
2108
- return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(cleaned)) };
2109
- } catch (error) {
2110
- return { parseError: this.truncateParseError(error, "TOML") };
2111
- }
2112
- }
2113
1988
  try {
2114
- return { parameters: JSON.parse(cleaned) };
2115
- } catch {
2116
- try {
2117
- return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(cleaned)) };
2118
- } catch {
2119
- try {
2120
- return { parameters: yaml2.load(preprocessYaml(cleaned)) };
2121
- } catch (error) {
2122
- return { parseError: this.truncateParseError(error, "auto") };
2123
- }
2124
- }
1989
+ return { parameters: parseBlockParams(cleaned, { argPrefix: this.argPrefix }) };
1990
+ } catch (error) {
1991
+ return { parseError: this.extractParseError(error) };
2125
1992
  }
2126
1993
  }
2127
1994
  // Feed a chunk of text and get parsed events
@@ -2180,8 +2047,7 @@ var init_parser = __esm({
2180
2047
  call: {
2181
2048
  gadgetName: actualGadgetName,
2182
2049
  invocationId,
2183
- parametersYaml: parametersRaw,
2184
- // Keep property name for backward compatibility
2050
+ parametersRaw,
2185
2051
  parameters,
2186
2052
  parseError
2187
2053
  }
@@ -2215,7 +2081,7 @@ var init_parser = __esm({
2215
2081
  call: {
2216
2082
  gadgetName: actualGadgetName,
2217
2083
  invocationId,
2218
- parametersYaml: parametersRaw,
2084
+ parametersRaw,
2219
2085
  parameters,
2220
2086
  parseError
2221
2087
  }
@@ -2266,9 +2132,9 @@ var init_stream_processor = __esm({
2266
2132
  this.stopOnGadgetError = options.stopOnGadgetError ?? true;
2267
2133
  this.shouldContinueAfterError = options.shouldContinueAfterError;
2268
2134
  this.parser = new StreamParser({
2269
- parameterFormat: options.parameterFormat,
2270
2135
  startPrefix: options.gadgetStartPrefix,
2271
- endPrefix: options.gadgetEndPrefix
2136
+ endPrefix: options.gadgetEndPrefix,
2137
+ argPrefix: options.gadgetArgPrefix
2272
2138
  });
2273
2139
  this.executor = new GadgetExecutor(
2274
2140
  options.registry,
@@ -2422,7 +2288,7 @@ var init_stream_processor = __esm({
2422
2288
  this.logger.warn("Gadget has parse error", {
2423
2289
  gadgetName: call.gadgetName,
2424
2290
  error: call.parseError,
2425
- rawParameters: call.parametersYaml
2291
+ rawParameters: call.parametersRaw
2426
2292
  });
2427
2293
  const shouldContinue = await this.checkContinueAfterError(
2428
2294
  call.parseError,
@@ -2658,9 +2524,9 @@ var init_agent = __esm({
2658
2524
  hooks;
2659
2525
  conversation;
2660
2526
  registry;
2661
- parameterFormat;
2662
2527
  gadgetStartPrefix;
2663
2528
  gadgetEndPrefix;
2529
+ gadgetArgPrefix;
2664
2530
  onHumanInputRequired;
2665
2531
  textOnlyHandler;
2666
2532
  textWithGadgetsHandler;
@@ -2689,9 +2555,9 @@ var init_agent = __esm({
2689
2555
  this.temperature = options.temperature;
2690
2556
  this.logger = options.logger ?? createLogger({ name: "llmist:agent" });
2691
2557
  this.registry = options.registry;
2692
- this.parameterFormat = options.parameterFormat ?? "json";
2693
2558
  this.gadgetStartPrefix = options.gadgetStartPrefix;
2694
2559
  this.gadgetEndPrefix = options.gadgetEndPrefix;
2560
+ this.gadgetArgPrefix = options.gadgetArgPrefix;
2695
2561
  this.onHumanInputRequired = options.onHumanInputRequired;
2696
2562
  this.textOnlyHandler = options.textOnlyHandler ?? "terminate";
2697
2563
  this.textWithGadgetsHandler = options.textWithGadgetsHandler;
@@ -2713,9 +2579,10 @@ var init_agent = __esm({
2713
2579
  if (options.systemPrompt) {
2714
2580
  baseBuilder.addSystem(options.systemPrompt);
2715
2581
  }
2716
- baseBuilder.addGadgets(this.registry.getAll(), this.parameterFormat, {
2582
+ baseBuilder.addGadgets(this.registry.getAll(), {
2717
2583
  startPrefix: options.gadgetStartPrefix,
2718
- endPrefix: options.gadgetEndPrefix
2584
+ endPrefix: options.gadgetEndPrefix,
2585
+ argPrefix: options.gadgetArgPrefix
2719
2586
  });
2720
2587
  const baseMessages = baseBuilder.build();
2721
2588
  const initialMessages = (options.initialMessages ?? []).map((message) => ({
@@ -2723,9 +2590,9 @@ var init_agent = __esm({
2723
2590
  content: message.content
2724
2591
  }));
2725
2592
  this.conversation = new ConversationManager(baseMessages, initialMessages, {
2726
- parameterFormat: this.parameterFormat,
2727
2593
  startPrefix: options.gadgetStartPrefix,
2728
- endPrefix: options.gadgetEndPrefix
2594
+ endPrefix: options.gadgetEndPrefix,
2595
+ argPrefix: options.gadgetArgPrefix
2729
2596
  });
2730
2597
  this.userPromptProvided = !!options.userPrompt;
2731
2598
  if (options.userPrompt) {
@@ -2818,9 +2685,9 @@ var init_agent = __esm({
2818
2685
  const processor = new StreamProcessor({
2819
2686
  iteration: currentIteration,
2820
2687
  registry: this.registry,
2821
- parameterFormat: this.parameterFormat,
2822
2688
  gadgetStartPrefix: this.gadgetStartPrefix,
2823
2689
  gadgetEndPrefix: this.gadgetEndPrefix,
2690
+ gadgetArgPrefix: this.gadgetArgPrefix,
2824
2691
  hooks: this.hooks,
2825
2692
  logger: this.logger.getSubLogger({ name: "stream-processor" }),
2826
2693
  onHumanInputRequired: this.onHumanInputRequired,
@@ -5086,9 +4953,9 @@ var init_builder = __esm({
5086
4953
  gadgets = [];
5087
4954
  initialMessages = [];
5088
4955
  onHumanInputRequired;
5089
- parameterFormat;
5090
4956
  gadgetStartPrefix;
5091
4957
  gadgetEndPrefix;
4958
+ gadgetArgPrefix;
5092
4959
  textOnlyHandler;
5093
4960
  textWithGadgetsHandler;
5094
4961
  stopOnGadgetError;
@@ -5275,21 +5142,6 @@ var init_builder = __esm({
5275
5142
  this.onHumanInputRequired = handler;
5276
5143
  return this;
5277
5144
  }
5278
- /**
5279
- * Set the parameter format for gadget calls.
5280
- *
5281
- * @param format - Parameter format ("json" or "xml")
5282
- * @returns This builder for chaining
5283
- *
5284
- * @example
5285
- * ```typescript
5286
- * .withParameterFormat("xml")
5287
- * ```
5288
- */
5289
- withParameterFormat(format) {
5290
- this.parameterFormat = format;
5291
- return this;
5292
- }
5293
5145
  /**
5294
5146
  * Set custom gadget marker prefix.
5295
5147
  *
@@ -5320,6 +5172,21 @@ var init_builder = __esm({
5320
5172
  this.gadgetEndPrefix = suffix;
5321
5173
  return this;
5322
5174
  }
5175
+ /**
5176
+ * Set custom argument prefix for block format parameters.
5177
+ *
5178
+ * @param prefix - Custom prefix for argument markers (default: "!!!ARG:")
5179
+ * @returns This builder for chaining
5180
+ *
5181
+ * @example
5182
+ * ```typescript
5183
+ * .withGadgetArgPrefix("<<ARG>>")
5184
+ * ```
5185
+ */
5186
+ withGadgetArgPrefix(prefix) {
5187
+ this.gadgetArgPrefix = prefix;
5188
+ return this;
5189
+ }
5323
5190
  /**
5324
5191
  * Set the text-only handler strategy.
5325
5192
  *
@@ -5519,8 +5386,7 @@ var init_builder = __esm({
5519
5386
  withSyntheticGadgetCall(gadgetName, parameters, result) {
5520
5387
  const startPrefix = this.gadgetStartPrefix ?? GADGET_START_PREFIX;
5521
5388
  const endPrefix = this.gadgetEndPrefix ?? GADGET_END_PREFIX;
5522
- const format = this.parameterFormat ?? "yaml";
5523
- const paramStr = this.formatSyntheticParameters(parameters, format);
5389
+ const paramStr = this.formatBlockParameters(parameters, "");
5524
5390
  this.initialMessages.push({
5525
5391
  role: "assistant",
5526
5392
  content: `${startPrefix}${gadgetName}
@@ -5534,25 +5400,31 @@ ${endPrefix}`
5534
5400
  return this;
5535
5401
  }
5536
5402
  /**
5537
- * Format parameters for synthetic gadget calls.
5538
- * Uses heredoc for multiline string values.
5403
+ * Format parameters as block format with JSON Pointer paths.
5539
5404
  */
5540
- formatSyntheticParameters(parameters, format) {
5541
- if (format === "json" || format === "auto") {
5542
- return JSON.stringify(parameters);
5543
- }
5544
- return Object.entries(parameters).map(([key, value]) => {
5545
- if (typeof value === "string" && value.includes("\n")) {
5546
- const separator = format === "yaml" ? ":" : " =";
5547
- return `${key}${separator} <<<EOF
5548
- ${value}
5549
- EOF`;
5550
- }
5551
- if (format === "yaml") {
5552
- return typeof value === "string" ? `${key}: ${value}` : `${key}: ${JSON.stringify(value)}`;
5405
+ formatBlockParameters(params, prefix) {
5406
+ const lines = [];
5407
+ const argPrefix = this.gadgetArgPrefix ?? GADGET_ARG_PREFIX;
5408
+ for (const [key, value] of Object.entries(params)) {
5409
+ const fullPath = prefix ? `${prefix}/${key}` : key;
5410
+ if (Array.isArray(value)) {
5411
+ value.forEach((item, index) => {
5412
+ const itemPath = `${fullPath}/${index}`;
5413
+ if (typeof item === "object" && item !== null) {
5414
+ lines.push(this.formatBlockParameters(item, itemPath));
5415
+ } else {
5416
+ lines.push(`${argPrefix}${itemPath}`);
5417
+ lines.push(String(item));
5418
+ }
5419
+ });
5420
+ } else if (typeof value === "object" && value !== null) {
5421
+ lines.push(this.formatBlockParameters(value, fullPath));
5422
+ } else {
5423
+ lines.push(`${argPrefix}${fullPath}`);
5424
+ lines.push(String(value));
5553
5425
  }
5554
- return `${key} = ${JSON.stringify(value)}`;
5555
- }).join("\n");
5426
+ }
5427
+ return lines.join("\n");
5556
5428
  }
5557
5429
  /**
5558
5430
  * Build and create the agent with the given user prompt.
@@ -5592,9 +5464,9 @@ EOF`;
5592
5464
  promptConfig: this.promptConfig,
5593
5465
  initialMessages: this.initialMessages,
5594
5466
  onHumanInputRequired: this.onHumanInputRequired,
5595
- parameterFormat: this.parameterFormat,
5596
5467
  gadgetStartPrefix: this.gadgetStartPrefix,
5597
5468
  gadgetEndPrefix: this.gadgetEndPrefix,
5469
+ gadgetArgPrefix: this.gadgetArgPrefix,
5598
5470
  textOnlyHandler: this.textOnlyHandler,
5599
5471
  textWithGadgetsHandler: this.textWithGadgetsHandler,
5600
5472
  stopOnGadgetError: this.stopOnGadgetError,
@@ -5694,9 +5566,9 @@ EOF`;
5694
5566
  promptConfig: this.promptConfig,
5695
5567
  initialMessages: this.initialMessages,
5696
5568
  onHumanInputRequired: this.onHumanInputRequired,
5697
- parameterFormat: this.parameterFormat,
5698
5569
  gadgetStartPrefix: this.gadgetStartPrefix,
5699
5570
  gadgetEndPrefix: this.gadgetEndPrefix,
5571
+ gadgetArgPrefix: this.gadgetArgPrefix,
5700
5572
  textOnlyHandler: this.textOnlyHandler,
5701
5573
  textWithGadgetsHandler: this.textWithGadgetsHandler,
5702
5574
  stopOnGadgetError: this.stopOnGadgetError,
@@ -6776,17 +6648,51 @@ function splitIntoChunks(text, minChunkSize = 5, maxChunkSize = 30) {
6776
6648
  }
6777
6649
  return chunks;
6778
6650
  }
6651
+ function serializeToBlockFormat(obj, prefix = "") {
6652
+ let result = "";
6653
+ for (const [key, value] of Object.entries(obj)) {
6654
+ const pointer = prefix ? `${prefix}/${key}` : key;
6655
+ if (value === null || value === void 0) {
6656
+ continue;
6657
+ }
6658
+ if (Array.isArray(value)) {
6659
+ for (let i = 0; i < value.length; i++) {
6660
+ const item = value[i];
6661
+ const itemPointer = `${pointer}/${i}`;
6662
+ if (typeof item === "object" && item !== null && !Array.isArray(item)) {
6663
+ result += serializeToBlockFormat(item, itemPointer);
6664
+ } else if (Array.isArray(item)) {
6665
+ for (let j = 0; j < item.length; j++) {
6666
+ result += `${GADGET_ARG_PREFIX}${itemPointer}/${j}
6667
+ ${String(item[j])}
6668
+ `;
6669
+ }
6670
+ } else {
6671
+ result += `${GADGET_ARG_PREFIX}${itemPointer}
6672
+ ${String(item)}
6673
+ `;
6674
+ }
6675
+ }
6676
+ } else if (typeof value === "object") {
6677
+ result += serializeToBlockFormat(value, pointer);
6678
+ } else {
6679
+ result += `${GADGET_ARG_PREFIX}${pointer}
6680
+ ${String(value)}
6681
+ `;
6682
+ }
6683
+ }
6684
+ return result;
6685
+ }
6779
6686
  function formatGadgetCalls(gadgetCalls) {
6780
6687
  let text = "";
6781
6688
  const calls = [];
6782
6689
  for (const call of gadgetCalls) {
6783
6690
  const invocationId = call.invocationId ?? generateInvocationId();
6784
6691
  calls.push({ name: call.gadgetName, invocationId });
6785
- const paramsJson = JSON.stringify(call.parameters);
6692
+ const blockParams = serializeToBlockFormat(call.parameters);
6786
6693
  text += `
6787
6694
  ${GADGET_START_PREFIX}${call.gadgetName}
6788
- ${paramsJson}
6789
- ${GADGET_END_PREFIX}`;
6695
+ ${blockParams}${GADGET_END_PREFIX}`;
6790
6696
  }
6791
6697
  return { text, calls };
6792
6698
  }