llmist 0.4.1 → 0.5.1

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
@@ -384,6 +384,7 @@ var init_prompt_config = __esm({
384
384
  criticalUsage: "INVOKE gadgets using the markers - do not describe what you want to do.",
385
385
  formatDescriptionYaml: "Parameters in YAML format (one per line)",
386
386
  formatDescriptionJson: "Parameters in JSON format (valid JSON object)",
387
+ formatDescriptionToml: "Parameters in TOML format (key = value pairs, use triple-quotes for multiline)",
387
388
  rules: () => [
388
389
  "Output ONLY plain text with the exact markers - never use function/tool calling",
389
390
  "You can invoke multiple gadgets in a single response",
@@ -391,6 +392,7 @@ var init_prompt_config = __esm({
391
392
  ],
392
393
  schemaLabelJson: "\n\nInput Schema (JSON):",
393
394
  schemaLabelYaml: "\n\nInput Schema (YAML):",
395
+ schemaLabelToml: "\n\nInput Schema (TOML):",
394
396
  customExamples: null
395
397
  };
396
398
  }
@@ -411,6 +413,15 @@ var init_messages = __esm({
411
413
  constructor(promptConfig) {
412
414
  this.promptConfig = promptConfig ?? {};
413
415
  }
416
+ /**
417
+ * Set custom prefixes for gadget markers.
418
+ * Used to configure history builder to match system prompt markers.
419
+ */
420
+ withPrefixes(startPrefix, endPrefix) {
421
+ this.startPrefix = startPrefix;
422
+ this.endPrefix = endPrefix;
423
+ return this;
424
+ }
414
425
  addSystem(content, metadata) {
415
426
  this.messages.push({ role: "system", content, metadata });
416
427
  return this;
@@ -448,7 +459,14 @@ var init_messages = __esm({
448
459
  for (const gadget of gadgets) {
449
460
  const gadgetName = gadget.name ?? gadget.constructor.name;
450
461
  const instruction = gadget.getInstruction(parameterFormat);
451
- const schemaMarker = parameterFormat === "yaml" ? "\n\nInput Schema (YAML):" : "\n\nInput Schema (JSON):";
462
+ const schemaMarkers = {
463
+ yaml: "\n\nInput Schema (YAML):",
464
+ json: "\n\nInput Schema (JSON):",
465
+ toml: "\n\nInput Schema (TOML):",
466
+ auto: "\n\nInput Schema (JSON):"
467
+ // auto defaults to JSON schema display
468
+ };
469
+ const schemaMarker = schemaMarkers[parameterFormat];
452
470
  const schemaIndex = instruction.indexOf(schemaMarker);
453
471
  const description = (schemaIndex !== -1 ? instruction.substring(0, schemaIndex) : instruction).trim();
454
472
  const schema = schemaIndex !== -1 ? instruction.substring(schemaIndex + schemaMarker.length).trim() : "";
@@ -468,15 +486,26 @@ ${schema}`);
468
486
  }
469
487
  buildUsageSection(parameterFormat, context) {
470
488
  const parts = [];
471
- const formatDescription = parameterFormat === "yaml" ? resolvePromptTemplate(
472
- this.promptConfig.formatDescriptionYaml,
473
- DEFAULT_PROMPTS.formatDescriptionYaml,
474
- context
475
- ) : resolvePromptTemplate(
476
- this.promptConfig.formatDescriptionJson,
477
- DEFAULT_PROMPTS.formatDescriptionJson,
478
- context
479
- );
489
+ const formatDescriptionMap = {
490
+ yaml: {
491
+ config: this.promptConfig.formatDescriptionYaml,
492
+ defaultValue: DEFAULT_PROMPTS.formatDescriptionYaml
493
+ },
494
+ json: {
495
+ config: this.promptConfig.formatDescriptionJson,
496
+ defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
497
+ },
498
+ toml: {
499
+ config: this.promptConfig.formatDescriptionToml,
500
+ defaultValue: DEFAULT_PROMPTS.formatDescriptionToml
501
+ },
502
+ auto: {
503
+ config: this.promptConfig.formatDescriptionJson,
504
+ defaultValue: DEFAULT_PROMPTS.formatDescriptionJson
505
+ }
506
+ };
507
+ const { config, defaultValue } = formatDescriptionMap[parameterFormat];
508
+ const formatDescription = resolvePromptTemplate(config, defaultValue, context);
480
509
  parts.push("\n\nHOW TO INVOKE GADGETS");
481
510
  parts.push("\n=====================\n");
482
511
  const criticalUsage = resolvePromptTemplate(
@@ -504,38 +533,110 @@ CRITICAL: ${criticalUsage}
504
533
  return this.promptConfig.customExamples(context);
505
534
  }
506
535
  const parts = [];
507
- const singleExample = parameterFormat === "yaml" ? `${this.startPrefix}translate
536
+ const singleExamples = {
537
+ yaml: `${this.startPrefix}translate
508
538
  from: English
509
539
  to: Polish
510
- content: Paris is the capital of France.
511
- ${this.endPrefix}` : `${this.startPrefix}translate
512
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France."}
513
- ${this.endPrefix}`;
540
+ content: "Paris is the capital of France: a beautiful city."
541
+ ${this.endPrefix}`,
542
+ json: `${this.startPrefix}translate
543
+ {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
544
+ ${this.endPrefix}`,
545
+ toml: `${this.startPrefix}translate
546
+ from = "English"
547
+ to = "Polish"
548
+ content = "Paris is the capital of France: a beautiful city."
549
+ ${this.endPrefix}`,
550
+ auto: `${this.startPrefix}translate
551
+ {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
552
+ ${this.endPrefix}`
553
+ };
514
554
  parts.push(`
515
555
 
516
556
  EXAMPLE (Single Gadget):
517
557
 
518
- ${singleExample}`);
519
- const multipleExample = parameterFormat === "yaml" ? `${this.startPrefix}translate
558
+ ${singleExamples[parameterFormat]}`);
559
+ const multipleExamples = {
560
+ yaml: `${this.startPrefix}translate
520
561
  from: English
521
562
  to: Polish
522
- content: Paris is the capital of France.
563
+ content: "Paris is the capital of France: a beautiful city."
523
564
  ${this.endPrefix}
524
565
  ${this.startPrefix}analyze
525
566
  type: economic_analysis
526
567
  matter: "Polish Economy"
527
- question: Polish arms exports 2025.
528
- ${this.endPrefix}` : `${this.startPrefix}translate
529
- {"from": "English", "to": "Polish", "content": "Paris is the capital of France."}
568
+ question: |
569
+ Analyze the following:
570
+ - Polish arms exports 2025
571
+ - Economic implications
572
+ ${this.endPrefix}`,
573
+ json: `${this.startPrefix}translate
574
+ {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
575
+ ${this.endPrefix}
576
+ ${this.startPrefix}analyze
577
+ {"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
578
+ ${this.endPrefix}`,
579
+ toml: `${this.startPrefix}translate
580
+ from = "English"
581
+ to = "Polish"
582
+ content = "Paris is the capital of France: a beautiful city."
530
583
  ${this.endPrefix}
531
584
  ${this.startPrefix}analyze
532
- {"type": "economic_analysis", "matter": "Polish Economy", "question": "Polish arms exports 2025."}
533
- ${this.endPrefix}`;
585
+ type = "economic_analysis"
586
+ matter = "Polish Economy"
587
+ question = """
588
+ Analyze the following:
589
+ - Polish arms exports 2025
590
+ - Economic implications
591
+ """
592
+ ${this.endPrefix}`,
593
+ auto: `${this.startPrefix}translate
594
+ {"from": "English", "to": "Polish", "content": "Paris is the capital of France: a beautiful city."}
595
+ ${this.endPrefix}
596
+ ${this.startPrefix}analyze
597
+ {"type": "economic_analysis", "matter": "Polish Economy", "question": "Analyze the following: Polish arms exports 2025, economic implications"}
598
+ ${this.endPrefix}`
599
+ };
534
600
  parts.push(`
535
601
 
536
602
  EXAMPLE (Multiple Gadgets):
537
603
 
538
- ${multipleExample}`);
604
+ ${multipleExamples[parameterFormat]}`);
605
+ if (parameterFormat === "yaml") {
606
+ parts.push(`
607
+
608
+ YAML MULTILINE SYNTAX:
609
+ For string values with special characters (colons, dashes, quotes) or multiple lines,
610
+ use the pipe (|) syntax. ALL content lines MUST be indented with 2 spaces:
611
+
612
+ CORRECT - all lines indented:
613
+ question: |
614
+ Which option do you prefer?
615
+ - Option A: fast processing
616
+ - Option B: thorough analysis
617
+ Please choose one.
618
+
619
+ WRONG - inconsistent indentation breaks YAML:
620
+ question: |
621
+ Which option do you prefer?
622
+ - Option A: fast
623
+ Please choose one. <-- ERROR: not indented, breaks out of the block`);
624
+ } else if (parameterFormat === "toml") {
625
+ parts.push(`
626
+
627
+ TOML MULTILINE SYNTAX:
628
+ For string values with multiple lines or special characters, use triple-quotes ("""):
629
+
630
+ filePath = "README.md"
631
+ content = """
632
+ # Project Title
633
+
634
+ This content can contain:
635
+ - Markdown lists
636
+ - Special characters: # : -
637
+ - Multiple paragraphs
638
+ """`);
639
+ }
539
640
  return parts.join("");
540
641
  }
541
642
  buildRulesSection(context) {
@@ -579,6 +680,16 @@ ${this.endPrefix}`
579
680
  return `${key}: ${JSON.stringify(value)}`;
580
681
  }).join("\n");
581
682
  }
683
+ if (format === "toml") {
684
+ return Object.entries(parameters).map(([key, value]) => {
685
+ if (typeof value === "string" && value.includes("\n")) {
686
+ return `${key} = """
687
+ ${value}
688
+ """`;
689
+ }
690
+ return `${key} = ${JSON.stringify(value)}`;
691
+ }).join("\n");
692
+ }
582
693
  return JSON.stringify(parameters);
583
694
  }
584
695
  build() {
@@ -680,11 +791,14 @@ var init_conversation_manager = __esm({
680
791
  initialMessages;
681
792
  historyBuilder;
682
793
  parameterFormat;
683
- constructor(baseMessages, initialMessages, parameterFormat = "json") {
794
+ constructor(baseMessages, initialMessages, options = {}) {
684
795
  this.baseMessages = baseMessages;
685
796
  this.initialMessages = initialMessages;
686
- this.parameterFormat = parameterFormat;
797
+ this.parameterFormat = options.parameterFormat ?? "json";
687
798
  this.historyBuilder = new LLMMessageBuilder();
799
+ if (options.startPrefix && options.endPrefix) {
800
+ this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix);
801
+ }
688
802
  }
689
803
  addUserMessage(content) {
690
804
  this.historyBuilder.addUser(content);
@@ -1185,11 +1299,109 @@ var init_executor = __esm({
1185
1299
  });
1186
1300
 
1187
1301
  // src/gadgets/parser.ts
1188
- var yaml, globalInvocationCounter, StreamParser;
1302
+ function preprocessYaml(yamlStr) {
1303
+ const lines = yamlStr.split("\n");
1304
+ const result = [];
1305
+ let i = 0;
1306
+ while (i < lines.length) {
1307
+ const line = lines[i];
1308
+ const match = line.match(/^(\s*)([\w-]+):\s+(.+)$/);
1309
+ if (match) {
1310
+ const [, indent, key, value] = match;
1311
+ if (value === "|" || value === ">" || value === "|-" || value === ">-") {
1312
+ result.push(line);
1313
+ i++;
1314
+ const keyIndentLen2 = indent.length;
1315
+ const blockLines = [];
1316
+ let minContentIndent = Infinity;
1317
+ while (i < lines.length) {
1318
+ const blockLine = lines[i];
1319
+ const blockIndentMatch = blockLine.match(/^(\s*)/);
1320
+ const blockIndentLen = blockIndentMatch ? blockIndentMatch[1].length : 0;
1321
+ if (blockLine.trim() === "") {
1322
+ blockLines.push({ content: "", originalIndent: 0 });
1323
+ i++;
1324
+ continue;
1325
+ }
1326
+ if (blockIndentLen > keyIndentLen2) {
1327
+ const content = blockLine.substring(blockIndentLen);
1328
+ blockLines.push({ content, originalIndent: blockIndentLen });
1329
+ if (content.trim().length > 0) {
1330
+ minContentIndent = Math.min(minContentIndent, blockIndentLen);
1331
+ }
1332
+ i++;
1333
+ } else {
1334
+ break;
1335
+ }
1336
+ }
1337
+ const targetIndent = keyIndentLen2 + 2;
1338
+ for (const blockLine of blockLines) {
1339
+ if (blockLine.content === "") {
1340
+ result.push("");
1341
+ } else {
1342
+ result.push(" ".repeat(targetIndent) + blockLine.content);
1343
+ }
1344
+ }
1345
+ continue;
1346
+ }
1347
+ if (value.startsWith('"') || value.startsWith("'") || value === "true" || value === "false" || /^-?\d+(\.\d+)?$/.test(value)) {
1348
+ result.push(line);
1349
+ i++;
1350
+ continue;
1351
+ }
1352
+ const keyIndentLen = indent.length;
1353
+ const continuationLines = [];
1354
+ let j = i + 1;
1355
+ while (j < lines.length) {
1356
+ const nextLine = lines[j];
1357
+ if (nextLine.trim() === "") {
1358
+ continuationLines.push(nextLine);
1359
+ j++;
1360
+ continue;
1361
+ }
1362
+ const nextIndentMatch = nextLine.match(/^(\s*)/);
1363
+ const nextIndentLen = nextIndentMatch ? nextIndentMatch[1].length : 0;
1364
+ if (nextIndentLen > keyIndentLen) {
1365
+ continuationLines.push(nextLine);
1366
+ j++;
1367
+ } else {
1368
+ break;
1369
+ }
1370
+ }
1371
+ if (continuationLines.length > 0 && continuationLines.some((l) => l.trim().length > 0)) {
1372
+ result.push(`${indent}${key}: |`);
1373
+ result.push(`${indent} ${value}`);
1374
+ for (const contLine of continuationLines) {
1375
+ if (contLine.trim() === "") {
1376
+ result.push("");
1377
+ } else {
1378
+ const contIndentMatch = contLine.match(/^(\s*)/);
1379
+ const contIndent = contIndentMatch ? contIndentMatch[1] : "";
1380
+ const contContent = contLine.substring(contIndent.length);
1381
+ result.push(`${indent} ${contContent}`);
1382
+ }
1383
+ }
1384
+ i = j;
1385
+ continue;
1386
+ }
1387
+ if (value.includes(": ") || value.endsWith(":")) {
1388
+ const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
1389
+ result.push(`${indent}${key}: "${escaped}"`);
1390
+ i++;
1391
+ continue;
1392
+ }
1393
+ }
1394
+ result.push(line);
1395
+ i++;
1396
+ }
1397
+ return result.join("\n");
1398
+ }
1399
+ var yaml, import_js_toml, globalInvocationCounter, StreamParser;
1189
1400
  var init_parser = __esm({
1190
1401
  "src/gadgets/parser.ts"() {
1191
1402
  "use strict";
1192
1403
  yaml = __toESM(require("js-yaml"), 1);
1404
+ import_js_toml = require("js-toml");
1193
1405
  init_constants();
1194
1406
  globalInvocationCounter = 0;
1195
1407
  StreamParser = class {
@@ -1211,6 +1423,17 @@ var init_parser = __esm({
1211
1423
  this.lastReportedTextLength = index;
1212
1424
  return segment.trim().length > 0 ? segment : void 0;
1213
1425
  }
1426
+ /**
1427
+ * Parse gadget name, handling both old format (name:invocationId) and new format (just name).
1428
+ * For new format, generates a unique invocation ID.
1429
+ */
1430
+ parseGadgetName(gadgetName) {
1431
+ if (gadgetName.includes(":")) {
1432
+ const parts = gadgetName.split(":");
1433
+ return { actualName: parts[0], invocationId: parts[1] };
1434
+ }
1435
+ return { actualName: gadgetName, invocationId: `gadget_${++globalInvocationCounter}` };
1436
+ }
1214
1437
  /**
1215
1438
  * Parse parameter string according to configured format
1216
1439
  */
@@ -1224,20 +1447,31 @@ var init_parser = __esm({
1224
1447
  }
1225
1448
  if (this.parameterFormat === "yaml") {
1226
1449
  try {
1227
- return { parameters: yaml.load(raw) };
1450
+ return { parameters: yaml.load(preprocessYaml(raw)) };
1228
1451
  } catch (error) {
1229
1452
  return { parseError: error instanceof Error ? error.message : "Failed to parse YAML" };
1230
1453
  }
1231
1454
  }
1455
+ if (this.parameterFormat === "toml") {
1456
+ try {
1457
+ return { parameters: (0, import_js_toml.load)(raw) };
1458
+ } catch (error) {
1459
+ return { parseError: error instanceof Error ? error.message : "Failed to parse TOML" };
1460
+ }
1461
+ }
1232
1462
  try {
1233
1463
  return { parameters: JSON.parse(raw) };
1234
1464
  } catch {
1235
1465
  try {
1236
- return { parameters: yaml.load(raw) };
1237
- } catch (error) {
1238
- return {
1239
- parseError: error instanceof Error ? error.message : "Failed to parse as JSON or YAML"
1240
- };
1466
+ return { parameters: (0, import_js_toml.load)(raw) };
1467
+ } catch {
1468
+ try {
1469
+ return { parameters: yaml.load(preprocessYaml(raw)) };
1470
+ } catch (error) {
1471
+ return {
1472
+ parseError: error instanceof Error ? error.message : "Failed to parse as JSON, TOML, or YAML"
1473
+ };
1474
+ }
1241
1475
  }
1242
1476
  }
1243
1477
  }
@@ -1256,16 +1490,7 @@ var init_parser = __esm({
1256
1490
  const metadataEndIndex = this.buffer.indexOf("\n", metadataStartIndex);
1257
1491
  if (metadataEndIndex === -1) break;
1258
1492
  const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
1259
- let invocationId;
1260
- let actualGadgetName;
1261
- if (gadgetName.includes(":")) {
1262
- const parts = gadgetName.split(":");
1263
- actualGadgetName = parts[0];
1264
- invocationId = parts[1];
1265
- } else {
1266
- actualGadgetName = gadgetName;
1267
- invocationId = `gadget_${++globalInvocationCounter}`;
1268
- }
1493
+ const { actualName: actualGadgetName, invocationId } = this.parseGadgetName(gadgetName);
1269
1494
  const contentStartIndex = metadataEndIndex + 1;
1270
1495
  let partEndIndex;
1271
1496
  let endMarkerLength = 0;
@@ -1275,23 +1500,29 @@ var init_parser = __esm({
1275
1500
  if (partEndIndex === -1) break;
1276
1501
  endMarkerLength = oldEndMarker.length;
1277
1502
  } else {
1278
- partEndIndex = contentStartIndex;
1503
+ const nextStartPos = this.buffer.indexOf(this.startPrefix, contentStartIndex);
1504
+ let validEndPos = -1;
1505
+ let searchPos = contentStartIndex;
1279
1506
  while (true) {
1280
- const endPos = this.buffer.indexOf(this.endPrefix, partEndIndex);
1281
- if (endPos === -1) {
1282
- partEndIndex = -1;
1283
- break;
1284
- }
1507
+ const endPos = this.buffer.indexOf(this.endPrefix, searchPos);
1508
+ if (endPos === -1) break;
1285
1509
  const afterEnd = this.buffer.substring(endPos + this.endPrefix.length);
1286
1510
  if (afterEnd.startsWith("\n") || afterEnd.startsWith("\r") || afterEnd.startsWith(this.startPrefix) || afterEnd.length === 0) {
1287
- partEndIndex = endPos;
1288
- endMarkerLength = this.endPrefix.length;
1511
+ validEndPos = endPos;
1289
1512
  break;
1290
1513
  } else {
1291
- partEndIndex = endPos + this.endPrefix.length;
1514
+ searchPos = endPos + this.endPrefix.length;
1292
1515
  }
1293
1516
  }
1294
- if (partEndIndex === -1) break;
1517
+ if (nextStartPos !== -1 && (validEndPos === -1 || nextStartPos < validEndPos)) {
1518
+ partEndIndex = nextStartPos;
1519
+ endMarkerLength = 0;
1520
+ } else if (validEndPos !== -1) {
1521
+ partEndIndex = validEndPos;
1522
+ endMarkerLength = this.endPrefix.length;
1523
+ } else {
1524
+ break;
1525
+ }
1295
1526
  }
1296
1527
  const parametersRaw = this.buffer.substring(contentStartIndex, partEndIndex).trim();
1297
1528
  const { parameters, parseError } = this.parseParameters(parametersRaw);
@@ -1314,8 +1545,35 @@ var init_parser = __esm({
1314
1545
  this.lastReportedTextLength = 0;
1315
1546
  }
1316
1547
  }
1317
- // Finalize parsing and return remaining text
1548
+ // Finalize parsing and return remaining text or incomplete gadgets
1318
1549
  *finalize() {
1550
+ const startIndex = this.buffer.indexOf(this.startPrefix, this.lastReportedTextLength);
1551
+ if (startIndex !== -1) {
1552
+ const textBefore = this.takeTextUntil(startIndex);
1553
+ if (textBefore !== void 0) {
1554
+ yield { type: "text", content: textBefore };
1555
+ }
1556
+ const metadataStartIndex = startIndex + this.startPrefix.length;
1557
+ const metadataEndIndex = this.buffer.indexOf("\n", metadataStartIndex);
1558
+ if (metadataEndIndex !== -1) {
1559
+ const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();
1560
+ const { actualName: actualGadgetName, invocationId } = this.parseGadgetName(gadgetName);
1561
+ const contentStartIndex = metadataEndIndex + 1;
1562
+ const parametersRaw = this.buffer.substring(contentStartIndex).trim();
1563
+ const { parameters, parseError } = this.parseParameters(parametersRaw);
1564
+ yield {
1565
+ type: "gadget_call",
1566
+ call: {
1567
+ gadgetName: actualGadgetName,
1568
+ invocationId,
1569
+ parametersYaml: parametersRaw,
1570
+ parameters,
1571
+ parseError
1572
+ }
1573
+ };
1574
+ return;
1575
+ }
1576
+ }
1319
1577
  const remainingText = this.takeTextUntil(this.buffer.length);
1320
1578
  if (remainingText !== void 0) {
1321
1579
  yield { type: "text", content: remainingText };
@@ -1796,11 +2054,11 @@ var init_agent = __esm({
1796
2054
  role: message.role,
1797
2055
  content: message.content
1798
2056
  }));
1799
- this.conversation = new ConversationManager(
1800
- baseMessages,
1801
- initialMessages,
1802
- this.parameterFormat
1803
- );
2057
+ this.conversation = new ConversationManager(baseMessages, initialMessages, {
2058
+ parameterFormat: this.parameterFormat,
2059
+ startPrefix: options.gadgetStartPrefix,
2060
+ endPrefix: options.gadgetEndPrefix
2061
+ });
1804
2062
  this.userPromptProvided = !!options.userPrompt;
1805
2063
  if (options.userPrompt) {
1806
2064
  this.conversation.addUserMessage(options.userPrompt);
@@ -5190,6 +5448,83 @@ function mergeDescriptions(schema, jsonSchema) {
5190
5448
 
5191
5449
  // src/gadgets/gadget.ts
5192
5450
  init_schema_validator();
5451
+ function formatYamlValue(value, indent = "") {
5452
+ if (typeof value === "string") {
5453
+ const lines = value.split("\n");
5454
+ if (lines.length === 1 && !value.includes(":") && !value.startsWith("-")) {
5455
+ return value;
5456
+ }
5457
+ const indentedLines = lines.map((line) => `${indent} ${line}`).join("\n");
5458
+ return `|
5459
+ ${indentedLines}`;
5460
+ }
5461
+ if (typeof value === "number" || typeof value === "boolean") {
5462
+ return String(value);
5463
+ }
5464
+ if (value === null || value === void 0) {
5465
+ return "null";
5466
+ }
5467
+ if (Array.isArray(value)) {
5468
+ if (value.length === 0) return "[]";
5469
+ const items = value.map((item) => `${indent}- ${formatYamlValue(item, indent + " ")}`);
5470
+ return "\n" + items.join("\n");
5471
+ }
5472
+ if (typeof value === "object") {
5473
+ const entries = Object.entries(value);
5474
+ if (entries.length === 0) return "{}";
5475
+ const lines = entries.map(([k, v]) => {
5476
+ const formattedValue = formatYamlValue(v, indent + " ");
5477
+ if (formattedValue.startsWith("\n") || formattedValue.startsWith("|")) {
5478
+ return `${indent}${k}: ${formattedValue}`;
5479
+ }
5480
+ return `${indent}${k}: ${formattedValue}`;
5481
+ });
5482
+ return "\n" + lines.join("\n");
5483
+ }
5484
+ return yaml2.dump(value).trimEnd();
5485
+ }
5486
+ function formatParamsAsYaml(params) {
5487
+ const lines = [];
5488
+ for (const [key, value] of Object.entries(params)) {
5489
+ const formattedValue = formatYamlValue(value, "");
5490
+ if (formattedValue.startsWith("\n")) {
5491
+ lines.push(`${key}:${formattedValue}`);
5492
+ } else {
5493
+ lines.push(`${key}: ${formattedValue}`);
5494
+ }
5495
+ }
5496
+ return lines.join("\n");
5497
+ }
5498
+ function formatTomlValue(value) {
5499
+ if (typeof value === "string") {
5500
+ if (value.includes("\n")) {
5501
+ return `"""
5502
+ ${value}
5503
+ """`;
5504
+ }
5505
+ return JSON.stringify(value);
5506
+ }
5507
+ if (typeof value === "number" || typeof value === "boolean") {
5508
+ return String(value);
5509
+ }
5510
+ if (value === null || value === void 0) {
5511
+ return '""';
5512
+ }
5513
+ if (Array.isArray(value)) {
5514
+ return JSON.stringify(value);
5515
+ }
5516
+ if (typeof value === "object") {
5517
+ return JSON.stringify(value);
5518
+ }
5519
+ return JSON.stringify(value);
5520
+ }
5521
+ function formatParamsAsToml(params) {
5522
+ const lines = [];
5523
+ for (const [key, value] of Object.entries(params)) {
5524
+ lines.push(`${key} = ${formatTomlValue(value)}`);
5525
+ }
5526
+ return lines.join("\n");
5527
+ }
5193
5528
  var BaseGadget = class {
5194
5529
  /**
5195
5530
  * The name of the gadget. Used for identification when LLM calls it.
@@ -5209,6 +5544,14 @@ var BaseGadget = class {
5209
5544
  * Set to 0 or undefined to disable timeout for this gadget.
5210
5545
  */
5211
5546
  timeoutMs;
5547
+ /**
5548
+ * Optional usage examples to help LLMs understand proper invocation.
5549
+ * Examples are rendered in getInstruction() alongside the schema.
5550
+ *
5551
+ * Note: Uses broader `unknown` type to allow typed examples from subclasses
5552
+ * while maintaining runtime compatibility.
5553
+ */
5554
+ examples;
5212
5555
  /**
5213
5556
  * Auto-generated instruction text for the LLM.
5214
5557
  * Combines name, description, and parameter schema into a formatted instruction.
@@ -5221,7 +5564,7 @@ var BaseGadget = class {
5221
5564
  * Generate instruction text for the LLM with format-specific schema.
5222
5565
  * Combines name, description, and parameter schema into a formatted instruction.
5223
5566
  *
5224
- * @param format - Format for the schema representation ('json' | 'yaml' | 'auto')
5567
+ * @param format - Format for the schema representation ('json' | 'yaml' | 'toml' | 'auto')
5225
5568
  * @returns Formatted instruction string
5226
5569
  */
5227
5570
  getInstruction(format = "json") {
@@ -5236,12 +5579,38 @@ var BaseGadget = class {
5236
5579
  if (format === "json" || format === "auto") {
5237
5580
  parts.push("\n\nInput Schema (JSON):");
5238
5581
  parts.push(JSON.stringify(jsonSchema, null, 2));
5582
+ } else if (format === "toml") {
5583
+ parts.push("\n\nInput Schema (TOML):");
5584
+ parts.push(JSON.stringify(jsonSchema, null, 2));
5239
5585
  } else {
5240
5586
  const yamlSchema = yaml2.dump(jsonSchema).trimEnd();
5241
5587
  parts.push("\n\nInput Schema (YAML):");
5242
5588
  parts.push(yamlSchema);
5243
5589
  }
5244
5590
  }
5591
+ if (this.examples && this.examples.length > 0) {
5592
+ parts.push("\n\nExamples:");
5593
+ this.examples.forEach((example, index) => {
5594
+ if (index > 0) {
5595
+ parts.push("");
5596
+ }
5597
+ if (example.comment) {
5598
+ parts.push(`# ${example.comment}`);
5599
+ }
5600
+ parts.push("Input:");
5601
+ if (format === "json" || format === "auto") {
5602
+ parts.push(JSON.stringify(example.params, null, 2));
5603
+ } else if (format === "toml") {
5604
+ parts.push(formatParamsAsToml(example.params));
5605
+ } else {
5606
+ parts.push(formatParamsAsYaml(example.params));
5607
+ }
5608
+ if (example.output !== void 0) {
5609
+ parts.push("Output:");
5610
+ parts.push(example.output);
5611
+ }
5612
+ });
5613
+ }
5245
5614
  return parts.join("\n");
5246
5615
  }
5247
5616
  };
@@ -5253,6 +5622,7 @@ function createGadget(config) {
5253
5622
  description = config.description;
5254
5623
  parameterSchema = config.schema;
5255
5624
  timeoutMs = config.timeoutMs;
5625
+ examples = config.examples;
5256
5626
  execute(params) {
5257
5627
  return config.execute(params);
5258
5628
  }
@@ -5273,6 +5643,7 @@ function Gadget(config) {
5273
5643
  parameterSchema = config.schema;
5274
5644
  name = config.name;
5275
5645
  timeoutMs = config.timeoutMs;
5646
+ examples = config.examples;
5276
5647
  /**
5277
5648
  * Type helper property for accessing inferred parameter type.
5278
5649
  * This is used in the execute method signature: `execute(params: this['params'])`