"use strict";
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024-2026 Gracker (Chris)
// This file is part of SmartPerfetto. See LICENSE for details.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.config = exports.frontendConfig = exports.sceneStoryConfig = exports.featureFlagsConfig = exports.contextConfig = exports.analysisConfig = exports.forkConfig = exports.modelRouterConfig = exports.pipelineConfig = exports.circuitBreakerConfig = exports.agentConfig = exports.agentSessionConfig = exports.agentRuntimeBudgetConfig = exports.DEFAULT_AGENT_SESSION_CLEANUP_INTERVAL_MS = exports.DEFAULT_AGENT_SESSION_MAX_IDLE_MS = exports.DEFAULT_AGENT_QUICK_MAX_TURNS = exports.DEFAULT_AGENT_MAX_TURNS = exports.traceProcessorConfig = exports.serverConfig = exports.featureConfig = exports.DEFAULT_FRONTEND_PORT = exports.DEFAULT_BACKEND_PORT = exports.SMARTPERFETTO_BACKEND_PUBLIC_URL_ENV = exports.SMARTPERFETTO_BACKEND_PUBLIC_PORT_ENV = exports.SMARTPERFETTO_FRONTEND_PORT_ENV = exports.SMARTPERFETTO_BACKEND_PORT_ENV = exports.ENTERPRISE_FEATURE_FLAG_ENV = void 0;
exports.resolveFeatureConfig = resolveFeatureConfig;
exports.resolveServerConfig = resolveServerConfig;
exports.resolveAgentRuntimeBudgetConfig = resolveAgentRuntimeBudgetConfig;
exports.resolveAgentSessionConfig = resolveAgentSessionConfig;
/**
 * SmartPerfetto Unified Configuration
 *
 * 集中管理所有配置值，支持环境变量覆盖
 * 遵循 12-factor app 原则
 */
// =============================================================================
// Helper Functions
// =============================================================================
function parseIntEnv(key, defaultValue, env = process.env) {
    const value = env[key];
    if (!value)
        return defaultValue;
    const parsed = parseInt(value, 10);
    return isNaN(parsed) ? defaultValue : parsed;
}
function parsePositiveIntEnv(key, defaultValue, env = process.env) {
    const parsed = parseIntEnv(key, defaultValue, env);
    return Number.isFinite(parsed) && parsed > 0 ? parsed : defaultValue;
}
function parseFloatEnv(key, defaultValue, env = process.env) {
    const value = env[key];
    if (!value)
        return defaultValue;
    const parsed = parseFloat(value);
    return isNaN(parsed) ? defaultValue : parsed;
}
function parseArrayEnv(key, defaultValue, env = process.env) {
    const value = env[key];
    if (!value)
        return defaultValue;
    return value.split(',').map(s => s.trim()).filter(s => s.length > 0);
}
function parseBoolEnv(key, defaultValue, env = process.env) {
    const value = env[key];
    if (!value)
        return defaultValue;
    return value.toLowerCase() === 'true' || value === '1';
}
function parseFeatureFlag(value, defaultValue = false) {
    if (!value)
        return defaultValue;
    const normalized = value.trim().toLowerCase();
    if (['1', 'true', 'yes', 'on', 'enabled'].includes(normalized))
        return true;
    if (['0', 'false', 'no', 'off', 'disabled'].includes(normalized))
        return false;
    return defaultValue;
}
// =============================================================================
// Feature Flags
// =============================================================================
exports.ENTERPRISE_FEATURE_FLAG_ENV = 'SMARTPERFETTO_ENTERPRISE';
exports.SMARTPERFETTO_BACKEND_PORT_ENV = 'SMARTPERFETTO_BACKEND_PORT';
exports.SMARTPERFETTO_FRONTEND_PORT_ENV = 'SMARTPERFETTO_FRONTEND_PORT';
exports.SMARTPERFETTO_BACKEND_PUBLIC_PORT_ENV = 'SMARTPERFETTO_BACKEND_PUBLIC_PORT';
exports.SMARTPERFETTO_BACKEND_PUBLIC_URL_ENV = 'SMARTPERFETTO_BACKEND_PUBLIC_URL';
exports.DEFAULT_BACKEND_PORT = 3000;
exports.DEFAULT_FRONTEND_PORT = 10000;
function resolveFeatureConfig(env = process.env) {
    return {
        enterprise: parseFeatureFlag(env[exports.ENTERPRISE_FEATURE_FLAG_ENV], false),
    };
}
exports.featureConfig = resolveFeatureConfig();
// =============================================================================
// Server Configuration
// =============================================================================
function parsePortValue(value) {
    if (!value)
        return null;
    const normalized = value.trim();
    if (!/^\d+$/.test(normalized))
        return null;
    const parsed = Number(normalized);
    if (!Number.isInteger(parsed) || parsed < 1 || parsed > 65535)
        return null;
    return parsed;
}
function resolvePort(env, keys, defaultValue) {
    for (const key of keys) {
        const parsed = parsePortValue(env[key]);
        if (parsed !== null)
            return parsed;
    }
    return defaultValue;
}
function defaultCorsOrigins(frontendPort, env) {
    const origins = [
        'http://localhost:8080',
        'http://localhost:5173',
        'http://localhost:5174',
        `http://localhost:${frontendPort}`,
        'http://127.0.0.1:8080',
        'http://127.0.0.1:5173',
        'http://127.0.0.1:5174',
        `http://127.0.0.1:${frontendPort}`,
    ];
    if (env.FRONTEND_URL)
        origins.push(env.FRONTEND_URL);
    return Array.from(new Set(origins));
}
function resolveServerConfig(env = process.env) {
    const frontendPort = resolvePort(env, [exports.SMARTPERFETTO_FRONTEND_PORT_ENV], exports.DEFAULT_FRONTEND_PORT);
    return {
        /** Server port */
        port: resolvePort(env, [exports.SMARTPERFETTO_BACKEND_PORT_ENV, 'PORT'], exports.DEFAULT_BACKEND_PORT),
        /** Perfetto UI/static frontend port */
        frontendPort,
        /** Browser-visible backend port for generated runtime config. */
        backendPublicPort: resolvePort(env, [
            exports.SMARTPERFETTO_BACKEND_PUBLIC_PORT_ENV,
            exports.SMARTPERFETTO_BACKEND_PORT_ENV,
            'PORT',
        ], exports.DEFAULT_BACKEND_PORT),
        /** Browser-visible backend URL for reverse proxy / HTTPS deployments. */
        backendPublicUrl: env[exports.SMARTPERFETTO_BACKEND_PUBLIC_URL_ENV]
            || env.SMARTPERFETTO_BACKEND_URL
            || '',
        /** Node environment */
        nodeEnv: env.NODE_ENV || 'development',
        /** CORS allowed origins */
        corsOrigins: parseArrayEnv('CORS_ORIGINS', defaultCorsOrigins(frontendPort, env), env),
        /** Request body size limit */
        bodyLimit: env.BODY_LIMIT || '50mb',
    };
}
exports.serverConfig = resolveServerConfig();
// =============================================================================
// Trace Processor Configuration
// =============================================================================
exports.traceProcessorConfig = {
    /** Port pool range for trace processors */
    portRange: {
        min: parseIntEnv('TP_PORT_MIN', 9100),
        max: parseIntEnv('TP_PORT_MAX', 9900),
    },
    /** Perfetto UI origin for CORS */
    perfettoUiOrigin: process.env.PERFETTO_UI_ORIGIN || `http://localhost:${exports.serverConfig.frontendPort}`,
    /** Server startup timeout (ms) */
    startupTimeoutMs: parseIntEnv('TP_STARTUP_TIMEOUT_MS', 30000),
    /** Query execution timeout (ms). Enterprise v1 requires 24h by default. */
    queryTimeoutMs: parseIntEnv('TP_QUERY_TIMEOUT_MS', 24 * 60 * 60 * 1000),
    /** Dedicated health-query timeout (ms); independent from the main SQL queue. */
    healthQueryTimeoutMs: parseIntEnv('TP_HEALTH_QUERY_TIMEOUT_MS', 10000),
    /** TCP accept probe timeout (ms) for trace_processor HTTP RPC health checks. */
    healthRpcAcceptTimeoutMs: parseIntEnv('TP_HEALTH_RPC_ACCEPT_TIMEOUT_MS', 10000),
    /** Process kill timeout (ms) */
    killTimeoutMs: parseIntEnv('TP_KILL_TIMEOUT_MS', 2000),
    /** Stale allocation cleanup age (ms) - default 30 minutes */
    staleAllocationMaxAgeMs: parseIntEnv('TP_STALE_MAX_AGE_MS', 30 * 60 * 1000),
    /**
     * Preload a small critical subset of stdlib modules during processor startup.
     * Keeps key Android views available without blocking startup on full stdlib preload.
     */
    preloadCriticalStdlibModules: parseBoolEnv('TP_PRELOAD_CRITICAL_STDLIB_MODULES', true),
    /**
     * Preload all stdlib modules in the background after processor is marked ready.
     * Disabled by default to reduce upload-to-ready latency.
     */
    preloadAllStdlibModules: parseBoolEnv('TP_PRELOAD_ALL_STDLIB_MODULES', false),
};
// =============================================================================
// Agent Configuration
// =============================================================================
exports.DEFAULT_AGENT_MAX_TURNS = 60;
exports.DEFAULT_AGENT_QUICK_MAX_TURNS = 10;
exports.DEFAULT_AGENT_SESSION_MAX_IDLE_MS = 12 * 60 * 60 * 1000;
exports.DEFAULT_AGENT_SESSION_CLEANUP_INTERVAL_MS = 30 * 60 * 1000;
function resolveAgentRuntimeBudgetConfig(env = process.env) {
    return {
        maxTurns: parsePositiveIntEnv('AGENT_MAX_TURNS', exports.DEFAULT_AGENT_MAX_TURNS, env),
        quickMaxTurns: parsePositiveIntEnv('AGENT_QUICK_MAX_TURNS', exports.DEFAULT_AGENT_QUICK_MAX_TURNS, env),
    };
}
function resolveAgentSessionConfig(env = process.env) {
    const nonTerminalMaxIdleMs = parsePositiveIntEnv('AGENT_NON_TERMINAL_SESSION_MAX_IDLE_MS', exports.DEFAULT_AGENT_SESSION_MAX_IDLE_MS, env);
    return {
        terminalMaxIdleMs: parsePositiveIntEnv('AGENT_TERMINAL_SESSION_MAX_IDLE_MS', exports.DEFAULT_AGENT_SESSION_MAX_IDLE_MS, env),
        nonTerminalMaxIdleMs,
        contextMaxAgeMs: parsePositiveIntEnv('AGENT_SESSION_CONTEXT_MAX_AGE_MS', nonTerminalMaxIdleMs, env),
        cleanupIntervalMs: parsePositiveIntEnv('AGENT_SESSION_CLEANUP_INTERVAL_MS', exports.DEFAULT_AGENT_SESSION_CLEANUP_INTERVAL_MS, env),
    };
}
exports.agentRuntimeBudgetConfig = resolveAgentRuntimeBudgetConfig();
exports.agentSessionConfig = resolveAgentSessionConfig();
exports.agentConfig = {
    /** Maximum total iterations for analysis */
    maxTotalIterations: parseIntEnv('AGENT_MAX_ITERATIONS', 3),
    /** Shared runtime turn budgets; runtime-specific env vars still take precedence. */
    runtimeBudget: exports.agentRuntimeBudgetConfig,
    /** Assistant session retention and cleanup settings. */
    sessions: exports.agentSessionConfig,
    /** Enable trace recording */
    enableTraceRecording: parseBoolEnv('AGENT_ENABLE_TRACE_RECORDING', true),
    /** Evaluation criteria */
    evaluation: {
        /** Minimum quality score to pass (0-1) */
        minQualityScore: parseFloatEnv('AGENT_MIN_QUALITY_SCORE', 0.5),
        /** Minimum completeness score to pass (0-1) */
        minCompletenessScore: parseFloatEnv('AGENT_MIN_COMPLETENESS_SCORE', 0.5),
        /** Maximum allowed contradictions */
        maxContradictions: parseIntEnv('AGENT_MAX_CONTRADICTIONS', 0),
    },
};
// =============================================================================
// Circuit Breaker Configuration
// =============================================================================
exports.circuitBreakerConfig = {
    /** Maximum retries per agent */
    maxRetriesPerAgent: parseIntEnv('CB_MAX_RETRIES_PER_AGENT', 3),
    /** Maximum iterations per stage */
    maxIterationsPerStage: parseIntEnv('CB_MAX_ITERATIONS_PER_STAGE', 5),
    /** Cooldown period after tripping (ms) */
    cooldownMs: parseIntEnv('CB_COOLDOWN_MS', 30000),
    /** Number of attempts in half-open state */
    halfOpenAttempts: parseIntEnv('CB_HALF_OPEN_ATTEMPTS', 1),
    /** Number of failures before tripping */
    failureThreshold: parseIntEnv('CB_FAILURE_THRESHOLD', 3),
    /** Number of successes to close circuit */
    successThreshold: parseIntEnv('CB_SUCCESS_THRESHOLD', 2),
    /** Base delay for exponential backoff (ms) */
    backoffBaseDelayMs: parseIntEnv('CB_BACKOFF_BASE_DELAY_MS', 1000),
    /** Maximum delay for exponential backoff (ms) */
    backoffMaxDelayMs: parseIntEnv('CB_BACKOFF_MAX_DELAY_MS', 30000),
    // === User Intervention Thresholds ===
    /** Timeout waiting for user response (ms) - default 5 minutes */
    userResponseTimeoutMs: parseIntEnv('CB_USER_RESPONSE_TIMEOUT_MS', 5 * 60 * 1000),
    /** Cooldown period between forceClose calls (ms) - default 30 seconds */
    forceCloseCooldownMs: parseIntEnv('CB_FORCE_CLOSE_COOLDOWN_MS', 30000),
    /** Maximum forceClose calls per session */
    maxForceCloseCount: parseIntEnv('CB_MAX_FORCE_CLOSE_COUNT', 5),
    /** Successes needed in half-open state to fully close */
    halfOpenSuccessThreshold: parseIntEnv('CB_HALF_OPEN_SUCCESS_THRESHOLD', 3),
};
// =============================================================================
// Pipeline Configuration
// =============================================================================
exports.pipelineConfig = {
    /** Maximum total duration for entire pipeline (ms) */
    maxTotalDurationMs: parseIntEnv('PIPELINE_MAX_DURATION_MS', 300000),
    /** Enable parallel execution of stages */
    enableParallelization: parseBoolEnv('PIPELINE_ENABLE_PARALLEL', true),
    /** Stage timeouts (ms) */
    stageTimeouts: {
        planner: parseIntEnv('PIPELINE_PLANNER_TIMEOUT_MS', 30000),
        analysis: parseIntEnv('PIPELINE_ANALYSIS_TIMEOUT_MS', 60000),
        evaluation: parseIntEnv('PIPELINE_EVALUATION_TIMEOUT_MS', 30000),
        synthesis: parseIntEnv('PIPELINE_SYNTHESIS_TIMEOUT_MS', 60000),
        decision: parseIntEnv('PIPELINE_DECISION_TIMEOUT_MS', 30000),
    },
    /** Stage max retries */
    stageMaxRetries: {
        planner: parseIntEnv('PIPELINE_PLANNER_MAX_RETRIES', 2),
        analysis: parseIntEnv('PIPELINE_ANALYSIS_MAX_RETRIES', 2),
        evaluation: parseIntEnv('PIPELINE_EVALUATION_MAX_RETRIES', 1),
        synthesis: parseIntEnv('PIPELINE_SYNTHESIS_MAX_RETRIES', 2),
        decision: parseIntEnv('PIPELINE_DECISION_MAX_RETRIES', 1),
    },
    /** Auto-save interval for state machine (ms) */
    autoSaveIntervalMs: parseIntEnv('PIPELINE_AUTO_SAVE_INTERVAL_MS', 5000),
};
// =============================================================================
// Model Router Configuration
// =============================================================================
exports.modelRouterConfig = {
    /** Default model to use */
    defaultModel: process.env.MODEL_DEFAULT || 'glm-5',
    /** Fallback chain for model failures */
    fallbackChain: parseArrayEnv('MODEL_FALLBACK_CHAIN', ['deepseek-reasoner', 'deepseek-chat']),
    /** Enable ensemble mode */
    enableEnsemble: parseBoolEnv('MODEL_ENABLE_ENSEMBLE', false),
    /** Ensemble confidence threshold (0-1) */
    ensembleThreshold: parseFloatEnv('MODEL_ENSEMBLE_THRESHOLD', 0.8),
};
// =============================================================================
// Fork Manager Configuration
// =============================================================================
exports.forkConfig = {
    /** Fork expiration time (ms) - default 24 hours */
    expirationMs: parseIntEnv('FORK_EXPIRATION_MS', 24 * 60 * 60 * 1000),
};
// =============================================================================
// Analysis Configuration (SQL query limits and thresholds)
// =============================================================================
exports.analysisConfig = {
    /** SQL query result limits */
    queryLimits: {
        /** VSYNC interval query limit */
        vsyncInterval: parseIntEnv('QUERY_LIMIT_VSYNC', 500),
        /** Frame data query limit */
        frameData: parseIntEnv('QUERY_LIMIT_FRAME', 1000),
        /** Jank details query limit */
        jankDetails: parseIntEnv('QUERY_LIMIT_JANK', 10),
        /** Slice details query limit */
        sliceDetails: parseIntEnv('QUERY_LIMIT_SLICE', 20),
    },
    /** Frame analysis thresholds (nanoseconds) */
    frameThresholds: {
        /** Default VSYNC period for 60Hz (16.67ms in ns) */
        defaultVsyncPeriodNs: parseIntEnv('FRAME_DEFAULT_VSYNC_NS', 16666666),
        /** Minimum VSYNC interval to consider valid (ns) */
        minVsyncIntervalNs: parseIntEnv('FRAME_MIN_VSYNC_NS', 5000000),
        /** Maximum VSYNC interval to consider valid (ns) */
        maxVsyncIntervalNs: parseIntEnv('FRAME_MAX_VSYNC_NS', 30000000),
        /** Minimum frame duration to consider (ns) */
        minFrameDurationNs: parseIntEnv('FRAME_MIN_DURATION_NS', 5000000),
        /** Maximum frame duration to consider (ns) */
        maxFrameDurationNs: parseIntEnv('FRAME_MAX_DURATION_NS', 20000000),
        /** Minimum slice duration for analysis (ns) */
        minSliceDurationNs: parseIntEnv('SLICE_MIN_DURATION_NS', 1000000),
        /** Frame analyzer minimum duration threshold (ms) */
        minDurationThresholdMs: parseFloatEnv('FRAME_MIN_DURATION_MS', 0.5),
    },
    /** Time windows for analysis (ns) */
    timeWindows: {
        /** Time window around events (ns) - 50ms */
        eventContextNs: parseIntEnv('TIME_WINDOW_EVENT_NS', 50000000),
    },
    /** Minimum counts for statistical validity */
    minCounts: {
        /** Minimum count for slice grouping */
        sliceGrouping: parseIntEnv('MIN_COUNT_SLICE_GROUP', 10),
    },
};
// =============================================================================
// Context Configuration
// =============================================================================
exports.contextConfig = {
    /** Maximum tokens for prompt context */
    maxPromptTokens: parseIntEnv('CONTEXT_MAX_PROMPT_TOKENS', 500),
};
// =============================================================================
// Feature Flags
// =============================================================================
exports.featureFlagsConfig = {
    /** Toggle scene reconstruction endpoints without redeploying code paths */
    enableAgentSceneReconstruct: parseBoolEnv('FEATURE_AGENT_SCENE_RECONSTRUCT', true),
    /** Toggle debug log endpoints */
    enableAgentLogsApi: parseBoolEnv('FEATURE_AGENT_LOGS_API', true),
};
// =============================================================================
// Scene Story Pipeline Configuration
// =============================================================================
exports.sceneStoryConfig = {
    /** JobRunner concurrent analysis jobs */
    analysisConcurrency: parseIntEnv('SCENE_ANALYSIS_CONCURRENCY', 3),
    /** Max retries per job after initial failure */
    jobMaxRetries: parseIntEnv('SCENE_JOB_MAX_RETRIES', 1),
    /** Disk cache TTL for file-backed trace reports */
    reportTtlMs: parseIntEnv('SCENE_REPORT_TTL_MS', 7 * 24 * 60 * 60 * 1000),
    /** Disk store directory for SceneReport JSON (relative to backend cwd) */
    reportDir: process.env.SCENE_REPORT_DIR || 'data/scene-reports',
    /** Disk store directory for out-of-band Smart job artifacts */
    jobArtifactDir: process.env.SCENE_JOB_ARTIFACT_DIR || 'data/scene-job-artifacts',
    /** Process-memory LRU size for external RPC trace reports where no content hash is available */
    memoryCacheMaxSize: parseIntEnv('SCENE_REPORT_MEMORY_CACHE_MAX', 50),
    /** Optional lightweight LLM double-check for ambiguous Smart scene reconstruction */
    llmVerify: parseBoolEnv('SCENE_RECONSTRUCTION_LLM_VERIFY', false),
    /** Timeout for optional scene reconstruction LLM verifier */
    llmVerifyTimeoutMs: parseIntEnv('SCENE_RECONSTRUCTION_LLM_VERIFY_TIMEOUT_MS', 30000),
};
// =============================================================================
// Frontend Configuration (for reference, actual values in frontend)
// =============================================================================
exports.frontendConfig = {
    /** Default backend URL */
    backendUrl: process.env.BACKEND_URL
        || exports.serverConfig.backendPublicUrl
        || `http://localhost:${exports.serverConfig.backendPublicPort}`,
    /** Default Ollama URL */
    ollamaUrl: process.env.OLLAMA_URL || 'http://localhost:11434',
};
// =============================================================================
// Re-export Thresholds Configuration
// =============================================================================
// Re-export all threshold-related types and values for easy access
__exportStar(require("./thresholds"), exports);
// =============================================================================
// Export all configs as single object
// =============================================================================
exports.config = {
    server: exports.serverConfig,
    traceProcessor: exports.traceProcessorConfig,
    agent: exports.agentConfig,
    circuitBreaker: exports.circuitBreakerConfig,
    pipeline: exports.pipelineConfig,
    modelRouter: exports.modelRouterConfig,
    fork: exports.forkConfig,
    analysis: exports.analysisConfig,
    context: exports.contextConfig,
    featureFlags: exports.featureFlagsConfig,
    sceneStory: exports.sceneStoryConfig,
    frontend: exports.frontendConfig,
};
exports.default = exports.config;
//# sourceMappingURL=index.js.map