Commit Graph
67 Commits
Author SHA1 Message Date
_Kerman e5269b3bd6 fix(plugin-manager): keep the check's diagnostic honest and off the answer
Review fixes for the GitHub connection check: the returned packageResult
no longer carries the check's command line (it stays a module-local field
of the streamed run), and the recorded line drops URL user information
while Git still runs the address as typed. A check the deadline stopped
records the coerced status 1 in the result because an exit code is a
number, while its streamed run reports none; the JSDoc, package README
and boot subsystem page now say exactly that.
2026-10-28 16:35:13 +08:00
_Kerman 80a0cd0977 chore(catalog): regenerate the Cordis catalog after the plugin-manager docs
The install-log event now describes an installation run rather than only a
pnpm run, which the generated catalog and boot subsystem docs project.
2026-10-28 14:12:33 +08:00
winewill 6cbbc8caa5 Merge master and reconcile desktop diagnostic records 2026-10-26 11:05:45 +08:00
creatixchu 82bbf85894 fix(plugins): report unsupported bundle activation and address review 2026-10-23 13:15:05 +08:00
ZiyaZhang dbe0eb3aa2 Merge feat/creation-recommendations into plugin recommendation experiment
Takes the action-card fixes: kinds reconcile before every action, only live
roots get cards, the tool refuses while messages are queued, and bodies no
longer receive ready. The plugin card drops ready, its queued-card test goes
with the suppressed phase, and the shared-row limitation follows the base's
new limitations.
2026-10-22 08:16:20 -07:00
ZiyaZhang 9fd47804c2 fix(experimental): reconcile action cards before Not now and offer them to live roots only
- Kinds can reconcile a card before every user action, including Not now;
  the page kind confirms uncertain runs against the installed profile, so an
  installed page keeps Undo instead of being dismissed.
- Only a live root's direct skill load activates propose_action; calls from
  subagents or from code are refused.
- The tool refuses while queuedMessageLimit messages wait, so the model is
  never told a hidden card was shown; the suppressed phase is gone and the
  projection moves to state version 2.
- record() refuses actions no kind registered and the derived replaced phase.
- Not now dismisses an unstarted card whose kind is no longer registered.
- The unused ready prop and dead locale keys are removed, and the READMEs
  state the card and row rules as implemented.
2026-10-22 08:01:23 -07:00
ZiyaZhang fcb7340be1 refactor(experimental): register plugin recommendations as an action card kind
Plugin recommendations now proposes through the shared propose_action tool
instead of a dsh-action answer block. The Host registers the
enable_official_plugin kind with the action card service: the
official-plugins skill, details holding the plugin name, the Enable verb
with global access, and the enabled, already-enabled and failed phases,
whose data carries the application outcome and the management error code.
The package drops its own projection, Remote act, status notice and
persisted record; it keeps the describe Remote for card text. The bundle
inserts the shared card rows beside its own, as Personalized pages does.
The browser half registers a card body in the shared frame that keeps the
catalog text cache, the reserved loading lines, the single details target
and the Enable and Not now footer. The skill's submission section now asks
for one propose_action call.
2026-10-22 07:18:05 -07:00
ZiyaZhang c6d9a964d3 Merge feat/creation-recommendations into plugin recommendation experiment 2026-10-22 06:50:25 -07:00
ZiyaZhang 9b04d772b9 feat(experimental): propose personalized pages through action cards
Personalized pages registers the create_personalized_page card kind with
its create, keep, undo, cancel and restore handlers and drops its own
projection, Remote and status notice. The skill now ends with a
propose_action call. The Client package contributes only the page card
body. The persistence record moves from the page status source to the
shared action-cards source and decision record.
2026-10-22 06:36:30 -07:00
winewill cda5c51b4f merge: reconcile desktop diagnostics with master 2026-10-22 18:47:16 +08:00
ZiyaZhang caa5535dee Merge feat/creation-recommendations into plugin recommendation experiment 2026-10-22 02:47:01 -07:00
ZiyaZhang 80997ea36a Merge master into personalized pages experiment 2026-10-22 02:34:47 -07:00
ZiyaZhang ea91bd7c16 feat(experimental): restore a removed page from its card 2026-10-21 23:38:49 -07:00
Turtle f59f0dfc67 fix(plugin-manager): install self-hosted Git plugins over SSH when only SSH can read them
Refs #6938
2026-10-22 13:42:56 +08:00
ZiyaZhang 50be7d37c9 feat(experimental): recommend official plugins through dsh-action answer blocks
Replaces list_official_plugins, suggest_plugin and the routing prompt
section with the official-plugins skill, whose load appends the live
catalog, and an enable_official_plugin block at the end of the answer.
The card reads catalog text from the Host, Enable goes through the plugin
manager, and each outcome reaches the model as a status notice on the
next request. Adds the queuedMessageLimit option, en/zh/ja card copy and
a re-recorded persistence change and Web replay.
2026-10-21 10:50:48 -07:00
ZiyaZhang 7cafebe528 Merge feat/creation-recommendations into plugin recommendation experiment 2026-10-21 09:11:34 -07:00
ZiyaZhang 1df9e40786 fix(experimental): avoid repeated discovery and honor declined recommendations 2026-10-20 05:11:51 -07:00
ZiyaZhang c97c9d4f8e fix(experimental): prioritize recommendation eligibility and refresh skill replay 2026-10-20 05:11:38 -07:00
ZiyaZhang 6543e1c3e5 feat(experimental): refine personalized page placement and first-use notice 2026-10-20 02:54:53 -07:00
ZiyaZhang 420a4ae6fd feat(experimental): offer personalized pages independently of plugin recommendations 2026-10-20 00:35:51 -07:00
winewill e9e7722d53 fix(desktop): preserve safe operation diagnostics across failures 2026-10-20 15:09:37 +08:00
ZiyaZhang 8145f4c05d fix(plugin-recommendations): settle actions safely across HMR and replay 2026-10-19 21:32:36 -07:00
ZiyaZhang facceb8be9 feat(experimental): recommend official plugins after completed answers 2026-10-19 07:46:24 -07:00
turtle1999 9c8522bb64 feat(plugin-detail): show Markdown plugin details on bundle and market entry pages
Plugins bundle pages and Discover entry pages show the plugin's long
description first, as Markdown with images, in a height-limited region
without its own heading. The document is the file locale meta.detail
names, otherwise the package README, otherwise (market entries only)
the declared repository's README.

The new dsh-plugin-detail library selects documents and reads local
package directories and npm file CDNs without state. plugin-manager
reads installed and offered bundles through readBundleDetail; plugin-market
reads market entries through readEntryDetail, single-file APIs, and a
size-limited partial clone cache serialized across processes. Raw HTML is
omitted, relative links stay text, and relative images load from Host
routes with a sandbox CSP.
2026-10-19 19:13:22 +08:00
winewill dfbe5d8da3 feat(desktop): retain bounded plugin operation diagnostics 2026-10-19 17:35:18 +08:00
turtle1999 b10bd84dfe feat(plugins): check and install newer registry versions of third-party bundles 2026-10-19 15:40:51 +08:00
Tianyi Cui cec41e73e0 fix(headless): validate invocation policy across custom profiles 2026-10-18 11:13:48 +08:00
turtle1999 3de3a977e0 feat(plugin-market): add the Custom plugin markets bundle and Discover tab
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.
2026-10-15 05:37:44 +08:00
turtle1999 879ad372ac feat(hmr): replace plugins whose package files changed during profile recomposition
With HMR, installing, enabling, disabling and removing bundles take effect live. Each profile recomposition compares
the loaded modules below the profile directory and its linked targets with disk, stops the plugins whose files
changed, and recomposes the profile through app-boot's recomposeProfile(): the rows the next generation drops are
removed first, the latest runtime resolution is published once, and the generation is applied and judged. Afterwards
HMR evicts the modules below the mappings the recomposition dropped.

- app-boot: recomposeProfile(); PluginPackages.resolution; ResolutionRestartRequired; the resolver accepts in-place
  version changes and relinks, and relocates Node's cached link real paths.
- plugin-manager: with HMR, installBundle refuses an installed package (already-installed), so an upgrade is a
  removal and an installation; every restart-required result carries a restartReason; removal uses the registry the
  package was installed from.
- ui-plugin-manager: the Official Update removes and then installs; restart prompts name their reason.
2026-10-13 22:15:57 +08:00
Turtle b173f3e2a2 revert(plugin): drop preset-scoped profile patches; ship optional tools as global Host rows
Remove the `{ preset, insert }` / `{ preset, id, ...override }` profile patch
operation added in #5773, together with the app-boot compiler and reload drain,
config-editor filtering, plugin-manager preset row inventory and retained-module
removal checks, the read-only preset rows on the Plugins page, and the
agent-preset-registry row identities that served them.

Session search, Ralph, persistent terminals, Codex, and Claude Code bundles now
insert ordinary Host rows whose tools register in the global tool layer, like the
earlier optional bundles. Every preset, including minimal, sees them, and toggling
a bundle updates live Agents without new composition generations.
2026-10-07 20:46:37 +08:00
Tianyi Cui e9a68b2484 fix(plugin): clarify on-demand recovery and preserve package diagnostics 2026-10-07 01:26:00 +08:00
Tianyi Cui c135bdf483 test(plugin): refresh official discovery browser and API evidence 2026-10-07 01:26:00 +08:00
Tianyi Cui 8ed0b530ed feat(plugins): offer official bundles through on-demand installation 2026-10-07 01:26:00 +08:00
Tianyi Cui 996007e103 fix(plugin): retain scoped row identity and source diagnostics 2026-10-06 23:48:59 +08:00
Tianyi Cui 8a9767c25e feat(plugin): validate optional bundle lifecycles and session output 2026-10-06 23:48:58 +08:00
Tianyi Cui 3aa1cab43a feat(plugin): compose optional bundles inside agent presets 2026-10-06 23:48:58 +08:00
Turtle 9c5fb6b0c5 Merge pull request #5550 from deepseek-harness/turtle/plugin-version-hint-66b6a2501f82
feat(plugin-manager): name the exact spec when pnpm installs an older version
2026-10-01 12:36:36 +08:00
Turtle 43c5f1e924 fix(plugin-manager): explain another installed version only for one-registry runs 2026-09-30 18:42:32 +08:00
turtle1999 f18d1911c6 chore: regenerate the Cordis catalog for the removeBundle contract 2026-09-30 17:52:03 +08:00
turtle1999 9b79f97010 fix(plugins): keep aliases and whole user information in bundle sources
Address the second ds-review-bot round on the bundle Source section:

- remove an http(s) URL's user information up to its last `@`, so a
  username containing `@` no longer leaves the password behind;
- keep the dependency name before a local or git spec when the package's
  own manifest name differs, so reinstalling restores the alias;
- accept scp-like git addresses with any user name;
- show Built in for a profile dependency whose loaded copy the
  installation supplies, instead of hiding the section;
- align the PackageView, subsystem page, and README wording with the
  shadowing rule and the kept query string, and assert the source of
  not-bundle and unreadable bundles.
2026-09-29 13:27:43 +08:00
turtle1999 6d1e12b237 fix(plugins): keep credentials and shadowed copies out of bundle sources
Address the first ds-review-bot round on the bundle Source section:

- strip the user information of http(s) and git+http(s) URLs so a private
  Git URL's token reaches neither the page nor the plugin_manager tool;
- expand `~` in file:/link: paths to the home directory as pnpm does;
- write jsr: aliases after the dependency name, like npm: aliases;
- give no source for a profile dependency the installation also supplies,
  whose installation copy is the one that loads;
- label the English row "Code source" to match the Chinese copy and hold
  for built-in bundles, and sync the subsystem page, READMEs, CSS comment,
  and tool test.
2026-09-29 12:07:56 +08:00
turtle1999 b96959ecf4 feat(plugins): show where a bundle comes from on its page
The bundle page ends with a Source section: the spec that installs the
bundle elsewhere, as `pnpm add` accepts it, or Built in for an official
bundle the installation ships, followed by its current version.

The Host's listBundles carries the new `source` field for profile
dependencies: git addresses and URLs as recorded, file:/link: paths made
absolute against the profile, and registry ranges, tags, or aliases after
the package name.
2026-09-29 10:51:33 +08:00
turtle1999 2c67633990 feat(plugins): enforce DSH peer compatibility with exact exemptions 2026-09-23 18:46:08 +08:00
Turtle ccaa0dc11c fix(plugin-manager): bound pnpm runs so a silent child cannot hold the profile lock (#4982)
* fix(plugin-manager): bound pnpm runs so a silent child cannot hold the profile lock

A pnpm child that prints its completion line and then never exits holds the
profile write lock until the host is restarted, so every other session and host
on that profile fails after its own lock timeout (issue #4981). execa resolves
its promise only once the piped stdio has ended, so a run now completes on the
process's own exit and drains the pipes under a bound instead of awaiting their
end.

A service run whose captured output stays silent for idleTimeoutMs is
terminated, reports timedOut alongside its exit status, and is not retried on
the next registry; a run with inherited descriptors captures nothing and is
left unbounded for its operator.

* test(plugin-manager): type the mocked child and await the drain descendants

The inherited-descriptor fixture no longer needs its legacy `as unknown` cast,
because the mocked child is typed for the fields the operations read; the
retired baseline entry is pruned (verify-no-unknown-casts).

The drain specs wait for the killed descendant to exit before removing its
directory: Windows refuses to delete a directory a live process still holds.

* test(plugin-manager): stop the drain descendant deterministically

The descendant that holds the pipes now ends on a stop file the teardown
writes, and on its own after a minute, so the fixture leaves no process behind
when a kill cannot be delivered. Windows stops it through taskkill, and the
spec waits for the exit before removing the directory it ran in.

* test(plugin-manager): run the drain descendant from its own script file

Windows cannot carry a nested `-e` script through another spawn argument: the
descendant failed to start there, so the fixture asserted on a process that was
already gone. The descendant now runs from a script file the fixture writes.

* test(plugin-manager): cover the bounded drain everywhere and stage the real descendant on POSIX

Windows does not stage a descendant that keeps the inherited pipes open past
the direct child's exit, so the real-process cases run on POSIX only. The
mocked child now models execa's own completion rule — its promise settles only
once both pipes end — which covers the bounded drain on every platform and
still fails without the raw-exit race.

* test(plugin-manager): cover the drain failure path without a child process

An output consumer failure that the bounded drain cuts short is staged with the
mocked child as well, so the per-file coverage gate also holds where the
real-process cases are skipped.

* fix(plugin-manager): terminate the whole tree of a stalled run

A lifecycle script is a child of pnpm, so signalling pnpm alone left an
approved postinstall writing into the profile after the operation reported a
timeout and released the lock. A stalled run now stops its process group (or
Windows process tree) and waits for it to disappear before the caller restores
the files. The cut tail's close is told apart from a reading failure by where it
happened, so a failure from before the cut still surfaces.

* docs(plugin-manager): regenerate the config catalog after the rebase

The English catalog gains `idleTimeoutMs` from the regenerator, and the Chinese
counterpart carries the same interface line so the pair stays consistent.

* fix(plugin-manager): terminate a run's tree through execa, keeping exit cleanup

Spawning a service run with `detached` made execa skip the handler that kills
the child when the manager exits, so a crashed manager left the pnpm tree
running in the profile. `killDescendants` spawns the run as its own process
group while keeping that cleanup, and it addresses the tree on every kill path,
including cancellation. The module now only decides the probe target and waits
for quiescence.
2026-09-23 16:11:30 +08:00
ZiyaZhang 75d74a055e fix(plugin-manager): preserve authentication fallback during GitHub checks 2026-09-22 22:15:09 -07:00
ZiyaZhang 0edfe83573 fix(plugin-manager): bound GitHub connection checks before installation 2026-09-22 08:33:49 -07:00
Yichen Jiang 3c50bf6b6c feat(plugin-manager): choose the first responsive public registry 2026-09-22 18:38:43 +08:00
Yichen Jiang 8cf07ea76c fix(plugin-manager): preserve remembered registries during initial lookup 2026-09-22 15:32:16 +08:00
Yichen Jiang dccf989cd8 feat(plugin-manager): prefer the mainland mirror for CN network exits 2026-09-22 12:37:32 +08:00
Turtle 601d6761e4 feat(settings): project volatile Config through profile-backed forms (#4587) 2026-09-21 18:26:03 +08:00