llmist 0.7.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.
@@ -110,12 +110,13 @@ var init_logger = __esm({
110
110
  });
111
111
 
112
112
  // src/core/constants.ts
113
- var GADGET_START_PREFIX, GADGET_END_PREFIX, DEFAULT_GADGET_OUTPUT_LIMIT, DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT, CHARS_PER_TOKEN, FALLBACK_CONTEXT_WINDOW;
113
+ var GADGET_START_PREFIX, GADGET_END_PREFIX, GADGET_ARG_PREFIX, DEFAULT_GADGET_OUTPUT_LIMIT, DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT, CHARS_PER_TOKEN, FALLBACK_CONTEXT_WINDOW;
114
114
  var init_constants = __esm({
115
115
  "src/core/constants.ts"() {
116
116
  "use strict";
117
117
  GADGET_START_PREFIX = "!!!GADGET_START:";
118
118
  GADGET_END_PREFIX = "!!!GADGET_END";
119
+ GADGET_ARG_PREFIX = "!!!ARG:";
119
120
  DEFAULT_GADGET_OUTPUT_LIMIT = true;
120
121
  DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;
121
122
  CHARS_PER_TOKEN = 4;
@@ -448,17 +449,12 @@ var init_prompt_config = __esm({
448
449
  "EACH MARKER MUST START WITH A NEWLINE."
449
450
  ].join("\n"),
450
451
  criticalUsage: "INVOKE gadgets using the markers - do not describe what you want to do.",
451
- formatDescriptionYaml: "Parameters in YAML format (one per line)",
452
- formatDescriptionJson: "Parameters in JSON format (valid JSON object)",
453
- formatDescriptionToml: "Parameters in TOML format (key = value pairs, use heredoc for multiline: key = <<<EOF ... EOF)",
452
+ formatDescription: (ctx) => `Parameters using ${ctx.argPrefix}name markers (value on next line(s), no escaping needed)`,
454
453
  rules: () => [
455
454
  "Output ONLY plain text with the exact markers - never use function/tool calling",
456
455
  "You can invoke multiple gadgets in a single response",
457
456
  "For dependent gadgets, invoke the first one and wait for the result"
458
457
  ],
459
- schemaLabelJson: "\n\nInput Schema (JSON):",
460
- schemaLabelYaml: "\n\nInput Schema (YAML):",
461
- schemaLabelToml: "\n\nInput Schema (TOML):",
462
458
  customExamples: null
463
459
  };
464
460
  }
@@ -475,6 +471,7 @@ var init_messages = __esm({
475
471
  messages = [];
476
472
  startPrefix = GADGET_START_PREFIX;
477
473
  endPrefix = GADGET_END_PREFIX;
474
+ argPrefix = GADGET_ARG_PREFIX;
478
475
  promptConfig;
479
476
  constructor(promptConfig) {
480
477
  this.promptConfig = promptConfig ?? {};
@@ -483,26 +480,32 @@ var init_messages = __esm({
483
480
  * Set custom prefixes for gadget markers.
484
481
  * Used to configure history builder to match system prompt markers.
485
482
  */
486
- withPrefixes(startPrefix, endPrefix) {
483
+ withPrefixes(startPrefix, endPrefix, argPrefix) {
487
484
  this.startPrefix = startPrefix;
488
485
  this.endPrefix = endPrefix;
486
+ if (argPrefix) {
487
+ this.argPrefix = argPrefix;
488
+ }
489
489
  return this;
490
490
  }
491
491
  addSystem(content, metadata) {
492
492
  this.messages.push({ role: "system", content, metadata });
493
493
  return this;
494
494
  }
495
- addGadgets(gadgets, parameterFormat = "json", options) {
495
+ addGadgets(gadgets, options) {
496
496
  if (options?.startPrefix) {
497
497
  this.startPrefix = options.startPrefix;
498
498
  }
499
499
  if (options?.endPrefix) {
500
500
  this.endPrefix = options.endPrefix;
501
501
  }
502
+ if (options?.argPrefix) {
503
+ this.argPrefix = options.argPrefix;
504
+ }
502
505
  const context = {
503
- parameterFormat,
504
506
  startPrefix: this.startPrefix,
505
507
  endPrefix: this.endPrefix,
508
+ argPrefix: this.argPrefix,
506
509
  gadgetCount: gadgets.length,
507
510
  gadgetNames: gadgets.map((g) => g.name ?? g.constructor.name)
508
511
  };
@@ -513,26 +516,19 @@ var init_messages = __esm({
513
516
  context
514
517
  );
515
518
  parts.push(mainInstruction);
516
- parts.push(this.buildGadgetsSection(gadgets, parameterFormat));
517
- parts.push(this.buildUsageSection(parameterFormat, context));
519
+ parts.push(this.buildGadgetsSection(gadgets));
520
+ parts.push(this.buildUsageSection(context));
518
521
  this.messages.push({ role: "system", content: parts.join("") });
519
522
  return this;
520
523
  }
521
- buildGadgetsSection(gadgets, parameterFormat) {
524
+ buildGadgetsSection(gadgets) {
522
525
  const parts = [];
523
526
  parts.push("\n\nAVAILABLE GADGETS");
524
527
  parts.push("\n=================\n");
525
528
  for (const gadget of gadgets) {
526
529
  const gadgetName = gadget.name ?? gadget.constructor.name;
527
- const instruction = gadget.getInstruction(parameterFormat);
528
- const schemaMarkers = {
529
- yaml: "\n\nInput Schema (YAML):",
530
- json: "\n\nInput Schema (JSON):",
531
- toml: "\n\nInput Schema (TOML):",
532
- auto: "\n\nInput Schema (JSON):"
533
- // auto defaults to JSON schema display
534
- };
535
- const schemaMarker = schemaMarkers[parameterFormat];
530
+ const instruction = gadget.getInstruction(this.argPrefix);
531
+ const schemaMarker = "\n\nInput Schema (BLOCK):";
536
532
  const schemaIndex = instruction.indexOf(schemaMarker);
537
533
  const description = (schemaIndex !== -1 ? instruction.substring(0, schemaIndex) : instruction).trim();
538
534
  const schema = schemaIndex !== -1 ? instruction.substring(schemaIndex + schemaMarker.length).trim() : "";
@@ -543,35 +539,20 @@ ${description}`);
543
539
  if (schema) {
544
540
  parts.push(`
545
541
 
546
- PARAMETERS (${parameterFormat.toUpperCase()}):
542
+ PARAMETERS (BLOCK):
547
543
  ${schema}`);
548
544
  }
549
545
  parts.push("\n\n---");
550
546
  }
551
547
  return parts.join("");
552
548
  }
553
- buildUsageSection(parameterFormat, context) {
549
+ buildUsageSection(context) {
554
550
  const parts = [];
555
- const formatDescriptionMap = {
556
- yaml: {
557
- config: this.promptConfig.formatDescriptionYaml,
558
- defaultValue: DEFAULT_PROMPTS.formatDescriptionYaml
559
- },
560
- json: {
561
- config: this.promptConfig.formatDescriptionJson,
562
- defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
563
- },
564
- toml: {
565
- config: this.promptConfig.formatDescriptionToml,
566
- defaultValue: DEFAULT_PROMPTS.formatDescriptionToml
567
- },
568
- auto: {
569
- config: this.promptConfig.formatDescriptionJson,
570
- defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
571
- }
572
- };
573
- const { config, defaultValue } = formatDescriptionMap[parameterFormat];
574
- const formatDescription = resolvePromptTemplate(config, defaultValue, context);
551
+ const formatDescription = resolvePromptTemplate(
552
+ this.promptConfig.formatDescription,
553
+ DEFAULT_PROMPTS.formatDescription,
554
+ context
555
+ );
575
556
  parts.push("\n\nHOW TO INVOKE GADGETS");
576
557
  parts.push("\n=====================\n");
577
558
  const criticalUsage = resolvePromptTemplate(
@@ -589,124 +570,90 @@ CRITICAL: ${criticalUsage}
589
570
  2. ${formatDescription}`);
590
571
  parts.push(`
591
572
  3. End marker: ${this.endPrefix}`);
592
- parts.push(this.buildExamplesSection(parameterFormat, context));
573
+ parts.push(this.buildExamplesSection(context));
593
574
  parts.push(this.buildRulesSection(context));
594
575
  parts.push("\n");
595
576
  return parts.join("");
596
577
  }
597
- buildExamplesSection(parameterFormat, context) {
578
+ buildExamplesSection(context) {
598
579
  if (this.promptConfig.customExamples) {
599
580
  return this.promptConfig.customExamples(context);
600
581
  }
601
582
  const parts = [];
602
- const singleExamples = {
603
- yaml: `${this.startPrefix}translate
604
- from: English
605
- to: Polish
606
- content: "Paris is the capital of France: a beautiful city."
607
- ${this.endPrefix}`,
608
- json: `${this.startPrefix}translate
609
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
610
- ${this.endPrefix}`,
611
- toml: `${this.startPrefix}translate
612
- from = "English"
613
- to = "Polish"
614
- content = "Paris is the capital of France: a beautiful city."
615
- ${this.endPrefix}`,
616
- auto: `${this.startPrefix}translate
617
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
618
- ${this.endPrefix}`
619
- };
583
+ const singleExample = `${this.startPrefix}translate
584
+ ${this.argPrefix}from
585
+ English
586
+ ${this.argPrefix}to
587
+ Polish
588
+ ${this.argPrefix}content
589
+ Paris is the capital of France: a beautiful city.
590
+ ${this.endPrefix}`;
620
591
  parts.push(`
621
592
 
622
593
  EXAMPLE (Single Gadget):
623
594
 
624
- ${singleExamples[parameterFormat]}`);
625
- const multipleExamples = {
626
- yaml: `${this.startPrefix}translate
627
- from: English
628
- to: Polish
629
- content: "Paris is the capital of France: a beautiful city."
595
+ ${singleExample}`);
596
+ const multipleExample = `${this.startPrefix}translate
597
+ ${this.argPrefix}from
598
+ English
599
+ ${this.argPrefix}to
600
+ Polish
601
+ ${this.argPrefix}content
602
+ Paris is the capital of France: a beautiful city.
630
603
  ${this.endPrefix}
631
604
  ${this.startPrefix}analyze
632
- type: economic_analysis
633
- matter: "Polish Economy"
634
- question: <<<EOF
605
+ ${this.argPrefix}type
606
+ economic_analysis
607
+ ${this.argPrefix}matter
608
+ Polish Economy
609
+ ${this.argPrefix}question
635
610
  Analyze the following:
636
611
  - Polish arms exports 2025
637
612
  - Economic implications
638
- EOF
639
- ${this.endPrefix}`,
640
- json: `${this.startPrefix}translate
641
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
642
- ${this.endPrefix}
643
- ${this.startPrefix}analyze
644
- {"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
645
- ${this.endPrefix}`,
646
- toml: `${this.startPrefix}translate
647
- from = "English"
648
- to = "Polish"
649
- content = "Paris is the capital of France: a beautiful city."
650
- ${this.endPrefix}
651
- ${this.startPrefix}analyze
652
- type = "economic_analysis"
653
- matter = "Polish Economy"
654
- question = <<<EOF
655
- Analyze the following:
656
- - Polish arms exports 2025
657
- - Economic implications
658
- EOF
659
- ${this.endPrefix}`,
660
- auto: `${this.startPrefix}translate
661
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
662
- ${this.endPrefix}
663
- ${this.startPrefix}analyze
664
- {"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
665
- ${this.endPrefix}`
666
- };
613
+ ${this.endPrefix}`;
667
614
  parts.push(`
668
615
 
669
616
  EXAMPLE (Multiple Gadgets):
670
617
 
671
- ${multipleExamples[parameterFormat]}`);
672
- if (parameterFormat === "yaml") {
673
- parts.push(`
674
-
675
- YAML HEREDOC SYNTAX:
676
- For string values with multiple lines, use heredoc syntax (<<<DELIMITER...DELIMITER):
677
-
678
- filePath: "README.md"
679
- content: <<<EOF
680
- # Project Title
618
+ ${multipleExample}`);
619
+ parts.push(`
681
620
 
682
- This content can contain:
683
- - Markdown lists
684
- - Special characters: # : -
685
- - Multiple paragraphs
686
- EOF
621
+ BLOCK FORMAT SYNTAX:
622
+ Block format uses ${this.argPrefix}name markers. Values are captured verbatim until the next marker.
687
623
 
688
- The delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.
689
- No indentation is required for the content.`);
690
- } else if (parameterFormat === "toml") {
691
- parts.push(`
624
+ ${this.argPrefix}filename
625
+ calculator.ts
626
+ ${this.argPrefix}code
627
+ class Calculator {
628
+ private history: string[] = [];
692
629
 
693
- TOML HEREDOC SYNTAX:
694
- For string values with multiple lines, use heredoc syntax (<<<DELIMITER...DELIMITER):
630
+ add(a: number, b: number): number {
631
+ const result = a + b;
632
+ this.history.push(\`\${a} + \${b} = \${result}\`);
633
+ return result;
634
+ }
635
+ }
695
636
 
696
- filePath = "README.md"
697
- content = <<<EOF
698
- # Project Title
637
+ BLOCK FORMAT RULES:
638
+ - Each parameter starts with ${this.argPrefix}parameterName on its own line
639
+ - The value starts on the NEXT line after the marker
640
+ - Value ends when the next ${this.argPrefix} or ${this.endPrefix} appears
641
+ - NO escaping needed - write values exactly as they should appear
642
+ - Perfect for code, JSON, markdown, or any content with special characters
699
643
 
700
- This content can contain:
701
- - Markdown lists
702
- - Special characters: # : -
703
- - Multiple paragraphs
704
- EOF
644
+ NESTED OBJECTS (use / separator):
645
+ ${this.argPrefix}config/timeout
646
+ 30
647
+ ${this.argPrefix}config/retries
648
+ 3
649
+ Produces: { "config": { "timeout": "30", "retries": "3" } }
705
650
 
706
- The delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.
707
- IMPORTANT: Content inside heredoc is LITERAL - do NOT escape backticks, dollar signs, or any characters.
708
- NEVER use TOML triple-quote strings ("""). ALWAYS use heredoc syntax (<<<EOF...EOF) for multiline content.`);
709
- }
651
+ ARRAYS (use numeric indices):
652
+ ${this.argPrefix}items/0
653
+ first
654
+ ${this.argPrefix}items/1
655
+ second
656
+ Produces: { "items": ["first", "second"] }`);
710
657
  return parts.join("");
711
658
  }
712
659
  buildRulesSection(context) {
@@ -727,8 +674,8 @@ NEVER use TOML triple-quote strings ("""). ALWAYS use heredoc syntax (<<<EOF...E
727
674
  this.messages.push({ role: "assistant", content, metadata });
728
675
  return this;
729
676
  }
730
- addGadgetCall(gadget, parameters, result, parameterFormat = "json") {
731
- const paramStr = this.formatParameters(parameters, parameterFormat);
677
+ addGadgetCall(gadget, parameters, result) {
678
+ const paramStr = this.formatBlockParameters(parameters, "");
732
679
  this.messages.push({
733
680
  role: "assistant",
734
681
  content: `${this.startPrefix}${gadget}
@@ -741,26 +688,32 @@ ${this.endPrefix}`
741
688
  });
742
689
  return this;
743
690
  }
744
- formatParameters(parameters, format) {
745
- if (format === "yaml") {
746
- return Object.entries(parameters).map(([key, value]) => {
747
- if (typeof value === "string") {
748
- return `${key}: ${value}`;
749
- }
750
- return `${key}: ${JSON.stringify(value)}`;
751
- }).join("\n");
752
- }
753
- if (format === "toml") {
754
- return Object.entries(parameters).map(([key, value]) => {
755
- if (typeof value === "string" && value.includes("\n")) {
756
- return `${key} = <<<EOF
757
- ${value}
758
- EOF`;
759
- }
760
- return `${key} = ${JSON.stringify(value)}`;
761
- }).join("\n");
691
+ /**
692
+ * Format parameters as Block format with JSON Pointer paths.
693
+ * Uses the configured argPrefix for consistency with system prompt.
694
+ */
695
+ formatBlockParameters(params, prefix) {
696
+ const lines = [];
697
+ for (const [key, value] of Object.entries(params)) {
698
+ const fullPath = prefix ? `${prefix}/${key}` : key;
699
+ if (Array.isArray(value)) {
700
+ value.forEach((item, index) => {
701
+ const itemPath = `${fullPath}/${index}`;
702
+ if (typeof item === "object" && item !== null) {
703
+ lines.push(this.formatBlockParameters(item, itemPath));
704
+ } else {
705
+ lines.push(`${this.argPrefix}${itemPath}`);
706
+ lines.push(String(item));
707
+ }
708
+ });
709
+ } else if (typeof value === "object" && value !== null) {
710
+ lines.push(this.formatBlockParameters(value, fullPath));
711
+ } else {
712
+ lines.push(`${this.argPrefix}${fullPath}`);
713
+ lines.push(String(value));
714
+ }
762
715
  }
763
- return JSON.stringify(parameters);
716
+ return lines.join("\n");
764
717
  }
765
718
  build() {
766
719
  return [...this.messages];
@@ -853,125 +806,72 @@ var init_schema_to_json = __esm({
853
806
  });
854
807
 
855
808
  // src/gadgets/gadget.ts
856
- function findSafeDelimiter(content) {
857
- const lines = content.split("\n");
858
- for (const delimiter of HEREDOC_DELIMITERS) {
859
- const regex = new RegExp(`^${delimiter}\\s*$`);
860
- const isUsed = lines.some((line) => regex.test(line));
861
- if (!isUsed) {
862
- return delimiter;
863
- }
864
- }
865
- let counter = 1;
866
- while (counter < 1e3) {
867
- const delimiter = `HEREDOC_${counter}`;
868
- const regex = new RegExp(`^${delimiter}\\s*$`);
869
- const isUsed = lines.some((line) => regex.test(line));
870
- if (!isUsed) {
871
- return delimiter;
872
- }
873
- counter++;
874
- }
875
- return "HEREDOC_FALLBACK";
876
- }
877
- function formatYamlValue(value, indent = "") {
878
- if (typeof value === "string") {
879
- const lines = value.split("\n");
880
- if (lines.length === 1 && !value.includes(":") && !value.startsWith("-")) {
881
- return value;
882
- }
883
- const delimiter = findSafeDelimiter(value);
884
- return `<<<${delimiter}
885
- ${value}
886
- ${delimiter}`;
887
- }
888
- if (typeof value === "number" || typeof value === "boolean") {
889
- return String(value);
890
- }
891
- if (value === null || value === void 0) {
892
- return "null";
893
- }
894
- if (Array.isArray(value)) {
895
- if (value.length === 0) return "[]";
896
- const items = value.map((item) => `${indent}- ${formatYamlValue(item, indent + " ")}`);
897
- return "\n" + items.join("\n");
898
- }
899
- if (typeof value === "object") {
900
- const entries = Object.entries(value);
901
- if (entries.length === 0) return "{}";
902
- const lines = entries.map(([k, v]) => {
903
- const formattedValue = formatYamlValue(v, indent + " ");
904
- if (formattedValue.startsWith("\n") || formattedValue.startsWith("|")) {
905
- return `${indent}${k}: ${formattedValue}`;
906
- }
907
- return `${indent}${k}: ${formattedValue}`;
908
- });
909
- return "\n" + lines.join("\n");
910
- }
911
- return yaml.dump(value).trimEnd();
912
- }
913
- function formatParamsAsYaml(params) {
809
+ function formatParamsAsBlock(params, prefix = "", argPrefix = GADGET_ARG_PREFIX) {
914
810
  const lines = [];
915
811
  for (const [key, value] of Object.entries(params)) {
916
- const formattedValue = formatYamlValue(value, "");
917
- if (formattedValue.startsWith("\n")) {
918
- lines.push(`${key}:${formattedValue}`);
812
+ const fullPath = prefix ? `${prefix}/${key}` : key;
813
+ if (Array.isArray(value)) {
814
+ value.forEach((item, index) => {
815
+ const itemPath = `${fullPath}/${index}`;
816
+ if (typeof item === "object" && item !== null) {
817
+ lines.push(formatParamsAsBlock(item, itemPath, argPrefix));
818
+ } else {
819
+ lines.push(`${argPrefix}${itemPath}`);
820
+ lines.push(String(item));
821
+ }
822
+ });
823
+ } else if (typeof value === "object" && value !== null) {
824
+ lines.push(formatParamsAsBlock(value, fullPath, argPrefix));
919
825
  } else {
920
- lines.push(`${key}: ${formattedValue}`);
826
+ lines.push(`${argPrefix}${fullPath}`);
827
+ lines.push(String(value));
921
828
  }
922
829
  }
923
830
  return lines.join("\n");
924
831
  }
925
- function formatTomlInlineTable(obj) {
926
- const entries = Object.entries(obj).map(([k, v]) => `${k} = ${formatTomlValue(v)}`);
927
- return `{ ${entries.join(", ")} }`;
928
- }
929
- function formatTomlValue(value) {
930
- if (typeof value === "string") {
931
- if (value.includes("\n")) {
932
- const delimiter = findSafeDelimiter(value);
933
- return `<<<${delimiter}
934
- ${value}
935
- ${delimiter}`;
936
- }
937
- return JSON.stringify(value);
938
- }
939
- if (typeof value === "number" || typeof value === "boolean") {
940
- return String(value);
941
- }
942
- if (value === null || value === void 0) {
943
- return '""';
944
- }
945
- if (Array.isArray(value)) {
946
- if (value.length === 0) return "[]";
947
- const items = value.map((item) => {
948
- if (typeof item === "object" && item !== null && !Array.isArray(item)) {
949
- return formatTomlInlineTable(item);
950
- }
951
- return formatTomlValue(item);
952
- });
953
- return `[${items.join(", ")}]`;
954
- }
955
- if (typeof value === "object") {
956
- return formatTomlInlineTable(value);
957
- }
958
- return JSON.stringify(value);
959
- }
960
- function formatParamsAsToml(params) {
832
+ function formatSchemaAsPlainText(schema, indent = "") {
961
833
  const lines = [];
962
- for (const [key, value] of Object.entries(params)) {
963
- lines.push(`${key} = ${formatTomlValue(value)}`);
834
+ const properties = schema.properties || {};
835
+ const required = schema.required || [];
836
+ for (const [key, prop] of Object.entries(properties)) {
837
+ const propObj = prop;
838
+ const type = propObj.type;
839
+ const description = propObj.description;
840
+ const isRequired = required.includes(key);
841
+ const enumValues = propObj.enum;
842
+ let line = `${indent}- ${key}`;
843
+ if (type === "array") {
844
+ const items = propObj.items;
845
+ const itemType = items?.type || "any";
846
+ line += ` (array of ${itemType})`;
847
+ } else if (type === "object" && propObj.properties) {
848
+ line += " (object)";
849
+ } else {
850
+ line += ` (${type})`;
851
+ }
852
+ if (isRequired) {
853
+ line += " [required]";
854
+ }
855
+ if (description) {
856
+ line += `: ${description}`;
857
+ }
858
+ if (enumValues) {
859
+ line += ` - one of: ${enumValues.map((v) => `"${v}"`).join(", ")}`;
860
+ }
861
+ lines.push(line);
862
+ if (type === "object" && propObj.properties) {
863
+ lines.push(formatSchemaAsPlainText(propObj, indent + " "));
864
+ }
964
865
  }
965
866
  return lines.join("\n");
966
867
  }
967
- var yaml, HEREDOC_DELIMITERS, BaseGadget;
868
+ var BaseGadget;
968
869
  var init_gadget = __esm({
969
870
  "src/gadgets/gadget.ts"() {
970
871
  "use strict";
971
- yaml = __toESM(require("js-yaml"), 1);
872
+ init_constants();
972
873
  init_schema_to_json();
973
874
  init_schema_validator();
974
- HEREDOC_DELIMITERS = ["EOF", "END", "DOC", "CONTENT", "TEXT", "HEREDOC", "DATA", "BLOCK"];
975
875
  BaseGadget = class {
976
876
  /**
977
877
  * The name of the gadget. Used for identification when LLM calls it.
@@ -1002,19 +902,19 @@ var init_gadget = __esm({
1002
902
  /**
1003
903
  * Auto-generated instruction text for the LLM.
1004
904
  * Combines name, description, and parameter schema into a formatted instruction.
1005
- * @deprecated Use getInstruction(format) instead for format-specific schemas
905
+ * @deprecated Use getInstruction() instead
1006
906
  */
1007
907
  get instruction() {
1008
- return this.getInstruction("yaml");
908
+ return this.getInstruction();
1009
909
  }
1010
910
  /**
1011
- * Generate instruction text for the LLM with format-specific schema.
911
+ * Generate instruction text for the LLM.
1012
912
  * Combines name, description, and parameter schema into a formatted instruction.
1013
913
  *
1014
- * @param format - Format for the schema representation ('json' | 'yaml' | 'toml' | 'auto')
914
+ * @param argPrefix - Optional custom argument prefix for block format examples
1015
915
  * @returns Formatted instruction string
1016
916
  */
1017
- getInstruction(format = "json") {
917
+ getInstruction(argPrefix) {
1018
918
  const parts = [];
1019
919
  parts.push(this.description);
1020
920
  if (this.parameterSchema) {
@@ -1023,20 +923,12 @@ var init_gadget = __esm({
1023
923
  const jsonSchema = schemaToJSONSchema(this.parameterSchema, {
1024
924
  target: "draft-7"
1025
925
  });
1026
- if (format === "json" || format === "auto") {
1027
- parts.push("\n\nInput Schema (JSON):");
1028
- parts.push(JSON.stringify(jsonSchema, null, 2));
1029
- } else if (format === "toml") {
1030
- parts.push("\n\nInput Schema (TOML):");
1031
- parts.push(JSON.stringify(jsonSchema, null, 2));
1032
- } else {
1033
- const yamlSchema = yaml.dump(jsonSchema).trimEnd();
1034
- parts.push("\n\nInput Schema (YAML):");
1035
- parts.push(yamlSchema);
1036
- }
926
+ parts.push("\n\nParameters:");
927
+ parts.push(formatSchemaAsPlainText(jsonSchema));
1037
928
  }
1038
929
  if (this.examples && this.examples.length > 0) {
1039
930
  parts.push("\n\nExamples:");
931
+ const effectiveArgPrefix = argPrefix ?? GADGET_ARG_PREFIX;
1040
932
  this.examples.forEach((example, index) => {
1041
933
  if (index > 0) {
1042
934
  parts.push("");
@@ -1045,13 +937,7 @@ var init_gadget = __esm({
1045
937
  parts.push(`# ${example.comment}`);
1046
938
  }
1047
939
  parts.push("Input:");
1048
- if (format === "json" || format === "auto") {
1049
- parts.push(JSON.stringify(example.params, null, 2));
1050
- } else if (format === "toml") {
1051
- parts.push(formatParamsAsToml(example.params));
1052
- } else {
1053
- parts.push(formatParamsAsYaml(example.params));
1054
- }
940
+ parts.push(formatParamsAsBlock(example.params, "", effectiveArgPrefix));
1055
941
  if (example.output !== void 0) {
1056
942
  parts.push("Output:");
1057
943
  parts.push(example.output);
@@ -1328,14 +1214,12 @@ var init_conversation_manager = __esm({
1328
1214
  baseMessages;
1329
1215
  initialMessages;
1330
1216
  historyBuilder;
1331
- parameterFormat;
1332
1217
  constructor(baseMessages, initialMessages, options = {}) {
1333
1218
  this.baseMessages = baseMessages;
1334
1219
  this.initialMessages = initialMessages;
1335
- this.parameterFormat = options.parameterFormat ?? "json";
1336
1220
  this.historyBuilder = new LLMMessageBuilder();
1337
1221
  if (options.startPrefix && options.endPrefix) {
1338
- this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix);
1222
+ this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix, options.argPrefix);
1339
1223
  }
1340
1224
  }
1341
1225
  addUserMessage(content) {
@@ -1345,7 +1229,7 @@ var init_conversation_manager = __esm({
1345
1229
  this.historyBuilder.addAssistant(content);
1346
1230
  }
1347
1231
  addGadgetCall(gadgetName, parameters, result) {
1348
- this.historyBuilder.addGadgetCall(gadgetName, parameters, result, this.parameterFormat);
1232
+ this.historyBuilder.addGadgetCall(gadgetName, parameters, result);
1349
1233
  }
1350
1234
  getMessages() {
1351
1235
  return [...this.baseMessages, ...this.initialMessages, ...this.historyBuilder.build()];
@@ -1368,7 +1252,7 @@ async function runWithHandlers(agentGenerator, handlers) {
1368
1252
  await handlers.onGadgetCall({
1369
1253
  gadgetName: event.call.gadgetName,
1370
1254
  parameters: event.call.parameters,
1371
- parametersYaml: event.call.parametersYaml
1255
+ parametersRaw: event.call.parametersRaw
1372
1256
  });
1373
1257
  }
1374
1258
  break;
@@ -1645,7 +1529,7 @@ var init_executor = __esm({
1645
1529
  this.logger.error("Gadget parameter parse error", {
1646
1530
  gadgetName: call.gadgetName,
1647
1531
  parseError: call.parseError,
1648
- rawParameters: call.parametersYaml
1532
+ rawParameters: call.parametersRaw
1649
1533
  });
1650
1534
  return {
1651
1535
  gadgetName: call.gadgetName,
@@ -1807,168 +1691,107 @@ var init_executor = __esm({
1807
1691
  }
1808
1692
  });
1809
1693
 
1810
- // src/gadgets/parser.ts
1811
- function preprocessYaml(yamlStr) {
1812
- const lines = yamlStr.split("\n");
1813
- const result = [];
1814
- let i = 0;
1815
- while (i < lines.length) {
1816
- const line = lines[i];
1817
- const heredocMatch = line.match(/^(\s*)([\w-]+):\s*<<<([A-Za-z_][A-Za-z0-9_]*)\s*$/);
1818
- if (heredocMatch) {
1819
- const [, indent, key, delimiter] = heredocMatch;
1820
- const bodyLines = [];
1821
- i++;
1822
- const closingRegex = new RegExp(`^${delimiter}\\s*$`);
1823
- while (i < lines.length && !closingRegex.test(lines[i])) {
1824
- bodyLines.push(lines[i]);
1825
- i++;
1826
- }
1827
- if (i < lines.length) {
1828
- i++;
1829
- }
1830
- result.push(`${indent}${key}: |`);
1831
- for (const bodyLine of bodyLines) {
1832
- result.push(`${indent} ${bodyLine}`);
1694
+ // src/gadgets/block-params.ts
1695
+ function parseBlockParams(content, options) {
1696
+ const argPrefix = options?.argPrefix ?? GADGET_ARG_PREFIX;
1697
+ const result = {};
1698
+ const seenPointers = /* @__PURE__ */ new Set();
1699
+ const parts = content.split(argPrefix);
1700
+ for (let i = 1; i < parts.length; i++) {
1701
+ const part = parts[i];
1702
+ const newlineIndex = part.indexOf("\n");
1703
+ if (newlineIndex === -1) {
1704
+ const pointer2 = part.trim();
1705
+ if (pointer2) {
1706
+ if (seenPointers.has(pointer2)) {
1707
+ throw new Error(`Duplicate pointer: ${pointer2}`);
1708
+ }
1709
+ seenPointers.add(pointer2);
1710
+ setByPointer(result, pointer2, "");
1833
1711
  }
1834
1712
  continue;
1835
1713
  }
1836
- const match = line.match(/^(\s*)([\w-]+):\s+(.+)$/);
1837
- if (match) {
1838
- const [, indent, key, value] = match;
1839
- if (value === "|" || value === ">" || value === "|-" || value === ">-") {
1840
- result.push(line);
1841
- i++;
1842
- const keyIndentLen2 = indent.length;
1843
- const blockLines = [];
1844
- let minContentIndent = Infinity;
1845
- while (i < lines.length) {
1846
- const blockLine = lines[i];
1847
- const blockIndentMatch = blockLine.match(/^(\s*)/);
1848
- const blockIndentLen = blockIndentMatch ? blockIndentMatch[1].length : 0;
1849
- if (blockLine.trim() === "") {
1850
- blockLines.push({ content: "", originalIndent: 0 });
1851
- i++;
1852
- continue;
1853
- }
1854
- if (blockIndentLen > keyIndentLen2) {
1855
- const content = blockLine.substring(blockIndentLen);
1856
- blockLines.push({ content, originalIndent: blockIndentLen });
1857
- if (content.trim().length > 0) {
1858
- minContentIndent = Math.min(minContentIndent, blockIndentLen);
1859
- }
1860
- i++;
1861
- } else {
1862
- break;
1863
- }
1864
- }
1865
- const targetIndent = keyIndentLen2 + 2;
1866
- for (const blockLine of blockLines) {
1867
- if (blockLine.content === "") {
1868
- result.push("");
1869
- } else {
1870
- result.push(" ".repeat(targetIndent) + blockLine.content);
1871
- }
1872
- }
1873
- continue;
1874
- }
1875
- if (value.startsWith('"') || value.startsWith("'") || value === "true" || value === "false" || /^-?\d+(\.\d+)?$/.test(value)) {
1876
- result.push(line);
1877
- i++;
1878
- continue;
1879
- }
1880
- const keyIndentLen = indent.length;
1881
- const continuationLines = [];
1882
- let j = i + 1;
1883
- while (j < lines.length) {
1884
- const nextLine = lines[j];
1885
- if (nextLine.trim() === "") {
1886
- continuationLines.push(nextLine);
1887
- j++;
1888
- continue;
1889
- }
1890
- const nextIndentMatch = nextLine.match(/^(\s*)/);
1891
- const nextIndentLen = nextIndentMatch ? nextIndentMatch[1].length : 0;
1892
- if (nextIndentLen > keyIndentLen) {
1893
- continuationLines.push(nextLine);
1894
- j++;
1895
- } else {
1896
- break;
1897
- }
1898
- }
1899
- if (continuationLines.length > 0 && continuationLines.some((l) => l.trim().length > 0)) {
1900
- result.push(`${indent}${key}: |`);
1901
- result.push(`${indent} ${value}`);
1902
- for (const contLine of continuationLines) {
1903
- if (contLine.trim() === "") {
1904
- result.push("");
1905
- } else {
1906
- const contIndentMatch = contLine.match(/^(\s*)/);
1907
- const contIndent = contIndentMatch ? contIndentMatch[1] : "";
1908
- const contContent = contLine.substring(contIndent.length);
1909
- result.push(`${indent} ${contContent}`);
1910
- }
1911
- }
1912
- i = j;
1913
- continue;
1914
- }
1915
- if (value.includes(": ") || value.endsWith(":")) {
1916
- const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
1917
- result.push(`${indent}${key}: "${escaped}"`);
1918
- i++;
1919
- continue;
1920
- }
1714
+ const pointer = part.substring(0, newlineIndex).trim();
1715
+ let value = part.substring(newlineIndex + 1);
1716
+ if (value.endsWith("\n")) {
1717
+ value = value.slice(0, -1);
1718
+ }
1719
+ if (!pointer) {
1720
+ continue;
1721
+ }
1722
+ if (seenPointers.has(pointer)) {
1723
+ throw new Error(`Duplicate pointer: ${pointer}`);
1921
1724
  }
1922
- result.push(line);
1923
- i++;
1725
+ seenPointers.add(pointer);
1726
+ setByPointer(result, pointer, value);
1924
1727
  }
1925
- return result.join("\n");
1728
+ return result;
1926
1729
  }
1927
- function unescapeHeredocContent(content) {
1928
- return content.replace(/\\`/g, "`").replace(/\\\$/g, "$").replace(/\\{/g, "{").replace(/\\}/g, "}");
1730
+ function coerceValue(value) {
1731
+ if (value.includes("\n")) {
1732
+ return value;
1733
+ }
1734
+ const trimmed = value.trim();
1735
+ if (trimmed === "true") return true;
1736
+ if (trimmed === "false") return false;
1737
+ if (trimmed !== "" && /^-?\d+(\.\d+)?$/.test(trimmed)) {
1738
+ const num = Number(trimmed);
1739
+ if (!isNaN(num) && isFinite(num)) {
1740
+ return num;
1741
+ }
1742
+ }
1743
+ return value;
1929
1744
  }
1930
- function preprocessTomlHeredoc(tomlStr) {
1931
- const lines = tomlStr.split("\n");
1932
- const result = [];
1933
- let i = 0;
1934
- const heredocStartRegex = /^(\s*)([\w-]+)\s*=\s*<<<([A-Za-z_][A-Za-z0-9_]*)\s*$/;
1935
- while (i < lines.length) {
1936
- const line = lines[i];
1937
- const match = line.match(heredocStartRegex);
1938
- if (match) {
1939
- const [, indent, key, delimiter] = match;
1940
- const bodyLines = [];
1941
- i++;
1942
- const closingRegex = new RegExp(`^${delimiter}\\s*$`);
1943
- let foundClosing = false;
1944
- while (i < lines.length) {
1945
- const bodyLine = lines[i];
1946
- if (closingRegex.test(bodyLine)) {
1947
- foundClosing = true;
1948
- i++;
1949
- break;
1950
- }
1951
- bodyLines.push(bodyLine);
1952
- i++;
1953
- }
1954
- if (bodyLines.length === 0) {
1955
- result.push(`${indent}${key} = ''''''`);
1956
- } else {
1957
- result.push(`${indent}${key} = '''`);
1958
- for (let j = 0; j < bodyLines.length - 1; j++) {
1959
- result.push(unescapeHeredocContent(bodyLines[j]));
1960
- }
1961
- result.push(`${unescapeHeredocContent(bodyLines[bodyLines.length - 1])}'''`);
1962
- }
1963
- if (!foundClosing) {
1745
+ function setByPointer(obj, pointer, value) {
1746
+ const segments = pointer.split("/");
1747
+ let current = obj;
1748
+ for (let i = 0; i < segments.length - 1; i++) {
1749
+ const segment = segments[i];
1750
+ const nextSegment = segments[i + 1];
1751
+ const nextIsArrayIndex = /^\d+$/.test(nextSegment);
1752
+ if (Array.isArray(current)) {
1753
+ const index = parseInt(segment, 10);
1754
+ if (isNaN(index) || index < 0) {
1755
+ throw new Error(`Invalid array index: ${segment}`);
1756
+ }
1757
+ if (index > current.length) {
1758
+ throw new Error(`Array index gap: expected ${current.length}, got ${index}`);
1759
+ }
1760
+ if (current[index] === void 0) {
1761
+ current[index] = nextIsArrayIndex ? [] : {};
1762
+ }
1763
+ current = current[index];
1764
+ } else {
1765
+ const rec = current;
1766
+ if (rec[segment] === void 0) {
1767
+ rec[segment] = nextIsArrayIndex ? [] : {};
1964
1768
  }
1965
- continue;
1769
+ current = rec[segment];
1770
+ }
1771
+ }
1772
+ const lastSegment = segments[segments.length - 1];
1773
+ const coercedValue = coerceValue(value);
1774
+ if (Array.isArray(current)) {
1775
+ const index = parseInt(lastSegment, 10);
1776
+ if (isNaN(index) || index < 0) {
1777
+ throw new Error(`Invalid array index: ${lastSegment}`);
1966
1778
  }
1967
- result.push(line);
1968
- i++;
1779
+ if (index > current.length) {
1780
+ throw new Error(`Array index gap: expected ${current.length}, got ${index}`);
1781
+ }
1782
+ current[index] = coercedValue;
1783
+ } else {
1784
+ current[lastSegment] = coercedValue;
1969
1785
  }
1970
- return result.join("\n");
1971
1786
  }
1787
+ var init_block_params = __esm({
1788
+ "src/gadgets/block-params.ts"() {
1789
+ "use strict";
1790
+ init_constants();
1791
+ }
1792
+ });
1793
+
1794
+ // src/gadgets/parser.ts
1972
1795
  function stripMarkdownFences(content) {
1973
1796
  let cleaned = content.trim();
1974
1797
  const openingFence = /^```(?:toml|yaml|json)?\s*\n/i;
@@ -1977,24 +1800,23 @@ function stripMarkdownFences(content) {
1977
1800
  cleaned = cleaned.replace(closingFence, "");
1978
1801
  return cleaned.trim();
1979
1802
  }
1980
- var yaml2, import_js_toml, globalInvocationCounter, StreamParser;
1803
+ var globalInvocationCounter, StreamParser;
1981
1804
  var init_parser = __esm({
1982
1805
  "src/gadgets/parser.ts"() {
1983
1806
  "use strict";
1984
- yaml2 = __toESM(require("js-yaml"), 1);
1985
- import_js_toml = require("js-toml");
1986
1807
  init_constants();
1808
+ init_block_params();
1987
1809
  globalInvocationCounter = 0;
1988
1810
  StreamParser = class {
1989
1811
  buffer = "";
1990
1812
  lastReportedTextLength = 0;
1991
1813
  startPrefix;
1992
1814
  endPrefix;
1993
- parameterFormat;
1815
+ argPrefix;
1994
1816
  constructor(options = {}) {
1995
1817
  this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;
1996
1818
  this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;
1997
- this.parameterFormat = options.parameterFormat ?? "json";
1819
+ this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;
1998
1820
  }
1999
1821
  takeTextUntil(index) {
2000
1822
  if (index <= this.lastReportedTextLength) {
@@ -2029,43 +1851,14 @@ var init_parser = __esm({
2029
1851
  return `${firstLine.slice(0, maxLen)}... (${message.length} chars total)`;
2030
1852
  }
2031
1853
  /**
2032
- * Parse parameter string according to configured format
1854
+ * Parse parameter string using block format
2033
1855
  */
2034
1856
  parseParameters(raw) {
2035
1857
  const cleaned = stripMarkdownFences(raw);
2036
- if (this.parameterFormat === "json") {
2037
- try {
2038
- return { parameters: JSON.parse(cleaned) };
2039
- } catch (error) {
2040
- return { parseError: this.truncateParseError(error, "JSON") };
2041
- }
2042
- }
2043
- if (this.parameterFormat === "yaml") {
2044
- try {
2045
- return { parameters: yaml2.load(preprocessYaml(cleaned)) };
2046
- } catch (error) {
2047
- return { parseError: this.truncateParseError(error, "YAML") };
2048
- }
2049
- }
2050
- if (this.parameterFormat === "toml") {
2051
- try {
2052
- return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(cleaned)) };
2053
- } catch (error) {
2054
- return { parseError: this.truncateParseError(error, "TOML") };
2055
- }
2056
- }
2057
1858
  try {
2058
- return { parameters: JSON.parse(cleaned) };
2059
- } catch {
2060
- try {
2061
- return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(cleaned)) };
2062
- } catch {
2063
- try {
2064
- return { parameters: yaml2.load(preprocessYaml(cleaned)) };
2065
- } catch (error) {
2066
- return { parseError: this.truncateParseError(error, "auto") };
2067
- }
2068
- }
1859
+ return { parameters: parseBlockParams(cleaned, { argPrefix: this.argPrefix }) };
1860
+ } catch (error) {
1861
+ return { parseError: this.truncateParseError(error, "block") };
2069
1862
  }
2070
1863
  }
2071
1864
  // Feed a chunk of text and get parsed events
@@ -2124,8 +1917,7 @@ var init_parser = __esm({
2124
1917
  call: {
2125
1918
  gadgetName: actualGadgetName,
2126
1919
  invocationId,
2127
- parametersYaml: parametersRaw,
2128
- // Keep property name for backward compatibility
1920
+ parametersRaw,
2129
1921
  parameters,
2130
1922
  parseError
2131
1923
  }
@@ -2159,7 +1951,7 @@ var init_parser = __esm({
2159
1951
  call: {
2160
1952
  gadgetName: actualGadgetName,
2161
1953
  invocationId,
2162
- parametersYaml: parametersRaw,
1954
+ parametersRaw,
2163
1955
  parameters,
2164
1956
  parseError
2165
1957
  }
@@ -2210,9 +2002,9 @@ var init_stream_processor = __esm({
2210
2002
  this.stopOnGadgetError = options.stopOnGadgetError ?? true;
2211
2003
  this.shouldContinueAfterError = options.shouldContinueAfterError;
2212
2004
  this.parser = new StreamParser({
2213
- parameterFormat: options.parameterFormat,
2214
2005
  startPrefix: options.gadgetStartPrefix,
2215
- endPrefix: options.gadgetEndPrefix
2006
+ endPrefix: options.gadgetEndPrefix,
2007
+ argPrefix: options.gadgetArgPrefix
2216
2008
  });
2217
2009
  this.executor = new GadgetExecutor(
2218
2010
  options.registry,
@@ -2366,7 +2158,7 @@ var init_stream_processor = __esm({
2366
2158
  this.logger.warn("Gadget has parse error", {
2367
2159
  gadgetName: call.gadgetName,
2368
2160
  error: call.parseError,
2369
- rawParameters: call.parametersYaml
2161
+ rawParameters: call.parametersRaw
2370
2162
  });
2371
2163
  const shouldContinue = await this.checkContinueAfterError(
2372
2164
  call.parseError,
@@ -2602,9 +2394,9 @@ var init_agent = __esm({
2602
2394
  hooks;
2603
2395
  conversation;
2604
2396
  registry;
2605
- parameterFormat;
2606
2397
  gadgetStartPrefix;
2607
2398
  gadgetEndPrefix;
2399
+ gadgetArgPrefix;
2608
2400
  onHumanInputRequired;
2609
2401
  textOnlyHandler;
2610
2402
  textWithGadgetsHandler;
@@ -2633,9 +2425,9 @@ var init_agent = __esm({
2633
2425
  this.temperature = options.temperature;
2634
2426
  this.logger = options.logger ?? createLogger({ name: "llmist:agent" });
2635
2427
  this.registry = options.registry;
2636
- this.parameterFormat = options.parameterFormat ?? "json";
2637
2428
  this.gadgetStartPrefix = options.gadgetStartPrefix;
2638
2429
  this.gadgetEndPrefix = options.gadgetEndPrefix;
2430
+ this.gadgetArgPrefix = options.gadgetArgPrefix;
2639
2431
  this.onHumanInputRequired = options.onHumanInputRequired;
2640
2432
  this.textOnlyHandler = options.textOnlyHandler ?? "terminate";
2641
2433
  this.textWithGadgetsHandler = options.textWithGadgetsHandler;
@@ -2657,9 +2449,10 @@ var init_agent = __esm({
2657
2449
  if (options.systemPrompt) {
2658
2450
  baseBuilder.addSystem(options.systemPrompt);
2659
2451
  }
2660
- baseBuilder.addGadgets(this.registry.getAll(), this.parameterFormat, {
2452
+ baseBuilder.addGadgets(this.registry.getAll(), {
2661
2453
  startPrefix: options.gadgetStartPrefix,
2662
- endPrefix: options.gadgetEndPrefix
2454
+ endPrefix: options.gadgetEndPrefix,
2455
+ argPrefix: options.gadgetArgPrefix
2663
2456
  });
2664
2457
  const baseMessages = baseBuilder.build();
2665
2458
  const initialMessages = (options.initialMessages ?? []).map((message) => ({
@@ -2667,9 +2460,9 @@ var init_agent = __esm({
2667
2460
  content: message.content
2668
2461
  }));
2669
2462
  this.conversation = new ConversationManager(baseMessages, initialMessages, {
2670
- parameterFormat: this.parameterFormat,
2671
2463
  startPrefix: options.gadgetStartPrefix,
2672
- endPrefix: options.gadgetEndPrefix
2464
+ endPrefix: options.gadgetEndPrefix,
2465
+ argPrefix: options.gadgetArgPrefix
2673
2466
  });
2674
2467
  this.userPromptProvided = !!options.userPrompt;
2675
2468
  if (options.userPrompt) {
@@ -2762,9 +2555,9 @@ var init_agent = __esm({
2762
2555
  const processor = new StreamProcessor({
2763
2556
  iteration: currentIteration,
2764
2557
  registry: this.registry,
2765
- parameterFormat: this.parameterFormat,
2766
2558
  gadgetStartPrefix: this.gadgetStartPrefix,
2767
2559
  gadgetEndPrefix: this.gadgetEndPrefix,
2560
+ gadgetArgPrefix: this.gadgetArgPrefix,
2768
2561
  hooks: this.hooks,
2769
2562
  logger: this.logger.getSubLogger({ name: "stream-processor" }),
2770
2563
  onHumanInputRequired: this.onHumanInputRequired,
@@ -3057,9 +2850,9 @@ var init_builder = __esm({
3057
2850
  gadgets = [];
3058
2851
  initialMessages = [];
3059
2852
  onHumanInputRequired;
3060
- parameterFormat;
3061
2853
  gadgetStartPrefix;
3062
2854
  gadgetEndPrefix;
2855
+ gadgetArgPrefix;
3063
2856
  textOnlyHandler;
3064
2857
  textWithGadgetsHandler;
3065
2858
  stopOnGadgetError;
@@ -3246,21 +3039,6 @@ var init_builder = __esm({
3246
3039
  this.onHumanInputRequired = handler;
3247
3040
  return this;
3248
3041
  }
3249
- /**
3250
- * Set the parameter format for gadget calls.
3251
- *
3252
- * @param format - Parameter format ("json" or "xml")
3253
- * @returns This builder for chaining
3254
- *
3255
- * @example
3256
- * ```typescript
3257
- * .withParameterFormat("xml")
3258
- * ```
3259
- */
3260
- withParameterFormat(format) {
3261
- this.parameterFormat = format;
3262
- return this;
3263
- }
3264
3042
  /**
3265
3043
  * Set custom gadget marker prefix.
3266
3044
  *
@@ -3291,6 +3069,21 @@ var init_builder = __esm({
3291
3069
  this.gadgetEndPrefix = suffix;
3292
3070
  return this;
3293
3071
  }
3072
+ /**
3073
+ * Set custom argument prefix for block format parameters.
3074
+ *
3075
+ * @param prefix - Custom prefix for argument markers (default: "!!!ARG:")
3076
+ * @returns This builder for chaining
3077
+ *
3078
+ * @example
3079
+ * ```typescript
3080
+ * .withGadgetArgPrefix("<<ARG>>")
3081
+ * ```
3082
+ */
3083
+ withGadgetArgPrefix(prefix) {
3084
+ this.gadgetArgPrefix = prefix;
3085
+ return this;
3086
+ }
3294
3087
  /**
3295
3088
  * Set the text-only handler strategy.
3296
3089
  *
@@ -3490,8 +3283,7 @@ var init_builder = __esm({
3490
3283
  withSyntheticGadgetCall(gadgetName, parameters, result) {
3491
3284
  const startPrefix = this.gadgetStartPrefix ?? GADGET_START_PREFIX;
3492
3285
  const endPrefix = this.gadgetEndPrefix ?? GADGET_END_PREFIX;
3493
- const format = this.parameterFormat ?? "yaml";
3494
- const paramStr = this.formatSyntheticParameters(parameters, format);
3286
+ const paramStr = this.formatBlockParameters(parameters, "");
3495
3287
  this.initialMessages.push({
3496
3288
  role: "assistant",
3497
3289
  content: `${startPrefix}${gadgetName}
@@ -3505,25 +3297,31 @@ ${endPrefix}`
3505
3297
  return this;
3506
3298
  }
3507
3299
  /**
3508
- * Format parameters for synthetic gadget calls.
3509
- * Uses heredoc for multiline string values.
3300
+ * Format parameters as block format with JSON Pointer paths.
3510
3301
  */
3511
- formatSyntheticParameters(parameters, format) {
3512
- if (format === "json" || format === "auto") {
3513
- return JSON.stringify(parameters);
3514
- }
3515
- return Object.entries(parameters).map(([key, value]) => {
3516
- if (typeof value === "string" && value.includes("\n")) {
3517
- const separator = format === "yaml" ? ":" : " =";
3518
- return `${key}${separator} <<<EOF
3519
- ${value}
3520
- EOF`;
3521
- }
3522
- if (format === "yaml") {
3523
- return typeof value === "string" ? `${key}: ${value}` : `${key}: ${JSON.stringify(value)}`;
3302
+ formatBlockParameters(params, prefix) {
3303
+ const lines = [];
3304
+ const argPrefix = this.gadgetArgPrefix ?? GADGET_ARG_PREFIX;
3305
+ for (const [key, value] of Object.entries(params)) {
3306
+ const fullPath = prefix ? `${prefix}/${key}` : key;
3307
+ if (Array.isArray(value)) {
3308
+ value.forEach((item, index) => {
3309
+ const itemPath = `${fullPath}/${index}`;
3310
+ if (typeof item === "object" && item !== null) {
3311
+ lines.push(this.formatBlockParameters(item, itemPath));
3312
+ } else {
3313
+ lines.push(`${argPrefix}${itemPath}`);
3314
+ lines.push(String(item));
3315
+ }
3316
+ });
3317
+ } else if (typeof value === "object" && value !== null) {
3318
+ lines.push(this.formatBlockParameters(value, fullPath));
3319
+ } else {
3320
+ lines.push(`${argPrefix}${fullPath}`);
3321
+ lines.push(String(value));
3524
3322
  }
3525
- return `${key} = ${JSON.stringify(value)}`;
3526
- }).join("\n");
3323
+ }
3324
+ return lines.join("\n");
3527
3325
  }
3528
3326
  /**
3529
3327
  * Build and create the agent with the given user prompt.
@@ -3563,9 +3361,9 @@ EOF`;
3563
3361
  promptConfig: this.promptConfig,
3564
3362
  initialMessages: this.initialMessages,
3565
3363
  onHumanInputRequired: this.onHumanInputRequired,
3566
- parameterFormat: this.parameterFormat,
3567
3364
  gadgetStartPrefix: this.gadgetStartPrefix,
3568
3365
  gadgetEndPrefix: this.gadgetEndPrefix,
3366
+ gadgetArgPrefix: this.gadgetArgPrefix,
3569
3367
  textOnlyHandler: this.textOnlyHandler,
3570
3368
  textWithGadgetsHandler: this.textWithGadgetsHandler,
3571
3369
  stopOnGadgetError: this.stopOnGadgetError,
@@ -3665,9 +3463,9 @@ EOF`;
3665
3463
  promptConfig: this.promptConfig,
3666
3464
  initialMessages: this.initialMessages,
3667
3465
  onHumanInputRequired: this.onHumanInputRequired,
3668
- parameterFormat: this.parameterFormat,
3669
3466
  gadgetStartPrefix: this.gadgetStartPrefix,
3670
3467
  gadgetEndPrefix: this.gadgetEndPrefix,
3468
+ gadgetArgPrefix: this.gadgetArgPrefix,
3671
3469
  textOnlyHandler: this.textOnlyHandler,
3672
3470
  textWithGadgetsHandler: this.textWithGadgetsHandler,
3673
3471
  stopOnGadgetError: this.stopOnGadgetError,
@@ -3697,7 +3495,8 @@ var init_anthropic_models = __esm({
3697
3495
  pricing: {
3698
3496
  input: 3,
3699
3497
  output: 15,
3700
- cachedInput: 0.3
3498
+ cachedInput: 0.3,
3499
+ cacheWriteInput: 3.75
3701
3500
  },
3702
3501
  knowledgeCutoff: "2025-01",
3703
3502
  features: {
@@ -3721,7 +3520,8 @@ var init_anthropic_models = __esm({
3721
3520
  pricing: {
3722
3521
  input: 1,
3723
3522
  output: 5,
3724
- cachedInput: 0.1
3523
+ cachedInput: 0.1,
3524
+ cacheWriteInput: 1.25
3725
3525
  },
3726
3526
  knowledgeCutoff: "2025-02",
3727
3527
  features: {
@@ -3745,7 +3545,8 @@ var init_anthropic_models = __esm({
3745
3545
  pricing: {
3746
3546
  input: 3,
3747
3547
  output: 15,
3748
- cachedInput: 0.3
3548
+ cachedInput: 0.3,
3549
+ cacheWriteInput: 3.75
3749
3550
  },
3750
3551
  knowledgeCutoff: "2025-03",
3751
3552
  features: {
@@ -3769,7 +3570,8 @@ var init_anthropic_models = __esm({
3769
3570
  pricing: {
3770
3571
  input: 3,
3771
3572
  output: 15,
3772
- cachedInput: 0.3
3573
+ cachedInput: 0.3,
3574
+ cacheWriteInput: 3.75
3773
3575
  },
3774
3576
  knowledgeCutoff: "2024-11",
3775
3577
  features: {
@@ -3793,7 +3595,8 @@ var init_anthropic_models = __esm({
3793
3595
  pricing: {
3794
3596
  input: 15,
3795
3597
  output: 75,
3796
- cachedInput: 1.5
3598
+ cachedInput: 1.5,
3599
+ cacheWriteInput: 18.75
3797
3600
  },
3798
3601
  knowledgeCutoff: "2025-01",
3799
3602
  features: {
@@ -3817,7 +3620,8 @@ var init_anthropic_models = __esm({
3817
3620
  pricing: {
3818
3621
  input: 15,
3819
3622
  output: 75,
3820
- cachedInput: 1.5
3623
+ cachedInput: 1.5,
3624
+ cacheWriteInput: 18.75
3821
3625
  },
3822
3626
  knowledgeCutoff: "2025-03",
3823
3627
  features: {
@@ -3840,7 +3644,8 @@ var init_anthropic_models = __esm({
3840
3644
  pricing: {
3841
3645
  input: 0.8,
3842
3646
  output: 4,
3843
- cachedInput: 0.08
3647
+ cachedInput: 0.08,
3648
+ cacheWriteInput: 1
3844
3649
  },
3845
3650
  knowledgeCutoff: "2024-07",
3846
3651
  features: {
@@ -3863,7 +3668,8 @@ var init_anthropic_models = __esm({
3863
3668
  pricing: {
3864
3669
  input: 0.25,
3865
3670
  output: 1.25,
3866
- cachedInput: 0.025
3671
+ cachedInput: 0.025,
3672
+ cacheWriteInput: 0.3125
3867
3673
  },
3868
3674
  knowledgeCutoff: "2023-08",
3869
3675
  features: {
@@ -3887,7 +3693,8 @@ var init_anthropic_models = __esm({
3887
3693
  pricing: {
3888
3694
  input: 1,
3889
3695
  output: 5,
3890
- cachedInput: 0.1
3696
+ cachedInput: 0.1,
3697
+ cacheWriteInput: 1.25
3891
3698
  },
3892
3699
  knowledgeCutoff: "2025-02",
3893
3700
  features: {
@@ -3911,7 +3718,8 @@ var init_anthropic_models = __esm({
3911
3718
  pricing: {
3912
3719
  input: 3,
3913
3720
  output: 15,
3914
- cachedInput: 0.3
3721
+ cachedInput: 0.3,
3722
+ cacheWriteInput: 3.75
3915
3723
  },
3916
3724
  knowledgeCutoff: "2025-01",
3917
3725
  features: {
@@ -3935,7 +3743,8 @@ var init_anthropic_models = __esm({
3935
3743
  pricing: {
3936
3744
  input: 5,
3937
3745
  output: 25,
3938
- cachedInput: 0.5
3746
+ cachedInput: 0.5,
3747
+ cacheWriteInput: 6.25
3939
3748
  },
3940
3749
  knowledgeCutoff: "2025-03",
3941
3750
  features: {
@@ -4050,15 +3859,27 @@ var init_anthropic = __esm({
4050
3859
  }
4051
3860
  buildRequestPayload(options, descriptor, spec, messages) {
4052
3861
  const systemMessages = messages.filter((message) => message.role === "system");
4053
- const system = systemMessages.length > 0 ? systemMessages.map((m) => m.content).join("\n\n") : void 0;
4054
- const conversation = messages.filter(
3862
+ const system = systemMessages.length > 0 ? systemMessages.map((m, index) => ({
3863
+ type: "text",
3864
+ text: m.content,
3865
+ // Add cache_control to the LAST system message block
3866
+ ...index === systemMessages.length - 1 ? { cache_control: { type: "ephemeral" } } : {}
3867
+ })) : void 0;
3868
+ const nonSystemMessages = messages.filter(
4055
3869
  (message) => message.role !== "system"
4056
- ).map((message) => ({
3870
+ );
3871
+ const lastUserIndex = nonSystemMessages.reduce(
3872
+ (lastIdx, msg, idx) => msg.role === "user" ? idx : lastIdx,
3873
+ -1
3874
+ );
3875
+ const conversation = nonSystemMessages.map((message, index) => ({
4057
3876
  role: message.role,
4058
3877
  content: [
4059
3878
  {
4060
3879
  type: "text",
4061
- text: message.content
3880
+ text: message.content,
3881
+ // Add cache_control to the LAST user message
3882
+ ...message.role === "user" && index === lastUserIndex ? { cache_control: { type: "ephemeral" } } : {}
4062
3883
  }
4063
3884
  ]
4064
3885
  }));
@@ -4084,15 +3905,22 @@ var init_anthropic = __esm({
4084
3905
  async *wrapStream(iterable) {
4085
3906
  const stream2 = iterable;
4086
3907
  let inputTokens = 0;
3908
+ let cachedInputTokens = 0;
3909
+ let cacheCreationInputTokens = 0;
4087
3910
  for await (const event of stream2) {
4088
3911
  if (event.type === "message_start") {
4089
- inputTokens = event.message.usage.input_tokens;
3912
+ const usage = event.message.usage;
3913
+ cachedInputTokens = usage.cache_read_input_tokens ?? 0;
3914
+ cacheCreationInputTokens = usage.cache_creation_input_tokens ?? 0;
3915
+ inputTokens = usage.input_tokens + cachedInputTokens + cacheCreationInputTokens;
4090
3916
  yield {
4091
3917
  text: "",
4092
3918
  usage: {
4093
3919
  inputTokens,
4094
3920
  outputTokens: 0,
4095
- totalTokens: inputTokens
3921
+ totalTokens: inputTokens,
3922
+ cachedInputTokens,
3923
+ cacheCreationInputTokens
4096
3924
  },
4097
3925
  rawEvent: event
4098
3926
  };
@@ -4106,7 +3934,9 @@ var init_anthropic = __esm({
4106
3934
  const usage = event.usage ? {
4107
3935
  inputTokens,
4108
3936
  outputTokens: event.usage.output_tokens,
4109
- totalTokens: inputTokens + event.usage.output_tokens
3937
+ totalTokens: inputTokens + event.usage.output_tokens,
3938
+ cachedInputTokens,
3939
+ cacheCreationInputTokens
4110
3940
  } : void 0;
4111
3941
  if (event.delta.stop_reason || usage) {
4112
3942
  yield {
@@ -4187,6 +4017,7 @@ var init_gemini_models = __esm({
4187
4017
  "src/providers/gemini-models.ts"() {
4188
4018
  "use strict";
4189
4019
  GEMINI_MODELS = [
4020
+ // Gemini 3 Pro (Preview)
4190
4021
  {
4191
4022
  provider: "gemini",
4192
4023
  modelId: "gemini-3-pro-preview",
@@ -4195,8 +4026,11 @@ var init_gemini_models = __esm({
4195
4026
  maxOutputTokens: 65536,
4196
4027
  pricing: {
4197
4028
  input: 2,
4029
+ // $2.00 for prompts <= 200k, $4.00 for > 200k (using lower tier)
4198
4030
  output: 12,
4031
+ // $12.00 for prompts <= 200k, $18.00 for > 200k
4199
4032
  cachedInput: 0.2
4033
+ // $0.20 for prompts <= 200k
4200
4034
  },
4201
4035
  knowledgeCutoff: "2025-01",
4202
4036
  features: {
@@ -4209,9 +4043,10 @@ var init_gemini_models = __esm({
4209
4043
  metadata: {
4210
4044
  family: "Gemini 3",
4211
4045
  releaseDate: "2025-11-18",
4212
- notes: "Most advanced model. 1501 Elo LMArena, 91.9% GPQA Diamond, 76.2% SWE-bench. Deep Think mode available."
4046
+ notes: "Best model for multimodal understanding, agentic and vibe-coding. Deep Think mode available."
4213
4047
  }
4214
4048
  },
4049
+ // Gemini 2.5 Pro
4215
4050
  {
4216
4051
  provider: "gemini",
4217
4052
  modelId: "gemini-2.5-pro",
@@ -4220,8 +4055,11 @@ var init_gemini_models = __esm({
4220
4055
  maxOutputTokens: 65536,
4221
4056
  pricing: {
4222
4057
  input: 1.25,
4058
+ // $1.25 for prompts <= 200k, $2.50 for > 200k
4223
4059
  output: 10,
4060
+ // $10.00 for prompts <= 200k, $15.00 for > 200k
4224
4061
  cachedInput: 0.125
4062
+ // $0.125 for prompts <= 200k
4225
4063
  },
4226
4064
  knowledgeCutoff: "2025-01",
4227
4065
  features: {
@@ -4234,9 +4072,10 @@ var init_gemini_models = __esm({
4234
4072
  metadata: {
4235
4073
  family: "Gemini 2.5",
4236
4074
  releaseDate: "2025-06",
4237
- notes: "Balanced multimodal model with 1M context. Best for complex agents and reasoning."
4075
+ notes: "State-of-the-art multipurpose model. Excels at coding and complex reasoning."
4238
4076
  }
4239
4077
  },
4078
+ // Gemini 2.5 Flash
4240
4079
  {
4241
4080
  provider: "gemini",
4242
4081
  modelId: "gemini-2.5-flash",
@@ -4245,8 +4084,10 @@ var init_gemini_models = __esm({
4245
4084
  maxOutputTokens: 65536,
4246
4085
  pricing: {
4247
4086
  input: 0.3,
4087
+ // $0.30 for text/image/video, $1.00 for audio
4248
4088
  output: 2.5,
4249
4089
  cachedInput: 0.03
4090
+ // $0.03 for text/image/video
4250
4091
  },
4251
4092
  knowledgeCutoff: "2025-01",
4252
4093
  features: {
@@ -4259,9 +4100,10 @@ var init_gemini_models = __esm({
4259
4100
  metadata: {
4260
4101
  family: "Gemini 2.5",
4261
4102
  releaseDate: "2025-06",
4262
- notes: "Best price-performance ratio with thinking enabled by default"
4103
+ notes: "First hybrid reasoning model with 1M context and thinking budgets."
4263
4104
  }
4264
4105
  },
4106
+ // Gemini 2.5 Flash-Lite
4265
4107
  {
4266
4108
  provider: "gemini",
4267
4109
  modelId: "gemini-2.5-flash-lite",
@@ -4270,8 +4112,10 @@ var init_gemini_models = __esm({
4270
4112
  maxOutputTokens: 65536,
4271
4113
  pricing: {
4272
4114
  input: 0.1,
4115
+ // $0.10 for text/image/video, $0.30 for audio
4273
4116
  output: 0.4,
4274
4117
  cachedInput: 0.01
4118
+ // $0.01 for text/image/video
4275
4119
  },
4276
4120
  knowledgeCutoff: "2025-01",
4277
4121
  features: {
@@ -4283,9 +4127,10 @@ var init_gemini_models = __esm({
4283
4127
  metadata: {
4284
4128
  family: "Gemini 2.5",
4285
4129
  releaseDate: "2025-06",
4286
- notes: "Fastest and most cost-efficient model for high-volume, low-latency tasks"
4130
+ notes: "Smallest and most cost effective model, built for at scale usage."
4287
4131
  }
4288
4132
  },
4133
+ // Gemini 2.0 Flash
4289
4134
  {
4290
4135
  provider: "gemini",
4291
4136
  modelId: "gemini-2.0-flash",
@@ -4294,8 +4139,10 @@ var init_gemini_models = __esm({
4294
4139
  maxOutputTokens: 8192,
4295
4140
  pricing: {
4296
4141
  input: 0.1,
4142
+ // $0.10 for text/image/video, $0.70 for audio
4297
4143
  output: 0.4,
4298
- cachedInput: 0.01
4144
+ cachedInput: 0.025
4145
+ // $0.025 for text/image/video
4299
4146
  },
4300
4147
  knowledgeCutoff: "2024-08",
4301
4148
  features: {
@@ -4306,9 +4153,10 @@ var init_gemini_models = __esm({
4306
4153
  },
4307
4154
  metadata: {
4308
4155
  family: "Gemini 2.0",
4309
- notes: "Previous generation with 1M context and multimodal capabilities"
4156
+ notes: "Balanced multimodal model with 1M context, built for the era of Agents."
4310
4157
  }
4311
4158
  },
4159
+ // Gemini 2.0 Flash-Lite
4312
4160
  {
4313
4161
  provider: "gemini",
4314
4162
  modelId: "gemini-2.0-flash-lite",
@@ -4317,8 +4165,8 @@ var init_gemini_models = __esm({
4317
4165
  maxOutputTokens: 8192,
4318
4166
  pricing: {
4319
4167
  input: 0.075,
4320
- output: 0.3,
4321
- cachedInput: 75e-4
4168
+ output: 0.3
4169
+ // No context caching available for 2.0-flash-lite
4322
4170
  },
4323
4171
  knowledgeCutoff: "2024-08",
4324
4172
  features: {
@@ -4329,7 +4177,7 @@ var init_gemini_models = __esm({
4329
4177
  },
4330
4178
  metadata: {
4331
4179
  family: "Gemini 2.0",
4332
- notes: "Lightweight previous generation model for cost-sensitive applications"
4180
+ notes: "Smallest and most cost effective 2.0 model for at scale usage."
4333
4181
  }
4334
4182
  }
4335
4183
  ];
@@ -4499,7 +4347,9 @@ var init_gemini = __esm({
4499
4347
  return {
4500
4348
  inputTokens: usageMetadata.promptTokenCount ?? 0,
4501
4349
  outputTokens: usageMetadata.candidatesTokenCount ?? 0,
4502
- totalTokens: usageMetadata.totalTokenCount ?? 0
4350
+ totalTokens: usageMetadata.totalTokenCount ?? 0,
4351
+ // Gemini returns cached token count in cachedContentTokenCount
4352
+ cachedInputTokens: usageMetadata.cachedContentTokenCount ?? 0
4503
4353
  };
4504
4354
  }
4505
4355
  /**
@@ -4555,10 +4405,11 @@ var init_openai_models = __esm({
4555
4405
  "src/providers/openai-models.ts"() {
4556
4406
  "use strict";
4557
4407
  OPENAI_MODELS = [
4408
+ // GPT-5 Family
4558
4409
  {
4559
4410
  provider: "openai",
4560
4411
  modelId: "gpt-5.1",
4561
- displayName: "GPT-5.1 Instant",
4412
+ displayName: "GPT-5.1",
4562
4413
  contextWindow: 128e3,
4563
4414
  maxOutputTokens: 32768,
4564
4415
  pricing: {
@@ -4578,34 +4429,7 @@ var init_openai_models = __esm({
4578
4429
  metadata: {
4579
4430
  family: "GPT-5",
4580
4431
  releaseDate: "2025-11-12",
4581
- notes: "Warmer, more intelligent, better instruction following. 2-3x faster than GPT-5.",
4582
- supportsTemperature: false
4583
- }
4584
- },
4585
- {
4586
- provider: "openai",
4587
- modelId: "gpt-5.1-thinking",
4588
- displayName: "GPT-5.1 Thinking",
4589
- contextWindow: 196e3,
4590
- maxOutputTokens: 32768,
4591
- pricing: {
4592
- input: 1.25,
4593
- output: 10,
4594
- cachedInput: 0.125
4595
- },
4596
- knowledgeCutoff: "2024-09-30",
4597
- features: {
4598
- streaming: true,
4599
- functionCalling: true,
4600
- vision: true,
4601
- reasoning: true,
4602
- structuredOutputs: true,
4603
- fineTuning: true
4604
- },
4605
- metadata: {
4606
- family: "GPT-5",
4607
- releaseDate: "2025-11-12",
4608
- notes: "Advanced reasoning with thinking levels: Light, Standard, Extended, Heavy. Best for complex tasks.",
4432
+ notes: "Latest GPT-5 with improved instruction following. 2-3x faster than GPT-5.",
4609
4433
  supportsTemperature: false
4610
4434
  }
4611
4435
  },
@@ -4685,6 +4509,255 @@ var init_openai_models = __esm({
4685
4509
  notes: "Fastest, most cost-efficient version for well-defined tasks",
4686
4510
  supportsTemperature: false
4687
4511
  }
4512
+ },
4513
+ {
4514
+ provider: "openai",
4515
+ modelId: "gpt-5-pro",
4516
+ displayName: "GPT-5 Pro",
4517
+ contextWindow: 272e3,
4518
+ maxOutputTokens: 128e3,
4519
+ pricing: {
4520
+ input: 15,
4521
+ output: 120
4522
+ // No cached input pricing for gpt-5-pro
4523
+ },
4524
+ knowledgeCutoff: "2024-09-30",
4525
+ features: {
4526
+ streaming: true,
4527
+ functionCalling: true,
4528
+ vision: true,
4529
+ reasoning: true,
4530
+ structuredOutputs: true
4531
+ },
4532
+ metadata: {
4533
+ family: "GPT-5",
4534
+ notes: "Premium tier with enhanced capabilities. Does not support prompt caching.",
4535
+ supportsTemperature: false
4536
+ }
4537
+ },
4538
+ // GPT-4.1 Family
4539
+ {
4540
+ provider: "openai",
4541
+ modelId: "gpt-4.1",
4542
+ displayName: "GPT-4.1",
4543
+ contextWindow: 128e3,
4544
+ maxOutputTokens: 32768,
4545
+ pricing: {
4546
+ input: 2,
4547
+ output: 8,
4548
+ cachedInput: 0.5
4549
+ },
4550
+ knowledgeCutoff: "2024-04-01",
4551
+ features: {
4552
+ streaming: true,
4553
+ functionCalling: true,
4554
+ vision: true,
4555
+ structuredOutputs: true,
4556
+ fineTuning: true
4557
+ },
4558
+ metadata: {
4559
+ family: "GPT-4.1",
4560
+ notes: "Improved GPT-4 with better instruction following"
4561
+ }
4562
+ },
4563
+ {
4564
+ provider: "openai",
4565
+ modelId: "gpt-4.1-mini",
4566
+ displayName: "GPT-4.1 Mini",
4567
+ contextWindow: 128e3,
4568
+ maxOutputTokens: 32768,
4569
+ pricing: {
4570
+ input: 0.4,
4571
+ output: 1.6,
4572
+ cachedInput: 0.1
4573
+ },
4574
+ knowledgeCutoff: "2024-04-01",
4575
+ features: {
4576
+ streaming: true,
4577
+ functionCalling: true,
4578
+ vision: true,
4579
+ structuredOutputs: true,
4580
+ fineTuning: true
4581
+ },
4582
+ metadata: {
4583
+ family: "GPT-4.1",
4584
+ notes: "Cost-efficient GPT-4.1 variant"
4585
+ }
4586
+ },
4587
+ {
4588
+ provider: "openai",
4589
+ modelId: "gpt-4.1-nano",
4590
+ displayName: "GPT-4.1 Nano",
4591
+ contextWindow: 128e3,
4592
+ maxOutputTokens: 32768,
4593
+ pricing: {
4594
+ input: 0.1,
4595
+ output: 0.4,
4596
+ cachedInput: 0.025
4597
+ },
4598
+ knowledgeCutoff: "2024-04-01",
4599
+ features: {
4600
+ streaming: true,
4601
+ functionCalling: true,
4602
+ vision: true,
4603
+ structuredOutputs: true,
4604
+ fineTuning: true
4605
+ },
4606
+ metadata: {
4607
+ family: "GPT-4.1",
4608
+ notes: "Fastest GPT-4.1 variant for simple tasks"
4609
+ }
4610
+ },
4611
+ // GPT-4o Family
4612
+ {
4613
+ provider: "openai",
4614
+ modelId: "gpt-4o",
4615
+ displayName: "GPT-4o",
4616
+ contextWindow: 128e3,
4617
+ maxOutputTokens: 16384,
4618
+ pricing: {
4619
+ input: 2.5,
4620
+ output: 10,
4621
+ cachedInput: 1.25
4622
+ },
4623
+ knowledgeCutoff: "2024-04-01",
4624
+ features: {
4625
+ streaming: true,
4626
+ functionCalling: true,
4627
+ vision: true,
4628
+ structuredOutputs: true,
4629
+ fineTuning: true
4630
+ },
4631
+ metadata: {
4632
+ family: "GPT-4o",
4633
+ notes: "Multimodal model optimized for speed"
4634
+ }
4635
+ },
4636
+ {
4637
+ provider: "openai",
4638
+ modelId: "gpt-4o-mini",
4639
+ displayName: "GPT-4o Mini",
4640
+ contextWindow: 128e3,
4641
+ maxOutputTokens: 16384,
4642
+ pricing: {
4643
+ input: 0.15,
4644
+ output: 0.6,
4645
+ cachedInput: 0.075
4646
+ },
4647
+ knowledgeCutoff: "2024-04-01",
4648
+ features: {
4649
+ streaming: true,
4650
+ functionCalling: true,
4651
+ vision: true,
4652
+ structuredOutputs: true,
4653
+ fineTuning: true
4654
+ },
4655
+ metadata: {
4656
+ family: "GPT-4o",
4657
+ notes: "Fast and affordable multimodal model"
4658
+ }
4659
+ },
4660
+ // o-series (Reasoning models)
4661
+ {
4662
+ provider: "openai",
4663
+ modelId: "o1",
4664
+ displayName: "o1",
4665
+ contextWindow: 2e5,
4666
+ maxOutputTokens: 1e5,
4667
+ pricing: {
4668
+ input: 15,
4669
+ output: 60,
4670
+ cachedInput: 7.5
4671
+ },
4672
+ knowledgeCutoff: "2024-12-01",
4673
+ features: {
4674
+ streaming: true,
4675
+ functionCalling: true,
4676
+ vision: true,
4677
+ reasoning: true,
4678
+ structuredOutputs: true
4679
+ },
4680
+ metadata: {
4681
+ family: "o-series",
4682
+ notes: "Advanced reasoning model with chain-of-thought",
4683
+ supportsTemperature: false
4684
+ }
4685
+ },
4686
+ {
4687
+ provider: "openai",
4688
+ modelId: "o3",
4689
+ displayName: "o3",
4690
+ contextWindow: 2e5,
4691
+ maxOutputTokens: 1e5,
4692
+ pricing: {
4693
+ input: 2,
4694
+ output: 8,
4695
+ cachedInput: 0.5
4696
+ },
4697
+ knowledgeCutoff: "2025-01-01",
4698
+ features: {
4699
+ streaming: true,
4700
+ functionCalling: true,
4701
+ vision: true,
4702
+ reasoning: true,
4703
+ structuredOutputs: true
4704
+ },
4705
+ metadata: {
4706
+ family: "o-series",
4707
+ notes: "Next-gen reasoning model, more efficient than o1",
4708
+ supportsTemperature: false
4709
+ }
4710
+ },
4711
+ {
4712
+ provider: "openai",
4713
+ modelId: "o4-mini",
4714
+ displayName: "o4 Mini",
4715
+ contextWindow: 2e5,
4716
+ maxOutputTokens: 1e5,
4717
+ pricing: {
4718
+ input: 1.1,
4719
+ output: 4.4,
4720
+ cachedInput: 0.275
4721
+ },
4722
+ knowledgeCutoff: "2025-04-01",
4723
+ features: {
4724
+ streaming: true,
4725
+ functionCalling: true,
4726
+ vision: true,
4727
+ reasoning: true,
4728
+ structuredOutputs: true,
4729
+ fineTuning: true
4730
+ },
4731
+ metadata: {
4732
+ family: "o-series",
4733
+ notes: "Cost-efficient reasoning model",
4734
+ supportsTemperature: false
4735
+ }
4736
+ },
4737
+ {
4738
+ provider: "openai",
4739
+ modelId: "o3-mini",
4740
+ displayName: "o3 Mini",
4741
+ contextWindow: 2e5,
4742
+ maxOutputTokens: 1e5,
4743
+ pricing: {
4744
+ input: 1.1,
4745
+ output: 4.4,
4746
+ cachedInput: 0.55
4747
+ },
4748
+ knowledgeCutoff: "2025-01-01",
4749
+ features: {
4750
+ streaming: true,
4751
+ functionCalling: true,
4752
+ vision: true,
4753
+ reasoning: true,
4754
+ structuredOutputs: true
4755
+ },
4756
+ metadata: {
4757
+ family: "o-series",
4758
+ notes: "Compact reasoning model for cost-sensitive applications",
4759
+ supportsTemperature: false
4760
+ }
4688
4761
  }
4689
4762
  ];
4690
4763
  }
@@ -4765,7 +4838,8 @@ var init_openai = __esm({
4765
4838
  const usage = chunk.usage ? {
4766
4839
  inputTokens: chunk.usage.prompt_tokens,
4767
4840
  outputTokens: chunk.usage.completion_tokens,
4768
- totalTokens: chunk.usage.total_tokens
4841
+ totalTokens: chunk.usage.total_tokens,
4842
+ cachedInputTokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0
4769
4843
  } : void 0;
4770
4844
  if (finishReason || usage) {
4771
4845
  yield { text: "", finishReason, usage, rawEvent: chunk };
@@ -4982,20 +5056,28 @@ var init_model_registry = __esm({
4982
5056
  /**
4983
5057
  * Estimate API cost for a given model and token usage
4984
5058
  * @param modelId - Full model identifier
4985
- * @param inputTokens - Number of input tokens
5059
+ * @param inputTokens - Number of input tokens (total, including cached and cache creation)
4986
5060
  * @param outputTokens - Number of output tokens
4987
- * @param useCachedInput - Whether to use cached input pricing (if supported by provider)
5061
+ * @param cachedInputTokens - Number of cached input tokens (subset of inputTokens)
5062
+ * @param cacheCreationInputTokens - Number of cache creation tokens (subset of inputTokens, Anthropic only)
4988
5063
  * @returns CostEstimate if model found, undefined otherwise
4989
5064
  */
4990
- estimateCost(modelId, inputTokens, outputTokens, useCachedInput = false) {
5065
+ estimateCost(modelId, inputTokens, outputTokens, cachedInputTokens = 0, cacheCreationInputTokens = 0) {
4991
5066
  const spec = this.getModelSpec(modelId);
4992
5067
  if (!spec) return void 0;
4993
- const inputRate = useCachedInput && spec.pricing.cachedInput !== void 0 ? spec.pricing.cachedInput : spec.pricing.input;
4994
- const inputCost = inputTokens / 1e6 * inputRate;
5068
+ const cachedRate = spec.pricing.cachedInput ?? spec.pricing.input;
5069
+ const cacheWriteRate = spec.pricing.cacheWriteInput ?? spec.pricing.input;
5070
+ const uncachedInputTokens = inputTokens - cachedInputTokens - cacheCreationInputTokens;
5071
+ const uncachedInputCost = uncachedInputTokens / 1e6 * spec.pricing.input;
5072
+ const cachedInputCost = cachedInputTokens / 1e6 * cachedRate;
5073
+ const cacheCreationCost = cacheCreationInputTokens / 1e6 * cacheWriteRate;
5074
+ const inputCost = uncachedInputCost + cachedInputCost + cacheCreationCost;
4995
5075
  const outputCost = outputTokens / 1e6 * spec.pricing.output;
4996
5076
  const totalCost = inputCost + outputCost;
4997
5077
  return {
4998
5078
  inputCost,
5079
+ cachedInputCost,
5080
+ cacheCreationCost,
4999
5081
  outputCost,
5000
5082
  totalCost,
5001
5083
  currency: "USD"
@@ -5651,17 +5733,51 @@ function splitIntoChunks(text, minChunkSize = 5, maxChunkSize = 30) {
5651
5733
  }
5652
5734
  return chunks;
5653
5735
  }
5736
+ function serializeToBlockFormat(obj, prefix = "") {
5737
+ let result = "";
5738
+ for (const [key, value] of Object.entries(obj)) {
5739
+ const pointer = prefix ? `${prefix}/${key}` : key;
5740
+ if (value === null || value === void 0) {
5741
+ continue;
5742
+ }
5743
+ if (Array.isArray(value)) {
5744
+ for (let i = 0; i < value.length; i++) {
5745
+ const item = value[i];
5746
+ const itemPointer = `${pointer}/${i}`;
5747
+ if (typeof item === "object" && item !== null && !Array.isArray(item)) {
5748
+ result += serializeToBlockFormat(item, itemPointer);
5749
+ } else if (Array.isArray(item)) {
5750
+ for (let j = 0; j < item.length; j++) {
5751
+ result += `${GADGET_ARG_PREFIX}${itemPointer}/${j}
5752
+ ${String(item[j])}
5753
+ `;
5754
+ }
5755
+ } else {
5756
+ result += `${GADGET_ARG_PREFIX}${itemPointer}
5757
+ ${String(item)}
5758
+ `;
5759
+ }
5760
+ }
5761
+ } else if (typeof value === "object") {
5762
+ result += serializeToBlockFormat(value, pointer);
5763
+ } else {
5764
+ result += `${GADGET_ARG_PREFIX}${pointer}
5765
+ ${String(value)}
5766
+ `;
5767
+ }
5768
+ }
5769
+ return result;
5770
+ }
5654
5771
  function formatGadgetCalls(gadgetCalls) {
5655
5772
  let text = "";
5656
5773
  const calls = [];
5657
5774
  for (const call of gadgetCalls) {
5658
5775
  const invocationId = call.invocationId ?? generateInvocationId();
5659
5776
  calls.push({ name: call.gadgetName, invocationId });
5660
- const paramsJson = JSON.stringify(call.parameters);
5777
+ const blockParams = serializeToBlockFormat(call.parameters);
5661
5778
  text += `
5662
5779
  ${GADGET_START_PREFIX}${call.gadgetName}
5663
- ${paramsJson}
5664
- ${GADGET_END_PREFIX}`;
5780
+ ${blockParams}${GADGET_END_PREFIX}`;
5665
5781
  }
5666
5782
  return { text, calls };
5667
5783
  }