hermes-agent/agent
brooklyn! 41fdcae688
fix(streaming): make the single-writer fence best-effort so a missing guard can't crash a turn (#66448)
A cron job ("Daily Buzz Report") died with 'AIAgent' object has no
attribute '_claim_stream_writer'. The #65991 single-writer fence lives on
AIAgent (run_agent.py), but the streaming paths that use it live in other
modules — chat_completion_helpers (chat / anthropic / bedrock) and
codex_runtime (codex responses) — and called it directly as
agent._claim_stream_writer() / agent._stream_writer_is_current(). That makes
those modules hard-depend on the method being present on whatever object is
passed as agent.

The fence is an *additive* safety net that may only ever drop a provably
superseded stream, never the sole legitimate writer. But the direct calls
turned any agent that doesn't expose it — a version-skewed checkout (the
streaming helper module newer than run_agent), a hot-reloaded gateway mid
git-pull, a duck-typed agent, or a test double — into a fatal AttributeError
that aborts the whole turn (and, on cron, fails the job).

Route every cross-module claim/check through agent/stream_single_writer.py.
claim_stream_writer(agent) returns 0 when the fence is unavailable (or
raises), and stream_writer_is_current(agent, token) treats a 0 token or an
absent guard as "current" — so a guard-less agent degrades to "no fence"
instead of crashing, while a real AIAgent keeps the full single-writer
protection. Internal self.* uses inside run_agent are unchanged (self is
always a full AIAgent there).
2026-07-17 18:31:09 +00:00
..
lsp
…
pet
…
secret_sources
…
transports fix(codex): forward drained notifications to on_event during approval roundtrips 2026-07-17 06:49:47 -07:00
__init__.py
…
account_usage.py feat(codex): redeem banked usage-limit resets via /usage reset (#64280) 2026-07-14 03:23:19 -07:00
agent_init.py fix(streaming): fence superseded streams out of the delta sink (single-writer) 2026-07-17 06:49:23 -07:00
agent_runtime_helpers.py fix(auth): make xAI OAuth pools multi-account resilient 2026-07-17 11:37:25 +05:30
anthropic_adapter.py fix(auxiliary): apply review fixes to #36043 — guard named-custom routing, drop dead key assignment, tighten Palantir host match 2026-07-16 07:28:07 -07:00
async_utils.py
…
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(auxiliary): scope runtime state to each turn 2026-07-17 09:08:30 -07:00
azure_identity_adapter.py
…
background_review.py fix(background_review): gate reasoning_config inheritance on not-routed + dedupe recorder stubs 2026-07-14 17:19:46 +05:30
bedrock_adapter.py fix(bedrock): streaming fallback to Converse API + image base64 decode + bearer token routing 2026-07-15 09:59:38 -07:00
billing_view.py
…
bounded_response.py
…
browser_provider.py
…
browser_registry.py
…
chat_completion_helpers.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
codex_responses_adapter.py fix(agent): treat Codex incomplete content filter as refusal 2026-07-15 09:47:37 -07:00
codex_runtime.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
coding_context.py
…
context_breakdown.py
…
context_compressor.py fix(compression): reset failure cooldown on runtime switch 2026-07-17 09:08:30 -07:00
context_engine.py
…
context_references.py
…
conversation_compression.py fix(context): persist fallback compaction breaker 2026-07-14 02:19:40 +05:30
conversation_loop.py fix(agent): execute valid tool calls in mixed batches with invalid names (#66317) 2026-07-17 06:48:42 -07:00
copilot_acp_client.py fix(file-safety): distinguish safe-root write denial from credential blocks 2026-07-14 17:09:40 +05:30
credential_persistence.py
…
credential_pool.py fix(credential-pool): throttle "no available entries" log to stop Windows log-lock storm (contributes to #62698) (#66338) 2026-07-17 13:08:46 -04:00
credential_sources.py
…
credits_tracker.py
…
curator.py
…
curator_backup.py
…
display.py fix: harden remaining display-layer surfaces against non-string tool args 2026-07-15 00:10:22 -07:00
error_classifier.py fix(errors): classify Z.AI GLM token-limit message as context overflow 2026-07-17 04:57:27 -07:00
errors.py fix(streaming): retry zero-chunk streams 2026-07-15 10:58:36 +05:30
file_safety.py Inspired by Claude Code: protect session transcripts 2026-07-17 04:54:34 -07:00
gemini_native_adapter.py feat(gemini): improve request context for support and compatibility 2026-07-13 22:26:19 -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
…
image_gen_provider.py
…
image_gen_registry.py
…
image_routing.py fix(auxiliary): scope runtime state to each turn 2026-07-17 09:08:30 -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
…
jiter_preload.py
…
kanban_stop.py follow-up: integrate agent nudge + dispatcher retry docs and tests 2026-07-14 16:47:33 +05:30
learn_prompt.py
…
learning_graph.py
…
learning_graph_render.py
…
learning_mutations.py
…
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(context): harden compression failure feedback 2026-07-16 14:34:03 +05:30
markdown_tables.py
…
memory_manager.py fix(memory): drain queued writes on shutdown 2026-07-17 04:55:58 -07:00
memory_provider.py
…
message_content.py
…
message_sanitization.py
…
moa_loop.py feat(portal): ambient conversation context entangles aux/MoA/delegate calls 2026-07-16 01:13:43 -07:00
moa_trace.py
…
model_metadata.py feat(kimi): discover K3 on coding endpoint 2026-07-16 13:33:02 -07:00
models_dev.py
…
moonshot_schema.py
…
nous_rate_guard.py
…
onboarding.py
…
oneshot.py
…
plugin_llm.py
…
portal_tags.py feat(portal): ambient conversation context entangles aux/MoA/delegate calls 2026-07-16 01:13:43 -07:00
process_bootstrap.py
…
prompt_builder.py fix: widen UTF-8 BOM tolerance to all sibling frontmatter parsers 2026-07-17 04:52:02 -07:00
prompt_caching.py
…
rate_limit_tracker.py
…
reactions.py
…
reasoning_timeouts.py
…
redact.py
…
replay_cleanup.py
…
retry_utils.py
…
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
…
shell_hooks.py
…
skill_bundles.py
…
skill_commands.py fix(skills): guard skill slash commands against core-command and slug collisions 2026-07-14 16:41:21 +05:30
skill_preprocessing.py
…
skill_utils.py fix(skills): strip UTF-8 BOM before parsing SKILL.md frontmatter 2026-07-17 04:52:02 -07:00
ssl_guard.py
…
ssl_verify.py
…
stream_diag.py
…
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
…
system_prompt.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
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
…
thread_scoped_output.py
…
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): canonicalise paths in parallel-batch planner to prevent same-file concurrent mutation 2026-07-16 04:26:32 -07:00
tool_guardrails.py
…
tool_result_classification.py
…
trace_upload.py
…
trajectory.py
…
transcription_provider.py
…
transcription_registry.py fix(deepinfra): harden multimodal provider routing 2026-07-14 02:59:39 +05:30
tts_provider.py
…
tts_registry.py feat(providers): Support DeepInfra as an LLM provider 2026-07-14 02:59:39 +05:30
turn_context.py fix(auxiliary): sync runtime after fallback restoration 2026-07-17 09:08:30 -07:00
turn_finalizer.py fix(session): restore clean API-local turn content 2026-07-14 03:32:46 +05:30
turn_retry_state.py
…
usage_pricing.py fix(usage): read DeepSeek's native prompt_cache_hit_tokens cache field (#65678) 2026-07-16 07:29:53 -07:00
verification_evidence.py
…
verification_stop.py fix(approval): allow verifier temp cleanup 2026-07-12 04:32:52 -07:00
verify_hooks.py
…
vertex_adapter.py
…
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
…
web_search_registry.py
…