@flrande/browserctl 0.1.0-dev.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README-CN.md +66 -0
- package/README.md +66 -0
- package/apps/browserctl/src/commands/a11y-snapshot.ts +20 -0
- package/apps/browserctl/src/commands/act.ts +20 -0
- package/apps/browserctl/src/commands/common.test.ts +87 -0
- package/apps/browserctl/src/commands/common.ts +191 -0
- package/apps/browserctl/src/commands/console-list.ts +20 -0
- package/apps/browserctl/src/commands/cookie-clear.ts +18 -0
- package/apps/browserctl/src/commands/cookie-get.ts +18 -0
- package/apps/browserctl/src/commands/cookie-set.ts +22 -0
- package/apps/browserctl/src/commands/dialog-arm.ts +20 -0
- package/apps/browserctl/src/commands/dom-query-all.ts +18 -0
- package/apps/browserctl/src/commands/dom-query.ts +18 -0
- package/apps/browserctl/src/commands/download-trigger.ts +22 -0
- package/apps/browserctl/src/commands/download-wait.test.ts +67 -0
- package/apps/browserctl/src/commands/download-wait.ts +27 -0
- package/apps/browserctl/src/commands/element-screenshot.ts +20 -0
- package/apps/browserctl/src/commands/frame-list.ts +16 -0
- package/apps/browserctl/src/commands/frame-snapshot.ts +18 -0
- package/apps/browserctl/src/commands/network-wait-for.ts +100 -0
- package/apps/browserctl/src/commands/profile-list.ts +16 -0
- package/apps/browserctl/src/commands/profile-use.ts +18 -0
- package/apps/browserctl/src/commands/response-body.ts +24 -0
- package/apps/browserctl/src/commands/screenshot.ts +16 -0
- package/apps/browserctl/src/commands/snapshot.ts +16 -0
- package/apps/browserctl/src/commands/status.ts +10 -0
- package/apps/browserctl/src/commands/storage-get.ts +20 -0
- package/apps/browserctl/src/commands/storage-set.ts +22 -0
- package/apps/browserctl/src/commands/tab-close.ts +20 -0
- package/apps/browserctl/src/commands/tab-focus.ts +20 -0
- package/apps/browserctl/src/commands/tab-open.ts +19 -0
- package/apps/browserctl/src/commands/tabs.ts +13 -0
- package/apps/browserctl/src/commands/upload-arm.ts +26 -0
- package/apps/browserctl/src/daemon-client.test.ts +253 -0
- package/apps/browserctl/src/daemon-client.ts +632 -0
- package/apps/browserctl/src/e2e.test.ts +99 -0
- package/apps/browserctl/src/main.test.ts +215 -0
- package/apps/browserctl/src/main.ts +372 -0
- package/apps/browserctl/src/smoke.test.ts +16 -0
- package/apps/browserctl/src/smoke.ts +5 -0
- package/apps/browserd/src/bootstrap.ts +432 -0
- package/apps/browserd/src/chrome-relay-extension-bridge.test.ts +275 -0
- package/apps/browserd/src/chrome-relay-extension-bridge.ts +506 -0
- package/apps/browserd/src/container.ts +1531 -0
- package/apps/browserd/src/main.test.ts +864 -0
- package/apps/browserd/src/main.ts +7 -0
- package/bin/browserctl.cjs +21 -0
- package/bin/browserd.cjs +21 -0
- package/extensions/chrome-relay/README-CN.md +38 -0
- package/extensions/chrome-relay/README.md +38 -0
- package/extensions/chrome-relay/background.js +1687 -0
- package/extensions/chrome-relay/manifest.json +15 -0
- package/extensions/chrome-relay/popup.html +369 -0
- package/extensions/chrome-relay/popup.js +972 -0
- package/package.json +51 -0
- package/packages/core/src/bootstrap.test.ts +10 -0
- package/packages/core/src/driver-registry.test.ts +45 -0
- package/packages/core/src/driver-registry.ts +22 -0
- package/packages/core/src/driver.ts +47 -0
- package/packages/core/src/index.ts +5 -0
- package/packages/core/src/ref-cache.test.ts +61 -0
- package/packages/core/src/ref-cache.ts +28 -0
- package/packages/core/src/session-store.test.ts +49 -0
- package/packages/core/src/session-store.ts +33 -0
- package/packages/core/src/types.ts +9 -0
- package/packages/driver-chrome-relay/src/chrome-relay-driver.test.ts +634 -0
- package/packages/driver-chrome-relay/src/chrome-relay-driver.ts +2206 -0
- package/packages/driver-chrome-relay/src/chrome-relay-extension-runtime.test.ts +264 -0
- package/packages/driver-chrome-relay/src/chrome-relay-extension-runtime.ts +521 -0
- package/packages/driver-chrome-relay/src/index.ts +26 -0
- package/packages/driver-managed/src/index.ts +22 -0
- package/packages/driver-managed/src/managed-driver.test.ts +59 -0
- package/packages/driver-managed/src/managed-driver.ts +125 -0
- package/packages/driver-managed/src/managed-local-driver.test.ts +506 -0
- package/packages/driver-managed/src/managed-local-driver.ts +2021 -0
- package/packages/driver-remote-cdp/src/index.ts +19 -0
- package/packages/driver-remote-cdp/src/remote-cdp-driver.test.ts +617 -0
- package/packages/driver-remote-cdp/src/remote-cdp-driver.ts +2042 -0
- package/packages/protocol/src/envelope.test.ts +25 -0
- package/packages/protocol/src/envelope.ts +31 -0
- package/packages/protocol/src/errors.test.ts +17 -0
- package/packages/protocol/src/errors.ts +11 -0
- package/packages/protocol/src/index.ts +3 -0
- package/packages/protocol/src/tools.ts +3 -0
- package/packages/transport-mcp-stdio/src/index.ts +3 -0
- package/packages/transport-mcp-stdio/src/sdk-server.ts +139 -0
- package/packages/transport-mcp-stdio/src/server.test.ts +281 -0
- package/packages/transport-mcp-stdio/src/server.ts +183 -0
- package/packages/transport-mcp-stdio/src/tool-map.ts +67 -0
- package/scripts/smoke.ps1 +127 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { ErrorCode, createErr, createOk, type ToolResponse } from "../../protocol/src/index";
|
|
2
|
+
|
|
3
|
+
export type ToolCallArgs = {
|
|
4
|
+
sessionId: string;
|
|
5
|
+
profile?: string;
|
|
6
|
+
targetId?: string;
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
[key: string]: unknown;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type ToolHandler<TData = Record<string, unknown>> = (
|
|
12
|
+
args: ToolCallArgs
|
|
13
|
+
) => Promise<ToolResponse<TData>> | ToolResponse<TData>;
|
|
14
|
+
|
|
15
|
+
export type ToolMap = Map<string, ToolHandler>;
|
|
16
|
+
|
|
17
|
+
export const V1_TOOL_NAMES = [
|
|
18
|
+
"browser.status",
|
|
19
|
+
"browser.profile.list",
|
|
20
|
+
"browser.profile.use",
|
|
21
|
+
"browser.tab.list",
|
|
22
|
+
"browser.tab.open",
|
|
23
|
+
"browser.tab.focus",
|
|
24
|
+
"browser.tab.close",
|
|
25
|
+
"browser.snapshot",
|
|
26
|
+
"browser.screenshot",
|
|
27
|
+
"browser.dom.query",
|
|
28
|
+
"browser.dom.queryAll",
|
|
29
|
+
"browser.element.screenshot",
|
|
30
|
+
"browser.a11y.snapshot",
|
|
31
|
+
"browser.act",
|
|
32
|
+
"browser.upload.arm",
|
|
33
|
+
"browser.dialog.arm",
|
|
34
|
+
"browser.download.wait",
|
|
35
|
+
"browser.download.trigger",
|
|
36
|
+
"browser.network.waitFor",
|
|
37
|
+
"browser.cookie.get",
|
|
38
|
+
"browser.cookie.set",
|
|
39
|
+
"browser.cookie.clear",
|
|
40
|
+
"browser.storage.get",
|
|
41
|
+
"browser.storage.set",
|
|
42
|
+
"browser.frame.list",
|
|
43
|
+
"browser.frame.snapshot",
|
|
44
|
+
"browser.console.list",
|
|
45
|
+
"browser.network.responseBody"
|
|
46
|
+
] as const;
|
|
47
|
+
|
|
48
|
+
const browserStatusHandler: ToolHandler<{ kind: "stdio"; ready: true }> = async () =>
|
|
49
|
+
createOk({
|
|
50
|
+
kind: "stdio",
|
|
51
|
+
ready: true
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
function createNotImplementedHandler(toolName: string): ToolHandler {
|
|
55
|
+
return async () => createErr(ErrorCode.E_DRIVER_UNAVAILABLE, `Tool is not implemented: ${toolName}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function buildToolMap(): ToolMap {
|
|
59
|
+
const map: ToolMap = new Map();
|
|
60
|
+
|
|
61
|
+
for (const toolName of V1_TOOL_NAMES) {
|
|
62
|
+
map.set(toolName, createNotImplementedHandler(toolName));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
map.set("browser.status", browserStatusHandler);
|
|
66
|
+
return map;
|
|
67
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
$ErrorActionPreference = 'Stop'
|
|
2
|
+
Set-StrictMode -Version Latest
|
|
3
|
+
|
|
4
|
+
$scriptDir = Split-Path -Parent $PSCommandPath
|
|
5
|
+
$repoRoot = Resolve-Path -LiteralPath (Join-Path $scriptDir '..')
|
|
6
|
+
$browserdEntry = Join-Path $repoRoot 'apps/browserd/src/main.ts'
|
|
7
|
+
$browserctlEntry = Join-Path $repoRoot 'apps/browserctl/src/main.ts'
|
|
8
|
+
|
|
9
|
+
$daemonProcess = $null
|
|
10
|
+
$daemonPort = 41337
|
|
11
|
+
$timeoutMs = 10000
|
|
12
|
+
$pollIntervalMs = 250
|
|
13
|
+
$pnpmExecutable = if ($IsWindows) { 'pnpm.cmd' } else { 'pnpm' }
|
|
14
|
+
|
|
15
|
+
function Invoke-SmokeStatus {
|
|
16
|
+
param(
|
|
17
|
+
[Parameter(Mandatory = $true)]
|
|
18
|
+
[string]$BrowserctlEntry
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
$previousPort = $env:BROWSERCTL_DAEMON_PORT
|
|
22
|
+
$env:BROWSERCTL_DAEMON_PORT = "$daemonPort"
|
|
23
|
+
|
|
24
|
+
$statusOutput = & pnpm exec tsx $BrowserctlEntry status --json 2>&1
|
|
25
|
+
$exitCode = $LASTEXITCODE
|
|
26
|
+
$statusText = [string]::Join([Environment]::NewLine, @($statusOutput))
|
|
27
|
+
|
|
28
|
+
if ($null -eq $previousPort) {
|
|
29
|
+
Remove-Item Env:\BROWSERCTL_DAEMON_PORT -ErrorAction SilentlyContinue
|
|
30
|
+
} else {
|
|
31
|
+
$env:BROWSERCTL_DAEMON_PORT = $previousPort
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if ($exitCode -ne 0) {
|
|
35
|
+
return @{
|
|
36
|
+
Ok = $false
|
|
37
|
+
Reason = "browserctl status exited with code $exitCode. Output: $statusText"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
$statusPayload = $null
|
|
42
|
+
try {
|
|
43
|
+
$statusPayload = $statusText | ConvertFrom-Json -ErrorAction Stop
|
|
44
|
+
} catch {
|
|
45
|
+
return @{
|
|
46
|
+
Ok = $false
|
|
47
|
+
Reason = "browserctl status returned invalid JSON. Output: $statusText"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (-not $statusPayload.ok) {
|
|
52
|
+
return @{
|
|
53
|
+
Ok = $false
|
|
54
|
+
Reason = 'browserctl status returned ok=false.'
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
$errorProperty = $statusPayload.PSObject.Properties['error']
|
|
59
|
+
if ($null -ne $errorProperty -and $null -ne $errorProperty.Value) {
|
|
60
|
+
$errorJson = $errorProperty.Value | ConvertTo-Json -Compress
|
|
61
|
+
return @{
|
|
62
|
+
Ok = $false
|
|
63
|
+
Reason = "browserctl status returned error payload: $errorJson"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return @{
|
|
68
|
+
Ok = $true
|
|
69
|
+
Payload = $statusPayload
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
$previousPort = $env:BROWSERCTL_DAEMON_PORT
|
|
75
|
+
$env:BROWSERCTL_DAEMON_PORT = "$daemonPort"
|
|
76
|
+
& pnpm exec tsx $browserctlEntry daemon-stop --json *> $null
|
|
77
|
+
if ($null -eq $previousPort) {
|
|
78
|
+
Remove-Item Env:\BROWSERCTL_DAEMON_PORT -ErrorAction SilentlyContinue
|
|
79
|
+
} else {
|
|
80
|
+
$env:BROWSERCTL_DAEMON_PORT = $previousPort
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
$daemonEnv = @{
|
|
84
|
+
BROWSERD_TRANSPORT = 'tcp'
|
|
85
|
+
BROWSERD_PORT = "$daemonPort"
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
$daemonProcess = Start-Process -FilePath $pnpmExecutable `
|
|
89
|
+
-ArgumentList @('exec', 'tsx', $browserdEntry) `
|
|
90
|
+
-WorkingDirectory $repoRoot `
|
|
91
|
+
-Environment $daemonEnv `
|
|
92
|
+
-PassThru
|
|
93
|
+
|
|
94
|
+
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
|
|
95
|
+
$lastFailure = 'status probe did not run'
|
|
96
|
+
$statusResult = $null
|
|
97
|
+
|
|
98
|
+
while ($stopwatch.ElapsedMilliseconds -lt $timeoutMs) {
|
|
99
|
+
$statusResult = Invoke-SmokeStatus -BrowserctlEntry $browserctlEntry
|
|
100
|
+
if ($statusResult.Ok) {
|
|
101
|
+
break
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
$lastFailure = [string]$statusResult.Reason
|
|
105
|
+
Start-Sleep -Milliseconds $pollIntervalMs
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if ($null -eq $statusResult -or -not $statusResult.Ok) {
|
|
109
|
+
$elapsedMs = [int]$stopwatch.ElapsedMilliseconds
|
|
110
|
+
throw "Smoke failed: browserctl status --json was not ready within ${timeoutMs}ms (elapsed ${elapsedMs}ms). Last failure: $lastFailure"
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
Write-Host 'Smoke passed: daemon started and browserctl status --json returned success.'
|
|
114
|
+
} finally {
|
|
115
|
+
if ($null -ne $daemonProcess -and -not $daemonProcess.HasExited) {
|
|
116
|
+
Stop-Process -Id $daemonProcess.Id -ErrorAction SilentlyContinue
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
$previousPort = $env:BROWSERCTL_DAEMON_PORT
|
|
120
|
+
$env:BROWSERCTL_DAEMON_PORT = "$daemonPort"
|
|
121
|
+
& pnpm exec tsx $browserctlEntry daemon-stop --json *> $null
|
|
122
|
+
if ($null -eq $previousPort) {
|
|
123
|
+
Remove-Item Env:\BROWSERCTL_DAEMON_PORT -ErrorAction SilentlyContinue
|
|
124
|
+
} else {
|
|
125
|
+
$env:BROWSERCTL_DAEMON_PORT = $previousPort
|
|
126
|
+
}
|
|
127
|
+
}
|