Skip to content

Releases: cortexkit/magic-context

10 releases found

Dashboard dashboard-v0.19.0

Choose a tag to compare

@github-actions github-actions released this 06 Oct 16:57

Dashboard v0.19.0

A redesigned configuration page. Works with Magic Context 0.45.x.

A clearer Config page

The configuration form is reorganised into eight sections with an index on the left: General, Context window, History, Memory & search, Background models, Dreamer schedule, Prompt surface and Advanced. Each section is a single column of settings, with the explanation on the left and the control on the right. Below about 1,000 pixels wide, rows stack so controls keep their full width. Raw config keys are hidden unless you turn on "Show config keys", and settings that need a restart are marked.

Pickers instead of free text

  • Output language is a searchable list of languages, for example "Turkish (tr)".
  • Variants for the historian and dreamer models offer the variants the selected model supports. If they're unknown, you can still type one.
  • The cue compressor model uses the same model picker as the historian and dreamer.
  • Fallback models each get a full row: model, variant and remove. The model list opens above the page instead of being cut off.

Forms instead of JSON boxes

  • Model routes are a table of route and preset.
  • Tool descriptions list each Magic Context tool with its built-in text. Edit one to override it, or reset it to the default; only the ones you change are saved.
  • Pi subagent extensions are a list with one entry per row.

Help next to each setting

The "How it works" expanders are now a small "?" button beside the setting. It opens a short explanation with a link to the matching page of the documentation, which opens in your browser.

Other changes

  • Per-model cache TTL and threshold overrides sit in one collapsible table.
  • The dreamer schedule is a compact table of tasks and their schedules.
  • The Auto Update setting shows its real default instead of "undefined".
  • A dreamer task that was skipped, or refused before reaching the model, says so on its card instead of showing a provider error.
  • Config files the dashboard writes are readable only by your user account.

v0.45.0

Choose a tag to compare

@github-actions github-actions released this 04 Oct 21:08

This release makes context.db the one database Magic Context keeps its data in, and lowers what each turn costs: reasoning from older turns now leaves the request on every provider, emergency drops skip passes that would save almost nothing, and a turn writes far less to disk. A pass that fails partway no longer sends the conversation without its reductions. Agents can recover a dropped item by its tag, and Pi's status displays stop showing raw estimates as usage. On OpenCode 2 it now needs 2.0.22 or newer, the dreamer's curate task works there again, and its retrospective task runs there for the first time. It also carries a long list of fixes across caching, compression, Pi, the CLI, config handling and search.

Upgrading

  • The database moves from schema v91 to v94. Three migrations run the first time the new version opens context.db: v92 records the database's single-store state and adds boundary columns to compartments, v93 tracks a history revision per session, and v94 stores each session's last good request in pieces instead of one record that grew on every turn. On a 7.5 GB database the first start took about 6 to 45 seconds longer than usual, almost all of it v94, and later starts are normal. The migration now runs on a separate thread, so OpenCode keeps answering while it works, including the /health checks that supervisors such as OpenChamber use.
  • Quit every OpenCode and Pi process before starting the new version. This includes OpenCode 1 and OpenCode 2 servers, Pi and OMP processes, and instances in other projects, because they all share the database. While a process on an older version is still running, the new version refuses to migrate, and its turns fail with OpenCode's generic "Unexpected server error" (the reason is in the Magic Context log). Once every old process has quit, start the new version. After the migration, 0.44.4 and earlier refuse the v94 database, and downgrading the plugin does not downgrade the database.
  • Expect a cache rebuild on a session's first turn after upgrading. The guidance and tool descriptions sent to the model changed. A session usually rebuilds its cached prefix once; one that resumes from a saved request may do so on a later turn instead.
  • Rust transform mode (experimental) needs a one-time offline migration. ck-mc now refuses a store that has not been moved into context.db, with MC-C14: "Magic Context's Rust mode needs a one-time migration of its store. Quit OpenCode and every ck-mc process, then run magic-context doctor single-store migrate." The command backs up both databases first. To roll back, restore ck-mc together with context.db and store.db from that backup.
  • OpenCode 2 needs 2.0.22 or newer. Magic Context creates and deletes its background sessions through the session API that OpenCode 2.0.22 added. On an older OpenCode 2 it stays off and refuses every turn before anything reaches the model, with a notice: "Magic Context is disabled: OpenCode 2.0.22 or newer is required (session.remove and session.compact). Upgrade OpenCode and restart." It never sends a turn it hasn't prepared. doctor prints the requirement next to the OpenCode version it finds.
  • OpenCode 2 does not install plugin updates on its own. Open /plugins, select Magic Context and press ctrl+u, or run opencode plugin update.

One database

  • context.db is the only authoritative store. In Rust transform mode, memories, notes, compartments and session state now live in context.db, shared with the plugin, instead of being copied between context.db and the module's own store.db. store.db keeps only caches that can be rebuilt. OpenCode and Pi without Rust mode already used context.db and need no action beyond the restart above.
  • doctor single-store migrates the store (migrate; --prefer-history <session>=store|context picks which copy of a session's history to keep) and restores a session history the migration left incomplete from its backup (repair-history --from-backup <dir>).
  • Installs with no host (only ck-mc) get a database with npx @cortexkit/magic-context doctor store init, which setup now runs. Without it, ck-mc refuses with MC-C15.

Lower costs

  • Old reasoning leaves the request on every provider. Reasoning from older turns was only cleared on Anthropic routes. It is now removed, with its provider metadata such as OpenAI's encrypted reasoning, on OpenAI, Vertex, Bedrock, OpenRouter and other routes too. The newest assistant turn keeps its reasoning.
  • Models whose reasoning must stay a contiguous run (Fable 5.1, Opus 5.5 and Sonnet 5.5, on any route) have the oldest reasoning trimmed from the front, so the provider never sees a gap that invalidates the rest.
  • Dropping a tool call or message also removes the reasoning tied to it on every provider, instead of writing [cleared] into the reasoning text.
  • Emergency drops skip passes that would reclaim less than 2,000 tokens. Before, a pass could rewrite a 300K-token prefix, and lose its cache, to save under 200 tokens.
  • Far fewer disk writes per turn. The last good request and replay decisions are now stored in pieces, so a turn no longer rewrites a record that grows with the session. On a large session, writes per new-message pass fell from about 3.6 MB to about 0.1 MB, and ck-mc's own writes fell by a similar factor.
  • Faster passes on large sessions. A whitespace check scanned every tag in the session on each pass; on a measured large session the median new-message pass went from 780 ms to 100 ms. Rust mode caches its compartment boundary checks between passes.
  • Identical parallel reads are deduplicated. Duplicate-tool cleanup only knew MCP-prefixed tool names, so it never matched OpenCode's and Pi's own read, grep and glob. When one reply makes the same call twice, the older copy is now dropped on the next pass that rebuilds the cache anyway, and a protected newest copy no longer keeps an older one alive.
  • A restart no longer re-splits embedded history. After every start, the first check of which history still needed embedding tokenized the whole session's text again. Magic Context now records how each compartment was split and skips that work while the text is unchanged (#604).

A failed pass is never sent unmanaged

  • The last good request is replayed, or the turn is refused. When a stage that changes the request fails (for example, tagging under a busy database), Magic Context used to continue and could send the conversation without its drops, once 2.5 times larger than the turn before. It now sends the last good request again or refuses the turn with MC-S06: "This request was not sent: Magic Context could not finish preparing it, and without that preparation it could be far larger than the previous request. Send your message again."
  • A request estimated above the context limit is refused when its pass was degraded in a way that could change or grow it. Pi refuses the same way instead of falling through to the raw history.

For agents

  • ctx_expand tag=N recovers an item by its tag. It accepts the number from a §N§ prefix or a [dropped §N§] placeholder and returns that text or tool call, including dropped ones. Before, agents passed the tag to message=, which counts raw messages and often recovered a neighbouring item (#585).
  • Explicit self-tagging guidance. Where tag prefixes are shown, the guidance now tells the agent to start each reply that has text with the next tag number, and that a reply of only tool calls gets none. This makes the stored text of a reply match what the provider returned more often, which routes that continue from earlier replies need (#582).
  • Tool descriptions match what the tools do (#575). ctx_search says an empty sources list searches everything and lists primer; ctx_note says an omitted filter includes pending smart notes and that reads take at most 50 IDs; ctx_memory no longer advertises a limit it ignores.

OpenCode 2

  • Background sessions use OpenCode's own lifecycle. Each historian and dreamer run gets a new session, under your session when there is one, and Magic Context deletes it through OpenCode's session API when the run ends. Background sessions that earlier versions recorded for reuse are deleted in small batches at startup (#589, #594).
  • Background runs survive OpenCode compacting them. When a historian or dreamer prompt was large enough for OpenCode 2 to compact its new session before the first step, Magic Context no longer recognised its own prompt and refused every run with hidden_prompt_unrecognized. Those runs now go through.
  • The retrospective task runs on OpenCode 2. It had no way to read OpenCode 2 history, found nothing, and still reported success. Manual and scheduled runs now read your messages from OpenCode 2's store (#602).
  • Skipped tasks are recorded as skipped, on every host. A dreamer task that cannot run (compress-cues with mural off, a retrospective with no history source, a Pi model chain with no available model, or a run held back by the single-store migration) now shows as skipped with its reason in run summaries and /ctx-status, not as a success (#602).
  • A refusal before the model is its own error. When Magic Context refuses a background request before it reaches the model, the run now fails with MC-D12, "Memory maintenance was refused before reaching the model.", and points to the log, instead of MC-D02 with advice to check the model connection (#602).
  • Tool calls are read the same way as on OpenCode 1. A call whose arguments arrive wrapped is recovered, and a wrongly typed field no longer throws; ctx_search had answered "query is required".
  • After a provider rejects a request as too long, the next turn keeps the size the rejection reported instead of going back to the smaller reading from the previous reply, so recove...
Read more

Dashboard dashboard-v0.18.2

Choose a tag to compare

@github-actions github-actions released this 03 Oct 00:41

Dashboard v0.18.2

Fixes for Broca sessions, dreamer cards, the config editor and the serve mode. Works with Magic Context 0.44.x.

Broca sessions show their cache data

Broca 0.3.166 and later write a newer log record format for sessions that use scopes, steers or module tool calls. The dashboard treated those records as a damaged file and dropped the whole session, so these sessions showed no cache data. It now reads them. A record in a format newer than this build knows stops the read at that point and shows a notice, and the entries before it are kept.

Dreamer cards show the latest run (#596)

A task card showed a provider error from any earlier failed run, even after later runs succeeded. Cards now reflect the newest run only.

The config form keeps your comments

Saving from the structured config form rewrote magic-context.jsonc without its comments. Edits now change only the values you touched, and comments stay where they were. Config saves also follow a symlinked config file to its target, keep the file's permissions, and no longer delete the old file before the new one is in place.

Other fixes

  • Serve mode no longer stalls other requests while a slow database read runs.
  • The dashboard follows the database path the plugin uses, even if it changes after the app starts.
  • Memory search escapes backslashes correctly, and paging past the full-text results no longer mixes in results from the fallback search.
  • A config file with a trailing comma followed by a comment now parses.
  • Pi session details reuse cached parent sessions, notice when a parent changes, and keep the cache bounded.
  • Cron descriptions use the right ordinals (21st, 22nd, 23rd), and invalid field values are rejected instead of described.
  • The session list keeps loading pages while you stay at the bottom.
  • The log view labels note nudges correctly and names each bust cause once.

v0.44.2

Choose a tag to compare

@github-actions github-actions released this 29 Sep 18:28

This patch release is mostly about Windows and OpenCode 2. Magic Context no longer opens console windows that steal focus (#553), OpenCode 2 stays responsive while Magic Context's storage opens (#554), a git project can no longer split into two identities, and doctor merge-identities repairs existing splits (#555). It also deletes finished hidden sessions on OpenCode 2 (#558), restores the historian and dreamer on some OpenCode 1 setups after a 0.44.1 regression (#560), unwedges Rust-mode sessions stuck on a compaction marker (#561), stops a reply made only of Magic Context's markers from stalling a session (#563), keeps OpenCode responsive while history embeddings catch up (#564, #565), and never sends an unreduced conversation when the database is busy.

Upgrading

  • No schema change. The database stays at v91, so hosts on 0.44.0, 0.44.1 and 0.44.2 can share it and no coordinated restart is needed.
  • If you pinned 0.43.2 because of #554: 0.44.2 fixes the boot stall 0.44.0 could cause, but the restart storms in #554 also happened on 0.43.2 and are still being investigated. If your database is still at v90, the first 0.44.2 start migrates it to v91, after which 0.43.x refuses to open it, so upgrade every host that shares the database.
  • OpenCode 2 does not install plugin updates on its own. Open /plugins, select Magic Context and press ctrl+u, or run opencode plugin update.
  • Existing identity splits are not merged automatically. Run npx @cortexkit/magic-context@latest doctor merge-identities to list them, then follow "Project identities" below.
  • OpenCode 2 under plain opencode serve: leftover hidden sessions are removed by doctor --fix with OpenCode closed (see "Hidden sessions on OpenCode 2" below).

Windows (#553, @devsiac; #554, @morpheus9393)

  • No more console windows. Process lists, git calls, update checks, Pi's historian and dreamer runs and doctor opened PowerShell and CMD windows that took keyboard focus. Every child process Magic Context starts is now hidden.
  • OpenCode 2 answers /health while Magic Context's storage opens. 0.44.0 checked for other running hosts with synchronous process lists before opening the database, which on Windows could stall the server long enough for a supervisor to kill and restart it. (The restart storms reported in #554 also occurred on 0.43.2, with many OpenCode instances sharing one database; that part is still under investigation.) Those checks are now asynchronous and time-limited, so the server keeps answering while Magic Context starts. A slow but healthy open still registers Magic Context's tools if it finishes within 15 seconds. If storage stays unavailable longer, turns are refused with a notice until it opens, and restarting OpenCode brings the tools back.
  • The "another Magic Context RPC server is active" log line now appears only when that server is actually running. Before, it appeared for any recorded server, live or not.

Project identities (#555, @morpheus9393)

  • A git project keeps its git: identity across restarts. If git failed right after a restart (dubious ownership, a slow git rev-list, a file not yet readable), the directory got a dir: identity, and memories written then were invisible to the project's normal sessions. Magic Context now records each project's git identity in its storage folder. A directory with git metadata never gets a dir: identity: if git fails, the recorded identity is used, and if none is recorded yet, memory features pause for that session.
  • allow_home_project recognizes Windows spellings of the home directory (drive-letter case, forward and back slashes, \\?\ prefixes), so a home session no longer slips past the check. A home directory that is a git repository uses its git: identity.
  • doctor reports split projects. It warns when one directory has more than one identity and shows what is stored under each.
  • doctor merge-identities repairs a split. Without arguments it lists the splits it finds. --from <identity> --to <identity> previews exactly what would move without writing anything, and adding --apply performs the merge. It refuses while OpenCode, Pi or ck-mc has the database open, prints the backup location and restore commands, backs up context.db, and merges in one transaction. Identical memories are combined, and different memories are both kept. Running it twice is safe. Projects in Rust mode are refused because their memories live in the module's store. The older merge-identity spelling still works. Details: Merge split project identities.

Busy database

  • Magic Context never sends an unreduced conversation because the database is busy. Before, a locked context.db could make a turn go to the model without Magic Context's changes, and in Rust mode an unreachable module could do the same whenever the raw history happened to fit. Now a turn retries the lock for up to about 16 seconds, then replays the last request Magic Context built for the session. If neither works, the turn stops with "Magic Context's database is busy (another process held it too long); send your message again." OpenCode 2 also shows a toast. This applies on OpenCode 1, OpenCode 2 and in Rust mode. With compaction off, turns pass through as before.
  • Background work doesn't retry the lock. Only the turn being sent retries; the historian, embeddings and other background jobs try once and pick the work up on their next run, so a held lock stalls the host for less time.
  • The last good request replays more often. On OpenCode it was checked against messages Magic Context had already edited, so it was rejected as changed. It is now checked against the original messages. An assistant turn that starts with two thinking blocks from the same message is now accepted for Anthropic models, as is a turn after an empty errored assistant message. The thinking-block checks are shared by OpenCode, Pi and Rust mode.

Rust mode

  • A compaction marker no longer wedges a session (#561, @iceteaSA). When the marker landed on a notice another plugin had added as a synthetic user message, every full pass failed with a coverage gap and every turn was refused. The marker no longer changes how that message is classified, and it is never placed on a synthetic message. Sessions already in this state recover on their next full pass. The raw-fallback refusal log line now shows whether its size estimate was trusted.
  • Slow module responses are retried, not failed. A request that times out while the module is still working gets one more wait of up to 45 seconds. A full resync after need_full_sync gets its own 45-second budget instead of whatever the first request left. A session parked after repeated failures tries the module again on the next turn when it has no last good request to replay.
  • Images are counted by their size in pixels. The historian trigger counted an inline image by the length of its base64 data, so a session with a few screenshots looked millions of tokens over budget. Images now count as width × height / 750 tokens (1 to 4,500 per image, 1,200 when the size can't be read), the same rule TypeScript mode uses. Sessions without images are unchanged.
  • Passes on long sessions use less time and memory. They no longer copy stored tag contents, repeat block and timestamp lookups, or count tokens for attachments they don't need.

Embeddings (#564, #565, @null-axiom)

  • Embedding catch-up no longer freezes OpenCode. After history embeddings were turned on, or the embedding provider or model changed, Magic Context re-embedded the history on OpenCode's main thread, and the app stopped responding for seconds at a time, Stop button included. The catch-up now runs after the turn in short slices that yield in between, paced so it can't take over the host. It is slower as a result. In a test with 1,500 compartments on OpenCode 1, the server answered every health check during catch-up (at most 323 ms).
  • A fully embedded session isn't checked again every turn. The coverage check re-chunked and re-counted a session's whole history on each pass. It now remembers a finished session until new history is written or the embedding model changes, and counts without re-reading everything.
  • Compartments that fail to embed back off. Instead of being retried every turn, they wait longer between attempts.
  • The local embedding model still runs inside OpenCode's process. It's paced now, but a large catch-up with the local model can still slow the app. Leaving the app idle until catch-up finishes, or setting embedding.provider: "off" while you work, avoids it.

Replies made only of markers (#563, @kido5217)

  • A reply that is only Magic Context's markers no longer stalls the session. Some models, especially small local ones, end a turn with nothing but notation such as §672§ [dropped §672§] or [cleared]. The check that neutralizes such replies missed a leading §N§ tag and didn't know [cleared], so the reply was sent back to the model and encouraged more of the same. It now recognizes these forms, and the same rule applies in TypeScript mode, Pi and Rust mode. It still leaves prose that merely mentions a marker alone, and it changes a reply only on a pass that already rebuilds the prompt cache. In Rust mode, an assistant reply that is only whitespace is now replaced the same way, as TypeScript mode already did.

OpenCode 1

  • The historian and dreamer get the model's output limit again (#560, @Sugaroverdose). 0.44.1 removed it when historian.maxTokens or dreamer.maxTokens was unset, and some providers then returned no output at all. An unset cap now leaves OpenCode's own limit in place. OpenCode 2 and Pi were not affected.

Hidden sessions on OpenCode 2 (#558, @morpheus9393)

  • **Finished historian and dre...
Read more

Dashboard dashboard-v0.18.1

Choose a tag to compare

@github-actions github-actions released this 29 Sep 13:51

Dashboard v0.18.1

Fixes for the Cache tab and for converted OpenCode 2 stores. Works with Magic Context 0.44.x.

Converted OpenCode stores show every session (#559)

An OpenCode store converted from 1 to 2 keeps older sessions in OpenCode 1's tables and adds new ones to session_v2. The dashboard read only one of them, so newer OpenCode 2 sessions were missing, or older ones were. It now reads both and merges them by session: a session present in both is shown from its OpenCode 2 record, and its messages and cache history are read from there.

Running Broca sessions show their steps

Broca stamps a session's time only when a run starts and when it ends, so the Cache tab saw no change during a run and a gather session stayed at "0 events" until it finished. The tab now dates a running Broca session by its live log file, so steps appear while the run is going.

Cache cards keep one height

A card whose provider reported no cached tokens showed "No cached tokens reported" in the figure slot, which wrapped and made that card taller than the others. The slot now shows a grey dash, with "cache not reported" in small text below it, and every card keeps the same height.

Fewer false cache warnings on OpenAI

For providers that don't report cache writes, the tab estimated the cache it expected from the previous turn's input plus its output. Output isn't re-read from the cache on the next turn, so healthy turns often showed as warnings. The estimate now uses the previous turn's input only.

v0.44.0

Choose a tag to compare

@github-actions github-actions released this 28 Sep 11:46

[!IMPORTANT] > On OpenCode 1, 0.43.x could let OpenCode's own automatic compaction run alongside Magic Context (#538). If no OpenCode config file you use has a compaction key, 0.43.0 to 0.43.2 kept Magic Context enabled while OpenCode 1's automatic compaction, which is on by default, also ran, so both managed the context window. Before 0.43.0, Magic Context switched itself off in that case. From this release, whenever Magic Context manages compaction, it turns OpenCode 1's automatic compaction off for its own OpenCode instance. It no longer depends on reading your config files to do this. Only compaction.auto is changed: manual /compact still works and your prune setting is kept. If you set compaction.enabled: false in Magic Context's config, native compaction is left alone. If you installed with npx @cortexkit/magic-context setup, your config already has compaction.auto: false and you were not affected. If you stay on 0.43.x, add this to your opencode.json(c) to get the same result: > > jsonc > "compaction": { "auto": false, "prune": false } >

This release fixes the rest of what #538 found on long sessions: the context limit changing between models, an extra cache rebuild after a native /compact, and a late usage reading overwriting a newer one. SQLite writes now wait for a lock held by another process instead of failing (#533). The first OpenCode 2 request on a large converted session no longer blocks for minutes (#536). doctor stops offering an OpenCode 2 reconversion that deleted messages (#493). Dropped tool calls no longer show models a placeholder they copy (#513). Queued drops now apply on the first turn after a long idle (#545). Images read by tools on OpenCode 2 reach the model as images, not as base64 text (#539). History search no longer depends on memory.enabled (#543). Transform mode rust now runs on OpenCode 2, and on OpenCode 1 and 2 it runs the historian and dreamer in the host by default. On OpenCode 2, a turn refused because the database can't be opened now says why and goes through again once the cause is gone, without a restart (#546). On OpenCode 1 builds that give plugins a client with a request timer, dreamer tasks no longer fail after five to six minutes. ck-mc refuses a store.db newer than itself instead of half-working on it (#540). Pi tools now report their errors as errors (#547).

Upgrading

  • The schema fence moves from 90 to 91. One migration runs on first open:
    • v91 adds a memory_embedding_watermarks table. It records, per project, the newest memory written by another writer and how far this host has embedded, so memories that did not come from this host still get embeddings. It adds a table and changes no existing rows. The migration is idempotent.
  • Restart every OpenCode and Pi host on the new version at the same time. This covers OpenCode 1 and OpenCode 2 servers, Pi and OMP processes, and instances in other projects that share the database. After the migration, 0.43.2 and earlier (fence 90) refuse the v91 database the next time they open it. With the default fail_closed_blocking: true, they block the primary-session prompt with a recovery error. Update pinned installs too. Downgrading the plugin does not downgrade the database.
  • OpenCode 1 and OpenCode 2 keep separate plugin caches. If both hosts use the same context.db, update both. doctor now reads the schema fence compiled into every cached Magic Context copy on both hosts. When a copy can't open the current database, doctor fails the check and says how to refresh it (see "doctor" below). Run npx @cortexkit/magic-context@latest doctor --fix after upgrading.
  • OpenCode 2: OpenCode 2 does not install plugin updates on its own. Open /plugins, select Magic Context and press ctrl+u, or run opencode plugin update.
  • Expect one prompt-cache rewrite per session on the first turn after the upgrade. The ctx_reduce guidance in the system prompt changed (see "What the agent sees"). This happens once and does not recur.
  • Rust transform mode: the Rust fixes below are in the ck-mc module and apply after a module update and restart. Its own store (store.db) moves from schema 56 to 60. A ck-mc from an earlier release on a newer store logs a warning and keeps running. This release's ck-mc refuses a store newer than itself instead (MC-C13, see "Rust transform mode" below), so rolling back a later update means restoring ck-mc together with context.db and store.db from the same backup. Rust mode on OpenCode 2 needs both this npm release and the updated module.
  • Rust transform mode on OpenCode 1 and OpenCode 2: historian and dreamer completions now run in the host by default. When historian.runner is unset, they run in the plugin on the models configured for OpenCode and are billed to those provider accounts, instead of being routed to the Broca module. Set historian.runner: "broca" in your user-level config to keep the previous behaviour (see "Rust transform mode" below).
  • History embedding no longer follows memory.enabled. With memory.enabled: false and the default embedding.provider (local), session history is now embedded. Set embedding.provider: "off" if you don't want that (see "Historian and memory" below).
  • The CLI runs on Node 22.16 or later on the 22 line, as well as Node 24 and later. Its engines field is now ^22.16.0 || >=24. Node 23 is not supported.

Fixes for long sessions (#538)

  • A native /compact on OpenCode 1.18 cost two cache rebuilds; it now costs one. OpenCode 1.18 rewrote its compaction prompt, so Magic Context no longer recognised the compaction request as an internal agent. It stored that prompt's hash as the session's own, and the next real turn saw the hash change back and rebuilt the cache a second time. The 1.18 compaction prompt is now recognised, so the request is skipped for injection and hash tracking, as on earlier OpenCode versions.
  • One re-anchor after a native compaction. A native compaction leaves Magic Context's stored history boundary pointing at a message OpenCode no longer loads. The first pass after the compaction now rebuilds the cached history block once, with reason host_compaction, so that the boundary is back inside the loaded window. That pass is already paying for a cache rebuild because of the compaction. The rebuild does not repeat, and which history is rendered does not change.
  • A boundary before the loaded window no longer counts as a refusal on every pass. When a resumed session loads only its most recent messages, the history boundary can sit before the first loaded message. Magic Context logged "absent from current messages" and marked the trim refused on every pass. It now checks where the boundary falls in the session's stored message order. If the boundary comes before every loaded message, there is nothing to cut: that is logged once as boundary-precedes-window. That log line used to say the boundary "sorts before the first live message" and the "whole window" was kept, which read as if OpenCode had not loaded the rows after the boundary. Often it had, and the rows were cut earlier in the same pass with the summarized history, or removed because all their tool calls were dropped. The line now says the boundary "precedes the first remaining message" and that the rows between were cut with the summarized history or removed by reduction. If a boundary inside the window is missing, the whole window is still served, the state is counted, and the next pass that rebuilds the cache anyway moves the boundary to the newest compartment end so the trim finds it again. What is sent to the model is byte-identical to before in all of these cases.
  • The context limit is kept per model. The usage handler raised a session's context limit to the largest input the provider had accepted, without checking which model that input was accepted for. After a model switch, the usage event and the next pass could compute different limits for the same model. The stored floor now carries its model and only applies to that model. Every usage event records what its limit came from (catalog window, a limit learned from an overflow error, the largest accepted input, the model), and the log names the inputs that moved whenever the limit changes.
  • A late usage reading from an older step no longer overwrites a newer one. OpenCode 1 publishes one usage event per step of a tool turn and does not wait for a plugin to finish handling one before it delivers the next. An older step's handler that waited on a model-catalog refresh could finish last and replace the final step's larger prompt size with a smaller one, so pressure stayed too low. Magic Context now keeps the newest assistant message per session and ignores an older reading that arrives after it.
  • On OpenCode 1.18.31 and later, a reading over the model's limit reaches the next pass. These OpenCode versions start the next step's transform without waiting for the usage handler. When a reading was above the catalog limit, the handler refreshed the model catalog before recording the reading, so the next pass still saw the previous, lower pressure and deferred work it should have done. The reading is now recorded first and the refresh runs afterwards. Pi had the same ordering, with a cache alert sent before the reading was saved; the reading is now saved first.
  • The "prepared prompt exceeds engine max_context" error is recognised as a context overflow. Some local inference engines reject an over-long prompt with prepared prompt exceeds engine max_context <N>, or with prompt exceeds ... max_context <N>. Magic Context did not recognise that text, so it did not run its overflow recovery and did not learn the limit. Both forms now count as an overflow, and the number after max_context is recorded as the model's context limit. This applies on OpenCode, Pi and Rust mode (Rust: `ck-mc...
Read more

Dashboard dashboard-v0.18.0

Choose a tag to compare

@github-actions github-actions released this 28 Sep 12:10

Dashboard v0.18.0

Works with Magic Context 0.44.0, including OpenCode 2.

OpenCode 2 sessions and projects are listed (#542)

The dashboard read sessions from OpenCode 1's session table. OpenCode 2 keeps its sessions in session_v2, and a fresh OpenCode 2 store has no session table at all, so no OpenCode 2 session was listed and the Projects page stayed empty. A store converted from OpenCode 1 showed only the sessions from before the upgrade. On an OpenCode 2 store, the Projects page, the Sessions list, session details and the Cache tab's session list and titles now read session_v2.

Logs page reads the OpenCode 2 log

The Logs page read only the OpenCode 1, Pi and OMP logs. It now also reads the OpenCode 2 plugin's log, at opencode2/magic-context/magic-context.log in the temp directory and logs/magic-context.opencode2.log in the storage directory.

OpenCode 2 filter in the Sessions viewer

The Sessions viewer's harness filter now offers OpenCode 2, next to OpenCode, Pi and OMP, and remembers it like the other choices.

Cache tab follows a live OpenCode 2 turn

OpenCode 2 updates a session's time when a prompt is sent and not again during the turn, so the Cache tab saw no change until the next prompt. It now dates an OpenCode 2 session by its newest message as well, so steps appear while the turn runs. If an OpenCode 2 store's session_message table has no time_updated column, the tab still lists its sessions but refreshes them only when a new prompt starts, and says so above the session cards.

The Cache tab's OpenCode 2 filter listed nothing before; it now lists OpenCode 2 sessions, and the OpenCode filter no longer includes them.

Broca runs are shown as run totals

Broca's run index records one usage sum per run, covering every model step in it. The Cache tab compared each run's sum with the previous run's, which showed busts that did not happen and a red 0% for a session's first run. A run total is now labelled RUN TOTAL and shows its own cached share; it is never marked stable or bust, and never compared with another run. A run that did not complete normally names how it ended, for example RUN TOTAL · ERROR. Every Broca session is now listed, not only historian and dreamer sessions.

Broca steps are read live

The Cache tab reads each Broca session's model steps from Broca's write-ahead log files as Broca writes them, including its archived logs, and shows one row per step, compared step against step as for OpenCode. Steps of a run that is still going appear, and a session whose only run is still active is listed. The files are only read, never written. When a session's log can't be read, its runs are shown as run totals.

Broca cache counts that were not reported

When a provider does not report cache reads or cache writes, Broca leaves the count out. The Cache tab showed these as 0; it now shows "not reported" in the list and in the timeline tooltip, and a reported 0 still shows as 0. A row with no reported cache reads shows "No cached tokens reported" instead of a percentage and is left out of the session's cached share. A turn where only some rows reported cache writes shows its total marked "(partial)". The timeline tooltip now also lists cache writes.

Session header and cards in the Cache tab

Above the timeline, the Cache tab shows the selected session's full name and its latest provider and model, with "(+N)" when the loaded rows used more than one model; the tooltip lists them all. For a Broca session it also shows the harness Broca ran it for ("via …") and puts the project root in the tooltip. On OpenCode 2 the model is read from model.id, where OpenCode 2 stores it.

Session cards shorten long names, such as alfonso:consult-<uuid>, and show the full name in a tooltip. A card is shown in a neutral color instead of red when no row in the window read anything from the cache, or when only the session's first run is loaded. A card of Broca run totals counts runs instead of events.

Pi todowrite default in the config editor

When the config does not set todowrite.enabled, the config editor now shows Pi's todowrite tool as off, matching the plugin's new opt-in default. Magic Context 0.44.0 still turns the tool on when the key is unset, so on 0.44.0 set todowrite.enabled to true or false yourself.

Smaller changes

  • A session's first row in the Cache tab is labelled COLD START in blue instead of NEW SESSION, with a tooltip saying nothing was cached yet.
  • Session cards in the Cache tab are slightly wider.

v0.43.1

Choose a tag to compare

@github-actions github-actions released this 25 Sep 00:24

If you run OpenCode 2, update now. On OpenCode 2.0.15, 0.43.0 could fail every turn of a session with "Schema validation failed" (see the first fix below). This release fixes that, runs the seven dreamer tasks OpenCode 2 could not run in 0.43.0, and fixes a set of smaller problems on OpenCode 1, Pi and Rust mode.

Upgrading

  • Updating on OpenCode 2. OpenCode 2 doesn't install new Magic Context releases on its own: it installs the plugin once and then only marks it "update available" in /plugins. To install this release, open /plugins and press ctrl+u, or run opencode plugin update. If your config pins a version (for example @cortexkit/opencode-magic-context@0.42.6), change it to @latest first. More on the OpenCode 2 page.
  • No database change. The schema fence stays at 90 and nothing migrates, so 0.43.0 and 0.43.1 can share a database.
  • Rust transform mode: some fixes below are in the npm package (they apply after an OpenCode restart) and some are in the ck-mc module (they apply after a module update and restart). Each item says which. Update the module as usual.

Fix for a failure that stopped turns

  • OpenCode 2: "Schema validation failed" on every turn (#493, MCKLtech). OpenCode 2.0.15 checks every request against its own message schema, and two parts Magic Context adds itself reached it in OpenCode 1's shape:

    • the synthetic todo reminder, placed in the latest assistant message once the agent has used todowrite, arrived as an OpenCode 1 tool part;
    • the memory mural, for projects that have one on an image-capable model, arrived as an OpenCode 1 file part.

    OpenCode 2 rejected the request. Both parts are replayed on every later pass, so once either appeared, every turn after it failed too, with or without an emergency drop, including the retry served from cache. A dropped tool call kept as a skeleton in a session converted from OpenCode 1 had the same problem and is fixed as well. All three are now converted to OpenCode 2's own tool-call, tool-result and media parts. Any other part the plugin does not recognise is left out of the request and logged instead of being sent. Every OpenCode 2 test now checks each request the plugin returns against OpenCode 2's message schema, and the two failures above are reproduced on a real 2.0.15 host as tests. The reporter's session had neither images nor files; the todo reminder was their case.

OpenCode 2: all dreamer tasks run

  • The seven dreamer tasks listed as unavailable in 0.43.0 now run on OpenCode 2: map-memories, verify, verify-broad, curate, retrospective, maintain-docs and refresh-primers. They need a tool loop, which the hidden-completion runner lacked, so 0.43.0 refused them with MC-D08. Each one now runs in its own hidden OpenCode 2 agent session. Every tool is denied by default and each task is allowed only the tools it needs (maintain-docs and map-memories read files, retrospective searches, curate edits memories), with a cap on how many steps it can take. Their results are read by the same code that reads them on OpenCode 1. The "Seven dreamer tasks cannot run" item in the 0.43.0 known limits no longer holds; the other limits listed there still do.

Other fixes

  • /ctx-* commands on OpenCode Desktop showed nothing and left the session busy (#523, Tahmid-kabir-addin). OpenCode Desktop (seen on 1.18.27) sends a slash command through the host's command endpoint, not as chat text. The command ran, but its result was never shown and the host never marked the session idle, so a new session stayed busy. The result now appears in the session, an empty session gets a title, and the session goes idle afterwards. All six commands are tested through that endpoint on a real OpenCode host.
  • The historian could stay suppressed while usage kept climbing (#524, iceteaSA). When queued ctx_reduce drops were projected to bring usage below target, the historian skipped its run on the assumption that the next pass would apply them. Queued drops only apply on a pass that already rebuilds the prompt cache, though, and in that state the rebuild they were waiting for was the historian's own publish, the one being skipped. In the reported session nothing was compacted or reclaimed for about 30 minutes while usage rose from 61% to 70%, and a larger ctx_reduce made it last longer. Queued drops now count toward the skip only on a pass that can apply them; otherwise the historian runs and the drops land with its publish. Fixed on OpenCode, Pi and Rust mode (Rust: ck-mc).
  • Dreamer provider refusals are retried (#518, iceteaSA). When a fallback model was refused by its provider before it produced anything (an exhausted account pool, for example), the refusal was on the host's assistant message, but the run was recorded as empty_completion with no provider error and scheduled like a permanent failure. It is now recorded as a provider error with the provider's own text, and the task is retried instead of being set aside as permanently failed.
  • Rust mode: last-known-good replay was refused on any session with a memory mural. The mural is an image in the first block, and the fit estimate treated every image as uncountable, so every estimate on those sessions was untrusted. After a module restart or stall, last-known-good replay was refused (lkg_fit_untrusted), the raw array went out instead, which is over the window on a long session, and you saw "engine is reconnecting". Inline images are now counted from their dimensions, capped per image. (npm package.)
  • Rust mode: full arrays every turn when OpenCode adds an empty summary. OpenCode 1 can add an empty summary to a user message after it has been served. The plugin read that as a change to the served prefix, so it sent the full message array every turn instead of the new messages alone, and last-known-good replay no longer matched its snapshot. The empty field is now ignored; any real change to a served message is still caught. On the same hosts tool definitions can arrive without an agent name, and the plugin dropped their measurements, which also left replay estimates untrusted; they are now kept. (npm package.)
  • Rust mode: no extra fold on the first turn on OpenCode 1.18.31 and 1.18.32. These hosts can transform the messages before the system prompt on a session's first turn, so the second turn looked like a new prompt and paid a full fold. The first turn's identity is now reused while the system prompt is unchanged; a real prompt change still rebuilds the cache. (npm package.)
  • Rust mode: the historian could not get past one oversized tool arc. A 0.43.0 change started checking the complete historian prompt against the model's window before sending. A single tool arc too large for that window was still trimmed by its own size alone, so the complete prompt, with the historian's instructions added, was refused every time and that stretch of history was never summarized. The arc is now trimmed until the complete prompt fits. (ck-mc.)
  • Rust mode: a subagent's late tags rewrote its cached prompt. 0.43.0 released a subagent's late-added tags on any pass, on the reasoning that a subagent has no cached prompt to protect. It does, so a tag that first appeared on an already-sent part changed bytes the provider had cached, on a pass meant to change nothing; one worker session rewrote 220,000 tokens this way. Late tags on a subagent now wait for a pass that rebuilds the cache anyway, as they do on a primary session. Separately, the plugin now knows whether ctx_reduce is available from the session's very first prompt, so a subagent's first request is tagged from the start instead of all its content counting as late. (npm package and ck-mc.)
  • Dashboard: runs whose provider reports no cache figures show that plainly. Cache Diagnostics used to show them as a 0% hit rate, in the colour for a bad hit rate. They now read "No cached tokens reported" in neutral text, and session totals count only the runs that reported cache figures. This ships with the next dashboard release.
  • Tests no longer leave three temporary directories behind on every run (#528, iceteaSA).

Known open

  • Usage on sessions converted from OpenCode 1 can be overestimated. In the #493 report, the plugin's estimate of the request put the session at 109% of its window while the provider reported 82.8%, and that estimate started an emergency drop. The schema failure it led to is fixed above; the estimate gap itself is not fixed in this release.

v0.43.0

Choose a tag to compare

@github-actions github-actions released this 24 Sep 16:53

Warning

Moving existing OpenCode 1 sessions to OpenCode 2? Run doctor --fix before you upgrade OpenCode. Stop OpenCode, then run npx @cortexkit/magic-context@latest doctor --fix. Compaction markers written by earlier Magic Context versions lack the time.completed field OpenCode 2's conversion requires, so OpenCode 2 drops them, and a long session then loads its entire history on open, using extreme memory and CPU. doctor --fix stamps the field on Magic Context's own markers only. If OpenCode 2 has already converted your store, see "Converting an OpenCode 1 store (and back)" below for the recovery.

Magic Context now supports OpenCode 2. Sessions on a 2.x host get the same context management, memory, history, search, notes and /ctx-* commands as on OpenCode 1. An OpenCode 1 store converts when OpenCode 2 first opens it, and converts back if you downgrade. The last two releases had a failure that stopped turns on OpenCode 2: 0.42.5 does not answer at all on a 2.0.11 host, on a fresh data directory or an aged one, and 0.42.6 refuses every turn on any data directory that has ever held OpenCode 1 sessions, and every turn of any session once it passes its context threshold. If you run OpenCode 2, this is the first release to use.

This release replaces the 0.42.7 and 0.42.8 builds that were prepared but never published. Everything they contained is included here.

Upgrading

  • The schema fence moves from 85 to 90. Coming from 0.42.6, five migrations run on first open:

    • v86 adds a per-session tags_version to session_meta, maintained by triggers on tags, so a write from another process no longer forces a full tag-map reload.
    • v87 decides each session's harness label from the OpenCode store, read-only. Newer session_message/session_v2 activity means opencode2; newer message/session activity means opencode; a session absent from both is left alone. It replaces migration v85 from 0.42.6, which rewrote every opencode2 row to opencode and so mislabelled a real OpenCode 2 install (#475, qoole). v85 is now inert (its version row is still recorded) and v87 repairs what it did, in whichever direction the store supports. An unreadable store changes nothing, logs once, and lists the skipped sessions in doctor.
    • v88 adds session_meta.coordinate_generation and compartments.rebase_status for the store-conversion rebase described under OpenCode 2.
    • v89 adds an indexed message_time_ms to the message search index for ctx_search date ranges. Existing messages are dated by a background backfill after the upgrade; a date-bounded search skips messages the backfill has not reached yet.
    • v90 records the owner process id on historian leases, so a lease left by a process that has exited is reclaimed right away instead of blocking the historian until it expires.

    All migrations are idempotent.

  • Restart every process that shares the database at the same time: OpenCode servers, Pi and OMP processes, and instances in other projects. A new build will not migrate while an older process holds the database. Once the migration has run, an older build (0.42.6 or earlier, fence 85 or lower) refuses the database at its next open instead of running without context management. With the default fail_closed_blocking: true it blocks the primary-session prompt with a recovery error. Update pinned installs too. Downgrading the plugin does not downgrade the database.

  • Changing the historian and dreamer models no longer needs a restart. Keys marked Live in the configuration reference now reload on their own: historian and dreamer models, fallbacks and variants/thinking levels for each harness, dreamer task lists and schedules, mural.model, historian_timeout_ms, historian.two_pass, the commit-cluster trigger, git-commit indexing, memory.auto_promote and toast_duration_ms. A change applies from the next historian run, dreamer run or dream-timer tick; a run already in progress keeps its settings. The same applies on OpenCode 1, OpenCode 2, Pi and the Rust module's historian chain. If the edited file is malformed, the last good configuration stays active and /ctx-status reports the error. Everything else still requires a host restart. See Changing config without a restart. The dashboard marks live keys with a badge.

  • Expect one prompt-cache rewrite per session on the first turn after the upgrade. The guidance block and the ctx_* tool descriptions changed (see "What the agent sees"). This happens once at the upgrade and does not recur.

  • Local embeddings re-embed once. Both plugins now bundle Transformers 4.3.0 with optional onnxruntime-node 1.30.0, which clears the high-severity adm-zip advisories in the published packages (#480, ice-fortress). The native runtime produces different vector bytes from the same model file (the WASM runtime does not), so the local embedding identity now includes the runtime versions, and existing vectors are rebuilt instead of mixed with new ones.

  • Moving an existing install to OpenCode 2: stop the host and run magic-context doctor --fix before you upgrade OpenCode. See "Converting an OpenCode 1 store" below for why and for the recovery if conversion already happened.

  • Rust transform mode fixes ship in two places: some in the npm package (take effect after an OpenCode restart) and some in the ck-mc module binary (take effect after a module restart). Each item below says which.

OpenCode 2

What works

Built against the OpenCode 2.0.5 plugin API and exercised on real 2.0.5, 2.0.11, 2.0.12, 2.0.14 and 2.0.15 hosts. The host-behavior test suite runs against OpenCode 2.0.15 in CI next to OpenCode 1, Pi and OMP, and every difference the host imposes is declared in PARITY.md rather than patched over. On 2.x you get:

  • the transform, tagging, ctx_reduce drops, historian compartments, memory, notes, search and emergency handling, as on OpenCode 1;
  • all six /ctx-* commands, registered with the host (listed by its command API and runnable against a session with no TUI);
  • the real terminal sidebar and the same /ctx-status dialog OpenCode 1 draws;
  • historian and text-only dreamer runs on their own configured models, in hidden sessions the plugin cleans up;
  • per-model ctx_* tool descriptions (OpenCode 2 carries the tool map with each request).

Rust transform mode is not available on OpenCode 2 in this release; see MC-S06 below.

The new OpenCode 2 page in the docs covers installing on 2.x, moving an OpenCode 1 install, what converts in each direction, the known limits and where the log lives.

Converting an OpenCode 1 store (and back)

OpenCode 2 converts an OpenCode 1 opencode.db in place the first time it opens it and keeps the v1 tables beside its own. Several things had to hold up across that conversion:

  • Session coordinates survive the conversion, in both directions (#492 finding 1, null-axiom). When OpenCode 2 opens a 1.x store it splits synthetic content into rows of its own and replaces completed compaction pairs with one native record. Every positional ordinal Magic Context had saved for that session moved by one or more: a compartment covering messages 4–9 could omit its own last message or take in one outside it, a queued ctx_reduce drop for one fragment applied to the merged text, and the message index carried the last message twice. Downgrading moves them back. Each session now records the projection its coordinates were derived against (coordinate_generation). The first pass after a flip in either direction re-derives every saved coordinate from surviving message ids in one transaction: compartments and their facts, the message index and its watermarks, chunk windows, note anchors and the protected-tail floor. It then pays one priced fold for that flip. A compartment whose anchor no longer resolves is marked unresolved: range recovery refuses it, but it still renders in <session-history> and stays readable by id, and it is re-evaluated on the next flip. Nothing is guessed. Queued drops that would broaden are discarded and reported. A session first seen by this build is stamped, not rebased, unless its store was already converted before this build first saw it; then it rebases from the projection its harness label implies. doctor lists sessions still pending a rebase and unresolved compartments per session, and the log carries one line per rebased session. Verified by driving a session through a real 1.18.30 host, a real 2.0.5 conversion, and 1.18.30 again, with the plugin loaded on every boot. Fresh OpenCode 2 sessions, Pi and project memory were never affected.
  • Magic Context compaction markers survive the conversion. OpenCode 2 drops a v1 compaction pair whose summary has no time.completed. Older Magic Context markers omitted that field, so converted long sessions could load their entire history, use extreme memory and CPU, and never reach the plugin. New markers stamp matching created and completed times, and magic-context doctor reports affected Magic Context rows without touching native summaries. Before upgrading OpenCode, stop the host and run magic-context doctor --fix to backfill them. Correction (2026-09-25): an earlier version of these notes recommended clearing kv.migration.v1-v2 to reconvert a store when doctor reported missing converted markers. Do not do that: reconversion rebuilds every session from its OpenCode 1 rows and deletes everything added on OpenCode 2 since the first conversion (#493). No recovery is needed. Magic Context on OpenCode 2 keeps its own history boundary, and newer doctor versions report a missing converted marker as informational. If you already ran it, restore opencode.db (with its -wal...
Read more

Dashboard dashboard-v0.17.0

Choose a tag to compare

@github-actions github-actions released this 24 Sep 17:25

Dashboard v0.17.0

Works with Magic Context 0.43.0, including OpenCode 2.

OpenCode 2 sessions

The dashboard reads OpenCode 2's store as well as OpenCode 1's, including a store OpenCode 2 has converted in place. A store counts as OpenCode 2 only when the OpenCode 1 message tables are absent, so an OpenCode 1 store that merely contains the newer tables is no longer misread. A session converted from OpenCode 1 keeps its id, and the dashboard now matches it by that id across both labels, so its timeline uses the real context limit instead of scaling to its own largest prompt.

Model pickers survive OpenCode 2's cold start

On a cold start opencode models can print nothing for over 30 seconds while OpenCode 2 installs its plugins. Model discovery now waits up to 45 seconds, shows a readable error (such as "timed out after 45s") instead of an empty picker, retries once on its own and offers a manual retry, and never replaces a catalog that already loaded with an empty one.

Live config keys are marked

Settings that take effect without a restart (historian and dreamer models, fallbacks and variants, dreamer schedules and several others) carry a Live badge in the config editor. The list comes from the same schema mark that drives the docs, so the two cannot disagree.

Cache Diagnostics shows Broca runs

Runs recorded in Broca's run index appear as their own harness, with the same cache figures and timeline as other sessions. The index is opened read-only. Each Broca run is one point on the timeline, because Broca keeps usage per run rather than per step.

Compartments count includes the newest history

The context breakdown now counts compartments served in <session-history-since> as well as <session-history>, so a session whose main history block was built before its first compartment no longer shows a near-zero Compartments figure.

Log viewer reads the current fleet log format

The log viewer parses the fleet's current log format (schema 2), decodes the control-character escapes it writes inside field values, and still reads the older formats.

Smaller changes

  • Historian runs that timed out or returned empty output are labelled "Timed out" and "Empty output" in the session viewer.
  • The /ctx-session-upgrade reference is gone from the session viewer, matching its removal from the plugin.