mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-03-12 17:37:24 +00:00
fix: coderabbit changes and new plugin name & repo
This commit is contained in:
@@ -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 */}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user