hermes-agent/agent
Drexuxux fb1b89b09e fix(prompt-caching): inject cache breakpoints after message normalization
The conversation loop normalizes message text right before the API call so
the request prefix is byte-identical across turns -- the stated reason is
KV cache reuse on local inference servers and better cache hit rates on
cloud providers. Cache breakpoints were injected *before* that pass, which
defeats it.

`_apply_cache_marker` rewrites a plain-string `content` into a
`[{"type": "text", ...}]` block. The normalization pass is guarded on
`isinstance(content, str)`, so every message that just got marked is
silently skipped by it and keeps its raw leading/trailing whitespace. A
message is only marked while it sits in the last-3 window, so:

    turn N      in the window  -> marked, content "file1\nfile2\n"
    turn N+1    rolled out     -> plain,  content "file1\nfile2"

The same logical message is sent with different bytes on consecutive
turns. The prefix stops matching at that position -- which is inside the
span the breakpoints were placed to protect -- so the reusable prefix
collapses back toward the system breakpoint on every turn. Tool results
carry a trailing newline almost by default (any shell command output), so
this is the common case, not an edge case.

Move the injection below every message mutation. Besides fixing the
whitespace divergence this stops breakpoints from being spent on messages
that the orphan sweep or the thinking-only drop is about to remove or
merge away -- a marker on a dropped message is a wasted breakpoint out of
the four available.

Nothing between the old and new call sites reads `cache_control`, and the
mutators now see the plain-string shapes they were written against.
2026-07-24 16:01:38 -07:00
..
lsp fix(windows): sweep remaining unguarded text-mode subprocess sites codebase-wide 2026-07-24 11:45:57 -07:00
pet fix: remove dead f-string prefixes via ruff F541 (216 sites) (#52336) 2026-07-05 13:42:46 -07:00
proxy_sources fix(windows): sweep remaining unguarded text-mode subprocess sites codebase-wide 2026-07-24 11:45:57 -07:00
secret_sources fix(windows): sweep remaining unguarded text-mode subprocess sites codebase-wide 2026-07-24 11:45:57 -07:00
transports fix(codex): scope 24h retention to Bedrock Mantle 2026-07-24 15:54:08 -07:00
__init__.py fix(agent): preload jiter native parser 2026-05-28 00:20:11 -07:00
account_usage.py fix(auth): detect upstream Codex quota resets and lift stale pool cooldowns (#69494) 2026-07-22 10:58:22 -07:00
agent_init.py fix(agent): cache static system prompt prefixes 2026-07-24 16:01:38 -07:00
agent_runtime_helpers.py refactor: extract sync_credential_pool_entry_id helper 2026-07-24 22:58:47 +05:30
anthropic_adapter.py fix(anthropic): keep replay content schema-valid when every block is blank 2026-07-24 15:54:38 -07:00
async_utils.py refactor(gateway): dedupe detached-task consumer + reconnect backoff policy 2026-07-18 20:01:55 +05:30
aux_accounting.py feat(analytics): record auxiliary model usage per task in session accounting (#65537) 2026-07-16 04:23:12 -07:00
auxiliary_client.py fix(codex): scope 24h retention to Bedrock Mantle 2026-07-24 15:54:08 -07:00
azure_identity_adapter.py feat(azure-foundry): add Microsoft Entra ID auth 2026-05-18 10:14:38 -07:00
background_review.py fix(background_review): gate reasoning_config inheritance on not-routed + dedupe recorder stubs 2026-07-14 17:19:46 +05:30
battery.py feat(status-bar): add /battery toggle for a color-coded battery read-out 2026-07-21 13:54:11 -05:00
bedrock_adapter.py feat(bedrock): add Converse API prompt caching (cachePoint) 2026-07-23 11:45:07 -07:00
billing_links.py feat(billing): shared cross-surface out-of-credits signal 2026-07-22 18:08:59 -05:00
billing_usage.py feat(tui+cli): change your Nous plan from the terminal (/subscription, /topup, terminal-billing UX) (#51639) 2026-07-18 14:30:24 +05:30
billing_view.py fix(billing): rename user-facing "terminal billing" copy to Remote Spending (#68355) 2026-07-21 12:20:25 +05:30
bounded_response.py fix(agents): bound streaming error-response body reads 2026-07-05 14:00:20 -07:00
browser_provider.py fix(browser): self-review pass — dead-import, log levels, future-proofing 2026-05-17 04:04:15 -07:00
browser_registry.py style: restore PEP8 blank-line separation after dead-code removal 2026-05-29 04:22:27 -07:00
chat_completion_helpers.py fix(codex): scope 24h retention to Bedrock Mantle 2026-07-24 15:54:08 -07:00
codex_responses_adapter.py fix(codex): send prompt_cache_retention 24h for the GPT-5.5 family 2026-07-24 15:54:08 -07:00
codex_runtime.py feat(codex): honor redirect and hard stop in the app-server runtime 2026-07-22 12:02:40 -05:00
coding_context.py fix(agent): cache static system prompt prefixes 2026-07-24 16:01:38 -07:00
context_breakdown.py feat(desktop): add context usage breakdown popover 2026-06-29 09:18:10 -04:00
context_compressor.py fix(compression): add recovery path to anti-thrash auto-compaction block 2026-07-24 15:57:09 -07:00
context_engine.py fix(context-engine): snapshot select_context read-only inputs; scope on_turn_complete coverage doc 2026-07-23 19:44:35 -07:00
context_references.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
conversation_compression.py fix: pre-lease drift guard must not fire on in-place compaction or mutated snapshots 2026-07-24 16:00:34 -07:00
conversation_loop.py fix(prompt-caching): inject cache breakpoints after message normalization 2026-07-24 16:01:38 -07:00
copilot_acp_client.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
credential_persistence.py feat(auth): make xAI Grok OAuth device-code-only, drop loopback login 2026-07-02 13:17:41 -07:00
credential_pool.py fix: break unbounded 401 retry loop in credential pool OAuth path 2026-07-24 15:50:36 -07:00
credential_sources.py feat(auth): make xAI Grok OAuth device-code-only, drop loopback login 2026-07-02 13:17:41 -07:00
credits_tracker.py feat(credits): report $used of $cap instead of % in the usage notice 2026-07-23 01:28:58 -05:00
curator.py docs: document 57-char system prompt truncation in authoring guide and curator 2026-07-23 21:06:56 -07:00
curator_backup.py fix(cron): widen UTF-8 BOM tolerance to backup/curator jobs.json readers 2026-07-18 02:31:20 -07:00
delegation_context.py fix(kanban): harden delegated-child mutation boundary 2026-07-23 07:33:36 -07:00
display.py feat(gateway): live per-tool status line on Slack 2026-07-18 12:28:59 -07:00
error_classifier.py fix(gateway): distinguish gateway auth 401 from provider API key errors 2026-07-23 11:54:47 -07:00
errors.py fix(moa): surface stale presets without retries 2026-07-17 13:49:12 -07:00
file_safety.py fix(secrets): harden encrypted Bitwarden cache 2026-07-22 04:40:07 -07:00
gemini_native_adapter.py fix(gemini): emit thoughtSignature sentinel for cross-provider tool_calls in native adapter 2026-07-23 17:26:24 -07:00
gemini_schema.py fix(gemini): prune required entries missing from properties in tool schemas 2026-07-17 04:54:06 -07:00
i18n.py feat(i18n): add Arabic (ar) catalog for agent/CLI messages 2026-07-24 12:10:03 -05:00
image_gen_provider.py feat(image-gen): add image-to-image / editing to image_generate (#48705) 2026-06-18 22:13:07 -07:00
image_gen_registry.py fix(plugins): filter resolution by is_available() in web + image_gen registries 2026-05-13 22:31:28 -07:00
image_routing.py feat(image_routing): accept vision alias for custom provider models 2026-07-23 08:32:09 -07:00
insights.py fix(insights): include auxiliary usage in overview token totals (#65603) 2026-07-16 05:39:33 -07:00
iteration_budget.py refactor(run_agent): extract OpenAI proxy, safe stdio, IterationBudget 2026-05-16 17:59:32 -07:00
jiter_preload.py fix(agent): preload jiter native parser 2026-05-28 00:20:11 -07:00
kanban_stop.py follow-up: integrate agent nudge + dispatcher retry docs and tests 2026-07-14 16:47:33 +05:30
learn_prompt.py fix(learn): honor requirements mixed with sources in /learn requests (#55956) 2026-06-30 16:56:01 -07:00
learning_graph.py fix(learning_graph): guard non-dict metadata so /journey can't crash 2026-07-01 16:25:48 -05:00
learning_graph_render.py fix: cover remaining GNU-only %-d strftime site in learning graph render 2026-07-05 00:59:35 -07:00
learning_mutations.py refactor(journey): route memory mutations through MemoryStore atomic I/O 2026-06-30 15:16:21 -05:00
lmstudio_reasoning.py fix(lmstudio): clamp max/ultra reasoning effort to LM Studio's ceiling 2026-07-16 07:57:51 -07:00
manual_compression_feedback.py fix(compress): classify unconfirmed lock-acquire failures and cover all manual-compress surfaces 2026-07-23 08:19:14 -07:00
markdown_tables.py fix(cli): vertical fallback for markdown tables wider than terminal (#23948) 2026-05-11 16:49:13 -07:00
memory_manager.py fix(memory): honor disabled toolsets for provider tools 2026-07-24 13:00:53 +05:30
memory_provider.py fix(backup): capture memory-provider state stored outside HERMES_HOME (#50325) 2026-06-21 12:03:46 -07:00
message_content.py fix(openviking): preserve structured sync attribution 2026-06-19 15:23:41 +08:00
message_sanitization.py fix(agent): close tool-call sequence on all interrupt aborts, not just finalize_turn 2026-06-25 12:24:34 -05:00
moa_loop.py fix(agent): cache static system prompt prefixes 2026-07-24 16:01:38 -07:00
moa_trace.py fix(moa): capture streamed aggregator output into full-turn traces (#56312) 2026-07-01 04:07:46 -07:00
model_metadata.py feat(models): add anthropic/claude-opus-5 to OpenRouter and Nous Portal catalogs 2026-07-24 13:00:15 -07:00
models_dev.py remove Vercel AI Gateway and Vercel Sandbox (#33067) 2026-05-27 00:43:32 -07:00
moonshot_schema.py fix(agent): inject empty required array on Moonshot object schemas 2026-07-20 11:05:52 -07:00
nous_rate_guard.py codebase: add encoding='utf-8' to all bare open() calls (PLW1514) 2026-05-08 14:27:40 -07:00
onboarding.py feat(surfaces): route busy-input corrections through active-turn redirect 2026-07-22 12:10:58 -05:00
oneshot.py feat(agent): one-shot LLM helper + llm.oneshot gateway RPC (#51261) 2026-06-23 08:01:50 +00:00
plugin_llm.py feat(plugins): run any LLM call from inside a plugin via ctx.llm (#23194) 2026-05-10 07:09:28 -07:00
portal_tags.py feat(portal): ambient conversation context entangles aux/MoA/delegate calls 2026-07-16 01:13:43 -07:00
process_bootstrap.py fix(agent): apply pool-level keepalive to the process_bootstrap sibling builder 2026-07-05 03:14:55 -07:00
prompt_builder.py fix(P1+P2): marker names skill_view(name='X') + DEDUP rule for repeated [SKILL_PRUNED] markers 2026-07-23 16:58:06 -07:00
prompt_caching.py fix(agent): cache static system prompt prefixes 2026-07-24 16:01:38 -07:00
rate_limit_tracker.py
reactions.py feat(agent): core affection reaction detector + reaction_callback 2026-07-10 05:41:59 -05:00
reasoning_timeouts.py feat(models): add anthropic/claude-opus-5 to OpenRouter and Nous Portal catalogs 2026-07-24 13:00:15 -07:00
redact.py fix(redaction): normalize URL credential key aliases 2026-07-20 02:25:57 -07:00
replay_cleanup.py refactor: shared helpers for api_content sidecar pop/drop/extract 2026-07-19 08:25:35 +05:30
retry_utils.py refactor(retry): single-source Z.AI overload short-attempts + drop change-detector assert 2026-07-07 11:57:01 +05:30
runtime_cwd.py fix(agent): scope install-tree guard to fallback-picked cwds, allow cli/tui in-tree dev 2026-07-16 04:32:23 -07:00
secret_scope.py fix(secrets): scope BWS-injected provider keys 2026-07-22 04:39:17 -07:00
shell_hooks.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
skill_bundles.py fix(gateway): apply platform-disabled skill gate to bundle invocations (#59156) 2026-07-05 14:48:11 -07:00
skill_commands.py feat: show system_prompt_preview when skill description exceeds prompt limit 2026-07-23 21:06:56 -07:00
skill_preprocessing.py fix: add explicit UTF-8 encoding to all subprocess text=True calls (#53428) 2026-07-24 11:45:57 -07:00
skill_utils.py refactor: extract SKILL_PROMPT_DESC_LIMIT constant and normalize description helpers 2026-07-23 21:06:56 -07:00
ssl_guard.py fix(ssl): detect and repair a missing certifi cacert.pem via existing venv-repair infra 2026-07-24 15:53:38 -07:00
ssl_verify.py fix(agent): honor custom CA certs on aux client + harden TLS resolution 2026-07-02 04:51:56 +05:30
stream_diag.py feat(agent): buffer retry/fallback status, surface only on terminal failure (#33816) 2026-05-28 04:53:27 -07:00
stream_single_writer.py fix(streaming): make the single-writer fence best-effort so a missing guard can't crash a turn (#66448) 2026-07-17 18:31:09 +00:00
subdirectory_hints.py fix(subdirectory_hints): catch RuntimeError from Path.expanduser() 2026-07-01 04:55:15 -07:00
subscription_view.py feat(cli): plan catalog on Free + plan= deep link + top-up/auto-refill copy split (#68689) 2026-07-22 08:11:09 +05:30
system_prompt.py fix(agent): cache static system prompt prefixes 2026-07-24 16:01:38 -07:00
think_scrubber.py fix(agent): re-arm think scrubber boundary after stream flush 2026-07-16 01:07:29 +05:30
thinking_timeout_guidance.py fix(agent): detect thinking-timeout for reasoning models and surface actionable guidance instead of misleading file-write advice 2026-06-25 19:00:48 -07:00
thread_scoped_output.py fix(bg-review): scope stdout/stderr silencing to the worker thread (#55966) 2026-06-30 17:28:33 -07:00
title_generator.py fix(title): prevent stale background title generation from reloading unloaded Ollama models 2026-07-16 23:07:13 -07:00
tool_dispatch_helpers.py fix(agent): canonicalise paths in parallel-batch planner to prevent same-file concurrent mutation 2026-07-16 04:26:32 -07:00
tool_executor.py fix(agent): mark tool failures in the activity log (#69131) 2026-07-24 15:56:09 -07:00
tool_guardrails.py fix(agent): tolerate lone UTF-16 surrogates in tool-guardrail hashing 2026-07-18 02:08:39 -07:00
tool_result_classification.py fix(agent): preserve none vs unknown tool effects (#61783) 2026-07-11 05:41:58 -07:00
trace_upload.py fix(windows): sweep remaining unguarded text-mode subprocess sites codebase-wide 2026-07-24 11:45:57 -07:00
trajectory.py
transcription_provider.py feat(stt): add register_transcription_provider() plugin hook 2026-05-25 01:41:19 -07:00
transcription_registry.py fix(deepinfra): harden multimodal provider routing 2026-07-14 02:59:39 +05:30
tts_provider.py feat(tts): add register_tts_provider() plugin hook (closes #30398) 2026-05-24 18:04:54 -07:00
tts_registry.py feat(providers): Support DeepInfra as an LLM provider 2026-07-14 02:59:39 +05:30
turn_context.py fix(compression): recover rotated session lineage 2026-07-24 16:00:34 -07:00
turn_finalizer.py feat(context-engine): forward real usage to on_turn_complete() 2026-07-23 19:44:35 -07:00
turn_retry_state.py feat(agent): add active-turn redirect core primitive 2026-07-22 12:02:40 -05:00
usage_pricing.py fix(pricing): strip apac./au. Bedrock region prefixes so cost isn't unknown 2026-07-20 05:38:45 -07:00
verification_evidence.py fix(gateway,tools,agent): close leaked SQLite connections in delivery, delegation, and verification ledgers 2026-07-24 15:55:08 -07:00
verification_stop.py fix(approval): allow verifier temp cleanup 2026-07-12 04:32:52 -07:00
verify_hooks.py feat(agent): add pre_verify hook and verify-on-stop coding guidance 2026-06-30 00:59:29 -05:00
vertex_adapter.py security(vertex): route credential/project/region resolution through the profile secret scope 2026-07-02 06:07:56 +05:30
video_gen_provider.py feat(providers): Support DeepInfra as an LLM provider 2026-07-14 02:59:39 +05:30
video_gen_registry.py fix(deepinfra): harden multimodal provider routing 2026-07-14 02:59:39 +05:30
web_search_provider.py fix(web): widen config-aware env resolution to exa/parallel/tavily/brave-free providers 2026-07-06 02:42:24 -07:00
web_search_registry.py fix(web): correct 'disabled plugin' diagnosis for web backends (#59573) 2026-07-06 04:38:17 -07:00