power-loop 0.7.1__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.
Files changed (63) hide show
  1. {power_loop-0.7.1 → power_loop-0.7.2}/PKG-INFO +16 -4
  2. {power_loop-0.7.1 → power_loop-0.7.2}/README.md +15 -3
  3. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/__init__.py +3 -2
  4. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/agent/stateful_loop.py +18 -2
  5. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/tools/__init__.py +3 -3
  6. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop.egg-info/PKG-INFO +16 -4
  7. {power_loop-0.7.1 → power_loop-0.7.2}/LICENSE +0 -0
  8. {power_loop-0.7.1 → power_loop-0.7.2}/llm_client/__init__.py +0 -0
  9. {power_loop-0.7.1 → power_loop-0.7.2}/llm_client/anthropic_factory.py +0 -0
  10. {power_loop-0.7.1 → power_loop-0.7.2}/llm_client/capabilities.py +0 -0
  11. {power_loop-0.7.1 → power_loop-0.7.2}/llm_client/interface.py +0 -0
  12. {power_loop-0.7.1 → power_loop-0.7.2}/llm_client/llm_factory.py +0 -0
  13. {power_loop-0.7.1 → power_loop-0.7.2}/llm_client/llm_tooling.py +0 -0
  14. {power_loop-0.7.1 → power_loop-0.7.2}/llm_client/llm_utils.py +0 -0
  15. {power_loop-0.7.1 → power_loop-0.7.2}/llm_client/multimodal.py +0 -0
  16. {power_loop-0.7.1 → power_loop-0.7.2}/llm_client/qwen_image.py +0 -0
  17. {power_loop-0.7.1 → power_loop-0.7.2}/llm_client/web_search.py +0 -0
  18. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/agent/__init__.py +0 -0
  19. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/agent/follow_up.py +0 -0
  20. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/agent/sink.py +0 -0
  21. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/agent/system_prompt.py +0 -0
  22. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/agent/types.py +0 -0
  23. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/contracts/__init__.py +0 -0
  24. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/contracts/errors.py +0 -0
  25. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/contracts/event_payloads.py +0 -0
  26. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/contracts/events.py +0 -0
  27. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/contracts/handlers.py +0 -0
  28. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/contracts/hook_contexts.py +0 -0
  29. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/contracts/hooks.py +0 -0
  30. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/contracts/messages.py +0 -0
  31. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/contracts/protocols.py +0 -0
  32. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/contracts/tools.py +0 -0
  33. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/core/agent_context.py +0 -0
  34. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/core/events.py +0 -0
  35. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/core/hooks.py +0 -0
  36. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/core/phase.py +0 -0
  37. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/core/pipeline.py +0 -0
  38. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/core/runner.py +0 -0
  39. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/core/state.py +0 -0
  40. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/budget.py +0 -0
  41. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/cancellation.py +0 -0
  42. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/compact.py +0 -0
  43. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/env.py +0 -0
  44. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/exec_backend.py +0 -0
  45. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/human_input.py +0 -0
  46. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/memory.py +0 -0
  47. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/provider.py +0 -0
  48. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/retry.py +0 -0
  49. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/runtime_state.py +0 -0
  50. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/session_store.py +0 -0
  51. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/skills.py +0 -0
  52. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/spec.py +0 -0
  53. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/runtime/structured.py +0 -0
  54. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/tools/default_manifest.py +0 -0
  55. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/tools/default_tools.py +0 -0
  56. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/tools/registry.py +0 -0
  57. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop/tools/spawn_agent.py +0 -0
  58. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop.egg-info/SOURCES.txt +0 -0
  59. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop.egg-info/dependency_links.txt +0 -0
  60. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop.egg-info/requires.txt +0 -0
  61. {power_loop-0.7.1 → power_loop-0.7.2}/power_loop.egg-info/top_level.txt +0 -0
  62. {power_loop-0.7.1 → power_loop-0.7.2}/pyproject.toml +0 -0
  63. {power_loop-0.7.1 → 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.1
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
@@ -139,10 +139,22 @@ await loop.send("…", session_id=sid, tools=["get_weather"])
139
139
  await loop.send("…", session_id=sid, system_prompt="You are a terse bot.")
140
140
  ```
141
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
+
142
146
  For a multi-tenant host that reuses one registry across workspaces, build an
143
- **unbound** registry and supply the workspace per call:
144
- `create_default_tool_registry(preset="core", bind=False)` +
145
- `runtime_env_context(...)`. See [`examples/23_per_send_overrides.py`](examples/23_per_send_overrides.py).
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).
146
158
 
147
159
  ## Public API
148
160
 
@@ -102,10 +102,22 @@ await loop.send("…", session_id=sid, tools=["get_weather"])
102
102
  await loop.send("…", session_id=sid, system_prompt="You are a terse bot.")
103
103
  ```
104
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
+
105
109
  For a multi-tenant host that reuses one registry across workspaces, build an
106
- **unbound** registry and supply the workspace per call:
107
- `create_default_tool_registry(preset="core", bind=False)` +
108
- `runtime_env_context(...)`. See [`examples/23_per_send_overrides.py`](examples/23_per_send_overrides.py).
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).
109
121
 
110
122
  ## Public API
111
123
 
@@ -22,7 +22,7 @@ Stability tiers
22
22
  无版本承诺,可随时变更或删除。
23
23
  """
24
24
 
25
- __version__ = "0.7.1"
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(user_input, session_id, stop_event=stop_event)
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(user_input, session_id, stop_event=stop_event)
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.1
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
@@ -139,10 +139,22 @@ await loop.send("…", session_id=sid, tools=["get_weather"])
139
139
  await loop.send("…", session_id=sid, system_prompt="You are a terse bot.")
140
140
  ```
141
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
+
142
146
  For a multi-tenant host that reuses one registry across workspaces, build an
143
- **unbound** registry and supply the workspace per call:
144
- `create_default_tool_registry(preset="core", bind=False)` +
145
- `runtime_env_context(...)`. See [`examples/23_per_send_overrides.py`](examples/23_per_send_overrides.py).
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).
146
158
 
147
159
  ## Public API
148
160
 
File without changes
File without changes
File without changes