Beaver — Obsidian plugin

AI Slop Inside

Two things:

  • Send the current note to Beaver's markdown frontend (POST /chat/stream on beaver-gateway) and stream the agent's reply back into the buffer. Skips the Obsidian Sync round-trip by POSTing the buffer contents directly.
  • Activity panel (v0): a side view that follows the active note's conversation_id and shows, live over SSE, what the agent is doing — tool calls, subagents as a tree, turn status, usage of each turn.

Commands

  • Beaver: Send using selected agent — uses frontmatter.agent. Only when the active note has an agent: field.
  • Beaver: Send using different agent — fetches the agent list from the gateway and opens a fuzzy picker. Same condition.
  • Beaver: Open chat in panel — reveals the activity panel in the right sidebar (creates it on first use) and points it at the active note.

Activity panel

Subscribes to GET /api/conversations/{id}/events (SSE, bearer) where {id} is the conversation_id from the active note's frontmatter. Switching notes switches the subscription; a note without conversation_id shows a hint instead. On connect it fetches GET /api/conversations/{id} for the snapshot (title, agent, kind, status, whether a turn is running), then renders bus events:

  • turn.start / turn.end — a turn block with status (running / done / interrupted / error), origin (user / inject), start time, duration and usage (in · out · cache read/write · $ · time).
  • tool / tool.result — a tool row (name, input summary, result status); clicking it expands the raw input and the result preview. Rows with parent_tool_use_id nest under the Task/Agent tool that spawned the subagent.
  • stream content_block_start of type tool_use — pre-creates the row so a long-running tool shows up before its input is complete.
  • say — text the dispatcher sent out of an inject turn.

The stream reconnects with exponential backoff (1 s → 30 s, jittered) and resets on hello. 401/403/404 are not retried: the panel shows the error and waits for you to fix the token or the id. When it reconnects and the snapshot says nothing is running, turns still shown as running are marked interrupted — their turn.end was lost with the connection.

Plain DOM and CSS on Obsidian's theme variables; no framework. It is the v0 of the panel from архитектура.md §2 — the full Svelte UI (M5) replaces it.

Settings

  • Base URL — markdown-frontend root, e.g. http://localhost:62993 or https://host/md.
  • API origin — where /api/… lives, e.g. http://localhost:62994 or https://host. Empty = derived from Base URL (…/md, port 6299362994).
  • Bearer token — needs the messages scope for sending and the api scope for the panel; a * bootstrap token covers both.
  • Vault subpath — folder in this vault that maps to the gateway's vault root.
  • Test connection / Test APIGET /agents on the markdown frontend, GET /api/agents on the API origin.

Note format

A minimal note that the plugin can send:

---
agent: beaver-opus-medium
---

hi there

The gateway parses ### User: / ### Assistant: markers; a note with no markers is treated as a single user turn. After the first turn the gateway adds conversation_id to the frontmatter — that is what the activity panel keys off.

Install

make install VAULT=~/Obsidian/my-vault     # build + copy manifest.json, main.js, styles.css, versions.json into <vault>/.obsidian/plugins/beaver
make zip                                    # build → beaver-plugin-<version>.zip you can carry to any vault

Then enable Beaver in Settings → Community plugins (or reload it if it was already enabled).

Mobile

The plugin is desktop-and-mobile (isDesktopOnly: false). Two things to get right on a phone:

  • The base URL / API origin in plugin settings have to be reachable from the phone — http://localhost:… won't work; use the gateway's LAN IP, a tunnel, or a public hostname.
  • Get the plugin files onto the phone vault via Obsidian Sync (toggle "Installed community plugins" in your sync settings) or any file-sync tool you already use (Working Copy, Syncthing, etc.). make install only knows how to write to a local path.

Hand-rolled

Four files are all Obsidian needs — manifest.json, main.js, styles.css, versions.json. Drop them in <vault>/.obsidian/plugins/beaver/ however you like (unzip, scp, rsync, your own git, …).

Bumping the version

Edit the version field in manifest.json, package.json, and versions.json by hand. Three files, one change each.

S
Description
Obsidian plugin for Beaver's markdown frontend
Readme
465 KiB
Languages
TypeScript 66.9%
JavaScript 16.7%
CSS 12.2%
Svelte 2.2%
HTML 1.4%
Other 0.6%