Skip to content

[v2] No idle-time compaction: a large session is re-sent uncached after its prompt cache expires #50777

Open

Description

@sergiopadure

Description

When a session sits idle longer than the provider's prompt-cache lifetime (Anthropic 5 min or 1 h, OpenAI 30 min), the next message re-sends the whole context uncached. On a long session that is the most expensive request it makes. Compacting an idle session before the user comes back avoids that, but OpenCode v2 has no way to do it:

  1. No idle trigger. Compaction runs only on context overflow (compaction.auto) or manually.
  2. Plugins can't do it either. The plugin context's ctx.session exposes create, get, switchAgent, switchModel, prompt, generate, command, synthetic, interrupt, update, move, wait and context, but not compact. The core session service has compact (packages/core/src/session.ts) and the server has POST /api/session/:sessionID/compact. The only built-in commands are init and review, and calling the HTTP route from a plugin would need the server password, which in service mode comes from the service config, not the environment.

The built-in warming option shows the gap: it keeps an idle session warm, but when warming ends nothing can compact the session.

Expected: either an idle-compaction option (for example compaction.idle: { after: "4 hours", minTokens: 100000 }), or compact exposed on the plugin session API so a plugin can do it. The second looks small: add compact to the host session object (packages/core/src/plugin/host.ts), one adaptApiMethod line in packages/core/src/plugin/promise.ts, and "compact" in SessionDomain in packages/plugin/src/promise/session.ts and packages/plugin/src/effect/session.ts.

Plugins

A local server plugin that keeps idle Anthropic sessions warm and compacts them at the end of the idle window. It feature-detects ctx.session.compact.

OpenCode version

2.0.14 (source checked on the v2 branch at 1746672)

Steps to reproduce

  1. Write a server plugin that calls ctx.session.compact({ sessionID }).
  2. typeof ctx.session.compact is "undefined", and no other plugin API compacts a session.
  3. Leave a large session idle past the cache lifetime. Nothing compacts it, and the next message pays for a full uncached write of the context.

Operating System

Ubuntu 26.04 LTS

Terminal

N/A (background service, opencode serve --service)

Activity

  1. github-actions commented on Sep 23, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    If the plugin API gap is the primary concern, #49389 is the closest match and may be the best place to continue discussion.

  2. changed the title [-][v2] No idle compaction, and plugins cannot trigger compaction (session.compact missing from the plugin context)[/-] [+][v2] No idle-time compaction: a large session is re-sent uncached after its prompt cache expires[/+] on Sep 23, 2026
  3. sergiopadure commented on Sep 23, 2026

    @sergiopadure
    ContributorAuthor

    Thanks for the pointers. The plugin half of this report duplicates #49389 (item 1) and #47229, so I'll follow those for session.compact on the plugin context.

    I'm narrowing this issue to the part none of them covers: compaction after idle time. #40113 asks for a size-based threshold, which v2 already has as compaction.auto. This one is about compacting a large session before its prompt cache expires, so the first message after a long break doesn't re-send the whole context uncached. Retitled to match.

  4. opencodejr commented on Oct 28, 2026

    @opencodejr
    Contributor

    Thanks for the detailed write-up, @sergiopadure! You're asking for a way to compact a large idle session before its prompt cache expires: either a built-in idle-compaction option, or compact exposed to plugins.

    ctx.session.compact is already available. It was added in #52385 and has shipped since v2.0.22. That PR made the changes you describe: the host session object, the promise adapter, and "compact" in SessionDomain for both the promise and effect APIs. You're on 2.0.14, and the v2 branch you checked is out of date (it was promoted to dev on 2026-10-10). Since your plugin already checks whether ctx.session.compact exists, it should start compacting once you upgrade, for example:

    await ctx.session.compact({ sessionID })

    This adds a compaction to the session's inbox, and you can pass delivery: "queue" if needed.

    There is no built-in idle compaction yet. Compaction runs only on context overflow (compaction.auto) or when you start it manually, and warming doesn't compact a session when warming ends. I've marked this as a feature request, and maintainers will consider an option like compaction.idle. In the meantime, a plugin like yours is the way to get this behaviour.

    Related issues:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions