Download tools/annotate_preview_tool.py from SaylorTwift/hermes-agent: direct link, hf CLI and curl.
- Browser
- Download file 3.95 kB
-
https://huggingface.co/SaylorTwift/hermes-agent/resolve/main/tools/annotate_preview_tool.py
- Command line
-
hf download hf://SaylorTwift/hermes-agent/tools/annotate_preview_tool.py
-
curl -L -o annotate_preview_tool.py https://huggingface.co/SaylorTwift/hermes-agent/resolve/main/tools/annotate_preview_tool.py
3.95 kB
| """Persistent element annotations in the Hermes desktop GUI's in-app browser. | |
| Unlike ``drive_preview``'s self-retiring marks, an annotation outlines an element | |
| (or, with ``hold``, the whole visible field) until removed. Annotations bind to | |
| elements, not coordinates: they ride scrolls and vanish with their element, so | |
| navigation clears them. Same ``preview.act`` bridge as ``drive_preview`` (the | |
| renderer resolves refs and owns the overlay). ``desktop_ui`` toolset only. | |
| """ | |
| import json | |
| from typing import Callable, Optional | |
| from tools.registry import registry, tool_error | |
| ACTIONS = ("add", "hold", "remove", "clear") | |
| # Renderer verbs keyed by ours; `clear` is `unpin` with no target = "all of them". | |
| WIRE = {"add": "pin", "hold": "hold", "remove": "unpin", "clear": "unpin"} | |
| def annotate_preview_tool( | |
| action: str = "add", ref: Optional[str] = None, selector: Optional[str] = None, | |
| label: Optional[str] = None, callback: Optional[Callable] = None, | |
| ) -> str: | |
| """Put one annotation up, take one down, or clear them all.""" | |
| if callback is None: | |
| return tool_error("annotate_preview is only available in the Hermes desktop app.") | |
| verb = (action or "add").strip().lower() | |
| if verb not in ACTIONS: | |
| return tool_error(f"action must be one of: {', '.join(ACTIONS)}.") | |
| if verb in ("add", "remove") and not (ref or selector): | |
| return tool_error(f"{verb} needs a ref from drive_preview action='elements' (e.g. 'btn-sign-in') or a CSS selector.") | |
| targeted = verb not in ("clear", "hold") | |
| fields = (("action", WIRE[verb]), ("ref", ref if targeted else None), ("selector", selector if targeted else None), ("text", label)) | |
| payload = {name: val for name, val in fields if val is not None} | |
| try: | |
| raw = callback(payload) | |
| except Exception as exc: | |
| return tool_error(f"Failed to annotate the in-app browser: {exc}") | |
| if not raw: | |
| return tool_error("The annotation timed out, or no GUI window answered. Open a page with open_preview first.") | |
| try: | |
| return json.dumps(json.loads(raw), ensure_ascii=False) | |
| except (TypeError, ValueError): | |
| return json.dumps({"text": str(raw)}, ensure_ascii=False) | |
| ANNOTATE_PREVIEW_SCHEMA = { | |
| "name": "annotate_preview", | |
| "description": ( | |
| "Highlight elements on the preview-pane page, lastingly (drive_preview's own " | |
| "marks fade; annotations stay until removed) โ point at findings, " | |
| "flag what you're about to change, keep your place. Use the refs " | |
| "from drive_preview action='elements'. add: outline one element " | |
| "(optional short label โ a word or two, drawn on the page). hold: " | |
| "freeze the whole visible field, every element outlined and named. " | |
| "remove/clear: take one/all down. Marks follow their element on " | |
| "scroll; navigation clears them." | |
| ), | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "action": { | |
| "type": "string", | |
| "enum": list(ACTIONS), | |
| "description": "Defaults to 'add'.", | |
| }, | |
| "ref": { | |
| "type": "string", | |
| "description": "Ref from drive_preview elements.", | |
| }, | |
| "selector": { | |
| "type": "string", | |
| "description": "CSS selector fallback. Prefer ref.", | |
| }, | |
| "label": { | |
| "type": "string", | |
| "description": "Optional caption, e.g. 'cheapest'.", | |
| }, | |
| }, | |
| "required": [], | |
| }, | |
| } | |
| registry.register( | |
| name="annotate_preview", | |
| toolset="desktop_ui", | |
| schema=ANNOTATE_PREVIEW_SCHEMA, | |
| handler=lambda args, **kw: annotate_preview_tool( | |
| action=args.get("action", "add"), | |
| ref=args.get("ref"), | |
| selector=args.get("selector"), | |
| label=args.get("label"), | |
| callback=kw.get("callback"), | |
| ), | |
| emoji="๐", | |
| ) | |