Expand description
pi’s capture extension: one installed file, branded at runtime.
pi has no base-URL environment knob, so capture requires code running
inside the harness: an extension that registers pi’s providers against the
capture proxy and stamps the X-Tapes-* envelope pi’s turns are attributed
by. That extension is harness knowledge — written against pi’s extension API
— and so it lives here, as super::PI_GATEWAY_EXTENSION.
§Why exactly one file
pi auto-discovers global extensions by loading every file in
~/.pi/agent/extensions/, into one process. That makes the number of
installed copies a correctness property rather than a packaging detail.
Two copies contend over everything the file touches. The nonce read is a
read-and-delete, so the second copy to load finds nothing; worse, it
registers the same three providers anyway, without the echo, and the last
registration wins. The proxy then cannot tell a real launch from a forged
envelope, and both products’ sessions file as unknown with no error
anywhere. Coordinating two copies — per-product variable names, a gate that
stands one of them down — manages that collision. Installing one file to one
path removes the second reader, and a collision needs two.
So the asset is not rendered per consumer. Every client writes the same bytes to the same path, which is the property the opencode plugin has always had for free and the reason it was never exposed to this bug.
§What a product may still say
Its status entry’s name, and what it tells a user to run when the proxy is
fronting the wrong schema. Those are real differences and shipping different
bytes was only ever one way to express them; the extension reads them from
the environment of the launch instead — GATEWAY_LABEL_ENV,
GATEWAY_LABEL_SUFFIX_ENV, GATEWAY_REMEDY_ENV — set by whichever
client launched the session, for the length of that session.
Runtime branding keeps the containment a rendered slot used to buy, and
keeps it more cheaply: a value read from the environment is a string in a
variable, so it cannot be syntax however it is spelled. It reaches
setStatus and notify and nothing else — never the nonce handling, the
envelope, or the provider registration — and the test
presentation_values_reach_only_the_status_entry_and_the_notification pins
that by reading the asset.
What is not here is a default endpoint. The asset used to carry one, so a
product running a long-lived proxy at a fixed address could capture pi
sessions nobody launched under it. One file cannot hold one product’s
address without redirecting every other product’s sessions there too, so the
address moved entirely into the launch: a product that wants uncaptured pi
sessions routed anyway sets super::GATEWAY_URL_ENV in the environment
those sessions inherit, where the claim is explicit and revocable.
The environment, nonce, and schema contract stays wholly crate-owned. There
is no product-supplied name anywhere in it, which is what makes the shared
spellings in super safe again.
Constants§
- DEFAULT_
LABEL - The status label the asset presents when
GATEWAY_LABEL_ENVis unset. - GATEWAY_
LABEL_ ENV - Environment variable naming the pi status entry this extension registers, and the prefix of the label shown in it.
- GATEWAY_
LABEL_ SUFFIX_ ENV - Environment variable appended to the status label after the active schema.
- GATEWAY_
REMEDY_ ENV - Environment variable carrying the sentence appended to the extension’s schema-mismatch warning.