fix: coderabbit changes and new plugin name & repo

This commit is contained in:
simosmik
2026-03-06 11:50:01 +00:00
parent a09aa5f68e
commit 0a3e22905f
11 changed files with 122 additions and 768 deletions

View File

@@ -1,5 +1,5 @@
import { useState } from 'react';
import { Trash2, RefreshCw, GitBranch, Loader2, ServerCrash, ChevronRight } from 'lucide-react';
import { Trash2, RefreshCw, GitBranch, Loader2, ServerCrash, ChevronRight, ShieldAlert, ExternalLink, BookOpen } from 'lucide-react';
import { usePlugins } from '../../contexts/PluginsContext';
import PluginIcon from './PluginIcon';
import type { Plugin } from '../../contexts/PluginsContext';
@@ -314,6 +314,43 @@ export default function PluginSettingsTab() {
{installError && (
<p className="mt-2 text-xs font-mono text-red-500">{installError}</p>
)}
<p className="mt-2.5 flex items-start gap-1.5 text-[11px] text-muted-foreground/60 leading-snug">
<ShieldAlert className="w-3 h-3 mt-px flex-shrink-0" />
<span>
Plugins run with full access to the host page. Only install plugins
whose source code you have reviewed or from authors you trust.
</span>
</p>
</div>
{/* Build your own */}
<div className="flex items-center gap-4 rounded-md border border-dashed border-border/60 px-4 py-3">
<BookOpen className="w-4 h-4 text-muted-foreground/50 flex-shrink-0" />
<div className="flex-1 min-w-0">
<p className="text-xs text-muted-foreground">
Build your own plugin or start from an example.
</p>
</div>
<div className="flex items-center gap-3 flex-shrink-0">
<a
href="https://github.com/cloudcli-ai/cloudcli-plugin-starter"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground transition-colors"
>
Starter plugin <ExternalLink className="w-3 h-3" />
</a>
<span className="text-border">|</span>
<a
href="https://cloudcli.ai/docs/plugin-overview"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground transition-colors"
>
Docs <ExternalLink className="w-3 h-3" />
</a>
</div>
</div>
{/* Plugin List */}

View File

@@ -9,7 +9,7 @@ export type Plugin = {
description: string;
author: string;
icon: string;
type: 'iframe' | 'react' | 'module';
type: 'react' | 'module';
slot: 'tab';
entry: string;
server: string | null;
@@ -22,11 +22,12 @@ export type Plugin = {
type PluginsContextValue = {
plugins: Plugin[];
loading: boolean;
pluginsError: string | null;
refreshPlugins: () => Promise<void>;
installPlugin: (url: string) => Promise<{ success: boolean; error?: string }>;
uninstallPlugin: (name: string) => Promise<{ success: boolean; error?: string }>;
updatePlugin: (name: string) => Promise<{ success: boolean; error?: string }>;
togglePlugin: (name: string, enabled: boolean) => Promise<void>;
togglePlugin: (name: string, enabled: boolean) => Promise<{ success: boolean; error: string | null }>;
};
const PluginsContext = createContext<PluginsContextValue | null>(null);
@@ -42,6 +43,7 @@ export function usePlugins() {
export function PluginsProvider({ children }: { children: ReactNode }) {
const [plugins, setPlugins] = useState<Plugin[]>([]);
const [loading, setLoading] = useState(true);
const [pluginsError, setPluginsError] = useState<string | null>(null);
const refreshPlugins = useCallback(async () => {
try {
@@ -49,8 +51,20 @@ export function PluginsProvider({ children }: { children: ReactNode }) {
if (res.ok) {
const data = await res.json();
setPlugins(data.plugins || []);
setPluginsError(null);
} else {
let errorMessage = `Failed to fetch plugins (${res.status})`;
try {
const data = await res.json();
errorMessage = data.details || data.error || errorMessage;
} catch {
errorMessage = res.statusText || errorMessage;
}
setPluginsError(errorMessage);
}
} catch (err) {
const message = err instanceof Error ? err.message : 'Failed to fetch plugins';
setPluginsError(message);
console.error('[Plugins] Failed to fetch plugins:', err);
} finally {
setLoading(false);
@@ -110,20 +124,32 @@ export function PluginsProvider({ children }: { children: ReactNode }) {
}
}, [refreshPlugins]);
const togglePlugin = useCallback(async (name: string, enabled: boolean) => {
const togglePlugin = useCallback(async (name: string, enabled: boolean): Promise<{ success: boolean; error: string | null }> => {
try {
await authenticatedFetch(`/api/plugins/${encodeURIComponent(name)}/enable`, {
const res = await authenticatedFetch(`/api/plugins/${encodeURIComponent(name)}/enable`, {
method: 'PUT',
body: JSON.stringify({ enabled }),
});
if (!res.ok) {
let errorMessage = `Toggle failed (${res.status})`;
try {
const data = await res.json();
errorMessage = data.details || data.error || errorMessage;
} catch {
// response body wasn't JSON, use status text
errorMessage = res.statusText || errorMessage;
}
return { success: false, error: errorMessage };
}
await refreshPlugins();
return { success: true, error: null };
} catch (err) {
console.error('[Plugins] Failed to toggle plugin:', err);
return { success: false, error: err instanceof Error ? err.message : 'Toggle failed' };
}
}, [refreshPlugins]);
return (
<PluginsContext.Provider value={{ plugins, loading, refreshPlugins, installPlugin, uninstallPlugin, updatePlugin, togglePlugin }}>
<PluginsContext.Provider value={{ plugins, loading, pluginsError, refreshPlugins, installPlugin, uninstallPlugin, updatePlugin, togglePlugin }}>
{children}
</PluginsContext.Provider>
);