feat: Muse Code and Devin CLI agents, OpenCode sqlite history, OpenCode quota accounts

Merged
KI
2mo ago
+2221-187

Summary

  • OpenCode history was silently empty. OpenCode 1.x keeps every session in <data>/opencode/opencode.db and no longer writes the storage/message JSON tree the collector scanned. The collector now reads the database read-only (better-sqlite3, joined to session for cwd and title) and keeps the JSON scan only for pre-1.x installs.

  • OpenCode logins show as quota accounts. auth.json holds Anthropic and OpenAI OAuth logins on the same OAuth clients Claude Code and Codex use, so the existing quota endpoints answer. A new OpenCode section in the quota panel shows one card per provider login.

  • Muse Code (Meta's terminal agent) becomes a built-in agent and joins token history. muse launches the interactive session (prompt as positional arg), muse resume <uuid> resumes, muse exec is the headless one-shot; registered in the Add-agent catalog, icon picker, settings search, README tables, docs and the marketing compatibility strip. A new collector reads its JSONL session logs; Muse is priced at Meta Model API list rates, attributed to a new meta model provider, and drawn as an eleventh series with the Meta mark as its icon (Meta blue on light, white on dark; Meta publishes no Muse-specific vector).

  • Devin CLI becomes a built-in agent with lifecycle hooks and usage history. devin --permission-mode dangerous launches, the prompt rides after --, --resume <id> resumes, devin -p --respect-workspace-trust false is headless. Devin's hooks follow Claude Code's contract, so agent-setup merges Superset's notify hook into ~/.config/devin/config.json and ships a devin wrapper; token history comes from ~/.local/share/devin/cli/sessions.db. Icon is Cognition's Devin mark.

  • Both new agents get Superset lifecycle hooks (working indicator, completion chime, session binding). Devin's config takes Claude's nested hooks block. Muse runs hooks with a cleared environment, so its settings-block hooks never see SUPERSET_*; Superset instead owns $SUPERSET_HOME_DIR/hooks/muse/hooks.json, points Muse's managed_hooks_path at it and allowlists the notify script's variables via managed_hooks_env_vars.

How It Works

  • history/opencode.ts checks for opencode.db; when present it dynamically imports opencode-db.ts (better-sqlite3 is a Node-only native binding the Bun unit suite cannot load) and maps rows through the pure opencode-rows.ts. The message JSON in the data column is the same shape as the old files.
  • claude.ts and codex.ts now expose fetchClaudeSubscriptionQuota / fetchCodexSubscriptionQuota (token in, quota out). opencode-quota.ts parses auth.json, classifies each OAuth entry as live / stale (lapsed access token, refresh token present — OpenCode renews it on its next request) / expired, and calls the matching fetcher. type: "api" entries become pay-per-token cards without the key ever being read.
  • history/muse.ts walks <data>/muse/sessions/YYYY/MM/DD/<id>/session.jsonl. Each line is an envelope (recorded_at in microseconds); the run stream is mirrored in as runtime.session records whose event.kind === "model_completed" carries usage.{input_tokens, output_tokens, cached_tokens, reasoning_tokens} (input includes the cached share, as with Codex). cwd and model come from runtime.session.metadata, the label from the run's started prompt. Entries dedupe on source_run_record_id because a child run can be mirrored into both its own and its parent's log.
  • agent-setup/agent-wrappers-devin.ts registers SessionStart/SessionEnd/UserPromptSubmit/Stop/PostToolUse/PermissionRequest in Devin's config (it drops the whole hooks block on an unknown event name, so only accepted names are written) and keeps version: 1, which Devin requires. history/devin.ts reads assistant message_nodes whose JSON embeds metrics (input, output, cache-read tokens) and generation_model; the streamed and committed copies of a message share a request_id and dedupe on it. Devin's own SWE models have no published token price and take the approximate fallback.
  • agent-setup/agent-wrappers-muse.ts: managed_hooks_path is single-valued, so a path Superset does not own is never replaced (a previous Superset home is). Teardown removes only the pointer and Superset's env names. Events: SessionStart, SessionEnd, UserPromptSubmit, Stop, StopFailure, PostToolUse, PermissionRequest.
  • Desktop: QuotaCapableAgent gains opencode (section, label, opencode auth login re-auth hint); AGENT_CHART_CONFIG gains Muse with a palette-validated rose. The stale-token hint is now worded per agent (it was hardcoded to Claude Code), with the new string translated in all 16 locales.

Manual QA (dev desktop over CDP, this worktree, signed in as kiet@superset.sh)

Screenshots and measurements: https://app.superset.sh/page/usage-tab-muse-opencode-verification-pd01op

  • Settings → Usage renders an OpenCode section: Anthropic login as stale (token expired months ago, refresh token present), OpenAI login with plan pro, weekly window, credits balance — matches a direct call to the ChatGPT usage endpoint with the same token.
  • OpenCode history line reads $0.18 for 30d, which is exactly the 14 assistant turns / 142,845 input tokens the sqlite store holds for that window at the gpt-5 list rate; the legacy JSON tree has 0 files in that window, so the number can only come from the database.
  • Three synthetic Muse session logs (shaped like a real muse exec log, with nonzero usage) dropped under ~/.local/share/muse/sessions appear as a Muse Code legend row with a cost after a refetch; removed afterwards.
  • Real Muse session. Muse Code 1.1.1 signed into a Meta account and ran one muse exec turn. Its log carries model_completed with usage.{input_tokens 28316, output_tokens 22, cached_tokens 0, cache_write_tokens 0, cache_read_tokens 0, reasoning_tokens 11} and model: "muse-spark-1.3-contributor"; the collector yields exactly that entry priced at the contributor rate, and the usage tab shows it as Muse Code · 28K in Tokens mode. The record is pinned in muse.test.ts.
  • Muse as an agent. Settings → Agents → Add agent lists Muse Code with its icon; adding it creates the device row with command muse and resume args resume; the workspace launcher bar shows it and launching opens a pane running muse (trust prompt, then the TUI boots on muse-spark-1.3-contributor and accepts a typed prompt; the model call itself returned Meta's 402 "Billing verification failed" for this account, which is the account's billing state, not the launch). The headless muse exec turn earlier the same evening did complete and is what the history collector was verified against. The usage legend row now carries the icon.
  • Devin as an agent. Two headless devin -p probes with a hook-capturing config confirmed the payload shape (hook_event_name, session_id, prompt, tool_name) on every registered event, in print mode too. In the dev app: Add agent lists Devin with its icon; adding creates the row with command devin --permission-mode dangerous, prompt args --, resume args --resume; the dev host-service merged Superset's hooks into ~/.config/devin/config.json at boot (alongside another tool's existing hooks) and created the wrapper; launching from the workspace bar opened a pane, Devin's first-run Git wizard was skipped, a typed prompt ran to completion on SWE-1.6, and terminal_agent_bindings recorded the terminal as devin with the real session id longhaired-file and Start/Stop events from the hook chain. Usage legend shows the probe sessions as Devin · 46K in Tokens mode with the icon.
  • Muse hooks. Env-dumping probe hooks proved settings-block hooks get 13 variables and no SUPERSET_*, while managed_hooks_path hooks get the allowlisted ones. In the dev app after boot: Muse's settings carry the pointer and allowlist, the managed file exists, and a pane launched from the workspace bar produced terminal_agent_bindings rows Attached → Start (with Muse's real session id) → Stop, with the amber working dot on the tab and pane while the turn ran. Muse's notify stderr shows the host-service receiving each post.
  • Stale-token hint on the OpenCode card reads "Refreshes when OpenCode next runs." (was "…Claude Code…" before the last commit).
  • Real-data collector run under Electron's Node: OpenCode 250 rows → 246 entries, 30 labels, ~180 ms; Muse collector finds the seeded logs.

Testing

  • bun run typecheck (host-service, desktop)
  • bunx biome check on changed files
  • bun test src/trpc/router/usage (host-service, 123 pass) — new: opencode-rows.test.ts, opencode-quota.test.ts, muse.test.ts
  • bun test src/agent-command.test.ts (shared, 31 pass) — new Muse and Devin registration cases
  • bun test src/agent-wrappers.test.ts (agent-setup, 79 pass) — new Devin config and Muse managed-hooks cases
  • host-service usage suite now 126 pass incl. devin-rows.test.ts built from a captured real record
  • bun run typecheck also clean for shared, ui, marketing
  • bun test src/renderer/routes/_authenticated/settings/usage (desktop, 43 pass)
  • bun run check:i18n clean

Known Limitations

  • Whether Muse's input_tokens includes the cached share could not be observed (the real call had cached_tokens 0); the collector assumes it does, as Codex reports, so a cached call can only be under-counted. The binary exposes no quota endpoint, so Muse has no quota card.
  • Eleven categorical series is past what the palette validator can fully satisfy; the rose is the best remaining slot (≥ 9 ΔE from every other hue for normal vision, bands and contrast pass in both modes). The pre-existing Antigravity/Grok adjacent pair already fails the CVD check.

https://claude.ai/code/session_012R8eHx1CdbVXNJveeGA2dV


Summary by cubic

'2027'

Summary by CodeRabbit

  • New Features

    • Added full Devin support, including terminal launching, managed setup, icons, usage history, charts, model attribution, and pricing.
    • Added full Muse Code support, including terminal launching, icons, usage history, charts, model attribution, and pricing.
    • Added OpenCode usage tracking for database and legacy records.
    • Added OpenCode quota visibility for Anthropic and OpenAI logins, including token status and subscription details.
    • OpenCode now appears in usage ordering and account displays.
  • Localization

    • Added translated OpenCode usage refresh messaging across supported languages.
  • Documentation

    • Added Muse Code and Devin to supported-agent documentation and product listings.