@probelabs/probe 0.6.0-rc162 → 0.6.0-rc163

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.
@@ -48,6 +48,7 @@ import {
48
48
  isJsonSchema,
49
49
  validateJsonResponse,
50
50
  createJsonCorrectionPrompt,
51
+ generateSchemaInstructions,
51
52
  isJsonSchemaDefinition,
52
53
  createSchemaDefinitionCorrectionPrompt,
53
54
  validateAndFixMermaidResponse
@@ -1455,11 +1456,18 @@ When troubleshooting:
1455
1456
 
1456
1457
  // Create user message with optional image support
1457
1458
  let userMessage = { role: 'user', content: message.trim() };
1458
-
1459
+
1460
+ // If schema is provided, prepend JSON format requirement to user message
1461
+ if (options.schema && !options._schemaFormatted) {
1462
+ const schemaInstructions = generateSchemaInstructions(options.schema, { debug: this.debug });
1463
+ userMessage.content = message.trim() + schemaInstructions;
1464
+ }
1465
+
1459
1466
  // If images are provided, use multi-modal message format
1460
1467
  if (images && images.length > 0) {
1468
+ const textContent = userMessage.content;
1461
1469
  userMessage.content = [
1462
- { type: 'text', text: message.trim() },
1470
+ { type: 'text', text: textContent },
1463
1471
  ...images.map(image => ({
1464
1472
  type: 'image',
1465
1473
  image: image
@@ -2004,7 +2012,7 @@ When troubleshooting:
2004
2012
  // Build appropriate reminder message based on whether schema is provided
2005
2013
  let reminderContent;
2006
2014
  if (options.schema) { // Apply for ANY schema, not just JSON schemas
2007
- // When schema is provided, AI must use attempt_completion to trigger schema formatting
2015
+ // When schema is provided, use the same instructions as initial message
2008
2016
  reminderContent = `Please use one of the available tools to help answer the question, or use attempt_completion if you have enough information to provide a final answer.
2009
2017
 
2010
2018
  Remember: Use proper XML format with BOTH opening and closing tags:
@@ -2012,15 +2020,7 @@ Remember: Use proper XML format with BOTH opening and closing tags:
2012
2020
  <tool_name>
2013
2021
  <parameter>value</parameter>
2014
2022
  </tool_name>
2015
-
2016
- IMPORTANT: A schema was provided for the final output format.
2017
-
2018
- You MUST use attempt_completion to provide your answer:
2019
- <attempt_completion>
2020
- [Your complete answer here - provide in natural language, it will be automatically formatted to match the schema]
2021
- </attempt_completion>
2022
-
2023
- Your response will be automatically formatted to JSON. You can provide your answer in natural language or as JSON - either will work.`;
2023
+ ` + generateSchemaInstructions(options.schema, { debug: this.debug }).trim();
2024
2024
  } else {
2025
2025
  // Standard reminder without schema
2026
2026
  reminderContent = `Please use one of the available tools to help answer the question, or use attempt_completion if you have enough information to provide a final answer.
@@ -54264,6 +54264,8 @@ __export(schemaUtils_exports, {
54264
54264
  createSchemaDefinitionCorrectionPrompt: () => createSchemaDefinitionCorrectionPrompt,
54265
54265
  decodeHtmlEntities: () => decodeHtmlEntities,
54266
54266
  extractMermaidFromMarkdown: () => extractMermaidFromMarkdown,
54267
+ generateExampleFromSchema: () => generateExampleFromSchema,
54268
+ generateSchemaInstructions: () => generateSchemaInstructions,
54267
54269
  isJsonSchema: () => isJsonSchema,
54268
54270
  isJsonSchemaDefinition: () => isJsonSchemaDefinition,
54269
54271
  isMermaidSchema: () => isMermaidSchema,
@@ -54276,6 +54278,63 @@ __export(schemaUtils_exports, {
54276
54278
  validateMermaidResponse: () => validateMermaidResponse,
54277
54279
  validateXmlResponse: () => validateXmlResponse
54278
54280
  });
54281
+ function generateExampleFromSchema(schema, options = {}) {
54282
+ const { debug = false } = options;
54283
+ try {
54284
+ const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
54285
+ if (parsedSchema.type !== "object" || !parsedSchema.properties) {
54286
+ return null;
54287
+ }
54288
+ const exampleObj = {};
54289
+ for (const [key, value] of Object.entries(parsedSchema.properties)) {
54290
+ if (value.type === "boolean") {
54291
+ exampleObj[key] = false;
54292
+ } else if (value.type === "number") {
54293
+ exampleObj[key] = 0;
54294
+ } else if (value.type === "string") {
54295
+ exampleObj[key] = value.description || "your answer here";
54296
+ } else if (value.type === "array") {
54297
+ exampleObj[key] = [];
54298
+ } else {
54299
+ exampleObj[key] = {};
54300
+ }
54301
+ }
54302
+ return exampleObj;
54303
+ } catch (e) {
54304
+ if (debug) {
54305
+ console.error("[DEBUG] generateExampleFromSchema: Failed to parse schema:", e.message);
54306
+ }
54307
+ return null;
54308
+ }
54309
+ }
54310
+ function generateSchemaInstructions(schema, options = {}) {
54311
+ const { debug = false } = options;
54312
+ let instructions = "\n\nIMPORTANT: When you provide your final answer using attempt_completion, you MUST format it as valid JSON matching this schema:\n\n";
54313
+ try {
54314
+ const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
54315
+ instructions += `${JSON.stringify(parsedSchema, null, 2)}
54316
+
54317
+ `;
54318
+ const exampleObj = generateExampleFromSchema(parsedSchema, { debug });
54319
+ if (exampleObj) {
54320
+ instructions += `Example:
54321
+ <attempt_completion>
54322
+ ${JSON.stringify(exampleObj, null, 2)}
54323
+ </attempt_completion>
54324
+
54325
+ `;
54326
+ }
54327
+ } catch (e) {
54328
+ if (debug) {
54329
+ console.error("[DEBUG] generateSchemaInstructions: Failed to parse schema:", e.message);
54330
+ }
54331
+ instructions += `${schema}
54332
+
54333
+ `;
54334
+ }
54335
+ instructions += "Your response inside attempt_completion must be ONLY valid JSON - no plain text, no explanations, no markdown.";
54336
+ return instructions;
54337
+ }
54279
54338
  function enforceNoAdditionalProperties(schema) {
54280
54339
  if (!schema || typeof schema !== "object") {
54281
54340
  return schema;
@@ -58305,9 +58364,14 @@ You are working with a repository located at: ${searchDirectory}
58305
58364
  });
58306
58365
  const systemMessage = await this.getSystemMessage();
58307
58366
  let userMessage = { role: "user", content: message.trim() };
58367
+ if (options.schema && !options._schemaFormatted) {
58368
+ const schemaInstructions = generateSchemaInstructions(options.schema, { debug: this.debug });
58369
+ userMessage.content = message.trim() + schemaInstructions;
58370
+ }
58308
58371
  if (images && images.length > 0) {
58372
+ const textContent = userMessage.content;
58309
58373
  userMessage.content = [
58310
- { type: "text", text: message.trim() },
58374
+ { type: "text", text: textContent },
58311
58375
  ...images.map((image) => ({
58312
58376
  type: "image",
58313
58377
  image
@@ -58736,15 +58800,7 @@ Remember: Use proper XML format with BOTH opening and closing tags:
58736
58800
  <tool_name>
58737
58801
  <parameter>value</parameter>
58738
58802
  </tool_name>
58739
-
58740
- IMPORTANT: A schema was provided for the final output format.
58741
-
58742
- You MUST use attempt_completion to provide your answer:
58743
- <attempt_completion>
58744
- [Your complete answer here - provide in natural language, it will be automatically formatted to match the schema]
58745
- </attempt_completion>
58746
-
58747
- Your response will be automatically formatted to JSON. You can provide your answer in natural language or as JSON - either will work.`;
58803
+ ` + generateSchemaInstructions(options.schema, { debug: this.debug }).trim();
58748
58804
  } else {
58749
58805
  reminderContent = `Please use one of the available tools to help answer the question, or use attempt_completion if you have enough information to provide a final answer.
58750
58806
 
@@ -7,6 +7,80 @@ import { createMessagePreview } from '../tools/common.js';
7
7
  import { validate, fixText, extractMermaidBlocks } from '@probelabs/maid';
8
8
  import Ajv from 'ajv';
9
9
 
10
+ /**
11
+ * Generate an example JSON object from a JSON schema
12
+ * @param {Object|string} schema - JSON schema object or string
13
+ * @param {Object} options - Options for generation
14
+ * @param {boolean} [options.debug=false] - Enable debug logging
15
+ * @returns {Object|null} - Example object, or null if schema cannot be processed
16
+ */
17
+ export function generateExampleFromSchema(schema, options = {}) {
18
+ const { debug = false } = options;
19
+
20
+ try {
21
+ const parsedSchema = typeof schema === 'string' ? JSON.parse(schema) : schema;
22
+
23
+ if (parsedSchema.type !== 'object' || !parsedSchema.properties) {
24
+ return null;
25
+ }
26
+
27
+ const exampleObj = {};
28
+ for (const [key, value] of Object.entries(parsedSchema.properties)) {
29
+ if (value.type === 'boolean') {
30
+ exampleObj[key] = false;
31
+ } else if (value.type === 'number') {
32
+ exampleObj[key] = 0;
33
+ } else if (value.type === 'string') {
34
+ exampleObj[key] = value.description || 'your answer here';
35
+ } else if (value.type === 'array') {
36
+ exampleObj[key] = [];
37
+ } else {
38
+ exampleObj[key] = {};
39
+ }
40
+ }
41
+
42
+ return exampleObj;
43
+ } catch (e) {
44
+ if (debug) {
45
+ console.error('[DEBUG] generateExampleFromSchema: Failed to parse schema:', e.message);
46
+ }
47
+ return null;
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Generate schema instructions for AI to follow
53
+ * @param {Object|string} schema - JSON schema object or string
54
+ * @param {Object} options - Options for generation
55
+ * @param {boolean} [options.debug=false] - Enable debug logging
56
+ * @returns {string} - Formatted schema instructions
57
+ */
58
+ export function generateSchemaInstructions(schema, options = {}) {
59
+ const { debug = false } = options;
60
+
61
+ let instructions = '\n\nIMPORTANT: When you provide your final answer using attempt_completion, you MUST format it as valid JSON matching this schema:\n\n';
62
+
63
+ try {
64
+ const parsedSchema = typeof schema === 'string' ? JSON.parse(schema) : schema;
65
+ instructions += `${JSON.stringify(parsedSchema, null, 2)}\n\n`;
66
+
67
+ // Generate example using helper function
68
+ const exampleObj = generateExampleFromSchema(parsedSchema, { debug });
69
+ if (exampleObj) {
70
+ instructions += `Example:\n<attempt_completion>\n${JSON.stringify(exampleObj, null, 2)}\n</attempt_completion>\n\n`;
71
+ }
72
+ } catch (e) {
73
+ if (debug) {
74
+ console.error('[DEBUG] generateSchemaInstructions: Failed to parse schema:', e.message);
75
+ }
76
+ instructions += `${schema}\n\n`;
77
+ }
78
+
79
+ instructions += 'Your response inside attempt_completion must be ONLY valid JSON - no plain text, no explanations, no markdown.';
80
+
81
+ return instructions;
82
+ }
83
+
10
84
  /**
11
85
  * Recursively apply additionalProperties: false to all object schemas
12
86
  * This ensures strict validation at all nesting levels
@@ -79944,6 +79944,8 @@ __export(schemaUtils_exports, {
79944
79944
  createSchemaDefinitionCorrectionPrompt: () => createSchemaDefinitionCorrectionPrompt,
79945
79945
  decodeHtmlEntities: () => decodeHtmlEntities,
79946
79946
  extractMermaidFromMarkdown: () => extractMermaidFromMarkdown,
79947
+ generateExampleFromSchema: () => generateExampleFromSchema,
79948
+ generateSchemaInstructions: () => generateSchemaInstructions,
79947
79949
  isJsonSchema: () => isJsonSchema,
79948
79950
  isJsonSchemaDefinition: () => isJsonSchemaDefinition,
79949
79951
  isMermaidSchema: () => isMermaidSchema,
@@ -79956,6 +79958,63 @@ __export(schemaUtils_exports, {
79956
79958
  validateMermaidResponse: () => validateMermaidResponse,
79957
79959
  validateXmlResponse: () => validateXmlResponse
79958
79960
  });
79961
+ function generateExampleFromSchema(schema, options = {}) {
79962
+ const { debug = false } = options;
79963
+ try {
79964
+ const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
79965
+ if (parsedSchema.type !== "object" || !parsedSchema.properties) {
79966
+ return null;
79967
+ }
79968
+ const exampleObj = {};
79969
+ for (const [key, value] of Object.entries(parsedSchema.properties)) {
79970
+ if (value.type === "boolean") {
79971
+ exampleObj[key] = false;
79972
+ } else if (value.type === "number") {
79973
+ exampleObj[key] = 0;
79974
+ } else if (value.type === "string") {
79975
+ exampleObj[key] = value.description || "your answer here";
79976
+ } else if (value.type === "array") {
79977
+ exampleObj[key] = [];
79978
+ } else {
79979
+ exampleObj[key] = {};
79980
+ }
79981
+ }
79982
+ return exampleObj;
79983
+ } catch (e3) {
79984
+ if (debug) {
79985
+ console.error("[DEBUG] generateExampleFromSchema: Failed to parse schema:", e3.message);
79986
+ }
79987
+ return null;
79988
+ }
79989
+ }
79990
+ function generateSchemaInstructions(schema, options = {}) {
79991
+ const { debug = false } = options;
79992
+ let instructions = "\n\nIMPORTANT: When you provide your final answer using attempt_completion, you MUST format it as valid JSON matching this schema:\n\n";
79993
+ try {
79994
+ const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
79995
+ instructions += `${JSON.stringify(parsedSchema, null, 2)}
79996
+
79997
+ `;
79998
+ const exampleObj = generateExampleFromSchema(parsedSchema, { debug });
79999
+ if (exampleObj) {
80000
+ instructions += `Example:
80001
+ <attempt_completion>
80002
+ ${JSON.stringify(exampleObj, null, 2)}
80003
+ </attempt_completion>
80004
+
80005
+ `;
80006
+ }
80007
+ } catch (e3) {
80008
+ if (debug) {
80009
+ console.error("[DEBUG] generateSchemaInstructions: Failed to parse schema:", e3.message);
80010
+ }
80011
+ instructions += `${schema}
80012
+
80013
+ `;
80014
+ }
80015
+ instructions += "Your response inside attempt_completion must be ONLY valid JSON - no plain text, no explanations, no markdown.";
80016
+ return instructions;
80017
+ }
79959
80018
  function enforceNoAdditionalProperties(schema) {
79960
80019
  if (!schema || typeof schema !== "object") {
79961
80020
  return schema;
@@ -83985,9 +84044,14 @@ You are working with a repository located at: ${searchDirectory}
83985
84044
  });
83986
84045
  const systemMessage = await this.getSystemMessage();
83987
84046
  let userMessage = { role: "user", content: message.trim() };
84047
+ if (options.schema && !options._schemaFormatted) {
84048
+ const schemaInstructions = generateSchemaInstructions(options.schema, { debug: this.debug });
84049
+ userMessage.content = message.trim() + schemaInstructions;
84050
+ }
83988
84051
  if (images && images.length > 0) {
84052
+ const textContent = userMessage.content;
83989
84053
  userMessage.content = [
83990
- { type: "text", text: message.trim() },
84054
+ { type: "text", text: textContent },
83991
84055
  ...images.map((image) => ({
83992
84056
  type: "image",
83993
84057
  image
@@ -84416,15 +84480,7 @@ Remember: Use proper XML format with BOTH opening and closing tags:
84416
84480
  <tool_name>
84417
84481
  <parameter>value</parameter>
84418
84482
  </tool_name>
84419
-
84420
- IMPORTANT: A schema was provided for the final output format.
84421
-
84422
- You MUST use attempt_completion to provide your answer:
84423
- <attempt_completion>
84424
- [Your complete answer here - provide in natural language, it will be automatically formatted to match the schema]
84425
- </attempt_completion>
84426
-
84427
- Your response will be automatically formatted to JSON. You can provide your answer in natural language or as JSON - either will work.`;
84483
+ ` + generateSchemaInstructions(options.schema, { debug: this.debug }).trim();
84428
84484
  } else {
84429
84485
  reminderContent = `Please use one of the available tools to help answer the question, or use attempt_completion if you have enough information to provide a final answer.
84430
84486
 
package/cjs/index.cjs CHANGED
@@ -77686,6 +77686,8 @@ __export(schemaUtils_exports, {
77686
77686
  createSchemaDefinitionCorrectionPrompt: () => createSchemaDefinitionCorrectionPrompt,
77687
77687
  decodeHtmlEntities: () => decodeHtmlEntities,
77688
77688
  extractMermaidFromMarkdown: () => extractMermaidFromMarkdown,
77689
+ generateExampleFromSchema: () => generateExampleFromSchema,
77690
+ generateSchemaInstructions: () => generateSchemaInstructions,
77689
77691
  isJsonSchema: () => isJsonSchema,
77690
77692
  isJsonSchemaDefinition: () => isJsonSchemaDefinition,
77691
77693
  isMermaidSchema: () => isMermaidSchema,
@@ -77698,6 +77700,63 @@ __export(schemaUtils_exports, {
77698
77700
  validateMermaidResponse: () => validateMermaidResponse,
77699
77701
  validateXmlResponse: () => validateXmlResponse
77700
77702
  });
77703
+ function generateExampleFromSchema(schema, options = {}) {
77704
+ const { debug = false } = options;
77705
+ try {
77706
+ const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
77707
+ if (parsedSchema.type !== "object" || !parsedSchema.properties) {
77708
+ return null;
77709
+ }
77710
+ const exampleObj = {};
77711
+ for (const [key, value] of Object.entries(parsedSchema.properties)) {
77712
+ if (value.type === "boolean") {
77713
+ exampleObj[key] = false;
77714
+ } else if (value.type === "number") {
77715
+ exampleObj[key] = 0;
77716
+ } else if (value.type === "string") {
77717
+ exampleObj[key] = value.description || "your answer here";
77718
+ } else if (value.type === "array") {
77719
+ exampleObj[key] = [];
77720
+ } else {
77721
+ exampleObj[key] = {};
77722
+ }
77723
+ }
77724
+ return exampleObj;
77725
+ } catch (e3) {
77726
+ if (debug) {
77727
+ console.error("[DEBUG] generateExampleFromSchema: Failed to parse schema:", e3.message);
77728
+ }
77729
+ return null;
77730
+ }
77731
+ }
77732
+ function generateSchemaInstructions(schema, options = {}) {
77733
+ const { debug = false } = options;
77734
+ let instructions = "\n\nIMPORTANT: When you provide your final answer using attempt_completion, you MUST format it as valid JSON matching this schema:\n\n";
77735
+ try {
77736
+ const parsedSchema = typeof schema === "string" ? JSON.parse(schema) : schema;
77737
+ instructions += `${JSON.stringify(parsedSchema, null, 2)}
77738
+
77739
+ `;
77740
+ const exampleObj = generateExampleFromSchema(parsedSchema, { debug });
77741
+ if (exampleObj) {
77742
+ instructions += `Example:
77743
+ <attempt_completion>
77744
+ ${JSON.stringify(exampleObj, null, 2)}
77745
+ </attempt_completion>
77746
+
77747
+ `;
77748
+ }
77749
+ } catch (e3) {
77750
+ if (debug) {
77751
+ console.error("[DEBUG] generateSchemaInstructions: Failed to parse schema:", e3.message);
77752
+ }
77753
+ instructions += `${schema}
77754
+
77755
+ `;
77756
+ }
77757
+ instructions += "Your response inside attempt_completion must be ONLY valid JSON - no plain text, no explanations, no markdown.";
77758
+ return instructions;
77759
+ }
77701
77760
  function enforceNoAdditionalProperties(schema) {
77702
77761
  if (!schema || typeof schema !== "object") {
77703
77762
  return schema;
@@ -81727,9 +81786,14 @@ You are working with a repository located at: ${searchDirectory}
81727
81786
  });
81728
81787
  const systemMessage = await this.getSystemMessage();
81729
81788
  let userMessage = { role: "user", content: message.trim() };
81789
+ if (options.schema && !options._schemaFormatted) {
81790
+ const schemaInstructions = generateSchemaInstructions(options.schema, { debug: this.debug });
81791
+ userMessage.content = message.trim() + schemaInstructions;
81792
+ }
81730
81793
  if (images && images.length > 0) {
81794
+ const textContent = userMessage.content;
81731
81795
  userMessage.content = [
81732
- { type: "text", text: message.trim() },
81796
+ { type: "text", text: textContent },
81733
81797
  ...images.map((image) => ({
81734
81798
  type: "image",
81735
81799
  image
@@ -82158,15 +82222,7 @@ Remember: Use proper XML format with BOTH opening and closing tags:
82158
82222
  <tool_name>
82159
82223
  <parameter>value</parameter>
82160
82224
  </tool_name>
82161
-
82162
- IMPORTANT: A schema was provided for the final output format.
82163
-
82164
- You MUST use attempt_completion to provide your answer:
82165
- <attempt_completion>
82166
- [Your complete answer here - provide in natural language, it will be automatically formatted to match the schema]
82167
- </attempt_completion>
82168
-
82169
- Your response will be automatically formatted to JSON. You can provide your answer in natural language or as JSON - either will work.`;
82225
+ ` + generateSchemaInstructions(options.schema, { debug: this.debug }).trim();
82170
82226
  } else {
82171
82227
  reminderContent = `Please use one of the available tools to help answer the question, or use attempt_completion if you have enough information to provide a final answer.
82172
82228
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@probelabs/probe",
3
- "version": "0.6.0-rc162",
3
+ "version": "0.6.0-rc163",
4
4
  "description": "Node.js wrapper for the probe code search tool",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
@@ -48,6 +48,7 @@ import {
48
48
  isJsonSchema,
49
49
  validateJsonResponse,
50
50
  createJsonCorrectionPrompt,
51
+ generateSchemaInstructions,
51
52
  isJsonSchemaDefinition,
52
53
  createSchemaDefinitionCorrectionPrompt,
53
54
  validateAndFixMermaidResponse
@@ -1455,11 +1456,18 @@ When troubleshooting:
1455
1456
 
1456
1457
  // Create user message with optional image support
1457
1458
  let userMessage = { role: 'user', content: message.trim() };
1458
-
1459
+
1460
+ // If schema is provided, prepend JSON format requirement to user message
1461
+ if (options.schema && !options._schemaFormatted) {
1462
+ const schemaInstructions = generateSchemaInstructions(options.schema, { debug: this.debug });
1463
+ userMessage.content = message.trim() + schemaInstructions;
1464
+ }
1465
+
1459
1466
  // If images are provided, use multi-modal message format
1460
1467
  if (images && images.length > 0) {
1468
+ const textContent = userMessage.content;
1461
1469
  userMessage.content = [
1462
- { type: 'text', text: message.trim() },
1470
+ { type: 'text', text: textContent },
1463
1471
  ...images.map(image => ({
1464
1472
  type: 'image',
1465
1473
  image: image
@@ -2004,7 +2012,7 @@ When troubleshooting:
2004
2012
  // Build appropriate reminder message based on whether schema is provided
2005
2013
  let reminderContent;
2006
2014
  if (options.schema) { // Apply for ANY schema, not just JSON schemas
2007
- // When schema is provided, AI must use attempt_completion to trigger schema formatting
2015
+ // When schema is provided, use the same instructions as initial message
2008
2016
  reminderContent = `Please use one of the available tools to help answer the question, or use attempt_completion if you have enough information to provide a final answer.
2009
2017
 
2010
2018
  Remember: Use proper XML format with BOTH opening and closing tags:
@@ -2012,15 +2020,7 @@ Remember: Use proper XML format with BOTH opening and closing tags:
2012
2020
  <tool_name>
2013
2021
  <parameter>value</parameter>
2014
2022
  </tool_name>
2015
-
2016
- IMPORTANT: A schema was provided for the final output format.
2017
-
2018
- You MUST use attempt_completion to provide your answer:
2019
- <attempt_completion>
2020
- [Your complete answer here - provide in natural language, it will be automatically formatted to match the schema]
2021
- </attempt_completion>
2022
-
2023
- Your response will be automatically formatted to JSON. You can provide your answer in natural language or as JSON - either will work.`;
2023
+ ` + generateSchemaInstructions(options.schema, { debug: this.debug }).trim();
2024
2024
  } else {
2025
2025
  // Standard reminder without schema
2026
2026
  reminderContent = `Please use one of the available tools to help answer the question, or use attempt_completion if you have enough information to provide a final answer.
@@ -7,6 +7,80 @@ import { createMessagePreview } from '../tools/common.js';
7
7
  import { validate, fixText, extractMermaidBlocks } from '@probelabs/maid';
8
8
  import Ajv from 'ajv';
9
9
 
10
+ /**
11
+ * Generate an example JSON object from a JSON schema
12
+ * @param {Object|string} schema - JSON schema object or string
13
+ * @param {Object} options - Options for generation
14
+ * @param {boolean} [options.debug=false] - Enable debug logging
15
+ * @returns {Object|null} - Example object, or null if schema cannot be processed
16
+ */
17
+ export function generateExampleFromSchema(schema, options = {}) {
18
+ const { debug = false } = options;
19
+
20
+ try {
21
+ const parsedSchema = typeof schema === 'string' ? JSON.parse(schema) : schema;
22
+
23
+ if (parsedSchema.type !== 'object' || !parsedSchema.properties) {
24
+ return null;
25
+ }
26
+
27
+ const exampleObj = {};
28
+ for (const [key, value] of Object.entries(parsedSchema.properties)) {
29
+ if (value.type === 'boolean') {
30
+ exampleObj[key] = false;
31
+ } else if (value.type === 'number') {
32
+ exampleObj[key] = 0;
33
+ } else if (value.type === 'string') {
34
+ exampleObj[key] = value.description || 'your answer here';
35
+ } else if (value.type === 'array') {
36
+ exampleObj[key] = [];
37
+ } else {
38
+ exampleObj[key] = {};
39
+ }
40
+ }
41
+
42
+ return exampleObj;
43
+ } catch (e) {
44
+ if (debug) {
45
+ console.error('[DEBUG] generateExampleFromSchema: Failed to parse schema:', e.message);
46
+ }
47
+ return null;
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Generate schema instructions for AI to follow
53
+ * @param {Object|string} schema - JSON schema object or string
54
+ * @param {Object} options - Options for generation
55
+ * @param {boolean} [options.debug=false] - Enable debug logging
56
+ * @returns {string} - Formatted schema instructions
57
+ */
58
+ export function generateSchemaInstructions(schema, options = {}) {
59
+ const { debug = false } = options;
60
+
61
+ let instructions = '\n\nIMPORTANT: When you provide your final answer using attempt_completion, you MUST format it as valid JSON matching this schema:\n\n';
62
+
63
+ try {
64
+ const parsedSchema = typeof schema === 'string' ? JSON.parse(schema) : schema;
65
+ instructions += `${JSON.stringify(parsedSchema, null, 2)}\n\n`;
66
+
67
+ // Generate example using helper function
68
+ const exampleObj = generateExampleFromSchema(parsedSchema, { debug });
69
+ if (exampleObj) {
70
+ instructions += `Example:\n<attempt_completion>\n${JSON.stringify(exampleObj, null, 2)}\n</attempt_completion>\n\n`;
71
+ }
72
+ } catch (e) {
73
+ if (debug) {
74
+ console.error('[DEBUG] generateSchemaInstructions: Failed to parse schema:', e.message);
75
+ }
76
+ instructions += `${schema}\n\n`;
77
+ }
78
+
79
+ instructions += 'Your response inside attempt_completion must be ONLY valid JSON - no plain text, no explanations, no markdown.';
80
+
81
+ return instructions;
82
+ }
83
+
10
84
  /**
11
85
  * Recursively apply additionalProperties: false to all object schemas
12
86
  * This ensures strict validation at all nesting levels