openzoo 0.48.47 → 0.48.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/proxy.js +23 -2
- package/package.json +1 -1
package/lib/proxy.js
CHANGED
|
@@ -863,6 +863,10 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
863
863
|
// answer back on the way out. See lib/anthropic.js.
|
|
864
864
|
let anthropicMode = false;
|
|
865
865
|
let anthropicModel = null;
|
|
866
|
+
// The CLIENT's streaming intent, kept separate from the body we send
|
|
867
|
+
// upstream. The Anthropic lane asks the gateway for a complete message (we
|
|
868
|
+
// can only translate a finished one) while still owing the caller SSE.
|
|
869
|
+
let clientWantsStream = false;
|
|
866
870
|
let responsesMode = false;
|
|
867
871
|
let responsesModel = null;
|
|
868
872
|
let responsesCustom = null; // names of freeform tools needing custom_tool_call on the way back
|
|
@@ -912,7 +916,24 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
912
916
|
try {
|
|
913
917
|
const inbound = JSON.parse(bodyBuf.toString('utf8'));
|
|
914
918
|
anthropicModel = inbound.model;
|
|
915
|
-
|
|
919
|
+
// ANTHROPIC CLIENTS CANNOT READ AN OPENAI STREAM.
|
|
920
|
+
//
|
|
921
|
+
// The gateway now streams for real, and `relay()` pipes those frames
|
|
922
|
+
// through untouched — which is correct for an OpenAI client and
|
|
923
|
+
// unreadable to Claude Code, which speaks the Anthropic SSE grammar
|
|
924
|
+
// (message_start / content_block_delta / message_stop). It surfaced as
|
|
925
|
+
// "API returned an empty or malformed response (HTTP 200)": a 200 whose
|
|
926
|
+
// body the client cannot parse.
|
|
927
|
+
//
|
|
928
|
+
// The translation we have (openAIToAnthropic + writeAnthropicSse) works
|
|
929
|
+
// on a COMPLETE message, so this lane asks the gateway not to stream and
|
|
930
|
+
// keeps the buffered translation. That costs Claude Code the
|
|
931
|
+
// time-to-first-byte win until an incremental OpenAI->Anthropic frame
|
|
932
|
+
// translator exists; a readable answer late beats an unreadable one now.
|
|
933
|
+
const converted = anthropicToOpenAI(inbound);
|
|
934
|
+
clientWantsStream = converted.stream === true || inbound.stream === true;
|
|
935
|
+
converted.stream = false;
|
|
936
|
+
bodyBuf = Buffer.from(JSON.stringify(converted));
|
|
916
937
|
anthropicMode = true;
|
|
917
938
|
req.url = '/v1/chat/completions';
|
|
918
939
|
url = `${config.apiBase}${req.url}`;
|
|
@@ -939,7 +960,7 @@ export async function startProxy({ silent = false, requireToken = null, sessionM
|
|
|
939
960
|
}
|
|
940
961
|
try {
|
|
941
962
|
const parsed = JSON.parse(bodyBuf.toString('utf8'));
|
|
942
|
-
wantsStream = parsed?.stream === true;
|
|
963
|
+
wantsStream = parsed?.stream === true || clientWantsStream;
|
|
943
964
|
// REASONING MODELS SPEND max_tokens ON THINKING FIRST.
|
|
944
965
|
//
|
|
945
966
|
// The budget covers hidden reasoning AND the visible answer, so a
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.48.
|
|
3
|
+
"version": "0.48.48",
|
|
4
4
|
"description": "Local x402-paying proxy + MCP server for openzoo.fun — point any OpenAI-compatible harness (Cursor, Claude Code, aider, SDKs) at localhost and it pays per call from a local burner wallet. Solana and Base rails live; Robinhood experimental.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|