/** * Interview Orchestrator * Bridges the event-based TUI hook to ConversationManager * * This class manages the interview flow for spec generation, * translating ConversationManager events into TUI-friendly callbacks. */ import type { AIProvider } from '../../ai/providers.js'; import type { ScanResult } from '../../scanner/types.js'; import type { GeneratorPhase } from '../hooks/useSpecGenerator.js'; import { type InterviewQuestion, type InterviewAnswer } from '../types/interview.js'; /** * Session context from /init analysis */ export interface SessionContext { entryPoints?: string[]; keyDirectories?: Record; commands?: { build?: string; dev?: string; test?: string; }; namingConventions?: string; implementationGuidelines?: string[]; keyPatterns?: string[]; } /** * Options for the InterviewOrchestrator */ export interface InterviewOrchestratorOptions { /** Name of the feature being specified */ featureName: string; /** Project root directory path */ projectRoot: string; /** AI provider to use */ provider: AIProvider; /** Model ID to use */ model: string; /** Optional scan result with detected tech stack */ scanResult?: ScanResult; /** Rich session context from /init */ sessionContext?: SessionContext; /** Tavily API key for web search */ tavilyApiKey?: string; /** Context7 API key for docs lookup */ context7ApiKey?: string; /** Called when a message should be added to the conversation */ onMessage: (role: 'user' | 'assistant' | 'system', content: string) => void; /** Called when streaming text should be appended */ onStreamChunk: (chunk: string) => void; /** Called when streaming is complete */ onStreamComplete: () => void; /** Called when a tool starts executing */ onToolStart: (toolName: string, input: Record) => string; /** Called when a tool completes */ onToolEnd: (toolId: string, output?: string, error?: string) => void; /** Called when the phase changes */ onPhaseChange: (phase: GeneratorPhase) => void; /** Called when spec generation is complete */ onComplete: (spec: string) => void; /** Called when an error occurs */ onError: (error: string) => void; /** Called when working state changes */ onWorkingChange: (isWorking: boolean, status: string) => void; /** Called when ready for user input */ onReady: () => void; /** Called when a structured interview question is received (null = no structured question, use free-text) */ onQuestion?: (question: InterviewQuestion | null) => void; } /** * Build enhanced system prompt with project context and tool awareness * @internal Exported for testing */ export declare function buildSystemPrompt(sessionContext?: SessionContext, hasTools?: { codebase: boolean; tavily: boolean; context7: boolean; }): string; /** * Parse an AI response to extract a structured interview question with options * @param response The AI response text * @returns InterviewQuestion object if parsing succeeds, null otherwise * @internal Exported for testing */ export declare function parseInterviewResponse(response: string): InterviewQuestion | null; /** * Extract session context from EnhancedScanResult * @internal Exported for testing */ export declare function extractSessionContext(scanResult: ScanResult): SessionContext | undefined; /** * InterviewOrchestrator * * Manages the interview flow for spec generation, bridging * the ConversationManager to TUI callbacks. */ export declare class InterviewOrchestrator { private conversation; private phase; private readonly featureName; private readonly projectRoot; private generatedSpec; private questionCount; private readonly hasTools; private readonly sessionContext?; private currentQuestion; private readonly onMessage; private readonly onStreamChunk; private readonly onStreamComplete; private readonly onToolStart; private readonly onToolEnd; private readonly onPhaseChange; private readonly onComplete; private readonly onError; private readonly onWorkingChange; private readonly onReady; private readonly onQuestion?; private activeToolCalls; constructor(options: InterviewOrchestratorOptions); /** * Start the interview flow * Called after the component mounts */ start(): Promise; /** * Add a reference URL or file path */ addReference(refUrl: string): Promise; /** * Add pre-fetched content as a reference (skips URL/file fetch) */ addReferenceContent(content: string, source: string): void; /** * Advance to the goals phase * Called when user is done adding context */ advanceToGoals(): Promise; /** * Submit user's goals and start the interview */ submitGoals(goals: string): Promise; /** * Submit an answer during the interview phase */ submitAnswer(answer: InterviewAnswer): Promise; /** * Parse an AI response and emit as structured question or plain text */ private emitParsedResponse; /** * Skip to generation phase */ skipToGeneration(): Promise; /** * Generate the specification */ private generateSpec; /** * Get current phase */ getPhase(): GeneratorPhase; /** * Get question count */ getQuestionCount(): number; /** * Get generated spec */ getSpec(): string; }