Skip to content

Collomia v0.2.0

Choose a tag to compare

@github-actions github-actions released this 30 Jul 20:13
· 103 commits to main since this release
c84ee16

What's Changed

Collomia v0.2.0 brings prompt caching for Anthropic and the ability to steer a turn while it runs instead of waiting it out or killing it. It also adds /restore, an undo that moves the files as well as the conversation.

Configuration stays at schema_version: 1 and the event schema stays at v1. No config file is rewritten by upgrading. Two behavior changes: pressing enter during a running turn now steers the agent rather than holding the draft, and input_tokens on the Anthropic routes now counts the whole prompt where it previously excluded the cached portion. Both are covered under Upgrade notes.

The minor version moves rather than the patch version because a reported field changed meaning. The project's compatibility policy treats that as requiring a version decision, and a patch release would have implied nothing observable changed.

Prompt caching

Collomia was reporting cache hits it never asked for. Both Anthropic adapters parsed cache_read_input_tokens, cost estimation priced it at a cached rate, and the capability matrix listed prompt caching as a tracked dimension — but no request ever carried a cache_control breakpoint, and Anthropic caches only on explicit opt-in. The number was structurally always zero. OpenAI-family endpoints cache implicitly above about 1024 tokens, which is why this went unnoticed for as long as it did.

Why it matters more than it sounds. A turn with ten tool calls is eleven provider requests over the same growing prompt, and every one of them resent the entire stable prefix at full price and full time-to-first-token. That prefix is 13.3 KB on a default install — 11.5 KB of tool schemas across 23 built-in tools, plus the system prompt. Measured across a turn, the share of prompt bytes that are pure retransmission is 33% at one tool call, 71% at five, and 83% at ten.

Two breakpoints, placed deliberately. One on the system block, which also covers the tool definitions ahead of it in the prefix, and one rolling breakpoint on the last message that will still be there next request. A cache write costs more than ordinary input, so a breakpoint placed where the prefix will not be read back is worse than no caching at all.

The prerequisite was moving the plan out of the system prompt. update_plan rendered the structured plan into the system block, so the front of every request changed during exactly the multi-step work caching exists for. The plan now rides a trailing message regenerated per request and never retained in the conversation, so the board stays the single source of truth and no stale copy accumulates in the history.

Measured against a live endpoint, not argued from structure:

first  request: input=9629 cache_read=0    cache_write=9627
second request: input=9629 cache_read=9627 cache_write=0

100% of the second prompt served from cache, with two tokens falling outside the cached prefix — which confirms the rolling conversation breakpoint is honored and not only the system one. A write costs 1.25x and a read 0.1x, so the one-time write premium is repaid by the first read; every turn that uses a tool makes at least two requests, so there is no crossover to plan around.

Anthropic routes only, and honestly declared. OpenAI-family endpoints need nothing. Bedrock is declared without cache support on purpose: its cache points vary by model and region and fail the entire request with a hard ValidationException rather than being ignored, so support waits until it can be qualified against a real deployment rather than shipped on an assumption. An endpoint that rejects a breakpoint disables caching for the life of the process after one wasted request. The lifetime is the provider's five-minute default; the one-hour extension needs a beta header, and sending an unrecognized beta header to an arbitrary compatible endpoint is a compatibility risk taken for a saving nobody has measured yet.

Steering a running turn

Type and press enter while the agent is working. Watching a turn head down the wrong path previously left two options: wait for it to finish, or press esc and lose the whole turn. The composer refused mid-turn input with a message explaining the draft would be sent afterwards.

It lands at a boundary, never mid-action. Guidance is delivered at the next iteration boundary — never inside an in-flight provider call, an executing tool, or a pending approval. The machinery is the same drain-once queue that has governed delegated agents since v0.1.x; what changed is that the primary session now uses it.

It grants nothing. Steering arrives as an ordinary user message that carries no authority: an action that would have prompted for approval before the guidance arrived still prompts after it. Telling the agent to go faster is not a way to tell the permission layer to stand down.

Undelivered guidance is discarded and reported. A turn that ends or is cancelled before the queue drains throws the text away rather than holding it against unrelated later work — a cancelled turn is the common case, and resurfacing that text three prompts later would be worse than losing it.

Delegated agents are still steered separately through /agents steer and alt+a. Headless runs and the JSONL event stream are unaffected.

Restore: an undo that moves the files too

/restore [turn] branches the conversation the way /rewind does and reverses every file mutation recorded after that turn. Both halves already existed and were independently solid; nothing connected them, so rewinding a turn left the files it wrote in place and a transcript describing a tree that no longer matched.

It refuses rather than half-applies. The whole workspace is verified before anything is written, and if any file changed outside Collomia the entire operation is refused, naming every affected file rather than the first one found. The check runs before the conversation branches — a drifted file discovered afterwards would leave a conversation that moved alone, which is the exact split this feature exists to close.

Two limits stated rather than papered over. Change tracking is in memory, so restoring to a turn from a resumed session reports that no tracked changes needed reversing instead of implying it rewound writes it never observed. External effects — commands, installs, network calls, deployments, MCP effects — are never reversed.

Each entry in the checkpoint picker carries how many changes across how many files restoring to it would reverse, because a turn number conveys none of that. /rewind, /undo, and collo sessions rewind are unchanged.

Upgrade notes

  1. enter during a running turn now steers. It previously held the draft until the turn ended. This is an interactive change only; nothing about permissions moved, and headless behavior is identical.
  2. input_tokens on the Anthropic routes now includes cached tokens. The Messages API reports that field net of both cache counters, so passing it through would have understated the prompt by whatever the cache served — a live request reported a raw input_tokens of 2 for a 9,629-token prompt, which would have collapsed the context gauge exactly when the context was fullest. Comparing this field across the upgrade shows an apparent increase that is a correction, not new consumption. Recompute spend from cost_usd, which accounts for cache reads and writes at their own rates. See the compatibility note.
  3. cache_write_tokens is new and optional. Additive under schema v1; consumers that tolerate unknown fields, as automation consumers are asked to, need no change. The event schema deliberately stays at v1 — bumping it would force every strict client to update in order to receive a correction.
  4. Nothing else changes by default. No sandbox, permission, provider, or configuration default moves in this release.

Also in this release

The status bar was hiding its own cancel key. Below roughly 100 columns the entire right-hand segment was dropped, taking esc cancel with it — so the control that stops a runaway turn was invisible in a split pane or a narrow tmux pane, which is where it is needed most. Segments are now shortened and dropped by priority, with the cancel key last to go. The golden screens had recorded the empty bar as expected output; coverage now spans three widths instead of one.

Build provenance in run traces. run.result carries the version and commit of the binary that produced it, and replay --check reports that against the running binary. Since prompts, tool descriptions, and agent logic are all compiled in with no runtime override, identical build means identical instructions — so build identity answers "would this binary have behaved the same?" without a partial prompt-only signal. Additive under schema v1; traces predating the field stay valid.

Agent prose moved out of Go string literals into embedded templates under internal/prompts, leaving only the conditional composition in code.

The capability matrix is now enforced. docs/CAPABILITIES.md had gone stale — the build-identity detail never reached it, and the full suite stayed green for an entire release window with the published matrix understating what the binary did. A test now diffs the committed file against its generator. Two rows describe what the host platform can actually enforce and vary by operating system on purpose, so those are checked for presence and status rather than byte equality.

docs/COMPATIBILITY.md gained sections for both behavior changes, docs/AUTOMATION.md documents the full usage object with the meaning change called out inline, and docs/BETA.md records the caching limits.

Install

macOS and Linux:

curl --proto '=https' --tlsv1.2 -fsSL \
  https://raw.githubusercontent.com/robert-mcdermott/collomia/main/install.sh |
  COLLO_VERSION=v0.2.0 sh

Windows 11, AMD64 or ARM64:

$env:COLLO_VERSION = 'v0.2.0'
irm https://raw.githubusercontent.com/robert-mcdermott/collomia/main/install.ps1 | iex

See INSTALLING.md for per-user directories, pinning, reviewing the installer before running it, and upgrade behavior.

Full Changelog: v0.1.9...v0.2.0