Summary
Align the plugin's prompt caching behavior more closely with the Codex CLI by making prompt_cache_key explicitly fork-aware and resilient to non-structural overrides (temperature, tools, etc.), matching the semantics exercised in openai/codex tests.
Background
The plugin already:
- Accepts both
prompt_cache_key and promptCacheKey from the host.
- Derives a stable key from metadata (e.g.
conversation_id, sessionId) when none is provided.
- Generates a fallback
cache_<uuid> when there is no usable identifier.
From the Codex CLI side:
codex-rs/core/src/client_common.rs and core/src/client.rs treat prompt_cache_key as a first-class field.
core/tests/suite/prompt_caching.rs asserts that prompt_cache_key remains constant across overrides.
core/tests/suite/compact_resume_fork.rs uses prompt_cache_key to distinguish resume/fork flows.
Right now the plugin behavior is “correct but minimal” (we ensure a key exists), but we don’t fully mirror Codex’s expectations around overrides and forks.
Proposed Behavior
-
Explicit fork-aware cache key derivation
- When the host provides a conversation or session identifier, continue to derive
prompt_cache_key from that, but introduce a clear fork story:
- Treat metadata like
forkId, branchId, or parentConversationId (once available) as hints that a new cache key should be generated.
- Use a deterministic format such as:
cache_<base> for the original conversation
cache_<base>-fork-<n> for forks, where <base> is derived from the original session ID.
- If opencode’s SessionManager begins exposing explicit fork metadata, prefer that over heuristics.
-
Stable cache keys across non-structural overrides
- Preserve the same
prompt_cache_key when only “soft” properties change, such as:
temperature, max_output_tokens, reasoningEffort, reasoningSummary, textVerbosity.
- Only rotate or derive a new
prompt_cache_key when the conversation identity changes (e.g. different session/conversation ID) or when a fork is explicitly requested.
-
Safer fallback behavior
- Keep the current fallback
cache_<uuid> logic but:
- Log a more explicit warning when we must generate a fallback key while we do see a conversation-like identifier (possible host bug).
- Optionally encode a short hash of the
input prefix into the fallback key (e.g. cache_<hash>-<uuid>) to reduce accidental key reuse.
-
Regression tests
- Extend
test/request-transformer.test.ts with scenarios inspired by openai/codex tests:
- “prompt_cache_key should remain constant across overrides”
- “prompt_cache_key should be distinct when session forks” (simulated via metadata)
- “fallback-generated prompt_cache_key does not change across multiple transforms for the same body”
Rationale
- Brings the plugin’s caching semantics much closer to Codex CLI behavior.
- Reduces surprise for users who move between Codex CLI and opencode, especially around resume/fork workflows.
- Provides a clearer story for future SessionManager integrations in opencode, which can rely on stable cache behavior.
Acceptance Criteria
- New tests cover:
- Stable cache key across non-structural changes.
- Distinct keys for forks.
- Deterministic behavior for fallback-derived keys.
- Existing mutation tests continue to pass (
pnpm test:mutation), and mutation coverage for the ensurePromptCacheKey/reasoning paths improves or stays flat.
Summary
Align the plugin's prompt caching behavior more closely with the Codex CLI by making
prompt_cache_keyexplicitly fork-aware and resilient to non-structural overrides (temperature, tools, etc.), matching the semantics exercised inopenai/codextests.Background
The plugin already:
prompt_cache_keyandpromptCacheKeyfrom the host.conversation_id,sessionId) when none is provided.cache_<uuid>when there is no usable identifier.From the Codex CLI side:
codex-rs/core/src/client_common.rsandcore/src/client.rstreatprompt_cache_keyas a first-class field.core/tests/suite/prompt_caching.rsasserts thatprompt_cache_keyremains constant across overrides.core/tests/suite/compact_resume_fork.rsusesprompt_cache_keyto distinguish resume/fork flows.Right now the plugin behavior is “correct but minimal” (we ensure a key exists), but we don’t fully mirror Codex’s expectations around overrides and forks.
Proposed Behavior
Explicit fork-aware cache key derivation
prompt_cache_keyfrom that, but introduce a clear fork story:forkId,branchId, orparentConversationId(once available) as hints that a new cache key should be generated.cache_<base>for the original conversationcache_<base>-fork-<n>for forks, where<base>is derived from the original session ID.Stable cache keys across non-structural overrides
prompt_cache_keywhen only “soft” properties change, such as:temperature,max_output_tokens,reasoningEffort,reasoningSummary,textVerbosity.prompt_cache_keywhen the conversation identity changes (e.g. different session/conversation ID) or when a fork is explicitly requested.Safer fallback behavior
cache_<uuid>logic but:inputprefix into the fallback key (e.g.cache_<hash>-<uuid>) to reduce accidental key reuse.Regression tests
test/request-transformer.test.tswith scenarios inspired byopenai/codextests:Rationale
Acceptance Criteria
pnpm test:mutation), and mutation coverage for theensurePromptCacheKey/reasoning paths improves or stays flat.