---
title: "Derive method contract"
description: "DeriveMethod, DeriveContext, the derive registry, the Derivation record and the derivation index functions."
canonical_url: "https://skaile-ai.github.io/forge-editor/reference/derive-methods"
---
# Derive method contract

> DeriveMethod, DeriveContext, the derive registry, the Derivation record and the derivation index functions.

The types come from `packages/editor/src/core/derive.ts` and `core/derivation.ts` and are exported from `@skaile/forge-editor/core`. For how to write a derive method, see [Derive methods and the Derivation index](https://skaile-ai.github.io/forge-editor/guides/derive-methods).

## `DeriveMethod`

One way to make a new block or text from a block. A Feature contributes methods in `EditorFeature.deriveMethods`; `defineEditor` merges them in feature order into `preset.deriveMethods` (`DeriveRegistry`).

<table>
<thead>
  <tr>
    <th>
      Field
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        id
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Unique across the preset. Also the id of the block action generated from the method.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        label
      </code>
    </td>
    
    <td>
      <code>
        (ctx: FeatureContext) => string
      </code>
    </td>
    
    <td>
      Menu label, in the language of the surface (<code>
        ctx.t
      </code>
      
      ).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        icon
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      Iconify name.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ability
      </code>
    </td>
    
    <td>
      <code>
        Ability?
      </code>
    </td>
    
    <td>
      Shown only on blocks that have this ability (<code>
        BlockAction.ability
      </code>
      
      ).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        order
      </code>
    </td>
    
    <td>
      <code>
        number?
      </code>
    </td>
    
    <td>
      Position among the block actions (<code>
        BlockAction.order
      </code>
      
      ).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        placement
      </code>
    </td>
    
    <td>
      <code>
        BlockAction['placement']?
      </code>
    </td>
    
    <td>
      Where the action shows.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        requires
      </code>
    </td>
    
    <td>
      <code>
        readonly string[]
      </code>
    </td>
    
    <td>
      Capability ids the original must all have. Every id must be declared by a Feature (or built in) when the preset is defined.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        available
      </code>
    </td>
    
    <td>
      <code>
        (ctx: DeriveContext) => boolean?
      </code>
    </td>
    
    <td>
      Backend flags and per-block conditions (<code>
        ctx.ctx.backend.ai
      </code>
      
      , a readable source). Absent: always available where <code>
        requires
      </code>
      
       holds.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        run
      </code>
    </td>
    
    <td>
      <code>
        (ctx: DeriveContext) => void
      </code>
    </td>
    
    <td>
      Does the work and writes the result, and for a Derived block its Derivation.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        menu
      </code>
    </td>
    
    <td>
      <code>
        (ctx: DeriveContext) => MenuItem[]
      </code>
    </td>
    
    <td>
      For a method with sub-choices (derive into one of several Block types).
    </td>
  </tr>
</tbody>
</table>

Exactly one of `run` and `menu` is set; `defineEditor` throws for neither or both, for a duplicate id and for a `requires` entry no Feature declares.

### `DeriveContext`

<table>
<thead>
  <tr>
    <th>
      Field
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        editor
      </code>
    </td>
    
    <td>
      the editor
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        node
      </code>
    </td>
    
    <td>
      the original block
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pos
      </code>
    </td>
    
    <td>
      the position right before <code>
        node
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ctx
      </code>
    </td>
    
    <td>
      the <code>
        FeatureContext
      </code>
      
       of the surface (backend, public AI flags, settings, notices, translations)
    </td>
  </tr>
</tbody>
</table>

## Registry and functions

<table>
<thead>
  <tr>
    <th>
      Export
    </th>
    
    <th>
      Does
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        DeriveRegistry
      </code>
    </td>
    
    <td>
      <code>
        methods
      </code>
      
       (feature order) and <code>
        get(id)
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        createDeriveRegistry(methods)
      </code>
    </td>
    
    <td>
      builds a registry
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        deriveMethodsAt(editor, ctx, pos)
      </code>
    </td>
    
    <td>
      the methods that can run on the block at <code>
        pos
      </code>
      
      : the block has every capability the method <code>
        requires
      </code>
      
      , and <code>
        available
      </code>
      
       holds. Empty without a block there or without a preset.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        deriveActionsOf(preset, ctx)
      </code>
    </td>
    
    <td>
      one <code>
        BlockAction
      </code>
      
       per method, in the shape the block UI renders; <code>
        requires
      </code>
      
      , <code>
        ability
      </code>
      
       and <code>
        available
      </code>
      
       gate it. <code>
        blockActionsOf
      </code>
      
       includes them.
    </td>
  </tr>
</tbody>
</table>

## `Derivation`

The record in `meta.derivation` of a Derived block. The original keeps nothing.

<table>
<thead>
  <tr>
    <th>
      Field
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        from
      </code>
    </td>
    
    <td>
      <code>
        { asset: string } | { block: string, document?: string }
      </code>
    </td>
    
    <td>
      The original: an uploaded asset by asset name, or a block by block ID. <code>
        document
      </code>
      
       is the Document the block lives in; absent = this Document.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        method
      </code>
    </td>
    
    <td>
      <code>
        DerivationMethod
      </code>
    </td>
    
    <td>
      How it was made: <code>
        'transcription'
      </code>
      
      , <code>
        'pdf-text'
      </code>
      
      , <code>
        'ocr'
      </code>
      
      , <code>
        'description'
      </code>
      
      , <code>
        'bibliography'
      </code>
      
      , <code>
        ai:<typeId>
      </code>
      
       for a block derived by the model, or any string.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        model
      </code>
    </td>
    
    <td>
      <code>
        string?
      </code>
    </td>
    
    <td>
      The model that made it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        createdAt
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      ISO timestamp.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        inputHash
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      SHA-256 hex of the asset bytes or of the source block's Markdown; <code>
        ''
      </code>
      
       when unknown.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        outputHash
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      SHA-256 hex of the produced body's Markdown; <code>
        ''
      </code>
      
       when unknown.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        output
      </code>
    </td>
    
    <td>
      <code>
        string?
      </code>
    </td>
    
    <td>
      Asset name of the stored raw output (text/markdown).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        inputs
      </code>
    </td>
    
    <td>
      <code>
        Record<string, { from: DerivationSource, hash: string }>?
      </code>
    </td>
    
    <td>
      The named inputs of an N-to-1 Derivation (<code>
        mixdown
      </code>
      
      , a summary of several Blocks). <code>
        from
      </code>
      
       and <code>
        inputHash
      </code>
      
       then name the primary input, and <code>
        inputHash
      </code>
      
       is <code>
        derivationFingerprint
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        activity
      </code>
    </td>
    
    <td>
      <code>
        { id: string, agent?: string, at?: string }?
      </code>
    </td>
    
    <td>
      The run that produced the Block (an AI request, a job); <code>
        agent
      </code>
      
       is a model or tool id.
    </td>
  </tr>
</tbody>
</table>

`DERIVATION_KEY` is the `meta` key (`'derivation'`). `derivationOf(node)` reads a Derivation (`null` without one). `derivedChildrenOf(parent)` lists the direct children of `parent` that are Derived blocks, with their child index. `isForeignSource(derivation, documentId)` tells whether it points at a block of another Document.

## Derivation index

`derivationIndexOf(doc)` builds the reverse index once per document version (memoised per `doc` node):

<table>
<thead>
  <tr>
    <th>
      Member of <code>
        DerivationIndex
      </code>
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        derived
      </code>
    </td>
    
    <td>
      every Derived block with its position, in document order
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        blockById(id)
      </code>
    </td>
    
    <td>
      <code>
        { node, pos }
      </code>
      
       of the block with block ID <code>
        id
      </code>
      
       (any depth), or <code>
        null
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        assetBlocks(name)
      </code>
    </td>
    
    <td>
      the <code>
        AssetBlock[]
      </code>
      
       (<code>
        { node, pos, holder }
      </code>
      
      ) that hold the stored asset <code>
        name
      </code>
      
      , in document order; <code>
        holder
      </code>
      
       is the position and size of the block around the asset block
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        derivedFromBlock(id)
      </code>
    </td>
    
    <td>
      the Derived blocks whose Derivation points at block <code>
        id
      </code>
      
      , in this or any Document (<code>
        isForeignSource
      </code>
      
       tells them apart)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        derivedFromAsset(name)
      </code>
    </td>
    
    <td>
      the Derived blocks whose Derivation points at the stored asset <code>
        name
      </code>
    </td>
  </tr>
</tbody>
</table>

Functions on top of it:

<table>
<thead>
  <tr>
    <th>
      Function
    </th>
    
    <th>
      Returns
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        derivedOf(doc, originalPos, documentId?)
      </code>
    </td>
    
    <td>
      the <code>
        DerivedEntry[]
      </code>
      
       (<code>
        { node, pos, derivation }
      </code>
      
      ) made from the original at <code>
        originalPos
      </code>
      
      , in document order. They point at its block ID or at an asset the original holds as a direct child (its Source media). A Derived block moved out of the original still counts; Derivations from another Document are not listed.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        derivationOriginOf(doc, derivedPos, documentId?)
      </code>
    </td>
    
    <td>
      <code>
        DerivationOrigin
      </code>
      
      : <code>
        { status: 'found', node, pos }
      </code>
      
      , <code>
        { status: 'missing' }
      </code>
      
       (the original was deleted) or <code>
        { status: 'foreign' }
      </code>
      
       (another Document, not looked up); <code>
        null
      </code>
      
       when the node is no Derived block
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        derivationState(doc, derivedPos, bodyHash, documentId?, foreignHash?, inputHashOf?)
      </code>
    </td>
    
    <td>
      <code>
        DerivationState
      </code>
      
      : <code>
        source
      </code>
      
       (the origin <code>
        status
      </code>
      
      ), <code>
        stale
      </code>
      
       (an original changed since: an asset's stored <code>
        hash
      </code>
      
       against <code>
        inputHash
      </code>
      
      , a Block of another Document through <code>
        foreignHash
      </code>
      
      , each named input through <code>
        inputHashOf(from)
      </code>
      
      ; <code>
        null
      </code>
      
       for a block original in this Document, when unknown, and for <code>
        inputs
      </code>
      
       without <code>
        inputHashOf
      </code>
      
      ) and <code>
        edited
      </code>
      
       (<code>
        bodyHash()
      </code>
      
       differs from <code>
        outputHash
      </code>
      
      ; <code>
        null
      </code>
      
       when <code>
        outputHash
      </code>
      
       is unknown); <code>
        null
      </code>
      
       when the node is no Derived block
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        derivedStateOf(state)
      </code>
    </td>
    
    <td>
      <code>
        DerivedStateId
      </code>
      
       (<code>
        'fresh' | 'stale' | 'edited' | 'missing' | 'foreign'
      </code>
      
      ): the first that applies of <code>
        missing
      </code>
      
      , <code>
        stale
      </code>
      
      , <code>
        edited
      </code>
      
      , <code>
        foreign
      </code>
      
       (original in another Document, nothing known of it), else <code>
        fresh
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        derivationFingerprint({ method, inputs })
      </code>
    </td>
    
    <td>
      SHA-256 hex of the method and the hash of every input by input name; independent of the order of the keys in <code>
        inputs
      </code>
    </td>
  </tr>
</tbody>
</table>


## Sitemap

See the full [sitemap](https://skaile-ai.github.io/forge-editor/sitemap.md) for all pages.
