power-loop 0.7.0__tar.gz → 0.7.2__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-0.7.0 → power_loop-0.7.2}/PKG-INFO +32 -1
- {power_loop-0.7.0 → power_loop-0.7.2}/README.md +31 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/__init__.py +3 -2
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/agent/stateful_loop.py +18 -2
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/tools/__init__.py +3 -3
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop.egg-info/PKG-INFO +32 -1
- {power_loop-0.7.0 → power_loop-0.7.2}/LICENSE +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/llm_client/__init__.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/llm_client/anthropic_factory.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/llm_client/capabilities.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/llm_client/interface.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/llm_client/llm_factory.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/llm_client/llm_tooling.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/llm_client/llm_utils.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/llm_client/multimodal.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/llm_client/qwen_image.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/llm_client/web_search.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/agent/__init__.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/agent/follow_up.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/agent/sink.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/agent/system_prompt.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/agent/types.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/contracts/__init__.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/contracts/errors.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/contracts/event_payloads.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/contracts/events.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/contracts/handlers.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/contracts/hook_contexts.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/contracts/hooks.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/contracts/messages.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/contracts/protocols.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/contracts/tools.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/core/agent_context.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/core/events.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/core/hooks.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/core/phase.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/core/pipeline.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/core/runner.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/core/state.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/budget.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/cancellation.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/compact.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/env.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/exec_backend.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/human_input.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/memory.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/provider.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/retry.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/runtime_state.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/session_store.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/skills.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/spec.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/runtime/structured.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/tools/default_manifest.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/tools/default_tools.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/tools/registry.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop/tools/spawn_agent.py +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop.egg-info/SOURCES.txt +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop.egg-info/dependency_links.txt +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop.egg-info/requires.txt +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/power_loop.egg-info/top_level.txt +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/pyproject.toml +0 -0
- {power_loop-0.7.0 → power_loop-0.7.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: power-loop
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Summary: Embeddable agent execution kernel — LLM loop, hooks, events, tools, dynamic sub-agents.
|
|
5
5
|
Author-email: zhangran <zhangran24@126.com>
|
|
6
6
|
License: MIT
|
|
@@ -125,6 +125,37 @@ See [Getting Started](docs/en/getting-started.md) for the complete first run.
|
|
|
125
125
|
| Pluggable cross-session memory | [Memory](docs/en/user-guide/memory.md) |
|
|
126
126
|
| Provider configuration | [Providers](docs/en/user-guide/providers.md) |
|
|
127
127
|
|
|
128
|
+
### Per-call overrides
|
|
129
|
+
|
|
130
|
+
Build one loop and reuse it across callers; restrict tools or swap the system
|
|
131
|
+
prompt **per `send`** without rebuilding (the model only *sees* the allowed
|
|
132
|
+
tools). Ideal for multi-tenant hosts.
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
# loop registered with all tools; this run exposes only "get_weather"
|
|
136
|
+
await loop.send("…", session_id=sid, tools=["get_weather"])
|
|
137
|
+
|
|
138
|
+
# per-run system prompt override (precedence: per-call > session > config)
|
|
139
|
+
await loop.send("…", session_id=sid, system_prompt="You are a terse bot.")
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The same overrides are available on `send_sync()`. When `follow_up()` is idle
|
|
143
|
+
and falls back to a new send, it accepts them too. A follow-up queued into an
|
|
144
|
+
already running call keeps that call's active tool and prompt policy.
|
|
145
|
+
|
|
146
|
+
For a multi-tenant host that reuses one registry across workspaces, build an
|
|
147
|
+
**unbound** registry and supply the workspace at invocation time:
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from power_loop import RuntimeEnv, create_default_tool_registry, runtime_env_context
|
|
151
|
+
|
|
152
|
+
registry = create_default_tool_registry(preset="core", bind=False)
|
|
153
|
+
with runtime_env_context(RuntimeEnv(workspace_dir=tenant_workspace)):
|
|
154
|
+
result = await registry.invoke_async("read_file", {"path": "README.md"})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
See [`examples/23_per_send_overrides.py`](examples/23_per_send_overrides.py).
|
|
158
|
+
|
|
128
159
|
## Public API
|
|
129
160
|
|
|
130
161
|
Stable imports are re-exported from `power_loop`:
|
|
@@ -88,6 +88,37 @@ See [Getting Started](docs/en/getting-started.md) for the complete first run.
|
|
|
88
88
|
| Pluggable cross-session memory | [Memory](docs/en/user-guide/memory.md) |
|
|
89
89
|
| Provider configuration | [Providers](docs/en/user-guide/providers.md) |
|
|
90
90
|
|
|
91
|
+
### Per-call overrides
|
|
92
|
+
|
|
93
|
+
Build one loop and reuse it across callers; restrict tools or swap the system
|
|
94
|
+
prompt **per `send`** without rebuilding (the model only *sees* the allowed
|
|
95
|
+
tools). Ideal for multi-tenant hosts.
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
# loop registered with all tools; this run exposes only "get_weather"
|
|
99
|
+
await loop.send("…", session_id=sid, tools=["get_weather"])
|
|
100
|
+
|
|
101
|
+
# per-run system prompt override (precedence: per-call > session > config)
|
|
102
|
+
await loop.send("…", session_id=sid, system_prompt="You are a terse bot.")
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The same overrides are available on `send_sync()`. When `follow_up()` is idle
|
|
106
|
+
and falls back to a new send, it accepts them too. A follow-up queued into an
|
|
107
|
+
already running call keeps that call's active tool and prompt policy.
|
|
108
|
+
|
|
109
|
+
For a multi-tenant host that reuses one registry across workspaces, build an
|
|
110
|
+
**unbound** registry and supply the workspace at invocation time:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from power_loop import RuntimeEnv, create_default_tool_registry, runtime_env_context
|
|
114
|
+
|
|
115
|
+
registry = create_default_tool_registry(preset="core", bind=False)
|
|
116
|
+
with runtime_env_context(RuntimeEnv(workspace_dir=tenant_workspace)):
|
|
117
|
+
result = await registry.invoke_async("read_file", {"path": "README.md"})
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
See [`examples/23_per_send_overrides.py`](examples/23_per_send_overrides.py).
|
|
121
|
+
|
|
91
122
|
## Public API
|
|
92
123
|
|
|
93
124
|
Stable imports are re-exported from `power_loop`:
|
|
@@ -22,7 +22,7 @@ Stability tiers
|
|
|
22
22
|
无版本承诺,可随时变更或删除。
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
|
-
__version__ = "0.7.
|
|
25
|
+
__version__ = "0.7.2"
|
|
26
26
|
|
|
27
27
|
from power_loop.agent.follow_up import FollowUpQueued
|
|
28
28
|
from power_loop.agent.sink import MessageSink, NullSink, SQLiteSink
|
|
@@ -116,7 +116,7 @@ from power_loop.core.pipeline import AgentPipeline
|
|
|
116
116
|
from power_loop.core.runner import AgentRunner
|
|
117
117
|
from power_loop.runtime.budget import estimate_text_tokens, estimate_tokens, trim_history
|
|
118
118
|
from power_loop.runtime.cancellation import CancellationLike, CancellationToken
|
|
119
|
-
from power_loop.runtime.env import RuntimeEnv, RuntimeEnvError
|
|
119
|
+
from power_loop.runtime.env import RuntimeEnv, RuntimeEnvError, runtime_env_context
|
|
120
120
|
from power_loop.runtime.exec_backend import (
|
|
121
121
|
DEFAULT_SHELL_BACKEND,
|
|
122
122
|
LocalShellBackend,
|
|
@@ -244,6 +244,7 @@ __all__ = [
|
|
|
244
244
|
"CancellationLike",
|
|
245
245
|
"RuntimeEnv",
|
|
246
246
|
"RuntimeEnvError",
|
|
247
|
+
"runtime_env_context",
|
|
247
248
|
"ShellBackend",
|
|
248
249
|
"LocalShellBackend",
|
|
249
250
|
"DEFAULT_SHELL_BACKEND",
|
|
@@ -196,9 +196,17 @@ class StatefulAgentLoop:
|
|
|
196
196
|
session_id: str,
|
|
197
197
|
*,
|
|
198
198
|
stop_event: CancellationLike = None,
|
|
199
|
+
tools: Sequence[str] | ToolRegistry | None = None,
|
|
200
|
+
system_prompt: str | None = None,
|
|
199
201
|
) -> StatefulResult | FollowUpQueued:
|
|
200
202
|
return asyncio.run(
|
|
201
|
-
self.follow_up(
|
|
203
|
+
self.follow_up(
|
|
204
|
+
user_input,
|
|
205
|
+
session_id,
|
|
206
|
+
stop_event=stop_event,
|
|
207
|
+
tools=tools,
|
|
208
|
+
system_prompt=system_prompt,
|
|
209
|
+
)
|
|
202
210
|
)
|
|
203
211
|
|
|
204
212
|
def send_sync(
|
|
@@ -207,9 +215,17 @@ class StatefulAgentLoop:
|
|
|
207
215
|
session_id: str,
|
|
208
216
|
*,
|
|
209
217
|
stop_event: CancellationLike = None,
|
|
218
|
+
tools: Sequence[str] | ToolRegistry | None = None,
|
|
219
|
+
system_prompt: str | None = None,
|
|
210
220
|
) -> StatefulResult:
|
|
211
221
|
return asyncio.run(
|
|
212
|
-
self.send(
|
|
222
|
+
self.send(
|
|
223
|
+
user_input,
|
|
224
|
+
session_id,
|
|
225
|
+
stop_event=stop_event,
|
|
226
|
+
tools=tools,
|
|
227
|
+
system_prompt=system_prompt,
|
|
228
|
+
)
|
|
213
229
|
)
|
|
214
230
|
|
|
215
231
|
async def resume(
|
|
@@ -50,6 +50,9 @@ def create_default_tool_registry(
|
|
|
50
50
|
If omitted, ``POWER_LOOP_HOME`` is used when present.
|
|
51
51
|
skills_dir: Optional default skills directory for ``load_skill``.
|
|
52
52
|
If omitted, ``POWER_LOOP_SKILLS_DIR`` is used when present.
|
|
53
|
+
bind: When true (default), bind handlers to one ``RuntimeEnv`` now.
|
|
54
|
+
When false, return handlers that resolve the current
|
|
55
|
+
``runtime_env_context`` at invocation time.
|
|
53
56
|
|
|
54
57
|
Examples::
|
|
55
58
|
|
|
@@ -68,9 +71,6 @@ def create_default_tool_registry(
|
|
|
68
71
|
workspace_dir="/path/to/project",
|
|
69
72
|
)
|
|
70
73
|
"""
|
|
71
|
-
from power_loop.tools.default_manifest import get_tool_definitions
|
|
72
|
-
from power_loop.tools.default_tools import DEFAULT_TOOL_HANDLERS
|
|
73
|
-
|
|
74
74
|
definitions = get_tool_definitions(preset=preset, include=include, exclude=exclude)
|
|
75
75
|
if not bind:
|
|
76
76
|
# Unbound: handlers read the current RuntimeEnv at call time; the caller
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: power-loop
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Summary: Embeddable agent execution kernel — LLM loop, hooks, events, tools, dynamic sub-agents.
|
|
5
5
|
Author-email: zhangran <zhangran24@126.com>
|
|
6
6
|
License: MIT
|
|
@@ -125,6 +125,37 @@ See [Getting Started](docs/en/getting-started.md) for the complete first run.
|
|
|
125
125
|
| Pluggable cross-session memory | [Memory](docs/en/user-guide/memory.md) |
|
|
126
126
|
| Provider configuration | [Providers](docs/en/user-guide/providers.md) |
|
|
127
127
|
|
|
128
|
+
### Per-call overrides
|
|
129
|
+
|
|
130
|
+
Build one loop and reuse it across callers; restrict tools or swap the system
|
|
131
|
+
prompt **per `send`** without rebuilding (the model only *sees* the allowed
|
|
132
|
+
tools). Ideal for multi-tenant hosts.
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
# loop registered with all tools; this run exposes only "get_weather"
|
|
136
|
+
await loop.send("…", session_id=sid, tools=["get_weather"])
|
|
137
|
+
|
|
138
|
+
# per-run system prompt override (precedence: per-call > session > config)
|
|
139
|
+
await loop.send("…", session_id=sid, system_prompt="You are a terse bot.")
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The same overrides are available on `send_sync()`. When `follow_up()` is idle
|
|
143
|
+
and falls back to a new send, it accepts them too. A follow-up queued into an
|
|
144
|
+
already running call keeps that call's active tool and prompt policy.
|
|
145
|
+
|
|
146
|
+
For a multi-tenant host that reuses one registry across workspaces, build an
|
|
147
|
+
**unbound** registry and supply the workspace at invocation time:
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from power_loop import RuntimeEnv, create_default_tool_registry, runtime_env_context
|
|
151
|
+
|
|
152
|
+
registry = create_default_tool_registry(preset="core", bind=False)
|
|
153
|
+
with runtime_env_context(RuntimeEnv(workspace_dir=tenant_workspace)):
|
|
154
|
+
result = await registry.invoke_async("read_file", {"path": "README.md"})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
See [`examples/23_per_send_overrides.py`](examples/23_per_send_overrides.py).
|
|
158
|
+
|
|
128
159
|
## Public API
|
|
129
160
|
|
|
130
161
|
Stable imports are re-exported from `power_loop`:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|