Skip to content

Fix gateway fields#38

Merged
ScriptSmith merged 6 commits into
mainfrom
fix-gateway-fields
May 30, 2026
Merged

Fix gateway fields#38
ScriptSmith merged 6 commits into
mainfrom
fix-gateway-fields

Conversation

@ScriptSmith

Copy link
Copy Markdown
Member

No description provided.

@greptile-apps

greptile-apps Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces server-side conversation reconstruction from previous_response_id so that Hadrian — not the upstream provider — is the system of record for chaining. It also adds strip_gateway_fields() to prevent orchestration-only fields (store, background, models, provider, plugins, sovereignty_requirements, skills) from leaking to upstream providers, and adds echo-field restoration so the persisted response and every streamed lifecycle event carry the caller's intent (Hadrian resp_… id, original store, original previous_response_id).

  • responses_chain.rs (new): walks the previous_response_id linked list, replays turns oldest→newest, hard-errors on corrupt records (addressing the silent-drop bug noted in the previous review).
  • response_persister.rs: new ResponseEchoFields struct threaded into the streaming wrapper; rewrite_lifecycle_echo_fields rewrites only lifecycle events (delta events short-circuit on a cheap byte-scan before JSON parsing).
  • chat.rs / background_executor.rs: stash original_previous_response_id before reconstruction clears payload.previous_response_id, and use the stashed value for both container-hint lookups and echo — fixing the previously reported container-binding bugs.

Confidence Score: 5/5

Safe to merge — the two container-binding breakages from the prior review are both fixed, and the new chain reconstruction, gateway-field stripping, and echo-field restoration are well-tested and logically sound.

The reconstruction logic hard-errors on corrupt records rather than silently dropping turns, the original_previous_response_id stash is applied consistently in all four lookup sites, and strip_gateway_fields is backed by a unit test. No new defects were found.

No files require special attention. The most complex new code (responses_chain.rs and the echo-field rewrite path in response_persister.rs) is well-covered by unit tests.

Important Files Changed

Filename Overview
src/services/responses_chain.rs New module implementing chain reconstruction; hard errors on corrupt records, depth-bounded at 200, tenant-scoped DB lookups. Exhaustive match via Rust's type system.
src/services/response_persister.rs Adds ResponseEchoFields and rewrite_lifecycle_echo_fields; correctly skips delta events via cheap byte-scan pre-filter, restores id/store/previous_response_id on lifecycle events only.
src/routes/api/chat.rs Stashes original_previous_response_id before clearing; uses it for container-hint lookup (fixing prior review bug) and non-streaming echo fields; restores original input/previous_response_id on the persisted snapshot.
src/services/background_executor.rs Applies the same reconstruction+stash pattern as the foreground handler; both container-lookup sites now correctly use original_previous_response_id instead of the cleared field.
src/api_types/responses.rs Adds strip_gateway_fields() with clear doc comments; forces store=false (not omitted) to prevent OpenAI double-storing and OpenRouter rejection. Backed by a targeted unit test.
src/providers/open_ai/mod.rs Calls strip_gateway_fields() on a local copy of the payload before serializing for the upstream; minimal, correct change.
src/services/responses_pipeline.rs Threads store_echo and previous_response_id_echo through PersistenceHandle into wrap_streaming_with_persistence; both callers supply the new fields.

Sequence Diagram

sequenceDiagram
    participant Client
    participant ChatRoute as chat.rs
    participant Chain as responses_chain.rs
    participant Store as ResponsesStore
    participant Provider as Upstream Provider
    participant Persister as response_persister.rs

    Client->>ChatRoute: "POST /responses {previous_response_id, input}"
    Note over ChatRoute: Stash original_previous_response_id & original_input
    ChatRoute->>Chain: reconstruct_input(store, org_id, prev_id, current_input)
    loop Walk chain newest to oldest
        Chain->>Store: get(id, org_id)
        Store-->>Chain: ResponseRecord
    end
    Chain-->>ChatRoute: "Vec<ResponsesInputItem> (full transcript)"
    Note over ChatRoute: payload.input = reconstructed, payload.previous_response_id = None
    ChatRoute->>Provider: POST /responses (strip_gateway_fields applied)
    alt Streaming
        Provider-->>Persister: SSE events
        Note over Persister: rewrite_lifecycle_echo_fields: id, store, previous_response_id restored
        Persister-->>Client: SSE events (echo fields restored)
        Persister->>Store: Persist final state
    else Non-streaming
        Provider-->>ChatRoute: JSON body
        Note over ChatRoute: apply_response_echo_fields patches id, store, previous_response_id
        ChatRoute-->>Client: JSON body (echo fields restored)
        ChatRoute->>Store: Persist with original_input + original_previous_response_id
    end
Loading

Reviews (6): Last reviewed commit: "Review fixes" | Re-trigger Greptile

Comment thread src/services/responses_chain.rs Outdated
@ScriptSmith

Copy link
Copy Markdown
Member Author

@greptile-apps

@ScriptSmith

Copy link
Copy Markdown
Member Author

@greptile-apps

@ScriptSmith ScriptSmith merged commit 0100c2b into main May 30, 2026
20 checks passed
@ScriptSmith ScriptSmith deleted the fix-gateway-fields branch May 30, 2026 12:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant