orbitx 0.0.8 → 0.0.9
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 +227 -67
- package/dist/core/agent-providers.d.ts +16 -0
- package/dist/core/agent-providers.d.ts.map +1 -0
- package/dist/core/agent-providers.js +21 -0
- package/dist/core/agent-providers.js.map +1 -0
- package/dist/core/ai-provider.d.ts +69 -1
- package/dist/core/ai-provider.d.ts.map +1 -1
- package/dist/core/ai-provider.js.map +1 -1
- package/dist/core/base-agent.d.ts +8 -4
- package/dist/core/base-agent.d.ts.map +1 -1
- package/dist/core/base-agent.js +220 -88
- package/dist/core/base-agent.js.map +1 -1
- package/dist/core/deepseek-provider.d.ts +10 -3
- package/dist/core/deepseek-provider.d.ts.map +1 -1
- package/dist/core/deepseek-provider.js +144 -39
- package/dist/core/deepseek-provider.js.map +1 -1
- package/dist/core/image-describer.d.ts +13 -0
- package/dist/core/image-describer.d.ts.map +1 -0
- package/dist/core/image-describer.js +33 -0
- package/dist/core/image-describer.js.map +1 -0
- package/dist/core/mcp-client.d.ts +17 -4
- package/dist/core/mcp-client.d.ts.map +1 -1
- package/dist/core/mcp-client.js +32 -16
- package/dist/core/mcp-client.js.map +1 -1
- package/dist/core/mcp-computer.d.ts +10 -2
- package/dist/core/mcp-computer.d.ts.map +1 -1
- package/dist/core/mcp-computer.js +108 -2
- package/dist/core/mcp-computer.js.map +1 -1
- package/dist/core/mcp-fs-storage.d.ts +8 -0
- package/dist/core/mcp-fs-storage.d.ts.map +1 -0
- package/dist/core/mcp-fs-storage.js +27 -0
- package/dist/core/mcp-fs-storage.js.map +1 -0
- package/dist/core/mcp-rng.d.ts +7 -0
- package/dist/core/mcp-rng.d.ts.map +1 -0
- package/dist/core/mcp-rng.js +14 -0
- package/dist/core/mcp-rng.js.map +1 -0
- package/dist/core/mcp-server.d.ts +8 -4
- package/dist/core/mcp-server.d.ts.map +1 -1
- package/dist/core/mcp-server.js +20 -3
- package/dist/core/mcp-server.js.map +1 -1
- package/dist/core/mcp-storage.d.ts +5 -0
- package/dist/core/mcp-storage.d.ts.map +1 -0
- package/dist/core/mcp-storage.js +3 -0
- package/dist/core/mcp-storage.js.map +1 -0
- package/dist/core/mcp.d.ts +37 -3
- package/dist/core/mcp.d.ts.map +1 -1
- package/dist/core/mcp.js +42 -1
- package/dist/core/mcp.js.map +1 -1
- package/dist/core/ollama-provider.d.ts +10 -3
- package/dist/core/ollama-provider.d.ts.map +1 -1
- package/dist/core/ollama-provider.js +122 -41
- package/dist/core/ollama-provider.js.map +1 -1
- package/dist/core/retry.d.ts +10 -0
- package/dist/core/retry.d.ts.map +1 -0
- package/dist/core/retry.js +39 -0
- package/dist/core/retry.js.map +1 -0
- package/dist/core/skill.d.ts +3 -0
- package/dist/core/skill.d.ts.map +1 -1
- package/dist/core/skill.js.map +1 -1
- package/dist/core/tool-schema-translator.d.ts +10 -0
- package/dist/core/tool-schema-translator.d.ts.map +1 -0
- package/dist/core/tool-schema-translator.js +29 -0
- package/dist/core/tool-schema-translator.js.map +1 -0
- package/dist/index.d.ts +34 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -5
- package/dist/index.js.map +1 -1
- package/dist/sandbox.d.ts +2 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +27 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/skills/backend-security.d.ts +4 -0
- package/dist/skills/backend-security.d.ts.map +1 -0
- package/dist/skills/backend-security.js +74 -0
- package/dist/skills/backend-security.js.map +1 -0
- package/dist/skills/big-task.d.ts +4 -0
- package/dist/skills/big-task.d.ts.map +1 -0
- package/dist/skills/big-task.js +66 -0
- package/dist/skills/big-task.js.map +1 -0
- package/dist/skills/code-verification.d.ts +4 -0
- package/dist/skills/code-verification.d.ts.map +1 -0
- package/dist/skills/code-verification.js +59 -0
- package/dist/skills/code-verification.js.map +1 -0
- package/dist/skills/long-task-efficiency.d.ts +4 -0
- package/dist/skills/long-task-efficiency.d.ts.map +1 -0
- package/dist/skills/long-task-efficiency.js +50 -0
- package/dist/skills/long-task-efficiency.js.map +1 -0
- package/dist/skills/node-backend.d.ts +4 -0
- package/dist/skills/node-backend.d.ts.map +1 -0
- package/dist/skills/node-backend.js +110 -0
- package/dist/skills/node-backend.js.map +1 -0
- package/dist/skills/planner.d.ts +4 -0
- package/dist/skills/planner.d.ts.map +1 -0
- package/dist/skills/planner.js +49 -0
- package/dist/skills/planner.js.map +1 -0
- package/dist/skills/present.d.ts +4 -0
- package/dist/skills/present.d.ts.map +1 -0
- package/dist/skills/present.js +56 -0
- package/dist/skills/present.js.map +1 -0
- package/dist/skills/question-answer.d.ts +4 -0
- package/dist/skills/question-answer.d.ts.map +1 -0
- package/dist/skills/question-answer.js +55 -0
- package/dist/skills/question-answer.js.map +1 -0
- package/dist/skills/react-frontend.d.ts +4 -0
- package/dist/skills/react-frontend.d.ts.map +1 -0
- package/dist/skills/react-frontend.js +111 -0
- package/dist/skills/react-frontend.js.map +1 -0
- package/dist/skills/research.d.ts +4 -0
- package/dist/skills/research.d.ts.map +1 -0
- package/dist/skills/research.js +81 -0
- package/dist/skills/research.js.map +1 -0
- package/dist/skills/shopping.d.ts +4 -0
- package/dist/skills/shopping.d.ts.map +1 -0
- package/dist/skills/shopping.js +71 -0
- package/dist/skills/shopping.js.map +1 -0
- package/dist/skills/ui-ux-design.d.ts +4 -0
- package/dist/skills/ui-ux-design.d.ts.map +1 -0
- package/dist/skills/ui-ux-design.js +70 -0
- package/dist/skills/ui-ux-design.js.map +1 -0
- package/dist/skills/web-end-to-end-test.d.ts +4 -0
- package/dist/skills/web-end-to-end-test.d.ts.map +1 -0
- package/dist/skills/web-end-to-end-test.js +76 -0
- package/dist/skills/web-end-to-end-test.js.map +1 -0
- package/dist/templates/simple.d.ts +1 -1
- package/dist/templates/simple.d.ts.map +1 -1
- package/dist/templates/simple.js +4 -0
- package/dist/templates/simple.js.map +1 -1
- package/dist/tests/mcp.test.js +2 -54
- package/dist/tests/mcp.test.js.map +1 -1
- package/dist/tools/bash/index.d.ts +10 -0
- package/dist/tools/bash/index.d.ts.map +1 -0
- package/dist/tools/bash/index.js +22 -0
- package/dist/tools/bash/index.js.map +1 -0
- package/dist/tools/bash/interaction.d.ts +29 -0
- package/dist/tools/bash/interaction.d.ts.map +1 -0
- package/dist/tools/bash/interaction.js +13 -0
- package/dist/tools/bash/interaction.js.map +1 -0
- package/dist/tools/bash/list.d.ts +4 -0
- package/dist/tools/bash/list.d.ts.map +1 -0
- package/dist/tools/bash/list.js +23 -0
- package/dist/tools/bash/list.js.map +1 -0
- package/dist/tools/bash/logs.d.ts +4 -0
- package/dist/tools/bash/logs.d.ts.map +1 -0
- package/dist/tools/bash/logs.js +47 -0
- package/dist/tools/bash/logs.js.map +1 -0
- package/dist/tools/bash/process-manager.d.ts +35 -0
- package/dist/tools/bash/process-manager.d.ts.map +1 -0
- package/dist/tools/bash/process-manager.js +137 -0
- package/dist/tools/bash/process-manager.js.map +1 -0
- package/dist/tools/bash/run.d.ts +5 -0
- package/dist/tools/bash/run.d.ts.map +1 -0
- package/dist/tools/bash/run.js +57 -0
- package/dist/tools/bash/run.js.map +1 -0
- package/dist/tools/bash/terminate.d.ts +5 -0
- package/dist/tools/bash/terminate.d.ts.map +1 -0
- package/dist/tools/bash/terminate.js +39 -0
- package/dist/tools/bash/terminate.js.map +1 -0
- package/dist/tools/bash/wait.d.ts +5 -0
- package/dist/tools/bash/wait.d.ts.map +1 -0
- package/dist/tools/bash/wait.js +50 -0
- package/dist/tools/bash/wait.js.map +1 -0
- package/dist/tools/bash/write-input.d.ts +5 -0
- package/dist/tools/bash/write-input.d.ts.map +1 -0
- package/dist/tools/bash/write-input.js +47 -0
- package/dist/tools/bash/write-input.js.map +1 -0
- package/dist/tools/browser/click.d.ts +5 -0
- package/dist/tools/browser/click.d.ts.map +1 -0
- package/dist/tools/browser/click.js +44 -0
- package/dist/tools/browser/click.js.map +1 -0
- package/dist/tools/browser/console.d.ts +4 -0
- package/dist/tools/browser/console.d.ts.map +1 -0
- package/dist/tools/browser/console.js +41 -0
- package/dist/tools/browser/console.js.map +1 -0
- package/dist/tools/browser/create-session.d.ts +5 -0
- package/dist/tools/browser/create-session.d.ts.map +1 -0
- package/dist/tools/browser/create-session.js +30 -0
- package/dist/tools/browser/create-session.js.map +1 -0
- package/dist/tools/browser/evaluate-safe.d.ts +10 -0
- package/dist/tools/browser/evaluate-safe.d.ts.map +1 -0
- package/dist/tools/browser/evaluate-safe.js +65 -0
- package/dist/tools/browser/evaluate-safe.js.map +1 -0
- package/dist/tools/browser/fill.d.ts +5 -0
- package/dist/tools/browser/fill.d.ts.map +1 -0
- package/dist/tools/browser/fill.js +78 -0
- package/dist/tools/browser/fill.js.map +1 -0
- package/dist/tools/browser/get-sessions.d.ts +4 -0
- package/dist/tools/browser/get-sessions.d.ts.map +1 -0
- package/dist/tools/browser/get-sessions.js +14 -0
- package/dist/tools/browser/get-sessions.js.map +1 -0
- package/dist/tools/browser/index.d.ts +19 -0
- package/dist/tools/browser/index.d.ts.map +1 -0
- package/dist/tools/browser/index.js +49 -0
- package/dist/tools/browser/index.js.map +1 -0
- package/dist/tools/browser/inject.d.ts +5 -0
- package/dist/tools/browser/inject.d.ts.map +1 -0
- package/dist/tools/browser/inject.js +51 -0
- package/dist/tools/browser/inject.js.map +1 -0
- package/dist/tools/browser/interaction.d.ts +49 -0
- package/dist/tools/browser/interaction.d.ts.map +1 -0
- package/dist/tools/browser/interaction.js +14 -0
- package/dist/tools/browser/interaction.js.map +1 -0
- package/dist/tools/browser/navigate.d.ts +5 -0
- package/dist/tools/browser/navigate.d.ts.map +1 -0
- package/dist/tools/browser/navigate.js +39 -0
- package/dist/tools/browser/navigate.js.map +1 -0
- package/dist/tools/browser/network-status.d.ts +4 -0
- package/dist/tools/browser/network-status.d.ts.map +1 -0
- package/dist/tools/browser/network-status.js +35 -0
- package/dist/tools/browser/network-status.js.map +1 -0
- package/dist/tools/browser/network.d.ts +4 -0
- package/dist/tools/browser/network.d.ts.map +1 -0
- package/dist/tools/browser/network.js +51 -0
- package/dist/tools/browser/network.js.map +1 -0
- package/dist/tools/browser/read-page.d.ts +45 -0
- package/dist/tools/browser/read-page.d.ts.map +1 -0
- package/dist/tools/browser/read-page.js +264 -0
- package/dist/tools/browser/read-page.js.map +1 -0
- package/dist/tools/browser/read.d.ts +5 -0
- package/dist/tools/browser/read.d.ts.map +1 -0
- package/dist/tools/browser/read.js +56 -0
- package/dist/tools/browser/read.js.map +1 -0
- package/dist/tools/browser/remove-session.d.ts +5 -0
- package/dist/tools/browser/remove-session.d.ts.map +1 -0
- package/dist/tools/browser/remove-session.js +29 -0
- package/dist/tools/browser/remove-session.js.map +1 -0
- package/dist/tools/browser/screenshot.d.ts +5 -0
- package/dist/tools/browser/screenshot.d.ts.map +1 -0
- package/dist/tools/browser/screenshot.js +50 -0
- package/dist/tools/browser/screenshot.js.map +1 -0
- package/dist/tools/browser/scroll-info.d.ts +4 -0
- package/dist/tools/browser/scroll-info.d.ts.map +1 -0
- package/dist/tools/browser/scroll-info.js +28 -0
- package/dist/tools/browser/scroll-info.js.map +1 -0
- package/dist/tools/browser/scroll.d.ts +5 -0
- package/dist/tools/browser/scroll.d.ts.map +1 -0
- package/dist/tools/browser/scroll.js +43 -0
- package/dist/tools/browser/scroll.js.map +1 -0
- package/dist/tools/browser/session-manager.d.ts +35 -0
- package/dist/tools/browser/session-manager.d.ts.map +1 -0
- package/dist/tools/browser/session-manager.js +101 -0
- package/dist/tools/browser/session-manager.js.map +1 -0
- package/dist/tools/browser/submit-form.d.ts +5 -0
- package/dist/tools/browser/submit-form.d.ts.map +1 -0
- package/dist/tools/browser/submit-form.js +45 -0
- package/dist/tools/browser/submit-form.js.map +1 -0
- package/dist/tools/fs/create-dir.d.ts +5 -0
- package/dist/tools/fs/create-dir.d.ts.map +1 -0
- package/dist/tools/fs/create-dir.js +28 -0
- package/dist/tools/fs/create-dir.js.map +1 -0
- package/dist/tools/fs/delete.d.ts +5 -0
- package/dist/tools/fs/delete.d.ts.map +1 -0
- package/dist/tools/fs/delete.js +45 -0
- package/dist/tools/fs/delete.js.map +1 -0
- package/dist/tools/fs/edit-file.d.ts +5 -0
- package/dist/tools/fs/edit-file.d.ts.map +1 -0
- package/dist/tools/fs/edit-file.js +74 -0
- package/dist/tools/fs/edit-file.js.map +1 -0
- package/dist/tools/fs/index.d.ts +11 -2
- package/dist/tools/fs/index.d.ts.map +1 -1
- package/dist/tools/fs/index.js +27 -2
- package/dist/tools/fs/index.js.map +1 -1
- package/dist/tools/fs/interaction.d.ts +37 -0
- package/dist/tools/fs/interaction.d.ts.map +1 -0
- package/dist/tools/fs/interaction.js +13 -0
- package/dist/tools/fs/interaction.js.map +1 -0
- package/dist/tools/fs/list-dir.d.ts +5 -0
- package/dist/tools/fs/list-dir.d.ts.map +1 -0
- package/dist/tools/fs/list-dir.js +87 -0
- package/dist/tools/fs/list-dir.js.map +1 -0
- package/dist/tools/fs/move.d.ts +5 -0
- package/dist/tools/fs/move.d.ts.map +1 -0
- package/dist/tools/fs/move.js +44 -0
- package/dist/tools/fs/move.js.map +1 -0
- package/dist/tools/fs/read-file.d.ts +4 -3
- package/dist/tools/fs/read-file.d.ts.map +1 -1
- package/dist/tools/fs/read-file.js +50 -42
- package/dist/tools/fs/read-file.js.map +1 -1
- package/dist/tools/fs/stat.d.ts +5 -0
- package/dist/tools/fs/stat.d.ts.map +1 -0
- package/dist/tools/fs/stat.js +40 -0
- package/dist/tools/fs/stat.js.map +1 -0
- package/dist/tools/fs/utils.d.ts +20 -0
- package/dist/tools/fs/utils.d.ts.map +1 -0
- package/dist/tools/fs/utils.js +33 -0
- package/dist/tools/fs/utils.js.map +1 -0
- package/dist/tools/fs/write-file.d.ts +4 -3
- package/dist/tools/fs/write-file.d.ts.map +1 -1
- package/dist/tools/fs/write-file.js +39 -58
- package/dist/tools/fs/write-file.js.map +1 -1
- package/dist/tools/present/add.d.ts +5 -0
- package/dist/tools/present/add.d.ts.map +1 -0
- package/dist/tools/present/add.js +54 -0
- package/dist/tools/present/add.js.map +1 -0
- package/dist/tools/present/clear.d.ts +5 -0
- package/dist/tools/present/clear.d.ts.map +1 -0
- package/dist/tools/present/clear.js +23 -0
- package/dist/tools/present/clear.js.map +1 -0
- package/dist/tools/present/get-list.d.ts +5 -0
- package/dist/tools/present/get-list.d.ts.map +1 -0
- package/dist/tools/present/get-list.js +24 -0
- package/dist/tools/present/get-list.js.map +1 -0
- package/dist/tools/present/index.d.ts +8 -0
- package/dist/tools/present/index.d.ts.map +1 -0
- package/dist/tools/present/index.js +14 -0
- package/dist/tools/present/index.js.map +1 -0
- package/dist/tools/present/interaction.d.ts +17 -0
- package/dist/tools/present/interaction.d.ts.map +1 -0
- package/dist/tools/present/interaction.js +15 -0
- package/dist/tools/present/interaction.js.map +1 -0
- package/dist/tools/present/utils.d.ts +12 -0
- package/dist/tools/present/utils.d.ts.map +1 -0
- package/dist/tools/present/utils.js +40 -0
- package/dist/tools/present/utils.js.map +1 -0
- package/dist/tools/question-answer/index.d.ts +5 -0
- package/dist/tools/question-answer/index.d.ts.map +1 -0
- package/dist/tools/question-answer/index.js +7 -0
- package/dist/tools/question-answer/index.js.map +1 -0
- package/dist/tools/question-answer/interaction.d.ts +14 -0
- package/dist/tools/question-answer/interaction.d.ts.map +1 -0
- package/dist/tools/question-answer/interaction.js +13 -0
- package/dist/tools/question-answer/interaction.js.map +1 -0
- package/dist/tools/question-answer/question-answer.d.ts +5 -0
- package/dist/tools/question-answer/question-answer.d.ts.map +1 -0
- package/dist/tools/question-answer/question-answer.js +24 -0
- package/dist/tools/question-answer/question-answer.js.map +1 -0
- package/dist/tools/todo/check-task.d.ts +5 -0
- package/dist/tools/todo/check-task.d.ts.map +1 -0
- package/dist/tools/todo/check-task.js +49 -0
- package/dist/tools/todo/check-task.js.map +1 -0
- package/dist/tools/todo/create-list.d.ts +5 -0
- package/dist/tools/todo/create-list.d.ts.map +1 -0
- package/dist/tools/todo/create-list.js +36 -0
- package/dist/tools/todo/create-list.js.map +1 -0
- package/dist/tools/todo/create-task.d.ts +5 -0
- package/dist/tools/todo/create-task.d.ts.map +1 -0
- package/dist/tools/todo/create-task.js +63 -0
- package/dist/tools/todo/create-task.js.map +1 -0
- package/dist/tools/todo/get-list.d.ts +4 -0
- package/dist/tools/todo/get-list.d.ts.map +1 -0
- package/dist/tools/todo/get-list.js +38 -0
- package/dist/tools/todo/get-list.js.map +1 -0
- package/dist/tools/todo/get-lists.d.ts +4 -0
- package/dist/tools/todo/get-lists.d.ts.map +1 -0
- package/dist/tools/todo/get-lists.js +18 -0
- package/dist/tools/todo/get-lists.js.map +1 -0
- package/dist/tools/todo/index.d.ts +12 -0
- package/dist/tools/todo/index.d.ts.map +1 -0
- package/dist/tools/todo/index.js +25 -0
- package/dist/tools/todo/index.js.map +1 -0
- package/dist/tools/todo/interaction.d.ts +30 -0
- package/dist/tools/todo/interaction.d.ts.map +1 -0
- package/dist/tools/todo/interaction.js +13 -0
- package/dist/tools/todo/interaction.js.map +1 -0
- package/dist/tools/todo/remove-list.d.ts +5 -0
- package/dist/tools/todo/remove-list.d.ts.map +1 -0
- package/dist/tools/todo/remove-list.js +42 -0
- package/dist/tools/todo/remove-list.js.map +1 -0
- package/dist/tools/todo/remove-task.d.ts +5 -0
- package/dist/tools/todo/remove-task.d.ts.map +1 -0
- package/dist/tools/todo/remove-task.js +45 -0
- package/dist/tools/todo/remove-task.js.map +1 -0
- package/dist/tools/todo/storage.d.ts +22 -0
- package/dist/tools/todo/storage.d.ts.map +1 -0
- package/dist/tools/todo/storage.js +44 -0
- package/dist/tools/todo/storage.js.map +1 -0
- package/dist/tools/utils/delay.d.ts +10 -0
- package/dist/tools/utils/delay.d.ts.map +1 -0
- package/dist/tools/utils/delay.js +33 -0
- package/dist/tools/utils/delay.js.map +1 -0
- package/dist/tools/utils/get-current-time.d.ts +7 -2
- package/dist/tools/utils/get-current-time.d.ts.map +1 -1
- package/dist/tools/utils/get-current-time.js +12 -31
- package/dist/tools/utils/get-current-time.js.map +1 -1
- package/dist/tools/utils/index.d.ts +2 -0
- package/dist/tools/utils/index.d.ts.map +1 -1
- package/dist/tools/utils/index.js +7 -0
- package/dist/tools/utils/index.js.map +1 -1
- package/package.json +54 -56
- package/dist/templates/researcher.d.ts +0 -27
- package/dist/templates/researcher.d.ts.map +0 -1
- package/dist/templates/researcher.js +0 -70
- package/dist/templates/researcher.js.map +0 -1
- package/dist/tools/www/fetch.d.ts +0 -4
- package/dist/tools/www/fetch.d.ts.map +0 -1
- package/dist/tools/www/fetch.js +0 -147
- package/dist/tools/www/fetch.js.map +0 -1
- package/dist/tools/www/index.d.ts +0 -4
- package/dist/tools/www/index.d.ts.map +0 -1
- package/dist/tools/www/index.js +0 -4
- package/dist/tools/www/index.js.map +0 -1
- package/dist/tools/www/read-web-page.d.ts +0 -4
- package/dist/tools/www/read-web-page.d.ts.map +0 -1
- package/dist/tools/www/read-web-page.js +0 -330
- package/dist/tools/www/read-web-page.js.map +0 -1
- package/dist/tools/www/web-search.d.ts +0 -4
- package/dist/tools/www/web-search.d.ts.map +0 -1
- package/dist/tools/www/web-search.js +0 -82
- package/dist/tools/www/web-search.js.map +0 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Page } from "puppeteer-core";
|
|
2
|
+
import { type MCP } from "../../core/mcp.js";
|
|
3
|
+
import type { BrowserSession } from "./session-manager.js";
|
|
4
|
+
export interface ReadPageResult {
|
|
5
|
+
content: string;
|
|
6
|
+
totalLines: number;
|
|
7
|
+
/**
|
|
8
|
+
* present only when there are more lines after the returned window;
|
|
9
|
+
* pass it back in as `ref` on the next browser-read call to keep paging
|
|
10
|
+
* through the SAME captured snapshot (no new DOM walk, no new ref ids)
|
|
11
|
+
* instead of re-reading the live page.
|
|
12
|
+
*/
|
|
13
|
+
ref?: string;
|
|
14
|
+
}
|
|
15
|
+
/** Resolves a ref id previously handed out by readPage() back to its live element, or null if it's no longer on the page. */
|
|
16
|
+
export declare function resolveRef(page: Page, ref: string): Promise<import("puppeteer-core").ElementHandle<Element> | null>;
|
|
17
|
+
/**
|
|
18
|
+
* Resolves the ref id of the <form> that a given fillable/clickable element
|
|
19
|
+
* ref lives inside, or null if that element isn't inside a form. Used by
|
|
20
|
+
* browser-fill to know whether it should also submit the form after typing
|
|
21
|
+
* (i.e. the form has no visible submit button, so pressing Enter is the
|
|
22
|
+
* only way a real user could submit it).
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveFormForRef(page: Page, ref: string): Promise<{
|
|
25
|
+
formRef: string;
|
|
26
|
+
hasSubmitButton: boolean;
|
|
27
|
+
} | null>;
|
|
28
|
+
/** Submits a form via its ref id, the same way a browser does when a lone text field receives Enter. */
|
|
29
|
+
export declare function submitForm(page: Page, formRef: string): Promise<boolean>;
|
|
30
|
+
/**
|
|
31
|
+
* Reads the current page into a readable, indented text outline (h1-h6, p,
|
|
32
|
+
* table cells, links, inputs, buttons, images), assigning a fresh unique ref
|
|
33
|
+
* id to every clickable/fillable element so the agent can act on it later
|
|
34
|
+
* via browser-click / browser-fill. Supports pagination via offsetLine/limitLine.
|
|
35
|
+
*
|
|
36
|
+
* The FULL, untruncated outline (every line, not just the requested window)
|
|
37
|
+
* is always saved to MCP storage under a fresh ref id, and that ref id is
|
|
38
|
+
* returned whenever the response was truncated. Passing that ref back in via
|
|
39
|
+
* `continueRef` skips re-walking the live DOM entirely and just pages
|
|
40
|
+
* through the previously captured text — useful once the agent has already
|
|
41
|
+
* read part of a long page and wants the rest without generating new
|
|
42
|
+
* (and therefore mismatched) click/fill ref ids.
|
|
43
|
+
*/
|
|
44
|
+
export declare function readPage(mcp: MCP | undefined, session: BrowserSession, offsetLine: number, limitLine: number, continueRef?: string): Promise<ReadPageResult>;
|
|
45
|
+
//# sourceMappingURL=read-page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-page.d.ts","sourceRoot":"","sources":["../../../src/tools/browser/read-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAiB,KAAK,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAkJ3D,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,6HAA6H;AAC7H,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,mEAEvD;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAAC,CAa9H;AAED,wGAAwG;AACxG,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAW9E;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAsB,QAAQ,CAC1B,GAAG,EAAE,GAAG,GAAG,SAAS,EACpB,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,cAAc,CAAC,CA+GzB"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { generateRefId } from "../../core/mcp.js";
|
|
2
|
+
const READABLE_TAGS = new Set([
|
|
3
|
+
"h1", "h2", "h3", "h4", "h5", "h6",
|
|
4
|
+
"p", "span", "li", "td", "th", "label", "a", "button",
|
|
5
|
+
"input", "textarea", "select", "img",
|
|
6
|
+
]);
|
|
7
|
+
const CLICKABLE_TAGS = new Set(["a", "button"]);
|
|
8
|
+
const FILLABLE_TAGS = new Set(["input", "textarea", "select"]);
|
|
9
|
+
/**
|
|
10
|
+
* Walks the live DOM in-page and produces a flat, depth-annotated outline of visible text/interactive nodes.
|
|
11
|
+
*
|
|
12
|
+
* IMPORTANT: The function passed to page.evaluate() is serialized via
|
|
13
|
+
* Function.prototype.toString() and executed in an isolated browser
|
|
14
|
+
* context that has NO access to this module's scope. Under esbuild/tsx,
|
|
15
|
+
* nested `function foo() {}` declarations get wrapped with a module-local
|
|
16
|
+
* `__name(foo, "foo")` helper call (for Function.name preservation), and
|
|
17
|
+
* that helper reference leaks into the serialized source, causing
|
|
18
|
+
* `ReferenceError: __name is not defined` inside the page. To avoid this,
|
|
19
|
+
* every helper inside the evaluate() callback below is a `const` arrow
|
|
20
|
+
* function instead of a named function declaration.
|
|
21
|
+
*/
|
|
22
|
+
async function extractOutline(page) {
|
|
23
|
+
return page.evaluate((readableTags, clickableTags, fillableTags) => {
|
|
24
|
+
const readable = new Set(readableTags);
|
|
25
|
+
const clickable = new Set(clickableTags);
|
|
26
|
+
const fillable = new Set(fillableTags);
|
|
27
|
+
const results = [];
|
|
28
|
+
let domIndex = 0;
|
|
29
|
+
// assign every <form> on the page a stable index (independent of
|
|
30
|
+
// walk() so it's known before we need to reference it from inputs
|
|
31
|
+
// nested inside it), and figure out up front whether each form has
|
|
32
|
+
// any visible element capable of submitting it.
|
|
33
|
+
const forms = Array.from(document.querySelectorAll("form"));
|
|
34
|
+
const formIndexOf = new Map();
|
|
35
|
+
const formHasSubmit = new Map();
|
|
36
|
+
forms.forEach((form, i) => {
|
|
37
|
+
formIndexOf.set(form, i);
|
|
38
|
+
const submitEl = form.querySelector('button:not([type="button"]):not([type="reset"]), input[type="submit"], input[type="image"], button[type="submit"]');
|
|
39
|
+
formHasSubmit.set(i, !!submitEl);
|
|
40
|
+
});
|
|
41
|
+
const nearestForm = (el) => {
|
|
42
|
+
return el.closest("form");
|
|
43
|
+
};
|
|
44
|
+
const isVisible = (el) => {
|
|
45
|
+
const style = window.getComputedStyle(el);
|
|
46
|
+
if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0")
|
|
47
|
+
return false;
|
|
48
|
+
const rect = el.getBoundingClientRect();
|
|
49
|
+
return rect.width > 0 && rect.height > 0;
|
|
50
|
+
};
|
|
51
|
+
const textOf = (el) => {
|
|
52
|
+
if (el.tagName.toLowerCase() === "img") {
|
|
53
|
+
return el.getAttribute("alt") || "";
|
|
54
|
+
}
|
|
55
|
+
if (el.tagName.toLowerCase() === "input" || el.tagName.toLowerCase() === "textarea") {
|
|
56
|
+
return el.placeholder || el.value || "";
|
|
57
|
+
}
|
|
58
|
+
// direct text content only (avoid re-printing children we'll visit separately)
|
|
59
|
+
let text = "";
|
|
60
|
+
for (const child of Array.from(el.childNodes)) {
|
|
61
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
62
|
+
text += child.textContent || "";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return text.trim();
|
|
66
|
+
};
|
|
67
|
+
const walk = (el, depth) => {
|
|
68
|
+
const currentIndex = domIndex++;
|
|
69
|
+
const tag = el.tagName.toLowerCase();
|
|
70
|
+
const isFormEl = tag === "form";
|
|
71
|
+
if ((readable.has(tag) || isFormEl) && isVisible(el)) {
|
|
72
|
+
const text = isFormEl ? "" : textOf(el);
|
|
73
|
+
const isInteractive = clickable.has(tag) || fillable.has(tag) || !!el.onclick;
|
|
74
|
+
if (text || isInteractive || isFormEl) {
|
|
75
|
+
if (isInteractive || isFormEl) {
|
|
76
|
+
// Marker attribute lets us re-select this exact element
|
|
77
|
+
// from outside evaluate() without relying on any
|
|
78
|
+
// custom global helper surviving across calls.
|
|
79
|
+
el.setAttribute("data-orbitx-dom-index", String(currentIndex));
|
|
80
|
+
}
|
|
81
|
+
const parentForm = fillable.has(tag) || clickable.has(tag) ? nearestForm(el) : null;
|
|
82
|
+
const parentFormIndex = parentForm ? formIndexOf.get(parentForm) : undefined;
|
|
83
|
+
results.push({
|
|
84
|
+
tag,
|
|
85
|
+
text,
|
|
86
|
+
depth,
|
|
87
|
+
domIndex: currentIndex,
|
|
88
|
+
clickable: clickable.has(tag) || !!el.onclick,
|
|
89
|
+
fillable: fillable.has(tag),
|
|
90
|
+
formIndex: isFormEl ? formIndexOf.get(el) : parentFormIndex,
|
|
91
|
+
isForm: isFormEl,
|
|
92
|
+
formHasNoSubmitButton: isFormEl
|
|
93
|
+
? !formHasSubmit.get(formIndexOf.get(el))
|
|
94
|
+
: parentFormIndex !== undefined
|
|
95
|
+
? !formHasSubmit.get(parentFormIndex)
|
|
96
|
+
: undefined,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
for (const child of Array.from(el.children)) {
|
|
101
|
+
walk(child, depth + (readable.has(tag) || isFormEl ? 1 : 0));
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
if (document.body)
|
|
105
|
+
walk(document.body, 0);
|
|
106
|
+
return results;
|
|
107
|
+
}, Array.from(READABLE_TAGS), Array.from(CLICKABLE_TAGS), Array.from(FILLABLE_TAGS));
|
|
108
|
+
}
|
|
109
|
+
/** Resolves a ref id previously handed out by readPage() back to its live element, or null if it's no longer on the page. */
|
|
110
|
+
export async function resolveRef(page, ref) {
|
|
111
|
+
return page.$(`[data-orbitx-ref="${ref}"]`);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Resolves the ref id of the <form> that a given fillable/clickable element
|
|
115
|
+
* ref lives inside, or null if that element isn't inside a form. Used by
|
|
116
|
+
* browser-fill to know whether it should also submit the form after typing
|
|
117
|
+
* (i.e. the form has no visible submit button, so pressing Enter is the
|
|
118
|
+
* only way a real user could submit it).
|
|
119
|
+
*/
|
|
120
|
+
export async function resolveFormForRef(page, ref) {
|
|
121
|
+
return page.evaluate((r) => {
|
|
122
|
+
const el = document.querySelector(`[data-orbitx-ref="${r}"]`);
|
|
123
|
+
if (!el)
|
|
124
|
+
return null;
|
|
125
|
+
const form = el.closest("form");
|
|
126
|
+
if (!form)
|
|
127
|
+
return null;
|
|
128
|
+
const formRef = form.getAttribute("data-orbitx-ref");
|
|
129
|
+
if (!formRef)
|
|
130
|
+
return null;
|
|
131
|
+
const hasSubmitButton = !!form.querySelector('button:not([type="button"]):not([type="reset"]), input[type="submit"], input[type="image"], button[type="submit"]');
|
|
132
|
+
return { formRef, hasSubmitButton };
|
|
133
|
+
}, ref);
|
|
134
|
+
}
|
|
135
|
+
/** Submits a form via its ref id, the same way a browser does when a lone text field receives Enter. */
|
|
136
|
+
export async function submitForm(page, formRef) {
|
|
137
|
+
return page.evaluate((r) => {
|
|
138
|
+
const form = document.querySelector(`[data-orbitx-ref="${r}"]`);
|
|
139
|
+
if (!form)
|
|
140
|
+
return false;
|
|
141
|
+
if (typeof form.requestSubmit === "function") {
|
|
142
|
+
form.requestSubmit();
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
form.submit();
|
|
146
|
+
}
|
|
147
|
+
return true;
|
|
148
|
+
}, formRef);
|
|
149
|
+
}
|
|
150
|
+
const READ_PAGE_STORAGE_PREFIX = "browser-read-page:";
|
|
151
|
+
/**
|
|
152
|
+
* Reads the current page into a readable, indented text outline (h1-h6, p,
|
|
153
|
+
* table cells, links, inputs, buttons, images), assigning a fresh unique ref
|
|
154
|
+
* id to every clickable/fillable element so the agent can act on it later
|
|
155
|
+
* via browser-click / browser-fill. Supports pagination via offsetLine/limitLine.
|
|
156
|
+
*
|
|
157
|
+
* The FULL, untruncated outline (every line, not just the requested window)
|
|
158
|
+
* is always saved to MCP storage under a fresh ref id, and that ref id is
|
|
159
|
+
* returned whenever the response was truncated. Passing that ref back in via
|
|
160
|
+
* `continueRef` skips re-walking the live DOM entirely and just pages
|
|
161
|
+
* through the previously captured text — useful once the agent has already
|
|
162
|
+
* read part of a long page and wants the rest without generating new
|
|
163
|
+
* (and therefore mismatched) click/fill ref ids.
|
|
164
|
+
*/
|
|
165
|
+
export async function readPage(mcp, session, offsetLine, limitLine, continueRef) {
|
|
166
|
+
if (continueRef) {
|
|
167
|
+
const stored = mcp ? await mcp.getStorage().get(READ_PAGE_STORAGE_PREFIX + continueRef) : "";
|
|
168
|
+
if (!stored) {
|
|
169
|
+
throw new Error(`ref "${continueRef}" was not found in storage (it may have expired, or belongs to a different session) — call browser-read without continueRef to take a fresh read of the page`);
|
|
170
|
+
}
|
|
171
|
+
const lines = stored.split("\n");
|
|
172
|
+
const totalLines = lines.length;
|
|
173
|
+
const windowed = lines.slice(offsetLine, offsetLine + limitLine);
|
|
174
|
+
const hasMore = offsetLine + limitLine < totalLines;
|
|
175
|
+
return {
|
|
176
|
+
content: windowed.join("\n"),
|
|
177
|
+
totalLines,
|
|
178
|
+
ref: hasMore ? continueRef : undefined,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
// Clear markers left over from a previous read so this read's domIndex
|
|
182
|
+
// numbering (which restarts at 0 every call) can't collide with them.
|
|
183
|
+
await session.page.evaluate(() => {
|
|
184
|
+
for (const el of Array.from(document.querySelectorAll("[data-orbitx-dom-index]"))) {
|
|
185
|
+
el.removeAttribute("data-orbitx-dom-index");
|
|
186
|
+
}
|
|
187
|
+
for (const el of Array.from(document.querySelectorAll("[data-orbitx-ref]"))) {
|
|
188
|
+
el.removeAttribute("data-orbitx-ref");
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
const nodes = await extractOutline(session.page);
|
|
192
|
+
const lines = [];
|
|
193
|
+
const domIndexToRef = new Map();
|
|
194
|
+
// one ref per distinct form domIndex, so fillable inputs can report
|
|
195
|
+
// which form they belong to and the agent can submit it directly
|
|
196
|
+
const formIndexToRef = new Map();
|
|
197
|
+
for (const node of nodes) {
|
|
198
|
+
if (node.isForm && node.formIndex !== undefined && !formIndexToRef.has(node.formIndex)) {
|
|
199
|
+
const ref = await generateRefId(mcp);
|
|
200
|
+
formIndexToRef.set(node.formIndex, ref);
|
|
201
|
+
domIndexToRef.set(node.domIndex, ref);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
for (const node of nodes) {
|
|
205
|
+
const indent = " ".repeat(node.depth);
|
|
206
|
+
let suffix = "";
|
|
207
|
+
if (node.isForm) {
|
|
208
|
+
const ref = node.formIndex !== undefined ? formIndexToRef.get(node.formIndex) : undefined;
|
|
209
|
+
suffix = ref ? ` [${ref}] [FORM]${node.formHasNoSubmitButton ? " [NO SUBMIT BUTTON: use browser-submit-form with this ref, or fill+Enter]" : ""}` : "";
|
|
210
|
+
lines.push(`${indent}- form${suffix}`);
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (node.clickable || node.fillable) {
|
|
214
|
+
const ref = await generateRefId(mcp);
|
|
215
|
+
domIndexToRef.set(node.domIndex, ref);
|
|
216
|
+
const formRef = node.formIndex !== undefined ? formIndexToRef.get(node.formIndex) : undefined;
|
|
217
|
+
suffix = ` [${ref}]${node.fillable ? " [FILLABLE]" : ""}${node.clickable ? " [CLICKABLE]" : ""}`;
|
|
218
|
+
if (node.fillable && node.formIndex !== undefined) {
|
|
219
|
+
suffix += node.formHasNoSubmitButton
|
|
220
|
+
? ` [inside form ${formRef}, NO SUBMIT BUTTON — submitting this field (e.g. pressing Enter) will submit form ${formRef}]`
|
|
221
|
+
: ` [inside form ${formRef}]`;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const label = node.text || "(empty)";
|
|
225
|
+
lines.push(`${indent}- ${node.tag}: ${label}${suffix}`);
|
|
226
|
+
}
|
|
227
|
+
// Stamp every interactive element (and every form) with its ref id
|
|
228
|
+
// (data-orbitx-ref) so browser-click / browser-fill / browser-submit-form
|
|
229
|
+
// can re-select it later purely from the ref string via page.$, without
|
|
230
|
+
// depending on a long-lived ElementHandle (handles can go stale once the
|
|
231
|
+
// DOM changes between tool calls).
|
|
232
|
+
if (domIndexToRef.size > 0) {
|
|
233
|
+
await session.page.evaluate((entries) => {
|
|
234
|
+
for (const [domIndex, ref] of entries) {
|
|
235
|
+
const el = document.querySelector(`[data-orbitx-dom-index="${domIndex}"]`);
|
|
236
|
+
if (el) {
|
|
237
|
+
el.setAttribute("data-orbitx-ref", ref);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}, Array.from(domIndexToRef.entries()));
|
|
241
|
+
}
|
|
242
|
+
const totalLines = lines.length;
|
|
243
|
+
const windowed = lines.slice(offsetLine, offsetLine + limitLine);
|
|
244
|
+
const hasMore = offsetLine + limitLine < totalLines;
|
|
245
|
+
// Always persist the complete, untruncated outline so a later call can
|
|
246
|
+
// page through the rest of it via continueRef without re-walking the
|
|
247
|
+
// DOM (which would hand out a fresh, incompatible set of ref ids).
|
|
248
|
+
let ref;
|
|
249
|
+
if (mcp) {
|
|
250
|
+
ref = await generateRefId(mcp);
|
|
251
|
+
await mcp.getStorage().set(READ_PAGE_STORAGE_PREFIX + ref, lines.join("\n"));
|
|
252
|
+
}
|
|
253
|
+
let content = windowed.join("\n");
|
|
254
|
+
if (hasMore) {
|
|
255
|
+
const remaining = totalLines - (offsetLine + limitLine);
|
|
256
|
+
content += `\n\n[... ${remaining} more line(s) not shown${ref ? ` — call browser-read again with continueRef: "${ref}" and a new offsetLine to keep reading` : ""}]`;
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
content,
|
|
260
|
+
totalLines,
|
|
261
|
+
ref: hasMore ? ref : undefined,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=read-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-page.js","sourceRoot":"","sources":["../../../src/tools/browser/read-page.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/tools/browser/read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAY,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAItD,eAAO,MAAM,eAAe,mCA2D1B,CAAC;AAEH,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { MCPTool } from "../../core/mcp.js";
|
|
2
|
+
import { BrowserInteraction } from "./interaction.js";
|
|
3
|
+
import { getSession } from "./session-manager.js";
|
|
4
|
+
import { readPage } from "./read-page.js";
|
|
5
|
+
export const BrowserReadTool = () => new MCPTool({
|
|
6
|
+
name: "browser-read",
|
|
7
|
+
description: "read the current page as a readable text outline (headings, paragraphs, tables, links, inputs, buttons, images, and forms), assigning a ref id to every clickable/fillable element for use with browser-click / browser-fill. " +
|
|
8
|
+
"forms are shown with their own ref, and any fillable field with no visible submit button nearby is flagged so you know pressing Enter (or browser-submit-form) is required to submit it. " +
|
|
9
|
+
"if the outline is too long to fit in one response, the output is truncated and a `ref` is returned — call this tool again with `continueRef` set to that value (and a new `offsetLine`) to keep reading the SAME captured snapshot without generating new element refs. " +
|
|
10
|
+
"do not pass `continueRef` on your first read of a page, or after the page has navigated/changed — only use it to keep paging through output you already started reading.",
|
|
11
|
+
inputs: [
|
|
12
|
+
{
|
|
13
|
+
name: "sessionId",
|
|
14
|
+
type: "string",
|
|
15
|
+
description: "session to read",
|
|
16
|
+
required: true,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: "offsetLine",
|
|
20
|
+
type: "number",
|
|
21
|
+
description: "line offset to start reading from",
|
|
22
|
+
required: false,
|
|
23
|
+
default: 0,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: "limitLine",
|
|
27
|
+
type: "number",
|
|
28
|
+
description: "max number of lines to return",
|
|
29
|
+
required: false,
|
|
30
|
+
default: 200,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: "continueRef",
|
|
34
|
+
type: "string",
|
|
35
|
+
description: "ref id returned by a previous browser-read call whose output was truncated; continues paging through that same snapshot instead of re-reading the live page",
|
|
36
|
+
required: false,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
customClass: new BrowserInteraction(),
|
|
40
|
+
execute: async (_envID, inputs, mcp, customClass) => {
|
|
41
|
+
const { sessionId, offsetLine = 0, limitLine = 200, continueRef } = inputs;
|
|
42
|
+
if (!sessionId || typeof sessionId !== "string") {
|
|
43
|
+
throw new Error("sessionId must be a non-empty string");
|
|
44
|
+
}
|
|
45
|
+
customClass?.emitBrowserEvent({ type: "reading", sessionId });
|
|
46
|
+
const session = getSession(sessionId);
|
|
47
|
+
const result = await readPage(mcp, session, offsetLine, limitLine, continueRef);
|
|
48
|
+
return {
|
|
49
|
+
content: result.content,
|
|
50
|
+
totalLines: result.totalLines,
|
|
51
|
+
ref: result.ref,
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
export default BrowserReadTool;
|
|
56
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/tools/browser/read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAY,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,EAAE,CAAC,IAAI,OAAO,CAAqB;IACjE,IAAI,EAAE,cAAc;IACpB,WAAW,EACP,gOAAgO;QAChO,2LAA2L;QAC3L,0QAA0Q;QAC1Q,0KAA0K;IAC9K,MAAM,EAAE;QACJ;YACI,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,iBAAiB;YAC9B,QAAQ,EAAE,IAAI;SACjB;QACD;YACI,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,mCAAmC;YAChD,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,CAAC;SACb;QACD;YACI,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,+BAA+B;YAC5C,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,GAAG;SACf;QACD;YACI,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,6JAA6J;YAC1K,QAAQ,EAAE,KAAK;SAClB;KACJ;IACD,WAAW,EAAE,IAAI,kBAAkB,EAAE;IACrC,OAAO,EAAE,KAAK,EACV,MAAc,EACd,MAA2B,EAC3B,GAAS,EACT,WAAgC,EACpB,EAAE;QACd,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,CAAC,EAAE,SAAS,GAAG,GAAG,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;QAE3E,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC5D,CAAC;QAED,WAAW,EAAE,gBAAgB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;QAE9D,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QAEhF,OAAO;YACH,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,GAAG,EAAE,MAAM,CAAC,GAAG;SAClB,CAAC;IACN,CAAC;CACJ,CAAC,CAAC;AAEH,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { MCPTool } from "../../core/mcp.js";
|
|
2
|
+
import { BrowserInteraction } from "./interaction.js";
|
|
3
|
+
export declare const BrowserRemoveSessionTool: () => MCPTool<BrowserInteraction>;
|
|
4
|
+
export default BrowserRemoveSessionTool;
|
|
5
|
+
//# sourceMappingURL=remove-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remove-session.d.ts","sourceRoot":"","sources":["../../../src/tools/browser/remove-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGtD,eAAO,MAAM,wBAAwB,mCAgCnC,CAAC;AAEH,eAAe,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MCPTool } from "../../core/mcp.js";
|
|
2
|
+
import { BrowserInteraction } from "./interaction.js";
|
|
3
|
+
import { removeSession } from "./session-manager.js";
|
|
4
|
+
export const BrowserRemoveSessionTool = () => new MCPTool({
|
|
5
|
+
name: "browser-remove-session",
|
|
6
|
+
description: "close and remove a browser session",
|
|
7
|
+
inputs: [
|
|
8
|
+
{
|
|
9
|
+
name: "sessionId",
|
|
10
|
+
type: "string",
|
|
11
|
+
description: "session to close",
|
|
12
|
+
required: true,
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
customClass: new BrowserInteraction(),
|
|
16
|
+
execute: async (_envID, inputs, _mcp, customClass) => {
|
|
17
|
+
const { sessionId } = inputs;
|
|
18
|
+
if (!sessionId || typeof sessionId !== "string") {
|
|
19
|
+
throw new Error("sessionId must be a non-empty string");
|
|
20
|
+
}
|
|
21
|
+
await removeSession(sessionId);
|
|
22
|
+
customClass?.emitBrowserEvent({ type: "session-removed", sessionId });
|
|
23
|
+
return {
|
|
24
|
+
message: "success",
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
export default BrowserRemoveSessionTool;
|
|
29
|
+
//# sourceMappingURL=remove-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remove-session.js","sourceRoot":"","sources":["../../../src/tools/browser/remove-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,EAAE,CAAC,IAAI,OAAO,CAAqB;IAC1E,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EAAE,oCAAoC;IACjD,MAAM,EAAE;QACJ;YACI,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,kBAAkB;YAC/B,QAAQ,EAAE,IAAI;SACjB;KACJ;IACD,WAAW,EAAE,IAAI,kBAAkB,EAAE;IACrC,OAAO,EAAE,KAAK,EACV,MAAc,EACd,MAA2B,EAC3B,IAAU,EACV,WAAgC,EACpB,EAAE;QACd,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;QAE7B,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;QAE/B,WAAW,EAAE,gBAAgB,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,SAAS,EAAE,CAAC,CAAC;QAEtE,OAAO;YACH,OAAO,EAAE,SAAS;SACrB,CAAC;IACN,CAAC;CACJ,CAAC,CAAC;AAEH,eAAe,wBAAwB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../../src/tools/browser/screenshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGtD,eAAO,MAAM,qBAAqB,mCAsDhC,CAAC;AAEH,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { MCPTool } from "../../core/mcp.js";
|
|
2
|
+
import { BrowserInteraction } from "./interaction.js";
|
|
3
|
+
import { getSession } from "./session-manager.js";
|
|
4
|
+
export const BrowserScreenshotTool = () => new MCPTool({
|
|
5
|
+
name: "browser-screenshot",
|
|
6
|
+
description: "capture a screenshot of the current page in a browser session. " +
|
|
7
|
+
"returns an image tool-output — depending on how the agent is configured, the raw image may be handed directly to the model, or first described by a separate image-capable AI so the main conversation doesn't have to carry image bytes. " +
|
|
8
|
+
"use `focusHint` to tell that description step what you actually care about (e.g. 'look for any red error banner or visually broken layout'), so the resulting description is useful for your task instead of a generic caption.",
|
|
9
|
+
inputs: [
|
|
10
|
+
{
|
|
11
|
+
name: "sessionId",
|
|
12
|
+
type: "string",
|
|
13
|
+
description: "session to screenshot",
|
|
14
|
+
required: true,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "fullPage",
|
|
18
|
+
type: "boolean",
|
|
19
|
+
description: "capture the full scrollable page instead of just the current viewport",
|
|
20
|
+
required: false,
|
|
21
|
+
default: false,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: "focusHint",
|
|
25
|
+
type: "string",
|
|
26
|
+
description: "what to focus on when describing the screenshot, e.g. 'look for any red object or any bug on the UI'",
|
|
27
|
+
required: false,
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
customClass: new BrowserInteraction(),
|
|
31
|
+
execute: async (_envID, inputs, _mcp, customClass) => {
|
|
32
|
+
const { sessionId, fullPage = false, focusHint } = inputs;
|
|
33
|
+
if (!sessionId || typeof sessionId !== "string") {
|
|
34
|
+
throw new Error("sessionId must be a non-empty string");
|
|
35
|
+
}
|
|
36
|
+
customClass?.emitBrowserEvent({ type: "screenshotting", sessionId });
|
|
37
|
+
const session = getSession(sessionId);
|
|
38
|
+
const image = await session.page.screenshot({ encoding: "base64", fullPage, type: "png" });
|
|
39
|
+
return {
|
|
40
|
+
type: "image",
|
|
41
|
+
output: {
|
|
42
|
+
image,
|
|
43
|
+
mimeType: "image/png",
|
|
44
|
+
...(focusHint ? { focusHint } : {}),
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
export default BrowserScreenshotTool;
|
|
50
|
+
//# sourceMappingURL=screenshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../../src/tools/browser/screenshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,EAAE,CAAC,IAAI,OAAO,CAAqB;IACvE,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACP,iEAAiE;QACjE,4OAA4O;QAC5O,iOAAiO;IACrO,MAAM,EAAE;QACJ;YACI,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,uBAAuB;YACpC,QAAQ,EAAE,IAAI;SACjB;QACD;YACI,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,uEAAuE;YACpF,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,KAAK;SACjB;QACD;YACI,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,sGAAsG;YACnH,QAAQ,EAAE,KAAK;SAClB;KACJ;IACD,WAAW,EAAE,IAAI,kBAAkB,EAAE;IACrC,OAAO,EAAE,KAAK,EACV,MAAc,EACd,MAA2B,EAC3B,IAAU,EACV,WAAgC,EACpB,EAAE;QACd,MAAM,EAAE,SAAS,EAAE,QAAQ,GAAG,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;QAE1D,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC5D,CAAC;QAED,WAAW,EAAE,gBAAgB,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,CAAC,CAAC;QAErE,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAE3F,OAAO;YACH,IAAI,EAAE,OAAO;YACb,MAAM,EAAE;gBACJ,KAAK;gBACL,QAAQ,EAAE,WAAW;gBACrB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtC;SACJ,CAAC;IACN,CAAC;CACJ,CAAC,CAAC;AAEH,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll-info.d.ts","sourceRoot":"","sources":["../../../src/tools/browser/scroll-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAG5C,eAAO,MAAM,qBAAqB,0BA2BhC,CAAC;AAEH,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { MCPTool } from "../../core/mcp.js";
|
|
2
|
+
import { getSession } from "./session-manager.js";
|
|
3
|
+
export const BrowserScrollInfoTool = () => new MCPTool({
|
|
4
|
+
name: "browser-scroll-info",
|
|
5
|
+
description: "get the total scrollable length and current scroll position of the page",
|
|
6
|
+
inputs: [
|
|
7
|
+
{
|
|
8
|
+
name: "sessionId",
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "session to inspect",
|
|
11
|
+
required: true,
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
execute: async (_envID, inputs) => {
|
|
15
|
+
const { sessionId } = inputs;
|
|
16
|
+
if (!sessionId || typeof sessionId !== "string") {
|
|
17
|
+
throw new Error("sessionId must be a non-empty string");
|
|
18
|
+
}
|
|
19
|
+
const session = getSession(sessionId);
|
|
20
|
+
const info = await session.page.evaluate(() => ({
|
|
21
|
+
length: document.documentElement.scrollHeight,
|
|
22
|
+
position: window.scrollY,
|
|
23
|
+
}));
|
|
24
|
+
return info;
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
export default BrowserScrollInfoTool;
|
|
28
|
+
//# sourceMappingURL=scroll-info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll-info.js","sourceRoot":"","sources":["../../../src/tools/browser/scroll-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,EAAE,CAAC,IAAI,OAAO,CAAC;IACnD,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EAAE,yEAAyE;IACtF,MAAM,EAAE;QACJ;YACI,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,oBAAoB;YACjC,QAAQ,EAAE,IAAI;SACjB;KACJ;IACD,OAAO,EAAE,KAAK,EAAE,MAAc,EAAE,MAA2B,EAAgB,EAAE;QACzE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;QAE7B,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QAEtC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;YAC5C,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,YAAY;YAC7C,QAAQ,EAAE,MAAM,CAAC,OAAO;SAC3B,CAAC,CAAC,CAAC;QAEJ,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ,CAAC,CAAC;AAEH,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll.d.ts","sourceRoot":"","sources":["../../../src/tools/browser/scroll.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGtD,eAAO,MAAM,iBAAiB,mCAgD5B,CAAC;AAEH,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { MCPTool } from "../../core/mcp.js";
|
|
2
|
+
import { BrowserInteraction } from "./interaction.js";
|
|
3
|
+
import { getSession } from "./session-manager.js";
|
|
4
|
+
export const BrowserScrollTool = () => new MCPTool({
|
|
5
|
+
name: "browser-scroll",
|
|
6
|
+
description: "scroll the page to a given vertical position (in pixels)",
|
|
7
|
+
inputs: [
|
|
8
|
+
{
|
|
9
|
+
name: "sessionId",
|
|
10
|
+
type: "string",
|
|
11
|
+
description: "session to scroll",
|
|
12
|
+
required: true,
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: "position",
|
|
16
|
+
type: "number",
|
|
17
|
+
description: "target vertical scroll position, in pixels",
|
|
18
|
+
required: true,
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
customClass: new BrowserInteraction(),
|
|
22
|
+
execute: async (_envID, inputs, _mcp, customClass) => {
|
|
23
|
+
const { sessionId, position } = inputs;
|
|
24
|
+
if (!sessionId || typeof sessionId !== "string") {
|
|
25
|
+
throw new Error("sessionId must be a non-empty string");
|
|
26
|
+
}
|
|
27
|
+
if (typeof position !== "number" || !Number.isFinite(position)) {
|
|
28
|
+
throw new Error("position must be a number");
|
|
29
|
+
}
|
|
30
|
+
customClass?.emitBrowserEvent({ type: "scrolling", sessionId, position });
|
|
31
|
+
const session = getSession(sessionId);
|
|
32
|
+
const info = await session.page.evaluate((pos) => {
|
|
33
|
+
window.scrollTo(0, pos);
|
|
34
|
+
return {
|
|
35
|
+
length: document.documentElement.scrollHeight,
|
|
36
|
+
position: window.scrollY,
|
|
37
|
+
};
|
|
38
|
+
}, position);
|
|
39
|
+
return info;
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
export default BrowserScrollTool;
|
|
43
|
+
//# sourceMappingURL=scroll.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll.js","sourceRoot":"","sources":["../../../src/tools/browser/scroll.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,EAAE,CAAC,IAAI,OAAO,CAAqB;IACnE,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,0DAA0D;IACvE,MAAM,EAAE;QACJ;YACI,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,mBAAmB;YAChC,QAAQ,EAAE,IAAI;SACjB;QACD;YACI,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,4CAA4C;YACzD,QAAQ,EAAE,IAAI;SACjB;KACJ;IACD,WAAW,EAAE,IAAI,kBAAkB,EAAE;IACrC,OAAO,EAAE,KAAK,EACV,MAAc,EACd,MAA2B,EAC3B,IAAU,EACV,WAAgC,EACpB,EAAE;QACd,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;QAEvC,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC5D,CAAC;QAED,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QACjD,CAAC;QAED,WAAW,EAAE,gBAAgB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QAE1E,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QAEtC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAW,EAAE,EAAE;YACrD,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YACxB,OAAO;gBACH,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,YAAY;gBAC7C,QAAQ,EAAE,MAAM,CAAC,OAAO;aAC3B,CAAC;QACN,CAAC,EAAE,QAAQ,CAAC,CAAC;QAEb,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ,CAAC,CAAC;AAEH,eAAe,iBAAiB,CAAC"}
|