feat(settings): add third-party integrations dashboard

Add a Settings → Integrations page for installing and managing the three
supported OpenCode provider plugins (Claude Code, Command Code, Cursor),
with search, i18n, and plugin-registry status wiring.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
This commit is contained in:
Serhii Dziupin
2026-08-14 15:19:25 +00:00
committed by Cursor Agent
co-authored by Serhii Dziupin
parent 3f266232f9
commit af380081c2
33 changed files with 1562 additions and 7 deletions
+13 -1
View File
@@ -292,12 +292,24 @@ describe('usePluginsStore', () => {
test('loadRegistryInfo skips empty specs and clears loading flag', async () => {
usePluginsStore.setState({ isLoadingRegistry: true });
await usePluginsStore.getState().loadRegistryInfo({ specs: [] });
const result = await usePluginsStore.getState().loadRegistryInfo({ specs: [] });
expect(result).toBe(true);
expect(fetchCalls).toHaveLength(0);
expect(usePluginsStore.getState().isLoadingRegistry).toBe(false);
});
test('loadRegistryInfo reports a failed request without clearing prior registry data', async () => {
usePluginsStore.setState({ registryInfo: { [entry.spec]: registryOk } });
queueFetchResponses([jsonResponse({ error: 'registry unavailable' }, { status: 500 })]);
const result = await usePluginsStore.getState().loadRegistryInfo({ specs: [entry.spec] });
expect(result).toBe(false);
expect(usePluginsStore.getState().registryInfo).toEqual({ [entry.spec]: registryOk });
expect(usePluginsStore.getState().isLoadingRegistry).toBe(false);
});
test('loadPlugins success triggers registry load without blocking result', async () => {
queueFetchResponses([jsonResponse(pluginListPayload), jsonResponse({ results: [registryOk] })]);