@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,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frontend Native UI Types
|
|
3
|
+
* For dialog, select dropdown, and context menu overlays
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Dialog types
|
|
7
|
+
export interface BrowserDialogEvent {
|
|
8
|
+
sessionId: string;
|
|
9
|
+
dialogId: string;
|
|
10
|
+
type: 'alert' | 'confirm' | 'prompt' | 'beforeunload';
|
|
11
|
+
message: string;
|
|
12
|
+
defaultValue?: string;
|
|
13
|
+
timestamp: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface BrowserPrintEvent {
|
|
17
|
+
sessionId: string;
|
|
18
|
+
timestamp: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Select dropdown types
|
|
22
|
+
export interface BrowserSelectOption {
|
|
23
|
+
index: number;
|
|
24
|
+
value: string;
|
|
25
|
+
text: string;
|
|
26
|
+
selected: boolean;
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface BrowserSelectInfo {
|
|
31
|
+
sessionId: string;
|
|
32
|
+
selectId: string;
|
|
33
|
+
x: number;
|
|
34
|
+
y: number;
|
|
35
|
+
boundingBox: {
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
width: number;
|
|
39
|
+
height: number;
|
|
40
|
+
};
|
|
41
|
+
options: BrowserSelectOption[];
|
|
42
|
+
selectedIndex: number;
|
|
43
|
+
timestamp: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Context menu types
|
|
47
|
+
export interface BrowserContextMenuItem {
|
|
48
|
+
id: string;
|
|
49
|
+
label: string;
|
|
50
|
+
enabled: boolean;
|
|
51
|
+
type?: 'normal' | 'separator' | 'submenu';
|
|
52
|
+
icon?: string;
|
|
53
|
+
submenu?: BrowserContextMenuItem[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface BrowserContextMenuInfo {
|
|
57
|
+
sessionId: string;
|
|
58
|
+
menuId: string;
|
|
59
|
+
x: number;
|
|
60
|
+
y: number;
|
|
61
|
+
items: BrowserContextMenuItem[];
|
|
62
|
+
elementInfo: {
|
|
63
|
+
tagName: string;
|
|
64
|
+
isLink: boolean;
|
|
65
|
+
isImage: boolean;
|
|
66
|
+
isInput: boolean;
|
|
67
|
+
isTextSelected: boolean;
|
|
68
|
+
linkUrl?: string;
|
|
69
|
+
imageUrl?: string;
|
|
70
|
+
inputType?: string;
|
|
71
|
+
};
|
|
72
|
+
timestamp: number;
|
|
73
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { SDKMessageFormatter } from '$shared/types/database/schema';
|
|
2
|
+
|
|
3
|
+
// Interface for date separator items
|
|
4
|
+
export interface DateSeparatorItem {
|
|
5
|
+
type: 'message' | 'date';
|
|
6
|
+
data: any;
|
|
7
|
+
key: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Add date separators to messages
|
|
11
|
+
// startIndex: global offset for stable keys when using windowed slices
|
|
12
|
+
export function addDateSeparators(messages: SDKMessageFormatter[], startIndex: number = 0): DateSeparatorItem[] {
|
|
13
|
+
const result: DateSeparatorItem[] = [];
|
|
14
|
+
let lastDate: string | null = null;
|
|
15
|
+
|
|
16
|
+
messages.forEach((message, index) => {
|
|
17
|
+
const createdAt = message.metadata?.created_at || new Date().toISOString();
|
|
18
|
+
const messageDate = new Date(createdAt).toDateString();
|
|
19
|
+
|
|
20
|
+
// Add date separator if date has changed
|
|
21
|
+
if (messageDate !== lastDate) {
|
|
22
|
+
result.push({
|
|
23
|
+
type: 'date',
|
|
24
|
+
data: createdAt,
|
|
25
|
+
key: `date-${messageDate}`
|
|
26
|
+
});
|
|
27
|
+
lastDate = messageDate;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Use global index for stable keys across window shifts
|
|
31
|
+
result.push({
|
|
32
|
+
type: 'message',
|
|
33
|
+
data: message,
|
|
34
|
+
key: `message-${startIndex + index}`
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import type { SDKMessageFormatter } from '$shared/types/database/schema';
|
|
2
|
+
import {
|
|
3
|
+
shouldFilterMessage,
|
|
4
|
+
extractToolUses,
|
|
5
|
+
extractToolResults
|
|
6
|
+
} from './message-processor';
|
|
7
|
+
import { processToolMessage } from './tool-handler';
|
|
8
|
+
|
|
9
|
+
// Tool group for mapping tool_use with tool_result
|
|
10
|
+
export interface ToolGroup {
|
|
11
|
+
toolUseMessage: SDKMessageFormatter;
|
|
12
|
+
toolResultMessage: SDKMessageFormatter | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Background bash session data
|
|
16
|
+
export interface BackgroundBashData {
|
|
17
|
+
bashToolId: string;
|
|
18
|
+
bashOutputs: any[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Processed message type
|
|
22
|
+
export type ProcessedMessage = SDKMessageFormatter;
|
|
23
|
+
|
|
24
|
+
// Group tool_use and tool_result messages together
|
|
25
|
+
export function groupMessages(messages: SDKMessageFormatter[]): {
|
|
26
|
+
groups: ProcessedMessage[],
|
|
27
|
+
toolUseMap: Map<string, ToolGroup>
|
|
28
|
+
} {
|
|
29
|
+
const groups: ProcessedMessage[] = [];
|
|
30
|
+
const toolUseMap = new Map<string, ToolGroup>();
|
|
31
|
+
|
|
32
|
+
messages.forEach(message => {
|
|
33
|
+
// Skip messages that should be filtered
|
|
34
|
+
if (shouldFilterMessage(message)) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Handle assistant messages with tool_use
|
|
39
|
+
if (message.type === 'assistant' && 'message' in message && message.message?.content) {
|
|
40
|
+
const toolUses = extractToolUses(message.message.content);
|
|
41
|
+
|
|
42
|
+
if (toolUses.length > 0) {
|
|
43
|
+
// Store tool_use messages for grouping
|
|
44
|
+
toolUses.forEach((toolUse: any) => {
|
|
45
|
+
if (toolUse.id) {
|
|
46
|
+
toolUseMap.set(toolUse.id, {
|
|
47
|
+
toolUseMessage: message,
|
|
48
|
+
toolResultMessage: null
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
groups.push(message as ProcessedMessage);
|
|
53
|
+
} else {
|
|
54
|
+
groups.push(message as ProcessedMessage);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Handle user messages with tool_result
|
|
58
|
+
else if (message.type === 'user' && 'message' in message && message.message?.content) {
|
|
59
|
+
const toolResults = extractToolResults(message.message.content);
|
|
60
|
+
|
|
61
|
+
if (toolResults.length > 0) {
|
|
62
|
+
// Group tool_result with corresponding tool_use
|
|
63
|
+
toolResults.forEach((toolResult: any) => {
|
|
64
|
+
if (toolResult.tool_use_id && toolUseMap.has(toolResult.tool_use_id)) {
|
|
65
|
+
const group = toolUseMap.get(toolResult.tool_use_id);
|
|
66
|
+
if (group) {
|
|
67
|
+
group.toolResultMessage = message;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
// Don't add tool_result messages separately
|
|
72
|
+
} else {
|
|
73
|
+
// Regular user message
|
|
74
|
+
groups.push(message as ProcessedMessage);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Include stream_event and other messages
|
|
78
|
+
else {
|
|
79
|
+
groups.push(message as ProcessedMessage);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return { groups, toolUseMap };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Add tool results to messages
|
|
87
|
+
export function embedToolResults(
|
|
88
|
+
groups: ProcessedMessage[],
|
|
89
|
+
toolUseMap: Map<string, ToolGroup>
|
|
90
|
+
): ProcessedMessage[] {
|
|
91
|
+
// Track background bash sessions
|
|
92
|
+
const backgroundBashMap = trackBackgroundBashSessions(groups, toolUseMap);
|
|
93
|
+
|
|
94
|
+
// Create combined messages with tool_use including $result property
|
|
95
|
+
return groups.map(message => {
|
|
96
|
+
if (message.type === 'assistant' && 'message' in message && message.message?.content) {
|
|
97
|
+
const toolUses = extractToolUses(message.message.content);
|
|
98
|
+
|
|
99
|
+
if (toolUses.length > 0) {
|
|
100
|
+
const processedMessage = processToolMessage(
|
|
101
|
+
message,
|
|
102
|
+
toolUseMap,
|
|
103
|
+
backgroundBashMap
|
|
104
|
+
);
|
|
105
|
+
return processedMessage;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return message;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Track background bash sessions and their outputs
|
|
114
|
+
function trackBackgroundBashSessions(
|
|
115
|
+
groups: ProcessedMessage[],
|
|
116
|
+
toolUseMap: Map<string, ToolGroup>
|
|
117
|
+
): Map<string, BackgroundBashData> {
|
|
118
|
+
const backgroundBashMap = new Map<string, BackgroundBashData>();
|
|
119
|
+
|
|
120
|
+
groups.forEach(message => {
|
|
121
|
+
if (message.type === 'assistant' && 'message' in message && message.message?.content) {
|
|
122
|
+
const contentArray = Array.isArray(message.message.content)
|
|
123
|
+
? message.message.content
|
|
124
|
+
: [message.message.content];
|
|
125
|
+
|
|
126
|
+
contentArray.forEach((item) => {
|
|
127
|
+
if (typeof item === 'object' && item && 'type' in item && item.type === 'tool_use') {
|
|
128
|
+
const toolUse = item as any;
|
|
129
|
+
// Check for Bash with run_in_background
|
|
130
|
+
if (toolUse.name === 'Bash' && toolUse.input &&
|
|
131
|
+
typeof toolUse.input === 'object' &&
|
|
132
|
+
'run_in_background' in toolUse.input &&
|
|
133
|
+
toolUse.input.run_in_background) {
|
|
134
|
+
trackBackgroundBash(toolUse, toolUseMap, backgroundBashMap);
|
|
135
|
+
}
|
|
136
|
+
// Collect all BashOutput results
|
|
137
|
+
else if (toolUse.name === 'BashOutput' && toolUse.input &&
|
|
138
|
+
typeof toolUse.input === 'object' &&
|
|
139
|
+
'bash_id' in toolUse.input) {
|
|
140
|
+
trackBashOutput(toolUse, toolUseMap, backgroundBashMap);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return backgroundBashMap;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function trackBackgroundBash(
|
|
151
|
+
item: any,
|
|
152
|
+
toolUseMap: Map<string, ToolGroup>,
|
|
153
|
+
backgroundBashMap: Map<string, BackgroundBashData>
|
|
154
|
+
): void {
|
|
155
|
+
const toolId = item.id;
|
|
156
|
+
if (!toolId || !toolUseMap.has(toolId)) return;
|
|
157
|
+
|
|
158
|
+
const group = toolUseMap.get(toolId);
|
|
159
|
+
if (!group?.toolResultMessage) return;
|
|
160
|
+
|
|
161
|
+
const resultMessage = group.toolResultMessage as any;
|
|
162
|
+
const resultContent = resultMessage.message ?
|
|
163
|
+
(Array.isArray(resultMessage.message.content) ? resultMessage.message.content : [resultMessage.message.content]) : [];
|
|
164
|
+
|
|
165
|
+
const toolResult = resultContent.find((resultItem: any) =>
|
|
166
|
+
typeof resultItem === 'object' &&
|
|
167
|
+
resultItem &&
|
|
168
|
+
'type' in resultItem &&
|
|
169
|
+
resultItem.type === 'tool_result' &&
|
|
170
|
+
'tool_use_id' in resultItem &&
|
|
171
|
+
resultItem.tool_use_id === toolId
|
|
172
|
+
) as any | undefined;
|
|
173
|
+
|
|
174
|
+
if (toolResult?.content && typeof toolResult.content === 'string') {
|
|
175
|
+
// Extract bash ID from "Command running in background with ID: xxxxx"
|
|
176
|
+
const idMatch = toolResult.content.match(/Command running in background with ID:\s*(\w+)/);
|
|
177
|
+
if (idMatch) {
|
|
178
|
+
const bashId = idMatch[1];
|
|
179
|
+
backgroundBashMap.set(bashId, {
|
|
180
|
+
bashToolId: toolId,
|
|
181
|
+
bashOutputs: []
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function trackBashOutput(
|
|
188
|
+
item: any,
|
|
189
|
+
toolUseMap: Map<string, ToolGroup>,
|
|
190
|
+
backgroundBashMap: Map<string, BackgroundBashData>
|
|
191
|
+
): void {
|
|
192
|
+
const bashId = (item.input as any).bash_id as string;
|
|
193
|
+
const toolId = item.id;
|
|
194
|
+
|
|
195
|
+
if (!toolId || !toolUseMap.has(toolId)) return;
|
|
196
|
+
|
|
197
|
+
const group = toolUseMap.get(toolId);
|
|
198
|
+
if (!group?.toolResultMessage) return;
|
|
199
|
+
|
|
200
|
+
const resultMessage = group.toolResultMessage as any;
|
|
201
|
+
const resultContent = resultMessage.message ?
|
|
202
|
+
(Array.isArray(resultMessage.message.content) ? resultMessage.message.content : [resultMessage.message.content]) : [];
|
|
203
|
+
|
|
204
|
+
const toolResult = resultContent.find((resultItem: any) =>
|
|
205
|
+
typeof resultItem === 'object' &&
|
|
206
|
+
resultItem &&
|
|
207
|
+
'type' in resultItem &&
|
|
208
|
+
resultItem.type === 'tool_result' &&
|
|
209
|
+
'tool_use_id' in resultItem &&
|
|
210
|
+
resultItem.tool_use_id === toolId
|
|
211
|
+
) as any | undefined;
|
|
212
|
+
|
|
213
|
+
if (toolResult && backgroundBashMap.has(bashId)) {
|
|
214
|
+
const bashData = backgroundBashMap.get(bashId);
|
|
215
|
+
if (bashData) {
|
|
216
|
+
bashData.bashOutputs.push(toolResult);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { SDKMessageFormatter } from '$shared/types/database/schema';
|
|
2
|
+
import type { ToolInput } from '$shared/types/messaging';
|
|
3
|
+
|
|
4
|
+
// Content that can be either single or array
|
|
5
|
+
export type MessageContentArray = any[] | any | string;
|
|
6
|
+
|
|
7
|
+
// Helper type guards
|
|
8
|
+
export function isToolUseBlock(item: unknown): boolean {
|
|
9
|
+
return (
|
|
10
|
+
typeof item === 'object' &&
|
|
11
|
+
item !== null &&
|
|
12
|
+
'type' in item &&
|
|
13
|
+
(item as any).type === 'tool_use'
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isToolResultBlock(item: unknown): boolean {
|
|
18
|
+
return (
|
|
19
|
+
typeof item === 'object' &&
|
|
20
|
+
item !== null &&
|
|
21
|
+
'type' in item &&
|
|
22
|
+
(item as any).type === 'tool_result'
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Ensure content is always an array
|
|
27
|
+
export function normalizeContent(content: MessageContentArray): any[] {
|
|
28
|
+
if (Array.isArray(content)) {
|
|
29
|
+
return content;
|
|
30
|
+
}
|
|
31
|
+
if (typeof content === 'string') {
|
|
32
|
+
return [{ type: 'text', text: content }];
|
|
33
|
+
}
|
|
34
|
+
return [content];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// List of tool names that should include tool_result in content
|
|
38
|
+
export const TOOLS_WITH_RESULTS: ToolInput['name'][] = [
|
|
39
|
+
'Bash',
|
|
40
|
+
'TaskOutput',
|
|
41
|
+
'Edit',
|
|
42
|
+
'ExitPlanMode',
|
|
43
|
+
'Glob',
|
|
44
|
+
'Grep',
|
|
45
|
+
'KillShell',
|
|
46
|
+
'ListMcpResources',
|
|
47
|
+
'NotebookEdit',
|
|
48
|
+
'ReadMcpResource',
|
|
49
|
+
'Read',
|
|
50
|
+
'Task',
|
|
51
|
+
'TodoWrite',
|
|
52
|
+
'WebFetch',
|
|
53
|
+
'WebSearch',
|
|
54
|
+
'Write'
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
// Tools that should be hidden from display
|
|
58
|
+
export const HIDDEN_TOOLS: ToolInput['name'][] = [
|
|
59
|
+
'TaskOutput',
|
|
60
|
+
'TodoWrite'
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
// Check if a message should be filtered out
|
|
64
|
+
export function shouldFilterMessage(message: SDKMessageFormatter): boolean {
|
|
65
|
+
// Skip system and result type messages
|
|
66
|
+
if (message.type === 'system' || message.type === 'result') {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Filter out stream_event messages with no partial text
|
|
71
|
+
if (message.type === 'stream_event') {
|
|
72
|
+
if (!('partialText' in message) || !message.partialText) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Filter out assistant messages with no visible content
|
|
78
|
+
if (message.type === 'assistant') {
|
|
79
|
+
// No message property at all
|
|
80
|
+
if (!('message' in message) || !message.message) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const content = message.message.content;
|
|
85
|
+
|
|
86
|
+
// No content or falsy content
|
|
87
|
+
if (!content) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (Array.isArray(content)) {
|
|
92
|
+
// Empty content array
|
|
93
|
+
if (content.length === 0) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
// Check if there's any meaningful visible content
|
|
97
|
+
const hasNonEmptyText = content.some((item: any) =>
|
|
98
|
+
item.type === 'text' && item.text && item.text.trim().length > 0
|
|
99
|
+
);
|
|
100
|
+
const hasToolUse = content.some((item: any) => item.type === 'tool_use');
|
|
101
|
+
// Filter if no meaningful text and no tool_use blocks
|
|
102
|
+
if (!hasNonEmptyText && !hasToolUse) {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Extract tool uses from message content
|
|
112
|
+
export function extractToolUses(content: MessageContentArray): any[] {
|
|
113
|
+
const contentArray = normalizeContent(content);
|
|
114
|
+
return contentArray.filter(isToolUseBlock);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Extract tool results from message content
|
|
118
|
+
export function extractToolResults(content: MessageContentArray): any[] {
|
|
119
|
+
const contentArray = normalizeContent(content);
|
|
120
|
+
return contentArray.filter(isToolResultBlock);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Check if a tool should have its result embedded
|
|
124
|
+
export function shouldEmbedResult(toolName: string): boolean {
|
|
125
|
+
// Custom MCP tools always embed results (they start with 'mcp__')
|
|
126
|
+
if (toolName.startsWith('mcp__')) {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
return TOOLS_WITH_RESULTS.includes(toolName as ToolInput['name']);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Check if a tool should be hidden
|
|
133
|
+
export function shouldHideTool(toolName: string): boolean {
|
|
134
|
+
return HIDDEN_TOOLS.includes(toolName as ToolInput['name']);
|
|
135
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import {
|
|
2
|
+
shouldEmbedResult,
|
|
3
|
+
shouldHideTool
|
|
4
|
+
} from './message-processor';
|
|
5
|
+
import type {
|
|
6
|
+
ProcessedMessage,
|
|
7
|
+
ToolGroup,
|
|
8
|
+
BackgroundBashData
|
|
9
|
+
} from './message-grouper';
|
|
10
|
+
|
|
11
|
+
// Extended ToolUse with embedded result
|
|
12
|
+
export interface ToolUseWithResult {
|
|
13
|
+
type: 'tool_use';
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
input: any;
|
|
17
|
+
$result?: any;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Process a tool message with embedded results
|
|
21
|
+
export function processToolMessage(
|
|
22
|
+
message: ProcessedMessage,
|
|
23
|
+
toolUseMap: Map<string, ToolGroup>,
|
|
24
|
+
backgroundBashMap: Map<string, BackgroundBashData>
|
|
25
|
+
): ProcessedMessage {
|
|
26
|
+
const messageAny = message as any;
|
|
27
|
+
const content = messageAny.message?.content ?
|
|
28
|
+
(Array.isArray(messageAny.message.content) ? messageAny.message.content : [messageAny.message.content]) : [];
|
|
29
|
+
|
|
30
|
+
// Create modified content with embedded tool_result in tool_use objects
|
|
31
|
+
const modifiedContent = content
|
|
32
|
+
.map((item: any): any => {
|
|
33
|
+
if (typeof item === 'object' && item && 'type' in item && item.type === 'tool_use') {
|
|
34
|
+
return processToolUse(item, toolUseMap, backgroundBashMap);
|
|
35
|
+
}
|
|
36
|
+
return item;
|
|
37
|
+
})
|
|
38
|
+
.filter((item: any) => item !== null); // Remove null items (hidden tools)
|
|
39
|
+
|
|
40
|
+
// Return modified message with embedded tool_results
|
|
41
|
+
return {
|
|
42
|
+
...message,
|
|
43
|
+
message: {
|
|
44
|
+
...messageAny.message,
|
|
45
|
+
content: modifiedContent
|
|
46
|
+
}
|
|
47
|
+
} as ProcessedMessage;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Process individual tool_use item
|
|
51
|
+
function processToolUse(
|
|
52
|
+
item: any,
|
|
53
|
+
toolUseMap: Map<string, ToolGroup>,
|
|
54
|
+
backgroundBashMap: Map<string, BackgroundBashData>
|
|
55
|
+
): ToolUseWithResult | null {
|
|
56
|
+
// Hide certain tools completely
|
|
57
|
+
if (shouldHideTool(item.name)) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Special handling for Bash with run_in_background
|
|
62
|
+
if (item.name === 'Bash' && item.input &&
|
|
63
|
+
typeof item.input === 'object' &&
|
|
64
|
+
'run_in_background' in item.input &&
|
|
65
|
+
item.input.run_in_background && item.id) {
|
|
66
|
+
return handleBackgroundBash(item, toolUseMap, backgroundBashMap);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Regular tool handling
|
|
70
|
+
if (item.id && item.name && shouldEmbedResult(item.name) && toolUseMap.has(item.id)) {
|
|
71
|
+
return handleRegularTool(item, toolUseMap);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return item;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Handle background bash commands
|
|
78
|
+
function handleBackgroundBash(
|
|
79
|
+
item: any,
|
|
80
|
+
toolUseMap: Map<string, ToolGroup>,
|
|
81
|
+
backgroundBashMap: Map<string, BackgroundBashData>
|
|
82
|
+
): ToolUseWithResult {
|
|
83
|
+
const group = toolUseMap.get(item.id);
|
|
84
|
+
if (!group?.toolResultMessage) return item;
|
|
85
|
+
|
|
86
|
+
const resultMessage = group.toolResultMessage as any;
|
|
87
|
+
const resultContent = resultMessage.message ?
|
|
88
|
+
(Array.isArray(resultMessage.message.content) ? resultMessage.message.content : [resultMessage.message.content]) : [];
|
|
89
|
+
|
|
90
|
+
const toolResult = findToolResult(resultContent, item.id);
|
|
91
|
+
|
|
92
|
+
if (!toolResult?.content || typeof toolResult.content !== 'string') return item;
|
|
93
|
+
|
|
94
|
+
// Extract bash ID and check for BashOutput
|
|
95
|
+
const idMatch = toolResult.content.match(/Command running in background with ID:\s*(\w+)/);
|
|
96
|
+
if (!idMatch) return item;
|
|
97
|
+
|
|
98
|
+
const bashId = idMatch[1];
|
|
99
|
+
const bashData = backgroundBashMap.get(bashId);
|
|
100
|
+
|
|
101
|
+
if (bashData && bashData.bashOutputs.length > 0) {
|
|
102
|
+
// Use the last BashOutput result
|
|
103
|
+
const lastOutput = bashData.bashOutputs[bashData.bashOutputs.length - 1];
|
|
104
|
+
return {
|
|
105
|
+
...item,
|
|
106
|
+
$result: {
|
|
107
|
+
...toolResult,
|
|
108
|
+
content: lastOutput.content || ""
|
|
109
|
+
}
|
|
110
|
+
} as ToolUseWithResult;
|
|
111
|
+
} else {
|
|
112
|
+
// No BashOutput found, clear the content
|
|
113
|
+
return {
|
|
114
|
+
...item,
|
|
115
|
+
$result: {
|
|
116
|
+
...toolResult,
|
|
117
|
+
content: ""
|
|
118
|
+
}
|
|
119
|
+
} as ToolUseWithResult;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Handle regular tools
|
|
124
|
+
function handleRegularTool(
|
|
125
|
+
item: any,
|
|
126
|
+
toolUseMap: Map<string, ToolGroup>
|
|
127
|
+
): ToolUseWithResult {
|
|
128
|
+
const group = toolUseMap.get(item.id);
|
|
129
|
+
if (!group || !group.toolResultMessage) return item;
|
|
130
|
+
|
|
131
|
+
const resultMessage = group.toolResultMessage as any;
|
|
132
|
+
const resultContent = resultMessage.message ?
|
|
133
|
+
(Array.isArray(resultMessage.message.content) ? resultMessage.message.content : [resultMessage.message.content]) : [];
|
|
134
|
+
|
|
135
|
+
const toolResult = findToolResult(resultContent, item.id);
|
|
136
|
+
|
|
137
|
+
if (toolResult) {
|
|
138
|
+
// Embed tool_result as $result property in tool_use object
|
|
139
|
+
return {
|
|
140
|
+
...item,
|
|
141
|
+
$result: toolResult
|
|
142
|
+
} as ToolUseWithResult;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return item;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Helper to find tool result by id
|
|
149
|
+
function findToolResult(
|
|
150
|
+
content: any[],
|
|
151
|
+
toolUseId: string
|
|
152
|
+
): any {
|
|
153
|
+
return content.find((resultItem: any) =>
|
|
154
|
+
typeof resultItem === 'object' &&
|
|
155
|
+
resultItem !== null &&
|
|
156
|
+
'type' in resultItem &&
|
|
157
|
+
resultItem.type === 'tool_result' &&
|
|
158
|
+
'tool_use_id' in resultItem &&
|
|
159
|
+
resultItem.tool_use_id === toolUseId
|
|
160
|
+
);
|
|
161
|
+
}
|