Skip to content

camelot 0.4.0

Latest

Choose a tag to compare

@trans trans released this 23 Sep 01:32
· 8 commits to main since this release

Camelot can see now, as well as read.

camelot shot — one frame through the XDG desktop portal. No PipeWire negotiation, permission remembered after the first grant, and the desktop announces every capture its own way (on GNOME, the shutter flash and sound — a consent signal worth keeping). A 2560x1440 screen arrives as a ~145 kB JPEG scaled to fit --max-edge (1568 by default, as much as a vision model uses), in about 0.65s. --pick hands the choice of window or region to the desktop's own picker.

Capture is a pull, never a push. A frame is taken when something asks, handed over and dropped: nothing image-shaped enters the event stream or the daemon's history, where frames would cost more memory in a minute than the whole event log does in a day. screenshots: false switches it off entirely.

MCP — shot is a tool, answering with the image itself. Verified end to end with a real agent session: given one frame at 1000px, it read window titles, tab names and the text of a conversation. Tool calls now return MCP content blocks, so text and image tools share one path. What an agent still is not given: the daemon, the raw event stream, and your controls over being recorded.

Fixes

  • The daemon crashed, reproducibly, whenever a context call followed a screenshot: the shell takes focus, and gnome-shell answers the AT-SPI Collection interface with a GArray whose length is not a length. The length is clamped and the caller falls back to walking the tree. A client fiber now also rescues anything that escapes — an exception leaving a fiber ends the process, and one malformed desktop should not take the service down.
  • docs/ was gitignored by crystal init, so the design note the README links to had never been in a clone.

Upgrade if you run 0.3.1 as a service; the crash fix matters.

Known limitation, and the plan. The screenshot portal flashes per frame, which is obstructive for an agent taking many — and there is no setting for it. The answer is org.freedesktop.portal.ScreenCast: approved once, a persistent "screen is being shared" indicator, frames pulled quietly from PipeWire. That makes capture a three-way choice — off, on demand, session — and it is written up in docs/daemon.md.