(opts: InstructionBlockOptions)
| 661 | |
| 662 | /** Pure function: generate a copy-pasteable instruction block for a remote agent. */ |
| 663 | export function generateInstructionBlock(opts: InstructionBlockOptions): string { |
| 664 | const { setupKey, serverUrl, scopes, expiresAt } = opts; |
| 665 | const scopeDesc = scopes.includes('admin') |
| 666 | ? 'read + write + admin access (can execute JS, read cookies, access storage)' |
| 667 | : 'read + write access (cannot execute JS, read cookies, or access storage)'; |
| 668 | |
| 669 | return `\ |
| 670 | ${'='.repeat(59)} |
| 671 | REMOTE BROWSER ACCESS |
| 672 | Paste this into your other AI agent's chat. |
| 673 | ${'='.repeat(59)} |
| 674 | |
| 675 | You can control a real Chromium browser via HTTP API. Navigate |
| 676 | pages, read content, click buttons, fill forms, take screenshots. |
| 677 | You get your own isolated tab. This setup key expires in 5 minutes. |
| 678 | |
| 679 | SERVER: ${serverUrl} |
| 680 | |
| 681 | STEP 1 — Exchange the setup key for a session token: |
| 682 | |
| 683 | curl -s -X POST \\ |
| 684 | -H "Content-Type: application/json" \\ |
| 685 | -d '{"setup_key": "${setupKey}"}' \\ |
| 686 | ${serverUrl}/connect |
| 687 | |
| 688 | Save the "token" value from the response. Use it as your |
| 689 | Bearer token for all subsequent requests. |
| 690 | |
| 691 | STEP 2 — Create your own tab (required before interacting): |
| 692 | |
| 693 | curl -s -X POST \\ |
| 694 | -H "Authorization: Bearer <TOKEN>" \\ |
| 695 | -H "Content-Type: application/json" \\ |
| 696 | -d '{"command": "newtab", "args": ["https://example.com"]}' \\ |
| 697 | ${serverUrl}/command |
| 698 | |
| 699 | Save the "tabId" from the response. Include it in every command. |
| 700 | |
| 701 | STEP 3 — Browse. The key pattern is snapshot then act: |
| 702 | |
| 703 | # Get an interactive snapshot with clickable @ref labels |
| 704 | curl -s -X POST \\ |
| 705 | -H "Authorization: Bearer <TOKEN>" \\ |
| 706 | -H "Content-Type: application/json" \\ |
| 707 | -d '{"command": "snapshot", "args": ["-i"], "tabId": <TAB>}' \\ |
| 708 | ${serverUrl}/command |
| 709 | |
| 710 | The snapshot returns labeled elements like: |
| 711 | @e1 [link] "Home" |
| 712 | @e2 [button] "Sign In" |
| 713 | @e3 [input] "Search..." |
| 714 | |
| 715 | Use those @refs to interact: |
| 716 | {"command": "click", "args": ["@e2"], "tabId": <TAB>} |
| 717 | {"command": "fill", "args": ["@e3", "query"], "tabId": <TAB>} |
| 718 | |
| 719 | Always snapshot first, then use the @refs. Don't guess selectors. |
| 720 |
no outgoing calls
no test coverage detected