pub enum Command {
Show 13 variants
Infer {
prompt: String,
max_tokens: u32,
images: Vec<Handle>,
},
Open {
path: String,
},
Slice {
handle: Handle,
offset: u64,
len: u64,
},
SliceBytes {
handle: Handle,
offset: u64,
len: u64,
},
PageText {
handle: Handle,
page: u32,
},
PageImage {
handle: Handle,
page: u32,
},
Embed {
texts: Vec<String>,
},
Fetch {
url: String,
},
DocumentText {
handle: Handle,
},
ImageOp {
handle: Handle,
op: ImageOperation,
},
Emit {
progress: Value,
},
Done {
result: Value,
},
Fail {
code: String,
message: String,
},
}Expand description
What a guest asks the host to do, returned from its init/step exports.
Variants§
Infer
Run a prompt against the job’s model.
Fields
max_tokens: u32Upper bound on tokens generated. A guest can also end generation
early by returning TokenAction::Stop from its on_token export.
images: Vec<Handle>Images to accompany the prompt, named by handle.
Handles rather than bytes, for the same reason file contents are not handed over: an image can be tens of megabytes, and routing it through guest memory would put the 4 GiB wasm32 ceiling back in play for no benefit. The host already holds the bytes; it can pass them to the model directly.
Requires a model with vision capability. Empty for ordinary
text-only inference, which is why it is #[serde(default)] — a block
compiled before this field existed still deserializes.
Open
Open a file. Capability-checked against the job’s spec.
Yields a handle and a length rather than contents — see the crate docs on why bulk data does not cross this boundary.
Slice
Pull one bounded window of an open file into guest memory.
The guest picks len, so the guest sets its own memory ceiling.
Fields
handle: HandleHandle from a previous Command::Open.
offset: u64Byte offset to read from. u64 so that files far larger than a guest
could hold remain fully addressable.
len: u64Maximum bytes to return. The host may return fewer; see
Event::Sliced.
SliceBytes
Pull one bounded window of an open file as raw bytes.
The binary counterpart to Command::Slice. Prefer Slice for text:
it needs no encoding, and it handles the character-boundary problem for
you. This exists for blocks that genuinely need bytes — inspecting an
image header, say — and pays base64’s cost to carry them.
Fields
handle: HandleHandle from a previous Command::Open.
PageText
Extract one page of a document as text.
Fails when the document has no text layer; check
MediaKind::Document::has_text_layer first.
PageImage
Render one page of a document to an image.
Yields a new handle referring to the rendered image, which can then be
named in Command::Infer. That indirection is deliberate: the image
stays host-side like every other bulk value, and a rendered page is
usable exactly wherever a file-backed image is.
Embed
Embed one or more texts, returning a vector each.
Batched by construction: the guest hands over every text it wants embedded in one command. Embedding a corpus means tens of thousands of chunks, and a round trip per chunk is the difference between minutes and hours — so the batch is the primitive and a single text is just a batch of one.
Served by the spec’s embedding_model, which is deliberately not the
job’s chat model: they are different models, and asking a chat model
to embed either fails or returns something that is not an embedding.
Fetch
Download a URL and hand back a handle to it.
Answers with Event::Opened, the same event Command::Open
produces, so everything downstream is unchanged: a fetched resource
can be sliced, identified, extracted from, or handed to a vision
model exactly as a local file can. One new command, no new surface.
Requires a matching Fetch prefix in the spec’s capabilities. A
corpus on the web is still a corpus, and the capability list has to
describe reaching it.
DocumentText
Every character of text in a document, in one call.
What most callers reading a PDF actually want, and the direct way to
ask for it. Before this existed the only route was
Command::PageText with page: 0, which reads like “the first
page” and quietly means “everything” whenever the extractor emitted
no page breaks — a gap that cost a real user two iterations and
nearly a wrong conclusion about whether cuttlefish could read their
corpus at all.
Prefer this over walking pages unless the pages are genuinely needed separately: the whole document is one extraction either way.
Fields
handle: HandleHandle from a previous Command::Open.
ImageOp
Transform an image handle, yielding a new image handle.
Same indirection as Command::PageImage, and for the same reason:
pixels stay host-side, and the result is usable exactly wherever a
file-backed image is — including as an Command::Infer image.
This is the one image operation that needs a decoder, which is why it lives here rather than in the guest. Metadata (dimensions, EXIF, chunk structure) is header parsing and is available to any script without a host round trip or a feature flag; looking at the pixels is not.
Hosts built without the image-ops feature reject this with a clear
message rather than pretending to succeed.
Fields
handle: HandleHandle from a previous Command::Open or Command::PageImage.
op: ImageOperationWhat to do to it.
Emit
Report progress to whoever is watching the job’s event stream.
Done
Finish successfully with this payload.
Fail
Give up. The job ends with this code and message, and no result.
Fields
code: StringMachine-readable code; see error_codes.