The reasoning-level editor hardcoded pi-ai's seven levels, so a level a
pi-ai upgrade adds would be missing from the page and a stored key outside
the list would be dropped by the next edit. The levels now come from the
llm-pi-ai namespace schema, the key union of reasoningEfforts, read the
way protocolChoices reads the protocols, and travel explicitly from the
Models section and the provider editor through the model list to each row.
A stored key the schema does not list keeps its row and stays selectable.
The reasoning control now appears wherever that list is non-empty instead
of being inferred from a missing catalog provider.
The goal domain e2e runs over the shipped headless profile, whose base
bundle mounts goal-round-driver. GoalService.create() arms the goal the
fixture seeds, so the driver queued round 1 when the task turn went idle
and the test's headless driver disposed the context mid-round. The
assertions held only while the aborted round's turn/end missed the log
before disposal; an extra await in the agent loop's pre-step path (#6024)
let it land and the test failed deterministically.
Disarm the goal right after creating it. Activation is process-local, so
the persisted goal/change snapshot is unchanged and the driver starts no
round. Also assert a single turn/start, which records a started round
even when disposal aborts it before its turn/end is persisted.
The reasoning-level editor kept the levels it switched off, its row order,
and typed text in component state, while the model list keys rows by
position, so deleting a row handed that state to the next model: turning
the survivor's switch on wrote the deleted model's levels into it. The
editor now renders only from the model; rows follow the stored order,
switching on always starts from the defaults, and only the focused field
keeps its typed text until the field is left.
The reasoning check moves out of the shared model validator into the two
cards whose rows edit it, so DeepSeek and catalog routes are untouched,
and it now mirrors every pi-ai refusal: a valueless field, a missing value
on a level besides off, and an empty value. A refused value marks its
field, and leaving that field repairs it with the level name.
The Providers guide now points custom model API users to the page before
the YAML, and both package READMEs describe the new behavior.
The help tooltip now says that Off needs no value but keeps and sends a
value already written in the configuration, matching the disabled field
that shows it. Both READMEs add the rule that a custom value carries over
only between two thinking levels, so changing a row to or from Off resets
it. The Models settings e2e header comment is rewrapped.
The persisted draft now records the leading command chip's claim token
(DraftSnapshot.command). Restoring the draft asks the trigger pipeline's
new resolveClaim, which polls the optional InputTriggerSource.matchClaim
hook: the command source awaits its catalog and answers only a
leadingInput claim, never opening a popup, running an action, or
executing the command. The input rebuilds the chip once the claim
resolves, only at the revision the restore produced and merged into the
seed's history entry; otherwise the literal token stays and Enter still
adjudicates it.
A model row on a hand-declared pi-ai route now edits its reasoningEfforts
from the Models settings page instead of only through cordis.patch.yml.
A switch turns the field on or off; when on, each row pairs a level
select with the API value sent for it, which defaults to the level name.
Off only turns reasoning off, so its value field is disabled and a value
already stored for it is kept. Saving refuses a list without a level
besides off, and a help tooltip beside the label explains the values.
Catalog routes and the DeepSeek card are unchanged.
Refs #6260
conversation.hero.options seats compact Session options at the right end of
the New Session row, after the workspace and agent-preset controls. It is a
session-scoped list slot rendered only while a Session exists, so plugins can
add choices such as a worktree toggle without displacing the shipped controls.
#5938 turned @deepseek-ai/dsh-session-persistence-jsonl into a function
plugin without a default export, while the SDK resume spec from #5988
still default-imported it. Typecheck failed with TS1192 and the spec's
six cases mounted an undefined plugin, which kept the coverage, snapshot
and Windows build checks red for every pull request.
Users of v0.2.1-alpha.2 who saved an account catalog through the Models
page editor must move single-model changes into modelOverrides, because
a models field now stops llm-deepseek-account at load. pi-ai routes that
name a missing credential now list no models.
The account README now says that a prerelease orders below its release,
that listed capabilities do not bound an override, that an override for
a refused unknown model is checked once the model becomes available, and
that an account whose listed models are all refused shows the generic
empty state. resolveAdapterOptions documents that resolved models keep
the input order, which the account catalog relies on.
The listing deadline now comes from dsh-timeout and carries
MODEL_LISTING_TIMEOUT, so a listing that misses modelsTimeoutMs fails
with TIMEOUT and "timed out after <n> ms" instead of ABORTED. Rescope
and disposal aborts keep reporting ABORTED.
The account route no longer accepts a models catalog, so paid Flash
translation compares Account modelOverrides (Official keeps models) when
it checks that the owner's model configuration is unchanged before
dispatch. The paid fixture and the Web e2e serve the account GET /models
listing instead of configuring models on the account entry.
Product profiles mount no console exporter for ctx.logger, so the
listing failure warning never surfaced. The account route now writes
each loaded listing, the first failure of a failing streak with the
catalog it falls back to, and hidden listing entries to the console
under the [llm-deepseek-account] tag, as the account Platform plugin
does. Hidden entries are logged once per listing on every path, not
only during model discovery.
The account route always reads /models at the Messages origin; the
modelsURL option is removed so a configuration cannot point the listing
elsewhere. Model refusals now report "current version is <version>"
instead of "this build is", since users usually run a downloaded release
rather than a local build, and override diagnostics name the built-in
catalog instead of the build.
The session.create change is not perceptible to users: its only caller is the
Web client that ships in the same release. Remove the guide and the
cross-reference added to the New Session upgrade guide.
Decide the command chip's selecting step on deletion input events as well
as the character-deletion command, so iOS ranged deleteContentBackward no
longer removes the chip in one press. A selected chip now clears only
after a keydown that produced no character deletion, which keeps platform
shortcuts such as macOS Ctrl+H working.
A failed command submission settles to the leading chip like every other
transition, so submit-settled no longer carries the draft. The claim event
reuses the same handler. The seat rule runs as chip and paragraph
transforms instead of walking the whole document on every update.
Document the reload limitation under Known Limitations and assert that a
chip ending its block does not grow the composer.
A claimed command is now a CommandChipNode on the draft's leading seat
instead of styled literal text. The submit machine follows the chip: it
holds the claim while the chip leads the document, releases it when the
chip is deleted or displaced, and re-enters claimed when history
restores the chip. Deleting at the chip's edge takes two steps: the
first Backspace or Delete selects the chip, the next removes it.
The claim-token decoration transform and the text-reference precedence
rule are removed with the literal token.
Update the blank reuse Agent Note and the writer acquisition note for the
review fixes: arrival-order claims with directory checks before preset
resolution, restoration from the logged preset, latest-connection coalescing,
and the registry select that leaves an already composed blank unchanged.
The Creator entry names cordis in its session.create request, and its chip may
still select cordis when the Session list updates before the new projection
arrives. select recomposed and logged unconditionally, so that race appended a
second agent-preset/selected record and announced tools/change again. select
now leaves a blank Session that records the preset and runs its current
revision unchanged; a replaced definition still recomposes and logs. The
Creator Web scenario pins a single selection record.
Keep one Workspace navigation options type: StartSessionOptions now carries
agentPreset, and openWorkspace and connectWorkspace take its preset field.
A connection joins the latest in-flight connection to its Workspace only when
both name the same preset, so a superseding request always reaches the Host,
and the map is keyed by the branded WorkspaceId instead of a composite
string. The fresh New Session path no longer accepts a preset it would drop.
Restoring a saved blank reloads that Session's projections first, because
listed values are cached hints that can lag the log after an unclean exit.
The New Session upgrade guide points to the session.create reuse guide.
session.create resolved the requested preset before queueing on the named
identity, so a later request whose preset resolved first could run first, and
an undeclared preset masked the directory conflict the README promises.
Queue first, check the named Session's directory and ownership, then resolve
the preset inside the queue, and report the preset each request left the
Session running instead of reading it after the queue moved on. The no-roster
conflict message now names its actual cause.
openWorkspace and connectWorkspace accept NewSessionOptions, so the Client
Cordis inspect catalog spec pinned outdated signatures and failed both
coverage lanes. Declare openWorkspace on one line so the generated catalog
signature carries no collapsed line breaks, regenerate the catalog, and pin
the new signatures.
session.create now reuses a named Session only while it is a reusable blank,
runs the requested or default preset, and creates a new Session otherwise.
Record the migration for JSON-RPC clients and Client plugins that name a
sessionId, including the removed session/writer-held result and the
existingPreset detail.
Master now creates a fresh Session for a plain New Session, and the Creator
entry names its preset in the session.create request instead of a separate
agentPresets.select call. Wait for that request in the Creator scenario and
count the startup blank in the outdated-cache scenario.
Typing at the end of the highlighted command token lands in the styled
node. The decoration split the overflow back out, but splitText copied
the token style onto it, so Lexical's normalization merged the halves
again and the transform looped until Lexical aborted the update. The
DOM kept the native insertion while the editor state rolled back, which
left the composer desynchronized for every later keystroke.
Clear the overflow style in the same transform pass.
Refs #4490
session.create treats a named sessionId as a blank Session to reuse while
the Host can verify it is still reusable: no turn has started, it belongs to
the requested directory, it is an unarchived member of the requested
Workspace, and no other owner writes it. The reused Session runs the
requested agentPreset or the configured default; its recorded preset is not
resolved, so a blank recorded under a preset that is no longer declared no
longer breaks New Session or startup restoration. A change is logged as
agent-preset/selected before the Agent is published. A candidate that is no
longer reusable stays unchanged and the Host creates a new Session, which
replaces the client's writer-held fallback.
The Web client restores a saved draft with its recorded preset and falls back
to the default when that preset is missing or fails to activate, passes the
creator entry's preset through creation instead of issuing a concurrent
select, and reloads the projections of a declined candidate so a stale blank
hint no longer hides a started conversation.
Related to #2566
Shell discovery keyed entries by resolved path. On merged-/usr hosts the
login shell /bin/bash from $SHELL and the PATH hit /usr/bin/bash for the
`bash` candidate are one file with two spellings, so the menu showed
"bash" twice. Key discovered shells by executable name, compared without
letter case or `.exe`, and keep the earliest entry so the default shell
stays first.
Moves the interface to the position SidebarRightBinding held, after the controller factory, so the change reads as one interface replacing the other. Its content is unchanged.
The fullscreen command needs to know whether the frame is narrow enough
that an expanded panel is fullscreen automatically. Reading it from a new
ctx.layout.viewportWidth widened the layout plugin's public face for this
one consumer. The seats already receive the frame width as owner props and
compute the rule they render with, so each seat now reports that verdict
through its inject face, as it reports its docking kit's room. The command
reads the latest report only when the user runs it, after the commit that
rendered the width has settled.
- Revert ctx.layout.viewportWidth and the test fakes that provided it.
- SidebarRightInjected gains reportAutoFullscreen.