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.
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,125 +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 = `HEREDOC_${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 = ["EOF", "END", "DOC", "CONTENT", "TEXT", "HEREDOC", "DATA", "BLOCK"];
992
892
  BaseGadget = class {
993
893
  /**
994
894
  * The name of the gadget. Used for identification when LLM calls it.
@@ -1019,19 +919,19 @@ var init_gadget = __esm({
1019
919
  /**
1020
920
  * Auto-generated instruction text for the LLM.
1021
921
  * Combines name, description, and parameter schema into a formatted instruction.
1022
- * @deprecated Use getInstruction(format) instead for format-specific schemas
922
+ * @deprecated Use getInstruction() instead
1023
923
  */
1024
924
  get instruction() {
1025
- return this.getInstruction("yaml");
925
+ return this.getInstruction();
1026
926
  }
1027
927
  /**
1028
- * Generate instruction text for the LLM with format-specific schema.
928
+ * Generate instruction text for the LLM.
1029
929
  * Combines name, description, and parameter schema into a formatted instruction.
1030
930
  *
1031
- * @param format - Format for the schema representation ('json' | 'yaml' | 'toml' | 'auto')
931
+ * @param argPrefix - Optional custom argument prefix for block format examples
1032
932
  * @returns Formatted instruction string
1033
933
  */
1034
- getInstruction(format = "json") {
934
+ getInstruction(argPrefix) {
1035
935
  const parts = [];
1036
936
  parts.push(this.description);
1037
937
  if (this.parameterSchema) {
@@ -1040,20 +940,12 @@ var init_gadget = __esm({
1040
940
  const jsonSchema = schemaToJSONSchema(this.parameterSchema, {
1041
941
  target: "draft-7"
1042
942
  });
1043
- if (format === "json" || format === "auto") {
1044
- parts.push("\n\nInput Schema (JSON):");
1045
- parts.push(JSON.stringify(jsonSchema, null, 2));
1046
- } else if (format === "toml") {
1047
- parts.push("\n\nInput Schema (TOML):");
1048
- parts.push(JSON.stringify(jsonSchema, null, 2));
1049
- } else {
1050
- const yamlSchema = yaml.dump(jsonSchema).trimEnd();
1051
- parts.push("\n\nInput Schema (YAML):");
1052
- parts.push(yamlSchema);
1053
- }
943
+ parts.push("\n\nParameters:");
944
+ parts.push(formatSchemaAsPlainText(jsonSchema));
1054
945
  }
1055
946
  if (this.examples && this.examples.length > 0) {
1056
947
  parts.push("\n\nExamples:");
948
+ const effectiveArgPrefix = argPrefix ?? GADGET_ARG_PREFIX;
1057
949
  this.examples.forEach((example, index) => {
1058
950
  if (index > 0) {
1059
951
  parts.push("");
@@ -1062,13 +954,7 @@ var init_gadget = __esm({
1062
954
  parts.push(`# ${example.comment}`);
1063
955
  }
1064
956
  parts.push("Input:");
1065
- if (format === "json" || format === "auto") {
1066
- parts.push(JSON.stringify(example.params, null, 2));
1067
- } else if (format === "toml") {
1068
- parts.push(formatParamsAsToml(example.params));
1069
- } else {
1070
- parts.push(formatParamsAsYaml(example.params));
1071
- }
957
+ parts.push(formatParamsAsBlock(example.params, "", effectiveArgPrefix));
1072
958
  if (example.output !== void 0) {
1073
959
  parts.push("Output:");
1074
960
  parts.push(example.output);
@@ -1345,14 +1231,12 @@ var init_conversation_manager = __esm({
1345
1231
  baseMessages;
1346
1232
  initialMessages;
1347
1233
  historyBuilder;
1348
- parameterFormat;
1349
1234
  constructor(baseMessages, initialMessages, options = {}) {
1350
1235
  this.baseMessages = baseMessages;
1351
1236
  this.initialMessages = initialMessages;
1352
- this.parameterFormat = options.parameterFormat ?? "json";
1353
1237
  this.historyBuilder = new LLMMessageBuilder();
1354
1238
  if (options.startPrefix && options.endPrefix) {
1355
- this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix);
1239
+ this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix, options.argPrefix);
1356
1240
  }
1357
1241
  }
1358
1242
  addUserMessage(content) {
@@ -1362,7 +1246,7 @@ var init_conversation_manager = __esm({
1362
1246
  this.historyBuilder.addAssistant(content);
1363
1247
  }
1364
1248
  addGadgetCall(gadgetName, parameters, result) {
1365
- this.historyBuilder.addGadgetCall(gadgetName, parameters, result, this.parameterFormat);
1249
+ this.historyBuilder.addGadgetCall(gadgetName, parameters, result);
1366
1250
  }
1367
1251
  getMessages() {
1368
1252
  return [...this.baseMessages, ...this.initialMessages, ...this.historyBuilder.build()];
@@ -1385,7 +1269,7 @@ async function runWithHandlers(agentGenerator, handlers) {
1385
1269
  await handlers.onGadgetCall({
1386
1270
  gadgetName: event.call.gadgetName,
1387
1271
  parameters: event.call.parameters,
1388
- parametersYaml: event.call.parametersYaml
1272
+ parametersRaw: event.call.parametersRaw
1389
1273
  });
1390
1274
  }
1391
1275
  break;
@@ -1692,7 +1576,7 @@ var init_executor = __esm({
1692
1576
  this.logger.error("Gadget parameter parse error", {
1693
1577
  gadgetName: call.gadgetName,
1694
1578
  parseError: call.parseError,
1695
- rawParameters: call.parametersYaml
1579
+ rawParameters: call.parametersRaw
1696
1580
  });
1697
1581
  return {
1698
1582
  gadgetName: call.gadgetName,
@@ -1854,168 +1738,107 @@ var init_executor = __esm({
1854
1738
  }
1855
1739
  });
1856
1740
 
1857
- // src/gadgets/parser.ts
1858
- function preprocessYaml(yamlStr) {
1859
- const lines = yamlStr.split("\n");
1860
- const result = [];
1861
- let i = 0;
1862
- while (i < lines.length) {
1863
- const line = lines[i];
1864
- const heredocMatch = line.match(/^(\s*)([\w-]+):\s*<<<([A-Za-z_][A-Za-z0-9_]*)\s*$/);
1865
- if (heredocMatch) {
1866
- const [, indent, key, delimiter] = heredocMatch;
1867
- const bodyLines = [];
1868
- i++;
1869
- const closingRegex = new RegExp(`^${delimiter}\\s*$`);
1870
- while (i < lines.length && !closingRegex.test(lines[i])) {
1871
- bodyLines.push(lines[i]);
1872
- i++;
1873
- }
1874
- if (i < lines.length) {
1875
- i++;
1876
- }
1877
- result.push(`${indent}${key}: |`);
1878
- for (const bodyLine of bodyLines) {
1879
- 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, "");
1880
1758
  }
1881
1759
  continue;
1882
1760
  }
1883
- const match = line.match(/^(\s*)([\w-]+):\s+(.+)$/);
1884
- if (match) {
1885
- const [, indent, key, value] = match;
1886
- if (value === "|" || value === ">" || value === "|-" || value === ">-") {
1887
- result.push(line);
1888
- i++;
1889
- const keyIndentLen2 = indent.length;
1890
- const blockLines = [];
1891
- let minContentIndent = Infinity;
1892
- while (i < lines.length) {
1893
- const blockLine = lines[i];
1894
- const blockIndentMatch = blockLine.match(/^(\s*)/);
1895
- const blockIndentLen = blockIndentMatch ? blockIndentMatch[1].length : 0;
1896
- if (blockLine.trim() === "") {
1897
- blockLines.push({ content: "", originalIndent: 0 });
1898
- i++;
1899
- continue;
1900
- }
1901
- if (blockIndentLen > keyIndentLen2) {
1902
- const content = blockLine.substring(blockIndentLen);
1903
- blockLines.push({ content, originalIndent: blockIndentLen });
1904
- if (content.trim().length > 0) {
1905
- minContentIndent = Math.min(minContentIndent, blockIndentLen);
1906
- }
1907
- i++;
1908
- } else {
1909
- break;
1910
- }
1911
- }
1912
- const targetIndent = keyIndentLen2 + 2;
1913
- for (const blockLine of blockLines) {
1914
- if (blockLine.content === "") {
1915
- result.push("");
1916
- } else {
1917
- result.push(" ".repeat(targetIndent) + blockLine.content);
1918
- }
1919
- }
1920
- continue;
1921
- }
1922
- if (value.startsWith('"') || value.startsWith("'") || value === "true" || value === "false" || /^-?\d+(\.\d+)?$/.test(value)) {
1923
- result.push(line);
1924
- i++;
1925
- continue;
1926
- }
1927
- const keyIndentLen = indent.length;
1928
- const continuationLines = [];
1929
- let j = i + 1;
1930
- while (j < lines.length) {
1931
- const nextLine = lines[j];
1932
- if (nextLine.trim() === "") {
1933
- continuationLines.push(nextLine);
1934
- j++;
1935
- continue;
1936
- }
1937
- const nextIndentMatch = nextLine.match(/^(\s*)/);
1938
- const nextIndentLen = nextIndentMatch ? nextIndentMatch[1].length : 0;
1939
- if (nextIndentLen > keyIndentLen) {
1940
- continuationLines.push(nextLine);
1941
- j++;
1942
- } else {
1943
- break;
1944
- }
1945
- }
1946
- if (continuationLines.length > 0 && continuationLines.some((l) => l.trim().length > 0)) {
1947
- result.push(`${indent}${key}: |`);
1948
- result.push(`${indent} ${value}`);
1949
- for (const contLine of continuationLines) {
1950
- if (contLine.trim() === "") {
1951
- result.push("");
1952
- } else {
1953
- const contIndentMatch = contLine.match(/^(\s*)/);
1954
- const contIndent = contIndentMatch ? contIndentMatch[1] : "";
1955
- const contContent = contLine.substring(contIndent.length);
1956
- result.push(`${indent} ${contContent}`);
1957
- }
1958
- }
1959
- i = j;
1960
- continue;
1961
- }
1962
- if (value.includes(": ") || value.endsWith(":")) {
1963
- const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
1964
- result.push(`${indent}${key}: "${escaped}"`);
1965
- i++;
1966
- continue;
1967
- }
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}`);
1968
1771
  }
1969
- result.push(line);
1970
- i++;
1772
+ seenPointers.add(pointer);
1773
+ setByPointer(result, pointer, value);
1971
1774
  }
1972
- return result.join("\n");
1775
+ return result;
1973
1776
  }
1974
- function unescapeHeredocContent(content) {
1975
- 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;
1976
1791
  }
1977
- function preprocessTomlHeredoc(tomlStr) {
1978
- const lines = tomlStr.split("\n");
1979
- const result = [];
1980
- let i = 0;
1981
- const heredocStartRegex = /^(\s*)([\w-]+)\s*=\s*<<<([A-Za-z_][A-Za-z0-9_]*)\s*$/;
1982
- while (i < lines.length) {
1983
- const line = lines[i];
1984
- const match = line.match(heredocStartRegex);
1985
- if (match) {
1986
- const [, indent, key, delimiter] = match;
1987
- const bodyLines = [];
1988
- i++;
1989
- const closingRegex = new RegExp(`^${delimiter}\\s*$`);
1990
- let foundClosing = false;
1991
- while (i < lines.length) {
1992
- const bodyLine = lines[i];
1993
- if (closingRegex.test(bodyLine)) {
1994
- foundClosing = true;
1995
- i++;
1996
- break;
1997
- }
1998
- bodyLines.push(bodyLine);
1999
- i++;
2000
- }
2001
- if (bodyLines.length === 0) {
2002
- result.push(`${indent}${key} = ''''''`);
2003
- } else {
2004
- result.push(`${indent}${key} = '''`);
2005
- for (let j = 0; j < bodyLines.length - 1; j++) {
2006
- result.push(unescapeHeredocContent(bodyLines[j]));
2007
- }
2008
- result.push(`${unescapeHeredocContent(bodyLines[bodyLines.length - 1])}'''`);
2009
- }
2010
- 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 ? [] : {};
2011
1815
  }
2012
- 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}`);
2013
1825
  }
2014
- result.push(line);
2015
- i++;
1826
+ if (index > current.length) {
1827
+ throw new Error(`Array index gap: expected ${current.length}, got ${index}`);
1828
+ }
1829
+ current[index] = coercedValue;
1830
+ } else {
1831
+ current[lastSegment] = coercedValue;
2016
1832
  }
2017
- return result.join("\n");
2018
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
2019
1842
  function stripMarkdownFences(content) {
2020
1843
  let cleaned = content.trim();
2021
1844
  const openingFence = /^```(?:toml|yaml|json)?\s*\n/i;
@@ -2024,24 +1847,23 @@ function stripMarkdownFences(content) {
2024
1847
  cleaned = cleaned.replace(closingFence, "");
2025
1848
  return cleaned.trim();
2026
1849
  }
2027
- var yaml2, import_js_toml, globalInvocationCounter, StreamParser;
1850
+ var globalInvocationCounter, StreamParser;
2028
1851
  var init_parser = __esm({
2029
1852
  "src/gadgets/parser.ts"() {
2030
1853
  "use strict";
2031
- yaml2 = __toESM(require("js-yaml"), 1);
2032
- import_js_toml = require("js-toml");
2033
1854
  init_constants();
1855
+ init_block_params();
2034
1856
  globalInvocationCounter = 0;
2035
1857
  StreamParser = class {
2036
1858
  buffer = "";
2037
1859
  lastReportedTextLength = 0;
2038
1860
  startPrefix;
2039
1861
  endPrefix;
2040
- parameterFormat;
1862
+ argPrefix;
2041
1863
  constructor(options = {}) {
2042
1864
  this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;
2043
1865
  this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;
2044
- this.parameterFormat = options.parameterFormat ?? "json";
1866
+ this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;
2045
1867
  }
2046
1868
  takeTextUntil(index) {
2047
1869
  if (index <= this.lastReportedTextLength) {
@@ -2076,43 +1898,14 @@ var init_parser = __esm({
2076
1898
  return `${firstLine.slice(0, maxLen)}... (${message.length} chars total)`;
2077
1899
  }
2078
1900
  /**
2079
- * Parse parameter string according to configured format
1901
+ * Parse parameter string using block format
2080
1902
  */
2081
1903
  parseParameters(raw) {
2082
1904
  const cleaned = stripMarkdownFences(raw);
2083
- if (this.parameterFormat === "json") {
2084
- try {
2085
- return { parameters: JSON.parse(cleaned) };
2086
- } catch (error) {
2087
- return { parseError: this.truncateParseError(error, "JSON") };
2088
- }
2089
- }
2090
- if (this.parameterFormat === "yaml") {
2091
- try {
2092
- return { parameters: yaml2.load(preprocessYaml(cleaned)) };
2093
- } catch (error) {
2094
- return { parseError: this.truncateParseError(error, "YAML") };
2095
- }
2096
- }
2097
- if (this.parameterFormat === "toml") {
2098
- try {
2099
- return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(cleaned)) };
2100
- } catch (error) {
2101
- return { parseError: this.truncateParseError(error, "TOML") };
2102
- }
2103
- }
2104
1905
  try {
2105
- return { parameters: JSON.parse(cleaned) };
2106
- } catch {
2107
- try {
2108
- return { parameters: (0, import_js_toml.load)(preprocessTomlHeredoc(cleaned)) };
2109
- } catch {
2110
- try {
2111
- return { parameters: yaml2.load(preprocessYaml(cleaned)) };
2112
- } catch (error) {
2113
- return { parseError: this.truncateParseError(error, "auto") };
2114
- }
2115
- }
1906
+ return { parameters: parseBlockParams(cleaned, { argPrefix: this.argPrefix }) };
1907
+ } catch (error) {
1908
+ return { parseError: this.truncateParseError(error, "block") };
2116
1909
  }
2117
1910
  }
2118
1911
  // Feed a chunk of text and get parsed events
@@ -2171,8 +1964,7 @@ var init_parser = __esm({
2171
1964
  call: {
2172
1965
  gadgetName: actualGadgetName,
2173
1966
  invocationId,
2174
- parametersYaml: parametersRaw,
2175
- // Keep property name for backward compatibility
1967
+ parametersRaw,
2176
1968
  parameters,
2177
1969
  parseError
2178
1970
  }
@@ -2206,7 +1998,7 @@ var init_parser = __esm({
2206
1998
  call: {
2207
1999
  gadgetName: actualGadgetName,
2208
2000
  invocationId,
2209
- parametersYaml: parametersRaw,
2001
+ parametersRaw,
2210
2002
  parameters,
2211
2003
  parseError
2212
2004
  }
@@ -2257,9 +2049,9 @@ var init_stream_processor = __esm({
2257
2049
  this.stopOnGadgetError = options.stopOnGadgetError ?? true;
2258
2050
  this.shouldContinueAfterError = options.shouldContinueAfterError;
2259
2051
  this.parser = new StreamParser({
2260
- parameterFormat: options.parameterFormat,
2261
2052
  startPrefix: options.gadgetStartPrefix,
2262
- endPrefix: options.gadgetEndPrefix
2053
+ endPrefix: options.gadgetEndPrefix,
2054
+ argPrefix: options.gadgetArgPrefix
2263
2055
  });
2264
2056
  this.executor = new GadgetExecutor(
2265
2057
  options.registry,
@@ -2413,7 +2205,7 @@ var init_stream_processor = __esm({
2413
2205
  this.logger.warn("Gadget has parse error", {
2414
2206
  gadgetName: call.gadgetName,
2415
2207
  error: call.parseError,
2416
- rawParameters: call.parametersYaml
2208
+ rawParameters: call.parametersRaw
2417
2209
  });
2418
2210
  const shouldContinue = await this.checkContinueAfterError(
2419
2211
  call.parseError,
@@ -2649,9 +2441,9 @@ var init_agent = __esm({
2649
2441
  hooks;
2650
2442
  conversation;
2651
2443
  registry;
2652
- parameterFormat;
2653
2444
  gadgetStartPrefix;
2654
2445
  gadgetEndPrefix;
2446
+ gadgetArgPrefix;
2655
2447
  onHumanInputRequired;
2656
2448
  textOnlyHandler;
2657
2449
  textWithGadgetsHandler;
@@ -2680,9 +2472,9 @@ var init_agent = __esm({
2680
2472
  this.temperature = options.temperature;
2681
2473
  this.logger = options.logger ?? createLogger({ name: "llmist:agent" });
2682
2474
  this.registry = options.registry;
2683
- this.parameterFormat = options.parameterFormat ?? "json";
2684
2475
  this.gadgetStartPrefix = options.gadgetStartPrefix;
2685
2476
  this.gadgetEndPrefix = options.gadgetEndPrefix;
2477
+ this.gadgetArgPrefix = options.gadgetArgPrefix;
2686
2478
  this.onHumanInputRequired = options.onHumanInputRequired;
2687
2479
  this.textOnlyHandler = options.textOnlyHandler ?? "terminate";
2688
2480
  this.textWithGadgetsHandler = options.textWithGadgetsHandler;
@@ -2704,9 +2496,10 @@ var init_agent = __esm({
2704
2496
  if (options.systemPrompt) {
2705
2497
  baseBuilder.addSystem(options.systemPrompt);
2706
2498
  }
2707
- baseBuilder.addGadgets(this.registry.getAll(), this.parameterFormat, {
2499
+ baseBuilder.addGadgets(this.registry.getAll(), {
2708
2500
  startPrefix: options.gadgetStartPrefix,
2709
- endPrefix: options.gadgetEndPrefix
2501
+ endPrefix: options.gadgetEndPrefix,
2502
+ argPrefix: options.gadgetArgPrefix
2710
2503
  });
2711
2504
  const baseMessages = baseBuilder.build();
2712
2505
  const initialMessages = (options.initialMessages ?? []).map((message) => ({
@@ -2714,9 +2507,9 @@ var init_agent = __esm({
2714
2507
  content: message.content
2715
2508
  }));
2716
2509
  this.conversation = new ConversationManager(baseMessages, initialMessages, {
2717
- parameterFormat: this.parameterFormat,
2718
2510
  startPrefix: options.gadgetStartPrefix,
2719
- endPrefix: options.gadgetEndPrefix
2511
+ endPrefix: options.gadgetEndPrefix,
2512
+ argPrefix: options.gadgetArgPrefix
2720
2513
  });
2721
2514
  this.userPromptProvided = !!options.userPrompt;
2722
2515
  if (options.userPrompt) {
@@ -2809,9 +2602,9 @@ var init_agent = __esm({
2809
2602
  const processor = new StreamProcessor({
2810
2603
  iteration: currentIteration,
2811
2604
  registry: this.registry,
2812
- parameterFormat: this.parameterFormat,
2813
2605
  gadgetStartPrefix: this.gadgetStartPrefix,
2814
2606
  gadgetEndPrefix: this.gadgetEndPrefix,
2607
+ gadgetArgPrefix: this.gadgetArgPrefix,
2815
2608
  hooks: this.hooks,
2816
2609
  logger: this.logger.getSubLogger({ name: "stream-processor" }),
2817
2610
  onHumanInputRequired: this.onHumanInputRequired,
@@ -3096,7 +2889,8 @@ var init_anthropic_models = __esm({
3096
2889
  pricing: {
3097
2890
  input: 3,
3098
2891
  output: 15,
3099
- cachedInput: 0.3
2892
+ cachedInput: 0.3,
2893
+ cacheWriteInput: 3.75
3100
2894
  },
3101
2895
  knowledgeCutoff: "2025-01",
3102
2896
  features: {
@@ -3120,7 +2914,8 @@ var init_anthropic_models = __esm({
3120
2914
  pricing: {
3121
2915
  input: 1,
3122
2916
  output: 5,
3123
- cachedInput: 0.1
2917
+ cachedInput: 0.1,
2918
+ cacheWriteInput: 1.25
3124
2919
  },
3125
2920
  knowledgeCutoff: "2025-02",
3126
2921
  features: {
@@ -3144,7 +2939,8 @@ var init_anthropic_models = __esm({
3144
2939
  pricing: {
3145
2940
  input: 3,
3146
2941
  output: 15,
3147
- cachedInput: 0.3
2942
+ cachedInput: 0.3,
2943
+ cacheWriteInput: 3.75
3148
2944
  },
3149
2945
  knowledgeCutoff: "2025-03",
3150
2946
  features: {
@@ -3168,7 +2964,8 @@ var init_anthropic_models = __esm({
3168
2964
  pricing: {
3169
2965
  input: 3,
3170
2966
  output: 15,
3171
- cachedInput: 0.3
2967
+ cachedInput: 0.3,
2968
+ cacheWriteInput: 3.75
3172
2969
  },
3173
2970
  knowledgeCutoff: "2024-11",
3174
2971
  features: {
@@ -3192,7 +2989,8 @@ var init_anthropic_models = __esm({
3192
2989
  pricing: {
3193
2990
  input: 15,
3194
2991
  output: 75,
3195
- cachedInput: 1.5
2992
+ cachedInput: 1.5,
2993
+ cacheWriteInput: 18.75
3196
2994
  },
3197
2995
  knowledgeCutoff: "2025-01",
3198
2996
  features: {
@@ -3216,7 +3014,8 @@ var init_anthropic_models = __esm({
3216
3014
  pricing: {
3217
3015
  input: 15,
3218
3016
  output: 75,
3219
- cachedInput: 1.5
3017
+ cachedInput: 1.5,
3018
+ cacheWriteInput: 18.75
3220
3019
  },
3221
3020
  knowledgeCutoff: "2025-03",
3222
3021
  features: {
@@ -3239,7 +3038,8 @@ var init_anthropic_models = __esm({
3239
3038
  pricing: {
3240
3039
  input: 0.8,
3241
3040
  output: 4,
3242
- cachedInput: 0.08
3041
+ cachedInput: 0.08,
3042
+ cacheWriteInput: 1
3243
3043
  },
3244
3044
  knowledgeCutoff: "2024-07",
3245
3045
  features: {
@@ -3262,7 +3062,8 @@ var init_anthropic_models = __esm({
3262
3062
  pricing: {
3263
3063
  input: 0.25,
3264
3064
  output: 1.25,
3265
- cachedInput: 0.025
3065
+ cachedInput: 0.025,
3066
+ cacheWriteInput: 0.3125
3266
3067
  },
3267
3068
  knowledgeCutoff: "2023-08",
3268
3069
  features: {
@@ -3286,7 +3087,8 @@ var init_anthropic_models = __esm({
3286
3087
  pricing: {
3287
3088
  input: 1,
3288
3089
  output: 5,
3289
- cachedInput: 0.1
3090
+ cachedInput: 0.1,
3091
+ cacheWriteInput: 1.25
3290
3092
  },
3291
3093
  knowledgeCutoff: "2025-02",
3292
3094
  features: {
@@ -3310,7 +3112,8 @@ var init_anthropic_models = __esm({
3310
3112
  pricing: {
3311
3113
  input: 3,
3312
3114
  output: 15,
3313
- cachedInput: 0.3
3115
+ cachedInput: 0.3,
3116
+ cacheWriteInput: 3.75
3314
3117
  },
3315
3118
  knowledgeCutoff: "2025-01",
3316
3119
  features: {
@@ -3334,7 +3137,8 @@ var init_anthropic_models = __esm({
3334
3137
  pricing: {
3335
3138
  input: 5,
3336
3139
  output: 25,
3337
- cachedInput: 0.5
3140
+ cachedInput: 0.5,
3141
+ cacheWriteInput: 6.25
3338
3142
  },
3339
3143
  knowledgeCutoff: "2025-03",
3340
3144
  features: {
@@ -3449,15 +3253,27 @@ var init_anthropic = __esm({
3449
3253
  }
3450
3254
  buildRequestPayload(options, descriptor, spec, messages) {
3451
3255
  const systemMessages = messages.filter((message) => message.role === "system");
3452
- const system = systemMessages.length > 0 ? systemMessages.map((m) => m.content).join("\n\n") : void 0;
3453
- const conversation = messages.filter(
3256
+ const system = systemMessages.length > 0 ? systemMessages.map((m, index) => ({
3257
+ type: "text",
3258
+ text: m.content,
3259
+ // Add cache_control to the LAST system message block
3260
+ ...index === systemMessages.length - 1 ? { cache_control: { type: "ephemeral" } } : {}
3261
+ })) : void 0;
3262
+ const nonSystemMessages = messages.filter(
3454
3263
  (message) => message.role !== "system"
3455
- ).map((message) => ({
3264
+ );
3265
+ const lastUserIndex = nonSystemMessages.reduce(
3266
+ (lastIdx, msg, idx) => msg.role === "user" ? idx : lastIdx,
3267
+ -1
3268
+ );
3269
+ const conversation = nonSystemMessages.map((message, index) => ({
3456
3270
  role: message.role,
3457
3271
  content: [
3458
3272
  {
3459
3273
  type: "text",
3460
- text: message.content
3274
+ text: message.content,
3275
+ // Add cache_control to the LAST user message
3276
+ ...message.role === "user" && index === lastUserIndex ? { cache_control: { type: "ephemeral" } } : {}
3461
3277
  }
3462
3278
  ]
3463
3279
  }));
@@ -3483,15 +3299,22 @@ var init_anthropic = __esm({
3483
3299
  async *wrapStream(iterable) {
3484
3300
  const stream2 = iterable;
3485
3301
  let inputTokens = 0;
3302
+ let cachedInputTokens = 0;
3303
+ let cacheCreationInputTokens = 0;
3486
3304
  for await (const event of stream2) {
3487
3305
  if (event.type === "message_start") {
3488
- inputTokens = event.message.usage.input_tokens;
3306
+ const usage = event.message.usage;
3307
+ cachedInputTokens = usage.cache_read_input_tokens ?? 0;
3308
+ cacheCreationInputTokens = usage.cache_creation_input_tokens ?? 0;
3309
+ inputTokens = usage.input_tokens + cachedInputTokens + cacheCreationInputTokens;
3489
3310
  yield {
3490
3311
  text: "",
3491
3312
  usage: {
3492
3313
  inputTokens,
3493
3314
  outputTokens: 0,
3494
- totalTokens: inputTokens
3315
+ totalTokens: inputTokens,
3316
+ cachedInputTokens,
3317
+ cacheCreationInputTokens
3495
3318
  },
3496
3319
  rawEvent: event
3497
3320
  };
@@ -3505,7 +3328,9 @@ var init_anthropic = __esm({
3505
3328
  const usage = event.usage ? {
3506
3329
  inputTokens,
3507
3330
  outputTokens: event.usage.output_tokens,
3508
- totalTokens: inputTokens + event.usage.output_tokens
3331
+ totalTokens: inputTokens + event.usage.output_tokens,
3332
+ cachedInputTokens,
3333
+ cacheCreationInputTokens
3509
3334
  } : void 0;
3510
3335
  if (event.delta.stop_reason || usage) {
3511
3336
  yield {
@@ -3586,6 +3411,7 @@ var init_gemini_models = __esm({
3586
3411
  "src/providers/gemini-models.ts"() {
3587
3412
  "use strict";
3588
3413
  GEMINI_MODELS = [
3414
+ // Gemini 3 Pro (Preview)
3589
3415
  {
3590
3416
  provider: "gemini",
3591
3417
  modelId: "gemini-3-pro-preview",
@@ -3594,8 +3420,11 @@ var init_gemini_models = __esm({
3594
3420
  maxOutputTokens: 65536,
3595
3421
  pricing: {
3596
3422
  input: 2,
3423
+ // $2.00 for prompts <= 200k, $4.00 for > 200k (using lower tier)
3597
3424
  output: 12,
3425
+ // $12.00 for prompts <= 200k, $18.00 for > 200k
3598
3426
  cachedInput: 0.2
3427
+ // $0.20 for prompts <= 200k
3599
3428
  },
3600
3429
  knowledgeCutoff: "2025-01",
3601
3430
  features: {
@@ -3608,9 +3437,10 @@ var init_gemini_models = __esm({
3608
3437
  metadata: {
3609
3438
  family: "Gemini 3",
3610
3439
  releaseDate: "2025-11-18",
3611
- notes: "Most advanced model. 1501 Elo LMArena, 91.9% GPQA Diamond, 76.2% SWE-bench. Deep Think mode available."
3440
+ notes: "Best model for multimodal understanding, agentic and vibe-coding. Deep Think mode available."
3612
3441
  }
3613
3442
  },
3443
+ // Gemini 2.5 Pro
3614
3444
  {
3615
3445
  provider: "gemini",
3616
3446
  modelId: "gemini-2.5-pro",
@@ -3619,8 +3449,11 @@ var init_gemini_models = __esm({
3619
3449
  maxOutputTokens: 65536,
3620
3450
  pricing: {
3621
3451
  input: 1.25,
3452
+ // $1.25 for prompts <= 200k, $2.50 for > 200k
3622
3453
  output: 10,
3454
+ // $10.00 for prompts <= 200k, $15.00 for > 200k
3623
3455
  cachedInput: 0.125
3456
+ // $0.125 for prompts <= 200k
3624
3457
  },
3625
3458
  knowledgeCutoff: "2025-01",
3626
3459
  features: {
@@ -3633,9 +3466,10 @@ var init_gemini_models = __esm({
3633
3466
  metadata: {
3634
3467
  family: "Gemini 2.5",
3635
3468
  releaseDate: "2025-06",
3636
- notes: "Balanced multimodal model with 1M context. Best for complex agents and reasoning."
3469
+ notes: "State-of-the-art multipurpose model. Excels at coding and complex reasoning."
3637
3470
  }
3638
3471
  },
3472
+ // Gemini 2.5 Flash
3639
3473
  {
3640
3474
  provider: "gemini",
3641
3475
  modelId: "gemini-2.5-flash",
@@ -3644,8 +3478,10 @@ var init_gemini_models = __esm({
3644
3478
  maxOutputTokens: 65536,
3645
3479
  pricing: {
3646
3480
  input: 0.3,
3481
+ // $0.30 for text/image/video, $1.00 for audio
3647
3482
  output: 2.5,
3648
3483
  cachedInput: 0.03
3484
+ // $0.03 for text/image/video
3649
3485
  },
3650
3486
  knowledgeCutoff: "2025-01",
3651
3487
  features: {
@@ -3658,9 +3494,10 @@ var init_gemini_models = __esm({
3658
3494
  metadata: {
3659
3495
  family: "Gemini 2.5",
3660
3496
  releaseDate: "2025-06",
3661
- notes: "Best price-performance ratio with thinking enabled by default"
3497
+ notes: "First hybrid reasoning model with 1M context and thinking budgets."
3662
3498
  }
3663
3499
  },
3500
+ // Gemini 2.5 Flash-Lite
3664
3501
  {
3665
3502
  provider: "gemini",
3666
3503
  modelId: "gemini-2.5-flash-lite",
@@ -3669,8 +3506,10 @@ var init_gemini_models = __esm({
3669
3506
  maxOutputTokens: 65536,
3670
3507
  pricing: {
3671
3508
  input: 0.1,
3509
+ // $0.10 for text/image/video, $0.30 for audio
3672
3510
  output: 0.4,
3673
3511
  cachedInput: 0.01
3512
+ // $0.01 for text/image/video
3674
3513
  },
3675
3514
  knowledgeCutoff: "2025-01",
3676
3515
  features: {
@@ -3682,9 +3521,10 @@ var init_gemini_models = __esm({
3682
3521
  metadata: {
3683
3522
  family: "Gemini 2.5",
3684
3523
  releaseDate: "2025-06",
3685
- notes: "Fastest and most cost-efficient model for high-volume, low-latency tasks"
3524
+ notes: "Smallest and most cost effective model, built for at scale usage."
3686
3525
  }
3687
3526
  },
3527
+ // Gemini 2.0 Flash
3688
3528
  {
3689
3529
  provider: "gemini",
3690
3530
  modelId: "gemini-2.0-flash",
@@ -3693,8 +3533,10 @@ var init_gemini_models = __esm({
3693
3533
  maxOutputTokens: 8192,
3694
3534
  pricing: {
3695
3535
  input: 0.1,
3536
+ // $0.10 for text/image/video, $0.70 for audio
3696
3537
  output: 0.4,
3697
- cachedInput: 0.01
3538
+ cachedInput: 0.025
3539
+ // $0.025 for text/image/video
3698
3540
  },
3699
3541
  knowledgeCutoff: "2024-08",
3700
3542
  features: {
@@ -3705,9 +3547,10 @@ var init_gemini_models = __esm({
3705
3547
  },
3706
3548
  metadata: {
3707
3549
  family: "Gemini 2.0",
3708
- notes: "Previous generation with 1M context and multimodal capabilities"
3550
+ notes: "Balanced multimodal model with 1M context, built for the era of Agents."
3709
3551
  }
3710
3552
  },
3553
+ // Gemini 2.0 Flash-Lite
3711
3554
  {
3712
3555
  provider: "gemini",
3713
3556
  modelId: "gemini-2.0-flash-lite",
@@ -3716,8 +3559,8 @@ var init_gemini_models = __esm({
3716
3559
  maxOutputTokens: 8192,
3717
3560
  pricing: {
3718
3561
  input: 0.075,
3719
- output: 0.3,
3720
- cachedInput: 75e-4
3562
+ output: 0.3
3563
+ // No context caching available for 2.0-flash-lite
3721
3564
  },
3722
3565
  knowledgeCutoff: "2024-08",
3723
3566
  features: {
@@ -3728,7 +3571,7 @@ var init_gemini_models = __esm({
3728
3571
  },
3729
3572
  metadata: {
3730
3573
  family: "Gemini 2.0",
3731
- notes: "Lightweight previous generation model for cost-sensitive applications"
3574
+ notes: "Smallest and most cost effective 2.0 model for at scale usage."
3732
3575
  }
3733
3576
  }
3734
3577
  ];
@@ -3898,7 +3741,9 @@ var init_gemini = __esm({
3898
3741
  return {
3899
3742
  inputTokens: usageMetadata.promptTokenCount ?? 0,
3900
3743
  outputTokens: usageMetadata.candidatesTokenCount ?? 0,
3901
- totalTokens: usageMetadata.totalTokenCount ?? 0
3744
+ totalTokens: usageMetadata.totalTokenCount ?? 0,
3745
+ // Gemini returns cached token count in cachedContentTokenCount
3746
+ cachedInputTokens: usageMetadata.cachedContentTokenCount ?? 0
3902
3747
  };
3903
3748
  }
3904
3749
  /**
@@ -3954,10 +3799,11 @@ var init_openai_models = __esm({
3954
3799
  "src/providers/openai-models.ts"() {
3955
3800
  "use strict";
3956
3801
  OPENAI_MODELS = [
3802
+ // GPT-5 Family
3957
3803
  {
3958
3804
  provider: "openai",
3959
3805
  modelId: "gpt-5.1",
3960
- displayName: "GPT-5.1 Instant",
3806
+ displayName: "GPT-5.1",
3961
3807
  contextWindow: 128e3,
3962
3808
  maxOutputTokens: 32768,
3963
3809
  pricing: {
@@ -3977,34 +3823,7 @@ var init_openai_models = __esm({
3977
3823
  metadata: {
3978
3824
  family: "GPT-5",
3979
3825
  releaseDate: "2025-11-12",
3980
- notes: "Warmer, more intelligent, better instruction following. 2-3x faster than GPT-5.",
3981
- supportsTemperature: false
3982
- }
3983
- },
3984
- {
3985
- provider: "openai",
3986
- modelId: "gpt-5.1-thinking",
3987
- displayName: "GPT-5.1 Thinking",
3988
- contextWindow: 196e3,
3989
- maxOutputTokens: 32768,
3990
- pricing: {
3991
- input: 1.25,
3992
- output: 10,
3993
- cachedInput: 0.125
3994
- },
3995
- knowledgeCutoff: "2024-09-30",
3996
- features: {
3997
- streaming: true,
3998
- functionCalling: true,
3999
- vision: true,
4000
- reasoning: true,
4001
- structuredOutputs: true,
4002
- fineTuning: true
4003
- },
4004
- metadata: {
4005
- family: "GPT-5",
4006
- releaseDate: "2025-11-12",
4007
- notes: "Advanced reasoning with thinking levels: Light, Standard, Extended, Heavy. Best for complex tasks.",
3826
+ notes: "Latest GPT-5 with improved instruction following. 2-3x faster than GPT-5.",
4008
3827
  supportsTemperature: false
4009
3828
  }
4010
3829
  },
@@ -4084,6 +3903,255 @@ var init_openai_models = __esm({
4084
3903
  notes: "Fastest, most cost-efficient version for well-defined tasks",
4085
3904
  supportsTemperature: false
4086
3905
  }
3906
+ },
3907
+ {
3908
+ provider: "openai",
3909
+ modelId: "gpt-5-pro",
3910
+ displayName: "GPT-5 Pro",
3911
+ contextWindow: 272e3,
3912
+ maxOutputTokens: 128e3,
3913
+ pricing: {
3914
+ input: 15,
3915
+ output: 120
3916
+ // No cached input pricing for gpt-5-pro
3917
+ },
3918
+ knowledgeCutoff: "2024-09-30",
3919
+ features: {
3920
+ streaming: true,
3921
+ functionCalling: true,
3922
+ vision: true,
3923
+ reasoning: true,
3924
+ structuredOutputs: true
3925
+ },
3926
+ metadata: {
3927
+ family: "GPT-5",
3928
+ notes: "Premium tier with enhanced capabilities. Does not support prompt caching.",
3929
+ supportsTemperature: false
3930
+ }
3931
+ },
3932
+ // GPT-4.1 Family
3933
+ {
3934
+ provider: "openai",
3935
+ modelId: "gpt-4.1",
3936
+ displayName: "GPT-4.1",
3937
+ contextWindow: 128e3,
3938
+ maxOutputTokens: 32768,
3939
+ pricing: {
3940
+ input: 2,
3941
+ output: 8,
3942
+ cachedInput: 0.5
3943
+ },
3944
+ knowledgeCutoff: "2024-04-01",
3945
+ features: {
3946
+ streaming: true,
3947
+ functionCalling: true,
3948
+ vision: true,
3949
+ structuredOutputs: true,
3950
+ fineTuning: true
3951
+ },
3952
+ metadata: {
3953
+ family: "GPT-4.1",
3954
+ notes: "Improved GPT-4 with better instruction following"
3955
+ }
3956
+ },
3957
+ {
3958
+ provider: "openai",
3959
+ modelId: "gpt-4.1-mini",
3960
+ displayName: "GPT-4.1 Mini",
3961
+ contextWindow: 128e3,
3962
+ maxOutputTokens: 32768,
3963
+ pricing: {
3964
+ input: 0.4,
3965
+ output: 1.6,
3966
+ cachedInput: 0.1
3967
+ },
3968
+ knowledgeCutoff: "2024-04-01",
3969
+ features: {
3970
+ streaming: true,
3971
+ functionCalling: true,
3972
+ vision: true,
3973
+ structuredOutputs: true,
3974
+ fineTuning: true
3975
+ },
3976
+ metadata: {
3977
+ family: "GPT-4.1",
3978
+ notes: "Cost-efficient GPT-4.1 variant"
3979
+ }
3980
+ },
3981
+ {
3982
+ provider: "openai",
3983
+ modelId: "gpt-4.1-nano",
3984
+ displayName: "GPT-4.1 Nano",
3985
+ contextWindow: 128e3,
3986
+ maxOutputTokens: 32768,
3987
+ pricing: {
3988
+ input: 0.1,
3989
+ output: 0.4,
3990
+ cachedInput: 0.025
3991
+ },
3992
+ knowledgeCutoff: "2024-04-01",
3993
+ features: {
3994
+ streaming: true,
3995
+ functionCalling: true,
3996
+ vision: true,
3997
+ structuredOutputs: true,
3998
+ fineTuning: true
3999
+ },
4000
+ metadata: {
4001
+ family: "GPT-4.1",
4002
+ notes: "Fastest GPT-4.1 variant for simple tasks"
4003
+ }
4004
+ },
4005
+ // GPT-4o Family
4006
+ {
4007
+ provider: "openai",
4008
+ modelId: "gpt-4o",
4009
+ displayName: "GPT-4o",
4010
+ contextWindow: 128e3,
4011
+ maxOutputTokens: 16384,
4012
+ pricing: {
4013
+ input: 2.5,
4014
+ output: 10,
4015
+ cachedInput: 1.25
4016
+ },
4017
+ knowledgeCutoff: "2024-04-01",
4018
+ features: {
4019
+ streaming: true,
4020
+ functionCalling: true,
4021
+ vision: true,
4022
+ structuredOutputs: true,
4023
+ fineTuning: true
4024
+ },
4025
+ metadata: {
4026
+ family: "GPT-4o",
4027
+ notes: "Multimodal model optimized for speed"
4028
+ }
4029
+ },
4030
+ {
4031
+ provider: "openai",
4032
+ modelId: "gpt-4o-mini",
4033
+ displayName: "GPT-4o Mini",
4034
+ contextWindow: 128e3,
4035
+ maxOutputTokens: 16384,
4036
+ pricing: {
4037
+ input: 0.15,
4038
+ output: 0.6,
4039
+ cachedInput: 0.075
4040
+ },
4041
+ knowledgeCutoff: "2024-04-01",
4042
+ features: {
4043
+ streaming: true,
4044
+ functionCalling: true,
4045
+ vision: true,
4046
+ structuredOutputs: true,
4047
+ fineTuning: true
4048
+ },
4049
+ metadata: {
4050
+ family: "GPT-4o",
4051
+ notes: "Fast and affordable multimodal model"
4052
+ }
4053
+ },
4054
+ // o-series (Reasoning models)
4055
+ {
4056
+ provider: "openai",
4057
+ modelId: "o1",
4058
+ displayName: "o1",
4059
+ contextWindow: 2e5,
4060
+ maxOutputTokens: 1e5,
4061
+ pricing: {
4062
+ input: 15,
4063
+ output: 60,
4064
+ cachedInput: 7.5
4065
+ },
4066
+ knowledgeCutoff: "2024-12-01",
4067
+ features: {
4068
+ streaming: true,
4069
+ functionCalling: true,
4070
+ vision: true,
4071
+ reasoning: true,
4072
+ structuredOutputs: true
4073
+ },
4074
+ metadata: {
4075
+ family: "o-series",
4076
+ notes: "Advanced reasoning model with chain-of-thought",
4077
+ supportsTemperature: false
4078
+ }
4079
+ },
4080
+ {
4081
+ provider: "openai",
4082
+ modelId: "o3",
4083
+ displayName: "o3",
4084
+ contextWindow: 2e5,
4085
+ maxOutputTokens: 1e5,
4086
+ pricing: {
4087
+ input: 2,
4088
+ output: 8,
4089
+ cachedInput: 0.5
4090
+ },
4091
+ knowledgeCutoff: "2025-01-01",
4092
+ features: {
4093
+ streaming: true,
4094
+ functionCalling: true,
4095
+ vision: true,
4096
+ reasoning: true,
4097
+ structuredOutputs: true
4098
+ },
4099
+ metadata: {
4100
+ family: "o-series",
4101
+ notes: "Next-gen reasoning model, more efficient than o1",
4102
+ supportsTemperature: false
4103
+ }
4104
+ },
4105
+ {
4106
+ provider: "openai",
4107
+ modelId: "o4-mini",
4108
+ displayName: "o4 Mini",
4109
+ contextWindow: 2e5,
4110
+ maxOutputTokens: 1e5,
4111
+ pricing: {
4112
+ input: 1.1,
4113
+ output: 4.4,
4114
+ cachedInput: 0.275
4115
+ },
4116
+ knowledgeCutoff: "2025-04-01",
4117
+ features: {
4118
+ streaming: true,
4119
+ functionCalling: true,
4120
+ vision: true,
4121
+ reasoning: true,
4122
+ structuredOutputs: true,
4123
+ fineTuning: true
4124
+ },
4125
+ metadata: {
4126
+ family: "o-series",
4127
+ notes: "Cost-efficient reasoning model",
4128
+ supportsTemperature: false
4129
+ }
4130
+ },
4131
+ {
4132
+ provider: "openai",
4133
+ modelId: "o3-mini",
4134
+ displayName: "o3 Mini",
4135
+ contextWindow: 2e5,
4136
+ maxOutputTokens: 1e5,
4137
+ pricing: {
4138
+ input: 1.1,
4139
+ output: 4.4,
4140
+ cachedInput: 0.55
4141
+ },
4142
+ knowledgeCutoff: "2025-01-01",
4143
+ features: {
4144
+ streaming: true,
4145
+ functionCalling: true,
4146
+ vision: true,
4147
+ reasoning: true,
4148
+ structuredOutputs: true
4149
+ },
4150
+ metadata: {
4151
+ family: "o-series",
4152
+ notes: "Compact reasoning model for cost-sensitive applications",
4153
+ supportsTemperature: false
4154
+ }
4087
4155
  }
4088
4156
  ];
4089
4157
  }
@@ -4164,7 +4232,8 @@ var init_openai = __esm({
4164
4232
  const usage = chunk.usage ? {
4165
4233
  inputTokens: chunk.usage.prompt_tokens,
4166
4234
  outputTokens: chunk.usage.completion_tokens,
4167
- totalTokens: chunk.usage.total_tokens
4235
+ totalTokens: chunk.usage.total_tokens,
4236
+ cachedInputTokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0
4168
4237
  } : void 0;
4169
4238
  if (finishReason || usage) {
4170
4239
  yield { text: "", finishReason, usage, rawEvent: chunk };
@@ -4381,20 +4450,28 @@ var init_model_registry = __esm({
4381
4450
  /**
4382
4451
  * Estimate API cost for a given model and token usage
4383
4452
  * @param modelId - Full model identifier
4384
- * @param inputTokens - Number of input tokens
4453
+ * @param inputTokens - Number of input tokens (total, including cached and cache creation)
4385
4454
  * @param outputTokens - Number of output tokens
4386
- * @param useCachedInput - Whether to use cached input pricing (if supported by provider)
4455
+ * @param cachedInputTokens - Number of cached input tokens (subset of inputTokens)
4456
+ * @param cacheCreationInputTokens - Number of cache creation tokens (subset of inputTokens, Anthropic only)
4387
4457
  * @returns CostEstimate if model found, undefined otherwise
4388
4458
  */
4389
- estimateCost(modelId, inputTokens, outputTokens, useCachedInput = false) {
4459
+ estimateCost(modelId, inputTokens, outputTokens, cachedInputTokens = 0, cacheCreationInputTokens = 0) {
4390
4460
  const spec = this.getModelSpec(modelId);
4391
4461
  if (!spec) return void 0;
4392
- const inputRate = useCachedInput && spec.pricing.cachedInput !== void 0 ? spec.pricing.cachedInput : spec.pricing.input;
4393
- const inputCost = inputTokens / 1e6 * inputRate;
4462
+ const cachedRate = spec.pricing.cachedInput ?? spec.pricing.input;
4463
+ const cacheWriteRate = spec.pricing.cacheWriteInput ?? spec.pricing.input;
4464
+ const uncachedInputTokens = inputTokens - cachedInputTokens - cacheCreationInputTokens;
4465
+ const uncachedInputCost = uncachedInputTokens / 1e6 * spec.pricing.input;
4466
+ const cachedInputCost = cachedInputTokens / 1e6 * cachedRate;
4467
+ const cacheCreationCost = cacheCreationInputTokens / 1e6 * cacheWriteRate;
4468
+ const inputCost = uncachedInputCost + cachedInputCost + cacheCreationCost;
4394
4469
  const outputCost = outputTokens / 1e6 * spec.pricing.output;
4395
4470
  const totalCost = inputCost + outputCost;
4396
4471
  return {
4397
4472
  inputCost,
4473
+ cachedInputCost,
4474
+ cacheCreationCost,
4398
4475
  outputCost,
4399
4476
  totalCost,
4400
4477
  currency: "USD"
@@ -4793,9 +4870,9 @@ var init_builder = __esm({
4793
4870
  gadgets = [];
4794
4871
  initialMessages = [];
4795
4872
  onHumanInputRequired;
4796
- parameterFormat;
4797
4873
  gadgetStartPrefix;
4798
4874
  gadgetEndPrefix;
4875
+ gadgetArgPrefix;
4799
4876
  textOnlyHandler;
4800
4877
  textWithGadgetsHandler;
4801
4878
  stopOnGadgetError;
@@ -4982,21 +5059,6 @@ var init_builder = __esm({
4982
5059
  this.onHumanInputRequired = handler;
4983
5060
  return this;
4984
5061
  }
4985
- /**
4986
- * Set the parameter format for gadget calls.
4987
- *
4988
- * @param format - Parameter format ("json" or "xml")
4989
- * @returns This builder for chaining
4990
- *
4991
- * @example
4992
- * ```typescript
4993
- * .withParameterFormat("xml")
4994
- * ```
4995
- */
4996
- withParameterFormat(format) {
4997
- this.parameterFormat = format;
4998
- return this;
4999
- }
5000
5062
  /**
5001
5063
  * Set custom gadget marker prefix.
5002
5064
  *
@@ -5027,6 +5089,21 @@ var init_builder = __esm({
5027
5089
  this.gadgetEndPrefix = suffix;
5028
5090
  return this;
5029
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
+ }
5030
5107
  /**
5031
5108
  * Set the text-only handler strategy.
5032
5109
  *
@@ -5226,8 +5303,7 @@ var init_builder = __esm({
5226
5303
  withSyntheticGadgetCall(gadgetName, parameters, result) {
5227
5304
  const startPrefix = this.gadgetStartPrefix ?? GADGET_START_PREFIX;
5228
5305
  const endPrefix = this.gadgetEndPrefix ?? GADGET_END_PREFIX;
5229
- const format = this.parameterFormat ?? "yaml";
5230
- const paramStr = this.formatSyntheticParameters(parameters, format);
5306
+ const paramStr = this.formatBlockParameters(parameters, "");
5231
5307
  this.initialMessages.push({
5232
5308
  role: "assistant",
5233
5309
  content: `${startPrefix}${gadgetName}
@@ -5241,25 +5317,31 @@ ${endPrefix}`
5241
5317
  return this;
5242
5318
  }
5243
5319
  /**
5244
- * Format parameters for synthetic gadget calls.
5245
- * Uses heredoc for multiline string values.
5320
+ * Format parameters as block format with JSON Pointer paths.
5246
5321
  */
5247
- formatSyntheticParameters(parameters, format) {
5248
- if (format === "json" || format === "auto") {
5249
- return JSON.stringify(parameters);
5250
- }
5251
- return Object.entries(parameters).map(([key, value]) => {
5252
- if (typeof value === "string" && value.includes("\n")) {
5253
- const separator = format === "yaml" ? ":" : " =";
5254
- return `${key}${separator} <<<EOF
5255
- ${value}
5256
- EOF`;
5257
- }
5258
- if (format === "yaml") {
5259
- 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));
5260
5342
  }
5261
- return `${key} = ${JSON.stringify(value)}`;
5262
- }).join("\n");
5343
+ }
5344
+ return lines.join("\n");
5263
5345
  }
5264
5346
  /**
5265
5347
  * Build and create the agent with the given user prompt.
@@ -5299,9 +5381,9 @@ EOF`;
5299
5381
  promptConfig: this.promptConfig,
5300
5382
  initialMessages: this.initialMessages,
5301
5383
  onHumanInputRequired: this.onHumanInputRequired,
5302
- parameterFormat: this.parameterFormat,
5303
5384
  gadgetStartPrefix: this.gadgetStartPrefix,
5304
5385
  gadgetEndPrefix: this.gadgetEndPrefix,
5386
+ gadgetArgPrefix: this.gadgetArgPrefix,
5305
5387
  textOnlyHandler: this.textOnlyHandler,
5306
5388
  textWithGadgetsHandler: this.textWithGadgetsHandler,
5307
5389
  stopOnGadgetError: this.stopOnGadgetError,
@@ -5401,9 +5483,9 @@ EOF`;
5401
5483
  promptConfig: this.promptConfig,
5402
5484
  initialMessages: this.initialMessages,
5403
5485
  onHumanInputRequired: this.onHumanInputRequired,
5404
- parameterFormat: this.parameterFormat,
5405
5486
  gadgetStartPrefix: this.gadgetStartPrefix,
5406
5487
  gadgetEndPrefix: this.gadgetEndPrefix,
5488
+ gadgetArgPrefix: this.gadgetArgPrefix,
5407
5489
  textOnlyHandler: this.textOnlyHandler,
5408
5490
  textWithGadgetsHandler: this.textWithGadgetsHandler,
5409
5491
  stopOnGadgetError: this.stopOnGadgetError,
@@ -6483,17 +6565,51 @@ function splitIntoChunks(text, minChunkSize = 5, maxChunkSize = 30) {
6483
6565
  }
6484
6566
  return chunks;
6485
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
+ }
6486
6603
  function formatGadgetCalls(gadgetCalls) {
6487
6604
  let text = "";
6488
6605
  const calls = [];
6489
6606
  for (const call of gadgetCalls) {
6490
6607
  const invocationId = call.invocationId ?? generateInvocationId();
6491
6608
  calls.push({ name: call.gadgetName, invocationId });
6492
- const paramsJson = JSON.stringify(call.parameters);
6609
+ const blockParams = serializeToBlockFormat(call.parameters);
6493
6610
  text += `
6494
6611
  ${GADGET_START_PREFIX}${call.gadgetName}
6495
- ${paramsJson}
6496
- ${GADGET_END_PREFIX}`;
6612
+ ${blockParams}${GADGET_END_PREFIX}`;
6497
6613
  }
6498
6614
  return { text, calls };
6499
6615
  }