Review follow-up on #126: RemovePlugin used to call
setPluginEnabled(name, false), which left the plugin's key in
EnabledPlugins and never touched PluginConfigs. settings.json retained
dangling state for plugins no longer on disk.
Replace the disable with purgePluginFromSettings, which deletes both
the EnabledPlugins entry and any PluginConfigs entry for the removed
plugin, leaving unrelated plugins' state intact. A re-install defaults
to enabled=true via the existing install paths, matching user
expectations.
Covered by TestRemovePluginPurgesSettings across both user and legacy
managed layouts.
Drop the hardcoded default-managed-plugin bootstrap that auto-fetched
DingTalk-Real-AI/* plugins on CLI startup. All third-party plugins are
now installed equally via `dws plugin install` — no privileged workspace.
Motivation (issue #124): first-run startup printed
WARN failed to fetch remote info for default plugin
DingTalk-Real-AI/conference: invalid character '<' looking for
beginning of value
because the GitHub Pages registry returned HTML for the missing plugin.
Beyond the error, the whole "built-in plugin" concept contradicts the
CLI's lightweight design: plugin installation planning belongs to
agent-authored skills, not to the CLI binary.
Changes:
- Delete internal/plugin/updater.go (EnsureManaged, CheckAndUpdate,
checkRemoteVersion, downloadAndInstall, promptUpdate, zip extraction
— the entire managed-plugin update pipeline).
- Delete internal/plugin/updater_test.go.
- Remove DefaultManagedPlugins, OfficialPluginWorkspace, and
PluginUpdateCheckInterval from pkg/config/constants.go.
- Remove the EnsureManaged/CheckAndUpdate bootstrap block from
internal/app/root.go; only legacy LoadManaged() kept for back-compat
so plugins already installed under ~/.dws/plugins/managed/ still load.
- internal/plugin/loader.go: InstallFromGit always installs under
PluginUserDir; RemovePlugin allows removal of legacy managed-dir
plugins instead of refusing.
- internal/app/plugin_cmd.go: drop `--type managed` flag and related
gating from `plugin install`; disable/remove commands no longer
differentiate managed vs user.
- Update plugin_test.go accordingly (replace TestRemoveManagedPluginBlocked
with TestRemoveLegacyManagedPlugin, drop TestPromptUpdate).
Backward compatibility: `PluginManagedDir = "managed"` constant retained
so plugins already on disk from older CLI versions still load and are
removable. No migration required.
Verification:
- go build ./cmd → success
- go test ./internal/plugin/... → PASS
- go test ./internal/app/... → PASS (436s, matches main baseline)
- Smoke: `/tmp/dws-new plugin list` no longer prints the "Pulling
built-in plugin" or "failed to fetch remote info" WARN.
- Pre-existing failures on main (unrelated): test/cli_compat,
test/integration/extensions (requires auth login),
test/scripts (requires DWS_PACKAGE_VERSION or git tag),
test/unit TestOpenSourceTreeOmitsEmbeddedHostMarkers.
Closes#124
- Add `EnsureManaged` to the plugin updater to automatically install missing default plugins on startup.
- Translate the managed plugin removal error message to English for better consistency.
- Update tests to match the new error message.
- Add updater.go for managed plugin auto-update (version check, download,
Y/n prompt, zip extraction with zip-slip protection)
- Add stdio.go transport for local MCP server subprocess communication
via stdin/stdout JSON-RPC 2.0
- Implement InstallFromGit in loader.go with URL parsing for HTTPS/SSH
- Wire up --git flag in plugin install command
- Switch all plugin CLI output to English (headers, status, messages)
- Add tests for parseGitURL and promptUpdate
Introduce the plugin system for DWS CLI, enabling official and third-party
plugin management. This includes plugin manifest parsing/validation, loader
with managed/user directory-based identity, MCP server conversion and
injection into the dynamic routing registry, pipeline hook adapter for
shell-based hooks, and CLI commands (list/install/info/enable/disable/
remove/validate).