local-openai2anthropic 0.2.8__py3-none-any.whl → 0.3.0__py3-none-any.whl

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.
@@ -179,6 +179,19 @@ async def _stream_response(
179
179
  if choice.get("finish_reason"):
180
180
  finish_reason = choice["finish_reason"]
181
181
 
182
+ # When finish_reason is tool_calls, we need to close the current block
183
+ # and prepare to send message_delta
184
+ if finish_reason == "tool_calls" and content_block_started:
185
+ stop_block = {
186
+ "type": "content_block_stop",
187
+ "index": content_block_index,
188
+ }
189
+ logger.debug(
190
+ f"[Anthropic Stream Event] content_block_stop (tool_calls): {json.dumps(stop_block, ensure_ascii=False)}"
191
+ )
192
+ yield f"event: content_block_stop\ndata: {json.dumps(stop_block)}\n\n"
193
+ content_block_started = False
194
+
182
195
  # Handle reasoning content (thinking)
183
196
  if delta.get("reasoning_content"):
184
197
  reasoning = delta["reasoning_content"]
@@ -253,6 +266,8 @@ async def _stream_response(
253
266
  if tool_calls:
254
267
  tool_call = tool_calls[0]
255
268
 
269
+ # Handle new tool call (with id) - use separate if, not elif
270
+ # because a chunk may have both id AND arguments
256
271
  if tool_call.get("id"):
257
272
  if content_block_started:
258
273
  yield f"event: content_block_stop\ndata: {json.dumps({'type': 'content_block_stop', 'index': content_block_index})}\n\n"
@@ -264,7 +279,9 @@ async def _stream_response(
264
279
  content_block_started = True
265
280
  current_block_type = "tool_use"
266
281
 
267
- elif (tool_call.get("function") or {}).get("arguments"):
282
+ # Handle tool call arguments - always check separately
283
+ # Note: This is intentionally NOT elif, as a single chunk may contain both
284
+ if (tool_call.get("function") or {}).get("arguments"):
268
285
  args = (tool_call.get("function") or {}).get("arguments", "")
269
286
  yield f"event: content_block_delta\ndata: {json.dumps({'type': 'content_block_delta', 'index': content_block_index, 'delta': {'type': 'input_json_delta', 'partial_json': args}})}\n\n"
270
287
 
@@ -495,8 +512,9 @@ async def _handle_with_server_tools(
495
512
  )
496
513
 
497
514
  completion_data = response.json()
498
- logger.debug(
499
- f"OpenAI response: {json.dumps(completion_data, indent=2)[:500]}..."
515
+ # Log raw OpenAI response for server tools
516
+ logger.info(
517
+ f"[OpenAI Response (Server Tools)] {json.dumps(completion_data, ensure_ascii=False, indent=2)[:2000]}"
500
518
  )
501
519
  from openai.types.chat import ChatCompletion
502
520
 
@@ -514,7 +532,12 @@ async def _handle_with_server_tools(
514
532
  if tool_calls:
515
533
  for tc in tool_calls:
516
534
  func_name = tc.function.name if tc.function else ""
535
+ func_args = tc.function.arguments if tc.function else "{}"
517
536
  logger.info(f" Tool call: {func_name}")
537
+ logger.info(f" Tool ID: {tc.id}")
538
+ logger.info(
539
+ f" Arguments: {func_args[:200]}"
540
+ ) # Log first 200 chars
518
541
 
519
542
  # Generate Anthropic-style ID for server tools
520
543
  is_server = handler.is_server_tool_call(
@@ -842,20 +865,60 @@ async def create_message(
842
865
  )
843
866
 
844
867
  openai_completion = response.json()
845
- logger.debug(
846
- f"[OpenAI Response] {json.dumps(openai_completion, ensure_ascii=False, indent=2)}"
868
+ # Log raw OpenAI response
869
+ logger.info(
870
+ f"[OpenAI Raw Response] {json.dumps(openai_completion, ensure_ascii=False, indent=2)[:2000]}"
847
871
  )
848
872
 
873
+ # Log response details
874
+ if openai_completion.get("choices"):
875
+ choice = openai_completion["choices"][0]
876
+ message = choice.get("message", {})
877
+ finish_reason = choice.get("finish_reason")
878
+ content_preview = (
879
+ message.get("content", "")[:100]
880
+ if message.get("content")
881
+ else ""
882
+ )
883
+ tool_calls_count = (
884
+ len(message.get("tool_calls", []))
885
+ if message.get("tool_calls")
886
+ else 0
887
+ )
888
+ logger.info(
889
+ f"[OpenAI Response Details] finish_reason={finish_reason}, "
890
+ f"content_length={len(message.get('content', ''))}, "
891
+ f"tool_calls={tool_calls_count}, "
892
+ f"content_preview={content_preview[:50]!r}"
893
+ )
894
+
849
895
  from openai.types.chat import ChatCompletion
850
896
 
851
897
  completion = ChatCompletion.model_validate(openai_completion)
852
898
  anthropic_message = convert_openai_to_anthropic(completion, model)
853
899
 
854
900
  anthropic_response = anthropic_message.model_dump()
855
- logger.debug(
856
- f"[Anthropic Response] {json.dumps(anthropic_response, ensure_ascii=False, indent=2)}"
901
+ # Log converted Anthropic response
902
+ logger.info(
903
+ f"[Anthropic Converted Response] {json.dumps(anthropic_response, ensure_ascii=False, indent=2)[:2000]}"
857
904
  )
858
905
 
906
+ # Log Anthropic response details
907
+ content_blocks = anthropic_response.get("content", [])
908
+ stop_reason = anthropic_response.get("stop_reason")
909
+ usage = anthropic_response.get("usage", {})
910
+ logger.info(
911
+ f"[Anthropic Response Details] stop_reason={stop_reason}, "
912
+ f"content_blocks={len(content_blocks)}, "
913
+ f"input_tokens={usage.get('input_tokens')}, "
914
+ f"output_tokens={usage.get('output_tokens')}"
915
+ )
916
+
917
+ # Log content block types
918
+ if content_blocks:
919
+ block_types = [block.get("type") for block in content_blocks]
920
+ logger.info(f"[Anthropic Content Blocks] types={block_types}")
921
+
859
922
  return JSONResponse(content=anthropic_response)
860
923
 
861
924
  except httpx.TimeoutException:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: local-openai2anthropic
3
- Version: 0.2.8
3
+ Version: 0.3.0
4
4
  Summary: A lightweight proxy server that converts Anthropic Messages API to OpenAI API
5
5
  Project-URL: Homepage, https://github.com/dongfangzan/local-openai2anthropic
6
6
  Project-URL: Repository, https://github.com/dongfangzan/local-openai2anthropic
@@ -7,13 +7,13 @@ local_openai2anthropic/daemon_runner.py,sha256=rguOH0PgpbjqNsKYei0uCQX8JQOQ1wmtQ
7
7
  local_openai2anthropic/main.py,sha256=FK5JBBpzB_T44y3N16lPl1hK4ht4LEQqRKzVmkIjIoo,9866
8
8
  local_openai2anthropic/openai_types.py,sha256=jFdCvLwtXYoo5gGRqOhbHQcVaxcsxNnCP_yFPIv7rG4,3823
9
9
  local_openai2anthropic/protocol.py,sha256=vUEgxtRPFll6jEtLc4DyxTLCBjrWIEScZXhEqe4uibk,5185
10
- local_openai2anthropic/router.py,sha256=SCmwXSh02E8QX_oNCSXC5JvMDDI8Zfso0YBnPIykBss,42853
10
+ local_openai2anthropic/router.py,sha256=ci8G3XL3eHzpn3kOko5QhnqLtIQTrlAaIhvzrvuk_Jc,46271
11
11
  local_openai2anthropic/tavily_client.py,sha256=QsBhnyF8BFWPAxB4XtWCCpHCquNL5SW93-zjTTi4Meg,3774
12
12
  local_openai2anthropic/server_tools/__init__.py,sha256=QlJfjEta-HOCtLe7NaY_fpbEKv-ZpInjAnfmSqE9tbk,615
13
13
  local_openai2anthropic/server_tools/base.py,sha256=pNFsv-jSgxVrkY004AHAcYMNZgVSO8ZOeCzQBUtQ3vU,5633
14
14
  local_openai2anthropic/server_tools/web_search.py,sha256=1C7lX_cm-tMaN3MsCjinEZYPJc_Hj4yAxYay9h8Zbvs,6543
15
- local_openai2anthropic-0.2.8.dist-info/METADATA,sha256=VfHnmWbI52pgbH9kzjimeUJ3r0XVwvdMnTodX8-3nH4,11240
16
- local_openai2anthropic-0.2.8.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
17
- local_openai2anthropic-0.2.8.dist-info/entry_points.txt,sha256=hdc9tSJUNxyNLXcTYye5SuD2K0bEQhxBhGnWTFup6ZM,116
18
- local_openai2anthropic-0.2.8.dist-info/licenses/LICENSE,sha256=X3_kZy3lJvd_xp8IeyUcIAO2Y367MXZc6aaRx8BYR_s,11369
19
- local_openai2anthropic-0.2.8.dist-info/RECORD,,
15
+ local_openai2anthropic-0.3.0.dist-info/METADATA,sha256=e8dCKWpeT7dth6tqLfW7RvRaJxrUUr4DRg3OJDc3MBI,11240
16
+ local_openai2anthropic-0.3.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
17
+ local_openai2anthropic-0.3.0.dist-info/entry_points.txt,sha256=hdc9tSJUNxyNLXcTYye5SuD2K0bEQhxBhGnWTFup6ZM,116
18
+ local_openai2anthropic-0.3.0.dist-info/licenses/LICENSE,sha256=X3_kZy3lJvd_xp8IeyUcIAO2Y367MXZc6aaRx8BYR_s,11369
19
+ local_openai2anthropic-0.3.0.dist-info/RECORD,,