Commit Graph
6 Commits
Author SHA1 Message Date
michaelxerandXubin Ren 7917466f4e fix(tests): update image placeholder assertions for new non-descriptive text
The _strip_image_content methods now use a fixed non-descriptive
placeholder instead of path-derived text. Update the 3 existing
test_provider_retry assertions to match the new placeholder format.
2026-06-19 14:59:52 +08:00
michaelxerandXubin Ren 9ed3905a23 fix(providers): use non-descriptive placeholder when stripping images
The image-strip fallback (triggered when a model errors on image input)
replaced image_url blocks with [image: <path>] or [image omitted]. Both
read like a live, available image to the LLM, causing it to:

1. hallucinate about image contents it never received
2. attempt read_file on the leaked server path
3. expose internal file paths to the model

Replace with an explicit '[Image not delivered to model — do not describe
or reference it]' placeholder that tells the LLM the image was stripped.

Fixes #4345
2026-06-19 14:59:52 +08:00
michaelxerandXubin Ren 0023f6d998 fix(providers): remove custom cloud httpx client, let SDK handle proxy defaults
chengyongru reviewed #4367 and identified that the cloud  branch
created a bare httpx.AsyncClient that lacked the SDK's default settings
(follow_redirects, connection pool limits). Since the SDK's
DefaultAsyncHttpxClient already has trust_env=True and proper defaults,
the simplest fix is to let http_client stay None for cloud endpoints.

Also updated the test to match the new behavior (http_client is None).
2026-06-18 00:03:03 +08:00
michaelxerandXubin Ren 72b8fc806f fix(providers): disable proxy for local endpoints, respect env proxy for cloud
When the host has HTTP_PROXY / HTTPS_PROXY / ALL_PROXY set, httpx routes
all traffic through the proxy — including requests to localhost or LAN
addresses that the proxy typically cannot reach.  This breaks local model
servers (Ollama, llama.cpp, vLLM) silently.

- Local endpoints: pass transport=httpx.AsyncHTTPTransport(proxy=None)
  so proxy env vars are ignored for local traffic.
- Cloud endpoints: pass trust_env=True so corporate/VPN proxies work
  without explicit configuration.

Fixes #4366
2026-06-18 00:03:03 +08:00
9814a3b9fe fix(api): forward real LLM usage in /v1/chat/completions response (#4310)
* fix(api): forward real LLM usage in /v1/chat/completions response

_chat_completion_response() hardcoded prompt_tokens/completion_tokens
to zero.  Now reads agent_loop._last_usage (set by process_direct
after every LLM call) and forwards the actual prompt/completion counts.

Streaming path is unchanged; usage is only surfaced in non-streaming
responses for now.

Fixes #4309

* fix: use defensive getattr for _last_usage and add it to all test mock agents

- Use getattr(agent_loop, '_last_usage', None) in server.py for safety
- Add _last_usage = {} to mock agents in test_api_attachment.py and test_api_stream.py
- Prevents AttributeError/500 when mock agents don't have the attribute

* fix(api): preserve provider total usage

---------

Co-authored-by: michaelxer <michaelxer@users.noreply.github.com>
Co-authored-by: Xubin Ren <52506698+Re-bin@users.noreply.github.com>
2026-06-15 15:13:11 +08:00
michaelxerandXubin Ren 05de864f5b fix: preserve empty-string reasoning_content instead of coercing to None
Custom providers (e.g. DeepSeek) may return reasoning_content as an
empty string "" to explicitly indicate no reasoning occurred. The
previous truthiness checks (, ) treated "" as falsy
and converted it to None, which caused the field to be dropped from
the message history entirely. Providers that require reasoning_content
on all assistant messages then rejected subsequent requests.

Replace truthiness checks with identity checks () so that
empty-string reasoning_content is preserved as-is. The streaming path
is unchanged since an empty join genuinely means no chunks received.

Fixes #4105
2026-06-08 01:08:27 +08:00