feat(docs): add structured output example and details

This commit is contained in:
2025-09-04 14:49:01 +02:00
parent 5da20536af
commit 18769c134d
10 changed files with 647 additions and 22 deletions

View File

@@ -19,9 +19,10 @@ import type {
CompletionParams,
CompletionResponse,
CompletionChunk,
ProviderInfo
ProviderInfo,
ResponseType
} from '../types/index.js';
import { AIProviderError, AIErrorType } from '../types/index.js';
import { AIProviderError, AIErrorType, generateResponseTypePrompt } from '../types/index.js';
// ============================================================================
// ABSTRACT BASE PROVIDER CLASS
@@ -147,7 +148,7 @@ export abstract class BaseAIProvider {
* console.log(response.content);
* ```
*/
public async complete(params: CompletionParams): Promise<CompletionResponse> {
public async complete<T = any>(params: CompletionParams<T>): Promise<CompletionResponse> {
// Ensure provider is ready for use
this.ensureInitialized();
@@ -155,8 +156,11 @@ export abstract class BaseAIProvider {
this.validateCompletionParams(params);
try {
// Process response type instructions if specified
const processedParams = this.processResponseType(params);
// Delegate to provider-specific implementation
return await this.doComplete(params);
return await this.doComplete(processedParams);
} catch (error) {
// Normalize error to our standard format
throw this.normalizeError(error as Error);
@@ -184,7 +188,7 @@ export abstract class BaseAIProvider {
* }
* ```
*/
public async *stream(params: CompletionParams): AsyncIterable<CompletionChunk> {
public async *stream<T = any>(params: CompletionParams<T>): AsyncIterable<CompletionChunk> {
// Ensure provider is ready for use
this.ensureInitialized();
@@ -192,8 +196,11 @@ export abstract class BaseAIProvider {
this.validateCompletionParams(params);
try {
// Process response type instructions if specified
const processedParams = this.processResponseType(params);
// Delegate to provider-specific implementation
yield* this.doStream(params);
yield* this.doStream(processedParams);
} catch (error) {
// Normalize error to our standard format
throw this.normalizeError(error as Error);
@@ -242,7 +249,7 @@ export abstract class BaseAIProvider {
* @returns Promise resolving to completion response
* @throws {Error} If completion fails (will be normalized to AIProviderError)
*/
protected abstract doComplete(params: CompletionParams): Promise<CompletionResponse>;
protected abstract doComplete<T = any>(params: CompletionParams<T>): Promise<CompletionResponse>;
/**
* Provider-specific streaming implementation.
@@ -256,7 +263,7 @@ export abstract class BaseAIProvider {
* @returns AsyncIterable yielding completion chunks
* @throws {Error} If streaming fails (will be normalized to AIProviderError)
*/
protected abstract doStream(params: CompletionParams): AsyncIterable<CompletionChunk>;
protected abstract doStream<T = any>(params: CompletionParams<T>): AsyncIterable<CompletionChunk>;
// ========================================================================
// PROTECTED UTILITY METHODS
@@ -370,7 +377,7 @@ export abstract class BaseAIProvider {
* @param params - Parameters to validate
* @throws {AIProviderError} If any parameter is invalid
*/
protected validateCompletionParams(params: CompletionParams): void {
protected validateCompletionParams<T = any>(params: CompletionParams<T>): void {
if (!params || typeof params !== 'object') {
throw new AIProviderError(
'Completion parameters object is required',
@@ -512,6 +519,45 @@ export abstract class BaseAIProvider {
}
}
/**
* Processes completion parameters to include response type instructions.
*
* This method automatically adds system prompt instructions when a response
* type is specified, ensuring the AI understands the expected output format.
*
* @protected
* @param params - Original completion parameters
* @returns Processed parameters with response type instructions
*/
protected processResponseType<T>(params: CompletionParams<T>): CompletionParams<T> {
if (!params.responseType) {
return params;
}
// Create a copy of the parameters to avoid mutation
const processedParams = { ...params };
// Generate the response type instruction
const responseTypePrompt = generateResponseTypePrompt(params.responseType);
// Find existing system messages or create new ones
const systemMessages = params.messages.filter(msg => msg.role === 'system');
const nonSystemMessages = params.messages.filter(msg => msg.role !== 'system');
// Combine existing system messages with response type instruction
const combinedSystemContent = systemMessages.length > 0
? systemMessages.map(msg => msg.content).join('\n\n') + '\n\n' + responseTypePrompt
: responseTypePrompt;
// Create new messages array with combined system message
processedParams.messages = [
{ role: 'system', content: combinedSystemContent },
...nonSystemMessages
];
return processedParams;
}
/**
* Normalizes any error into a standardized AIProviderError.
*