import { q as SequenceTrackKind, f as SequenceExportFormat, p as SequenceTrack, o as SequenceTimeline, T as TimelineClipBounds, S as SequenceClip, g as SequenceExportRecord, k as SequenceMeta, m as SequenceStore } from './store-gckrNq-g.js';

/**
 * The sequence operation union — the ONE mutation vocabulary shared by every
 * writer of a timeline: the MCP tool dispatcher (agent edits), the React
 * editor's command stack (human edits, undo/redo), and batch agent plans.
 * Positions are integer frames; the seconds→frames conversion happens at the
 * tool-argument edge (./mcp), never here.
 *
 * Validation lives in ./validate (`validateSequenceOperations`) and runs
 * against a `SequenceTimeline` BEFORE any store write; application lives in
 * ./apply (`applySequenceOperation`) which maps one validated operation to
 * `SequenceStore` calls. Keeping the union closed and frame-typed is what lets
 * undo work: every operation has a computable inverse given the pre-state.
 */

interface PlaceClipOperation {
    type: 'place_clip';
    /** Omitted → first unlocked track matching the media kind. */
    trackId?: string;
    label: string;
    startFrame: number;
    durationFrames: number;
    sourceInFrame?: number;
    /** Explicit source out-point; null/omitted → natural end of the source.
     *  Carried so the durable inverse of a delete can restore a split clip's
     *  exact playable window. */
    sourceOutFrame?: number | null;
    /** Create the clip disabled; omitted → enabled. Carried so the durable
     *  inverse of deleting a disabled clip does not resurrect it visible. */
    disabled?: boolean;
    media?: {
        url: string;
        kind: 'video' | 'image' | 'audio';
    };
    generationId?: string;
    assetId?: string;
    metadata?: Record<string, unknown>;
}
interface AddCaptionOperation {
    type: 'add_caption';
    text: string;
    /** BCP-47 tag; omitted → sequence default language. */
    language?: string;
    /** Omitted → placed near the playhead via `chooseCaptionPlacement`. */
    startFrame?: number;
    durationFrames?: number;
    /** Target caption track; omitted → first unlocked caption track, creating
     *  a per-language track when `language` names one that has none. */
    trackId?: string;
}
interface MoveClipOperation {
    type: 'move_clip';
    clipId: string;
    startFrame: number;
    trackId?: string;
}
interface TrimClipOperation {
    type: 'trim_clip';
    clipId: string;
    startFrame: number;
    durationFrames: number;
    /** New source in-point when trimming the head; omitted → unchanged. */
    sourceInFrame?: number;
    /** New source out-point; null releases it to the source's natural end;
     *  omitted → unchanged. Required when extending a clip whose stored window
     *  (e.g. a split head's cut point) is too short for the new duration, and
     *  by the durable inverse of `split_clip` to restore the original window. */
    sourceOutFrame?: number | null;
}
interface SplitClipOperation {
    type: 'split_clip';
    clipId: string;
    /** Sequence-frame to cut at; must fall strictly inside the clip. */
    atFrame: number;
}
interface SetClipTextOperation {
    type: 'set_clip_text';
    clipId: string;
    text: string;
    language?: string;
}
interface SetClipDisabledOperation {
    type: 'set_clip_disabled';
    clipId: string;
    disabled: boolean;
}
interface DeleteClipOperation {
    type: 'delete_clip';
    clipId: string;
}
interface CreateTrackOperation {
    type: 'create_track';
    kind: SequenceTrackKind;
    name: string;
}
interface ExtendSequenceOperation {
    type: 'extend_sequence';
    durationFrames: number;
}
interface QueueExportOperation {
    type: 'queue_export';
    format: SequenceExportFormat;
    metadata?: Record<string, unknown>;
}
type SequenceOperation = PlaceClipOperation | AddCaptionOperation | MoveClipOperation | TrimClipOperation | SplitClipOperation | SetClipTextOperation | SetClipDisabledOperation | DeleteClipOperation | CreateTrackOperation | ExtendSequenceOperation | QueueExportOperation;
/** A batch of operations with the agent's stated intent — the decision-log
 *  unit for agent edits. */
interface SequencePlan {
    summary: string;
    operations: SequenceOperation[];
}
type SequenceOperationType = SequenceOperation['type'];
declare const SEQUENCE_OPERATION_TYPES: readonly SequenceOperationType[];

/**
 * Pre-write validation for sequence operations. Every rule runs against a
 * `SequenceTimeline` snapshot BEFORE any `SequenceStore` write, so a rejected
 * plan leaves no partial state. Batch errors carry the shape
 * `operation N (type): reason` — precise enough for an LLM planner to repair
 * the offending operation and resubmit.
 *
 * The resolution helpers (`resolvePlaceClipTrack`, `resolveCaptionTarget`,
 * `resolveCaptionPlacement`) are shared with ./apply so validation and
 * application cannot disagree about which track or bounds an operation lands
 * on.
 *
 * Validation is static: a batch is checked against the timeline as given, so
 * an operation may not reference entities created by an earlier operation in
 * the same batch. Dispatchers that chain operations must refresh the timeline
 * between applications and validate per-operation.
 */

/** Editor/agent context an operation is resolved against. `playheadFrame` is
 *  the implicit position for omitted caption placement; never persisted. */
interface SequenceOperationContext {
    playheadFrame: number;
}
declare function validateSequenceOperations(timeline: SequenceTimeline, operations: SequenceOperation[], ctx: SequenceOperationContext): void;
declare function validateSequenceOperation(timeline: SequenceTimeline, operation: SequenceOperation, ctx: SequenceOperationContext): void;
declare function validatePlaceClip(timeline: SequenceTimeline, operation: PlaceClipOperation): void;
declare function validateAddCaption(timeline: SequenceTimeline, operation: AddCaptionOperation, ctx: SequenceOperationContext): void;
declare function validateMoveClip(timeline: SequenceTimeline, operation: MoveClipOperation): void;
declare function validateTrimClip(timeline: SequenceTimeline, operation: TrimClipOperation): void;
declare function validateSplitClip(timeline: SequenceTimeline, operation: SplitClipOperation): void;
declare function validateSetClipText(timeline: SequenceTimeline, operation: SetClipTextOperation): void;
declare function validateSetClipDisabled(timeline: SequenceTimeline, operation: SetClipDisabledOperation): void;
declare function validateDeleteClip(timeline: SequenceTimeline, operation: DeleteClipOperation): void;
declare function validateCreateTrack(operation: CreateTrackOperation): void;
declare function validateExtendSequence(timeline: SequenceTimeline, operation: ExtendSequenceOperation): void;
declare function validateQueueExport(operation: QueueExportOperation): void;
/**
 * Shape-gate untrusted JSON (a product's `onApplyOperations` route body) into
 * `SequenceOperation[]` BEFORE `validateSequenceOperations` sees it. The
 * validator assumes well-typed fields (`label.trim()` on a number is a raw
 * TypeError → 500); this parser turns junk into a thrown Error naming the
 * operation index and field so the route can answer 400 with an actionable
 * reason. Unknown fields are dropped — only vocabulary fields reach the
 * validator and store.
 */
declare function parseSequenceOperations(input: unknown): SequenceOperation[];
type CaptionTargetResolution = {
    kind: 'existing';
    track: SequenceTrack;
} | {
    kind: 'create';
    language: string;
    name: string;
};
/** Naming convention for auto-created per-language caption tracks. The name
 *  doubles as the recognition rule because `SequenceStore.createTrack` cannot
 *  persist track metadata — matching by `metadata.language` alone would never
 *  find tracks this module created. */
declare function captionTrackNameForLanguage(language: string): string;
/** Target track for a `place_clip`. Video and image media land on video
 *  tracks, audio media on audio tracks; a `reference` track is valid only when
 *  targeted explicitly. Media-less clips (placeholders, agent markers) need an
 *  explicit trackId because no kind can be inferred. */
declare function resolvePlaceClipTrack(timeline: SequenceTimeline, operation: PlaceClipOperation): SequenceTrack;
/** Target caption track for an `add_caption`. With `language` set and no
 *  matching caption track, resolution returns a `create` instruction the apply
 *  layer turns into a real track — a locked matching track is an error, never
 *  a silent duplicate. */
declare function resolveCaptionTarget(timeline: SequenceTimeline, operation: AddCaptionOperation): CaptionTargetResolution;
/** Caption bounds. Fully omitted placement slides past occupied intervals via
 *  `chooseCaptionPlacement`; a partially explicit placement fills the missing
 *  half deterministically (startFrame ← playhead, durationFrames ← fps*3) and
 *  must pass the caller's bounds check — no collision slide. */
declare function resolveCaptionPlacement(timeline: SequenceTimeline, operation: AddCaptionOperation, ctx: SequenceOperationContext, targetTrackId: string | null): TimelineClipBounds;
/** Last occupied frame across all clips — the floor for `extend_sequence`. */
declare function lastClipEndFrame(timeline: SequenceTimeline): number;
/** Media references must be provider URLs or app-served paths. Local sandbox
 *  artifacts (file:, data:, /tmp/, /home/) are rejected because they are
 *  unreachable from the product and signal an agent substituting local ffmpeg
 *  output for real provider generation. Delegates to the canonical
 *  `assertMediaUrl` boundary in `../web` — sequences and design-canvas share ONE
 *  rule so the two surfaces cannot drift on what counts as a reachable url. */
declare function assertSequenceMediaUrl(url: string): void;

/**
 * Maps one validated `SequenceOperation` to `SequenceStore` calls and reports
 * what changed. Each call re-validates its single operation against the
 * provided timeline — a dispatcher that skips batch validation still cannot
 * reach the store with an invalid write. The timeline must be the CURRENT
 * state: dispatchers applying a batch refresh it between operations so later
 * operations can reference entities earlier ones created.
 *
 * Split assumes source frames advance 1:1 with sequence frames (the model
 * addresses source in/out points at sequence fps); time-remapped clips are
 * outside this operation vocabulary.
 */

/**
 * The entity an operation changed, for the MCP layer to serialize back to the
 * agent. Conventions for multi-entity operations:
 * - `split_clip` returns the newly created second half (the first half is the
 *   original clip id with a shortened duration).
 * - `delete_clip` returns the pre-delete clip snapshot.
 */
type SequenceApplyResult = {
    kind: 'clip';
    clip: SequenceClip;
} | {
    kind: 'track';
    track: SequenceTrack;
} | {
    kind: 'export';
    record: SequenceExportRecord;
} | {
    kind: 'sequence';
    sequence: SequenceMeta;
};
/**
 * The batch path every dispatcher (the MCP tools, a product's editor
 * persistence route) funnels through: fetch the timeline, validate the WHOLE
 * batch against pre-state, then apply in order with a timeline refresh between
 * operations — later operations must see earlier writes (the static-validation
 * boundary in ./validate).
 *
 * Atomicity contract: validation throws (before the first store write) leave
 * the sequence untouched. Store-layer throws after at least one successful
 * write leave a prefix-committed state — operations 1..N-1 are persisted,
 * operations N..end are not. The store is non-transactional (SQLite D1);
 * callers that receive a partial-commit throw must treat the result as partial
 * success, not a full rollback. Decision-log rows are the caller's job: the
 * MCP layer records `agent_edit`, an editor route records `human_edit`.
 */
declare function applySequenceOperations(store: SequenceStore, operations: SequenceOperation[], ctx: SequenceOperationContext): Promise<SequenceApplyResult[]>;
declare function applySequenceOperation(store: SequenceStore, timeline: SequenceTimeline, op: SequenceOperation, ctx: SequenceOperationContext): Promise<SequenceApplyResult>;

export { type AddCaptionOperation as A, validateSequenceOperations as B, type CaptionTargetResolution as C, type DeleteClipOperation as D, type ExtendSequenceOperation as E, validateSetClipDisabled as F, validateSetClipText as G, validateSplitClip as H, validateTrimClip as I, type MoveClipOperation as M, type PlaceClipOperation as P, type QueueExportOperation as Q, SEQUENCE_OPERATION_TYPES as S, type TrimClipOperation as T, type CreateTrackOperation as a, type SequenceApplyResult as b, type SequenceOperation as c, type SequenceOperationContext as d, type SequenceOperationType as e, type SequencePlan as f, type SetClipDisabledOperation as g, type SetClipTextOperation as h, type SplitClipOperation as i, applySequenceOperation as j, applySequenceOperations as k, assertSequenceMediaUrl as l, captionTrackNameForLanguage as m, lastClipEndFrame as n, resolveCaptionTarget as o, parseSequenceOperations as p, resolvePlaceClipTrack as q, resolveCaptionPlacement as r, validateCreateTrack as s, validateDeleteClip as t, validateExtendSequence as u, validateAddCaption as v, validateMoveClip as w, validatePlaceClip as x, validateQueueExport as y, validateSequenceOperation as z };
