Repository navigation
Commit c77a4b8
authored
✨ Select the model and effort a
* ✨ Add Session configuration contracts
`<Session>` accepts `model` and `effort`, and the Agent Api carries them:
`session()` takes the configuration the element authored, and `options()`
answers with the model and effort choices an agent advertises, in
provider-neutral terms. Both are exported from `@executablemd/core/api`, so a
Plugin composes them without naming a provider's protocol.
Core does not apply anything. What it owns is what the document asked for and
what a provider reported: a prompt retains the requested and effective model
and effort, a launch request carries the requested pair as facts, and the
coordinator refuses a preparation that changed them. `configuration-refused`
joins the durable launch failure classes.
Every new durable member is optional and exact. A record written before this
feature parses as a launch or prompt that asked for nothing, and a member that
names no choice refuses the record rather than being read past.
* ✨ Configure ACP sessions in place
A `<Session>` that names a model or an effort level reaches the provider that
issued it, and the conversation is put into that configuration before anything
is said in it. The order is the contract: read, write the model, refresh for
that model's effort choices, write the effort, verify — and only then does a
turn start. A setting nobody authored is never written, and a session nobody
configured reads no status at all.
What ACP advertises is read strictly and translated once. Categories are
preferred and exact ids are the fallback, groups flatten onto their members in
the provider's own order, and a selector that does not read back fails the
operation rather than degrading to "this agent offers you nothing".
A write that may have landed and then failed is put back, model first, and
verified. The original rejection is still what the caller is told. A
restoration nobody can verify marks that exact session unusable for the rest of
the run, and every later route to it refuses before a status read, a write, an
ensure, a turn or a process.
`Agent.options()` answers what an agent advertises through a conversation of
its own: created, read, and given up however the operation ends, with no
prompt, no placement, no host mapping and no route.
* ✨ Verify configured native launches
A launch beneath a configured `<Session>` puts the conversation under what the
document asked for at the one moment it can: after the exact session exists and
before anything is spent in it. The turn a launch may owe, the detach, and the
native UI all follow a configuration this provider applied and verified, and
the preparation retains what was asked and what the provider reported.
An adapter whose session its own interface creates has no such moment. A
configured launch on that route refuses before a route is published, before an
identity is allocated, before a private instruction file exists, and before
anything could be detached or spawned. Unconfigured launches on either route
are unchanged, and read no configuration at all.
A replay reaches its conversation again at whatever phase the journal stopped
at — the detach for a launch that never handed over, the spawn for one that
did. It reattaches by the exact retained identity, puts the retained
configuration back into force, and relinquishes ACP again without authoring a
second account of having done so.
* ✨ Inspect Agent model and effort options
Model and effort are settings a `<Session>` supplies, not inputs a handler
composes. `Agent.session()` carries a name and nothing else, so middleware
selects, reroutes or refuses whole conversations exactly as it always could and
never receives a settings object it could edit.
What an element asks of its conversation travels where the engine identity
already travels: sealed inside the opaque placement, before anything routes. A
handler holding that placement can transfer the whole route — which is what
routing is for — and cannot read the settings, edit them, or attach them to a
route of its own. A structural copy, a descriptor clone, an object built on the
prototype and a request from another loaded copy carry no issuance, so they
carry no settings either.
The installed provider settles that placement through the coordinator delivered
to its factory, saying which exact conversation it resolved and whether that
conversation exists yet. A fresh placement applies nothing and stays inert until
its first consumer builds it. An established one is configured in place, and the
value sealed into the use is the canonical one the provider reports it verified
— a provider that reports something else, or nothing at all, refuses rather than
being recorded as having complied.
Who settles is an ordinary closure inside one provider installation, and it is
the authority for the uses it issues as well as for the placements it settles.
It decides once per placement, holds one way of configuring each conversation,
and closes immediately after that provider's own finalizers — dropping its
registrations, so a placement settled afterwards and a use read afterwards both
reach nothing. Two providers side by side in one document own different ones, so
a conversation one of them configured is one only it can describe. Nothing
points back to it: no context, no module table, no property on a session, no
middleware value.
What an element asks is settled when it opens its placement, either way: an
element that authored nothing says so. By the time any handler holds the
request there is nothing left to say, so there is no authored configuration to
overwrite and no unconfigured placement to attach one to.
A configured `<Session>` owns one frozen use, and nested operations select that
same object. Where a handler routes is where the operation runs: an authentic
use applies and verifies its own settings; another authentic use applies that
other use's; a raw session, a name, no session at all, or a session a handler
answered with itself is an ordinary unconfigured route that reads and writes
nothing; and a value claiming to be configured that nobody issued refuses at the
provider's first read. A launch follows the same rule through its own one-use
request and never consults what a prompt is doing.
A live operation applies the settings under that session's existing
serialization and ownership: read, apply the model, refresh for that model's
effort choices, apply the effort, verify exact equality. Only then does a turn
begin or a native UI open. A value the agent does not advertise, a rejected
write, a readback naming something else, or an agent that cannot report its
configuration all fail before the turn — restoring model-first, reporting the
original rejection, and taking a session nobody can describe out of use for the
rest of the run. Omitted settings read and write nothing at all.
One durable member carries it, on a prompt record and on a launch record alike,
retained only for work that actually ran under it and read from the session the
provider named as the one the turn ran in — so a record describes the
conversation that ran rather than the element the operation was written inside.
The members a released build wrote are read, validated and dropped: they
configure no replay, they are never written again, and beside the canonical
member they refuse the record.
`xmd agent options` reports what an agent advertises, as text or version-1 JSON,
through one scoped inspection session that sends no prompt and creates no
document run, journal or durable session — which its help states before the
command is run. A real `xmd` binary proves it against a real agent process: one
session, one refresh, no turn, nothing left behind, and an answer it cannot read
refused whole without repeating a word of what the agent sent.
* 🐛 Recognize a placement the provider's own copy did not mint
A provider is a package, and the host that installs it may have loaded a
different copy of core than the one the provider resolved — a bundled plugin, a
vendored build, two specifiers that do not dedupe. Asking its own copy whether a
routed value is a placement answers no about a perfectly genuine one, and the
conversation it names then runs as an ordinary session: unconfigured, and
quietly, because nothing on that path fails.
So the provider classifies only what every copy agrees about. A conversation
somebody already resolved carries a session key and a working directory; a
placement carries neither. Everything else in the routing union that is an
object goes to the coordinator delivered to this factory, which is the only
thing that can say whose placement it is. Its refusal is the answer — not
caught, with no raw-session path behind it — and the descriptive name is read
as the public member it is.
Reading the public shape classifies the route and does nothing else: it says
this is the kind of value a placement is, never that it is a live one and never
whose. The exact object crosses unchanged, and an object that is neither a
conversation nor the shape of a placement refuses rather than resolving some
other conversation and saying nothing about it.
Nothing new is published to reach that decision: no context, no registry, no
authenticity marker, no shared symbol, and no readable configuration member.
The evidence runs this repository's provider against a second, separately
bundled copy of core, which is the same situation the other way round: every
placement and the coordinator itself are foreign to the provider's own copy.
An unconfigured placement is handed over exactly once and asks for nothing; a
configured one has its engine identity read by the provider's placement
integration and is put under exactly what it asked; a placement this
installation did not issue refuses before anything is resolved or written; and
a resolved session routed back in is still a session, carrying nothing to
apply. Everything that crosses from the other copy is read by its members —
requests, owners, handles and the sessions they settle — because asserting a
shape would be claiming to recognize values from a copy this one cannot.<Session> runs under (#829)1 parent c00fa82 commit c77a4b8
45 files changed
Lines changed: 7837 additions & 254 deletions
File tree
- packages
- acp
- src
- tests
- cli
- src
- tests
- core
- src/agent
- tests
- scripts
- specs
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5186 | 5186 | | |
5187 | 5187 | | |
5188 | 5188 | | |
| 5189 | + | |
5189 | 5190 | | |
5190 | 5191 | | |
5191 | 5192 | | |
| |||
0 commit comments