@riotprompt/riotprompt 0.0.13 → 0.0.14
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/README.md +18 -15
- package/dist/chat.d.ts +2 -0
- package/dist/chat.js +2 -0
- package/dist/chat.js.map +1 -1
- package/dist/cli.cjs +118 -20
- package/dist/execution/anthropic.js +27 -3
- package/dist/execution/anthropic.js.map +1 -1
- package/dist/execution/gemini.js +45 -1
- package/dist/execution/gemini.js.map +1 -1
- package/dist/execution/openai.js +2 -1
- package/dist/execution/openai.js.map +1 -1
- package/dist/formatter.js +42 -14
- package/dist/formatter.js.map +1 -1
- package/dist/prompt.d.ts +19 -1
- package/dist/prompt.js +11 -2
- package/dist/prompt.js.map +1 -1
- package/dist/recipes.d.ts +108 -0
- package/dist/recipes.js +195 -30
- package/dist/recipes.js.map +1 -1
- package/dist/riotprompt.cjs +323 -51
- package/dist/riotprompt.cjs.map +1 -1
- package/package.json +3 -2
package/dist/riotprompt.cjs
CHANGED
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
5
5
|
const zod = require('zod');
|
|
6
6
|
const fs = require('fs/promises');
|
|
7
7
|
const path = require('path');
|
|
8
|
+
const zodToJsonSchema = require('zod-to-json-schema');
|
|
8
9
|
const crypto = require('crypto');
|
|
9
10
|
const tiktoken = require('tiktoken');
|
|
10
11
|
const OpenAI = require('openai');
|
|
@@ -236,12 +237,21 @@ const create$7 = (text, options = {})=>{
|
|
|
236
237
|
return create$c(text, weightedOptions);
|
|
237
238
|
};
|
|
238
239
|
|
|
239
|
-
const create$6 = ({ persona, instructions, contents, contexts })=>{
|
|
240
|
+
const create$6 = ({ persona, instructions, contents, contexts, constraints, tone, examples, reasoning, responseFormat, recap, safeguards, schema, validator })=>{
|
|
240
241
|
return {
|
|
241
242
|
persona,
|
|
242
243
|
instructions,
|
|
243
244
|
contents,
|
|
244
|
-
contexts
|
|
245
|
+
contexts,
|
|
246
|
+
constraints,
|
|
247
|
+
tone,
|
|
248
|
+
examples,
|
|
249
|
+
reasoning,
|
|
250
|
+
responseFormat,
|
|
251
|
+
recap,
|
|
252
|
+
safeguards,
|
|
253
|
+
schema,
|
|
254
|
+
validator
|
|
245
255
|
};
|
|
246
256
|
};
|
|
247
257
|
|
|
@@ -519,6 +529,8 @@ const createRequest = (model)=>{
|
|
|
519
529
|
return {
|
|
520
530
|
model,
|
|
521
531
|
messages,
|
|
532
|
+
responseFormat: undefined,
|
|
533
|
+
validator: undefined,
|
|
522
534
|
addMessage: (message)=>{
|
|
523
535
|
messages.push(message);
|
|
524
536
|
}
|
|
@@ -671,24 +683,52 @@ const create$5 = (formatterOptions)=>{
|
|
|
671
683
|
const formatPrompt = (model, prompt)=>{
|
|
672
684
|
logger.silly('Formatting prompt');
|
|
673
685
|
const chatRequest = createRequest(model);
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
686
|
+
// --- System/Role Message Construction ---
|
|
687
|
+
// Collect sections that belong in the system/developer prompt (Persona, Tone, Constraints, etc.)
|
|
688
|
+
const systemSections = [];
|
|
689
|
+
if (prompt.persona) systemSections.push(prompt.persona);
|
|
690
|
+
if (prompt.tone) systemSections.push(prompt.tone);
|
|
691
|
+
if (prompt.constraints) systemSections.push(prompt.constraints);
|
|
692
|
+
if (prompt.safeguards) systemSections.push(prompt.safeguards);
|
|
693
|
+
if (prompt.responseFormat) systemSections.push(prompt.responseFormat);
|
|
694
|
+
if (systemSections.length > 0) {
|
|
695
|
+
// Combine all system sections into one system message content
|
|
696
|
+
const systemContent = systemSections.map((section)=>formatSection(section)).join('\n\n');
|
|
697
|
+
chatRequest.addMessage({
|
|
698
|
+
role: getPersonaRole(model),
|
|
699
|
+
content: systemContent
|
|
679
700
|
});
|
|
680
701
|
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
702
|
+
// --- User/Task Message Construction ---
|
|
703
|
+
// Logical flow: Context -> Examples -> Instructions -> Content -> Reasoning -> Recap
|
|
704
|
+
// This structure guides the model through the context and examples before presenting the core task
|
|
705
|
+
const userSections = [
|
|
706
|
+
prompt.contexts,
|
|
707
|
+
prompt.examples,
|
|
708
|
+
prompt.instructions,
|
|
709
|
+
prompt.contents,
|
|
710
|
+
prompt.reasoning,
|
|
711
|
+
prompt.recap
|
|
712
|
+
];
|
|
713
|
+
let formattedUserContent = "";
|
|
714
|
+
for (const section of userSections){
|
|
715
|
+
if (section) {
|
|
716
|
+
formattedUserContent += formatSection(section) + '\n\n';
|
|
717
|
+
}
|
|
684
718
|
}
|
|
685
|
-
if
|
|
686
|
-
|
|
719
|
+
// Ensure we always have a user message, or if we have content to send
|
|
720
|
+
if (formattedUserContent.trim().length > 0 || systemSections.length === 0) {
|
|
721
|
+
chatRequest.addMessage({
|
|
722
|
+
role: "user",
|
|
723
|
+
content: formattedUserContent.trim() || " "
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
if (prompt.schema) {
|
|
727
|
+
chatRequest.responseFormat = prompt.schema;
|
|
728
|
+
}
|
|
729
|
+
if (prompt.validator) {
|
|
730
|
+
chatRequest.validator = prompt.validator;
|
|
687
731
|
}
|
|
688
|
-
chatRequest.addMessage({
|
|
689
|
-
role: "user",
|
|
690
|
-
content: formattedAreas
|
|
691
|
-
});
|
|
692
732
|
return chatRequest;
|
|
693
733
|
};
|
|
694
734
|
return {
|
|
@@ -4891,6 +4931,15 @@ const RecipeConfigSchema = zod.z.object({
|
|
|
4891
4931
|
instructions: zod.z.array(ContentItemSchema).optional().default([]),
|
|
4892
4932
|
content: zod.z.array(ContentItemSchema).optional().default([]),
|
|
4893
4933
|
context: zod.z.array(ContentItemSchema).optional().default([]),
|
|
4934
|
+
// Advanced prompting sections
|
|
4935
|
+
constraints: zod.z.array(ContentItemSchema).optional().default([]),
|
|
4936
|
+
tone: zod.z.array(ContentItemSchema).optional().default([]),
|
|
4937
|
+
examples: zod.z.array(ContentItemSchema).optional().default([]),
|
|
4938
|
+
reasoning: zod.z.array(ContentItemSchema).optional().default([]),
|
|
4939
|
+
responseFormat: zod.z.array(ContentItemSchema).optional().default([]),
|
|
4940
|
+
recap: zod.z.array(ContentItemSchema).optional().default([]),
|
|
4941
|
+
safeguards: zod.z.array(ContentItemSchema).optional().default([]),
|
|
4942
|
+
schema: zod.z.any().optional(),
|
|
4894
4943
|
// Templates and inheritance
|
|
4895
4944
|
extends: zod.z.string().optional(),
|
|
4896
4945
|
template: zod.z.string().optional(),
|
|
@@ -5056,6 +5105,13 @@ const cook = async (config)=>{
|
|
|
5056
5105
|
instructions: [],
|
|
5057
5106
|
content: [],
|
|
5058
5107
|
context: [],
|
|
5108
|
+
constraints: [],
|
|
5109
|
+
tone: [],
|
|
5110
|
+
examples: [],
|
|
5111
|
+
reasoning: [],
|
|
5112
|
+
responseFormat: [],
|
|
5113
|
+
recap: [],
|
|
5114
|
+
safeguards: [],
|
|
5059
5115
|
...config
|
|
5060
5116
|
});
|
|
5061
5117
|
// Handle template inheritance
|
|
@@ -5079,7 +5135,36 @@ const cook = async (config)=>{
|
|
|
5079
5135
|
context: [
|
|
5080
5136
|
...template.context || [],
|
|
5081
5137
|
...validatedConfig.context || []
|
|
5082
|
-
]
|
|
5138
|
+
],
|
|
5139
|
+
constraints: [
|
|
5140
|
+
...template.constraints || [],
|
|
5141
|
+
...validatedConfig.constraints || []
|
|
5142
|
+
],
|
|
5143
|
+
tone: [
|
|
5144
|
+
...template.tone || [],
|
|
5145
|
+
...validatedConfig.tone || []
|
|
5146
|
+
],
|
|
5147
|
+
examples: [
|
|
5148
|
+
...template.examples || [],
|
|
5149
|
+
...validatedConfig.examples || []
|
|
5150
|
+
],
|
|
5151
|
+
reasoning: [
|
|
5152
|
+
...template.reasoning || [],
|
|
5153
|
+
...validatedConfig.reasoning || []
|
|
5154
|
+
],
|
|
5155
|
+
responseFormat: [
|
|
5156
|
+
...template.responseFormat || [],
|
|
5157
|
+
...validatedConfig.responseFormat || []
|
|
5158
|
+
],
|
|
5159
|
+
recap: [
|
|
5160
|
+
...template.recap || [],
|
|
5161
|
+
...validatedConfig.recap || []
|
|
5162
|
+
],
|
|
5163
|
+
safeguards: [
|
|
5164
|
+
...template.safeguards || [],
|
|
5165
|
+
...validatedConfig.safeguards || []
|
|
5166
|
+
],
|
|
5167
|
+
schema: validatedConfig.schema || template.schema
|
|
5083
5168
|
};
|
|
5084
5169
|
}
|
|
5085
5170
|
}
|
|
@@ -5111,6 +5196,39 @@ const cook = async (config)=>{
|
|
|
5111
5196
|
const contextSection = create$8({
|
|
5112
5197
|
title: "Context"
|
|
5113
5198
|
});
|
|
5199
|
+
// Advanced sections
|
|
5200
|
+
const constraintSection = create$8({
|
|
5201
|
+
title: "Constraints"
|
|
5202
|
+
});
|
|
5203
|
+
const toneSection = create$8({
|
|
5204
|
+
title: "Tone"
|
|
5205
|
+
});
|
|
5206
|
+
const exampleSection = create$8({
|
|
5207
|
+
title: "Examples"
|
|
5208
|
+
});
|
|
5209
|
+
const reasoningSection = create$8({
|
|
5210
|
+
title: "Reasoning"
|
|
5211
|
+
});
|
|
5212
|
+
const responseFormatSection = create$8({
|
|
5213
|
+
title: "Response Format"
|
|
5214
|
+
});
|
|
5215
|
+
const recapSection = create$8({
|
|
5216
|
+
title: "Recap"
|
|
5217
|
+
});
|
|
5218
|
+
const safeguardSection = create$8({
|
|
5219
|
+
title: "Safeguards"
|
|
5220
|
+
});
|
|
5221
|
+
// Helper for processing list items
|
|
5222
|
+
const processList = async (items, section, type)=>{
|
|
5223
|
+
for (const item of items){
|
|
5224
|
+
await processContentItem(item, section, type, {
|
|
5225
|
+
basePath: finalConfig.basePath,
|
|
5226
|
+
parser: parser$1,
|
|
5227
|
+
override: override$1,
|
|
5228
|
+
loader: loader$1,
|
|
5229
|
+
parameters: finalConfig.parameters});
|
|
5230
|
+
}
|
|
5231
|
+
};
|
|
5114
5232
|
// Process persona
|
|
5115
5233
|
if (finalConfig.persona) {
|
|
5116
5234
|
await processContentItem(finalConfig.persona, personaSection, 'persona', {
|
|
@@ -5120,15 +5238,18 @@ const cook = async (config)=>{
|
|
|
5120
5238
|
loader: loader$1,
|
|
5121
5239
|
parameters: finalConfig.parameters});
|
|
5122
5240
|
}
|
|
5123
|
-
// Process
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5241
|
+
// Process standard sections
|
|
5242
|
+
await processList(finalConfig.instructions || [], instructionSection, 'instruction');
|
|
5243
|
+
await processList(finalConfig.content || [], contentSection, 'content');
|
|
5244
|
+
await processList(finalConfig.context || [], contextSection, 'context');
|
|
5245
|
+
// Process advanced sections
|
|
5246
|
+
await processList(finalConfig.constraints || [], constraintSection, 'instruction');
|
|
5247
|
+
await processList(finalConfig.tone || [], toneSection, 'instruction');
|
|
5248
|
+
await processList(finalConfig.examples || [], exampleSection, 'content');
|
|
5249
|
+
await processList(finalConfig.reasoning || [], reasoningSection, 'instruction');
|
|
5250
|
+
await processList(finalConfig.responseFormat || [], responseFormatSection, 'instruction');
|
|
5251
|
+
await processList(finalConfig.recap || [], recapSection, 'instruction');
|
|
5252
|
+
await processList(finalConfig.safeguards || [], safeguardSection, 'instruction');
|
|
5132
5253
|
// Generate tool guidance if tools are provided
|
|
5133
5254
|
if (finalConfig.tools) {
|
|
5134
5255
|
const tools = Array.isArray(finalConfig.tools) ? finalConfig.tools : finalConfig.tools.getAll();
|
|
@@ -5142,30 +5263,59 @@ const cook = async (config)=>{
|
|
|
5142
5263
|
instructionSection.add(toolSection);
|
|
5143
5264
|
}
|
|
5144
5265
|
}
|
|
5145
|
-
// Process
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5266
|
+
// Process schema
|
|
5267
|
+
let schema = finalConfig.schema;
|
|
5268
|
+
let validator = undefined;
|
|
5269
|
+
if (schema instanceof zod.z.ZodType) {
|
|
5270
|
+
var _jsonSchema_definitions;
|
|
5271
|
+
// It's a Zod schema!
|
|
5272
|
+
validator = schema;
|
|
5273
|
+
const jsonSchema = zodToJsonSchema(schema, "response");
|
|
5274
|
+
// Wrap in OpenAI Structured Output format
|
|
5275
|
+
// zod-to-json-schema returns { "$schema": "...", "definitions": { "response": { ... } }, "$ref": "#/definitions/response" }
|
|
5276
|
+
// We need to extract the schema part.
|
|
5277
|
+
// Simpler usage for OpenAI: just get the schema object.
|
|
5278
|
+
// Actually, zod-to-json-schema produces a full JSON schema object.
|
|
5279
|
+
// OpenAI expects: { type: "json_schema", json_schema: { name: "...", schema: ... } }
|
|
5280
|
+
// Let's create a clean schema object
|
|
5281
|
+
// NOTE: OpenAI requires strict: true and additionalProperties: false
|
|
5282
|
+
// zod-to-json-schema generally produces compatible schemas but strictness might need tweaking if required by OpenAI.
|
|
5283
|
+
// For now, let's assume "response" as the name.
|
|
5284
|
+
// We'll define a simpler conversion if possible, or trust the user to configure Zod strictly if they want strict mode.
|
|
5285
|
+
// Extract the definition if it exists
|
|
5286
|
+
const actualSchema = ((_jsonSchema_definitions = jsonSchema.definitions) === null || _jsonSchema_definitions === void 0 ? void 0 : _jsonSchema_definitions.response) || jsonSchema;
|
|
5287
|
+
schema = {
|
|
5288
|
+
type: "json_schema",
|
|
5289
|
+
json_schema: {
|
|
5290
|
+
name: "response",
|
|
5291
|
+
schema: actualSchema,
|
|
5292
|
+
strict: true // Try to enable strict mode for OpenAI
|
|
5293
|
+
}
|
|
5294
|
+
};
|
|
5295
|
+
} else if (typeof schema === 'string') {
|
|
5296
|
+
const schemaPath = path.resolve(finalConfig.basePath, schema);
|
|
5297
|
+
try {
|
|
5298
|
+
const schemaContent = await fs.readFile(schemaPath, 'utf-8');
|
|
5299
|
+
schema = JSON.parse(schemaContent);
|
|
5300
|
+
} catch (e) {
|
|
5301
|
+
throw new Error(`Failed to load schema from ${schemaPath}: ${e.message}`);
|
|
5302
|
+
}
|
|
5162
5303
|
}
|
|
5163
5304
|
// Build and return prompt
|
|
5164
5305
|
return create$6({
|
|
5165
|
-
persona: personaSection,
|
|
5306
|
+
persona: personaSection.items.length > 0 ? personaSection : undefined,
|
|
5166
5307
|
instructions: instructionSection,
|
|
5167
|
-
contents: contentSection,
|
|
5168
|
-
contexts: contextSection
|
|
5308
|
+
contents: contentSection.items.length > 0 ? contentSection : undefined,
|
|
5309
|
+
contexts: contextSection.items.length > 0 ? contextSection : undefined,
|
|
5310
|
+
constraints: constraintSection.items.length > 0 ? constraintSection : undefined,
|
|
5311
|
+
tone: toneSection.items.length > 0 ? toneSection : undefined,
|
|
5312
|
+
examples: exampleSection.items.length > 0 ? exampleSection : undefined,
|
|
5313
|
+
reasoning: reasoningSection.items.length > 0 ? reasoningSection : undefined,
|
|
5314
|
+
responseFormat: responseFormatSection.items.length > 0 ? responseFormatSection : undefined,
|
|
5315
|
+
recap: recapSection.items.length > 0 ? recapSection : undefined,
|
|
5316
|
+
safeguards: safeguardSection.items.length > 0 ? safeguardSection : undefined,
|
|
5317
|
+
schema,
|
|
5318
|
+
validator
|
|
5169
5319
|
});
|
|
5170
5320
|
};
|
|
5171
5321
|
const processContentItem = async (item, section, type, ctx)=>{
|
|
@@ -5243,6 +5393,59 @@ const recipe = (basePath)=>{
|
|
|
5243
5393
|
];
|
|
5244
5394
|
return builder;
|
|
5245
5395
|
},
|
|
5396
|
+
constraints: (...constraints)=>{
|
|
5397
|
+
config.constraints = [
|
|
5398
|
+
...config.constraints || [],
|
|
5399
|
+
...constraints
|
|
5400
|
+
];
|
|
5401
|
+
return builder;
|
|
5402
|
+
},
|
|
5403
|
+
tone: (...tone)=>{
|
|
5404
|
+
config.tone = [
|
|
5405
|
+
...config.tone || [],
|
|
5406
|
+
...tone
|
|
5407
|
+
];
|
|
5408
|
+
return builder;
|
|
5409
|
+
},
|
|
5410
|
+
examples: (...examples)=>{
|
|
5411
|
+
config.examples = [
|
|
5412
|
+
...config.examples || [],
|
|
5413
|
+
...examples
|
|
5414
|
+
];
|
|
5415
|
+
return builder;
|
|
5416
|
+
},
|
|
5417
|
+
reasoning: (...reasoning)=>{
|
|
5418
|
+
config.reasoning = [
|
|
5419
|
+
...config.reasoning || [],
|
|
5420
|
+
...reasoning
|
|
5421
|
+
];
|
|
5422
|
+
return builder;
|
|
5423
|
+
},
|
|
5424
|
+
responseFormat: (...responseFormat)=>{
|
|
5425
|
+
config.responseFormat = [
|
|
5426
|
+
...config.responseFormat || [],
|
|
5427
|
+
...responseFormat
|
|
5428
|
+
];
|
|
5429
|
+
return builder;
|
|
5430
|
+
},
|
|
5431
|
+
recap: (...recap)=>{
|
|
5432
|
+
config.recap = [
|
|
5433
|
+
...config.recap || [],
|
|
5434
|
+
...recap
|
|
5435
|
+
];
|
|
5436
|
+
return builder;
|
|
5437
|
+
},
|
|
5438
|
+
safeguards: (...safeguards)=>{
|
|
5439
|
+
config.safeguards = [
|
|
5440
|
+
...config.safeguards || [],
|
|
5441
|
+
...safeguards
|
|
5442
|
+
];
|
|
5443
|
+
return builder;
|
|
5444
|
+
},
|
|
5445
|
+
schema: (schema)=>{
|
|
5446
|
+
config.schema = schema;
|
|
5447
|
+
return builder;
|
|
5448
|
+
},
|
|
5246
5449
|
parameters: (parameters)=>{
|
|
5247
5450
|
config.parameters = {
|
|
5248
5451
|
...config.parameters,
|
|
@@ -5666,7 +5869,8 @@ class OpenAIProvider {
|
|
|
5666
5869
|
model: model,
|
|
5667
5870
|
messages: messages,
|
|
5668
5871
|
temperature: options.temperature,
|
|
5669
|
-
max_tokens: options.maxTokens
|
|
5872
|
+
max_tokens: options.maxTokens,
|
|
5873
|
+
response_format: request.responseFormat
|
|
5670
5874
|
});
|
|
5671
5875
|
const choice = response.choices[0];
|
|
5672
5876
|
return {
|
|
@@ -5682,6 +5886,7 @@ class OpenAIProvider {
|
|
|
5682
5886
|
|
|
5683
5887
|
class AnthropicProvider {
|
|
5684
5888
|
async execute(request, options = {}) {
|
|
5889
|
+
var _request_responseFormat, _request_responseFormat1;
|
|
5685
5890
|
const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY;
|
|
5686
5891
|
if (!apiKey) throw new Error('Anthropic API key is required');
|
|
5687
5892
|
const client = new Anthropic({
|
|
@@ -5706,11 +5911,34 @@ class AnthropicProvider {
|
|
|
5706
5911
|
system: systemPrompt.trim() || undefined,
|
|
5707
5912
|
messages: messages,
|
|
5708
5913
|
max_tokens: options.maxTokens || 4096,
|
|
5709
|
-
temperature: options.temperature
|
|
5914
|
+
temperature: options.temperature,
|
|
5915
|
+
...((_request_responseFormat = request.responseFormat) === null || _request_responseFormat === void 0 ? void 0 : _request_responseFormat.type) === 'json_schema' ? {
|
|
5916
|
+
tools: [
|
|
5917
|
+
{
|
|
5918
|
+
name: request.responseFormat.json_schema.name,
|
|
5919
|
+
description: request.responseFormat.json_schema.description || "Output data in this structured format",
|
|
5920
|
+
input_schema: request.responseFormat.json_schema.schema
|
|
5921
|
+
}
|
|
5922
|
+
],
|
|
5923
|
+
tool_choice: {
|
|
5924
|
+
type: 'tool',
|
|
5925
|
+
name: request.responseFormat.json_schema.name
|
|
5926
|
+
}
|
|
5927
|
+
} : {}
|
|
5710
5928
|
});
|
|
5711
5929
|
// Handle ContentBlock
|
|
5712
|
-
|
|
5713
|
-
|
|
5930
|
+
// Check for tool_use first if we requested structured output
|
|
5931
|
+
let text = '';
|
|
5932
|
+
if (((_request_responseFormat1 = request.responseFormat) === null || _request_responseFormat1 === void 0 ? void 0 : _request_responseFormat1.type) === 'json_schema') {
|
|
5933
|
+
const toolUseBlock = response.content.find((block)=>block.type === 'tool_use');
|
|
5934
|
+
if (toolUseBlock && toolUseBlock.type === 'tool_use') {
|
|
5935
|
+
// Return the structured data as a JSON string to match OpenAI behavior
|
|
5936
|
+
text = JSON.stringify(toolUseBlock.input, null, 2);
|
|
5937
|
+
}
|
|
5938
|
+
} else {
|
|
5939
|
+
const contentBlock = response.content[0];
|
|
5940
|
+
text = contentBlock.type === 'text' ? contentBlock.text : '';
|
|
5941
|
+
}
|
|
5714
5942
|
return {
|
|
5715
5943
|
content: text,
|
|
5716
5944
|
model: response.model,
|
|
@@ -5724,10 +5952,53 @@ class AnthropicProvider {
|
|
|
5724
5952
|
|
|
5725
5953
|
class GeminiProvider {
|
|
5726
5954
|
async execute(request, options = {}) {
|
|
5955
|
+
var _request_responseFormat;
|
|
5727
5956
|
const apiKey = options.apiKey || process.env.GEMINI_API_KEY; // or GOOGLE_API_KEY
|
|
5728
5957
|
if (!apiKey) throw new Error('Gemini API key is required');
|
|
5729
5958
|
const genAI = new generativeAi.GoogleGenerativeAI(apiKey);
|
|
5730
5959
|
const modelName = options.model || request.model || 'gemini-1.5-pro';
|
|
5960
|
+
// Handle generation config for structured output
|
|
5961
|
+
const generationConfig = {};
|
|
5962
|
+
if (((_request_responseFormat = request.responseFormat) === null || _request_responseFormat === void 0 ? void 0 : _request_responseFormat.type) === 'json_schema') {
|
|
5963
|
+
generationConfig.responseMimeType = "application/json";
|
|
5964
|
+
// Map OpenAI JSON schema to Gemini Schema
|
|
5965
|
+
// OpenAI: { name: "...", schema: { type: "object", properties: ... } }
|
|
5966
|
+
// Gemini expects the schema object directly
|
|
5967
|
+
const openAISchema = request.responseFormat.json_schema.schema;
|
|
5968
|
+
// We need to recursively map the types because Gemini uses uppercase enums
|
|
5969
|
+
// SchemaType.OBJECT, SchemaType.STRING, etc.
|
|
5970
|
+
// But the SDK also accepts string types "OBJECT", "STRING" etc.
|
|
5971
|
+
// Let's implement a simple converter or pass it if compatible.
|
|
5972
|
+
// Zod-to-json-schema produces lowercase types ("object", "string").
|
|
5973
|
+
// Google's SDK might need them to be uppercase or mapped.
|
|
5974
|
+
// Helper to clean up schema for Gemini
|
|
5975
|
+
// Removes $schema, strict, and additionalProperties if not supported or formatted differently
|
|
5976
|
+
// And maps 'type' to uppercase.
|
|
5977
|
+
const mapSchema = (s)=>{
|
|
5978
|
+
if (!s) return undefined;
|
|
5979
|
+
const newSchema = {
|
|
5980
|
+
...s
|
|
5981
|
+
};
|
|
5982
|
+
if (newSchema.type) {
|
|
5983
|
+
newSchema.type = typeof newSchema.type === 'string' ? newSchema.type.toUpperCase() : newSchema.type;
|
|
5984
|
+
}
|
|
5985
|
+
if (newSchema.properties) {
|
|
5986
|
+
const newProps = {};
|
|
5987
|
+
for (const [key, val] of Object.entries(newSchema.properties)){
|
|
5988
|
+
newProps[key] = mapSchema(val);
|
|
5989
|
+
}
|
|
5990
|
+
newSchema.properties = newProps;
|
|
5991
|
+
}
|
|
5992
|
+
if (newSchema.items) {
|
|
5993
|
+
newSchema.items = mapSchema(newSchema.items);
|
|
5994
|
+
}
|
|
5995
|
+
// Remove unsupported OpenAI-specific fields if Gemini complains
|
|
5996
|
+
delete newSchema.additionalProperties;
|
|
5997
|
+
delete newSchema['$schema'];
|
|
5998
|
+
return newSchema;
|
|
5999
|
+
};
|
|
6000
|
+
generationConfig.responseSchema = mapSchema(openAISchema);
|
|
6001
|
+
}
|
|
5731
6002
|
// Gemini format: system instruction is separate, history is separate from last message
|
|
5732
6003
|
// generateContent accepts a string or parts.
|
|
5733
6004
|
// We need to construct the prompt.
|
|
@@ -5744,7 +6015,8 @@ class GeminiProvider {
|
|
|
5744
6015
|
// Let's try to prepend for compatibility if needed, but 'systemInstruction' param exists in getGenerativeModel config.
|
|
5745
6016
|
const configuredModel = genAI.getGenerativeModel({
|
|
5746
6017
|
model: modelName,
|
|
5747
|
-
systemInstruction: systemInstruction ? systemInstruction.trim() : undefined
|
|
6018
|
+
systemInstruction: systemInstruction ? systemInstruction.trim() : undefined,
|
|
6019
|
+
generationConfig
|
|
5748
6020
|
});
|
|
5749
6021
|
// Build history/messages
|
|
5750
6022
|
// Gemini `generateContent` takes the *last* user message.
|