power-loop 2.0.0__tar.gz → 2.2.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.
Files changed (104) hide show
  1. {power_loop-2.0.0 → power_loop-2.2.0}/PKG-INFO +2 -1
  2. {power_loop-2.0.0 → power_loop-2.2.0}/README.md +1 -0
  3. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/__init__.py +17 -1
  4. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/agent/sink.py +6 -0
  5. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/agent/stateful_loop.py +648 -81
  6. power_loop-2.2.0/power_loop/agent/types.py +159 -0
  7. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contracts/errors.py +8 -4
  8. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contracts/tools.py +11 -1
  9. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/core/pipeline.py +13 -1
  10. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/compact.py +156 -7
  11. power_loop-2.2.0/power_loop/runtime/history_projector.py +385 -0
  12. power_loop-2.2.0/power_loop/runtime/history_sanitize.py +104 -0
  13. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/store/backends/mysql.py +8 -5
  14. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/store/backends/sqlite.py +54 -8
  15. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/store/dialect.py +58 -5
  16. power_loop-2.2.0/power_loop/runtime/store/factory.py +103 -0
  17. power_loop-2.2.0/power_loop/runtime/store/schema.py +428 -0
  18. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/store/store.py +397 -30
  19. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/store/types.py +33 -0
  20. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/tools/default_manifest.py +17 -0
  21. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/tools/default_tools.py +166 -18
  22. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/workflow/journal.py +46 -33
  23. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/workflow/resume.py +1 -1
  24. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/workflow/runner.py +6 -2
  25. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop.egg-info/PKG-INFO +2 -1
  26. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop.egg-info/SOURCES.txt +2 -0
  27. power_loop-2.0.0/power_loop/agent/types.py +0 -90
  28. power_loop-2.0.0/power_loop/runtime/store/factory.py +0 -59
  29. power_loop-2.0.0/power_loop/runtime/store/schema.py +0 -169
  30. {power_loop-2.0.0 → power_loop-2.2.0}/LICENSE +0 -0
  31. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/_vendor/__init__.py +0 -0
  32. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/_vendor/llm_client/__init__.py +0 -0
  33. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/_vendor/llm_client/anthropic_factory.py +0 -0
  34. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/_vendor/llm_client/capabilities.py +0 -0
  35. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/_vendor/llm_client/interface.py +0 -0
  36. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/_vendor/llm_client/llm_factory.py +0 -0
  37. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/_vendor/llm_client/llm_tooling.py +0 -0
  38. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/_vendor/llm_client/llm_utils.py +0 -0
  39. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/_vendor/llm_client/multimodal.py +0 -0
  40. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/agent/__init__.py +0 -0
  41. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/agent/follow_up.py +0 -0
  42. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/agent/system_prompt.py +0 -0
  43. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contracts/__init__.py +0 -0
  44. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contracts/event_payloads.py +0 -0
  45. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contracts/events.py +0 -0
  46. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contracts/handlers.py +0 -0
  47. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contracts/hook_contexts.py +0 -0
  48. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contracts/hooks.py +0 -0
  49. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contracts/messages.py +0 -0
  50. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contracts/protocols.py +0 -0
  51. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contrib/__init__.py +0 -0
  52. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contrib/_redact.py +0 -0
  53. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contrib/jsonl_sink.py +0 -0
  54. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contrib/logging_sink.py +0 -0
  55. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contrib/mcp.py +0 -0
  56. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contrib/metrics_sink.py +0 -0
  57. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/contrib/otel_sink.py +0 -0
  58. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/core/agent_context.py +0 -0
  59. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/core/events.py +0 -0
  60. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/core/hooks.py +0 -0
  61. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/core/phase.py +0 -0
  62. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/core/runner.py +0 -0
  63. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/core/state.py +0 -0
  64. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/py.typed +0 -0
  65. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/blackboard.py +0 -0
  66. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/budget.py +0 -0
  67. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/cancellation.py +0 -0
  68. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/env.py +0 -0
  69. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/exec_backend.py +0 -0
  70. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/human_input.py +0 -0
  71. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/memory.py +0 -0
  72. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/notes.py +0 -0
  73. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/provider.py +0 -0
  74. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/retry.py +0 -0
  75. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/runtime_state.py +0 -0
  76. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/session_store.py +0 -0
  77. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/skills.py +0 -0
  78. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/spec.py +0 -0
  79. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/store/__init__.py +0 -0
  80. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/store/backends/__init__.py +0 -0
  81. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/store/backends/postgres.py +0 -0
  82. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/store/capabilities.py +0 -0
  83. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/store/db.py +0 -0
  84. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/structured.py +0 -0
  85. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/stub_provider.py +0 -0
  86. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/runtime/timers.py +0 -0
  87. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/tools/__init__.py +0 -0
  88. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/tools/blackboard.py +0 -0
  89. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/tools/registry.py +0 -0
  90. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/tools/spawn_agent.py +0 -0
  91. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/workflow/__init__.py +0 -0
  92. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/workflow/api.py +0 -0
  93. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/workflow/engine.py +0 -0
  94. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/workflow/introspect.py +0 -0
  95. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/workflow/result.py +0 -0
  96. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/workflow/spec.py +0 -0
  97. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/workflow/subprocess_executor.py +0 -0
  98. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/workflow/tool.py +0 -0
  99. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop/workflow/worker.py +0 -0
  100. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop.egg-info/dependency_links.txt +0 -0
  101. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop.egg-info/requires.txt +0 -0
  102. {power_loop-2.0.0 → power_loop-2.2.0}/power_loop.egg-info/top_level.txt +0 -0
  103. {power_loop-2.0.0 → power_loop-2.2.0}/pyproject.toml +0 -0
  104. {power_loop-2.0.0 → power_loop-2.2.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: power-loop
3
- Version: 2.0.0
3
+ Version: 2.2.0
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
@@ -154,6 +154,7 @@ Most "agent frameworks" ask you to build your app *inside* them. power-loop is t
154
154
  | **Process sandboxing** | Each workflow leaf in its own OS process + own DB; wrap each in gVisor/Docker per leaf | [Sandboxing](docs/en/user-guide/sandboxing.md) |
155
155
  | **Durable timers** | Agents schedule their own wake-ups; survive restarts; one-shot or recurring | [Timers](docs/en/user-guide/timers.md) |
156
156
  | **Context compaction** | Auto-summarize old turns (never splits a tool-call pair); `recall_compacted` to pull originals back | [Compaction](docs/en/user-guide/compaction.md) |
157
+ | **Send-context projection** | Opt-in: feed a per-send plain-text projection of finished sends (derived `pl_project_messages`) instead of verbatim history; `pl_messages` stays immutable; `recall_send` to re-expand | [Projection](docs/en/user-guide/send-context-projection.md) |
157
158
  | **Durability ops** | Portable migration-version table, retention/prune, VACUUM, `export_session`/`import_session`, graceful `aclose()` | [Sessions](docs/en/user-guide/sessions.md) |
158
159
  | **Observability** | Typed `seq`-ordered events → durable JSONL + `replay`, Prometheus/StatsD metrics, OpenTelemetry spans | [Observability](docs/en/user-guide/observability.md) |
159
160
  | **MCP tools** | Surface a Model Context Protocol server's tools as power-loop tools | [Extending](docs/en/user-guide/extending-tools.md) |
@@ -81,6 +81,7 @@ Most "agent frameworks" ask you to build your app *inside* them. power-loop is t
81
81
  | **Process sandboxing** | Each workflow leaf in its own OS process + own DB; wrap each in gVisor/Docker per leaf | [Sandboxing](docs/en/user-guide/sandboxing.md) |
82
82
  | **Durable timers** | Agents schedule their own wake-ups; survive restarts; one-shot or recurring | [Timers](docs/en/user-guide/timers.md) |
83
83
  | **Context compaction** | Auto-summarize old turns (never splits a tool-call pair); `recall_compacted` to pull originals back | [Compaction](docs/en/user-guide/compaction.md) |
84
+ | **Send-context projection** | Opt-in: feed a per-send plain-text projection of finished sends (derived `pl_project_messages`) instead of verbatim history; `pl_messages` stays immutable; `recall_send` to re-expand | [Projection](docs/en/user-guide/send-context-projection.md) |
84
85
  | **Durability ops** | Portable migration-version table, retention/prune, VACUUM, `export_session`/`import_session`, graceful `aclose()` | [Sessions](docs/en/user-guide/sessions.md) |
85
86
  | **Observability** | Typed `seq`-ordered events → durable JSONL + `replay`, Prometheus/StatsD metrics, OpenTelemetry spans | [Observability](docs/en/user-guide/observability.md) |
86
87
  | **MCP tools** | Surface a Model Context Protocol server's tools as power-loop tools | [Extending](docs/en/user-guide/extending-tools.md) |
@@ -15,7 +15,7 @@ Stability tiers
15
15
  无版本承诺,可随时变更或删除。
16
16
  """
17
17
 
18
- __version__ = "2.0.0"
18
+ __version__ = "2.2.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).
@@ -145,6 +145,14 @@ from power_loop.runtime.exec_backend import (
145
145
  LocalShellBackend,
146
146
  ShellBackend,
147
147
  )
148
+ from power_loop.runtime.history_projector import (
149
+ DefaultDeterministicProjector,
150
+ HistoryProjector,
151
+ IdentityProjector,
152
+ ProjectedCompact,
153
+ ProjectedRow,
154
+ ProjectedSend,
155
+ )
148
156
  from power_loop.runtime.human_input import HumanInputRequired, request_user_input
149
157
  from power_loop.runtime.memory import MemoryProvider, MemorySnapshot, tag_as_memory
150
158
  from power_loop.runtime.notes import (
@@ -186,6 +194,7 @@ from power_loop.runtime.store.store import (
186
194
  from power_loop.runtime.store.types import (
187
195
  MessageRow,
188
196
  MessageState,
197
+ ProjectMessageRow,
189
198
  SessionKind,
190
199
  SessionRow,
191
200
  SessionStatsRow,
@@ -311,6 +320,13 @@ __all__ = [
311
320
  "BackgroundRuntimeProjector",
312
321
  "default_runtime_projectors",
313
322
  "get_tool_runtime_context",
323
+ "HistoryProjector",
324
+ "IdentityProjector",
325
+ "DefaultDeterministicProjector",
326
+ "ProjectedSend",
327
+ "ProjectedRow",
328
+ "ProjectedCompact",
329
+ "ProjectMessageRow",
314
330
  "CancellationToken",
315
331
  "CancellationLike",
316
332
  "RuntimeEnv",
@@ -158,6 +158,8 @@ class SQLiteSink:
158
158
  tool_call_id=tool_call_id,
159
159
  name=message.get("name"),
160
160
  round_index=round_index,
161
+ meta=message.get("meta"),
162
+ send_index=message.get("send_index"),
161
163
  )
162
164
  self._history_seqs.append(seq)
163
165
  self._history_ord.append(seq)
@@ -199,6 +201,8 @@ class SQLiteSink:
199
201
  content=_as_text(message.get("content")),
200
202
  tool_calls=list(tool_calls) if tool_calls else None,
201
203
  round_index=round_index,
204
+ meta=message.get("meta"),
205
+ send_index=message.get("send_index"),
202
206
  )
203
207
  self._history_seqs.append(seq)
204
208
  self._history_ord.append(seq)
@@ -212,6 +216,8 @@ class SQLiteSink:
212
216
  content=_as_text(message.get("content")),
213
217
  name=message.get("name"),
214
218
  round_index=round_index,
219
+ meta=message.get("meta"),
220
+ send_index=message.get("send_index"),
215
221
  )
216
222
  self._history_seqs.append(seq)
217
223
  self._history_ord.append(seq)