Repository navigation
Releases: TonyDua/dsh-web-search-exa
Releases · TonyDua/dsh-web-search-exa
Release list
v0.2.3
Two changes make this release. The dsh 0.2.x line stops being declared
compatible and becomes verified: 0.2.3 was run on the current dsh release,
0.2.0-rc.2, and works there. And the plugin gets its configuration page back
on that line, live. Everything below that is incidental.
Added
- The plugin is configurable from the Web UI again on dsh 0.2.0 and later,
and a save applies to the next search with no restart.0.1.7-alpha.1
replacedSettingsProvider.installSectionwithSettingsForms, whose page is
derived from the Config schema the Loader already holds. From that release the
plugin had no way to receive an edit — it kept the config it was mounted with,
and only a remount picked up a change. On0.2.0+it was worse than that:
dsh-settingsbuilds a form withvolatileForm(schema), and a schema with no
volatile field yieldsundefined, at which pointdescribe()drops the entry
from Settings entirely andupdate()throws
Plugin entry "web-search-exa" has no volatile fields. So 0.2.1 and 0.2.2
installed cleanly on that line and then offered no page to edit.
The release that removed the old API added its replacement: from0.2.0-rc.1
a Config field declared.volatile()in the schema (schemastery>= 3.18.4)
reachesapplyas a live reference, and the loader commits a saved edit into
that reference in place. Every field of this plugin's Config — including
mcpTool— is now declared volatile, so the page is generated and a save
reaches the next search without restartingdsh web, including switching
between the anonymous and keyed paths by adding or removing the key. The
mechanism is the loader's; this package declares the fields and reads through
the reference. - The read side stays version-proof. Fields are read through a structural
probe (readConfigValue): a plain value passes through, a live reference is
dereferenced. Older hosts, and direct library use, are unchanged, so one build
still serves every supported dsh line.
Fixed
scripts/compat-matrix.shcould test a tarball from a previous run.
npm_installspacked into a directory that survives across runs and then
picked the tarball withls | head -1, which sorts alphabetically — a
0.1.6tarball left over from an earlier run of a different plugin version
sorted before0.2.3and was the one installed, failing strict install only
beside the one host whose cordis requirement its stale peers could not
satisfy (0.2.1-alpha.1). The failure read as a real incompatibility; it was
leftover state. The pack directory is now wiped per call.- The REST
user-agentno longer reports the wrong version. It stayed
deepseek-harness-exa/0.1.5through the 0.2.0–0.2.2 releases, because the
string was a hand-written literal rather than derived from the package
version. It is now bumped with every release.
Changed
- devDependencies target dsh
0.2.0-rc.2(cordis~4.0.4), and
@deepseek-ai/schemasterymoved to^3.18.4, the first version with
.volatile(). Peer ranges anddsh.compatibility.dshReleasesare unchanged
from 0.2.2. - Documentation: the Web panel section is per dsh version, troubleshooting
names the plugin upgrade that clears the0.2.xskip warning, and the
version-differences section describes the volatile mechanism.
Verified
All of it on this base, and on the runtime the release names:
- On the current dsh release.
0.2.0-rc.2is what npm tagslatest. A real
dsh 0.2.0-rc.2process installed this tarball, composed the profile with no
compatibility warning, and served a headless search through the anonymous
structured MCP path with noEXA_API_KEY— 9 sources. AproviderIdset in
cordis.patch.ymlis what the booted process then serves, which is how the
patch layer was checked; that path is boot-time, see Notes. - The 17-version compatibility matrix passes (
0.1.2-alpha.2through
0.2.1-alpha.1): isolated install,tscagainst each host's own
declarations, the full 30-test suite, and a strict npm install of the real
tarball beside every host — including0.2.1-alpha.1, which only passes once
the stale-tarball defect above is fixed. - A live edit on the real loader (cordis-plugin-loader 1.0.5): a
volatile-only config change committed into the same fiber, with
loader/volatile-updatefiring for exactly the changed path, no remount and
no re-registration, and the next search carrying the new value. An ordinary
change took the ordinary update path instead.
Notes
- No peer range, compatibility declaration, or install-time behavior changed.
This package installs and resolves exactly as 0.2.2 did. What changed is what
it does once running on0.2.0+. - "Live" means a save made in Settings → Plugins.
dsh-config-editor.edit()
writes the profile patch and reconciles the running loader in the same call,
which is what carries the new value into the live reference. Editing
cordis.patch.ymlby hand is a separate path: dsh0.2.0-rc.2watches no
patch file, so a hand edit still needs a restart.
v0.2.2
Fixed
- The README was still advertising the old support range. The
dshbadge
hard-coded0.1.2-alpha.2 – 0.1.7-alpha.1and was not touched by the 0.2.x
work, so the first thing a reader sees contradicted the package it describes.
It now reads0.1.2-alpha.2 – 0.2.1-alpha.1and links to the compatibility
section rather than to the harness repository. - The install section dated a claim it had outgrown. It said "v0.1.4 and
later ship thedsh.bundlemanifest", which invites a reader on an older
release to wonder whether the documented command still applies to them. The
manifest ships in every published version; the sentence no longer carries a
version.
Changed
dsh.compatibility.dshReleasesis now explained where the reader meets it,
instead of only in a collapsed section. The text states what the key is and
what it is not: catalog metadata that the dsh runtime never reads and that
does not affect dependency resolution, present because registries such as DSH
STORE require an exact per-version record. That distinction was worth making
explicitly after a peer range that looked like a compatibility claim turned
out to exclude the entire 0.2.x line.- The note separating a version that resolves from one that was tested was
ambiguous about which number it was comparing; it now names the three
releases (0.1.7-alpha.2,0.1.7-rc.1,0.1.7-rc.2) that account for the
difference between 20 resolved and 17 tested.
Notes
- Documentation only. No runtime behavior, manifest field, or peer range
changed in this release; it exists because the READMEs are part of the
published tarball, so a documentation fix only reachesdsh plugin addand
npm users through a release.
v0.2.1
Fixed
- The plugin could not be installed beside any dsh 0.2.x release. The peer
ranges ended at>=0.1.8, and because a prerelease only satisfies a range
that carries a prerelease comparator on the samemajor.minor.patchtriple,
that enumeration excluded the entire0.2.xline.npm installof the
published tarball beside0.2.0-rc.2failed withERESOLVE— which is what
took this package off the DSH STORE listing
(AI-Scarlett/DSH-Store#1016),
since the catalog requires an installable result for at least one of the
official latest three releases. The ranges now end with
|| >=0.2.0-rc.1 || >=0.2.1-alpha.1. @deepseek-ai/cordishad the same defect one line down.>=4.0.2
excludes4.0.5-alpha.1, which is what a0.2.1-alpha.1host peers, so that
version failed strict installation even after the dsh ranges were fixed. The
range is now>=4.0.2 || >=4.0.5-alpha.1.scripts/compat-matrix.shpinned cordis wrongly, in a way that hid the
real problem. It hard-coded4.0.3for the whole0.2.*line, which is
wrong for0.2.0-rc.2(~4.0.4) and wrong again for0.2.1-alpha.1
(~4.0.5-alpha.1); the resulting npm conflict came from the harness's own
graph but surfaced as an install failure next to this plugin, reading like our
bug. The range is now read from each version's published manifest and its
floor pinned as a concrete version. Pinning the range itself — the obvious
first fix — is broken, which is how that mistake was caught: on the0.1.5
line^4.0.2resolves to4.0.4, the plugin then fails to install strictly,
and four versions went red. Passing cordis through nowhere at all fails the
other way, becausetscneeds it resolvable at the top level while the
harness's own tree nests it. The0.2.xline is in the version list now, so
the gap that caused this cannot silently reopen.
Added
dsh.compatibility.dshReleasesinpackage.json, declaring
0.2.0-rc.1,0.2.0-rc.2, and0.2.1-alpha.1ascompatible. A catalog
requires a precise per-version record; a peer range is not installable
evidence. Each declared version was verified by installing the real tarball
with npm under strict peer resolution beside that host and then running a live
keyless search through the registered provider.
Notes
- The
||in these ranges picks the highest lower bound rather than widening
the range, because every comparator is open-ended>=. Appending
|| >=0.2.0-rc.1to a range ending in>=0.1.8silently drops0.1.8
through0.2.0-rc.1. Both READMEs now say so, with the measured numbers: the
shipped enumeration resolves on all 20 published releases from
0.1.2-alpha.2to0.2.1-alpha.1. - No runtime behavior changed in this release.
v0.1.5
Fixed
- The peer range now actually installs on every claimed version. The earlier
>=0.1.2-rc.1was verified with pnpm, where it works, and assumed to work
everywhere. Measured with npm against the real tarball it installs on 1 of
14 versions and fails the other 13 withERESOLVE. The cause is the
pre-release rule: a prerelease satisfies a range only when some comparator
carries a prerelease on the samemajor.minor.patchtuple, so
>=0.1.2-rc.1excludes0.1.5-rc.2. Each0.1.xline that shipped a
prerelease now gets its own comparator, ending with>=0.1.8to carry future
stable releases. Result: 14/14 under both npm and pnpm. A future0.1.9
prerelease line needs one added entry. - Runs on dsh 0.1.7+.
0.1.7-alpha.1removed
SettingsProvider.installSectionand replaced the service with
SettingsForms, which derives a page from the Config schema the Loader
already holds. The old unconditional call threw aTypeErrorthere — the
plugin loaded but failed.installSettingsSection()now describes the service
structurally, callsinstallSectiononly when it is a function, and
otherwise returnsfalse; provider registration was already outside that
branch and stays unconditional. idno longer freezes at construction. It was assigned once in the
constructor, so a live Settings change toproviderIdleft the provider
reporting a stale id. It is now read per access.- The keyless channel now reports its own health. A new
ExaAvailabilityBreakeropens after 3 consecutive transient failures
(5xx/429/network/parse) for a 5-minute cooldown, during which
available()returns false — previously it returned true unconditionally, so
a throttled public endpoint produced a hard error on every search with no way
for the seam to route around it. One successful search closes the breaker.
A 4xx other than 429 deliberately does not trip it: that failure would repeat
forever, and hiding it behind a cooldown only delays the same error. - 429 is no longer indistinguishable from a network failure. The anonymous
path throwsExaRateLimitErrorwith codeWEB_RATE_LIMITEDand a message
namingEXA_API_KEY, instead of a genericWEB_PROVIDER_ERROR, so the model
can tell throttling from breakage. The keyed REST path is unaffected by the
breaker — a paid endpoint's failure is the caller's to see.
Added
- TypeScript source tree (
src/) — the implementation is now real source
rather than only a committed compile artifact:constants.ts,types.ts,
provider.ts, andindex.ts, carrying the JSDoc the bundle used to hold. - Build toolchain matching the harness's own packages:
tsdownbundles
src/index.tstolib/index.jsand rolls the declarations into
lib/index.d.ts;tsc --noEmitgates types. pnpm run build,pnpm run typecheck,pnpm run test:only, and a
prepublishOnlybuild hook so the tarball cannot ship stale artifacts.- 6 regression tests covering the three fixes above (the frozen-
idtest was
confirmed to fail against the previous build). - Cross-version compatibility matrix (
scripts/compat-matrix.sh,pnpm run compat): installs every published dsh version in isolation and typechecks +
tests the plugin against each one's own declarations. Wired into CI as a
separate job. This is the evidence behind the README's compatibility table
rather than a hand-written claim. - 3 regression tests pinning the settings-generation behaviour: the 0.1.7 shape
is tolerated,applystill registers the provider on it, and the older API
still adopts live Settings edits.
Audit findings (no code change needed)
- The
ctx.webseam is byte-stable across all 14 published versions:
WebErroris exported fromdsh-weband extendsHarnessErrorin every one,
launchEnvironmentOfis always present, andctx.settingsis always mounted. 0.1.7-alpha.1peers@deepseek-ai/cordis^4.0.3while the cordislatest
dist-tag still points at4.0.2;4.0.3is published and resolves it.
Changed
- Peer ranges are no longer pinned to a single prerelease.
@deepseek-ai/cordis
is>=4.0.2, and each dsh package now enumerates one comparator per released
line (>=0.1.2-alpha.2 || >=0.1.3-alpha.2 || … || >=0.1.8) because semver
excludes pre-release versions from ordinary ranges:^0.1.2-rc.1did not
match0.1.5-rc.2, so every install on the 0.1.5 line reported missing peers
even though the plugin worked.0.1.2-alpha.2remains the oldest tested
baseline. @deepseek-ai/dsh-settingsis now declared an optional peer
(peerDependenciesMeta): the provider registers whether or not a settings
service is mounted, so a keyless profile without the Settings UI is supported.engines.noderaised to>=22.19.0, matching the harness.- Declarations are generated, not hand-written. The former
lib/types/index.d.tswas maintained by hand next to the bundle and could
drift from it; types now come fromsrc/and land inlib/index.d.ts. READMEgains a supported-version matrix, the profilepeerDependencyRules
recipe that silences host-provided peer warnings, and source-build steps.
Verified
- 14/14
node:testcases pass against the rebuilt artifact on dsh0.1.5-rc.2. - End-to-end:
dsh --profile headlesssearched through the anonymous MCP path
with no API key in the environment, both before and after the rebuild.
Known limitation
- The plugin can now report that it is degraded, but the harness seam has no
provider priority chain: it selects exactly one usable provider and errors
(WEB_PROVIDER_AMBIGUOUS) when several are usable. So this makes failover
possible, not automatic — see the README note on unpinningsearchProvider.