UNPKG

@meldscience/meld

Version:

pipeable one-shot prompt scripting toolkit

114 lines (99 loc) 3.81 kB
import { readFileSync, existsSync } from 'fs'; import { ToolError } from './errors'; import { AIProvider } from './providers/anthropic'; import { loadConfig } from './config'; export interface Variation { system?: string; model?: string; prompt?: string; } export interface OneshotOptions { model: string; // e.g. "gpt-4" or "claude-2" or an alias promptFile: string; // path to user prompt or direct text system?: string; // optional single system prompt systemFile?: string; // or read system prompt from file variations?: (string | Variation)[]; // list of variation prompts or objects iterations?: number; // number of responses per variation } export interface ResponseEnvelope { variation?: string | Variation; systemPrompt: string; response: string; model: string; } export class Oneshot { private resolvedModel: string; private systemPrompt: string = ''; constructor( private options: OneshotOptions, private provider: AIProvider ) { // Resolve model alias if it exists const config = loadConfig(); this.resolvedModel = config.modelAliases?.[options.model] || options.model; } async process(): Promise<ResponseEnvelope[]> { // Check if prompt file exists if (!existsSync(this.options.promptFile)) { throw new ToolError(`Oneshot: Prompt file not found: ${this.options.promptFile}`, 'FILE_NOT_FOUND'); } // Check if system file exists if (this.options.systemFile && !existsSync(this.options.systemFile)) { throw new ToolError(`Oneshot: System file not found: ${this.options.systemFile}`, 'FILE_NOT_FOUND'); } // Initialize system prompt this.systemPrompt = ''; if (this.options.system) { this.systemPrompt = this.options.system; } else if (this.options.systemFile) { try { this.systemPrompt = readFileSync(this.options.systemFile, 'utf-8'); } catch (error: any) { throw new ToolError(`Oneshot: Failed to read system file: ${error.message}`, 'FILE_READ_ERROR'); } } // Get prompt content from file let promptContent: string; try { promptContent = readFileSync(this.options.promptFile, 'utf-8'); } catch (error: any) { throw new ToolError(`Oneshot: Failed to read prompt: ${error.message}`, 'FILE_READ_ERROR'); } // Process variations const variations = this.options.variations || [undefined]; const iterations = this.options.iterations || 1; // Run all variations and iterations const responses: ResponseEnvelope[] = []; for (const variation of variations) { for (let i = 0; i < iterations; i++) { // Handle variation object or string let variationPrompt = ''; let variationSystem = this.systemPrompt; let variationModel = this.resolvedModel; if (typeof variation === 'string') { variationPrompt = variation; } else if (variation) { variationPrompt = variation.prompt || ''; variationSystem = variation.system || this.systemPrompt; if (variation.model) { const config = loadConfig(); variationModel = config.modelAliases?.[variation.model] || variation.model; } } const combinedPrompt = variationPrompt ? `${promptContent}\n\n${variationPrompt}` : promptContent; const response = await this.provider.sendPrompt({ model: variationModel, systemPrompt: variationSystem, userPrompt: combinedPrompt }); responses.push({ variation, systemPrompt: variationSystem, response, model: variationModel }); } } return responses; } }