From fc0a4b5cdf641b59cfda1759bc616269557309ac Mon Sep 17 00:00:00 2001 From: Bogdan Date: Wed, 10 Jun 2026 03:48:28 +0300 Subject: [PATCH] fix(typecheck): add plugin command view types (#1565) * fix(typecheck): add plugin command view types * fix(typecheck): simplify plugin settings update --- src/commands/plugin/ManagePlugins.tsx | 33 ++++++----- src/commands/plugin/PluginSettings.tsx | 49 ++++++++++------- src/commands/plugin/UnifiedInstalledCell.tsx | 2 +- src/commands/plugin/types.ts | 35 ++++++++++++ src/commands/plugin/unifiedTypes.ts | 58 ++++++++++++++++++++ 5 files changed, 142 insertions(+), 35 deletions(-) create mode 100644 src/commands/plugin/types.ts create mode 100644 src/commands/plugin/unifiedTypes.ts diff --git a/src/commands/plugin/ManagePlugins.tsx b/src/commands/plugin/ManagePlugins.tsx index 1b7d6ca4a..a87f2ac0d 100644 --- a/src/commands/plugin/ManagePlugins.tsx +++ b/src/commands/plugin/ManagePlugins.tsx @@ -236,7 +236,7 @@ function PluginComponentsDisplay({ const pluginEntry = marketplaceData.plugins.find(p => p.name === plugin.name); if (pluginEntry) { // Combine commands from both sources - const commandPathList = []; + const commandPathList: string[] = []; if (plugin.commandsPath) { commandPathList.push(plugin.commandsPath); } @@ -255,7 +255,7 @@ function PluginComponentsDisplay({ } // Combine agents from both sources - const agentPathList = []; + const agentPathList: string[] = []; if (plugin.agentsPath) { agentPathList.push(plugin.agentsPath); } @@ -274,7 +274,7 @@ function PluginComponentsDisplay({ } // Combine skills from both sources - const skillPathList = []; + const skillPathList: string[] = []; if (plugin.skillsPath) { skillPathList.push(plugin.skillsPath); } @@ -294,7 +294,7 @@ function PluginComponentsDisplay({ } // Combine hooks from both sources - const hooksList = []; + const hooksList: unknown[] = []; if (plugin.hooksConfig) { hooksList.push(Object.keys(plugin.hooksConfig)); } @@ -303,7 +303,7 @@ function PluginComponentsDisplay({ } // Combine MCP servers from both sources - const mcpServersList = []; + const mcpServersList: unknown[] = []; if (plugin.mcpServers) { mcpServersList.push(Object.keys(plugin.mcpServers)); } @@ -1468,12 +1468,14 @@ export function ManagePlugins({ for (const source of editableSources) { const settings = getSettingsForSource(source); if (settings?.enabledPlugins?.[pluginId_7] !== undefined) { - updateSettingsForSource(source, { - enabledPlugins: { - ...settings.enabledPlugins, - [pluginId_7]: undefined - } - }); + const enabledPlugins: Record = { + ...settings.enabledPlugins, + [pluginId_7]: undefined + }; + const settingsUpdate: Record = { + enabledPlugins + }; + updateSettingsForSource(source, settingsUpdate); success = true; } } @@ -1509,13 +1511,14 @@ export function ManagePlugins({ // Write `false` directly — disablePluginOp's cross-scope guard would // reject this (plugin isn't in localSettings yet; the override IS the // point). + const enabledPlugins: Record = { + ...(getSettingsForSource('localSettings')?.enabledPlugins ?? {}), + [pluginId_8]: false + }; const { error: error_2 } = updateSettingsForSource('localSettings', { - enabledPlugins: { - ...getSettingsForSource('localSettings')?.enabledPlugins, - [pluginId_8]: false - } + enabledPlugins }); if (error_2) { setIsProcessing(false); diff --git a/src/commands/plugin/PluginSettings.tsx b/src/commands/plugin/PluginSettings.tsx index 131d5f643..79a31bc13 100644 --- a/src/commands/plugin/PluginSettings.tsx +++ b/src/commands/plugin/PluginSettings.tsx @@ -28,7 +28,16 @@ import { type ParsedCommand, parsePluginArgs } from './parseArgs.js'; import type { PluginSettingsProps, ViewState } from './types.js'; import { ValidatePlugin } from './ValidatePlugin.js'; type TabId = 'discover' | 'installed' | 'marketplaces' | 'errors'; -function MarketplaceList(t0) { +type MarketplaceLoadFailure = { + name: string; + error: string; +}; +type ErrorsTabContentProps = { + setViewState: (state: ViewState) => void; + setActiveTab: (tab: TabId) => void; + markPluginsChanged: () => void | Promise; +}; +function MarketplaceList(t0: Pick): React.ReactNode { const $ = _c(4); const { onComplete @@ -336,7 +345,7 @@ function removeExtraMarketplace(name: string, sources: Array<{ if (settings.enabledPlugins) { const suffix = `@${name}`; let removedPlugins = false; - const updatedPlugins = { + const updatedPlugins: Record = { ...settings.enabledPlugins }; for (const pluginId in updatedPlugins) { @@ -354,7 +363,7 @@ function removeExtraMarketplace(name: string, sources: Array<{ } } } -function ErrorsTabContent(t0) { +function ErrorsTabContent(t0: ErrorsTabContentProps): React.ReactNode { const $ = _c(26); const { setViewState, @@ -365,15 +374,15 @@ function ErrorsTabContent(t0) { const installationStatus = useAppState(_temp3); const setAppState = useSetAppState(); const [selectedIndex, setSelectedIndex] = useState(0); - const [actionMessage, setActionMessage] = useState(null); + const [actionMessage, setActionMessage] = useState(null); let t1; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - t1 = []; + t1 = [] as MarketplaceLoadFailure[]; $[0] = t1; } else { t1 = $[0]; } - const [marketplaceLoadFailures, setMarketplaceLoadFailures] = useState(t1); + const [marketplaceLoadFailures, setMarketplaceLoadFailures] = useState(t1); let t2; let t3; if ($[1] === Symbol.for("react.memo_cache_sentinel")) { @@ -725,7 +734,7 @@ function getInitialTab(viewState: ViewState): TabId { if (viewState.type === 'manage-marketplaces') return 'marketplaces'; return 'discover'; } -export function PluginSettings(t0) { +export function PluginSettings(t0: PluginSettingsProps): React.ReactNode { const $ = _c(75); const { onComplete, @@ -744,8 +753,8 @@ export function PluginSettings(t0) { parsedCommand = $[1]; t1 = $[2]; } - const initialViewState = t1; - const [viewState, setViewState] = useState(initialViewState); + const initialViewState = t1 as ViewState; + const [viewState, setViewState] = useState(initialViewState); let t2; if ($[3] !== initialViewState) { t2 = getInitialTab(initialViewState); @@ -754,11 +763,11 @@ export function PluginSettings(t0) { } else { t2 = $[4]; } - const [activeTab, setActiveTab] = useState(t2); + const [activeTab, setActiveTab] = useState(t2 as TabId); const [inputValue, setInputValue] = useState(viewState.type === "add-marketplace" ? viewState.initialValue || "" : ""); const [cursorOffset, setCursorOffset] = useState(0); - const [error, setError] = useState(null); - const [result, setResult] = useState(null); + const [error, setError] = useState(null); + const [result, setResult] = useState(null); const [childSearchActive, setChildSearchActive] = useState(false); const setAppState = useSetAppState(); const pluginErrorCount = useAppState(_temp0); @@ -977,14 +986,16 @@ export function PluginSettings(t0) { } else { t16 = $[43]; } + const browseMarketplaceTarget = viewState.type === "browse-marketplace" ? viewState.targetMarketplace : undefined; + const pluginTarget = viewState.type === "browse-marketplace" || viewState.type === "discover-plugins" ? viewState.targetPlugin : undefined; let t17; - if ($[44] !== error || $[45] !== markPluginsChanged || $[46] !== result || $[47] !== viewState.targetMarketplace || $[48] !== viewState.targetPlugin || $[49] !== viewState.type) { - t17 = {viewState.type === "browse-marketplace" ? : }; - $[44] = error; - $[45] = markPluginsChanged; - $[46] = result; - $[47] = viewState.targetMarketplace; - $[48] = viewState.targetPlugin; + if ($[44] !== browseMarketplaceTarget || $[45] !== error || $[46] !== markPluginsChanged || $[47] !== pluginTarget || $[48] !== result || $[49] !== viewState.type) { + t17 = {viewState.type === "browse-marketplace" ? : }; + $[44] = browseMarketplaceTarget; + $[45] = error; + $[46] = markPluginsChanged; + $[47] = pluginTarget; + $[48] = result; $[49] = viewState.type; $[50] = t17; } else { diff --git a/src/commands/plugin/UnifiedInstalledCell.tsx b/src/commands/plugin/UnifiedInstalledCell.tsx index 70ee16fe7..6ef45033c 100644 --- a/src/commands/plugin/UnifiedInstalledCell.tsx +++ b/src/commands/plugin/UnifiedInstalledCell.tsx @@ -8,7 +8,7 @@ type Props = { item: UnifiedInstalledItem; isSelected: boolean; }; -export function UnifiedInstalledCell(t0) { +export function UnifiedInstalledCell(t0: Props): React.ReactNode { const $ = _c(142); const { item, diff --git a/src/commands/plugin/types.ts b/src/commands/plugin/types.ts new file mode 100644 index 000000000..624e91fb7 --- /dev/null +++ b/src/commands/plugin/types.ts @@ -0,0 +1,35 @@ +import type { LocalJSXCommandOnDone } from '../../types/command.js' + +export type PluginSettingsProps = { + onComplete: LocalJSXCommandOnDone + args?: string + showMcpRedirectMessage?: boolean +} + +export type PluginManageAction = 'enable' | 'disable' | 'uninstall' +export type MarketplaceManageAction = 'update' | 'remove' + +export type ViewState = + | { type: 'menu' } + | { type: 'help' } + | { type: 'validate'; path?: string } + | { type: 'discover-plugins'; targetPlugin?: string } + | { + type: 'browse-marketplace' + targetMarketplace?: string + targetPlugin?: string + } + | { + type: 'manage-plugins' + targetPlugin?: string + targetMarketplace?: string + action?: PluginManageAction + } + | { type: 'marketplace-list' } + | { type: 'marketplace-menu' } + | { type: 'add-marketplace'; initialValue?: string } + | { + type: 'manage-marketplaces' + targetMarketplace?: string + action?: MarketplaceManageAction + } diff --git a/src/commands/plugin/unifiedTypes.ts b/src/commands/plugin/unifiedTypes.ts new file mode 100644 index 000000000..97ef4d157 --- /dev/null +++ b/src/commands/plugin/unifiedTypes.ts @@ -0,0 +1,58 @@ +import type { MCPServerConnection, ConfigScope } from '../../services/mcp/types.js' +import type { LoadedPlugin, PluginError } from '../../types/plugin.js' +import type { PersistablePluginScope } from '../../utils/plugins/pluginIdentifier.js' + +export type PluginInstalledScope = PersistablePluginScope | 'builtin' +export type UnifiedPluginScope = PluginInstalledScope | 'flagged' | ConfigScope +export type McpStatus = + | 'connected' + | 'disabled' + | 'pending' + | 'needs-auth' + | 'failed' + +export type UnifiedInstalledItem = + | { + type: 'plugin' + id: string + name: string + description?: string + marketplace: string + scope: PluginInstalledScope + isEnabled: boolean + errorCount: number + errors: PluginError[] + plugin: LoadedPlugin + pendingEnable?: boolean + pendingUpdate?: boolean + pendingToggle?: 'will-enable' | 'will-disable' + } + | { + type: 'failed-plugin' + id: string + name: string + marketplace: string + scope: PersistablePluginScope + errorCount: number + errors: PluginError[] + } + | { + type: 'flagged-plugin' + id: string + name: string + marketplace: string + scope: 'flagged' + reason: string + text: string + flaggedAt: string + } + | { + type: 'mcp' + id: string + name: string + description?: string + scope: ConfigScope + status: McpStatus + client: MCPServerConnection + indented?: boolean + }