97 lines
3.8 KiB
Org Mode
97 lines
3.8 KiB
Org Mode
:PROPERTIES:
|
|
:ID: playwright-bridge-skill
|
|
:CREATED: [2026-04-11 Sat 18:00]
|
|
:END:
|
|
#+TITLE: SKILL: Playwright-Python Bridge (Universal Literate Note)
|
|
#+STARTUP: content
|
|
#+FILETAGS: :intelligence:browsing:automation:psf:
|
|
|
|
* Overview
|
|
The *Playwright Bridge* provides high-fidelity web browsing capabilities by wrapping a headless Chromium instance managed via Python. It allows the agent to interact with JavaScript-heavy applications that are inaccessible to standard HTTP clients.
|
|
|
|
* Phase A: Demand (PRD)
|
|
:PROPERTIES:
|
|
:STATUS: SIGNED
|
|
:END:
|
|
|
|
** 1. Purpose
|
|
Enable the agent to "see" and "read" the modern web by executing JavaScript and waiting for network idle states.
|
|
|
|
** 2. Success Criteria
|
|
- [ ] *Interaction:* Can navigate to any URL and wait for full page rendering.
|
|
- [ ] *Extraction:* Can retrieve inner text from any CSS selector.
|
|
- [ ] *Vision:* Can take base64-encoded screenshots of rendered pages.
|
|
|
|
* Phase B: Blueprint (PROTOCOL)
|
|
:PROPERTIES:
|
|
:STATUS: SIGNED
|
|
:END:
|
|
|
|
** 1. Architectural Intent
|
|
Uses a "JSON Bridge" over standard I/O. The Lisp kernel executes a standalone Python script, passing parameters via `stdin` and receiving structured results via `stdout`.
|
|
|
|
** 2. Semantic Interfaces
|
|
- `(:target :tool :action :call :tool "browser" :args (:url "..." :action "extract_text"))`
|
|
|
|
* Phase D: Build (Implementation)
|
|
|
|
** Package Context
|
|
#+begin_src lisp :tangle ../src/playwright.lisp
|
|
(in-package :opencortex)
|
|
#+end_src
|
|
|
|
** Bridge Script Path
|
|
Calculates the location of the Python bridge script relative to the project root.
|
|
|
|
#+begin_src lisp :tangle ../src/playwright.lisp
|
|
(defun get-browser-bridge-path ()
|
|
"Returns the absolute path to the Python browser bridge script."
|
|
(let ((root (or (uiop:getenv "PROJECT_ROOT") (uiop:native-namestring (uiop:getcwd)))))
|
|
(merge-pathnames "scripts/browser-bridge.py" (uiop:ensure-directory-pathname root))))
|
|
#+end_src
|
|
|
|
** Execution Wrapper (execute-browser-command)
|
|
Invokes the Python bridge and parses its JSON output.
|
|
|
|
#+begin_src lisp :tangle ../src/playwright.lisp
|
|
(defun execute-browser-command (args)
|
|
"Invokes the Playwright Python bridge with the provided arguments."
|
|
(let* ((script-path (get-browser-bridge-path))
|
|
(json-input (cl-json:encode-json-to-string args)))
|
|
(handler-case
|
|
(let ((output (uiop:run-program (list "python3" (uiop:native-namestring script-path))
|
|
:input (make-string-input-stream json-input)
|
|
:output :string
|
|
:error-output :string)))
|
|
(cl-json:decode-json-from-string output))
|
|
(error (c)
|
|
(list :status "error" :message (format nil "Bridge Execution Failed: ~a" c))))))
|
|
#+end_src
|
|
|
|
** Cognitive Tool: Browser
|
|
Register the high-fidelity browsing tool with the harness.
|
|
|
|
#+begin_src lisp :tangle ../src/playwright.lisp
|
|
(def-cognitive-tool :browser
|
|
"High-fidelity web browsing via Playwright (Chromium). Supports JS rendering."
|
|
((:url :type :string :description "The target URL")
|
|
(:action :type :string :description "Action to perform: 'extract_text' or 'screenshot'")
|
|
(:selector :type :string :description "Optional CSS selector (default: 'body')"))
|
|
:body (lambda (args)
|
|
(let ((result (execute-browser-command args)))
|
|
(if (string= (cdr (assoc :status result)) "success")
|
|
(or (cdr (assoc :content result))
|
|
(cdr (assoc :screenshot--base64 result))
|
|
"Success (no content returned)")
|
|
(format nil "BROWSER ERROR: ~a" (cdr (assoc :message result)))))))
|
|
#+end_src
|
|
|
|
** Registration: Skill
|
|
#+begin_src lisp :tangle ../src/playwright.lisp
|
|
(defskill :skill-playwright
|
|
:priority 150
|
|
:trigger (lambda (ctx) (declare (ignore ctx)) nil) ; Passive tool provider
|
|
:neuro nil
|
|
:symbolic (lambda (action ctx) (declare (ignore ctx)) action))
|
|
#+end_src
|