export type RunStatus = 'pending' | 'running' | 'waiting_user_input' | 'completed' | 'failed' | 'cancelled';
export interface RunQuota {
    maxIterPerNode: number;
    maxLlmCalls: number;
    maxRunDurationMs: number;
}
export type NodeRuntimeState = 'active' | 'completed' | 'failed' | 'skipped';
export interface RunInfo {
    runId: string;
    projectId: string;
    basename: string;
    status: RunStatus;
    startedAt: number;
    quota: RunQuota;
    iterCounts: Map<string, number>;
    llmCallsCount: number;
    cancelAbortController: AbortController;
    error?: {
        nodeId?: string;
        message: string;
    };
    pendingUserInput?: {
        nodeId: string;
        fields: {
            varKey: string;
            description: string;
            uiHint?: string;
            variants?: string[];
        }[];
    };
    snapshot: Record<string, unknown>;
    nodeStates: Map<string, NodeRuntimeState>;
    currentNodeId: string | null;
}
/**
 * In-memory registry of active flow runs.
 *
 * Lock semantics（v-h，原 spec §8.3 修订）：**同一 projectId 同时只允许 1 个 active run**。
 * 原本是 (projectId, basename) 级，但 cwd 文件（`.ccweb-flow-train.json`）是 project
 * 根级一份，不带 basename 区分；如果不同 basename 可并发，两个 flow 会互相覆盖
 * cwd 文件 → `filterByWhitelist` 用本 flow 白名单去过滤别人写的数据 → snapshot
 * 错乱 / outputs 检测假阳。锁升到 projectId 级是最 surgical 的解决（替代方案是
 * cwd 文件名带 basename，但 prompt-translator 系统指令也得改、LLM 不知道是哪个轨）。
 *
 * 重复 register 抛 FLOW_ALREADY_RUNNING（路由层映射为 409 + existingRunId）。
 */
export declare class FlowRunRegistry {
    private byRunId;
    private activeByProject;
    start(opts: {
        runId: string;
        projectId: string;
        basename: string;
        quotaOverride?: Partial<RunQuota>;
    }): RunInfo;
    get(runId: string): RunInfo | undefined;
    findActive(projectId: string, basename?: string): RunInfo | undefined;
    listActive(projectId: string): RunInfo[];
    /**
     * Check & increment quotas. Returns null if all pass, or error message if exceeded.
     * 调用方在每节点循环开始前调一次。
     */
    checkQuotaForNode(runId: string, nodeId: string): string | null;
    checkQuotaBeforeLlmCall(runId: string): string | null;
    /** Return remaining quotas for WS payload (spec §9.5 last bullet). */
    remainingQuota(runId: string, currentNodeId?: string): {
        iterRemaining?: number;
        llmCallsRemaining: number;
        durationRemainingMs: number;
    };
    updateStatus(runId: string, status: RunStatus, error?: RunInfo['error']): void;
    setPendingUserInput(runId: string, payload: RunInfo['pendingUserInput']): void;
    clearPendingUserInput(runId: string): void;
    setSnapshot(runId: string, snapshot: Record<string, unknown>): void;
    setCurrentNode(runId: string, nodeId: string | null): void;
    setNodeState(runId: string, nodeId: string, state: NodeRuntimeState): void;
    cancel(runId: string): boolean;
}
/**
 * Singleton registry instance used by routes / runtime.
 */
export declare const flowRunRegistry: FlowRunRegistry;
/**
 * Cleanup stale cwd train.json / workflow_data.json on daemon startup.
 * spec §9.6：daemon 重启检测到 cwd 文件存在视为"上次 run 异常中断"，删除。
 *
 * Pass a list of project folders to clean.
 */
export declare function cleanupStaleCwdFiles(projectFolders: string[]): void;
//# sourceMappingURL=run-registry.d.ts.map