feat(plugin-inventory): live plugin activation, mirror install, and toggle lists

Installing a plugin now activates it without a restart: the CLI boot provides a
dshReloadProfile handle that re-runs the profile composition and applies it to
the running root Include, and the install/uninstall Remotes recompose live when
the handle is present (restartRequired: false). Registry installs try the
ordered INSTALL_REGISTRIES mirrors with the official npm registry as the final
fallback, erroring only when every source is unreachable. The enable/disable
guard splits into a REQUIRED_PLUGINS blacklist and a USER_TOGGLEABLE_PLUGINS
whitelist (default toggleable) generated from the running plugin list, and the
offline optional-bundle catalog is emptied (default bundles are not
installable/uninstallable). The plugin-list tab becomes a registry install form
and shows immediate-activation instead of a restart notice.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Pine
2026-08-14 20:45:00 +08:00
parent a0efe02c04
commit e18cfbfb93
16 changed files with 486 additions and 196 deletions
@@ -4,22 +4,24 @@ import { isRequiredPlugin, isUserToggleable } from '../src/required.ts'
describe('isRequiredPlugin (blacklist/whitelist, default-open)', () => {
it('marks the blacklist core as required', () => {
for (const name of ['@deepseek-ai/cordis-plugin-loader', '@deepseek-ai/dsh-session', 'cordis:required']) {
for (const name of ['@deepseek-ai/cordis-plugin-loader', '@deepseek-ai/dsh-session', 'cordis:required', 'cordis:include']) {
expect(isRequiredPlugin(name)).toBe(true)
expect(isUserToggleable(name)).toBe(false)
}
})
it('defaults everything else to toggleable', () => {
for (const name of ['@deepseek-ai/dsh-hmr', '@deepseek-ai/dsh-tool-todo', 'cordis:user-toggleable']) {
it('whitelists the currently-disabled set as toggleable', () => {
for (const name of [
'@deepseek-ai/dsh-tool-pwsh', '@deepseek-ai/dsh-skill-badge',
'@deepseek-ai/dsh-session-telemetry-otel', '@deepseek-ai/dsh-pwsh-sandbox',
]) {
expect(isRequiredPlugin(name)).toBe(false)
expect(isUserToggleable(name)).toBe(true)
}
})
it('whitelist overrides the blacklist for an explicitly toggleable plugin', () => {
// image-recognition is on the whitelist, so it is never required.
for (const name of ['@deepseek-ai/dsh-image-recognition', '@deepseek-ai/dsh-image-recognition-http']) {
it('defaults unknown modules to toggleable', () => {
for (const name of ['@fixture/never', 'cordis:user-toggleable']) {
expect(isRequiredPlugin(name)).toBe(false)
expect(isUserToggleable(name)).toBe(true)
}
@@ -27,8 +29,7 @@ describe('isRequiredPlugin (blacklist/whitelist, default-open)', () => {
})
describe('AVAILABLE_BUNDLES', () => {
it('lists the offline-installable optional bundles', () => {
expect(AVAILABLE_BUNDLES).toContain('@deepseek-ai/dsh-image-recognition-bundle')
expect(new Set(AVAILABLE_BUNDLES).size).toBe(AVAILABLE_BUNDLES.length)
it('is empty: no optional bundles ship as offline-installable yet', () => {
expect(AVAILABLE_BUNDLES).toEqual([])
})
})