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,234 @@
|
|
|
1
|
+
-- Supabase Database Schema for Codex Linux Cloud Sync
|
|
2
|
+
-- Run this in your Supabase SQL Editor
|
|
3
|
+
|
|
4
|
+
-- Enable realtime for threads table
|
|
5
|
+
alter publication supabase_realtime add table threads;
|
|
6
|
+
|
|
7
|
+
-- Create threads table
|
|
8
|
+
CREATE TABLE IF NOT EXISTS threads (
|
|
9
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
10
|
+
agent_id UUID NOT NULL,
|
|
11
|
+
user_id UUID NOT NULL,
|
|
12
|
+
device_id TEXT NOT NULL,
|
|
13
|
+
project_path TEXT NOT NULL,
|
|
14
|
+
messages JSONB NOT NULL DEFAULT '[]',
|
|
15
|
+
status TEXT NOT NULL DEFAULT 'idle',
|
|
16
|
+
last_modified BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) * 1000,
|
|
17
|
+
version INTEGER NOT NULL DEFAULT 1,
|
|
18
|
+
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
|
19
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
20
|
+
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
-- Create indexes for better performance
|
|
24
|
+
CREATE INDEX IF NOT EXISTS idx_threads_user_id ON threads(user_id);
|
|
25
|
+
CREATE INDEX IF NOT EXISTS idx_threads_agent_id ON threads(agent_id);
|
|
26
|
+
CREATE INDEX IF NOT EXISTS idx_threads_device_id ON threads(device_id);
|
|
27
|
+
CREATE INDEX IF NOT EXISTS idx_threads_last_modified ON threads(last_modified);
|
|
28
|
+
CREATE INDEX IF NOT EXISTS idx_threads_user_deleted ON threads(user_id, is_deleted);
|
|
29
|
+
|
|
30
|
+
-- Create users table for cloud sync
|
|
31
|
+
CREATE TABLE IF NOT EXISTS cloud_users (
|
|
32
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
33
|
+
email TEXT UNIQUE NOT NULL,
|
|
34
|
+
display_name TEXT,
|
|
35
|
+
avatar_url TEXT,
|
|
36
|
+
devices JSONB NOT NULL DEFAULT '[]',
|
|
37
|
+
settings JSONB NOT NULL DEFAULT '{}',
|
|
38
|
+
subscription_tier TEXT DEFAULT 'free',
|
|
39
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
40
|
+
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
-- Create devices table to track user devices
|
|
44
|
+
CREATE TABLE IF NOT EXISTS user_devices (
|
|
45
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
46
|
+
user_id UUID NOT NULL REFERENCES cloud_users(id) ON DELETE CASCADE,
|
|
47
|
+
device_id TEXT NOT NULL,
|
|
48
|
+
device_name TEXT NOT NULL,
|
|
49
|
+
device_type TEXT NOT NULL,
|
|
50
|
+
last_sync BIGINT,
|
|
51
|
+
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
52
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
53
|
+
UNIQUE(user_id, device_id)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
-- Create sync conflicts table for manual resolution
|
|
57
|
+
CREATE TABLE IF NOT EXISTS sync_conflicts (
|
|
58
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
59
|
+
thread_id UUID NOT NULL REFERENCES threads(id) ON DELETE CASCADE,
|
|
60
|
+
user_id UUID NOT NULL,
|
|
61
|
+
local_version JSONB NOT NULL,
|
|
62
|
+
remote_version JSONB NOT NULL,
|
|
63
|
+
resolution TEXT,
|
|
64
|
+
resolved_at TIMESTAMP WITH TIME ZONE,
|
|
65
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
-- Row Level Security (RLS) Policies
|
|
69
|
+
|
|
70
|
+
-- Enable RLS on all tables
|
|
71
|
+
ALTER TABLE threads ENABLE ROW LEVEL SECURITY;
|
|
72
|
+
ALTER TABLE cloud_users ENABLE ROW LEVEL SECURITY;
|
|
73
|
+
ALTER TABLE user_devices ENABLE ROW LEVEL SECURITY;
|
|
74
|
+
ALTER TABLE sync_conflicts ENABLE ROW LEVEL SECURITY;
|
|
75
|
+
|
|
76
|
+
-- Threads policies
|
|
77
|
+
CREATE POLICY "Users can only access their own threads"
|
|
78
|
+
ON threads FOR ALL
|
|
79
|
+
USING (user_id = auth.uid());
|
|
80
|
+
|
|
81
|
+
-- Cloud users policies
|
|
82
|
+
CREATE POLICY "Users can only access their own profile"
|
|
83
|
+
ON cloud_users FOR ALL
|
|
84
|
+
USING (id = auth.uid());
|
|
85
|
+
|
|
86
|
+
-- User devices policies
|
|
87
|
+
CREATE POLICY "Users can only access their own devices"
|
|
88
|
+
ON user_devices FOR ALL
|
|
89
|
+
USING (user_id = auth.uid());
|
|
90
|
+
|
|
91
|
+
-- Sync conflicts policies
|
|
92
|
+
CREATE POLICY "Users can only access their own conflicts"
|
|
93
|
+
ON sync_conflicts FOR ALL
|
|
94
|
+
USING (user_id = auth_uid());
|
|
95
|
+
|
|
96
|
+
-- Functions
|
|
97
|
+
|
|
98
|
+
-- Function to update the updated_at timestamp
|
|
99
|
+
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
100
|
+
RETURNS TRIGGER AS $$
|
|
101
|
+
BEGIN
|
|
102
|
+
NEW.updated_at = NOW();
|
|
103
|
+
RETURN NEW;
|
|
104
|
+
END;
|
|
105
|
+
$$ language 'plpgsql';
|
|
106
|
+
|
|
107
|
+
-- Triggers for updated_at
|
|
108
|
+
CREATE TRIGGER update_threads_updated_at
|
|
109
|
+
BEFORE UPDATE ON threads
|
|
110
|
+
FOR EACH ROW
|
|
111
|
+
EXECUTE FUNCTION update_updated_at_column();
|
|
112
|
+
|
|
113
|
+
CREATE TRIGGER update_cloud_users_updated_at
|
|
114
|
+
BEFORE UPDATE ON cloud_users
|
|
115
|
+
FOR EACH ROW
|
|
116
|
+
EXECUTE FUNCTION update_updated_at_column();
|
|
117
|
+
|
|
118
|
+
-- Function to get threads modified since a timestamp
|
|
119
|
+
CREATE OR REPLACE FUNCTION get_threads_since(
|
|
120
|
+
p_user_id UUID,
|
|
121
|
+
p_since BIGINT
|
|
122
|
+
)
|
|
123
|
+
RETURNS TABLE (
|
|
124
|
+
id UUID,
|
|
125
|
+
agent_id UUID,
|
|
126
|
+
user_id UUID,
|
|
127
|
+
device_id TEXT,
|
|
128
|
+
project_path TEXT,
|
|
129
|
+
messages JSONB,
|
|
130
|
+
status TEXT,
|
|
131
|
+
last_modified BIGINT,
|
|
132
|
+
version INTEGER,
|
|
133
|
+
is_deleted BOOLEAN,
|
|
134
|
+
created_at TIMESTAMP WITH TIME ZONE,
|
|
135
|
+
updated_at TIMESTAMP WITH TIME ZONE
|
|
136
|
+
) AS $$
|
|
137
|
+
BEGIN
|
|
138
|
+
RETURN QUERY
|
|
139
|
+
SELECT t.*
|
|
140
|
+
FROM threads t
|
|
141
|
+
WHERE t.user_id = p_user_id
|
|
142
|
+
AND t.last_modified > p_since
|
|
143
|
+
AND t.is_deleted = FALSE
|
|
144
|
+
ORDER BY t.last_modified DESC;
|
|
145
|
+
END;
|
|
146
|
+
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
147
|
+
|
|
148
|
+
-- Function to upsert thread with conflict detection
|
|
149
|
+
CREATE OR REPLACE FUNCTION upsert_thread(
|
|
150
|
+
p_id UUID,
|
|
151
|
+
p_agent_id UUID,
|
|
152
|
+
p_user_id UUID,
|
|
153
|
+
p_device_id TEXT,
|
|
154
|
+
p_project_path TEXT,
|
|
155
|
+
p_messages JSONB,
|
|
156
|
+
p_status TEXT,
|
|
157
|
+
p_last_modified BIGINT,
|
|
158
|
+
p_version INTEGER,
|
|
159
|
+
p_is_deleted BOOLEAN
|
|
160
|
+
)
|
|
161
|
+
RETURNS JSONB AS $$
|
|
162
|
+
DECLARE
|
|
163
|
+
existing_version INTEGER;
|
|
164
|
+
result JSONB;
|
|
165
|
+
BEGIN
|
|
166
|
+
-- Check if thread exists and get its version
|
|
167
|
+
SELECT version INTO existing_version
|
|
168
|
+
FROM threads
|
|
169
|
+
WHERE id = p_id;
|
|
170
|
+
|
|
171
|
+
IF existing_version IS NULL THEN
|
|
172
|
+
-- Insert new thread
|
|
173
|
+
INSERT INTO threads (
|
|
174
|
+
id, agent_id, user_id, device_id, project_path,
|
|
175
|
+
messages, status, last_modified, version, is_deleted
|
|
176
|
+
) VALUES (
|
|
177
|
+
p_id, p_agent_id, p_user_id, p_device_id, p_project_path,
|
|
178
|
+
p_messages, p_status, p_last_modified, p_version, p_is_deleted
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
result := jsonb_build_object(
|
|
182
|
+
'success', true,
|
|
183
|
+
'action', 'insert',
|
|
184
|
+
'conflict', false
|
|
185
|
+
);
|
|
186
|
+
ELSIF p_version > existing_version THEN
|
|
187
|
+
-- Update with newer version
|
|
188
|
+
UPDATE threads SET
|
|
189
|
+
agent_id = p_agent_id,
|
|
190
|
+
device_id = p_device_id,
|
|
191
|
+
project_path = p_project_path,
|
|
192
|
+
messages = p_messages,
|
|
193
|
+
status = p_status,
|
|
194
|
+
last_modified = p_last_modified,
|
|
195
|
+
version = p_version,
|
|
196
|
+
is_deleted = p_is_deleted
|
|
197
|
+
WHERE id = p_id;
|
|
198
|
+
|
|
199
|
+
result := jsonb_build_object(
|
|
200
|
+
'success', true,
|
|
201
|
+
'action', 'update',
|
|
202
|
+
'conflict', false
|
|
203
|
+
);
|
|
204
|
+
ELSE
|
|
205
|
+
-- Version conflict detected
|
|
206
|
+
INSERT INTO sync_conflicts (
|
|
207
|
+
thread_id, user_id, local_version, remote_version
|
|
208
|
+
) VALUES (
|
|
209
|
+
p_id, p_user_id,
|
|
210
|
+
(SELECT to_jsonb(t.*) FROM threads t WHERE t.id = p_id),
|
|
211
|
+
jsonb_build_object(
|
|
212
|
+
'id', p_id,
|
|
213
|
+
'agent_id', p_agent_id,
|
|
214
|
+
'device_id', p_device_id,
|
|
215
|
+
'project_path', p_project_path,
|
|
216
|
+
'messages', p_messages,
|
|
217
|
+
'status', p_status,
|
|
218
|
+
'last_modified', p_last_modified,
|
|
219
|
+
'version', p_version,
|
|
220
|
+
'is_deleted', p_is_deleted
|
|
221
|
+
)
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
result := jsonb_build_object(
|
|
225
|
+
'success', false,
|
|
226
|
+
'action', 'none',
|
|
227
|
+
'conflict', true,
|
|
228
|
+
'message', 'Version conflict detected. Manual resolution required.'
|
|
229
|
+
);
|
|
230
|
+
END IF;
|
|
231
|
+
|
|
232
|
+
RETURN result;
|
|
233
|
+
END;
|
|
234
|
+
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/** @type {import('tailwindcss').Config} */
|
|
2
|
+
module.exports = {
|
|
3
|
+
darkMode: ["class"],
|
|
4
|
+
content: [
|
|
5
|
+
'./index.html',
|
|
6
|
+
'./src/renderer/**/*.{js,ts,jsx,tsx}',
|
|
7
|
+
],
|
|
8
|
+
theme: {
|
|
9
|
+
container: {
|
|
10
|
+
center: true,
|
|
11
|
+
padding: "2rem",
|
|
12
|
+
screens: {
|
|
13
|
+
"2xl": "1400px",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
extend: {
|
|
17
|
+
colors: {
|
|
18
|
+
border: "hsl(var(--border))",
|
|
19
|
+
input: "hsl(var(--input))",
|
|
20
|
+
ring: "hsl(var(--ring))",
|
|
21
|
+
background: "hsl(var(--background))",
|
|
22
|
+
foreground: "hsl(var(--foreground))",
|
|
23
|
+
primary: {
|
|
24
|
+
DEFAULT: "hsl(var(--primary))",
|
|
25
|
+
foreground: "hsl(var(--primary-foreground))",
|
|
26
|
+
},
|
|
27
|
+
secondary: {
|
|
28
|
+
DEFAULT: "hsl(var(--secondary))",
|
|
29
|
+
foreground: "hsl(var(--secondary-foreground))",
|
|
30
|
+
},
|
|
31
|
+
destructive: {
|
|
32
|
+
DEFAULT: "hsl(var(--destructive))",
|
|
33
|
+
foreground: "hsl(var(--destructive-foreground))",
|
|
34
|
+
},
|
|
35
|
+
muted: {
|
|
36
|
+
DEFAULT: "hsl(var(--muted))",
|
|
37
|
+
foreground: "hsl(var(--muted-foreground))",
|
|
38
|
+
},
|
|
39
|
+
accent: {
|
|
40
|
+
DEFAULT: "hsl(var(--accent))",
|
|
41
|
+
foreground: "hsl(var(--accent-foreground))",
|
|
42
|
+
},
|
|
43
|
+
popover: {
|
|
44
|
+
DEFAULT: "hsl(var(--popover))",
|
|
45
|
+
foreground: "hsl(var(--popover-foreground))",
|
|
46
|
+
},
|
|
47
|
+
card: {
|
|
48
|
+
DEFAULT: "hsl(var(--card))",
|
|
49
|
+
foreground: "hsl(var(--card-foreground))",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
borderRadius: {
|
|
53
|
+
lg: "var(--radius)",
|
|
54
|
+
md: "calc(var(--radius) - 2px)",
|
|
55
|
+
sm: "calc(var(--radius) - 4px)",
|
|
56
|
+
},
|
|
57
|
+
fontFamily: {
|
|
58
|
+
sans: ['Inter', 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'],
|
|
59
|
+
mono: ['JetBrains Mono', 'Fira Code', 'Menlo', 'Monaco', 'Consolas', 'monospace'],
|
|
60
|
+
},
|
|
61
|
+
keyframes: {
|
|
62
|
+
"accordion-down": {
|
|
63
|
+
from: { height: "0" },
|
|
64
|
+
to: { height: "var(--radix-accordion-content-height)" },
|
|
65
|
+
},
|
|
66
|
+
"accordion-up": {
|
|
67
|
+
from: { height: "var(--radix-accordion-content-height)" },
|
|
68
|
+
to: { height: "0" },
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
animation: {
|
|
72
|
+
"accordion-down": "accordion-down 0.2s ease-out",
|
|
73
|
+
"accordion-up": "accordion-up 0.2s ease-out",
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
plugins: [require("tailwindcss-animate")],
|
|
78
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codex-linux/e2e",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "playwright test",
|
|
7
|
+
"test:ui": "playwright test --ui",
|
|
8
|
+
"test:debug": "playwright test --debug",
|
|
9
|
+
"report": "playwright show-report"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@playwright/test": "^1.40.0",
|
|
13
|
+
"@types/node": "^20.10.0"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
testDir: './specs',
|
|
5
|
+
fullyParallel: true,
|
|
6
|
+
forbidOnly: !!process.env.CI,
|
|
7
|
+
retries: process.env.CI ? 2 : 0,
|
|
8
|
+
workers: process.env.CI ? 1 : undefined,
|
|
9
|
+
reporter: 'html',
|
|
10
|
+
use: {
|
|
11
|
+
baseURL: 'http://localhost:3000',
|
|
12
|
+
trace: 'on-first-retry',
|
|
13
|
+
screenshot: 'only-on-failure',
|
|
14
|
+
video: 'retain-on-failure',
|
|
15
|
+
},
|
|
16
|
+
projects: [
|
|
17
|
+
{
|
|
18
|
+
name: 'chromium',
|
|
19
|
+
use: { ...devices['Desktop Chrome'] },
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: 'firefox',
|
|
23
|
+
use: { ...devices['Desktop Firefox'] },
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
webServer: {
|
|
27
|
+
command: 'cd ../.. && npm run dev',
|
|
28
|
+
url: 'http://localhost:3000',
|
|
29
|
+
reuseExistingServer: !process.env.CI,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { test, expect, type Page } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
test.describe('Codex Linux E2E Tests', () => {
|
|
4
|
+
|
|
5
|
+
test.beforeEach(async ({ page }) => {
|
|
6
|
+
await page.goto('/');
|
|
7
|
+
await page.waitForLoadState('networkidle');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
describe('Application Launch', () => {
|
|
11
|
+
test('should display loading screen', async ({ page }) => {
|
|
12
|
+
await expect(page.locator('text=Loading')).toBeVisible({ timeout: 10000 });
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('should load main interface within timeout', async ({ page }) => {
|
|
16
|
+
await expect(page.locator('nav, aside, [class*="sidebar"]')).toBeVisible({ timeout: 30000 });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('should have correct window title', async ({ page }) => {
|
|
20
|
+
await expect(page).toHaveTitle(/Codex/i, { timeout: 10000 });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('should show sidebar navigation', async ({ page }) => {
|
|
24
|
+
await expect(page.locator('text=Agents')).toBeVisible({ timeout: 30000 });
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe('Navigation', () => {
|
|
29
|
+
test.beforeEach(async ({ page }) => {
|
|
30
|
+
await page.waitForSelector('text=Agents', { timeout: 30000 });
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('should navigate to all main sections', async ({ page }) => {
|
|
34
|
+
const sections = ['Agents', 'Worktrees', 'Skills', 'Settings'];
|
|
35
|
+
|
|
36
|
+
for (const section of sections) {
|
|
37
|
+
await expect(page.locator(`text=${section}`)).toBeVisible();
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('should navigate using keyboard shortcuts', async ({ page }) => {
|
|
42
|
+
await page.keyboard.press('Alt+1');
|
|
43
|
+
await expect(page.locator('[class*="agent"]')).toBeVisible({ timeout: 5000 });
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('Agent Management', () => {
|
|
48
|
+
test.beforeEach(async ({ page }) => {
|
|
49
|
+
await page.goto('/');
|
|
50
|
+
await page.waitForSelector('text=Agents', { timeout: 30000 });
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('should open create agent modal', async ({ page }) => {
|
|
54
|
+
const createButton = page.locator('[data-testid="create-agent-button"], button:has-text("Create")').first();
|
|
55
|
+
if (await createButton.isVisible()) {
|
|
56
|
+
await createButton.click();
|
|
57
|
+
await expect(page.locator('text=Create New Agent, text=New Agent')).toBeVisible({ timeout: 5000 });
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('should display agent list', async ({ page }) => {
|
|
62
|
+
await page.waitForTimeout(2000);
|
|
63
|
+
const agentCards = page.locator('[class*="card"], [class*="agent"]');
|
|
64
|
+
const count = await agentCards.count();
|
|
65
|
+
expect(count).toBeGreaterThanOrEqual(0);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('should select an agent', async ({ page }) => {
|
|
69
|
+
await page.waitForTimeout(2000);
|
|
70
|
+
const firstAgent = page.locator('[class*="card"], [class*="agent"]').first();
|
|
71
|
+
if (await firstAgent.isVisible()) {
|
|
72
|
+
await firstAgent.click();
|
|
73
|
+
await page.waitForTimeout(1000);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('Chat Interface', () => {
|
|
79
|
+
test.beforeEach(async ({ page }) => {
|
|
80
|
+
await page.goto('/');
|
|
81
|
+
await page.waitForSelector('text=Agents', { timeout: 30000 });
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('should display chat input', async ({ page }) => {
|
|
85
|
+
await page.waitForTimeout(2000);
|
|
86
|
+
const chatInput = page.locator('input[type="text"], textarea, [data-testid="chat-input"]').first();
|
|
87
|
+
await expect(chatInput).toBeVisible({ timeout: 5000 });
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('should type and send message', async ({ page }) => {
|
|
91
|
+
await page.waitForTimeout(2000);
|
|
92
|
+
const chatInput = page.locator('input[type="text"], textarea, [data-testid="chat-input"]').first();
|
|
93
|
+
|
|
94
|
+
if (await chatInput.isVisible()) {
|
|
95
|
+
await chatInput.fill('test message');
|
|
96
|
+
await expect(chatInput).toHaveValue('test message');
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('Settings', () => {
|
|
102
|
+
test.beforeEach(async ({ page }) => {
|
|
103
|
+
await page.goto('/');
|
|
104
|
+
await page.waitForSelector('text=Settings', { timeout: 30000 });
|
|
105
|
+
await page.click('text=Settings');
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test('should display settings page', async ({ page }) => {
|
|
109
|
+
await expect(page.locator('text=Settings, h1:has-text("Settings")')).toBeVisible({ timeout: 5000 });
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test('should have general settings', async ({ page }) => {
|
|
113
|
+
await expect(page.locator('text=General, text=AI')).toBeVisible({ timeout: 5000 });
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe('Accessibility', () => {
|
|
118
|
+
test('should have proper heading structure', async ({ page }) => {
|
|
119
|
+
await page.goto('/');
|
|
120
|
+
await page.waitForSelector('text=Agents', { timeout: 30000 });
|
|
121
|
+
|
|
122
|
+
const h1 = page.locator('h1');
|
|
123
|
+
const count = await h1.count();
|
|
124
|
+
expect(count).toBeGreaterThanOrEqual(0);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test('should have focusable elements', async ({ page }) => {
|
|
128
|
+
await page.goto('/');
|
|
129
|
+
await page.waitForSelector('text=Agents', { timeout: 30000 });
|
|
130
|
+
|
|
131
|
+
const buttons = page.locator('button');
|
|
132
|
+
const count = await buttons.count();
|
|
133
|
+
expect(count).toBeGreaterThan(0);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('should support keyboard navigation', async ({ page }) => {
|
|
137
|
+
await page.goto('/');
|
|
138
|
+
await page.waitForSelector('text=Agents', { timeout: 30000 });
|
|
139
|
+
|
|
140
|
+
await page.keyboard.press('Tab');
|
|
141
|
+
const focusedElement = await page.locator(':focus').first();
|
|
142
|
+
await expect(focusedElement).toBeVisible();
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
describe('Error Handling', () => {
|
|
147
|
+
test('should handle network errors gracefully', async ({ page }) => {
|
|
148
|
+
await page.route('**/api/**', route => route.abort('failed'));
|
|
149
|
+
await page.goto('/');
|
|
150
|
+
await page.waitForTimeout(3000);
|
|
151
|
+
|
|
152
|
+
const content = await page.content();
|
|
153
|
+
expect(content.length).toBeGreaterThan(0);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe('Responsive Design', () => {
|
|
158
|
+
test('should work at different viewport sizes', async ({ page }) => {
|
|
159
|
+
await page.setViewportSize({ width: 1920, height: 1080 });
|
|
160
|
+
await page.goto('/');
|
|
161
|
+
await expect(page.locator('text=Agents')).toBeVisible({ timeout: 30000 });
|
|
162
|
+
|
|
163
|
+
await page.setViewportSize({ width: 768, height: 1024 });
|
|
164
|
+
await page.reload();
|
|
165
|
+
await expect(page.locator('text=Agents')).toBeVisible({ timeout: 30000 });
|
|
166
|
+
|
|
167
|
+
await page.setViewportSize({ width: 375, height: 667 });
|
|
168
|
+
await page.reload();
|
|
169
|
+
await page.waitForTimeout(2000);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('Performance', () => {
|
|
174
|
+
test('should load within acceptable time', async ({ page }) => {
|
|
175
|
+
const startTime = Date.now();
|
|
176
|
+
await page.goto('/');
|
|
177
|
+
await page.waitForSelector('text=Agents', { timeout: 30000 });
|
|
178
|
+
const loadTime = Date.now() - startTime;
|
|
179
|
+
|
|
180
|
+
console.log(`Page load time: ${loadTime}ms`);
|
|
181
|
+
expect(loadTime).toBeLessThan(30000);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test('should not have memory leaks on navigation', async ({ page }) => {
|
|
185
|
+
await page.goto('/');
|
|
186
|
+
await page.waitForSelector('text=Agents', { timeout: 30000 });
|
|
187
|
+
|
|
188
|
+
for (let i = 0; i < 3; i++) {
|
|
189
|
+
await page.reload();
|
|
190
|
+
await page.waitForSelector('text=Agents', { timeout: 30000 });
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
});
|
package/tests/setup.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Test setup and utilities
|
|
2
|
+
|
|
3
|
+
// Mock electron modules
|
|
4
|
+
jest.mock('electron', () => ({
|
|
5
|
+
app: {
|
|
6
|
+
getPath: () => '/tmp/test',
|
|
7
|
+
on: () => {},
|
|
8
|
+
whenReady: () => Promise.resolve(),
|
|
9
|
+
},
|
|
10
|
+
BrowserWindow: () => {},
|
|
11
|
+
ipcMain: {
|
|
12
|
+
handle: () => {},
|
|
13
|
+
on: () => {},
|
|
14
|
+
},
|
|
15
|
+
dialog: {
|
|
16
|
+
showOpenDialog: () => Promise.resolve({ filePaths: [] }),
|
|
17
|
+
showSaveDialog: () => Promise.resolve({ filePath: '' }),
|
|
18
|
+
},
|
|
19
|
+
shell: {
|
|
20
|
+
openExternal: () => Promise.resolve(),
|
|
21
|
+
openPath: () => Promise.resolve(''),
|
|
22
|
+
},
|
|
23
|
+
Notification: () => {},
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
jest.mock('electron-log', () => ({
|
|
27
|
+
info: () => {},
|
|
28
|
+
error: () => {},
|
|
29
|
+
warn: () => {},
|
|
30
|
+
debug: () => {},
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
jest.mock('electron-store', () => {
|
|
34
|
+
return () => ({
|
|
35
|
+
get: () => {},
|
|
36
|
+
set: () => {},
|
|
37
|
+
clear: () => {},
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Global test utilities
|
|
42
|
+
(global as any).testUtils = {
|
|
43
|
+
createMockAgent: (overrides = {}) => ({
|
|
44
|
+
id: 'test-agent-1',
|
|
45
|
+
name: 'Test Agent',
|
|
46
|
+
status: 'idle',
|
|
47
|
+
projectPath: '/tmp/test-project',
|
|
48
|
+
worktreeName: 'test-worktree',
|
|
49
|
+
providerId: 'openai',
|
|
50
|
+
model: 'gpt-4o',
|
|
51
|
+
skills: [],
|
|
52
|
+
createdAt: new Date(),
|
|
53
|
+
updatedAt: new Date(),
|
|
54
|
+
lastActiveAt: null,
|
|
55
|
+
messages: [],
|
|
56
|
+
tasks: [],
|
|
57
|
+
metadata: {},
|
|
58
|
+
...overrides,
|
|
59
|
+
}),
|
|
60
|
+
|
|
61
|
+
createMockWorktree: (overrides = {}) => ({
|
|
62
|
+
name: 'test-worktree',
|
|
63
|
+
path: '/tmp/test-project/.codex/worktrees/test-worktree',
|
|
64
|
+
commit: 'abc123',
|
|
65
|
+
branch: 'codex/test-agent-1',
|
|
66
|
+
isMain: false,
|
|
67
|
+
agents: [],
|
|
68
|
+
createdAt: new Date(),
|
|
69
|
+
...overrides,
|
|
70
|
+
}),
|
|
71
|
+
|
|
72
|
+
createMockSkill: (overrides = {}) => ({
|
|
73
|
+
id: 'test-skill-1',
|
|
74
|
+
name: 'Test Skill',
|
|
75
|
+
description: 'A test skill',
|
|
76
|
+
version: '1.0.0',
|
|
77
|
+
author: 'Test Author',
|
|
78
|
+
tags: ['test'],
|
|
79
|
+
files: [],
|
|
80
|
+
config: {
|
|
81
|
+
entryPoint: 'index.md',
|
|
82
|
+
parameters: [],
|
|
83
|
+
dependencies: [],
|
|
84
|
+
permissions: [],
|
|
85
|
+
},
|
|
86
|
+
createdAt: new Date(),
|
|
87
|
+
updatedAt: new Date(),
|
|
88
|
+
...overrides,
|
|
89
|
+
}),
|
|
90
|
+
|
|
91
|
+
wait: (ms: number) => new Promise(resolve => setTimeout(resolve, ms)),
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Console suppression for cleaner test output
|
|
95
|
+
if (process.env.SUPPRESS_CONSOLE) {
|
|
96
|
+
console.log = () => {};
|
|
97
|
+
console.error = () => {};
|
|
98
|
+
console.warn = () => {};
|
|
99
|
+
}
|