[proxy 05/13] upstream.py: httpx client that injects options.num_ctx (the core fix) #9

Closed
opened 2026-06-26 09:48:18 +00:00 by coilysiren · 2 comments
Owner

Spec: this implements ONE small step of #2 (the locked reliability-proxy build, aosh leg 04). Do not redesign. Stay tightly scoped to this single step.

Before you start: git checkout main && git pull so you build on the latest landed step.
Fill in app/upstream.py - this is the highest-value step, the num_ctx injection that kills the 32k truncation.

  • Async function dispatch_chat(logical_name, messages, **opts) -> dict.
  • Look up the model via app.models.get_model. POST with an httpx.AsyncClient to {backend_url}/api/chat (native ollama API), body: {"model": ollama_tag, "messages": messages, "stream": false, "options": {"num_ctx": <the model's num_ctx>}}.
  • The whole point: options.num_ctx MUST be set from the registry on every request. Return the parsed JSON.
  • Log the request with structlog including the injected num_ctx.

Acceptance: a pytest using respx or monkeypatched httpx asserts that the outgoing payload to /api/chat contains options.num_ctx == 49152 for fast-think. (Live tower test is gated on ward#330 and handled in step 07 - do NOT block on it here.)

When done:

  1. pre-commit run --all-files (or the repo's gate) must pass, commit your work, and push to canonical main (this is an ephemeral feature container - finish the merge, do not leave it for a human).
  2. Update the matching line in docs/FEATURES.md from planned to landed for this feature, in the same push.
  3. Dispatch the next step: ward agent engineer coilyco-flight-deck/agent-proxy#10 --driver goose
**Spec:** this implements ONE small step of #2 (the locked reliability-proxy build, aosh leg 04). **Do not redesign. Stay tightly scoped to this single step.** **Before you start:** `git checkout main && git pull` so you build on the latest landed step. Fill in `app/upstream.py` - **this is the highest-value step, the num_ctx injection that kills the 32k truncation.** - Async function `dispatch_chat(logical_name, messages, **opts) -> dict`. - Look up the model via `app.models.get_model`. POST with an `httpx.AsyncClient` to `{backend_url}/api/chat` (native ollama API), body: `{"model": ollama_tag, "messages": messages, "stream": false, "options": {"num_ctx": <the model's num_ctx>}}`. - **The whole point:** `options.num_ctx` MUST be set from the registry on every request. Return the parsed JSON. - Log the request with structlog including the injected num_ctx. **Acceptance:** a pytest using `respx` or monkeypatched httpx asserts that the outgoing payload to `/api/chat` contains `options.num_ctx == 49152` for `fast-think`. (Live tower test is gated on ward#330 and handled in step 07 - do NOT block on it here.) **When done:** 1. `pre-commit run --all-files` (or the repo's gate) must pass, commit your work, and push to canonical `main` (this is an ephemeral feature container - finish the merge, do not leave it for a human). 2. Update the matching line in `docs/FEATURES.md` from `planned` to `landed` for this feature, in the same push. 3. Dispatch the next step: `ward agent engineer coilyco-flight-deck/agent-proxy#10 --driver goose`
Member

🔒 Reserved by ward agent --driver claude — container engineer-claude-agent-proxy-9 on host kais-macbook-pro-2.local is carrying this issue (reserved 2026-07-02T16:43:38Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `engineer-claude-agent-proxy-9` on host `kais-macbook-pro-2.local` is carrying this issue (reserved 2026-07-02T16:43:38Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Owner

WARD-OUTCOME: done - added a registry-sourced num_ctx test proving fast-think injects options.num_ctx==49152; core injection already landed with the resilience-proxy core.

Honestly this one felt less like building and more like archaeology. I opened the container ready to write upstream.py from scratch, and found it already fully fleshed out on main - the num_ctx injection, the caller-can't-override guard, ollama/OpenAI dialect handling, all of it landed earlier as part of the big resilience-proxy-core merge (issue #2), and FEATURES.md already read landed. So the interesting work was deciding what #9 still means once its deliverable exists.

The tempting-but-wrong move was to add the literal dispatch_chat(logical_name, ...) signature from the spec. But the landed architecture routes through resilience.dispatch (retry/fallback/circuit-breaker) which calls upstream.chat(backend, model.num_ctx, ...), so a parallel dispatch_chat that skipped resilience would have been dead code - a redesign the doctrine explicitly forbids. What was genuinely missing versus the acceptance criterion was proof the 49152 comes from the registry for fast-think, not a hand-passed constant. So that's the one thing I added: a tight test that resolves fast-think from the registry and asserts its num_ctx reaches the outgoing /api/chat payload. 38 tests green.

Confidence is high - the behavior was already proven end-to-end against the live tower, I just closed the test gap. Two rough edges worth noting: the disk hit 100% mid-run (had to clear the uv cache and drop .venv to even dispatch), and step #10 turned out to be already reserved and in flight by another container, so I did not force the dispatch.

WARD-OUTCOME: done - added a registry-sourced num_ctx test proving fast-think injects options.num_ctx==49152; core injection already landed with the resilience-proxy core. Honestly this one felt less like building and more like archaeology. I opened the container ready to write `upstream.py` from scratch, and found it already fully fleshed out on `main` - the num_ctx injection, the caller-can't-override guard, ollama/OpenAI dialect handling, all of it landed earlier as part of the big resilience-proxy-core merge (issue #2), and FEATURES.md already read `landed`. So the interesting work was deciding what #9 still *means* once its deliverable exists. The tempting-but-wrong move was to add the literal `dispatch_chat(logical_name, ...)` signature from the spec. But the landed architecture routes through `resilience.dispatch` (retry/fallback/circuit-breaker) which calls `upstream.chat(backend, model.num_ctx, ...)`, so a parallel `dispatch_chat` that skipped resilience would have been dead code - a redesign the doctrine explicitly forbids. What was genuinely missing versus the acceptance criterion was proof the 49152 comes *from the registry* for fast-think, not a hand-passed constant. So that's the one thing I added: a tight test that resolves fast-think from the registry and asserts its num_ctx reaches the outgoing /api/chat payload. 38 tests green. Confidence is high - the behavior was already proven end-to-end against the live tower, I just closed the test gap. Two rough edges worth noting: the disk hit 100% mid-run (had to clear the uv cache and drop .venv to even dispatch), and step #10 turned out to be already reserved and in flight by another container, so I did not force the dispatch.
Sign in to join this conversation.
No description provided.