Address the ds-review-bot round on #6272: the README summary, completion
notice, token effect, and Known Limitations lines no longer call the
payload the final answer; the empty-result error reads "without an
answer"; the ordering spec also interleaves commentary; the partial_answer
branch cites its upstream source.
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.
Codex app-server 0.162 adds `partial_answer` to the agentMessage phases
(stable answer text that later assistant output or tool calls may follow).
The wire treated every phase other than final_answer, commentary, and null
as fatal, so one such message failed the whole delegation. Record the
latest partial answer and select final, then partial, then unphased text;
unknown phases still fail the run. The pinned @openai/codex 0.153.4 payload
never emits the phase, so behavior with the shipped binary is unchanged.
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
The packer images the web template bundles, every optional bundle, and an installation manifest instead of a dumped composition, and the Worker boots that profile through app-boot like dsh web. Package-local lazy client chunks move into content-addressed archives that the VFS fetches on first asynchronous read; client-modules reads chunks asynchronously.
The Worker replaces node-addon-require-builtin with Node v24.18.0 internal-module interfaces and reports Node 24, so plugin metadata, the Cordis Loader, and HMR reach one cascaded loader backed by the Worker loader. Resolution failures carry Node error codes, the empty load cache lets HMR apply profile changes, and every optional bundle switches on and off live. Platform stubs throw ERR_FEATURE_UNAVAILABLE_ON_PLATFORM.
Copy each plugin's manifest repository as its web page and package
directory, converting shorthands and Git URLs with hosted-git-info. Parse
options and generate help with commander.
Generate a validated format-1 plugin market index from a list of npm package
names and https Git repository URLs, without running package code.
- List every non-deprecated npm bundle version, and Git versions at release
tags and the default branch, each with its engines.dsh range.
- Read display fields, keywords, homepage, and icons the way DSH reads
installed plugins; inline small icons up to the format's 32 KiB limit.
- Cache results per immutable input and rewrite output only when it changes.
A Discover install passes the entry's localized title and version with its
spec. Every install dialog screen names the plugin and version, and shows the
spec, such as a pinned git+https URL, below in smaller monospace text.
The Installed tab panel now wraps its loading, unavailable, and empty states.
Custom plugin markets joins the bundles the More page holds back until the
profile enables them, and the repository field and its directory rule are
documented.
Indexes may give each plugin an optional repository: the web URL of its
source repository and the package directory inside it. The Discover entry
page links it as Source code, and the plugin_market tool returns it.
Read configured plugin market indexes on the Host, search them with fuzzy
multilingual matching, and install a chosen version from the Plugins page.
- dsh-plugin-market-index validates format-1 indexes and builds install
arguments; inline icons are capped at 32 KiB.
- The pluginMarket service fetches configured http(s) URLs, parses bodies in
a Worker Thread, caches documents, and pages filtered, ordered results with
installation status and engines.dsh compatibility.
- Discover is an opt-in experimental bundle; the Plugins page gains a
plugins.tab slot and confirmed installs.
- The plugin_market tool lists indexes, plugins, and versions for Creator mode.
- Plugin compatibility reads engines.dsh before DSH peer dependencies.
A Client plugin loaded after the page starts fetches its bootstrap once. The Host now registers that route before starting the Worker and answers once the Worker is ready, so enabling Developer Tools on a running page opens the bottom DevTools without a reload. A failed start answers 503.
When the platform cannot run the Worker (ERR_FEATURE_UNAVAILABLE_ON_PLATFORM), the Host warns once and stays active with only the 503 bootstrap route; serve-static and open load after the Worker starts. Every other startup failure still fails the fiber.
verify-package-dependencies now covers every packages/*/* manifest, experimental included, and reads each package's tsdown build entries so Worker and child-process entries count as Host runtime sources. Experimental Client packages no longer declare browser and type relationships as peers.
Package modules that other code imports must not suspend evaluation at module scope. A syntax-aware gate scans packages/*/*/src and excludes only executables (a shebang or a package bin target). The SenseVoice worker, the SSH helper entry, and the Inspector worker entry now run an explicit main().
The provider's Linux decisions now live in LinuxScopeSelector, a state machine
over injected observations: the deep probe, the user-manager listener, the
manager confirmation, and the systemd-run binary identity. Each decision
carries its reason and probe trigger, the runtime logs it at debug level, and
table-driven scenarios cover every transition.
- A positive verdict probes again when the systemd-run found through PATH
changes device, inode, size, or modification time, so an in-place upgrade
past v254 cannot reuse options that no longer keep argv literal.
- The listener is read before the probe, so a manager that starts during a
failed probe counts as a new listener.
- The kernel socket table is decoded as UTF-8, matching runtime directories
outside ASCII.
- LinuxScopeNotStartedError drops its unused code field.
A cached positive verdict let a hung user manager that still listens fail every
later command, and a cached negative verdict ignored a manager that started
later until the provider restarted.
- A scope launch whose bootstrap never consumed its launch request now fails
with LinuxScopeNotStartedError, and the runtime clears the verdict it
launched under, so the next eligible spawn probes again and records the
fallback when that probe fails. A generation counter keeps launches from a
superseded probe from forcing another probe.
- After a negative verdict, the runtime records the /proc/net/unix listener on
$XDG_RUNTIME_DIR/systemd/private and probes again only when a different
listener, meaning a new manager instance, appears.