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.
@@ -110,12 +110,13 @@ var init_logger = __esm({
110
110
  });
111
111
 
112
112
  // src/core/constants.ts
113
- var GADGET_START_PREFIX, GADGET_END_PREFIX, DEFAULT_GADGET_OUTPUT_LIMIT, DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT, CHARS_PER_TOKEN, FALLBACK_CONTEXT_WINDOW;
113
+ 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;
114
114
  var init_constants = __esm({
115
115
  "src/core/constants.ts"() {
116
116
  "use strict";
117
117
  GADGET_START_PREFIX = "!!!GADGET_START:";
118
118
  GADGET_END_PREFIX = "!!!GADGET_END";
119
+ GADGET_ARG_PREFIX = "!!!ARG:";
119
120
  DEFAULT_GADGET_OUTPUT_LIMIT = true;
120
121
  DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;
121
122
  CHARS_PER_TOKEN = 4;
@@ -448,17 +449,12 @@ var init_prompt_config = __esm({
448
449
  "EACH MARKER MUST START WITH A NEWLINE."
449
450
  ].join("\n"),
450
451
  criticalUsage: "INVOKE gadgets using the markers - do not describe what you want to do.",
451
- formatDescriptionYaml: "Parameters in YAML format (one per line)",
452
- formatDescriptionJson: "Parameters in JSON format (valid JSON object)",
453
- formatDescriptionToml: "Parameters in TOML format (key = value pairs, use heredoc for multiline: key = <<<EOF ... EOF)",
452
+ formatDescription: (ctx) => `Parameters using ${ctx.argPrefix}name markers (value on next line(s), no escaping needed)`,
454
453
  rules: () => [
455
454
  "Output ONLY plain text with the exact markers - never use function/tool calling",
456
455
  "You can invoke multiple gadgets in a single response",
457
456
  "For dependent gadgets, invoke the first one and wait for the result"
458
457
  ],
459
- schemaLabelJson: "\n\nInput Schema (JSON):",
460
- schemaLabelYaml: "\n\nInput Schema (YAML):",
461
- schemaLabelToml: "\n\nInput Schema (TOML):",
462
458
  customExamples: null
463
459
  };
464
460
  }
@@ -475,6 +471,7 @@ var init_messages = __esm({
475
471
  messages = [];
476
472
  startPrefix = GADGET_START_PREFIX;
477
473
  endPrefix = GADGET_END_PREFIX;
474
+ argPrefix = GADGET_ARG_PREFIX;
478
475
  promptConfig;
479
476
  constructor(promptConfig) {
480
477
  this.promptConfig = promptConfig ?? {};
@@ -483,26 +480,32 @@ var init_messages = __esm({
483
480
  * Set custom prefixes for gadget markers.
484
481
  * Used to configure history builder to match system prompt markers.
485
482
  */
486
- withPrefixes(startPrefix, endPrefix) {
483
+ withPrefixes(startPrefix, endPrefix, argPrefix) {
487
484
  this.startPrefix = startPrefix;
488
485
  this.endPrefix = endPrefix;
486
+ if (argPrefix) {
487
+ this.argPrefix = argPrefix;
488
+ }
489
489
  return this;
490
490
  }
491
491
  addSystem(content, metadata) {
492
492
  this.messages.push({ role: "system", content, metadata });
493
493
  return this;
494
494
  }
495
- addGadgets(gadgets, parameterFormat = "json", options) {
495
+ addGadgets(gadgets, options) {
496
496
  if (options?.startPrefix) {
497
497
  this.startPrefix = options.startPrefix;
498
498
  }
499
499
  if (options?.endPrefix) {
500
500
  this.endPrefix = options.endPrefix;
501
501
  }
502
+ if (options?.argPrefix) {
503
+ this.argPrefix = options.argPrefix;
504
+ }
502
505
  const context = {
503
- parameterFormat,
504
506
  startPrefix: this.startPrefix,
505
507
  endPrefix: this.endPrefix,
508
+ argPrefix: this.argPrefix,
506
509
  gadgetCount: gadgets.length,
507
510
  gadgetNames: gadgets.map((g) => g.name ?? g.constructor.name)
508
511
  };
@@ -513,26 +516,19 @@ var init_messages = __esm({
513
516
  context
514
517
  );
515
518
  parts.push(mainInstruction);
516
- parts.push(this.buildGadgetsSection(gadgets, parameterFormat));
517
- parts.push(this.buildUsageSection(parameterFormat, context));
519
+ parts.push(this.buildGadgetsSection(gadgets));
520
+ parts.push(this.buildUsageSection(context));
518
521
  this.messages.push({ role: "system", content: parts.join("") });
519
522
  return this;
520
523
  }
521
- buildGadgetsSection(gadgets, parameterFormat) {
524
+ buildGadgetsSection(gadgets) {
522
525
  const parts = [];
523
526
  parts.push("\n\nAVAILABLE GADGETS");
524
527
  parts.push("\n=================\n");
525
528
  for (const gadget of gadgets) {
526
529
  const gadgetName = gadget.name ?? gadget.constructor.name;
527
- const instruction = gadget.getInstruction(parameterFormat);
528
- const schemaMarkers = {
529
- yaml: "\n\nInput Schema (YAML):",
530
- json: "\n\nInput Schema (JSON):",
531
- toml: "\n\nInput Schema (TOML):",
532
- auto: "\n\nInput Schema (JSON):"
533
- // auto defaults to JSON schema display
534
- };
535
- const schemaMarker = schemaMarkers[parameterFormat];
530
+ const instruction = gadget.getInstruction(this.argPrefix);
531
+ const schemaMarker = "\n\nInput Schema (BLOCK):";
536
532
  const schemaIndex = instruction.indexOf(schemaMarker);
537
533
  const description = (schemaIndex !== -1 ? instruction.substring(0, schemaIndex) : instruction).trim();
538
534
  const schema = schemaIndex !== -1 ? instruction.substring(schemaIndex + schemaMarker.length).trim() : "";
@@ -543,35 +539,20 @@ ${description}`);
543
539
  if (schema) {
544
540
  parts.push(`
545
541
 
546
- PARAMETERS (${parameterFormat.toUpperCase()}):
542
+ PARAMETERS (BLOCK):
547
543
  ${schema}`);
548
544
  }
549
545
  parts.push("\n\n---");
550
546
  }
551
547
  return parts.join("");
552
548
  }
553
- buildUsageSection(parameterFormat, context) {
549
+ buildUsageSection(context) {
554
550
  const parts = [];
555
- const formatDescriptionMap = {
556
- yaml: {
557
- config: this.promptConfig.formatDescriptionYaml,
558
- defaultValue: DEFAULT_PROMPTS.formatDescriptionYaml
559
- },
560
- json: {
561
- config: this.promptConfig.formatDescriptionJson,
562
- defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
563
- },
564
- toml: {
565
- config: this.promptConfig.formatDescriptionToml,
566
- defaultValue: DEFAULT_PROMPTS.formatDescriptionToml
567
- },
568
- auto: {
569
- config: this.promptConfig.formatDescriptionJson,
570
- defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
571
- }
572
- };
573
- const { config, defaultValue } = formatDescriptionMap[parameterFormat];
574
- const formatDescription = resolvePromptTemplate(config, defaultValue, context);
551
+ const formatDescription = resolvePromptTemplate(
552
+ this.promptConfig.formatDescription,
553
+ DEFAULT_PROMPTS.formatDescription,
554
+ context
555
+ );
575
556
  parts.push("\n\nHOW TO INVOKE GADGETS");
576
557
  parts.push("\n=====================\n");
577
558
  const criticalUsage = resolvePromptTemplate(
@@ -589,124 +570,90 @@ CRITICAL: ${criticalUsage}
589
570
  2. ${formatDescription}`);
590
571
  parts.push(`
591
572
  3. End marker: ${this.endPrefix}`);
592
- parts.push(this.buildExamplesSection(parameterFormat, context));
573
+ parts.push(this.buildExamplesSection(context));
593
574
  parts.push(this.buildRulesSection(context));
594
575
  parts.push("\n");
595
576
  return parts.join("");
596
577
  }
597
- buildExamplesSection(parameterFormat, context) {
578
+ buildExamplesSection(context) {
598
579
  if (this.promptConfig.customExamples) {
599
580
  return this.promptConfig.customExamples(context);
600
581
  }
601
582
  const parts = [];
602
- const singleExamples = {
603
- yaml: `${this.startPrefix}translate
604
- from: English
605
- to: Polish
606
- content: "Paris is the capital of France: a beautiful city."
607
- ${this.endPrefix}`,
608
- json: `${this.startPrefix}translate
609
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
610
- ${this.endPrefix}`,
611
- toml: `${this.startPrefix}translate
612
- from = "English"
613
- to = "Polish"
614
- content = "Paris is the capital of France: a beautiful city."
615
- ${this.endPrefix}`,
616
- auto: `${this.startPrefix}translate
617
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
618
- ${this.endPrefix}`
619
- };
583
+ const singleExample = `${this.startPrefix}translate
584
+ ${this.argPrefix}from
585
+ English
586
+ ${this.argPrefix}to
587
+ Polish
588
+ ${this.argPrefix}content
589
+ Paris is the capital of France: a beautiful city.
590
+ ${this.endPrefix}`;
620
591
  parts.push(`
621
592
 
622
593
  EXAMPLE (Single Gadget):
623
594
 
624
- ${singleExamples[parameterFormat]}`);
625
- const multipleExamples = {
626
- yaml: `${this.startPrefix}translate
627
- from: English
628
- to: Polish
629
- content: "Paris is the capital of France: a beautiful city."
595
+ ${singleExample}`);
596
+ const multipleExample = `${this.startPrefix}translate
597
+ ${this.argPrefix}from
598
+ English
599
+ ${this.argPrefix}to
600
+ Polish
601
+ ${this.argPrefix}content
602
+ Paris is the capital of France: a beautiful city.
630
603
  ${this.endPrefix}
631
604
  ${this.startPrefix}analyze
632
- type: economic_analysis
633
- matter: "Polish Economy"
634
- question: <<<EOF
605
+ ${this.argPrefix}type
606
+ economic_analysis
607
+ ${this.argPrefix}matter
608
+ Polish Economy
609
+ ${this.argPrefix}question
635
610
  Analyze the following:
636
611
  - Polish arms exports 2025
637
612
  - Economic implications
638
- EOF
639
- ${this.endPrefix}`,
640
- json: `${this.startPrefix}translate
641
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
642
- ${this.endPrefix}
643
- ${this.startPrefix}analyze
644
- {"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
645
- ${this.endPrefix}`,
646
- toml: `${this.startPrefix}translate
647
- from = "English"
648
- to = "Polish"
649
- content = "Paris is the capital of France: a beautiful city."
650
- ${this.endPrefix}
651
- ${this.startPrefix}analyze
652
- type = "economic_analysis"
653
- matter = "Polish Economy"
654
- question = <<<EOF
655
- Analyze the following:
656
- - Polish arms exports 2025
657
- - Economic implications
658
- EOF
659
- ${this.endPrefix}`,
660
- auto: `${this.startPrefix}translate
661
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
662
- ${this.endPrefix}
663
- ${this.startPrefix}analyze
664
- {"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
665
- ${this.endPrefix}`
666
- };
613
+ ${this.endPrefix}`;
667
614
  parts.push(`
668
615
 
669
616
  EXAMPLE (Multiple Gadgets):
670
617
 
671
- ${multipleExamples[parameterFormat]}`);
672
- if (parameterFormat === "yaml") {
673
- parts.push(`
674
-
675
- YAML HEREDOC SYNTAX:
676
- For string values with multiple lines, use heredoc syntax (<<<DELIMITER...DELIMITER):
618
+ ${multipleExample}`);
619
+ parts.push(`
677
620
 
678
- filePath: "README.md"
679
- content: <<<EOF
680
- # Project Title
621
+ BLOCK FORMAT SYNTAX:
622
+ Block format uses ${this.argPrefix}name markers. Values are captured verbatim until the next marker.
681
623
 
682
- This content can contain:
683
- - Markdown lists
684
- - Special characters: # : -
685
- - Multiple paragraphs
686
- EOF
624
+ ${this.argPrefix}filename
625
+ calculator.ts
626
+ ${this.argPrefix}code
627
+ class Calculator {
628
+ private history: string[] = [];
687
629
 
688
- The delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.
689
- No indentation is required for the content.`);
690
- } else if (parameterFormat === "toml") {
691
- parts.push(`
692
-
693
- TOML HEREDOC SYNTAX:
694
- For string values with multiple lines, use heredoc syntax (<<<DELIMITER...DELIMITER):
630
+ add(a: number, b: number): number {
631
+ const result = a + b;
632
+ this.history.push(\`\${a} + \${b} = \${result}\`);
633
+ return result;
634
+ }
635
+ }
695
636
 
696
- filePath = "README.md"
697
- content = <<<EOF
698
- # Project Title
637
+ BLOCK FORMAT RULES:
638
+ - Each parameter starts with ${this.argPrefix}parameterName on its own line
639
+ - The value starts on the NEXT line after the marker
640
+ - Value ends when the next ${this.argPrefix} or ${this.endPrefix} appears
641
+ - NO escaping needed - write values exactly as they should appear
642
+ - Perfect for code, JSON, markdown, or any content with special characters
699
643
 
700
- This content can contain:
701
- - Markdown lists
702
- - Special characters: # : -
703
- - Multiple paragraphs
704
- EOF
644
+ NESTED OBJECTS (use / separator):
645
+ ${this.argPrefix}config/timeout
646
+ 30
647
+ ${this.argPrefix}config/retries
648
+ 3
649
+ Produces: { "config": { "timeout": "30", "retries": "3" } }
705
650
 
706
- The delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.
707
- IMPORTANT: Content inside heredoc is LITERAL - do NOT escape backticks, dollar signs, or any characters.
708
- NEVER use TOML triple-quote strings ("""). ALWAYS use heredoc syntax (<<<EOF...EOF) for multiline content.`);
709
- }
651
+ ARRAYS (use numeric indices):
652
+ ${this.argPrefix}items/0
653
+ first
654
+ ${this.argPrefix}items/1
655
+ second
656
+ Produces: { "items": ["first", "second"] }`);
710
657
  return parts.join("");
711
658
  }
712
659
  buildRulesSection(context) {
@@ -727,8 +674,8 @@ NEVER use TOML triple-quote strings ("""). ALWAYS use heredoc syntax (<<<EOF...E
727
674
  this.messages.push({ role: "assistant", content, metadata });
728
675
  return this;
729
676
  }
730
- addGadgetCall(gadget, parameters, result, parameterFormat = "json") {
731
- const paramStr = this.formatParameters(parameters, parameterFormat);
677
+ addGadgetCall(gadget, parameters, result) {
678
+ const paramStr = this.formatBlockParameters(parameters, "");
732
679
  this.messages.push({
733
680
  role: "assistant",
734
681
  content: `${this.startPrefix}${gadget}
@@ -741,26 +688,32 @@ ${this.endPrefix}`
741
688
  });
742
689
  return this;
743
690
  }
744
- formatParameters(parameters, format) {
745
- if (format === "yaml") {
746
- return Object.entries(parameters).map(([key, value]) => {
747
- if (typeof value === "string") {
748
- return `${key}: ${value}`;
749
- }
750
- return `${key}: ${JSON.stringify(value)}`;
751
- }).join("\n");
752
- }
753
- if (format === "toml") {
754
- return Object.entries(parameters).map(([key, value]) => {
755
- if (typeof value === "string" && value.includes("\n")) {
756
- return `${key} = <<<EOF
757
- ${value}
758
- EOF`;
759
- }
760
- return `${key} = ${JSON.stringify(value)}`;
761
- }).join("\n");
691
+ /**
692
+ * Format parameters as Block format with JSON Pointer paths.
693
+ * Uses the configured argPrefix for consistency with system prompt.
694
+ */
695
+ formatBlockParameters(params, prefix) {
696
+ const lines = [];
697
+ for (const [key, value] of Object.entries(params)) {
698
+ const fullPath = prefix ? `${prefix}/${key}` : key;
699
+ if (Array.isArray(value)) {
700
+ value.forEach((item, index) => {
701
+ const itemPath = `${fullPath}/${index}`;
702
+ if (typeof item === "object" && item !== null) {
703
+ lines.push(this.formatBlockParameters(item, itemPath));
704
+ } else {
705
+ lines.push(`${this.argPrefix}${itemPath}`);
706
+ lines.push(String(item));
707
+ }
708
+ });
709
+ } else if (typeof value === "object" && value !== null) {
710
+ lines.push(this.formatBlockParameters(value, fullPath));
711
+ } else {
712
+ lines.push(`${this.argPrefix}${fullPath}`);
713
+ lines.push(String(value));
714
+ }
762
715
  }
763
- return JSON.stringify(parameters);
716
+ return lines.join("\n");
764
717
  }
765
718
  build() {
766
719
  return [...this.messages];
@@ -853,134 +806,72 @@ var init_schema_to_json = __esm({
853
806
  });
854
807
 
855
808
  // src/gadgets/gadget.ts
856
- function findSafeDelimiter(content) {
857
- const lines = content.split("\n");
858
- for (const delimiter of HEREDOC_DELIMITERS) {
859
- const regex = new RegExp(`^${delimiter}\\s*$`);
860
- const isUsed = lines.some((line) => regex.test(line));
861
- if (!isUsed) {
862
- return delimiter;
863
- }
864
- }
865
- let counter = 1;
866
- while (counter < 1e3) {
867
- const delimiter = `__GADGET_PARAM_${counter}__`;
868
- const regex = new RegExp(`^${delimiter}\\s*$`);
869
- const isUsed = lines.some((line) => regex.test(line));
870
- if (!isUsed) {
871
- return delimiter;
872
- }
873
- counter++;
874
- }
875
- return "HEREDOC_FALLBACK";
876
- }
877
- function formatYamlValue(value, indent = "") {
878
- if (typeof value === "string") {
879
- const lines = value.split("\n");
880
- if (lines.length === 1 && !value.includes(":") && !value.startsWith("-")) {
881
- return value;
882
- }
883
- const delimiter = findSafeDelimiter(value);
884
- return `<<<${delimiter}
885
- ${value}
886
- ${delimiter}`;
887
- }
888
- if (typeof value === "number" || typeof value === "boolean") {
889
- return String(value);
890
- }
891
- if (value === null || value === void 0) {
892
- return "null";
893
- }
894
- if (Array.isArray(value)) {
895
- if (value.length === 0) return "[]";
896
- const items = value.map((item) => `${indent}- ${formatYamlValue(item, indent + " ")}`);
897
- return "\n" + items.join("\n");
898
- }
899
- if (typeof value === "object") {
900
- const entries = Object.entries(value);
901
- if (entries.length === 0) return "{}";
902
- const lines = entries.map(([k, v]) => {
903
- const formattedValue = formatYamlValue(v, indent + " ");
904
- if (formattedValue.startsWith("\n") || formattedValue.startsWith("|")) {
905
- return `${indent}${k}: ${formattedValue}`;
906
- }
907
- return `${indent}${k}: ${formattedValue}`;
908
- });
909
- return "\n" + lines.join("\n");
910
- }
911
- return yaml.dump(value).trimEnd();
912
- }
913
- function formatParamsAsYaml(params) {
809
+ function formatParamsAsBlock(params, prefix = "", argPrefix = GADGET_ARG_PREFIX) {
914
810
  const lines = [];
915
811
  for (const [key, value] of Object.entries(params)) {
916
- const formattedValue = formatYamlValue(value, "");
917
- if (formattedValue.startsWith("\n")) {
918
- lines.push(`${key}:${formattedValue}`);
812
+ const fullPath = prefix ? `${prefix}/${key}` : key;
813
+ if (Array.isArray(value)) {
814
+ value.forEach((item, index) => {
815
+ const itemPath = `${fullPath}/${index}`;
816
+ if (typeof item === "object" && item !== null) {
817
+ lines.push(formatParamsAsBlock(item, itemPath, argPrefix));
818
+ } else {
819
+ lines.push(`${argPrefix}${itemPath}`);
820
+ lines.push(String(item));
821
+ }
822
+ });
823
+ } else if (typeof value === "object" && value !== null) {
824
+ lines.push(formatParamsAsBlock(value, fullPath, argPrefix));
919
825
  } else {
920
- lines.push(`${key}: ${formattedValue}`);
826
+ lines.push(`${argPrefix}${fullPath}`);
827
+ lines.push(String(value));
921
828
  }
922
829
  }
923
830
  return lines.join("\n");
924
831
  }
925
- function formatTomlInlineTable(obj) {
926
- const entries = Object.entries(obj).map(([k, v]) => `${k} = ${formatTomlValue(v)}`);
927
- return `{ ${entries.join(", ")} }`;
928
- }
929
- function formatTomlValue(value) {
930
- if (typeof value === "string") {
931
- if (value.includes("\n")) {
932
- const delimiter = findSafeDelimiter(value);
933
- return `<<<${delimiter}
934
- ${value}
935
- ${delimiter}`;
936
- }
937
- return JSON.stringify(value);
938
- }
939
- if (typeof value === "number" || typeof value === "boolean") {
940
- return String(value);
941
- }
942
- if (value === null || value === void 0) {
943
- return '""';
944
- }
945
- if (Array.isArray(value)) {
946
- if (value.length === 0) return "[]";
947
- const items = value.map((item) => {
948
- if (typeof item === "object" && item !== null && !Array.isArray(item)) {
949
- return formatTomlInlineTable(item);
950
- }
951
- return formatTomlValue(item);
952
- });
953
- return `[${items.join(", ")}]`;
954
- }
955
- if (typeof value === "object") {
956
- return formatTomlInlineTable(value);
957
- }
958
- return JSON.stringify(value);
959
- }
960
- function formatParamsAsToml(params) {
832
+ function formatSchemaAsPlainText(schema, indent = "") {
961
833
  const lines = [];
962
- for (const [key, value] of Object.entries(params)) {
963
- lines.push(`${key} = ${formatTomlValue(value)}`);
834
+ const properties = schema.properties || {};
835
+ const required = schema.required || [];
836
+ for (const [key, prop] of Object.entries(properties)) {
837
+ const propObj = prop;
838
+ const type = propObj.type;
839
+ const description = propObj.description;
840
+ const isRequired = required.includes(key);
841
+ const enumValues = propObj.enum;
842
+ let line = `${indent}- ${key}`;
843
+ if (type === "array") {
844
+ const items = propObj.items;
845
+ const itemType = items?.type || "any";
846
+ line += ` (array of ${itemType})`;
847
+ } else if (type === "object" && propObj.properties) {
848
+ line += " (object)";
849
+ } else {
850
+ line += ` (${type})`;
851
+ }
852
+ if (isRequired) {
853
+ line += " [required]";
854
+ }
855
+ if (description) {
856
+ line += `: ${description}`;
857
+ }
858
+ if (enumValues) {
859
+ line += ` - one of: ${enumValues.map((v) => `"${v}"`).join(", ")}`;
860
+ }
861
+ lines.push(line);
862
+ if (type === "object" && propObj.properties) {
863
+ lines.push(formatSchemaAsPlainText(propObj, indent + " "));
864
+ }
964
865
  }
965
866
  return lines.join("\n");
966
867
  }
967
- var yaml, HEREDOC_DELIMITERS, BaseGadget;
868
+ var BaseGadget;
968
869
  var init_gadget = __esm({
969
870
  "src/gadgets/gadget.ts"() {
970
871
  "use strict";
971
- yaml = __toESM(require("js-yaml"), 1);
872
+ init_constants();
972
873
  init_schema_to_json();
973
874
  init_schema_validator();
974
- HEREDOC_DELIMITERS = [
975
- "__GADGET_PARAM_EOF__",
976
- "__GADGET_PARAM_END__",
977
- "__GADGET_PARAM_DOC__",
978
- "__GADGET_PARAM_CONTENT__",
979
- "__GADGET_PARAM_TEXT__",
980
- "__GADGET_PARAM_HEREDOC__",
981
- "__GADGET_PARAM_DATA__",
982
- "__GADGET_PARAM_BLOCK__"
983
- ];
984
875
  BaseGadget = class {
985
876
  /**
986
877
  * The name of the gadget. Used for identification when LLM calls it.
@@ -1011,19 +902,19 @@ var init_gadget = __esm({
1011
902
  /**
1012
903
  * Auto-generated instruction text for the LLM.
1013
904
  * Combines name, description, and parameter schema into a formatted instruction.
1014
- * @deprecated Use getInstruction(format) instead for format-specific schemas
905
+ * @deprecated Use getInstruction() instead
1015
906
  */
1016
907
  get instruction() {
1017
- return this.getInstruction("yaml");
908
+ return this.getInstruction();
1018
909
  }
1019
910
  /**
1020
- * Generate instruction text for the LLM with format-specific schema.
911
+ * Generate instruction text for the LLM.
1021
912
  * Combines name, description, and parameter schema into a formatted instruction.
1022
913
  *
1023
- * @param format - Format for the schema representation ('json' | 'yaml' | 'toml' | 'auto')
914
+ * @param argPrefix - Optional custom argument prefix for block format examples
1024
915
  * @returns Formatted instruction string
1025
916
  */
1026
- getInstruction(format = "json") {
917
+ getInstruction(argPrefix) {
1027
918
  const parts = [];
1028
919
  parts.push(this.description);
1029
920
  if (this.parameterSchema) {
@@ -1032,20 +923,12 @@ var init_gadget = __esm({
1032
923
  const jsonSchema = schemaToJSONSchema(this.parameterSchema, {
1033
924
  target: "draft-7"
1034
925
  });
1035
- if (format === "json" || format === "auto") {
1036
- parts.push("\n\nInput Schema (JSON):");
1037
- parts.push(JSON.stringify(jsonSchema, null, 2));
1038
- } else if (format === "toml") {
1039
- parts.push("\n\nInput Schema (TOML):");
1040
- parts.push(JSON.stringify(jsonSchema, null, 2));
1041
- } else {
1042
- const yamlSchema = yaml.dump(jsonSchema).trimEnd();
1043
- parts.push("\n\nInput Schema (YAML):");
1044
- parts.push(yamlSchema);
1045
- }
926
+ parts.push("\n\nParameters:");
927
+ parts.push(formatSchemaAsPlainText(jsonSchema));
1046
928
  }
1047
929
  if (this.examples && this.examples.length > 0) {
1048
930
  parts.push("\n\nExamples:");
931
+ const effectiveArgPrefix = argPrefix ?? GADGET_ARG_PREFIX;
1049
932
  this.examples.forEach((example, index) => {
1050
933
  if (index > 0) {
1051
934
  parts.push("");
@@ -1054,13 +937,7 @@ var init_gadget = __esm({
1054
937
  parts.push(`# ${example.comment}`);
1055
938
  }
1056
939
  parts.push("Input:");
1057
- if (format === "json" || format === "auto") {
1058
- parts.push(JSON.stringify(example.params, null, 2));
1059
- } else if (format === "toml") {
1060
- parts.push(formatParamsAsToml(example.params));
1061
- } else {
1062
- parts.push(formatParamsAsYaml(example.params));
1063
- }
940
+ parts.push(formatParamsAsBlock(example.params, "", effectiveArgPrefix));
1064
941
  if (example.output !== void 0) {
1065
942
  parts.push("Output:");
1066
943
  parts.push(example.output);
@@ -1337,14 +1214,12 @@ var init_conversation_manager = __esm({
1337
1214
  baseMessages;
1338
1215
  initialMessages;
1339
1216
  historyBuilder;
1340
- parameterFormat;
1341
1217
  constructor(baseMessages, initialMessages, options = {}) {
1342
1218
  this.baseMessages = baseMessages;
1343
1219
  this.initialMessages = initialMessages;
1344
- this.parameterFormat = options.parameterFormat ?? "json";
1345
1220
  this.historyBuilder = new LLMMessageBuilder();
1346
1221
  if (options.startPrefix && options.endPrefix) {
1347
- this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix);
1222
+ this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix, options.argPrefix);
1348
1223
  }
1349
1224
  }
1350
1225
  addUserMessage(content) {
@@ -1354,7 +1229,7 @@ var init_conversation_manager = __esm({
1354
1229
  this.historyBuilder.addAssistant(content);
1355
1230
  }
1356
1231
  addGadgetCall(gadgetName, parameters, result) {
1357
- this.historyBuilder.addGadgetCall(gadgetName, parameters, result, this.parameterFormat);
1232
+ this.historyBuilder.addGadgetCall(gadgetName, parameters, result);
1358
1233
  }
1359
1234
  getMessages() {
1360
1235
  return [...this.baseMessages, ...this.initialMessages, ...this.historyBuilder.build()];
@@ -1377,7 +1252,7 @@ async function runWithHandlers(agentGenerator, handlers) {
1377
1252
  await handlers.onGadgetCall({
1378
1253
  gadgetName: event.call.gadgetName,
1379
1254
  parameters: event.call.parameters,
1380
- parametersYaml: event.call.parametersYaml
1255
+ parametersRaw: event.call.parametersRaw
1381
1256
  });
1382
1257
  }
1383
1258
  break;
@@ -1571,6 +1446,89 @@ var init_hook_validators = __esm({
1571
1446
  }
1572
1447
  });
1573
1448
 
1449
+ // src/gadgets/error-formatter.ts
1450
+ var GadgetErrorFormatter;
1451
+ var init_error_formatter = __esm({
1452
+ "src/gadgets/error-formatter.ts"() {
1453
+ "use strict";
1454
+ init_constants();
1455
+ GadgetErrorFormatter = class {
1456
+ argPrefix;
1457
+ startPrefix;
1458
+ endPrefix;
1459
+ constructor(options = {}) {
1460
+ this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;
1461
+ this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;
1462
+ this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;
1463
+ }
1464
+ /**
1465
+ * Format a Zod validation error with full gadget instructions.
1466
+ *
1467
+ * @param gadgetName - Name of the gadget that was called
1468
+ * @param zodError - The Zod validation error
1469
+ * @param gadget - The gadget instance (for generating instructions)
1470
+ * @returns Formatted error message with usage instructions
1471
+ */
1472
+ formatValidationError(gadgetName, zodError, gadget) {
1473
+ const parts = [];
1474
+ parts.push(`Error: Invalid parameters for '${gadgetName}':`);
1475
+ for (const issue of zodError.issues) {
1476
+ const path = issue.path.join(".") || "root";
1477
+ parts.push(` - ${path}: ${issue.message}`);
1478
+ }
1479
+ parts.push("");
1480
+ parts.push("Gadget Usage:");
1481
+ parts.push(gadget.getInstruction(this.argPrefix));
1482
+ return parts.join("\n");
1483
+ }
1484
+ /**
1485
+ * Format a parse error with block format reference.
1486
+ *
1487
+ * @param gadgetName - Name of the gadget that was called
1488
+ * @param parseError - The parse error message
1489
+ * @param gadget - The gadget instance if found (for generating instructions)
1490
+ * @returns Formatted error message with format reference
1491
+ */
1492
+ formatParseError(gadgetName, parseError, gadget) {
1493
+ const parts = [];
1494
+ parts.push(`Error: Failed to parse parameters for '${gadgetName}':`);
1495
+ parts.push(` ${parseError}`);
1496
+ if (gadget) {
1497
+ parts.push("");
1498
+ parts.push("Gadget Usage:");
1499
+ parts.push(gadget.getInstruction(this.argPrefix));
1500
+ }
1501
+ parts.push("");
1502
+ parts.push("Block Format Reference:");
1503
+ parts.push(` ${this.startPrefix}${gadgetName}`);
1504
+ parts.push(` ${this.argPrefix}parameterName`);
1505
+ parts.push(" parameter value here");
1506
+ parts.push(` ${this.endPrefix}`);
1507
+ return parts.join("\n");
1508
+ }
1509
+ /**
1510
+ * Format a registry error (gadget not found) with available gadgets list.
1511
+ *
1512
+ * @param gadgetName - Name of the gadget that was not found
1513
+ * @param availableGadgets - List of available gadget names
1514
+ * @returns Formatted error message with available gadgets
1515
+ */
1516
+ formatRegistryError(gadgetName, availableGadgets) {
1517
+ const parts = [];
1518
+ parts.push(`Error: Gadget '${gadgetName}' not found.`);
1519
+ if (availableGadgets.length > 0) {
1520
+ parts.push("");
1521
+ parts.push(`Available gadgets: ${availableGadgets.join(", ")}`);
1522
+ } else {
1523
+ parts.push("");
1524
+ parts.push("No gadgets are currently registered.");
1525
+ }
1526
+ return parts.join("\n");
1527
+ }
1528
+ };
1529
+ }
1530
+ });
1531
+
1574
1532
  // src/gadgets/exceptions.ts
1575
1533
  var BreakLoopException, HumanInputException, TimeoutException;
1576
1534
  var init_exceptions = __esm({
@@ -1609,15 +1567,18 @@ var init_executor = __esm({
1609
1567
  "src/gadgets/executor.ts"() {
1610
1568
  "use strict";
1611
1569
  init_logger();
1570
+ init_error_formatter();
1612
1571
  init_exceptions();
1613
1572
  GadgetExecutor = class {
1614
- constructor(registry, onHumanInputRequired, logger, defaultGadgetTimeoutMs) {
1573
+ constructor(registry, onHumanInputRequired, logger, defaultGadgetTimeoutMs, errorFormatterOptions) {
1615
1574
  this.registry = registry;
1616
1575
  this.onHumanInputRequired = onHumanInputRequired;
1617
1576
  this.defaultGadgetTimeoutMs = defaultGadgetTimeoutMs;
1618
1577
  this.logger = logger ?? createLogger({ name: "llmist:executor" });
1578
+ this.errorFormatter = new GadgetErrorFormatter(errorFormatterOptions);
1619
1579
  }
1620
1580
  logger;
1581
+ errorFormatter;
1621
1582
  /**
1622
1583
  * Creates a promise that rejects with a TimeoutException after the specified timeout.
1623
1584
  */
@@ -1642,11 +1603,12 @@ var init_executor = __esm({
1642
1603
  const gadget = this.registry.get(call.gadgetName);
1643
1604
  if (!gadget) {
1644
1605
  this.logger.error("Gadget not found", { gadgetName: call.gadgetName });
1606
+ const availableGadgets = this.registry.getNames();
1645
1607
  return {
1646
1608
  gadgetName: call.gadgetName,
1647
1609
  invocationId: call.invocationId,
1648
1610
  parameters: call.parameters ?? {},
1649
- error: `Gadget '${call.gadgetName}' not found in registry`,
1611
+ error: this.errorFormatter.formatRegistryError(call.gadgetName, availableGadgets),
1650
1612
  executionTimeMs: Date.now() - startTime
1651
1613
  };
1652
1614
  }
@@ -1654,27 +1616,28 @@ var init_executor = __esm({
1654
1616
  this.logger.error("Gadget parameter parse error", {
1655
1617
  gadgetName: call.gadgetName,
1656
1618
  parseError: call.parseError,
1657
- rawParameters: call.parametersYaml
1619
+ rawParameters: call.parametersRaw
1658
1620
  });
1621
+ const parseErrorMessage = call.parseError ?? "Failed to parse parameters";
1659
1622
  return {
1660
1623
  gadgetName: call.gadgetName,
1661
1624
  invocationId: call.invocationId,
1662
1625
  parameters: {},
1663
- error: call.parseError ?? "Failed to parse parameters",
1626
+ error: this.errorFormatter.formatParseError(call.gadgetName, parseErrorMessage, gadget),
1664
1627
  executionTimeMs: Date.now() - startTime
1665
1628
  };
1666
1629
  }
1667
1630
  if (gadget.parameterSchema) {
1668
1631
  const validationResult = gadget.parameterSchema.safeParse(rawParameters);
1669
1632
  if (!validationResult.success) {
1670
- const formattedIssues = validationResult.error.issues.map((issue) => {
1671
- const path = issue.path.join(".") || "root";
1672
- return `${path}: ${issue.message}`;
1673
- }).join("; ");
1674
- const validationError = `Invalid parameters: ${formattedIssues}`;
1633
+ const validationError = this.errorFormatter.formatValidationError(
1634
+ call.gadgetName,
1635
+ validationResult.error,
1636
+ gadget
1637
+ );
1675
1638
  this.logger.error("Gadget parameter validation failed", {
1676
1639
  gadgetName: call.gadgetName,
1677
- error: validationError
1640
+ issueCount: validationResult.error.issues.length
1678
1641
  });
1679
1642
  return {
1680
1643
  gadgetName: call.gadgetName,
@@ -1816,168 +1779,107 @@ var init_executor = __esm({
1816
1779
  }
1817
1780
  });
1818
1781
 
1819
- // src/gadgets/parser.ts
1820
- function preprocessYaml(yamlStr) {
1821
- const lines = yamlStr.split("\n");
1822
- const result = [];
1823
- let i = 0;
1824
- while (i < lines.length) {
1825
- const line = lines[i];
1826
- const heredocMatch = line.match(/^(\s*)([\w-]+):\s*<<<([A-Za-z_][A-Za-z0-9_]*)\s*$/);
1827
- if (heredocMatch) {
1828
- const [, indent, key, delimiter] = heredocMatch;
1829
- const bodyLines = [];
1830
- i++;
1831
- const closingRegex = new RegExp(`^${delimiter}\\s*$`);
1832
- while (i < lines.length && !closingRegex.test(lines[i])) {
1833
- bodyLines.push(lines[i]);
1834
- i++;
1835
- }
1836
- if (i < lines.length) {
1837
- i++;
1838
- }
1839
- result.push(`${indent}${key}: |`);
1840
- for (const bodyLine of bodyLines) {
1841
- result.push(`${indent} ${bodyLine}`);
1782
+ // src/gadgets/block-params.ts
1783
+ function parseBlockParams(content, options) {
1784
+ const argPrefix = options?.argPrefix ?? GADGET_ARG_PREFIX;
1785
+ const result = {};
1786
+ const seenPointers = /* @__PURE__ */ new Set();
1787
+ const parts = content.split(argPrefix);
1788
+ for (let i = 1; i < parts.length; i++) {
1789
+ const part = parts[i];
1790
+ const newlineIndex = part.indexOf("\n");
1791
+ if (newlineIndex === -1) {
1792
+ const pointer2 = part.trim();
1793
+ if (pointer2) {
1794
+ if (seenPointers.has(pointer2)) {
1795
+ throw new Error(`Duplicate pointer: ${pointer2}`);
1796
+ }
1797
+ seenPointers.add(pointer2);
1798
+ setByPointer(result, pointer2, "");
1842
1799
  }
1843
1800
  continue;
1844
1801
  }
1845
- const match = line.match(/^(\s*)([\w-]+):\s+(.+)$/);
1846
- if (match) {
1847
- const [, indent, key, value] = match;
1848
- if (value === "|" || value === ">" || value === "|-" || value === ">-") {
1849
- result.push(line);
1850
- i++;
1851
- const keyIndentLen2 = indent.length;
1852
- const blockLines = [];
1853
- let minContentIndent = Infinity;
1854
- while (i < lines.length) {
1855
- const blockLine = lines[i];
1856
- const blockIndentMatch = blockLine.match(/^(\s*)/);
1857
- const blockIndentLen = blockIndentMatch ? blockIndentMatch[1].length : 0;
1858
- if (blockLine.trim() === "") {
1859
- blockLines.push({ content: "", originalIndent: 0 });
1860
- i++;
1861
- continue;
1862
- }
1863
- if (blockIndentLen > keyIndentLen2) {
1864
- const content = blockLine.substring(blockIndentLen);
1865
- blockLines.push({ content, originalIndent: blockIndentLen });
1866
- if (content.trim().length > 0) {
1867
- minContentIndent = Math.min(minContentIndent, blockIndentLen);
1868
- }
1869
- i++;
1870
- } else {
1871
- break;
1872
- }
1873
- }
1874
- const targetIndent = keyIndentLen2 + 2;
1875
- for (const blockLine of blockLines) {
1876
- if (blockLine.content === "") {
1877
- result.push("");
1878
- } else {
1879
- result.push(" ".repeat(targetIndent) + blockLine.content);
1880
- }
1881
- }
1882
- continue;
1883
- }
1884
- if (value.startsWith('"') || value.startsWith("'") || value === "true" || value === "false" || /^-?\d+(\.\d+)?$/.test(value)) {
1885
- result.push(line);
1886
- i++;
1887
- continue;
1888
- }
1889
- const keyIndentLen = indent.length;
1890
- const continuationLines = [];
1891
- let j = i + 1;
1892
- while (j < lines.length) {
1893
- const nextLine = lines[j];
1894
- if (nextLine.trim() === "") {
1895
- continuationLines.push(nextLine);
1896
- j++;
1897
- continue;
1898
- }
1899
- const nextIndentMatch = nextLine.match(/^(\s*)/);
1900
- const nextIndentLen = nextIndentMatch ? nextIndentMatch[1].length : 0;
1901
- if (nextIndentLen > keyIndentLen) {
1902
- continuationLines.push(nextLine);
1903
- j++;
1904
- } else {
1905
- break;
1906
- }
1907
- }
1908
- if (continuationLines.length > 0 && continuationLines.some((l) => l.trim().length > 0)) {
1909
- result.push(`${indent}${key}: |`);
1910
- result.push(`${indent} ${value}`);
1911
- for (const contLine of continuationLines) {
1912
- if (contLine.trim() === "") {
1913
- result.push("");
1914
- } else {
1915
- const contIndentMatch = contLine.match(/^(\s*)/);
1916
- const contIndent = contIndentMatch ? contIndentMatch[1] : "";
1917
- const contContent = contLine.substring(contIndent.length);
1918
- result.push(`${indent} ${contContent}`);
1919
- }
1920
- }
1921
- i = j;
1922
- continue;
1923
- }
1924
- if (value.includes(": ") || value.endsWith(":")) {
1925
- const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
1926
- result.push(`${indent}${key}: "${escaped}"`);
1927
- i++;
1928
- continue;
1929
- }
1802
+ const pointer = part.substring(0, newlineIndex).trim();
1803
+ let value = part.substring(newlineIndex + 1);
1804
+ if (value.endsWith("\n")) {
1805
+ value = value.slice(0, -1);
1930
1806
  }
1931
- result.push(line);
1932
- i++;
1807
+ if (!pointer) {
1808
+ continue;
1809
+ }
1810
+ if (seenPointers.has(pointer)) {
1811
+ throw new Error(`Duplicate pointer: ${pointer}`);
1812
+ }
1813
+ seenPointers.add(pointer);
1814
+ setByPointer(result, pointer, value);
1933
1815
  }
1934
- return result.join("\n");
1816
+ return result;
1935
1817
  }
1936
- function unescapeHeredocContent(content) {
1937
- return content.replace(/\\`/g, "`").replace(/\\\$/g, "$").replace(/\\{/g, "{").replace(/\\}/g, "}");
1818
+ function coerceValue(value) {
1819
+ if (value.includes("\n")) {
1820
+ return value;
1821
+ }
1822
+ const trimmed = value.trim();
1823
+ if (trimmed === "true") return true;
1824
+ if (trimmed === "false") return false;
1825
+ if (trimmed !== "" && /^-?\d+(\.\d+)?$/.test(trimmed)) {
1826
+ const num = Number(trimmed);
1827
+ if (!isNaN(num) && isFinite(num)) {
1828
+ return num;
1829
+ }
1830
+ }
1831
+ return value;
1938
1832
  }
1939
- function preprocessTomlHeredoc(tomlStr) {
1940
- const lines = tomlStr.split("\n");
1941
- const result = [];
1942
- let i = 0;
1943
- const heredocStartRegex = /^(\s*)([\w-]+)\s*=\s*<<<([A-Za-z_][A-Za-z0-9_]*)\s*$/;
1944
- while (i < lines.length) {
1945
- const line = lines[i];
1946
- const match = line.match(heredocStartRegex);
1947
- if (match) {
1948
- const [, indent, key, delimiter] = match;
1949
- const bodyLines = [];
1950
- i++;
1951
- const closingRegex = new RegExp(`^${delimiter}\\s*$`);
1952
- let foundClosing = false;
1953
- while (i < lines.length) {
1954
- const bodyLine = lines[i];
1955
- if (closingRegex.test(bodyLine)) {
1956
- foundClosing = true;
1957
- i++;
1958
- break;
1959
- }
1960
- bodyLines.push(bodyLine);
1961
- i++;
1962
- }
1963
- if (bodyLines.length === 0) {
1964
- result.push(`${indent}${key} = ''''''`);
1965
- } else {
1966
- result.push(`${indent}${key} = '''`);
1967
- for (let j = 0; j < bodyLines.length - 1; j++) {
1968
- result.push(unescapeHeredocContent(bodyLines[j]));
1969
- }
1970
- result.push(`${unescapeHeredocContent(bodyLines[bodyLines.length - 1])}'''`);
1971
- }
1972
- if (!foundClosing) {
1833
+ function setByPointer(obj, pointer, value) {
1834
+ const segments = pointer.split("/");
1835
+ let current = obj;
1836
+ for (let i = 0; i < segments.length - 1; i++) {
1837
+ const segment = segments[i];
1838
+ const nextSegment = segments[i + 1];
1839
+ const nextIsArrayIndex = /^\d+$/.test(nextSegment);
1840
+ if (Array.isArray(current)) {
1841
+ const index = parseInt(segment, 10);
1842
+ if (isNaN(index) || index < 0) {
1843
+ throw new Error(`Invalid array index: ${segment}`);
1844
+ }
1845
+ if (index > current.length) {
1846
+ throw new Error(`Array index gap: expected ${current.length}, got ${index}`);
1847
+ }
1848
+ if (current[index] === void 0) {
1849
+ current[index] = nextIsArrayIndex ? [] : {};
1850
+ }
1851
+ current = current[index];
1852
+ } else {
1853
+ const rec = current;
1854
+ if (rec[segment] === void 0) {
1855
+ rec[segment] = nextIsArrayIndex ? [] : {};
1973
1856
  }
1974
- continue;
1857
+ current = rec[segment];
1858
+ }
1859
+ }
1860
+ const lastSegment = segments[segments.length - 1];
1861
+ const coercedValue = coerceValue(value);
1862
+ if (Array.isArray(current)) {
1863
+ const index = parseInt(lastSegment, 10);
1864
+ if (isNaN(index) || index < 0) {
1865
+ throw new Error(`Invalid array index: ${lastSegment}`);
1866
+ }
1867
+ if (index > current.length) {
1868
+ throw new Error(`Array index gap: expected ${current.length}, got ${index}`);
1975
1869
  }
1976
- result.push(line);
1977
- i++;
1870
+ current[index] = coercedValue;
1871
+ } else {
1872
+ current[lastSegment] = coercedValue;
1978
1873
  }
1979
- return result.join("\n");
1980
1874
  }
1875
+ var init_block_params = __esm({
1876
+ "src/gadgets/block-params.ts"() {
1877
+ "use strict";
1878
+ init_constants();
1879
+ }
1880
+ });
1881
+
1882
+ // src/gadgets/parser.ts
1981
1883
  function stripMarkdownFences(content) {
1982
1884
  let cleaned = content.trim();
1983
1885
  const openingFence = /^```(?:toml|yaml|json)?\s*\n/i;
@@ -1986,24 +1888,23 @@ function stripMarkdownFences(content) {
1986
1888
  cleaned = cleaned.replace(closingFence, "");
1987
1889
  return cleaned.trim();
1988
1890
  }
1989
- var yaml2, import_js_toml, globalInvocationCounter, StreamParser;
1891
+ var globalInvocationCounter, StreamParser;
1990
1892
  var init_parser = __esm({
1991
1893
  "src/gadgets/parser.ts"() {
1992
1894
  "use strict";
1993
- yaml2 = __toESM(require("js-yaml"), 1);
1994
- import_js_toml = require("js-toml");
1995
1895
  init_constants();
1896
+ init_block_params();
1996
1897
  globalInvocationCounter = 0;
1997
1898
  StreamParser = class {
1998
1899
  buffer = "";
1999
1900
  lastReportedTextLength = 0;
2000
1901
  startPrefix;
2001
1902
  endPrefix;
2002
- parameterFormat;
1903
+ argPrefix;
2003
1904
  constructor(options = {}) {
2004
1905
  this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;
2005
1906
  this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;
2006
- this.parameterFormat = options.parameterFormat ?? "json";
1907
+ this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;
2007
1908
  }
2008
1909
  takeTextUntil(index) {
2009
1910
  if (index <= this.lastReportedTextLength) {
@@ -2025,56 +1926,22 @@ var init_parser = __esm({
2025
1926
  return { actualName: gadgetName, invocationId: `gadget_${++globalInvocationCounter}` };
2026
1927
  }
2027
1928
  /**
2028
- * Truncate verbose parse errors to avoid context overflow.
2029
- * Keeps first meaningful line and limits total length.
1929
+ * Extract the error message from a parse error.
1930
+ * Preserves full message since the error formatter adds contextual help
1931
+ * that benefits from precise, detailed error information.
2030
1932
  */
2031
- truncateParseError(error, format) {
2032
- const message = error instanceof Error ? error.message : String(error);
2033
- const firstLine = message.split("\n")[0];
2034
- const maxLen = 200;
2035
- if (firstLine.length <= maxLen) {
2036
- return firstLine;
2037
- }
2038
- return `${firstLine.slice(0, maxLen)}... (${message.length} chars total)`;
1933
+ extractParseError(error) {
1934
+ return error instanceof Error ? error.message : String(error);
2039
1935
  }
2040
1936
  /**
2041
- * Parse parameter string according to configured format
1937
+ * Parse parameter string using block format
2042
1938
  */
2043
1939
  parseParameters(raw) {
2044
1940
  const cleaned = stripMarkdownFences(raw);
2045
- if (this.parameterFormat === "json") {
2046
- try {
2047
- return { parameters: JSON.parse(cleaned) };
2048
- } catch (error) {
2049
- return { parseError: this.truncateParseError(error, "JSON") };
2050
- }
2051
- }
2052
- if (this.parameterFormat === "yaml") {
2053
- try {
2054
- return { parameters: yaml2.load(preprocessYaml(cleaned)) };
2055
- } catch (error) {
2056
- return { parseError: this.truncateParseError(error, "YAML") };
2057
- }
2058
- }
2059
- if (this.parameterFormat === "toml") {
2060
- try {
2061
- return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(cleaned)) };
2062
- } catch (error) {
2063
- return { parseError: this.truncateParseError(error, "TOML") };
2064
- }
2065
- }
2066
1941
  try {
2067
- return { parameters: JSON.parse(cleaned) };
2068
- } catch {
2069
- try {
2070
- return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(cleaned)) };
2071
- } catch {
2072
- try {
2073
- return { parameters: yaml2.load(preprocessYaml(cleaned)) };
2074
- } catch (error) {
2075
- return { parseError: this.truncateParseError(error, "auto") };
2076
- }
2077
- }
1942
+ return { parameters: parseBlockParams(cleaned, { argPrefix: this.argPrefix }) };
1943
+ } catch (error) {
1944
+ return { parseError: this.extractParseError(error) };
2078
1945
  }
2079
1946
  }
2080
1947
  // Feed a chunk of text and get parsed events
@@ -2133,8 +2000,7 @@ var init_parser = __esm({
2133
2000
  call: {
2134
2001
  gadgetName: actualGadgetName,
2135
2002
  invocationId,
2136
- parametersYaml: parametersRaw,
2137
- // Keep property name for backward compatibility
2003
+ parametersRaw,
2138
2004
  parameters,
2139
2005
  parseError
2140
2006
  }
@@ -2168,7 +2034,7 @@ var init_parser = __esm({
2168
2034
  call: {
2169
2035
  gadgetName: actualGadgetName,
2170
2036
  invocationId,
2171
- parametersYaml: parametersRaw,
2037
+ parametersRaw,
2172
2038
  parameters,
2173
2039
  parseError
2174
2040
  }
@@ -2219,9 +2085,9 @@ var init_stream_processor = __esm({
2219
2085
  this.stopOnGadgetError = options.stopOnGadgetError ?? true;
2220
2086
  this.shouldContinueAfterError = options.shouldContinueAfterError;
2221
2087
  this.parser = new StreamParser({
2222
- parameterFormat: options.parameterFormat,
2223
2088
  startPrefix: options.gadgetStartPrefix,
2224
- endPrefix: options.gadgetEndPrefix
2089
+ endPrefix: options.gadgetEndPrefix,
2090
+ argPrefix: options.gadgetArgPrefix
2225
2091
  });
2226
2092
  this.executor = new GadgetExecutor(
2227
2093
  options.registry,
@@ -2375,7 +2241,7 @@ var init_stream_processor = __esm({
2375
2241
  this.logger.warn("Gadget has parse error", {
2376
2242
  gadgetName: call.gadgetName,
2377
2243
  error: call.parseError,
2378
- rawParameters: call.parametersYaml
2244
+ rawParameters: call.parametersRaw
2379
2245
  });
2380
2246
  const shouldContinue = await this.checkContinueAfterError(
2381
2247
  call.parseError,
@@ -2611,9 +2477,9 @@ var init_agent = __esm({
2611
2477
  hooks;
2612
2478
  conversation;
2613
2479
  registry;
2614
- parameterFormat;
2615
2480
  gadgetStartPrefix;
2616
2481
  gadgetEndPrefix;
2482
+ gadgetArgPrefix;
2617
2483
  onHumanInputRequired;
2618
2484
  textOnlyHandler;
2619
2485
  textWithGadgetsHandler;
@@ -2642,9 +2508,9 @@ var init_agent = __esm({
2642
2508
  this.temperature = options.temperature;
2643
2509
  this.logger = options.logger ?? createLogger({ name: "llmist:agent" });
2644
2510
  this.registry = options.registry;
2645
- this.parameterFormat = options.parameterFormat ?? "json";
2646
2511
  this.gadgetStartPrefix = options.gadgetStartPrefix;
2647
2512
  this.gadgetEndPrefix = options.gadgetEndPrefix;
2513
+ this.gadgetArgPrefix = options.gadgetArgPrefix;
2648
2514
  this.onHumanInputRequired = options.onHumanInputRequired;
2649
2515
  this.textOnlyHandler = options.textOnlyHandler ?? "terminate";
2650
2516
  this.textWithGadgetsHandler = options.textWithGadgetsHandler;
@@ -2666,9 +2532,10 @@ var init_agent = __esm({
2666
2532
  if (options.systemPrompt) {
2667
2533
  baseBuilder.addSystem(options.systemPrompt);
2668
2534
  }
2669
- baseBuilder.addGadgets(this.registry.getAll(), this.parameterFormat, {
2535
+ baseBuilder.addGadgets(this.registry.getAll(), {
2670
2536
  startPrefix: options.gadgetStartPrefix,
2671
- endPrefix: options.gadgetEndPrefix
2537
+ endPrefix: options.gadgetEndPrefix,
2538
+ argPrefix: options.gadgetArgPrefix
2672
2539
  });
2673
2540
  const baseMessages = baseBuilder.build();
2674
2541
  const initialMessages = (options.initialMessages ?? []).map((message) => ({
@@ -2676,9 +2543,9 @@ var init_agent = __esm({
2676
2543
  content: message.content
2677
2544
  }));
2678
2545
  this.conversation = new ConversationManager(baseMessages, initialMessages, {
2679
- parameterFormat: this.parameterFormat,
2680
2546
  startPrefix: options.gadgetStartPrefix,
2681
- endPrefix: options.gadgetEndPrefix
2547
+ endPrefix: options.gadgetEndPrefix,
2548
+ argPrefix: options.gadgetArgPrefix
2682
2549
  });
2683
2550
  this.userPromptProvided = !!options.userPrompt;
2684
2551
  if (options.userPrompt) {
@@ -2771,9 +2638,9 @@ var init_agent = __esm({
2771
2638
  const processor = new StreamProcessor({
2772
2639
  iteration: currentIteration,
2773
2640
  registry: this.registry,
2774
- parameterFormat: this.parameterFormat,
2775
2641
  gadgetStartPrefix: this.gadgetStartPrefix,
2776
2642
  gadgetEndPrefix: this.gadgetEndPrefix,
2643
+ gadgetArgPrefix: this.gadgetArgPrefix,
2777
2644
  hooks: this.hooks,
2778
2645
  logger: this.logger.getSubLogger({ name: "stream-processor" }),
2779
2646
  onHumanInputRequired: this.onHumanInputRequired,
@@ -3066,9 +2933,9 @@ var init_builder = __esm({
3066
2933
  gadgets = [];
3067
2934
  initialMessages = [];
3068
2935
  onHumanInputRequired;
3069
- parameterFormat;
3070
2936
  gadgetStartPrefix;
3071
2937
  gadgetEndPrefix;
2938
+ gadgetArgPrefix;
3072
2939
  textOnlyHandler;
3073
2940
  textWithGadgetsHandler;
3074
2941
  stopOnGadgetError;
@@ -3255,21 +3122,6 @@ var init_builder = __esm({
3255
3122
  this.onHumanInputRequired = handler;
3256
3123
  return this;
3257
3124
  }
3258
- /**
3259
- * Set the parameter format for gadget calls.
3260
- *
3261
- * @param format - Parameter format ("json" or "xml")
3262
- * @returns This builder for chaining
3263
- *
3264
- * @example
3265
- * ```typescript
3266
- * .withParameterFormat("xml")
3267
- * ```
3268
- */
3269
- withParameterFormat(format) {
3270
- this.parameterFormat = format;
3271
- return this;
3272
- }
3273
3125
  /**
3274
3126
  * Set custom gadget marker prefix.
3275
3127
  *
@@ -3300,6 +3152,21 @@ var init_builder = __esm({
3300
3152
  this.gadgetEndPrefix = suffix;
3301
3153
  return this;
3302
3154
  }
3155
+ /**
3156
+ * Set custom argument prefix for block format parameters.
3157
+ *
3158
+ * @param prefix - Custom prefix for argument markers (default: "!!!ARG:")
3159
+ * @returns This builder for chaining
3160
+ *
3161
+ * @example
3162
+ * ```typescript
3163
+ * .withGadgetArgPrefix("<<ARG>>")
3164
+ * ```
3165
+ */
3166
+ withGadgetArgPrefix(prefix) {
3167
+ this.gadgetArgPrefix = prefix;
3168
+ return this;
3169
+ }
3303
3170
  /**
3304
3171
  * Set the text-only handler strategy.
3305
3172
  *
@@ -3499,8 +3366,7 @@ var init_builder = __esm({
3499
3366
  withSyntheticGadgetCall(gadgetName, parameters, result) {
3500
3367
  const startPrefix = this.gadgetStartPrefix ?? GADGET_START_PREFIX;
3501
3368
  const endPrefix = this.gadgetEndPrefix ?? GADGET_END_PREFIX;
3502
- const format = this.parameterFormat ?? "yaml";
3503
- const paramStr = this.formatSyntheticParameters(parameters, format);
3369
+ const paramStr = this.formatBlockParameters(parameters, "");
3504
3370
  this.initialMessages.push({
3505
3371
  role: "assistant",
3506
3372
  content: `${startPrefix}${gadgetName}
@@ -3514,25 +3380,31 @@ ${endPrefix}`
3514
3380
  return this;
3515
3381
  }
3516
3382
  /**
3517
- * Format parameters for synthetic gadget calls.
3518
- * Uses heredoc for multiline string values.
3383
+ * Format parameters as block format with JSON Pointer paths.
3519
3384
  */
3520
- formatSyntheticParameters(parameters, format) {
3521
- if (format === "json" || format === "auto") {
3522
- return JSON.stringify(parameters);
3523
- }
3524
- return Object.entries(parameters).map(([key, value]) => {
3525
- if (typeof value === "string" && value.includes("\n")) {
3526
- const separator = format === "yaml" ? ":" : " =";
3527
- return `${key}${separator} <<<EOF
3528
- ${value}
3529
- EOF`;
3530
- }
3531
- if (format === "yaml") {
3532
- return typeof value === "string" ? `${key}: ${value}` : `${key}: ${JSON.stringify(value)}`;
3385
+ formatBlockParameters(params, prefix) {
3386
+ const lines = [];
3387
+ const argPrefix = this.gadgetArgPrefix ?? GADGET_ARG_PREFIX;
3388
+ for (const [key, value] of Object.entries(params)) {
3389
+ const fullPath = prefix ? `${prefix}/${key}` : key;
3390
+ if (Array.isArray(value)) {
3391
+ value.forEach((item, index) => {
3392
+ const itemPath = `${fullPath}/${index}`;
3393
+ if (typeof item === "object" && item !== null) {
3394
+ lines.push(this.formatBlockParameters(item, itemPath));
3395
+ } else {
3396
+ lines.push(`${argPrefix}${itemPath}`);
3397
+ lines.push(String(item));
3398
+ }
3399
+ });
3400
+ } else if (typeof value === "object" && value !== null) {
3401
+ lines.push(this.formatBlockParameters(value, fullPath));
3402
+ } else {
3403
+ lines.push(`${argPrefix}${fullPath}`);
3404
+ lines.push(String(value));
3533
3405
  }
3534
- return `${key} = ${JSON.stringify(value)}`;
3535
- }).join("\n");
3406
+ }
3407
+ return lines.join("\n");
3536
3408
  }
3537
3409
  /**
3538
3410
  * Build and create the agent with the given user prompt.
@@ -3572,9 +3444,9 @@ EOF`;
3572
3444
  promptConfig: this.promptConfig,
3573
3445
  initialMessages: this.initialMessages,
3574
3446
  onHumanInputRequired: this.onHumanInputRequired,
3575
- parameterFormat: this.parameterFormat,
3576
3447
  gadgetStartPrefix: this.gadgetStartPrefix,
3577
3448
  gadgetEndPrefix: this.gadgetEndPrefix,
3449
+ gadgetArgPrefix: this.gadgetArgPrefix,
3578
3450
  textOnlyHandler: this.textOnlyHandler,
3579
3451
  textWithGadgetsHandler: this.textWithGadgetsHandler,
3580
3452
  stopOnGadgetError: this.stopOnGadgetError,
@@ -3674,9 +3546,9 @@ EOF`;
3674
3546
  promptConfig: this.promptConfig,
3675
3547
  initialMessages: this.initialMessages,
3676
3548
  onHumanInputRequired: this.onHumanInputRequired,
3677
- parameterFormat: this.parameterFormat,
3678
3549
  gadgetStartPrefix: this.gadgetStartPrefix,
3679
3550
  gadgetEndPrefix: this.gadgetEndPrefix,
3551
+ gadgetArgPrefix: this.gadgetArgPrefix,
3680
3552
  textOnlyHandler: this.textOnlyHandler,
3681
3553
  textWithGadgetsHandler: this.textWithGadgetsHandler,
3682
3554
  stopOnGadgetError: this.stopOnGadgetError,
@@ -5944,17 +5816,51 @@ function splitIntoChunks(text, minChunkSize = 5, maxChunkSize = 30) {
5944
5816
  }
5945
5817
  return chunks;
5946
5818
  }
5819
+ function serializeToBlockFormat(obj, prefix = "") {
5820
+ let result = "";
5821
+ for (const [key, value] of Object.entries(obj)) {
5822
+ const pointer = prefix ? `${prefix}/${key}` : key;
5823
+ if (value === null || value === void 0) {
5824
+ continue;
5825
+ }
5826
+ if (Array.isArray(value)) {
5827
+ for (let i = 0; i < value.length; i++) {
5828
+ const item = value[i];
5829
+ const itemPointer = `${pointer}/${i}`;
5830
+ if (typeof item === "object" && item !== null && !Array.isArray(item)) {
5831
+ result += serializeToBlockFormat(item, itemPointer);
5832
+ } else if (Array.isArray(item)) {
5833
+ for (let j = 0; j < item.length; j++) {
5834
+ result += `${GADGET_ARG_PREFIX}${itemPointer}/${j}
5835
+ ${String(item[j])}
5836
+ `;
5837
+ }
5838
+ } else {
5839
+ result += `${GADGET_ARG_PREFIX}${itemPointer}
5840
+ ${String(item)}
5841
+ `;
5842
+ }
5843
+ }
5844
+ } else if (typeof value === "object") {
5845
+ result += serializeToBlockFormat(value, pointer);
5846
+ } else {
5847
+ result += `${GADGET_ARG_PREFIX}${pointer}
5848
+ ${String(value)}
5849
+ `;
5850
+ }
5851
+ }
5852
+ return result;
5853
+ }
5947
5854
  function formatGadgetCalls(gadgetCalls) {
5948
5855
  let text = "";
5949
5856
  const calls = [];
5950
5857
  for (const call of gadgetCalls) {
5951
5858
  const invocationId = call.invocationId ?? generateInvocationId();
5952
5859
  calls.push({ name: call.gadgetName, invocationId });
5953
- const paramsJson = JSON.stringify(call.parameters);
5860
+ const blockParams = serializeToBlockFormat(call.parameters);
5954
5861
  text += `
5955
5862
  ${GADGET_START_PREFIX}${call.gadgetName}
5956
- ${paramsJson}
5957
- ${GADGET_END_PREFIX}`;
5863
+ ${blockParams}${GADGET_END_PREFIX}`;
5958
5864
  }
5959
5865
  return { text, calls };
5960
5866
  }