codex-linux 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +10 -0
- package/.eslintrc.json +27 -0
- package/.github/workflows/ci.yml +156 -0
- package/.huskyrc +7 -0
- package/.lintstagedrc +13 -0
- package/.prettierrc +12 -0
- package/CLAUDE.md +163 -0
- package/DESIGN_SUPERIOR.md +73 -0
- package/Dockerfile +64 -0
- package/INSTALLATION.md +152 -0
- package/LICENSE +21 -0
- package/README.md +245 -0
- package/assets/skills/code-review/instructions.md +102 -0
- package/assets/skills/code-review/skill.yaml +15 -0
- package/assets/skills/refactoring/instructions.md +149 -0
- package/assets/skills/refactoring/skill.yaml +15 -0
- package/assets/skills/testing/skill.yaml +15 -0
- package/commitlint.config.js +23 -0
- package/dist/main/DatabaseManager.js +763 -0
- package/dist/main/DatabaseManager.js.map +1 -0
- package/dist/main/SettingsManager.js +61 -0
- package/dist/main/SettingsManager.js.map +1 -0
- package/dist/main/agents/AgentOrchestrator.js +787 -0
- package/dist/main/agents/AgentOrchestrator.js.map +1 -0
- package/dist/main/agents/AgentSDK.js +219 -0
- package/dist/main/agents/AgentSDK.js.map +1 -0
- package/dist/main/agents/AgentTools.js +348 -0
- package/dist/main/agents/AgentTools.js.map +1 -0
- package/dist/main/agents/CodeIndex.js +233 -0
- package/dist/main/agents/CodeIndex.js.map +1 -0
- package/dist/main/agents/EmbeddingService.js +80 -0
- package/dist/main/agents/EmbeddingService.js.map +1 -0
- package/dist/main/agents/NativeToolCalling.js +206 -0
- package/dist/main/agents/NativeToolCalling.js.map +1 -0
- package/dist/main/api/APIServer.js +278 -0
- package/dist/main/api/APIServer.js.map +1 -0
- package/dist/main/api/RateLimiter.js +138 -0
- package/dist/main/api/RateLimiter.js.map +1 -0
- package/dist/main/api/WebSocketManager.js +300 -0
- package/dist/main/api/WebSocketManager.js.map +1 -0
- package/dist/main/assistant/ContextOptimizer.js +192 -0
- package/dist/main/assistant/ContextOptimizer.js.map +1 -0
- package/dist/main/assistant/PredictedOutputManager.js +172 -0
- package/dist/main/assistant/PredictedOutputManager.js.map +1 -0
- package/dist/main/assistant/PromptCacheManager.js +193 -0
- package/dist/main/assistant/PromptCacheManager.js.map +1 -0
- package/dist/main/assistant/PromptOptimizer.js +626 -0
- package/dist/main/assistant/PromptOptimizer.js.map +1 -0
- package/dist/main/assistant/SmartCodeAssistant.js +224 -0
- package/dist/main/assistant/SmartCodeAssistant.js.map +1 -0
- package/dist/main/auth/SessionManager.js +300 -0
- package/dist/main/auth/SessionManager.js.map +1 -0
- package/dist/main/automations/AdvancedWebhookSystem.js +212 -0
- package/dist/main/automations/AdvancedWebhookSystem.js.map +1 -0
- package/dist/main/automations/AutomationScheduler.js +269 -0
- package/dist/main/automations/AutomationScheduler.js.map +1 -0
- package/dist/main/automations/BatchProcessingSystem.js +159 -0
- package/dist/main/automations/BatchProcessingSystem.js.map +1 -0
- package/dist/main/automations/BrowserAutomationManager.js +195 -0
- package/dist/main/automations/BrowserAutomationManager.js.map +1 -0
- package/dist/main/automations/GitHubActionsManager.js +129 -0
- package/dist/main/automations/GitHubActionsManager.js.map +1 -0
- package/dist/main/automations/GitLabCIManager.js +122 -0
- package/dist/main/automations/GitLabCIManager.js.map +1 -0
- package/dist/main/automations/PriorityQueueManager.js +240 -0
- package/dist/main/automations/PriorityQueueManager.js.map +1 -0
- package/dist/main/background/BackgroundModeManager.js +117 -0
- package/dist/main/background/BackgroundModeManager.js.map +1 -0
- package/dist/main/backup/BackupManager.js +254 -0
- package/dist/main/backup/BackupManager.js.map +1 -0
- package/dist/main/backup/MigrationManager.js +114 -0
- package/dist/main/backup/MigrationManager.js.map +1 -0
- package/dist/main/commands/SlashCommandManager.js +399 -0
- package/dist/main/commands/SlashCommandManager.js.map +1 -0
- package/dist/main/config/ClaudeMdParser.js +519 -0
- package/dist/main/config/ClaudeMdParser.js.map +1 -0
- package/dist/main/config/CustomizationManager.js +381 -0
- package/dist/main/config/CustomizationManager.js.map +1 -0
- package/dist/main/config/LaunchConfigManager.js +211 -0
- package/dist/main/config/LaunchConfigManager.js.map +1 -0
- package/dist/main/config/SettingsManager.js +166 -0
- package/dist/main/config/SettingsManager.js.map +1 -0
- package/dist/main/connectors/ConnectorManager.js +151 -0
- package/dist/main/connectors/ConnectorManager.js.map +1 -0
- package/dist/main/connectors/DatabaseConnector.js +222 -0
- package/dist/main/connectors/DatabaseConnector.js.map +1 -0
- package/dist/main/cowork/CoworkManager.js +324 -0
- package/dist/main/cowork/CoworkManager.js.map +1 -0
- package/dist/main/evals/AgentEvalFramework.js +538 -0
- package/dist/main/evals/AgentEvalFramework.js.map +1 -0
- package/dist/main/evals/GraderManager.js +285 -0
- package/dist/main/evals/GraderManager.js.map +1 -0
- package/dist/main/git/GitWorktreeManager.js +214 -0
- package/dist/main/git/GitWorktreeManager.js.map +1 -0
- package/dist/main/github/GitHubPRMonitor.js +244 -0
- package/dist/main/github/GitHubPRMonitor.js.map +1 -0
- package/dist/main/ide/ContinueInManager.js +181 -0
- package/dist/main/ide/ContinueInManager.js.map +1 -0
- package/dist/main/ide/IDEIntegration.js +277 -0
- package/dist/main/ide/IDEIntegration.js.map +1 -0
- package/dist/main/integrations/LinearManager.js +252 -0
- package/dist/main/integrations/LinearManager.js.map +1 -0
- package/dist/main/integrations/SlackBotManager.js +247 -0
- package/dist/main/integrations/SlackBotManager.js.map +1 -0
- package/dist/main/lsp/LSPManager.js +394 -0
- package/dist/main/lsp/LSPManager.js.map +1 -0
- package/dist/main/main.js +1087 -0
- package/dist/main/main.js.map +1 -0
- package/dist/main/mcp/MCPConfigurationManager.js +281 -0
- package/dist/main/mcp/MCPConfigurationManager.js.map +1 -0
- package/dist/main/mcp/MCPManager.js +710 -0
- package/dist/main/mcp/MCPManager.js.map +1 -0
- package/dist/main/mcp/MCPRegistry.js +272 -0
- package/dist/main/mcp/MCPRegistry.js.map +1 -0
- package/dist/main/monitoring/ErrorRecoveryManager.js +268 -0
- package/dist/main/monitoring/ErrorRecoveryManager.js.map +1 -0
- package/dist/main/monitoring/ErrorTracker.js +57 -0
- package/dist/main/monitoring/ErrorTracker.js.map +1 -0
- package/dist/main/monitoring/MetricsCollector.js +155 -0
- package/dist/main/monitoring/MetricsCollector.js.map +1 -0
- package/dist/main/monitoring/TraceGradingSystem.js +148 -0
- package/dist/main/monitoring/TraceGradingSystem.js.map +1 -0
- package/dist/main/notifications/NotificationManager.js +67 -0
- package/dist/main/notifications/NotificationManager.js.map +1 -0
- package/dist/main/pair/AIPairProgramming.js +200 -0
- package/dist/main/pair/AIPairProgramming.js.map +1 -0
- package/dist/main/plugins/PluginManager.js +222 -0
- package/dist/main/plugins/PluginManager.js.map +1 -0
- package/dist/main/plugins/PluginMarketplace.js +237 -0
- package/dist/main/plugins/PluginMarketplace.js.map +1 -0
- package/dist/main/preload.js +189 -0
- package/dist/main/preload.js.map +1 -0
- package/dist/main/preview/PreviewSessionManager.js +170 -0
- package/dist/main/preview/PreviewSessionManager.js.map +1 -0
- package/dist/main/providers/AIProviderManager.js +327 -0
- package/dist/main/providers/AIProviderManager.js.map +1 -0
- package/dist/main/providers/FineTuningManager.js +276 -0
- package/dist/main/providers/FineTuningManager.js.map +1 -0
- package/dist/main/providers/FreeModelsProvider.js +1104 -0
- package/dist/main/providers/FreeModelsProvider.js.map +1 -0
- package/dist/main/realtime/RealtimeManager.js +116 -0
- package/dist/main/realtime/RealtimeManager.js.map +1 -0
- package/dist/main/remote/CloudEnvironmentManager.js +232 -0
- package/dist/main/remote/CloudEnvironmentManager.js.map +1 -0
- package/dist/main/remote/RemoteSessionManager.js +255 -0
- package/dist/main/remote/RemoteSessionManager.js.map +1 -0
- package/dist/main/search/DeepResearchManager.js +335 -0
- package/dist/main/search/DeepResearchManager.js.map +1 -0
- package/dist/main/search/WebSearchIntegration.js +147 -0
- package/dist/main/search/WebSearchIntegration.js.map +1 -0
- package/dist/main/security/AdminConsoleManager.js +223 -0
- package/dist/main/security/AdminConsoleManager.js.map +1 -0
- package/dist/main/security/AuditLogger.js +136 -0
- package/dist/main/security/AuditLogger.js.map +1 -0
- package/dist/main/security/PermissionManager.js +144 -0
- package/dist/main/security/PermissionManager.js.map +1 -0
- package/dist/main/security/SSOManager.js +173 -0
- package/dist/main/security/SSOManager.js.map +1 -0
- package/dist/main/security/SecurityManager.js +152 -0
- package/dist/main/security/SecurityManager.js.map +1 -0
- package/dist/main/skills/SkillsManager.js +223 -0
- package/dist/main/skills/SkillsManager.js.map +1 -0
- package/dist/main/ssh/SSHManager.js +65 -0
- package/dist/main/ssh/SSHManager.js.map +1 -0
- package/dist/main/streaming/StreamingManager.js +225 -0
- package/dist/main/streaming/StreamingManager.js.map +1 -0
- package/dist/main/sync/CloudSyncManager.js +422 -0
- package/dist/main/sync/CloudSyncManager.js.map +1 -0
- package/dist/main/types.js +28 -0
- package/dist/main/types.js.map +1 -0
- package/dist/main/verification/AutoVerifyManager.js +235 -0
- package/dist/main/verification/AutoVerifyManager.js.map +1 -0
- package/dist/main/vision/ComputerUseManager.js +376 -0
- package/dist/main/vision/ComputerUseManager.js.map +1 -0
- package/dist/main/vision/ImageVideoGenerationManager.js +401 -0
- package/dist/main/vision/ImageVideoGenerationManager.js.map +1 -0
- package/dist/main/vision/VisionManager.js +172 -0
- package/dist/main/vision/VisionManager.js.map +1 -0
- package/dist/renderer/assets/main-DJlZQBCA.js +304 -0
- package/dist/renderer/assets/main-N33ZXEr8.css +1 -0
- package/dist/renderer/index.html +21 -0
- package/dist/renderer/manifest.json +42 -0
- package/dist/renderer/sw.ts +109 -0
- package/dist/shared/types.js +35 -0
- package/dist/shared/types.js.map +1 -0
- package/docker-compose.yml +65 -0
- package/docs/API.md +307 -0
- package/docs/USER_GUIDE.md +476 -0
- package/examples/plugins/sample-plugin/package.json +41 -0
- package/examples/plugins/sample-plugin/src/index.ts +75 -0
- package/index.html +20 -0
- package/jest.config.js +39 -0
- package/package.json +180 -0
- package/packages/cli/package.json +29 -0
- package/packages/cli/src/commands/agents.ts +199 -0
- package/packages/cli/src/commands/tasks.ts +61 -0
- package/packages/cli/src/index.ts +91 -0
- package/packages/cli/src/utils/api.ts +45 -0
- package/packages/cli/src/utils/config.ts +61 -0
- package/packages/npm-installer/bin/codex-linux +126 -0
- package/packages/npm-installer/lib/download.js +273 -0
- package/packages/npm-installer/package.json +42 -0
- package/packages/vscode-extension/package.json +167 -0
- package/packages/vscode-extension/src/api.ts +68 -0
- package/packages/vscode-extension/src/extension.ts +161 -0
- package/packages/vscode-extension/src/panels/chatPanel.ts +265 -0
- package/packages/vscode-extension/src/panels/createAgentPanel.ts +227 -0
- package/packages/vscode-extension/src/providers/agentsProvider.ts +80 -0
- package/postcss.config.js +6 -0
- package/public/manifest.json +42 -0
- package/public/sw.ts +109 -0
- package/scripts/install-dev.sh +103 -0
- package/scripts/install.sh +275 -0
- package/src/main/DatabaseManager.ts +950 -0
- package/src/main/SettingsManager.ts +63 -0
- package/src/main/agents/AgentOrchestrator.ts +930 -0
- package/src/main/agents/AgentSDK.ts +269 -0
- package/src/main/agents/AgentTools.ts +380 -0
- package/src/main/agents/CodeIndex.ts +240 -0
- package/src/main/agents/EmbeddingService.ts +88 -0
- package/src/main/agents/NativeToolCalling.ts +245 -0
- package/src/main/api/APIServer.ts +316 -0
- package/src/main/api/RateLimiter.ts +165 -0
- package/src/main/api/WebSocketManager.ts +398 -0
- package/src/main/assistant/ContextOptimizer.ts +214 -0
- package/src/main/assistant/PredictedOutputManager.ts +265 -0
- package/src/main/assistant/PromptCacheManager.ts +280 -0
- package/src/main/assistant/PromptOptimizer.ts +746 -0
- package/src/main/assistant/SmartCodeAssistant.ts +234 -0
- package/src/main/auth/SessionManager.ts +415 -0
- package/src/main/automations/AdvancedWebhookSystem.ts +281 -0
- package/src/main/automations/AutomationScheduler.ts +272 -0
- package/src/main/automations/BatchProcessingSystem.ts +207 -0
- package/src/main/automations/BrowserAutomationManager.ts +203 -0
- package/src/main/automations/GitHubActionsManager.ts +151 -0
- package/src/main/automations/GitLabCIManager.ts +206 -0
- package/src/main/automations/PriorityQueueManager.ts +328 -0
- package/src/main/background/BackgroundModeManager.ts +130 -0
- package/src/main/backup/BackupManager.ts +287 -0
- package/src/main/backup/MigrationManager.ts +132 -0
- package/src/main/commands/SlashCommandManager.ts +407 -0
- package/src/main/config/ClaudeMdParser.ts +539 -0
- package/src/main/config/CustomizationManager.ts +493 -0
- package/src/main/config/LaunchConfigManager.ts +212 -0
- package/src/main/config/SettingsManager.ts +163 -0
- package/src/main/connectors/ConnectorManager.ts +175 -0
- package/src/main/connectors/DatabaseConnector.ts +212 -0
- package/src/main/cowork/CoworkManager.ts +431 -0
- package/src/main/evals/AgentEvalFramework.ts +665 -0
- package/src/main/evals/GraderManager.ts +417 -0
- package/src/main/git/GitWorktreeManager.ts +211 -0
- package/src/main/github/GitHubPRMonitor.ts +317 -0
- package/src/main/ide/ContinueInManager.ts +180 -0
- package/src/main/ide/IDEIntegration.ts +288 -0
- package/src/main/integrations/LinearManager.ts +327 -0
- package/src/main/integrations/SlackBotManager.ts +312 -0
- package/src/main/lsp/LSPManager.ts +445 -0
- package/src/main/main.ts +1221 -0
- package/src/main/mcp/MCPConfigurationManager.ts +281 -0
- package/src/main/mcp/MCPManager.ts +799 -0
- package/src/main/mcp/MCPRegistry.ts +273 -0
- package/src/main/monitoring/ErrorRecoveryManager.ts +359 -0
- package/src/main/monitoring/ErrorTracker.ts +60 -0
- package/src/main/monitoring/MetricsCollector.ts +196 -0
- package/src/main/monitoring/TraceGradingSystem.ts +196 -0
- package/src/main/notifications/NotificationManager.ts +96 -0
- package/src/main/pair/AIPairProgramming.ts +290 -0
- package/src/main/plugins/PluginManager.ts +266 -0
- package/src/main/plugins/PluginMarketplace.ts +318 -0
- package/src/main/preload.ts +215 -0
- package/src/main/preview/PreviewSessionManager.ts +186 -0
- package/src/main/providers/AIProviderManager.ts +394 -0
- package/src/main/providers/FineTuningManager.ts +390 -0
- package/src/main/providers/FreeModelsProvider.ts +1156 -0
- package/src/main/realtime/RealtimeManager.ts +147 -0
- package/src/main/remote/CloudEnvironmentManager.ts +253 -0
- package/src/main/remote/RemoteSessionManager.ts +323 -0
- package/src/main/search/DeepResearchManager.ts +458 -0
- package/src/main/search/WebSearchIntegration.ts +203 -0
- package/src/main/security/AdminConsoleManager.ts +244 -0
- package/src/main/security/AuditLogger.ts +143 -0
- package/src/main/security/PermissionManager.ts +184 -0
- package/src/main/security/SSOManager.ts +241 -0
- package/src/main/security/SecurityManager.ts +139 -0
- package/src/main/skills/SkillsManager.ts +218 -0
- package/src/main/ssh/SSHManager.ts +86 -0
- package/src/main/streaming/StreamingManager.ts +306 -0
- package/src/main/sync/CloudSyncManager.ts +532 -0
- package/src/main/verification/AutoVerifyManager.ts +285 -0
- package/src/main/vision/ComputerUseManager.ts +475 -0
- package/src/main/vision/ImageVideoGenerationManager.ts +526 -0
- package/src/main/vision/VisionManager.ts +186 -0
- package/src/renderer/App.tsx +314 -0
- package/src/renderer/components/AdvancedSettingsPanel.tsx +225 -0
- package/src/renderer/components/AgentPanel.tsx +760 -0
- package/src/renderer/components/AppPreview.tsx +220 -0
- package/src/renderer/components/AuditTrailPanel.tsx +148 -0
- package/src/renderer/components/AutomationPanel.tsx +220 -0
- package/src/renderer/components/ChatInterface.tsx +595 -0
- package/src/renderer/components/ChatTab.tsx +296 -0
- package/src/renderer/components/CodeEditor.tsx +257 -0
- package/src/renderer/components/CodeReviewPanel.tsx +256 -0
- package/src/renderer/components/CodeWorkspace.tsx +192 -0
- package/src/renderer/components/CodebaseDashboard.tsx +295 -0
- package/src/renderer/components/ComputerUsePanel.tsx +262 -0
- package/src/renderer/components/ConnectorsPanel.tsx +471 -0
- package/src/renderer/components/ContextMenu.tsx +155 -0
- package/src/renderer/components/ContextUsageDisplay.tsx +248 -0
- package/src/renderer/components/CoworkPanel.tsx +415 -0
- package/src/renderer/components/DiffViewer.tsx +452 -0
- package/src/renderer/components/ErrorBoundary.tsx +273 -0
- package/src/renderer/components/ExtendedThinkingToggle.tsx +244 -0
- package/src/renderer/components/FileAttachments.tsx +247 -0
- package/src/renderer/components/FileExplorer.tsx +242 -0
- package/src/renderer/components/FileExplorerPanel.tsx +302 -0
- package/src/renderer/components/GitPanel.tsx +154 -0
- package/src/renderer/components/Header.tsx +113 -0
- package/src/renderer/components/MCPPanel.tsx +326 -0
- package/src/renderer/components/MentionAutocomplete.tsx +239 -0
- package/src/renderer/components/PermissionPanel.tsx +159 -0
- package/src/renderer/components/PermissionSelector.tsx +203 -0
- package/src/renderer/components/PluginMarketplace.tsx +325 -0
- package/src/renderer/components/PromptOptimizerPanel.tsx +399 -0
- package/src/renderer/components/SearchPanel.tsx +173 -0
- package/src/renderer/components/SearchReplace.tsx +284 -0
- package/src/renderer/components/SessionSidebar.tsx +367 -0
- package/src/renderer/components/SettingsPanel.tsx +426 -0
- package/src/renderer/components/Sidebar.tsx +100 -0
- package/src/renderer/components/SkillsPanel.tsx +245 -0
- package/src/renderer/components/SplitPane.tsx +173 -0
- package/src/renderer/components/Terminal.tsx +190 -0
- package/src/renderer/components/VoiceCommand.tsx +129 -0
- package/src/renderer/components/WorktreePanel.tsx +163 -0
- package/src/renderer/components/ui/AriaComponents.tsx +193 -0
- package/src/renderer/components/ui/Button.tsx +68 -0
- package/src/renderer/components/ui/Card.tsx +102 -0
- package/src/renderer/components/ui/Input.tsx +44 -0
- package/src/renderer/components/ui/Skeleton.tsx +55 -0
- package/src/renderer/components/ui/VirtualList.tsx +196 -0
- package/src/renderer/i18n/I18nProvider.tsx +101 -0
- package/src/renderer/i18n/de.ts +161 -0
- package/src/renderer/i18n/en.ts +163 -0
- package/src/renderer/i18n/es.ts +161 -0
- package/src/renderer/i18n/fr.ts +161 -0
- package/src/renderer/i18n/index.ts +44 -0
- package/src/renderer/index.css +129 -0
- package/src/renderer/lib/accessibility.tsx +287 -0
- package/src/renderer/lib/hooks.ts +304 -0
- package/src/renderer/lib/utils.ts +6 -0
- package/src/renderer/main.tsx +25 -0
- package/src/renderer/styles/minimalist.css +539 -0
- package/src/renderer/sw.ts +180 -0
- package/src/renderer/types.d.ts +138 -0
- package/src/shared/types.ts +813 -0
- package/supabase/schema.sql +234 -0
- package/tailwind.config.js +78 -0
- package/tests/e2e/package.json +15 -0
- package/tests/e2e/playwright.config.ts +31 -0
- package/tests/e2e/specs/app.spec.ts +194 -0
- package/tests/setup.ts +99 -0
- package/tests/unit/AgentOrchestrator.test.ts +274 -0
- package/tests/unit/DatabaseManager.test.ts +262 -0
- package/tests/unit/GitWorktreeManager.test.ts +150 -0
- package/tests/unit/SecurityManager.test.ts +110 -0
- package/tsconfig.main.json +22 -0
- package/tsconfig.renderer.json +27 -0
- package/vite.config.ts +28 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { PermissionRequest } from '../../shared/types';
|
|
3
|
+
import {
|
|
4
|
+
FileEdit,
|
|
5
|
+
Terminal,
|
|
6
|
+
Wrench,
|
|
7
|
+
Check,
|
|
8
|
+
X,
|
|
9
|
+
Clock,
|
|
10
|
+
AlertCircle
|
|
11
|
+
} from 'lucide-react';
|
|
12
|
+
|
|
13
|
+
interface PermissionPanelProps {
|
|
14
|
+
requests: PermissionRequest[];
|
|
15
|
+
onApprove: (requestId: string) => void;
|
|
16
|
+
onReject: (requestId: string) => void;
|
|
17
|
+
onViewDetails?: (request: PermissionRequest) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const getActionIcon = (type: string) => {
|
|
21
|
+
switch (type) {
|
|
22
|
+
case 'edit':
|
|
23
|
+
return <FileEdit className="w-4 h-4" />;
|
|
24
|
+
case 'command':
|
|
25
|
+
return <Terminal className="w-4 h-4" />;
|
|
26
|
+
case 'tool':
|
|
27
|
+
return <Wrench className="w-4 h-4" />;
|
|
28
|
+
default:
|
|
29
|
+
return <AlertCircle className="w-4 h-4" />;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const getActionColor = (type: string) => {
|
|
34
|
+
switch (type) {
|
|
35
|
+
case 'edit':
|
|
36
|
+
return 'text-blue-500 bg-blue-500/10';
|
|
37
|
+
case 'command':
|
|
38
|
+
return 'text-yellow-500 bg-yellow-500/10';
|
|
39
|
+
case 'tool':
|
|
40
|
+
return 'text-purple-500 bg-purple-500/10';
|
|
41
|
+
default:
|
|
42
|
+
return 'text-gray-500 bg-gray-500/10';
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const PermissionPanel: React.FC<PermissionPanelProps> = ({
|
|
47
|
+
requests,
|
|
48
|
+
onApprove,
|
|
49
|
+
onReject,
|
|
50
|
+
onViewDetails
|
|
51
|
+
}) => {
|
|
52
|
+
if (requests.length === 0) {
|
|
53
|
+
return (
|
|
54
|
+
<div className="flex flex-col items-center justify-center h-full text-muted-foreground p-8">
|
|
55
|
+
<Check className="w-16 h-16 mb-4 opacity-30" />
|
|
56
|
+
<h3 className="text-lg font-medium">No Pending Permissions</h3>
|
|
57
|
+
<p className="text-sm mt-2 text-center">
|
|
58
|
+
All actions have been approved or rejected
|
|
59
|
+
</p>
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<div className="flex flex-col h-full">
|
|
66
|
+
<div className="px-4 py-3 border-b border-border flex items-center justify-between bg-background/50">
|
|
67
|
+
<div className="flex items-center gap-2">
|
|
68
|
+
<Clock className="w-5 h-5 text-yellow-500" />
|
|
69
|
+
<h3 className="font-medium">Pending Permissions</h3>
|
|
70
|
+
</div>
|
|
71
|
+
<span className="text-sm text-muted-foreground">
|
|
72
|
+
{requests.length} pending
|
|
73
|
+
</span>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div className="flex-1 overflow-auto p-4 space-y-3">
|
|
77
|
+
{requests.map((request) => (
|
|
78
|
+
<div
|
|
79
|
+
key={request.id}
|
|
80
|
+
className="bg-card border border-border rounded-lg p-4 hover:border-primary/50 transition-colors"
|
|
81
|
+
>
|
|
82
|
+
{/* Header */}
|
|
83
|
+
<div className="flex items-start justify-between mb-3">
|
|
84
|
+
<div className="flex items-center gap-2">
|
|
85
|
+
<div className={`p-2 rounded-lg ${getActionColor(request.type)}`}>
|
|
86
|
+
{getActionIcon(request.type)}
|
|
87
|
+
</div>
|
|
88
|
+
<div>
|
|
89
|
+
<span className="font-medium capitalize">{request.type}</span>
|
|
90
|
+
<span className="text-muted-foreground text-sm ml-2">
|
|
91
|
+
{request.action}
|
|
92
|
+
</span>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
<span className="text-xs text-muted-foreground">
|
|
96
|
+
{new Date(request.createdAt).toLocaleTimeString()}
|
|
97
|
+
</span>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
{/* Details */}
|
|
101
|
+
{request.details && Object.keys(request.details).length > 0 && (
|
|
102
|
+
<div className="bg-muted/50 rounded-lg p-3 mb-3">
|
|
103
|
+
{request.type === 'edit' && request.details.filePath && (
|
|
104
|
+
<div className="text-sm">
|
|
105
|
+
<span className="text-muted-foreground">File: </span>
|
|
106
|
+
<code className="bg-background px-1.5 py-0.5 rounded text-xs">
|
|
107
|
+
{request.details.filePath}
|
|
108
|
+
</code>
|
|
109
|
+
</div>
|
|
110
|
+
)}
|
|
111
|
+
{request.type === 'command' && request.details.command && (
|
|
112
|
+
<div className="text-sm">
|
|
113
|
+
<span className="text-muted-foreground">Command: </span>
|
|
114
|
+
<code className="bg-background px-1.5 py-0.5 rounded text-xs font-mono">
|
|
115
|
+
{request.details.command}
|
|
116
|
+
</code>
|
|
117
|
+
</div>
|
|
118
|
+
)}
|
|
119
|
+
{request.details.description && (
|
|
120
|
+
<p className="text-sm text-muted-foreground mt-2">
|
|
121
|
+
{request.details.description}
|
|
122
|
+
</p>
|
|
123
|
+
)}
|
|
124
|
+
</div>
|
|
125
|
+
)}
|
|
126
|
+
|
|
127
|
+
{/* Actions */}
|
|
128
|
+
<div className="flex items-center justify-end gap-2">
|
|
129
|
+
{onViewDetails && (
|
|
130
|
+
<button
|
|
131
|
+
onClick={() => onViewDetails(request)}
|
|
132
|
+
className="px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
133
|
+
>
|
|
134
|
+
View Details
|
|
135
|
+
</button>
|
|
136
|
+
)}
|
|
137
|
+
<button
|
|
138
|
+
onClick={() => onReject(request.id)}
|
|
139
|
+
className="flex items-center gap-1.5 px-3 py-1.5 text-sm text-red-500 hover:bg-red-500/10 rounded-lg transition-colors"
|
|
140
|
+
>
|
|
141
|
+
<X className="w-4 h-4" />
|
|
142
|
+
Reject
|
|
143
|
+
</button>
|
|
144
|
+
<button
|
|
145
|
+
onClick={() => onApprove(request.id)}
|
|
146
|
+
className="flex items-center gap-1.5 px-3 py-1.5 text-sm bg-green-500/10 text-green-500 hover:bg-green-500/20 rounded-lg transition-colors"
|
|
147
|
+
>
|
|
148
|
+
<Check className="w-4 h-4" />
|
|
149
|
+
Approve
|
|
150
|
+
</button>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
))}
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export default PermissionPanel;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { PermissionMode } from '../../shared/types';
|
|
3
|
+
import {
|
|
4
|
+
Shield,
|
|
5
|
+
ShieldCheck,
|
|
6
|
+
ShieldAlert,
|
|
7
|
+
ShieldOff,
|
|
8
|
+
ChevronDown,
|
|
9
|
+
AlertTriangle
|
|
10
|
+
} from 'lucide-react';
|
|
11
|
+
|
|
12
|
+
interface PermissionSelectorProps {
|
|
13
|
+
currentMode: PermissionMode;
|
|
14
|
+
onModeChange: (mode: PermissionMode) => void;
|
|
15
|
+
allowBypass: boolean;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
showDescriptions?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const permissionModes = [
|
|
21
|
+
{
|
|
22
|
+
mode: PermissionMode.ASK,
|
|
23
|
+
label: 'Ask permissions',
|
|
24
|
+
description: 'Ask before editing files or running commands',
|
|
25
|
+
icon: Shield,
|
|
26
|
+
color: 'text-blue-500',
|
|
27
|
+
bgColor: 'bg-blue-500/10',
|
|
28
|
+
borderColor: 'border-blue-500/30'
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
mode: PermissionMode.AUTO_ACCEPT_EDITS,
|
|
32
|
+
label: 'Auto accept edits',
|
|
33
|
+
description: 'Auto-accept file edits, ask for commands',
|
|
34
|
+
icon: ShieldCheck,
|
|
35
|
+
color: 'text-green-500',
|
|
36
|
+
bgColor: 'bg-green-500/10',
|
|
37
|
+
borderColor: 'border-green-500/30'
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
mode: PermissionMode.PLAN,
|
|
41
|
+
label: 'Plan mode',
|
|
42
|
+
description: 'Analyze only, no changes or commands',
|
|
43
|
+
icon: ShieldAlert,
|
|
44
|
+
color: 'text-yellow-500',
|
|
45
|
+
bgColor: 'bg-yellow-500/10',
|
|
46
|
+
borderColor: 'border-yellow-500/30'
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
mode: PermissionMode.BYPASS,
|
|
50
|
+
label: 'Bypass permissions',
|
|
51
|
+
description: 'Run without any permission prompts',
|
|
52
|
+
icon: ShieldOff,
|
|
53
|
+
color: 'text-red-500',
|
|
54
|
+
bgColor: 'bg-red-500/10',
|
|
55
|
+
borderColor: 'border-red-500/30',
|
|
56
|
+
dangerous: true
|
|
57
|
+
}
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
export const PermissionSelector: React.FC<PermissionSelectorProps> = ({
|
|
61
|
+
currentMode,
|
|
62
|
+
onModeChange,
|
|
63
|
+
allowBypass,
|
|
64
|
+
disabled = false,
|
|
65
|
+
showDescriptions = true
|
|
66
|
+
}) => {
|
|
67
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
68
|
+
const [showBypassWarning, setShowBypassWarning] = useState(false);
|
|
69
|
+
|
|
70
|
+
const currentConfig = permissionModes.find(m => m.mode === currentMode) || permissionModes[0];
|
|
71
|
+
const Icon = currentConfig.icon;
|
|
72
|
+
|
|
73
|
+
const handleModeSelect = (mode: PermissionMode) => {
|
|
74
|
+
if (mode === PermissionMode.BYPASS && !allowBypass) {
|
|
75
|
+
setShowBypassWarning(true);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
onModeChange(mode);
|
|
80
|
+
setIsOpen(false);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
const handleClickOutside = () => setIsOpen(false);
|
|
85
|
+
if (isOpen) {
|
|
86
|
+
document.addEventListener('click', handleClickOutside);
|
|
87
|
+
return () => document.removeEventListener('click', handleClickOutside);
|
|
88
|
+
}
|
|
89
|
+
}, [isOpen]);
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<div className="relative">
|
|
93
|
+
{/* Selector Button */}
|
|
94
|
+
<button
|
|
95
|
+
onClick={(e) => {
|
|
96
|
+
e.stopPropagation();
|
|
97
|
+
if (!disabled) setIsOpen(!isOpen);
|
|
98
|
+
}}
|
|
99
|
+
disabled={disabled}
|
|
100
|
+
className={`flex items-center gap-2 px-3 py-2 rounded-lg border transition-all ${
|
|
101
|
+
disabled
|
|
102
|
+
? 'opacity-50 cursor-not-allowed bg-muted'
|
|
103
|
+
: 'hover:bg-muted cursor-pointer'
|
|
104
|
+
} ${currentConfig.bgColor} ${currentConfig.borderColor}`}
|
|
105
|
+
>
|
|
106
|
+
<Icon className={`w-4 h-4 ${currentConfig.color}`} />
|
|
107
|
+
<span className="text-sm font-medium">{currentConfig.label}</span>
|
|
108
|
+
{!disabled && <ChevronDown className={`w-4 h-4 transition-transform ${isOpen ? 'rotate-180' : ''}`} />}
|
|
109
|
+
</button>
|
|
110
|
+
|
|
111
|
+
{/* Dropdown Menu */}
|
|
112
|
+
{isOpen && (
|
|
113
|
+
<div className="absolute top-full left-0 mt-1 w-80 bg-card border border-border rounded-lg shadow-lg z-50 overflow-hidden">
|
|
114
|
+
<div className="p-2 space-y-1">
|
|
115
|
+
{permissionModes.map((config) => {
|
|
116
|
+
const ModeIcon = config.icon;
|
|
117
|
+
const isDisabled = config.mode === PermissionMode.BYPASS && !allowBypass;
|
|
118
|
+
const isActive = config.mode === currentMode;
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<button
|
|
122
|
+
key={config.mode}
|
|
123
|
+
onClick={(e) => {
|
|
124
|
+
e.stopPropagation();
|
|
125
|
+
handleModeSelect(config.mode);
|
|
126
|
+
}}
|
|
127
|
+
disabled={isDisabled}
|
|
128
|
+
className={`w-full flex items-start gap-3 p-3 rounded-lg text-left transition-all ${
|
|
129
|
+
isActive
|
|
130
|
+
? `${config.bgColor} ${config.borderColor} border`
|
|
131
|
+
: 'hover:bg-muted'
|
|
132
|
+
} ${isDisabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}`}
|
|
133
|
+
>
|
|
134
|
+
<div className={`mt-0.5 ${config.color}`}>
|
|
135
|
+
<ModeIcon className="w-5 h-5" />
|
|
136
|
+
</div>
|
|
137
|
+
<div className="flex-1 min-w-0">
|
|
138
|
+
<div className="flex items-center gap-2">
|
|
139
|
+
<span className="font-medium text-sm">{config.label}</span>
|
|
140
|
+
{config.dangerous && (
|
|
141
|
+
<AlertTriangle className="w-3.5 h-3.5 text-red-500" />
|
|
142
|
+
)}
|
|
143
|
+
</div>
|
|
144
|
+
{showDescriptions && (
|
|
145
|
+
<p className="text-xs text-muted-foreground mt-0.5">
|
|
146
|
+
{config.description}
|
|
147
|
+
</p>
|
|
148
|
+
)}
|
|
149
|
+
</div>
|
|
150
|
+
{isActive && (
|
|
151
|
+
<div className={`w-2 h-2 rounded-full ${config.color.replace('text-', 'bg-')}`} />
|
|
152
|
+
)}
|
|
153
|
+
</button>
|
|
154
|
+
);
|
|
155
|
+
})}
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
{/* Footer hint */}
|
|
159
|
+
<div className="px-3 py-2 bg-muted/50 border-t border-border">
|
|
160
|
+
<p className="text-xs text-muted-foreground">
|
|
161
|
+
You can change permission mode anytime during a session
|
|
162
|
+
</p>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
)}
|
|
166
|
+
|
|
167
|
+
{/* Bypass Warning Modal */}
|
|
168
|
+
{showBypassWarning && (
|
|
169
|
+
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
|
|
170
|
+
<div className="bg-card border border-border rounded-lg p-6 w-[400px] max-w-[90vw]">
|
|
171
|
+
<div className="flex items-center gap-3 mb-4">
|
|
172
|
+
<div className="p-2 bg-red-500/10 rounded-lg">
|
|
173
|
+
<AlertTriangle className="w-6 h-6 text-red-500" />
|
|
174
|
+
</div>
|
|
175
|
+
<h3 className="text-lg font-semibold">Bypass Mode Disabled</h3>
|
|
176
|
+
</div>
|
|
177
|
+
|
|
178
|
+
<p className="text-sm text-muted-foreground mb-4">
|
|
179
|
+
Bypass permission mode is disabled for security reasons. This mode allows
|
|
180
|
+
Claude to run without any permission prompts, which can be dangerous.
|
|
181
|
+
</p>
|
|
182
|
+
|
|
183
|
+
<p className="text-sm mb-6">
|
|
184
|
+
To enable bypass mode, go to <strong>Settings → Security</strong> and
|
|
185
|
+
toggle "Allow bypass permissions mode".
|
|
186
|
+
</p>
|
|
187
|
+
|
|
188
|
+
<div className="flex justify-end gap-2">
|
|
189
|
+
<button
|
|
190
|
+
onClick={() => setShowBypassWarning(false)}
|
|
191
|
+
className="px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90"
|
|
192
|
+
>
|
|
193
|
+
Got it
|
|
194
|
+
</button>
|
|
195
|
+
</div>
|
|
196
|
+
</div>
|
|
197
|
+
</div>
|
|
198
|
+
)}
|
|
199
|
+
</div>
|
|
200
|
+
);
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
export default PermissionSelector;
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { Search, Download, Star, Shield, Zap, Package, X, ExternalLink, Check } from 'lucide-react';
|
|
3
|
+
|
|
4
|
+
export interface Plugin {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
author: string;
|
|
9
|
+
version: string;
|
|
10
|
+
rating: number;
|
|
11
|
+
downloads: number;
|
|
12
|
+
tags: string[];
|
|
13
|
+
icon?: string;
|
|
14
|
+
installed?: boolean;
|
|
15
|
+
updateAvailable?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface PluginMarketplaceProps {
|
|
19
|
+
onInstall: (pluginId: string) => void;
|
|
20
|
+
onUninstall: (pluginId: string) => void;
|
|
21
|
+
installedPlugins: string[];
|
|
22
|
+
onClose: () => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const PLUGIN_CATEGORIES = [
|
|
26
|
+
{ id: 'all', label: 'All' },
|
|
27
|
+
{ id: 'productivity', label: 'Productivity' },
|
|
28
|
+
{ id: 'ai', label: 'AI & ML' },
|
|
29
|
+
{ id: 'integrations', label: 'Integrations' },
|
|
30
|
+
{ id: 'tools', label: 'Dev Tools' },
|
|
31
|
+
{ id: 'custom', label: 'Custom' },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const SAMPLE_PLUGINS: Plugin[] = [
|
|
35
|
+
{
|
|
36
|
+
id: 'code-review',
|
|
37
|
+
name: 'Code Review Pro',
|
|
38
|
+
description: 'Advanced code review with pattern detection and best practices enforcement',
|
|
39
|
+
author: 'Codex Team',
|
|
40
|
+
version: '1.2.0',
|
|
41
|
+
rating: 4.8,
|
|
42
|
+
downloads: 12500,
|
|
43
|
+
tags: ['ai', 'productivity'],
|
|
44
|
+
installed: false,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: 'test-generator',
|
|
48
|
+
name: 'Test Generator',
|
|
49
|
+
description: 'Automatically generate unit tests based on code changes and coverage gaps',
|
|
50
|
+
author: 'Codex Team',
|
|
51
|
+
version: '2.0.0',
|
|
52
|
+
rating: 4.6,
|
|
53
|
+
downloads: 8900,
|
|
54
|
+
tags: ['productivity', 'tools'],
|
|
55
|
+
installed: false,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'github-integration',
|
|
59
|
+
name: 'GitHub Integration',
|
|
60
|
+
description: 'Enhanced GitHub workflow with PR templates, auto-merge, and issue tracking',
|
|
61
|
+
author: 'Community',
|
|
62
|
+
version: '1.5.0',
|
|
63
|
+
rating: 4.5,
|
|
64
|
+
downloads: 15000,
|
|
65
|
+
tags: ['integrations'],
|
|
66
|
+
installed: true,
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: 'slack-notifications',
|
|
70
|
+
name: 'Slack Notifications',
|
|
71
|
+
description: 'Get real-time notifications in Slack for agent activities and errors',
|
|
72
|
+
author: 'Community',
|
|
73
|
+
version: '1.0.0',
|
|
74
|
+
rating: 4.2,
|
|
75
|
+
downloads: 5200,
|
|
76
|
+
tags: ['integrations'],
|
|
77
|
+
installed: false,
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'context7-docs',
|
|
81
|
+
name: 'Context7 Docs',
|
|
82
|
+
description: 'Fetch always-up-to-date library documentation from Context7',
|
|
83
|
+
author: 'Community',
|
|
84
|
+
version: '1.1.0',
|
|
85
|
+
rating: 4.9,
|
|
86
|
+
downloads: 22000,
|
|
87
|
+
tags: ['ai', 'tools'],
|
|
88
|
+
installed: false,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: 'brave-search',
|
|
92
|
+
name: 'Brave Search',
|
|
93
|
+
description: 'Web search capability using Brave Search API',
|
|
94
|
+
author: 'Anthropic',
|
|
95
|
+
version: '1.0.0',
|
|
96
|
+
rating: 4.7,
|
|
97
|
+
downloads: 18000,
|
|
98
|
+
tags: ['ai', 'integrations'],
|
|
99
|
+
installed: false,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: 'database-mcp',
|
|
103
|
+
name: 'Database MCP',
|
|
104
|
+
description: 'Connect to PostgreSQL, MySQL, and other databases directly',
|
|
105
|
+
author: 'Community',
|
|
106
|
+
version: '2.1.0',
|
|
107
|
+
rating: 4.4,
|
|
108
|
+
downloads: 7500,
|
|
109
|
+
tags: ['tools', 'integrations'],
|
|
110
|
+
installed: false,
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: 'figma-integration',
|
|
114
|
+
name: 'Figma Integration',
|
|
115
|
+
description: 'Import designs from Figma and generate UI code automatically',
|
|
116
|
+
author: 'Community',
|
|
117
|
+
version: '0.9.0',
|
|
118
|
+
rating: 4.3,
|
|
119
|
+
downloads: 4100,
|
|
120
|
+
tags: ['integrations', 'ai'],
|
|
121
|
+
installed: false,
|
|
122
|
+
},
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
function cn(...inputs: (string | undefined | null | boolean)[]): string {
|
|
126
|
+
return inputs.filter(Boolean).join(' ');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export const PluginMarketplace: React.FC<PluginMarketplaceProps> = ({
|
|
130
|
+
onInstall,
|
|
131
|
+
onUninstall,
|
|
132
|
+
installedPlugins,
|
|
133
|
+
onClose,
|
|
134
|
+
}) => {
|
|
135
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
136
|
+
const [selectedCategory, setSelectedCategory] = useState('all');
|
|
137
|
+
const [plugins, setPlugins] = useState<Plugin[]>(SAMPLE_PLUGINS);
|
|
138
|
+
const [installing, setInstalling] = useState<string | null>(null);
|
|
139
|
+
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
setPlugins(SAMPLE_PLUGINS.map(p => ({
|
|
142
|
+
...p,
|
|
143
|
+
installed: installedPlugins.includes(p.id),
|
|
144
|
+
})));
|
|
145
|
+
}, [installedPlugins]);
|
|
146
|
+
|
|
147
|
+
const filteredPlugins = plugins.filter(plugin => {
|
|
148
|
+
const matchesSearch = plugin.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
149
|
+
plugin.description.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
150
|
+
plugin.tags.some(t => t.includes(searchQuery.toLowerCase()));
|
|
151
|
+
|
|
152
|
+
const matchesCategory = selectedCategory === 'all' ||
|
|
153
|
+
plugin.tags.includes(selectedCategory);
|
|
154
|
+
|
|
155
|
+
return matchesSearch && matchesCategory;
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const handleInstall = async (pluginId: string) => {
|
|
159
|
+
setInstalling(pluginId);
|
|
160
|
+
await onInstall(pluginId);
|
|
161
|
+
setInstalling(null);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const handleUninstall = async (pluginId: string) => {
|
|
165
|
+
setInstalling(pluginId);
|
|
166
|
+
await onUninstall(pluginId);
|
|
167
|
+
setInstalling(null);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const formatDownloads = (num: number) => {
|
|
171
|
+
if (num >= 1000) {
|
|
172
|
+
return `${(num / 1000).toFixed(1)}k`;
|
|
173
|
+
}
|
|
174
|
+
return num.toString();
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
<div className="fixed inset-0 z-50 bg-black/50 flex items-center justify-center p-4">
|
|
179
|
+
<div className="bg-background rounded-xl shadow-2xl w-full max-w-4xl max-h-[80vh] flex flex-col">
|
|
180
|
+
{/* Header */}
|
|
181
|
+
<div className="flex items-center justify-between px-6 py-4 border-b border-border">
|
|
182
|
+
<div className="flex items-center gap-3">
|
|
183
|
+
<div className="p-2 bg-primary/10 rounded-lg">
|
|
184
|
+
<Package className="w-5 h-5 text-primary" />
|
|
185
|
+
</div>
|
|
186
|
+
<div>
|
|
187
|
+
<h2 className="text-lg font-semibold">Plugin Marketplace</h2>
|
|
188
|
+
<p className="text-sm text-muted-foreground">Extend Codex Linux with plugins</p>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
<button
|
|
192
|
+
onClick={onClose}
|
|
193
|
+
className="p-2 hover:bg-muted rounded-lg transition-colors"
|
|
194
|
+
>
|
|
195
|
+
<X className="w-5 h-5" />
|
|
196
|
+
</button>
|
|
197
|
+
</div>
|
|
198
|
+
|
|
199
|
+
{/* Search & Filters */}
|
|
200
|
+
<div className="px-6 py-4 border-b border-border">
|
|
201
|
+
<div className="flex items-center gap-4">
|
|
202
|
+
<div className="flex-1 relative">
|
|
203
|
+
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
|
|
204
|
+
<input
|
|
205
|
+
type="text"
|
|
206
|
+
placeholder="Search plugins..."
|
|
207
|
+
value={searchQuery}
|
|
208
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
209
|
+
className="w-full pl-10 pr-4 py-2 bg-muted border-0 rounded-lg text-sm"
|
|
210
|
+
/>
|
|
211
|
+
</div>
|
|
212
|
+
</div>
|
|
213
|
+
|
|
214
|
+
<div className="flex items-center gap-2 mt-3 overflow-x-auto">
|
|
215
|
+
{PLUGIN_CATEGORIES.map((category) => (
|
|
216
|
+
<button
|
|
217
|
+
key={category.id}
|
|
218
|
+
onClick={() => setSelectedCategory(category.id)}
|
|
219
|
+
className={cn(
|
|
220
|
+
'px-3 py-1.5 text-sm rounded-full whitespace-nowrap transition-colors',
|
|
221
|
+
selectedCategory === category.id
|
|
222
|
+
? 'bg-primary text-primary-foreground'
|
|
223
|
+
: 'bg-muted hover:bg-muted/80'
|
|
224
|
+
)}
|
|
225
|
+
>
|
|
226
|
+
{category.label}
|
|
227
|
+
</button>
|
|
228
|
+
))}
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
|
|
232
|
+
{/* Plugin List */}
|
|
233
|
+
<div className="flex-1 overflow-y-auto p-6">
|
|
234
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
235
|
+
{filteredPlugins.map((plugin) => (
|
|
236
|
+
<div
|
|
237
|
+
key={plugin.id}
|
|
238
|
+
className="p-4 border border-border rounded-lg hover:border-primary/50 transition-colors"
|
|
239
|
+
>
|
|
240
|
+
<div className="flex items-start justify-between">
|
|
241
|
+
<div className="flex-1">
|
|
242
|
+
<div className="flex items-center gap-2">
|
|
243
|
+
<h3 className="font-medium">{plugin.name}</h3>
|
|
244
|
+
{plugin.installed && (
|
|
245
|
+
<span className="px-1.5 py-0.5 text-xs bg-green-500/10 text-green-500 rounded">
|
|
246
|
+
<Check className="w-3 h-3 inline" /> Installed
|
|
247
|
+
</span>
|
|
248
|
+
)}
|
|
249
|
+
</div>
|
|
250
|
+
<p className="text-sm text-muted-foreground mt-1">{plugin.description}</p>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
|
|
254
|
+
<div className="flex items-center gap-4 mt-3 text-xs text-muted-foreground">
|
|
255
|
+
<div className="flex items-center gap-1">
|
|
256
|
+
<Star className="w-3.5 h-3.5 text-yellow-500 fill-yellow-500" />
|
|
257
|
+
<span>{plugin.rating}</span>
|
|
258
|
+
</div>
|
|
259
|
+
<div className="flex items-center gap-1">
|
|
260
|
+
<Download className="w-3.5 h-3.5" />
|
|
261
|
+
<span>{formatDownloads(plugin.downloads)}</span>
|
|
262
|
+
</div>
|
|
263
|
+
<span>v{plugin.version}</span>
|
|
264
|
+
</div>
|
|
265
|
+
|
|
266
|
+
<div className="flex items-center justify-between mt-3 pt-3 border-t border-border">
|
|
267
|
+
<span className="text-xs text-muted-foreground">by {plugin.author}</span>
|
|
268
|
+
|
|
269
|
+
{plugin.installed ? (
|
|
270
|
+
<button
|
|
271
|
+
onClick={() => handleUninstall(plugin.id)}
|
|
272
|
+
disabled={installing === plugin.id}
|
|
273
|
+
className="px-3 py-1.5 text-sm text-red-500 hover:bg-red-500/10 rounded-md transition-colors disabled:opacity-50"
|
|
274
|
+
>
|
|
275
|
+
{installing === plugin.id ? 'Uninstalling...' : 'Uninstall'}
|
|
276
|
+
</button>
|
|
277
|
+
) : (
|
|
278
|
+
<button
|
|
279
|
+
onClick={() => handleInstall(plugin.id)}
|
|
280
|
+
disabled={installing === plugin.id}
|
|
281
|
+
className="px-3 py-1.5 text-sm bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors disabled:opacity-50 flex items-center gap-1"
|
|
282
|
+
>
|
|
283
|
+
<Download className="w-3.5 h-3.5" />
|
|
284
|
+
{installing === plugin.id ? 'Installing...' : 'Install'}
|
|
285
|
+
</button>
|
|
286
|
+
)}
|
|
287
|
+
</div>
|
|
288
|
+
</div>
|
|
289
|
+
))}
|
|
290
|
+
</div>
|
|
291
|
+
|
|
292
|
+
{filteredPlugins.length === 0 && (
|
|
293
|
+
<div className="text-center py-12 text-muted-foreground">
|
|
294
|
+
<Search className="w-12 h-12 mx-auto mb-4 opacity-30" />
|
|
295
|
+
<p>No plugins found matching your search</p>
|
|
296
|
+
</div>
|
|
297
|
+
)}
|
|
298
|
+
</div>
|
|
299
|
+
|
|
300
|
+
{/* Footer */}
|
|
301
|
+
<div className="px-6 py-3 border-t border-border flex items-center justify-between text-xs text-muted-foreground">
|
|
302
|
+
<div className="flex items-center gap-4">
|
|
303
|
+
<span className="flex items-center gap-1">
|
|
304
|
+
<Shield className="w-3.5 h-3.5" />
|
|
305
|
+
Verified plugins
|
|
306
|
+
</span>
|
|
307
|
+
<span className="flex items-center gap-1">
|
|
308
|
+
<Zap className="w-3.5 h-3.5" />
|
|
309
|
+
Fast installation
|
|
310
|
+
</span>
|
|
311
|
+
</div>
|
|
312
|
+
<a
|
|
313
|
+
href="#"
|
|
314
|
+
className="flex items-center gap-1 hover:text-primary transition-colors"
|
|
315
|
+
>
|
|
316
|
+
Browse more plugins
|
|
317
|
+
<ExternalLink className="w-3.5 h-3.5" />
|
|
318
|
+
</a>
|
|
319
|
+
</div>
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
322
|
+
);
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
export default PluginMarketplace;
|