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.
Files changed (367) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/.eslintrc.json +27 -0
  3. package/.github/workflows/ci.yml +156 -0
  4. package/.huskyrc +7 -0
  5. package/.lintstagedrc +13 -0
  6. package/.prettierrc +12 -0
  7. package/CLAUDE.md +163 -0
  8. package/DESIGN_SUPERIOR.md +73 -0
  9. package/Dockerfile +64 -0
  10. package/INSTALLATION.md +152 -0
  11. package/LICENSE +21 -0
  12. package/README.md +245 -0
  13. package/assets/skills/code-review/instructions.md +102 -0
  14. package/assets/skills/code-review/skill.yaml +15 -0
  15. package/assets/skills/refactoring/instructions.md +149 -0
  16. package/assets/skills/refactoring/skill.yaml +15 -0
  17. package/assets/skills/testing/skill.yaml +15 -0
  18. package/commitlint.config.js +23 -0
  19. package/dist/main/DatabaseManager.js +763 -0
  20. package/dist/main/DatabaseManager.js.map +1 -0
  21. package/dist/main/SettingsManager.js +61 -0
  22. package/dist/main/SettingsManager.js.map +1 -0
  23. package/dist/main/agents/AgentOrchestrator.js +787 -0
  24. package/dist/main/agents/AgentOrchestrator.js.map +1 -0
  25. package/dist/main/agents/AgentSDK.js +219 -0
  26. package/dist/main/agents/AgentSDK.js.map +1 -0
  27. package/dist/main/agents/AgentTools.js +348 -0
  28. package/dist/main/agents/AgentTools.js.map +1 -0
  29. package/dist/main/agents/CodeIndex.js +233 -0
  30. package/dist/main/agents/CodeIndex.js.map +1 -0
  31. package/dist/main/agents/EmbeddingService.js +80 -0
  32. package/dist/main/agents/EmbeddingService.js.map +1 -0
  33. package/dist/main/agents/NativeToolCalling.js +206 -0
  34. package/dist/main/agents/NativeToolCalling.js.map +1 -0
  35. package/dist/main/api/APIServer.js +278 -0
  36. package/dist/main/api/APIServer.js.map +1 -0
  37. package/dist/main/api/RateLimiter.js +138 -0
  38. package/dist/main/api/RateLimiter.js.map +1 -0
  39. package/dist/main/api/WebSocketManager.js +300 -0
  40. package/dist/main/api/WebSocketManager.js.map +1 -0
  41. package/dist/main/assistant/ContextOptimizer.js +192 -0
  42. package/dist/main/assistant/ContextOptimizer.js.map +1 -0
  43. package/dist/main/assistant/PredictedOutputManager.js +172 -0
  44. package/dist/main/assistant/PredictedOutputManager.js.map +1 -0
  45. package/dist/main/assistant/PromptCacheManager.js +193 -0
  46. package/dist/main/assistant/PromptCacheManager.js.map +1 -0
  47. package/dist/main/assistant/PromptOptimizer.js +626 -0
  48. package/dist/main/assistant/PromptOptimizer.js.map +1 -0
  49. package/dist/main/assistant/SmartCodeAssistant.js +224 -0
  50. package/dist/main/assistant/SmartCodeAssistant.js.map +1 -0
  51. package/dist/main/auth/SessionManager.js +300 -0
  52. package/dist/main/auth/SessionManager.js.map +1 -0
  53. package/dist/main/automations/AdvancedWebhookSystem.js +212 -0
  54. package/dist/main/automations/AdvancedWebhookSystem.js.map +1 -0
  55. package/dist/main/automations/AutomationScheduler.js +269 -0
  56. package/dist/main/automations/AutomationScheduler.js.map +1 -0
  57. package/dist/main/automations/BatchProcessingSystem.js +159 -0
  58. package/dist/main/automations/BatchProcessingSystem.js.map +1 -0
  59. package/dist/main/automations/BrowserAutomationManager.js +195 -0
  60. package/dist/main/automations/BrowserAutomationManager.js.map +1 -0
  61. package/dist/main/automations/GitHubActionsManager.js +129 -0
  62. package/dist/main/automations/GitHubActionsManager.js.map +1 -0
  63. package/dist/main/automations/GitLabCIManager.js +122 -0
  64. package/dist/main/automations/GitLabCIManager.js.map +1 -0
  65. package/dist/main/automations/PriorityQueueManager.js +240 -0
  66. package/dist/main/automations/PriorityQueueManager.js.map +1 -0
  67. package/dist/main/background/BackgroundModeManager.js +117 -0
  68. package/dist/main/background/BackgroundModeManager.js.map +1 -0
  69. package/dist/main/backup/BackupManager.js +254 -0
  70. package/dist/main/backup/BackupManager.js.map +1 -0
  71. package/dist/main/backup/MigrationManager.js +114 -0
  72. package/dist/main/backup/MigrationManager.js.map +1 -0
  73. package/dist/main/commands/SlashCommandManager.js +399 -0
  74. package/dist/main/commands/SlashCommandManager.js.map +1 -0
  75. package/dist/main/config/ClaudeMdParser.js +519 -0
  76. package/dist/main/config/ClaudeMdParser.js.map +1 -0
  77. package/dist/main/config/CustomizationManager.js +381 -0
  78. package/dist/main/config/CustomizationManager.js.map +1 -0
  79. package/dist/main/config/LaunchConfigManager.js +211 -0
  80. package/dist/main/config/LaunchConfigManager.js.map +1 -0
  81. package/dist/main/config/SettingsManager.js +166 -0
  82. package/dist/main/config/SettingsManager.js.map +1 -0
  83. package/dist/main/connectors/ConnectorManager.js +151 -0
  84. package/dist/main/connectors/ConnectorManager.js.map +1 -0
  85. package/dist/main/connectors/DatabaseConnector.js +222 -0
  86. package/dist/main/connectors/DatabaseConnector.js.map +1 -0
  87. package/dist/main/cowork/CoworkManager.js +324 -0
  88. package/dist/main/cowork/CoworkManager.js.map +1 -0
  89. package/dist/main/evals/AgentEvalFramework.js +538 -0
  90. package/dist/main/evals/AgentEvalFramework.js.map +1 -0
  91. package/dist/main/evals/GraderManager.js +285 -0
  92. package/dist/main/evals/GraderManager.js.map +1 -0
  93. package/dist/main/git/GitWorktreeManager.js +214 -0
  94. package/dist/main/git/GitWorktreeManager.js.map +1 -0
  95. package/dist/main/github/GitHubPRMonitor.js +244 -0
  96. package/dist/main/github/GitHubPRMonitor.js.map +1 -0
  97. package/dist/main/ide/ContinueInManager.js +181 -0
  98. package/dist/main/ide/ContinueInManager.js.map +1 -0
  99. package/dist/main/ide/IDEIntegration.js +277 -0
  100. package/dist/main/ide/IDEIntegration.js.map +1 -0
  101. package/dist/main/integrations/LinearManager.js +252 -0
  102. package/dist/main/integrations/LinearManager.js.map +1 -0
  103. package/dist/main/integrations/SlackBotManager.js +247 -0
  104. package/dist/main/integrations/SlackBotManager.js.map +1 -0
  105. package/dist/main/lsp/LSPManager.js +394 -0
  106. package/dist/main/lsp/LSPManager.js.map +1 -0
  107. package/dist/main/main.js +1087 -0
  108. package/dist/main/main.js.map +1 -0
  109. package/dist/main/mcp/MCPConfigurationManager.js +281 -0
  110. package/dist/main/mcp/MCPConfigurationManager.js.map +1 -0
  111. package/dist/main/mcp/MCPManager.js +710 -0
  112. package/dist/main/mcp/MCPManager.js.map +1 -0
  113. package/dist/main/mcp/MCPRegistry.js +272 -0
  114. package/dist/main/mcp/MCPRegistry.js.map +1 -0
  115. package/dist/main/monitoring/ErrorRecoveryManager.js +268 -0
  116. package/dist/main/monitoring/ErrorRecoveryManager.js.map +1 -0
  117. package/dist/main/monitoring/ErrorTracker.js +57 -0
  118. package/dist/main/monitoring/ErrorTracker.js.map +1 -0
  119. package/dist/main/monitoring/MetricsCollector.js +155 -0
  120. package/dist/main/monitoring/MetricsCollector.js.map +1 -0
  121. package/dist/main/monitoring/TraceGradingSystem.js +148 -0
  122. package/dist/main/monitoring/TraceGradingSystem.js.map +1 -0
  123. package/dist/main/notifications/NotificationManager.js +67 -0
  124. package/dist/main/notifications/NotificationManager.js.map +1 -0
  125. package/dist/main/pair/AIPairProgramming.js +200 -0
  126. package/dist/main/pair/AIPairProgramming.js.map +1 -0
  127. package/dist/main/plugins/PluginManager.js +222 -0
  128. package/dist/main/plugins/PluginManager.js.map +1 -0
  129. package/dist/main/plugins/PluginMarketplace.js +237 -0
  130. package/dist/main/plugins/PluginMarketplace.js.map +1 -0
  131. package/dist/main/preload.js +189 -0
  132. package/dist/main/preload.js.map +1 -0
  133. package/dist/main/preview/PreviewSessionManager.js +170 -0
  134. package/dist/main/preview/PreviewSessionManager.js.map +1 -0
  135. package/dist/main/providers/AIProviderManager.js +327 -0
  136. package/dist/main/providers/AIProviderManager.js.map +1 -0
  137. package/dist/main/providers/FineTuningManager.js +276 -0
  138. package/dist/main/providers/FineTuningManager.js.map +1 -0
  139. package/dist/main/providers/FreeModelsProvider.js +1104 -0
  140. package/dist/main/providers/FreeModelsProvider.js.map +1 -0
  141. package/dist/main/realtime/RealtimeManager.js +116 -0
  142. package/dist/main/realtime/RealtimeManager.js.map +1 -0
  143. package/dist/main/remote/CloudEnvironmentManager.js +232 -0
  144. package/dist/main/remote/CloudEnvironmentManager.js.map +1 -0
  145. package/dist/main/remote/RemoteSessionManager.js +255 -0
  146. package/dist/main/remote/RemoteSessionManager.js.map +1 -0
  147. package/dist/main/search/DeepResearchManager.js +335 -0
  148. package/dist/main/search/DeepResearchManager.js.map +1 -0
  149. package/dist/main/search/WebSearchIntegration.js +147 -0
  150. package/dist/main/search/WebSearchIntegration.js.map +1 -0
  151. package/dist/main/security/AdminConsoleManager.js +223 -0
  152. package/dist/main/security/AdminConsoleManager.js.map +1 -0
  153. package/dist/main/security/AuditLogger.js +136 -0
  154. package/dist/main/security/AuditLogger.js.map +1 -0
  155. package/dist/main/security/PermissionManager.js +144 -0
  156. package/dist/main/security/PermissionManager.js.map +1 -0
  157. package/dist/main/security/SSOManager.js +173 -0
  158. package/dist/main/security/SSOManager.js.map +1 -0
  159. package/dist/main/security/SecurityManager.js +152 -0
  160. package/dist/main/security/SecurityManager.js.map +1 -0
  161. package/dist/main/skills/SkillsManager.js +223 -0
  162. package/dist/main/skills/SkillsManager.js.map +1 -0
  163. package/dist/main/ssh/SSHManager.js +65 -0
  164. package/dist/main/ssh/SSHManager.js.map +1 -0
  165. package/dist/main/streaming/StreamingManager.js +225 -0
  166. package/dist/main/streaming/StreamingManager.js.map +1 -0
  167. package/dist/main/sync/CloudSyncManager.js +422 -0
  168. package/dist/main/sync/CloudSyncManager.js.map +1 -0
  169. package/dist/main/types.js +28 -0
  170. package/dist/main/types.js.map +1 -0
  171. package/dist/main/verification/AutoVerifyManager.js +235 -0
  172. package/dist/main/verification/AutoVerifyManager.js.map +1 -0
  173. package/dist/main/vision/ComputerUseManager.js +376 -0
  174. package/dist/main/vision/ComputerUseManager.js.map +1 -0
  175. package/dist/main/vision/ImageVideoGenerationManager.js +401 -0
  176. package/dist/main/vision/ImageVideoGenerationManager.js.map +1 -0
  177. package/dist/main/vision/VisionManager.js +172 -0
  178. package/dist/main/vision/VisionManager.js.map +1 -0
  179. package/dist/renderer/assets/main-DJlZQBCA.js +304 -0
  180. package/dist/renderer/assets/main-N33ZXEr8.css +1 -0
  181. package/dist/renderer/index.html +21 -0
  182. package/dist/renderer/manifest.json +42 -0
  183. package/dist/renderer/sw.ts +109 -0
  184. package/dist/shared/types.js +35 -0
  185. package/dist/shared/types.js.map +1 -0
  186. package/docker-compose.yml +65 -0
  187. package/docs/API.md +307 -0
  188. package/docs/USER_GUIDE.md +476 -0
  189. package/examples/plugins/sample-plugin/package.json +41 -0
  190. package/examples/plugins/sample-plugin/src/index.ts +75 -0
  191. package/index.html +20 -0
  192. package/jest.config.js +39 -0
  193. package/package.json +180 -0
  194. package/packages/cli/package.json +29 -0
  195. package/packages/cli/src/commands/agents.ts +199 -0
  196. package/packages/cli/src/commands/tasks.ts +61 -0
  197. package/packages/cli/src/index.ts +91 -0
  198. package/packages/cli/src/utils/api.ts +45 -0
  199. package/packages/cli/src/utils/config.ts +61 -0
  200. package/packages/npm-installer/bin/codex-linux +126 -0
  201. package/packages/npm-installer/lib/download.js +273 -0
  202. package/packages/npm-installer/package.json +42 -0
  203. package/packages/vscode-extension/package.json +167 -0
  204. package/packages/vscode-extension/src/api.ts +68 -0
  205. package/packages/vscode-extension/src/extension.ts +161 -0
  206. package/packages/vscode-extension/src/panels/chatPanel.ts +265 -0
  207. package/packages/vscode-extension/src/panels/createAgentPanel.ts +227 -0
  208. package/packages/vscode-extension/src/providers/agentsProvider.ts +80 -0
  209. package/postcss.config.js +6 -0
  210. package/public/manifest.json +42 -0
  211. package/public/sw.ts +109 -0
  212. package/scripts/install-dev.sh +103 -0
  213. package/scripts/install.sh +275 -0
  214. package/src/main/DatabaseManager.ts +950 -0
  215. package/src/main/SettingsManager.ts +63 -0
  216. package/src/main/agents/AgentOrchestrator.ts +930 -0
  217. package/src/main/agents/AgentSDK.ts +269 -0
  218. package/src/main/agents/AgentTools.ts +380 -0
  219. package/src/main/agents/CodeIndex.ts +240 -0
  220. package/src/main/agents/EmbeddingService.ts +88 -0
  221. package/src/main/agents/NativeToolCalling.ts +245 -0
  222. package/src/main/api/APIServer.ts +316 -0
  223. package/src/main/api/RateLimiter.ts +165 -0
  224. package/src/main/api/WebSocketManager.ts +398 -0
  225. package/src/main/assistant/ContextOptimizer.ts +214 -0
  226. package/src/main/assistant/PredictedOutputManager.ts +265 -0
  227. package/src/main/assistant/PromptCacheManager.ts +280 -0
  228. package/src/main/assistant/PromptOptimizer.ts +746 -0
  229. package/src/main/assistant/SmartCodeAssistant.ts +234 -0
  230. package/src/main/auth/SessionManager.ts +415 -0
  231. package/src/main/automations/AdvancedWebhookSystem.ts +281 -0
  232. package/src/main/automations/AutomationScheduler.ts +272 -0
  233. package/src/main/automations/BatchProcessingSystem.ts +207 -0
  234. package/src/main/automations/BrowserAutomationManager.ts +203 -0
  235. package/src/main/automations/GitHubActionsManager.ts +151 -0
  236. package/src/main/automations/GitLabCIManager.ts +206 -0
  237. package/src/main/automations/PriorityQueueManager.ts +328 -0
  238. package/src/main/background/BackgroundModeManager.ts +130 -0
  239. package/src/main/backup/BackupManager.ts +287 -0
  240. package/src/main/backup/MigrationManager.ts +132 -0
  241. package/src/main/commands/SlashCommandManager.ts +407 -0
  242. package/src/main/config/ClaudeMdParser.ts +539 -0
  243. package/src/main/config/CustomizationManager.ts +493 -0
  244. package/src/main/config/LaunchConfigManager.ts +212 -0
  245. package/src/main/config/SettingsManager.ts +163 -0
  246. package/src/main/connectors/ConnectorManager.ts +175 -0
  247. package/src/main/connectors/DatabaseConnector.ts +212 -0
  248. package/src/main/cowork/CoworkManager.ts +431 -0
  249. package/src/main/evals/AgentEvalFramework.ts +665 -0
  250. package/src/main/evals/GraderManager.ts +417 -0
  251. package/src/main/git/GitWorktreeManager.ts +211 -0
  252. package/src/main/github/GitHubPRMonitor.ts +317 -0
  253. package/src/main/ide/ContinueInManager.ts +180 -0
  254. package/src/main/ide/IDEIntegration.ts +288 -0
  255. package/src/main/integrations/LinearManager.ts +327 -0
  256. package/src/main/integrations/SlackBotManager.ts +312 -0
  257. package/src/main/lsp/LSPManager.ts +445 -0
  258. package/src/main/main.ts +1221 -0
  259. package/src/main/mcp/MCPConfigurationManager.ts +281 -0
  260. package/src/main/mcp/MCPManager.ts +799 -0
  261. package/src/main/mcp/MCPRegistry.ts +273 -0
  262. package/src/main/monitoring/ErrorRecoveryManager.ts +359 -0
  263. package/src/main/monitoring/ErrorTracker.ts +60 -0
  264. package/src/main/monitoring/MetricsCollector.ts +196 -0
  265. package/src/main/monitoring/TraceGradingSystem.ts +196 -0
  266. package/src/main/notifications/NotificationManager.ts +96 -0
  267. package/src/main/pair/AIPairProgramming.ts +290 -0
  268. package/src/main/plugins/PluginManager.ts +266 -0
  269. package/src/main/plugins/PluginMarketplace.ts +318 -0
  270. package/src/main/preload.ts +215 -0
  271. package/src/main/preview/PreviewSessionManager.ts +186 -0
  272. package/src/main/providers/AIProviderManager.ts +394 -0
  273. package/src/main/providers/FineTuningManager.ts +390 -0
  274. package/src/main/providers/FreeModelsProvider.ts +1156 -0
  275. package/src/main/realtime/RealtimeManager.ts +147 -0
  276. package/src/main/remote/CloudEnvironmentManager.ts +253 -0
  277. package/src/main/remote/RemoteSessionManager.ts +323 -0
  278. package/src/main/search/DeepResearchManager.ts +458 -0
  279. package/src/main/search/WebSearchIntegration.ts +203 -0
  280. package/src/main/security/AdminConsoleManager.ts +244 -0
  281. package/src/main/security/AuditLogger.ts +143 -0
  282. package/src/main/security/PermissionManager.ts +184 -0
  283. package/src/main/security/SSOManager.ts +241 -0
  284. package/src/main/security/SecurityManager.ts +139 -0
  285. package/src/main/skills/SkillsManager.ts +218 -0
  286. package/src/main/ssh/SSHManager.ts +86 -0
  287. package/src/main/streaming/StreamingManager.ts +306 -0
  288. package/src/main/sync/CloudSyncManager.ts +532 -0
  289. package/src/main/verification/AutoVerifyManager.ts +285 -0
  290. package/src/main/vision/ComputerUseManager.ts +475 -0
  291. package/src/main/vision/ImageVideoGenerationManager.ts +526 -0
  292. package/src/main/vision/VisionManager.ts +186 -0
  293. package/src/renderer/App.tsx +314 -0
  294. package/src/renderer/components/AdvancedSettingsPanel.tsx +225 -0
  295. package/src/renderer/components/AgentPanel.tsx +760 -0
  296. package/src/renderer/components/AppPreview.tsx +220 -0
  297. package/src/renderer/components/AuditTrailPanel.tsx +148 -0
  298. package/src/renderer/components/AutomationPanel.tsx +220 -0
  299. package/src/renderer/components/ChatInterface.tsx +595 -0
  300. package/src/renderer/components/ChatTab.tsx +296 -0
  301. package/src/renderer/components/CodeEditor.tsx +257 -0
  302. package/src/renderer/components/CodeReviewPanel.tsx +256 -0
  303. package/src/renderer/components/CodeWorkspace.tsx +192 -0
  304. package/src/renderer/components/CodebaseDashboard.tsx +295 -0
  305. package/src/renderer/components/ComputerUsePanel.tsx +262 -0
  306. package/src/renderer/components/ConnectorsPanel.tsx +471 -0
  307. package/src/renderer/components/ContextMenu.tsx +155 -0
  308. package/src/renderer/components/ContextUsageDisplay.tsx +248 -0
  309. package/src/renderer/components/CoworkPanel.tsx +415 -0
  310. package/src/renderer/components/DiffViewer.tsx +452 -0
  311. package/src/renderer/components/ErrorBoundary.tsx +273 -0
  312. package/src/renderer/components/ExtendedThinkingToggle.tsx +244 -0
  313. package/src/renderer/components/FileAttachments.tsx +247 -0
  314. package/src/renderer/components/FileExplorer.tsx +242 -0
  315. package/src/renderer/components/FileExplorerPanel.tsx +302 -0
  316. package/src/renderer/components/GitPanel.tsx +154 -0
  317. package/src/renderer/components/Header.tsx +113 -0
  318. package/src/renderer/components/MCPPanel.tsx +326 -0
  319. package/src/renderer/components/MentionAutocomplete.tsx +239 -0
  320. package/src/renderer/components/PermissionPanel.tsx +159 -0
  321. package/src/renderer/components/PermissionSelector.tsx +203 -0
  322. package/src/renderer/components/PluginMarketplace.tsx +325 -0
  323. package/src/renderer/components/PromptOptimizerPanel.tsx +399 -0
  324. package/src/renderer/components/SearchPanel.tsx +173 -0
  325. package/src/renderer/components/SearchReplace.tsx +284 -0
  326. package/src/renderer/components/SessionSidebar.tsx +367 -0
  327. package/src/renderer/components/SettingsPanel.tsx +426 -0
  328. package/src/renderer/components/Sidebar.tsx +100 -0
  329. package/src/renderer/components/SkillsPanel.tsx +245 -0
  330. package/src/renderer/components/SplitPane.tsx +173 -0
  331. package/src/renderer/components/Terminal.tsx +190 -0
  332. package/src/renderer/components/VoiceCommand.tsx +129 -0
  333. package/src/renderer/components/WorktreePanel.tsx +163 -0
  334. package/src/renderer/components/ui/AriaComponents.tsx +193 -0
  335. package/src/renderer/components/ui/Button.tsx +68 -0
  336. package/src/renderer/components/ui/Card.tsx +102 -0
  337. package/src/renderer/components/ui/Input.tsx +44 -0
  338. package/src/renderer/components/ui/Skeleton.tsx +55 -0
  339. package/src/renderer/components/ui/VirtualList.tsx +196 -0
  340. package/src/renderer/i18n/I18nProvider.tsx +101 -0
  341. package/src/renderer/i18n/de.ts +161 -0
  342. package/src/renderer/i18n/en.ts +163 -0
  343. package/src/renderer/i18n/es.ts +161 -0
  344. package/src/renderer/i18n/fr.ts +161 -0
  345. package/src/renderer/i18n/index.ts +44 -0
  346. package/src/renderer/index.css +129 -0
  347. package/src/renderer/lib/accessibility.tsx +287 -0
  348. package/src/renderer/lib/hooks.ts +304 -0
  349. package/src/renderer/lib/utils.ts +6 -0
  350. package/src/renderer/main.tsx +25 -0
  351. package/src/renderer/styles/minimalist.css +539 -0
  352. package/src/renderer/sw.ts +180 -0
  353. package/src/renderer/types.d.ts +138 -0
  354. package/src/shared/types.ts +813 -0
  355. package/supabase/schema.sql +234 -0
  356. package/tailwind.config.js +78 -0
  357. package/tests/e2e/package.json +15 -0
  358. package/tests/e2e/playwright.config.ts +31 -0
  359. package/tests/e2e/specs/app.spec.ts +194 -0
  360. package/tests/setup.ts +99 -0
  361. package/tests/unit/AgentOrchestrator.test.ts +274 -0
  362. package/tests/unit/DatabaseManager.test.ts +262 -0
  363. package/tests/unit/GitWorktreeManager.test.ts +150 -0
  364. package/tests/unit/SecurityManager.test.ts +110 -0
  365. package/tsconfig.main.json +22 -0
  366. package/tsconfig.renderer.json +27 -0
  367. package/vite.config.ts +28 -0
@@ -0,0 +1,284 @@
1
+ import React, { useState, useCallback, useEffect } from 'react';
2
+ import { Search, Replace, ChevronDown, ChevronUp, X, FileText } from 'lucide-react';
3
+ import { debounce } from 'lodash';
4
+
5
+ interface SearchReplaceProps {
6
+ rootPath: string;
7
+ onClose: () => void;
8
+ }
9
+
10
+ interface SearchMatch {
11
+ file: string;
12
+ line: number;
13
+ column: number;
14
+ content: string;
15
+ }
16
+
17
+ export const SearchReplace: React.FC<SearchReplaceProps> = ({
18
+ rootPath,
19
+ onClose,
20
+ }) => {
21
+ const [searchQuery, setSearchQuery] = useState('');
22
+ const [replaceQuery, setReplaceQuery] = useState('');
23
+ const [isRegex, setIsRegex] = useState(false);
24
+ const [caseSensitive, setCaseSensitive] = useState(false);
25
+ const [wholeWord, setWholeWord] = useState(false);
26
+ const [filePattern, setFilePattern] = useState('*');
27
+ const [matches, setMatches] = useState<SearchMatch[]>([]);
28
+ const [isSearching, setIsSearching] = useState(false);
29
+ const [currentMatchIndex, setCurrentMatchIndex] = useState(0);
30
+ const [showReplace, setShowReplace] = useState(false);
31
+ const [includeIgnored, setIncludeIgnored] = useState(false);
32
+
33
+ const performSearch = useCallback(
34
+ debounce(async (query: string) => {
35
+ if (!query.trim()) {
36
+ setMatches([]);
37
+ return;
38
+ }
39
+
40
+ setIsSearching(true);
41
+ try {
42
+ const results = await window.electronAPI.search.files({
43
+ query,
44
+ path: rootPath,
45
+ pattern: filePattern !== '*' ? filePattern : undefined,
46
+ });
47
+
48
+ const allMatches: SearchMatch[] = [];
49
+ results.forEach((result: any) => {
50
+ result.matches.forEach((match: any) => {
51
+ allMatches.push({
52
+ file: result.path,
53
+ line: match.line,
54
+ column: match.content.indexOf(query) + 1,
55
+ content: match.content,
56
+ });
57
+ });
58
+ });
59
+
60
+ setMatches(allMatches);
61
+ setCurrentMatchIndex(0);
62
+ } catch (error) {
63
+ console.error('Search failed:', error);
64
+ }
65
+ setIsSearching(false);
66
+ }, 300),
67
+ [rootPath, filePattern]
68
+ );
69
+
70
+ useEffect(() => {
71
+ performSearch(searchQuery);
72
+ }, [searchQuery, performSearch]);
73
+
74
+ const handleReplace = async () => {
75
+ if (!replaceQuery.trim() || matches.length === 0) return;
76
+
77
+ let replaced = 0;
78
+ for (const match of matches) {
79
+ try {
80
+ const content = await window.electronAPI.fs.readFile(match.file);
81
+ const lines = content.split('\n');
82
+
83
+ if (lines[match.line - 1]) {
84
+ const searchRegex = isRegex
85
+ ? new RegExp(searchQuery, caseSensitive ? 'g' : 'gi')
86
+ : new RegExp(
87
+ searchQuery.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'),
88
+ caseSensitive ? 'g' : 'gi'
89
+ );
90
+
91
+ lines[match.line - 1] = lines[match.line - 1].replace(
92
+ searchRegex,
93
+ replaceQuery
94
+ );
95
+
96
+ await window.electronAPI.fs.writeFile(match.file, lines.join('\n'));
97
+ replaced++;
98
+ }
99
+ } catch (error) {
100
+ console.error(`Failed to replace in ${match.file}:`, error);
101
+ }
102
+ }
103
+
104
+ // Refresh search
105
+ performSearch(searchQuery);
106
+ };
107
+
108
+ const navigateMatch = (direction: 'prev' | 'next') => {
109
+ if (matches.length === 0) return;
110
+
111
+ if (direction === 'next') {
112
+ setCurrentMatchIndex((prev) => (prev + 1) % matches.length);
113
+ } else {
114
+ setCurrentMatchIndex((prev) => (prev - 1 + matches.length) % matches.length);
115
+ }
116
+ };
117
+
118
+ const highlightMatch = (content: string, query: string) => {
119
+ if (!query) return content;
120
+
121
+ const parts = content.split(new RegExp(`(${query})`, caseSensitive ? 'g' : 'gi'));
122
+ return parts.map((part, i) =>
123
+ part.toLowerCase() === query.toLowerCase() ? (
124
+ <mark key={i} className="bg-yellow-500/30 text-yellow-900 dark:text-yellow-100">
125
+ {part}
126
+ </mark>
127
+ ) : (
128
+ part
129
+ )
130
+ );
131
+ };
132
+
133
+ return (
134
+ <div className="flex flex-col h-full bg-card border-l border-border">
135
+ {/* Header */}
136
+ <div className="flex items-center justify-between p-4 border-b border-border">
137
+ <h2 className="font-semibold">
138
+ {showReplace ? 'Search & Replace' : 'Search'}
139
+ </h2>
140
+ <button onClick={onClose} className="p-1 hover:bg-muted rounded">
141
+ <X className="w-4 h-4" />
142
+ </button>
143
+ </div>
144
+
145
+ {/* Search Input */}
146
+ <div className="p-4 space-y-3">
147
+ <div className="relative">
148
+ <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
149
+ <input
150
+ type="text"
151
+ value={searchQuery}
152
+ onChange={(e) => setSearchQuery(e.target.value)}
153
+ placeholder="Search..."
154
+ className="w-full pl-10 pr-4 py-2 bg-background border border-input rounded-md"
155
+ autoFocus
156
+ />
157
+ </div>
158
+
159
+ {/* Replace Input */}
160
+ {showReplace && (
161
+ <div className="relative">
162
+ <Replace className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
163
+ <input
164
+ type="text"
165
+ value={replaceQuery}
166
+ onChange={(e) => setReplaceQuery(e.target.value)}
167
+ placeholder="Replace..."
168
+ className="w-full pl-10 pr-4 py-2 bg-background border border-input rounded-md"
169
+ />
170
+ </div>
171
+ )}
172
+
173
+ {/* Options */}
174
+ <div className="flex flex-wrap gap-2">
175
+ <button
176
+ onClick={() => setIsRegex(!isRegex)}
177
+ className={`px-2 py-1 text-xs rounded ${
178
+ isRegex ? 'bg-primary text-primary-foreground' : 'bg-muted'
179
+ }`}
180
+ >
181
+ .*
182
+ </button>
183
+ <button
184
+ onClick={() => setCaseSensitive(!caseSensitive)}
185
+ className={`px-2 py-1 text-xs rounded ${
186
+ caseSensitive ? 'bg-primary text-primary-foreground' : 'bg-muted'
187
+ }`}
188
+ >
189
+ Aa
190
+ </button>
191
+ <button
192
+ onClick={() => setWholeWord(!wholeWord)}
193
+ className={`px-2 py-1 text-xs rounded ${
194
+ wholeWord ? 'bg-primary text-primary-foreground' : 'bg-muted'
195
+ }`}
196
+ >
197
+ ""
198
+ </button>
199
+ <button
200
+ onClick={() => setShowReplace(!showReplace)}
201
+ className="px-2 py-1 text-xs rounded bg-muted hover:bg-muted/80"
202
+ >
203
+ {showReplace ? 'Hide Replace' : 'Show Replace'}
204
+ </button>
205
+ </div>
206
+
207
+ {/* File Pattern */}
208
+ <input
209
+ type="text"
210
+ value={filePattern}
211
+ onChange={(e) => setFilePattern(e.target.value)}
212
+ placeholder="Files to include (e.g., *.ts)"
213
+ className="w-full px-3 py-2 bg-background border border-input rounded-md text-sm"
214
+ />
215
+
216
+ {/* Replace Actions */}
217
+ {showReplace && matches.length > 0 && (
218
+ <div className="flex gap-2">
219
+ <button
220
+ onClick={handleReplace}
221
+ className="flex-1 px-4 py-2 bg-primary text-primary-foreground rounded-md text-sm hover:bg-primary/90"
222
+ >
223
+ Replace All ({matches.length})
224
+ </button>
225
+ </div>
226
+ )}
227
+ </div>
228
+
229
+ {/* Results */}
230
+ <div className="flex-1 overflow-auto">
231
+ {isSearching ? (
232
+ <div className="flex items-center justify-center py-8 text-muted-foreground">
233
+ Searching...
234
+ </div>
235
+ ) : matches.length > 0 ? (
236
+ <div>
237
+ <div className="px-4 py-2 text-xs text-muted-foreground border-b border-border flex items-center justify-between">
238
+ <span>{matches.length} results</span>
239
+ <div className="flex items-center gap-1">
240
+ <button
241
+ onClick={() => navigateMatch('prev')}
242
+ className="p-1 hover:bg-muted rounded"
243
+ >
244
+ <ChevronUp className="w-3 h-3" />
245
+ </button>
246
+ <span>{currentMatchIndex + 1}</span>
247
+ <button
248
+ onClick={() => navigateMatch('next')}
249
+ className="p-1 hover:bg-muted rounded"
250
+ >
251
+ <ChevronDown className="w-3 h-3" />
252
+ </button>
253
+ </div>
254
+ </div>
255
+
256
+ {matches.map((match, index) => (
257
+ <div
258
+ key={`${match.file}-${match.line}`}
259
+ className={`px-4 py-2 border-b border-border cursor-pointer ${
260
+ index === currentMatchIndex ? 'bg-primary/10' : 'hover:bg-muted/50'
261
+ }`}
262
+ onClick={() => setCurrentMatchIndex(index)}
263
+ >
264
+ <div className="flex items-center gap-2 text-xs text-muted-foreground mb-1">
265
+ <FileText className="w-3 h-3" />
266
+ <span className="truncate">{match.file.replace(rootPath, '')}</span>
267
+ <span>:{match.line}</span>
268
+ </div>
269
+ <code className="text-xs font-mono block truncate">
270
+ {highlightMatch(match.content, searchQuery)}
271
+ </code>
272
+ </div>
273
+ ))}
274
+ </div>
275
+ ) : searchQuery ? (
276
+ <div className="flex flex-col items-center justify-center py-8 text-muted-foreground">
277
+ <Search className="w-8 h-8 mb-2 opacity-30" />
278
+ <p className="text-sm">No results</p>
279
+ </div>
280
+ ) : null}
281
+ </div>
282
+ </div>
283
+ );
284
+ };
@@ -0,0 +1,367 @@
1
+ import React, { useState } from 'react';
2
+ import {
3
+ Plus,
4
+ MoreHorizontal,
5
+ Cloud,
6
+ CloudOff,
7
+ Terminal,
8
+ Filter,
9
+ Archive,
10
+ Clock,
11
+ CheckCircle,
12
+ XCircle,
13
+ AlertCircle,
14
+ Loader2,
15
+ GitBranch,
16
+ Circle,
17
+ Pencil,
18
+ X,
19
+ Check
20
+ } from 'lucide-react';
21
+
22
+ export type SessionStatus = 'active' | 'archived' | 'running';
23
+ export type SessionEnvironment = 'local' | 'cloud' | 'ssh';
24
+
25
+ export interface Session {
26
+ id: string;
27
+ name: string;
28
+ projectPath: string;
29
+ environment: SessionEnvironment;
30
+ status: SessionStatus;
31
+ model?: string;
32
+ lastActivity: Date;
33
+ createdAt: Date;
34
+ branch?: string;
35
+ prMonitored?: number;
36
+ isLoading?: boolean;
37
+ ciStatus?: 'pending' | 'running' | 'success' | 'failure';
38
+ }
39
+
40
+ interface SessionSidebarProps {
41
+ sessions: Session[];
42
+ activeSessionId?: string;
43
+ onSessionSelect: (sessionId: string) => void;
44
+ onSessionNew: () => void;
45
+ onSessionArchive?: (sessionId: string) => void;
46
+ onSessionDelete?: (sessionId: string) => void;
47
+ onSessionRename?: (sessionId: string, newName: string) => void;
48
+ }
49
+
50
+ function cn(...inputs: (string | undefined | null | boolean)[]): string {
51
+ return inputs.filter(Boolean).join(' ');
52
+ }
53
+
54
+ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
55
+ sessions,
56
+ activeSessionId,
57
+ onSessionSelect,
58
+ onSessionNew,
59
+ onSessionArchive,
60
+ onSessionDelete,
61
+ onSessionRename
62
+ }) => {
63
+ const [filter, setFilter] = useState<'all' | 'active' | 'archived'>('all');
64
+ const [envFilter, setEnvFilter] = useState<'all' | 'local' | 'cloud' | 'ssh'>('all');
65
+ const [contextMenu, setContextMenu] = useState<string | null>(null);
66
+ const [renamingSession, setRenamingSession] = useState<string | null>(null);
67
+ const [newName, setNewName] = useState('');
68
+
69
+ const filteredSessions = sessions.filter(session => {
70
+ if (filter === 'active' && session.status !== 'active') return false;
71
+ if (filter === 'archived' && session.status !== 'archived') return false;
72
+ if (envFilter !== 'all' && session.environment !== envFilter) return false;
73
+ return true;
74
+ });
75
+
76
+ const getStatusIcon = (session: Session) => {
77
+ if (session.isLoading) {
78
+ return <Loader2 className="w-4 h-4 animate-spin text-blue-500" />;
79
+ }
80
+ switch (session.status) {
81
+ case 'active':
82
+ return <Circle className="w-4 h-4 fill-green-500 text-green-500" />;
83
+ case 'archived':
84
+ return <Archive className="w-4 h-4 text-muted-foreground" />;
85
+ default:
86
+ return <Clock className="w-4 h-4 text-muted-foreground" />;
87
+ }
88
+ };
89
+
90
+ const getEnvIcon = (env: SessionEnvironment) => {
91
+ switch (env) {
92
+ case 'cloud':
93
+ return <Cloud className="w-3.5 h-3.5 text-blue-500" />;
94
+ case 'ssh':
95
+ return <Terminal className="w-3.5 h-3.5 text-purple-500" />;
96
+ default:
97
+ return <CloudOff className="w-3.5 h-3.5 text-muted-foreground" />;
98
+ }
99
+ };
100
+
101
+ const getCIStatusIcon = (status?: Session['ciStatus']) => {
102
+ switch (status) {
103
+ case 'success':
104
+ return <CheckCircle className="w-3 h-3 text-green-500" />;
105
+ case 'failure':
106
+ return <XCircle className="w-3 h-3 text-red-500" />;
107
+ case 'running':
108
+ return <Loader2 className="w-3 h-3 text-blue-500 animate-spin" />;
109
+ case 'pending':
110
+ return <AlertCircle className="w-3 h-3 text-yellow-500" />;
111
+ default:
112
+ return null;
113
+ }
114
+ };
115
+
116
+ const formatTimeAgo = (date: Date) => {
117
+ const now = new Date();
118
+ const diff = now.getTime() - date.getTime();
119
+ const minutes = Math.floor(diff / 60000);
120
+ const hours = Math.floor(diff / 3600000);
121
+ const days = Math.floor(diff / 86400000);
122
+
123
+ if (minutes < 1) return 'Just now';
124
+ if (minutes < 60) return `${minutes}m ago`;
125
+ if (hours < 24) return `${hours}h ago`;
126
+ return `${days}d ago`;
127
+ };
128
+
129
+ return (
130
+ <div className="flex flex-col h-full bg-card border-r border-border w-72">
131
+ <div className="px-4 py-3 border-b border-border">
132
+ <div className="flex items-center justify-between mb-3">
133
+ <h3 className="font-semibold">Sessions</h3>
134
+ <button
135
+ onClick={onSessionNew}
136
+ className="p-1.5 hover:bg-muted rounded-md transition-colors"
137
+ title="New session"
138
+ >
139
+ <Plus className="w-4 h-4" />
140
+ </button>
141
+ </div>
142
+
143
+ <div className="flex items-center gap-2">
144
+ <div className="flex items-center gap-1 bg-muted rounded-md p-0.5">
145
+ <button
146
+ onClick={() => setFilter('all')}
147
+ className={cn(
148
+ 'px-2 py-1 text-xs rounded',
149
+ filter === 'all' ? 'bg-background shadow-sm' : 'text-muted-foreground'
150
+ )}
151
+ >
152
+ All
153
+ </button>
154
+ <button
155
+ onClick={() => setFilter('active')}
156
+ className={cn(
157
+ 'px-2 py-1 text-xs rounded',
158
+ filter === 'active' ? 'bg-background shadow-sm' : 'text-muted-foreground'
159
+ )}
160
+ >
161
+ Active
162
+ </button>
163
+ <button
164
+ onClick={() => setFilter('archived')}
165
+ className={cn(
166
+ 'px-2 py-1 text-xs rounded',
167
+ filter === 'archived' ? 'bg-background shadow-sm' : 'text-muted-foreground'
168
+ )}
169
+ >
170
+ Archived
171
+ </button>
172
+ </div>
173
+ </div>
174
+
175
+ <div className="flex items-center gap-1 mt-2">
176
+ <Filter className="w-3 h-3 text-muted-foreground" />
177
+ <select
178
+ value={envFilter}
179
+ onChange={(e) => setEnvFilter(e.target.value as typeof envFilter)}
180
+ className="text-xs bg-muted border-0 rounded px-2 py-1"
181
+ >
182
+ <option value="all">All environments</option>
183
+ <option value="local">Local</option>
184
+ <option value="cloud">Cloud</option>
185
+ <option value="ssh">SSH</option>
186
+ </select>
187
+ </div>
188
+ </div>
189
+
190
+ <div className="flex-1 overflow-y-auto">
191
+ {filteredSessions.length === 0 ? (
192
+ <div className="flex flex-col items-center justify-center h-full text-muted-foreground p-4">
193
+ <p className="text-sm">No sessions found</p>
194
+ <button
195
+ onClick={onSessionNew}
196
+ className="mt-2 text-sm text-primary hover:underline"
197
+ >
198
+ Create a new session
199
+ </button>
200
+ </div>
201
+ ) : (
202
+ <div className="p-2 space-y-1">
203
+ {filteredSessions.map((session) => (
204
+ <div
205
+ key={session.id}
206
+ onClick={() => onSessionSelect(session.id)}
207
+ className={cn(
208
+ 'group relative p-3 rounded-lg cursor-pointer transition-all',
209
+ activeSessionId === session.id
210
+ ? 'bg-primary/10 border border-primary/30'
211
+ : 'hover:bg-muted border border-transparent'
212
+ )}
213
+ >
214
+ {session.ciStatus && (
215
+ <div className="absolute top-2 right-2">
216
+ {getCIStatusIcon(session.ciStatus)}
217
+ </div>
218
+ )}
219
+
220
+ <div className="flex items-start gap-2">
221
+ {getStatusIcon(session)}
222
+
223
+ <div className="flex-1 min-w-0">
224
+ <div className="flex items-center gap-2">
225
+ {renamingSession === session.id ? (
226
+ <div className="flex items-center gap-1 flex-1">
227
+ <input
228
+ type="text"
229
+ value={newName}
230
+ onChange={(e) => setNewName(e.target.value)}
231
+ onKeyDown={(e) => {
232
+ if (e.key === 'Enter') {
233
+ onSessionRename?.(session.id, newName);
234
+ setRenamingSession(null);
235
+ }
236
+ if (e.key === 'Escape') {
237
+ setRenamingSession(null);
238
+ }
239
+ }}
240
+ onClick={(e) => e.stopPropagation()}
241
+ className="flex-1 px-2 py-0.5 text-sm bg-background border border-input rounded"
242
+ autoFocus
243
+ />
244
+ <button
245
+ onClick={(e) => {
246
+ e.stopPropagation();
247
+ onSessionRename?.(session.id, newName);
248
+ setRenamingSession(null);
249
+ }}
250
+ className="p-1 hover:bg-muted rounded"
251
+ >
252
+ <Check className="w-3 h-3 text-green-500" />
253
+ </button>
254
+ <button
255
+ onClick={(e) => {
256
+ e.stopPropagation();
257
+ setRenamingSession(null);
258
+ }}
259
+ className="p-1 hover:bg-muted rounded"
260
+ >
261
+ <X className="w-3 h-3" />
262
+ </button>
263
+ </div>
264
+ ) : (
265
+ <>
266
+ <span className="font-medium text-sm truncate">
267
+ {session.name}
268
+ </span>
269
+ {getEnvIcon(session.environment)}
270
+ </>
271
+ )}
272
+ </div>
273
+
274
+ <div className="flex items-center gap-2 mt-1 text-xs text-muted-foreground">
275
+ {session.branch && (
276
+ <span className="flex items-center gap-0.5 truncate max-w-[120px]">
277
+ <GitBranch className="w-3 h-3" />
278
+ {session.branch}
279
+ </span>
280
+ )}
281
+ {session.prMonitored !== undefined && session.prMonitored > 0 && (
282
+ <span className="text-blue-500">
283
+ #{session.prMonitored}
284
+ </span>
285
+ )}
286
+ </div>
287
+
288
+ <div className="flex items-center gap-2 mt-1 text-xs text-muted-foreground">
289
+ <span>{formatTimeAgo(session.lastActivity)}</span>
290
+ {session.model && (
291
+ <>
292
+ <span>•</span>
293
+ <span>{session.model}</span>
294
+ </>
295
+ )}
296
+ </div>
297
+ </div>
298
+
299
+ <button
300
+ onClick={(e) => {
301
+ e.stopPropagation();
302
+ setContextMenu(contextMenu === session.id ? null : session.id);
303
+ }}
304
+ className="p-1 opacity-0 group-hover:opacity-100 hover:bg-muted rounded transition-all"
305
+ >
306
+ <MoreHorizontal className="w-4 h-4" />
307
+ </button>
308
+ </div>
309
+
310
+ {contextMenu === session.id && (
311
+ <div className="absolute right-2 top-10 z-10 bg-background border border-border rounded-md shadow-lg py-1 min-w-[140px]">
312
+ {session.status !== 'archived' && onSessionArchive && (
313
+ <button
314
+ onClick={(e) => {
315
+ e.stopPropagation();
316
+ onSessionArchive(session.id);
317
+ setContextMenu(null);
318
+ }}
319
+ className="w-full px-3 py-1.5 text-left text-sm hover:bg-muted flex items-center gap-2"
320
+ >
321
+ <Archive className="w-4 h-4" />
322
+ Archive
323
+ </button>
324
+ )}
325
+ {onSessionDelete && (
326
+ <button
327
+ onClick={(e) => {
328
+ e.stopPropagation();
329
+ onSessionDelete(session.id);
330
+ setContextMenu(null);
331
+ }}
332
+ className="w-full px-3 py-1.5 text-left text-sm hover:bg-muted flex items-center gap-2 text-red-500"
333
+ >
334
+ <XCircle className="w-4 h-4" />
335
+ Delete
336
+ </button>
337
+ )}
338
+ {onSessionRename && (
339
+ <button
340
+ onClick={(e) => {
341
+ e.stopPropagation();
342
+ setRenamingSession(session.id);
343
+ setNewName(session.name);
344
+ setContextMenu(null);
345
+ }}
346
+ className="w-full px-3 py-1.5 text-left text-sm hover:bg-muted flex items-center gap-2"
347
+ >
348
+ <Pencil className="w-4 h-4" />
349
+ Rename
350
+ </button>
351
+ )}
352
+ </div>
353
+ )}
354
+ </div>
355
+ ))}
356
+ </div>
357
+ )}
358
+ </div>
359
+
360
+ <div className="px-4 py-2 border-t border-border text-xs text-muted-foreground">
361
+ {filteredSessions.length} session{filteredSessions.length !== 1 ? 's' : ''}
362
+ </div>
363
+ </div>
364
+ );
365
+ };
366
+
367
+ export default SessionSidebar;