agent-browser-priv 0.27.3-priv.3
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 +201 -0
- package/README.md +1564 -0
- package/bin/agent-browser.js +125 -0
- package/package.json +52 -0
- package/scripts/build-all-platforms.sh +76 -0
- package/scripts/check-version-sync.js +51 -0
- package/scripts/copy-native.js +36 -0
- package/scripts/postinstall.js +327 -0
- package/scripts/sync-version.js +81 -0
- package/scripts/windows-debug/provision.sh +220 -0
- package/scripts/windows-debug/run.sh +92 -0
- package/scripts/windows-debug/start.sh +43 -0
- package/scripts/windows-debug/stop.sh +28 -0
- package/scripts/windows-debug/sync.sh +27 -0
- package/skill-data/agentcore/SKILL.md +115 -0
- package/skill-data/core/SKILL.md +488 -0
- package/skill-data/core/references/authentication.md +303 -0
- package/skill-data/core/references/commands.md +403 -0
- package/skill-data/core/references/profiling.md +120 -0
- package/skill-data/core/references/proxy-support.md +194 -0
- package/skill-data/core/references/session-management.md +193 -0
- package/skill-data/core/references/snapshot-refs.md +219 -0
- package/skill-data/core/references/trust-boundaries.md +89 -0
- package/skill-data/core/references/video-recording.md +175 -0
- package/skill-data/core/templates/authenticated-session.sh +105 -0
- package/skill-data/core/templates/capture-workflow.sh +69 -0
- package/skill-data/core/templates/form-automation.sh +62 -0
- package/skill-data/dogfood/SKILL.md +220 -0
- package/skill-data/dogfood/references/issue-taxonomy.md +109 -0
- package/skill-data/dogfood/templates/dogfood-report-template.md +53 -0
- package/skill-data/electron/SKILL.md +236 -0
- package/skill-data/slack/SKILL.md +285 -0
- package/skill-data/slack/references/slack-tasks.md +348 -0
- package/skill-data/slack/templates/slack-report-template.md +163 -0
- package/skill-data/vercel-sandbox/SKILL.md +280 -0
- package/skills/agent-browser/SKILL.md +55 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Syncs the version from package.json to all other config files.
|
|
5
|
+
* Run this script before building or releasing.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { execSync } from "child_process";
|
|
9
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
10
|
+
import { dirname, join } from "path";
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const rootDir = join(__dirname, "..");
|
|
15
|
+
const cliDir = join(rootDir, "cli");
|
|
16
|
+
|
|
17
|
+
// Read version from package.json (single source of truth)
|
|
18
|
+
const packageJson = JSON.parse(
|
|
19
|
+
readFileSync(join(rootDir, "package.json"), "utf-8")
|
|
20
|
+
);
|
|
21
|
+
const version = packageJson.version;
|
|
22
|
+
|
|
23
|
+
console.log(`Syncing version ${version} to all config files...`);
|
|
24
|
+
|
|
25
|
+
// Update Cargo.toml
|
|
26
|
+
const cargoTomlPath = join(cliDir, "Cargo.toml");
|
|
27
|
+
let cargoToml = readFileSync(cargoTomlPath, "utf-8");
|
|
28
|
+
const cargoVersionRegex = /^version\s*=\s*"[^"]*"/m;
|
|
29
|
+
const newCargoVersion = `version = "${version}"`;
|
|
30
|
+
|
|
31
|
+
let cargoTomlUpdated = false;
|
|
32
|
+
if (cargoVersionRegex.test(cargoToml)) {
|
|
33
|
+
const oldMatch = cargoToml.match(cargoVersionRegex)?.[0];
|
|
34
|
+
if (oldMatch !== newCargoVersion) {
|
|
35
|
+
cargoToml = cargoToml.replace(cargoVersionRegex, newCargoVersion);
|
|
36
|
+
writeFileSync(cargoTomlPath, cargoToml);
|
|
37
|
+
console.log(` Updated cli/Cargo.toml: ${oldMatch} -> ${newCargoVersion}`);
|
|
38
|
+
cargoTomlUpdated = true;
|
|
39
|
+
} else {
|
|
40
|
+
console.log(` cli/Cargo.toml already up to date`);
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
console.error(" Could not find version field in cli/Cargo.toml");
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Update packages/dashboard/package.json
|
|
48
|
+
const dashboardPkgPath = join(rootDir, "packages", "dashboard", "package.json");
|
|
49
|
+
const dashboardPkg = JSON.parse(readFileSync(dashboardPkgPath, "utf-8"));
|
|
50
|
+
if (dashboardPkg.version !== version) {
|
|
51
|
+
const oldVersion = dashboardPkg.version;
|
|
52
|
+
dashboardPkg.version = version;
|
|
53
|
+
writeFileSync(dashboardPkgPath, JSON.stringify(dashboardPkg, null, 2) + "\n");
|
|
54
|
+
console.log(` Updated packages/dashboard/package.json: ${oldVersion} -> ${version}`);
|
|
55
|
+
} else {
|
|
56
|
+
console.log(` packages/dashboard/package.json already up to date`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Update Cargo.lock to match Cargo.toml
|
|
60
|
+
if (cargoTomlUpdated) {
|
|
61
|
+
try {
|
|
62
|
+
execSync("cargo update -p agent-browser --offline", {
|
|
63
|
+
cwd: cliDir,
|
|
64
|
+
stdio: "pipe",
|
|
65
|
+
});
|
|
66
|
+
console.log(` Updated cli/Cargo.lock`);
|
|
67
|
+
} catch {
|
|
68
|
+
// --offline may fail if package not in cache, try without it
|
|
69
|
+
try {
|
|
70
|
+
execSync("cargo update -p agent-browser", {
|
|
71
|
+
cwd: cliDir,
|
|
72
|
+
stdio: "pipe",
|
|
73
|
+
});
|
|
74
|
+
console.log(` Updated cli/Cargo.lock`);
|
|
75
|
+
} catch (e) {
|
|
76
|
+
console.error(` Warning: Could not update Cargo.lock: ${e.message}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
console.log("Version sync complete.");
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
+
INSTANCE_FILE="$SCRIPT_DIR/.instance"
|
|
6
|
+
NAME_PREFIX="agent-browser-debug"
|
|
7
|
+
INSTANCE_TYPE="${INSTANCE_TYPE:-t3.xlarge}"
|
|
8
|
+
|
|
9
|
+
if [[ -f "$INSTANCE_FILE" ]]; then
|
|
10
|
+
echo "Error: Instance already provisioned. See $INSTANCE_FILE"
|
|
11
|
+
echo "Run ./scripts/windows-debug/start.sh to start it, or delete .instance to re-provision."
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
REGION=$(aws configure get region 2>/dev/null || echo "")
|
|
16
|
+
if [[ -z "$REGION" ]]; then
|
|
17
|
+
echo "Error: No AWS region configured. Run: aws configure set region us-east-1"
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
echo "Provisioning Windows debug instance in $REGION..."
|
|
22
|
+
|
|
23
|
+
# --- IAM Role for SSM ---
|
|
24
|
+
ROLE_NAME="${IAM_ROLE_NAME:-$NAME_PREFIX-ssm-role}"
|
|
25
|
+
PROFILE_NAME="${INSTANCE_PROFILE_NAME:-$NAME_PREFIX-instance-profile}"
|
|
26
|
+
|
|
27
|
+
if aws iam get-instance-profile --instance-profile-name "$PROFILE_NAME" &>/dev/null; then
|
|
28
|
+
echo "Instance profile $PROFILE_NAME already exists, reusing."
|
|
29
|
+
else
|
|
30
|
+
echo "Instance profile $PROFILE_NAME not found. Creating IAM resources..."
|
|
31
|
+
|
|
32
|
+
if ! aws iam get-role --role-name "$ROLE_NAME" &>/dev/null; then
|
|
33
|
+
echo "Creating IAM role: $ROLE_NAME"
|
|
34
|
+
if ! aws iam create-role \
|
|
35
|
+
--role-name "$ROLE_NAME" \
|
|
36
|
+
--assume-role-policy-document '{
|
|
37
|
+
"Version": "2012-10-17",
|
|
38
|
+
"Statement": [{
|
|
39
|
+
"Effect": "Allow",
|
|
40
|
+
"Principal": {"Service": "ec2.amazonaws.com"},
|
|
41
|
+
"Action": "sts:AssumeRole"
|
|
42
|
+
}]
|
|
43
|
+
}' \
|
|
44
|
+
--no-cli-pager; then
|
|
45
|
+
|
|
46
|
+
echo ""
|
|
47
|
+
echo "Error: Failed to create IAM role (see error above)."
|
|
48
|
+
echo ""
|
|
49
|
+
echo "Ask an IAM admin to create the following, then re-run with:"
|
|
50
|
+
echo " INSTANCE_PROFILE_NAME=<name> ./scripts/windows-debug/provision.sh"
|
|
51
|
+
echo ""
|
|
52
|
+
echo "What the admin needs to create:"
|
|
53
|
+
echo " 1. IAM Role: $ROLE_NAME"
|
|
54
|
+
echo " - Trusted entity: EC2 (ec2.amazonaws.com)"
|
|
55
|
+
echo " - Attached policy: AmazonSSMManagedInstanceCore"
|
|
56
|
+
echo " 2. Instance Profile: $PROFILE_NAME"
|
|
57
|
+
echo " - With the above role added to it"
|
|
58
|
+
echo ""
|
|
59
|
+
echo "Or run these commands with an account that has iam:CreateRole permission:"
|
|
60
|
+
echo ""
|
|
61
|
+
echo " aws iam create-role --role-name $ROLE_NAME \\"
|
|
62
|
+
echo " --assume-role-policy-document '{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ec2.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}'"
|
|
63
|
+
echo ""
|
|
64
|
+
echo " aws iam attach-role-policy --role-name $ROLE_NAME \\"
|
|
65
|
+
echo " --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
|
|
66
|
+
echo ""
|
|
67
|
+
echo " aws iam create-instance-profile --instance-profile-name $PROFILE_NAME"
|
|
68
|
+
echo ""
|
|
69
|
+
echo " aws iam add-role-to-instance-profile \\"
|
|
70
|
+
echo " --instance-profile-name $PROFILE_NAME --role-name $ROLE_NAME"
|
|
71
|
+
exit 1
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
aws iam attach-role-policy \
|
|
75
|
+
--role-name "$ROLE_NAME" \
|
|
76
|
+
--policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
|
|
77
|
+
else
|
|
78
|
+
echo "IAM role $ROLE_NAME already exists."
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
echo "Creating instance profile: $PROFILE_NAME"
|
|
82
|
+
aws iam create-instance-profile --instance-profile-name "$PROFILE_NAME" --no-cli-pager
|
|
83
|
+
aws iam add-role-to-instance-profile \
|
|
84
|
+
--instance-profile-name "$PROFILE_NAME" \
|
|
85
|
+
--role-name "$ROLE_NAME"
|
|
86
|
+
echo "Waiting for instance profile propagation..."
|
|
87
|
+
sleep 10
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# --- Security Group (no inbound rules) ---
|
|
91
|
+
VPC_ID=$(aws ec2 describe-vpcs --filters "Name=isDefault,Values=true" --query "Vpcs[0].VpcId" --output text)
|
|
92
|
+
if [[ "$VPC_ID" == "None" || -z "$VPC_ID" ]]; then
|
|
93
|
+
echo "Error: No default VPC found. Create one with: aws ec2 create-default-vpc"
|
|
94
|
+
exit 1
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
SG_NAME="$NAME_PREFIX-sg"
|
|
98
|
+
SG_ID=$(aws ec2 describe-security-groups \
|
|
99
|
+
--filters "Name=group-name,Values=$SG_NAME" "Name=vpc-id,Values=$VPC_ID" \
|
|
100
|
+
--query "SecurityGroups[0].GroupId" --output text 2>/dev/null || echo "None")
|
|
101
|
+
|
|
102
|
+
if [[ "$SG_ID" == "None" || -z "$SG_ID" ]]; then
|
|
103
|
+
echo "Creating security group: $SG_NAME"
|
|
104
|
+
SG_ID=$(aws ec2 create-security-group \
|
|
105
|
+
--group-name "$SG_NAME" \
|
|
106
|
+
--description "agent-browser Windows debug instance (SSM only, no inbound)" \
|
|
107
|
+
--vpc-id "$VPC_ID" \
|
|
108
|
+
--query "GroupId" --output text)
|
|
109
|
+
|
|
110
|
+
# Revoke default egress isn't needed; SSM requires outbound HTTPS.
|
|
111
|
+
# No inbound rules -- SSM uses outbound connections only.
|
|
112
|
+
else
|
|
113
|
+
echo "Security group $SG_NAME ($SG_ID) already exists, reusing."
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
# --- AMI (latest Windows Server 2022) ---
|
|
117
|
+
AMI_ID=$(aws ssm get-parameter \
|
|
118
|
+
--name "/aws/service/ami-windows-latest/Windows_Server-2022-English-Full-Base" \
|
|
119
|
+
--query "Parameter.Value" --output text)
|
|
120
|
+
echo "Using AMI: $AMI_ID (Windows Server 2022)"
|
|
121
|
+
|
|
122
|
+
# --- UserData bootstrap script ---
|
|
123
|
+
USERDATA_FILE=$(mktemp)
|
|
124
|
+
trap "rm -f $USERDATA_FILE" EXIT
|
|
125
|
+
|
|
126
|
+
cat > "$USERDATA_FILE" <<'PWSH'
|
|
127
|
+
<powershell>
|
|
128
|
+
$ErrorActionPreference = "Continue"
|
|
129
|
+
$logFile = "C:\bootstrap.log"
|
|
130
|
+
|
|
131
|
+
function Log($msg) {
|
|
132
|
+
$ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
133
|
+
"$ts $msg" | Tee-Object -FilePath $logFile -Append
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
Log "--- Bootstrap starting ---"
|
|
137
|
+
|
|
138
|
+
# Install Git
|
|
139
|
+
Log "Installing Git..."
|
|
140
|
+
$gitInstaller = "$env:TEMP\git-installer.exe"
|
|
141
|
+
Invoke-WebRequest -Uri "https://github.com/git-for-windows/git/releases/download/v2.47.1.windows.2/Git-2.47.1.2-64-bit.exe" -OutFile $gitInstaller
|
|
142
|
+
Start-Process -FilePath $gitInstaller -ArgumentList "/VERYSILENT /NORESTART /NOCANCEL /SP- /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /COMPONENTS=`"icons,ext\reg\shellhere,assoc,assoc_sh`"" -Wait
|
|
143
|
+
$env:PATH = "C:\Program Files\Git\cmd;$env:PATH"
|
|
144
|
+
[Environment]::SetEnvironmentVariable("PATH", "C:\Program Files\Git\cmd;$([Environment]::GetEnvironmentVariable('PATH', 'Machine'))", "Machine")
|
|
145
|
+
Log "Git installed: $(git --version)"
|
|
146
|
+
|
|
147
|
+
# Install Rust
|
|
148
|
+
Log "Installing Rust..."
|
|
149
|
+
$rustupInit = "$env:TEMP\rustup-init.exe"
|
|
150
|
+
Invoke-WebRequest -Uri "https://win.rustup.rs/x86_64" -OutFile $rustupInit
|
|
151
|
+
Start-Process -FilePath $rustupInit -ArgumentList "-y --default-toolchain stable" -Wait
|
|
152
|
+
$env:PATH = "$env:USERPROFILE\.cargo\bin;$env:PATH"
|
|
153
|
+
[Environment]::SetEnvironmentVariable("PATH", "$env:USERPROFILE\.cargo\bin;$([Environment]::GetEnvironmentVariable('PATH', 'Machine'))", "Machine")
|
|
154
|
+
Log "Rust installed: $(rustc --version)"
|
|
155
|
+
|
|
156
|
+
# Install MSVC build tools (required for Rust on Windows)
|
|
157
|
+
Log "Installing Visual Studio Build Tools..."
|
|
158
|
+
$vsInstaller = "$env:TEMP\vs_buildtools.exe"
|
|
159
|
+
Invoke-WebRequest -Uri "https://aka.ms/vs/17/release/vs_buildtools.exe" -OutFile $vsInstaller
|
|
160
|
+
Start-Process -FilePath $vsInstaller -ArgumentList "--quiet --wait --norestart --nocache --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended" -Wait
|
|
161
|
+
Log "Build tools installed."
|
|
162
|
+
|
|
163
|
+
# Clone repo
|
|
164
|
+
Log "Cloning agent-browser..."
|
|
165
|
+
git clone https://github.com/vercel-labs/agent-browser.git C:\agent-browser
|
|
166
|
+
Set-Location C:\agent-browser
|
|
167
|
+
Log "Repo cloned."
|
|
168
|
+
|
|
169
|
+
# Build CLI
|
|
170
|
+
Log "Building agent-browser CLI..."
|
|
171
|
+
cargo build --release --manifest-path cli\Cargo.toml
|
|
172
|
+
Log "Build complete."
|
|
173
|
+
|
|
174
|
+
# Install Chrome
|
|
175
|
+
Log "Installing Chrome via agent-browser..."
|
|
176
|
+
.\cli\target\release\agent-browser.exe install
|
|
177
|
+
Log "Chrome installed."
|
|
178
|
+
|
|
179
|
+
Log "--- Bootstrap complete ---"
|
|
180
|
+
</powershell>
|
|
181
|
+
PWSH
|
|
182
|
+
|
|
183
|
+
# --- Launch instance ---
|
|
184
|
+
echo "Launching $INSTANCE_TYPE instance..."
|
|
185
|
+
INSTANCE_ID=$(aws ec2 run-instances \
|
|
186
|
+
--image-id "$AMI_ID" \
|
|
187
|
+
--instance-type "$INSTANCE_TYPE" \
|
|
188
|
+
--iam-instance-profile "Name=$PROFILE_NAME" \
|
|
189
|
+
--security-group-ids "$SG_ID" \
|
|
190
|
+
--user-data "file://$USERDATA_FILE" \
|
|
191
|
+
--block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":80,"VolumeType":"gp3"}}]' \
|
|
192
|
+
--tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=$NAME_PREFIX}]" \
|
|
193
|
+
--metadata-options "HttpTokens=required" \
|
|
194
|
+
--query "Instances[0].InstanceId" --output text)
|
|
195
|
+
|
|
196
|
+
echo "Instance launched: $INSTANCE_ID"
|
|
197
|
+
|
|
198
|
+
# Save instance config
|
|
199
|
+
cat > "$INSTANCE_FILE" <<EOF
|
|
200
|
+
INSTANCE_ID=$INSTANCE_ID
|
|
201
|
+
REGION=$REGION
|
|
202
|
+
EOF
|
|
203
|
+
|
|
204
|
+
echo "Waiting for instance to enter running state..."
|
|
205
|
+
aws ec2 wait instance-running --instance-ids "$INSTANCE_ID"
|
|
206
|
+
echo "Instance is running."
|
|
207
|
+
|
|
208
|
+
echo ""
|
|
209
|
+
echo "Instance $INSTANCE_ID is booting and bootstrapping (Rust, Git, Chrome)."
|
|
210
|
+
echo "Bootstrap takes ~15-20 minutes on first boot."
|
|
211
|
+
echo ""
|
|
212
|
+
echo "Check bootstrap progress:"
|
|
213
|
+
echo " ./scripts/windows-debug/run.sh \"Get-Content C:\\bootstrap.log\""
|
|
214
|
+
echo ""
|
|
215
|
+
echo "Once ready, sync your branch and start debugging:"
|
|
216
|
+
echo " ./scripts/windows-debug/sync.sh"
|
|
217
|
+
echo " ./scripts/windows-debug/run.sh \"cd C:\\agent-browser && cargo test\""
|
|
218
|
+
echo ""
|
|
219
|
+
echo "Stop when done to save costs:"
|
|
220
|
+
echo " ./scripts/windows-debug/stop.sh"
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
+
INSTANCE_FILE="$SCRIPT_DIR/.instance"
|
|
6
|
+
|
|
7
|
+
if [[ ! -f "$INSTANCE_FILE" ]]; then
|
|
8
|
+
echo "Error: No instance provisioned. Run ./scripts/windows-debug/provision.sh first."
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
if [[ $# -eq 0 ]]; then
|
|
13
|
+
echo "Usage: ./scripts/windows-debug/run.sh \"<powershell-command>\""
|
|
14
|
+
echo ""
|
|
15
|
+
echo "Examples:"
|
|
16
|
+
echo " ./scripts/windows-debug/run.sh \"cd C:\\agent-browser && cargo test\""
|
|
17
|
+
echo " ./scripts/windows-debug/run.sh \"Get-Content C:\\bootstrap.log\""
|
|
18
|
+
echo " ./scripts/windows-debug/run.sh \"cd C:\\agent-browser && cargo test e2e -- --ignored --test-threads=1\""
|
|
19
|
+
exit 1
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
source "$INSTANCE_FILE"
|
|
23
|
+
export AWS_DEFAULT_REGION="$REGION"
|
|
24
|
+
|
|
25
|
+
COMMAND="$*"
|
|
26
|
+
|
|
27
|
+
PARAMS_FILE=$(mktemp)
|
|
28
|
+
trap "rm -f $PARAMS_FILE" EXIT
|
|
29
|
+
|
|
30
|
+
python3 -c '
|
|
31
|
+
import json, sys
|
|
32
|
+
path_setup = "$env:PATH = \"$env:USERPROFILE\\.cargo\\bin;C:\\Program Files\\Git\\cmd;$env:PATH\""
|
|
33
|
+
cmd = path_setup + "\n" + sys.argv[1]
|
|
34
|
+
json.dump({"commands": [cmd]}, open(sys.argv[2], "w"))
|
|
35
|
+
' "$COMMAND" "$PARAMS_FILE"
|
|
36
|
+
|
|
37
|
+
COMMAND_ID=$(aws ssm send-command \
|
|
38
|
+
--instance-ids "$INSTANCE_ID" \
|
|
39
|
+
--document-name "AWS-RunPowerShellScript" \
|
|
40
|
+
--parameters "file://$PARAMS_FILE" \
|
|
41
|
+
--timeout-seconds 3600 \
|
|
42
|
+
--query "Command.CommandId" --output text)
|
|
43
|
+
|
|
44
|
+
echo "Command sent (ID: $COMMAND_ID). Waiting..." >&2
|
|
45
|
+
|
|
46
|
+
while true; do
|
|
47
|
+
RESULT=$(aws ssm get-command-invocation \
|
|
48
|
+
--command-id "$COMMAND_ID" \
|
|
49
|
+
--instance-id "$INSTANCE_ID" \
|
|
50
|
+
--output json 2>&1) || true
|
|
51
|
+
|
|
52
|
+
STATUS=$(echo "$RESULT" | python3 -c "
|
|
53
|
+
import sys, json
|
|
54
|
+
try:
|
|
55
|
+
print(json.loads(sys.stdin.read()).get('Status', 'Unknown'))
|
|
56
|
+
except:
|
|
57
|
+
print('Pending')
|
|
58
|
+
" 2>/dev/null)
|
|
59
|
+
|
|
60
|
+
case "$STATUS" in
|
|
61
|
+
Success)
|
|
62
|
+
echo "$RESULT" | python3 -c "
|
|
63
|
+
import sys, json
|
|
64
|
+
r = json.loads(sys.stdin.read())
|
|
65
|
+
out = r.get('StandardOutputContent', '').rstrip()
|
|
66
|
+
err = r.get('StandardErrorContent', '').rstrip()
|
|
67
|
+
if out:
|
|
68
|
+
print(out)
|
|
69
|
+
if err:
|
|
70
|
+
print(err, file=sys.stderr)
|
|
71
|
+
"
|
|
72
|
+
exit 0
|
|
73
|
+
;;
|
|
74
|
+
Failed|TimedOut|Cancelled)
|
|
75
|
+
echo "$RESULT" | python3 -c "
|
|
76
|
+
import sys, json
|
|
77
|
+
r = json.loads(sys.stdin.read())
|
|
78
|
+
out = r.get('StandardOutputContent', '').rstrip()
|
|
79
|
+
err = r.get('StandardErrorContent', '').rstrip()
|
|
80
|
+
if out:
|
|
81
|
+
print(out)
|
|
82
|
+
if err:
|
|
83
|
+
print(err, file=sys.stderr)
|
|
84
|
+
"
|
|
85
|
+
echo "Command $STATUS." >&2
|
|
86
|
+
exit 1
|
|
87
|
+
;;
|
|
88
|
+
*)
|
|
89
|
+
sleep 3
|
|
90
|
+
;;
|
|
91
|
+
esac
|
|
92
|
+
done
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
+
INSTANCE_FILE="$SCRIPT_DIR/.instance"
|
|
6
|
+
|
|
7
|
+
if [[ ! -f "$INSTANCE_FILE" ]]; then
|
|
8
|
+
echo "Error: No instance provisioned. Run ./scripts/windows-debug/provision.sh first."
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
source "$INSTANCE_FILE"
|
|
13
|
+
export AWS_DEFAULT_REGION="$REGION"
|
|
14
|
+
|
|
15
|
+
STATE=$(aws ec2 describe-instances \
|
|
16
|
+
--instance-ids "$INSTANCE_ID" \
|
|
17
|
+
--query "Reservations[0].Instances[0].State.Name" --output text)
|
|
18
|
+
|
|
19
|
+
if [[ "$STATE" == "running" ]]; then
|
|
20
|
+
echo "Instance $INSTANCE_ID is already running."
|
|
21
|
+
else
|
|
22
|
+
echo "Starting instance $INSTANCE_ID..."
|
|
23
|
+
aws ec2 start-instances --instance-ids "$INSTANCE_ID" --no-cli-pager
|
|
24
|
+
echo "Waiting for running state..."
|
|
25
|
+
aws ec2 wait instance-running --instance-ids "$INSTANCE_ID"
|
|
26
|
+
echo "Instance is running."
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
echo "Waiting for SSM agent connectivity..."
|
|
30
|
+
for i in $(seq 1 30); do
|
|
31
|
+
SSM_STATUS=$(aws ssm describe-instance-information \
|
|
32
|
+
--filters "Key=InstanceIds,Values=$INSTANCE_ID" \
|
|
33
|
+
--query "InstanceInformationList[0].PingStatus" --output text 2>/dev/null || echo "None")
|
|
34
|
+
if [[ "$SSM_STATUS" == "Online" ]]; then
|
|
35
|
+
echo "SSM agent is online. Ready for commands."
|
|
36
|
+
echo " ./scripts/windows-debug/run.sh \"your-command-here\""
|
|
37
|
+
exit 0
|
|
38
|
+
fi
|
|
39
|
+
sleep 10
|
|
40
|
+
done
|
|
41
|
+
|
|
42
|
+
echo "Warning: SSM agent not online after 5 minutes. The instance may still be booting."
|
|
43
|
+
echo "Try again in a minute: ./scripts/windows-debug/run.sh \"hostname\""
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
+
INSTANCE_FILE="$SCRIPT_DIR/.instance"
|
|
6
|
+
|
|
7
|
+
if [[ ! -f "$INSTANCE_FILE" ]]; then
|
|
8
|
+
echo "Error: No instance provisioned. Nothing to stop."
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
source "$INSTANCE_FILE"
|
|
13
|
+
export AWS_DEFAULT_REGION="$REGION"
|
|
14
|
+
|
|
15
|
+
STATE=$(aws ec2 describe-instances \
|
|
16
|
+
--instance-ids "$INSTANCE_ID" \
|
|
17
|
+
--query "Reservations[0].Instances[0].State.Name" --output text)
|
|
18
|
+
|
|
19
|
+
if [[ "$STATE" == "stopped" ]]; then
|
|
20
|
+
echo "Instance $INSTANCE_ID is already stopped."
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
echo "Stopping instance $INSTANCE_ID..."
|
|
25
|
+
aws ec2 stop-instances --instance-ids "$INSTANCE_ID" --no-cli-pager
|
|
26
|
+
echo "Waiting for stopped state..."
|
|
27
|
+
aws ec2 wait instance-stopped --instance-ids "$INSTANCE_ID"
|
|
28
|
+
echo "Instance stopped. No compute charges while stopped (storage only: ~$0.64/mo)."
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
+
RUN="$SCRIPT_DIR/run.sh"
|
|
6
|
+
|
|
7
|
+
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
|
|
8
|
+
REMOTE_URL=$(git remote get-url origin 2>/dev/null || echo "https://github.com/vercel-labs/agent-browser.git")
|
|
9
|
+
|
|
10
|
+
echo "Syncing branch '$BRANCH' on Windows instance..."
|
|
11
|
+
|
|
12
|
+
"$RUN" "
|
|
13
|
+
cd C:\agent-browser
|
|
14
|
+
git remote set-url origin '$REMOTE_URL'
|
|
15
|
+
git fetch origin
|
|
16
|
+
git checkout -B '$BRANCH' 'origin/$BRANCH'
|
|
17
|
+
git log -1 --oneline
|
|
18
|
+
"
|
|
19
|
+
|
|
20
|
+
echo ""
|
|
21
|
+
echo "Branch synced. Rebuilding..."
|
|
22
|
+
|
|
23
|
+
"$RUN" "
|
|
24
|
+
cd C:\agent-browser
|
|
25
|
+
cargo build --release --manifest-path cli\Cargo.toml
|
|
26
|
+
Write-Host 'Build complete.'
|
|
27
|
+
"
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agentcore
|
|
3
|
+
description: Run agent-browser on AWS Bedrock AgentCore cloud browsers. Use when the user wants to use AgentCore, run browser automation on AWS, use a cloud browser with AWS credentials, or needs a managed browser session backed by AWS infrastructure. Triggers include "use agentcore", "run on AWS", "cloud browser with AWS", "bedrock browser", "agentcore session", or any task requiring AWS-hosted browser automation.
|
|
4
|
+
allowed-tools: Bash(agent-browser:*), Bash(npx agent-browser:*)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# AWS Bedrock AgentCore
|
|
8
|
+
|
|
9
|
+
Run agent-browser on cloud browser sessions hosted by AWS Bedrock AgentCore. All standard agent-browser commands work identically; the only difference is where the browser runs.
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Credentials are resolved automatically:
|
|
14
|
+
|
|
15
|
+
1. Environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, optionally `AWS_SESSION_TOKEN`)
|
|
16
|
+
2. AWS CLI fallback (`aws configure export-credentials`), which supports SSO, IAM roles, and named profiles
|
|
17
|
+
|
|
18
|
+
No additional setup is needed if the user already has working AWS credentials.
|
|
19
|
+
|
|
20
|
+
## Core Workflow
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Open a page on an AgentCore cloud browser
|
|
24
|
+
agent-browser -p agentcore open https://example.com
|
|
25
|
+
|
|
26
|
+
# Everything else is the same as local Chrome
|
|
27
|
+
agent-browser snapshot -i
|
|
28
|
+
agent-browser click @e1
|
|
29
|
+
agent-browser screenshot page.png
|
|
30
|
+
agent-browser close
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Environment Variables
|
|
34
|
+
|
|
35
|
+
| Variable | Description | Default |
|
|
36
|
+
|----------|-------------|---------|
|
|
37
|
+
| `AGENTCORE_REGION` | AWS region | `us-east-1` |
|
|
38
|
+
| `AGENTCORE_BROWSER_ID` | Browser identifier | `aws.browser.v1` |
|
|
39
|
+
| `AGENTCORE_PROFILE_ID` | Persistent browser profile (cookies, localStorage) | (none) |
|
|
40
|
+
| `AGENTCORE_SESSION_TIMEOUT` | Session timeout in seconds | `3600` |
|
|
41
|
+
| `AWS_PROFILE` | AWS CLI profile for credential resolution | `default` |
|
|
42
|
+
|
|
43
|
+
## Persistent Profiles
|
|
44
|
+
|
|
45
|
+
Use `AGENTCORE_PROFILE_ID` to persist browser state across sessions. This is useful for maintaining login sessions:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# First run: log in
|
|
49
|
+
AGENTCORE_PROFILE_ID=my-app agent-browser -p agentcore open https://app.example.com/login
|
|
50
|
+
agent-browser snapshot -i
|
|
51
|
+
agent-browser fill @e1 "user@example.com"
|
|
52
|
+
agent-browser fill @e2 "password"
|
|
53
|
+
agent-browser click @e3
|
|
54
|
+
agent-browser close
|
|
55
|
+
|
|
56
|
+
# Future runs: already authenticated
|
|
57
|
+
AGENTCORE_PROFILE_ID=my-app agent-browser -p agentcore open https://app.example.com/dashboard
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Live View
|
|
61
|
+
|
|
62
|
+
When a session starts, AgentCore prints a Live View URL to stderr. Open it in a browser to watch the session in real time from the AWS Console:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
Session: abc123-def456
|
|
66
|
+
Live View: https://us-east-1.console.aws.amazon.com/bedrock-agentcore/browser/aws.browser.v1/session/abc123-def456#
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Region Selection
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Default: us-east-1
|
|
73
|
+
agent-browser -p agentcore open https://example.com
|
|
74
|
+
|
|
75
|
+
# Explicit region
|
|
76
|
+
AGENTCORE_REGION=eu-west-1 agent-browser -p agentcore open https://example.com
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Credential Patterns
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Explicit credentials (CI/CD, scripts)
|
|
83
|
+
export AWS_ACCESS_KEY_ID=AKIA...
|
|
84
|
+
export AWS_SECRET_ACCESS_KEY=...
|
|
85
|
+
agent-browser -p agentcore open https://example.com
|
|
86
|
+
|
|
87
|
+
# SSO (interactive)
|
|
88
|
+
aws sso login --profile my-profile
|
|
89
|
+
AWS_PROFILE=my-profile agent-browser -p agentcore open https://example.com
|
|
90
|
+
|
|
91
|
+
# IAM role / default credential chain
|
|
92
|
+
agent-browser -p agentcore open https://example.com
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Using with AGENT_BROWSER_PROVIDER
|
|
96
|
+
|
|
97
|
+
Set the provider via environment variable to avoid passing `-p agentcore` on every command:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
export AGENT_BROWSER_PROVIDER=agentcore
|
|
101
|
+
export AGENTCORE_REGION=us-east-2
|
|
102
|
+
|
|
103
|
+
agent-browser open https://example.com
|
|
104
|
+
agent-browser snapshot -i
|
|
105
|
+
agent-browser click @e1
|
|
106
|
+
agent-browser close
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Common Issues
|
|
110
|
+
|
|
111
|
+
**"Failed to run aws CLI"** means AWS CLI is not installed or not in PATH. Either install it or set `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` directly.
|
|
112
|
+
|
|
113
|
+
**"AWS CLI failed: ... Run 'aws sso login'"** means SSO credentials have expired. Run `aws sso login` to refresh them.
|
|
114
|
+
|
|
115
|
+
**Session timeout:** The default is 3600 seconds (1 hour). For longer tasks, increase with `AGENTCORE_SESSION_TIMEOUT=7200`.
|