agstack 1.17.1__tar.gz → 1.18.0__tar.gz

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.
Files changed (76) hide show
  1. {agstack-1.17.1 → agstack-1.18.0}/PKG-INFO +1 -1
  2. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/agent.py +10 -0
  3. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/context.py +6 -0
  4. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/nodes/base.py +5 -0
  5. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/tool.py +26 -4
  6. {agstack-1.17.1 → agstack-1.18.0}/agstack.egg-info/PKG-INFO +1 -1
  7. {agstack-1.17.1 → agstack-1.18.0}/pyproject.toml +1 -1
  8. {agstack-1.17.1 → agstack-1.18.0}/LICENSE +0 -0
  9. {agstack-1.17.1 → agstack-1.18.0}/README.md +0 -0
  10. {agstack-1.17.1 → agstack-1.18.0}/agstack/__init__.py +0 -0
  11. {agstack-1.17.1 → agstack-1.18.0}/agstack/cache/__init__.py +0 -0
  12. {agstack-1.17.1 → agstack-1.18.0}/agstack/cache/base.py +0 -0
  13. {agstack-1.17.1 → agstack-1.18.0}/agstack/cache/memory.py +0 -0
  14. {agstack-1.17.1 → agstack-1.18.0}/agstack/cache/redis.py +0 -0
  15. {agstack-1.17.1 → agstack-1.18.0}/agstack/config/__init__.py +0 -0
  16. {agstack-1.17.1 → agstack-1.18.0}/agstack/config/logger.py +0 -0
  17. {agstack-1.17.1 → agstack-1.18.0}/agstack/config/manager.py +0 -0
  18. {agstack-1.17.1 → agstack-1.18.0}/agstack/config/types.py +0 -0
  19. {agstack-1.17.1 → agstack-1.18.0}/agstack/contexts.py +0 -0
  20. {agstack-1.17.1 → agstack-1.18.0}/agstack/decorators.py +0 -0
  21. {agstack-1.17.1 → agstack-1.18.0}/agstack/events.py +0 -0
  22. {agstack-1.17.1 → agstack-1.18.0}/agstack/exceptions.py +0 -0
  23. {agstack-1.17.1 → agstack-1.18.0}/agstack/fastapi/__init__.py +0 -0
  24. {agstack-1.17.1 → agstack-1.18.0}/agstack/fastapi/exception.py +0 -0
  25. {agstack-1.17.1 → agstack-1.18.0}/agstack/fastapi/middleware.py +0 -0
  26. {agstack-1.17.1 → agstack-1.18.0}/agstack/fastapi/offline.py +0 -0
  27. {agstack-1.17.1 → agstack-1.18.0}/agstack/fastapi/sse.py +0 -0
  28. {agstack-1.17.1 → agstack-1.18.0}/agstack/infra/db/__init__.py +0 -0
  29. {agstack-1.17.1 → agstack-1.18.0}/agstack/infra/es/__init__.py +0 -0
  30. {agstack-1.17.1 → agstack-1.18.0}/agstack/infra/kg/__init__.py +0 -0
  31. {agstack-1.17.1 → agstack-1.18.0}/agstack/infra/mq/__init__.py +0 -0
  32. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/__init__.py +0 -0
  33. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/client.py +0 -0
  34. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/__init__.py +0 -0
  35. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/event.py +0 -0
  36. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/exceptions.py +0 -0
  37. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/factory.py +0 -0
  38. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/flow.py +0 -0
  39. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/loader.py +0 -0
  40. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/nodes/__init__.py +0 -0
  41. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/nodes/agent_node.py +0 -0
  42. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/nodes/detect_node.py +0 -0
  43. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/nodes/echo_node.py +0 -0
  44. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/nodes/llm_chat_node.py +0 -0
  45. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/nodes/llm_embed_node.py +0 -0
  46. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/nodes/llm_rerank_node.py +0 -0
  47. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/nodes/python_node.py +0 -0
  48. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/nodes/subflow_node.py +0 -0
  49. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/nodes/switch_node.py +0 -0
  50. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/nodes/tool_node.py +0 -0
  51. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/records.py +0 -0
  52. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/registry.py +0 -0
  53. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/sandbox.py +0 -0
  54. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/flow/state.py +0 -0
  55. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/prompts.py +0 -0
  56. {agstack-1.17.1 → agstack-1.18.0}/agstack/llm/token.py +0 -0
  57. {agstack-1.17.1 → agstack-1.18.0}/agstack/messagebus/__init__.py +0 -0
  58. {agstack-1.17.1 → agstack-1.18.0}/agstack/messagebus/base.py +0 -0
  59. {agstack-1.17.1 → agstack-1.18.0}/agstack/messagebus/memory.py +0 -0
  60. {agstack-1.17.1 → agstack-1.18.0}/agstack/messagebus/redis.py +0 -0
  61. {agstack-1.17.1 → agstack-1.18.0}/agstack/schema.py +0 -0
  62. {agstack-1.17.1 → agstack-1.18.0}/agstack/security/__init__.py +0 -0
  63. {agstack-1.17.1 → agstack-1.18.0}/agstack/security/casbin.py +0 -0
  64. {agstack-1.17.1 → agstack-1.18.0}/agstack/security/crypt.py +0 -0
  65. {agstack-1.17.1 → agstack-1.18.0}/agstack/status.py +0 -0
  66. {agstack-1.17.1 → agstack-1.18.0}/agstack.egg-info/SOURCES.txt +0 -0
  67. {agstack-1.17.1 → agstack-1.18.0}/agstack.egg-info/dependency_links.txt +0 -0
  68. {agstack-1.17.1 → agstack-1.18.0}/agstack.egg-info/requires.txt +0 -0
  69. {agstack-1.17.1 → agstack-1.18.0}/agstack.egg-info/top_level.txt +0 -0
  70. {agstack-1.17.1 → agstack-1.18.0}/setup.cfg +0 -0
  71. {agstack-1.17.1 → agstack-1.18.0}/tests/test_cache_memory.py +0 -0
  72. {agstack-1.17.1 → agstack-1.18.0}/tests/test_cache_redis.py +0 -0
  73. {agstack-1.17.1 → agstack-1.18.0}/tests/test_flow_io.py +0 -0
  74. {agstack-1.17.1 → agstack-1.18.0}/tests/test_flow_switch_subflow.py +0 -0
  75. {agstack-1.17.1 → agstack-1.18.0}/tests/test_messagebus_memory.py +0 -0
  76. {agstack-1.17.1 → agstack-1.18.0}/tests/test_messagebus_redis.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agstack
3
- Version: 1.17.1
3
+ Version: 1.18.0
4
4
  Summary: Production-ready toolkit for building FastAPI and LLM applications
5
5
  Author-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
6
6
  Maintainer-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
@@ -88,6 +88,10 @@ class Agent:
88
88
  ) -> AsyncIterator[dict[str, Any]]:
89
89
  """流式执行 Agent,输出 AG-UI 标准事件"""
90
90
 
91
+ # 注入 agent_call_id 供 tool 审计关联
92
+ agent_call_id = str(uuid4())
93
+ context.set_variable("_agent_call_id", agent_call_id)
94
+
91
95
  # 输入来源:优先 inputs 参数,回退到 context.variables
92
96
  user_input = ""
93
97
  if inputs:
@@ -230,6 +234,7 @@ class Agent:
230
234
  context.set_output(self.name, {"result": assistant_content})
231
235
  # AG-UI: TEXT_MESSAGE_END
232
236
  yield event.text_message_end(message_id=msg_id)
237
+ context.set_variable("_agent_call_id", None)
233
238
  return
234
239
 
235
240
  # 执行工具调用
@@ -266,5 +271,10 @@ class Agent:
266
271
  # AG-UI: TOOL_CALL_RESULT
267
272
  yield event.tool_call_result(tool_call_id=tool_call["id"], content=result_content)
268
273
 
274
+ # 可观测性:yield tool 执行记录
275
+ for record in context.pop_execution_records():
276
+ record["tool_call_id"] = tool_call["id"]
277
+ yield event.custom(name="tool_execution", value=record)
278
+
269
279
  # 更新消息列表,继续下一轮
270
280
  messages = [self.get_system_message()] + context.history + context.get_messages(self.name)
@@ -151,3 +151,9 @@ class FlowContext:
151
151
  if task_id is None:
152
152
  return self.execution_records
153
153
  return [r for r in self.execution_records if r.get("task_id") == task_id]
154
+
155
+ def pop_execution_records(self) -> list[dict[str, Any]]:
156
+ """取出并清空待发射的执行记录"""
157
+ records = self.execution_records
158
+ self.execution_records = []
159
+ return records
@@ -48,4 +48,9 @@ class NodeHandler:
48
48
  yield event.step_started(step_name=step_name)
49
49
  result = await self.execute(node, context)
50
50
  context.set_output(node_id, result)
51
+
52
+ # 可观测性:drain tool 执行记录
53
+ for record in context.pop_execution_records():
54
+ yield event.custom(name="tool_execution", value=record)
55
+
51
56
  yield event.step_finished(step_name=step_name)
@@ -2,7 +2,9 @@
2
2
 
3
3
  """工具定义和执行"""
4
4
 
5
+ import json
5
6
  import logging
7
+ import time
6
8
  from dataclasses import dataclass
7
9
  from typing import TYPE_CHECKING, Any, Callable
8
10
 
@@ -54,18 +56,38 @@ class Tool:
54
56
  self.echo = echo
55
57
 
56
58
  async def execute_async(self, context: "FlowContext", inputs: dict[str, Any] | None = None) -> ToolResult:
57
- """异步执行工具"""
59
+ """异步执行工具(包含计时和可观测性记录)"""
60
+ args = inputs or {}
61
+ _t0 = time.perf_counter()
62
+ result = await self._execute(context, args)
63
+ _duration_ms = int((time.perf_counter() - _t0) * 1000)
64
+
65
+ result_content = json.dumps(result.result) if result.success else json.dumps({"error": result.error})
66
+ context.execution_records.append({
67
+ "agent_call_id": context.get_variable("_agent_call_id"),
68
+ "tool_name": self.name,
69
+ "tool_args": args,
70
+ "success": result.success,
71
+ "result": result_content,
72
+ "error": result.error,
73
+ "duration_ms": _duration_ms,
74
+ })
75
+
76
+ return result
77
+
78
+ async def _execute(self, context: "FlowContext", inputs: dict[str, Any]) -> ToolResult:
79
+ """实际执行逻辑,子类应覆写此方法"""
58
80
  try:
59
- result = self.function(context, inputs or {})
81
+ result = self.function(context, inputs)
60
82
  if hasattr(result, "__await__"):
61
83
  result = await result
62
84
 
63
- return ToolResult(name=self.name, arguments=inputs or {}, result=result, success=True)
85
+ return ToolResult(name=self.name, arguments=inputs, result=result, success=True)
64
86
  except Exception as e:
65
87
  logger.warning("Tool %s failed: %s", self.name, e, exc_info=True)
66
88
  return ToolResult(
67
89
  name=self.name,
68
- arguments=inputs or {},
90
+ arguments=inputs,
69
91
  result={},
70
92
  success=False,
71
93
  error=str(e),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agstack
3
- Version: 1.17.1
3
+ Version: 1.18.0
4
4
  Summary: Production-ready toolkit for building FastAPI and LLM applications
5
5
  Author-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
6
6
  Maintainer-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agstack"
3
- version = "1.17.1"
3
+ version = "1.18.0"
4
4
  description = "Production-ready toolkit for building FastAPI and LLM applications"
5
5
  readme = "README.md"
6
6
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes