import { Z as FlowNode, a2 as FlowNodeAuthzExtension, X as FlowNodeRuntimeState, W as IxoEditorType, f as UcanService, I as InvocationStore, a0 as EvaluationStatus, i as UcanCapability, U as UcanDelegationStore, S as StoredDelegation } from './index-C0ikjICf.mjs';
import * as Y from 'yjs';
import { Doc, Map } from 'yjs';
import { MatrixClient } from 'matrix-js-sdk';

/** Condition that gates when a capability activates. */
interface ConditionRef {
    /** ID of the upstream capability whose output is checked. */
    sourceId: string;
    /** Output field path to inspect, e.g., "decision". */
    field: string;
    /** Comparison operator. */
    operator: 'eq' | 'neq' | 'gt' | 'lt' | 'in' | 'exists';
    /** Value to compare against (omit for 'exists'). */
    value?: unknown;
    /** What happens when the condition is (not) met. */
    effect?: {
        action: 'enable' | 'disable' | 'hide' | 'show';
        message?: string;
    };
}
/** Authorization constraint for a capability. */
interface ActorConstraint {
    /** Whitelisted actor DIDs. */
    authorisedActors?: string[];
    /** Parent capability URI for delegation chain. */
    parentCapability?: string;
}
/** Time-to-live constraint for a capability. */
interface TTLConstraint {
    /** Hard deadline (ISO 8601 date string). */
    absoluteDueDate?: string;
    /** Duration from when the block becomes enabled (ISO 8601 duration, e.g., "P7D"). */
    fromEnablement?: string;
    /** Duration from when an actor commits (ISO 8601 duration, e.g., "PT2H"). */
    fromCommitment?: string;
}
/**
 * A single capability in a Base UCAN flow plan.
 *
 * UCAN semantics:
 *   can  = the action
 *   with = the resource or scope
 *   nb   = typed caveats, inputs, parameters
 *
 * Workflow semantics (kept separate from nb):
 *   condition, trigger, parallelGroup, phase
 */
interface FlowCapability {
    /** Stable node identifier for this step. */
    id: string;
    /** UCAN-style ability string, e.g., "bid/submit", "email/send". */
    can: string;
    /** Resource URI, e.g., "ixo:flow:{flowId}" or "ixo:flow:{flowId}:{nodeId}". */
    with: string;
    /** Typed caveats / input parameters. Shape is dictated by the action registry. */
    nb?: Record<string, unknown>;
    /** Condition that must be met for this capability to activate. */
    condition?: ConditionRef;
    /** Capabilities sharing a parallelGroup run concurrently. */
    parallelGroup?: string;
    /** Semantic grouping for layout lanes. */
    phase?: string;
    /** Who can execute this step. */
    actor?: ActorConstraint;
    /** Time-to-live constraints. */
    ttl?: TTLConstraint;
    /**
     * When and how this block fires. Defaults to `{ type: 'manual' }` if absent
     * (i.e. block runs only when a user explicitly invokes it).
     *
     * `block.event` triggers turn this block into a listener: when the source
     * block emits an event matching `eventName`, a pending invocation is
     * queued on this block and the assigned actor is DM'd to invoke it. See
     * `docs/events-and-triggers-plan.md` §3.7 and §18 for the full model.
     *
     * Triggers are a NEW sibling field on FlowCapability (decided in eng review
     * pass 2 phase 0 #1). They are NOT an extension of `condition`. The decompile
     * branch's author needs to add `props.trigger` parsing when their work merges.
     */
    trigger?: TriggerSpec;
    /** Display title (falls back to can statement). */
    title?: string;
    /** Description of what this step does. */
    description?: string;
    /** Icon identifier. */
    icon?: string;
}
/**
 * Trigger declaration for a block. When and how it fires.
 */
/** A single event source in a barrier trigger. */
interface TriggerSource {
    /** ID of the block that emits the event. */
    sourceBlockId: string;
    /** Name of the event (must match an event declared on the source action's `events` vocabulary). */
    eventName: string;
    /** Namespace alias for payload access: `trigger.payload.<alias>.*` */
    alias: string;
}
interface TriggerSpec {
    /**
     * - `manual`: block runs only when a user explicitly invokes it (default).
     * - `flow.start`: block runs when the flow execution begins.
     * - `block.event`: block runs each time another block emits a matching event.
     * - `block.event.all`: block runs once ALL listed sources have emitted (barrier/join).
     */
    type: 'manual' | 'flow.start' | 'block.event' | 'block.event.all';
    /** Required when `type === 'block.event'`. ID of the block that emits the event. */
    sourceBlockId?: string;
    /** Required when `type === 'block.event'`. Name of the event (must match an event declared on the source action's `events` vocabulary). */
    eventName?: string;
    /** Required when `type === 'block.event.all'`. Array of event sources — ALL must fire before the listener is queued. */
    sources?: TriggerSource[];
}
/**
 * The Base UCAN flow plan — the intermediate representation between
 * user intent and the compiled flow graph.
 *
 * capabilities is an ordered list. Each capability carries its own stable `id`.
 */
interface BaseUcanFlow {
    kind: 'qi.flow.base-ucan';
    version: '1.0';
    flowId: string;
    title: string;
    goal?: string;
    meta?: {
        entityDid?: string;
        flowUri?: string;
        rootIssuer?: string;
    };
    /** Ordered capabilities, each with its own stable node ID. */
    capabilities: FlowCapability[];
}
/** A reference to an upstream node's output field. Format: "nodeId.output.fieldPath" */
interface RuntimeRef {
    $ref: string;
}
declare function isRuntimeRef(value: unknown): value is RuntimeRef;
/** A single block ready for insertion into BlockNote. */
interface CompiledBlock {
    /** Pre-generated stable block ID. */
    id: string;
    /** BlockNote block type (e.g., "action"). */
    type: string;
    /** Block props — all values are strings per BlockNote convention. */
    props: Record<string, string>;
}
/**
 * An edge in the flow graph. Currently only `kind: 'trigger'` edges are
 * synthesized — they come from `block.event` triggers and represent the
 * source → listener relationship visually on the canvas.
 */
interface CompiledEdge {
    id: string;
    source: string;
    target: string;
    kind: 'trigger';
    condition?: ConditionRef;
}
/** A compiled flow node stored in qi.flow.nodes. */
interface CompiledFlowNode {
    id: string;
    blockId: string;
    can: string;
    with: string;
    registryType: string;
    title: string;
    description: string;
    props: Record<string, string>;
    phase?: string;
    parallelGroup?: string;
    actor?: ActorConstraint;
}
/** The complete compiled output from the Base UCAN compiler. */
interface CompiledFlow {
    /** Flow metadata for qi.flow.meta and Y.Map('root'). */
    meta: {
        flowId: string;
        title: string;
        goal?: string;
        version: string;
        flowOwnerDid: string;
        flowUri?: string;
        compiledAt: string;
        compiledFrom: 'BaseUcanFlow';
    };
    /** Blocks to insert into BlockNote, in topological order. */
    blocks: CompiledBlock[];
    /** Flow graph nodes, keyed by node ID. */
    nodes: Record<string, CompiledFlowNode>;
    /** Dependency edges. */
    edges: CompiledEdge[];
    /** Topological order of node IDs. */
    order: string[];
    /** nodeId → blockId mapping. */
    blockIndex: Record<string, string>;
}
/** Strategy for how a compiled flow is applied to an existing document. */
type FlowStrategy = 'full' | 'merge' | 'patch';

declare const buildAuthzFromProps: (props: Record<string, any>) => FlowNodeAuthzExtension;
declare const buildFlowNodeFromBlock: (block: any) => FlowNode;

interface FlowRuntimeStateManager {
    get: (nodeId: string) => FlowNodeRuntimeState;
    update: (nodeId: string, updates: Partial<FlowNodeRuntimeState>) => void;
}
declare const createRuntimeStateManager: (editor?: IxoEditorType | null) => FlowRuntimeStateManager;
/**
 * Clears runtime, invocations, and pending invocations from a Y.Doc.
 * Used when cloning a flow as a template — the new document should
 * carry only configuration (intent), not execution history.
 *
 * The audit trail (which now also holds run records as `type: 'block.run'`
 * entries) and pending invocations are observation, not configuration —
 * both are cleared on template clone.
 */
declare function clearRuntimeForTemplateClone(yDoc: Doc): void;

interface NodeActionResult {
    claimId?: string;
    evaluationStatus?: EvaluationStatus;
    submittedByDid?: string;
    payload?: any;
}
interface ExecutionContext {
    runtime: FlowRuntimeStateManager;
    /** UCAN service — optional for v0.x flows, required for v1.0.0+ */
    ucanService?: UcanService;
    /** Invocation store — optional for v0.x flows */
    invocationStore?: InvocationStore;
    flowUri: string;
    flowId: string;
    flowOwnerDid: string;
    /** Flow schema version. When set, controls whether UCAN is enforced. */
    schemaVersion?: string;
    now?: () => number;
}
interface ExecutionOutcome {
    success: boolean;
    stage: 'authorization' | 'claim' | 'action' | 'complete';
    error?: string;
    result?: NodeActionResult;
    capabilityId?: string;
    invocationCid?: string;
}
interface ExecuteNodeParams {
    node: FlowNode;
    actorDid: string;
    actorType: 'entity' | 'user';
    entityRoomId?: string;
    context: ExecutionContext;
    action: () => Promise<NodeActionResult>;
    pin: string;
}
/**
 * Execute a node.
 *
 * The pipeline adapts based on the flow's schema version (via context.schemaVersion):
 *
 * **v0.x (legacy):** activation → action → runtime update.
 * UCAN authorization and invocations are skipped when ucanService is not available.
 *
 * **v1.0.0+:** activation → UCAN authorization → invocation → action → runtime update.
 * Requires a configured ucanService with valid delegation chains.
 */
declare const executeNode: ({ node, actorDid, actorType, entityRoomId, context, action, pin }: ExecuteNodeParams) => Promise<ExecutionOutcome>;

interface AuthorizationResult {
    authorized: boolean;
    reason?: string;
    capabilityId?: string;
    proofCids?: string[];
}
/**
 * Check if an actor is authorized to execute a block.
 *
 * Behaviour depends on the flow's schema version:
 * - v0.x (or no version): UCAN is optional. If ucanService is unavailable,
 *   execution is allowed without a delegation chain.
 * - v1.0.0+: UCAN is required. A valid delegation chain must exist.
 */
declare const isAuthorized: (blockId: string, actorDid: string, ucanService: UcanService | undefined, flowUri: string, schemaVersion?: string) => Promise<AuthorizationResult>;

interface ActionContext {
    actorDid: string;
    flowId: string;
    nodeId: string;
    services: ActionServices;
    flowNode?: any;
    runtime?: any;
    flowUri?: string;
    handlers?: any;
    editor?: any;
}
interface ActionServices {
    http?: {
        request: (params: {
            url: string;
            method: string;
            headers?: Record<string, string>;
            body?: any;
        }) => Promise<{
            status: number;
            headers: Record<string, string>;
            data: any;
        }>;
    };
    email?: {
        send: (params: {
            to: string;
            subject: string;
            template: string;
            templateVersion?: string;
            variables?: Record<string, any>;
            cc?: string;
            bcc?: string;
            replyTo?: string;
        }) => Promise<{
            messageId: string;
            sentAt: string;
        }>;
    };
    notify?: {
        send: (params: {
            channel: string;
            to: string[];
            cc?: string[];
            bcc?: string[];
            subject?: string;
            body?: string;
            bodyType?: 'text' | 'html';
            from?: string;
            replyTo?: string;
        }) => Promise<{
            messageId: string;
            sentAt: string;
        }>;
    };
    bid?: {
        submitBid: (params: {
            collectionId: string;
            role: string;
            surveyAnswers: Record<string, any>;
        }) => Promise<any>;
        approveBid: (params: {
            bidId: string;
            collectionId: string;
            did: string;
        }) => Promise<any>;
        rejectBid: (params: {
            bidId: string;
            collectionId: string;
            did: string;
            reason: string;
        }) => Promise<any>;
        approveServiceAgentApplication: (params: {
            adminAddress: string;
            collectionId: string;
            agentQuota: number;
            deedDid: string;
            currentUserAddress: string;
        }) => Promise<void>;
        approveEvaluatorApplication: (params: {
            adminAddress: string;
            collectionId: string;
            deedDid: string;
            evaluatorAddress: string;
            agentQuota?: number;
            claimIds?: string[];
            maxAmounts?: Array<{
                denom: string;
                amount: string;
            }>;
        }) => Promise<void>;
    };
    claim?: {
        requestPin: (config?: {
            title?: string;
            description?: string;
            submitText?: string;
        }) => Promise<string>;
        submitClaim: (params: {
            surveyData: any;
            deedDid: string;
            collectionId: string;
            adminAddress: string;
            pin: string;
        }) => Promise<{
            transactionHash: string;
            claimId: string;
        }>;
        evaluateClaim: (granteeAddress: string, did: string, payload: {
            claimId: string;
            collectionId: string;
            adminAddress: string;
            status?: number;
            verificationProof: string;
            amount?: {
                denom: string;
                amount: string;
            };
        }) => Promise<{
            code: number;
            transactionHash: string;
            rawLog?: string;
            height?: number;
            txIndex?: number;
            gasWanted?: bigint;
            gasUsed?: bigint;
        }>;
        disputeClaim?: (granteeAddress: string, did: string, payload: {
            subjectId: string;
            disputeType: number;
            reason: string;
        }) => Promise<any>;
        getCurrentUser: () => {
            address: string;
        };
        createUdid?: (params: any) => Promise<any>;
    };
    matrix?: {
        storeCredential: (params: {
            roomId: string;
            credentialKey: string;
            credential: Record<string, any>;
            cid: string;
        }) => Promise<{
            storedAt: string;
            duplicate: boolean;
        }>;
    };
    integrations?: {
        executeTool: (args: {
            toolSlug: string;
            connectedAccountId: string;
            arguments: Record<string, unknown>;
        }) => Promise<{
            successful: boolean;
            data?: Record<string, unknown>;
            error?: string;
            code?: 'OK' | 'VALIDATION' | 'AUTH_EXPIRED' | 'UPSTREAM_4XX' | 'UPSTREAM_5XX' | 'RATE_LIMIT' | 'UNKNOWN';
        }>;
        fetchCurrentState?: (args: {
            toolSlug: string;
            connectedAccountId: string;
            arguments: Record<string, unknown>;
        }) => Promise<Record<string, unknown>>;
        getEntityDid?: () => string | undefined;
    };
    oracle?: {
        generateWallet: () => Promise<{
            address: string;
            did: string;
            pubKey: string;
            mnemonic: string;
        }>;
        fundWallet: (params: {
            address: string;
            amount: number;
        }) => Promise<{
            transactionHash: string;
        }>;
        createIidDocument: (params: {
            mnemonic: string;
            did: string;
            address: string;
            pubKey: string;
        }) => Promise<{
            did: string;
            transactionHash: string;
        }>;
        registerMatrixAccount: (params: {
            mnemonic: string;
            address: string;
            did: string;
            pin: string;
            oracleName: string;
            avatarUrl?: string;
        }) => Promise<{
            matrixUserId: string;
            matrixAccessToken: string;
            matrixRoomId: string;
            matrixDeviceId: string;
            matrixMnemonic: string;
            matrixPassword: string;
            matrixRecoveryPhrase: string;
            matrixHomeServerUrl: string;
        }>;
        createOracleEntity: (params: {
            mnemonic: string;
            address: string;
            did: string;
            pubKey: string;
            pin: string;
            matrixAccessToken: string;
            matrixRoomId: string;
            oracleName: string;
            orgName: string;
            description: string;
            location: string;
            logoUrl: string;
            coverImageUrl: string;
            apiUrl: string;
            price: number;
            llmModel: string;
            opening?: string;
            communicationStyle?: string;
            capabilities?: string;
            mcpConfig?: any;
            parentProtocol?: string;
        }) => Promise<{
            entityDid: string;
            transactionHash: string;
            /** Multibase-encoded P-256 public key registered as a keyAgreement vm on the oracle entity DID. */
            encryptionPublicKeyMultibase: string;
            /** DID verification method id of the P-256 keyAgreement key. */
            encryptionVerificationMethodId: string;
        }>;
        /**
         * Contract the oracle: ensure the user↔oracle Matrix DM room exists and
         * the user has joined it. Pure Matrix work — no chain calls, no key setup.
         * Returns the user↔oracle room id which downstream steps (storeSecrets,
         * storeConfig) write into.
         */
        contract: (params: {
            oracleEntityDid: string;
        }) => Promise<{
            userOracleRoomId: string;
            userOracleRoomAlias: string;
        }>;
        provisionSandbox: (params: {
            entityDid: string;
            matrixRoomId: string;
        }) => Promise<{
            sandboxUrl: string;
            status: string;
        }>;
        storeSecrets: (params: {
            matrixRoomId: string;
            publicKeyMultibase: string;
            verificationMethodId: string;
            matrixHomeServerUrl: string;
            matrixUsername: string;
            matrixPassword: string;
            secrets: Record<string, string>;
            preEncryptedSecrets?: Record<string, string>;
        }) => Promise<{
            storedSecrets: string[];
            roomId: string;
            freshAccessToken?: string;
        }>;
        /** JWE-encrypts a single plaintext value to the oracle's P-256 public key (multibase).
         *  Used by storeSecrets FlowDetail to encrypt user-typed OpenRouter key at-rest. */
        encryptForOracle: (params: {
            plaintext: string;
            publicKeyMultibase: string;
        }) => Promise<{
            jwe: string;
        }>;
        /** Reads `ixo.room.secret.index` state events from the matrix room and returns the
         *  list of secret names already stored. Used for idempotency checks. */
        readStoredSecrets: (params: {
            matrixRoomId: string;
        }) => Promise<{
            secretNames: string[];
        }>;
        /** Returns the network-derived .env constants (RPC URL, matrix homeserver, etc.)
         *  for the consumer's currently configured network. Used by the storeSecrets
         *  FlowDetail's "Additional Configuration" display section, and merged into the
         *  storeConfig state event by the consumer handler. Must be deterministic per network. */
        getNetworkConstants: (params: {
            oracleName: string;
        }) => Promise<{
            constants: Record<string, string>;
        }>;
        validateMcpServer: (params: {
            url: string;
            authType?: 'bearer' | 'api-key' | 'none';
            authToken?: string;
        }) => Promise<{
            success: boolean;
            tools?: Array<{
                name: string;
                description?: string;
            }>;
            error?: string;
        }>;
        storeConfig: (params: {
            matrixRoomId: string;
            config: {
                oracleName: string;
                orgName: string;
                description: string;
                location: string;
                price: number;
                apiUrl: string;
                entityDid: string;
                logoUrl: string;
                llmModel: string;
                opening?: string;
                communicationStyle?: string;
                capabilities?: string;
                skills?: string[];
                mcpServers?: Array<{
                    name: string;
                    url: string;
                    description?: string;
                    authEnvVar?: string;
                }>;
                matrixUserId?: string;
                matrixAccountRoomId?: string;
                oracleAddress?: string;
                oracleDid?: string;
            };
        }) => Promise<{
            configStored: boolean;
            roomId: string;
        }>;
        deploySetup: (params: {
            name: string;
            config: Record<string, any>;
            roomId: string;
            secrets?: Record<string, string>;
        }) => Promise<{
            setupComplete: boolean;
            stdout?: string;
            stderr?: string;
        }>;
        deployStart: (params: {
            name: string;
            entityDid: string;
            roomId: string;
            secrets?: Record<string, string>;
        }) => Promise<{
            processId: string;
            status: string;
            url?: string;
        }>;
        updateOracleDomain: (params: {
            entityDid: string;
            newApiUrl: string;
        }) => Promise<{
            transactionHash: string;
        }>;
    };
}
interface OutputSchemaField {
    path: string;
    displayName: string;
    type: 'string' | 'number' | 'boolean' | 'object' | 'array';
    description?: string;
    /**
     * For `type === 'array'`: the shape of each element. Drives item-scoped
     * reference pickers (e.g. the Xero invoice LineItems iterative mapper,
     * where each cell refs into `{{item.<field>}}`).
     */
    itemSchema?: OutputSchemaField[];
}
/**
 * A typed event that an action can emit when it runs.
 *
 * Events drive the trigger/listener model: another block can declare a
 * `block.event` trigger on a (sourceBlockId, eventName) pair, and when this
 * action emits a matching event, a pending invocation is queued on the
 * listener block. See `docs/events-and-triggers-plan.md` for the full model.
 */
interface ActionEventDefinition {
    /** Stable identifier — used in trigger declarations and ref strings. */
    name: string;
    /** Human-readable label shown in the trigger picker UI. */
    displayName: string;
    /** Short description shown as inline hint in the trigger picker. */
    description: string;
    /** Schema of the event payload. Same shape as `outputSchema`. */
    payloadSchema: OutputSchemaField[];
    /**
     * Field paths from `payloadSchema` (in order) shown inline in the
     * pending-invocation list so the assignee can distinguish queued
     * invocations at a glance. E.g. `['claimId', 'evaluatedAt']`.
     */
    pendingDisplayFields?: string[];
}
interface ActionDefinition<TInputs extends Record<string, any> = Record<string, any>> {
    type: string;
    /** UCAN-style ability string used by the flow compiler, e.g., "bid/submit". */
    can?: string;
    sideEffect: boolean;
    defaultRequiresConfirmation: boolean;
    requiredCapability?: string;
    inputSchema?: object;
    /** Static output schema for action types with predictable output (e.g. email.send).
     *  For action types with dynamic output (e.g. http.request), the schema is user-defined in inputs. */
    outputSchema?: OutputSchemaField[];
    /**
     * Typed vocabulary of events this action can emit. Drives the trigger
     * picker UI and compile-time validation of `block.event` triggers.
     */
    events?: ActionEventDefinition[];
    /**
     * Optional per-block event resolver. Called with the block's current
     * template inputs; returns the event vocabulary that applies to this
     * specific block.
     *
     * Use this when the event schema depends on configuration the designer
     * picks at template time. For example, `qi/claim.submit` only knows the
     * shape of `surveyAnswers` once a claim collection has been chosen —
     * returning `[]` until then hides the block from the trigger picker.
     *
     * Consumers (trigger picker, flow compiler, event payload picker) prefer
     * `getDynamicEvents(inputs)` when defined and fall back to static `events`
     * otherwise. The contract is: whatever this returns **is** the event list
     * for the block — it does not merge with `events`. Include the static
     * baseline yourself if you want it.
     */
    getDynamicEvents?: (inputs: TInputs) => ActionEventDefinition[];
    /**
     * Optional per-block output-schema resolver. Symmetric to `getDynamicEvents`
     * but for `outputSchema` — drives the reference picker for `${block.field}`
     * refs so survey-derived fields like `output.surveyAnswers.<question>` show
     * up alongside the static baseline.
     *
     * Returned array **replaces** `outputSchema` for this specific block (no
     * merging). Include the baseline fields yourself.
     */
    getDynamicOutputSchema?: (inputs: TInputs) => OutputSchemaField[];
    /**
     * Whether this action can be wired to a `block.event` trigger.
     * False (the default) for user-interaction-driven actions like forms,
     * claims, and evaluations — they always run as `manual`. True for actions
     * where it makes sense for an event to nudge a human assignee to invoke
     * them (email, http, notify).
     *
     * The trigger picker UI is hidden for blocks whose action type has this
     * set to false.
     */
    eligibleForEventTrigger?: boolean;
    run: (inputs: TInputs, ctx: ActionContext) => Promise<ActionResult>;
}
/**
 * Result returned by an action's `run()` function.
 *
 * The optional `events` array is the explicit emission surface — actions
 * declare which named events they're emitting on this particular run, with
 * the payload by value. The runtime persists these as part of the run record
 * and the reconciliation loop turns them into pending invocations on
 * subscribed listener blocks.
 */
interface ActionResult {
    output: Record<string, any>;
    events?: Array<{
        name: string;
        payload: Record<string, any>;
    }>;
}

/** Registry interface expected by the compiler (keeps it pure / testable). */
interface CompilerRegistry {
    getActionByCan(can: string): ActionDefinition | undefined;
}
/**
 * Compile a Base UCAN flow plan into blocks, graph state, and metadata.
 *
 * This is a **pure function** — no React, no Yjs, no side effects.
 * The output is consumed by `hydrateFlowFromPlan()`.
 */
declare function compileBaseUcanFlow(plan: BaseUcanFlow, registry: CompilerRegistry): CompiledFlow;

/** Describes what changed when merging two compiled flows. */
interface MergeResult {
    /** The merged compiled flow (full state). */
    merged: CompiledFlow;
    /** Node IDs that were added (new in incoming, not in existing). */
    added: string[];
    /** Node IDs that were replaced (patch only — existed and was overwritten). */
    replaced: string[];
    /** Node IDs that were kept unchanged from existing. */
    kept: string[];
}
/**
 * Merge an incoming compiled flow into an existing one.
 *
 * This is a **pure function** — no Yjs, no side effects.
 *
 * Strategies:
 * - `merge`: existing nodes win on ID collision. Incoming nodes with new IDs
 *   are added. Existing nodes are never modified.
 * - `patch`: incoming nodes overwrite existing nodes on ID collision. Incoming
 *   nodes with new IDs are added. Existing nodes not in incoming are kept.
 *
 * Edges in the merged result are the union of edges from both sides, filtered
 * to those whose source and target both exist in the merged node set, with
 * duplicates collapsed by edge id. Order is the merged node insertion order
 * (existing first, then newly added) — there is no topological sort because
 * there is no inferred dependency relationship.
 */
declare function mergeCompiledFlows(existing: CompiledFlow, incoming: CompiledFlow, strategy: 'merge' | 'patch'): MergeResult;

interface SetupFlowOptions {
    /** The Base UCAN flow plan to compile. */
    plan: BaseUcanFlow;
    /** Matrix room ID to hydrate the flow into. */
    roomId: string;
    /** Authenticated Matrix client. */
    matrixClient: MatrixClient;
    /** DID of the user setting up the flow. */
    creatorDid: string;
    /** Optional doc ID override (defaults to plan.flowId). */
    docId?: string;
    /**
     * How to apply the plan to the existing document.
     * - `full` (default): wipe existing flow state and rebuild entirely.
     * - `merge`: keep existing blocks, add new capabilities from the plan.
     * - `patch`: replace matching nodes, add new ones, keep the rest.
     */
    strategy?: FlowStrategy;
}
interface SetupFlowResult {
    /** The compiled flow artifacts. */
    compiled: CompiledFlow;
    /** The room ID (same as input, for convenience). */
    roomId: string;
    /** The flow ID from the plan. */
    flowId: string;
}
interface ReadFlowOptions {
    /** Matrix room ID to read from. */
    roomId: string;
    /** Authenticated Matrix client. */
    matrixClient: MatrixClient;
}
interface ReadFlowResult {
    /** The current flow plan in BaseUcanFlow format (what the agent reads/writes). */
    plan: BaseUcanFlow;
    /** The compiled flow state (lower-level representation). */
    compiled: CompiledFlow;
    /** The room ID (same as input, for convenience). */
    roomId: string;
}
/**
 * Read the current Base UCAN flow plan from a Matrix room.
 *
 * Connects to the room, reads the Y.Doc, decompiles the flow state
 * back into a `BaseUcanFlow`, and disconnects. Returns `null` if the
 * room has no flow state.
 *
 * **This is the lower-level API.** It exists for cases where you need
 * to read a flow from a room you are NOT currently editing — e.g.
 * cross-room operations or background reads. For the common case of
 * "read the flow the user is currently looking at," use
 * `readFlowFromEditor(editor)` instead. That function takes no
 * parameters from the agent and reads from the editor's existing
 * Y.Doc directly — no Matrix connection, no async, no room ID
 * resolution. The browser tool that exposes `read_flow` to the AI
 * agent should wrap `readFlowFromEditor`, not this function.
 */
declare function readFlowAsBaseUcan(options: ReadFlowOptions): Promise<ReadFlowResult | null>;
/**
 * Minimal editor shape required by `readFlowFromEditor` and the active
 * editor registry. The full `IxoEditorType` is fine to pass — this is
 * just a structural lower bound so test harnesses can construct fake
 * editors without pulling in React dependencies.
 */
interface ReadableEditor {
    _yDoc?: Y.Doc;
    getRoomId?: () => string;
}
/**
 * Read the current flow from a specific editor instance, synchronously.
 *
 * Use this when you have an editor reference in hand (e.g. from inside a
 * React component, a test, or a multi-editor host that needs to target a
 * specific instance). For the common case of "read the flow the user is
 * currently looking at," prefer the parameterless `readFlow()` below — it
 * uses the active editor registry so you don't have to thread an editor
 * reference through your call sites.
 *
 * Returns `null` ONLY when the editor's Y.Doc has no flow state at all
 * (no nodes AND no meta). An empty `flowId` string is no longer treated
 * as "no flow" — that was the historical bug where successful
 * `setup_flow` calls authored with `flowId: ""` (the documented agent
 * convention) showed up as null on subsequent reads.
 */
declare function readFlowFromEditor(editor: ReadableEditor): ReadFlowResult | null;
/**
 * Register an editor as the current active editor. Called by the editor's
 * mount hook when the document is connected and ready. Pass `null` on
 * unmount to clear the registry.
 *
 * If a different editor is already registered, it is replaced silently —
 * the most recent registration wins. This matches the single-editor
 * assumption above.
 */
declare function setActiveEditor(editor: ReadableEditor | null): void;
/**
 * Get the currently registered active editor, or null if none is set.
 * Provided for cases where a caller wants to check the registry directly
 * (e.g. for diagnostics) without going through `readFlow()`.
 */
declare function getActiveEditor(): ReadableEditor | null;
/**
 * Read the current flow from the active editor, with no parameters at all.
 *
 * This is the parameterless API the AI agent's `read_flow` browser tool
 * should wrap. The browser tool literally becomes `read_flow: () => readFlow()`.
 *
 * Returns `null` if there is no active editor registered (e.g. the editor
 * hasn't finished mounting yet, or no editor is open in this JS context),
 * OR if the active editor's Y.Doc has no flow state at all.
 *
 * If `null` is returned and the user is referencing an existing flow, that
 * is a hard signal to STOP and report to the user — never silently rebuild,
 * because the duplicate-blocks bug is the inevitable consequence.
 */
declare function readFlow(): ReadFlowResult | null;
/**
 * One-shot function that compiles a Base UCAN flow plan and writes it
 * into a Matrix room's Y.Doc. After this completes, the room is a
 * normal flow that anyone can open via `useCreateCollaborativeIxoEditor`.
 *
 * Supports three strategies:
 * - `full` (default): clears any existing flow and rebuilds from scratch.
 * - `merge`: adds new capabilities alongside existing ones.
 * - `patch`: replaces matching nodes and adds new ones.
 */
declare function setupFlowFromBaseUcan(options: SetupFlowOptions): Promise<SetupFlowResult>;

/**
 * Read the current compiled flow state from a live Y.Doc.
 *
 * This is the inverse of `hydrateYDocFromCompiledFlow`. It extracts the flow
 * graph state from Yjs maps so that the pure merge/patch logic can operate
 * on plain objects.
 *
 * Returns `null` if the document has no flow state.
 */
declare function readCompiledFlowFromYDoc(yDoc: Doc): CompiledFlow | null;

/**
 * Reconstruct a BaseUcanFlow plan from a CompiledFlow.
 *
 * This is the inverse of `compileBaseUcanFlow`. It allows the AI agent to
 * read the current flow in the same format it writes — a plain capability
 * list it can reason about, modify, and pass back to the compiler.
 *
 * This is a **pure function** — no Yjs, no side effects.
 *
 * Note: some information is lossy (e.g. conditions are stored as a JSON
 * string in props and are not fully round-tripped back to ConditionRef).
 * The core capability data (can, with, nb, trigger, actor, ttl, metadata)
 * is fully preserved.
 */
declare function decompileToBaseUcanFlow(compiled: CompiledFlow): BaseUcanFlow;

type FlowAgentPublicNodeState = 'Pending' | 'Blocked' | 'Overdue' | 'Done';
type FlowAgentRunPhase = 'Running' | 'Validating' | 'Failed' | 'Archived';
type FlowAgentBlockerCause = 'missing_input' | 'failed_upstream' | 'missing_ucan' | 'stale_config' | 'service_error' | 'external_confirmation_pending' | 'validation_mismatch' | 'unknown';
type FlowAgentCommandType = 'diagnose_blocker' | 'assign_actor' | 'notify_actor' | 'execute_action' | 'validate_external_state' | 'submit_claim' | 'watch_udid' | 'archive_flow' | 'propose_config_change';
type FlowAgentCommandStatus = 'queued' | 'leased' | 'running' | 'confirmed' | 'failed' | 'skipped';
type FlowAgentLedgerEventType = 'agent.decision' | 'agent.command' | 'agent.validation' | 'agent.escalation' | 'agent.memory';
interface FlowAgentActor {
    did: string;
    matrixUserId?: string;
    displayName?: string;
    skills?: string[];
}
interface FlowAgentLease {
    id: string;
    commandId: string;
    nodeId: string;
    actorDid: string;
    acquiredAt: number;
    expiresAt: number;
    epoch: number;
}
interface FlowAgentNodeSnapshot {
    nodeId: string;
    blockType: string;
    actionType?: string;
    title?: string;
    runtime: FlowNodeRuntimeState;
    publicState: FlowAgentPublicNodeState;
    blockerCause?: FlowAgentBlockerCause;
    assigneeDid?: string;
    dueAt?: number;
    pendingInvocationCount: number;
}
interface FlowAgentCommandBase {
    id: string;
    type: FlowAgentCommandType;
    flowId: string;
    flowUri: string;
    nodeId: string;
    actorDid: string;
    status: FlowAgentCommandStatus;
    capability: UcanCapability;
    idempotencyKey: string;
    createdAt: number;
    updatedAt: number;
    reason: string;
    payload: Record<string, unknown>;
    lease?: FlowAgentLease;
    error?: string;
}
type FlowAgentCommand = FlowAgentCommandBase;
interface FlowAgentLedgerEvent {
    id: string;
    type: FlowAgentLedgerEventType;
    flowId: string;
    nodeId?: string;
    commandId?: string;
    actorDid: string;
    timestamp: number;
    details: Record<string, unknown>;
}
interface FlowAgentMaps {
    outbox: Map<FlowAgentCommand>;
    leases: Map<FlowAgentLease>;
}
interface FlowAgentPolicyDecision {
    allowed: boolean;
    reason: string;
    capability: UcanCapability;
    proofCids: string[];
}
interface FlowAgentContext {
    yDoc: Doc;
    editor?: IxoEditorType;
    blocks?: unknown[];
    flowId: string;
    flowUri: string;
    actor: FlowAgentActor;
    now?: () => number;
}
interface FlowAgentCommandResult {
    commandId: string;
    success: boolean;
    output?: Record<string, unknown>;
    confirmed?: boolean;
    error?: string;
}
interface FlowAgentExecutor {
    executeAction?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
    assignActor?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
    notifyActor?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
    validateExternalState?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
    submitClaim?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
    watchUdid?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
    archiveFlow?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
    proposeConfigChange?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
    diagnoseBlocker?: (command: FlowAgentCommand, context: FlowAgentContext) => Promise<FlowAgentCommandResult>;
}
interface FlowAgentTickResult {
    flowDone: boolean;
    snapshots: FlowAgentNodeSnapshot[];
    queuedCommands: FlowAgentCommand[];
    executedCommands: FlowAgentCommandResult[];
}

interface CreateAgentCommandParams {
    type: FlowAgentCommandType;
    flowId: string;
    flowUri: string;
    nodeId: string;
    actor: FlowAgentActor;
    reason: string;
    payload?: Record<string, unknown>;
    now?: number;
}
declare function createAgentCommand({ type, flowId, flowUri, nodeId, actor, reason, payload, now }: CreateAgentCommandParams): FlowAgentCommand;
declare function validateAgentCommand(command: FlowAgentCommand): {
    valid: boolean;
    error?: string;
};
declare function isExternalMutation(type: FlowAgentCommandType): boolean;

interface BuildFlowAgentContextParams {
    yDoc: Doc;
    flowId: string;
    flowUri?: string;
    actor: FlowAgentActor;
    blocks?: unknown[];
    editor?: IxoEditorType;
    now?: () => number;
}
/**
 * Builds the host-facing runtime context expected by the Flow Agent.
 *
 * Headless hosts own Matrix login, room joins, and Y.Doc sync. Once a host has
 * a live room document and an agent identity, this helper gives it the stable
 * context shape to pass into `tickFlowAgent` or `FlowAgentService`.
 */
declare function buildFlowAgentContext({ yDoc, flowId, flowUri, actor, blocks, editor, now }: BuildFlowAgentContextParams): FlowAgentContext;

interface AcquireFlowAgentLeaseParams {
    leases: Map<FlowAgentLease>;
    commandId: string;
    nodeId: string;
    actorDid: string;
    now?: number;
    ttlMs?: number;
}
declare function acquireFlowAgentLease({ leases, commandId, nodeId, actorDid, now, ttlMs, }: AcquireFlowAgentLeaseParams): FlowAgentLease | null;
declare function validateFlowAgentLease(leases: Map<FlowAgentLease>, lease: FlowAgentLease, now?: number): boolean;
declare function releaseFlowAgentLease(leases: Map<FlowAgentLease>, lease: FlowAgentLease): boolean;
declare function cleanupExpiredFlowAgentLeases(leases: Map<FlowAgentLease>, now?: number): FlowAgentLease[];

declare function requiredCapabilityForCommand(type: FlowAgentCommandType, flowUri: string, nodeId: string): UcanCapability;
declare function isCapabilityMatch(granted: UcanCapability, required: UcanCapability): boolean;
declare function canMatches(granted: string, required: string): boolean;
declare function resourceMatches(granted: string, required: string): boolean;
interface EvaluateFlowAgentPolicyParams {
    actorDid: string;
    commandType: FlowAgentCommandType;
    flowUri: string;
    nodeId: string;
    delegationStore?: UcanDelegationStore;
    delegations?: StoredDelegation[];
    now?: number;
}
declare function evaluateFlowAgentPolicy({ actorDid, commandType, flowUri, nodeId, delegationStore, delegations, now, }: EvaluateFlowAgentPolicyParams): FlowAgentPolicyDecision;

interface FlowAgentOrchestratorOptions {
    delegationStore?: UcanDelegationStore;
    delegations?: StoredDelegation[];
    candidateActors?: FlowAgentActor[];
    executor?: FlowAgentExecutor;
    leaseTtlMs?: number;
    archiveWhenDone?: boolean;
}
declare function planRalphLoopCommands(context: FlowAgentContext, options?: FlowAgentOrchestratorOptions): {
    snapshots: FlowAgentNodeSnapshot[];
    queuedCommands: FlowAgentCommand[];
    flowDone: boolean;
};
declare function executeQueuedAgentCommands(context: FlowAgentContext, options?: FlowAgentOrchestratorOptions): Promise<FlowAgentCommandResult[]>;
declare function tickFlowAgent(context: FlowAgentContext, options?: FlowAgentOrchestratorOptions): Promise<FlowAgentTickResult>;

interface FlowAgentServiceOptions extends FlowAgentOrchestratorOptions {
    intervalMs?: number;
    onTick?: (result: FlowAgentTickResult) => void | Promise<void>;
    onError?: (error: unknown) => void;
}
/**
 * Headless-service adapter boundary.
 *
 * Host applications own Matrix login, room joins, and Y.Doc sync. Once they
 * have a live Y.Doc/editor snapshot, this service provides the deterministic
 * Ralph-loop tick and command execution cycle.
 */
declare class FlowAgentService {
    private readonly context;
    private readonly options;
    private timer;
    private running;
    constructor(context: FlowAgentContext, options?: FlowAgentServiceOptions);
    tick(): Promise<FlowAgentTickResult>;
    start(): void;
    stop(): void;
}

declare function getFlowAgentMaps(yDoc: Doc): FlowAgentMaps;
declare function computeAgentCommandId(params: {
    flowId: string;
    nodeId: string;
    type: string;
    payload: Record<string, unknown>;
}): string;
declare function queueAgentCommand(yDoc: Doc, command: FlowAgentCommand): {
    command: FlowAgentCommand;
    created: boolean;
};
declare function readQueuedAgentCommands(yDoc: Doc): FlowAgentCommand[];
declare function updateAgentCommand(yDoc: Doc, commandId: string, patch: Partial<FlowAgentCommand>): FlowAgentCommand | null;
declare function appendAgentLedgerEvent(yDoc: Doc, event: Omit<FlowAgentLedgerEvent, 'id'> & {
    id?: string;
}): FlowAgentLedgerEvent;
declare function readAgentLedgerEvents(yDoc: Doc, eventType?: FlowAgentLedgerEventType): FlowAgentLedgerEvent[];

export { type FlowAgentContext as $, type AuthorizationResult as A, type BaseUcanFlow as B, type CompilerRegistry as C, buildFlowAgentContext as D, type ExecuteNodeParams as E, type FlowRuntimeStateManager as F, cleanupExpiredFlowAgentLeases as G, createAgentCommand as H, evaluateFlowAgentPolicy as I, executeQueuedAgentCommands as J, getFlowAgentMaps as K, planRalphLoopCommands as L, type MergeResult as M, type NodeActionResult as N, queueAgentCommand as O, readAgentLedgerEvents as P, readQueuedAgentCommands as Q, type ReadFlowOptions as R, type SetupFlowOptions as S, releaseFlowAgentLease as T, tickFlowAgent as U, validateAgentCommand as V, validateFlowAgentLease as W, type BuildFlowAgentContextParams as X, type FlowAgentActor as Y, type FlowAgentCommand as Z, type FlowAgentCommandResult as _, buildAuthzFromProps as a, type FlowAgentExecutor as a0, type FlowAgentLease as a1, type FlowAgentNodeSnapshot as a2, type FlowAgentPublicNodeState as a3, type FlowAgentTickResult as a4, type ActionDefinition as a5, type ActionServices as a6, type FlowAgentBlockerCause as a7, clearRuntimeForTemplateClone as a8, type ActionContext as a9, type CompiledBlock as aA, type CompiledEdge as aB, type CompiledFlowNode as aC, type TriggerSpec as aD, isRuntimeRef as aE, type ActionResult as aa, type OutputSchemaField as ab, canMatches as ac, computeAgentCommandId as ad, isCapabilityMatch as ae, isExternalMutation as af, requiredCapabilityForCommand as ag, resourceMatches as ah, updateAgentCommand as ai, type AcquireFlowAgentLeaseParams as aj, type CreateAgentCommandParams as ak, type EvaluateFlowAgentPolicyParams as al, type FlowAgentOrchestratorOptions as am, type FlowAgentServiceOptions as an, type FlowAgentCommandBase as ao, type FlowAgentCommandStatus as ap, type FlowAgentCommandType as aq, type FlowAgentLedgerEvent as ar, type FlowAgentLedgerEventType as as, type FlowAgentMaps as at, type FlowAgentPolicyDecision as au, type FlowAgentRunPhase as av, type ConditionRef as aw, type ActorConstraint as ax, type TTLConstraint as ay, type RuntimeRef as az, buildFlowNodeFromBlock as b, createRuntimeStateManager as c, type ExecutionOutcome as d, executeNode as e, type ExecutionContext as f, readFlowFromEditor as g, readFlow as h, isAuthorized as i, setActiveEditor as j, getActiveEditor as k, compileBaseUcanFlow as l, readCompiledFlowFromYDoc as m, mergeCompiledFlows as n, decompileToBaseUcanFlow as o, type SetupFlowResult as p, type ReadFlowResult as q, readFlowAsBaseUcan as r, setupFlowFromBaseUcan as s, type ReadableEditor as t, type FlowCapability as u, type CompiledFlow as v, type FlowStrategy as w, FlowAgentService as x, acquireFlowAgentLease as y, appendAgentLedgerEvent as z };
