llmist 0.8.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -31,12 +31,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
33
  // src/core/constants.ts
34
- var GADGET_START_PREFIX, GADGET_END_PREFIX, DEFAULT_GADGET_OUTPUT_LIMIT, DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT, CHARS_PER_TOKEN, FALLBACK_CONTEXT_WINDOW;
34
+ var GADGET_START_PREFIX, GADGET_END_PREFIX, GADGET_ARG_PREFIX, DEFAULT_GADGET_OUTPUT_LIMIT, DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT, CHARS_PER_TOKEN, FALLBACK_CONTEXT_WINDOW;
35
35
  var init_constants = __esm({
36
36
  "src/core/constants.ts"() {
37
37
  "use strict";
38
38
  GADGET_START_PREFIX = "!!!GADGET_START:";
39
39
  GADGET_END_PREFIX = "!!!GADGET_END";
40
+ GADGET_ARG_PREFIX = "!!!ARG:";
40
41
  DEFAULT_GADGET_OUTPUT_LIMIT = true;
41
42
  DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;
42
43
  CHARS_PER_TOKEN = 4;
@@ -386,17 +387,12 @@ var init_prompt_config = __esm({
386
387
  "EACH MARKER MUST START WITH A NEWLINE."
387
388
  ].join("\n"),
388
389
  criticalUsage: "INVOKE gadgets using the markers - do not describe what you want to do.",
389
- formatDescriptionYaml: "Parameters in YAML format (one per line)",
390
- formatDescriptionJson: "Parameters in JSON format (valid JSON object)",
391
- formatDescriptionToml: "Parameters in TOML format (key = value pairs, use heredoc for multiline: key = <<<EOF ... EOF)",
390
+ formatDescription: (ctx) => `Parameters using ${ctx.argPrefix}name markers (value on next line(s), no escaping needed)`,
392
391
  rules: () => [
393
392
  "Output ONLY plain text with the exact markers - never use function/tool calling",
394
393
  "You can invoke multiple gadgets in a single response",
395
394
  "For dependent gadgets, invoke the first one and wait for the result"
396
395
  ],
397
- schemaLabelJson: "\n\nInput Schema (JSON):",
398
- schemaLabelYaml: "\n\nInput Schema (YAML):",
399
- schemaLabelToml: "\n\nInput Schema (TOML):",
400
396
  customExamples: null
401
397
  };
402
398
  }
@@ -413,6 +409,7 @@ var init_messages = __esm({
413
409
  messages = [];
414
410
  startPrefix = GADGET_START_PREFIX;
415
411
  endPrefix = GADGET_END_PREFIX;
412
+ argPrefix = GADGET_ARG_PREFIX;
416
413
  promptConfig;
417
414
  constructor(promptConfig) {
418
415
  this.promptConfig = promptConfig ?? {};
@@ -421,26 +418,32 @@ var init_messages = __esm({
421
418
  * Set custom prefixes for gadget markers.
422
419
  * Used to configure history builder to match system prompt markers.
423
420
  */
424
- withPrefixes(startPrefix, endPrefix) {
421
+ withPrefixes(startPrefix, endPrefix, argPrefix) {
425
422
  this.startPrefix = startPrefix;
426
423
  this.endPrefix = endPrefix;
424
+ if (argPrefix) {
425
+ this.argPrefix = argPrefix;
426
+ }
427
427
  return this;
428
428
  }
429
429
  addSystem(content, metadata) {
430
430
  this.messages.push({ role: "system", content, metadata });
431
431
  return this;
432
432
  }
433
- addGadgets(gadgets, parameterFormat = "json", options) {
433
+ addGadgets(gadgets, options) {
434
434
  if (options?.startPrefix) {
435
435
  this.startPrefix = options.startPrefix;
436
436
  }
437
437
  if (options?.endPrefix) {
438
438
  this.endPrefix = options.endPrefix;
439
439
  }
440
+ if (options?.argPrefix) {
441
+ this.argPrefix = options.argPrefix;
442
+ }
440
443
  const context = {
441
- parameterFormat,
442
444
  startPrefix: this.startPrefix,
443
445
  endPrefix: this.endPrefix,
446
+ argPrefix: this.argPrefix,
444
447
  gadgetCount: gadgets.length,
445
448
  gadgetNames: gadgets.map((g) => g.name ?? g.constructor.name)
446
449
  };
@@ -451,26 +454,19 @@ var init_messages = __esm({
451
454
  context
452
455
  );
453
456
  parts.push(mainInstruction);
454
- parts.push(this.buildGadgetsSection(gadgets, parameterFormat));
455
- parts.push(this.buildUsageSection(parameterFormat, context));
457
+ parts.push(this.buildGadgetsSection(gadgets));
458
+ parts.push(this.buildUsageSection(context));
456
459
  this.messages.push({ role: "system", content: parts.join("") });
457
460
  return this;
458
461
  }
459
- buildGadgetsSection(gadgets, parameterFormat) {
462
+ buildGadgetsSection(gadgets) {
460
463
  const parts = [];
461
464
  parts.push("\n\nAVAILABLE GADGETS");
462
465
  parts.push("\n=================\n");
463
466
  for (const gadget of gadgets) {
464
467
  const gadgetName = gadget.name ?? gadget.constructor.name;
465
- const instruction = gadget.getInstruction(parameterFormat);
466
- const schemaMarkers = {
467
- yaml: "\n\nInput Schema (YAML):",
468
- json: "\n\nInput Schema (JSON):",
469
- toml: "\n\nInput Schema (TOML):",
470
- auto: "\n\nInput Schema (JSON):"
471
- // auto defaults to JSON schema display
472
- };
473
- const schemaMarker = schemaMarkers[parameterFormat];
468
+ const instruction = gadget.getInstruction(this.argPrefix);
469
+ const schemaMarker = "\n\nInput Schema (BLOCK):";
474
470
  const schemaIndex = instruction.indexOf(schemaMarker);
475
471
  const description = (schemaIndex !== -1 ? instruction.substring(0, schemaIndex) : instruction).trim();
476
472
  const schema = schemaIndex !== -1 ? instruction.substring(schemaIndex + schemaMarker.length).trim() : "";
@@ -481,35 +477,20 @@ ${description}`);
481
477
  if (schema) {
482
478
  parts.push(`
483
479
 
484
- PARAMETERS (${parameterFormat.toUpperCase()}):
480
+ PARAMETERS (BLOCK):
485
481
  ${schema}`);
486
482
  }
487
483
  parts.push("\n\n---");
488
484
  }
489
485
  return parts.join("");
490
486
  }
491
- buildUsageSection(parameterFormat, context) {
487
+ buildUsageSection(context) {
492
488
  const parts = [];
493
- const formatDescriptionMap = {
494
- yaml: {
495
- config: this.promptConfig.formatDescriptionYaml,
496
- defaultValue: DEFAULT_PROMPTS.formatDescriptionYaml
497
- },
498
- json: {
499
- config: this.promptConfig.formatDescriptionJson,
500
- defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
501
- },
502
- toml: {
503
- config: this.promptConfig.formatDescriptionToml,
504
- defaultValue: DEFAULT_PROMPTS.formatDescriptionToml
505
- },
506
- auto: {
507
- config: this.promptConfig.formatDescriptionJson,
508
- defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
509
- }
510
- };
511
- const { config, defaultValue } = formatDescriptionMap[parameterFormat];
512
- const formatDescription = resolvePromptTemplate(config, defaultValue, context);
489
+ const formatDescription = resolvePromptTemplate(
490
+ this.promptConfig.formatDescription,
491
+ DEFAULT_PROMPTS.formatDescription,
492
+ context
493
+ );
513
494
  parts.push("\n\nHOW TO INVOKE GADGETS");
514
495
  parts.push("\n=====================\n");
515
496
  const criticalUsage = resolvePromptTemplate(
@@ -527,124 +508,90 @@ CRITICAL: ${criticalUsage}
527
508
  2. ${formatDescription}`);
528
509
  parts.push(`
529
510
  3. End marker: ${this.endPrefix}`);
530
- parts.push(this.buildExamplesSection(parameterFormat, context));
511
+ parts.push(this.buildExamplesSection(context));
531
512
  parts.push(this.buildRulesSection(context));
532
513
  parts.push("\n");
533
514
  return parts.join("");
534
515
  }
535
- buildExamplesSection(parameterFormat, context) {
516
+ buildExamplesSection(context) {
536
517
  if (this.promptConfig.customExamples) {
537
518
  return this.promptConfig.customExamples(context);
538
519
  }
539
520
  const parts = [];
540
- const singleExamples = {
541
- yaml: `${this.startPrefix}translate
542
- from: English
543
- to: Polish
544
- content: "Paris is the capital of France: a beautiful city."
545
- ${this.endPrefix}`,
546
- json: `${this.startPrefix}translate
547
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
548
- ${this.endPrefix}`,
549
- toml: `${this.startPrefix}translate
550
- from = "English"
551
- to = "Polish"
552
- content = "Paris is the capital of France: a beautiful city."
553
- ${this.endPrefix}`,
554
- auto: `${this.startPrefix}translate
555
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
556
- ${this.endPrefix}`
557
- };
521
+ const singleExample = `${this.startPrefix}translate
522
+ ${this.argPrefix}from
523
+ English
524
+ ${this.argPrefix}to
525
+ Polish
526
+ ${this.argPrefix}content
527
+ Paris is the capital of France: a beautiful city.
528
+ ${this.endPrefix}`;
558
529
  parts.push(`
559
530
 
560
531
  EXAMPLE (Single Gadget):
561
532
 
562
- ${singleExamples[parameterFormat]}`);
563
- const multipleExamples = {
564
- yaml: `${this.startPrefix}translate
565
- from: English
566
- to: Polish
567
- content: "Paris is the capital of France: a beautiful city."
533
+ ${singleExample}`);
534
+ const multipleExample = `${this.startPrefix}translate
535
+ ${this.argPrefix}from
536
+ English
537
+ ${this.argPrefix}to
538
+ Polish
539
+ ${this.argPrefix}content
540
+ Paris is the capital of France: a beautiful city.
568
541
  ${this.endPrefix}
569
542
  ${this.startPrefix}analyze
570
- type: economic_analysis
571
- matter: "Polish Economy"
572
- question: <<<EOF
543
+ ${this.argPrefix}type
544
+ economic_analysis
545
+ ${this.argPrefix}matter
546
+ Polish Economy
547
+ ${this.argPrefix}question
573
548
  Analyze the following:
574
549
  - Polish arms exports 2025
575
550
  - Economic implications
576
- EOF
577
- ${this.endPrefix}`,
578
- json: `${this.startPrefix}translate
579
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
580
- ${this.endPrefix}
581
- ${this.startPrefix}analyze
582
- {"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
583
- ${this.endPrefix}`,
584
- toml: `${this.startPrefix}translate
585
- from = "English"
586
- to = "Polish"
587
- content = "Paris is the capital of France: a beautiful city."
588
- ${this.endPrefix}
589
- ${this.startPrefix}analyze
590
- type = "economic_analysis"
591
- matter = "Polish Economy"
592
- question = <<<EOF
593
- Analyze the following:
594
- - Polish arms exports 2025
595
- - Economic implications
596
- EOF
597
- ${this.endPrefix}`,
598
- auto: `${this.startPrefix}translate
599
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
600
- ${this.endPrefix}
601
- ${this.startPrefix}analyze
602
- {"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
603
- ${this.endPrefix}`
604
- };
551
+ ${this.endPrefix}`;
605
552
  parts.push(`
606
553
 
607
554
  EXAMPLE (Multiple Gadgets):
608
555
 
609
- ${multipleExamples[parameterFormat]}`);
610
- if (parameterFormat === "yaml") {
611
- parts.push(`
612
-
613
- YAML HEREDOC SYNTAX:
614
- For string values with multiple lines, use heredoc syntax (<<<DELIMITER...DELIMITER):
615
-
616
- filePath: "README.md"
617
- content: <<<EOF
618
- # Project Title
556
+ ${multipleExample}`);
557
+ parts.push(`
619
558
 
620
- This content can contain:
621
- - Markdown lists
622
- - Special characters: # : -
623
- - Multiple paragraphs
624
- EOF
559
+ BLOCK FORMAT SYNTAX:
560
+ Block format uses ${this.argPrefix}name markers. Values are captured verbatim until the next marker.
625
561
 
626
- The delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.
627
- No indentation is required for the content.`);
628
- } else if (parameterFormat === "toml") {
629
- parts.push(`
562
+ ${this.argPrefix}filename
563
+ calculator.ts
564
+ ${this.argPrefix}code
565
+ class Calculator {
566
+ private history: string[] = [];
630
567
 
631
- TOML HEREDOC SYNTAX:
632
- For string values with multiple lines, use heredoc syntax (<<<DELIMITER...DELIMITER):
568
+ add(a: number, b: number): number {
569
+ const result = a + b;
570
+ this.history.push(\`\${a} + \${b} = \${result}\`);
571
+ return result;
572
+ }
573
+ }
633
574
 
634
- filePath = "README.md"
635
- content = <<<EOF
636
- # Project Title
575
+ BLOCK FORMAT RULES:
576
+ - Each parameter starts with ${this.argPrefix}parameterName on its own line
577
+ - The value starts on the NEXT line after the marker
578
+ - Value ends when the next ${this.argPrefix} or ${this.endPrefix} appears
579
+ - NO escaping needed - write values exactly as they should appear
580
+ - Perfect for code, JSON, markdown, or any content with special characters
637
581
 
638
- This content can contain:
639
- - Markdown lists
640
- - Special characters: # : -
641
- - Multiple paragraphs
642
- EOF
582
+ NESTED OBJECTS (use / separator):
583
+ ${this.argPrefix}config/timeout
584
+ 30
585
+ ${this.argPrefix}config/retries
586
+ 3
587
+ Produces: { "config": { "timeout": "30", "retries": "3" } }
643
588
 
644
- The delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.
645
- IMPORTANT: Content inside heredoc is LITERAL - do NOT escape backticks, dollar signs, or any characters.
646
- NEVER use TOML triple-quote strings ("""). ALWAYS use heredoc syntax (<<<EOF...EOF) for multiline content.`);
647
- }
589
+ ARRAYS (use numeric indices):
590
+ ${this.argPrefix}items/0
591
+ first
592
+ ${this.argPrefix}items/1
593
+ second
594
+ Produces: { "items": ["first", "second"] }`);
648
595
  return parts.join("");
649
596
  }
650
597
  buildRulesSection(context) {
@@ -665,8 +612,8 @@ NEVER use TOML triple-quote strings ("""). ALWAYS use heredoc syntax (<<<EOF...E
665
612
  this.messages.push({ role: "assistant", content, metadata });
666
613
  return this;
667
614
  }
668
- addGadgetCall(gadget, parameters, result, parameterFormat = "json") {
669
- const paramStr = this.formatParameters(parameters, parameterFormat);
615
+ addGadgetCall(gadget, parameters, result) {
616
+ const paramStr = this.formatBlockParameters(parameters, "");
670
617
  this.messages.push({
671
618
  role: "assistant",
672
619
  content: `${this.startPrefix}${gadget}
@@ -679,26 +626,32 @@ ${this.endPrefix}`
679
626
  });
680
627
  return this;
681
628
  }
682
- formatParameters(parameters, format) {
683
- if (format === "yaml") {
684
- return Object.entries(parameters).map(([key, value]) => {
685
- if (typeof value === "string") {
686
- return `${key}: ${value}`;
687
- }
688
- return `${key}: ${JSON.stringify(value)}`;
689
- }).join("\n");
690
- }
691
- if (format === "toml") {
692
- return Object.entries(parameters).map(([key, value]) => {
693
- if (typeof value === "string" && value.includes("\n")) {
694
- return `${key} = <<<EOF
695
- ${value}
696
- EOF`;
697
- }
698
- return `${key} = ${JSON.stringify(value)}`;
699
- }).join("\n");
629
+ /**
630
+ * Format parameters as Block format with JSON Pointer paths.
631
+ * Uses the configured argPrefix for consistency with system prompt.
632
+ */
633
+ formatBlockParameters(params, prefix) {
634
+ const lines = [];
635
+ for (const [key, value] of Object.entries(params)) {
636
+ const fullPath = prefix ? `${prefix}/${key}` : key;
637
+ if (Array.isArray(value)) {
638
+ value.forEach((item, index) => {
639
+ const itemPath = `${fullPath}/${index}`;
640
+ if (typeof item === "object" && item !== null) {
641
+ lines.push(this.formatBlockParameters(item, itemPath));
642
+ } else {
643
+ lines.push(`${this.argPrefix}${itemPath}`);
644
+ lines.push(String(item));
645
+ }
646
+ });
647
+ } else if (typeof value === "object" && value !== null) {
648
+ lines.push(this.formatBlockParameters(value, fullPath));
649
+ } else {
650
+ lines.push(`${this.argPrefix}${fullPath}`);
651
+ lines.push(String(value));
652
+ }
700
653
  }
701
- return JSON.stringify(parameters);
654
+ return lines.join("\n");
702
655
  }
703
656
  build() {
704
657
  return [...this.messages];
@@ -870,134 +823,72 @@ var init_schema_to_json = __esm({
870
823
  });
871
824
 
872
825
  // src/gadgets/gadget.ts
873
- function findSafeDelimiter(content) {
874
- const lines = content.split("\n");
875
- for (const delimiter of HEREDOC_DELIMITERS) {
876
- const regex = new RegExp(`^${delimiter}\\s*$`);
877
- const isUsed = lines.some((line) => regex.test(line));
878
- if (!isUsed) {
879
- return delimiter;
880
- }
881
- }
882
- let counter = 1;
883
- while (counter < 1e3) {
884
- const delimiter = `__GADGET_PARAM_${counter}__`;
885
- const regex = new RegExp(`^${delimiter}\\s*$`);
886
- const isUsed = lines.some((line) => regex.test(line));
887
- if (!isUsed) {
888
- return delimiter;
889
- }
890
- counter++;
891
- }
892
- return "HEREDOC_FALLBACK";
893
- }
894
- function formatYamlValue(value, indent = "") {
895
- if (typeof value === "string") {
896
- const lines = value.split("\n");
897
- if (lines.length === 1 && !value.includes(":") && !value.startsWith("-")) {
898
- return value;
899
- }
900
- const delimiter = findSafeDelimiter(value);
901
- return `<<<${delimiter}
902
- ${value}
903
- ${delimiter}`;
904
- }
905
- if (typeof value === "number" || typeof value === "boolean") {
906
- return String(value);
907
- }
908
- if (value === null || value === void 0) {
909
- return "null";
910
- }
911
- if (Array.isArray(value)) {
912
- if (value.length === 0) return "[]";
913
- const items = value.map((item) => `${indent}- ${formatYamlValue(item, indent + " ")}`);
914
- return "\n" + items.join("\n");
915
- }
916
- if (typeof value === "object") {
917
- const entries = Object.entries(value);
918
- if (entries.length === 0) return "{}";
919
- const lines = entries.map(([k, v]) => {
920
- const formattedValue = formatYamlValue(v, indent + " ");
921
- if (formattedValue.startsWith("\n") || formattedValue.startsWith("|")) {
922
- return `${indent}${k}: ${formattedValue}`;
923
- }
924
- return `${indent}${k}: ${formattedValue}`;
925
- });
926
- return "\n" + lines.join("\n");
927
- }
928
- return yaml.dump(value).trimEnd();
929
- }
930
- function formatParamsAsYaml(params) {
826
+ function formatParamsAsBlock(params, prefix = "", argPrefix = GADGET_ARG_PREFIX) {
931
827
  const lines = [];
932
828
  for (const [key, value] of Object.entries(params)) {
933
- const formattedValue = formatYamlValue(value, "");
934
- if (formattedValue.startsWith("\n")) {
935
- lines.push(`${key}:${formattedValue}`);
829
+ const fullPath = prefix ? `${prefix}/${key}` : key;
830
+ if (Array.isArray(value)) {
831
+ value.forEach((item, index) => {
832
+ const itemPath = `${fullPath}/${index}`;
833
+ if (typeof item === "object" && item !== null) {
834
+ lines.push(formatParamsAsBlock(item, itemPath, argPrefix));
835
+ } else {
836
+ lines.push(`${argPrefix}${itemPath}`);
837
+ lines.push(String(item));
838
+ }
839
+ });
840
+ } else if (typeof value === "object" && value !== null) {
841
+ lines.push(formatParamsAsBlock(value, fullPath, argPrefix));
936
842
  } else {
937
- lines.push(`${key}: ${formattedValue}`);
843
+ lines.push(`${argPrefix}${fullPath}`);
844
+ lines.push(String(value));
938
845
  }
939
846
  }
940
847
  return lines.join("\n");
941
848
  }
942
- function formatTomlInlineTable(obj) {
943
- const entries = Object.entries(obj).map(([k, v]) => `${k} = ${formatTomlValue(v)}`);
944
- return `{ ${entries.join(", ")} }`;
945
- }
946
- function formatTomlValue(value) {
947
- if (typeof value === "string") {
948
- if (value.includes("\n")) {
949
- const delimiter = findSafeDelimiter(value);
950
- return `<<<${delimiter}
951
- ${value}
952
- ${delimiter}`;
953
- }
954
- return JSON.stringify(value);
955
- }
956
- if (typeof value === "number" || typeof value === "boolean") {
957
- return String(value);
958
- }
959
- if (value === null || value === void 0) {
960
- return '""';
961
- }
962
- if (Array.isArray(value)) {
963
- if (value.length === 0) return "[]";
964
- const items = value.map((item) => {
965
- if (typeof item === "object" && item !== null && !Array.isArray(item)) {
966
- return formatTomlInlineTable(item);
967
- }
968
- return formatTomlValue(item);
969
- });
970
- return `[${items.join(", ")}]`;
971
- }
972
- if (typeof value === "object") {
973
- return formatTomlInlineTable(value);
974
- }
975
- return JSON.stringify(value);
976
- }
977
- function formatParamsAsToml(params) {
849
+ function formatSchemaAsPlainText(schema, indent = "") {
978
850
  const lines = [];
979
- for (const [key, value] of Object.entries(params)) {
980
- lines.push(`${key} = ${formatTomlValue(value)}`);
851
+ const properties = schema.properties || {};
852
+ const required = schema.required || [];
853
+ for (const [key, prop] of Object.entries(properties)) {
854
+ const propObj = prop;
855
+ const type = propObj.type;
856
+ const description = propObj.description;
857
+ const isRequired = required.includes(key);
858
+ const enumValues = propObj.enum;
859
+ let line = `${indent}- ${key}`;
860
+ if (type === "array") {
861
+ const items = propObj.items;
862
+ const itemType = items?.type || "any";
863
+ line += ` (array of ${itemType})`;
864
+ } else if (type === "object" && propObj.properties) {
865
+ line += " (object)";
866
+ } else {
867
+ line += ` (${type})`;
868
+ }
869
+ if (isRequired) {
870
+ line += " [required]";
871
+ }
872
+ if (description) {
873
+ line += `: ${description}`;
874
+ }
875
+ if (enumValues) {
876
+ line += ` - one of: ${enumValues.map((v) => `"${v}"`).join(", ")}`;
877
+ }
878
+ lines.push(line);
879
+ if (type === "object" && propObj.properties) {
880
+ lines.push(formatSchemaAsPlainText(propObj, indent + " "));
881
+ }
981
882
  }
982
883
  return lines.join("\n");
983
884
  }
984
- var yaml, HEREDOC_DELIMITERS, BaseGadget;
885
+ var BaseGadget;
985
886
  var init_gadget = __esm({
986
887
  "src/gadgets/gadget.ts"() {
987
888
  "use strict";
988
- yaml = __toESM(require("js-yaml"), 1);
889
+ init_constants();
989
890
  init_schema_to_json();
990
891
  init_schema_validator();
991
- HEREDOC_DELIMITERS = [
992
- "__GADGET_PARAM_EOF__",
993
- "__GADGET_PARAM_END__",
994
- "__GADGET_PARAM_DOC__",
995
- "__GADGET_PARAM_CONTENT__",
996
- "__GADGET_PARAM_TEXT__",
997
- "__GADGET_PARAM_HEREDOC__",
998
- "__GADGET_PARAM_DATA__",
999
- "__GADGET_PARAM_BLOCK__"
1000
- ];
1001
892
  BaseGadget = class {
1002
893
  /**
1003
894
  * The name of the gadget. Used for identification when LLM calls it.
@@ -1028,19 +919,19 @@ var init_gadget = __esm({
1028
919
  /**
1029
920
  * Auto-generated instruction text for the LLM.
1030
921
  * Combines name, description, and parameter schema into a formatted instruction.
1031
- * @deprecated Use getInstruction(format) instead for format-specific schemas
922
+ * @deprecated Use getInstruction() instead
1032
923
  */
1033
924
  get instruction() {
1034
- return this.getInstruction("yaml");
925
+ return this.getInstruction();
1035
926
  }
1036
927
  /**
1037
- * Generate instruction text for the LLM with format-specific schema.
928
+ * Generate instruction text for the LLM.
1038
929
  * Combines name, description, and parameter schema into a formatted instruction.
1039
930
  *
1040
- * @param format - Format for the schema representation ('json' | 'yaml' | 'toml' | 'auto')
931
+ * @param argPrefix - Optional custom argument prefix for block format examples
1041
932
  * @returns Formatted instruction string
1042
933
  */
1043
- getInstruction(format = "json") {
934
+ getInstruction(argPrefix) {
1044
935
  const parts = [];
1045
936
  parts.push(this.description);
1046
937
  if (this.parameterSchema) {
@@ -1049,20 +940,12 @@ var init_gadget = __esm({
1049
940
  const jsonSchema = schemaToJSONSchema(this.parameterSchema, {
1050
941
  target: "draft-7"
1051
942
  });
1052
- if (format === "json" || format === "auto") {
1053
- parts.push("\n\nInput Schema (JSON):");
1054
- parts.push(JSON.stringify(jsonSchema, null, 2));
1055
- } else if (format === "toml") {
1056
- parts.push("\n\nInput Schema (TOML):");
1057
- parts.push(JSON.stringify(jsonSchema, null, 2));
1058
- } else {
1059
- const yamlSchema = yaml.dump(jsonSchema).trimEnd();
1060
- parts.push("\n\nInput Schema (YAML):");
1061
- parts.push(yamlSchema);
1062
- }
943
+ parts.push("\n\nParameters:");
944
+ parts.push(formatSchemaAsPlainText(jsonSchema));
1063
945
  }
1064
946
  if (this.examples && this.examples.length > 0) {
1065
947
  parts.push("\n\nExamples:");
948
+ const effectiveArgPrefix = argPrefix ?? GADGET_ARG_PREFIX;
1066
949
  this.examples.forEach((example, index) => {
1067
950
  if (index > 0) {
1068
951
  parts.push("");
@@ -1071,13 +954,7 @@ var init_gadget = __esm({
1071
954
  parts.push(`# ${example.comment}`);
1072
955
  }
1073
956
  parts.push("Input:");
1074
- if (format === "json" || format === "auto") {
1075
- parts.push(JSON.stringify(example.params, null, 2));
1076
- } else if (format === "toml") {
1077
- parts.push(formatParamsAsToml(example.params));
1078
- } else {
1079
- parts.push(formatParamsAsYaml(example.params));
1080
- }
957
+ parts.push(formatParamsAsBlock(example.params, "", effectiveArgPrefix));
1081
958
  if (example.output !== void 0) {
1082
959
  parts.push("Output:");
1083
960
  parts.push(example.output);
@@ -1354,14 +1231,12 @@ var init_conversation_manager = __esm({
1354
1231
  baseMessages;
1355
1232
  initialMessages;
1356
1233
  historyBuilder;
1357
- parameterFormat;
1358
1234
  constructor(baseMessages, initialMessages, options = {}) {
1359
1235
  this.baseMessages = baseMessages;
1360
1236
  this.initialMessages = initialMessages;
1361
- this.parameterFormat = options.parameterFormat ?? "json";
1362
1237
  this.historyBuilder = new LLMMessageBuilder();
1363
1238
  if (options.startPrefix && options.endPrefix) {
1364
- this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix);
1239
+ this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix, options.argPrefix);
1365
1240
  }
1366
1241
  }
1367
1242
  addUserMessage(content) {
@@ -1371,7 +1246,7 @@ var init_conversation_manager = __esm({
1371
1246
  this.historyBuilder.addAssistant(content);
1372
1247
  }
1373
1248
  addGadgetCall(gadgetName, parameters, result) {
1374
- this.historyBuilder.addGadgetCall(gadgetName, parameters, result, this.parameterFormat);
1249
+ this.historyBuilder.addGadgetCall(gadgetName, parameters, result);
1375
1250
  }
1376
1251
  getMessages() {
1377
1252
  return [...this.baseMessages, ...this.initialMessages, ...this.historyBuilder.build()];
@@ -1394,7 +1269,7 @@ async function runWithHandlers(agentGenerator, handlers) {
1394
1269
  await handlers.onGadgetCall({
1395
1270
  gadgetName: event.call.gadgetName,
1396
1271
  parameters: event.call.parameters,
1397
- parametersYaml: event.call.parametersYaml
1272
+ parametersRaw: event.call.parametersRaw
1398
1273
  });
1399
1274
  }
1400
1275
  break;
@@ -1701,7 +1576,7 @@ var init_executor = __esm({
1701
1576
  this.logger.error("Gadget parameter parse error", {
1702
1577
  gadgetName: call.gadgetName,
1703
1578
  parseError: call.parseError,
1704
- rawParameters: call.parametersYaml
1579
+ rawParameters: call.parametersRaw
1705
1580
  });
1706
1581
  return {
1707
1582
  gadgetName: call.gadgetName,
@@ -1863,168 +1738,107 @@ var init_executor = __esm({
1863
1738
  }
1864
1739
  });
1865
1740
 
1866
- // src/gadgets/parser.ts
1867
- function preprocessYaml(yamlStr) {
1868
- const lines = yamlStr.split("\n");
1869
- const result = [];
1870
- let i = 0;
1871
- while (i < lines.length) {
1872
- const line = lines[i];
1873
- const heredocMatch = line.match(/^(\s*)([\w-]+):\s*<<<([A-Za-z_][A-Za-z0-9_]*)\s*$/);
1874
- if (heredocMatch) {
1875
- const [, indent, key, delimiter] = heredocMatch;
1876
- const bodyLines = [];
1877
- i++;
1878
- const closingRegex = new RegExp(`^${delimiter}\\s*$`);
1879
- while (i < lines.length && !closingRegex.test(lines[i])) {
1880
- bodyLines.push(lines[i]);
1881
- i++;
1882
- }
1883
- if (i < lines.length) {
1884
- i++;
1885
- }
1886
- result.push(`${indent}${key}: |`);
1887
- for (const bodyLine of bodyLines) {
1888
- result.push(`${indent} ${bodyLine}`);
1741
+ // src/gadgets/block-params.ts
1742
+ function parseBlockParams(content, options) {
1743
+ const argPrefix = options?.argPrefix ?? GADGET_ARG_PREFIX;
1744
+ const result = {};
1745
+ const seenPointers = /* @__PURE__ */ new Set();
1746
+ const parts = content.split(argPrefix);
1747
+ for (let i = 1; i < parts.length; i++) {
1748
+ const part = parts[i];
1749
+ const newlineIndex = part.indexOf("\n");
1750
+ if (newlineIndex === -1) {
1751
+ const pointer2 = part.trim();
1752
+ if (pointer2) {
1753
+ if (seenPointers.has(pointer2)) {
1754
+ throw new Error(`Duplicate pointer: ${pointer2}`);
1755
+ }
1756
+ seenPointers.add(pointer2);
1757
+ setByPointer(result, pointer2, "");
1889
1758
  }
1890
1759
  continue;
1891
1760
  }
1892
- const match = line.match(/^(\s*)([\w-]+):\s+(.+)$/);
1893
- if (match) {
1894
- const [, indent, key, value] = match;
1895
- if (value === "|" || value === ">" || value === "|-" || value === ">-") {
1896
- result.push(line);
1897
- i++;
1898
- const keyIndentLen2 = indent.length;
1899
- const blockLines = [];
1900
- let minContentIndent = Infinity;
1901
- while (i < lines.length) {
1902
- const blockLine = lines[i];
1903
- const blockIndentMatch = blockLine.match(/^(\s*)/);
1904
- const blockIndentLen = blockIndentMatch ? blockIndentMatch[1].length : 0;
1905
- if (blockLine.trim() === "") {
1906
- blockLines.push({ content: "", originalIndent: 0 });
1907
- i++;
1908
- continue;
1909
- }
1910
- if (blockIndentLen > keyIndentLen2) {
1911
- const content = blockLine.substring(blockIndentLen);
1912
- blockLines.push({ content, originalIndent: blockIndentLen });
1913
- if (content.trim().length > 0) {
1914
- minContentIndent = Math.min(minContentIndent, blockIndentLen);
1915
- }
1916
- i++;
1917
- } else {
1918
- break;
1919
- }
1920
- }
1921
- const targetIndent = keyIndentLen2 + 2;
1922
- for (const blockLine of blockLines) {
1923
- if (blockLine.content === "") {
1924
- result.push("");
1925
- } else {
1926
- result.push(" ".repeat(targetIndent) + blockLine.content);
1927
- }
1928
- }
1929
- continue;
1930
- }
1931
- if (value.startsWith('"') || value.startsWith("'") || value === "true" || value === "false" || /^-?\d+(\.\d+)?$/.test(value)) {
1932
- result.push(line);
1933
- i++;
1934
- continue;
1935
- }
1936
- const keyIndentLen = indent.length;
1937
- const continuationLines = [];
1938
- let j = i + 1;
1939
- while (j < lines.length) {
1940
- const nextLine = lines[j];
1941
- if (nextLine.trim() === "") {
1942
- continuationLines.push(nextLine);
1943
- j++;
1944
- continue;
1945
- }
1946
- const nextIndentMatch = nextLine.match(/^(\s*)/);
1947
- const nextIndentLen = nextIndentMatch ? nextIndentMatch[1].length : 0;
1948
- if (nextIndentLen > keyIndentLen) {
1949
- continuationLines.push(nextLine);
1950
- j++;
1951
- } else {
1952
- break;
1953
- }
1954
- }
1955
- if (continuationLines.length > 0 && continuationLines.some((l) => l.trim().length > 0)) {
1956
- result.push(`${indent}${key}: |`);
1957
- result.push(`${indent} ${value}`);
1958
- for (const contLine of continuationLines) {
1959
- if (contLine.trim() === "") {
1960
- result.push("");
1961
- } else {
1962
- const contIndentMatch = contLine.match(/^(\s*)/);
1963
- const contIndent = contIndentMatch ? contIndentMatch[1] : "";
1964
- const contContent = contLine.substring(contIndent.length);
1965
- result.push(`${indent} ${contContent}`);
1966
- }
1967
- }
1968
- i = j;
1969
- continue;
1970
- }
1971
- if (value.includes(": ") || value.endsWith(":")) {
1972
- const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
1973
- result.push(`${indent}${key}: "${escaped}"`);
1974
- i++;
1975
- continue;
1976
- }
1761
+ const pointer = part.substring(0, newlineIndex).trim();
1762
+ let value = part.substring(newlineIndex + 1);
1763
+ if (value.endsWith("\n")) {
1764
+ value = value.slice(0, -1);
1765
+ }
1766
+ if (!pointer) {
1767
+ continue;
1768
+ }
1769
+ if (seenPointers.has(pointer)) {
1770
+ throw new Error(`Duplicate pointer: ${pointer}`);
1977
1771
  }
1978
- result.push(line);
1979
- i++;
1772
+ seenPointers.add(pointer);
1773
+ setByPointer(result, pointer, value);
1980
1774
  }
1981
- return result.join("\n");
1775
+ return result;
1982
1776
  }
1983
- function unescapeHeredocContent(content) {
1984
- return content.replace(/\\`/g, "`").replace(/\\\$/g, "$").replace(/\\{/g, "{").replace(/\\}/g, "}");
1777
+ function coerceValue(value) {
1778
+ if (value.includes("\n")) {
1779
+ return value;
1780
+ }
1781
+ const trimmed = value.trim();
1782
+ if (trimmed === "true") return true;
1783
+ if (trimmed === "false") return false;
1784
+ if (trimmed !== "" && /^-?\d+(\.\d+)?$/.test(trimmed)) {
1785
+ const num = Number(trimmed);
1786
+ if (!isNaN(num) && isFinite(num)) {
1787
+ return num;
1788
+ }
1789
+ }
1790
+ return value;
1985
1791
  }
1986
- function preprocessTomlHeredoc(tomlStr) {
1987
- const lines = tomlStr.split("\n");
1988
- const result = [];
1989
- let i = 0;
1990
- const heredocStartRegex = /^(\s*)([\w-]+)\s*=\s*<<<([A-Za-z_][A-Za-z0-9_]*)\s*$/;
1991
- while (i < lines.length) {
1992
- const line = lines[i];
1993
- const match = line.match(heredocStartRegex);
1994
- if (match) {
1995
- const [, indent, key, delimiter] = match;
1996
- const bodyLines = [];
1997
- i++;
1998
- const closingRegex = new RegExp(`^${delimiter}\\s*$`);
1999
- let foundClosing = false;
2000
- while (i < lines.length) {
2001
- const bodyLine = lines[i];
2002
- if (closingRegex.test(bodyLine)) {
2003
- foundClosing = true;
2004
- i++;
2005
- break;
2006
- }
2007
- bodyLines.push(bodyLine);
2008
- i++;
2009
- }
2010
- if (bodyLines.length === 0) {
2011
- result.push(`${indent}${key} = ''''''`);
2012
- } else {
2013
- result.push(`${indent}${key} = '''`);
2014
- for (let j = 0; j < bodyLines.length - 1; j++) {
2015
- result.push(unescapeHeredocContent(bodyLines[j]));
2016
- }
2017
- result.push(`${unescapeHeredocContent(bodyLines[bodyLines.length - 1])}'''`);
2018
- }
2019
- if (!foundClosing) {
1792
+ function setByPointer(obj, pointer, value) {
1793
+ const segments = pointer.split("/");
1794
+ let current = obj;
1795
+ for (let i = 0; i < segments.length - 1; i++) {
1796
+ const segment = segments[i];
1797
+ const nextSegment = segments[i + 1];
1798
+ const nextIsArrayIndex = /^\d+$/.test(nextSegment);
1799
+ if (Array.isArray(current)) {
1800
+ const index = parseInt(segment, 10);
1801
+ if (isNaN(index) || index < 0) {
1802
+ throw new Error(`Invalid array index: ${segment}`);
1803
+ }
1804
+ if (index > current.length) {
1805
+ throw new Error(`Array index gap: expected ${current.length}, got ${index}`);
1806
+ }
1807
+ if (current[index] === void 0) {
1808
+ current[index] = nextIsArrayIndex ? [] : {};
1809
+ }
1810
+ current = current[index];
1811
+ } else {
1812
+ const rec = current;
1813
+ if (rec[segment] === void 0) {
1814
+ rec[segment] = nextIsArrayIndex ? [] : {};
2020
1815
  }
2021
- continue;
1816
+ current = rec[segment];
1817
+ }
1818
+ }
1819
+ const lastSegment = segments[segments.length - 1];
1820
+ const coercedValue = coerceValue(value);
1821
+ if (Array.isArray(current)) {
1822
+ const index = parseInt(lastSegment, 10);
1823
+ if (isNaN(index) || index < 0) {
1824
+ throw new Error(`Invalid array index: ${lastSegment}`);
1825
+ }
1826
+ if (index > current.length) {
1827
+ throw new Error(`Array index gap: expected ${current.length}, got ${index}`);
2022
1828
  }
2023
- result.push(line);
2024
- i++;
1829
+ current[index] = coercedValue;
1830
+ } else {
1831
+ current[lastSegment] = coercedValue;
2025
1832
  }
2026
- return result.join("\n");
2027
1833
  }
1834
+ var init_block_params = __esm({
1835
+ "src/gadgets/block-params.ts"() {
1836
+ "use strict";
1837
+ init_constants();
1838
+ }
1839
+ });
1840
+
1841
+ // src/gadgets/parser.ts
2028
1842
  function stripMarkdownFences(content) {
2029
1843
  let cleaned = content.trim();
2030
1844
  const openingFence = /^```(?:toml|yaml|json)?\s*\n/i;
@@ -2033,24 +1847,23 @@ function stripMarkdownFences(content) {
2033
1847
  cleaned = cleaned.replace(closingFence, "");
2034
1848
  return cleaned.trim();
2035
1849
  }
2036
- var yaml2, import_js_toml, globalInvocationCounter, StreamParser;
1850
+ var globalInvocationCounter, StreamParser;
2037
1851
  var init_parser = __esm({
2038
1852
  "src/gadgets/parser.ts"() {
2039
1853
  "use strict";
2040
- yaml2 = __toESM(require("js-yaml"), 1);
2041
- import_js_toml = require("js-toml");
2042
1854
  init_constants();
1855
+ init_block_params();
2043
1856
  globalInvocationCounter = 0;
2044
1857
  StreamParser = class {
2045
1858
  buffer = "";
2046
1859
  lastReportedTextLength = 0;
2047
1860
  startPrefix;
2048
1861
  endPrefix;
2049
- parameterFormat;
1862
+ argPrefix;
2050
1863
  constructor(options = {}) {
2051
1864
  this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;
2052
1865
  this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;
2053
- this.parameterFormat = options.parameterFormat ?? "json";
1866
+ this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;
2054
1867
  }
2055
1868
  takeTextUntil(index) {
2056
1869
  if (index <= this.lastReportedTextLength) {
@@ -2085,43 +1898,14 @@ var init_parser = __esm({
2085
1898
  return `${firstLine.slice(0, maxLen)}... (${message.length} chars total)`;
2086
1899
  }
2087
1900
  /**
2088
- * Parse parameter string according to configured format
1901
+ * Parse parameter string using block format
2089
1902
  */
2090
1903
  parseParameters(raw) {
2091
1904
  const cleaned = stripMarkdownFences(raw);
2092
- if (this.parameterFormat === "json") {
2093
- try {
2094
- return { parameters: JSON.parse(cleaned) };
2095
- } catch (error) {
2096
- return { parseError: this.truncateParseError(error, "JSON") };
2097
- }
2098
- }
2099
- if (this.parameterFormat === "yaml") {
2100
- try {
2101
- return { parameters: yaml2.load(preprocessYaml(cleaned)) };
2102
- } catch (error) {
2103
- return { parseError: this.truncateParseError(error, "YAML") };
2104
- }
2105
- }
2106
- if (this.parameterFormat === "toml") {
2107
- try {
2108
- return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(cleaned)) };
2109
- } catch (error) {
2110
- return { parseError: this.truncateParseError(error, "TOML") };
2111
- }
2112
- }
2113
1905
  try {
2114
- return { parameters: JSON.parse(cleaned) };
2115
- } catch {
2116
- try {
2117
- return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(cleaned)) };
2118
- } catch {
2119
- try {
2120
- return { parameters: yaml2.load(preprocessYaml(cleaned)) };
2121
- } catch (error) {
2122
- return { parseError: this.truncateParseError(error, "auto") };
2123
- }
2124
- }
1906
+ return { parameters: parseBlockParams(cleaned, { argPrefix: this.argPrefix }) };
1907
+ } catch (error) {
1908
+ return { parseError: this.truncateParseError(error, "block") };
2125
1909
  }
2126
1910
  }
2127
1911
  // Feed a chunk of text and get parsed events
@@ -2180,8 +1964,7 @@ var init_parser = __esm({
2180
1964
  call: {
2181
1965
  gadgetName: actualGadgetName,
2182
1966
  invocationId,
2183
- parametersYaml: parametersRaw,
2184
- // Keep property name for backward compatibility
1967
+ parametersRaw,
2185
1968
  parameters,
2186
1969
  parseError
2187
1970
  }
@@ -2215,7 +1998,7 @@ var init_parser = __esm({
2215
1998
  call: {
2216
1999
  gadgetName: actualGadgetName,
2217
2000
  invocationId,
2218
- parametersYaml: parametersRaw,
2001
+ parametersRaw,
2219
2002
  parameters,
2220
2003
  parseError
2221
2004
  }
@@ -2266,9 +2049,9 @@ var init_stream_processor = __esm({
2266
2049
  this.stopOnGadgetError = options.stopOnGadgetError ?? true;
2267
2050
  this.shouldContinueAfterError = options.shouldContinueAfterError;
2268
2051
  this.parser = new StreamParser({
2269
- parameterFormat: options.parameterFormat,
2270
2052
  startPrefix: options.gadgetStartPrefix,
2271
- endPrefix: options.gadgetEndPrefix
2053
+ endPrefix: options.gadgetEndPrefix,
2054
+ argPrefix: options.gadgetArgPrefix
2272
2055
  });
2273
2056
  this.executor = new GadgetExecutor(
2274
2057
  options.registry,
@@ -2422,7 +2205,7 @@ var init_stream_processor = __esm({
2422
2205
  this.logger.warn("Gadget has parse error", {
2423
2206
  gadgetName: call.gadgetName,
2424
2207
  error: call.parseError,
2425
- rawParameters: call.parametersYaml
2208
+ rawParameters: call.parametersRaw
2426
2209
  });
2427
2210
  const shouldContinue = await this.checkContinueAfterError(
2428
2211
  call.parseError,
@@ -2658,9 +2441,9 @@ var init_agent = __esm({
2658
2441
  hooks;
2659
2442
  conversation;
2660
2443
  registry;
2661
- parameterFormat;
2662
2444
  gadgetStartPrefix;
2663
2445
  gadgetEndPrefix;
2446
+ gadgetArgPrefix;
2664
2447
  onHumanInputRequired;
2665
2448
  textOnlyHandler;
2666
2449
  textWithGadgetsHandler;
@@ -2689,9 +2472,9 @@ var init_agent = __esm({
2689
2472
  this.temperature = options.temperature;
2690
2473
  this.logger = options.logger ?? createLogger({ name: "llmist:agent" });
2691
2474
  this.registry = options.registry;
2692
- this.parameterFormat = options.parameterFormat ?? "json";
2693
2475
  this.gadgetStartPrefix = options.gadgetStartPrefix;
2694
2476
  this.gadgetEndPrefix = options.gadgetEndPrefix;
2477
+ this.gadgetArgPrefix = options.gadgetArgPrefix;
2695
2478
  this.onHumanInputRequired = options.onHumanInputRequired;
2696
2479
  this.textOnlyHandler = options.textOnlyHandler ?? "terminate";
2697
2480
  this.textWithGadgetsHandler = options.textWithGadgetsHandler;
@@ -2713,9 +2496,10 @@ var init_agent = __esm({
2713
2496
  if (options.systemPrompt) {
2714
2497
  baseBuilder.addSystem(options.systemPrompt);
2715
2498
  }
2716
- baseBuilder.addGadgets(this.registry.getAll(), this.parameterFormat, {
2499
+ baseBuilder.addGadgets(this.registry.getAll(), {
2717
2500
  startPrefix: options.gadgetStartPrefix,
2718
- endPrefix: options.gadgetEndPrefix
2501
+ endPrefix: options.gadgetEndPrefix,
2502
+ argPrefix: options.gadgetArgPrefix
2719
2503
  });
2720
2504
  const baseMessages = baseBuilder.build();
2721
2505
  const initialMessages = (options.initialMessages ?? []).map((message) => ({
@@ -2723,9 +2507,9 @@ var init_agent = __esm({
2723
2507
  content: message.content
2724
2508
  }));
2725
2509
  this.conversation = new ConversationManager(baseMessages, initialMessages, {
2726
- parameterFormat: this.parameterFormat,
2727
2510
  startPrefix: options.gadgetStartPrefix,
2728
- endPrefix: options.gadgetEndPrefix
2511
+ endPrefix: options.gadgetEndPrefix,
2512
+ argPrefix: options.gadgetArgPrefix
2729
2513
  });
2730
2514
  this.userPromptProvided = !!options.userPrompt;
2731
2515
  if (options.userPrompt) {
@@ -2818,9 +2602,9 @@ var init_agent = __esm({
2818
2602
  const processor = new StreamProcessor({
2819
2603
  iteration: currentIteration,
2820
2604
  registry: this.registry,
2821
- parameterFormat: this.parameterFormat,
2822
2605
  gadgetStartPrefix: this.gadgetStartPrefix,
2823
2606
  gadgetEndPrefix: this.gadgetEndPrefix,
2607
+ gadgetArgPrefix: this.gadgetArgPrefix,
2824
2608
  hooks: this.hooks,
2825
2609
  logger: this.logger.getSubLogger({ name: "stream-processor" }),
2826
2610
  onHumanInputRequired: this.onHumanInputRequired,
@@ -5086,9 +4870,9 @@ var init_builder = __esm({
5086
4870
  gadgets = [];
5087
4871
  initialMessages = [];
5088
4872
  onHumanInputRequired;
5089
- parameterFormat;
5090
4873
  gadgetStartPrefix;
5091
4874
  gadgetEndPrefix;
4875
+ gadgetArgPrefix;
5092
4876
  textOnlyHandler;
5093
4877
  textWithGadgetsHandler;
5094
4878
  stopOnGadgetError;
@@ -5275,21 +5059,6 @@ var init_builder = __esm({
5275
5059
  this.onHumanInputRequired = handler;
5276
5060
  return this;
5277
5061
  }
5278
- /**
5279
- * Set the parameter format for gadget calls.
5280
- *
5281
- * @param format - Parameter format ("json" or "xml")
5282
- * @returns This builder for chaining
5283
- *
5284
- * @example
5285
- * ```typescript
5286
- * .withParameterFormat("xml")
5287
- * ```
5288
- */
5289
- withParameterFormat(format) {
5290
- this.parameterFormat = format;
5291
- return this;
5292
- }
5293
5062
  /**
5294
5063
  * Set custom gadget marker prefix.
5295
5064
  *
@@ -5320,6 +5089,21 @@ var init_builder = __esm({
5320
5089
  this.gadgetEndPrefix = suffix;
5321
5090
  return this;
5322
5091
  }
5092
+ /**
5093
+ * Set custom argument prefix for block format parameters.
5094
+ *
5095
+ * @param prefix - Custom prefix for argument markers (default: "!!!ARG:")
5096
+ * @returns This builder for chaining
5097
+ *
5098
+ * @example
5099
+ * ```typescript
5100
+ * .withGadgetArgPrefix("<<ARG>>")
5101
+ * ```
5102
+ */
5103
+ withGadgetArgPrefix(prefix) {
5104
+ this.gadgetArgPrefix = prefix;
5105
+ return this;
5106
+ }
5323
5107
  /**
5324
5108
  * Set the text-only handler strategy.
5325
5109
  *
@@ -5519,8 +5303,7 @@ var init_builder = __esm({
5519
5303
  withSyntheticGadgetCall(gadgetName, parameters, result) {
5520
5304
  const startPrefix = this.gadgetStartPrefix ?? GADGET_START_PREFIX;
5521
5305
  const endPrefix = this.gadgetEndPrefix ?? GADGET_END_PREFIX;
5522
- const format = this.parameterFormat ?? "yaml";
5523
- const paramStr = this.formatSyntheticParameters(parameters, format);
5306
+ const paramStr = this.formatBlockParameters(parameters, "");
5524
5307
  this.initialMessages.push({
5525
5308
  role: "assistant",
5526
5309
  content: `${startPrefix}${gadgetName}
@@ -5534,25 +5317,31 @@ ${endPrefix}`
5534
5317
  return this;
5535
5318
  }
5536
5319
  /**
5537
- * Format parameters for synthetic gadget calls.
5538
- * Uses heredoc for multiline string values.
5320
+ * Format parameters as block format with JSON Pointer paths.
5539
5321
  */
5540
- formatSyntheticParameters(parameters, format) {
5541
- if (format === "json" || format === "auto") {
5542
- return JSON.stringify(parameters);
5543
- }
5544
- return Object.entries(parameters).map(([key, value]) => {
5545
- if (typeof value === "string" && value.includes("\n")) {
5546
- const separator = format === "yaml" ? ":" : " =";
5547
- return `${key}${separator} <<<EOF
5548
- ${value}
5549
- EOF`;
5550
- }
5551
- if (format === "yaml") {
5552
- return typeof value === "string" ? `${key}: ${value}` : `${key}: ${JSON.stringify(value)}`;
5322
+ formatBlockParameters(params, prefix) {
5323
+ const lines = [];
5324
+ const argPrefix = this.gadgetArgPrefix ?? GADGET_ARG_PREFIX;
5325
+ for (const [key, value] of Object.entries(params)) {
5326
+ const fullPath = prefix ? `${prefix}/${key}` : key;
5327
+ if (Array.isArray(value)) {
5328
+ value.forEach((item, index) => {
5329
+ const itemPath = `${fullPath}/${index}`;
5330
+ if (typeof item === "object" && item !== null) {
5331
+ lines.push(this.formatBlockParameters(item, itemPath));
5332
+ } else {
5333
+ lines.push(`${argPrefix}${itemPath}`);
5334
+ lines.push(String(item));
5335
+ }
5336
+ });
5337
+ } else if (typeof value === "object" && value !== null) {
5338
+ lines.push(this.formatBlockParameters(value, fullPath));
5339
+ } else {
5340
+ lines.push(`${argPrefix}${fullPath}`);
5341
+ lines.push(String(value));
5553
5342
  }
5554
- return `${key} = ${JSON.stringify(value)}`;
5555
- }).join("\n");
5343
+ }
5344
+ return lines.join("\n");
5556
5345
  }
5557
5346
  /**
5558
5347
  * Build and create the agent with the given user prompt.
@@ -5592,9 +5381,9 @@ EOF`;
5592
5381
  promptConfig: this.promptConfig,
5593
5382
  initialMessages: this.initialMessages,
5594
5383
  onHumanInputRequired: this.onHumanInputRequired,
5595
- parameterFormat: this.parameterFormat,
5596
5384
  gadgetStartPrefix: this.gadgetStartPrefix,
5597
5385
  gadgetEndPrefix: this.gadgetEndPrefix,
5386
+ gadgetArgPrefix: this.gadgetArgPrefix,
5598
5387
  textOnlyHandler: this.textOnlyHandler,
5599
5388
  textWithGadgetsHandler: this.textWithGadgetsHandler,
5600
5389
  stopOnGadgetError: this.stopOnGadgetError,
@@ -5694,9 +5483,9 @@ EOF`;
5694
5483
  promptConfig: this.promptConfig,
5695
5484
  initialMessages: this.initialMessages,
5696
5485
  onHumanInputRequired: this.onHumanInputRequired,
5697
- parameterFormat: this.parameterFormat,
5698
5486
  gadgetStartPrefix: this.gadgetStartPrefix,
5699
5487
  gadgetEndPrefix: this.gadgetEndPrefix,
5488
+ gadgetArgPrefix: this.gadgetArgPrefix,
5700
5489
  textOnlyHandler: this.textOnlyHandler,
5701
5490
  textWithGadgetsHandler: this.textWithGadgetsHandler,
5702
5491
  stopOnGadgetError: this.stopOnGadgetError,
@@ -6776,17 +6565,51 @@ function splitIntoChunks(text, minChunkSize = 5, maxChunkSize = 30) {
6776
6565
  }
6777
6566
  return chunks;
6778
6567
  }
6568
+ function serializeToBlockFormat(obj, prefix = "") {
6569
+ let result = "";
6570
+ for (const [key, value] of Object.entries(obj)) {
6571
+ const pointer = prefix ? `${prefix}/${key}` : key;
6572
+ if (value === null || value === void 0) {
6573
+ continue;
6574
+ }
6575
+ if (Array.isArray(value)) {
6576
+ for (let i = 0; i < value.length; i++) {
6577
+ const item = value[i];
6578
+ const itemPointer = `${pointer}/${i}`;
6579
+ if (typeof item === "object" && item !== null && !Array.isArray(item)) {
6580
+ result += serializeToBlockFormat(item, itemPointer);
6581
+ } else if (Array.isArray(item)) {
6582
+ for (let j = 0; j < item.length; j++) {
6583
+ result += `${GADGET_ARG_PREFIX}${itemPointer}/${j}
6584
+ ${String(item[j])}
6585
+ `;
6586
+ }
6587
+ } else {
6588
+ result += `${GADGET_ARG_PREFIX}${itemPointer}
6589
+ ${String(item)}
6590
+ `;
6591
+ }
6592
+ }
6593
+ } else if (typeof value === "object") {
6594
+ result += serializeToBlockFormat(value, pointer);
6595
+ } else {
6596
+ result += `${GADGET_ARG_PREFIX}${pointer}
6597
+ ${String(value)}
6598
+ `;
6599
+ }
6600
+ }
6601
+ return result;
6602
+ }
6779
6603
  function formatGadgetCalls(gadgetCalls) {
6780
6604
  let text = "";
6781
6605
  const calls = [];
6782
6606
  for (const call of gadgetCalls) {
6783
6607
  const invocationId = call.invocationId ?? generateInvocationId();
6784
6608
  calls.push({ name: call.gadgetName, invocationId });
6785
- const paramsJson = JSON.stringify(call.parameters);
6609
+ const blockParams = serializeToBlockFormat(call.parameters);
6786
6610
  text += `
6787
6611
  ${GADGET_START_PREFIX}${call.gadgetName}
6788
- ${paramsJson}
6789
- ${GADGET_END_PREFIX}`;
6612
+ ${blockParams}${GADGET_END_PREFIX}`;
6790
6613
  }
6791
6614
  return { text, calls };
6792
6615
  }