/**
* PromptArchitect API Client
*
* Routes requests through the PromptArchitect backend for:
* - Proper billing and credit tracking
* - Usage analytics
* - Consistent model access across all clients
*
* Environment Variables:
* - PROMPTARCHITECT_API_URL: Backend API URL (default: production)
* - PROMPTARCHITECT_API_KEY: Optional API key for authenticated requests
*/
import { logger } from './logger.js';
const DEFAULT_API_URL = 'https://us-central1-prompt-architect-3df7a.cloudfunctions.net/api';
let apiUrl: string = DEFAULT_API_URL;
let apiKey: string | null = null;
/**
* Initialize the API client
*/
export function initializeApiClient(options?: { apiUrl?: string; apiKey?: string }): void {
apiUrl = options?.apiUrl || process.env.PROMPTARCHITECT_API_URL || DEFAULT_API_URL;
apiKey = options?.apiKey || process.env.PROMPTARCHITECT_API_KEY || null;
logger.info('API client initialized', {
apiUrl: apiUrl.replace(/^(https?:\/\/[^\/]+).*/, '$1/...'),
hasApiKey: !!apiKey
});
}
/**
* Check if API client is configured
*/
export function isApiClientAvailable(): boolean {
return !!apiUrl;
}
/**
* Get the configured API URL
*/
export function getApiUrl(): string {
return apiUrl;
}
interface GenerateResponse {
prompt: string;
template?: string;
metadata?: {
wordCount: number;
targetModel?: string;
};
}
interface RefineResponse {
refinedPrompt: string;
changes: string[];
metadata?: {
originalWordCount: number;
refinedWordCount: number;
structurePreserved: boolean;
};
}
interface AnalyzeResponse {
overallScore: number;
scores: {
clarity: number;
specificity: number;
structure: number;
actionability: number;
};
strengths: string[];
weaknesses: string[];
suggestions: string[];
}
/**
* Make authenticated API request
*/
async function apiRequest<T>(endpoint: string, body: Record<string, unknown>): Promise<T> {
const url = `${apiUrl}/vscode${endpoint}`;
const headers: Record<string, string> = {
'Content-Type': 'application/json',
'X-Client': 'mcp-server',
'X-Client-Version': '0.1.6',
};
if (apiKey) {
headers['Authorization'] = `Bearer ${apiKey}`;
}
logger.debug('API request', { endpoint, bodyKeys: Object.keys(body) });
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify(body),
});
if (!response.ok) {
const errorText = await response.text();
logger.error('API request failed', {
endpoint,
status: response.status,
error: errorText.slice(0, 200)
});
throw new Error(`API request failed: ${response.status} ${response.statusText}`);
}
return response.json() as Promise<T>;
}
/**
* Generate a prompt using the backend API
*/
export async function apiGeneratePrompt(params: {
idea: string;
template?: string;
context?: string;
targetModel?: string;
workspaceContext?: string;
}): Promise<GenerateResponse> {
logger.info('Generating prompt via API', {
template: params.template,
ideaLength: params.idea.length,
hasWorkspaceContext: !!params.workspaceContext
});
const response = await apiRequest<GenerateResponse>('/generate', {
idea: params.idea,
template: params.template || 'general',
context: params.context,
targetModel: params.targetModel || 'gemini',
workspaceContext: params.workspaceContext,
});
return response;
}
/**
* Refine a prompt using the backend API
*/
export async function apiRefinePrompt(params: {
prompt: string;
feedback: string;
preserveStructure?: boolean;
targetModel?: string;
workspaceContext?: string;
}): Promise<RefineResponse> {
logger.info('Refining prompt via API', {
promptLength: params.prompt.length,
feedbackLength: params.feedback.length,
hasWorkspaceContext: !!params.workspaceContext
});
const response = await apiRequest<RefineResponse>('/refine', {
prompt: params.prompt,
feedback: params.feedback,
preserveStructure: params.preserveStructure ?? true,
targetModel: params.targetModel || 'gemini',
workspaceContext: params.workspaceContext,
});
return response;
}
/**
* Analyze a prompt using the backend API
*/
export async function apiAnalyzePrompt(params: {
prompt: string;
evaluationCriteria?: string[];
}): Promise<AnalyzeResponse> {
logger.info('Analyzing prompt via API', {
promptLength: params.prompt.length
});
const response = await apiRequest<AnalyzeResponse>('/analyze', {
prompt: params.prompt,
evaluationCriteria: params.evaluationCriteria,
});
return response;
}
// Auto-initialize on module load
initializeApiClient();