import { getErrorMeta, getLogger } from "../../util/logger.js";
import { globalPerfettoProfiler } from "./perfetto-profiler.js";
/**
 * Clark-specific profiler that tracks performance across LLM operations,
 * tool calls, and debug cycles
 */
export class ClarkProfiler {
    profiler;
    sessionId;
    appShell;
    runTimestamp;
    constructor(sessionId) {
        this.profiler = globalPerfettoProfiler;
        this.sessionId = sessionId;
    }
    /**
     * Initialize the profiler with required services
     */
    initialize(appShell, runTimestamp) {
        this.appShell = appShell;
        this.runTimestamp = runTimestamp;
    }
    startSession() {
        this.profiler.reset();
    }
    /**
     * End the LLM session and write profiling data
     */
    async endSession() {
        // End all active events across all tracks
        this.profiler.endAllActiveEvents();
        if (!this.appShell) {
            getLogger().warn("[ClarkProfiler] AppShell not initialized, cannot save profiling data");
            return;
        }
        const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
        const filename = `clark-profile-${this.sessionId}-${timestamp}.json`;
        const content = this.profiler.generateJSON();
        const profilingArtifact = {
            type: "file",
            filePath: filename,
            content,
        };
        const stepId = `profiling-${this.sessionId}`;
        const runTimestamp = this.runTimestamp || new Date().toISOString().replace(/[:.]/g, "-");
        try {
            await this.appShell.saveGeneratedArtifact(profilingArtifact, stepId, runTimestamp);
            const stats = this.profiler.getStats();
            getLogger().info(`[ClarkProfiler] Session ${this.sessionId} profiling data saved as ${filename}`);
            getLogger().info(`[ClarkProfiler] Total events: ${stats.totalEvents}, Active events: ${stats.activeEvents}, Tracks: ${stats.totalTracks}`);
        }
        catch (error) {
            getLogger().error("[ClarkProfiler] Failed to save profiling data:", getErrorMeta(error));
        }
    }
    /**
     * Track FSM state transitions
     */
    onStateTransition(fromState, toState, _event) {
        // Track states that perform significant operations
        const trackedStates = [
            "LLMGenerating",
            "PostProcessing",
            "RuntimeReviewing",
        ];
        // End previous state if we were tracking one
        if (fromState && trackedStates.includes(fromState)) {
            this.profiler.endFrame("main");
        }
        // Start new state tracking for operational states
        // Don't start duplicate frames for the same state
        if (toState && trackedStates.includes(toState) && fromState !== toState) {
            this.profiler.startFrame(`state_${toState.toLowerCase()}`, "main");
        }
    }
    /**
     * Time a tool execution
     */
    async timeToolCall(toolName, fn) {
        const trackKey = `tool_${toolName}`;
        this.profiler.createTrack(trackKey, `Tool: ${toolName}`, "tool");
        return this.profiler.timeAsync(`${toolName}`, fn, trackKey);
    }
    /**
     * Time an LLM generation with waiting_on_llm and stream_text spans
     */
    async timeLLMGeneration(fn, messageContext) {
        const trackKey = "llm";
        this.profiler.createTrack(trackKey, "LLM Operations", "llm");
        return this.profiler.timeAsync("waiting_on_llm", fn, trackKey, {
            model: messageContext?.model,
            messageCount: messageContext?.messages?.length,
            messages: messageContext?.messages?.map((msg, i) => ({
                index: i,
                role: msg.role,
                contentPreview: typeof msg.content === "string"
                    ? msg.content
                        .slice(0, 200)
                        .replace(/[\n\r\t]/g, " ")
                        .replace(/\s+/g, " ")
                        .trim() + (msg.content.length > 200 ? "..." : "")
                    : "[complex content]",
                contentLength: typeof msg.content === "string" ? msg.content.length : 0,
            })),
        });
    }
    /**
     * Start LLM waiting profiling span
     */
    startLLMWaiting(messageContext) {
        const trackKey = "llm";
        this.profiler.createTrack(trackKey, "LLM Operations", "llm");
        this.profiler.startFrame("waiting_on_llm", trackKey, {
            model: messageContext?.model,
            messageCount: messageContext?.messages?.length,
            messages: messageContext?.messages?.map((msg, i) => ({
                index: i,
                role: msg.role,
                contentPreview: typeof msg.content === "string"
                    ? msg.content
                        .slice(0, 200)
                        .replace(/[\n\r\t]/g, " ")
                        .replace(/\s+/g, " ")
                        .trim() + (msg.content.length > 200 ? "..." : "")
                    : "[complex content]",
                contentLength: typeof msg.content === "string" ? msg.content.length : 0,
            })),
        });
    }
    /**
     * Start streaming profiling span (call after first token received)
     */
    startLLMStreaming(responseContext) {
        const trackKey = "llm";
        this.profiler.createTrack(trackKey, "LLM Operations", "llm");
        this.profiler.startFrame("stream_text", trackKey, {
            firstChunkPreview: responseContext?.firstChunk?.slice(0, 100) || "[no preview]",
            streamingStarted: new Date().toISOString(),
        });
    }
    endFrame(trackKey) {
        this.profiler.endFrame(trackKey);
    }
    /**
     * Time debug operations (typecheck, lint)
     */
    async timeDebugOperation(operation, fn) {
        const trackKey = "debug";
        this.profiler.createTrack(trackKey, "Debug Operations", "debug");
        return this.profiler.timeAsync(operation, fn, trackKey);
    }
    /**
     * Time file system operations
     */
    async timeFileOperation(operation, fn) {
        const trackKey = "file_system";
        this.profiler.createTrack(trackKey, "File System Operations", "file");
        return this.profiler.timeAsync(operation, fn, trackKey);
    }
    /**
     * Time post-processing operations
     */
    async timePostProcessing(operation, fn) {
        return this.profiler.timeAsync(operation, fn, "main");
    }
    getProfiler() {
        return this.profiler;
    }
    /**
     * Create a scoped profiler for a specific operation
     */
    createScope(scopeName) {
        return new ScopedProfiler(this.profiler, scopeName);
    }
}
/**
 * A scoped profiler that automatically manages start/end for a specific operation
 */
export class ScopedProfiler {
    profiler;
    scopeName;
    trackKey;
    isActive = false;
    constructor(profiler, scopeName) {
        this.profiler = profiler;
        this.scopeName = scopeName;
        this.trackKey = `scope_${scopeName}`;
        this.profiler.createTrack(this.trackKey, `Scope: ${scopeName}`, "tool");
    }
    start() {
        if (!this.isActive) {
            this.profiler.startFrame(this.scopeName, this.trackKey);
            this.isActive = true;
        }
    }
    end() {
        if (this.isActive) {
            this.profiler.endFrame(this.trackKey);
            this.isActive = false;
        }
    }
    /**
     * Time a function within this scope
     */
    async time(operation, fn) {
        return this.profiler.timeAsync(operation, fn, this.trackKey);
    }
}
//# sourceMappingURL=clark-profiler.js.map