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:PaletteSiteentries map theme tokens to an encoding and value location.events:EventSiteentries name a function, an app-definedhook, its requiredcapability, and the pointer/length argument pairs to copy.returns:ReturnSiteentries rewrite a result after the function body runs.args:ArgSiteentries rewrite a zero-based argument before the function body runs.patches:BytePatchSiteentries overwrite bytes with a replacement of the same length.replaces:ReplaceSiteentries 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.
| site | live behavior | relocation | monitor |
|---|---|---|---|
| color | write the mapped color value | byte signature | yes |
| event | observe a function call | string anchor or byte signature | yes; not the full anchored runtime path |
| return | rewrite the result after the body | string anchor when provided; otherwise pinned offset | no |
| argument | rewrite an argument before the body | string anchor when provided; otherwise pinned offset | no |
| byte patch | same-length overwrite in memory | pinned offset in the live backend; signatures in the offline helper and monitor | yes |
| replacement | constant result instead of the original body; implemented, live verification pending | string anchor when provided; otherwise pinned offset | no |
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.
| crate | responsibility |
|---|---|
fpui-manifest | extension metadata, kinds, and app-defined capability strings |
fpui-theme | theme packages, color parsing, and the shared role vocabulary |
fpui-target | build identity, adapter schema, site kinds, and operations |
fpui-loader | launch checks, site resolution, native patch backends, and agent orchestration |
fpui-agent | the injectable library entry point |
fpui-host | generic transform and observe hooks, ordered dispatch, and capability enforcement |
fpui-wasm | interpreted wasm, resource limits, trap handling, and the experimental javascript backend |
fpui-plugin-sdk | guest-side plugin macro and abi glue |
fpui-install | macos bundle wrapping and unwrapping |
fpui-monitor | read-only patch compatibility reports |
fpui-discover | site 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) -> i64fpui_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.