Foreword¶
The philosophy of DSH is “everything is a plugin”; most functional extensions are achieved by installing plugins. However, installing plugins is still a manual task: manually running installation commands, modifying configurations, and restarting processes. After restarting, the current conversation is severed; the model either has to start from scratch or you manually paste the context back. Worse still, if a newly installed plugin breaks the startup, DSH fails to start, and you have to rely on yourself to delete dependencies and restore configurations.
dsh-plugin-installer encapsulates the entire pipeline of “backup → install/uninstall → restart → auto continue conversation” into a model tool, handed over to the model to execute, with automatic rollback on failure or abnormal startup. Below is an introduction to its features, usage, and precautions.
What is it¶
dsh-plugin-installer is a DSH plugin maintained by Quophic (current version 0.4.1, MIT license). It provides three model tools: install_plugin, uninstall_plugin, and restart_dsh, covering plugin installation, uninstallation, and restart. It is a host-side plugin and does not require a browser UI. It requires Node ^22.19.0 || >=24.0.0.
The Three Model Tools¶
install_plugin¶
Install a persistent plugin (bundle) to a specified profile. The flow is fixed:
- Backup: Automatically backs up the profile’s
package.json,cordis.patch.yml,cordis.yml, andsettings.yamlto$DSH_HOME/backups/plugin-install-<timestamp>/before installation, including a manifest list. - Install: Calls the official
dsh plugin --profile <name> add <package>, which follows the same path aspnpm addwith bundles reconciliation. - Success: Records the currently running session → automatically restarts DSH → injects a “continue” prompt into the session after restart completes, seamlessly resuming the conversation.
- Installation command fails: Automatically rolls back the backup → restarts DSH → writes the problem into the session, allowing the agent to analyze and resolve it.
- DSH fails to start after restart: A separate detached helper probes the port; if it fails to start, it automatically rolls back the backup and restarts again, then writes the rollback result into the session.
uninstall_plugin¶
Uninstall an installed plugin. It mirrors the protection of installation: backup first, then call the official dsh plugin --profile <name> remove <package>, restart and resume the conversation after success. The difference lies in the rollback action—when the uninstall command fails, startup fails after uninstallation, or the tool health is abnormal, in addition to rolling back the backup, it re-installs the plugin to wrap it back up, restoring the state before uninstallation (e.g., a package removed that was referenced by other configurations).
restart_dsh¶
Restarts DSH only, without installing, uninstalling, or modifying any plugins or configurations. Records the current session → restarts in a hidden console manner (no window flash) → automatically resumes the conversation after restart. Suitable for making newly loaded plugins or latest configurations take effect and restoring normal process state. Note that it lacks the backup, rollback, and tool health verification protection of the installation process.
Tool Health Verification: Port Up Does Not Mean Everything is Normal¶
This is a critical layer of protection for this plugin. There is a class of malformed code—such as the tool’s parameters: {} empty object, or passing raw properties directly to ctx.tools.register (without defineTool compilation)—which does not throw an error during registration, but when DSH projects tools to the LLM, the API rejects it. This manifests as an Invalid schema for function 'X' error in every conversation, making chatting impossible.
Therefore, getting the port up is not the end of the story: the plugin in the new process audits the parameter schemas of all registered tools (requiring top-level type: 'object'). If such malformed code is discovered during the audit, it automatically rolls back the backup and restarts again, writing the problem details into the session.
Updating Plugins and Self-Update¶
install_plugin automatically performs a “remove then add” forced refresh for any installed package (not limited to this plugin itself). The reason to remove before adding is that pnpm reuses stale copies for file: dependencies when the version number remains unchanged; a direct add will not refresh them. For daily updates of local plugins under development:
{
"package": "file:E:/GitHub/dsh-plugins/xxx",
"profile": "web",
"restart": true
}
It doesn’t matter if the version number hasn’t changed; it will be reinstalled from the latest source code. The same applies to updating this plugin itself (self-upgrade):
{
"package": "file:E:/GitHub/dsh-portal/dsh-plugin-installer",
"profile": "web",
"restart": true
}
Two precautions:
file:paths must use forward slashes (file:E:/...); backslashes will be consumed by the shell as escapes, causing the package to not be found.file:sources carry their own version numbers, and theversionparameter only applies to npm package names.- The complete workflow for updating local source code: modify
src/→npm run build→ invoke the tool → the new logic takes effect after restart.
Update operations are also subject to single-time privilege approval (sessions not in danger-full-access mode will request owner approval) and allowProfiles whitelist constraints.
Permission Control¶
Installation, uninstallation, and restart are sensitive actions. The plugin incorporates two layers of constraints:
- Prompt Layer: The plugin injects a
systemPromptsection, explicitly telling the model that “installing/upgrading persistent plugins must callinstall_plugin, and uninstallation must calluninstall_plugin; do not runpnpm/dshcommands directly.” - Approval Layer: Single-time privilege approval is enabled by default. If the calling session is not in
danger-full-accesssandbox mode, the tool does not hard reject but initiates a single-time privilege approval request to the owner via the approval seam (ctx.approval.request). After approval (allowed-once), the current call is allowed; if rejected, cancelled, or the approval channel is unavailable, it fails closed. This is the same mechanism as thesandbox_permissionselevation of the sandbox bash tool.
Configuration is written on the line for this plugin in the profile’s cordis.patch.yml:
requireApproval: false # Disable approval (any mode can call directly)
allowAuto: true # Fully allow LLM auto-invocation (skip approval)
allowProfiles: ['web'] # Only allow installation/uninstallation to these profiles; empty array = unrestricted
Even when allowed, there is still a secondary whitelist check for allowProfiles inside execute.
Implementation of Restart and Rollback¶
Understanding the mechanism helps with troubleshooting:
- Restart uses the Node native method: spawn a detached helper, wait for the old process to exit and release the port, then relaunch DSH with the same argv/cwd, appending output to
%TEMP%/dsh-install-*.log. - The helper polls the web port (
DSH_WEB_URLor default 3080). If it fails to start within 120 seconds, it is judged as a startup failure, automatically rolling back backup files and launching once more. - Tool Health Verification Protocol: After the port is up, the helper continues to wait for
$DSH_HOME/dsh-install-verify.json(for up to 60 seconds). The plugin in the new process enumerates all registered tools viactx.tools.schemas()and validates them one by one; thetools/changeevent triggers a debounced recheck with a maximum of 6 retries, covering plugins that load late. The conclusion is written to the verify file; ifok: false, it rolls back and relaunches. - Auto-continue conversation: Writes the running session ID to
$DSH_HOME/dsh-install-resume.jsonbefore restart, and injects a followup (a continue prompt for success, or problem details plus resolution guidance for rollback) into the restored session after restart. - All operations are written to
$DSH_HOME/dsh-install.logfor easy troubleshooting.
Installation and Activation¶
The installation command given in the README is in the form of a local file: source:
dsh plugin --profile web add file:E:/GitHub/dsh-portal/dsh-plugin-installer
After installation, restart DSH once. The bundle patch layer loads during startup, and the three model tools can then be used.
Typical Usage¶
The parameters for the three tools are relatively short. Installation:
{
"package": "dsh-xxx",
"profile": "web",
"version": "0.1.0",
"restart": true,
"delayMs": 2000
}
package supports npm package names, file: paths, and git URLs; profile defaults to web; version is an optional version number; restart defaults to true; delayMs is the wait before restart (time for result return), default 2000.
Uninstallation:
{
"package": "dsh-xxx",
"profile": "web",
"restart": true,
"delayMs": 2000
}
Restart directly:
{
"profile": "web",
"delayMs": 2000
}
The profile in restart_dsh is only for recording; the restart is not specific to a single profile. Use install_plugin with restart left as default true when updates involving installation/updates (including backup rollback protection) are needed; use restart_dsh when you just want changes to take effect.
Applicable Scenarios and Notes¶
Suitable for people who often tinker with DSH plugins: maintaining your own plugins requires repeatedly refreshing local file: sources, or you want to hand over the backup, rollback, and continuation process to the model for management.
A few usage notes:
- When
restart: false, it will not restart, and thus tool health verification cannot be performed (this will be noted in the response), and new plugins will only take effect after the next restart. - During rollback, configuration files like
settings.yamlwill be restored; failed installations will not leave half-modified configurations. - The backup directory will accumulate under
$DSH_HOME/backups/and can be cleaned periodically. - The plugin runs with the permissions of the current DSH process and can modify your profile configurations and installed plugins. Before installing or updating any plugin, you should first check its source code and license (this plugin is MIT).
- Engines require Node
^22.19.0 || >=24.0.0.
Conclusion¶
Through the steps above, installing plugins has changed from manual operation to a tool call with backup, rollback, and conversation continuation. Even if DSH breaks during installation, it can recover itself. See the plugin directory page at https://www.skillhub.cn/plugins/Quophic/dsh-plugin-installer and the source code at https://github.com/Quophic/dsh-plugin-installer .