@ashx-j/lunr 0.2.26 → 0.2.27
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/CHANGELOG.md +16 -1
- package/LICENSE +22 -0
- package/dist/builtin-extensions/ashxj-thinking.d.ts +1 -1
- package/dist/builtin-extensions/ashxj-thinking.d.ts.map +1 -1
- package/dist/builtin-extensions/ashxj-thinking.js +1 -1
- package/dist/builtin-extensions/ashxj-thinking.js.map +1 -1
- package/dist/builtin-extensions/ashxj-tui.d.ts +11 -1
- package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
- package/dist/builtin-extensions/ashxj-tui.js +6 -10
- package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
- package/dist/builtin-extensions/lunr-cron.d.ts +4 -5
- package/dist/builtin-extensions/lunr-cron.d.ts.map +1 -1
- package/dist/builtin-extensions/lunr-cron.js +94 -108
- package/dist/builtin-extensions/lunr-cron.js.map +1 -1
- package/dist/builtin-extensions/lunr-local-providers/local-servers.d.ts.map +1 -1
- package/dist/builtin-extensions/lunr-local-providers/local-servers.js +3 -1
- package/dist/builtin-extensions/lunr-local-providers/local-servers.js.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.d.ts.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.js +2 -2
- package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.js.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.d.ts.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.d.ts.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.js +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.js.map +1 -1
- package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-intercom/index.js +2 -2
- package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.d.ts +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.js +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/index.js +1 -15
- package/dist/builtin-extensions/pi-lsp-extension/src/index.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.d.ts +6 -0
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.js +187 -132
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.d.ts +8 -0
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.js +142 -112
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.d.ts +12 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.js +14 -7
- package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.d.ts +11 -3
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.js +67 -41
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.d.ts +4 -2
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.js +3 -0
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/commands.d.ts +2 -1
- package/dist/builtin-extensions/pi-mcp-adapter/commands.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/commands.js +6 -6
- package/dist/builtin-extensions/pi-mcp-adapter/commands.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/config.d.ts +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/config.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/config.js +11 -5
- package/dist/builtin-extensions/pi-mcp-adapter/config.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js +2 -2
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/host-html-template.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/host-html-template.js +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/host-html-template.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/index.js +48 -40
- package/dist/builtin-extensions/pi-mcp-adapter/index.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/init.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/init.js +3 -1
- package/dist/builtin-extensions/pi-mcp-adapter/init.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.d.ts +12 -40
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.js +166 -235
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.d.ts +5 -0
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.js +43 -13
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.d.ts +14 -3
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.js +73 -21
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/proxy-modes.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/proxy-modes.js +4 -4
- package/dist/builtin-extensions/pi-mcp-adapter/proxy-modes.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js +2 -2
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/state.d.ts +2 -0
- package/dist/builtin-extensions/pi-mcp-adapter/state.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/state.js.map +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/index.d.ts +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/index.js +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/index.js.map +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/models.d.ts +11 -5
- package/dist/builtin-extensions/pi-ollama-cloud/models.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/models.js +12 -32
- package/dist/builtin-extensions/pi-ollama-cloud/models.js.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/index.js +5 -3
- package/dist/builtin-extensions/pi-prompt-template-model/index.js.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.d.ts +2 -1
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js +21 -12
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js +7 -24
- package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js +39 -77
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js +15 -31
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js +7 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +10 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +8 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +106 -24
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +25 -5
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +7 -8
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js +60 -32
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/utils.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/utils.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/utils.js +15 -5
- package/dist/builtin-extensions/pi-subagents/src/shared/utils.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +4 -3
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js +17 -8
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/review.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js +3 -3
- package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js.map +1 -1
- package/dist/builtin-extensions/pi-tps.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-tps.js +20 -17
- package/dist/builtin-extensions/pi-tps.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/activity.d.ts +1 -0
- package/dist/builtin-extensions/pi-web-access/activity.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/activity.js +27 -5
- package/dist/builtin-extensions/pi-web-access/activity.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/bounded-body.d.ts +3 -0
- package/dist/builtin-extensions/pi-web-access/bounded-body.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-web-access/bounded-body.js +43 -0
- package/dist/builtin-extensions/pi-web-access/bounded-body.js.map +1 -0
- package/dist/builtin-extensions/pi-web-access/content-page.d.ts +24 -0
- package/dist/builtin-extensions/pi-web-access/content-page.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-web-access/content-page.js +57 -0
- package/dist/builtin-extensions/pi-web-access/content-page.js.map +1 -0
- package/dist/builtin-extensions/pi-web-access/extract.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/extract.js +7 -2
- package/dist/builtin-extensions/pi-web-access/extract.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/github-extract.d.ts +0 -1
- package/dist/builtin-extensions/pi-web-access/github-extract.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/github-extract.js +147 -36
- package/dist/builtin-extensions/pi-web-access/github-extract.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/index.js +48 -73
- package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts +12 -4
- package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/session-cleanup.js +35 -12
- package/dist/builtin-extensions/pi-web-access/session-cleanup.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/storage.d.ts +9 -6
- package/dist/builtin-extensions/pi-web-access/storage.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/storage.js +36 -24
- package/dist/builtin-extensions/pi-web-access/storage.js.map +1 -1
- package/dist/builtin-extensions/simple-pi-memory.d.ts +1 -1
- package/dist/builtin-extensions/simple-pi-memory.d.ts.map +1 -1
- package/dist/builtin-extensions/simple-pi-memory.js +1 -1
- package/dist/builtin-extensions/simple-pi-memory.js.map +1 -1
- package/dist/cli/install-cli.d.ts.map +1 -1
- package/dist/cli/install-cli.js +38 -30
- package/dist/cli/install-cli.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +13 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +75 -11
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +40 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +309 -76
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/browser/runtime.d.ts +2 -0
- package/dist/core/browser/runtime.d.ts.map +1 -1
- package/dist/core/browser/runtime.js +80 -45
- package/dist/core/browser/runtime.js.map +1 -1
- package/dist/core/browser/setup.d.ts.map +1 -1
- package/dist/core/browser/setup.js +12 -1
- package/dist/core/browser/setup.js.map +1 -1
- package/dist/core/computer-use/adapter.d.ts.map +1 -1
- package/dist/core/computer-use/adapter.js +7 -2
- package/dist/core/computer-use/adapter.js.map +1 -1
- package/dist/core/computer-use/image.d.ts.map +1 -1
- package/dist/core/computer-use/image.js +17 -5
- package/dist/core/computer-use/image.js.map +1 -1
- package/dist/core/computer-use/schemas.d.ts.map +1 -1
- package/dist/core/computer-use/schemas.js +23 -6
- package/dist/core/computer-use/schemas.js.map +1 -1
- package/dist/core/computer-use/workflow.d.ts.map +1 -1
- package/dist/core/computer-use/workflow.js +459 -119
- package/dist/core/computer-use/workflow.js.map +1 -1
- package/dist/core/cron/jobs.d.ts +26 -8
- package/dist/core/cron/jobs.d.ts.map +1 -1
- package/dist/core/cron/jobs.js +357 -232
- package/dist/core/cron/jobs.js.map +1 -1
- package/dist/core/cron/origin-context.d.ts +1 -0
- package/dist/core/cron/origin-context.d.ts.map +1 -1
- package/dist/core/cron/origin-context.js.map +1 -1
- package/dist/core/cron/scheduler.d.ts +22 -17
- package/dist/core/cron/scheduler.d.ts.map +1 -1
- package/dist/core/cron/scheduler.js +153 -73
- package/dist/core/cron/scheduler.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +8 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +8 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +4 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +22 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/large-subagent-launch.d.ts +1 -1
- package/dist/core/large-subagent-launch.d.ts.map +1 -1
- package/dist/core/large-subagent-launch.js +7 -7
- package/dist/core/large-subagent-launch.js.map +1 -1
- package/dist/core/model-registry.d.ts +2 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +5 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-runtime.d.ts +4 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +40 -4
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/permissions.d.ts +3 -3
- package/dist/core/permissions.d.ts.map +1 -1
- package/dist/core/permissions.js +11 -35
- package/dist/core/permissions.js.map +1 -1
- package/dist/core/plan-mode.d.ts +5 -13
- package/dist/core/plan-mode.d.ts.map +1 -1
- package/dist/core/plan-mode.js +126 -116
- package/dist/core/plan-mode.js.map +1 -1
- package/dist/core/project-trust.d.ts.map +1 -1
- package/dist/core/project-trust.js +1 -1
- package/dist/core/project-trust.js.map +1 -1
- package/dist/core/prompt-resource-bridge.d.ts +12 -0
- package/dist/core/prompt-resource-bridge.d.ts.map +1 -0
- package/dist/core/prompt-resource-bridge.js +9 -0
- package/dist/core/prompt-resource-bridge.js.map +1 -0
- package/dist/core/protected-targets.d.ts +6 -0
- package/dist/core/protected-targets.d.ts.map +1 -0
- package/dist/core/protected-targets.js +45 -0
- package/dist/core/protected-targets.js.map +1 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +7 -0
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/rollback.d.ts +19 -3
- package/dist/core/rollback.d.ts.map +1 -1
- package/dist/core/rollback.js +172 -56
- package/dist/core/rollback.js.map +1 -1
- package/dist/core/runtime-credentials.d.ts +3 -0
- package/dist/core/runtime-credentials.d.ts.map +1 -1
- package/dist/core/runtime-credentials.js +14 -1
- package/dist/core/runtime-credentials.js.map +1 -1
- package/dist/core/sdk.d.ts +3 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +6 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +95 -32
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-ownership.d.ts.map +1 -1
- package/dist/core/session-ownership.js +8 -3
- package/dist/core/session-ownership.js.map +1 -1
- package/dist/core/session-retention.d.ts.map +1 -1
- package/dist/core/session-retention.js +18 -7
- package/dist/core/session-retention.js.map +1 -1
- package/dist/core/session-startup-settings.d.ts +10 -0
- package/dist/core/session-startup-settings.d.ts.map +1 -0
- package/dist/core/session-startup-settings.js +70 -0
- package/dist/core/session-startup-settings.js.map +1 -0
- package/dist/core/subscriptions.d.ts +16 -7
- package/dist/core/subscriptions.d.ts.map +1 -1
- package/dist/core/subscriptions.js +96 -55
- package/dist/core/subscriptions.js.map +1 -1
- package/dist/core/trust-manager.d.ts +2 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +6 -1
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/core/update-check.d.ts.map +1 -1
- package/dist/core/update-check.js.map +1 -1
- package/dist/core/usage-adapters/kimi-coding.d.ts +2 -2
- package/dist/core/usage-adapters/kimi-coding.d.ts.map +1 -1
- package/dist/core/usage-adapters/kimi-coding.js +2 -2
- package/dist/core/usage-adapters/kimi-coding.js.map +1 -1
- package/dist/core/usage-adapters/openai-codex.d.ts +3 -2
- package/dist/core/usage-adapters/openai-codex.d.ts.map +1 -1
- package/dist/core/usage-adapters/openai-codex.js +3 -3
- package/dist/core/usage-adapters/openai-codex.js.map +1 -1
- package/dist/core/usage-adapters/xai.d.ts +2 -2
- package/dist/core/usage-adapters/xai.d.ts.map +1 -1
- package/dist/core/usage-adapters/xai.js +3 -3
- package/dist/core/usage-adapters/xai.js.map +1 -1
- package/dist/core/usage-adapters/zai.d.ts +2 -2
- package/dist/core/usage-adapters/zai.d.ts.map +1 -1
- package/dist/core/usage-adapters/zai.js +2 -2
- package/dist/core/usage-adapters/zai.js.map +1 -1
- package/dist/core/usage-service.d.ts +9 -2
- package/dist/core/usage-service.d.ts.map +1 -1
- package/dist/core/usage-service.js +95 -50
- package/dist/core/usage-service.js.map +1 -1
- package/dist/gateway/agent-bridge.d.ts +9 -1
- package/dist/gateway/agent-bridge.d.ts.map +1 -1
- package/dist/gateway/agent-bridge.js +91 -37
- package/dist/gateway/agent-bridge.js.map +1 -1
- package/dist/gateway/buttons.d.ts +8 -1
- package/dist/gateway/buttons.d.ts.map +1 -1
- package/dist/gateway/buttons.js +76 -18
- package/dist/gateway/buttons.js.map +1 -1
- package/dist/gateway/commands.d.ts +1 -0
- package/dist/gateway/commands.d.ts.map +1 -1
- package/dist/gateway/commands.js +10 -4
- package/dist/gateway/commands.js.map +1 -1
- package/dist/gateway/cron.d.ts +12 -11
- package/dist/gateway/cron.d.ts.map +1 -1
- package/dist/gateway/cron.js +65 -56
- package/dist/gateway/cron.js.map +1 -1
- package/dist/gateway/index.d.ts.map +1 -1
- package/dist/gateway/index.js +2 -1
- package/dist/gateway/index.js.map +1 -1
- package/dist/gateway/mobile-commands.d.ts +1 -0
- package/dist/gateway/mobile-commands.d.ts.map +1 -1
- package/dist/gateway/mobile-commands.js +56 -14
- package/dist/gateway/mobile-commands.js.map +1 -1
- package/dist/gateway/presenter.d.ts +12 -2
- package/dist/gateway/presenter.d.ts.map +1 -1
- package/dist/gateway/presenter.js +73 -38
- package/dist/gateway/presenter.js.map +1 -1
- package/dist/gateway/router.d.ts +2 -2
- package/dist/gateway/router.d.ts.map +1 -1
- package/dist/gateway/router.js +17 -2
- package/dist/gateway/router.js.map +1 -1
- package/dist/gateway/service.d.ts +2 -0
- package/dist/gateway/service.d.ts.map +1 -1
- package/dist/gateway/service.js +153 -0
- package/dist/gateway/service.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +86 -33
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +6 -4
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/copyable-text.d.ts.map +1 -1
- package/dist/modes/interactive/components/copyable-text.js +3 -2
- package/dist/modes/interactive/components/copyable-text.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +1 -1
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +96 -109
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/smooth-streaming.d.ts.map +1 -1
- package/dist/modes/interactive/smooth-streaming.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +2 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/node-runtime/{adapter-VFG7WNPX.js → adapter-247RTYLS.js} +4 -5
- package/dist/node-runtime/agent-session-services-KDMSPQDY.js +53 -0
- package/dist/node-runtime/{brave-UWDA3I22.js → brave-2AFFAXNN.js} +1 -1
- package/dist/node-runtime/{builtin-extensions-I2HIFEMY.js → builtin-extensions-OX6KELNX.js} +8 -7
- package/dist/node-runtime/{chunk-QH6YL7VK.js → chunk-252ZVPPF.js} +3 -3
- package/dist/node-runtime/{chunk-PCEW76PM.js → chunk-2OIPYKLZ.js} +6 -6
- package/dist/node-runtime/{chunk-XBWPBZBN.js → chunk-2SWW7KMW.js} +1 -1
- package/dist/node-runtime/{chunk-UQUCFAJ3.js → chunk-2VIW3IMF.js} +40 -7
- package/dist/node-runtime/{chunk-UOEDI7RP.js → chunk-4KNKQGHM.js} +2 -2
- package/dist/node-runtime/{chunk-FQMM2EZ2.js → chunk-64XTQNLA.js} +29 -7
- package/dist/node-runtime/{chunk-SPVDBUOS.js → chunk-6O3IW3IA.js} +2 -2
- package/dist/node-runtime/{chunk-5ZQXRPMC.js → chunk-6ZZHGUSA.js} +2 -2
- package/dist/node-runtime/chunk-A2WO6WIN.js +1197 -0
- package/dist/node-runtime/{chunk-WIF24I7G.js → chunk-APVM5NEU.js} +149 -144
- package/dist/node-runtime/{chunk-RCR3XAQY.js → chunk-AYHH7YSD.js} +177 -144
- package/dist/node-runtime/{chunk-LWYIVUGV.js → chunk-B2IBAXNX.js} +48 -31
- package/dist/node-runtime/{chunk-M3LZLQW2.js → chunk-BDRGN3L2.js} +1 -0
- package/dist/node-runtime/{chunk-GJ2RDBRL.js → chunk-BYC6RKCN.js} +4 -2
- package/dist/node-runtime/{chunk-UVWCDQYF.js → chunk-C3P6Q3B2.js} +455 -278
- package/dist/node-runtime/{chunk-SN2KSMPQ.js → chunk-DQSCFU7R.js} +13 -7
- package/dist/node-runtime/{chunk-4SBQAI4T.js → chunk-EBLAZVSA.js} +2058 -73
- package/dist/node-runtime/{chunk-2KIPT4HJ.js → chunk-EPR2F3GU.js} +68 -20
- package/dist/node-runtime/{chunk-CSFI6YXL.js → chunk-ES6PBSIE.js} +1 -1
- package/dist/node-runtime/{chunk-IF24A3FH.js → chunk-EVM653DD.js} +4 -4
- package/dist/node-runtime/{chunk-HTFRRDSF.js → chunk-F2SMQ6ES.js} +3 -2
- package/dist/node-runtime/chunk-F2V2F4ZG.js +114 -0
- package/dist/node-runtime/{chunk-IKU6Y7DL.js → chunk-FE3WZI7F.js} +9 -6
- package/dist/node-runtime/{chunk-GYIXXQAO.js → chunk-FIRA54AC.js} +2 -5
- package/dist/node-runtime/{chunk-6VYZ5UFP.js → chunk-FLGEEH27.js} +1 -1
- package/dist/node-runtime/{chunk-5EFIU3OM.js → chunk-FTKEZL27.js} +1 -1
- package/dist/node-runtime/{chunk-RGQAEOM5.js → chunk-FYIFPFXE.js} +23 -6
- package/dist/node-runtime/{chunk-HMBGROQK.js → chunk-GLDXBBL6.js} +3 -3
- package/dist/node-runtime/{chunk-KWA4OC2J.js → chunk-H6YBCWKG.js} +1 -1
- package/dist/node-runtime/{chunk-2MI5OPMN.js → chunk-HNNHHJAB.js} +68 -50
- package/dist/node-runtime/{chunk-I74LN5JG.js → chunk-HUD2RFJW.js} +2 -2
- package/dist/node-runtime/{chunk-I54LGHWM.js → chunk-I2H5QMWW.js} +3 -3
- package/dist/node-runtime/{chunk-XHIRAZ26.js → chunk-IAZSK7KK.js} +1 -1
- package/dist/node-runtime/{chunk-X3PGBLQ7.js → chunk-IHHTWSXN.js} +9 -9
- package/dist/node-runtime/{chunk-DAPBPCBP.js → chunk-IPP5BIV5.js} +25 -3
- package/dist/node-runtime/{chunk-QFWG2RVL.js → chunk-IXG6F4NT.js} +11 -0
- package/dist/node-runtime/{chunk-RDDAZOMU.js → chunk-JL4HYQXK.js} +1 -1
- package/dist/node-runtime/{chunk-CDVHZOOK.js → chunk-JQYNHAKX.js} +1 -1
- package/dist/node-runtime/{chunk-L24TPBS4.js → chunk-JWEVT363.js} +37 -29
- package/dist/node-runtime/{chunk-2HMIRK7W.js → chunk-LHV3V67B.js} +5 -5
- package/dist/node-runtime/{chunk-UAEOTO52.js → chunk-MNQXDFPV.js} +6 -2
- package/dist/node-runtime/{chunk-T4DA4XE7.js → chunk-MQPKUHRN.js} +162 -82
- package/dist/node-runtime/{chunk-MPKSOJBT.js → chunk-NHATCSOI.js} +4 -7
- package/dist/node-runtime/{chunk-RMQZU2YU.js → chunk-NNNR3QIY.js} +1 -1
- package/dist/node-runtime/{chunk-RWTKOC3B.js → chunk-QBTJG3UM.js} +1 -1
- package/dist/node-runtime/{chunk-P7XBVXGT.js → chunk-QNVMKNNN.js} +18 -14
- package/dist/node-runtime/{chunk-GS42T6MX.js → chunk-QW3AAHWN.js} +1 -1
- package/dist/node-runtime/{chunk-DVQSHCVP.js → chunk-R4WSB2MQ.js} +5 -5
- package/dist/node-runtime/{chunk-B4HP6ZWM.js → chunk-RHCGYWO7.js} +1 -1
- package/dist/node-runtime/{chunk-2CFDTH5B.js → chunk-RLGY2QIL.js} +45 -59
- package/dist/node-runtime/{chunk-KKUTQQV7.js → chunk-RYRGL7P4.js} +1 -1
- package/dist/node-runtime/{chunk-5Q4A37RB.js → chunk-TCT6PCUR.js} +32 -11
- package/dist/node-runtime/{chunk-D5UCKPBQ.js → chunk-UBWW2PID.js} +1 -1
- package/dist/node-runtime/{chunk-E75WFZ33.js → chunk-UNUZICC4.js} +3 -3
- package/dist/node-runtime/{chunk-RAK2QA2B.js → chunk-UYRKUKFE.js} +4 -4
- package/dist/node-runtime/{chunk-LWJXTA6Z.js → chunk-VSUEAI7O.js} +1377 -45
- package/dist/node-runtime/{chunk-NAY6UUQZ.js → chunk-WDIVLMOH.js} +1 -1
- package/dist/node-runtime/{chunk-E24EO34J.js → chunk-WPXUR3HE.js} +1 -1
- package/dist/node-runtime/{chunk-SLVOAQOY.js → chunk-WXYNALHD.js} +113 -1
- package/dist/node-runtime/{chunk-KJ6DWS3K.js → chunk-XEOCUEUJ.js} +121 -60
- package/dist/node-runtime/chunk-YD3IZAZ7.js +47 -0
- package/dist/node-runtime/chunk-YSB6URMT.js +41 -0
- package/dist/node-runtime/{chunk-LJTIVM7I.js → chunk-ZDJUR45D.js} +427 -126
- package/dist/node-runtime/{chunk-YWOJIGFY.js → chunk-ZEVFBFNF.js} +95 -142
- package/dist/node-runtime/{chunk-5B6VKFEV.js → chunk-ZIQUS5QO.js} +1 -1
- package/dist/node-runtime/cli-runtime.js +4 -4
- package/dist/node-runtime/{command-FSBU2EVZ.js → command-3HMSY6W2.js} +5 -5
- package/dist/node-runtime/{commands-EMBQQVVT.js → commands-D6A6H4TS.js} +11 -18
- package/dist/node-runtime/{commands-NAAL7KNT.js → commands-OCSSEEWJ.js} +16 -16
- package/dist/node-runtime/{config-QDD5PUE2.js → config-CU7M7BTK.js} +1 -1
- package/dist/node-runtime/{config-D4QUPAHX.js → config-DS7XLMEM.js} +2 -2
- package/dist/node-runtime/{direct-tool-executor-4D7UXYU4.js → direct-tool-executor-2QJXVQD2.js} +6 -11
- package/dist/node-runtime/{exa-LL64QZR2.js → exa-6VBZNPGE.js} +1 -1
- package/dist/node-runtime/{export-html-VM4J2MNR.js → export-html-BRWF5AHI.js} +4 -4
- package/dist/node-runtime/{extension-input-E7BJZ35H.js → extension-input-VBBMX7YV.js} +5 -5
- package/dist/node-runtime/{extension-selector-WU42XDTU.js → extension-selector-T5AOG5XB.js} +5 -5
- package/dist/node-runtime/{extract-EQJE7FZZ.js → extract-BFX2N35A.js} +3 -3
- package/dist/node-runtime/{gateway-DQM333YV.js → gateway-6623C2U3.js} +51 -42
- package/dist/node-runtime/{gemini-search-35OCRFLN.js → gemini-search-C66QHDT6.js} +2 -2
- package/dist/node-runtime/{gemini-url-context-UQY3PHHW.js → gemini-url-context-T7DEK73R.js} +3 -3
- package/dist/node-runtime/{github-extract-F64RZOEA.js → github-extract-HOGE3D6F.js} +107 -38
- package/dist/node-runtime/{goal-NJEE5CTU.js → goal-AIHEDUYA.js} +5 -5
- package/dist/node-runtime/index.js +50 -48
- package/dist/node-runtime/{init-P5AUV77I.js → init-JBQJIPYI.js} +3 -6
- package/dist/node-runtime/{install-cli-NN4YAU44.js → install-cli-INGHIVBY.js} +30 -25
- package/dist/node-runtime/interactive-mode-FM5DNUSW.js +74 -0
- package/dist/node-runtime/{interactive-view-NGFAMHPW.js → interactive-view-K33PM4OS.js} +8 -8
- package/dist/node-runtime/{lsp-manager-3ASUSO4T.js → lsp-manager-S554V5HR.js} +240 -155
- package/dist/node-runtime/{lunr-browser-IR7TL3J7.js → lunr-browser-H4FDOR3C.js} +7 -7
- package/dist/node-runtime/{lunr-computer-use-Y23CCDIJ.js → lunr-computer-use-VDP2QNRQ.js} +9 -9
- package/dist/node-runtime/{lunr-cron-USHC4LXH.js → lunr-cron-LKVA5CZZ.js} +93 -80
- package/dist/node-runtime/main.js +42 -41
- package/dist/node-runtime/{mobile-commands-O5LCHL32.js → mobile-commands-XT3NQXLD.js} +12 -12
- package/dist/node-runtime/{model-runtime-OO5HFLWE.js → model-runtime-MZ2JMDV4.js} +4 -4
- package/dist/node-runtime/{openai-search-B3MSNCQA.js → openai-search-K72LJDYN.js} +1 -1
- package/dist/node-runtime/{package-manager-cli-Q7BL6KZO.js → package-manager-cli-CYM262SI.js} +20 -20
- package/dist/node-runtime/{parallel-AI2MNSCU.js → parallel-X724NCNU.js} +1 -1
- package/dist/node-runtime/{perplexity-QVJW3I35.js → perplexity-RDHQHVMK.js} +2 -2
- package/dist/node-runtime/{pi-intercom-QM53RLTS.js → pi-intercom-NHHEPBMI.js} +2 -2
- package/dist/node-runtime/{pi-mcp-adapter-3PHF4KZ4.js → pi-mcp-adapter-PP3GQJQ2.js} +98 -94
- package/dist/node-runtime/{pi-ollama-cloud-2F3Y2QNM.js → pi-ollama-cloud-4MNWIMFN.js} +11 -24
- package/dist/node-runtime/{pi-prompt-template-model-QWTCGLJU.js → pi-prompt-template-model-FTGELLS5.js} +32 -36
- package/dist/node-runtime/{pi-subagents-7IBSSGEW.js → pi-subagents-LT3CTO4E.js} +98 -106
- package/dist/node-runtime/{pi-web-access-WTGMNZ32.js → pi-web-access-Z3LP246C.js} +144 -108
- package/dist/node-runtime/{print-mode-XQ76CYMT.js → print-mode-2XHN5SUA.js} +3 -3
- package/dist/node-runtime/{process-registry-4FAKZQOL.js → process-registry-Q4QWIU33.js} +3 -3
- package/dist/node-runtime/{proxy-modes-5FAPSZEZ.js → proxy-modes-VEGC6QG5.js} +8 -15
- package/dist/node-runtime/rpc-entry.js +42 -41
- package/dist/node-runtime/{rpc-mode-O3XV4SID.js → rpc-mode-32DHJPEJ.js} +4 -4
- package/dist/node-runtime/{runtime-4VA6JKNF.js → runtime-EDUUGAQD.js} +56 -46
- package/dist/node-runtime/{runtime-EFPPD2UW.js → runtime-UGXM4NPQ.js} +2 -2
- package/dist/node-runtime/{runtime-bridges-7WVCLI76.js → runtime-bridges-DNKMNJCF.js} +7 -7
- package/dist/node-runtime/{service-MDQIPQ26.js → service-IHLGFLBT.js} +6 -4
- package/dist/node-runtime/{session-handoff-GWARVEWT.js → session-handoff-LNSPDTKY.js} +4 -4
- package/dist/node-runtime/{session-manager-JB5J6XBN.js → session-manager-YIFIAVGC.js} +3 -3
- package/dist/node-runtime/{session-selector-GIM4DHQ2.js → session-selector-I73U3EIO.js} +7 -7
- package/dist/node-runtime/{settings-manager-DJDM5AHM.js → settings-manager-P2TKGYTR.js} +5 -5
- package/dist/node-runtime/{setup-JBKOLJ6F.js → setup-H7CCELIL.js} +15 -1
- package/dist/node-runtime/{setup-PFBWRNUI.js → setup-OLQ4GXWS.js} +17 -17
- package/dist/node-runtime/{src-IVPNZ2BX.js → src-6RV4PXKJ.js} +64 -36
- package/dist/node-runtime/{subagent-executor-LPZ4BHWE.js → subagent-executor-Q5F7DBVM.js} +119 -58
- package/dist/node-runtime/{tavily-WEZFVFP7.js → tavily-KZBFYQB6.js} +1 -1
- package/dist/node-runtime/{theme-UOO5RVFN.js → theme-YLVZKKZD.js} +2 -2
- package/dist/node-runtime/{trust-manager-MMISNCYO.js → trust-manager-ZCU76D23.js} +2 -2
- package/dist/node-runtime/{update-cli-HNMOTNGX.js → update-cli-F3XXJANQ.js} +6 -6
- package/dist/node-runtime/{usage-service-LFB2SWYV.js → usage-service-CPAGBED5.js} +1 -1
- package/dist/node-runtime/{video-extract-OOZHR7SU.js → video-extract-UPKYIBW3.js} +3 -3
- package/dist/node-runtime/{workflow-OHPBEFO4.js → workflow-ICDI4N3J.js} +208 -78
- package/dist/node-runtime/{youtube-extract-FNPAUNHU.js → youtube-extract-77NT7FWH.js} +4 -4
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js +25 -10
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts.map +1 -1
- package/dist/utils/image-resize-core.js +2 -0
- package/dist/utils/image-resize-core.js.map +1 -1
- package/dist/utils/paths.d.ts +4 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +33 -2
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/sanitize-terminal-text.d.ts +7 -0
- package/dist/utils/sanitize-terminal-text.d.ts.map +1 -0
- package/dist/utils/sanitize-terminal-text.js +67 -0
- package/dist/utils/sanitize-terminal-text.js.map +1 -0
- package/docs/browser.md +1 -1
- package/docs/custom-provider.md +3 -3
- package/docs/extensions.md +8 -4
- package/docs/features.md +15 -7
- package/docs/keybindings.md +1 -1
- package/docs/models.md +5 -5
- package/docs/packages.md +1 -1
- package/docs/providers.md +2 -2
- package/docs/rpc.md +7 -7
- package/docs/security.md +10 -5
- package/docs/sessions.md +2 -2
- package/docs/skills.md +1 -1
- package/docs/terminal-setup.md +7 -7
- package/docs/themes.md +1 -1
- package/docs/usage.md +1 -1
- package/examples/extensions/auto-commit-on-exit.ts +1 -1
- package/examples/extensions/bash-spawn-hook.ts +1 -1
- package/examples/extensions/built-in-tool-renderer.ts +1 -1
- package/examples/extensions/claude-rules.ts +1 -1
- package/examples/extensions/commands.ts +1 -1
- package/examples/extensions/custom-compaction.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/index.ts +3 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/doom-overlay/index.ts +1 -1
- package/examples/extensions/git-merge-and-resolve.ts +2 -2
- package/examples/extensions/gondolin/index.ts +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/hidden-thinking-label.ts +1 -1
- package/examples/extensions/inline-bash.ts +2 -2
- package/examples/extensions/input-transform-streaming.ts +2 -2
- package/examples/extensions/input-transform.ts +2 -2
- package/examples/extensions/interactive-shell.ts +1 -1
- package/examples/extensions/kimi-deferred-tools.ts +1 -1
- package/examples/extensions/mac-system-theme.ts +1 -1
- package/examples/extensions/minimal-mode.ts +1 -1
- package/examples/extensions/modal-editor.ts +1 -1
- package/examples/extensions/model-status.ts +1 -1
- package/examples/extensions/notify.ts +3 -3
- package/examples/extensions/overlay-qa-tests.ts +1 -1
- package/examples/extensions/overlay-test.ts +1 -1
- package/examples/extensions/pirate.ts +1 -1
- package/examples/extensions/preset.ts +3 -3
- package/examples/extensions/project-trust.ts +4 -4
- package/examples/extensions/prompt-customizer.ts +1 -1
- package/examples/extensions/rainbow-editor.ts +1 -1
- package/examples/extensions/rpc-demo.ts +1 -1
- package/examples/extensions/sandbox/index.ts +7 -7
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/shutdown-command.ts +5 -5
- package/examples/extensions/ssh.ts +2 -2
- package/examples/extensions/subagent/README.md +3 -3
- package/examples/extensions/subagent/index.ts +2 -2
- package/examples/extensions/titlebar-spinner.ts +1 -1
- package/examples/extensions/tool-override.ts +1 -1
- package/examples/extensions/tools.ts +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/extensions/working-indicator.ts +1 -1
- package/examples/extensions/working-message-test.ts +1 -1
- package/examples/sdk/01-minimal.ts +1 -1
- package/examples/sdk/03-custom-prompt.ts +1 -1
- package/examples/sdk/04-skills.ts +1 -1
- package/examples/sdk/06-extensions.ts +2 -2
- package/examples/sdk/08-prompt-templates.ts +1 -1
- package/install-lock/package-lock.json +24 -24
- package/install-lock/package.json +2 -2
- package/npm-shrinkwrap.json +60 -24
- package/package.json +9 -9
- package/dist/modes/interactive/components/exit-card.d.ts +0 -22
- package/dist/modes/interactive/components/exit-card.d.ts.map +0 -1
- package/dist/modes/interactive/components/exit-card.js +0 -69
- package/dist/modes/interactive/components/exit-card.js.map +0 -1
- package/dist/node-runtime/agent-session-services-5YXS2PLF.js +0 -51
- package/dist/node-runtime/chunk-2IDTZAG5.js +0 -1415
- package/dist/node-runtime/chunk-3MISGG4S.js +0 -769
- package/dist/node-runtime/chunk-4HXHDDCF.js +0 -16
- package/dist/node-runtime/chunk-5B5QN3ZQ.js +0 -356
- package/dist/node-runtime/chunk-7IQGBKBJ.js +0 -2033
- package/dist/node-runtime/chunk-AUXVGBO4.js +0 -19
- package/dist/node-runtime/chunk-PTFBPO3C.js +0 -50
- package/dist/node-runtime/interactive-mode-YOHZVMKX.js +0 -74
- package/dist/node-runtime/mcp-auth-flow-QVLFVLEO.js +0 -33
|
@@ -3,6 +3,8 @@ import type { BrowserInput } from "./schema.ts";
|
|
|
3
3
|
export declare function boundedBrowserText(text: string): string;
|
|
4
4
|
export declare class BrowserSession {
|
|
5
5
|
private resources?;
|
|
6
|
+
private owner?;
|
|
7
|
+
private activeCancellation?;
|
|
6
8
|
private queue;
|
|
7
9
|
private closing;
|
|
8
10
|
private generation;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/core/browser/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAI9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAWhD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMvD;AAoBD,qBAAa,cAAc;IAC1B,OAAO,CAAC,SAAS,CAAC,CAAqB;IACvC,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,IAAI,CAAC,CAAgC;IAE7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,YAAY,YAAY,UAAQ,EAAE,MAAM,SAAS,EAGhD;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAkB3B;IAEK,GAAG,CACR,KAAK,EAAE,YAAY,EACnB,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,CAAC;QAAC,OAAO,EAAE;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAkFnF;YAEa,IAAI;YAwDJ,OAAO;CAkGrB","sourcesContent":["import type { ImageContent, TextContent } from \"@ashx-j/lunr-ai/compat\";\nimport type { Browser, BrowserContext, Locator, Page } from \"playwright-core\";\nimport { truncateHead } from \"../tools/truncate.ts\";\nimport { browserUrl, createBrowserProxy, resolveBrowserHost } from \"./network.ts\";\nimport type { BrowserInput } from \"./schema.ts\";\n\ntype Resources = {\n\tbrowser: Browser;\n\tcontext: BrowserContext;\n\tproxy: Awaited<ReturnType<typeof createBrowserProxy>>;\n\tpages: Map<number, Page>;\n\tselected?: number;\n\tnextId: number;\n};\n\nexport function boundedBrowserText(text: string): string {\n\tconst result = truncateHead(text.replace(/[\\x00-\\x08\\x0b-\\x1f\\x7f-\\x9f]/g, \"\"), { maxBytes: 16384, maxLines: 300 });\n\treturn (\n\t\tresult.content +\n\t\t(result.truncated ? \"\\n[Snapshot truncated. Inspect a specific role/name or label to narrow it.]\" : \"\")\n\t);\n}\n\nfunction target(page: Page, input: BrowserInput): Locator {\n\tif (input.label !== undefined && input.role === undefined && input.name === undefined) {\n\t\treturn page.getByLabel(input.label, { exact: true });\n\t}\n\tif (input.role && input.label === undefined) return page.getByRole(input.role, { name: input.name, exact: true });\n\tthrow new Error(\"Specify role with optional exact name, or label alone. Inspect the page to find a target.\");\n}\n\nasync function uniqueTarget(page: Page, input: BrowserInput): Promise<Locator> {\n\tconst locator = target(page, input);\n\tconst count = await locator.count();\n\tif (count !== 1)\n\t\tthrow new Error(\n\t\t\t`Target matched ${count} elements. Inspect and choose a unique exact role/name or label; no action was taken.`,\n\t\t);\n\treturn locator;\n}\n\nexport class BrowserSession {\n\tprivate resources?: Promise<Resources>;\n\tprivate queue: Promise<unknown> = Promise.resolve();\n\tprivate closing: Promise<void> = Promise.resolve();\n\tprivate generation = 0;\n\tprivate queued = 0;\n\tprivate idle?: ReturnType<typeof setTimeout>;\n\n\tprivate readonly allowPrivate: boolean;\n\tprivate readonly idleMs: number;\n\n\tconstructor(allowPrivate = false, idleMs = 300000) {\n\t\tthis.allowPrivate = allowPrivate;\n\t\tthis.idleMs = idleMs;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.generation++;\n\t\tclearTimeout(this.idle);\n\t\tconst pending = this.resources;\n\t\tthis.resources = undefined;\n\t\tconst previous = this.closing;\n\t\tconst closing = (async () => {\n\t\t\tawait previous;\n\t\t\tconst resources = await pending?.catch(() => undefined);\n\t\t\tif (!resources) return;\n\t\t\ttry {\n\t\t\t\tawait resources.browser.close();\n\t\t\t} finally {\n\t\t\t\tawait resources.proxy.close();\n\t\t\t}\n\t\t})();\n\t\tthis.closing = closing.catch(() => undefined);\n\t\treturn closing;\n\t}\n\n\tasync run(\n\t\tinput: BrowserInput,\n\t\tsignal?: AbortSignal,\n\t): Promise<{ content: (TextContent | ImageContent)[]; details: { action: string } }> {\n\t\tif (this.queued >= 16) throw new Error(\"Browser queue is full. Wait for the current operation.\");\n\t\tconst generation = this.generation;\n\t\tthis.queued++;\n\t\tconst operation = this.queue.then(async () => {\n\t\t\tif (signal?.aborted || generation !== this.generation)\n\t\t\t\tthrow new Error(\"Browser operation cancelled; navigate again in a new call.\");\n\t\t\tclearTimeout(this.idle);\n\t\t\tconst cancellation = new AbortController();\n\t\t\tconst abort = () => {\n\t\t\t\tcancellation.abort();\n\t\t\t\tvoid this.close().catch(() => undefined);\n\t\t\t};\n\t\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t\t\tconst deadline = setTimeout(abort, 30000);\n\t\t\ttry {\n\t\t\t\tif (input.action === \"close\") {\n\t\t\t\t\tawait this.close();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: \"Browser closed; ephemeral cookies and tabs discarded.\" }],\n\t\t\t\t\t\tdetails: { action: input.action },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tawait this.closing;\n\t\t\t\tif (signal?.aborted || generation !== this.generation) throw new Error(\"Browser operation cancelled.\");\n\t\t\t\tif (\n\t\t\t\t\t!this.resources &&\n\t\t\t\t\tinput.action !== \"navigate\" &&\n\t\t\t\t\t!(input.action === \"tabs\" && input.operation === \"create\")\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"No browser is open. Use navigate or tabs/create first. Idle cleanup discards tabs after 5 minutes.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis.resources ??= this.open().catch((error) => {\n\t\t\t\t\tif (generation === this.generation) this.resources = undefined;\n\t\t\t\t\tthrow error;\n\t\t\t\t});\n\t\t\t\tconst resources = await this.resources;\n\t\t\t\tif (generation !== this.generation) throw new Error(\"Browser operation cancelled.\");\n\t\t\t\tconst content = await Promise.race([\n\t\t\t\t\tthis.perform(resources, input),\n\t\t\t\t\tnew Promise<never>((_resolve, reject) => {\n\t\t\t\t\t\tconst cancelled = () =>\n\t\t\t\t\t\t\treject(\n\t\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t\t\"Browser cancelled or exceeded 30s; browser closed. External effects may already have occurred.\",\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\tif (cancellation.signal.aborted) cancelled();\n\t\t\t\t\t\telse cancellation.signal.addEventListener(\"abort\", cancelled, { once: true });\n\t\t\t\t\t}),\n\t\t\t\t]);\n\t\t\t\tif (signal?.aborted || generation !== this.generation)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Browser operation cancelled; external effects may already have occurred. Inspect before retrying.\",\n\t\t\t\t\t);\n\t\t\t\tthis.idle = setTimeout(() => {\n\t\t\t\t\tvoid this.close().catch(() => undefined);\n\t\t\t\t}, this.idleMs);\n\t\t\t\tthis.idle.unref();\n\t\t\t\treturn { content, details: { action: input.action } };\n\t\t\t} catch (error) {\n\t\t\t\tif (generation === this.generation) {\n\t\t\t\t\tthis.idle = setTimeout(() => {\n\t\t\t\t\t\tvoid this.close().catch(() => undefined);\n\t\t\t\t\t}, this.idleMs);\n\t\t\t\t\tthis.idle.unref();\n\t\t\t\t}\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tthrow new Error(boundedBrowserText(message));\n\t\t\t} finally {\n\t\t\t\tclearTimeout(deadline);\n\t\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t\t}\n\t\t});\n\t\tthis.queue = operation.catch(() => undefined);\n\t\ttry {\n\t\t\treturn await operation;\n\t\t} finally {\n\t\t\tthis.queued--;\n\t\t}\n\t}\n\n\tprivate async open(): Promise<Resources> {\n\t\tconst proxy = await createBrowserProxy(this.allowPrivate);\n\t\tlet browser: Browser | undefined;\n\t\ttry {\n\t\t\tconst { chromium } = await import(\"playwright-core\");\n\t\t\tbrowser = await chromium.launch({\n\t\t\t\theadless: true,\n\t\t\t\ttimeout: 15000,\n\t\t\t\tchromiumSandbox: true,\n\t\t\t\tproxy: { server: proxy.url, bypass: \"<-loopback>\" },\n\t\t\t\targs: [\"--disable-quic\", \"--force-webrtc-ip-handling-policy=disable_non_proxied_udp\"],\n\t\t\t});\n\t\t\tconst context = await browser.newContext({\n\t\t\t\tacceptDownloads: false,\n\t\t\t\tserviceWorkers: \"block\",\n\t\t\t\tpermissions: [],\n\t\t\t\tviewport: { width: 1280, height: 800 },\n\t\t\t});\n\t\t\tcontext.setDefaultTimeout(10000);\n\t\t\tcontext.setDefaultNavigationTimeout(15000);\n\t\t\tawait context.route(\"**/*\", async (route) => {\n\t\t\t\ttry {\n\t\t\t\t\tbrowserUrl(route.request().url());\n\t\t\t\t\tawait route.continue();\n\t\t\t\t} catch {\n\t\t\t\t\tawait route.abort().catch(() => undefined);\n\t\t\t\t}\n\t\t\t});\n\t\t\tawait context.routeWebSocket(\"**/*\", (socket) => socket.close());\n\t\t\tconst resources: Resources = { browser, context, proxy, pages: new Map(), nextId: 1 };\n\t\t\tcontext.on(\"page\", (page) => {\n\t\t\t\tif (resources.pages.size >= 4) {\n\t\t\t\t\tvoid page.close().catch(() => undefined);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst id = resources.nextId++;\n\t\t\t\tresources.pages.set(id, page);\n\t\t\t\tpage.on(\"close\", () => resources.pages.delete(id));\n\t\t\t\tpage.on(\"dialog\", (dialog) => {\n\t\t\t\t\tvoid dialog.dismiss().catch(() => undefined);\n\t\t\t\t});\n\t\t\t\tpage.on(\"download\", (download) => {\n\t\t\t\t\tvoid download.cancel().catch(() => undefined);\n\t\t\t\t});\n\t\t\t});\n\t\t\treturn resources;\n\t\t} catch (error) {\n\t\t\tawait browser?.close().catch(() => undefined);\n\t\t\tawait proxy.close();\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(\n\t\t\t\t`Browser launch failed. Matching Chromium may be missing after --ignore-scripts or offline installation. Ask the user to run lunr browser install when online. Nothing was installed by this call. ${message}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async perform(resources: Resources, input: BrowserInput): Promise<(TextContent | ImageContent)[]> {\n\t\tconst text = (value: string): TextContent[] => [{ type: \"text\", text: boundedBrowserText(value) }];\n\t\tlet page = resources.pages.get(input.tab ?? resources.selected ?? -1);\n\t\tif (input.action === \"tabs\") {\n\t\t\tif (!input.operation) throw new Error(\"tabs requires operation list/create/select/close.\");\n\t\t\tif (input.operation === \"list\")\n\t\t\t\treturn text(\n\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t[...resources.pages].map(([id, tab]) => ({\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\tselected: id === resources.selected,\n\t\t\t\t\t\t\turl: tab.url(),\n\t\t\t\t\t\t})),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\tif (input.operation === \"select\") {\n\t\t\t\tif (!page || input.tab === undefined) throw new Error(\"Select requires an existing tab id from tabs/list.\");\n\t\t\t\tresources.selected = input.tab;\n\t\t\t\treturn text(`Selected tab ${input.tab}.`);\n\t\t\t}\n\t\t\tif (input.operation === \"close\") {\n\t\t\t\tif (!page) throw new Error(\"No matching tab. Use tabs/list.\");\n\t\t\t\tawait page.close();\n\t\t\t\tif (!resources.pages.has(resources.selected ?? -1))\n\t\t\t\t\tresources.selected = resources.pages.keys().next().value;\n\t\t\t\treturn text(\"Tab closed.\");\n\t\t\t}\n\t\t}\n\t\tif (input.action === \"navigate\" || (input.action === \"tabs\" && input.operation === \"create\")) {\n\t\t\tif (input.action === \"navigate\" && !input.url) throw new Error(\"navigate requires url.\");\n\t\t\tconst url = input.url ? browserUrl(input.url) : undefined;\n\t\t\tif (url) await resolveBrowserHost(url.hostname, this.allowPrivate);\n\t\t\tif (input.tab !== undefined && !page && input.action === \"navigate\")\n\t\t\t\tthrow new Error(\"Unknown tab. Use tabs/list.\");\n\t\t\tif (!page || input.action === \"tabs\") {\n\t\t\t\tif (resources.pages.size >= 4) throw new Error(\"Maximum 4 tabs. Close a tab first.\");\n\t\t\t\tpage = await resources.context.newPage();\n\t\t\t}\n\t\t\tresources.selected = [...resources.pages].find(([, candidate]) => candidate === page)?.[0];\n\t\t\tif (url) await page.goto(url.href, { waitUntil: \"domcontentloaded\" });\n\t\t\treturn text(\n\t\t\t\t`Tab ${resources.selected}: ${page.url()}\\nUse inspect for rendered content.${resources.proxy.blockedReason() ? `\\nNetwork warning: ${resources.proxy.blockedReason()}` : \"\"}`,\n\t\t\t);\n\t\t}\n\t\tif (!page) throw new Error(\"No selected tab. Use tabs/list or navigate.\");\n\t\tif (input.action === \"inspect\") {\n\t\t\tconst locator =\n\t\t\t\tinput.role || input.label !== undefined ? await uniqueTarget(page, input) : page.locator(\"body\");\n\t\t\treturn text(`Untrusted page content at ${page.url()}:\\n${await locator.ariaSnapshot()}`);\n\t\t}\n\t\tif (input.action === \"screenshot\") {\n\t\t\tconst image = await page.screenshot({ type: \"jpeg\", quality: 70, fullPage: false, timeout: 10000 });\n\t\t\tif (image.length > 2 * 1024 * 1024) throw new Error(\"Screenshot exceeds 2MB limit.\");\n\t\t\treturn [\n\t\t\t\t...text(`Untrusted viewport screenshot at ${page.url()}`),\n\t\t\t\t{ type: \"image\", mimeType: \"image/jpeg\", data: image.toString(\"base64\") },\n\t\t\t];\n\t\t}\n\t\tif (input.action === \"act\") {\n\t\t\tconst locator = await uniqueTarget(page, input);\n\t\t\tswitch (input.interaction) {\n\t\t\t\tcase \"click\":\n\t\t\t\t\tawait locator.click();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"fill\":\n\t\t\t\t\tif (input.value === undefined) throw new Error(\"fill requires value.\");\n\t\t\t\t\tawait locator.fill(input.value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"select\":\n\t\t\t\t\tif (input.value === undefined) throw new Error(\"select requires option value.\");\n\t\t\t\t\tawait locator.selectOption(input.value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"check\":\n\t\t\t\t\tif (input.checked === undefined) throw new Error(\"check requires checked.\");\n\t\t\t\t\tawait locator.setChecked(input.checked);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"press\":\n\t\t\t\t\tif (\n\t\t\t\t\t\t!input.value ||\n\t\t\t\t\t\t!/^(Enter|Tab|Escape|Space|Backspace|Delete|ArrowUp|ArrowDown|ArrowLeft|ArrowRight|Home|End|PageUp|PageDown)$/.test(\n\t\t\t\t\t\t\tinput.value,\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"press accepts Enter/Tab/Escape/Space/Backspace/Delete/arrows/Home/End/PageUp/PageDown only. Use fill for text.\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait locator.press(input.value);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(\"act requires interaction click/fill/select/check/press.\");\n\t\t\t}\n\t\t\treturn text(\n\t\t\t\t`Interaction completed at ${page.url()}. Inspect to verify the result. External effects cannot be undone by /undo.`,\n\t\t\t);\n\t\t}\n\t\tthrow new Error(\"Unsupported browser action.\");\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/core/browser/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAI9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA8BhD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMvD;AAoBD,qBAAa,cAAc;IAC1B,OAAO,CAAC,SAAS,CAAC,CAAqB;IACvC,OAAO,CAAC,KAAK,CAAC,CAAgB;IAC9B,OAAO,CAAC,kBAAkB,CAAC,CAAkB;IAC7C,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,IAAI,CAAC,CAAgC;IAE7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,YAAY,YAAY,UAAQ,EAAE,MAAM,SAAS,EAGhD;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAW3B;IAEK,GAAG,CACR,KAAK,EAAE,YAAY,EACnB,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,CAAC;QAAC,OAAO,EAAE;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CA8FnF;YAEa,IAAI;YAqEJ,OAAO;CAkGrB","sourcesContent":["import type { ImageContent, TextContent } from \"@ashx-j/lunr-ai/compat\";\nimport type { Browser, BrowserContext, Locator, Page } from \"playwright-core\";\nimport { truncateHead } from \"../tools/truncate.ts\";\nimport { browserUrl, createBrowserProxy, resolveBrowserHost } from \"./network.ts\";\nimport type { BrowserInput } from \"./schema.ts\";\n\ntype Resources = {\n\tbrowser: Browser;\n\tcontext: BrowserContext;\n\tproxy: Awaited<ReturnType<typeof createBrowserProxy>>;\n\tpages: Map<number, Page>;\n\tselected?: number;\n\tnextId: number;\n};\n\ntype ResourceOwner = {\n\tgeneration: number;\n\tbrowser?: Browser;\n\tproxy?: Resources[\"proxy\"];\n\tbrowserClose?: Promise<void>;\n\tproxyClose?: Promise<void>;\n};\n\n// Resources can arrive after cancellation. Each owner closes only its own handles, once.\nfunction closeOwnedResources(owner?: ResourceOwner): Promise<void> {\n\tif (owner?.browser) owner.browserClose ??= Promise.resolve().then(() => owner.browser!.close());\n\tif (owner?.proxy) owner.proxyClose ??= Promise.resolve().then(() => owner.proxy!.close());\n\treturn Promise.allSettled([owner?.browserClose, owner?.proxyClose]).then((results) => {\n\t\tfor (const result of results) {\n\t\t\tif (result.status === \"rejected\") throw result.reason;\n\t\t}\n\t});\n}\n\nexport function boundedBrowserText(text: string): string {\n\tconst result = truncateHead(text.replace(/[\\x00-\\x08\\x0b-\\x1f\\x7f-\\x9f]/g, \"\"), { maxBytes: 16384, maxLines: 300 });\n\treturn (\n\t\tresult.content +\n\t\t(result.truncated ? \"\\n[Snapshot truncated. Inspect a specific role/name or label to narrow it.]\" : \"\")\n\t);\n}\n\nfunction target(page: Page, input: BrowserInput): Locator {\n\tif (input.label !== undefined && input.role === undefined && input.name === undefined) {\n\t\treturn page.getByLabel(input.label, { exact: true });\n\t}\n\tif (input.role && input.label === undefined) return page.getByRole(input.role, { name: input.name, exact: true });\n\tthrow new Error(\"Specify role with optional exact name, or label alone. Inspect the page to find a target.\");\n}\n\nasync function uniqueTarget(page: Page, input: BrowserInput): Promise<Locator> {\n\tconst locator = target(page, input);\n\tconst count = await locator.count();\n\tif (count !== 1)\n\t\tthrow new Error(\n\t\t\t`Target matched ${count} elements. Inspect and choose a unique exact role/name or label; no action was taken.`,\n\t\t);\n\treturn locator;\n}\n\nexport class BrowserSession {\n\tprivate resources?: Promise<Resources>;\n\tprivate owner?: ResourceOwner;\n\tprivate activeCancellation?: AbortController;\n\tprivate queue: Promise<unknown> = Promise.resolve();\n\tprivate closing: Promise<void> = Promise.resolve();\n\tprivate generation = 0;\n\tprivate queued = 0;\n\tprivate idle?: ReturnType<typeof setTimeout>;\n\n\tprivate readonly allowPrivate: boolean;\n\tprivate readonly idleMs: number;\n\n\tconstructor(allowPrivate = false, idleMs = 300000) {\n\t\tthis.allowPrivate = allowPrivate;\n\t\tthis.idleMs = idleMs;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.generation++;\n\t\tclearTimeout(this.idle);\n\t\tthis.activeCancellation?.abort();\n\t\tconst owner = this.owner;\n\t\tthis.owner = undefined;\n\t\tthis.resources = undefined;\n\t\t// Do not wait for initialization to discover handles. open() cleans late arrivals.\n\t\tconst closing = Promise.all([this.closing, closeOwnedResources(owner)]).then(() => undefined);\n\t\tthis.closing = closing.catch(() => undefined);\n\t\treturn closing;\n\t}\n\n\tasync run(\n\t\tinput: BrowserInput,\n\t\tsignal?: AbortSignal,\n\t): Promise<{ content: (TextContent | ImageContent)[]; details: { action: string } }> {\n\t\tif (this.queued >= 16) throw new Error(\"Browser queue is full. Wait for the current operation.\");\n\t\tconst generation = this.generation;\n\t\tthis.queued++;\n\t\tconst operation = this.queue.then(async () => {\n\t\t\tif (signal?.aborted || generation !== this.generation)\n\t\t\t\tthrow new Error(\"Browser operation cancelled; navigate again in a new call.\");\n\t\t\tclearTimeout(this.idle);\n\t\t\tconst cancellation = new AbortController();\n\t\t\tthis.activeCancellation = cancellation;\n\t\t\tlet ownedGeneration = generation;\n\t\t\tconst abort = () => {\n\t\t\t\tcancellation.abort();\n\t\t\t\tif (ownedGeneration === this.generation) void this.close().catch(() => undefined);\n\t\t\t};\n\t\t\tconst cancellationError = new Error(\n\t\t\t\t\"Browser cancelled or exceeded 30s; browser cleanup requested. External effects may already have occurred.\",\n\t\t\t);\n\t\t\tconst checkCurrent = () => {\n\t\t\t\tif (cancellation.signal.aborted || generation !== this.generation) throw cancellationError;\n\t\t\t};\n\t\t\tlet rejectCancellation!: () => void;\n\t\t\tconst interrupted = new Promise<never>((_resolve, reject) => {\n\t\t\t\trejectCancellation = () => reject(cancellationError);\n\t\t\t\tcancellation.signal.addEventListener(\"abort\", rejectCancellation, { once: true });\n\t\t\t});\n\t\t\tconst wait = <T>(pending: Promise<T>) => Promise.race([pending, interrupted]);\n\t\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t\t\tconst deadline = setTimeout(abort, 30000);\n\t\t\ttry {\n\t\t\t\tif (input.action === \"close\") {\n\t\t\t\t\t// This operation intentionally invalidates its generation, without cancelling itself.\n\t\t\t\t\tthis.activeCancellation = undefined;\n\t\t\t\t\tconst closing = this.close();\n\t\t\t\t\townedGeneration = this.generation;\n\t\t\t\t\tawait wait(closing);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: \"Browser closed; ephemeral cookies and tabs discarded.\" }],\n\t\t\t\t\t\tdetails: { action: input.action },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tawait wait(this.closing);\n\t\t\t\tcheckCurrent();\n\t\t\t\tif (\n\t\t\t\t\t!this.resources &&\n\t\t\t\t\tinput.action !== \"navigate\" &&\n\t\t\t\t\t!(input.action === \"tabs\" && input.operation === \"create\")\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"No browser is open. Use navigate or tabs/create first. Idle cleanup discards tabs after 5 minutes.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (!this.resources) {\n\t\t\t\t\tconst owner: ResourceOwner = { generation };\n\t\t\t\t\tthis.owner = owner;\n\t\t\t\t\tthis.resources = this.open(owner).catch((error) => {\n\t\t\t\t\t\tif (this.owner === owner) {\n\t\t\t\t\t\t\tthis.resources = undefined;\n\t\t\t\t\t\t\tthis.owner = undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst resources = await wait(this.resources);\n\t\t\t\tcheckCurrent();\n\t\t\t\tconst content = await wait(this.perform(resources, input));\n\t\t\t\tcheckCurrent();\n\t\t\t\tthis.idle = setTimeout(() => {\n\t\t\t\t\tvoid this.close().catch(() => undefined);\n\t\t\t\t}, this.idleMs);\n\t\t\t\tthis.idle.unref();\n\t\t\t\treturn { content, details: { action: input.action } };\n\t\t\t} catch (error) {\n\t\t\t\tif (generation === this.generation) {\n\t\t\t\t\tthis.idle = setTimeout(() => {\n\t\t\t\t\t\tvoid this.close().catch(() => undefined);\n\t\t\t\t\t}, this.idleMs);\n\t\t\t\t\tthis.idle.unref();\n\t\t\t\t}\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tthrow new Error(boundedBrowserText(message));\n\t\t\t} finally {\n\t\t\t\tclearTimeout(deadline);\n\t\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t\t\tcancellation.signal.removeEventListener(\"abort\", rejectCancellation);\n\t\t\t\tif (this.activeCancellation === cancellation) this.activeCancellation = undefined;\n\t\t\t}\n\t\t});\n\t\tthis.queue = operation.catch(() => undefined);\n\t\ttry {\n\t\t\treturn await operation;\n\t\t} finally {\n\t\t\tthis.queued--;\n\t\t}\n\t}\n\n\tprivate async open(owner: ResourceOwner): Promise<Resources> {\n\t\tconst checkCurrent = () => {\n\t\t\tif (owner.generation !== this.generation) throw new Error(\"Browser operation cancelled.\");\n\t\t};\n\t\ttry {\n\t\t\tconst proxy = await createBrowserProxy(this.allowPrivate);\n\t\t\towner.proxy = proxy;\n\t\t\tcheckCurrent();\n\t\t\tconst { chromium } = await import(\"playwright-core\");\n\t\t\tcheckCurrent();\n\t\t\tconst browser = await chromium.launch({\n\t\t\t\theadless: true,\n\t\t\t\ttimeout: 15000,\n\t\t\t\tchromiumSandbox: true,\n\t\t\t\tproxy: { server: proxy.url, bypass: \"<-loopback>\" },\n\t\t\t\targs: [\"--disable-quic\", \"--force-webrtc-ip-handling-policy=disable_non_proxied_udp\"],\n\t\t\t});\n\t\t\towner.browser = browser;\n\t\t\tcheckCurrent();\n\t\t\tconst context = await browser.newContext({\n\t\t\t\tacceptDownloads: false,\n\t\t\t\tserviceWorkers: \"block\",\n\t\t\t\tpermissions: [],\n\t\t\t\tviewport: { width: 1280, height: 800 },\n\t\t\t});\n\t\t\tif (owner.generation !== this.generation) {\n\t\t\t\t// newContext may complete after browser.close() was already requested.\n\t\t\t\tvoid context.close().catch(() => undefined);\n\t\t\t\tcheckCurrent();\n\t\t\t}\n\t\t\tcontext.setDefaultTimeout(10000);\n\t\t\tcontext.setDefaultNavigationTimeout(15000);\n\t\t\tawait context.route(\"**/*\", async (route) => {\n\t\t\t\ttry {\n\t\t\t\t\tbrowserUrl(route.request().url());\n\t\t\t\t\tawait route.continue();\n\t\t\t\t} catch {\n\t\t\t\t\tawait route.abort().catch(() => undefined);\n\t\t\t\t}\n\t\t\t});\n\t\t\tcheckCurrent();\n\t\t\tawait context.routeWebSocket(\"**/*\", (socket) => socket.close());\n\t\t\tcheckCurrent();\n\t\t\tconst resources: Resources = { browser, context, proxy, pages: new Map(), nextId: 1 };\n\t\t\tcontext.on(\"page\", (page) => {\n\t\t\t\tif (resources.pages.size >= 4) {\n\t\t\t\t\tvoid page.close().catch(() => undefined);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst id = resources.nextId++;\n\t\t\t\tresources.pages.set(id, page);\n\t\t\t\tpage.on(\"close\", () => resources.pages.delete(id));\n\t\t\t\tpage.on(\"dialog\", (dialog) => {\n\t\t\t\t\tvoid dialog.dismiss().catch(() => undefined);\n\t\t\t\t});\n\t\t\t\tpage.on(\"download\", (download) => {\n\t\t\t\t\tvoid download.cancel().catch(() => undefined);\n\t\t\t\t});\n\t\t\t});\n\t\t\treturn resources;\n\t\t} catch (error) {\n\t\t\tawait closeOwnedResources(owner).catch(() => undefined);\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(\n\t\t\t\t`Browser launch failed. Matching Chromium may be missing after --ignore-scripts or offline installation. Ask the user to run lunr browser install when online. Nothing was installed by this call. ${message}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async perform(resources: Resources, input: BrowserInput): Promise<(TextContent | ImageContent)[]> {\n\t\tconst text = (value: string): TextContent[] => [{ type: \"text\", text: boundedBrowserText(value) }];\n\t\tlet page = resources.pages.get(input.tab ?? resources.selected ?? -1);\n\t\tif (input.action === \"tabs\") {\n\t\t\tif (!input.operation) throw new Error(\"tabs requires operation list/create/select/close.\");\n\t\t\tif (input.operation === \"list\")\n\t\t\t\treturn text(\n\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t[...resources.pages].map(([id, tab]) => ({\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\tselected: id === resources.selected,\n\t\t\t\t\t\t\turl: tab.url(),\n\t\t\t\t\t\t})),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\tif (input.operation === \"select\") {\n\t\t\t\tif (!page || input.tab === undefined) throw new Error(\"Select requires an existing tab id from tabs/list.\");\n\t\t\t\tresources.selected = input.tab;\n\t\t\t\treturn text(`Selected tab ${input.tab}.`);\n\t\t\t}\n\t\t\tif (input.operation === \"close\") {\n\t\t\t\tif (!page) throw new Error(\"No matching tab. Use tabs/list.\");\n\t\t\t\tawait page.close();\n\t\t\t\tif (!resources.pages.has(resources.selected ?? -1))\n\t\t\t\t\tresources.selected = resources.pages.keys().next().value;\n\t\t\t\treturn text(\"Tab closed.\");\n\t\t\t}\n\t\t}\n\t\tif (input.action === \"navigate\" || (input.action === \"tabs\" && input.operation === \"create\")) {\n\t\t\tif (input.action === \"navigate\" && !input.url) throw new Error(\"navigate requires url.\");\n\t\t\tconst url = input.url ? browserUrl(input.url) : undefined;\n\t\t\tif (url) await resolveBrowserHost(url.hostname, this.allowPrivate);\n\t\t\tif (input.tab !== undefined && !page && input.action === \"navigate\")\n\t\t\t\tthrow new Error(\"Unknown tab. Use tabs/list.\");\n\t\t\tif (!page || input.action === \"tabs\") {\n\t\t\t\tif (resources.pages.size >= 4) throw new Error(\"Maximum 4 tabs. Close a tab first.\");\n\t\t\t\tpage = await resources.context.newPage();\n\t\t\t}\n\t\t\tresources.selected = [...resources.pages].find(([, candidate]) => candidate === page)?.[0];\n\t\t\tif (url) await page.goto(url.href, { waitUntil: \"domcontentloaded\" });\n\t\t\treturn text(\n\t\t\t\t`Tab ${resources.selected}: ${page.url()}\\nUse inspect for rendered content.${resources.proxy.blockedReason() ? `\\nNetwork warning: ${resources.proxy.blockedReason()}` : \"\"}`,\n\t\t\t);\n\t\t}\n\t\tif (!page) throw new Error(\"No selected tab. Use tabs/list or navigate.\");\n\t\tif (input.action === \"inspect\") {\n\t\t\tconst locator =\n\t\t\t\tinput.role || input.label !== undefined ? await uniqueTarget(page, input) : page.locator(\"body\");\n\t\t\treturn text(`Untrusted page content at ${page.url()}:\\n${await locator.ariaSnapshot()}`);\n\t\t}\n\t\tif (input.action === \"screenshot\") {\n\t\t\tconst image = await page.screenshot({ type: \"jpeg\", quality: 70, fullPage: false, timeout: 10000 });\n\t\t\tif (image.length > 2 * 1024 * 1024) throw new Error(\"Screenshot exceeds 2MB limit.\");\n\t\t\treturn [\n\t\t\t\t...text(`Untrusted viewport screenshot at ${page.url()}`),\n\t\t\t\t{ type: \"image\", mimeType: \"image/jpeg\", data: image.toString(\"base64\") },\n\t\t\t];\n\t\t}\n\t\tif (input.action === \"act\") {\n\t\t\tconst locator = await uniqueTarget(page, input);\n\t\t\tswitch (input.interaction) {\n\t\t\t\tcase \"click\":\n\t\t\t\t\tawait locator.click();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"fill\":\n\t\t\t\t\tif (input.value === undefined) throw new Error(\"fill requires value.\");\n\t\t\t\t\tawait locator.fill(input.value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"select\":\n\t\t\t\t\tif (input.value === undefined) throw new Error(\"select requires option value.\");\n\t\t\t\t\tawait locator.selectOption(input.value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"check\":\n\t\t\t\t\tif (input.checked === undefined) throw new Error(\"check requires checked.\");\n\t\t\t\t\tawait locator.setChecked(input.checked);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"press\":\n\t\t\t\t\tif (\n\t\t\t\t\t\t!input.value ||\n\t\t\t\t\t\t!/^(Enter|Tab|Escape|Space|Backspace|Delete|ArrowUp|ArrowDown|ArrowLeft|ArrowRight|Home|End|PageUp|PageDown)$/.test(\n\t\t\t\t\t\t\tinput.value,\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"press accepts Enter/Tab/Escape/Space/Backspace/Delete/arrows/Home/End/PageUp/PageDown only. Use fill for text.\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait locator.press(input.value);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(\"act requires interaction click/fill/select/check/press.\");\n\t\t\t}\n\t\t\treturn text(\n\t\t\t\t`Interaction completed at ${page.url()}. Inspect to verify the result. External effects cannot be undone by /undo.`,\n\t\t\t);\n\t\t}\n\t\tthrow new Error(\"Unsupported browser action.\");\n\t}\n}\n"]}
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { truncateHead } from "../tools/truncate.js";
|
|
2
2
|
import { browserUrl, createBrowserProxy, resolveBrowserHost } from "./network.js";
|
|
3
|
+
// Resources can arrive after cancellation. Each owner closes only its own handles, once.
|
|
4
|
+
function closeOwnedResources(owner) {
|
|
5
|
+
if (owner?.browser)
|
|
6
|
+
owner.browserClose ??= Promise.resolve().then(() => owner.browser.close());
|
|
7
|
+
if (owner?.proxy)
|
|
8
|
+
owner.proxyClose ??= Promise.resolve().then(() => owner.proxy.close());
|
|
9
|
+
return Promise.allSettled([owner?.browserClose, owner?.proxyClose]).then((results) => {
|
|
10
|
+
for (const result of results) {
|
|
11
|
+
if (result.status === "rejected")
|
|
12
|
+
throw result.reason;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
3
16
|
export function boundedBrowserText(text) {
|
|
4
17
|
const result = truncateHead(text.replace(/[\x00-\x08\x0b-\x1f\x7f-\x9f]/g, ""), { maxBytes: 16384, maxLines: 300 });
|
|
5
18
|
return (result.content +
|
|
@@ -22,6 +35,8 @@ async function uniqueTarget(page, input) {
|
|
|
22
35
|
}
|
|
23
36
|
export class BrowserSession {
|
|
24
37
|
resources;
|
|
38
|
+
owner;
|
|
39
|
+
activeCancellation;
|
|
25
40
|
queue = Promise.resolve();
|
|
26
41
|
closing = Promise.resolve();
|
|
27
42
|
generation = 0;
|
|
@@ -36,21 +51,12 @@ export class BrowserSession {
|
|
|
36
51
|
async close() {
|
|
37
52
|
this.generation++;
|
|
38
53
|
clearTimeout(this.idle);
|
|
39
|
-
|
|
54
|
+
this.activeCancellation?.abort();
|
|
55
|
+
const owner = this.owner;
|
|
56
|
+
this.owner = undefined;
|
|
40
57
|
this.resources = undefined;
|
|
41
|
-
|
|
42
|
-
const closing = (
|
|
43
|
-
await previous;
|
|
44
|
-
const resources = await pending?.catch(() => undefined);
|
|
45
|
-
if (!resources)
|
|
46
|
-
return;
|
|
47
|
-
try {
|
|
48
|
-
await resources.browser.close();
|
|
49
|
-
}
|
|
50
|
-
finally {
|
|
51
|
-
await resources.proxy.close();
|
|
52
|
-
}
|
|
53
|
-
})();
|
|
58
|
+
// Do not wait for initialization to discover handles. open() cleans late arrivals.
|
|
59
|
+
const closing = Promise.all([this.closing, closeOwnedResources(owner)]).then(() => undefined);
|
|
54
60
|
this.closing = closing.catch(() => undefined);
|
|
55
61
|
return closing;
|
|
56
62
|
}
|
|
@@ -64,48 +70,60 @@ export class BrowserSession {
|
|
|
64
70
|
throw new Error("Browser operation cancelled; navigate again in a new call.");
|
|
65
71
|
clearTimeout(this.idle);
|
|
66
72
|
const cancellation = new AbortController();
|
|
73
|
+
this.activeCancellation = cancellation;
|
|
74
|
+
let ownedGeneration = generation;
|
|
67
75
|
const abort = () => {
|
|
68
76
|
cancellation.abort();
|
|
69
|
-
|
|
77
|
+
if (ownedGeneration === this.generation)
|
|
78
|
+
void this.close().catch(() => undefined);
|
|
79
|
+
};
|
|
80
|
+
const cancellationError = new Error("Browser cancelled or exceeded 30s; browser cleanup requested. External effects may already have occurred.");
|
|
81
|
+
const checkCurrent = () => {
|
|
82
|
+
if (cancellation.signal.aborted || generation !== this.generation)
|
|
83
|
+
throw cancellationError;
|
|
70
84
|
};
|
|
85
|
+
let rejectCancellation;
|
|
86
|
+
const interrupted = new Promise((_resolve, reject) => {
|
|
87
|
+
rejectCancellation = () => reject(cancellationError);
|
|
88
|
+
cancellation.signal.addEventListener("abort", rejectCancellation, { once: true });
|
|
89
|
+
});
|
|
90
|
+
const wait = (pending) => Promise.race([pending, interrupted]);
|
|
71
91
|
signal?.addEventListener("abort", abort, { once: true });
|
|
72
92
|
const deadline = setTimeout(abort, 30000);
|
|
73
93
|
try {
|
|
74
94
|
if (input.action === "close") {
|
|
75
|
-
|
|
95
|
+
// This operation intentionally invalidates its generation, without cancelling itself.
|
|
96
|
+
this.activeCancellation = undefined;
|
|
97
|
+
const closing = this.close();
|
|
98
|
+
ownedGeneration = this.generation;
|
|
99
|
+
await wait(closing);
|
|
76
100
|
return {
|
|
77
101
|
content: [{ type: "text", text: "Browser closed; ephemeral cookies and tabs discarded." }],
|
|
78
102
|
details: { action: input.action },
|
|
79
103
|
};
|
|
80
104
|
}
|
|
81
|
-
await this.closing;
|
|
82
|
-
|
|
83
|
-
throw new Error("Browser operation cancelled.");
|
|
105
|
+
await wait(this.closing);
|
|
106
|
+
checkCurrent();
|
|
84
107
|
if (!this.resources &&
|
|
85
108
|
input.action !== "navigate" &&
|
|
86
109
|
!(input.action === "tabs" && input.operation === "create")) {
|
|
87
110
|
throw new Error("No browser is open. Use navigate or tabs/create first. Idle cleanup discards tabs after 5 minutes.");
|
|
88
111
|
}
|
|
89
|
-
this.resources
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
cancellation.signal.addEventListener("abort", cancelled, { once: true });
|
|
105
|
-
}),
|
|
106
|
-
]);
|
|
107
|
-
if (signal?.aborted || generation !== this.generation)
|
|
108
|
-
throw new Error("Browser operation cancelled; external effects may already have occurred. Inspect before retrying.");
|
|
112
|
+
if (!this.resources) {
|
|
113
|
+
const owner = { generation };
|
|
114
|
+
this.owner = owner;
|
|
115
|
+
this.resources = this.open(owner).catch((error) => {
|
|
116
|
+
if (this.owner === owner) {
|
|
117
|
+
this.resources = undefined;
|
|
118
|
+
this.owner = undefined;
|
|
119
|
+
}
|
|
120
|
+
throw error;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
const resources = await wait(this.resources);
|
|
124
|
+
checkCurrent();
|
|
125
|
+
const content = await wait(this.perform(resources, input));
|
|
126
|
+
checkCurrent();
|
|
109
127
|
this.idle = setTimeout(() => {
|
|
110
128
|
void this.close().catch(() => undefined);
|
|
111
129
|
}, this.idleMs);
|
|
@@ -125,6 +143,9 @@ export class BrowserSession {
|
|
|
125
143
|
finally {
|
|
126
144
|
clearTimeout(deadline);
|
|
127
145
|
signal?.removeEventListener("abort", abort);
|
|
146
|
+
cancellation.signal.removeEventListener("abort", rejectCancellation);
|
|
147
|
+
if (this.activeCancellation === cancellation)
|
|
148
|
+
this.activeCancellation = undefined;
|
|
128
149
|
}
|
|
129
150
|
});
|
|
130
151
|
this.queue = operation.catch(() => undefined);
|
|
@@ -135,24 +156,37 @@ export class BrowserSession {
|
|
|
135
156
|
this.queued--;
|
|
136
157
|
}
|
|
137
158
|
}
|
|
138
|
-
async open() {
|
|
139
|
-
const
|
|
140
|
-
|
|
159
|
+
async open(owner) {
|
|
160
|
+
const checkCurrent = () => {
|
|
161
|
+
if (owner.generation !== this.generation)
|
|
162
|
+
throw new Error("Browser operation cancelled.");
|
|
163
|
+
};
|
|
141
164
|
try {
|
|
165
|
+
const proxy = await createBrowserProxy(this.allowPrivate);
|
|
166
|
+
owner.proxy = proxy;
|
|
167
|
+
checkCurrent();
|
|
142
168
|
const { chromium } = await import("playwright-core");
|
|
143
|
-
|
|
169
|
+
checkCurrent();
|
|
170
|
+
const browser = await chromium.launch({
|
|
144
171
|
headless: true,
|
|
145
172
|
timeout: 15000,
|
|
146
173
|
chromiumSandbox: true,
|
|
147
174
|
proxy: { server: proxy.url, bypass: "<-loopback>" },
|
|
148
175
|
args: ["--disable-quic", "--force-webrtc-ip-handling-policy=disable_non_proxied_udp"],
|
|
149
176
|
});
|
|
177
|
+
owner.browser = browser;
|
|
178
|
+
checkCurrent();
|
|
150
179
|
const context = await browser.newContext({
|
|
151
180
|
acceptDownloads: false,
|
|
152
181
|
serviceWorkers: "block",
|
|
153
182
|
permissions: [],
|
|
154
183
|
viewport: { width: 1280, height: 800 },
|
|
155
184
|
});
|
|
185
|
+
if (owner.generation !== this.generation) {
|
|
186
|
+
// newContext may complete after browser.close() was already requested.
|
|
187
|
+
void context.close().catch(() => undefined);
|
|
188
|
+
checkCurrent();
|
|
189
|
+
}
|
|
156
190
|
context.setDefaultTimeout(10000);
|
|
157
191
|
context.setDefaultNavigationTimeout(15000);
|
|
158
192
|
await context.route("**/*", async (route) => {
|
|
@@ -164,7 +198,9 @@ export class BrowserSession {
|
|
|
164
198
|
await route.abort().catch(() => undefined);
|
|
165
199
|
}
|
|
166
200
|
});
|
|
201
|
+
checkCurrent();
|
|
167
202
|
await context.routeWebSocket("**/*", (socket) => socket.close());
|
|
203
|
+
checkCurrent();
|
|
168
204
|
const resources = { browser, context, proxy, pages: new Map(), nextId: 1 };
|
|
169
205
|
context.on("page", (page) => {
|
|
170
206
|
if (resources.pages.size >= 4) {
|
|
@@ -184,8 +220,7 @@ export class BrowserSession {
|
|
|
184
220
|
return resources;
|
|
185
221
|
}
|
|
186
222
|
catch (error) {
|
|
187
|
-
await
|
|
188
|
-
await proxy.close();
|
|
223
|
+
await closeOwnedResources(owner).catch(() => undefined);
|
|
189
224
|
const message = error instanceof Error ? error.message : String(error);
|
|
190
225
|
throw new Error(`Browser launch failed. Matching Chromium may be missing after --ignore-scripts or offline installation. Ask the user to run lunr browser install when online. Nothing was installed by this call. ${message}`);
|
|
191
226
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/core/browser/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ImageContent, TextContent } from \"@ashx-j/lunr-ai/compat\";\nimport type { Browser, BrowserContext, Locator, Page } from \"playwright-core\";\nimport { truncateHead } from \"../tools/truncate.ts\";\nimport { browserUrl, createBrowserProxy, resolveBrowserHost } from \"./network.ts\";\nimport type { BrowserInput } from \"./schema.ts\";\n\ntype Resources = {\n\tbrowser: Browser;\n\tcontext: BrowserContext;\n\tproxy: Awaited<ReturnType<typeof createBrowserProxy>>;\n\tpages: Map<number, Page>;\n\tselected?: number;\n\tnextId: number;\n};\n\nexport function boundedBrowserText(text: string): string {\n\tconst result = truncateHead(text.replace(/[\\x00-\\x08\\x0b-\\x1f\\x7f-\\x9f]/g, \"\"), { maxBytes: 16384, maxLines: 300 });\n\treturn (\n\t\tresult.content +\n\t\t(result.truncated ? \"\\n[Snapshot truncated. Inspect a specific role/name or label to narrow it.]\" : \"\")\n\t);\n}\n\nfunction target(page: Page, input: BrowserInput): Locator {\n\tif (input.label !== undefined && input.role === undefined && input.name === undefined) {\n\t\treturn page.getByLabel(input.label, { exact: true });\n\t}\n\tif (input.role && input.label === undefined) return page.getByRole(input.role, { name: input.name, exact: true });\n\tthrow new Error(\"Specify role with optional exact name, or label alone. Inspect the page to find a target.\");\n}\n\nasync function uniqueTarget(page: Page, input: BrowserInput): Promise<Locator> {\n\tconst locator = target(page, input);\n\tconst count = await locator.count();\n\tif (count !== 1)\n\t\tthrow new Error(\n\t\t\t`Target matched ${count} elements. Inspect and choose a unique exact role/name or label; no action was taken.`,\n\t\t);\n\treturn locator;\n}\n\nexport class BrowserSession {\n\tprivate resources?: Promise<Resources>;\n\tprivate queue: Promise<unknown> = Promise.resolve();\n\tprivate closing: Promise<void> = Promise.resolve();\n\tprivate generation = 0;\n\tprivate queued = 0;\n\tprivate idle?: ReturnType<typeof setTimeout>;\n\n\tprivate readonly allowPrivate: boolean;\n\tprivate readonly idleMs: number;\n\n\tconstructor(allowPrivate = false, idleMs = 300000) {\n\t\tthis.allowPrivate = allowPrivate;\n\t\tthis.idleMs = idleMs;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.generation++;\n\t\tclearTimeout(this.idle);\n\t\tconst pending = this.resources;\n\t\tthis.resources = undefined;\n\t\tconst previous = this.closing;\n\t\tconst closing = (async () => {\n\t\t\tawait previous;\n\t\t\tconst resources = await pending?.catch(() => undefined);\n\t\t\tif (!resources) return;\n\t\t\ttry {\n\t\t\t\tawait resources.browser.close();\n\t\t\t} finally {\n\t\t\t\tawait resources.proxy.close();\n\t\t\t}\n\t\t})();\n\t\tthis.closing = closing.catch(() => undefined);\n\t\treturn closing;\n\t}\n\n\tasync run(\n\t\tinput: BrowserInput,\n\t\tsignal?: AbortSignal,\n\t): Promise<{ content: (TextContent | ImageContent)[]; details: { action: string } }> {\n\t\tif (this.queued >= 16) throw new Error(\"Browser queue is full. Wait for the current operation.\");\n\t\tconst generation = this.generation;\n\t\tthis.queued++;\n\t\tconst operation = this.queue.then(async () => {\n\t\t\tif (signal?.aborted || generation !== this.generation)\n\t\t\t\tthrow new Error(\"Browser operation cancelled; navigate again in a new call.\");\n\t\t\tclearTimeout(this.idle);\n\t\t\tconst cancellation = new AbortController();\n\t\t\tconst abort = () => {\n\t\t\t\tcancellation.abort();\n\t\t\t\tvoid this.close().catch(() => undefined);\n\t\t\t};\n\t\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t\t\tconst deadline = setTimeout(abort, 30000);\n\t\t\ttry {\n\t\t\t\tif (input.action === \"close\") {\n\t\t\t\t\tawait this.close();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: \"Browser closed; ephemeral cookies and tabs discarded.\" }],\n\t\t\t\t\t\tdetails: { action: input.action },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tawait this.closing;\n\t\t\t\tif (signal?.aborted || generation !== this.generation) throw new Error(\"Browser operation cancelled.\");\n\t\t\t\tif (\n\t\t\t\t\t!this.resources &&\n\t\t\t\t\tinput.action !== \"navigate\" &&\n\t\t\t\t\t!(input.action === \"tabs\" && input.operation === \"create\")\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"No browser is open. Use navigate or tabs/create first. Idle cleanup discards tabs after 5 minutes.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis.resources ??= this.open().catch((error) => {\n\t\t\t\t\tif (generation === this.generation) this.resources = undefined;\n\t\t\t\t\tthrow error;\n\t\t\t\t});\n\t\t\t\tconst resources = await this.resources;\n\t\t\t\tif (generation !== this.generation) throw new Error(\"Browser operation cancelled.\");\n\t\t\t\tconst content = await Promise.race([\n\t\t\t\t\tthis.perform(resources, input),\n\t\t\t\t\tnew Promise<never>((_resolve, reject) => {\n\t\t\t\t\t\tconst cancelled = () =>\n\t\t\t\t\t\t\treject(\n\t\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t\t\"Browser cancelled or exceeded 30s; browser closed. External effects may already have occurred.\",\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\tif (cancellation.signal.aborted) cancelled();\n\t\t\t\t\t\telse cancellation.signal.addEventListener(\"abort\", cancelled, { once: true });\n\t\t\t\t\t}),\n\t\t\t\t]);\n\t\t\t\tif (signal?.aborted || generation !== this.generation)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Browser operation cancelled; external effects may already have occurred. Inspect before retrying.\",\n\t\t\t\t\t);\n\t\t\t\tthis.idle = setTimeout(() => {\n\t\t\t\t\tvoid this.close().catch(() => undefined);\n\t\t\t\t}, this.idleMs);\n\t\t\t\tthis.idle.unref();\n\t\t\t\treturn { content, details: { action: input.action } };\n\t\t\t} catch (error) {\n\t\t\t\tif (generation === this.generation) {\n\t\t\t\t\tthis.idle = setTimeout(() => {\n\t\t\t\t\t\tvoid this.close().catch(() => undefined);\n\t\t\t\t\t}, this.idleMs);\n\t\t\t\t\tthis.idle.unref();\n\t\t\t\t}\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tthrow new Error(boundedBrowserText(message));\n\t\t\t} finally {\n\t\t\t\tclearTimeout(deadline);\n\t\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t\t}\n\t\t});\n\t\tthis.queue = operation.catch(() => undefined);\n\t\ttry {\n\t\t\treturn await operation;\n\t\t} finally {\n\t\t\tthis.queued--;\n\t\t}\n\t}\n\n\tprivate async open(): Promise<Resources> {\n\t\tconst proxy = await createBrowserProxy(this.allowPrivate);\n\t\tlet browser: Browser | undefined;\n\t\ttry {\n\t\t\tconst { chromium } = await import(\"playwright-core\");\n\t\t\tbrowser = await chromium.launch({\n\t\t\t\theadless: true,\n\t\t\t\ttimeout: 15000,\n\t\t\t\tchromiumSandbox: true,\n\t\t\t\tproxy: { server: proxy.url, bypass: \"<-loopback>\" },\n\t\t\t\targs: [\"--disable-quic\", \"--force-webrtc-ip-handling-policy=disable_non_proxied_udp\"],\n\t\t\t});\n\t\t\tconst context = await browser.newContext({\n\t\t\t\tacceptDownloads: false,\n\t\t\t\tserviceWorkers: \"block\",\n\t\t\t\tpermissions: [],\n\t\t\t\tviewport: { width: 1280, height: 800 },\n\t\t\t});\n\t\t\tcontext.setDefaultTimeout(10000);\n\t\t\tcontext.setDefaultNavigationTimeout(15000);\n\t\t\tawait context.route(\"**/*\", async (route) => {\n\t\t\t\ttry {\n\t\t\t\t\tbrowserUrl(route.request().url());\n\t\t\t\t\tawait route.continue();\n\t\t\t\t} catch {\n\t\t\t\t\tawait route.abort().catch(() => undefined);\n\t\t\t\t}\n\t\t\t});\n\t\t\tawait context.routeWebSocket(\"**/*\", (socket) => socket.close());\n\t\t\tconst resources: Resources = { browser, context, proxy, pages: new Map(), nextId: 1 };\n\t\t\tcontext.on(\"page\", (page) => {\n\t\t\t\tif (resources.pages.size >= 4) {\n\t\t\t\t\tvoid page.close().catch(() => undefined);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst id = resources.nextId++;\n\t\t\t\tresources.pages.set(id, page);\n\t\t\t\tpage.on(\"close\", () => resources.pages.delete(id));\n\t\t\t\tpage.on(\"dialog\", (dialog) => {\n\t\t\t\t\tvoid dialog.dismiss().catch(() => undefined);\n\t\t\t\t});\n\t\t\t\tpage.on(\"download\", (download) => {\n\t\t\t\t\tvoid download.cancel().catch(() => undefined);\n\t\t\t\t});\n\t\t\t});\n\t\t\treturn resources;\n\t\t} catch (error) {\n\t\t\tawait browser?.close().catch(() => undefined);\n\t\t\tawait proxy.close();\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(\n\t\t\t\t`Browser launch failed. Matching Chromium may be missing after --ignore-scripts or offline installation. Ask the user to run lunr browser install when online. Nothing was installed by this call. ${message}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async perform(resources: Resources, input: BrowserInput): Promise<(TextContent | ImageContent)[]> {\n\t\tconst text = (value: string): TextContent[] => [{ type: \"text\", text: boundedBrowserText(value) }];\n\t\tlet page = resources.pages.get(input.tab ?? resources.selected ?? -1);\n\t\tif (input.action === \"tabs\") {\n\t\t\tif (!input.operation) throw new Error(\"tabs requires operation list/create/select/close.\");\n\t\t\tif (input.operation === \"list\")\n\t\t\t\treturn text(\n\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t[...resources.pages].map(([id, tab]) => ({\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\tselected: id === resources.selected,\n\t\t\t\t\t\t\turl: tab.url(),\n\t\t\t\t\t\t})),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\tif (input.operation === \"select\") {\n\t\t\t\tif (!page || input.tab === undefined) throw new Error(\"Select requires an existing tab id from tabs/list.\");\n\t\t\t\tresources.selected = input.tab;\n\t\t\t\treturn text(`Selected tab ${input.tab}.`);\n\t\t\t}\n\t\t\tif (input.operation === \"close\") {\n\t\t\t\tif (!page) throw new Error(\"No matching tab. Use tabs/list.\");\n\t\t\t\tawait page.close();\n\t\t\t\tif (!resources.pages.has(resources.selected ?? -1))\n\t\t\t\t\tresources.selected = resources.pages.keys().next().value;\n\t\t\t\treturn text(\"Tab closed.\");\n\t\t\t}\n\t\t}\n\t\tif (input.action === \"navigate\" || (input.action === \"tabs\" && input.operation === \"create\")) {\n\t\t\tif (input.action === \"navigate\" && !input.url) throw new Error(\"navigate requires url.\");\n\t\t\tconst url = input.url ? browserUrl(input.url) : undefined;\n\t\t\tif (url) await resolveBrowserHost(url.hostname, this.allowPrivate);\n\t\t\tif (input.tab !== undefined && !page && input.action === \"navigate\")\n\t\t\t\tthrow new Error(\"Unknown tab. Use tabs/list.\");\n\t\t\tif (!page || input.action === \"tabs\") {\n\t\t\t\tif (resources.pages.size >= 4) throw new Error(\"Maximum 4 tabs. Close a tab first.\");\n\t\t\t\tpage = await resources.context.newPage();\n\t\t\t}\n\t\t\tresources.selected = [...resources.pages].find(([, candidate]) => candidate === page)?.[0];\n\t\t\tif (url) await page.goto(url.href, { waitUntil: \"domcontentloaded\" });\n\t\t\treturn text(\n\t\t\t\t`Tab ${resources.selected}: ${page.url()}\\nUse inspect for rendered content.${resources.proxy.blockedReason() ? `\\nNetwork warning: ${resources.proxy.blockedReason()}` : \"\"}`,\n\t\t\t);\n\t\t}\n\t\tif (!page) throw new Error(\"No selected tab. Use tabs/list or navigate.\");\n\t\tif (input.action === \"inspect\") {\n\t\t\tconst locator =\n\t\t\t\tinput.role || input.label !== undefined ? await uniqueTarget(page, input) : page.locator(\"body\");\n\t\t\treturn text(`Untrusted page content at ${page.url()}:\\n${await locator.ariaSnapshot()}`);\n\t\t}\n\t\tif (input.action === \"screenshot\") {\n\t\t\tconst image = await page.screenshot({ type: \"jpeg\", quality: 70, fullPage: false, timeout: 10000 });\n\t\t\tif (image.length > 2 * 1024 * 1024) throw new Error(\"Screenshot exceeds 2MB limit.\");\n\t\t\treturn [\n\t\t\t\t...text(`Untrusted viewport screenshot at ${page.url()}`),\n\t\t\t\t{ type: \"image\", mimeType: \"image/jpeg\", data: image.toString(\"base64\") },\n\t\t\t];\n\t\t}\n\t\tif (input.action === \"act\") {\n\t\t\tconst locator = await uniqueTarget(page, input);\n\t\t\tswitch (input.interaction) {\n\t\t\t\tcase \"click\":\n\t\t\t\t\tawait locator.click();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"fill\":\n\t\t\t\t\tif (input.value === undefined) throw new Error(\"fill requires value.\");\n\t\t\t\t\tawait locator.fill(input.value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"select\":\n\t\t\t\t\tif (input.value === undefined) throw new Error(\"select requires option value.\");\n\t\t\t\t\tawait locator.selectOption(input.value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"check\":\n\t\t\t\t\tif (input.checked === undefined) throw new Error(\"check requires checked.\");\n\t\t\t\t\tawait locator.setChecked(input.checked);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"press\":\n\t\t\t\t\tif (\n\t\t\t\t\t\t!input.value ||\n\t\t\t\t\t\t!/^(Enter|Tab|Escape|Space|Backspace|Delete|ArrowUp|ArrowDown|ArrowLeft|ArrowRight|Home|End|PageUp|PageDown)$/.test(\n\t\t\t\t\t\t\tinput.value,\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"press accepts Enter/Tab/Escape/Space/Backspace/Delete/arrows/Home/End/PageUp/PageDown only. Use fill for text.\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait locator.press(input.value);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(\"act requires interaction click/fill/select/check/press.\");\n\t\t\t}\n\t\t\treturn text(\n\t\t\t\t`Interaction completed at ${page.url()}. Inspect to verify the result. External effects cannot be undone by /undo.`,\n\t\t\t);\n\t\t}\n\t\tthrow new Error(\"Unsupported browser action.\");\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/core/browser/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ImageContent, TextContent } from \"@ashx-j/lunr-ai/compat\";\nimport type { Browser, BrowserContext, Locator, Page } from \"playwright-core\";\nimport { truncateHead } from \"../tools/truncate.ts\";\nimport { browserUrl, createBrowserProxy, resolveBrowserHost } from \"./network.ts\";\nimport type { BrowserInput } from \"./schema.ts\";\n\ntype Resources = {\n\tbrowser: Browser;\n\tcontext: BrowserContext;\n\tproxy: Awaited<ReturnType<typeof createBrowserProxy>>;\n\tpages: Map<number, Page>;\n\tselected?: number;\n\tnextId: number;\n};\n\ntype ResourceOwner = {\n\tgeneration: number;\n\tbrowser?: Browser;\n\tproxy?: Resources[\"proxy\"];\n\tbrowserClose?: Promise<void>;\n\tproxyClose?: Promise<void>;\n};\n\n// Resources can arrive after cancellation. Each owner closes only its own handles, once.\nfunction closeOwnedResources(owner?: ResourceOwner): Promise<void> {\n\tif (owner?.browser) owner.browserClose ??= Promise.resolve().then(() => owner.browser!.close());\n\tif (owner?.proxy) owner.proxyClose ??= Promise.resolve().then(() => owner.proxy!.close());\n\treturn Promise.allSettled([owner?.browserClose, owner?.proxyClose]).then((results) => {\n\t\tfor (const result of results) {\n\t\t\tif (result.status === \"rejected\") throw result.reason;\n\t\t}\n\t});\n}\n\nexport function boundedBrowserText(text: string): string {\n\tconst result = truncateHead(text.replace(/[\\x00-\\x08\\x0b-\\x1f\\x7f-\\x9f]/g, \"\"), { maxBytes: 16384, maxLines: 300 });\n\treturn (\n\t\tresult.content +\n\t\t(result.truncated ? \"\\n[Snapshot truncated. Inspect a specific role/name or label to narrow it.]\" : \"\")\n\t);\n}\n\nfunction target(page: Page, input: BrowserInput): Locator {\n\tif (input.label !== undefined && input.role === undefined && input.name === undefined) {\n\t\treturn page.getByLabel(input.label, { exact: true });\n\t}\n\tif (input.role && input.label === undefined) return page.getByRole(input.role, { name: input.name, exact: true });\n\tthrow new Error(\"Specify role with optional exact name, or label alone. Inspect the page to find a target.\");\n}\n\nasync function uniqueTarget(page: Page, input: BrowserInput): Promise<Locator> {\n\tconst locator = target(page, input);\n\tconst count = await locator.count();\n\tif (count !== 1)\n\t\tthrow new Error(\n\t\t\t`Target matched ${count} elements. Inspect and choose a unique exact role/name or label; no action was taken.`,\n\t\t);\n\treturn locator;\n}\n\nexport class BrowserSession {\n\tprivate resources?: Promise<Resources>;\n\tprivate owner?: ResourceOwner;\n\tprivate activeCancellation?: AbortController;\n\tprivate queue: Promise<unknown> = Promise.resolve();\n\tprivate closing: Promise<void> = Promise.resolve();\n\tprivate generation = 0;\n\tprivate queued = 0;\n\tprivate idle?: ReturnType<typeof setTimeout>;\n\n\tprivate readonly allowPrivate: boolean;\n\tprivate readonly idleMs: number;\n\n\tconstructor(allowPrivate = false, idleMs = 300000) {\n\t\tthis.allowPrivate = allowPrivate;\n\t\tthis.idleMs = idleMs;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.generation++;\n\t\tclearTimeout(this.idle);\n\t\tthis.activeCancellation?.abort();\n\t\tconst owner = this.owner;\n\t\tthis.owner = undefined;\n\t\tthis.resources = undefined;\n\t\t// Do not wait for initialization to discover handles. open() cleans late arrivals.\n\t\tconst closing = Promise.all([this.closing, closeOwnedResources(owner)]).then(() => undefined);\n\t\tthis.closing = closing.catch(() => undefined);\n\t\treturn closing;\n\t}\n\n\tasync run(\n\t\tinput: BrowserInput,\n\t\tsignal?: AbortSignal,\n\t): Promise<{ content: (TextContent | ImageContent)[]; details: { action: string } }> {\n\t\tif (this.queued >= 16) throw new Error(\"Browser queue is full. Wait for the current operation.\");\n\t\tconst generation = this.generation;\n\t\tthis.queued++;\n\t\tconst operation = this.queue.then(async () => {\n\t\t\tif (signal?.aborted || generation !== this.generation)\n\t\t\t\tthrow new Error(\"Browser operation cancelled; navigate again in a new call.\");\n\t\t\tclearTimeout(this.idle);\n\t\t\tconst cancellation = new AbortController();\n\t\t\tthis.activeCancellation = cancellation;\n\t\t\tlet ownedGeneration = generation;\n\t\t\tconst abort = () => {\n\t\t\t\tcancellation.abort();\n\t\t\t\tif (ownedGeneration === this.generation) void this.close().catch(() => undefined);\n\t\t\t};\n\t\t\tconst cancellationError = new Error(\n\t\t\t\t\"Browser cancelled or exceeded 30s; browser cleanup requested. External effects may already have occurred.\",\n\t\t\t);\n\t\t\tconst checkCurrent = () => {\n\t\t\t\tif (cancellation.signal.aborted || generation !== this.generation) throw cancellationError;\n\t\t\t};\n\t\t\tlet rejectCancellation!: () => void;\n\t\t\tconst interrupted = new Promise<never>((_resolve, reject) => {\n\t\t\t\trejectCancellation = () => reject(cancellationError);\n\t\t\t\tcancellation.signal.addEventListener(\"abort\", rejectCancellation, { once: true });\n\t\t\t});\n\t\t\tconst wait = <T>(pending: Promise<T>) => Promise.race([pending, interrupted]);\n\t\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t\t\tconst deadline = setTimeout(abort, 30000);\n\t\t\ttry {\n\t\t\t\tif (input.action === \"close\") {\n\t\t\t\t\t// This operation intentionally invalidates its generation, without cancelling itself.\n\t\t\t\t\tthis.activeCancellation = undefined;\n\t\t\t\t\tconst closing = this.close();\n\t\t\t\t\townedGeneration = this.generation;\n\t\t\t\t\tawait wait(closing);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: \"Browser closed; ephemeral cookies and tabs discarded.\" }],\n\t\t\t\t\t\tdetails: { action: input.action },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tawait wait(this.closing);\n\t\t\t\tcheckCurrent();\n\t\t\t\tif (\n\t\t\t\t\t!this.resources &&\n\t\t\t\t\tinput.action !== \"navigate\" &&\n\t\t\t\t\t!(input.action === \"tabs\" && input.operation === \"create\")\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"No browser is open. Use navigate or tabs/create first. Idle cleanup discards tabs after 5 minutes.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (!this.resources) {\n\t\t\t\t\tconst owner: ResourceOwner = { generation };\n\t\t\t\t\tthis.owner = owner;\n\t\t\t\t\tthis.resources = this.open(owner).catch((error) => {\n\t\t\t\t\t\tif (this.owner === owner) {\n\t\t\t\t\t\t\tthis.resources = undefined;\n\t\t\t\t\t\t\tthis.owner = undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst resources = await wait(this.resources);\n\t\t\t\tcheckCurrent();\n\t\t\t\tconst content = await wait(this.perform(resources, input));\n\t\t\t\tcheckCurrent();\n\t\t\t\tthis.idle = setTimeout(() => {\n\t\t\t\t\tvoid this.close().catch(() => undefined);\n\t\t\t\t}, this.idleMs);\n\t\t\t\tthis.idle.unref();\n\t\t\t\treturn { content, details: { action: input.action } };\n\t\t\t} catch (error) {\n\t\t\t\tif (generation === this.generation) {\n\t\t\t\t\tthis.idle = setTimeout(() => {\n\t\t\t\t\t\tvoid this.close().catch(() => undefined);\n\t\t\t\t\t}, this.idleMs);\n\t\t\t\t\tthis.idle.unref();\n\t\t\t\t}\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tthrow new Error(boundedBrowserText(message));\n\t\t\t} finally {\n\t\t\t\tclearTimeout(deadline);\n\t\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t\t\tcancellation.signal.removeEventListener(\"abort\", rejectCancellation);\n\t\t\t\tif (this.activeCancellation === cancellation) this.activeCancellation = undefined;\n\t\t\t}\n\t\t});\n\t\tthis.queue = operation.catch(() => undefined);\n\t\ttry {\n\t\t\treturn await operation;\n\t\t} finally {\n\t\t\tthis.queued--;\n\t\t}\n\t}\n\n\tprivate async open(owner: ResourceOwner): Promise<Resources> {\n\t\tconst checkCurrent = () => {\n\t\t\tif (owner.generation !== this.generation) throw new Error(\"Browser operation cancelled.\");\n\t\t};\n\t\ttry {\n\t\t\tconst proxy = await createBrowserProxy(this.allowPrivate);\n\t\t\towner.proxy = proxy;\n\t\t\tcheckCurrent();\n\t\t\tconst { chromium } = await import(\"playwright-core\");\n\t\t\tcheckCurrent();\n\t\t\tconst browser = await chromium.launch({\n\t\t\t\theadless: true,\n\t\t\t\ttimeout: 15000,\n\t\t\t\tchromiumSandbox: true,\n\t\t\t\tproxy: { server: proxy.url, bypass: \"<-loopback>\" },\n\t\t\t\targs: [\"--disable-quic\", \"--force-webrtc-ip-handling-policy=disable_non_proxied_udp\"],\n\t\t\t});\n\t\t\towner.browser = browser;\n\t\t\tcheckCurrent();\n\t\t\tconst context = await browser.newContext({\n\t\t\t\tacceptDownloads: false,\n\t\t\t\tserviceWorkers: \"block\",\n\t\t\t\tpermissions: [],\n\t\t\t\tviewport: { width: 1280, height: 800 },\n\t\t\t});\n\t\t\tif (owner.generation !== this.generation) {\n\t\t\t\t// newContext may complete after browser.close() was already requested.\n\t\t\t\tvoid context.close().catch(() => undefined);\n\t\t\t\tcheckCurrent();\n\t\t\t}\n\t\t\tcontext.setDefaultTimeout(10000);\n\t\t\tcontext.setDefaultNavigationTimeout(15000);\n\t\t\tawait context.route(\"**/*\", async (route) => {\n\t\t\t\ttry {\n\t\t\t\t\tbrowserUrl(route.request().url());\n\t\t\t\t\tawait route.continue();\n\t\t\t\t} catch {\n\t\t\t\t\tawait route.abort().catch(() => undefined);\n\t\t\t\t}\n\t\t\t});\n\t\t\tcheckCurrent();\n\t\t\tawait context.routeWebSocket(\"**/*\", (socket) => socket.close());\n\t\t\tcheckCurrent();\n\t\t\tconst resources: Resources = { browser, context, proxy, pages: new Map(), nextId: 1 };\n\t\t\tcontext.on(\"page\", (page) => {\n\t\t\t\tif (resources.pages.size >= 4) {\n\t\t\t\t\tvoid page.close().catch(() => undefined);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst id = resources.nextId++;\n\t\t\t\tresources.pages.set(id, page);\n\t\t\t\tpage.on(\"close\", () => resources.pages.delete(id));\n\t\t\t\tpage.on(\"dialog\", (dialog) => {\n\t\t\t\t\tvoid dialog.dismiss().catch(() => undefined);\n\t\t\t\t});\n\t\t\t\tpage.on(\"download\", (download) => {\n\t\t\t\t\tvoid download.cancel().catch(() => undefined);\n\t\t\t\t});\n\t\t\t});\n\t\t\treturn resources;\n\t\t} catch (error) {\n\t\t\tawait closeOwnedResources(owner).catch(() => undefined);\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(\n\t\t\t\t`Browser launch failed. Matching Chromium may be missing after --ignore-scripts or offline installation. Ask the user to run lunr browser install when online. Nothing was installed by this call. ${message}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async perform(resources: Resources, input: BrowserInput): Promise<(TextContent | ImageContent)[]> {\n\t\tconst text = (value: string): TextContent[] => [{ type: \"text\", text: boundedBrowserText(value) }];\n\t\tlet page = resources.pages.get(input.tab ?? resources.selected ?? -1);\n\t\tif (input.action === \"tabs\") {\n\t\t\tif (!input.operation) throw new Error(\"tabs requires operation list/create/select/close.\");\n\t\t\tif (input.operation === \"list\")\n\t\t\t\treturn text(\n\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t[...resources.pages].map(([id, tab]) => ({\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\tselected: id === resources.selected,\n\t\t\t\t\t\t\turl: tab.url(),\n\t\t\t\t\t\t})),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\tif (input.operation === \"select\") {\n\t\t\t\tif (!page || input.tab === undefined) throw new Error(\"Select requires an existing tab id from tabs/list.\");\n\t\t\t\tresources.selected = input.tab;\n\t\t\t\treturn text(`Selected tab ${input.tab}.`);\n\t\t\t}\n\t\t\tif (input.operation === \"close\") {\n\t\t\t\tif (!page) throw new Error(\"No matching tab. Use tabs/list.\");\n\t\t\t\tawait page.close();\n\t\t\t\tif (!resources.pages.has(resources.selected ?? -1))\n\t\t\t\t\tresources.selected = resources.pages.keys().next().value;\n\t\t\t\treturn text(\"Tab closed.\");\n\t\t\t}\n\t\t}\n\t\tif (input.action === \"navigate\" || (input.action === \"tabs\" && input.operation === \"create\")) {\n\t\t\tif (input.action === \"navigate\" && !input.url) throw new Error(\"navigate requires url.\");\n\t\t\tconst url = input.url ? browserUrl(input.url) : undefined;\n\t\t\tif (url) await resolveBrowserHost(url.hostname, this.allowPrivate);\n\t\t\tif (input.tab !== undefined && !page && input.action === \"navigate\")\n\t\t\t\tthrow new Error(\"Unknown tab. Use tabs/list.\");\n\t\t\tif (!page || input.action === \"tabs\") {\n\t\t\t\tif (resources.pages.size >= 4) throw new Error(\"Maximum 4 tabs. Close a tab first.\");\n\t\t\t\tpage = await resources.context.newPage();\n\t\t\t}\n\t\t\tresources.selected = [...resources.pages].find(([, candidate]) => candidate === page)?.[0];\n\t\t\tif (url) await page.goto(url.href, { waitUntil: \"domcontentloaded\" });\n\t\t\treturn text(\n\t\t\t\t`Tab ${resources.selected}: ${page.url()}\\nUse inspect for rendered content.${resources.proxy.blockedReason() ? `\\nNetwork warning: ${resources.proxy.blockedReason()}` : \"\"}`,\n\t\t\t);\n\t\t}\n\t\tif (!page) throw new Error(\"No selected tab. Use tabs/list or navigate.\");\n\t\tif (input.action === \"inspect\") {\n\t\t\tconst locator =\n\t\t\t\tinput.role || input.label !== undefined ? await uniqueTarget(page, input) : page.locator(\"body\");\n\t\t\treturn text(`Untrusted page content at ${page.url()}:\\n${await locator.ariaSnapshot()}`);\n\t\t}\n\t\tif (input.action === \"screenshot\") {\n\t\t\tconst image = await page.screenshot({ type: \"jpeg\", quality: 70, fullPage: false, timeout: 10000 });\n\t\t\tif (image.length > 2 * 1024 * 1024) throw new Error(\"Screenshot exceeds 2MB limit.\");\n\t\t\treturn [\n\t\t\t\t...text(`Untrusted viewport screenshot at ${page.url()}`),\n\t\t\t\t{ type: \"image\", mimeType: \"image/jpeg\", data: image.toString(\"base64\") },\n\t\t\t];\n\t\t}\n\t\tif (input.action === \"act\") {\n\t\t\tconst locator = await uniqueTarget(page, input);\n\t\t\tswitch (input.interaction) {\n\t\t\t\tcase \"click\":\n\t\t\t\t\tawait locator.click();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"fill\":\n\t\t\t\t\tif (input.value === undefined) throw new Error(\"fill requires value.\");\n\t\t\t\t\tawait locator.fill(input.value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"select\":\n\t\t\t\t\tif (input.value === undefined) throw new Error(\"select requires option value.\");\n\t\t\t\t\tawait locator.selectOption(input.value);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"check\":\n\t\t\t\t\tif (input.checked === undefined) throw new Error(\"check requires checked.\");\n\t\t\t\t\tawait locator.setChecked(input.checked);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"press\":\n\t\t\t\t\tif (\n\t\t\t\t\t\t!input.value ||\n\t\t\t\t\t\t!/^(Enter|Tab|Escape|Space|Backspace|Delete|ArrowUp|ArrowDown|ArrowLeft|ArrowRight|Home|End|PageUp|PageDown)$/.test(\n\t\t\t\t\t\t\tinput.value,\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"press accepts Enter/Tab/Escape/Space/Backspace/Delete/arrows/Home/End/PageUp/PageDown only. Use fill for text.\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait locator.press(input.value);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(\"act requires interaction click/fill/select/check/press.\");\n\t\t\t}\n\t\t\treturn text(\n\t\t\t\t`Interaction completed at ${page.url()}. Inspect to verify the result. External effects cannot be undone by /undo.`,\n\t\t\t);\n\t\t}\n\t\tthrow new Error(\"Unsupported browser action.\");\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/core/browser/setup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/core/browser/setup.ts"],"names":[],"mappings":"AAIA,wBAAsB,cAAc,CAAC,QAAQ,UAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBnE","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { fileURLToPath } from \"node:url\";\nimport { isBunBinary } from \"../../config.ts\";\n\nexport async function installBrowser(explicit = true): Promise<void> {\n\tif (isBunBinary) {\n\t\tconst notice =\n\t\t\t\"Chromium installation is unavailable in the compiled standalone executable. Install the same lunR version through npm and run lunr browser install there. Use the same PLAYWRIGHT_BROWSERS_PATH for installation and standalone execution.\";\n\t\tif (explicit) throw new Error(notice);\n\t\tconsole.warn(notice);\n\t\treturn;\n\t}\n\tconst script = fileURLToPath(new URL(\"../../../scripts/install-browser.mjs\", import.meta.url));\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst child = spawn(process.execPath, [script, ...(explicit ? [\"--explicit\"] : [])], {\n\t\t\tstdio: \"inherit\",\n\t\t\twindowsHide: true,\n\t\t});\n\t\tchild.once(\"error\", reject);\n\t\tchild.once(\"exit\", (code) => {\n\t\t\tif (code === 0) resolve();\n\t\t\telse reject(new Error(`Chromium setup failed (${code}). Retry lunr browser install when online.`));\n\t\t});\n\t});\n}\n"]}
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { isBunBinary } from "../../config.js";
|
|
3
4
|
export async function installBrowser(explicit = true) {
|
|
5
|
+
if (isBunBinary) {
|
|
6
|
+
const notice = "Chromium installation is unavailable in the compiled standalone executable. Install the same lunR version through npm and run lunr browser install there. Use the same PLAYWRIGHT_BROWSERS_PATH for installation and standalone execution.";
|
|
7
|
+
if (explicit)
|
|
8
|
+
throw new Error(notice);
|
|
9
|
+
console.warn(notice);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
4
12
|
const script = fileURLToPath(new URL("../../../scripts/install-browser.mjs", import.meta.url));
|
|
5
13
|
await new Promise((resolve, reject) => {
|
|
6
|
-
const child = spawn(process.execPath, [script, ...(explicit ? ["--explicit"] : [])], {
|
|
14
|
+
const child = spawn(process.execPath, [script, ...(explicit ? ["--explicit"] : [])], {
|
|
15
|
+
stdio: "inherit",
|
|
16
|
+
windowsHide: true,
|
|
17
|
+
});
|
|
7
18
|
child.once("error", reject);
|
|
8
19
|
child.once("exit", (code) => {
|
|
9
20
|
if (code === 0)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/core/browser/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/core/browser/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAQ,GAAG,IAAI,EAAiB;IACpE,IAAI,WAAW,EAAE,CAAC;QACjB,MAAM,MAAM,GACX,4OAA4O,CAAC;QAC9O,IAAI,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,OAAO;IACR,CAAC;IACD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,sCAAsC,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/F,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;YACpF,KAAK,EAAE,SAAS;YAChB,WAAW,EAAE,IAAI;SACjB,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;YAC5B,IAAI,IAAI,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;;gBACrB,MAAM,CAAC,IAAI,KAAK,CAAC,0BAA0B,IAAI,4CAA4C,CAAC,CAAC,CAAC;QAAA,CACnG,CAAC,CAAC;IAAA,CACH,CAAC,CAAC;AAAA,CACH","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { fileURLToPath } from \"node:url\";\nimport { isBunBinary } from \"../../config.ts\";\n\nexport async function installBrowser(explicit = true): Promise<void> {\n\tif (isBunBinary) {\n\t\tconst notice =\n\t\t\t\"Chromium installation is unavailable in the compiled standalone executable. Install the same lunR version through npm and run lunr browser install there. Use the same PLAYWRIGHT_BROWSERS_PATH for installation and standalone execution.\";\n\t\tif (explicit) throw new Error(notice);\n\t\tconsole.warn(notice);\n\t\treturn;\n\t}\n\tconst script = fileURLToPath(new URL(\"../../../scripts/install-browser.mjs\", import.meta.url));\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst child = spawn(process.execPath, [script, ...(explicit ? [\"--explicit\"] : [])], {\n\t\t\tstdio: \"inherit\",\n\t\t\twindowsHide: true,\n\t\t});\n\t\tchild.once(\"error\", reject);\n\t\tchild.once(\"exit\", (code) => {\n\t\t\tif (code === 0) resolve();\n\t\t\telse reject(new Error(`Chromium setup failed (${code}). Retry lunr browser install when online.`));\n\t\t});\n\t});\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/core/computer-use/adapter.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAMnE,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAClE,qBAAa,eAAgB,SAAQ,KAAK;IACzC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,GAAG,gBAAgB,CAAC;IACvD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,YAAY,KAAK,EAAE,mBAAmB,GAAG,gBAAgB,EAAE,UAAU,EAAE,OAAO,EAI7E;CACD;AACD,MAAM,WAAW,cAAc;IAC9B,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9F,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,kBAAkB,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACpE;AAED,qBAAa,UAAW,YAAW,cAAc;IAChD,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,SAAS,CAAC,CAAuB;IACzC,OAAO,CAAC,GAAG,CAAC,CAAa;IACzB,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,UAAU,CAAC,CAAgB;IACnC,OAAO,CAAC,OAAO,CAAC,CAAgB;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAC/C,OAAO,CAAC,eAAe,CAAC,CAAiC;IACzD,kBAAkB,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAEjE;YAEa,OAAO;IA4Cf,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/core/computer-use/adapter.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAMnE,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAClE,qBAAa,eAAgB,SAAQ,KAAK;IACzC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,GAAG,gBAAgB,CAAC;IACvD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,YAAY,KAAK,EAAE,mBAAmB,GAAG,gBAAgB,EAAE,UAAU,EAAE,OAAO,EAI7E;CACD;AACD,MAAM,WAAW,cAAc;IAC9B,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9F,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,kBAAkB,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACpE;AAED,qBAAa,UAAW,YAAW,cAAc;IAChD,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,SAAS,CAAC,CAAuB;IACzC,OAAO,CAAC,GAAG,CAAC,CAAa;IACzB,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,UAAU,CAAC,CAAgB;IACnC,OAAO,CAAC,OAAO,CAAC,CAAgB;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAC/C,OAAO,CAAC,eAAe,CAAC,CAAiC;IACzD,kBAAkB,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAEjE;YAEa,OAAO;IA4Cf,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CA0BlG;IAED,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAIrB;YAEa,IAAI;CAwBlB","sourcesContent":["import { mkdir, mkdtemp, realpath, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { MacRuntime } from \"./macos-runtime.ts\";\nimport { CUA_VERSION, installRuntime, runtimeEnvironment } from \"./runtime.ts\";\nimport { assertInteractiveDesktop } from \"./windows-desktop.ts\";\n\nexport type DriverReply = Awaited<ReturnType<Client[\"callTool\"]>>;\nexport class DriverCallError extends Error {\n\treadonly phase: \"adapter_preflight\" | \"native_request\";\n\treadonly dispatched: boolean;\n\tconstructor(phase: \"adapter_preflight\" | \"native_request\", dispatched: boolean) {\n\t\tsuper(phase === \"adapter_preflight\" ? \"Computer adapter preflight failed.\" : \"Computer native request failed.\");\n\t\tthis.phase = phase;\n\t\tthis.dispatched = dispatched;\n\t}\n}\nexport interface ComputerDriver {\n\tcall(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<DriverReply>;\n\tclose(): Promise<void>;\n\tsetProcessObserver?(observer: (pid: number) => Promise<void>): void;\n}\n\nexport class CuaAdapter implements ComputerDriver {\n\tprivate client?: Client;\n\tprivate transport?: StdioClientTransport;\n\tprivate mac?: MacRuntime;\n\tprivate stateDirectory?: string;\n\tprivate connecting?: Promise<void>;\n\tprivate closing?: Promise<void>;\n\tprivate readonly abort = new AbortController();\n\tprivate processObserver?: (pid: number) => Promise<void>;\n\tsetProcessObserver(observer: (pid: number) => Promise<void>): void {\n\t\tthis.processObserver = observer;\n\t}\n\n\tprivate async connect(signal: AbortSignal): Promise<void> {\n\t\tconst { command, app } = await installRuntime(signal);\n\t\tsignal.throwIfAborted();\n\t\tlet args = [\"mcp\", \"--direct\", \"--embedded\", \"--no-overlay\"];\n\t\tif (app) {\n\t\t\tthis.mac = new MacRuntime();\n\t\t\tconst socket = await this.mac.start(app, signal);\n\t\t\targs = [\"mcp\", \"--embedded\", \"--socket\", socket, \"--no-overlay\"];\n\t\t}\n\t\tsignal.throwIfAborted();\n\t\tconst state = await mkdtemp(join(await realpath(tmpdir()), \"lunr-cua-client-\"));\n\t\tthis.stateDirectory = state;\n\t\tconst appData = join(state, \"AppData\");\n\t\tawait mkdir(appData);\n\t\tsignal.throwIfAborted();\n\t\tthis.transport = new StdioClientTransport({\n\t\t\tcommand,\n\t\t\targs,\n\t\t\tstderr: \"pipe\",\n\t\t\tenv: {\n\t\t\t\t...runtimeEnvironment(),\n\t\t\t\tHOME: state,\n\t\t\t\tUSERPROFILE: state,\n\t\t\t\tAPPDATA: appData,\n\t\t\t\tLOCALAPPDATA: appData,\n\t\t\t\tXDG_CONFIG_HOME: appData,\n\t\t\t\tXDG_STATE_HOME: appData,\n\t\t\t},\n\t\t});\n\t\t// Drain diagnostics without retaining desktop or runtime data in session history.\n\t\tthis.transport.stderr?.on(\"data\", () => {});\n\t\tthis.client = new Client({ name: \"lunr-computer-use\", version: CUA_VERSION });\n\t\tawait this.client.connect(this.transport, { timeout: 15000, signal });\n\t\tsignal.throwIfAborted();\n\t\tif (this.client.getServerVersion()?.version !== CUA_VERSION)\n\t\t\tthrow new Error(\"Computer runtime version mismatch.\");\n\t\tconst pids = [this.transport.pid, ...(this.mac ? [this.mac.processId] : [])];\n\t\tfor (const pid of pids) {\n\t\t\tif (typeof pid !== \"number\" || !Number.isInteger(pid) || pid < 1)\n\t\t\t\tthrow new Error(\"Computer runtime process identity is missing. Input refused.\");\n\t\t\tawait this.processObserver?.(pid);\n\t\t}\n\t}\n\n\tasync call(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<DriverReply> {\n\t\tconst combined = AbortSignal.any([this.abort.signal, ...(signal ? [signal] : [])]);\n\t\tcombined.throwIfAborted();\n\t\tlet dispatched = false;\n\t\ttry {\n\t\t\tawait assertInteractiveDesktop(combined);\n\t\t\tcombined.throwIfAborted();\n\t\t\tthis.connecting ??= this.connect(AbortSignal.any([combined, AbortSignal.timeout(60000)]));\n\t\t\tawait this.connecting;\n\t\t\tcombined.throwIfAborted();\n\t\t\tif (!this.client) throw new Error(\"Computer connection closed.\");\n\t\t\tdispatched = true;\n\t\t\treturn await this.client.callTool({ name, arguments: args }, undefined, {\n\t\t\t\ttimeout: name === \"launch_app\" ? 45000 : 15000,\n\t\t\t\tsignal: combined,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst wasCancelled = combined.aborted;\n\t\t\ttry {\n\t\t\t\tawait this.close();\n\t\t\t} catch {\n\t\t\t\t/* The workflow retains the lease if shutdown is unconfirmed. */\n\t\t\t}\n\t\t\tif (wasCancelled) throw error;\n\t\t\tthrow new DriverCallError(dispatched ? \"native_request\" : \"adapter_preflight\", dispatched);\n\t\t}\n\t}\n\n\tclose(): Promise<void> {\n\t\tthis.abort.abort();\n\t\tthis.closing ??= this.stop();\n\t\treturn this.closing;\n\t}\n\n\tprivate async stop(): Promise<void> {\n\t\tawait this.connecting?.catch(() => undefined);\n\t\tconst pid = this.transport?.pid;\n\t\tawait this.client?.close();\n\t\tawait this.transport?.close();\n\t\tif (pid) {\n\t\t\tconst deadline = Date.now() + 5000;\n\t\t\tfor (;;) {\n\t\t\t\ttry {\n\t\t\t\t\tprocess.kill(pid, 0);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof Error && \"code\" in error && error.code === \"ESRCH\") break;\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (Date.now() >= deadline)\n\t\t\t\t\tthrow new Error(\"Owned computer process shutdown is unconfirmed. Desktop lease retained.\");\n\t\t\t\tawait delay(50);\n\t\t\t}\n\t\t}\n\t\tawait this.mac?.close();\n\t\tif (this.stateDirectory) await rm(this.stateDirectory, { recursive: true, force: true });\n\t\tthis.client = undefined;\n\t\tthis.transport = undefined;\n\t}\n}\n"]}
|
|
@@ -84,14 +84,19 @@ export class CuaAdapter {
|
|
|
84
84
|
if (!this.client)
|
|
85
85
|
throw new Error("Computer connection closed.");
|
|
86
86
|
dispatched = true;
|
|
87
|
-
return await this.client.callTool({ name, arguments: args }, undefined, {
|
|
87
|
+
return await this.client.callTool({ name, arguments: args }, undefined, {
|
|
88
|
+
timeout: name === "launch_app" ? 45000 : 15000,
|
|
89
|
+
signal: combined,
|
|
90
|
+
});
|
|
88
91
|
}
|
|
89
92
|
catch (error) {
|
|
90
93
|
const wasCancelled = combined.aborted;
|
|
91
94
|
try {
|
|
92
95
|
await this.close();
|
|
93
96
|
}
|
|
94
|
-
catch {
|
|
97
|
+
catch {
|
|
98
|
+
/* The workflow retains the lease if shutdown is unconfirmed. */
|
|
99
|
+
}
|
|
95
100
|
if (wasCancelled)
|
|
96
101
|
throw error;
|
|
97
102
|
throw new DriverCallError(dispatched ? "native_request" : "adapter_preflight", dispatched);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/core/computer-use/adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, mkdtemp, realpath, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { MacRuntime } from \"./macos-runtime.ts\";\nimport { CUA_VERSION, installRuntime, runtimeEnvironment } from \"./runtime.ts\";\nimport { assertInteractiveDesktop } from \"./windows-desktop.ts\";\n\nexport type DriverReply = Awaited<ReturnType<Client[\"callTool\"]>>;\nexport class DriverCallError extends Error {\n\treadonly phase: \"adapter_preflight\" | \"native_request\";\n\treadonly dispatched: boolean;\n\tconstructor(phase: \"adapter_preflight\" | \"native_request\", dispatched: boolean) {\n\t\tsuper(phase === \"adapter_preflight\" ? \"Computer adapter preflight failed.\" : \"Computer native request failed.\");\n\t\tthis.phase = phase;\n\t\tthis.dispatched = dispatched;\n\t}\n}\nexport interface ComputerDriver {\n\tcall(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<DriverReply>;\n\tclose(): Promise<void>;\n\tsetProcessObserver?(observer: (pid: number) => Promise<void>): void;\n}\n\nexport class CuaAdapter implements ComputerDriver {\n\tprivate client?: Client;\n\tprivate transport?: StdioClientTransport;\n\tprivate mac?: MacRuntime;\n\tprivate stateDirectory?: string;\n\tprivate connecting?: Promise<void>;\n\tprivate closing?: Promise<void>;\n\tprivate readonly abort = new AbortController();\n\tprivate processObserver?: (pid: number) => Promise<void>;\n\tsetProcessObserver(observer: (pid: number) => Promise<void>): void {\n\t\tthis.processObserver = observer;\n\t}\n\n\tprivate async connect(signal: AbortSignal): Promise<void> {\n\t\tconst { command, app } = await installRuntime(signal);\n\t\tsignal.throwIfAborted();\n\t\tlet args = [\"mcp\", \"--direct\", \"--embedded\", \"--no-overlay\"];\n\t\tif (app) {\n\t\t\tthis.mac = new MacRuntime();\n\t\t\tconst socket = await this.mac.start(app, signal);\n\t\t\targs = [\"mcp\", \"--embedded\", \"--socket\", socket, \"--no-overlay\"];\n\t\t}\n\t\tsignal.throwIfAborted();\n\t\tconst state = await mkdtemp(join(await realpath(tmpdir()), \"lunr-cua-client-\"));\n\t\tthis.stateDirectory = state;\n\t\tconst appData = join(state, \"AppData\");\n\t\tawait mkdir(appData);\n\t\tsignal.throwIfAborted();\n\t\tthis.transport = new StdioClientTransport({\n\t\t\tcommand,\n\t\t\targs,\n\t\t\tstderr: \"pipe\",\n\t\t\tenv: {\n\t\t\t\t...runtimeEnvironment(),\n\t\t\t\tHOME: state,\n\t\t\t\tUSERPROFILE: state,\n\t\t\t\tAPPDATA: appData,\n\t\t\t\tLOCALAPPDATA: appData,\n\t\t\t\tXDG_CONFIG_HOME: appData,\n\t\t\t\tXDG_STATE_HOME: appData,\n\t\t\t},\n\t\t});\n\t\t// Drain diagnostics without retaining desktop or runtime data in session history.\n\t\tthis.transport.stderr?.on(\"data\", () => {});\n\t\tthis.client = new Client({ name: \"lunr-computer-use\", version: CUA_VERSION });\n\t\tawait this.client.connect(this.transport, { timeout: 15000, signal });\n\t\tsignal.throwIfAborted();\n\t\tif (this.client.getServerVersion()?.version !== CUA_VERSION)\n\t\t\tthrow new Error(\"Computer runtime version mismatch.\");\n\t\tconst pids = [this.transport.pid, ...(this.mac ? [this.mac.processId] : [])];\n\t\tfor (const pid of pids) {\n\t\t\tif (typeof pid !== \"number\" || !Number.isInteger(pid) || pid < 1)\n\t\t\t\tthrow new Error(\"Computer runtime process identity is missing. Input refused.\");\n\t\t\tawait this.processObserver?.(pid);\n\t\t}\n\t}\n\n\tasync call(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<DriverReply> {\n\t\tconst combined = AbortSignal.any([this.abort.signal, ...(signal ? [signal] : [])]);\n\t\tcombined.throwIfAborted();\n\t\tlet dispatched = false;\n\t\ttry {\n\t\t\tawait assertInteractiveDesktop(combined);\n\t\t\tcombined.throwIfAborted();\n\t\t\tthis.connecting ??= this.connect(AbortSignal.any([combined, AbortSignal.timeout(60000)]));\n\t\t\tawait this.connecting;\n\t\t\tcombined.throwIfAborted();\n\t\t\tif (!this.client) throw new Error(\"Computer connection closed.\");\n\t\t\tdispatched = true;\n\t\t\treturn await this.client.callTool({ name, arguments: args }, undefined, { timeout: name === \"launch_app\" ? 45000 : 15000, signal: combined });\n\t\t} catch (error) {\n\t\t\tconst wasCancelled = combined.aborted;\n\t\t\ttry { await this.close(); } catch { /* The workflow retains the lease if shutdown is unconfirmed. */ }\n\t\t\tif (wasCancelled) throw error;\n\t\t\tthrow new DriverCallError(dispatched ? \"native_request\" : \"adapter_preflight\", dispatched);\n\t\t}\n\t}\n\n\tclose(): Promise<void> {\n\t\tthis.abort.abort();\n\t\tthis.closing ??= this.stop();\n\t\treturn this.closing;\n\t}\n\n\tprivate async stop(): Promise<void> {\n\t\tawait this.connecting?.catch(() => undefined);\n\t\tconst pid = this.transport?.pid;\n\t\tawait this.client?.close();\n\t\tawait this.transport?.close();\n\t\tif (pid) {\n\t\t\tconst deadline = Date.now() + 5000;\n\t\t\tfor (;;) {\n\t\t\t\ttry {\n\t\t\t\t\tprocess.kill(pid, 0);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof Error && \"code\" in error && error.code === \"ESRCH\") break;\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (Date.now() >= deadline)\n\t\t\t\t\tthrow new Error(\"Owned computer process shutdown is unconfirmed. Desktop lease retained.\");\n\t\t\t\tawait delay(50);\n\t\t\t}\n\t\t}\n\t\tawait this.mac?.close();\n\t\tif (this.stateDirectory) await rm(this.stateDirectory, { recursive: true, force: true });\n\t\tthis.client = undefined;\n\t\tthis.transport = undefined;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/core/computer-use/adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, mkdtemp, realpath, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { MacRuntime } from \"./macos-runtime.ts\";\nimport { CUA_VERSION, installRuntime, runtimeEnvironment } from \"./runtime.ts\";\nimport { assertInteractiveDesktop } from \"./windows-desktop.ts\";\n\nexport type DriverReply = Awaited<ReturnType<Client[\"callTool\"]>>;\nexport class DriverCallError extends Error {\n\treadonly phase: \"adapter_preflight\" | \"native_request\";\n\treadonly dispatched: boolean;\n\tconstructor(phase: \"adapter_preflight\" | \"native_request\", dispatched: boolean) {\n\t\tsuper(phase === \"adapter_preflight\" ? \"Computer adapter preflight failed.\" : \"Computer native request failed.\");\n\t\tthis.phase = phase;\n\t\tthis.dispatched = dispatched;\n\t}\n}\nexport interface ComputerDriver {\n\tcall(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<DriverReply>;\n\tclose(): Promise<void>;\n\tsetProcessObserver?(observer: (pid: number) => Promise<void>): void;\n}\n\nexport class CuaAdapter implements ComputerDriver {\n\tprivate client?: Client;\n\tprivate transport?: StdioClientTransport;\n\tprivate mac?: MacRuntime;\n\tprivate stateDirectory?: string;\n\tprivate connecting?: Promise<void>;\n\tprivate closing?: Promise<void>;\n\tprivate readonly abort = new AbortController();\n\tprivate processObserver?: (pid: number) => Promise<void>;\n\tsetProcessObserver(observer: (pid: number) => Promise<void>): void {\n\t\tthis.processObserver = observer;\n\t}\n\n\tprivate async connect(signal: AbortSignal): Promise<void> {\n\t\tconst { command, app } = await installRuntime(signal);\n\t\tsignal.throwIfAborted();\n\t\tlet args = [\"mcp\", \"--direct\", \"--embedded\", \"--no-overlay\"];\n\t\tif (app) {\n\t\t\tthis.mac = new MacRuntime();\n\t\t\tconst socket = await this.mac.start(app, signal);\n\t\t\targs = [\"mcp\", \"--embedded\", \"--socket\", socket, \"--no-overlay\"];\n\t\t}\n\t\tsignal.throwIfAborted();\n\t\tconst state = await mkdtemp(join(await realpath(tmpdir()), \"lunr-cua-client-\"));\n\t\tthis.stateDirectory = state;\n\t\tconst appData = join(state, \"AppData\");\n\t\tawait mkdir(appData);\n\t\tsignal.throwIfAborted();\n\t\tthis.transport = new StdioClientTransport({\n\t\t\tcommand,\n\t\t\targs,\n\t\t\tstderr: \"pipe\",\n\t\t\tenv: {\n\t\t\t\t...runtimeEnvironment(),\n\t\t\t\tHOME: state,\n\t\t\t\tUSERPROFILE: state,\n\t\t\t\tAPPDATA: appData,\n\t\t\t\tLOCALAPPDATA: appData,\n\t\t\t\tXDG_CONFIG_HOME: appData,\n\t\t\t\tXDG_STATE_HOME: appData,\n\t\t\t},\n\t\t});\n\t\t// Drain diagnostics without retaining desktop or runtime data in session history.\n\t\tthis.transport.stderr?.on(\"data\", () => {});\n\t\tthis.client = new Client({ name: \"lunr-computer-use\", version: CUA_VERSION });\n\t\tawait this.client.connect(this.transport, { timeout: 15000, signal });\n\t\tsignal.throwIfAborted();\n\t\tif (this.client.getServerVersion()?.version !== CUA_VERSION)\n\t\t\tthrow new Error(\"Computer runtime version mismatch.\");\n\t\tconst pids = [this.transport.pid, ...(this.mac ? [this.mac.processId] : [])];\n\t\tfor (const pid of pids) {\n\t\t\tif (typeof pid !== \"number\" || !Number.isInteger(pid) || pid < 1)\n\t\t\t\tthrow new Error(\"Computer runtime process identity is missing. Input refused.\");\n\t\t\tawait this.processObserver?.(pid);\n\t\t}\n\t}\n\n\tasync call(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<DriverReply> {\n\t\tconst combined = AbortSignal.any([this.abort.signal, ...(signal ? [signal] : [])]);\n\t\tcombined.throwIfAborted();\n\t\tlet dispatched = false;\n\t\ttry {\n\t\t\tawait assertInteractiveDesktop(combined);\n\t\t\tcombined.throwIfAborted();\n\t\t\tthis.connecting ??= this.connect(AbortSignal.any([combined, AbortSignal.timeout(60000)]));\n\t\t\tawait this.connecting;\n\t\t\tcombined.throwIfAborted();\n\t\t\tif (!this.client) throw new Error(\"Computer connection closed.\");\n\t\t\tdispatched = true;\n\t\t\treturn await this.client.callTool({ name, arguments: args }, undefined, {\n\t\t\t\ttimeout: name === \"launch_app\" ? 45000 : 15000,\n\t\t\t\tsignal: combined,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst wasCancelled = combined.aborted;\n\t\t\ttry {\n\t\t\t\tawait this.close();\n\t\t\t} catch {\n\t\t\t\t/* The workflow retains the lease if shutdown is unconfirmed. */\n\t\t\t}\n\t\t\tif (wasCancelled) throw error;\n\t\t\tthrow new DriverCallError(dispatched ? \"native_request\" : \"adapter_preflight\", dispatched);\n\t\t}\n\t}\n\n\tclose(): Promise<void> {\n\t\tthis.abort.abort();\n\t\tthis.closing ??= this.stop();\n\t\treturn this.closing;\n\t}\n\n\tprivate async stop(): Promise<void> {\n\t\tawait this.connecting?.catch(() => undefined);\n\t\tconst pid = this.transport?.pid;\n\t\tawait this.client?.close();\n\t\tawait this.transport?.close();\n\t\tif (pid) {\n\t\t\tconst deadline = Date.now() + 5000;\n\t\t\tfor (;;) {\n\t\t\t\ttry {\n\t\t\t\t\tprocess.kill(pid, 0);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof Error && \"code\" in error && error.code === \"ESRCH\") break;\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (Date.now() >= deadline)\n\t\t\t\t\tthrow new Error(\"Owned computer process shutdown is unconfirmed. Desktop lease retained.\");\n\t\t\t\tawait delay(50);\n\t\t\t}\n\t\t}\n\t\tawait this.mac?.close();\n\t\tif (this.stateDirectory) await rm(this.stateDirectory, { recursive: true, force: true });\n\t\tthis.client = undefined;\n\t\tthis.transport = undefined;\n\t}\n}\n"]}
|