/**
 * Resume Strategy Engine - Determines optimal resume approach
 * Supports native resume, prompt concatenation, and hybrid modes
 */
/**
 * Determine the optimal resume strategy based on scenario
 *
 * Scenarios:
 * 1. Single append (no customId) → native if mapping exists
 * 2. Fork (customId provided) → prompt-concat (new conversation)
 * 3. Merge multiple → hybrid (primary native + others as context)
 * 4. Cross-tool → prompt-concat (tools differ)
 * 5. resume=true (latest) → native with isLatest flag
 */
export function determineResumeStrategy(options) {
    const { tool, resumeIds, customId, forceNative, forcePromptConcat, getNativeSessionId, getConversation, getConversationTool } = options;
    // Force prompt concatenation
    if (forcePromptConcat) {
        return buildPromptConcatDecision(resumeIds, getConversation);
    }
    // No resume IDs - new conversation
    if (resumeIds.length === 0) {
        return { strategy: 'prompt-concat' };
    }
    // Scenario 5: resume=true (latest) - use native latest
    // This is handled before this function is called, but included for completeness
    // Scenario 2: Fork (customId provided) → always prompt-concat
    if (customId) {
        return buildPromptConcatDecision(resumeIds, getConversation);
    }
    // Scenario 4: Check for cross-tool resume
    const crossTool = resumeIds.some(id => {
        const convTool = getConversationTool(id);
        return convTool && convTool !== tool;
    });
    if (crossTool) {
        return buildPromptConcatDecision(resumeIds, getConversation);
    }
    // Scenario 1: Single append
    if (resumeIds.length === 1) {
        const nativeId = getNativeSessionId(resumeIds[0]);
        if (nativeId || forceNative) {
            return {
                strategy: 'native',
                nativeSessionId: nativeId || undefined,
                primaryConversationId: resumeIds[0]
            };
        }
        // No native mapping, fall back to prompt-concat
        return buildPromptConcatDecision(resumeIds, getConversation);
    }
    // Scenario 3: Merge multiple conversations → hybrid mode
    return buildHybridDecision(resumeIds, tool, getNativeSessionId, getConversation);
}
/**
 * Build prompt-concat decision with all turns loaded
 */
function buildPromptConcatDecision(resumeIds, getConversation) {
    const allTurns = [];
    for (const id of resumeIds) {
        const conversation = getConversation(id);
        if (conversation) {
            // Add source ID to each turn for tracking
            const turnsWithSource = conversation.turns.map(turn => ({
                ...turn,
                _sourceId: id
            }));
            allTurns.push(...turnsWithSource);
        }
    }
    // Sort by timestamp
    allTurns.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
    return {
        strategy: 'prompt-concat',
        contextTurns: allTurns,
        primaryConversationId: resumeIds[0]
    };
}
/**
 * Build hybrid decision: primary uses native, others as context prefix
 */
function buildHybridDecision(resumeIds, tool, getNativeSessionId, getConversation) {
    // Find the first ID with native session mapping
    let primaryId = null;
    let nativeId = null;
    for (const id of resumeIds) {
        const native = getNativeSessionId(id);
        if (native) {
            primaryId = id;
            nativeId = native;
            break;
        }
    }
    // If no native mapping found, use first as primary
    if (!primaryId) {
        primaryId = resumeIds[0];
    }
    // Collect context turns from non-primary conversations
    const contextTurns = [];
    for (const id of resumeIds) {
        if (id === primaryId && nativeId) {
            // Skip primary if using native - its context is handled natively
            continue;
        }
        const conversation = getConversation(id);
        if (conversation) {
            const turnsWithSource = conversation.turns.map(turn => ({
                ...turn,
                _sourceId: id
            }));
            contextTurns.push(...turnsWithSource);
        }
    }
    // Sort context turns by timestamp
    contextTurns.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
    // If we have native ID, use hybrid; otherwise fall back to prompt-concat
    if (nativeId) {
        return {
            strategy: 'hybrid',
            nativeSessionId: nativeId,
            contextTurns: contextTurns.length > 0 ? contextTurns : undefined,
            primaryConversationId: primaryId
        };
    }
    // No native mapping, use full prompt-concat
    return buildPromptConcatDecision(resumeIds, getConversation);
}
/**
 * Build context prefix for hybrid mode
 * Formats non-primary conversation turns as context
 */
export function buildContextPrefix(contextTurns, format = 'plain') {
    if (!contextTurns || contextTurns.length === 0) {
        return '';
    }
    const maxOutputLength = 4096; // Truncate long outputs
    switch (format) {
        case 'yaml':
            return buildYamlContext(contextTurns, maxOutputLength);
        case 'json':
            return buildJsonContext(contextTurns, maxOutputLength);
        default:
            return buildPlainContext(contextTurns, maxOutputLength);
    }
}
function buildPlainContext(turns, maxLength) {
    const lines = [
        '=== MERGED CONTEXT FROM OTHER CONVERSATIONS ===',
        ''
    ];
    for (const turn of turns) {
        const sourceId = turn._sourceId || 'unknown';
        lines.push(`--- Turn ${turn.turn} [${sourceId}] ---`);
        lines.push(`USER:`);
        lines.push(turn.prompt);
        lines.push('');
        lines.push(`ASSISTANT:`);
        const output = turn.output.stdout || '';
        lines.push(output.length > maxLength ? output.substring(0, maxLength) + '\n[truncated]' : output);
        lines.push('');
    }
    lines.push('=== END MERGED CONTEXT ===');
    lines.push('');
    return lines.join('\n');
}
function buildYamlContext(turns, maxLength) {
    const lines = [
        'merged_context:',
        '  source: "other_conversations"',
        '  turns:'
    ];
    for (const turn of turns) {
        const sourceId = turn._sourceId || 'unknown';
        const output = turn.output.stdout || '';
        const truncatedOutput = output.length > maxLength
            ? output.substring(0, maxLength) + '\n[truncated]'
            : output;
        lines.push(`    - turn: ${turn.turn}`);
        lines.push(`      source: "${sourceId}"`);
        lines.push(`      user: |`);
        lines.push(turn.prompt.split('\n').map(l => `        ${l}`).join('\n'));
        lines.push(`      assistant: |`);
        lines.push(truncatedOutput.split('\n').map(l => `        ${l}`).join('\n'));
    }
    lines.push('');
    return lines.join('\n');
}
function buildJsonContext(turns, maxLength) {
    const context = {
        merged_context: {
            source: 'other_conversations',
            turns: turns.map(turn => {
                const output = turn.output.stdout || '';
                return {
                    turn: turn.turn,
                    source: turn._sourceId || 'unknown',
                    user: turn.prompt,
                    assistant: output.length > maxLength
                        ? output.substring(0, maxLength) + '\n[truncated]'
                        : output
                };
            })
        }
    };
    return JSON.stringify(context, null, 2) + '\n\n';
}
/**
 * Check if a resume scenario requires native resume
 */
export function shouldUseNativeResume(tool, resumeIds, customId, getNativeSessionId, getConversationTool) {
    // Fork always uses prompt-concat
    if (customId)
        return false;
    // No resume IDs
    if (resumeIds.length === 0)
        return false;
    // Cross-tool not supported natively
    const crossTool = resumeIds.some(id => {
        const convTool = getConversationTool(id);
        return convTool && convTool !== tool;
    });
    if (crossTool)
        return false;
    // Single resume with native mapping
    if (resumeIds.length === 1) {
        return !!getNativeSessionId(resumeIds[0]);
    }
    // Merge: at least one needs native mapping for hybrid
    return resumeIds.some(id => !!getNativeSessionId(id));
}
/**
 * Get resume mode description for logging
 */
export function getResumeModeDescription(decision) {
    switch (decision.strategy) {
        case 'native':
            return `Native resume (session: ${decision.nativeSessionId || 'latest'})`;
        case 'hybrid':
            const contextCount = decision.contextTurns?.length || 0;
            return `Hybrid (native + ${contextCount} context turns)`;
        case 'prompt-concat':
            const turnCount = decision.contextTurns?.length || 0;
            return `Prompt concat (${turnCount} turns)`;
        default:
            return 'Unknown';
    }
}
//# sourceMappingURL=resume-strategy.js.map