Conversation
|
Thanks for carrying the Azure-specific replay fix forward. The premise remains present on current main: Suggested changes
Automated hermes-sweeper review. |
Correction: #67667 is related to #63264, not a duplicate. Both preserve Azure Foundry replay IDs, but #67667 replaces #63264's substring endpoint detection with hostname-aware matching and adds current-path coverage. Please choose or consolidate the approach; a rebase must retain current main's existing base_url propagation. |
Correction: this is related to #63264 rather than a duplicate. The current head keeps the same Azure replay fix but materially changes endpoint detection to hostname-aware matching; maintainers should choose the corrected implementation. |
Corrected |
dc7e558 to
619adfd
Compare
|
Rebased onto current main (40e0e7a) and resolved all conflicts. Changes since last push:
The PR is now mergeable (mergeable_state: blocked, awaiting maintainer review). |
Self-review of the previous force-push — issues found and fixedReviewed my own rebase before asking for another look, and found a self-defeating regression plus several conflict-resolution artefacts. All fixed in The critical oneThe previous push removed That parameter is what the transport keys the Azure detection off: is_azure_foundry = _is_azure_foundry_base_url(params.get("base_url"))So the main conversation loop passed Demonstrated: Three unrelated features read the same parameter and regressed silently with it:
Existing tests could not catch this: they call
Also fixed
Test coverage added
VerificationRun on Linux / Python 3.11: The 3 failures are pre-existing (missing Still open for maintainersOne thing I deliberately did not change, since it is a design call: Azure Foundry detection is now implemented three times — |
f67a743 to
66687dc
Compare
Post-merge review + fixes (
|
| Decision | Predicate used | Matches on |
|---|---|---|
| Post-tool reasoning suppression | _is_azure_foundry_responses(params) |
provider id OR host |
Wire-shape normalization (reasoning id, annotations) |
_is_azure_foundry_base_url(base_url) |
host only |
A registered provider: azure-foundry pointed at a gateway/proxy URL therefore got the suppression but not the reasoning id this PR exists to preserve — exactly the failure mode #63257 fixes. Reproduced against the merge commit:
provider=azure-foundry base_url=https://proxy.corp.example/v1
-> {'type': 'reasoning', 'encrypted_content': 'enc', 'summary': []} # id missing
provider=None base_url=https://x.services.ai.azure.com/...
-> {'type': 'reasoning', ..., 'id': 'rs_1'} # id present
Fix: both decisions now key off the provider-aware _is_azure_foundry_responses. Two call sites; _is_azure_foundry_base_url stays as the URL-only helper it always was.
🔴 annotations stamped onto image parts
The Azure branch defaulted annotations: [] on every assistant content part — four duplicated inline loops, one of which runs over input_image parts. annotations has no member in the Responses schema for images:
{'type': 'input_image', 'image_url': 'https://…/a.png', 'annotations': []} # undocumented shape
Fix: extracted _apply_azure_output_text_annotations(), scoped strictly to output_text, replacing all four loops.
🟡 Test coverage gap (the reason both slipped through)
The merged tests exercised each feature in isolation, so a merge that dropped either half still went green:
tests/agent/transports/test_codex_transport.py:261— Azure preflight tested withoutsanitize_harmony_tokens=Truetests/agent/test_codex_responses_adapter.py:98,125,187-190— Harmony sanitization tested withoutis_azure_foundry=True- The live-path fixture
_azure_reasoning_item()(tests/run_agent/test_run_agent_codex_responses.py:353) has noid, sotest_build_api_kwargs_azure_foundry_non_tool_preserves_reasoningasserted only that a reasoning item exists — never that the id survives, which is the whole point of the fix
Added TestAzureFoundryWireShape: behaviour contracts for which items get Foundry-only fields, provider-vs-host detection agreement, hostname substring false-positives (https://evil.com/openai.azure.com/v1, https://openai.azure.com.evil.net/v1), and a combined Azure + Harmony test proving the two merged features compose on the same request.
Verification
Both guards were validated by re-injecting each bug — a guard that can't detect its own failure mode is worthless:
inject bug 1 (host-only predicate) -> 2 failed (only the provider-detection cases)
inject bug 2 (annotations on all) -> 1 failed (only the output_text-scoping case)
both fixed -> 115 passed
Regression sweep across the codex transport, adapter, auxiliary-client and native-compaction suites:
with changes: 364 passed, 10 failed
baseline: 249 passed, 10 failed
Same 10 pre-existing failures in both runs — all ModuleNotFoundError: No module named 'openai' in my checkout's environment, unrelated to these changes. Net +115 passing tests, zero regressions.
Remaining (not addressed here — happy to take direction)
tests/run_agent/test_native_compaction.py:540-562passesnative_compaction_eligible=Truedirectly, bypassing the production derivation fromcontext_management. A full config-to-wire test throughbuild_kwargswith a persisted checkpoint would close that gap; it's orthogonal to this PR's scope, so I left it alone rather than widen the diff.
125a61a to
e568fe2
Compare
Related to #63264, not a duplicate: this current-main implementation retains the Azure reasoning replay-ID repair while using hostname-aware endpoint matching requested in review. |
fix(codex): preserve azure reasoning replay ids with hostname-aware matching Unifying the Foundry predicate (suppression and wire shape now key off
|
174920b to
2dab6b9
Compare
2dab6b9 to
a6e10e6
Compare
Refactor port: tests restored, one detection gap fixed (
|
| File | Coverage |
|---|---|
tests/agent/test_azure_foundry_preflight_propagation.py (new) |
Drives the real turn_api_request.build_api_request and turn_api_call.perform_api_call with ResponsesApiTransport; asserts the wire payload. Provider-detected behind a proxy, host-detected on both hostnames, untouched for OpenAI / Codex / Copilot / xAI / look-alikes. Current-main equivalent of the "survives full build_api_kwargs" guard from 1 Aug. |
transports/test_codex_transport.py::TestAzureFoundryWireShape |
build_kwargs and preflight_kwargs contracts, predicate table, post-tool suppression / wire-shape agreement on one predicate. |
test_codex_responses_adapter.py |
Reasoning id kept for Foundry / stripped otherwise; annotations only on output_text (helper contract vs input_image / input_text / refusal, existing annotations preserved); Foundry + Harmony sanitisation compose. |
test_auxiliary_client.py::TestCodexAdapterAzureFoundryReasoningReplay |
Host detection on both hostnames; runtime-provider detection behind a proxy via set_runtime_main; non-Foundry unchanged. |
Verification
Each guard was validated by re-injecting its bug:
host-only predicate (services.ai.azure.com only) -> 5 failed
annotations stamped on every part -> 1 failed
provider/base_url not forwarded in turn_api_request -> 4 failed
all fixed -> 192 passed (targeted)
Regression sweep (adapter, transports/, auxiliary client, run_agent codex / native-compaction / provider-parity, surrogate chokepoints, cache-TTL propagation): 774 passed, 0 failed.
508fc17 to
5be2286
Compare
|
Simplified in 1331e9a to build directly on the merged Azure Responses predicate from 267a6b7.
The remaining fix is specifically reasoning-ID preservation and Verification via the repository's clean-environment Updated the PR title/description to reflect the current post-refactor paths and its relationship to the merged fix. These are local regression results, not a new live Azure endpoint test or a full-repository CI claim. |
ae6698f to
0ba9d90
Compare
d17f46e to
1a3b310
Compare
…azure.com in transport predicate The refactor port (a129010) was regenerated from a source-only local patch, so the behaviour-contract tests that previously lived on this branch were dropped. Restore them against the current call graph and close the gaps the E2E test found. Fix: `_is_azure_foundry_responses` matched only `services.ai.azure.com`, while the auxiliary client (and the pre-refactor branch) also matched `openai.azure.com` resource endpoints. A custom provider pointed at `https://<res>.openai.azure.com/…` therefore got the Foundry shape on auxiliary calls but not on the main turn. The transport predicate now covers both hostnames (hostname-aware, no substring match). Tests: - tests/agent/test_azure_foundry_preflight_propagation.py (new): drives the real `turn_api_request.build_api_request` and `turn_api_call.perform_api_call` with `ResponsesApiTransport` and asserts the wire payload — provider-detected behind a proxy, host-detected on both hostnames, and untouched for OpenAI / Codex / Copilot / xAI / look-alike hosts. - transports/test_codex_transport.py::TestAzureFoundryWireShape: build_kwargs and preflight_kwargs contracts, predicate table, suppression/wire-shape agreement. - test_codex_responses_adapter.py: id preservation both ways, annotations only on output_text (incl. helper contract vs input_image/input_text/refusal), Foundry + Harmony sanitisation compose. - test_auxiliary_client.py::TestCodexAdapterAzureFoundryReasoningReplay: host detection on both hostnames, runtime-provider detection behind a proxy via `set_runtime_main`, non-Foundry unchanged. Each guard was verified by re-injecting its bug: host-only predicate → 5 failed; annotations on all parts → 1 failed; dropped provider/base_url forwarding in turn_api_request → 4 failed.
Leave the upstream post-tool suppression predicate unchanged. Resolve Azure context in preflight from provider/base_url instead of forwarding a redundant boolean. Preserve payload coverage and parameterize the streaming path across provider and hostname detection. Verified: independent diff review; 869 targeted tests pass via scripts/run_tests.sh. Policy-boundary test fails on the previous patch; dropping streaming base_url fails both hostname cases.
f19dfb8 to
c0f74d2
Compare
Rebased onto current
|
Summary
Preserve Azure-required reasoning IDs and assistant
output_text.annotationsthrough Responses replay conversion and preflight validation. Non-Azure Responses endpoints retain their existing ID-stripping behavior.Builds on the merged Azure detection / newest-only replay handling, including 267a6b7. The transport reuses
_is_azure_responses()for wire-shape classification instead of broadening_is_azure_foundry_responses(). This PR leaves main's replay-selection and post-tool suppression policy unchanged.Based on the original PR #63264 by @LeonSGP43 and the report in #63257. Retains hostname-aware
base_url_host_matches()detection requested in review; Azure-looking URL paths and look-alike host suffixes do not activate the workaround.Closes #63257
Changes
{type, id, encrypted_content, summary}on replayed Azure reasoning items through conversion and preflight.annotations: []only to assistantoutput_textparts, never image/input-text parts.Production files:
agent/codex_responses_adapter.py,agent/transports/codex.py,agent/auxiliary_client.py,agent/turn_api_request.py, andagent/turn_api_call.py.Policy boundary
For a custom provider such as
azon*.openai.azure.com, main retains newest-only reasoning after tools. This PR preserves that selection and repairs the replayed item's fields. Registeredazure-foundryproviders and*.services.ai.azure.comstill use main's existing post-tool suppression. No new replay policy is introduced.Validation
Run via
scripts/run_tests.sh(clean environment and per-file subprocess isolation):base_urlfrom streaming preflight was re-injected experimentally: both hostname-based cases failed; restoring it passed.openai.azure.com; passes after restoring upstream's suppression predicate.git diff --check: clean.These are local regression tests, not a new live Azure endpoint validation or a claim that the full repository suite ran.