Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@

## Unreleased

- Added two launch points for account plugins. A launcher `select` may declare `"optionsFrom": "service"`: the launcher asks the service `canvastty.launch.options` (3 s) and lists up to 64 more choices after the declared ones, such as the plugin's own accounts; the saved value is then checked by the service when it prepares. Orchestrators may pass plugin launch options to `spawn_agent` as `launchOptions`, checked exactly like the launcher's. A plugin's inline Claude `--settings` is merged into CanvasTTY's own (Claude Code keeps only the last one, which dropped the lifecycle and decision hooks); approval and hook keys in it are refused. Example: `examples/plugins/launch-env` (Profile).
- Added plugin services (manifest apiVersion 2, `services`): bundled single-file JavaScript that runs as a supervised child process only after the separate per-plugin **Extension native code** confirmation in Settings → Agents (off by default, never granted by install, revoked by update, module change, disable, or a changed entry file). Services get a minimal environment without keys or CanvasTTY internals, speak JSON-RPC over stdio with 1 MB messages and 15 s timeouts, restart with backoff, stop on disable, uninstall, update and quit, and log to a bounded per-plugin log. Plugin surfaces call their own plugin's services through `host.service.request` and receive `host.service.onEvent`; services may call back `log`, own-plugin `storage` and `event`, and read their own plugin's secrets with `secrets.get` (needs `secrets`). Example: `examples/plugins/service-echo` (its service also reads a token the page saved).
- Added launch contributors (`launch:contribute`): a trusted plugin service can declare launcher options (boolean, select, text) shown under **Advanced** in the agent launcher. For launches where the person chose the plugin, and their restarts and restores, CanvasTTY asks the service to prepare the launch and adds its environment variables, secret variables resolved from the plugin's own secrets (masked in text other agents and the control CLI read), arguments and per-run files. Contributors merge in plugin-id order; a refusal, a 5 s timeout, a conflict, a reserved name or an approval/conversation argument refuses the launch with the reason on the card, and a restored card whose plugin is unavailable comes back stopped. The chosen values are saved with the session. A contributor may also declare `launch.policy`: it is then asked before every launch of its agents where the person did not choose it (`chosen: false`), may only refuse, and no answer refuses too. Examples: `examples/plugins/launch-env`, `examples/plugins/yolo-guard` (a launch policy).
- Added session environments (`environment:provide`): a trusted plugin service can offer places a card runs in (a git worktree, a container, a remote host), chosen under **Where** in the launcher's Advanced section; terminals get the same launcher while such an environment applies to them. The service prepares the place once, then wraps every start (validated: an absolute program path or a bare name resolved on PATH, never a shell string; launch-contributor env rules; plugin secrets masked) while CanvasTTY keeps spawning the PTY. The opaque ref is saved with the card; restore resumes environments first, then parents before children, and a missing, disabled or untrusted plugin, a stopped environment or a timeout brings the card back stopped with the reason, never run locally. Closing such a card asks once "Keep environment data?" and releases it accordingly. Launch contributors and policies are told the card's environment (`environment` in `canvastty.launch.prepare`). Example: `examples/plugins/env-worktree` (one git worktree per card).
- Added base protection and decision hooks. Base protection (Settings → Agents, on by default, the person can turn it off) refuses, before a local Claude Code, Codex, Qwen Code or OpenCode tool call runs (YOLO included), sudo and other elevation, curl | sh and download-and-run, disk and format commands, fork bombs, and writes or deletes outside the working folder (`/tmp` and the home folder included, and deleting the folder itself; the agent's own plan and memory folders excepted), telling the model what to do instead. A trusted plugin service can declare `decide` (`decision:provide`) and answer `canvastty.decide` with deny, ask or allow: base protection runs first, any deny wins, a timeout or error asks the person, and an allow counts only after a separate **May allow agent actions** confirmation. A service may declare `decide.timeoutMs` (1–60 s, 3 s by default): CanvasTTY waits that long, tells the service its `budgetMs`, and sizes each card's hook, helper and gateway deadlines at launch for the longest budget that applies (the default keeps today's deadlines). Example: `examples/plugins/deny-rm`. Every text one agent reads from another (`observe_agent`, `get_agent_result`, the control CLI's screen, result and failure details) is now masked for vault keys, launch secrets, values a service registers (`redaction.register`) or reads (`secrets.get`), keys wrapped over lines, and common key shapes.
- Reworked "Windows after restart" into one "Agent sessions after restart" model: **Don't save**, **Reopen windows** (new conversations), or **Continue conversations** (the old "on" migrates here). Claude Code and OpenCode now resume their own conversation by the id their lifecycle hook reported, as Codex does (`claude --resume`, `opencode --session`); two cards of one CLI in one folder no longer continue the same conversation. Finished agents come back stopped with Restart / Continue instead of rerunning, the card options menu has **Don't restore this card**, and session records (v2, read-compatible with v1) keep no scrollback, prompts or secrets.
- Made the agent orchestration endpoint an explicit setting (Settings → Agents → "Agent orchestration endpoint", `agentControlEnabled`, off by default; `--agent-control` / `CANVASTTY_AGENT_CONTROL=1` still force it on for one launch) that starts and stops the endpoint at runtime, and added an **Orchestrator** role to the launch dialog next to the normal/YOLO profile: the session keeps the provider you opened the dialog for, gets `CANVASTTY_CONTROL_CONNECTION` and `CANVASTTY_CONTROL_CLI` in its environment so the bundled CLI works without setup, shows an "Orchestrator" badge, keeps its role across restore, and the dialog offers to enable the endpoint first when it is off instead of enabling anything silently. The endpoint's `create` now accepts every agent provider (`codex, claude, qwen, kimi, opencode, hermes, grok, omp, pi`) and reports `capabilities { result, menus }` per worker on `create` and `list`: both are `true` for Codex only; other providers' `screen` has no menu interaction, `choose`/`dismiss` fail with `NOT_SUPPORTED`, `send` relies on the idle status alone, and `result` completes as `no_result`.
- Added a native Codex orchestration CLI (`agent-control/canvastty-control.mjs`, documented in `agent/orchestrator/SKILL.md`) behind `--agent-control` or `CANVASTTY_AGENT_CONTROL=1`: a local controller creates Codex sessions in a project directory, sends work, observes bounded terminal output against a screen revision, and collects the final answer. Each controller sees only the sessions it created, grants are bound to the session generation, mutation IDs are deduplicated, and only controlled sessions opt into authenticated Stop-hook result capture. No automatic approval or terminal deletion endpoint is included.
- Added the opt-in Even G2 companion (Settings → Controls → Even G2, with the Even App companion under `integrations/even-g2`): Bonjour discovery, short-lived SRP-6a pairing with a six-digit code and explicit device approval, encrypted local requests and audio, per-session grants, bounded terminal presentation on the glasses HUD, local speech recognition through the pinned transcribe.cpp helper (bundled on macOS only), and session creation through the existing desktop launcher. The final answer of a Codex turn reaches the companion only for sessions spawned while the companion is enabled: the runtime hook reports it under a separate per-session grant, bounded to 4000 characters, and the gateway refuses it for any other session.
Expand Down
Loading
Loading