import { join } from 'node:path';
import { PlanManager } from '../../manager/plan/lifecycle.js';
import { RunPersistence } from '../../manager/run/persistence.js';
import { DefaultFilesystemMigrator, NOOP_FILESYSTEM_MIGRATION_SINK, } from '../../session/migration/index.js';
import { DefaultPathBuilder } from '../../session/workspace/path-builder.js';
import { ActivityStore } from '../../store/activity/memory.js';
import { resolveActivityTracking } from '../../types/activity/index.js';
import { generateRunId } from '../../utils/id.js';
import { getRootLogger } from '../../utils/logger.js';
/**
 * Module-level first-call guard for the boot-time filesystem migration
 * (session-hierarchy.md §13.4.1). Keyed on the root directory so a single
 * process that spans multiple `.namzu` roots (unusual but legal) migrates
 * each one once. Subsequent calls short-circuit via the cached promise —
 * never re-reading the on-disk marker per call.
 */
const migrationPromises = new Map();
export class RunContextFactory {
    /**
     * Run the boot-time filesystem migration for `rootDir` at most once per
     * process. Safe to `await` from any async entry point; concurrent callers
     * for the same root share a single migration promise (no duplicate work,
     * no race with the on-disk `.tmp` lock).
     */
    static ensureMigrated(rootDir, migrator = new DefaultFilesystemMigrator(NOOP_FILESYSTEM_MIGRATION_SINK)) {
        const cached = migrationPromises.get(rootDir);
        if (cached)
            return cached;
        const promise = migrator.migrate(rootDir);
        migrationPromises.set(rootDir, promise);
        // Crash-safety: if the migration rejects, drop the cached promise so
        // the next caller gets a fresh attempt. Successful results stay cached
        // (idempotency — further calls short-circuit without re-running).
        promise.catch(() => {
            migrationPromises.delete(rootDir);
        });
        return promise;
    }
    static build(config) {
        const abortController = new AbortController();
        if (config.signal) {
            config.signal.addEventListener('abort', () => abortController.abort(), { once: true });
        }
        const cwd = config.workingDirectory ?? process.cwd();
        const permissionMode = config.runConfig.permissionMode ?? 'auto';
        const runId = config.runId ?? generateRunId();
        const pathBuilder = config.pathBuilder ?? new DefaultPathBuilder(join(cwd, '.namzu'));
        const outputDir = pathBuilder.sessionDir(config.projectId, config.sessionId);
        const runsDir = join(outputDir, 'runs');
        const log = getRootLogger().child({
            component: 'query',
            agent: config.agentName,
            runId,
            sessionId: config.sessionId,
            threadId: config.threadId,
            projectId: config.projectId,
            tenantId: config.tenantId,
        });
        const runMgr = new RunPersistence({
            runId,
            agentId: config.agentId,
            agentName: config.agentName,
            runConfig: config.runConfig,
            providerId: config.provider.id,
            outputDir: runsDir,
            pricing: config.pricing,
            log,
            sessionId: config.sessionId,
            threadId: config.threadId,
            tenantId: config.tenantId,
            projectId: config.projectId,
            parentRunId: config.parentRunId,
            depth: config.depth,
        });
        const trackingConfig = resolveActivityTracking(permissionMode, config.enableActivityTracking);
        const activityStore = new ActivityStore(runId, trackingConfig);
        const planManager = new PlanManager(runId);
        return {
            runId,
            sessionId: config.sessionId,
            threadId: config.threadId,
            projectId: config.projectId,
            tenantId: config.tenantId,
            runMgr,
            activityStore,
            planManager,
            abortController,
            cwd,
            outputDir,
            permissionMode,
            log,
            trackingConfig,
        };
    }
}
//# sourceMappingURL=context.js.map