power-loop 9.0.0__tar.gz → 9.1.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 (225) hide show
  1. {power_loop-9.0.0 → power_loop-9.1.0}/PKG-INFO +17 -1
  2. {power_loop-9.0.0 → power_loop-9.1.0}/README.md +16 -0
  3. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/__init__.py +1 -1
  4. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/agent/stateful_loop.py +1 -1
  5. power_loop-9.1.0/power_loop/core/control.py +14 -0
  6. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/core/pipeline.py +10 -3
  7. power_loop-9.1.0/power_loop/runtime/invocation.py +58 -0
  8. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/jobs.py +4 -0
  9. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop.egg-info/PKG-INFO +17 -1
  10. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop.egg-info/SOURCES.txt +1 -0
  11. power_loop-9.0.0/power_loop/runtime/invocation.py +0 -24
  12. {power_loop-9.0.0 → power_loop-9.1.0}/LICENSE +0 -0
  13. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/_vendor/__init__.py +0 -0
  14. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/_vendor/llm_client/__init__.py +0 -0
  15. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/_vendor/llm_client/anthropic_factory.py +0 -0
  16. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/_vendor/llm_client/attempt_scope.py +0 -0
  17. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/_vendor/llm_client/capabilities.py +0 -0
  18. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/_vendor/llm_client/interface.py +0 -0
  19. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/_vendor/llm_client/llm_factory.py +0 -0
  20. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/_vendor/llm_client/llm_tooling.py +0 -0
  21. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/_vendor/llm_client/llm_utils.py +0 -0
  22. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/_vendor/llm_client/multimodal.py +0 -0
  23. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/_vendor/llm_client/proxy_fallback.py +0 -0
  24. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/agent/__init__.py +0 -0
  25. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/agent/follow_up.py +0 -0
  26. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/agent/sink.py +0 -0
  27. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/agent/system_prompt.py +0 -0
  28. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/agent/types.py +0 -0
  29. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contracts/__init__.py +0 -0
  30. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contracts/context_policy.py +0 -0
  31. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contracts/errors.py +0 -0
  32. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contracts/event_payloads.py +0 -0
  33. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contracts/events.py +0 -0
  34. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contracts/handlers.py +0 -0
  35. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contracts/hook_contexts.py +0 -0
  36. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contracts/hooks.py +0 -0
  37. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contracts/messages.py +0 -0
  38. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contracts/protocols.py +0 -0
  39. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contracts/tools.py +0 -0
  40. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contrib/__init__.py +0 -0
  41. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contrib/_redact.py +0 -0
  42. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contrib/jsonl_sink.py +0 -0
  43. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contrib/logging_sink.py +0 -0
  44. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contrib/mcp.py +0 -0
  45. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contrib/metrics_sink.py +0 -0
  46. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/contrib/otel_sink.py +0 -0
  47. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/core/agent_context.py +0 -0
  48. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/core/events.py +0 -0
  49. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/core/hooks.py +0 -0
  50. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/core/pass_turn.py +0 -0
  51. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/core/phase.py +0 -0
  52. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/core/runner.py +0 -0
  53. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/core/state.py +0 -0
  54. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/py.typed +0 -0
  55. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/_tagged_processes.py +0 -0
  56. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/abort_outcomes.py +0 -0
  57. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/background.py +0 -0
  58. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/bash_capture.py +0 -0
  59. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/blackboard.py +0 -0
  60. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/budget.py +0 -0
  61. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/budget_contracts.py +0 -0
  62. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/budget_revisions.py +0 -0
  63. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/budget_scopes.py +0 -0
  64. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/cancellation.py +0 -0
  65. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/capability_probe.py +0 -0
  66. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/compact.py +0 -0
  67. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/completion.py +0 -0
  68. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/completion_windows.py +0 -0
  69. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/context_window_probe.py +0 -0
  70. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/controller_handoff.py +0 -0
  71. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/controller_recovery.py +0 -0
  72. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/controller_retirement.py +0 -0
  73. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/controller_task_exit.py +0 -0
  74. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/delegation.py +0 -0
  75. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/env.py +0 -0
  76. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/exec_backend.py +0 -0
  77. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/execution_membership.py +0 -0
  78. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/execution_roles.py +0 -0
  79. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/executor_lifecycle.py +0 -0
  80. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/executor_registry.py +0 -0
  81. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/finalization.py +0 -0
  82. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/fold.py +0 -0
  83. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/fold_adapter.py +0 -0
  84. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/fold_calls.py +0 -0
  85. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/history_projector.py +0 -0
  86. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/history_sanitize.py +0 -0
  87. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/host_send_steps.py +0 -0
  88. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/human_input.py +0 -0
  89. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/image_recall.py +0 -0
  90. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/input_dispositions.py +0 -0
  91. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/lineage.py +0 -0
  92. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/managed_claim.py +0 -0
  93. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/managed_completion.py +0 -0
  94. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/managed_delivery.py +0 -0
  95. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/managed_effects.py +0 -0
  96. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/memory.py +0 -0
  97. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/message_ref.py +0 -0
  98. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/model_attempt_query.py +0 -0
  99. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/model_attempts.py +0 -0
  100. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/model_budgets.py +0 -0
  101. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/model_calls.py +0 -0
  102. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/model_exit.py +0 -0
  103. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/native_returns.py +0 -0
  104. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/nested_tools.py +0 -0
  105. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/node_inputs.py +0 -0
  106. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/node_resume.py +0 -0
  107. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/notes.py +0 -0
  108. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/nudges.py +0 -0
  109. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/original_owner_review.py +0 -0
  110. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/owner_waits.py +0 -0
  111. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/pending_calls.py +0 -0
  112. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/pending_native.py +0 -0
  113. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/pending_owner.py +0 -0
  114. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/pricing.py +0 -0
  115. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/process_control.py +0 -0
  116. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/processing.py +0 -0
  117. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/provider.py +0 -0
  118. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/recall.py +0 -0
  119. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/representation.py +0 -0
  120. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/response_capture.py +0 -0
  121. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/result_payloads.py +0 -0
  122. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/result_proof.py +0 -0
  123. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/result_revisions.py +0 -0
  124. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/retry.py +0 -0
  125. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/review_tools.py +0 -0
  126. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/root_context.py +0 -0
  127. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/root_control.py +0 -0
  128. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/runtime_state.py +0 -0
  129. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/send_receipt.py +0 -0
  130. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/session_store.py +0 -0
  131. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/skills.py +0 -0
  132. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/spec.py +0 -0
  133. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/steer.py +0 -0
  134. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/stop_policy.py +0 -0
  135. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/__init__.py +0 -0
  136. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/backends/__init__.py +0 -0
  137. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/backends/mysql.py +0 -0
  138. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/backends/postgres.py +0 -0
  139. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/backends/sqlite.py +0 -0
  140. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/capabilities.py +0 -0
  141. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/context_cache.py +0 -0
  142. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/db.py +0 -0
  143. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/dialect.py +0 -0
  144. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/factory.py +0 -0
  145. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/schema.py +0 -0
  146. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/store.py +0 -0
  147. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/task_schema.py +0 -0
  148. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/store/types.py +0 -0
  149. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/structured.py +0 -0
  150. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/stub_provider.py +0 -0
  151. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/subagent_output.py +0 -0
  152. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/subagent_resume.py +0 -0
  153. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/task_control.py +0 -0
  154. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/task_events.py +0 -0
  155. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/task_history.py +0 -0
  156. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/task_inspection.py +0 -0
  157. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/task_query.py +0 -0
  158. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/task_runtime.py +0 -0
  159. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/task_sessions.py +0 -0
  160. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/timer_backend.py +0 -0
  161. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/timer_waits.py +0 -0
  162. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/timers.py +0 -0
  163. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/todos.py +0 -0
  164. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/tool_archive.py +0 -0
  165. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/tool_attempts.py +0 -0
  166. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/tool_billing.py +0 -0
  167. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/tool_call_abort.py +0 -0
  168. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/tool_call_plans.py +0 -0
  169. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/tool_context.py +0 -0
  170. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/tool_contracts.py +0 -0
  171. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/tool_truncation.py +0 -0
  172. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/usage_estimate.py +0 -0
  173. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/wait_decisions.py +0 -0
  174. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/wait_dispositions.py +0 -0
  175. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/wait_effects.py +0 -0
  176. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/wait_notifications.py +0 -0
  177. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/wait_reviews.py +0 -0
  178. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/wait_terminal.py +0 -0
  179. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/workflow_controller.py +0 -0
  180. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/workflow_profile.py +0 -0
  181. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/workflow_resources.py +0 -0
  182. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/workflow_restore.py +0 -0
  183. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/workflow_restore_execution.py +0 -0
  184. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/workflow_restore_resources.py +0 -0
  185. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/workflow_restore_runner.py +0 -0
  186. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/workflow_results.py +0 -0
  187. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/workflow_resume.py +0 -0
  188. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/runtime/workflow_tasks.py +0 -0
  189. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/tools/__init__.py +0 -0
  190. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/tools/background_contract.py +0 -0
  191. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/tools/blackboard.py +0 -0
  192. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/tools/command_policy.py +0 -0
  193. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/tools/command_rules.py +0 -0
  194. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/tools/default_manifest.py +0 -0
  195. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/tools/default_tools.py +0 -0
  196. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/tools/jobs.py +0 -0
  197. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/tools/registry.py +0 -0
  198. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/tools/shell_contract.py +0 -0
  199. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/tools/skill_contract.py +0 -0
  200. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/tools/spawn_agent.py +0 -0
  201. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/tools/wait_handoff.py +0 -0
  202. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/__init__.py +0 -0
  203. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/_process_guard.py +0 -0
  204. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/admission.py +0 -0
  205. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/api.py +0 -0
  206. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/continuation.py +0 -0
  207. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/control.py +0 -0
  208. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/engine.py +0 -0
  209. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/facade.py +0 -0
  210. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/introspect.py +0 -0
  211. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/journal.py +0 -0
  212. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/legacy_history.py +0 -0
  213. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/result.py +0 -0
  214. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/resume.py +0 -0
  215. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/runner.py +0 -0
  216. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/spec.py +0 -0
  217. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/subprocess_executor.py +0 -0
  218. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/tool.py +0 -0
  219. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/worker.py +0 -0
  220. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop/workflow/yaml.py +0 -0
  221. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop.egg-info/dependency_links.txt +0 -0
  222. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop.egg-info/requires.txt +0 -0
  223. {power_loop-9.0.0 → power_loop-9.1.0}/power_loop.egg-info/top_level.txt +0 -0
  224. {power_loop-9.0.0 → power_loop-9.1.0}/pyproject.toml +0 -0
  225. {power_loop-9.0.0 → power_loop-9.1.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: power-loop
3
- Version: 9.0.0
3
+ Version: 9.1.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
@@ -418,3 +418,19 @@ After the exact charge is locally durable, API delivery failure leaves a pending
418
418
  budget submission and preserves the real tool result. Reconciliation never calls
419
419
  the handler again or reads a replacement price. Managed recovery sources without
420
420
  an ordinary callback checkpoint still need a separate adapter.
421
+
422
+
423
+ ### Host lifecycle extensions
424
+
425
+ Hosts can raise `power_loop.core.control.ControlledLoopStop(reason, message=...)`
426
+ from session-entry or round-start hooks. The pipeline records a controlled stop,
427
+ keeps completed work, and skips memory summarization on that exit. Hosts own
428
+ quota policy and settlement; the SDK has no application currency or user model.
429
+
430
+ `power_loop.runtime.invocation.register_invocation_scope(name, factory, exporter=...)`
431
+ installs a synchronous context manager around each actual tool invocation. The
432
+ factory receives `session_id`, `assistant_seq`, `tool_call_id`, and `tool_name`.
433
+ An optional exporter returns a small JSON snapshot which is saved as
434
+ `host_contexts[name]` on original job creation. Replay retains the original saved
435
+ snapshot; hosts restore it when recovering a child job. Business snapshots do not
436
+ carry execution authority and do not replace the SDK's signed task request.
@@ -340,3 +340,19 @@ After the exact charge is locally durable, API delivery failure leaves a pending
340
340
  budget submission and preserves the real tool result. Reconciliation never calls
341
341
  the handler again or reads a replacement price. Managed recovery sources without
342
342
  an ordinary callback checkpoint still need a separate adapter.
343
+
344
+
345
+ ### Host lifecycle extensions
346
+
347
+ Hosts can raise `power_loop.core.control.ControlledLoopStop(reason, message=...)`
348
+ from session-entry or round-start hooks. The pipeline records a controlled stop,
349
+ keeps completed work, and skips memory summarization on that exit. Hosts own
350
+ quota policy and settlement; the SDK has no application currency or user model.
351
+
352
+ `power_loop.runtime.invocation.register_invocation_scope(name, factory, exporter=...)`
353
+ installs a synchronous context manager around each actual tool invocation. The
354
+ factory receives `session_id`, `assistant_seq`, `tool_call_id`, and `tool_name`.
355
+ An optional exporter returns a small JSON snapshot which is saved as
356
+ `host_contexts[name]` on original job creation. Replay retains the original saved
357
+ snapshot; hosts restore it when recovering a child job. Business snapshots do not
358
+ carry execution authority and do not replace the SDK's signed task request.
@@ -15,7 +15,7 @@ Stability tiers
15
15
  无版本承诺,可随时变更或删除。
16
16
  """
17
17
 
18
- __version__ = "9.0.0"
18
+ __version__ = "9.1.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).
@@ -1737,7 +1737,7 @@ class StatefulAgentLoop:
1737
1737
  else:
1738
1738
  try:
1739
1739
  from power_loop.runtime.invocation import invocation_context
1740
- with invocation_context(sid, pending.get("assistant_seq"), cid):
1740
+ with invocation_context(sid, pending.get("assistant_seq"), cid, name):
1741
1741
  raw = await self.tool_registry.invoke_async(name, args)
1742
1742
  if not isinstance(raw, str):
1743
1743
  raw = json.dumps(raw, ensure_ascii=False)
@@ -0,0 +1,14 @@
1
+ """Host-controlled stops at lifecycle boundaries, separate from business errors."""
2
+
3
+
4
+ class ControlledLoopStop(Exception):
5
+ """A host hook requests a terminal result without another model request."""
6
+
7
+ def __init__(self, reason: str, *, message: str = "", status: str = "budget_exceeded"):
8
+ if not reason or status not in ("budget_exceeded", "cancelled", "degraded"):
9
+ raise ValueError("invalid controlled loop stop")
10
+ self.reason = reason
11
+ self.message = message
12
+ self.status = status
13
+ super().__init__(reason)
14
+
@@ -768,7 +768,7 @@ class AgentPipeline:
768
768
  # ── Helper: finalize session ──
769
769
 
770
770
  async def _finalize(self, reason: str, *, final_text: str | None = None,
771
- rounds: int | None = None) -> None:
771
+ rounds: int | None = None, remember: bool = True) -> None:
772
772
  if self._finalized:
773
773
  return # idempotent: SESSION_ENDED fires exactly once per run
774
774
  self._finalized = True
@@ -780,7 +780,8 @@ class AgentPipeline:
780
780
  )
781
781
  await self.hooks.run_typed_async(HookPoint.SESSION_END, ctx)
782
782
  self._emit(AgentEventType.SESSION_ENDED, SessionEndedPayload(reason=reason))
783
- await self._maybe_remember(reason=reason, final_text=final_text or "")
783
+ if remember:
784
+ await self._maybe_remember(reason=reason, final_text=final_text or "")
784
785
 
785
786
  async def _emit_error_terminal(self, exc: BaseException) -> None:
786
787
  """Emit the ``AGENT_ERROR`` channel + a terminal ``SESSION_ENDED`` after an
@@ -1605,7 +1606,7 @@ class AgentPipeline:
1605
1606
  from power_loop.runtime.invocation import invocation_context
1606
1607
  with invocation_context(self.session_id,
1607
1608
  assistant_seq if assistant_seq is not None else getattr(self.sink, "persisted_assistant_seq", None),
1608
- tool_call_id):
1609
+ tool_call_id, tool_name):
1609
1610
  from power_loop.runtime.task_runtime import check_tool_dispatch
1610
1611
  registered = await check_tool_dispatch(self.session_id, tool_name, self.tool_registry, tool_args)
1611
1612
  from power_loop.runtime.tool_contracts import validate_registration
@@ -1668,12 +1669,18 @@ class AgentPipeline:
1668
1669
  async def run(self, messages: list[LoopMessage]) -> AgentLoopResult:
1669
1670
  """Run the full agent loop. Returns when done, cancelled, or hit round limit."""
1670
1671
  from power_loop.core import pass_turn as _pass
1672
+ from power_loop.core.control import ControlledLoopStop
1671
1673
 
1672
1674
  token = _pass.begin() # pass_turn 的状态按 send 隔离(子 agent 内联跑也不串)
1673
1675
  self._pass_state = _pass.current()
1674
1676
  self._step_texts: list[dict[str, Any]] = []
1675
1677
  try:
1676
1678
  return await self._run(messages)
1679
+ except ControlledLoopStop as stop:
1680
+ await self._finalize(stop.reason, final_text=stop.message,
1681
+ rounds=self._completed_rounds, remember=False)
1682
+ return self._make_result(stop.status, final_text=stop.message,
1683
+ rounds=self._completed_rounds)
1677
1684
  finally:
1678
1685
  try:
1679
1686
  from power_loop.runtime.task_runtime import preserve_model_usage
@@ -0,0 +1,58 @@
1
+ """Identity of the actual persisted assistant call currently invoking a tool."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from contextlib import ExitStack, contextmanager
6
+ from contextvars import ContextVar
7
+
8
+ _INVOCATION: ContextVar[tuple[str | None, int | None, str | None] | None] = ContextVar(
9
+ "power_loop_tool_invocation", default=None
10
+ )
11
+
12
+
13
+ _SCOPE_FACTORIES = {}
14
+
15
+
16
+ def register_invocation_scope(name, factory, *, exporter=None):
17
+ """Install a trusted host context manager around each actual invocation."""
18
+ if not isinstance(name, str) or not name or not callable(factory):
19
+ raise ValueError("invalid invocation scope provider")
20
+ _SCOPE_FACTORIES[name] = (factory, exporter)
21
+
22
+
23
+ @contextmanager
24
+ def invocation_context(session_id, assistant_seq, tool_call_id, tool_name=None):
25
+ token = _INVOCATION.set((session_id, assistant_seq, tool_call_id))
26
+ try:
27
+ with ExitStack() as scopes:
28
+ for factory, _exporter in tuple(_SCOPE_FACTORIES.values()):
29
+ scopes.enter_context(
30
+ factory(
31
+ session_id=session_id,
32
+ assistant_seq=assistant_seq,
33
+ tool_call_id=tool_call_id,
34
+ tool_name=tool_name,
35
+ )
36
+ )
37
+ yield
38
+ finally:
39
+ _INVOCATION.reset(token)
40
+
41
+
42
+ def current_invocation(session_id):
43
+ current = _INVOCATION.get()
44
+ # A child's model run inherits ContextVars but must not inherit its parent's
45
+ # tool identity. A real child tool invocation will install its own context.
46
+ return current[1:] if current and current[0] == session_id else (None, None)
47
+
48
+
49
+ def capture_host_contexts():
50
+ """Audit-only host snapshots; never part of task authority or request input."""
51
+ import json
52
+
53
+ values = {}
54
+ for name, (_factory, exporter) in tuple(_SCOPE_FACTORIES.items()):
55
+ value = exporter() if exporter is not None else None
56
+ if value is not None:
57
+ values[name] = json.loads(json.dumps(value, allow_nan=False))
58
+ return values
@@ -727,6 +727,10 @@ class JobManager:
727
727
  payload["request"] = request_data
728
728
  if wait_binding is not None:
729
729
  payload["wait_binding"] = wait_binding
730
+ from .invocation import capture_host_contexts
731
+ host_contexts = capture_host_contexts()
732
+ if host_contexts:
733
+ payload["host_contexts"] = host_contexts
730
734
  operation = await self._insert_operation(tx, job_id=job_id, version=1, actor=actor, action="create",
731
735
  key=key, fingerprint=fingerprint, call_ref=call_ref, tool_call_id=tool_call_id,
732
736
  payload=payload)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: power-loop
3
- Version: 9.0.0
3
+ Version: 9.1.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
@@ -418,3 +418,19 @@ After the exact charge is locally durable, API delivery failure leaves a pending
418
418
  budget submission and preserves the real tool result. Reconciliation never calls
419
419
  the handler again or reads a replacement price. Managed recovery sources without
420
420
  an ordinary callback checkpoint still need a separate adapter.
421
+
422
+
423
+ ### Host lifecycle extensions
424
+
425
+ Hosts can raise `power_loop.core.control.ControlledLoopStop(reason, message=...)`
426
+ from session-entry or round-start hooks. The pipeline records a controlled stop,
427
+ keeps completed work, and skips memory summarization on that exit. Hosts own
428
+ quota policy and settlement; the SDK has no application currency or user model.
429
+
430
+ `power_loop.runtime.invocation.register_invocation_scope(name, factory, exporter=...)`
431
+ installs a synchronous context manager around each actual tool invocation. The
432
+ factory receives `session_id`, `assistant_seq`, `tool_call_id`, and `tool_name`.
433
+ An optional exporter returns a small JSON snapshot which is saved as
434
+ `host_contexts[name]` on original job creation. Replay retains the original saved
435
+ snapshot; hosts restore it when recovering a child job. Business snapshots do not
436
+ carry execution authority and do not replace the SDK's signed task request.
@@ -44,6 +44,7 @@ power_loop/contrib/mcp.py
44
44
  power_loop/contrib/metrics_sink.py
45
45
  power_loop/contrib/otel_sink.py
46
46
  power_loop/core/agent_context.py
47
+ power_loop/core/control.py
47
48
  power_loop/core/events.py
48
49
  power_loop/core/hooks.py
49
50
  power_loop/core/pass_turn.py
@@ -1,24 +0,0 @@
1
- """Identity of the actual persisted assistant call currently invoking a tool."""
2
- from __future__ import annotations
3
-
4
- from contextlib import contextmanager
5
- from contextvars import ContextVar
6
-
7
- _INVOCATION: ContextVar[tuple[str | None, int | None, str | None] | None] = ContextVar(
8
- "power_loop_tool_invocation", default=None)
9
-
10
-
11
- @contextmanager
12
- def invocation_context(session_id, assistant_seq, tool_call_id):
13
- token = _INVOCATION.set((session_id, assistant_seq, tool_call_id))
14
- try:
15
- yield
16
- finally:
17
- _INVOCATION.reset(token)
18
-
19
-
20
- def current_invocation(session_id):
21
- current = _INVOCATION.get()
22
- # A child's model run inherits ContextVars but must not inherit its parent's
23
- # tool identity. A real child tool invocation will install its own context.
24
- return current[1:] if current and current[0] == session_id else (None, None)
File without changes
File without changes
File without changes