power-loop 6.3.0__tar.gz → 6.4.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.
- {power_loop-6.3.0 → power_loop-6.4.0}/PKG-INFO +1 -1
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/__init__.py +1 -1
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/image_recall.py +38 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop.egg-info/PKG-INFO +1 -1
- {power_loop-6.3.0 → power_loop-6.4.0}/LICENSE +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/README.md +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/_vendor/__init__.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/_vendor/llm_client/__init__.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/_vendor/llm_client/anthropic_factory.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/_vendor/llm_client/capabilities.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/_vendor/llm_client/interface.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/_vendor/llm_client/llm_factory.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/_vendor/llm_client/llm_tooling.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/_vendor/llm_client/llm_utils.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/_vendor/llm_client/multimodal.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/agent/__init__.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/agent/follow_up.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/agent/sink.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/agent/stateful_loop.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/agent/system_prompt.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/agent/types.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contracts/__init__.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contracts/errors.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contracts/event_payloads.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contracts/events.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contracts/handlers.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contracts/hook_contexts.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contracts/hooks.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contracts/messages.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contracts/protocols.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contracts/tools.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contrib/__init__.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contrib/_redact.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contrib/jsonl_sink.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contrib/logging_sink.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contrib/mcp.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contrib/metrics_sink.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/contrib/otel_sink.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/core/agent_context.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/core/events.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/core/hooks.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/core/phase.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/core/pipeline.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/core/runner.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/core/state.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/py.typed +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/blackboard.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/budget.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/cancellation.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/compact.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/env.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/exec_backend.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/fold.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/fold_adapter.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/history_projector.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/history_sanitize.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/human_input.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/memory.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/notes.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/provider.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/representation.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/retry.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/runtime_state.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/session_store.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/skills.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/spec.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/store/__init__.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/store/backends/__init__.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/store/backends/mysql.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/store/backends/postgres.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/store/backends/sqlite.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/store/capabilities.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/store/db.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/store/dialect.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/store/factory.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/store/schema.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/store/store.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/store/types.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/structured.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/stub_provider.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/runtime/timers.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/tools/__init__.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/tools/blackboard.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/tools/command_policy.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/tools/default_manifest.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/tools/default_tools.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/tools/registry.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/tools/spawn_agent.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/workflow/__init__.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/workflow/api.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/workflow/engine.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/workflow/introspect.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/workflow/journal.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/workflow/result.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/workflow/resume.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/workflow/runner.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/workflow/spec.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/workflow/subprocess_executor.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/workflow/tool.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop/workflow/worker.py +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop.egg-info/SOURCES.txt +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop.egg-info/dependency_links.txt +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop.egg-info/requires.txt +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/power_loop.egg-info/top_level.txt +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/pyproject.toml +0 -0
- {power_loop-6.3.0 → power_loop-6.4.0}/setup.cfg +0 -0
|
@@ -15,7 +15,7 @@ Stability tiers
|
|
|
15
15
|
无版本承诺,可随时变更或删除。
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
__version__ = "6.
|
|
18
|
+
__version__ = "6.4.0"
|
|
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).
|
|
@@ -28,6 +28,7 @@ Pass ``durable=False`` for the look-once case (request-only, never stored).
|
|
|
28
28
|
from __future__ import annotations
|
|
29
29
|
|
|
30
30
|
import threading
|
|
31
|
+
from collections.abc import Sequence
|
|
31
32
|
from typing import Any
|
|
32
33
|
|
|
33
34
|
LoopMessage = dict[str, Any]
|
|
@@ -77,6 +78,43 @@ def queue_image_for_next_round(
|
|
|
77
78
|
return True
|
|
78
79
|
|
|
79
80
|
|
|
81
|
+
def queue_images_for_next_round(
|
|
82
|
+
session_id: str | None,
|
|
83
|
+
images: Sequence[tuple[str, str]],
|
|
84
|
+
*,
|
|
85
|
+
note: str = "",
|
|
86
|
+
durable: bool = True,
|
|
87
|
+
) -> int:
|
|
88
|
+
"""Queue a BATCH as ONE user message: a single note + one attachment block per image.
|
|
89
|
+
|
|
90
|
+
Queuing them one by one produces N separate user turns, each repeating the note — three
|
|
91
|
+
screenshots asked about with one question became three copies of that question in the
|
|
92
|
+
transcript. A batch is one turn, which is also what the provider APIs expect.
|
|
93
|
+
|
|
94
|
+
``images`` is ``[(path, ref)]``. Returns how many were accepted (0 = nothing queued, so the
|
|
95
|
+
caller must say so rather than claim the pictures were delivered).
|
|
96
|
+
"""
|
|
97
|
+
if not session_id:
|
|
98
|
+
return 0
|
|
99
|
+
blocks: list[dict[str, Any]] = []
|
|
100
|
+
if note:
|
|
101
|
+
blocks.append({"type": "text", "text": note})
|
|
102
|
+
accepted = 0
|
|
103
|
+
for path, ref in images:
|
|
104
|
+
if not path:
|
|
105
|
+
continue
|
|
106
|
+
blocks.append({"type": "attachment", "attachment": _attachment_ref(path, ref=ref)})
|
|
107
|
+
accepted += 1
|
|
108
|
+
if not accepted:
|
|
109
|
+
return 0
|
|
110
|
+
with _lock:
|
|
111
|
+
queue = _pending.setdefault(session_id, [])
|
|
112
|
+
if len(queue) >= MAX_PENDING_PER_SESSION:
|
|
113
|
+
return 0
|
|
114
|
+
queue.append({"role": "user", "content": blocks, "__durable__": durable})
|
|
115
|
+
return accepted
|
|
116
|
+
|
|
117
|
+
|
|
80
118
|
def drain_queued_images(session_id: str | None) -> tuple[list[LoopMessage], list[LoopMessage]]:
|
|
81
119
|
"""Take everything queued for this session (and clear it).
|
|
82
120
|
|
|
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
|