adapters and api

the per-build contract, patch primitives, current crate names, and plugin abi.

the adapter contract

a TargetAdapter describes one executable build. its identity includes the architecture, executable SHA-256, and platform image identifier. the demonstrated platform uses a Mach-O UUID. the remaining lists describe native code and memory sites: offsets, bytes, function operations, and value locations. this contract is independent of the app’s ui framework. an adapter can contain behavior patches without any color sites.

  • sites: PaletteSite entries map theme tokens to an encoding and value location.
  • events: EventSite entries name a function, an app-defined hook, its required capability, and the pointer/length argument pairs to copy.
  • returns: ReturnSite entries rewrite a result after the function body runs.
  • args: ArgSite entries rewrite a zero-based argument before the function body runs.
  • patches: BytePatchSite entries overwrite bytes with a replacement of the same length.
  • replaces: ReplaceSite entries replace a function with a constant result.

return operations include invert_bool and force. argument operations support force. ReplaceOp::ReturnConst skips the original body and supplies a constant result. this reversible detour is implemented and unit tested; an end-to-end live target run has not yet been demonstrated.

ValueLocation supports general registers, vector registers, stack slots, and indirect memory locations. color encodings include straight sRGB floats, premultiplied linear floats, packed sRGB, and straight HSLA floats. the adapter must describe the representation the target actually uses. the HSLA example reflects a gpui target. adapting another framework or custom renderer requires establishing its color encoding and value locations; live theme mappings beyond gpui have not yet been demonstrated.

illustrative shape only: the identity, offsets, and bytes below are placeholders, not a working adapter for any application.

{
  "name": "example build — illustrative only",
  "identity": {
    "arch": "aarch64",
    "sha256": "0000000000000000000000000000000000000000000000000000000000000000",
    "image": {
      "mach_uuid": [
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0
      ]
    }
  },
  "sites": [
    {
      "token": "sidebar",
      "image_offset": 2380,
      "expected_bytes": "ff430091",
      "encoding": "straight_hsla_f32",
      "location": {
        "indirect": {
          "base": 0,
          "offset": 16
        }
      }
    }
  ],
  "events": [
    {
      "image_offset": 80312,
      "expected_bytes": "ff4302d1",
      "hook": "text-updated",
      "capability": "events",
      "args": [
        {
          "ptr_arg": 0,
          "len_arg": 1
        }
      ]
    }
  ],
  "returns": [
    {
      "token": "example-check",
      "image_offset": 33280,
      "expected_bytes": "ff4302d1",
      "op": "invert_bool"
    }
  ],
  "args": [
    {
      "token": "example-flag",
      "image_offset": 40960,
      "expected_bytes": "ff4302d1",
      "arg": 2,
      "op": {
        "force": {
          "value": 0
        }
      }
    }
  ],
  "replaces": [
    {
      "token": "example-result",
      "image_offset": 45056,
      "expected_bytes": "ff4302d1",
      "op": {
        "return_const": {
          "value": 1
        }
      }
    }
  ],
  "patches": [
    {
      "token": "example-text",
      "image_offset": 51200,
      "expected_bytes": "48656c6c6f",
      "replacement_bytes": "4865796121"
    }
  ]
}

all six site lists are optional, but an adapter must contain at least one site. validation rejects duplicate color tokens and byte patches whose replacement length differs. the event hook and capability strings in this example are illustrative app vocabulary.

signatures and string anchors can locate supported site kinds; see the relocation limits. valid JSON and matching bytes do not establish the function’s identity, calling convention, or address bounds. adapters remain trusted, build-specific inputs.

runtime support

this is the verified engine baseline. a field existing in the schema does not mean every backend consumes it.

sitelive behaviorrelocationmonitor
colorwrite the mapped color valuebyte signatureyes
eventobserve a function callstring anchor or byte signatureyes; not the full anchored runtime path
returnrewrite the result after the bodystring anchor when provided; otherwise pinned offsetno
argumentrewrite an argument before the bodystring anchor when provided; otherwise pinned offsetno
byte patchsame-length overwrite in memorypinned offset in the live backend; signatures in the offline helper and monitoryes
replacementconstant result instead of the original body; implemented, live verification pendingstring anchor when provided; otherwise pinned offsetno

each live backend checks the expected bytes before changing a site. failed or changed sites are skipped and reported. byte patches can replace interface strings or write a force-return sequence over a suitable function entry. a force-return skips the body; a return override does not.

constant-result replacements require a function returning an integer, pointer, or boolean in the primary return register. floating-point and struct returns are not supported, and the adapter author must establish the signature; matching entry bytes cannot establish it.

live memory patches leave the executable file unchanged. the separate offline helper changes an executable copy, and the wrapper changes bundle metadata and signatures. those are different workflows.

engine crates

each crate owns a specific part of the framework or its development tools.

crateresponsibility
fpui-manifestextension metadata, kinds, and app-defined capability strings
fpui-themetheme packages, color parsing, and the shared role vocabulary
fpui-targetbuild identity, adapter schema, site kinds, and operations
fpui-loaderlaunch checks, site resolution, native patch backends, and agent orchestration
fpui-agentthe injectable library entry point
fpui-hostgeneric transform and observe hooks, ordered dispatch, and capability enforcement
fpui-wasminterpreted wasm, resource limits, trap handling, and the experimental javascript backend
fpui-plugin-sdkguest-side plugin macro and abi glue
fpui-installmacos bundle wrapping and unwrapping
fpui-monitorread-only patch compatibility reports
fpui-discoversite discovery and signature generation

plugin abi

the native wasm abi exports linear memory and fpui_alloc(len). the host allocates separate guest buffers for the UTF-8 hook name and opaque payload, copies both into memory, and invokes an exported dispatcher:

  • fpui_transform(hook_ptr, hook_len, in_ptr, in_len) -> i64
  • fpui_observe(hook_ptr, hook_len, in_ptr, in_len)

a transform packs the output pointer into the upper 32 bits and the byte length into the lower 32 bits. 0 means no change, so the host retains the current payload. an observer returns nothing. the host bounds and reads the result through the guest memory API.

the rust plugin! macro generates allocation and dispatcher glue. hook names, capability names, and payload formats belong to the app integration. Capability(String) carries a name; it is not a fixed engine enum.

the sdk has no explicit transform-output free export. the separate javascript backend uses javy’s command interface rather than this pointer/length abi. see plugin authoring for examples, resource limits, and integration boundaries.