mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-19 13:33:35 +08:00
Plugin enablement already has a live CLI reload control path, so desktop now applies plugin changes by refreshing the active session instead of waiting for a future conversation startup. The server forwards reload_plugins to the active CLI session, refreshes session slash-command cache, and notifies the client. The desktop plugin store automatically reloads after mutating plugin state, and the empty-session composer refetches skills when plugin capabilities change. Constraint: Existing CLI exposes reload_plugins as the supported hot-refresh mechanism for commands, agents, plugins, and MCP state. Rejected: Start a hidden replacement CLI process | higher cost, extra process lifecycle risk, and less precise than the existing control channel. Confidence: high Scope-risk: moderate Directive: Keep plugin refresh routed through reload_plugins unless the CLI control contract is removed or changed. Tested: bun test src/server/__tests__/plugins.test.ts Tested: cd desktop && bun run test --run src/stores/pluginStore.test.ts src/__tests__/pluginsSettings.test.tsx src/pages/EmptySession.test.tsx Tested: bun run check:server Tested: cd desktop && bun run lint Tested: cd desktop && bun run build Not-tested: bun run check:desktop is blocked by a pre-existing color-mix compatibility failure in desktop/src/theme/globals.css.
92 lines
2.1 KiB
TypeScript
92 lines
2.1 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { usePluginStore } from './pluginStore'
|
|
import { pluginsApi } from '../api/plugins'
|
|
|
|
vi.mock('../api/plugins', () => ({
|
|
pluginsApi: {
|
|
list: vi.fn(),
|
|
detail: vi.fn(),
|
|
enable: vi.fn(),
|
|
disable: vi.fn(),
|
|
update: vi.fn(),
|
|
uninstall: vi.fn(),
|
|
reload: vi.fn(),
|
|
},
|
|
}))
|
|
|
|
const mockedPluginsApi = vi.mocked(pluginsApi)
|
|
|
|
describe('pluginStore', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
mockedPluginsApi.list.mockResolvedValue({
|
|
plugins: [],
|
|
marketplaces: [],
|
|
summary: { total: 0, enabled: 0, errorCount: 0, marketplaceCount: 0 },
|
|
})
|
|
mockedPluginsApi.reload.mockResolvedValue({
|
|
ok: true,
|
|
summary: {
|
|
enabled: 1,
|
|
disabled: 0,
|
|
skills: 1,
|
|
agents: 0,
|
|
hooks: 0,
|
|
mcpServers: 0,
|
|
lspServers: 0,
|
|
errors: 0,
|
|
},
|
|
session: {
|
|
applied: true,
|
|
commands: 1,
|
|
agents: 0,
|
|
plugins: 1,
|
|
mcpServers: 0,
|
|
errors: 0,
|
|
},
|
|
})
|
|
usePluginStore.setState({
|
|
plugins: [],
|
|
marketplaces: [],
|
|
summary: null,
|
|
selectedPlugin: null,
|
|
lastReloadSummary: null,
|
|
isLoading: false,
|
|
isDetailLoading: false,
|
|
isApplying: false,
|
|
error: null,
|
|
})
|
|
})
|
|
|
|
it('reloads the active CLI session after enabling a plugin', async () => {
|
|
mockedPluginsApi.enable.mockResolvedValue({
|
|
ok: true,
|
|
message: 'enabled',
|
|
})
|
|
|
|
const message = await usePluginStore
|
|
.getState()
|
|
.enablePlugin('draw@test', 'user', '/workspace/project', 'session-1')
|
|
|
|
expect(message).toBe('enabled')
|
|
expect(mockedPluginsApi.enable).toHaveBeenCalledWith({
|
|
id: 'draw@test',
|
|
scope: 'user',
|
|
})
|
|
expect(mockedPluginsApi.reload).toHaveBeenCalledWith(
|
|
'/workspace/project',
|
|
'session-1',
|
|
)
|
|
expect(usePluginStore.getState().lastReloadSummary).toEqual({
|
|
enabled: 1,
|
|
disabled: 0,
|
|
skills: 1,
|
|
agents: 0,
|
|
hooks: 0,
|
|
mcpServers: 0,
|
|
lspServers: 0,
|
|
errors: 0,
|
|
})
|
|
})
|
|
})
|