agstack 1.22.0__tar.gz → 1.22.1__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.
- {agstack-1.22.0 → agstack-1.22.1}/PKG-INFO +1 -1
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/event.py +4 -4
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/flow.py +12 -8
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/nodes/agent_node.py +4 -2
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/nodes/base.py +4 -2
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/nodes/echo_node.py +3 -2
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/nodes/llm_chat_node.py +6 -4
- {agstack-1.22.0 → agstack-1.22.1}/agstack.egg-info/PKG-INFO +1 -1
- {agstack-1.22.0 → agstack-1.22.1}/pyproject.toml +1 -1
- {agstack-1.22.0 → agstack-1.22.1}/LICENSE +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/README.md +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/__init__.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/cache/__init__.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/cache/base.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/cache/memory.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/cache/redis.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/config/__init__.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/config/logger.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/config/manager.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/config/types.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/contexts.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/decorators.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/events.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/exceptions.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/fastapi/__init__.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/fastapi/exception.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/fastapi/middleware.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/fastapi/offline.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/fastapi/sse.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/infra/db/__init__.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/infra/es/__init__.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/infra/kg/__init__.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/infra/mq/__init__.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/__init__.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/client.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/__init__.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/agent.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/context.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/exceptions.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/factory.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/loader.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/nodes/__init__.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/nodes/detect_node.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/nodes/llm_embed_node.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/nodes/llm_rerank_node.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/nodes/python_node.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/nodes/subflow_node.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/nodes/switch_node.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/nodes/tool_node.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/records.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/registry.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/sandbox.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/state.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/tool.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/flow/trace.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/prompts.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/llm/token.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/messagebus/__init__.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/messagebus/base.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/messagebus/memory.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/messagebus/redis.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/schema.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/security/__init__.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/security/casbin.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/security/crypt.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack/status.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack.egg-info/SOURCES.txt +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack.egg-info/dependency_links.txt +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack.egg-info/requires.txt +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/agstack.egg-info/top_level.txt +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/setup.cfg +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/tests/test_cache_memory.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/tests/test_cache_redis.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/tests/test_flow_io.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/tests/test_flow_switch_subflow.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/tests/test_messagebus_memory.py +0 -0
- {agstack-1.22.0 → agstack-1.22.1}/tests/test_messagebus_redis.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agstack
|
|
3
|
-
Version: 1.22.
|
|
3
|
+
Version: 1.22.1
|
|
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>
|
|
@@ -97,12 +97,12 @@ def run_error(*, message: str, code: str | None = None) -> dict[str, Any]:
|
|
|
97
97
|
# ── Step ──
|
|
98
98
|
|
|
99
99
|
|
|
100
|
-
def step_started(*, step_name: str) -> dict[str, Any]:
|
|
101
|
-
return _ev(EventType.STEP_STARTED, step_name=step_name)
|
|
100
|
+
def step_started(*, step_name: str, step_id: str | None = None) -> dict[str, Any]:
|
|
101
|
+
return _ev(EventType.STEP_STARTED, step_name=step_name, step_id=step_id or str(uuid4()))
|
|
102
102
|
|
|
103
103
|
|
|
104
|
-
def step_finished(*, step_name: str) -> dict[str, Any]:
|
|
105
|
-
return _ev(EventType.STEP_FINISHED, step_name=step_name)
|
|
104
|
+
def step_finished(*, step_name: str, step_id: str) -> dict[str, Any]:
|
|
105
|
+
return _ev(EventType.STEP_FINISHED, step_name=step_name, step_id=step_id)
|
|
106
106
|
|
|
107
107
|
|
|
108
108
|
# ── State ──
|
|
@@ -370,7 +370,8 @@ class Flow:
|
|
|
370
370
|
async def stream(self, context: "FlowContext") -> AsyncIterator[dict[str, Any]]:
|
|
371
371
|
"""流式执行 Flow(输出 AG-UI 标准事件)"""
|
|
372
372
|
context.trace.started_at = time.time()
|
|
373
|
-
|
|
373
|
+
flow_sid = str(uuid4())
|
|
374
|
+
yield event.step_started(step_name=f"flow:{self.name}", step_id=flow_sid)
|
|
374
375
|
|
|
375
376
|
try:
|
|
376
377
|
if not self.edges:
|
|
@@ -386,7 +387,7 @@ class Flow:
|
|
|
386
387
|
context.trace.finished_at = time.time()
|
|
387
388
|
context.trace.total_usage = context.usage
|
|
388
389
|
|
|
389
|
-
yield event.step_finished(step_name=f"flow:{self.name}")
|
|
390
|
+
yield event.step_finished(step_name=f"flow:{self.name}", step_id=flow_sid)
|
|
390
391
|
|
|
391
392
|
async def _stream_sequential(self, context: "FlowContext") -> AsyncIterator[dict[str, Any]]:
|
|
392
393
|
"""顺序流式执行"""
|
|
@@ -437,7 +438,8 @@ class Flow:
|
|
|
437
438
|
context.trace.record_node_start(current_node_id, "message", inputs=msg_config)
|
|
438
439
|
|
|
439
440
|
# message 节点增加 STEP 事件
|
|
440
|
-
|
|
441
|
+
msg_sid = str(uuid4())
|
|
442
|
+
step_evt = event.step_started(step_name=f"message:{current_node_id}", step_id=msg_sid)
|
|
441
443
|
step_evt["_node_id"] = current_node_id
|
|
442
444
|
step_evt["_label"] = msg_config.get("label")
|
|
443
445
|
step_evt["_echo"] = msg_config.get("echo", True)
|
|
@@ -454,7 +456,7 @@ class Flow:
|
|
|
454
456
|
text = template.format_map(_SafeFormatDict(context.variables))
|
|
455
457
|
context.set_output(current_node_id, {"result": text})
|
|
456
458
|
|
|
457
|
-
fin_evt = event.step_finished(step_name=f"message:{current_node_id}")
|
|
459
|
+
fin_evt = event.step_finished(step_name=f"message:{current_node_id}", step_id=msg_sid)
|
|
458
460
|
fin_evt["_node_id"] = current_node_id
|
|
459
461
|
fin_evt["_label"] = msg_config.get("label")
|
|
460
462
|
fin_evt["_echo"] = msg_config.get("echo", True)
|
|
@@ -469,7 +471,8 @@ class Flow:
|
|
|
469
471
|
|
|
470
472
|
context.trace.record_node_start(current_node_id, "parallel", inputs=config)
|
|
471
473
|
|
|
472
|
-
|
|
474
|
+
parallel_sid = str(uuid4())
|
|
475
|
+
step_evt = event.step_started(step_name=f"parallel:{current_node_id}", step_id=parallel_sid)
|
|
473
476
|
step_evt["_node_id"] = current_node_id
|
|
474
477
|
step_evt["_label"] = None
|
|
475
478
|
step_evt["_echo"] = False
|
|
@@ -510,7 +513,7 @@ class Flow:
|
|
|
510
513
|
merged.update(branch_result)
|
|
511
514
|
context.set_output(current_node_id, merged)
|
|
512
515
|
|
|
513
|
-
fin_evt = event.step_finished(step_name=f"parallel:{current_node_id}")
|
|
516
|
+
fin_evt = event.step_finished(step_name=f"parallel:{current_node_id}", step_id=parallel_sid)
|
|
514
517
|
fin_evt["_node_id"] = current_node_id
|
|
515
518
|
fin_evt["_label"] = None
|
|
516
519
|
fin_evt["_echo"] = False
|
|
@@ -533,7 +536,8 @@ class Flow:
|
|
|
533
536
|
|
|
534
537
|
context.trace.record_node_start(current_node_id, "iteration", inputs=config)
|
|
535
538
|
|
|
536
|
-
|
|
539
|
+
iter_sid = str(uuid4())
|
|
540
|
+
step_evt = event.step_started(step_name=f"iteration:{current_node_id}", step_id=iter_sid)
|
|
537
541
|
step_evt["_node_id"] = current_node_id
|
|
538
542
|
step_evt["_label"] = None
|
|
539
543
|
step_evt["_echo"] = False
|
|
@@ -574,7 +578,7 @@ class Flow:
|
|
|
574
578
|
iteration_output = {"results": results}
|
|
575
579
|
context.set_output(current_node_id, iteration_output)
|
|
576
580
|
|
|
577
|
-
fin_evt = event.step_finished(step_name=f"iteration:{current_node_id}")
|
|
581
|
+
fin_evt = event.step_finished(step_name=f"iteration:{current_node_id}", step_id=iter_sid)
|
|
578
582
|
fin_evt["_node_id"] = current_node_id
|
|
579
583
|
fin_evt["_label"] = None
|
|
580
584
|
fin_evt["_echo"] = False
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"""Agent 节点处理器 — 从 flow.py 提取"""
|
|
4
4
|
|
|
5
5
|
from typing import TYPE_CHECKING, Any, AsyncIterator
|
|
6
|
+
from uuid import uuid4
|
|
6
7
|
|
|
7
8
|
from .. import event
|
|
8
9
|
from ..exceptions import FlowError
|
|
@@ -46,8 +47,9 @@ class AgentNodeHandler(NodeHandler):
|
|
|
46
47
|
async def stream(self, node: dict, context: "FlowContext", node_id: str) -> AsyncIterator[dict[str, Any]]:
|
|
47
48
|
config = node.get("config", {})
|
|
48
49
|
step_name = self.get_step_name(node, node_id)
|
|
50
|
+
sid = str(uuid4())
|
|
49
51
|
|
|
50
|
-
yield event.step_started(step_name=step_name)
|
|
52
|
+
yield event.step_started(step_name=step_name, step_id=sid)
|
|
51
53
|
resolved = self.resolve_inputs(config, context)
|
|
52
54
|
ag = self._create_agent(config, context)
|
|
53
55
|
async for evt in ag.stream(context, inputs=resolved):
|
|
@@ -63,4 +65,4 @@ class AgentNodeHandler(NodeHandler):
|
|
|
63
65
|
tool_calls = context.pop_execution_records()
|
|
64
66
|
context.set_variable("_last_node_tool_calls", tool_calls)
|
|
65
67
|
|
|
66
|
-
yield event.step_finished(step_name=step_name)
|
|
68
|
+
yield event.step_finished(step_name=step_name, step_id=sid)
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"""NodeHandler 基类 — 所有执行类节点的公共接口"""
|
|
4
4
|
|
|
5
5
|
from typing import TYPE_CHECKING, Any, AsyncIterator
|
|
6
|
+
from uuid import uuid4
|
|
6
7
|
|
|
7
8
|
from .. import event
|
|
8
9
|
|
|
@@ -45,7 +46,8 @@ class NodeHandler:
|
|
|
45
46
|
需要流式输出的节点(如 agent, llm_chat)应覆盖此方法。
|
|
46
47
|
"""
|
|
47
48
|
step_name = self.get_step_name(node, node_id)
|
|
48
|
-
|
|
49
|
+
sid = str(uuid4())
|
|
50
|
+
yield event.step_started(step_name=step_name, step_id=sid)
|
|
49
51
|
result = await self.execute(node, context)
|
|
50
52
|
context.set_output(node_id, result)
|
|
51
|
-
yield event.step_finished(step_name=step_name)
|
|
53
|
+
yield event.step_finished(step_name=step_name, step_id=sid)
|
|
@@ -32,8 +32,9 @@ class EchoNodeHandler(NodeHandler):
|
|
|
32
32
|
async def stream(self, node: dict, context: "FlowContext", node_id: str) -> AsyncIterator[dict[str, Any]]:
|
|
33
33
|
config = node.get("config", {})
|
|
34
34
|
step_name = self.get_step_name(node, node_id)
|
|
35
|
+
sid = str(uuid4())
|
|
35
36
|
|
|
36
|
-
yield event.step_started(step_name=step_name)
|
|
37
|
+
yield event.step_started(step_name=step_name, step_id=sid)
|
|
37
38
|
|
|
38
39
|
resolved = self.resolve_inputs(config, context)
|
|
39
40
|
content = resolved.get("content", "")
|
|
@@ -51,4 +52,4 @@ class EchoNodeHandler(NodeHandler):
|
|
|
51
52
|
yield event.text_message_end(message_id=msg_id)
|
|
52
53
|
|
|
53
54
|
context.set_output(node_id, {"result": content})
|
|
54
|
-
yield event.step_finished(step_name=step_name)
|
|
55
|
+
yield event.step_finished(step_name=step_name, step_id=sid)
|
|
@@ -92,15 +92,17 @@ class LLMChatNodeHandler(NodeHandler):
|
|
|
92
92
|
if not use_stream:
|
|
93
93
|
# 非流式:走默认 execute 路径
|
|
94
94
|
step_name = self.get_step_name(node, node_id)
|
|
95
|
-
|
|
95
|
+
sid = str(uuid4())
|
|
96
|
+
yield event.step_started(step_name=step_name, step_id=sid)
|
|
96
97
|
result = await self.execute(node, context)
|
|
97
98
|
context.set_output(node_id, result)
|
|
98
|
-
yield event.step_finished(step_name=step_name)
|
|
99
|
+
yield event.step_finished(step_name=step_name, step_id=sid)
|
|
99
100
|
return
|
|
100
101
|
|
|
101
102
|
# 流式输出
|
|
102
103
|
step_name = self.get_step_name(node, node_id)
|
|
103
|
-
|
|
104
|
+
sid = str(uuid4())
|
|
105
|
+
yield event.step_started(step_name=step_name, step_id=sid)
|
|
104
106
|
|
|
105
107
|
resolved_inputs = self.resolve_inputs(config, context)
|
|
106
108
|
prompt_text = self._build_prompt(config.get("prompt", ""), resolved_inputs)
|
|
@@ -153,4 +155,4 @@ class LLMChatNodeHandler(NodeHandler):
|
|
|
153
155
|
result_text = "".join(content_parts)
|
|
154
156
|
context.set_output(node_id, {"result": result_text})
|
|
155
157
|
|
|
156
|
-
yield event.step_finished(step_name=step_name)
|
|
158
|
+
yield event.step_finished(step_name=step_name, step_id=sid)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agstack
|
|
3
|
-
Version: 1.22.
|
|
3
|
+
Version: 1.22.1
|
|
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>
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|