Skip to content

v0.4.0

Latest

Choose a tag to compare

@volt-release-tagger-hansjm10 volt-release-tagger-hansjm10 released this 17 Oct 04:44
Immutable release. Only release title and notes can be modified.
051a195

Standalone Windows executables in this release are not code-signed. Windows may show a SmartScreen warning when you first run them.

Highlights

  • Extensions can run agents as conversation work with ctx.subagents: start one in a directory of the conversation or a managed worktree, under turn, token, cost, and time limits, and get its result.
  • Extensions can start reviews on any review engine with ctx.reviews, read their results, record finding outcomes, and post a complete pull request review as a chosen GitHub CLI account with a trailer.
  • Extensions in daemon-hosted conversations can list and create the managed worktrees of the conversation's repository with ctx.worktrees, and run subagents in them.

Breaking Changes

  • mcp: OAuth credentials for HTTP MCP servers are now bound to the authorization server that issued them and are never sent to a different one named by the MCP server, fixing GHSA-6qxp-vccf-f47h. (#843)
    Migration: stored MCP OAuth tokens and client registrations saved by earlier versions carry no authorization server binding and are discarded, so authenticate each affected server again with volt mcp auth <server> or volt mcp auth-device <server>. A server configured with a pre-registered auth.clientId must also set auth.issuer to the authorization server URL that client is registered with; without it, authentication fails. If a Volt client may have connected to an untrusted MCP server while holding OAuth credentials, rotate the affected client secrets and revoke their tokens.

  • packages: Each pinned git ref is now its own package with its own checkout, so store packages from the same repository install side by side instead of replacing each other. (#659)
    Migration: volt install git:host/user/repo@new-ref now installs the new ref beside the installed one instead of moving it. To move a package to a new ref, volt remove git:host/user/repo@old-ref and install the new one. volt remove, volt update, and volt store remove with a repository source without a ref still act on the repository's pinned ref when it is the only one configured in the scope, and fail when there are several; name the ref then. A user-scope and a project-scope entry of one repository at different refs are now two packages that both load: when they declare the same extension id, the user-scope one runs and the project one is reported as not loaded, so remove the entry you do not want. Existing pinned packages are cloned again into <path>@<ref> on the next start; their previous checkout at <path> is no longer used and can be deleted.

    volt store update installs a catalog package's new pin beside the installed one and replaces it once its permissions are acknowledged; declining keeps the installed pin. Installing a catalog package that is already installed at another pin points to volt store update.

  • config: Volt no longer migrates or reads configuration, credential, package, daemon, and remote-host files in pre-release formats.
    Migration: rename pre-namespaced ids in keybindings.json (for example cursorUp to tui.editor.cursorUp, expandTools to app.tools.expand) using the ids /hotkeys lists. In settings.json, replace queueMode with steeringMode, websockets with transport ("websocket" or "sse"), a skills object with a list of skill directories plus enableSkillCommands, and retry.maxDelayMs with retry.provider.maxRetryDelayMs. Move credentials from oauth.json or settings.json apiKeys into auth.json with /login, and rename a commands/ directory to prompts/. User npm packages are no longer loaded from the global npm or pnpm root; Volt installs them into ~/.volt/agent/npm on the next start. A remote/iroh-host.json from before the daemon is no longer imported, regenerating a daemon state.json from before access grants (volt daemon regenerate-state or /remote) now starts empty state with a new Iroh identity, and a state.json missing any host-state section or a workspace's generation record is reported as invalid instead of being filled in; pair phones again. SDK: InteractiveModeOptions.migratedProviders is removed, the daemon runtime factory takes toolPolicy instead of allowTools, the IrohRemoteGrantedClient, IrohRemoteGrantedRevokedClient, and IrohRemoteGrantedPendingPairingTicket types are removed because every record now carries rpcGrant, and every IrohRemoteHostState section is required. Daemon control protocol: status_result no longer carries capabilities, and revokedClients, remotePolicy, and each client's allowedTools, usesDefaultTools, and rpcGrant are always present.

  • sdk: Session event listeners now share one deeply frozen event typed DeepReadonly<AgentSessionEvent>, so streaming costs less CPU when several observers watch a conversation. (#772)
    Migration: a listener that changed the event it received must build its own values from it instead; writing to an event now throws, and AgentSessionEventListener, SubagentEvent, and review onSessionEvent callbacks receive DeepReadonly<AgentSessionEvent> from @hansjm10/volt-ai. Replace session.subscribeRuntimeEvents(listener) with session.paceRuntimeEvents(pace): the pace is awaited after each loop event and receives no event. Live items for the streaming assistant message are read-only types.

Improvements

  • daemon: Reduced CPU use while a large tool call streams: the live state no longer re-parses the call's whole argument text on every delta. (#775)
  • daemon: Reduced per-token streaming overhead when no extension handles message or tool execution events. (#750)
  • jobs: A background bash or subagent call no longer shows a "Background job" card that kept saying "Started"; the job's live state under the call is the only status shown.
  • remote: Paired devices can list a workspace's extensions and review engines before a conversation is open.
  • remote: Paired devices now time tool calls by the host's clock, and calls in a conversation's history keep how long they took. (#923)
  • remote: Paired phones now see this computer's name (for example "Jordan's MacBook Pro") instead of only its node ID, including before an agent is open.
  • remote: Reduced the host CPU each paired device costs while a long answer or tool call streams: path redaction now processes only the newly streamed text instead of the whole message on every token. (#820)
    Arguments that stream on one long line, such as a file a tool call writes, now reach the device in larger steps.
  • review: Review runs record the label of the engine that produced them, so clients, posted pull request reviews, and a refused rerun name a past run's engine (such as Swarm) instead of its id.
  • review: Reviews on every engine can run the project's checks and tests: the reviewTools setting and the tools of ctx.reviews.start now apply to extension engines, and the reviewSetup setting or the setup of ctx.reviews.start first runs a command, such as installing dependencies, in each review checkout.
    A review an extension starts can also follow the previous round of a review loop: it reviews everything again, keeps the id of each finding still open, and closes the ones it finds fixed where they were found. It can also collect follow-ups: verified defects it notices outside the change, kept apart from the findings with a fingerprint that identifies the same defect across reviews.
  • rpc: The RPC contract declares review run startedAt, endedAt, usageUpdatedAt, and acknowledgedAt and the live phase's run and compaction startedAt as safe non-negative integer epoch milliseconds (RpcEpochMilliseconds) instead of unrestricted numbers. (#316)
  • rpc: The RPC contract declares the retry start time, prompt-cache times, worktree creation times, finding-outcome creation time, and daemon status times (paired, last seen, revoked, re-pair approved, and daemon start) as safe non-negative integer epoch milliseconds (RpcEpochMilliseconds) instead of unrestricted numbers. (#842)
  • A collapsed failed command now shows its last lines and how it ended, and a collapsed edit shows the first 16 lines of its diff. (#921)

Fixes

  • docs: Fixed the keybindings action tables to list the actual defaults for thinking-level cycling, new line, line start and end, and editor page up and down. (#797)

  • docs: Fixed the keybindings Custom Configuration and Emacs examples so ctrl+p moves the cursor up instead of cycling models. (#796)

  • docs: Fixed the keybindings Vim example so alt+j moves the cursor down instead of opening the work inspector. (#792)

  • docs: Listed the custom messages that message_start and message_end fire for in the extensions guide. (#869)

  • docs: Listed the prompt history, selection left/right/toggle, focus traversal, and review tools toggle actions in the keybindings action tables. (#804)

  • extensions: Changing an entry or header read through ctx.sessionManager no longer changes the session's committed entries. (#855)

  • extensions: Changing the parameters or promptGuidelines that volt.getAllTools() returns no longer changes the schema the model is offered and tool arguments are validated against, or the system prompt, in that session or, for built-in tools, in any other session. (#794)

  • extensions: Changing the sourceInfo that volt.getAllTools() or volt.getCommands() returns no longer changes the session, so an extension tool that overrides a built-in can no longer pass as the trusted built-in. (#789)

  • extensions: Extension handlers of agent loop events such as turn_end and message_update each get their own copy of the event, so one handler's change no longer reaches later handlers, session listeners, or clients. (#773)

  • extensions: Extension session_before_compact and session_before_tree handlers each get their own copy of the preparation, so a handler that returns no result no longer changes what Volt's default summary or later handlers receive. (#849)

  • extensions: Extension session_before_switch handlers each get their own copy of the event, so a handler that changes targetSessionRef no longer changes which session Volt opens or what later handlers see. (#852)

  • extensions: Extension session_compact and session_tree handlers each get their own copy of the event, so a handler that changes compactionEntry or summaryEntry no longer changes the session's saved entry or what later handlers see. (#853)

  • extensions: Work-detail actions can now open and cancel subagent runs started by the same extension.

  • extensions: Prevented worktree operations from targeting the enclosing repository when a conversation runs in a nested repository inside a managed checkout.
    The worktree example now checks checkout availability and explains how to handle archived worktrees without reusing a missing checkout or its reserved id.

  • extensions: Made managed worktrees visible and removable across primary and linked checkouts of the same Git repository within a workspace.
    Worktree creation keeps the selected source checkout's default branch or commit, even when the primary checkout is outside the workspace.

  • extensions: Extensions can no longer change the content, details, or display of the host's custom messages (review, work_notice, plan, and subagent recovery messages) through a message_end replacement; passing one through unchanged still works. (#867)

  • extensions: Extensions can no longer commit the host's custom message types (review, work_notice, plan, and subagent recovery messages) through a before_agent_start message or a message_end replacement. (#865)

  • extensions: Fixed an input handler that mutated event.images changing the images committed with the prompt and seen by later handlers. (#781)

  • extensions: Fixed a before_agent_start handler that mutated event.images changing the images committed with the prompt and seen by later handlers. (#609)

  • extensions: Editing the before_provider_request payload in place now changes only that request instead of the registered tool parameter schemas, which for built-in tools reached every session in the process. (#806)

  • extensions: Changing an entry or header read through writer.sessionManager in a ctx.newSession() setup callback no longer changes the new session, and the view no longer exposes host-only session manager methods. (#858)

  • extensions: Extensions can no longer write the host's custom message types (review, work_notice, plan, and subagent recovery messages) through the writer a new session's setup gets. (#862)

  • extensions: Subagents an extension starts now close their conversation when the run ends in daemon-hosted conversations too, and ctx.worktrees can remove a worktree and create one on an existing branch, so an extension can free checkouts it is done with.

  • extensions: Fixed before_agent_start handlers and extension commands that mutated systemPromptOptions changing the skills and context files the session had loaded; each now receives a copy. (#782)

  • mcp: Redacted the value after a secret-named flag such as --token or --password in array arguments written to the MCP audit log. (#883)

  • mcp: Fixed MCP error and audit-log redaction of Authorization values with auth-params, such as Digest response/nonce/cnonce or OAuth 1.0 oauth_signature, and of Authorization <scheme> <credential> without a separator, which left credentials in clear text. (#900)
    Every auth-param is redacted, including quoted values that contain commas. The Bearer, Basic, and token schemes stay visible.

  • mcp: Fixed MCP error and argument redaction of Authorization values such as Bearer <token>, Bot <token>, or a quoted "Bearer <token>", which hid the scheme but kept the credential and wrote it to the MCP audit log. (#884)
    The Bearer, Basic, and token schemes stay visible. With any other scheme, or none, the whole value is redacted up to the next ,, ;, quote, or line end.

  • mcp: Fixed MCP error and argument redaction leaving secrets in clear text after a quoted key such as JSON's "access_token" or after API key:, including in the MCP audit log. (#881)
    A quoted string value is now redacted through its closing quote, also inside JSON-encoded text, and an object or array value under a secret key is redacted whole.

  • mcp: Fixed MCP error, argument, and audit-log redaction missing quoted credentials after leading whitespace and a known authorization scheme, Basic Base64 credentials without digits, or later Cookie values after empty or valueless segments.

  • mcp: Prevented adversarial text from exposing earlier secrets when MCP redaction reaches its parsing limit.
    When the parsing limit is reached, the entire error or string argument is redacted, including in the MCP audit log.

  • mcp: Fixed MCP error and argument redaction keeping request signatures such as a presigned URL's X-Amz-Signature, an Azure SAS sig, or an OAuth 1.0 oauth_signature in clear text, including in the MCP audit log. (#902)

  • mcp: Kept MCP OAuth error messages such as "token endpoint must use HTTPS" readable while still redacting token: value, token=value, --token value, and credential-like values such as invalid token ghp_abc123. (#876)

  • mcp: Fixed MCP error and argument redaction leaving parts of secrets in clear text, including in the MCP audit log: quoted values with spaces after any key, a scheme other than Bearer or Basic, a quoted value that starts with a line break, and keys such as cookie, passphrase, pwd, and auth. (#904, #907, #908, #910)
    A quoted value after a key is now redacted through its closing quote, keeping the quotes, and an object or array after a key is redacted whole.

    Quoted credential-like values after whitespace alone are also detected when their content starts with whitespace. Quoted credentials after unknown schemes and all Cookie header pairs are redacted; Set-Cookie attributes stay readable.

  • mcp: Fixed MCP connections forgetting the OAuth client registered during browser sign-in, which forced a new sign-in once the access token expired. (#878)

  • models: NVIDIA now defaults to Nemotron 3.5 Super VL because NVIDIA retired Nemotron 3 Super.
    The model lists also drop the other models their providers retired. Choose another NVIDIA model with /model or --model if you prefer a different default.

  • remote: Fixed a paired device being sent the start of a workspace path when the host resent a streaming answer, after redaction rewrote text it held or when the device joined mid-stream. (#823)

  • remote: Fixed a paired device sometimes missing the last frame of a relayed conversation stream, such as the notice that its workspace was unregistered, when it sent another frame as the stream closed (#800).

  • remote: Paired devices keep receiving streaming tool call arguments past a JSON escape such as \n instead of only the finished call. (#824)
    Streaming text no longer resends the whole message, with the start of an unfinished path in it, when a delta ends inside a word the device already shows part of.

  • remote: Paired phones no longer receive host paths under the worktrees root when text names them through a symlinked agent directory. (#930)

  • remote: Remote host state with a negative, fractional, or unsafe pairing or worktree timestamp now fails to load with a clear error instead of breaking daemon status, client, and worktree responses. (#861)

  • remote: Fixed a paired device sometimes losing the answer to an intent that ends its relayed conversation stream, such as unregistering its workspace, when it sent another frame before the stream closed (#793).

  • remote: Fixed a paired device being sent the start of a workspace path from a tool call whose arguments were still streaming, when the host resent a streaming answer or the device joined mid-stream. (#830)

  • review: A review on an extension engine that follows an earlier run now decides every earlier finding, so a review loop on any engine can come back clean.
    The host verifies, with the review verifier model, each earlier finding the engine neither decided nor reported again. Before, such a finding stayed open in every later round, so the review never came back clean.

  • review: Review discussion intents now reject a stale branch as stale and a reused reset request id as conflict, and report other failures with their own message instead of as an unavailable review source. (#818)

  • review: Review run lists and results skip a stored run or acknowledgment whose timestamp is negative, fractional, or beyond the safe integer range instead of sending it to clients. (#841)

  • rpc: Assistant transcript items now separate their text blocks with a blank line in text, and review discussion or source-unavailable failures reach protocol clients as unavailable instead of failed. (#636)

  • sessions: Fixed a message the host lost while sending it blocking every later message in the session: /discard-stuck and the discard_client_input intent now discard it without sending it again. (#492)

  • sessions: Listed conversations that only ran work, such as extension command work, in /resume, volt -r, and remote session lists. (#801)

  • subagents: Oversized duration limits now fail validation instead of cancelling subagents immediately.

  • tui: Durations past a minute now show as minutes, hours, and days (47m 12s, 1h 2m) in /work, tool cards, bash output, and subagent status instead of raw seconds. (#836)
    The working indicator and /remote use the same format, so /remote now shows seconds past a minute and days past a day.

  • tui: Fixed text after a non-SGR terminal escape sequence, such as a cursor movement, being measured as part of the escape, which let lines overflow the terminal width. (#751)

  • tui: Fullscreen link clicks open only http and https links; a click on a file:, smb:, or custom-scheme link shows a notice instead of launching its handler. (#697)

  • update: On Windows, volt update now explains how to update a standalone, source checkout, or other unrecognized installation and shows where the running volt is, and for yarn and bun installs it prints the command to run instead of only rejecting the update. (#553)