Repository navigation
Harness API: per-session context ceiling (set_context_cap) so concurrent sessions can hold different compaction budgets #1971
Description
Context. We embed jcode headless through the harness API (@1jehuang/jcode-sdk), one connection and one session per conversation, with several conversations running at the same time in one daemon. We set [compaction] max_context_tokens = 200000 (the compaction half of #723) so a 1M-window model folds at about 160k, and short messages stay fast and cheap.
The cap is one value for the whole daemon, but the right value differs per conversation. A short question-and-answer thread wants the small cap. A long multi-step task in another conversation (a large refactor, research across many files, a big data job) is slowed down by it: it compacts again and again, loses detail it then has to re-read, and takes longer overall. We would like each session to have its own ceiling, and to change it as the work changes.
Citations are against master @ b09a8a5.
Today
- The cap is read from the global config.
CompactionManager::refresh_context_capcopiescrate::config::config().compaction.max_context_tokens(crates/jcode-base/src/compaction.rs:255-259), and it runs before every request throughensure_context_fits(:959) and on everyset_budget(:251). - Each session already has its own
CompactionManager(theRegistryclone gives a fresh one,crates/jcode-app-core/src/tool/mod.rs:339-341). So the compaction state is per session, but the ceiling is not. - Rewriting
config.tomlchanges the cap for every live session in the daemon at its next request. Two concurrent sessions cannot hold different values. - The harness API already has per-session
set_reasoning_effort(crates/jcode-harness-api/src/requests.rs:269),set_model, andcompact(:275). There is no per-session control over the context ceiling. (The native wire hasset_compaction_mode, which the harness API does not expose either.)
Ask 1: a per-session context ceiling
A harness API request such as:
{ "req": "set_context_cap", "session_id": "...", "max_context_tokens": 600000 }Semantics we would expect:
- It applies to that session only.
0ornullclears it, and the session falls back to the global[compaction] max_context_tokens. - Effective budget =
min(model window, session override if set, else the global cap). Never above the model's window. - It is persisted with the session, so
resume_sessionafter a daemon restart keeps it. - Lowering it below current usage behaves like the existing thresholds (background compaction at 80%, hard compact at 95%). The embedder can call
compactto fold right away. - The reply carries the effective budget, for example
{ "ev": "context_cap_changed", "session_id": "...", "max_context_tokens": 600000, "effective_budget": 600000 }.
Ask 2 (nice to have): report the effective budget
Expose the session's effective budget where an embedder can read it, for example on model_info or token_usage. Then the embedder can show "x of y tokens" and decide when to raise or lower the ceiling. This is related to the context-meter point still open in #723.
Why
Our users run one agent for both quick questions and long tasks. With a single ceiling we have to pick a trade-off for everyone. A small one makes big tasks slow and lossy. A large one makes every short message re-send a huge transcript. Per session, the agent (or the embedder) can raise the ceiling for a big task and lower it afterwards, without affecting the other conversations running in the same daemon.
Happy to test a pre-release build against our integration.
Activity
ianalitis commentedon Oct 26, 2026
Thanks, the citations match master:
CompactionManager::refresh_context_capcopies the global[compaction] max_context_tokensbefore every request, each session already has its ownCompactionManager, and the harness API hasset_reasoning_effort/set_model/compactbut no per-session ceiling.The contract you describe is implementable as specified (session override,
0/nullclears,min(model window, override or global), persisted acrossresume_session, reply carries the effective budget). Two things are maintainer decisions rather than implementation detail, so it is bucketed needs-decision:resume_sessionrestores, so it needs agreement on whether it is stored in session metadata or re-applied by the embedder after attach (the same question feat: per-session environment for tool-spawned processes (finish #1967) #1969 is asking about per-session env).Ask 2 falls out of the same change if the effective budget is computed once and exposed on
token_usage.— Jcode agent (automated triage), on behalf of @1jehuang
1jehuang commentedon Oct 30, 2026
Implemented and pushed to master in 2054a04 and cf05b03 (persisted per-session context caps, daemon controls, and effective-budget reporting), 6b8e8ef (harness API and SDK support), 3403aee (public-transport regression tests), and a30ea25 (documentation). Closing as completed.