agentmb 0.1.0
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/INSTALL.md +154 -0
- package/README.md +228 -0
- package/dist/audit/logger.d.ts +25 -0
- package/dist/audit/logger.d.ts.map +1 -0
- package/dist/audit/logger.js +56 -0
- package/dist/audit/logger.js.map +1 -0
- package/dist/browser/actions.d.ts +111 -0
- package/dist/browser/actions.d.ts.map +1 -0
- package/dist/browser/actions.js +291 -0
- package/dist/browser/actions.js.map +1 -0
- package/dist/browser/manager.d.ts +51 -0
- package/dist/browser/manager.d.ts.map +1 -0
- package/dist/browser/manager.js +233 -0
- package/dist/browser/manager.js.map +1 -0
- package/dist/cli/client.d.ts +13 -0
- package/dist/cli/client.d.ts.map +1 -0
- package/dist/cli/client.js +109 -0
- package/dist/cli/client.js.map +1 -0
- package/dist/cli/commands/actions.d.ts +3 -0
- package/dist/cli/commands/actions.d.ts.map +1 -0
- package/dist/cli/commands/actions.js +349 -0
- package/dist/cli/commands/actions.js.map +1 -0
- package/dist/cli/commands/pages.d.ts +3 -0
- package/dist/cli/commands/pages.d.ts.map +1 -0
- package/dist/cli/commands/pages.js +107 -0
- package/dist/cli/commands/pages.js.map +1 -0
- package/dist/cli/commands/route.d.ts +3 -0
- package/dist/cli/commands/route.d.ts.map +1 -0
- package/dist/cli/commands/route.js +72 -0
- package/dist/cli/commands/route.js.map +1 -0
- package/dist/cli/commands/session.d.ts +3 -0
- package/dist/cli/commands/session.d.ts.map +1 -0
- package/dist/cli/commands/session.js +57 -0
- package/dist/cli/commands/session.js.map +1 -0
- package/dist/cli/commands/start.d.ts +8 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +66 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/status.d.ts +6 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +25 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/stop.d.ts +6 -0
- package/dist/cli/commands/stop.d.ts.map +1 -0
- package/dist/cli/commands/stop.js +53 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/commands/trace.d.ts +3 -0
- package/dist/cli/commands/trace.d.ts.map +1 -0
- package/dist/cli/commands/trace.js +43 -0
- package/dist/cli/commands/trace.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +44 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/daemon/config.d.ts +25 -0
- package/dist/daemon/config.d.ts.map +1 -0
- package/dist/daemon/config.js +35 -0
- package/dist/daemon/config.js.map +1 -0
- package/dist/daemon/index.d.ts +7 -0
- package/dist/daemon/index.d.ts.map +1 -0
- package/dist/daemon/index.js +84 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/routes/actions.d.ts +5 -0
- package/dist/daemon/routes/actions.d.ts.map +1 -0
- package/dist/daemon/routes/actions.js +425 -0
- package/dist/daemon/routes/actions.js.map +1 -0
- package/dist/daemon/routes/sessions.d.ts +5 -0
- package/dist/daemon/routes/sessions.d.ts.map +1 -0
- package/dist/daemon/routes/sessions.js +507 -0
- package/dist/daemon/routes/sessions.js.map +1 -0
- package/dist/daemon/server.d.ts +6 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +66 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/session.d.ts +52 -0
- package/dist/daemon/session.d.ts.map +1 -0
- package/dist/daemon/session.js +191 -0
- package/dist/daemon/session.js.map +1 -0
- package/dist/daemon/types.d.ts +17 -0
- package/dist/daemon/types.d.ts.map +1 -0
- package/dist/daemon/types.js +3 -0
- package/dist/daemon/types.js.map +1 -0
- package/dist/policy/engine.d.ts +43 -0
- package/dist/policy/engine.d.ts.map +1 -0
- package/dist/policy/engine.js +234 -0
- package/dist/policy/engine.js.map +1 -0
- package/dist/policy/types.d.ts +40 -0
- package/dist/policy/types.d.ts.map +1 -0
- package/dist/policy/types.js +53 -0
- package/dist/policy/types.js.map +1 -0
- package/package.json +61 -0
package/INSTALL.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Installation Guide
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
| Component | Version | Install |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| Node.js | ≥ 20 LTS | [nodejs.org](https://nodejs.org) or `nvm install 20` |
|
|
8
|
+
| Python | ≥ 3.9 | [python.org](https://python.org) |
|
|
9
|
+
| Chromium | (auto) | `npx playwright install chromium` |
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## macOS
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# 1. Clone the repo
|
|
17
|
+
git clone https://github.com/what552/agent-managed-browser.git
|
|
18
|
+
cd agent-managed-browser
|
|
19
|
+
|
|
20
|
+
# 2. Install Node dependencies and build
|
|
21
|
+
npm ci
|
|
22
|
+
npm run build
|
|
23
|
+
|
|
24
|
+
# 3. Install Chromium (one-time)
|
|
25
|
+
npx playwright install chromium
|
|
26
|
+
|
|
27
|
+
# 4. (Optional) Install CLI globally
|
|
28
|
+
npm link
|
|
29
|
+
# → agentmb start / agentmb session / agentmb navigate …
|
|
30
|
+
|
|
31
|
+
# 5. Install Python SDK
|
|
32
|
+
pip install sdk/python
|
|
33
|
+
# or editable: pip install -e sdk/python
|
|
34
|
+
|
|
35
|
+
# 6. Verify
|
|
36
|
+
agentmb start &
|
|
37
|
+
sleep 2
|
|
38
|
+
curl http://localhost:19315/health
|
|
39
|
+
agentmb stop
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Linux (Ubuntu / Debian)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# 1. Install Node 20 LTS
|
|
48
|
+
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
|
49
|
+
sudo apt-get install -y nodejs
|
|
50
|
+
|
|
51
|
+
# 2. Clone and build
|
|
52
|
+
git clone https://github.com/what552/agent-managed-browser.git
|
|
53
|
+
cd agent-managed-browser
|
|
54
|
+
npm ci
|
|
55
|
+
npm run build
|
|
56
|
+
|
|
57
|
+
# 3. Install Chromium + headless dependencies
|
|
58
|
+
npx playwright install chromium
|
|
59
|
+
npx playwright install-deps chromium # installs libglib2, libnss3, etc.
|
|
60
|
+
|
|
61
|
+
# 4. (Optional) CLI global install
|
|
62
|
+
sudo npm link
|
|
63
|
+
|
|
64
|
+
# 5. Install Python SDK
|
|
65
|
+
pip3 install sdk/python
|
|
66
|
+
# or: pip3 install -e sdk/python
|
|
67
|
+
|
|
68
|
+
# 6. Verify (headless — no display needed)
|
|
69
|
+
agentmb start &
|
|
70
|
+
sleep 2
|
|
71
|
+
curl http://localhost:19315/health
|
|
72
|
+
agentmb stop
|
|
73
|
+
|
|
74
|
+
# Headed mode (visual / login handoff) requires Xvfb:
|
|
75
|
+
sudo apt-get install -y xvfb
|
|
76
|
+
bash scripts/xvfb-headed.sh
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Linux: run tests
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Full regression gate (starts/stops daemon automatically)
|
|
83
|
+
bash scripts/verify.sh
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Windows (PowerShell / WSL2)
|
|
89
|
+
|
|
90
|
+
### Option A — WSL2 (recommended)
|
|
91
|
+
|
|
92
|
+
Run the Linux instructions above inside WSL2 (Ubuntu).
|
|
93
|
+
|
|
94
|
+
### Option B — Native Windows (PowerShell)
|
|
95
|
+
|
|
96
|
+
```powershell
|
|
97
|
+
# 1. Install Node 20 LTS from https://nodejs.org
|
|
98
|
+
# Verify: node --version (must be >= 20)
|
|
99
|
+
|
|
100
|
+
# 2. Clone and build
|
|
101
|
+
git clone https://github.com/what552/agent-managed-browser.git
|
|
102
|
+
cd agent-managed-browser
|
|
103
|
+
npm ci
|
|
104
|
+
npm run build
|
|
105
|
+
|
|
106
|
+
# 3. Install Chromium
|
|
107
|
+
npx playwright install chromium
|
|
108
|
+
|
|
109
|
+
# 4. (Optional) CLI global install
|
|
110
|
+
npm link
|
|
111
|
+
|
|
112
|
+
# 5. Install Python SDK
|
|
113
|
+
pip install sdk/python
|
|
114
|
+
|
|
115
|
+
# 6. Verify
|
|
116
|
+
Start-Process node -ArgumentList "dist/daemon/index.js" -NoNewWindow
|
|
117
|
+
Start-Sleep 2
|
|
118
|
+
Invoke-RestMethod http://localhost:19315/health
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
> **Note**: Windows headed mode works natively (no Xvfb needed).
|
|
122
|
+
> Windows headless mode requires `--no-sandbox` which is already set in `src/browser/manager.ts`.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Environment variables
|
|
127
|
+
|
|
128
|
+
| Variable | Default | Description |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| `AGENTMB_PORT` | `19315` | Daemon HTTP port |
|
|
131
|
+
| `AGENTMB_DATA_DIR` | `~/.agentmb` | Profile & log storage |
|
|
132
|
+
| `AGENTMB_API_TOKEN` | (none) | Enable token auth |
|
|
133
|
+
| `AGENTMB_ENCRYPTION_KEY` | (none) | AES-256-GCM sessions.json encryption key (32 bytes as base64 or hex) |
|
|
134
|
+
| `AGENTMB_LOG_LEVEL` | `info` | Pino log level |
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Quick sanity check (all platforms)
|
|
139
|
+
|
|
140
|
+
After install:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# Build
|
|
144
|
+
npm run build # → 0 errors
|
|
145
|
+
|
|
146
|
+
# SDK import
|
|
147
|
+
python3 -c "from agentmb import BrowserClient; print('SDK OK')"
|
|
148
|
+
|
|
149
|
+
# CLI version
|
|
150
|
+
node dist/cli/index.js --help # shows usage
|
|
151
|
+
|
|
152
|
+
# Full gate (needs network for example.com)
|
|
153
|
+
bash scripts/verify.sh
|
|
154
|
+
```
|
package/README.md
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# agent-managed-browser
|
|
2
|
+
|
|
3
|
+
Agent-ready local browser runtime for stable, auditable web automation.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
`agent-managed-browser` provides a persistent Chromium daemon with session management, CLI/Python SDK access, and human login handoff support. It is designed for coding/ops agents that need reproducible browser workflows instead of fragile one-off scripts.
|
|
8
|
+
|
|
9
|
+
## Use Cases
|
|
10
|
+
|
|
11
|
+
- **Agent web tasks**: Let Codex/Claude run navigation, click/fill, extraction, screenshot, and evaluation in a controlled runtime.
|
|
12
|
+
- **Human-in-the-loop login**: Switch to headed mode for manual login, then return to headless automation with the same profile.
|
|
13
|
+
- **E2E and CI verification**: Run isolated smoke/auth/handoff/cdp checks with configurable port and data dir.
|
|
14
|
+
- **Local automation service**: Keep one daemon running and let multiple tools/agents reuse sessions safely.
|
|
15
|
+
|
|
16
|
+
Local Chromium runtime for AI agents, with:
|
|
17
|
+
|
|
18
|
+
- daemon API (`agentmb`)
|
|
19
|
+
- CLI (`agentmb`)
|
|
20
|
+
- Python SDK (`agentmb`)
|
|
21
|
+
|
|
22
|
+
This repo supports macOS, Linux, and Windows.
|
|
23
|
+
|
|
24
|
+
## Agent Skill
|
|
25
|
+
|
|
26
|
+
For Codex/Claude/AgentMB operation guidance (initialization, core commands, troubleshooting), see:
|
|
27
|
+
|
|
28
|
+
- [agentmb-operations-skill/SKILL.md](./agentmb-operations-skill/SKILL.md)
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git clone https://github.com/what552/agent-managed-browser.git
|
|
34
|
+
cd agent-managed-browser
|
|
35
|
+
|
|
36
|
+
# Node 20+ required
|
|
37
|
+
npm ci
|
|
38
|
+
npm run build
|
|
39
|
+
npx playwright install chromium
|
|
40
|
+
|
|
41
|
+
# optional: install CLI globally
|
|
42
|
+
npm link
|
|
43
|
+
|
|
44
|
+
# start daemon
|
|
45
|
+
agentmb start
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
In another terminal:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
agentmb status
|
|
52
|
+
agentmb session new --profile demo
|
|
53
|
+
agentmb session list
|
|
54
|
+
agentmb navigate <session-id> https://example.com
|
|
55
|
+
agentmb screenshot <session-id> -o ./shot.png
|
|
56
|
+
agentmb stop
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Python SDK
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install -e sdk/python
|
|
63
|
+
python3 -c "from agentmb import BrowserClient; print('SDK OK')"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Install By Platform
|
|
67
|
+
|
|
68
|
+
For full installation steps on all environments:
|
|
69
|
+
|
|
70
|
+
- macOS
|
|
71
|
+
- Linux (Ubuntu / Debian)
|
|
72
|
+
- Windows (PowerShell / WSL2)
|
|
73
|
+
|
|
74
|
+
See [INSTALL.md](./INSTALL.md).
|
|
75
|
+
|
|
76
|
+
## Action Reference
|
|
77
|
+
|
|
78
|
+
| Action | CLI command | Description |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| navigate | `agentmb navigate <sess> <url>` | Navigate to URL |
|
|
81
|
+
| screenshot | `agentmb screenshot <sess> -o out.png` | Capture screenshot |
|
|
82
|
+
| eval | `agentmb eval <sess> <expr>` | Run JavaScript expression |
|
|
83
|
+
| extract | `agentmb extract <sess> <selector>` | Extract text/attributes |
|
|
84
|
+
| click | `agentmb click <sess> <selector>` | Click element |
|
|
85
|
+
| fill | `agentmb fill <sess> <selector> <value>` | Fill form field |
|
|
86
|
+
| type | `agentmb type <sess> <selector> <text>` | Type char-by-char |
|
|
87
|
+
| press | `agentmb press <sess> <selector> <key>` | Press key / combo (e.g. `Enter`, `Control+a`) |
|
|
88
|
+
| select | `agentmb select <sess> <selector> <val>` | Select `<option>` in a `<select>` |
|
|
89
|
+
| hover | `agentmb hover <sess> <selector>` | Hover over element |
|
|
90
|
+
| wait-selector | `agentmb wait-selector <sess> <selector>` | Wait for element state |
|
|
91
|
+
| wait-url | `agentmb wait-url <sess> <pattern>` | Wait for URL pattern |
|
|
92
|
+
| upload | `agentmb upload <sess> <selector> <file>` | Upload local file to file input |
|
|
93
|
+
| download | `agentmb download <sess> <selector> -o out` | Click link and save download |
|
|
94
|
+
|
|
95
|
+
## Multi-Page Management
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
agentmb pages list <session-id> # list all open tabs
|
|
99
|
+
agentmb pages new <session-id> # open a new tab
|
|
100
|
+
agentmb pages switch <session-id> <page-id> # make a tab the active target
|
|
101
|
+
agentmb pages close <session-id> <page-id> # close a tab (last tab protected)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Network Route Mocks
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
agentmb route list <session-id> # list active mocks
|
|
108
|
+
agentmb route add <session-id> "**/api/**" \
|
|
109
|
+
--status 200 --body '{"ok":true}' \
|
|
110
|
+
--content-type application/json # intercept requests
|
|
111
|
+
agentmb route rm <session-id> "**/api/**" # remove a mock
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Playwright Trace Recording
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
agentmb trace start <session-id> # start recording
|
|
118
|
+
# ... do actions ...
|
|
119
|
+
agentmb trace stop <session-id> -o trace.zip # save ZIP
|
|
120
|
+
npx playwright show-trace trace.zip # open in Playwright UI
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## CDP WebSocket URL
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
agentmb cdp-ws <session-id> # print browser CDP WebSocket URL
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Linux Headed Mode
|
|
130
|
+
|
|
131
|
+
Linux visual/headed mode requires Xvfb.
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
sudo apt-get install -y xvfb
|
|
135
|
+
bash scripts/xvfb-headed.sh
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Verify
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
bash scripts/verify.sh
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## npm Release Setup
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# login once
|
|
148
|
+
npm login
|
|
149
|
+
npm whoami
|
|
150
|
+
|
|
151
|
+
# check package payload before publish
|
|
152
|
+
npm run pack:check
|
|
153
|
+
|
|
154
|
+
# publish from repo root
|
|
155
|
+
npm publish
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
If your global npm cache has permission issues, this repo uses project-local cache (`.npm-cache`) via `.npmrc`.
|
|
159
|
+
|
|
160
|
+
## Environment Variables
|
|
161
|
+
|
|
162
|
+
Common runtime env vars:
|
|
163
|
+
|
|
164
|
+
- `AGENTMB_PORT` (default `19315`)
|
|
165
|
+
- `AGENTMB_DATA_DIR` (default `~/.agentmb`)
|
|
166
|
+
- `AGENTMB_API_TOKEN` (optional API auth)
|
|
167
|
+
- `AGENTMB_ENCRYPTION_KEY` (optional AES-256-GCM profile encryption key, 32 bytes as base64 or hex)
|
|
168
|
+
- `AGENTMB_LOG_LEVEL` (default `info`)
|
|
169
|
+
- `AGENTMB_POLICY_PROFILE` (default `safe`) — daemon-wide default safety policy profile
|
|
170
|
+
|
|
171
|
+
## Safety Execution Policy
|
|
172
|
+
|
|
173
|
+
agentmb enforces a configurable **safety execution policy** that throttles actions, enforces per-domain rate limits, and blocks sensitive actions (e.g. form submissions, file uploads) unless explicitly permitted.
|
|
174
|
+
|
|
175
|
+
### Profiles
|
|
176
|
+
|
|
177
|
+
| Profile | Min interval | Jitter | Max actions/min | Sensitive actions |
|
|
178
|
+
|---|---|---|---|---|
|
|
179
|
+
| `safe` | 1500 ms | 300–800 ms | 8 | blocked by default |
|
|
180
|
+
| `permissive` | 200 ms | 0–100 ms | 60 | allowed |
|
|
181
|
+
| `disabled` | 0 ms | 0 ms | unlimited | allowed |
|
|
182
|
+
|
|
183
|
+
Set the daemon-wide default via env var:
|
|
184
|
+
```bash
|
|
185
|
+
AGENTMB_POLICY_PROFILE=disabled node dist/daemon/index.js # CI / trusted automation
|
|
186
|
+
AGENTMB_POLICY_PROFILE=safe node dist/daemon/index.js # social-media / sensitive workflows
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Per-session override (CLI)
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
agentmb policy <session-id> # get current policy
|
|
193
|
+
agentmb policy <session-id> safe # switch to safe profile
|
|
194
|
+
agentmb policy <session-id> permissive # switch to permissive
|
|
195
|
+
agentmb policy <session-id> safe --allow-sensitive # safe + allow sensitive actions
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Per-session override (Python SDK)
|
|
199
|
+
|
|
200
|
+
```python
|
|
201
|
+
from agentmb import BrowserClient
|
|
202
|
+
|
|
203
|
+
with BrowserClient() as client:
|
|
204
|
+
sess = client.sessions.create()
|
|
205
|
+
policy = sess.set_policy("safe", allow_sensitive_actions=False)
|
|
206
|
+
print(policy.max_retries_per_domain) # 3
|
|
207
|
+
current = sess.get_policy()
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Audit logs
|
|
211
|
+
|
|
212
|
+
All policy events (`throttle`, `jitter`, `cooldown`, `deny`, `retry`) are written to the session audit log with `type="policy"`.
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
agentmb logs <session-id> # shows policy events inline
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Sensitive actions
|
|
219
|
+
|
|
220
|
+
Mark any action as sensitive by passing `"sensitive": true` in the request body. With `safe` profile and `allow_sensitive_actions=false`, the request returns HTTP 403:
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{ "error": "sensitive action blocked by policy", "policy_event": "deny" }
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
MIT
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface AuditEntry {
|
|
2
|
+
ts?: string;
|
|
3
|
+
v?: number;
|
|
4
|
+
session_id?: string;
|
|
5
|
+
action_id?: string;
|
|
6
|
+
type: string;
|
|
7
|
+
action?: string;
|
|
8
|
+
url?: string;
|
|
9
|
+
selector?: string;
|
|
10
|
+
params?: Record<string, unknown>;
|
|
11
|
+
result?: Record<string, unknown>;
|
|
12
|
+
agent?: Record<string, unknown>;
|
|
13
|
+
error?: string | null;
|
|
14
|
+
purpose?: string;
|
|
15
|
+
operator?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class AuditLogger {
|
|
18
|
+
private logsDir;
|
|
19
|
+
private currentDate;
|
|
20
|
+
private stream;
|
|
21
|
+
constructor(logsDir: string);
|
|
22
|
+
write(entry: AuditEntry): void;
|
|
23
|
+
tail(sessionId: string, lines: number): AuditEntry[];
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,qBAAa,WAAW;IAIV,OAAO,CAAC,OAAO;IAH3B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,MAAM,CAA8B;gBAExB,OAAO,EAAE,MAAM;IAInC,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAiB9B,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE;CAsBrD"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.AuditLogger = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
class AuditLogger {
|
|
10
|
+
logsDir;
|
|
11
|
+
currentDate = '';
|
|
12
|
+
stream = null;
|
|
13
|
+
constructor(logsDir) {
|
|
14
|
+
this.logsDir = logsDir;
|
|
15
|
+
fs_1.default.mkdirSync(logsDir, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
write(entry) {
|
|
18
|
+
const now = new Date();
|
|
19
|
+
const date = now.toISOString().slice(0, 10); // YYYY-MM-DD
|
|
20
|
+
if (date !== this.currentDate || !this.stream) {
|
|
21
|
+
this.stream?.end();
|
|
22
|
+
this.currentDate = date;
|
|
23
|
+
this.stream = fs_1.default.createWriteStream(path_1.default.join(this.logsDir, `${date}.jsonl`), { flags: 'a' });
|
|
24
|
+
}
|
|
25
|
+
const record = {
|
|
26
|
+
ts: now.toISOString(),
|
|
27
|
+
v: 1,
|
|
28
|
+
...entry,
|
|
29
|
+
};
|
|
30
|
+
this.stream.write(JSON.stringify(record) + '\n');
|
|
31
|
+
}
|
|
32
|
+
tail(sessionId, lines) {
|
|
33
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
34
|
+
const file = path_1.default.join(this.logsDir, `${date}.jsonl`);
|
|
35
|
+
if (!fs_1.default.existsSync(file))
|
|
36
|
+
return [];
|
|
37
|
+
const content = fs_1.default.readFileSync(file, 'utf8');
|
|
38
|
+
const all = content
|
|
39
|
+
.trim()
|
|
40
|
+
.split('\n')
|
|
41
|
+
.filter(Boolean)
|
|
42
|
+
.map((line) => {
|
|
43
|
+
try {
|
|
44
|
+
return JSON.parse(line);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
.filter((e) => e !== null)
|
|
51
|
+
.filter((e) => !sessionId || e.session_id === sessionId);
|
|
52
|
+
return all.slice(-lines);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.AuditLogger = AuditLogger;
|
|
56
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAmB;AACnB,gDAAuB;AAmBvB,MAAa,WAAW;IAIF;IAHZ,WAAW,GAAG,EAAE,CAAA;IAChB,MAAM,GAA0B,IAAI,CAAA;IAE5C,YAAoB,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;QACjC,YAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC5C,CAAC;IAED,KAAK,CAAC,KAAiB;QACrB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;QACtB,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA,CAAC,aAAa;QACzD,IAAI,IAAI,KAAK,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAC9C,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAA;YAClB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAA;YACvB,IAAI,CAAC,MAAM,GAAG,YAAE,CAAC,iBAAiB,CAAC,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;QAC9F,CAAC;QAED,MAAM,MAAM,GAAe;YACzB,EAAE,EAAE,GAAG,CAAC,WAAW,EAAE;YACrB,CAAC,EAAE,CAAC;YACJ,GAAG,KAAK;SACT,CAAA;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAA;IAClD,CAAC;IAED,IAAI,CAAC,SAAiB,EAAE,KAAa;QACnC,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QAClD,MAAM,IAAI,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,QAAQ,CAAC,CAAA;QACrD,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,CAAA;QAEnC,MAAM,OAAO,GAAG,YAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAC7C,MAAM,GAAG,GAAG,OAAO;aAChB,IAAI,EAAE;aACN,KAAK,CAAC,IAAI,CAAC;aACX,MAAM,CAAC,OAAO,CAAC;aACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAA;YACvC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,CAAC,EAAmB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;aAC1C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAA;QAE1D,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAA;IAC1B,CAAC;CACF;AA/CD,kCA+CC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Page, Frame } from 'playwright-core';
|
|
2
|
+
import { AuditLogger } from '../audit/logger';
|
|
3
|
+
/** Page or frame — both expose the same action surface */
|
|
4
|
+
export type Actionable = Page | Frame;
|
|
5
|
+
type WaitUntil = 'load' | 'networkidle' | 'commit' | 'domcontentloaded';
|
|
6
|
+
export interface ActionDiagnostics {
|
|
7
|
+
error: string;
|
|
8
|
+
url: string;
|
|
9
|
+
title: string;
|
|
10
|
+
readyState: string;
|
|
11
|
+
elapsedMs: number;
|
|
12
|
+
stack?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class ActionDiagnosticsError extends Error {
|
|
15
|
+
readonly diagnostics: ActionDiagnostics;
|
|
16
|
+
constructor(diagnostics: ActionDiagnostics);
|
|
17
|
+
}
|
|
18
|
+
export declare function navigate(page: Page, url: string, waitUntil?: WaitUntil, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
19
|
+
status: string;
|
|
20
|
+
url: string;
|
|
21
|
+
title: string;
|
|
22
|
+
duration_ms: number;
|
|
23
|
+
}>;
|
|
24
|
+
export declare function click(page: Actionable, selector: string, timeoutMs?: number, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
25
|
+
status: string;
|
|
26
|
+
selector: string;
|
|
27
|
+
duration_ms: number;
|
|
28
|
+
}>;
|
|
29
|
+
export declare function fill(page: Actionable, selector: string, value: string, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
30
|
+
status: string;
|
|
31
|
+
selector: string;
|
|
32
|
+
duration_ms: number;
|
|
33
|
+
}>;
|
|
34
|
+
export declare function evaluate(page: Actionable, expression: string, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
35
|
+
status: string;
|
|
36
|
+
result: unknown;
|
|
37
|
+
duration_ms: number;
|
|
38
|
+
}>;
|
|
39
|
+
export declare function extract(page: Actionable, selector: string, attribute?: string, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
40
|
+
status: string;
|
|
41
|
+
selector: string;
|
|
42
|
+
items: Array<Record<string, string | null>>;
|
|
43
|
+
count: number;
|
|
44
|
+
duration_ms: number;
|
|
45
|
+
}>;
|
|
46
|
+
export declare function screenshot(page: Page, format?: 'png' | 'jpeg', fullPage?: boolean, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
47
|
+
status: string;
|
|
48
|
+
data: string;
|
|
49
|
+
format: string;
|
|
50
|
+
duration_ms: number;
|
|
51
|
+
}>;
|
|
52
|
+
export declare function typeText(page: Actionable, selector: string, text: string, delayMs?: number, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
53
|
+
status: string;
|
|
54
|
+
selector: string;
|
|
55
|
+
duration_ms: number;
|
|
56
|
+
}>;
|
|
57
|
+
export declare function press(page: Actionable, selector: string, key: string, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
58
|
+
status: string;
|
|
59
|
+
selector: string;
|
|
60
|
+
key: string;
|
|
61
|
+
duration_ms: number;
|
|
62
|
+
}>;
|
|
63
|
+
export declare function selectOption(page: Actionable, selector: string, values: string[], logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
64
|
+
status: string;
|
|
65
|
+
selector: string;
|
|
66
|
+
selected: string[];
|
|
67
|
+
duration_ms: number;
|
|
68
|
+
}>;
|
|
69
|
+
export declare function hover(page: Actionable, selector: string, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
70
|
+
status: string;
|
|
71
|
+
selector: string;
|
|
72
|
+
duration_ms: number;
|
|
73
|
+
}>;
|
|
74
|
+
export declare function waitForSelector(page: Actionable, selector: string, state?: 'attached' | 'detached' | 'visible' | 'hidden', timeoutMs?: number, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
75
|
+
status: string;
|
|
76
|
+
selector: string;
|
|
77
|
+
state: string;
|
|
78
|
+
duration_ms: number;
|
|
79
|
+
}>;
|
|
80
|
+
export declare function waitForUrl(page: Page, urlPattern: string, timeoutMs?: number, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
81
|
+
status: string;
|
|
82
|
+
url: string;
|
|
83
|
+
duration_ms: number;
|
|
84
|
+
}>;
|
|
85
|
+
export interface WaitForResponseTrigger {
|
|
86
|
+
type: 'navigate';
|
|
87
|
+
url: string;
|
|
88
|
+
waitUntil?: 'load' | 'networkidle' | 'commit' | 'domcontentloaded';
|
|
89
|
+
}
|
|
90
|
+
export declare function waitForResponse(page: Page, urlPattern: string, timeoutMs?: number, trigger?: WaitForResponseTrigger, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
91
|
+
status: string;
|
|
92
|
+
url: string;
|
|
93
|
+
status_code: number;
|
|
94
|
+
duration_ms: number;
|
|
95
|
+
}>;
|
|
96
|
+
export declare function uploadFile(page: Page, selector: string, fileContent: string, filename: string, mimeType?: string, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
97
|
+
status: string;
|
|
98
|
+
selector: string;
|
|
99
|
+
filename: string;
|
|
100
|
+
size_bytes: number;
|
|
101
|
+
duration_ms: number;
|
|
102
|
+
}>;
|
|
103
|
+
export declare function downloadFile(page: Page, selector: string, timeoutMs?: number, maxBytes?: number, logger?: AuditLogger, sessionId?: string, purpose?: string, operator?: string): Promise<{
|
|
104
|
+
status: string;
|
|
105
|
+
filename: string;
|
|
106
|
+
data: string;
|
|
107
|
+
size_bytes: number;
|
|
108
|
+
duration_ms: number;
|
|
109
|
+
}>;
|
|
110
|
+
export {};
|
|
111
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/browser/actions.ts"],"names":[],"mappings":"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"}
|