Commit Graph

3 Commits

Author SHA1 Message Date
Teknium e029e300ca fix(compression): harden native compaction rejection matcher + config coercion (#82777)
Two reliability gaps from #82777:

1. Rejection matcher required only a field-name mention, so a transient
   5xx/timeout whose body echoed the request (which contains
   context_management) permanently downgraded native compaction for the
   session. Now requires rejection language (unknown/unsupported/invalid/...)
   alongside the field name, and when a parsed HTTP status is available,
   400 specifically — non-400 statuses never match. Message-only transports
   (no status attribute) keep working unchanged.

2. compression.codex_responses_native was coerced with bool(), so the
   strings "false"/"off" enabled the feature. Now uses the shared
   utils.is_truthy_value helper.

Conversation-loop call site passes api_error.status_code through.
Sabotage-verified: reverting the matcher to field-name-only fails the new
echo and non-400 tests.
2026-08-13 03:04:31 -07:00
Teknium e4b3b91b62 fix(compression): prune pre-checkpoint history on native compaction replay
Live verification (gpt-5.6 @ api.openai.com) proved the Responses server
renders NOTHING placed before a replayed compaction checkpoint: a fact
stated in a pre-checkpoint input item is invisible to the model, while the
same item after the checkpoint recalls perfectly. Hermes was replaying the
full pre-checkpoint transcript anyway — dead upload weight, and worse, every
plaintext user ask from before the boundary silently vanished from the
model's view, surviving only inside the opaque server summary. That is the
goal-drift failure mode reported against native compaction sessions.

Codex CLI never hits this because it rebuilds history client-side after
compaction, retaining user messages verbatim under a token budget. This
change is the wire-level equivalent: when a replayed checkpoint is present,
_chat_messages_to_responses_input restructures the input as

  [newest checkpoint run] + [retained pre-checkpoint user messages,
  newest-first within a 64K-token budget] + [post-checkpoint tail]

Histories without a checkpoint are returned unchanged, so non-native
sessions see a byte-identical wire.
2026-08-13 01:51:24 -07:00
Teknium 5e1b50115f feat(compression): native OpenAI Responses server-side compaction for gpt-5.6
Opt-in via compression.codex_responses_native (default: false). When enabled,
gpt-5.6-family models on the direct OpenAI API (api.openai.com) or a ChatGPT
Codex subscription send context_management=[{type: compaction,
compact_threshold: N}] on Responses requests. OpenAI compacts server-side and
returns an encrypted compaction output item; Hermes captures it into the
existing codex_reasoning_items sidecar and replays it on later turns in place
of the pruned history — inheriting persistence, session replay, the
cross-issuer guard, and the encrypted-replay kill switch with zero new state.

Scope is deliberately hard-gated (agent/native_compaction.py, re-checked per
request): gpt-5.6 family only — gpt-5.1/5.2 fail server-side on the field
(HTTP 500 / stream stall, no structured rejection; live-verified) — and
direct OpenAI/Codex routes only; xAI, GitHub/Copilot, OpenRouter, relays,
and local servers never see the field.

Hermes' local compression stays armed as the fallback owner: the native
threshold is clamped ~8K tokens below the local trigger so the server
compacts first, and a structured provider rejection of context_management
disables native compaction for the session and retries without it
(one-shot guard in TurnRetryState).

Live-verified E2E on api.openai.com/gpt-5.6: server compaction fired at a
4K threshold, checkpoints captured and replayed, recall preserved across
3 turns; gpt-5.1 with the flag enabled stays clean (field never sent).

Direction credit: PR #76950 by @laryhorb explored native Responses
compaction; this is a minimal reimplementation on current main.
2026-08-08 11:24:45 -07:00