mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +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.
56 lines
1.6 KiB
TypeScript
56 lines
1.6 KiB
TypeScript
import { api } from './client'
|
|
import type {
|
|
PluginDetail,
|
|
PluginListResponse,
|
|
PluginReloadSummary,
|
|
PluginSessionReloadSummary,
|
|
PluginScope,
|
|
} from '../types/plugin'
|
|
|
|
type PluginActionPayload = {
|
|
id: string
|
|
scope?: PluginScope
|
|
keepData?: boolean
|
|
}
|
|
|
|
export const pluginsApi = {
|
|
list: (cwd?: string) => {
|
|
const query = cwd ? `?cwd=${encodeURIComponent(cwd)}` : ''
|
|
return api.get<PluginListResponse>(`/api/plugins${query}`)
|
|
},
|
|
|
|
detail: (id: string, cwd?: string) => {
|
|
const query = new URLSearchParams({ id })
|
|
if (cwd) query.set('cwd', cwd)
|
|
return api.get<{ detail: PluginDetail }>(`/api/plugins/detail?${query.toString()}`)
|
|
},
|
|
|
|
enable: (payload: PluginActionPayload) =>
|
|
api.post<{ ok: true; message: string }>('/api/plugins/enable', payload),
|
|
|
|
disable: (payload: PluginActionPayload) =>
|
|
api.post<{ ok: true; message: string }>('/api/plugins/disable', payload),
|
|
|
|
update: (payload: PluginActionPayload) =>
|
|
api.post<{ ok: true; message: string }>('/api/plugins/update', payload),
|
|
|
|
uninstall: (payload: PluginActionPayload) =>
|
|
api.post<{ ok: true; message: string }>('/api/plugins/uninstall', payload),
|
|
|
|
reload: (cwd?: string, sessionId?: string) => {
|
|
const query = new URLSearchParams()
|
|
if (cwd) query.set('cwd', cwd)
|
|
if (sessionId) query.set('sessionId', sessionId)
|
|
const suffix = query.size > 0 ? `?${query.toString()}` : ''
|
|
return api.post<{
|
|
ok: true
|
|
summary: PluginReloadSummary
|
|
session?: PluginSessionReloadSummary
|
|
}>(
|
|
`/api/plugins/reload${suffix}`,
|
|
undefined,
|
|
{ timeout: 120_000 },
|
|
)
|
|
},
|
|
}
|