orquesta-cli 0.1.13 → 0.1.15
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/README.md +30 -4
- package/dist/cli.js +65 -4
- package/dist/core/config/config-manager.d.ts +13 -1
- package/dist/core/config/config-manager.js +83 -0
- package/dist/core/slash-command-handler.d.ts +1 -0
- package/dist/core/slash-command-handler.js +129 -0
- package/dist/orquesta/config-sync.d.ts +73 -0
- package/dist/orquesta/config-sync.js +230 -0
- package/dist/orquesta/prompt-reporter.d.ts +16 -0
- package/dist/orquesta/prompt-reporter.js +85 -0
- package/dist/setup/first-run-setup.d.ts +15 -0
- package/dist/setup/first-run-setup.js +238 -0
- package/dist/types/index.d.ts +11 -2
- package/dist/ui/TodoPanel.d.ts +1 -0
- package/dist/ui/TodoPanel.js +6 -1
- package/dist/ui/components/LLMSetupWizard.js +381 -7
- package/dist/ui/components/Logo.d.ts +2 -0
- package/dist/ui/components/Logo.js +10 -3
- package/dist/ui/components/OpenRouterModelBrowser.d.ts +13 -0
- package/dist/ui/components/OpenRouterModelBrowser.js +221 -0
- package/dist/ui/components/PlanExecuteApp.js +30 -4
- package/dist/ui/components/ProjectSelector.d.ts +8 -0
- package/dist/ui/components/ProjectSelector.js +119 -0
- package/dist/ui/components/StatusBar.d.ts +2 -0
- package/dist/ui/components/StatusBar.js +6 -1
- package/dist/ui/hooks/slashCommandProcessor.js +8 -4
- package/package.json +11 -5
- package/.eslintrc.json +0 -26
- package/.prettierrc.json +0 -10
- package/CLAUDE.md +0 -199
- package/SECURITY.md +0 -290
- package/TEST_LOCAL.md +0 -245
- package/dist/agents/base/base-agent.d.ts.map +0 -1
- package/dist/agents/base/base-agent.js.map +0 -1
- package/dist/agents/docs-search/index.d.ts.map +0 -1
- package/dist/agents/docs-search/index.js.map +0 -1
- package/dist/agents/index.d.ts.map +0 -1
- package/dist/agents/index.js.map +0 -1
- package/dist/agents/planner/index.d.ts.map +0 -1
- package/dist/agents/planner/index.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/core/compact/compact-manager.d.ts.map +0 -1
- package/dist/core/compact/compact-manager.js.map +0 -1
- package/dist/core/compact/compact-prompts.d.ts.map +0 -1
- package/dist/core/compact/compact-prompts.js.map +0 -1
- package/dist/core/compact/context-tracker.d.ts.map +0 -1
- package/dist/core/compact/context-tracker.js.map +0 -1
- package/dist/core/compact/index.d.ts.map +0 -1
- package/dist/core/compact/index.js.map +0 -1
- package/dist/core/config/config-manager.d.ts.map +0 -1
- package/dist/core/config/config-manager.js.map +0 -1
- package/dist/core/config/index.d.ts.map +0 -1
- package/dist/core/config/index.js.map +0 -1
- package/dist/core/docs-manager.d.ts.map +0 -1
- package/dist/core/docs-manager.js.map +0 -1
- package/dist/core/git-auto-updater.d.ts +0 -58
- package/dist/core/git-auto-updater.d.ts.map +0 -1
- package/dist/core/git-auto-updater.js +0 -374
- package/dist/core/git-auto-updater.js.map +0 -1
- package/dist/core/llm/index.d.ts.map +0 -1
- package/dist/core/llm/index.js.map +0 -1
- package/dist/core/llm/llm-client.d.ts.map +0 -1
- package/dist/core/llm/llm-client.js.map +0 -1
- package/dist/core/session/index.d.ts.map +0 -1
- package/dist/core/session/index.js.map +0 -1
- package/dist/core/session/session-manager.d.ts.map +0 -1
- package/dist/core/session/session-manager.js.map +0 -1
- package/dist/core/slash-command-handler.d.ts.map +0 -1
- package/dist/core/slash-command-handler.js.map +0 -1
- package/dist/core/usage-tracker.d.ts.map +0 -1
- package/dist/core/usage-tracker.js.map +0 -1
- package/dist/errors/base.d.ts.map +0 -1
- package/dist/errors/base.js.map +0 -1
- package/dist/errors/file.d.ts.map +0 -1
- package/dist/errors/file.js.map +0 -1
- package/dist/errors/index.d.ts.map +0 -1
- package/dist/errors/index.js.map +0 -1
- package/dist/errors/llm.d.ts.map +0 -1
- package/dist/errors/llm.js.map +0 -1
- package/dist/errors/network.d.ts.map +0 -1
- package/dist/errors/network.js.map +0 -1
- package/dist/errors/validation.d.ts.map +0 -1
- package/dist/errors/validation.js.map +0 -1
- package/dist/eval/eval-runner.d.ts.map +0 -1
- package/dist/eval/eval-runner.js.map +0 -1
- package/dist/eval/index.d.ts.map +0 -1
- package/dist/eval/index.js.map +0 -1
- package/dist/eval/types.d.ts.map +0 -1
- package/dist/eval/types.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/orchestration/index.d.ts.map +0 -1
- package/dist/orchestration/index.js.map +0 -1
- package/dist/orchestration/plan-executor.d.ts.map +0 -1
- package/dist/orchestration/plan-executor.js.map +0 -1
- package/dist/orchestration/types.d.ts.map +0 -1
- package/dist/orchestration/types.js.map +0 -1
- package/dist/orchestration/utils.d.ts.map +0 -1
- package/dist/orchestration/utils.js.map +0 -1
- package/dist/orquesta/connection.d.ts.map +0 -1
- package/dist/orquesta/connection.js.map +0 -1
- package/dist/prompts/agents/docs-search-decision.d.ts.map +0 -1
- package/dist/prompts/agents/docs-search-decision.js.map +0 -1
- package/dist/prompts/agents/docs-search.d.ts.map +0 -1
- package/dist/prompts/agents/docs-search.js.map +0 -1
- package/dist/prompts/agents/planning.d.ts.map +0 -1
- package/dist/prompts/agents/planning.js.map +0 -1
- package/dist/prompts/index.d.ts.map +0 -1
- package/dist/prompts/index.js.map +0 -1
- package/dist/prompts/shared/codebase-rules.d.ts.map +0 -1
- package/dist/prompts/shared/codebase-rules.js.map +0 -1
- package/dist/prompts/shared/git-rules.d.ts.map +0 -1
- package/dist/prompts/shared/git-rules.js.map +0 -1
- package/dist/prompts/shared/language-rules.d.ts.map +0 -1
- package/dist/prompts/shared/language-rules.js.map +0 -1
- package/dist/prompts/shared/tool-usage.d.ts.map +0 -1
- package/dist/prompts/shared/tool-usage.js.map +0 -1
- package/dist/prompts/system/compact.d.ts.map +0 -1
- package/dist/prompts/system/compact.js.map +0 -1
- package/dist/prompts/system/plan-execute.d.ts.map +0 -1
- package/dist/prompts/system/plan-execute.js.map +0 -1
- package/dist/tools/browser/browser-client.d.ts.map +0 -1
- package/dist/tools/browser/browser-client.js.map +0 -1
- package/dist/tools/browser/browser-tools.d.ts.map +0 -1
- package/dist/tools/browser/browser-tools.js.map +0 -1
- package/dist/tools/browser/index.d.ts.map +0 -1
- package/dist/tools/browser/index.js.map +0 -1
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js.map +0 -1
- package/dist/tools/llm/agents/docs-search-tools.d.ts.map +0 -1
- package/dist/tools/llm/agents/docs-search-tools.js.map +0 -1
- package/dist/tools/llm/agents/index.d.ts.map +0 -1
- package/dist/tools/llm/agents/index.js.map +0 -1
- package/dist/tools/llm/index.d.ts.map +0 -1
- package/dist/tools/llm/index.js.map +0 -1
- package/dist/tools/llm/simple/ask-user-tool.d.ts.map +0 -1
- package/dist/tools/llm/simple/ask-user-tool.js.map +0 -1
- package/dist/tools/llm/simple/background-bash-tool.d.ts.map +0 -1
- package/dist/tools/llm/simple/background-bash-tool.js.map +0 -1
- package/dist/tools/llm/simple/background-powershell-tool.d.ts.map +0 -1
- package/dist/tools/llm/simple/background-powershell-tool.js.map +0 -1
- package/dist/tools/llm/simple/bash-tool.d.ts.map +0 -1
- package/dist/tools/llm/simple/bash-tool.js.map +0 -1
- package/dist/tools/llm/simple/docs-search-agent-tool.d.ts.map +0 -1
- package/dist/tools/llm/simple/docs-search-agent-tool.js.map +0 -1
- package/dist/tools/llm/simple/file-tools.d.ts.map +0 -1
- package/dist/tools/llm/simple/file-tools.js.map +0 -1
- package/dist/tools/llm/simple/final-response-tool.d.ts.map +0 -1
- package/dist/tools/llm/simple/final-response-tool.js.map +0 -1
- package/dist/tools/llm/simple/index.d.ts.map +0 -1
- package/dist/tools/llm/simple/index.js.map +0 -1
- package/dist/tools/llm/simple/planning-tools.d.ts.map +0 -1
- package/dist/tools/llm/simple/planning-tools.js.map +0 -1
- package/dist/tools/llm/simple/powershell-tool.d.ts.map +0 -1
- package/dist/tools/llm/simple/powershell-tool.js.map +0 -1
- package/dist/tools/llm/simple/simple-tool-executor.d.ts.map +0 -1
- package/dist/tools/llm/simple/simple-tool-executor.js.map +0 -1
- package/dist/tools/llm/simple/todo-tools.d.ts.map +0 -1
- package/dist/tools/llm/simple/todo-tools.js.map +0 -1
- package/dist/tools/llm/simple/user-interaction-tools.d.ts.map +0 -1
- package/dist/tools/llm/simple/user-interaction-tools.js.map +0 -1
- package/dist/tools/office/common/constants.d.ts.map +0 -1
- package/dist/tools/office/common/constants.js.map +0 -1
- package/dist/tools/office/common/index.d.ts.map +0 -1
- package/dist/tools/office/common/index.js.map +0 -1
- package/dist/tools/office/common/types.d.ts.map +0 -1
- package/dist/tools/office/common/types.js.map +0 -1
- package/dist/tools/office/common/utils.d.ts.map +0 -1
- package/dist/tools/office/common/utils.js.map +0 -1
- package/dist/tools/office/excel-client.d.ts.map +0 -1
- package/dist/tools/office/excel-client.js.map +0 -1
- package/dist/tools/office/excel-tools/cells.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/cells.js.map +0 -1
- package/dist/tools/office/excel-tools/charts.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/charts.js.map +0 -1
- package/dist/tools/office/excel-tools/comments.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/comments.js.map +0 -1
- package/dist/tools/office/excel-tools/data-ops.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/data-ops.js.map +0 -1
- package/dist/tools/office/excel-tools/export.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/export.js.map +0 -1
- package/dist/tools/office/excel-tools/formatting.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/formatting.js.map +0 -1
- package/dist/tools/office/excel-tools/index.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/index.js.map +0 -1
- package/dist/tools/office/excel-tools/launch.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/launch.js.map +0 -1
- package/dist/tools/office/excel-tools/media.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/media.js.map +0 -1
- package/dist/tools/office/excel-tools/named-ranges.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/named-ranges.js.map +0 -1
- package/dist/tools/office/excel-tools/protection.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/protection.js.map +0 -1
- package/dist/tools/office/excel-tools/rows-columns.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/rows-columns.js.map +0 -1
- package/dist/tools/office/excel-tools/sheets.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/sheets.js.map +0 -1
- package/dist/tools/office/excel-tools/validation.d.ts.map +0 -1
- package/dist/tools/office/excel-tools/validation.js.map +0 -1
- package/dist/tools/office/excel-tools.d.ts.map +0 -1
- package/dist/tools/office/excel-tools.js.map +0 -1
- package/dist/tools/office/index.d.ts.map +0 -1
- package/dist/tools/office/index.js.map +0 -1
- package/dist/tools/office/office-client-base.d.ts.map +0 -1
- package/dist/tools/office/office-client-base.js.map +0 -1
- package/dist/tools/office/office-client.d.ts.map +0 -1
- package/dist/tools/office/office-client.js.map +0 -1
- package/dist/tools/office/powerpoint-client.d.ts.map +0 -1
- package/dist/tools/office/powerpoint-client.js.map +0 -1
- package/dist/tools/office/powerpoint-tools/effects.d.ts.map +0 -1
- package/dist/tools/office/powerpoint-tools/effects.js.map +0 -1
- package/dist/tools/office/powerpoint-tools/export.d.ts.map +0 -1
- package/dist/tools/office/powerpoint-tools/export.js.map +0 -1
- package/dist/tools/office/powerpoint-tools/index.d.ts.map +0 -1
- package/dist/tools/office/powerpoint-tools/index.js.map +0 -1
- package/dist/tools/office/powerpoint-tools/launch.d.ts.map +0 -1
- package/dist/tools/office/powerpoint-tools/launch.js.map +0 -1
- package/dist/tools/office/powerpoint-tools/media.d.ts.map +0 -1
- package/dist/tools/office/powerpoint-tools/media.js.map +0 -1
- package/dist/tools/office/powerpoint-tools/notes.d.ts.map +0 -1
- package/dist/tools/office/powerpoint-tools/notes.js.map +0 -1
- package/dist/tools/office/powerpoint-tools/sections.d.ts.map +0 -1
- package/dist/tools/office/powerpoint-tools/sections.js.map +0 -1
- package/dist/tools/office/powerpoint-tools/shapes.d.ts.map +0 -1
- package/dist/tools/office/powerpoint-tools/shapes.js.map +0 -1
- package/dist/tools/office/powerpoint-tools/slides.d.ts.map +0 -1
- package/dist/tools/office/powerpoint-tools/slides.js.map +0 -1
- package/dist/tools/office/powerpoint-tools/tables.d.ts.map +0 -1
- package/dist/tools/office/powerpoint-tools/tables.js.map +0 -1
- package/dist/tools/office/powerpoint-tools/text.d.ts.map +0 -1
- package/dist/tools/office/powerpoint-tools/text.js.map +0 -1
- package/dist/tools/office/powerpoint-tools.d.ts.map +0 -1
- package/dist/tools/office/powerpoint-tools.js.map +0 -1
- package/dist/tools/office/word-client.d.ts.map +0 -1
- package/dist/tools/office/word-client.js.map +0 -1
- package/dist/tools/office/word-tools/bookmarks.d.ts.map +0 -1
- package/dist/tools/office/word-tools/bookmarks.js.map +0 -1
- package/dist/tools/office/word-tools/comments.d.ts.map +0 -1
- package/dist/tools/office/word-tools/comments.js.map +0 -1
- package/dist/tools/office/word-tools/content.d.ts.map +0 -1
- package/dist/tools/office/word-tools/content.js.map +0 -1
- package/dist/tools/office/word-tools/export.d.ts.map +0 -1
- package/dist/tools/office/word-tools/export.js.map +0 -1
- package/dist/tools/office/word-tools/formatting.d.ts.map +0 -1
- package/dist/tools/office/word-tools/formatting.js.map +0 -1
- package/dist/tools/office/word-tools/headers-footers.d.ts.map +0 -1
- package/dist/tools/office/word-tools/headers-footers.js.map +0 -1
- package/dist/tools/office/word-tools/index.d.ts.map +0 -1
- package/dist/tools/office/word-tools/index.js.map +0 -1
- package/dist/tools/office/word-tools/launch.d.ts.map +0 -1
- package/dist/tools/office/word-tools/launch.js.map +0 -1
- package/dist/tools/office/word-tools/lists.d.ts.map +0 -1
- package/dist/tools/office/word-tools/lists.js.map +0 -1
- package/dist/tools/office/word-tools/navigation.d.ts.map +0 -1
- package/dist/tools/office/word-tools/navigation.js.map +0 -1
- package/dist/tools/office/word-tools/page-setup.d.ts.map +0 -1
- package/dist/tools/office/word-tools/page-setup.js.map +0 -1
- package/dist/tools/office/word-tools/tables.d.ts.map +0 -1
- package/dist/tools/office/word-tools/tables.js.map +0 -1
- package/dist/tools/office/word-tools/text.d.ts.map +0 -1
- package/dist/tools/office/word-tools/text.js.map +0 -1
- package/dist/tools/office/word-tools/undo-redo.d.ts.map +0 -1
- package/dist/tools/office/word-tools/undo-redo.js.map +0 -1
- package/dist/tools/office/word-tools/watermarks.d.ts.map +0 -1
- package/dist/tools/office/word-tools/watermarks.js.map +0 -1
- package/dist/tools/office/word-tools.d.ts.map +0 -1
- package/dist/tools/office/word-tools.js.map +0 -1
- package/dist/tools/registry.d.ts.map +0 -1
- package/dist/tools/registry.js.map +0 -1
- package/dist/tools/types.d.ts.map +0 -1
- package/dist/tools/types.js.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js.map +0 -1
- package/dist/ui/PlanExecuteView.d.ts.map +0 -1
- package/dist/ui/PlanExecuteView.js.map +0 -1
- package/dist/ui/TodoPanel.d.ts.map +0 -1
- package/dist/ui/TodoPanel.js.map +0 -1
- package/dist/ui/UpdateNotification.d.ts.map +0 -1
- package/dist/ui/UpdateNotification.js.map +0 -1
- package/dist/ui/components/ActivityIndicator.d.ts.map +0 -1
- package/dist/ui/components/ActivityIndicator.js.map +0 -1
- package/dist/ui/components/CommandBrowser.d.ts.map +0 -1
- package/dist/ui/components/CommandBrowser.js.map +0 -1
- package/dist/ui/components/CustomTextInput.d.ts.map +0 -1
- package/dist/ui/components/CustomTextInput.js.map +0 -1
- package/dist/ui/components/DocsSearchProgress.d.ts.map +0 -1
- package/dist/ui/components/DocsSearchProgress.js.map +0 -1
- package/dist/ui/components/FileBrowser.d.ts.map +0 -1
- package/dist/ui/components/FileBrowser.js.map +0 -1
- package/dist/ui/components/LLMSetupWizard.d.ts.map +0 -1
- package/dist/ui/components/LLMSetupWizard.js.map +0 -1
- package/dist/ui/components/Logo.d.ts.map +0 -1
- package/dist/ui/components/Logo.js.map +0 -1
- package/dist/ui/components/MarkdownRenderer.d.ts.map +0 -1
- package/dist/ui/components/MarkdownRenderer.js.map +0 -1
- package/dist/ui/components/ModelSelector.d.ts.map +0 -1
- package/dist/ui/components/ModelSelector.js.map +0 -1
- package/dist/ui/components/PlanExecuteApp.d.ts.map +0 -1
- package/dist/ui/components/PlanExecuteApp.js.map +0 -1
- package/dist/ui/components/ProgressBar.d.ts.map +0 -1
- package/dist/ui/components/ProgressBar.js.map +0 -1
- package/dist/ui/components/StatusBar.d.ts.map +0 -1
- package/dist/ui/components/StatusBar.js.map +0 -1
- package/dist/ui/components/ThinkingIndicator.d.ts.map +0 -1
- package/dist/ui/components/ThinkingIndicator.js.map +0 -1
- package/dist/ui/components/TodoListView.d.ts.map +0 -1
- package/dist/ui/components/TodoListView.js.map +0 -1
- package/dist/ui/components/ToolSelector.d.ts.map +0 -1
- package/dist/ui/components/ToolSelector.js.map +0 -1
- package/dist/ui/components/dialogs/ApprovalDialog.d.ts.map +0 -1
- package/dist/ui/components/dialogs/ApprovalDialog.js.map +0 -1
- package/dist/ui/components/dialogs/AskUserDialog.d.ts.map +0 -1
- package/dist/ui/components/dialogs/AskUserDialog.js.map +0 -1
- package/dist/ui/components/dialogs/DocsBrowser.d.ts.map +0 -1
- package/dist/ui/components/dialogs/DocsBrowser.js.map +0 -1
- package/dist/ui/components/dialogs/SettingsDialog.d.ts.map +0 -1
- package/dist/ui/components/dialogs/SettingsDialog.js.map +0 -1
- package/dist/ui/components/dialogs/index.d.ts.map +0 -1
- package/dist/ui/components/dialogs/index.js.map +0 -1
- package/dist/ui/components/index.d.ts.map +0 -1
- package/dist/ui/components/index.js.map +0 -1
- package/dist/ui/components/panels/LogPanel.d.ts.map +0 -1
- package/dist/ui/components/panels/LogPanel.js.map +0 -1
- package/dist/ui/components/panels/SessionPanel.d.ts.map +0 -1
- package/dist/ui/components/panels/SessionPanel.js.map +0 -1
- package/dist/ui/components/panels/index.d.ts.map +0 -1
- package/dist/ui/components/panels/index.js.map +0 -1
- package/dist/ui/components/views/ChatView.d.ts.map +0 -1
- package/dist/ui/components/views/ChatView.js.map +0 -1
- package/dist/ui/components/views/index.d.ts.map +0 -1
- package/dist/ui/components/views/index.js.map +0 -1
- package/dist/ui/contexts/TokenContext.d.ts.map +0 -1
- package/dist/ui/contexts/TokenContext.js.map +0 -1
- package/dist/ui/hooks/atFileProcessor.d.ts.map +0 -1
- package/dist/ui/hooks/atFileProcessor.js.map +0 -1
- package/dist/ui/hooks/index.d.ts.map +0 -1
- package/dist/ui/hooks/index.js.map +0 -1
- package/dist/ui/hooks/slashCommandProcessor.d.ts.map +0 -1
- package/dist/ui/hooks/slashCommandProcessor.js.map +0 -1
- package/dist/ui/hooks/useCommandBrowserState.d.ts.map +0 -1
- package/dist/ui/hooks/useCommandBrowserState.js.map +0 -1
- package/dist/ui/hooks/useFileBrowserState.d.ts.map +0 -1
- package/dist/ui/hooks/useFileBrowserState.js.map +0 -1
- package/dist/ui/hooks/useFileList.d.ts.map +0 -1
- package/dist/ui/hooks/useFileList.js.map +0 -1
- package/dist/ui/hooks/useInputHistory.d.ts.map +0 -1
- package/dist/ui/hooks/useInputHistory.js.map +0 -1
- package/dist/ui/hooks/usePlanExecution.d.ts.map +0 -1
- package/dist/ui/hooks/usePlanExecution.js.map +0 -1
- package/dist/ui/index.d.ts.map +0 -1
- package/dist/ui/index.js.map +0 -1
- package/dist/ui/ink-entry.d.ts.map +0 -1
- package/dist/ui/ink-entry.js.map +0 -1
- package/dist/utils/env-filter.d.ts.map +0 -1
- package/dist/utils/env-filter.js.map +0 -1
- package/dist/utils/file-system.d.ts.map +0 -1
- package/dist/utils/file-system.js.map +0 -1
- package/dist/utils/git-utils.d.ts.map +0 -1
- package/dist/utils/git-utils.js.map +0 -1
- package/dist/utils/json-stream-logger.d.ts.map +0 -1
- package/dist/utils/json-stream-logger.js.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/platform-utils.d.ts.map +0 -1
- package/dist/utils/platform-utils.js.map +0 -1
- package/dist/utils/wsl-utils.d.ts.map +0 -1
- package/dist/utils/wsl-utils.js.map +0 -1
- package/electron.vite.config.ts +0 -63
- package/google374b9eba0c52b043.html +0 -1
- package/src/agents/base/base-agent.ts +0 -159
- package/src/agents/docs-search/index.ts +0 -365
- package/src/agents/index.ts +0 -34
- package/src/agents/planner/index.ts +0 -544
- package/src/cli.ts +0 -201
- package/src/constants.ts +0 -47
- package/src/core/compact/compact-manager.ts +0 -160
- package/src/core/compact/compact-prompts.ts +0 -150
- package/src/core/compact/context-tracker.ts +0 -164
- package/src/core/compact/index.ts +0 -25
- package/src/core/config/config-manager.ts +0 -460
- package/src/core/config/index.ts +0 -5
- package/src/core/docs-manager.ts +0 -678
- package/src/core/llm/index.ts +0 -7
- package/src/core/llm/llm-client.ts +0 -1550
- package/src/core/session/index.ts +0 -5
- package/src/core/session/session-manager.ts +0 -464
- package/src/core/slash-command-handler.ts +0 -410
- package/src/core/usage-tracker.ts +0 -438
- package/src/errors/base.ts +0 -81
- package/src/errors/file.ts +0 -183
- package/src/errors/index.ts +0 -95
- package/src/errors/llm.ts +0 -151
- package/src/errors/network.ts +0 -124
- package/src/errors/validation.ts +0 -111
- package/src/eval/eval-runner.ts +0 -456
- package/src/eval/index.ts +0 -8
- package/src/eval/types.ts +0 -139
- package/src/index.ts +0 -22
- package/src/orchestration/index.ts +0 -30
- package/src/orchestration/plan-executor.ts +0 -652
- package/src/orchestration/types.ts +0 -127
- package/src/orchestration/utils.ts +0 -119
- package/src/orquesta/connection.ts +0 -291
- package/src/prompts/agents/docs-search-decision.ts +0 -74
- package/src/prompts/agents/docs-search.ts +0 -84
- package/src/prompts/agents/planning.ts +0 -143
- package/src/prompts/index.ts +0 -31
- package/src/prompts/shared/codebase-rules.ts +0 -29
- package/src/prompts/shared/git-rules.ts +0 -94
- package/src/prompts/shared/language-rules.ts +0 -36
- package/src/prompts/shared/tool-usage.ts +0 -72
- package/src/prompts/system/compact.ts +0 -80
- package/src/prompts/system/plan-execute.ts +0 -89
- package/src/tools/browser/browser-client.ts +0 -1363
- package/src/tools/browser/browser-tools.ts +0 -1139
- package/src/tools/browser/index.ts +0 -65
- package/src/tools/index.ts +0 -23
- package/src/tools/llm/agents/docs-search-tools.ts +0 -368
- package/src/tools/llm/agents/index.ts +0 -22
- package/src/tools/llm/index.ts +0 -11
- package/src/tools/llm/simple/ask-user-tool.ts +0 -25
- package/src/tools/llm/simple/background-bash-tool.ts +0 -443
- package/src/tools/llm/simple/background-powershell-tool.ts +0 -421
- package/src/tools/llm/simple/bash-tool.ts +0 -238
- package/src/tools/llm/simple/docs-search-agent-tool.ts +0 -146
- package/src/tools/llm/simple/file-tools.ts +0 -1051
- package/src/tools/llm/simple/final-response-tool.ts +0 -180
- package/src/tools/llm/simple/index.ts +0 -42
- package/src/tools/llm/simple/planning-tools.ts +0 -143
- package/src/tools/llm/simple/powershell-tool.ts +0 -241
- package/src/tools/llm/simple/simple-tool-executor.ts +0 -279
- package/src/tools/llm/simple/todo-tools.ts +0 -207
- package/src/tools/llm/simple/user-interaction-tools.ts +0 -277
- package/src/tools/office/common/constants.ts +0 -335
- package/src/tools/office/common/index.ts +0 -133
- package/src/tools/office/common/types.ts +0 -286
- package/src/tools/office/common/utils.ts +0 -116
- package/src/tools/office/excel-client.ts +0 -1336
- package/src/tools/office/excel-tools/cells.ts +0 -359
- package/src/tools/office/excel-tools/charts.ts +0 -166
- package/src/tools/office/excel-tools/comments.ts +0 -155
- package/src/tools/office/excel-tools/data-ops.ts +0 -349
- package/src/tools/office/excel-tools/export.ts +0 -105
- package/src/tools/office/excel-tools/formatting.ts +0 -357
- package/src/tools/office/excel-tools/index.ts +0 -55
- package/src/tools/office/excel-tools/launch.ts +0 -303
- package/src/tools/office/excel-tools/media.ts +0 -117
- package/src/tools/office/excel-tools/named-ranges.ts +0 -148
- package/src/tools/office/excel-tools/protection.ts +0 -105
- package/src/tools/office/excel-tools/rows-columns.ts +0 -386
- package/src/tools/office/excel-tools/sheets.ts +0 -228
- package/src/tools/office/excel-tools/validation.ts +0 -226
- package/src/tools/office/excel-tools.ts +0 -9
- package/src/tools/office/index.ts +0 -259
- package/src/tools/office/office-client-base.ts +0 -242
- package/src/tools/office/office-client.ts +0 -377
- package/src/tools/office/powerpoint-client.ts +0 -1498
- package/src/tools/office/powerpoint-tools/effects.ts +0 -315
- package/src/tools/office/powerpoint-tools/export.ts +0 -138
- package/src/tools/office/powerpoint-tools/index.ts +0 -45
- package/src/tools/office/powerpoint-tools/launch.ts +0 -263
- package/src/tools/office/powerpoint-tools/media.ts +0 -291
- package/src/tools/office/powerpoint-tools/notes.ts +0 -220
- package/src/tools/office/powerpoint-tools/sections.ts +0 -140
- package/src/tools/office/powerpoint-tools/shapes.ts +0 -870
- package/src/tools/office/powerpoint-tools/slides.ts +0 -350
- package/src/tools/office/powerpoint-tools/tables.ts +0 -182
- package/src/tools/office/powerpoint-tools/text.ts +0 -473
- package/src/tools/office/powerpoint-tools.ts +0 -9
- package/src/tools/office/word-client.ts +0 -1697
- package/src/tools/office/word-tools/bookmarks.ts +0 -186
- package/src/tools/office/word-tools/comments.ts +0 -185
- package/src/tools/office/word-tools/content.ts +0 -229
- package/src/tools/office/word-tools/export.ts +0 -97
- package/src/tools/office/word-tools/formatting.ts +0 -161
- package/src/tools/office/word-tools/headers-footers.ts +0 -155
- package/src/tools/office/word-tools/index.ts +0 -57
- package/src/tools/office/word-tools/launch.ts +0 -312
- package/src/tools/office/word-tools/lists.ts +0 -97
- package/src/tools/office/word-tools/navigation.ts +0 -114
- package/src/tools/office/word-tools/page-setup.ts +0 -195
- package/src/tools/office/word-tools/tables.ts +0 -262
- package/src/tools/office/word-tools/text.ts +0 -294
- package/src/tools/office/word-tools/undo-redo.ts +0 -97
- package/src/tools/office/word-tools/watermarks.ts +0 -105
- package/src/tools/office/word-tools.ts +0 -9
- package/src/tools/registry.ts +0 -527
- package/src/tools/types.ts +0 -231
- package/src/types/index.ts +0 -181
- package/src/ui/PlanExecuteView.tsx +0 -119
- package/src/ui/TodoPanel.tsx +0 -240
- package/src/ui/UpdateNotification.tsx +0 -105
- package/src/ui/components/ActivityIndicator.tsx +0 -234
- package/src/ui/components/CommandBrowser.tsx +0 -114
- package/src/ui/components/CustomTextInput.tsx +0 -389
- package/src/ui/components/DocsSearchProgress.tsx +0 -85
- package/src/ui/components/FileBrowser.tsx +0 -93
- package/src/ui/components/LLMSetupWizard.tsx +0 -333
- package/src/ui/components/Logo.tsx +0 -125
- package/src/ui/components/MarkdownRenderer.tsx +0 -358
- package/src/ui/components/ModelSelector.tsx +0 -203
- package/src/ui/components/PlanExecuteApp.tsx +0 -2007
- package/src/ui/components/ProgressBar.tsx +0 -51
- package/src/ui/components/StatusBar.tsx +0 -302
- package/src/ui/components/ThinkingIndicator.tsx +0 -120
- package/src/ui/components/TodoListView.tsx +0 -140
- package/src/ui/components/ToolSelector.tsx +0 -215
- package/src/ui/components/dialogs/ApprovalDialog.tsx +0 -259
- package/src/ui/components/dialogs/AskUserDialog.tsx +0 -159
- package/src/ui/components/dialogs/DocsBrowser.tsx +0 -222
- package/src/ui/components/dialogs/SettingsDialog.tsx +0 -939
- package/src/ui/components/dialogs/index.ts +0 -13
- package/src/ui/components/index.ts +0 -27
- package/src/ui/components/panels/LogPanel.tsx +0 -385
- package/src/ui/components/panels/SessionPanel.tsx +0 -146
- package/src/ui/components/panels/index.ts +0 -13
- package/src/ui/components/views/ChatView.tsx +0 -447
- package/src/ui/components/views/index.ts +0 -5
- package/src/ui/contexts/TokenContext.tsx +0 -139
- package/src/ui/hooks/atFileProcessor.ts +0 -167
- package/src/ui/hooks/index.ts +0 -11
- package/src/ui/hooks/slashCommandProcessor.ts +0 -174
- package/src/ui/hooks/useCommandBrowserState.ts +0 -97
- package/src/ui/hooks/useFileBrowserState.ts +0 -116
- package/src/ui/hooks/useFileList.ts +0 -132
- package/src/ui/hooks/useInputHistory.ts +0 -89
- package/src/ui/hooks/usePlanExecution.ts +0 -339
- package/src/ui/index.ts +0 -10
- package/src/ui/ink-entry.tsx +0 -36
- package/src/utils/env-filter.ts +0 -164
- package/src/utils/file-system.ts +0 -133
- package/src/utils/git-utils.ts +0 -30
- package/src/utils/json-stream-logger.ts +0 -1259
- package/src/utils/logger.ts +0 -2767
- package/src/utils/platform-utils.ts +0 -256
- package/src/utils/wsl-utils.ts +0 -113
- package/tsconfig.electron.json +0 -39
- package/tsconfig.json +0 -64
|
@@ -1,1363 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Browser Automation Client (Pure CDP approach)
|
|
3
|
-
*
|
|
4
|
-
* Launches Chrome with CDP port via PowerShell,
|
|
5
|
-
* and controls the browser by directly connecting to CDP (Chrome DevTools Protocol) via WebSocket.
|
|
6
|
-
*
|
|
7
|
-
* Works without external dependencies (no playwright required).
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { spawn, ChildProcess, execSync } from 'child_process';
|
|
11
|
-
import * as path from 'path';
|
|
12
|
-
import * as fs from 'fs';
|
|
13
|
-
import WebSocket from 'ws';
|
|
14
|
-
import { logger } from '../../utils/logger.js';
|
|
15
|
-
import { LOCAL_HOME_DIR } from '../../constants.js';
|
|
16
|
-
import {
|
|
17
|
-
getPlatform,
|
|
18
|
-
getPowerShellPath,
|
|
19
|
-
Platform,
|
|
20
|
-
} from '../../utils/platform-utils.js';
|
|
21
|
-
|
|
22
|
-
// ===========================================================================
|
|
23
|
-
// Types
|
|
24
|
-
// ===========================================================================
|
|
25
|
-
|
|
26
|
-
interface BrowserResponse {
|
|
27
|
-
success: boolean;
|
|
28
|
-
message?: string;
|
|
29
|
-
error?: string;
|
|
30
|
-
details?: string;
|
|
31
|
-
[key: string]: unknown;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
interface HealthResponse extends BrowserResponse {
|
|
35
|
-
status: string;
|
|
36
|
-
version: string;
|
|
37
|
-
browser: {
|
|
38
|
-
active: boolean;
|
|
39
|
-
type: string | null;
|
|
40
|
-
chrome_available: boolean;
|
|
41
|
-
edge_available: boolean;
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
interface ScreenshotResponse extends BrowserResponse {
|
|
46
|
-
image?: string;
|
|
47
|
-
format?: string;
|
|
48
|
-
encoding?: string;
|
|
49
|
-
url?: string;
|
|
50
|
-
title?: string;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
interface NavigateResponse extends BrowserResponse {
|
|
54
|
-
url?: string;
|
|
55
|
-
title?: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
interface PageInfoResponse extends BrowserResponse {
|
|
59
|
-
url?: string;
|
|
60
|
-
title?: string;
|
|
61
|
-
html?: string;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
interface ConsoleLogEntry {
|
|
65
|
-
level: string;
|
|
66
|
-
message: string;
|
|
67
|
-
timestamp: number;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
interface ConsoleResponse extends BrowserResponse {
|
|
71
|
-
logs?: ConsoleLogEntry[];
|
|
72
|
-
count?: number;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
interface NetworkLogEntry {
|
|
76
|
-
type: 'request' | 'response';
|
|
77
|
-
url: string;
|
|
78
|
-
method?: string;
|
|
79
|
-
status?: number;
|
|
80
|
-
statusText?: string;
|
|
81
|
-
mimeType?: string;
|
|
82
|
-
timestamp: number;
|
|
83
|
-
requestId: string;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
interface NetworkResponse extends BrowserResponse {
|
|
87
|
-
logs?: NetworkLogEntry[];
|
|
88
|
-
count?: number;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// CDP Protocol types
|
|
92
|
-
interface CDPTarget {
|
|
93
|
-
id: string;
|
|
94
|
-
type: string;
|
|
95
|
-
title: string;
|
|
96
|
-
url: string;
|
|
97
|
-
webSocketDebuggerUrl: string;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
interface CDPMessage {
|
|
101
|
-
id: number;
|
|
102
|
-
method?: string;
|
|
103
|
-
params?: Record<string, unknown>;
|
|
104
|
-
result?: unknown;
|
|
105
|
-
error?: {
|
|
106
|
-
code: number;
|
|
107
|
-
message: string;
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// ===========================================================================
|
|
112
|
-
// CDP Client (WebSocket-based)
|
|
113
|
-
// ===========================================================================
|
|
114
|
-
|
|
115
|
-
class CDPConnection {
|
|
116
|
-
private ws: WebSocket | null = null;
|
|
117
|
-
private messageId: number = 0;
|
|
118
|
-
private pendingMessages: Map<number, {
|
|
119
|
-
resolve: (value: unknown) => void;
|
|
120
|
-
reject: (error: Error) => void;
|
|
121
|
-
}> = new Map();
|
|
122
|
-
private eventHandlers: Map<string, ((params: unknown) => void)[]> = new Map();
|
|
123
|
-
|
|
124
|
-
async connect(wsUrl: string): Promise<void> {
|
|
125
|
-
return new Promise((resolve, reject) => {
|
|
126
|
-
this.ws = new WebSocket(wsUrl);
|
|
127
|
-
|
|
128
|
-
this.ws.on('open', () => {
|
|
129
|
-
logger.debug('[CDP] WebSocket connected');
|
|
130
|
-
resolve();
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
this.ws.on('message', (data: WebSocket.Data) => {
|
|
134
|
-
try {
|
|
135
|
-
const message: CDPMessage = JSON.parse(data.toString());
|
|
136
|
-
|
|
137
|
-
if (message.id !== undefined) {
|
|
138
|
-
// Response to a command
|
|
139
|
-
const pending = this.pendingMessages.get(message.id);
|
|
140
|
-
if (pending) {
|
|
141
|
-
this.pendingMessages.delete(message.id);
|
|
142
|
-
if (message.error) {
|
|
143
|
-
pending.reject(new Error(message.error.message));
|
|
144
|
-
} else {
|
|
145
|
-
pending.resolve(message.result);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
} else if (message.method) {
|
|
149
|
-
// Event from browser
|
|
150
|
-
const handlers = this.eventHandlers.get(message.method) || [];
|
|
151
|
-
for (const handler of handlers) {
|
|
152
|
-
handler(message.params);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
} catch (e) {
|
|
156
|
-
logger.debug('[CDP] Failed to parse message: ' + e);
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
this.ws.on('error', (error) => {
|
|
161
|
-
logger.debug('[CDP] WebSocket error: ' + error.message);
|
|
162
|
-
reject(error);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
this.ws.on('close', () => {
|
|
166
|
-
logger.debug('[CDP] WebSocket closed');
|
|
167
|
-
// Reject all pending messages
|
|
168
|
-
for (const [, pending] of this.pendingMessages) {
|
|
169
|
-
pending.reject(new Error('WebSocket closed'));
|
|
170
|
-
}
|
|
171
|
-
this.pendingMessages.clear();
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
async send(method: string, params?: Record<string, unknown>): Promise<unknown> {
|
|
177
|
-
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
178
|
-
throw new Error('WebSocket not connected');
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const id = ++this.messageId;
|
|
182
|
-
const message: CDPMessage = { id, method, params };
|
|
183
|
-
|
|
184
|
-
return new Promise((resolve, reject) => {
|
|
185
|
-
this.pendingMessages.set(id, { resolve, reject });
|
|
186
|
-
this.ws!.send(JSON.stringify(message));
|
|
187
|
-
|
|
188
|
-
// Timeout after 30 seconds
|
|
189
|
-
setTimeout(() => {
|
|
190
|
-
if (this.pendingMessages.has(id)) {
|
|
191
|
-
this.pendingMessages.delete(id);
|
|
192
|
-
reject(new Error(`CDP command timeout: ${method}`));
|
|
193
|
-
}
|
|
194
|
-
}, 30000);
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
on(event: string, handler: (params: unknown) => void): void {
|
|
199
|
-
if (!this.eventHandlers.has(event)) {
|
|
200
|
-
this.eventHandlers.set(event, []);
|
|
201
|
-
}
|
|
202
|
-
this.eventHandlers.get(event)!.push(handler);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
off(event: string): void {
|
|
206
|
-
this.eventHandlers.delete(event);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
close(): void {
|
|
210
|
-
if (this.ws) {
|
|
211
|
-
this.ws.close();
|
|
212
|
-
this.ws = null;
|
|
213
|
-
}
|
|
214
|
-
this.pendingMessages.clear();
|
|
215
|
-
this.eventHandlers.clear();
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
isConnected(): boolean {
|
|
219
|
-
return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// ===========================================================================
|
|
224
|
-
// Browser Client
|
|
225
|
-
// ===========================================================================
|
|
226
|
-
|
|
227
|
-
class BrowserClient {
|
|
228
|
-
private cdp: CDPConnection | null = null;
|
|
229
|
-
private browserProcess: ChildProcess | null = null;
|
|
230
|
-
private platform: Platform;
|
|
231
|
-
private cdpPort: number = 9222;
|
|
232
|
-
private browserType: 'chrome' | 'edge' = 'chrome';
|
|
233
|
-
private screenshotDir: string;
|
|
234
|
-
|
|
235
|
-
// Console/Network log collection
|
|
236
|
-
private consoleLogs: ConsoleLogEntry[] = [];
|
|
237
|
-
private networkLogs: NetworkLogEntry[] = [];
|
|
238
|
-
|
|
239
|
-
constructor() {
|
|
240
|
-
this.platform = getPlatform();
|
|
241
|
-
logger.debug('[BrowserClient] constructor: platform = ' + this.platform);
|
|
242
|
-
|
|
243
|
-
// Create screenshot directory
|
|
244
|
-
this.screenshotDir = path.join(LOCAL_HOME_DIR, 'screenshots', 'browser');
|
|
245
|
-
if (!fs.existsSync(this.screenshotDir)) {
|
|
246
|
-
fs.mkdirSync(this.screenshotDir, { recursive: true });
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
logger.debug('[BrowserClient] constructor: CDP URL = ' + this.getCDPUrl());
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Get CDP endpoint URL
|
|
254
|
-
*/
|
|
255
|
-
private getCDPUrl(): string {
|
|
256
|
-
return `http://localhost:${this.cdpPort}`;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Get screenshot directory path
|
|
261
|
-
*/
|
|
262
|
-
getScreenshotDir(): string {
|
|
263
|
-
return this.screenshotDir;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Find browser executable path based on platform
|
|
268
|
-
*/
|
|
269
|
-
private findBrowserPath(windowsPaths: string[], linuxPaths?: string[]): string | null {
|
|
270
|
-
// Native Windows - direct file system check
|
|
271
|
-
if (this.platform === 'native-windows') {
|
|
272
|
-
for (const p of windowsPaths) {
|
|
273
|
-
if (fs.existsSync(p)) return p;
|
|
274
|
-
}
|
|
275
|
-
return null;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// WSL - use PowerShell to check Windows paths
|
|
279
|
-
if (this.platform === 'wsl') {
|
|
280
|
-
try {
|
|
281
|
-
const powerShellPath = getPowerShellPath();
|
|
282
|
-
const conditions = windowsPaths
|
|
283
|
-
.map((p, index) => {
|
|
284
|
-
const keyword = index === 0 ? 'if' : 'elseif';
|
|
285
|
-
return `${keyword} (Test-Path '${p}') { Write-Output '${p}' }`;
|
|
286
|
-
})
|
|
287
|
-
.join(' ');
|
|
288
|
-
const result = execSync(
|
|
289
|
-
`${powerShellPath} -Command "${conditions}"`,
|
|
290
|
-
{ encoding: 'utf-8', timeout: 5000 }
|
|
291
|
-
).trim();
|
|
292
|
-
if (result) return result;
|
|
293
|
-
} catch (error) {
|
|
294
|
-
logger.debug(
|
|
295
|
-
`[BrowserClient] findBrowserPath: PowerShell check failed (${error instanceof Error ? error.message : String(error)})`
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
return null;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Native Linux - check Linux paths
|
|
302
|
-
if (linuxPaths) {
|
|
303
|
-
for (const p of linuxPaths) {
|
|
304
|
-
if (fs.existsSync(p)) return p;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
return null;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
private findChromePath(): string | null {
|
|
311
|
-
return this.findBrowserPath(
|
|
312
|
-
// Windows paths
|
|
313
|
-
[
|
|
314
|
-
'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
|
|
315
|
-
'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
|
|
316
|
-
],
|
|
317
|
-
// Linux paths
|
|
318
|
-
[
|
|
319
|
-
'/usr/bin/google-chrome',
|
|
320
|
-
'/usr/bin/google-chrome-stable',
|
|
321
|
-
'/usr/bin/chromium',
|
|
322
|
-
'/usr/bin/chromium-browser',
|
|
323
|
-
'/snap/bin/chromium',
|
|
324
|
-
]
|
|
325
|
-
);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
private findEdgePath(): string | null {
|
|
329
|
-
return this.findBrowserPath(
|
|
330
|
-
// Windows paths
|
|
331
|
-
[
|
|
332
|
-
'C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe',
|
|
333
|
-
'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe',
|
|
334
|
-
],
|
|
335
|
-
// Linux paths (Edge for Linux)
|
|
336
|
-
[
|
|
337
|
-
'/usr/bin/microsoft-edge',
|
|
338
|
-
'/usr/bin/microsoft-edge-stable',
|
|
339
|
-
]
|
|
340
|
-
);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* Kill existing browser processes with CDP port
|
|
345
|
-
*/
|
|
346
|
-
private killExistingBrowser(): void {
|
|
347
|
-
logger.debug('[BrowserClient] killExistingBrowser: killing processes on port ' + this.cdpPort);
|
|
348
|
-
try {
|
|
349
|
-
if (this.platform === 'native-windows' || this.platform === 'wsl') {
|
|
350
|
-
// Use PowerShell to kill processes on Windows
|
|
351
|
-
const powerShellPath = getPowerShellPath();
|
|
352
|
-
execSync(
|
|
353
|
-
`${powerShellPath} -Command "Get-NetTCPConnection -LocalPort ${this.cdpPort} -ErrorAction SilentlyContinue | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force -ErrorAction SilentlyContinue }"`,
|
|
354
|
-
{ stdio: 'ignore', timeout: 5000 }
|
|
355
|
-
);
|
|
356
|
-
} else {
|
|
357
|
-
// Native Linux - use fuser or lsof
|
|
358
|
-
try {
|
|
359
|
-
execSync(`fuser -k ${this.cdpPort}/tcp 2>/dev/null || true`, { stdio: 'ignore', timeout: 5000 });
|
|
360
|
-
} catch {
|
|
361
|
-
// Try lsof as fallback
|
|
362
|
-
try {
|
|
363
|
-
execSync(`lsof -ti:${this.cdpPort} | xargs -r kill -9 2>/dev/null || true`, { stdio: 'ignore', timeout: 5000 });
|
|
364
|
-
} catch {
|
|
365
|
-
// Ignore
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
} catch {
|
|
370
|
-
// Ignore errors
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
* Check if CDP endpoint is available
|
|
376
|
-
*/
|
|
377
|
-
private async isCDPAvailable(): Promise<boolean> {
|
|
378
|
-
try {
|
|
379
|
-
const response = await fetch(`${this.getCDPUrl()}/json/version`, {
|
|
380
|
-
signal: AbortSignal.timeout(2000),
|
|
381
|
-
});
|
|
382
|
-
return response.ok;
|
|
383
|
-
} catch {
|
|
384
|
-
return false;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* Get list of available targets (tabs)
|
|
390
|
-
*/
|
|
391
|
-
private async getTargets(): Promise<CDPTarget[]> {
|
|
392
|
-
const response = await fetch(`${this.getCDPUrl()}/json`);
|
|
393
|
-
return await response.json() as CDPTarget[];
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* Check if browser is running
|
|
398
|
-
*/
|
|
399
|
-
async isRunning(): Promise<boolean> {
|
|
400
|
-
return this.cdp !== null && this.cdp.isConnected();
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
/**
|
|
404
|
-
* Get server health status
|
|
405
|
-
*/
|
|
406
|
-
async getHealth(): Promise<HealthResponse | null> {
|
|
407
|
-
const chromePath = this.findChromePath();
|
|
408
|
-
const edgePath = this.findEdgePath();
|
|
409
|
-
|
|
410
|
-
return {
|
|
411
|
-
success: true,
|
|
412
|
-
status: 'running',
|
|
413
|
-
version: '2.0.0-pure-cdp',
|
|
414
|
-
browser: {
|
|
415
|
-
active: this.cdp !== null && this.cdp.isConnected(),
|
|
416
|
-
type: this.browserType,
|
|
417
|
-
chrome_available: chromePath !== null,
|
|
418
|
-
edge_available: edgePath !== null,
|
|
419
|
-
},
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* Start the browser server (for compatibility)
|
|
425
|
-
*/
|
|
426
|
-
async startServer(): Promise<boolean> {
|
|
427
|
-
return true;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
/**
|
|
431
|
-
* Stop the browser server (for compatibility)
|
|
432
|
-
*/
|
|
433
|
-
async stopServer(): Promise<boolean> {
|
|
434
|
-
return this.close().then(() => true).catch(() => true);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* Setup console and network logging via CDP
|
|
439
|
-
*/
|
|
440
|
-
private setupLogging(): void {
|
|
441
|
-
if (!this.cdp) return;
|
|
442
|
-
|
|
443
|
-
// Enable Console domain
|
|
444
|
-
this.cdp.send('Console.enable').catch(err => logger.debug('[CDP] Failed to enable Console domain: ' + err));
|
|
445
|
-
this.cdp.on('Console.messageAdded', (params: unknown) => {
|
|
446
|
-
const p = params as { message: { level: string; text: string } };
|
|
447
|
-
this.consoleLogs.push({
|
|
448
|
-
level: p.message.level.toUpperCase(),
|
|
449
|
-
message: p.message.text,
|
|
450
|
-
timestamp: Date.now(),
|
|
451
|
-
});
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
// Enable Runtime for console.log
|
|
455
|
-
this.cdp.send('Runtime.enable').catch(err => logger.debug('[CDP] Failed to enable Runtime domain: ' + err));
|
|
456
|
-
this.cdp.on('Runtime.consoleAPICalled', (params: unknown) => {
|
|
457
|
-
const p = params as { type: string; args: { value?: string; description?: string }[] };
|
|
458
|
-
const message = p.args.map(a => a.value || a.description || '').join(' ');
|
|
459
|
-
this.consoleLogs.push({
|
|
460
|
-
level: p.type.toUpperCase(),
|
|
461
|
-
message,
|
|
462
|
-
timestamp: Date.now(),
|
|
463
|
-
});
|
|
464
|
-
});
|
|
465
|
-
|
|
466
|
-
// Enable Network domain
|
|
467
|
-
this.cdp.send('Network.enable').catch(err => logger.debug('[CDP] Failed to enable Network domain: ' + err));
|
|
468
|
-
this.cdp.on('Network.requestWillBeSent', (params: unknown) => {
|
|
469
|
-
const p = params as { requestId: string; request: { url: string; method: string } };
|
|
470
|
-
this.networkLogs.push({
|
|
471
|
-
type: 'request',
|
|
472
|
-
url: p.request.url,
|
|
473
|
-
method: p.request.method,
|
|
474
|
-
timestamp: Date.now(),
|
|
475
|
-
requestId: p.requestId,
|
|
476
|
-
});
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
this.cdp.on('Network.responseReceived', (params: unknown) => {
|
|
480
|
-
const p = params as { requestId: string; response: { url: string; status: number; statusText: string; mimeType: string } };
|
|
481
|
-
this.networkLogs.push({
|
|
482
|
-
type: 'response',
|
|
483
|
-
url: p.response.url,
|
|
484
|
-
status: p.response.status,
|
|
485
|
-
statusText: p.response.statusText,
|
|
486
|
-
mimeType: p.response.mimeType,
|
|
487
|
-
timestamp: Date.now(),
|
|
488
|
-
requestId: p.requestId,
|
|
489
|
-
});
|
|
490
|
-
});
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
/**
|
|
494
|
-
* Get current page info (URL and title) - helper to reduce code duplication
|
|
495
|
-
*/
|
|
496
|
-
private async getCurrentPageInfo(): Promise<{ url: string; title: string }> {
|
|
497
|
-
if (!this.cdp || !this.cdp.isConnected()) {
|
|
498
|
-
return { url: '', title: '' };
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
const evalResult = await this.cdp.send('Runtime.evaluate', {
|
|
502
|
-
expression: 'JSON.stringify({ url: window.location.href, title: document.title })',
|
|
503
|
-
returnByValue: true,
|
|
504
|
-
}) as { result: { value: string } };
|
|
505
|
-
|
|
506
|
-
return JSON.parse(evalResult.result.value);
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
// ===========================================================================
|
|
510
|
-
// Browser Operations
|
|
511
|
-
// ===========================================================================
|
|
512
|
-
|
|
513
|
-
/**
|
|
514
|
-
* Launch browser with CDP
|
|
515
|
-
*/
|
|
516
|
-
async launch(options?: { headless?: boolean; browser?: 'chrome' | 'edge' }): Promise<BrowserResponse> {
|
|
517
|
-
const headless = options?.headless ?? false;
|
|
518
|
-
const preferredBrowser = options?.browser ?? 'chrome';
|
|
519
|
-
|
|
520
|
-
logger.debug(`[BrowserClient] launch: starting browser (preferred=${preferredBrowser}, headless=${headless})`);
|
|
521
|
-
|
|
522
|
-
try {
|
|
523
|
-
// Clean up existing connection
|
|
524
|
-
if (this.cdp) {
|
|
525
|
-
this.cdp.close();
|
|
526
|
-
this.cdp = null;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// Terminate existing CDP processes
|
|
530
|
-
this.killExistingBrowser();
|
|
531
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
532
|
-
|
|
533
|
-
// Find browser path
|
|
534
|
-
let browserPath: string | null = null;
|
|
535
|
-
if (preferredBrowser === 'chrome') {
|
|
536
|
-
browserPath = this.findChromePath();
|
|
537
|
-
if (!browserPath) {
|
|
538
|
-
browserPath = this.findEdgePath();
|
|
539
|
-
this.browserType = 'edge';
|
|
540
|
-
} else {
|
|
541
|
-
this.browserType = 'chrome';
|
|
542
|
-
}
|
|
543
|
-
} else {
|
|
544
|
-
browserPath = this.findEdgePath();
|
|
545
|
-
if (!browserPath) {
|
|
546
|
-
browserPath = this.findChromePath();
|
|
547
|
-
this.browserType = 'chrome';
|
|
548
|
-
} else {
|
|
549
|
-
this.browserType = 'edge';
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
if (!browserPath) {
|
|
554
|
-
return {
|
|
555
|
-
success: false,
|
|
556
|
-
error: 'No browser found',
|
|
557
|
-
details: 'Neither Chrome nor Edge is installed',
|
|
558
|
-
};
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
logger.debug(`[BrowserClient] launch: using ${this.browserType} at ${browserPath}`);
|
|
562
|
-
|
|
563
|
-
// Common browser arguments (without user-data-dir)
|
|
564
|
-
const baseArgs = [
|
|
565
|
-
`--remote-debugging-port=${this.cdpPort}`,
|
|
566
|
-
'--no-first-run',
|
|
567
|
-
'--no-default-browser-check',
|
|
568
|
-
'--disable-popup-blocking',
|
|
569
|
-
'--start-maximized',
|
|
570
|
-
];
|
|
571
|
-
|
|
572
|
-
if (headless) {
|
|
573
|
-
baseArgs.push('--headless=new');
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
// Launch browser based on platform
|
|
577
|
-
if (this.platform === 'native-windows') {
|
|
578
|
-
// Native Windows - spawn directly with user data dir
|
|
579
|
-
const userDataDir = `${process.env['LOCALAPPDATA']}\\local-cli-browser-profile`;
|
|
580
|
-
const args = [...baseArgs, `--user-data-dir=${userDataDir}`];
|
|
581
|
-
|
|
582
|
-
logger.debug(`[BrowserClient] launch: spawning browser directly on Windows`);
|
|
583
|
-
this.browserProcess = spawn(browserPath, args, {
|
|
584
|
-
detached: true,
|
|
585
|
-
stdio: 'ignore',
|
|
586
|
-
});
|
|
587
|
-
} else if (this.platform === 'wsl') {
|
|
588
|
-
// WSL - use PowerShell to launch Windows browser
|
|
589
|
-
// We need to use a PowerShell variable ($dir) for user-data-dir
|
|
590
|
-
const argsForPowerShell = ['--user-data-dir=$dir', ...baseArgs];
|
|
591
|
-
const argsString = argsForPowerShell.map(arg => `"${arg}"`).join(',');
|
|
592
|
-
const psCommand = `$dir = "$env:LOCALAPPDATA\\local-cli-browser-profile"; Start-Process -FilePath '${browserPath}' -ArgumentList ${argsString}`;
|
|
593
|
-
|
|
594
|
-
logger.debug(`[BrowserClient] launch: executing PowerShell command from WSL`);
|
|
595
|
-
|
|
596
|
-
const powershellPath = getPowerShellPath();
|
|
597
|
-
this.browserProcess = spawn(powershellPath, ['-Command', psCommand], {
|
|
598
|
-
detached: true,
|
|
599
|
-
stdio: 'ignore',
|
|
600
|
-
});
|
|
601
|
-
} else {
|
|
602
|
-
// Native Linux - spawn directly
|
|
603
|
-
const userDataDir = `${process.env['HOME']}/.local-cli-browser-profile`;
|
|
604
|
-
const args = [...baseArgs, `--user-data-dir=${userDataDir}`];
|
|
605
|
-
|
|
606
|
-
logger.debug(`[BrowserClient] launch: spawning browser directly on Linux`);
|
|
607
|
-
this.browserProcess = spawn(browserPath, args, {
|
|
608
|
-
detached: true,
|
|
609
|
-
stdio: 'ignore',
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
this.browserProcess.unref();
|
|
614
|
-
|
|
615
|
-
// Wait for CDP connection
|
|
616
|
-
logger.debug('[BrowserClient] launch: waiting for CDP endpoint...');
|
|
617
|
-
const maxWait = 15000;
|
|
618
|
-
const startTime = Date.now();
|
|
619
|
-
|
|
620
|
-
while (Date.now() - startTime < maxWait) {
|
|
621
|
-
if (await this.isCDPAvailable()) {
|
|
622
|
-
break;
|
|
623
|
-
}
|
|
624
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
if (!(await this.isCDPAvailable())) {
|
|
628
|
-
return {
|
|
629
|
-
success: false,
|
|
630
|
-
error: 'CDP endpoint not available',
|
|
631
|
-
details: `Timeout waiting for browser to start on port ${this.cdpPort}`,
|
|
632
|
-
};
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
// Get targets (pages)
|
|
636
|
-
const targets = await this.getTargets();
|
|
637
|
-
const pageTarget = targets.find(t => t.type === 'page');
|
|
638
|
-
|
|
639
|
-
if (!pageTarget) {
|
|
640
|
-
return {
|
|
641
|
-
success: false,
|
|
642
|
-
error: 'No page target found',
|
|
643
|
-
details: 'Browser started but no page available',
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
// Connect to CDP via WebSocket
|
|
648
|
-
logger.debug('[BrowserClient] launch: connecting to page via WebSocket...');
|
|
649
|
-
this.cdp = new CDPConnection();
|
|
650
|
-
await this.cdp.connect(pageTarget.webSocketDebuggerUrl);
|
|
651
|
-
// Target connected
|
|
652
|
-
|
|
653
|
-
// Setup logging
|
|
654
|
-
this.consoleLogs = [];
|
|
655
|
-
this.networkLogs = [];
|
|
656
|
-
this.setupLogging();
|
|
657
|
-
|
|
658
|
-
// Enable Page domain
|
|
659
|
-
await this.cdp.send('Page.enable');
|
|
660
|
-
|
|
661
|
-
logger.debug('[BrowserClient] launch: browser connected successfully');
|
|
662
|
-
|
|
663
|
-
return {
|
|
664
|
-
success: true,
|
|
665
|
-
message: `${this.browserType} launched successfully`,
|
|
666
|
-
browser: this.browserType,
|
|
667
|
-
headless,
|
|
668
|
-
};
|
|
669
|
-
} catch (error) {
|
|
670
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
671
|
-
logger.debug('[BrowserClient] launch: error - ' + errorMsg);
|
|
672
|
-
return {
|
|
673
|
-
success: false,
|
|
674
|
-
error: 'Failed to launch browser',
|
|
675
|
-
details: errorMsg,
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
/**
|
|
681
|
-
* Close browser
|
|
682
|
-
*/
|
|
683
|
-
async close(): Promise<BrowserResponse> {
|
|
684
|
-
try {
|
|
685
|
-
// 1. Disconnect CDP
|
|
686
|
-
if (this.cdp) {
|
|
687
|
-
this.cdp.close();
|
|
688
|
-
}
|
|
689
|
-
this.cdp = null;
|
|
690
|
-
// Target disconnected
|
|
691
|
-
this.consoleLogs = [];
|
|
692
|
-
this.networkLogs = [];
|
|
693
|
-
|
|
694
|
-
// 2. Terminate browser process (platform-specific)
|
|
695
|
-
try {
|
|
696
|
-
if (this.platform === 'native-windows' || this.platform === 'wsl') {
|
|
697
|
-
const processName = this.browserType === 'chrome' ? 'chrome.exe' : 'msedge.exe';
|
|
698
|
-
execSync(
|
|
699
|
-
`powershell.exe -Command "Get-WmiObject Win32_Process -Filter \\"name='${processName}'\\" | Where-Object { \\$_.CommandLine -like '*local-cli*' } | ForEach-Object { Stop-Process -Id \\$_.ProcessId -Force -ErrorAction SilentlyContinue }"`,
|
|
700
|
-
{ stdio: 'ignore', timeout: 10000 }
|
|
701
|
-
);
|
|
702
|
-
} else {
|
|
703
|
-
// Native Linux - kill browser processes with our profile
|
|
704
|
-
const processName = this.browserType === 'chrome' ? 'chrome' : 'msedge';
|
|
705
|
-
execSync(
|
|
706
|
-
`pkill -f "${processName}.*local-cli-browser-profile" 2>/dev/null || true`,
|
|
707
|
-
{ stdio: 'ignore', timeout: 10000 }
|
|
708
|
-
);
|
|
709
|
-
}
|
|
710
|
-
} catch {
|
|
711
|
-
// Process doesn't exist or already terminated
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
// 3. Also terminate processes using CDP port (backup)
|
|
715
|
-
this.killExistingBrowser();
|
|
716
|
-
|
|
717
|
-
return { success: true, message: 'Browser closed' };
|
|
718
|
-
} catch (error) {
|
|
719
|
-
return {
|
|
720
|
-
success: false,
|
|
721
|
-
error: 'Failed to close browser',
|
|
722
|
-
details: error instanceof Error ? error.message : String(error),
|
|
723
|
-
};
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
/**
|
|
728
|
-
* Navigate to URL
|
|
729
|
-
*/
|
|
730
|
-
async navigate(url: string): Promise<NavigateResponse> {
|
|
731
|
-
try {
|
|
732
|
-
if (!this.cdp || !this.cdp.isConnected()) {
|
|
733
|
-
return { success: false, error: 'Browser not running. Use launch first.' };
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
await this.cdp.send('Page.navigate', { url });
|
|
737
|
-
|
|
738
|
-
// Wait for Page.loadEventFired event to reliably confirm page load completion
|
|
739
|
-
await new Promise<void>((resolve, reject) => {
|
|
740
|
-
const timeoutId = setTimeout(() => {
|
|
741
|
-
this.cdp?.off('Page.loadEventFired');
|
|
742
|
-
reject(new Error(`Navigation to ${url} timed out after 30 seconds`));
|
|
743
|
-
}, 30000);
|
|
744
|
-
|
|
745
|
-
const handler = () => {
|
|
746
|
-
clearTimeout(timeoutId);
|
|
747
|
-
this.cdp?.off('Page.loadEventFired');
|
|
748
|
-
resolve();
|
|
749
|
-
};
|
|
750
|
-
|
|
751
|
-
this.cdp?.on('Page.loadEventFired', handler);
|
|
752
|
-
});
|
|
753
|
-
|
|
754
|
-
// Get current URL and title
|
|
755
|
-
const pageInfo = await this.getCurrentPageInfo();
|
|
756
|
-
|
|
757
|
-
return {
|
|
758
|
-
success: true,
|
|
759
|
-
message: 'Navigated successfully',
|
|
760
|
-
url: pageInfo.url,
|
|
761
|
-
title: pageInfo.title,
|
|
762
|
-
};
|
|
763
|
-
} catch (error) {
|
|
764
|
-
return {
|
|
765
|
-
success: false,
|
|
766
|
-
error: 'Failed to navigate',
|
|
767
|
-
details: error instanceof Error ? error.message : String(error),
|
|
768
|
-
};
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
/**
|
|
773
|
-
* Take screenshot
|
|
774
|
-
*/
|
|
775
|
-
async screenshot(fullPage: boolean = false): Promise<ScreenshotResponse> {
|
|
776
|
-
try {
|
|
777
|
-
if (!this.cdp || !this.cdp.isConnected()) {
|
|
778
|
-
return { success: false, error: 'Browser not running. Use launch first.' };
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
// Screenshot options
|
|
782
|
-
const params: Record<string, unknown> = { format: 'png' };
|
|
783
|
-
|
|
784
|
-
if (fullPage) {
|
|
785
|
-
// Get full page dimensions
|
|
786
|
-
const layoutMetrics = await this.cdp.send('Page.getLayoutMetrics') as {
|
|
787
|
-
contentSize: { width: number; height: number };
|
|
788
|
-
};
|
|
789
|
-
|
|
790
|
-
params['clip'] = {
|
|
791
|
-
x: 0,
|
|
792
|
-
y: 0,
|
|
793
|
-
width: layoutMetrics.contentSize.width,
|
|
794
|
-
height: layoutMetrics.contentSize.height,
|
|
795
|
-
scale: 1,
|
|
796
|
-
};
|
|
797
|
-
params['captureBeyondViewport'] = true;
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
const result = await this.cdp.send('Page.captureScreenshot', params) as { data: string };
|
|
801
|
-
|
|
802
|
-
// Get current page info
|
|
803
|
-
const pageInfo = await this.getCurrentPageInfo();
|
|
804
|
-
|
|
805
|
-
return {
|
|
806
|
-
success: true,
|
|
807
|
-
message: 'Screenshot captured',
|
|
808
|
-
image: result.data,
|
|
809
|
-
format: 'png',
|
|
810
|
-
encoding: 'base64',
|
|
811
|
-
url: pageInfo.url,
|
|
812
|
-
title: pageInfo.title,
|
|
813
|
-
};
|
|
814
|
-
} catch (error) {
|
|
815
|
-
return {
|
|
816
|
-
success: false,
|
|
817
|
-
error: 'Failed to take screenshot',
|
|
818
|
-
details: error instanceof Error ? error.message : String(error),
|
|
819
|
-
};
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
/**
|
|
824
|
-
* Click element by selector
|
|
825
|
-
*/
|
|
826
|
-
async click(selector: string): Promise<BrowserResponse> {
|
|
827
|
-
try {
|
|
828
|
-
if (!this.cdp || !this.cdp.isConnected()) {
|
|
829
|
-
return { success: false, error: 'Browser not running. Use launch first.' };
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
// Click element via JavaScript
|
|
833
|
-
const result = await this.cdp.send('Runtime.evaluate', {
|
|
834
|
-
expression: `
|
|
835
|
-
(function() {
|
|
836
|
-
const el = document.querySelector(${JSON.stringify(selector)});
|
|
837
|
-
if (!el) return { success: false, error: 'Element not found' };
|
|
838
|
-
el.click();
|
|
839
|
-
return { success: true };
|
|
840
|
-
})()
|
|
841
|
-
`,
|
|
842
|
-
returnByValue: true,
|
|
843
|
-
}) as { result: { value: { success: boolean; error?: string } } };
|
|
844
|
-
|
|
845
|
-
if (!result.result.value.success) {
|
|
846
|
-
return {
|
|
847
|
-
success: false,
|
|
848
|
-
error: result.result.value.error || 'Click failed',
|
|
849
|
-
};
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
// Get current URL
|
|
853
|
-
const urlResult = await this.cdp.send('Runtime.evaluate', {
|
|
854
|
-
expression: 'window.location.href',
|
|
855
|
-
returnByValue: true,
|
|
856
|
-
}) as { result: { value: string } };
|
|
857
|
-
|
|
858
|
-
return {
|
|
859
|
-
success: true,
|
|
860
|
-
message: 'Element clicked',
|
|
861
|
-
selector,
|
|
862
|
-
current_url: urlResult.result.value,
|
|
863
|
-
};
|
|
864
|
-
} catch (error) {
|
|
865
|
-
return {
|
|
866
|
-
success: false,
|
|
867
|
-
error: 'Failed to click element',
|
|
868
|
-
details: error instanceof Error ? error.message : String(error),
|
|
869
|
-
};
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
/**
|
|
874
|
-
* Fill input field
|
|
875
|
-
*/
|
|
876
|
-
async fill(selector: string, value: string): Promise<BrowserResponse> {
|
|
877
|
-
try {
|
|
878
|
-
if (!this.cdp || !this.cdp.isConnected()) {
|
|
879
|
-
return { success: false, error: 'Browser not running. Use launch first.' };
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
// Fill element value via JavaScript
|
|
883
|
-
const result = await this.cdp.send('Runtime.evaluate', {
|
|
884
|
-
expression: `
|
|
885
|
-
(function() {
|
|
886
|
-
const el = document.querySelector(${JSON.stringify(selector)});
|
|
887
|
-
if (!el) return { success: false, error: 'Element not found' };
|
|
888
|
-
el.focus();
|
|
889
|
-
el.value = ${JSON.stringify(value)};
|
|
890
|
-
el.dispatchEvent(new Event('input', { bubbles: true }));
|
|
891
|
-
el.dispatchEvent(new Event('change', { bubbles: true }));
|
|
892
|
-
return { success: true };
|
|
893
|
-
})()
|
|
894
|
-
`,
|
|
895
|
-
returnByValue: true,
|
|
896
|
-
}) as { result: { value: { success: boolean; error?: string } } };
|
|
897
|
-
|
|
898
|
-
if (!result.result.value.success) {
|
|
899
|
-
return {
|
|
900
|
-
success: false,
|
|
901
|
-
error: result.result.value.error || 'Fill failed',
|
|
902
|
-
};
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
return {
|
|
906
|
-
success: true,
|
|
907
|
-
message: 'Field filled',
|
|
908
|
-
selector,
|
|
909
|
-
length: value.length,
|
|
910
|
-
};
|
|
911
|
-
} catch (error) {
|
|
912
|
-
return {
|
|
913
|
-
success: false,
|
|
914
|
-
error: 'Failed to fill field',
|
|
915
|
-
details: error instanceof Error ? error.message : String(error),
|
|
916
|
-
};
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
/**
|
|
921
|
-
* Get element text
|
|
922
|
-
*/
|
|
923
|
-
async getText(selector: string): Promise<BrowserResponse> {
|
|
924
|
-
try {
|
|
925
|
-
if (!this.cdp || !this.cdp.isConnected()) {
|
|
926
|
-
return { success: false, error: 'Browser not running. Use launch first.' };
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
const result = await this.cdp.send('Runtime.evaluate', {
|
|
930
|
-
expression: `
|
|
931
|
-
(function() {
|
|
932
|
-
const el = document.querySelector(${JSON.stringify(selector)});
|
|
933
|
-
if (!el) return { success: false, error: 'Element not found' };
|
|
934
|
-
return { success: true, text: el.textContent || '' };
|
|
935
|
-
})()
|
|
936
|
-
`,
|
|
937
|
-
returnByValue: true,
|
|
938
|
-
}) as { result: { value: { success: boolean; text?: string; error?: string } } };
|
|
939
|
-
|
|
940
|
-
if (!result.result.value.success) {
|
|
941
|
-
return {
|
|
942
|
-
success: false,
|
|
943
|
-
error: result.result.value.error || 'Get text failed',
|
|
944
|
-
};
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
return {
|
|
948
|
-
success: true,
|
|
949
|
-
message: 'Text retrieved',
|
|
950
|
-
selector,
|
|
951
|
-
text: result.result.value.text || '',
|
|
952
|
-
};
|
|
953
|
-
} catch (error) {
|
|
954
|
-
return {
|
|
955
|
-
success: false,
|
|
956
|
-
error: 'Failed to get text',
|
|
957
|
-
details: error instanceof Error ? error.message : String(error),
|
|
958
|
-
};
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
/**
|
|
963
|
-
* Get page info
|
|
964
|
-
*/
|
|
965
|
-
async getPageInfo(): Promise<PageInfoResponse> {
|
|
966
|
-
try {
|
|
967
|
-
if (!this.cdp || !this.cdp.isConnected()) {
|
|
968
|
-
return { success: false, error: 'Browser not running. Use launch first.' };
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
const pageInfo = await this.getCurrentPageInfo();
|
|
972
|
-
|
|
973
|
-
return {
|
|
974
|
-
success: true,
|
|
975
|
-
message: 'Page info retrieved',
|
|
976
|
-
url: pageInfo.url,
|
|
977
|
-
title: pageInfo.title,
|
|
978
|
-
};
|
|
979
|
-
} catch (error) {
|
|
980
|
-
return {
|
|
981
|
-
success: false,
|
|
982
|
-
error: 'Failed to get page info',
|
|
983
|
-
details: error instanceof Error ? error.message : String(error),
|
|
984
|
-
};
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
/**
|
|
989
|
-
* Get page HTML
|
|
990
|
-
*/
|
|
991
|
-
async getHtml(): Promise<PageInfoResponse> {
|
|
992
|
-
try {
|
|
993
|
-
if (!this.cdp || !this.cdp.isConnected()) {
|
|
994
|
-
return { success: false, error: 'Browser not running. Use launch first.' };
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
const result = await this.cdp.send('Runtime.evaluate', {
|
|
998
|
-
expression: 'JSON.stringify({ url: window.location.href, title: document.title, html: document.documentElement.outerHTML })',
|
|
999
|
-
returnByValue: true,
|
|
1000
|
-
}) as { result: { value: string } };
|
|
1001
|
-
|
|
1002
|
-
const pageInfo = JSON.parse(result.result.value);
|
|
1003
|
-
|
|
1004
|
-
return {
|
|
1005
|
-
success: true,
|
|
1006
|
-
message: 'HTML retrieved',
|
|
1007
|
-
url: pageInfo.url,
|
|
1008
|
-
title: pageInfo.title,
|
|
1009
|
-
html: pageInfo.html,
|
|
1010
|
-
};
|
|
1011
|
-
} catch (error) {
|
|
1012
|
-
return {
|
|
1013
|
-
success: false,
|
|
1014
|
-
error: 'Failed to get HTML',
|
|
1015
|
-
details: error instanceof Error ? error.message : String(error),
|
|
1016
|
-
};
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
/**
|
|
1021
|
-
* Execute JavaScript
|
|
1022
|
-
* Wraps script in async IIFE to support return statements and await
|
|
1023
|
-
*/
|
|
1024
|
-
async executeScript(script: string): Promise<BrowserResponse> {
|
|
1025
|
-
try {
|
|
1026
|
-
if (!this.cdp || !this.cdp.isConnected()) {
|
|
1027
|
-
return { success: false, error: 'Browser not running. Use launch first.' };
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
// Wrap script in async IIFE to support return statements and await
|
|
1031
|
-
const wrappedScript = `(async function() { ${script} })()`;
|
|
1032
|
-
|
|
1033
|
-
const result = await this.cdp.send('Runtime.evaluate', {
|
|
1034
|
-
expression: wrappedScript,
|
|
1035
|
-
returnByValue: true,
|
|
1036
|
-
awaitPromise: true,
|
|
1037
|
-
}) as { result: { value: unknown }; exceptionDetails?: { exception?: { description?: string }; text?: string } };
|
|
1038
|
-
|
|
1039
|
-
if (result.exceptionDetails) {
|
|
1040
|
-
return {
|
|
1041
|
-
success: false,
|
|
1042
|
-
error: 'Script execution error',
|
|
1043
|
-
details: result.exceptionDetails.exception?.description || result.exceptionDetails.text || 'Unknown error',
|
|
1044
|
-
};
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
return {
|
|
1048
|
-
success: true,
|
|
1049
|
-
message: 'Script executed',
|
|
1050
|
-
result: result.result.value,
|
|
1051
|
-
};
|
|
1052
|
-
} catch (error) {
|
|
1053
|
-
return {
|
|
1054
|
-
success: false,
|
|
1055
|
-
error: 'Failed to execute script',
|
|
1056
|
-
details: error instanceof Error ? error.message : String(error),
|
|
1057
|
-
};
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1061
|
-
/**
|
|
1062
|
-
* Get console logs
|
|
1063
|
-
*/
|
|
1064
|
-
async getConsole(): Promise<ConsoleResponse> {
|
|
1065
|
-
return {
|
|
1066
|
-
success: true,
|
|
1067
|
-
message: 'Console logs retrieved',
|
|
1068
|
-
logs: [...this.consoleLogs],
|
|
1069
|
-
count: this.consoleLogs.length,
|
|
1070
|
-
};
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
/**
|
|
1074
|
-
* Wait for element
|
|
1075
|
-
*/
|
|
1076
|
-
async waitFor(selector: string, timeout: number = 10): Promise<BrowserResponse> {
|
|
1077
|
-
try {
|
|
1078
|
-
if (!this.cdp || !this.cdp.isConnected()) {
|
|
1079
|
-
return { success: false, error: 'Browser not running. Use launch first.' };
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
const startTime = Date.now();
|
|
1083
|
-
const timeoutMs = timeout * 1000;
|
|
1084
|
-
|
|
1085
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
1086
|
-
const result = await this.cdp.send('Runtime.evaluate', {
|
|
1087
|
-
expression: `document.querySelector(${JSON.stringify(selector)}) !== null`,
|
|
1088
|
-
returnByValue: true,
|
|
1089
|
-
}) as { result: { value: boolean } };
|
|
1090
|
-
|
|
1091
|
-
if (result.result.value) {
|
|
1092
|
-
return {
|
|
1093
|
-
success: true,
|
|
1094
|
-
message: 'Element found',
|
|
1095
|
-
selector,
|
|
1096
|
-
};
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
return {
|
|
1103
|
-
success: false,
|
|
1104
|
-
error: 'Timeout waiting for element',
|
|
1105
|
-
selector,
|
|
1106
|
-
};
|
|
1107
|
-
} catch (error) {
|
|
1108
|
-
return {
|
|
1109
|
-
success: false,
|
|
1110
|
-
error: 'Timeout waiting for element',
|
|
1111
|
-
details: error instanceof Error ? error.message : String(error),
|
|
1112
|
-
};
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
|
|
1116
|
-
/**
|
|
1117
|
-
* Get network logs
|
|
1118
|
-
*/
|
|
1119
|
-
async getNetwork(): Promise<NetworkResponse> {
|
|
1120
|
-
return {
|
|
1121
|
-
success: true,
|
|
1122
|
-
message: 'Network logs retrieved',
|
|
1123
|
-
logs: [...this.networkLogs],
|
|
1124
|
-
count: this.networkLogs.length,
|
|
1125
|
-
};
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
/**
|
|
1129
|
-
* Focus browser window
|
|
1130
|
-
*/
|
|
1131
|
-
async focus(): Promise<BrowserResponse> {
|
|
1132
|
-
try {
|
|
1133
|
-
if (!this.cdp || !this.cdp.isConnected()) {
|
|
1134
|
-
return { success: false, error: 'Browser not running. Use launch first.' };
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
await this.cdp.send('Page.bringToFront');
|
|
1138
|
-
|
|
1139
|
-
return {
|
|
1140
|
-
success: true,
|
|
1141
|
-
message: 'Browser window focused',
|
|
1142
|
-
};
|
|
1143
|
-
} catch (error) {
|
|
1144
|
-
return {
|
|
1145
|
-
success: false,
|
|
1146
|
-
error: 'Failed to focus browser',
|
|
1147
|
-
details: error instanceof Error ? error.message : String(error),
|
|
1148
|
-
};
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
|
|
1152
|
-
/**
|
|
1153
|
-
* Press a keyboard key
|
|
1154
|
-
* Supports: Enter, Tab, Escape, ArrowUp, ArrowDown, ArrowLeft, ArrowRight,
|
|
1155
|
-
* Backspace, Delete, Home, End, PageUp, PageDown, F1-F12,
|
|
1156
|
-
* Control, Alt, Shift, Meta, and combinations like Control+A
|
|
1157
|
-
*/
|
|
1158
|
-
async pressKey(key: string, selector?: string): Promise<BrowserResponse> {
|
|
1159
|
-
try {
|
|
1160
|
-
if (!this.cdp || !this.cdp.isConnected()) {
|
|
1161
|
-
return { success: false, error: 'Browser not running. Use launch first.' };
|
|
1162
|
-
}
|
|
1163
|
-
|
|
1164
|
-
// Special key mapping (extended version)
|
|
1165
|
-
const keyMap: Record<string, { key: string; code: string; keyCode: number }> = {
|
|
1166
|
-
// Navigation keys
|
|
1167
|
-
'Enter': { key: 'Enter', code: 'Enter', keyCode: 13 },
|
|
1168
|
-
'Tab': { key: 'Tab', code: 'Tab', keyCode: 9 },
|
|
1169
|
-
'Escape': { key: 'Escape', code: 'Escape', keyCode: 27 },
|
|
1170
|
-
'Backspace': { key: 'Backspace', code: 'Backspace', keyCode: 8 },
|
|
1171
|
-
'Delete': { key: 'Delete', code: 'Delete', keyCode: 46 },
|
|
1172
|
-
'Space': { key: ' ', code: 'Space', keyCode: 32 },
|
|
1173
|
-
// Arrow keys
|
|
1174
|
-
'ArrowUp': { key: 'ArrowUp', code: 'ArrowUp', keyCode: 38 },
|
|
1175
|
-
'ArrowDown': { key: 'ArrowDown', code: 'ArrowDown', keyCode: 40 },
|
|
1176
|
-
'ArrowLeft': { key: 'ArrowLeft', code: 'ArrowLeft', keyCode: 37 },
|
|
1177
|
-
'ArrowRight': { key: 'ArrowRight', code: 'ArrowRight', keyCode: 39 },
|
|
1178
|
-
// Page navigation
|
|
1179
|
-
'Home': { key: 'Home', code: 'Home', keyCode: 36 },
|
|
1180
|
-
'End': { key: 'End', code: 'End', keyCode: 35 },
|
|
1181
|
-
'PageUp': { key: 'PageUp', code: 'PageUp', keyCode: 33 },
|
|
1182
|
-
'PageDown': { key: 'PageDown', code: 'PageDown', keyCode: 34 },
|
|
1183
|
-
'Insert': { key: 'Insert', code: 'Insert', keyCode: 45 },
|
|
1184
|
-
// Modifier keys
|
|
1185
|
-
'Control': { key: 'Control', code: 'ControlLeft', keyCode: 17 },
|
|
1186
|
-
'Alt': { key: 'Alt', code: 'AltLeft', keyCode: 18 },
|
|
1187
|
-
'Shift': { key: 'Shift', code: 'ShiftLeft', keyCode: 16 },
|
|
1188
|
-
'Meta': { key: 'Meta', code: 'MetaLeft', keyCode: 91 },
|
|
1189
|
-
// Function keys
|
|
1190
|
-
'F1': { key: 'F1', code: 'F1', keyCode: 112 },
|
|
1191
|
-
'F2': { key: 'F2', code: 'F2', keyCode: 113 },
|
|
1192
|
-
'F3': { key: 'F3', code: 'F3', keyCode: 114 },
|
|
1193
|
-
'F4': { key: 'F4', code: 'F4', keyCode: 115 },
|
|
1194
|
-
'F5': { key: 'F5', code: 'F5', keyCode: 116 },
|
|
1195
|
-
'F6': { key: 'F6', code: 'F6', keyCode: 117 },
|
|
1196
|
-
'F7': { key: 'F7', code: 'F7', keyCode: 118 },
|
|
1197
|
-
'F8': { key: 'F8', code: 'F8', keyCode: 119 },
|
|
1198
|
-
'F9': { key: 'F9', code: 'F9', keyCode: 120 },
|
|
1199
|
-
'F10': { key: 'F10', code: 'F10', keyCode: 121 },
|
|
1200
|
-
'F11': { key: 'F11', code: 'F11', keyCode: 122 },
|
|
1201
|
-
'F12': { key: 'F12', code: 'F12', keyCode: 123 },
|
|
1202
|
-
};
|
|
1203
|
-
|
|
1204
|
-
if (selector) {
|
|
1205
|
-
// Focus on specific element
|
|
1206
|
-
await this.cdp.send('Runtime.evaluate', {
|
|
1207
|
-
expression: `document.querySelector(${JSON.stringify(selector)})?.focus()`,
|
|
1208
|
-
});
|
|
1209
|
-
}
|
|
1210
|
-
|
|
1211
|
-
// Handle key combinations (e.g., Control+A, Shift+Tab)
|
|
1212
|
-
const parts = key.split('+');
|
|
1213
|
-
const modifiers: { ctrl?: boolean; alt?: boolean; shift?: boolean; meta?: boolean } = {};
|
|
1214
|
-
let mainKey = key;
|
|
1215
|
-
|
|
1216
|
-
if (parts.length > 1) {
|
|
1217
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
1218
|
-
const mod = parts[i]?.toLowerCase();
|
|
1219
|
-
if (mod === 'control' || mod === 'ctrl') modifiers.ctrl = true;
|
|
1220
|
-
else if (mod === 'alt') modifiers.alt = true;
|
|
1221
|
-
else if (mod === 'shift') modifiers.shift = true;
|
|
1222
|
-
else if (mod === 'meta' || mod === 'cmd') modifiers.meta = true;
|
|
1223
|
-
}
|
|
1224
|
-
mainKey = parts[parts.length - 1] || key;
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
// Handle single character upper/lowercase
|
|
1228
|
-
let keyInfo = keyMap[mainKey];
|
|
1229
|
-
if (!keyInfo) {
|
|
1230
|
-
if (mainKey.length === 1) {
|
|
1231
|
-
const charCode = mainKey.charCodeAt(0);
|
|
1232
|
-
const isUpper = mainKey >= 'A' && mainKey <= 'Z';
|
|
1233
|
-
keyInfo = {
|
|
1234
|
-
key: mainKey,
|
|
1235
|
-
code: `Key${mainKey.toUpperCase()}`,
|
|
1236
|
-
keyCode: isUpper ? charCode : charCode - 32,
|
|
1237
|
-
};
|
|
1238
|
-
} else {
|
|
1239
|
-
keyInfo = { key: mainKey, code: mainKey, keyCode: 0 };
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
// Calculate modifier flags (for CDP)
|
|
1244
|
-
let modifierFlags = 0;
|
|
1245
|
-
if (modifiers.alt) modifierFlags |= 1;
|
|
1246
|
-
if (modifiers.ctrl) modifierFlags |= 2;
|
|
1247
|
-
if (modifiers.meta) modifierFlags |= 4;
|
|
1248
|
-
if (modifiers.shift) modifierFlags |= 8;
|
|
1249
|
-
|
|
1250
|
-
// keyDown
|
|
1251
|
-
await this.cdp.send('Input.dispatchKeyEvent', {
|
|
1252
|
-
type: 'keyDown',
|
|
1253
|
-
key: keyInfo.key,
|
|
1254
|
-
code: keyInfo.code,
|
|
1255
|
-
windowsVirtualKeyCode: keyInfo.keyCode,
|
|
1256
|
-
nativeVirtualKeyCode: keyInfo.keyCode,
|
|
1257
|
-
modifiers: modifierFlags,
|
|
1258
|
-
});
|
|
1259
|
-
|
|
1260
|
-
// keyUp
|
|
1261
|
-
await this.cdp.send('Input.dispatchKeyEvent', {
|
|
1262
|
-
type: 'keyUp',
|
|
1263
|
-
key: keyInfo.key,
|
|
1264
|
-
code: keyInfo.code,
|
|
1265
|
-
windowsVirtualKeyCode: keyInfo.keyCode,
|
|
1266
|
-
nativeVirtualKeyCode: keyInfo.keyCode,
|
|
1267
|
-
modifiers: modifierFlags,
|
|
1268
|
-
});
|
|
1269
|
-
|
|
1270
|
-
return {
|
|
1271
|
-
success: true,
|
|
1272
|
-
message: `Key "${key}" pressed successfully`,
|
|
1273
|
-
key,
|
|
1274
|
-
selector: selector || '(focused element)',
|
|
1275
|
-
};
|
|
1276
|
-
} catch (error) {
|
|
1277
|
-
return {
|
|
1278
|
-
success: false,
|
|
1279
|
-
error: 'Failed to press key',
|
|
1280
|
-
details: error instanceof Error ? error.message : String(error),
|
|
1281
|
-
};
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
/**
|
|
1286
|
-
* Type text character by character
|
|
1287
|
-
*/
|
|
1288
|
-
async type(text: string, selector?: string): Promise<BrowserResponse> {
|
|
1289
|
-
try {
|
|
1290
|
-
if (!this.cdp || !this.cdp.isConnected()) {
|
|
1291
|
-
return { success: false, error: 'Browser not running. Use launch first.' };
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
if (selector) {
|
|
1295
|
-
// Focus on specific element
|
|
1296
|
-
await this.cdp.send('Runtime.evaluate', {
|
|
1297
|
-
expression: `document.querySelector(${JSON.stringify(selector)})?.focus()`,
|
|
1298
|
-
});
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
// Type character by character
|
|
1302
|
-
for (const char of text) {
|
|
1303
|
-
await this.cdp.send('Input.dispatchKeyEvent', {
|
|
1304
|
-
type: 'char',
|
|
1305
|
-
text: char,
|
|
1306
|
-
});
|
|
1307
|
-
await new Promise(resolve => setTimeout(resolve, 50));
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
return {
|
|
1311
|
-
success: true,
|
|
1312
|
-
message: `Typed ${text.length} characters`,
|
|
1313
|
-
length: text.length,
|
|
1314
|
-
};
|
|
1315
|
-
} catch (error) {
|
|
1316
|
-
return {
|
|
1317
|
-
success: false,
|
|
1318
|
-
error: 'Failed to type text',
|
|
1319
|
-
details: error instanceof Error ? error.message : String(error),
|
|
1320
|
-
};
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
|
-
/**
|
|
1325
|
-
* Check if browser is currently active
|
|
1326
|
-
*/
|
|
1327
|
-
async isBrowserActive(): Promise<boolean> {
|
|
1328
|
-
return this.cdp !== null && this.cdp.isConnected();
|
|
1329
|
-
}
|
|
1330
|
-
|
|
1331
|
-
/**
|
|
1332
|
-
* Save screenshot to file and return path
|
|
1333
|
-
*/
|
|
1334
|
-
saveScreenshot(base64Image: string, prefix: string = 'browser'): string {
|
|
1335
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
1336
|
-
const filename = `${prefix}_${timestamp}.png`;
|
|
1337
|
-
const filepath = path.join(this.screenshotDir, filename);
|
|
1338
|
-
|
|
1339
|
-
const imageBuffer = Buffer.from(base64Image, 'base64');
|
|
1340
|
-
fs.writeFileSync(filepath, imageBuffer);
|
|
1341
|
-
|
|
1342
|
-
logger.debug('[BrowserClient] saveScreenshot: saved to ' + filepath);
|
|
1343
|
-
return filepath;
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
/**
|
|
1347
|
-
* For compatibility: getServerExePath
|
|
1348
|
-
*/
|
|
1349
|
-
getServerExePath(): string | null {
|
|
1350
|
-
return null;
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
/**
|
|
1354
|
-
* For compatibility: getServerUrl
|
|
1355
|
-
*/
|
|
1356
|
-
getServerUrl(): string {
|
|
1357
|
-
return this.getCDPUrl();
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
|
|
1361
|
-
// Export singleton instance
|
|
1362
|
-
export const browserClient = new BrowserClient();
|
|
1363
|
-
export type { BrowserResponse, HealthResponse, ScreenshotResponse, NavigateResponse, PageInfoResponse, ConsoleResponse, NetworkResponse };
|