Skip to content

refactor: unify transport dispatch + collapse normalize shims#13862

Closed
kshitijk4poor wants to merge 1 commit into
mainfrom
refactor/unify-transport-dispatch
Closed

refactor: unify transport dispatch + collapse normalize shims#13862
kshitijk4poor wants to merge 1 commit into
mainfrom
refactor/unify-transport-dispatch

Conversation

@kshitijk4poor

@kshitijk4poor kshitijk4poor commented Apr 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

PR 7 of the provider transport refactor (#13473). Final consolidation PR — combines the planned PR 7 (unify dispatch) and PR 8 (runtime simplification). Closes cycle 1 of the refactor.

Changes

1. Consolidate 4 transport helpers → 1 generic _get_transport(api_mode=None)

Replace _get_anthropic_transport(), _get_codex_transport(), _get_chat_completions_transport(), _get_bedrock_transport() with one method using a shared dict cache. 22 call sites updated.

2. Collapse 65-line main normalize block → 7 lines

One _get_transport().normalize_response() call + one shared _nr_to_assistant_message() shim. The shim extracts provider_data fields (codex_reasoning_items, reasoning_content, reasoning_details, call_id, response_item_id) into the SimpleNamespace shape downstream expects.

3. Wire ALL remaining response.choices[0] accesses through transports

Zero response.choices[0] remaining in non-streaming run_agent.py code. Every response access goes through transport.normalize_response(). Sites wired:

  • Main normalize (L10701)
  • Truncation handler (L9483)
  • flush_memories chat/bedrock tool extraction (L7304)
  • Iteration summary (L8378) + retry (L8419)
  • Bedrock finish_reason (L9451)
  • Chat completions finish_reason + truncation check (L9455)

4. Remove scaffolding from PRs 1-6

  • normalize_anthropic_response_v2 deleted from anthropic_adapter.py (39 lines) — transport now calls v1 directly
  • test_anthropic_normalize_v2.py deleted (238 lines) — tested a wrapper that no longer exists
  • 10 dead imports removed from run_agent.py: 8 codex adapter functions + OPENROUTER_BASE_URL + DEVELOPER_ROLE_MODELS
  • Dead comment referencing removed import updated

5. Transport lifecycle

  • Eagerly warm transport cache at __init__ (surfaces import errors early)
  • Invalidate transport cache at ALL 4 self.api_mode = mutation sites: switch_model(), fallback activation, fallback restore, AND transport recovery

Impact

run_agent.py:           11,988 → 11,944 (-44 lines)
anthropic_adapter.py:    1,601 → 1,562 (-39 lines)
test_normalize_v2.py:      238 → 0      (-238 lines)
test_multimodal:             3 → 4      (+1 line, import path fix)
anthropic transport:       129 → 150    (+21 lines, inlined v2 logic)

Net:  +145 / -444 = -299 lines

Test plan

  • 2,576 run_agent + agent tests pass (3 pre-existing flaky failures)
  • Zero response.choices[0] in non-streaming code
  • Transport cache invalidation at all 4 api_mode mutation sites

@alt-glitch alt-glitch added type/refactor Code restructuring, no behavior change P3 Low — cosmetic, nice to have comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint labels Apr 22, 2026
@kshitijk4poor
kshitijk4poor force-pushed the refactor/unify-transport-dispatch branch 5 times, most recently from b6958db to 08ff76b Compare April 22, 2026 08:48
Consolidate 4 per-transport lazy singleton helpers (_get_anthropic_transport,
_get_codex_transport, _get_chat_completions_transport, _get_bedrock_transport)
into one generic _get_transport(api_mode) with a shared dict cache.

Collapse the 65-line main normalize block (3 api_mode branches, each with
its own SimpleNamespace shim) into 7 lines: one _get_transport() call +
one _nr_to_assistant_message() shared shim. The shim extracts provider_data
fields (codex_reasoning_items, reasoning_details, call_id, response_item_id)
into the SimpleNamespace shape downstream code expects.

Wire chat_completions and bedrock_converse normalize through their transports
for the first time — these were previously falling into the raw
response.choices[0].message else branch.

Remove 8 dead codex adapter imports that have zero callers after PRs 1-6.

Transport lifecycle improvements:
- Eagerly warm transport cache at __init__ (surfaces import errors early)
- Invalidate transport cache on api_mode change (switch_model, fallback
  activation, fallback restore, transport recovery) — prevents stale
  transport after mid-session provider switch

run_agent.py: -32 net lines (11,988 -> 11,956).

PR 7 of the provider transport refactor.
@kshitijk4poor
kshitijk4poor force-pushed the refactor/unify-transport-dispatch branch from 08ff76b to 4459673 Compare April 22, 2026 09:00
kshitijk4poor added a commit that referenced this pull request Apr 22, 2026
The transport refactor (PRs #13862 ff.) added agent/transports/ as a
sub-package but the setuptools packages.find include list only had
"agent" (top-level files), not "agent.*" (sub-packages).

pip install / Nix builds therefore ship run_agent.py (which now imports
from agent.transports on every API call) but omit the transports
directory entirely, causing:

  ModuleNotFoundError: No module named 'agent.transports'

on every LLM call for packaged installs.

Adds "agent.*" to match the existing pattern used by tools, gateway,
tui_gateway, and plugins.
teknium1 added a commit that referenced this pull request Apr 23, 2026
…odex_responses

Follow-up for #13862 — the post-init api_mode upgrade at __init__ (direct OpenAI /
gpt-5-requires-responses path) runs AFTER the eager transport warm. Clear the cache
so the stale chat_completions entry is evicted.

Cosmetic: correctness was already fine since _get_transport() keys by current
api_mode, but this avoids leaving unused cache state behind.
ulasbilgen pushed a commit to ulasbilgen/hermes-adhd-agent that referenced this pull request May 1, 2026
The transport refactor (PRs NousResearch#13862 ff.) added agent/transports/ as a
sub-package but the setuptools packages.find include list only had
"agent" (top-level files), not "agent.*" (sub-packages).

pip install / Nix builds therefore ship run_agent.py (which now imports
from agent.transports on every API call) but omit the transports
directory entirely, causing:

  ModuleNotFoundError: No module named 'agent.transports'

on every LLM call for packaged installs.

Adds "agent.*" to match the existing pattern used by tools, gateway,
tui_gateway, and plugins.
ulasbilgen pushed a commit to ulasbilgen/hermes-adhd-agent that referenced this pull request May 1, 2026
…odex_responses

Follow-up for NousResearch#13862 — the post-init api_mode upgrade at __init__ (direct OpenAI /
gpt-5-requires-responses path) runs AFTER the eager transport warm. Clear the cache
so the stale chat_completions entry is evicted.

Cosmetic: correctness was already fine since _get_transport() keys by current
api_mode, but this avoids leaving unused cache state behind.
aj-nt pushed a commit to aj-nt/hermes-agent that referenced this pull request May 1, 2026
The transport refactor (PRs NousResearch#13862 ff.) added agent/transports/ as a
sub-package but the setuptools packages.find include list only had
"agent" (top-level files), not "agent.*" (sub-packages).

pip install / Nix builds therefore ship run_agent.py (which now imports
from agent.transports on every API call) but omit the transports
directory entirely, causing:

  ModuleNotFoundError: No module named 'agent.transports'

on every LLM call for packaged installs.

Adds "agent.*" to match the existing pattern used by tools, gateway,
tui_gateway, and plugins.
aj-nt pushed a commit to aj-nt/hermes-agent that referenced this pull request May 1, 2026
…odex_responses

Follow-up for NousResearch#13862 — the post-init api_mode upgrade at __init__ (direct OpenAI /
gpt-5-requires-responses path) runs AFTER the eager transport warm. Clear the cache
so the stale chat_completions entry is evicted.

Cosmetic: correctness was already fine since _get_transport() keys by current
api_mode, but this avoids leaving unused cache state behind.
donald131 pushed a commit to donald131/hermes-agent that referenced this pull request May 2, 2026
…odex_responses

Follow-up for NousResearch#13862 — the post-init api_mode upgrade at __init__ (direct OpenAI /
gpt-5-requires-responses path) runs AFTER the eager transport warm. Clear the cache
so the stale chat_completions entry is evicted.

Cosmetic: correctness was already fine since _get_transport() keys by current
api_mode, but this avoids leaving unused cache state behind.
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
The transport refactor (PRs NousResearch#13862 ff.) added agent/transports/ as a
sub-package but the setuptools packages.find include list only had
"agent" (top-level files), not "agent.*" (sub-packages).

pip install / Nix builds therefore ship run_agent.py (which now imports
from agent.transports on every API call) but omit the transports
directory entirely, causing:

  ModuleNotFoundError: No module named 'agent.transports'

on every LLM call for packaged installs.

Adds "agent.*" to match the existing pattern used by tools, gateway,
tui_gateway, and plugins.
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
…odex_responses

Follow-up for NousResearch#13862 — the post-init api_mode upgrade at __init__ (direct OpenAI /
gpt-5-requires-responses path) runs AFTER the eager transport warm. Clear the cache
so the stale chat_completions entry is evicted.

Cosmetic: correctness was already fine since _get_transport() keys by current
api_mode, but this avoids leaving unused cache state behind.
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
The transport refactor (PRs NousResearch#13862 ff.) added agent/transports/ as a
sub-package but the setuptools packages.find include list only had
"agent" (top-level files), not "agent.*" (sub-packages).

pip install / Nix builds therefore ship run_agent.py (which now imports
from agent.transports on every API call) but omit the transports
directory entirely, causing:

  ModuleNotFoundError: No module named 'agent.transports'

on every LLM call for packaged installs.

Adds "agent.*" to match the existing pattern used by tools, gateway,
tui_gateway, and plugins.
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…odex_responses

Follow-up for NousResearch#13862 — the post-init api_mode upgrade at __init__ (direct OpenAI /
gpt-5-requires-responses path) runs AFTER the eager transport warm. Clear the cache
so the stale chat_completions entry is evicted.

Cosmetic: correctness was already fine since _get_transport() keys by current
api_mode, but this avoids leaving unused cache state behind.
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
The transport refactor (PRs NousResearch#13862 ff.) added agent/transports/ as a
sub-package but the setuptools packages.find include list only had
"agent" (top-level files), not "agent.*" (sub-packages).

pip install / Nix builds therefore ship run_agent.py (which now imports
from agent.transports on every API call) but omit the transports
directory entirely, causing:

  ModuleNotFoundError: No module named 'agent.transports'

on every LLM call for packaged installs.

Adds "agent.*" to match the existing pattern used by tools, gateway,
tui_gateway, and plugins.
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
…odex_responses

Follow-up for NousResearch#13862 — the post-init api_mode upgrade at __init__ (direct OpenAI /
gpt-5-requires-responses path) runs AFTER the eager transport warm. Clear the cache
so the stale chat_completions entry is evicted.

Cosmetic: correctness was already fine since _get_transport() keys by current
api_mode, but this avoids leaving unused cache state behind.
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
The transport refactor (PRs NousResearch#13862 ff.) added agent/transports/ as a
sub-package but the setuptools packages.find include list only had
"agent" (top-level files), not "agent.*" (sub-packages).

pip install / Nix builds therefore ship run_agent.py (which now imports
from agent.transports on every API call) but omit the transports
directory entirely, causing:

  ModuleNotFoundError: No module named 'agent.transports'

on every LLM call for packaged installs.

Adds "agent.*" to match the existing pattern used by tools, gateway,
tui_gateway, and plugins.
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…odex_responses

Follow-up for NousResearch#13862 — the post-init api_mode upgrade at __init__ (direct OpenAI /
gpt-5-requires-responses path) runs AFTER the eager transport warm. Clear the cache
so the stale chat_completions entry is evicted.

Cosmetic: correctness was already fine since _get_transport() keys by current
api_mode, but this avoids leaving unused cache state behind.
liuchanchen pushed a commit to liuchanchen/hermes-agent that referenced this pull request Jul 3, 2026
The transport refactor (PRs NousResearch#13862 ff.) added agent/transports/ as a
sub-package but the setuptools packages.find include list only had
"agent" (top-level files), not "agent.*" (sub-packages).

pip install / Nix builds therefore ship run_agent.py (which now imports
from agent.transports on every API call) but omit the transports
directory entirely, causing:

  ModuleNotFoundError: No module named 'agent.transports'

on every LLM call for packaged installs.

Adds "agent.*" to match the existing pattern used by tools, gateway,
tui_gateway, and plugins.
liuchanchen pushed a commit to liuchanchen/hermes-agent that referenced this pull request Jul 3, 2026
…odex_responses

Follow-up for NousResearch#13862 — the post-init api_mode upgrade at __init__ (direct OpenAI /
gpt-5-requires-responses path) runs AFTER the eager transport warm. Clear the cache
so the stale chat_completions entry is evicted.

Cosmetic: correctness was already fine since _get_transport() keys by current
api_mode, but this avoids leaving unused cache state behind.
kulikman pushed a commit to kulikman/hermes-agent that referenced this pull request Jul 16, 2026
The transport refactor (PRs NousResearch#13862 ff.) added agent/transports/ as a
sub-package but the setuptools packages.find include list only had
"agent" (top-level files), not "agent.*" (sub-packages).

pip install / Nix builds therefore ship run_agent.py (which now imports
from agent.transports on every API call) but omit the transports
directory entirely, causing:

  ModuleNotFoundError: No module named 'agent.transports'

on every LLM call for packaged installs.

Adds "agent.*" to match the existing pattern used by tools, gateway,
tui_gateway, and plugins.
kulikman pushed a commit to kulikman/hermes-agent that referenced this pull request Jul 16, 2026
…odex_responses

Follow-up for NousResearch#13862 — the post-init api_mode upgrade at __init__ (direct OpenAI /
gpt-5-requires-responses path) runs AFTER the eager transport warm. Clear the cache
so the stale chat_completions entry is evicted.

Cosmetic: correctness was already fine since _get_transport() keys by current
api_mode, but this avoids leaving unused cache state behind.
smasoftware pushed a commit to smasoftware/hermes-agent that referenced this pull request Jul 18, 2026
The transport refactor (PRs NousResearch#13862 ff.) added agent/transports/ as a
sub-package but the setuptools packages.find include list only had
"agent" (top-level files), not "agent.*" (sub-packages).

pip install / Nix builds therefore ship run_agent.py (which now imports
from agent.transports on every API call) but omit the transports
directory entirely, causing:

  ModuleNotFoundError: No module named 'agent.transports'

on every LLM call for packaged installs.

Adds "agent.*" to match the existing pattern used by tools, gateway,
tui_gateway, and plugins.
waym0reom3ga added a commit to waym0reom3ga/autolycus-agent that referenced this pull request Jul 21, 2026
The transport refactor (PRs NousResearch#13862 ff.) added agent/transports/ as a
sub-package but the setuptools packages.find include list only had
"agent" (top-level files), not "agent.*" (sub-packages).

pip install / Nix builds therefore ship run_agent.py (which now imports
from agent.transports on every API call) but omit the transports
directory entirely, causing:

  ModuleNotFoundError: No module named 'agent.transports'

on every LLM call for packaged installs.

Adds "agent.*" to match the existing pattern used by tools, gateway,
tui_gateway, and plugins.
waym0reom3ga added a commit to waym0reom3ga/autolycus-agent that referenced this pull request Jul 21, 2026
…odex_responses

Follow-up for NousResearch#13862 — the post-init api_mode upgrade at __init__ (direct OpenAI /
gpt-5-requires-responses path) runs AFTER the eager transport warm. Clear the cache
so the stale chat_completions entry is evicted.

Cosmetic: correctness was already fine since _get_transport() keys by current
api_mode, but this avoids leaving unused cache state behind.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P3 Low — cosmetic, nice to have type/refactor Code restructuring, no behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants