surf-cli 2.13.1 → 2.15.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/README.md +65 -34
- package/agents/gpt-pro.md +19 -0
- package/dist/content/index.js +116 -0
- package/dist/content/index.js.map +1 -0
- package/dist/icons/icon-128.png +0 -0
- package/dist/icons/icon-16.png +0 -0
- package/dist/icons/icon-48.png +0 -0
- package/dist/manifest.json +2 -11
- package/dist/options/options.js +3 -3
- package/dist/options/options.js.map +1 -1
- package/dist/service-worker/index.js +261 -61
- package/dist/service-worker/index.js.map +1 -1
- package/native/browser-scheduler.cjs +348 -0
- package/native/browser-session-store.cjs +271 -0
- package/native/chatgpt-client-selection.cjs +20 -10
- package/native/chatgpt-client-ui.cjs +35 -7
- package/native/cli.cjs +333 -62
- package/native/do-executor.cjs +5 -0
- package/native/host-helpers.cjs +19 -3
- package/native/host-sessions.cjs +8 -1
- package/native/host.cjs +766 -19
- package/native/mcp-server.cjs +1 -1
- package/native/oracle-cli.cjs +2 -2
- package/native/oracle-jobs.cjs +25 -3
- package/native/playbook-cli.cjs +16 -3
- package/native/surf-error.cjs +47 -0
- package/native/tool-scope.cjs +107 -0
- package/native/workflow-definition.cjs +7 -0
- package/package.json +8 -2
- package/pi-extension/surf.ts +275 -2
- package/skills/surf/SKILL.md +52 -23
- package/dist/content/accessibility-tree.js +0 -11
- package/dist/content/accessibility-tree.js.map +0 -1
- package/dist/content/visual-indicator.js +0 -111
- package/dist/content/visual-indicator.js.map +0 -1
package/README.md
CHANGED
|
@@ -142,7 +142,7 @@ surf remote revoke agent-macbook
|
|
|
142
142
|
surf remote list
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
-
`--remote <host>:<port>` takes precedence over `SURF_REMOTE`; `--remote-credential` takes precedence over `SURF_REMOTE_CREDENTIAL`. A selected remote endpoint overrides `SURF_SOCKET` and the default local socket. Local and remote requests share
|
|
145
|
+
`--remote <host>:<port>` takes precedence over `SURF_REMOTE`; `--remote-credential` takes precedence over `SURF_REMOTE_CREDENTIAL`. A selected remote endpoint overrides `SURF_SOCKET` and the default local socket. Local and remote requests share the same host scheduler: each tab has a FIFO lane, different tabs may execute concurrently, and browser-wide writers are exclusive. Disconnects and timeouts abort queued or in-flight work and retain admission until request-owned cleanup drains or the hard deadline is reached. Browser side effects that already completed are not rolled back.
|
|
146
146
|
|
|
147
147
|
`surf install --listen` persists the explicit Tailnet address in the native-host wrapper. Re-run `surf install` without `--listen` to remove it. The address must be a Tailscale IPv4 or IPv6 address with a port; Surf does not bind every interface. Remote listeners currently require a POSIX browser host and are not supported by Windows native-host wrappers.
|
|
148
148
|
|
|
@@ -348,44 +348,65 @@ surf tab.switch "dashboard" # Switch by name
|
|
|
348
348
|
surf tab.group --name "Work" --color blue
|
|
349
349
|
```
|
|
350
350
|
|
|
351
|
-
###
|
|
351
|
+
### Browser Sessions and Concurrent Agents
|
|
352
352
|
|
|
353
|
-
|
|
353
|
+
Give every independent agent a durable Surf session before its first browser command. `session.ensure` is idempotent: it creates a missing session, reuses a live one, and reopens a stale or closed binding.
|
|
354
354
|
|
|
355
355
|
```bash
|
|
356
|
-
#
|
|
357
|
-
|
|
358
|
-
|
|
356
|
+
# First command rule for every independent agent shell
|
|
357
|
+
export SURF_SESSION="$(basename "$PWD" | sed 's/[^A-Za-z0-9._-]/-/g')"
|
|
358
|
+
surf session.ensure "$SURF_SESSION" about:blank
|
|
359
359
|
|
|
360
|
-
#
|
|
361
|
-
surf
|
|
362
|
-
surf read
|
|
363
|
-
surf
|
|
360
|
+
# All later tab-scoped commands use that session automatically
|
|
361
|
+
surf go "https://example.com"
|
|
362
|
+
surf read
|
|
363
|
+
surf click e5
|
|
364
|
+
```
|
|
364
365
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
366
|
+
Use a distinct worktree/directory name per agent. When several agents share one directory, append a stable agent identifier instead of reusing the same `SURF_SESSION` value.
|
|
367
|
+
|
|
368
|
+
A session owns one explicit Chrome tab. New sessions use a separate **unfocused normal window** by default, so Chrome focus changes cannot retarget another agent's commands.
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
surf session.new research "https://example.com" # separate unfocused window
|
|
372
|
+
surf session.ensure research about:blank # safe to run repeatedly
|
|
373
|
+
surf session.new scout about:blank --tab # inactive tab instead
|
|
374
|
+
|
|
375
|
+
surf --session research read # explicit selector
|
|
376
|
+
SURF_SESSION=research surf screenshot # environment selector
|
|
368
377
|
|
|
369
|
-
#
|
|
370
|
-
surf
|
|
371
|
-
surf
|
|
372
|
-
surf
|
|
373
|
-
surf
|
|
378
|
+
surf session.list --refresh # all bindings + queue state
|
|
379
|
+
surf session.info research --refresh # target and scheduler details
|
|
380
|
+
surf session.close research # closes Surf-created target
|
|
381
|
+
surf session.rebind research --tab-id 789 # adopt an existing tab
|
|
382
|
+
surf session.reopen research # recreate from last URL
|
|
374
383
|
```
|
|
375
384
|
|
|
376
|
-
|
|
385
|
+
Commands for the same session tab run FIFO. Commands for different session tabs can overlap. Browser-wide mutations—such as creating, moving, closing, or focusing tabs/windows and writing cookies—wait for active tab lanes to drain. Add `--no-wait` to return `tab_busy` or `browser_busy` immediately instead of queueing.
|
|
377
386
|
|
|
378
|
-
|
|
387
|
+
Recovery errors print an exact command that can be copied directly:
|
|
379
388
|
|
|
380
|
-
|
|
389
|
+
```text
|
|
390
|
+
Error: The tab for session research is gone.
|
|
391
|
+
Recovery: surf session.reopen research
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
`session.info` distinguishes work queued on the session's own tab, activity on other tabs, and an active or waiting browser-wide writer. Browser-login provider commands such as `surf chatgpt`, `surf gemini`, and `surf oracle ask` print a warning before taking exclusive browser access, so a queued provider flow is not mistaken for a hung command.
|
|
395
|
+
|
|
396
|
+
Sessions share the same Chrome profile. Cookies, authentication, same-origin storage, downloads, history, bookmarks, and other profile state are shared. For hard isolation, use separate browser profiles/instances with separate native hosts and `SURF_SOCKET` values.
|
|
397
|
+
|
|
398
|
+
### Explicit Tabs and Windows
|
|
399
|
+
|
|
400
|
+
Session targeting is the recommended coordination mechanism. Explicit IDs and named tabs remain available for one-off work:
|
|
381
401
|
|
|
382
402
|
```bash
|
|
383
|
-
|
|
384
|
-
|
|
403
|
+
surf window.new "https://example.com"
|
|
404
|
+
surf read --tab-id 789
|
|
405
|
+
surf click e5 --window-id 123456
|
|
406
|
+
surf tab.name dashboard --tab-id 789
|
|
407
|
+
surf tab.switch dashboard
|
|
385
408
|
```
|
|
386
409
|
|
|
387
|
-
Surf does not yet provide `session.new`, session IDs, or independent per-agent CDP sessions.
|
|
388
|
-
|
|
389
410
|
### Device Emulation
|
|
390
411
|
|
|
391
412
|
Test responsive designs and mobile layouts:
|
|
@@ -458,7 +479,7 @@ Query AI models using your browser's logged-in session:
|
|
|
458
479
|
# ChatGPT
|
|
459
480
|
surf chatgpt "explain this code"
|
|
460
481
|
surf chatgpt "summarize" --with-page # Include page context
|
|
461
|
-
surf chatgpt "analyze" --model gpt-
|
|
482
|
+
surf chatgpt "analyze" --model gpt-5.5 # Specify model
|
|
462
483
|
surf chatgpt "review" --file code.ts # Attach file
|
|
463
484
|
|
|
464
485
|
# Gemini
|
|
@@ -505,10 +526,10 @@ surf aistudio.build "game" --keep-open --timeout 600 # Keep tab open, 1
|
|
|
505
526
|
|
|
506
527
|
#### Oracle
|
|
507
528
|
|
|
508
|
-
Use `surf oracle` for a durable, local ChatGPT consult instead of a quick `surf chatgpt` one-shot. It persists jobs by conversation URL, supports repeatable file-context globs, and verifies requested model and reasoning effort before submission.
|
|
529
|
+
Use `surf oracle` for a durable, local ChatGPT consult instead of a quick `surf chatgpt` one-shot. It persists jobs by conversation URL, supports repeatable file-context globs, and verifies requested model and reasoning effort before submission. ChatGPT model aliases include `instant`, `thinking`, `pro`, `gpt-5.5`, and `gpt-5.6-sol`; `pro` selects the current ChatGPT GPT-5.6 Sol Pro web mode.
|
|
509
530
|
|
|
510
531
|
```bash
|
|
511
|
-
surf oracle ask "review this change" --files "src/**/*.ts" --model
|
|
532
|
+
surf oracle ask "review this change" --files "src/**/*.ts" --model gpt-5.5 --effort pro --detach --json
|
|
512
533
|
surf oracle status <job-id> --json
|
|
513
534
|
surf oracle result <job-id> --wait --json
|
|
514
535
|
surf oracle follow <job-id> "challenge that recommendation" --detach --json
|
|
@@ -764,11 +785,13 @@ Generated manifests declare provenance and authentication environment inputs. Su
|
|
|
764
785
|
## Global Options
|
|
765
786
|
|
|
766
787
|
```bash
|
|
767
|
-
--
|
|
768
|
-
--
|
|
769
|
-
--
|
|
788
|
+
--session <name> # Target a durable browser session (or set SURF_SESSION)
|
|
789
|
+
--tab-id <id> # Target a specific tab
|
|
790
|
+
--window-id <id> # Target a specific window
|
|
791
|
+
--no-wait # Return tab_busy/browser_busy instead of queueing
|
|
792
|
+
--json # Raw JSON including resolved target metadata
|
|
770
793
|
--soft-fail # Warn instead of error (exit 0) on restricted pages
|
|
771
|
-
--no-lock # Bypass the
|
|
794
|
+
--no-lock # Bypass the legacy lock for compound client-side commands
|
|
772
795
|
--no-screenshot # Skip auto-screenshot after actions
|
|
773
796
|
--full # Full resolution screenshots (skip resize)
|
|
774
797
|
```
|
|
@@ -777,6 +800,8 @@ Generated manifests declare provenance and authentication environment inputs. Su
|
|
|
777
800
|
|
|
778
801
|
```bash
|
|
779
802
|
SURF_NETWORK_PATH # Native-host network state root (default: ~/.surf/state/network)
|
|
803
|
+
SURF_STATE_DIR # Private Surf state root, including browser sessions (default: ~/.surf/state)
|
|
804
|
+
SURF_SESSION # Default named browser session for tab-scoped commands
|
|
780
805
|
SURF_SOCKET # Socket path or named pipe (default: /tmp/surf.sock, Windows: //./pipe/surf)
|
|
781
806
|
SURF_REMOTE # Remote Surf endpoint as host:port (overrides SURF_SOCKET)
|
|
782
807
|
SURF_REMOTE_CREDENTIAL # Client Ed25519 credential for the selected remote endpoint
|
|
@@ -788,7 +813,9 @@ SURF_EXTENSION_PATH # Path to extension dist/ directory
|
|
|
788
813
|
```
|
|
789
814
|
|
|
790
815
|
**Use cases:**
|
|
791
|
-
- `
|
|
816
|
+
- `SURF_SESSION`: Per-shell default session. Give each independent agent a unique value and run `surf session.ensure "$SURF_SESSION" about:blank` before its first browser command.
|
|
817
|
+
- `SURF_STATE_DIR`: Private mode-0700 state root for durable browser-session bindings and other Surf state.
|
|
818
|
+
- `SURF_SOCKET`: Advanced socket override. Set it for both the native host and CLI when separate browser/profile instances need hard isolation.
|
|
792
819
|
- `SURF_REMOTE`: Remote client endpoint. `--remote <host>:<port>` overrides it; both override `SURF_SOCKET`.
|
|
793
820
|
- `SURF_REMOTE_CREDENTIAL`: Credential used for mutual remote authentication. `--remote-credential <path>` overrides it.
|
|
794
821
|
- `SURF_REMOTE_STATE_DIR`: Advanced host-side override for the mode-0700 identity and client registry directory.
|
|
@@ -969,7 +996,11 @@ pi -e /path/to/surf-cli/pi-extension/surf.ts
|
|
|
969
996
|
|
|
970
997
|
It registers `surf_read`, `surf_screenshot`, `surf_click`, `surf_type`, `surf_tool`, and the `surf_oracle_*` tools. Browser calls use Surf's native-host socket, not shell commands. If `pi-subagents/background-work` is installed, the extension also reports active oracle jobs started by that Pi session. Pi still loads the browser tools when pi-subagents is not installed.
|
|
971
998
|
|
|
972
|
-
|
|
999
|
+
The extension also registers a `surf-oracle` external-job provider when a Pi runtime exposes that provider bridge. The provider has `start`, `status`, `result`, `reattach`, and `follow` operations. It reads `options.model` and `options.effort` for starts and follows, so a Pi profile can request `model: pro` and reach the ChatGPT GPT-5.6 Sol Pro web mode through Surf. Each operation returns Surf job metadata with the durable conversation URL, requested and verified ChatGPT model and effort, prompt digest, result text when captured, and failure details when present. Capacity stays fail-closed: Surf returns the blocking job id instead of silently queueing a second ChatGPT job.
|
|
1000
|
+
|
|
1001
|
+
When Surf is installed as a Pi package, it also exposes an optional `gpt-pro` package agent for `pi-subagents`. That profile uses `runner.type: external-job`, provider `surf-oracle`, and `options.model: pro`. Surf remains useful without Pi or `pi-subagents`; the package agent only wires Surf's browser-backed model alias into Pi's agent picker.
|
|
1002
|
+
|
|
1003
|
+
Shell-based agents should select a unique session with `SURF_SESSION` and call `surf session.ensure` before their first browser command. The optional Pi extension still uses its existing socket-tool interface; callers that coordinate several Pi workers should pass explicit tab targets until session selection is exposed by that integration.
|
|
973
1004
|
|
|
974
1005
|
## Development
|
|
975
1006
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gpt-pro
|
|
3
|
+
description: Surf GPT Pro advisor through ChatGPT GPT-5.6 Sol Pro web mode
|
|
4
|
+
runner:
|
|
5
|
+
type: external-job
|
|
6
|
+
provider: surf-oracle
|
|
7
|
+
options:
|
|
8
|
+
model: pro
|
|
9
|
+
async: true
|
|
10
|
+
systemPromptMode: replace
|
|
11
|
+
inheritProjectContext: false
|
|
12
|
+
inheritSkills: false
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
You are a read-only GPT Pro advisor reached through Surf Oracle.
|
|
16
|
+
|
|
17
|
+
Review the supplied task and context.
|
|
18
|
+
Return clear advice, risks, and recommended next steps.
|
|
19
|
+
Do not claim you edited files or ran local tools.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
var e=`59, 178, 191`,t=1e4,n=null,r=null,i=null,a=!1,o=!1,s=!1,c=!1,l=null,u=t,d=!1,f=!1,p=window===window.top;p&&(chrome.storage.local.get(`heartbeatInterval`).then(({heartbeatInterval:e})=>{e&&typeof e==`number`&&(u=e*1e3)}),chrome.storage.onChanged.addListener((e,t)=>{if(t===`local`&&e.heartbeatInterval){let t=e.heartbeatInterval.newValue;t&&typeof t==`number`&&(u=t*1e3,o&&l&&(clearInterval(l),m()))}}));function m(){l=window.setInterval(async()=>{try{(await chrome.runtime.sendMessage({type:`STATIC_INDICATOR_HEARTBEAT`}))?.success||S()}catch{S()}},u)}function h(){if(document.getElementById(`pi-agent-styles`))return;let t=document.createElement(`style`);t.id=`pi-agent-styles`,t.textContent=`
|
|
2
|
+
@keyframes pi-pulse {
|
|
3
|
+
0% {
|
|
4
|
+
box-shadow:
|
|
5
|
+
inset 0 0 10px rgba(${e}, 0.5),
|
|
6
|
+
inset 0 0 20px rgba(${e}, 0.3),
|
|
7
|
+
inset 0 0 30px rgba(${e}, 0.1);
|
|
8
|
+
}
|
|
9
|
+
50% {
|
|
10
|
+
box-shadow:
|
|
11
|
+
inset 0 0 15px rgba(${e}, 0.7),
|
|
12
|
+
inset 0 0 25px rgba(${e}, 0.5),
|
|
13
|
+
inset 0 0 35px rgba(${e}, 0.2);
|
|
14
|
+
}
|
|
15
|
+
100% {
|
|
16
|
+
box-shadow:
|
|
17
|
+
inset 0 0 10px rgba(${e}, 0.5),
|
|
18
|
+
inset 0 0 20px rgba(${e}, 0.3),
|
|
19
|
+
inset 0 0 30px rgba(${e}, 0.1);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
`,document.head.appendChild(t)}function g(){let t=document.createElement(`div`);return t.id=`pi-agent-glow`,t.style.cssText=`
|
|
23
|
+
position: fixed;
|
|
24
|
+
top: 0;
|
|
25
|
+
left: 0;
|
|
26
|
+
right: 0;
|
|
27
|
+
bottom: 0;
|
|
28
|
+
pointer-events: none;
|
|
29
|
+
z-index: 2147483646;
|
|
30
|
+
opacity: 0;
|
|
31
|
+
transition: opacity 0.3s ease-in-out;
|
|
32
|
+
animation: pi-pulse 2s ease-in-out infinite;
|
|
33
|
+
box-shadow:
|
|
34
|
+
inset 0 0 10px rgba(${e}, 0.5),
|
|
35
|
+
inset 0 0 20px rgba(${e}, 0.3),
|
|
36
|
+
inset 0 0 30px rgba(${e}, 0.1);
|
|
37
|
+
`,t}function _(){let t=document.createElement(`div`);t.id=`pi-agent-stop-container`,t.style.cssText=`
|
|
38
|
+
position: fixed;
|
|
39
|
+
bottom: 16px;
|
|
40
|
+
left: 50%;
|
|
41
|
+
transform: translateX(-50%);
|
|
42
|
+
display: flex;
|
|
43
|
+
justify-content: center;
|
|
44
|
+
align-items: center;
|
|
45
|
+
pointer-events: none;
|
|
46
|
+
z-index: 2147483647;
|
|
47
|
+
`;let n=document.createElement(`button`);return n.id=`pi-agent-stop-button`,n.innerHTML=`
|
|
48
|
+
<svg width="16" height="16" viewBox="0 0 256 256" fill="currentColor" style="margin-right: 12px; vertical-align: middle;">
|
|
49
|
+
<path d="M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm0,192a84,84,0,1,1,84-84A84.09,84.09,0,0,1,128,212Zm40-112v56a12,12,0,0,1-12,12H100a12,12,0,0,1-12-12V100a12,12,0,0,1,12-12h56A12,12,0,0,1,168,100Z"></path>
|
|
50
|
+
</svg>
|
|
51
|
+
<span style="vertical-align: middle;">Stop Surf</span>
|
|
52
|
+
`,n.style.cssText=`
|
|
53
|
+
position: relative;
|
|
54
|
+
transform: translateY(100px);
|
|
55
|
+
padding: 12px 16px;
|
|
56
|
+
background: #FAF9F5;
|
|
57
|
+
color: #141413;
|
|
58
|
+
border: 0.5px solid rgba(31, 30, 29, 0.4);
|
|
59
|
+
border-radius: 12px;
|
|
60
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
61
|
+
font-size: 14px;
|
|
62
|
+
font-weight: 600;
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
display: inline-flex;
|
|
65
|
+
align-items: center;
|
|
66
|
+
justify-content: center;
|
|
67
|
+
box-shadow:
|
|
68
|
+
0 40px 80px rgba(${e}, 0.24),
|
|
69
|
+
0 4px 14px rgba(${e}, 0.24);
|
|
70
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
71
|
+
opacity: 0;
|
|
72
|
+
user-select: none;
|
|
73
|
+
pointer-events: auto;
|
|
74
|
+
white-space: nowrap;
|
|
75
|
+
margin: 0 auto;
|
|
76
|
+
`,n.addEventListener(`mouseenter`,()=>{a&&(n.style.background=`#F5F4F0`)}),n.addEventListener(`mouseleave`,()=>{a&&(n.style.background=`#FAF9F5`)}),n.addEventListener(`click`,async()=>{await chrome.runtime.sendMessage({type:`STOP_AGENT`,fromTabId:`CURRENT_TAB`})}),t.appendChild(n),t}function v(){let t=document.createElement(`div`);t.id=`pi-agent-static-indicator`,t.innerHTML=`
|
|
77
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" style="width: 16px; height: 16px; margin-right: 8px; flex-shrink: 0;">
|
|
78
|
+
<circle cx="8" cy="8" r="7" fill="rgb(${e})"/>
|
|
79
|
+
<text x="8" y="11" font-size="9" fill="white" text-anchor="middle" font-weight="bold">π</text>
|
|
80
|
+
</svg>
|
|
81
|
+
<span style="color: #141413; font-size: 14px;">Surf is active in this tab group</span>
|
|
82
|
+
<div style="width: 0.5px; height: 32px; background: rgba(31, 30, 29, 0.15); margin: 0 8px;"></div>
|
|
83
|
+
<button id="pi-static-chat-button" style="display: inline-flex; align-items: center; justify-content: center; padding: 6px; background: transparent; border: none; cursor: pointer; width: 32px; height: 32px; border-radius: 8px; transition: background 0.2s;">
|
|
84
|
+
<svg width="20" height="20" viewBox="0 0 20 20" fill="#141413">
|
|
85
|
+
<path d="M10 2.5C14.1421 2.5 17.5 5.85786 17.5 10C17.5 14.1421 14.1421 17.5 10 17.5H3C2.79779 17.5 2.61549 17.3782 2.53809 17.1914C2.4607 17.0046 2.50349 16.7895 2.64648 16.6465L4.35547 14.9365C3.20124 13.6175 2.5 11.8906 2.5 10C2.5 5.85786 5.85786 2.5 10 2.5Z"/>
|
|
86
|
+
</svg>
|
|
87
|
+
</button>
|
|
88
|
+
<button id="pi-static-close-button" style="display: inline-flex; align-items: center; justify-content: center; padding: 6px; background: transparent; border: none; cursor: pointer; width: 32px; height: 32px; margin-left: 4px; border-radius: 8px; transition: background 0.2s;">
|
|
89
|
+
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
|
90
|
+
<path d="M15.1464 4.14642C15.3417 3.95121 15.6582 3.95118 15.8534 4.14642C16.0486 4.34168 16.0486 4.65822 15.8534 4.85346L10.7069 9.99997L15.8534 15.1465C16.0486 15.3417 16.0486 15.6583 15.8534 15.8535C15.6826 16.0244 15.4186 16.0461 15.2245 15.918L15.1464 15.8535L9.99989 10.707L4.85338 15.8535C4.65813 16.0486 4.34155 16.0486 4.14634 15.8535C3.95115 15.6583 3.95129 15.3418 4.14634 15.1465L9.29286 9.99997L4.14634 4.85346C3.95129 4.65818 3.95115 4.34162 4.14634 4.14642C4.34154 3.95128 4.65812 3.95138 4.85338 4.14642L9.99989 9.29294L15.1464 4.14642Z" fill="#141413"/>
|
|
91
|
+
</svg>
|
|
92
|
+
</button>
|
|
93
|
+
`,t.style.cssText=`
|
|
94
|
+
position: fixed;
|
|
95
|
+
bottom: 16px;
|
|
96
|
+
left: 50%;
|
|
97
|
+
transform: translateX(-50%);
|
|
98
|
+
display: inline-flex;
|
|
99
|
+
align-items: center;
|
|
100
|
+
padding: 6px 6px 6px 16px;
|
|
101
|
+
background: #FAF9F5;
|
|
102
|
+
border: 0.5px solid rgba(31, 30, 29, 0.30);
|
|
103
|
+
border-radius: 14px;
|
|
104
|
+
box-shadow: 0 40px 80px 0 rgba(0, 0, 0, 0.15);
|
|
105
|
+
z-index: 2147483647;
|
|
106
|
+
pointer-events: none;
|
|
107
|
+
white-space: nowrap;
|
|
108
|
+
user-select: none;
|
|
109
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
110
|
+
`;let n=t.querySelector(`#pi-static-chat-button`),r=t.querySelector(`#pi-static-close-button`);return n&&(n.style.pointerEvents=`auto`,n.addEventListener(`mouseenter`,()=>n.style.background=`#F0EEE6`),n.addEventListener(`mouseleave`,()=>n.style.background=`transparent`),n.addEventListener(`click`,async()=>{await chrome.runtime.sendMessage({type:`OPEN_SIDEPANEL`})})),r&&(r.style.pointerEvents=`auto`,r.addEventListener(`mouseenter`,()=>r.style.background=`#F0EEE6`),r.addEventListener(`mouseleave`,()=>r.style.background=`transparent`),r.addEventListener(`click`,async()=>{await chrome.runtime.sendMessage({type:`DISMISS_STATIC_INDICATOR`}),S()})),t}function y(){if(!document.body){d||(d=!0,window.addEventListener(`DOMContentLoaded`,()=>{d&&(d=!1,y())},{once:!0}));return}d=!1,!a&&(a=!0,h(),n?n.style.display=``:(n=g(),document.body.appendChild(n)),r?r.style.display=``:(r=_(),document.body.appendChild(r)),requestAnimationFrame(()=>{if(n&&(n.style.opacity=`1`),r){let e=r.querySelector(`#pi-agent-stop-button`);e&&(e.style.transform=`translateY(0)`,e.style.opacity=`1`)}}))}function b(){if(d=!1,a){if(a=!1,n&&(n.style.opacity=`0`),r){let e=r.querySelector(`#pi-agent-stop-button`);e&&(e.style.transform=`translateY(100px)`,e.style.opacity=`0`)}setTimeout(()=>{a||(n?.parentNode&&(n.parentNode.removeChild(n),n=null),r?.parentNode&&(r.parentNode.removeChild(r),r=null))},300)}}function x(){if(!document.body){f||(f=!0,window.addEventListener(`DOMContentLoaded`,()=>{f&&(f=!1,x())},{once:!0}));return}f=!1,!o&&(o=!0,i?i.style.display=``:(i=v(),document.body.appendChild(i)),l&&clearInterval(l),m())}function S(){f=!1,o&&(o=!1,l&&=(clearInterval(l),null),i?.parentNode&&(i.parentNode.removeChild(i),i=null))}p&&(window.__piVisualIndicatorMessageHandler=e=>{switch(e){case`SHOW_AGENT_INDICATORS`:y();break;case`HIDE_AGENT_INDICATORS`:b();break;case`HIDE_FOR_TOOL_USE`:s=a||d,c=o||f,d=!1,f=!1,n&&(n.style.display=`none`),r&&(r.style.display=`none`),i&&o&&(i.style.display=`none`);break;case`SHOW_AFTER_TOOL_USE`:s&&(a?(n&&(n.style.display=``),r&&(r.style.display=``)):y()),c&&(o&&i?i.style.display=``:x()),s=!1,c=!1;break;case`SHOW_STATIC_INDICATOR`:x();break;case`HIDE_STATIC_INDICATOR`:S()}},window.addEventListener(`beforeunload`,()=>{b(),S()}));var C=new Set(`alert.alertdialog.application.article.banner.blockquote.button.caption.cell.checkbox.code.columnheader.combobox.complementary.contentinfo.definition.deletion.dialog.directory.document.emphasis.feed.figure.form.generic.grid.gridcell.group.heading.img.insertion.link.list.listbox.listitem.log.main.mark.marquee.math.menu.menubar.menuitem.menuitemcheckbox.menuitemradio.meter.navigation.none.note.option.paragraph.presentation.progressbar.radio.radiogroup.region.row.rowgroup.rowheader.scrollbar.search.searchbox.separator.slider.spinbutton.status.strong.subscript.superscript.switch.tab.table.tablist.tabpanel.term.textbox.time.timer.toolbar.tooltip.tree.treegrid.treeitem`.split(`.`));function w(e){let t=e.tagName.toLowerCase();if([`button`,`input`,`select`,`textarea`].includes(t))return!e.disabled;if(t===`a`&&e.hasAttribute(`href`))return!0;if(e.hasAttribute(`tabindex`)){let t=parseInt(e.getAttribute(`tabindex`)||``,10);return!isNaN(t)&&t>=0}return e.getAttribute(`contenteditable`)===`true`}function T(e){let t=e.getAttribute(`role`);if(!t)return null;let n=t.split(/\s+/).filter(e=>e);for(let e of n)if(C.has(e))return e;return null}function E(e){let t=e.tagName.toLowerCase(),n=e.getAttribute(`type`),r={a:e=>e.hasAttribute(`href`)?`link`:`generic`,article:`article`,aside:`complementary`,button:`button`,datalist:`listbox`,dd:`definition`,details:`group`,dialog:`dialog`,dt:`term`,fieldset:`group`,figure:`figure`,footer:e=>e.closest(`article, aside, main, nav, section`)?`generic`:`contentinfo`,form:e=>e.hasAttribute(`aria-label`)||e.hasAttribute(`aria-labelledby`)?`form`:`generic`,h1:`heading`,h2:`heading`,h3:`heading`,h4:`heading`,h5:`heading`,h6:`heading`,header:e=>e.closest(`article, aside, main, nav, section`)?`generic`:`banner`,hr:`separator`,img:e=>e.getAttribute(`alt`)===``?`presentation`:`img`,li:`listitem`,main:`main`,math:`math`,menu:`list`,meter:`meter`,nav:`navigation`,ol:`list`,optgroup:`group`,option:`option`,output:`status`,p:`paragraph`,progress:`progressbar`,search:`search`,section:e=>e.hasAttribute(`aria-label`)||e.hasAttribute(`aria-labelledby`)?`region`:`generic`,select:e=>{let t=e;return t.hasAttribute(`multiple`)||t.size&&t.size>1?`listbox`:`combobox`},table:`table`,tbody:`rowgroup`,td:`cell`,textarea:`textbox`,tfoot:`rowgroup`,th:`columnheader`,thead:`rowgroup`,time:`time`,tr:`row`,ul:`list`};if(t===`input`)return{button:`button`,checkbox:`checkbox`,email:`textbox`,file:`button`,image:`button`,number:`spinbutton`,radio:`radio`,range:`slider`,reset:`button`,search:`searchbox`,submit:`button`,tel:`textbox`,text:`textbox`,url:`textbox`}[n||``]||`textbox`;let i=r[t];return typeof i==`function`?i(e):i||`generic`}function D(e){let t=T(e);return!t||(t===`none`||t===`presentation`)&&w(e)?E(e):t}window.__piElementMap||(window.__piElementMap={});var O=new WeakMap,k=0;function A(e,t,n){let r=O.get(e);if(r&&r.role===t&&r.name===n)return r.ref;let i=`e${++k}`;return O.set(e,{role:t,name:n,ref:i}),i}function j(){let e=[];return document.querySelectorAll(`[role="dialog"], [role="alertdialog"], dialog[open]`).forEach(t=>{let n=window.getComputedStyle(t);if(!(n.display!==`none`&&n.visibility!==`hidden`&&n.opacity!==`0`&&t.offsetWidth>0&&t.offsetHeight>0))return;let r=t.getAttribute(`role`)||`dialog`,i=t.getAttribute(`aria-label`)||t.querySelector(`[role="heading"], h1, h2, h3`)?.textContent?.trim()||`Dialog`;i.length>100&&(i=i.substring(0,100)+`...`),e.push({type:r,description:`${r}: ${i}`,clearedBy:`computer(action=key, text=Escape)`})}),e}var M={wait(e){return new Promise(t=>setTimeout(t,e))},async waitForSelector(e,t={}){let{state:n=`visible`,timeout:r=2e4}=t,i=e=>{if(!e)return!1;let t=window.getComputedStyle(e);return t.display!==`none`&&t.visibility!==`hidden`&&t.opacity!==`0`&&e.offsetWidth>0&&e.offsetHeight>0},a=()=>{let t=document.querySelector(e);switch(n){case`attached`:return t;case`detached`:return t?null:document.body;case`hidden`:return t?i(t)?null:t:document.body;default:return i(t)?t:null}};return new Promise((t,i)=>{let o=a();if(o){t(n===`detached`||n===`hidden`?null:o);return}let s=new MutationObserver(()=>{let e=a();e&&(s.disconnect(),clearTimeout(c),t(n===`detached`||n===`hidden`?null:e))}),c=setTimeout(()=>{s.disconnect(),i(Error(`Timeout waiting for "${e}" to be ${n}`))},r);s.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`style`,`class`,`hidden`]})})},async waitForText(e,t={}){let{selector:n,timeout:r=2e4}=t,i=()=>{let t=n?document.querySelector(n):document.body;if(!t)return null;let r=document.createTreeWalker(t,NodeFilter.SHOW_TEXT);for(;r.nextNode();)if(r.currentNode.textContent?.includes(e))return r.currentNode.parentElement;return null};return new Promise((t,n)=>{let a=i();if(a){t(a);return}let o=new MutationObserver(()=>{let e=i();e&&(o.disconnect(),clearTimeout(s),t(e))}),s=setTimeout(()=>{o.disconnect(),n(Error(`Timeout waiting for text "${e}"`))},r);o.observe(document.documentElement,{childList:!0,subtree:!0,characterData:!0})})},async waitForHidden(e,t=2e4){await M.waitForSelector(e,{state:`hidden`,timeout:t})},getByRole(e,t={}){let{name:n}=t,r={button:[`button`,`input[type="button"]`,`input[type="submit"]`,`input[type="reset"]`],link:[`a[href]`],textbox:[`input:not([type])`,`input[type="text"]`,`input[type="email"]`,`input[type="password"]`,`input[type="search"]`,`input[type="tel"]`,`input[type="url"]`,`textarea`],checkbox:[`input[type="checkbox"]`],radio:[`input[type="radio"]`],combobox:[`select`],heading:[`h1`,`h2`,`h3`,`h4`,`h5`,`h6`],list:[`ul`,`ol`],listitem:[`li`],navigation:[`nav`],main:[`main`],banner:[`header`],contentinfo:[`footer`],form:[`form`],img:[`img`],table:[`table`]},i=[];i.push(...document.querySelectorAll(`[role="${e}"]`));let a=r[e];if(a)for(let e of a)i.push(...document.querySelectorAll(`${e}:not([role])`));if(!n)return i[0]||null;let o=n.toLowerCase().trim();for(let e of i){let t=e.getAttribute(`aria-label`)?.toLowerCase().trim(),n=e.textContent?.toLowerCase().trim(),r=e.getAttribute(`title`)?.toLowerCase().trim(),i=e.getAttribute(`placeholder`)?.toLowerCase().trim();if(t===o||n===o||r===o||i===o||t?.includes(o)||n?.includes(o))return e}return null}};window.__piHelpers||(window.__piHelpers=M,window.piHelpers=M);function N(){return window.__piElementMap}function P(e=`interactive`,t=15,n,r=!1,i=!1){try{window.__piRefs={};function a(e){return D(e)}function o(e){let t=e.tagName.toLowerCase(),n=e.getAttribute(`aria-labelledby`);if(n){let e=n.split(/\s+/).map(e=>document.getElementById(e)?.textContent?.trim()||``).filter(Boolean);if(e.length){let t=e.join(` `);return t.length>100?t.substring(0,100)+`...`:t}}if(t===`select`){let t=e,n=t.querySelector(`option[selected]`)||(t.selectedIndex>=0?t.options[t.selectedIndex]:null);if(n?.textContent?.trim())return n.textContent.trim()}let r=e.getAttribute(`aria-label`);if(r?.trim())return r.trim();let i=e.getAttribute(`placeholder`);if(i?.trim())return i.trim();let a=e.getAttribute(`title`);if(a?.trim())return a.trim();let o=e.getAttribute(`alt`);if(o?.trim())return o.trim();if(e.id){let t=document.querySelector(`label[for="${e.id}"]`);if(t?.textContent?.trim())return t.textContent.trim()}if(t===`input`){let t=e,n=e.getAttribute(`type`)||``,r=e.getAttribute(`value`);if(n===`submit`&&r?.trim())return r.trim();if(t.value&&t.value.length<50&&t.value.trim())return t.value.trim()}if([`button`,`a`,`summary`].includes(t)){let t=e.textContent||``;if(t.trim())return t.trim()}if(/^h[1-6]$/.test(t)){let t=e.textContent;if(t?.trim()){let e=t.trim();return e.length>100?e.substring(0,100)+`...`:e}}if(t===`img`)return``;let s=``;for(let t of e.childNodes)t.nodeType===Node.TEXT_NODE&&(s+=t.textContent);if(s?.trim()&&s.trim().length>=3){let e=s.trim();return e.length>100?e.substring(0,100)+`...`:e}return``}function s(e){let t={},n=e.getAttribute(`aria-checked`);n===`true`?t.checked=!0:n===`false`?t.checked=!1:n===`mixed`?t.checked=`mixed`:e instanceof HTMLInputElement&&(e.type===`checkbox`||e.type===`radio`)&&(t.checked=e.type===`checkbox`&&e.indeterminate?`mixed`:e.checked);let r=e instanceof HTMLButtonElement||e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement;(e.getAttribute(`aria-disabled`)===`true`||r&&e.disabled||e.closest(`fieldset:disabled`))&&(t.disabled=!0);let i=e.getAttribute(`aria-expanded`);i===`true`?t.expanded=!0:i===`false`&&(t.expanded=!1);let a=e.getAttribute(`aria-pressed`);a===`true`?t.pressed=!0:a===`false`?t.pressed=!1:a===`mixed`&&(t.pressed=`mixed`);let o=e.getAttribute(`aria-selected`);o===`true`?t.selected=!0:o===`false`&&(t.selected=!1);let s=e.getAttribute(`aria-current`);s&&s!==`false`&&(t.active=!0);let c=e.tagName.toLowerCase();if(/^h[1-6]$/.test(c))t.level=parseInt(c[1],10);else{let n=e.getAttribute(`aria-level`);n&&(t.level=parseInt(n,10))}return t}function c(e){let t=[];return e.checked!==void 0&&t.push(e.checked===`mixed`?`[checked=mixed]`:e.checked?`[checked]`:`[unchecked]`),e.disabled&&t.push(`[disabled]`),e.expanded!==void 0&&t.push(e.expanded?`[expanded]`:`[collapsed]`),e.pressed!==void 0&&t.push(e.pressed===`mixed`?`[pressed=mixed]`:e.pressed?`[pressed]`:`[not-pressed]`),e.selected!==void 0&&t.push(e.selected?`[selected]`:`[not-selected]`),e.active&&t.push(`[active]`),e.level!==void 0&&t.push(`[level=${e.level}]`),t.join(` `)}function l(e){let t=window.getComputedStyle(e);return t.display!==`none`&&t.visibility!==`hidden`&&t.opacity!==`0`&&e.offsetWidth>0&&e.offsetHeight>0}function u(e){let t=e.tagName.toLowerCase();return[`a`,`button`,`input`,`select`,`textarea`,`details`,`summary`].includes(t)||e.hasAttribute(`onclick`)||e.hasAttribute(`tabindex`)||e.getAttribute(`role`)===`button`||e.getAttribute(`role`)===`link`||e.getAttribute(`contenteditable`)===`true`}function d(e){let t=e.tagName.toLowerCase();return[`h1`,`h2`,`h3`,`h4`,`h5`,`h6`,`nav`,`main`,`header`,`footer`,`section`,`article`,`aside`].includes(t)||e.hasAttribute(`role`)}function f(e){return window.getComputedStyle(e).cursor===`pointer`}function p(e,t){let n=e.tagName.toLowerCase();if([`script`,`style`,`meta`,`link`,`title`,`noscript`].includes(n)||t.filter!==`all`&&e.getAttribute(`aria-hidden`)===`true`||t.filter!==`all`&&!l(e))return!1;if(t.filter!==`all`&&!t.refId){let t=e.getBoundingClientRect();if(!(t.top<window.innerHeight&&t.bottom>0&&t.left<window.innerWidth&&t.right>0))return!1}if(t.filter===`interactive`)return u(e);if(u(e)||d(e)||o(e).length>0)return!0;let r=a(e);return t.compact&&new Set([`generic`,`group`,`region`,`article`,`section`,`complementary`]).has(r)&&o(e).length===0?!1:r!==`generic`&&r!==`img`}function m(r,l){let u=[],d={filter:e,refId:n||null,compact:i},h=N(),g=p(r,d)||n&&l===0;if(g){let e=a(r),t=o(r),n=s(r),i=A(r,e,t);window.__piRefs[i]=r,h[i]={element:new WeakRef(r),role:e,name:t};let d=`${` `.repeat(l)}${e}`;if(t){let e=t.replace(/\s+/g,` `).replace(/"/g,`\\"`);d+=` "${e}"`}d+=` [${i}]`;let p=c(n);p&&(d+=` ${p}`),f(r)&&(d+=` [cursor=pointer]`);let m=r.getAttribute(`href`);m&&(d+=` href="${m}"`);let g=r.getAttribute(`type`);g&&(d+=` type="${g}"`);let _=r.getAttribute(`placeholder`);_&&(d+=` placeholder="${_}"`),u.push(d)}if(l<t)for(let e of r.children)u.push(...m(e,g?l+1:l));return u}function h(e){return e.replace(/\[e\d+\]/g,`[REF]`)}function g(e){let t=new Map;for(let n of e){if(!n.trim())continue;let e=h(n);t.set(e,(t.get(e)||0)+1)}return t}function _(e,t){let n=e.split(`
|
|
111
|
+
`),r=t.split(`
|
|
112
|
+
`),i=g(n),a=g(r),o=[],s=[];for(let e of r){if(!e.trim())continue;let t=h(e),n=i.get(t)||0;(a.get(t)||0)>n&&(o.push(e),i.set(t,n+1))}let c=g(n);for(let e of n){if(!e.trim())continue;let t=h(e),n=c.get(t)||0;n>(a.get(t)||0)&&(s.push(e),c.set(t,n-1))}if(o.length===0&&s.length===0)return{diff:`[NO CHANGES]`,hasChanges:!1};let l=[];return s.length>0&&l.push(...s.map(e=>`- ${e}`)),o.length>0&&l.push(...o.map(e=>`+ ${e}`)),{diff:l.join(`
|
|
113
|
+
`),hasChanges:!0}}let v=N(),y=null;if(n){let e=v[n];if(!e)return{error:`Element with ref_id '${n}' not found. Use read_page without ref_id to get current elements.`,pageContent:``,viewport:{width:window.innerWidth,height:window.innerHeight}};let t=e.element.deref();if(!t)return delete v[n],{error:`Element with ref_id '${n}' no longer exists. Use read_page without ref_id to get current elements.`,pageContent:``,viewport:{width:window.innerWidth,height:window.innerHeight}};y=t}else y=document.body;let b=y?m(y,0):[];for(let e of Object.keys(v))v[e].element.deref()||delete v[e];let x=b.join(`
|
|
114
|
+
`);if(x.length>5e4)return{error:`Output exceeds 50000 character limit (${x.length} characters). Try using filter="interactive" or specify a ref_id.`,pageContent:``,viewport:{width:window.innerWidth,height:window.innerHeight}};let S=j(),C,w=!1,T=window.__piLastSnapshot;return!r&&!n&&T&&Date.now()-T.timestamp<5e3&&(C=_(T.content,x).diff,w=!0),window.__piLastSnapshot={content:x,timestamp:Date.now()},{pageContent:x+`\n\n[Viewport: ${window.innerWidth}x${window.innerHeight}]`,diff:w?C:void 0,viewport:{width:window.innerWidth,height:window.innerHeight},modalStates:S.length>0?S:void 0,modalLimitations:`Only custom modals ([role=dialog]) detected. Native alert/confirm/prompt dialogs and system file choosers cannot be detected from content scripts.`,isIncremental:w}}catch(e){return{error:`Error generating accessibility tree: ${e instanceof Error?e.message:`Unknown error`}`,pageContent:``,viewport:{width:window.innerWidth,height:window.innerHeight}}}}function F(e){return e.length?/[\n\r]/.test(e)||/^[\s]/.test(e)||/[\s]$/.test(e)||/[:"{}[\]]/.test(e)?`"`+e.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`).replace(/\n/g,`\\n`).replace(/\r/g,`\\r`)+`"`:e:`""`}function I(e=`interactive`,t=15){try{window.__piRefs={};let n=[];function r(e){return D(e)}function i(e){let t=e.tagName.toLowerCase(),n=e.getAttribute(`aria-labelledby`);if(n){let e=n.split(/\s+/).map(e=>document.getElementById(e)?.textContent?.trim()||``).filter(Boolean);if(e.length){let t=e.join(` `);return t.length>100?t.substring(0,100)+`...`:t}}if(t===`select`){let t=e,n=t.querySelector(`option[selected]`)||(t.selectedIndex>=0?t.options[t.selectedIndex]:null);if(n?.textContent?.trim())return n.textContent.trim()}let r=e.getAttribute(`aria-label`);if(r?.trim())return r.trim();let i=e.getAttribute(`placeholder`);if(i?.trim())return i.trim();let a=e.getAttribute(`title`);if(a?.trim())return a.trim();let o=e.getAttribute(`alt`);if(o?.trim())return o.trim();if(e.id){let t=document.querySelector(`label[for="${e.id}"]`);if(t?.textContent?.trim())return t.textContent.trim()}if(t===`input`){let t=e,n=e.getAttribute(`type`)||``,r=e.getAttribute(`value`);if(n===`submit`&&r?.trim())return r.trim();if(t.value&&t.value.length<50&&t.value.trim())return t.value.trim()}if([`button`,`a`,`summary`].includes(t)){let t=e.textContent||``;if(t.trim())return t.trim()}if(/^h[1-6]$/.test(t)){let t=e.textContent;if(t?.trim()){let e=t.trim();return e.length>100?e.substring(0,100)+`...`:e}}if(t===`img`)return``;let s=``;for(let t of e.childNodes)t.nodeType===Node.TEXT_NODE&&(s+=t.textContent);if(s?.trim()&&s.trim().length>=3){let e=s.trim();return e.length>100?e.substring(0,100)+`...`:e}return``}function a(e){let t={},n=e.getAttribute(`aria-checked`);n===`true`?t.checked=!0:n===`false`?t.checked=!1:n===`mixed`?t.checked=`mixed`:e instanceof HTMLInputElement&&(e.type===`checkbox`||e.type===`radio`)&&(t.checked=e.type===`checkbox`&&e.indeterminate?`mixed`:e.checked);let r=e instanceof HTMLButtonElement||e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement;(e.getAttribute(`aria-disabled`)===`true`||r&&e.disabled||e.closest(`fieldset:disabled`))&&(t.disabled=!0);let i=e.getAttribute(`aria-expanded`);i===`true`?t.expanded=!0:i===`false`&&(t.expanded=!1);let a=e.getAttribute(`aria-pressed`);a===`true`?t.pressed=!0:a===`false`?t.pressed=!1:a===`mixed`&&(t.pressed=`mixed`);let o=e.getAttribute(`aria-selected`);o===`true`?t.selected=!0:o===`false`&&(t.selected=!1);let s=e.getAttribute(`aria-current`);s&&s!==`false`&&(t.active=!0);let c=e.tagName.toLowerCase();if(/^h[1-6]$/.test(c))t.level=parseInt(c[1],10);else{let n=e.getAttribute(`aria-level`);n&&(t.level=parseInt(n,10))}return t}function o(e){let t=[];return e.checked!==void 0&&t.push(e.checked===`mixed`?`[checked=mixed]`:e.checked?`[checked]`:`[unchecked]`),e.disabled&&t.push(`[disabled]`),e.expanded!==void 0&&t.push(e.expanded?`[expanded]`:`[collapsed]`),e.pressed!==void 0&&t.push(e.pressed===`mixed`?`[pressed=mixed]`:e.pressed?`[pressed]`:`[not-pressed]`),e.selected!==void 0&&t.push(e.selected?`[selected]`:`[not-selected]`),e.active&&t.push(`[active]`),e.level!==void 0&&t.push(`[level=${e.level}]`),t.join(` `)}function s(e){let t=window.getComputedStyle(e);return t.display!==`none`&&t.visibility!==`hidden`&&t.opacity!==`0`&&e.offsetWidth>0&&e.offsetHeight>0}function c(e){let t=e.tagName.toLowerCase();return[`a`,`button`,`input`,`select`,`textarea`,`details`,`summary`].includes(t)||e.hasAttribute(`onclick`)||e.hasAttribute(`tabindex`)||e.getAttribute(`role`)===`button`||e.getAttribute(`role`)===`link`||e.getAttribute(`contenteditable`)===`true`}function l(e){let t=e.tagName.toLowerCase();return[`h1`,`h2`,`h3`,`h4`,`h5`,`h6`,`nav`,`main`,`header`,`footer`,`section`,`article`,`aside`].includes(t)||e.hasAttribute(`role`)}function u(e){return window.getComputedStyle(e).cursor===`pointer`}function d(e,t,n,r){let i=e;t&&(i+=` `+F(t));let a=A(n,e,t);window.__piRefs[a]=n,i+=` [ref=${a}]`;let s=o(r);return s&&(i+=` ${s}`),u(n)&&(i+=` [cursor=pointer]`),i}function f(e){let t={},n=e.getAttribute(`href`);n&&(t.url=n);let r=e.getAttribute(`placeholder`);return r&&(t.placeholder=r),t}function p(o,u,m){if(u>t)return;let h=o.tagName.toLowerCase();if([`script`,`style`,`meta`,`link`,`title`,`noscript`].includes(h)||e!==`all`&&o.getAttribute(`aria-hidden`)===`true`||e!==`all`&&!s(o))return;if(e!==`all`){let e=o.getBoundingClientRect();if(!(e.top<window.innerHeight&&e.bottom>0&&e.left<window.innerWidth&&e.right>0))return}let g=r(o),_=i(o),v=a(o),y=c(o),b=l(o),x=_.length>0,S;if(S=e===`interactive`?y:e===`all`||y||b||x||g!==`generic`&&g!==`img`,S){let e=` `.repeat(u),t=d(g,_,o,v),r=f(o),i=[];for(let e of o.children)i.push(e);let a=i.length>0,s=Object.keys(r).length>0;if(!a&&!s)n.push(`${e}- ${t}`);else{n.push(`${e}- ${t}:`);for(let[t,i]of Object.entries(r))n.push(`${e} - /${t}: ${F(i)}`);for(let e of i)p(e,u+1,!0)}}else for(let e of o.children)p(e,u,m)}p(document.body,0,!1);let m=n.join(`
|
|
115
|
+
`);return m.length>5e4?{error:`Output exceeds 50000 character limit (${m.length} characters). Try using filter="interactive".`,yaml:``,viewport:{width:window.innerWidth,height:window.innerHeight}}:{yaml:m+`\n\n[Viewport: ${window.innerWidth}x${window.innerHeight}]`,viewport:{width:window.innerWidth,height:window.innerHeight}}}catch(e){return{error:`Error generating YAML tree: ${e instanceof Error?e.message:`Unknown error`}`,yaml:``,viewport:{width:window.innerWidth,height:window.innerHeight}}}}function L(e){let t=N(),n=t[e],r;if(n&&(r=n.element.deref(),r||delete t[e]),!r&&window.__piRefs&&(r=window.__piRefs[e]),!r)return{x:0,y:0,error:`Element ${e} not found. Use read_page to get current elements.`};let i=r.getBoundingClientRect();return{x:Math.round(i.left+i.width/2),y:Math.round(i.top+i.height/2)}}function R(e,t){let n=N(),r=n[e],i;if(r&&(i=r.element.deref(),i||delete n[e]),!i&&window.__piRefs&&(i=window.__piRefs[e]),!i)return{success:!1,error:`Element ${e} not found. Use read_page to get current elements.`};let a=i.tagName.toLowerCase();try{if(a===`input`){let e=i,n=e.type.toLowerCase();n===`checkbox`||n===`radio`?(e.checked=!!t,e.dispatchEvent(new Event(`change`,{bubbles:!0}))):(e.value=String(t),e.dispatchEvent(new Event(`input`,{bubbles:!0})),e.dispatchEvent(new Event(`change`,{bubbles:!0})))}else if(a===`textarea`){let e=i;e.value=String(t),e.dispatchEvent(new Event(`input`,{bubbles:!0})),e.dispatchEvent(new Event(`change`,{bubbles:!0}))}else if(a===`select`){let n=i,r=String(t),a=!1;for(let e of n.options)if(e.value===r||e.textContent?.trim()===r){n.value=e.value,a=!0;break}if(!a)return{success:!1,error:`Option "${t}" not found in select element ${e}`};n.dispatchEvent(new Event(`change`,{bubbles:!0}))}else if(i.getAttribute(`contenteditable`)===`true`)i.textContent=String(t),i.dispatchEvent(new Event(`input`,{bubbles:!0}));else return{success:!1,error:`Element ${e} (${a}) is not a form field`};return{success:!0}}catch(e){return{success:!1,error:`Failed to set value: ${e instanceof Error?e.message:`Unknown error`}`}}}function z(e,t,n=!0,r=!1){try{let i=document.querySelector(e);if(!i)return{success:!1,error:`Element not found: ${e}`};let a=i.querySelector(`[contenteditable="true"]`),o=a||i,s=i.isContentEditable||!!a;if(o.focus(),n&&(s?o.textContent=``:o.value=``),s?o.textContent=t:o.value=t,o.dispatchEvent(new Event(`input`,{bubbles:!0})),o.dispatchEvent(new Event(`change`,{bubbles:!0})),r){let e=i.closest(`form`),t=e?.querySelector(`button[type="submit"], input[type="submit"]`)||document.querySelector(`button[type="submit"], button[data-testid*="send"], button[aria-label*="Send"]`);t?t.click():e?e.dispatchEvent(new Event(`submit`,{bubbles:!0})):o.dispatchEvent(new KeyboardEvent(`keydown`,{key:`Enter`,code:`Enter`,keyCode:13,bubbles:!0}))}return{success:!0,contentEditable:s}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}function B(e,t){let n=new TextEncoder().encode(e);if(n.length<=t)return e;let r=t;for(;r>0&&(n[r]&192)==128;)r--;return new TextDecoder(`utf-8`,{fatal:!1}).decode(n.subarray(0,r))}function V(e={}){try{let t=document.querySelector(`article`),n=document.querySelector(`main`),r=(t||n||document.body).textContent?.replace(/\s+/g,` `).trim()||``;return{text:Number.isFinite(e.maxBytes)&&e.maxBytes>0?B(r,e.maxBytes):r.substring(0,5e4),title:document.title,url:window.location.href}}catch(e){return{text:``,title:``,url:``,error:`Failed to extract text: ${e instanceof Error?e.message:`Unknown error`}`}}}function H(e){let t=N(),n=t[e],r;return n&&(r=n.element.deref(),r||delete t[e]),!r&&window.__piRefs&&(r=window.__piRefs[e]),r?(r.scrollIntoView({behavior:`smooth`,block:`center`}),{success:!0}):{success:!1,error:`Element ${e} not found. Run read_page to get current element refs.`}}function U(e,t,n,r=`screenshot.png`){try{let i=atob(e),a=new ArrayBuffer(i.length),o=new Uint8Array(a);for(let e=0;e<i.length;e++)o[e]=i.charCodeAt(e);let s=new Blob([a],{type:`image/png`}),c=new File([s],r,{type:`image/png`}),l=null;if(t){let e=N(),n=e[t];if(n&&(l=n.element.deref(),l||delete e[t]),!l&&window.__piRefs&&(l=window.__piRefs[t]),!l)return{success:!1,error:`Element ${t} not found. Run read_page to get current element refs.`}}else if(n&&(l=document.elementFromPoint(n[0],n[1]),!l))return{success:!1,error:`No element at (${n[0]}, ${n[1]})`};if(!l)return{success:!1,error:`No target element`};if(l.tagName===`INPUT`&&l.type===`file`){let e=l,t=new DataTransfer;return t.items.add(c),e.files=t.files,e.dispatchEvent(new Event(`change`,{bubbles:!0})),{success:!0}}let u=new DataTransfer;u.items.add(c);let d=new DragEvent(`drop`,{bubbles:!0,cancelable:!0,dataTransfer:u});return l.dispatchEvent(d),{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:`Upload failed`}}}var W=null;function G(e){if(e.id)return`#${CSS.escape(e.id)}`;for(let t of[`data-testid`,`data-test-id`,`name`,`aria-label`]){let n=e.getAttribute(t);if(n)return`${e.tagName.toLowerCase()}[${t}=${JSON.stringify(n)}]`}return e.tagName.toLowerCase()}function K(e,t,n){W&&chrome.runtime.sendMessage({type:`PLAYBOOK_WATCH_EVENT`,event:e,selector:t?G(t):void 0,value:n,url:location.href,timestamp:new Date().toISOString()}).catch(()=>{})}typeof document.addEventListener==`function`&&(document.addEventListener(`click`,e=>{e.isTrusted&&e.target instanceof Element&&K(`click`,e.target)},!0),document.addEventListener(`change`,e=>{if(!e.isTrusted||!(e.target instanceof HTMLInputElement||e.target instanceof HTMLTextAreaElement||e.target instanceof HTMLSelectElement))return;let t=e.target,n=t instanceof HTMLInputElement&&t.type===`password`;K(`input`,t,W?.includeInputValues&&!n?t.value:`<input>`)},!0)),typeof window.addEventListener==`function`&&(window.addEventListener(`popstate`,()=>K(`navigation`)),window.addEventListener(`hashchange`,()=>K(`navigation`))),chrome.runtime.onMessage.addListener((e,t,n)=>{switch(e.type){case`PLAYBOOK_WATCH_START`:W={includeInputValues:e.includeInputValues===!0},n({success:!0});break;case`PLAYBOOK_WATCH_STOP`:W=null,n({success:!0});break;case`SHOW_AGENT_INDICATORS`:case`HIDE_AGENT_INDICATORS`:case`HIDE_FOR_TOOL_USE`:case`SHOW_AFTER_TOOL_USE`:case`SHOW_STATIC_INDICATOR`:case`HIDE_STATIC_INDICATOR`:if(!window.__piVisualIndicatorMessageHandler){n({error:`Visual indicator content script not loaded.`});break}window.__piVisualIndicatorMessageHandler(e.type),n({success:!0});break;case`GENERATE_ACCESSIBILITY_TREE`:{let t=e.options||{};if(t.format===`yaml`){let e=I(t.filter||`interactive`,t.depth??15),r=j();e.error?n({error:e.error,pageContent:``,viewport:e.viewport}):n({pageContent:e.yaml,viewport:e.viewport,modalStates:r.length>0?r:void 0,modalLimitations:`Only custom modals ([role=dialog]) detected. Native alert/confirm/prompt dialogs and system file choosers cannot be detected from content scripts.`})}else n(P(t.filter||`interactive`,t.depth??15,t.refId,t.forceFullSnapshot??!1,t.compact??!1));break}case`GET_ELEMENT_COORDINATES`:n(L(e.ref));break;case`CLICK_ELEMENT`:{let t=N(),r=t[e.ref],i;if(r&&(i=r.element.deref(),i||delete t[e.ref]),!i&&window.__piRefs&&(i=window.__piRefs[e.ref]),!i){n({error:`Element ${e.ref} not found. Use read_page to get current elements.`});break}if(e.button===`triple`){let e=new MouseEvent(`click`,{bubbles:!0,cancelable:!0,view:window,detail:3});i.dispatchEvent(e)}else e.button===`double`?i.dispatchEvent(new MouseEvent(`dblclick`,{bubbles:!0,cancelable:!0,view:window})):e.button===`right`?i.dispatchEvent(new MouseEvent(`contextmenu`,{bubbles:!0,cancelable:!0,view:window})):i.click();n({success:!0});break}case`FORM_INPUT`:n(R(e.ref,e.value));break;case`EVAL_IN_PAGE`:try{let t=document.createElement(`script`);t.textContent=`(function() { ${e.code} })();`,document.documentElement.appendChild(t),t.remove(),n({success:!0})}catch(e){n({success:!1,error:e instanceof Error?e.message:String(e)})}break;case`GET_PAGE_TEXT`:n(V(e.options||{}));break;case`SMART_TYPE`:n(z(e.selector,e.text,e.clear,e.submit));break;case`GET_FRAME_BY_SELECTOR`:try{let t=document.querySelector(e.selector);if(!t||t.tagName.toLowerCase()!==`iframe`){n({error:`No iframe found with selector "${e.selector}"`});break}n({url:t.src,name:t.name||void 0})}catch(e){n({error:e instanceof Error?e.message:String(e)})}break;case`GET_FRAME_NAME`:try{n({name:window.name||null})}catch{n({name:null})}break;case`LOCATE_ROLE`:try{let{role:t,name:r,all:i}=e,a=N(),o={button:[`button`,`input[type="button"]`,`input[type="submit"]`,`input[type="reset"]`,`[role="button"]`],link:[`a[href]`,`[role="link"]`],textbox:[`input:not([type])`,`input[type="text"]`,`input[type="email"]`,`input[type="password"]`,`input[type="search"]`,`input[type="tel"]`,`input[type="url"]`,`textarea`,`[role="textbox"]`],checkbox:[`input[type="checkbox"]`,`[role="checkbox"]`],radio:[`input[type="radio"]`,`[role="radio"]`],combobox:[`select`,`[role="combobox"]`],listbox:[`[role="listbox"]`,`select[multiple]`],option:[`option`,`[role="option"]`],heading:[`h1`,`h2`,`h3`,`h4`,`h5`,`h6`,`[role="heading"]`],navigation:[`nav`,`[role="navigation"]`],main:[`main`,`[role="main"]`],img:[`img[alt]`,`[role="img"]`],dialog:[`dialog`,`[role="dialog"]`,`[role="alertdialog"]`],tab:[`[role="tab"]`],tabpanel:[`[role="tabpanel"]`],menu:[`[role="menu"]`],menuitem:[`[role="menuitem"]`]}[t]||[`[role="${t}"]`],s=[];for(let e of o)try{s.push(...document.querySelectorAll(e))}catch{}let c=s.filter(e=>{let t=window.getComputedStyle(e);return t.display!==`none`&&t.visibility!==`hidden`&&e.offsetWidth>0&&e.offsetHeight>0}),l=c;if(r){let e=r.toLowerCase();l=c.filter(t=>{let n=t.getAttribute(`aria-label`)?.toLowerCase(),r=t.textContent?.trim().toLowerCase(),i=t.getAttribute(`title`)?.toLowerCase(),a=t.placeholder?.toLowerCase(),o=t.value?.toLowerCase();return n?.includes(e)||r?.includes(e)||i?.includes(e)||a?.includes(e)||o?.includes(e)})}if(l.length===0){n({error:`No element found with role "${t}"${r?` and name "${r}"`:``}`});break}let u=l.map(e=>{let n=A(e,t,r||``);return window.__piRefs=window.__piRefs||{},window.__piRefs[n]=e,a[n]={element:new WeakRef(e),role:t,name:r||``},{ref:n,text:e.textContent?.trim().slice(0,50)}});n(i?{matches:u}:{ref:u[0].ref,text:u[0].text})}catch(e){n({error:e instanceof Error?e.message:String(e)})}break;case`LOCATE_TEXT`:try{let{text:t,exact:r}=e,i=N(),a=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT),o=[];for(;a.nextNode();){let e=a.currentNode.textContent||``;if(r?e.trim()===t:e.toLowerCase().includes(t.toLowerCase())){let e=a.currentNode.parentElement;if(e&&!o.includes(e)){let t=window.getComputedStyle(e);t.display!==`none`&&t.visibility!==`hidden`&&o.push(e)}}}if(o.length===0){n({error:`No element found with text "${t}"`});break}let s=o.sort((e,t)=>(e.textContent?.length||0)-(t.textContent?.length||0))[0],c=D(s),l=A(s,c,t);window.__piRefs=window.__piRefs||{},window.__piRefs[l]=s,i[l]={element:new WeakRef(s),role:c,name:t},n({ref:l,text:s.textContent?.trim().slice(0,50)})}catch(e){n({error:e instanceof Error?e.message:String(e)})}break;case`LOCATE_LABEL`:try{let{label:t}=e,r=N(),i=document.querySelectorAll(`label`),a=null;for(let e of i)if((e.textContent?.trim().toLowerCase())?.includes(t.toLowerCase())){let t=e.getAttribute(`for`);if(t&&(a=document.getElementById(t)),a||=e.querySelector(`input, select, textarea`),a)break}if(a||=(t.toLowerCase(),document.querySelector(`input[aria-label*="${t}" i], input[placeholder*="${t}" i], textarea[aria-label*="${t}" i], textarea[placeholder*="${t}" i], select[aria-label*="${t}" i]`)),!a){n({error:`No form field found with label "${t}"`});break}let o=D(a),s=A(a,o,t);window.__piRefs=window.__piRefs||{},window.__piRefs[s]=a,r[s]={element:new WeakRef(a),role:o,name:t},n({ref:s,label:t})}catch(e){n({error:e instanceof Error?e.message:String(e)})}break;case`GET_ELEMENT_STYLES`:try{let{selector:t}=e,r=N(),i=e=>{let t=getComputedStyle(e),n=e.getBoundingClientRect();return{tag:e.tagName.toLowerCase(),text:e.innerText?.trim().slice(0,80)||null,box:{x:Math.round(n.x),y:Math.round(n.y),width:Math.round(n.width),height:Math.round(n.height)},styles:{fontSize:t.fontSize,fontWeight:t.fontWeight,fontFamily:t.fontFamily.split(`,`)[0].trim().replace(/"/g,``),color:t.color,backgroundColor:t.backgroundColor,borderRadius:t.borderRadius,border:t.border!==`none`&&t.borderWidth!==`0px`?t.border:null,boxShadow:t.boxShadow===`none`?null:t.boxShadow,padding:t.padding}}};if(/^e\d+$/.test(t)){let e=r[t],a;if(e&&(a=e.element.deref(),a||delete r[t]),!a&&window.__piRefs&&(a=window.__piRefs[t]),!a){n({error:`Element ${t} not found`});break}n({styles:[i(a)]})}else{let e=document.querySelectorAll(t);if(e.length===0){n({error:`No elements found matching "${t}"`});break}n({styles:Array.from(e).map(i)})}}catch(e){n({error:e instanceof Error?e.message:String(e)})}break;case`SELECT_OPTION`:try{let{selector:t,values:r,by:i}=e,a=N(),o=null;if(/^e\d+$/.test(t)){let e=a[t],r;if(e&&(r=e.element.deref(),r||delete a[t]),!r&&window.__piRefs&&(r=window.__piRefs[t]),!r){n({error:`Element ${t} not found`});break}if(r.tagName!==`SELECT`){n({error:`Element ${t} is not a <select>`});break}o=r}else{if(o=document.querySelector(t),!o){n({error:`No element found matching "${t}"`});break}if(o.tagName!==`SELECT`){n({error:`Element "${t}" is not a <select>`});break}}if(o.multiple)for(let e of o.options)e.selected=!1;let s=[],c=[],l=o.multiple?r:[r[0]];for(let e of l){let t=!1;for(let n of o.options){let r=!1;if(r=i===`index`?n.index===parseInt(e,10):i===`label`?n.text.toLowerCase().includes(e.toLowerCase()):n.value===e,r){n.selected=!0,s.push(n.value),t=!0;break}}t||c.push(e)}o.dispatchEvent(new Event(`change`,{bubbles:!0})),c.length>0?n({selected:s,warning:`Values not found: ${c.join(`, `)}`}):n({selected:s})}catch(e){n({error:e instanceof Error?e.message:String(e)})}break;case`GET_ELEMENT_TEXT`:try{let{ref:t}=e,r=N(),i=r[t],a;if(i&&(a=i.element.deref(),a||delete r[t]),!a&&window.__piRefs&&(a=window.__piRefs[t]),!a){n({error:`Element ${t} not found`});break}n({text:a.textContent?.trim()||``})}catch(e){n({error:e instanceof Error?e.message:String(e)})}break;case`SCROLL_TO_ELEMENT`:n(H(e.ref));break;case`UPLOAD_IMAGE`:n(U(e.base64,e.ref,e.coordinate,e.filename));break;case`WAIT_FOR_ELEMENT`:{let{selector:t,state:r=`visible`,timeout:i=2e4}=e,a=Math.min(i,6e4),o=e=>{if(!e)return!1;let t=window.getComputedStyle(e);return t.display!==`none`&&t.visibility!==`hidden`&&t.opacity!==`0`&&e.offsetWidth>0&&e.offsetHeight>0},s=()=>{let e=document.querySelector(t);switch(r){case`attached`:return!!e;case`detached`:return!e;case`hidden`:return!e||!o(e);default:return o(e)}},c=Date.now();return new Promise(e=>{if(s()){e({success:!0,waited:Date.now()-c});return}let n=new MutationObserver(()=>{s()&&(n.disconnect(),clearTimeout(i),e({success:!0,waited:Date.now()-c}))}),i=setTimeout(()=>{n.disconnect(),e({success:!1,waited:Date.now()-c,error:`Timeout waiting for "${t}" to be ${r}`})},a);n.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`style`,`class`,`hidden`,`disabled`]})}).then(e=>{if(!e.success){n({error:e.error,waited:e.waited,pageContent:``,viewport:{width:window.innerWidth,height:window.innerHeight}});return}n({...P(`interactive`,15,void 0,!0),waited:e.waited})}),!0}case`WAIT_FOR_URL`:{let{pattern:t,timeout:r=2e4}=e,i=Math.min(r,6e4),a=e=>{if(t.includes(`*`)){let n=t.replace(/[.+?^${}()|[\]\\]/g,`\\$&`).replace(/\*\*/g,`<<<GLOBSTAR>>>`).replace(/\*/g,`[^/]*`).replace(/<<<GLOBSTAR>>>/g,`.*`);return RegExp(`^${n}$`).test(e)}return e.includes(t)},o=Date.now();return new Promise(e=>{if(a(window.location.href)){e({success:!0,waited:Date.now()-o});return}let n=!1,r=()=>{n||a(window.location.href)&&(n=!0,clearInterval(s),clearTimeout(c),window.removeEventListener(`popstate`,r),window.removeEventListener(`hashchange`,r),e({success:!0,waited:Date.now()-o}))},s=setInterval(r,100),c=setTimeout(()=>{n||(n=!0,clearInterval(s),window.removeEventListener(`popstate`,r),window.removeEventListener(`hashchange`,r),e({success:!1,waited:Date.now()-o,error:`Timeout waiting for URL to match "${t}". Current: ${window.location.href}`}))},i);window.addEventListener(`popstate`,r),window.addEventListener(`hashchange`,r)}).then(e=>{if(!e.success){n({error:e.error,waited:e.waited,pageContent:``,viewport:{width:window.innerWidth,height:window.innerHeight}});return}n({...P(`interactive`,15,void 0,!0),waited:e.waited})}),!0}case`WAIT_FOR_DOM_STABLE`:{let{stable:t=100,timeout:r=5e3}=e,i=Math.min(r,3e4),a=Date.now();return new Promise(e=>{let n=Date.now(),r=!1,o=()=>{r||Date.now()-n>=t&&(r=!0,s.disconnect(),clearTimeout(c),clearInterval(l),e({success:!0,waited:Date.now()-a}))},s=new MutationObserver(()=>{n=Date.now()}),c=setTimeout(()=>{r||(r=!0,s.disconnect(),clearInterval(l),e({success:!1,waited:Date.now()-a,error:`Timeout: DOM did not stabilize within ${i}ms`}))},i),l=setInterval(o,Math.max(10,Math.min(50,t/2)));s.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0,characterData:!0}),o()}).then(e=>{if(!e.success){n({error:e.error,waited:e.waited,pageContent:``,viewport:{width:window.innerWidth,height:window.innerHeight}});return}n({...P(`interactive`,15,void 0,!0),waited:e.waited})}),!0}case`FORM_FILL`:{let{data:t}=e;if(!Array.isArray(t))return n({error:`data must be an array of {ref, value} pairs`}),!0;let r=N(),i=[];for(let e of t){let{ref:t,value:n}=e;if(!t){i.push({ref:t||`unknown`,success:!1,error:`Missing ref`});continue}let a=r[t];if(!a){i.push({ref:t,success:!1,error:`Element not found (run page.read first)`});continue}let o=a.element.deref();if(!o){delete r[t],i.push({ref:t,success:!1,error:`Element no longer exists`});continue}try{if(o instanceof HTMLInputElement){let e=o.type.toLowerCase();e===`checkbox`||e===`radio`?(o.checked=n===!0||n===`true`||n===`1`||n===`checked`,o.dispatchEvent(new Event(`change`,{bubbles:!0}))):(o.focus(),o.value=String(n),o.dispatchEvent(new Event(`input`,{bubbles:!0})),o.dispatchEvent(new Event(`change`,{bubbles:!0}))),i.push({ref:t,success:!0})}else o instanceof HTMLTextAreaElement?(o.focus(),o.value=String(n),o.dispatchEvent(new Event(`input`,{bubbles:!0})),o.dispatchEvent(new Event(`change`,{bubbles:!0})),i.push({ref:t,success:!0})):o instanceof HTMLSelectElement?(o.value=String(n),o.dispatchEvent(new Event(`change`,{bubbles:!0})),i.push({ref:t,success:!0})):o.isContentEditable?(o.focus(),o.textContent=String(n),o.dispatchEvent(new Event(`input`,{bubbles:!0})),i.push({ref:t,success:!0})):i.push({ref:t,success:!1,error:`Element is not fillable`})}catch(e){i.push({ref:t,success:!1,error:e instanceof Error?e.message:String(e)})}}let a=i.filter(e=>!e.success);return n({success:a.length===0,filled:i.filter(e=>e.success).length,failed:a.length,results:i}),!0}case`GET_FILE_INPUT_SELECTOR`:{let{ref:t}=e;if(!t)return n({error:`No ref provided`}),!0;let r=N(),i=r[t];if(!i)return n({error:`Element not found (run page.read first)`}),!0;let a=i.element.deref();if(!a)return delete r[t],n({error:`Element no longer exists`}),!0;if(!(a instanceof HTMLInputElement)||a.type!==`file`)return n({error:`Element is not a file input`}),!0;let o=`__pi_file_${Date.now()}`;return a.setAttribute(`data-pi-file-id`,o),n({selector:`[data-pi-file-id="${o}"]`}),!0}case`WAIT_FOR_NETWORK_IDLE`:{let{timeout:t=1e4}=e,r=Math.min(t,6e4),i=[`doubleclick.net`,`googlesyndication.com`,`googletagmanager.com`,`google-analytics.com`,`facebook.net`,`connect.facebook.net`,`analytics`,`ads`,`tracking`,`pixel`,`hotjar.com`,`clarity.ms`,`mixpanel.com`,`segment.com`,`newrelic.com`,`nr-data.net`,`/tracker/`,`/collector/`,`/beacon/`,`/telemetry/`,`/log/`,`/events/`,`/track.`,`/metrics/`],a=[`img`,`image`,`font`,`icon`],o=e=>i.some(t=>e.includes(t)),s=e=>{let t=e.initiatorType||`unknown`;return!!(a.includes(t)||/\.(jpg|jpeg|png|gif|webp|svg|ico|woff|woff2|ttf|eot)(\?|$)/i.test(e.name))},c=()=>{let e=performance.now();return performance.getEntriesByType(`resource`).filter(t=>{if(t.responseEnd!==0||t.name.startsWith(`data:`)||t.name.length>500||o(t.name))return!1;let n=e-t.startTime;return!(n>1e4||s(t)&&n>3e3)})},l=Date.now();return new Promise(e=>{let t=()=>{let n=c(),i=Date.now()-l;if(n.length===0){e({success:!0,waited:i});return}if(i>=r){e({success:!1,waited:i,pendingCount:n.length});return}setTimeout(t,100)};t()}).then(e=>{if(!e.success){n({error:`Network not idle after ${e.waited}ms (${e.pendingCount} requests pending)`,waited:e.waited,pageContent:``,viewport:{width:window.innerWidth,height:window.innerHeight}});return}n({...P(`interactive`,15,void 0,!0),waited:e.waited})}),!0}case`SEARCH_PAGE`:{let{term:t,caseSensitive:r,limit:i}=e,a=q(t,r||!1,i||10);n({query:t,count:a.length,matches:a});break}case`GET_ELEMENT_BOUNDS_FOR_ANNOTATION`:{let e=N(),t=[];for(let[n,r]of Object.entries(e)){let e=r.element.deref();if(!e)continue;let i=e.getBoundingClientRect();i.width<=0||i.height<=0||i.bottom<0||i.top>window.innerHeight||i.right<0||i.left>window.innerWidth||t.push({ref:n,tag:e.tagName.toLowerCase(),bounds:{x:i.x,y:i.y,width:i.width,height:i.height}})}n({elements:t});break}default:return!1}return!1});function q(e,t,n){let r=[],i=t?e:e.toLowerCase(),a=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT),o=N(),s=0;for(;a.nextNode()&&r.length<n;){let c=a.currentNode,l=c.textContent||``,u=t?l:l.toLowerCase(),d=0;for(;(d=u.indexOf(i,d))!==-1&&r.length<n;){let t=c.parentElement;if(!t){d++;continue}let n=document.createRange();n.setStart(c,d),n.setEnd(c,Math.min(d+e.length,l.length));let i=n.getBoundingClientRect();if(i.width===0||i.height===0){d++;continue}let a=c.textContent||``,u=Math.max(0,d-30),f=Math.min(a.length,d+e.length+30),p=a.slice(u,f).trim(),m=null;for(let[e,n]of Object.entries(o)){let r=n.element.deref();if(r&&(r===t||r.contains(t))){m=e;break}}r.push({ref:`m${++s}`,text:a.slice(d,d+e.length),context:p,bounds:{x:Math.round(i.x),y:Math.round(i.y),width:Math.round(i.width),height:Math.round(i.height)},elementRef:m}),d++}}return r}
|
|
116
|
+
//# sourceMappingURL=index.js.map
|