@myrialabs/clopen 0.0.1
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/.env.example +6 -0
- package/.github/workflows/release.yml +60 -0
- package/.github/workflows/test.yml +40 -0
- package/CONTRIBUTING.md +499 -0
- package/LICENSE +21 -0
- package/README.md +209 -0
- package/backend/index.ts +156 -0
- package/backend/lib/chat/helpers.ts +42 -0
- package/backend/lib/chat/index.ts +2 -0
- package/backend/lib/chat/stream-manager.ts +1126 -0
- package/backend/lib/database/README.md +77 -0
- package/backend/lib/database/index.ts +119 -0
- package/backend/lib/database/migrations/001_create_projects_table.ts +31 -0
- package/backend/lib/database/migrations/002_create_chat_sessions_table.ts +33 -0
- package/backend/lib/database/migrations/003_create_messages_table.ts +32 -0
- package/backend/lib/database/migrations/004_create_prompt_templates_table.ts +34 -0
- package/backend/lib/database/migrations/005_create_settings_table.ts +24 -0
- package/backend/lib/database/migrations/006_add_user_to_messages.ts +58 -0
- package/backend/lib/database/migrations/007_create_stream_states_table.ts +41 -0
- package/backend/lib/database/migrations/008_create_message_snapshots_table.ts +62 -0
- package/backend/lib/database/migrations/009_add_delta_snapshot_fields.ts +41 -0
- package/backend/lib/database/migrations/010_add_soft_delete_and_branch_support.ts +70 -0
- package/backend/lib/database/migrations/011_git_like_commit_graph.ts +156 -0
- package/backend/lib/database/migrations/012_add_file_change_statistics.ts +41 -0
- package/backend/lib/database/migrations/013_checkpoint_tree_state.ts +118 -0
- package/backend/lib/database/migrations/014_add_engine_to_sessions.ts +18 -0
- package/backend/lib/database/migrations/015_add_model_to_sessions.ts +18 -0
- package/backend/lib/database/migrations/016_create_user_projects_table.ts +34 -0
- package/backend/lib/database/migrations/017_add_current_session_to_user_projects.ts +32 -0
- package/backend/lib/database/migrations/018_create_claude_accounts_table.ts +24 -0
- package/backend/lib/database/migrations/019_add_claude_account_to_sessions.ts +18 -0
- package/backend/lib/database/migrations/020_add_snapshot_tree_hash.ts +32 -0
- package/backend/lib/database/migrations/021_drop_prompt_templates_table.ts +33 -0
- package/backend/lib/database/migrations/index.ts +154 -0
- package/backend/lib/database/queries/checkpoint-queries.ts +87 -0
- package/backend/lib/database/queries/engine-queries.ts +75 -0
- package/backend/lib/database/queries/index.ts +9 -0
- package/backend/lib/database/queries/message-queries.ts +472 -0
- package/backend/lib/database/queries/project-queries.ts +117 -0
- package/backend/lib/database/queries/session-queries.ts +271 -0
- package/backend/lib/database/queries/settings-queries.ts +34 -0
- package/backend/lib/database/queries/snapshot-queries.ts +326 -0
- package/backend/lib/database/queries/utils-queries.ts +59 -0
- package/backend/lib/database/seeders/index.ts +13 -0
- package/backend/lib/database/seeders/settings_seeder.ts +84 -0
- package/backend/lib/database/utils/connection.ts +174 -0
- package/backend/lib/database/utils/index.ts +4 -0
- package/backend/lib/database/utils/migration-runner.ts +118 -0
- package/backend/lib/database/utils/seeder-runner.ts +121 -0
- package/backend/lib/engine/adapters/claude/environment.ts +164 -0
- package/backend/lib/engine/adapters/claude/error-handler.ts +60 -0
- package/backend/lib/engine/adapters/claude/index.ts +1 -0
- package/backend/lib/engine/adapters/claude/path-utils.ts +38 -0
- package/backend/lib/engine/adapters/claude/stream.ts +177 -0
- package/backend/lib/engine/adapters/opencode/index.ts +2 -0
- package/backend/lib/engine/adapters/opencode/message-converter.ts +862 -0
- package/backend/lib/engine/adapters/opencode/server.ts +104 -0
- package/backend/lib/engine/adapters/opencode/stream.ts +755 -0
- package/backend/lib/engine/index.ts +196 -0
- package/backend/lib/engine/types.ts +58 -0
- package/backend/lib/files/file-operations.ts +478 -0
- package/backend/lib/files/file-reading.ts +308 -0
- package/backend/lib/files/file-watcher.ts +383 -0
- package/backend/lib/files/path-browsing.ts +382 -0
- package/backend/lib/git/git-executor.ts +88 -0
- package/backend/lib/git/git-parser.ts +411 -0
- package/backend/lib/git/git-service.ts +505 -0
- package/backend/lib/mcp/README.md +1144 -0
- package/backend/lib/mcp/config.ts +316 -0
- package/backend/lib/mcp/index.ts +35 -0
- package/backend/lib/mcp/project-context.ts +236 -0
- package/backend/lib/mcp/servers/browser-automation/actions.ts +156 -0
- package/backend/lib/mcp/servers/browser-automation/browser.ts +419 -0
- package/backend/lib/mcp/servers/browser-automation/index.ts +791 -0
- package/backend/lib/mcp/servers/browser-automation/inspection.ts +501 -0
- package/backend/lib/mcp/servers/helper.ts +143 -0
- package/backend/lib/mcp/servers/index.ts +45 -0
- package/backend/lib/mcp/servers/weather/get-temperature.ts +56 -0
- package/backend/lib/mcp/servers/weather/index.ts +31 -0
- package/backend/lib/mcp/stdio-server.ts +103 -0
- package/backend/lib/mcp/types.ts +65 -0
- package/backend/lib/preview/browser/browser-audio-capture.ts +86 -0
- package/backend/lib/preview/browser/browser-console-manager.ts +263 -0
- package/backend/lib/preview/browser/browser-dialog-handler.ts +222 -0
- package/backend/lib/preview/browser/browser-interaction-handler.ts +421 -0
- package/backend/lib/preview/browser/browser-mcp-control.ts +415 -0
- package/backend/lib/preview/browser/browser-native-ui-handler.ts +512 -0
- package/backend/lib/preview/browser/browser-navigation-tracker.ts +104 -0
- package/backend/lib/preview/browser/browser-pool.ts +357 -0
- package/backend/lib/preview/browser/browser-preview-service.ts +882 -0
- package/backend/lib/preview/browser/browser-tab-manager.ts +935 -0
- package/backend/lib/preview/browser/browser-video-capture.ts +695 -0
- package/backend/lib/preview/browser/scripts/audio-stream.ts +292 -0
- package/backend/lib/preview/browser/scripts/cursor-tracking.ts +85 -0
- package/backend/lib/preview/browser/scripts/video-stream.ts +438 -0
- package/backend/lib/preview/browser/types.ts +359 -0
- package/backend/lib/preview/index.ts +24 -0
- package/backend/lib/project/index.ts +2 -0
- package/backend/lib/project/status-manager.ts +182 -0
- package/backend/lib/shared/index.ts +2 -0
- package/backend/lib/shared/port-utils.ts +25 -0
- package/backend/lib/shared/process-manager.ts +281 -0
- package/backend/lib/snapshot/blob-store.ts +227 -0
- package/backend/lib/snapshot/gitignore.ts +307 -0
- package/backend/lib/snapshot/helpers.ts +397 -0
- package/backend/lib/snapshot/snapshot-service.ts +483 -0
- package/backend/lib/terminal/helpers.ts +14 -0
- package/backend/lib/terminal/index.ts +8 -0
- package/backend/lib/terminal/pty-manager.ts +4 -0
- package/backend/lib/terminal/pty-session-manager.ts +387 -0
- package/backend/lib/terminal/shell-utils.ts +313 -0
- package/backend/lib/terminal/stream-manager.ts +293 -0
- package/backend/lib/tunnel/global-tunnel-manager.ts +243 -0
- package/backend/lib/tunnel/project-tunnel-manager.ts +311 -0
- package/backend/lib/user/helpers.ts +87 -0
- package/backend/lib/utils/ws.ts +944 -0
- package/backend/lib/vite-dev.ts +353 -0
- package/backend/middleware/cors.ts +15 -0
- package/backend/middleware/error-handler.ts +49 -0
- package/backend/middleware/logger.ts +9 -0
- package/backend/types/api.ts +24 -0
- package/backend/ws/README.md +1505 -0
- package/backend/ws/chat/background.ts +198 -0
- package/backend/ws/chat/index.ts +21 -0
- package/backend/ws/chat/stream.ts +707 -0
- package/backend/ws/engine/claude/accounts.ts +401 -0
- package/backend/ws/engine/claude/index.ts +13 -0
- package/backend/ws/engine/claude/status.ts +43 -0
- package/backend/ws/engine/index.ts +14 -0
- package/backend/ws/engine/opencode/index.ts +11 -0
- package/backend/ws/engine/opencode/status.ts +30 -0
- package/backend/ws/engine/utils.ts +36 -0
- package/backend/ws/files/index.ts +30 -0
- package/backend/ws/files/read.ts +189 -0
- package/backend/ws/files/search.ts +453 -0
- package/backend/ws/files/watch.ts +124 -0
- package/backend/ws/files/write.ts +143 -0
- package/backend/ws/git/branch.ts +106 -0
- package/backend/ws/git/commit.ts +39 -0
- package/backend/ws/git/conflict.ts +68 -0
- package/backend/ws/git/diff.ts +69 -0
- package/backend/ws/git/index.ts +24 -0
- package/backend/ws/git/log.ts +41 -0
- package/backend/ws/git/remote.ts +214 -0
- package/backend/ws/git/staging.ts +84 -0
- package/backend/ws/git/status.ts +90 -0
- package/backend/ws/index.ts +69 -0
- package/backend/ws/mcp/index.ts +61 -0
- package/backend/ws/messages/crud.ts +74 -0
- package/backend/ws/messages/index.ts +14 -0
- package/backend/ws/preview/browser/cleanup.ts +129 -0
- package/backend/ws/preview/browser/console.ts +114 -0
- package/backend/ws/preview/browser/interact.ts +513 -0
- package/backend/ws/preview/browser/mcp.ts +129 -0
- package/backend/ws/preview/browser/native-ui.ts +235 -0
- package/backend/ws/preview/browser/stats.ts +55 -0
- package/backend/ws/preview/browser/tab-info.ts +126 -0
- package/backend/ws/preview/browser/tab.ts +166 -0
- package/backend/ws/preview/browser/webcodecs.ts +293 -0
- package/backend/ws/preview/index.ts +146 -0
- package/backend/ws/projects/crud.ts +113 -0
- package/backend/ws/projects/index.ts +25 -0
- package/backend/ws/projects/presence.ts +46 -0
- package/backend/ws/projects/status.ts +116 -0
- package/backend/ws/sessions/crud.ts +327 -0
- package/backend/ws/sessions/index.ts +33 -0
- package/backend/ws/settings/crud.ts +112 -0
- package/backend/ws/settings/index.ts +14 -0
- package/backend/ws/snapshot/index.ts +17 -0
- package/backend/ws/snapshot/restore.ts +173 -0
- package/backend/ws/snapshot/timeline.ts +141 -0
- package/backend/ws/system/index.ts +14 -0
- package/backend/ws/system/operations.ts +49 -0
- package/backend/ws/terminal/index.ts +40 -0
- package/backend/ws/terminal/persistence.ts +153 -0
- package/backend/ws/terminal/session.ts +382 -0
- package/backend/ws/terminal/stream.ts +79 -0
- package/backend/ws/tunnel/index.ts +14 -0
- package/backend/ws/tunnel/operations.ts +91 -0
- package/backend/ws/types.ts +20 -0
- package/backend/ws/user/crud.ts +156 -0
- package/backend/ws/user/index.ts +14 -0
- package/bin/clopen.ts +307 -0
- package/bun.lock +1352 -0
- package/frontend/App.svelte +34 -0
- package/frontend/app.css +313 -0
- package/frontend/lib/app-environment.ts +10 -0
- package/frontend/lib/components/chat/ChatInterface.svelte +407 -0
- package/frontend/lib/components/chat/formatters/ErrorMessage.svelte +57 -0
- package/frontend/lib/components/chat/formatters/MessageFormatter.svelte +224 -0
- package/frontend/lib/components/chat/formatters/TextMessage.svelte +395 -0
- package/frontend/lib/components/chat/formatters/Tools.svelte +70 -0
- package/frontend/lib/components/chat/formatters/index.ts +3 -0
- package/frontend/lib/components/chat/input/ChatInput.svelte +421 -0
- package/frontend/lib/components/chat/input/components/ChatInputActions.svelte +78 -0
- package/frontend/lib/components/chat/input/components/DragDropOverlay.svelte +30 -0
- package/frontend/lib/components/chat/input/components/EditModeIndicator.svelte +33 -0
- package/frontend/lib/components/chat/input/components/EngineModelPicker.svelte +619 -0
- package/frontend/lib/components/chat/input/components/FileAttachmentPreview.svelte +48 -0
- package/frontend/lib/components/chat/input/components/LoadingIndicator.svelte +31 -0
- package/frontend/lib/components/chat/input/composables/use-animations.svelte.ts +201 -0
- package/frontend/lib/components/chat/input/composables/use-chat-actions.svelte.ts +148 -0
- package/frontend/lib/components/chat/input/composables/use-file-handling.svelte.ts +216 -0
- package/frontend/lib/components/chat/input/composables/use-input-state.svelte.ts +357 -0
- package/frontend/lib/components/chat/input/composables/use-textarea-resize.svelte.ts +57 -0
- package/frontend/lib/components/chat/message/ChatMessage.svelte +478 -0
- package/frontend/lib/components/chat/message/ChatMessages.svelte +541 -0
- package/frontend/lib/components/chat/message/DateSeparator.svelte +86 -0
- package/frontend/lib/components/chat/message/MessageBubble.svelte +86 -0
- package/frontend/lib/components/chat/message/MessageHeader.svelte +157 -0
- package/frontend/lib/components/chat/modal/DebugModal.svelte +59 -0
- package/frontend/lib/components/chat/modal/TokenUsageModal.svelte +124 -0
- package/frontend/lib/components/chat/shared/index.ts +2 -0
- package/frontend/lib/components/chat/shared/utils.ts +116 -0
- package/frontend/lib/components/chat/tools/BashOutputTool.svelte +35 -0
- package/frontend/lib/components/chat/tools/BashTool.svelte +46 -0
- package/frontend/lib/components/chat/tools/CustomMcpTool.svelte +139 -0
- package/frontend/lib/components/chat/tools/EditTool.svelte +48 -0
- package/frontend/lib/components/chat/tools/ExitPlanModeTool.svelte +32 -0
- package/frontend/lib/components/chat/tools/GlobTool.svelte +51 -0
- package/frontend/lib/components/chat/tools/GrepTool.svelte +90 -0
- package/frontend/lib/components/chat/tools/KillShellTool.svelte +26 -0
- package/frontend/lib/components/chat/tools/ListMcpResourcesTool.svelte +31 -0
- package/frontend/lib/components/chat/tools/NotebookEditTool.svelte +38 -0
- package/frontend/lib/components/chat/tools/ReadMcpResourceTool.svelte +34 -0
- package/frontend/lib/components/chat/tools/ReadTool.svelte +41 -0
- package/frontend/lib/components/chat/tools/TaskTool.svelte +64 -0
- package/frontend/lib/components/chat/tools/TodoWriteTool.svelte +75 -0
- package/frontend/lib/components/chat/tools/WebFetchTool.svelte +35 -0
- package/frontend/lib/components/chat/tools/WebSearchTool.svelte +84 -0
- package/frontend/lib/components/chat/tools/WriteTool.svelte +33 -0
- package/frontend/lib/components/chat/tools/components/CodeBlock.svelte +79 -0
- package/frontend/lib/components/chat/tools/components/DiffBlock.svelte +408 -0
- package/frontend/lib/components/chat/tools/components/FileHeader.svelte +45 -0
- package/frontend/lib/components/chat/tools/components/InfoLine.svelte +19 -0
- package/frontend/lib/components/chat/tools/components/StatsBadges.svelte +27 -0
- package/frontend/lib/components/chat/tools/components/TerminalCommand.svelte +54 -0
- package/frontend/lib/components/chat/tools/components/index.ts +7 -0
- package/frontend/lib/components/chat/tools/index.ts +26 -0
- package/frontend/lib/components/chat/widgets/FloatingTodoList.svelte +249 -0
- package/frontend/lib/components/chat/widgets/TokenUsage.svelte +78 -0
- package/frontend/lib/components/checkpoint/TimelineModal.svelte +391 -0
- package/frontend/lib/components/checkpoint/timeline/TimelineEdge.svelte +26 -0
- package/frontend/lib/components/checkpoint/timeline/TimelineGraph.svelte +87 -0
- package/frontend/lib/components/checkpoint/timeline/TimelineNode.svelte +108 -0
- package/frontend/lib/components/checkpoint/timeline/TimelineVersionGroup.svelte +59 -0
- package/frontend/lib/components/checkpoint/timeline/animation.ts +168 -0
- package/frontend/lib/components/checkpoint/timeline/config.ts +44 -0
- package/frontend/lib/components/checkpoint/timeline/graph-builder.ts +304 -0
- package/frontend/lib/components/checkpoint/timeline/types.ts +65 -0
- package/frontend/lib/components/checkpoint/timeline/utils.ts +53 -0
- package/frontend/lib/components/common/Alert.svelte +139 -0
- package/frontend/lib/components/common/AvatarBubble.svelte +56 -0
- package/frontend/lib/components/common/Button.svelte +71 -0
- package/frontend/lib/components/common/Card.svelte +102 -0
- package/frontend/lib/components/common/Checkbox.svelte +48 -0
- package/frontend/lib/components/common/Dialog.svelte +249 -0
- package/frontend/lib/components/common/FolderBrowser.svelte +843 -0
- package/frontend/lib/components/common/Icon.svelte +58 -0
- package/frontend/lib/components/common/Input.svelte +72 -0
- package/frontend/lib/components/common/Lightbox.svelte +233 -0
- package/frontend/lib/components/common/LoadingScreen.svelte +52 -0
- package/frontend/lib/components/common/LoadingSpinner.svelte +48 -0
- package/frontend/lib/components/common/Modal.svelte +177 -0
- package/frontend/lib/components/common/ModalProvider.svelte +28 -0
- package/frontend/lib/components/common/ModelSelector.svelte +110 -0
- package/frontend/lib/components/common/MonacoEditor.svelte +569 -0
- package/frontend/lib/components/common/NotificationToast.svelte +113 -0
- package/frontend/lib/components/common/PageTemplate.svelte +76 -0
- package/frontend/lib/components/common/ProjectUserAvatars.svelte +79 -0
- package/frontend/lib/components/common/Select.svelte +98 -0
- package/frontend/lib/components/common/Textarea.svelte +80 -0
- package/frontend/lib/components/common/ThemeToggle.svelte +44 -0
- package/frontend/lib/components/common/lucide-icons.ts +1642 -0
- package/frontend/lib/components/common/material-icons.ts +1082 -0
- package/frontend/lib/components/common/xterm/XTerm.svelte +796 -0
- package/frontend/lib/components/common/xterm/index.ts +16 -0
- package/frontend/lib/components/common/xterm/terminal-config.ts +68 -0
- package/frontend/lib/components/common/xterm/types.ts +31 -0
- package/frontend/lib/components/common/xterm/xterm-service.ts +353 -0
- package/frontend/lib/components/files/FileNode.svelte +384 -0
- package/frontend/lib/components/files/FileTree.svelte +681 -0
- package/frontend/lib/components/files/FileViewer.svelte +728 -0
- package/frontend/lib/components/files/SearchResults.svelte +303 -0
- package/frontend/lib/components/git/BranchManager.svelte +458 -0
- package/frontend/lib/components/git/ChangesSection.svelte +107 -0
- package/frontend/lib/components/git/CommitForm.svelte +76 -0
- package/frontend/lib/components/git/ConflictResolver.svelte +158 -0
- package/frontend/lib/components/git/DiffViewer.svelte +364 -0
- package/frontend/lib/components/git/FileChangeItem.svelte +97 -0
- package/frontend/lib/components/git/GitButton.svelte +33 -0
- package/frontend/lib/components/git/GitLog.svelte +361 -0
- package/frontend/lib/components/git/GitModal.svelte +80 -0
- package/frontend/lib/components/history/HistoryModal.svelte +563 -0
- package/frontend/lib/components/history/HistoryView.svelte +615 -0
- package/frontend/lib/components/index.ts +34 -0
- package/frontend/lib/components/preview/browser/BrowserPreview.svelte +549 -0
- package/frontend/lib/components/preview/browser/components/Canvas.svelte +1058 -0
- package/frontend/lib/components/preview/browser/components/ConsolePanel.svelte +757 -0
- package/frontend/lib/components/preview/browser/components/Container.svelte +450 -0
- package/frontend/lib/components/preview/browser/components/ContextMenu.svelte +236 -0
- package/frontend/lib/components/preview/browser/components/SelectDropdown.svelte +224 -0
- package/frontend/lib/components/preview/browser/components/Toolbar.svelte +339 -0
- package/frontend/lib/components/preview/browser/components/VirtualCursor.svelte +36 -0
- package/frontend/lib/components/preview/browser/core/cleanup.svelte.ts +155 -0
- package/frontend/lib/components/preview/browser/core/coordinator.svelte.ts +837 -0
- package/frontend/lib/components/preview/browser/core/interactions.svelte.ts +113 -0
- package/frontend/lib/components/preview/browser/core/mcp-handlers.svelte.ts +296 -0
- package/frontend/lib/components/preview/browser/core/native-ui-handlers.svelte.ts +391 -0
- package/frontend/lib/components/preview/browser/core/stream-handler.svelte.ts +231 -0
- package/frontend/lib/components/preview/browser/core/tab-manager.svelte.ts +210 -0
- package/frontend/lib/components/preview/browser/core/tab-operations.svelte.ts +239 -0
- package/frontend/lib/components/preview/index.ts +2 -0
- package/frontend/lib/components/settings/SettingsModal.svelte +235 -0
- package/frontend/lib/components/settings/SettingsView.svelte +36 -0
- package/frontend/lib/components/settings/appearance/AppearanceSettings.svelte +51 -0
- package/frontend/lib/components/settings/appearance/LayoutPresetSettings.svelte +160 -0
- package/frontend/lib/components/settings/appearance/LayoutPreview.svelte +76 -0
- package/frontend/lib/components/settings/engines/AIEnginesSettings.svelte +917 -0
- package/frontend/lib/components/settings/general/AdvancedSettings.svelte +187 -0
- package/frontend/lib/components/settings/general/DataManagementSettings.svelte +203 -0
- package/frontend/lib/components/settings/general/GeneralSettings.svelte +10 -0
- package/frontend/lib/components/settings/model/ModelSettings.svelte +357 -0
- package/frontend/lib/components/settings/notifications/NotificationSettings.svelte +205 -0
- package/frontend/lib/components/settings/user/UserSettings.svelte +197 -0
- package/frontend/lib/components/terminal/Terminal.svelte +368 -0
- package/frontend/lib/components/terminal/TerminalTabs.svelte +87 -0
- package/frontend/lib/components/terminal/TerminalView.svelte +55 -0
- package/frontend/lib/components/tunnel/TunnelActive.svelte +142 -0
- package/frontend/lib/components/tunnel/TunnelButton.svelte +54 -0
- package/frontend/lib/components/tunnel/TunnelInactive.svelte +284 -0
- package/frontend/lib/components/tunnel/TunnelModal.svelte +47 -0
- package/frontend/lib/components/tunnel/TunnelQRCode.svelte +49 -0
- package/frontend/lib/components/workspace/DesktopNavigator.svelte +382 -0
- package/frontend/lib/components/workspace/MobileNavigator.svelte +403 -0
- package/frontend/lib/components/workspace/PanelContainer.svelte +100 -0
- package/frontend/lib/components/workspace/PanelHeader.svelte +505 -0
- package/frontend/lib/components/workspace/ViewMenu.svelte +162 -0
- package/frontend/lib/components/workspace/WorkspaceLayout.svelte +169 -0
- package/frontend/lib/components/workspace/layout/DesktopLayout.svelte +15 -0
- package/frontend/lib/components/workspace/layout/MobileLayout.svelte +17 -0
- package/frontend/lib/components/workspace/layout/split-pane/Container.svelte +42 -0
- package/frontend/lib/components/workspace/layout/split-pane/Handle.svelte +85 -0
- package/frontend/lib/components/workspace/layout/split-pane/Layout.svelte +37 -0
- package/frontend/lib/components/workspace/panels/ChatPanel.svelte +274 -0
- package/frontend/lib/components/workspace/panels/FilesPanel.svelte +1261 -0
- package/frontend/lib/components/workspace/panels/GitPanel.svelte +1560 -0
- package/frontend/lib/components/workspace/panels/PreviewPanel.svelte +150 -0
- package/frontend/lib/components/workspace/panels/TerminalPanel.svelte +73 -0
- package/frontend/lib/constants/preview.ts +45 -0
- package/frontend/lib/services/chat/chat.service.ts +704 -0
- package/frontend/lib/services/chat/index.ts +7 -0
- package/frontend/lib/services/notification/global-stream-monitor.ts +86 -0
- package/frontend/lib/services/notification/index.ts +8 -0
- package/frontend/lib/services/notification/push.service.ts +144 -0
- package/frontend/lib/services/notification/sound.service.ts +127 -0
- package/frontend/lib/services/preview/browser/browser-console.service.ts +61 -0
- package/frontend/lib/services/preview/browser/browser-webcodecs.service.ts +1499 -0
- package/frontend/lib/services/preview/browser/mcp-integration.svelte.ts +67 -0
- package/frontend/lib/services/preview/index.ts +23 -0
- package/frontend/lib/services/project/index.ts +8 -0
- package/frontend/lib/services/project/status.service.ts +159 -0
- package/frontend/lib/services/snapshot/snapshot.service.ts +47 -0
- package/frontend/lib/services/terminal/background/index.ts +130 -0
- package/frontend/lib/services/terminal/background/session-restore.ts +274 -0
- package/frontend/lib/services/terminal/background/stream-manager.ts +286 -0
- package/frontend/lib/services/terminal/index.ts +14 -0
- package/frontend/lib/services/terminal/persistence.service.ts +260 -0
- package/frontend/lib/services/terminal/project.service.ts +953 -0
- package/frontend/lib/services/terminal/session.service.ts +364 -0
- package/frontend/lib/services/terminal/terminal.service.ts +369 -0
- package/frontend/lib/stores/core/app.svelte.ts +117 -0
- package/frontend/lib/stores/core/files.svelte.ts +73 -0
- package/frontend/lib/stores/core/presence.svelte.ts +48 -0
- package/frontend/lib/stores/core/projects.svelte.ts +317 -0
- package/frontend/lib/stores/core/sessions.svelte.ts +383 -0
- package/frontend/lib/stores/features/claude-accounts.svelte.ts +58 -0
- package/frontend/lib/stores/features/models.svelte.ts +89 -0
- package/frontend/lib/stores/features/settings.svelte.ts +87 -0
- package/frontend/lib/stores/features/terminal.svelte.ts +701 -0
- package/frontend/lib/stores/features/tunnel.svelte.ts +161 -0
- package/frontend/lib/stores/features/user.svelte.ts +96 -0
- package/frontend/lib/stores/ui/chat-input.svelte.ts +57 -0
- package/frontend/lib/stores/ui/chat-model.svelte.ts +61 -0
- package/frontend/lib/stores/ui/dialog.svelte.ts +59 -0
- package/frontend/lib/stores/ui/edit-mode.svelte.ts +214 -0
- package/frontend/lib/stores/ui/notification.svelte.ts +166 -0
- package/frontend/lib/stores/ui/settings-modal.svelte.ts +88 -0
- package/frontend/lib/stores/ui/theme.svelte.ts +179 -0
- package/frontend/lib/stores/ui/workspace.svelte.ts +754 -0
- package/frontend/lib/types/native-ui.ts +73 -0
- package/frontend/lib/utils/chat/date-separator.ts +39 -0
- package/frontend/lib/utils/chat/message-grouper.ts +219 -0
- package/frontend/lib/utils/chat/message-processor.ts +135 -0
- package/frontend/lib/utils/chat/tool-handler.ts +161 -0
- package/frontend/lib/utils/chat/virtual-scroll.svelte.ts +142 -0
- package/frontend/lib/utils/click-outside.ts +20 -0
- package/frontend/lib/utils/context-manager.ts +257 -0
- package/frontend/lib/utils/file-icon-mappings.ts +769 -0
- package/frontend/lib/utils/folder-icon-mappings.ts +1030 -0
- package/frontend/lib/utils/git-status.ts +68 -0
- package/frontend/lib/utils/platform.ts +113 -0
- package/frontend/lib/utils/port-check.ts +65 -0
- package/frontend/lib/utils/terminalFormatter.ts +207 -0
- package/frontend/lib/utils/theme.ts +6 -0
- package/frontend/lib/utils/tree-visualizer.ts +320 -0
- package/frontend/lib/utils/ws.ts +44 -0
- package/frontend/main.ts +13 -0
- package/index.html +70 -0
- package/package.json +111 -0
- package/scripts/generate-icons.ts +87 -0
- package/scripts/pre-publish-check.sh +142 -0
- package/scripts/setup-hooks.sh +134 -0
- package/scripts/validate-branch-name.sh +47 -0
- package/scripts/validate-commit-msg.sh +42 -0
- package/shared/constants/engines.ts +134 -0
- package/shared/types/database/connection.ts +16 -0
- package/shared/types/database/index.ts +6 -0
- package/shared/types/database/schema.ts +141 -0
- package/shared/types/engine/index.ts +45 -0
- package/shared/types/filesystem/index.ts +22 -0
- package/shared/types/git.ts +171 -0
- package/shared/types/messaging/index.ts +239 -0
- package/shared/types/messaging/tool.ts +526 -0
- package/shared/types/network/api.ts +18 -0
- package/shared/types/network/index.ts +5 -0
- package/shared/types/stores/app.ts +23 -0
- package/shared/types/stores/dialog.ts +21 -0
- package/shared/types/stores/index.ts +3 -0
- package/shared/types/stores/settings.ts +15 -0
- package/shared/types/terminal/index.ts +44 -0
- package/shared/types/ui/components.ts +61 -0
- package/shared/types/ui/icons.ts +23 -0
- package/shared/types/ui/index.ts +22 -0
- package/shared/types/ui/notifications.ts +14 -0
- package/shared/types/ui/theme.ts +12 -0
- package/shared/types/websocket/index.ts +43 -0
- package/shared/types/window.d.ts +13 -0
- package/shared/utils/anonymous-user.ts +168 -0
- package/shared/utils/async.ts +10 -0
- package/shared/utils/diff-calculator.ts +184 -0
- package/shared/utils/file-type-detection.ts +166 -0
- package/shared/utils/logger.ts +158 -0
- package/shared/utils/message-formatter.ts +79 -0
- package/shared/utils/path.ts +47 -0
- package/shared/utils/ws-client.ts +768 -0
- package/shared/utils/ws-server.ts +660 -0
- package/static/audio/notification.ogg +0 -0
- package/static/favicon.svg +8 -0
- package/static/fonts/dm-sans/dm-sans-italic-latin-ext.woff2 +0 -0
- package/static/fonts/dm-sans/dm-sans-italic-latin.woff2 +0 -0
- package/static/fonts/dm-sans/dm-sans-normal-latin-ext.woff2 +0 -0
- package/static/fonts/dm-sans/dm-sans-normal-latin.woff2 +0 -0
- package/static/fonts/dm-sans.css +96 -0
- package/svelte.config.js +20 -0
- package/vite.config.ts +33 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get Temperature Handler
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export async function getTemperatureHandler(args: { latitude: number; longitude: number }) {
|
|
6
|
+
try {
|
|
7
|
+
// Call Open-Meteo API (no API key required)
|
|
8
|
+
const url = `https://api.open-meteo.com/v1/forecast?latitude=${args.latitude}&longitude=${args.longitude}¤t=temperature_2m&temperature_unit=fahrenheit`;
|
|
9
|
+
|
|
10
|
+
const response = await fetch(url);
|
|
11
|
+
|
|
12
|
+
if (!response.ok) {
|
|
13
|
+
return {
|
|
14
|
+
content: [{
|
|
15
|
+
type: "text" as const,
|
|
16
|
+
text: `Failed to fetch weather data: ${response.status} ${response.statusText}`
|
|
17
|
+
}],
|
|
18
|
+
isError: true
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const data = await response.json();
|
|
23
|
+
|
|
24
|
+
// Check if temperature data is available
|
|
25
|
+
if (!data.current || data.current.temperature_2m === undefined) {
|
|
26
|
+
return {
|
|
27
|
+
content: [{
|
|
28
|
+
type: "text" as const,
|
|
29
|
+
text: "Temperature data not available for this location."
|
|
30
|
+
}],
|
|
31
|
+
isError: true
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const temperature = data.current.temperature_2m;
|
|
36
|
+
const unit = data.current_units?.temperature_2m || "°F";
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
content: [{
|
|
40
|
+
type: "text" as const,
|
|
41
|
+
text: `Temperature: ${temperature}${unit}`
|
|
42
|
+
}]
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
} catch (error) {
|
|
46
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
content: [{
|
|
50
|
+
type: "text" as const,
|
|
51
|
+
text: `Error fetching temperature: ${errorMessage}`
|
|
52
|
+
}],
|
|
53
|
+
isError: true
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Weather Service - Custom MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Provides weather-related tools using the Open-Meteo API.
|
|
5
|
+
* No API key required.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import { defineServer } from "../helper";
|
|
10
|
+
import { getTemperatureHandler } from "./get-temperature";
|
|
11
|
+
|
|
12
|
+
export default defineServer({
|
|
13
|
+
name: "weather-service",
|
|
14
|
+
version: "1.0.0",
|
|
15
|
+
tools: {
|
|
16
|
+
"get_temperature": {
|
|
17
|
+
description: "Get current temperature for a location using coordinates. Returns temperature in Fahrenheit.",
|
|
18
|
+
schema: {
|
|
19
|
+
latitude: z.number()
|
|
20
|
+
.min(-90)
|
|
21
|
+
.max(90)
|
|
22
|
+
.describe("Latitude coordinate (-90 to 90)"),
|
|
23
|
+
longitude: z.number()
|
|
24
|
+
.min(-180)
|
|
25
|
+
.max(180)
|
|
26
|
+
.describe("Longitude coordinate (-180 to 180)")
|
|
27
|
+
},
|
|
28
|
+
handler: getTemperatureHandler
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* MCP Stdio Server for Open Code
|
|
4
|
+
*
|
|
5
|
+
* Standalone subprocess that exposes our custom MCP tools via stdio transport.
|
|
6
|
+
* Open Code spawns this process and communicates over stdin/stdout (JSON-RPC 2.0).
|
|
7
|
+
*
|
|
8
|
+
* Tool definitions (schema, description) are loaded from the SAME source as
|
|
9
|
+
* Claude Code — the `serverMetadata` registry in `./servers/index.ts`.
|
|
10
|
+
*
|
|
11
|
+
* ALL tool calls are proxied to the main Clopen server via WSClient bridge,
|
|
12
|
+
* because handlers need in-process access to browser instances, project context, etc.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
16
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
17
|
+
import { WSClient } from '$shared/utils/ws-client';
|
|
18
|
+
import { serverMetadata } from './servers/index';
|
|
19
|
+
import { mcpServers } from './config';
|
|
20
|
+
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// WebSocket Bridge — proxies tool calls to the main Clopen server via WSClient
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
25
|
+
const BRIDGE_PORT = process.env.CLOPEN_PORT || '9141';
|
|
26
|
+
const WS_URL = `ws://localhost:${BRIDGE_PORT}/ws`;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* WSClient instance for communicating with the main Clopen server.
|
|
30
|
+
* Uses the same protocol as the frontend (JSON messages with action/payload).
|
|
31
|
+
*/
|
|
32
|
+
const wsClient = new WSClient<any>(WS_URL, {
|
|
33
|
+
autoReconnect: true,
|
|
34
|
+
maxReconnectAttempts: 10,
|
|
35
|
+
reconnectDelay: 1000,
|
|
36
|
+
maxReconnectDelay: 10000,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Call a tool handler on the main Clopen server via the WS bridge.
|
|
41
|
+
* Uses WSClient.http() which follows the standard request-response pattern.
|
|
42
|
+
*/
|
|
43
|
+
async function callBridge(
|
|
44
|
+
serverName: string,
|
|
45
|
+
toolName: string,
|
|
46
|
+
args: Record<string, unknown>
|
|
47
|
+
): Promise<{ content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>; isError?: boolean }> {
|
|
48
|
+
try {
|
|
49
|
+
return await wsClient.http('mcp:execute' as any, {
|
|
50
|
+
server: serverName,
|
|
51
|
+
tool: toolName,
|
|
52
|
+
args,
|
|
53
|
+
} as any, 30000);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
56
|
+
return {
|
|
57
|
+
content: [{ type: 'text', text: `Bridge connection failed: ${msg}` }],
|
|
58
|
+
isError: true,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// Build MCP server from existing server metadata (single source of truth)
|
|
65
|
+
// ============================================================================
|
|
66
|
+
|
|
67
|
+
const server = new McpServer({
|
|
68
|
+
name: 'clopen-mcp',
|
|
69
|
+
version: '1.0.0',
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Iterate over all configured servers and register their enabled tools
|
|
73
|
+
for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
|
|
74
|
+
if (!serverConfig.enabled) continue;
|
|
75
|
+
|
|
76
|
+
// Get tool definitions from the metadata registry
|
|
77
|
+
const meta = (serverMetadata as Record<string, { toolDefs: Record<string, { description: string; schema: Record<string, any> }> }>)[serverName];
|
|
78
|
+
if (!meta) continue;
|
|
79
|
+
|
|
80
|
+
for (const toolName of serverConfig.tools) {
|
|
81
|
+
const toolDef = meta.toolDefs[toolName];
|
|
82
|
+
if (!toolDef) continue;
|
|
83
|
+
|
|
84
|
+
// Register tool with the same schema/description, but handler goes through bridge
|
|
85
|
+
server.registerTool(
|
|
86
|
+
toolName,
|
|
87
|
+
{
|
|
88
|
+
description: toolDef.description,
|
|
89
|
+
inputSchema: toolDef.schema,
|
|
90
|
+
},
|
|
91
|
+
async (args: Record<string, unknown>) => {
|
|
92
|
+
return await callBridge(serverName, toolName, args) as any;
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ============================================================================
|
|
99
|
+
// Connect via stdio transport
|
|
100
|
+
// ============================================================================
|
|
101
|
+
|
|
102
|
+
const transport = new StdioServerTransport();
|
|
103
|
+
await server.connect(transport);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP (Model Context Protocol) Custom Tools - Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* This file contains all TypeScript types and interfaces used across
|
|
5
|
+
* the custom MCP tools system.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { serverMetadata } from './servers';
|
|
9
|
+
import type { McpSdkServerConfigWithInstance } from '@anthropic-ai/claude-agent-sdk';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Extract server names from metadata registry
|
|
13
|
+
*/
|
|
14
|
+
export type ServerName = keyof typeof serverMetadata;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Extract tool names from a specific server
|
|
18
|
+
* Automatically inferred from server metadata
|
|
19
|
+
*/
|
|
20
|
+
export type ToolsForServer<S extends ServerName> = (typeof serverMetadata)[S]['tools'][number];
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Configuration for an MCP server (user-defined)
|
|
24
|
+
*/
|
|
25
|
+
export type ServerConfig<S extends ServerName = ServerName> = {
|
|
26
|
+
/** Whether this server is enabled */
|
|
27
|
+
enabled: boolean;
|
|
28
|
+
/** List of enabled tool names for this server */
|
|
29
|
+
tools: readonly ToolsForServer<S>[];
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Complete server configuration with instance (internal use)
|
|
34
|
+
*/
|
|
35
|
+
export type McpServerConfigWithInstance<S extends ServerName = ServerName> = ServerConfig<S> & {
|
|
36
|
+
instance: McpSdkServerConfigWithInstance;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Parsed MCP tool name
|
|
41
|
+
* Format: mcp__server-name__tool-name
|
|
42
|
+
*/
|
|
43
|
+
export interface ParsedMcpToolName {
|
|
44
|
+
/** Server name (e.g., "weather-service") */
|
|
45
|
+
server: string;
|
|
46
|
+
/** Tool name (e.g., "get_temperature") */
|
|
47
|
+
tool: string;
|
|
48
|
+
/** Full tool name (e.g., "mcp__weather-service__get_temperature") */
|
|
49
|
+
fullName: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* MCP server status from SDK
|
|
54
|
+
*/
|
|
55
|
+
export interface McpServerStatus {
|
|
56
|
+
/** Server name */
|
|
57
|
+
name: string;
|
|
58
|
+
/** Connection status */
|
|
59
|
+
status: 'connected' | 'failed' | 'needs-auth' | 'pending';
|
|
60
|
+
/** Server information if connected */
|
|
61
|
+
serverInfo?: {
|
|
62
|
+
name: string;
|
|
63
|
+
version: string;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser Audio Capture Handler
|
|
3
|
+
*
|
|
4
|
+
* Handles audio capture setup and management for headless browser sessions.
|
|
5
|
+
* Audio is captured via AudioContext interception and encoded with AudioEncoder (Opus).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Page } from 'puppeteer';
|
|
9
|
+
import type { StreamingConfig } from './types';
|
|
10
|
+
import { audioCaptureScript } from './scripts/audio-stream';
|
|
11
|
+
|
|
12
|
+
export class BrowserAudioCapture {
|
|
13
|
+
/**
|
|
14
|
+
* Setup audio capture for a page
|
|
15
|
+
* Injects audio capture script that intercepts AudioContext before page loads
|
|
16
|
+
*/
|
|
17
|
+
async setupAudioCapture(page: Page, config: StreamingConfig['audio']): Promise<void> {
|
|
18
|
+
// Inject audio capture script BEFORE page loads to intercept AudioContext
|
|
19
|
+
await page.evaluateOnNewDocument(audioCaptureScript, config);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Check if audio encoder is supported in the page
|
|
24
|
+
*/
|
|
25
|
+
async isAudioSupported(page: Page): Promise<boolean> {
|
|
26
|
+
try {
|
|
27
|
+
return await page.evaluate(() => {
|
|
28
|
+
return typeof (window as any).__audioEncoder?.isSupported === 'function'
|
|
29
|
+
&& (window as any).__audioEncoder.isSupported();
|
|
30
|
+
});
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Initialize and start audio capture
|
|
38
|
+
*/
|
|
39
|
+
async startAudioCapture(page: Page): Promise<boolean> {
|
|
40
|
+
try {
|
|
41
|
+
const initialized = await page.evaluate(async () => {
|
|
42
|
+
const encoder = (window as any).__audioEncoder;
|
|
43
|
+
if (!encoder) return false;
|
|
44
|
+
|
|
45
|
+
const initiated = await encoder.init();
|
|
46
|
+
if (initiated) {
|
|
47
|
+
return encoder.start();
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return initialized;
|
|
53
|
+
} catch (error) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Stop audio capture
|
|
60
|
+
*/
|
|
61
|
+
async stopAudioCapture(page: Page): Promise<void> {
|
|
62
|
+
try {
|
|
63
|
+
await page.evaluate(() => {
|
|
64
|
+
const encoder = (window as any).__audioEncoder;
|
|
65
|
+
if (encoder) {
|
|
66
|
+
encoder.stop();
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
} catch {
|
|
70
|
+
// Ignore errors during cleanup
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Check if audio is currently being captured
|
|
76
|
+
*/
|
|
77
|
+
async isCapturing(page: Page): Promise<boolean> {
|
|
78
|
+
try {
|
|
79
|
+
return await page.evaluate(() => {
|
|
80
|
+
return (window as any).__audioEncoder?.isCapturing() || false;
|
|
81
|
+
});
|
|
82
|
+
} catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import type { Page, ConsoleMessage as PuppeteerConsoleMessage, HTTPResponse } from 'puppeteer';
|
|
3
|
+
import type { BrowserConsoleMessage, BrowserTab } from './types';
|
|
4
|
+
|
|
5
|
+
import { debug } from '$shared/utils/logger';
|
|
6
|
+
export class BrowserConsoleManager extends EventEmitter {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async setupConsoleLogging(sessionId: string, page: Page, session: BrowserTab) {
|
|
12
|
+
|
|
13
|
+
// Clear any existing console logs for this session
|
|
14
|
+
session.consoleLogs = [];
|
|
15
|
+
|
|
16
|
+
// Listen to ALL console events from the page
|
|
17
|
+
page.on('console', async (consoleMessage: PuppeteerConsoleMessage) => {
|
|
18
|
+
// Always log to server console for debugging
|
|
19
|
+
if (!session.consoleEnabled) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const messageId = `console-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
25
|
+
const text = consoleMessage.text();
|
|
26
|
+
const type = consoleMessage.type() as BrowserConsoleMessage['type'];
|
|
27
|
+
|
|
28
|
+
// Get location information (Puppeteer uses location() method)
|
|
29
|
+
const location = consoleMessage.location();
|
|
30
|
+
const messageLocation = location ? {
|
|
31
|
+
url: location.url || '',
|
|
32
|
+
lineNumber: location.lineNumber || 0,
|
|
33
|
+
columnNumber: location.columnNumber || 0
|
|
34
|
+
} : undefined;
|
|
35
|
+
|
|
36
|
+
// Extract arguments with improved error handling
|
|
37
|
+
let args: any[] = [];
|
|
38
|
+
try {
|
|
39
|
+
const messageArgs = consoleMessage.args();
|
|
40
|
+
if (messageArgs && messageArgs.length > 0) {
|
|
41
|
+
args = await Promise.all(
|
|
42
|
+
messageArgs.map(async (arg) => {
|
|
43
|
+
try {
|
|
44
|
+
// Try to get JSON value first
|
|
45
|
+
const jsonValue = await arg.jsonValue();
|
|
46
|
+
return jsonValue;
|
|
47
|
+
} catch {
|
|
48
|
+
try {
|
|
49
|
+
// Fallback to string representation
|
|
50
|
+
return arg.toString();
|
|
51
|
+
} catch {
|
|
52
|
+
// Final fallback
|
|
53
|
+
return '[Unable to serialize]';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
debug.warn('preview', 'Could not extract console message args:', error);
|
|
61
|
+
args = [];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const consoleLog: BrowserConsoleMessage = {
|
|
65
|
+
id: messageId,
|
|
66
|
+
type,
|
|
67
|
+
text,
|
|
68
|
+
args,
|
|
69
|
+
location: messageLocation,
|
|
70
|
+
timestamp: Date.now()
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// Add to session logs (with limit to prevent memory issues)
|
|
74
|
+
session.consoleLogs.push(consoleLog);
|
|
75
|
+
if (session.consoleLogs.length > 1000) {
|
|
76
|
+
session.consoleLogs = session.consoleLogs.slice(-500); // Keep last 500 logs
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Emit console message event for real-time streaming
|
|
80
|
+
this.emit('console-message', {
|
|
81
|
+
sessionId: session.id,
|
|
82
|
+
message: consoleLog
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
} catch (error) {
|
|
87
|
+
debug.error('preview', '❌ Error processing console message:', error);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Listen to page errors (uncaught JavaScript errors)
|
|
92
|
+
page.on('pageerror', (err) => {
|
|
93
|
+
if (!session.consoleEnabled) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const error = err as Error;
|
|
99
|
+
const messageId = `error-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
100
|
+
const consoleLog: BrowserConsoleMessage = {
|
|
101
|
+
id: messageId,
|
|
102
|
+
type: 'error',
|
|
103
|
+
text: `Uncaught ${error.message || String(err)}`,
|
|
104
|
+
stackTrace: error.stack,
|
|
105
|
+
timestamp: Date.now()
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
session.consoleLogs.push(consoleLog);
|
|
109
|
+
if (session.consoleLogs.length > 1000) {
|
|
110
|
+
session.consoleLogs = session.consoleLogs.slice(-500);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
this.emit('console-message', {
|
|
114
|
+
sessionId: session.id,
|
|
115
|
+
message: consoleLog
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
} catch (err) {
|
|
120
|
+
debug.error('preview', '❌ Error processing page error:', err);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Listen to response failures (network errors)
|
|
125
|
+
page.on('response', (response: HTTPResponse) => {
|
|
126
|
+
if (!session.consoleEnabled) return;
|
|
127
|
+
|
|
128
|
+
if (!response.ok() && response.status() >= 400) {
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
const messageId = `network-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
133
|
+
const consoleLog: BrowserConsoleMessage = {
|
|
134
|
+
id: messageId,
|
|
135
|
+
type: 'error',
|
|
136
|
+
text: `Network error: ${response.status()} ${response.statusText()} - ${response.url()}`,
|
|
137
|
+
location: {
|
|
138
|
+
url: response.url(),
|
|
139
|
+
lineNumber: 0,
|
|
140
|
+
columnNumber: 0
|
|
141
|
+
},
|
|
142
|
+
timestamp: Date.now()
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
session.consoleLogs.push(consoleLog);
|
|
146
|
+
if (session.consoleLogs.length > 1000) {
|
|
147
|
+
session.consoleLogs = session.consoleLogs.slice(-500);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
this.emit('console-message', {
|
|
151
|
+
sessionId: session.id,
|
|
152
|
+
message: consoleLog
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
} catch (err) {
|
|
157
|
+
debug.error('preview', '❌ Error processing network error:', err);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Console monitoring is handled automatically by Puppeteer's console event listener
|
|
163
|
+
// No additional injection needed
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
getConsoleLogs(session: BrowserTab): BrowserConsoleMessage[] {
|
|
169
|
+
return session ? session.consoleLogs : [];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
clearConsoleLogs(session: BrowserTab): boolean {
|
|
173
|
+
if (!session) return false;
|
|
174
|
+
|
|
175
|
+
session.consoleLogs = [];
|
|
176
|
+
|
|
177
|
+
// Add a clear message to console logs
|
|
178
|
+
const clearMessage: BrowserConsoleMessage = {
|
|
179
|
+
id: `clear-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
180
|
+
type: 'clear',
|
|
181
|
+
text: 'Console was cleared',
|
|
182
|
+
timestamp: Date.now()
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
session.consoleLogs.push(clearMessage);
|
|
186
|
+
|
|
187
|
+
// Emit clear event
|
|
188
|
+
this.emit('console-clear', {
|
|
189
|
+
sessionId: session.id,
|
|
190
|
+
timestamp: Date.now()
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
toggleConsoleLogging(session: BrowserTab, enabled: boolean): boolean {
|
|
198
|
+
if (!session) return false;
|
|
199
|
+
|
|
200
|
+
session.consoleEnabled = enabled;
|
|
201
|
+
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async executeConsoleCommand(session: BrowserTab, command: string): Promise<any> {
|
|
206
|
+
if (!session) throw new Error('Session not found');
|
|
207
|
+
|
|
208
|
+
try {
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
// Execute the command in the browser context
|
|
212
|
+
const result = await session.page.evaluate((cmd: string) => {
|
|
213
|
+
// Create a safe evaluation context
|
|
214
|
+
try {
|
|
215
|
+
// Use Function constructor for safer evaluation than eval
|
|
216
|
+
const func = new Function('return ' + cmd);
|
|
217
|
+
return func();
|
|
218
|
+
} catch (error) {
|
|
219
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
220
|
+
}
|
|
221
|
+
}, command);
|
|
222
|
+
|
|
223
|
+
// Log the command execution as a console message
|
|
224
|
+
const commandMessage: BrowserConsoleMessage = {
|
|
225
|
+
id: `command-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
226
|
+
type: 'log',
|
|
227
|
+
text: `> ${command}`,
|
|
228
|
+
args: [result],
|
|
229
|
+
timestamp: Date.now()
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
session.consoleLogs.push(commandMessage);
|
|
233
|
+
|
|
234
|
+
// Emit the command result
|
|
235
|
+
this.emit('console-message', {
|
|
236
|
+
sessionId: session.id,
|
|
237
|
+
message: commandMessage
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
return result;
|
|
241
|
+
} catch (error) {
|
|
242
|
+
debug.error('preview', 'Error executing console command:', error);
|
|
243
|
+
|
|
244
|
+
// Log the error as a console message
|
|
245
|
+
const errorMessage: BrowserConsoleMessage = {
|
|
246
|
+
id: `command-error-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
247
|
+
type: 'error',
|
|
248
|
+
text: `Error executing command: ${command}`,
|
|
249
|
+
args: [error instanceof Error ? error.message : String(error)],
|
|
250
|
+
timestamp: Date.now()
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
session.consoleLogs.push(errorMessage);
|
|
254
|
+
|
|
255
|
+
this.emit('console-message', {
|
|
256
|
+
sessionId: session.id,
|
|
257
|
+
message: errorMessage
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|