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,220 @@
|
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
+
import { Play, Square, RefreshCw, ExternalLink, Maximize2, Minimize2, Smartphone, Monitor, Tablet } from 'lucide-react';
|
|
3
|
+
|
|
4
|
+
interface AppPreviewProps {
|
|
5
|
+
projectPath: string;
|
|
6
|
+
port?: number;
|
|
7
|
+
onPortChange?: (port: number) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const AppPreview: React.FC<AppPreviewProps> = ({
|
|
11
|
+
projectPath,
|
|
12
|
+
port = 3000,
|
|
13
|
+
onPortChange,
|
|
14
|
+
}) => {
|
|
15
|
+
const [isRunning, setIsRunning] = useState(false);
|
|
16
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
17
|
+
const [url, setUrl] = useState(`http://localhost:${port}`);
|
|
18
|
+
const [viewMode, setViewMode] = useState<'desktop' | 'tablet' | 'mobile'>('desktop');
|
|
19
|
+
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
20
|
+
const [logs, setLogs] = useState<string[]>([]);
|
|
21
|
+
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
22
|
+
|
|
23
|
+
const viewModes = {
|
|
24
|
+
desktop: { width: '100%', height: '100%' },
|
|
25
|
+
tablet: { width: '768px', height: '1024px' },
|
|
26
|
+
mobile: { width: '375px', height: '667px' },
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const startServer = async () => {
|
|
30
|
+
setIsLoading(true);
|
|
31
|
+
try {
|
|
32
|
+
// Detect package.json and start command
|
|
33
|
+
const packageJson = await window.electronAPI.fs.readFile(
|
|
34
|
+
`${projectPath}/package.json`
|
|
35
|
+
);
|
|
36
|
+
const pkg = JSON.parse(packageJson);
|
|
37
|
+
const startCommand = pkg.scripts?.dev || pkg.scripts?.start || 'npm start';
|
|
38
|
+
|
|
39
|
+
// Start dev server
|
|
40
|
+
await window.electronAPI.terminal.execute({
|
|
41
|
+
command: startCommand,
|
|
42
|
+
cwd: projectPath,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Wait for server to be ready
|
|
46
|
+
await waitForServer(url);
|
|
47
|
+
|
|
48
|
+
setIsRunning(true);
|
|
49
|
+
addLog(`Server started on ${url}`);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
addLog(`Error: ${error}`);
|
|
52
|
+
}
|
|
53
|
+
setIsLoading(false);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const stopServer = async () => {
|
|
57
|
+
await window.electronAPI.terminal.kill();
|
|
58
|
+
setIsRunning(false);
|
|
59
|
+
addLog('Server stopped');
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const refreshPreview = () => {
|
|
63
|
+
if (iframeRef.current) {
|
|
64
|
+
iframeRef.current.src = iframeRef.current.src;
|
|
65
|
+
addLog('Preview refreshed');
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const waitForServer = async (url: string, timeout = 30000): Promise<void> => {
|
|
70
|
+
const startTime = Date.now();
|
|
71
|
+
|
|
72
|
+
while (Date.now() - startTime < timeout) {
|
|
73
|
+
try {
|
|
74
|
+
const response = await fetch(url, { method: 'HEAD', mode: 'no-cors' });
|
|
75
|
+
return;
|
|
76
|
+
} catch {
|
|
77
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
throw new Error('Server failed to start within timeout');
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const addLog = (message: string) => {
|
|
85
|
+
setLogs(prev => [...prev.slice(-50), `[${new Date().toLocaleTimeString()}] ${message}`]);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const openExternal = () => {
|
|
89
|
+
window.electronAPI.shell.openExternal(url);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div className={`flex flex-col bg-card ${isFullscreen ? 'fixed inset-0 z-50' : 'h-full'}`}>
|
|
94
|
+
{/* Toolbar */}
|
|
95
|
+
<div className="flex items-center justify-between px-4 py-2 border-b border-border bg-background/50">
|
|
96
|
+
<div className="flex items-center gap-2">
|
|
97
|
+
{!isRunning ? (
|
|
98
|
+
<button
|
|
99
|
+
onClick={startServer}
|
|
100
|
+
disabled={isLoading}
|
|
101
|
+
className="flex items-center gap-2 px-3 py-1.5 bg-green-500 text-white rounded-md hover:bg-green-600 disabled:opacity-50"
|
|
102
|
+
>
|
|
103
|
+
<Play className="w-4 h-4" />
|
|
104
|
+
{isLoading ? 'Starting...' : 'Start'}
|
|
105
|
+
</button>
|
|
106
|
+
) : (
|
|
107
|
+
<button
|
|
108
|
+
onClick={stopServer}
|
|
109
|
+
className="flex items-center gap-2 px-3 py-1.5 bg-red-500 text-white rounded-md hover:bg-red-600"
|
|
110
|
+
>
|
|
111
|
+
<Square className="w-4 h-4" />
|
|
112
|
+
Stop
|
|
113
|
+
</button>
|
|
114
|
+
)}
|
|
115
|
+
|
|
116
|
+
<button
|
|
117
|
+
onClick={refreshPreview}
|
|
118
|
+
disabled={!isRunning}
|
|
119
|
+
className="p-2 hover:bg-muted rounded-md disabled:opacity-50"
|
|
120
|
+
>
|
|
121
|
+
<RefreshCw className="w-4 h-4" />
|
|
122
|
+
</button>
|
|
123
|
+
|
|
124
|
+
<div className="h-6 w-px bg-border mx-2" />
|
|
125
|
+
|
|
126
|
+
<div className="flex items-center gap-1">
|
|
127
|
+
<button
|
|
128
|
+
onClick={() => setViewMode('desktop')}
|
|
129
|
+
className={`p-2 rounded-md ${viewMode === 'desktop' ? 'bg-primary text-primary-foreground' : 'hover:bg-muted'}`}
|
|
130
|
+
>
|
|
131
|
+
<Monitor className="w-4 h-4" />
|
|
132
|
+
</button>
|
|
133
|
+
<button
|
|
134
|
+
onClick={() => setViewMode('tablet')}
|
|
135
|
+
className={`p-2 rounded-md ${viewMode === 'tablet' ? 'bg-primary text-primary-foreground' : 'hover:bg-muted'}`}
|
|
136
|
+
>
|
|
137
|
+
<Tablet className="w-4 h-4" />
|
|
138
|
+
</button>
|
|
139
|
+
<button
|
|
140
|
+
onClick={() => setViewMode('mobile')}
|
|
141
|
+
className={`p-2 rounded-md ${viewMode === 'mobile' ? 'bg-primary text-primary-foreground' : 'hover:bg-muted'}`}
|
|
142
|
+
>
|
|
143
|
+
<Smartphone className="w-4 h-4" />
|
|
144
|
+
</button>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<div className="flex items-center gap-2">
|
|
149
|
+
<input
|
|
150
|
+
type="text"
|
|
151
|
+
value={url}
|
|
152
|
+
onChange={(e) => {
|
|
153
|
+
setUrl(e.target.value);
|
|
154
|
+
const newPort = parseInt(e.target.value.split(':')[2]) || port;
|
|
155
|
+
onPortChange?.(newPort);
|
|
156
|
+
}}
|
|
157
|
+
className="px-3 py-1.5 bg-background border border-input rounded-md text-sm w-48"
|
|
158
|
+
/>
|
|
159
|
+
|
|
160
|
+
<button
|
|
161
|
+
onClick={openExternal}
|
|
162
|
+
className="p-2 hover:bg-muted rounded-md"
|
|
163
|
+
>
|
|
164
|
+
<ExternalLink className="w-4 h-4" />
|
|
165
|
+
</button>
|
|
166
|
+
|
|
167
|
+
<button
|
|
168
|
+
onClick={() => setIsFullscreen(!isFullscreen)}
|
|
169
|
+
className="p-2 hover:bg-muted rounded-md"
|
|
170
|
+
>
|
|
171
|
+
{isFullscreen ? <Minimize2 className="w-4 h-4" /> : <Maximize2 className="w-4 h-4" />}
|
|
172
|
+
</button>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
{/* Preview Area */}
|
|
177
|
+
<div className="flex-1 flex overflow-hidden">
|
|
178
|
+
<div className="flex-1 bg-[#1e1e1e] flex items-center justify-center p-4 overflow-auto">
|
|
179
|
+
{isRunning ? (
|
|
180
|
+
<div
|
|
181
|
+
className="bg-white rounded-lg shadow-2xl overflow-hidden transition-all duration-300"
|
|
182
|
+
style={viewModes[viewMode]}
|
|
183
|
+
>
|
|
184
|
+
<iframe
|
|
185
|
+
ref={iframeRef}
|
|
186
|
+
src={url}
|
|
187
|
+
className="w-full h-full border-0"
|
|
188
|
+
sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
|
|
189
|
+
title="App Preview"
|
|
190
|
+
/>
|
|
191
|
+
</div>
|
|
192
|
+
) : (
|
|
193
|
+
<div className="text-center text-muted-foreground">
|
|
194
|
+
<Monitor className="w-16 h-16 mx-auto mb-4 opacity-30" />
|
|
195
|
+
<p className="text-lg font-medium">App Preview</p>
|
|
196
|
+
<p className="text-sm mt-2">Start the dev server to see your app</p>
|
|
197
|
+
</div>
|
|
198
|
+
)}
|
|
199
|
+
</div>
|
|
200
|
+
|
|
201
|
+
{/* Logs Panel */}
|
|
202
|
+
<div className="w-80 border-l border-border bg-card flex flex-col">
|
|
203
|
+
<div className="px-4 py-2 border-b border-border font-medium text-sm">
|
|
204
|
+
Server Logs
|
|
205
|
+
</div>
|
|
206
|
+
<div className="flex-1 overflow-auto p-2 font-mono text-xs">
|
|
207
|
+
{logs.map((log, i) => (
|
|
208
|
+
<div key={i} className="text-muted-foreground py-0.5">
|
|
209
|
+
{log}
|
|
210
|
+
</div>
|
|
211
|
+
))}
|
|
212
|
+
{logs.length === 0 && (
|
|
213
|
+
<div className="text-muted-foreground italic">No logs yet...</div>
|
|
214
|
+
)}
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
);
|
|
220
|
+
};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { ScrollText, Download, Filter, RefreshCw } from 'lucide-react';
|
|
3
|
+
import { format } from 'date-fns';
|
|
4
|
+
|
|
5
|
+
interface AuditEvent {
|
|
6
|
+
id: string;
|
|
7
|
+
timestamp: string;
|
|
8
|
+
action: string;
|
|
9
|
+
userId: string;
|
|
10
|
+
details: Record<string, any>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const AuditTrailPanel: React.FC = () => {
|
|
14
|
+
const [events, setEvents] = useState<AuditEvent[]>([]);
|
|
15
|
+
const [loading, setLoading] = useState(false);
|
|
16
|
+
const [filter, setFilter] = useState<string>('');
|
|
17
|
+
const [expandedId, setExpandedId] = useState<string | null>(null);
|
|
18
|
+
|
|
19
|
+
const loadEvents = async () => {
|
|
20
|
+
setLoading(true);
|
|
21
|
+
try {
|
|
22
|
+
const recent = await window.electronAPI.audit.recent(100);
|
|
23
|
+
setEvents(recent as AuditEvent[]);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.error('Failed to load audit events:', error);
|
|
26
|
+
} finally {
|
|
27
|
+
setLoading(false);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
loadEvents();
|
|
33
|
+
}, []);
|
|
34
|
+
|
|
35
|
+
const filteredEvents = filter
|
|
36
|
+
? events.filter(e => e.action.toLowerCase().includes(filter.toLowerCase()))
|
|
37
|
+
: events;
|
|
38
|
+
|
|
39
|
+
const exportLogs = async () => {
|
|
40
|
+
try {
|
|
41
|
+
const path = await window.electronAPI.dialog.selectFile?.([{ name: 'JSON', extensions: ['json'] }]);
|
|
42
|
+
if (path) {
|
|
43
|
+
await window.electronAPI.audit.export(path);
|
|
44
|
+
await window.electronAPI.notification.show({
|
|
45
|
+
title: 'Audit log exported',
|
|
46
|
+
body: `Exported to ${path}`
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error('Export failed:', error);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const getActionColor = (action: string) => {
|
|
55
|
+
if (action.includes('created')) return 'bg-green-500/10 text-green-500';
|
|
56
|
+
if (action.includes('deleted')) return 'bg-red-500/10 text-red-500';
|
|
57
|
+
if (action.includes('applied') || action.includes('restored')) return 'bg-blue-500/10 text-blue-500';
|
|
58
|
+
if (action.includes('failed')) return 'bg-orange-500/10 text-orange-500';
|
|
59
|
+
return 'bg-gray-500/10 text-gray-500';
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<div className="h-full flex flex-col bg-card">
|
|
64
|
+
<div className="px-4 py-3 border-b border-border flex items-center justify-between bg-background/50">
|
|
65
|
+
<div className="flex items-center gap-3">
|
|
66
|
+
<ScrollText className="w-5 h-5 text-muted-foreground" />
|
|
67
|
+
<div>
|
|
68
|
+
<h3 className="font-medium">Audit Trail</h3>
|
|
69
|
+
<p className="text-xs text-muted-foreground">Session activity log</p>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
<div className="flex items-center gap-2">
|
|
73
|
+
<button
|
|
74
|
+
onClick={loadEvents}
|
|
75
|
+
disabled={loading}
|
|
76
|
+
className="p-2 hover:bg-muted rounded-md disabled:opacity-50"
|
|
77
|
+
title="Refresh"
|
|
78
|
+
>
|
|
79
|
+
<RefreshCw className={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />
|
|
80
|
+
</button>
|
|
81
|
+
<button
|
|
82
|
+
onClick={exportLogs}
|
|
83
|
+
className="p-2 hover:bg-muted rounded-md"
|
|
84
|
+
title="Export logs"
|
|
85
|
+
>
|
|
86
|
+
<Download className="w-4 h-4" />
|
|
87
|
+
</button>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<div className="p-3 border-b border-border">
|
|
92
|
+
<div className="relative">
|
|
93
|
+
<Filter className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
|
|
94
|
+
<input
|
|
95
|
+
type="text"
|
|
96
|
+
value={filter}
|
|
97
|
+
onChange={(e) => setFilter(e.target.value)}
|
|
98
|
+
placeholder="Filter by action..."
|
|
99
|
+
className="w-full pl-9 pr-3 py-2 bg-background border border-input rounded-md text-sm"
|
|
100
|
+
/>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<div className="flex-1 overflow-y-auto p-3 space-y-2">
|
|
105
|
+
{filteredEvents.length === 0 ? (
|
|
106
|
+
<div className="text-center py-8 text-muted-foreground">
|
|
107
|
+
<ScrollText className="w-12 h-12 mx-auto mb-3 opacity-30" />
|
|
108
|
+
<p className="text-sm">No audit events</p>
|
|
109
|
+
</div>
|
|
110
|
+
) : (
|
|
111
|
+
filteredEvents.map((event) => (
|
|
112
|
+
<div
|
|
113
|
+
key={event.id}
|
|
114
|
+
className="border border-border rounded-lg overflow-hidden"
|
|
115
|
+
>
|
|
116
|
+
<button
|
|
117
|
+
onClick={() => setExpandedId(expandedId === event.id ? null : event.id)}
|
|
118
|
+
className="w-full px-3 py-2 flex items-center gap-3 hover:bg-muted/50 transition-colors text-left"
|
|
119
|
+
>
|
|
120
|
+
<span className={`px-2 py-0.5 rounded text-xs font-medium ${getActionColor(event.action)}`}>
|
|
121
|
+
{event.action}
|
|
122
|
+
</span>
|
|
123
|
+
<span className="text-xs text-muted-foreground flex-1">
|
|
124
|
+
{format(new Date(event.timestamp), 'MMM d, HH:mm:ss')}
|
|
125
|
+
</span>
|
|
126
|
+
<span className="text-xs text-muted-foreground">
|
|
127
|
+
{expandedId === event.id ? '−' : '+'}
|
|
128
|
+
</span>
|
|
129
|
+
</button>
|
|
130
|
+
|
|
131
|
+
{expandedId === event.id && (
|
|
132
|
+
<div className="px-3 py-2 bg-muted/30 border-t border-border">
|
|
133
|
+
<pre className="text-xs font-mono text-muted-foreground overflow-x-auto">
|
|
134
|
+
{JSON.stringify(event.details, null, 2)}
|
|
135
|
+
</pre>
|
|
136
|
+
</div>
|
|
137
|
+
)}
|
|
138
|
+
</div>
|
|
139
|
+
))
|
|
140
|
+
)}
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
<div className="px-4 py-2 border-t border-border text-xs text-muted-foreground">
|
|
144
|
+
Showing {filteredEvents.length} of {events.length} events
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
);
|
|
148
|
+
};
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Automation, Agent, Skill } from '../../shared/types';
|
|
3
|
+
import { Clock, Plus, Play, Pause, Settings, Trash2, Calendar, Zap } from 'lucide-react';
|
|
4
|
+
|
|
5
|
+
interface AutomationPanelProps {
|
|
6
|
+
automations: Automation[];
|
|
7
|
+
agents: Agent[];
|
|
8
|
+
skills: Skill[];
|
|
9
|
+
onCreateAutomation: (config: any) => Promise<Automation>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const AutomationPanel: React.FC<AutomationPanelProps> = ({
|
|
13
|
+
automations,
|
|
14
|
+
agents,
|
|
15
|
+
skills,
|
|
16
|
+
onCreateAutomation
|
|
17
|
+
}) => {
|
|
18
|
+
const [showCreateModal, setShowCreateModal] = useState(false);
|
|
19
|
+
const [newAutomation, setNewAutomation] = useState({
|
|
20
|
+
name: '',
|
|
21
|
+
description: '',
|
|
22
|
+
triggerType: 'schedule' as const,
|
|
23
|
+
triggerConfig: { cron: '0 9 * * *' },
|
|
24
|
+
actions: [] as any[]
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const handleCreate = async () => {
|
|
28
|
+
try {
|
|
29
|
+
await onCreateAutomation(newAutomation);
|
|
30
|
+
setShowCreateModal(false);
|
|
31
|
+
setNewAutomation({
|
|
32
|
+
name: '',
|
|
33
|
+
description: '',
|
|
34
|
+
triggerType: 'schedule',
|
|
35
|
+
triggerConfig: { cron: '0 9 * * *' },
|
|
36
|
+
actions: []
|
|
37
|
+
});
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error('Failed to create automation:', error);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const handleToggle = async (automationId: string, enabled: boolean) => {
|
|
44
|
+
try {
|
|
45
|
+
await window.electronAPI.automation.toggle(automationId, enabled);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error('Failed to toggle automation:', error);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div className="h-full flex flex-col">
|
|
53
|
+
<div className="p-4 border-b border-border flex items-center justify-between">
|
|
54
|
+
<div>
|
|
55
|
+
<h2 className="text-lg font-semibold">Automations</h2>
|
|
56
|
+
<p className="text-sm text-muted-foreground">Schedule and automate agent tasks</p>
|
|
57
|
+
</div>
|
|
58
|
+
<button
|
|
59
|
+
onClick={() => setShowCreateModal(true)}
|
|
60
|
+
className="flex items-center gap-2 px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90"
|
|
61
|
+
>
|
|
62
|
+
<Plus className="w-4 h-4" />
|
|
63
|
+
New Automation
|
|
64
|
+
</button>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div className="flex-1 overflow-auto p-4">
|
|
68
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
69
|
+
{automations.map(automation => (
|
|
70
|
+
<div
|
|
71
|
+
key={automation.id}
|
|
72
|
+
className="p-4 bg-card border border-border rounded-lg"
|
|
73
|
+
>
|
|
74
|
+
<div className="flex items-start justify-between mb-3">
|
|
75
|
+
<div className="flex items-center gap-2">
|
|
76
|
+
<Clock className="w-5 h-5 text-muted-foreground" />
|
|
77
|
+
<span className="font-medium">{automation.name}</span>
|
|
78
|
+
</div>
|
|
79
|
+
<div className="flex items-center gap-2">
|
|
80
|
+
<button
|
|
81
|
+
onClick={() => handleToggle(automation.id, !automation.enabled)}
|
|
82
|
+
className={`p-1.5 rounded-md ${
|
|
83
|
+
automation.enabled
|
|
84
|
+
? 'text-green-500 hover:bg-green-500/10'
|
|
85
|
+
: 'text-muted-foreground hover:bg-muted'
|
|
86
|
+
}`}
|
|
87
|
+
>
|
|
88
|
+
{automation.enabled ? <Pause className="w-4 h-4" /> : <Play className="w-4 h-4" />}
|
|
89
|
+
</button>
|
|
90
|
+
<button className="p-1.5 text-destructive hover:bg-destructive/10 rounded-md">
|
|
91
|
+
<Trash2 className="w-4 h-4" />
|
|
92
|
+
</button>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<p className="text-sm text-muted-foreground mb-3">
|
|
97
|
+
{automation.description}
|
|
98
|
+
</p>
|
|
99
|
+
|
|
100
|
+
<div className="flex items-center gap-4 text-xs text-muted-foreground">
|
|
101
|
+
<div className="flex items-center gap-1">
|
|
102
|
+
<Calendar className="w-3 h-3" />
|
|
103
|
+
<span className="capitalize">{automation.trigger.type}</span>
|
|
104
|
+
</div>
|
|
105
|
+
<div className="flex items-center gap-1">
|
|
106
|
+
<Zap className="w-3 h-3" />
|
|
107
|
+
<span>{automation.actions.length} actions</span>
|
|
108
|
+
</div>
|
|
109
|
+
{automation.runCount > 0 && (
|
|
110
|
+
<div>
|
|
111
|
+
Run {automation.runCount} times
|
|
112
|
+
</div>
|
|
113
|
+
)}
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
{automation.enabled && (
|
|
117
|
+
<div className="mt-3 flex items-center gap-2 text-xs text-green-500">
|
|
118
|
+
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
|
|
119
|
+
Active
|
|
120
|
+
</div>
|
|
121
|
+
)}
|
|
122
|
+
</div>
|
|
123
|
+
))}
|
|
124
|
+
|
|
125
|
+
{automations.length === 0 && (
|
|
126
|
+
<div className="col-span-full flex flex-col items-center justify-center py-12 text-muted-foreground">
|
|
127
|
+
<Clock className="w-16 h-16 mb-4 opacity-30" />
|
|
128
|
+
<p className="text-lg font-medium">No automations yet</p>
|
|
129
|
+
<p className="text-sm">Create an automation to schedule agent tasks</p>
|
|
130
|
+
</div>
|
|
131
|
+
)}
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
{showCreateModal && (
|
|
136
|
+
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
|
|
137
|
+
<div className="bg-card border border-border rounded-lg p-6 w-[600px]">
|
|
138
|
+
<h2 className="text-lg font-semibold mb-4">Create New Automation</h2>
|
|
139
|
+
|
|
140
|
+
<div className="space-y-4">
|
|
141
|
+
<div>
|
|
142
|
+
<label className="block text-sm font-medium mb-1">Name</label>
|
|
143
|
+
<input
|
|
144
|
+
type="text"
|
|
145
|
+
value={newAutomation.name}
|
|
146
|
+
onChange={e => setNewAutomation({ ...newAutomation, name: e.target.value })}
|
|
147
|
+
className="w-full px-3 py-2 bg-background border border-input rounded-md"
|
|
148
|
+
placeholder="Daily Code Review"
|
|
149
|
+
/>
|
|
150
|
+
</div>
|
|
151
|
+
|
|
152
|
+
<div>
|
|
153
|
+
<label className="block text-sm font-medium mb-1">Description</label>
|
|
154
|
+
<textarea
|
|
155
|
+
value={newAutomation.description}
|
|
156
|
+
onChange={e => setNewAutomation({ ...newAutomation, description: e.target.value })}
|
|
157
|
+
className="w-full px-3 py-2 bg-background border border-input rounded-md h-20 resize-none"
|
|
158
|
+
placeholder="What does this automation do?"
|
|
159
|
+
/>
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<div>
|
|
163
|
+
<label className="block text-sm font-medium mb-1">Trigger Type</label>
|
|
164
|
+
<select
|
|
165
|
+
value={newAutomation.triggerType}
|
|
166
|
+
onChange={e => setNewAutomation({
|
|
167
|
+
...newAutomation,
|
|
168
|
+
triggerType: e.target.value as any,
|
|
169
|
+
triggerConfig: e.target.value === 'schedule' ? { cron: '0 9 * * *' } : {}
|
|
170
|
+
})}
|
|
171
|
+
className="w-full px-3 py-2 bg-background border border-input rounded-md"
|
|
172
|
+
>
|
|
173
|
+
<option value="schedule">Schedule (Cron)</option>
|
|
174
|
+
<option value="event">Event</option>
|
|
175
|
+
<option value="webhook">Webhook</option>
|
|
176
|
+
<option value="manual">Manual Only</option>
|
|
177
|
+
</select>
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
{newAutomation.triggerType === 'schedule' && (
|
|
181
|
+
<div>
|
|
182
|
+
<label className="block text-sm font-medium mb-1">Cron Expression</label>
|
|
183
|
+
<input
|
|
184
|
+
type="text"
|
|
185
|
+
value={newAutomation.triggerConfig.cron}
|
|
186
|
+
onChange={e => setNewAutomation({
|
|
187
|
+
...newAutomation,
|
|
188
|
+
triggerConfig: { cron: e.target.value }
|
|
189
|
+
})}
|
|
190
|
+
className="w-full px-3 py-2 bg-background border border-input rounded-md font-mono"
|
|
191
|
+
placeholder="0 9 * * *"
|
|
192
|
+
/>
|
|
193
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
194
|
+
Example: 0 9 * * * (every day at 9 AM)
|
|
195
|
+
</p>
|
|
196
|
+
</div>
|
|
197
|
+
)}
|
|
198
|
+
</div>
|
|
199
|
+
|
|
200
|
+
<div className="flex justify-end gap-2 mt-6">
|
|
201
|
+
<button
|
|
202
|
+
onClick={() => setShowCreateModal(false)}
|
|
203
|
+
className="px-4 py-2 text-muted-foreground"
|
|
204
|
+
>
|
|
205
|
+
Cancel
|
|
206
|
+
</button>
|
|
207
|
+
<button
|
|
208
|
+
onClick={handleCreate}
|
|
209
|
+
disabled={!newAutomation.name}
|
|
210
|
+
className="px-4 py-2 bg-primary text-primary-foreground rounded-md disabled:opacity-50"
|
|
211
|
+
>
|
|
212
|
+
Create Automation
|
|
213
|
+
</button>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
)}
|
|
218
|
+
</div>
|
|
219
|
+
);
|
|
220
|
+
};
|