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.
@@ -360,29 +360,25 @@ var init_prompt_config = __esm({
360
360
  "EACH MARKER MUST START WITH A NEWLINE."
361
361
  ].join("\n"),
362
362
  criticalUsage: "INVOKE gadgets using the markers - do not describe what you want to do.",
363
- formatDescriptionYaml: "Parameters in YAML format (one per line)",
364
- formatDescriptionJson: "Parameters in JSON format (valid JSON object)",
365
- formatDescriptionToml: "Parameters in TOML format (key = value pairs, use heredoc for multiline: key = <<<EOF ... EOF)",
363
+ formatDescription: (ctx) => `Parameters using ${ctx.argPrefix}name markers (value on next line(s), no escaping needed)`,
366
364
  rules: () => [
367
365
  "Output ONLY plain text with the exact markers - never use function/tool calling",
368
366
  "You can invoke multiple gadgets in a single response",
369
367
  "For dependent gadgets, invoke the first one and wait for the result"
370
368
  ],
371
- schemaLabelJson: "\n\nInput Schema (JSON):",
372
- schemaLabelYaml: "\n\nInput Schema (YAML):",
373
- schemaLabelToml: "\n\nInput Schema (TOML):",
374
369
  customExamples: null
375
370
  };
376
371
  }
377
372
  });
378
373
 
379
374
  // src/core/constants.ts
380
- var GADGET_START_PREFIX, GADGET_END_PREFIX, DEFAULT_GADGET_OUTPUT_LIMIT, DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT, CHARS_PER_TOKEN, FALLBACK_CONTEXT_WINDOW;
375
+ 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;
381
376
  var init_constants = __esm({
382
377
  "src/core/constants.ts"() {
383
378
  "use strict";
384
379
  GADGET_START_PREFIX = "!!!GADGET_START:";
385
380
  GADGET_END_PREFIX = "!!!GADGET_END";
381
+ GADGET_ARG_PREFIX = "!!!ARG:";
386
382
  DEFAULT_GADGET_OUTPUT_LIMIT = true;
387
383
  DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;
388
384
  CHARS_PER_TOKEN = 4;
@@ -401,6 +397,7 @@ var init_messages = __esm({
401
397
  messages = [];
402
398
  startPrefix = GADGET_START_PREFIX;
403
399
  endPrefix = GADGET_END_PREFIX;
400
+ argPrefix = GADGET_ARG_PREFIX;
404
401
  promptConfig;
405
402
  constructor(promptConfig) {
406
403
  this.promptConfig = promptConfig ?? {};
@@ -409,26 +406,32 @@ var init_messages = __esm({
409
406
  * Set custom prefixes for gadget markers.
410
407
  * Used to configure history builder to match system prompt markers.
411
408
  */
412
- withPrefixes(startPrefix, endPrefix) {
409
+ withPrefixes(startPrefix, endPrefix, argPrefix) {
413
410
  this.startPrefix = startPrefix;
414
411
  this.endPrefix = endPrefix;
412
+ if (argPrefix) {
413
+ this.argPrefix = argPrefix;
414
+ }
415
415
  return this;
416
416
  }
417
417
  addSystem(content, metadata) {
418
418
  this.messages.push({ role: "system", content, metadata });
419
419
  return this;
420
420
  }
421
- addGadgets(gadgets, parameterFormat = "json", options) {
421
+ addGadgets(gadgets, options) {
422
422
  if (options?.startPrefix) {
423
423
  this.startPrefix = options.startPrefix;
424
424
  }
425
425
  if (options?.endPrefix) {
426
426
  this.endPrefix = options.endPrefix;
427
427
  }
428
+ if (options?.argPrefix) {
429
+ this.argPrefix = options.argPrefix;
430
+ }
428
431
  const context = {
429
- parameterFormat,
430
432
  startPrefix: this.startPrefix,
431
433
  endPrefix: this.endPrefix,
434
+ argPrefix: this.argPrefix,
432
435
  gadgetCount: gadgets.length,
433
436
  gadgetNames: gadgets.map((g) => g.name ?? g.constructor.name)
434
437
  };
@@ -439,26 +442,19 @@ var init_messages = __esm({
439
442
  context
440
443
  );
441
444
  parts.push(mainInstruction);
442
- parts.push(this.buildGadgetsSection(gadgets, parameterFormat));
443
- parts.push(this.buildUsageSection(parameterFormat, context));
445
+ parts.push(this.buildGadgetsSection(gadgets));
446
+ parts.push(this.buildUsageSection(context));
444
447
  this.messages.push({ role: "system", content: parts.join("") });
445
448
  return this;
446
449
  }
447
- buildGadgetsSection(gadgets, parameterFormat) {
450
+ buildGadgetsSection(gadgets) {
448
451
  const parts = [];
449
452
  parts.push("\n\nAVAILABLE GADGETS");
450
453
  parts.push("\n=================\n");
451
454
  for (const gadget of gadgets) {
452
455
  const gadgetName = gadget.name ?? gadget.constructor.name;
453
- const instruction = gadget.getInstruction(parameterFormat);
454
- const schemaMarkers = {
455
- yaml: "\n\nInput Schema (YAML):",
456
- json: "\n\nInput Schema (JSON):",
457
- toml: "\n\nInput Schema (TOML):",
458
- auto: "\n\nInput Schema (JSON):"
459
- // auto defaults to JSON schema display
460
- };
461
- const schemaMarker = schemaMarkers[parameterFormat];
456
+ const instruction = gadget.getInstruction(this.argPrefix);
457
+ const schemaMarker = "\n\nInput Schema (BLOCK):";
462
458
  const schemaIndex = instruction.indexOf(schemaMarker);
463
459
  const description = (schemaIndex !== -1 ? instruction.substring(0, schemaIndex) : instruction).trim();
464
460
  const schema = schemaIndex !== -1 ? instruction.substring(schemaIndex + schemaMarker.length).trim() : "";
@@ -469,35 +465,20 @@ ${description}`);
469
465
  if (schema) {
470
466
  parts.push(`
471
467
 
472
- PARAMETERS (${parameterFormat.toUpperCase()}):
468
+ PARAMETERS (BLOCK):
473
469
  ${schema}`);
474
470
  }
475
471
  parts.push("\n\n---");
476
472
  }
477
473
  return parts.join("");
478
474
  }
479
- buildUsageSection(parameterFormat, context) {
475
+ buildUsageSection(context) {
480
476
  const parts = [];
481
- const formatDescriptionMap = {
482
- yaml: {
483
- config: this.promptConfig.formatDescriptionYaml,
484
- defaultValue: DEFAULT_PROMPTS.formatDescriptionYaml
485
- },
486
- json: {
487
- config: this.promptConfig.formatDescriptionJson,
488
- defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
489
- },
490
- toml: {
491
- config: this.promptConfig.formatDescriptionToml,
492
- defaultValue: DEFAULT_PROMPTS.formatDescriptionToml
493
- },
494
- auto: {
495
- config: this.promptConfig.formatDescriptionJson,
496
- defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
497
- }
498
- };
499
- const { config, defaultValue } = formatDescriptionMap[parameterFormat];
500
- const formatDescription = resolvePromptTemplate(config, defaultValue, context);
477
+ const formatDescription = resolvePromptTemplate(
478
+ this.promptConfig.formatDescription,
479
+ DEFAULT_PROMPTS.formatDescription,
480
+ context
481
+ );
501
482
  parts.push("\n\nHOW TO INVOKE GADGETS");
502
483
  parts.push("\n=====================\n");
503
484
  const criticalUsage = resolvePromptTemplate(
@@ -515,124 +496,90 @@ CRITICAL: ${criticalUsage}
515
496
  2. ${formatDescription}`);
516
497
  parts.push(`
517
498
  3. End marker: ${this.endPrefix}`);
518
- parts.push(this.buildExamplesSection(parameterFormat, context));
499
+ parts.push(this.buildExamplesSection(context));
519
500
  parts.push(this.buildRulesSection(context));
520
501
  parts.push("\n");
521
502
  return parts.join("");
522
503
  }
523
- buildExamplesSection(parameterFormat, context) {
504
+ buildExamplesSection(context) {
524
505
  if (this.promptConfig.customExamples) {
525
506
  return this.promptConfig.customExamples(context);
526
507
  }
527
508
  const parts = [];
528
- const singleExamples = {
529
- yaml: `${this.startPrefix}translate
530
- from: English
531
- to: Polish
532
- content: "Paris is the capital of France: a beautiful city."
533
- ${this.endPrefix}`,
534
- json: `${this.startPrefix}translate
535
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
536
- ${this.endPrefix}`,
537
- toml: `${this.startPrefix}translate
538
- from = "English"
539
- to = "Polish"
540
- content = "Paris is the capital of France: a beautiful city."
541
- ${this.endPrefix}`,
542
- auto: `${this.startPrefix}translate
543
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
544
- ${this.endPrefix}`
545
- };
509
+ const singleExample = `${this.startPrefix}translate
510
+ ${this.argPrefix}from
511
+ English
512
+ ${this.argPrefix}to
513
+ Polish
514
+ ${this.argPrefix}content
515
+ Paris is the capital of France: a beautiful city.
516
+ ${this.endPrefix}`;
546
517
  parts.push(`
547
518
 
548
519
  EXAMPLE (Single Gadget):
549
520
 
550
- ${singleExamples[parameterFormat]}`);
551
- const multipleExamples = {
552
- yaml: `${this.startPrefix}translate
553
- from: English
554
- to: Polish
555
- content: "Paris is the capital of France: a beautiful city."
521
+ ${singleExample}`);
522
+ const multipleExample = `${this.startPrefix}translate
523
+ ${this.argPrefix}from
524
+ English
525
+ ${this.argPrefix}to
526
+ Polish
527
+ ${this.argPrefix}content
528
+ Paris is the capital of France: a beautiful city.
556
529
  ${this.endPrefix}
557
530
  ${this.startPrefix}analyze
558
- type: economic_analysis
559
- matter: "Polish Economy"
560
- question: <<<EOF
531
+ ${this.argPrefix}type
532
+ economic_analysis
533
+ ${this.argPrefix}matter
534
+ Polish Economy
535
+ ${this.argPrefix}question
561
536
  Analyze the following:
562
537
  - Polish arms exports 2025
563
538
  - Economic implications
564
- EOF
565
- ${this.endPrefix}`,
566
- json: `${this.startPrefix}translate
567
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
568
- ${this.endPrefix}
569
- ${this.startPrefix}analyze
570
- {"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
571
- ${this.endPrefix}`,
572
- toml: `${this.startPrefix}translate
573
- from = "English"
574
- to = "Polish"
575
- content = "Paris is the capital of France: a beautiful city."
576
- ${this.endPrefix}
577
- ${this.startPrefix}analyze
578
- type = "economic_analysis"
579
- matter = "Polish Economy"
580
- question = <<<EOF
581
- Analyze the following:
582
- - Polish arms exports 2025
583
- - Economic implications
584
- EOF
585
- ${this.endPrefix}`,
586
- auto: `${this.startPrefix}translate
587
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
588
- ${this.endPrefix}
589
- ${this.startPrefix}analyze
590
- {"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
591
- ${this.endPrefix}`
592
- };
539
+ ${this.endPrefix}`;
593
540
  parts.push(`
594
541
 
595
542
  EXAMPLE (Multiple Gadgets):
596
543
 
597
- ${multipleExamples[parameterFormat]}`);
598
- if (parameterFormat === "yaml") {
599
- parts.push(`
600
-
601
- YAML HEREDOC SYNTAX:
602
- For string values with multiple lines, use heredoc syntax (<<<DELIMITER...DELIMITER):
603
-
604
- filePath: "README.md"
605
- content: <<<EOF
606
- # Project Title
544
+ ${multipleExample}`);
545
+ parts.push(`
607
546
 
608
- This content can contain:
609
- - Markdown lists
610
- - Special characters: # : -
611
- - Multiple paragraphs
612
- EOF
547
+ BLOCK FORMAT SYNTAX:
548
+ Block format uses ${this.argPrefix}name markers. Values are captured verbatim until the next marker.
613
549
 
614
- The delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.
615
- No indentation is required for the content.`);
616
- } else if (parameterFormat === "toml") {
617
- parts.push(`
550
+ ${this.argPrefix}filename
551
+ calculator.ts
552
+ ${this.argPrefix}code
553
+ class Calculator {
554
+ private history: string[] = [];
618
555
 
619
- TOML HEREDOC SYNTAX:
620
- For string values with multiple lines, use heredoc syntax (<<<DELIMITER...DELIMITER):
556
+ add(a: number, b: number): number {
557
+ const result = a + b;
558
+ this.history.push(\`\${a} + \${b} = \${result}\`);
559
+ return result;
560
+ }
561
+ }
621
562
 
622
- filePath = "README.md"
623
- content = <<<EOF
624
- # Project Title
563
+ BLOCK FORMAT RULES:
564
+ - Each parameter starts with ${this.argPrefix}parameterName on its own line
565
+ - The value starts on the NEXT line after the marker
566
+ - Value ends when the next ${this.argPrefix} or ${this.endPrefix} appears
567
+ - NO escaping needed - write values exactly as they should appear
568
+ - Perfect for code, JSON, markdown, or any content with special characters
625
569
 
626
- This content can contain:
627
- - Markdown lists
628
- - Special characters: # : -
629
- - Multiple paragraphs
630
- EOF
570
+ NESTED OBJECTS (use / separator):
571
+ ${this.argPrefix}config/timeout
572
+ 30
573
+ ${this.argPrefix}config/retries
574
+ 3
575
+ Produces: { "config": { "timeout": "30", "retries": "3" } }
631
576
 
632
- The delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.
633
- IMPORTANT: Content inside heredoc is LITERAL - do NOT escape backticks, dollar signs, or any characters.
634
- NEVER use TOML triple-quote strings ("""). ALWAYS use heredoc syntax (<<<EOF...EOF) for multiline content.`);
635
- }
577
+ ARRAYS (use numeric indices):
578
+ ${this.argPrefix}items/0
579
+ first
580
+ ${this.argPrefix}items/1
581
+ second
582
+ Produces: { "items": ["first", "second"] }`);
636
583
  return parts.join("");
637
584
  }
638
585
  buildRulesSection(context) {
@@ -653,8 +600,8 @@ NEVER use TOML triple-quote strings ("""). ALWAYS use heredoc syntax (<<<EOF...E
653
600
  this.messages.push({ role: "assistant", content, metadata });
654
601
  return this;
655
602
  }
656
- addGadgetCall(gadget, parameters, result, parameterFormat = "json") {
657
- const paramStr = this.formatParameters(parameters, parameterFormat);
603
+ addGadgetCall(gadget, parameters, result) {
604
+ const paramStr = this.formatBlockParameters(parameters, "");
658
605
  this.messages.push({
659
606
  role: "assistant",
660
607
  content: `${this.startPrefix}${gadget}
@@ -667,26 +614,32 @@ ${this.endPrefix}`
667
614
  });
668
615
  return this;
669
616
  }
670
- formatParameters(parameters, format) {
671
- if (format === "yaml") {
672
- return Object.entries(parameters).map(([key, value]) => {
673
- if (typeof value === "string") {
674
- return `${key}: ${value}`;
675
- }
676
- return `${key}: ${JSON.stringify(value)}`;
677
- }).join("\n");
678
- }
679
- if (format === "toml") {
680
- return Object.entries(parameters).map(([key, value]) => {
681
- if (typeof value === "string" && value.includes("\n")) {
682
- return `${key} = <<<EOF
683
- ${value}
684
- EOF`;
685
- }
686
- return `${key} = ${JSON.stringify(value)}`;
687
- }).join("\n");
617
+ /**
618
+ * Format parameters as Block format with JSON Pointer paths.
619
+ * Uses the configured argPrefix for consistency with system prompt.
620
+ */
621
+ formatBlockParameters(params, prefix) {
622
+ const lines = [];
623
+ for (const [key, value] of Object.entries(params)) {
624
+ const fullPath = prefix ? `${prefix}/${key}` : key;
625
+ if (Array.isArray(value)) {
626
+ value.forEach((item, index) => {
627
+ const itemPath = `${fullPath}/${index}`;
628
+ if (typeof item === "object" && item !== null) {
629
+ lines.push(this.formatBlockParameters(item, itemPath));
630
+ } else {
631
+ lines.push(`${this.argPrefix}${itemPath}`);
632
+ lines.push(String(item));
633
+ }
634
+ });
635
+ } else if (typeof value === "object" && value !== null) {
636
+ lines.push(this.formatBlockParameters(value, fullPath));
637
+ } else {
638
+ lines.push(`${this.argPrefix}${fullPath}`);
639
+ lines.push(String(value));
640
+ }
688
641
  }
689
- return JSON.stringify(parameters);
642
+ return lines.join("\n");
690
643
  }
691
644
  build() {
692
645
  return [...this.messages];
@@ -857,134 +810,72 @@ var init_schema_to_json = __esm({
857
810
  });
858
811
 
859
812
  // src/gadgets/gadget.ts
860
- import * as yaml from "js-yaml";
861
- function findSafeDelimiter(content) {
862
- const lines = content.split("\n");
863
- for (const delimiter of HEREDOC_DELIMITERS) {
864
- const regex = new RegExp(`^${delimiter}\\s*$`);
865
- const isUsed = lines.some((line) => regex.test(line));
866
- if (!isUsed) {
867
- return delimiter;
868
- }
869
- }
870
- let counter = 1;
871
- while (counter < 1e3) {
872
- const delimiter = `__GADGET_PARAM_${counter}__`;
873
- const regex = new RegExp(`^${delimiter}\\s*$`);
874
- const isUsed = lines.some((line) => regex.test(line));
875
- if (!isUsed) {
876
- return delimiter;
877
- }
878
- counter++;
879
- }
880
- return "HEREDOC_FALLBACK";
881
- }
882
- function formatYamlValue(value, indent = "") {
883
- if (typeof value === "string") {
884
- const lines = value.split("\n");
885
- if (lines.length === 1 && !value.includes(":") && !value.startsWith("-")) {
886
- return value;
887
- }
888
- const delimiter = findSafeDelimiter(value);
889
- return `<<<${delimiter}
890
- ${value}
891
- ${delimiter}`;
892
- }
893
- if (typeof value === "number" || typeof value === "boolean") {
894
- return String(value);
895
- }
896
- if (value === null || value === void 0) {
897
- return "null";
898
- }
899
- if (Array.isArray(value)) {
900
- if (value.length === 0) return "[]";
901
- const items = value.map((item) => `${indent}- ${formatYamlValue(item, indent + " ")}`);
902
- return "\n" + items.join("\n");
903
- }
904
- if (typeof value === "object") {
905
- const entries = Object.entries(value);
906
- if (entries.length === 0) return "{}";
907
- const lines = entries.map(([k, v]) => {
908
- const formattedValue = formatYamlValue(v, indent + " ");
909
- if (formattedValue.startsWith("\n") || formattedValue.startsWith("|")) {
910
- return `${indent}${k}: ${formattedValue}`;
911
- }
912
- return `${indent}${k}: ${formattedValue}`;
913
- });
914
- return "\n" + lines.join("\n");
915
- }
916
- return yaml.dump(value).trimEnd();
917
- }
918
- function formatParamsAsYaml(params) {
813
+ function formatParamsAsBlock(params, prefix = "", argPrefix = GADGET_ARG_PREFIX) {
919
814
  const lines = [];
920
815
  for (const [key, value] of Object.entries(params)) {
921
- const formattedValue = formatYamlValue(value, "");
922
- if (formattedValue.startsWith("\n")) {
923
- lines.push(`${key}:${formattedValue}`);
816
+ const fullPath = prefix ? `${prefix}/${key}` : key;
817
+ if (Array.isArray(value)) {
818
+ value.forEach((item, index) => {
819
+ const itemPath = `${fullPath}/${index}`;
820
+ if (typeof item === "object" && item !== null) {
821
+ lines.push(formatParamsAsBlock(item, itemPath, argPrefix));
822
+ } else {
823
+ lines.push(`${argPrefix}${itemPath}`);
824
+ lines.push(String(item));
825
+ }
826
+ });
827
+ } else if (typeof value === "object" && value !== null) {
828
+ lines.push(formatParamsAsBlock(value, fullPath, argPrefix));
924
829
  } else {
925
- lines.push(`${key}: ${formattedValue}`);
830
+ lines.push(`${argPrefix}${fullPath}`);
831
+ lines.push(String(value));
926
832
  }
927
833
  }
928
834
  return lines.join("\n");
929
835
  }
930
- function formatTomlInlineTable(obj) {
931
- const entries = Object.entries(obj).map(([k, v]) => `${k} = ${formatTomlValue(v)}`);
932
- return `{ ${entries.join(", ")} }`;
933
- }
934
- function formatTomlValue(value) {
935
- if (typeof value === "string") {
936
- if (value.includes("\n")) {
937
- const delimiter = findSafeDelimiter(value);
938
- return `<<<${delimiter}
939
- ${value}
940
- ${delimiter}`;
941
- }
942
- return JSON.stringify(value);
943
- }
944
- if (typeof value === "number" || typeof value === "boolean") {
945
- return String(value);
946
- }
947
- if (value === null || value === void 0) {
948
- return '""';
949
- }
950
- if (Array.isArray(value)) {
951
- if (value.length === 0) return "[]";
952
- const items = value.map((item) => {
953
- if (typeof item === "object" && item !== null && !Array.isArray(item)) {
954
- return formatTomlInlineTable(item);
955
- }
956
- return formatTomlValue(item);
957
- });
958
- return `[${items.join(", ")}]`;
959
- }
960
- if (typeof value === "object") {
961
- return formatTomlInlineTable(value);
962
- }
963
- return JSON.stringify(value);
964
- }
965
- function formatParamsAsToml(params) {
836
+ function formatSchemaAsPlainText(schema, indent = "") {
966
837
  const lines = [];
967
- for (const [key, value] of Object.entries(params)) {
968
- lines.push(`${key} = ${formatTomlValue(value)}`);
838
+ const properties = schema.properties || {};
839
+ const required = schema.required || [];
840
+ for (const [key, prop] of Object.entries(properties)) {
841
+ const propObj = prop;
842
+ const type = propObj.type;
843
+ const description = propObj.description;
844
+ const isRequired = required.includes(key);
845
+ const enumValues = propObj.enum;
846
+ let line = `${indent}- ${key}`;
847
+ if (type === "array") {
848
+ const items = propObj.items;
849
+ const itemType = items?.type || "any";
850
+ line += ` (array of ${itemType})`;
851
+ } else if (type === "object" && propObj.properties) {
852
+ line += " (object)";
853
+ } else {
854
+ line += ` (${type})`;
855
+ }
856
+ if (isRequired) {
857
+ line += " [required]";
858
+ }
859
+ if (description) {
860
+ line += `: ${description}`;
861
+ }
862
+ if (enumValues) {
863
+ line += ` - one of: ${enumValues.map((v) => `"${v}"`).join(", ")}`;
864
+ }
865
+ lines.push(line);
866
+ if (type === "object" && propObj.properties) {
867
+ lines.push(formatSchemaAsPlainText(propObj, indent + " "));
868
+ }
969
869
  }
970
870
  return lines.join("\n");
971
871
  }
972
- var HEREDOC_DELIMITERS, BaseGadget;
872
+ var BaseGadget;
973
873
  var init_gadget = __esm({
974
874
  "src/gadgets/gadget.ts"() {
975
875
  "use strict";
876
+ init_constants();
976
877
  init_schema_to_json();
977
878
  init_schema_validator();
978
- HEREDOC_DELIMITERS = [
979
- "__GADGET_PARAM_EOF__",
980
- "__GADGET_PARAM_END__",
981
- "__GADGET_PARAM_DOC__",
982
- "__GADGET_PARAM_CONTENT__",
983
- "__GADGET_PARAM_TEXT__",
984
- "__GADGET_PARAM_HEREDOC__",
985
- "__GADGET_PARAM_DATA__",
986
- "__GADGET_PARAM_BLOCK__"
987
- ];
988
879
  BaseGadget = class {
989
880
  /**
990
881
  * The name of the gadget. Used for identification when LLM calls it.
@@ -1015,19 +906,19 @@ var init_gadget = __esm({
1015
906
  /**
1016
907
  * Auto-generated instruction text for the LLM.
1017
908
  * Combines name, description, and parameter schema into a formatted instruction.
1018
- * @deprecated Use getInstruction(format) instead for format-specific schemas
909
+ * @deprecated Use getInstruction() instead
1019
910
  */
1020
911
  get instruction() {
1021
- return this.getInstruction("yaml");
912
+ return this.getInstruction();
1022
913
  }
1023
914
  /**
1024
- * Generate instruction text for the LLM with format-specific schema.
915
+ * Generate instruction text for the LLM.
1025
916
  * Combines name, description, and parameter schema into a formatted instruction.
1026
917
  *
1027
- * @param format - Format for the schema representation ('json' | 'yaml' | 'toml' | 'auto')
918
+ * @param argPrefix - Optional custom argument prefix for block format examples
1028
919
  * @returns Formatted instruction string
1029
920
  */
1030
- getInstruction(format = "json") {
921
+ getInstruction(argPrefix) {
1031
922
  const parts = [];
1032
923
  parts.push(this.description);
1033
924
  if (this.parameterSchema) {
@@ -1036,20 +927,12 @@ var init_gadget = __esm({
1036
927
  const jsonSchema = schemaToJSONSchema(this.parameterSchema, {
1037
928
  target: "draft-7"
1038
929
  });
1039
- if (format === "json" || format === "auto") {
1040
- parts.push("\n\nInput Schema (JSON):");
1041
- parts.push(JSON.stringify(jsonSchema, null, 2));
1042
- } else if (format === "toml") {
1043
- parts.push("\n\nInput Schema (TOML):");
1044
- parts.push(JSON.stringify(jsonSchema, null, 2));
1045
- } else {
1046
- const yamlSchema = yaml.dump(jsonSchema).trimEnd();
1047
- parts.push("\n\nInput Schema (YAML):");
1048
- parts.push(yamlSchema);
1049
- }
930
+ parts.push("\n\nParameters:");
931
+ parts.push(formatSchemaAsPlainText(jsonSchema));
1050
932
  }
1051
933
  if (this.examples && this.examples.length > 0) {
1052
934
  parts.push("\n\nExamples:");
935
+ const effectiveArgPrefix = argPrefix ?? GADGET_ARG_PREFIX;
1053
936
  this.examples.forEach((example, index) => {
1054
937
  if (index > 0) {
1055
938
  parts.push("");
@@ -1058,13 +941,7 @@ var init_gadget = __esm({
1058
941
  parts.push(`# ${example.comment}`);
1059
942
  }
1060
943
  parts.push("Input:");
1061
- if (format === "json" || format === "auto") {
1062
- parts.push(JSON.stringify(example.params, null, 2));
1063
- } else if (format === "toml") {
1064
- parts.push(formatParamsAsToml(example.params));
1065
- } else {
1066
- parts.push(formatParamsAsYaml(example.params));
1067
- }
944
+ parts.push(formatParamsAsBlock(example.params, "", effectiveArgPrefix));
1068
945
  if (example.output !== void 0) {
1069
946
  parts.push("Output:");
1070
947
  parts.push(example.output);
@@ -1329,14 +1206,12 @@ var init_conversation_manager = __esm({
1329
1206
  baseMessages;
1330
1207
  initialMessages;
1331
1208
  historyBuilder;
1332
- parameterFormat;
1333
1209
  constructor(baseMessages, initialMessages, options = {}) {
1334
1210
  this.baseMessages = baseMessages;
1335
1211
  this.initialMessages = initialMessages;
1336
- this.parameterFormat = options.parameterFormat ?? "json";
1337
1212
  this.historyBuilder = new LLMMessageBuilder();
1338
1213
  if (options.startPrefix && options.endPrefix) {
1339
- this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix);
1214
+ this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix, options.argPrefix);
1340
1215
  }
1341
1216
  }
1342
1217
  addUserMessage(content) {
@@ -1346,7 +1221,7 @@ var init_conversation_manager = __esm({
1346
1221
  this.historyBuilder.addAssistant(content);
1347
1222
  }
1348
1223
  addGadgetCall(gadgetName, parameters, result) {
1349
- this.historyBuilder.addGadgetCall(gadgetName, parameters, result, this.parameterFormat);
1224
+ this.historyBuilder.addGadgetCall(gadgetName, parameters, result);
1350
1225
  }
1351
1226
  getMessages() {
1352
1227
  return [...this.baseMessages, ...this.initialMessages, ...this.historyBuilder.build()];
@@ -1369,7 +1244,7 @@ async function runWithHandlers(agentGenerator, handlers) {
1369
1244
  await handlers.onGadgetCall({
1370
1245
  gadgetName: event.call.gadgetName,
1371
1246
  parameters: event.call.parameters,
1372
- parametersYaml: event.call.parametersYaml
1247
+ parametersRaw: event.call.parametersRaw
1373
1248
  });
1374
1249
  }
1375
1250
  break;
@@ -1471,21 +1346,107 @@ var init_exceptions = __esm({
1471
1346
  }
1472
1347
  });
1473
1348
 
1349
+ // src/gadgets/error-formatter.ts
1350
+ var GadgetErrorFormatter;
1351
+ var init_error_formatter = __esm({
1352
+ "src/gadgets/error-formatter.ts"() {
1353
+ "use strict";
1354
+ init_constants();
1355
+ GadgetErrorFormatter = class {
1356
+ argPrefix;
1357
+ startPrefix;
1358
+ endPrefix;
1359
+ constructor(options = {}) {
1360
+ this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;
1361
+ this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;
1362
+ this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;
1363
+ }
1364
+ /**
1365
+ * Format a Zod validation error with full gadget instructions.
1366
+ *
1367
+ * @param gadgetName - Name of the gadget that was called
1368
+ * @param zodError - The Zod validation error
1369
+ * @param gadget - The gadget instance (for generating instructions)
1370
+ * @returns Formatted error message with usage instructions
1371
+ */
1372
+ formatValidationError(gadgetName, zodError, gadget) {
1373
+ const parts = [];
1374
+ parts.push(`Error: Invalid parameters for '${gadgetName}':`);
1375
+ for (const issue of zodError.issues) {
1376
+ const path = issue.path.join(".") || "root";
1377
+ parts.push(` - ${path}: ${issue.message}`);
1378
+ }
1379
+ parts.push("");
1380
+ parts.push("Gadget Usage:");
1381
+ parts.push(gadget.getInstruction(this.argPrefix));
1382
+ return parts.join("\n");
1383
+ }
1384
+ /**
1385
+ * Format a parse error with block format reference.
1386
+ *
1387
+ * @param gadgetName - Name of the gadget that was called
1388
+ * @param parseError - The parse error message
1389
+ * @param gadget - The gadget instance if found (for generating instructions)
1390
+ * @returns Formatted error message with format reference
1391
+ */
1392
+ formatParseError(gadgetName, parseError, gadget) {
1393
+ const parts = [];
1394
+ parts.push(`Error: Failed to parse parameters for '${gadgetName}':`);
1395
+ parts.push(` ${parseError}`);
1396
+ if (gadget) {
1397
+ parts.push("");
1398
+ parts.push("Gadget Usage:");
1399
+ parts.push(gadget.getInstruction(this.argPrefix));
1400
+ }
1401
+ parts.push("");
1402
+ parts.push("Block Format Reference:");
1403
+ parts.push(` ${this.startPrefix}${gadgetName}`);
1404
+ parts.push(` ${this.argPrefix}parameterName`);
1405
+ parts.push(" parameter value here");
1406
+ parts.push(` ${this.endPrefix}`);
1407
+ return parts.join("\n");
1408
+ }
1409
+ /**
1410
+ * Format a registry error (gadget not found) with available gadgets list.
1411
+ *
1412
+ * @param gadgetName - Name of the gadget that was not found
1413
+ * @param availableGadgets - List of available gadget names
1414
+ * @returns Formatted error message with available gadgets
1415
+ */
1416
+ formatRegistryError(gadgetName, availableGadgets) {
1417
+ const parts = [];
1418
+ parts.push(`Error: Gadget '${gadgetName}' not found.`);
1419
+ if (availableGadgets.length > 0) {
1420
+ parts.push("");
1421
+ parts.push(`Available gadgets: ${availableGadgets.join(", ")}`);
1422
+ } else {
1423
+ parts.push("");
1424
+ parts.push("No gadgets are currently registered.");
1425
+ }
1426
+ return parts.join("\n");
1427
+ }
1428
+ };
1429
+ }
1430
+ });
1431
+
1474
1432
  // src/gadgets/executor.ts
1475
1433
  var GadgetExecutor;
1476
1434
  var init_executor = __esm({
1477
1435
  "src/gadgets/executor.ts"() {
1478
1436
  "use strict";
1479
1437
  init_logger();
1438
+ init_error_formatter();
1480
1439
  init_exceptions();
1481
1440
  GadgetExecutor = class {
1482
- constructor(registry, onHumanInputRequired, logger, defaultGadgetTimeoutMs) {
1441
+ constructor(registry, onHumanInputRequired, logger, defaultGadgetTimeoutMs, errorFormatterOptions) {
1483
1442
  this.registry = registry;
1484
1443
  this.onHumanInputRequired = onHumanInputRequired;
1485
1444
  this.defaultGadgetTimeoutMs = defaultGadgetTimeoutMs;
1486
1445
  this.logger = logger ?? createLogger({ name: "llmist:executor" });
1446
+ this.errorFormatter = new GadgetErrorFormatter(errorFormatterOptions);
1487
1447
  }
1488
1448
  logger;
1449
+ errorFormatter;
1489
1450
  /**
1490
1451
  * Creates a promise that rejects with a TimeoutException after the specified timeout.
1491
1452
  */
@@ -1510,11 +1471,12 @@ var init_executor = __esm({
1510
1471
  const gadget = this.registry.get(call.gadgetName);
1511
1472
  if (!gadget) {
1512
1473
  this.logger.error("Gadget not found", { gadgetName: call.gadgetName });
1474
+ const availableGadgets = this.registry.getNames();
1513
1475
  return {
1514
1476
  gadgetName: call.gadgetName,
1515
1477
  invocationId: call.invocationId,
1516
1478
  parameters: call.parameters ?? {},
1517
- error: `Gadget '${call.gadgetName}' not found in registry`,
1479
+ error: this.errorFormatter.formatRegistryError(call.gadgetName, availableGadgets),
1518
1480
  executionTimeMs: Date.now() - startTime
1519
1481
  };
1520
1482
  }
@@ -1522,27 +1484,28 @@ var init_executor = __esm({
1522
1484
  this.logger.error("Gadget parameter parse error", {
1523
1485
  gadgetName: call.gadgetName,
1524
1486
  parseError: call.parseError,
1525
- rawParameters: call.parametersYaml
1487
+ rawParameters: call.parametersRaw
1526
1488
  });
1489
+ const parseErrorMessage = call.parseError ?? "Failed to parse parameters";
1527
1490
  return {
1528
1491
  gadgetName: call.gadgetName,
1529
1492
  invocationId: call.invocationId,
1530
1493
  parameters: {},
1531
- error: call.parseError ?? "Failed to parse parameters",
1494
+ error: this.errorFormatter.formatParseError(call.gadgetName, parseErrorMessage, gadget),
1532
1495
  executionTimeMs: Date.now() - startTime
1533
1496
  };
1534
1497
  }
1535
1498
  if (gadget.parameterSchema) {
1536
1499
  const validationResult = gadget.parameterSchema.safeParse(rawParameters);
1537
1500
  if (!validationResult.success) {
1538
- const formattedIssues = validationResult.error.issues.map((issue) => {
1539
- const path = issue.path.join(".") || "root";
1540
- return `${path}: ${issue.message}`;
1541
- }).join("; ");
1542
- const validationError = `Invalid parameters: ${formattedIssues}`;
1501
+ const validationError = this.errorFormatter.formatValidationError(
1502
+ call.gadgetName,
1503
+ validationResult.error,
1504
+ gadget
1505
+ );
1543
1506
  this.logger.error("Gadget parameter validation failed", {
1544
1507
  gadgetName: call.gadgetName,
1545
- error: validationError
1508
+ issueCount: validationResult.error.issues.length
1546
1509
  });
1547
1510
  return {
1548
1511
  gadgetName: call.gadgetName,
@@ -1684,170 +1647,107 @@ var init_executor = __esm({
1684
1647
  }
1685
1648
  });
1686
1649
 
1687
- // src/gadgets/parser.ts
1688
- import * as yaml2 from "js-yaml";
1689
- import { load as parseToml } from "js-toml";
1690
- function preprocessYaml(yamlStr) {
1691
- const lines = yamlStr.split("\n");
1692
- const result = [];
1693
- let i = 0;
1694
- while (i < lines.length) {
1695
- const line = lines[i];
1696
- const heredocMatch = line.match(/^(\s*)([\w-]+):\s*<<<([A-Za-z_][A-Za-z0-9_]*)\s*$/);
1697
- if (heredocMatch) {
1698
- const [, indent, key, delimiter] = heredocMatch;
1699
- const bodyLines = [];
1700
- i++;
1701
- const closingRegex = new RegExp(`^${delimiter}\\s*$`);
1702
- while (i < lines.length && !closingRegex.test(lines[i])) {
1703
- bodyLines.push(lines[i]);
1704
- i++;
1705
- }
1706
- if (i < lines.length) {
1707
- i++;
1708
- }
1709
- result.push(`${indent}${key}: |`);
1710
- for (const bodyLine of bodyLines) {
1711
- result.push(`${indent} ${bodyLine}`);
1650
+ // src/gadgets/block-params.ts
1651
+ function parseBlockParams(content, options) {
1652
+ const argPrefix = options?.argPrefix ?? GADGET_ARG_PREFIX;
1653
+ const result = {};
1654
+ const seenPointers = /* @__PURE__ */ new Set();
1655
+ const parts = content.split(argPrefix);
1656
+ for (let i = 1; i < parts.length; i++) {
1657
+ const part = parts[i];
1658
+ const newlineIndex = part.indexOf("\n");
1659
+ if (newlineIndex === -1) {
1660
+ const pointer2 = part.trim();
1661
+ if (pointer2) {
1662
+ if (seenPointers.has(pointer2)) {
1663
+ throw new Error(`Duplicate pointer: ${pointer2}`);
1664
+ }
1665
+ seenPointers.add(pointer2);
1666
+ setByPointer(result, pointer2, "");
1712
1667
  }
1713
1668
  continue;
1714
1669
  }
1715
- const match = line.match(/^(\s*)([\w-]+):\s+(.+)$/);
1716
- if (match) {
1717
- const [, indent, key, value] = match;
1718
- if (value === "|" || value === ">" || value === "|-" || value === ">-") {
1719
- result.push(line);
1720
- i++;
1721
- const keyIndentLen2 = indent.length;
1722
- const blockLines = [];
1723
- let minContentIndent = Infinity;
1724
- while (i < lines.length) {
1725
- const blockLine = lines[i];
1726
- const blockIndentMatch = blockLine.match(/^(\s*)/);
1727
- const blockIndentLen = blockIndentMatch ? blockIndentMatch[1].length : 0;
1728
- if (blockLine.trim() === "") {
1729
- blockLines.push({ content: "", originalIndent: 0 });
1730
- i++;
1731
- continue;
1732
- }
1733
- if (blockIndentLen > keyIndentLen2) {
1734
- const content = blockLine.substring(blockIndentLen);
1735
- blockLines.push({ content, originalIndent: blockIndentLen });
1736
- if (content.trim().length > 0) {
1737
- minContentIndent = Math.min(minContentIndent, blockIndentLen);
1738
- }
1739
- i++;
1740
- } else {
1741
- break;
1742
- }
1743
- }
1744
- const targetIndent = keyIndentLen2 + 2;
1745
- for (const blockLine of blockLines) {
1746
- if (blockLine.content === "") {
1747
- result.push("");
1748
- } else {
1749
- result.push(" ".repeat(targetIndent) + blockLine.content);
1750
- }
1751
- }
1752
- continue;
1753
- }
1754
- if (value.startsWith('"') || value.startsWith("'") || value === "true" || value === "false" || /^-?\d+(\.\d+)?$/.test(value)) {
1755
- result.push(line);
1756
- i++;
1757
- continue;
1758
- }
1759
- const keyIndentLen = indent.length;
1760
- const continuationLines = [];
1761
- let j = i + 1;
1762
- while (j < lines.length) {
1763
- const nextLine = lines[j];
1764
- if (nextLine.trim() === "") {
1765
- continuationLines.push(nextLine);
1766
- j++;
1767
- continue;
1768
- }
1769
- const nextIndentMatch = nextLine.match(/^(\s*)/);
1770
- const nextIndentLen = nextIndentMatch ? nextIndentMatch[1].length : 0;
1771
- if (nextIndentLen > keyIndentLen) {
1772
- continuationLines.push(nextLine);
1773
- j++;
1774
- } else {
1775
- break;
1776
- }
1777
- }
1778
- if (continuationLines.length > 0 && continuationLines.some((l) => l.trim().length > 0)) {
1779
- result.push(`${indent}${key}: |`);
1780
- result.push(`${indent} ${value}`);
1781
- for (const contLine of continuationLines) {
1782
- if (contLine.trim() === "") {
1783
- result.push("");
1784
- } else {
1785
- const contIndentMatch = contLine.match(/^(\s*)/);
1786
- const contIndent = contIndentMatch ? contIndentMatch[1] : "";
1787
- const contContent = contLine.substring(contIndent.length);
1788
- result.push(`${indent} ${contContent}`);
1789
- }
1790
- }
1791
- i = j;
1792
- continue;
1793
- }
1794
- if (value.includes(": ") || value.endsWith(":")) {
1795
- const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
1796
- result.push(`${indent}${key}: "${escaped}"`);
1797
- i++;
1798
- continue;
1799
- }
1670
+ const pointer = part.substring(0, newlineIndex).trim();
1671
+ let value = part.substring(newlineIndex + 1);
1672
+ if (value.endsWith("\n")) {
1673
+ value = value.slice(0, -1);
1674
+ }
1675
+ if (!pointer) {
1676
+ continue;
1677
+ }
1678
+ if (seenPointers.has(pointer)) {
1679
+ throw new Error(`Duplicate pointer: ${pointer}`);
1800
1680
  }
1801
- result.push(line);
1802
- i++;
1681
+ seenPointers.add(pointer);
1682
+ setByPointer(result, pointer, value);
1803
1683
  }
1804
- return result.join("\n");
1684
+ return result;
1805
1685
  }
1806
- function unescapeHeredocContent(content) {
1807
- return content.replace(/\\`/g, "`").replace(/\\\$/g, "$").replace(/\\{/g, "{").replace(/\\}/g, "}");
1686
+ function coerceValue(value) {
1687
+ if (value.includes("\n")) {
1688
+ return value;
1689
+ }
1690
+ const trimmed = value.trim();
1691
+ if (trimmed === "true") return true;
1692
+ if (trimmed === "false") return false;
1693
+ if (trimmed !== "" && /^-?\d+(\.\d+)?$/.test(trimmed)) {
1694
+ const num = Number(trimmed);
1695
+ if (!isNaN(num) && isFinite(num)) {
1696
+ return num;
1697
+ }
1698
+ }
1699
+ return value;
1808
1700
  }
1809
- function preprocessTomlHeredoc(tomlStr) {
1810
- const lines = tomlStr.split("\n");
1811
- const result = [];
1812
- let i = 0;
1813
- const heredocStartRegex = /^(\s*)([\w-]+)\s*=\s*<<<([A-Za-z_][A-Za-z0-9_]*)\s*$/;
1814
- while (i < lines.length) {
1815
- const line = lines[i];
1816
- const match = line.match(heredocStartRegex);
1817
- if (match) {
1818
- const [, indent, key, delimiter] = match;
1819
- const bodyLines = [];
1820
- i++;
1821
- const closingRegex = new RegExp(`^${delimiter}\\s*$`);
1822
- let foundClosing = false;
1823
- while (i < lines.length) {
1824
- const bodyLine = lines[i];
1825
- if (closingRegex.test(bodyLine)) {
1826
- foundClosing = true;
1827
- i++;
1828
- break;
1829
- }
1830
- bodyLines.push(bodyLine);
1831
- i++;
1832
- }
1833
- if (bodyLines.length === 0) {
1834
- result.push(`${indent}${key} = ''''''`);
1835
- } else {
1836
- result.push(`${indent}${key} = '''`);
1837
- for (let j = 0; j < bodyLines.length - 1; j++) {
1838
- result.push(unescapeHeredocContent(bodyLines[j]));
1839
- }
1840
- result.push(`${unescapeHeredocContent(bodyLines[bodyLines.length - 1])}'''`);
1841
- }
1842
- if (!foundClosing) {
1701
+ function setByPointer(obj, pointer, value) {
1702
+ const segments = pointer.split("/");
1703
+ let current = obj;
1704
+ for (let i = 0; i < segments.length - 1; i++) {
1705
+ const segment = segments[i];
1706
+ const nextSegment = segments[i + 1];
1707
+ const nextIsArrayIndex = /^\d+$/.test(nextSegment);
1708
+ if (Array.isArray(current)) {
1709
+ const index = parseInt(segment, 10);
1710
+ if (isNaN(index) || index < 0) {
1711
+ throw new Error(`Invalid array index: ${segment}`);
1712
+ }
1713
+ if (index > current.length) {
1714
+ throw new Error(`Array index gap: expected ${current.length}, got ${index}`);
1715
+ }
1716
+ if (current[index] === void 0) {
1717
+ current[index] = nextIsArrayIndex ? [] : {};
1718
+ }
1719
+ current = current[index];
1720
+ } else {
1721
+ const rec = current;
1722
+ if (rec[segment] === void 0) {
1723
+ rec[segment] = nextIsArrayIndex ? [] : {};
1843
1724
  }
1844
- continue;
1725
+ current = rec[segment];
1845
1726
  }
1846
- result.push(line);
1847
- i++;
1848
1727
  }
1849
- return result.join("\n");
1728
+ const lastSegment = segments[segments.length - 1];
1729
+ const coercedValue = coerceValue(value);
1730
+ if (Array.isArray(current)) {
1731
+ const index = parseInt(lastSegment, 10);
1732
+ if (isNaN(index) || index < 0) {
1733
+ throw new Error(`Invalid array index: ${lastSegment}`);
1734
+ }
1735
+ if (index > current.length) {
1736
+ throw new Error(`Array index gap: expected ${current.length}, got ${index}`);
1737
+ }
1738
+ current[index] = coercedValue;
1739
+ } else {
1740
+ current[lastSegment] = coercedValue;
1741
+ }
1850
1742
  }
1743
+ var init_block_params = __esm({
1744
+ "src/gadgets/block-params.ts"() {
1745
+ "use strict";
1746
+ init_constants();
1747
+ }
1748
+ });
1749
+
1750
+ // src/gadgets/parser.ts
1851
1751
  function stripMarkdownFences(content) {
1852
1752
  let cleaned = content.trim();
1853
1753
  const openingFence = /^```(?:toml|yaml|json)?\s*\n/i;
@@ -1861,17 +1761,18 @@ var init_parser = __esm({
1861
1761
  "src/gadgets/parser.ts"() {
1862
1762
  "use strict";
1863
1763
  init_constants();
1764
+ init_block_params();
1864
1765
  globalInvocationCounter = 0;
1865
1766
  StreamParser = class {
1866
1767
  buffer = "";
1867
1768
  lastReportedTextLength = 0;
1868
1769
  startPrefix;
1869
1770
  endPrefix;
1870
- parameterFormat;
1771
+ argPrefix;
1871
1772
  constructor(options = {}) {
1872
1773
  this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;
1873
1774
  this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;
1874
- this.parameterFormat = options.parameterFormat ?? "json";
1775
+ this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;
1875
1776
  }
1876
1777
  takeTextUntil(index) {
1877
1778
  if (index <= this.lastReportedTextLength) {
@@ -1893,56 +1794,22 @@ var init_parser = __esm({
1893
1794
  return { actualName: gadgetName, invocationId: `gadget_${++globalInvocationCounter}` };
1894
1795
  }
1895
1796
  /**
1896
- * Truncate verbose parse errors to avoid context overflow.
1897
- * Keeps first meaningful line and limits total length.
1797
+ * Extract the error message from a parse error.
1798
+ * Preserves full message since the error formatter adds contextual help
1799
+ * that benefits from precise, detailed error information.
1898
1800
  */
1899
- truncateParseError(error, format) {
1900
- const message = error instanceof Error ? error.message : String(error);
1901
- const firstLine = message.split("\n")[0];
1902
- const maxLen = 200;
1903
- if (firstLine.length <= maxLen) {
1904
- return firstLine;
1905
- }
1906
- return `${firstLine.slice(0, maxLen)}... (${message.length} chars total)`;
1801
+ extractParseError(error) {
1802
+ return error instanceof Error ? error.message : String(error);
1907
1803
  }
1908
1804
  /**
1909
- * Parse parameter string according to configured format
1805
+ * Parse parameter string using block format
1910
1806
  */
1911
1807
  parseParameters(raw) {
1912
1808
  const cleaned = stripMarkdownFences(raw);
1913
- if (this.parameterFormat === "json") {
1914
- try {
1915
- return { parameters: JSON.parse(cleaned) };
1916
- } catch (error) {
1917
- return { parseError: this.truncateParseError(error, "JSON") };
1918
- }
1919
- }
1920
- if (this.parameterFormat === "yaml") {
1921
- try {
1922
- return { parameters: yaml2.load(preprocessYaml(cleaned)) };
1923
- } catch (error) {
1924
- return { parseError: this.truncateParseError(error, "YAML") };
1925
- }
1926
- }
1927
- if (this.parameterFormat === "toml") {
1928
- try {
1929
- return { parameters: parseToml(preprocessTomlHeredoc(cleaned)) };
1930
- } catch (error) {
1931
- return { parseError: this.truncateParseError(error, "TOML") };
1932
- }
1933
- }
1934
1809
  try {
1935
- return { parameters: JSON.parse(cleaned) };
1936
- } catch {
1937
- try {
1938
- return { parameters: parseToml(preprocessTomlHeredoc(cleaned)) };
1939
- } catch {
1940
- try {
1941
- return { parameters: yaml2.load(preprocessYaml(cleaned)) };
1942
- } catch (error) {
1943
- return { parseError: this.truncateParseError(error, "auto") };
1944
- }
1945
- }
1810
+ return { parameters: parseBlockParams(cleaned, { argPrefix: this.argPrefix }) };
1811
+ } catch (error) {
1812
+ return { parseError: this.extractParseError(error) };
1946
1813
  }
1947
1814
  }
1948
1815
  // Feed a chunk of text and get parsed events
@@ -2001,8 +1868,7 @@ var init_parser = __esm({
2001
1868
  call: {
2002
1869
  gadgetName: actualGadgetName,
2003
1870
  invocationId,
2004
- parametersYaml: parametersRaw,
2005
- // Keep property name for backward compatibility
1871
+ parametersRaw,
2006
1872
  parameters,
2007
1873
  parseError
2008
1874
  }
@@ -2036,7 +1902,7 @@ var init_parser = __esm({
2036
1902
  call: {
2037
1903
  gadgetName: actualGadgetName,
2038
1904
  invocationId,
2039
- parametersYaml: parametersRaw,
1905
+ parametersRaw,
2040
1906
  parameters,
2041
1907
  parseError
2042
1908
  }
@@ -2241,9 +2107,9 @@ var init_stream_processor = __esm({
2241
2107
  this.stopOnGadgetError = options.stopOnGadgetError ?? true;
2242
2108
  this.shouldContinueAfterError = options.shouldContinueAfterError;
2243
2109
  this.parser = new StreamParser({
2244
- parameterFormat: options.parameterFormat,
2245
2110
  startPrefix: options.gadgetStartPrefix,
2246
- endPrefix: options.gadgetEndPrefix
2111
+ endPrefix: options.gadgetEndPrefix,
2112
+ argPrefix: options.gadgetArgPrefix
2247
2113
  });
2248
2114
  this.executor = new GadgetExecutor(
2249
2115
  options.registry,
@@ -2397,7 +2263,7 @@ var init_stream_processor = __esm({
2397
2263
  this.logger.warn("Gadget has parse error", {
2398
2264
  gadgetName: call.gadgetName,
2399
2265
  error: call.parseError,
2400
- rawParameters: call.parametersYaml
2266
+ rawParameters: call.parametersRaw
2401
2267
  });
2402
2268
  const shouldContinue = await this.checkContinueAfterError(
2403
2269
  call.parseError,
@@ -4376,9 +4242,9 @@ var init_agent = __esm({
4376
4242
  hooks;
4377
4243
  conversation;
4378
4244
  registry;
4379
- parameterFormat;
4380
4245
  gadgetStartPrefix;
4381
4246
  gadgetEndPrefix;
4247
+ gadgetArgPrefix;
4382
4248
  onHumanInputRequired;
4383
4249
  textOnlyHandler;
4384
4250
  textWithGadgetsHandler;
@@ -4407,9 +4273,9 @@ var init_agent = __esm({
4407
4273
  this.temperature = options.temperature;
4408
4274
  this.logger = options.logger ?? createLogger({ name: "llmist:agent" });
4409
4275
  this.registry = options.registry;
4410
- this.parameterFormat = options.parameterFormat ?? "json";
4411
4276
  this.gadgetStartPrefix = options.gadgetStartPrefix;
4412
4277
  this.gadgetEndPrefix = options.gadgetEndPrefix;
4278
+ this.gadgetArgPrefix = options.gadgetArgPrefix;
4413
4279
  this.onHumanInputRequired = options.onHumanInputRequired;
4414
4280
  this.textOnlyHandler = options.textOnlyHandler ?? "terminate";
4415
4281
  this.textWithGadgetsHandler = options.textWithGadgetsHandler;
@@ -4431,9 +4297,10 @@ var init_agent = __esm({
4431
4297
  if (options.systemPrompt) {
4432
4298
  baseBuilder.addSystem(options.systemPrompt);
4433
4299
  }
4434
- baseBuilder.addGadgets(this.registry.getAll(), this.parameterFormat, {
4300
+ baseBuilder.addGadgets(this.registry.getAll(), {
4435
4301
  startPrefix: options.gadgetStartPrefix,
4436
- endPrefix: options.gadgetEndPrefix
4302
+ endPrefix: options.gadgetEndPrefix,
4303
+ argPrefix: options.gadgetArgPrefix
4437
4304
  });
4438
4305
  const baseMessages = baseBuilder.build();
4439
4306
  const initialMessages = (options.initialMessages ?? []).map((message) => ({
@@ -4441,9 +4308,9 @@ var init_agent = __esm({
4441
4308
  content: message.content
4442
4309
  }));
4443
4310
  this.conversation = new ConversationManager(baseMessages, initialMessages, {
4444
- parameterFormat: this.parameterFormat,
4445
4311
  startPrefix: options.gadgetStartPrefix,
4446
- endPrefix: options.gadgetEndPrefix
4312
+ endPrefix: options.gadgetEndPrefix,
4313
+ argPrefix: options.gadgetArgPrefix
4447
4314
  });
4448
4315
  this.userPromptProvided = !!options.userPrompt;
4449
4316
  if (options.userPrompt) {
@@ -4536,9 +4403,9 @@ var init_agent = __esm({
4536
4403
  const processor = new StreamProcessor({
4537
4404
  iteration: currentIteration,
4538
4405
  registry: this.registry,
4539
- parameterFormat: this.parameterFormat,
4540
4406
  gadgetStartPrefix: this.gadgetStartPrefix,
4541
4407
  gadgetEndPrefix: this.gadgetEndPrefix,
4408
+ gadgetArgPrefix: this.gadgetArgPrefix,
4542
4409
  hooks: this.hooks,
4543
4410
  logger: this.logger.getSubLogger({ name: "stream-processor" }),
4544
4411
  onHumanInputRequired: this.onHumanInputRequired,
@@ -4831,9 +4698,9 @@ var init_builder = __esm({
4831
4698
  gadgets = [];
4832
4699
  initialMessages = [];
4833
4700
  onHumanInputRequired;
4834
- parameterFormat;
4835
4701
  gadgetStartPrefix;
4836
4702
  gadgetEndPrefix;
4703
+ gadgetArgPrefix;
4837
4704
  textOnlyHandler;
4838
4705
  textWithGadgetsHandler;
4839
4706
  stopOnGadgetError;
@@ -5020,21 +4887,6 @@ var init_builder = __esm({
5020
4887
  this.onHumanInputRequired = handler;
5021
4888
  return this;
5022
4889
  }
5023
- /**
5024
- * Set the parameter format for gadget calls.
5025
- *
5026
- * @param format - Parameter format ("json" or "xml")
5027
- * @returns This builder for chaining
5028
- *
5029
- * @example
5030
- * ```typescript
5031
- * .withParameterFormat("xml")
5032
- * ```
5033
- */
5034
- withParameterFormat(format) {
5035
- this.parameterFormat = format;
5036
- return this;
5037
- }
5038
4890
  /**
5039
4891
  * Set custom gadget marker prefix.
5040
4892
  *
@@ -5065,6 +4917,21 @@ var init_builder = __esm({
5065
4917
  this.gadgetEndPrefix = suffix;
5066
4918
  return this;
5067
4919
  }
4920
+ /**
4921
+ * Set custom argument prefix for block format parameters.
4922
+ *
4923
+ * @param prefix - Custom prefix for argument markers (default: "!!!ARG:")
4924
+ * @returns This builder for chaining
4925
+ *
4926
+ * @example
4927
+ * ```typescript
4928
+ * .withGadgetArgPrefix("<<ARG>>")
4929
+ * ```
4930
+ */
4931
+ withGadgetArgPrefix(prefix) {
4932
+ this.gadgetArgPrefix = prefix;
4933
+ return this;
4934
+ }
5068
4935
  /**
5069
4936
  * Set the text-only handler strategy.
5070
4937
  *
@@ -5264,8 +5131,7 @@ var init_builder = __esm({
5264
5131
  withSyntheticGadgetCall(gadgetName, parameters, result) {
5265
5132
  const startPrefix = this.gadgetStartPrefix ?? GADGET_START_PREFIX;
5266
5133
  const endPrefix = this.gadgetEndPrefix ?? GADGET_END_PREFIX;
5267
- const format = this.parameterFormat ?? "yaml";
5268
- const paramStr = this.formatSyntheticParameters(parameters, format);
5134
+ const paramStr = this.formatBlockParameters(parameters, "");
5269
5135
  this.initialMessages.push({
5270
5136
  role: "assistant",
5271
5137
  content: `${startPrefix}${gadgetName}
@@ -5279,25 +5145,31 @@ ${endPrefix}`
5279
5145
  return this;
5280
5146
  }
5281
5147
  /**
5282
- * Format parameters for synthetic gadget calls.
5283
- * Uses heredoc for multiline string values.
5148
+ * Format parameters as block format with JSON Pointer paths.
5284
5149
  */
5285
- formatSyntheticParameters(parameters, format) {
5286
- if (format === "json" || format === "auto") {
5287
- return JSON.stringify(parameters);
5288
- }
5289
- return Object.entries(parameters).map(([key, value]) => {
5290
- if (typeof value === "string" && value.includes("\n")) {
5291
- const separator = format === "yaml" ? ":" : " =";
5292
- return `${key}${separator} <<<EOF
5293
- ${value}
5294
- EOF`;
5295
- }
5296
- if (format === "yaml") {
5297
- return typeof value === "string" ? `${key}: ${value}` : `${key}: ${JSON.stringify(value)}`;
5150
+ formatBlockParameters(params, prefix) {
5151
+ const lines = [];
5152
+ const argPrefix = this.gadgetArgPrefix ?? GADGET_ARG_PREFIX;
5153
+ for (const [key, value] of Object.entries(params)) {
5154
+ const fullPath = prefix ? `${prefix}/${key}` : key;
5155
+ if (Array.isArray(value)) {
5156
+ value.forEach((item, index) => {
5157
+ const itemPath = `${fullPath}/${index}`;
5158
+ if (typeof item === "object" && item !== null) {
5159
+ lines.push(this.formatBlockParameters(item, itemPath));
5160
+ } else {
5161
+ lines.push(`${argPrefix}${itemPath}`);
5162
+ lines.push(String(item));
5163
+ }
5164
+ });
5165
+ } else if (typeof value === "object" && value !== null) {
5166
+ lines.push(this.formatBlockParameters(value, fullPath));
5167
+ } else {
5168
+ lines.push(`${argPrefix}${fullPath}`);
5169
+ lines.push(String(value));
5298
5170
  }
5299
- return `${key} = ${JSON.stringify(value)}`;
5300
- }).join("\n");
5171
+ }
5172
+ return lines.join("\n");
5301
5173
  }
5302
5174
  /**
5303
5175
  * Build and create the agent with the given user prompt.
@@ -5337,9 +5209,9 @@ EOF`;
5337
5209
  promptConfig: this.promptConfig,
5338
5210
  initialMessages: this.initialMessages,
5339
5211
  onHumanInputRequired: this.onHumanInputRequired,
5340
- parameterFormat: this.parameterFormat,
5341
5212
  gadgetStartPrefix: this.gadgetStartPrefix,
5342
5213
  gadgetEndPrefix: this.gadgetEndPrefix,
5214
+ gadgetArgPrefix: this.gadgetArgPrefix,
5343
5215
  textOnlyHandler: this.textOnlyHandler,
5344
5216
  textWithGadgetsHandler: this.textWithGadgetsHandler,
5345
5217
  stopOnGadgetError: this.stopOnGadgetError,
@@ -5439,9 +5311,9 @@ EOF`;
5439
5311
  promptConfig: this.promptConfig,
5440
5312
  initialMessages: this.initialMessages,
5441
5313
  onHumanInputRequired: this.onHumanInputRequired,
5442
- parameterFormat: this.parameterFormat,
5443
5314
  gadgetStartPrefix: this.gadgetStartPrefix,
5444
5315
  gadgetEndPrefix: this.gadgetEndPrefix,
5316
+ gadgetArgPrefix: this.gadgetArgPrefix,
5445
5317
  textOnlyHandler: this.textOnlyHandler,
5446
5318
  textWithGadgetsHandler: this.textWithGadgetsHandler,
5447
5319
  stopOnGadgetError: this.stopOnGadgetError,
@@ -5701,6 +5573,7 @@ var init_client = __esm({
5701
5573
  export {
5702
5574
  GADGET_START_PREFIX,
5703
5575
  GADGET_END_PREFIX,
5576
+ GADGET_ARG_PREFIX,
5704
5577
  init_constants,
5705
5578
  MODEL_ALIASES,
5706
5579
  resolveModel,
@@ -5708,6 +5581,8 @@ export {
5708
5581
  getProvider,
5709
5582
  getModelId,
5710
5583
  init_model_shortcuts,
5584
+ validateGadgetSchema,
5585
+ init_schema_validator,
5711
5586
  GadgetRegistry,
5712
5587
  init_registry,
5713
5588
  DEFAULT_PROMPTS,
@@ -5719,6 +5594,8 @@ export {
5719
5594
  createLogger,
5720
5595
  defaultLogger,
5721
5596
  init_logger,
5597
+ schemaToJSONSchema,
5598
+ init_schema_to_json,
5722
5599
  BaseGadget,
5723
5600
  init_gadget,
5724
5601
  createGadget,
@@ -5767,4 +5644,4 @@ export {
5767
5644
  AgentBuilder,
5768
5645
  init_builder
5769
5646
  };
5770
- //# sourceMappingURL=chunk-62M4TDAK.js.map
5647
+ //# sourceMappingURL=chunk-VXPZQZF5.js.map