lite-agent 0.8.0__py3-none-any.whl → 0.10.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.
Potentially problematic release.
This version of lite-agent might be problematic. Click here for more details.
- lite_agent/agent.py +17 -263
- lite_agent/chat_display.py +304 -41
- lite_agent/client.py +15 -8
- lite_agent/message_transfers.py +21 -2
- lite_agent/processors/response_event_processor.py +4 -2
- lite_agent/runner.py +90 -104
- lite_agent/types/__init__.py +1 -1
- lite_agent/types/messages.py +2 -1
- lite_agent/utils/advanced_message_builder.py +201 -0
- lite_agent/utils/message_builder.py +4 -2
- lite_agent/utils/message_converter.py +232 -0
- lite_agent/utils/message_state_manager.py +152 -0
- {lite_agent-0.8.0.dist-info → lite_agent-0.10.0.dist-info}/METADATA +2 -2
- {lite_agent-0.8.0.dist-info → lite_agent-0.10.0.dist-info}/RECORD +15 -12
- {lite_agent-0.8.0.dist-info → lite_agent-0.10.0.dist-info}/WHEEL +0 -0
lite_agent/chat_display.py
CHANGED
|
@@ -454,7 +454,7 @@ def _display_single_message_compact(
|
|
|
454
454
|
show_timestamp: bool = False,
|
|
455
455
|
local_timezone: timezone | None = None,
|
|
456
456
|
) -> None:
|
|
457
|
-
"""
|
|
457
|
+
"""以列式格式打印单个消息,类似 rich log。"""
|
|
458
458
|
|
|
459
459
|
def truncate_content(content: str, max_length: int) -> str:
|
|
460
460
|
"""截断内容并添加省略号。"""
|
|
@@ -462,20 +462,265 @@ def _display_single_message_compact(
|
|
|
462
462
|
return content
|
|
463
463
|
return content[: max_length - 3] + "..."
|
|
464
464
|
|
|
465
|
-
#
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
"max_content_length": max_content_length,
|
|
471
|
-
"truncate_content": truncate_content,
|
|
472
|
-
"show_timestamp": show_timestamp,
|
|
473
|
-
"local_timezone": local_timezone,
|
|
474
|
-
}
|
|
475
|
-
context = _create_message_context(context_config)
|
|
465
|
+
# 获取时间戳
|
|
466
|
+
timestamp = None
|
|
467
|
+
if show_timestamp:
|
|
468
|
+
message_time = _extract_message_time(message)
|
|
469
|
+
timestamp = _format_timestamp(message_time, local_timezone=local_timezone)
|
|
476
470
|
|
|
477
|
-
#
|
|
478
|
-
|
|
471
|
+
# 创建列式显示
|
|
472
|
+
_display_message_in_columns(message, console, index, timestamp, max_content_length, truncate_content)
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
def _display_message_in_columns(
|
|
476
|
+
message: FlexibleRunnerMessage,
|
|
477
|
+
console: Console,
|
|
478
|
+
index: int | None,
|
|
479
|
+
timestamp: str | None,
|
|
480
|
+
max_content_length: int,
|
|
481
|
+
truncate_content: Callable[[str, int], str],
|
|
482
|
+
) -> None:
|
|
483
|
+
"""以列式格式显示消息,类似 rich log。"""
|
|
484
|
+
|
|
485
|
+
# 构建时间和索引列
|
|
486
|
+
time_str = timestamp or ""
|
|
487
|
+
index_str = f"#{index:2d}" if index is not None else ""
|
|
488
|
+
|
|
489
|
+
# 根据消息类型处理内容
|
|
490
|
+
if isinstance(message, NewUserMessage):
|
|
491
|
+
_display_user_message_with_columns(message, console, time_str, index_str, max_content_length, truncate_content)
|
|
492
|
+
elif isinstance(message, NewAssistantMessage):
|
|
493
|
+
_display_assistant_message_with_columns(message, console, time_str, index_str, max_content_length, truncate_content)
|
|
494
|
+
elif isinstance(message, NewSystemMessage):
|
|
495
|
+
_display_system_message_with_columns(message, console, time_str, index_str, max_content_length, truncate_content)
|
|
496
|
+
else:
|
|
497
|
+
# 处理旧格式消息
|
|
498
|
+
_display_legacy_message_with_columns(message, console, time_str, index_str, max_content_length, truncate_content)
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
def _display_user_message_with_columns(
|
|
502
|
+
message: NewUserMessage,
|
|
503
|
+
console: Console,
|
|
504
|
+
time_str: str,
|
|
505
|
+
index_str: str,
|
|
506
|
+
max_content_length: int,
|
|
507
|
+
truncate_content: Callable[[str, int], str],
|
|
508
|
+
) -> None:
|
|
509
|
+
"""使用列布局显示用户消息。"""
|
|
510
|
+
content_parts = []
|
|
511
|
+
for item in message.content:
|
|
512
|
+
if item.type == "text":
|
|
513
|
+
content_parts.append(item.text)
|
|
514
|
+
elif item.type == "image":
|
|
515
|
+
if item.image_url:
|
|
516
|
+
content_parts.append(f"[Image: {item.image_url}]")
|
|
517
|
+
elif item.file_id:
|
|
518
|
+
content_parts.append(f"[Image: {item.file_id}]")
|
|
519
|
+
elif item.type == "file":
|
|
520
|
+
file_name = item.file_name or item.file_id
|
|
521
|
+
content_parts.append(f"[File: {file_name}]")
|
|
522
|
+
|
|
523
|
+
content = " ".join(content_parts)
|
|
524
|
+
content = truncate_content(content, max_content_length)
|
|
525
|
+
|
|
526
|
+
# 创建表格来确保对齐
|
|
527
|
+
table = Table.grid(padding=0)
|
|
528
|
+
table.add_column(width=8, justify="left") # 时间列
|
|
529
|
+
table.add_column(width=4, justify="left") # 序号列
|
|
530
|
+
table.add_column(min_width=0) # 内容列
|
|
531
|
+
|
|
532
|
+
lines = content.split("\n")
|
|
533
|
+
for i, line in enumerate(lines):
|
|
534
|
+
if i == 0:
|
|
535
|
+
# 第一行显示 User: 标签
|
|
536
|
+
table.add_row(
|
|
537
|
+
f"[dim]{time_str:8}[/dim]",
|
|
538
|
+
f"[dim]{index_str:4}[/dim]",
|
|
539
|
+
"[blue]User:[/blue]",
|
|
540
|
+
)
|
|
541
|
+
# 如果有内容,添加内容行
|
|
542
|
+
if line:
|
|
543
|
+
table.add_row("", "", line)
|
|
544
|
+
else:
|
|
545
|
+
# 续行只在内容列显示
|
|
546
|
+
table.add_row("", "", line)
|
|
547
|
+
|
|
548
|
+
console.print(table)
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
def _display_system_message_with_columns(
|
|
552
|
+
message: NewSystemMessage,
|
|
553
|
+
console: Console,
|
|
554
|
+
time_str: str,
|
|
555
|
+
index_str: str,
|
|
556
|
+
max_content_length: int,
|
|
557
|
+
truncate_content: Callable[[str, int], str],
|
|
558
|
+
) -> None:
|
|
559
|
+
"""使用列布局显示系统消息。"""
|
|
560
|
+
content = truncate_content(message.content, max_content_length)
|
|
561
|
+
|
|
562
|
+
# 创建表格来确保对齐
|
|
563
|
+
table = Table.grid(padding=0)
|
|
564
|
+
table.add_column(width=8, justify="left") # 时间列
|
|
565
|
+
table.add_column(width=4, justify="left") # 序号列
|
|
566
|
+
table.add_column(min_width=0) # 内容列
|
|
567
|
+
|
|
568
|
+
lines = content.split("\n")
|
|
569
|
+
for i, line in enumerate(lines):
|
|
570
|
+
if i == 0:
|
|
571
|
+
# 第一行显示完整信息
|
|
572
|
+
table.add_row(
|
|
573
|
+
f"[dim]{time_str:8}[/dim]",
|
|
574
|
+
f"[dim]{index_str:4}[/dim]",
|
|
575
|
+
f"[yellow]System:[/yellow] {line}",
|
|
576
|
+
)
|
|
577
|
+
else:
|
|
578
|
+
# 续行只在内容列显示
|
|
579
|
+
table.add_row("", "", line)
|
|
580
|
+
|
|
581
|
+
console.print(table)
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def _display_assistant_message_with_columns(
|
|
585
|
+
message: NewAssistantMessage,
|
|
586
|
+
console: Console,
|
|
587
|
+
time_str: str,
|
|
588
|
+
index_str: str,
|
|
589
|
+
max_content_length: int,
|
|
590
|
+
truncate_content: Callable[[str, int], str],
|
|
591
|
+
) -> None:
|
|
592
|
+
"""使用列布局显示助手消息。"""
|
|
593
|
+
# 提取内容
|
|
594
|
+
text_parts = []
|
|
595
|
+
tool_calls = []
|
|
596
|
+
tool_results = []
|
|
597
|
+
|
|
598
|
+
for item in message.content:
|
|
599
|
+
if item.type == "text":
|
|
600
|
+
text_parts.append(item.text)
|
|
601
|
+
elif item.type == "tool_call":
|
|
602
|
+
tool_calls.append(item)
|
|
603
|
+
elif item.type == "tool_call_result":
|
|
604
|
+
tool_results.append(item)
|
|
605
|
+
|
|
606
|
+
# 构建元信息
|
|
607
|
+
meta_info = ""
|
|
608
|
+
if message.meta:
|
|
609
|
+
meta_parts = []
|
|
610
|
+
if message.meta.model is not None:
|
|
611
|
+
meta_parts.append(f"Model:{message.meta.model}")
|
|
612
|
+
if message.meta.latency_ms is not None:
|
|
613
|
+
meta_parts.append(f"Latency:{message.meta.latency_ms}ms")
|
|
614
|
+
if message.meta.total_time_ms is not None:
|
|
615
|
+
meta_parts.append(f"Output:{message.meta.total_time_ms}ms")
|
|
616
|
+
if message.meta.usage and message.meta.usage.input_tokens is not None and message.meta.usage.output_tokens is not None:
|
|
617
|
+
total_tokens = message.meta.usage.input_tokens + message.meta.usage.output_tokens
|
|
618
|
+
meta_parts.append(f"Tokens:↑{message.meta.usage.input_tokens}↓{message.meta.usage.output_tokens}={total_tokens}")
|
|
619
|
+
|
|
620
|
+
if meta_parts:
|
|
621
|
+
meta_info = f" [dim]({' | '.join(meta_parts)})[/dim]"
|
|
622
|
+
|
|
623
|
+
# 创建表格来确保对齐
|
|
624
|
+
table = Table.grid(padding=0)
|
|
625
|
+
table.add_column(width=8, justify="left") # 时间列
|
|
626
|
+
table.add_column(width=4, justify="left") # 序号列
|
|
627
|
+
table.add_column(min_width=0) # 内容列
|
|
628
|
+
|
|
629
|
+
# 处理文本内容
|
|
630
|
+
first_row_added = False
|
|
631
|
+
if text_parts:
|
|
632
|
+
content = " ".join(text_parts)
|
|
633
|
+
content = truncate_content(content, max_content_length)
|
|
634
|
+
lines = content.split("\n")
|
|
635
|
+
for i, line in enumerate(lines):
|
|
636
|
+
if i == 0:
|
|
637
|
+
# 第一行显示 Assistant: 标签
|
|
638
|
+
table.add_row(
|
|
639
|
+
f"[dim]{time_str:8}[/dim]",
|
|
640
|
+
f"[dim]{index_str:4}[/dim]",
|
|
641
|
+
f"[green]Assistant:[/green]{meta_info}",
|
|
642
|
+
)
|
|
643
|
+
# 如果有内容,添加内容行
|
|
644
|
+
if line:
|
|
645
|
+
table.add_row("", "", line)
|
|
646
|
+
first_row_added = True
|
|
647
|
+
else:
|
|
648
|
+
# 续行只在内容列显示
|
|
649
|
+
table.add_row("", "", line)
|
|
650
|
+
|
|
651
|
+
# 如果没有文本内容,只显示助手消息头
|
|
652
|
+
if not first_row_added:
|
|
653
|
+
table.add_row(
|
|
654
|
+
f"[dim]{time_str:8}[/dim]",
|
|
655
|
+
f"[dim]{index_str:4}[/dim]",
|
|
656
|
+
f"[green]Assistant:[/green]{meta_info}",
|
|
657
|
+
)
|
|
658
|
+
|
|
659
|
+
# 添加工具调用
|
|
660
|
+
for tool_call in tool_calls:
|
|
661
|
+
args_str = ""
|
|
662
|
+
if tool_call.arguments:
|
|
663
|
+
try:
|
|
664
|
+
parsed_args = json.loads(tool_call.arguments) if isinstance(tool_call.arguments, str) else tool_call.arguments
|
|
665
|
+
args_str = f" {parsed_args}"
|
|
666
|
+
except (json.JSONDecodeError, TypeError):
|
|
667
|
+
args_str = f" {tool_call.arguments}"
|
|
668
|
+
|
|
669
|
+
args_display = truncate_content(args_str, max_content_length - len(tool_call.name) - 10)
|
|
670
|
+
table.add_row("", "", f"[magenta]Call:[/magenta] {tool_call.name}{args_display}")
|
|
671
|
+
|
|
672
|
+
# 添加工具结果
|
|
673
|
+
for tool_result in tool_results:
|
|
674
|
+
output = truncate_content(str(tool_result.output), max_content_length)
|
|
675
|
+
time_info = ""
|
|
676
|
+
if tool_result.execution_time_ms is not None:
|
|
677
|
+
time_info = f" [dim]({tool_result.execution_time_ms}ms)[/dim]"
|
|
678
|
+
|
|
679
|
+
table.add_row("", "", f"[cyan]Output:[/cyan]{time_info}")
|
|
680
|
+
lines = output.split("\n")
|
|
681
|
+
for line in lines:
|
|
682
|
+
table.add_row("", "", line)
|
|
683
|
+
|
|
684
|
+
console.print(table)
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
def _display_legacy_message_with_columns(
|
|
688
|
+
message: FlexibleRunnerMessage,
|
|
689
|
+
console: Console,
|
|
690
|
+
time_str: str,
|
|
691
|
+
index_str: str,
|
|
692
|
+
max_content_length: int,
|
|
693
|
+
truncate_content: Callable[[str, int], str],
|
|
694
|
+
) -> None:
|
|
695
|
+
"""使用列布局显示旧格式消息。"""
|
|
696
|
+
# 这里可以处理旧格式消息,暂时简单显示
|
|
697
|
+
try:
|
|
698
|
+
content = str(message.model_dump()) if hasattr(message, "model_dump") else str(message) # type: ignore[attr-defined]
|
|
699
|
+
except Exception:
|
|
700
|
+
content = str(message)
|
|
701
|
+
|
|
702
|
+
content = truncate_content(content, max_content_length)
|
|
703
|
+
|
|
704
|
+
# 创建表格来确保对齐
|
|
705
|
+
table = Table.grid(padding=0)
|
|
706
|
+
table.add_column(width=8, justify="left") # 时间列
|
|
707
|
+
table.add_column(width=4, justify="left") # 序号列
|
|
708
|
+
table.add_column(min_width=0) # 内容列
|
|
709
|
+
|
|
710
|
+
lines = content.split("\n")
|
|
711
|
+
for i, line in enumerate(lines):
|
|
712
|
+
if i == 0:
|
|
713
|
+
# 第一行显示完整信息
|
|
714
|
+
table.add_row(
|
|
715
|
+
f"[dim]{time_str:8}[/dim]",
|
|
716
|
+
f"[dim]{index_str:4}[/dim]",
|
|
717
|
+
f"[red]Legacy:[/red] {line}",
|
|
718
|
+
)
|
|
719
|
+
else:
|
|
720
|
+
# 续行只在内容列显示
|
|
721
|
+
table.add_row("", "", line)
|
|
722
|
+
|
|
723
|
+
console.print(table)
|
|
479
724
|
|
|
480
725
|
|
|
481
726
|
def _create_message_context(context_config: dict[str, FlexibleRunnerMessage | Console | int | bool | timezone | Callable[[str, int], str] | None]) -> MessageContext:
|
|
@@ -581,6 +826,8 @@ def _display_assistant_message_compact_v2(message: AgentAssistantMessage, contex
|
|
|
581
826
|
meta_info = ""
|
|
582
827
|
if message.meta:
|
|
583
828
|
meta_parts = []
|
|
829
|
+
if message.meta.model is not None:
|
|
830
|
+
meta_parts.append(f"Model:{message.meta.model}")
|
|
584
831
|
if message.meta.latency_ms is not None:
|
|
585
832
|
meta_parts.append(f"Latency:{message.meta.latency_ms}ms")
|
|
586
833
|
if message.meta.output_time_ms is not None:
|
|
@@ -656,7 +903,11 @@ def _display_dict_function_call_compact(message: dict, context: MessageContext)
|
|
|
656
903
|
def _display_dict_function_output_compact(message: dict, context: MessageContext) -> None:
|
|
657
904
|
"""显示字典类型的函数输出消息。"""
|
|
658
905
|
output = context.truncate_content(str(message.get("output", "")), context.max_content_length)
|
|
659
|
-
|
|
906
|
+
# Add execution time if available
|
|
907
|
+
time_info = ""
|
|
908
|
+
if message.get("execution_time_ms") is not None:
|
|
909
|
+
time_info = f" [dim]({message['execution_time_ms']}ms)[/dim]"
|
|
910
|
+
context.console.print(f"{context.timestamp_str}{context.index_str}[cyan]Output:[/cyan]{time_info}")
|
|
660
911
|
context.console.print(f"{output}")
|
|
661
912
|
|
|
662
913
|
|
|
@@ -676,6 +927,8 @@ def _display_dict_assistant_compact(message: dict, context: MessageContext) -> N
|
|
|
676
927
|
meta = message.get("meta")
|
|
677
928
|
if meta and isinstance(meta, dict):
|
|
678
929
|
meta_parts = []
|
|
930
|
+
if meta.get("model") is not None:
|
|
931
|
+
meta_parts.append(f"Model:{meta['model']}")
|
|
679
932
|
if meta.get("latency_ms") is not None:
|
|
680
933
|
meta_parts.append(f"Latency:{meta['latency_ms']}ms")
|
|
681
934
|
if meta.get("output_time_ms") is not None:
|
|
@@ -743,30 +996,34 @@ def _display_new_assistant_message_compact(message: NewAssistantMessage, context
|
|
|
743
996
|
elif item.type == "tool_call_result":
|
|
744
997
|
tool_results.append(item)
|
|
745
998
|
|
|
746
|
-
#
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
if message.meta.usage and message.meta.usage.input_tokens is not None and message.meta.usage.output_tokens is not None:
|
|
760
|
-
total_tokens = message.meta.usage.input_tokens + message.meta.usage.output_tokens
|
|
761
|
-
meta_parts.append(f"Tokens:↑{message.meta.usage.input_tokens}↓{message.meta.usage.output_tokens}={total_tokens}")
|
|
762
|
-
|
|
763
|
-
if meta_parts:
|
|
764
|
-
meta_info = f" [dim]({' | '.join(meta_parts)})[/dim]"
|
|
999
|
+
# Add meta data information (使用英文标签)
|
|
1000
|
+
meta_info = ""
|
|
1001
|
+
if message.meta:
|
|
1002
|
+
meta_parts = []
|
|
1003
|
+
if message.meta.model is not None:
|
|
1004
|
+
meta_parts.append(f"Model:{message.meta.model}")
|
|
1005
|
+
if message.meta.latency_ms is not None:
|
|
1006
|
+
meta_parts.append(f"Latency:{message.meta.latency_ms}ms")
|
|
1007
|
+
if message.meta.total_time_ms is not None:
|
|
1008
|
+
meta_parts.append(f"Output:{message.meta.total_time_ms}ms")
|
|
1009
|
+
if message.meta.usage and message.meta.usage.input_tokens is not None and message.meta.usage.output_tokens is not None:
|
|
1010
|
+
total_tokens = message.meta.usage.input_tokens + message.meta.usage.output_tokens
|
|
1011
|
+
meta_parts.append(f"Tokens:↑{message.meta.usage.input_tokens}↓{message.meta.usage.output_tokens}={total_tokens}")
|
|
765
1012
|
|
|
1013
|
+
if meta_parts:
|
|
1014
|
+
meta_info = f" [dim]({' | '.join(meta_parts)})[/dim]"
|
|
1015
|
+
|
|
1016
|
+
# Always show Assistant header if there's any content (text, tool calls, or results)
|
|
1017
|
+
if text_parts or tool_calls or tool_results:
|
|
766
1018
|
context.console.print(f"{context.timestamp_str}{context.index_str}[green]Assistant:[/green]{meta_info}")
|
|
767
|
-
context.console.print(f"{content}")
|
|
768
1019
|
|
|
769
|
-
|
|
1020
|
+
# Display text content if available
|
|
1021
|
+
if text_parts:
|
|
1022
|
+
content = " ".join(text_parts)
|
|
1023
|
+
content = context.truncate_content(content, context.max_content_length)
|
|
1024
|
+
context.console.print(f"{content}")
|
|
1025
|
+
|
|
1026
|
+
# Display tool calls with proper indentation
|
|
770
1027
|
for tool_call in tool_calls:
|
|
771
1028
|
args_str = ""
|
|
772
1029
|
if tool_call.arguments:
|
|
@@ -777,11 +1034,17 @@ def _display_new_assistant_message_compact(message: NewAssistantMessage, context
|
|
|
777
1034
|
args_str = f" {tool_call.arguments}"
|
|
778
1035
|
|
|
779
1036
|
args_display = context.truncate_content(args_str, context.max_content_length - len(tool_call.name) - 10)
|
|
780
|
-
|
|
781
|
-
context.console.print(f"{tool_call.name}{args_display}")
|
|
1037
|
+
# Always use indented format for better hierarchy
|
|
1038
|
+
context.console.print(f" [magenta]Call:[/magenta] {tool_call.name}{args_display}")
|
|
782
1039
|
|
|
783
|
-
# Display tool results
|
|
1040
|
+
# Display tool results with proper indentation
|
|
784
1041
|
for tool_result in tool_results:
|
|
785
1042
|
output = context.truncate_content(str(tool_result.output), context.max_content_length)
|
|
786
|
-
|
|
787
|
-
|
|
1043
|
+
# Add execution time if available
|
|
1044
|
+
time_info = ""
|
|
1045
|
+
if tool_result.execution_time_ms is not None:
|
|
1046
|
+
time_info = f" [dim]({tool_result.execution_time_ms}ms)[/dim]"
|
|
1047
|
+
|
|
1048
|
+
# Always use indented format for better hierarchy
|
|
1049
|
+
context.console.print(f" [cyan]Output:[/cyan]{time_info}")
|
|
1050
|
+
context.console.print(f" {output}")
|
lite_agent/client.py
CHANGED
|
@@ -37,7 +37,7 @@ def parse_reasoning_config(reasoning: ReasoningConfig) -> tuple[ReasoningEffort
|
|
|
37
37
|
Args:
|
|
38
38
|
reasoning: 统一的推理配置
|
|
39
39
|
- str: "minimal", "low", "medium", "high" -> reasoning_effort
|
|
40
|
-
- dict: {"
|
|
40
|
+
- dict: {"effort": "minimal"} -> reasoning_effort, 其他格式 -> thinking_config
|
|
41
41
|
- bool: True -> "medium", False -> None
|
|
42
42
|
- None: 不启用推理
|
|
43
43
|
|
|
@@ -46,19 +46,26 @@ def parse_reasoning_config(reasoning: ReasoningConfig) -> tuple[ReasoningEffort
|
|
|
46
46
|
"""
|
|
47
47
|
if reasoning is None:
|
|
48
48
|
return None, None
|
|
49
|
+
|
|
49
50
|
if isinstance(reasoning, str):
|
|
50
51
|
# 字符串类型,使用 reasoning_effort
|
|
51
52
|
# 确保字符串是有效的 ReasoningEffort 值
|
|
52
53
|
if reasoning in ("minimal", "low", "medium", "high"):
|
|
53
54
|
return reasoning, None # type: ignore[return-value]
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
elif isinstance(reasoning, dict):
|
|
56
|
+
# 检查是否为 {"effort": "value"} 格式
|
|
57
|
+
if "effort" in reasoning and len(reasoning) == 1:
|
|
58
|
+
effort = reasoning["effort"]
|
|
59
|
+
if isinstance(effort, str) and effort in ("minimal", "low", "medium", "high"):
|
|
60
|
+
return effort, None # type: ignore[return-value]
|
|
61
|
+
else:
|
|
62
|
+
# 其他字典格式,作为 thinking_config
|
|
63
|
+
return None, reasoning
|
|
64
|
+
elif isinstance(reasoning, bool):
|
|
59
65
|
# 布尔类型,True 使用默认的 medium,False 不启用
|
|
60
|
-
return "medium" if reasoning else None, None
|
|
61
|
-
|
|
66
|
+
return ("medium", None) if reasoning else (None, None)
|
|
67
|
+
|
|
68
|
+
# 其他类型或无效格式,默认不启用
|
|
62
69
|
return None, None
|
|
63
70
|
|
|
64
71
|
|
lite_agent/message_transfers.py
CHANGED
|
@@ -5,6 +5,8 @@ This module provides common message transfer functions that can be used
|
|
|
5
5
|
with agents to preprocess messages before sending them to the API.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
import json
|
|
9
|
+
|
|
8
10
|
from lite_agent.types import NewUserMessage, RunnerMessages, UserTextContent
|
|
9
11
|
|
|
10
12
|
|
|
@@ -67,8 +69,25 @@ def _process_message_to_xml(message: dict | object) -> list[str]:
|
|
|
67
69
|
|
|
68
70
|
# Handle new message format where content is a list
|
|
69
71
|
if isinstance(content, list):
|
|
70
|
-
#
|
|
71
|
-
text_parts = [
|
|
72
|
+
# Process each content item
|
|
73
|
+
text_parts = []
|
|
74
|
+
for item in content:
|
|
75
|
+
if hasattr(item, "type"):
|
|
76
|
+
if item.type == "text":
|
|
77
|
+
text_parts.append(item.text)
|
|
78
|
+
elif item.type == "tool_call":
|
|
79
|
+
# Handle tool call content
|
|
80
|
+
arguments = item.arguments
|
|
81
|
+
if isinstance(arguments, dict):
|
|
82
|
+
arguments = json.dumps(arguments, ensure_ascii=False)
|
|
83
|
+
xml_lines.append(f" <function_call name='{item.name}' arguments='{arguments}' />")
|
|
84
|
+
elif item.type == "tool_call_result":
|
|
85
|
+
# Handle tool call result content
|
|
86
|
+
xml_lines.append(f" <function_result call_id='{item.call_id}'>{item.output}</function_result>")
|
|
87
|
+
elif hasattr(item, "text"):
|
|
88
|
+
text_parts.append(item.text)
|
|
89
|
+
|
|
90
|
+
# Add text content as message if any
|
|
72
91
|
content_text = " ".join(text_parts)
|
|
73
92
|
if content_text:
|
|
74
93
|
xml_lines.append(f" <message role='{role}'>{content_text}</message>")
|
|
@@ -119,8 +119,10 @@ class ResponseEventProcessor:
|
|
|
119
119
|
# Extract model information from event
|
|
120
120
|
model_name = getattr(event, "model", None)
|
|
121
121
|
# Debug: check if event has model info in different location
|
|
122
|
-
if hasattr(event, "response")
|
|
123
|
-
|
|
122
|
+
if hasattr(event, "response"):
|
|
123
|
+
response = getattr(event, "response", None)
|
|
124
|
+
if response and hasattr(response, "model"):
|
|
125
|
+
model_name = getattr(response, "model", None)
|
|
124
126
|
# Create usage information
|
|
125
127
|
usage = MessageUsage(
|
|
126
128
|
input_tokens=self._usage_data.get("input_tokens"),
|