power-loop 6.46.3__tar.gz → 6.46.4__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.
- {power_loop-6.46.3 → power_loop-6.46.4}/PKG-INFO +1 -1
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/__init__.py +1 -1
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/workflow/engine.py +14 -5
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop.egg-info/PKG-INFO +1 -1
- {power_loop-6.46.3 → power_loop-6.46.4}/LICENSE +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/README.md +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/_vendor/__init__.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/_vendor/llm_client/__init__.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/_vendor/llm_client/anthropic_factory.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/_vendor/llm_client/capabilities.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/_vendor/llm_client/interface.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/_vendor/llm_client/llm_factory.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/_vendor/llm_client/llm_tooling.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/_vendor/llm_client/llm_utils.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/_vendor/llm_client/multimodal.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/_vendor/llm_client/proxy_fallback.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/agent/__init__.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/agent/follow_up.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/agent/sink.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/agent/stateful_loop.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/agent/system_prompt.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/agent/types.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contracts/__init__.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contracts/errors.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contracts/event_payloads.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contracts/events.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contracts/handlers.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contracts/hook_contexts.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contracts/hooks.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contracts/messages.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contracts/protocols.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contracts/tools.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contrib/__init__.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contrib/_redact.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contrib/jsonl_sink.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contrib/logging_sink.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contrib/mcp.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contrib/metrics_sink.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/contrib/otel_sink.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/core/agent_context.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/core/events.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/core/hooks.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/core/phase.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/core/pipeline.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/core/runner.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/core/state.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/py.typed +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/blackboard.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/budget.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/cancellation.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/capability_probe.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/compact.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/env.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/exec_backend.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/fold.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/fold_adapter.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/history_projector.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/history_sanitize.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/human_input.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/image_recall.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/memory.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/notes.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/provider.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/representation.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/retry.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/runtime_state.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/session_store.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/skills.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/spec.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/steer.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/stop_policy.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/store/__init__.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/store/backends/__init__.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/store/backends/mysql.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/store/backends/postgres.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/store/backends/sqlite.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/store/capabilities.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/store/db.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/store/dialect.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/store/factory.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/store/schema.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/store/store.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/store/types.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/structured.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/stub_provider.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/timers.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/todos.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/runtime/usage_estimate.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/tools/__init__.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/tools/blackboard.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/tools/command_policy.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/tools/command_rules.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/tools/default_manifest.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/tools/default_tools.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/tools/registry.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/tools/spawn_agent.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/workflow/__init__.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/workflow/api.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/workflow/introspect.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/workflow/journal.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/workflow/result.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/workflow/resume.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/workflow/runner.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/workflow/spec.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/workflow/subprocess_executor.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/workflow/tool.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop/workflow/worker.py +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop.egg-info/SOURCES.txt +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop.egg-info/dependency_links.txt +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop.egg-info/requires.txt +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/power_loop.egg-info/top_level.txt +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/pyproject.toml +0 -0
- {power_loop-6.46.3 → power_loop-6.46.4}/setup.cfg +0 -0
|
@@ -15,7 +15,7 @@ Stability tiers
|
|
|
15
15
|
无版本承诺,可随时变更或删除。
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
__version__ = "6.46.
|
|
18
|
+
__version__ = "6.46.4"
|
|
19
19
|
|
|
20
20
|
# Public LLM contract (SDK-free) re-exported so callers (e.g. writing llm.* hooks or
|
|
21
21
|
# a custom LLMService) don't reach into the internal vendored transport package (H3.4).
|
|
@@ -514,7 +514,10 @@ class WorkflowEngine:
|
|
|
514
514
|
lc = {"loop_id": node.id, "iteration": iteration, "max": node.max_iterations,
|
|
515
515
|
"continue": set(node.continue_nodes), "prev": dict(prev), "why": why,
|
|
516
516
|
"feedback": self._loop_feedback(feedback_node) if iteration > 1 else ""}
|
|
517
|
-
await self._exec(node.body, {**env, _LOOP_KEY: lc, "loop_iteration": iteration}, driver_sid)
|
|
517
|
+
body_result = await self._exec(node.body, {**env, _LOOP_KEY: lc, "loop_iteration": iteration}, driver_sid)
|
|
518
|
+
if body_result is not None and body_result.status not in ("completed", "skipped") and body_result.node_id not in self._tolerated:
|
|
519
|
+
why = f"上游 {body_result.node_id} 未完成:{body_result.status};审核与下一轮已阻断"
|
|
520
|
+
break
|
|
518
521
|
for nid in node.continue_nodes:
|
|
519
522
|
r = self._results.get(nid)
|
|
520
523
|
if r is not None and r.session_id:
|
|
@@ -526,7 +529,9 @@ class WorkflowEngine:
|
|
|
526
529
|
last = {nid: {"status": r.status, "text": (r.text or "")[:4000], "payload": r.payload, "session_id": r.session_id}
|
|
527
530
|
for nid in body_ids if (r := self._results.get(nid)) is not None}
|
|
528
531
|
payload = {"converged": converged, "iterations": iteration, "why": why, "last": last}
|
|
529
|
-
|
|
532
|
+
broken = any(r.status not in ("completed", "skipped") and nid not in self._tolerated
|
|
533
|
+
for nid in body_ids if (r := self._results.get(nid)) is not None)
|
|
534
|
+
ok = converged or (node.on_exhausted == "continue" and not broken and not self._cancel.is_cancelled())
|
|
530
535
|
err = None if converged else (f"跑了 {iteration} 轮仍不满足 until:{why}" if not self._cancel.is_cancelled()
|
|
531
536
|
else "循环被取消")
|
|
532
537
|
res = AgentResult(node_id=node.id, status="completed" if ok else ("cancelled" if self._cancel.is_cancelled() else "failed"),
|
|
@@ -789,7 +794,7 @@ class WorkflowEngine:
|
|
|
789
794
|
|
|
790
795
|
res = AgentResult(
|
|
791
796
|
node_id=node.id,
|
|
792
|
-
status=str(raw.get("status")),
|
|
797
|
+
status="failed" if err else str(raw.get("status")),
|
|
793
798
|
text=raw.get("final_text") or "",
|
|
794
799
|
payload=payload,
|
|
795
800
|
usage=dict(raw.get("usage") or {}),
|
|
@@ -804,7 +809,6 @@ class WorkflowEngine:
|
|
|
804
809
|
self._add_usage(res.usage)
|
|
805
810
|
if self._budget is not None:
|
|
806
811
|
self._budget.commit(res.usage)
|
|
807
|
-
await self._emit_step(res)
|
|
808
812
|
|
|
809
813
|
# ── 兜底节点:所有 attempt 用尽仍失败时跑,成功则**顶替**本节点的结果供下游引用 ──
|
|
810
814
|
if res.status != "completed" and node.fallback is not None and not self._cancelled:
|
|
@@ -825,6 +829,7 @@ class WorkflowEngine:
|
|
|
825
829
|
# continue_on_error:失败但明确放行——记下来,run 终态判定跳过它。被单独取消的节点同样放行。
|
|
826
830
|
if (res.status == "failed" and node.continue_on_error) or node.id in self._node_cancelled:
|
|
827
831
|
self._tolerated.add(node.id)
|
|
832
|
+
await self._emit_step(res)
|
|
828
833
|
return res
|
|
829
834
|
|
|
830
835
|
def _session_cb(self, node_id: str) -> Callable[[str], Awaitable[None]]:
|
|
@@ -952,6 +957,8 @@ class WorkflowEngine:
|
|
|
952
957
|
last = await self._exec(step, env, driver_sid)
|
|
953
958
|
if self._budget_hit or self._cancelled:
|
|
954
959
|
break
|
|
960
|
+
if last is not None and last.status not in ("completed", "skipped") and last.node_id not in self._tolerated:
|
|
961
|
+
break
|
|
955
962
|
return last
|
|
956
963
|
|
|
957
964
|
async def _gather_branches(
|
|
@@ -1014,7 +1021,9 @@ class WorkflowEngine:
|
|
|
1014
1021
|
for r in gathered:
|
|
1015
1022
|
if isinstance(r, BaseException):
|
|
1016
1023
|
self._errors.append(f"parallel branch error: {r}")
|
|
1017
|
-
|
|
1024
|
+
broken = next((r for r in gathered if isinstance(r, AgentResult)
|
|
1025
|
+
and r.status not in ("completed", "skipped") and r.node_id not in self._tolerated), None)
|
|
1026
|
+
return broken or next((r for r in reversed(gathered) if isinstance(r, AgentResult)), None)
|
|
1018
1027
|
|
|
1019
1028
|
async def _exec_foreach(self, node: ForeachNode, env: dict[str, Any], driver_sid: str) -> AgentResult | None:
|
|
1020
1029
|
# Resume: a foreach is replayed atomically via its journaled aggregate.
|
|
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
|
|
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
|