lite-agent 0.11.0__py3-none-any.whl → 0.12.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 CHANGED
@@ -41,6 +41,7 @@ class Agent:
41
41
  message_transfer: Callable[[RunnerMessages], RunnerMessages] | None = None,
42
42
  completion_condition: str = "stop",
43
43
  stop_before_tools: list[str] | list[Callable] | None = None,
44
+ termination_tools: list[str] | list[Callable] | None = None,
44
45
  ) -> None:
45
46
  self.name = name
46
47
  self.instructions = instructions
@@ -58,6 +59,20 @@ class Agent:
58
59
  else:
59
60
  self.stop_before_functions = set()
60
61
 
62
+ # Convert termination_tools to function names
63
+ if termination_tools:
64
+ self.termination_tools = set()
65
+ for func in termination_tools:
66
+ if isinstance(func, str):
67
+ self.termination_tools.add(func)
68
+ elif callable(func):
69
+ self.termination_tools.add(func.__name__)
70
+ else:
71
+ msg = f"termination_tools must contain strings or callables, got {type(func)}"
72
+ raise TypeError(msg)
73
+ else:
74
+ self.termination_tools = set()
75
+
61
76
  if isinstance(model, BaseLLMClient):
62
77
  # If model is a BaseLLMClient instance, use it directly
63
78
  self.client = model
lite_agent/context.py ADDED
@@ -0,0 +1,37 @@
1
+ """Context utilities for injecting history messages into tool calls."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Generic, TypeVar
6
+
7
+ from pydantic import BaseModel
8
+
9
+ T = TypeVar("T")
10
+
11
+
12
+ class HistoryContext(BaseModel, Generic[T]):
13
+ """包含历史消息的上下文容器
14
+
15
+ 这个类会自动被 Runner 用来包装用户的 context,确保工具函数能够访问历史消息。
16
+
17
+ Attributes:
18
+ history_messages: 工具调用前的所有历史消息
19
+ data: 用户自定义的上下文数据(可选)
20
+
21
+ Examples:
22
+ >>> # 只需要历史消息的工具
23
+ >>> async def count_messages(ctx: Context[HistoryContext[None]]) -> str:
24
+ ... return f"总共 {len(ctx.value.history_messages)} 条消息"
25
+
26
+ >>> # 需要历史消息和用户数据的工具
27
+ >>> class UserData(BaseModel):
28
+ ... user_id: str
29
+ >>>
30
+ >>> async def analyze_user(ctx: Context[HistoryContext[UserData]]) -> str:
31
+ ... messages = ctx.value.history_messages
32
+ ... user_id = ctx.value.data.user_id
33
+ ... return f"用户 {user_id} 有 {len(messages)} 条消息"
34
+ """
35
+
36
+ history_messages: list[Any]
37
+ data: T | None = None
lite_agent/runner.py CHANGED
@@ -5,8 +5,11 @@ from os import PathLike
5
5
  from pathlib import Path
6
6
  from typing import Any, Literal, cast
7
7
 
8
+ from funcall import Context
9
+
8
10
  from lite_agent.agent import Agent
9
11
  from lite_agent.constants import CompletionMode, StreamIncludes, ToolName
12
+ from lite_agent.context import HistoryContext
10
13
  from lite_agent.loggers import logger
11
14
  from lite_agent.types import (
12
15
  AgentChunk,
@@ -181,6 +184,24 @@ class Runner:
181
184
  )
182
185
  return # Stop processing other tool calls after transfer
183
186
 
187
+ # Auto-inject history messages into context
188
+ if context is not None and not isinstance(context, Context):
189
+ # If user provided a plain object, wrap it in Context first
190
+ context = Context(context)
191
+
192
+ if isinstance(context, Context):
193
+ # Extract original value and wrap in HistoryContext
194
+ original_value = context.value
195
+ wrapped = HistoryContext(
196
+ history_messages=self.messages.copy(),
197
+ data=original_value,
198
+ )
199
+ context = Context(wrapped)
200
+ else:
201
+ # No context provided, create HistoryContext with only history messages
202
+ wrapped = HistoryContext(history_messages=self.messages.copy())
203
+ context = Context(wrapped)
204
+
184
205
  async for tool_call_chunk in self.agent.handle_tool_calls(tool_calls, context=context):
185
206
  # if tool_call_chunk.type == "function_call" and tool_call_chunk.type in includes:
186
207
  # yield tool_call_chunk
@@ -270,12 +291,18 @@ class Runner:
270
291
 
271
292
  def is_finish() -> bool:
272
293
  if completion_condition == CompletionMode.CALL:
273
- # Check if wait_for_user was called in the last assistant message
294
+ # Check if any termination tool was called in the last assistant message
274
295
  if self.messages and isinstance(self.messages[-1], NewAssistantMessage):
275
296
  last_message = self.messages[-1]
276
297
  for content_item in last_message.content:
277
- if isinstance(content_item, AssistantToolCallResult) and self._get_tool_call_name_by_id(content_item.call_id) == ToolName.WAIT_FOR_USER:
278
- return True
298
+ if isinstance(content_item, AssistantToolCallResult):
299
+ tool_name = self._get_tool_call_name_by_id(content_item.call_id)
300
+ # Check custom termination tools first, then default wait_for_user
301
+ if hasattr(self.agent, "termination_tools") and self.agent.termination_tools:
302
+ if tool_name in self.agent.termination_tools:
303
+ return True
304
+ elif tool_name == ToolName.WAIT_FOR_USER:
305
+ return True
279
306
  return False
280
307
  return finish_reason == CompletionMode.STOP
281
308
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lite-agent
3
- Version: 0.11.0
3
+ Version: 0.12.0
4
4
  Summary: A lightweight, extensible framework for building AI agent.
5
5
  Author-email: Jianqi Pan <jannchie@gmail.com>
6
6
  License: MIT
@@ -1,12 +1,13 @@
1
1
  lite_agent/__init__.py,sha256=Swuefee0etSiaDnn30K2hBNV9UI3hIValW3A-pRE7e0,338
2
- lite_agent/agent.py,sha256=UXmQY8vhi_2DIPcWkji0B_pCGlBvZLfx6YoNaUJO6Wc,18028
2
+ lite_agent/agent.py,sha256=gMn-NeQxl0298uKmlJph_c9WP3QN8WeKMEEDuv5RdVw,18681
3
3
  lite_agent/chat_display.py,sha256=6gPgutMj7hCUOH6QBcC2f4Bhc93Gdq4vBa_1y6QKt2g,40793
4
4
  lite_agent/client.py,sha256=-9BXLhAp3bGJsdKJ02lLpPJeHQKyHKQwhebZ6WCYh_k,9988
5
5
  lite_agent/constants.py,sha256=_xIDdQwaJrWk8N_62o-KYEo3jj1waPJ0ZOd3hHybKNo,718
6
+ lite_agent/context.py,sha256=qnqj4JVYL0pkle1YptwM_CXJUWTeLaYtI1_MGtJYaHI,1225
6
7
  lite_agent/loggers.py,sha256=XkNkdqwD_nQGfhQJ-bBWT7koci_mMkNw3aBpyMhOICw,57
7
8
  lite_agent/message_transfers.py,sha256=N9ViK7Gxqqa1sd3V_hkNuQ9fUipg7M95l-sVBBG2Id4,5357
8
9
  lite_agent/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- lite_agent/runner.py,sha256=qcKS12JRnzwdBDzOlxn8TNJU9nf4Dz2ZzLvD_7yUt2s,43819
10
+ lite_agent/runner.py,sha256=p-Dw4RNYfRnIwnbt8oJv8e4qI84X7OUWLxgyITMnGe8,45090
10
11
  lite_agent/processors/__init__.py,sha256=ybpAzpMBIE9v5I24wIBZRXeaOaPNTmoKH13aofgNI6Q,234
11
12
  lite_agent/processors/completion_event_processor.py,sha256=zoWvs8dfrIkCSITGtS-4Hpve3WFCA0UUsMvYifL2fw0,13010
12
13
  lite_agent/processors/response_event_processor.py,sha256=Jr3cj1ItJ8aq9UBhEEjDwWDnPNOZ2ZXjWJ3-g4ghkhM,8514
@@ -29,6 +30,6 @@ lite_agent/utils/message_builder.py,sha256=J-yycL9pXSO9MbgC5NEGqvoP1LC2Nxe9r2YRW
29
30
  lite_agent/utils/message_converter.py,sha256=5HmNncTl71TD2M_6Ezz1Tnfavzna8DQYb4-D47Du7mA,9165
30
31
  lite_agent/utils/message_state_manager.py,sha256=rFUyqyd_7NdJRtyqsAWGcfwrDIlD6gK2dBDSDx1eGBs,5766
31
32
  lite_agent/utils/metrics.py,sha256=RzOEhCWxbLmmIEkzaxOJ6tAdthI8dv2Foc98Lq8afOQ,1915
32
- lite_agent-0.11.0.dist-info/METADATA,sha256=WRwZ5xKujQt0pJdWvIBvhYQsnedrsW9WUqOseXQiVhU,3538
33
- lite_agent-0.11.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
34
- lite_agent-0.11.0.dist-info/RECORD,,
33
+ lite_agent-0.12.0.dist-info/METADATA,sha256=CvsMgd3DNYoZTvD0bTirNibch5S9eH8K-hjwWvEjFZo,3538
34
+ lite_agent-0.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
35
+ lite_agent-0.12.0.dist-info/RECORD,,